diff --git a/src/audio/AudioManager.h b/src/audio/AudioManager.h index d3f3fb81..0ee1adf7 100644 --- a/src/audio/AudioManager.h +++ b/src/audio/AudioManager.h @@ -96,8 +96,8 @@ public: m_nCommentsInBank[i] = 0; m_nActiveBank = 0; } - void Add(tPedComment *com); // done - void Process(); // done + void Add(tPedComment *com); + void Process(); }; VALIDATE_SIZE(cPedComments, 0x490); @@ -251,34 +251,34 @@ public: ~cAudioManager(); // getters - uint32 GetFrameCounter() const { return m_FrameCounter; } // done - float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; } // done + uint32 GetFrameCounter() const { return m_FrameCounter; } + float GetReflectionsDistance(int32 idx) const { return m_afReflectionsDistances[idx]; } int32 GetRandomNumber(int32 idx) const { return m_anRandomTable[idx]; } int32 GetRandomNumberInRange(int32 idx, int32 low, int32 high) const { return (m_anRandomTable[idx] % (high - low + 1)) + low; } bool8 IsMissionAudioSamplePlaying(uint8 slot) const; // { return m_sMissionAudio.m_nPlayStatus == 1; } bool8 ShouldDuckMissionAudio(uint8 slot) const; // "Should" be in alphabetic order, except "getXTalkSfx" - void AddDetailsToRequestedOrderList(uint8 sample); // done (inlined in vc) - void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping); // done - void AddReflectionsToRequestedQueue(); // done - void AddReleasingSounds(); // done - void AddSampleToRequestedQueue(); // done - void AgeCrimes(); // done (inlined in vc) - - void CalculateDistance(bool8 &condition, float dist); // done - bool8 CheckForAnAudioFileOnCD() const; // done - void ClearActiveSamples(); // done - void ClearMissionAudio(uint8 slot); // done (inlined in vc) - void ClearRequestedQueue(); // done (inlined in vc) - uint32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const; // done - int32 ComputePan(float, CVector *); // done - uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; // done - int32 CreateEntity(eAudioType type, void *entity); // done - - void DestroyAllGameCreatedEntities(); // done - void DestroyEntity(int32 id); // done (inlined in vc) - void DoPoliceRadioCrackle(); // done + void AddDetailsToRequestedOrderList(uint8 sample); // inlined in vc + void AddPlayerCarSample(uint8 emittingVolume, int32 freq, uint32 sample, uint8 bank, uint8 counter, bool8 notLooping); + void AddReflectionsToRequestedQueue(); + void AddReleasingSounds(); + void AddSampleToRequestedQueue(); + void AgeCrimes(); // inlined in vc + + void CalculateDistance(bool8 &condition, float dist); + bool8 CheckForAnAudioFileOnCD() const; + void ClearActiveSamples(); + void ClearMissionAudio(uint8 slot); // inlined in vc + void ClearRequestedQueue(); // inlined in vc + uint32 ComputeDopplerEffectedFrequency(uint32 oldFreq, float position1, float position2, float speedMultiplier) const; + int32 ComputePan(float, CVector *); + uint8 ComputeVolume(uint8 emittingVolume, float soundIntensity, float distance) const; + int32 CreateEntity(eAudioType type, void *entity); + + void DestroyAllGameCreatedEntities(); + void DestroyEntity(int32 id); // inlined in vc + void DoPoliceRadioCrackle(); // functions returning talk sfx, // order from GetPedCommentSfx @@ -382,170 +382,170 @@ public: uint32 GetGenericFemaleTalkSfx(CPed *ped, int16 sound); // todo names (inlined in vc) // end of functions returning talk sfx - void GenerateIntegerRandomNumberTable(); // done - char *Get3DProviderName(uint8 id) const; // done - char GetCDAudioDriveLetter() const; // done - int8 GetCurrent3DProviderIndex() const; // done - int8 AutoDetect3DProviders() const; // done - float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used - float GetCollisionOneShotRatio(int32 a, float b) const; // done - float GetCollisionRatio(float a, float b, float c, float d) const; // done (inlined in vc) - float GetDistanceSquared(const CVector &v) const; // done (inlined in vc) - int32 GetJumboTaxiFreq() const; // done (inlined in vc) - uint8 GetMissionAudioLoadingStatus(uint8 slot) const; // done - int8 GetMissionScriptPoliceAudioPlayingStatus() const; // done - uint8 GetNum3DProvidersAvailable() const; // done - uint32 GetPedCommentSfx(CPed *ped, int32 sound); // done - void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const; // done + void GenerateIntegerRandomNumberTable(); + char *Get3DProviderName(uint8 id) const; + char GetCDAudioDriveLetter() const; + int8 GetCurrent3DProviderIndex() const; + int8 AutoDetect3DProviders() const; + float GetCollisionLoopingRatio(uint32 a, uint32 b, float c) const; // not used + float GetCollisionOneShotRatio(int32 a, float b) const; + float GetCollisionRatio(float a, float b, float c, float d) const; // inlined in vc + float GetDistanceSquared(const CVector &v) const; // inlined in vc + int32 GetJumboTaxiFreq() const; // inlined in vc + uint8 GetMissionAudioLoadingStatus(uint8 slot) const; + int8 GetMissionScriptPoliceAudioPlayingStatus() const; + uint8 GetNum3DProvidersAvailable() const; + uint32 GetPedCommentSfx(CPed *ped, int32 sound); + void GetPhrase(uint32 &phrase, uint32 &prevPhrase, uint32 sample, uint32 maxOffset) const; float GetVehicleDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, float gasPedalAudio, cTransmission *transmission, - float velocityChange); // done - float GetVehicleNonDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, cTransmission *transmission, float velocityChange); // done - - bool8 HasAirBrakes(int32 model) const; // done - - void Initialise(); // done - void InitialisePoliceRadio(); // done - void InitialisePoliceRadioZones(); // done - void InterrogateAudioEntities(); // done (inlined) - bool8 IsAudioInitialised() const; // done - bool8 IsMissionAudioSampleFinished(uint8 slot); // done - bool8 IsMP3RadioChannelAvailable() const; // done - - bool8 MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; //done - - void PlayLoadedMissionAudio(uint8 slot); // done - void PlayOneShot(int32 index, uint16 sound, float vol); // done - void PlaySuspectLastSeen(float x, float y, float z); // done - void PlayerJustGotInCar() const; // done - void PlayerJustLeftCar() const; // done - void PostInitialiseGameSpecificSetup(); // done - void PostTerminateGameSpecificShutdown(); // done - void PreInitialiseGameSpecificSetup() const; // done - void PreloadMissionAudio(uint8 slot, Const char *name); // done - void PreTerminateGameSpecificShutdown(); // done + float velocityChange); + float GetVehicleNonDriveWheelSkidValue(CVehicle *veh, tWheelState wheelState, cTransmission *transmission, float velocityChange); + + bool8 HasAirBrakes(int32 model) const; + + void Initialise(); + void InitialisePoliceRadio(); + void InitialisePoliceRadioZones(); + void InterrogateAudioEntities(); // inlined + bool8 IsAudioInitialised() const; + bool8 IsMissionAudioSampleFinished(uint8 slot); + bool8 IsMP3RadioChannelAvailable() const; + + bool8 MissionScriptAudioUsesPoliceChannel(int32 soundMission) const; + + void PlayLoadedMissionAudio(uint8 slot); + void PlayOneShot(int32 index, uint16 sound, float vol); + void PlaySuspectLastSeen(float x, float y, float z); + void PlayerJustGotInCar() const; + void PlayerJustLeftCar() const; + void PostInitialiseGameSpecificSetup(); + void PostTerminateGameSpecificShutdown(); + void PreInitialiseGameSpecificSetup() const; + void PreloadMissionAudio(uint8 slot, Const char *name); + void PreTerminateGameSpecificShutdown(); /// processX - main logic of adding new sounds - void ProcessActiveQueues(); // done - bool8 ProcessAirBrakes(cVehicleParams& params); // done + void ProcessActiveQueues(); + bool8 ProcessAirBrakes(cVehicleParams& params); bool8 ProcessBoatEngine(cVehicleParams& params); - bool8 ProcessBoatMovingOverWater(cVehicleParams& params); //done + bool8 ProcessBoatMovingOverWater(cVehicleParams& params); #ifdef GTA_BRIDGE - void ProcessBridge(); // done(bcs not exists in VC) - void ProcessBridgeMotor(); // done(bcs not exists in VC) - void ProcessBridgeOneShots(); // done(bcs not exists in VC) - void ProcessBridgeWarning(); // done(bcs not exists in VC) + void ProcessBridge(); + void ProcessBridgeMotor(); + void ProcessBridgeOneShots(); + void ProcessBridgeWarning(); #endif - bool8 ProcessCarBombTick(cVehicleParams& params); // done - void ProcessCarHeli(cVehicleParams& params); // done - void ProcessCesna(cVehicleParams& params); // done - //void ProcessCrane(); // done(bcs not exists in VC) - bool8 ProcessEngineDamage(cVehicleParams& params); // done - void ProcessEntity(int32 sound); // done - void ProcessExplosions(int32 explosion); // done - void ProcessFireHydrant(); // done - void ProcessFires(int32 entity); // done - void ProcessFrontEnd(); // done - void ProcessGarages(); // done - void ProcessJumbo(cVehicleParams& params); // done - void ProcessJumboAccel(CPlane *plane); // done - void ProcessJumboDecel(CPlane *plane); // done - void ProcessJumboFlying(); // done - void ProcessJumboLanding(CPlane *plane); // done - void ProcessJumboTakeOff(CPlane *plane); // done - void ProcessJumboTaxi(); // done - void ProcessLoopingScriptObject(uint8 sound); // done - void ProcessMissionAudio(); // done - void ProcessMissionAudioSlot(uint8 slot); // done - void ProcessModelHeliVehicle(cVehicleParams& params); // done - void ProcessModelVehicle(cVehicleParams& params); // done - void ProcessOneShotScriptObject(uint8 sound); // - void ProcessPed(CPhysical *ped); // done - void ProcessPedOneShots(cPedParams ¶ms); // - void ProcessPhysical(int32 id); // done - void ProcessPlane(cVehicleParams& params); // done - void ProcessPlayerMood(); // done - void ProcessPlayersVehicleEngine(cVehicleParams& params, CVehicle* veh); // done - void ProcessProjectiles(); // done - void ProcessRainOnVehicle(cVehicleParams& params); // done - void ProcessReverb() const; // done - bool8 ProcessReverseGear(cVehicleParams& params); // done - void ProcessScriptObject(int32 id); // done - void ProcessSpecial(); // done + bool8 ProcessCarBombTick(cVehicleParams& params); + void ProcessCarHeli(cVehicleParams& params); + void ProcessCesna(cVehicleParams& params); + //void ProcessCrane(); + bool8 ProcessEngineDamage(cVehicleParams& params); + void ProcessEntity(int32 sound); + void ProcessExplosions(int32 explosion); + void ProcessFireHydrant(); + void ProcessFires(int32 entity); + void ProcessFrontEnd(); + void ProcessGarages(); + void ProcessJumbo(cVehicleParams& params); + void ProcessJumboAccel(CPlane *plane); + void ProcessJumboDecel(CPlane *plane); + void ProcessJumboFlying(); + void ProcessJumboLanding(CPlane *plane); + void ProcessJumboTakeOff(CPlane *plane); + void ProcessJumboTaxi(); + void ProcessLoopingScriptObject(uint8 sound); + void ProcessMissionAudio(); + void ProcessMissionAudioSlot(uint8 slot); + void ProcessModelHeliVehicle(cVehicleParams& params); + void ProcessModelVehicle(cVehicleParams& params); + void ProcessOneShotScriptObject(uint8 sound); + void ProcessPed(CPhysical *ped); + void ProcessPedOneShots(cPedParams ¶ms); + void ProcessPhysical(int32 id); + void ProcessPlane(cVehicleParams& params); + void ProcessPlayerMood(); + void ProcessPlayersVehicleEngine(cVehicleParams& params, CVehicle* veh); + void ProcessProjectiles(); + void ProcessRainOnVehicle(cVehicleParams& params); + void ProcessReverb() const; + bool8 ProcessReverseGear(cVehicleParams& params); + void ProcessScriptObject(int32 id); + void ProcessSpecial(); #ifdef GTA_TRAIN - bool8 ProcessTrainNoise(cVehicleParams ¶ms); //done(bcs not exists in VC) + bool8 ProcessTrainNoise(cVehicleParams ¶ms); #endif - void ProcessVehicle(CVehicle *vehicle); // done - bool8 ProcessVehicleDoors(cVehicleParams ¶ms); // done - void ProcessVehicleEngine(cVehicleParams ¶ms); // done - void ProcessVehicleFlatTyre(cVehicleParams ¶ms); // done - bool8 ProcessVehicleHorn(cVehicleParams ¶ms); // done - void ProcessVehicleOneShots(cVehicleParams ¶ms); // done - bool8 ProcessVehicleReverseWarning(cVehicleParams ¶ms); // done - bool8 ProcessVehicleRoadNoise(cVehicleParams ¶ms); // done - bool8 ProcessVehicleSirenOrAlarm(cVehicleParams ¶ms); // done - bool8 ProcessVehicleSkidding(cVehicleParams ¶ms); // done - void ProcessWaterCannon(int32); // done - void ProcessWeather(int32 id); // done - bool8 ProcessWetRoadNoise(cVehicleParams& params); // done - void ProcessEscalators(); // done - void ProcessExtraSounds(); // done - - int32 RandomDisplacement(uint32 seed) const; // done - void ReacquireDigitalHandle() const; // done - void ReleaseDigitalHandle() const; // done - void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2); // done - void ReportCrime(eCrimeType crime, const CVector &pos); // done - void ResetAudioLogicTimers(uint32 timer); // done - void ResetPoliceRadio(); // done - void ResetTimers(uint32 time); // done - - void Service(); // done - void ServiceCollisions(); // done - void ServicePoliceRadio(); // done - void ServicePoliceRadioChannel(uint8 wantedLevel); // done - void ServiceSoundEffects(); // done - int8 SetCurrent3DProvider(uint8 which); // done - void SetDynamicAcousticModelingStatus(bool8 status); // done - void SetEffectsFadeVol(uint8 volume) const; // done - void SetEffectsMasterVolume(uint8 volume) const; // done - void SetMP3BoostVolume(uint8 volume) const; // done - void SetEntityStatus(int32 id, bool8 status); // done - uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); // done - void SetMissionAudioLocation(uint8 slot, float x, float y, float z); // done - void SetMissionScriptPoliceAudio(int32 sfx) const; // inlined and optimized - void SetMonoMode(bool8 mono); // done - void SetMusicFadeVol(uint8 volume) const; // done - void SetMusicMasterVolume(uint8 volume) const; // done - void SetSpeakerConfig(int32 conf) const; // done - void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter); // done - void SetUpOneShotCollisionSound(const cAudioCollision &col); // done - bool8 SetupCrimeReport(); // done - bool8 SetupJumboEngineSound(uint8 vol, uint32 freq); // done - bool8 SetupJumboFlySound(uint8 emittingVol); // done - bool8 SetupJumboRumbleSound(uint8 emittingVol); // done - bool8 SetupJumboTaxiSound(uint8 vol); // done - bool8 SetupJumboWhineSound(uint8 emittingVol, uint32 freq); // done - void SetupPedComments(cPedParams ¶ms, uint16 sound); // done + void ProcessVehicle(CVehicle *vehicle); + bool8 ProcessVehicleDoors(cVehicleParams ¶ms); + void ProcessVehicleEngine(cVehicleParams ¶ms); + void ProcessVehicleFlatTyre(cVehicleParams ¶ms); + bool8 ProcessVehicleHorn(cVehicleParams ¶ms); + void ProcessVehicleOneShots(cVehicleParams ¶ms); + bool8 ProcessVehicleReverseWarning(cVehicleParams ¶ms); + bool8 ProcessVehicleRoadNoise(cVehicleParams ¶ms); + bool8 ProcessVehicleSirenOrAlarm(cVehicleParams ¶ms); + bool8 ProcessVehicleSkidding(cVehicleParams ¶ms); + void ProcessWaterCannon(int32); + void ProcessWeather(int32 id); + bool8 ProcessWetRoadNoise(cVehicleParams& params); + void ProcessEscalators(); + void ProcessExtraSounds(); + + int32 RandomDisplacement(uint32 seed) const; + void ReacquireDigitalHandle() const; + void ReleaseDigitalHandle() const; + void ReportCollision(CEntity *entity1, CEntity *entity2, uint8 surface1, uint8 surface2, float collisionPower, float intensity2); + void ReportCrime(eCrimeType crime, const CVector &pos); + void ResetAudioLogicTimers(uint32 timer); + void ResetPoliceRadio(); + void ResetTimers(uint32 time); + + void Service(); + void ServiceCollisions(); + void ServicePoliceRadio(); + void ServicePoliceRadioChannel(uint8 wantedLevel); + void ServiceSoundEffects(); + int8 SetCurrent3DProvider(uint8 which); + void SetDynamicAcousticModelingStatus(bool8 status); + void SetEffectsFadeVol(uint8 volume) const; + void SetEffectsMasterVolume(uint8 volume) const; + void SetMP3BoostVolume(uint8 volume) const; + void SetEntityStatus(int32 id, bool8 status); + uint32 SetLoopingCollisionRequestedSfxFreqAndGetVol(const cAudioCollision &audioCollision); + void SetMissionAudioLocation(uint8 slot, float x, float y, float z); + void SetMissionScriptPoliceAudio(int32 sfx) const; // inlined and optimized + void SetMonoMode(bool8 mono); + void SetMusicFadeVol(uint8 volume) const; + void SetMusicMasterVolume(uint8 volume) const; + void SetSpeakerConfig(int32 conf) const; + void SetUpLoopingCollisionSound(const cAudioCollision &col, uint8 counter); + void SetUpOneShotCollisionSound(const cAudioCollision &col); + bool8 SetupCrimeReport(); + bool8 SetupJumboEngineSound(uint8 vol, uint32 freq); + bool8 SetupJumboFlySound(uint8 emittingVol); + bool8 SetupJumboRumbleSound(uint8 emittingVol); + bool8 SetupJumboTaxiSound(uint8 vol); + bool8 SetupJumboWhineSound(uint8 emittingVol, uint32 freq); + void SetupPedComments(cPedParams ¶ms, uint16 sound); void SetupSuspectLastSeenReport(); - void Terminate(); // done - void TranslateEntity(Const CVector *v1, CVector *v2) const; // done + void Terminate(); + void TranslateEntity(Const CVector *v1, CVector *v2) const; - void UpdateGasPedalAudio(CVehicle *veh, int vehType); // done - void UpdateReflections(); // done - bool8 UsesReverseWarning(int32 model) const; // done - bool8 UsesSiren(cVehicleParams ¶ms) const; // done - bool8 UsesSirenSwitching(cVehicleParams ¶ms) const; // done + void UpdateGasPedalAudio(CVehicle *veh, int vehType); + void UpdateReflections(); + bool8 UsesReverseWarning(int32 model) const; + bool8 UsesSiren(cVehicleParams ¶ms) const; + bool8 UsesSirenSwitching(cVehicleParams ¶ms) const; - CVehicle *FindVehicleOfPlayer(); // done - void SetPedTalkingStatus(CPed *ped, bool8 status); // done - void SetPlayersMood(uint8 mood, uint32 time); // done + CVehicle *FindVehicleOfPlayer(); + void SetPedTalkingStatus(CPed *ped, bool8 status); + void SetPlayersMood(uint8 mood, uint32 time); float Sqrt(float v) const { return v <= 0.0f ? 0.0f : ::Sqrt(v); } #ifdef GTA_PC // only used in pc - void AdjustSamplesVolume(); // done (inlined) - uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); // done (inlined) + void AdjustSamplesVolume(); // inlined + uint8 ComputeEmittingVolume(uint8 emittingVolume, float intensity, float dist); // inlined #endif }; diff --git a/src/audio/oal/stream.cpp b/src/audio/oal/stream.cpp index 7fc36acd..3789573e 100644 --- a/src/audio/oal/stream.cpp +++ b/src/audio/oal/stream.cpp @@ -1648,7 +1648,7 @@ void CStream::SetPlay(bool state) { ALint sourceState = AL_STOPPED; alGetSourcei(m_pAlSources[0], AL_SOURCE_STATE, &sourceState); - if (sourceState != AL_STOPPED ) + if (sourceState != AL_STOPPED) alSourceStop(m_pAlSources[0]); sourceState = AL_STOPPED; diff --git a/src/control/AutoPilot.cpp b/src/control/AutoPilot.cpp index db72548f..d7c17a68 100644 --- a/src/control/AutoPilot.cpp +++ b/src/control/AutoPilot.cpp @@ -50,45 +50,45 @@ void CAutoPilot::RemoveOnePathNode() #ifdef COMPATIBLE_SAVES void CAutoPilot::Save(uint8*& buf) { - WriteSaveBuf(buf, m_nCurrentRouteNode); - WriteSaveBuf(buf, m_nNextRouteNode); - WriteSaveBuf(buf, m_nPrevRouteNode); - WriteSaveBuf(buf, m_nTimeEnteredCurve); - WriteSaveBuf(buf, m_nTimeToSpendOnCurrentCurve); - WriteSaveBuf(buf, m_nCurrentPathNodeInfo); - WriteSaveBuf(buf, m_nNextPathNodeInfo); - WriteSaveBuf(buf, m_nPreviousPathNodeInfo); - WriteSaveBuf(buf, m_nAntiReverseTimer); - WriteSaveBuf(buf, m_nTimeToStartMission); - WriteSaveBuf(buf, m_nPreviousDirection); - WriteSaveBuf(buf, m_nCurrentDirection); - WriteSaveBuf(buf, m_nNextDirection); - WriteSaveBuf(buf, m_nCurrentLane); - WriteSaveBuf(buf, m_nNextLane); - WriteSaveBuf(buf, m_nDrivingStyle); - WriteSaveBuf(buf, m_nCarMission); - WriteSaveBuf(buf, m_nTempAction); - WriteSaveBuf(buf, m_nTimeTempAction); - WriteSaveBuf(buf, m_fMaxTrafficSpeed); - WriteSaveBuf(buf, m_nCruiseSpeed); - WriteSaveBuf(buf, m_nCruiseSpeedMultiplierType); - SkipSaveBuf(buf, 2); - WriteSaveBuf(buf, m_fCruiseSpeedMultiplier); + WriteSaveBuf(buf, m_nCurrentRouteNode); + WriteSaveBuf(buf, m_nNextRouteNode); + WriteSaveBuf(buf, m_nPrevRouteNode); + WriteSaveBuf(buf, m_nTimeEnteredCurve); + WriteSaveBuf(buf, m_nTimeToSpendOnCurrentCurve); + WriteSaveBuf(buf, m_nCurrentPathNodeInfo); + WriteSaveBuf(buf, m_nNextPathNodeInfo); + WriteSaveBuf(buf, m_nPreviousPathNodeInfo); + WriteSaveBuf(buf, m_nAntiReverseTimer); + WriteSaveBuf(buf, m_nTimeToStartMission); + WriteSaveBuf(buf, m_nPreviousDirection); + WriteSaveBuf(buf, m_nCurrentDirection); + WriteSaveBuf(buf, m_nNextDirection); + WriteSaveBuf(buf, m_nCurrentLane); + WriteSaveBuf(buf, m_nNextLane); + WriteSaveBuf(buf, m_nDrivingStyle); + WriteSaveBuf(buf, m_nCarMission); + WriteSaveBuf(buf, m_nTempAction); + WriteSaveBuf(buf, m_nTimeTempAction); + WriteSaveBuf(buf, m_fMaxTrafficSpeed); + WriteSaveBuf(buf, m_nCruiseSpeed); + WriteSaveBuf(buf, m_nCruiseSpeedMultiplierType); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_fCruiseSpeedMultiplier); uint8 flags = 0; if (m_bSlowedDownBecauseOfCars) flags |= BIT(0); if (m_bSlowedDownBecauseOfPeds) flags |= BIT(1); if (m_bStayInCurrentLevel) flags |= BIT(2); if (m_bStayInFastLane) flags |= BIT(3); if (m_bIgnorePathfinding) flags |= BIT(4); - WriteSaveBuf(buf, flags); - WriteSaveBuf(buf, m_nSwitchDistance); - SkipSaveBuf(buf, 2); - WriteSaveBuf(buf, m_vecDestinationCoors.x); - WriteSaveBuf(buf, m_vecDestinationCoors.y); - WriteSaveBuf(buf, m_vecDestinationCoors.z); - SkipSaveBuf(buf, 32); - WriteSaveBuf(buf, m_nPathFindNodesCount); - SkipSaveBuf(buf, 6); + WriteSaveBuf(buf, flags); + WriteSaveBuf(buf, m_nSwitchDistance); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_vecDestinationCoors.x); + WriteSaveBuf(buf, m_vecDestinationCoors.y); + WriteSaveBuf(buf, m_vecDestinationCoors.z); + ZeroSaveBuf(buf, 32); + WriteSaveBuf(buf, m_nPathFindNodesCount); + ZeroSaveBuf(buf, 6); } void CAutoPilot::Load(uint8*& buf) diff --git a/src/control/Garages.cpp b/src/control/Garages.cpp index 73d0781c..cbf17be9 100644 --- a/src/control/Garages.cpp +++ b/src/control/Garages.cpp @@ -29,13 +29,6 @@ #include "VarConsole.h" #include "SaveBuf.h" -#define CRUSHER_GARAGE_X1 (1135.5f) -#define CRUSHER_GARAGE_Y1 (57.0f) -#define CRUSHER_GARAGE_Z1 (-1.0f) -#define CRUSHER_GARAGE_X2 (1149.5f) -#define CRUSHER_GARAGE_Y2 (63.7f) -#define CRUSHER_GARAGE_Z2 (3.5f) - #define ROTATED_DOOR_OPEN_SPEED (0.015f) #define ROTATED_DOOR_CLOSE_SPEED (0.02f) #define DEFAULT_DOOR_OPEN_SPEED (0.035f) @@ -2640,8 +2633,53 @@ void CGarages::Save(uint8 * buf, uint32 * size) WriteSaveBuf(buf, aCarsInSafeHouses[j][i]); } } - for (int i = 0; i < NUM_GARAGES; i++) + for (int i = 0; i < NUM_GARAGES; i++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aGarages[i].m_eGarageType); + WriteSaveBuf(buf, aGarages[i].m_eGarageState); + WriteSaveBuf(buf, aGarages[i].m_nMaxStoredCars); + WriteSaveBuf(buf, aGarages[i].field_2); + WriteSaveBuf(buf, aGarages[i].m_bClosingWithoutTargetCar); + WriteSaveBuf(buf, aGarages[i].m_bDeactivated); + WriteSaveBuf(buf, aGarages[i].m_bResprayHappened); + ZeroSaveBuf(buf, 1); + WriteSaveBuf(buf, aGarages[i].m_nTargetModelIndex); + ZeroSaveBuf(buf, 4 + 4); + WriteSaveBuf(buf, aGarages[i].m_bDoor1PoolIndex); + WriteSaveBuf(buf, aGarages[i].m_bDoor2PoolIndex); + WriteSaveBuf(buf, aGarages[i].m_bDoor1IsDummy); + WriteSaveBuf(buf, aGarages[i].m_bDoor2IsDummy); + WriteSaveBuf(buf, aGarages[i].m_bRecreateDoorOnNextRefresh); + WriteSaveBuf(buf, aGarages[i].m_bRotatedDoor); + WriteSaveBuf(buf, aGarages[i].m_bCameraFollowsPlayer); + ZeroSaveBuf(buf, 1); + WriteSaveBuf(buf, aGarages[i].m_vecCorner1); + WriteSaveBuf(buf, aGarages[i].m_fInfZ); + WriteSaveBuf(buf, aGarages[i].m_vDir1); + WriteSaveBuf(buf, aGarages[i].m_vDir2); + WriteSaveBuf(buf, aGarages[i].m_fSupZ); + WriteSaveBuf(buf, aGarages[i].m_fDir1Len); + WriteSaveBuf(buf, aGarages[i].m_fDir2Len); + WriteSaveBuf(buf, aGarages[i].m_fInfX); + WriteSaveBuf(buf, aGarages[i].m_fSupX); + WriteSaveBuf(buf, aGarages[i].m_fInfY); + WriteSaveBuf(buf, aGarages[i].m_fSupY); + WriteSaveBuf(buf, aGarages[i].m_fDoorPos); + WriteSaveBuf(buf, aGarages[i].m_fDoorHeight); + WriteSaveBuf(buf, aGarages[i].m_fDoor1X); + WriteSaveBuf(buf, aGarages[i].m_fDoor1Y); + WriteSaveBuf(buf, aGarages[i].m_fDoor2X); + WriteSaveBuf(buf, aGarages[i].m_fDoor2Y); + WriteSaveBuf(buf, aGarages[i].m_fDoor1Z); + WriteSaveBuf(buf, aGarages[i].m_fDoor2Z); + WriteSaveBuf(buf, aGarages[i].m_nTimeToStartAction); + WriteSaveBuf(buf, aGarages[i].m_bCollectedCarsState); + ZeroSaveBuf(buf, 3 + 4); + ZeroSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar)); +#else WriteSaveBuf(buf, aGarages[i]); +#endif + } //VALIDATESAVEBUF(*size); } @@ -2669,7 +2707,51 @@ void CGarages::Load(uint8* buf, uint32 size) } } for (int i = 0; i < NUM_GARAGES; i++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&aGarages[i].m_eGarageType, buf); + ReadSaveBuf(&aGarages[i].m_eGarageState, buf); + ReadSaveBuf(&aGarages[i].m_nMaxStoredCars, buf); + ReadSaveBuf(&aGarages[i].field_2, buf); + ReadSaveBuf(&aGarages[i].m_bClosingWithoutTargetCar, buf); + ReadSaveBuf(&aGarages[i].m_bDeactivated, buf); + ReadSaveBuf(&aGarages[i].m_bResprayHappened, buf); + SkipSaveBuf(buf, 1); + ReadSaveBuf(&aGarages[i].m_nTargetModelIndex, buf); + SkipSaveBuf(buf, 4 + 4); + ReadSaveBuf(&aGarages[i].m_bDoor1PoolIndex, buf); + ReadSaveBuf(&aGarages[i].m_bDoor2PoolIndex, buf); + ReadSaveBuf(&aGarages[i].m_bDoor1IsDummy, buf); + ReadSaveBuf(&aGarages[i].m_bDoor2IsDummy, buf); + ReadSaveBuf(&aGarages[i].m_bRecreateDoorOnNextRefresh, buf); + ReadSaveBuf(&aGarages[i].m_bRotatedDoor, buf); + ReadSaveBuf(&aGarages[i].m_bCameraFollowsPlayer, buf); + SkipSaveBuf(buf, 1); + ReadSaveBuf(&aGarages[i].m_vecCorner1, buf); + ReadSaveBuf(&aGarages[i].m_fInfZ, buf); + ReadSaveBuf(&aGarages[i].m_vDir1, buf); + ReadSaveBuf(&aGarages[i].m_vDir2, buf); + ReadSaveBuf(&aGarages[i].m_fSupZ, buf); + ReadSaveBuf(&aGarages[i].m_fDir1Len, buf); + ReadSaveBuf(&aGarages[i].m_fDir2Len, buf); + ReadSaveBuf(&aGarages[i].m_fInfX, buf); + ReadSaveBuf(&aGarages[i].m_fSupX, buf); + ReadSaveBuf(&aGarages[i].m_fInfY, buf); + ReadSaveBuf(&aGarages[i].m_fSupY, buf); + ReadSaveBuf(&aGarages[i].m_fDoorPos, buf); + ReadSaveBuf(&aGarages[i].m_fDoorHeight, buf); + ReadSaveBuf(&aGarages[i].m_fDoor1X, buf); + ReadSaveBuf(&aGarages[i].m_fDoor1Y, buf); + ReadSaveBuf(&aGarages[i].m_fDoor2X, buf); + ReadSaveBuf(&aGarages[i].m_fDoor2Y, buf); + ReadSaveBuf(&aGarages[i].m_fDoor1Z, buf); + ReadSaveBuf(&aGarages[i].m_fDoor2Z, buf); + ReadSaveBuf(&aGarages[i].m_nTimeToStartAction, buf); + ReadSaveBuf(&aGarages[i].m_bCollectedCarsState, buf); + SkipSaveBuf(buf, 3 + 4); + SkipSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar)); +#else ReadSaveBuf(&aGarages[i], buf); +#endif aGarages[i].m_pDoor1 = nil; aGarages[i].m_pDoor2 = nil; aGarages[i].m_pTarget = nil; diff --git a/src/control/Garages.h b/src/control/Garages.h index 2ab74606..5230b657 100644 --- a/src/control/Garages.h +++ b/src/control/Garages.h @@ -115,7 +115,7 @@ public: bool m_bClosingWithoutTargetCar; bool m_bDeactivated; bool m_bResprayHappened; - int m_nTargetModelIndex; + int32 m_nTargetModelIndex; CEntity *m_pDoor1; CEntity *m_pDoor2; uint8 m_bDoor1PoolIndex; diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp index a962052f..41f9d766 100644 --- a/src/control/Phones.cpp +++ b/src/control/Phones.cpp @@ -18,6 +18,12 @@ #include "Replay.h" #endif +#ifdef COMPATIBLE_SAVES +#define PHONEINFO_SAVE_SIZE 0xA30 +#else +#define PHONEINFO_SAVE_SIZE sizeof(CPhoneInfo) +#endif + CPhoneInfo gPhoneInfo; bool CPhoneInfo::bDisplayingPhoneMessage; // is phone picked up @@ -201,11 +207,24 @@ INITSAVEBUF ReadSaveBuf(&m_nMax, buf); ReadSaveBuf(&m_nScriptPhonesMax, buf); for (int i = 0; i < NUMPHONES; i++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&m_aPhones[i].m_vecPos, buf); + SkipSaveBuf(buf, 6 * 4); + ReadSaveBuf(&m_aPhones[i].m_repeatedMessagePickupStart, buf); + int32 tmp; + ReadSaveBuf(&tmp, buf); + // It's saved as building pool index in save file, convert it to true entity + m_aPhones[i].m_pEntity = tmp != 0 ? CPools::GetBuildingPool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&m_aPhones[i].m_nState, buf); + ReadSaveBuf(&m_aPhones[i].m_visibleToCam, buf); + SkipSaveBuf(buf, 3); +#else ReadSaveBuf(&m_aPhones[i], buf); // It's saved as building pool index in save file, convert it to true entity if (m_aPhones[i].m_pEntity) { m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((uintptr)m_aPhones[i].m_pEntity - 1); } +#endif } VALIDATESAVEBUF(size) } @@ -299,17 +318,29 @@ CPhoneInfo::Initialise(void) void CPhoneInfo::Save(uint8 *buf, uint32 *size) { - *size = sizeof(CPhoneInfo); + *size = PHONEINFO_SAVE_SIZE; INITSAVEBUF WriteSaveBuf(buf, m_nMax); WriteSaveBuf(buf, m_nScriptPhonesMax); for(int phoneId = 0; phoneId < NUMPHONES; phoneId++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, m_aPhones[phoneId].m_vecPos); + ZeroSaveBuf(buf, 6 * 4); + WriteSaveBuf(buf, m_aPhones[phoneId].m_repeatedMessagePickupStart); + // Convert entity pointer to building pool index while saving + int32 tmp = m_aPhones[phoneId].m_pEntity ? CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)m_aPhones[phoneId].m_pEntity) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, m_aPhones[phoneId].m_nState); + WriteSaveBuf(buf, m_aPhones[phoneId].m_visibleToCam); + ZeroSaveBuf(buf, 3); +#else CPhone* phone = WriteSaveBuf(buf, m_aPhones[phoneId]); // Convert entity pointer to building pool index while saving if (phone->m_pEntity) { phone->m_pEntity = (CEntity*) (CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert((CBuilding*)phone->m_pEntity) + 1); } +#endif } VALIDATESAVEBUF(*size) } diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp index b0b0952f..9233a172 100644 --- a/src/control/Pickups.cpp +++ b/src/control/Pickups.cpp @@ -35,6 +35,12 @@ #include "Streaming.h" #include "SaveBuf.h" +#ifdef COMPATIBLE_SAVES +#define PICKUPS_SAVE_SIZE 0x4440 +#else +#define PICKUPS_SAVE_SIZE sizeof(aPickUps) +#endif + CPickup CPickups::aPickUps[NUMPICKUPS]; int16 CPickups::NumMessages; int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS]; @@ -1442,6 +1448,31 @@ CPickups::Load(uint8 *buf, uint32 size) INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&aPickUps[i].m_vecPos, buf); + ReadSaveBuf(&aPickUps[i].m_fRevenue, buf); + int32 tmp_pObject; + ReadSaveBuf(&tmp_pObject, buf); + int32 tmp_pExtraObject; + ReadSaveBuf(&tmp_pExtraObject, buf); + ReadSaveBuf(&aPickUps[i].m_nQuantity, buf); + ReadSaveBuf(&aPickUps[i].m_nTimer, buf); + ReadSaveBuf(&aPickUps[i].m_nMoneySpeed, buf); + ReadSaveBuf(&aPickUps[i].m_eModelIndex, buf); + ReadSaveBuf(&aPickUps[i].m_nIndex, buf); + memcpy(aPickUps[i].m_sTextKey, buf, sizeof(aPickUps[i].m_sTextKey)); + SkipSaveBuf(buf, sizeof(aPickUps[i].m_sTextKey)); + ReadSaveBuf(&aPickUps[i].m_eType, buf); + ReadSaveBuf(&aPickUps[i].m_bRemoved, buf); + uint8 flags; + ReadSaveBuf(&flags, buf); + aPickUps[i].m_bWasAmmoCollected = !!(flags & BIT(0)); + aPickUps[i].m_bWasControlMessageShown = !!(flags & BIT(1)); + SkipSaveBuf(buf, 3); + + aPickUps[i].m_pObject = aPickUps[i].m_eType != PICKUP_NONE && tmp_pObject != 0 ? CPools::GetObjectPool()->GetSlot(tmp_pObject - 1) : nil; + aPickUps[i].m_pExtraObject = aPickUps[i].m_eType != PICKUP_NONE && tmp_pExtraObject != 0 ? CPools::GetObjectPool()->GetSlot(tmp_pExtraObject - 1) : nil; +#else ReadSaveBuf(&aPickUps[i], buf); if (aPickUps[i].m_eType != PICKUP_NONE) { @@ -1450,7 +1481,7 @@ INITSAVEBUF if (aPickUps[i].m_pExtraObject != nil) aPickUps[i].m_pExtraObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pExtraObject - 1); } - +#endif } ReadSaveBuf(&CollectedPickUpIndex, buf); @@ -1466,12 +1497,34 @@ VALIDATESAVEBUF(size) void CPickups::Save(uint8 *buf, uint32 *size) { - *size = sizeof(aPickUps); + *size = PICKUPS_SAVE_SIZE; *size += sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected); INITSAVEBUF for (int32 i = 0; i < NUMPICKUPS; i++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aPickUps[i].m_vecPos); + WriteSaveBuf(buf, aPickUps[i].m_fRevenue); + int32 tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pObject) + 1 : 0; + WriteSaveBuf(buf, tmp); + tmp = aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pExtraObject != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aPickUps[i].m_pExtraObject) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, aPickUps[i].m_nQuantity); + WriteSaveBuf(buf, aPickUps[i].m_nTimer); + WriteSaveBuf(buf, aPickUps[i].m_nMoneySpeed); + WriteSaveBuf(buf, aPickUps[i].m_eModelIndex); + WriteSaveBuf(buf, aPickUps[i].m_nIndex); + memcpy(buf, aPickUps[i].m_sTextKey, sizeof(aPickUps[i].m_sTextKey)); + SkipSaveBuf(buf, sizeof(aPickUps[i].m_sTextKey)); + WriteSaveBuf(buf, aPickUps[i].m_eType); + WriteSaveBuf(buf, aPickUps[i].m_bRemoved); + uint8 flags = 0; + if (aPickUps[i].m_bWasAmmoCollected) flags |= BIT(0); + if (aPickUps[i].m_bWasControlMessageShown) flags |= BIT(1); + WriteSaveBuf(buf, flags); + ZeroSaveBuf(buf, 3); +#else CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]); if (buf_pickup->m_eType != PICKUP_NONE) { if (buf_pickup->m_pObject != nil) @@ -1479,6 +1532,7 @@ INITSAVEBUF if (buf_pickup->m_pExtraObject != nil) buf_pickup->m_pExtraObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pExtraObject) + 1); } +#endif } WriteSaveBuf(buf, CollectedPickUpIndex); diff --git a/src/control/Script5.cpp b/src/control/Script5.cpp index 88054f3f..f6036b50 100644 --- a/src/control/Script5.cpp +++ b/src/control/Script5.cpp @@ -2314,35 +2314,35 @@ VALIDATESAVEBUF(size) void CRunningScript::Save(uint8*& buf) { #ifdef COMPATIBLE_SAVES - SkipSaveBuf(buf, 8); + ZeroSaveBuf(buf, 8); WriteSaveBuf(buf, m_nId); for (int i = 0; i < 8; i++) - WriteSaveBuf(buf, m_abScriptName[i]); - WriteSaveBuf(buf, m_nIp); + WriteSaveBuf(buf, m_abScriptName[i]); + WriteSaveBuf(buf, m_nIp); #ifdef CHECK_STRUCT_SIZES static_assert(MAX_STACK_DEPTH == 6, "Compatibility loss: MAX_STACK_DEPTH != 6"); #endif for (int i = 0; i < MAX_STACK_DEPTH; i++) - WriteSaveBuf(buf, m_anStack[i]); - WriteSaveBuf(buf, m_nStackPointer); - SkipSaveBuf(buf, 2); + WriteSaveBuf(buf, m_anStack[i]); + WriteSaveBuf(buf, m_nStackPointer); + ZeroSaveBuf(buf, 2); #ifdef CHECK_STRUCT_SIZES static_assert(NUM_LOCAL_VARS + 8 + NUM_TIMERS == 106, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 106"); #endif for (int i = 0; i < NUM_LOCAL_VARS + 8 + NUM_TIMERS; i++) - WriteSaveBuf(buf, m_anLocalVariables[i]); - WriteSaveBuf(buf, m_nLocalsPointer); - WriteSaveBuf(buf, m_bIsActive); - WriteSaveBuf(buf, m_bCondResult); - WriteSaveBuf(buf, m_bIsMissionScript); - WriteSaveBuf(buf, m_bSkipWakeTime); - WriteSaveBuf(buf, m_nWakeTime); - WriteSaveBuf(buf, m_nAndOrState); - WriteSaveBuf(buf, m_bNotFlag); - WriteSaveBuf(buf, m_bDeatharrestEnabled); - WriteSaveBuf(buf, m_bDeatharrestExecuted); - WriteSaveBuf(buf, m_bMissionFlag); - SkipSaveBuf(buf, 2); + WriteSaveBuf(buf, m_anLocalVariables[i]); + WriteSaveBuf(buf, m_nLocalsPointer); + WriteSaveBuf(buf, m_bIsActive); + WriteSaveBuf(buf, m_bCondResult); + WriteSaveBuf(buf, m_bIsMissionScript); + WriteSaveBuf(buf, m_bSkipWakeTime); + WriteSaveBuf(buf, m_nWakeTime); + WriteSaveBuf(buf, m_nAndOrState); + WriteSaveBuf(buf, m_bNotFlag); + WriteSaveBuf(buf, m_bDeatharrestEnabled); + WriteSaveBuf(buf, m_bDeatharrestExecuted); + WriteSaveBuf(buf, m_bMissionFlag); + ZeroSaveBuf(buf, 2); #else WriteSaveBuf(buf, *this); #endif diff --git a/src/core/Placeable.h b/src/core/Placeable.h index 9c8c292a..94be3211 100644 --- a/src/core/Placeable.h +++ b/src/core/Placeable.h @@ -33,4 +33,4 @@ public: bool IsWithinArea(float x1, float y1, float z1, float x2, float y2, float z2); }; -VALIDATE_SIZE(CPlaceable, 0x4C); +VALIDATE_SIZE(CPlaceable, 0x48); diff --git a/src/core/Pools.cpp b/src/core/Pools.cpp index d1947813..a85d6846 100644 --- a/src/core/Pools.cpp +++ b/src/core/Pools.cpp @@ -310,9 +310,9 @@ INITSAVEBUF #else if ((pVehicle->IsCar() || pVehicle->IsBoat() || pVehicle->IsBike()) && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf(buf, pVehicle->m_vehType); - WriteSaveBuf(buf, pVehicle->GetModelIndex()); - WriteSaveBuf(buf, GetVehicleRef(pVehicle)); + WriteSaveBuf(buf, pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->GetModelIndex()); + WriteSaveBuf(buf, GetVehicleRef(pVehicle)); pVehicle->Save(buf); } #else @@ -321,7 +321,7 @@ INITSAVEBUF #else if (pVehicle->IsCar() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, GetVehicleRef(pVehicle)); memcpy(buf, pVehicle, sizeof(CAutomobile)); @@ -332,7 +332,7 @@ INITSAVEBUF #else if (pVehicle->IsBoat() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, GetVehicleRef(pVehicle)); memcpy(buf, pVehicle, sizeof(CBoat)); @@ -343,7 +343,7 @@ INITSAVEBUF #else if (pVehicle->IsBike() && pVehicle->VehicleCreatedBy == MISSION_VEHICLE) { #endif - WriteSaveBuf(buf, (uint32)pVehicle->m_vehType); + WriteSaveBuf(buf, pVehicle->m_vehType); WriteSaveBuf(buf, pVehicle->GetModelIndex()); WriteSaveBuf(buf, GetVehicleRef(pVehicle)); memcpy(buf, pVehicle, sizeof(CBike)); diff --git a/src/core/Stats.cpp b/src/core/Stats.cpp index 7ada0da9..8c6137f2 100644 --- a/src/core/Stats.cpp +++ b/src/core/Stats.cpp @@ -1229,7 +1229,11 @@ CStats::ConstructStatLine(int rowIdx) FASTEST_TIME(20, "STFT_21"); if (FastestTimes[21]) +#ifdef FIX_BUGS + STAT_LINE_1(float, "STFT_22", Floor(FastestTimes[21] / 10) / 100, 1); +#else STAT_LINE_1(float, "STFT_22", FastestTimes[21] / 1000, 1); +#endif if (TopShootingRangeScore > 0.0f) STAT_LINE_1(int, "TOP_SHO", TopShootingRangeScore, 0); diff --git a/src/core/config.h b/src/core/config.h index ca0aadc5..c8fca082 100644 --- a/src/core/config.h +++ b/src/core/config.h @@ -1,7 +1,9 @@ #pragma once -// disables (most) stuff that wasn't in original gta-vc.exe - check section at the bottom of this file -//#define VANILLA_DEFINES +// disables (most) stuff that wasn't in original gta-vc.exe +#ifdef __MWERKS__ +#define VANILLA_DEFINES +#endif enum Config { NUMPLAYERS = 1, @@ -154,8 +156,36 @@ enum Config { //#define GTA_PS2 //#define GTA_XBOX -// This enables things from the PS2 version on PC -#define GTA_PS2_STUFF +#define GTA_TRAIN +#define GTA_BRIDGE + +// Version defines +#define GTAVC_PS2 400 +#define GTAVC_PC_10 410 +#define GTAVC_PC_11 411 +#define GTAVC_PC_JAP 412 +// TODO? maybe something for xbox or android? + +#define GTA_VERSION GTAVC_PC_11 + +// TODO(MIAMI): someone ought to find and check out uses of these defines: +//#define GTA3_STEAM_PATCH +//#define GTAVC_JP_PATCH + +#if defined GTA_PS2 +# define GTA_PS2_STUFF +# define RANDOMSPLASH +//# define USE_CUSTOM_ALLOCATOR +# define VU_COLLISION +# define PS2_MENU +#elif defined GTA_PC +# define PC_PLAYER_CONTROLS // mouse player/cam mode +//# define GTA_REPLAY +# define GTA_SCENE_EDIT +# define PC_MENU +# define PC_WATER +#elif defined GTA_XBOX +#endif // This is enabled for all released games. // any debug stuff that isn't left in any game is not in FINAL @@ -174,22 +204,24 @@ enum Config { #define FINAL #endif -// Version defines -#define GTAVC_PS2 400 -#define GTAVC_PC_10 410 -#define GTAVC_PC_11 411 -#define GTAVC_PC_JAP 412 -// TODO? maybe something for xbox or android? - -#define GTA_VERSION GTAVC_PC_11 +// these are placed here to work with VANILLA_DEFINES for compatibility +#define NO_CDCHECK // skip audio CD check +#define DEFAULT_NATIVE_RESOLUTION // Set default video mode to your native resolution (fixes Windows 10 launch) -// TODO(MIAMI): someone ought to find and check out uses of these defines: -//#define GTA3_STEAM_PATCH -//#define GTAVC_JP_PATCH +#ifdef VANILLA_DEFINES +#define FINAL +#define MASTER +//#define USE_MY_DOCUMENTS +#define THIS_IS_STUPID +#define DONT_FIX_REPLAY_BUGS +#define USE_TXD_CDIMAGE // generate and load textures from txd.img +//#define USE_TEXTURE_POOL // not possible because R* used custom RW33 +#else +// This enables things from the PS2 version on PC +#define GTA_PS2_STUFF // quality of life fixes that should also be in FINAL #define NASTY_GAME // nasty game for all languages -#define NO_CDCHECK // those infamous texts #define DRAW_GAME_VERSION_TEXT @@ -204,24 +236,10 @@ enum Config { //#define COMPRESSED_COL_VECTORS // use compressed vectors for collision vertices //#define ANIM_COMPRESSION // only keep most recently used anims uncompressed -#define GTA_TRAIN -#define GTA_BRIDGE - -#if defined GTA_PS2 -# define GTA_PS2_STUFF -# define RANDOMSPLASH -//# define USE_CUSTOM_ALLOCATOR -# define VU_COLLISION -#elif defined GTA_PC -# ifdef GTA_PS2_STUFF -# define USE_PS2_RAND -# define RANDOMSPLASH // use random splash as on PS2 -# define PS2_MATFX -# endif -# define PC_PLAYER_CONTROLS // mouse player/cam mode -//# define GTA_REPLAY -# define GTA_SCENE_EDIT -#elif defined GTA_XBOX +#if defined GTA_PC && defined GTA_PS2_STUFF +# define USE_PS2_RAND +# define RANDOMSPLASH // use random splash as on PS2 +# define PS2_MATFX #endif #ifdef VU_COLLISION @@ -249,7 +267,8 @@ enum Config { #define FIX_BUGS // fixes bugs that we've came across during reversing. You can undefine this only on release builds. //#define MORE_LANGUAGES // Add more translations to the game -#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible +#define COMPATIBLE_SAVES // this allows changing structs while keeping saves compatible, and keeps saves compatible between platforms +#define FIX_INCOMPATIBLE_SAVES // try to fix incompatible saves, requires COMPATIBLE_SAVES #define LOAD_INI_SETTINGS // as the name suggests. fundamental for CUSTOM_FRONTEND_OPTIONS #define NO_MOVIES // add option to disable intro videos @@ -260,7 +279,7 @@ enum Config { #define ASCII_STRCMP // use faster ascii str comparisons -#if !defined _WIN32 || defined __MWERKS__ || defined __MINGW32__ || defined VANILLA_DEFINES +#if !defined _WIN32 || defined __MINGW32__ #undef ASCII_STRCMP #endif @@ -295,7 +314,7 @@ enum Config { #endif // Water & Particle -// #define PC_WATER +#undef PC_WATER #define WATER_CHEATS //#define PSP_WATERCANNON @@ -432,97 +451,4 @@ static_assert(false, "SUPPORT_XBOX_SCRIPT and SUPPORT_MOBILE_SCRIPT are mutually #undef PS2_AUDIO_CHANNELS #endif -// ------- - -#if defined __MWERKS__ || defined VANILLA_DEFINES -#define FINAL -#undef CHATTYSPLASH -#undef TIMEBARS - -#define MASTER -#undef VALIDATE_SAVE_SIZE -#undef NO_MOVIES -#undef DEBUGMENU - -#undef DRAW_GAME_VERSION_TEXT - -//#undef NASTY_GAME -//#undef NO_CDCHECK - -#undef GTA_PS2_STUFF -#undef USE_PS2_RAND -#undef RANDOMSPLASH -#undef PS2_MATFX - -#undef FIX_BUGS -#define THIS_IS_STUPID -#undef MORE_LANGUAGES -#undef COMPATIBLE_SAVES -#undef LOAD_INI_SETTINGS - -#undef ASPECT_RATIO_SCALE -#undef PROPER_SCALING -//#undef DEFAULT_NATIVE_RESOLUTION -#undef PS2_ALPHA_TEST -#undef IMPROVED_VIDEOMODE -#undef DISABLE_LOADING_SCREEN -#undef DISABLE_VSYNC_ON_TEXTURE_CONVERSION - -#undef EXTENDED_COLOURFILTER -#undef EXTENDED_PIPELINES -#undef SCREEN_DROPLETS -#undef NEW_RENDERER - -#undef FIX_SPRITES - -#define PC_WATER -#undef WATER_CHEATS - -#undef USE_CUTSCENE_SHADOW_FOR_PED -#undef DISABLE_CUTSCENE_SHADOWS - -#undef XINPUT -#undef DETECT_PAD_INPUT_SWITCH -#undef KANGAROO_CHEAT -#undef RESTORE_ALLCARSHELI_CHEAT -#undef BETTER_ALLCARSAREDODO_CHEAT -#undef WALLCLIMB_CHEAT -#undef REGISTER_START_BUTTON -#undef BIND_VEHICLE_FIREWEAPON -#undef BUTTON_ICONS - -#undef FIX_RADAR -#undef RADIO_OFF_TEXT - -#undef MAP_ENHANCEMENTS -#undef GAMEPAD_MENU -#undef MUCH_SHORTER_OUTRO_SCREEN -#undef CUSTOM_FRONTEND_OPTIONS - -#undef GRAPHICS_MENU_OPTIONS -#undef NO_ISLAND_LOADING -#undef CUTSCENE_BORDERS_SWITCH -#undef MULTISAMPLING -#undef INVERT_LOOK_FOR_PAD - -#undef USE_DEBUG_SCRIPT_LOADER -#undef USE_MEASUREMENTS_IN_METERS -#undef USE_PRECISE_MEASUREMENT_CONVERTION -#undef SUPPORT_JAPANESE_SCRIPT -#undef MISSION_REPLAY -#undef USE_ADVANCED_SCRIPT_DEBUG_OUTPUT -#undef USE_BASIC_SCRIPT_DEBUG_OUTPUT - -#define DONT_FIX_REPLAY_BUGS - -#undef EXPLODING_AIRTRAIN -#undef CPLANE_ROTORS -#undef CAMERA_PICKUP -#undef CANCELLABLE_CAR_ENTER -#undef IMPROVED_CAMERA -#undef FREE_CAM -#undef BIG_IMG -#undef PS2_AUDIO_CHANNELS -#undef MULTITHREADED_AUDIO -#undef RADIO_SCROLL_TO_PREV_STATION -#endif +#endif // VANILLA_DEFINES diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 83c65eeb..cd50923a 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -901,7 +901,7 @@ CEntity::SaveEntityFlags(uint8*& buf) if (bStreamingDontDelete) tmp |= BIT(30); if (bRemoveFromWorld) tmp |= BIT(31); - WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, tmp); tmp = 0; @@ -922,7 +922,7 @@ CEntity::SaveEntityFlags(uint8*& buf) if (bUnderwater) tmp |= BIT(13); if (bHasPreRenderEffects) tmp |= BIT(14); - WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, tmp); } void diff --git a/src/entities/Physical.cpp b/src/entities/Physical.cpp index 69110a83..fd635b90 100644 --- a/src/entities/Physical.cpp +++ b/src/entities/Physical.cpp @@ -529,6 +529,10 @@ CPhysical::ApplySpringDampening(float damping, float dampingLimit, CVector &spri { float speedA = DotProduct(speed, springDir); float speedB = DotProduct(GetSpeed(point), springDir); +#ifdef FIX_BUGS + if (speedB == 0.0f) + return true; +#endif float step = Min(CTimer::GetTimeStep(), 3.0f); damping *= step; if(bIsHeavy) diff --git a/src/objects/ParticleObject.cpp b/src/objects/ParticleObject.cpp index defd1995..c49044a0 100644 --- a/src/objects/ParticleObject.cpp +++ b/src/objects/ParticleObject.cpp @@ -10,6 +10,12 @@ #include "DMAudio.h" #include "screendroplets.h" +#ifdef COMPATIBLE_SAVES +#define PARTICLE_OBJECT_SIZEOF 0x84 +#else +#define PARTICLE_OBJECT_SIZEOF sizeof(CParticleObject) +#endif + CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS]; @@ -1062,6 +1068,48 @@ CParticleObject::UpdateFar(void) } } +#ifdef COMPATIBLE_SAVES +static inline void +SaveOneParticle(CParticleObject *p, uint8 *&buffer) +{ +#define SkipBuf(buf, num) buf += num +#define ZeroBuf(buf, num) memset(buf, 0, num); SkipBuf(buf, num) +#define CopyToBuf(buf, data) memcpy(buf, &data, sizeof(data)); SkipBuf(buf, sizeof(data)) + // CPlaceable + { + CopyToBuf(buffer, p->GetMatrix().f); + ZeroBuf(buffer, 4); + CopyToBuf(buffer, p->GetMatrix().m_hasRwMatrix); + ZeroBuf(buffer, 3); + } + + // CParticleObject + { + ZeroBuf(buffer, 4); + ZeroBuf(buffer, 4); + ZeroBuf(buffer, 4); + CopyToBuf(buffer, p->m_nRemoveTimer); + CopyToBuf(buffer, p->m_Type); + CopyToBuf(buffer, p->m_ParticleType); + CopyToBuf(buffer, p->m_nNumEffectCycles); + CopyToBuf(buffer, p->m_nSkipFrames); + CopyToBuf(buffer, p->m_nFrameCounter); + CopyToBuf(buffer, p->m_nState); + ZeroBuf(buffer, 2); + CopyToBuf(buffer, p->m_vecTarget); + CopyToBuf(buffer, p->m_fRandVal); + CopyToBuf(buffer, p->m_fSize); + CopyToBuf(buffer, p->m_Color); + CopyToBuf(buffer, p->m_bRemove); + CopyToBuf(buffer, p->m_nCreationChance); + ZeroBuf(buffer, 2); + } +#undef SkipBuf +#undef ZeroBuf +#undef CopyToBuf +} +#endif + bool CParticleObject::SaveParticle(uint8 *buffer, uint32 *length) { @@ -1079,27 +1127,35 @@ CParticleObject::SaveParticle(uint8 *buffer, uint32 *length) *(int32 *)buffer = numObjects; buffer += sizeof(int32); - int32 objectsLength = sizeof(CParticleObject) * (numObjects + 1); + int32 objectsLength = PARTICLE_OBJECT_SIZEOF * (numObjects + 1); int32 dataLength = objectsLength + sizeof(int32); for ( CParticleObject *p = pCloseListHead; p != nil; p = p->m_pNext ) { -#if 0 // todo better +#ifdef COMPATIBLE_SAVES + SaveOneParticle(p, buffer); +#else +#ifdef THIS_IS_STUPID *(CParticleObject*)buffer = *p; #else memcpy(buffer, p, sizeof(CParticleObject)); #endif buffer += sizeof(CParticleObject); +#endif } for ( CParticleObject *p = pFarListHead; p != nil; p = p->m_pNext ) { -#if 0 // todo better +#ifdef COMPATIBLE_SAVES + SaveOneParticle(p, buffer); +#else +#ifdef THIS_IS_STUPID *(CParticleObject*)buffer = *p; #else memcpy(buffer, p, sizeof(CParticleObject)); #endif buffer += sizeof(CParticleObject); +#endif } *length = dataLength; @@ -1117,7 +1173,7 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length) int32 numObjects = *(int32 *)buffer; buffer += sizeof(int32); - if ( length != sizeof(CParticleObject) * (numObjects + 1) + sizeof(int32) ) + if ( length != PARTICLE_OBJECT_SIZEOF * (numObjects + 1) + sizeof(int32) ) return false; if ( numObjects == 0 ) @@ -1128,14 +1184,17 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length) while ( i < numObjects ) { CParticleObject *dst = pUnusedListHead; +#ifndef COMPATIBLE_SAVES CParticleObject *src = (CParticleObject *)buffer; buffer += sizeof(CParticleObject); +#endif if ( dst == nil ) return false; MoveToList(&pUnusedListHead, &pCloseListHead, dst); - + +#ifndef COMPATIBLE_SAVES dst->m_nState = POBJECTSTATE_UPDATE_CLOSE; dst->m_Type = src->m_Type; dst->m_ParticleType = src->m_ParticleType; @@ -1151,6 +1210,46 @@ CParticleObject::LoadParticle(uint8 *buffer, uint32 length) dst->m_nNumEffectCycles = src->m_nNumEffectCycles; dst->m_nSkipFrames = src->m_nSkipFrames; dst->m_nCreationChance = src->m_nCreationChance; +#else + dst->m_nState = POBJECTSTATE_UPDATE_CLOSE; + dst->m_pParticle = NULL; + +#define SkipBuf(buf, num) buf += num +#define CopyFromBuf(buf, data) memcpy(&data, buf, sizeof(data)); SkipBuf(buf, sizeof(data)) + // CPlaceable + { + CMatrix matrix; + CopyFromBuf(buffer, matrix.f); + SkipBuf(buffer, 4); + CopyFromBuf(buffer, matrix.m_hasRwMatrix); + SkipBuf(buffer, 3); + dst->SetPosition(matrix.GetPosition()); + } + + // CParticleObject + { + SkipBuf(buffer, 4); + SkipBuf(buffer, 4); + SkipBuf(buffer, 4); + CopyFromBuf(buffer, dst->m_nRemoveTimer); + CopyFromBuf(buffer, dst->m_Type); + CopyFromBuf(buffer, dst->m_ParticleType); + CopyFromBuf(buffer, dst->m_nNumEffectCycles); + CopyFromBuf(buffer, dst->m_nSkipFrames); + CopyFromBuf(buffer, dst->m_nFrameCounter); + SkipBuf(buffer, 2); + SkipBuf(buffer, 2); + CopyFromBuf(buffer, dst->m_vecTarget); + CopyFromBuf(buffer, dst->m_fRandVal); + CopyFromBuf(buffer, dst->m_fSize); + CopyFromBuf(buffer, dst->m_Color); + CopyFromBuf(buffer, dst->m_bRemove); + CopyFromBuf(buffer, dst->m_nCreationChance); + SkipBuf(buffer, 2); + } +#undef CopyFromBuf +#undef SkipBuf +#endif i++; } diff --git a/src/peds/Ped.cpp b/src/peds/Ped.cpp index 4f695e3a..8729ce26 100644 --- a/src/peds/Ped.cpp +++ b/src/peds/Ped.cpp @@ -10136,19 +10136,19 @@ CPed::UnloadNonStandardPedAnim(eWaitState waitState) void CPed::Save(uint8*& buf) { - SkipSaveBuf(buf, 52); + ZeroSaveBuf(buf, 52); CopyToBuf(buf, GetPosition().x); CopyToBuf(buf, GetPosition().y); CopyToBuf(buf, GetPosition().z); - SkipSaveBuf(buf, 288); + ZeroSaveBuf(buf, 288); CopyToBuf(buf, CharCreatedBy); - SkipSaveBuf(buf, 499); + ZeroSaveBuf(buf, 499); CopyToBuf(buf, m_fHealth); CopyToBuf(buf, m_fArmour); - SkipSaveBuf(buf, 172); + ZeroSaveBuf(buf, 172); for (int i = 0; i < 10; i++) // has to be hardcoded m_weapons[i].Save(buf); - SkipSaveBuf(buf, 252); + ZeroSaveBuf(buf, 252); } void diff --git a/src/peds/PlayerPed.cpp b/src/peds/PlayerPed.cpp index c82fe850..047eae10 100644 --- a/src/peds/PlayerPed.cpp +++ b/src/peds/PlayerPed.cpp @@ -2189,14 +2189,14 @@ void CPlayerPed::Save(uint8*& buf) { CPed::Save(buf); - SkipSaveBuf(buf, 16); + ZeroSaveBuf(buf, 16); CopyToBuf(buf, m_fMaxStamina); - SkipSaveBuf(buf, 28); + ZeroSaveBuf(buf, 28); CopyToBuf(buf, m_nTargettableObjects[0]); CopyToBuf(buf, m_nTargettableObjects[1]); CopyToBuf(buf, m_nTargettableObjects[2]); CopyToBuf(buf, m_nTargettableObjects[3]); - SkipSaveBuf(buf, 164); + ZeroSaveBuf(buf, 164); } void diff --git a/src/render/Fluff.cpp b/src/render/Fluff.cpp index b6a7e766..404f1a4a 100644 --- a/src/render/Fluff.cpp +++ b/src/render/Fluff.cpp @@ -25,6 +25,12 @@ #include "Coronas.h" #include "SaveBuf.h" +#ifdef COMPATIBLE_SAVES +#define SCRIPTPATHS_SAVE_SIZE 0x9C +#else +#define SCRIPTPATHS_SAVE_SIZE sizeof(aArray) +#endif + CPlaneTrail CPlaneTrails::aArray[6]; RwImVertexIndex TrailIndices[32] = { 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 9, 9, @@ -1269,14 +1275,34 @@ INITSAVEBUF aArray[i].Clear(); for (int32 i = 0; i < 3; i++) { +#ifdef COMPATIBLE_SAVES + ReadSaveBuf(&aArray[i].m_numNodes, buf); + SkipSaveBuf(buf, 4); + ReadSaveBuf(&aArray[i].m_fTotalLength, buf); + ReadSaveBuf(&aArray[i].m_fSpeed, buf); + ReadSaveBuf(&aArray[i].m_fPosition, buf); + ReadSaveBuf(&aArray[i].m_fObjectLength, buf); + ReadSaveBuf(&aArray[i].m_state, buf); +#else ReadSaveBuf(&aArray[i], buf); +#endif for (int32 j = 0; j < 6; j++) { +#ifdef COMPATIBLE_SAVES + aArray[i].m_pObjects[j] = nil; + int32 tmp; + ReadSaveBuf(&tmp, buf); + if (tmp != 0) { + aArray[i].m_pObjects[j] = CPools::GetObjectPool()->GetSlot(tmp - 1); + aArray[i].m_pObjects[j]->m_phy_flagA08 = false; + } +#else CScriptPath *pPath = &aArray[i]; if (pPath->m_pObjects[j] != nil) { pPath->m_pObjects[j] = CPools::GetObjectPool()->GetSlot((uintptr)pPath->m_pObjects[j] - 1); pPath->m_pObjects[j]->m_phy_flagA08 = false; } +#endif } aArray[i].m_pNode = new CPlaneNode[aArray[i].m_numNodes]; @@ -1288,14 +1314,28 @@ VALIDATESAVEBUF(size) } void CScriptPaths::Save(uint8 *buf, uint32 *size) { - *size = sizeof(aArray); + *size = SCRIPTPATHS_SAVE_SIZE; INITSAVEBUF for (int32 i = 0; i < 3; i++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aArray[i].m_numNodes); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, aArray[i].m_fTotalLength); + WriteSaveBuf(buf, aArray[i].m_fSpeed); + WriteSaveBuf(buf, aArray[i].m_fPosition); + WriteSaveBuf(buf, aArray[i].m_fObjectLength); + WriteSaveBuf(buf, aArray[i].m_state); +#else CScriptPath *pPath = WriteSaveBuf(buf, aArray[i]); +#endif for (int32 j = 0; j < 6; j++) { +#ifdef COMPATIBLE_SAVES + WriteSaveBuf(buf, aArray[i].m_pObjects[j] != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aArray[i].m_pObjects[j]) + 1 : 0); +#else if (pPath->m_pObjects[j] != nil) pPath->m_pObjects[j] = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pPath->m_pObjects[j]) + 1); +#endif } for (int32 j = 0; j < aArray[i].m_numNodes; j++) { diff --git a/src/save/GenericGameStorage.cpp b/src/save/GenericGameStorage.cpp index 7921b22a..dbd12cc6 100644 --- a/src/save/GenericGameStorage.cpp +++ b/src/save/GenericGameStorage.cpp @@ -643,6 +643,525 @@ align4bytes(int32 size) return (size + 3) & 0xFFFFFFFC; } +#ifdef FIX_INCOMPATIBLE_SAVES +#define LoadSaveDataBlockNoCheck(buf, file, size) \ +do { \ + CFileMgr::Read(file, (const char *)&size, sizeof(size)); \ + size = align4bytes(size); \ + CFileMgr::Read(file, (const char *)work_buff, size); \ + buf = work_buff; \ +} while(0) + +#define WriteSavaDataBlockNoFunc(buf, file, size) \ +do { \ + if (!PcSaveHelper.PcClassSaveRoutine(file, buf, size)) \ + goto fail; \ + totalSize += size; \ +} while(0) + +#define FixSaveDataBlock(fix_func, file, size) \ +do { \ + ReadDataFromBufferPointer(buf, size); \ + memset(work_buff2, 0, sizeof(work_buff2)); \ + buf2 = work_buff2; \ + reserved = 0; \ + MakeSpaceForSizeInBufferPointer(presize, buf2, postsize); \ + fix_func(save_type, buf, buf2, &size); \ + CopySizeAndPreparePointer(presize, buf2, postsize, reserved, size); \ + if (!PcSaveHelper.PcClassSaveRoutine(file, work_buff2, buf2 - work_buff2)) \ + goto fail; \ + totalSize += buf2 - work_buff2; \ +} while(0) + +#define ReadDataFromBufferPointerWithSize(buf, to, size) memcpy(&to, buf, size); buf += align4bytes(size) + +#define ReadBuf(buf, to) memcpy(&to, buf, sizeof(to)); buf += sizeof(to) +#define WriteBuf(buf, from) memcpy(buf, &from, sizeof(from)); buf += sizeof(from) +#define CopyBuf(from, to, size) memcpy(to, from, size); to += (size); from += (size) +#define CopyPtr(from, to) memcpy(to, from, 4); to += 4; from += 8 +#define SkipBuf(buf, size) buf += (size) +#define SkipBoth(from, to, size) to += (size); from += (size) +#define SkipPtr(from, to) to += 4; from += 8 + +// unfortunately we need a 2nd buffer of the same size to store the fixed output ... +static uint8 work_buff2[sizeof(work_buff)]; + +enum +{ + SAVE_TYPE_NONE = 0, + SAVE_TYPE_32_BIT = 1, + SAVE_TYPE_64_BIT = 2, + SAVE_TYPE_MSVC = 4, + SAVE_TYPE_GCC = 8, +}; + +uint8 +GetSaveType(char *savename) +{ + uint8 save_type = SAVE_TYPE_NONE; + int file = CFileMgr::OpenFile(savename, "rb"); + + uint32 size; + CFileMgr::Read(file, (const char *)&size, sizeof(size)); + + uint8 *buf = work_buff; + CFileMgr::Read(file, (const char *)work_buff, size); // simple vars + scripts + + LoadSaveDataBlockNoCheck(buf, file, size); // ped pool + + LoadSaveDataBlockNoCheck(buf, file, size); // garages + ReadDataFromBufferPointer(buf, size); + + // 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 + + LoadSaveDataBlockNoCheck(buf, file, size); // cranes + + CFileMgr::CloseFile(file); + + ReadDataFromBufferPointer(buf, size); + + if (size == 1000) + save_type |= SAVE_TYPE_32_BIT; + else if (size == 1160) + save_type |= SAVE_TYPE_64_BIT; + else + assert(0); // this should never happen + + buf = work_buff2; + + buf += 1964; // skip everything before the first garage + buf += save_type & SAVE_TYPE_32_BIT ? 28 : 40; // skip first garage up to m_vecCorner1 + + CVector2D vecCorner1; + float fInfZ, fSupZ; + + ReadBuf(buf, vecCorner1); + ReadBuf(buf, fInfZ); + SkipBuf(buf, sizeof(CVector2D)); + SkipBuf(buf, sizeof(CVector2D)); + ReadBuf(buf, fSupZ); + + // 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; + + return save_type; +} + +static void +FixGarages(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + // 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 = 7340; + + if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_GCC) + read = 7020; + else if (save_type & SAVE_TYPE_64_BIT && save_type & SAVE_TYPE_GCC) + read = 7660; + else + read = 7852; + + uint32 ptrsize = save_type & SAVE_TYPE_32_BIT ? 4 : 8; + + CopyBuf(buf, buf2, 4 * 6); + CopyBuf(buf, buf2, 4 * TOTAL_COLLECTCARS_GARAGES); + CopyBuf(buf, buf2, 4); + + if (save_type & SAVE_TYPE_GCC) + { + for (int32 i = 0; i < NUM_GARAGE_STORED_CARS; i++) + { + 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 * TOTAL_HIDEOUT_GARAGES); + } + + for (int32 i = 0; i < NUM_GARAGES; i++) + { + 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 + SkipBuf(buf, sizeof(CStoredCar)); + + SkipBuf(buf2, sizeof(CStoredCar)); + } +} + +static void +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) + 0x3E0; // see CRANES_SAVE_SIZE + + CopyBuf(buf, buf2, 4 + 4); + + for (int32 i = 0; i < NUM_CRANES; i++) + { + CopyPtr(buf, buf2); + CopyPtr(buf, buf2); + 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); + SkipBuf(buf2, 1); + } + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixPickups(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + 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, sizeof(CVector) + 4); + CopyPtr(buf, buf2); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 4 * 2 + 2 * 3 + 8 + 1 * 3); + SkipBuf(buf, 7); + SkipBuf(buf2, 3); + } + + CopyBuf(buf, buf2, 2); + SkipBoth(buf, buf2, 2); + + CopyBuf(buf, buf2, NUMCOLLECTEDPICKUPS * 4); + + *size = 0; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +static void +FixPhoneInfo(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size) +{ + uint8 *buf_start = buf; + uint8 *buf2_start = buf2; + uint32 read = 0x1138; // sizeof(CPhoneInfo) + uint32 written = 0xA30; // see PHONEINFO_SAVE_SIZE + + CopyBuf(buf, buf2, 4 + 4); + + for (int32 i = 0; i < NUMPHONES; i++) + { + CopyBuf(buf, buf2, sizeof(CVector)); + SkipBuf(buf, 4); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 4); + SkipBuf(buf, 4); + CopyPtr(buf, buf2); + CopyBuf(buf, buf2, 4 + 1); + SkipBoth(buf, buf2, 3); + } + + *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; + uint8 *buf2_start = buf2; + + int32 numObjects; + ReadBuf(buf, numObjects); + WriteBuf(buf2, numObjects); + + 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 + CopyBuf(buf, buf2, 4 * 4 * 4); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 1); + SkipBuf(buf, 7); + SkipBuf(buf2, 3); + + // CParticleObject + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + SkipPtr(buf, buf2); + CopyBuf(buf, buf2, 4 * 3 + 2 * 1 + 2 * 2); + SkipBoth(buf, buf2, 2); + CopyBuf(buf, buf2, sizeof(CVector) + 2 * 4 + sizeof(CRGBA) + 2 * 1); + SkipBoth(buf, buf2, 2); + } + + 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; + + assert(buf - buf_start == read); + assert(buf2 - buf2_start == written); + + *size = written; +} + +bool +FixSave(int32 slot, uint8 save_type) +{ + if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_MSVC) + return true; + + bool success = false; + + uint8 *buf, *presize, *postsize, *buf2; + uint32 size; + uint32 reserved; + + uint32 totalSize; + + char savename[MAX_PATH]; + char savename_bak[MAX_PATH]; + + sprintf(savename, "%s%i%s", DefaultPCSaveFileName, slot + 1, ".b"); + sprintf(savename_bak, "%s%i%s.%lld.bak", DefaultPCSaveFileName, slot + 1, ".b", time(nil)); + + assert(caserename(savename, savename_bak) == 0); + + int file_in = CFileMgr::OpenFile(savename_bak, "rb"); + int file_out = CFileMgr::OpenFileForWriting(savename); + + CheckSum = 0; + totalSize = 0; + + CFileMgr::Read(file_in, (const char *)&size, sizeof(size)); + + buf = work_buff; + CFileMgr::Read(file_in, (const char *)work_buff, size); // simple vars + scripts + + 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 + + LoadSaveDataBlockNoCheck(buf, file_in, size); // game logic + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // vehicle pool + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // object pool + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // paths + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // cranes + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixCranes, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // pickups + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixPickups, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // phoneinfo + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixPhoneInfo, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // restart + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // radar blips + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // zones + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // gang data + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // car generators + WriteSavaDataBlockNoFunc(buf, file_out, size); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // particles + if (save_type & SAVE_TYPE_64_BIT) + FixSaveDataBlock(FixParticles, file_out, size); + else + WriteSavaDataBlockNoFunc(buf, file_out, size); + + 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); + + LoadSaveDataBlockNoCheck(buf, file_in, size); // ped type + WriteSavaDataBlockNoFunc(buf, file_out, size); + + memset(work_buff, 0, sizeof(work_buff)); + + for (int i = 0; i < 4; i++) { + size = align4bytes(SIZE_OF_ONE_GAME_IN_BYTES - totalSize - 4); + if (size > sizeof(work_buff)) + size = sizeof(work_buff); + if (size > 4) { + if (!PcSaveHelper.PcClassSaveRoutine(file_out, work_buff, size)) + goto fail; + totalSize += size; + } + } + + if (!CFileMgr::Write(file_out, (const char *)&CheckSum, sizeof(CheckSum))) + goto fail; + + success = true; + +fail:; + CFileMgr::CloseFile(file_in); + CFileMgr::CloseFile(file_out); + + return success; +} + +#undef LoadSaveDataBlockNoCheck +#undef WriteSavaDataBlockNoFunc +#undef FixSaveDataBlock +#undef ReadDataFromBufferPointerWithSize +#undef ReadBuf +#undef WriteBuf +#undef CopyBuf +#undef CopyPtr +#undef SkipBuf +#undef SkipBoth +#undef SkipPtr +#endif + #ifdef MISSION_REPLAY void DisplaySaveResult(int unk, char* name) diff --git a/src/save/GenericGameStorage.h b/src/save/GenericGameStorage.h index 65f1cc16..b2bf7a24 100644 --- a/src/save/GenericGameStorage.h +++ b/src/save/GenericGameStorage.h @@ -25,6 +25,11 @@ bool CheckDataNotCorrupt(int32 slot, char *name); bool RestoreForStartLoad(); int align4bytes(int32 size); +#ifdef FIX_INCOMPATIBLE_SAVES +uint8 GetSaveType(char *savename); +bool FixSave(int32 slot, uint8 save_type); +#endif + extern char DefaultPCSaveFileName[260]; extern char ValidSaveName[260]; extern char LoadFileName[256]; diff --git a/src/save/PCSave.cpp b/src/save/PCSave.cpp index c9045705..a33e9d90 100644 --- a/src/save/PCSave.cpp +++ b/src/save/PCSave.cpp @@ -122,6 +122,13 @@ C_PcSave::PopulateSlotInfo() } 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] = SLOT_CORRUPTED; + continue; + } +#endif SYSTEMTIME st; memcpy(&st, &header.SaveDateTime, sizeof(SYSTEMTIME)); const char *month; diff --git a/src/save/PCSave.h b/src/save/PCSave.h index 2e85867a..2a29fa95 100644 --- a/src/save/PCSave.h +++ b/src/save/PCSave.h @@ -33,7 +33,7 @@ public: void PopulateSlotInfo(); bool DeleteSlot(int32 slot); int8 SaveSlot(int32 slot); - bool PcClassSaveRoutine(int32 a2, uint8 *data, uint32 size); + 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 6e9b3ae9..d0817e9a 100644 --- a/src/save/SaveBuf.h +++ b/src/save/SaveBuf.h @@ -64,6 +64,14 @@ WriteSaveBuf(uint8 *&buf, uint32 &length, const T &value) return p; } +#ifdef COMPATIBLE_SAVES +inline void +ZeroSaveBuf(uint8 *&buf, uint32 length) +{ + memset(buf, 0, length); + SkipSaveBuf(buf, length); +} +#endif #define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32)) diff --git a/src/skel/crossplatform.cpp b/src/skel/crossplatform.cpp index 68df6704..f7016b21 100644 --- a/src/skel/crossplatform.cpp +++ b/src/skel/crossplatform.cpp @@ -155,6 +155,29 @@ FILE* _fcaseopen(char const* filename, char const* mode) return result; } +int _caserename(const char *old_filename, const char *new_filename) +{ + int result; + char *real_old = casepath(old_filename); + char *real_new = casepath(new_filename); + + // hack so we don't even try to rename it to new_filename if it already exists + if (!real_new) { + free(real_old); + return -1; + } + + if (!real_old) + result = rename(old_filename, real_new); + else + result = rename(real_old, real_new); + + free(real_old); + free(real_new); + + return result; +} + // Case-insensitivity on linux (from https://github.com/OneSadCookie/fcaseopen) // Returned string should freed manually (if exists) char* casepath(char const* path, bool checkPathFirst) diff --git a/src/skel/crossplatform.h b/src/skel/crossplatform.h index a073f854..f37e64a1 100644 --- a/src/skel/crossplatform.h +++ b/src/skel/crossplatform.h @@ -33,6 +33,7 @@ char *_strdate(char *buf); #endif extern DWORD _dwOperatingSystemVersion; #define fcaseopen fopen +#define caserename rename #else char *strupr(char *str); char *strlwr(char *str); @@ -55,6 +56,8 @@ extern long _dwOperatingSystemVersion; char *casepath(char const *path, bool checkPathFirst = true); FILE *_fcaseopen(char const *filename, char const *mode); #define fcaseopen _fcaseopen +int _caserename(const char *old_filename, const char *new_filename); +#define caserename _caserename #endif #ifdef RW_GL3 diff --git a/src/vehicles/Automobile.cpp b/src/vehicles/Automobile.cpp index ef7fded0..2c199030 100644 --- a/src/vehicles/Automobile.cpp +++ b/src/vehicles/Automobile.cpp @@ -5725,7 +5725,7 @@ CAutomobile::Save(uint8*& buf) { CVehicle::Save(buf); WriteSaveBuf(buf, Damage); - SkipSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager)); + ZeroSaveBuf(buf, 1500 - 672 - sizeof(CDamageManager)); } void diff --git a/src/vehicles/Bike.cpp b/src/vehicles/Bike.cpp index 627cddbb..39612a15 100644 --- a/src/vehicles/Bike.cpp +++ b/src/vehicles/Bike.cpp @@ -2953,7 +2953,7 @@ void CBike::Save(uint8*& buf) { CVehicle::Save(buf); - SkipSaveBuf(buf, 1260 - 672); + ZeroSaveBuf(buf, 1260 - 672); } void diff --git a/src/vehicles/Boat.cpp b/src/vehicles/Boat.cpp index ab70f19b..a3aec041 100644 --- a/src/vehicles/Boat.cpp +++ b/src/vehicles/Boat.cpp @@ -1478,7 +1478,7 @@ void CBoat::Save(uint8*& buf) { CVehicle::Save(buf); - SkipSaveBuf(buf, 1216 - 672); + ZeroSaveBuf(buf, 1216 - 672); } void diff --git a/src/vehicles/Cranes.cpp b/src/vehicles/Cranes.cpp index 857b846f..d4b58f05 100644 --- a/src/vehicles/Cranes.cpp +++ b/src/vehicles/Cranes.cpp @@ -37,6 +37,12 @@ #define MIN_VALID_POSITION (-10000.0f) #define DEFAULT_OFFSET (20.0f) +#ifdef COMPATIBLE_SAVES +#define CRANES_SAVE_SIZE 0x3E0 +#else +#define CRANES_SAVE_SIZE sizeof(aCranes) +#endif + uint32 TimerForCamInterpolation; uint32 CCranes::CarsCollectedMilitaryCrane; @@ -624,10 +630,45 @@ void CCranes::Save(uint8* buf, uint32* size) { INITSAVEBUF - *size = 2 * sizeof(uint32) + sizeof(aCranes); + *size = 2 * sizeof(uint32) + CRANES_SAVE_SIZE; WriteSaveBuf(buf, NumCranes); WriteSaveBuf(buf, CarsCollectedMilitaryCrane); for (int i = 0; i < NUM_CRANES; i++) { +#ifdef COMPATIBLE_SAVES + int32 tmp = aCranes[i].m_pCraneEntity != nil ? CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pCraneEntity) + 1 : 0; + WriteSaveBuf(buf, tmp); + tmp = aCranes[i].m_pHook != nil ? CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pHook) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, aCranes[i].m_fPickupX1); + WriteSaveBuf(buf, aCranes[i].m_fPickupX2); + WriteSaveBuf(buf, aCranes[i].m_fPickupY1); + WriteSaveBuf(buf, aCranes[i].m_fPickupY2); + WriteSaveBuf(buf, aCranes[i].m_vecDropoffTarget); + WriteSaveBuf(buf, aCranes[i].m_fDropoffHeading); + WriteSaveBuf(buf, aCranes[i].m_fPickupAngle); + WriteSaveBuf(buf, aCranes[i].m_fDropoffAngle); + WriteSaveBuf(buf, aCranes[i].m_fPickupDistance); + WriteSaveBuf(buf, aCranes[i].m_fDropoffDistance); + WriteSaveBuf(buf, aCranes[i].m_fPickupHeight); + WriteSaveBuf(buf, aCranes[i].m_fDropoffHeight); + WriteSaveBuf(buf, aCranes[i].m_fHookAngle); + WriteSaveBuf(buf, aCranes[i].m_fHookOffset); + WriteSaveBuf(buf, aCranes[i].m_fHookHeight); + WriteSaveBuf(buf, aCranes[i].m_vecHookInitPos); + WriteSaveBuf(buf, aCranes[i].m_vecHookCurPos); + WriteSaveBuf(buf, aCranes[i].m_vecHookVelocity); + tmp = aCranes[i].m_pVehiclePickedUp != nil ? CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(aCranes[i].m_pVehiclePickedUp) + 1 : 0; + WriteSaveBuf(buf, tmp); + WriteSaveBuf(buf, aCranes[i].m_nTimeForNextCheck); + WriteSaveBuf(buf, aCranes[i].m_nCraneStatus); + WriteSaveBuf(buf, aCranes[i].m_nCraneState); + WriteSaveBuf(buf, aCranes[i].m_nVehiclesCollected); + WriteSaveBuf(buf, aCranes[i].m_bIsCrusher); + WriteSaveBuf(buf, aCranes[i].m_bIsMilitaryCrane); + WriteSaveBuf(buf, aCranes[i].m_bWasMilitaryCrane); + WriteSaveBuf(buf, aCranes[i].m_bIsTop); + ZeroSaveBuf(buf, 1); +#else CCrane *pCrane = WriteSaveBuf(buf, aCranes[i]); if (pCrane->m_pCraneEntity != nil) pCrane->m_pCraneEntity = (CBuilding*)(CPools::GetBuildingPool()->GetJustIndex_NoFreeAssert(pCrane->m_pCraneEntity) + 1); @@ -635,6 +676,7 @@ void CCranes::Save(uint8* buf, uint32* size) pCrane->m_pHook = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(pCrane->m_pHook) + 1); if (pCrane->m_pVehiclePickedUp != nil) pCrane->m_pVehiclePickedUp = (CVehicle*)(CPools::GetVehiclePool()->GetJustIndex_NoFreeAssert(pCrane->m_pVehiclePickedUp) + 1); +#endif } VALIDATESAVEBUF(*size); @@ -646,8 +688,45 @@ void CCranes::Load(uint8* buf, uint32 size) ReadSaveBuf(&NumCranes, buf); ReadSaveBuf(&CarsCollectedMilitaryCrane, buf); - for (int i = 0; i < NUM_CRANES; i++) + for (int i = 0; i < NUM_CRANES; i++) { +#ifdef COMPATIBLE_SAVES + int32 tmp; + ReadSaveBuf(&tmp, buf); + aCranes[i].m_pCraneEntity = tmp != 0 ? CPools::GetBuildingPool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&tmp, buf); + aCranes[i].m_pHook = tmp != 0 ? CPools::GetObjectPool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&aCranes[i].m_fPickupX1, buf); + ReadSaveBuf(&aCranes[i].m_fPickupX2, buf); + ReadSaveBuf(&aCranes[i].m_fPickupY1, buf); + ReadSaveBuf(&aCranes[i].m_fPickupY2, buf); + ReadSaveBuf(&aCranes[i].m_vecDropoffTarget, buf); + ReadSaveBuf(&aCranes[i].m_fDropoffHeading, buf); + ReadSaveBuf(&aCranes[i].m_fPickupAngle, buf); + ReadSaveBuf(&aCranes[i].m_fDropoffAngle, buf); + ReadSaveBuf(&aCranes[i].m_fPickupDistance, buf); + ReadSaveBuf(&aCranes[i].m_fDropoffDistance, buf); + ReadSaveBuf(&aCranes[i].m_fPickupHeight, buf); + ReadSaveBuf(&aCranes[i].m_fDropoffHeight, buf); + ReadSaveBuf(&aCranes[i].m_fHookAngle, buf); + ReadSaveBuf(&aCranes[i].m_fHookOffset, buf); + ReadSaveBuf(&aCranes[i].m_fHookHeight, buf); + ReadSaveBuf(&aCranes[i].m_vecHookInitPos, buf); + ReadSaveBuf(&aCranes[i].m_vecHookCurPos, buf); + ReadSaveBuf(&aCranes[i].m_vecHookVelocity, buf); + ReadSaveBuf(&tmp, buf); + aCranes[i].m_pVehiclePickedUp = tmp != 0 ? CPools::GetVehiclePool()->GetSlot(tmp - 1) : nil; + ReadSaveBuf(&aCranes[i].m_nTimeForNextCheck, buf); + ReadSaveBuf(&aCranes[i].m_nCraneStatus, buf); + ReadSaveBuf(&aCranes[i].m_nCraneState, buf); + ReadSaveBuf(&aCranes[i].m_nVehiclesCollected, buf); + ReadSaveBuf(&aCranes[i].m_bIsCrusher, buf); + ReadSaveBuf(&aCranes[i].m_bIsMilitaryCrane, buf); + ReadSaveBuf(&aCranes[i].m_bWasMilitaryCrane, buf); + ReadSaveBuf(&aCranes[i].m_bIsTop, buf); + SkipSaveBuf(buf, 1); +#else ReadSaveBuf(&aCranes[i], buf); + } for (int i = 0; i < NUM_CRANES; i++) { CCrane *pCrane = &aCranes[i]; if (pCrane->m_pCraneEntity != nil) @@ -656,6 +735,7 @@ void CCranes::Load(uint8* buf, uint32 size) pCrane->m_pHook = CPools::GetObjectPool()->GetSlot((uintptr)pCrane->m_pHook - 1); if (pCrane->m_pVehiclePickedUp != nil) pCrane->m_pVehiclePickedUp = CPools::GetVehiclePool()->GetSlot((uintptr)pCrane->m_pVehiclePickedUp - 1); +#endif } VALIDATESAVEBUF(size); diff --git a/src/vehicles/Vehicle.cpp b/src/vehicles/Vehicle.cpp index 49427476..a4c983f7 100644 --- a/src/vehicles/Vehicle.cpp +++ b/src/vehicles/Vehicle.cpp @@ -2377,42 +2377,42 @@ DestroyVehicleAndDriverAndPassengers(CVehicle* pVehicle) void CVehicle::Save(uint8*& buf) { - SkipSaveBuf(buf, 4); - WriteSaveBuf(buf, GetRight().x); - WriteSaveBuf(buf, GetRight().y); - WriteSaveBuf(buf, GetRight().z); - SkipSaveBuf(buf, 4); - WriteSaveBuf(buf, GetForward().x); - WriteSaveBuf(buf, GetForward().y); - WriteSaveBuf(buf, GetForward().z); - SkipSaveBuf(buf, 4); - WriteSaveBuf(buf, GetUp().x); - WriteSaveBuf(buf, GetUp().y); - WriteSaveBuf(buf, GetUp().z); - SkipSaveBuf(buf, 4); - WriteSaveBuf(buf, GetPosition().x); - WriteSaveBuf(buf, GetPosition().y); - WriteSaveBuf(buf, GetPosition().z); - SkipSaveBuf(buf, 16); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetRight().x); + WriteSaveBuf(buf, GetRight().y); + WriteSaveBuf(buf, GetRight().z); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetForward().x); + WriteSaveBuf(buf, GetForward().y); + WriteSaveBuf(buf, GetForward().z); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetUp().x); + WriteSaveBuf(buf, GetUp().y); + WriteSaveBuf(buf, GetUp().z); + ZeroSaveBuf(buf, 4); + WriteSaveBuf(buf, GetPosition().x); + WriteSaveBuf(buf, GetPosition().y); + WriteSaveBuf(buf, GetPosition().z); + ZeroSaveBuf(buf, 16); SaveEntityFlags(buf); - SkipSaveBuf(buf, 208); + ZeroSaveBuf(buf, 208); AutoPilot.Save(buf); - WriteSaveBuf(buf, m_currentColour1); - WriteSaveBuf(buf, m_currentColour2); - SkipSaveBuf(buf, 2); - WriteSaveBuf(buf, m_nAlarmState); - SkipSaveBuf(buf, 42); - WriteSaveBuf(buf, m_nNumMaxPassengers); - SkipSaveBuf(buf, 3); - WriteSaveBuf(buf, field_1D0[0]); - WriteSaveBuf(buf, field_1D0[1]); - WriteSaveBuf(buf, field_1D0[2]); - WriteSaveBuf(buf, field_1D0[3]); - SkipSaveBuf(buf, 8); - WriteSaveBuf(buf, m_fSteerAngle); - WriteSaveBuf(buf, m_fGasPedal); - WriteSaveBuf(buf, m_fBrakePedal); - WriteSaveBuf(buf, VehicleCreatedBy); + WriteSaveBuf(buf, m_currentColour1); + WriteSaveBuf(buf, m_currentColour2); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_nAlarmState); + ZeroSaveBuf(buf, 42); + WriteSaveBuf(buf, m_nNumMaxPassengers); + ZeroSaveBuf(buf, 3); + WriteSaveBuf(buf, field_1D0[0]); + WriteSaveBuf(buf, field_1D0[1]); + WriteSaveBuf(buf, field_1D0[2]); + WriteSaveBuf(buf, field_1D0[3]); + ZeroSaveBuf(buf, 8); + WriteSaveBuf(buf, m_fSteerAngle); + WriteSaveBuf(buf, m_fGasPedal); + WriteSaveBuf(buf, m_fBrakePedal); + WriteSaveBuf(buf, VehicleCreatedBy); uint8 flags = 0; if (bIsLawEnforcer) flags |= BIT(0); if (bIsLocked) flags |= BIT(3); @@ -2420,19 +2420,19 @@ CVehicle::Save(uint8*& buf) if (bIsHandbrakeOn) flags |= BIT(5); if (bLightsOn) flags |= BIT(6); if (bFreebies) flags |= BIT(7); - WriteSaveBuf(buf, flags); - SkipSaveBuf(buf, 10); - WriteSaveBuf(buf, m_fHealth); - WriteSaveBuf(buf, m_nCurrentGear); - SkipSaveBuf(buf, 3); - WriteSaveBuf(buf, m_fChangeGearTime); - SkipSaveBuf(buf, 12); - WriteSaveBuf(buf, m_nTimeOfDeath); - SkipSaveBuf(buf, 2); - WriteSaveBuf(buf, m_nBombTimer); - SkipSaveBuf(buf, 12); - WriteSaveBuf(buf, m_nDoorLock); - SkipSaveBuf(buf, 111); + WriteSaveBuf(buf, flags); + ZeroSaveBuf(buf, 10); + WriteSaveBuf(buf, m_fHealth); + WriteSaveBuf(buf, m_nCurrentGear); + ZeroSaveBuf(buf, 3); + WriteSaveBuf(buf, m_fChangeGearTime); + ZeroSaveBuf(buf, 12); + WriteSaveBuf(buf, m_nTimeOfDeath); + ZeroSaveBuf(buf, 2); + WriteSaveBuf(buf, m_nBombTimer); + ZeroSaveBuf(buf, 12); + WriteSaveBuf(buf, m_nDoorLock); + ZeroSaveBuf(buf, 108); } void @@ -2494,9 +2494,8 @@ CVehicle::Load(uint8*& buf) SkipSaveBuf(buf, 2); ReadSaveBuf(&m_nBombTimer, buf); SkipSaveBuf(buf, 12); - ReadSaveBuf(&flags, buf); - m_nDoorLock = (eCarLock)flags; - SkipSaveBuf(buf, 111); + ReadSaveBuf(&m_nDoorLock, buf); + SkipSaveBuf(buf, 108); } #endif diff --git a/src/vehicles/Vehicle.h b/src/vehicles/Vehicle.h index d29c2dc0..5458590f 100644 --- a/src/vehicles/Vehicle.h +++ b/src/vehicles/Vehicle.h @@ -279,7 +279,7 @@ public: int8 m_comedyControlState; CStoredCollPoly m_aCollPolys[2]; // poly which is under front/rear part of car float m_fSteerInput; - uint8 m_vehType; + eVehicleType m_vehType; static void *operator new(size_t) throw(); static void *operator new(size_t sz, int slot) throw(); diff --git a/src/weapons/Weapon.cpp b/src/weapons/Weapon.cpp index 1f98cb2b..e546eb05 100644 --- a/src/weapons/Weapon.cpp +++ b/src/weapons/Weapon.cpp @@ -3285,7 +3285,7 @@ CWeapon::Save(uint8*& buf) CopyToBuf(buf, m_nAmmoTotal); CopyToBuf(buf, m_nTimer); CopyToBuf(buf, m_bAddRotOffset); - SkipSaveBuf(buf, 3); + ZeroSaveBuf(buf, 3); } void diff --git a/utils/gxt/french.txt b/utils/gxt/french.txt index 6644a107..3f57a6a6 100644 --- a/utils/gxt/french.txt +++ b/utils/gxt/french.txt @@ -17107,6 +17107,12 @@ This track contains a sample of "Next Level" as performed by Showbiz & AG. Court [CR19_20:CRED01] ~n~ ~n~Donna Young, Richie Zito +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + [DUMMY] THIS LABEL NEEDS TO BE HERE !!! AS THE LAST LABEL DOES NOT GET COMPILED \ No newline at end of file diff --git a/utils/gxt/german.txt b/utils/gxt/german.txt index 79df0b13..2867b1c6 100644 --- a/utils/gxt/german.txt +++ b/utils/gxt/german.txt @@ -17452,6 +17452,12 @@ This track contains a sample of "Next Level" as performed by Showbiz & AG. Court [CR19_20:CRED01] ~n~ ~n~Donna Young, Richie Zito +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + [DUMMY] THIS LABEL NEEDS TO BE HERE !!! AS THE LAST LABEL DOES NOT GET COMPILED \ No newline at end of file diff --git a/utils/gxt/italian.txt b/utils/gxt/italian.txt index c9a966ad..887f08b2 100644 --- a/utils/gxt/italian.txt +++ b/utils/gxt/italian.txt @@ -17455,6 +17455,12 @@ This track contains a sample of "Next Level" as performed by Showbiz & AG. Court [CR19_20:CRED01] ~n~ ~n~Donna Young, Richie Zito +[FEM_PED] +PED DENSITY + +[FEM_CAR] +CAR DENSITY + [DUMMY] THIS LABEL NEEDS TO BE HERE !!! AS THE LAST LABEL DOES NOT GET COMPILED \ No newline at end of file