1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1997, 2005 - 3D Realms Entertainment
4 
5 This file is part of Shadow Warrior version 1.2
6 
7 Shadow Warrior is free software; you can redistribute it and/or
8 modify it under the terms of the GNU General Public License
9 as published by the Free Software Foundation; either version 2
10 of the License, or (at your option) any later version.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15 
16 See the GNU General Public License for more details.
17 
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
21 
22 Original Source: 1997 - Frank Maddin and Jim Norwood
23 Prepared for public release: 03/28/2005 - Charlie Wiederhold, 3D Realms
24 */
25 //-------------------------------------------------------------------------
26 
27 #define MAIN
28 #define QUIET
29 #include "build.h"
30 
31 #include "keys.h"
32 #include "names2.h"
33 #include "panel.h"
34 #include "game.h"
35 #include "tags.h"
36 #include "lists.h"
37 #include "interp.h"
38 
39 #include "net.h"
40 //#include "save.h"
41 #include "jsector.h"
42 #include "parent.h"
43 #include "reserve.h"
44 
45 //#define FILE_TYPE 1
46 #include "mfile.h"
47 
48 #include "fx_man.h"
49 #include "music.h"
50 
51 #include "weapon.h"
52 #include "cache.h"
53 #include "colormap.h"
54 #include "player.h"
55 
56 #include "saveable.h"
57 
58 //void TimerFunc(task * Task);
59 
60 /*
61 //////////////////////////////////////////////////////////////////////////////
62 TO DO
63 
64 
65 //////////////////////////////////////////////////////////////////////////////
66 */
67 
68 extern int lastUpdate;
69 extern BYTE RedBookSong[40];
70 extern char UserMapName[80];
71 extern char LevelSong[16];
72 extern char SaveGameDescr[10][80];
73 extern int PlayClock;
74 extern short TotalKillable;
75 extern short LevelSecrets;
76 extern short Bunny_Count;
77 extern BOOL NewGame;
78 extern char CacheLastLevel[];
79 extern short PlayingLevel;
80 extern int GodMode;
81 extern int GameVersion;
82 //extern short Zombies;
83 
84 extern BOOL serpwasseen;
85 extern BOOL sumowasseen;
86 extern BOOL zillawasseen;
87 extern short BossSpriteNum[3];
88 
89 VOID ScreenTileLock(void);
90 VOID ScreenTileUnLock(void);
91 
92 int ScreenSaveSetup(PLAYERp pp);
93 VOID ScreenSave(FILE *fout);
94 
95 int ScreenLoadSaveSetup(PLAYERp pp);
96 VOID ScreenLoad(FILE *fin);
97 
98 #define PANEL_SAVE 1
99 #define ANIM_SAVE 1
100 
101 extern SW_PACKET loc;
102 extern char LevelName[20];
103 extern STATE s_NotRestored[];
104 
105 OrgTileListP otlist[] = {&orgwalllist, &orgwalloverlist, &orgsectorceilinglist, &orgsectorfloorlist};
106 
107 int
PanelSpriteToNdx(PLAYERp pp,PANEL_SPRITEp psprite)108 PanelSpriteToNdx(PLAYERp pp, PANEL_SPRITEp psprite)
109     {
110     short ndx = 0;
111     PANEL_SPRITEp psp=NULL, next=NULL;
112 
113     TRAVERSE(&pp->PanelSpriteList, psp, next)
114         {
115         if (psp == psprite)
116             return(ndx);
117 
118         ndx++;
119         }
120 
121     // special case for pointing to the list head
122     if ((LIST)psprite == (LIST)&pp->PanelSpriteList)
123         return(9999);
124 
125     return(-1);
126     }
127 
128 
129 PANEL_SPRITEp
PanelNdxToSprite(PLAYERp pp,int ndx)130 PanelNdxToSprite(PLAYERp pp, int ndx)
131     {
132     short count = 0;
133     PANEL_SPRITEp psp, next;
134 
135     if (ndx == -1)
136         return(NULL);
137 
138     if (ndx == 9999)
139         return((PANEL_SPRITEp)&pp->PanelSpriteList);
140 
141     TRAVERSE(&pp->PanelSpriteList, psp, next)
142         {
143         if (count == ndx)
144             return(psp);
145 
146         count++;
147         }
148 
149     return(NULL);
150     }
151 
SaveSymDataInfo(MFILE fil,void * ptr)152 int SaveSymDataInfo(MFILE fil, void *ptr)
153 {
154 	saveddatasym sym;
155 
156 	if (Saveable_FindDataSym(ptr, &sym)) {
157 		FILE *fp;
158 
159 		fp = fopen("savegame symbols missing.txt", "a");
160 		if (fp) {
161 			fprintf(fp,"data %p\n",ptr);
162 			fclose(fp);
163 		}
164 		return 1;
165 	}
166 
167 	MWRITE(&sym, sizeof(sym), 1, fil);
168 
169 	return 0;
170 }
SaveSymCodeInfo(MFILE fil,void * ptr)171 int SaveSymCodeInfo(MFILE fil, void *ptr)
172 {
173 	savedcodesym sym;
174 
175 	if (Saveable_FindCodeSym(ptr, &sym)) {
176 		FILE *fp;
177 
178 		fp = fopen("savegame symbols missing.txt", "a");
179 		if (fp) {
180 			fprintf(fp,"code %p\n",ptr);
181 			fclose(fp);
182 		}
183 		return 1;
184 	}
185 
186 	MWRITE(&sym, sizeof(sym), 1, fil);
187 
188 	return 0;
189 }
190 
LoadSymDataInfo(MFILE fil,void ** ptr)191 int LoadSymDataInfo(MFILE fil, void **ptr)
192 {
193 	saveddatasym sym;
194 
195 	MREAD(&sym, sizeof(sym), 1, fil);
196 
197 	return Saveable_RestoreDataSym(&sym, ptr);
198 }
LoadSymCodeInfo(MFILE fil,void ** ptr)199 int LoadSymCodeInfo(MFILE fil, void **ptr)
200 {
201 	savedcodesym sym;
202 
203 	MREAD(&sym, sizeof(sym), 1, fil);
204 
205 	return Saveable_RestoreCodeSym(&sym, ptr);
206 }
207 
208 
SaveGame(short save_num)209 int SaveGame(short save_num)
210 {
211     MFILE fil;
212     int i,j;
213     short ndx;
214     SPRITE tsp;
215     SPRITEp sp;
216     PLAYER tp;
217     PLAYERp pp;
218     SECT_USERp sectu;
219     USER tu;
220     USERp u;
221     ANIM tanim;
222     ANIMp a;
223     CHAR code;
224     BYTE data_code;
225     SHORT data_ndx;
226     PANEL_SPRITE tpanel_sprite;
227     PANEL_SPRITEp psp,cur,next;
228     SECTOR_OBJECTp sop;
229     char game_name[80];
230     int cnt = 0, saveisshot=0;
231     OrgTileP otp, next_otp;
232 
233     Saveable_Init();
234 
235     sprintf(game_name,"game%d.sav",save_num);
236     if ((fil = MOPEN_WRITE(game_name)) == MF_ERR)
237         return(-1);
238 
239     MWRITE(&GameVersion,sizeof(GameVersion),1,fil);
240 
241     MWRITE(SaveGameDescr[save_num],sizeof(SaveGameDescr[save_num]),1,fil);
242 
243     MWRITE(&Level,sizeof(Level),1,fil);
244     MWRITE(&Skill,sizeof(Skill),1,fil);
245 
246     ScreenSaveSetup(&Player[myconnectindex]);
247 
248     ScreenSave(fil);
249 
250     ScreenTileUnLock();
251 
252     MWRITE(&numplayers,sizeof(numplayers),1,fil);
253     MWRITE(&myconnectindex,sizeof(myconnectindex),1,fil);
254     MWRITE(&connecthead,sizeof(connecthead),1,fil);
255     MWRITE(connectpoint2,sizeof(connectpoint2),1,fil);
256 
257     //save players info
258     pp = &tp;
259     for (i = 0; i < numplayers; i++)
260         {
261         memcpy(&tp, &Player[i], sizeof(PLAYER));
262 
263         // this does not point to global data - this is allocated link list based
264         // save this inside the structure
265         #if PANEL_SAVE
266         pp->CurWpn = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->CurWpn);
267         for (ndx = 0; ndx < MAX_WEAPONS; ndx++)
268             pp->Wpn[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->Wpn[ndx]);
269         pp->Chops = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->Chops);
270         for (ndx = 0; ndx < MAX_INVENTORY; ndx++)
271             pp->InventorySprite[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->InventorySprite[ndx]);
272         pp->InventorySelectionBox = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->InventorySelectionBox);
273         pp->MiniBarHealthBox = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarHealthBox);
274         pp->MiniBarAmmo = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarAmmo);
275         for (ndx = 0; ndx < (short)SIZ(pp->MiniBarHealthBoxDigit); ndx++)
276             pp->MiniBarHealthBoxDigit[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarHealthBoxDigit[ndx]);
277         for (ndx = 0; ndx < (short)SIZ(pp->MiniBarAmmoDigit); ndx++)
278             pp->MiniBarAmmoDigit[ndx] = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(&Player[i], pp->MiniBarAmmoDigit[ndx]);
279         #endif
280 
281         MWRITE(&tp, sizeof(PLAYER),1,fil);
282 
283         //////
284 
285         saveisshot |= SaveSymDataInfo(fil, pp->remote_sprite);
286         saveisshot |= SaveSymDataInfo(fil, pp->remote.sop_control);
287         saveisshot |= SaveSymDataInfo(fil, pp->sop_remote);
288         saveisshot |= SaveSymDataInfo(fil, pp->sop);
289         saveisshot |= SaveSymDataInfo(fil, pp->hi_sectp);
290         saveisshot |= SaveSymDataInfo(fil, pp->lo_sectp);
291         saveisshot |= SaveSymDataInfo(fil, pp->hi_sp);
292         saveisshot |= SaveSymDataInfo(fil, pp->lo_sp);
293 
294         saveisshot |= SaveSymDataInfo(fil, pp->last_camera_sp);
295         saveisshot |= SaveSymDataInfo(fil, pp->SpriteP);
296         saveisshot |= SaveSymDataInfo(fil, pp->UnderSpriteP);
297 
298         saveisshot |= SaveSymCodeInfo(fil, pp->DoPlayerAction);
299 
300         saveisshot |= SaveSymDataInfo(fil, pp->sop_control);
301         saveisshot |= SaveSymDataInfo(fil, pp->sop_riding);
302         }
303 
304     #if PANEL_SAVE
305     // local copy
306     psp = &tpanel_sprite;
307     for (i = 0; i < numplayers; i++)
308         {
309         unsigned j;
310         pp = &Player[i];
311         ndx = 0;
312 
313         TRAVERSE(&pp->PanelSpriteList, cur, next)
314             {
315             // this is a HEADER
316             MWRITE(&ndx, sizeof(ndx),1,fil);
317 
318             memcpy(psp, cur, sizeof(PANEL_SPRITE));
319 
320             // Panel Sprite - save in structure
321             psp->sibling = (PANEL_SPRITEp)(intptr_t)PanelSpriteToNdx(pp, cur->sibling);
322             MWRITE(psp, sizeof(PANEL_SPRITE),1,fil);
323 
324             saveisshot |= SaveSymDataInfo(fil, psp->PlayerP);
325             saveisshot |= SaveSymDataInfo(fil, psp->State);
326             saveisshot |= SaveSymDataInfo(fil, psp->RetractState);
327             saveisshot |= SaveSymDataInfo(fil, psp->PresentState);
328             saveisshot |= SaveSymDataInfo(fil, psp->ActionState);
329             saveisshot |= SaveSymDataInfo(fil, psp->RestState);
330             saveisshot |= SaveSymCodeInfo(fil, psp->PanelSpriteFunc);
331 
332             for (j = 0; j < SIZ(psp->over); j++)
333                 {
334                 saveisshot |= SaveSymDataInfo(fil, psp->over[j].State);
335                 }
336 
337             ndx++;
338             }
339 
340         // store -1 when done for player
341         ndx = -1;
342         MWRITE(&ndx, sizeof(ndx),1,fil);
343         }
344     #endif
345 
346     MWRITE(&numsectors,sizeof(numsectors),1,fil);
347     MWRITE(sector,sizeof(SECTOR), numsectors, fil);
348 
349     //Sector User information
350     for (i = 0; i < numsectors; i++)
351         {
352         sectu = SectUser[i];
353         ndx = i;
354         if (sectu)
355             {
356             // write header
357             MWRITE(&ndx,sizeof(ndx),1,fil);
358 
359             MWRITE(sectu,sizeof(SECT_USER),1,fil);
360             }
361         else
362             {
363             // write trailer
364             ndx = -1;
365             MWRITE(&ndx,sizeof(ndx),1,fil);
366             }
367         }
368 
369     MWRITE(&numwalls,sizeof(numwalls),1,fil);
370     MWRITE(wall,sizeof(WALL),numwalls,fil);
371 
372     for (i = 0; i < MAXSPRITES; i++)
373         {
374         if (sprite[i].statnum != MAXSTATUS)
375             {
376             MWRITE(&i,sizeof(i),1,fil);
377 
378             MWRITE(&sprite[i],sizeof(SPRITE),1,fil);
379             }
380         }
381     i = -1;
382     MWRITE(&i,sizeof(i),1,fil);
383 
384     MWRITE(headspritesect,sizeof(headspritesect),1,fil);
385     MWRITE(prevspritesect,sizeof(prevspritesect),1,fil);
386     MWRITE(nextspritesect,sizeof(nextspritesect),1,fil);
387     MWRITE(headspritestat,sizeof(headspritestat),1,fil);
388     MWRITE(prevspritestat,sizeof(prevspritestat),1,fil);
389     MWRITE(nextspritestat,sizeof(nextspritestat),1,fil);
390 
391     //User information
392     for (i = 0; i < MAXSPRITES; i++)
393         {
394         ndx = i;
395         if (User[i])
396             {
397             // write header
398             MWRITE(&ndx,sizeof(ndx),1,fil);
399 
400             sp = &sprite[i];
401             memcpy(&tu, User[i], sizeof(USER));
402             u = &tu;
403 
404             MWRITE(u,sizeof(USER),1,fil);
405 
406             if (u->WallShade)
407                 {
408                 MWRITE(u->WallShade,sizeof(*u->WallShade)*u->WallCount,1,fil);
409                 }
410 
411             if (u->rotator)
412                 {
413                 MWRITE(u->rotator,sizeof(*u->rotator),1,fil);
414                 if (u->rotator->origx)
415                     MWRITE(u->rotator->origx,sizeof(*u->rotator->origx)*u->rotator->num_walls,1,fil);
416                 if (u->rotator->origy)
417                     MWRITE(u->rotator->origy,sizeof(*u->rotator->origy)*u->rotator->num_walls,1,fil);
418                 }
419 
420             saveisshot |= SaveSymDataInfo(fil, u->WallP);
421             saveisshot |= SaveSymDataInfo(fil, u->State);
422             saveisshot |= SaveSymDataInfo(fil, u->Rot);
423             saveisshot |= SaveSymDataInfo(fil, u->StateStart);
424             saveisshot |= SaveSymDataInfo(fil, u->StateEnd);
425             saveisshot |= SaveSymDataInfo(fil, u->StateFallOverride);
426             saveisshot |= SaveSymCodeInfo(fil, u->ActorActionFunc);
427             saveisshot |= SaveSymDataInfo(fil, u->ActorActionSet);
428             saveisshot |= SaveSymDataInfo(fil, u->Personality);
429             saveisshot |= SaveSymDataInfo(fil, u->Attrib);
430             saveisshot |= SaveSymDataInfo(fil, u->sop_parent);
431             saveisshot |= SaveSymDataInfo(fil, u->hi_sectp);
432             saveisshot |= SaveSymDataInfo(fil, u->lo_sectp);
433             saveisshot |= SaveSymDataInfo(fil, u->hi_sp);
434             saveisshot |= SaveSymDataInfo(fil, u->lo_sp);
435             saveisshot |= SaveSymDataInfo(fil, u->SpriteP);
436             saveisshot |= SaveSymDataInfo(fil, u->PlayerP);
437             saveisshot |= SaveSymDataInfo(fil, u->tgt_sp);
438             }
439         }
440     ndx = -1;
441     MWRITE(&ndx,sizeof(ndx),1,fil);
442 
443     //
444     // Sector object
445     //
446 
447     MWRITE(SectorObject, sizeof(SectorObject),1,fil);
448 
449     for (ndx = 0; ndx < (short)SIZ(SectorObject); ndx++)
450         {
451         sop = &SectorObject[ndx];
452 
453         saveisshot |= SaveSymCodeInfo(fil, sop->PreMoveAnimator);
454         saveisshot |= SaveSymCodeInfo(fil, sop->PostMoveAnimator);
455         saveisshot |= SaveSymCodeInfo(fil, sop->Animator);
456         saveisshot |= SaveSymDataInfo(fil, sop->controller);
457         saveisshot |= SaveSymDataInfo(fil, sop->sp_child);
458         }
459 
460 
461     MWRITE(SineWaveFloor, sizeof(SineWaveFloor),1,fil);
462     MWRITE(SineWall, sizeof(SineWall),1,fil);
463     MWRITE(SpringBoard, sizeof(SpringBoard),1,fil);
464     //MWRITE(Rotate, sizeof(Rotate),1,fil);
465     //MWRITE(DoorAutoClose, sizeof(DoorAutoClose),1,fil);
466     MWRITE(&x_min_bound, sizeof(x_min_bound),1,fil);
467     MWRITE(&y_min_bound, sizeof(y_min_bound),1,fil);
468     MWRITE(&x_max_bound, sizeof(x_max_bound),1,fil);
469     MWRITE(&y_max_bound, sizeof(y_max_bound),1,fil);
470 
471 
472     MWRITE(Track, sizeof(Track),1,fil);
473     for (i = 0; i < MAX_TRACKS; i++)
474         {
475         ASSERT(Track[i].TrackPoint);
476         if (Track[i].NumPoints == 0)
477             MWRITE(Track[i].TrackPoint, sizeof(TRACK_POINT),1,fil);
478         else
479             MWRITE(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil);
480         }
481 
482     MWRITE(&vel,sizeof(vel),1,fil);
483     MWRITE(&svel,sizeof(svel),1,fil);
484     MWRITE(&angvel,sizeof(angvel),1,fil);
485 
486     MWRITE(&loc,sizeof(loc),1,fil);
487     //MWRITE(&oloc,sizeof(oloc),1,fil);
488     //MWRITE(&fsync,sizeof(fsync),1,fil);
489 
490     MWRITE(LevelName,sizeof(LevelName),1,fil);
491     MWRITE(&screenpeek,sizeof(screenpeek),1,fil);
492     MWRITE(&totalsynctics,sizeof(totalsynctics),1,fil);
493 
494     // do all sector manipulation structures
495 
496     #if ANIM_SAVE
497     #if 1
498     MWRITE(&AnimCnt,sizeof(AnimCnt),1,fil);
499 
500     for(i = 0, a = &tanim; i < AnimCnt; i++)
501         {
502         intptr_t offset;
503         memcpy(a,&Anim[i],sizeof(ANIM));
504 
505         // maintain compatibility with sinking boat which points to user data
506         for (j=0; j<MAXSPRITES; j++)
507             {
508             if (User[j])
509                 {
510                 BYTEp bp = (BYTEp)User[j];
511 
512                 if ((BYTEp)a->ptr >= bp && (BYTEp)a->ptr < bp + sizeof(USER))
513                     {
514                     offset = (intptr_t)((BYTEp)a->ptr - bp); // offset from user data
515                     a->ptr = (int*)-2;
516                     break;
517                     }
518                 }
519             }
520 
521         if ((intptr_t)a->ptr != -2)
522             {
523             for (j=0; j<numsectors; j++)
524                 {
525                 if (SectUser[j])
526                     {
527                     BYTEp bp = (BYTEp)SectUser[j];
528 
529                     if ((BYTEp)a->ptr >= bp && (BYTEp)a->ptr < bp + sizeof(SECT_USER))
530                         {
531                         offset = (intptr_t)((BYTEp)a->ptr - bp); // offset from user data
532                         a->ptr = (int*)-3;
533                         break;
534                         }
535                     }
536                 }
537             }
538         MWRITE(a,sizeof(ANIM),1,fil);
539 
540         if ((intptr_t)a->ptr == -2 || (intptr_t)a->ptr == -3)
541             {
542             MWRITE(&j, sizeof(j),1,fil);
543             MWRITE(&offset, sizeof(offset),1,fil);
544             }
545         else
546             {
547             saveisshot |= SaveSymDataInfo(fil, a->ptr);
548             }
549 
550         saveisshot |= SaveSymCodeInfo(fil, a->callback);
551         saveisshot |= SaveSymDataInfo(fil, a->callbackdata);
552         }
553 
554     #else
555     ndx = 0;
556     for(i = AnimCnt - 1, a = &tanim; i >= 0; i--)
557         {
558         // write header
559         MWRITE(&ndx,sizeof(ndx),1,fil);
560 
561         memcpy(a,&Anim[i],sizeof(ANIM));
562         MWRITE(a,sizeof(ANIM),1,fil);
563 
564         saveisshot |= SaveSymDataInfo(fil, a->ptr);
565         saveisshot |= SaveSymCodeInfo(fil, a->callback);
566         saveisshot |= SaveSymDataInfo(fil, a->callbackdata);
567 
568         ndx++;
569         }
570 
571     // write trailer
572     ndx = -1;
573     MWRITE(&ndx,sizeof(ndx),1,fil);
574     #endif
575     #endif
576 
577     MWRITE(&totalclock,sizeof(totalclock),1,fil);
578     MWRITE(&numframes,sizeof(numframes),1,fil);
579     MWRITE(&randomseed,sizeof(randomseed),1,fil);
580     MWRITE(&numpalookups,sizeof(numpalookups),1,fil);
581 
582     MWRITE(&NormalVisibility,sizeof(NormalVisibility),1,fil);
583     MWRITE(&visibility,sizeof(visibility),1,fil);
584     MWRITE(&parallaxtype,sizeof(parallaxtype),1,fil);
585     MWRITE(&parallaxyoffs,sizeof(parallaxyoffs),1,fil);
586     MWRITE(pskyoff,sizeof(pskyoff),1,fil);
587     MWRITE(&pskybits,sizeof(pskybits),1,fil);
588 
589     MWRITE(&BorderInfo,sizeof(BorderInfo),1,fil);
590     MWRITE(&MoveSkip2,sizeof(MoveSkip2),1,fil);
591     MWRITE(&MoveSkip4,sizeof(MoveSkip4),1,fil);
592     MWRITE(&MoveSkip8,sizeof(MoveSkip8),1,fil);
593 
594     // long interpolations
595     MWRITE(&numinterpolations,sizeof(numinterpolations),1,fil);
596     MWRITE(&startofdynamicinterpolations,sizeof(startofdynamicinterpolations),1,fil);
597     MWRITE(oldipos,sizeof(oldipos),1,fil);
598     MWRITE(bakipos,sizeof(bakipos),1,fil);
599     for (i = numinterpolations - 1; i >= 0; i--)
600         saveisshot |= SaveSymDataInfo(fil, curipos[i]);
601 
602     // short interpolations
603     MWRITE(&short_numinterpolations,sizeof(short_numinterpolations),1,fil);
604     MWRITE(&short_startofdynamicinterpolations,sizeof(short_startofdynamicinterpolations),1,fil);
605     MWRITE(short_oldipos,sizeof(short_oldipos),1,fil);
606     MWRITE(short_bakipos,sizeof(short_bakipos),1,fil);
607     for (i = short_numinterpolations - 1; i >= 0; i--)
608         saveisshot |= SaveSymDataInfo(fil, short_curipos[i]);
609 
610 
611     // parental lock
612     for (i = 0; i < (int)SIZ(otlist); i++)
613         {
614         ndx = 0;
615         TRAVERSE(otlist[i], otp, next_otp)
616             {
617             MWRITE(&ndx,sizeof(ndx),1,fil);
618             MWRITE(&otp,sizeof(*otp),1,fil);
619             ndx++;
620             }
621         ndx = -1;
622         MWRITE(&ndx, sizeof(ndx),1,fil);
623         }
624 
625     // mirror
626     MWRITE(mirror,sizeof(mirror),1,fil);
627     MWRITE(&mirrorcnt,sizeof(mirrorcnt),1,fil);
628     MWRITE(&mirrorinview,sizeof(mirrorinview),1,fil);
629 
630     // queue
631     MWRITE(&StarQueueHead,sizeof(StarQueueHead),1,fil);
632     MWRITE(StarQueue,sizeof(StarQueue),1,fil);
633     MWRITE(&HoleQueueHead,sizeof(HoleQueueHead),1,fil);
634     MWRITE(HoleQueue,sizeof(HoleQueue),1,fil);
635     MWRITE(&WallBloodQueueHead,sizeof(WallBloodQueueHead),1,fil);
636     MWRITE(WallBloodQueue,sizeof(WallBloodQueue),1,fil);
637     MWRITE(&FloorBloodQueueHead,sizeof(FloorBloodQueueHead),1,fil);
638     MWRITE(FloorBloodQueue,sizeof(FloorBloodQueue),1,fil);
639     MWRITE(&GenericQueueHead,sizeof(GenericQueueHead),1,fil);
640     MWRITE(GenericQueue,sizeof(GenericQueue),1,fil);
641     MWRITE(&LoWangsQueueHead,sizeof(LoWangsQueueHead),1,fil);
642     MWRITE(LoWangsQueue,sizeof(LoWangsQueue),1,fil);
643 
644     MWRITE(&PlayClock,sizeof(PlayClock),1,fil);
645     MWRITE(&TotalKillable,sizeof(TotalKillable),1,fil);
646 
647     // game settings
648     MWRITE(&gNet,sizeof(gNet),1,fil);
649 
650     MWRITE(LevelSong,sizeof(LevelSong),1,fil);
651 
652     MWRITE(palette,sizeof(palette),1,fil);
653     MWRITE(palette_data,sizeof(palette_data),1,fil);
654     MWRITE(&gs,sizeof(gs),1,fil);
655     MWRITE(picanm,sizeof(picanm),1,fil);
656 
657     MWRITE(&LevelSecrets,sizeof(LevelSecrets),1,fil);
658 
659     MWRITE(show2dwall,sizeof(show2dwall),1,fil);
660     MWRITE(show2dsprite,sizeof(show2dsprite),1,fil);
661     MWRITE(show2dsector,sizeof(show2dsector),1,fil);
662 
663     MWRITE(&Bunny_Count,sizeof(Bunny_Count),1,fil);
664 
665     MWRITE(UserMapName,sizeof(UserMapName),1,fil);
666     MWRITE(&GodMode,sizeof(GodMode),1,fil);
667 
668     MWRITE(&serpwasseen, sizeof(serpwasseen), 1, fil);
669     MWRITE(&sumowasseen, sizeof(sumowasseen), 1, fil);
670     MWRITE(&zillawasseen, sizeof(zillawasseen), 1, fil);
671     MWRITE(BossSpriteNum, sizeof(BossSpriteNum), 1, fil);
672     //MWRITE(&Zombies, sizeof(Zombies), 1, fil);
673 
674     MCLOSE(fil);
675 
676     ////DSPRINTF(ds, "done saving");
677     //MONO_PRINT(ds);
678 
679     if (saveisshot)
680 	CON_Message("There was a problem saving. See \"Save Help\" section of release notes.");
681 
682     return(saveisshot?-1:0);
683 }
684 
LoadGameFullHeader(short save_num,char * descr,short * level,short * skill)685 int LoadGameFullHeader(short save_num, char *descr, short *level, short *skill)
686 {
687     MFILE fil;
688     char game_name[80];
689     short tile;
690     int ver;
691 
692     sprintf(game_name,"game%d.sav",save_num);
693     if ((fil = MOPEN_READ(game_name)) == MF_ERR)
694         return(-1);
695 
696     MREAD(&ver,sizeof(ver),1,fil);
697     if (ver != GameVersion) {
698 	MCLOSE(fil);
699 	return -1;
700     }
701 
702     MREAD(descr, sizeof(SaveGameDescr[0]), 1,fil);
703 
704     MREAD(level,sizeof(*level),1,fil);
705     MREAD(skill,sizeof(*skill),1,fil);
706 
707     tile = ScreenLoadSaveSetup(Player + myconnectindex);
708     ScreenLoad(fil);
709 
710     MCLOSE(fil);
711 
712     return(tile);
713 }
714 
LoadGameDescr(short save_num,char * descr)715 void LoadGameDescr(short save_num, char *descr)
716 {
717     MFILE fil;
718     char game_name[80];
719     short tile;
720     int ver;
721 
722     sprintf(game_name,"game%d.sav",save_num);
723     if ((fil = MOPEN_READ(game_name)) == MF_ERR)
724         return;
725 
726     MREAD(&ver,sizeof(ver),1,fil);
727     if (ver != GameVersion) {
728 	MCLOSE(fil);
729 	return;
730     }
731 
732     MREAD(descr, sizeof(SaveGameDescr[0]),1,fil);
733 
734     MCLOSE(fil);
735 }
736 
737 
LoadGame(short save_num)738 int LoadGame(short save_num)
739 {
740     MFILE fil;
741     int i,j,saveisshot=0;
742     short ndx,SpriteNum,sectnum;
743     PLAYERp pp = NULL;
744     SPRITEp sp;
745     USERp u;
746     SECTOR_OBJECTp sop;
747     SECT_USERp sectu;
748     CHAR code;
749     ANIMp a;
750     BYTE data_code;
751     SHORT data_ndx;
752     PANEL_SPRITEp psp,next,cur;
753     PANEL_SPRITE tpanel_sprite;
754     char game_name[80];
755     OrgTileP otp, next_otp;
756 
757     int RotNdx;
758     int StateStartNdx;
759     int StateNdx;
760     int StateEndNdx;
761     extern BOOL InMenuLevel;
762 
763     Saveable_Init();
764 
765     sprintf(game_name,"game%d.sav",save_num);
766     if ((fil = MOPEN_READ(game_name)) == MF_ERR)
767         return(-1);
768 
769     MREAD(&i,sizeof(i),1,fil);
770     if (i != GameVersion) {
771 	MCLOSE(fil);
772 	return -1;
773     }
774 
775     // Don't terminate until you've made sure conditions are valid for loading.
776     if (InMenuLevel)
777         StopSong();
778     else
779         TerminateLevel();
780     Terminate3DSounds();
781 
782     Terminate3DSounds();
783 
784     MREAD(SaveGameDescr[save_num], sizeof(SaveGameDescr[save_num]),1,fil);
785 
786     MREAD(&Level,sizeof(Level),1,fil);
787     MREAD(&Skill,sizeof(Skill),1,fil);
788 
789     ScreenLoadSaveSetup(Player + myconnectindex);
790     ScreenLoad(fil);
791     ScreenTileUnLock();
792 
793     MREAD(&numplayers, sizeof(numplayers),1,fil);
794     MREAD(&myconnectindex,sizeof(myconnectindex),1,fil);
795     MREAD(&connecthead,sizeof(connecthead),1,fil);
796     MREAD(connectpoint2,sizeof(connectpoint2),1,fil);
797 
798     //save players
799     //MREAD(Player,sizeof(PLAYER), numplayers,fil);
800 
801     //save players info
802     for (i = 0; i < numplayers; i++)
803         {
804         pp = &Player[i];
805 
806         MREAD(pp, sizeof(*pp), 1, fil);
807 
808         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->remote_sprite);
809         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->remote.sop_control);
810         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->sop_remote);
811         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->sop);
812 
813         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->hi_sectp);
814         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->lo_sectp);
815 
816         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->hi_sp);
817         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->lo_sp);
818 
819         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->last_camera_sp);
820         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->SpriteP);
821         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->UnderSpriteP);
822         saveisshot |= LoadSymCodeInfo(fil, (void**)&pp->DoPlayerAction);
823         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->sop_control);
824         saveisshot |= LoadSymDataInfo(fil, (void**)&pp->sop_riding);
825 	if (saveisshot) { MCLOSE(fil); return -1; }
826         }
827 
828 
829     #if PANEL_SAVE
830     for (i = 0; i < numplayers; i++)
831         {
832         int j;
833         pp = &Player[i];
834 
835         INITLIST(&pp->PanelSpriteList);
836 
837         while (TRUE)
838             {
839             MREAD(&ndx, sizeof(ndx),1,fil);
840 
841             if (ndx == -1)
842                 break;
843 
844             psp = CallocMem(sizeof(PANEL_SPRITE), 1);
845             ASSERT(psp);
846 
847             MREAD(psp, sizeof(PANEL_SPRITE),1,fil);
848             INSERT_TAIL(&pp->PanelSpriteList,psp);
849 
850             saveisshot |= LoadSymDataInfo(fil, (void**)&psp->PlayerP);
851             saveisshot |= LoadSymDataInfo(fil, (void**)&psp->State);
852             saveisshot |= LoadSymDataInfo(fil, (void**)&psp->RetractState);
853             saveisshot |= LoadSymDataInfo(fil, (void**)&psp->PresentState);
854             saveisshot |= LoadSymDataInfo(fil, (void**)&psp->ActionState);
855             saveisshot |= LoadSymDataInfo(fil, (void**)&psp->RestState);
856             saveisshot |= LoadSymCodeInfo(fil, (void**)&psp->PanelSpriteFunc);
857 	    if (saveisshot) { MCLOSE(fil); return -1; }
858 
859             for (j = 0; j < (int)SIZ(psp->over); j++)
860                 {
861                 saveisshot |= LoadSymDataInfo(fil, (void**)&psp->over[j].State);
862 		if (saveisshot) { MCLOSE(fil); return -1; }
863                 }
864 
865             }
866         }
867     #endif
868 
869     MREAD(&numsectors,sizeof(numsectors),1,fil);
870     MREAD(sector,sizeof(SECTOR),numsectors,fil);
871 
872     //Sector User information
873     for (i = 0; i < numsectors; i++)
874         {
875         MREAD(&sectnum,sizeof(sectnum),1,fil);
876         if (sectnum != -1)
877             {
878             SectUser[sectnum] = sectu = (SECT_USERp)CallocMem(sizeof(SECT_USER), 1);
879             MREAD(sectu,sizeof(SECT_USER),1,fil);
880             }
881         }
882 
883     MREAD(&numwalls,sizeof(numwalls),1,fil);
884     MREAD(wall,sizeof(WALL),numwalls,fil);
885 
886     //Store all sprites to preserve indeces
887     MREAD(&i, sizeof(i),1,fil);
888     while(i != -1)
889         {
890         MREAD(&sprite[i], sizeof(SPRITE),1,fil);
891         MREAD(&i, sizeof(i),1,fil);
892         }
893 
894     MREAD(headspritesect,sizeof(headspritesect),1,fil);
895     MREAD(prevspritesect,sizeof(prevspritesect),1,fil);
896     MREAD(nextspritesect,sizeof(nextspritesect),1,fil);
897     MREAD(headspritestat,sizeof(headspritestat),1,fil);
898     MREAD(prevspritestat,sizeof(prevspritestat),1,fil);
899     MREAD(nextspritestat,sizeof(nextspritestat),1,fil);
900 
901     //User information
902     memset(User, 0, sizeof(User));
903 
904     MREAD(&SpriteNum, sizeof(SpriteNum),1,fil);
905     while(SpriteNum != -1)
906         {
907         sp = &sprite[SpriteNum];
908         User[SpriteNum] = u = (USERp)CallocMem(sizeof(USER), 1);
909         MREAD(u,sizeof(USER),1,fil);
910 
911         if (u->WallShade)
912             {
913             u->WallShade = CallocMem(u->WallCount * sizeof(*u->WallShade), 1);
914             MREAD(u->WallShade,sizeof(*u->WallShade)*u->WallCount,1,fil);
915             }
916 
917         if (u->rotator)
918             {
919             u->rotator = CallocMem(sizeof(*u->rotator), 1);
920             MREAD(u->rotator,sizeof(*u->rotator),1,fil);
921 
922             if (u->rotator->origx)
923                 {
924                 u->rotator->origx = CallocMem(u->rotator->num_walls * sizeof(*u->rotator->origx), 1);
925                 MREAD(u->rotator->origx,sizeof(*u->rotator->origx)*u->rotator->num_walls,1,fil);
926                 }
927             if (u->rotator->origy)
928                 {
929                 u->rotator->origy = CallocMem(u->rotator->num_walls * sizeof(*u->rotator->origy), 1);
930                 MREAD(u->rotator->origy,sizeof(*u->rotator->origy)*u->rotator->num_walls,1,fil);
931                 }
932             }
933 
934         saveisshot |= LoadSymDataInfo(fil, (void**)&u->WallP);
935         saveisshot |= LoadSymDataInfo(fil, (void**)&u->State);
936         saveisshot |= LoadSymDataInfo(fil, (void**)&u->Rot);
937         saveisshot |= LoadSymDataInfo(fil, (void**)&u->StateStart);
938         saveisshot |= LoadSymDataInfo(fil, (void**)&u->StateEnd);
939         saveisshot |= LoadSymDataInfo(fil, (void**)&u->StateFallOverride);
940         saveisshot |= LoadSymCodeInfo(fil, (void**)&u->ActorActionFunc);
941         saveisshot |= LoadSymDataInfo(fil, (void**)&u->ActorActionSet);
942         saveisshot |= LoadSymDataInfo(fil, (void**)&u->Personality);
943         saveisshot |= LoadSymDataInfo(fil, (void**)&u->Attrib);
944         saveisshot |= LoadSymDataInfo(fil, (void**)&u->sop_parent);
945         saveisshot |= LoadSymDataInfo(fil, (void**)&u->hi_sectp);
946         saveisshot |= LoadSymDataInfo(fil, (void**)&u->lo_sectp);
947         saveisshot |= LoadSymDataInfo(fil, (void**)&u->hi_sp);
948         saveisshot |= LoadSymDataInfo(fil, (void**)&u->lo_sp);
949         saveisshot |= LoadSymDataInfo(fil, (void**)&u->SpriteP);
950         saveisshot |= LoadSymDataInfo(fil, (void**)&u->PlayerP);
951         saveisshot |= LoadSymDataInfo(fil, (void**)&u->tgt_sp);
952 	if (saveisshot) { MCLOSE(fil); return -1; }
953 
954         MREAD(&SpriteNum,sizeof(SpriteNum),1,fil);
955         }
956 
957     MREAD(SectorObject, sizeof(SectorObject),1,fil);
958 
959     for (ndx = 0; ndx < (short)SIZ(SectorObject); ndx++)
960         {
961         sop = &SectorObject[ndx];
962 
963         saveisshot |= LoadSymCodeInfo(fil, (void**)&sop->PreMoveAnimator);
964         saveisshot |= LoadSymCodeInfo(fil, (void**)&sop->PostMoveAnimator);
965         saveisshot |= LoadSymCodeInfo(fil, (void**)&sop->Animator);
966         saveisshot |= LoadSymDataInfo(fil, (void**)&sop->controller);
967         saveisshot |= LoadSymDataInfo(fil, (void**)&sop->sp_child);
968 	if (saveisshot) { MCLOSE(fil); return -1; }
969         }
970 
971     MREAD(SineWaveFloor, sizeof(SineWaveFloor),1,fil);
972     MREAD(SineWall, sizeof(SineWall),1,fil);
973     MREAD(SpringBoard, sizeof(SpringBoard),1,fil);
974     //MREAD(Rotate, sizeof(Rotate),1,fil);
975     //MREAD(DoorAutoClose, sizeof(DoorAutoClose),1,fil);
976     MREAD(&x_min_bound, sizeof(x_min_bound),1,fil);
977     MREAD(&y_min_bound, sizeof(y_min_bound),1,fil);
978     MREAD(&x_max_bound, sizeof(x_max_bound),1,fil);
979     MREAD(&y_max_bound, sizeof(y_max_bound),1,fil);
980 
981     MREAD(Track, sizeof(Track),1,fil);
982     for (i = 0; i < MAX_TRACKS; i++)
983         {
984         if (Track[i].NumPoints == 0)
985             {
986             Track[i].TrackPoint = (TRACK_POINTp)CallocMem(sizeof(TRACK_POINT), 1);
987             MREAD(Track[i].TrackPoint, sizeof(TRACK_POINT),1,fil);
988             }
989         else
990             {
991             Track[i].TrackPoint = (TRACK_POINTp)CallocMem(Track[i].NumPoints * sizeof(TRACK_POINT), 1);
992             MREAD(Track[i].TrackPoint, Track[i].NumPoints * sizeof(TRACK_POINT),1,fil);
993             }
994         }
995 
996     MREAD(&vel,sizeof(vel),1,fil);
997     MREAD(&svel,sizeof(svel),1,fil);
998     MREAD(&angvel,sizeof(angvel),1,fil);
999 
1000     MREAD(&loc,sizeof(loc),1,fil);
1001 
1002     MREAD(LevelName,sizeof(LevelName),1,fil);
1003     MREAD(&screenpeek,sizeof(screenpeek),1,fil);
1004     MREAD(&totalsynctics,sizeof(totalsynctics),1,fil);  // same as kens lockclock
1005 
1006     // do all sector manipulation structures
1007 
1008     #if ANIM_SAVE
1009     #if 1
1010     MREAD(&AnimCnt,sizeof(AnimCnt),1,fil);
1011 
1012     for(i = 0; i < AnimCnt; i++)
1013         {
1014         a = &Anim[i];
1015         MREAD(a,sizeof(ANIM),1,fil);
1016 
1017         if ((intptr_t)a->ptr == -2)
1018             {
1019             // maintain compatibility with sinking boat which points to user data
1020             int offset;
1021             MREAD(&j, sizeof(j),1,fil);
1022             MREAD(&offset, sizeof(offset),1,fil);
1023             a->ptr = (int*)(((char *)User[j]) + offset);
1024             }
1025         else
1026         if ((intptr_t)a->ptr == -3)
1027             {
1028             // maintain compatibility with sinking boat which points to user data
1029             int offset;
1030             MREAD(&j, sizeof(j),1,fil);
1031             MREAD(&offset, sizeof(offset),1,fil);
1032             a->ptr = (int*)(((char *)SectUser[j]) + offset);
1033             }
1034         else
1035             {
1036             saveisshot |= LoadSymDataInfo(fil, (void**)&a->ptr);
1037             }
1038 
1039         saveisshot |= LoadSymCodeInfo(fil, (void**)&a->callback);
1040         saveisshot |= LoadSymDataInfo(fil, (void**)&a->callbackdata);
1041 	if (saveisshot) { MCLOSE(fil); return -1; }
1042         }
1043     #else
1044     AnimCnt = 0;
1045     for(i = MAXANIM - 1; i >= 0; i--)
1046         {
1047         a = &Anim[i];
1048 
1049         MREAD(&ndx,sizeof(ndx),1,fil);
1050 
1051         if (ndx == -1)
1052             break;
1053 
1054         AnimCnt++;
1055 
1056         MREAD(a,sizeof(ANIM),1,fil);
1057 
1058         saveisshot |= LoadSymDataInfo(fil, (void**)&a->ptr);
1059         saveisshot |= LoadSymCodeInfo(fil, (void**)&a->callback);
1060         saveisshot |= LoadSymDataInfo(fil, (void**)&a->callbackdata);
1061 	if (saveisshot) { MCLOSE(fil); return -1; }
1062         }
1063     #endif
1064     #endif
1065 
1066     MREAD(&totalclock,sizeof(totalclock),1,fil);
1067     MREAD(&numframes,sizeof(numframes),1,fil);
1068     MREAD(&randomseed,sizeof(randomseed),1,fil);
1069     MREAD(&numpalookups,sizeof(numpalookups),1,fil);
1070 
1071     MREAD(&NormalVisibility,sizeof(NormalVisibility),1,fil);
1072     MREAD(&visibility,sizeof(visibility),1,fil);
1073     MREAD(&parallaxtype,sizeof(parallaxtype),1,fil);
1074     MREAD(&parallaxyoffs,sizeof(parallaxyoffs),1,fil);
1075     MREAD(pskyoff,sizeof(pskyoff),1,fil);
1076     MREAD(&pskybits,sizeof(pskybits),1,fil);
1077 
1078     MREAD(&BorderInfo,sizeof(BorderInfo),1,fil);
1079     MREAD(&MoveSkip2,sizeof(MoveSkip2),1,fil);
1080     MREAD(&MoveSkip4,sizeof(MoveSkip4),1,fil);
1081     MREAD(&MoveSkip8,sizeof(MoveSkip8),1,fil);
1082 
1083     // long interpolations
1084     MREAD(&numinterpolations,sizeof(numinterpolations),1,fil);
1085     MREAD(&startofdynamicinterpolations,sizeof(startofdynamicinterpolations),1,fil);
1086     MREAD(oldipos,sizeof(oldipos),1,fil);
1087     MREAD(bakipos,sizeof(bakipos),1,fil);
1088     for (i = numinterpolations - 1; i >= 0; i--)
1089         saveisshot |= LoadSymDataInfo(fil, (void**)&curipos[i]);
1090     if (saveisshot) { MCLOSE(fil); return -1; }
1091 
1092     // short interpolations
1093     MREAD(&short_numinterpolations,sizeof(short_numinterpolations),1,fil);
1094     MREAD(&short_startofdynamicinterpolations,sizeof(short_startofdynamicinterpolations),1,fil);
1095     MREAD(short_oldipos,sizeof(short_oldipos),1,fil);
1096     MREAD(short_bakipos,sizeof(short_bakipos),1,fil);
1097     for (i = short_numinterpolations - 1; i >= 0; i--)
1098         saveisshot |= LoadSymDataInfo(fil, (void**)&short_curipos[i]);
1099     if (saveisshot) { MCLOSE(fil); return -1; }
1100 
1101     // parental lock
1102     for (i = 0; i < (int)SIZ(otlist); i++)
1103         {
1104         INITLIST(otlist[i]);
1105 
1106         while (TRUE)
1107             {
1108             MREAD(&ndx, sizeof(ndx),1,fil);
1109 
1110             if (ndx == -1)
1111                 break;
1112 
1113             otp = CallocMem(sizeof(*otp), 1);
1114             ASSERT(otp);
1115 
1116             MREAD(otp, sizeof(*otp),1,fil);
1117             INSERT_TAIL(otlist[i],otp);
1118             }
1119         }
1120 
1121     // mirror
1122     MREAD(mirror,sizeof(mirror),1,fil);
1123     MREAD(&mirrorcnt,sizeof(mirrorcnt),1,fil);
1124     MREAD(&mirrorinview,sizeof(mirrorinview),1,fil);
1125 
1126     // queue
1127     MREAD(&StarQueueHead,sizeof(StarQueueHead),1,fil);
1128     MREAD(StarQueue,sizeof(StarQueue),1,fil);
1129     MREAD(&HoleQueueHead,sizeof(HoleQueueHead),1,fil);
1130     MREAD(HoleQueue,sizeof(HoleQueue),1,fil);
1131     MREAD(&WallBloodQueueHead,sizeof(WallBloodQueueHead),1,fil);
1132     MREAD(WallBloodQueue,sizeof(WallBloodQueue),1,fil);
1133     MREAD(&FloorBloodQueueHead,sizeof(FloorBloodQueueHead),1,fil);
1134     MREAD(FloorBloodQueue,sizeof(FloorBloodQueue),1,fil);
1135     MREAD(&GenericQueueHead,sizeof(GenericQueueHead),1,fil);
1136     MREAD(GenericQueue,sizeof(GenericQueue),1,fil);
1137     MREAD(&LoWangsQueueHead,sizeof(LoWangsQueueHead),1,fil);
1138     MREAD(LoWangsQueue,sizeof(LoWangsQueue),1,fil);
1139 
1140     // init timing vars before PlayClock is read
1141     MREAD(&PlayClock,sizeof(PlayClock),1,fil);
1142     MREAD(&TotalKillable,sizeof(TotalKillable),1,fil);
1143 
1144     // game settings
1145     MREAD(&gNet,sizeof(gNet),1,fil);
1146 
1147     MREAD(LevelSong,sizeof(LevelSong),1,fil);
1148 
1149     MREAD(palette,sizeof(palette),1,fil);
1150     MREAD(palette_data,sizeof(palette_data),1,fil);
1151 
1152     {
1153     BOOL AmbBak = gs.Ambient;
1154     BOOL MusicBak = gs.MusicOn;
1155     BOOL FxBak = gs.FxOn;
1156     short SndVolBak = gs.SoundVolume;
1157     short MusVolBak = gs.MusicVolume;
1158     MREAD(&gs,sizeof(gs),1,fil);
1159     gs.MusicOn = MusicBak;
1160     gs.FxOn = FxBak;
1161     gs.Ambient = AmbBak;
1162     gs.SoundVolume = SndVolBak;
1163     gs.MusicVolume = MusVolBak;
1164     }
1165 
1166 
1167     //COVERsetbrightness(gs.Brightness,(char *)palette_data);
1168 
1169     MREAD(picanm,sizeof(picanm),1,fil);
1170 
1171     MREAD(&LevelSecrets,sizeof(LevelSecrets),1,fil);
1172 
1173     MREAD(show2dwall,sizeof(show2dwall),1,fil);
1174     MREAD(show2dsprite,sizeof(show2dsprite),1,fil);
1175     MREAD(show2dsector,sizeof(show2dsector),1,fil);
1176 
1177     MREAD(&Bunny_Count,sizeof(Bunny_Count),1,fil);
1178 
1179     MREAD(UserMapName,sizeof(UserMapName),1,fil);
1180     MREAD(&GodMode,sizeof(GodMode),1,fil);
1181 
1182     MREAD(&serpwasseen, sizeof(serpwasseen), 1, fil);
1183     MREAD(&sumowasseen, sizeof(sumowasseen), 1, fil);
1184     MREAD(&zillawasseen, sizeof(zillawasseen), 1, fil);
1185     MREAD(BossSpriteNum, sizeof(BossSpriteNum), 1, fil);
1186     //MREAD(&Zombies, sizeof(Zombies), 1, fil);
1187 
1188     MCLOSE(fil);
1189 
1190 
1191     //!!IMPORTANT - this POST stuff will not work here now becaus it does actual reads
1192 
1193 
1194     //
1195     // POST processing of info MREAD in
1196     //
1197 
1198     #if PANEL_SAVE
1199     for (i = 0; i < numplayers; i++)
1200         {
1201         pp = &Player[i];
1202         TRAVERSE(&pp->PanelSpriteList, psp, next)
1203             {
1204             // dont need to set Next and Prev this was done
1205             // when sprites were inserted
1206 
1207             // sibling is the only PanelSprite (malloced ptr) in the PanelSprite struct
1208             psp->sibling = PanelNdxToSprite(pp, (int)(intptr_t)psp->sibling);
1209             }
1210         }
1211     #endif
1212 
1213     if (Bstrcasecmp(CacheLastLevel, LevelName) != 0)
1214         {
1215         SetupPreCache();
1216         DoTheCache();
1217         }
1218 
1219     // what is this for? don't remember
1220     totalclock = totalsynctics;
1221     ototalclock = totalsynctics;
1222 
1223     // this is ok - just duplicating sector list with pointers
1224     for (sop = SectorObject; sop < &SectorObject[SIZ(SectorObject)]; sop++)
1225         {
1226         for (i = 0; i < sop->num_sectors; i++)
1227             sop->sectp[i] = &sector[sop->sector[i]];
1228         }
1229 
1230     //!!Again this will not work here
1231     //restore players info
1232     for (i = 0; i < numplayers; i++)
1233         {
1234         #if PANEL_SAVE
1235         pp->CurWpn = PanelNdxToSprite(pp, (int)(intptr_t)pp->CurWpn);
1236 
1237         for (ndx = 0; ndx < MAX_WEAPONS; ndx++)
1238             pp->Wpn[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->Wpn[ndx]);
1239 
1240         for (ndx = 0; ndx < MAX_INVENTORY; ndx++)
1241             pp->InventorySprite[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->InventorySprite[ndx]);
1242 
1243         pp->Chops = PanelNdxToSprite(pp, (int)(intptr_t)pp->Chops);
1244         pp->InventorySelectionBox = PanelNdxToSprite(pp, (int)(intptr_t)pp->InventorySelectionBox);
1245         pp->MiniBarHealthBox = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarHealthBox);
1246         pp->MiniBarAmmo = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarAmmo);
1247 
1248         for (ndx = 0; ndx < (short)SIZ(pp->MiniBarHealthBoxDigit); ndx++)
1249             pp->MiniBarHealthBoxDigit[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarHealthBoxDigit[ndx]);
1250 
1251         for (ndx = 0; ndx < (short)SIZ(pp->MiniBarAmmoDigit); ndx++)
1252             pp->MiniBarAmmoDigit[ndx] = PanelNdxToSprite(pp, (int)(intptr_t)pp->MiniBarAmmoDigit[ndx]);
1253 
1254         #endif
1255         }
1256 
1257     {
1258     int SavePlayClock = PlayClock;
1259     InitTimingVars();
1260     PlayClock = SavePlayClock;
1261     }
1262     InitNetVars();
1263 
1264     SetupAspectRatio();
1265     SetRedrawScreen(Player + myconnectindex);
1266 
1267     COVERsetbrightness(gs.Brightness,&palette_data[0][0]);
1268 
1269     screenpeek = myconnectindex;
1270     PlayingLevel = Level;
1271 
1272     PlaySong(LevelSong, RedBookSong[Level], TRUE, TRUE);
1273     if (gs.Ambient)
1274         StartAmbientSound();
1275     FX_SetVolume(gs.SoundVolume);
1276     SetSongVolume(gs.MusicVolume);
1277 
1278     TRAVERSE_CONNECT(i)
1279         {
1280         Player[i].PlayerTalking = FALSE;
1281         Player[i].TalkVocnum = -1;
1282         Player[i].TalkVocHandle = -1;
1283         Player[i].StartColor = 0;
1284         }
1285 
1286     // this is not a new game
1287     NewGame = FALSE;
1288 
1289 
1290     DoPlayerDivePalette(Player+myconnectindex);
1291     DoPlayerNightVisionPalette(Player+myconnectindex);
1292 
1293     return(0);
1294 }
1295 
1296 VOID
ScreenSave(MFILE fout)1297 ScreenSave(MFILE fout)
1298     {
1299     int num;
1300     num = MWRITE((void*)waloff[SAVE_SCREEN_TILE], SAVE_SCREEN_XSIZE * SAVE_SCREEN_YSIZE, 1, fout);
1301     ASSERT(num == 1);
1302     }
1303 
1304 VOID
ScreenLoad(MFILE fin)1305 ScreenLoad(MFILE fin)
1306     {
1307     int num;
1308 
1309     setviewtotile(SAVE_SCREEN_TILE, SAVE_SCREEN_YSIZE, SAVE_SCREEN_XSIZE);
1310 
1311     num = MREAD((void*)waloff[SAVE_SCREEN_TILE], SAVE_SCREEN_XSIZE * SAVE_SCREEN_YSIZE, 1, fin);
1312 
1313     setviewback();
1314     }
1315 
1316