- 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)
This commit is contained in:
Randy Heit 2007-03-06 01:33:18 +00:00
parent 3f1a681451
commit 560d4f8140
12 changed files with 378 additions and 311 deletions

View file

@ -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 February 28, 2007
- Changed the net start pane to open underneath the existing window instead - Changed the net start pane to open underneath the existing window instead
of scrunching the startup screen up to make room for it. of scrunching the startup screen up to make room for it.

View file

@ -2080,7 +2080,7 @@ void D_DoomMain (void)
S_Init (); S_Init ();
Printf ("ST_Init: Init startup screen.\n"); 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"); Printf ("P_Init: Checking cmd-line parameters...\n");
flags = dmflags; flags = dmflags;
@ -2208,21 +2208,21 @@ void D_DoomMain (void)
timelimit = 20.f; timelimit = 20.f;
} }
// //
// Build status bar line! // Build status bar line!
// //
if (deathmatch) if (deathmatch)
ST_HereticStatus("DeathMatch..."); StartScreen->AppendStatusLine("DeathMatch...");
if (dmflags & DF_NO_MONSTERS) if (dmflags & DF_NO_MONSTERS)
ST_HereticStatus("No Monsters..."); StartScreen->AppendStatusLine("No Monsters...");
if (dmflags & DF_MONSTERS_RESPAWN) if (dmflags & DF_MONSTERS_RESPAWN)
ST_HereticStatus("Respawning..."); StartScreen->AppendStatusLine("Respawning...");
if (autostart) if (autostart)
{ {
FString temp; FString temp;
temp.Format ("Warp to map %s, Skill %d ", startmap, gameskill + 1); temp.Format ("Warp to map %s, Skill %d ", startmap, gameskill + 1);
ST_HereticStatus (temp); StartScreen->AppendStatusLine(temp);
} }
// [RH] Now that all text strings are set up, // [RH] Now that all text strings are set up,
// insert them into the level and cluster data. // insert them into the level and cluster data.
@ -2251,10 +2251,10 @@ void D_DoomMain (void)
} }
FActorInfo::StaticGameSet (); FActorInfo::StaticGameSet ();
ST_Progress (); StartScreen->Progress ();
Printf ("R_Init: Init %s refresh subsystem.\n", GameNames[gameinfo.gametype]); Printf ("R_Init: Init %s refresh subsystem.\n", GameNames[gameinfo.gametype]);
ST_HereticMessage ("Loading graphics", 0x3f); StartScreen->LoadingStatus ("Loading graphics", 0x3f);
R_Init (); R_Init ();
Printf ("DecalLibrary: Load decals.\n"); Printf ("DecalLibrary: Load decals.\n");
@ -2322,11 +2322,11 @@ void D_DoomMain (void)
M_Init (); M_Init ();
Printf ("P_Init: Init Playloop state.\n"); Printf ("P_Init: Init Playloop state.\n");
ST_HereticMessage ("Init game engine", 0x3f); StartScreen->LoadingStatus ("Init game engine", 0x3f);
P_Init (); P_Init ();
Printf ("D_CheckNetGame: Checking network game status.\n"); Printf ("D_CheckNetGame: Checking network game status.\n");
ST_HereticMessage ("Checking network game status.", 0x3f); StartScreen->LoadingStatus ("Checking network game status.", 0x3f);
D_CheckNetGame (); D_CheckNetGame ();
// [RH] Lock any cvars that should be locked now that we're // [RH] Lock any cvars that should be locked now that we're
@ -2350,7 +2350,8 @@ void D_DoomMain (void)
autostart = true; autostart = true;
} }
ST_Done(); delete StartScreen;
StartScreen = NULL;
V_Init2(); V_Init2();
files = Args.GatherFiles ("-playdemo", ".lmp", false); files = Args.GatherFiles ("-playdemo", ".lmp", false);

View file

@ -1358,7 +1358,7 @@ bool DoArbitrate (void *userdata)
D_ReadUserInfoStrings (netbuffer[1], &stream, false); 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, players[netbuffer[1]].userinfo.netname,
node, netbuffer[1]+1); node, netbuffer[1]+1);
} }
@ -1503,8 +1503,8 @@ void D_ArbitrateNetStart (void)
data.gotsetup[0] = 0x80; data.gotsetup[0] = 0x80;
} }
ST_NetInit ("Exchanging game information", 1); StartScreen->NetInit ("Exchanging game information", 1);
if (!ST_NetLoop (DoArbitrate, &data)) if (!StartScreen->NetLoop (DoArbitrate, &data))
{ {
exit (0); exit (0);
} }
@ -1522,7 +1522,7 @@ void D_ArbitrateNetStart (void)
fprintf (debugfile, "player %d is on node %d\n", i, nodeforplayer[i]); 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) static void SendSetup (DWORD playersdetected[MAXNETNODES], BYTE gotsetup[MAXNETNODES], int len)

View file

@ -1643,7 +1643,7 @@ static void goOn (int position, bool keepFacing, bool secret, bool resetinv)
if (thiscluster && (thiscluster->flags & CLUSTER_HUB)) if (thiscluster && (thiscluster->flags & CLUSTER_HUB))
{ {
if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster)) if ((level.flags & LEVEL_NOINTERMISSION) || (nextcluster == thiscluster))
NoWipe = 4; NoWipe = 35;
D_DrawIcon = "TELEICON"; D_DrawIcon = "TELEICON";
} }

View file

@ -224,7 +224,7 @@ void PacketGet (void)
if (err == WSAECONNRESET) if (err == WSAECONNRESET)
{ // The remote node aborted unexpectedly, so pretend it sent an exit packet { // 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); players[sendplayer[node]].userinfo.netname);
doomcom.data[0] = 0x80; // NCMD_EXIT doomcom.data[0] = 0x80; // NCMD_EXIT
@ -401,7 +401,7 @@ static void SendConAck (int num_connected, int num_needed)
{ {
PreSend (&packet, 4, &sendaddress[node]); PreSend (&packet, 4, &sendaddress[node]);
} }
ST_NetProgress (doomcom.numnodes); StartScreen->NetProgress (doomcom.numnodes);
} }
bool Host_CheckForConnects (void *userdata) bool Host_CheckForConnects (void *userdata)
@ -426,7 +426,7 @@ bool Host_CheckForConnects (void *userdata)
if (node == -1) if (node == -1)
{ {
const BYTE *s_addr_bytes = (const BYTE *)&from->sin_addr; 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], s_addr_bytes[0], s_addr_bytes[1], s_addr_bytes[2], s_addr_bytes[3],
from->sin_port); from->sin_port);
packet.Message = PRE_ALLFULL; packet.Message = PRE_ALLFULL;
@ -439,7 +439,7 @@ bool Host_CheckForConnects (void *userdata)
{ {
node = doomcom.numnodes++; node = doomcom.numnodes++;
sendaddress[node] = *from; 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. // Let the new guest (and everyone else) know we got their message.
@ -451,7 +451,7 @@ bool Host_CheckForConnects (void *userdata)
node = FindNode (from); node = FindNode (from);
if (node >= 0) if (node >= 0)
{ {
ST_NetMessage ("Got disconnect from node %d.", node); StartScreen->NetMessage ("Got disconnect from node %d.", node);
doomcom.numnodes--; doomcom.numnodes--;
while (node < doomcom.numnodes) while (node < doomcom.numnodes)
{ {
@ -590,20 +590,20 @@ void HostGame (int i)
atterm (SendAbort); atterm (SendAbort);
ST_NetInit ("Waiting for players", numplayers); StartScreen->NetInit ("Waiting for players", numplayers);
// Wait for numplayers-1 different connections // 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); exit (0);
} }
// Now inform everyone of all machines involved in the game // Now inform everyone of all machines involved in the game
memset (gotack, 0, sizeof(gotack)); memset (gotack, 0, sizeof(gotack));
ST_NetMessage ("Sending all here."); StartScreen->NetMessage ("Sending all here.");
ST_NetInit ("Done waiting", 1); StartScreen->NetInit ("Done waiting", 1);
if (!ST_NetLoop (Host_SendAllHere, (void *)gotack)) if (!StartScreen->NetLoop (Host_SendAllHere, (void *)gotack))
{ {
exit (0); exit (0);
} }
@ -611,7 +611,7 @@ void HostGame (int i)
popterm (); popterm ();
// Now go // Now go
ST_NetMessage ("Go"); StartScreen->NetMessage ("Go");
packet.Fake = PRE_FAKE; packet.Fake = PRE_FAKE;
packet.Message = PRE_GO; packet.Message = PRE_GO;
for (node = 1; node < doomcom.numnodes; node++) 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.id = DOOMCOM_ID;
doomcom.numplayers = doomcom.numnodes; doomcom.numplayers = doomcom.numnodes;
@ -657,9 +657,9 @@ bool Guest_ContactHost (void *userdata)
{ {
if (packet.Message == PRE_CONACK) if (packet.Message == PRE_CONACK)
{ {
ST_NetMessage ("Total players: %d", packet.NumNodes); StartScreen->NetMessage ("Total players: %d", packet.NumNodes);
ST_NetInit ("Waiting for other players", packet.NumNodes); StartScreen->NetInit ("Waiting for other players", packet.NumNodes);
ST_NetProgress (packet.NumPresent); StartScreen->NetProgress (packet.NumPresent);
return true; return true;
} }
else if (packet.Message == PRE_DISCONNECT) 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. // In case the progress bar could not be marqueed, bump it.
ST_NetProgress (0); StartScreen->NetProgress (0);
return false; return false;
} }
@ -695,7 +695,7 @@ bool Guest_WaitForOthers (void *userdata)
switch (packet.Message) switch (packet.Message)
{ {
case PRE_CONACK: case PRE_CONACK:
ST_NetProgress (packet.NumPresent); StartScreen->NetProgress (packet.NumPresent);
break; break;
case PRE_ALLHERE: case PRE_ALLHERE:
@ -707,7 +707,7 @@ bool Guest_WaitForOthers (void *userdata)
doomcom.numnodes = packet.NumNodes + 2; doomcom.numnodes = packet.NumNodes + 2;
sendplayer[0] = packet.ConsoleNum; // My player number sendplayer[0] = packet.ConsoleNum; // My player number
doomcom.consoleplayer = packet.ConsoleNum; 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++) for (node = 0; node < packet.NumNodes; node++)
{ {
sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address; 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.Fake = PRE_FAKE;
packet.Message = PRE_ALLHEREACK; packet.Message = PRE_ALLHEREACK;
PreSend (&packet, 2, &sendaddress[1]); PreSend (&packet, 2, &sendaddress[1]);
break; break;
case PRE_GO: case PRE_GO:
ST_NetMessage ("Received \"Go.\""); StartScreen->NetMessage ("Received \"Go.\"");
return true; return true;
case PRE_DISCONNECT: case PRE_DISCONNECT:
@ -757,22 +757,22 @@ void JoinGame (int i)
atterm (SendAbort); atterm (SendAbort);
// Let host know we are here // 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); exit (0);
} }
// Wait for everyone else to connect // Wait for everyone else to connect
if (!ST_NetLoop (Guest_WaitForOthers, 0)) if (!StartScreen->NetLoop (Guest_WaitForOthers, 0))
{ {
exit (0); exit (0);
} }
popterm (); popterm ();
ST_NetMessage ("Total players: %d", doomcom.numnodes); StartScreen->NetMessage ("Total players: %d", doomcom.numnodes);
doomcom.id = DOOMCOM_ID; doomcom.id = DOOMCOM_ID;
doomcom.numplayers = doomcom.numnodes; doomcom.numplayers = doomcom.numnodes;

View file

@ -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. // Set the missile's speed to reflect the speed it was spawned at.
if (mobj->flags & MF_MISSILE) 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 // Hugger missiles don't have any vertical velocity
if (mobj->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER)) if (mobj->flags3 & (MF3_FLOORHUGGER|MF3_CEILINGHUGGER))

View file

@ -297,7 +297,7 @@ void FTextureManager::AddGroup(const char * startlump, const char * endlump, int
{ {
CreateTexture (firsttx, usetype); CreateTexture (firsttx, usetype);
} }
ST_Progress(); StartScreen->Progress();
} }
} }
@ -353,7 +353,7 @@ void FTextureManager::AddHiresTextures ()
newtex->TopOffset = Scale(oldtex->TopOffset, newtex->ScaleY, 8); newtex->TopOffset = Scale(oldtex->TopOffset, newtex->ScaleY, 8);
ReplaceTexture(oldtexno, newtex, true); 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); CreateTexture (Wads.CheckNumForName (name, ns_patches), FTexture::TEX_WallPatch);
} }
ST_Progress(); StartScreen->Progress();
} }
delete file; delete file;
@ -729,10 +729,10 @@ DWORD R_BlendForColormap (DWORD map)
void R_InitData () void R_InitData ()
{ {
FTexture::InitGrayMap(); FTexture::InitGrayMap();
ST_Progress(); StartScreen->Progress();
TexMan.AddGroup("S_START", "S_END", ns_sprites, FTexture::TEX_Sprite); TexMan.AddGroup("S_START", "S_END", ns_sprites, FTexture::TEX_Sprite);
R_InitPatches (); // Initializes "special" textures that have no external references R_InitPatches (); // Initializes "special" textures that have no external references
ST_Progress(); StartScreen->Progress();
R_InitTextures (); R_InitTextures ();
TexMan.AddGroup("F_START", "F_END", ns_flats, FTexture::TEX_Flat); TexMan.AddGroup("F_START", "F_END", ns_flats, FTexture::TEX_Flat);
R_InitBuildTiles (); R_InitBuildTiles ();
@ -741,9 +741,9 @@ void R_InitData ()
TexMan.LoadHiresTex (); TexMan.LoadHiresTex ();
TexMan.DefaultTexture = TexMan.CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0); TexMan.DefaultTexture = TexMan.CheckForTexture ("-NOFLAT-", FTexture::TEX_Override, 0);
V_InitFonts(); V_InitFonts();
ST_Progress(); StartScreen->Progress();
R_InitColormaps (); R_InitColormaps ();
ST_Progress(); StartScreen->Progress();
} }
//=========================================================================== //===========================================================================

View file

@ -34,14 +34,27 @@
** Actual implementation is system-specific. ** Actual implementation is system-specific.
*/ */
extern void ST_Init(int maxProgress); class FStartupScreen
extern void (*ST_Done)(); {
extern void (*ST_Progress)(); public:
extern void (*ST_HereticMessage)(const char *message, int attributes); static FStartupScreen *CreateInstance(int max_progress);
extern void (*ST_HereticStatus)(const char *status);
extern void (*ST_NetInit)(const char *message, int numplayers); FStartupScreen(int max_progress);
extern void (*ST_NetProgress)(int count); virtual ~FStartupScreen();
extern void (*ST_NetMessage)(const char *format, ...); // cover for printf()
extern void (*ST_NetDone)(); virtual void Progress() = 0;
extern bool (*ST_NetLoop)(bool (*timer_callback)(void *), void *userdata); 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(); extern void ST_Endoom();

View file

@ -138,7 +138,7 @@ static void AddTiles (void *tiles)
tiledata++; tiledata++;
size--; size--;
} }
ST_Progress(); StartScreen->Progress();
if ((picanm[pic] & 63) && (picanm[pic] & 192)) if ((picanm[pic] & 63) && (picanm[pic] & 192))
{ {

View file

@ -512,7 +512,7 @@ void FTextureManager::AddTexturesLump (const void *lumpdata, int lumpsize, int p
tex->UseType = FTexture::TEX_Null; tex->UseType = FTexture::TEX_Null;
} }
TexMan.AddTexture (tex); TexMan.AddTexture (tex);
ST_Progress(); StartScreen->Progress();
} }
} }
} }

View file

@ -653,9 +653,10 @@ void RestoreConView()
ShowWindow (GameTitleWindow, SW_SHOW); ShowWindow (GameTitleWindow, SW_SHOW);
I_ShutdownInput (); // Make sure the mouse pointer is available. I_ShutdownInput (); // Make sure the mouse pointer is available.
// Make sure the progress bar isn't visible. // 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); 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); 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) if (ErrorIcon != NULL)
{ {

View file

@ -106,6 +106,66 @@
// TYPES ------------------------------------------------------------------- // 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 -------------------------------------------- // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
void RestoreConView(); 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 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 ---------------------------------------------- // EXTERNAL DATA DECLARATIONS ----------------------------------------------
extern HINSTANCE g_hInst; extern HINSTANCE g_hInst;
@ -167,16 +201,7 @@ extern HWND Window, ConWindow, ProgressBar, NetStartPane, StartupScreen, GameTit
// PUBLIC DATA DEFINITIONS ------------------------------------------------- // PUBLIC DATA DEFINITIONS -------------------------------------------------
void (*ST_Done)(); FStartupScreen *StartScreen;
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);
BITMAPINFO *StartupBitmap; BITMAPINFO *StartupBitmap;
CUSTOM_CVAR(Int, showendoom, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) 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 ------------------------------------------------ // 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] = static const char *StrifeStartupPicNames[4+2+1] =
{ {
"STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1", "STRTPA1", "STRTPB1", "STRTPC1", "STRTPD1",
@ -281,75 +299,123 @@ static const BYTE NetNotchBits[] =
//========================================================================== //==========================================================================
// //
// ST_Init // FStartupScreen :: CreateInstance
// //
// Initializes the startup screen for the detected game. // Initializes the startup screen for the detected game.
// Sets the size of the progress bar and displays the startup screen. // 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; FStartupScreen *scr = NULL;
CurPos = 0; HRESULT hr;
NotchPos = 0;
if (gameinfo.gametype == GAME_Hexen) if (gameinfo.gametype == GAME_Hexen)
{ {
ST_Hexen_Init (); scr = new FHexenStartupScreen(max_progress, hr);
} }
else if (gameinfo.gametype == GAME_Heretic) else if (gameinfo.gametype == GAME_Heretic)
{ {
ST_Heretic_Init (); scr = new FHereticStartupScreen(max_progress, hr);
} }
else if (gameinfo.gametype == GAME_Strife) 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. // 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, if (show_bar)
NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS, {
0, 0, 0, 0, ProgressBar = CreateWindowEx(0, PROGRESS_CLASS,
Window, 0, g_hInst, NULL); NULL, WS_CHILD | WS_VISIBLE | WS_CLIPSIBLINGS,
SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos)); 0, 0, 0, 0,
LayoutMainWindow (Window, NULL); Window, 0, g_hInst, NULL);
SendMessage (ProgressBar, PBM_SETRANGE, 0, MAKELPARAM(0,MaxPos));
ST_Done = ST_Basic_Done; LayoutMainWindow (Window, NULL);
ST_Progress = ST_Basic_Progress; }
ST_HereticMessage = ST_Basic_HereticMessage; NetMaxPos = 0;
ST_HereticStatus = ST_Basic_HereticStatus; NetCurPos = 0;
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;
} }
//========================================================================== //==========================================================================
// //
// ST_Basic_Done // FBasicStartupScreen Destructor
// //
// Called just before entering graphics mode to deconstruct the startup // Called just before entering graphics mode to deconstruct the startup
// screen. // screen.
// //
//========================================================================== //==========================================================================
static void ST_Basic_Done() FBasicStartupScreen::~FBasicStartupScreen()
{ {
if (ProgressBar != NULL) if (ProgressBar != NULL)
{ {
@ -361,13 +427,13 @@ static void ST_Basic_Done()
//========================================================================== //==========================================================================
// //
// ST_Basic_Progress // FBasicStartupScreen :: Progress
// //
// Bumps the progress meter one notch. // Bumps the progress meter one notch.
// //
//========================================================================== //==========================================================================
static void ST_Basic_Progress() void FBasicStartupScreen::Progress()
{ {
if (CurPos < MaxPos) if (CurPos < MaxPos)
{ {
@ -378,31 +444,7 @@ static void ST_Basic_Progress()
//========================================================================== //==========================================================================
// //
// ST_Basic_HereticMessage // FBasicStartupScreen :: NetInit
//
// 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
// //
// Shows the network startup pane if it isn't visible. Sets the message in // 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 // 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; NetMaxPos = numplayers;
if (NetStartPane == NULL) 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), winrect.right - winrect.left, winrect.bottom - winrect.top + LayoutNetStartPane (NetStartPane, 0),
SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER); SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOZORDER);
LayoutMainWindow (Window, NULL); LayoutMainWindow (Window, NULL);
SetFocus (NetStartPane);
} }
if (NetStartPane != NULL) if (NetStartPane != NULL)
{ {
@ -470,18 +513,18 @@ static void ST_Basic_NetInit(const char *message, int numplayers)
} }
NetMaxPos = numplayers; NetMaxPos = numplayers;
NetCurPos = 0; 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. // Removes the network startup pane.
// //
//========================================================================== //==========================================================================
static void ST_Basic_NetDone() void FBasicStartupScreen::NetDone()
{ {
if (NetStartPane != NULL) 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 // display messages, in case the progress meter is mixed in the same output
// stream as normal messages. // stream as normal messages.
// //
//========================================================================== //==========================================================================
static void ST_Basic_NetMessage(const char *format, ...) void FBasicStartupScreen::NetMessage(const char *format, ...)
{ {
FString str; FString str;
va_list argptr; 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. // Sets the network progress meter. If count is 0, it gets bumped by 1.
// Otherwise, it is set to count. // Otherwise, it is set to count.
// //
//========================================================================== //==========================================================================
static void ST_Basic_NetProgress(int count) void FBasicStartupScreen :: NetProgress(int count)
{ {
if (count == 0) 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 // 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 // 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; BOOL bRet;
MSG msg; 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) 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); PostQuitMessage (0);
return TRUE; 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 // 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 // The startup graphic is a planar, 4-bit 640x480 graphic preceded by a
// 16 entry (48 byte) VGA palette. // 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"); int startup_lump = Wads.CheckNumForName ("STARTUP");
hr = E_FAIL;
if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 153648 || !ST_Util_CreateStartupWindow()) if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 153648 || !ST_Util_CreateStartupWindow())
{ {
ST_Basic_Init ();
return; return;
} }
@ -676,53 +754,20 @@ static void ST_Hexen_Init ()
LayoutMainWindow (Window, NULL); LayoutMainWindow (Window, NULL);
InvalidateRect (StartupScreen, NULL, TRUE); 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); S_ChangeMusic ("orb", true, true);
hr = S_OK;
} }
//========================================================================== //==========================================================================
// //
// ST_Hexen_Done // FHexenStartupScreen :: Progress
//
// 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
// //
// Bumps the progress meter one notch. // Bumps the progress meter one notch.
// //
//========================================================================== //==========================================================================
static void ST_Hexen_Progress() void FHexenStartupScreen::Progress()
{ {
int notch_pos, x, y; 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. // 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 oldpos = NetCurPos;
int x, y; int x, y;
ST_Basic_NetProgress (count); FGraphicalStartupScreen::NetProgress (count);
if (NetMaxPos != 0 && NetCurPos > oldpos) if (NetMaxPos != 0 && NetCurPos > oldpos)
{ {
for (; oldpos < NetCurPos && oldpos < ST_MAX_NETNOTCHES; ++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 // 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 // The loading screen is an 80x25 text screen with character data and
// attributes intermixed, which means it must be exactly 4000 bytes long. // 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"); int loading_lump = Wads.CheckNumForName ("LOADING");
BYTE loading_screen[4000]; BYTE loading_screen[4000];
BYTE *font; BYTE *font;
hr = E_FAIL;
if (loading_lump < 0 || Wads.LumpLength (loading_lump) != 4000 || !ST_Util_CreateStartupWindow()) if (loading_lump < 0 || Wads.LumpLength (loading_lump) != 4000 || !ST_Util_CreateStartupWindow())
{ {
ST_Basic_Init ();
return; return;
} }
@ -799,7 +859,6 @@ static void ST_Heretic_Init ()
if (font == NULL) if (font == NULL)
{ {
DestroyWindow (StartupScreen); DestroyWindow (StartupScreen);
ST_Basic_Init ();
return; return;
} }
@ -826,27 +885,18 @@ static void ST_Heretic_Init ()
ST_Util_SizeWindowForBitmap (1); ST_Util_SizeWindowForBitmap (1);
LayoutMainWindow (Window, NULL); LayoutMainWindow (Window, NULL);
InvalidateRect (StartupScreen, NULL, TRUE); InvalidateRect (StartupScreen, NULL, TRUE);
hr = S_OK;
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;
} }
//========================================================================== //==========================================================================
// //
// ST_Heretic_Progress // FHereticStartupScreen::Progress
// //
// Bumps the progress meter one notch. // Bumps the progress meter one notch.
// //
//========================================================================== //==========================================================================
static void ST_Heretic_Progress() void FHereticStartupScreen::Progress()
{ {
int notch_pos; 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. // 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); BYTE *font = ST_Util_LoadFont (TEXT_FONT_NAME);
if (font != NULL) if (font != NULL)
@ -884,7 +934,7 @@ static void ST_Heretic_Message (const char *message, int attributes)
for (x = 0; message[x] != '\0'; ++x) 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_InvalidateRect (StartupScreen, StartupBitmap, 17 * 8, HMsgY * font[0], (17 + x) * 8, HMsgY * font[0] + font[0]);
ST_Util_FreeFont (font); 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. // 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); BYTE *font = ST_Util_LoadFont (TEXT_FONT_NAME);
if (font != NULL) 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 // 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 // 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 // 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 startup_lump = Wads.CheckNumForName ("STARTUP0");
int i; 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()) if (startup_lump < 0 || Wads.LumpLength (startup_lump) != 64000 || !ST_Util_CreateStartupWindow())
{ {
ST_Basic_Init ();
return; return;
} }
@ -961,77 +1017,52 @@ static void ST_Strife_Init ()
int lumpnum = Wads.CheckNumForName (StrifeStartupPicNames[i]); int lumpnum = Wads.CheckNumForName (StrifeStartupPicNames[i]);
int lumplen; int lumplen;
if (lumpnum < 0 || (lumplen = Wads.LumpLength (lumpnum)) != StrifeStartupPicSizes[i]) if (lumpnum >= 0 && (lumplen = Wads.LumpLength (lumpnum)) == StrifeStartupPicSizes[i])
{
StrifeStartupPics[i] = NULL;
}
else
{ {
FWadLump lumpr = Wads.OpenLumpNum (lumpnum); FWadLump lumpr = Wads.OpenLumpNum (lumpnum);
StrifeStartupPics[i] = new BYTE[lumplen]; StartupPics[i] = new BYTE[lumplen];
lumpr.Read (StrifeStartupPics[i], lumplen); lumpr.Read (StartupPics[i], lumplen);
} }
} }
// Make the startup image appear. // Make the startup image appear.
ST_Strife_DrawStuff (0, 0); DrawStuff (0, 0);
ST_Util_SizeWindowForBitmap (2); ST_Util_SizeWindowForBitmap (2);
LayoutMainWindow (Window, NULL); LayoutMainWindow (Window, NULL);
InvalidateRect (StartupScreen, NULL, TRUE); InvalidateRect (StartupScreen, NULL, TRUE);
ST_Done = ST_Strife_Done; hr = S_OK;
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;
} }
//========================================================================== //==========================================================================
// //
// ST_Strife_Done // FStrifeStartupScreen Deconstructor
// //
// Called just before entering graphics mode to deconstruct the startup // Frees the strife pictures.
// screen.
// //
//========================================================================== //==========================================================================
static void ST_Strife_Done() FStrifeStartupScreen::~FStrifeStartupScreen()
{ {
int i; for (int i = 0; i < 4+2+1; ++i)
for (i = 0; i < 4+2+1; ++i)
{ {
if (StrifeStartupPics[i] != NULL) if (StartupPics[i] != NULL)
{ {
delete[] StrifeStartupPics[i]; delete[] StartupPics[i];
} }
StrifeStartupPics[i] = NULL; StartupPics[i] = NULL;
}
if (StartupScreen != NULL)
{
DestroyWindow (StartupScreen);
StartupScreen = NULL;
}
if (StartupBitmap != NULL)
{
ST_Util_FreeBitmap (StartupBitmap);
StartupBitmap = NULL;
} }
} }
//========================================================================== //==========================================================================
// //
// ST_Strife_Progress // FStrifeStartupScreen :: Progress
// //
// Bumps the progress meter one notch. // Bumps the progress meter one notch.
// //
//========================================================================== //==========================================================================
static void ST_Strife_Progress() void FStrifeStartupScreen::Progress()
{ {
int notch_pos; int notch_pos;
@ -1041,7 +1072,7 @@ static void ST_Strife_Progress()
notch_pos = (CurPos * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos; notch_pos = (CurPos * (ST_LASERSPACE_WIDTH - ST_LASER_WIDTH)) / MaxPos;
if (notch_pos != NotchPos && !(notch_pos & 1)) if (notch_pos != NotchPos && !(notch_pos & 1))
{ // Time to update. { // Time to update.
ST_Strife_DrawStuff (NotchPos, notch_pos); DrawStuff (NotchPos, notch_pos);
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 // 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 // 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; 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_Util_ClearBlock (StartupBitmap, 0xF0, ST_LASERSPACE_X + old_laser,
ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT); ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT);
// Draw new laser // 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); ST_LASERSPACE_X + new_laser, ST_LASERSPACE_Y, ST_LASER_WIDTH, ST_LASER_HEIGHT);
// The bot jumps up and down like crazy. // 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_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) 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); 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. // 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. // 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); ST_PEASANT_X, ST_PEASANT_Y, ST_PEASANT_WIDTH, ST_PEASANT_HEIGHT);
} }
@ -1107,6 +1138,7 @@ void ST_Endoom()
BYTE endoom_screen[4000]; BYTE endoom_screen[4000];
BYTE *font; BYTE *font;
MSG mess; MSG mess;
BOOL bRet;
if (endoom_lump < 0 || Wads.LumpLength (endoom_lump) != 4000) if (endoom_lump < 0 || Wads.LumpLength (endoom_lump) != 4000)
{ {
@ -1130,7 +1162,6 @@ void ST_Endoom()
ST_Util_FreeFont (font); ST_Util_FreeFont (font);
exit(0); exit(0);
} }
ST_Done = ST_Basic_Done;
I_ShutdownGraphics (); I_ShutdownGraphics ();
RestoreConView (); RestoreConView ();
@ -1156,19 +1187,21 @@ void ST_Endoom()
// Wait until any key has been pressed or a quit message has been received // 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));
exit (int(mess.wParam));
if (mess.message == WM_KEYDOWN || mess.message == WM_SYSKEYDOWN || mess.message == WM_LBUTTONDOWN)
exit(0);
TranslateMessage (&mess);
DispatchMessage (&mess);
} }
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) 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 pitchshift = int(bitmap_info->bmiHeader.biBitCount == 4);
int destpitch = bitmap_info->bmiHeader.biWidth >> pitchshift; int destpitch = bitmap_info->bmiHeader.biWidth >> pitchshift;
BYTE *dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch; BYTE *dest = ST_Util_BitsForBitmap(bitmap_info) + (x >> pitchshift) + y * destpitch;