diff options
Diffstat (limited to 'src/save/GenericGameStorage.cpp')
-rw-r--r-- | src/save/GenericGameStorage.cpp | 497 |
1 files changed, 284 insertions, 213 deletions
diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index e4ee4542..b68b805a 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -30,6 +30,7 @@ #include "Radar.h" #include "Restart.h" #include "Script.h" +#include "SetPieces.h" #include "Stats.h" #include "Streaming.h" #include "Timer.h" @@ -37,9 +38,11 @@ #include "Weather.h" #include "World.h" #include "Zones.h" +#include "Timecycle.h" +#include "Fluff.h" -#define BLOCK_COUNT 20 -#define SIZE_OF_SIMPLEVARS 0xBC +#define BLOCK_COUNT 22 +#define SIZE_OF_SIMPLEVARS 0xE4 const uint32 SIZE_OF_ONE_GAME_IN_BYTES = 201729; @@ -56,8 +59,7 @@ wchar SlotSaveDate[SLOT_COUNT][70]; int CheckSum; eLevelName m_LevelToLoad; char SaveFileNameJustSaved[260]; -int Slots[SLOT_COUNT+1]; -CDate CompileDateAndTime; +int Slots[SLOT_COUNT]; bool b_FoundRecentSavedGameWantToLoad; bool JustLoadedDontFadeInYet; @@ -65,6 +67,28 @@ bool StillToFadeOut; uint32 TimeStartedCountingForFade; uint32 TimeToStayFadedBeforeFadeOut = 1750; +int32 RadioStationPosition[NUM_RADIOS]; + +void +InitRadioStationPositionList() +{ + for (int i = 0; i < NUM_RADIOS; i++) + RadioStationPosition[i] = -1; +} + +int32 +GetSavedRadioStationPosition(int32 station) +{ + return RadioStationPosition[station]; +} + +void +PopulateRadioStationPositionList() +{ + for (int i = 0; i < NUM_RADIOS; i++) + RadioStationPosition[i] = DMAudio.GetRadioPosition(i); +} + #define ReadDataFromBufferPointer(buf, to) memcpy(&to, buf, sizeof(to)); buf += align4bytes(sizeof(to)); #define WriteDataToBufferPointer(buf, from) memcpy(buf, &from, sizeof(from)); buf += align4bytes(sizeof(from)); @@ -87,12 +111,14 @@ do {\ buf += size;\ } while (0) -#define WriteSaveDataBlock(save_func)\ +#define WriteSaveDataBlock(save_func, msg)\ do {\ + size = 0;\ buf = work_buff;\ reserved = 0;\ MakeSpaceForSizeInBufferPointer(presize, buf, postsize);\ save_func(buf, &size);\ + debug(msg"== %i \n", size);\ CopySizeAndPreparePointer(presize, buf, postsize, reserved, size);\ if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff))\ return false;\ @@ -119,24 +145,23 @@ GenericSave(int file) reserved = 0; // Save simple vars - lastMissionPassed = TheText.Get(CStats::LastMissionPassedName); - if (lastMissionPassed[0] != '\0') { - AsciiToUnicode("...'", suffix); + lastMissionPassed = TheText.Get(CStats::LastMissionPassedName[0] ? CStats::LastMissionPassedName : "ITBEG"); + AsciiToUnicode("...'", suffix); + suffix[3] = L'\0'; #ifdef FIX_BUGS - // fix buffer overflow - int len = UnicodeStrlen(lastMissionPassed); - if (len > ARRAY_SIZE(saveName)-1) - len = ARRAY_SIZE(saveName)-1; - memcpy(saveName, lastMissionPassed, sizeof(wchar) * len); + // fix buffer overflow + int len = UnicodeStrlen(lastMissionPassed); + if (len > ARRAY_SIZE(saveName)-1) + len = ARRAY_SIZE(saveName)-1; + memcpy(saveName, lastMissionPassed, sizeof(wchar) * len); #else - TextCopy(saveName, lastMissionPassed); - int len = UnicodeStrlen(saveName); + TextCopy(saveName, lastMissionPassed); + int len = UnicodeStrlen(saveName); #endif - saveName[len] = '\0'; - if (len > ARRAY_SIZE(saveName)-2) - TextCopy(&saveName[ARRAY_SIZE(saveName)-ARRAY_SIZE(suffix)], suffix); - saveName[ARRAY_SIZE(saveName)-1] = '\0'; - } + saveName[len] = '\0'; + if (len > ARRAY_SIZE(saveName)-2) + TextCopy(&saveName[ARRAY_SIZE(saveName)-ARRAY_SIZE(suffix)], suffix); + saveName[ARRAY_SIZE(saveName)-1] = '\0'; WriteDataToBufferPointer(buf, saveName); GetLocalTime(&saveTime); WriteDataToBufferPointer(buf, saveTime); @@ -168,12 +193,6 @@ GenericSave(int file) WriteDataToBufferPointer(buf, CWeather::NewWeatherType); WriteDataToBufferPointer(buf, CWeather::ForcedWeatherType); WriteDataToBufferPointer(buf, CWeather::InterpolationValue); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nSecond); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nMinute); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nHour); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nDay); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nMonth); - WriteDataToBufferPointer(buf, CompileDateAndTime.m_nYear); WriteDataToBufferPointer(buf, CWeather::WeatherTypeInList); #ifdef COMPATIBLE_SAVES // converted to float for compatibility with original format @@ -186,6 +205,14 @@ GenericSave(int file) WriteDataToBufferPointer(buf, TheCamera.CarZoomIndicator); WriteDataToBufferPointer(buf, TheCamera.PedZoomIndicator); #endif + WriteDataToBufferPointer(buf, CGame::currArea); + WriteDataToBufferPointer(buf, CVehicle::bAllTaxisHaveNitro); + WriteDataToBufferPointer(buf, CPad::bInvertLook4Pad); + WriteDataToBufferPointer(buf, CTimeCycle::m_ExtraColour); + WriteDataToBufferPointer(buf, CTimeCycle::m_bExtraColourOn); + WriteDataToBufferPointer(buf, CTimeCycle::m_ExtraColourInter); + PopulateRadioStationPositionList(); + WriteDataToBufferPointer(buf, RadioStationPosition); assert(buf - work_buff == SIZE_OF_SIMPLEVARS); // Save scripts, block is nested within the same block as simple vars for some reason @@ -193,6 +220,7 @@ GenericSave(int file) buf += 4; postsize = buf; CTheScripts::SaveAllScripts(buf, &size); + debug("ScriptSize== %i \n", size); CopySizeAndPreparePointer(presize, buf, postsize, reserved, size); if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff, buf - work_buff)) return false; @@ -200,25 +228,28 @@ GenericSave(int file) totalSize = buf - work_buff; // Save the rest - WriteSaveDataBlock(CPools::SavePedPool); - WriteSaveDataBlock(CGarages::Save); - WriteSaveDataBlock(CPools::SaveVehiclePool); - WriteSaveDataBlock(CPools::SaveObjectPool); - WriteSaveDataBlock(ThePaths.Save); - WriteSaveDataBlock(CCranes::Save); - WriteSaveDataBlock(CPickups::Save); - WriteSaveDataBlock(gPhoneInfo.Save); - WriteSaveDataBlock(CRestart::SaveAllRestartPoints); - WriteSaveDataBlock(CRadar::SaveAllRadarBlips); - WriteSaveDataBlock(CTheZones::SaveAllZones); - WriteSaveDataBlock(CGangs::SaveAllGangData); - WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators); - WriteSaveDataBlock(CParticleObject::SaveParticle); - WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects); - WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo); - WriteSaveDataBlock(CStats::SaveStats); - WriteSaveDataBlock(CStreaming::MemoryCardSave); - WriteSaveDataBlock(CPedType::Save); + WriteSaveDataBlock(CPools::SavePedPool, "PedPoolSize"); + WriteSaveDataBlock(CGarages::Save, "GaragesSize"); + WriteSaveDataBlock(CGameLogic::Save, "GameLogicSize"); + WriteSaveDataBlock(CPools::SaveVehiclePool, "VehPoolSize"); + WriteSaveDataBlock(CPools::SaveObjectPool, "ObjectPoolSize"); + WriteSaveDataBlock(ThePaths.Save, "ThePathsSize"); + WriteSaveDataBlock(CCranes::Save, "CranesSize"); + WriteSaveDataBlock(CPickups::Save, "PickUpsSize"); + WriteSaveDataBlock(gPhoneInfo.Save, "PhoneInfoSize"); + WriteSaveDataBlock(CRestart::SaveAllRestartPoints, "RestartPointsBufferSize"); + WriteSaveDataBlock(CRadar::SaveAllRadarBlips, "RadarBlipsBufferSize"); + WriteSaveDataBlock(CTheZones::SaveAllZones, "AllZonesBufferSize"); + WriteSaveDataBlock(CGangs::SaveAllGangData, "AllGangDataSize"); + WriteSaveDataBlock(CTheCarGenerators::SaveAllCarGenerators, "AllCarGeneratorsSize"); + WriteSaveDataBlock(CParticleObject::SaveParticle, "ParticlesSize"); + WriteSaveDataBlock(cAudioScriptObject::SaveAllAudioScriptObjects, "AllAudioScriptObjectsSize"); + WriteSaveDataBlock(CScriptPaths::Save, "ScriptPathsSize"); + WriteSaveDataBlock(CWorld::Players[CWorld::PlayerInFocus].SavePlayerInfo, "PlayerInfoSize"); + WriteSaveDataBlock(CStats::SaveStats, "StatsSize"); + WriteSaveDataBlock(CSetPieces::Save, "SetPiecesSize"); + WriteSaveDataBlock(CStreaming::MemoryCardSave, "StreamingSize"); + WriteSaveDataBlock(CPedType::Save, "PedTypeSize"); // sure just write garbage data repeatedly ... #ifndef THIS_IS_STUPID @@ -246,7 +277,8 @@ GenericSave(int file) return false; } - + + CPad::FixPadsAfterSave(); return true; } @@ -297,13 +329,12 @@ GenericLoad() ReadDataFromBufferPointer(buf, CWeather::OldWeatherType); ReadDataFromBufferPointer(buf, CWeather::NewWeatherType); ReadDataFromBufferPointer(buf, CWeather::ForcedWeatherType); +#ifdef SECUROM + if (CTimer::m_FrameCounter > 72000){ + buf += align4bytes(4); + } +#endif ReadDataFromBufferPointer(buf, CWeather::InterpolationValue); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nSecond); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMinute); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nHour); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nDay); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nMonth); - ReadDataFromBufferPointer(buf, CompileDateAndTime.m_nYear); ReadDataFromBufferPointer(buf, CWeather::WeatherTypeInList); #ifdef COMPATIBLE_SAVES // converted to float for compatibility with original format @@ -317,6 +348,17 @@ GenericLoad() ReadDataFromBufferPointer(buf, TheCamera.CarZoomIndicator); ReadDataFromBufferPointer(buf, TheCamera.PedZoomIndicator); #endif + ReadDataFromBufferPointer(buf, CGame::currArea); + ReadDataFromBufferPointer(buf, CVehicle::bAllTaxisHaveNitro); +#ifdef LOAD_INI_SETTINGS + buf += align4bytes(sizeof(CPad::bInvertLook4Pad)); +#else + ReadDataFromBufferPointer(buf, CPad::bInvertLook4Pad); +#endif + ReadDataFromBufferPointer(buf, CTimeCycle::m_ExtraColour); + ReadDataFromBufferPointer(buf, CTimeCycle::m_bExtraColourOn); + ReadDataFromBufferPointer(buf, CTimeCycle::m_ExtraColourInter); + ReadDataFromBufferPointer(buf, RadioStationPosition); assert(buf - work_buff == SIZE_OF_SIMPLEVARS); #ifdef MISSION_REPLAY WaitForSave = 0; @@ -331,6 +373,8 @@ GenericLoad() LoadSaveDataBlock(); ReadDataFromBlock("Loading Garages \n", CGarages::Load); LoadSaveDataBlock(); + ReadDataFromBlock("Loading GameLogic \n", CGameLogic::Load); + LoadSaveDataBlock(); ReadDataFromBlock("Loading Vehicles \n", CPools::LoadVehiclePool); LoadSaveDataBlock(); CProjectileInfo::RemoveAllProjectiles(); @@ -360,16 +404,20 @@ GenericLoad() LoadSaveDataBlock(); ReadDataFromBlock("Loading AudioScript Objects \n", cAudioScriptObject::LoadAllAudioScriptObjects); LoadSaveDataBlock(); + ReadDataFromBlock("Loading ScriptPaths \n", CScriptPaths::Load); + LoadSaveDataBlock(); ReadDataFromBlock("Loading Player Info \n", CWorld::Players[CWorld::PlayerInFocus].LoadPlayerInfo); LoadSaveDataBlock(); ReadDataFromBlock("Loading Stats \n", CStats::LoadStats); LoadSaveDataBlock(); + ReadDataFromBlock("Loading Set Pieces \n", CSetPieces::Load); + LoadSaveDataBlock(); ReadDataFromBlock("Loading Streaming Stuff \n", CStreaming::MemoryCardLoad); LoadSaveDataBlock(); ReadDataFromBlock("Loading PedType Stuff \n", CPedType::Load); - DMAudio.SetMusicMasterVolume(CMenuManager::m_PrefsMusicVolume); - DMAudio.SetEffectsMasterVolume(CMenuManager::m_PrefsSfxVolume); + DMAudio.SetMusicMasterVolume(FrontEndMenuManager.m_PrefsMusicVolume); + DMAudio.SetEffectsMasterVolume(FrontEndMenuManager.m_PrefsSfxVolume); if (!CloseFile(file)) { PcSaveHelper.nErrorCode = SAVESTATUS_ERR_LOAD_CLOSE; return false; @@ -424,8 +472,13 @@ CloseFile(int32 file) void DoGameSpecificStuffAfterSucessLoad() { + CCollision::SortOutCollisionAfterLoad(); + CStreaming::LoadSceneCollision(TheCamera.GetPosition()); + CStreaming::LoadScene(TheCamera.GetPosition()); + CGame::TidyUpMemory(true, false); StillToFadeOut = true; JustLoadedDontFadeInYet = true; + TheCamera.Fade(0.0f, FADE_OUT); CTheScripts::Process(); } @@ -572,19 +625,9 @@ RestoreForStartLoad() ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().x); ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().y); ReadDataFromBufferPointer(_buf, TheCamera.GetMatrix().GetPosition().z); - ISLAND_LOADING_IS(LOW) - { - CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); - CStreaming::RemoveUnusedBuildings(CGame::currLevel); - } - CCollision::SortOutCollisionAfterLoad(); - ISLAND_LOADING_IS(LOW) - { - CStreaming::RequestBigBuildings(CGame::currLevel); - CStreaming::LoadAllRequestedModels(false); - CStreaming::HaveAllBigBuildingsLoaded(CGame::currLevel); - CGame::TidyUpMemory(true, false); - } + CStreaming::RemoveUnusedBigBuildings(CGame::currLevel); + CStreaming::RemoveUnusedBuildings(CGame::currLevel); + if (CloseFile(file)) { return true; } else { @@ -650,6 +693,7 @@ enum SAVE_TYPE_64_BIT = 2, SAVE_TYPE_MSVC = 4, SAVE_TYPE_GCC = 8, + SAVE_TYPE_STEAM = 16, }; uint8 @@ -664,6 +708,14 @@ GetSaveType(char *savename) uint8 *buf = work_buff; CFileMgr::Read(file, (const char *)work_buff, size); // simple vars + scripts + buf += 0x40 + sizeof(int32) + sizeof(int32) + sizeof(float) * 3; + + int8 steam_byte; + ReadDataFromBufferPointer(buf, steam_byte); + + if (steam_byte == -3) + save_type |= SAVE_TYPE_STEAM; + LoadSaveDataBlockNoCheck(buf, file, size); // ped pool LoadSaveDataBlockNoCheck(buf, file, size); // garages @@ -672,6 +724,7 @@ GetSaveType(char *savename) // store for later after we know how much data we need to skip ReadDataFromBufferPointerWithSize(buf, work_buff2, size); + LoadSaveDataBlockNoCheck(buf, file, size); // game logic LoadSaveDataBlockNoCheck(buf, file, size); // vehicle pool LoadSaveDataBlockNoCheck(buf, file, size); // object pool LoadSaveDataBlockNoCheck(buf, file, size); // paths @@ -682,7 +735,7 @@ GetSaveType(char *savename) ReadDataFromBufferPointer(buf, size); - if (size == 1032) + if (size == 1000) save_type |= SAVE_TYPE_32_BIT; else if (size == 1160) save_type |= SAVE_TYPE_64_BIT; @@ -691,22 +744,21 @@ GetSaveType(char *savename) buf = work_buff2; - buf += 760; // skip everything before the first garage - buf += save_type & SAVE_TYPE_32_BIT ? 28 : 40; // skip first garage up to m_fX1 + buf += 1964; // skip everything before the first garage + buf += save_type & SAVE_TYPE_32_BIT ? 28 : 40; // skip first garage up to m_vecCorner1 - // now the values we want to verify - float fX1, fX2, fY1, fY2, fZ1, fZ2; + CVector2D vecCorner1; + float fInfZ, fSupZ; - ReadBuf(buf, fX1); - ReadBuf(buf, fX2); - ReadBuf(buf, fY1); - ReadBuf(buf, fY2); - ReadBuf(buf, fZ1); - ReadBuf(buf, fZ2); + ReadBuf(buf, vecCorner1); + ReadBuf(buf, fInfZ); + SkipBuf(buf, sizeof(CVector2D)); + SkipBuf(buf, sizeof(CVector2D)); + ReadBuf(buf, fSupZ); - if (fX1 == CRUSHER_GARAGE_X1 && fX2 == CRUSHER_GARAGE_X2 && - fY1 == CRUSHER_GARAGE_Y1 && fY2 == CRUSHER_GARAGE_Y2 && - fZ1 == CRUSHER_GARAGE_Z1 && fZ2 == CRUSHER_GARAGE_Z2) + // SET_GARAGE -914.129028 -1263.540039 10.706000 -907.137024 -1246.625977 -906.299988 -1266.900024 14.421000 + if (vecCorner1.x == -914.129028f && vecCorner1.y == -1263.540039f && + fInfZ == 10.706000f && fSupZ == 14.421000f) save_type |= SAVE_TYPE_MSVC; else save_type |= SAVE_TYPE_GCC; @@ -715,25 +767,48 @@ GetSaveType(char *savename) } static void +FixSimpleVarsAndScripts(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = *size; + uint32 written = *size - (sizeof(int8) + 3); + + uint32 pre_steam = 0x40 + sizeof(int32) + sizeof(int32) + sizeof(float) * 3; + uint32 post_steam = *size - (sizeof(int8) + 3) - pre_steam; + + CopyBuf(buf, buf2, pre_steam); + SkipBuf(buf, sizeof(int8) + 3); + CopyBuf(buf, buf2, post_steam); + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void FixGarages(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) { - // hardcoded: 5484 - // x86 msvc: 5240 - // x86 gcc: 5040 - // amd64 msvc: 5880 - // amd64 gcc: 5808 + // hardcoded: 7876 + // x86 msvc: 7340 + // x86 gcc: 7020 + // amd64 msvc: 7852 + // amd64 gcc: 7660 uint8 *buf_start = buf; uint8 *buf2_start = buf2; uint32 read; - uint32 written = 5240; + uint32 written = 7340; if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_GCC) - read = 5040; + read = 7020; else if (save_type & SAVE_TYPE_64_BIT && save_type & SAVE_TYPE_GCC) - read = 5808; + read = 7660; else - read = 5880; + read = 7852; uint32 ptrsize = save_type & SAVE_TYPE_32_BIT ? 4 : 8; @@ -745,62 +820,45 @@ FixGarages(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) { for (int32 i = 0; i < NUM_GARAGE_STORED_CARS; i++) { -#define FixStoredCar(buf, buf2) \ -do { \ - CopyBuf(buf, buf2, 4 + sizeof(CVector) + sizeof(CVector)); \ - uint8 nFlags8; \ - ReadBuf(buf, nFlags8); \ - int32 nFlags32 = nFlags8; \ - WriteBuf(buf2, nFlags32); \ - CopyBuf(buf, buf2, 1 * 6); \ - SkipBuf(buf, 1); \ - SkipBuf(buf2, 2); \ -} while(0) - - FixStoredCar(buf, buf2); - FixStoredCar(buf, buf2); - FixStoredCar(buf, buf2); - -#undef FixStoredCar + for (int32 j = 0; j < TOTAL_HIDEOUT_GARAGES; j++) + { + CopyBuf(buf, buf2, 4 + sizeof(CVector) + sizeof(CVector)); + uint8 nFlags8; + ReadBuf(buf, nFlags8); + int32 nFlags32 = nFlags8; + WriteBuf(buf2, nFlags32); + CopyBuf(buf, buf2, 1 * 6); + SkipBuf(buf, 1); + SkipBuf(buf2, 2); + } } } else { - CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS); - CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS); - CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS); + CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS * TOTAL_HIDEOUT_GARAGES); } for (int32 i = 0; i < NUM_GARAGES; i++) { - // skip the last 5 garages in 64bit builds without FIX_GARAGE_SIZE since they weren't actually saved and are unused - if (save_type & SAVE_TYPE_64_BIT && *size == 5484 && i >= NUM_GARAGES - 5) - { - SkipBuf(buf, 160); // sizeof(CGarage) on x64 - SkipBuf(buf2, 140); // sizeof(CGarage) on x86 - } + CopyBuf(buf, buf2, 1 * 7); + SkipBoth(buf, buf2, 1); + CopyBuf(buf, buf2, 4); + SkipBuf(buf, ptrsize - 4); // write 4 bytes padding if 8 byte pointer, if not, write 0 + SkipBuf(buf, ptrsize * 2); + SkipBuf(buf2, 4 * 2); + CopyBuf(buf, buf2, 1 * 7); + SkipBoth(buf, buf2, 1); + CopyBuf(buf, buf2, sizeof(CVector2D) * 3 + 4 * 17 + 1); + SkipBoth(buf, buf2, 3); + SkipBuf(buf, ptrsize); + SkipBuf(buf2, 4); + + if (save_type & SAVE_TYPE_GCC) + SkipBuf(buf, save_type & SAVE_TYPE_64_BIT ? 36 + 4 : 36); // sizeof(CStoredCar) on gcc 64/32 before fix else - { - CopyBuf(buf, buf2, 1 * 6); - SkipBoth(buf, buf2, 2); - CopyBuf(buf, buf2, 4); - SkipBuf(buf, ptrsize - 4); // write 4 bytes padding if 8 byte pointer, if not, write 0 - SkipBuf(buf, ptrsize * 2); - SkipBuf(buf2, 4 * 2); - CopyBuf(buf, buf2, 1 * 7); - SkipBoth(buf, buf2, 1); - CopyBuf(buf, buf2, 4 * 15 + 1); - SkipBoth(buf, buf2, 3); - SkipBuf(buf, ptrsize * 2); - SkipBuf(buf2, 4 * 2); - - if (save_type & SAVE_TYPE_GCC) - SkipBuf(buf, save_type & SAVE_TYPE_64_BIT ? 36 + 4 : 36); // sizeof(CStoredCar) on gcc 64/32 before fix - else - SkipBuf(buf, sizeof(CStoredCar)); - - SkipBuf(buf2, sizeof(CStoredCar)); - } + SkipBuf(buf, sizeof(CStoredCar)); + + SkipBuf(buf2, sizeof(CStoredCar)); } *size = 0; @@ -808,11 +866,7 @@ do { \ assert(buf - buf_start == read); assert(buf2 - buf2_start == written); -#ifdef FIX_GARAGE_SIZE - *size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CGarages::CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)); -#else - *size = 5484; -#endif + *size = 7876; } static void @@ -821,7 +875,7 @@ FixCranes(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) uint8 *buf_start = buf; uint8 *buf2_start = buf2; uint32 read = 2 * sizeof(uint32) + 0x480; // sizeof(aCranes) - uint32 written = 2 * sizeof(uint32) + 0x400; // see CRANES_SAVE_SIZE + uint32 written = 2 * sizeof(uint32) + 0x3E0; // see CRANES_SAVE_SIZE CopyBuf(buf, buf2, 4 + 4); @@ -829,7 +883,8 @@ FixCranes(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) { CopyPtr(buf, buf2); CopyPtr(buf, buf2); - CopyBuf(buf, buf2, 15 * 4 + sizeof(CVector) * 3 + sizeof(CVector2D)); + CopyBuf(buf, buf2, 14 * 4 + sizeof(CVector) * 3 + sizeof(CVector2D)); + SkipBuf(buf, 4); CopyPtr(buf, buf2); CopyBuf(buf, buf2, 4 + 7 * 1); SkipBuf(buf, 5); @@ -849,16 +904,17 @@ FixPickups(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) { uint8 *buf_start = buf; uint8 *buf2_start = buf2; - uint32 read = 0x3480 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // sizeof(aPickUps) - uint32 written = 0x24C0 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // see PICKUPS_SAVE_SIZE + uint32 read = 0x5400 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // sizeof(aPickUps) + uint32 written = 0x4440 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // see PICKUPS_SAVE_SIZE for (int32 i = 0; i < NUMPICKUPS; i++) { - CopyBuf(buf, buf2, 1 + 1 + 2); - SkipBuf(buf, 4); + CopyBuf(buf, buf2, sizeof(CVector) + 4); CopyPtr(buf, buf2); - CopyBuf(buf, buf2, 4 + 2 + 2 + sizeof(CVector)); - SkipBuf(buf, 4); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 4 * 2 + 2 * 3 + 8 + 1 * 3); + SkipBuf(buf, 7); + SkipBuf(buf2, 3); } CopyBuf(buf, buf2, 2); @@ -910,54 +966,6 @@ FixPhoneInfo(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) } static void -FixZones(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) -{ - uint8 *buf_start = buf; - uint8 *buf2_start = buf2; - uint32 read = 11300; // see SaveAllZones - uint32 written = 10100; // see SaveAllZones - - CopyBuf(buf, buf2, 1 * 4); - - SkipBuf(buf, 4); - uint32 hdr_size = 10100 - (1 * 4 + 4); // see SaveAllZones - WriteBuf(buf2, hdr_size); - - CopyBuf(buf, buf2, 4 * 2 + 2); - SkipBoth(buf, buf2, 2); - -#define FixOneZone(buf, buf2) \ -do { \ - CopyBuf(buf, buf2, 8 + 8 * 4 + 2 * 2); \ - SkipBuf(buf, 4); \ - CopyPtr(buf, buf2); \ - CopyPtr(buf, buf2); \ - CopyPtr(buf, buf2); \ -} while(0) - - for (int32 i = 0; i < NUMZONES; i++) - FixOneZone(buf, buf2); - - CopyBuf(buf, buf2, sizeof(CZoneInfo) * NUMZONES * 2); - CopyBuf(buf, buf2, 2 + 2); - - for (int32 i = 0; i < NUMMAPZONES; i++) - FixOneZone(buf, buf2); - - CopyBuf(buf, buf2, 2 * NUMAUDIOZONES); - CopyBuf(buf, buf2, 2 + 2); - -#undef FixOneZone - - *size = 0; - - assert(buf - buf_start == read); - assert(buf2 - buf2_start == written); - - *size = written; -} - -static void FixParticles(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) { uint8 *buf_start = buf; @@ -967,13 +975,12 @@ FixParticles(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) ReadBuf(buf, numObjects); WriteBuf(buf2, numObjects); - uint32 read = 0xA0 * (numObjects + 1) + 4; // sizeof(CParticleObject) - uint32 written = 0x88 * (numObjects + 1) + 4; // see PARTICLE_OBJECT_SIZEOF + uint32 read = 0x98 * (numObjects + 1) + 4; // sizeof(CParticleObject) + uint32 written = 0x84 * (numObjects + 1) + 4; // see PARTICLE_OBJECT_SIZEOF for (int32 i = 0; i < numObjects; i++) { // CPlaceable - SkipPtr(buf, buf2); CopyBuf(buf, buf2, 4 * 4 * 4); SkipPtr(buf, buf2); CopyBuf(buf, buf2, 1); @@ -990,8 +997,47 @@ FixParticles(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) SkipBoth(buf, buf2, 2); } - SkipBuf(buf, 0xA0); // sizeof(CParticleObject) - SkipBuf(buf2, 0x88); // see PARTICLE_OBJECT_SIZEOF + SkipBuf(buf, 0x98); // sizeof(CParticleObject) + SkipBuf(buf2, 0x84); // see PARTICLE_OBJECT_SIZEOF + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixScriptPaths(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = 0x108; // sizeof(CScriptPath) * 3 + uint32 written = 0x9C; // see SCRIPTPATHS_SAVE_SIZE + + for (int32 i = 0; i < 3; i++) + { + int32 numNodes; + ReadBuf(buf, numNodes); + WriteBuf(buf2, numNodes); + SkipBuf(buf, 4); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 4 * 5); + SkipBuf(buf, 4); + + for (int32 i = 0; i < 6; i++) + { + CopyPtr(buf, buf2); + } + + for (int32 i = 0; i < numNodes; i++) + { + CopyBuf(buf, buf2, sizeof(CPlaneNode)); + read += sizeof(CPlaneNode); + written += sizeof(CPlaneNode); + } + } *size = 0; @@ -1004,7 +1050,7 @@ FixParticles(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) bool FixSave(int32 slot, uint8 save_type) { - if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_MSVC) + if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_MSVC && !(save_type & SAVE_TYPE_STEAM)) return true; bool success = false; @@ -1035,13 +1081,27 @@ FixSave(int32 slot, uint8 save_type) buf = work_buff; CFileMgr::Read(file_in, (const char *)work_buff, size); // simple vars + scripts - WriteSavaDataBlockNoFunc(buf, file_out, size); + if (save_type & SAVE_TYPE_STEAM && save_type & SAVE_TYPE_MSVC && save_type & SAVE_TYPE_32_BIT) { + memset(work_buff2, 0, sizeof(work_buff2)); + buf2 = work_buff2; + FixSimpleVarsAndScripts(save_type, buf, buf2, &size); + if (!PcSaveHelper.PcClassSaveRoutine(file_out, work_buff2, size)) + goto fail; + totalSize += size; + } else + WriteSavaDataBlockNoFunc(buf, file_out, size); LoadSaveDataBlockNoCheck(buf, file_in, size); // ped pool WriteSavaDataBlockNoFunc(buf, file_out, size); LoadSaveDataBlockNoCheck(buf, file_in, size); // garages - FixSaveDataBlock(FixGarages, file_out, size); // garages need to be fixed in either case + if (!(save_type & SAVE_TYPE_STEAM && save_type & SAVE_TYPE_MSVC && save_type & SAVE_TYPE_32_BIT)) + FixSaveDataBlock(FixGarages, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // game logic + WriteSavaDataBlockNoFunc(buf, file_out, size); LoadSaveDataBlockNoCheck(buf, file_in, size); // vehicle pool WriteSavaDataBlockNoFunc(buf, file_out, size); @@ -1077,10 +1137,7 @@ FixSave(int32 slot, uint8 save_type) WriteSavaDataBlockNoFunc(buf, file_out, size); LoadSaveDataBlockNoCheck(buf, file_in, size); // zones - if (save_type & SAVE_TYPE_64_BIT) - FixSaveDataBlock(FixZones, file_out, size); - else - WriteSavaDataBlockNoFunc(buf, file_out, size); + WriteSavaDataBlockNoFunc(buf, file_out, size); LoadSaveDataBlockNoCheck(buf, file_in, size); // gang data WriteSavaDataBlockNoFunc(buf, file_out, size); @@ -1097,12 +1154,21 @@ FixSave(int32 slot, uint8 save_type) LoadSaveDataBlockNoCheck(buf, file_in, size); // audio script objects WriteSavaDataBlockNoFunc(buf, file_out, size); + LoadSaveDataBlockNoCheck(buf, file_in, size); // script paths + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixScriptPaths, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + LoadSaveDataBlockNoCheck(buf, file_in, size); // player info WriteSavaDataBlockNoFunc(buf, file_out, size); LoadSaveDataBlockNoCheck(buf, file_in, size); // stats WriteSavaDataBlockNoFunc(buf, file_out, size); + LoadSaveDataBlockNoCheck(buf, file_in, size); // set pieces + WriteSavaDataBlockNoFunc(buf, file_out, size); + LoadSaveDataBlockNoCheck(buf, file_in, size); // streaming WriteSavaDataBlockNoFunc(buf, file_out, size); @@ -1154,15 +1220,20 @@ void DisplaySaveResult(int unk, char* name) bool SaveGameForPause(int type) { - if (AllowMissionReplay != MISSION_RETRY_STAGE_NORMAL) + if (AllowMissionReplay != MISSION_RETRY_STAGE_NORMAL && AllowMissionReplay != MISSION_RETRY_STAGE_WAIT_FOR_TIMER_AFTER_RESTART) { + debug("SaveGameForPause failed during AllowMissionReplay %d", AllowMissionReplay); return false; - if (type != SAVE_TYPE_QUICKSAVE_FOR_MISSION_REPLAY && WaitForSave > CTimer::GetTimeInMilliseconds()) + } + if (type != SAVE_TYPE_QUICKSAVE_FOR_MISSION_REPLAY && WaitForSave > CTimer::GetTimeInMilliseconds()) { + debug("SaveGameForPause failed WaitForSave"); return false; + } WaitForSave = 0; - if (gGameState != GS_PLAYING_GAME || CTheScripts::IsPlayerOnAMission() || CStats::LastMissionPassedName[0] == '\0') { + if (gGameState != GS_PLAYING_GAME || (CTheScripts::bAlreadyRunningAMissionScript && type != SAVE_TYPE_QUICKSAVE_FOR_SCRIPT_ON_A_MISSION)) { DisplaySaveResult(3, CStats::LastMissionPassedName); return false; } + debug("SaveGameForPause ******************************** %s doSave %d", CStats::LastMissionPassedName, !CTheScripts::bAlreadyRunningAMissionScript); IsQuickSave = type; MissionStartTime = 0; int res = PcSaveHelper.SaveSlot(PAUSE_SAVE_SLOT); |