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(¶llaxtype,sizeof(parallaxtype),1,fil);
585 MWRITE(¶llaxyoffs,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(§num,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(¶llaxtype,sizeof(parallaxtype),1,fil);
1074 MREAD(¶llaxyoffs,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] = §or[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