buffer csprogs downloads and load csprogs from the buffer instead of a file, if available
authordivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 19 Sep 2012 15:13:14 +0000 (15:13 +0000)
committerdivverent <divverent@d7cf8633-e32d-0410-b094-e92efae38249>
Wed, 19 Sep 2012 15:13:14 +0000 (15:13 +0000)
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
client.h
csprogs.c
menu.c
progsvm.h
prvm_edict.c
sv_main.c

index 4b8da40..acacc54 100644 (file)
@@ -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);
+                                               }
                                        }
                                }
                        }
index c229d28..da20b90 100644 (file)
--- 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;
 
index 45cb955..9051cae 100644 (file)
--- 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 c815291..3e7efaf 100644 (file)
--- 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
index 17ee4aa..5dbfd46 100644 (file)
--- 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);
index 4de128b..56f3602 100644 (file)
@@ -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
index d94bb03..14ae253 100644 (file)
--- 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"