void G_LoadCachedRoffs() { int i, count = 0, len = 0; char buffer[MAX_QPATH]; ojk::SavedGameHelper saved_game( ::gi.saved_game); // Get the count of goodies we need to revive saved_game.read_chunk<int32_t>( INT_ID('R', 'O', 'F', 'F'), count); // Now bring 'em back to life for ( i = 0; i < count; i++ ) { saved_game.read_chunk<int32_t>( INT_ID('S', 'L', 'E', 'N'), len); if (len < 0 || static_cast<size_t>(len) >= sizeof(buffer)) { len = 0; } saved_game.read_chunk( INT_ID('R', 'S', 'T', 'R'), buffer, len); G_LoadRoff( buffer ); } }
void TIMER_Load( void ) { int j; gentity_t *ent; for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { unsigned char numTimers; gi.ReadFromSaveGame( INT_ID('T','I','M','E'), (void *)&numTimers, sizeof(numTimers), NULL ); //Read back all entries for ( int i = 0; i < numTimers; i++ ) { int time; char tempBuffer[1024]; // Still ugly. Setting ourselves up for 007 AUF all over again. =) assert (sizeof(g_timers[0]->time) == sizeof(time) );//make sure we're reading the same size as we wrote //Read the id string and time gi.ReadFromSaveGame( INT_ID('T','M','I','D'), (char *) tempBuffer, 0, NULL ); gi.ReadFromSaveGame( INT_ID('T','D','T','A'), (void *) &time, sizeof( time ), NULL ); //this is odd, we saved all the timers in the autosave, but not all the ents are spawned yet from an auto load, so skip it if (ent->inuse) { //Restore it TIMER_Set(ent, tempBuffer, time); } } } }
void G_SaveCachedRoffs() { int i, len; ojk::SavedGameHelper saved_game( ::gi.saved_game); // Write out the number of cached ROFFs saved_game.write_chunk<int32_t>( INT_ID('R', 'O', 'F', 'F'), ::num_roffs); // Now dump out the cached ROFF file names in order so they can be loaded on the other end for ( i = 0; i < num_roffs; i++ ) { // Dump out the string length to make things a bit easier on the other end...heh heh. len = strlen( roffs[i].fileName ) + 1; saved_game.write_chunk<int32_t>( INT_ID('S', 'L', 'E', 'N'), len); saved_game.write_chunk( INT_ID('R', 'S', 'T', 'R'), ::roffs[i].fileName, len); } }
void TIMER_Save( void ) { int j; gentity_t *ent; for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { int numTimers = g_timers[ent->s.number].size(); int i; //Write out the timer information gi.AppendToSaveGame(INT_ID('T','I','M','E'), (void *)&numTimers, sizeof(numTimers)); timer_m::iterator ti; for ( i = 0, ti = g_timers[ j ].begin(); i < numTimers; i++, ti++ ) { const char *id = ((*ti).first).c_str(); int length = strlen( id ); //Write out the string size and data gi.AppendToSaveGame(INT_ID('T','S','L','N'), (void *) &length, sizeof(length) ); gi.AppendToSaveGame(INT_ID('T','S','N','M'), (void *) id, length ); //Write out the timer data gi.AppendToSaveGame(INT_ID('T','D','T','A'), (void *) &(*ti).second, sizeof( (*ti).second ) ); } } }
void WriteLevel(qboolean qbAutosave) { if (!qbAutosave) //-always save the client { // write out one client - us! // assert(level.maxclients == 1); // I'll need to know if this changes, otherwise I'll need to change the way ReadGame works gclient_t client = level.clients[0]; EnumerateFields(savefields_gClient, (byte *)&client, INT_ID('G','C','L','I'), sizeof(client)); WriteLevelLocals(); // level_locals_t level } OBJ_SaveObjectiveData(); ///////////// WriteGEntities(qbAutosave); Q3_VariableSave(); G_LoadSave_WriteMiscData(); extern void CG_WriteTheEvilCGHackStuff(void); CG_WriteTheEvilCGHackStuff(); // (Do NOT put any write-code below this line) // // put out an end-marker so that the load code can check everything was read in... // static int iDONE = 1234; gi.AppendToSaveGame(INT_ID('D','O','N','E'), &iDONE, sizeof(iDONE)); }
void TIMER_Load( void ) { int j; gentity_t *ent; ojk::SavedGameHelper saved_game( ::gi.saved_game); for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { unsigned char numTimers = 0; saved_game.read_chunk<uint8_t>( INT_ID('T', 'I', 'M', 'E'), numTimers); //Read back all entries for ( int i = 0; i < numTimers; i++ ) { int time = 0; char tempBuffer[1024]; // Still ugly. Setting ourselves up for 007 AUF all over again. =) assert (sizeof(g_timers[0]->time) == sizeof(time) );//make sure we're reading the same size as we wrote //Read the id string and time saved_game.read_chunk( INT_ID('T', 'M', 'I', 'D')); const char* sg_buffer_data = static_cast<const char*>( saved_game.get_buffer_data()); int sg_buffer_size = saved_game.get_buffer_size(); if (sg_buffer_size < 0 || static_cast<size_t>(sg_buffer_size) >= sizeof(tempBuffer)) { sg_buffer_size = 0; } else { std::uninitialized_copy_n( sg_buffer_data, sg_buffer_size, tempBuffer); } tempBuffer[sg_buffer_size] = '\0'; saved_game.read_chunk<int32_t>( INT_ID('T', 'D', 'T', 'A'), time); //this is odd, we saved all the timers in the autosave, but not all the ents are spawned yet from an auto load, so skip it if (ent->inuse) { //Restore it TIMER_Set(ent, tempBuffer, time); } } } }
void TIMER_Load( void ) { int j; gentity_t *ent; ojk::SavedGameHelper saved_game( ::gi.saved_game); for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { int numTimers = 0; saved_game.read_chunk<int32_t>( INT_ID('T', 'I', 'M', 'E'), numTimers); //Make sure there's something to read if ( numTimers == 0 ) continue; //Read back all entries for ( int i = 0; i < numTimers; i++ ) { int length = 0, time = 0; char tempBuffer[1024]; // Still ugly. Setting ourselves up for 007 AUF all over again. =) assert (sizeof(g_timers[0]->time) == sizeof(time) );//make sure we're reading the same size as we wrote saved_game.read_chunk<int32_t>( INT_ID('T', 'S', 'L', 'N'), length); if ( length >= 1024 ) { assert( 0 ); continue; } //Read the id and time saved_game.read_chunk( INT_ID('T', 'S', 'N', 'M'), tempBuffer, length); tempBuffer[length] = '\0'; saved_game.read_chunk<int32_t>( INT_ID('T', 'D', 'T', 'A'), time); //this is odd, we saved all the timers in the autosave, but not all the ents are spawned yet from an auto load, so skip it if (ent->inuse) { //Restore it TIMER_Set(ent, tempBuffer, time); } } } }
void ReadLevel(qboolean qbAutosave, qboolean qbLoadTransition) { if ( qbLoadTransition ) { //loadtransitions do not need to read the objectives and client data from the level they're going to //In a loadtransition, client data is carried over on the server and will be stomped later anyway. //The objective info (in client->sess data), however, is read in from G_ReadSessionData which is called before this func, //we do NOT want to stomp that session data when doing a load transition //However, we should still save this info out because these savegames may need to be //loaded normally later- perhaps if you die and need to respawn, perhaps as some kind //of emergency savegame for resuming, etc. //SO: We read it in, but throw it away. //Read & throw away gclient info gclient_t junkClient; EvaluateFields(savefields_gClient, (byte *)&junkClient, (byte *)&level.clients[0], INT_ID('G','C','L','I'), sizeof(*level.clients), qfalse); //Read & throw away objective info objectives_t junkObj[MAX_MISSION_OBJ]; gi.ReadFromSaveGame(INT_ID('O','B','J','T'), (void *) &junkObj, 0, NULL); ReadLevelLocals(); // level_locals_t level } else { if (!qbAutosave )//always load the client unless it's an autosave { assert(level.maxclients == 1); // I'll need to know if this changes, otherwise I'll need to change the way things work gclient_t GClient; EvaluateFields(savefields_gClient, (byte *)&GClient, (byte *)&level.clients[0], INT_ID('G','C','L','I'), sizeof(*level.clients), qfalse); level.clients[0] = GClient; // struct copy ReadLevelLocals(); // level_locals_t level } OBJ_LoadObjectiveData();//loads mission objectives AND tactical info } ///////////// ReadGEntities(qbAutosave); Q3_VariableLoad(); G_LoadSave_ReadMiscData(); extern void CG_ReadTheEvilCGHackStuff(void); CG_ReadTheEvilCGHackStuff(); // (Do NOT put any read-code below this line) // // check that the whole file content was loaded by specifically requesting an end-marker... // static int iDONE = 1234; gi.ReadFromSaveGame(INT_ID('D','O','N','E'), &iDONE, sizeof(iDONE), NULL); }
void TIMER_Save( void ) { int j; gentity_t *ent; ojk::SavedGameHelper saved_game( ::gi.saved_game); for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { int numTimers = TIMER_GetCount(j); if ( !ent->inuse && numTimers) { // Com_Printf( "WARNING: ent with timers not inuse\n" ); assert(numTimers); TIMER_Clear( j ); numTimers = 0; } //Write out the timer information saved_game.write_chunk<int32_t>( INT_ID('T', 'I', 'M', 'E'), numTimers); gtimer_t *p = g_timers[j]; assert ((numTimers && p) || (!numTimers && !p)); while(p) { const char *timerID = p->id.c_str(); const int length = strlen(timerID) + 1; const int time = p->time - level.time; //convert this back to delta so we can use SET after loading assert( length < 1024 );//This will cause problems when loading the timer if longer //Write out the string size and data saved_game.write_chunk<int32_t>( INT_ID('T', 'S', 'L', 'N'), length); saved_game.write_chunk( INT_ID('T', 'S', 'N', 'M'), timerID, length); //Write out the timer data saved_game.write_chunk<int32_t>( INT_ID('T', 'D', 'T', 'A'), time); p = p->next; } } }
void EvaluateFields(field_t *pFields, byte *pbData, byte *pbOriginalRefData, unsigned int ulChid, int iSize, qboolean bOkToSizeMisMatch) { int iReadSize = gi.ReadFromSaveGame(ulChid, pbData, bOkToSizeMisMatch?0:iSize, NULL); if (iReadSize != iSize) { // handle any chunks that are ok to change length (typically this is a last minute hack, // so hopefully we won't need it any more... ;-) // switch (ulChid) { // example chunk handler... // case INT_ID('G','C','L','I'): /* assert(iSize>iReadSize); memset(&pbData[iReadSize], 0, iSize-iReadSize); // zero out new objectives that weren't in old-format save file break; */ default: // won't return... // G_Error(va("EvaluateFields(): variable-sized chunk '%s' without handler!",SG_GetChidText(ulChid))); break; } } if (pFields) { for (field_t *pField = pFields; pField->psName; pField++) { EvaluateField(pField, pbData, pbOriginalRefData); } } }
void EnumerateFields(field_t *pFields, byte *pbData, unsigned int ulChid, int iLen) { assert(strList.empty()); // enumerate all the fields... // if (pFields) { for (field_t *pField = pFields; pField->psName; pField++) { assert(pField->iOffset < iLen); EnumerateField(pField, pbData); } } // save out raw data... // gi.AppendToSaveGame(ulChid, pbData, iLen); // save out any associated strings.. // list<sstring_t>::iterator it = strList.begin(); for (unsigned int i=0; i<strList.size(); i++, ++it) { gi.AppendToSaveGame(INT_ID('S','T','R','G'), (void *)(*it).c_str(), (*it).length() + 1); } strList.clear(); // make sure everything is cleaned up nicely }
static void EnumerateFields(const field_t *pFields, byte *pbData, unsigned int ulChid, size_t iLen) { strList = new list<sstring_t>; // enumerate all the fields... // if (pFields) { for (const field_t *pField = pFields; pField->psName; pField++) { assert(pField->iOffset < iLen); EnumerateField(pField, pbData); } } // save out raw data... // gi.AppendToSaveGame(ulChid, pbData, iLen); // save out any associated strings.. // for (list<sstring_t>::iterator it = strList->begin(); it != strList->end(); ++it) { gi.AppendToSaveGame(INT_ID('S','T','R','G'), (void*)it->c_str(), it->length()+1); } delete strList; strList = NULL; }
qboolean SG_Open( const char *psPathlessBaseName ) { // if ( fhSaveGame ) // hmmm... // { // // SG_Close(); // // } // assert( !fhSaveGame); // I'd rather know about this if(!psPathlessBaseName) { return qfalse; } //JLFSAVEGAME const char *psLocalFilename = SG_AddSavePath( psPathlessBaseName ); FS_FOpenFileRead( psLocalFilename, &fhSaveGame, qtrue ); //qtrue = dup handle, so I can close it ok later if (!fhSaveGame) { // Com_Printf(S_COLOR_RED "Failed to open savegame file %s\n", psLocalFilename); Com_DPrintf(GetString_FailedToOpenSaveGame(psLocalFilename, qtrue)); return qfalse; } giSaveGameVersion=-1;//jic SG_Read(INT_ID('_','V','E','R'), &giSaveGameVersion, sizeof(giSaveGameVersion)); if (giSaveGameVersion != iSAVEGAME_VERSION) { SG_Close(); Com_Printf (S_COLOR_RED "File \"%s\" has version # %d (expecting %d)\n",psPathlessBaseName, giSaveGameVersion, iSAVEGAME_VERSION); return qfalse; } return qtrue; }
void process_text(char *in_buffer) { uint8_t last_pos = *ringbuffer_pos; char buffer[64] = {0}; while(1) { uint8_t new_pos; while(last_pos == (new_pos = *ringbuffer_pos)) { uint64_t info = wait_for_interrupt(); if(INT_ID(info) == CLOCK_ID) { toggle_pos(cursor_pos, normal, inverted); } } while(last_pos != new_pos) { uint8_t c; c = keyboard_ringbuffer[last_pos]; process_char(c,1); last_pos = ((last_pos + 1) % RINGBUFFER_SIZE); if(c == '\r') { strcpy(in_buffer, input); process_char('\r',0); input_size = 0; memset(input,0,sizeof(input)); goto done; } } } done: return; }
static char *GetStringPtr(int iStrlen, char *psOriginal/*may be NULL*/) { if (iStrlen != -1) { char sString[768]; // arb, inc if nec. sString[0]=0; assert(iStrlen+1<=(int)sizeof(sString)); ojk::SavedGameHelper saved_game( ::gi.saved_game); saved_game.read_chunk( INT_ID('S', 'T', 'R', 'G'), sString, iStrlen); // TAG_G_ALLOC is always blown away, we can never recycle if (psOriginal && gi.bIsFromZone(psOriginal, TAG_G_ALLOC)) { if (!strcmp(psOriginal,sString)) {//it's a legal ptr and they're the same so let's just reuse it instead of free/alloc return psOriginal; } gi.Free(psOriginal); } return G_NewString(sString); } return NULL; }
/* ============== WriteLevelLocals All pointer variables (except function pointers) must be handled specially. ============== */ static void WriteLevelLocals () { level_locals_t *temp = (level_locals_t *)gi.Malloc(sizeof(level_locals_t), TAG_TEMP_WORKSPACE, qfalse); *temp = level; // copy out all data into a temp space EnumerateFields(savefields_LevelLocals, temp, INT_ID('L','V','L','C')); gi.Free(temp); }
/* ============== WriteLevelLocals All pointer variables (except function pointers) must be handled specially. ============== */ static void WriteLevelLocals () { level_locals_t *temp = (level_locals_t *)gi.Malloc(sizeof(level_locals_t), TAG_TEMP_WORKSPACE, qfalse); *temp = level; // copy out all data into a temp space EnumerateFields(savefields_LevelLocals, (byte *)temp, INT_ID('L','V','L','C'), LLOFS(LEVEL_LOCALS_T_SAVESTOP)); // sizeof(temp)); gi.Free(temp); }
void G_LoadSave_ReadMiscData(void) { ojk::SavedGameHelper saved_game( ::gi.saved_game); saved_game.read_chunk<int32_t>( INT_ID('L', 'C', 'K', 'D'), ::player_locked); }
void WriteInUseBits() { ojk::SavedGameHelper saved_game( ::gi.saved_game); saved_game.write_chunk<uint32_t>( INT_ID('I', 'N', 'U', 'S'), ::g_entityInUseBits); }
void ReadInUseBits(void) { gi.ReadFromSaveGame(INT_ID('I','N','U','S'), &g_entityInUseBits, sizeof(g_entityInUseBits), NULL); // This is only temporary. Once I have converted all the ent->inuse refs, // it won;t be needed -MW. for(int i=0;i<MAX_GENTITIES;i++) { g_entities[i].inuse=PInUse(i); } }
static void EvaluateFields( const save_field_t* pFields, T* pbData, byte* pbOriginalRefData, unsigned int ulChid) { T& instance = *pbData; ojk::SavedGameHelper saved_game( ::gi.saved_game); if (ulChid != INT_ID('G', 'C', 'L', 'I')) { saved_game.read_chunk( ulChid, instance); } else { if (!saved_game.try_read_chunk( ulChid, instance)) { RetailGClient retail_client; saved_game.reset_buffer_offset(); if (saved_game.try_read( retail_client)) { copy_retail_gclient_to_current( retail_client, *reinterpret_cast<gclient_t*>(pbData)); } else { ::G_Error( ::va("EvaluateFields(): variable-sized chunk '%s' without handler!", ::SG_GetChidText(ulChid))); } } } if (pFields) { for (const save_field_t* pField = pFields; pField->psName; ++pField) { ::EvaluateField( pField, reinterpret_cast<byte*>(pbData), pbOriginalRefData); } } }
/* ============== ReadLevelLocals All pointer variables (except function pointers) must be handled specially. ============== */ void ReadLevelLocals () { // preserve client ptr either side of the load, because clients are already saved/loaded through Read/Writegame... // gclient_t *pClients = level.clients; // save clients level_locals_t temp = level; // struct copy EvaluateFields(savefields_LevelLocals, (byte *)&temp, (byte *)&level, INT_ID('L','V','L','C'), LLOFS(LEVEL_LOCALS_T_SAVESTOP),qfalse); // sizeof(level_locals_t)); level = temp; // struct copy level.clients = pClients; // restore clients }
void TIMER_Save( void ) { int j; gentity_t *ent; for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { unsigned char numTimers = TIMER_GetCount(j); if ( !ent->inuse && numTimers) { // Com_Printf( "WARNING: ent with timers not inuse\n" ); assert(numTimers); TIMER_Clear( j ); numTimers = 0; } //Write out the timer information gi.AppendToSaveGame(INT_ID('T','I','M','E'), (void *)&numTimers, sizeof(numTimers)); gtimer_t *p = g_timers[j]; assert ((numTimers && p) || (!numTimers && !p)); while(p) { const char *timerID = p->id.c_str(); const int length = strlen(timerID) + 1; const int time = p->time - level.time; //convert this back to delta so we can use SET after loading assert( length < 1024 );//This will cause problems when loading the timer if longer //Write out the id string gi.AppendToSaveGame(INT_ID('T','M','I','D'), (void *) timerID, length); //Write out the timer data gi.AppendToSaveGame(INT_ID('T','D','T','A'), (void *) &time, sizeof( time ) ); p = p->next; } } }
int CSequence::SaveCommand( CBlock *block ) { unsigned char flags; int numMembers, bID, size; CBlockMember *bm; ojk::SavedGameHelper saved_game( m_owner->GetInterface()->saved_game); //Save out the block ID bID = block->GetBlockID(); saved_game.write_chunk<int32_t>( INT_ID('B', 'L', 'I', 'D'), bID); //Save out the block's flags flags = block->GetFlags(); saved_game.write_chunk<uint8_t>( INT_ID('B', 'F', 'L', 'G'), flags); //Save out the number of members to read numMembers = block->GetNumMembers(); saved_game.write_chunk<int32_t>( INT_ID('B', 'N', 'U', 'M'), numMembers); for ( int i = 0; i < numMembers; i++ ) { bm = block->GetMember( i ); //Save the block id bID = bm->GetID(); saved_game.write_chunk<int32_t>( INT_ID('B', 'M', 'I', 'D'), bID); //Save out the data size size = bm->GetSize(); saved_game.write_chunk<int32_t>( INT_ID('B', 'S', 'I', 'Z'), size); //Save out the raw data const uint8_t* raw_data = static_cast<const uint8_t*>(bm->GetData()); saved_game.write_chunk( INT_ID('B', 'M', 'E', 'M'), raw_data, size); } return true; }
void TIMER_Load( void ) { int j; gentity_t *ent; for ( j = 0, ent = &g_entities[0]; j < MAX_GENTITIES; j++, ent++ ) { int numTimers; gi.ReadFromSaveGame( INT_ID('T','I','M','E'), (void *)&numTimers, sizeof(numTimers), NULL ); //Make sure there's something to read if ( numTimers == 0 ) continue; //Read back all entries for ( int i = 0; i < numTimers; i++ ) { int length, time; char tempBuffer[1024]; //FIXME: Blech! gi.ReadFromSaveGame( INT_ID('T','S','L','N'), (void *) &length, sizeof( length ), NULL ); //Validity check, though this will never happen (unless of course you pass in gibberish) if ( length >= 1024 ) { assert(0); continue; } //Read the id and time gi.ReadFromSaveGame( INT_ID('T','S','N','M'), (char *) tempBuffer, length, NULL ); gi.ReadFromSaveGame( INT_ID('T','D','T','A'), (void *) &time, sizeof( time ), NULL ); //Restore it g_timers[ j ][(const char *) tempBuffer ] = time; } } }
/* ============== ReadLevelLocals All pointer variables (except function pointers) must be handled specially. ============== */ static void ReadLevelLocals () { // preserve client ptr either side of the load, because clients are already saved/loaded through Read/Writegame... // gclient_t *pClients = level.clients; // save clients level_locals_t *temp = (level_locals_t *)gi.Malloc(sizeof(level_locals_t), TAG_TEMP_WORKSPACE, qfalse); *temp = level; // struct copy EvaluateFields(savefields_LevelLocals, temp, (byte *)&level, INT_ID('L','V','L','C')); level = *temp; // struct copy level.clients = pClients; // restore clients gi.Free(temp); }
int CSequence::Save( void ) { sequence_l::iterator ci; block_l::iterator bi; int id; //Save the parent (by GUID) id = ( m_parent != NULL ) ? m_parent->GetID() : -1; (m_owner->GetInterface())->I_WriteSaveData( INT_ID('S','P','I','D'), &id, sizeof( id ) ); //Save the return (by GUID) id = ( m_return != NULL ) ? m_return->GetID() : -1; (m_owner->GetInterface())->I_WriteSaveData( INT_ID('S','R','I','D'), &id, sizeof( id ) ); //Save the number of children (m_owner->GetInterface())->I_WriteSaveData( INT_ID('S','N','C','H'), &m_numChildren, sizeof( m_numChildren ) ); //Save out the children (only by GUID) STL_ITERATE( ci, m_children ) { id = (*ci)->GetID(); (m_owner->GetInterface())->I_WriteSaveData( INT_ID('S','C','H','D'), &id, sizeof( id ) ); }
int CSequence::Save( void ) { sequence_l::iterator ci; block_l::iterator bi; int id; ojk::SavedGameHelper saved_game( m_owner->GetInterface()->saved_game); //Save the parent (by GUID) id = ( m_parent != NULL ) ? m_parent->GetID() : -1; saved_game.write_chunk<int32_t>( INT_ID('S', 'P', 'I', 'D'), id); //Save the return (by GUID) id = ( m_return != NULL ) ? m_return->GetID() : -1; saved_game.write_chunk<int32_t>( INT_ID('S', 'R', 'I', 'D'), id); //Save the number of children saved_game.write_chunk<int32_t>( INT_ID('S', 'N', 'C', 'H'), m_numChildren); //Save out the children (only by GUID) STL_ITERATE( ci, m_children ) { id = (*ci)->GetID(); saved_game.write_chunk<int32_t>( INT_ID('S', 'C', 'H', 'D'), id); }
void ReadInUseBits() { ojk::SavedGameHelper saved_game( ::gi.saved_game); saved_game.read_chunk<uint32_t>( INT_ID('I', 'N', 'U', 'S'), ::g_entityInUseBits); // This is only temporary. Once I have converted all the ent->inuse refs, // it won;t be needed -MW. for(int i=0;i<MAX_GENTITIES;i++) { g_entities[i].inuse=PInUse(i); } }
static void EvaluateFields(const save_field_t *pFields, byte *pbData, byte *pbOriginalRefData, unsigned int ulChid, int iSize, qboolean bOkToSizeMisMatch) { int iReadSize = gi.ReadFromSaveGame(ulChid, pbData, bOkToSizeMisMatch?0:iSize, NULL); if (iReadSize != iSize) { // handle any chunks that are ok to change length (typically this is a last minute hack, // so hopefully we won't need it any more... ;-) // switch (ulChid) { // example chunk handler... // case INT_ID('G','C','L','I'): if ( iSize == (int)(iReadSize+((sizeof(saberInfo_t)-sizeof(saberInfoRetail_t))*2)) ) { gclient_t newClient; const int preSaberDataSize = ((intptr_t)&newClient.ps.saber[0]-(intptr_t)&newClient); memcpy( &newClient, pbData, preSaberDataSize ); SG_ConvertRetailSaberinfoToNewSaberinfo( ((void *)(&((gclient_t *)(pbData))->ps.saber[0])), &newClient.ps.saber[0] ); memcpy( &newClient.ps.dualSabers, pbData+preSaberDataSize+(sizeof(saberInfoRetail_t)*2), sizeof(newClient)-(preSaberDataSize+(sizeof(saberInfo_t)*2)) ); memcpy( pbData, &newClient, sizeof(gclient_t) ); } else {//opps, not a saberInfo size mismatch, some other FUBAR-ness... G_Error(va("EvaluateFields(): variable-sized chunk '%s' without handler!",SG_GetChidText(ulChid))); } break; default: // won't return... // G_Error(va("EvaluateFields(): variable-sized chunk '%s' without handler!",SG_GetChidText(ulChid))); break; } } if (pFields) { for (const save_field_t *pField = pFields; pField->psName; pField++) { EvaluateField(pField, pbData, pbOriginalRefData); } } }