From 560d4f81404344dd8ed28ce3bdcfd2d483dff297 Mon Sep 17 00:00:00 2001 From: Randy Heit Date: Tue, 6 Mar 2007 01:33:18 +0000 Subject: [PATCH] - Fixed: Thing_ProjectileAimed did not set the missile's speed correctly. - The net start pane is now given focus when it is created, so it can receive keyboard input. - Added playback of the "WeaponPickup" sound when a Hexen net game starts. - Separated the different startup screens into classes for better modularization (which I should have done in the first place). (Sorry, have not done it for Linux yet, so that won't compile as-is.) SVN r496 (trunk) --- docs/rh-log.txt | 10 + src/d_main.cpp | 43 +-- src/d_net.cpp | 8 +- src/g_level.cpp | 2 +- src/i_net.cpp | 48 +-- src/p_things.cpp | 2 +- src/r_data.cpp | 14 +- src/st_start.h | 33 +- src/textures/buildtexture.cpp | 2 +- src/textures/multipatchtexture.cpp | 2 +- src/win32/i_main.cpp | 11 +- src/win32/st_start.cpp | 514 ++++++++++++++++------------- 12 files changed, 378 insertions(+), 311 deletions(-) diff --git a/docs/rh-log.txt b/docs/rh-log.txt index e44cf3c6f..a81f110b5 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,13 @@ +March 5, 2007 +- Fixed: Thing_ProjectileAimed did not set the missile's speed correctly. + +March 3, 2007 +- The net start pane is now given focus when it is created, so it can + receive keyboard input. +- Added playback of the "WeaponPickup" sound when a Hexen net game starts. +- Separated the different startup screens into classes for better + modularization (which I should have done in the first place). + February 28, 2007 - Changed the net start pane to open underneath the existing window instead of scrunching the startup screen up to make room for it. diff --git a/src/d_main.cpp b/src/d_main.cpp index e42692d71..12a0a791a 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -2080,7 +2080,7 @@ void D_DoomMain (void) S_Init (); Printf ("ST_Init: Init startup screen.\n"); - ST_Init (R_GuesstimateNumTextures() + 5); + StartScreen = FStartupScreen::CreateInstance (R_GuesstimateNumTextures() + 5); Printf ("P_Init: Checking cmd-line parameters...\n"); flags = dmflags; @@ -2208,21 +2208,21 @@ void D_DoomMain (void) timelimit = 20.f; } - // - // Build status bar line! - // - if (deathmatch) - ST_HereticStatus("DeathMatch..."); - if (dmflags & DF_NO_MONSTERS) - ST_HereticStatus("No Monsters..."); - if (dmflags & DF_MONSTERS_RESPAWN) - ST_HereticStatus("Respawning..."); - if (autostart) - { - FString temp; - temp.Format ("Warp to map %s, Skill %d ", startmap, gameskill + 1); - ST_HereticStatus (temp); - } + // + // Build status bar line! + // + if (deathmatch) + StartScreen->AppendStatusLine("DeathMatch..."); + if (dmflags & DF_NO_MONSTERS) + StartScreen->AppendStatusLine("No Monsters..."); + if (dmflags & DF_MONSTERS_RESPAWN) + StartScreen->AppendStatusLine("Respawning..."); + if (autostart) + { + FString temp; + temp.Format ("Warp to map %s, Skill %d ", startmap, gameskill + 1); + StartScreen->AppendStatusLine(temp); + } // [RH] Now that all text strings are set up, // insert them into the level and cluster data. @@ -2251,10 +2251,10 @@ void D_DoomMain (void) } FActorInfo::StaticGameSet (); - ST_Progress (); + StartScreen->Progress (); Printf ("R_Init: Init %s refresh subsystem.\n", GameNames[gameinfo.gametype]); - ST_HereticMessage ("Loading graphics", 0x3f); + StartScreen->LoadingStatus ("Loading graphics", 0x3f); R_Init (); Printf ("DecalLibrary: Load decals.\n"); @@ -2322,11 +2322,11 @@ void D_DoomMain (void) M_Init (); Printf ("P_Init: Init Playloop state.\n"); - ST_HereticMessage ("Init game engine", 0x3f); + StartScreen->LoadingStatus ("Init game engine", 0x3f); P_Init (); Printf ("D_CheckNetGame: Checking network game status.\n"); - ST_HereticMessage ("Checking network game status.", 0x3f); + StartScreen->LoadingStatus ("Checking network game status.", 0x3f); D_CheckNetGame (); // [RH] Lock any cvars that should be locked now that we're @@ -2350,7 +2350,8 @@ void D_DoomMain (void) autostart = true; } - ST_Done(); + delete StartScreen; + StartScreen = NULL; V_Init2(); files = Args.GatherFiles ("-playdemo", ".lmp", false); diff --git a/src/d_net.cpp b/src/d_net.cpp index 2ad61972e..18fac8f64 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -1358,7 +1358,7 @@ bool DoArbitrate (void *userdata) D_ReadUserInfoStrings (netbuffer[1], &stream, false); - ST_NetMessage ("Found %s (node %d, player %d)", + StartScreen->NetMessage ("Found %s (node %d, player %d)", players[netbuffer[1]].userinfo.netname, node, netbuffer[1]+1); } @@ -1503,8 +1503,8 @@ void D_ArbitrateNetStart (void) data.gotsetup[0] = 0x80; } - ST_NetInit ("Exchanging game information", 1); - if (!ST_NetLoop (DoArbitrate, &data)) + StartScreen->NetInit ("Exchanging game information", 1); + if (!StartScreen->NetLoop (DoArbitrate, &data)) { exit (0); } @@ -1522,7 +1522,7 @@ void D_ArbitrateNetStart (void) fprintf (debugfile, "player %d is on node %d\n", i, nodeforplayer[i]); } } - ST_NetDone(); + StartScreen->NetDone(); } static void SendSetup (DWORD playersdetected[MAXNETNODES], BYTE gotsetup[MAXNETNODES], int len) diff --git a/src/g_level.cpp b/src/g_level.cpp index 8ded9730d..960313c83 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1643,7 +1643,7 @@ static void goOn (int position, bool keepFacing, bool secret, bool resetinv) if (thiscluster && (thiscluster->flags & CLUSTER_HUB)) { if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster)) - NoWipe = 4; + NoWipe = 35; D_DrawIcon = "TELEICON"; } diff --git a/src/i_net.cpp b/src/i_net.cpp index ecbf66d62..1ea41f7d8 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -224,7 +224,7 @@ void PacketGet (void) if (err == WSAECONNRESET) { // The remote node aborted unexpectedly, so pretend it sent an exit packet - ST_NetMessage ("The connection from %s was dropped.\n", + StartScreen->NetMessage ("The connection from %s was dropped.\n", players[sendplayer[node]].userinfo.netname); doomcom.data[0] = 0x80; // NCMD_EXIT @@ -401,7 +401,7 @@ static void SendConAck (int num_connected, int num_needed) { PreSend (&packet, 4, &sendaddress[node]); } - ST_NetProgress (doomcom.numnodes); + StartScreen->NetProgress (doomcom.numnodes); } bool Host_CheckForConnects (void *userdata) @@ -426,7 +426,7 @@ bool Host_CheckForConnects (void *userdata) if (node == -1) { const BYTE *s_addr_bytes = (const BYTE *)&from->sin_addr; - ST_NetMessage ("Got extra connect from %d.%d.%d.%d:%d", + StartScreen->NetMessage ("Got extra connect from %d.%d.%d.%d:%d", s_addr_bytes[0], s_addr_bytes[1], s_addr_bytes[2], s_addr_bytes[3], from->sin_port); packet.Message = PRE_ALLFULL; @@ -439,7 +439,7 @@ bool Host_CheckForConnects (void *userdata) { node = doomcom.numnodes++; sendaddress[node] = *from; - ST_NetMessage ("Got connect from node %d.", node); + StartScreen->NetMessage ("Got connect from node %d.", node); } // Let the new guest (and everyone else) know we got their message. @@ -451,7 +451,7 @@ bool Host_CheckForConnects (void *userdata) node = FindNode (from); if (node >= 0) { - ST_NetMessage ("Got disconnect from node %d.", node); + StartScreen->NetMessage ("Got disconnect from node %d.", node); doomcom.numnodes--; while (node < doomcom.numnodes) { @@ -590,20 +590,20 @@ void HostGame (int i) atterm (SendAbort); - ST_NetInit ("Waiting for players", numplayers); + StartScreen->NetInit ("Waiting for players", numplayers); // Wait for numplayers-1 different connections - if (!ST_NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) + if (!StartScreen->NetLoop (Host_CheckForConnects, (void *)(intptr_t)numplayers)) { exit (0); } // Now inform everyone of all machines involved in the game memset (gotack, 0, sizeof(gotack)); - ST_NetMessage ("Sending all here."); - ST_NetInit ("Done waiting", 1); + StartScreen->NetMessage ("Sending all here."); + StartScreen->NetInit ("Done waiting", 1); - if (!ST_NetLoop (Host_SendAllHere, (void *)gotack)) + if (!StartScreen->NetLoop (Host_SendAllHere, (void *)gotack)) { exit (0); } @@ -611,7 +611,7 @@ void HostGame (int i) popterm (); // Now go - ST_NetMessage ("Go"); + StartScreen->NetMessage ("Go"); packet.Fake = PRE_FAKE; packet.Message = PRE_GO; for (node = 1; node < doomcom.numnodes; node++) @@ -624,7 +624,7 @@ void HostGame (int i) } } - ST_NetMessage ("Total players: %d", doomcom.numnodes); + StartScreen->NetMessage ("Total players: %d", doomcom.numnodes); doomcom.id = DOOMCOM_ID; doomcom.numplayers = doomcom.numnodes; @@ -657,9 +657,9 @@ bool Guest_ContactHost (void *userdata) { if (packet.Message == PRE_CONACK) { - ST_NetMessage ("Total players: %d", packet.NumNodes); - ST_NetInit ("Waiting for other players", packet.NumNodes); - ST_NetProgress (packet.NumPresent); + StartScreen->NetMessage ("Total players: %d", packet.NumNodes); + StartScreen->NetInit ("Waiting for other players", packet.NumNodes); + StartScreen->NetProgress (packet.NumPresent); return true; } else if (packet.Message == PRE_DISCONNECT) @@ -676,7 +676,7 @@ bool Guest_ContactHost (void *userdata) } // In case the progress bar could not be marqueed, bump it. - ST_NetProgress (0); + StartScreen->NetProgress (0); return false; } @@ -695,7 +695,7 @@ bool Guest_WaitForOthers (void *userdata) switch (packet.Message) { case PRE_CONACK: - ST_NetProgress (packet.NumPresent); + StartScreen->NetProgress (packet.NumPresent); break; case PRE_ALLHERE: @@ -707,7 +707,7 @@ bool Guest_WaitForOthers (void *userdata) doomcom.numnodes = packet.NumNodes + 2; sendplayer[0] = packet.ConsoleNum; // My player number doomcom.consoleplayer = packet.ConsoleNum; - ST_NetMessage ("Console player number: %d", doomcom.consoleplayer); + StartScreen->NetMessage ("Console player number: %d", doomcom.consoleplayer); for (node = 0; node < packet.NumNodes; node++) { sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address; @@ -721,14 +721,14 @@ bool Guest_WaitForOthers (void *userdata) } } - ST_NetMessage ("Received All Here, sending ACK."); + StartScreen->NetMessage ("Received All Here, sending ACK."); packet.Fake = PRE_FAKE; packet.Message = PRE_ALLHEREACK; PreSend (&packet, 2, &sendaddress[1]); break; case PRE_GO: - ST_NetMessage ("Received \"Go.\""); + StartScreen->NetMessage ("Received \"Go.\""); return true; case PRE_DISCONNECT: @@ -757,22 +757,22 @@ void JoinGame (int i) atterm (SendAbort); // Let host know we are here - ST_NetInit ("Contacting host", 0); + StartScreen->NetInit ("Contacting host", 0); - if (!ST_NetLoop (Guest_ContactHost, NULL)) + if (!StartScreen->NetLoop (Guest_ContactHost, NULL)) { exit (0); } // Wait for everyone else to connect - if (!ST_NetLoop (Guest_WaitForOthers, 0)) + if (!StartScreen->NetLoop (Guest_WaitForOthers, 0)) { exit (0); } popterm (); - ST_NetMessage ("Total players: %d", doomcom.numnodes); + StartScreen->NetMessage ("Total players: %d", doomcom.numnodes); doomcom.id = DOOMCOM_ID; doomcom.numplayers = doomcom.numnodes; diff --git a/src/p_things.cpp b/src/p_things.cpp index 3070ebda5..d2643be54 100644 --- a/src/p_things.cpp +++ b/src/p_things.cpp @@ -328,7 +328,7 @@ nolead: mobj->angle = R_PointToAngle2 (mobj->x, mobj->y, targ->x, targ->y); // Set the missile's speed to reflect the speed it was spawned at. if (mobj->flags & MF_MISSILE) { - mobj->Speed = fixed_t (sqrtf (float(speed*speed + vspeed*vspeed))); + mobj->Speed = fixed_t (sqrt (double(mobj->momx)*mobj->momx + double(mobj->momy)*mobj->momy + double(mobj->momz)*mobj->momz)); } // Hugger missiles don't have any vertical velocity if (mobj->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)) diff --git a/src/r_data.cpp b/src/r_data.cpp index ce0f20920..49b5c2dd1 100644 --- a/src/r_data.cpp +++ b/src/r_data.cpp @@ -297,7 +297,7 @@ void FTextureManager::AddGroup(const char * startlump, const char * endlump, int { CreateTexture (firsttx, usetype); } - ST_Progress(); + StartScreen->Progress(); } } @@ -353,7 +353,7 @@ void FTextureManager::AddHiresTextures () newtex->TopOffset = Scale(oldtex->TopOffset, newtex->ScaleY, 8); ReplaceTexture(oldtexno, newtex, true); } - ST_Progress(); + StartScreen->Progress(); } } } @@ -479,7 +479,7 @@ void FTextureManager::AddPatches (int lumpnum) { CreateTexture (Wads.CheckNumForName (name, ns_patches), FTexture::TEX_WallPatch); } - ST_Progress(); + StartScreen->Progress(); } delete file; @@ -729,10 +729,10 @@ DWORD R_BlendForColormap (DWORD map) void R_InitData () { FTexture::InitGrayMap(); - ST_Progress(); + StartScreen->Progress(); TexMan.AddGroup("S_START", "S_END", ns_sprites, FTexture::TEX_Sprite); R_InitPatches (); // Initializes "special" textures that have no external references - ST_Progress(); + StartScreen->Progress(); R_InitTextures (); TexMan.AddGroup("F_START", "F_END", ns_flats, FTexture::TEX_Flat); R_InitBuildTiles (); @@ -741,9 +741,9 @@ void R_InitData () TexMan.LoadHiresTex (); TexMan.DefaultTexture = TexMan.CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0); V_InitFonts(); - ST_Progress(); + StartScreen->Progress(); R_InitColormaps (); - ST_Progress(); + StartScreen->Progress(); } //=========================================================================== diff --git a/src/st_start.h b/src/st_start.h index e14a96dd8..3b90aa06f 100644 --- a/src/st_start.h +++ b/src/st_start.h @@ -34,14 +34,27 @@ ** Actual implementation is system-specific. */ -extern void ST_Init(int maxProgress); -extern void (*ST_Done)(); -extern void (*ST_Progress)(); -extern void (*ST_HereticMessage)(const char *message, int attributes); -extern void (*ST_HereticStatus)(const char *status); -extern void (*ST_NetInit)(const char *message, int numplayers); -extern void (*ST_NetProgress)(int count); -extern void (*ST_NetMessage)(const char *format, ...); // cover for printf() -extern void (*ST_NetDone)(); -extern bool (*ST_NetLoop)(bool (*timer_callback)(void *), void *userdata); +class FStartupScreen +{ +public: + static FStartupScreen *CreateInstance(int max_progress); + + FStartupScreen(int max_progress); + virtual ~FStartupScreen(); + + virtual void Progress() = 0; + virtual void LoadingStatus(const char *message, int colors); // Used by Heretic only + virtual void AppendStatusLine(const char *status); // Used by Heretic only + + virtual void NetInit(const char *message, int num_players) = 0; + virtual void NetProgress(int count) = 0; + virtual void NetMessage(const char *format, ...) = 0; // cover for printf + virtual void NetDone() = 0; + virtual bool NetLoop(bool (*timer_callback)(void *), void *userdata) = 0; +protected: + int MaxPos, CurPos, NotchPos; +}; + +extern FStartupScreen *StartScreen; + extern void ST_Endoom(); diff --git a/src/textures/buildtexture.cpp b/src/textures/buildtexture.cpp index f8c4e0a36..330aca51d 100644 --- a/src/textures/buildtexture.cpp +++ b/src/textures/buildtexture.cpp @@ -138,7 +138,7 @@ static void AddTiles (void *tiles) tiledata++; size--; } - ST_Progress(); + StartScreen->Progress(); if ((picanm[pic] & 63) && (picanm[pic] & 192)) { diff --git a/src/textures/multipatchtexture.cpp b/src/textures/multipatchtexture.cpp index f6e33af78..7b1c6d9b5 100644 --- a/src/textures/multipatchtexture.cpp +++ b/src/textures/multipatchtexture.cpp @@ -512,7 +512,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int p tex->UseType = FTexture::TEX_Null; } TexMan.AddTexture (tex); - ST_Progress(); + StartScreen->Progress(); } } } diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 27880f324..ce5b97592 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -653,9 +653,10 @@ void RestoreConView() ShowWindow (GameTitleWindow, SW_SHOW); I_ShutdownInput (); // Make sure the mouse pointer is available. // Make sure the progress bar isn't visible. - if (ST_Done != NULL) + if (StartScreen != NULL) { - ST_Done(); + delete StartScreen; + StartScreen = NULL; } } @@ -678,7 +679,11 @@ void ShowErrorPane(const char *text) } SetWindowText (Window, "Fatal Error - " WINDOW_TITLE); - if (ST_NetDone != NULL) ST_NetDone(); // Ensure that the network pane is hidden. + if (StartScreen != NULL) // Ensure that the network pane is hidden. + { + delete StartScreen; + StartScreen = NULL; + } ErrorIcon = CreateWindowEx (WS_EX_NOPARENTNOTIFY, "STATIC", NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS | SS_OWNERDRAW, 0, 0, 0, 0, Window, NULL, g_hInst, NULL); if (ErrorIcon != NULL) { diff --git a/src/win32/st_start.cpp b/src/win32/st_start.cpp index d63854a17..5fa4ea433 100644 --- a/src/win32/st_start.cpp +++ b/src/win32/st_start.cpp @@ -106,6 +106,66 @@ // TYPES ------------------------------------------------------------------- +class FBasicStartupScreen : public FStartupScreen +{ +public: + FBasicStartupScreen(int max_progress, bool show_bar); + ~FBasicStartupScreen(); + + void Progress(); + void NetInit(const char *message, int num_players); + void NetProgress(int count); + void NetMessage(const char *format, ...); // cover for printf + void NetDone(); + bool NetLoop(bool (*timer_callback)(void *), void *userdata); +protected: + LRESULT NetMarqueeMode; + int NetMaxPos, NetCurPos; +}; + +class FGraphicalStartupScreen : public FBasicStartupScreen +{ +public: + FGraphicalStartupScreen(int max_progress); + ~FGraphicalStartupScreen(); +}; + +class FHereticStartupScreen : public FGraphicalStartupScreen +{ +public: + FHereticStartupScreen(int max_progress, HRESULT &hr); + + void Progress(); + void LoadingStatus(const char *message, int colors); + void AppendStatusLine(const char *status); +protected: + int ThermX, ThermY, ThermWidth, ThermHeight; + int HMsgY, SMsgX; +}; + +class FHexenStartupScreen : public FGraphicalStartupScreen +{ +public: + FHexenStartupScreen(int max_progress, HRESULT &hr); + + void Progress(); + void NetProgress(int count); + void NetDone(); +}; + +class FStrifeStartupScreen : public FGraphicalStartupScreen +{ +public: + FStrifeStartupScreen(int max_progress, HRESULT &hr); + ~FStrifeStartupScreen(); + + void Progress(); +protected: + void DrawStuff(int old_laser, int new_laser); + + BYTE *StartupPics[4+2+1]; +}; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- void RestoreConView(); @@ -134,32 +194,6 @@ void ST_Util_DrawChar (BITMAPINFO *screen, const BYTE *font, int x, int y, BYTE static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam); -static void ST_Basic_Init (); -static void ST_Basic_Done (); -static void ST_Basic_Progress (); -static void ST_Basic_HereticMessage (const char *message, int attributes); -static void ST_Basic_HereticStatus (const char *status); -static void ST_Basic_NetInit (const char *message, int numplayers); -static void ST_Basic_NetProgress (int count); -static void ST_Basic_NetMessage (const char *format, ...); -static void ST_Basic_NetDone (); -static bool ST_Basic_NetLoop (bool (*timer_callback)(void *), void *userdata); - -static void ST_Hexen_Init (); -static void ST_Hexen_Done (); -static void ST_Hexen_Progress (); -static void ST_Hexen_NetProgress (int count); - -static void ST_Heretic_Init (); -static void ST_Heretic_Progress (); -static void ST_Heretic_Message (const char *message, int attributes); -static void ST_Heretic_Status (const char *status); - -static void ST_Strife_Init (); -static void ST_Strife_Done (); -static void ST_Strife_Progress (); -static void ST_Strife_DrawStuff (int old_laser, int new_laser); - // EXTERNAL DATA DECLARATIONS ---------------------------------------------- extern HINSTANCE g_hInst; @@ -167,16 +201,7 @@ extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTit // PUBLIC DATA DEFINITIONS ------------------------------------------------- -void (*ST_Done)(); -void (*ST_Progress)(); -void (*ST_HereticMessage)(const char *message, int attributes); -void (*ST_HereticStatus)(const char *status); -void (*ST_NetInit)(const char *message, int numplayers); -void (*ST_NetProgress)(int count); -void (*ST_NetMessage)(const char *format, ...); -void (*ST_NetDone)(); -bool (*ST_NetLoop)(bool (*timer_callback)(void *), void *userdata); - +FStartupScreen *StartScreen; BITMAPINFO *StartupBitmap; CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) @@ -187,13 +212,6 @@ CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) // PRIVATE DATA DEFINITIONS ------------------------------------------------ -static int MaxPos, CurPos, NotchPos; -static int NetMaxPos, NetCurPos; -static LRESULT NetMarqueeMode; -static int ThermX, ThermY, ThermWidth, ThermHeight; -static int HMsgY, SMsgX; -static BYTE *StrifeStartupPics[4+2+1]; - static const char *StrifeStartupPicNames[4+2+1] = { "STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1", @@ -281,75 +299,123 @@ static const BYTE NetNotchBits[] = //========================================================================== // -// ST_Init +// FStartupScreen :: CreateInstance // // Initializes the startup screen for the detected game. // Sets the size of the progress bar and displays the startup screen. // //========================================================================== -void ST_Init(int maxProgress) +FStartupScreen *FStartupScreen::CreateInstance(int max_progress) { - MaxPos = maxProgress; - CurPos = 0; - NotchPos = 0; + FStartupScreen *scr = NULL; + HRESULT hr; if (gameinfo.gametype == GAME_Hexen) { - ST_Hexen_Init (); + scr = new FHexenStartupScreen(max_progress, hr); } else if (gameinfo.gametype == GAME_Heretic) { - ST_Heretic_Init (); + scr = new FHereticStartupScreen(max_progress, hr); } else if (gameinfo.gametype == GAME_Strife) { - ST_Strife_Init (); + scr = new FStrifeStartupScreen(max_progress, hr); } - else + if (scr != NULL && FAILED(hr)) { - ST_Basic_Init (); + delete scr; + scr = NULL; } + if (scr == NULL) + { + scr = new FBasicStartupScreen(max_progress, true); + } + return scr; } //========================================================================== // -// ST_Basic_Init +// FStartupScreen Constructor +// +//========================================================================== + +FStartupScreen::FStartupScreen(int max_progress) +{ + MaxPos = max_progress; + CurPos = 0; + NotchPos = 0; +} + +//========================================================================== +// +// FStartupScreen Destructor +// +//========================================================================== + +FStartupScreen::~FStartupScreen() +{ +} + +//========================================================================== +// +// FStartupScreen :: LoadingStatus +// +// Used by Heretic for the Loading Status "window." +// +//========================================================================== + +void FStartupScreen::LoadingStatus(const char *message, int colors) +{ +} + +//========================================================================== +// +// FStartupScreen :: AppendStatusLine +// +// Used by Heretic for the "status line" at the bottom of the screen. +// +//========================================================================== + +void FStartupScreen::AppendStatusLine(const char *status) +{ +} + +//========================================================================== +// +// FBasicStartupScreen Constructor // // Shows a progress bar at the bottom of the window. // //========================================================================== -static void ST_Basic_Init () +FBasicStartupScreen::FBasicStartupScreen(int max_progress, bool show_bar) +: FStartupScreen(max_progress) { - ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, - NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, - 0, 0, 0, 0, - Window, 0, g_hInst, NULL); - SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos)); - LayoutMainWindow (Window, NULL); - - ST_Done = ST_Basic_Done; - ST_Progress = ST_Basic_Progress; - ST_HereticMessage = ST_Basic_HereticMessage; - ST_HereticStatus = ST_Basic_HereticStatus; - ST_NetInit = ST_Basic_NetInit; - ST_NetProgress = ST_Basic_NetProgress; - ST_NetMessage = ST_Basic_NetMessage; - ST_NetDone = ST_Basic_NetDone; - ST_NetLoop = ST_Basic_NetLoop; + if (show_bar) + { + ProgressBar = CreateWindowEx(0, PROGRESS_CLASS, + NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, + 0, 0, 0, 0, + Window, 0, g_hInst, NULL); + SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos)); + LayoutMainWindow (Window, NULL); + } + NetMaxPos = 0; + NetCurPos = 0; } //========================================================================== // -// ST_Basic_Done +// FBasicStartupScreen Destructor // // Called just before entering graphics mode to deconstruct the startup // screen. // //========================================================================== -static void ST_Basic_Done() +FBasicStartupScreen::~FBasicStartupScreen() { if (ProgressBar != NULL) { @@ -361,13 +427,13 @@ static void ST_Basic_Done() //========================================================================== // -// ST_Basic_Progress +// FBasicStartupScreen :: Progress // // Bumps the progress meter one notch. // //========================================================================== -static void ST_Basic_Progress() +void FBasicStartupScreen::Progress() { if (CurPos < MaxPos) { @@ -378,31 +444,7 @@ static void ST_Basic_Progress() //========================================================================== // -// ST_Basic_HereticMessage -// -// Only used by the Heretic startup screen. -// -//========================================================================== - -static void ST_Basic_HereticMessage (const char *, int) -{ -} - -//========================================================================== -// -// ST_Basic_HereticStatus -// -// Only used by the Heretic startup screen. -// -//========================================================================== - -static void ST_Basic_HereticStatus (const char *) -{ -} - -//========================================================================== -// -// ST_Basic_NetInit +// FBasicStartupScreen :: NetInit // // Shows the network startup pane if it isn't visible. Sets the message in // the pane to the one provided. If numplayers is 0, then the progress bar @@ -412,7 +454,7 @@ static void ST_Basic_HereticStatus (const char *) // //========================================================================== -static void ST_Basic_NetInit(const char *message, int numplayers) +void FBasicStartupScreen::NetInit(const char *message, int numplayers) { NetMaxPos = numplayers; if (NetStartPane == NULL) @@ -430,6 +472,7 @@ static void ST_Basic_NetInit(const char *message, int numplayers) winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane (NetStartPane, 0), SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); LayoutMainWindow (Window, NULL); + SetFocus (NetStartPane); } if (NetStartPane != NULL) { @@ -470,18 +513,18 @@ static void ST_Basic_NetInit(const char *message, int numplayers) } NetMaxPos = numplayers; NetCurPos = 0; - ST_NetProgress(1); // You always know about yourself + NetProgress(1); // You always know about yourself } //========================================================================== // -// ST_Basic_NetDone +// FBasicStartupScreen :: NetDone // // Removes the network startup pane. // //========================================================================== -static void ST_Basic_NetDone() +void FBasicStartupScreen::NetDone() { if (NetStartPane != NULL) { @@ -493,15 +536,15 @@ static void ST_Basic_NetDone() //========================================================================== // -// ST_Basic_NetMessage +// FBasicStartupScreen :: NetMessage // -// Call this between ST_NetInit() and ST_NetDone() instead of Printf() to +// Call this between NetInit() and NetDone() instead of Printf() to // display messages, in case the progress meter is mixed in the same output // stream as normal messages. // //========================================================================== -static void ST_Basic_NetMessage(const char *format, ...) +void FBasicStartupScreen::NetMessage(const char *format, ...) { FString str; va_list argptr; @@ -514,14 +557,14 @@ static void ST_Basic_NetMessage(const char *format, ...) //========================================================================== // -// ST_Basic_NetProgress +// FBasicStartupScreen :: NetProgress // // Sets the network progress meter. If count is 0, it gets bumped by 1. // Otherwise, it is set to count. // //========================================================================== -static void ST_Basic_NetProgress(int count) +void FBasicStartupScreen :: NetProgress(int count) { if (count == 0) { @@ -552,7 +595,7 @@ static void ST_Basic_NetProgress(int count) //========================================================================== // -// ST_Basic_NetLoop +// FBasicStartupScreen :: NetLoop // // The timer_callback function is called at least two times per second // and passed the userdata value. It should return true to stop the loop and @@ -564,7 +607,7 @@ static void ST_Basic_NetProgress(int count) // //========================================================================== -static bool ST_Basic_NetLoop(bool (*timer_callback)(void *), void *userdata) +bool FBasicStartupScreen::NetLoop(bool (*timer_callback)(void *), void *userdata) { BOOL bRet; MSG msg; @@ -613,7 +656,7 @@ static bool ST_Basic_NetLoop(bool (*timer_callback)(void *), void *userdata) static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam) { - if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED) + if (msg == WM_COMMAND && HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDCANCEL) { PostQuitMessage (0); return TRUE; @@ -623,23 +666,58 @@ static INT_PTR CALLBACK NetStartPaneProc (HWND hDlg, UINT msg, WPARAM wParam, LP //========================================================================== // -// ST_Hexen_Init +// 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; + } +} + +//========================================================================== +// +// FHexenStartupScreen Constructor // // Shows the Hexen startup screen. If the screen doesn't appear to be -// valid, it falls back to ST_Basic_Init. +// 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. // //========================================================================== -static void ST_Hexen_Init () +FHexenStartupScreen::FHexenStartupScreen(int max_progress, HRESULT &hr) +: FGraphicalStartupScreen(max_progress) { int startup_lump = Wads.CheckNumForName ("STARTUP"); + hr = E_FAIL; if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 153648 || !ST_Util_CreateStartupWindow()) { - ST_Basic_Init (); return; } @@ -676,53 +754,20 @@ static void ST_Hexen_Init () LayoutMainWindow (Window, NULL); InvalidateRect (StartupScreen, NULL, TRUE); - ST_Done = ST_Hexen_Done; - ST_Progress = ST_Hexen_Progress; - ST_HereticMessage = ST_Basic_HereticMessage; - ST_HereticStatus = ST_Basic_HereticStatus; - ST_NetInit = ST_Basic_NetInit; - ST_NetProgress = ST_Hexen_NetProgress; - ST_NetMessage = ST_Basic_NetMessage; - ST_NetDone = ST_Basic_NetDone; - ST_NetLoop = ST_Basic_NetLoop; - - // Not that this screen will be around long enough for anyone to - // really hear the music, but start it anyway. S_ChangeMusic ("orb", true, true); + + hr = S_OK; } //========================================================================== // -// ST_Hexen_Done -// -// Called just before entering graphics mode to deconstruct the startup -// screen. -// -//========================================================================== - -static void ST_Hexen_Done() -{ - if (StartupScreen != NULL) - { - DestroyWindow (StartupScreen); - StartupScreen = NULL; - } - if (StartupBitmap != NULL) - { - ST_Util_FreeBitmap (StartupBitmap); - StartupBitmap = NULL; - } -} - -//========================================================================== -// -// ST_Hexen_Progress +// FHexenStartupScreen :: Progress // // Bumps the progress meter one notch. // //========================================================================== -static void ST_Hexen_Progress() +void FHexenStartupScreen::Progress() { int notch_pos, x, y; @@ -746,18 +791,18 @@ static void ST_Hexen_Progress() //========================================================================== // -// ST_Hexen_NetProgress +// FHexenStartupScreen :: NetProgress // // Draws the red net noches in addition to the normal progress bar. // //========================================================================== -static void ST_Hexen_NetProgress (int count) +void FHexenStartupScreen::NetProgress(int count) { int oldpos = NetCurPos; int x, y; - ST_Basic_NetProgress (count); + FGraphicalStartupScreen::NetProgress (count); if (NetMaxPos != 0 && NetCurPos > oldpos) { for (; oldpos < NetCurPos && oldpos < ST_MAX_NETNOTCHES; ++oldpos) @@ -773,25 +818,40 @@ static void ST_Hexen_NetProgress (int count) //========================================================================== // -// ST_Heretic_Init +// FHexenStartupScreen :: NetDone +// +// Aside from the standard processing, also plays a sound. +// +//========================================================================== + +void FHexenStartupScreen::NetDone() +{ + S_Sound (CHAN_BODY, "PickupWeapon", 1, ATTN_NORM); + FGraphicalStartupScreen::NetDone(); +} + +//========================================================================== +// +// FHereticStartupScreen Constructor // // Shows the Heretic startup screen. If the screen doesn't appear to be -// valid, it falls back to ST_Basic_Init. +// 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. // //========================================================================== -static void ST_Heretic_Init () +FHereticStartupScreen::FHereticStartupScreen(int max_progress, HRESULT &hr) +: FGraphicalStartupScreen(max_progress) { int loading_lump = Wads.CheckNumForName ("LOADING"); BYTE loading_screen[4000]; BYTE *font; + hr = E_FAIL; if (loading_lump < 0 || Wads.LumpLength (loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) { - ST_Basic_Init (); return; } @@ -799,7 +859,6 @@ static void ST_Heretic_Init () if (font == NULL) { DestroyWindow (StartupScreen); - ST_Basic_Init (); return; } @@ -826,27 +885,18 @@ static void ST_Heretic_Init () ST_Util_SizeWindowForBitmap (1); LayoutMainWindow (Window, NULL); InvalidateRect (StartupScreen, NULL, TRUE); - - ST_Done = ST_Hexen_Done; - ST_Progress = ST_Heretic_Progress; - ST_HereticMessage = ST_Heretic_Message; - ST_HereticStatus = ST_Heretic_Status; - ST_NetInit = ST_Basic_NetInit; - ST_NetProgress = ST_Basic_NetProgress; - ST_NetMessage = ST_Basic_NetMessage; - ST_NetDone = ST_Basic_NetDone; - ST_NetLoop = ST_Basic_NetLoop; + hr = S_OK; } //========================================================================== // -// ST_Heretic_Progress +// FHereticStartupScreen::Progress // // Bumps the progress meter one notch. // //========================================================================== -static void ST_Heretic_Progress() +void FHereticStartupScreen::Progress() { int notch_pos; @@ -869,13 +919,13 @@ static void ST_Heretic_Progress() //========================================================================== // -// ST_Heretic_Message +// FHereticStartupScreen :: LoadingStatus // // Prints text in the center box of the startup screen. // //========================================================================== -static void ST_Heretic_Message (const char *message, int attributes) +void FHereticStartupScreen::LoadingStatus(const char *message, int colors) { BYTE *font = ST_Util_LoadFont (TEXT_FONT_NAME); if (font != NULL) @@ -884,7 +934,7 @@ static void ST_Heretic_Message (const char *message, int attributes) for (x = 0; message[x] != '\0'; ++x) { - ST_Util_DrawChar (StartupBitmap, font, 17 + x, HMsgY, message[x], attributes); + ST_Util_DrawChar (StartupBitmap, font, 17 + x, HMsgY, message[x], colors); } ST_Util_InvalidateRect (StartupScreen, StartupBitmap, 17 * 8, HMsgY * font[0], (17 + x) * 8, HMsgY * font[0] + font[0]); ST_Util_FreeFont (font); @@ -895,13 +945,13 @@ static void ST_Heretic_Message (const char *message, int attributes) //========================================================================== // -// ST_Heretic_Status +// FHereticStartupScreen :: AppendStatusLine // // Appends text to Heretic's status line. // //========================================================================== -static void ST_Heretic_Status (const char *status) +void FHereticStartupScreen::AppendStatusLine(const char *status) { BYTE *font = ST_Util_LoadFont (TEXT_FONT_NAME); if (font != NULL) @@ -921,10 +971,10 @@ static void ST_Heretic_Status (const char *status) //========================================================================== // -// ST_Strife_Init +// FStrifeStartupScreen Constructor // // Shows the Strife startup screen. If the screen doesn't appear to be -// valid, it falls back to ST_Basic_Init. +// 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 @@ -935,14 +985,20 @@ static void ST_Heretic_Status (const char *status) // //========================================================================== -static void ST_Strife_Init () +FStrifeStartupScreen::FStrifeStartupScreen(int max_progress, HRESULT &hr) +: FGraphicalStartupScreen(max_progress) { int startup_lump = Wads.CheckNumForName ("STARTUP0"); int i; + hr = E_FAIL; + for (i = 0; i < 4+2+1; ++i) + { + StartupPics[i] = NULL; + } + if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 64000 || !ST_Util_CreateStartupWindow()) { - ST_Basic_Init (); return; } @@ -961,77 +1017,52 @@ static void ST_Strife_Init () int lumpnum = Wads.CheckNumForName (StrifeStartupPicNames[i]); int lumplen; - if (lumpnum < 0 || (lumplen = Wads.LumpLength (lumpnum)) != StrifeStartupPicSizes[i]) - { - StrifeStartupPics[i] = NULL; - } - else + if (lumpnum >= 0 && (lumplen = Wads.LumpLength (lumpnum)) == StrifeStartupPicSizes[i]) { FWadLump lumpr = Wads.OpenLumpNum (lumpnum); - StrifeStartupPics[i] = new BYTE[lumplen]; - lumpr.Read (StrifeStartupPics[i], lumplen); + StartupPics[i] = new BYTE[lumplen]; + lumpr.Read (StartupPics[i], lumplen); } } // Make the startup image appear. - ST_Strife_DrawStuff (0, 0); + DrawStuff (0, 0); ST_Util_SizeWindowForBitmap (2); LayoutMainWindow (Window, NULL); InvalidateRect (StartupScreen, NULL, TRUE); - ST_Done = ST_Strife_Done; - ST_Progress = ST_Strife_Progress; - ST_HereticMessage = ST_Basic_HereticMessage; - ST_HereticStatus = ST_Basic_HereticStatus; - ST_NetInit = ST_Basic_NetInit; - ST_NetProgress = ST_Basic_NetProgress; - ST_NetMessage = ST_Basic_NetMessage; - ST_NetDone = ST_Basic_NetDone; - ST_NetLoop = ST_Basic_NetLoop; + hr = S_OK; } //========================================================================== // -// ST_Strife_Done +// FStrifeStartupScreen Deconstructor // -// Called just before entering graphics mode to deconstruct the startup -// screen. +// Frees the strife pictures. // //========================================================================== -static void ST_Strife_Done() +FStrifeStartupScreen::~FStrifeStartupScreen() { - int i; - - for (i = 0; i < 4+2+1; ++i) + for (int i = 0; i < 4+2+1; ++i) { - if (StrifeStartupPics[i] != NULL) + if (StartupPics[i] != NULL) { - delete[] StrifeStartupPics[i]; + delete[] StartupPics[i]; } - StrifeStartupPics[i] = NULL; - } - if (StartupScreen != NULL) - { - DestroyWindow (StartupScreen); - StartupScreen = NULL; - } - if (StartupBitmap != NULL) - { - ST_Util_FreeBitmap (StartupBitmap); - StartupBitmap = NULL; + StartupPics[i] = NULL; } } //========================================================================== // -// ST_Strife_Progress +// FStrifeStartupScreen :: Progress // // Bumps the progress meter one notch. // //========================================================================== -static void ST_Strife_Progress() +void FStrifeStartupScreen::Progress() { int notch_pos; @@ -1041,7 +1072,7 @@ static void ST_Strife_Progress() notch_pos = (CurPos * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos; if (notch_pos != NotchPos && !(notch_pos & 1)) { // Time to update. - ST_Strife_DrawStuff (NotchPos, notch_pos); + DrawStuff (NotchPos, notch_pos); NotchPos = notch_pos; } } @@ -1050,7 +1081,7 @@ static void ST_Strife_Progress() //========================================================================== // -// ST_Strife_DrawStuff +// 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 @@ -1058,7 +1089,7 @@ static void ST_Strife_Progress() // //========================================================================== -static void ST_Strife_DrawStuff (int old_laser, int new_laser) +void FStrifeStartupScreen::DrawStuff(int old_laser, int new_laser) { int y; @@ -1066,7 +1097,7 @@ static void ST_Strife_DrawStuff (int old_laser, int new_laser) ST_Util_ClearBlock (StartupBitmap, 0xF0, ST_LASERSPACE_X + old_laser, ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT); // Draw new laser - ST_Util_DrawBlock (StartupBitmap, StrifeStartupPics[LASER_INDEX + (new_laser & 1)], + ST_Util_DrawBlock (StartupBitmap, 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. @@ -1075,7 +1106,7 @@ static void ST_Strife_DrawStuff (int old_laser, int new_laser) { ST_Util_ClearBlock (StartupBitmap, 0xF0, ST_BOT_X, ST_BOT_Y, ST_BOT_WIDTH, y); } - ST_Util_DrawBlock (StartupBitmap, StrifeStartupPics[BOT_INDEX], ST_BOT_X, ST_BOT_Y + y, ST_BOT_WIDTH, ST_BOT_HEIGHT); + ST_Util_DrawBlock (StartupBitmap, StartupPics[BOT_INDEX], ST_BOT_X, ST_BOT_Y + y, ST_BOT_WIDTH, ST_BOT_HEIGHT); if (y < (5 - 1) - 2) { ST_Util_ClearBlock (StartupBitmap, 0xF0, ST_BOT_X, ST_BOT_Y + ST_BOT_HEIGHT + y, ST_BOT_WIDTH, 2 - y); @@ -1083,7 +1114,7 @@ static void ST_Strife_DrawStuff (int old_laser, int new_laser) // 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 (StartupBitmap, StrifeStartupPics[PEASANT_INDEX + ((new_laser >> 1) & 3)], + ST_Util_DrawBlock (StartupBitmap, StartupPics[PEASANT_INDEX + ((new_laser >> 1) & 3)], ST_PEASANT_X, ST_PEASANT_Y, ST_PEASANT_WIDTH, ST_PEASANT_HEIGHT); } @@ -1107,6 +1138,7 @@ void ST_Endoom() BYTE endoom_screen[4000]; BYTE *font; MSG mess; + BOOL bRet; if (endoom_lump < 0 || Wads.LumpLength (endoom_lump) != 4000) { @@ -1130,7 +1162,6 @@ void ST_Endoom() ST_Util_FreeFont (font); exit(0); } - ST_Done = ST_Basic_Done; I_ShutdownGraphics (); RestoreConView (); @@ -1156,19 +1187,21 @@ void ST_Endoom() // Wait until any key has been pressed or a quit message has been received - while (1) + while ((bRet = GetMessage(&mess, NULL, 0, 0)) != 0) { - if (PeekMessage (&mess, NULL, 0, 0, PM_REMOVE)) + if (bRet == 0) // Received WM_QUIT { - if (mess.message == WM_QUIT) - exit (int(mess.wParam)); - if (mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN) - exit(0); - - TranslateMessage (&mess); - DispatchMessage (&mess); + exit (int(mess.wParam)); } - else WaitMessage(); + else if (bRet != -1) + { + if (mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN) + { + exit (0); + } + } + TranslateMessage (&mess); + DispatchMessage (&mess); } } @@ -1301,6 +1334,11 @@ void ST_Util_PlanarToChunky4 (BYTE *dest, const BYTE *src, int width, int height void ST_Util_DrawBlock (BITMAPINFO *bitmap_info, const BYTE *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; BYTE *dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch;