⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 vid_win.c

📁 quake1 dos源代码最新版本
💻 C
📖 第 1 页 / 共 5 页
字号:
/*
Copyright (C) 1996-1997 Id Software, Inc.

This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.

*/
// vid_win.c -- Win32 video driver

#include "quakedef.h"
#include "winquake.h"
#include "d_local.h"
#include "resource.h"

#define MAX_MODE_LIST	30
#define VID_ROW_SIZE	3

qboolean	dibonly;

//extern int		Minimized;	//wrong, and correct in winquake.h	// 2001-12-10 Compilable with LCC-Win32 by Jeff Ford

HWND		mainwindow;

HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow);

int			DIBWidth, DIBHeight;
qboolean	DDActive;
RECT		WindowRect;
DWORD		WindowStyle, ExWindowStyle;

int			window_center_x, window_center_y, window_x, window_y, window_width, window_height;
RECT		window_rect;

static DEVMODE	gdevmode;
static qboolean	startwindowed = 0, windowed_mode_set;
static int		firstupdate = 1;
static qboolean	vid_initialized = false, vid_palettized;
static int		lockcount;
static int		vid_fulldib_on_focus_mode;
static qboolean	force_minimized, in_mode_set, is_mode0x13, force_mode_set;
static int		vid_stretched, windowed_mouse;
static qboolean	palette_changed, syscolchg, vid_mode_set, hide_window, pal_is_nostatic;
static HICON	hIcon;

viddef_t	vid;				// global video state

#define MODE_WINDOWED			0
#define MODE_SETTABLE_WINDOW	2
#define NO_MODE					(MODE_WINDOWED - 1)
#define MODE_FULLSCREEN_DEFAULT	(MODE_WINDOWED + 3)

// Note that 0 is MODE_WINDOWED
cvar_t	*vid_mode;
// Note that 0 is MODE_WINDOWED
cvar_t	*_vid_default_mode;
// Note that 3 is MODE_FULLSCREEN_DEFAULT
cvar_t	*_vid_default_mode_win;
cvar_t	*vid_wait;
cvar_t	*vid_nopageflip;
cvar_t	*_vid_wait_override;
cvar_t	*vid_config_x;
cvar_t	*vid_config_y;
cvar_t	*vid_stretch_by_2;
cvar_t	*_windowed_mouse;
cvar_t	*vid_fullscreen_mode;
cvar_t	*vid_windowed_mode;
cvar_t	*block_switch;
cvar_t	*vid_window_x;
cvar_t	*vid_window_y;

typedef struct {
	int		width;
	int		height;
} lmode_t;

lmode_t	lowresmodes[] = {
	{320, 200},
	{320, 240},
	{400, 300},
	{512, 384},
};

int			vid_modenum = NO_MODE;
int			vid_testingmode, vid_realmode;
double		vid_testendtime;
int			vid_default = MODE_WINDOWED;
static int	windowed_default;

modestate_t	modestate = MS_UNINIT;

static byte		*vid_surfcache;
static int		vid_surfcachesize;
static int		VID_highhunkmark;

unsigned char	vid_curpal[256*3];

unsigned short	d_8to16table[256];
unsigned	d_8to24table[256];

int		driver = grDETECT,mode;
bool	useWinDirect = true, useDirectDraw = true;
MGLDC	*mgldc = NULL,*memdc = NULL,*dibdc = NULL,*windc = NULL;

typedef struct {
	modestate_t	type;
	int			width;
	int			height;
	int			modenum;
	int			mode13;
	int			stretched;
	int			dib;
	int			fullscreen;
	int			bpp;
	int			halfscreen;
	char		modedesc[13];
} vmode_t;

static vmode_t	modelist[MAX_MODE_LIST];
static int		nummodes;
static vmode_t	*pcurrentmode;

int		aPage;					// Current active display page
int		vPage;					// Current visible display page
int		waitVRT = true;			// True to wait for retrace on flip

static vmode_t	badmode;

static byte	backingbuf[48*24];

void VID_MenuDraw (void);
void VID_MenuKey (int key);

LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
void AppActivate(BOOL fActive, BOOL minimize);


/*
================
VID_RememberWindowPos
================
*/
void VID_RememberWindowPos (void)
{
	RECT	rect;

	if (GetWindowRect (mainwindow, &rect))
	{
		if ((rect.left < GetSystemMetrics (SM_CXSCREEN)) &&
			(rect.top < GetSystemMetrics (SM_CYSCREEN))  &&
			(rect.right > 0)                             &&
			(rect.bottom > 0))
		{
			Cvar_SetValue (vid_window_x, (float)rect.left);
			Cvar_SetValue (vid_window_y, (float)rect.top);
		}
	}
}


/*
================
VID_CheckWindowXY
================
*/
void VID_CheckWindowXY (void)
{

	if (((int)vid_window_x->value > (GetSystemMetrics (SM_CXSCREEN) - 160)) ||
		((int)vid_window_y->value > (GetSystemMetrics (SM_CYSCREEN) - 120)) ||
		((int)vid_window_x->value < 0)									   ||
		((int)vid_window_y->value < 0))
	{
		Cvar_Set (vid_window_x, "0");
		Cvar_Set (vid_window_y, "0" );
	}
}


/*
================
VID_UpdateWindowStatus
================
*/
void VID_UpdateWindowStatus (void)
{

	window_rect.left = window_x;
	window_rect.top = window_y;
	window_rect.right = window_x + window_width;
	window_rect.bottom = window_y + window_height;
	window_center_x = (window_rect.left + window_rect.right) / 2;
	window_center_y = (window_rect.top + window_rect.bottom) / 2;

	IN_UpdateClipCursor ();
}


/*
================
ClearAllStates
================
*/
void ClearAllStates (void)
{
	int		i;

// send an up event for each key, to make sure the server clears them all
	for (i=0 ; i<256 ; i++)
	{
		Key_Event (i, false);
	}

	Key_ClearStates ();
	IN_ClearStates ();
}


/*
================
VID_CheckAdequateMem
================
*/
qboolean VID_CheckAdequateMem (int width, int height)
{
	int		tbuffersize;

	tbuffersize = width * height * sizeof (*d_pzbuffer);

	tbuffersize += D_SurfaceCacheForRes (width, height);

// see if there's enough memory, allowing for the normal mode 0x13 pixel,
// z, and surface buffers
	if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
		 0x10000 * 3) < minimum_memory)
	{
		return false;		// not enough memory for mode
	}

	return true;
}


/*
================
VID_AllocBuffers
================
*/
qboolean VID_AllocBuffers (int width, int height)
{
	int		tsize, tbuffersize;

	tbuffersize = width * height * sizeof (*d_pzbuffer);

	tsize = D_SurfaceCacheForRes (width, height);

	tbuffersize += tsize;

// see if there's enough memory, allowing for the normal mode 0x13 pixel,
// z, and surface buffers
	if ((host_parms.memsize - tbuffersize + SURFCACHE_SIZE_AT_320X200 +
		 0x10000 * 3) < minimum_memory)
	{
		Con_SafePrintf ("Not enough memory for video mode\n");
		return false;		// not enough memory for mode
	}

	vid_surfcachesize = tsize;

	if (d_pzbuffer)
	{
		D_FlushCaches ();
		Hunk_FreeToHighMark (VID_highhunkmark);
		d_pzbuffer = NULL;
	}

	VID_highhunkmark = Hunk_HighMark ();

	d_pzbuffer = Hunk_HighAllocName (tbuffersize, "video");

	vid_surfcache = (byte *)d_pzbuffer +
			width * height * sizeof (*d_pzbuffer);

	return true;
}


void initFatalError(void)
{
	MGL_exit();
	MGL_fatalError(MGL_errorMsg(MGL_result()));
	exit(EXIT_FAILURE);
}


int VID_Suspend (MGLDC *dc,m_int flags)
{

	if (flags & MGL_DEACTIVATE)
	{
	// FIXME: this doesn't currently work on NT
		if (block_switch->value && !WinNT)
		{
			return MGL_NO_DEACTIVATE;
		}

		S_BlockSound ();
		S_ClearBuffer ();

		IN_RestoreOriginalMouseState ();
		CDAudio_Pause ();

	// keep WM_PAINT from trying to redraw
		in_mode_set = true;

		block_drawing = true;	// so we don't try to draw while switched away

//		return MGL_NO_SUSPEND_APP;	// 2000-01-31 Valid result correction by Maddes
	}
	else if (flags & MGL_REACTIVATE)
	{
		IN_SetQuakeMouseState ();
	// fix the leftover Alt from any Alt-Tab or the like that switched us away
		ClearAllStates ();
		CDAudio_Resume ();
		S_UnblockSound ();

		in_mode_set = false;

		vid.recalc_refdef = 1;

		block_drawing = false;

//		return MGL_NO_SUSPEND_APP;	// 2000-01-31 Valid result correction by Maddes
	}

	return MGL_NO_SUSPEND_APP;		// 2000-01-31 Valid result correction by Maddes
						// changed like bounce.c example from SciTech
}


void registerAllDispDrivers(void)
{
	/* Event though these driver require WinDirect, we register
	 * them so that they will still be available even if DirectDraw
	 * is present and the user has disable the high performance
	 * WinDirect modes.
	 */
	MGL_registerDriver(MGL_VGA8NAME,VGA8_driver);
//	MGL_registerDriver(MGL_VGAXNAME,VGAX_driver);

	/* Register display drivers */
	if (useWinDirect)
	{
//we don't want VESA 1.X drivers		MGL_registerDriver(MGL_SVGA8NAME,SVGA8_driver);
		MGL_registerDriver(MGL_LINEAR8NAME,LINEAR8_driver);

		if (!COM_CheckParm ("-novbeaf"))
			MGL_registerDriver(MGL_ACCEL8NAME,ACCEL8_driver);
	}

	if (useDirectDraw)
	{
		MGL_registerDriver(MGL_DDRAW8NAME,DDRAW8_driver);
	}
}


void registerAllMemDrivers(void)
{
	/* Register memory context drivers */
	MGL_registerDriver(MGL_PACKED8NAME,PACKED8_driver);
}


void VID_InitMGLFull (HINSTANCE hInstance)
{
	int			i, xRes, yRes, bits, vMode, lowres, curmode, temp;
	int			lowstretchedres, stretchedmode, lowstretched;
	uchar		*m;

// FIXME: NT is checked for because MGL currently has a bug that causes it
// to try to use WinDirect modes even on NT
	if (COM_CheckParm("-nowindirect") ||
		COM_CheckParm("-nowd") ||
		COM_CheckParm("-novesa") ||
		WinNT)
	{
		useWinDirect = false;
	}

	if (COM_CheckParm("-nodirectdraw") || COM_CheckParm("-noddraw") || COM_CheckParm("-nodd"))
		useDirectDraw = false;

	// Initialise the MGL
	MGL_unregisterAllDrivers();
	registerAllDispDrivers();
	registerAllMemDrivers();
	MGL_detectGraph(&driver,&mode);
	m = MGL_availableModes();

	if (m[0] != 0xFF)
	{
		lowres = lowstretchedres = 99999;
		lowstretched = 0;
		curmode = 0;

	// find the lowest-res mode, or a mode we can stretch up to and get
	// lowest-res that way
		for (i = 0; m[i] != 0xFF; i++)
		{
			MGL_modeResolution(m[i], &xRes, &yRes,&bits);

			if ((bits == 8) &&
				(xRes <= MAXWIDTH) &&
				(yRes <= MAXHEIGHT) &&
				(curmode < MAX_MODE_LIST))
			{
				if (m[i] == grVGA_320x200x256)
					is_mode0x13 = true;

				if (!COM_CheckParm("-noforcevga"))
				{
					if (m[i] == grVGA_320x200x256)
					{
						mode = i;
						break;
					}
				}

				if (xRes < lowres)
				{
					lowres = xRes;
					mode = i;
				}

				if ((xRes < lowstretchedres) && ((xRes >> 1) >= 320))
				{
					lowstretchedres = xRes >> 1;
					stretchedmode = i;
				}
			}

			curmode++;
		}

	// if there's a mode we can stretch by 2 up to, thereby effectively getting
	// a lower-res mode than the lowest-res real but still at least 320x200, that
	// will be our default mode
		if (lowstretchedres < lowres)
		{
			mode = stretchedmode;
			lowres = lowstretchedres;
			lowstretched = 1;
		}

	// build the mode list, leaving room for the low-res stretched mode, if any
		nummodes++;		// leave room for default mode

		for (i = 0; m[i] != 0xFF; i++)
		{
			MGL_modeResolution(m[i], &xRes, &yRes,&bits);

			if ((bits == 8) &&
				(xRes <= MAXWIDTH) &&
				(yRes <= MAXHEIGHT) &&
				(nummodes < MAX_MODE_LIST))
			{
				if (i == mode)
				{
					if (lowstretched)
					{
						stretchedmode = nummodes;
						curmode = nummodes++;
					}
					else
					{
						curmode = MODE_FULLSCREEN_DEFAULT;
					}
				}
				else
				{
					curmode = nummodes++;
				}

				modelist[curmode].type = MS_FULLSCREEN;
				modelist[curmode].width = xRes;
				modelist[curmode].height = yRes;
				sprintf (modelist[curmode].modedesc, "%dx%d", xRes, yRes);

				if (m[i] == grVGA_320x200x256)
					modelist[curmode].mode13 = 1;
				else
					modelist[curmode].mode13 = 0;

				modelist[curmode].modenum = m[i];
				modelist[curmode].stretched = 0;
				modelist[curmode].dib = 0;
				modelist[curmode].fullscreen = 1;
				modelist[curmode].halfscreen = 0;
				modelist[curmode].bpp = 8;
			}
		}

		if (lowstretched)
		{
			modelist[MODE_FULLSCREEN_DEFAULT] = modelist[stretchedmode];
			modelist[MODE_FULLSCREEN_DEFAULT].stretched = 1;
			modelist[MODE_FULLSCREEN_DEFAULT].width >>= 1;
			modelist[MODE_FULLSCREEN_DEFAULT].height >>= 1;
			sprintf (modelist[MODE_FULLSCREEN_DEFAULT].modedesc, "%dx%d",
					 modelist[MODE_FULLSCREEN_DEFAULT].width,
					 modelist[MODE_FULLSCREEN_DEFAULT].height);
		}

		vid_default = MODE_FULLSCREEN_DEFAULT;

		temp = m[0];

		if (!MGL_init(&driver, &temp, ""))
		{
			initFatalError();
		}
	}

	MGL_setSuspendAppCallback(VID_Suspend);
}


MGLDC *createDisplayDC(int forcemem)
/****************************************************************************
*
* Function:     createDisplayDC
* Returns:      Pointer to the MGL device context to use for the application
*
* Description:  Initialises the MGL and creates an appropriate display
*               device context to be used by the GUI. This creates and
*               apropriate device context depending on the system being
*               compile for, and should be the only place where system
*               specific code is required.
*
****************************************************************************/
{
	MGLDC			*dc;
	pixel_format_t	pf;
	int				npages;

	// Start the specified video mode
	if (!MGL_changeDisplayMode(mode))
		initFatalError();

	npages = MGL_availablePages(mode);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -