diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 968ee717a..f569d1484 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,3 +1,60 @@ +June 29, 2006 +- Added some hackery at the start of MouseRead_Win32() that prevents it from + yanking the mouse around if they keys haven't been read yet to combat the + same situation that causes the keyboard to return DIERR_NOTACQUIRED in + KeyRead(): The window is sort of in focus and sort of not. User.dll + considers it to be focused and it's drawn as such, but another focused + window is on top of it, and DirectInput doesn't see it as focused. +- Fixed: KeyRead() should handle DIERR_NOTACQUIRED errors the same way it + handles DIERR_INPUTLOST errors. This can happen if our window had the + focus stolen away from it before we tried to acquire the keyboard in + DI_Init2(). Strangely, MouseRead_DI() already did this. +- When a stack overflow occurs, report.txt now only includes the first and + last 16KB of the stack to make it more manageable. +- Limited StreamEditBinary() to the first 64KB of the file to keep it from + taking too long on large dumps. +- And now I know why gathering crash information in the same process that + crashed can be bad: Stack overflows. You get one spare page to play with + when the stack overflows. MiniDumpWriteDump() needs more than that and + causes an access violation when it runs out of leftover stack, silently + terminating the application. Windows XP x64 offers SetThreadStackGuarantee() + to increase this, but that isn't available on anything older, including + 32-bit XP. To get around this, a new thread is created to write the mini + dump when the stack overflows. +- Changed A_Burnination() to be closer to Strife's. +- Fixed: When playing back demos, DoAddBot() can be called without an + associated call to SpawnBot(). So if the bot can't spawn, botnum can + go negative, which will cause problems later in DCajunMaster::Main() + when it sees that wanted_botnum (0) is higher than botnum (-1). +- Fixed: Stopping demo recording in multiplayer games should not abruptly + drop the recorder out of the game without notifying the other players. + In fact, there's no reason why it should drop them out of multiplayer at + all. +- Fixed: Earthquakes were unreliable in multiplayer games because + P_PredictPlayer() did not preserve the player's xviewshift. +- Fixed: PlayerIsGone() needs to stop any scripts that belong to the player + who left, in addition to executing disconnect scripts. +- Fixed: APlayerPawn::AddInventory() should also check for a NULL player->mo + in case the player left but somebody still has a reference to their actor. +- Fixed: DDrawFB::PaintToWindow() should simulate proper unlocking behavior + and set Buffer to NULL. +- Improved feedback for network game initialization with the console ticker. +- Moved i_net.cpp and i_net.h out of sdl/ and win32/ and into the main source + directory. They are identical, so keeping two copies of them is bad. +- Fixed: (At least with Creative's driver's,) EAX settings are global and not + per-application. So if you play a multiplayer ZDoom game on one computer + (or even another EAX-using application), ZDoom needs to restore the + environment when it regains focus. +- Maybe fixed: (See http://forum.zdoom.org/potato.php?t=10689) Apparently, + PacketGet can receive ECONNRESET from nodes that aren't in the game. It + should be safe to just ignore these packets. +- Fixed: PlayerIsGone() should set the gone player's camera to NULL in case + the player who left was player 0. This is because if a remaining player + receives a "recoverable" error, they will become player 0. Once that happens, + they game will try to update sounds through their camera and crash in + FMODSoundRenderer::UpdateListener() because the zones array is now NULL. + G_NewInit() should also clear all the player structures. + June 29, 2006 (Changes by Graf Zahl) - Added a 'default' setting to all color selection menu items that leaves the font untranslated. diff --git a/src/b_game.cpp b/src/b_game.cpp index 5a58a2f03..ae02d136e 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -361,7 +361,10 @@ void DCajunMaster::DoAddBot (int bnum, char *info) Printf ("%s tried to join, but there was no player %d start\n", players[bnum].userinfo.netname, bnum+1); ClearPlayer (bnum, false); // Make the bot inactive again - botnum--; + if (botnum > 0) + { + botnum--; + } } else { diff --git a/src/c_console.cpp b/src/c_console.cpp index 18463d4f1..3b1951837 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -121,6 +121,7 @@ static GameAtExit *ExitCmdList; EXTERN_CVAR (Bool, show_messages) static unsigned int TickerAt, TickerMax; +static bool TickerPercent; static const char *TickerLabel; static bool TickerVisible; @@ -1079,8 +1080,9 @@ static void C_DrawNotifyText () } } -void C_InitTicker (const char *label, unsigned int max) +void C_InitTicker (const char *label, unsigned int max, bool showpercent) { + TickerPercent = showpercent; TickerMax = max; TickerLabel = label; TickerAt = 0; @@ -1170,7 +1172,14 @@ void C_DrawConsole () memset (tickstr + tickbegin + 1, 0x11, tickend - tickbegin); tickstr[tickend + 1] = 0x12; tickstr[tickend + 2] = ' '; - sprintf (tickstr + tickend + 3, "%lu%%", Scale (TickerAt, 100, TickerMax)); + if (TickerPercent) + { + sprintf (tickstr + tickend + 3, "%lu%%", Scale (TickerAt, 100, TickerMax)); + } + else + { + tickstr[tickend+3] = 0; + } screen->DrawText (CR_BROWN, LEFTMARGIN, tickerY, tickstr, TAG_DONE); // Draw the marker @@ -1268,6 +1277,7 @@ void C_FullConsole () { if (demoplayback) G_CheckDemoStatus (); + D_QuitNetGame (); advancedemo = false; ConsoleState = c_down; HistPos = NULL; diff --git a/src/c_console.h b/src/c_console.h index d2b8ec545..4a6fc0152 100644 --- a/src/c_console.h +++ b/src/c_console.h @@ -69,7 +69,7 @@ void C_HideConsole (void); void C_AdjustBottom (void); void C_FlushDisplay (void); -void C_InitTicker (const char *label, unsigned int max); +void C_InitTicker (const char *label, unsigned int max, bool showpercent=true); void C_SetTicker (unsigned int at, bool forceUpdate=false); void C_MidPrint (const char *message); diff --git a/src/d_main.cpp b/src/d_main.cpp index 252726b54..97f5e48d2 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -633,16 +633,16 @@ void D_ErrorCleanup () screen->Unlock (); bglobal.RemoveAllBots (true); D_QuitNetGame (); + if (demorecording || demoplayback) + G_CheckDemoStatus (); Net_ClearBuffers (); G_NewInit (); singletics = false; - if (demorecording || demoplayback) - G_CheckDemoStatus (); playeringame[0] = 1; players[0].playerstate = PST_LIVE; gameaction = ga_fullconsole; menuactive = MENU_Off; - insave=false; + insave = false; } //========================================================================== diff --git a/src/d_net.cpp b/src/d_net.cpp index a48efe357..0e581b4b1 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -621,11 +621,13 @@ void PlayerIsGone (int netnode, int netconsole) } // [RH] Make the player disappear + FBehavior::StaticStopMyScripts (players[netconsole].mo); if (players[netconsole].mo != NULL) { P_DisconnectEffect (players[netconsole].mo); players[netconsole].mo->Destroy (); players[netconsole].mo = NULL; + players[netconsole].camera = NULL; } // [RH] Let the scripts know the player left FBehavior::StaticStartTypedScripts (SCRIPT_Disconnect, NULL, true, netconsole); diff --git a/src/g_game.cpp b/src/g_game.cpp index ed25a3070..9be81fb91 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -2101,7 +2101,10 @@ void G_WriteDemoTiccmd (ticcmd_t *cmd, int player, int buf) if (stoprecording) { // use "stop" console command to end demo recording G_CheckDemoStatus (); - gameaction = ga_fullconsole; + if (!netgame) + { + gameaction = ga_fullconsole; + } return; } diff --git a/src/g_level.cpp b/src/g_level.cpp index 6ed6d115f..eee619901 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1369,10 +1369,13 @@ void G_NewInit () demoplayback = false; D_SetupUserInfo (); } - memset (playeringame, 0, sizeof(playeringame)); for (i = 0; i < MAXPLAYERS; ++i) { + player_t *p = &players[i]; + p->~player_t(); + ::new(p) player_t; players[i].playerstate = PST_DEAD; + playeringame[i] = 0; } BackupSaveName = ""; consoleplayer = 0; diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 6cd8cf630..78b5acdcd 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -142,7 +142,10 @@ DHUDMessage::~DHUDMessage () { V_FreeBrokenLines (Lines); Lines = NULL; - BorderNeedRefresh = screen->GetPageCount (); + if (screen != NULL) + { + BorderNeedRefresh = screen->GetPageCount (); + } } if (SourceText != NULL) { diff --git a/src/g_strife/a_strifeweapons.cpp b/src/g_strife/a_strifeweapons.cpp index d8d5c42e3..3e1614fc2 100644 --- a/src/g_strife/a_strifeweapons.cpp +++ b/src/g_strife/a_strifeweapons.cpp @@ -1598,27 +1598,20 @@ void A_Burnination (AActor *self) // x + (((pr_phburn() + 12) & 31) << FRACBITS); // // But that creates a lop-sided burn because it won't use negative offsets. - int xofs = pr_phburn(); - int yofs = pr_phburn(); + int xofs, xrand = pr_phburn(); + int yofs, yrand = pr_phburn(); - xofs = (xofs - 128); - if (xofs < 0) + // Adding 12 is pointless if you're going to mask it afterward. + xofs = xrand & 31; + if (xrand & 128) { - xofs = clamp (xofs, -31, -12); - } - else - { - xofs = clamp (xofs, 12, 31); + xofs = -xofs; } - yofs = (yofs - 128); - if (yofs < 0) + yofs = yrand & 31; + if (yrand & 128) { - yofs = clamp (yofs, -31, -12); - } - else - { - yofs = clamp (yofs, 12, 31); + yofs = -yofs; } fixed_t x = self->x + (xofs << FRACBITS); diff --git a/src/sdl/i_net.cpp b/src/i_net.cpp similarity index 85% rename from src/sdl/i_net.cpp rename to src/i_net.cpp index 32dbcb067..6456cf282 100644 --- a/src/sdl/i_net.cpp +++ b/src/i_net.cpp @@ -57,6 +57,7 @@ #include "m_crc32.h" #include "d_player.h" #include "templates.h" +#include "c_console.h" #include "doomstat.h" @@ -215,11 +216,11 @@ void PacketGet (void) , (sockaddr *)&fromaddress, &fromlen); node = FindNode (&fromaddress); - if (c == SOCKET_ERROR) + if (node >= 0 && c == SOCKET_ERROR) { int err = WSAGetLastError(); - if (err == WSAECONNRESET && node >= 0) + if (err == WSAECONNRESET) { // The remote node aborted unexpectedly, so pretend it sent an exit packet Printf (PRINT_BOLD, "The connection from %s was dropped\n", @@ -435,11 +436,15 @@ void HostGame (int i) atterm (SendAbort); + C_InitTicker ("Waiting for players", numplayers); + C_SetTicker (1, true); + // Wait for numplayers-1 different connections while (doomcom.numnodes < numplayers) { while (doomcom.numnodes < numplayers) { + C_SetTicker (doomcom.numnodes, true); if (CheckAbort ()) { SendAbort (); @@ -510,6 +515,8 @@ void HostGame (int i) ackcount = 0; memset (gotack, 0, sizeof(gotack)); Printf ("Sending all here\n"); + C_InitTicker ("Done waiting", 1); + C_SetTicker (1, true); while (ackcount < doomcom.numnodes - 1) { packet.fake = PRE_FAKE; @@ -585,13 +592,32 @@ void HostGame (int i) { sendplayer[i] = i; } + C_SetTicker (1, true); + C_InitTicker (NULL, 0); } -void SendToHost (BYTE message, BYTE ackmess, bool abortable) +// This routine is used by a guest to notify the host of its presence. +// Once that host acknowledges receipt of the notification, this routine +// is never called again. + +static const int bouncerfps = 10; +static const int bouncerdelay = 1000 / bouncerfps; +static const int updateperiod = 300 / bouncerdelay; + +int SendToHost (BYTE message, BYTE ackmess, bool abortable) { sockaddr_in *from; bool waiting = true; PreGamePacket packet; + int bouncer = 0; + + C_InitTicker ("Waiting for host", 8, false); + C_SetTicker (0, true); + + // Let host know we are here + packet.fake = PRE_FAKE; + packet.message = message; + PreSend (&packet, 2, &sendaddress[1]); while (waiting) { @@ -601,25 +627,41 @@ void SendToHost (BYTE message, BYTE ackmess, bool abortable) I_FatalError ("Network game synchronization aborted."); } - // Let host know we are here - packet.fake = PRE_FAKE; - packet.message = message; - PreSend (&packet, 2, &sendaddress[1]); + Sleep (bouncerdelay); - Sleep (300); // Listen for acknowledgement - while ( (from = PreGet (&packet, sizeof(packet), true)) ) + if (bouncer % updateperiod == 0) { - if (packet.fake == PRE_FAKE && packet.message == ackmess) + while ( (from = PreGet (&packet, sizeof(packet), true)) ) { - waiting = false; + if (packet.fake == PRE_FAKE && packet.message == ackmess) + { + waiting = false; - doomcom.consoleplayer = packet.consolenum; - sendplayer[0] = packet.consolenum; - Printf ("Console player number: %d\n", doomcom.consoleplayer); + doomcom.consoleplayer = packet.consolenum; + sendplayer[0] = packet.consolenum; + Printf ("Console player number: %d\n", doomcom.consoleplayer); + } + } + if (waiting) + { + // Let host know we are here + packet.fake = PRE_FAKE; + packet.message = message; + PreSend (&packet, 2, &sendaddress[1]); } } + if (waiting) + { + int tickpos = ++bouncer & 15; + if (tickpos > 8) + { + tickpos = 16 - tickpos; + } + C_SetTicker (tickpos, true); + } } + return bouncer; } void JoinGame (int i) @@ -627,6 +669,7 @@ void JoinGame (int i) sockaddr_in *from; bool waiting; PreGamePacket packet; + int bouncer; if ((i == Args.NumArgs() - 1) || (Args.GetArg(i+1)[0] == '-') || @@ -640,9 +683,10 @@ void JoinGame (int i) sendplayer[1] = 0; // Let host know we are here - SendToHost (PRE_CONNECT, PRE_CONACK, true); + bouncer = SendToHost (PRE_CONNECT, PRE_CONACK, true); // Wait for everyone else to connect + C_InitTicker ("Waiting for players", 8, false); waiting = true; //doomcom.numnodes = 2; atterm (SendAbort); @@ -655,54 +699,68 @@ void JoinGame (int i) I_FatalError ("Network game synchronization aborted."); } - Sleep (300); - while (waiting && (from = PreGet (&packet, sizeof(packet), false)) ) + Sleep (bouncerdelay); + + if (bouncer % updateperiod == 0) { - if (packet.fake != PRE_FAKE) + while (waiting && (from = PreGet (&packet, sizeof(packet), false)) ) { - continue; - } - switch (packet.message) - { - case PRE_ALLHERE: - if (doomcom.numnodes == 0) + if (packet.fake != PRE_FAKE) { - int node; - - packet.numnodes = packet.numnodes; - doomcom.numnodes = packet.numnodes + 2; - for (node = 0; node < packet.numnodes; node++) - { - sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address; - sendaddress[node+2].sin_port = packet.machines[node].port; - sendplayer[node+2] = packet.machines[node].player; - - // [JC] - fixes problem of games not starting due to - // no address family being assigned to nodes stored in - // sendaddress[] from the All Here packet. - sendaddress[node+2].sin_family = AF_INET; - } + continue; } + switch (packet.message) + { + case PRE_ALLHERE: + if (doomcom.numnodes == 0) + { + int node; - Printf ("Received All Here, sending ACK\n"); - packet.fake = PRE_FAKE; - packet.message = PRE_ALLHEREACK; - PreSend (&packet, 2, &sendaddress[1]); - break; - case PRE_GO: - Printf ("Go\n"); - waiting = false; - break; - case PRE_DISCONNECT: - I_FatalError ("Host cancelled the game"); - break; + packet.numnodes = packet.numnodes; + doomcom.numnodes = packet.numnodes + 2; + for (node = 0; node < packet.numnodes; node++) + { + sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address; + sendaddress[node+2].sin_port = packet.machines[node].port; + sendplayer[node+2] = packet.machines[node].player; + + // [JC] - fixes problem of games not starting due to + // no address family being assigned to nodes stored in + // sendaddress[] from the All Here packet. + sendaddress[node+2].sin_family = AF_INET; + } + } + + Printf ("Received All Here, sending ACK\n"); + packet.fake = PRE_FAKE; + packet.message = PRE_ALLHEREACK; + PreSend (&packet, 2, &sendaddress[1]); + break; + case PRE_GO: + Printf ("Go\n"); + waiting = false; + break; + case PRE_DISCONNECT: + I_FatalError ("Host cancelled the game"); + break; + } } } + if (waiting) + { + int tickpos = ++bouncer & 15; + if (tickpos > 8) + { + tickpos = 16 - tickpos; + } + C_SetTicker (tickpos, true); + } } popterm (); Printf ("Total players: %d\n", doomcom.numnodes); + C_InitTicker (NULL, 0); doomcom.id = DOOMCOM_ID; doomcom.numplayers = doomcom.numnodes; diff --git a/src/sdl/i_net.h b/src/i_net.h similarity index 100% rename from src/sdl/i_net.h rename to src/i_net.h diff --git a/src/m_options.cpp b/src/m_options.cpp index 322769acf..d46b3fc9f 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -753,7 +753,7 @@ static value_t TextColors[] = { 7.0, "blue" }, { 8.0, "orange" }, { 9.0, "white" }, - { 10.0, "yellow" } + { 10.0, "yellow" }, { 11.0, "default" } }; diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 6ec8971ed..9afa41b27 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -1434,6 +1434,22 @@ void FBehavior::StartTypedScripts (WORD type, AActor *activator, bool always, in } } +// FBehavior :: StaticStopMyScripts +// +// Stops any scripts started by the specified actor. Used by the net code +// when a player disconnects. Should this be used in general whenever an +// actor is destroyed? + +void FBehavior::StaticStopMyScripts (AActor *actor) +{ + DACSThinker *controller = DACSThinker::ActiveThinker; + + if (controller != NULL) + { + controller->StopScriptsFor (actor); + } +} + //---- The ACS Interpreter ----// void strbin (char *str); @@ -1512,6 +1528,21 @@ void DACSThinker::Tick () } } +void DACSThinker::StopScriptsFor (AActor *actor) +{ + DLevelScript *script = Scripts; + + while (script != NULL) + { + DLevelScript *next = script->next; + if (script->activator == actor) + { + script->SetState (DLevelScript::SCRIPT_PleaseRemove); + } + script = next; + } +} + IMPLEMENT_POINTY_CLASS (DLevelScript) DECLARE_POINTER (activator) END_POINTERS diff --git a/src/p_acs.h b/src/p_acs.h index fcdca7712..72146d22d 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -156,6 +156,7 @@ public: static const ScriptPtr *StaticFindScript (int script, FBehavior *&module); static const char *StaticLookupString (DWORD index); static void StaticStartTypedScripts (WORD type, AActor *activator, bool always, int arg1=0, bool runNow=false); + static void StaticStopMyScripts (AActor *actor); private: struct ArrayInfo; @@ -632,6 +633,7 @@ public: static DACSThinker *ActiveThinker; void DumpScriptStatus(); + void StopScriptsFor (AActor *actor); private: DLevelScript *LastScript; diff --git a/src/p_user.cpp b/src/p_user.cpp index 0566b7b31..16d934be3 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -278,7 +278,7 @@ void APlayerPawn::Tick() void APlayerPawn::AddInventory (AInventory *item) { // Adding inventory to a voodoo doll should add it to the real player instead. - if (player != NULL && player->mo != this) + if (player != NULL && player->mo != this && player->mo != NULL) { player->mo->AddInventory (item); return; @@ -1728,13 +1728,14 @@ void P_PredictPlayer (player_t *player) } act->BlockNode = NULL; - + int xviewshift = player->xviewshift; for (int i = gametic; i < maxtic; ++i) { player->cmd = localcmds[i % LOCALCMDTICS]; P_PlayerThink (player); player->mo->Tick (); } + player->xviewshift = xviewshift; } extern msecnode_t *P_AddSecnode (sector_t *s, AActor *thing, msecnode_t *nextnode); diff --git a/src/sound/fmodsound.cpp b/src/sound/fmodsound.cpp index 9b8ca9c9d..bccdc9a54 100644 --- a/src/sound/fmodsound.cpp +++ b/src/sound/fmodsound.cpp @@ -857,6 +857,11 @@ void FMODSoundRenderer::UpdateSoundParams3D (long handle, float pos[3], float ve FSOUND_3D_SetAttributes (ChannelMap[handle].channelID, pos, vel); } +void FMODSoundRenderer::ResetEnvironment () +{ + PrevEnvironment = NULL; +} + void FMODSoundRenderer::UpdateListener (AActor *listener) { float angle; @@ -908,6 +913,7 @@ void FMODSoundRenderer::UpdateListener (AActor *listener) else { underwater = (listener->waterlevel == 3 && snd_waterreverb); + assert (zones != NULL); env = zones[listener->Sector->ZoneNumber].Environment; if (env == NULL) { diff --git a/src/sound/fmodsound.h b/src/sound/fmodsound.h index 10178012e..fca3d671c 100644 --- a/src/sound/fmodsound.h +++ b/src/sound/fmodsound.h @@ -51,6 +51,7 @@ public: void PrintStatus (); void PrintDriversList (); void GatherStats (char *outstring); + void ResetEnvironment (); private: // Maps sfx channels onto FMOD channels diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index ac1550a5b..b24329a27 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -332,6 +332,10 @@ void SoundRenderer::GatherStats (char *outstring) sprintf (outstring, "No stats for this sound renderer."); } +void SoundRenderer::ResetEnvironment () +{ +} + SoundStream::~SoundStream () { } @@ -339,3 +343,4 @@ SoundStream::~SoundStream () SoundTrackerModule::~SoundTrackerModule () { } + diff --git a/src/sound/i_sound.h b/src/sound/i_sound.h index eecb31f0c..300e8ce2d 100644 --- a/src/sound/i_sound.h +++ b/src/sound/i_sound.h @@ -120,6 +120,7 @@ public: virtual void PrintStatus () = 0; virtual void PrintDriversList () = 0; virtual void GatherStats (char *outstring); + virtual void ResetEnvironment (); bool Sound3D; }; diff --git a/src/win32/i_crash.cpp b/src/win32/i_crash.cpp index 6a3803c90..c7e8ddc23 100644 --- a/src/win32/i_crash.cpp +++ b/src/win32/i_crash.cpp @@ -175,6 +175,13 @@ typedef BOOL (WINAPI *WRITEDUMP) (HANDLE, DWORD, HANDLE, MINIDUMP_TYPE, PMINIDUMP_USER_STREAM_INFORMATION, PMINIDUMP_CALLBACK_INFORMATION); +struct MiniDumpThreadData +{ + HANDLE File; + WRITEDUMP pMiniDumpWriteDump; + MINIDUMP_EXCEPTION_INFORMATION *Exceptor; +}; + // EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- // PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- @@ -188,11 +195,12 @@ static void AddZipFile (HANDLE ziphandle, TarFile *whichfile, short dosdate, sho static HANDLE CreateTempFile (); static void DumpBytes (HANDLE file, BYTE *address); -static void AddStackInfo (HANDLE file, void *dumpaddress); -static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack); +static void AddStackInfo (HANDLE file, void *dumpaddress, DWORD code); +static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack, DWORD *jump); static void AddToolHelp (HANDLE file); static HANDLE WriteTextReport (); +static DWORD WINAPI WriteMiniDumpInAnotherThread (LPVOID lpParam); static INT_PTR CALLBACK DetailsDlgProc (HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam); static void SetEditControl (HWND control, HWND sizedisplay, int filenum); @@ -379,8 +387,23 @@ static HANDLE WriteMyMiniDump (void) file = CreateTempFile (); if (file != INVALID_HANDLE_VALUE) { - good = pMiniDumpWriteDump (DbgProcess, DbgProcessID, file, - MiniDumpNormal, &exceptor, NULL, NULL); + if (CrashPointers.ExceptionRecord->ExceptionCode != EXCEPTION_STACK_OVERFLOW) + { + good = pMiniDumpWriteDump (DbgProcess, DbgProcessID, file, + MiniDumpNormal, &exceptor, NULL, NULL); + } + else + { + MiniDumpThreadData dumpdata = { file, pMiniDumpWriteDump, &exceptor }; + DWORD id; + HANDLE thread = CreateThread (NULL, 0, WriteMiniDumpInAnotherThread, + &dumpdata, 0, &id); + WaitForSingleObject (thread, INFINITE); + if (GetExitCodeThread (thread, &id)) + { + good = id; + } + } } } else @@ -390,6 +413,23 @@ static HANDLE WriteMyMiniDump (void) return good ? file : INVALID_HANDLE_VALUE; } +//========================================================================== +// +// WriteMiniDumpInAnotherThread +// +// When a stack overflow occurs, there isn't enough room left on the stack +// for MiniDumpWriteDump to do its thing, so we create a new thread with +// a new stack to do the work. +// +//========================================================================== + +static DWORD WINAPI WriteMiniDumpInAnotherThread (LPVOID lpParam) +{ + MiniDumpThreadData *dumpdata = (MiniDumpThreadData *)lpParam; + return dumpdata->pMiniDumpWriteDump (DbgProcess, DbgProcessID, + dumpdata->File, MiniDumpNormal, dumpdata->Exceptor, NULL, NULL); +} + //========================================================================== // // Writef @@ -634,7 +674,8 @@ HANDLE WriteTextReport () if (ctxt->ContextFlags & CONTEXT_CONTROL) { - AddStackInfo (file, (void *)(size_t)CrashPointers.ContextRecord->Esp); + AddStackInfo (file, (void *)(size_t)CrashPointers.ContextRecord->Esp, + CrashPointers.ExceptionRecord->ExceptionCode); } return file; @@ -731,14 +772,24 @@ static void AddToolHelp (HANDLE file) // //========================================================================== -static void AddStackInfo (HANDLE file, void *dumpaddress) +static void AddStackInfo (HANDLE file, void *dumpaddress, DWORD code) { - DWORD *addr = (DWORD *)dumpaddress; + DWORD *addr = (DWORD *)dumpaddress, *jump; DWORD *topOfStack = GetTopOfStack (dumpaddress); BYTE peekb; DWORD peekd; - StackWalk (file, dumpaddress, topOfStack); + jump = topOfStack; + if (code == EXCEPTION_STACK_OVERFLOW) + { + // If the stack overflowed, only dump the first and last 16KB of it. + if (topOfStack - addr > 32768/4) + { + jump = addr + 16384/4; + } + } + + StackWalk (file, dumpaddress, topOfStack, jump); Writef (file, "\r\nStack Contents:\r\n"); DWORD *scan; @@ -747,6 +798,12 @@ static void AddStackInfo (HANDLE file, void *dumpaddress) int i; ptrdiff_t max; + if (scan == jump) + { + scan = topOfStack - 16384/4; + Writef (file, "\r\n . . . Snip . . .\r\n\r\n"); + } + if (topOfStack - scan < 4) { max = topOfStack - scan; @@ -792,7 +849,7 @@ static void AddStackInfo (HANDLE file, void *dumpaddress) // //========================================================================== -static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack) +static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack, DWORD *jump) { DWORD *addr = (DWORD *)dumpaddress; @@ -809,6 +866,12 @@ static void StackWalk (HANDLE file, void *dumpaddress, DWORD *topOfStack) { DWORD_PTR code; + if (scan == jump) + { + scan = topOfStack - 16384/4; + Writef (file, "\r\n\r\n . . . . Snip . . . .\r\n"); + } + if (SafeReadMemory (scan, &code, sizeof(code)) && code >= codeStart && code < codeEnd) { @@ -1793,9 +1856,9 @@ repeat: while (cb - ((LPBYTE)buff_p - buffer) > 150) { ReadFile (info->File, buf16, 16, &read, NULL); - if (read == 0) + if (read == 0 || info->Pointer >= 65536) { - info->Stage++; + info->Stage = read == 0 ? 2 : 3; goto repeat; } char *linestart = buff_p; @@ -1833,10 +1896,15 @@ repeat: case 2: // Write epilogue buff_p += sprintf (buff_p, "\\cf0 }"); - info->Stage++; + info->Stage = 4; break; - case 3: // We're done + case 3: // Write epilogue for truncated file + buff_p += sprintf (buff_p, "--- Rest of file truncated ---\\cf0 }"); + info->Stage = 4; + break; + + case 4: // We're done return TRUE; } diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index 1cdecc1bc..f314682ac 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -357,6 +357,7 @@ CUSTOM_CVAR (Int, in_mouse, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) static BYTE KeyState[256]; static BYTE DIKState[2][NUM_KEYS]; +static int KeysReadCount; static int ActiveDIKState; static void SetSoundPaused (int state); @@ -744,6 +745,10 @@ LRESULT CALLBACK WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) if (wParam) { SetPriorityClass (GetCurrentProcess (), INGAME_PRIORITY_CLASS); + if (GSnd != NULL) + { + GSnd->ResetEnvironment(); + } } else if (!noidle && !netgame) { @@ -1686,8 +1691,18 @@ static void MouseRead_Win32 () POINT pt; int x, y; + if (KeysReadCount == 0) + { + UngrabMouse_Win32(); + } + else if (KeysReadCount == 1 && HaveFocus && !MakeMouseEvents) + { + GrabMouse_Win32(); + } if (!HaveFocus || !MakeMouseEvents || !GetCursorPos (&pt)) + { return; + } x = pt.x - PrevX; y = PrevY - pt.y; @@ -1829,7 +1844,7 @@ static void KeyRead () toState = DIKState[ActiveDIKState ^ 1]; hr = g_pKey->GetDeviceState (256, toState); - if (hr == DIERR_INPUTLOST) + if (hr == DIERR_INPUTLOST || hr == DIERR_NOTACQUIRED) { hr = g_pKey->Acquire (); if (hr != DI_OK) @@ -1844,6 +1859,7 @@ static void KeyRead () } // Successfully got the buffer + KeysReadCount++; ActiveDIKState ^= 1; // Copy key states not handled here from the old to the new buffer diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 66c9ece9b..18aeb6d54 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -519,6 +519,14 @@ LONG WINAPI CatchAllExceptions (LPEXCEPTION_POINTERS info) return EXCEPTION_CONTINUE_EXECUTION; } +static void infiniterecursion(int foo) +{ + if (foo) + { + infiniterecursion(foo); + } +} + int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int nCmdShow) { g_hInst = hInstance; @@ -539,6 +547,19 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n DisplayCrashLog (); exit (0); } + if (__argc == 2 && strcmp (__argv[1], "TestStackCrash") == 0) + { + __try + { + infiniterecursion(1); + } + __except(CrashPointers = *GetExceptionInformation(), + CreateCrashLog (__argv[1], 14), EXCEPTION_EXECUTE_HANDLER) + { + } + DisplayCrashLog (); + exit (0); + } #endif #ifdef REGEXEPEEK @@ -550,17 +571,12 @@ int WINAPI WinMain (HINSTANCE hInstance, HINSTANCE nothing, LPSTR cmdline, int n 0, FALSE, DUPLICATE_SAME_ACCESS); MainThreadID = GetCurrentThreadId(); +#ifndef _DEBUG if (MainThread != INVALID_HANDLE_VALUE) { - // SetUnhandledExceptionFilter is not supposed to do anything if a debugger - // is attached to the process, but one time I did see my exception filter - // used instead of breaking into the debugger. (Or maybe I just forgot to - // run it in the debugger. Whatever. It doesn't hurt to check for one.) -#ifdef _DEBUG - if (!IsDebuggerPresent ()) -#endif - SetUnhandledExceptionFilter (CatchAllExceptions); + SetUnhandledExceptionFilter (CatchAllExceptions); } +#endif #if defined(_DEBUG) && defined(_MSC_VER) // Uncomment this line to make the Visual C++ CRT check the heap before diff --git a/src/win32/i_net.cpp b/src/win32/i_net.cpp deleted file mode 100644 index 32dbcb067..000000000 --- a/src/win32/i_net.cpp +++ /dev/null @@ -1,837 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id: i_net.c,v 1.2 1997/12/29 19:50:54 pekangas Exp $ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// DESCRIPTION: -// Low-level networking code. Uses BSD sockets for UDP networking. -// -//----------------------------------------------------------------------------- - - -/* [Petteri] Check if compiling for Win32: */ -#if defined(__WINDOWS__) || defined(__NT__) || defined(_MSC_VER) || defined(_WIN32) -#ifndef __WIN32__ -# define __WIN32__ -#endif -#endif -/* Follow #ifdef __WIN32__ marks */ - -#include -#include -#include - -/* [Petteri] Use Winsock for Win32: */ -#ifdef __WIN32__ -# define WIN32_LEAN_AND_MEAN -# include -# include -#else -# include -# include -# include -# include -# include -# include -# include -#endif - -#include "doomtype.h" -#include "i_system.h" -#include "d_event.h" -#include "d_net.h" -#include "m_argv.h" -#include "m_alloc.h" -#include "m_swap.h" -#include "m_crc32.h" -#include "d_player.h" -#include "templates.h" - -#include "doomstat.h" - -#include "i_net.h" - - - -/* [Petteri] Get more portable: */ -#ifndef __WIN32__ -typedef int SOCKET; -#define SOCKET_ERROR -1 -#define INVALID_SOCKET -1 -#define closesocket close -#define ioctlsocket ioctl -#define Sleep(x) usleep (x * 1000) -#define WSAEWOULDBLOCK EWOULDBLOCK -#define WSAECONNRESET ECONNRESET -#define WSAGetLastError() errno -#endif - -#ifdef __WIN32__ -#define IPPORT_USERRESERVED 5000 -typedef int socklen_t; -#endif - -extern BOOL CheckAbort (void); - - -// -// NETWORKING -// - -static u_short DOOMPORT = (IPPORT_USERRESERVED + 29); -static SOCKET mysocket = INVALID_SOCKET; -static sockaddr_in sendaddress[MAXNETNODES]; -static BYTE sendplayer[MAXNETNODES]; - -void (*netget) (void); -void (*netsend) (void); - -#ifdef __WIN32__ -char *neterror (void); -#else -#define neterror() strerror(errno) -#endif - -enum -{ - PRE_CONNECT, - PRE_DISCONNECT, - PRE_ALLHERE, - PRE_CONACK, - PRE_ALLHEREACK, - PRE_GO -}; - -// Set PreGamePacket.fake to this so that the game rejects any pregame packets -// after it starts. This translates to NCMD_SETUP|NCMD_MULTI. -#define PRE_FAKE 0x30 - -struct PreGamePacket -{ - BYTE fake; - BYTE message; - BYTE numnodes; - BYTE consolenum; - struct - { - u_long address; - u_short port; - BYTE player; - BYTE pad; - } machines[MAXNETNODES]; -}; - -// -// UDPsocket -// -SOCKET UDPsocket (void) -{ - SOCKET s; - - // allocate a socket - s = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP); - if (s == INVALID_SOCKET) - I_FatalError ("can't create socket: %s", neterror ()); - - return s; -} - -// -// BindToLocalPort -// -void BindToLocalPort (SOCKET s, u_short port) -{ - int v; - sockaddr_in address; - - memset (&address, 0, sizeof(address)); - address.sin_family = AF_INET; - address.sin_addr.s_addr = INADDR_ANY; - address.sin_port = htons(port); - - v = bind (s, (sockaddr *)&address, sizeof(address)); - if (v == SOCKET_ERROR) - I_FatalError ("BindToPort: %s", neterror ()); -} - -int FindNode (sockaddr_in *address) -{ - int i; - - // find remote node number - for (i = 0; isin_addr.s_addr == sendaddress[i].sin_addr.s_addr - && address->sin_port == sendaddress[i].sin_port) - break; - - if (i == doomcom.numnodes) - { - // packet is not from one of the players (new game broadcast?) - i = -1; - } - return i; -} - -// -// PacketSend -// -void PacketSend (void) -{ - int c; - - //printf ("sending %i\n",gametic); - c = sendto (mysocket , (const char*)doomcom.data, doomcom.datalength - ,0,(sockaddr *)&sendaddress[doomcom.remotenode] - ,sizeof(sendaddress[doomcom.remotenode])); - - // if (c == -1) - // I_Error ("SendPacket error: %s",strerror(errno)); -} - - -// -// PacketGet -// -void PacketGet (void) -{ - int c; - socklen_t fromlen; - sockaddr_in fromaddress; - int node; - - fromlen = sizeof(fromaddress); - c = recvfrom (mysocket, (char*)doomcom.data, MAX_MSGLEN, 0 - , (sockaddr *)&fromaddress, &fromlen); - node = FindNode (&fromaddress); - - if (c == SOCKET_ERROR) - { - int err = WSAGetLastError(); - - if (err == WSAECONNRESET && node >= 0) - { // The remote node aborted unexpectedly, so pretend it sent an exit packet - - Printf (PRINT_BOLD, "The connection from %s was dropped\n", - players[sendplayer[node]].userinfo.netname); - - doomcom.data[0] = 0x80; // NCMD_EXIT - c = 1; - } - else if (err != WSAEWOULDBLOCK) - { - I_Error ("GetPacket: %s", neterror ()); - } - else - { - doomcom.remotenode = -1; // no packet - return; - } - } - - doomcom.remotenode = node; - doomcom.datalength = (short)c; -} - -sockaddr_in *PreGet (void *buffer, int bufferlen, bool noabort) -{ - static sockaddr_in fromaddress; - socklen_t fromlen; - int c; - - fromlen = sizeof(fromaddress); - c = recvfrom (mysocket, (char *)buffer, bufferlen, 0, - (sockaddr *)&fromaddress, &fromlen); - - if (c == SOCKET_ERROR) - { - int err = WSAGetLastError(); - if (err == WSAEWOULDBLOCK || (noabort && err == WSAECONNRESET)) - return NULL; // no packet - I_Error ("PreGet: %s", neterror ()); - } - return &fromaddress; -} - -void PreSend (const void *buffer, int bufferlen, sockaddr_in *to) -{ - sendto (mysocket, (const char *)buffer, bufferlen, 0, (sockaddr *)to, sizeof(*to)); -} - -void BuildAddress (sockaddr_in *address, char *name) -{ - hostent *hostentry; // host information entry - u_short port; - char *portpart; - bool isnamed = false; - int curchar; - char c; - - address->sin_family = AF_INET; - - if ( (portpart = strchr (name, ':')) ) - { - *portpart = 0; - port = atoi (portpart + 1); - if (!port) - { - Printf ("Weird port: %s (using %d)\n", portpart + 1, DOOMPORT); - port = DOOMPORT; - } - } - else - { - port = DOOMPORT; - } - address->sin_port = htons(port); - - for (curchar = 0; (c = name[curchar]) ; curchar++) - { - if ((c < '0' || c > '9') && c != '.') - { - isnamed = true; - break; - } - } - - if (!isnamed) - { - address->sin_addr.s_addr = inet_addr (name); - Printf ("Node number %d address %s\n", doomcom.numnodes, name); - } - else - { - hostentry = gethostbyname (name); - if (!hostentry) - I_FatalError ("gethostbyname: couldn't find %s\n%s", name, neterror()); - address->sin_addr.s_addr = *(int *)hostentry->h_addr_list[0]; - Printf ("Node number %d hostname %s\n", - doomcom.numnodes, hostentry->h_name); - } - - if (portpart) - *portpart = ':'; -} - -void CloseNetwork (void) -{ - if (mysocket != INVALID_SOCKET) - { - closesocket (mysocket); - mysocket = INVALID_SOCKET; - } -#ifdef __WIN32__ - WSACleanup (); -#endif -} - -void StartNetwork (bool autoPort) -{ - u_long trueval = 1; -#ifdef __WIN32__ - WSADATA wsad; - - if (WSAStartup (0x0101, &wsad)) - { - I_FatalError ("Could not initialize Windows Sockets"); - } -#endif - - atterm (CloseNetwork); - - netsend = PacketSend; - netget = PacketGet; - netgame = true; - multiplayer = true; - - // create communication socket - mysocket = UDPsocket (); - BindToLocalPort (mysocket, autoPort ? 0 : DOOMPORT); - ioctlsocket (mysocket, FIONBIO, &trueval); -} - -void WaitForPlayers (int i) -{ - if (i == Args.NumArgs() - 1) - I_FatalError ("Not enough parameters after -net"); - - StartNetwork (false); - - // parse player number and host list - doomcom.consoleplayer = (short)(Args.GetArg (i+1)[0]-'1'); - Printf ("Console player number: %d\n", doomcom.consoleplayer); - - doomcom.numnodes = 1; // this node for sure - - i++; - while (++i < Args.NumArgs() && Args.GetArg (i)[0] != '-' && Args.GetArg (i)[0] != '+') - { - BuildAddress (&sendaddress[doomcom.numnodes], Args.GetArg (i)); - doomcom.numnodes++; - } - - Printf ("Total players: %d\n", doomcom.numnodes); - - doomcom.id = DOOMCOM_ID; - doomcom.numplayers = doomcom.numnodes; -} - -void SendAbort (void) -{ - BYTE dis[2] = { PRE_FAKE, PRE_DISCONNECT }; - - while (--doomcom.numnodes > 0) - { - PreSend (dis, 2, &sendaddress[doomcom.numnodes]); - PreSend (dis, 2, &sendaddress[doomcom.numnodes]); - PreSend (dis, 2, &sendaddress[doomcom.numnodes]); - PreSend (dis, 2, &sendaddress[doomcom.numnodes]); - } -} - -void HostGame (int i) -{ - PreGamePacket packet; - int numplayers; - bool gotack[MAXNETNODES]; - int ackcount; - sockaddr_in *from; - int node; - - if ((i == Args.NumArgs() - 1) || !(numplayers = atoi (Args.GetArg(i+1)))) - { // No player count specified, assume 2 - numplayers = 2; - } - - if (numplayers == 1) - { // Special case: Only 1 player, so don't bother starting the network - netgame = false; - multiplayer = true; - doomcom.id = DOOMCOM_ID; - doomcom.numplayers = doomcom.numnodes = 1; - doomcom.consoleplayer = 0; - return; - } - - StartNetwork (false); - - // [JC] - this computer is starting the game, therefore it should - // be the Net Arbitrator. - doomcom.consoleplayer = 0; - Printf ("Console player number: %d\n", doomcom.consoleplayer); - - doomcom.numnodes = 1; - Printf ("Waiting for players...\n"); - - atterm (SendAbort); - - // Wait for numplayers-1 different connections - while (doomcom.numnodes < numplayers) - { - while (doomcom.numnodes < numplayers) - { - if (CheckAbort ()) - { - SendAbort (); - I_FatalError ("Network game synchronization aborted."); - } - - while ( (from = PreGet (&packet, sizeof(packet), false)) ) - { - if (packet.fake != PRE_FAKE) - { - continue; - } - switch (packet.message) - { - case PRE_CONNECT: - node = FindNode (from); - if (node == -1) - { - node = doomcom.numnodes++; - sendaddress[node] = *from; - } - Printf ("Got connect from node %d\n", node); - packet.message = PRE_CONACK; - packet.consolenum = node; - PreSend (&packet, 4, from); - break; - - case PRE_DISCONNECT: - node = FindNode (from); - if (node >= 0) - { - Printf ("Got disconnect from node %d\n", node); - doomcom.numnodes--; - while (node < doomcom.numnodes) - { - sendaddress[node] = sendaddress[node+1]; - node++; - } - } - break; - } - } - } - - // It's possible somebody bailed out after all players were found. - // Unfortunately, this isn't guaranteed to catch all of them. - // Oh well. Better than nothing. - while ( (from = PreGet (&packet, sizeof(packet), false)) ) - { - if (packet.fake == PRE_FAKE && packet.message == PRE_DISCONNECT) - { - node = FindNode (from); - if (node >= 0) - { - doomcom.numnodes--; - while (node < doomcom.numnodes) - { - sendaddress[node] = sendaddress[node+1]; - node++; - } - } - break; - } - } - } - - // Now inform everyone of all machines involved in the game - ackcount = 0; - memset (gotack, 0, sizeof(gotack)); - Printf ("Sending all here\n"); - while (ackcount < doomcom.numnodes - 1) - { - packet.fake = PRE_FAKE; - packet.message = PRE_ALLHERE; - packet.numnodes = doomcom.numnodes - 2; - for (node = 1; node < doomcom.numnodes; node++) - { - int machine, spot = 0; - - if (!gotack[node]) - { - for (spot = 0, machine = 1; machine < doomcom.numnodes; machine++) - { - if (node != machine) - { - packet.machines[spot].address = sendaddress[machine].sin_addr.s_addr; - packet.machines[spot].port = sendaddress[machine].sin_port; - packet.machines[spot].player = node; - - spot++; // fixes problem of new address replacing existing address in - // array, it's supposed to increment the index before getting - // and storing in the packet the next address. - } - } - } - PreSend (&packet, 4 + spot*8, &sendaddress[node]); - } - if (CheckAbort ()) - { - SendAbort (); - I_FatalError ("Network game synchronization aborted."); - } - - while ( (from = PreGet (&packet, sizeof(packet), false)) ) - { - if (packet.fake == PRE_FAKE && packet.message == PRE_ALLHEREACK) - { - node = FindNode (from); - if (node >= 0) - { - if (!gotack[node]) - { - gotack[node] = true; - ackcount++; - } - } - PreSend (&packet, 2, from); - } - } - } - - popterm (); - - // Now go - Printf ("Go\n"); - packet.fake = PRE_FAKE; - packet.message = PRE_GO; - for (node = 1; node < doomcom.numnodes; node++) - { - for (int i = 8; i != 0; --i) - { - PreSend (&packet, 2, &sendaddress[node]); - } - } - - Printf ("Total players: %d\n", doomcom.numnodes); - - doomcom.id = DOOMCOM_ID; - doomcom.numplayers = doomcom.numnodes; - - // On the host, each player's number is the same as its node number - for (i = 0; i < doomcom.numnodes; ++i) - { - sendplayer[i] = i; - } -} - -void SendToHost (BYTE message, BYTE ackmess, bool abortable) -{ - sockaddr_in *from; - bool waiting = true; - PreGamePacket packet; - - while (waiting) - { - if (abortable && CheckAbort ()) - { - SendAbort (); - I_FatalError ("Network game synchronization aborted."); - } - - // Let host know we are here - packet.fake = PRE_FAKE; - packet.message = message; - PreSend (&packet, 2, &sendaddress[1]); - - Sleep (300); - // Listen for acknowledgement - while ( (from = PreGet (&packet, sizeof(packet), true)) ) - { - if (packet.fake == PRE_FAKE && packet.message == ackmess) - { - waiting = false; - - doomcom.consoleplayer = packet.consolenum; - sendplayer[0] = packet.consolenum; - Printf ("Console player number: %d\n", doomcom.consoleplayer); - } - } - } -} - -void JoinGame (int i) -{ - sockaddr_in *from; - bool waiting; - PreGamePacket packet; - - if ((i == Args.NumArgs() - 1) || - (Args.GetArg(i+1)[0] == '-') || - (Args.GetArg(i+1)[0] == '+')) - I_FatalError ("You need to specify the host machine's address"); - - StartNetwork (true); - - // Host is always node 1 - BuildAddress (&sendaddress[1], Args.GetArg(i+1)); - sendplayer[1] = 0; - - // Let host know we are here - SendToHost (PRE_CONNECT, PRE_CONACK, true); - - // Wait for everyone else to connect - waiting = true; - //doomcom.numnodes = 2; - atterm (SendAbort); - - while (waiting) - { - if (CheckAbort ()) - { - SendAbort (); - I_FatalError ("Network game synchronization aborted."); - } - - Sleep (300); - while (waiting && (from = PreGet (&packet, sizeof(packet), false)) ) - { - if (packet.fake != PRE_FAKE) - { - continue; - } - switch (packet.message) - { - case PRE_ALLHERE: - if (doomcom.numnodes == 0) - { - int node; - - packet.numnodes = packet.numnodes; - doomcom.numnodes = packet.numnodes + 2; - for (node = 0; node < packet.numnodes; node++) - { - sendaddress[node+2].sin_addr.s_addr = packet.machines[node].address; - sendaddress[node+2].sin_port = packet.machines[node].port; - sendplayer[node+2] = packet.machines[node].player; - - // [JC] - fixes problem of games not starting due to - // no address family being assigned to nodes stored in - // sendaddress[] from the All Here packet. - sendaddress[node+2].sin_family = AF_INET; - } - } - - Printf ("Received All Here, sending ACK\n"); - packet.fake = PRE_FAKE; - packet.message = PRE_ALLHEREACK; - PreSend (&packet, 2, &sendaddress[1]); - break; - case PRE_GO: - Printf ("Go\n"); - waiting = false; - break; - case PRE_DISCONNECT: - I_FatalError ("Host cancelled the game"); - break; - } - } - } - - popterm (); - - Printf ("Total players: %d\n", doomcom.numnodes); - - doomcom.id = DOOMCOM_ID; - doomcom.numplayers = doomcom.numnodes; -} - -// -// I_InitNetwork -// -void I_InitNetwork (void) -{ - int i; - char *v; - - memset (&doomcom, 0, sizeof(doomcom)); - - // set up for network - v = Args.CheckValue ("-dup"); - if (v) - { - doomcom.ticdup = clamp (atoi (v), 1, MAXTICDUP); - } - else - { - doomcom.ticdup = 1; - } - - if (Args.CheckParm ("-extratic")) - doomcom.extratics = 1; - else - doomcom.extratics = 0; - - v = Args.CheckValue ("-port"); - if (v) - { - DOOMPORT = atoi (v); - Printf ("using alternate port %i\n", DOOMPORT); - } - - // parse network game options, - // -net ... - // -or- - // player 1: -host - // player x: -join - if ( (i = Args.CheckParm ("-net")) ) - WaitForPlayers (i); - else if ( (i = Args.CheckParm ("-host")) ) - HostGame (i); - else if ( (i = Args.CheckParm ("-join")) ) - JoinGame (i); - else - { - // single player game - netgame = false; - multiplayer = false; - doomcom.id = DOOMCOM_ID; - doomcom.numplayers = doomcom.numnodes = 1; - doomcom.consoleplayer = 0; - return; - } -} - - -void I_NetCmd (void) -{ - if (doomcom.command == CMD_SEND) - { - netsend (); - } - else if (doomcom.command == CMD_GET) - { - netget (); - } - else - I_Error ("Bad net cmd: %i\n",doomcom.command); -} - -#ifdef __WIN32__ -char *neterror (void) -{ - static char neterr[16]; - int code; - - switch (code = WSAGetLastError ()) { - case WSAEACCES: return "EACCES"; - case WSAEADDRINUSE: return "EADDRINUSE"; - case WSAEADDRNOTAVAIL: return "EADDRNOTAVAIL"; - case WSAEAFNOSUPPORT: return "EAFNOSUPPORT"; - case WSAEALREADY: return "EALREADY"; - case WSAECONNABORTED: return "ECONNABORTED"; - case WSAECONNREFUSED: return "ECONNREFUSED"; - case WSAECONNRESET: return "ECONNRESET"; - case WSAEDESTADDRREQ: return "EDESTADDRREQ"; - case WSAEFAULT: return "EFAULT"; - case WSAEHOSTDOWN: return "EHOSTDOWN"; - case WSAEHOSTUNREACH: return "EHOSTUNREACH"; - case WSAEINPROGRESS: return "EINPROGRESS"; - case WSAEINTR: return "EINTR"; - case WSAEINVAL: return "EINVAL"; - case WSAEISCONN: return "EISCONN"; - case WSAEMFILE: return "EMFILE"; - case WSAEMSGSIZE: return "EMSGSIZE"; - case WSAENETDOWN: return "ENETDOWN"; - case WSAENETRESET: return "ENETRESET"; - case WSAENETUNREACH: return "ENETUNREACH"; - case WSAENOBUFS: return "ENOBUFS"; - case WSAENOPROTOOPT: return "ENOPROTOOPT"; - case WSAENOTCONN: return "ENOTCONN"; - case WSAENOTSOCK: return "ENOTSOCK"; - case WSAEOPNOTSUPP: return "EOPNOTSUPP"; - case WSAEPFNOSUPPORT: return "EPFNOSUPPORT"; - case WSAEPROCLIM: return "EPROCLIM"; - case WSAEPROTONOSUPPORT: return "EPROTONOSUPPORT"; - case WSAEPROTOTYPE: return "EPROTOTYPE"; - case WSAESHUTDOWN: return "ESHUTDOWN"; - case WSAESOCKTNOSUPPORT: return "ESOCKTNOSUPPORT"; - case WSAETIMEDOUT: return "ETIMEDOUT"; - case WSAEWOULDBLOCK: return "EWOULDBLOCK"; - case WSAHOST_NOT_FOUND: return "HOST_NOT_FOUND"; - case WSANOTINITIALISED: return "NOTINITIALISED"; - case WSANO_DATA: return "NO_DATA"; - case WSANO_RECOVERY: return "NO_RECOVERY"; - case WSASYSNOTREADY: return "SYSNOTREADY"; - case WSATRY_AGAIN: return "TRY_AGAIN"; - case WSAVERNOTSUPPORTED: return "VERNOTSUPPORTED"; - case WSAEDISCON: return "EDISCON"; - - default: - sprintf (neterr, "%d", code); - return neterr; - } -} -#endif diff --git a/src/win32/i_net.h b/src/win32/i_net.h deleted file mode 100644 index 5b8496cb0..000000000 --- a/src/win32/i_net.h +++ /dev/null @@ -1,30 +0,0 @@ -// Emacs style mode select -*- C++ -*- -//----------------------------------------------------------------------------- -// -// $Id: i_net.h,v 1.1.1.1 1997/12/28 12:59:02 pekangas Exp $ -// -// Copyright (C) 1993-1996 by id Software, Inc. -// -// This source is available for distribution and/or modification -// only under the terms of the DOOM Source Code License as -// published by id Software. All rights reserved. -// -// The source is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License -// for more details. -// -// DESCRIPTION: -// System specific network interface stuff. -// -//----------------------------------------------------------------------------- - - -#ifndef __I_NET_H__ -#define __I_NET_H__ - -// Called by D_DoomMain. -void I_InitNetwork (void); -void I_NetCmd (void); - -#endif diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index 2850a9d75..9c069d005 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -1599,6 +1599,7 @@ bool DDrawFB::PaintToWindow () PrimarySurf->Blt (&rect, BackSurf, NULL, DDBLT_WAIT, NULL); } } + Buffer = NULL; LOG ("Did paint to window\n"); } return true; diff --git a/zdoom.vcproj b/zdoom.vcproj index c48aa9e0c..49669e3bb 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1847,6 +1847,10 @@ /> + + @@ -4526,6 +4530,10 @@ RelativePath=".\src\i_movie.h" > + + @@ -5271,46 +5279,6 @@ /> - - - - - - - - - - - - - - - - @@ -10080,82 +10048,6 @@ /> - - - - - - - - - - - - - - - - - - - - - - - - - - - -