DOOM-3-BFG

DOOM 3 BFG Edition
Log | Files | Refs

p_saveg.cpp (26293B)


      1 /*
      2 ===========================================================================
      3 
      4 Doom 3 BFG Edition GPL Source Code
      5 Copyright (C) 1993-2012 id Software LLC, a ZeniMax Media company. 
      6 
      7 This file is part of the Doom 3 BFG Edition GPL Source Code ("Doom 3 BFG Edition Source Code").  
      8 
      9 Doom 3 BFG Edition Source Code is free software: you can redistribute it and/or modify
     10 it under the terms of the GNU General Public License as published by
     11 the Free Software Foundation, either version 3 of the License, or
     12 (at your option) any later version.
     13 
     14 Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful,
     15 but WITHOUT ANY WARRANTY; without even the implied warranty of
     16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     17 GNU General Public License for more details.
     18 
     19 You should have received a copy of the GNU General Public License
     20 along with Doom 3 BFG Edition Source Code.  If not, see <http://www.gnu.org/licenses/>.
     21 
     22 In addition, the Doom 3 BFG Edition Source Code is also subject to certain additional terms. You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code.  If not, please request a copy in writing from id Software at the address below.
     23 
     24 If you have questions concerning this license or the applicable additional terms, you may contact in writing id Software LLC, c/o ZeniMax Media Inc., Suite 120, Rockville, Maryland 20850 USA.
     25 
     26 ===========================================================================
     27 */
     28 
     29 #include "Precompiled.h"
     30 #include "globaldata.h"
     31 
     32 #include "i_system.h"
     33 #include "z_zone.h"
     34 #include "p_local.h"
     35 
     36 // State.
     37 #include "doomstat.h"
     38 #include "r_state.h"
     39 
     40 
     41 
     42 // Pads ::g->save_p to a 4-byte boundary
     43 //  so that the load/save works on SGI&Gecko.
     44 
     45 
     46 
     47 //
     48 // P_ArchivePlayers
     49 //
     50 void P_ArchivePlayers (void)
     51 {
     52     int		i;
     53     int		j;
     54     player_t*	dest;
     55 		
     56     for (i=0 ; i<MAXPLAYERS ; i++)
     57     {
     58 	if (!::g->playeringame[i])
     59 	    continue;
     60 	
     61 	PADSAVEP();
     62 
     63 	dest = (player_t *)::g->save_p;
     64 	memcpy (dest,&::g->players[i],sizeof(player_t));
     65 	::g->save_p += sizeof(player_t);
     66 	for (j=0 ; j<NUMPSPRITES ; j++)
     67 	{
     68 	    if (dest->psprites[j].state)
     69 	    {
     70 		dest->psprites[j].state 
     71 			= (state_t *)(dest->psprites[j].state-::g->states);
     72 	    }
     73 	}
     74     }
     75 }
     76 
     77 
     78 
     79 //
     80 // P_UnArchivePlayers
     81 //
     82 void P_UnArchivePlayers (void)
     83 {
     84     int		i;
     85     int		j;
     86 	
     87     for (i=0 ; i<MAXPLAYERS ; i++)
     88     {
     89 	if (!::g->playeringame[i])
     90 	    continue;
     91 	
     92 	PADSAVEP();
     93 
     94 	memcpy (&::g->players[i],::g->save_p, sizeof(player_t));
     95 	::g->save_p += sizeof(player_t);
     96 	
     97 	// will be set when unarc thinker
     98 	::g->players[i].mo = NULL;	
     99 	::g->players[i].message = NULL;
    100 	::g->players[i].attacker = NULL;
    101 
    102 	for (j=0 ; j<NUMPSPRITES ; j++)
    103 	{
    104 	    if (::g->players[i]. psprites[j].state)
    105 	    {
    106 		::g->players[i]. psprites[j].state 
    107 		    = &::g->states[ (int)::g->players[i].psprites[j].state ];
    108 	    }
    109 	}
    110     }
    111 }
    112 
    113 
    114 //
    115 // P_ArchiveWorld
    116 //
    117 void P_ArchiveWorld (void)
    118 {
    119     int			i;
    120     int			j;
    121     sector_t*		sec;
    122     line_t*		li;
    123     side_t*		si;
    124     short*		put;
    125 	
    126     put = (short *)::g->save_p;
    127     
    128     // do ::g->sectors
    129     for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++)
    130     {
    131 	*put++ = sec->floorheight >> FRACBITS;
    132 	*put++ = sec->ceilingheight >> FRACBITS;
    133 	*put++ = sec->floorpic;
    134 	*put++ = sec->ceilingpic;
    135 	*put++ = sec->lightlevel;
    136 	*put++ = sec->special;		// needed?
    137 	*put++ = sec->tag;		// needed?
    138     }
    139 
    140     
    141     // do ::g->lines
    142     for (i=0, li = ::g->lines ; i < ::g->numlines ; i++,li++)
    143     {
    144 	*put++ = li->flags;
    145 	*put++ = li->special;
    146 	*put++ = li->tag;
    147 	for (j=0 ; j<2 ; j++)
    148 	{
    149 	    if (li->sidenum[j] == -1)
    150 		continue;
    151 	    
    152 	    si = &::g->sides[li->sidenum[j]];
    153 
    154 	    *put++ = si->textureoffset >> FRACBITS;
    155 	    *put++ = si->rowoffset >> FRACBITS;
    156 	    *put++ = si->toptexture;
    157 	    *put++ = si->bottomtexture;
    158 	    *put++ = si->midtexture;	
    159 	}
    160     }
    161 
    162 	// Doom 2 level 30 requires some global pointers, wheee!
    163 	*put++ = ::g->braintargeton;
    164 	*put++ = ::g->easy;
    165 
    166     ::g->save_p = (byte *)put;
    167 }
    168 
    169 
    170 
    171 //
    172 // P_UnArchiveWorld
    173 //
    174 void P_UnArchiveWorld (void)
    175 {
    176     int			i;
    177     int			j;
    178     sector_t*	sec;
    179     line_t*		li;
    180     side_t*		si;
    181     short*		get;
    182 	
    183     get = (short *)::g->save_p;
    184     
    185     // do ::g->sectors
    186     for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++)
    187     {
    188 	sec->floorheight = *get++ << FRACBITS;
    189 	sec->ceilingheight = *get++ << FRACBITS;
    190 	sec->floorpic = *get++;
    191 	sec->ceilingpic = *get++;
    192 	sec->lightlevel = *get++;
    193 	sec->special = *get++;		// needed?
    194 	sec->tag = *get++;		// needed?
    195 	sec->specialdata = 0;
    196 	sec->soundtarget = 0;
    197     }
    198     
    199     // do ::g->lines
    200     for (i=0, li = ::g->lines ; i < ::g->numlines ; i++,li++)
    201     {
    202 	li->flags = *get++;
    203 	li->special = *get++;
    204 	li->tag = *get++;
    205 	for (j=0 ; j<2 ; j++)
    206 	{
    207 	    if (li->sidenum[j] == -1)
    208 		continue;
    209 	    si = &::g->sides[li->sidenum[j]];
    210 	    si->textureoffset = *get++ << FRACBITS;
    211 	    si->rowoffset = *get++ << FRACBITS;
    212 	    si->toptexture = *get++;
    213 	    si->bottomtexture = *get++;
    214 	    si->midtexture = *get++;
    215 	}
    216     }
    217 
    218 	// Doom 2 level 30 requires some global pointers, wheee!
    219 	::g->braintargeton = *get++;
    220 	::g->easy = *get++;
    221 
    222     ::g->save_p = (byte *)get;	
    223 }
    224 
    225 
    226 
    227 
    228 
    229 //
    230 // Thinkers
    231 //
    232 
    233 int GetMOIndex( mobj_t* findme ) {
    234 	thinker_t*	th;
    235 	mobj_t*		mobj;
    236 	int			index = 0;
    237 
    238 	for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next)
    239 	{
    240 		if (th->function.acp1 == (actionf_p1)P_MobjThinker) {
    241 			index++;
    242 			mobj = (mobj_t*)th;
    243 
    244 			if ( mobj == findme ) {
    245 				return index;
    246 			}
    247 		}
    248 	}
    249 
    250 	return 0;
    251 }
    252 
    253 mobj_t* GetMO( int index ) {
    254 	thinker_t*	th;
    255 	int			testindex = 0;
    256 
    257 	if ( !index ) {
    258 		return NULL;
    259 	}
    260 
    261 	for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next)
    262 	{
    263 		if (th->function.acp1 == (actionf_p1)P_MobjThinker) {
    264 			testindex++;
    265 
    266 			if ( testindex == index ) {
    267 				return (mobj_t*)th;
    268 			}
    269 		}
    270 	}
    271 
    272 	return NULL;
    273 }
    274 
    275 //
    276 // P_ArchiveThinkers
    277 //
    278 void P_ArchiveThinkers (void)
    279 {
    280 	thinker_t*		th;
    281 	mobj_t*			mobj;
    282 	ceiling_t*		ceiling;
    283 	vldoor_t*		door;
    284 	floormove_t*	floor;
    285 	plat_t*			plat;
    286 	fireflicker_t*	fire;
    287 	lightflash_t*	flash;
    288 	strobe_t*		strobe;
    289 	glow_t*			glow;
    290 
    291 	int i;
    292 	
    293 	// save off the current thinkers
    294 	//I_Printf( "Savegame on leveltime %d\n====================\n", ::g->leveltime );
    295 
    296 	for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next)
    297 	{
    298 		//mobj_t*	test = (mobj_t*)th;
    299 		//I_Printf( "%3d: %x == function\n", index++, th->function.acp1 );
    300 
    301 		if (th->function.acp1 == (actionf_p1)P_MobjThinker)
    302 		{
    303 			*::g->save_p++ = tc_mobj;
    304 			PADSAVEP();
    305 
    306 			mobj = (mobj_t *)::g->save_p;
    307 			memcpy (mobj, th, sizeof(*mobj));
    308 			::g->save_p += sizeof(*mobj);
    309 			mobj->state = (state_t *)(mobj->state - ::g->states);
    310 
    311 			if (mobj->player)
    312 				mobj->player = (player_t *)((mobj->player-::g->players) + 1);
    313 
    314 			// Save out 'target'
    315 			int moIndex = GetMOIndex( mobj->target );
    316 			*::g->save_p++ = moIndex >> 8;
    317 			*::g->save_p++ = moIndex;
    318 
    319 			// Save out 'tracer'
    320 			moIndex = GetMOIndex( mobj->tracer );
    321 			*::g->save_p++ = moIndex >> 8;
    322 			*::g->save_p++ = moIndex;
    323 
    324 			moIndex = GetMOIndex( mobj->snext );
    325 			*::g->save_p++ = moIndex >> 8;
    326 			*::g->save_p++ = moIndex;
    327 
    328 			moIndex = GetMOIndex( mobj->sprev );
    329 			*::g->save_p++ = moIndex >> 8;
    330 			*::g->save_p++ = moIndex;
    331 
    332 			// Is this the head of a sector list?
    333 			if ( mobj->subsector->sector->thinglist == (mobj_t*)th ) {
    334 				*::g->save_p++ = 1;
    335 			}
    336 			else {
    337 				*::g->save_p++ = 0;
    338 			}
    339 
    340 			moIndex = GetMOIndex( mobj->bnext );
    341 			*::g->save_p++ = moIndex >> 8;
    342 			*::g->save_p++ = moIndex;
    343 
    344 			moIndex = GetMOIndex( mobj->bprev );
    345 			*::g->save_p++ = moIndex >> 8;
    346 			*::g->save_p++ = moIndex;
    347 
    348 			// Is this the head of a block list?
    349 			int	blockx = (mobj->x - ::g->bmaporgx)>>MAPBLOCKSHIFT;
    350 			int	blocky = (mobj->y - ::g->bmaporgy)>>MAPBLOCKSHIFT;
    351 			if ( blockx >= 0 && blockx < ::g->bmapwidth && blocky >= 0 && blocky < ::g->bmapheight 
    352 				&& (mobj_t*)th == ::g->blocklinks[blocky*::g->bmapwidth+blockx] ) {
    353 
    354 					*::g->save_p++ = 1;
    355 			}
    356 			else {
    357 				*::g->save_p++ = 0;
    358 			}
    359 			continue;
    360 		}
    361 
    362 		if (th->function.acv == (actionf_v)NULL)
    363 		{
    364 			for (i = 0; i < MAXCEILINGS;i++)
    365 				if (::g->activeceilings[i] == (ceiling_t *)th)
    366 					break;
    367 
    368 			if (i<MAXCEILINGS)
    369 			{
    370 				*::g->save_p++ = tc_ceiling;
    371 				PADSAVEP();
    372 				ceiling = (ceiling_t *)::g->save_p;
    373 				memcpy (ceiling, th, sizeof(*ceiling));
    374 				::g->save_p += sizeof(*ceiling);
    375 				ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors);
    376 			}
    377 			continue;
    378 		}
    379 
    380 		if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
    381 		{
    382 			*::g->save_p++ = tc_ceiling;
    383 			PADSAVEP();
    384 			ceiling = (ceiling_t *)::g->save_p;
    385 			memcpy (ceiling, th, sizeof(*ceiling));
    386 			::g->save_p += sizeof(*ceiling);
    387 			ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors);
    388 			continue;
    389 		}
    390 
    391 		if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
    392 		{
    393 			*::g->save_p++ = tc_door;
    394 			PADSAVEP();
    395 			door = (vldoor_t *)::g->save_p;
    396 			memcpy (door, th, sizeof(*door));
    397 			::g->save_p += sizeof(*door);
    398 			door->sector = (sector_t *)(door->sector - ::g->sectors);
    399 			continue;
    400 		}
    401 
    402 		if (th->function.acp1 == (actionf_p1)T_MoveFloor)
    403 		{
    404 			*::g->save_p++ = tc_floor;
    405 			PADSAVEP();
    406 			floor = (floormove_t *)::g->save_p;
    407 			memcpy (floor, th, sizeof(*floor));
    408 			::g->save_p += sizeof(*floor);
    409 			floor->sector = (sector_t *)(floor->sector - ::g->sectors);
    410 			continue;
    411 		}
    412 
    413 		if (th->function.acp1 == (actionf_p1)T_PlatRaise)
    414 		{
    415 			*::g->save_p++ = tc_plat;
    416 			PADSAVEP();
    417 			plat = (plat_t *)::g->save_p;
    418 			memcpy (plat, th, sizeof(*plat));
    419 			::g->save_p += sizeof(*plat);
    420 			plat->sector = (sector_t *)(plat->sector - ::g->sectors);
    421 			continue;
    422 		}
    423 
    424 		if (th->function.acp1 == (actionf_p1)T_FireFlicker)
    425 		{
    426 			*::g->save_p++ = tc_fire;
    427 			PADSAVEP();
    428 			fire = (fireflicker_t *)::g->save_p;
    429 			memcpy (fire, th, sizeof(*fire));
    430 			::g->save_p += sizeof(*fire);
    431 			fire->sector = (sector_t *)(fire->sector - ::g->sectors);
    432 			continue;
    433 		}
    434 
    435 		if (th->function.acp1 == (actionf_p1)T_LightFlash)
    436 		{
    437 			*::g->save_p++ = tc_flash;
    438 			PADSAVEP();
    439 			flash = (lightflash_t *)::g->save_p;
    440 			memcpy (flash, th, sizeof(*flash));
    441 			::g->save_p += sizeof(*flash);
    442 			flash->sector = (sector_t *)(flash->sector - ::g->sectors);
    443 			continue;
    444 		}
    445 
    446 		if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
    447 		{
    448 			*::g->save_p++ = tc_strobe;
    449 			PADSAVEP();
    450 			strobe = (strobe_t *)::g->save_p;
    451 			memcpy (strobe, th, sizeof(*strobe));
    452 			::g->save_p += sizeof(*strobe);
    453 			strobe->sector = (sector_t *)(strobe->sector - ::g->sectors);
    454 			continue;
    455 		}
    456 
    457 		if (th->function.acp1 == (actionf_p1)T_Glow)
    458 		{
    459 			*::g->save_p++ = tc_glow;
    460 			PADSAVEP();
    461 			glow = (glow_t *)::g->save_p;
    462 			memcpy (glow, th, sizeof(*glow));
    463 			::g->save_p += sizeof(*glow);
    464 			glow->sector = (sector_t *)(glow->sector - ::g->sectors);
    465 			continue;
    466 		}
    467 	}
    468 
    469 	// add a terminating marker
    470 	*::g->save_p++ = tc_end;
    471 
    472 	sector_t* sec;
    473     short* put = (short *)::g->save_p;
    474 	for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++) {
    475 		*put++ = (short)GetMOIndex( sec->soundtarget );
    476 	}
    477 
    478 	::g->save_p = (byte *)put;
    479 
    480 	// add a terminating marker
    481 	*::g->save_p++ = tc_end;
    482 }
    483 
    484 
    485 
    486 //
    487 // P_UnArchiveThinkers
    488 //
    489 void P_UnArchiveThinkers (void)
    490 {
    491 	byte			tclass;
    492 	thinker_t*		currentthinker;
    493 	thinker_t*		next;
    494 	mobj_t*			mobj;
    495 	ceiling_t*		ceiling;
    496 	vldoor_t*		door;
    497 	floormove_t*	floor;
    498 	plat_t*			plat;
    499 	fireflicker_t*	fire;
    500 	lightflash_t*	flash;
    501 	strobe_t*		strobe;
    502 	glow_t*			glow;
    503 
    504 	thinker_t*	th;
    505 
    506 	int count = 0;
    507 	sector_t* ss = NULL;
    508 
    509 	int			mo_index = 0;
    510 	int			mo_targets[1024];
    511 	int			mo_tracers[1024];
    512 	int			mo_snext[1024];
    513 	int			mo_sprev[1024];
    514 	bool		mo_shead[1024];
    515 	int			mo_bnext[1024];
    516 	int			mo_bprev[1024];
    517 	bool		mo_bhead[1024];
    518 
    519 	// remove all the current thinkers
    520 	currentthinker = ::g->thinkercap.next;
    521 	while (currentthinker != &::g->thinkercap)
    522 	{
    523 		next = currentthinker->next;
    524 
    525 		if (currentthinker->function.acp1 == (actionf_p1)P_MobjThinker)
    526 			P_RemoveMobj ((mobj_t *)currentthinker);
    527 		else
    528 			Z_Free(currentthinker);
    529 
    530 		currentthinker = next;
    531 	}
    532 
    533 	P_InitThinkers ();
    534 
    535 	// read in saved thinkers
    536 	while (1)
    537 	{
    538 		tclass = *::g->save_p++;
    539 		switch (tclass)
    540 		{
    541 		case tc_end:
    542 
    543 			// clear sector thing lists
    544 			ss = ::g->sectors;
    545 			for (int i=0 ; i < ::g->numsectors ; i++, ss++) {
    546 				ss->thinglist = NULL;
    547 			}
    548 
    549 			// clear blockmap thing lists
    550 			count = sizeof(*::g->blocklinks) * ::g->bmapwidth * ::g->bmapheight;
    551 			memset (::g->blocklinks, 0, count);
    552 
    553 			// Doom 2 level 30 requires some global pointers, wheee!
    554 			::g->numbraintargets = 0;
    555 
    556 			// fixup mobj_t pointers now that all thinkers have been restored
    557 			mo_index = 0;
    558 			for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next) {
    559 				if (th->function.acp1 == (actionf_p1)P_MobjThinker) {
    560 					mobj = (mobj_t*)th;
    561 
    562 					mobj->target = GetMO( mo_targets[mo_index] );
    563 					mobj->tracer = GetMO( mo_tracers[mo_index] );
    564 
    565 					mobj->snext = GetMO( mo_snext[mo_index] );
    566 					mobj->sprev = GetMO( mo_sprev[mo_index] );
    567 
    568 					if ( mo_shead[mo_index] ) {
    569 						mobj->subsector->sector->thinglist = mobj;
    570 					}
    571 
    572 					mobj->bnext = GetMO( mo_bnext[mo_index] );
    573 					mobj->bprev = GetMO( mo_bprev[mo_index] );
    574 
    575 					if ( mo_bhead[mo_index] ) {
    576 						// Is this the head of a block list?
    577 						int	blockx = (mobj->x - ::g->bmaporgx)>>MAPBLOCKSHIFT;
    578 						int	blocky = (mobj->y - ::g->bmaporgy)>>MAPBLOCKSHIFT;
    579 						if ( blockx >= 0 && blockx < ::g->bmapwidth && blocky >= 0 && blocky < ::g->bmapheight ) {
    580 							::g->blocklinks[blocky*::g->bmapwidth+blockx] = mobj;
    581 						}
    582 					}
    583 
    584 					// Doom 2 level 30 requires some global pointers, wheee!
    585 					if ( mobj->type == MT_BOSSTARGET ) {
    586 						::g->braintargets[::g->numbraintargets] = mobj;
    587 						::g->numbraintargets++;
    588 					}
    589 
    590 					mo_index++;
    591 				}
    592 			}
    593 
    594 			int i;
    595 			sector_t*	sec;
    596 		    short*	get;
    597 
    598 			get = (short *)::g->save_p;
    599 			for (i=0, sec = ::g->sectors ; i < ::g->numsectors ; i++,sec++)
    600 			{
    601 				sec->soundtarget = GetMO( *get++ );
    602 			}
    603 			::g->save_p = (byte *)get;
    604 
    605 			tclass = *::g->save_p++;
    606 			if ( tclass != tc_end ) {
    607 				I_Error( "Savegame error after loading sector soundtargets." );
    608 			}
    609 
    610 			// print the current thinkers
    611 			//I_Printf( "Loadgame on leveltime %d\n====================\n", ::g->leveltime );
    612 			for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next)
    613 			{
    614 				//mobj_t*	test = (mobj_t*)th;
    615 				//I_Printf( "%3d: %x == function\n", index++, th->function.acp1 );
    616 			}
    617 
    618 			return; 	// end of list
    619 
    620 		case tc_mobj:
    621 			PADSAVEP();
    622 			mobj = (mobj_t*)DoomLib::Z_Malloc(sizeof(*mobj), PU_LEVEL, NULL);
    623 			memcpy (mobj, ::g->save_p, sizeof(*mobj));
    624 			::g->save_p += sizeof(*mobj);
    625 			mobj->state = &::g->states[(int)mobj->state];
    626 
    627 			mobj->target = NULL;
    628 			mobj->tracer = NULL;
    629 
    630 			if (mobj->player)
    631 			{
    632 				mobj->player = &::g->players[(int)mobj->player-1];
    633 				mobj->player->mo = mobj;
    634 			}
    635 
    636 			P_SetThingPosition (mobj);
    637 
    638 			mobj->info = &mobjinfo[mobj->type];
    639 			mobj->floorz = mobj->subsector->sector->floorheight;
    640 			mobj->ceilingz = mobj->subsector->sector->ceilingheight;
    641 			mobj->thinker.function.acp1 = (actionf_p1)P_MobjThinker;
    642 
    643 			// Read in 'target' and store for fixup
    644 			int a, b, foundIndex;
    645 			a = *::g->save_p++;
    646 			b = *::g->save_p++;
    647 			foundIndex = (a << 8) + b;
    648 			mo_targets[mo_index] = foundIndex;
    649 
    650 			// Read in 'tracer' and store for fixup
    651 			a = *::g->save_p++;
    652 			b = *::g->save_p++;
    653 			foundIndex = (a << 8) + b;
    654 			mo_tracers[mo_index] = foundIndex;
    655 
    656 			// Read in 'snext' and store for fixup
    657 			a = *::g->save_p++;
    658 			b = *::g->save_p++;
    659 			foundIndex = (a << 8) + b;
    660 			mo_snext[mo_index] = foundIndex;
    661 
    662 			// Read in 'sprev' and store for fixup
    663 			a = *::g->save_p++;
    664 			b = *::g->save_p++;
    665 			foundIndex = (a << 8) + b;
    666 			mo_sprev[mo_index] = foundIndex;
    667 
    668 			foundIndex = *::g->save_p++;
    669 			mo_shead[mo_index] = foundIndex == 1;
    670 
    671 			// Read in 'bnext' and store for fixup
    672 			a = *::g->save_p++;
    673 			b = *::g->save_p++;
    674 			foundIndex = (a << 8) + b;
    675 			mo_bnext[mo_index] = foundIndex;
    676 
    677 			// Read in 'bprev' and store for fixup
    678 			a = *::g->save_p++;
    679 			b = *::g->save_p++;
    680 			foundIndex = (a << 8) + b;
    681 			mo_bprev[mo_index] = foundIndex;
    682 
    683 			foundIndex = *::g->save_p++;
    684 			mo_bhead[mo_index] = foundIndex == 1;
    685 
    686 			mo_index++;
    687 
    688 			P_AddThinker (&mobj->thinker);
    689 			break;
    690 
    691 		case tc_ceiling:
    692 			PADSAVEP();
    693 			ceiling = (ceiling_t*)DoomLib::Z_Malloc(sizeof(*ceiling), PU_LEVEL, NULL);
    694 			memcpy (ceiling, ::g->save_p, sizeof(*ceiling));
    695 			::g->save_p += sizeof(*ceiling);
    696 			ceiling->sector = &::g->sectors[(int)ceiling->sector];
    697 			ceiling->sector->specialdata = ceiling;
    698 
    699 			if (ceiling->thinker.function.acp1)
    700 				ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
    701 
    702 			P_AddThinker (&ceiling->thinker);
    703 			P_AddActiveCeiling(ceiling);
    704 			break;
    705 
    706 		case tc_door:
    707 			PADSAVEP();
    708 			door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, NULL);
    709 			memcpy (door, ::g->save_p, sizeof(*door));
    710 			::g->save_p += sizeof(*door);
    711 			door->sector = &::g->sectors[(int)door->sector];
    712 			door->sector->specialdata = door;
    713 			door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
    714 			P_AddThinker (&door->thinker);
    715 			break;
    716 
    717 		case tc_floor:
    718 			PADSAVEP();
    719 			floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
    720 			memcpy (floor, ::g->save_p, sizeof(*floor));
    721 			::g->save_p += sizeof(*floor);
    722 			floor->sector = &::g->sectors[(int)floor->sector];
    723 			floor->sector->specialdata = floor;
    724 			floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
    725 			P_AddThinker (&floor->thinker);
    726 			break;
    727 
    728 		case tc_plat:
    729 			PADSAVEP();
    730 			plat = (plat_t*)DoomLib::Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
    731 			memcpy (plat, ::g->save_p, sizeof(*plat));
    732 			::g->save_p += sizeof(*plat);
    733 			plat->sector = &::g->sectors[(int)plat->sector];
    734 			plat->sector->specialdata = plat;
    735 
    736 			if (plat->thinker.function.acp1)
    737 				plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
    738 
    739 			P_AddThinker (&plat->thinker);
    740 			P_AddActivePlat(plat);
    741 			break;
    742 
    743 		case tc_fire:
    744 			PADSAVEP();
    745 			fire = (fireflicker_t*)DoomLib::Z_Malloc (sizeof(*fire), PU_LEVEL, NULL);
    746 			memcpy (fire, ::g->save_p, sizeof(*fire));
    747 			::g->save_p += sizeof(*fire);
    748 			fire->sector = &::g->sectors[(int)fire->sector];
    749 			fire->thinker.function.acp1 = (actionf_p1)T_FireFlicker;
    750 			P_AddThinker (&fire->thinker);
    751 			break;
    752 
    753 		case tc_flash:
    754 			PADSAVEP();
    755 			flash = (lightflash_t*)DoomLib::Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
    756 			memcpy (flash, ::g->save_p, sizeof(*flash));
    757 			::g->save_p += sizeof(*flash);
    758 			flash->sector = &::g->sectors[(int)flash->sector];
    759 			flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
    760 			P_AddThinker (&flash->thinker);
    761 			break;
    762 
    763 		case tc_strobe:
    764 			PADSAVEP();
    765 			strobe = (strobe_t*)DoomLib::Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
    766 			memcpy (strobe, ::g->save_p, sizeof(*strobe));
    767 			::g->save_p += sizeof(*strobe);
    768 			strobe->sector = &::g->sectors[(int)strobe->sector];
    769 			strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
    770 			P_AddThinker (&strobe->thinker);
    771 			break;
    772 
    773 		case tc_glow:
    774 			PADSAVEP();
    775 			glow = (glow_t*)DoomLib::Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
    776 			memcpy (glow, ::g->save_p, sizeof(*glow));
    777 			::g->save_p += sizeof(*glow);
    778 			glow->sector = &::g->sectors[(int)glow->sector];
    779 			glow->thinker.function.acp1 = (actionf_p1)T_Glow;
    780 			P_AddThinker (&glow->thinker);
    781 			break;
    782 
    783 		default:
    784 			I_Error ("Unknown tclass %i in savegame",tclass);
    785 		}
    786 	}
    787 }
    788 
    789 
    790 //
    791 // P_ArchiveSpecials
    792 //
    793 
    794 
    795 
    796 //
    797 // Things to handle:
    798 //
    799 // T_MoveCeiling, (ceiling_t: sector_t * swizzle), - active list
    800 // T_VerticalDoor, (vldoor_t: sector_t * swizzle),
    801 // T_MoveFloor, (floormove_t: sector_t * swizzle),
    802 // T_LightFlash, (lightflash_t: sector_t * swizzle),
    803 // T_StrobeFlash, (strobe_t: sector_t *),
    804 // T_Glow, (glow_t: sector_t *),
    805 // T_PlatRaise, (plat_t: sector_t *), - active list
    806 //
    807 void P_ArchiveSpecials (void)
    808 {
    809     thinker_t*		th;
    810     ceiling_t*		ceiling;
    811     vldoor_t*		door;
    812     floormove_t*	floor;
    813     plat_t*		plat;
    814     lightflash_t*	flash;
    815     strobe_t*		strobe;
    816     glow_t*		glow;
    817     int			i;
    818 	
    819     // save off the current thinkers
    820     for (th = ::g->thinkercap.next ; th != &::g->thinkercap ; th=th->next)
    821     {
    822 	if (th->function.acv == (actionf_v)NULL)
    823 	{
    824 	    for (i = 0; i < MAXCEILINGS;i++)
    825 		if (::g->activeceilings[i] == (ceiling_t *)th)
    826 		    break;
    827 	    
    828 	    if (i<MAXCEILINGS)
    829 	    {
    830 		*::g->save_p++ = tc_ceiling;
    831 		PADSAVEP();
    832 		ceiling = (ceiling_t *)::g->save_p;
    833 		memcpy (ceiling, th, sizeof(*ceiling));
    834 		::g->save_p += sizeof(*ceiling);
    835 		ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors);
    836 	    }
    837 	    continue;
    838 	}
    839 			
    840 	if (th->function.acp1 == (actionf_p1)T_MoveCeiling)
    841 	{
    842 	    *::g->save_p++ = tc_ceiling;
    843 	    PADSAVEP();
    844 	    ceiling = (ceiling_t *)::g->save_p;
    845 	    memcpy (ceiling, th, sizeof(*ceiling));
    846 	    ::g->save_p += sizeof(*ceiling);
    847 	    ceiling->sector = (sector_t *)(ceiling->sector - ::g->sectors);
    848 	    continue;
    849 	}
    850 			
    851 	if (th->function.acp1 == (actionf_p1)T_VerticalDoor)
    852 	{
    853 	    *::g->save_p++ = tc_door;
    854 	    PADSAVEP();
    855 	    door = (vldoor_t *)::g->save_p;
    856 	    memcpy (door, th, sizeof(*door));
    857 	    ::g->save_p += sizeof(*door);
    858 	    door->sector = (sector_t *)(door->sector - ::g->sectors);
    859 	    continue;
    860 	}
    861 			
    862 	if (th->function.acp1 == (actionf_p1)T_MoveFloor)
    863 	{
    864 	    *::g->save_p++ = tc_floor;
    865 	    PADSAVEP();
    866 	    floor = (floormove_t *)::g->save_p;
    867 	    memcpy (floor, th, sizeof(*floor));
    868 	    ::g->save_p += sizeof(*floor);
    869 	    floor->sector = (sector_t *)(floor->sector - ::g->sectors);
    870 	    continue;
    871 	}
    872 			
    873 	if (th->function.acp1 == (actionf_p1)T_PlatRaise)
    874 	{
    875 	    *::g->save_p++ = tc_plat;
    876 	    PADSAVEP();
    877 	    plat = (plat_t *)::g->save_p;
    878 	    memcpy (plat, th, sizeof(*plat));
    879 	    ::g->save_p += sizeof(*plat);
    880 	    plat->sector = (sector_t *)(plat->sector - ::g->sectors);
    881 	    continue;
    882 	}
    883 			
    884 	if (th->function.acp1 == (actionf_p1)T_LightFlash)
    885 	{
    886 	    *::g->save_p++ = tc_flash;
    887 	    PADSAVEP();
    888 	    flash = (lightflash_t *)::g->save_p;
    889 	    memcpy (flash, th, sizeof(*flash));
    890 	    ::g->save_p += sizeof(*flash);
    891 	    flash->sector = (sector_t *)(flash->sector - ::g->sectors);
    892 	    continue;
    893 	}
    894 			
    895 	if (th->function.acp1 == (actionf_p1)T_StrobeFlash)
    896 	{
    897 	    *::g->save_p++ = tc_strobe;
    898 	    PADSAVEP();
    899 	    strobe = (strobe_t *)::g->save_p;
    900 	    memcpy (strobe, th, sizeof(*strobe));
    901 	    ::g->save_p += sizeof(*strobe);
    902 	    strobe->sector = (sector_t *)(strobe->sector - ::g->sectors);
    903 	    continue;
    904 	}
    905 			
    906 	if (th->function.acp1 == (actionf_p1)T_Glow)
    907 	{
    908 	    *::g->save_p++ = tc_glow;
    909 	    PADSAVEP();
    910 	    glow = (glow_t *)::g->save_p;
    911 	    memcpy (glow, th, sizeof(*glow));
    912 	    ::g->save_p += sizeof(*glow);
    913 	    glow->sector = (sector_t *)(glow->sector - ::g->sectors);
    914 	    continue;
    915 	}
    916     }
    917 	
    918     // add a terminating marker
    919     *::g->save_p++ = tc_endspecials;	
    920 
    921 }
    922 
    923 
    924 //
    925 // P_UnArchiveSpecials
    926 //
    927 void P_UnArchiveSpecials (void)
    928 {
    929     byte		tclass;
    930     ceiling_t*		ceiling;
    931     vldoor_t*		door;
    932     floormove_t*	floor;
    933     plat_t*		plat;
    934     lightflash_t*	flash;
    935     strobe_t*		strobe;
    936     glow_t*		glow;
    937 
    938     // read in saved thinkers
    939     while (1)
    940     {
    941 	tclass = *::g->save_p++;
    942 	switch (tclass)
    943 	{
    944 	  case tc_endspecials:
    945 	    return;	// end of list
    946 			
    947 	  case tc_ceiling:
    948 	    PADSAVEP();
    949 	    ceiling = (ceiling_t*)DoomLib::Z_Malloc(sizeof(*ceiling), PU_LEVEL, NULL);
    950 	    memcpy (ceiling, ::g->save_p, sizeof(*ceiling));
    951 	    ::g->save_p += sizeof(*ceiling);
    952 	    ceiling->sector = &::g->sectors[(int)ceiling->sector];
    953 	    ceiling->sector->specialdata = ceiling;
    954 
    955 	    if (ceiling->thinker.function.acp1)
    956 		ceiling->thinker.function.acp1 = (actionf_p1)T_MoveCeiling;
    957 
    958 	    P_AddThinker (&ceiling->thinker);
    959 	    P_AddActiveCeiling(ceiling);
    960 	    break;
    961 				
    962 	  case tc_door:
    963 	    PADSAVEP();
    964 	    door = (vldoor_t*)DoomLib::Z_Malloc(sizeof(*door), PU_LEVEL, NULL);
    965 	    memcpy (door, ::g->save_p, sizeof(*door));
    966 	    ::g->save_p += sizeof(*door);
    967 	    door->sector = &::g->sectors[(int)door->sector];
    968 	    door->sector->specialdata = door;
    969 	    door->thinker.function.acp1 = (actionf_p1)T_VerticalDoor;
    970 	    P_AddThinker (&door->thinker);
    971 	    break;
    972 				
    973 	  case tc_floor:
    974 	    PADSAVEP();
    975 	    floor = (floormove_t*)DoomLib::Z_Malloc (sizeof(*floor), PU_LEVEL, NULL);
    976 	    memcpy (floor, ::g->save_p, sizeof(*floor));
    977 	    ::g->save_p += sizeof(*floor);
    978 	    floor->sector = &::g->sectors[(int)floor->sector];
    979 	    floor->sector->specialdata = floor;
    980 	    floor->thinker.function.acp1 = (actionf_p1)T_MoveFloor;
    981 	    P_AddThinker (&floor->thinker);
    982 	    break;
    983 				
    984 	  case tc_plat:
    985 	    PADSAVEP();
    986 	    plat = (plat_t*)DoomLib::Z_Malloc (sizeof(*plat), PU_LEVEL, NULL);
    987 	    memcpy (plat, ::g->save_p, sizeof(*plat));
    988 	    ::g->save_p += sizeof(*plat);
    989 	    plat->sector = &::g->sectors[(int)plat->sector];
    990 	    plat->sector->specialdata = plat;
    991 
    992 	    if (plat->thinker.function.acp1)
    993 		plat->thinker.function.acp1 = (actionf_p1)T_PlatRaise;
    994 
    995 	    P_AddThinker (&plat->thinker);
    996 	    P_AddActivePlat(plat);
    997 	    break;
    998 				
    999 	  case tc_flash:
   1000 	    PADSAVEP();
   1001 	    flash = (lightflash_t*)DoomLib::Z_Malloc (sizeof(*flash), PU_LEVEL, NULL);
   1002 	    memcpy (flash, ::g->save_p, sizeof(*flash));
   1003 	    ::g->save_p += sizeof(*flash);
   1004 	    flash->sector = &::g->sectors[(int)flash->sector];
   1005 	    flash->thinker.function.acp1 = (actionf_p1)T_LightFlash;
   1006 	    P_AddThinker (&flash->thinker);
   1007 	    break;
   1008 				
   1009 	  case tc_strobe:
   1010 	    PADSAVEP();
   1011 	    strobe = (strobe_t*)DoomLib::Z_Malloc (sizeof(*strobe), PU_LEVEL, NULL);
   1012 	    memcpy (strobe, ::g->save_p, sizeof(*strobe));
   1013 	    ::g->save_p += sizeof(*strobe);
   1014 	    strobe->sector = &::g->sectors[(int)strobe->sector];
   1015 	    strobe->thinker.function.acp1 = (actionf_p1)T_StrobeFlash;
   1016 	    P_AddThinker (&strobe->thinker);
   1017 	    break;
   1018 				
   1019 	  case tc_glow:
   1020 	    PADSAVEP();
   1021 	    glow = (glow_t*)DoomLib::Z_Malloc (sizeof(*glow), PU_LEVEL, NULL);
   1022 	    memcpy (glow, ::g->save_p, sizeof(*glow));
   1023 	    ::g->save_p += sizeof(*glow);
   1024 	    glow->sector = &::g->sectors[(int)glow->sector];
   1025 	    glow->thinker.function.acp1 = (actionf_p1)T_Glow;
   1026 	    P_AddThinker (&glow->thinker);
   1027 	    break;
   1028 				
   1029 	  default:
   1030 	    I_Error ("P_UnarchiveSpecials:Unknown tclass %i "
   1031 		     "in savegame",tclass);
   1032 	}
   1033 	
   1034     }
   1035 
   1036 }
   1037 
   1038