Subversion Repositories eduke32

Rev

Rev 4815 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 4815 Rev 4831
1
//-------------------------------------------------------------------------
1
//-------------------------------------------------------------------------
2
/*
2
/*
3
Copyright (C) 2010 EDuke32 developers and contributors
3
Copyright (C) 2010 EDuke32 developers and contributors
4

4

5
This file is part of EDuke32.
5
This file is part of EDuke32.
6

6

7
EDuke32 is free software; you can redistribute it and/or
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
8
modify it under the terms of the GNU General Public License version 2
9
as published by the Free Software Foundation.
9
as published by the Free Software Foundation.
10

10

11
This program is distributed in the hope that it will be useful,
11
This program is distributed in the hope that it will be useful,
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
but WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14

14

15
See the GNU General Public License for more details.
15
See the GNU General Public License for more details.
16

16

17
You should have received a copy of the GNU General Public License
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
18
along with this program; if not, write to the Free Software
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
19
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
20
*/
20
*/
21
//-------------------------------------------------------------------------
21
//-------------------------------------------------------------------------
22
22
23
#include "duke3d.h"
23
#include "duke3d.h"
24
#include "demo.h"
24
#include "demo.h"
25
//#include "premap.h"  // G_UpdateScreenArea()
25
//#include "premap.h"  // G_UpdateScreenArea()
26
#include "menus.h"
26
#include "menus.h"
27
#include "savegame.h"
27
#include "savegame.h"
28
#include "input.h"
28
#include "input.h"
29
29
30
char g_firstDemoFile[BMAX_PATH];
30
char g_firstDemoFile[BMAX_PATH];
31
31
32
FILE *g_demo_filePtr = (FILE *)NULL;  // write
32
FILE *g_demo_filePtr = (FILE *)NULL;  // write
33
int32_t g_demo_recFilePtr = -1;  // read
33
int32_t g_demo_recFilePtr = -1;  // read
34
34
35
int32_t g_demo_cnt;
35
int32_t g_demo_cnt;
36
int32_t g_demo_goalCnt=0;
36
int32_t g_demo_goalCnt=0;
37
int32_t g_demo_totalCnt;
37
int32_t g_demo_totalCnt;
38
int32_t g_demo_paused=0;
38
int32_t g_demo_paused=0;
39
int32_t g_demo_rewind=0;
39
int32_t g_demo_rewind=0;
40
int32_t g_demo_showStats=1;
40
int32_t g_demo_showStats=1;
41
static int32_t g_demo_soundToggle;
41
static int32_t g_demo_soundToggle;
42
42
43
static int32_t demo_hasdiffs, demorec_diffs=1, demorec_difftics = 2*REALGAMETICSPERSEC;
43
static int32_t demo_hasdiffs, demorec_diffs=1, demorec_difftics = 2*REALGAMETICSPERSEC;
44
int32_t demoplay_diffs=1;
44
int32_t demoplay_diffs=1;
45
int32_t demorec_diffs_cvar=1;
45
int32_t demorec_diffs_cvar=1;
46
int32_t demorec_force_cvar=0;
46
int32_t demorec_force_cvar=0;
47
int32_t demorec_difftics_cvar = 2*REALGAMETICSPERSEC;
47
int32_t demorec_difftics_cvar = 2*REALGAMETICSPERSEC;
48
int32_t demorec_diffcompress_cvar=1;
48
int32_t demorec_diffcompress_cvar=1;
49
int32_t demorec_synccompress_cvar=1;
49
int32_t demorec_synccompress_cvar=1;
50
int32_t demorec_seeds_cvar=1;
50
int32_t demorec_seeds_cvar=1;
51
int32_t demoplay_showsync=1;
51
int32_t demoplay_showsync=1;
52
52
53
static int32_t demo_synccompress=1, demorec_seeds=1, demo_hasseeds;
53
static int32_t demo_synccompress=1, demorec_seeds=1, demo_hasseeds;
54
54
55
static void Demo_RestoreModes(int32_t menu)
55
static void Demo_RestoreModes(int32_t menu)
56
{
56
{
57
    if (menu)
57
    if (menu)
58
        M_OpenMenu(myconnectindex);
58
        M_OpenMenu(myconnectindex);
59
    else
59
    else
60
        M_CloseMenu(myconnectindex);
60
        M_CloseMenu(myconnectindex);
61
61
62
    g_player[myconnectindex].ps->gm &= ~MODE_GAME;
62
    g_player[myconnectindex].ps->gm &= ~MODE_GAME;
63
    g_player[myconnectindex].ps->gm |= MODE_DEMO;
63
    g_player[myconnectindex].ps->gm |= MODE_DEMO;
64
}
64
}
65
65
66
void Demo_PrepareWarp(void)
66
void Demo_PrepareWarp(void)
67
{
67
{
68
    if (!g_demo_paused)
68
    if (!g_demo_paused)
69
    {
69
    {
70
        g_demo_soundToggle = ud.config.SoundToggle;
70
        g_demo_soundToggle = ud.config.SoundToggle;
71
        ud.config.SoundToggle = 0;
71
        ud.config.SoundToggle = 0;
72
    }
72
    }
73
73
74
    FX_StopAllSounds();
74
    FX_StopAllSounds();
75
    S_ClearSoundLocks();
75
    S_ClearSoundLocks();
76
}
76
}
77
77
78
78
79
static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
79
static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
80
{
80
{
81
    int32_t i;
81
    int32_t i;
82
    savehead_t saveh;
82
    savehead_t saveh;
83
83
84
    char demofn[14];
84
    char demofn[14];
85
    const char *demofnptr;
85
    const char *demofnptr;
86
86
87
    if (g_whichDemo == 1 && g_firstDemoFile[0])
87
    if (g_whichDemo == 1 && g_firstDemoFile[0])
88
    {
88
    {
89
        demofnptr = g_firstDemoFile;
89
        demofnptr = g_firstDemoFile;
90
    }
90
    }
91
    else
91
    else
92
    {
92
    {
93
        Bsprintf(demofn, DEMOFN_FMT, g_whichDemo);
93
        Bsprintf(demofn, DEMOFN_FMT, g_whichDemo);
94
        demofnptr = demofn;
94
        demofnptr = demofn;
95
    }
95
    }
96
96
97
    g_demo_recFilePtr = kopen4loadfrommod(demofnptr, g_loadFromGroupOnly);
97
    g_demo_recFilePtr = kopen4loadfrommod(demofnptr, g_loadFromGroupOnly);
98
    if (g_demo_recFilePtr == -1)
98
    if (g_demo_recFilePtr == -1)
99
        return 0;
99
        return 0;
100
100
101
    Bassert(g_whichDemo >= 1);
101
    Bassert(g_whichDemo >= 1);
102
    i = sv_loadsnapshot(g_demo_recFilePtr, -g_whichDemo, &saveh);
102
    i = sv_loadsnapshot(g_demo_recFilePtr, -g_whichDemo, &saveh);
103
    if (i)
103
    if (i)
104
    {
104
    {
105
        OSD_Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i);
105
        OSD_Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i);
106
        kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
106
        kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
107
        return 0;
107
        return 0;
108
    }
108
    }
109
109
110
    demo_hasdiffs = saveh.recdiffsp;
110
    demo_hasdiffs = saveh.recdiffsp;
111
    g_demo_totalCnt = saveh.reccnt;
111
    g_demo_totalCnt = saveh.reccnt;
112
    demo_synccompress = saveh.synccompress;
112
    demo_synccompress = saveh.synccompress;
113
113
114
    demo_hasseeds = demo_synccompress&2;
114
    demo_hasseeds = demo_synccompress&2;
115
    demo_synccompress &= 1;
115
    demo_synccompress &= 1;
116
116
117
    i = g_demo_totalCnt/REALGAMETICSPERSEC;
117
    i = g_demo_totalCnt/REALGAMETICSPERSEC;
118
    OSD_Printf("demo %d duration: %d min %d sec\n", g_whichDemo, i/60, i%60);
118
    OSD_Printf("demo %d duration: %d min %d sec\n", g_whichDemo, i/60, i%60);
119
119
120
    g_demo_cnt = 1;
120
    g_demo_cnt = 1;
121
    ud.reccnt = 0;
121
    ud.reccnt = 0;
122
122
123
    ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
123
    ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
124
    ud.noclip = ud.scrollmode = ud.overhead_on = 0; //= ud.pause_on = 0;
124
    ud.noclip = ud.scrollmode = ud.overhead_on = 0; //= ud.pause_on = 0;
125
125
126
    totalclock = ototalclock = lockclock = 0;
126
    totalclock = ototalclock = lockclock = 0;
127
127
128
    return 1;
128
    return 1;
129
}
129
}
130
130
131
#if KRANDDEBUG
131
#if KRANDDEBUG
132
extern void krd_enable(int32_t which);
132
extern void krd_enable(int32_t which);
133
extern int32_t krd_print(const char *filename);
133
extern int32_t krd_print(const char *filename);
134
#endif
134
#endif
135
135
136
void G_OpenDemoWrite(void)
136
void G_OpenDemoWrite(void)
137
{
137
{
138
#ifdef LUNATIC
138
#ifdef LUNATIC
139
    // TODO: Currently, we can't diff gamevars in Lunatic...
139
    // TODO: Currently, we can't diff gamevars in Lunatic...
140
    Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "DEMOS UNSUPPORTED IN LUNATIC BUILD");
140
    Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "DEMOS UNSUPPORTED IN LUNATIC BUILD");
141
    P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
141
    P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
142
    ud.recstat = ud.m_recstat = 0;
142
    ud.recstat = ud.m_recstat = 0;
143
    return;
143
    return;
144
#else
144
#else
145
    char demofn[BMAX_PATH];
145
    char demofn[BMAX_PATH];
146
    int32_t i, demonum=1;
146
    int32_t i, demonum=1;
147
147
148
    if (ud.recstat == 2)
148
    if (ud.recstat == 2)
149
    {
149
    {
150
        kclose(g_demo_recFilePtr);
150
        kclose(g_demo_recFilePtr);
151
        g_demo_recFilePtr = -1;
151
        g_demo_recFilePtr = -1;
152
    }
152
    }
153
153
154
    if ((g_player[myconnectindex].ps->gm&MODE_GAME) && g_player[myconnectindex].ps->dead_flag)
154
    if ((g_player[myconnectindex].ps->gm&MODE_GAME) && g_player[myconnectindex].ps->dead_flag)
155
    {
155
    {
156
        Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "CANNOT START DEMO RECORDING WHEN DEAD!");
156
        Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "CANNOT START DEMO RECORDING WHEN DEAD!");
157
        P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
157
        P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
158
        ud.recstat = ud.m_recstat = 0;
158
        ud.recstat = ud.m_recstat = 0;
159
        return;
159
        return;
160
    }
160
    }
161
# if !defined LUNATIC
161
# if !defined LUNATIC
162
    if (demorec_diffs_cvar && !demorec_force_cvar)
162
    if (demorec_diffs_cvar && !demorec_force_cvar)
163
        for (i=1; i<g_scriptSize-2; i++)
163
        for (i=1; i<g_scriptSize-2; i++)
164
        {
164
        {
165
            intptr_t w=script[i];
165
            intptr_t w=script[i];
166
            if ((w&0x0fff)==CON_RESIZEARRAY && (w>>12) && script[i+1]>=0 && script[i+1]<g_gameArrayCount)
166
            if ((w&0x0fff)==CON_RESIZEARRAY && (w>>12) && script[i+1]>=0 && script[i+1]<g_gameArrayCount)
167
            {
167
            {
168
                OSD_Printf("\nThe CON code possibly contains a RESIZEARRAY command.\n");
168
                OSD_Printf("\nThe CON code possibly contains a RESIZEARRAY command.\n");
169
                OSD_Printf("Gamearrays that change their size during the game are unsupported by\n");
169
                OSD_Printf("Gamearrays that change their size during the game are unsupported by\n");
170
                OSD_Printf("the demo recording system. If you are sure that the code doesn't\n");
170
                OSD_Printf("the demo recording system. If you are sure that the code doesn't\n");
171
                OSD_Printf("contain a RESIZEARRAY command, you can force recording with the\n");
171
                OSD_Printf("contain a RESIZEARRAY command, you can force recording with the\n");
172
                OSD_Printf("`demorec_force' cvar. Alternatively, you can disable diff recording\n");
172
                OSD_Printf("`demorec_force' cvar. Alternatively, you can disable diff recording\n");
173
                OSD_Printf("with the `demorec_diffs' cvar.\n\n");
173
                OSD_Printf("with the `demorec_diffs' cvar.\n\n");
174
                Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE OSD.");
174
                Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE OSD.");
175
                P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
175
                P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
176
                ud.recstat = ud.m_recstat = 0;
176
                ud.recstat = ud.m_recstat = 0;
177
                return;
177
                return;
178
            }
178
            }
179
        }
179
        }
180
# endif
180
# endif
181
    do
181
    do
182
    {
182
    {
183
        if (demonum == MAXDEMOS)
183
        if (demonum == MAXDEMOS)
184
            return;
184
            return;
185
185
186
        if (G_ModDirSnprintf(demofn, sizeof(demofn), DEMOFN_FMT, demonum))
186
        if (G_ModDirSnprintf(demofn, sizeof(demofn), DEMOFN_FMT, demonum))
187
        {
187
        {
188
            initprintf("Couldn't start demo writing: INTERNAL ERROR: file name too long\n");
188
            initprintf("Couldn't start demo writing: INTERNAL ERROR: file name too long\n");
189
            goto error_wopen_demo;
189
            goto error_wopen_demo;
190
        }
190
        }
191
191
192
        demonum++;
192
        demonum++;
193
193
194
        g_demo_filePtr = Bfopen(demofn, "rb");
194
        g_demo_filePtr = Bfopen(demofn, "rb");
195
        if (g_demo_filePtr == NULL)
195
        if (g_demo_filePtr == NULL)
196
            break;
196
            break;
197
197
198
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
198
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
199
    }
199
    }
200
    while (1);
200
    while (1);
201
201
202
    g_demo_filePtr = Bfopen(demofn,"wb");
202
    g_demo_filePtr = Bfopen(demofn,"wb");
203
    if (g_demo_filePtr == NULL)
203
    if (g_demo_filePtr == NULL)
204
        return;
204
        return;
205
205
206
    i=sv_saveandmakesnapshot(g_demo_filePtr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar,
206
    i=sv_saveandmakesnapshot(g_demo_filePtr, -1, demorec_diffs_cvar, demorec_diffcompress_cvar,
207
                             demorec_synccompress_cvar|(demorec_seeds_cvar<<1));
207
                             demorec_synccompress_cvar|(demorec_seeds_cvar<<1));
208
    if (i)
208
    if (i)
209
    {
209
    {
210
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
210
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
211
error_wopen_demo:
211
error_wopen_demo:
212
        Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE OSD FOR DETAILS.");
212
        Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "FAILED STARTING DEMO RECORDING. SEE OSD FOR DETAILS.");
213
        P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
213
        P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
214
        ud.recstat = ud.m_recstat = 0;
214
        ud.recstat = ud.m_recstat = 0;
215
        return;
215
        return;
216
    }
216
    }
217
217
218
    demorec_seeds = demorec_seeds_cvar;
218
    demorec_seeds = demorec_seeds_cvar;
219
    demorec_diffs = demorec_diffs_cvar;
219
    demorec_diffs = demorec_diffs_cvar;
220
    demo_synccompress = demorec_synccompress_cvar;
220
    demo_synccompress = demorec_synccompress_cvar;
221
    demorec_difftics = demorec_difftics_cvar;
221
    demorec_difftics = demorec_difftics_cvar;
222
222
223
    Bsprintf(ScriptQuotes[QUOTE_RESERVED4], "DEMO %d RECORDING STARTED", demonum-1);
223
    Bsprintf(ScriptQuotes[QUOTE_RESERVED4], "DEMO %d RECORDING STARTED", demonum-1);
224
    P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
224
    P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
225
225
226
    ud.reccnt = 0;
226
    ud.reccnt = 0;
227
    ud.recstat = ud.m_recstat = 1;  //
227
    ud.recstat = ud.m_recstat = 1;  //
228
228
229
# if KRANDDEBUG
229
# if KRANDDEBUG
230
    krd_enable(1);
230
    krd_enable(1);
231
# endif
231
# endif
232
    g_demo_cnt = 1;
232
    g_demo_cnt = 1;
233
#endif
233
#endif
234
}
234
}
235
235
236
// demo_profile: < 0: prepare
236
// demo_profile: < 0: prepare
237
static int32_t g_demo_playFirstFlag, g_demo_profile, g_demo_stopProfile;
237
static int32_t g_demo_playFirstFlag, g_demo_profile, g_demo_stopProfile;
238
static int32_t g_demo_exitAfter;
238
static int32_t g_demo_exitAfter;
239
void Demo_PlayFirst(int32_t prof, int32_t exitafter)
239
void Demo_PlayFirst(int32_t prof, int32_t exitafter)
240
{
240
{
241
    g_demo_playFirstFlag = 1;
241
    g_demo_playFirstFlag = 1;
242
    g_demo_exitAfter = exitafter;
242
    g_demo_exitAfter = exitafter;
243
    Bassert(prof >= 0);
243
    Bassert(prof >= 0);
244
    g_demo_profile = -prof;  // prepare
244
    g_demo_profile = -prof;  // prepare
245
}
245
}
246
246
247
void Demo_SetFirst(const char *demostr)
247
void Demo_SetFirst(const char *demostr)
248
{
248
{
249
    char *tailptr;
249
    char *tailptr;
250
    int32_t i = Bstrtol(demostr, &tailptr, 10);
250
    int32_t i = Bstrtol(demostr, &tailptr, 10);
251
251
252
    if (tailptr==demostr+Bstrlen(demostr) && (unsigned)i < MAXDEMOS)  // demo number passed
252
    if (tailptr==demostr+Bstrlen(demostr) && (unsigned)i < MAXDEMOS)  // demo number passed
253
        Bsprintf(g_firstDemoFile, DEMOFN_FMT, i);
253
        Bsprintf(g_firstDemoFile, DEMOFN_FMT, i);
254
    else  // demo file name passed
254
    else  // demo file name passed
255
        maybe_append_ext(g_firstDemoFile, sizeof(g_firstDemoFile), demostr, ".edm");
255
        maybe_append_ext(g_firstDemoFile, sizeof(g_firstDemoFile), demostr, ".edm");
256
}
256
}
257
257
258
258
259
static uint8_t g_demo_seedbuf[RECSYNCBUFSIZ];
259
static uint8_t g_demo_seedbuf[RECSYNCBUFSIZ];
260
260
261
static void Demo_WriteSync()
261
static void Demo_WriteSync()
262
{
262
{
263
    int16_t tmpreccnt;
263
    int16_t tmpreccnt;
264
264
265
    fwrite("sYnC", 4, 1, g_demo_filePtr);
265
    fwrite("sYnC", 4, 1, g_demo_filePtr);
266
    tmpreccnt = (int16_t)ud.reccnt;
266
    tmpreccnt = (int16_t)ud.reccnt;
267
    fwrite(&tmpreccnt, sizeof(int16_t), 1, g_demo_filePtr);
267
    fwrite(&tmpreccnt, sizeof(int16_t), 1, g_demo_filePtr);
268
    if (demorec_seeds)
268
    if (demorec_seeds)
269
        fwrite(g_demo_seedbuf, 1, ud.reccnt, g_demo_filePtr);
269
        fwrite(g_demo_seedbuf, 1, ud.reccnt, g_demo_filePtr);
270
270
271
    if (demo_synccompress)
271
    if (demo_synccompress)
272
        dfwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr);
272
        dfwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr);
273
    else //if (demo_synccompress==0)
273
    else //if (demo_synccompress==0)
274
        fwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr);
274
        fwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr);
275
275
276
    ud.reccnt = 0;
276
    ud.reccnt = 0;
277
}
277
}
278
278
279
void G_DemoRecord(void)
279
void G_DemoRecord(void)
280
{
280
{
281
    int16_t i;
281
    int16_t i;
282
282
283
    g_demo_cnt++;
283
    g_demo_cnt++;
284
284
285
    if (demorec_diffs && (g_demo_cnt%demorec_difftics == 1))
285
    if (demorec_diffs && (g_demo_cnt%demorec_difftics == 1))
286
    {
286
    {
287
        sv_writediff(g_demo_filePtr);
287
        sv_writediff(g_demo_filePtr);
288
        demorec_difftics = demorec_difftics_cvar;
288
        demorec_difftics = demorec_difftics_cvar;
289
    }
289
    }
290
290
291
    if (demorec_seeds)
291
    if (demorec_seeds)
292
        g_demo_seedbuf[ud.reccnt] = (uint8_t)(randomseed>>24);
292
        g_demo_seedbuf[ud.reccnt] = (uint8_t)(randomseed>>24);
293
293
294
    for (TRAVERSE_CONNECT(i))
294
    for (TRAVERSE_CONNECT(i))
295
    {
295
    {
296
        Bmemcpy(&recsync[ud.reccnt], g_player[i].sync, sizeof(input_t));
296
        Bmemcpy(&recsync[ud.reccnt], g_player[i].sync, sizeof(input_t));
297
        ud.reccnt++;
297
        ud.reccnt++;
298
    }
298
    }
299
299
300
    if (ud.reccnt > RECSYNCBUFSIZ-MAXPLAYERS || (demorec_diffs && (g_demo_cnt%demorec_difftics == 0)))
300
    if (ud.reccnt > RECSYNCBUFSIZ-MAXPLAYERS || (demorec_diffs && (g_demo_cnt%demorec_difftics == 0)))
301
        Demo_WriteSync();
301
        Demo_WriteSync();
302
}
302
}
303
303
304
void G_CloseDemoWrite(void)
304
void G_CloseDemoWrite(void)
305
{
305
{
306
    if (ud.recstat == 1)
306
    if (ud.recstat == 1)
307
    {
307
    {
308
        if (ud.reccnt > 0)
308
        if (ud.reccnt > 0)
309
            Demo_WriteSync();
309
            Demo_WriteSync();
310
310
311
        fwrite("EnD!", 4, 1, g_demo_filePtr);
311
        fwrite("EnD!", 4, 1, g_demo_filePtr);
312
312
313
        // lastly, we need to write the number of written recsyncs to the demo file
313
        // lastly, we need to write the number of written recsyncs to the demo file
314
        if (fseek(g_demo_filePtr, offsetof(savehead_t, reccnt), SEEK_SET))
314
        if (fseek(g_demo_filePtr, offsetof(savehead_t, reccnt), SEEK_SET))
315
            perror("G_CloseDemoWrite: final fseek");
315
            perror("G_CloseDemoWrite: final fseek");
316
        else
316
        else
317
            fwrite(&g_demo_cnt, sizeof(g_demo_cnt), 1, g_demo_filePtr);
317
            fwrite(&g_demo_cnt, sizeof(g_demo_cnt), 1, g_demo_filePtr);
318
318
319
        ud.recstat = ud.m_recstat = 0;
319
        ud.recstat = ud.m_recstat = 0;
320
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
320
        MAYBE_FCLOSE_AND_NULL(g_demo_filePtr);
321
321
322
        sv_freemem();
322
        sv_freemem();
323
323
324
        Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "DEMO RECORDING STOPPED");
324
        Bstrcpy(ScriptQuotes[QUOTE_RESERVED4], "DEMO RECORDING STOPPED");
325
        P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
325
        P_DoQuote(QUOTE_RESERVED4, g_player[myconnectindex].ps);
326
    }
326
    }
327
#if KRANDDEBUG
327
#if KRANDDEBUG
328
    krd_print("krandrec.log");
328
    krd_print("krandrec.log");
329
#endif
329
#endif
330
}
330
}
331
331
332
static int32_t g_whichDemo = 1;
332
static int32_t g_whichDemo = 1;
333
333
334
static int32_t Demo_UpdateState(int32_t frominit)
334
static int32_t Demo_UpdateState(int32_t frominit)
335
{
335
{
336
    int32_t j = g_player[myconnectindex].ps->gm&MODE_MENU;
336
    int32_t j = g_player[myconnectindex].ps->gm&MODE_MENU;
337
    int32_t k = sv_updatestate(frominit);
337
    int32_t k = sv_updatestate(frominit);
338
    //                            tmpdifftime = g_demo_cnt+12;
338
    //                            tmpdifftime = g_demo_cnt+12;
339
    Demo_RestoreModes(j);
339
    Demo_RestoreModes(j);
340
340
341
    if (k)
341
    if (k)
342
        OSD_Printf("sv_updatestate() returned %d.\n", k);
342
        OSD_Printf("sv_updatestate() returned %d.\n", k);
343
    return k;
343
    return k;
344
}
344
}
345
345
346
#define CORRUPT(code) do { corruptcode=code; goto corrupt; } while(0)
346
#define CORRUPT(code) do { corruptcode=code; goto corrupt; } while(0)
347
347
348
static int32_t Demo_ReadSync(int32_t errcode)
348
static int32_t Demo_ReadSync(int32_t errcode)
349
{
349
{
350
    uint16_t si;
350
    uint16_t si;
351
    int32_t i;
351
    int32_t i;
352
352
353
    if (kread(g_demo_recFilePtr, &si, sizeof(uint16_t)) != sizeof(uint16_t))
353
    if (kread(g_demo_recFilePtr, &si, sizeof(uint16_t)) != sizeof(uint16_t))
354
        return errcode;
354
        return errcode;
355
355
356
    i = si;
356
    i = si;
357
    if (demo_hasseeds)
357
    if (demo_hasseeds)
358
    {
358
    {
359
        if (kread(g_demo_recFilePtr, g_demo_seedbuf, i) != i)
359
        if (kread(g_demo_recFilePtr, g_demo_seedbuf, i) != i)
360
            return errcode;
360
            return errcode;
361
    }
361
    }
362
362
363
    if (demo_synccompress)
363
    if (demo_synccompress)
364
    {
364
    {
365
        if (kdfread(recsync, sizeof(input_t), i, g_demo_recFilePtr) != i)
365
        if (kdfread(recsync, sizeof(input_t), i, g_demo_recFilePtr) != i)
366
            return errcode+1;
366
            return errcode+1;
367
    }
367
    }
368
    else
368
    else
369
    {
369
    {
370
        int32_t bytes = sizeof(input_t)*i;
370
        int32_t bytes = sizeof(input_t)*i;
371
371
372
        if (kread(g_demo_recFilePtr, recsync, bytes) != bytes)
372
        if (kread(g_demo_recFilePtr, recsync, bytes) != bytes)
373
            return errcode+2;
373
            return errcode+2;
374
    }
374
    }
375
375
376
    ud.reccnt = i;
376
    ud.reccnt = i;
377
    return 0;
377
    return 0;
378
}
378
}
379
379
380
////////// DEMO PROFILING (TIMEDEMO MODE) //////////
380
////////// DEMO PROFILING (TIMEDEMO MODE) //////////
381
static struct {
381
static struct {
382
    int32_t numtics, numframes;
382
    int32_t numtics, numframes;
383
    double totalgamems;
383
    double totalgamems;
384
    double totalroomsdrawms, totalrestdrawms;
384
    double totalroomsdrawms, totalrestdrawms;
385
    double starthiticks;
385
    double starthiticks;
386
} g_prof;
386
} g_prof;
387
387
388
int32_t Demo_IsProfiling(void)
388
int32_t Demo_IsProfiling(void)
389
{
389
{
390
    return (g_demo_profile > 0);
390
    return (g_demo_profile > 0);
391
}
391
}
392
392
393
static void Demo_StopProfiling(void)
393
static void Demo_StopProfiling(void)
394
{
394
{
395
    g_demo_stopProfile = 1;
395
    g_demo_stopProfile = 1;
396
}
396
}
397
397
398
static void Demo_GToc(double t)
398
static void Demo_GToc(double t)
399
{
399
{
400
    g_prof.numtics++;
400
    g_prof.numtics++;
401
    g_prof.totalgamems += gethiticks()-t;
401
    g_prof.totalgamems += gethiticks()-t;
402
}
402
}
403
403
404
static void Demo_RToc(double t1, double t2)
404
static void Demo_RToc(double t1, double t2)
405
{
405
{
406
    g_prof.numframes++;
406
    g_prof.numframes++;
407
    g_prof.totalroomsdrawms += t2-t1;
407
    g_prof.totalroomsdrawms += t2-t1;
408
    g_prof.totalrestdrawms += gethiticks()-t2;
408
    g_prof.totalrestdrawms += gethiticks()-t2;
409
}
409
}
410
410
411
static void Demo_DisplayProfStatus(void)
411
static void Demo_DisplayProfStatus(void)
412
{
412
{
413
    char buf[64];
413
    char buf[64];
414
414
415
    static int32_t lastpercent=-1;
415
    static int32_t lastpercent=-1;
416
    int32_t percent = (100*g_demo_cnt)/g_demo_totalCnt;
416
    int32_t percent = (100*g_demo_cnt)/g_demo_totalCnt;
417
417
418
    if (lastpercent == percent)
418
    if (lastpercent == percent)
419
        return;
419
        return;
420
    lastpercent = percent;
420
    lastpercent = percent;
421
421
422
    clearallviews(0);
422
    clearallviews(0);
423
    Bsnprintf(buf, sizeof(buf), "timing... %d/%d game tics (%d %%)",
423
    Bsnprintf(buf, sizeof(buf), "timing... %d/%d game tics (%d %%)",
424
              g_demo_cnt, g_demo_totalCnt, percent);
424
              g_demo_cnt, g_demo_totalCnt, percent);
425
    gametext(160,60, buf, 0, 2+8+16);
425
    gametext(160,60, buf, 0, 2+8+16);
426
    nextpage();
426
    nextpage();
427
}
427
}
428
428
429
static void Demo_SetupProfile(void)
429
static void Demo_SetupProfile(void)
430
{
430
{
431
    g_demo_profile *= -1;  // now >0: profile for real
431
    g_demo_profile *= -1;  // now >0: profile for real
432
432
433
    g_demo_soundToggle = ud.config.SoundToggle;
433
    g_demo_soundToggle = ud.config.SoundToggle;
434
    ud.config.SoundToggle = 0;  // restored by Demo_FinishProfile()
434
    ud.config.SoundToggle = 0;  // restored by Demo_FinishProfile()
435
435
436
    Bmemset(&g_prof, 0, sizeof(g_prof));
436
    Bmemset(&g_prof, 0, sizeof(g_prof));
437
437
438
    g_prof.starthiticks = gethiticks();
438
    g_prof.starthiticks = gethiticks();
439
}
439
}
440
440
441
static void Demo_FinishProfile(void)
441
static void Demo_FinishProfile(void)
442
{
442
{
443
    if (Demo_IsProfiling())
443
    if (Demo_IsProfiling())
444
    {
444
    {
445
        int32_t dn=g_whichDemo-1;
445
        int32_t dn=g_whichDemo-1;
446
        int32_t nt=g_prof.numtics, nf=g_prof.numframes;
446
        int32_t nt=g_prof.numtics, nf=g_prof.numframes;
447
        double gms=g_prof.totalgamems;
447
        double gms=g_prof.totalgamems;
448
        double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms;
448
        double dms1=g_prof.totalroomsdrawms, dms2=g_prof.totalrestdrawms;
449
449
450
        ud.config.SoundToggle = g_demo_soundToggle;
450
        ud.config.SoundToggle = g_demo_soundToggle;
451
451
452
        if (nt > 0)
452
        if (nt > 0)
453
        {
453
        {
454
            OSD_Printf("== demo %d: %d gametics\n", dn, nt);
454
            OSD_Printf("== demo %d: %d gametics\n", dn, nt);
455
            OSD_Printf("== demo %d game times: %.03f ms (%.03f us/gametic)\n",
455
            OSD_Printf("== demo %d game times: %.03f ms (%.03f us/gametic)\n",
456
                       dn, gms, (gms*1000.0)/nt);
456
                       dn, gms, (gms*1000.0)/nt);
457
        }
457
        }
458
458
459
        if (nf > 0)
459
        if (nf > 0)
460
        {
460
        {
461
            OSD_Printf("== demo %d: %d frames (%d frames/gametic)\n", dn, nf, g_demo_profile-1);
461
            OSD_Printf("== demo %d: %d frames (%d frames/gametic)\n", dn, nf, g_demo_profile-1);
462
            OSD_Printf("== demo %d drawrooms times: %.03f s (%.03f ms/frame)\n",
462
            OSD_Printf("== demo %d drawrooms times: %.03f s (%.03f ms/frame)\n",
463
                       dn, dms1/1000.0, dms1/nf);
463
                       dn, dms1/1000.0, dms1/nf);
464
            OSD_Printf("== demo %d drawrest times: %.03f s (%.03f ms/frame)\n",
464
            OSD_Printf("== demo %d drawrest times: %.03f s (%.03f ms/frame)\n",
465
                       dn, dms2/1000.0, dms2/nf);
465
                       dn, dms2/1000.0, dms2/nf);
466
        }
466
        }
467
467
468
        {
468
        {
469
            double totalprofms = gms+dms1+dms2;
469
            double totalprofms = gms+dms1+dms2;
470
            double totalms = gethiticks()-g_prof.starthiticks;
470
            double totalms = gethiticks()-g_prof.starthiticks;
471
            if (totalprofms != 0)
471
            if (totalprofms != 0)
472
                OSD_Printf("== demo %d: non-profiled time overhead: %.02f %%\n",
472
                OSD_Printf("== demo %d: non-profiled time overhead: %.02f %%\n",
473
                           dn, 100.0*totalms/totalprofms - 100.0);
473
                           dn, 100.0*totalms/totalprofms - 100.0);
474
        }
474
        }
475
    }
475
    }
476
476
477
    g_demo_profile = 0;
477
    g_demo_profile = 0;
478
    g_demo_stopProfile = 0;
478
    g_demo_stopProfile = 0;
479
}
479
}
480
////////////////////
480
////////////////////
481
481
482
int32_t G_PlaybackDemo(void)
482
int32_t G_PlaybackDemo(void)
483
{
483
{
484
    int32_t bigi, j, initsyncofs = 0, lastsyncofs = 0, lastsynctic = 0, lastsyncclock = 0;
484
    int32_t bigi, j, initsyncofs = 0, lastsyncofs = 0, lastsynctic = 0, lastsyncclock = 0;
485
    int32_t foundemo = 0, corruptcode, outofsync=0;
485
    int32_t foundemo = 0, corruptcode, outofsync=0;
486
    static int32_t in_menu = 0;
486
    static int32_t in_menu = 0;
487
    //    static int32_t tmpdifftime=0;
487
    //    static int32_t tmpdifftime=0;
488
488
489
    if (ready2send)
489
    if (ready2send)
490
        return 0;
490
        return 0;
491
491
492
    if (!g_demo_playFirstFlag)
492
    if (!g_demo_playFirstFlag)
493
        g_demo_profile = 0;
493
        g_demo_profile = 0;
494
494
495
RECHECK:
495
RECHECK:
496
    if (g_demo_playFirstFlag)
496
    if (g_demo_playFirstFlag)
497
        g_demo_playFirstFlag = 0;
497
        g_demo_playFirstFlag = 0;
498
    else if (g_demo_exitAfter)
498
    else if (g_demo_exitAfter)
499
        G_GameExit(" ");
499
        G_GameExit(" ");
500
500
501
#if KRANDDEBUG
501
#if KRANDDEBUG
502
    if (foundemo)
502
    if (foundemo)
503
        krd_print("krandplay.log");
503
        krd_print("krandplay.log");
504
#endif
504
#endif
505
505
506
    in_menu = g_player[myconnectindex].ps->gm&MODE_MENU;
506
    in_menu = g_player[myconnectindex].ps->gm&MODE_MENU;
507
507
508
    pub = NUMPAGES;
508
    pub = NUMPAGES;
509
    pus = NUMPAGES;
509
    pus = NUMPAGES;
510
510
511
    flushperms();
511
    flushperms();
512
512
513
    if (!g_netServer && ud.multimode < 2)
513
    if (!g_netServer && ud.multimode < 2)
514
        foundemo = G_OpenDemoRead(g_whichDemo);
514
        foundemo = G_OpenDemoRead(g_whichDemo);
515
515
516
    if (foundemo == 0)
516
    if (foundemo == 0)
517
    {
517
    {
518
        ud.recstat = 0;
518
        ud.recstat = 0;
519
519
520
        if (g_whichDemo > 1)
520
        if (g_whichDemo > 1)
521
        {
521
        {
522
            g_whichDemo = 1;
522
            g_whichDemo = 1;
523
            goto RECHECK;
523
            goto RECHECK;
524
        }
524
        }
525
525
526
        fadepal(0,0,0, 0,63,7);
526
        fadepal(0,0,0, 0,63,7);
527
        P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1);    // JBF 20040308
527
        P_SetGamePalette(g_player[myconnectindex].ps, BASEPAL, 1);    // JBF 20040308
528
        G_DrawBackground();
528
        G_DrawBackground();
529
        M_DisplayMenus();
529
        M_DisplayMenus();
530
        //g_player[myconnectindex].ps->palette = palette;
530
        //g_player[myconnectindex].ps->palette = palette;
531
        nextpage();
531
        nextpage();
532
        fadepal(0,0,0, 63,0,-7);
532
        fadepal(0,0,0, 63,0,-7);
533
        ud.reccnt = 0;
533
        ud.reccnt = 0;
534
    }
534
    }
535
    else
535
    else
536
    {
536
    {
537
        ud.recstat = 2;
537
        ud.recstat = 2;
538
538
539
        g_whichDemo++;
539
        g_whichDemo++;
540
        if (g_whichDemo == MAXDEMOS)
540
        if (g_whichDemo == MAXDEMOS)
541
            g_whichDemo = 1;
541
            g_whichDemo = 1;
542
542
543
        g_player[myconnectindex].ps->gm &= ~MODE_GAME;
543
        g_player[myconnectindex].ps->gm &= ~MODE_GAME;
544
        g_player[myconnectindex].ps->gm |= MODE_DEMO;
544
        g_player[myconnectindex].ps->gm |= MODE_DEMO;
545
545
546
        lastsyncofs = ktell(g_demo_recFilePtr);
546
        lastsyncofs = ktell(g_demo_recFilePtr);
547
        initsyncofs = lastsyncofs;
547
        initsyncofs = lastsyncofs;
548
        lastsynctic = g_demo_cnt;
548
        lastsynctic = g_demo_cnt;
549
        lastsyncclock = totalclock;
549
        lastsyncclock = totalclock;
550
        outofsync = 0;
550
        outofsync = 0;
551
#if KRANDDEBUG
551
#if KRANDDEBUG
552
        krd_enable(2);
552
        krd_enable(2);
553
#endif
553
#endif
554
        if (g_demo_profile < 0)
554
        if (g_demo_profile < 0)
555
        {
555
        {
556
            Demo_SetupProfile();
556
            Demo_SetupProfile();
557
        }
557
        }
558
    }
558
    }
559
559
560
    if (foundemo == 0 || in_menu || I_CheckAllInput() || numplayers > 1)
560
    if (foundemo == 0 || in_menu || I_CheckAllInput() || numplayers > 1)
561
    {
561
    {
562
        FX_StopAllSounds();
562
        FX_StopAllSounds();
563
        S_ClearSoundLocks();
563
        S_ClearSoundLocks();
564
        M_OpenMenu(myconnectindex);
564
        M_OpenMenu(myconnectindex);
565
    }
565
    }
566
566
567
    ready2send = 0;
567
    ready2send = 0;
568
    bigi = 0;
568
    bigi = 0;
569
569
570
    I_ClearAllInput();
570
    I_ClearAllInput();
571
571
572
    //    OSD_Printf("ticcnt=%d, total=%d\n", g_demo_cnt, g_demo_totalCnt);
572
    //    OSD_Printf("ticcnt=%d, total=%d\n", g_demo_cnt, g_demo_totalCnt);
573
    while (g_demo_cnt < g_demo_totalCnt || foundemo==0)
573
    while (g_demo_cnt < g_demo_totalCnt || foundemo==0)
574
    {
574
    {
575
        // Main loop here. It also runs when there's no demo to show,
575
        // Main loop here. It also runs when there's no demo to show,
576
        // so maybe a better name for this function would be
576
        // so maybe a better name for this function would be
577
        // G_MainLoopWhenNotInGame()?
577
        // G_MainLoopWhenNotInGame()?
578
578
579
        // Demo requested from the OSD, its name is in g_firstDemoFile[]
579
        // Demo requested from the OSD, its name is in g_firstDemoFile[]
580
        if (g_demo_playFirstFlag)
580
        if (g_demo_playFirstFlag)
581
        {
581
        {
582
            g_demo_playFirstFlag = 0;
582
            g_demo_playFirstFlag = 0;
583
            g_whichDemo = 1;  // force g_firstDemoFile[]
583
            g_whichDemo = 1;  // force g_firstDemoFile[]
584
            g_demo_paused = 0;
584
            g_demo_paused = 0;
585
            goto nextdemo_nomenu;
585
            goto nextdemo_nomenu;
586
        }
586
        }
587
587
588
        if (foundemo && (!g_demo_paused || g_demo_goalCnt))
588
        if (foundemo && (!g_demo_paused || g_demo_goalCnt))
589
        {
589
        {
590
            if (g_demo_goalCnt>0 && g_demo_goalCnt < g_demo_cnt)
590
            if (g_demo_goalCnt>0 && g_demo_goalCnt < g_demo_cnt)
591
            {
591
            {
592
                // initialize rewind
592
                // initialize rewind
593
593
594
                int32_t menu = g_player[myconnectindex].ps->gm&MODE_MENU;
594
                int32_t menu = g_player[myconnectindex].ps->gm&MODE_MENU;
595
595
596
                if (g_demo_goalCnt > lastsynctic)
596
                if (g_demo_goalCnt > lastsynctic)
597
                {
597
                {
598
                    // we can use a previous diff
598
                    // we can use a previous diff
599
                    if (Demo_UpdateState(0)==0)
599
                    if (Demo_UpdateState(0)==0)
600
                    {
600
                    {
601
                        g_demo_cnt = lastsynctic;
601
                        g_demo_cnt = lastsynctic;
602
                        klseek(g_demo_recFilePtr, lastsyncofs, SEEK_SET);
602
                        klseek(g_demo_recFilePtr, lastsyncofs, SEEK_SET);
603
                        ud.reccnt = 0;
603
                        ud.reccnt = 0;
604
604
605
                        totalclock = ototalclock = lockclock = lastsyncclock;
605
                        totalclock = ototalclock = lockclock = lastsyncclock;
606
                    }
606
                    }
607
                    else CORRUPT(-1);
607
                    else CORRUPT(-1);
608
                }
608
                }
609
                else
609
                else
610
                {
610
                {
611
                    // update to initial state
611
                    // update to initial state
612
                    if (Demo_UpdateState(1) == 0)
612
                    if (Demo_UpdateState(1) == 0)
613
                    {
613
                    {
614
                        klseek(g_demo_recFilePtr, initsyncofs, SEEK_SET);
614
                        klseek(g_demo_recFilePtr, initsyncofs, SEEK_SET);
615
                        g_levelTextTime = 0;
615
                        g_levelTextTime = 0;
616
616
617
                        g_demo_cnt = 1;
617
                        g_demo_cnt = 1;
618
                        ud.reccnt = 0;
618
                        ud.reccnt = 0;
619
619
620
                        //                        ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
620
                        //                        ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
621
                        //                        ud.noclip = ud.scrollmode = ud.overhead_on = ud.pause_on = 0;
621
                        //                        ud.noclip = ud.scrollmode = ud.overhead_on = ud.pause_on = 0;
622
622
623
                        totalclock = ototalclock = lockclock = 0;
623
                        totalclock = ototalclock = lockclock = 0;
624
                    }
624
                    }
625
                    else CORRUPT(0);
625
                    else CORRUPT(0);
626
                }
626
                }
627
627
628
                Demo_RestoreModes(menu);
628
                Demo_RestoreModes(menu);
629
            }
629
            }
630
630
631
            if (g_demo_stopProfile)
631
            if (g_demo_stopProfile)
632
                Demo_FinishProfile();
632
                Demo_FinishProfile();
633
633
634
            while (totalclock >= (lockclock+TICSPERFRAME)
634
            while (totalclock >= (lockclock+TICSPERFRAME)
635
                //                   || (ud.reccnt > REALGAMETICSPERSEC*2 && ud.pause_on)
635
                //                   || (ud.reccnt > REALGAMETICSPERSEC*2 && ud.pause_on)
636
                || (g_demo_goalCnt>0 && g_demo_cnt<g_demo_goalCnt))
636
                || (g_demo_goalCnt>0 && g_demo_cnt<g_demo_goalCnt))
637
            {
637
            {
638
                if (ud.reccnt<=0)
638
                if (ud.reccnt<=0)
639
                {
639
                {
640
                    // Record count reached zero (or <0, corrupted), need
640
                    // Record count reached zero (or <0, corrupted), need
641
                    // reading another chunk.
641
                    // reading another chunk.
642
642
643
                    char tmpbuf[4];
643
                    char tmpbuf[4];
644
644
645
                    if (ud.reccnt<0)
645
                    if (ud.reccnt<0)
646
                    {
646
                    {
647
                        OSD_Printf("G_PlaybackDemo: ud.reccnt<0!\n");
647
                        OSD_Printf("G_PlaybackDemo: ud.reccnt<0!\n");
648
                        CORRUPT(1);
648
                        CORRUPT(1);
649
                    }
649
                    }
650
650
651
                    bigi = 0;
651
                    bigi = 0;
652
                    //reread:
652
                    //reread:
653
                    if (kread(g_demo_recFilePtr, tmpbuf, 4) != 4)
653
                    if (kread(g_demo_recFilePtr, tmpbuf, 4) != 4)
654
                        CORRUPT(2);
654
                        CORRUPT(2);
655
655
656
                    if (Bmemcmp(tmpbuf, "sYnC", 4)==0)
656
                    if (Bmemcmp(tmpbuf, "sYnC", 4)==0)
657
                    {
657
                    {
658
                        int32_t err = Demo_ReadSync(3);
658
                        int32_t err = Demo_ReadSync(3);
659
                        if (err)
659
                        if (err)
660
                            CORRUPT(err);
660
                            CORRUPT(err);
661
                    }
661
                    }
662
662
663
                    else if (demo_hasdiffs && Bmemcmp(tmpbuf, "dIfF", 4)==0)
663
                    else if (demo_hasdiffs && Bmemcmp(tmpbuf, "dIfF", 4)==0)
664
                    {
664
                    {
665
                        int32_t k = sv_readdiff(g_demo_recFilePtr);
665
                        int32_t k = sv_readdiff(g_demo_recFilePtr);
666
666
667
                        if (k)
667
                        if (k)
668
                        {
668
                        {
669
                            OSD_Printf("sv_readdiff() returned %d.\n", k);
669
                            OSD_Printf("sv_readdiff() returned %d.\n", k);
670
                            CORRUPT(6);
670
                            CORRUPT(6);
671
                        }
671
                        }
672
                        else
672
                        else
673
                        {
673
                        {
674
                            lastsyncofs = ktell(g_demo_recFilePtr);
674
                            lastsyncofs = ktell(g_demo_recFilePtr);
675
                            lastsynctic = g_demo_cnt;
675
                            lastsynctic = g_demo_cnt;
676
                            lastsyncclock = totalclock;
676
                            lastsyncclock = totalclock;
677
677
678
                            if (kread(g_demo_recFilePtr, tmpbuf, 4) != 4)
678
                            if (kread(g_demo_recFilePtr, tmpbuf, 4) != 4)
679
                                CORRUPT(7);
679
                                CORRUPT(7);
680
                            if (Bmemcmp(tmpbuf, "sYnC", 4))
680
                            if (Bmemcmp(tmpbuf, "sYnC", 4))
681
                                CORRUPT(8);
681
                                CORRUPT(8);
682
682
683
                            {
683
                            {
684
                                int32_t err = Demo_ReadSync(9);
684
                                int32_t err = Demo_ReadSync(9);
685
                                if (err)
685
                                if (err)
686
                                    CORRUPT(err);
686
                                    CORRUPT(err);
687
                            }
687
                            }
688
688
689
                            if ((g_demo_goalCnt==0 && demoplay_diffs) ||
689
                            if ((g_demo_goalCnt==0 && demoplay_diffs) ||
690
                                (g_demo_goalCnt>0 && ud.reccnt/ud.multimode >= g_demo_goalCnt-g_demo_cnt))
690
                                (g_demo_goalCnt>0 && ud.reccnt/ud.multimode >= g_demo_goalCnt-g_demo_cnt))
691
                            {
691
                            {
692
                                Demo_UpdateState(0);
692
                                Demo_UpdateState(0);
693
                            }
693
                            }
694
                        }
694
                        }
695
                    }
695
                    }
696
                    else if (Bmemcmp(tmpbuf, "EnD!", 4)==0)
696
                    else if (Bmemcmp(tmpbuf, "EnD!", 4)==0)
697
                        goto nextdemo;
697
                        goto nextdemo;
698
                    else CORRUPT(12);
698
                    else CORRUPT(12);
699
699
700
                    if (0)
700
                    if (0)
701
                    {
701
                    {
702
corrupt:
702
corrupt:
703
                        OSD_Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode);
703
                        OSD_Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode);
704
nextdemo:
704
nextdemo:
705
                        M_OpenMenu(myconnectindex);
705
                        M_OpenMenu(myconnectindex);
706
nextdemo_nomenu:
706
nextdemo_nomenu:
707
                        foundemo = 0;
707
                        foundemo = 0;
708
                        ud.reccnt = 0;
708
                        ud.reccnt = 0;
709
                        kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
709
                        kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
710
710
711
                        if (g_demo_goalCnt>0)
711
                        if (g_demo_goalCnt>0)
712
                        {
712
                        {
713
                            g_demo_goalCnt=0;
713
                            g_demo_goalCnt=0;
714
                            ud.config.SoundToggle = g_demo_soundToggle;
714
                            ud.config.SoundToggle = g_demo_soundToggle;
715
                        }
715
                        }
716
716
717
                        if (Demo_IsProfiling())  // don't reset g_demo_profile if it's < 0
717
                        if (Demo_IsProfiling())  // don't reset g_demo_profile if it's < 0
718
                            Demo_FinishProfile();
718
                            Demo_FinishProfile();
719
                        goto RECHECK;
719
                        goto RECHECK;
720
                    }
720
                    }
721
                }
721
                }
722
722
723
                if (demo_hasseeds)
723
                if (demo_hasseeds)
724
                    outofsync = ((uint8_t)(randomseed>>24) != g_demo_seedbuf[bigi]);
724
                    outofsync = ((uint8_t)(randomseed>>24) != g_demo_seedbuf[bigi]);
725
725
726
                for (TRAVERSE_CONNECT(j))
726
                for (TRAVERSE_CONNECT(j))
727
                {
727
                {
728
                    Bmemcpy(&inputfifo[0][j], &recsync[bigi], sizeof(input_t));
728
                    Bmemcpy(&inputfifo[0][j], &recsync[bigi], sizeof(input_t));
729
                    bigi++;
729
                    bigi++;
730
                    ud.reccnt--;
730
                    ud.reccnt--;
731
                }
731
                }
732
732
733
                g_demo_cnt++;
733
                g_demo_cnt++;
734
734
735
                if (Demo_IsProfiling())
735
                if (Demo_IsProfiling())
736
                {
736
                {
737
                    double t = gethiticks();
737
                    double t = gethiticks();
738
                    G_DoMoveThings();
738
                    G_DoMoveThings();
739
                    Demo_GToc(t);
739
                    Demo_GToc(t);
740
                }
740
                }
741
                else if (!g_demo_paused)
741
                else if (!g_demo_paused)
742
                {
742
                {
743
                    // assumption that ud.multimode doesn't change in a demo may not be true
743
                    // assumption that ud.multimode doesn't change in a demo may not be true
744
                    // sometime in the future                    v v v v v v v v v
744
                    // sometime in the future                    v v v v v v v v v
745
                    if (g_demo_goalCnt==0 || !demo_hasdiffs || ud.reccnt/ud.multimode>=g_demo_goalCnt-g_demo_cnt)
745
                    if (g_demo_goalCnt==0 || !demo_hasdiffs || ud.reccnt/ud.multimode>=g_demo_goalCnt-g_demo_cnt)
746
                    {
746
                    {
747
                        G_DoMoveThings();  // increases lockclock by TICSPERFRAME
747
                        G_DoMoveThings();  // increases lockclock by TICSPERFRAME
748
                    }
748
                    }
749
                    else
749
                    else
750
                    {
750
                    {
751
                        lockclock += TICSPERFRAME;
751
                        lockclock += TICSPERFRAME;
752
                    }
752
                    }
753
                }
753
                }
754
                else
754
                else
755
                {
755
                {
756
                    int32_t k = ud.config.SoundToggle;
756
                    int32_t k = ud.config.SoundToggle;
757
                    ud.config.SoundToggle = 0;
757
                    ud.config.SoundToggle = 0;
758
                    G_DoMoveThings();
758
                    G_DoMoveThings();
759
                    ud.config.SoundToggle = k;
759
                    ud.config.SoundToggle = k;
760
                }
760
                }
761
761
762
                ototalclock += TICSPERFRAME;
762
                ototalclock += TICSPERFRAME;
763
763
764
                if (g_demo_goalCnt > 0)
764
                if (g_demo_goalCnt > 0)
765
                {
765
                {
766
                    // if fast-forwarding, we must update totalclock
766
                    // if fast-forwarding, we must update totalclock
767
                    totalclock += TICSPERFRAME;
767
                    totalclock += TICSPERFRAME;
768
768
769
//                    OSD_Printf("t:%d, l+T:%d; cnt:%d, goal:%d%s", totalclock, (lockclock+TICSPERFRAME),
769
//                    OSD_Printf("t:%d, l+T:%d; cnt:%d, goal:%d%s", totalclock, (lockclock+TICSPERFRAME),
770
//                               g_demo_cnt, g_demo_goalCnt, g_demo_cnt>=g_demo_goalCnt?" ":"\n");
770
//                               g_demo_cnt, g_demo_goalCnt, g_demo_cnt>=g_demo_goalCnt?" ":"\n");
771
                    if (g_demo_cnt>=g_demo_goalCnt)
771
                    if (g_demo_cnt>=g_demo_goalCnt)
772
                    {
772
                    {
773
                        g_demo_goalCnt = 0;
773
                        g_demo_goalCnt = 0;
774
                        ud.config.SoundToggle = g_demo_soundToggle;
774
                        ud.config.SoundToggle = g_demo_soundToggle;
775
                    }
775
                    }
776
                }
776
                }
777
            }
777
            }
778
        }
778
        }
779
        else if (foundemo && g_demo_paused)
779
        else if (foundemo && g_demo_paused)
780
        {
780
        {
781
            totalclock = lockclock;
781
            totalclock = lockclock;
782
        }
782
        }
783
783
784
        if (Demo_IsProfiling())
784
        if (Demo_IsProfiling())
785
            totalclock += TICSPERFRAME;
785
            totalclock += TICSPERFRAME;
786
786
787
        if (foundemo == 0)
787
        if (foundemo == 0)
788
        {
788
        {
789
            G_DrawBackground();
789
            G_DrawBackground();
790
#ifdef LUNATIC
790
#ifdef LUNATIC
791
            El_DisplayErrors();
791
            El_DisplayErrors();
792
#endif
792
#endif
793
        }
793
        }
794
        else
794
        else
795
        {
795
        {
796
            static uint32_t nextrender = 0, framewaiting = 0;
796
            static uint32_t nextrender = 0, framewaiting = 0;
797
            uint32_t tt;
797
            uint32_t tt;
798
798
799
            // NOTE: currently, no key/mouse events will be seen while
799
            // NOTE: currently, no key/mouse events will be seen while
800
            // demo-profiling because we need 'totalclock' for ourselves.
800
            // demo-profiling because we need 'totalclock' for ourselves.
801
            // And handleevents() -> sampletimer() would mess that up.
801
            // And handleevents() -> sampletimer() would mess that up.
802
            G_HandleLocalKeys();
802
            G_HandleLocalKeys();
803
803
804
            if (framewaiting)
804
            if (framewaiting)
805
            {
805
            {
806
                framewaiting--;
806
                framewaiting--;
807
                nextpage();
807
                nextpage();
808
            }
808
            }
809
809
810
            tt = getticks();
810
            tt = getticks();
811
811
812
            // Render one frame (potentially many if profiling)
812
            // Render one frame (potentially many if profiling)
813
            if (Demo_IsProfiling())
813
            if (Demo_IsProfiling())
814
            {
814
            {
815
                int32_t i, num = g_demo_profile-1;
815
                int32_t i, num = g_demo_profile-1;
816
816
817
                Bassert(totalclock-ototalclock==4);
817
                Bassert(totalclock-ototalclock==4);
818
818
819
                for (i=0; i<num; i++)
819
                for (i=0; i<num; i++)
820
                {
820
                {
821
                    double t1 = gethiticks(), t2;
821
                    double t1 = gethiticks(), t2;
822
822
823
//                    initprintf("t=%d, o=%d, t-o = %d\n", totalclock,
823
//                    initprintf("t=%d, o=%d, t-o = %d\n", totalclock,
824
//                               ototalclock, totalclock-ototalclock);
824
//                               ototalclock, totalclock-ototalclock);
825
825
826
                    // NOTE: G_DrawRooms() calculates smoothratio inside and
826
                    // NOTE: G_DrawRooms() calculates smoothratio inside and
827
                    // ignores the function argument, so we set totalclock
827
                    // ignores the function argument, so we set totalclock
828
                    // accordingly.
828
                    // accordingly.
829
                    j = (i<<16)/num;
829
                    j = (i<<16)/num;
830
                    totalclock = ototalclock + (j>>16);
830
                    totalclock = ototalclock + (j>>16);
831
831
832
                    G_DrawRooms(screenpeek,j);
832
                    G_DrawRooms(screenpeek,j);
833
833
834
                    t2 = gethiticks();
834
                    t2 = gethiticks();
835
835
836
                    G_DisplayRest(j);
836
                    G_DisplayRest(j);
837
837
838
                    Demo_RToc(t1, t2);
838
                    Demo_RToc(t1, t2);
839
                }
839
                }
840
840
841
                totalclock = ototalclock+4;
841
                totalclock = ototalclock+4;
842
842
843
                // draw status
843
                // draw status
844
                Demo_DisplayProfStatus();
844
                Demo_DisplayProfStatus();
845
845
846
                if (handleevents_peekkeys())
846
                if (handleevents_peekkeys())
847
                    Demo_StopProfiling();
847
                    Demo_StopProfiling();
848
            }
848
            }
849
            else if (r_maxfps == 0 || tt >= nextrender)
849
            else if (r_maxfps == 0 || tt >= nextrender)
850
            {
850
            {
851
                if (tt > nextrender+g_frameDelay)
851
                if (tt > nextrender+g_frameDelay)
852
                    nextrender = tt;
852
                    nextrender = tt;
853
853
854
                nextrender += g_frameDelay;
854
                nextrender += g_frameDelay;
855
855
856
                j = calc_smoothratio(totalclock, ototalclock);
856
                j = calc_smoothratio(totalclock, ototalclock);
857
                if (g_demo_paused && g_demo_rewind)
857
                if (g_demo_paused && g_demo_rewind)
858
                    j = 65536-j;
858
                    j = 65536-j;
859
859
860
                G_DrawRooms(screenpeek,j);
860
                G_DrawRooms(screenpeek,j);
861
                G_DisplayRest(j);
861
                G_DisplayRest(j);
862
862
863
                framewaiting++;
863
                framewaiting++;
864
            }
864
            }
865
865
866
            if (!Demo_IsProfiling() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
866
            if (!Demo_IsProfiling() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
867
            {
867
            {
868
                if (demoplay_showsync && outofsync)
868
                if (demoplay_showsync && outofsync)
869
                    gametext(160,100,"OUT OF SYNC",0,2+8+16);
869
                    gametext(160,100,"OUT OF SYNC",0,2+8+16);
870
870
871
                if (g_demo_showStats)
871
                if (g_demo_showStats)
872
                {
872
                {
873
#if 0
873
#if 0
874
                    if (g_demo_cnt<tmpdifftime)
874
                    if (g_demo_cnt<tmpdifftime)
875
                        gametext(160,100,"DIFF",0,2+8+16);
875
                        gametext(160,100,"DIFF",0,2+8+16);
876
876
877
                    {
877
                    {
878
                        char buf[32];
878
                        char buf[32];
879
                        Bsprintf(buf, "RC:%4d  TC:%5d", ud.reccnt, g_demo_cnt);
879
                        Bsprintf(buf, "RC:%4d  TC:%5d", ud.reccnt, g_demo_cnt);
880
                        gametext(160,100,buf,0,2+8+16);
880
                        gametext(160,100,buf,0,2+8+16);
881
                    }
881
                    }
882
#endif
882
#endif
883
                    j=g_demo_cnt/REALGAMETICSPERSEC;
883
                    j=g_demo_cnt/REALGAMETICSPERSEC;
884
                    Bsprintf(buf, "%02d:%02d", j/60, j%60);
884
                    Bsprintf(buf, "%02d:%02d", j/60, j%60);
885
                    gametext(18,16,buf,0,2+8+16+1024);
885
                    gametext(18,16,buf,0,2+8+16+1024);
886
886
887
                    rotatesprite(60<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,0,0,(xdim*95)/320,ydim-1);
887
                    rotatesprite(60<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,0,0,(xdim*95)/320,ydim-1);
888
                    rotatesprite(90<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,(xdim*95)/320,0,(xdim*125)/320,ydim-1);
888
                    rotatesprite(90<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,(xdim*95)/320,0,(xdim*125)/320,ydim-1);
889
                    rotatesprite(120<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,(xdim*125)/320,0,(xdim*155)/320,ydim-1);
889
                    rotatesprite(120<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,(xdim*125)/320,0,(xdim*155)/320,ydim-1);
890
                    rotatesprite(150<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,(xdim*155)/320,0,xdim-1,ydim-1);
890
                    rotatesprite(150<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16+1024,(xdim*155)/320,0,xdim-1,ydim-1);
891
891
892
                    j = (182<<16) - (tabledivide32_noinline((120*(g_demo_totalCnt-g_demo_cnt))<<4, g_demo_totalCnt)<<12);
892
                    j = (182<<16) - (tabledivide32_noinline((120*(g_demo_totalCnt-g_demo_cnt))<<4, g_demo_totalCnt)<<12);
893
                    rotatesprite_fs(j,(16<<16)+(1<<15),32768,0,SLIDEBAR+1,0,0,2+8+16+1024);
893
                    rotatesprite_fs(j,(16<<16)+(1<<15),32768,0,SLIDEBAR+1,0,0,2+8+16+1024);
894
894
895
                    j=(g_demo_totalCnt-g_demo_cnt)/REALGAMETICSPERSEC;
895
                    j=(g_demo_totalCnt-g_demo_cnt)/REALGAMETICSPERSEC;
896
                    Bsprintf(buf, "-%02d:%02d%s", j/60, j%60, g_demo_paused?"   ^15PAUSED":"");
896
                    Bsprintf(buf, "-%02d:%02d%s", j/60, j%60, g_demo_paused?"   ^15PAUSED":"");
897
                    gametext(194,16,buf,0,2+8+16+1024);
897
                    gametext(194,16,buf,0,2+8+16+1024);
898
                }
898
                }
899
            }
899
            }
900
900
901
            if ((g_netServer || ud.multimode > 1) && g_player[myconnectindex].ps->gm)
901
            if ((g_netServer || ud.multimode > 1) && g_player[myconnectindex].ps->gm)
902
                Net_GetPackets();
902
                Net_GetPackets();
903
903
904
            if (g_player[myconnectindex].gotvote == 0 && voting != -1 && voting != myconnectindex)
904
            if (g_player[myconnectindex].gotvote == 0 && voting != -1 && voting != myconnectindex)
905
                gametext(160,60,"Press F1 to Accept, F2 to Decline",0,2+8+16);
905
                gametext(160,60,"Press F1 to Accept, F2 to Decline",0,2+8+16);
906
        }
906
        }
907
907
908
        if ((g_player[myconnectindex].ps->gm&MODE_MENU) && (g_player[myconnectindex].ps->gm&MODE_EOL))
908
        if ((g_player[myconnectindex].ps->gm&MODE_MENU) && (g_player[myconnectindex].ps->gm&MODE_EOL))
909
        {
909
        {
910
            Demo_FinishProfile();
910
            Demo_FinishProfile();
911
            goto RECHECK;
911
            goto RECHECK;
912
        }
912
        }
913
913
914
        if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0)
914
        if (I_EscapeTrigger() && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0 && (g_player[myconnectindex].ps->gm&MODE_TYPE) == 0)
915
        {
915
        {
916
            I_EscapeTriggerClear();
916
            I_EscapeTriggerClear();
917
            FX_StopAllSounds();
917
            FX_StopAllSounds();
918
            S_ClearSoundLocks();
918
            S_ClearSoundLocks();
919
            M_OpenMenu(myconnectindex);
919
            M_OpenMenu(myconnectindex);
920
            M_ChangeMenu(MENU_MAIN);
920
            M_ChangeMenu(MENU_MAIN);
921
            S_MenuSound();
921
            S_MenuSound();
922
        }
922
        }
923
923
924
        if (Demo_IsProfiling())
924
        if (Demo_IsProfiling())
925
        {
925
        {
926
            // Do nothing: sampletimer() is reached from M_DisplayMenus() ->
926
            // Do nothing: sampletimer() is reached from M_DisplayMenus() ->
927
            // Net_GetPackets() else.
927
            // Net_GetPackets() else.
928
        }
928
        }
929
        else if (g_player[myconnectindex].ps->gm&MODE_TYPE)
929
        else if (g_player[myconnectindex].ps->gm&MODE_TYPE)
930
        {
930
        {
931
            Net_SendMessage();
931
            Net_SendMessage();
932
932
933
            if ((g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE)
933
            if ((g_player[myconnectindex].ps->gm&MODE_TYPE) != MODE_TYPE)
934
            {
934
            {
935
                g_player[myconnectindex].ps->gm = 0;
935
                g_player[myconnectindex].ps->gm = 0;
936
                M_OpenMenu(myconnectindex);
936
                M_OpenMenu(myconnectindex);
937
            }
937
            }
938
        }
938
        }
939
        else
939
        else
940
        {
940
        {
941
            if (ud.recstat != 2)
941
            if (ud.recstat != 2)
942
                M_DisplayMenus();
942
                M_DisplayMenus();
943
943
944
            if ((g_netServer || ud.multimode > 1)  && !M_IsTextInput(m_currentMenu))
944
            if ((g_netServer || ud.multimode > 1)  && !M_IsTextInput(m_currentMenu))
945
            {
945
            {
946
                ControlInfo noshareinfo;
946
                ControlInfo noshareinfo;
947
                CONTROL_GetInput(&noshareinfo);
947
                CONTROL_GetInput(&noshareinfo);
948
                if (BUTTON(gamefunc_SendMessage))
948
                if (BUTTON(gamefunc_SendMessage))
949
                {
949
                {
950
                    KB_FlushKeyboardQueue();
950
                    KB_FlushKeyboardQueue();
951
                    CONTROL_ClearButton(gamefunc_SendMessage);
951
                    CONTROL_ClearButton(gamefunc_SendMessage);
952
                    g_player[myconnectindex].ps->gm = MODE_TYPE;
952
                    g_player[myconnectindex].ps->gm = MODE_TYPE;
953
                    typebuf[0] = 0;
953
                    typebuf[0] = 0;
954
                }
954
                }
955
            }
955
            }
956
        }
956
        }
957
957
958
        if (!Demo_IsProfiling())
958
        if (!Demo_IsProfiling())
959
            G_PrintGameQuotes(screenpeek);
959
            G_PrintGameQuotes(screenpeek);
960
960
961
        if (ud.last_camsprite != ud.camerasprite)
961
        if (ud.last_camsprite != ud.camerasprite)
962
        {
-
 
963
            ud.last_camsprite = ud.camerasprite;
962
            ud.last_camsprite = ud.camerasprite;
964
//            ud.camera_time = totalclock+(TICRATE*2);
-
 
965
        }
-
 
966
963
967
        if (VOLUMEONE)
964
        if (VOLUMEONE)
968
        {
965
        {
969
            if (ud.show_help == 0 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
966
            if (ud.show_help == 0 && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
970
                rotatesprite_fs((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128);
967
                rotatesprite_fs((320-50)<<16,9<<16,65536L,0,BETAVERSION,0,0,2+8+16+128);
971
        }
968
        }
972
969
973
        // NOTE: We must prevent handleevents() and Net_GetPackets() from
970
        // NOTE: We must prevent handleevents() and Net_GetPackets() from
974
        // updating totalclock when profiling (both via sampletimer()):
971
        // updating totalclock when profiling (both via sampletimer()):
975
        if (!Demo_IsProfiling())
972
        if (!Demo_IsProfiling())
976
            G_HandleAsync();
973
            G_HandleAsync();
977
974
978
        if (ud.recstat==0)
975
        if (ud.recstat==0)
979
            nextpage();
976
            nextpage();
980
977
981
        if (g_player[myconnectindex].ps->gm == MODE_GAME)
978
        if (g_player[myconnectindex].ps->gm == MODE_GAME)
982
        {
979
        {
983
            // user wants to play a game, quit showing demo!
980
            // user wants to play a game, quit showing demo!
984
981
985
            if (foundemo)
982
            if (foundemo)
986
            {
983
            {
987
#if KRANDDEBUG
984
#if KRANDDEBUG
988
                krd_print("krandplay.log");
985
                krd_print("krandplay.log");
989
#endif
986
#endif
990
                kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
987
                kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
991
            }
988
            }
992
989
993
            return 0;
990
            return 0;
994
        }
991
        }
995
    }
992
    }
996
993
997
    ud.multimode = numplayers;  // fixes 2 infinite loops after watching demo
994
    ud.multimode = numplayers;  // fixes 2 infinite loops after watching demo
998
    kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
995
    kclose(g_demo_recFilePtr); g_demo_recFilePtr = -1;
999
996
1000
    Demo_FinishProfile();
997
    Demo_FinishProfile();
1001
998
1002
    // if we're in the menu, try next demo immediately
999
    // if we're in the menu, try next demo immediately
1003
    if (g_player[myconnectindex].ps->gm&MODE_MENU)
1000
    if (g_player[myconnectindex].ps->gm&MODE_MENU)
1004
        goto RECHECK;
1001
        goto RECHECK;
1005
1002
1006
#if KRANDDEBUG
1003
#if KRANDDEBUG
1007
    if (foundemo)
1004
    if (foundemo)
1008
        krd_print("krandplay.log");
1005
        krd_print("krandplay.log");
1009
#endif
1006
#endif
1010
1007
1011
    // finished playing a demo and not in menu:
1008
    // finished playing a demo and not in menu:
1012
    // return so that e.g. the title can be shown
1009
    // return so that e.g. the title can be shown
1013
    return 1;
1010
    return 1;
1014
}
1011
}
1015
 
1012