From 29db3febb88157ac41036671035a25738a4636c1 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 23 Apr 2020 21:18:40 +0200 Subject: [PATCH] - updated the platform code to be mostly identical with GZDoom --- source/CMakeLists.txt | 4 +- source/blood/src/blood.h | 2 +- source/blood/src/d_menu.cpp | 2 +- source/build/include/baselayer.h | 7 +- source/common/audio/sound/i_sound.cpp | 1 + source/common/audio/sound/i_soundinternal.h | 2 +- source/common/engine/i_interface.cpp | 5 + source/common/engine/i_interface.h | 13 + source/common/engine/i_specialpaths.h | 22 + source/{core => common/engine}/st_start.h | 95 +- source/common/engine/startupinfo.h | 28 + source/common/menu/menustate.h | 10 + source/core/console/c_console.cpp | 4 +- source/core/console/d_event.cpp | 2 +- source/core/gamecontrol.cpp | 123 +- source/core/gamecontrol.h | 23 +- source/core/i_specialpaths.h | 1 + source/core/initfs.cpp | 9 +- source/core/inputstate.cpp | 4 +- source/core/inputstate.h | 2 - source/core/menu/menu.cpp | 40 +- source/core/menu/menu.h | 4 +- source/core/menu/optionmenuitems.h | 2 - source/duke3d/src/d_menu.cpp | 2 +- source/duke3d/src/duke3d.h | 2 +- source/duke3d/src/game.cpp | 2 +- source/duke3d/src/gamestructures.cpp | 4 +- source/exhumed/src/d_menu.cpp | 2 +- source/exhumed/src/exhumed.cpp | 2 +- source/exhumed/src/exhumed.h | 2 +- source/platform/posix/cocoa/i_input.mm | 51 +- source/platform/posix/cocoa/i_main.mm | 8 +- source/platform/posix/cocoa/i_system.mm | 25 +- source/platform/posix/cocoa/i_video.mm | 20 +- source/platform/posix/cocoa/st_console.mm | 23 +- source/platform/posix/cocoa/st_start.mm | 11 +- source/platform/posix/i_system.h | 6 +- source/platform/posix/i_system_posix.cpp | 45 + source/platform/posix/osx/i_specialpaths.mm | 22 + source/platform/posix/osx/iwadpicker_cocoa.mm | 4 +- source/platform/posix/sdl/i_gui.cpp | 2 +- source/platform/posix/sdl/i_input.cpp | 50 +- source/platform/posix/sdl/i_main.cpp | 16 +- source/platform/posix/sdl/i_system.cpp | 51 +- source/platform/posix/sdl/sdlglvideo.cpp | 58 +- source/platform/posix/sdl/st_start.cpp | 2 +- source/platform/posix/unix/gtk_dialogs.cpp | 6 +- source/platform/posix/unix/i_specialpaths.cpp | 21 + source/platform/win32/hardware.cpp | 19 +- source/platform/win32/i_input.cpp | 36 +- source/platform/win32/i_input.h | 2 +- source/platform/win32/i_keyboard.cpp | 3 +- source/platform/win32/i_main.cpp | 114 +- source/platform/win32/i_mouse.cpp | 75 +- source/platform/win32/i_rawps2.cpp | 2 +- source/platform/win32/i_specialpaths.cpp | 33 +- source/platform/win32/i_steam.cpp | 39 + source/platform/win32/i_system.cpp | 115 +- source/platform/win32/i_system.h | 7 +- source/platform/win32/i_xinput.cpp | 13 +- source/platform/win32/st_start.cpp | 307 ++++- source/platform/win32/st_start_util.cpp | 1191 +++++++++++++++++ source/platform/win32/win32basevideo.cpp | 4 +- source/platform/win32/win32glvideo.cpp | 3 +- source/rr/src/d_menu.cpp | 2 +- source/rr/src/duke3d.h | 2 +- source/rr/src/game.cpp | 6 +- source/rr/src/net.cpp | 2 +- source/sw/src/d_menu.cpp | 2 +- source/sw/src/game.h | 2 +- 70 files changed, 2292 insertions(+), 529 deletions(-) create mode 100644 source/common/engine/i_specialpaths.h rename source/{core => common/engine}/st_start.h (81%) create mode 100644 source/common/engine/startupinfo.h create mode 100644 source/common/menu/menustate.h create mode 100644 source/platform/posix/i_system_posix.cpp create mode 100644 source/platform/win32/i_steam.cpp diff --git a/source/CMakeLists.txt b/source/CMakeLists.txt index 2163a08bb..41a357154 100644 --- a/source/CMakeLists.txt +++ b/source/CMakeLists.txt @@ -464,7 +464,8 @@ endif() set( PLAT_POSIX_SOURCES - platform/posix/i_steam.cpp ) + platform/posix/i_steam.cpp + platform/posix/i_system_posix.cpp ) set( PLAT_SDL_SOURCES platform/posix/sdl/crashcatcher.c platform/posix/sdl/hardware.cpp @@ -511,6 +512,7 @@ set( PLAT_WIN32_SOURCES platform/win32/win32basevideo.cpp platform/win32/win32glvideo.cpp platform/win32/win32vulkanvideo.cpp + platform/win32/i_steam.cpp ) diff --git a/source/blood/src/blood.h b/source/blood/src/blood.h index e01449c1f..2c916533c 100644 --- a/source/blood/src/blood.h +++ b/source/blood/src/blood.h @@ -152,7 +152,7 @@ struct GameInterface : ::GameInterface void MenuOpened() override; void MenuClosed() override; bool CanSave() override; - void StartGame(FGameStartup& gs) override; + void StartGame(FNewGameStartup& gs) override; void DrawNativeMenuText(int fontnum, int state, double xpos, double ypos, float fontscale, const char* text, int flags) override; void DrawMenuCaption(const DVector2& origin, const char* text) override; bool SaveGame(FSaveGameNode*) override; diff --git a/source/blood/src/d_menu.cpp b/source/blood/src/d_menu.cpp index 6b0e4657c..1d616a843 100644 --- a/source/blood/src/d_menu.cpp +++ b/source/blood/src/d_menu.cpp @@ -254,7 +254,7 @@ bool GameInterface::CanSave() return (gGameStarted && gPlayer[myconnectindex].pXSprite->health != 0); } -void GameInterface::StartGame(FGameStartup& gs) +void GameInterface::StartGame(FNewGameStartup& gs) { sfxKillAllSounds(); gGameOptions.nDifficulty = gs.Skill; diff --git a/source/build/include/baselayer.h b/source/build/include/baselayer.h index 12fc727a6..8f89f420a 100644 --- a/source/build/include/baselayer.h +++ b/source/build/include/baselayer.h @@ -38,8 +38,7 @@ extern int32_t qsetmode; #define in3dmode() (qsetmode==200) extern int32_t g_logFlushWindow; - -void mouseGrabInput(bool grab); +bool System_WantGuiCapture(); // During playing this tells us whether the game must be paused due to active GUI elememts. void getScreen(uint8_t* imgBuf); @@ -54,7 +53,7 @@ struct GameStats int frags; }; -struct FGameStartup +struct FNewGameStartup { int Episode; int Level; @@ -109,7 +108,7 @@ struct GameInterface virtual void MenuSound(EMenuSounds snd) {} virtual bool CanSave() { return true; } virtual void CustomMenuSelection(int menu, int item) {} - virtual void StartGame(FGameStartup& gs) {} + virtual void StartGame(FNewGameStartup& gs) {} virtual FSavegameInfo GetSaveSig() { return { "", 0, 0}; } virtual bool DrawSpecialScreen(const DVector2 &origin, int tilenum) { return false; } virtual void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool withbg = true) {} diff --git a/source/common/audio/sound/i_sound.cpp b/source/common/audio/sound/i_sound.cpp index 74290c4ab..209f58a47 100644 --- a/source/common/audio/sound/i_sound.cpp +++ b/source/common/audio/sound/i_sound.cpp @@ -486,3 +486,4 @@ SoundHandle SoundRenderer::LoadSoundVoc(uint8_t *sfxdata, int length) if (data) delete[] data; return retval; } + diff --git a/source/common/audio/sound/i_soundinternal.h b/source/common/audio/sound/i_soundinternal.h index 039e308d7..be3486440 100644 --- a/source/common/audio/sound/i_soundinternal.h +++ b/source/common/audio/sound/i_soundinternal.h @@ -144,7 +144,7 @@ struct FISoundChannel class SoundStream; - +void S_SetSoundPaused(int state); #endif diff --git a/source/common/engine/i_interface.cpp b/source/common/engine/i_interface.cpp index b95563279..803317a81 100644 --- a/source/common/engine/i_interface.cpp +++ b/source/common/engine/i_interface.cpp @@ -1,3 +1,8 @@ #include "i_interface.h" +// Some global engine variables taken out of the backend code. SystemCallbacks *sysCallbacks; +double refreshfreq; +FString endoomName; +bool batchrun; + diff --git a/source/common/engine/i_interface.h b/source/common/engine/i_interface.h index 0199f97ea..c862feb20 100644 --- a/source/common/engine/i_interface.h +++ b/source/common/engine/i_interface.h @@ -1,5 +1,6 @@ #pragma once +#include "zstring.h" struct SystemCallbacks { @@ -8,6 +9,18 @@ struct SystemCallbacks bool (*NetGame)(); bool (*WantNativeMouse)(); bool (*CaptureModeInGame)(); + void (*CrashInfo)(char* buffer, size_t bufflen, const char* lfstr); + }; extern SystemCallbacks *sysCallbacks; + +struct WadStuff +{ + FString Path; + FString Name; +}; + + +extern FString endoomName; +extern bool batchrun; diff --git a/source/common/engine/i_specialpaths.h b/source/common/engine/i_specialpaths.h new file mode 100644 index 000000000..4d61bc3d7 --- /dev/null +++ b/source/common/engine/i_specialpaths.h @@ -0,0 +1,22 @@ +#pragma once + +#include "zstring.h" + +#ifdef __unix__ +FString GetUserFile (const char *path); +#endif +FString M_GetAppDataPath(bool create); +FString M_GetCachePath(bool create); +FString M_GetAutoexecPath(); +FString M_GetConfigPath(bool for_reading); +FString M_GetScreenshotsPath(); +FString M_GetSavegamesPath(); +FString M_GetDocumentsPath(); +FString M_GetDemoPath(); + +FString M_GetNormalizedPath(const char* path); + +#ifdef __APPLE__ +FString M_GetMacAppSupportPath(const bool create = true); +void M_GetMacSearchDirectories(FString& user_docs, FString& user_app_support, FString& local_app_support); +#endif // __APPLE__ diff --git a/source/core/st_start.h b/source/common/engine/st_start.h similarity index 81% rename from source/core/st_start.h rename to source/common/engine/st_start.h index ac31e5317..5b8edad4b 100644 --- a/source/core/st_start.h +++ b/source/common/engine/st_start.h @@ -78,28 +78,63 @@ protected: int NetMaxPos, NetCurPos; }; +class FGraphicalStartupScreen : public FBasicStartupScreen +{ +public: + FGraphicalStartupScreen(int max_progress); + ~FGraphicalStartupScreen(); +}; + +class FHereticStartupScreen : public FGraphicalStartupScreen +{ +public: + FHereticStartupScreen(int max_progress, long &hr); + + void Progress(); + void LoadingStatus(const char *message, int colors); + void AppendStatusLine(const char *status); +protected: + void SetWindowSize(); + + int ThermX, ThermY, ThermWidth, ThermHeight; + int HMsgY, SMsgX; +}; + +class FHexenStartupScreen : public FGraphicalStartupScreen +{ +public: + FHexenStartupScreen(int max_progress, long &hr); + ~FHexenStartupScreen(); + + void Progress(); + void NetProgress(int count); + void NetDone(); + void SetWindowSize(); + + // Hexen's notch graphics, converted to chunky pixels. + uint8_t * NotchBits; + uint8_t * NetNotchBits; +}; + +class FStrifeStartupScreen : public FGraphicalStartupScreen +{ +public: + FStrifeStartupScreen(int max_progress, long &hr); + ~FStrifeStartupScreen(); + + void Progress(); +protected: + void DrawStuff(int old_laser, int new_laser); + void SetWindowSize(); + + uint8_t *StartupPics[4+2+1]; +}; + + extern FStartupScreen *StartScreen; - - -//=========================================================================== -// -// DeleteStartupScreen -// -// Makes sure the startup screen has been deleted before quitting. -// -//=========================================================================== - -inline void DeleteStartupScreen() -{ - if (StartScreen != nullptr) - { - delete StartScreen; - StartScreen = nullptr; - } -} - +void DeleteStartupScreen(); extern void ST_Endoom(); // The entire set of functions here uses native Windows types. These are recreations of those types so that the code doesn't need to be changed more than necessary @@ -134,6 +169,9 @@ struct BitmapInfo RgbQuad bmiColors[1]; }; +extern BitmapInfo* StartupBitmap; + + void ST_Util_PlanarToChunky4(uint8_t* dest, const uint8_t* src, int width, int height); void ST_Util_DrawBlock(BitmapInfo* bitmap_info, const uint8_t* src, int x, int y, int bytewidth, int height); void ST_Util_ClearBlock(BitmapInfo* bitmap_info, uint8_t fill, int x, int y, int bytewidth, int height); @@ -148,3 +186,22 @@ void ST_Util_DrawTextScreen(BitmapInfo* bitmap_info, const uint8_t* text_screen, void ST_Util_DrawChar(BitmapInfo* screen, const uint8_t* font, int x, int y, uint8_t charnum, uint8_t attrib); void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font, bool on); + +//=========================================================================== +// +// DeleteStartupScreen +// +// Makes sure the startup screen has been deleted before quitting. +// +//=========================================================================== + +inline void DeleteStartupScreen() +{ + if (StartScreen != nullptr) + { + delete StartScreen; + StartScreen = nullptr; + } +} + + diff --git a/source/common/engine/startupinfo.h b/source/common/engine/startupinfo.h new file mode 100644 index 000000000..9cf9724fd --- /dev/null +++ b/source/common/engine/startupinfo.h @@ -0,0 +1,28 @@ +#pragma once + +#include +#include "zstring.h" + +struct FStartupInfo +{ + FString Name; + uint32_t FgColor; // Foreground color for title banner + uint32_t BkColor; // Background color for title banner + FString Song; + int Type; + int LoadLights = -1; + int LoadBrightmaps = -1; + int modern = -1; + enum + { + DefaultStartup, + DoomStartup, + HereticStartup, + HexenStartup, + StrifeStartup, + }; +}; + + +extern FStartupInfo GameStartupInfo; + diff --git a/source/common/menu/menustate.h b/source/common/menu/menustate.h new file mode 100644 index 000000000..5dfd38609 --- /dev/null +++ b/source/common/menu/menustate.h @@ -0,0 +1,10 @@ +#pragma once + +enum EMenuState : int +{ + MENU_Off, // Menu is closed + MENU_On, // Menu is opened + MENU_WaitKey, // Menu is opened and waiting for a key in the controls menu + MENU_OnNoPause, // Menu is opened but does not pause the game +}; +extern EMenuState menuactive; // Menu overlayed? diff --git a/source/core/console/c_console.cpp b/source/core/console/c_console.cpp index 258d7bf72..71c5452ef 100644 --- a/source/core/console/c_console.cpp +++ b/source/core/console/c_console.cpp @@ -1308,14 +1308,12 @@ void C_ToggleConsole () HistPos = NULL; TabbedLast = false; TabbedList = false; - mouseGrabInput(false); - + } else //if (gamestate != GS_FULLCONSOLE && gamestate != GS_STARTUP) { ConsoleState = c_rising; C_FlushDisplay (); - mouseGrabInput(true); } } diff --git a/source/core/console/d_event.cpp b/source/core/console/d_event.cpp index e6e8f0307..cc926e9b3 100644 --- a/source/core/console/d_event.cpp +++ b/source/core/console/d_event.cpp @@ -133,7 +133,7 @@ void D_PostEvent (const event_t *ev) return; } - if (ev->type == EV_Mouse && GUICapture == 0) + if (ev->type == EV_Mouse && !System_WantGuiCapture()) { inputState.MouseAddToPos(ev->x, -ev->y); return; diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index d787c6d20..c9ff2457e 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -61,12 +61,30 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. #include "gamestate.h" #include "gstrings.h" #include "texturemanager.h" +#include "i_interface.h" +#include "x86.h" +#include "startupinfo.h" + +CVAR(Bool, autoloadlights, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR(Bool, autoloadbrightmaps, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CUSTOM_CVAR(String, language, "auto", CVAR_ARCHIVE | CVAR_NOINITCALL | CVAR_GLOBALCONFIG) { GStrings.UpdateLanguage(self); } +CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) +{ + if (self < 0) + { + self = 0; + } + else if (self > 2) + { + self = 2; + } +} + // The last remains of sdlayer.cpp double g_beforeSwapTime; GameInterface* gi; @@ -85,7 +103,7 @@ gamestate_t gamestate = GS_STARTUP; FILE* hashfile; -FStartupInfo RazeStartupInfo; +FStartupInfo GameStartupInfo; FMemArena dump; // this is for memory blocks than cannot be deallocated without some huge effort. Put them in here so that they do not register on shutdown. void C_CON_SetAliases(); @@ -134,22 +152,73 @@ static StringtableCallbacks stblcb = }; - -//========================================================================== -// -// -// -//========================================================================== - -bool grab_mouse; - -void mouseGrabInput(bool grab) +bool System_WantGuiCapture() { - grab_mouse = grab; - if (grab) GUICapture &= ~1; - else GUICapture |= 1; + bool wantCapt; + + if (menuactive == MENU_Off) + { + wantCapt = ConsoleState == c_down || ConsoleState == c_falling || chatmodeon; + } + else + { + wantCapt = (menuactive == MENU_On || menuactive == MENU_OnNoPause); + } + return wantCapt; } +bool System_WantLeftButton() +{ + return false;// (gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL); +} + +bool System_NetGame() +{ + return false; // fixme later. For now there is no netgame support. +} + +bool System_WantNativeMouse() +{ + return false; +} + +static bool System_CaptureModeInGame() +{ + return true; +} + +//========================================================================== +// +// DoomSpecificInfo +// +// Called by the crash logger to get application-specific information. +// +//========================================================================== + +void System_CrashInfo(char* buffer, size_t bufflen, const char *lfstr) +{ + const char* arg; + char* const buffend = buffer + bufflen - 2; // -2 for CRLF at end + int i; + + buffer += mysnprintf(buffer, buffend - buffer, GAMENAME " version %s (%s)", GetVersionString(), GetGitHash()); + + buffer += snprintf(buffer, buffend - buffer, "%sCommand line:", lfstr); + for (i = 0; i < Args->NumArgs(); ++i) + { + buffer += snprintf(buffer, buffend - buffer, " %s", Args->GetArg(i)); + } + + for (i = 0; (arg = fileSystem.GetResourceFileName(i)) != NULL; ++i) + { + buffer += mysnprintf(buffer, buffend - buffer, "%sFile %d: %s", lfstr, i, arg); + } + buffer += mysnprintf(buffer, buffend - buffer, "%s", lfstr); + *buffer = 0; +} + + + //========================================================================== // // @@ -373,11 +442,11 @@ void CheckFrontend(int flags) { gi = Powerslave::CreateInterface(); } - else if ((flags & GAMEFLAG_FURY) || RazeStartupInfo.modern > 0) + else if ((flags & GAMEFLAG_FURY) || GameStartupInfo.modern > 0) { gi = Duke::CreateInterface(); } - else if (RazeStartupInfo.modern < 0) + else if (GameStartupInfo.modern < 0) { gi = Redneck::CreateInterface(); } @@ -395,6 +464,17 @@ int RunGame(); int GameMain() { int r; + + static SystemCallbacks syscb = + { + System_WantGuiCapture, + System_WantLeftButton, + System_NetGame, + System_WantNativeMouse, + System_CaptureModeInGame, + }; + sysCallbacks = &syscb; + try { r = RunGame(); @@ -576,7 +656,7 @@ static TArray SetupGame() if (groupno == -1) return TArray(); auto& group = groups[groupno]; - if (RazeStartupInfo.Name.IsNotEmpty()) I_SetWindowTitle(RazeStartupInfo.Name); + if (GameStartupInfo.Name.IsNotEmpty()) I_SetWindowTitle(GameStartupInfo.Name); else I_SetWindowTitle(group.FileInfo.name); // Now filter out the data we actually need and delete the rest. @@ -682,7 +762,11 @@ int RunGame() V_InitFontColors(); GStrings.LoadStrings(language); - I_Init(); + CheckCPUID(&CPU); + CalculateCPUSpeed(); + auto ci = DumpCPUInfo(&CPU); + Printf("%s", ci.GetChars()); + V_InitScreenSize(); V_InitScreen(); StartScreen = FStartupScreen::CreateInstance(100); @@ -734,8 +818,6 @@ int RunGame() I_FatalError("app_main: There was a problem initializing the Build engine: %s\n", engineerrstr); } - mouseGrabInput(true); // the intros require the mouse to be grabbed. - auto exec = C_ParseCmdLineParams(nullptr); if (exec) exec->ExecCommands(); @@ -748,7 +830,6 @@ void G_FatalEngineError(void) I_FatalError("There was a problem initializing the engine: %s\n\nThe application will now close.", engineerrstr); } - //========================================================================== // // diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index 71af02387..88f76eed3 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -12,6 +12,7 @@ extern FString currentGame; extern FString LumpFilter; class FArgs; +extern bool GUICapture; extern FMemArena dump; // this is for memory blocks than cannot be deallocated without some huge effort. Put them in here so that they do not register on shutdown. @@ -135,12 +136,6 @@ struct GrpInfo }; -struct WadStuff -{ - FString Path; - FString Name; -}; - struct GrpEntry { FString FileName; @@ -154,28 +149,12 @@ const char* G_DefaultConFile(void); const char* G_ConFile(void); TArray GrpScan(); -void S_SetSoundPaused(int state); void G_FatalEngineError(void); int CalcSmoothRatio(const ClockTicks& totalclk, const ClockTicks& ototalclk, int realgameticspersec); FString G_GetDemoPath(); - -struct FStartupInfo -{ - FString Name; - uint32_t FgColor; // Foreground color for title banner - uint32_t BkColor; // Background color for title banner - int modern; - //FString Song; - //int Type; - //int LoadLights = -1; - //int LoadBrightmaps = -1; -}; - -extern FStartupInfo RazeStartupInfo; - enum { PAUSESFX_MENU = 1, diff --git a/source/core/i_specialpaths.h b/source/core/i_specialpaths.h index 44596165a..4d61bc3d7 100644 --- a/source/core/i_specialpaths.h +++ b/source/core/i_specialpaths.h @@ -6,6 +6,7 @@ FString GetUserFile (const char *path); #endif FString M_GetAppDataPath(bool create); +FString M_GetCachePath(bool create); FString M_GetAutoexecPath(); FString M_GetConfigPath(bool for_reading); FString M_GetScreenshotsPath(); diff --git a/source/core/initfs.cpp b/source/core/initfs.cpp index 0712adda6..0f75128c0 100644 --- a/source/core/initfs.cpp +++ b/source/core/initfs.cpp @@ -46,6 +46,7 @@ #include "v_text.h" #include "findfile.h" #include "palutil.h" +#include "startupinfo.h" #ifndef PATH_MAX #define PATH_MAX 260 @@ -111,20 +112,20 @@ static FString ParseGameInfo(TArray& pwads, const char* fn, const char* else if (!nextKey.CompareNoCase("STARTUPTITLE")) { sc.MustGetString(); - RazeStartupInfo.Name = sc.String; + GameStartupInfo.Name = sc.String; } else if (!nextKey.CompareNoCase("STARTUPCOLORS")) { sc.MustGetString(); - RazeStartupInfo.FgColor = V_GetColor(NULL, sc); + GameStartupInfo.FgColor = V_GetColor(NULL, sc); sc.MustGetStringName(","); sc.MustGetString(); - RazeStartupInfo.BkColor = V_GetColor(NULL, sc); + GameStartupInfo.BkColor = V_GetColor(NULL, sc); } else if (!nextKey.CompareNoCase("MODERN")) { sc.MustGetNumber(); - RazeStartupInfo.modern = sc.Number ? 1 : -1; + GameStartupInfo.modern = sc.Number ? 1 : -1; } else { diff --git a/source/core/inputstate.cpp b/source/core/inputstate.cpp index bc38b34d0..c3ced8ba6 100644 --- a/source/core/inputstate.cpp +++ b/source/core/inputstate.cpp @@ -32,13 +32,12 @@ */ #include "inputstate.h" +#include "i_system.h" #include "v_draw.h" #include "build.h" #include "gamecvars.h" #include "v_video.h" -int GUICapture = false; - //========================================================================== // // @@ -172,6 +171,7 @@ int32_t handleevents(void) D_PostEvent(&ev); } + I_StartFrame(); I_StartTic(); return 0; } diff --git a/source/core/inputstate.h b/source/core/inputstate.h index c64b76d4a..ebf6db5d1 100644 --- a/source/core/inputstate.h +++ b/source/core/inputstate.h @@ -11,8 +11,6 @@ #include "gamecvars.h" typedef uint16_t kb_scancode; -extern int GUICapture; - // This encapsulates the entire game-readable input state which previously was spread out across several files. struct ControlInfo diff --git a/source/core/menu/menu.cpp b/source/core/menu/menu.cpp index 165dc881e..ec8e24fa3 100644 --- a/source/core/menu/menu.cpp +++ b/source/core/menu/menu.cpp @@ -88,7 +88,7 @@ TArray menuClasses(TArray::ENoInit(0 DMenu *DMenu::CurrentMenu; int DMenu::MenuTime; -FGameStartup GameStartupInfo; +FNewGameStartup NewGameStartupInfo; EMenuState menuactive; bool M_DemoNoPlay; FButtonStatus MenuButtons[NUM_MKEYS]; @@ -384,7 +384,6 @@ void M_StartControlPanel (bool makeSound) } C_HideConsole (); // [RH] Make sure console goes bye bye. - mouseGrabInput(false); menuactive = MENU_On; // Pause sound effects before we play the menu switch sound. // That way, it won't be paused. @@ -431,7 +430,7 @@ bool M_SetMenu(FName menu, int param, FName caller) #if 0 // skip the menu and go right into the first level. // For tracking memory leaks that normally require operating the menu to start the game so that they always get the same allocation number. - GameStartupInfo.Episode = GameStartupInfo.Skill = 0; + NewGameStartupInfo.Episode = NewGameStartupInfo.Skill = 0; menu = NAME_Startgame; #endif if (DrawBackground == -1) @@ -446,22 +445,22 @@ bool M_SetMenu(FName menu, int param, FName caller) case NAME_HuntMenu: case NAME_TargetMenu: // sent from the episode menu - GameStartupInfo.Episode = param; - GameStartupInfo.Level = 0; - GameStartupInfo.CustomLevel1 = GameStartupInfo.CustomLevel2 = -1; - GameStartupInfo.Skill = gDefaultSkill; + NewGameStartupInfo.Episode = param; + NewGameStartupInfo.Level = 0; + NewGameStartupInfo.CustomLevel1 = NewGameStartupInfo.CustomLevel2 = -1; + NewGameStartupInfo.Skill = gDefaultSkill; break; case NAME_WeaponMenu: - GameStartupInfo.Skill = param; + NewGameStartupInfo.Skill = param; break; case NAME_CustomGameMenu: - GameStartupInfo.CustomLevel1 = param; - GameStartupInfo.CustomLevel2 = -1; - GameStartupInfo.Episode = 0; // Set start to E1L1 so that even if the script fails to set the starting level it is set to something valid. - GameStartupInfo.Level = 0; - GameStartupInfo.Skill = gDefaultSkill; + NewGameStartupInfo.CustomLevel1 = param; + NewGameStartupInfo.CustomLevel2 = -1; + NewGameStartupInfo.Episode = 0; // Set start to E1L1 so that even if the script fails to set the starting level it is set to something valid. + NewGameStartupInfo.Level = 0; + NewGameStartupInfo.Skill = gDefaultSkill; gi->CustomMenuSelection(param, -1); break; @@ -472,12 +471,12 @@ bool M_SetMenu(FName menu, int param, FName caller) case NAME_CustomSubMenu5: case NAME_CustomSubMenu6: case NAME_CustomSubMenu7: - GameStartupInfo.CustomLevel2 = param; - gi->CustomMenuSelection(GameStartupInfo.CustomLevel1, param); + NewGameStartupInfo.CustomLevel2 = param; + gi->CustomMenuSelection(NewGameStartupInfo.CustomLevel1, param); break; case NAME_Skillmenu: - GameStartupInfo.Skill = param; + NewGameStartupInfo.Skill = param; break; case NAME_EngineCredits: @@ -495,11 +494,11 @@ bool M_SetMenu(FName menu, int param, FName caller) { case NAME_Startgame: M_ClearMenus(); // must be done before starting the level. - if (caller == NAME_Mainmenu || caller == NAME_IngameMenu) GameStartupInfo.Episode = param; - STAT_StartNewGame(gVolumeNames[GameStartupInfo.Episode], GameStartupInfo.Skill); + if (caller == NAME_Mainmenu || caller == NAME_IngameMenu) NewGameStartupInfo.Episode = param; + STAT_StartNewGame(gVolumeNames[NewGameStartupInfo.Episode], NewGameStartupInfo.Skill); inputState.ClearAllInput(); - gi->StartGame(GameStartupInfo); + gi->StartGame(NewGameStartupInfo); return false; case NAME_CustomSubMenu1: @@ -510,7 +509,7 @@ bool M_SetMenu(FName menu, int param, FName caller) case NAME_StartgameConfirm: { // sent from the skill menu for a skill that needs to be confirmed - GameStartupInfo.Skill = param; + NewGameStartupInfo.Skill = param; const char *msg = AllSkills[param].MustConfirmText; if (*msg==0) msg = GStrings("NIGHTMARE"); @@ -968,7 +967,6 @@ void M_ClearMenus (bool final) M_UnpauseSound(); if (!final) { - mouseGrabInput(true); gi->MenuClosed(); } } diff --git a/source/core/menu/menu.h b/source/core/menu/menu.h index 8542bd7c3..549db2e7c 100644 --- a/source/core/menu/menu.h +++ b/source/core/menu/menu.h @@ -151,7 +151,7 @@ enum ENativeFontValues // positive values for color are direct palswap indices. }; -extern FGameStartup GameStartupInfo; +extern FNewGameStartup NewGameStartupInfo; extern EMenuState menuactive; @@ -752,7 +752,7 @@ void M_CreateMenus(); void M_ActivateMenu(DMenu *menu); void M_ClearMenus (bool final = false); void M_ParseMenuDefs(); -void M_StartupSkillMenu(FGameStartup *gs); +void M_StartupSkillMenu(FNewGameStartup *gs); int M_GetDefaultSkill(); void M_StartControlPanel (bool makeSound); bool M_SetMenu(FName menu, int param = -1, FName callingMenu = NAME_None); diff --git a/source/core/menu/optionmenuitems.h b/source/core/menu/optionmenuitems.h index 47523fe09..2870f5341 100644 --- a/source/core/menu/optionmenuitems.h +++ b/source/core/menu/optionmenuitems.h @@ -373,7 +373,6 @@ public: pKey = keyptr; SetMenuMessage(1); menuactive = MENU_WaitKey; // There should be a better way to disable GUI capture... - mouseGrabInput(true); } bool TranslateKeyboardEvents() override @@ -400,7 +399,6 @@ public: { *pKey = ev->data1; menuactive = MENU_On; - mouseGrabInput(false); SetMenuMessage(0); auto p = mParentMenu; Close(); diff --git a/source/duke3d/src/d_menu.cpp b/source/duke3d/src/d_menu.cpp index bdb7e0959..e47f6c26b 100644 --- a/source/duke3d/src/d_menu.cpp +++ b/source/duke3d/src/d_menu.cpp @@ -514,7 +514,7 @@ void GameInterface::CustomMenuSelection(int menu, int item) VM_OnEventWithReturn(EVENT_NEWGAMECUSTOM, -1, myconnectindex, menu); } -void GameInterface::StartGame(FGameStartup& gs) +void GameInterface::StartGame(FNewGameStartup& gs) { int32_t skillsound = PISTOL_BODYHIT; diff --git a/source/duke3d/src/duke3d.h b/source/duke3d/src/duke3d.h index dc734d314..1cc8470a1 100644 --- a/source/duke3d/src/duke3d.h +++ b/source/duke3d/src/duke3d.h @@ -233,7 +233,7 @@ struct GameInterface : ::GameInterface void MenuSound(EMenuSounds snd) override; bool CanSave() override; void CustomMenuSelection(int menu, int item) override; - void StartGame(FGameStartup& gs) override; + void StartGame(FNewGameStartup& gs) override; FSavegameInfo GetSaveSig() override; bool DrawSpecialScreen(const DVector2 &origin, int tilenum) override; void DrawCenteredTextScreen(const DVector2 &origin, const char *text, int position, bool bg) override; diff --git a/source/duke3d/src/game.cpp b/source/duke3d/src/game.cpp index 5557d334a..372e713cd 100644 --- a/source/duke3d/src/game.cpp +++ b/source/duke3d/src/game.cpp @@ -5945,7 +5945,7 @@ MAIN_LOOP_RESTART: localInput = {}; - if (((myplayer.gm & MODE_MENU) != MODE_MENU || ud.recstat == 2 || (g_netServer || ud.multimode > 1)) + if ((!System_WantGuiCapture() || ud.recstat == 2 || (g_netServer || ud.multimode > 1)) && (myplayer.gm & MODE_GAME)) { Net_GetPackets(); diff --git a/source/duke3d/src/gamestructures.cpp b/source/duke3d/src/gamestructures.cpp index 98ff5e3cd..2e6650614 100644 --- a/source/duke3d/src/gamestructures.cpp +++ b/source/duke3d/src/gamestructures.cpp @@ -1633,8 +1633,8 @@ void __fastcall VM_SetUserdef(int const labelNum, int const lParm2, int32_t cons case USERDEFS_M_FFIRE: m_ffire = iSet; break; case USERDEFS_FFIRE: ud.ffire = iSet; break; case USERDEFS_M_PLAYER_SKILL: ud.m_player_skill = iSet; break; - case USERDEFS_M_LEVEL_NUMBER: GameStartupInfo.Level = m_level_number = iSet; break; - case USERDEFS_M_VOLUME_NUMBER: GameStartupInfo.Episode = ud.m_volume_number = iSet; break; + case USERDEFS_M_LEVEL_NUMBER: NewGameStartupInfo.Level = m_level_number = iSet; break; + case USERDEFS_M_VOLUME_NUMBER: NewGameStartupInfo.Episode = ud.m_volume_number = iSet; break; case USERDEFS_MULTIMODE: ud.multimode = iSet; break; case USERDEFS_PLAYER_SKILL: ud.player_skill = iSet; break; case USERDEFS_LEVEL_NUMBER: ud.level_number = iSet; break; diff --git a/source/exhumed/src/d_menu.cpp b/source/exhumed/src/d_menu.cpp index cbd617e6d..5cc49e807 100644 --- a/source/exhumed/src/d_menu.cpp +++ b/source/exhumed/src/d_menu.cpp @@ -187,7 +187,7 @@ void GameInterface::MenuClosed() } -void GameInterface::StartGame(FGameStartup& gs) +void GameInterface::StartGame(FNewGameStartup& gs) { MenuExitCondition = gs.Episode; // Gross hack. The main loop needs to be redone for better handling. } diff --git a/source/exhumed/src/exhumed.cpp b/source/exhumed/src/exhumed.cpp index e8895195b..5d535ab54 100644 --- a/source/exhumed/src/exhumed.cpp +++ b/source/exhumed/src/exhumed.cpp @@ -2332,7 +2332,7 @@ GAMELOOP: { bInMove = kTrue; - if (M_Active() || GUICapture || bPause) + if (System_WantGuiCapture() || bPause) { tclocks = totalclock - 4; buttonMap.ResetButtonStates(); diff --git a/source/exhumed/src/exhumed.h b/source/exhumed/src/exhumed.h index e2372a660..3ad991319 100644 --- a/source/exhumed/src/exhumed.h +++ b/source/exhumed/src/exhumed.h @@ -345,7 +345,7 @@ struct GameInterface : ::GameInterface void MenuOpened() override; void MenuSound(EMenuSounds snd) override; void MenuClosed() override; - void StartGame(FGameStartup& gs) override; + void StartGame(FNewGameStartup& gs) override; FSavegameInfo GetSaveSig() override; void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override; void DrawMenuCaption(const DVector2& origin, const char* text) override; diff --git a/source/platform/posix/cocoa/i_input.mm b/source/platform/posix/cocoa/i_input.mm index 16c18a8f8..8b81f86ad 100644 --- a/source/platform/posix/cocoa/i_input.mm +++ b/source/platform/posix/cocoa/i_input.mm @@ -43,7 +43,9 @@ #include "d_gui.h" #include "dikeys.h" #include "v_video.h" -#include "menu/menu.h" +#include "i_interface.h" +#include "menustate.h" +#include "engineerrors.h" EXTERN_CVAR(Int, m_use_mouse) @@ -54,22 +56,11 @@ CVAR(Bool, m_filter, false, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR(Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) -CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG | CVAR_ARCHIVE) -{ - if (self < 0) - { - self = 0; - } - else if (self > 2) - { - self = 2; - } -} - - extern int paused, chatmodeon; extern constate_e ConsoleState; extern bool ToggleFullscreen; +bool GUICapture; + namespace { @@ -81,21 +72,20 @@ size_t s_skipMouseMoves; // --------------------------------------------------------------------------- -#if 0 void CheckGUICapture() { - bool wantCapture = (MENU_Off == menuactive) - ? (c_down == ConsoleState || c_falling == ConsoleState || chatmodeon) - : (MENU_On == menuactive || MENU_OnNoPause == menuactive); + bool wantCapt = sysCallbacks && sysCallbacks->WantGuiCapture && sysCallbacks->WantGuiCapture(); - if (wantCapture != GUICapture) + if (wantCapt != GUICapture) { - GUICapture = wantCapture; - - ResetButtonStates(); + GUICapture = wantCapt; + if (wantCapt) + { + buttonMap.ResetButtonStates(); + } } + } -#endif void SetCursorPosition(const NSPoint position) { @@ -143,14 +133,9 @@ void CenterCursor() SetCursorPosition(centerPoint); } -bool IsInGame() -{ - return gi->CanSave(); -} - void CheckNativeMouse() { - const bool windowed = !vid_fullscreen; + const bool windowed = (NULL == screen) || !screen->IsFullscreen(); bool wantNative; if (windowed) @@ -165,8 +150,9 @@ void CheckNativeMouse() } else { + bool captureModeInGame = sysCallbacks && sysCallbacks->CaptureModeInGame && sysCallbacks->CaptureModeInGame(); wantNative = (!m_use_mouse || MENU_WaitKey != menuactive) - && (!IsInGame() || GUICapture /*|| paused*/); + && (!captureModeInGame || GUICapture); } } else @@ -176,6 +162,9 @@ void CheckNativeMouse() && (MENU_On == menuactive || MENU_OnNoPause == menuactive); } + if (!wantNative && sysCallbacks && sysCallbacks->WantNativeMouse && sysCallbacks->WantNativeMouse()) + wantNative = true; + I_SetNativeMouse(wantNative); } @@ -189,7 +178,7 @@ void I_GetEvent() void I_StartTic() { - //CheckGUICapture(); + CheckGUICapture(); CheckNativeMouse(); I_ProcessJoysticks(); diff --git a/source/platform/posix/cocoa/i_main.mm b/source/platform/posix/cocoa/i_main.mm index b70534cc7..f33b206fd 100644 --- a/source/platform/posix/cocoa/i_main.mm +++ b/source/platform/posix/cocoa/i_main.mm @@ -45,7 +45,7 @@ #include "version.h" #include "printf.h" #include "s_music.h" -#include "gamecontrol.h" +#include "engineerrors.h" #define ZD_UNUSED(VARIABLE) ((void)(VARIABLE)) @@ -59,7 +59,7 @@ EXTERN_CVAR(Int, vid_defwidth ) EXTERN_CVAR(Int, vid_defheight) EXTERN_CVAR(Bool, vid_vsync ) - +int GameMain(); // --------------------------------------------------------------------------- @@ -103,8 +103,6 @@ void I_DetectOS() if (10 == version.majorVersion) switch (version.minorVersion) { - case 7: name = "Mac OS X Lion"; break; - case 8: name = "OS X Mountain Lion"; break; case 9: name = "OS X Mavericks"; break; case 10: name = "OS X Yosemite"; break; case 11: name = "OS X El Capitan"; break; @@ -139,8 +137,6 @@ void I_DetectOS() FArgs* Args; // command line arguments -double refreshfreq; -bool batchrun; namespace { diff --git a/source/platform/posix/cocoa/i_system.mm b/source/platform/posix/cocoa/i_system.mm index 3bbfa70ff..627c82901 100644 --- a/source/platform/posix/cocoa/i_system.mm +++ b/source/platform/posix/cocoa/i_system.mm @@ -36,18 +36,14 @@ #include #include -#include "gameconfigfile.h" -#include "i_sound.h" #include "i_system.h" #include "st_console.h" #include "v_text.h" -#include "cmdlib.h" -#include "printf.h" double PerfToSec, PerfToMillisec; -static void CalculateCPUSpeed() +void CalculateCPUSpeed() { long long frequency; size_t size = sizeof frequency; @@ -64,10 +60,6 @@ static void CalculateCPUSpeed() } } -void I_Init(void) -{ - CalculateCPUSpeed(); -} void I_SetIWADInfo() { @@ -147,13 +139,6 @@ int I_PickIWad(WadStuff* const wads, const int numwads, const bool showwin, cons } -bool I_WriteIniFailed() -{ - printf("The config file %s could not be saved:\n%s\n", GameConfig->GetPathName(), strerror(errno)); - return false; // return true to retry -} - - void I_PutInClipboard(const char* const string) { NSPasteboard* const pasteBoard = [NSPasteboard generalPasteboard]; @@ -185,11 +170,3 @@ unsigned int I_MakeRNGSeed() { return static_cast(arc4random()); } - - -TArray I_GetGogPaths() -{ - // GOG's Doom games are Windows only at the moment - return TArray(); -} - diff --git a/source/platform/posix/cocoa/i_video.mm b/source/platform/posix/cocoa/i_video.mm index 1cc73a343..666f3235d 100644 --- a/source/platform/posix/cocoa/i_video.mm +++ b/source/platform/posix/cocoa/i_video.mm @@ -31,7 +31,7 @@ ** */ -#include "gl_load/gl_load.h" +#include "gl_load.h" #ifdef HAVE_VULKAN #define VK_USE_PLATFORM_MACOS_MVK @@ -54,8 +54,12 @@ #include "printf.h" #include "gl/system/gl_framebuffer.h" -//#include "vulkan/system/vk_framebuffer.h" -//#include "rendering/polyrenderer/backend/poly_framebuffer.h" +#ifdef HAVE_VULKAN +#include "vulkan/system/vk_framebuffer.h" +#endif +#ifdef HAVE_SOFTPOLY +#include "rendering/polyrenderer/backend/poly_framebuffer.h" +#endif extern bool ToggleFullscreen; @@ -429,7 +433,7 @@ public: try { m_vulkanDevice = new VulkanDevice(); - fb = new VulkanFrameBuffer(nullptr, fullscreen, m_vulkanDevice); + fb = new VulkanFrameBuffer(nullptr, vid_fullscreen, m_vulkanDevice); } catch (std::exception const&) { @@ -441,7 +445,7 @@ public: else #endif -#if 0 +#ifdef HAVE_SOFTPOLY if (vid_preferbackend == 2) { SetupOpenGLView(ms_window, OpenGLProfile::Legacy); @@ -642,7 +646,7 @@ void SystemBaseFrameBuffer::SetMode(const bool fullscreen, const bool hiDPI) else { assert(m_window.screen != nil); - assert(m_window.contentView.layer != nil); + assert([m_window.contentView layer] != nil); [m_window.contentView layer].contentsScale = hiDPI ? m_window.screen.backingScaleFactor : 1.0; } @@ -808,11 +812,11 @@ bool I_SetCursor(FTexture *cursorpic) NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init]; NSCursor* cursor = nil; - if (NULL != cursorpic) + if (NULL != cursorpic && cursorpic->isValid()) { // Create bitmap image representation - auto sbuffer = cursorpic->CreateTexBuffer(0); + auto sbuffer = cursorpic->GetTexture()->CreateTexBuffer(0); const NSInteger imageWidth = sbuffer.mWidth; const NSInteger imageHeight = sbuffer.mHeight; diff --git a/source/platform/posix/cocoa/st_console.mm b/source/platform/posix/cocoa/st_console.mm index 89e5a1470..b4c0878c8 100644 --- a/source/platform/posix/cocoa/st_console.mm +++ b/source/platform/posix/cocoa/st_console.mm @@ -32,7 +32,7 @@ */ #include "i_common.h" - +#include "startupinfo.h" #include "st_console.h" #include "v_text.h" #include "version.h" @@ -48,11 +48,16 @@ static NSColor* RGB(const uint8_t red, const uint8_t green, const uint8_t blue) alpha:1.0f]; } -static NSColor* RGB(PalEntry color) +static NSColor* RGB(const PalEntry& color) { return RGB(color.r, color.g, color.b); } +static NSColor* RGB(const uint32_t color) +{ + return RGB(PalEntry(color)); +} + static const CGFloat PROGRESS_BAR_HEIGHT = 18.0f; static const CGFloat NET_VIEW_HEIGHT = 88.0f; @@ -331,29 +336,27 @@ void FConsoleWindow::SetTitleText() textViewFrame.size.width, TITLE_TEXT_HEIGHT); -#if 0 // Temporary solution for the same foreground and background colors // It's used in graphical startup screen, with Hexen style in particular // Native OS X backend doesn't implement this yet - if (RazeStartupInfo.FgColor == RazeStartupInfo.BkColor) + if (GameStartupInfo.FgColor == GameStartupInfo.BkColor) { - RazeStartupInfo.FgColor = ~RazeStartupInfo.FgColor; + GameStartupInfo.FgColor = ~GameStartupInfo.FgColor; } NSTextField* titleText = [[NSTextField alloc] initWithFrame:titleTextRect]; - [titleText setStringValue:[NSString stringWithCString:RazeStartupInfo.Name + [titleText setStringValue:[NSString stringWithCString:GameStartupInfo.Name.GetChars() encoding:NSISOLatin1StringEncoding]]; [titleText setAlignment:NSCenterTextAlignment]; - [titleText setTextColor:RGB(RazeStartupInfo.FgColor)]; - [titleText setBackgroundColor:RGB(RazeStartupInfo.BkColor)]; + [titleText setTextColor:RGB(GameStartupInfo.FgColor)]; + [titleText setBackgroundColor:RGB(GameStartupInfo.BkColor)]; [titleText setFont:[NSFont fontWithName:@"Trebuchet MS Bold" size:18.0f]]; [titleText setAutoresizingMask:NSViewWidthSizable | NSViewMinYMargin]; [titleText setSelectable:NO]; [titleText setBordered:NO]; - [[m_window contentView] addSubview:titleText]; - #endif + [[m_window contentView] addSubview:titleText]; } void FConsoleWindow::SetProgressBar(const bool visible) diff --git a/source/platform/posix/cocoa/st_start.mm b/source/platform/posix/cocoa/st_start.mm index 89acced53..044c36986 100644 --- a/source/platform/posix/cocoa/st_start.mm +++ b/source/platform/posix/cocoa/st_start.mm @@ -39,6 +39,7 @@ #include "st_console.h" #include "st_start.h" #include "printf.h" +#include "engineerrors.h" FStartupScreen *StartScreen; @@ -64,7 +65,7 @@ FBasicStartupScreen::FBasicStartupScreen(int maxProgress, bool showBar) : FStartupScreen(maxProgress) { FConsoleWindow& consoleWindow = FConsoleWindow::GetInstance(); - consoleWindow.SetProgressBar(false); + consoleWindow.SetProgressBar(true); #if 0 // Testing code, please do not remove @@ -164,3 +165,11 @@ FStartupScreen *FStartupScreen::CreateInstance(const int maxProgress) return new FBasicStartupScreen(maxProgress, true); } + +// --------------------------------------------------------------------------- + + +void ST_Endoom() +{ + throw CExitEvent(0); +} diff --git a/source/platform/posix/i_system.h b/source/platform/posix/i_system.h index ad8fa8806..9c84ee28c 100644 --- a/source/platform/posix/i_system.h +++ b/source/platform/posix/i_system.h @@ -20,9 +20,7 @@ struct WadStuff; #define SHARE_DIR "/usr/local/share/" #endif - -// Called by DoomMain. -void I_Init (void); +void CalculateCPUSpeed(void); // Return a seed value for the RNG. unsigned int I_MakeRNGSeed(); @@ -43,8 +41,6 @@ void I_StartTic (void); // for normal input. ticcmd_t *I_BaseTiccmd (void); -void I_Tactile (int on, int off, int total); - // Print a console string void I_PrintStr (const char *str); diff --git a/source/platform/posix/i_system_posix.cpp b/source/platform/posix/i_system_posix.cpp new file mode 100644 index 000000000..cef139be4 --- /dev/null +++ b/source/platform/posix/i_system_posix.cpp @@ -0,0 +1,45 @@ +//----------------------------------------------------------------------------- +// +// Copyright 1993-1996 id Software +// Copyright 1999-2016 Randy Heit +// +// 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 3 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, see http://www.gnu.org/licenses/ +// +//----------------------------------------------------------------------------- +// + +#include + +#ifdef __APPLE__ +#include +#endif // __APPLE__ + +#include "cmdlib.h" +#include "d_protocol.h" +#include "i_system.h" +#include "gameconfigfile.h" +#include "x86.h" + + +bool I_WriteIniFailed() +{ + printf("The config file %s could not be saved:\n%s\n", GameConfig->GetPathName(), strerror(errno)); + return false; // return true to retry +} + +TArray I_GetGogPaths() +{ + // GOG's Doom games are Windows only at the moment + return TArray(); +} diff --git a/source/platform/posix/osx/i_specialpaths.mm b/source/platform/posix/osx/i_specialpaths.mm index 913aa215b..ff435b769 100644 --- a/source/platform/posix/osx/i_specialpaths.mm +++ b/source/platform/posix/osx/i_specialpaths.mm @@ -109,6 +109,28 @@ FString M_GetAppDataPath(bool create) return path; } +//=========================================================================== +// +// M_GetCachePath macOS +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath(bool create) +{ + FString path = M_GetMacAppSupportPath(create); + + if (path.IsEmpty()) + { + path = progdir; + } + + path += "/zdoom/cache"; + if (create) CreatePath(path); + return path; +} + //=========================================================================== // // M_GetAutoexecPath macOS diff --git a/source/platform/posix/osx/iwadpicker_cocoa.mm b/source/platform/posix/osx/iwadpicker_cocoa.mm index 0ef86f2e1..8670ec2bd 100644 --- a/source/platform/posix/osx/iwadpicker_cocoa.mm +++ b/source/platform/posix/osx/iwadpicker_cocoa.mm @@ -38,8 +38,8 @@ #include "c_cvars.h" #include "m_argv.h" #include "gameconfigfile.h" -#include "printf.h" -#include "gamecontrol.h" +#include "engineerrors.h" +#include "i_interface.h" #include #include diff --git a/source/platform/posix/sdl/i_gui.cpp b/source/platform/posix/sdl/i_gui.cpp index cd3ffb3b8..d06732624 100644 --- a/source/platform/posix/sdl/i_gui.cpp +++ b/source/platform/posix/sdl/i_gui.cpp @@ -43,7 +43,7 @@ bool I_SetCursor(FGameTexture *cursorpic) static SDL_Cursor *cursor; static SDL_Surface *cursorSurface; - if (cursorpic != NULL) + if (cursorpic != NULL && cursorpic->isValid()) { auto src = cursorpic->GetTexture()->GetBgraBitmap(nullptr); // Must be no larger than 32x32. diff --git a/source/platform/posix/sdl/i_input.cpp b/source/platform/posix/sdl/i_input.cpp index ac64d7b2d..164b0b228 100644 --- a/source/platform/posix/sdl/i_input.cpp +++ b/source/platform/posix/sdl/i_input.cpp @@ -36,15 +36,21 @@ #include "d_event.h" #include "d_gui.h" +#include "c_buttons.h" #include "c_console.h" #include "c_dispatch.h" #include "dikeys.h" #include "utf8.h" #include "keydef.h" -#include "menu/menu.h" +#include "i_interface.h" +#include "engineerrors.h" +#include "i_interface.h" + +static void I_CheckGUICapture (); static void I_CheckNativeMouse (); +bool GUICapture; static bool NativeMouse = true; CVAR (Bool, use_mouse, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -159,6 +165,20 @@ static TMap InitKeyScanMap () } static const TMap KeyScanToDIK(InitKeyScanMap()); +static void I_CheckGUICapture () +{ + bool wantCapt = sysCallbacks && sysCallbacks->WantGuiCapture && sysCallbacks->WantGuiCapture(); + + if (wantCapt != GUICapture) + { + GUICapture = wantCapt; + if (wantCapt) + { + buttonMap.ResetButtonStates(); + } + } +} + void I_SetMouseCapture() { // Clear out any mouse movement. @@ -216,30 +236,15 @@ static void MouseRead () } } -CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) -{ - if (self < 0) self = 0; - else if (self > 2) self = 2; -} - -static bool inGame() -{ - if (mouse_capturemode == 2) - { - return true; - } - else - { - return gi->CanSave(); - } -} - static void I_CheckNativeMouse () { bool focus = SDL_GetKeyboardFocus() != NULL; + + bool captureModeInGame = sysCallbacks && sysCallbacks->CaptureModeInGame && sysCallbacks->CaptureModeInGame(); + bool wantNative = !focus || (!use_mouse || GUICapture || !captureModeInGame); - // TODO: We want this to check for demo playback, as well. And paused state - bool wantNative = !focus || (!use_mouse || GUICapture || !inGame()); + if (!wantNative && sysCallbacks && sysCallbacks->WantNativeMouse && sysCallbacks->WantNativeMouse()) + wantNative = true; if (wantNative != NativeMouse) { @@ -381,7 +386,7 @@ void MessagePump (const SDL_Event &sev) if (sev.wheel.y != 0) event.data1 = sev.wheel.y > 0 ? KEY_MWHEELUP : KEY_MWHEELDOWN; - else + else event.data1 = sev.wheel.x > 0 ? KEY_MWHEELRIGHT : KEY_MWHEELLEFT; D_PostEvent (&event); @@ -519,6 +524,7 @@ void I_GetEvent () void I_StartTic () { + I_CheckGUICapture (); I_CheckNativeMouse (); I_GetEvent (); } diff --git a/source/platform/posix/sdl/i_main.cpp b/source/platform/posix/sdl/i_main.cpp index 800171960..fe52d53af 100644 --- a/source/platform/posix/sdl/i_main.cpp +++ b/source/platform/posix/sdl/i_main.cpp @@ -41,12 +41,14 @@ #include #include +#include "engineerrors.h" #include "m_argv.h" #include "c_console.h" #include "version.h" #include "cmdlib.h" +#include "engineerrors.h" #include "i_system.h" -#include "core/gamecontrol.h" +#include "i_interface.h" // MACROS ------------------------------------------------------------------ @@ -66,6 +68,7 @@ void Linux_I_FatalError(const char* errortext); #endif // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- +int GameMain(); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- @@ -82,6 +85,13 @@ FArgs *Args; // CODE -------------------------------------------------------------------- + +static int GetCrashInfo (char *buffer, char *end) +{ + if (sysCallbacks && sysCallbacks->CrashInfo) sysCallbacks->CrashInfo(buffer, end - buffer, "\n"); + return strlen(buffer); +} + void I_DetectOS() { // The POSIX version never implemented this. @@ -93,10 +103,8 @@ int main (int argc, char **argv) { #if !defined (__APPLE__) { -#if 0 // TODO: Crash handling int s[4] = { SIGSEGV, SIGILL, SIGFPE, SIGBUS }; - cc_install_handlers(argc, argv, 4, s, GAMENAMELOWERCASE "-crash.log", DoomSpecificInfo); -#endif + cc_install_handlers(argc, argv, 4, s, GAMENAMELOWERCASE "-crash.log", GetCrashInfo); } #endif // !__APPLE__ diff --git a/source/platform/posix/sdl/i_system.cpp b/source/platform/posix/sdl/i_system.cpp index 746ee5ded..43b8c8664 100644 --- a/source/platform/posix/sdl/i_system.cpp +++ b/source/platform/posix/sdl/i_system.cpp @@ -33,8 +33,6 @@ ** */ -#include "i_system.h" - #include #include #include @@ -46,23 +44,17 @@ #include #include #include +#include #include +#include "x86.h" #include "version.h" #include "cmdlib.h" #include "m_argv.h" #include "i_sound.h" +#include "i_interface.h" -#include "c_dispatch.h" -#include "gamecontrol.h" -#include "gameconfigfile.h" - -extern "C" -{ - double SecondsPerCycle = 1e-8; - double CyclesPerSecond = 1e8; -} #ifndef NO_GTK bool I_GtkAvailable (); @@ -74,30 +66,13 @@ int I_PickIWad_Cocoa (WadStuff *wads, int numwads, bool showwin, int defaultiwad double PerfToSec, PerfToMillisec; -void I_BeginRead(void) +void I_SetIWADInfo() { } -void I_EndRead(void) -{ -} - - -// -// I_Init -// -void I_Init (void) -{ -#if 0 // do we need this? - CheckCPUID (&CPU); - DumpCPUInfo (&CPU); -#endif -} - // // I_Error // -extern FILE *Logfile; #ifdef __APPLE__ void Mac_I_FatalError(const char* errortext); @@ -146,11 +121,9 @@ void I_ShowFatalError(const char *message) #else // ??? #endif - } - -void I_SetIWADInfo () +void CalculateCPUSpeed() { } @@ -273,13 +246,6 @@ int I_PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) return i-1; } -bool I_WriteIniFailed () -{ - printf ("The config file %s could not be saved:\n%s\n", GameConfig->GetPathName(), strerror(errno)); - return false; - // return true to retry -} - void I_PutInClipboard (const char *str) { SDL_SetClipboardText(str); @@ -317,10 +283,3 @@ unsigned int I_MakeRNGSeed() } return seed; } - -TArray I_GetGogPaths() -{ - // GOG's Doom games are Windows only at the moment - return TArray(); -} - diff --git a/source/platform/posix/sdl/sdlglvideo.cpp b/source/platform/posix/sdl/sdlglvideo.cpp index 6be854c96..66edd075e 100644 --- a/source/platform/posix/sdl/sdlglvideo.cpp +++ b/source/platform/posix/sdl/sdlglvideo.cpp @@ -31,8 +31,6 @@ ** */ -// TODO: Softpoly is temporarily #if 0'd out in 5 places. - // HEADER FILES ------------------------------------------------------------ #include "i_module.h" @@ -44,26 +42,31 @@ #include "c_console.h" #include "c_dispatch.h" #include "printf.h" -#include "gamecontrol.h" #include "hardware.h" #include "gl_sysfb.h" -#include "gl_load/gl_system.h" +#include "gl_system.h" #include "gl/renderer/gl_renderer.h" #include "gl/system/gl_framebuffer.h" -#include "glbackend/gl_shader.h" #ifdef HAVE_VULKAN #include "rendering/vulkan/system/vk_framebuffer.h" #endif -#if 0 // softpoly +#ifdef HAVE_SOFTPOLY #include "rendering/polyrenderer/backend/poly_framebuffer.h" #endif // MACROS ------------------------------------------------------------------ +// Requires SDL 2.0.6 or newer +//#define SDL2_STATIC_LIBRARY + +#if defined SDL2_STATIC_LIBRARY && defined HAVE_VULKAN +#include +#endif // SDL2_STATIC_LIBRARY && HAVE_VULKAN + // TYPES ------------------------------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -71,7 +74,7 @@ // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- // EXTERNAL DATA DECLARATIONS ---------------------------------------------- - +extern double refreshfreq; extern IVideo *Video; EXTERN_CVAR (Int, vid_adapter) @@ -111,17 +114,24 @@ CCMD(vid_list_sdl_render_drivers) } } -double refreshfreq; - // PRIVATE DATA DEFINITIONS ------------------------------------------------ namespace Priv { +#ifdef SDL2_STATIC_LIBRARY + +#define SDL2_OPTIONAL_FUNCTION(RESULT, NAME, ...) \ + RESULT(*NAME)(__VA_ARGS__) = SDL_ ## NAME + +#else // !SDL2_STATIC_LIBRARY + FModule library("SDL2"); #define SDL2_OPTIONAL_FUNCTION(RESULT, NAME, ...) \ static TOptProc NAME("SDL_" #NAME) +#endif // SDL2_STATIC_LIBRARY + SDL2_OPTIONAL_FUNCTION(int, GetWindowBordersSize, SDL_Window *window, int *top, int *left, int *bottom, int *right); #ifdef HAVE_VULKAN SDL2_OPTIONAL_FUNCTION(void, Vulkan_GetDrawableSize, SDL_Window *window, int *width, int *height); @@ -249,7 +259,7 @@ bool I_CreateVulkanSurface(VkInstance instance, VkSurfaceKHR *surface) } #endif -#if 0 // softpoly stuff +#ifdef HAVE_SOFTPOLY namespace { SDL_Renderer* polyrendertarget = nullptr; @@ -409,16 +419,20 @@ SDLVideo::SDLVideo () return; } +#ifndef SDL2_STATIC_LIBRARY // Load optional SDL functions if (!Priv::library.IsLoaded()) { Priv::library.Load({ "libSDL2-2.0.so.0", "libSDL2-2.0.so", "libSDL2.so" }); } +#endif // !SDL2_STATIC_LIBRARY +#ifdef HAVE_SOFTPOLY + Priv::softpolyEnabled = vid_preferbackend == 2; +#endif #ifdef HAVE_VULKAN Priv::vulkanEnabled = vid_preferbackend == 1 && Priv::Vulkan_GetDrawableSize && Priv::Vulkan_GetInstanceExtensions && Priv::Vulkan_CreateSurface; - Priv::softpolyEnabled = vid_preferbackend == 2; if (Priv::vulkanEnabled) { @@ -429,7 +443,9 @@ SDLVideo::SDLVideo () Priv::vulkanEnabled = false; } } - else if (Priv::softpolyEnabled) +#endif +#ifdef HAVE_SOFTPOLY + if (Priv::softpolyEnabled) { Priv::CreateWindow(SDL_WINDOW_HIDDEN); } @@ -482,7 +498,7 @@ DFrameBuffer *SDLVideo::CreateFrameBuffer () } #endif -#if 0 // softpoly is not yet implemented +#ifdef HAVE_SOFTPOLY if (Priv::softpolyEnabled) { fb = new PolyFrameBuffer(nullptr, vid_fullscreen); @@ -505,12 +521,12 @@ IVideo *gl_CreateVideo() // FrameBuffer Implementation ----------------------------------------------- -SystemBaseFrameBuffer::SystemBaseFrameBuffer (void *, bool vid_fullscreen) +SystemBaseFrameBuffer::SystemBaseFrameBuffer (void *, bool fullscreen) : DFrameBuffer (vid_defwidth, vid_defheight) { if (Priv::window != nullptr) { - SDL_SetWindowFullscreen(Priv::window, vid_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); + SDL_SetWindowFullscreen(Priv::window, fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0); SDL_ShowWindow(Priv::window); } } @@ -519,7 +535,7 @@ int SystemBaseFrameBuffer::GetClientWidth() { int width = 0; -#if 0 // softpoly +#ifdef HAVE_SOFTPOLY if (Priv::softpolyEnabled) { if (polyrendertarget) @@ -542,7 +558,7 @@ int SystemBaseFrameBuffer::GetClientHeight() { int height = 0; -#if 0 // softpoly +#ifdef HAVE_SOFTPOLY if (Priv::softpolyEnabled) { if (polyrendertarget) @@ -593,7 +609,7 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h) } win_w = w; win_h = h; - if ( vid_fullscreen ) + if (vid_fullscreen) { vid_fullscreen = false; } @@ -611,8 +627,8 @@ void SystemBaseFrameBuffer::SetWindowSize(int w, int h) } -SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool vid_fullscreen) -: SystemBaseFrameBuffer(hMonitor, vid_fullscreen) +SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool fullscreen) +: SystemBaseFrameBuffer(hMonitor, fullscreen) { // NOTE: Core profiles were added with GL 3.2, so there's no sense trying // to set core 3.1 or 3.0. We could try a forward-compatible context @@ -647,7 +663,7 @@ SystemGLFrameBuffer::SystemGLFrameBuffer(void *hMonitor, bool vid_fullscreen) for ( ; glvers[glveridx][0] > 0; ++glveridx) { Priv::SetupPixelFormat(0, glvers[glveridx]); - Priv::CreateWindow(SDL_WINDOW_OPENGL | (vid_fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); + Priv::CreateWindow(SDL_WINDOW_OPENGL | (fullscreen ? SDL_WINDOW_FULLSCREEN_DESKTOP : 0)); if (Priv::window == nullptr) { diff --git a/source/platform/posix/sdl/st_start.cpp b/source/platform/posix/sdl/st_start.cpp index 05893c078..75459eac7 100644 --- a/source/platform/posix/sdl/st_start.cpp +++ b/source/platform/posix/sdl/st_start.cpp @@ -41,7 +41,7 @@ #include "st_start.h" #include "i_system.h" #include "c_cvars.h" -#include "compat.h" +#include "engineerrors.h" // MACROS ------------------------------------------------------------------ diff --git a/source/platform/posix/unix/gtk_dialogs.cpp b/source/platform/posix/unix/gtk_dialogs.cpp index a7171eba0..6a3042e44 100644 --- a/source/platform/posix/unix/gtk_dialogs.cpp +++ b/source/platform/posix/unix/gtk_dialogs.cpp @@ -58,8 +58,10 @@ typedef enum #include "i_module.h" #include "i_system.h" #include "version.h" -#include "gamecontrol.h" +#include "startupinfo.h" #include "cmdlib.h" +#include "i_interface.h" +#include "printf.h" EXTERN_CVAR (Bool, queryiwad); @@ -208,7 +210,7 @@ static int PickIWad (WadStuff *wads, int numwads, bool showwin, int defaultiwad) // Create the dialog window. window = gtk_window_new (GTK_WINDOW_TOPLEVEL); - snprintf(caption, countof(caption), GAMENAME " %s: Select an IWAD to use", GetVersionString()); + mysnprintf(caption, countof(caption), GAMENAME " %s: Select an IWAD to use", GetVersionString()); gtk_window_set_title (GTK_WINDOW(window), caption); gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER); gtk_window_set_gravity (GTK_WINDOW(window), GDK_GRAVITY_CENTER); diff --git a/source/platform/posix/unix/i_specialpaths.cpp b/source/platform/posix/unix/i_specialpaths.cpp index 9599dbb8b..524f94c60 100644 --- a/source/platform/posix/unix/i_specialpaths.cpp +++ b/source/platform/posix/unix/i_specialpaths.cpp @@ -38,6 +38,7 @@ #include "i_system.h" #include "cmdlib.h" #include "printf.h" +#include "engineerrors.h" #include "version.h" // for GAMENAME @@ -119,6 +120,26 @@ FString M_GetAppDataPath(bool create) return path; } +//=========================================================================== +// +// M_GetCachePath Unix +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath(bool create) +{ + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + FString path = NicePath("$HOME/.config/zdoom/cache"); + if (create) + { + CreatePath(path); + } + return path; +} + //=========================================================================== // // M_GetAutoexecPath Unix diff --git a/source/platform/win32/hardware.cpp b/source/platform/win32/hardware.cpp index 410ccbbc6..3cadc1ced 100644 --- a/source/platform/win32/hardware.cpp +++ b/source/platform/win32/hardware.cpp @@ -44,9 +44,13 @@ #include "version.h" #include "printf.h" #include "win32glvideo.h" +#ifdef HAVE_SOFTPOLY +#include "win32polyvideo.h" +#endif #ifdef HAVE_VULKAN #include "win32vulkanvideo.h" #endif +#include "engineerrors.h" #include "i_system.h" EXTERN_CVAR(Int, vid_preferbackend) @@ -127,8 +131,15 @@ void I_InitGraphics () // are the active app. Huh? } +#ifdef HAVE_SOFTPOLY + if (vid_preferbackend == 2) + { + Video = new Win32PolyVideo(); + } + else +#endif #ifdef HAVE_VULKAN - else if (vid_preferbackend == 1) + if (vid_preferbackend == 1) { // first try Vulkan, if that fails OpenGL try @@ -141,12 +152,16 @@ void I_InitGraphics () Video = new Win32GLVideo(); } } -#endif else +#endif { Video = new Win32GLVideo(); } +#ifdef HAVE_SOFTPOLY + if (Video == NULL) + Video = new Win32PolyVideo(); +#endif // we somehow STILL don't have a display!! if (Video == NULL) I_FatalError ("Failed to initialize display"); diff --git a/source/platform/win32/i_input.cpp b/source/platform/win32/i_input.cpp index 1711b58dc..2a67766bd 100644 --- a/source/platform/win32/i_input.cpp +++ b/source/platform/win32/i_input.cpp @@ -80,12 +80,11 @@ #include "d_event.h" #include "v_text.h" #include "version.h" +#include "engineerrors.h" #include "i_system.h" +#include "i_interface.h" #include "printf.h" -#include "c_console.h" -#include "menu.h" #include "c_buttons.h" -#include "gamecontrol.h" #include "cmdlib.h" // Compensate for w32api's lack @@ -109,6 +108,7 @@ extern DWORD SessionID; static HMODULE DInputDLL; +bool GUICapture; extern FMouse *Mouse; extern FKeyboard *Keyboard; extern bool ToggleFullscreen; @@ -136,7 +136,7 @@ extern bool AppActive; int SessionState = 0; int BlockMouseMove; -double refreshfreq; +extern double refreshfreq; static bool EventHandlerResultForNativeMouse; @@ -146,6 +146,19 @@ CVAR (Bool, k_allowfullscreentoggle, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) extern int chatmodeon; +static void I_CheckGUICapture () +{ + bool wantCapt = sysCallbacks && sysCallbacks->WantGuiCapture && sysCallbacks->WantGuiCapture(); + + if (wantCapt != GUICapture) + { + GUICapture = wantCapt; + if (wantCapt && Keyboard != NULL) + { + Keyboard->AllKeysUp(); + } + } +} void I_SetMouseCapture() { @@ -398,15 +411,13 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) return result; } -#if 0 - if ((gamestate == GS_DEMOSCREEN || gamestate == GS_TITLELEVEL) && message == WM_LBUTTONDOWN) + if (message == WM_LBUTTONDOWN && sysCallbacks && sysCallbacks->WantLeftButton() && sysCallbacks->WantLeftButton()) { if (GUIWndProcHook(hWnd, message, wParam, lParam, &result)) { return result; } } -#endif switch (message) @@ -436,7 +447,7 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_SETFOCUS: GetRefreshRate(hWnd); - I_CheckNativeMouse (false, false); // This cannot call the event handler. Doing it from here is unsafe. + I_CheckNativeMouse (false, EventHandlerResultForNativeMouse); // This cannot call the event handler. Doing it from here is unsafe. break; case WM_SETCURSOR: @@ -513,12 +524,10 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { SetPriorityClass (GetCurrentProcess (), INGAME_PRIORITY_CLASS); } -#if 0 - else if (!noidle && !netgame) + else if (!noidle && !(sysCallbacks && sysCallbacks->NetGame && sysCallbacks->NetGame())) { SetPriorityClass (GetCurrentProcess (), IDLE_PRIORITY_CLASS); } -#endif S_SetSoundPaused ((!!i_soundinbackground) || wParam); break; @@ -757,10 +766,11 @@ void I_GetEvent () // void I_StartTic () { - I_StartFrame(); BlockMouseMove--; buttonMap.ResetButtonTriggers (); - I_CheckNativeMouse (false, false); + I_CheckGUICapture (); + EventHandlerResultForNativeMouse = sysCallbacks && sysCallbacks->WantNativeMouse && sysCallbacks->WantNativeMouse(); + I_CheckNativeMouse (false, EventHandlerResultForNativeMouse); I_GetEvent (); } diff --git a/source/platform/win32/i_input.h b/source/platform/win32/i_input.h index c004a6bbf..5e5204212 100644 --- a/source/platform/win32/i_input.h +++ b/source/platform/win32/i_input.h @@ -117,7 +117,7 @@ protected: void PostKeyEvent(int keynum, INTBOOL down, bool foreground); }; -class /*NOVTABLE*/ FJoystickCollection : public FInputDevice +class NOVTABLE FJoystickCollection : public FInputDevice { public: virtual void AddAxes(float axes[NUM_JOYAXIS]) = 0; diff --git a/source/platform/win32/i_keyboard.cpp b/source/platform/win32/i_keyboard.cpp index c4379de55..9567809f5 100644 --- a/source/platform/win32/i_keyboard.cpp +++ b/source/platform/win32/i_keyboard.cpp @@ -40,7 +40,6 @@ #include "i_input.h" #include "d_event.h" -#include "inputstate.h" // MACROS ------------------------------------------------------------------ @@ -91,7 +90,7 @@ protected: extern HWND Window; extern LPDIRECTINPUT8 g_pdi; extern LPDIRECTINPUT g_pdi3; - +extern bool GUICapture; // PRIVATE DATA DEFINITIONS ------------------------------------------------ diff --git a/source/platform/win32/i_main.cpp b/source/platform/win32/i_main.cpp index face4d06e..0eaceba72 100644 --- a/source/platform/win32/i_main.cpp +++ b/source/platform/win32/i_main.cpp @@ -55,28 +55,27 @@ #endif #include "resource.h" -//#include "doomerrors.h" +#include "engineerrors.h" #include "hardware.h" #include "m_argv.h" -#include "gamecontrol.h" #include "i_module.h" #include "c_console.h" #include "version.h" #include "i_input.h" #include "filesystem.h" #include "cmdlib.h" -//#include "g_game.h" -//#include "r_utility.h" -//#include "g_levellocals.h" #include "s_soundinternal.h" -//#include "vm.h" +#include "vm.h" #include "i_system.h" #include "gstrings.h" #include "s_music.h" #include "stats.h" #include "st_start.h" +#include "i_interface.h" +#include "startupinfo.h" +#include "printf.h" // MACROS ------------------------------------------------------------------ @@ -88,7 +87,7 @@ #endif // TYPES ------------------------------------------------------------------- -bool batchrun; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- LRESULT CALLBACK WndProc (HWND, UINT, WPARAM, LPARAM); @@ -96,6 +95,7 @@ void CreateCrashLog (const char *custominfo, DWORD customsize, HWND richedit); void DisplayCrashLog (); void I_FlushBufferedConsoleStuff(); void DestroyCustomCursor(); +int GameMain(); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -268,14 +268,12 @@ void LayoutMainWindow (HWND hWnd, HWND pane) w = rect.right; h = rect.bottom; - /* - if (userConfig..IsNotEmpty() && GameTitleWindow != NULL) + if (GameStartupInfo.Name.IsNotEmpty() && GameTitleWindow != NULL) { bannerheight = GameTitleFontHeight + 5; MoveWindow (GameTitleWindow, 0, 0, w, bannerheight, TRUE); InvalidateRect (GameTitleWindow, NULL, FALSE); } - */ if (ProgressBar != NULL) { // Base the height of the progress bar on the height of a scroll bar @@ -340,14 +338,14 @@ LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) { HWND view; HDC hdc; - //HBRUSH hbr; + HBRUSH hbr; HGDIOBJ oldfont; - //RECT rect; - //SIZE size; + RECT rect; + SIZE size; LOGFONT lf; TEXTMETRIC tm; HINSTANCE inst = (HINSTANCE)(LONG_PTR)GetWindowLongPtr(hWnd, GWLP_HINSTANCE); - //DRAWITEMSTRUCT *drawitem; + DRAWITEMSTRUCT *drawitem; CHARFORMAT2W format; switch (msg) @@ -428,45 +426,73 @@ LRESULT CALLBACK LConProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) case WM_DRAWITEM: // Draw title banner. - if (wParam == IDC_STATIC_TITLE && RazeStartupInfo.Name.IsNotEmpty()) + if (wParam == IDC_STATIC_TITLE && GameStartupInfo.Name.IsNotEmpty()) { const PalEntry *c; // Draw the game title strip at the top of the window. - auto drawitem = (LPDRAWITEMSTRUCT)lParam; - SIZE size; + drawitem = (LPDRAWITEMSTRUCT)lParam; // Draw the background. - auto rect = drawitem->rcItem; + rect = drawitem->rcItem; rect.bottom -= 1; - c = (const PalEntry *)&RazeStartupInfo.BkColor; - auto hbr = CreateSolidBrush (RGB(c->r,c->g,c->b)); + c = (const PalEntry *)&GameStartupInfo.BkColor; + hbr = CreateSolidBrush (RGB(c->r,c->g,c->b)); FillRect (drawitem->hDC, &drawitem->rcItem, hbr); DeleteObject (hbr); // Calculate width of the title string. SetTextAlign (drawitem->hDC, TA_TOP); oldfont = SelectObject (drawitem->hDC, GameTitleFont != NULL ? GameTitleFont : (HFONT)GetStockObject (DEFAULT_GUI_FONT)); - auto widename = RazeStartupInfo.Name.WideString(); + auto widename = GameStartupInfo.Name.WideString(); GetTextExtentPoint32W (drawitem->hDC, widename.c_str(), (int)widename.length(), &size); // Draw the title. - c = (const PalEntry *)&RazeStartupInfo.FgColor; + c = (const PalEntry *)&GameStartupInfo.FgColor; SetTextColor (drawitem->hDC, RGB(c->r,c->g,c->b)); SetBkMode (drawitem->hDC, TRANSPARENT); TextOutW (drawitem->hDC, rect.left + (rect.right - rect.left - size.cx) / 2, 2, widename.c_str(), (int)widename.length()); SelectObject (drawitem->hDC, oldfont); return TRUE; } + // Draw startup screen + else if (wParam == IDC_STATIC_STARTUP) + { + if (StartupScreen != NULL) + { + drawitem = (LPDRAWITEMSTRUCT)lParam; + + rect = drawitem->rcItem; + // Windows expects DIBs to be bottom-up but ours is top-down, + // so flip it vertically while drawing it. + StretchDIBits (drawitem->hDC, rect.left, rect.bottom - 1, rect.right - rect.left, rect.top - rect.bottom, + 0, 0, StartupBitmap->bmiHeader.biWidth, StartupBitmap->bmiHeader.biHeight, + ST_Util_BitsForBitmap(StartupBitmap), reinterpret_cast(StartupBitmap), DIB_RGB_COLORS, SRCCOPY); + + // If the title banner is gone, then this is an ENDOOM screen, so draw a short prompt + // where the command prompt would have been in DOS. + if (GameTitleWindow == NULL) + { + auto quitmsg = WideString(GStrings("TXT_QUITENDOOM")); + + SetTextColor (drawitem->hDC, RGB(240,240,240)); + SetBkMode (drawitem->hDC, TRANSPARENT); + oldfont = SelectObject (drawitem->hDC, (HFONT)GetStockObject (DEFAULT_GUI_FONT)); + TextOutW (drawitem->hDC, 3, drawitem->rcItem.bottom - DefaultGUIFontHeight - 3, quitmsg.c_str(), (int)quitmsg.length()); + SelectObject (drawitem->hDC, oldfont); + } + return TRUE; + } + } // Draw stop icon. else if (wParam == IDC_ICONPIC) { HICON icon; POINTL char_pos; - auto drawitem = (LPDRAWITEMSTRUCT)lParam; + drawitem = (LPDRAWITEMSTRUCT)lParam; // This background color should match the edit control's. - auto hbr = CreateSolidBrush (RGB(70,70,70)); + hbr = CreateSolidBrush (RGB(70,70,70)); FillRect (drawitem->hDC, &drawitem->rcItem, hbr); DeleteObject (hbr); @@ -613,12 +639,10 @@ void ShowErrorPane(const char *text) return; } -#if 0 if (StartScreen != NULL) // Ensure that the network pane is hidden. { StartScreen->NetDone(); } -#endif if (text != NULL) { FStringf caption("Fatal Error - " GAMENAME " %s " X64 " (%s)", GetVersionString(), GetGitTime()); @@ -959,6 +983,11 @@ void I_ShowFatalError(const char *msg) S_StopMusic(true); I_FlushBufferedConsoleStuff(); + if (CVMAbortException::stacktrace.IsNotEmpty()) + { + Printf("%s", CVMAbortException::stacktrace.GetChars()); + } + if (!batchrun) { ShowErrorPane(msg); @@ -969,34 +998,6 @@ void I_ShowFatalError(const char *msg) } } -//========================================================================== -// -// DoomSpecificInfo -// -// Called by the crash logger to get application-specific information. -// -//========================================================================== - -void DoomSpecificInfo (char *buffer, size_t bufflen) -{ - const char *arg; - char *const buffend = buffer + bufflen - 2; // -2 for CRLF at end - int i; - - buffer += snprintf (buffer, buffend - buffer, GAMENAME " version %s (%s)", GetVersionString(), GetGitHash()); - FString cmdline(GetCommandLineW()); - buffer += snprintf (buffer, buffend - buffer, "\r\nCommand line: %s\r\n", cmdline.GetChars() ); - - for (i = 0; (arg = fileSystem.GetResourceFileFullName (i)) != NULL; ++i) - { - buffer += snprintf (buffer, buffend - buffer, "\r\nFile %d: %s", i, arg); - } - - *buffer++ = '\r'; - *buffer++ = '\n'; - *buffer++ = '\0'; -} - // Here is how the error logging system works. // // To catch exceptions that occur in secondary threads, CatchAllExceptions is @@ -1089,7 +1090,7 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) char *custominfo = (char *)HeapAlloc (GetProcessHeap(), 0, 16384); CrashPointers = *info; - DoomSpecificInfo (custominfo, 16384); + if (sysCallbacks && sysCallbacks->CrashInfo && custominfo) sysCallbacks->CrashInfo(custominfo, 16384, "\r\n"); CreateCrashLog (custominfo, (DWORD)strlen(custominfo), ConWindow); // If the main thread crashed, then make it clean up after itself. @@ -1223,8 +1224,7 @@ int WINAPI wWinMain (HINSTANCE hInstance, HINSTANCE nothing, LPWSTR cmdline, int _CrtSetDbgFlag (_CrtSetDbgFlag(0) | _CRTDBG_LEAK_CHECK_DF); // Use this to break at a specific allocation number. - - //_crtBreakAlloc = 254849; + //_crtBreakAlloc = 227524; #endif int ret = DoMain (hInstance); diff --git a/source/platform/win32/i_mouse.cpp b/source/platform/win32/i_mouse.cpp index b7c4a4420..a3aaec674 100644 --- a/source/platform/win32/i_mouse.cpp +++ b/source/platform/win32/i_mouse.cpp @@ -43,6 +43,7 @@ #include "d_gui.h" #include "hardware.h" #include "menu/menu.h" +#include "i_interface.h" // MACROS ------------------------------------------------------------------ @@ -138,6 +139,7 @@ static void CenterMouse(int x, int y, LONG *centx, LONG *centy); extern HWND Window; extern LPDIRECTINPUT8 g_pdi; extern LPDIRECTINPUT g_pdi3; +extern bool GUICapture; extern int BlockMouseMove; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -162,7 +164,7 @@ CVAR (Bool, m_noprescale, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, m_filter, false, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, m_hidepointer, true, 0) -CUSTOM_CVAR (Int, in_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) +CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) { if (self < 0) { @@ -178,19 +180,6 @@ CUSTOM_CVAR (Int, in_mouse, 2, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOINITCALL) } } -CUSTOM_CVAR(Int, mouse_capturemode, 1, CVAR_GLOBALCONFIG|CVAR_ARCHIVE) -{ - if (self < 0) - { - self = 0; - } - else if (self > 2) - { - self = 2; - } -} - - // CODE -------------------------------------------------------------------- //========================================================================== @@ -248,24 +237,6 @@ static void CenterMouse(int curx, int cury, LONG *centxp, LONG *centyp) } } -//========================================================================== -// -// CaptureMode_InGame -// -//========================================================================== - -static bool CaptureMode_InGame() -{ - if (mouse_capturemode == 2) - { - return true; - } - else - { - return gi->CanSave(); - } -} - //========================================================================== // // I_CheckNativeMouse @@ -275,11 +246,40 @@ static bool CaptureMode_InGame() // //========================================================================== -extern bool grab_mouse; - void I_CheckNativeMouse(bool preferNative, bool eventhandlerresult) { - bool want_native = !grab_mouse || preferNative; + bool windowed = (screen == NULL) || !screen->IsFullscreen(); + bool want_native; + + if (!windowed) + { + // ungrab mouse when in the menu with mouse control on. + want_native = m_use_mouse && (menuactive == MENU_On || menuactive == MENU_OnNoPause); + } + else + { + if ((GetForegroundWindow() != Window) || preferNative || !use_mouse) + { + want_native = true; + } + else if (menuactive == MENU_WaitKey) + { + want_native = false; + } + else + { + bool pauseState = false; + bool captureModeInGame = sysCallbacks && sysCallbacks->CaptureModeInGame && sysCallbacks->CaptureModeInGame(); + want_native = ((!m_use_mouse || menuactive != MENU_WaitKey) && + (!captureModeInGame || GUICapture)); + } + } + + if (!want_native && eventhandlerresult) + want_native = true; + + //Printf ("%d %d %d\n", wantNative, preferNative, NativeMouse); + if (want_native != NativeMouse) { if (Mouse != NULL) @@ -382,9 +382,8 @@ void FMouse::WheelMoved(int axis, int wheelmove) { ev.type = EV_KeyDown; D_PostEvent(&ev); - // The Up events must be delayed so that the wheel can remain in a "pressed" state for the next tic's duration. - //ev.type = EV_KeyUp; - //D_PostEvent(&ev); + ev.type = EV_KeyUp; + D_PostEvent(&ev); WheelMove[axis] += dir; } } diff --git a/source/platform/win32/i_rawps2.cpp b/source/platform/win32/i_rawps2.cpp index fb86205db..a6b31970f 100644 --- a/source/platform/win32/i_rawps2.cpp +++ b/source/platform/win32/i_rawps2.cpp @@ -41,8 +41,8 @@ #include "templates.h" #include "gameconfigfile.h" #include "m_argv.h" -#include "keydef.h" #include "cmdlib.h" +#include "keydef.h" // MACROS ------------------------------------------------------------------ diff --git a/source/platform/win32/i_specialpaths.cpp b/source/platform/win32/i_specialpaths.cpp index 616e85c01..3078f59c1 100644 --- a/source/platform/win32/i_specialpaths.cpp +++ b/source/platform/win32/i_specialpaths.cpp @@ -44,8 +44,6 @@ #include "findfile.h" #include "version.h" // for GAMENAME -// Stuff that needs to be set up later. - // Vanilla MinGW does not have folder ids #if defined(__MINGW32__) && !defined(__MINGW64_VERSION_MAJOR) static const GUID FOLDERID_LocalAppData = { 0xf1b32785, 0x6fba, 0x4fcf, 0x9d, 0x55, 0x7b, 0x8e, 0x7f, 0x15, 0x70, 0x91 }; @@ -138,6 +136,33 @@ FString M_GetAppDataPath(bool create) return path; } +//=========================================================================== +// +// M_GetCachePath Windows +// +// Returns the path for cache GL nodes. +// +//=========================================================================== + +FString M_GetCachePath(bool create) +{ + FString path; + + if (!GetKnownFolder(CSIDL_LOCAL_APPDATA, FOLDERID_LocalAppData, create, path)) + { // Failed (e.g. On Win9x): use program directory + path = progdir; + } + // Don't use GAME_DIR and such so that ZDoom and its child ports can + // share the node cache. + path += "/zdoom/cache"; + path.Substitute("//", "/"); // needed because progdir ends with a slash. + if (create) + { + CreatePath(path); + } + return path; +} + //=========================================================================== // // M_GetAutoexecPath Windows @@ -332,9 +357,9 @@ FString M_GetDocumentsPath() //=========================================================================== // -// M_GetDocumentsPath Windows +// M_GetDemoPath Windows // -// Returns the path to the default documents directory. +// Returns the path to the default demp directory. // //=========================================================================== diff --git a/source/platform/win32/i_steam.cpp b/source/platform/win32/i_steam.cpp new file mode 100644 index 000000000..2c2ae27b8 --- /dev/null +++ b/source/platform/win32/i_steam.cpp @@ -0,0 +1,39 @@ +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include "zstring.h" + + + +//========================================================================== +// +// QueryPathKey +// +// Returns the value of a registry key into the output variable value. +// +//========================================================================== + +bool I_QueryPathKey(const wchar_t* keypath, const wchar_t* valname, FString& value) +{ + HKEY pathkey; + DWORD pathtype; + DWORD pathlen; + LONG res; + + value = ""; + if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, keypath, 0, KEY_QUERY_VALUE, &pathkey)) + { + if (ERROR_SUCCESS == RegQueryValueEx(pathkey, valname, 0, &pathtype, NULL, &pathlen) && + pathtype == REG_SZ && pathlen != 0) + { + // Don't include terminating null in count + TArray chars(pathlen + 1, true); + res = RegQueryValueEx(pathkey, valname, 0, NULL, (LPBYTE)chars.Data(), &pathlen); + if (res == ERROR_SUCCESS) value = FString(chars.Data()); + } + RegCloseKey(pathkey); + } + return value.IsNotEmpty(); +} + diff --git a/source/platform/win32/i_system.cpp b/source/platform/win32/i_system.cpp index a6ddbb4d3..48bf64541 100644 --- a/source/platform/win32/i_system.cpp +++ b/source/platform/win32/i_system.cpp @@ -70,7 +70,6 @@ #include "stats.h" #include "v_text.h" #include "utf8.h" -#include "gamecontrol.h" #include "i_input.h" #include "c_dispatch.h" @@ -80,8 +79,8 @@ #include "i_system.h" #include "bitmap.h" #include "cmdlib.h" +#include "i_interface.h" -extern bool batchrun; // MACROS ------------------------------------------------------------------ #ifdef _MSC_VER @@ -94,7 +93,6 @@ extern bool batchrun; // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- -//extern void CheckCPUID(CPUInfo *cpu); extern void LayoutMainWindow(HWND hWnd, HWND pane); // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -103,8 +101,6 @@ void DestroyCustomCursor(); // PRIVATE FUNCTION PROTOTYPES --------------------------------------------- -static void CalculateCPUSpeed(); - static HCURSOR CreateCompatibleCursor(FBitmap &cursorpic, int leftofs, int topofs); static HCURSOR CreateAlphaCursor(FBitmap &cursorpic, int leftofs, int topofs); static HCURSOR CreateBitmapCursor(int xhot, int yhot, HBITMAP and_mask, HBITMAP color_mask); @@ -145,7 +141,6 @@ static int DefaultWad; static HCURSOR CustomCursor; - //========================================================================== // // I_DetectOS @@ -171,24 +166,7 @@ void I_DetectOS(void) { case VER_PLATFORM_WIN32_NT: osname = "NT"; - if (info.dwMajorVersion == 5) - { - if (info.dwMinorVersion == 0) - { - osname = "2000"; - } - if (info.dwMinorVersion == 1) - { - osname = "XP"; - sys_ostype = 1; // legacy OS - } - else if (info.dwMinorVersion == 2) - { - osname = "Server 2003"; - sys_ostype = 1; // legacy OS - } - } - else if (info.dwMajorVersion == 6) + if (info.dwMajorVersion == 6) { if (info.dwMinorVersion == 0) { @@ -215,12 +193,12 @@ void I_DetectOS(void) } else if (info.dwMinorVersion == 4) { - osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (beta)" : "Server 10 (beta)"; + osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (beta)" : "Server 2016 (beta)"; } } else if (info.dwMajorVersion == 10) { - osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (or higher)" : "Server 10 (or higher)"; + osname = (info.wProductType == VER_NT_WORKSTATION) ? "10 (or higher)" : "Server 2016 (or higher)"; sys_ostype = 3; // modern OS } break; @@ -292,20 +270,6 @@ void CalculateCPUSpeed() if (!batchrun) Printf ("CPU speed: %.0f MHz\n", 0.001 / PerfToMillisec); } -//========================================================================== -// -// I_Init -// -//========================================================================== - -void I_Init() -{ - //CheckCPUID(&CPU); - CalculateCPUSpeed(); - //DumpCPUInfo(&CPU); -} - - //========================================================================== // // I_PrintStr @@ -394,6 +358,31 @@ static void DoPrintStr(const char *cpt, HWND edit, HANDLE StdOut) { // Change the color of future text added to the control. PalEntry color = V_LogColorFromColorRange(range); + if (StdOut != NULL && FancyStdOut) + { + // Unfortunately, we are pretty limited here: There are only + // eight basic colors, and each comes in a dark and a bright + // variety. + float h, s, v, r, g, b; + int attrib = 0; + + RGBtoHSV(color.r / 255.f, color.g / 255.f, color.b / 255.f, &h, &s, &v); + if (s != 0) + { // color + HSVtoRGB(&r, &g, &b, h, 1, 1); + if (r == 1) attrib = FOREGROUND_RED; + if (g == 1) attrib |= FOREGROUND_GREEN; + if (b == 1) attrib |= FOREGROUND_BLUE; + if (v > 0.6) attrib |= FOREGROUND_INTENSITY; + } + else + { // gray + if (v < 0.33) attrib = FOREGROUND_INTENSITY; + else if (v < 0.90) attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; + else attrib = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; + } + SetConsoleTextAttribute(StdOut, (WORD)attrib); + } if (edit != NULL) { // GDI uses BGR colors, but color is RGB, so swap the R and the B. @@ -538,8 +527,8 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa // [SP] This is our's SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_SETCHECK, disableautoload ? BST_CHECKED : BST_UNCHECKED, 0 ); - //SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_SETCHECK, autoloadlights ? BST_CHECKED : BST_UNCHECKED, 0 ); - //SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_SETCHECK, autoloadbrightmaps ? BST_CHECKED : BST_UNCHECKED, 0 ); + SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_SETCHECK, autoloadlights ? BST_CHECKED : BST_UNCHECKED, 0 ); + SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_SETCHECK, autoloadbrightmaps ? BST_CHECKED : BST_UNCHECKED, 0 ); // Set up our version string. sprintf(szString, "Version %s.", GetVersionString()); @@ -592,8 +581,8 @@ BOOL CALLBACK IWADBoxCallback(HWND hDlg, UINT message, WPARAM wParam, LPARAM lPa // [SP] This is our's. disableautoload = SendDlgItemMessage( hDlg, IDC_WELCOME_NOAUTOLOAD, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - //autoloadlights = SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; - //autoloadbrightmaps = SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; + autoloadlights = SendDlgItemMessage( hDlg, IDC_WELCOME_LIGHTS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; + autoloadbrightmaps = SendDlgItemMessage( hDlg, IDC_WELCOME_BRIGHTMAPS, BM_GETCHECK, 0, 0 ) == BST_CHECKED; ctrl = GetDlgItem (hDlg, IDC_IWADLIST); EndDialog(hDlg, SendMessage (ctrl, LB_GETCURSEL, 0, 0)); } @@ -650,7 +639,7 @@ bool I_SetCursor(FGameTexture *cursorpic) { HCURSOR cursor; - if (cursorpic != NULL) + if (cursorpic != NULL && cursorpic->isValid()) { auto image = cursorpic->GetTexture()->GetBgraBitmap(nullptr); // Must be no larger than 32x32. (is this still necessary? @@ -659,8 +648,8 @@ bool I_SetCursor(FGameTexture *cursorpic) return false; } // Fixme: This should get a raw image, not a texture. (Once raw images get implemented.) - int lo = cursorpic->GetTexelLeftOffset(0); - int to = cursorpic->GetTexelTopOffset(0); + int lo = cursorpic->GetTexelLeftOffset(); + int to = cursorpic->GetTexelTopOffset(); cursor = CreateAlphaCursor(image, lo, to); if (cursor == NULL) @@ -1089,35 +1078,3 @@ void I_SetThreadNumaNode(std::thread &thread, int numaNode) SetThreadAffinityMask(handle, (DWORD_PTR)numaNodes[numaNode].affinityMask); } } - -//========================================================================== -// -// QueryPathKey -// -// Returns the value of a registry key into the output variable value. -// -//========================================================================== - -bool I_QueryPathKey(const wchar_t* keypath, const wchar_t* valname, FString& value) -{ - HKEY pathkey; - DWORD pathtype; - DWORD pathlen; - LONG res; - - value = ""; - if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, keypath, 0, KEY_QUERY_VALUE, &pathkey)) - { - if (ERROR_SUCCESS == RegQueryValueEx(pathkey, valname, 0, &pathtype, NULL, &pathlen) && - pathtype == REG_SZ && pathlen != 0) - { - // Don't include terminating null in count - TArray chars(pathlen + 1, true); - res = RegQueryValueEx(pathkey, valname, 0, NULL, (LPBYTE)chars.Data(), &pathlen); - if (res == ERROR_SUCCESS) value = FString(chars.Data()); - } - RegCloseKey(pathkey); - } - return value.IsNotEmpty(); -} - diff --git a/source/platform/win32/i_system.h b/source/platform/win32/i_system.h index 071b25a93..88a76caf7 100644 --- a/source/platform/win32/i_system.h +++ b/source/platform/win32/i_system.h @@ -15,7 +15,7 @@ struct WadStuff; void I_DetectOS (void); // Called by DoomMain. -void I_Init (void); +void CalculateCPUSpeed (void); // Return a seed value for the RNG. unsigned int I_MakeRNGSeed(); @@ -59,8 +59,6 @@ ticcmd_t *I_BaseTiccmd (void); void I_Quit (void); -void I_Tactile (int on, int off, int total); - // Set the mouse cursor. The texture must be 32x32. class FGameTexture; bool I_SetCursor(FGameTexture *cursor); @@ -104,8 +102,6 @@ typedef long WLONG_PTR; // Wrapper for GetLongPathName FString I_GetLongPathName(const FString &shortpath); -// Directory searching routines - // Mirror WIN32_FIND_DATAA in #ifndef MAX_PATH #define MAX_PATH 260 @@ -114,7 +110,6 @@ FString I_GetLongPathName(const FString &shortpath); #define PATH_MAX 260 #endif - int I_GetNumaNodeCount(); int I_GetNumaNodeThreadCount(int numaNode); void I_SetThreadNumaNode(std::thread &thread, int numaNode); diff --git a/source/platform/win32/i_xinput.cpp b/source/platform/win32/i_xinput.cpp index cdcd66a08..e473d8bd2 100644 --- a/source/platform/win32/i_xinput.cpp +++ b/source/platform/win32/i_xinput.cpp @@ -31,8 +31,6 @@ ** */ -#ifndef NO_XINPUT - // HEADER FILES ------------------------------------------------------------ #define WIN32_LEAN_AND_MEAN @@ -45,6 +43,7 @@ #include "templates.h" #include "gameconfigfile.h" #include "m_argv.h" +#include "cmdlib.h" #include "keydef.h" // MACROS ------------------------------------------------------------------ @@ -830,13 +829,3 @@ void I_StartupXInput() } } -#else // NO_XINPUT - -#include "i_input.h" - -void I_StartupXInput() -{ - JoyDevices[INPUT_XInput] = NULL; -} - -#endif diff --git a/source/platform/win32/st_start.cpp b/source/platform/win32/st_start.cpp index 50e9d2539..32aa3c1c6 100644 --- a/source/platform/win32/st_start.cpp +++ b/source/platform/win32/st_start.cpp @@ -40,18 +40,21 @@ #include "resource.h" #include "st_start.h" +#include "cmdlib.h" #include "templates.h" #include "i_system.h" #include "i_input.h" #include "hardware.h" +#include "filesystem.h" #include "m_argv.h" +#include "engineerrors.h" #include "s_music.h" #include "printf.h" -#include "cmdlib.h" +#include "startupinfo.h" +#include "i_interface.h" // MACROS ------------------------------------------------------------------ - // How many ms elapse between blinking text flips. On a standard VGA // adapter, the characters are on for 16 frames and then off for another 16. // The number here therefore corresponds roughly to the blink rate on a @@ -109,7 +112,32 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) FStartupScreen *FStartupScreen::CreateInstance(int max_progress) { FStartupScreen *scr = NULL; - scr = new FBasicStartupScreen(max_progress, true); + HRESULT hr; + + if (!Args->CheckParm("-nostartup")) + { + if (GameStartupInfo.Type == FStartupInfo::HexenStartup) + { + scr = new FHexenStartupScreen(max_progress, hr); + } + else if (GameStartupInfo.Type == FStartupInfo::HereticStartup) + { + scr = new FHereticStartupScreen(max_progress, hr); + } + else if (GameStartupInfo.Type == FStartupInfo::StrifeStartup) + { + scr = new FStrifeStartupScreen(max_progress, hr); + } + if (scr != NULL && FAILED(hr)) + { + delete scr; + scr = NULL; + } + } + if (scr == NULL) + { + scr = new FBasicStartupScreen(max_progress, true); + } return scr; } @@ -124,7 +152,7 @@ FStartupScreen *FStartupScreen::CreateInstance(int max_progress) FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar) : FStartupScreen(max_progress) { - if (false)//show_bar) + if (show_bar) { ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, @@ -320,7 +348,7 @@ void FBasicStartupScreen :: NetProgress(int count) { char buf[16]; - snprintf (buf, countof(buf), "%d/%d", NetCurPos, NetMaxPos); + mysnprintf (buf, countof(buf), "%d/%d", NetCurPos, NetMaxPos); SetDlgItemTextA (NetStartPane, IDC_NETSTARTCOUNT, buf); SendDlgItemMessage (NetStartPane, IDC_NETSTARTPROGRESS, PBM_SETPOS, std::min(NetCurPos, NetMaxPos), 0); } @@ -397,6 +425,192 @@ static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LP return FALSE; } +//========================================================================== +// +// FGraphicalStartupScreen Constructor +// +// This doesn't really do anything. The subclass is responsible for +// creating the resources that will be freed by this class's destructor. +// +//========================================================================== + +FGraphicalStartupScreen::FGraphicalStartupScreen(int max_progress) +: FBasicStartupScreen(max_progress, false) +{ +} + +//========================================================================== +// +// FGraphicalStartupScreen Destructor +// +//========================================================================== + +FGraphicalStartupScreen::~FGraphicalStartupScreen() +{ + if (StartupScreen != NULL) + { + DestroyWindow (StartupScreen); + StartupScreen = NULL; + } + if (StartupBitmap != NULL) + { + ST_Util_FreeBitmap (StartupBitmap); + StartupBitmap = NULL; + } +} + +//========================================================================== +// +// +// +//========================================================================== + +void FHexenStartupScreen::SetWindowSize() +{ + ST_Util_SizeWindowForBitmap(1); + LayoutMainWindow(Window, NULL); + InvalidateRect(StartupScreen, NULL, TRUE); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FHereticStartupScreen::SetWindowSize() +{ + ST_Util_SizeWindowForBitmap(1); + LayoutMainWindow(Window, NULL); + InvalidateRect(StartupScreen, NULL, TRUE); +} + +//========================================================================== +// +// +// +//========================================================================== + +void FStrifeStartupScreen::SetWindowSize() +{ + ST_Util_SizeWindowForBitmap(2); + LayoutMainWindow(Window, NULL); + InvalidateRect(StartupScreen, NULL, TRUE); +} + +//========================================================================== +// +// ST_Endoom +// +// Shows an ENDOOM text screen +// +//========================================================================== + +int RunEndoom() +{ + if (showendoom == 0 || endoomName.Len() == 0) + { + return 0; + } + + int endoom_lump = fileSystem.CheckNumForFullName (endoomName, true); + + uint8_t endoom_screen[4000]; + uint8_t *font; + MSG mess; + BOOL bRet; + bool blinking = false, blinkstate = false; + int i; + + if (endoom_lump < 0 || fileSystem.FileLength (endoom_lump) != 4000) + { + return 0; + } + + if (fileSystem.GetFileContainer(endoom_lump) == fileSystem.GetMaxIwadNum() && showendoom == 2) + { + // showendoom==2 means to show only lumps from PWADs. + return 0; + } + + font = ST_Util_LoadFont (TEXT_FONT_NAME); + if (font == NULL) + { + return 0; + } + + if (!ST_Util_CreateStartupWindow()) + { + ST_Util_FreeFont (font); + return 0; + } + + I_ShutdownGraphics (); + RestoreConView (); + S_StopMusic(true); + + fileSystem.ReadFile (endoom_lump, endoom_screen); + + // Draw the loading screen to a bitmap. + StartupBitmap = ST_Util_AllocTextBitmap (font); + ST_Util_DrawTextScreen (StartupBitmap, endoom_screen, font); + + // Make the title banner go away. + if (GameTitleWindow != NULL) + { + DestroyWindow (GameTitleWindow); + GameTitleWindow = NULL; + } + + ST_Util_SizeWindowForBitmap (1); + LayoutMainWindow (Window, NULL); + InvalidateRect (StartupScreen, NULL, TRUE); + + // Does this screen need blinking? + for (i = 0; i < 80*25; ++i) + { + if (endoom_screen[1+i*2] & 0x80) + { + blinking = true; + break; + } + } + if (blinking && SetTimer (Window, 0x5A15A, BLINK_PERIOD, NULL) == 0) + { + blinking = false; + } + + // Wait until any key has been pressed or a quit message has been received + for (;;) + { + bRet = GetMessage (&mess, NULL, 0, 0); + if (bRet == 0 || bRet == -1 || // bRet == 0 means we received WM_QUIT + mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN) + { + if (blinking) + { + KillTimer (Window, 0x5A15A); + } + ST_Util_FreeBitmap (StartupBitmap); + ST_Util_FreeFont (font); + return int(bRet == 0 ? mess.wParam : 0); + } + else if (blinking && mess.message == WM_TIMER && mess.hwnd == Window && mess.wParam == 0x5A15A) + { + ST_Util_UpdateTextBlink (StartupBitmap, endoom_screen, font, blinkstate); + blinkstate = !blinkstate; + } + TranslateMessage (&mess); + DispatchMessage (&mess); + } +} + +void ST_Endoom() +{ + int code = RunEndoom(); + throw CExitEvent(code); + +} //========================================================================== // @@ -419,3 +633,86 @@ bool ST_Util_CreateStartupWindow () return true; } +//========================================================================== +// +// ST_Util_SizeWindowForBitmap +// +// Resizes the main window so that the startup bitmap will be drawn +// at the desired scale. +// +//========================================================================== + +void ST_Util_SizeWindowForBitmap (int scale) +{ + DEVMODE displaysettings; + int w, h, cx, cy, x, y; + RECT rect; + + if (GameTitleWindow != NULL) + { + GetClientRect (GameTitleWindow, &rect); + } + else + { + rect.bottom = 0; + } + RECT sizerect = { 0, 0, StartupBitmap->bmiHeader.biWidth * scale, + StartupBitmap->bmiHeader.biHeight * scale + rect.bottom }; + AdjustWindowRectEx(&sizerect, WS_VISIBLE|WS_OVERLAPPEDWINDOW, FALSE, WS_EX_APPWINDOW); + w = sizerect.right - sizerect.left; + h = sizerect.bottom - sizerect.top; + + // Resize the window, but keep its center point the same, unless that + // puts it partially offscreen. + memset (&displaysettings, 0, sizeof(displaysettings)); + displaysettings.dmSize = sizeof(displaysettings); + EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &displaysettings); + GetWindowRect (Window, &rect); + cx = (rect.left + rect.right) / 2; + cy = (rect.top + rect.bottom) / 2; + x = cx - w / 2; + y = cy - h / 2; + if (x + w > (int)displaysettings.dmPelsWidth) + { + x = displaysettings.dmPelsWidth - w; + } + if (x < 0) + { + x = 0; + } + if (y + h > (int)displaysettings.dmPelsHeight) + { + y = displaysettings.dmPelsHeight - h; + } + if (y < 0) + { + y = 0; + } + MoveWindow (Window, x, y, w, h, TRUE); +} + +//========================================================================== +// +// ST_Util_InvalidateRect +// +// Invalidates the portion of the window that the specified rect of the +// bitmap appears in. +// +//========================================================================== + +void ST_Util_InvalidateRect (HWND hwnd, BitmapInfo *bitmap_info, int left, int top, int right, int bottom) +{ + RECT rect; + + GetClientRect (hwnd, &rect); + rect.left = left * rect.right / bitmap_info->bmiHeader.biWidth - 1; + rect.top = top * rect.bottom / bitmap_info->bmiHeader.biHeight - 1; + rect.right = right * rect.right / bitmap_info->bmiHeader.biWidth + 1; + rect.bottom = bottom * rect.bottom / bitmap_info->bmiHeader.biHeight + 1; + InvalidateRect (hwnd, &rect, FALSE); +} + +void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom) +{ + ST_Util_InvalidateRect(StartupScreen , bitmap_info, left, top, right, bottom); +} diff --git a/source/platform/win32/st_start_util.cpp b/source/platform/win32/st_start_util.cpp index e69de29bb..11a0b146c 100644 --- a/source/platform/win32/st_start_util.cpp +++ b/source/platform/win32/st_start_util.cpp @@ -0,0 +1,1191 @@ +/* +** st_start.cpp +** Handles the startup screen. +** +**--------------------------------------------------------------------------- +** Copyright 2006-2007 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ + + +#include +#include +#include "st_start.h" +#include "m_alloc.h" +#include "filesystem.h" +#include "s_soundinternal.h" +#include "s_music.h" +#include "startupinfo.h" +#include "palutil.h" +#include "i_interface.h" + +void I_GetEvent(); // i_input.h pulls in too much garbage. + +void ST_Util_InvalidateRect(BitmapInfo* bitmap_info, int left, int top, int right, int bottom); +bool ST_Util_CreateStartupWindow(); + +static const uint16_t IBM437ToUnicode[] = { + 0x0000, //#NULL + 0x0001, //#START OF HEADING + 0x0002, //#START OF TEXT + 0x0003, //#END OF TEXT + 0x0004, //#END OF TRANSMISSION + 0x0005, //#ENQUIRY + 0x0006, //#ACKNOWLEDGE + 0x0007, //#BELL + 0x0008, //#BACKSPACE + 0x0009, //#HORIZONTAL TABULATION + 0x000a, //#LINE FEED + 0x000b, //#VERTICAL TABULATION + 0x000c, //#FORM FEED + 0x000d, //#CARRIAGE RETURN + 0x000e, //#SHIFT OUT + 0x000f, //#SHIFT IN + 0x0010, //#DATA LINK ESCAPE + 0x0011, //#DEVICE CONTROL ONE + 0x0012, //#DEVICE CONTROL TWO + 0x0013, //#DEVICE CONTROL THREE + 0x0014, //#DEVICE CONTROL FOUR + 0x0015, //#NEGATIVE ACKNOWLEDGE + 0x0016, //#SYNCHRONOUS IDLE + 0x0017, //#END OF TRANSMISSION BLOCK + 0x0018, //#CANCEL + 0x0019, //#END OF MEDIUM + 0x001a, //#SUBSTITUTE + 0x001b, //#ESCAPE + 0x001c, //#FILE SEPARATOR + 0x001d, //#GROUP SEPARATOR + 0x001e, //#RECORD SEPARATOR + 0x001f, //#UNIT SEPARATOR + 0x0020, //#SPACE + 0x0021, //#EXCLAMATION MARK + 0x0022, //#QUOTATION MARK + 0x0023, //#NUMBER SIGN + 0x0024, //#DOLLAR SIGN + 0x0025, //#PERCENT SIGN + 0x0026, //#AMPERSAND + 0x0027, //#APOSTROPHE + 0x0028, //#LEFT PARENTHESIS + 0x0029, //#RIGHT PARENTHESIS + 0x002a, //#ASTERISK + 0x002b, //#PLUS SIGN + 0x002c, //#COMMA + 0x002d, //#HYPHEN-MINUS + 0x002e, //#FULL STOP + 0x002f, //#SOLIDUS + 0x0030, //#DIGIT ZERO + 0x0031, //#DIGIT ONE + 0x0032, //#DIGIT TWO + 0x0033, //#DIGIT THREE + 0x0034, //#DIGIT FOUR + 0x0035, //#DIGIT FIVE + 0x0036, //#DIGIT SIX + 0x0037, //#DIGIT SEVEN + 0x0038, //#DIGIT EIGHT + 0x0039, //#DIGIT NINE + 0x003a, //#COLON + 0x003b, //#SEMICOLON + 0x003c, //#LESS-THAN SIGN + 0x003d, //#EQUALS SIGN + 0x003e, //#GREATER-THAN SIGN + 0x003f, //#QUESTION MARK + 0x0040, //#COMMERCIAL AT + 0x0041, //#LATIN CAPITAL LETTER A + 0x0042, //#LATIN CAPITAL LETTER B + 0x0043, //#LATIN CAPITAL LETTER C + 0x0044, //#LATIN CAPITAL LETTER D + 0x0045, //#LATIN CAPITAL LETTER E + 0x0046, //#LATIN CAPITAL LETTER F + 0x0047, //#LATIN CAPITAL LETTER G + 0x0048, //#LATIN CAPITAL LETTER H + 0x0049, //#LATIN CAPITAL LETTER I + 0x004a, //#LATIN CAPITAL LETTER J + 0x004b, //#LATIN CAPITAL LETTER K + 0x004c, //#LATIN CAPITAL LETTER L + 0x004d, //#LATIN CAPITAL LETTER M + 0x004e, //#LATIN CAPITAL LETTER N + 0x004f, //#LATIN CAPITAL LETTER O + 0x0050, //#LATIN CAPITAL LETTER P + 0x0051, //#LATIN CAPITAL LETTER Q + 0x0052, //#LATIN CAPITAL LETTER R + 0x0053, //#LATIN CAPITAL LETTER S + 0x0054, //#LATIN CAPITAL LETTER T + 0x0055, //#LATIN CAPITAL LETTER U + 0x0056, //#LATIN CAPITAL LETTER V + 0x0057, //#LATIN CAPITAL LETTER W + 0x0058, //#LATIN CAPITAL LETTER X + 0x0059, //#LATIN CAPITAL LETTER Y + 0x005a, //#LATIN CAPITAL LETTER Z + 0x005b, //#LEFT SQUARE BRACKET + 0x005c, //#REVERSE SOLIDUS + 0x005d, //#RIGHT SQUARE BRACKET + 0x005e, //#CIRCUMFLEX ACCENT + 0x005f, //#LOW LINE + 0x0060, //#GRAVE ACCENT + 0x0061, //#LATIN SMALL LETTER A + 0x0062, //#LATIN SMALL LETTER B + 0x0063, //#LATIN SMALL LETTER C + 0x0064, //#LATIN SMALL LETTER D + 0x0065, //#LATIN SMALL LETTER E + 0x0066, //#LATIN SMALL LETTER F + 0x0067, //#LATIN SMALL LETTER G + 0x0068, //#LATIN SMALL LETTER H + 0x0069, //#LATIN SMALL LETTER I + 0x006a, //#LATIN SMALL LETTER J + 0x006b, //#LATIN SMALL LETTER K + 0x006c, //#LATIN SMALL LETTER L + 0x006d, //#LATIN SMALL LETTER M + 0x006e, //#LATIN SMALL LETTER N + 0x006f, //#LATIN SMALL LETTER O + 0x0070, //#LATIN SMALL LETTER P + 0x0071, //#LATIN SMALL LETTER Q + 0x0072, //#LATIN SMALL LETTER R + 0x0073, //#LATIN SMALL LETTER S + 0x0074, //#LATIN SMALL LETTER T + 0x0075, //#LATIN SMALL LETTER U + 0x0076, //#LATIN SMALL LETTER V + 0x0077, //#LATIN SMALL LETTER W + 0x0078, //#LATIN SMALL LETTER X + 0x0079, //#LATIN SMALL LETTER Y + 0x007a, //#LATIN SMALL LETTER Z + 0x007b, //#LEFT CURLY BRACKET + 0x007c, //#VERTICAL LINE + 0x007d, //#RIGHT CURLY BRACKET + 0x007e, //#TILDE + 0x007f, //#DELETE + 0x00c7, //#LATIN CAPITAL LETTER C WITH CEDILLA + 0x00fc, //#LATIN SMALL LETTER U WITH DIAERESIS + 0x00e9, //#LATIN SMALL LETTER E WITH ACUTE + 0x00e2, //#LATIN SMALL LETTER A WITH CIRCUMFLEX + 0x00e4, //#LATIN SMALL LETTER A WITH DIAERESIS + 0x00e0, //#LATIN SMALL LETTER A WITH GRAVE + 0x00e5, //#LATIN SMALL LETTER A WITH RING ABOVE + 0x00e7, //#LATIN SMALL LETTER C WITH CEDILLA + 0x00ea, //#LATIN SMALL LETTER E WITH CIRCUMFLEX + 0x00eb, //#LATIN SMALL LETTER E WITH DIAERESIS + 0x00e8, //#LATIN SMALL LETTER E WITH GRAVE + 0x00ef, //#LATIN SMALL LETTER I WITH DIAERESIS + 0x00ee, //#LATIN SMALL LETTER I WITH CIRCUMFLEX + 0x00ec, //#LATIN SMALL LETTER I WITH GRAVE + 0x00c4, //#LATIN CAPITAL LETTER A WITH DIAERESIS + 0x00c5, //#LATIN CAPITAL LETTER A WITH RING ABOVE + 0x00c9, //#LATIN CAPITAL LETTER E WITH ACUTE + 0x00e6, //#LATIN SMALL LIGATURE AE + 0x00c6, //#LATIN CAPITAL LIGATURE AE + 0x00f4, //#LATIN SMALL LETTER O WITH CIRCUMFLEX + 0x00f6, //#LATIN SMALL LETTER O WITH DIAERESIS + 0x00f2, //#LATIN SMALL LETTER O WITH GRAVE + 0x00fb, //#LATIN SMALL LETTER U WITH CIRCUMFLEX + 0x00f9, //#LATIN SMALL LETTER U WITH GRAVE + 0x00ff, //#LATIN SMALL LETTER Y WITH DIAERESIS + 0x00d6, //#LATIN CAPITAL LETTER O WITH DIAERESIS + 0x00dc, //#LATIN CAPITAL LETTER U WITH DIAERESIS + 0x00a2, //#CENT SIGN + 0x00a3, //#POUND SIGN + 0x00a5, //#YEN SIGN + 0x20a7, //#PESETA SIGN + 0x0192, //#LATIN SMALL LETTER F WITH HOOK + 0x00e1, //#LATIN SMALL LETTER A WITH ACUTE + 0x00ed, //#LATIN SMALL LETTER I WITH ACUTE + 0x00f3, //#LATIN SMALL LETTER O WITH ACUTE + 0x00fa, //#LATIN SMALL LETTER U WITH ACUTE + 0x00f1, //#LATIN SMALL LETTER N WITH TILDE + 0x00d1, //#LATIN CAPITAL LETTER N WITH TILDE + 0x00aa, //#FEMININE ORDINAL INDICATOR + 0x00ba, //#MASCULINE ORDINAL INDICATOR + 0x00bf, //#INVERTED QUESTION MARK + 0x2310, //#REVERSED NOT SIGN + 0x00ac, //#NOT SIGN + 0x00bd, //#VULGAR FRACTION ONE HALF + 0x00bc, //#VULGAR FRACTION ONE QUARTER + 0x00a1, //#INVERTED EXCLAMATION MARK + 0x00ab, //#LEFT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x00bb, //#RIGHT-POINTING DOUBLE ANGLE QUOTATION MARK + 0x2591, //#LIGHT SHADE + 0x2592, //#MEDIUM SHADE + 0x2593, //#DARK SHADE + 0x2502, //#BOX DRAWINGS LIGHT VERTICAL + 0x2524, //#BOX DRAWINGS LIGHT VERTICAL AND LEFT + 0x2561, //#BOX DRAWINGS VERTICAL SINGLE AND LEFT DOUBLE + 0x2562, //#BOX DRAWINGS VERTICAL DOUBLE AND LEFT SINGLE + 0x2556, //#BOX DRAWINGS DOWN DOUBLE AND LEFT SINGLE + 0x2555, //#BOX DRAWINGS DOWN SINGLE AND LEFT DOUBLE + 0x2563, //#BOX DRAWINGS DOUBLE VERTICAL AND LEFT + 0x2551, //#BOX DRAWINGS DOUBLE VERTICAL + 0x2557, //#BOX DRAWINGS DOUBLE DOWN AND LEFT + 0x255d, //#BOX DRAWINGS DOUBLE UP AND LEFT + 0x255c, //#BOX DRAWINGS UP DOUBLE AND LEFT SINGLE + 0x255b, //#BOX DRAWINGS UP SINGLE AND LEFT DOUBLE + 0x2510, //#BOX DRAWINGS LIGHT DOWN AND LEFT + 0x2514, //#BOX DRAWINGS LIGHT UP AND RIGHT + 0x2534, //#BOX DRAWINGS LIGHT UP AND HORIZONTAL + 0x252c, //#BOX DRAWINGS LIGHT DOWN AND HORIZONTAL + 0x251c, //#BOX DRAWINGS LIGHT VERTICAL AND RIGHT + 0x2500, //#BOX DRAWINGS LIGHT HORIZONTAL + 0x253c, //#BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL + 0x255e, //#BOX DRAWINGS VERTICAL SINGLE AND RIGHT DOUBLE + 0x255f, //#BOX DRAWINGS VERTICAL DOUBLE AND RIGHT SINGLE + 0x255a, //#BOX DRAWINGS DOUBLE UP AND RIGHT + 0x2554, //#BOX DRAWINGS DOUBLE DOWN AND RIGHT + 0x2569, //#BOX DRAWINGS DOUBLE UP AND HORIZONTAL + 0x2566, //#BOX DRAWINGS DOUBLE DOWN AND HORIZONTAL + 0x2560, //#BOX DRAWINGS DOUBLE VERTICAL AND RIGHT + 0x2550, //#BOX DRAWINGS DOUBLE HORIZONTAL + 0x256c, //#BOX DRAWINGS DOUBLE VERTICAL AND HORIZONTAL + 0x2567, //#BOX DRAWINGS UP SINGLE AND HORIZONTAL DOUBLE + 0x2568, //#BOX DRAWINGS UP DOUBLE AND HORIZONTAL SINGLE + 0x2564, //#BOX DRAWINGS DOWN SINGLE AND HORIZONTAL DOUBLE + 0x2565, //#BOX DRAWINGS DOWN DOUBLE AND HORIZONTAL SINGLE + 0x2559, //#BOX DRAWINGS UP DOUBLE AND RIGHT SINGLE + 0x2558, //#BOX DRAWINGS UP SINGLE AND RIGHT DOUBLE + 0x2552, //#BOX DRAWINGS DOWN SINGLE AND RIGHT DOUBLE + 0x2553, //#BOX DRAWINGS DOWN DOUBLE AND RIGHT SINGLE + 0x256b, //#BOX DRAWINGS VERTICAL DOUBLE AND HORIZONTAL SINGLE + 0x256a, //#BOX DRAWINGS VERTICAL SINGLE AND HORIZONTAL DOUBLE + 0x2518, //#BOX DRAWINGS LIGHT UP AND LEFT + 0x250c, //#BOX DRAWINGS LIGHT DOWN AND RIGHT + 0x2588, //#FULL BLOCK + 0x2584, //#LOWER HALF BLOCK + 0x258c, //#LEFT HALF BLOCK + 0x2590, //#RIGHT HALF BLOCK + 0x2580, //#UPPER HALF BLOCK + 0x03b1, //#GREEK SMALL LETTER ALPHA + 0x00df, //#LATIN SMALL LETTER SHARP S + 0x0393, //#GREEK CAPITAL LETTER GAMMA + 0x03c0, //#GREEK SMALL LETTER PI + 0x03a3, //#GREEK CAPITAL LETTER SIGMA + 0x03c3, //#GREEK SMALL LETTER SIGMA + 0x00b5, //#MICRO SIGN + 0x03c4, //#GREEK SMALL LETTER TAU + 0x03a6, //#GREEK CAPITAL LETTER PHI + 0x0398, //#GREEK CAPITAL LETTER THETA + 0x03a9, //#GREEK CAPITAL LETTER OMEGA + 0x03b4, //#GREEK SMALL LETTER DELTA + 0x221e, //#INFINITY + 0x03c6, //#GREEK SMALL LETTER PHI + 0x03b5, //#GREEK SMALL LETTER EPSILON + 0x2229, //#INTERSECTION + 0x2261, //#IDENTICAL TO + 0x00b1, //#PLUS-MINUS SIGN + 0x2265, //#GREATER-THAN OR EQUAL TO + 0x2264, //#LESS-THAN OR EQUAL TO + 0x2320, //#TOP HALF INTEGRAL + 0x2321, //#BOTTOM HALF INTEGRAL + 0x00f7, //#DIVISION SIGN + 0x2248, //#ALMOST EQUAL TO + 0x00b0, //#DEGREE SIGN + 0x2219, //#BULLET OPERATOR + 0x00b7, //#MIDDLE DOT + 0x221a, //#SQUARE ROOT + 0x207f, //#SUPERSCRIPT LATIN SMALL LETTER N + 0x00b2, //#SUPERSCRIPT TWO + 0x25a0, //#BLACK SQUARE + 0x00a0, //#NO-BREAK SPACE +}; + +BitmapInfo* StartupBitmap; + +// Hexen startup screen +#define ST_MAX_NOTCHES 32 +#define ST_NOTCH_WIDTH 16 +#define ST_NOTCH_HEIGHT 23 +#define ST_PROGRESS_X 64 // Start of notches x screen pos. +#define ST_PROGRESS_Y 441 // Start of notches y screen pos. + +#define ST_NETPROGRESS_X 288 +#define ST_NETPROGRESS_Y 32 +#define ST_NETNOTCH_WIDTH 4 +#define ST_NETNOTCH_HEIGHT 16 +#define ST_MAX_NETNOTCHES 8 + +// Heretic startup screen +#define HERETIC_MINOR_VERSION '3' // Since we're based on Heretic 1.3 + +#define THERM_X 14 +#define THERM_Y 14 +#define THERM_LEN 51 +#define THERM_COLOR 0xAA // light green + +#define TEXT_FONT_NAME "vga-rom-font.16" + +// Strife startup screen +#define PEASANT_INDEX 0 +#define LASER_INDEX 4 +#define BOT_INDEX 6 + +#define ST_LASERSPACE_X 60 +#define ST_LASERSPACE_Y 156 +#define ST_LASERSPACE_WIDTH 200 +#define ST_LASER_WIDTH 16 +#define ST_LASER_HEIGHT 16 + +#define ST_BOT_X 14 +#define ST_BOT_Y 138 +#define ST_BOT_WIDTH 48 +#define ST_BOT_HEIGHT 48 + +#define ST_PEASANT_X 262 +#define ST_PEASANT_Y 136 +#define ST_PEASANT_WIDTH 32 +#define ST_PEASANT_HEIGHT 64 + +// Text mode color values +#define LO 85 +#define MD 170 +#define HI 255 + +static const RgbQuad TextModePalette[16] = +{ + { 0, 0, 0, 0 }, // 0 black + { MD, 0, 0, 0 }, // 1 blue + { 0, MD, 0, 0 }, // 2 green + { MD, MD, 0, 0 }, // 3 cyan + { 0, 0, MD, 0 }, // 4 red + { MD, 0, MD, 0 }, // 5 magenta + { 0, LO, MD, 0 }, // 6 brown + { MD, MD, MD, 0 }, // 7 light gray + + { LO, LO, LO, 0 }, // 8 dark gray + { HI, LO, LO, 0 }, // 9 light blue + { LO, HI, LO, 0 }, // A light green + { HI, HI, LO, 0 }, // B light cyan + { LO, LO, HI, 0 }, // C light red + { HI, LO, HI, 0 }, // D light magenta + { LO, HI, HI, 0 }, // E yellow + { HI, HI, HI, 0 }, // F white +}; + +static const char* StrifeStartupPicNames[4 + 2 + 1] = +{ + "STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1", + "STRTLZ1", "STRTLZ2", + "STRTBOT" +}; +static const int StrifeStartupPicSizes[4 + 2 + 1] = +{ + 2048, 2048, 2048, 2048, + 256, 256, + 2304 +}; + + +static void ST_Sound(const char* sndname) +{ + //S_Sound(CHAN_BODY, 0, sndname, 1, ATTN_NONE); +} + +//========================================================================== +// +// FHexenStartupScreen Constructor +// +// Shows the Hexen startup screen. If the screen doesn't appear to be +// valid, it sets hr for a failure. +// +// The startup graphic is a planar, 4-bit 640x480 graphic preceded by a +// 16 entry (48 byte) VGA palette. +// +//========================================================================== + +FHexenStartupScreen::FHexenStartupScreen(int max_progress, long& hr) + : FGraphicalStartupScreen(max_progress) +{ + int startup_lump = fileSystem.CheckNumForName("STARTUP"); + int netnotch_lump = fileSystem.CheckNumForName("NETNOTCH"); + int notch_lump = fileSystem.CheckNumForName("NOTCH"); + hr = -1; + + if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 153648 || !ST_Util_CreateStartupWindow() || + netnotch_lump < 0 || fileSystem.FileLength(netnotch_lump) != ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT || + notch_lump < 0 || fileSystem.FileLength(notch_lump) != ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT) + { + NetNotchBits = NotchBits = NULL; + return; + } + + NetNotchBits = new uint8_t[ST_NETNOTCH_WIDTH / 2 * ST_NETNOTCH_HEIGHT]; + fileSystem.ReadFile(netnotch_lump, NetNotchBits); + NotchBits = new uint8_t[ST_NOTCH_WIDTH / 2 * ST_NOTCH_HEIGHT]; + fileSystem.ReadFile(notch_lump, NotchBits); + + uint8_t startup_screen[153648]; + union + { + RgbQuad color; + uint32_t quad; + } c; + + fileSystem.ReadFile(startup_lump, startup_screen); + + c.color.rgbReserved = 0; + + StartupBitmap = ST_Util_CreateBitmap(640, 480, 4); + + // Initialize the bitmap palette. + for (int i = 0; i < 16; ++i) + { + c.color.rgbRed = startup_screen[i * 3 + 0]; + c.color.rgbGreen = startup_screen[i * 3 + 1]; + c.color.rgbBlue = startup_screen[i * 3 + 2]; + // Convert from 6-bit per component to 8-bit per component. + c.quad = (c.quad << 2) | ((c.quad >> 4) & 0x03030303); + StartupBitmap->bmiColors[i] = c.color; + } + + // Fill in the bitmap data. Convert to chunky, because I can't figure out + // if Windows actually supports planar images or not, despite the presence + // of biPlanes in the BITMAPINFOHEADER. + ST_Util_PlanarToChunky4(ST_Util_BitsForBitmap(StartupBitmap), startup_screen + 48, 640, 480); + + + if (!batchrun) + { + if (GameStartupInfo.Song.IsNotEmpty()) + { + S_ChangeMusic(GameStartupInfo.Song.GetChars(), true, true); + } + else + { + S_ChangeMusic("orb", true, true); + } + } + SetWindowSize(); + hr = 0; +} + +//========================================================================== +// +// FHexenStartupScreen Deconstructor +// +// Frees the notch pictures. +// +//========================================================================== + +FHexenStartupScreen::~FHexenStartupScreen() +{ + if (NotchBits) + delete[] NotchBits; + if (NetNotchBits) + delete[] NetNotchBits; +} + +//========================================================================== +// +// FHexenStartupScreen :: Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +void FHexenStartupScreen::Progress() +{ + int notch_pos, x, y; + + if (CurPos < MaxPos) + { + CurPos++; + notch_pos = (CurPos * ST_MAX_NOTCHES) / MaxPos; + if (notch_pos != NotchPos) + { // Time to draw another notch. + for (; NotchPos < notch_pos; NotchPos++) + { + x = ST_PROGRESS_X + ST_NOTCH_WIDTH * NotchPos; + y = ST_PROGRESS_Y; + ST_Util_DrawBlock(StartupBitmap, NotchBits, x, y, ST_NOTCH_WIDTH / 2, ST_NOTCH_HEIGHT); + } + ST_Sound("StartupTick"); + } + } + I_GetEvent(); +} + +//========================================================================== +// +// FHexenStartupScreen :: NetProgress +// +// Draws the red net noches in addition to the normal progress bar. +// +//========================================================================== + +void FHexenStartupScreen::NetProgress(int count) +{ + int oldpos = NetCurPos; + int x, y; + + FGraphicalStartupScreen::NetProgress(count); + if (NetMaxPos != 0 && NetCurPos > oldpos) + { + for (; oldpos < NetCurPos && oldpos < ST_MAX_NETNOTCHES; ++oldpos) + { + x = ST_NETPROGRESS_X + ST_NETNOTCH_WIDTH * oldpos; + y = ST_NETPROGRESS_Y; + ST_Util_DrawBlock(StartupBitmap, NetNotchBits, x, y, ST_NETNOTCH_WIDTH / 2, ST_NETNOTCH_HEIGHT); + } + ST_Sound("misc/netnotch"); + I_GetEvent(); + } +} + +//========================================================================== +// +// FHexenStartupScreen :: NetDone +// +// Aside from the standard processing, also plays a sound. +// +//========================================================================== + +void FHexenStartupScreen::NetDone() +{ + ST_Sound("PickupWeapon"); + FGraphicalStartupScreen::NetDone(); +} + + +//========================================================================== +// +// FHereticStartupScreen Constructor +// +// Shows the Heretic startup screen. If the screen doesn't appear to be +// valid, it returns a failure code in hr. +// +// The loading screen is an 80x25 text screen with character data and +// attributes intermixed, which means it must be exactly 4000 bytes long. +// +//========================================================================== + +FHereticStartupScreen::FHereticStartupScreen(int max_progress, long& hr) + : FGraphicalStartupScreen(max_progress) +{ + int loading_lump = fileSystem.CheckNumForName("LOADING"); + uint8_t loading_screen[4000]; + uint8_t* font; + + hr = -1; + if (loading_lump < 0 || fileSystem.FileLength(loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) + { + return; + } + + font = ST_Util_LoadFont(TEXT_FONT_NAME); + if (font == NULL) + { + return; + } + + fileSystem.ReadFile(loading_lump, loading_screen); + + // Slap the Heretic minor version on the loading screen. Heretic + // did this inside the executable rather than coming with modified + // LOADING screens, so we need to do the same. + loading_screen[2 * 160 + 49 * 2] = HERETIC_MINOR_VERSION; + + // Draw the loading screen to a bitmap. + StartupBitmap = ST_Util_AllocTextBitmap(font); + ST_Util_DrawTextScreen(StartupBitmap, loading_screen, font); + + ThermX = THERM_X * 8; + ThermY = THERM_Y * font[0]; + ThermWidth = THERM_LEN * 8 - 4; + ThermHeight = font[0]; + HMsgY = 7; + SMsgX = 1; + + ST_Util_FreeFont(font); + SetWindowSize(); + hr = 0; +} + +//========================================================================== +// +// FHereticStartupScreen::Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +void FHereticStartupScreen::Progress() +{ + int notch_pos; + + if (CurPos < MaxPos) + { + CurPos++; + notch_pos = (CurPos * ThermWidth) / MaxPos; + if (notch_pos != NotchPos && !(notch_pos & 3)) + { // Time to draw another notch. + int left = NotchPos + ThermX; + int top = ThermY; + int right = notch_pos + ThermX; + int bottom = top + ThermHeight; + ST_Util_ClearBlock(StartupBitmap, THERM_COLOR, left, top, right - left, bottom - top); + NotchPos = notch_pos; + } + } + I_GetEvent(); +} + +//========================================================================== +// +// FHereticStartupScreen :: LoadingStatus +// +// Prints text in the center box of the startup screen. +// +//========================================================================== + +void FHereticStartupScreen::LoadingStatus(const char* message, int colors) +{ + uint8_t* font = ST_Util_LoadFont(TEXT_FONT_NAME); + if (font != NULL) + { + int x; + + for (x = 0; message[x] != '\0'; ++x) + { + ST_Util_DrawChar(StartupBitmap, font, 17 + x, HMsgY, message[x], colors); + } + ST_Util_InvalidateRect(StartupBitmap, 17 * 8, HMsgY * font[0], (17 + x) * 8, HMsgY * font[0] + font[0]); + ST_Util_FreeFont(font); + HMsgY++; + I_GetEvent(); + } +} + +//========================================================================== +// +// FHereticStartupScreen :: AppendStatusLine +// +// Appends text to Heretic's status line. +// +//========================================================================== + +void FHereticStartupScreen::AppendStatusLine(const char* status) +{ + uint8_t* font = ST_Util_LoadFont(TEXT_FONT_NAME); + if (font != NULL) + { + int x; + + for (x = 0; status[x] != '\0'; ++x) + { + ST_Util_DrawChar(StartupBitmap, font, SMsgX + x, 24, status[x], 0x1f); + } + ST_Util_InvalidateRect(StartupBitmap, SMsgX * 8, 24 * font[0], (SMsgX + x) * 8, 25 * font[0]); + ST_Util_FreeFont(font); + SMsgX += x; + I_GetEvent(); + } +} + +//========================================================================== +// +// FStrifeStartupScreen Constructor +// +// Shows the Strife startup screen. If the screen doesn't appear to be +// valid, it returns a failure code in hr. +// +// The startup background is a raw 320x200 image, however Strife only +// actually uses 95 rows from it, starting at row 57. The rest of the image +// is discarded. (What a shame.) +// +// The peasants are raw 32x64 images. The laser dots are raw 16x16 images. +// The bot is a raw 48x48 image. All use the standard PLAYPAL. +// +//========================================================================== + +FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, long& hr) + : FGraphicalStartupScreen(max_progress) +{ + int startup_lump = fileSystem.CheckNumForName("STARTUP0"); + int i; + + hr = -1; + for (i = 0; i < 4 + 2 + 1; ++i) + { + StartupPics[i] = NULL; + } + + if (startup_lump < 0 || fileSystem.FileLength(startup_lump) != 64000 || !ST_Util_CreateStartupWindow()) + { + return; + } + + StartupBitmap = ST_Util_CreateBitmap(320, 200, 8); + ST_Util_BitmapColorsFromPlaypal(StartupBitmap); + + // Fill bitmap with the startup image. + memset(ST_Util_BitsForBitmap(StartupBitmap), 0xF0, 64000); + auto lumpr = fileSystem.OpenFileReader(startup_lump); + lumpr.Seek(57 * 320, FileReader::SeekSet); + lumpr.Read(ST_Util_BitsForBitmap(StartupBitmap) + 41 * 320, 95 * 320); + + // Load the animated overlays. + for (i = 0; i < 4 + 2 + 1; ++i) + { + int lumpnum = fileSystem.CheckNumForName(StrifeStartupPicNames[i]); + int lumplen; + + if (lumpnum >= 0 && (lumplen = fileSystem.FileLength(lumpnum)) == StrifeStartupPicSizes[i]) + { + auto lumpr = fileSystem.OpenFileReader(lumpnum); + StartupPics[i] = new uint8_t[lumplen]; + lumpr.Read(StartupPics[i], lumplen); + } + } + + // Make the startup image appear. + DrawStuff(0, 0); + SetWindowSize(); + hr = 0; +} + +//========================================================================== +// +// FStrifeStartupScreen Destructor +// +// Frees the strife pictures. +// +//========================================================================== + +FStrifeStartupScreen::~FStrifeStartupScreen() +{ + for (int i = 0; i < 4 + 2 + 1; ++i) + { + if (StartupPics[i] != NULL) + { + delete[] StartupPics[i]; + } + StartupPics[i] = NULL; + } +} + +//========================================================================== +// +// FStrifeStartupScreen :: Progress +// +// Bumps the progress meter one notch. +// +//========================================================================== + +void FStrifeStartupScreen::Progress() +{ + int notch_pos; + + if (CurPos < MaxPos) + { + CurPos++; + notch_pos = (CurPos * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos; + if (notch_pos != NotchPos && !(notch_pos & 1)) + { // Time to update. + DrawStuff(NotchPos, notch_pos); + NotchPos = notch_pos; + } + } + I_GetEvent(); +} + +//========================================================================== +// +// FStrifeStartupScreen :: DrawStuff +// +// Draws all the moving parts of Strife's startup screen. If you're +// running off a slow drive, it can look kind of good. Otherwise, it +// borders on crazy insane fast. +// +//========================================================================== + +void FStrifeStartupScreen::DrawStuff(int old_laser, int new_laser) +{ + int y; + auto bitmap_info = StartupBitmap; + + // Clear old laser + ST_Util_ClearBlock(bitmap_info, 0xF0, ST_LASERSPACE_X + old_laser, + ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT); + // Draw new laser + ST_Util_DrawBlock(bitmap_info, StartupPics[LASER_INDEX + (new_laser & 1)], + ST_LASERSPACE_X + new_laser, ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT); + + // The bot jumps up and down like crazy. + y = std::max(0, (new_laser >> 1) % 5 - 2); + if (y > 0) + { + ST_Util_ClearBlock(bitmap_info, 0xF0, ST_BOT_X, ST_BOT_Y, ST_BOT_WIDTH, y); + } + ST_Util_DrawBlock(bitmap_info, StartupPics[BOT_INDEX], ST_BOT_X, ST_BOT_Y + y, ST_BOT_WIDTH, ST_BOT_HEIGHT); + if (y < (5 - 1) - 2) + { + ST_Util_ClearBlock(bitmap_info, 0xF0, ST_BOT_X, ST_BOT_Y + ST_BOT_HEIGHT + y, ST_BOT_WIDTH, 2 - y); + } + + // The peasant desperately runs in place, trying to get away from the laser. + // Yet, despite all his limb flailing, he never manages to get anywhere. + ST_Util_DrawBlock(bitmap_info, StartupPics[PEASANT_INDEX + ((new_laser >> 1) & 3)], + ST_PEASANT_X, ST_PEASANT_Y, ST_PEASANT_WIDTH, ST_PEASANT_HEIGHT); +} + + +//========================================================================== +// +// ST_Util_PlanarToChunky4 +// +// Convert a 4-bpp planar image to chunky pixels. +// +//========================================================================== + +void ST_Util_PlanarToChunky4(uint8_t* dest, const uint8_t* src, int width, int height) +{ + int y, x; + const uint8_t* src1, * src2, * src3, * src4; + size_t plane_size = width / 8 * height; + + src1 = src; + src2 = src1 + plane_size; + src3 = src2 + plane_size; + src4 = src3 + plane_size; + + for (y = height; y > 0; --y) + { + for (x = width; x > 0; x -= 8) + { + // Pixels 0 and 1 + dest[0] = (*src4 & 0x80) | ((*src3 & 0x80) >> 1) | ((*src2 & 0x80) >> 2) | ((*src1 & 0x80) >> 3) | + ((*src4 & 0x40) >> 3) | ((*src3 & 0x40) >> 4) | ((*src2 & 0x40) >> 5) | ((*src1 & 0x40) >> 6); + // Pixels 2 and 3 + dest[1] = ((*src4 & 0x20) << 2) | ((*src3 & 0x20) << 1) | ((*src2 & 0x20)) | ((*src1 & 0x20) >> 1) | + ((*src4 & 0x10) >> 1) | ((*src3 & 0x10) >> 2) | ((*src2 & 0x10) >> 3) | ((*src1 & 0x10) >> 4); + // Pixels 4 and 5 + dest[2] = ((*src4 & 0x08) << 4) | ((*src3 & 0x08) << 3) | ((*src2 & 0x08) << 2) | ((*src1 & 0x08) << 1) | + ((*src4 & 0x04) << 1) | ((*src3 & 0x04)) | ((*src2 & 0x04) >> 1) | ((*src1 & 0x04) >> 2); + // Pixels 6 and 7 + dest[3] = ((*src4 & 0x02) << 6) | ((*src3 & 0x02) << 5) | ((*src2 & 0x02) << 4) | ((*src1 & 0x02) << 3) | + ((*src4 & 0x01) << 3) | ((*src3 & 0x01) << 2) | ((*src2 & 0x01) << 1) | ((*src1 & 0x01)); + dest += 4; + src1 += 1; + src2 += 1; + src3 += 1; + src4 += 1; + } + } +} + +//========================================================================== +// +// ST_Util_DrawBlock +// +//========================================================================== + +void ST_Util_DrawBlock(BitmapInfo* bitmap_info, const uint8_t* src, int x, int y, int bytewidth, int height) +{ + if (src == NULL) + { + return; + } + + int pitchshift = int(bitmap_info->bmiHeader.biBitCount == 4); + int destpitch = bitmap_info->bmiHeader.biWidth >> pitchshift; + uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch; + + ST_Util_InvalidateRect(bitmap_info, x, y, x + (bytewidth << pitchshift), y + height); + + if (bytewidth == 8) + { // progress notches + for (; height > 0; --height) + { + ((uint32_t*)dest)[0] = ((const uint32_t*)src)[0]; + ((uint32_t*)dest)[1] = ((const uint32_t*)src)[1]; + dest += destpitch; + src += 8; + } + } + else if (bytewidth == 2) + { // net progress notches + for (; height > 0; --height) + { + *((uint16_t*)dest) = *((const uint16_t*)src); + dest += destpitch; + src += 2; + } + } + else + { + for (; height > 0; --height) + { + memcpy(dest, src, bytewidth); + dest += destpitch; + src += bytewidth; + } + } +} + +//========================================================================== +// +// ST_Util_ClearBlock +// +//========================================================================== + +void ST_Util_ClearBlock(BitmapInfo* bitmap_info, uint8_t fill, int x, int y, int bytewidth, int height) +{ + int pitchshift = int(bitmap_info->bmiHeader.biBitCount == 4); + int destpitch = bitmap_info->bmiHeader.biWidth >> pitchshift; + uint8_t* dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch; + + ST_Util_InvalidateRect(bitmap_info, x, y, x + (bytewidth << pitchshift), y + height); + + while (height > 0) + { + memset(dest, fill, bytewidth); + dest += destpitch; + height--; + } +} + +//========================================================================== +// +// ST_Util_CreateBitmap +// +// Creates a BitmapInfoHeader, RgbQuad, and pixel data arranged +// consecutively in memory (in other words, a normal Windows BMP file). +// The BitmapInfoHeader will be filled in, and the caller must fill +// in the color and pixel data. +// +// You must pass 4 or 8 for color_bits. +// +//========================================================================== + +BitmapInfo* ST_Util_CreateBitmap(int width, int height, int color_bits) +{ + uint32_t size_image = (width * height) >> int(color_bits == 4); + BitmapInfo* bitmap_info = (BitmapInfo*)M_Malloc(sizeof(BitmapInfoHeader) + + (sizeof(RgbQuad) << color_bits) + size_image); + + // Initialize the header. + bitmap_info->bmiHeader.biSize = sizeof(BitmapInfoHeader); + bitmap_info->bmiHeader.biWidth = width; + bitmap_info->bmiHeader.biHeight = height; + bitmap_info->bmiHeader.biPlanes = 1; + bitmap_info->bmiHeader.biBitCount = color_bits; + bitmap_info->bmiHeader.biCompression = 0; + bitmap_info->bmiHeader.biSizeImage = size_image; + bitmap_info->bmiHeader.biXPelsPerMeter = 0; + bitmap_info->bmiHeader.biYPelsPerMeter = 0; + bitmap_info->bmiHeader.biClrUsed = 1 << color_bits; + bitmap_info->bmiHeader.biClrImportant = 0; + + return bitmap_info; +} + +//========================================================================== +// +// ST_Util_BitsForBitmap +// +// Given a bitmap created by ST_Util_CreateBitmap, returns the start +// address for the pixel data for the bitmap. +// +//========================================================================== + +uint8_t* ST_Util_BitsForBitmap(BitmapInfo* bitmap_info) +{ + return (uint8_t*)bitmap_info + sizeof(BitmapInfoHeader) + (sizeof(RgbQuad) << bitmap_info->bmiHeader.biBitCount); +} + +//========================================================================== +// +// ST_Util_FreeBitmap +// +// Frees all the data for a bitmap created by ST_Util_CreateBitmap. +// +//========================================================================== + +void ST_Util_FreeBitmap(BitmapInfo* bitmap_info) +{ + M_Free(bitmap_info); +} + +//========================================================================== +// +// ST_Util_BitmapColorsFromPlaypal +// +// Fills the bitmap palette from the PLAYPAL lump. +// +//========================================================================== + +void ST_Util_BitmapColorsFromPlaypal(BitmapInfo* bitmap_info) +{ + uint8_t playpal[768]; + + ReadPalette(fileSystem.GetNumForName("PLAYPAL"), playpal); + for (int i = 0; i < 256; ++i) + { + bitmap_info->bmiColors[i].rgbBlue = playpal[i * 3 + 2]; + bitmap_info->bmiColors[i].rgbGreen = playpal[i * 3 + 1]; + bitmap_info->bmiColors[i].rgbRed = playpal[i * 3]; + bitmap_info->bmiColors[i].rgbReserved = 0; + } +} + +//========================================================================== +// +// ST_Util_LoadFont +// +// Loads a monochrome fixed-width font. Every character is one byte +// (eight pixels) wide, so we can deduce the height of each character +// by looking at the size of the font data. +// +//========================================================================== + +uint8_t* ST_Util_LoadFont(const char* filename) +{ + int lumpnum, lumplen, height; + uint8_t* font; + + lumpnum = fileSystem.CheckNumForFullName(filename); + if (lumpnum < 0) + { // font not found + return NULL; + } + lumplen = fileSystem.FileLength(lumpnum); + height = lumplen / 256; + if (height * 256 != lumplen) + { // font is a bad size + return NULL; + } + if (height < 6 || height > 36) + { // let's be reasonable here + return NULL; + } + font = new uint8_t[lumplen + 1]; + font[0] = height; // Store font height in the first byte. + fileSystem.ReadFile(lumpnum, font + 1); + return font; +} + +void ST_Util_FreeFont(uint8_t* font) +{ + delete[] font; +} + +//========================================================================== +// +// ST_Util_AllocTextBitmap +// +// Returns a bitmap properly sized to hold an 80x25 display of characters +// using the specified font. +// +//========================================================================== + +BitmapInfo* ST_Util_AllocTextBitmap(const uint8_t* font) +{ + BitmapInfo* bitmap = ST_Util_CreateBitmap(80 * 8, 25 * font[0], 4); + memcpy(bitmap->bmiColors, TextModePalette, sizeof(TextModePalette)); + return bitmap; +} + +//========================================================================== +// +// ST_Util_DrawTextScreen +// +// Draws the text screen to the bitmap. The bitmap must be the proper size +// for the font. +// +//========================================================================== + +void ST_Util_DrawTextScreen(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font) +{ + int x, y; + + for (y = 0; y < 25; ++y) + { + for (x = 0; x < 80; ++x) + { + ST_Util_DrawChar(bitmap_info, font, x, y, text_screen[0], text_screen[1]); + text_screen += 2; + } + } +} + +//========================================================================== +// +// ST_Util_DrawChar +// +// Draws a character on the bitmap. X and Y specify the character cell, +// and fg and bg are 4-bit colors. +// +//========================================================================== + +void ST_Util_DrawChar(BitmapInfo* screen, const uint8_t* font, int x, int y, uint8_t charnum, uint8_t attrib) +{ + const uint8_t bg_left = attrib & 0x70; + const uint8_t fg = attrib & 0x0F; + const uint8_t fg_left = fg << 4; + const uint8_t bg = bg_left >> 4; + const uint8_t color_array[4] = { (uint8_t)(bg_left | bg), (uint8_t)(attrib & 0x7F), (uint8_t)(fg_left | bg), (uint8_t)(fg_left | fg) }; + const uint8_t* src = font + 1 + charnum * font[0]; + int pitch = screen->bmiHeader.biWidth >> 1; + uint8_t* dest = ST_Util_BitsForBitmap(screen) + x * 4 + y * font[0] * pitch; + + for (y = font[0]; y > 0; --y) + { + uint8_t srcbyte = *src++; + + // Pixels 0 and 1 + dest[0] = color_array[(srcbyte >> 6) & 3]; + // Pixels 2 and 3 + dest[1] = color_array[(srcbyte >> 4) & 3]; + // Pixels 4 and 5 + dest[2] = color_array[(srcbyte >> 2) & 3]; + // Pixels 6 and 7 + dest[3] = color_array[(srcbyte) & 3]; + dest += pitch; + } +} + +//========================================================================== +// +// ST_Util_UpdateTextBlink +// +// Draws the parts of the text screen that blink to the bitmap. The bitmap +// must be the proper size for the font. +// +//========================================================================== + +void ST_Util_UpdateTextBlink(BitmapInfo* bitmap_info, const uint8_t* text_screen, const uint8_t* font, bool on) +{ + int x, y; + + for (y = 0; y < 25; ++y) + { + for (x = 0; x < 80; ++x) + { + if (text_screen[1] & 0x80) + { + ST_Util_DrawChar(bitmap_info, font, x, y, on ? text_screen[0] : ' ', text_screen[1]); + ST_Util_InvalidateRect(bitmap_info, x * 8, y * font[0], x * 8 + 8, y * font[0] + font[0]); + } + text_screen += 2; + } + } +} diff --git a/source/platform/win32/win32basevideo.cpp b/source/platform/win32/win32basevideo.cpp index c400ad4a7..bb1fb81ba 100644 --- a/source/platform/win32/win32basevideo.cpp +++ b/source/platform/win32/win32basevideo.cpp @@ -38,6 +38,7 @@ #include "gl_sysfb.h" #include "hardware.h" +#include "x86.h" #include "templates.h" #include "version.h" #include "c_console.h" @@ -46,6 +47,7 @@ #include "i_system.h" #include "v_text.h" #include "m_argv.h" +#include "engineerrors.h" #include "printf.h" #include "win32basevideo.h" #include "cmdlib.h" @@ -167,7 +169,7 @@ static BOOL CALLBACK DumpAdaptersMonitorEnumProc(HMONITOR hMonitor, HDC, LPRECT, { bool primary = !!(mi.dwFlags & MONITORINFOF_PRIMARY); - snprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s", + mysnprintf(moreinfo, countof(moreinfo), " [%ldx%ld @ (%ld,%ld)]%s", mi.rcMonitor.right - mi.rcMonitor.left, mi.rcMonitor.bottom - mi.rcMonitor.top, mi.rcMonitor.left, mi.rcMonitor.top, diff --git a/source/platform/win32/win32glvideo.cpp b/source/platform/win32/win32glvideo.cpp index 37be0d154..80dadfd0e 100644 --- a/source/platform/win32/win32glvideo.cpp +++ b/source/platform/win32/win32glvideo.cpp @@ -40,6 +40,7 @@ #include "gl_sysfb.h" #include "hardware.h" +#include "x86.h" #include "templates.h" #include "version.h" #include "c_console.h" @@ -49,6 +50,7 @@ #include "v_text.h" #include "m_argv.h" #include "printf.h" +#include "engineerrors.h" #include "win32glvideo.h" #include "gl/system/gl_framebuffer.h" @@ -407,7 +409,6 @@ bool Win32GLVideo::InitHardware(HWND Window, int multisample) int prof = WGL_CONTEXT_CORE_PROFILE_BIT_ARB; const char *version = Args->CheckValue("-glversion"); - //prof = WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; // At the moment the renderer still needs the compatibility profile. for (; prof <= WGL_CONTEXT_COMPATIBILITY_PROFILE_BIT_ARB; prof++) { diff --git a/source/rr/src/d_menu.cpp b/source/rr/src/d_menu.cpp index 50bb444de..035365e3a 100644 --- a/source/rr/src/d_menu.cpp +++ b/source/rr/src/d_menu.cpp @@ -662,7 +662,7 @@ bool GameInterface::CanSave() return true; } -void GameInterface::StartGame(FGameStartup& gs) +void GameInterface::StartGame(FNewGameStartup& gs) { int32_t skillsound = PISTOL_BODYHIT; diff --git a/source/rr/src/duke3d.h b/source/rr/src/duke3d.h index 5297c50a7..dc27cbe4c 100644 --- a/source/rr/src/duke3d.h +++ b/source/rr/src/duke3d.h @@ -225,7 +225,7 @@ struct GameInterface : ::GameInterface void MenuSound(EMenuSounds snd) override; void MenuClosed() override; bool CanSave() override; - void StartGame(FGameStartup& gs) override; + void StartGame(FNewGameStartup& gs) override; FSavegameInfo GetSaveSig() override; void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override; void DrawMenuCaption(const DVector2& origin, const char* text) override; diff --git a/source/rr/src/game.cpp b/source/rr/src/game.cpp index 3e6476d67..aba0efbf7 100644 --- a/source/rr/src/game.cpp +++ b/source/rr/src/game.cpp @@ -924,7 +924,7 @@ void G_DrawRooms(int32_t playerNum, int32_t smoothRatio) if (RRRA && pPlayer->drug_mode > 0) { - while (pPlayer->drug_timer < totalclock && !(pPlayer->gm & MODE_MENU) && !ud.pause_on && !GUICapture) + while (pPlayer->drug_timer < totalclock && !(pPlayer->gm & MODE_MENU) && !ud.pause_on && !System_WantGuiCapture()) { int aspect; if (pPlayer->drug_stat[0] == 0) @@ -5850,7 +5850,7 @@ void G_HandleLocalKeys(void) } } - if (g_player[myconnectindex].ps->cheat_phase == 1 || (g_player[myconnectindex].ps->gm&(MODE_MENU|MODE_TYPE)) || GUICapture) + if (g_player[myconnectindex].ps->cheat_phase == 1 || (g_player[myconnectindex].ps->gm&(MODE_MENU|MODE_TYPE)) || System_WantGuiCapture()) return; if (buttonMap.ButtonDown(gamefunc_See_Coop_View) && (GTFLAGS(GAMETYPE_COOPVIEW) || ud.recstat == 2)) @@ -7335,7 +7335,7 @@ MAIN_LOOP_RESTART: g_player[myconnectindex].movefifoend++; - if (((g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU || ud.recstat == 2 || (g_netServer || ud.multimode > 1)) && + if (((!System_WantGuiCapture() && (g_player[myconnectindex].ps->gm&MODE_MENU) != MODE_MENU) || ud.recstat == 2 || (g_netServer || ud.multimode > 1)) && (g_player[myconnectindex].ps->gm&MODE_GAME)) { G_MoveLoop(); diff --git a/source/rr/src/net.cpp b/source/rr/src/net.cpp index d3473ceb5..d01e79189 100644 --- a/source/rr/src/net.cpp +++ b/source/rr/src/net.cpp @@ -1775,7 +1775,7 @@ void Net_GetInput(void) if (numplayers > 1) Net_GetPackets(); - if (g_player[myconnectindex].movefifoend - movefifoplc >= 100 || GUICapture) + if (g_player[myconnectindex].movefifoend - movefifoplc >= 100 || System_WantGuiCapture()) return; if (RRRA && g_player[myconnectindex].ps->on_motorcycle) diff --git a/source/sw/src/d_menu.cpp b/source/sw/src/d_menu.cpp index eb0ca4f07..e82e4a92d 100644 --- a/source/sw/src/d_menu.cpp +++ b/source/sw/src/d_menu.cpp @@ -212,7 +212,7 @@ bool GameInterface::CanSave() return (!CommEnabled && numplayers ==1 && !DemoMode && !InMenuLevel && !TEST(Player[myconnectindex].Flags, PF_DEAD)); } -void GameInterface::StartGame(FGameStartup& gs) +void GameInterface::StartGame(FNewGameStartup& gs) { PLAYERp pp = Player + screenpeek; int handle = 0; diff --git a/source/sw/src/game.h b/source/sw/src/game.h index 2734e58e5..d406ef594 100644 --- a/source/sw/src/game.h +++ b/source/sw/src/game.h @@ -2545,7 +2545,7 @@ struct GameInterface : ::GameInterface void MenuSound(EMenuSounds snd) override; void MenuClosed() override; bool CanSave() override; - void StartGame(FGameStartup& gs) override; + void StartGame(FNewGameStartup& gs) override; FSavegameInfo GetSaveSig() override; void DrawMenuCaption(const DVector2& origin, const char* text) override; void DrawCenteredTextScreen(const DVector2& origin, const char* text, int position, bool bg) override;