/* 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. */ // gl_vidnt.c -- NT GL vid component #include "quakedef.h" #include "winquake.h" #include "resource.h" #include #define MAX_MODE_LIST 30 #define VID_ROW_SIZE 3 #define WARP_WIDTH 320 #define WARP_HEIGHT 200 #define MAXWIDTH 10000 #define MAXHEIGHT 10000 #define BASEWIDTH 320 #define BASEHEIGHT 200 #define MODE_WINDOWED 0 #define NO_MODE (MODE_WINDOWED - 1) #define MODE_FULLSCREEN_DEFAULT (MODE_WINDOWED + 1) typedef struct { modestate_t type; int width; int height; int modenum; int dib; int fullscreen; int bpp; int halfscreen; char modedesc[17]; } vmode_t; typedef struct { int width; int height; } lmode_t; lmode_t lowresmodes[] = { {320, 200}, {320, 240}, {400, 300}, {512, 384}, }; const char *gl_vendor; const char *gl_renderer; const char *gl_version; const char *gl_extensions; qboolean DDActive; qboolean scr_skipupdate; static vmode_t modelist[MAX_MODE_LIST]; static int nummodes; static vmode_t *pcurrentmode; static vmode_t badmode; static DEVMODE gdevmode; static qboolean vid_initialized = false; static qboolean windowed, leavecurrentmode; static qboolean vid_canalttab = false; static qboolean vid_wassuspended = false; static int windowed_mouse; extern qboolean mouseactive; // from in_win.c static HICON hIcon; int DIBWidth, DIBHeight; RECT WindowRect; DWORD WindowStyle, ExWindowStyle; HWND mainwindow, dibwindow; int vid_modenum = NO_MODE; int vid_default = MODE_WINDOWED; static int windowed_default; unsigned char vid_curpal[256*3]; static float vid_gamma = 1.0; HGLRC baseRC; HDC maindc; glvert_t glv; HWND WINAPI InitializeWindow (HINSTANCE hInstance, int nCmdShow); viddef_t vid; // global video state unsigned short d_8to16table[256]; unsigned d_8to24table[256]; unsigned char d_15to8table[65536]; modestate_t modestate = MS_UNINIT; LONG WINAPI MainWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); void AppActivate(BOOL fActive, BOOL minimize); char *VID_GetModeDescription (int mode); void ClearAllStates (void); void VID_UpdateWindowStatus (void); void GL_Init (void); PROC glArrayElementEXT; PROC glColorPointerEXT; PROC glTexCoordPointerEXT; PROC glVertexPointerEXT; float gldepthmin, gldepthmax; qboolean gl_mtexable = false; qboolean console_enabled = true; // Tomaz - Console Toggle //==================================== cvar_t vid_mode = {"vid_mode","0", false}; // Note that 0 is MODE_WINDOWED cvar_t _vid_default_mode = {"_vid_default_mode","0", true}; // Note that 3 is MODE_FULLSCREEN_DEFAULT cvar_t _vid_default_mode_win = {"_vid_default_mode_win","3", true}; cvar_t vid_wait = {"vid_wait","0"}; cvar_t vid_nopageflip = {"vid_nopageflip","0", true}; cvar_t _vid_wait_override = {"_vid_wait_override", "0", true}; cvar_t vid_config_x = {"vid_config_x","800", true}; cvar_t vid_config_y = {"vid_config_y","600", true}; cvar_t vid_stretch_by_2 = {"vid_stretch_by_2","1", true}; cvar_t _windowed_mouse = {"_windowed_mouse","1", true}; int window_center_x, window_center_y, window_x, window_y, window_width, window_height; RECT window_rect; int MHz,CPUfamily,Mem,InstCache,DataCache,L2Cache; char VendorID[16]; boolean SupportCMOVs,Support3DNow,Support3DNowExt,SupportMMX,SupportMMXext,SupportSSE; #pragma warning(disable: 4035) __inline __int64 GetCycleNumber() { __asm { RDTSC } } void CenterWindow(HWND hWndCenter, int width, int height, BOOL lefttopjustify) { int CenterX, CenterY; CenterX = (GetSystemMetrics(SM_CXSCREEN) - width) * 0.5; // Tomaz - Speed CenterY = (GetSystemMetrics(SM_CYSCREEN) - height) * 0.5; // Tomaz - Speed if (CenterX > CenterY*2) CenterX >>= 1; // dual screens CenterX = (CenterX < 0) ? 0: CenterX; CenterY = (CenterY < 0) ? 0: CenterY; SetWindowPos (hWndCenter, NULL, CenterX, CenterY, 0, 0, SWP_NOSIZE | SWP_NOZORDER | SWP_SHOWWINDOW | SWP_DRAWFRAME); } qboolean VID_SetWindowedMode (int modenum) { HDC hdc; int lastmodestate, width, height; RECT rect; lastmodestate = modestate; WindowRect.top = 0; WindowRect.left = 0; WindowRect.right = modelist[modenum].width; WindowRect.bottom = modelist[modenum].height; DIBWidth = modelist[modenum].width; DIBHeight = modelist[modenum].height; WindowStyle = WS_OVERLAPPED | WS_BORDER | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX; ExWindowStyle = 0; rect = WindowRect; AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); width = rect.right - rect.left; height = rect.bottom - rect.top; // Create the DIB window dibwindow = CreateWindowEx ( ExWindowStyle, "EternalWar", "EternalWar", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); if (!dibwindow) Sys_Error ("Couldn't create DIB window"); // Center and show the DIB window CenterWindow(dibwindow, WindowRect.right - WindowRect.left, WindowRect.bottom - WindowRect.top, false); ShowWindow (dibwindow, SW_SHOWDEFAULT); UpdateWindow (dibwindow); modestate = MS_WINDOWED; // because we have set the background brush for the window to NULL // (to avoid flickering when re-sizing the window on the desktop), // we clear the window to black when created, otherwise it will be // empty while Quake starts up. hdc = GetDC(dibwindow); PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); ReleaseDC(dibwindow, hdc); if ((signed)vid.conheight > modelist[modenum].height) vid.conheight = modelist[modenum].height; if ((signed)vid.conwidth > modelist[modenum].width) vid.conwidth = modelist[modenum].width; vid.width = vid.conwidth; vid.height = vid.conheight; vid.numpages = 2; mainwindow = dibwindow; SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); return true; } qboolean VID_SetFullDIBMode (int modenum) { HDC hdc; int lastmodestate, width, height; RECT rect; if (!leavecurrentmode) { gdevmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; gdevmode.dmBitsPerPel = modelist[modenum].bpp; gdevmode.dmPelsWidth = modelist[modenum].width << modelist[modenum].halfscreen; gdevmode.dmPelsHeight = modelist[modenum].height; gdevmode.dmSize = sizeof (gdevmode); if (ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN) != DISP_CHANGE_SUCCESSFUL) Sys_Error ("Couldn't set fullscreen DIB mode"); } lastmodestate = modestate; modestate = MS_FULLDIB; WindowRect.top = WindowRect.left = 0; WindowRect.right = modelist[modenum].width; WindowRect.bottom = modelist[modenum].height; DIBWidth = modelist[modenum].width; DIBHeight = modelist[modenum].height; WindowStyle = WS_POPUP; ExWindowStyle = 0; rect = WindowRect; AdjustWindowRectEx(&rect, WindowStyle, FALSE, 0); width = rect.right - rect.left; height = rect.bottom - rect.top; // Create the DIB window dibwindow = CreateWindowEx ( ExWindowStyle, "EternalWar", "EternalWar", WindowStyle, rect.left, rect.top, width, height, NULL, NULL, global_hInstance, NULL); if (!dibwindow) Sys_Error ("Couldn't create DIB window"); ShowWindow (dibwindow, SW_SHOWDEFAULT); UpdateWindow (dibwindow); // Because we have set the background brush for the window to NULL // (to avoid flickering when re-sizing the window on the desktop), we // clear the window to black when created, otherwise it will be // empty while Quake starts up. hdc = GetDC(dibwindow); PatBlt(hdc,0,0,WindowRect.right,WindowRect.bottom,BLACKNESS); ReleaseDC(dibwindow, hdc); if ((signed)vid.conheight > modelist[modenum].height) vid.conheight = modelist[modenum].height; if ((signed)vid.conwidth > modelist[modenum].width) vid.conwidth = modelist[modenum].width; vid.width = vid.conwidth; vid.height = vid.conheight; vid.numpages = 2; // needed because we're not getting WM_MOVE messages fullscreen on NT window_x = 0; window_y = 0; mainwindow = dibwindow; SendMessage (mainwindow, WM_SETICON, (WPARAM)TRUE, (LPARAM)hIcon); SendMessage (mainwindow, WM_SETICON, (WPARAM)FALSE, (LPARAM)hIcon); return true; } int VID_SetMode (int modenum, unsigned char *palette) { int original_mode, temp; qboolean stat; MSG msg; if ((windowed && (modenum != 0)) || (!windowed && (modenum < 1)) || (!windowed && (modenum >= nummodes))) { Sys_Error ("Bad video mode\n"); } // so Con_Printfs don't mess us up by forcing vid and snd updates temp = scr_disabled_for_loading; scr_disabled_for_loading = true; // S_PauseMusic(); if (vid_modenum == NO_MODE) original_mode = windowed_default; else original_mode = vid_modenum; // Set either the fullscreen or windowed mode if (modelist[modenum].type == MS_WINDOWED) { if (_windowed_mouse.value && key_dest == key_game) { stat = VID_SetWindowedMode(modenum); IN_ActivateMouse (); IN_HideMouse (); } else { IN_DeactivateMouse (); IN_ShowMouse (); stat = VID_SetWindowedMode(modenum); } } else if (modelist[modenum].type == MS_FULLDIB) { stat = VID_SetFullDIBMode(modenum); IN_ActivateMouse (); IN_HideMouse (); } else { Sys_Error ("VID_SetMode: Bad mode type in modelist"); } window_width = DIBWidth; window_height = DIBHeight; VID_UpdateWindowStatus (); // S_ResumeMusic(); scr_disabled_for_loading = temp; if (!stat) { Sys_Error ("Couldn't set video mode"); } // now we try to make sure we get the focus on the mode switch, because // sometimes in some systems we don't. We grab the foreground, then // finish setting up, pump all our messages, and sleep for a little while // to let messages finish bouncing around the system, then we put // ourselves at the top of the z order, then grab the foreground again, // Who knows if it helps, but it probably doesn't hurt SetForegroundWindow (mainwindow); VID_SetPalette (palette); vid_modenum = modenum; Cvar_SetValue ("vid_mode", (float)vid_modenum); while (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) { TranslateMessage (&msg); DispatchMessage (&msg); } Sleep (100); SetWindowPos (mainwindow, HWND_TOP, 0, 0, 0, 0, SWP_DRAWFRAME | SWP_NOMOVE | SWP_NOSIZE | SWP_SHOWWINDOW | SWP_NOCOPYBITS); SetForegroundWindow (mainwindow); // fix the leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); if (!msg_suppress_1) Con_SafePrintf ("Video mode %s initialized.\n", VID_GetModeDescription (vid_modenum)); VID_SetPalette (palette); vid.recalc_refdef = 1; return true; } /* ================ 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) * 0.5; // Tomaz - Speed window_center_y = (window_rect.top + window_rect.bottom) * 0.5; // Tomaz - Speed IN_UpdateClipCursor (); } //==================================== BINDTEXFUNCPTR bindTexFunc; #define TEXTURE_EXT_STRING "GL_EXT_texture_object" void CheckTextureExtensions (void) { char *tmp; qboolean texture_ext; HINSTANCE hInstGL; texture_ext = FALSE; /* check for texture extension */ tmp = (unsigned char *)glGetString(GL_EXTENSIONS); while (*tmp) { if (strncmp((const char*)tmp, TEXTURE_EXT_STRING, strlen(TEXTURE_EXT_STRING)) == 0) texture_ext = TRUE; tmp++; } if (!texture_ext || COM_CheckParm ("-gl11") ) { hInstGL = LoadLibrary("opengl32.dll"); if (hInstGL == NULL) Sys_Error ("Couldn't load opengl32.dll\n"); bindTexFunc = (void *)GetProcAddress(hInstGL,"glBindTexture"); if (!bindTexFunc) Sys_Error ("No texture objects!"); return; } /* load library and get procedure adresses for texture extension API */ if ((bindTexFunc = (BINDTEXFUNCPTR) wglGetProcAddress((LPCSTR) "glBindTextureEXT")) == NULL) { Sys_Error ("GetProcAddress for BindTextureEXT failed"); return; } } void CheckArrayExtensions (void) { char *tmp; /* check for texture extension */ tmp = (unsigned char *)glGetString(GL_EXTENSIONS); while (*tmp) { if (strncmp((const char*)tmp, "GL_EXT_vertex_array", strlen("GL_EXT_vertex_array")) == 0) { if (((glArrayElementEXT = wglGetProcAddress("glArrayElementEXT")) == NULL) || ((glColorPointerEXT = wglGetProcAddress("glColorPointerEXT")) == NULL) || ((glTexCoordPointerEXT = wglGetProcAddress("glTexCoordPointerEXT")) == NULL) || ((glVertexPointerEXT = wglGetProcAddress("glVertexPointerEXT")) == NULL) ) { Sys_Error ("GetProcAddress for vertex extension failed"); return; } return; } tmp++; } Sys_Error ("Vertex array extension not present"); } int texture_mode = GL_LINEAR; int texture_extension_number = 1; GLenum TEXTURE0_SGIS_ARB; GLenum TEXTURE1_SGIS_ARB; void CheckMultiTextureExtensions(void) { if (COM_CheckParm("-nomtex")) { Con_Printf("&f9001 Multitexture Disabled\n\n &r"); return; } if (strstr(gl_extensions, "GL_ARB_multitexture ")) { Con_Printf("&f9001 GL_ARB_multitexture enabled &r \n\n"); qglMTexCoord2fSGIS_ARB = (void *) wglGetProcAddress("glMultiTexCoord2fARB"); qglSelectTextureSGIS_ARB = (void *) wglGetProcAddress("glActiveTextureARB"); gl_mtexable = true; TEXTURE0_SGIS_ARB = TEXTURE0_ARB; TEXTURE1_SGIS_ARB = TEXTURE1_ARB; return; } if (strstr(gl_extensions, "GL_SGIS_multitexture ")) { Con_Printf("&f9001 GL_SGIS_multitexture enabled\n\n &r"); qglMTexCoord2fSGIS_ARB = (void *) wglGetProcAddress("glMTexCoord2fSGIS"); qglSelectTextureSGIS_ARB = (void *) wglGetProcAddress("glSelectTextureSGIS"); gl_mtexable = true; TEXTURE0_SGIS_ARB = TEXTURE0_SGIS; TEXTURE1_SGIS_ARB = TEXTURE1_SGIS; return; } Con_Printf("\n&f9001 Multitexture Not Found\n &r"); } void GetMHz(void) { LARGE_INTEGER t1,t2,tf; __int64 c1,c2; QueryPerformanceFrequency(&tf); QueryPerformanceCounter(&t1); c1 = GetCycleNumber(); _asm { MOV EBX, 5000000 WaitAlittle: DEC EBX JNZ WaitAlittle } QueryPerformanceCounter(&t2); c2 = GetCycleNumber(); Con_Printf("\nCPU Speed: %d MHz\n", (int) ((c2 - c1) * tf.QuadPart / (t2.QuadPart - t1.QuadPart) / 1000000)); } void GetSysInfo(){ MEMORYSTATUS ms; ms.dwLength = sizeof(MEMORYSTATUS); GlobalMemoryStatus(&ms); Mem = ms.dwTotalPhys >> 10; __asm { PUSHFD POP EAX MOV EBX, EAX XOR EAX, 00200000h PUSH EAX POPFD PUSHFD POP EAX CMP EAX, EBX JZ ExitCpuTest XOR EAX, EAX CPUID MOV DWORD PTR [VendorID], EBX MOV DWORD PTR [VendorID + 4], EDX MOV DWORD PTR [VendorID + 8], ECX MOV DWORD PTR [VendorID + 12], 0 MOV EAX, 1 CPUID TEST EDX, 0x00008000 SETNZ AL MOV SupportCMOVs, AL TEST EDX, 0x00800000 SETNZ AL MOV SupportMMX, AL TEST EDX, 0x02000000 SETNZ AL MOV SupportSSE, AL SHR EAX, 8 AND EAX, 0x0000000F MOV CPUfamily, EAX MOV MHz, 0 TEST EDX, 0x00000008 JZ NoTimeStampCounter CALL GetMHz MOV MHz, EAX NoTimeStampCounter: MOV Support3DNow, 0 MOV EAX, 80000000h CPUID CMP EAX, 80000000h JBE NoExtendedFunction MOV EAX, 80000001h CPUID TEST EDX, 80000000h SETNZ AL MOV Support3DNow, AL TEST EDX, 40000000h SETNZ AL MOV Support3DNowExt, AL TEST EDX, 0x00400000 SETNZ AL MOV SupportMMXext, AL MOV EAX, 80000005h CPUID SHR ECX, 24 MOV DataCache, ECX SHR EDX, 24 MOV InstCache, EDX MOV EAX, 80000006h CPUID SHR ECX, 16 MOV L2Cache, ECX JMP ExitCpuTest NoExtendedFunction: MOV EAX, 2 CPUID MOV ESI, 4 TestCache: CMP DL, 0x40 JNA NotL2 MOV CL, DL SUB CL, 0x40 SETZ CH DEC CH AND CL, CH MOV EBX, 64 SHL EBX, CL MOV L2Cache, EBX NotL2: CMP DL, 0x06 JNE Next1 MOV InstCache, 8 Next1: CMP DL, 0x08 JNE Next2 MOV InstCache, 16 Next2: CMP DL, 0x0A JNE Next3 MOV DataCache, 8 Next3: CMP DL, 0x0C JNE Next4 MOV DataCache, 16 Next4: SHR EDX, 8 DEC ESI JNZ TestCache ExitCpuTest: } } /* =============== GL_Init =============== */ extern char *QSG_EXTENSIONS; void GL_Init (void) { // // Request system info - useless, but funny // GetSysInfo(); // // Print the info we just requested // Con_Printf("CPU Family: %i\n", CPUfamily); Con_Printf("CPU Vendor: %s\n", VendorID); Con_Printf("Memory: %i Kb\n\n", Mem); Con_Printf("Detecting CPU extensions:\n"); if (Support3DNow) { Con_Printf(" *3DNow detected\n"); } if (Support3DNowExt) { Con_Printf(" *3DNow extensions detected\n"); } if (SupportMMX) { Con_Printf(" *MMX detected\n"); } if (SupportMMXext) { Con_Printf(" *MMX extensions detected\n"); } // // Video card info // gl_vendor = glGetString (GL_VENDOR); Con_Printf ("\nGL_VENDOR: %s\n", gl_vendor); gl_renderer = glGetString (GL_RENDERER); Con_Printf ("GL_RENDERER: %s\n", gl_renderer); gl_version = glGetString (GL_VERSION); Con_Printf ("GL_VERSION: %s\n\n", gl_version); gl_extensions = glGetString (GL_EXTENSIONS); Con_Printf ("GL_EXTENSIONS:\n%s\n", gl_extensions); Con_Printf ("\nQSG extensions: %s\n", QSG_EXTENSIONS); // // Tomaz - Console Toggle Begin // if (COM_CheckParm ("-console")) console_enabled = true; // // Check extensions // CheckTextureExtensions (); CheckMultiTextureExtensions (); glLineWidth(2); glHint (GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); glClearColor (0,0,0,0); glCullFace(GL_FRONT); glEnable(GL_TEXTURE_2D); glEnable(GL_DITHER); glAlphaFunc(GL_GREATER, 0); glDepthFunc (GL_LEQUAL); // glPolygonMode (GL_FRONT_AND_BACK, GL_FILL); glShadeModel (GL_SMOOTH); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); //Changed glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); //Changed glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_SPHERE_MAP); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); glEnable (GL_CULL_FACE); // This can be done locally, but is a pain in the ass to change when it's already // removed from every function, so we'll just leave it here for now. glEnable (GL_BLEND); glDisable (GL_ALPHA_TEST); Con_Printf ("Forcing glFinish\n"); glFinish(); } /* ================= GL_BeginRendering ================= */ void GL_BeginRendering (int *x, int *y, int *width, int *height) { extern cvar_t gl_clear; *x = *y = 0; *width = WindowRect.right - WindowRect.left; *height = WindowRect.bottom - WindowRect.top; } void GL_EndRendering (void) { if (!scr_skipupdate) SwapBuffers(maindc); // handle the mouse state when windowed if that's changed if (modestate == MS_WINDOWED) { if (!_windowed_mouse.value) { if (windowed_mouse) { IN_DeactivateMouse (); IN_ShowMouse (); windowed_mouse = false; } } else { windowed_mouse = true; if (key_dest == key_game && !mouseactive && ActiveApp) { IN_ActivateMouse (); IN_HideMouse (); } else if (mouseactive && key_dest != key_game) { IN_DeactivateMouse (); IN_ShowMouse (); } } } } void VID_SetPalette (unsigned char *palette) { byte *pal; unsigned r,g,b; unsigned v; int r1,g1,b1; int j,k,l; unsigned short i; unsigned *table; // // 8 8 8 encoding // pal = palette; table = d_8to24table; for (i=0 ; i<256 ; i++) { r = pal[0]; g = pal[1]; b = pal[2]; pal += 3; v = (255<<24) + (r<<0) + (g<<8) + (b<<16); *table++ = v; } d_8to24table[255] &= 0x000000; // 255 is transparent // JACK: 3D distance calcs - k is last closest, l is the distance. // FIXME: Precalculate this and cache to disk. for (i=0; i < (1<<15); i++) { /* Maps 000000000000000 000000000011111 = Red = 0x1F 000001111100000 = Blue = 0x03E0 111110000000000 = Grn = 0x7C00 */ r = ((i & 0x1F) << 3)+4; g = ((i & 0x03E0) >> 2)+4; b = ((i & 0x7C00) >> 7)+4; pal = (unsigned char *)d_8to24table; for (v=0,k=0,l=100000000; v<256; v++,pal+=4) // Tomaz Speed { r1 = r-pal[0]; g1 = g-pal[1]; b1 = b-pal[2]; j = (r1*r1)+(g1*g1)+(b1*b1); if (j', '?', K_SHIFT,'*', K_ALT,' ', 0 , K_F1, K_F2, K_F3, K_F4, K_F5, // 3 K_F6, K_F7, K_F8, K_F9, K_F10, K_PAUSE , 0 , K_HOME, K_UPARROW,K_PGUP,'_',K_LEFTARROW,'%',K_RIGHTARROW,'+',K_END, //4 K_DOWNARROW,K_PGDN,K_INS,K_DEL,0,0, 0, K_F11, K_F12,0 , 0 , 0 , 0 , 0 , 0 , 0, // 5 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, // 6 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0, 0 , 0 , 0 , 0 , 0 , 0 , 0 , 0 // 7 }; /* ======= MapKey Map from windows to quake keynums ======= */ int MapKey (int key) { key = (key>>16)&255; if (key > 127) return 0; if (scantokey[key] == 0) Con_DPrintf("key 0x%02x has no translation\n", key); return scantokey[key]; } /* =================================================================== MAIN WINDOW =================================================================== */ /* ================ 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 (); } void AppActivate(BOOL fActive, BOOL minimize) /**************************************************************************** * * Function: AppActivate * Parameters: fActive - True if app is activating * * Description: If the application is activating, then swap the system * into SYSPAL_NOSTATIC mode so that our palettes will display * correctly. * ****************************************************************************/ { static BOOL sound_active; ActiveApp = fActive; Minimized = minimize; // enable/disable sound on focus gain/loss if (!ActiveApp && sound_active) { S_BlockSound (); sound_active = false; } else if (ActiveApp && !sound_active) { S_UnblockSound (); sound_active = true; } if (fActive) { if (modestate == MS_FULLDIB) { IN_ActivateMouse (); IN_HideMouse (); if (vid_canalttab && vid_wassuspended) { vid_wassuspended = false; ChangeDisplaySettings (&gdevmode, CDS_FULLSCREEN); ShowWindow(mainwindow, SW_SHOWNORMAL); MoveWindow(mainwindow, 0, 0, gdevmode.dmPelsWidth, gdevmode.dmPelsHeight, false); // Tomaz - Alt+Tab Fix } } else if ((modestate == MS_WINDOWED) && _windowed_mouse.value && key_dest == key_game) { IN_ActivateMouse (); IN_HideMouse (); } } if (!fActive) { if (modestate == MS_FULLDIB) { IN_DeactivateMouse (); IN_ShowMouse (); if (vid_canalttab) { ChangeDisplaySettings (NULL, 0); vid_wassuspended = true; } } else if ((modestate == MS_WINDOWED) && _windowed_mouse.value) { IN_DeactivateMouse (); IN_ShowMouse (); } } } /* main window procedure */ LONG WINAPI MainWndProc ( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { LONG lRet = 1; int fActive, fMinimized, temp; extern unsigned int uiWheelMessage; if ( uMsg == uiWheelMessage ) uMsg = WM_MOUSEWHEEL; switch (uMsg) { case WM_KILLFOCUS: if (modestate == MS_FULLDIB) ShowWindow(mainwindow, SW_SHOWMINNOACTIVE); break; case WM_CREATE: break; case WM_MOVE: window_x = (int) LOWORD(lParam); window_y = (int) HIWORD(lParam); VID_UpdateWindowStatus (); break; case WM_KEYDOWN: case WM_SYSKEYDOWN: Key_Event (MapKey(lParam), true); break; case WM_KEYUP: case WM_SYSKEYUP: Key_Event (MapKey(lParam), false); break; case WM_SYSCHAR: // keep Alt-Space from happening break; // this is complicated because Win32 seems to pack multiple mouse events into // one update sometimes, so we always check all states and look for events case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_RBUTTONDOWN: case WM_RBUTTONUP: case WM_MBUTTONDOWN: case WM_MBUTTONUP: case WM_MOUSEMOVE: temp = 0; if (wParam & MK_LBUTTON) temp |= 1; if (wParam & MK_RBUTTON) temp |= 2; if (wParam & MK_MBUTTON) temp |= 4; IN_MouseEvent (temp); break; // JACK: This is the mouse wheel with the Intellimouse // Its delta is either positive or neg, and we generate the proper // Event. case WM_MOUSEWHEEL: if ((short) HIWORD(wParam) > 0) { Key_Event(K_MWHEELUP, true); Key_Event(K_MWHEELUP, false); } else { Key_Event(K_MWHEELDOWN, true); Key_Event(K_MWHEELDOWN, false); } break; case WM_SIZE: break; case WM_CLOSE: if (MessageBox (mainwindow, "Are you sure you want to quit?", "Confirm Exit", MB_YESNO | MB_SETFOREGROUND | MB_ICONQUESTION) == IDYES) { Sys_Quit (); } break; case WM_ACTIVATE: fActive = LOWORD(wParam); fMinimized = (BOOL) HIWORD(wParam); AppActivate(!(fActive == WA_INACTIVE), fMinimized); // fix the leftover Alt from any Alt-Tab or the like that switched us away ClearAllStates (); break; case WM_DESTROY: { if (dibwindow) DestroyWindow (dibwindow); PostQuitMessage (0); } break; case MM_MCINOTIFY: // lRet = CDAudio_MessageHandler (hWnd, uMsg, wParam, lParam); break; default: /* pass all unhandled messages to DefWindowProc */ lRet = DefWindowProc (hWnd, uMsg, wParam, lParam); break; } /* return 1 if handled message, 0 if not */ return lRet; } /* ================= VID_NumModes ================= */ int VID_NumModes (void) { return nummodes; } /* ================= VID_GetModePtr ================= */ vmode_t *VID_GetModePtr (int modenum) { if ((modenum >= 0) && (modenum < nummodes)) return &modelist[modenum]; else return &badmode; } /* ================= VID_GetModeDescription ================= */ char *VID_GetModeDescription (int mode) { char *pinfo; vmode_t *pv; static char temp[100]; if ((mode < 0) || (mode >= nummodes)) return NULL; if (!leavecurrentmode) { pv = VID_GetModePtr (mode); pinfo = pv->modedesc; } else { sprintf (temp, "Desktop resolution (%dx%d)", modelist[MODE_FULLSCREEN_DEFAULT].width, modelist[MODE_FULLSCREEN_DEFAULT].height); pinfo = temp; } return pinfo; } // KJB: Added this to return the mode driver name in description for console char *VID_GetExtModeDescription (int mode) { static char pinfo[40]; vmode_t *pv; if ((mode < 0) || (mode >= nummodes)) return NULL; pv = VID_GetModePtr (mode); if (modelist[mode].type == MS_FULLDIB) { if (!leavecurrentmode) { sprintf(pinfo,"%s fullscreen", pv->modedesc); } else { sprintf (pinfo, "Desktop resolution (%dx%d)", modelist[MODE_FULLSCREEN_DEFAULT].width, modelist[MODE_FULLSCREEN_DEFAULT].height); } } else { if (modestate == MS_WINDOWED) sprintf(pinfo, "%s windowed", pv->modedesc); else sprintf(pinfo, "windowed"); } return pinfo; } /* ================= VID_DescribeCurrentMode_f ================= */ void VID_DescribeCurrentMode_f (void) { Con_Printf ("%s\n", VID_GetExtModeDescription (vid_modenum)); } /* ================= VID_NumModes_f ================= */ void VID_NumModes_f (void) { if (nummodes == 1) Con_Printf ("%d video mode is available\n", nummodes); else Con_Printf ("%d video modes are available\n", nummodes); } /* ================= VID_DescribeMode_f ================= */ void VID_DescribeMode_f (void) { int t, modenum; modenum = Q_atoi (Cmd_Argv(1)); t = leavecurrentmode; leavecurrentmode = 0; Con_Printf ("%s\n", VID_GetExtModeDescription (modenum)); leavecurrentmode = t; } /* ================= VID_DescribeModes_f ================= */ void VID_DescribeModes_f (void) { int i, lnummodes, t; char *pinfo; vmode_t *pv; lnummodes = VID_NumModes (); t = leavecurrentmode; leavecurrentmode = 0; for (i=1 ; i8 bpp modes originalnummodes = nummodes; modenum = 0; do { stat = EnumDisplaySettings (NULL, modenum, &devmode); if ((devmode.dmBitsPerPel >= 15) && (devmode.dmPelsWidth <= MAXWIDTH) && (devmode.dmPelsHeight <= MAXHEIGHT) && (nummodes < MAX_MODE_LIST)) { devmode.dmFields = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT; if (ChangeDisplaySettings (&devmode, CDS_TEST | CDS_FULLSCREEN) == DISP_CHANGE_SUCCESSFUL) { modelist[nummodes].type = MS_FULLDIB; modelist[nummodes].width = devmode.dmPelsWidth; modelist[nummodes].height = devmode.dmPelsHeight; modelist[nummodes].modenum = 0; modelist[nummodes].halfscreen = 0; modelist[nummodes].dib = 1; modelist[nummodes].fullscreen = 1; modelist[nummodes].bpp = devmode.dmBitsPerPel; sprintf (modelist[nummodes].modedesc, "%dx%dx%d", devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel); // if the width is more than twice the height, reduce it by half because this // is probably a dual-screen monitor if (!COM_CheckParm("-noadjustaspect")) { if (modelist[nummodes].width > (modelist[nummodes].height << 1)) { modelist[nummodes].width >>= 1; modelist[nummodes].halfscreen = 1; sprintf (modelist[nummodes].modedesc, "%dx%dx%d", modelist[nummodes].width, modelist[nummodes].height, modelist[nummodes].bpp); } } for (i=originalnummodes, existingmode = 0 ; i 255) inf = 255; palette[i] = inf; } memcpy (pal, palette, sizeof(palette)); } /* =================== SaveCurrentVidMode =================== */ void SaveCurrentVidMode (void) { FILE *f; int i; Sys_mkdir (va("%s/scripts", com_gamedir)); f = fopen (va("%s/scripts/startup.txt",com_gamedir), "w"); // open/create file for writing if (!f) { // crash, when we don't have the right to write a file, or out of disk space Sys_Error ("Could not write startup-resolution file, check diskspace or user-rights"); } i = vid_modenum; // assign our current video mode to i fprintf (f, "%i\n", modelist[i].width); // save current width fprintf (f, "%i\n", modelist[i].bpp); // save current bpp fprintf (f, "// file generated by Eternal War, do not modify"); // warning msg, can be removed fclose (f); // close the file } /* =================== VID_Init Edited by BramBo to support reading the default screen resolution from startup.cfg =================== */ void VID_Init (unsigned char *palette) { int i, existingmode; int basenummodes, width, height, bpp, findbpp, done; HDC hdc; DEVMODE devmode; memset(&devmode, 0, sizeof(devmode)); Cvar_RegisterVariable (&vid_mode); Cvar_RegisterVariable (&vid_wait); Cvar_RegisterVariable (&vid_nopageflip); Cvar_RegisterVariable (&_vid_wait_override); Cvar_RegisterVariable (&_vid_default_mode); Cvar_RegisterVariable (&_vid_default_mode_win); Cvar_RegisterVariable (&vid_config_x); Cvar_RegisterVariable (&vid_config_y); Cvar_RegisterVariable (&vid_stretch_by_2); Cvar_RegisterVariable (&_windowed_mouse); Cmd_AddCommand ("vid_nummodes", VID_NumModes_f); Cmd_AddCommand ("vid_describecurrentmode", VID_DescribeCurrentMode_f); Cmd_AddCommand ("vid_describemode", VID_DescribeMode_f); Cmd_AddCommand ("vid_describemodes", VID_DescribeModes_f); Cmd_AddCommand ("vid_savecurrentmode", SaveCurrentVidMode); // command to write our current config to the startup file hIcon = LoadIcon (global_hInstance, MAKEINTRESOURCE (IDI_ICON2)); InitCommonControls(); VID_InitDIB (global_hInstance); // this is where our config file is read, so we don't have to do it twice basenummodes = nummodes = 1; VID_InitFullDIB (global_hInstance); if (!filexists) { cbpp = 15; // HACK - default bpp to 15 if our startup config file doesn't exist. findbpp = 1; } // decide wether to choose windowed or fullscreen if (COM_CheckParm("-window")) { hdc = GetDC (NULL); if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) { Sys_Error ("Can't run in non-RGB mode"); } ReleaseDC (NULL, hdc); windowed = true; vid_default = MODE_WINDOWED; // check to see if "-width" is set by the user if (COM_CheckParm("-width")) { // yes, set the value as our current width width = Q_atoi(com_argv[COM_CheckParm("-width")+1]); } else { // no, check if our config file exists if (!filexists) { width = 640; // config file doesn't exist, use the standard value } else { width = cwidth; //assign our config file width to the internal width } } } else { // user didn't set "-window", so check cbpp if (cbpp == 0) // if -window isn't set, but cbpp == 0, assume we're running windowed { // do the normal windowed code stuff hdc = GetDC (NULL); if (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) { Sys_Error ("Can't run in non-RGB mode"); } ReleaseDC (NULL, hdc); windowed = true; vid_default = MODE_WINDOWED; // strangely enough, the windowed height/width isn't set here... } else // else, do the normal fullscreen stuff { if (nummodes == 1) { Sys_Error ("No RGB fullscreen modes available"); } windowed = false; if (COM_CheckParm("-mode")) { vid_default = Q_atoi(com_argv[COM_CheckParm("-mode")+1]); } else { if (COM_CheckParm("-current")) { modelist[MODE_FULLSCREEN_DEFAULT].width = GetSystemMetrics (SM_CXSCREEN); modelist[MODE_FULLSCREEN_DEFAULT].height = GetSystemMetrics (SM_CYSCREEN); vid_default = MODE_FULLSCREEN_DEFAULT; leavecurrentmode = 1; } else { // check to see if "-width" is set by the user if (COM_CheckParm("-width")) { // yes, set the value as our current width width = Q_atoi(com_argv[COM_CheckParm("-width")+1]); } else { // no, check if our config file exists if (!filexists) { width = 640; // config file doesn't exist, use the standard value } else { width = cwidth; //assign our config file width to the internal width } } // check to see if the "-bpp" is set by the user if (COM_CheckParm("-bpp")) { // yes, set the user value as our current value bpp = Q_atoi(com_argv[COM_CheckParm("-bpp")+1]); findbpp = 0; // don't search for a decent bpp } else { // no, again, check if our config file exists if (!filexists) { // config file doesn't exist, set bpp to standard value bpp = 15; findbpp = 1; // search for a bpp value which may be better } else { // config file exists, set our config value as bpp bpp = cbpp; findbpp = 0; // don't search for other bpp values } } if (COM_CheckParm("-height")) { height = Q_atoi(com_argv[COM_CheckParm("-height")+1]); } // if they want to force it, add the specified mode to the list if (COM_CheckParm("-force") && (nummodes < MAX_MODE_LIST)) { modelist[nummodes].type = MS_FULLDIB; modelist[nummodes].width = width; modelist[nummodes].height = height; modelist[nummodes].modenum = 0; modelist[nummodes].halfscreen = 0; modelist[nummodes].dib = 1; modelist[nummodes].fullscreen = 1; modelist[nummodes].bpp = bpp; sprintf (modelist[nummodes].modedesc, "%dx%dx%d", devmode.dmPelsWidth, devmode.dmPelsHeight, devmode.dmBitsPerPel); for (i=nummodes, existingmode = 0 ; i