- Fixed: If an object is flagged for euthanization while it's in the gray

list, it should just be ignored during the propagation stage.
- After sleeping on it and realizing what was really going in, I generalized
  the inventory fix from the 13th: The actor is flagged by Destroy(), then it
  is later inserted into the thinker list by DThinker::SerializeAll(). So
  rather than unlinking the skipped player from their inventory, just make
  sure any flagged thinkers aren't inserted into a list.
- Fixed: FCanvasTextureInfo::Viewpoint needed a read barrier, and the whole
  list should serve as a root.
- Reimplemented SPC playback as a custom codec for FMOD.
- Removed spc_frequency, because snes_spc only supports the SPC's native
  frequency of 32000 Hz.


SVN r806 (trunk)
This commit is contained in:
Randy Heit 2008-03-16 00:54:53 +00:00
commit ce811319a7
12 changed files with 367 additions and 168 deletions

View file

@ -54,6 +54,8 @@ bool DThinker::bSerialOverride = false;
void FThinkerList::AddTail(DThinker *thinker)
{
assert(thinker->PrevThinker == NULL && thinker->NextThinker == NULL);
assert(!(thinker->ObjectFlags & OF_EuthanizeMe));
if (Sentinel == NULL)
{
Sentinel = new DThinker(DThinker::NO_LINK);
@ -62,7 +64,6 @@ void FThinkerList::AddTail(DThinker *thinker)
Sentinel->PrevThinker = Sentinel;
GC::WriteBarrier(Sentinel);
}
assert(thinker->PrevThinker == NULL && thinker->NextThinker == NULL);
DThinker *tail = Sentinel->PrevThinker;
assert(tail->NextThinker == Sentinel);
thinker->PrevThinker = tail;
@ -172,7 +173,12 @@ void DThinker::SerializeAll(FArchive &arc, bool hubLoad)
}
// Thinkers with the OF_JustSpawned flag set go in the FreshThinkers
// list. Anything else goes in the regular Thinkers list.
if (thinker->ObjectFlags & OF_JustSpawned)
if (thinker->ObjectFlags & OF_EuthanizeMe)
{
// This thinker was destroyed during the loading process. Do
// not link it in to any list.
}
else if (thinker->ObjectFlags & OF_JustSpawned)
{
FreshThinkers[stat].AddTail(thinker);
}
@ -367,16 +373,30 @@ void DThinker::DestroyMostThinkersInList (FThinkerList &list, int stat)
DestroyThinkersInList (list);
}
else if (list.Sentinel != NULL)
{ // Move all players to an ancillary list to ensure
// that the collector won't consider them dead.
while (list.Sentinel->NextThinker != list.Sentinel)
{ // If it's a voodoo doll, destroy it. Otherwise, simply remove
// it from the list. G_FinishTravel() will find it later from
// a players[].mo link and destroy it then, after copying various
// information to a new player.
for (DThinker *probe = list.Sentinel->NextThinker, *next; probe != list.Sentinel; probe = next)
{
DThinker *thinker = list.Sentinel->NextThinker;
thinker->Remove();
Thinkers[MAX_STATNUM+1].AddTail(thinker);
next = probe->NextThinker;
if (!probe->IsKindOf(RUNTIME_CLASS(APlayerPawn)) || // <- should not happen
static_cast<AActor *>(probe)->player == NULL ||
static_cast<AActor *>(probe)->player->mo != probe)
{
probe->Destroy();
}
else
{
probe->Remove();
// Technically, this doesn't need to be in any list now, since
// it's only going to be found later and destroyed before ever
// needing to tick again, but by moving it to a separate list,
// I can keep my debug assertions that all thinkers are either
// euthanizing or in a list.
Thinkers[MAX_STATNUM+1].AddTail(probe);
}
}
list.Sentinel->Destroy();
list.Sentinel = NULL;
}
}