From 45bd9ec32061806e659961e6a8a3b133a1352b5d Mon Sep 17 00:00:00 2001 From: divverent Date: Wed, 19 Sep 2012 15:13:14 +0000 Subject: [PATCH] buffer csprogs downloads and load csprogs from the buffer instead of a file, if available This fixes csprogs-from-demo loading if dlcache is not writable git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@11848 d7cf8633-e32d-0410-b094-e92efae38249 --- cl_parse.c | 9 +++++++++ client.h | 4 ++++ csprogs.c | 16 ++++++++++++++-- menu.c | 2 +- progsvm.h | 2 +- prvm_edict.c | 13 ++++++++++--- sv_main.c | 2 +- 7 files changed, 40 insertions(+), 8 deletions(-) diff --git a/cl_parse.c b/cl_parse.c index 4b8da407..acacc542 100644 --- a/cl_parse.c +++ b/cl_parse.c @@ -1405,6 +1405,15 @@ static void CL_StopDownload(int size, int crc) { Con_Printf("Downloaded \"%s\" (%i bytes, %i CRC)\n", name, size, crc); FS_WriteFile(name, cls.qw_downloadmemory, cls.qw_downloadmemorycursize); + if(!strcmp(cls.qw_downloadname, csqc_progname.string)) + { + if(cls.caughtcsprogsdata) + Mem_Free(cls.caughtcsprogsdata); + cls.caughtcsprogsdata = Mem_Alloc(cls.permanentmempool, cls.qw_downloadmemorycursize); + memcpy(cls.caughtcsprogsdata, cls.qw_downloadmemory, cls.qw_downloadmemorycursize); + cls.caughtcsprogsdatasize = cls.qw_downloadmemorycursize; + Con_DPrintf("Buffered \"%s\"\n", name); + } } } } diff --git a/client.h b/client.h index c229d288..da20b908 100644 --- a/client.h +++ b/client.h @@ -718,6 +718,10 @@ typedef struct client_static_s int proquake_servermod; // 0 = not proquake, 1 = proquake int proquake_serverversion; // actual proquake server version * 10 (3.40 = 34, etc) int proquake_serverflags; // 0 (PQF_CHEATFREE not supported) + + // don't write-then-read csprogs.dat (useful for demo playback) + unsigned char *caughtcsprogsdata; + fs_offset_t caughtcsprogsdatasize; } client_static_t; diff --git a/csprogs.c b/csprogs.c index 45cb9551..9051caef 100644 --- a/csprogs.c +++ b/csprogs.c @@ -1003,7 +1003,19 @@ void CL_VM_Init (void) if (!cls.demoplayback || csqc_usedemoprogs.integer) { csprogsfn = va(vabuf, sizeof(vabuf), "dlcache/%s.%i.%i", csqc_progname.string, requiredsize, requiredcrc); - csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize); + if(cls.caughtcsprogsdata && cls.caughtcsprogsdatasize == requiredsize && CRC_Block(cls.caughtcsprogsdata, (size_t)cls.caughtcsprogsdatasize) == requiredcrc) + { + Con_DPrintf("Using buffered \"%s\"\n", csprogsfn); + csprogsdata = cls.caughtcsprogsdata; + csprogsdatasize = cls.caughtcsprogsdatasize; + cls.caughtcsprogsdata = NULL; + cls.caughtcsprogsdatasize = 0; + } + else + { + Con_DPrintf("Not using buffered \"%s\" (buffered: %p, %d)\n", csprogsfn, cls.caughtcsprogsdata, (int) cls.caughtcsprogsdatasize); + csprogsdata = FS_LoadFile(csprogsfn, tempmempool, true, &csprogsdatasize); + } } if (!csprogsdata) { @@ -1073,7 +1085,7 @@ void CL_VM_Init (void) prog->error_cmd = Host_Error; prog->ExecuteProgram = CLVM_ExecuteProgram; - PRVM_Prog_Load(prog, csprogsfn, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals); + PRVM_Prog_Load(prog, csprogsfn, csprogsdata, csprogsdatasize, cl_numrequiredfunc, cl_required_func, CL_REQFIELDS, cl_reqfields, CL_REQGLOBALS, cl_reqglobals); if (!prog->loaded) { diff --git a/menu.c b/menu.c index c8152918..3e7efaf2 100644 --- a/menu.c +++ b/menu.c @@ -5364,7 +5364,7 @@ static void MP_Init (void) // allocate the mempools prog->progs_mempool = Mem_AllocPool(M_PROG_FILENAME, 0, NULL); - PRVM_Prog_Load(prog, M_PROG_FILENAME, m_numrequiredfunc, m_required_func, m_numrequiredfields, m_required_fields, m_numrequiredglobals, m_required_globals); + PRVM_Prog_Load(prog, M_PROG_FILENAME, NULL, 0, m_numrequiredfunc, m_required_func, m_numrequiredfields, m_required_fields, m_numrequiredglobals, m_required_globals); // note: OP_STATE is not supported by menu qc, we don't even try to detect // it here diff --git a/progsvm.h b/progsvm.h index 17ee4aa4..5dbfd464 100644 --- a/progsvm.h +++ b/progsvm.h @@ -857,7 +857,7 @@ Load a program with LoadProgs */ // Load expects to be called right after Init void PRVM_Prog_Init(prvm_prog_t *prog); -void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global); +void PRVM_Prog_Load(prvm_prog_t *prog, const char *filename, unsigned char *data, fs_offset_t size, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global); void PRVM_Prog_Reset(prvm_prog_t *prog); void PRVM_StackTrace(prvm_prog_t *prog); diff --git a/prvm_edict.c b/prvm_edict.c index 4de128b2..56f3602e 100644 --- a/prvm_edict.c +++ b/prvm_edict.c @@ -1875,7 +1875,7 @@ static void PRVM_LoadLNO( prvm_prog_t *prog, const char *progname ) { PRVM_LoadProgs =============== */ -void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global) +void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, unsigned char * data, fs_offset_t size, int numrequiredfunc, const char **required_func, int numrequiredfields, prvm_required_field_t *required_field, int numrequiredglobals, prvm_required_field_t *required_global) { int i; dprograms_t *dprograms; @@ -1906,7 +1906,13 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, int numrequiredfun Host_LockSession(); // all progs can use the session cvar Crypto_LoadKeys(); // all progs might use the keys at init time - dprograms = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false, &filesize); + if (data) + { + dprograms = (dprograms_t *) data; + filesize = size; + } + else + dprograms = (dprograms_t *)FS_LoadFile (filename, prog->progs_mempool, false, &filesize); if (dprograms == NULL || filesize < (fs_offset_t)sizeof(dprograms_t)) prog->error_cmd("PRVM_LoadProgs: couldn't load %s for %s", filename, prog->name); // TODO bounds check header fields (e.g. numstatements), they must never go behind end of file @@ -2213,7 +2219,8 @@ void PRVM_Prog_Load(prvm_prog_t *prog, const char * filename, int numrequiredfun } // we're done with the file now - Mem_Free(dprograms); + if(!data) + Mem_Free(dprograms); dprograms = NULL; // check required functions diff --git a/sv_main.c b/sv_main.c index d94bb032..14ae253c 100644 --- a/sv_main.c +++ b/sv_main.c @@ -3711,7 +3711,7 @@ static void SV_VM_Setup(void) prog->error_cmd = Host_Error; prog->ExecuteProgram = SVVM_ExecuteProgram; - PRVM_Prog_Load(prog, sv_progs.string, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals); + PRVM_Prog_Load(prog, sv_progs.string, NULL, 0, SV_REQFUNCS, sv_reqfuncs, SV_REQFIELDS, sv_reqfields, SV_REQGLOBALS, sv_reqglobals); // some mods compiled with scrambling compilers lack certain critical // global names and field names such as "self" and "time" and "nextthink" -- 2.39.2