diff options
Diffstat (limited to 'src/save')
-rw-r--r-- | src/save/GenericGameStorage.cpp | 497 | ||||
-rw-r--r-- | src/save/GenericGameStorage.h | 11 | ||||
-rw-r--r-- | src/save/PCSave.cpp | 18 | ||||
-rw-r--r-- | src/save/PCSave.h | 2 | ||||
-rw-r--r-- | src/save/SaveBuf.h | 74 |
5 files changed, 363 insertions, 239 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); diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h index 6a5b04fa..bebf426a 100644 --- a/src/save/GenericGameStorage.h +++ b/src/save/GenericGameStorage.h @@ -5,6 +5,9 @@ #define SLOT_COUNT (8) +void InitRadioStationPositionList(); +int32 GetSavedRadioStationPosition(int32 station); +void PopulateRadioStationPositionList(); bool GenericSave(int file); bool GenericLoad(); bool ReadInSizeofSaveFileBuffer(int32 &file, uint32 &size); @@ -27,8 +30,6 @@ uint8 GetSaveType(char *savename); bool FixSave(int32 slot, uint8 save_type); #endif -extern class CDate CompileDateAndTime; - extern char DefaultPCSaveFileName[260]; extern char ValidSaveName[260]; extern char LoadFileName[256]; @@ -36,7 +37,7 @@ extern wchar SlotFileName[SLOT_COUNT][260]; extern wchar SlotSaveDate[SLOT_COUNT][70]; extern int CheckSum; extern enum eLevelName m_LevelToLoad; -extern int Slots[SLOT_COUNT+1]; +extern int Slots[SLOT_COUNT]; extern bool b_FoundRecentSavedGameWantToLoad; extern bool JustLoadedDontFadeInYet; @@ -57,7 +58,9 @@ enum { SAVE_TYPE_NORMAL, SAVE_TYPE_QUICKSAVE, SAVE_TYPE_2, - SAVE_TYPE_QUICKSAVE_FOR_MISSION_REPLAY + SAVE_TYPE_QUICKSAVE_FOR_MISSION_REPLAY, + SAVE_TYPE_QUICKSAVE_FOR_SCRIPT, + SAVE_TYPE_QUICKSAVE_FOR_SCRIPT_ON_A_MISSION }; #endif diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index 0c228a6d..a33e9d90 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -19,7 +19,7 @@ C_PcSave PcSaveHelper; void C_PcSave::SetSaveDirectory(const char *path) { - sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTA3sf"); + sprintf(DefaultPCSaveFileName, "%s\\%s", path, "GTAVCsf"); } bool @@ -38,7 +38,7 @@ C_PcSave::DeleteSlot(int32 slot) return true; } -bool +int8 C_PcSave::SaveSlot(int32 slot) { MakeValidSaveName(slot); @@ -53,10 +53,10 @@ C_PcSave::SaveSlot(int32 slot) if (GenericSave(file)) { if (!!CFileMgr::CloseFile(file)) nErrorCode = SAVESTATUS_ERR_SAVE_CLOSE; - return true; + return 0; } - return false; + return 2; } PcSaveHelper.nErrorCode = SAVESTATUS_ERR_SAVE_CREATE; return false; @@ -93,7 +93,7 @@ void C_PcSave::PopulateSlotInfo() { for (int i = 0; i < SLOT_COUNT; i++) { - Slots[i + 1] = SLOT_EMPTY; + Slots[i] = SLOT_EMPTY; SlotFileName[i][0] = '\0'; SlotSaveDate[i][0] = '\0'; } @@ -113,19 +113,19 @@ C_PcSave::PopulateSlotInfo() if (file != 0) { CFileMgr::Read(file, (char*)&header, sizeof(header)); if (strncmp((char*)&header, TopLineEmptyFile, sizeof(TopLineEmptyFile)-1) != 0) { - Slots[i + 1] = SLOT_OK; + Slots[i] = SLOT_OK; memcpy(SlotFileName[i], &header.FileName, sizeof(header.FileName)); SlotFileName[i][24] = '\0'; } CFileMgr::CloseFile(file); } - if (Slots[i + 1] == SLOT_OK) { + if (Slots[i] == SLOT_OK) { if (CheckDataNotCorrupt(i, savename)) { #ifdef FIX_INCOMPATIBLE_SAVES if (!FixSave(i, GetSaveType(savename))) { CMessages::InsertNumberInString(TheText.Get("FEC_SLC"), i + 1, -1, -1, -1, -1, -1, SlotFileName[i]); - Slots[i + 1] = SLOT_CORRUPTED; + Slots[i] = SLOT_CORRUPTED; continue; } #endif @@ -159,7 +159,7 @@ C_PcSave::PopulateSlotInfo() } else { CMessages::InsertNumberInString(TheText.Get("FEC_SLC"), i + 1, -1, -1, -1, -1, -1, SlotFileName[i]); - Slots[i + 1] = SLOT_CORRUPTED; + Slots[i] = SLOT_CORRUPTED; } } } diff --git a/src/save/PCSave.h b/src/save/PCSave.h index 83471b5d..2a29fa95 100644 --- a/src/save/PCSave.h +++ b/src/save/PCSave.h @@ -32,7 +32,7 @@ public: C_PcSave() : nErrorCode(SAVESTATUS_SUCCESSFUL) {} void PopulateSlotInfo(); bool DeleteSlot(int32 slot); - bool SaveSlot(int32 slot); + int8 SaveSlot(int32 slot); bool PcClassSaveRoutine(int32 file, uint8 *data, uint32 size); static void SetSaveDirectory(const char *path); }; diff --git a/src/save/SaveBuf.h b/src/save/SaveBuf.h index aad2e1a8..d0817e9a 100644 --- a/src/save/SaveBuf.h +++ b/src/save/SaveBuf.h @@ -18,24 +18,52 @@ SkipSaveBuf(uint8 *&buf, int32 skip) #endif } -template <typename T> inline void -ReadSaveBuf(T* out, uint8 *&buf) +SkipSaveBuf(uint8*& buf, uint32 &length, int32 skip) +{ + buf += skip; + length += skip; +#ifdef VALIDATE_SAVE_SIZE + _saveBufCount += skip; +#endif +} + +template<typename T> +inline void +ReadSaveBuf(T *out, uint8 *&buf) { *out = *(T *)buf; SkipSaveBuf(buf, sizeof(T)); } -template <typename T> +template<typename T> +inline void +ReadSaveBuf(T *out, uint8 *&buf, uint32 &length) +{ + *out = *(T *)buf; + SkipSaveBuf(buf, length, sizeof(T)); +} + +template<typename T> inline T * WriteSaveBuf(uint8 *&buf, const T &value) { - T *p = (T *)buf; + T *p = (T*)buf; *p = value; SkipSaveBuf(buf, sizeof(T)); return p; } +template<typename T> +inline T * +WriteSaveBuf(uint8 *&buf, uint32 &length, const T &value) +{ + T *p = (T*)buf; + *p = value; + SkipSaveBuf(buf, length, sizeof(T)); + return p; +} + #ifdef COMPATIBLE_SAVES inline void ZeroSaveBuf(uint8 *&buf, uint32 length) @@ -45,14 +73,21 @@ ZeroSaveBuf(uint8 *&buf, uint32 length) } #endif -#define SAVE_HEADER_SIZE (4 * sizeof(char) + sizeof(uint32)) +#define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32)) -#define WriteSaveHeader(buf, a, b, c, d, size) \ - WriteSaveBuf(buf, a); \ - WriteSaveBuf(buf, b); \ - WriteSaveBuf(buf, c); \ - WriteSaveBuf(buf, d); \ - WriteSaveBuf(buf, (uint32)(size)); +#define WriteSaveHeader(buf,a,b,c,d,size) \ + WriteSaveBuf(buf, a);\ + WriteSaveBuf(buf, b);\ + WriteSaveBuf(buf, c);\ + WriteSaveBuf(buf, d);\ + WriteSaveBuf<uint32>(buf, size); + +#define WriteSaveHeaderWithLength(buf,len,a,b,c,d,size) \ + WriteSaveBuf(buf, len, a);\ + WriteSaveBuf(buf, len, b);\ + WriteSaveBuf(buf, len, c);\ + WriteSaveBuf(buf, len, d);\ + WriteSaveBuf(buf, len, (uint32)(size)); #ifdef VALIDATE_SAVE_SIZE #define CheckSaveHeader(buf, a, b, c, d, size) do { \ @@ -68,6 +103,21 @@ ZeroSaveBuf(uint8 *&buf, uint32 length) ReadSaveBuf(&_size, buf);\ assert(_size == size);\ } while(0) + +#define CheckSaveHeaderWithLength(buf,len,a,b,c,d,size) do { \ + char _c; uint32 _size;\ + ReadSaveBuf(&_c, buf, len);\ + assert(_c == a);\ + ReadSaveBuf(&_c, buf, len);\ + assert(_c == b);\ + ReadSaveBuf(&_c, buf, len);\ + assert(_c == c);\ + ReadSaveBuf(&_c, buf, len);\ + assert(_c == d);\ + ReadSaveBuf(&_size, buf, len);\ + assert(_size == size);\ + } while(0) #else #define CheckSaveHeader(buf, a, b, c, d, size) SkipSaveBuf(buf, 8); -#endif
\ No newline at end of file +#define CheckSaveHeaderWithLength(buf, len, a, b, c, d, size) SkipSaveBuf(buf, 8); +#endif |