Subversion Repositories eduke32

Rev

Rev 1677 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
5 Plagman 1
//-------------------------------------------------------------------------
2
/*
1652 terminx 3
Copyright (C) 2010 EDuke32 developers and contributors
5 Plagman 4
 
1652 terminx 5
This file is part of EDuke32.
5 Plagman 6
 
7
EDuke32 is free software; you can redistribute it and/or
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
10
 
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 
15
See the GNU General Public License for more details.
16
 
17
You should have received a copy of the GNU General Public License
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
20
*/
21
//-------------------------------------------------------------------------
22
 
23
#include "duke3d.h"
1677 terminx 24
#include "gamedef.h"
25
#include "premap.h"
26
#include "menus.h"
1660 terminx 27
#include "prlights.h"
5 Plagman 28
 
983 hnt_ts 29
extern char *bitptr;
30
 
984 terminx 31
#define BITPTR_POINTER 1
32
 
1143 terminx 33
void ReadSaveGameHeaders(void)
398 terminx 34
{
1205 terminx 35
    int32_t dummy,j;
36
    int32_t i;
398 terminx 37
    char fn[13];
1205 terminx 38
    int32_t fil;
398 terminx 39
 
40
    Bstrcpy(fn,"egam_.sav");
41
 
1229 terminx 42
    for (i=0; i<10; i++)
398 terminx 43
    {
44
        fn[4] = i+'0';
995 terminx 45
        if ((fil = kopen4loadfrommod(fn,0)) == -1) continue;
1205 terminx 46
        if (kdfread(&j,sizeof(int32_t),1,fil) != 1)
398 terminx 47
        {
995 terminx 48
            kclose(fil);
398 terminx 49
            continue;
50
        }
995 terminx 51
        if (kdfread(g_szBuf,j,1,fil) != 1)
398 terminx 52
        {
995 terminx 53
            kclose(fil);
398 terminx 54
            continue;
55
        }
1457 terminx 56
        if (kdfread(&dummy,sizeof(dummy),1,fil) != 1)
398 terminx 57
        {
995 terminx 58
            kclose(fil);
398 terminx 59
            continue;
60
        }
566 terminx 61
        if (dummy != BYTEVERSION)
398 terminx 62
        {
995 terminx 63
            kclose(fil);
398 terminx 64
            continue;
65
        }
1457 terminx 66
        if (kdfread(&dummy,sizeof(dummy),1,fil) != 1)
398 terminx 67
        {
995 terminx 68
            kclose(fil);
398 terminx 69
            continue;
70
        }
1707 terminx 71
        if (kdfread(&ud.savegame[i][0],21,1,fil) != 1)
398 terminx 72
        {
73
            ud.savegame[i][0] = 0;
74
        }
1707 terminx 75
        else ud.savegame[i][19] = 0;
76
 
995 terminx 77
        kclose(fil);
398 terminx 78
    }
79
}
80
 
1205 terminx 81
int32_t G_LoadSaveHeader(char spot,struct savehead *saveh)
5 Plagman 82
{
83
    char fn[13];
1205 terminx 84
    int32_t fil;
85
    int32_t bv;
5 Plagman 86
 
87
    strcpy(fn, "egam0.sav");
88
    fn[4] = spot+'0';
89
 
994 terminx 90
    if ((fil = kopen4loadfrommod(fn,0)) == -1) return(-1);
5 Plagman 91
 
92
    walock[TILE_LOADSHOT] = 255;
93
 
331 terminx 94
    if (kdfread(&bv,sizeof(bv),1,fil) != 1) goto corrupt;
95
    if (kdfread(g_szBuf,bv,1,fil) != 1) goto corrupt;
120 terminx 96
    g_szBuf[bv]=0;
296 terminx 97
    //    AddLog(g_szBuf);
120 terminx 98
 
1457 terminx 99
    if (kdfread(&bv,sizeof(bv),1,fil) != 1) goto corrupt;
877 terminx 100
    /*    if (bv != BYTEVERSION)
101
        {
1143 terminx 102
            P_DoQuote(114,g_player[myconnectindex].ps);
877 terminx 103
            kclose(fil);
104
            return 1;
105
        }*/
5 Plagman 106
 
1346 terminx 107
    if (kdfread(&saveh->numplr,sizeof(int32_t),1,fil) != 1) goto corrupt;
5 Plagman 108
 
1707 terminx 109
    if (kdfread(saveh->name,21,1,fil) != 1) goto corrupt;
1346 terminx 110
    if (kdfread(&saveh->volnum,sizeof(int32_t),1,fil) != 1) goto corrupt;
111
    if (kdfread(&saveh->levnum,sizeof(int32_t),1,fil) != 1) goto corrupt;
112
    if (kdfread(&saveh->plrskl,sizeof(int32_t),1,fil) != 1) goto corrupt;
5 Plagman 113
    if (kdfread(saveh->boardfn,BMAX_PATH,1,fil) != 1) goto corrupt;
114
 
115
    if (waloff[TILE_LOADSHOT] == 0) allocache(&waloff[TILE_LOADSHOT],320*200,&walock[TILE_LOADSHOT]);
335 terminx 116
    tilesizx[TILE_LOADSHOT] = 200;
117
    tilesizy[TILE_LOADSHOT] = 320;
5 Plagman 118
    if (kdfread((char *)waloff[TILE_LOADSHOT],320,200,fil) != 200) goto corrupt;
119
    invalidatetile(TILE_LOADSHOT,0,255);
120
 
121
    kclose(fil);
122
 
123
    return(0);
124
corrupt:
29 terminx 125
    kclose(fil);
5 Plagman 126
    return 1;
127
}
128
 
1205 terminx 129
int32_t G_LoadPlayer(int32_t spot)
5 Plagman 130
{
1205 terminx 131
    int32_t k;
5 Plagman 132
    char fn[13];
133
    char mpfn[13];
570 terminx 134
    char *fnptr, *scriptptrs;
1205 terminx 135
    int32_t fil, bv, i, x;
792 qbix79 136
    intptr_t j;
1346 terminx 137
    int32_t nump;
5 Plagman 138
 
139
    strcpy(fn, "egam0.sav");
140
    strcpy(mpfn, "egamA_00.sav");
141
 
1677 terminx 142
    fnptr = fn;
143
    fn[4] = spot + '0';
5 Plagman 144
 
994 terminx 145
    if ((fil = kopen4loadfrommod(fnptr,0)) == -1) return(-1);
5 Plagman 146
 
147
    ready2send = 0;
148
 
331 terminx 149
    if (kdfread(&bv,sizeof(bv),1,fil) != 1) goto corrupt;
150
    if (kdfread(g_szBuf,bv,1,fil) != 1) goto corrupt;
120 terminx 151
    g_szBuf[bv]=0;
296 terminx 152
    //    AddLog(g_szBuf);
120 terminx 153
 
1457 terminx 154
    if (kdfread(&bv,sizeof(bv),1,fil) != 1) return -1;
566 terminx 155
    if (bv != BYTEVERSION)
5 Plagman 156
    {
1143 terminx 157
        P_DoQuote(114,g_player[myconnectindex].ps);
5 Plagman 158
        kclose(fil);
159
        ototalclock = totalclock;
160
        ready2send = 1;
161
        return 1;
162
    }
163
 
164
    if (kdfread(&nump,sizeof(nump),1,fil) != 1) return -1;
331 terminx 165
    if (nump != ud.multimode)
5 Plagman 166
    {
167
        kclose(fil);
168
        ototalclock = totalclock;
169
        ready2send = 1;
1143 terminx 170
        P_DoQuote(124,g_player[myconnectindex].ps);
5 Plagman 171
        return 1;
335 terminx 172
    }
173
    else ud.multimode = nump;
5 Plagman 174
 
331 terminx 175
    if (numplayers > 1)
5 Plagman 176
    {
177
        pub = NUMPAGES;
178
        pus = NUMPAGES;
1143 terminx 179
        G_UpdateScreenArea();
180
        G_DrawBackground();
5 Plagman 181
        menutext(160,100,0,0,"LOADING...");
182
        nextpage();
183
    }
184
 
1574 terminx 185
    Net_WaitForServer();
5 Plagman 186
 
187
    FX_StopAllSounds();
1143 terminx 188
    S_ClearSoundLocks();
5 Plagman 189
 
335 terminx 190
    if (numplayers > 1)
191
    {
1707 terminx 192
        if (kdfread(&buf,21,1,fil) != 1) goto corrupt;
335 terminx 193
    }
194
    else
195
    {
1707 terminx 196
        if (kdfread(&ud.savegame[spot][0],21,1,fil) != 1) goto corrupt;
197
        ud.savegame[spot][19] = 0;
5 Plagman 198
    }
199
 
200
 
201
    if (kdfread(&ud.volume_number,sizeof(ud.volume_number),1,fil) != 1) goto corrupt;
202
    if (kdfread(&ud.level_number,sizeof(ud.level_number),1,fil) != 1) goto corrupt;
203
    if (kdfread(&ud.player_skill,sizeof(ud.player_skill),1,fil) != 1) goto corrupt;
204
    if (kdfread(&boardfilename[0],BMAX_PATH,1,fil) != 1) goto corrupt;
1652 terminx 205
 
206
    currentboardfilename[0] = 0;
207
 
208
    if (boardfilename[0])
209
        strcpy(currentboardfilename, boardfilename);
210
    else if (MapInfo[(ud.volume_number * MAXLEVELS) + ud.level_number].filename)
211
        strcpy(currentboardfilename, MapInfo[(ud.volume_number * MAXLEVELS) + ud.level_number].filename);
212
 
213
    if (currentboardfilename[0])
214
    {
215
        char *p;
216
 
217
        p = Bstrrchr(currentboardfilename,'.');
218
        if (!p) strcat(currentboardfilename,".mhk");
219
        else
220
        {
221
            p[1]='m';
222
            p[2]='h';
223
            p[3]='k';
224
            p[4]=0;
225
        }
226
 
227
        loadmaphack(currentboardfilename);
228
    }
229
 
1068 terminx 230
    Bmemcpy(&currentboardfilename[0],&boardfilename[0],BMAX_PATH);
5 Plagman 231
 
232
    ud.m_level_number = ud.level_number;
233
    ud.m_volume_number = ud.volume_number;
234
    ud.m_player_skill = ud.player_skill;
235
 
236
    //Fake read because lseek won't work with compression
237
    walock[TILE_LOADSHOT] = 1;
238
    if (waloff[TILE_LOADSHOT] == 0) allocache(&waloff[TILE_LOADSHOT],320*200,&walock[TILE_LOADSHOT]);
335 terminx 239
    tilesizx[TILE_LOADSHOT] = 200;
240
    tilesizy[TILE_LOADSHOT] = 320;
5 Plagman 241
    if (kdfread((char *)waloff[TILE_LOADSHOT],320,200,fil) != 200) goto corrupt;
242
    invalidatetile(TILE_LOADSHOT,0,255);
243
 
1378 qbix79 244
    if (kdfread(&numwalls,sizeof(numwalls),1,fil) != 1) goto corrupt;
5 Plagman 245
    if (kdfread(&wall[0],sizeof(walltype),MAXWALLS,fil) != MAXWALLS) goto corrupt;
1378 qbix79 246
    if (kdfread(&numsectors,sizeof(numsectors),1,fil) != 1) goto corrupt;
5 Plagman 247
    if (kdfread(&sector[0],sizeof(sectortype),MAXSECTORS,fil) != MAXSECTORS) goto corrupt;
248
    if (kdfread(&sprite[0],sizeof(spritetype),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
1206 terminx 249
    if (kdfread(&spriteext[0],sizeof(spriteext_t),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
1336 terminx 250
 
251
#ifdef POLYMER
1409 terminx 252
    if (kdfread(&lightcount,sizeof(lightcount),1,fil) != 1) goto corrupt;
253
    if (kdfread(&prlights[0],sizeof(_prlight),lightcount,fil) != lightcount) goto corrupt;
1336 terminx 254
#else
255
    if (kdfread(&i,sizeof(int32_t),1,fil) != 1) goto corrupt;
256
#endif // POLYMER
1308 plagman 257
 
606 terminx 258
#if defined(POLYMOST) && defined(USE_OPENGL)
1229 terminx 259
    for (i=0; i<MAXSPRITES; i++)
622 terminx 260
        if (spriteext[i].mdanimtims)
261
            spriteext[i].mdanimtims+=mdtims;
606 terminx 262
#endif
1378 qbix79 263
    if (kdfread(&headspritesect[0],sizeof(headspritesect[0]),MAXSECTORS+1,fil) != MAXSECTORS+1) goto corrupt;
264
    if (kdfread(&prevspritesect[0],sizeof(prevspritesect[0]),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
265
    if (kdfread(&nextspritesect[0],sizeof(nextspritesect[0]),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
266
    if (kdfread(&headspritestat[STAT_DEFAULT],sizeof(headspritestat[STAT_DEFAULT]),MAXSTATUS+1,fil) != MAXSTATUS+1) goto corrupt;
267
    if (kdfread(&prevspritestat[STAT_DEFAULT],sizeof(prevspritestat[STAT_DEFAULT]),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
268
    if (kdfread(&nextspritestat[STAT_DEFAULT],sizeof(nextspritestat[STAT_DEFAULT]),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
1143 terminx 269
    if (kdfread(&g_numCyclers,sizeof(g_numCyclers),1,fil) != 1) goto corrupt;
1378 qbix79 270
    if (kdfread(&cyclers[0][0],sizeof(cyclers[0][0])*6,MAXCYCLERS,fil) != MAXCYCLERS) goto corrupt;
1229 terminx 271
    for (i=0; i<nump; i++)
1143 terminx 272
        if (kdfread(g_player[i].ps,sizeof(DukePlayer_t),1,fil) != 1) goto corrupt;
273
    if (kdfread(&g_playerSpawnPoints,sizeof(g_playerSpawnPoints),1,fil) != 1) goto corrupt;
274
    if (kdfread(&g_numAnimWalls,sizeof(g_numAnimWalls),1,fil) != 1) goto corrupt;
5 Plagman 275
    if (kdfread(&animwall,sizeof(animwall),1,fil) != 1) goto corrupt;
1205 terminx 276
    if (kdfread(&msx[0],sizeof(int32_t),sizeof(msx)/sizeof(int32_t),fil) != sizeof(msx)/sizeof(int32_t)) goto corrupt;
277
    if (kdfread(&msy[0],sizeof(int32_t),sizeof(msy)/sizeof(int32_t),fil) != sizeof(msy)/sizeof(int32_t)) goto corrupt;
278
    if (kdfread((int16_t *)&g_spriteDeleteQueuePos,sizeof(int16_t),1,fil) != 1) goto corrupt;
279
    if (kdfread((int16_t *)&g_spriteDeleteQueueSize,sizeof(int16_t),1,fil) != 1) goto corrupt;
280
    if (kdfread((int16_t *)&SpriteDeletionQueue[0],sizeof(int16_t),g_spriteDeleteQueueSize,fil) != g_spriteDeleteQueueSize) goto corrupt;
281
    if (kdfread(&g_mirrorCount,sizeof(int16_t),1,fil) != 1) goto corrupt;
282
    if (kdfread(&g_mirrorWall[0],sizeof(int16_t),64,fil) != 64) goto corrupt;
283
    if (kdfread(&g_mirrorSector[0],sizeof(int16_t),64,fil) != 64) goto corrupt;
284
    if (kdfread(&show2dsector[0],sizeof(uint8_t),MAXSECTORS>>3,fil) != (MAXSECTORS>>3)) goto corrupt;
285
    if (kdfread(&ActorType[0],sizeof(uint8_t),MAXTILES,fil) != MAXTILES) goto corrupt;
5 Plagman 286
 
1143 terminx 287
    if (kdfread(&g_numClouds,sizeof(g_numClouds),1,fil) != 1) goto corrupt;
1205 terminx 288
    if (kdfread(&clouds[0],sizeof(int16_t)<<7,1,fil) != 1) goto corrupt;
289
    if (kdfread(&cloudx[0],sizeof(int16_t)<<7,1,fil) != 1) goto corrupt;
290
    if (kdfread(&cloudy[0],sizeof(int16_t)<<7,1,fil) != 1) goto corrupt;
5 Plagman 291
 
1143 terminx 292
    if (kdfread(&g_scriptSize,sizeof(g_scriptSize),1,fil) != 1) goto corrupt;
293
    if (!g_scriptSize) goto corrupt;
294
    scriptptrs = Bcalloc(1,g_scriptSize * sizeof(scriptptrs));
1082 terminx 295
    Bfree(bitptr);
1205 terminx 296
    bitptr = Bcalloc(1,(((g_scriptSize+7)>>3)+1) * sizeof(uint8_t));
297
    if (kdfread(&bitptr[0],sizeof(uint8_t),(g_scriptSize+7)>>3,fil) != ((g_scriptSize+7)>>3)) goto corrupt;
568 terminx 298
    if (script != NULL)
299
        Bfree(script);
1143 terminx 300
    script = Bcalloc(1,g_scriptSize * sizeof(intptr_t));
301
    if (kdfread(&script[0],sizeof(script),g_scriptSize,fil) != g_scriptSize) goto corrupt;
1229 terminx 302
    for (i=0; i<g_scriptSize; i++)
1064 terminx 303
        if (bitptr[i>>3]&(BITPTR_POINTER<<(i&7)))
29 terminx 304
        {
792 qbix79 305
            j = (intptr_t)script[i]+(intptr_t)&script[0];
29 terminx 306
            script[i] = j;
307
        }
5 Plagman 308
 
1378 qbix79 309
    if (kdfread(&actorscrptr[0],sizeof(actorscrptr[0]),MAXTILES,fil) != MAXTILES) goto corrupt;
1229 terminx 310
    for (i=0; i<MAXTILES; i++)
331 terminx 311
        if (actorscrptr[i])
29 terminx 312
        {
792 qbix79 313
            j = (intptr_t)actorscrptr[i]+(intptr_t)&script[0];
314
            actorscrptr[i] = (intptr_t *)j;
29 terminx 315
        }
1378 qbix79 316
    if (kdfread(&actorLoadEventScrptr[0],sizeof(&actorLoadEventScrptr[0]),MAXTILES,fil) != MAXTILES) goto corrupt;
1229 terminx 317
    for (i=0; i<MAXTILES; i++)
331 terminx 318
        if (actorLoadEventScrptr[i])
29 terminx 319
        {
792 qbix79 320
            j = (intptr_t)actorLoadEventScrptr[i]+(intptr_t)&script[0];
321
            actorLoadEventScrptr[i] = (intptr_t *)j;
29 terminx 322
        }
5 Plagman 323
 
1043 terminx 324
    scriptptrs = Brealloc(scriptptrs, MAXSPRITES * sizeof(scriptptrs));
325
 
567 terminx 326
    if (kdfread(&scriptptrs[0],sizeof(scriptptrs),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
1677 terminx 327
    if (kdfread(&actor[0],sizeof(actor_t),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
5 Plagman 328
 
1229 terminx 329
    for (i=0; i<MAXSPRITES; i++)
5 Plagman 330
    {
792 qbix79 331
        j = (intptr_t)(&script[0]);
333 terminx 332
        if (scriptptrs[i]&1) T2 += j;
333
        if (scriptptrs[i]&2) T5 += j;
334
        if (scriptptrs[i]&4) T6 += j;
1625 terminx 335
        actor[i].projectile = &SpriteProjectile[i];
5 Plagman 336
    }
337
 
338
    if (kdfread(&lockclock,sizeof(lockclock),1,fil) != 1) goto corrupt;
339
    if (kdfread(&pskybits,sizeof(pskybits),1,fil) != 1) goto corrupt;
340
    if (kdfread(&pskyoff[0],sizeof(pskyoff[0]),MAXPSKYTILES,fil) != MAXPSKYTILES) goto corrupt;
341
 
1143 terminx 342
    if (kdfread(&g_animateCount,sizeof(g_animateCount),1,fil) != 1) goto corrupt;
1378 qbix79 343
    if (kdfread(&animatesect[0],sizeof(animatesect[0]),MAXANIMATES,fil) != MAXANIMATES) goto corrupt;
344
    if (kdfread(&animateptr[0],sizeof(animateptr[0]),MAXANIMATES,fil) != MAXANIMATES) goto corrupt;
1677 terminx 345
    for (i = g_animateCount-1; i>=0; i--) animateptr[i] = (int32_t *)((intptr_t)animateptr[i]+(intptr_t)(&sector[0]));
1378 qbix79 346
    if (kdfread(&animategoal[0],sizeof(animategoal[0]),MAXANIMATES,fil) != MAXANIMATES) goto corrupt;
347
    if (kdfread(&animatevel[0],sizeof(animatevel[0]),MAXANIMATES,fil) != MAXANIMATES) goto corrupt;
5 Plagman 348
 
1143 terminx 349
    if (kdfread(&g_earthquakeTime,sizeof(g_earthquakeTime),1,fil) != 1) goto corrupt;
5 Plagman 350
    if (kdfread(&ud.from_bonus,sizeof(ud.from_bonus),1,fil) != 1) goto corrupt;
351
    if (kdfread(&ud.secretlevel,sizeof(ud.secretlevel),1,fil) != 1) goto corrupt;
352
    if (kdfread(&ud.respawn_monsters,sizeof(ud.respawn_monsters),1,fil) != 1) goto corrupt;
353
    ud.m_respawn_monsters = ud.respawn_monsters;
354
    if (kdfread(&ud.respawn_items,sizeof(ud.respawn_items),1,fil) != 1) goto corrupt;
355
    ud.m_respawn_items = ud.respawn_items;
356
    if (kdfread(&ud.respawn_inventory,sizeof(ud.respawn_inventory),1,fil) != 1) goto corrupt;
357
    ud.m_respawn_inventory = ud.respawn_inventory;
358
 
359
    if (kdfread(&ud.god,sizeof(ud.god),1,fil) != 1) goto corrupt;
360
    if (kdfread(&ud.auto_run,sizeof(ud.auto_run),1,fil) != 1) goto corrupt;
361
    if (kdfread(&ud.crosshair,sizeof(ud.crosshair),1,fil) != 1) goto corrupt;
362
    if (kdfread(&ud.monsters_off,sizeof(ud.monsters_off),1,fil) != 1) goto corrupt;
363
    ud.m_monsters_off = ud.monsters_off;
364
    if (kdfread(&ud.last_level,sizeof(ud.last_level),1,fil) != 1) goto corrupt;
365
    if (kdfread(&ud.eog,sizeof(ud.eog),1,fil) != 1) goto corrupt;
366
 
367
    if (kdfread(&ud.coop,sizeof(ud.coop),1,fil) != 1) goto corrupt;
368
    ud.m_coop = ud.coop;
369
    if (kdfread(&ud.marker,sizeof(ud.marker),1,fil) != 1) goto corrupt;
370
    ud.m_marker = ud.marker;
371
    if (kdfread(&ud.ffire,sizeof(ud.ffire),1,fil) != 1) goto corrupt;
372
    ud.m_ffire = ud.ffire;
373
 
374
    if (kdfread(&camsprite,sizeof(camsprite),1,fil) != 1) goto corrupt;
375
    if (kdfread(&connecthead,sizeof(connecthead),1,fil) != 1) goto corrupt;
376
    if (kdfread(connectpoint2,sizeof(connectpoint2),1,fil) != 1) goto corrupt;
1143 terminx 377
    if (kdfread(&g_numPlayerSprites,sizeof(g_numPlayerSprites),1,fil) != 1) goto corrupt;
1229 terminx 378
    for (i=0; i<MAXPLAYERS; i++)
1205 terminx 379
        if (kdfread((int16_t *)&g_player[i].frags[0],sizeof(g_player[i].frags),1,fil) != 1) goto corrupt;
5 Plagman 380
 
381
    if (kdfread(&randomseed,sizeof(randomseed),1,fil) != 1) goto corrupt;
1143 terminx 382
    if (kdfread(&g_globalRandom,sizeof(g_globalRandom),1,fil) != 1) goto corrupt;
5 Plagman 383
    if (kdfread(&parallaxyscale,sizeof(parallaxyscale),1,fil) != 1) goto corrupt;
384
 
1457 terminx 385
    if (kdfread(&SpriteProjectile[0],sizeof(projectile_t),MAXSPRITES,fil) != MAXSPRITES) goto corrupt;
1143 terminx 386
    if (kdfread(&ProjectileData[0],sizeof(projectile_t),MAXTILES,fil) != MAXTILES) goto corrupt;
387
    if (kdfread(&DefaultProjectileData[0],sizeof(projectile_t),MAXTILES,fil) != MAXTILES) goto corrupt;
5 Plagman 388
 
1143 terminx 389
    if (kdfread(&SpriteFlags[0],sizeof(SpriteFlags[0]),MAXTILES,fil) != MAXTILES) goto corrupt;
105 terminx 390
 
1143 terminx 391
    if (kdfread(&SpriteCacheList[0],sizeof(SpriteCacheList[0]),MAXTILES,fil) != MAXTILES) goto corrupt;
105 terminx 392
 
1205 terminx 393
    if (kdfread(&i,sizeof(int32_t),1,fil) != 1) goto corrupt;
105 terminx 394
 
331 terminx 395
    while (i != MAXQUOTES)
105 terminx 396
    {
1143 terminx 397
        if (ScriptQuotes[i] != NULL)
398
            Bfree(ScriptQuotes[i]);
105 terminx 399
 
1205 terminx 400
        ScriptQuotes[i] = Bcalloc(MAXQUOTELEN,sizeof(uint8_t));
105 terminx 401
 
1143 terminx 402
        if (kdfread((char *)ScriptQuotes[i],MAXQUOTELEN,1,fil) != 1) goto corrupt;
1205 terminx 403
        if (kdfread(&i,sizeof(int32_t),1,fil) != 1) goto corrupt;
106 terminx 404
    }
105 terminx 405
 
1143 terminx 406
    if (kdfread(&g_numQuoteRedefinitions,sizeof(g_numQuoteRedefinitions),1,fil) != 1) goto corrupt;
105 terminx 407
 
1229 terminx 408
    for (i=0; i<g_numQuoteRedefinitions; i++)
105 terminx 409
    {
1143 terminx 410
        if (ScriptQuoteRedefinitions[i] != NULL)
411
            Bfree(ScriptQuoteRedefinitions[i]);
105 terminx 412
 
1205 terminx 413
        ScriptQuoteRedefinitions[i] = Bcalloc(MAXQUOTELEN,sizeof(uint8_t));
105 terminx 414
 
1143 terminx 415
        if (kdfread((char *)ScriptQuoteRedefinitions[i],MAXQUOTELEN,1,fil) != 1) goto corrupt;
106 terminx 416
    }
105 terminx 417
 
1143 terminx 418
    if (kdfread(&DynamicTileMap[0],sizeof(DynamicTileMap[0]),MAXTILES,fil) != MAXTILES) goto corrupt;
114 terminx 419
 
147 terminx 420
    if (kdfread(&ud.noexits,sizeof(ud.noexits),1,fil) != 1) goto corrupt;
421
    ud.m_noexits = ud.noexits;
422
 
423
 
1595 helixhorne 424
    if (Gv_ReadSave(fil, 0)) goto corrupt;
5 Plagman 425
 
426
    kclose(fil);
427
 
564 terminx 428
    if (g_player[myconnectindex].ps->over_shoulder_on != 0)
5 Plagman 429
    {
1143 terminx 430
        g_cameraDistance = 0;
431
        g_cameraClock = 0;
564 terminx 432
        g_player[myconnectindex].ps->over_shoulder_on = 1;
5 Plagman 433
    }
434
 
435
    screenpeek = myconnectindex;
436
 
437
    clearbufbyte(gotpic,sizeof(gotpic),0L);
1143 terminx 438
    S_ClearSoundLocks();
439
    G_CacheMapData();
5 Plagman 440
 
1143 terminx 441
    i = g_musicIndex;
442
    g_musicIndex = (ud.volume_number*MAXLEVELS) + ud.level_number;
1196 terminx 443
 
444
    if (boardfilename[0] != 0 && ud.level_number == 7 && ud.volume_number == 0)
445
    {
446
        char *p;
447
        char levname[BMAX_PATH];
1205 terminx 448
        int32_t fil;
1196 terminx 449
 
450
        strcpy(levname, boardfilename);
451
        // usermap music based on map filename
452
        Bcorrectfilename(levname,0);
453
        p = Bstrrchr(levname,'.');
454
        if (!p) strcat(levname,".ogg");
455
        else
456
        {
457
            p[1]='o';
458
            p[2]='g';
459
            p[3]='g';
460
            p[4]=0;
461
        }
462
 
463
        fil = kopen4loadfrommod(levname,0);
464
 
465
        if (fil > -1)
466
        {
467
            kclose(fil);
1475 terminx 468
            if (MapInfo[ud.level_number].alt_musicfn == NULL)
469
                MapInfo[ud.level_number].alt_musicfn = Bcalloc(Bstrlen(levname)+1,sizeof(uint8_t));
470
            else if ((Bstrlen(levname)+1) > sizeof(MapInfo[ud.level_number].alt_musicfn))
471
                MapInfo[ud.level_number].alt_musicfn = Brealloc(MapInfo[ud.level_number].alt_musicfn,(Bstrlen(levname)+1));
472
            Bstrcpy(MapInfo[ud.level_number].alt_musicfn,levname);
1196 terminx 473
        }
1475 terminx 474
        else if (MapInfo[ud.level_number].alt_musicfn != NULL)
1196 terminx 475
        {
1475 terminx 476
            Bfree(MapInfo[ud.level_number].alt_musicfn);
477
            MapInfo[ud.level_number].alt_musicfn = NULL;
1196 terminx 478
        }
479
 
480
        p[1]='m';
481
        p[2]='i';
482
        p[3]='d';
483
        p[4]=0;
484
 
485
        fil = kopen4loadfrommod(levname,0);
486
 
487
        if (fil == -1)
488
            Bsprintf(levname,"dethtoll.mid");
489
        else kclose(fil);
490
 
491
        if (MapInfo[ud.level_number].musicfn == NULL)
1205 terminx 492
            MapInfo[ud.level_number].musicfn = Bcalloc(Bstrlen(levname)+1,sizeof(uint8_t));
1196 terminx 493
        else if ((Bstrlen(levname)+1) > sizeof(MapInfo[ud.level_number].musicfn))
494
            MapInfo[ud.level_number].musicfn = Brealloc(MapInfo[ud.level_number].musicfn,(Bstrlen(levname)+1));
495
        Bstrcpy(MapInfo[ud.level_number].musicfn,levname);
496
    }
497
 
1475 terminx 498
    if (MapInfo[(uint8_t)g_musicIndex].musicfn != NULL && (i != g_musicIndex || MapInfo[MAXVOLUMES*MAXLEVELS+2].alt_musicfn))
559 terminx 499
    {
1468 terminx 500
        S_StopMusic();
1205 terminx 501
        S_PlayMusic(&MapInfo[(uint8_t)g_musicIndex].musicfn[0],g_musicIndex);
559 terminx 502
    }
1468 terminx 503
    S_PauseMusic(0);
5 Plagman 504
 
564 terminx 505
    g_player[myconnectindex].ps->gm = MODE_GAME;
5 Plagman 506
    ud.recstat = 0;
507
 
564 terminx 508
    if (g_player[myconnectindex].ps->jetpack_on)
1143 terminx 509
        A_PlaySound(DUKE_JETPACK_IDLE,g_player[myconnectindex].ps->i);
5 Plagman 510
 
1143 terminx 511
    g_restorePalette = 1;
512
    P_UpdateScreenPal(g_player[myconnectindex].ps);
513
    G_UpdateScreenArea();
5 Plagman 514
 
515
    FX_SetReverb(0);
516
 
331 terminx 517
    if (ud.lockout == 0)
5 Plagman 518
    {
1229 terminx 519
        for (x=0; x<g_numAnimWalls; x++)
333 terminx 520
            if (wall[animwall[x].wallnum].extra >= 0)
5 Plagman 521
                wall[animwall[x].wallnum].picnum = wall[animwall[x].wallnum].extra;
522
    }
523
    else
524
    {
1229 terminx 525
        for (x=0; x<g_numAnimWalls; x++)
1143 terminx 526
            switch (DynamicTileMap[wall[animwall[x].wallnum].picnum])
29 terminx 527
            {
337 terminx 528
            case FEMPIC1__STATIC:
529
                wall[animwall[x].wallnum].picnum = BLANKSCREEN;
530
                break;
531
            case FEMPIC2__STATIC:
532
            case FEMPIC3__STATIC:
533
                wall[animwall[x].wallnum].picnum = SCREENBREAK6;
534
                break;
29 terminx 535
            }
5 Plagman 536
    }
537
 
1143 terminx 538
    g_numInterpolations = 0;
5 Plagman 539
    startofdynamicinterpolations = 0;
540
 
1143 terminx 541
    k = headspritestat[STAT_EFFECTOR];
331 terminx 542
    while (k >= 0)
5 Plagman 543
    {
331 terminx 544
        switch (sprite[k].lotag)
5 Plagman 545
        {
337 terminx 546
        case 31:
1143 terminx 547
            G_SetInterpolation(&sector[sprite[k].sectnum].floorz);
337 terminx 548
            break;
549
        case 32:
1143 terminx 550
            G_SetInterpolation(&sector[sprite[k].sectnum].ceilingz);
337 terminx 551
            break;
552
        case 25:
1143 terminx 553
            G_SetInterpolation(&sector[sprite[k].sectnum].floorz);
554
            G_SetInterpolation(&sector[sprite[k].sectnum].ceilingz);
337 terminx 555
            break;
556
        case 17:
1143 terminx 557
            G_SetInterpolation(&sector[sprite[k].sectnum].floorz);
558
            G_SetInterpolation(&sector[sprite[k].sectnum].ceilingz);
337 terminx 559
            break;
560
        case 0:
561
        case 5:
562
        case 6:
563
        case 11:
564
        case 14:
565
        case 15:
566
        case 16:
567
        case 26:
568
        case 30:
1143 terminx 569
            Sect_SetInterpolation(k);
337 terminx 570
            break;
5 Plagman 571
        }
572
 
573
        k = nextspritestat[k];
574
    }
575
 
1229 terminx 576
    for (i=g_numInterpolations-1; i>=0; i--) bakipos[i] = *curipos[i];
577
    for (i = g_animateCount-1; i>=0; i--)
1143 terminx 578
        G_SetInterpolation(animateptr[i]);
5 Plagman 579
 
1143 terminx 580
    g_showShareware = 0;
5 Plagman 581
    everyothertime = 0;
582
 
563 terminx 583
//    clearbufbyte(playerquitflag,MAXPLAYERS,0x01010101);
5 Plagman 584
 
1229 terminx 585
    for (i=0; i<MAXPLAYERS; i++)
564 terminx 586
        clearbufbyte(&g_player[i].playerquitflag,1,0x01010101);
563 terminx 587
 
1143 terminx 588
    Net_ResetPrediction();
5 Plagman 589
 
590
    ready2send = 1;
591
 
592
    clearfifo();
1574 terminx 593
    Net_WaitForServer();
5 Plagman 594
 
1143 terminx 595
    G_ResetTimers();
5 Plagman 596
 
1276 plagman 597
#ifdef POLYMER
1410 terminx 598
    if (getrendermode() == 4)
599
    {
600
        int32_t i = 0;
601
 
1276 plagman 602
        polymer_loadboard();
1652 terminx 603
 
1410 terminx 604
        while (i < MAXSPRITES)
605
        {
1625 terminx 606
            if (actor[i].lightptr)
1410 terminx 607
            {
1625 terminx 608
                actor[i].lightptr = NULL;
609
                actor[i].lightId = -1;
1410 terminx 610
            }
611
            i++;
612
        }
613
    }
1276 plagman 614
#endif
615
 
5 Plagman 616
    return(0);
617
corrupt:
609 terminx 618
    Bsprintf(tempbuf,"Save game file \"%s\" is corrupt or of the wrong version.",fnptr);
1143 terminx 619
    G_GameExit(tempbuf);
5 Plagman 620
    return -1;
621
}
622
 
1205 terminx 623
int32_t G_SavePlayer(int32_t spot)
5 Plagman 624
{
1205 terminx 625
    int32_t i;
792 qbix79 626
    intptr_t j;
5 Plagman 627
    char fn[13];
628
    char mpfn[13];
570 terminx 629
    char *fnptr, *scriptptrs;
5 Plagman 630
    FILE *fil;
1205 terminx 631
    int32_t bv = BYTEVERSION;
5 Plagman 632
 
633
    strcpy(fn, "egam0.sav");
634
    strcpy(mpfn, "egamA_00.sav");
635
 
1574 terminx 636
    Net_WaitForServer();
5 Plagman 637
 
1677 terminx 638
    fnptr = fn;
639
    fn[4] = spot + '0';
5 Plagman 640
 
641
    {
994 terminx 642
        char temp[BMAX_PATH];
1587 terminx 643
        if (g_modDir[0] != '/')
644
            Bsprintf(temp,"%s/%s",g_modDir,fnptr);
995 terminx 645
        else Bsprintf(temp,"%s",fnptr);
994 terminx 646
        if ((fil = fopen(temp,"wb")) == 0) return(-1);
647
    }
5 Plagman 648
 
649
    ready2send = 0;
650
 
120 terminx 651
    Bsprintf(g_szBuf,"EDuke32");
652
    i=strlen(g_szBuf);
653
    dfwrite(&i,sizeof(i),1,fil);
654
    dfwrite(g_szBuf,i,1,fil);
655
 
1457 terminx 656
    dfwrite(&bv,sizeof(bv),1,fil);
5 Plagman 657
    dfwrite(&ud.multimode,sizeof(ud.multimode),1,fil);
658
 
1707 terminx 659
    dfwrite(&ud.savegame[spot][0],21,1,fil);
5 Plagman 660
    dfwrite(&ud.volume_number,sizeof(ud.volume_number),1,fil);
661
    dfwrite(&ud.level_number,sizeof(ud.level_number),1,fil);
662
    dfwrite(&ud.player_skill,sizeof(ud.player_skill),1,fil);
1068 terminx 663
    dfwrite(&currentboardfilename[0],BMAX_PATH,1,fil);
335 terminx 664
    if (!waloff[TILE_SAVESHOT])
665
    {
29 terminx 666
        walock[TILE_SAVESHOT] = 254;
618 terminx 667
        allocache(&waloff[TILE_SAVESHOT],200*320,&walock[TILE_SAVESHOT]);
1677 terminx 668
        clearbuf((void *)waloff[TILE_SAVESHOT],(200*320)/4,0);
29 terminx 669
        walock[TILE_SAVESHOT] = 1;
670
    }
671
    dfwrite((char *)waloff[TILE_SAVESHOT],320,200,fil);
5 Plagman 672
 
1378 qbix79 673
    dfwrite(&numwalls,sizeof(numwalls),1,fil);
5 Plagman 674
    dfwrite(&wall[0],sizeof(walltype),MAXWALLS,fil);
1378 qbix79 675
    dfwrite(&numsectors,sizeof(numsectors),1,fil);
5 Plagman 676
    dfwrite(&sector[0],sizeof(sectortype),MAXSECTORS,fil);
677
    dfwrite(&sprite[0],sizeof(spritetype),MAXSPRITES,fil);
606 terminx 678
#if defined(POLYMOST) && defined(USE_OPENGL)
1229 terminx 679
    for (i=0; i<MAXSPRITES; i++)
622 terminx 680
        if (spriteext[i].mdanimtims)
681
        {
682
            spriteext[i].mdanimtims=spriteext[i].mdanimtims-mdtims;
683
            if (!spriteext[i].mdanimtims)
684
                spriteext[i].mdanimtims++;
685
        }
606 terminx 686
#endif
1206 terminx 687
    dfwrite(&spriteext[0],sizeof(spriteext_t),MAXSPRITES,fil);
1336 terminx 688
 
689
#ifdef POLYMER
1409 terminx 690
    dfwrite(&lightcount,sizeof(lightcount),1,fil);
691
    dfwrite(&prlights[0],sizeof(_prlight),lightcount,fil);
1336 terminx 692
#else
693
    i = 0;
694
    dfwrite(&i,sizeof(int32_t),1,fil);
695
#endif // POLYMER
696
 
606 terminx 697
#if defined(POLYMOST) && defined(USE_OPENGL)
1229 terminx 698
    for (i=0; i<MAXSPRITES; i++)if (spriteext[i].mdanimtims)spriteext[i].mdanimtims+=mdtims;
606 terminx 699
#endif
1378 qbix79 700
    dfwrite(&headspritesect[0],sizeof(headspritesect[0]),MAXSECTORS+1,fil);
701
    dfwrite(&prevspritesect[0],sizeof(prevspritesect[0]),MAXSPRITES,fil);
702
    dfwrite(&nextspritesect[0],sizeof(nextspritesect[0]),MAXSPRITES,fil);
1457 terminx 703
    dfwrite(&headspritestat[STAT_DEFAULT],sizeof(headspritestat[0]),MAXSTATUS+1,fil);
704
    dfwrite(&prevspritestat[STAT_DEFAULT],sizeof(prevspritestat[0]),MAXSPRITES,fil);
705
    dfwrite(&nextspritestat[STAT_DEFAULT],sizeof(nextspritestat[0]),MAXSPRITES,fil);
1143 terminx 706
    dfwrite(&g_numCyclers,sizeof(g_numCyclers),1,fil);
1378 qbix79 707
    dfwrite(&cyclers[0][0],sizeof(cyclers[0][0])*6,MAXCYCLERS,fil);
1229 terminx 708
    for (i=0; i<ud.multimode; i++)
1143 terminx 709
        dfwrite(g_player[i].ps,sizeof(DukePlayer_t),1,fil);
710
    dfwrite(&g_playerSpawnPoints,sizeof(g_playerSpawnPoints),1,fil);
711
    dfwrite(&g_numAnimWalls,sizeof(g_numAnimWalls),1,fil);
5 Plagman 712
    dfwrite(&animwall,sizeof(animwall),1,fil);
1205 terminx 713
    dfwrite(&msx[0],sizeof(int32_t),sizeof(msx)/sizeof(int32_t),fil);
714
    dfwrite(&msy[0],sizeof(int32_t),sizeof(msy)/sizeof(int32_t),fil);
715
    dfwrite(&g_spriteDeleteQueuePos,sizeof(int16_t),1,fil);
716
    dfwrite(&g_spriteDeleteQueueSize,sizeof(int16_t),1,fil);
717
    dfwrite(&SpriteDeletionQueue[0],sizeof(int16_t),g_spriteDeleteQueueSize,fil);
718
    dfwrite(&g_mirrorCount,sizeof(int16_t),1,fil);
719
    dfwrite(&g_mirrorWall[0],sizeof(int16_t),64,fil);
720
    dfwrite(&g_mirrorSector[0],sizeof(int16_t),64,fil);
721
    dfwrite(&show2dsector[0],sizeof(uint8_t),MAXSECTORS>>3,fil);
722
    dfwrite(&ActorType[0],sizeof(uint8_t),MAXTILES,fil);
5 Plagman 723
 
1143 terminx 724
    dfwrite(&g_numClouds,sizeof(g_numClouds),1,fil);
1205 terminx 725
    dfwrite(&clouds[0],sizeof(int16_t)<<7,1,fil);
726
    dfwrite(&cloudx[0],sizeof(int16_t)<<7,1,fil);
727
    dfwrite(&cloudy[0],sizeof(int16_t)<<7,1,fil);
5 Plagman 728
 
1143 terminx 729
    dfwrite(&g_scriptSize,sizeof(g_scriptSize),1,fil);
730
    scriptptrs = Bcalloc(1, g_scriptSize * sizeof(scriptptrs));
1229 terminx 731
    for (i=0; i<g_scriptSize; i++)
5 Plagman 732
    {
1064 terminx 733
        if (bitptr[i>>3]&(BITPTR_POINTER<<(i&7)))
5 Plagman 734
        {
1064 terminx 735
//            scriptptrs[i] = 1;
792 qbix79 736
            j = (intptr_t)script[i] - (intptr_t)&script[0];
5 Plagman 737
            script[i] = j;
738
        }
1064 terminx 739
        //      else scriptptrs[i] = 0;
5 Plagman 740
    }
741
 
1143 terminx 742
//    dfwrite(&scriptptrs[0],sizeof(scriptptrs),g_scriptSize,fil);
1457 terminx 743
    dfwrite(&bitptr[0],sizeof(bitptr[0]),(g_scriptSize+7)>>3,fil);
744
    dfwrite(&script[0],sizeof(script[0]),g_scriptSize,fil);
5 Plagman 745
 
1229 terminx 746
    for (i=0; i<g_scriptSize; i++)
1064 terminx 747
        if (bitptr[i>>3]&(BITPTR_POINTER<<(i&7)))
29 terminx 748
        {
792 qbix79 749
            j = script[i]+(intptr_t)&script[0];
29 terminx 750
            script[i] = j;
751
        }
5 Plagman 752
 
1229 terminx 753
    for (i=0; i<MAXTILES; i++)
331 terminx 754
        if (actorscrptr[i])
29 terminx 755
        {
792 qbix79 756
            j = (intptr_t)actorscrptr[i]-(intptr_t)&script[0];
757
            actorscrptr[i] = (intptr_t *)j;
29 terminx 758
        }
1378 qbix79 759
    dfwrite(&actorscrptr[0],sizeof(actorscrptr[0]),MAXTILES,fil);
1229 terminx 760
    for (i=0; i<MAXTILES; i++)
331 terminx 761
        if (actorscrptr[i])
29 terminx 762
        {
792 qbix79 763
            j = (intptr_t)actorscrptr[i]+(intptr_t)&script[0];
764
            actorscrptr[i] = (intptr_t *)j;
29 terminx 765
        }
5 Plagman 766
 
1229 terminx 767
    for (i=0; i<MAXTILES; i++)
331 terminx 768
        if (actorLoadEventScrptr[i])
29 terminx 769
        {
792 qbix79 770
            j = (intptr_t)actorLoadEventScrptr[i]-(intptr_t)&script[0];
771
            actorLoadEventScrptr[i] = (intptr_t *)j;
29 terminx 772
        }
1378 qbix79 773
    dfwrite(&actorLoadEventScrptr[0],sizeof(actorLoadEventScrptr[0]),MAXTILES,fil);
1229 terminx 774
    for (i=0; i<MAXTILES; i++)
331 terminx 775
        if (actorLoadEventScrptr[i])
29 terminx 776
        {
792 qbix79 777
            j = (intptr_t)actorLoadEventScrptr[i]+(intptr_t)&script[0];
778
            actorLoadEventScrptr[i] = (intptr_t *)j;
29 terminx 779
        }
5 Plagman 780
 
1082 terminx 781
    Bfree(scriptptrs);
782
    scriptptrs = Bcalloc(1, MAXSPRITES * sizeof(scriptptrs));
5 Plagman 783
 
1229 terminx 784
    for (i=0; i<MAXSPRITES; i++)
5 Plagman 785
    {
786
        scriptptrs[i] = 0;
787
 
331 terminx 788
        if (actorscrptr[PN] == 0) continue;
5 Plagman 789
 
792 qbix79 790
        j = (intptr_t)&script[0];
5 Plagman 791
 
1143 terminx 792
        if (T2 >= j && T2 < (intptr_t)(&script[g_scriptSize]))
5 Plagman 793
        {
794
            scriptptrs[i] |= 1;
795
            T2 -= j;
796
        }
1143 terminx 797
        if (T5 >= j && T5 < (intptr_t)(&script[g_scriptSize]))
5 Plagman 798
        {
799
            scriptptrs[i] |= 2;
800
            T5 -= j;
801
        }
1143 terminx 802
        if (T6 >= j && T6 < (intptr_t)(&script[g_scriptSize]))
5 Plagman 803
        {
804
            scriptptrs[i] |= 4;
805
            T6 -= j;
806
        }
807
    }
808
 
567 terminx 809
    dfwrite(&scriptptrs[0],sizeof(scriptptrs),MAXSPRITES,fil);
1677 terminx 810
    dfwrite(&actor[0],sizeof(actor_t),MAXSPRITES,fil);
5 Plagman 811
 
1229 terminx 812
    for (i=0; i<MAXSPRITES; i++)
5 Plagman 813
    {
331 terminx 814
        if (actorscrptr[PN] == 0) continue;
792 qbix79 815
        j = (intptr_t)&script[0];
5 Plagman 816
 
331 terminx 817
        if (scriptptrs[i]&1)
5 Plagman 818
            T2 += j;
331 terminx 819
        if (scriptptrs[i]&2)
5 Plagman 820
            T5 += j;
331 terminx 821
        if (scriptptrs[i]&4)
5 Plagman 822
            T6 += j;
823
    }
824
 
825
    dfwrite(&lockclock,sizeof(lockclock),1,fil);
826
    dfwrite(&pskybits,sizeof(pskybits),1,fil);
827
    dfwrite(&pskyoff[0],sizeof(pskyoff[0]),MAXPSKYTILES,fil);
1143 terminx 828
    dfwrite(&g_animateCount,sizeof(g_animateCount),1,fil);
1378 qbix79 829
    dfwrite(&animatesect[0],sizeof(animatesect[0]),MAXANIMATES,fil);
1229 terminx 830
    for (i = g_animateCount-1; i>=0; i--) animateptr[i] = (int32_t *)((intptr_t)animateptr[i]-(intptr_t)(&sector[0]));
1378 qbix79 831
    dfwrite(&animateptr[0],sizeof(animateptr[0]),MAXANIMATES,fil);
1229 terminx 832
    for (i = g_animateCount-1; i>=0; i--) animateptr[i] = (int32_t *)((intptr_t)animateptr[i]+(intptr_t)(&sector[0]));
1378 qbix79 833
    dfwrite(&animategoal[0],sizeof(animategoal[0]),MAXANIMATES,fil);
834
    dfwrite(&animatevel[0],sizeof(animatevel[0]),MAXANIMATES,fil);
5 Plagman 835
 
1143 terminx 836
    dfwrite(&g_earthquakeTime,sizeof(g_earthquakeTime),1,fil);
5 Plagman 837
    dfwrite(&ud.from_bonus,sizeof(ud.from_bonus),1,fil);
838
    dfwrite(&ud.secretlevel,sizeof(ud.secretlevel),1,fil);
839
    dfwrite(&ud.respawn_monsters,sizeof(ud.respawn_monsters),1,fil);
840
    dfwrite(&ud.respawn_items,sizeof(ud.respawn_items),1,fil);
841
    dfwrite(&ud.respawn_inventory,sizeof(ud.respawn_inventory),1,fil);
842
    dfwrite(&ud.god,sizeof(ud.god),1,fil);
843
    dfwrite(&ud.auto_run,sizeof(ud.auto_run),1,fil);
844
    dfwrite(&ud.crosshair,sizeof(ud.crosshair),1,fil);
845
    dfwrite(&ud.monsters_off,sizeof(ud.monsters_off),1,fil);
846
    dfwrite(&ud.last_level,sizeof(ud.last_level),1,fil);
847
    dfwrite(&ud.eog,sizeof(ud.eog),1,fil);
848
    dfwrite(&ud.coop,sizeof(ud.coop),1,fil);
849
    dfwrite(&ud.marker,sizeof(ud.marker),1,fil);
850
    dfwrite(&ud.ffire,sizeof(ud.ffire),1,fil);
851
    dfwrite(&camsprite,sizeof(camsprite),1,fil);
852
    dfwrite(&connecthead,sizeof(connecthead),1,fil);
853
    dfwrite(connectpoint2,sizeof(connectpoint2),1,fil);
1143 terminx 854
    dfwrite(&g_numPlayerSprites,sizeof(g_numPlayerSprites),1,fil);
1229 terminx 855
    for (i=0; i<MAXPLAYERS; i++)
1205 terminx 856
        dfwrite((int16_t *)&g_player[i].frags[0],sizeof(g_player[i].frags),1,fil);
5 Plagman 857
 
858
    dfwrite(&randomseed,sizeof(randomseed),1,fil);
1143 terminx 859
    dfwrite(&g_globalRandom,sizeof(g_globalRandom),1,fil);
5 Plagman 860
    dfwrite(&parallaxyscale,sizeof(parallaxyscale),1,fil);
861
 
1457 terminx 862
    dfwrite(&SpriteProjectile[0],sizeof(projectile_t),MAXSPRITES,fil);
1143 terminx 863
    dfwrite(&ProjectileData[0],sizeof(projectile_t),MAXTILES,fil);
864
    dfwrite(&DefaultProjectileData[0],sizeof(projectile_t),MAXTILES,fil);
5 Plagman 865
 
1143 terminx 866
    dfwrite(&SpriteFlags[0],sizeof(SpriteFlags[0]),MAXTILES,fil);
105 terminx 867
 
1143 terminx 868
    dfwrite(&SpriteCacheList[0],sizeof(SpriteCacheList[0]),MAXTILES,fil);
105 terminx 869
 
1229 terminx 870
    for (i=0; i<MAXQUOTES; i++)
105 terminx 871
    {
1143 terminx 872
        if (ScriptQuotes[i] != NULL)
105 terminx 873
        {
1205 terminx 874
            dfwrite(&i,sizeof(int32_t),1,fil);
1143 terminx 875
            dfwrite(ScriptQuotes[i],MAXQUOTELEN, 1, fil);
105 terminx 876
        }
877
    }
1205 terminx 878
    dfwrite(&i,sizeof(int32_t),1,fil);
105 terminx 879
 
1143 terminx 880
    dfwrite(&g_numQuoteRedefinitions,sizeof(g_numQuoteRedefinitions),1,fil);
1229 terminx 881
    for (i=0; i<g_numQuoteRedefinitions; i++)
105 terminx 882
    {
1143 terminx 883
        if (ScriptQuoteRedefinitions[i] != NULL)
884
            dfwrite(ScriptQuoteRedefinitions[i],MAXQUOTELEN, 1, fil);
105 terminx 885
    }
886
 
1143 terminx 887
    dfwrite(&DynamicTileMap[0],sizeof(DynamicTileMap[0]),MAXTILES,fil);
114 terminx 888
 
147 terminx 889
    dfwrite(&ud.noexits,sizeof(ud.noexits),1,fil);
890
 
1595 helixhorne 891
    Gv_WriteSave(fil, 0);
5 Plagman 892
 
893
    fclose(fil);
894
 
1587 terminx 895
    if ((!g_netServer && ud.multimode < 2))
5 Plagman 896
    {
1143 terminx 897
        strcpy(ScriptQuotes[122],"GAME SAVED");
898
        P_DoQuote(122,g_player[myconnectindex].ps);
5 Plagman 899
    }
900
 
901
    ready2send = 1;
902
 
1574 terminx 903
    Net_WaitForServer();
5 Plagman 904
 
905
    ototalclock = totalclock;
906
 
907
    return(0);
908
}
1595 helixhorne 909
 
910
 
911
////////// GENERIC SAVING/LOADING SYSTEM //////////
912
 
913
typedef struct dataspec_
914
{
915
    uint32_t flags;
916
    void *ptr;
917
    uint32_t size;
918
    intptr_t cnt;
919
} dataspec_t;
920
 
921
#define SV_MAJOR_VER 0
1598 helixhorne 922
#define SV_MINOR_VER 2
1595 helixhorne 923
#define SV_DEFAULTCOMPRTHRES 8
924
static uint8_t savegame_diffcompress;  // 0:none, 1:Ken's LZW in cache1d.c
925
static uint8_t savegame_comprthres;
926
 
927
 
928
#define DS_DYNAMIC 1  // dereference .ptr one more time
929
#define DS_STRING 2
930
#define DS_CMP 4
931
// 8
932
#define DS_CNT(x) ((sizeof(x))<<3)  // .cnt is pointer to...
933
#define DS_CNT16 16
934
#define DS_CNT32 32
935
#define DS_CNTMASK (8|DS_CNT16|DS_CNT32|64)
936
// 64
937
#define DS_LOADFN 128  // .ptr is function that is run when loading
938
#define DS_SAVEFN 256  // .ptr is function that is run when saving
939
#define DS_NOCHK 1024  // don't check for diffs (and don't write out in dump) since assumend constant throughout demo
940
#define DS_END (0x70000000)
941
 
942
static int32_t ds_getcnt(const dataspec_t *sp)
943
{
944
    switch (sp->flags&DS_CNTMASK)
945
    {
1599 terminx 946
    case 0: return sp->cnt;
1595 helixhorne 947
    case DS_CNT16: return *((int16_t *)sp->cnt);
948
    case DS_CNT32: return *((int32_t *)sp->cnt);
949
    default: return -1;
950
    }
951
}
952
 
1598 helixhorne 953
static void ds_get(const dataspec_t *sp, const void **ptr, int32_t *cnt)
1595 helixhorne 954
{
955
    *cnt = ds_getcnt(sp);
956
 
957
    if (sp->flags&DS_DYNAMIC)
958
        *ptr = *((void **)sp->ptr);
959
    else
960
        *ptr = sp->ptr;
961
}
962
 
963
// write state to file and/or to dump
964
static uint8_t *writespecdata(const dataspec_t *spec, FILE *fil, uint8_t *dump)
965
{
966
    int32_t cnt;
967
    const void *ptr;
968
    const dataspec_t *sp=spec;
969
 
970
    for (; sp->flags!=DS_END; sp++)
971
    {
972
        if (sp->flags&(DS_SAVEFN|DS_LOADFN))
973
        {
974
            if (sp->flags&DS_SAVEFN)
1677 terminx 975
                (*(void ( *)(void))sp->ptr)();
1595 helixhorne 976
            continue;
977
        }
978
 
979
        if (!fil && (sp->flags&(DS_NOCHK|DS_CMP|DS_STRING)))
980
            continue;
981
 
982
        if (sp->flags&DS_STRING)
983
        {
984
            fwrite(sp->ptr, Bstrlen(sp->ptr), 1, fil);  // not null-terminated!
985
            continue;
986
        }
987
 
988
        ds_get(sp, &ptr, &cnt);
989
        if (cnt < 0) { OSD_Printf("wsd: cnt=%d, f=0x%x.\n",cnt,sp->flags); continue; }
990
 
991
        if (fil)
992
        {
1677 terminx 993
            if (((sp->flags&DS_CNTMASK)==0 && sp->size *cnt<=(int32_t)savegame_comprthres)
1599 terminx 994
                    || (sp->flags&DS_CMP))
1595 helixhorne 995
                fwrite(ptr, sp->size, cnt, fil);
996
            else
997
                dfwrite((void *)ptr, sp->size, cnt, fil);
998
        }
999
 
1000
        if (dump && (sp->flags&(DS_NOCHK|DS_CMP))==0)
1001
        {
1002
            Bmemcpy(dump, ptr, sp->size*cnt);
1003
            dump += sp->size*cnt;
1004
        }
1005
    }
1006
    return dump;
1007
}
1008
 
1009
// let havedump=dumpvar&&*dumpvar
1010
// (fil>=0 && havedump): first restore dump from file, then restore state from dump
1011
// (fil<0 && havedump): only restore state from dump
1012
// (fil>=0 && !havedump): only restore state from file
1013
static int32_t readspecdata(const dataspec_t *spec, int32_t fil, uint8_t **dumpvar)
1014
{
1015
    int32_t cnt, i, j;
1016
    void *ptr;
1017
    uint8_t *dump=dumpvar?*dumpvar:NULL, *mem;
1018
    const dataspec_t *sp=spec;
1019
    static char cmpstrbuf[32];
1020
 
1021
    for (; sp->flags!=DS_END; sp++)
1022
    {
1023
        if (fil < 0 && sp->flags&(DS_NOCHK|DS_STRING|DS_CMP))  // we're updating
1024
            continue;
1025
 
1026
        if (sp->flags&(DS_LOADFN|DS_SAVEFN))
1027
        {
1028
            if (sp->flags&DS_LOADFN)
1677 terminx 1029
                (*(void ( *)())sp->ptr)();
1595 helixhorne 1030
            continue;
1031
        }
1032
 
1033
        if (sp->flags&(DS_STRING|DS_CMP))  // DS_STRING and DS_CMP is for static data only
1034
        {
1035
            if (sp->flags&(DS_STRING))
1036
                i = Bstrlen(sp->ptr);
1037
            else
1038
                i = sp->size*sp->cnt;
1039
 
1040
            j=kread(fil, cmpstrbuf, i);
1041
            if (j!=i || Bmemcmp(sp->ptr, cmpstrbuf, i))
1042
            {
1043
                OSD_Printf("rds: spec=%p, sp=%p ", spec, sp);
1044
                if (j!=i)
1045
                    OSD_Printf("kread returned %d, expected %d.\n", j, i);
1046
                else
1047
                    OSD_Printf("sp->ptr and cmpstrbuf not identical!\n");
1048
//                *(int32_t *)0 = 1;
1049
                return -1;
1050
            }
1051
            continue;
1052
        }
1053
 
1598 helixhorne 1054
        ds_get(sp, (const void **)&ptr, &cnt);
1595 helixhorne 1055
        if (cnt < 0) { OSD_Printf("rsd: cnt<0... wtf?\n"); return -1; }
1056
 
1057
        if (fil>=0)
1058
        {
1059
            mem = (dump && (sp->flags&DS_NOCHK)==0) ? dump : ptr;
1060
 
1677 terminx 1061
            if ((sp->flags&DS_CNTMASK)==0 && sp->size *cnt<=(int32_t)savegame_comprthres)
1595 helixhorne 1062
            {
1063
                i = kread(fil, mem, cnt*sp->size);
1064
                j = cnt*sp->size;
1065
            }
1066
            else
1067
            {
1068
                i = kdfread(mem, sp->size, cnt, fil);
1069
                j = cnt;
1070
            }
1071
            if (i!=j)
1072
            {
1073
                OSD_Printf("rsd: spec=%p, sp=%p, mem=%p ", spec, sp, mem);
1074
                OSD_Printf("rsd: %s: read %d, expected %d!\n",
1677 terminx 1075
                           ((sp->flags&DS_CNTMASK)==0 && sp->size *cnt<=(int32_t)savegame_comprthres)?
1595 helixhorne 1076
                           "UNCOMP":"COMPR", i, j);
1599 terminx 1077
 
1595 helixhorne 1078
                if (i==-1)
1079
                    perror("read");
1080
//            *(int32_t *)0 = 1;
1081
                return -1;
1082
            }
1083
        }
1084
 
1085
        if (dump && (sp->flags&DS_NOCHK)==0)
1086
        {
1087
            Bmemcpy(ptr, dump, sp->size*cnt);
1088
            dump += sp->size*cnt;
1089
        }
1090
    }
1091
 
1092
    if (dumpvar)
1093
        *dumpvar = dump;
1094
    return 0;
1095
}
1096
 
1097
#define UINT(bits) uint##bits##_t
1098
#define BYTES(bits) (bits>>3)
1099
#define VAL(bits,p) (*(UINT(bits) *)(p))
1100
 
1101
static void docmpsd(const void *ptr, void *dump, uint32_t size, uint32_t cnt, uint8_t **diffvar)
1102
{
1103
    uint8_t *retdiff = *diffvar;
1104
 
1105
    // Hail to the C preprocessor, baby!
1599 terminx 1106
#define CPSINGLEVAL(Datbits) \
1595 helixhorne 1107
        if (VAL(Datbits, ptr) != VAL(Datbits, dump))  \
1108
        {                                             \
1109
            VAL(Datbits, retdiff) = VAL(Datbits, dump) = VAL(Datbits, ptr); \
1110
            *diffvar = retdiff+BYTES(Datbits);        \
1111
        }
1112
 
1113
    if (cnt==1)
1114
        switch (size)
1115
        {
1116
        case 8: CPSINGLEVAL(64); return;
1117
        case 4: CPSINGLEVAL(32); return;
1118
        case 2: CPSINGLEVAL(16); return;
1119
        case 1: CPSINGLEVAL(8); return;
1120
        }
1121
 
1599 terminx 1122
#define CPELTS(Idxbits, Datbits) do \
1595 helixhorne 1123
    {                                         \
1124
        for (i=0; i<nelts; i++)               \
1125
        {                                     \
1126
            if (*p!=*op)                      \
1127
            {                                 \
1128
                *op = *p;                     \
1129
                VAL(Idxbits, retdiff) = i;    \
1130
                retdiff += BYTES(Idxbits);    \
1131
                VAL(Datbits, retdiff) = *p;   \
1132
                retdiff += BYTES(Datbits);    \
1133
            }                                 \
1134
            p++;                              \
1135
            op++;                             \
1136
        }                                     \
1137
        VAL(Idxbits, retdiff) = -1;           \
1138
        retdiff += BYTES(Idxbits);            \
1139
    } while (0)
1140
 
1599 terminx 1141
#define CPDATA(Datbits) do \
1595 helixhorne 1142
    { \
1143
        const UINT(Datbits) *p=ptr;  \
1144
        UINT(Datbits) *op=dump;      \
1145
        uint32_t i, nelts=(size*cnt)/BYTES(Datbits); \
1146
        if (nelts>65536)          \
1147
            CPELTS(32,Datbits);   \
1148
        else if (nelts>256)       \
1149
            CPELTS(16,Datbits);   \
1150
        else                      \
1151
            CPELTS(8,Datbits);    \
1152
    } while (0)
1153
 
1154
    if (size==8)
1155
        CPDATA(64);
1156
    else if ((size&3)==0)
1157
        CPDATA(32);
1158
    else if ((size&1)==0)
1159
        CPDATA(16);
1160
    else
1161
        CPDATA(8);
1162
 
1163
    *diffvar = retdiff;
1164
    return;
1165
 
1599 terminx 1166
#undef CPELTS
1167
#undef CPSINGLEVAL
1168
#undef CPDATA
1595 helixhorne 1169
}
1170
 
1171
// get the number of elements to be monitored for changes
1172
static int32_t getnumvar(const dataspec_t *spec)
1173
{
1174
    int32_t n=0;
1599 terminx 1175
    for (; spec->flags!=DS_END; spec++)
1595 helixhorne 1176
        n += (spec->flags&(DS_STRING|DS_CMP|DS_NOCHK|DS_SAVEFN|DS_LOADFN) ? 0 : 1);
1177
    return n;
1178
}
1179
 
1180
// update dump at *dumpvar with new state and write diff to *diffvar
1181
static void cmpspecdata(const dataspec_t *spec, uint8_t **dumpvar, uint8_t **diffvar)
1182
{
1183
    const void *ptr;
1184
    uint8_t *dump=*dumpvar, *diff=*diffvar, *tmptr;
1185
    const dataspec_t *sp=spec;
1186
    int32_t cnt, eltnum=0, nbytes=(getnumvar(spec)+7)>>3, l=Bstrlen(spec->ptr);
1187
 
1188
    Bmemcpy(diff, spec->ptr, l);
1189
    diff+=l;
1190
 
1191
    while (nbytes--)
1192
        *(diff++) = 0;  // the bitmap of indices which elements of spec have changed go here
1193
 
1194
    for (sp++; sp->flags!=DS_END; sp++)
1195
    {
1196
        if ((sp->flags&(DS_NOCHK|DS_STRING|DS_CMP)))
1197
            continue;
1198
 
1199
        if (sp->flags&(DS_LOADFN|DS_SAVEFN))
1200
        {
1677 terminx 1201
            (*(void ( *)())sp->ptr)();
1595 helixhorne 1202
            continue;
1203
        }
1204
 
1205
        ds_get(sp, &ptr, &cnt);
1206
        if (cnt < 0) { OSD_Printf("csd: cnt=%d, f=0x%x\n", cnt, sp->flags); continue; }
1207
 
1208
        tmptr = diff;
1209
        docmpsd(ptr, dump, sp->size, cnt, &diff);
1210
        if (diff != tmptr)
1211
            (*diffvar + l)[eltnum>>3] |= 1<<(eltnum&7);
1212
        dump += sp->size*cnt;
1213
        eltnum++;
1214
    }
1215
 
1216
    *diffvar = diff;
1217
    *dumpvar = dump;
1218
    return;
1219
}
1220
 
1221
#define VALOFS(bits,p,ofs) (*(((UINT(bits) *)(p)) + (ofs)))
1222
 
1223
// apply diff to dump, not to state! state is restored from dump afterwards.
1224
static int32_t applydiff(const dataspec_t *spec, uint8_t **dumpvar, uint8_t **diffvar)
1225
{
1226
    uint8_t *dumptr=*dumpvar, *diffptr=*diffvar;
1227
    const dataspec_t *sp=spec;
1228
    int32_t cnt, eltnum=-1, nbytes=(getnumvar(spec)+7)>>3, l=Bstrlen(spec->ptr);
1229
 
1230
    if (Bmemcmp(diffptr, spec->ptr, l))  // check STRING magic (sync check)
1231
    {
1232
//        *(int32_t *)0 = 1;
1233
        return 1;
1234
    }
1235
    diffptr += l+nbytes;
1236
 
1237
    for (sp++; sp->flags!=DS_END; sp++)
1238
    {
1239
        if ((sp->flags&(DS_NOCHK|DS_STRING|DS_CMP|DS_LOADFN|DS_SAVEFN)))
1240
            continue;
1241
 
1242
        cnt = ds_getcnt(sp);
1243
        if (cnt < 0) return 1;
1244
 
1245
        eltnum++;
1246
        if (((*diffvar + l)[eltnum>>3]&(1<<(eltnum&7))) == 0)
1247
        {
1248
            dumptr += sp->size*cnt;
1249
            continue;
1250
        }
1251
 
1252
// ----------
1599 terminx 1253
#define CPSINGLEVAL(Datbits) \
1595 helixhorne 1254
            VAL(Datbits, dumptr) = VAL(Datbits, diffptr); \
1255
            diffptr += BYTES(Datbits); \
1256
            dumptr += BYTES(Datbits)
1257
 
1258
        if (cnt==1)
1259
        {
1260
            switch (sp->size)
1261
            {
1262
            case 8: CPSINGLEVAL(64); continue;
1263
            case 4: CPSINGLEVAL(32); continue;
1264
            case 2: CPSINGLEVAL(16); continue;
1265
            case 1: CPSINGLEVAL(8); continue;
1266
            }
1267
        }
1268
 
1599 terminx 1269
#define CPELTS(Idxbits, Datbits) do \
1595 helixhorne 1270
        {                                    \
1271
            UINT(Idxbits) idx;               \
1272
            goto readidx_##Idxbits##_##Datbits; \
1273
            do                               \
1274
            {                                \
1275
                VALOFS(Datbits, dumptr, idx) = VAL(Datbits, diffptr); \
1276
                diffptr += BYTES(Datbits);   \
1277
readidx_##Idxbits##_##Datbits:               \
1278
                idx = VAL(Idxbits, diffptr); \
1279
                diffptr += BYTES(Idxbits);   \
1280
            } while ((int##Idxbits##_t)idx != -1);  \
1281
        } while (0)
1282
 
1599 terminx 1283
#define CPDATA(Datbits) do \
1595 helixhorne 1284
        {                             \
1285
            uint32_t nelts=(sp->size*cnt)/BYTES(Datbits); \
1286
            if (nelts>65536)          \
1287
                CPELTS(32,Datbits);   \
1288
            else if (nelts>256)       \
1289
                CPELTS(16,Datbits);   \
1290
            else                      \
1291
                CPELTS(8,Datbits);    \
1292
        } while (0)
1293
 
1294
        if (sp->size==8)
1295
            CPDATA(64);
1296
        else if ((sp->size&3)==0)
1297
            CPDATA(32);
1298
        else if ((sp->size&1)==0)
1299
            CPDATA(16);
1300
        else
1301
            CPDATA(8);
1302
        dumptr += sp->size*cnt;
1303
// ----------
1304
 
1599 terminx 1305
#undef CPELTS
1306
#undef CPSINGLEVAL
1307
#undef CPDATA
1595 helixhorne 1308
    }
1309
 
1310
    *diffvar = diffptr;
1311
    *dumpvar = dumptr;
1312
    return 0;
1313
}
1314
 
1315
#undef VAL
1316
#undef VALOFS
1317
#undef BYTES
1318
#undef UINT
1319
 
1320
// calculate size needed for dump
1321
static uint32_t calcsz(const dataspec_t *spec)
1322
{
1323
    const dataspec_t *sp=spec;
1324
    int32_t cnt;
1325
    uint32_t dasiz=0;
1326
 
1327
    for (; sp->flags!=DS_END; sp++)
1328
    {
1329
        // DS_STRINGs are used as sync checks in the diffs but not in the dump
1330
        if ((sp->flags&(DS_CMP|DS_NOCHK|DS_SAVEFN|DS_LOADFN|DS_STRING)))
1331
            continue;
1332
 
1333
        cnt = ds_getcnt(sp);
1334
        if (cnt<=0) continue;
1335
 
1336
        dasiz += cnt*sp->size;
1337
    }
1338
 
1339
    return dasiz;
1340
}
1341
 
1596 plagman 1342
static void sv_postudload();
1343
static void sv_prespriteextsave();
1344
static void sv_postspriteext();
1345
static void sv_calcbitptrsize();
1346
static void sv_prescriptsave_once();
1598 helixhorne 1347
static void sv_prescriptload_once();
1596 plagman 1348
static void sv_postscript_once();
1349
static void sv_preactordatasave();
1350
static void sv_postactordata();
1351
static void sv_preanimateptrsave();
1352
static void sv_postanimateptr();
1353
static void sv_prequote();
1354
static void sv_quotesave();
1355
static void sv_quoteload();
1356
static void sv_prequoteredef();
1357
static void sv_quoteredefsave();
1358
static void sv_quoteredefload();
1359
static void sv_postquoteredef();
1360
static void sv_restsave();
1361
static void sv_restload();
1362
 
1363
#define SVARDATALEN \
1364
    ((sizeof(g_player[0].user_name)+sizeof(g_player[0].pcolor)+sizeof(g_player[0].pteam) \
1365
      +sizeof(g_player[0].frags)+sizeof(DukePlayer_t))*MAXPLAYERS + sizeof(_prlight)*PR_MAXLIGHTS + sizeof(lightcount))
1366
 
1367
static uint8_t savegame_bitmap[MAXSPRITES>>3][3];
1368
static uint32_t savegame_bitptrsize;
1369
static uint8_t savegame_quotedef[MAXQUOTES>>3];
1599 terminx 1370
static char(*savegame_quotes)[MAXQUOTELEN];
1371
static char(*savegame_quoteredefs)[MAXQUOTELEN];
1596 plagman 1372
static uint8_t savegame_restdata[SVARDATALEN];
1373
 
1374
static const dataspec_t svgm_udnetw[] =
1375
{
1376
    { DS_STRING, "blK:udnt", 0, 1 },
1377
    { 0, &ud.multimode, sizeof(ud.multimode), 1 },
1378
    { 0, &g_numPlayerSprites, sizeof(g_numPlayerSprites), 1 },
1379
    { 0, &g_playerSpawnPoints, sizeof(g_playerSpawnPoints), 1 },
1380
 
1381
    { DS_NOCHK, &ud.volume_number, sizeof(ud.volume_number), 1 },
1382
    { DS_NOCHK, &ud.level_number, sizeof(ud.level_number), 1 },
1383
    { DS_NOCHK, &ud.player_skill, sizeof(ud.player_skill), 1 },
1384
 
1385
    { DS_NOCHK, &ud.from_bonus, sizeof(ud.from_bonus), 1 },
1386
    { DS_NOCHK, &ud.secretlevel, sizeof(ud.secretlevel), 1 },
1387
    { DS_NOCHK, &ud.respawn_monsters, sizeof(ud.respawn_monsters), 1 },
1388
    { DS_NOCHK, &ud.respawn_items, sizeof(ud.respawn_items), 1 },
1389
    { DS_NOCHK, &ud.respawn_inventory, sizeof(ud.respawn_inventory), 1 },
1390
    { 0, &ud.god, sizeof(ud.god), 1 },
1391
    { 0, &ud.auto_run, sizeof(ud.auto_run), 1 },
1392
//    { DS_NOCHK, &ud.crosshair, sizeof(ud.crosshair), 1 },
1393
    { DS_NOCHK, &ud.monsters_off, sizeof(ud.monsters_off), 1 },
1394
    { DS_NOCHK, &ud.last_level, sizeof(ud.last_level), 1 },
1395
    { 0, &ud.eog, sizeof(ud.eog), 1 },
1396
    { DS_NOCHK, &ud.coop, sizeof(ud.coop), 1 },
1397
    { DS_NOCHK, &ud.marker, sizeof(ud.marker), 1 },
1398
    { DS_NOCHK, &ud.ffire, sizeof(ud.ffire), 1 },
1399
    { DS_NOCHK, &ud.noexits, sizeof(ud.noexits), 1 },
1400
    { DS_NOCHK, &ud.playerai, sizeof(ud.playerai), 1 },
1598 helixhorne 1401
    { 0, &ud.pause_on, sizeof(ud.pause_on), 1 },
1596 plagman 1402
    { DS_NOCHK, &currentboardfilename[0], BMAX_PATH, 1 },
1403
    { DS_LOADFN, (void *)&sv_postudload, 0, 1 },
1404
    { 0, &connecthead, sizeof(connecthead), 1 },
1405
    { 0, connectpoint2, sizeof(connectpoint2), 1 },
1406
    { 0, &randomseed, sizeof(randomseed), 1 },
1407
    { 0, &g_globalRandom, sizeof(g_globalRandom), 1 },
1408
//    { 0, &lockclock_dummy, sizeof(lockclock), 1 },
1409
    { DS_END, 0, 0, 0 }
1410
};
1411
 
1412
static const dataspec_t svgm_secwsp[] =
1413
{
1414
    { DS_STRING, "blK:swsp", 0, 1 },
1415
    { DS_NOCHK, &numwalls, sizeof(numwalls), 1 },
1416
    { DS_DYNAMIC|DS_CNT(numwalls), &wall, sizeof(walltype), (intptr_t)&numwalls },
1417
    { DS_NOCHK, &numsectors, sizeof(numsectors), 1 },
1418
    { DS_DYNAMIC|DS_CNT(numsectors), &sector, sizeof(sectortype), (intptr_t)&numsectors },
1419
    { DS_DYNAMIC, &sprite, sizeof(spritetype), MAXSPRITES },
1420
    { 0, &headspritesect[0], sizeof(headspritesect[0]), MAXSECTORS+1 },
1421
    { 0, &prevspritesect[0], sizeof(prevspritesect[0]), MAXSPRITES },
1422
    { 0, &nextspritesect[0], sizeof(nextspritesect[0]), MAXSPRITES },
1423
    { 0, &headspritestat[0], sizeof(headspritestat[0]), MAXSTATUS+1 },
1424
    { 0, &prevspritestat[0], sizeof(prevspritestat[0]), MAXSPRITES },
1425
    { 0, &nextspritestat[0], sizeof(nextspritestat[0]), MAXSPRITES },
1426
#if defined(POLYMOST) && defined(USE_OPENGL)
1427
    { DS_SAVEFN, (void *)&sv_prespriteextsave, 0, 1 },
1428
#endif
1429
    { DS_DYNAMIC, &spriteext, sizeof(spriteext_t), MAXSPRITES },
1430
#if defined(POLYMOST) && defined(USE_OPENGL)
1431
    { DS_SAVEFN|DS_LOADFN, (void *)&sv_postspriteext, 0, 1 },
1432
#endif
1433
    { DS_NOCHK, &SpriteFlags[0], sizeof(SpriteFlags[0]), MAXTILES },
1434
    { DS_NOCHK, &SpriteCacheList[0], sizeof(SpriteCacheList[0]), MAXTILES },
1435
    { 0, &DynamicTileMap[0], sizeof(DynamicTileMap[0]), MAXTILES },  // NOCHK?
1436
    { DS_NOCHK, &ActorType[0], sizeof(uint8_t), MAXTILES },
1437
    { DS_NOCHK, &g_numCyclers, sizeof(g_numCyclers), 1 },
1438
    { DS_CNT(g_numCyclers), &cyclers[0][0], sizeof(cyclers[0]), (intptr_t)&g_numCyclers },
1439
    { DS_NOCHK, &g_numAnimWalls, sizeof(g_numAnimWalls), 1 },
1440
    { DS_CNT(g_numAnimWalls), &animwall, sizeof(animwall[0]), (intptr_t)&g_numAnimWalls },
1441
    { DS_NOCHK, &g_mirrorCount, sizeof(g_mirrorCount), 1 },
1442
    { DS_NOCHK, &g_mirrorWall[0], sizeof(g_mirrorWall[0]), sizeof(g_mirrorWall)/sizeof(g_mirrorWall[0]) },
1443
    { DS_NOCHK, &g_mirrorSector[0], sizeof(g_mirrorSector[0]), sizeof(g_mirrorSector)/sizeof(g_mirrorSector[0]) },
1444
// projectiles
1445
    { 0, &SpriteProjectile[0], sizeof(projectile_t), MAXSPRITES },
1446
    { 0, &ProjectileData[0], sizeof(projectile_t), MAXTILES },
1447
    { DS_NOCHK, &DefaultProjectileData[0], sizeof(projectile_t), MAXTILES },
1448
    { 0, &everyothertime, sizeof(everyothertime), 1 },
1449
    { DS_END, 0, 0, 0 }
1450
};
1451
 
1452
static const dataspec_t svgm_script[] =
1453
{
1454
    { DS_STRING, "blK:scri", 0, 1 },
1455
    { DS_NOCHK, &g_scriptSize, sizeof(g_scriptSize), 1 },
1456
    { DS_SAVEFN|DS_LOADFN|DS_NOCHK, (void *)&sv_calcbitptrsize, 0, 1 },
1457
    { DS_DYNAMIC|DS_CNT(savegame_bitptrsize)|DS_NOCHK, &bitptr, sizeof(bitptr[0]), (intptr_t)&savegame_bitptrsize },
1458
 
1459
    { DS_SAVEFN|DS_NOCHK, (void *)&sv_prescriptsave_once, 0, 1 },
1460
    { DS_NOCHK, &actorscrptr[0], sizeof(actorscrptr[0]), MAXTILES },
1598 helixhorne 1461
    { DS_LOADFN|DS_NOCHK, (void *)&sv_prescriptload_once, 0, 1 },
1596 plagman 1462
    { DS_DYNAMIC|DS_CNT(g_scriptSize)|DS_NOCHK, &script, sizeof(script[0]), (intptr_t)&g_scriptSize },
1463
    { DS_NOCHK, &actorLoadEventScrptr[0], sizeof(actorLoadEventScrptr[0]), MAXTILES },
1464
//    { DS_NOCHK, &apScriptGameEvent[0], sizeof(apScriptGameEvent[0]), MAXGAMEEVENTS },
1465
    { DS_SAVEFN|DS_LOADFN|DS_NOCHK, (void *)&sv_postscript_once, 0, 1 },
1466
 
1467
    { DS_SAVEFN, (void *)&sv_preactordatasave, 0, 1 },
1468
    { 0, &savegame_bitmap, sizeof(savegame_bitmap), 1 },
1677 terminx 1469
    { 0, &actor[0], sizeof(actor_t), MAXSPRITES },
1596 plagman 1470
    { DS_SAVEFN|DS_LOADFN, (void *)&sv_postactordata, 0, 1 },
1471
 
1472
    { DS_END, 0, 0, 0 }
1473
};
1474
 
1475
static const dataspec_t svgm_anmisc[] =
1476
{
1477
    { DS_STRING, "blK:anms", 0, 1 },
1478
    { 0, &g_animateCount, sizeof(g_animateCount), 1 },
1479
    { 0, &animatesect[0], sizeof(animatesect[0]), MAXANIMATES },
1480
    { 0, &animategoal[0], sizeof(animategoal[0]), MAXANIMATES },
1481
    { 0, &animatevel[0], sizeof(animatevel[0]), MAXANIMATES },
1482
    { DS_SAVEFN, (void *)&sv_preanimateptrsave, 0, 1 },
1483
    { 0, &animateptr[0], sizeof(animateptr[0]), MAXANIMATES },
1484
    { DS_SAVEFN|DS_LOADFN , (void *)&sv_postanimateptr, 0, 1 },
1485
    { 0, &camsprite, sizeof(camsprite), 1 },
1486
    { 0, &msx[0], sizeof(msx[0]), sizeof(msx)/sizeof(msx[0]) },
1487
    { 0, &msy[0], sizeof(msy[0]), sizeof(msy)/sizeof(msy[0]) },
1598 helixhorne 1488
    { 0, &g_spriteDeleteQueuePos, sizeof(g_spriteDeleteQueuePos), 1 },
1489
    { DS_NOCHK, &g_spriteDeleteQueueSize, sizeof(g_spriteDeleteQueueSize), 1 },
1490
    { DS_CNT(g_spriteDeleteQueueSize), &SpriteDeletionQueue[0], sizeof(int16_t), (intptr_t)&g_spriteDeleteQueueSize },
1596 plagman 1491
    { 0, &show2dsector[0], sizeof(uint8_t), MAXSECTORS>>3 },
1492
    { DS_NOCHK, &g_numClouds, sizeof(g_numClouds), 1 },
1493
    { 0, &clouds[0], sizeof(clouds), 1 },
1494
    { 0, &cloudx[0], sizeof(cloudx), 1 },
1495
    { 0, &cloudy[0], sizeof(cloudy), 1 },
1496
    { DS_NOCHK, &parallaxyscale, sizeof(parallaxyscale), 1 },
1497
    { 0, &pskybits, sizeof(pskybits), 1 },
1498
    { 0, &pskyoff[0], sizeof(pskyoff[0]), MAXPSKYTILES },
1499
    { 0, &g_earthquakeTime, sizeof(g_earthquakeTime), 1 },
1500
 
1501
    { DS_SAVEFN|DS_LOADFN|DS_NOCHK, (void *)sv_prequote, 0, 1 },
1502
    { DS_SAVEFN, (void *)&sv_quotesave, 0, 1 },
1503
    { DS_NOCHK, &savegame_quotedef, sizeof(savegame_quotedef), 1 },  // quotes can change during runtime, but new quote numbers cannot be allocated
1504
    { DS_DYNAMIC, &savegame_quotes, MAXQUOTELEN, MAXQUOTES },
1505
    { DS_LOADFN, (void *)&sv_quoteload, 0, 1 },
1506
 
1507
    { DS_NOCHK, &g_numQuoteRedefinitions, sizeof(g_numQuoteRedefinitions), 1 },
1508
    { DS_NOCHK|DS_SAVEFN|DS_LOADFN, (void *)&sv_prequoteredef, 0, 1 },
1509
    { DS_NOCHK|DS_SAVEFN, (void *)&sv_quoteredefsave, 0, 1 },  // quote redefinitions replace quotes at runtime, but cannot be changed after CON compilation
1510
    { DS_NOCHK|DS_DYNAMIC|DS_CNT(g_numQuoteRedefinitions), &savegame_quoteredefs, MAXQUOTELEN, (intptr_t)&g_numQuoteRedefinitions },
1511
    { DS_NOCHK|DS_LOADFN, (void *)&sv_quoteredefload, 0, 1 },
1512
    { DS_NOCHK|DS_SAVEFN|DS_LOADFN, (void *)&sv_postquoteredef, 0, 1 },
1513
 
1514
    { DS_SAVEFN, (void *)&sv_restsave, 0, 1 },
1515
    { 0, savegame_restdata, 1, sizeof(savegame_restdata) },  // sz/cnt swapped for kdfread
1516
    { DS_LOADFN, (void *)&sv_restload, 0, 1 },
1517
 
1518
    { DS_STRING, "savegame_end", 0, 1 },
1519
    { DS_END, 0, 0, 0 }
1520
};
1521
 
1595 helixhorne 1522
static dataspec_t *svgm_vars=NULL;
1523
static uint8_t *dosaveplayer2(int32_t spot, FILE *fil, uint8_t *mem);
1524
static int32_t doloadplayer2(int32_t spot, int32_t fil, uint8_t **memptr);
1525
static void postloadplayer1();
1526
static void postloadplayer2();
1527
 
1528
// SVGM snapshot system
1529
static uint32_t svsnapsiz;
1530
static uint8_t *svsnapshot, *svinitsnap;
1531
static uint32_t svdiffsiz;
1532
static uint8_t *svdiff;
1533
 
1534
#include "gamedef.h"
1535
 
1598 helixhorne 1536
#define SV_SKIPMASK (/*GAMEVAR_SYSTEM|*/GAMEVAR_READONLY|GAMEVAR_INTPTR|    \
1595 helixhorne 1537
                     GAMEVAR_SHORTPTR|GAMEVAR_CHARPTR /*|GAMEVAR_NORESET*/ |GAMEVAR_SPECIAL)
1538
// setup gamevar data spec for snapshotting and diffing... gamevars must be loaded when called
1539
static void sv_makevarspec()
1540
{
1541
    static char *magic = "blK:vars";
1542
    int32_t i, j, numsavedvars=0, per;
1543
 
1544
    if (svgm_vars)
1545
        Bfree(svgm_vars);
1546
 
1547
    for (i=0; i<g_gameVarCount; i++)
1548
        numsavedvars += (aGameVars[i].dwFlags&SV_SKIPMASK) ? 0 : 1;
1549
 
1550
    svgm_vars = Bmalloc((numsavedvars+g_gameArrayCount+2)*sizeof(dataspec_t));
1551
 
1552
    svgm_vars[0].flags = DS_STRING;
1553
    svgm_vars[0].ptr = magic;
1554
    svgm_vars[0].cnt = 1;
1555
 
1556
    j=1;
1557
    for (i=0; i<g_gameVarCount; i++)
1558
    {
1559
        if (aGameVars[i].dwFlags&SV_SKIPMASK)
1560
            continue;
1561
 
1562
        per = aGameVars[i].dwFlags&GAMEVAR_USER_MASK;
1563
 
1564
        svgm_vars[j].flags = 0;
1565
        svgm_vars[j].ptr = (per==0) ? &aGameVars[i].val.lValue : aGameVars[i].val.plValues;
1566
        svgm_vars[j].size = sizeof(intptr_t);
1567
        svgm_vars[j].cnt = (per==0) ? 1 : (per==GAMEVAR_PERPLAYER ? MAXPLAYERS : MAXSPRITES);
1568
        j++;
1569
    }
1570
 
1571
    for (i=0; i<g_gameArrayCount; i++)
1572
    {
1573
        svgm_vars[j].flags = 0;
1574
        svgm_vars[j].ptr = aGameArrays[i].plValues;
1575
        svgm_vars[j].size = sizeof(aGameArrays[0].plValues[0]);
1576
        svgm_vars[j].cnt = aGameArrays[i].size;  // assumed constant throughout demo, i.e. no RESIZEARRAY
1577
        j++;
1578
    }
1579
 
1580
    svgm_vars[j].flags = DS_END;
1581
}
1582
 
1583
void sv_freemem()
1584
{
1585
    if (svsnapshot)
1586
        Bfree(svsnapshot), svsnapshot=NULL;
1587
    if (svinitsnap)
1588
        Bfree(svinitsnap), svinitsnap=NULL;
1589
    if (svdiff)
1590
        Bfree(svdiff), svdiff=NULL;
1591
//    if (svgm_vars)
1592
//        Bfree(svgm_vars), svgm_vars=NULL;
1593
}
1594
 
1595
static int32_t doallocsnap(int32_t allocinit)
1596
{
1597
    sv_freemem();
1598
 
1599
    svsnapshot = Bmalloc(svsnapsiz);
1600
    if (allocinit)
1601
        svinitsnap = Bmalloc(svsnapsiz);
1602
    svdiffsiz = svsnapsiz;  // theoretically it's less than could be needed in the worst case, but practically it's overkill
1603
    svdiff = Bmalloc(svdiffsiz);
1604
    if (svsnapshot==NULL || (allocinit && svinitsnap==0) || svdiff==NULL)
1605
    {
1606
        sv_freemem();
1607
        return 1;
1608
    }
1609
    return 0;
1610
}
1611
 
1677 terminx 1612
int32_t sv_saveandmakesnapshot(FILE *fil, int32_t recdiffs, int32_t diffcompress, int32_t synccompress)
1595 helixhorne 1613
{
1614
    uint8_t *p, tb;
1615
    uint16_t ts;
1616
 
1617
    fwrite("EDuke32demo", 11, 1, fil);//0 11b
1618
    tb = SV_MAJOR_VER;
1619
    fwrite(&tb, sizeof(tb), 1, fil);  //11 1b
1620
    tb = SV_MINOR_VER;
1621
    fwrite(&tb, sizeof(tb), 1, fil);  //12 1b
1622
    tb = sizeof(intptr_t);
1623
    fwrite(&tb, sizeof(tb), 1, fil);  //13 1b
1624
 
1625
    ts = BYTEVERSION;
1626
    fwrite(&ts, sizeof(ts), 1, fil);  //14 2b
1627
 
1628
    savegame_comprthres = SV_DEFAULTCOMPRTHRES;
1629
    fwrite(&savegame_comprthres, sizeof(savegame_comprthres), 1, fil);  //16 1b
1630
 
1631
    tb = recdiffs;
1632
    fwrite(&tb, sizeof(tb), 1, fil);  //17 1b
1633
 
1634
    savegame_diffcompress = (uint8_t)diffcompress;
1635
    fwrite(&savegame_diffcompress, sizeof(savegame_diffcompress), 1, fil);  //18 1b
1636
 
1637
    tb = (uint8_t)synccompress;
1638
    fwrite(&tb, sizeof(tb), 1, fil);  //19 1b
1639
 
1640
    sv_makevarspec();
1641
    svsnapsiz = 0;
1642
    fwrite(&svsnapsiz, sizeof(svsnapsiz), 1, fil);  // 20 4b record count for demos
1643
    svsnapsiz = calcsz(svgm_vars);
1644
    svsnapsiz += calcsz(svgm_udnetw) + calcsz(svgm_secwsp) + calcsz(svgm_script) + calcsz(svgm_anmisc);
1645
    fwrite(&svsnapsiz, sizeof(svsnapsiz), 1, fil);  // 24 4b
1646
 
1647
    OSD_Printf("sv_saveandmakesnapshot: size: %d bytes.\n", svsnapsiz);
1648
 
1649
    if (doallocsnap(0))
1650
    {
1651
        OSD_Printf("sv_saveandmakesnapshot: failed allocating memory.\n");
1652
        return 1;
1653
    }
1654
 
1655
    p = dosaveplayer2(-1, fil, svsnapshot);
1656
    if (p != svsnapshot+svsnapsiz)
1657
        OSD_Printf("sv_saveandmakesnapshot: ptr-(snapshot end)=%d!\n", (int32_t)(p-(svsnapshot+svsnapsiz)));
1658
 
1659
    return 0;
1660
}
1661
 
1662
int32_t sv_loadsnapshot(int32_t fil, int32_t *ret_hasdiffs, int32_t *ret_demoticcnt, int32_t *ret_synccompress)
1663
{
1664
    uint8_t *p, tmpbuf[11];
1665
    int32_t i;
1666
 
1667
    if (kread(fil, tmpbuf, 11) != 11) goto corrupt;
1668
    if (Bmemcmp(tmpbuf, "EDuke32demo", 11))
1669
    {
1670
        OSD_Printf("Missing demo header.\n");
1671
        return 1;
1672
    }
1673
 
1674
    if (kread(fil, tmpbuf, 9) != 9) goto corrupt;
1675
    if (tmpbuf[0] != SV_MAJOR_VER || tmpbuf[1] != SV_MINOR_VER || *(uint16_t *)&tmpbuf[3] != BYTEVERSION)
1676
    {
1677
        OSD_Printf("Incompatible demo version. Expected %d.%d.%d, found %d.%d.%d\n",
1678
                   SV_MAJOR_VER, SV_MINOR_VER, BYTEVERSION,
1679
                   (int)tmpbuf[0], (int)tmpbuf[1], (int)(*(uint16_t *)&tmpbuf[3]));
1680
        return 2;
1681
    }
1682
    if (tmpbuf[2] != sizeof(intptr_t))
1683
    {
1684
        OSD_Printf("Demo incompatible. Expected pointer size %d, found %d.\n",
1685
                   (int32_t)sizeof(intptr_t), (int32_t)tmpbuf[2]);
1686
        return 3;
1687
    }
1688
 
1689
    savegame_comprthres = tmpbuf[5];
1690
    *ret_hasdiffs = (int32_t)tmpbuf[6];
1691
    savegame_diffcompress = tmpbuf[7];
1692
    *ret_synccompress = (int32_t)tmpbuf[8];
1693
 
1694
    if (kread(fil, ret_demoticcnt, sizeof(ret_demoticcnt)) != sizeof(ret_demoticcnt)) goto corrupt;
1695
    if (kread(fil, &svsnapsiz, sizeof(svsnapsiz)) != sizeof(svsnapsiz)) goto corrupt;
1696
 
1697
 
1698
    OSD_Printf("sv_loadsnapshot: size: %d bytes.\n", svsnapsiz);
1699
 
1700
    if (doallocsnap(1))
1701
    {
1702
        OSD_Printf("sv_loadsnapshot: failed allocating memory.\n");
1703
        return 4;
1704
    }
1705
 
1706
    p = svsnapshot;
1707
    i = doloadplayer2(-1, fil, &p);
1708
    if (i)
1709
    {
1710
        OSD_Printf("sv_loadsnapshot: doloadplayer2() returned %d.\n", i);
1711
        sv_freemem();
1712
        return 5;
1713
    }
1714
 
1715
    Bmemcpy(svinitsnap, svsnapshot, svsnapsiz);
1716
 
1717
    postloadplayer1();
1718
    postloadplayer2();
1719
 
1720
    if (p != svsnapshot+svsnapsiz)
1721
    {
1722
        OSD_Printf("sv_loadsnapshot: internal error: p-(snapshot end)=%d!\n",
1723
                   p-(svsnapshot+svsnapsiz));
1724
        sv_freemem();
1725
        return 6;
1726
    }
1727
 
1728
    return 0;
1729
corrupt:
1730
    OSD_Printf("Demo header corrupt.\n");
1731
    return 8;
1732
}
1733
 
1734
uint32_t sv_writediff(FILE *fil)
1735
{
1736
    uint8_t *p=svsnapshot, *d=svdiff;
1737
    uint32_t diffsiz;
1738
 
1739
    cmpspecdata(svgm_udnetw, &p, &d);
1740
    cmpspecdata(svgm_secwsp, &p, &d);
1741
    cmpspecdata(svgm_script, &p, &d);
1742
    cmpspecdata(svgm_anmisc, &p, &d);
1743
    cmpspecdata(svgm_vars, &p, &d);
1744
 
1745
    if (p != svsnapshot+svsnapsiz)
1746
        OSD_Printf("sv_writediff: dump+siz=%p, p=%p!\n", svsnapshot+svsnapsiz, p);
1747
 
1748
    diffsiz = d-svdiff;
1749
 
1750
    fwrite("dIfF",4,1,fil);
1751
    fwrite(&diffsiz, sizeof(diffsiz), 1, fil);
1752
    if (savegame_diffcompress)
1753
        dfwrite(svdiff, 1, diffsiz, fil);  // cnt and sz swapped
1754
    else
1755
        fwrite(svdiff, 1, diffsiz, fil);
1756
 
1757
    return diffsiz;
1758
}
1759
 
1760
int32_t sv_readdiff(int32_t fil)
1761
{
1762
    uint8_t *p=svsnapshot, *d=svdiff, i=0; //, tbuf[4];
1599 terminx 1763
    int32_t diffsiz;
1595 helixhorne 1764
 
1765
#if 0  // handled by the caller
1599 terminx 1766
    if (kread(fil, tbuf, 4)!=4)
1767
        return -1;
1768
    if (Bmemcmp(tbuf, "dIfF", 4))
1769
        return 4;
1595 helixhorne 1770
#endif
1599 terminx 1771
    if (kread(fil, &diffsiz, sizeof(uint32_t))!=sizeof(uint32_t))
1772
        return -1;
1595 helixhorne 1773
    if (savegame_diffcompress)
1774
    {
1775
        if (kdfread(svdiff, 1, diffsiz, fil) != diffsiz)  // cnt and sz swapped
1776
            return -2;
1777
    }
1778
    else
1779
    {
1780
        if (kread(fil, svdiff, diffsiz) != diffsiz)
1781
            return -2;
1782
    }
1783
 
1599 terminx 1784
    if (applydiff(svgm_udnetw, &p, &d)) return -3;
1785
    if (applydiff(svgm_secwsp, &p, &d)) return -4;
1786
    if (applydiff(svgm_script, &p, &d)) return -5;
1787
    if (applydiff(svgm_anmisc, &p, &d)) return -6;
1788
    if (applydiff(svgm_vars, &p, &d)) return -7;
1595 helixhorne 1789
 
1599 terminx 1790
    if (p!=svsnapshot+svsnapsiz)
1791
        i|=1;
1792
    if (d!=svdiff+diffsiz)
1793
        i|=2;
1794
    if (i)
1795
        OSD_Printf("sv_readdiff: p=%p, svsnapshot+svsnapsiz=%p; d=%p, svdiff+diffsiz=%p",
1796
                   p, svsnapshot+svsnapsiz, d, svdiff+diffsiz);
1797
    return i;
1595 helixhorne 1798
}
1799
 
1800
// SVGM data description
1801
static void sv_postudload()
1802
{
1803
    Bmemcpy(&boardfilename[0], &currentboardfilename[0], BMAX_PATH);
1598 helixhorne 1804
#if 0
1595 helixhorne 1805
    ud.m_level_number = ud.level_number;
1806
    ud.m_volume_number = ud.volume_number;
1807
    ud.m_player_skill = ud.player_skill;
1808
    ud.m_respawn_monsters = ud.respawn_monsters;
1809
    ud.m_respawn_items = ud.respawn_items;
1810
    ud.m_respawn_inventory = ud.respawn_inventory;
1811
    ud.m_monsters_off = ud.monsters_off;
1812
    ud.m_coop = ud.coop;
1813
    ud.m_marker = ud.marker;
1814
    ud.m_ffire = ud.ffire;
1815
    ud.m_noexits = ud.noexits;
1598 helixhorne 1816
#endif
1595 helixhorne 1817
}
1818
//static int32_t lockclock_dummy;
1819
 
1820
#if defined(POLYMOST) && defined(USE_OPENGL)
1821
static void sv_prespriteextsave()
1822
{
1823
    int32_t i;
1824
    for (i=0; i<MAXSPRITES; i++)
1825
        if (spriteext[i].mdanimtims)
1826
        {
1827
            spriteext[i].mdanimtims -= mdtims;
1828
            if (spriteext[i].mdanimtims==0)
1829
                spriteext[i].mdanimtims++;
1830
        }
1831
}
1832
static void sv_postspriteext()
1833
{
1834
    int32_t i;
1835
    for (i=0; i<MAXSPRITES; i++)
1836
        if (spriteext[i].mdanimtims)
1837
            spriteext[i].mdanimtims += mdtims;
1838
}
1839
#endif
1840
 
1841
static void sv_calcbitptrsize()
1842
{
1843
    savegame_bitptrsize = (g_scriptSize+7)>>3;
1844
}
1845
static void sv_prescriptsave_once()
1846
{
1847
    int32_t i;
1848
    for (i=0; i<g_scriptSize; i++)
1849
        if (bitptr[i>>3]&(BITPTR_POINTER<<(i&7)))
1850
            script[i] = (intptr_t)((intptr_t *)script[i] - &script[0]);
1851
    for (i=0; i<MAXTILES; i++)
1852
        if (actorscrptr[i])
1853
            actorscrptr[i] = (intptr_t *)(actorscrptr[i]-&script[0]);
1854
    for (i=0; i<MAXTILES; i++)
1855
        if (actorLoadEventScrptr[i])
1856
            actorLoadEventScrptr[i] = (intptr_t *)(actorLoadEventScrptr[i]-&script[0]);
1857
}
1598 helixhorne 1858
static void sv_prescriptload_once()
1859
{
1860
    if (script)
1861
        Bfree(script);
1862
    script = Bmalloc(g_scriptSize * sizeof(script[0]));
1863
}
1595 helixhorne 1864
static void sv_postscript_once()
1865
{
1866
    int32_t i;
1867
    for (i=0; i<MAXTILES; i++)
1868
        if (actorLoadEventScrptr[i])
1869
            actorLoadEventScrptr[i] = (intptr_t)actorLoadEventScrptr[i] + &script[0];
1870
    for (i=0; i<MAXTILES; i++)
1871
        if (actorscrptr[i])
1872
            actorscrptr[i] = (intptr_t)actorscrptr[i] + &script[0];
1873
    for (i=0; i<g_scriptSize; i++)
1874
        if (bitptr[i>>3]&(BITPTR_POINTER<<(i&7)))
1875
            script[i] = (intptr_t)(script[i] + &script[0]);
1876
}
1877
static void sv_preactordatasave()
1878
{
1879
    int32_t i;
1880
    intptr_t j=(intptr_t)&script[0], k=(intptr_t)&script[g_scriptSize];
1881
 
1882
    Bmemset(savegame_bitmap, 0, sizeof(savegame_bitmap));
1883
    for (i=0; i<MAXSPRITES; i++)
1884
    {
1625 terminx 1885
//        Actor[i].lightptr = NULL;
1886
//        Actor[i].lightId = -1;
1595 helixhorne 1887
 
1888
        if (sprite[i].statnum==MAXSTATUS || actorscrptr[PN]==NULL) continue;
1889
        if (T2 >= j && T2 < k) savegame_bitmap[i>>3][0] |= 1<<(i&7), T2 -= j;
1890
        if (T5 >= j && T5 < k) savegame_bitmap[i>>3][1] |= 1<<(i&7), T5 -= j;
1891
        if (T6 >= j && T6 < k) savegame_bitmap[i>>3][2] |= 1<<(i&7), T6 -= j;
1892
    }
1893
}
1894
static void sv_postactordata()
1895
{
1896
    int32_t i;
1897
    intptr_t j=(intptr_t)&script[0];
1898
 
1899
#if POLYMER
1599 terminx 1900
    if (getrendermode() == 4)
1901
        polymer_resetlights();
1595 helixhorne 1902
#endif
1903
 
1904
    for (i=0; i<MAXSPRITES; i++)
1905
    {
1625 terminx 1906
//        Actor[i].lightptr = NULL;
1907
//        Actor[i].lightId = -1;
1908
        actor[i].projectile = &SpriteProjectile[i];
1595 helixhorne 1909
 
1910
        if (sprite[i].statnum==MAXSTATUS || actorscrptr[PN]==NULL) continue;
1911
        if (savegame_bitmap[i>>3][0]&(1<<(i&7))) T2 += j;
1912
        if (savegame_bitmap[i>>3][1]&(1<<(i&7))) T5 += j;
1913
        if (savegame_bitmap[i>>3][2]&(1<<(i&7))) T6 += j;
1914
    }
1915
}
1916
 
1917
static void sv_preanimateptrsave()
1918
{
1919
    int32_t i;
1920
    for (i=g_animateCount-1; i>=0; i--)
1921
        animateptr[i] = (int32_t *)((intptr_t)animateptr[i]-(intptr_t)&sector[0]);
1922
}
1923
static void sv_postanimateptr()
1924
{
1925
    int32_t i;
1926
    for (i=g_animateCount-1; i>=0; i--)
1927
        animateptr[i] = (int32_t *)((intptr_t)animateptr[i]+(intptr_t)&sector[0]);
1928
}
1929
static void sv_prequote()
1930
{
1931
    if (!savegame_quotes)
1932
        savegame_quotes = Bcalloc(MAXQUOTES, MAXQUOTELEN);
1933
}
1934
static void sv_quotesave()
1935
{
1936
    int32_t i;
1937
    Bmemset(savegame_quotedef, 0, sizeof(savegame_quotedef));
1938
    for (i=0; i<MAXQUOTES; i++)
1939
        if (ScriptQuotes[i])
1940
        {
1941
            savegame_quotedef[i>>3] |= 1<<(i&7);
1942
            Bmemcpy(savegame_quotes[i], ScriptQuotes[i], MAXQUOTELEN);
1943
        }
1944
}
1945
static void sv_quoteload()
1946
{
1947
    int32_t i;
1948
    for (i=0; i<MAXQUOTES; i++)
1949
    {
1950
        if (savegame_quotedef[i>>3]&(1<<(i&7)))
1951
        {
1952
            if (!ScriptQuotes[i])
1953
                ScriptQuotes[i] = Bcalloc(1,MAXQUOTELEN);
1954
            Bmemcpy(ScriptQuotes[i], savegame_quotes[i], MAXQUOTELEN);
1955
        }
1956
    }
1957
}
1958
static void sv_prequoteredef()
1959
{
1960
    // "+1" needed for dfwrite which doesn't handle the src==NULL && cnt==0 case
1961
    savegame_quoteredefs = Bcalloc(g_numQuoteRedefinitions+1, MAXQUOTELEN);
1962
}
1963
static void sv_quoteredefsave()
1964
{
1965
    int32_t i;
1966
    for (i=0; i<g_numQuoteRedefinitions; i++)
1967
        if (ScriptQuoteRedefinitions[i])
1968
            Bmemcpy(savegame_quoteredefs[i], ScriptQuoteRedefinitions[i], MAXQUOTELEN);
1969
}
1970
static void sv_quoteredefload()
1971
{
1972
    int32_t i;
1973
    for (i=0; i<g_numQuoteRedefinitions; i++)
1974
    {
1975
        if (!ScriptQuoteRedefinitions[i])
1976
            ScriptQuoteRedefinitions[i] = Bcalloc(1,MAXQUOTELEN);
1977
        Bmemcpy(ScriptQuoteRedefinitions[i], savegame_quoteredefs[i], MAXQUOTELEN);
1978
    }
1979
}
1980
static void sv_postquoteredef()
1981
{
1982
    Bfree(savegame_quoteredefs), savegame_quoteredefs=NULL;
1983
}
1984
static void sv_restsave()
1985
{
1986
    int32_t i;
1987
    uint8_t *mem = savegame_restdata;
1988
    DukePlayer_t dummy_ps;
1989
 
1990
    Bmemset(&dummy_ps, 0, sizeof(DukePlayer_t));
1991
 
1599 terminx 1992
#define CPDAT(ptr,sz) Bmemcpy(mem, ptr, sz), mem+=sz
1595 helixhorne 1993
    for (i=0; i<MAXPLAYERS; i++)
1994
    {
1995
        CPDAT(g_player[i].user_name, 32);
1996
        CPDAT(&g_player[i].pcolor, sizeof(g_player[0].pcolor));
1997
        CPDAT(&g_player[i].pteam, sizeof(g_player[0].pteam));
1998
        CPDAT(&g_player[i].frags[0], sizeof(g_player[0].frags));
1999
        if (g_player[i].ps)
2000
            CPDAT(g_player[i].ps, sizeof(DukePlayer_t));
2001
        else
2002
            CPDAT(&dummy_ps, sizeof(DukePlayer_t));
2003
    }
2004
#if 0  // POLYMER  this will have to wait...
2005
    CPDAT(&lightcount, sizeof(lightcount));
2006
    for (i=0; i<lightcount; i++)
2007
    {
2008
        CPDAT(&prlights[i], sizeof(_prlight));
2009
        ((prlight_ *)(mem-sizeof(_prlight)))->planelist = NULL;
2010
    }
2011
#endif
2012
    Bmemset(mem, 0, (savegame_restdata+SVARDATALEN)-mem);
1599 terminx 2013
#undef CPDAT
1595 helixhorne 2014
}
2015
static void sv_restload()
2016
{
2017
    int32_t i;
2018
    uint8_t *mem = savegame_restdata;
2019
    DukePlayer_t dummy_ps;
2020
 
1599 terminx 2021
#define CPDAT(ptr,sz) Bmemcpy(ptr, mem, sz), mem+=sz
1595 helixhorne 2022
    for (i=0; i<MAXPLAYERS; i++)
2023
    {
2024
        CPDAT(g_player[i].user_name, 32);
2025
        CPDAT(&g_player[i].pcolor, sizeof(g_player[0].pcolor));
2026
        CPDAT(&g_player[i].pteam, sizeof(g_player[0].pteam));
2027
        CPDAT(&g_player[i].frags[0], sizeof(g_player[0].frags));
2028
        if (g_player[i].ps)
2029
            CPDAT(g_player[i].ps, sizeof(DukePlayer_t));
2030
        else
2031
            CPDAT(&dummy_ps, sizeof(DukePlayer_t));
2032
    }
2033
#if 0  // POLYMER
2034
    CPDAT(&lightcount, sizeof(lightcount));
2035
    for (i=0; i<lightcount; i++)
2036
        CPDAT(&prlights[i], sizeof(_prlight));
2037
#endif
1599 terminx 2038
#undef CPDAT
1595 helixhorne 2039
}
2040
 
2041
#define SAVEWR(ptr, sz, cnt) do { if (fil) dfwrite(ptr,sz,cnt,fil); } while (0)
2042
#define SAVEWRU(ptr, sz, cnt) do { if (fil) fwrite(ptr,sz,cnt,fil); } while (0)
2043
 
2044
#define PRINTSIZE(name) OSD_Printf(#name ": %d\n", mem-tmem), tmem=mem
2045
 
2046
static uint8_t *dosaveplayer2(int32_t spot, FILE *fil, uint8_t *mem)
2047
{
2048
    uint8_t *tmem = mem;
2049
    mem=writespecdata(svgm_udnetw, fil, mem);  // user settings, players & net
2050
    PRINTSIZE(ud);
2051
 
2052
    if (spot>=0)
2053
    {
1707 terminx 2054
        SAVEWRU(&ud.savegame[spot][0], 21, 1);
1595 helixhorne 2055
        SAVEWRU("1", 1, 1);
2056
        if (!waloff[TILE_SAVESHOT])
2057
        {
2058
            walock[TILE_SAVESHOT] = 254;
2059
            allocache(&waloff[TILE_SAVESHOT],200*320,&walock[TILE_SAVESHOT]);
1677 terminx 2060
            clearbuf((void *)waloff[TILE_SAVESHOT],(200*320)/4,0);
1595 helixhorne 2061
            walock[TILE_SAVESHOT] = 1;
2062
        }
2063
        SAVEWR((char *)waloff[TILE_SAVESHOT], 320, 200);
2064
    }
2065
    else
2066
    {
1707 terminx 2067
        char buf[21];
1595 helixhorne 2068
        const time_t t=time(NULL);
1596 plagman 2069
        struct tm *st;
1595 helixhorne 2070
        Bsprintf(buf, "Eduke32 demo");
1596 plagman 2071
        if (t>=0 && (st = localtime(&t)))
2072
            Bsprintf(buf, "Edemo32 %04d%02d%02d", st->tm_year+1900, st->tm_mon+1, st->tm_mday);
1707 terminx 2073
        SAVEWRU(&buf, 21, 1);
1595 helixhorne 2074
        SAVEWRU("\0", 1, 1);  // demos don't save screenshot
2075
    }
2076
 
2077
    mem=writespecdata(svgm_secwsp, fil, mem);  // sector, wall, sprite
2078
    PRINTSIZE(sws);
2079
    mem=writespecdata(svgm_script, fil, mem);  // script
2080
    PRINTSIZE(script);
2081
    mem=writespecdata(svgm_anmisc, fil, mem);  // animates, quotes & misc.
2082
    PRINTSIZE(animisc);
2083
 
2084
    Gv_WriteSave(fil, 1);  // gamevars
2085
    mem=writespecdata(svgm_vars, 0, mem);
2086
    PRINTSIZE(vars);
2087
 
2088
    return mem;
2089
}
2090
 
2091
#define LOADRD(ptr, sz, cnt) (kdfread(ptr,sz,cnt,fil)!=(cnt))
2092
#define LOADRDU(ptr, sz, cnt) (kread(fil,ptr,(sz)*(cnt))!=(sz)*(cnt))
2093
 
2094
static int32_t doloadplayer2(int32_t spot, int32_t fil, uint8_t **memptr)
2095
{
2096
    uint8_t *mem = memptr ? *memptr : NULL, *tmem=mem;
1707 terminx 2097
    char tbuf[21];
1595 helixhorne 2098
    int32_t i;
2099
 
2100
    if (readspecdata(svgm_udnetw, fil, &mem))
2101
        return -2;
2102
    PRINTSIZE(ud);
2103
    if (spot >= 0 && ud.multimode!=numplayers)
2104
        return 2;
2105
 
1598 helixhorne 2106
    if (spot<0 || numplayers > 1)
1595 helixhorne 2107
    {
1707 terminx 2108
        if (LOADRDU(&tbuf, 21, 1)) return -3;
1595 helixhorne 2109
    }
1707 terminx 2110
    else if (LOADRDU(&ud.savegame[spot][0], 21