components/prboom/p_saveg.c
//
// P_ArchiveThinkers
//
// 2/14/98 killough: substantially modified to fix savegame bugs
P_ArchiveThinkers
2/14/98 killough: substantially modified to fix savegame bugs
P_ArchiveThinkers 2 / 14 / 98 killough : substantially modified to fix savegame bugs
void P_ArchiveThinkers (void)
{
  thinker_t *th;
  CheckSaveGame(sizeof brain);      
  memcpy(save_p, &brain, sizeof brain);
  save_p += sizeof brain;
  CheckSaveGame(number_of_thinkers*(sizeof(mobj_t)-3*sizeof(fixed_t)+4+3*sizeof(void*)) +1);
  for (th = thinkercap.next ; th != &thinkercap ; th=th->next)
    if (th->function == P_MobjThinker)
      {
        mobj_t *mobj;
        *save_p++ = tc_mobj;
        PADSAVEP();
        mobj = (mobj_t *)save_p;
        memcpy (mobj, th, sizeof(*mobj) - 2*sizeof(void*));
        save_p += sizeof(*mobj) - 2*sizeof(void*) - 4*sizeof(fixed_t);
        memset (save_p, 0, 5*sizeof(void*));
        mobj->state = (state_t *)(mobj->state - states);
        if (mobj->target)
          mobj->target = mobj->target->thinker.function ==
            P_MobjThinker ?
            (mobj_t *) mobj->target->thinker.prev : NULL;
        if (mobj->tracer)
          mobj->tracer = mobj->tracer->thinker.function ==
            P_MobjThinker ?
            (mobj_t *) mobj->tracer->thinker.prev : NULL;
        if (((mobj_t*)th)->lastenemy && ((mobj_t*)th)->lastenemy->thinker.function == P_MobjThinker) {
          memcpy (save_p + sizeof(void*), &(((mobj_t*)th)->lastenemy->thinker.prev), sizeof(void*));
	}
        save_p += 5*sizeof(void*);
        if (mobj->player)
          mobj->player = (player_t *)((mobj->player-players) + 1);
      }
  *save_p++ = tc_end;
  {
    int i;
    CheckSaveGame(numsectors * sizeof(mobj_t *));       
    for (i = 0; i < numsectors; i++)
    {
      mobj_t *target = sectors[i].soundtarget;
      if (target && target->thinker.function == P_MobjThinker)
        target = (mobj_t *) target->thinker.prev;
      else
        target = NULL;
      memcpy(save_p, &target, sizeof target);
      save_p += sizeof target;
    }
  }
}
void P_ArchiveThinkers ( void ) { thinker_t * th ; CheckSaveGame ( sizeof brain ) ; memcpy ( save_p , & brain , sizeof brain ) ; save_p += sizeof brain ; CheckSaveGame ( number_of_thinkers * ( sizeof ( mobj_t ) -3 * sizeof ( fixed_t ) + 4 + 3 * sizeof ( void * ) ) + 1 ) ; for ( th = thinkercap . next ; th != & thinkercap ; th = th -> next ) if ( th -> function == P_MobjThinker ) { mobj_t * mobj ; * save_p ++ = tc_mobj ; PADSAVEP ( ) ; mobj = ( mobj_t * ) save_p ; memcpy ( mobj , th , sizeof ( * mobj ) - 2 * sizeof ( void * ) ) ; save_p += sizeof ( * mobj ) - 2 * sizeof ( void * ) - 4 * sizeof ( fixed_t ) ; memset ( save_p , 0 , 5 * sizeof ( void * ) ) ; mobj -> state = ( state_t * ) ( mobj -> state - states ) ; if ( mobj -> target ) mobj -> target = mobj -> target -> thinker . function == P_MobjThinker ? ( mobj_t * ) mobj -> target -> thinker . prev : NULL ; if ( mobj -> tracer ) mobj -> tracer = mobj -> tracer -> thinker . function == P_MobjThinker ? ( mobj_t * ) mobj -> tracer -> thinker . prev : NULL ; if ( ( ( mobj_t * ) th ) -> lastenemy && ( ( mobj_t * ) th ) -> lastenemy -> thinker . function == P_MobjThinker ) { memcpy ( save_p + sizeof ( void * ) , & ( ( ( mobj_t * ) th ) -> lastenemy -> thinker . prev ) , sizeof ( void * ) ) ; } save_p += 5 * sizeof ( void * ) ; if ( mobj -> player ) mobj -> player = ( player_t * ) ( ( mobj -> player - players ) + 1 ) ; } * save_p ++ = tc_end ; { int i ; CheckSaveGame ( numsectors * sizeof ( mobj_t * ) ) ; for ( i = 0 ; i < numsectors ; i ++ ) { mobj_t * target = sectors [ i ] . soundtarget ; if ( target && target -> thinker . function == P_MobjThinker ) target = ( mobj_t * ) target -> thinker . prev ; else target = NULL ; memcpy ( save_p , & target , sizeof target ) ; save_p += sizeof target ; } } }
P_ArchiveThinkers
2/14/98 killough: substantially modified to fix savegame bugs
P_ArchiveThinkers 2 / 14 / 98 killough : substantially modified to fix savegame bugs
// killough 3/26/98: Save boss brain state /* check that enough room is available in savegame buffer
   * - killough 2/14/98
   * cph - use number_of_thinkers saved by P_ThinkerToIndex above
   * size per object is sizeof(mobj_t) - 2*sizeof(void*) - 4*sizeof(fixed_t) plus
   * padded type (4) plus 5*sizeof(void*), i.e. sizeof(mobj_t) + 4 +
   * 3*sizeof(void*)
   * cph - +1 for the tc_end
   */ // save off the current thinkers /* cph 2006/07/30 - 
	 * The end of mobj_t changed from
	 *  boolean invisible;
	 *  mobj_t* lastenemy;
	 *  mobj_t* above_monster;
	 *  mobj_t* below_monster;
	 *  void* touching_sectorlist;
	 * to
	 *  mobj_t* lastenemy;
	 *  void* touching_sectorlist;
         *  fixed_t PrevX, PrevY, PrevZ, padding;
	 * at prboom 2.4.4. There is code here to preserve the savegame format.
	 *
	 * touching_sectorlist is reconstructed anyway, so we now leave off the
	 * last 2 words of mobj_t, write 5 words of 0 and then write lastenemy
	 * into the second of these.
	 */ // killough 2/14/98: convert pointers into indices. // Fixes many savegame problems, by properly saving // target and tracer fields. Note: we store NULL if // the thinker pointed to by these fields is not a // mobj thinker. // killough 2/14/98: new field: save last known enemy. Prevents // monsters from going to sleep after killing monsters and not // seeing player anymore. // killough 2/14/98: end changes // add a terminating marker // killough 9/14/98: save soundtargets // killough 9/14/98 // Fix crash on reload when a soundtarget points to a removed corpse // (prboom bug #1590350)