📄 vid_win.c
字号:
/*
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 + -