diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 4bb0a59f44..d0ba96e02d 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -53,7 +53,7 @@ March 7, 2008 hardware 3D support is used and default to false. - Removed the libFLAC source, since FMOD Ex has native FLAC support. - Removed the altsound code, since it was terribly gimped in comparison to - the FMOD code. It's original purpose was to have been as a springboard for + the FMOD code. Its original purpose was to have been as a springboard for writing a non-FMOD sound system for Unix-y systems, but that never happened. - Finished preliminary FMOD Ex support. @@ -66,6 +66,15 @@ March 6, 2008 it seems to have a working volume control. - Renamed music_midi_stream.cpp to music_midi_base.cpp. - Moved the WinMM MIDI code into a new container class. +- Fixed: StatusBar and screen need to be barriered, because they are roots + but can also change at runtime. +- Fixed: Objects that are forcibly deleted outside the GC need to be removed + from the gray list too. + +March 5, 2008 +- Fixed: Thinkers needed write barriers when they were removed from their + lists. +- Fixed: DLevelScript::Link() and Unlink() needed write barriers. March 4, 2008 - Moved the identical code between the MUS and MIDI streamers into a new base @@ -115,6 +124,20 @@ March 1, 2008 (Changes by Graf Zahl) - Gave Strife's instant death sector type its own damage type. February 29, 2008 +- Changed the default GC parameters to make it run more aggressively. +- Added NULL checks to the GC::WriteBarrier() wrappers. +- Fixed: The DObject destructor set GC::SweepPos incorrectly if it pointed + at that object being deleted. +- Added "soft roots" to the garbage collector. These are similar in + purpose to setting the OF_Fixed bit, but they behave as full-fledged roots + as far as the collector is concerned, so any objects reachable through + them will not be collected. +- Added support for the OF_Fixed bit. This is ONLY for simple objects which + do not contain pointers to other objects, because all it does is prevent + an object that is otherwise dead from being freed. It does not include + the object in the propagate stage if it is unreachable, so any objects + that are only reachable through it will still be freed unless they are + also fixed. - Fixed: R_SetupAddClampCol() checked add4cols' memory instead of adclamp4cols' memory when deciding if it should skip modification. @@ -125,6 +148,8 @@ February 28, 2008 February 27, 2008 - Added assembly versions of rt_add4cols and rt_addclamp4cols. +- Added a read barrier to FArchive::SerializeObject() to make sure that + objects that are being euthanized are not stored in the archive. February 26, 2008 - Added an assembly version of rt_shaded4cols, since that's the main decal @@ -139,12 +164,54 @@ February 26, 2008 the translation in one step and the drawing in another. This lets me call the untranslated drawer to do the real drawing instead of mostly duplicating them. Performance wise, there is practically no difference from before. +- Fixed: Using +stat from the command line caused a crash. +- More write barriers and pointer declarations. Here are rules I've come up + with so far for when write barriers can be ommitted: + * Initializing pointers for a newly created object: A new object can never + black, so none of its pointers that get set by the constructor (or code + just following its creation) need to be behind write barriers. + * Creating a new thinker and storing it in a pointer: The thinker + constructor already puts it behind a write barrier when it links it into + the thinker list, so you don't need to do it again. + * As a corollary of the above: No pointers to thinkers should need to be + behind write barriers, because it is incorrect to have a thinker that is + live but not in a thinker list. I realized this while I was going through + the long list of actor target references, so there are some write barriers + for those in place already, since they don't hurt to have them around. + As a consequence of the last point, I think I'm done placing write barriers + in all their necessary places without even touching most of the code. I'm + going to let it sit like this for a few days to see if I can think of a + counter-example where a live thinker wouldn't be in a thinker list, but it + feels correct to me right now. February 25, 2008 (Changes by Graf Zahl) - Fixed: The DECORATE expression evaluator's random function could produce incorrect results for ranges > 255. Changed so that FRandom's default implementation is used instead. +February 24, 2008 +- Fixed: DDecalFader::Tick() still referenced TheDecal even after destroying + it. +- Added write barriers around the thinker list insertions in dthinker.cpp. + +February 23, 2008 (Changes by Graf Zahl) +- Fixed: AWeaponPiece didn't declare its FullWeapon pointer as such. +- Fixed: Hexen's random player class skill menu was missing the '$' indicating + a string table identifier. +- Fixed: DCorpsePointer::Serialize didn't call the super method. + +February 22, 2008 +- Moved DSeqNode's and its children's destructor code into their Destroy() + methods. +- Moved DSectorEffect's destructor code into a Destroy() method. +- Changed the myoffsetof definition to match DECLARE_POINTER's because GCC + started complaining about its use in p_setup.cpp, though I'm not sure why. +- Added a pointer list to DACSThinker so that the collector can find scripts + instead of thinking they're all dead. +- Added read barriers to sector_t's pointers. +- Used the HAS_OBJECT_POINTERS macros to locate places to place TObjPtrs to + form read barriers. + February 21, 2008 - Fixed: DThinker::SerializeAll() did not serialize any thinkers in the FreshThinkers lists. These thinkers would still be saved in the savegame if @@ -162,6 +229,30 @@ February 21, 2008 work for GCC (and presumably VC++, though I never ran into that case with it) because it tried to stringify something that wasn't a macro argument. +February 20, 2008 +- Changed the DHUDMessage deletions into destroys. +- Added read barriers to the pointers inside AActor. +- Split the AActor::LastLook union into its constituent parts. + +February 20, 2008 (Changes by Graf Zahl) +- Added a modified version of Karate Chris's submission for killing specific + monsters with the 'Kill' ccmd. + +February 19, 2008 +- Added a rough initial garbage collector, based largely on Lua's. There are + no write or read barriers in place yet, so it's not a very close + approximation of the pointer cleaning code that was in place before, but it + does collect stuff. But guess what! Nuts.wad ran at 1-2 FPS before. Now + it's way, way more and easily stays above 35 FPS. The performance hit when + the GC is running is pretty minimal compared to the old way, which was in + many ways like a full garbage collection every tic. +- Changed the status bars into DObjects. +- Fixed: FBaseStatusBar::Tick() deleted hud messages instead of destroying + them. +- Changed the global Args object to a pointer to one. +- Changed several DArgs deletions into destroys. +- Removed DBoundingBox from the DObject hierarchy. + February 20, 2008 (Changes by Graf Zahl) - Added a modified version of Karate Chris's submission for killing specific monsters with the 'Kill' ccmd. @@ -760,7 +851,7 @@ January 1, 2008 - Fixed a D3D memory leak on every frame in windowed mode and the same thing for the screen wipes. Note to self: If it's an interface, be sure to Release it, because it will be AddRef'ed before being returned to you. -- Moved the BlendView() call out of FBaseStatusBar::Draw() so that it can be +- Moved the BlendView() call out of DBaseStatusBar::Draw() so that it can be applied before copying the 3D scene to the screen underneath the 2D parts. - Restored the console's darkening level to its old table-based amount. - Fixed D3DFB::SetColorOverlay()'s incorrect calculations. @@ -4458,7 +4549,7 @@ April 18, 2006 (Changes by Graf Zahl) fighting the programmer. April 18, 2006 -- Fixed: FBaseStatusBar::DrBNumber() should behave like Doom's +- Fixed: DBaseStatusBar::DrBNumber() should behave like Doom's STlib_drawNum(), and FDoomStatusBarTexture::DrawToBar() should add the textures left offset to the x coordinate before drawing. These fix Twice Risen's status bar. @@ -5271,7 +5362,7 @@ February 11, 2005 February 10, 2005 - Fixed: The screen fading ACS commands did not work when viewing through a camera - because FBaseStatusBar::BlendView() did not think there was a player to get those + because DBaseStatusBar::BlendView() did not think there was a player to get those values from. Now, the blend comes from either the player viewing from or the console player if the current view is not from a player. - Fixed: Returning to a previously visited level in a hub with fewer players than you @@ -5446,7 +5537,7 @@ January 26, 2005 Unfortunately, I didn't bump the demo version between 2.0.63a and 2.0.90, so anything pre-2.0.97 won't play with 2.0.97, even though there's probably no changes that would cause desynching between 96 and 97. Oh well. -- Fixed FBaseStatusBar::DrBNumber(Outer) to work when some of the big number +- Fixed DBaseStatusBar::DrBNumber(Outer) to work when some of the big number graphics are missing. January 15, 2005 @@ -5622,7 +5713,7 @@ December 18, 2004 on top of the next digit. - Fixed: The Doom HUD drew the selected inventory item on top of the secondary ammo if both were present. -- Moved the DrawPowerups() call out of FBaseStatusBar::Draw() and into +- Moved the DrawPowerups() call out of DBaseStatusBar::Draw() and into DrawTopStuff(), so the Doom HUD key display won't cover them up - Fixed: If you started flying and then pressed the land key, you wouldn't be able to fly again until the Wings of Wrath wore off. This was done by changing @@ -6478,7 +6569,7 @@ July 15, 2004 - Updated to FMOD 3.73. July 14, 2004 -- Moved the full-screen HUD coordinate logic out of FBaseStatusBar and into +- Moved the full-screen HUD coordinate logic out of DBaseStatusBar and into DCanvas::DrawTexture. This is so that powerups can draw their status icons themselves without needing to hook into the status bar. - Reimplemented the Tome of Power. @@ -7047,7 +7138,7 @@ December 12, 2003 up okay in Doom.) - Added a fix to the blockmap tracers where all the blocks along the trace are crossed on their corners. -- Fixed a potential crash in FBaseStatusBar::DrawMessages() when a HUD message +- Fixed a potential crash in DBaseStatusBar::DrawMessages() when a HUD message removes itself as part of its drawing process. - Fixed: A few of the Strife weapons were erroneously defined with WIF_NOALERT. - Fixed: Sky textures defaulted to 0 if a map had a MAPINFO that did not @@ -7195,7 +7286,7 @@ November 23, 2003 things spawned afterward. - Added calls to SetWindowLongPtr to take away the window's border in fullscreen mode and put it back in windowed mode. -- Fixed FBaseStatusBar::RepositionCoords() so that LilWhiteMouse's Chosen +- Fixed DBaseStatusBar::RepositionCoords() so that LilWhiteMouse's Chosen ammo icons appear on the fullscreen HUD again. November 21, 2003 @@ -7927,7 +8018,7 @@ July 30, 2003 - Added nonexistant texture check to the warping texture setup. July 28, 2003 -- Removed the ScaleCopy canvas from FBaseStatusBar, because everything is now +- Removed the ScaleCopy canvas from DBaseStatusBar, because everything is now drawn to the screen directly even when the status bar is scaled. - Changed the pitch calculations in the DSimpleCanvas constructor to provide better wall drawing performance at all resolutions. @@ -11069,7 +11160,7 @@ October 23, 2001 torch lighting up the entire sky, so skies should ignore the setting of fixedlightlev. - Fixed the scaled status bar. I was simply forgetting to add the image - offsets in FBaseStatusBar::DrawImage() before calling CopyToScreen(). + offsets in DBaseStatusBar::DrawImage() before calling CopyToScreen(). - Added code to let decals move with sliding and rotating polyobjects. - Fixed: The wait console command waited one tic too few. - Fixed a resizing problem with playing movies windowed. @@ -11889,7 +11980,7 @@ April 7, 2001 big ammo count when switching to a weapon that does not use ammo. - Fixed: At certain screen heights, scaled status bars would not touch the bottom of the screen because of inaccuracy in the calculation of ::ST_Y - in FBaseStatusBar::SetScaled(). + in DBaseStatusBar::SetScaled(). - Added separate pickup sounds for health, armor, and ammo items. - Improved sound link resolution in S_StartSound() so that regular sounds can alias player sounds. diff --git a/snes_spc/Makefile b/snes_spc/Makefile index 4a3d11ab9d..c32c06cc71 100644 --- a/snes_spc/Makefile +++ b/snes_spc/Makefile @@ -1,11 +1,11 @@ # Makefile for snes_spc, derived from zlib/Makefile.mgw. -ifeq (Windows_NT,$(OS)) - CMD=1 -endif -ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys) - CMD=0 -endif +ifeq (Windows_NT,$(OS)) + CMD=1 +endif +ifeq ($(findstring msys,$(shell sh --version 2>nul)),msys) + CMD=0 +endif STATICLIB = libsnes_spc.a diff --git a/src/actor.h b/src/actor.h index a08ea5d68a..e6e3d9c51c 100644 --- a/src/actor.h +++ b/src/actor.h @@ -543,9 +543,9 @@ public: bool CheckLocalView (int playernum) const; // Finds the first item of a particular type. - AInventory *FindInventory (const PClass *type) const; - AInventory *FindInventory (FName type) const; - template T *FindInventory () const + AInventory *FindInventory (const PClass *type); + AInventory *FindInventory (FName type); + template T *FindInventory () { return static_cast (FindInventory (RUNTIME_CLASS(T))); } @@ -554,7 +554,7 @@ public: AInventory *GiveInventoryType (const PClass *type); // Returns the first item held with IF_INVBAR set. - AInventory *FirstInv () const; + AInventory *FirstInv (); // Tries to give the actor some ammo. bool GiveAmmo (const PClass *type, int amount); @@ -570,7 +570,7 @@ public: void ConversationAnimation (int animnum); // Make this actor hate the same things as another actor - void CopyFriendliness (const AActor *other, bool changeTarget); + void CopyFriendliness (AActor *other, bool changeTarget); // Moves the other actor's inventory to this one void ObtainInventory (AActor *other); @@ -645,35 +645,32 @@ public: BYTE movedir; // 0-7 SBYTE visdir; SWORD movecount; // when 0, select a new dir - AActor *target; // thing being chased/attacked (or NULL) + TObjPtr target; // thing being chased/attacked (or NULL) // also the originator for missiles - AActor *lastenemy; // Last known enemy -- killogh 2/15/98 - AActor *LastHeard; // [RH] Last actor this one heard + TObjPtr lastenemy; // Last known enemy -- killogh 2/15/98 + TObjPtr LastHeard; // [RH] Last actor this one heard SDWORD reactiontime; // if non 0, don't attack yet; used by // player to freeze a bit after teleporting SDWORD threshold; // if > 0, the target will be chased // no matter what (even if shot) player_s *player; // only valid if type of APlayerPawn - union - { - AActor *Actor; // Actor last looked for (if TIDtoHate != 0) - SDWORD PlayerNumber; // Player number last looked for - } LastLook; + TObjPtr LastLookActor; // Actor last looked for (if TIDtoHate != 0) WORD SpawnPoint[3]; // For nightmare respawn WORD SpawnAngle; int skillrespawncount; - AActor *tracer; // Thing being chased/attacked for tracers - AActor *master; // Thing which spawned this one (prevents mutual attacks) + TObjPtr tracer; // Thing being chased/attacked for tracers + TObjPtr master; // Thing which spawned this one (prevents mutual attacks) fixed_t floorclip; // value to use for floor clipping SWORD tid; // thing identifier BYTE special; // special int args[5]; // special arguments AActor *inext, **iprev;// Links to other mobjs in same bucket - AActor *goal; // Monster's goal if not chasing anything + TObjPtr goal; // Monster's goal if not chasing anything BYTE waterlevel; // 0=none, 1=feet, 2=waist, 3=eyes BYTE boomwaterlevel; // splash information for non-swimmable water sectors BYTE MinMissileChance;// [RH] If a random # is > than this, then missile attack. + SBYTE LastLookPlayerNumber;// Player number last looked for (if TIDtoHate == 0) WORD SpawnFlags; fixed_t meleerange; // specifies how far a melee attack reaches. fixed_t meleethreshold; // Distance below which a monster doesn't try to shoot missiles anynore @@ -684,9 +681,10 @@ public: int bouncecount; // Strife's grenades only bounce twice before exploding fixed_t gravity; // [GRB] Gravity factor int FastChaseStrafeCount; - // [KS] These temporary-use properties are needed to allow A_LookEx to pass it's parameters to LookFor*InBlock in - // P_BlockmapSearch so that friendly enemies and monsters that look for other monsters can find their targets properly. - // If there's a cleaner way of doing this, feel free to remove these and use that method instead. + // [KS] These temporary-use properties are needed to allow A_LookEx to pass its parameters to + // LookFor*InBlock in P_BlockmapSearch so that friendly enemies and monsters that look for + // other monsters can find their targets properly. If there's a cleaner way of doing this, + // feel free to remove these and use that method instead. fixed_t LookExMinDist; // Minimum sight distance fixed_t LookExMaxDist; // Maximum sight distance angle_t LookExFOV; // Field of Vision @@ -694,7 +692,7 @@ public: // a linked list of sectors where this object appears struct msecnode_s *touching_sectorlist; // phares 3/14/98 - AInventory *Inventory; // [RH] This actor's inventory + TObjPtr Inventory; // [RH] This actor's inventory DWORD InventoryID; // A unique ID to keep track of inventory items //Added by MC: diff --git a/src/b_bot.h b/src/b_bot.h index 1dd48864b6..607fd01ff9 100644 --- a/src/b_bot.h +++ b/src/b_bot.h @@ -117,7 +117,7 @@ public: botinfo_t *botinfo; int spawn_tries; int wanted_botnum; - AActor *firstthing; + TObjPtr firstthing; bool m_Thinking; @@ -141,8 +141,8 @@ protected: bool ctf; int loaded_bots; int t_join; - AActor *body1; - AActor *body2; + TObjPtr body1; + TObjPtr body2; bool observer; //Consoleplayer is observer. }; diff --git a/src/b_func.cpp b/src/b_func.cpp index e77761bc50..8e4fe03d01 100644 --- a/src/b_func.cpp +++ b/src/b_func.cpp @@ -453,16 +453,26 @@ void DCajunMaster::SetBodyAt (fixed_t x, fixed_t y, fixed_t z, int hostnum) if (hostnum == 1) { if (body1) + { body1->SetOrigin (x, y, z); + } else + { body1 = Spawn ("CajunBodyNode", x, y, z, NO_REPLACE); + GC::WriteBarrier(this, body1); + } } else if (hostnum == 2) { if (body2) + { body2->SetOrigin (x, y, z); + } else + { body2 = Spawn ("CajunBodyNode", x, y, z, NO_REPLACE); + GC::WriteBarrier(this, body2); + } } } diff --git a/src/b_game.cpp b/src/b_game.cpp index d8dcccf1d3..cdb2e52e96 100644 --- a/src/b_game.cpp +++ b/src/b_game.cpp @@ -94,9 +94,11 @@ DCajunMaster::~DCajunMaster() ForgetBots(); if (getspawned != NULL) { - delete getspawned; + getspawned->Destroy(); getspawned = NULL; } + // FIXME: Make this object proper + ObjectFlags |= OF_Cleanup | OF_YesReallyDelete; } //This function is called every tick (from g_game.c), diff --git a/src/c_console.cpp b/src/c_console.cpp index 9a3920a1f9..9ea68023fb 100644 --- a/src/c_console.cpp +++ b/src/c_console.cpp @@ -229,7 +229,7 @@ CUSTOM_CVAR (Int, msgmidcolor2, 4, CVAR_ARCHIVE) static void maybedrawnow (bool tick, bool force) { // FIXME: Does not work right with hw2d - if (ConsoleDrawing || !gotconback || screen->IsLocked () || screen->Accel2D) + if (ConsoleDrawing || !gotconback || screen == NULL || screen->IsLocked () || screen->Accel2D) { return; } diff --git a/src/c_dispatch.cpp b/src/c_dispatch.cpp index fb43ec2736..2d5abf050a 100644 --- a/src/c_dispatch.cpp +++ b/src/c_dispatch.cpp @@ -1250,23 +1250,23 @@ CCMD (key) // These all begin with '+' as opposed to '-'. void C_ExecCmdLineParams () { - for (int currArg = 1; currArg < Args.NumArgs(); ) + for (int currArg = 1; currArg < Args->NumArgs(); ) { - if (*Args.GetArg (currArg++) == '+') + if (*Args->GetArg (currArg++) == '+') { FString cmdString; int cmdlen = 1; int argstart = currArg - 1; - while (currArg < Args.NumArgs()) + while (currArg < Args->NumArgs()) { - if (*Args.GetArg (currArg) == '-' || *Args.GetArg (currArg) == '+') + if (*Args->GetArg (currArg) == '-' || *Args->GetArg (currArg) == '+') break; currArg++; cmdlen++; } - cmdString = BuildString (cmdlen, Args.GetArgList (argstart)); + cmdString = BuildString (cmdlen, Args->GetArgList (argstart)); if (!cmdString.IsEmpty()) { C_DoCommand (&cmdString[1]); diff --git a/src/cmdlib.h b/src/cmdlib.h index a6a4509758..af31bb2641 100644 --- a/src/cmdlib.h +++ b/src/cmdlib.h @@ -23,7 +23,7 @@ #include // the dec offsetof macro doesnt work very well... -#define myoffsetof(type,identifier) ((size_t)&((type *)0)->identifier) +#define myoffsetof(type,identifier) ((size_t)&((type *)1)->identifier - 1) int Q_filelength (FILE *f); bool FileExists (const char *filename); diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 9a728287b3..071e2a5ea1 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -161,7 +161,7 @@ public: void DoPickupSpecial (AActor *toucher); private: const PClass *DetermineType (); - AInventory *RealPickup; + TObjPtr RealPickup; }; IMPLEMENT_POINTY_CLASS (ADehackedPickup) diff --git a/src/d_main.cpp b/src/d_main.cpp index dae6892d6e..0a614962ee 100644 --- a/src/d_main.cpp +++ b/src/d_main.cpp @@ -745,7 +745,6 @@ void D_DoomLoop () if (singletics) { I_StartTic (); - DObject::BeginFrame (); D_ProcessEvents (); G_BuildTiccmd (&netcmds[consoleplayer][maketic%BACKUPTICS]); //Added by MC: For some of that bot stuff. The main bot function. @@ -774,7 +773,7 @@ void D_DoomLoop () G_Ticker (); gametic++; maketic++; - DObject::EndFrame (); + GC::CheckGC (); Net_NewMakeTic (); } else @@ -1644,7 +1643,7 @@ static EIWADType IdentifyVersion (const char *zdoom_wad) { WadStuff wads[sizeof(IWADNames)/sizeof(char *)]; size_t foundwads[NUM_IWAD_TYPES] = { 0 }; - const char *iwadparm = Args.CheckValue ("-iwad"); + const char *iwadparm = Args->CheckValue ("-iwad"); size_t numwads; int pickwad; size_t i; @@ -1914,7 +1913,7 @@ static const char *BaseFileSearch (const char *file, const char *ext, bool lookf bool ConsiderPatches (const char *arg, const char *ext) { bool noDef = false; - DArgs *files = Args.GatherFiles (arg, ext, false); + DArgs *files = Args->GatherFiles (arg, ext, false); if (files->NumArgs() > 0) { @@ -1930,7 +1929,7 @@ bool ConsiderPatches (const char *arg, const char *ext) } noDef = true; } - delete files; + files->Destroy(); return noDef; } @@ -2038,8 +2037,7 @@ void D_DoomMain (void) const IWADInfo *iwad_info; srand(I_MSTime()); - - atterm (DObject::StaticShutdown); + PClass::StaticInit (); atterm (C_DeinitConsole); @@ -2121,19 +2119,19 @@ void D_DoomMain (void) execFiles = new DArgs; GameConfig->AddAutoexec (execFiles, GameNames[gameinfo.gametype]); D_MultiExec (execFiles, true); - delete execFiles; + execFiles->Destroy(); // Run .cfg files at the start of the command line. - execFiles = Args.GatherFiles (NULL, ".cfg", false); + execFiles = Args->GatherFiles (NULL, ".cfg", false); D_MultiExec (execFiles, true); - delete execFiles; + execFiles->Destroy(); C_ExecCmdLineParams (); // [RH] do all +set commands on the command line - DArgs *files = Args.GatherFiles ("-file", ".wad", true); - DArgs *files1 = Args.GatherFiles (NULL, ".zip", false); - DArgs *files2 = Args.GatherFiles (NULL, ".pk3", false); - DArgs *files3 = Args.GatherFiles (NULL, ".txt", false); + DArgs *files = Args->GatherFiles ("-file", ".wad", true); + DArgs *files1 = Args->GatherFiles (NULL, ".zip", false); + DArgs *files2 = Args->GatherFiles (NULL, ".pk3", false); + DArgs *files3 = Args->GatherFiles (NULL, ".txt", false); if (files->NumArgs() > 0 || files1->NumArgs() > 0 || files2->NumArgs() > 0 || files3->NumArgs() > 0) { // Check for -file in shareware @@ -2160,10 +2158,10 @@ void D_DoomMain (void) D_AddWildFile (files3->GetArg (i)); } } - delete files; - delete files1; - delete files2; - delete files3; + files->Destroy(); + files1->Destroy(); + files2->Destroy(); + files3->Destroy(); Printf ("W_Init: Init WADfiles.\n"); Wads.InitMultipleFiles (&wadfiles); @@ -2193,18 +2191,18 @@ void D_DoomMain (void) Printf ("P_Init: Checking cmd-line parameters...\n"); flags = dmflags; - if (Args.CheckParm ("-nomonsters")) flags |= DF_NO_MONSTERS; - if (Args.CheckParm ("-respawn")) flags |= DF_MONSTERS_RESPAWN; - if (Args.CheckParm ("-fast")) flags |= DF_FAST_MONSTERS; + if (Args->CheckParm ("-nomonsters")) flags |= DF_NO_MONSTERS; + if (Args->CheckParm ("-respawn")) flags |= DF_MONSTERS_RESPAWN; + if (Args->CheckParm ("-fast")) flags |= DF_FAST_MONSTERS; - devparm = !!Args.CheckParm ("-devparm"); + devparm = !!Args->CheckParm ("-devparm"); - if (Args.CheckParm ("-altdeath")) + if (Args->CheckParm ("-altdeath")) { deathmatch = 1; flags |= DF_ITEMS_RESPAWN; } - else if (Args.CheckParm ("-deathmatch")) + else if (Args->CheckParm ("-deathmatch")) { deathmatch = 1; flags |= DF_WEAPONS_STAY | DF_ITEMS_RESPAWN; @@ -2223,27 +2221,27 @@ void D_DoomMain (void) } autostart = false; - const char *val = Args.CheckValue ("-skill"); + const char *val = Args->CheckValue ("-skill"); if (val) { gameskill = val[0] - '1'; autostart = true; } - p = Args.CheckParm ("-warp"); - if (p && p < Args.NumArgs() - 1) + p = Args->CheckParm ("-warp"); + if (p && p < Args->NumArgs() - 1) { int ep, map; if (gameinfo.flags & GI_MAPxx) { ep = 1; - map = atoi (Args.GetArg(p+1)); + map = atoi (Args->GetArg(p+1)); } else { - ep = atoi (Args.GetArg(p+1)); - map = p < Args.NumArgs() - 2 ? atoi (Args.GetArg(p+2)) : 10; + ep = atoi (Args->GetArg(p+1)); + map = p < Args->NumArgs() - 2 ? atoi (Args->GetArg(p+2)) : 10; if (map < 1 || map > 9) { map = ep; @@ -2256,19 +2254,19 @@ void D_DoomMain (void) } // [RH] Hack to handle +map - p = Args.CheckParm ("+map"); - if (p && p < Args.NumArgs()-1) + p = Args->CheckParm ("+map"); + if (p && p < Args->NumArgs()-1) { - MapData * map = P_OpenMapData(Args.GetArg (p+1)); + MapData * map = P_OpenMapData(Args->GetArg (p+1)); if (map == NULL) { - Printf ("Can't find map %s\n", Args.GetArg (p+1)); + Printf ("Can't find map %s\n", Args->GetArg (p+1)); } else { delete map; - strncpy (startmap, Args.GetArg (p+1), 8); - Args.GetArg (p)[0] = '-'; + strncpy (startmap, Args->GetArg (p+1), 8); + Args->GetArg (p)[0] = '-'; autostart = true; } } @@ -2281,7 +2279,7 @@ void D_DoomMain (void) // We do not need to support -cdrom under Unix, because all the files // that would go to c:\\zdoomdat are already stored in .zdoom inside // the user's home directory. - if (Args.CheckParm("-cdrom")) + if (Args->CheckParm("-cdrom")) { Printf (GStrings("D_CDROM")); mkdir (CDROM_DIR, 0); @@ -2293,7 +2291,7 @@ void D_DoomMain (void) UCVarValue value; static char one_hundred[] = "100"; - value.String = Args.CheckValue ("-turbo"); + value.String = Args->CheckValue ("-turbo"); if (value.String == NULL) value.String = one_hundred; else @@ -2302,7 +2300,7 @@ void D_DoomMain (void) turbo.SetGenericRepDefault (value, CVAR_String); } - v = Args.CheckValue ("-timer"); + v = Args->CheckValue ("-timer"); if (v) { double time = strtod (v, NULL); @@ -2310,7 +2308,7 @@ void D_DoomMain (void) timelimit = (float)time; } - v = Args.CheckValue ("-avg"); + v = Args->CheckValue ("-avg"); if (v) { Printf ("Austin Virtual Gaming: Levels will end after 20 minutes\n"); @@ -2420,10 +2418,10 @@ void D_DoomMain (void) } //Added by MC: - bglobal.getspawned = Args.GatherFiles ("-bots", "", false); + bglobal.getspawned = Args->GatherFiles ("-bots", "", false); if (bglobal.getspawned->NumArgs() == 0) { - delete bglobal.getspawned; + bglobal.getspawned->Destroy(); bglobal.getspawned = NULL; } else @@ -2459,13 +2457,11 @@ void D_DoomMain (void) // [RH] Run any saved commands from the command line or autoexec.cfg now. gamestate = GS_FULLCONSOLE; Net_NewMakeTic (); - DObject::BeginFrame (); DThinker::RunThinkers (); - DObject::EndFrame (); gamestate = GS_STARTUP; // start the apropriate game based on parms - v = Args.CheckValue ("-record"); + v = Args->CheckValue ("-record"); if (v) { @@ -2477,24 +2473,23 @@ void D_DoomMain (void) StartScreen = NULL; V_Init2(); - files = Args.GatherFiles ("-playdemo", ".lmp", false); + files = Args->GatherFiles ("-playdemo", ".lmp", false); if (files->NumArgs() > 0) { singledemo = true; // quit after one demo G_DeferedPlayDemo (files->GetArg (0)); - delete files; D_DoomLoop (); // never returns } - delete files; + files->Destroy(); - v = Args.CheckValue ("-timedemo"); + v = Args->CheckValue ("-timedemo"); if (v) { G_TimeDemo (v); D_DoomLoop (); // never returns } - v = Args.CheckValue ("-loadgame"); + v = Args->CheckValue ("-loadgame"); if (v) { file = v; diff --git a/src/d_net.cpp b/src/d_net.cpp index bbf79f5d40..1bb3225401 100644 --- a/src/d_net.cpp +++ b/src/d_net.cpp @@ -921,6 +921,8 @@ void NetUpdate (void) BYTE *cmddata; bool resendOnly; + GC::CheckGC(); + if (ticdup == 0) { return; @@ -1586,7 +1588,7 @@ void D_CheckNetGame (void) consoleplayer = doomcom.consoleplayer; - v = Args.CheckValue ("-netmode"); + v = Args->CheckValue ("-netmode"); if (v != NULL) { NetMode = atoi (v) != 0 ? NET_PacketServer : NET_PeerToPeer; @@ -1595,7 +1597,7 @@ void D_CheckNetGame (void) // [RH] Setup user info D_SetupUserInfo (); - if (Args.CheckParm ("-debugfile")) + if (Args->CheckParm ("-debugfile")) { char filename[20]; sprintf (filename,"debug%i.txt",consoleplayer); @@ -1834,12 +1836,11 @@ void TryRunTics (void) D_DoAdvanceDemo (); } if (debugfile) fprintf (debugfile, "run tic %d\n", gametic); - DObject::BeginFrame (); C_Ticker (); M_Ticker (); I_GetTime (true); G_Ticker (); - DObject::EndFrame (); + GC::CheckGC (); gametic++; NetUpdate (); // check for new console commands diff --git a/src/d_player.h b/src/d_player.h index 7c5e5fbaa2..27553ea406 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -105,8 +105,8 @@ public: int crouchsprite; int MaxHealth; int RunHealth; - AInventory *InvFirst; // first inventory item displayed on inventory bar - AInventory *InvSel; // selected inventory item + TObjPtr InvFirst; // first inventory item displayed on inventory bar + TObjPtr InvSel; // selected inventory item // [GRB] Player class properties fixed_t JumpZ; @@ -192,6 +192,7 @@ public: void Serialize (FArchive &arc); void FixPointers (const DObject *obj, DObject *replacement); + size_t PropagateMark(); void SetLogNumber (int num); void SetLogText (const char *text); diff --git a/src/decallib.cpp b/src/decallib.cpp index e157cf2ba7..1a0e193e74 100644 --- a/src/decallib.cpp +++ b/src/decallib.cpp @@ -110,7 +110,7 @@ struct DDecalThinker : public DThinker public: DDecalThinker (DBaseDecal *decal) : DThinker (STAT_DECALTHINKER), TheDecal (decal) {} void Serialize (FArchive &arc); - DBaseDecal *TheDecal; + TObjPtr TheDecal; protected: DDecalThinker () : DThinker (STAT_DECALTHINKER) {} }; @@ -1143,6 +1143,7 @@ void DDecalFader::Tick () { TheDecal->Destroy (); // remove the decal Destroy (); // remove myself + return; } if (StartTrans == -1) { diff --git a/src/dobject.cpp b/src/dobject.cpp index ebce108382..4bd7d4a2de 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -47,6 +47,7 @@ #include "r_state.h" #include "stats.h" #include "a_sharedglobal.h" +#include "dsectoreffect.h" #include "autosegs.h" @@ -343,148 +344,120 @@ CCMD (dumpclasses) Printf ("%d classes shown, %d omitted\n", shown, omitted); } -TArray DObject::Objects (TArray::NoInit); -TArray DObject::FreeIndices (TArray::NoInit); -TArray DObject::ToDestroy (TArray::NoInit); -bool DObject::Inactive; - void DObject::InPlaceConstructor (void *mem) { new ((EInPlace *)mem) DObject; } DObject::DObject () -: ObjectFlags(0), Class(0) +: Class(0), ObjectFlags(0) { - if (FreeIndices.Pop (Index)) - Objects[Index] = this; - else - Index = Objects.Push (this); + ObjectFlags = GC::CurrentWhite & OF_WhiteBits; + ObjNext = GC::Root; + GC::Root = this; } DObject::DObject (PClass *inClass) -: ObjectFlags(0), Class(inClass) +: Class(inClass), ObjectFlags(0) { - if (FreeIndices.Pop (Index)) - Objects[Index] = this; - else - Index = Objects.Push (this); + ObjectFlags = GC::CurrentWhite & OF_WhiteBits; + ObjNext = GC::Root; + GC::Root = this; } DObject::~DObject () { - if (!Inactive) + if (!(ObjectFlags & OF_Cleanup)) { - if (!(ObjectFlags & OF_MassDestruction)) - { - RemoveFromArray (); - DestroyScan (this); - } - else if (!(ObjectFlags & OF_Cleanup)) - { - // object is queued for deletion, but is not being deleted - // by the destruction process, so remove it from the - // ToDestroy array and do other necessary stuff. - unsigned int i; + DObject **probe; + PClass *type = GetClass(); - for (i = ToDestroy.Size() - 1; i-- > 0; ) + if (!(ObjectFlags & OF_YesReallyDelete)) + { + Printf ("Warning: '%s' is freed outside the GC process.\n", + type != NULL ? type->TypeName.GetChars() : "==some object=="); + } + + // Find all pointers that reference this object and NULL them. + PointerSubstitution(this, NULL); + + // Now unlink this object from the GC list. + for (probe = &GC::Root; *probe != NULL; probe = &((*probe)->ObjNext)) + { + if (*probe == this) { - if (ToDestroy[i] == this) + *probe = ObjNext; + if (&ObjNext == GC::SweepPos) { - ToDestroy[i] = NULL; + GC::SweepPos = probe; + } + break; + } + } + + // If it's gray, also unlink it from the gray list. + if (this->IsGray()) + { + for (probe = &GC::Gray; *probe != NULL; probe = &((*probe)->GCNext)) + { + if (*probe == this) + { + *probe = GCNext; break; } } - DestroyScan (this); } } } void DObject::Destroy () { - if (!Inactive) - { - if (!(ObjectFlags & OF_MassDestruction)) - { - RemoveFromArray (); - ObjectFlags |= OF_MassDestruction; - ToDestroy.Push (this); - } - } - else - delete this; + ObjectFlags |= OF_EuthanizeMe; } -void DObject::BeginFrame () +size_t DObject::PropagateMark() { - StaleCycles = 0; - StaleCount = 0; -} - -void DObject::EndFrame () -{ - clock (StaleCycles); - if (ToDestroy.Size ()) + const PClass *info = GetClass(); + const size_t *offsets = info->FlatPointers; + if (offsets == NULL) { - StaleCount += (int)ToDestroy.Size (); - DestroyScan (); - //Printf ("Destroyed %d objects\n", ToDestroy.Size()); - - DObject *obj; - while (ToDestroy.Pop (obj)) - { - if (obj) - { - obj->ObjectFlags |= OF_Cleanup; - delete obj; - } - } + const_cast(info)->BuildFlatPointers(); + offsets = info->FlatPointers; } - unclock (StaleCycles); -} - -void DObject::RemoveFromArray () -{ - if (Objects.Size() == Index + 1) + while (*offsets != ~(size_t)0) { - DObject *dummy; - Objects.Pop (dummy); - } - else if (Objects.Size() > Index) - { - Objects[Index] = NULL; - FreeIndices.Push (Index); + GC::Mark((DObject **)((BYTE *)this + *offsets)); + offsets++; } + return info->Size; } void DObject::PointerSubstitution (DObject *old, DObject *notOld) { - unsigned int i, highest; - highest = Objects.Size (); + DObject *probe; + int i; - for (i = 0; i <= highest; i++) + // Go through all objects. + for (probe = GC::Root; probe != NULL; probe = probe->ObjNext) { - DObject *current = i < highest ? Objects[i] : &bglobal; - if (current) + const PClass *info = probe->GetClass(); + const size_t *offsets = info->FlatPointers; + if (offsets == NULL) { - const PClass *info = current->GetClass(); - const size_t *offsets = info->FlatPointers; - if (offsets == NULL) + const_cast(info)->BuildFlatPointers(); + offsets = info->FlatPointers; + } + while (*offsets != ~(size_t)0) + { + if (*(DObject **)((BYTE *)probe + *offsets) == old) { - const_cast(info)->BuildFlatPointers(); - offsets = info->FlatPointers; - } - while (*offsets != ~(size_t)0) - { - if (*(DObject **)((BYTE *)current + *offsets) == old) - { - *(DObject **)((BYTE *)current + *offsets) = notOld; - } - offsets++; + *(DObject **)((BYTE *)probe + *offsets) = notOld; } + offsets++; } } + // Go through the bodyque. for (i = 0; i < BODYQUESIZE; ++i) { if (bodyque[i] == old) @@ -493,125 +466,32 @@ void DObject::PointerSubstitution (DObject *old, DObject *notOld) } } - // This is an ugly hack, but it's the best I can do for now. + // Go through players. for (i = 0; i < MAXPLAYERS; i++) { if (playeringame[i]) players[i].FixPointers (old, notOld); } + // Go through sectors. if (sectors != NULL) { - for (i = 0; i < (unsigned int)numsectors; ++i) + for (i = 0; i < numsectors; ++i) { - if (sectors[i].SoundTarget == old) - { - sectors[i].SoundTarget = static_cast(notOld); - } - if (sectors[i].CeilingSkyBox == old) - { - sectors[i].CeilingSkyBox = static_cast(notOld); - } - if (sectors[i].FloorSkyBox == old) - { - sectors[i].FloorSkyBox = static_cast(notOld); - } +#define SECTOR_CHECK(f,t) \ + if (sectors[i].f == static_cast(old)) { sectors[i].f = static_cast(notOld); } + SECTOR_CHECK( SoundTarget, AActor ); + SECTOR_CHECK( CeilingSkyBox, ASkyViewpoint ); + SECTOR_CHECK( FloorSkyBox, ASkyViewpoint ); + SECTOR_CHECK( SecActTarget, ASectorAction ); + SECTOR_CHECK( floordata, DSectorEffect ); + SECTOR_CHECK( ceilingdata, DSectorEffect ); + SECTOR_CHECK( lightingdata, DSectorEffect ); +#undef SECTOR_CHECK } } } -// Search for references to a single object and NULL them. -// It should not be listed in ToDestroy. -void DObject::DestroyScan (DObject *obj) -{ - PointerSubstitution (obj, NULL); -} - -// Search for references to all objects scheduled for -// destruction and NULL them. -void DObject::DestroyScan () -{ - unsigned int i, highest; - int j, destroycount; - DObject **destroybase; - destroycount = (int)ToDestroy.Size (); - if (destroycount == 0) - return; - destroybase = &ToDestroy[0] + destroycount; - destroycount = -destroycount; - highest = Objects.Size (); - - for (i = 0; i <= highest; i++) - { - DObject *current = i < highest ? Objects[i] : &bglobal; - if (current) - { - const PClass *info = current->GetClass(); - const size_t *offsets = info->FlatPointers; - if (offsets == NULL) - { - const_cast(info)->BuildFlatPointers(); - offsets = info->FlatPointers; - } - while (*offsets != ~(size_t)0) - { - j = destroycount; - do - { - if (*(DObject **)((BYTE *)current + *offsets) == *(destroybase + j)) - { - *(DObject **)((BYTE *)current + *offsets) = NULL; - } - } while (++j); - offsets++; - } - } - } - - j = destroycount; - do - { - for (i = 0; i < BODYQUESIZE; ++i) - { - if (bodyque[i] == *(destroybase + j)) - { - bodyque[i] = NULL; - } - } - - } while (++j); - - // This is an ugly hack, but it's the best I can do for now. - for (i = 0; i < MAXPLAYERS; i++) - { - if (playeringame[i]) - { - j = destroycount; - do - { - players[i].FixPointers (*(destroybase + j), NULL); - } while (++j); - } - } - - for (i = 0; i < (unsigned int)numsectors; ++i) - { - j = destroycount; - do - { - if (sectors[i].SoundTarget == *(destroybase + j)) - { - sectors[i].SoundTarget = NULL; - } - } while (++j); - } -} - -void DObject::StaticShutdown () -{ - Inactive = true; -} - void DObject::Serialize (FArchive &arc) { ObjectFlags |= OF_SerialSuccess; diff --git a/src/dobject.h b/src/dobject.h index f18f1e03cd..b0ef5d7080 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -2,7 +2,7 @@ ** dobject.h ** **--------------------------------------------------------------------------- -** Copyright 1998-2006 Randy Heit +** Copyright 1998-2008 Randy Heit ** All rights reserved. ** ** Redistribution and use in source and binary forms, with or without @@ -48,7 +48,6 @@ class FArchive; class DObject; class DArgs; -class DBoundingBox; class DCanvas; class DConsoleCommand; class DConsoleAlias; @@ -211,12 +210,205 @@ private: \ enum EObjectFlags { - OF_MassDestruction = 0x00000001, // Object is queued for deletion - OF_Cleanup = 0x00000002, // Object is being deconstructed as a result of a queued deletion - OF_JustSpawned = 0x00000004, // Thinker was spawned this tic - OF_SerialSuccess = 0x10000000 // For debugging Serialize() calls + // GC flags + OF_White0 = 1 << 0, // Object is white (type 0) + OF_White1 = 1 << 1, // Object is white (type 1) + OF_Black = 1 << 2, // Object is black + OF_Fixed = 1 << 3, // Object is fixed (should not be collected) + OF_Rooted = 1 << 4, // Object is soft-rooted + OF_EuthanizeMe = 1 << 5, // Object wants to die + OF_Cleanup = 1 << 6, // Object is now being deleted by the collector + OF_YesReallyDelete = 1 << 7, // Object is being deleted outside the collector, and this is okay, so don't print a warning + + OF_WhiteBits = OF_White0 | OF_White1, + OF_MarkBits = OF_WhiteBits | OF_Black, + + // Other flags + OF_JustSpawned = 1 << 8, // Thinker was spawned this tic + OF_SerialSuccess = 1 << 9, // For debugging Serialize() calls }; +template class TObjPtr; + +namespace GC +{ + enum EGCState + { + GCS_Pause, + GCS_Propagate, + GCS_Sweep, + GCS_Finalize + }; + + // Number of bytes currently allocated through M_Malloc/M_Realloc. + extern size_t AllocBytes; + + // Amount of memory to allocate before triggering a collection. + extern size_t Threshold; + + // List of gray objects. + extern DObject *Gray; + + // List of every object. + extern DObject *Root; + + // Current white value for potentially-live objects. + extern DWORD CurrentWhite; + + // Current collector state. + extern EGCState State; + + // Position of GC sweep in the list of objects. + extern DObject **SweepPos; + + // Size of GC pause. + extern int Pause; + + // Size of GC steps. + extern int StepMul; + + // Current white value for known-dead objects. + static inline DWORD OtherWhite() + { + return CurrentWhite ^ OF_WhiteBits; + } + + // Frees all objects, whether they're dead or not. + void FreeAll(); + + // Does one collection step. + void Step(); + + // Does a complete collection. + void FullGC(); + + // Handles the grunt work for a write barrier. + void Barrier(DObject *pointing, DObject *pointed); + + // Handles a write barrier. + static inline void WriteBarrier(DObject *pointing, DObject *pointed); + + // Handles a write barrier for a pointer that isn't inside an object. + static inline void WriteBarrier(DObject *pointed); + + // Handles a read barrier. + template inline T *ReadBarrier(T *&obj) + { + if (obj == NULL || !(obj->ObjectFlags & OF_EuthanizeMe)) + { + return obj; + } + return obj = NULL; + } + + // Check if it's time to collect, and do a collection step if it is. + static inline void CheckGC() + { + if (AllocBytes >= Threshold) + Step(); + } + + // Marks a white object gray. If the object wants to die, the pointer + // is NULLed instead. + void Mark(DObject **obj); + + // Soft-roots an object. + void AddSoftRoot(DObject *obj); + + // Unroots an object. + void DelSoftRoot(DObject *obj); + + template void Mark(T *&obj) { Mark((DObject **)&obj); } + template void Mark(TObjPtr &obj); +} + +// A template class to help with handling read barriers. It does not +// handle write barriers, because those can be handled more efficiently +// with knowledge of the object that holds the pointer. +template +class TObjPtr +{ + T *p; +public: + TObjPtr() throw() + { + } + TObjPtr(T *q) throw() + : p(q) + { + } + TObjPtr(const TObjPtr &q) throw() + : p(q.p) + { + } + T *operator=(T *q) throw() + { + return p = q; + // The caller must now perform a write barrier. + } + operator T*() throw() + { + return GC::ReadBarrier(p); + } + T &operator*() + { + T *q = GC::ReadBarrier(p); + assert(q != NULL); + return *q; + } + T **operator&() throw() + { + // Does not perform a read barrier. The only real use for this is with + // the DECLARE_POINTER macro, where a read barrier would be a very bad + // thing. + return &p; + } + T *operator->() throw() + { + return GC::ReadBarrier(p); + } + bool operator<(T *u) throw() + { + return GC::ReadBarrier(p) < u; + } + bool operator<=(T *u) throw() + { + return GC::ReadBarrier(p) <= u; + } + bool operator>(T *u) throw() + { + return GC::ReadBarrier(p) > u; + } + bool operator>=(T *u) throw() + { + return GC::ReadBarrier(p) >= u; + } + bool operator!=(T *u) throw() + { + return GC::ReadBarrier(p) != u; + } + bool operator==(T *u) throw() + { + return GC::ReadBarrier(p) == u; + } + + template friend inline FArchive &operator<<(FArchive &arc, TObjPtr &o); +}; + +template inline FArchive &operator<<(FArchive &arc, TObjPtr &o) +{ + return arc << o.p; +} + +// Use barrier_cast instead of static_cast when you need to cast +// the contents of a TObjPtr to a related type. +template inline T barrier_cast(TObjPtr &o) +{ + return static_cast(static_cast(o)); +} + +template void GC::Mark(TObjPtr &obj) { GC::Mark((DObject **)&obj); } + class DObject { public: @@ -227,12 +419,13 @@ public: private: typedef DObject ThisClass; - // Per-instance variables. There are three. -public: - DWORD ObjectFlags; // Flags for this object + // Per-instance variables. There are four. private: PClass *Class; // This object's type - unsigned int Index; // This object's index in the global object table +public: + DObject *ObjNext; // Keep track of all allocated objects + DObject *GCNext; // Next object in this collection list + DWORD ObjectFlags; // Flags for this object public: DObject (); @@ -250,16 +443,11 @@ public: virtual void Destroy (); - static void BeginFrame (); - static void EndFrame (); - // If you need to replace one object with another and want to // change any pointers from the old object to the new object, // use this method. static void PointerSubstitution (DObject *old, DObject *notOld); - static void StaticShutdown (); - PClass *GetClass() const { if (Class == NULL) @@ -286,6 +474,60 @@ public: M_Free(mem); } + // GC fiddling + + // An object is white if either white bit is set. + bool IsWhite() const + { + return !!(ObjectFlags & OF_WhiteBits); + } + + bool IsBlack() const + { + return !!(ObjectFlags & OF_Black); + } + + // An object is gray if it isn't white or black. + bool IsGray() const + { + return !(ObjectFlags & OF_MarkBits); + } + + // An object is dead if it's the other white. + bool IsDead() const + { + return !!(ObjectFlags & GC::OtherWhite() & OF_WhiteBits); + } + + void ChangeWhite() + { + ObjectFlags ^= OF_WhiteBits; + } + + void MakeWhite() + { + ObjectFlags = (ObjectFlags & ~OF_MarkBits) | (GC::CurrentWhite & OF_WhiteBits); + } + + void White2Gray() + { + ObjectFlags &= ~OF_WhiteBits; + } + + void Black2Gray() + { + ObjectFlags &= ~OF_Black; + } + + void Gray2Black() + { + ObjectFlags |= OF_Black; + } + + // Marks all objects pointed to by this one. Returns the (approximate) + // amount of memory used by this object. + virtual size_t PropagateMark(); + protected: // This form of placement new and delete is for use *only* by PClass's // CreateNew() method. Do not use them for some other purpose. @@ -296,22 +538,26 @@ protected: void operator delete (void *mem, EInPlace *) { - free (mem); + M_Free (mem); } - -private: - static TArray Objects; - static TArray FreeIndices; - static TArray ToDestroy; - - static void DestroyScan (DObject *obj); - static void DestroyScan (); - - void RemoveFromArray (); - - static bool Inactive; }; +static inline void GC::WriteBarrier(DObject *pointing, DObject *pointed) +{ + if (pointed != NULL && pointed->IsWhite() && pointing->IsBlack()) + { + Barrier(pointing, pointed); + } +} + +static inline void GC::WriteBarrier(DObject *pointed) +{ + if (pointed != NULL && State == GCS_Propagate && pointed->IsWhite()) + { + Barrier(NULL, pointed); + } +} + #include "dobjtype.h" inline bool DObject::IsKindOf (const PClass *base) const diff --git a/src/dobjgc.cpp b/src/dobjgc.cpp new file mode 100644 index 0000000000..ec0ede4b28 --- /dev/null +++ b/src/dobjgc.cpp @@ -0,0 +1,623 @@ +/* +** dobjgc.cpp +** The garbage collector. Based largely on Lua's. +** +**--------------------------------------------------------------------------- +** Copyright 2008 Randy Heit +** All rights reserved. +** +** Redistribution and use in source and binary forms, with or without +** modification, are permitted provided that the following conditions +** are met: +** +** 1. Redistributions of source code must retain the above copyright +** notice, this list of conditions and the following disclaimer. +** 2. Redistributions in binary form must reproduce the above copyright +** notice, this list of conditions and the following disclaimer in the +** documentation and/or other materials provided with the distribution. +** 3. The name of the author may not be used to endorse or promote products +** derived from this software without specific prior written permission. +** +** THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +** IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +** INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +** NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +** DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +** THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +** (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +** THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +**--------------------------------------------------------------------------- +** +*/ +/****************************************************************************** +* Copyright (C) 1994-2008 Lua.org, PUC-Rio. All rights reserved. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + +// HEADER FILES ------------------------------------------------------------ + +#include "dobject.h" +#include "templates.h" +#include "b_bot.h" +#include "p_local.h" +#include "g_game.h" +#include "r_data.h" +#include "a_sharedglobal.h" +#include "sbar.h" +#include "stats.h" +#include "c_dispatch.h" +#include "p_acs.h" + +// MACROS ------------------------------------------------------------------ + +/* +@@ DEFAULT_GCPAUSE defines the default pause between garbage-collector cycles +@* as a percentage. +** CHANGE it if you want the GC to run faster or slower (higher values +** mean larger pauses which mean slower collection.) You can also change +** this value dynamically. +*/ +#define DEFAULT_GCPAUSE 150 // 150% (wait for memory to increase by half before next GC) + +/* +@@ DEFAULT_GCMUL defines the default speed of garbage collection relative to +@* memory allocation as a percentage. +** CHANGE it if you want to change the granularity of the garbage +** collection. (Higher values mean coarser collections. 0 represents +** infinity, where each step performs a full collection.) You can also +** change this value dynamically. +*/ +#define DEFAULT_GCMUL 400 // GC runs 'quadruple the speed' of memory allocation + + +#define GCSTEPSIZE 1024u +#define GCSWEEPMAX 40 +#define GCSWEEPCOST 10 +#define GCFINALIZECOST 100 + +// TYPES ------------------------------------------------------------------- + +// EXTERNAL FUNCTION PROTOTYPES -------------------------------------------- + +// PUBLIC FUNCTION PROTOTYPES ---------------------------------------------- + +// PRIVATE FUNCTION PROTOTYPES --------------------------------------------- + +// EXTERNAL DATA DECLARATIONS ---------------------------------------------- + +// PUBLIC DATA DEFINITIONS ------------------------------------------------- + +namespace GC +{ +size_t AllocBytes; +size_t Threshold; +size_t Estimate; +DObject *Gray; +DObject *Root; +DObject *SoftRoots; +DObject **SweepPos; +DWORD CurrentWhite = OF_White0 | OF_Fixed; +EGCState State = GCS_Pause; +int Pause = DEFAULT_GCPAUSE; +int StepMul = DEFAULT_GCMUL; +int StepCount; +size_t Dept; + +// PRIVATE DATA DEFINITIONS ------------------------------------------------ + +// CODE -------------------------------------------------------------------- + +//========================================================================== +// +// SetThreshold +// +// Sets the new threshold after a collection is finished. +// +//========================================================================== + +void SetThreshold() +{ + Threshold = (Estimate / 100) * Pause; +} + +//========================================================================== +// +// PropagateMark +// +// Marks the top-most gray object black and marks all objects it points to +// gray. +// +//========================================================================== + +size_t PropagateMark() +{ + DObject *obj = Gray; + assert(obj->IsGray()); + obj->Gray2Black(); + Gray = obj->GCNext; + return obj->PropagateMark(); +} + +//========================================================================== +// +// PropagateAll +// +// Empties the gray list by propagating every single object in it. +// +//========================================================================== + +static size_t PropagateAll() +{ + size_t m = 0; + while (Gray != NULL) + { + m += PropagateMark(); + } + return m; +} + +//========================================================================== +// +// SweepList +// +// Runs a limited sweep on a list, returning the location where to resume +// the sweep at next time. +// +//========================================================================== + +static DObject **SweepList(DObject **p, size_t count) +{ + static int scount; + DObject *curr; + int deadmask = OtherWhite(); + + while ((curr = *p) != NULL && count-- > 0) + { + if ((curr->ObjectFlags ^ OF_WhiteBits) & deadmask) // not dead? + { + assert(!curr->IsDead() || (curr->ObjectFlags & OF_Fixed)); + curr->MakeWhite(); // make it white (for next cycle) + p = &curr->ObjNext; + } + else // must erase 'curr' + { + assert(curr->IsDead()); + *p = curr->ObjNext; + if (!(curr->ObjectFlags & OF_EuthanizeMe)) + { // The object must be destroyed before it can be finalized. + assert(!curr->IsKindOf(RUNTIME_CLASS(DThinker))); + curr->Destroy(); + } + curr->ObjectFlags |= OF_Cleanup; + delete curr; + } + } + return p; +} + +//========================================================================== +// +// Mark +// +// Mark a single object gray. +// +//========================================================================== + +void Mark(DObject **obj) +{ + DObject *lobj = *obj; + if (lobj != NULL) + { + if (lobj->ObjectFlags & OF_EuthanizeMe) + { + *obj = NULL; + } + else if (lobj->IsWhite()) + { + lobj->White2Gray(); + lobj->GCNext = Gray; + Gray = lobj; + } + } +} + +//========================================================================== +// +// MarkRoot +// +// Mark the root set of objects. +// +//========================================================================== + +static void MarkRoot() +{ + int i; + + Gray = NULL; + Mark(Args); + Mark(screen); + Mark(StatusBar); + DThinker::MarkRoots(); + Mark(DACSThinker::ActiveThinker); + for (i = 0; i < BODYQUESIZE; ++i) + { + Mark(bodyque[i]); + } + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i]) + players[i].PropagateMark(); + } + if (sectors != NULL) + { + for (i = 0; i < numsectors; ++i) + { + Mark(sectors[i].SoundTarget); + Mark(sectors[i].CeilingSkyBox); + Mark(sectors[i].FloorSkyBox); + Mark(sectors[i].SecActTarget); + Mark(sectors[i].floordata); + Mark(sectors[i].ceilingdata); + Mark(sectors[i].lightingdata); + } + } + { // Silly bots + DObject *foo = &bglobal; + Mark(foo); + } + // Add soft roots + if (SoftRoots != NULL) + { + DObject **probe = &SoftRoots->ObjNext; + while (*probe != NULL) + { + DObject *soft = *probe; + probe = &soft->ObjNext; + if ((soft->ObjectFlags & (OF_Rooted | OF_EuthanizeMe)) == OF_Rooted) + { + Mark(soft); + } + } + } + State = GCS_Propagate; + StepCount = 0; +} + +//========================================================================== +// +// Atomic +// +// If their were any propagations that needed to be done atomicly, they +// would go here. It also sets things up for the sweep state. +// +//========================================================================== + +static void Atomic() +{ + // Flip current white + CurrentWhite = OtherWhite(); + SweepPos = &Root; + State = GCS_Sweep; + Estimate = AllocBytes; +} + +//========================================================================== +// +// SingleStep +// +// Performs one step of the collector. +// +//========================================================================== + +static size_t SingleStep() +{ + switch (State) + { + case GCS_Pause: + MarkRoot(); // Start a new collection + return 0; + + case GCS_Propagate: + if (Gray != NULL) + { + return PropagateMark(); + } + else + { // no more gray objects + Atomic(); // finish mark phase + return 0; + } + + case GCS_Sweep: { + size_t old = AllocBytes; + SweepPos = SweepList(SweepPos, GCSWEEPMAX); + if (*SweepPos == NULL) + { // Nothing more to sweep? + State = GCS_Finalize; + } + assert(old >= AllocBytes); + Estimate -= old - AllocBytes; + return GCSWEEPMAX * GCSWEEPCOST; + } + + case GCS_Finalize: + State = GCS_Pause; // end collection + Dept = 0; + return 0; + + default: + assert(0); + return 0; + } +} + +//========================================================================== +// +// Step +// +// Performs enough single steps to cover GCSTEPSIZE * StepMul% bytes of +// memory. +// +//========================================================================== + +void Step() +{ + size_t lim = (GCSTEPSIZE/100) * StepMul; + size_t olim; + if (lim == 0) + { + lim = (~(size_t)0) / 2; // no limit + } + Dept += AllocBytes - Threshold; + do + { + olim = lim; + lim -= SingleStep(); + } while (olim > lim && State != GCS_Pause); + if (State != GCS_Pause) + { + if (Dept < GCSTEPSIZE) + { + Threshold = AllocBytes + GCSTEPSIZE; // - lim/StepMul + } + else + { + Dept -= GCSTEPSIZE; + Threshold = AllocBytes; + } + } + else + { + assert(AllocBytes >= Estimate); + SetThreshold(); + } + StepCount++; +} + +//========================================================================== +// +// FullGC +// +// Collects everything in one fell swoop. +// +//========================================================================== + +void FullGC() +{ + if (State <= GCS_Propagate) + { + // Reset sweep mark to sweep all elements (returning them to white) + SweepPos = &Root; + // Reset other collector lists + Gray = NULL; + State = GCS_Sweep; + } + // Finish any pending sweep phase + while (State != GCS_Finalize) + { + SingleStep(); + } + MarkRoot(); + while (State != GCS_Pause) + { + SingleStep(); + } + SetThreshold(); +} + +//========================================================================== +// +// Barrier +// +// Implements a write barrier to maintain the invariant that a black node +// never points to a white node by making the node pointed at gray. +// +//========================================================================== + +void Barrier(DObject *pointing, DObject *pointed) +{ + assert(pointing == NULL || (pointing->IsBlack() && !pointing->IsDead())); + assert(pointed->IsWhite() && !pointed->IsDead()); + assert(State != GCS_Finalize && State != GCS_Pause); + // The invariant only needs to be maintained in the propagate state. + if (State == GCS_Propagate) + { + pointed->White2Gray(); + pointed->GCNext = Gray; + Gray = pointed; + } + // In other states, we can mark the pointing object white so this + // barrier won't be triggered again, saving a few cycles in the future. + else if (pointing != NULL) + { + pointing->MakeWhite(); + } +} + +//========================================================================== +// +// AddSoftRoot +// +// Marks an object as a soft root. A soft root behaves exactly like a root +// in MarkRoot, except it can be added at run-time. +// +//========================================================================== + +void AddSoftRoot(DObject *obj) +{ + DObject **probe; + + // Are there any soft roots yet? + if (SoftRoots == NULL) + { + // Create a new object to root the soft roots off of, and stick + // it at the end of the object list, so we know that anything + // before it is not a soft root. + SoftRoots = new DObject; + SoftRoots->ObjectFlags |= OF_Fixed; + probe = &Root; + while (*probe != NULL) + { + probe = &(*probe)->ObjNext; + } + Root = SoftRoots->ObjNext; + SoftRoots->ObjNext = NULL; + *probe = SoftRoots; + } + // Mark this object as rooted and move it after the SoftRoots marker. + probe = &Root; + while (*probe != NULL && *probe != obj) + { + probe = &(*probe)->ObjNext; + } + *probe = (*probe)->ObjNext; + obj->ObjNext = SoftRoots->ObjNext; + SoftRoots->ObjNext = obj; + obj->ObjectFlags |= OF_Rooted; + WriteBarrier(obj); +} + +//========================================================================== +// +// DelSoftRoot +// +// Unroots an object so that it must be reachable or it will get collected. +// +//========================================================================== + +void DelSoftRoot(DObject *obj) +{ + DObject **probe; + + if (!(obj->ObjectFlags & OF_Rooted)) + { // Not rooted, so nothing to do. + return; + } + obj->ObjectFlags &= ~OF_Rooted; + // Move object out of the soft roots part of the list. + probe = &SoftRoots; + while (*probe != NULL && *probe != obj) + { + probe = &(*probe)->ObjNext; + } + if (*probe == obj) + { + *probe = obj->ObjNext; + obj->ObjNext = Root; + Root = obj; + } +} + +} + +ADD_STAT(gc) +{ + static const char *StateStrings[] = { + " Pause ", + "Propagate", + " Sweep ", + "Finalize " }; + FString out; + out.Format("[%s] Alloc:%6uK Thresh:%6uK Est:%6uK Steps: %d", + StateStrings[GC::State], + (GC::AllocBytes + 1023) >> 10, + (GC::Threshold + 1023) >> 10, + (GC::Estimate + 1023) >> 10, + GC::StepCount); + if (GC::State != GC::GCS_Pause) + { + out.AppendFormat(" %uK", (GC::Dept + 1023) >> 10); + } + return out; +} + +//========================================================================== +// +// CCMD gc +// +// Controls various aspects of the collector. +// +//========================================================================== + +CCMD(gc) +{ + if (argv.argc() == 1) + { + Printf ("Usage: gc stop|now|full|pause [size]|stepmul [size]\n"); + return; + } + if (stricmp(argv[1], "stop") == 0) + { + GC::Threshold = ~(size_t)0 - 2; + } + else if (stricmp(argv[1], "now") == 0) + { + GC::Threshold = GC::AllocBytes; + } + else if (stricmp(argv[1], "full") == 0) + { + GC::FullGC(); + } + else if (stricmp(argv[1], "pause") == 0) + { + if (argv.argc() == 2) + { + Printf ("Current GC pause is %d\n", GC::Pause); + } + else + { + GC::Pause = MAX(1,atoi(argv[2])); + } + } + else if (stricmp(argv[1], "stepmul") == 0) + { + if (argv.argc() == 2) + { + Printf ("Current GC stepmul is %d\n", GC::StepMul); + } + else + { + GC::StepMul = MAX(100, atoi(argv[2])); + } + } +} diff --git a/src/dsectoreffect.cpp b/src/dsectoreffect.cpp index 5aa9754054..3a4a4c43c0 100644 --- a/src/dsectoreffect.cpp +++ b/src/dsectoreffect.cpp @@ -33,7 +33,7 @@ DSectorEffect::DSectorEffect () m_Sector = NULL; } -DSectorEffect::~DSectorEffect () +void DSectorEffect::Destroy() { if (m_Sector) { @@ -52,6 +52,7 @@ DSectorEffect::~DSectorEffect () m_Sector->lightingdata = NULL; } } + Super::Destroy(); } DSectorEffect::DSectorEffect (sector_t *sector) diff --git a/src/dsectoreffect.h b/src/dsectoreffect.h index 1c35bbd706..64e1e65835 100644 --- a/src/dsectoreffect.h +++ b/src/dsectoreffect.h @@ -10,9 +10,9 @@ class DSectorEffect : public DThinker DECLARE_CLASS (DSectorEffect, DThinker) public: DSectorEffect (sector_t *sector); - ~DSectorEffect (); void Serialize (FArchive &arc); + void Destroy(); sector_t *GetSector() const { return m_Sector; } diff --git a/src/dthinker.cpp b/src/dthinker.cpp index fa6bfe0596..bd8990bbba 100644 --- a/src/dthinker.cpp +++ b/src/dthinker.cpp @@ -155,6 +155,14 @@ DThinker::DThinker (int statnum) throw() { statnum = MAX_STATNUM; } + if (FreshThinkers[statnum].TailPred->Pred != NULL) + { + GC::WriteBarrier(static_cast(FreshThinkers[statnum].Tail, this)); + } + else + { + GC::WriteBarrier(this); + } FreshThinkers[statnum].AddTail (this); } @@ -179,6 +187,16 @@ void DThinker::Destroy () Super::Destroy (); } +void DThinker::Remove() +{ + if (Pred->Pred != NULL && Succ->Succ != NULL) + { + GC::WriteBarrier(static_cast(Pred), static_cast(Succ)); + GC::WriteBarrier(static_cast(Succ), static_cast(Pred)); + } + Node::Remove(); +} + void DThinker::PostBeginPlay () { } @@ -205,6 +223,8 @@ DThinker *DThinker::FirstThinker (int statnum) void DThinker::ChangeStatNum (int statnum) { + List *list; + if ((unsigned)statnum > MAX_STATNUM) { statnum = MAX_STATNUM; @@ -212,12 +232,44 @@ void DThinker::ChangeStatNum (int statnum) Remove (); if ((ObjectFlags & OF_JustSpawned) && statnum >= STAT_FIRST_THINKING) { - FreshThinkers[statnum].AddTail (this); + list = &FreshThinkers[statnum]; } else { - Thinkers[statnum].AddTail (this); + list = &Thinkers[statnum]; } + if (list->TailPred->Pred != NULL) + { + GC::WriteBarrier(static_cast(list->Tail, this)); + } + else + { + GC::WriteBarrier(this); + } + list->AddTail(this); +} + +// Mark the first thinker of each list +void DThinker::MarkRoots() +{ + for (int i = 0; i <= MAX_STATNUM; ++i) + { + DThinker *t = static_cast(Thinkers[i].Head); + GC::Mark(t); + t = static_cast(FreshThinkers[i].Head); + GC::Mark(t); + } +} + +size_t DThinker::PropagateMark() +{ + // Mark the next thinker in my list + if (Succ != NULL && Succ->Succ != NULL) + { + DThinker *t = static_cast(Succ); + GC::Mark(t); + } + return Super::PropagateMark(); } // Destroy every thinker @@ -225,7 +277,6 @@ void DThinker::DestroyAllThinkers () { int i; - DObject::BeginFrame (); for (i = 0; i <= MAX_STATNUM; i++) { if (i != STAT_TRAVELLING) @@ -234,7 +285,7 @@ void DThinker::DestroyAllThinkers () DestroyThinkersInList (FreshThinkers[i].Head); } } - DObject::EndFrame (); + GC::FullGC (); } // Destroy all thinkers except for player-controlled actors @@ -244,7 +295,6 @@ void DThinker::DestroyMostThinkers () { int i; - DObject::BeginFrame (); for (i = 0; i <= MAX_STATNUM; i++) { if (i != STAT_TRAVELLING) @@ -253,7 +303,7 @@ void DThinker::DestroyMostThinkers () DestroyMostThinkersInList (FreshThinkers[i], i); } } - DObject::EndFrame (); + GC::FullGC (); } void DThinker::DestroyThinkersInList (Node *node) @@ -327,6 +377,14 @@ int DThinker::TickThinkers (List *list, List *dest) if (dest != NULL) { // Move thinker from this list to the destination list node->Remove (); + if (dest->TailPred->Pred != NULL) + { + GC::WriteBarrier(static_cast(dest->Tail, thinker)); + } + else + { + GC::WriteBarrier(thinker); + } dest->AddTail (node); } thinker->PostBeginPlay (); @@ -336,7 +394,7 @@ int DThinker::TickThinkers (List *list, List *dest) I_Error ("There is a thinker in the fresh list that has already ticked.\n"); } - if (!(thinker->ObjectFlags & OF_MassDestruction)) + if (!(thinker->ObjectFlags & OF_EuthanizeMe)) { // Only tick thinkers not scheduled for destruction thinker->Tick (); } diff --git a/src/dthinker.h b/src/dthinker.h index f7905c5b8d..53e52846ae 100644 --- a/src/dthinker.h +++ b/src/dthinker.h @@ -49,13 +49,14 @@ class FThinkerIterator; enum { MAX_STATNUM = 127 }; // Doubly linked list of thinkers -class DThinker : public DObject, public Node +class DThinker : public DObject, private Node { DECLARE_CLASS (DThinker, DObject) public: DThinker (int statnum = MAX_STATNUM) throw(); void Destroy (); + size_t PropagateMark(); virtual ~DThinker (); virtual void Tick (); virtual void PostBeginPlay (); // Called just before the first tick @@ -67,6 +68,7 @@ public: static void DestroyAllThinkers (); static void DestroyMostThinkers (); static void SerializeAll (FArchive &arc, bool keepPlayers); + static void MarkRoots(); static DThinker *FirstThinker (int statnum); @@ -75,6 +77,7 @@ private: static void DestroyMostThinkersInList (List &list, int stat); static int TickThinkers (List *list, List *dest); // Returns: # of thinkers ticked static void SaveList(FArchive &arc, Node *node); + void Remove(); static List Thinkers[MAX_STATNUM+1]; // Current thinkers static List FreshThinkers[MAX_STATNUM+1]; // Newly created thinkers diff --git a/src/farchive.cpp b/src/farchive.cpp index 7d17c8d4c6..2087b7bed5 100644 --- a/src/farchive.cpp +++ b/src/farchive.cpp @@ -1004,9 +1004,17 @@ FArchive &FArchive::SerializePointer (void *ptrbase, BYTE **ptr, DWORD elemSize) FArchive &FArchive::SerializeObject (DObject *&object, PClass *type) { if (IsStoring ()) + { + if (object != (DObject*)~0) + { + GC::ReadBarrier(object); + } return WriteObject (object); + } else + { return ReadObject (object, type); + } } FArchive &FArchive::WriteObject (DObject *obj) diff --git a/src/g_doom/a_bossbrain.cpp b/src/g_doom/a_bossbrain.cpp index 16a64af6c9..4ad3ae2121 100644 --- a/src/g_doom/a_bossbrain.cpp +++ b/src/g_doom/a_bossbrain.cpp @@ -315,7 +315,7 @@ void A_SpawnFly (AActor *self) if (newmobj->SeeState != NULL && P_LookForPlayers (newmobj, true)) newmobj->SetState (newmobj->SeeState); - if (!(newmobj->ObjectFlags & OF_MassDestruction)) + if (!(newmobj->ObjectFlags & OF_EuthanizeMe)) { // telefrag anything in this spot P_TeleportMove (newmobj, newmobj->x, newmobj->y, newmobj->z, true); diff --git a/src/g_doom/doom_sbar.cpp b/src/g_doom/doom_sbar.cpp index 31538f7b68..c97b39613f 100644 --- a/src/g_doom/doom_sbar.cpp +++ b/src/g_doom/doom_sbar.cpp @@ -27,10 +27,11 @@ EXTERN_CVAR (Bool, vid_fps) -class FDoomStatusBar : public FBaseStatusBar +class DDoomStatusBar : public DBaseStatusBar { + DECLARE_CLASS(DDoomStatusBar, DBaseStatusBar) public: - FDoomStatusBar () : FBaseStatusBar (32) + DDoomStatusBar () : DBaseStatusBar (32) { static const char *sharedLumpNames[] = { @@ -44,8 +45,8 @@ public: }; FTexture *tex; - FBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); - tex = FBaseStatusBar::Images[imgBNumbers]; + DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); + tex = DBaseStatusBar::Images[imgBNumbers]; BigWidth = tex->GetWidth(); BigHeight = tex->GetHeight(); @@ -53,7 +54,7 @@ public: bEvilGrin = false; } - ~FDoomStatusBar () + ~DDoomStatusBar () { } @@ -126,7 +127,7 @@ public: void MultiplayerChanged () { - FBaseStatusBar::MultiplayerChanged (); + DBaseStatusBar::MultiplayerChanged (); if (multiplayer) { // set face background color @@ -138,7 +139,7 @@ public: { player_t *oldplayer = CPlayer; - FBaseStatusBar::AttachToPlayer (player); + DBaseStatusBar::AttachToPlayer (player); if (oldplayer != CPlayer) { SetFace (&skins[CPlayer->userinfo.skin]); @@ -153,14 +154,14 @@ public: void Tick () { - FBaseStatusBar::Tick (); + DBaseStatusBar::Tick (); RandomNumber = M_Random (); UpdateFace (); } void Draw (EHudState state) { - FBaseStatusBar::Draw (state); + DBaseStatusBar::Draw (state); if (state == HUD_Fullscreen) { @@ -375,7 +376,7 @@ private: void DrawArm (int on, int picnum, int x, int y, bool drawBackground) { int w; - FTexture *pic = on ? FBaseStatusBar::Images[imgSmNumbers + 2 + picnum] : Images[imgGNUM2 + picnum]; + FTexture *pic = on ? DBaseStatusBar::Images[imgSmNumbers + 2 + picnum] : Images[imgGNUM2 + picnum]; if (pic != NULL) { @@ -555,7 +556,7 @@ private: void DrawInventoryBar () { - const AInventory *item; + AInventory *item; int i; // If the player has no artifacts, don't draw the bar @@ -602,7 +603,7 @@ private: void DrawFullScreenStuff () { - const AInventory *item; + AInventory *item; int i; int ammotop; @@ -1041,7 +1042,9 @@ private: bool bEvilGrin; }; -FDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture () +IMPLEMENT_CLASS(DDoomStatusBar) + +DDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture () { BaseTexture = TexMan["STBAR"]; if (BaseTexture==NULL) @@ -1057,7 +1060,7 @@ FDoomStatusBar::FDoomStatusBarTexture::FDoomStatusBarTexture () STBFremap = NULL; } -const BYTE *FDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out) +const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int column, const Span **spans_out) { if (Pixels == NULL) { @@ -1068,7 +1071,7 @@ const BYTE *FDoomStatusBar::FDoomStatusBarTexture::GetColumn (unsigned int colum return Pixels + column*Height; } -const BYTE *FDoomStatusBar::FDoomStatusBarTexture::GetPixels () +const BYTE *DDoomStatusBar::FDoomStatusBarTexture::GetPixels () { if (Pixels == NULL) { @@ -1077,7 +1080,7 @@ const BYTE *FDoomStatusBar::FDoomStatusBarTexture::GetPixels () return Pixels; } -void FDoomStatusBar::FDoomStatusBarTexture::Unload () +void DDoomStatusBar::FDoomStatusBarTexture::Unload () { if (Pixels != NULL) { @@ -1086,13 +1089,13 @@ void FDoomStatusBar::FDoomStatusBarTexture::Unload () } } -FDoomStatusBar::FDoomStatusBarTexture::~FDoomStatusBarTexture () +DDoomStatusBar::FDoomStatusBarTexture::~FDoomStatusBarTexture () { Unload (); } -void FDoomStatusBar::FDoomStatusBarTexture::MakeTexture () +void DDoomStatusBar::FDoomStatusBarTexture::MakeTexture () { Pixels = new BYTE[Width*Height]; const BYTE *pix = BaseTexture->GetPixels(); @@ -1103,7 +1106,7 @@ void FDoomStatusBar::FDoomStatusBarTexture::MakeTexture () if (multiplayer) DrawToBar("STFBANY", 143, 1, STBFremap? STBFremap->Remap : NULL); } -int FDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) +int DDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int buf_pitch, int buf_height, int x, int y) { FTexture *tex; @@ -1136,7 +1139,7 @@ int FDoomStatusBar::FDoomStatusBarTexture::CopyTrueColorPixels(BYTE *buffer, int -void FDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, const BYTE *colormap_in) +void DDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, int y, const BYTE *colormap_in) { FTexture *pic; BYTE colormap[256]; @@ -1165,14 +1168,14 @@ void FDoomStatusBar::FDoomStatusBarTexture::DrawToBar (const char *name, int x, } } -void FDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap) +void DDoomStatusBar::FDoomStatusBarTexture::SetPlayerRemap(FRemapTable *remap) { Unload(); KillNative(); STBFremap = remap; } -FBaseStatusBar *CreateDoomStatusBar () +DBaseStatusBar *CreateDoomStatusBar () { - return new FDoomStatusBar; + return new DDoomStatusBar; } diff --git a/src/g_game.cpp b/src/g_game.cpp index a0d3ec1c3f..53aa2906a8 100644 --- a/src/g_game.cpp +++ b/src/g_game.cpp @@ -1850,7 +1850,7 @@ FString G_BuildSaveName (const char *prefix, int slot) const char *leader; const char *slash = ""; - if (NULL != (leader = Args.CheckValue ("-savedir"))) + if (NULL != (leader = Args->CheckValue ("-savedir"))) { size_t len = strlen (leader); if (leader[len-1] != '\\' && leader[len-1] != '/') @@ -1859,7 +1859,7 @@ FString G_BuildSaveName (const char *prefix, int slot) } } #ifndef unix - else if (Args.CheckParm ("-cdrom")) + else if (Args->CheckParm ("-cdrom")) { leader = CDROM_DIR "/"; } @@ -2205,7 +2205,7 @@ void G_RecordDemo (char* name) strcpy (demoname, name); FixPathSeperator (demoname); DefaultExtension (demoname, ".lmp"); - v = Args.CheckValue ("-maxdemo"); + v = Args->CheckValue ("-maxdemo"); maxdemosize = 0x20000; demobuffer = (BYTE *)M_Malloc (maxdemosize); @@ -2510,8 +2510,8 @@ void G_DoPlayDemo (void) // void G_TimeDemo (char* name) { - nodrawers = !!Args.CheckParm ("-nodraw"); - noblit = !!Args.CheckParm ("-noblit"); + nodrawers = !!Args->CheckParm ("-nodraw"); + noblit = !!Args->CheckParm ("-noblit"); timingdemo = true; singletics = true; diff --git a/src/g_heretic/a_hereticmisc.cpp b/src/g_heretic/a_hereticmisc.cpp index 773ad6ca25..c0f44e9c29 100644 --- a/src/g_heretic/a_hereticmisc.cpp +++ b/src/g_heretic/a_hereticmisc.cpp @@ -32,7 +32,7 @@ class APod : public AActor HAS_OBJECT_POINTERS public: void BeginPlay (); - AActor *Generator; + TObjPtr Generator; void Serialize (FArchive &arc); }; diff --git a/src/g_heretic/a_hereticweaps.cpp b/src/g_heretic/a_hereticweaps.cpp index ec4abd3f69..8874729b29 100644 --- a/src/g_heretic/a_hereticweaps.cpp +++ b/src/g_heretic/a_hereticweaps.cpp @@ -803,7 +803,7 @@ public: protected: bool DoRespawn (); int NumMaceSpots; - AActor *FirstSpot; + TObjPtr FirstSpot; private: friend void A_SpawnMace (AActor *self); diff --git a/src/g_heretic/heretic_sbar.cpp b/src/g_heretic/heretic_sbar.cpp index d2b02d6e15..058779c94d 100644 --- a/src/g_heretic/heretic_sbar.cpp +++ b/src/g_heretic/heretic_sbar.cpp @@ -84,10 +84,12 @@ const BYTE *FHereticShader::GetPixels () } -class FHereticStatusBar : public FBaseStatusBar +class DHereticStatusBar : public DBaseStatusBar { + DECLARE_CLASS(DHereticStatusBar, DBaseStatusBar) + HAS_OBJECT_POINTERS public: - FHereticStatusBar () : FBaseStatusBar (42) + DHereticStatusBar () : DBaseStatusBar (42) { static const char *hereticLumpNames[NUM_HERETICSB_IMAGES] = { @@ -118,7 +120,7 @@ public: hereticLumpNames[5] = "LIFEBAR"; } - FBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); + DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); Images.Init (hereticLumpNames, NUM_HERETICSB_IMAGES); oldarti = NULL; @@ -136,7 +138,7 @@ public: ArtifactFlash = 0; } - ~FHereticStatusBar () + ~DHereticStatusBar () { } @@ -144,7 +146,7 @@ public: { int curHealth; - FBaseStatusBar::Tick (); + DBaseStatusBar::Tick (); if (level.time & 1) { ChainWiggle = pr_chainwiggle() & 1; @@ -174,7 +176,7 @@ public: void Draw (EHudState state) { - FBaseStatusBar::Draw (state); + DBaseStatusBar::Draw (state); if (state == HUD_Fullscreen) { @@ -316,6 +318,7 @@ private: || (oldarti != NULL && oldartiCount != oldarti->Amount)) { oldarti = CPlayer->mo->InvSel; + GC::WriteBarrier(this, oldarti); oldartiCount = oldarti != NULL ? oldarti->Amount : 0; ArtiRefresh = screen->GetPageCount (); } @@ -422,6 +425,8 @@ private: oldammo2 = ammo2; oldammocount1 = ammocount1; oldammocount2 = ammocount2; + GC::WriteBarrier(this, ammo1); + GC::WriteBarrier(this, ammo2); AmmoRefresh = screen->GetPageCount (); } if (AmmoRefresh) @@ -475,7 +480,7 @@ private: void DrawInventoryBar () { - const AInventory *item; + AInventory *item; int i; DrawImage (Images[imgINVBAR], 34, 2); @@ -517,7 +522,7 @@ private: void DrawFullScreenStuff () { - const AInventory *item; + AInventory *item; FTexture *pic; int i; @@ -713,8 +718,8 @@ private: static const char patcharti[][10]; static const char ammopic[][10]; - AInventory *oldarti; - AAmmo *oldammo1, *oldammo2; + TObjPtr oldarti; + TObjPtr oldammo1, oldammo2; int oldammocount1, oldammocount2; int oldartiCount; int oldfrags; @@ -773,7 +778,13 @@ private: char ArmorRefresh; }; -FBaseStatusBar *CreateHereticStatusBar () +IMPLEMENT_POINTY_CLASS(DHereticStatusBar) + DECLARE_POINTER(oldarti) + DECLARE_POINTER(oldammo1) + DECLARE_POINTER(oldammo2) +END_POINTERS + +DBaseStatusBar *CreateHereticStatusBar () { - return new FHereticStatusBar; + return new DHereticStatusBar; } diff --git a/src/g_hexen/a_clericholy.cpp b/src/g_hexen/a_clericholy.cpp index e9b5c6ad06..177bbde2db 100644 --- a/src/g_hexen/a_clericholy.cpp +++ b/src/g_hexen/a_clericholy.cpp @@ -386,6 +386,7 @@ bool AHolySpirit::SpecialBlastHandling (AActor *source, fixed_t strength) { tracer = target; target = source; + GC::WriteBarrier(this, source); } return true; } diff --git a/src/g_hexen/a_heresiarch.cpp b/src/g_hexen/a_heresiarch.cpp index 7a17c98603..e0d969cf55 100644 --- a/src/g_hexen/a_heresiarch.cpp +++ b/src/g_hexen/a_heresiarch.cpp @@ -706,7 +706,7 @@ void A_SorcBallOrbit(AActor *ball) int x,y; angle_t angle, baseangle; int mode = ball->target->args[3]; - AHeresiarch *parent = static_cast (ball->target); + AHeresiarch *parent = barrier_cast(ball->target); int dist = parent->radius - (ball->radius<<1); angle_t prevangle = ball->special1; diff --git a/src/g_hexen/a_hexenglobal.h b/src/g_hexen/a_hexenglobal.h index 9720ffdf20..dbc16d2a0d 100644 --- a/src/g_hexen/a_hexenglobal.h +++ b/src/g_hexen/a_hexenglobal.h @@ -66,7 +66,7 @@ protected: virtual bool MatchPlayerClass (AActor *toucher); const PClass *FourthWeaponClass; int PieceValue; - AInventory *TempFourthWeapon; + TObjPtr TempFourthWeapon; bool PrivateShouldStay (); }; diff --git a/src/g_hexen/a_spike.cpp b/src/g_hexen/a_spike.cpp index 775e0af73b..fa4ff486dd 100644 --- a/src/g_hexen/a_spike.cpp +++ b/src/g_hexen/a_spike.cpp @@ -103,7 +103,7 @@ public: void Activate (AActor *activator); void Deactivate (AActor *activator); - ADirtClump *DirtClump; + TObjPtr DirtClump; }; IMPLEMENT_POINTY_CLASS (AThrustFloor) diff --git a/src/g_hexen/a_teleportother.cpp b/src/g_hexen/a_teleportother.cpp index 75610b3ba8..2a0cd8b58a 100644 --- a/src/g_hexen/a_teleportother.cpp +++ b/src/g_hexen/a_teleportother.cpp @@ -249,7 +249,7 @@ int ATelOtherFX1::DoSpecialDamage (AActor *target, int damage) { target->RemoveFromHash (); LineSpecials[target->special] (NULL, level.flags & LEVEL_ACTOWNSPECIAL - ? target : this->target, false, target->args[0], target->args[1], + ? target : (AActor *)(this->target), false, target->args[0], target->args[1], target->args[2], target->args[3], target->args[4]); target->special = 0; } diff --git a/src/g_hexen/hexen_sbar.cpp b/src/g_hexen/hexen_sbar.cpp index ebff79bb5c..1a12a82aa2 100644 --- a/src/g_hexen/hexen_sbar.cpp +++ b/src/g_hexen/hexen_sbar.cpp @@ -119,10 +119,12 @@ void FManaBar::MakeTexture () memset (Pixels + 25+24+24, color0, run); } -class FHexenStatusBar : public FBaseStatusBar +class DHexenStatusBar : public DBaseStatusBar { + DECLARE_CLASS(DHexenStatusBar, DBaseStatusBar) + HAS_OBJECT_POINTERS public: - FHexenStatusBar () : FBaseStatusBar (38) + DHexenStatusBar () : DBaseStatusBar (38) { static const char *hexenLumpNames[NUM_HEXENSB_IMAGES] = { @@ -166,7 +168,7 @@ public: "INRED5", "INRED6", "INRED7", "INRED8", "INRED9" }; - FBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES + 10); + DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES + 10); Images.Init (hexenLumpNames, NUM_HEXENSB_IMAGES); ClassImages[0].Init (classLumpNames[0], NUM_HEXENCLASSSB_IMAGES); ClassImages[1].Init (classLumpNames[1], NUM_HEXENCLASSSB_IMAGES); @@ -201,7 +203,7 @@ public: AmmoRefresh = 0; } - ~FHexenStatusBar () + ~DHexenStatusBar () { } @@ -209,7 +211,7 @@ public: { int curHealth; - FBaseStatusBar::Tick (); + DBaseStatusBar::Tick (); if (CPlayer->mo == NULL) { curHealth = 0; @@ -242,7 +244,7 @@ public: void Draw (EHudState state) { - FBaseStatusBar::Draw (state); + DBaseStatusBar::Draw (state); if (state == HUD_Fullscreen) { @@ -309,7 +311,7 @@ public: void AttachToPlayer (player_s *player) { - FBaseStatusBar::AttachToPlayer (player); + DBaseStatusBar::AttachToPlayer (player); if (player->mo != NULL) { if (player->mo->IsKindOf (PClass::FindClass(NAME_MagePlayer))) @@ -395,6 +397,7 @@ private: || (oldarti != NULL && oldartiCount != oldarti->Amount)) { oldarti = CPlayer->mo->InvSel; + GC::WriteBarrier(this, oldarti); oldartiCount = oldarti != NULL ? oldarti->Amount : 0; ArtiRefresh = screen->GetPageCount (); } @@ -521,12 +524,14 @@ private: AmmoRefresh = screen->GetPageCount (); oldammo1 = ammo1; oldammocount1 = ammocount1; + GC::WriteBarrier(this, ammo1); } if (ammo2 != oldammo2 || ammocount2 != oldammocount2) { AmmoRefresh = screen->GetPageCount (); oldammo2 = ammo2; oldammocount2 = ammocount2; + GC::WriteBarrier(this, ammo2); } if (AmmoRefresh) @@ -705,7 +710,7 @@ private: void DrawInventoryBar () { - const AInventory *item; + AInventory *item; int i; DrawImage (Images[imgINVBAR], 38, 0); @@ -772,6 +777,7 @@ private: if (keys[i] != oldkeys[i]) { oldkeys[i] = keys[i]; + GC::WriteBarrier(this, keys[i]); different = true; } } @@ -880,7 +886,7 @@ private: void DrawFullScreenStuff () { - const AInventory *item; + AInventory *item; int i; // Health @@ -1051,9 +1057,9 @@ private: static const char patcharti[][10]; static const char ammopic[][10]; - AInventory *oldarti; - AAmmo *oldammo1, *oldammo2; - AKey *oldkeys[5]; + TObjPtr oldarti; + TObjPtr oldammo1, oldammo2; + TObjPtr oldkeys[5]; int oldammocount1, oldammocount2; int oldartiCount; int oldfrags; @@ -1155,7 +1161,18 @@ private: FManaBar ManaVial2Pic; }; -FBaseStatusBar *CreateHexenStatusBar () +IMPLEMENT_POINTY_CLASS(DHexenStatusBar) + DECLARE_POINTER(oldarti) + DECLARE_POINTER(oldammo1) + DECLARE_POINTER(oldammo2) + DECLARE_POINTER(oldkeys[0]) + DECLARE_POINTER(oldkeys[1]) + DECLARE_POINTER(oldkeys[2]) + DECLARE_POINTER(oldkeys[3]) + DECLARE_POINTER(oldkeys[4]) +END_POINTERS + +DBaseStatusBar *CreateHexenStatusBar () { - return new FHexenStatusBar; + return new DHexenStatusBar; } diff --git a/src/g_level.cpp b/src/g_level.cpp index 29e2d25af6..a503032568 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1536,12 +1536,12 @@ void G_InitNew (const char *mapname, bool bTitleLevel) if (StatusBar != NULL) { - delete StatusBar; + StatusBar->Destroy(); StatusBar = NULL; } if (bTitleLevel) { - StatusBar = new FBaseStatusBar (0); + StatusBar = new DBaseStatusBar (0); } else if (SBarInfoScript != NULL) { @@ -1588,9 +1588,10 @@ void G_InitNew (const char *mapname, bool bTitleLevel) } else { - StatusBar = new FBaseStatusBar (0); + StatusBar = new DBaseStatusBar (0); } } + GC::WriteBarrier(StatusBar); StatusBar->AttachToPlayer (&players[consoleplayer]); StatusBar->NewGame (); setsizeneeded = true; diff --git a/src/g_shared/a_action.cpp b/src/g_shared/a_action.cpp index e708e5a331..d043389bba 100644 --- a/src/g_shared/a_action.cpp +++ b/src/g_shared/a_action.cpp @@ -332,7 +332,7 @@ public: DCorpsePointer (AActor *ptr); void Destroy (); void Serialize (FArchive &arc); - AActor *Corpse; + TObjPtr Corpse; DWORD Count; // Only the first corpse pointer's count is valid. private: DCorpsePointer () {} diff --git a/src/g_shared/a_decals.cpp b/src/g_shared/a_decals.cpp index 5e4c3141c8..811348bc0f 100644 --- a/src/g_shared/a_decals.cpp +++ b/src/g_shared/a_decals.cpp @@ -52,10 +52,10 @@ static int ImpactCount; CVAR (Bool, cl_spreaddecals, true, CVAR_ARCHIVE) -// They also overload floorclip to be the fractional distance from the -// left edge of the side. This distance is stored as a 2.30 fixed pt number. +IMPLEMENT_POINTY_CLASS (DBaseDecal) + DECLARE_POINTER(WallNext) +END_POINTERS -IMPLEMENT_CLASS (DBaseDecal) IMPLEMENT_CLASS (DImpactDecal) DBaseDecal::DBaseDecal () diff --git a/src/g_shared/a_morph.cpp b/src/g_shared/a_morph.cpp index 3837a0af2f..c091c51337 100644 --- a/src/g_shared/a_morph.cpp +++ b/src/g_shared/a_morph.cpp @@ -137,7 +137,7 @@ bool P_UndoPlayerMorph (player_t *player, bool force) { return false; } - mo = static_cast(pmo->tracer); + mo = barrier_cast(pmo->tracer); mo->SetOrigin (pmo->x, pmo->y, pmo->z); mo->flags |= MF_SOLID; pmo->flags &= ~MF_SOLID; diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index 775260b9f6..50015f34f8 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -61,7 +61,7 @@ public: void Serialize (FArchive &arc); - AInterpolationPoint *Next; + TObjPtr Next; }; IMPLEMENT_POINTY_CLASS (AInterpolationPoint) @@ -181,7 +181,7 @@ protected: void Serialize (FArchive &arc); bool bActive, bJustStepped; - AInterpolationPoint *PrevNode, *CurrNode; + TObjPtr PrevNode, CurrNode; float Time; // Runs from 0.0 to 1.0 between CurrNode and CurrNode->Next int HoldTime; }; @@ -289,8 +289,8 @@ void APathFollower::Activate (AActor *activator) { if (!bActive) { - CurrNode = static_cast(target); - PrevNode = static_cast(lastenemy); + CurrNode = barrier_cast(target); + PrevNode = barrier_cast(lastenemy); if (CurrNode != NULL) { @@ -638,7 +638,7 @@ public: protected: bool Interpolate (); - AActor *Activator; + TObjPtr Activator; }; IMPLEMENT_POINTY_CLASS (AMovingCamera) diff --git a/src/g_shared/a_pickups.cpp b/src/g_shared/a_pickups.cpp index a7660bdfb8..a85f022bef 100644 --- a/src/g_shared/a_pickups.cpp +++ b/src/g_shared/a_pickups.cpp @@ -101,7 +101,7 @@ bool AAmmo::HandlePickup (AInventory *item) (Owner->player->ReadyWeapon == NULL || (Owner->player->ReadyWeapon->WeaponFlags & WIF_WIMPY_WEAPON))) { - AWeapon *best = static_cast(Owner)->BestWeapon (GetClass()); + AWeapon *best = barrier_cast(Owner)->BestWeapon (GetClass()); if (best != NULL && (Owner->player->ReadyWeapon == NULL || best->SelectionOrder < Owner->player->ReadyWeapon->SelectionOrder)) { @@ -1052,7 +1052,7 @@ PalEntry AInventory::GetBlend () // //=========================================================================== -AInventory *AInventory::PrevItem () const +AInventory *AInventory::PrevItem () { AInventory *item = Owner->Inventory; @@ -1071,7 +1071,7 @@ AInventory *AInventory::PrevItem () const // //=========================================================================== -AInventory *AInventory::PrevInv () const +AInventory *AInventory::PrevInv () { AInventory *lastgood = NULL; AInventory *item = Owner->Inventory; @@ -1094,7 +1094,7 @@ AInventory *AInventory::PrevInv () const // //=========================================================================== -AInventory *AInventory::NextInv () const +AInventory *AInventory::NextInv () { AInventory *item = Inventory; diff --git a/src/g_shared/a_pickups.h b/src/g_shared/a_pickups.h index 3ceaa9a0a9..ad0e3a6529 100644 --- a/src/g_shared/a_pickups.h +++ b/src/g_shared/a_pickups.h @@ -124,11 +124,11 @@ public: virtual const char *PickupMessage (); virtual void PlayPickupSound (AActor *toucher); - AInventory *PrevItem () const; // Returns the item preceding this one in the list. - AInventory *PrevInv () const; // Returns the previous item with IF_INVBAR set. - AInventory *NextInv () const; // Returns the next item with IF_INVBAR set. + AInventory *PrevItem(); // Returns the item preceding this one in the list. + AInventory *PrevInv(); // Returns the previous item with IF_INVBAR set. + AInventory *NextInv(); // Returns the next item with IF_INVBAR set. - AActor *Owner; // Who owns this item? NULL if it's still a pickup. + TObjPtr Owner; // Who owns this item? NULL if it's still a pickup. int Amount; // Amount of item this instance has int MaxAmount; // Max amount of item this instance can have int RespawnTics; // Tics from pickup time to respawn time @@ -217,8 +217,8 @@ public: fixed_t MoveCombatDist; // Used by bots, but do they *really* need it? // In-inventory instance variables - AAmmo *Ammo1, *Ammo2; - AWeapon *SisterWeapon; + TObjPtr Ammo1, Ammo2; + TObjPtr SisterWeapon; bool bAltFire; // Set when this weapon's alternate fire is used. diff --git a/src/g_shared/a_sectoraction.cpp b/src/g_shared/a_sectoraction.cpp index bddc0f15b5..3b82aff002 100644 --- a/src/g_shared/a_sectoraction.cpp +++ b/src/g_shared/a_sectoraction.cpp @@ -88,7 +88,7 @@ void ASectorAction::Deactivate (AActor *source) bool ASectorAction::TriggerAction (AActor *triggerer, int activationType) { if (tracer != NULL) - return static_cast(tracer)->TriggerAction (triggerer, activationType); + return barrier_cast(tracer)->TriggerAction (triggerer, activationType); else return false; } diff --git a/src/g_shared/a_sharedglobal.h b/src/g_shared/a_sharedglobal.h index d89bbe9040..c8b376ce46 100644 --- a/src/g_shared/a_sharedglobal.h +++ b/src/g_shared/a_sharedglobal.h @@ -23,6 +23,7 @@ struct side_s; class DBaseDecal : public DThinker { DECLARE_CLASS (DBaseDecal, DThinker) + HAS_OBJECT_POINTERS public: DBaseDecal (); DBaseDecal (fixed_t z); @@ -147,7 +148,7 @@ protected: float Blends[2][4]; int TotalTics; int StartTic; - AActor *ForWho; + TObjPtr ForWho; void SetBlend (float time); DFlashFader (); @@ -163,7 +164,7 @@ public: void Serialize (FArchive &arc); void Tick (); - AActor *m_Spot; + TObjPtr m_Spot; fixed_t m_TremorRadius, m_DamageRadius; int m_Intensity; int m_Countdown; @@ -195,7 +196,7 @@ public: void Die (AActor *source, AActor *inflictor); void Destroy (); - AActor *UnmorphedMe; + TObjPtr UnmorphedMe; int UnmorphTime; DWORD FlagsSave; }; diff --git a/src/g_shared/a_weaponpiece.cpp b/src/g_shared/a_weaponpiece.cpp index 2e987c33e1..aa47874e63 100644 --- a/src/g_shared/a_weaponpiece.cpp +++ b/src/g_shared/a_weaponpiece.cpp @@ -27,7 +27,11 @@ IMPLEMENT_STATELESS_ACTOR (AWeaponHolder, Any, -1, 0) PROP_Inventory_FlagsSet (IF_UNDROPPABLE) END_DEFAULTS -IMPLEMENT_STATELESS_ACTOR (AWeaponPiece, Any, -1, 0) + +IMPLEMENT_POINTY_CLASS (AWeaponPiece) + DECLARE_POINTER (FullWeapon) +END_POINTERS +BEGIN_STATELESS_DEFAULTS (AWeaponPiece, Any, -1, 0) END_DEFAULTS diff --git a/src/g_shared/a_weaponpiece.h b/src/g_shared/a_weaponpiece.h index f0d4657714..d6df4a71a4 100644 --- a/src/g_shared/a_weaponpiece.h +++ b/src/g_shared/a_weaponpiece.h @@ -2,6 +2,7 @@ class AWeaponPiece : public AInventory { DECLARE_CLASS (AWeaponPiece, AInventory) + HAS_OBJECT_POINTERS protected: bool PrivateShouldStay (); public: @@ -13,5 +14,5 @@ public: int PieceValue; const PClass * WeaponClass; - AWeapon * FullWeapon; + TObjPtr FullWeapon; }; diff --git a/src/g_shared/a_weapons.cpp b/src/g_shared/a_weapons.cpp index 6cdcab3fe7..8f35819f7c 100644 --- a/src/g_shared/a_weapons.cpp +++ b/src/g_shared/a_weapons.cpp @@ -370,7 +370,7 @@ bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo) bool gotSome = CheckAmmo (PrimaryFire, false) || CheckAmmo (AltFire, false); if (!gotSome && autoSwitch) { - static_cast (Owner)->PickNewWeapon (NULL); + barrier_cast(Owner)->PickNewWeapon (NULL); } return gotSome; } @@ -402,7 +402,7 @@ bool AWeapon::CheckAmmo (int fireMode, bool autoSwitch, bool requireAmmo) // out of ammo, pick a weapon to change to if (autoSwitch) { - static_cast (Owner)->PickNewWeapon (NULL); + barrier_cast(Owner)->PickNewWeapon (NULL); } return false; } diff --git a/src/g_shared/hudmessages.cpp b/src/g_shared/hudmessages.cpp index 0f17da0291..5bb9be2b87 100644 --- a/src/g_shared/hudmessages.cpp +++ b/src/g_shared/hudmessages.cpp @@ -41,7 +41,10 @@ EXTERN_CVAR (Int, con_scaletext) -IMPLEMENT_CLASS (DHUDMessage) +IMPLEMENT_POINTY_CLASS (DHUDMessage) + DECLARE_POINTER(Next) +END_POINTERS + IMPLEMENT_CLASS (DHUDMessageFadeOut) IMPLEMENT_CLASS (DHUDMessageFadeInOut) IMPLEMENT_CLASS (DHUDMessageTypeOnFadeOut) diff --git a/src/g_shared/sbar.h b/src/g_shared/sbar.h index d6c3ee70c7..f7101d974d 100644 --- a/src/g_shared/sbar.h +++ b/src/g_shared/sbar.h @@ -55,6 +55,7 @@ class AWeapon; class DHUDMessage : public DObject { DECLARE_CLASS (DHUDMessage, DObject) + HAS_OBJECT_POINTERS public: DHUDMessage (const char *text, float x, float y, int hudwidth, int hudheight, EColorRange textColor, float holdTime); @@ -84,11 +85,11 @@ protected: DHUDMessage () : SourceText(NULL) {} private: - DHUDMessage *Next; + TObjPtr Next; DWORD SBarID; char *SourceText; - friend class FBaseStatusBar; + friend class DBaseStatusBar; }; class DHUDMessageFadeOut : public DHUDMessage @@ -149,8 +150,10 @@ protected: class FTexture; class AAmmo; -class FBaseStatusBar +class DBaseStatusBar : public DObject { + DECLARE_CLASS (DBaseStatusBar, DObject) + HAS_OBJECT_POINTERS public: // Popup screens for Strife's status bar enum @@ -162,8 +165,8 @@ public: POP_Status }; - FBaseStatusBar (int reltop); - virtual ~FBaseStatusBar (); + DBaseStatusBar (int reltop); + void Destroy (); void SetScaled (bool scale); @@ -246,20 +249,21 @@ public: player_s *CPlayer; private: + DBaseStatusBar() {} bool RepositionCoords (int &x, int &y, int xo, int yo, const int w, const int h) const; - void DrawMessages (int bottom) const; + void DrawMessages (int bottom); void DrawConsistancy () const; static BYTE DamageToAlpha[114]; - DHUDMessage *Messages; + TObjPtr Messages; bool ShowLog; }; -extern FBaseStatusBar *StatusBar; +extern DBaseStatusBar *StatusBar; -FBaseStatusBar *CreateDoomStatusBar (); -FBaseStatusBar *CreateHereticStatusBar (); -FBaseStatusBar *CreateHexenStatusBar (); -FBaseStatusBar *CreateStrifeStatusBar (); -FBaseStatusBar *CreateCustomStatusBar (); +DBaseStatusBar *CreateDoomStatusBar (); +DBaseStatusBar *CreateHereticStatusBar (); +DBaseStatusBar *CreateHexenStatusBar (); +DBaseStatusBar *CreateStrifeStatusBar (); +DBaseStatusBar *CreateCustomStatusBar (); diff --git a/src/g_shared/sbarinfo.cpp b/src/g_shared/sbarinfo.cpp index 4f546004de..31e38ae42e 100644 --- a/src/g_shared/sbarinfo.cpp +++ b/src/g_shared/sbarinfo.cpp @@ -1238,10 +1238,11 @@ SBarInfoBlock::SBarInfoBlock() } //SBarInfo Display -class FSBarInfo : public FBaseStatusBar +class DSBarInfo : public DBaseStatusBar { + DECLARE_CLASS(DSBarInfo, DBaseStatusBar) public: - FSBarInfo () : FBaseStatusBar (SBarInfoScript->height), + DSBarInfo () : DBaseStatusBar (SBarInfoScript->height), shader_horz_normal(false, false), shader_horz_reverse(false, true), shader_vert_normal(true, false), @@ -1279,7 +1280,7 @@ public: artiflash = 4; } - ~FSBarInfo () + ~DSBarInfo () { Images.Uninit(); Faces.Uninit(); @@ -1287,7 +1288,7 @@ public: void Draw (EHudState state) { - FBaseStatusBar::Draw(state); + DBaseStatusBar::Draw(state); int hud = 2; if(state == HUD_StatusBar) { @@ -1341,7 +1342,7 @@ public: void AttachToPlayer (player_t *player) { player_t *oldplayer = CPlayer; - FBaseStatusBar::AttachToPlayer(player); + DBaseStatusBar::AttachToPlayer(player); if (oldplayer != CPlayer) { SetFace(&skins[CPlayer->userinfo.skin], "STF"); @@ -1350,7 +1351,7 @@ public: void Tick () { - FBaseStatusBar::Tick(); + DBaseStatusBar::Tick(); if(level.time & 1) chainWiggle = pr_chainwiggle() & 1; getNewFace(M_Random()); @@ -2310,7 +2311,7 @@ private: void DrawInventoryBar(int type, int num, int x, int y, bool alwaysshow, int counterx, int countery, EColorRange translation, bool drawArtiboxes, bool noArrows, bool alwaysshowcounter) { //yes, there is some Copy & Paste here too - const AInventory *item; + AInventory *item; int i; // If the player has no artifacts, don't draw the bar @@ -2408,7 +2409,9 @@ private: FBarShader shader_vert_reverse; }; -FBaseStatusBar *CreateCustomStatusBar () +IMPLEMENT_CLASS(DSBarInfo); + +DBaseStatusBar *CreateCustomStatusBar () { - return new FSBarInfo; + return new DSBarInfo; } diff --git a/src/g_shared/shared_sbar.cpp b/src/g_shared/shared_sbar.cpp index 52d5299fca..c8209eb4b3 100644 --- a/src/g_shared/shared_sbar.cpp +++ b/src/g_shared/shared_sbar.cpp @@ -53,6 +53,10 @@ #define XHAIRPICKUPSIZE (FRACUNIT*2+XHAIRSHRINKSIZE) #define POWERUPICONSIZE 32 +IMPLEMENT_POINTY_CLASS(DBaseStatusBar) + DECLARE_POINTER(Messages) +END_POINTERS + EXTERN_CVAR (Bool, am_showmonsters) EXTERN_CVAR (Bool, am_showsecrets) EXTERN_CVAR (Bool, am_showitems) @@ -62,7 +66,7 @@ EXTERN_CVAR (Bool, noisedebug) EXTERN_CVAR (Bool, hud_scale) EXTERN_CVAR (Int, con_scaletext) -FBaseStatusBar *StatusBar; +DBaseStatusBar *StatusBar; extern int setblocks; @@ -126,7 +130,7 @@ CVAR (Bool, idmypos, false, 0); // [RH] Amount of red flash for up to 114 damage points. Calculated by hand // using a logarithmic scale and my trusty HP48G. -BYTE FBaseStatusBar::DamageToAlpha[114] = +BYTE DBaseStatusBar::DamageToAlpha[114] = { 0, 8, 16, 23, 30, 36, 42, 47, 53, 58, 62, 67, 71, 75, 79, 83, 87, 90, 94, 97, 100, 103, 107, 109, 112, 115, 118, 120, 123, 125, @@ -144,7 +148,7 @@ BYTE FBaseStatusBar::DamageToAlpha[114] = // //--------------------------------------------------------------------------- -FBaseStatusBar::FBaseStatusBar (int reltop) +DBaseStatusBar::DBaseStatusBar (int reltop) { Centering = false; FixedOrigin = false; @@ -160,11 +164,11 @@ FBaseStatusBar::FBaseStatusBar (int reltop) //--------------------------------------------------------------------------- // -// Destructor +// PROP Destroy // //--------------------------------------------------------------------------- -FBaseStatusBar::~FBaseStatusBar () +void DBaseStatusBar::Destroy () { DHUDMessage *msg; @@ -172,9 +176,10 @@ FBaseStatusBar::~FBaseStatusBar () while (msg) { DHUDMessage *next = msg->Next; - delete msg; + msg->Destroy(); msg = next; } + Super::Destroy(); } //--------------------------------------------------------------------------- @@ -183,7 +188,7 @@ FBaseStatusBar::~FBaseStatusBar () // //--------------------------------------------------------------------------- -void FBaseStatusBar::SetScaled (bool scale) +void DBaseStatusBar::SetScaled (bool scale) { Scaled = RelTop != 0 && (SCREENWIDTH != 320 && scale); if (!Scaled) @@ -225,7 +230,7 @@ void FBaseStatusBar::SetScaled (bool scale) // //--------------------------------------------------------------------------- -void FBaseStatusBar::AttachToPlayer (player_s *player) +void DBaseStatusBar::AttachToPlayer (player_s *player) { CPlayer = player; SB_state = screen->GetPageCount (); @@ -237,7 +242,7 @@ void FBaseStatusBar::AttachToPlayer (player_s *player) // //--------------------------------------------------------------------------- -int FBaseStatusBar::GetPlayer () +int DBaseStatusBar::GetPlayer () { return int(CPlayer - players); } @@ -248,7 +253,7 @@ int FBaseStatusBar::GetPlayer () // //--------------------------------------------------------------------------- -void FBaseStatusBar::MultiplayerChanged () +void DBaseStatusBar::MultiplayerChanged () { SB_state = screen->GetPageCount (); } @@ -259,7 +264,7 @@ void FBaseStatusBar::MultiplayerChanged () // //--------------------------------------------------------------------------- -void FBaseStatusBar::Tick () +void DBaseStatusBar::Tick () { DHUDMessage *msg = Messages; DHUDMessage **prev = &Messages; @@ -271,7 +276,7 @@ void FBaseStatusBar::Tick () if (msg->Tick ()) { *prev = next; - delete msg; + msg->Destroy(); } else { @@ -297,15 +302,16 @@ void FBaseStatusBar::Tick () // //--------------------------------------------------------------------------- -void FBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id) +void DBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id) { DHUDMessage *old = NULL; DHUDMessage **prev; + DObject *container = this; old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id); if (old != NULL) { - delete old; + old->Destroy(); } prev = &Messages; @@ -315,12 +321,14 @@ void FBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id) // it gets drawn back to front.) while (*prev != NULL && (*prev)->SBarID > id) { + container = *prev; prev = &(*prev)->Next; } msg->Next = *prev; msg->SBarID = id; *prev = msg; + GC::WriteBarrier(container, msg); } //--------------------------------------------------------------------------- @@ -329,7 +337,7 @@ void FBaseStatusBar::AttachMessage (DHUDMessage *msg, DWORD id) // //--------------------------------------------------------------------------- -DHUDMessage *FBaseStatusBar::DetachMessage (DHUDMessage *msg) +DHUDMessage *DBaseStatusBar::DetachMessage (DHUDMessage *msg) { DHUDMessage *probe = Messages; DHUDMessage **prev = &Messages; @@ -349,7 +357,7 @@ DHUDMessage *FBaseStatusBar::DetachMessage (DHUDMessage *msg) return probe; } -DHUDMessage *FBaseStatusBar::DetachMessage (DWORD id) +DHUDMessage *DBaseStatusBar::DetachMessage (DWORD id) { DHUDMessage *probe = Messages; DHUDMessage **prev = &Messages; @@ -375,7 +383,7 @@ DHUDMessage *FBaseStatusBar::DetachMessage (DWORD id) // //--------------------------------------------------------------------------- -void FBaseStatusBar::DetachAllMessages () +void DBaseStatusBar::DetachAllMessages () { DHUDMessage *probe = Messages; @@ -383,7 +391,7 @@ void FBaseStatusBar::DetachAllMessages () while (probe != NULL) { DHUDMessage *next = probe->Next; - delete probe; + probe->Destroy(); probe = next; } } @@ -394,7 +402,7 @@ void FBaseStatusBar::DetachAllMessages () // //--------------------------------------------------------------------------- -bool FBaseStatusBar::CheckMessage (DHUDMessage *msg) +bool DBaseStatusBar::CheckMessage (DHUDMessage *msg) { DHUDMessage *probe = Messages; while (probe && probe != msg) @@ -410,7 +418,7 @@ bool FBaseStatusBar::CheckMessage (DHUDMessage *msg) // //--------------------------------------------------------------------------- -void FBaseStatusBar::ShowPlayerName () +void DBaseStatusBar::ShowPlayerName () { EColorRange color; @@ -427,7 +435,7 @@ void FBaseStatusBar::ShowPlayerName () // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawImage (FTexture *img, +void DBaseStatusBar::DrawImage (FTexture *img, int x, int y, FRemapTable *translation) const { if (img != NULL) @@ -448,7 +456,7 @@ void FBaseStatusBar::DrawImage (FTexture *img, // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawDimImage (FTexture *img, +void DBaseStatusBar::DrawDimImage (FTexture *img, int x, int y, bool dimmed) const { if (img != NULL) @@ -469,7 +477,7 @@ void FBaseStatusBar::DrawDimImage (FTexture *img, // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawFadedImage (FTexture *img, +void DBaseStatusBar::DrawFadedImage (FTexture *img, int x, int y, fixed_t shade) const { if (img != NULL) @@ -491,7 +499,7 @@ void FBaseStatusBar::DrawFadedImage (FTexture *img, // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawPartialImage (FTexture *img, int wx, int ww) const +void DBaseStatusBar::DrawPartialImage (FTexture *img, int wx, int ww) const { if (img != NULL) { @@ -511,7 +519,7 @@ void FBaseStatusBar::DrawPartialImage (FTexture *img, int wx, int ww) const // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrINumber (signed int val, int x, int y, int imgBase) const +void DBaseStatusBar::DrINumber (signed int val, int x, int y, int imgBase) const { int oldval; @@ -551,7 +559,7 @@ void FBaseStatusBar::DrINumber (signed int val, int x, int y, int imgBase) const // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrBNumber (signed int val, int x, int y, int size) const +void DBaseStatusBar::DrBNumber (signed int val, int x, int y, int size) const { bool neg; int i, w; @@ -611,7 +619,7 @@ void FBaseStatusBar::DrBNumber (signed int val, int x, int y, int size) const // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrSmallNumber (int val, int x, int y) const +void DBaseStatusBar::DrSmallNumber (int val, int x, int y) const { int digit = 0; @@ -642,7 +650,7 @@ void FBaseStatusBar::DrSmallNumber (int val, int x, int y) const // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrINumberOuter (signed int val, int x, int y, bool center, int w) const +void DBaseStatusBar::DrINumberOuter (signed int val, int x, int y, bool center, int w) const { bool negative = false; @@ -706,7 +714,7 @@ void FBaseStatusBar::DrINumberOuter (signed int val, int x, int y, bool center, // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrBNumberOuter (signed int val, int x, int y, int size) const +void DBaseStatusBar::DrBNumberOuter (signed int val, int x, int y, int size) const { int xpos; int w; @@ -813,7 +821,7 @@ void FBaseStatusBar::DrBNumberOuter (signed int val, int x, int y, int size) con // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) const +void DBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) const { int xpos; int w, v; @@ -914,7 +922,7 @@ void FBaseStatusBar::DrBNumberOuterFont (signed int val, int x, int y, int size) // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrSmallNumberOuter (int val, int x, int y, bool center) const +void DBaseStatusBar::DrSmallNumberOuter (int val, int x, int y, bool center) const { int digit = 0; @@ -946,7 +954,7 @@ void FBaseStatusBar::DrSmallNumberOuter (int val, int x, int y, bool center) con // //--------------------------------------------------------------------------- -void FBaseStatusBar::RefreshBackground () const +void DBaseStatusBar::RefreshBackground () const { int x, x2, y, ratio; @@ -981,7 +989,7 @@ void FBaseStatusBar::RefreshBackground () const // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawCrosshair () +void DBaseStatusBar::DrawCrosshair () { static DWORD prevcolor = 0xffffffff; static int palettecolor = 0; @@ -1072,7 +1080,7 @@ void FBaseStatusBar::DrawCrosshair () // //--------------------------------------------------------------------------- -void FBaseStatusBar::FlashCrosshair () +void DBaseStatusBar::FlashCrosshair () { CrosshairSize = XHAIRPICKUPSIZE; } @@ -1083,7 +1091,7 @@ void FBaseStatusBar::FlashCrosshair () // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawMessages (int bottom) const +void DBaseStatusBar::DrawMessages (int bottom) { DHUDMessage *msg = Messages; while (msg) @@ -1100,7 +1108,7 @@ void FBaseStatusBar::DrawMessages (int bottom) const // //--------------------------------------------------------------------------- -void FBaseStatusBar::Draw (EHudState state) +void DBaseStatusBar::Draw (EHudState state) { char line[64+10]; @@ -1254,7 +1262,7 @@ void FBaseStatusBar::Draw (EHudState state) } -void FBaseStatusBar::DrawLog () +void DBaseStatusBar::DrawLog () { int hudwidth, hudheight; @@ -1318,7 +1326,7 @@ void FBaseStatusBar::DrawLog () } } -bool FBaseStatusBar::MustDrawLog(EHudState) +bool DBaseStatusBar::MustDrawLog(EHudState) { return true; } @@ -1329,7 +1337,7 @@ bool FBaseStatusBar::MustDrawLog(EHudState) // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawTopStuff (EHudState state) +void DBaseStatusBar::DrawTopStuff (EHudState state) { if (demoplayback && demover != DEMOGAMEVERSION) { @@ -1360,7 +1368,7 @@ void FBaseStatusBar::DrawTopStuff (EHudState state) // //--------------------------------------------------------------------------- -void FBaseStatusBar::DrawPowerups () +void DBaseStatusBar::DrawPowerups () { // Each icon gets a 32x32 block to draw itself in. int x, y; @@ -1388,7 +1396,7 @@ SV_AddBlend [RH] This is from Q2. ============= */ -void FBaseStatusBar::AddBlend (float r, float g, float b, float a, float v_blend[4]) +void DBaseStatusBar::AddBlend (float r, float g, float b, float a, float v_blend[4]) { float a2, a3; @@ -1409,7 +1417,7 @@ void FBaseStatusBar::AddBlend (float r, float g, float b, float a, float v_blend // //--------------------------------------------------------------------------- -void FBaseStatusBar::BlendView (float blend[4]) +void DBaseStatusBar::BlendView (float blend[4]) { int cnt; @@ -1480,7 +1488,7 @@ void FBaseStatusBar::BlendView (float blend[4]) (int)(blend[2] * 255.0f), (int)(blend[3] * 256.0f)); } -void FBaseStatusBar::DrawConsistancy () const +void DBaseStatusBar::DrawConsistancy () const { static bool firsttime = true; int i; @@ -1524,37 +1532,37 @@ void FBaseStatusBar::DrawConsistancy () const } } -void FBaseStatusBar::FlashItem (const PClass *itemtype) +void DBaseStatusBar::FlashItem (const PClass *itemtype) { } -void FBaseStatusBar::SetFace (void *) +void DBaseStatusBar::SetFace (void *) { } -void FBaseStatusBar::NewGame () +void DBaseStatusBar::NewGame () { } -void FBaseStatusBar::SetInteger (int pname, int param) +void DBaseStatusBar::SetInteger (int pname, int param) { } -void FBaseStatusBar::ShowPop (int popnum) +void DBaseStatusBar::ShowPop (int popnum) { ShowLog = (popnum == POP_Log && !ShowLog); } -void FBaseStatusBar::ReceivedWeapon (AWeapon *weapon) +void DBaseStatusBar::ReceivedWeapon (AWeapon *weapon) { } -void FBaseStatusBar::Serialize (FArchive &arc) +void DBaseStatusBar::Serialize (FArchive &arc) { arc << Messages; } -void FBaseStatusBar::ScreenSizeChanged () +void DBaseStatusBar::ScreenSizeChanged () { st_scale.Callback (); SB_state = screen->GetPageCount (); @@ -1576,7 +1584,7 @@ void FBaseStatusBar::ScreenSizeChanged () // //--------------------------------------------------------------------------- -AInventory *FBaseStatusBar::ValidateInvFirst (int numVisible) const +AInventory *DBaseStatusBar::ValidateInvFirst (int numVisible) const { AInventory *item; int i; @@ -1660,14 +1668,14 @@ AInventory *FBaseStatusBar::ValidateInvFirst (int numVisible) const //============================================================================ // -// FBaseStatusBar :: GetCurrentAmmo +// DBaseStatusBar :: GetCurrentAmmo // // Returns the types and amounts of ammo used by the current weapon. If the // weapon only uses one type of ammo, it is always returned as ammo1. // //============================================================================ -void FBaseStatusBar::GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const +void DBaseStatusBar::GetCurrentAmmo (AAmmo *&ammo1, AAmmo *&ammo2, int &ammocount1, int &ammocount2) const { if (CPlayer->ReadyWeapon != NULL) { diff --git a/src/g_strife/strife_sbar.cpp b/src/g_strife/strife_sbar.cpp index 2583e36a4e..83cf9a3773 100644 --- a/src/g_strife/strife_sbar.cpp +++ b/src/g_strife/strife_sbar.cpp @@ -180,10 +180,11 @@ void FHealthBar::FillBar (int min, int max, BYTE light, BYTE dark) } } -class FStrifeStatusBar : public FBaseStatusBar +class DStrifeStatusBar : public DBaseStatusBar { + DECLARE_CLASS(DStrifeStatusBar, DBaseStatusBar) public: - FStrifeStatusBar () : FBaseStatusBar (32) + DStrifeStatusBar () : DBaseStatusBar (32) { static const char *sharedLumpNames[] = { @@ -196,11 +197,11 @@ public: "INVFONG7", "INVFONG8", "INVFONG9" }; - FBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); + DBaseStatusBar::Images.Init (sharedLumpNames, NUM_BASESB_IMAGES); DoCommonInit (); } - ~FStrifeStatusBar () + ~DStrifeStatusBar () { } @@ -216,7 +217,7 @@ public: void Draw (EHudState state) { - FBaseStatusBar::Draw (state); + DBaseStatusBar::Draw (state); if (state == HUD_Fullscreen) { @@ -235,7 +236,7 @@ public: void ShowPop (int popnum) { - FBaseStatusBar::ShowPop(popnum); + DBaseStatusBar::ShowPop(popnum); if (popnum == CurrentPop) { if (popnum == POP_Keys) @@ -310,7 +311,7 @@ private: void Tick () { - FBaseStatusBar::Tick (); + DBaseStatusBar::Tick (); if (ItemFlash > 0) { @@ -845,7 +846,9 @@ private: fixed_t ItemFlash; }; -FBaseStatusBar *CreateStrifeStatusBar () +IMPLEMENT_CLASS(DStrifeStatusBar); + +DBaseStatusBar *CreateStrifeStatusBar () { - return new FStrifeStatusBar; + return new DStrifeStatusBar; } diff --git a/src/gameconfigfile.cpp b/src/gameconfigfile.cpp index ab77aa89be..7db13ed726 100644 --- a/src/gameconfigfile.cpp +++ b/src/gameconfigfile.cpp @@ -525,7 +525,7 @@ FString FGameConfigFile::GetConfigPath (bool tryProg) char *pathval; FString path; - pathval = Args.CheckValue ("-config"); + pathval = Args->CheckValue ("-config"); if (pathval != NULL) return FString(pathval); @@ -578,7 +578,7 @@ FString FGameConfigFile::GetConfigPath (bool tryProg) if (path.IsEmpty()) { - if (Args.CheckParm ("-cdrom")) + if (Args->CheckParm ("-cdrom")) return CDROM_DIR "\\zdoom.ini"; path = progdir; @@ -625,7 +625,7 @@ void FGameConfigFile::AddAutoexec (DArgs *list, const char *game) FString path; #ifndef unix - if (Args.CheckParm ("-cdrom")) + if (Args->CheckParm ("-cdrom")) { path = CDROM_DIR "\\autoexec.cfg"; } diff --git a/src/i_net.cpp b/src/i_net.cpp index 7c4b38d973..6e080df8b0 100644 --- a/src/i_net.cpp +++ b/src/i_net.cpp @@ -564,7 +564,7 @@ void HostGame (int i) int node; int gotack[MAXNETNODES+1]; - if ((i == Args.NumArgs() - 1) || !(numplayers = atoi (Args.GetArg(i+1)))) + if ((i == Args->NumArgs() - 1) || !(numplayers = atoi (Args->GetArg(i+1)))) { // No player count specified, assume 2 numplayers = 2; } @@ -742,15 +742,15 @@ bool Guest_WaitForOthers (void *userdata) void JoinGame (int i) { - if ((i == Args.NumArgs() - 1) || - (Args.GetArg(i+1)[0] == '-') || - (Args.GetArg(i+1)[0] == '+')) + 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)); + BuildAddress (&sendaddress[1], Args->GetArg(i+1)); sendplayer[1] = 0; doomcom.numnodes = 2; @@ -789,7 +789,7 @@ void I_InitNetwork (void) memset (&doomcom, 0, sizeof(doomcom)); // set up for network - v = Args.CheckValue ("-dup"); + v = Args->CheckValue ("-dup"); if (v) { doomcom.ticdup = clamp (atoi (v), 1, MAXTICDUP); @@ -799,12 +799,12 @@ void I_InitNetwork (void) doomcom.ticdup = 1; } - if (Args.CheckParm ("-extratic")) + if (Args->CheckParm ("-extratic")) doomcom.extratics = 1; else doomcom.extratics = 0; - v = Args.CheckValue ("-port"); + v = Args->CheckValue ("-port"); if (v) { DOOMPORT = atoi (v); @@ -814,11 +814,11 @@ void I_InitNetwork (void) // parse network game options, // player 1: -host // player x: -join - if ( (i = Args.CheckParm ("-host")) ) + if ( (i = Args->CheckParm ("-host")) ) { HostGame (i); } - else if ( (i = Args.CheckParm ("-join")) ) + else if ( (i = Args->CheckParm ("-join")) ) { JoinGame (i); } diff --git a/src/m_alloc.cpp b/src/m_alloc.cpp index 897f2e5472..4d9e0fbf3e 100644 --- a/src/m_alloc.cpp +++ b/src/m_alloc.cpp @@ -33,18 +33,8 @@ */ #include "i_system.h" -#include "stats.h" #include -ADD_STAT(mem) -{ - FString out; - out.Format("Alloc: %uKB", (AllocBytes + 1023) >> 10); - return out; -} - -size_t AllocBytes; - #ifndef _MSC_VER #define _NORMAL_BLOCK 0 #define _malloc_dbg(s,b,f,l) malloc(s) @@ -62,7 +52,7 @@ void *M_Malloc(size_t size) if (block == NULL) I_FatalError("Could not malloc %u bytes", size); - AllocBytes += _msize(block); + GC::AllocBytes += _msize(block); return block; } @@ -70,14 +60,14 @@ void *M_Realloc(void *memblock, size_t size) { if (memblock != NULL) { - AllocBytes -= _msize(memblock); + GC::AllocBytes -= _msize(memblock); } void *block = realloc(memblock, size); if (block == NULL) { I_FatalError("Could not realloc %u bytes", size); } - AllocBytes += _msize(block); + GC::AllocBytes += _msize(block); return block; } #else @@ -92,7 +82,7 @@ void *M_Malloc_Dbg(size_t size, const char *file, int lineno) if (block == NULL) I_FatalError("Could not malloc %u bytes", size); - AllocBytes += _msize(block); + GC::AllocBytes += _msize(block); return block; } @@ -100,14 +90,14 @@ void *M_Realloc_Dbg(void *memblock, size_t size, const char *file, int lineno) { if (memblock != NULL) { - AllocBytes -= _msize(memblock); + GC::AllocBytes -= _msize(memblock); } void *block = _realloc_dbg(memblock, size, _NORMAL_BLOCK, file, lineno); if (block == NULL) { I_FatalError("Could not realloc %u bytes", size); } - AllocBytes += _msize(block); + GC::AllocBytes += _msize(block); return block; } #endif @@ -116,7 +106,7 @@ void M_Free (void *block) { if (block != NULL) { - AllocBytes -= _msize(block); + GC::AllocBytes -= _msize(block); free(block); } } diff --git a/src/m_alloc.h b/src/m_alloc.h index 8d7866a7f2..17a6adeb51 100644 --- a/src/m_alloc.h +++ b/src/m_alloc.h @@ -53,7 +53,4 @@ void *M_Realloc (void *memblock, size_t size); void M_Free (void *memblock); -// Number of bytes currently allocated through M_Malloc/M_Realloc -extern size_t AllocBytes; - #endif //__M_ALLOC_H__ diff --git a/src/m_argv.h b/src/m_argv.h index 65973de9e0..b0d44076ae 100644 --- a/src/m_argv.h +++ b/src/m_argv.h @@ -71,6 +71,6 @@ private: void CopyArgs (int argc, char **argv); }; -extern DArgs Args; +extern DArgs *Args; #endif //__M_ARGV_H__ diff --git a/src/m_bbox.cpp b/src/m_bbox.cpp index 42b54361ab..7be4e90c89 100644 --- a/src/m_bbox.cpp +++ b/src/m_bbox.cpp @@ -26,20 +26,18 @@ #include "m_bbox.h" -IMPLEMENT_CLASS (DBoundingBox) - -DBoundingBox::DBoundingBox () +FBoundingBox::FBoundingBox () { ClearBox (); } -void DBoundingBox::ClearBox () +void FBoundingBox::ClearBox () { m_Box[BOXTOP] = m_Box[BOXRIGHT] = FIXED_MIN; m_Box[BOXBOTTOM] = m_Box[BOXLEFT] = FIXED_MAX; } -void DBoundingBox::AddToBox (fixed_t x, fixed_t y) +void FBoundingBox::AddToBox (fixed_t x, fixed_t y) { if (x < m_Box[BOXLEFT]) m_Box[BOXLEFT] = x; diff --git a/src/m_bbox.h b/src/m_bbox.h index 0ef2853ae3..7a813ffa1f 100644 --- a/src/m_bbox.h +++ b/src/m_bbox.h @@ -23,7 +23,6 @@ #define __M_BBOX_H__ #include "doomtype.h" -#include "dobject.h" #include "m_fixed.h" @@ -37,11 +36,10 @@ enum }; // bbox coordinates -class DBoundingBox : public DObject +class FBoundingBox { - DECLARE_CLASS (DBoundingBox, DObject) public: - DBoundingBox(); + FBoundingBox(); void ClearBox (); void AddToBox (fixed_t x, fixed_t y); diff --git a/src/m_misc.cpp b/src/m_misc.cpp index 3909d32ede..7246fcdf8f 100644 --- a/src/m_misc.cpp +++ b/src/m_misc.cpp @@ -150,9 +150,9 @@ void M_FindResponseFile (void) { int i; - for (i = 1; i < Args.NumArgs(); i++) + for (i = 1; i < Args->NumArgs(); i++) { - if (Args.GetArg(i)[0] == '@') + if (Args->GetArg(i)[0] == '@') { char **argv; char *file; @@ -165,14 +165,14 @@ void M_FindResponseFile (void) int index; // READ THE RESPONSE FILE INTO MEMORY - handle = fopen (Args.GetArg(i) + 1,"rb"); + handle = fopen (Args->GetArg(i) + 1,"rb"); if (!handle) { // [RH] Make this a warning, not an error. - Printf ("No such response file (%s)!", Args.GetArg(i) + 1); + Printf ("No such response file (%s)!", Args->GetArg(i) + 1); continue; } - Printf ("Found response file %s!\n", Args.GetArg(i) + 1); + Printf ("Found response file %s!\n", Args->GetArg(i) + 1); fseek (handle, 0, SEEK_END); size = ftell (handle); fseek (handle, 0, SEEK_SET); @@ -182,7 +182,7 @@ void M_FindResponseFile (void) fclose (handle); argsize = ParseCommandLine (file, &argcinresp, NULL); - argc = argcinresp + Args.NumArgs() - 1; + argc = argcinresp + Args->NumArgs() - 1; if (argc != 0) { @@ -191,21 +191,21 @@ void M_FindResponseFile (void) ParseCommandLine (file, NULL, argv+i); for (index = 0; index < i; ++index) - argv[index] = Args.GetArg (index); + argv[index] = Args->GetArg (index); - for (index = i + 1, i += argcinresp; index < Args.NumArgs (); ++index) - argv[i++] = Args.GetArg (index); + for (index = i + 1, i += argcinresp; index < Args->NumArgs (); ++index) + argv[i++] = Args->GetArg (index); - DArgs newargs (i, argv); - Args = newargs; + Args->Destroy(); + Args = new DArgs(i, argv); } delete[] file; // DISPLAY ARGS - Printf ("%d command-line args:\n", Args.NumArgs ()); - for (k = 1; k < Args.NumArgs (); k++) - Printf ("%s\n", Args.GetArg (k)); + Printf ("%d command-line args:\n", Args->NumArgs ()); + for (k = 1; k < Args->NumArgs (); k++) + Printf ("%s\n", Args->GetArg (k)); break; } @@ -652,7 +652,7 @@ void M_ScreenShot (const char *filename) if (filename == NULL || filename[0] == '\0') { #ifndef unix - if (Args.CheckParm ("-cdrom")) + if (Args->CheckParm ("-cdrom")) { autoname = CDROM_DIR "\\"; } diff --git a/src/p_acs.cpp b/src/p_acs.cpp index 503fd7def0..37b56d57ff 100644 --- a/src/p_acs.cpp +++ b/src/p_acs.cpp @@ -106,7 +106,7 @@ struct CallReturn }; static DLevelScript *P_GetScriptGoing (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, - bool lineSide, int arg0, int arg1, int arg2, int always, bool delay); + bool lineSide, int arg0, int arg1, int arg2, int always); struct FBehavior::ArrayInfo { @@ -456,7 +456,7 @@ private: sector_t *Sector; fixed_t WatchD, LastD; int Special, Arg0, Arg1, Arg2, Arg3, Arg4; - AActor *Activator; + TObjPtr Activator; line_t *Line; bool LineSide; bool bCeiling; @@ -1530,7 +1530,7 @@ void FBehavior::StartTypedScripts (WORD type, AActor *activator, bool always, in if (ptr->Type == type) { DLevelScript *runningScript = P_GetScriptGoing (activator, NULL, ptr->Number, - ptr, this, 0, arg1, 0, 0, always, true); + ptr, this, 0, arg1, 0, 0, always); if (runNow) { runningScript->RunScript (); @@ -1557,7 +1557,10 @@ void FBehavior::StaticStopMyScripts (AActor *actor) //---- The ACS Interpreter ----// -IMPLEMENT_CLASS (DACSThinker) +IMPLEMENT_POINTY_CLASS (DACSThinker) + DECLARE_POINTER(LastScript) + DECLARE_POINTER(Scripts) +END_POINTERS DACSThinker *DACSThinker::ActiveThinker = NULL; @@ -1579,13 +1582,6 @@ DACSThinker::DACSThinker () DACSThinker::~DACSThinker () { - DLevelScript *script = Scripts; - while (script) - { - DLevelScript *next = script->next; - script->Destroy (); - script = next; - } Scripts = NULL; ActiveThinker = NULL; } @@ -1647,7 +1643,9 @@ void DACSThinker::StopScriptsFor (AActor *actor) } IMPLEMENT_POINTY_CLASS (DLevelScript) - DECLARE_POINTER (activator) + DECLARE_POINTER(next) + DECLARE_POINTER(prev) + DECLARE_POINTER(activator) END_POINTERS void DLevelScript::Serialize (FArchive &arc) @@ -1713,13 +1711,25 @@ void DLevelScript::Unlink () DACSThinker *controller = DACSThinker::ActiveThinker; if (controller->LastScript == this) + { controller->LastScript = prev; + GC::WriteBarrier(controller, prev); + } if (controller->Scripts == this) + { controller->Scripts = next; + GC::WriteBarrier(controller, next); + } if (prev) + { prev->next = next; + GC::WriteBarrier(prev, next); + } if (next) + { next->prev = prev; + GC::WriteBarrier(next, prev); + } } void DLevelScript::Link () @@ -1727,12 +1737,19 @@ void DLevelScript::Link () DACSThinker *controller = DACSThinker::ActiveThinker; next = controller->Scripts; + GC::WriteBarrier(this, next); if (controller->Scripts) + { controller->Scripts->prev = this; + GC::WriteBarrier(controller->Scripts, this); + } prev = NULL; controller->Scripts = this; + GC::WriteBarrier(controller, this); if (controller->LastScript == NULL) + { controller->LastScript = this; + } } void DLevelScript::PutLast () @@ -4852,9 +4869,9 @@ int DLevelScript::RunScript () } else { - if (activator->IsKindOf (RUNTIME_CLASS(AScriptedMarine))) + if (activator != NULL && activator->IsKindOf (RUNTIME_CLASS(AScriptedMarine))) { - static_cast(activator)->SetWeapon ( + barrier_cast(activator)->SetWeapon ( (AScriptedMarine::EMarineWeapon)STACK(1)); } } @@ -4879,9 +4896,9 @@ int DLevelScript::RunScript () } else { - if (activator->IsKindOf (RUNTIME_CLASS(AScriptedMarine))) + if (activator != NULL && activator->IsKindOf (RUNTIME_CLASS(AScriptedMarine))) { - static_cast(activator)->SetSprite (type); + barrier_cast(activator)->SetSprite (type); } } } @@ -5114,7 +5131,7 @@ int DLevelScript::RunScript () if (STACK(3) == 0) { - state = RUNTIME_TYPE(activator)->ActorInfo->FindState (statelist.Size(), &statelist[0], !!STACK(1)); + state = activator->GetClass()->ActorInfo->FindState (statelist.Size(), &statelist[0], !!STACK(1)); if (state != NULL) { activator->SetState (state); @@ -5133,7 +5150,7 @@ int DLevelScript::RunScript () while ( (actor = iterator.Next ()) ) { - state = RUNTIME_TYPE(actor)->ActorInfo->FindState (statelist.Size(), &statelist[0], !!STACK(1)); + state = actor->GetClass()->ActorInfo->FindState (statelist.Size(), &statelist[0], !!STACK(1)); if (state != NULL) { actor->SetState (state); @@ -5309,7 +5326,6 @@ int DLevelScript::RunScript () Unlink (); if (controller->RunningScripts[script] == this) controller->RunningScripts[script] = NULL; - this->Destroy (); } else { @@ -5326,7 +5342,7 @@ int DLevelScript::RunScript () #undef PushtoStack static DLevelScript *P_GetScriptGoing (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, - bool backSide, int arg0, int arg1, int arg2, int always, bool delay) + bool backSide, int arg0, int arg1, int arg2, int always) { DACSThinker *controller = DACSThinker::ActiveThinker; @@ -5340,11 +5356,11 @@ static DLevelScript *P_GetScriptGoing (AActor *who, line_t *where, int num, cons return NULL; } - return new DLevelScript (who, where, num, code, module, backSide, arg0, arg1, arg2, always, delay); + return new DLevelScript (who, where, num, code, module, backSide, arg0, arg1, arg2, always); } DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, - bool backside, int arg0, int arg1, int arg2, int always, bool delay) + bool backside, int arg0, int arg1, int arg2, int always) : activeBehavior (module) { if (DACSThinker::ActiveThinker == NULL) @@ -5363,17 +5379,12 @@ DLevelScript::DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr backSide = backside; activefont = SmallFont; hudwidth = hudheight = 0; - if (delay) - { - // From Hexen: Give the world some time to set itself up before running open scripts. - //script->state = SCRIPT_Delayed; - //script->statedata = TICRATE; - state = SCRIPT_Running; - } - else - { - state = SCRIPT_Running; - } + state = SCRIPT_Running; + // Hexen waited one second before executing any open scripts. I didn't realize + // this when I wrote my ACS implementation. Now that I know, it's still best to + // run them right away because there are several map properties that can't be + // set in an editor. If an open script sets them, it looks dumb if a second + // goes by while they're in their default state. if (!always) DACSThinker::ActiveThinker->RunningScripts[num] = this; @@ -5414,7 +5425,7 @@ void P_DoDeferedScripts () NULL, def->script, scriptdata, module, 0, def->arg0, def->arg1, def->arg2, - def->type == acsdefered_t::defexealways, true); + def->type == acsdefered_t::defexealways); } else { @@ -5487,7 +5498,7 @@ int P_StartScript (AActor *who, line_t *where, int script, char *map, bool backS } } DLevelScript *runningScript = P_GetScriptGoing (who, where, script, - scriptdata, module, backSide, arg0, arg1, arg2, always, false); + scriptdata, module, backSide, arg0, arg1, arg2, always); if (runningScript != NULL) { if (wantResultCode) diff --git a/src/p_acs.h b/src/p_acs.h index de0b0ea98b..9da001459c 100644 --- a/src/p_acs.h +++ b/src/p_acs.h @@ -638,7 +638,7 @@ public: DLevelScript (AActor *who, line_t *where, int num, const ScriptPtr *code, FBehavior *module, - bool backSide, int arg0, int arg1, int arg2, int always, bool delay); + bool backSide, int arg0, int arg1, int arg2, int always); ~DLevelScript (); void Serialize (FArchive &arc); @@ -655,7 +655,7 @@ protected: int *pc; EScriptState state; int statedata; - AActor *activator; + TObjPtr activator; line_t *activationline; bool backSide; FFont *activefont; @@ -701,6 +701,7 @@ inline FArchive &operator<< (FArchive &arc, DLevelScript::EScriptState &state) class DACSThinker : public DThinker { DECLARE_CLASS (DACSThinker, DThinker) + HAS_OBJECT_POINTERS public: DACSThinker (); ~DACSThinker (); diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 2fce22ba69..c4b7d48680 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -69,7 +69,7 @@ void DDoor::Tick () if (m_Sector->floorplane.d != m_OldFloorDist) { if (!m_Sector->floordata || !m_Sector->floordata->IsKindOf(RUNTIME_CLASS(DPlat)) || - !((DPlat*)m_Sector->floordata)->IsLift()) + !(barrier_cast(m_Sector->floordata))->IsLift()) { m_OldFloorDist = m_Sector->floorplane.d; m_BotDist = m_Sector->ceilingplane.PointToDist (m_BotSpot, @@ -340,7 +340,7 @@ DDoor::DDoor (sector_t *sec, EVlDoor type, fixed_t speed, int delay, int lightTa } if (!m_Sector->floordata || !m_Sector->floordata->IsKindOf(RUNTIME_CLASS(DPlat)) || - !((DPlat*)m_Sector->floordata)->IsLift()) + !(barrier_cast(m_Sector->floordata))->IsLift()) { height = sec->FindHighestFloorPoint (&m_BotSpot); m_BotDist = sec->ceilingplane.PointToDist (m_BotSpot, height); @@ -384,7 +384,7 @@ bool EV_DoDoor (DDoor::EVlDoor type, line_t *line, AActor *thing, { if (sec->ceilingdata->IsKindOf (RUNTIME_CLASS(DDoor))) { - DDoor *door = static_cast(sec->ceilingdata); + DDoor *door = barrier_cast(sec->ceilingdata); // ONLY FOR "RAISE" DOORS, NOT "OPEN"s if (door->m_Type == DDoor::doorRaise && type == DDoor::doorRaise) @@ -761,7 +761,7 @@ bool EV_SlidingDoor (line_t *line, AActor *actor, int tag, int speed, int delay) if (sec->ceilingdata->IsA (RUNTIME_CLASS(DAnimatedDoor))) { - DAnimatedDoor *door = static_cast (sec->ceilingdata); + DAnimatedDoor *door = barrier_cast(sec->ceilingdata); if (door->m_Status == DAnimatedDoor::Waiting) { return door->StartClosing(); diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 214c4463c5..ce509b4ae5 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1133,22 +1133,22 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround) actor->reactiontime = 0; actor->target = other; - actor->LastLook.Actor = other; + actor->LastLookActor = other; return true; } // The actor's TID could change because of death or because of // Thing_ChangeTID. If it's not what we expect, then don't use // it as a base for the iterator. - if (actor->LastLook.Actor != NULL && - actor->LastLook.Actor->tid != actor->TIDtoHate) + if (actor->LastLookActor != NULL && + actor->LastLookActor->tid != actor->TIDtoHate) { - actor->LastLook.Actor = NULL; + actor->LastLookActor = NULL; } - FActorIterator iterator (actor->TIDtoHate, actor->LastLook.Actor); + FActorIterator iterator (actor->TIDtoHate, actor->LastLookActor); int c = (pr_look3() & 31) + 7; // Look for between 7 and 38 hatees at a time - while ((other = iterator.Next()) != actor->LastLook.Actor) + while ((other = iterator.Next()) != actor->LastLookActor) { if (other == NULL) { @@ -1206,10 +1206,10 @@ bool P_LookForTID (AActor *actor, INTBOOL allaround) actor->reactiontime = 0; actor->target = other; - actor->LastLook.Actor = other; + actor->LastLookActor = other; return true; } - actor->LastLook.Actor = other; + actor->LastLookActor = other; if (actor->target == NULL) { // [RH] use goal as target @@ -1436,7 +1436,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround) } else { - pnum = actor->LastLook.PlayerNumber; + pnum = actor->LastLookPlayerNumber; } stop = (pnum - 1) & (MAXPLAYERS-1); @@ -1448,7 +1448,7 @@ bool P_LookForPlayers (AActor *actor, INTBOOL allaround) if (actor->TIDtoHate == 0) { - actor->LastLook.PlayerNumber = pnum; + actor->LastLookPlayerNumber = pnum; } if (++c == MAXPLAYERS-1 || pnum == stop) diff --git a/src/p_enemy_a_lookex.cpp b/src/p_enemy_a_lookex.cpp index ff679c774c..3a5e4b6a57 100644 --- a/src/p_enemy_a_lookex.cpp +++ b/src/p_enemy_a_lookex.cpp @@ -346,22 +346,22 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, actor->reactiontime = 0; actor->target = other; - actor->LastLook.Actor = other; + actor->LastLookActor = other; return true; } // The actor's TID could change because of death or because of // Thing_ChangeTID. If it's not what we expect, then don't use // it as a base for the iterator. - if (actor->LastLook.Actor != NULL && - actor->LastLook.Actor->tid != actor->TIDtoHate) + if (actor->LastLookActor != NULL && + actor->LastLookActor->tid != actor->TIDtoHate) { - actor->LastLook.Actor = NULL; + actor->LastLookActor = NULL; } - FActorIterator iterator (actor->TIDtoHate, actor->LastLook.Actor); + FActorIterator iterator (actor->TIDtoHate, actor->LastLookActor); int c = (pr_look3() & 31) + 7; // Look for between 7 and 38 hatees at a time - while ((other = iterator.Next()) != actor->LastLook.Actor) + while ((other = iterator.Next()) != actor->LastLookActor) { if (other == NULL) { @@ -448,10 +448,10 @@ bool P_NewLookTID (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxdist, actor->reactiontime = 0; actor->target = other; - actor->LastLook.Actor = other; + actor->LastLookActor = other; return true; } - actor->LastLook.Actor = other; + actor->LastLookActor = other; if (actor->target == NULL) { // [RH] use goal as target @@ -562,7 +562,7 @@ bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxd } else { - pnum = actor->LastLook.PlayerNumber; + pnum = actor->LastLookPlayerNumber; } stop = (pnum - 1) & (MAXPLAYERS-1); @@ -574,7 +574,7 @@ bool P_NewLookPlayers (AActor *actor, angle_t fov, fixed_t mindist, fixed_t maxd if (actor->TIDtoHate == 0) { - actor->LastLook.PlayerNumber = pnum; + actor->LastLookPlayerNumber = pnum; } if (++c == MAXPLAYERS-1 || pnum == stop) diff --git a/src/p_floor.cpp b/src/p_floor.cpp index 33d1d22185..469cfab61d 100644 --- a/src/p_floor.cpp +++ b/src/p_floor.cpp @@ -600,7 +600,7 @@ bool EV_FloorCrushStop (int tag) sector_t *sec = sectors + secnum; if (sec->floordata && sec->floordata->IsKindOf (RUNTIME_CLASS(DFloor)) && - static_cast(sec->floordata)->m_Type == DFloor::floorRaiseAndCrush) + barrier_cast(sec->floordata)->m_Type == DFloor::floorRaiseAndCrush) { SN_StopSequence (sec); sec->floordata->Destroy (); diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index 36b4e20c7c..555b542a17 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -932,7 +932,7 @@ FUNC(LS_Thing_ChangeTID) { if (arg0 == 0) { - if (it != NULL && !(it->ObjectFlags & OF_MassDestruction)) + if (it != NULL && !(it->ObjectFlags & OF_EuthanizeMe)) { it->RemoveFromHash (); it->tid = arg1; @@ -950,7 +950,7 @@ FUNC(LS_Thing_ChangeTID) actor = next; next = iterator.Next (); - if (!(actor->ObjectFlags & OF_MassDestruction)) + if (!(actor->ObjectFlags & OF_EuthanizeMe)) { actor->RemoveFromHash (); actor->tid = arg1; @@ -1227,7 +1227,7 @@ FUNC(LS_Thing_Hate) if (arg2 != 0) { hater->TIDtoHate = arg1; - hater->LastLook.Actor = NULL; + hater->LastLookActor = NULL; // If the TID to hate is 0, then don't forget the target and // lastenemy fields. diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 1dbdfc93d5..c4a9f8694f 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -167,7 +167,7 @@ IMPLEMENT_POINTY_CLASS (AActor) DECLARE_POINTER (lastenemy) DECLARE_POINTER (tracer) DECLARE_POINTER (goal) - DECLARE_POINTER (LastLook) // This is actually a union + DECLARE_POINTER (LastLookActor) DECLARE_POINTER (Inventory) DECLARE_POINTER (LastHeard) DECLARE_POINTER (master) @@ -236,11 +236,13 @@ void AActor::Serialize (FArchive &arc) arc << TIDtoHate; if (TIDtoHate == 0) { - arc << LastLook.PlayerNumber; + arc << LastLookPlayerNumber; + LastLookActor = NULL; } else { - arc << LastLook.Actor; + arc << LastLookActor; + LastLookPlayerNumber = -1; } arc << effects << alpha @@ -563,7 +565,8 @@ bool AActor::SetState (FState *newstate) newstate->GetAction() (this); // Check whether the called action function resulted in destroying the actor - if (ObjectFlags & OF_MassDestruction) return false; + if (ObjectFlags & OF_EuthanizeMe) + return false; } newstate = newstate->GetNextState(); } while (tics == 0); @@ -708,7 +711,7 @@ void AActor::DestroyAllInventory () // //============================================================================ -AInventory *AActor::FirstInv () const +AInventory *AActor::FirstInv () { if (Inventory == NULL) { @@ -797,7 +800,7 @@ AInventory *AActor::DropInventory (AInventory *item) // //============================================================================ -AInventory *AActor::FindInventory (const PClass *type) const +AInventory *AActor::FindInventory (const PClass *type) { AInventory *item; @@ -814,7 +817,7 @@ AInventory *AActor::FindInventory (const PClass *type) const return item; } -AInventory *AActor::FindInventory (FName type) const +AInventory *AActor::FindInventory (FName type) { return FindInventory(PClass::FindClass(type)); } @@ -874,11 +877,12 @@ bool AActor::GiveAmmo (const PClass *type, int amount) // //============================================================================ -void AActor::CopyFriendliness (const AActor *other, bool changeTarget) +void AActor::CopyFriendliness (AActor *other, bool changeTarget) { level.total_monsters -= CountsAsKill(); TIDtoHate = other->TIDtoHate; - LastLook = other->LastLook; + LastLookActor = other->LastLookActor; + LastLookPlayerNumber = other->LastLookPlayerNumber; flags = (flags & ~MF_FRIENDLY) | (other->flags & MF_FRIENDLY); flags3 = (flags3 & ~(MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS)) | (other->flags3 & (MF3_NOSIGHTCHECK | MF3_HUNTPLAYERS)); flags4 = (flags4 & ~MF4_NOHATEPLAYERS) | (other->flags4 & MF4_NOHATEPLAYERS); @@ -1052,7 +1056,7 @@ void P_ExplodeMissile (AActor *mo, line_t *line, AActor *target) if (nextstate == NULL) nextstate = mo->FindState(NAME_Death); mo->SetState (nextstate); - if (mo->ObjectFlags & OF_MassDestruction) + if (mo->ObjectFlags & OF_EuthanizeMe) { return; } @@ -2865,7 +2869,7 @@ void AActor::Tick () // Handle X and Y momemtums BlockingMobj = NULL; P_XYMovement (this, cummx, cummy); - if (ObjectFlags & OF_MassDestruction) + if (ObjectFlags & OF_EuthanizeMe) { // actor was destroyed return; } @@ -2923,7 +2927,7 @@ void AActor::Tick () P_ZMovement (this); } - if (ObjectFlags & OF_MassDestruction) + if (ObjectFlags & OF_EuthanizeMe) return; // actor was destroyed } else if (z <= floorz) @@ -3163,7 +3167,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t if (actor->flags3 & MF3_ISMONSTER) { - actor->LastLook.PlayerNumber = rng() % MAXPLAYERS; + actor->LastLookPlayerNumber = rng() % MAXPLAYERS; actor->TIDtoHate = 0; } @@ -3251,7 +3255,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t if (!SpawningMapThing) { actor->BeginPlay (); - if (actor->ObjectFlags & OF_MassDestruction) + if (actor->ObjectFlags & OF_EuthanizeMe) { return NULL; } @@ -3990,7 +3994,7 @@ void P_SpawnMapThing (mapthing2_t *mthing, int position) mobj->angle = (DWORD)((mthing->angle * UCONST64(0x100000000)) / 360); mobj->BeginPlay (); - if (mobj->ObjectFlags & OF_MassDestruction) + if (mobj->ObjectFlags & OF_EuthanizeMe) { return; } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 2977542c76..15204b6cea 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -2689,7 +2689,7 @@ void P_LoadBlockMap (MapData * map) if (ForceNodeBuild || genblockmap || count/2 >= 0x10000 || count == 0 || - Args.CheckParm("-blockmap") + Args->CheckParm("-blockmap") ) { DPrintf ("Generating BLOCKMAP\n"); @@ -2757,7 +2757,7 @@ static void P_GroupLines (bool buildmap) int totallights; line_t* li; sector_t* sector; - DBoundingBox bbox; + FBoundingBox bbox; bool flaggedNoFronts = false; unsigned int ii, jj; @@ -3765,7 +3765,7 @@ static void P_Shutdown () P_FreeExtraLevelData (); if (StatusBar != NULL) { - delete StatusBar; + StatusBar->Destroy(); StatusBar = NULL; } } diff --git a/src/p_spec.h b/src/p_spec.h index 9bc860ff13..72aea8a95d 100644 --- a/src/p_spec.h +++ b/src/p_spec.h @@ -128,7 +128,7 @@ public: protected: EPusher m_Type; - AActor *m_Source; // Point source if point pusher + TObjPtr m_Source;// Point source if point pusher int m_Xmag; // X Strength int m_Ymag; // Y Strength int m_Magnitude; // Vector strength for point pusher diff --git a/src/p_user.cpp b/src/p_user.cpp index 4265e9ca55..4d2dccac43 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -316,6 +316,26 @@ void player_s::FixPointers (const DObject *old, DObject *rep) if (PendingWeapon == old) PendingWeapon = static_cast(rep); } +size_t player_s::PropagateMark() +{ + GC::Mark(mo); + GC::Mark(poisoner); + GC::Mark(attacker); + GC::Mark(camera); + GC::Mark(dest); + GC::Mark(prev); + GC::Mark(enemy); + GC::Mark(missile); + GC::Mark(mate); + GC::Mark(last_mate); + GC::Mark(ReadyWeapon); + if (PendingWeapon != WP_NOCHANGE) + { + GC::Mark(PendingWeapon); + } + return sizeof(*this); +} + void player_s::SetLogNumber (int num) { char lumpname[16]; diff --git a/src/r_defs.h b/src/r_defs.h index ad58b39e53..1e34ba9c6d 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -306,7 +306,7 @@ struct sector_t int floorpic, ceilingpic; BYTE lightlevel; - AActor * SoundTarget; + TObjPtr SoundTarget; BYTE soundtraversed; // 0 = untraversed, 1,2 = sndlines -1 short special; @@ -326,9 +326,9 @@ struct sector_t fixed_t friction, movefactor; // thinker_t for reversable actions - DSectorEffect *floordata; // jff 2/22/98 make thinkers on - DSectorEffect *ceilingdata; // floors, ceilings, lighting, - DSectorEffect *lightingdata; // independent of one another + TObjPtr floordata; // jff 2/22/98 make thinkers on + TObjPtr ceilingdata; // floors, ceilings, lighting, + TObjPtr lightingdata; // independent of one another // jff 2/26/98 lockout machinery for stairbuilding SBYTE stairlock; // -2 on first locked -1 after thinker done 0 normally @@ -360,11 +360,11 @@ struct sector_t // flexible in a Bloody way. SecActTarget forms a list of actors // joined by their tracer fields. When a potential sector action // occurs, SecActTarget's TriggerAction method is called. - ASectorAction *SecActTarget; + TObjPtr SecActTarget; // [RH] The sky box to render for this sector. NULL means use a // regular sky. - ASkyViewpoint *FloorSkyBox, *CeilingSkyBox; + TObjPtr FloorSkyBox, CeilingSkyBox; // Planes that partition this sector into different light zones. FExtraLight *ExtraLights; diff --git a/src/r_things.cpp b/src/r_things.cpp index b39ecde2e8..b3a85b089c 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -2226,7 +2226,7 @@ void R_InitParticles () { char *i; - if ((i = Args.CheckValue ("-numparticles"))) + if ((i = Args->CheckValue ("-numparticles"))) NumParticles = atoi (i); // [BC] Use r_maxparticles now. else diff --git a/src/s_sndseq.cpp b/src/s_sndseq.cpp index 8a1c8e60e8..412abba627 100644 --- a/src/s_sndseq.cpp +++ b/src/s_sndseq.cpp @@ -100,7 +100,7 @@ class DSeqActorNode : public DSeqNode HAS_OBJECT_POINTERS public: DSeqActorNode (AActor *actor, int sequence, int modenum); - ~DSeqActorNode (); + void Destroy (); void Serialize (FArchive &arc); void MakeSound () { S_SoundID (m_Actor, CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } void MakeLoopedSound () { S_LoopedSoundID (m_Actor, CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } @@ -109,7 +109,7 @@ public: DSeqNode *SpawnChild (int seqnum) { return SN_StartSequence (m_Actor, seqnum, SEQ_NOTRANS, m_ModeNum, true); } private: DSeqActorNode () {} - AActor *m_Actor; + TObjPtr m_Actor; }; class DSeqPolyNode : public DSeqNode @@ -117,7 +117,7 @@ class DSeqPolyNode : public DSeqNode DECLARE_CLASS (DSeqPolyNode, DSeqNode) public: DSeqPolyNode (polyobj_t *poly, int sequence, int modenum); - ~DSeqPolyNode (); + void Destroy (); void Serialize (FArchive &arc); void MakeSound () { S_SoundID (&m_Poly->startSpot[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } void MakeLoopedSound () { S_LoopedSoundID (&m_Poly->startSpot[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); } @@ -134,7 +134,7 @@ class DSeqSectorNode : public DSeqNode DECLARE_CLASS (DSeqSectorNode, DSeqNode) public: DSeqSectorNode (sector_t *sec, int sequence, int modenum); - ~DSeqSectorNode (); + void Destroy (); void Serialize (FArchive &arc); void MakeSound () { S_SoundID (&m_Sector->soundorg[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); Looping = false; } void MakeLoopedSound () { S_LoopedSoundID (&m_Sector->soundorg[0], CHAN_BODY, m_CurrentSoundID, clamp(m_Volume, 0.f, 1.f), m_Atten); Looping = true; } @@ -242,7 +242,12 @@ void DSeqNode::SerializeSequences (FArchive &arc) arc << SequenceListHead; } -IMPLEMENT_CLASS (DSeqNode) +IMPLEMENT_POINTY_CLASS (DSeqNode) + DECLARE_POINTER(m_ChildSeqNode) + DECLARE_POINTER(m_ParentSeqNode) + DECLARE_POINTER(m_Next) + DECLARE_POINTER(m_Prev) +END_POINTERS DSeqNode::DSeqNode () : m_SequenceChoices(0) @@ -331,6 +336,19 @@ void DSeqNode::Destroy() m_ParentSeqNode->m_ChildSeqNode = NULL; m_ParentSeqNode = NULL; } + if (SequenceListHead == this) + SequenceListHead = m_Next; + if (m_Prev) + { + m_Prev->m_Next = m_Next; + GC::WriteBarrier(m_Prev, m_Next); + } + if (m_Next) + { + m_Next->m_Prev = m_Prev; + GC::WriteBarrier(m_Next, m_Prev); + } + ActiveSequences--; Super::Destroy(); } @@ -676,17 +694,6 @@ static void AddSequence (int curseq, FName seqname, FName slot, int stopsound, c Sequences[curseq]->Script[ScriptTemp.Size()] = MakeCommand(SS_CMD_END, 0); } -DSeqNode::~DSeqNode () -{ - if (SequenceListHead == this) - SequenceListHead = m_Next; - if (m_Prev) - m_Prev->m_Next = m_Next; - if (m_Next) - m_Next->m_Prev = m_Prev; - ActiveSequences--; -} - DSeqNode::DSeqNode (int sequence, int modenum) : m_ModeNum(modenum), m_SequenceChoices(0) { @@ -912,28 +919,31 @@ void SN_DoStop (void *source) } } -DSeqActorNode::~DSeqActorNode () +void DSeqActorNode::Destroy () { if (m_StopSound >= 0) S_StopSound (m_Actor, CHAN_BODY); if (m_StopSound >= 1) S_SoundID (m_Actor, CHAN_BODY, m_StopSound, m_Volume, m_Atten); + Super::Destroy(); } -DSeqSectorNode::~DSeqSectorNode () +void DSeqSectorNode::Destroy () { if (m_StopSound >= 0) S_StopSound (m_Sector->soundorg, CHAN_BODY); if (m_StopSound >= 1) S_SoundID (m_Sector->soundorg, CHAN_BODY, m_StopSound, m_Volume, m_Atten); + Super::Destroy(); } -DSeqPolyNode::~DSeqPolyNode () +void DSeqPolyNode::Destroy () { if (m_StopSound >= 0) S_StopSound (m_Poly->startSpot, CHAN_BODY); if (m_StopSound >= 1) S_SoundID (m_Poly->startSpot, CHAN_BODY, m_StopSound, m_Volume, m_Atten); + Super::Destroy(); } //========================================================================== @@ -1026,6 +1036,7 @@ void DSeqNode::Tick () { int choice = pr_sndseq() % m_SequenceChoices.Size(); m_ChildSeqNode = SpawnChild (m_SequenceChoices[choice]); + GC::WriteBarrier(this, m_ChildSeqNode); if (m_ChildSeqNode == NULL) { // Failed, so skip to next instruction. m_SequencePtr++; diff --git a/src/s_sndseq.h b/src/s_sndseq.h index e8cb442232..46ca46425a 100644 --- a/src/s_sndseq.h +++ b/src/s_sndseq.h @@ -20,8 +20,8 @@ struct sector_t; class DSeqNode : public DObject { DECLARE_CLASS (DSeqNode, DObject) + HAS_OBJECT_POINTERS public: - virtual ~DSeqNode (); void Serialize (FArchive &arc); void StopAndDestroy (); void Destroy (); @@ -56,8 +56,8 @@ protected: int m_ModeNum; TArray m_SequenceChoices; - DSeqNode *m_ChildSeqNode; - DSeqNode *m_ParentSeqNode; + TObjPtr m_ChildSeqNode; + TObjPtr m_ParentSeqNode; private: static DSeqNode *SequenceListHead; diff --git a/src/sdl/hardware.cpp b/src/sdl/hardware.cpp index 4d599e69b0..cce3af1495 100644 --- a/src/sdl/hardware.cpp +++ b/src/sdl/hardware.cpp @@ -52,7 +52,11 @@ IVideo *Video; void I_ShutdownGraphics () { if (screen) - delete screen, screen = NULL; + { + screen->ObjectFlags |= OF_YesReallyDelete; + delete screen; + screen = NULL; + } if (Video) delete Video, Video = NULL; } @@ -61,7 +65,7 @@ void I_InitGraphics () { UCVarValue val; - val.Bool = !!Args.CheckParm ("-devparm"); + val.Bool = !!Args->CheckParm ("-devparm"); ticker.SetGenericRepDefault (val, CVAR_Bool); Video = new SDLVideo (0); diff --git a/src/sdl/i_main.cpp b/src/sdl/i_main.cpp index 4d7ac911d6..e208bae0b9 100644 --- a/src/sdl/i_main.cpp +++ b/src/sdl/i_main.cpp @@ -75,7 +75,7 @@ extern "C" int cc_install_handlers(int, int*, const char*, int(*)(char*, char*)) bool GtkAvailable; // The command line arguments. -DArgs Args; +DArgs *Args; // PRIVATE DATA DEFINITIONS ------------------------------------------------ @@ -137,9 +137,9 @@ static int DoomSpecificInfo (char *buffer, char *end) p = 0; p += snprintf (buffer+p, size-p, GAMENAME" version " DOTVERSIONSTR " (" __DATE__ ")\n"); p += snprintf (buffer+p, size-p, "\nCommand line:"); - for (i = 0; i < Args.NumArgs(); ++i) + for (i = 0; i < Args->NumArgs(); ++i) { - p += snprintf (buffer+p, size-p, " %s", Args.GetArg(i)); + p += snprintf (buffer+p, size-p, " %s", Args->GetArg(i)); } p += snprintf (buffer+p, size-p, "\n"); @@ -208,7 +208,7 @@ int main (int argc, char **argv) try { - Args.SetArgs (argc, argv); + Args = new DArgs(argc, argv); /* killough 1/98: diff --git a/src/sound/i_music.cpp b/src/sound/i_music.cpp index 6a295e3407..ea13abca84 100644 --- a/src/sound/i_music.cpp +++ b/src/sound/i_music.cpp @@ -136,7 +136,7 @@ void I_InitMusic (void) snd_musicvolume.Callback (); - nomusic = !!Args.CheckParm("-nomusic") || !!Args.CheckParm("-nosound"); + nomusic = !!Args->CheckParm("-nomusic") || !!Args->CheckParm("-nosound"); #ifdef _WIN32 I_InitMusicWin32 (); diff --git a/src/sound/i_sound.cpp b/src/sound/i_sound.cpp index 4cf4a4956b..6e836a1bc9 100644 --- a/src/sound/i_sound.cpp +++ b/src/sound/i_sound.cpp @@ -151,7 +151,7 @@ CUSTOM_CVAR (Float, snd_sfxvolume, 0.5f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG|CVAR_NOI void I_InitSound () { /* Get command line options: */ - bool nosound = !!Args.CheckParm ("-nosfx") || !!Args.CheckParm ("-nosound"); + bool nosound = !!Args->CheckParm ("-nosfx") || !!Args->CheckParm ("-nosound"); if (nosound) { diff --git a/src/stats.cpp b/src/stats.cpp index fe75484b7f..07a0277295 100644 --- a/src/stats.cpp +++ b/src/stats.cpp @@ -40,6 +40,7 @@ #include "st_stuff.h" #include "c_dispatch.h" #include "m_swap.h" +#include "sbar.h" FStat *FStat::FirstStat; @@ -84,7 +85,7 @@ void FStat::ToggleStat (const char *name) void FStat::ToggleStat () { m_Active = !m_Active; - SB_state = screen->GetPageCount (); + SB_state = StatusBar == NULL ? 0 : screen->GetPageCount (); } void FStat::PrintStat () diff --git a/src/v_video.cpp b/src/v_video.cpp index 00d40c1d31..cec1edbad1 100644 --- a/src/v_video.cpp +++ b/src/v_video.cpp @@ -357,7 +357,7 @@ void DCanvas::Dim (PalEntry color) if (color.a != 0) { float dim[4] = { color.r/255.f, color.g/255.f, color.b/255.f, color.a/255.f }; - FBaseStatusBar::AddBlend (dimmer.r/255.f, dimmer.g/255.f, dimmer.b/255.f, amount, dim); + DBaseStatusBar::AddBlend (dimmer.r/255.f, dimmer.g/255.f, dimmer.b/255.f, amount, dim); dimmer = PalEntry (BYTE(dim[0]*255), BYTE(dim[1]*255), BYTE(dim[2]*255)); amount = dim[3]; } @@ -1390,6 +1390,7 @@ void DFrameBuffer::WriteSavePic (player_t *player, FILE *file, int width, int he GetFlashedPalette (palette); M_CreatePNG (file, pic->GetBuffer(), palette, SS_PAL, width, height, pic->GetPitch()); pic->Unlock (); + pic->ObjectFlags |= OF_YesReallyDelete; delete pic; } @@ -1426,6 +1427,7 @@ bool V_DoModeSetup (int width, int height, int bits) } screen = buff; + GC::WriteBarrier(screen); screen->SetFont (SmallFont); screen->SetGamma (Gamma); @@ -1594,13 +1596,13 @@ void V_Init (void) width = height = bits = 0; - if ( (i = Args.CheckValue ("-width")) ) + if ( (i = Args->CheckValue ("-width")) ) width = atoi (i); - if ( (i = Args.CheckValue ("-height")) ) + if ( (i = Args->CheckValue ("-height")) ) height = atoi (i); - if ( (i = Args.CheckValue ("-bits")) ) + if ( (i = Args->CheckValue ("-bits")) ) bits = atoi (i); if (width == 0) @@ -1638,6 +1640,7 @@ void V_Init2() float gamma = static_cast(screen)->Gamma; FFont *font = screen->Font; + screen->ObjectFlags |= OF_YesReallyDelete; delete screen; screen = NULL; diff --git a/src/w_wad.cpp b/src/w_wad.cpp index 4f431ef4ec..b2673a86b0 100644 --- a/src/w_wad.cpp +++ b/src/w_wad.cpp @@ -1148,7 +1148,7 @@ bool FWadCollection::IsMarker (const FWadCollection::LumpRecord *lump, const cha void FWadCollection::ScanForFlatHack (int startlump) { - if (Args.CheckParm ("-noflathack")) + if (Args->CheckParm ("-noflathack")) { return; } @@ -1348,7 +1348,7 @@ void FWadCollection::RenameSprites (int startlump) break; } - renameAll = !!Args.CheckParm ("-oldsprites"); + renameAll = !!Args->CheckParm ("-oldsprites"); for (DWORD i = startlump + 1; i < NumLumps && diff --git a/src/win32/hardware.cpp b/src/win32/hardware.cpp index ff67fd3c3f..211cdafbf6 100644 --- a/src/win32/hardware.cpp +++ b/src/win32/hardware.cpp @@ -61,7 +61,11 @@ IVideo *Video; void I_ShutdownGraphics () { if (screen) - delete screen, screen = NULL; + { + screen->ObjectFlags |= OF_YesReallyDelete; + delete screen; + screen = NULL; + } if (Video) delete Video, Video = NULL; } @@ -86,7 +90,7 @@ void I_InitGraphics () // are the active app. Huh? } - val.Bool = !!Args.CheckParm ("-devparm"); + val.Bool = !!Args->CheckParm ("-devparm"); ticker.SetGenericRepDefault (val, CVAR_Bool); Video = new Win32Video (0); if (Video == NULL) @@ -227,7 +231,7 @@ static void KeepWindowOnScreen (int &winx, int &winy, int winw, int winh, int sc void I_SaveWindowedPos () { // Don't save if we were run with the -0 option. - if (Args.CheckParm ("-0")) + if (Args->CheckParm ("-0")) { return; } @@ -268,7 +272,7 @@ void I_RestoreWindowedPos () GetCenteredPos (winx, winy, winw, winh, scrwidth, scrheight); // Just move to (0,0) if we were run with the -0 option. - if (Args.CheckParm ("-0")) + if (Args->CheckParm ("-0")) { winx = winy = 0; } diff --git a/src/win32/i_cd.cpp b/src/win32/i_cd.cpp index 3de373cca7..c1d5328be5 100644 --- a/src/win32/i_cd.cpp +++ b/src/win32/i_cd.cpp @@ -473,7 +473,7 @@ bool CD_Init () bool CD_Init (int device) { - if (!cd_enabled || Args.CheckParm ("-nocdaudio")) + if (!cd_enabled || Args->CheckParm ("-nocdaudio")) return false; if (CDThread == NULL) diff --git a/src/win32/i_input.cpp b/src/win32/i_input.cpp index c8bc89eb5e..750dc00e59 100644 --- a/src/win32/i_input.cpp +++ b/src/win32/i_input.cpp @@ -1105,7 +1105,7 @@ void DI_EnumJoy () JoyActive = 0; JoystickNames.Clear (); - if (g_pdi != NULL && !Args.CheckParm ("-nojoy")) + if (g_pdi != NULL && !Args->CheckParm ("-nojoy")) { g_pdi->EnumDevices (DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, NULL, DIEDFL_ALLDEVICES); } @@ -1403,7 +1403,7 @@ bool I_InitInput (void *hwnd) NativeMouse = -1; GetCursorPos (&UngrabbedPointerPos); - noidle = !!Args.CheckParm ("-noidle"); + noidle = !!Args->CheckParm ("-noidle"); g_pdi = NULL; g_pdi3 = NULL; diff --git a/src/win32/i_main.cpp b/src/win32/i_main.cpp index 60de2bbd08..f29ab2c151 100644 --- a/src/win32/i_main.cpp +++ b/src/win32/i_main.cpp @@ -111,7 +111,7 @@ extern HCURSOR TheArrowCursor, TheInvisibleCursor; // PUBLIC DATA DEFINITIONS ------------------------------------------------- // The command line arguments. -DArgs Args; +DArgs *Args; HINSTANCE g_hInst; DWORD SessionID; @@ -776,7 +776,7 @@ void DoMain (HINSTANCE hInstance) _set_new_handler (NewFailure); #endif - Args.SetArgs (__argc, __argv); + Args = new DArgs(__argc, __argv); // Under XP, get our session ID so we can know when the user changes/locks sessions. // Since we need to remain binary compatible with older versions of Windows, we @@ -827,7 +827,7 @@ void DoMain (HINSTANCE hInstance) x = (displaysettings.dmPelsWidth - width) / 2; y = (displaysettings.dmPelsHeight - height) / 2; - if (Args.CheckParm ("-0")) + if (Args->CheckParm ("-0")) { x = y = 0; } diff --git a/src/win32/i_system.cpp b/src/win32/i_system.cpp index 197f3903e6..2e8b333dd7 100644 --- a/src/win32/i_system.cpp +++ b/src/win32/i_system.cpp @@ -404,7 +404,7 @@ void I_Init (void) UINT delay; char *cmdDelay; - cmdDelay = Args.CheckValue ("-timerdelay"); + cmdDelay = Args->CheckValue ("-timerdelay"); delay = 0; if (cmdDelay != 0) { diff --git a/src/win32/win32video.cpp b/src/win32/win32video.cpp index 23ab38524b..800f512f06 100644 --- a/src/win32/win32video.cpp +++ b/src/win32/win32video.cpp @@ -504,6 +504,7 @@ DFrameBuffer *Win32Video::CreateFrameBuffer (int width, int height, bool fullscr return old; } old->GetFlash (flashColor, flashAmount); + old->ObjectFlags |= OF_YesReallyDelete; delete old; } else diff --git a/zdoom.vcproj b/zdoom.vcproj index 5f4030fbd7..8b4276e101 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -167,7 +167,6 @@ /> @@ -513,7 +507,6 @@ > @@ -549,7 +542,7 @@ > @@ -585,7 +578,7 @@ > @@ -621,7 +614,7 @@ > @@ -657,7 +650,7 @@ > @@ -693,7 +686,7 @@ > @@ -729,7 +722,7 @@ > @@ -765,7 +758,7 @@ > @@ -801,7 +794,7 @@ > @@ -837,7 +830,7 @@ > @@ -873,7 +866,7 @@ > @@ -909,7 +902,7 @@ > @@ -945,7 +938,7 @@ > @@ -981,7 +974,7 @@ > @@ -1017,7 +1010,7 @@ > @@ -1053,7 +1046,7 @@ > @@ -1089,7 +1082,7 @@ > @@ -1125,7 +1118,7 @@ > @@ -1161,7 +1154,7 @@ > @@ -1197,7 +1190,7 @@ > @@ -1233,7 +1226,7 @@ > @@ -1269,7 +1262,7 @@ > @@ -1305,7 +1298,7 @@ > @@ -1341,7 +1334,7 @@ > @@ -1377,7 +1370,7 @@ > + + @@ -1417,7 +1414,7 @@ > @@ -1453,7 +1450,7 @@ > @@ -1489,7 +1486,7 @@ > @@ -1525,7 +1522,7 @@ > @@ -1561,7 +1558,7 @@ > @@ -1597,7 +1594,7 @@ > @@ -1633,7 +1630,7 @@ > @@ -1673,7 +1670,7 @@ > @@ -1713,7 +1710,7 @@ > @@ -1749,7 +1746,7 @@ > @@ -1785,7 +1782,7 @@ > @@ -1821,7 +1818,7 @@ > @@ -1861,7 +1858,7 @@ > @@ -1897,7 +1894,7 @@ > @@ -1933,7 +1930,7 @@ > @@ -1969,7 +1966,7 @@ > @@ -2005,7 +2002,7 @@ > @@ -2041,7 +2038,7 @@ > @@ -2077,7 +2074,7 @@ > @@ -2113,7 +2110,7 @@ > @@ -2149,7 +2146,7 @@ > @@ -2185,7 +2182,7 @@ > @@ -2221,7 +2218,7 @@ > @@ -2257,7 +2254,7 @@ > @@ -2293,7 +2290,7 @@ > @@ -2377,7 +2374,7 @@ > @@ -2413,7 +2410,7 @@ > @@ -2449,7 +2446,7 @@ > @@ -2489,7 +2486,7 @@ > @@ -2525,7 +2522,7 @@ > @@ -2561,7 +2558,7 @@ > @@ -2601,7 +2598,7 @@ > @@ -2637,7 +2634,7 @@ > @@ -2673,7 +2670,7 @@ > @@ -2709,7 +2706,7 @@ > @@ -2734,7 +2731,7 @@ > @@ -2747,7 +2744,7 @@ > @@ -2783,7 +2780,7 @@ > @@ -2819,7 +2816,7 @@ > @@ -2828,7 +2825,7 @@ > @@ -2837,7 +2834,7 @@ > @@ -2846,7 +2843,7 @@ > @@ -2859,7 +2856,7 @@ > @@ -2895,7 +2892,7 @@ > @@ -2931,7 +2928,7 @@ > @@ -2967,7 +2964,7 @@ > @@ -3003,7 +3000,7 @@ > @@ -3039,7 +3036,7 @@ > @@ -3075,7 +3072,7 @@ > @@ -3111,7 +3108,7 @@ > @@ -3147,7 +3144,7 @@ > @@ -3183,7 +3180,7 @@ > @@ -3219,7 +3216,7 @@ > @@ -3255,7 +3252,7 @@ > @@ -3291,7 +3288,7 @@ > @@ -3327,7 +3324,7 @@ > @@ -3363,7 +3360,7 @@ > @@ -3399,7 +3396,7 @@ > @@ -3435,7 +3432,7 @@ > @@ -3471,7 +3468,7 @@ > @@ -3507,7 +3504,7 @@ > @@ -3547,7 +3544,7 @@ > @@ -3583,7 +3580,7 @@ > @@ -3619,7 +3616,7 @@ > @@ -3655,7 +3652,7 @@ > @@ -3739,7 +3736,7 @@ > @@ -3775,7 +3772,7 @@ > @@ -3811,7 +3808,7 @@ > @@ -3847,7 +3844,7 @@ > @@ -3883,7 +3880,7 @@ > @@ -3923,7 +3920,7 @@ > @@ -3959,7 +3956,7 @@ > @@ -3995,7 +3992,7 @@ > @@ -4031,7 +4028,7 @@ > @@ -4067,7 +4064,7 @@ > @@ -4103,7 +4100,7 @@ > @@ -4139,7 +4136,7 @@ > @@ -4175,7 +4172,7 @@ > @@ -4211,7 +4208,7 @@ > @@ -4247,7 +4244,7 @@ > @@ -5065,7 +5062,7 @@ > @@ -5105,7 +5102,7 @@ > @@ -5145,7 +5142,7 @@ > @@ -5185,7 +5182,7 @@ > @@ -5225,7 +5222,7 @@ > @@ -5261,7 +5258,7 @@ > @@ -5297,7 +5294,7 @@ > @@ -5357,7 +5354,7 @@ > @@ -5437,7 +5434,7 @@ > @@ -5481,7 +5478,7 @@ > @@ -5521,7 +5518,7 @@ > @@ -5557,7 +5554,7 @@ > @@ -5593,7 +5590,7 @@ > @@ -5629,7 +5626,7 @@ > @@ -5638,7 +5635,7 @@ > @@ -5647,7 +5644,7 @@ > @@ -5667,7 +5664,7 @@ > @@ -5703,7 +5700,7 @@ > @@ -5751,7 +5748,7 @@ > @@ -5799,7 +5796,7 @@ > @@ -5835,7 +5832,7 @@ > @@ -5879,7 +5876,7 @@ > @@ -5915,7 +5912,7 @@ > @@ -5951,7 +5948,7 @@ > @@ -5995,7 +5992,7 @@ > @@ -6039,7 +6036,7 @@ > @@ -6075,7 +6072,7 @@ > @@ -6119,7 +6116,7 @@ > @@ -6155,7 +6152,7 @@ > @@ -6207,7 +6204,7 @@ > @@ -6247,7 +6244,7 @@ > @@ -6283,7 +6280,7 @@ > @@ -6319,7 +6316,7 @@ > @@ -6355,7 +6352,7 @@ > @@ -6391,7 +6388,7 @@ > @@ -6427,7 +6424,7 @@ > @@ -6463,7 +6460,7 @@ > @@ -6503,7 +6500,7 @@ > @@ -6539,7 +6536,7 @@ > @@ -6575,7 +6572,7 @@ > @@ -6611,7 +6608,7 @@ > @@ -6647,7 +6644,7 @@ > @@ -6683,7 +6680,7 @@ > @@ -6719,7 +6716,7 @@ > @@ -6755,7 +6752,7 @@ > @@ -6791,7 +6788,7 @@ > @@ -6827,7 +6824,7 @@ > @@ -6863,7 +6860,7 @@ > @@ -6899,7 +6896,7 @@ > @@ -6939,7 +6936,7 @@ > @@ -6975,7 +6972,7 @@ > @@ -7019,7 +7016,7 @@ > @@ -7055,7 +7052,7 @@ > @@ -7091,7 +7088,7 @@ > @@ -7131,7 +7128,7 @@ > @@ -7167,7 +7164,7 @@ > @@ -7203,7 +7200,7 @@ > @@ -7239,7 +7236,7 @@ > @@ -7275,7 +7272,7 @@ > @@ -7311,7 +7308,7 @@ > @@ -7347,7 +7344,7 @@ > @@ -7387,7 +7384,7 @@ > @@ -7423,7 +7420,7 @@ > @@ -7459,7 +7456,7 @@ > @@ -7495,7 +7492,7 @@ > @@ -7531,7 +7528,7 @@ > @@ -7567,7 +7564,7 @@ > @@ -7603,7 +7600,7 @@ > @@ -7639,7 +7636,7 @@ > @@ -7675,7 +7672,7 @@ > @@ -7711,7 +7708,7 @@ > @@ -7747,7 +7744,7 @@ > @@ -7783,7 +7780,7 @@ > @@ -7819,7 +7816,7 @@ > @@ -7855,7 +7852,7 @@ > @@ -7899,7 +7896,7 @@ > @@ -7935,7 +7932,7 @@ > @@ -7971,7 +7968,7 @@ > @@ -8011,7 +8008,7 @@ > @@ -8051,7 +8048,7 @@ > @@ -8087,7 +8084,7 @@ > @@ -8123,7 +8120,7 @@ > @@ -8159,7 +8156,7 @@ > @@ -8195,7 +8192,7 @@ > @@ -8231,7 +8228,7 @@ > @@ -8267,7 +8264,7 @@ > @@ -8303,7 +8300,7 @@ > @@ -8343,7 +8340,7 @@ > @@ -8379,7 +8376,7 @@ > @@ -8415,7 +8412,7 @@ > @@ -8451,7 +8448,7 @@ > @@ -8491,7 +8488,7 @@ > @@ -8650,7 +8647,7 @@ > @@ -8686,7 +8683,7 @@ > @@ -8722,7 +8719,7 @@ > @@ -8758,7 +8755,7 @@ > @@ -8794,7 +8791,7 @@ > @@ -8830,7 +8827,7 @@ > @@ -8870,7 +8867,7 @@ > @@ -8906,7 +8903,7 @@ > @@ -8942,7 +8939,7 @@ >