Improved demo system. Kick ass and watch :)\

Features:  * start recording in mid-game (ScrollLock)
           * saves interleaved diffs for later sync correction
           * supports fast-forward/rewind

Some work still needed to trace down remaining sync problems. Also be sure to check the demo* cvars.

git-svn-id: https://svn.eduke32.com/eduke32@1595 1a8010ca-5511-0410-912e-c29ae57300e0
This commit is contained in:
helixhorned 2010-01-24 23:33:17 +00:00
parent 0d6dc3a531
commit eb5f59ca7f
15 changed files with 2051 additions and 312 deletions

View file

@ -22,10 +22,15 @@ BUILD32_ON_64 = 0
# Debugging/Build options
RELEASE?=1
DEBUGANYWAY?=0
KRANDDEBUG?=0
NOSOUND?=0
OPTLEVEL?=2
PROFILER?=0
ifneq (0,$(KRANDDEBUG))
RELEASE=0
endif
# Build locations
SRC=source
RSRC=rsrc
@ -42,6 +47,10 @@ ifneq (0,$(RELEASE))
else
# Debugging enabled
debug=-ggdb -O0 -DDEBUGGINGAIDS
ifneq (0,$(KRANDDEBUG))
debug+=-fno-inline -fno-inline-functions -fno-inline-functions-called-once
debug+=-DKRANDDEBUG=1
endif
endif
ifneq (0,$(DEBUGANYWAY))
@ -199,6 +208,11 @@ EDITOROBJS+= $(OBJ)/sounds_mapster32.$o
OURCFLAGS+= $(BUILDCFLAGS)
OURCXXFLAGS+= $(BUILDCFLAGS)
MISCLINKOPTS=
ifneq (0,$(KRANDDEBUG))
MISCLINKOPTS=-Wl,-Map=$@.memmap
endif
ifeq ($(PRETTY_OUTPUT),1)
.SILENT:
endif
@ -218,7 +232,7 @@ notice:
eduke32$(EXESUFFIX): $(GAMEOBJS) $(EOBJ)/$(ENGINELIB) $(JAUDIOLIBDIR)/$(JAUDIOLIB) $(ENETDIR)/$(ENETLIB)
$(LINK_STATUS)
if $(CC) -o $@ $^ $(LIBS) $(STDCPPLIB); then $(LINK_OK); else $(LINK_FAILED); fi
if $(CC) -o $@ $^ $(LIBS) $(STDCPPLIB) $(MISCLINKOPTS); then $(LINK_OK); else $(LINK_FAILED); fi
ifeq (1,$(RELEASE))
ifeq (0,$(DEBUGANYWAY))
$(STRIP) eduke32$(EXESUFFIX)
@ -252,7 +266,7 @@ ifeq ($(PRETTY_OUTPUT),1)
printf "\033[K\033[0;35mChanging dir to \033[1;35m$(CURDIR)/$(EROOT)\033[0;35m \033[0m\n"
endif
$(MAKE) -C $(EROOT)/ "OBJ=../$(EOBJ)" \
SUPERBUILD=$(SUPERBUILD) POLYMOST=$(POLYMOST) DEBUGANYWAY=$(DEBUGANYWAY)\
SUPERBUILD=$(SUPERBUILD) POLYMOST=$(POLYMOST) DEBUGANYWAY=$(DEBUGANYWAY) KRANDDEBUG=$(KRANDDEBUG)\
USE_OPENGL=$(USE_OPENGL) BUILD32_ON_64=$(BUILD32_ON_64) \
NOASM=$(NOASM) RELEASE=$(RELEASE) OPTLEVEL=$(OPTLEVEL) $@
ifeq ($(PRETTY_OUTPUT),1)

View file

@ -38,9 +38,14 @@ endif
#
RELEASE?=1
DEBUGANYWAY?=0
KRANDDEBUG?=0
EFENCE?=0
OPTLEVEL ?= 2
ifneq (0,$(KRANDDEBUG))
RELEASE=0
endif
# SDK locations for Windows - adjust to match your setup
#
DXROOT=c:/sdks/directx/dx61
@ -69,6 +74,9 @@ ifneq ($(RELEASE),0)
else
# Debugging enabled
debug=-ggdb -O0 -DDEBUGGINGAIDS -DNOSDLPARACHUTE
ifneq (0,$(KRANDDEBUG))
debug+=-DKRANDDEBUG=1
endif
endif
ifneq (0,$(DEBUGANYWAY))

View file

@ -294,6 +294,7 @@ typedef struct s_pranimatespritesinfo {
int32_t polymer_init(void);
void polymer_uninit(void);
void polymer_glinit(void);
void polymer_resetlights(void);
void polymer_loadboard(void);
void polymer_drawrooms(int32_t daposx, int32_t daposy, int32_t daposz, int16_t daang, int32_t dahoriz, int16_t dacursectnum);
void polymer_drawmasks(void);
@ -355,7 +356,7 @@ static void polymer_compileprogram(int32_t programbits);
// LIGHTS
static void polymer_removelight(int16_t lighti);
static void polymer_updatelights(void);
static void polymer_resetlights(void);
//static void polymer_resetlights(void);
static inline void polymer_resetplanelights(_prplane* plane);
static void polymer_addplanelight(_prplane* plane, int16_t lighti);
static inline void polymer_deleteplanelight(_prplane* plane, int16_t lighti);

View file

@ -9500,6 +9500,58 @@ void getmousevalues(int32_t *mousx, int32_t *mousy, int32_t *bstatus)
}
#if KRANDDEBUG
# include <execinfo.h>
# define KRD_MAXCALLS 262144
# define KRD_DEPTH 8
static int krd_numcalls=0;
static int krd_randomseed[KRD_MAXCALLS];
static int krd_totalclock[KRD_MAXCALLS];
static void *krd_fromwhere[KRD_MAXCALLS][KRD_DEPTH];
static int32_t krd_enabled=0;
void krd_enable()
{
krd_enabled = 1;
}
int32_t krd_print(const char *filename)
{
FILE *krd_fp = fopen(filename, "w");
int i, j, k, ototalclk=0;
krd_enabled = 0;
if (!krd_fp) { printf("KRANDDEBUG: Couldn't open file!"); return 1; }
for (i=0; i<krd_numcalls; i++)
{
k = (ototalclk != krd_totalclock[i]);
if (k)
{
ototalclk = krd_totalclock[i];
fprintf(krd_fp, "#%d:", ototalclk);
}
fprintf(krd_fp, " %08x:", krd_randomseed[i]);
for (j=1;; j++) // skip self entry
{
if (j>=KRD_DEPTH || krd_fromwhere[i][j]==NULL)
{
fprintf(krd_fp, "\n");
break;
}
fprintf(krd_fp, " [%p]", krd_fromwhere[i][j]);
}
}
krd_numcalls = 0;
fclose(krd_fp);
return 0;
}
#endif
//
// krand
//
@ -9507,6 +9559,20 @@ int32_t krand(void)
{
// randomseed = (randomseed*27584621)+1;
randomseed = (randomseed * 1664525ul) + 221297ul;
#if KRANDDEBUG
if (krd_enabled)
if (krd_numcalls < KRD_MAXCALLS)
{
int32_t i;
krd_randomseed[krd_numcalls] = randomseed;
krd_totalclock[krd_numcalls] = totalclock;
for (i=backtrace(krd_fromwhere[krd_numcalls],KRD_DEPTH); i<KRD_DEPTH; i++)
krd_fromwhere[krd_numcalls][i] = NULL;
krd_numcalls++;
}
#endif
return(((uint32_t)randomseed)>>16);
}

View file

@ -1379,8 +1379,6 @@ void OSD_Draw(void)
// and write it to the log file
//
extern int32_t premap_quickenterlevel;
static inline void linefeed(void)
{
Bmemmove(osdtext+osdcols, osdtext, TEXTSIZE-osdcols);
@ -1398,8 +1396,6 @@ void OSD_Printf(const char *fmt, ...)
if (!osdinited) OSD_Init();
if (premap_quickenterlevel) return;
va_start(va, fmt);
Bvsnprintf(tmpstr, 8192, fmt, va);
va_end(va);

View file

@ -25,6 +25,15 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "gamedef.h"
#include "compat.h"
#if KRANDDEBUG
# define ACTOR_INLINE
# define ACTOR_STATIC
#else
# define ACTOR_INLINE inline
# define ACTOR_STATIC static
#endif
#define KILLIT(KX) {deletesprite(KX);goto BOLT;}
extern int32_t g_numEnvSoundsPlaying;
@ -456,7 +465,7 @@ int32_t A_MoveSprite(int32_t spritenum, const vec3_t *change, uint32_t cliptype)
return(retval);
}
inline int32_t A_SetSprite(int32_t i,uint32_t cliptype)
ACTOR_INLINE int32_t A_SetSprite(int32_t i,uint32_t cliptype)
{
vec3_t davect = {(sprite[i].xvel*(sintable[(sprite[i].ang+512)&2047]))>>14,
(sprite[i].xvel*(sintable[sprite[i].ang&2047]))>>14,
@ -724,7 +733,7 @@ inline void G_AddGameLight(int32_t radius, int32_t srcsprite, int32_t zoffset, i
}
// sleeping monsters, etc
static void G_MoveZombieActors(void)
ACTOR_STATIC void G_MoveZombieActors(void)
{
int32_t x, px, py, sx, sy;
int32_t i = headspritestat[STAT_ZOMBIEACTOR], j, p, nexti;
@ -1020,7 +1029,7 @@ BOLT:
int32_t otherp;
static void G_MovePlayers(void)
ACTOR_STATIC void G_MovePlayers(void)
{
int32_t i = headspritestat[STAT_PLAYER], nexti;
int32_t otherx;
@ -1153,7 +1162,7 @@ BOLT:
}
}
static void G_MoveFX(void)
ACTOR_STATIC void G_MoveFX(void)
{
int32_t i = headspritestat[STAT_FX], j, nexti, p;
int32_t x, ht;
@ -1253,7 +1262,7 @@ BOLT:
}
}
static void G_MoveFallers(void)
ACTOR_STATIC void G_MoveFallers(void)
{
int32_t i = headspritestat[STAT_FALLER], nexti, sect, j;
spritetype *s;
@ -1351,7 +1360,7 @@ BOLT:
}
}
static void G_MoveStandables(void)
ACTOR_STATIC void G_MoveStandables(void)
{
int32_t i = headspritestat[STAT_STANDABLE], j, k, nexti, nextj, p=0, sect, switchpicnum;
int32_t l=0, x;
@ -2312,7 +2321,7 @@ BOLT:
}
}
static void A_DoProjectileBounce(int32_t i)
ACTOR_STATIC void A_DoProjectileBounce(int32_t i)
{
int32_t dax, day, daz = 4096;
spritetype *s = &sprite[i];
@ -2349,7 +2358,7 @@ static void A_DoProjectileBounce(int32_t i)
s->ang = getangle(xvect,yvect);
}
static void G_MoveWeapons(void)
ACTOR_STATIC void G_MoveWeapons(void)
{
int32_t i = headspritestat[STAT_PROJECTILE], j=0, k, f, nexti, p, q;
vec3_t davect;
@ -3092,7 +3101,7 @@ BOLT:
}
}
static void G_MoveTransports(void)
ACTOR_STATIC void G_MoveTransports(void)
{
int32_t warpspriteto;
int32_t i = headspritestat[STAT_TRANSPORT], j, k, l, p, sect, sectlotag, nexti, nextj;
@ -3447,7 +3456,7 @@ static int16_t A_FindLocator(int32_t n,int32_t sn)
return -1;
}
static void G_MoveActors(void)
ACTOR_STATIC void G_MoveActors(void)
{
int32_t x, m, l;
intptr_t *t;
@ -4796,7 +4805,7 @@ BOLT:
}
static void G_MoveMisc(void) // STATNUM 5
ACTOR_STATIC void G_MoveMisc(void) // STATNUM 5
{
int16_t i, j, nexti, sect, p;
int32_t l, x;
@ -5359,7 +5368,7 @@ BOLT:
}
}
static void G_MoveEffectors(void) //STATNUM 3
ACTOR_STATIC void G_MoveEffectors(void) //STATNUM 3
{
int32_t q=0, m, x, st, j;
intptr_t *t,l;

View file

@ -78,8 +78,6 @@ static int16_t g_definedsndnum[MAXSOUNDS]; // maps parse order index to g_sound
static int16_t g_sndnum[MAXSOUNDS]; // maps current order index to g_sounds index
int32_t g_numsounds = 0;
int32_t premap_quickenterlevel=0;
#if !defined(_WIN32)
static int32_t usecwd = 0;
#endif

View file

@ -606,6 +606,8 @@ extern palette_t DefaultCrosshairColors;
extern char g_modDir[BMAX_PATH];
extern int32_t r_maxfps;
extern int32_t g_noSetup;
extern int32_t demorec_diffs_cvar, demoplay_diffs;
extern int32_t demorec_difftics_cvar, demorec_diffcompress_cvar, demorec_synccompress_cvar;
int32_t CONFIG_ReadSetup(void)
{
@ -879,6 +881,19 @@ int32_t CONFIG_ReadSetup(void)
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "WeaponScale",&ud.weaponscale);
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "WeaponSway",&ud.weaponsway);
{
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "DemoRecDiffs",&demorec_diffs_cvar);
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "DemoRecDiffTics",&demorec_difftics_cvar);
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "DemoRecDiffCompress",&demorec_diffcompress_cvar);
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "DemoRecSyncCompress",&demorec_synccompress_cvar);
SCRIPT_GetNumber(ud.config.scripthandle, "Misc", "DemoPlayDiffs",&demoplay_diffs);
demorec_diffs_cvar = !!demorec_diffs_cvar;
demorec_difftics_cvar = min(max(2, demorec_difftics_cvar), 60*(TICRATE/TICSPERFRAME));
demorec_diffcompress_cvar = min(max(0, demorec_diffcompress_cvar), 1);
demorec_synccompress_cvar = min(max(0, demorec_synccompress_cvar), 1);
demoplay_diffs = !!demoplay_diffs;
}
// weapon choices are defaulted in G_CheckCommandLine, which may override them
if (!g_forceWeaponChoice)
for (i=0; i<10; i++)
@ -1071,6 +1086,12 @@ void CONFIG_WriteSetup(void)
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "WeaponScale",ud.weaponscale,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "WeaponSway",ud.weaponsway,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "DemoRecDiffs",demorec_diffs_cvar,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "DemoRecDiffTics",demorec_difftics_cvar,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "DemoRecDiffCompress",demorec_diffcompress_cvar,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "DemoRecSyncCompress",demorec_synccompress_cvar,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Misc", "DemoPlayDiffs",demoplay_diffs,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Setup","ConfigVersion",BYTEVERSION_JF,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Setup", "ForceSetup",ud.config.ForceSetup,FALSE,FALSE);
SCRIPT_PutNumber(ud.config.scripthandle, "Setup", "NoAutoLoad",ud.config.NoAutoLoad,FALSE,FALSE);

View file

@ -222,8 +222,8 @@ extern void Gv_DumpValues(void);
extern void Gv_ResetSystemDefaults(void);
extern void Gv_InitWeaponPointers(void);
extern void Gv_Init(void);
extern void Gv_WriteSave(FILE *fil);
extern int32_t Gv_ReadSave(int32_t fil);
extern void Gv_WriteSave(FILE *fil, int32_t newbehav);
extern int32_t Gv_ReadSave(int32_t fil, int32_t newbehav);
extern int32_t __fastcall Gv_GetVar(register int32_t id, register int32_t iActor, register int32_t iPlayer);
extern void __fastcall Gv_SetVar(register int32_t id, register int32_t lValue, register int32_t iActor, register int32_t iPlayer);

View file

@ -49,6 +49,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "enet/enet.h"
#include "quicklz.h"
#if KRANDDEBUG
# define GAME_INLINE
# define GAME_STATIC
#else
# define GAME_INLINE inline
# define GAME_STATIC static
#endif
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
@ -106,9 +114,17 @@ static int32_t g_Debug = 0;
extern int32_t numlumps;
static FILE *g_demo_filePtr = (FILE *)NULL;
static int32_t g_demo_goalCnt=0, g_demo_startCnt=0, g_demo_soundToggle, g_demo_showStats=1;
static int32_t g_demo_paused=0;
static int32_t g_demo_recFilePtr, g_demo_totalCnt;
static int32_t g_demo_cnt, g_demo_goalCnt=0, g_demo_totalCnt, g_demo_soundToggle;
static int32_t g_demo_paused=0, g_demo_rewind=0, g_demo_showStats=1;
static int32_t g_demo_recFilePtr;
static int32_t demo_hasdiffs, demorec_diffs=1, demorec_difftics = 2*(TICRATE/TICSPERFRAME);
int32_t demoplay_diffs=1, demorec_diffs_cvar=1, demorec_force_cvar=0;
int32_t demorec_difftics_cvar = 2*(TICRATE/TICSPERFRAME);
int32_t demorec_diffcompress_cvar=1;
int32_t demorec_synccompress_cvar=1;
int32_t demorec_seeds_cvar=1, demoplay_showsync=1;
static int32_t demo_synccompress=1, demorec_seeds=1, demo_hasseeds;
int32_t g_restorePalette = 0, g_screenCapture = 0, g_noEnemies = 0;
static int32_t g_noLogoAnim = 0;
@ -144,10 +160,10 @@ static int32_t nonsharedtimer;
int32_t ticrandomseed;
static void G_DrawCameraText(int16_t i);
static inline int32_t G_MoveLoop(void);
GAME_STATIC GAME_INLINE int32_t G_MoveLoop(void);
static void G_DoOrderScreen(void);
static int32_t G_DoMoveThings(void);
static int32_t G_PlaybackDemo(void);
GAME_STATIC int32_t G_DoMoveThings(void);
GAME_STATIC int32_t G_PlaybackDemo(void);
static char recbuf[180];
@ -8450,7 +8466,7 @@ void G_CheatGetInv(void)
int8_t cheatbuf[MAXCHEATLEN],cheatbuflen;
static void G_DoCheats(void)
GAME_STATIC void G_DoCheats(void)
{
int32_t ch, i, j, k=0, weapon;
static int32_t z=0;
@ -8957,7 +8973,19 @@ static void G_ShowScores(void)
#undef SCORESHEETOFFSET
static void G_HandleLocalKeys(void)
static void demo_preparewarp()
{
if (!g_demo_paused)
{
g_demo_soundToggle = ud.config.SoundToggle;
ud.config.SoundToggle = 0;
}
FX_StopAllSounds();
S_ClearSoundLocks();
}
GAME_STATIC void G_HandleLocalKeys(void)
{
int32_t i,ch;
int32_t j;
@ -9078,12 +9106,35 @@ static void G_HandleLocalKeys(void)
P_DoQuote(83+ud.scrollmode,g_player[myconnectindex].ps);
}
if (KB_UnBoundKeyPressed(sc_ScrollLock))
{
KB_ClearKeyDown(sc_ScrollLock);
switch (ud.recstat)
{
case 0:
G_OpenDemoWrite();
break;
case 1:
G_CloseDemoWrite();
break;
}
}
if (ud.recstat == 2)
{
if (KB_KeyPressed(sc_Space))
{
KB_ClearKeyDown(sc_Space);
g_demo_paused = !g_demo_paused;
g_demo_rewind = 0;
if (g_demo_paused)
{
FX_StopAllSounds();
S_ClearSoundLocks();
}
}
if (KB_KeyPressed(sc_Tab))
@ -9092,6 +9143,7 @@ static void G_HandleLocalKeys(void)
g_demo_showStats = !g_demo_showStats;
}
#if 0
if (KB_KeyPressed(sc_kpad_Plus))
{
if (g_timerTicsPerSecond != 240)
@ -9116,44 +9168,31 @@ static void G_HandleLocalKeys(void)
inittimer(120);
g_timerTicsPerSecond = 120;
}
#endif
if (KB_KeyPressed(sc_kpad_6))
{
KB_ClearKeyDown(sc_kpad_6);
j = ALT_IS_PRESSED ? 30 : 10;
g_demo_goalCnt = g_demo_paused ? ud.reccnt-ud.multimode : ud.reccnt-(TICRATE/TICSPERFRAME)*ud.multimode*j;
g_demo_soundToggle = ud.config.SoundToggle;
j = (15<<ALT_IS_PRESSED)<<(2*SHIFTS_IS_PRESSED);
g_demo_goalCnt = g_demo_paused ? g_demo_cnt+1 : g_demo_cnt+(TICRATE/TICSPERFRAME)*j;
g_demo_rewind = 0;
// j=(g_demo_startCnt-ud.reccnt)/(ud.multimode*(TICRATE/TICSPERFRAME));
// OSD_Printf(" FF %d s from %02d:%02d\n", ALT_IS_PRESSED ? 30 : 10, j/60, j%60);
if (g_demo_goalCnt <= 0)
if (g_demo_goalCnt > g_demo_totalCnt)
g_demo_goalCnt = 0;
else
{
ud.config.SoundToggle = 0;
FX_StopAllSounds();
S_ClearSoundLocks();
}
demo_preparewarp();
}
else if (KB_KeyPressed(sc_kpad_4))
{
KB_ClearKeyDown(sc_kpad_4);
j = ALT_IS_PRESSED ? 30 : 10;
g_demo_goalCnt = g_demo_paused ? ud.reccnt+ud.multimode : ud.reccnt+(TICRATE/TICSPERFRAME)*ud.multimode*j;
g_demo_soundToggle = ud.config.SoundToggle;
j = (15<<ALT_IS_PRESSED)<<(2*SHIFTS_IS_PRESSED);
g_demo_goalCnt = g_demo_paused ? g_demo_cnt-1 : g_demo_cnt-(TICRATE/TICSPERFRAME)*j;
g_demo_rewind = 1;
// j=(g_demo_startCnt-ud.reccnt)/(ud.multimode*TICRATE/TICSPERFRAME);
// OSD_Printf(" RW %d s from %02d:%02d\n", ALT_IS_PRESSED ? 30 : 10, j/60, j%60);
if (g_demo_goalCnt <= 0)
g_demo_goalCnt = 1;
if (g_demo_goalCnt > g_demo_startCnt)
g_demo_goalCnt = g_demo_startCnt;
g_demo_goalCnt = -g_demo_goalCnt;
ud.config.SoundToggle = 0;
FX_StopAllSounds();
S_ClearSoundLocks();
demo_preparewarp();
}
#if 0
@ -9163,11 +9202,11 @@ static void G_HandleLocalKeys(void)
KB_ClearKeyDown(sc_Return);
ud.reccnt = 0;
ud.recstat = 0;
// kclose(recfilep);
kclose(g_demo_recFilePtr);
g_player[myconnectindex].ps->gm = MODE_GAME;
ready2send=0;
// ready2send=0;
screenpeek=myconnectindex;
demo_paused=0;
// g_demo_paused=0;
}
#endif
}
@ -11947,22 +11986,19 @@ MAIN_LOOP_RESTART:
G_GameExit(" ");
}
static int32_t demo_version;
extern int32_t sv_loadsnapshot(int32_t fil, int32_t *ret_hasdiffs, int32_t *ret_demoticcnt, int32_t *ret_synccompress);
static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
GAME_STATIC int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
{
char d[13];
char ver;
char d[14];
int32_t i;
Bstrcpy(d, "demo_.dmo");
Bstrcpy(d, "edemo_.edm");
if (g_whichDemo == 10)
d[4] = 'x';
d[5] = 'x';
else
d[4] = '0' + g_whichDemo;
ud.reccnt = 0;
d[5] = '0' + g_whichDemo;
if (g_whichDemo == 1 && firstdemofile[0] != 0)
{
@ -11970,192 +12006,257 @@ static int32_t G_OpenDemoRead(int32_t g_whichDemo) // 0 = mine
}
else if ((g_demo_recFilePtr = kopen4loadfrommod(d,g_loadFromGroupOnly)) == -1) return(0);
if (kread(g_demo_recFilePtr,&ud.reccnt,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
if (kread(g_demo_recFilePtr,&ver,sizeof(uint8_t)) != sizeof(uint8_t)) goto corrupt;
if (ver != BYTEVERSION /*&& ver != 116 && ver != 117*/)
i=sv_loadsnapshot(g_demo_recFilePtr, &demo_hasdiffs, &g_demo_totalCnt, &demo_synccompress);
if (i==0)
{
/* old demo playback */
if (ver == BYTEVERSION_JF) initprintf("Demo %s is for Regular edition.\n", d);
else if (ver == BYTEVERSION_JF+1) initprintf("Demo %s is for Atomic edition.\n", d);
else if (ver == BYTEVERSION_JF+2) initprintf("Demo %s is for Shareware version.\n", d);
// else OSD_Printf("Demo %s is of an incompatible version (%d).\n", d, ver);
kclose(g_demo_recFilePtr);
ud.reccnt=0;
demo_version = 0;
return 0;
}
else
{
demo_version = ver;
OSD_Printf("Demo %s is of version %d.\n", d, ver);
}
demo_hasseeds = demo_synccompress&2;
demo_synccompress &= 1;
if (kread(g_demo_recFilePtr,(char *)&ud.volume_number,sizeof(uint8_t)) != sizeof(uint8_t)) goto corrupt;
OSD_Printf("ud.volume_number: %d\n",ud.volume_number);
if (kread(g_demo_recFilePtr,(char *)&ud.level_number,sizeof(uint8_t)) != sizeof(uint8_t)) goto corrupt;
OSD_Printf("ud.level_number: %d\n",ud.level_number);
if (kread(g_demo_recFilePtr,(char *)&ud.player_skill,sizeof(uint8_t)) != sizeof(uint8_t)) goto corrupt;
OSD_Printf("ud.player_skill: %d\n",ud.player_skill);
if (kread(g_demo_recFilePtr,(char *)&ud.m_coop,sizeof(uint8_t)) != sizeof(uint8_t)) goto corrupt;
OSD_Printf("ud.m_coop: %d\n",ud.m_coop);
if (kread(g_demo_recFilePtr,(char *)&ud.m_ffire,sizeof(uint8_t)) != sizeof(uint8_t)) goto corrupt;
OSD_Printf("ud.m_ffire: %d\n",ud.m_ffire);
if (kread(g_demo_recFilePtr,(int16_t *)&ud.multimode,sizeof(int16_t)) != sizeof(int16_t)) goto corrupt;
OSD_Printf("ud.multimode: %d\n",ud.multimode);
if (kread(g_demo_recFilePtr,(int16_t *)&ud.m_monsters_off,sizeof(int16_t)) != sizeof(int16_t)) goto corrupt;
OSD_Printf("ud.m_monsters_off: %d\n",ud.m_monsters_off);
if (kread(g_demo_recFilePtr,(int32_t *)&ud.m_respawn_monsters,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
OSD_Printf("ud.m_respawn_monsters: %d\n",ud.m_respawn_monsters);
if (kread(g_demo_recFilePtr,(int32_t *)&ud.m_respawn_items,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
OSD_Printf("ud.m_respawn_items: %d\n",ud.m_respawn_items);
if (kread(g_demo_recFilePtr,(int32_t *)&ud.m_respawn_inventory,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
OSD_Printf("ud.m_respawn_inventory: %d\n",ud.m_respawn_inventory);
if (kread(g_demo_recFilePtr,(int32_t *)&ud.playerai,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
OSD_Printf("ud.playerai: %d\n",ud.playerai);
if (kread(g_demo_recFilePtr,(int32_t *)&i,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
if (kread(g_demo_recFilePtr,(char *)boardfilename,sizeof(boardfilename)) != sizeof(boardfilename)) goto corrupt;
if (boardfilename[0] != 0)
{
ud.m_level_number = 7;
ud.m_volume_number = 0;
}
if (kread(g_demo_recFilePtr,(int32_t *)&ud.m_noexits,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
for (i=0; i<ud.multimode; i++)
{
if (!g_player[i].ps)
g_player[i].ps = (DukePlayer_t *) Bcalloc(1,sizeof(DukePlayer_t));
if (!g_player[i].sync)
g_player[i].sync = (input_t *) Bcalloc(1,sizeof(input_t));
if (kread(g_demo_recFilePtr,(char *)g_player[i].user_name,sizeof(g_player[i].user_name)) != sizeof(g_player[i].user_name)) goto corrupt;
OSD_Printf("ud.user_name: %s\n",g_player[i].user_name);
if (kread(g_demo_recFilePtr,(int32_t *)&g_player[i].ps->aim_mode,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
if (kread(g_demo_recFilePtr,(int32_t *)&g_player[i].ps->auto_aim,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt; // JBF 20031126
if (kread(g_demo_recFilePtr,(int32_t *)&g_player[i].ps->weaponswitch,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
if (kread(g_demo_recFilePtr,(int32_t *)&g_player[i].pcolor,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
g_player[i].ps->palookup = g_player[i].pcolor;
if (kread(g_demo_recFilePtr,(int32_t *)&g_player[i].pteam,sizeof(int32_t)) != sizeof(int32_t)) goto corrupt;
g_player[i].ps->team = g_player[i].pteam;
}
i = ud.reccnt/((TICRATE/TICSPERFRAME)*ud.multimode);
i = g_demo_totalCnt/(TICRATE/TICSPERFRAME);
OSD_Printf("demo duration: %d min %d sec\n", i/60, i%60);
g_demo_startCnt = ud.reccnt;
g_demo_cnt=1;
ud.reccnt = 0;
ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
ud.clipping = ud.scrollmode = ud.overhead_on = ud.pause_on = 0;
G_NewGame(ud.volume_number,ud.level_number,ud.player_skill);
return(1);
// G_NewGame(ud.volume_number,ud.level_number,ud.player_skill);
// G_ResetTimers();
totalclock = ototalclock = lockclock = 0;
return 1;
}
else
{
OSD_Printf(OSD_ERROR "There were errors opening demo %d (code: %d).\n", g_whichDemo, i);
kclose(g_demo_recFilePtr);
return 0;
}
#if 0
corrupt:
OSD_Printf(OSD_ERROR "Demo %d header is corrupt.\n",g_whichDemo);
ud.reccnt = 0;
kclose(g_demo_recFilePtr);
return 0;
#endif
}
#if KRANDDEBUG
extern int32_t krd_enable();
extern int32_t krd_print(const char *filename);
#endif
void G_OpenDemoWrite(void)
{
char d[13];
int32_t dummylong = 0, demonum=1;
char ver;
int16_t i;
char d[14];
int32_t i, demonum=1;
extern int32_t sv_saveandmakesnapshot(FILE* fil, int32_t recdiffs, int32_t diffcompress, int32_t synccompress);
if (ud.recstat == 2) kclose(g_demo_recFilePtr);
ver = BYTEVERSION;
if ((g_player[myconnectindex].ps->gm&MODE_GAME) && g_player[myconnectindex].ps->dead_flag)
{
Bstrcpy(ScriptQuotes[122], "CANNOT START DEMO RECORDING WHEN DEAD!");
P_DoQuote(122, g_player[myconnectindex].ps);
ud.recstat = 0;
return;
}
if (demorec_diffs_cvar && !demorec_force_cvar)
for (i=1; i<g_scriptSize; i++)
{
intptr_t w=script[i];
if ((w&0x0fff)==CON_RESIZEARRAY && (w>>12) && i<g_scriptSize-2 &&
script[i+1]>=0 && script[i+1]<g_gameArrayCount)
{
OSD_Printf("\nThe CON code possibly contains a RESIZEARRAY command.\n");
OSD_Printf("Gamearrays that change their size during the game are unsupported by\n");
OSD_Printf("the demo recording system. If you are sure that the code doesn't\n");
OSD_Printf("contain a RESIZEARRAY command, you can force recording with the\n");
OSD_Printf("`demorec_force' cvar. Alternatively, you can disable diff recording\n");
OSD_Printf("with the `demorec_diffs' cvar.\n\n");
Bstrcpy(ScriptQuotes[122], "FAILED STARTING DEMO RECORDING. SEE OSD FOR DETAILS.");
P_DoQuote(122, g_player[myconnectindex].ps);
ud.recstat = 0;
return;
}
}
while (1)
{
if (demonum == 10000) return;
Bsprintf(d, "demo%d.dmo", demonum++);
Bsprintf(d, "edemo%d.edm", demonum++);
g_demo_filePtr = fopen(d, "rb");
if (g_demo_filePtr == NULL) break;
Bfclose(g_demo_filePtr);
}
if ((g_demo_filePtr = fopen(d,"wb")) == NULL) return;
fwrite(&dummylong,sizeof(dummylong),1,g_demo_filePtr);
fwrite(&ver,sizeof(uint8_t),1,g_demo_filePtr);
fwrite((char *)&ud.volume_number,sizeof(uint8_t),1,g_demo_filePtr);
fwrite((char *)&ud.level_number,sizeof(uint8_t),1,g_demo_filePtr);
fwrite((char *)&ud.player_skill,sizeof(uint8_t),1,g_demo_filePtr);
fwrite((char *)&ud.m_coop,sizeof(uint8_t),1,g_demo_filePtr);
fwrite((char *)&ud.m_ffire,sizeof(uint8_t),1,g_demo_filePtr);
fwrite((int16_t *)&ud.multimode,sizeof(int16_t),1,g_demo_filePtr);
fwrite((int16_t *)&ud.m_monsters_off,sizeof(int16_t),1,g_demo_filePtr);
fwrite((int32_t *)&ud.m_respawn_monsters,sizeof(int32_t),1,g_demo_filePtr);
fwrite((int32_t *)&ud.m_respawn_items,sizeof(int32_t),1,g_demo_filePtr);
fwrite((int32_t *)&ud.m_respawn_inventory,sizeof(int32_t),1,g_demo_filePtr);
fwrite((int32_t *)&ud.playerai,sizeof(int32_t),1,g_demo_filePtr);
fwrite((int32_t *)&ud.auto_run,sizeof(int32_t),1,g_demo_filePtr);
fwrite((char *)boardfilename,sizeof(boardfilename),1,g_demo_filePtr);
fwrite((int32_t *)&ud.m_noexits,sizeof(int32_t),1,g_demo_filePtr);
for (i=0; i<ud.multimode; i++)
i=sv_saveandmakesnapshot(g_demo_filePtr, demorec_diffs_cvar, demorec_diffcompress_cvar,
demorec_synccompress_cvar|(demorec_seeds_cvar<<1));
if (i)
{
fwrite((char *)&g_player[i].user_name,sizeof(g_player[i].user_name),1,g_demo_filePtr);
fwrite((int32_t *)&g_player[i].ps->aim_mode,sizeof(int32_t),1,g_demo_filePtr);
fwrite((int32_t *)&g_player[i].ps->auto_aim,sizeof(int32_t),1,g_demo_filePtr); // JBF 20031126
fwrite(&g_player[i].ps->weaponswitch,sizeof(int32_t),1,g_demo_filePtr);
fwrite(&g_player[i].pcolor,sizeof(int32_t),1,g_demo_filePtr);
fwrite(&g_player[i].pteam,sizeof(int32_t),1,g_demo_filePtr);
Bstrcpy(ScriptQuotes[122], "FAILED STARTING DEMO RECORDING. SEE OSD FOR DETAILS.");
P_DoQuote(122, g_player[myconnectindex].ps);
Bfclose(g_demo_filePtr), g_demo_filePtr=NULL;
ud.recstat = 0;
return;
}
demorec_seeds = demorec_seeds_cvar;
demorec_diffs = demorec_diffs_cvar;
demo_synccompress = demorec_synccompress_cvar;
demorec_difftics = demorec_difftics_cvar;
g_demo_totalCnt = 0;
Bstrcpy(ScriptQuotes[122], "DEMO RECORDING STARTED");
P_DoQuote(122, g_player[myconnectindex].ps);
ud.reccnt = 0;
ud.recstat = 1; //
#if KRANDDEBUG
krd_enable();
#endif
g_demo_cnt = 1;
}
static uint8_t g_demo_seedbuf[RECSYNCBUFSIZ];
static void dowritesync()
{
int16_t tmpreccnt;
fwrite("sYnC", 4, 1, g_demo_filePtr);
tmpreccnt = (int16_t)ud.reccnt;
fwrite(&tmpreccnt, sizeof(int16_t), 1, g_demo_filePtr);
if (demorec_seeds)
fwrite(g_demo_seedbuf, 1, ud.reccnt, g_demo_filePtr);
if (demo_synccompress)
dfwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr);
else //if (demo_synccompress==0)
fwrite(recsync, sizeof(input_t), ud.reccnt, g_demo_filePtr);
ud.reccnt = 0;
}
static void G_DemoRecord(void)
{
int16_t i;
extern uint32_t sv_writediff(FILE *fil);
g_demo_cnt++;
if (demorec_diffs && (g_demo_cnt%demorec_difftics == 1))
{
sv_writediff(g_demo_filePtr);
demorec_difftics = demorec_difftics_cvar;
}
if (demorec_seeds)
g_demo_seedbuf[ud.reccnt] = (uint8_t)(randomseed>>24);
TRAVERSE_CONNECT(i)
{
copybufbyte(g_player[i].sync,&recsync[ud.reccnt],sizeof(input_t));
Bmemcpy(&recsync[ud.reccnt], g_player[i].sync, sizeof(input_t));
ud.reccnt++;
g_demo_totalCnt++;
if (ud.reccnt >= RECSYNCBUFSIZ)
{
dfwrite(recsync,sizeof(input_t)*ud.multimode,ud.reccnt/ud.multimode,g_demo_filePtr);
ud.reccnt = 0;
}
}
if (ud.reccnt > RECSYNCBUFSIZ-MAXPLAYERS || (demorec_diffs && (g_demo_cnt%demorec_difftics == 0)))
dowritesync();
}
void G_CloseDemoWrite(void)
{
extern void sv_freemem();
if (ud.recstat == 1)
{
if (ud.reccnt > 0)
{
dfwrite(recsync,sizeof(input_t)*ud.multimode,ud.reccnt/ud.multimode,g_demo_filePtr);
dowritesync();
fwrite("EnD!", 4, 1, g_demo_filePtr);
if (fseek(g_demo_filePtr, 20, SEEK_SET))
perror("G_CloseDemoWrite: fseek");
else
fwrite(&g_demo_cnt, sizeof(g_demo_cnt), 1, g_demo_filePtr);
fseek(g_demo_filePtr,SEEK_SET,0L);
fwrite(&g_demo_totalCnt,sizeof(int32_t),1,g_demo_filePtr);
ud.recstat = ud.m_recstat = 0;
}
fclose(g_demo_filePtr);
sv_freemem();
Bstrcpy(ScriptQuotes[122], "DEMO RECORDING STOPPED");
P_DoQuote(122, g_player[myconnectindex].ps);
}
#if KRANDDEBUG
krd_print("krandrec.log");
#endif
}
static int32_t g_whichDemo = 1;
extern int32_t premap_quickenterlevel;
extern int32_t sv_updatestate(int32_t frominit);
static int32_t G_PlaybackDemo(void)
static void dorestoremodes(int32_t menu)
{
int32_t i,j,k,l;
int32_t foundemo = 0;
if (menu) g_player[myconnectindex].ps->gm |= MODE_MENU;
else g_player[myconnectindex].ps->gm &= ~MODE_MENU;
g_player[myconnectindex].ps->gm &= ~MODE_GAME;
g_player[myconnectindex].ps->gm |= MODE_DEMO;
}
static int32_t doupdatestate(int32_t frominit)
{
int32_t j,k;
j = g_player[myconnectindex].ps->gm&MODE_MENU;
k = sv_updatestate(frominit);
// tmpdifftime = g_demo_cnt+12;
dorestoremodes(j);
if (k) OSD_Printf("sv_updatestate() returned %d.\n", k);
return k;
}
#define CORRUPT(code) do { corruptcode=code; goto corrupt; } while(0)
#define DOREADSYNC(code) do \
{ \
uint16_t si; \
int32_t i; \
if (kread(g_demo_recFilePtr, &si, sizeof(uint16_t)) != (int32_t)sizeof(uint16_t)) CORRUPT(code); \
i = si; \
if (demo_hasseeds) \
{ \
if (kread(g_demo_recFilePtr, g_demo_seedbuf, i) != i) CORRUPT(code); \
} \
if (demo_synccompress) \
{ \
if (kdfread(recsync, sizeof(input_t), i, g_demo_recFilePtr) != i) CORRUPT(code+1); \
} \
else \
if (kread(g_demo_recFilePtr, recsync, sizeof(input_t)*i) != (int32_t)sizeof(input_t)*i) CORRUPT(code+2); \
ud.reccnt = i; \
} while (0)
GAME_STATIC int32_t G_PlaybackDemo(void)
{
int32_t bigi, j, k, initsyncofs, lastsyncofs, lastsynctic, lastsyncclock;
int32_t foundemo = 0, corruptcode, outofsync=0;
static int32_t in_menu = 0;
// static int32_t tmpdifftime=0;
if (ready2send) return 0;
RECHECK:
#if KRANDDEBUG
if (foundemo)
krd_print("krandplay.log");
#endif
in_menu = g_player[myconnectindex].ps->gm&MODE_MENU;
pub = NUMPAGES;
@ -12168,7 +12269,6 @@ RECHECK:
if (g_whichDemo > 1)
{
g_whichDemo = 1;
premap_quickenterlevel=0;
goto RECHECK;
}
fadepal(0,0,0, 0,63,7);
@ -12186,89 +12286,200 @@ RECHECK:
g_whichDemo++;
if (g_whichDemo == 10) g_whichDemo = 1;
if (G_EnterLevel(MODE_DEMO)) ud.recstat = foundemo = 0;
g_player[myconnectindex].ps->gm &= ~MODE_GAME;
g_player[myconnectindex].ps->gm |= MODE_DEMO;
// if (G_EnterLevel(MODE_DEMO))
// {
// OSD_Printf("G_PlaybackDemo: G_EnterLevel\n");
// ud.recstat = foundemo = 0;
// }
//
lastsyncofs = ktell(g_demo_recFilePtr);
initsyncofs = lastsyncofs;
lastsynctic = g_demo_cnt;
lastsyncclock = totalclock;
outofsync = 0;
#if KRANDDEBUG
krd_enable();
#endif
}
if (!premap_quickenterlevel)
{
if (foundemo == 0 || in_menu || KB_KeyWaiting() || numplayers > 1)
{
FX_StopAllSounds();
S_ClearSoundLocks();
g_player[myconnectindex].ps->gm |= MODE_MENU;
}
}
ready2send = 0;
i = 0;
bigi = 0;
KB_FlushKeyboardQueue();
k = 0;
// OSD_Printf("ticcnt=%d, total=%d\n", g_demo_cnt, g_demo_totalCnt);
while (g_demo_cnt < g_demo_totalCnt || foundemo==0)
{
if (foundemo && (!g_demo_paused || g_demo_goalCnt))
{
static int32_t t1=0;
if (t1==0 && g_demo_goalCnt)
t1=getticks();
while (ud.reccnt > 0 || foundemo == 0)
if (g_demo_goalCnt>0 && g_demo_goalCnt < g_demo_cnt) // rewind
{
if (foundemo && (!g_demo_paused || g_demo_goalCnt!=0))
k = g_player[myconnectindex].ps->gm&MODE_MENU;
if (g_demo_goalCnt > lastsynctic)
{
if (g_demo_goalCnt < 0)
if (doupdatestate(0)==0)
{
g_demo_goalCnt = -g_demo_goalCnt;
if (g_whichDemo > 1) // load the same demo again and FF from beginning... yay!
g_whichDemo--;
foundemo = 0;
g_demo_cnt = lastsynctic;
klseek(g_demo_recFilePtr, lastsyncofs, SEEK_SET);
ud.reccnt = 0;
kclose(g_demo_recFilePtr);
premap_quickenterlevel=1;
goto RECHECK;
totalclock = ototalclock = lockclock = lastsyncclock;
}
else CORRUPT(-1);
}
else
{
//loadfrombeg:
// j = sv_loadsnapshot(g_demo_recFilePtr, &g_demo_totalCnt);
j = doupdatestate(1);
if (!j)
{
klseek(g_demo_recFilePtr, initsyncofs, SEEK_SET);
g_levelTextTime = 0;
g_demo_cnt = 1;
ud.reccnt = 0;
ud.god = ud.cashman = ud.eog = ud.showallmap = 0;
ud.clipping = ud.scrollmode = ud.overhead_on = ud.pause_on = 0;
totalclock = ototalclock = lockclock = 0;
}
else CORRUPT(0);
}
dorestoremodes(k);
}
while (totalclock >= (lockclock+TICSPERFRAME)
|| (ud.reccnt > (TICRATE/TICSPERFRAME)*2 && ud.pause_on)
|| (g_demo_goalCnt>0 && g_demo_goalCnt<ud.reccnt))
// || (ud.reccnt > (TICRATE/TICSPERFRAME)*2 && ud.pause_on)
|| (g_demo_goalCnt>0 && g_demo_cnt<g_demo_goalCnt))
{
if ((i == 0) || (i >= RECSYNCBUFSIZ))
if (ud.reccnt<=0)
{
i = 0;
l = min(ud.reccnt,RECSYNCBUFSIZ);
if (kdfread(recsync,sizeof(input_t)*ud.multimode,l/ud.multimode,g_demo_recFilePtr) != l/ud.multimode)
char tmpbuf[4];
if (ud.reccnt<0)
{
OSD_Printf(OSD_ERROR "Demo %d is corrupt.\n", g_whichDemo-1);
OSD_Printf("G_PlaybackDemo: ud.reccnt<0!\n");
CORRUPT(1);
}
bigi = 0;
//reread:
if (kread(g_demo_recFilePtr, tmpbuf, 4) != 4) CORRUPT(2);
if (Bmemcmp(tmpbuf, "sYnC", 4)==0)
DOREADSYNC(3);
else if (demo_hasdiffs && Bmemcmp(tmpbuf, "dIfF", 4)==0)
{
extern int32_t sv_readdiff(int32_t fil);
k=sv_readdiff(g_demo_recFilePtr);
if (k)
{
OSD_Printf("sv_readdiff() returned %d.\n", k);
CORRUPT(6);
}
else
{
lastsyncofs = ktell(g_demo_recFilePtr);
lastsynctic = g_demo_cnt;
lastsyncclock = totalclock;
if (kread(g_demo_recFilePtr, tmpbuf, 4) != 4) CORRUPT(7);
if (Bmemcmp(tmpbuf, "sYnC", 4)) CORRUPT(8);
DOREADSYNC(9);
if ((g_demo_goalCnt==0 && demoplay_diffs) ||
(g_demo_goalCnt>0 && ud.reccnt/ud.multimode >= g_demo_goalCnt-g_demo_cnt))
{
doupdatestate(0);
}
}
}
else if (Bmemcmp(tmpbuf, "EnD!", 4)==0)
goto nextdemo;
else CORRUPT(12);
if (demo_hasseeds)
outofsync = (uint16_t)(randomseed>>24) != g_demo_seedbuf[bigi];
if (0)
{
corrupt:
OSD_Printf(OSD_ERROR "Demo %d is corrupt (code %d).\n", g_whichDemo-1, corruptcode);
nextdemo:
foundemo = 0;
ud.reccnt = 0;
kclose(g_demo_recFilePtr);
g_player[myconnectindex].ps->gm |= MODE_MENU;
if (g_demo_goalCnt>0)
{
g_demo_goalCnt=0;
ud.config.SoundToggle = g_demo_soundToggle;
}
goto RECHECK;
}
}
TRAVERSE_CONNECT(j)
{
copybufbyte(&recsync[i],&inputfifo[0][j],sizeof(input_t));
copybufbyte(&recsync[bigi], &inputfifo[0][j], sizeof(input_t));
g_player[j].movefifoend++;
i++;
bigi++;
ud.reccnt--;
}
g_demo_cnt++;
if (!g_demo_paused)
{
// assumption that ud.multimode doesn't change in a demo may not be true
// sometime in the future v v v v v v v v v
if (g_demo_goalCnt==0 || !demo_hasdiffs || ud.reccnt/ud.multimode>=g_demo_goalCnt-g_demo_cnt)
G_DoMoveThings(); // increases lockclock by TICSPERFRAME
else
lockclock += TICSPERFRAME;
}
else
{
k = ud.config.SoundToggle;
ud.config.SoundToggle = 0;
G_DoMoveThings();
ud.config.SoundToggle = k;
}
ototalclock += TICSPERFRAME;
if (g_demo_goalCnt > 0)
{
if (g_demo_goalCnt<ud.reccnt || (ud.reccnt > (TICRATE/TICSPERFRAME)*2 && ud.pause_on))
totalclock += TICSPERFRAME;
}
}
if (g_demo_goalCnt > 0 && ud.reccnt<=g_demo_goalCnt)
// OSD_Printf("t:%d, l+T:%d; cnt:%d, goal:%d%s", totalclock, (lockclock+TICSPERFRAME),
// g_demo_cnt, g_demo_goalCnt, g_demo_cnt>=g_demo_goalCnt?" ":"\n");
if (g_demo_cnt>=g_demo_goalCnt)
{
g_demo_goalCnt = 0;
ud.config.SoundToggle = g_demo_soundToggle;
premap_quickenterlevel = 0;
}
}
else if (foundemo && g_demo_paused && g_demo_goalCnt==0)
}
}
else if (foundemo && g_demo_paused)
{
lockclock = ototalclock = totalclock;
totalclock = lockclock;
}
if (foundemo == 0)
@ -12278,13 +12489,30 @@ RECHECK:
G_HandleLocalKeys();
// j = min(max((totalclock-lockclock)*(65536/TICSPERFRAME),0),65536);
j = min(max((totalclock - ototalclock) * (65536 / 4),0),65536);
if (g_demo_paused && g_demo_rewind)
j = 65536-j;
G_DrawRooms(screenpeek,j);
G_DisplayRest(j);
if (g_demo_showStats && (g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
if ((g_player[myconnectindex].ps->gm&MODE_MENU) == 0)
{
j=(g_demo_startCnt-ud.reccnt)/(TICRATE/TICSPERFRAME);
if (demoplay_showsync && outofsync)
gametext(160,100,"OUT OF SYNC",0,2+8+16);
if (g_demo_showStats)
{
// if (g_demo_cnt<tmpdifftime)
// gametext(160,100,"DIFF",0,2+8+16);
// {
// char buf[32];
// Bsprintf(buf, "RC:%4d TC:%5d", ud.reccnt, g_demo_cnt);
// gametext(160,100,buf,0,2+8+16);
// }
j=g_demo_cnt/(TICRATE/TICSPERFRAME);
Bsprintf(buf, "%02d:%02d", j/60, j%60);
gametext(18,16,buf,0,2+8+16);
@ -12293,13 +12521,14 @@ RECHECK:
rotatesprite(120<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16,(xdim*125)/320,0,(xdim*155)/320,ydim-1);
rotatesprite(150<<16,16<<16,32768,0,SLIDEBAR,0,0,2+8+16,(xdim*155)/320,0,xdim-1,ydim-1);
j = (182<<16) - ((((120*ud.reccnt)<<4)/g_demo_startCnt)<<12);
j = (182<<16) - ((((120*(g_demo_totalCnt-g_demo_cnt))<<4)/g_demo_totalCnt)<<12);
rotatesprite(j,(16<<16)+(1<<15),32768,0,SLIDEBAR+1,0,0,2+8+16,0,0,xdim-1,ydim-1);
j=ud.reccnt/(TICRATE/TICSPERFRAME);
j=(g_demo_totalCnt-g_demo_cnt)/(TICRATE/TICSPERFRAME);
Bsprintf(buf, "-%02d:%02d%s", j/60, j%60, g_demo_paused?" ^15PAUSED":"");
gametext(194,16,buf,0,2+8+16);
}
}
if ((g_netServer || ud.multimode > 1) && g_player[myconnectindex].ps->gm)
Net_GetPackets();
@ -12388,10 +12617,13 @@ RECHECK:
#endif
if (g_player[myconnectindex].ps->gm&MODE_MENU) goto RECHECK;
#if KRANDDEBUG
krd_print("krandplay.log");
#endif
return 1;
}
static inline int32_t G_MoveLoop()
GAME_STATIC GAME_INLINE int32_t G_MoveLoop()
{
/*
if (numplayers > 1)
@ -12412,7 +12644,7 @@ static inline int32_t G_MoveLoop()
return 0;
}
static int32_t G_DoMoveThings(void)
GAME_STATIC int32_t G_DoMoveThings(void)
{
int32_t i, j;
// char ch;

View file

@ -32,6 +32,14 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "osdcmds.h"
#include "osd.h"
#if KRANDDEBUG
# define GAMEEXEC_INLINE
# define GAMEEXEC_STATIC
#else
# define GAMEEXEC_INLINE inline
# define GAMEEXEC_STATIC static
#endif
void G_RestoreMapState(mapstate_t *save);
void G_SaveMapState(mapstate_t *save);
@ -41,7 +49,7 @@ int32_t g_errorLineNum;
int32_t g_tw;
extern int32_t ticrandomseed;
static int32_t X_DoExecute(int32_t once);
GAMEEXEC_STATIC int32_t X_DoExecute(int32_t once);
#include "gamestructures.c"
@ -151,7 +159,7 @@ static int32_t A_CheckSquished(int32_t i, int32_t p)
return 0;
}
static inline void P_ForceAngle(DukePlayer_t *p)
GAMEEXEC_STATIC GAMEEXEC_INLINE void P_ForceAngle(DukePlayer_t *p)
{
int32_t n = 128-(krand()&255);
@ -161,7 +169,7 @@ static inline void P_ForceAngle(DukePlayer_t *p)
p->rotscrnang = n>>1;
}
static int32_t A_Dodge(spritetype *s)
GAMEEXEC_STATIC int32_t A_Dodge(spritetype *s)
{
int32_t bx,by,bxvect,byvect,d,i;
int32_t mx = s->x, my = s->y;
@ -382,7 +390,7 @@ int32_t G_GetAngleDelta(int32_t a,int32_t na)
return (na-a);
}
static inline void X_AlterAng(int32_t a)
GAMEEXEC_STATIC GAMEEXEC_INLINE void X_AlterAng(int32_t a)
{
intptr_t *moveptr = (intptr_t *)vm.g_t[1];
int32_t ticselapsed = (vm.g_t[0])&31;
@ -448,7 +456,7 @@ static inline void X_AlterAng(int32_t a)
}
}
static void X_Move(void)
GAMEEXEC_STATIC void X_Move(void)
{
int32_t l;
intptr_t *moveptr;
@ -647,7 +655,7 @@ static void X_Move(void)
}
}
static inline void __fastcall X_DoConditional(register int32_t condition)
GAMEEXEC_STATIC GAMEEXEC_INLINE void __fastcall X_DoConditional(register int32_t condition)
{
if (condition)
{
@ -666,7 +674,7 @@ static inline void __fastcall X_DoConditional(register int32_t condition)
}
}
static int32_t X_DoExecute(int32_t once)
GAMEEXEC_STATIC int32_t X_DoExecute(int32_t once)
{
register int32_t tw = *insptr;
@ -4776,6 +4784,23 @@ void A_Execute(int32_t iActor,int32_t iPlayer,int32_t lDist)
changespritestat(vm.g_i,STAT_ZOMBIEACTOR);
}
void G_FreeMapState2(mapstate_t *save)
{
int i;
for (i=g_gameVarCount-1; i>=0; i--)
{
if (aGameVars[i].dwFlags & GAMEVAR_NORESET) continue;
if (aGameVars[i].dwFlags & (GAMEVAR_PERPLAYER|GAMEVAR_PERACTOR))
{
if (save->vars[i])
{
Bfree(save->vars[i]);
save->vars[i]=0;
}
}
}
}
void G_SaveMapState(mapstate_t *save)
{
if (save != NULL)

View file

@ -97,11 +97,18 @@ static void Gv_Clear(void)
return;
}
int32_t Gv_ReadSave(int32_t fil)
int32_t Gv_ReadSave(int32_t fil, int32_t newbehav)
{
int32_t i, j;
intptr_t l;
char savedstate[MAXVOLUMES*MAXLEVELS];
char tbuf[12];
if (newbehav)
{
if (kread(fil, tbuf, 12)!=12) goto corrupt;
if (Bmemcmp(tbuf, "BEG: EDuke32", 12)) { OSD_Printf("BEG ERR\n"); return 2; }
}
Bmemset(&savedstate,0,sizeof(savedstate));
@ -197,10 +204,18 @@ int32_t Gv_ReadSave(int32_t fil)
}
}
if (!newbehav)
{
if (kdfread(&l,sizeof(l),1,fil) != 1) goto corrupt;
if (kdfread(g_szBuf,l,1,fil) != 1) goto corrupt;
g_szBuf[l]=0;
OSD_Printf("%s\n",g_szBuf);
}
else
{
if (kread(fil, tbuf, 12)!=12) goto corrupt;
if (Bmemcmp(tbuf, "EOF: EDuke32", 12)) { OSD_Printf("EOF ERR\n"); return 2; }
}
#if 0
{
@ -220,7 +235,7 @@ corrupt:
return(1);
}
void Gv_WriteSave(FILE *fil)
void Gv_WriteSave(FILE *fil, int32_t newbehav)
{
int32_t i, j;
intptr_t l;
@ -229,6 +244,9 @@ void Gv_WriteSave(FILE *fil)
Bmemset(&savedstate,0,sizeof(savedstate));
// AddLog("Saving Game Vars to File");
if (newbehav)
fwrite("BEG: EDuke32", 12, 1, fil);
dfwrite(&g_gameVarCount,sizeof(g_gameVarCount),1,fil);
for (i=0; i<g_gameVarCount; i++)
@ -297,10 +315,15 @@ void Gv_WriteSave(FILE *fil)
}
}
if (!newbehav)
{
Bsprintf(g_szBuf,"EOF: EDuke32");
l=Bstrlen(g_szBuf);
dfwrite(&l,sizeof(l),1,fil);
dfwrite(g_szBuf,l,1,fil);
}
else
fwrite("EOF: EDuke32", 12, 1, fil);
}
void Gv_DumpValues(void)

View file

@ -40,6 +40,8 @@ extern int32_t althud_numbertile, althud_numberpal, althud_shadows, althud_flash
extern int32_t hud_showmapname;
extern int32_t r_maxfps;
extern uint32_t g_frameDelay;
extern int32_t demorec_diffs_cvar, demorec_force_cvar, demorec_seeds_cvar, demoplay_diffs, demoplay_showsync;
extern int32_t demorec_difftics_cvar, demorec_diffcompress_cvar, demorec_synccompress_cvar;
static inline int32_t osdcmd_quit(const osdfuncparm_t *parm)
{
@ -1439,6 +1441,14 @@ int32_t registerosdcommands(void)
{ "vid_contrast","vid_contrast <gamma>: adjusts gamma ramp",(void*)&vid_contrast, CVAR_DOUBLE|CVAR_FUNCPTR, 0, 0, 10 },
{ "vid_brightness","vid_brightness <gamma>: adjusts gamma ramp",(void*)&vid_brightness, CVAR_DOUBLE|CVAR_FUNCPTR, 0, 0, 10 },
{ "demorec_diffs","demorec_diffs: enable/disable diff recording in demos",(void*)&demorec_diffs_cvar, CVAR_BOOL, 0, 0, 1 },
{ "demorec_force","demorec_force: enable/disable forced demo recording",(void*)&demorec_force_cvar, CVAR_BOOL|CVAR_NOSAVE, 0, 0, 1 },
{ "demorec_difftics","demorec_difftics <number>: sets game tic interval after which a diff is recorded",(void*)&demorec_difftics_cvar, CVAR_INT, 0, 2, 60*(TICRATE/TICSPERFRAME) },
{ "demorec_diffcompress","demorec_diffcompress <number>: Compression method for diffs. (0: none, 1: KSLZW)",(void*)&demorec_diffcompress_cvar, CVAR_INT, 0, 0, 1 },
{ "demorec_synccompress","demorec_synccompress <number>: Compression method for input. (0: none, 1: KSLZW)",(void*)&demorec_synccompress_cvar, CVAR_INT, 0, 0, 1 },
{ "demorec_seeds","demorec_seeds: enable/disable recording of random seed for later sync checking",(void*)&demorec_seeds_cvar, CVAR_BOOL, 0, 0, 1 },
{ "demoplay_diffs","demoplay_diffs: enable/disable application of diffs in demo playback",(void*)&demoplay_diffs, CVAR_BOOL, 0, 0, 1 },
{ "demoplay_showsync","demoplay_showsync: enable/disable display of sync status",(void*)&demoplay_showsync, CVAR_BOOL, 0, 0, 1 },
};
osdcmd_cheatsinfo_stat.cheatnum = -1;

View file

@ -1271,16 +1271,12 @@ static inline void prelevel(char g)
}
}
int32_t premap_quickenterlevel=0;
void G_NewGame(int32_t vn,int32_t ln,int32_t sk)
{
DukePlayer_t *p = g_player[0].ps;
int32_t i;
if (premap_quickenterlevel)
goto quick;
handleevents();
Net_GetPackets();
@ -1321,7 +1317,6 @@ void G_NewGame(int32_t vn,int32_t ln,int32_t sk)
FX_StopAllSounds();
}
quick:
g_showShareware = GAMETICSPERSEC*34;
ud.level_number = ln;
@ -1729,15 +1724,12 @@ int32_t G_EnterLevel(int32_t g)
}
}
if (!premap_quickenterlevel)
{
i = ud.screen_size;
ud.screen_size = 0;
G_DoLoadScreen(NULL, -1);
G_UpdateScreenArea();
ud.screen_size = i;
}
if (boardfilename[0] != 0 && ud.m_level_number == 7 && ud.m_volume_number == 0)
{
@ -1875,12 +1867,10 @@ int32_t G_EnterLevel(int32_t g)
}
}
if (!premap_quickenterlevel)
{
g_precacheCount = 0;
clearbufbyte(gotpic,sizeof(gotpic),0L);
clearbufbyte(precachehightile, sizeof(precachehightile), 0l);
}
//clearbufbyte(ActorExtra,sizeof(ActorExtra),0l); // JBF 20040531: yes? no?
prelevel(g);
@ -1891,7 +1881,6 @@ int32_t G_EnterLevel(int32_t g)
cachedebug = 0;
automapping = 0;
if (!premap_quickenterlevel)
G_CacheMapData();
if (ud.recstat != 2)
@ -1942,13 +1931,10 @@ int32_t G_EnterLevel(int32_t g)
//g_player[myconnectindex].ps->palette = palette;
//G_FadePalette(0,0,0,0);
if (!premap_quickenterlevel)
{
P_SetGamePalette(g_player[myconnectindex].ps, palette, 0); // JBF 20040308
P_UpdateScreenPal(g_player[myconnectindex].ps);
flushperms();
}
everyothertime = 0;
g_globalRandom = 0;
@ -1961,8 +1947,6 @@ int32_t G_EnterLevel(int32_t g)
g_restorePalette = 1;
if (!premap_quickenterlevel)
{
Net_WaitForServer();
// mmulti_flushpackets();
@ -1971,7 +1955,6 @@ int32_t G_EnterLevel(int32_t g)
clearview(0L);
G_DrawBackground();
G_DrawRooms(myconnectindex,65536);
}
g_player[myconnectindex].ps->over_shoulder_on = 0;
@ -1985,7 +1968,6 @@ int32_t G_EnterLevel(int32_t g)
Bmemcpy(&currentboardfilename[0],&boardfilename[0],BMAX_PATH);
X_OnEvent(EVENT_ENTERLEVEL, -1, -1, -1);
if (!premap_quickenterlevel)
OSD_Printf(OSDTEXT_YELLOW "E%dL%d: %s\n",ud.volume_number+1,ud.level_number+1,MapInfo[(ud.volume_number*MAXLEVELS)+ud.level_number].name);
return 0;
}

File diff suppressed because it is too large Load diff