2014-03-15 16:59:03 +00:00
|
|
|
// Emacs style mode select -*- C++ -*-
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
|
|
// Copyright (C) 1998-2000 by DooM Legacy Team.
|
|
|
|
//
|
|
|
|
// 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.
|
|
|
|
//-----------------------------------------------------------------------------
|
|
|
|
/// \file
|
|
|
|
/// \brief win32 video driver for Doom Legacy
|
|
|
|
|
|
|
|
#include "../doomdef.h"
|
|
|
|
|
|
|
|
#ifdef _WINDOWS
|
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <stdarg.h>
|
|
|
|
|
|
|
|
#include "../d_clisrv.h"
|
|
|
|
#include "../i_system.h"
|
|
|
|
#include "../m_argv.h"
|
|
|
|
#include "../v_video.h"
|
|
|
|
#include "../st_stuff.h"
|
|
|
|
#include "../i_video.h"
|
|
|
|
#include "../z_zone.h"
|
|
|
|
#include "fabdxlib.h"
|
|
|
|
#include "../doomstat.h"
|
|
|
|
#include "win_main.h"
|
|
|
|
#include "../command.h"
|
|
|
|
#include "../screen.h"
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
#include "win_dll.h" // loading the render DLL
|
|
|
|
#include "../hardware/hw_drv.h" // calling driver init & shutdown
|
|
|
|
#include "../hardware/hw_main.h" // calling HWR module init & shutdown
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// -------
|
|
|
|
// Globals
|
|
|
|
// -------
|
|
|
|
|
|
|
|
// this is the CURRENT rendermode!! very important: used by w_wad, and much other code
|
|
|
|
rendermode_t rendermode = render_soft;
|
|
|
|
static void OnTop_OnChange(void);
|
|
|
|
// synchronize page flipping with screen refresh
|
|
|
|
static CV_PossibleValue_t CV_NeverOnOff[] = {{-1, "Never"}, {0, "Off"}, {1, "On"}, {0, NULL}};
|
|
|
|
consvar_t cv_vidwait = {"vid_wait", "On", CV_SAVE, CV_OnOff, OnTop_OnChange, 0, NULL, NULL, 0, 0, NULL};
|
|
|
|
static consvar_t cv_stretch = {"stretch", "On", CV_SAVE|CV_NOSHOWHELP, CV_OnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
|
|
|
static consvar_t cv_ontop = {"ontop", "Never", 0, CV_NeverOnOff, NULL, 0, NULL, NULL, 0, 0, NULL};
|
|
|
|
|
|
|
|
boolean highcolor;
|
2020-05-06 22:35:54 +00:00
|
|
|
int vid_opengl_state = 0;
|
2014-03-15 16:59:03 +00:00
|
|
|
|
|
|
|
static BOOL bDIBMode; // means we are using DIB instead of DirectDraw surfaces
|
|
|
|
static LPBITMAPINFO bmiMain = NULL;
|
|
|
|
static HDC hDCMain = NULL;
|
|
|
|
|
|
|
|
// -----------------
|
|
|
|
// Video modes stuff
|
|
|
|
// -----------------
|
|
|
|
|
|
|
|
#define MAX_EXTRA_MODES 36
|
|
|
|
static vmode_t extra_modes[MAX_EXTRA_MODES] = {{NULL, NULL, 0, 0, 0, 0, 0, 0, NULL, NULL, 0}};
|
|
|
|
static char names[MAX_EXTRA_MODES][10];
|
|
|
|
|
|
|
|
static INT32 numvidmodes; // total number of DirectDraw display modes
|
|
|
|
static vmode_t *pvidmodes; // start of videomodes list.
|
|
|
|
static vmode_t *pcurrentmode; // the current active videomode.
|
|
|
|
static BOOL bWinParm;
|
|
|
|
static INT32 WINAPI VID_SetWindowedDisplayMode(viddef_t *lvid, vmode_t *currentmode);
|
|
|
|
|
|
|
|
// this holds description of the startup video mode,
|
|
|
|
// the resolution is 320x200, windowed on the desktop
|
|
|
|
static char winmodenames[NUMSPECIALMODES][11] = {
|
|
|
|
// W to make sure it's the windowed mode
|
|
|
|
"320x200W",
|
|
|
|
"640x400W",
|
|
|
|
"960x600W",
|
|
|
|
"1280x800W"
|
|
|
|
};
|
|
|
|
vmode_t specialmodes[NUMSPECIALMODES] =
|
|
|
|
{
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
winmodenames[0], // hehe
|
|
|
|
320, 200, //(200.0/320.0)*(320.0/240.0),
|
|
|
|
320, 1, // rowbytes, bytes per pixel
|
|
|
|
1, 2, // windowed (TRUE), numpages
|
|
|
|
NULL,
|
|
|
|
VID_SetWindowedDisplayMode, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
winmodenames[1], // haha
|
|
|
|
640, 400,
|
|
|
|
640, 1, // rowbytes, bytes per pixel
|
|
|
|
1, 2, // windowed (TRUE), numpages
|
|
|
|
NULL,
|
|
|
|
VID_SetWindowedDisplayMode, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
winmodenames[2], // hihi?
|
|
|
|
960, 600,
|
|
|
|
960, 1, // rowbytes, bytes per pixel
|
|
|
|
1, 2, // windowed (TRUE), numpages
|
|
|
|
NULL,
|
|
|
|
VID_SetWindowedDisplayMode, 0
|
|
|
|
},
|
|
|
|
{
|
|
|
|
NULL,
|
|
|
|
winmodenames[3], // hoho!
|
|
|
|
1280, 800,
|
|
|
|
1280, 1, // rowbytes, bytes per pixel
|
|
|
|
1, 2, // windowed (TRUE), numpages
|
|
|
|
NULL,
|
|
|
|
VID_SetWindowedDisplayMode, 0
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
// ------
|
|
|
|
// Protos
|
|
|
|
// ------
|
|
|
|
static void VID_Command_NumModes_f(void);
|
|
|
|
static void VID_Command_ModeInfo_f(void);
|
|
|
|
static void VID_Command_ModeList_f(void);
|
|
|
|
static void VID_Command_Mode_f(void);
|
|
|
|
static INT32 WINAPI VID_SetDirectDrawMode(viddef_t *lvid, vmode_t *currentmode);
|
|
|
|
static vmode_t *VID_GetModePtr(int modenum);
|
|
|
|
static VOID VID_Init(VOID);
|
|
|
|
static BOOL VID_FreeAndAllocVidbuffer(viddef_t *lvid);
|
|
|
|
|
|
|
|
#if 0
|
|
|
|
// Disable Composition in Vista DWM (Desktop Window Manager) ----------------
|
|
|
|
static HMODULE DMdll = NULL;
|
|
|
|
typedef HRESULT (CALLBACK *P_DwmIsCompositionEnabled) (BOOL *pfEnabled);
|
|
|
|
static P_DwmIsCompositionEnabled pfnDwmIsCompositionEnabled = NULL;
|
|
|
|
typedef HRESULT (CALLBACK *P_DwmEnableComposition) (BOOL fEnable);
|
|
|
|
static P_DwmEnableComposition pfnDwmEnableComposition = NULL;
|
|
|
|
static BOOL AeroWasEnabled = FALSE;
|
|
|
|
|
|
|
|
static inline VOID UnloadDM(VOID)
|
|
|
|
{
|
|
|
|
pfnDwmEnableComposition = NULL;
|
|
|
|
pfnDwmIsCompositionEnabled = NULL;
|
|
|
|
if (DMdll) FreeLibrary(DMdll);
|
|
|
|
DMdll = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline BOOL LoadDM(VOID)
|
|
|
|
{
|
|
|
|
if (DMdll)
|
|
|
|
return TRUE;
|
|
|
|
|
|
|
|
DMdll = LoadLibraryA("dwmapi.dll");
|
|
|
|
if (DMdll)
|
|
|
|
I_OutputMsg("dmwapi.dll loaded, Vista's Desktop Window Manager API\n");
|
|
|
|
else
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
pfnDwmIsCompositionEnabled = (P_DwmIsCompositionEnabled)GetProcAddress(DMdll, "DwmIsCompositionEnabled");
|
|
|
|
if (pfnDwmIsCompositionEnabled)
|
|
|
|
I_OutputMsg("Composition Aero API found, DwmIsCompositionEnabled\n");
|
|
|
|
|
|
|
|
pfnDwmEnableComposition = (P_DwmEnableComposition)GetProcAddress(DMdll, "DwmEnableComposition");
|
|
|
|
if (pfnDwmEnableComposition)
|
|
|
|
I_OutputMsg("Composition Aero API found, DwmEnableComposition\n");
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline VOID DisableAero(VOID)
|
|
|
|
{
|
|
|
|
BOOL pfnDwmEnableCompositiond = FALSE;
|
|
|
|
AeroWasEnabled = FALSE;
|
|
|
|
|
|
|
|
if (!LoadDM())
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pfnDwmIsCompositionEnabled && SUCCEEDED(pfnDwmIsCompositionEnabled(&pfnDwmEnableCompositiond)))
|
|
|
|
I_OutputMsg("Got the result of DwmIsCompositionEnabled, %i\n", pfnDwmEnableCompositiond);
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if ((AeroWasEnabled = pfnDwmEnableCompositiond))
|
|
|
|
I_OutputMsg("Disable the Aero rendering\n");
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (pfnDwmEnableComposition && SUCCEEDED(pfnDwmEnableComposition(FALSE)))
|
|
|
|
I_OutputMsg("Aero rendering disabled\n");
|
|
|
|
else
|
|
|
|
I_OutputMsg("We failed to disable the Aero rendering\n");
|
|
|
|
}
|
|
|
|
|
|
|
|
static inline VOID ResetAero(VOID)
|
|
|
|
{
|
|
|
|
if (pfnDwmEnableComposition && AeroWasEnabled)
|
|
|
|
{
|
|
|
|
if (SUCCEEDED(pfnDwmEnableComposition(AeroWasEnabled)))
|
|
|
|
I_OutputMsg("Aero rendering setting restored\n");
|
|
|
|
else
|
|
|
|
I_OutputMsg("We failed to restore Aero rendering\n");
|
|
|
|
}
|
|
|
|
UnloadDM();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// -----------------
|
|
|
|
// I_StartupGraphics
|
|
|
|
// Initialize video mode, setup dynamic screen size variables,
|
|
|
|
// and allocate screens.
|
|
|
|
// -----------------
|
|
|
|
void I_StartupGraphics(void)
|
|
|
|
{
|
|
|
|
if (graphics_started)
|
|
|
|
return;
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
else if (M_CheckParm("-opengl"))
|
|
|
|
rendermode = render_opengl;
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
rendermode = render_soft;
|
|
|
|
|
|
|
|
if (dedicated)
|
|
|
|
rendermode = render_none;
|
|
|
|
else
|
|
|
|
VID_Init();
|
|
|
|
|
|
|
|
// register exit code for graphics
|
|
|
|
I_AddExitFunc(I_ShutdownGraphics);
|
|
|
|
if (!dedicated) graphics_started = true;
|
|
|
|
}
|
|
|
|
|
2020-02-18 00:11:56 +00:00
|
|
|
void VID_StartupOpenGL(void){}
|
2019-09-09 01:25:18 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// ------------------
|
|
|
|
// I_ShutdownGraphics
|
|
|
|
// Close the screen, restore previous video mode.
|
|
|
|
// ------------------
|
|
|
|
void I_ShutdownGraphics(void)
|
|
|
|
{
|
|
|
|
#ifdef HWRENDER
|
|
|
|
const rendermode_t oldrendermode = rendermode;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// This is BAD because it makes the I_Error box screw up!
|
|
|
|
// rendermode = render_none;
|
|
|
|
|
|
|
|
if (!graphics_started)
|
|
|
|
return;
|
|
|
|
|
|
|
|
CONS_Printf("I_ShutdownGraphics: ");
|
|
|
|
|
|
|
|
//FreeConsole();
|
|
|
|
|
|
|
|
//ResetAero();
|
|
|
|
|
|
|
|
// release windowed startup stuff
|
|
|
|
if (hDCMain)
|
|
|
|
{
|
|
|
|
ReleaseDC(hWndMain, hDCMain);
|
|
|
|
hDCMain = NULL;
|
|
|
|
}
|
|
|
|
if (bmiMain)
|
|
|
|
{
|
|
|
|
GlobalFree(bmiMain);
|
|
|
|
bmiMain = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
if (oldrendermode != render_soft)
|
|
|
|
{
|
|
|
|
HWR_Shutdown(); // free stuff from the hardware renderer
|
|
|
|
HWD.pfnShutdown(); // close 3d card display
|
|
|
|
Shutdown3DDriver(); // free the driver DLL
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// free the last video mode screen buffers
|
|
|
|
if (vid.buffer)
|
|
|
|
{
|
|
|
|
GlobalFree(vid.buffer);
|
|
|
|
vid.buffer = NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
if (rendermode == render_soft)
|
|
|
|
#endif
|
|
|
|
CloseDirectDraw();
|
|
|
|
|
|
|
|
graphics_started = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------
|
|
|
|
// I_UpdateNoBlit
|
|
|
|
// --------------
|
|
|
|
void I_UpdateNoBlit(void)
|
|
|
|
{
|
|
|
|
// what is this?
|
|
|
|
}
|
|
|
|
|
|
|
|
// I_SkipFrame
|
|
|
|
//
|
|
|
|
// Returns true if it thinks we can afford to skip this frame
|
|
|
|
// from PrBoom's src/SDL/i_video.c
|
|
|
|
static inline boolean I_SkipFrame(void)
|
|
|
|
{
|
|
|
|
static boolean skip = false;
|
|
|
|
|
|
|
|
if (render_soft != rendermode)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
skip = !skip;
|
|
|
|
switch (gamestate)
|
|
|
|
{
|
|
|
|
case GS_LEVEL:
|
|
|
|
if (!paused)
|
|
|
|
return false;
|
2017-01-28 13:13:03 +00:00
|
|
|
//case GS_TIMEATTACK: -- sorry optimisation but now we have a cool level platter and that being laggardly looks terrible
|
2014-03-15 16:59:03 +00:00
|
|
|
#ifndef CLIENT_LOADINGSCREEN
|
2019-09-09 19:02:13 +00:00
|
|
|
/* FALLTHRU */
|
2014-03-15 16:59:03 +00:00
|
|
|
case GS_WAITINGPLAYERS:
|
|
|
|
#endif
|
|
|
|
return skip; // Skip odd frames
|
|
|
|
default:
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void OnTop_OnChange(void)
|
|
|
|
{
|
|
|
|
const UINT uFlags = SWP_NOACTIVATE|SWP_NOMOVE|SWP_NOSIZE|SWP_NOZORDER;
|
|
|
|
RECT bounds;
|
|
|
|
int x = 0, y = 0, w = 0, h = 0;
|
|
|
|
|
|
|
|
if (!hWndMain || bAppFullScreen || cv_ontop.value == -1)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GetWindowRect(hWndMain, &bounds);
|
|
|
|
AdjustWindowRectEx(&bounds, GetWindowLong(hWndMain, GWL_STYLE), 0, 0);
|
|
|
|
w = bounds.right - (x = bounds.left); h = bounds.bottom - (y = bounds.top);
|
|
|
|
|
|
|
|
if (cv_ontop.value && !paused)
|
|
|
|
SetWindowPos(hWndMain, HWND_TOP , x, y, w, h, uFlags);
|
|
|
|
else
|
|
|
|
SetWindowPos(hWndMain, HWND_NOTOPMOST, x, y, w, h, uFlags);
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------
|
|
|
|
// I_FinishUpdate
|
|
|
|
// --------------
|
|
|
|
void I_FinishUpdate(void)
|
|
|
|
{
|
|
|
|
if (rendermode == render_none)
|
|
|
|
return;
|
|
|
|
|
|
|
|
if (I_SkipFrame())
|
|
|
|
return;
|
|
|
|
|
2017-04-17 00:09:47 +00:00
|
|
|
// draw captions if enabled
|
|
|
|
if (cv_closedcaptioning.value)
|
|
|
|
SCR_ClosedCaptions();
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// display a graph of ticrate
|
|
|
|
if (cv_ticrate.value)
|
|
|
|
SCR_DisplayTicRate();
|
|
|
|
|
2019-11-18 01:22:47 +00:00
|
|
|
if (cv_showping.value && netgame && consoleplayer != serverplayer)
|
|
|
|
SCR_DisplayLocalPing();
|
|
|
|
|
Introducing Marathon Run. (I was going to call it Marathon Mode, but NiGHTS Mode being right next to it on the menu looked terrible.)
Basically a dedicated Record Attack-like experience for speedrunning the game as a continuous chunk rather than ILs. Has several quality of life features.
Benefits include:
* An unambiguous real-time bar across the bottom of the screen, always displaying the current time, ticking up until you reach the ending.
* Disable the console (pausing is still allowed, but the timer will still increment).
* Automatically skip intermissions as if you're holding down the spin button.
* Show centiseconds on HUD automatically, like record attack.
* "Live Event Backups" - a category of run fit for major events like GDQ, where recovery from crashes or chokes makes for better entertainment. Essentially a modified SP savefile, down to using the same basic functions, but has its own filename and tweaked internal layout.
* "spmarathon_start" MainCfg block parameter and "marathonnext" mapheader parameter, allowing for a customised flow (makes this fit for purpose for an eventual SUGOI port).
* Disabling inter-level custom cutscenes by default with a menu option to toggle this (won't show up if the mod doesn't *have* any custom cutscenes), although either way ending cutscenes (vanilla or custom) remain intact since is time is called before them.
* Won't show up if you have a mod that consists of only one level (determined by spmarathon_start's nextlevel; this won't trip if you manually set its marathonnext).
* Unconditional gratitude on the evaluation screen, instead of a negging "Try again..." if you didn't get all the emeralds (which you may not have been aiming for).
* Gorgeous new menu (no new assets required, unless you wanna give it a header later).
Changes which were required for the above but affect other areas of the game include:
* "useBlackRock" MainCFG block parameter, which can be used to disable the presence of the Black Rock or Egg Rock in both the Evaluation screen and the Marathon Run menu (for total conversions with different stories).
* Disabling Continues in NiGHTS mode, to match the most common singleplayer experience post 2.2.4's release (is reverted if useContinues is set to true).
* Hiding the exitmove "powerup" outside of multiplayer. (Okay, this isn't really related, I just saw this bug in action a lot while doing test runs and got annoyed enough to fix it here.)
* The ability to use V_DrawPromptBack (in hardcode only at the moment, but) to draw in terms of pixels rather than rows of text, by providing negative instead of positive inputs).
* A refactoring of redundant game saves smattered across the ending, credits, and evaluation - in addition to saving the game slightly earlier.
* Minor m_menu.c touchups and refactorings here and there.
Built using feedback from the official server's #speedruns channel, among other places.
2020-05-14 22:10:00 +00:00
|
|
|
if (marathonmode)
|
|
|
|
SCR_DisplayMarathonInfo();
|
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
//
|
|
|
|
if (bDIBMode)
|
|
|
|
{
|
|
|
|
// paranoia
|
|
|
|
if (!hDCMain || !bmiMain || !vid.buffer)
|
|
|
|
return;
|
|
|
|
// main game loop, still in a window (-win parm)
|
|
|
|
SetDIBitsToDevice(hDCMain, 0, 0, vid.width, vid.height, 0, 0, 0, vid.height, vid.buffer, bmiMain,
|
|
|
|
DIB_RGB_COLORS);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#ifdef HWRENDER
|
|
|
|
if (rendermode != render_soft)
|
|
|
|
HWD.pfnFinishUpdate(cv_vidwait.value);
|
|
|
|
else
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
// DIRECT DRAW
|
|
|
|
// copy virtual screen to real screen
|
|
|
|
// can fail when not active (alt-tab)
|
|
|
|
if (LockScreen())
|
|
|
|
{
|
|
|
|
/// \todo use directX blit here!!? a blit might use hardware with access
|
|
|
|
/// to main memory on recent hardware, and software blit of directX may be
|
|
|
|
/// optimized for p2 or mmx??
|
|
|
|
if (ScreenHeight > vid.height)
|
|
|
|
{
|
|
|
|
UINT8 *ptr = (UINT8 *)ScreenPtr;
|
|
|
|
size_t half_excess = ScreenPitch*(ScreenHeight-vid.height)/2;
|
|
|
|
memset(ptr, 0x1F, half_excess);
|
|
|
|
ptr += half_excess;
|
|
|
|
VID_BlitLinearScreen(screens[0], ptr, vid.width*vid.bpp, vid.height,
|
|
|
|
vid.width*vid.bpp, ScreenPitch);
|
|
|
|
ptr += vid.height*ScreenPitch;
|
|
|
|
memset(ptr, 0x1F, half_excess);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
VID_BlitLinearScreen(screens[0], (UINT8 *)ScreenPtr, vid.width*vid.bpp, vid.height,
|
|
|
|
vid.width*vid.bpp, ScreenPitch);
|
|
|
|
|
|
|
|
UnlockScreen();
|
|
|
|
|
|
|
|
// swap screens
|
|
|
|
ScreenFlip(cv_vidwait.value);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------
|
|
|
|
// I_UpdateNoVsync
|
|
|
|
// ---------------
|
|
|
|
void I_UpdateNoVsync(void)
|
|
|
|
{
|
|
|
|
int real_vidwait = cv_vidwait.value;
|
|
|
|
cv_vidwait.value = 0;
|
|
|
|
I_FinishUpdate();
|
|
|
|
cv_vidwait.value = real_vidwait;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// This is meant to be called only by CONS_Printf() while game startup
|
|
|
|
//
|
|
|
|
void I_LoadingScreen(LPCSTR msg)
|
|
|
|
{
|
|
|
|
RECT rect;
|
|
|
|
|
|
|
|
// paranoia
|
|
|
|
if (!hDCMain || !bmiMain || !vid.buffer)
|
|
|
|
return;
|
|
|
|
|
|
|
|
GetClientRect(vid.WndParent, &rect);
|
|
|
|
|
|
|
|
SetDIBitsToDevice(hDCMain, 0, 0, vid.width, vid.height, 0, 0, 0, vid.height, vid.buffer, bmiMain, DIB_RGB_COLORS);
|
|
|
|
|
|
|
|
if (msg)
|
|
|
|
{
|
|
|
|
if (rect.bottom - rect.top > 32)
|
|
|
|
rect.top = rect.bottom - 32; // put msg on bottom of window
|
|
|
|
SetBkMode(hDCMain, TRANSPARENT);
|
|
|
|
SetTextColor(hDCMain, RGB(0x00, 0x00, 0x00));
|
|
|
|
DrawTextA(hDCMain, msg, -1, &rect, DT_WORDBREAK|DT_CENTER);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------
|
|
|
|
// I_ReadScreen
|
|
|
|
// ------------
|
|
|
|
void I_ReadScreen(UINT8 *scr)
|
|
|
|
{
|
|
|
|
// DEBUGGING
|
|
|
|
if (rendermode != render_soft)
|
|
|
|
I_Error("I_ReadScreen: called while in non-software mode");
|
|
|
|
VID_BlitLinearScreen(screens[0], scr, vid.width*vid.bpp, vid.height, vid.width*vid.bpp,
|
|
|
|
vid.rowbytes);
|
|
|
|
}
|
|
|
|
|
|
|
|
// ------------
|
|
|
|
// I_SetPalette
|
|
|
|
// ------------
|
|
|
|
void I_SetPalette(RGBA_t *palette)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if (bDIBMode)
|
|
|
|
{
|
|
|
|
// set palette in RGBQUAD format, NOT THE SAME ORDER as PALETTEENTRY, grmpf!
|
|
|
|
RGBQUAD *pColors;
|
|
|
|
pColors = (RGBQUAD *)((LPBYTE)bmiMain + bmiMain->bmiHeader.biSize);
|
|
|
|
ZeroMemory(pColors, sizeof (RGBQUAD)*256);
|
|
|
|
for (i = 0; i < 256; i++, pColors++, palette++)
|
|
|
|
{
|
|
|
|
pColors->rgbRed = palette->s.red;
|
|
|
|
pColors->rgbGreen = palette->s.green;
|
|
|
|
pColors->rgbBlue = palette->s.blue;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
#ifdef HWRENDER
|
|
|
|
if (rendermode == render_soft)
|
|
|
|
#endif
|
|
|
|
{
|
|
|
|
PALETTEENTRY mainpal[256];
|
|
|
|
|
|
|
|
// this clears the 'flag' for each color in palette
|
|
|
|
ZeroMemory(mainpal, sizeof mainpal);
|
|
|
|
|
|
|
|
// set palette in PALETTEENTRY format
|
|
|
|
for (i = 0; i < 256; i++, palette++)
|
|
|
|
{
|
|
|
|
mainpal[i].peRed = palette->s.red;
|
|
|
|
mainpal[i].peGreen = palette->s.green;
|
|
|
|
mainpal[i].peBlue = palette->s.blue;
|
|
|
|
}
|
|
|
|
SetDDPalette(mainpal); // set DirectDraw palette
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// return number of video modes in pvidmodes list
|
|
|
|
// MODES ARE ZERO INDEXED. DO NOT USE (n > nummodes). USE >= INSTEAD.
|
|
|
|
//
|
|
|
|
INT32 VID_NumModes(void)
|
|
|
|
{
|
|
|
|
return numvidmodes;
|
|
|
|
}
|
|
|
|
|
|
|
|
// return a video mode number from the dimensions
|
|
|
|
// returns any available video mode if the mode was not found
|
|
|
|
INT32 VID_GetModeForSize(INT32 w, INT32 h)
|
|
|
|
{
|
|
|
|
vmode_t *pv = pvidmodes;
|
|
|
|
int modenum = 0;
|
|
|
|
|
|
|
|
// Fullscreen resolutions exist
|
|
|
|
if (numvidmodes > NUMSPECIALMODES)
|
|
|
|
{
|
|
|
|
// skip the special modes so that it finds only fullscreen modes
|
|
|
|
for (; pv && modenum < NUMSPECIALMODES; pv = pv->pnext, ++modenum);
|
|
|
|
for (; pv; pv = pv->pnext, ++modenum)
|
|
|
|
if (pv->width == (unsigned)w && pv->height == (unsigned)h)
|
|
|
|
return modenum;
|
|
|
|
|
|
|
|
// Try default video mode first
|
|
|
|
if (w != cv_scr_width.value || h != cv_scr_height.value)
|
|
|
|
return VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value);
|
|
|
|
|
|
|
|
// didn't find, return first fullscreen mode
|
|
|
|
return NUMSPECIALMODES;
|
|
|
|
}
|
|
|
|
|
|
|
|
// rely only on special (windowed) modes
|
|
|
|
for (; pv && modenum < NUMSPECIALMODES; pv = pv->pnext, ++modenum)
|
|
|
|
if (pv->width == (unsigned)w && pv->height == (unsigned)h)
|
|
|
|
return modenum;
|
|
|
|
|
|
|
|
// Try default video mode first
|
|
|
|
if (w != cv_scr_width.value || h != cv_scr_height.value)
|
|
|
|
return VID_GetModeForSize(cv_scr_width.value, cv_scr_height.value);
|
|
|
|
|
|
|
|
// didn't find, return first windowed mode
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Enumerate DirectDraw modes available
|
|
|
|
//
|
|
|
|
static int nummodes = 0;
|
|
|
|
static BOOL GetExtraModesCallback(int width, int height, int bpp)
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
|
|
CONS_Printf("mode %d x %d x %d bpp\n", width, height, bpp);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// skip all unwanted modes
|
|
|
|
if (highcolor && bpp != 15)
|
|
|
|
goto skip;
|
|
|
|
if (!highcolor && bpp != 8)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
if (bpp > 16 || width > MAXVIDWIDTH || height > MAXVIDHEIGHT)
|
|
|
|
goto skip;
|
|
|
|
|
|
|
|
// check if we have space for this mode
|
|
|
|
if (nummodes >= MAX_EXTRA_MODES)
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
|
|
CONS_Printf("mode skipped (too many)\n");
|
|
|
|
#endif
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// store mode info
|
|
|
|
extra_modes[nummodes].pnext = &extra_modes[nummodes+1];
|
|
|
|
memset(names[nummodes], 0, 10);
|
|
|
|
snprintf(names[nummodes], 9, "%dx%d", width, height);
|
|
|
|
|
|
|
|
extra_modes[nummodes].name = names[nummodes];
|
|
|
|
extra_modes[nummodes].width = width;
|
|
|
|
extra_modes[nummodes].height = height;
|
|
|
|
|
|
|
|
// exactly, the current FinishUdpate() gets the rowbytes itself after locking the video buffer
|
|
|
|
// so for now we put anything here
|
|
|
|
extra_modes[nummodes].rowbytes = width;
|
|
|
|
extra_modes[nummodes].windowed = false;
|
|
|
|
extra_modes[nummodes].misc = 0; // unused
|
|
|
|
extra_modes[nummodes].pextradata = NULL;
|
|
|
|
extra_modes[nummodes].setmode = VID_SetDirectDrawMode;
|
|
|
|
|
|
|
|
extra_modes[nummodes].numpages = 3; // triple-buffer (but this value is unused)
|
|
|
|
|
|
|
|
extra_modes[nummodes].bytesperpixel = (bpp+1)>>3;
|
|
|
|
|
|
|
|
nummodes++;
|
|
|
|
skip:
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Collect info about DirectDraw display modes we use
|
|
|
|
//
|
|
|
|
static inline VOID VID_GetExtraModes(VOID)
|
|
|
|
{
|
|
|
|
nummodes = 0;
|
|
|
|
EnumDirectDrawDisplayModes(GetExtraModesCallback);
|
|
|
|
|
|
|
|
// add the extra modes (not 320x200) at the start of the mode list (if there are any)
|
|
|
|
if (nummodes)
|
|
|
|
{
|
|
|
|
extra_modes[nummodes-1].pnext = NULL;
|
|
|
|
pvidmodes = &extra_modes[0];
|
|
|
|
numvidmodes += nummodes;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// ---------------
|
|
|
|
// WindowMode_Init
|
|
|
|
// Add windowed modes to the start of the list,
|
|
|
|
// mode 0 is used for windowed console startup (works on all computers with no DirectX)
|
|
|
|
// ---------------
|
|
|
|
static VOID WindowMode_Init(VOID)
|
|
|
|
{
|
|
|
|
int modenum;
|
|
|
|
|
|
|
|
for (modenum = 0; modenum < NUMSPECIALMODES - 1; modenum++)
|
|
|
|
specialmodes[modenum].pnext = &specialmodes[modenum + 1];
|
|
|
|
specialmodes[NUMSPECIALMODES-1].pnext = pvidmodes;
|
|
|
|
|
|
|
|
pvidmodes = specialmodes;
|
|
|
|
numvidmodes += NUMSPECIALMODES;
|
|
|
|
}
|
|
|
|
|
|
|
|
// *************************************************************************************
|
|
|
|
// VID_Init
|
|
|
|
// Initialize Video modes subsystem
|
|
|
|
// *************************************************************************************
|
|
|
|
static VOID VID_Init(VOID)
|
|
|
|
{
|
|
|
|
#ifdef _DEBUG
|
|
|
|
vmode_t *pv;
|
|
|
|
int iMode;
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// if '-win' is specified on the command line, do not add DirectDraw modes
|
|
|
|
bWinParm = M_CheckParm("-win");
|
|
|
|
|
|
|
|
COM_AddCommand("vid_nummodes", VID_Command_NumModes_f);
|
|
|
|
COM_AddCommand("vid_modeinfo", VID_Command_ModeInfo_f);
|
|
|
|
COM_AddCommand("vid_modelist", VID_Command_ModeList_f);
|
|
|
|
COM_AddCommand("vid_mode", VID_Command_Mode_f);
|
|
|
|
|
|
|
|
CV_RegisterVar(&cv_vidwait);
|
|
|
|
CV_RegisterVar(&cv_stretch);
|
|
|
|
CV_RegisterVar(&cv_ontop);
|
|
|
|
|
|
|
|
// setup the videmodes list,
|
|
|
|
// note that mode 0 must always be VGA mode 0x13
|
|
|
|
pvidmodes = pcurrentmode = NULL;
|
|
|
|
numvidmodes = 0;
|
|
|
|
|
|
|
|
//DisableAero();
|
|
|
|
|
|
|
|
// store the main window handle in viddef struct
|
|
|
|
SetWindowPos(hWndMain, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOACTIVATE|SWP_NOSENDCHANGING|SWP_NOSIZE|SWP_NOMOVE);
|
|
|
|
vid.WndParent = hWndMain;
|
|
|
|
vid.buffer = NULL;
|
|
|
|
|
|
|
|
// we startup in windowed mode using DIB bitmap
|
|
|
|
// we will use DirectDraw when switching fullScreen and entering main game loop
|
|
|
|
bDIBMode = TRUE;
|
|
|
|
bAppFullScreen = FALSE;
|
|
|
|
|
|
|
|
#ifdef HWRENDER
|
|
|
|
// initialize the appropriate display device
|
|
|
|
if (rendermode != render_soft)
|
|
|
|
{
|
|
|
|
const char *drvname = NULL;
|
|
|
|
|
|
|
|
switch (rendermode)
|
|
|
|
{
|
|
|
|
case render_opengl:
|
|
|
|
drvname = "r_opengl.dll";
|
|
|
|
break;
|
|
|
|
default:
|
|
|
|
I_Error("Unknown hardware render mode");
|
|
|
|
}
|
|
|
|
|
|
|
|
// load the DLL
|
|
|
|
if (drvname && Init3DDriver(drvname))
|
|
|
|
{
|
|
|
|
int hwdversion = HWD.pfnGetRenderVersion();
|
|
|
|
if (hwdversion != VERSION)
|
|
|
|
CONS_Alert(CONS_WARNING, M_GetText("This r_opengl version is not supported, use it at your own risk!\n"));
|
|
|
|
|
|
|
|
// perform initialisations
|
|
|
|
HWD.pfnInit(I_Error);
|
|
|
|
// get available display modes for the device
|
|
|
|
HWD.pfnGetModeList(&pvidmodes, &numvidmodes);
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
switch (rendermode)
|
|
|
|
{
|
|
|
|
case render_opengl:
|
|
|
|
I_Error("Error initializing OpenGL");
|
|
|
|
default:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
rendermode = render_soft;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (rendermode == render_soft)
|
|
|
|
#endif
|
|
|
|
if (!bWinParm)
|
|
|
|
{
|
|
|
|
if (!CreateDirectDrawInstance())
|
|
|
|
bWinParm = TRUE;
|
|
|
|
else // get available display modes for the device
|
|
|
|
VID_GetExtraModes();
|
|
|
|
}
|
|
|
|
|
|
|
|
// the game boots in 320x200 standard VGA, but
|
|
|
|
// we need a highcolor mode to run the game in highcolor
|
|
|
|
if (highcolor && !numvidmodes)
|
|
|
|
I_Error("Cannot run in highcolor - No 15bit highcolor DirectX video mode found.");
|
|
|
|
|
|
|
|
// add windowed mode at the start of the list, very important!
|
|
|
|
WindowMode_Init();
|
|
|
|
|
|
|
|
if (!numvidmodes)
|
|
|
|
I_Error("No display modes available.");
|
|
|
|
|
|
|
|
#ifdef _DEBUG // DEBUG
|
|
|
|
for (iMode = 0, pv = pvidmodes; pv; pv = pv->pnext, iMode++)
|
|
|
|
I_OutputMsg("#%02d: %dx%dx%dbpp (desc: '%s')\n", iMode, pv->width, pv->height, pv->bytesperpixel, pv->name);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
// set the startup screen in a window
|
|
|
|
VID_SetMode(0);
|
|
|
|
}
|
|
|
|
|
|
|
|
// --------------------------
|
|
|
|
// VID_SetWindowedDisplayMode
|
|
|
|
// Display the startup 320x200 console screen into a window on the desktop,
|
|
|
|
// switching to fullscreen display only when we will enter the main game loop.
|
|
|
|
// - we can display error message boxes for startup errors
|
|
|
|
// - we can set the last used resolution only once, when entering the main game loop
|
|
|
|
// --------------------------
|
|
|
|
static INT32 WINAPI VID_SetWindowedDisplayMode(viddef_t *lvid, vmode_t *currentmode)
|
|
|
|
{
|
|
|
|
RECT bounds;
|
|
|
|
int x = 0, y = 0, w = 0, h = 0;
|
|
|
|
|
|
|
|
UNREFERENCED_PARAMETER(currentmode);
|
|
|
|
|
|
|
|
I_OutputMsg("VID_SetWindowedDisplayMode()\n");
|
|
|
|
|
|
|
|
|
|
|
|
lvid->u.numpages = 1; // not used
|
|
|
|
lvid->direct = NULL; // DOS remains
|
|
|
|
lvid->buffer = NULL;
|
|
|
|
|
|
|
|
// allocate screens
|
|
|
|
if (!VID_FreeAndAllocVidbuffer(lvid))
|
|
|
|
return -1;
|
|
|
|
|
|
|
|
// lvid->buffer should be NULL here!
|
|
|
|
|
|
|
|
bmiMain = GlobalAlloc(GPTR, sizeof (BITMAPINFO) + (sizeof (RGBQUAD)*256));
|
|
|
|
if (!bmiMain)
|
|
|
|
I_Error("VID_SWDM(): No mem");
|
|
|
|
|
|
|
|
// setup a BITMAPINFO to allow copying our video buffer to the desktop,
|
|
|
|
// with color conversion as needed
|
|
|
|
bmiMain->bmiHeader.biSize = sizeof (BITMAPINFOHEADER);
|
|
|
|
bmiMain->bmiHeader.biWidth = lvid->width;
|
|
|
|
bmiMain->bmiHeader.biHeight= -(lvid->height);
|
|
|
|
bmiMain->bmiHeader.biPlanes = 1;
|
|
|
|
bmiMain->bmiHeader.biBitCount = 8;
|
|
|
|
bmiMain->bmiHeader.biCompression = BI_RGB;
|
|
|
|
|
|
|
|
// center window on the desktop
|
|
|
|
bounds.left = 0;
|
|
|
|
bounds.right = lvid->width;
|
|
|
|
bounds.top = 0;
|
|
|
|
bounds.bottom = lvid->height;
|
|
|
|
AdjustWindowRectEx(&bounds, GetWindowLong(hWndMain, GWL_STYLE), FALSE, GetWindowLong(hWndMain, GWL_EXSTYLE));
|
|
|
|
|
|
|
|
w = bounds.right-bounds.left;
|
|
|
|
h = bounds.bottom-bounds.top;
|
|
|
|
x = (GetSystemMetrics(SM_CXSCREEN)-w)/2;
|
|
|
|
y = (GetSystemMetrics(SM_CYSCREEN)-h)/2;
|
|
|
|
|
|
|
|
if (devparm)
|
|
|
|
MoveWindow(hWndMain, x<<1, y<<1, w, h, TRUE);
|
|
|
|
else
|
|
|
|
MoveWindow(hWndMain, x, y, w, h, TRUE);
|
|
|
|
|
|
|
|
SetFocus(hWndMain);
|
|
|
|
ShowWindow(hWndMain, SW_SHOW);
|
|
|
|
|
|
|
|
hDCMain = GetDC(hWndMain);
|
|
|
|
if (!hDCMain)
|
|
|
|
I_Error("VID_SWDM(): GetDC FAILED");
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Returns a vmode_t from the video modes list, given a video mode number.
|
|
|
|
// ========================================================================
|
|
|
|
vmode_t *VID_GetModePtr(int modenum)
|
|
|
|
{
|
|
|
|
vmode_t *pv;
|
|
|
|
|
|
|
|
pv = pvidmodes;
|
|
|
|
if (!pv)
|
|
|
|
I_Error("VID_error: No video mode found\n");
|
|
|
|
|
|
|
|
while (modenum--)
|
|
|
|
{
|
|
|
|
pv = pv->pnext;
|
|
|
|
if (!pv)
|
|
|
|
I_Error("VID_error: Mode not available\n");
|
|
|
|
}
|
|
|
|
return pv;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// return the name of a video mode
|
|
|
|
//
|
|
|
|
const char *VID_GetModeName(INT32 modenum)
|
|
|
|
{
|
|
|
|
return (VID_GetModePtr(modenum))->name;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Sets a video mode
|
|
|
|
// ========================================================================
|
|
|
|
INT32 VID_SetMode(INT32 modenum)
|
|
|
|
{
|
|
|
|
int vstat;
|
|
|
|
vmode_t *pnewmode;
|
|
|
|
|
|
|
|
if (dedicated)
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
I_OutputMsg("VID_SetMode(%d)\n", modenum);
|
|
|
|
|
|
|
|
// if mode 0 (windowed) we must not be fullscreen already,
|
|
|
|
// if other mode, check it is not mode 0 and existing
|
|
|
|
if (modenum >= numvidmodes)
|
|
|
|
{
|
|
|
|
if (!pcurrentmode)
|
|
|
|
modenum = 0; // revert to the default base vid mode
|
|
|
|
else
|
|
|
|
I_Error("Unknown video mode: %d\n", modenum);
|
|
|
|
}
|
|
|
|
else if (bAppFullScreen && modenum < NUMSPECIALMODES)
|
|
|
|
I_Error("Tried to switch from fullscreen back to windowed mode %d\n", modenum);
|
|
|
|
|
|
|
|
pnewmode = VID_GetModePtr(modenum);
|
|
|
|
|
|
|
|
// dont switch to the same display mode
|
|
|
|
if (pnewmode == pcurrentmode)
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
// initialize the new mode
|
|
|
|
pcurrentmode = pnewmode;
|
|
|
|
|
|
|
|
// initialize vidbuffer size for setmode
|
|
|
|
vid.width = pcurrentmode->width;
|
|
|
|
vid.height = pcurrentmode->height;
|
|
|
|
vid.rowbytes = pcurrentmode->rowbytes;
|
|
|
|
vid.bpp = pcurrentmode->bytesperpixel;
|
|
|
|
if (modenum) // if not 320x200 windowed mode, it's actually a hack
|
|
|
|
{
|
|
|
|
if (rendermode == render_opengl)
|
|
|
|
{
|
|
|
|
// don't accept depth < 16 for OpenGL mode (too much ugly)
|
|
|
|
if (cv_scr_depth.value < 16)
|
|
|
|
CV_SetValue(&cv_scr_depth, 16);
|
|
|
|
vid.bpp = cv_scr_depth.value/8;
|
|
|
|
vid.u.windowed = (bWinParm || !cv_fullscreen.value);
|
|
|
|
pcurrentmode->bytesperpixel = vid.bpp;
|
|
|
|
pcurrentmode->windowed = vid.u.windowed;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
vstat = (*pcurrentmode->setmode)(&vid, pcurrentmode);
|
|
|
|
|
|
|
|
if (vstat == -1)
|
|
|
|
I_Error("Not enough mem for VID_SetMode\n");
|
|
|
|
else if (vstat == -2)
|
|
|
|
I_Error("Couldn't set video mode because it failed the test\n");
|
|
|
|
else if (vstat == -3)
|
|
|
|
I_Error("Couldn't set video mode because it failed the change?\n");
|
|
|
|
else if (!vstat)
|
|
|
|
I_Error("Couldn't set video mode %d (%dx%d %d bits)\n", modenum, vid.width, vid.height, (vid.bpp*8));// hardware could not setup mode
|
|
|
|
else
|
|
|
|
CONS_Printf(M_GetText("Mode changed to %d (%s)\n"), modenum, pcurrentmode->name);
|
|
|
|
|
|
|
|
vid.modenum = modenum;
|
|
|
|
|
|
|
|
// tell game engine to recalc all tables and realloc buffers based on new values
|
|
|
|
vid.recalc = 1;
|
|
|
|
|
|
|
|
if (modenum < NUMSPECIALMODES)
|
|
|
|
{
|
|
|
|
// we are in startup windowed mode
|
|
|
|
bAppFullScreen = FALSE;
|
|
|
|
bDIBMode = TRUE;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// we switch to fullscreen
|
|
|
|
bAppFullScreen = TRUE;
|
|
|
|
bDIBMode = FALSE;
|
|
|
|
#ifdef HWRENDER
|
|
|
|
if (rendermode != render_soft)
|
|
|
|
{
|
|
|
|
// purge all patch graphics stored in software format
|
|
|
|
//Z_FreeTags (PU_PURGELEVEL, PU_PURGELEVEL+100);
|
|
|
|
HWR_Startup();
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
I_RestartSysMouse();
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
2020-02-18 00:11:56 +00:00
|
|
|
void VID_CheckRenderer(void) {}
|
2020-05-06 22:35:54 +00:00
|
|
|
void VID_CheckGLLoaded(rendermode_t oldrender)
|
|
|
|
{
|
|
|
|
(void)oldrender;
|
|
|
|
}
|
2019-09-08 21:27:35 +00:00
|
|
|
|
2014-03-15 16:59:03 +00:00
|
|
|
// ========================================================================
|
|
|
|
// Free the video buffer of the last video mode,
|
|
|
|
// allocate a new buffer for the video mode to set.
|
|
|
|
// ========================================================================
|
|
|
|
static BOOL VID_FreeAndAllocVidbuffer(viddef_t *lvid)
|
|
|
|
{
|
|
|
|
const DWORD vidbuffersize = (lvid->width * lvid->height * lvid->bpp * NUMSCREENS);
|
|
|
|
|
|
|
|
// free allocated buffer for previous video mode
|
|
|
|
if (lvid->buffer)
|
|
|
|
GlobalFree(lvid->buffer);
|
|
|
|
|
|
|
|
// allocate & clear the new screen buffer
|
|
|
|
lvid->buffer = GlobalAlloc(GPTR, vidbuffersize);
|
|
|
|
if (!lvid->buffer)
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
ZeroMemory(lvid->buffer, vidbuffersize);
|
|
|
|
I_OutputMsg("VID_FreeAndAllocVidbuffer done, vidbuffersize: %x\n",(UINT32)vidbuffersize);
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// Set video mode routine for DirectDraw display modes
|
|
|
|
// Out: 1 ok,
|
|
|
|
// 0 hardware could not set mode,
|
|
|
|
// -1 no mem
|
|
|
|
// ========================================================================
|
|
|
|
static INT32 WINAPI VID_SetDirectDrawMode(viddef_t *lvid, vmode_t *currentmode)
|
|
|
|
{
|
|
|
|
UNREFERENCED_PARAMETER(currentmode);
|
|
|
|
|
|
|
|
I_OutputMsg("VID_SetDirectDrawMode...\n");
|
|
|
|
|
|
|
|
|
|
|
|
// DD modes do double-buffer page flipping, but the game engine doesn't need this..
|
|
|
|
lvid->u.numpages = 2;
|
|
|
|
|
|
|
|
// release ddraw surfaces etc..
|
|
|
|
ReleaseChtuff();
|
|
|
|
|
|
|
|
// clean up any old vid buffer lying around, alloc new if needed
|
|
|
|
if (!VID_FreeAndAllocVidbuffer(lvid))
|
|
|
|
return -1; // no mem
|
|
|
|
|
|
|
|
// should clear video mem here
|
|
|
|
|
|
|
|
// note use lvid->bpp instead of 8...will this be needed? will we support other than 256color
|
|
|
|
// in software ?
|
|
|
|
if (!InitDirectDrawe(hWndMain, lvid->width, lvid->height, 8, TRUE)) // TRUE currently always full screen
|
|
|
|
return 0; // could not set mode
|
|
|
|
|
|
|
|
// this is NOT used with DirectDraw modes, game engine should never use this directly
|
|
|
|
// but rather render to memory bitmap buffer
|
|
|
|
lvid->direct = NULL;
|
|
|
|
|
2018-12-16 19:01:28 +00:00
|
|
|
if (!cv_stretch.value && fabsf((float)vid.width/vid.height - ((float)BASEVIDWIDTH/BASEVIDHEIGHT)) > 1.0E-36f)
|
2014-03-15 16:59:03 +00:00
|
|
|
vid.height = (int)(vid.width * ((float)BASEVIDHEIGHT/BASEVIDWIDTH));// Adjust the height to match
|
|
|
|
|
|
|
|
return 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// ========================================================================
|
|
|
|
// VIDEO MODE CONSOLE COMMANDS
|
|
|
|
// ========================================================================
|
|
|
|
|
|
|
|
// vid_nummodes
|
|
|
|
//
|
|
|
|
static void VID_Command_NumModes_f(void)
|
|
|
|
{
|
|
|
|
CONS_Printf(M_GetText("%d video mode(s) available(s)\n"), VID_NumModes());
|
|
|
|
}
|
|
|
|
|
|
|
|
// vid_modeinfo <modenum>
|
|
|
|
//
|
|
|
|
static void VID_Command_ModeInfo_f(void)
|
|
|
|
{
|
|
|
|
vmode_t *pv;
|
|
|
|
int modenum;
|
|
|
|
|
|
|
|
if (COM_Argc() != 2)
|
|
|
|
modenum = vid.modenum; // describe the current mode
|
|
|
|
else
|
|
|
|
modenum = atoi(COM_Argv(1)); // the given mode number
|
|
|
|
|
|
|
|
if (modenum >= VID_NumModes()
|
|
|
|
|| (!bWinParm && modenum < NUMSPECIALMODES)) // don't accept the windowed modes
|
|
|
|
{
|
|
|
|
CONS_Printf(M_GetText("Video mode not present\n"));
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
pv = VID_GetModePtr(modenum);
|
|
|
|
|
|
|
|
CONS_Printf("\x82" "%s\n", VID_GetModeName(modenum));
|
|
|
|
CONS_Printf(M_GetText("width: %d\nheight: %d\n"),
|
|
|
|
pv->width, pv->height);
|
|
|
|
if (rendermode == render_soft)
|
|
|
|
CONS_Printf(M_GetText("bytes per scanline: %d\nbytes per pixel: %d\nnumpages: %d\n"),
|
|
|
|
pv->rowbytes, pv->bytesperpixel, pv->numpages);
|
|
|
|
}
|
|
|
|
|
|
|
|
// vid_modelist
|
|
|
|
//
|
|
|
|
static void VID_Command_ModeList_f(void)
|
|
|
|
{
|
|
|
|
int i, numodes;
|
|
|
|
const char *pinfo;
|
|
|
|
vmode_t *pv;
|
|
|
|
|
|
|
|
numodes = VID_NumModes();
|
|
|
|
|
|
|
|
// hide windowed modes unless using them
|
|
|
|
i = (!bWinParm) ? NUMSPECIALMODES : 0;
|
|
|
|
|
|
|
|
for (; i < numodes; i++)
|
|
|
|
{
|
|
|
|
pv = VID_GetModePtr(i);
|
|
|
|
pinfo = VID_GetModeName(i);
|
|
|
|
|
|
|
|
if (pv->bytesperpixel == 1)
|
|
|
|
CONS_Printf("%d: %s\n", i, pinfo);
|
|
|
|
else
|
|
|
|
CONS_Printf("%d: %s (hicolor)\n", i, pinfo);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// vid_mode <modenum>
|
|
|
|
//
|
|
|
|
static void VID_Command_Mode_f(void)
|
|
|
|
{
|
|
|
|
int modenum;
|
|
|
|
|
|
|
|
if (COM_Argc() != 2)
|
|
|
|
{
|
|
|
|
CONS_Printf(M_GetText("vid_mode <modenum> : set video mode, current video mode %i\n"), vid.modenum);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
modenum = atoi(COM_Argv(1));
|
|
|
|
|
|
|
|
if (modenum >= VID_NumModes()
|
|
|
|
|| (!bWinParm && modenum < NUMSPECIALMODES)) // don't accept the windowed modes
|
|
|
|
CONS_Printf(M_GetText("Video mode not present\n"));
|
|
|
|
else
|
|
|
|
setmodeneeded = modenum + 1; // request vid mode change
|
|
|
|
}
|
|
|
|
#endif
|