summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/audio/AudioManager.h344
-rw-r--r--src/audio/oal/stream.cpp2
-rw-r--r--src/control/AutoPilot.cpp66
-rw-r--r--src/control/Garages.cpp98
-rw-r--r--src/control/Garages.h2
-rw-r--r--src/control/Phones.cpp33
-rw-r--r--src/control/Pickups.cpp58
-rw-r--r--src/control/Script5.cpp38
-rw-r--r--src/core/Placeable.h2
-rw-r--r--src/core/Pools.cpp12
-rw-r--r--src/core/Stats.cpp4
-rw-r--r--src/core/config.h188
-rw-r--r--src/entities/Entity.cpp4
-rw-r--r--src/entities/Physical.cpp4
-rw-r--r--src/objects/ParticleObject.cpp109
-rw-r--r--src/peds/Ped.cpp10
-rw-r--r--src/peds/PlayerPed.cpp6
-rw-r--r--src/render/Fluff.cpp42
-rw-r--r--src/save/GenericGameStorage.cpp519
-rw-r--r--src/save/GenericGameStorage.h5
-rw-r--r--src/save/PCSave.cpp7
-rw-r--r--src/save/PCSave.h2
-rw-r--r--src/save/SaveBuf.h8
-rw-r--r--src/skel/crossplatform.cpp23
-rw-r--r--src/skel/crossplatform.h3
-rw-r--r--src/vehicles/Automobile.cpp2
-rw-r--r--src/vehicles/Bike.cpp2
-rw-r--r--src/vehicles/Boat.cpp2
-rw-r--r--src/vehicles/Cranes.cpp84
-rw-r--r--src/vehicles/Vehicle.cpp99
-rw-r--r--src/vehicles/Vehicle.h2
-rw-r--r--src/weapons/Weapon.cpp2
32 files changed, 1333 insertions, 449 deletions
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 &params); //
- 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 &params);
+ 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 &params); //done(bcs not exists in VC)
+ bool8 ProcessTrainNoise(cVehicleParams &params);
#endif
- void ProcessVehicle(CVehicle *vehicle); // done
- bool8 ProcessVehicleDoors(cVehicleParams &params); // done
- void ProcessVehicleEngine(cVehicleParams &params); // done
- void ProcessVehicleFlatTyre(cVehicleParams &params); // done
- bool8 ProcessVehicleHorn(cVehicleParams &params); // done
- void ProcessVehicleOneShots(cVehicleParams &params); // done
- bool8 ProcessVehicleReverseWarning(cVehicleParams &params); // done
- bool8 ProcessVehicleRoadNoise(cVehicleParams &params); // done
- bool8 ProcessVehicleSirenOrAlarm(cVehicleParams &params); // done
- bool8 ProcessVehicleSkidding(cVehicleParams &params); // 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 &params, uint16 sound); // done
+ void ProcessVehicle(CVehicle *vehicle);
+ bool8 ProcessVehicleDoors(cVehicleParams &params);
+ void ProcessVehicleEngine(cVehicleParams &params);
+ void ProcessVehicleFlatTyre(cVehicleParams &params);
+ bool8 ProcessVehicleHorn(cVehicleParams &params);
+ void ProcessVehicleOneShots(cVehicleParams &params);
+ bool8 ProcessVehicleReverseWarning(cVehicleParams &params);
+ bool8 ProcessVehicleRoadNoise(cVehicleParams &params);
+ bool8 ProcessVehicleSirenOrAlarm(cVehicleParams &params);
+ bool8 ProcessVehicleSkidding(cVehicleParams &params);
+ 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 &params, 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 &params) const; // done
- bool8 UsesSirenSwitching(cVehicleParams &params) const; // done
+ void UpdateGasPedalAudio(CVehicle *veh, int vehType);
+ void UpdateReflections();
+ bool8 UsesReverseWarning(int32 model) const;
+ bool8 UsesSiren(cVehicleParams &params) const;
+ bool8 UsesSirenSwitching(cVehicleParams &params) 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<int32>(buf, m_nCurrentRouteNode);
- WriteSaveBuf<int32>(buf, m_nNextRouteNode);
- WriteSaveBuf<int32>(buf, m_nPrevRouteNode);
- WriteSaveBuf<int32>(buf, m_nTimeEnteredCurve);
- WriteSaveBuf<int32>(buf, m_nTimeToSpendOnCurrentCurve);
- WriteSaveBuf<uint32>(buf, m_nCurrentPathNodeInfo);
- WriteSaveBuf<uint32>(buf, m_nNextPathNodeInfo);
- WriteSaveBuf<uint32>(buf, m_nPreviousPathNodeInfo);
- WriteSaveBuf<uint32>(buf, m_nAntiReverseTimer);
- WriteSaveBuf<uint32>(buf, m_nTimeToStartMission);
- WriteSaveBuf<int8>(buf, m_nPreviousDirection);
- WriteSaveBuf<int8>(buf, m_nCurrentDirection);
- WriteSaveBuf<int8>(buf, m_nNextDirection);
- WriteSaveBuf<int8>(buf, m_nCurrentLane);
- WriteSaveBuf<int8>(buf, m_nNextLane);
- WriteSaveBuf<uint8>(buf, m_nDrivingStyle);
- WriteSaveBuf<uint8>(buf, m_nCarMission);
- WriteSaveBuf<uint8>(buf, m_nTempAction);
- WriteSaveBuf<uint32>(buf, m_nTimeTempAction);
- WriteSaveBuf<float>(buf, m_fMaxTrafficSpeed);
- WriteSaveBuf<uint8>(buf, m_nCruiseSpeed);
- WriteSaveBuf<uint8>(buf, m_nCruiseSpeedMultiplierType);
- SkipSaveBuf(buf, 2);
- WriteSaveBuf<float>(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<uint8>(buf, flags);
- WriteSaveBuf<uint8>(buf, m_nSwitchDistance);
- SkipSaveBuf(buf, 2);
- WriteSaveBuf<float>(buf, m_vecDestinationCoors.x);
- WriteSaveBuf<float>(buf, m_vecDestinationCoors.y);
- WriteSaveBuf<float>(buf, m_vecDestinationCoors.z);
- SkipSaveBuf(buf, 32);
- WriteSaveBuf<int16>(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<int32>(buf, m_nId);
for (int i = 0; i < 8; i++)
- WriteSaveBuf<char>(buf, m_abScriptName[i]);
- WriteSaveBuf<uint32>(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<uint32>(buf, m_anStack[i]);
- WriteSaveBuf<uint16>(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<int32>(buf, m_anLocalVariables[i]);
- WriteSaveBuf<int32>(buf, m_nLocalsPointer);
- WriteSaveBuf<bool>(buf, m_bIsActive);
- WriteSaveBuf<bool>(buf, m_bCondResult);
- WriteSaveBuf<bool>(buf, m_bIsMissionScript);
- WriteSaveBuf<bool>(buf, m_bSkipWakeTime);
- WriteSaveBuf<uint32>(buf, m_nWakeTime);
- WriteSaveBuf<uint16>(buf, m_nAndOrState);
- WriteSaveBuf<bool>(buf, m_bNotFlag);
- WriteSaveBuf<bool>(buf, m_bDeatharrestEnabled);
- WriteSaveBuf<bool>(buf, m_bDeatharrestExecuted);
- WriteSaveBuf<bool>(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<uint32>(buf, pVehicle->m_vehType);
- WriteSaveBuf<int16>(buf, pVehicle->GetModelIndex());
- WriteSaveBuf<int32>(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 69775a62..877b37cc 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,
@@ -156,8 +158,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
@@ -176,22 +206,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
@@ -206,24 +238,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
@@ -251,7 +269,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
@@ -262,7 +281,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
@@ -297,7 +316,7 @@ enum Config {
#endif
// Water & Particle
-// #define PC_WATER
+#undef PC_WATER
#define WATER_CHEATS
//#define PSP_WATERCANNON
@@ -434,97 +453,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<uint32>(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<uint32>(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<float>(buf, GetRight().x);
- WriteSaveBuf<float>(buf, GetRight().y);
- WriteSaveBuf<float>(buf, GetRight().z);
- SkipSaveBuf(buf, 4);
- WriteSaveBuf<float>(buf, GetForward().x);
- WriteSaveBuf<float>(buf, GetForward().y);
- WriteSaveBuf<float>(buf, GetForward().z);
- SkipSaveBuf(buf, 4);
- WriteSaveBuf<float>(buf, GetUp().x);
- WriteSaveBuf<float>(buf, GetUp().y);
- WriteSaveBuf<float>(buf, GetUp().z);
- SkipSaveBuf(buf, 4);
- WriteSaveBuf<float>(buf, GetPosition().x);
- WriteSaveBuf<float>(buf, GetPosition().y);
- WriteSaveBuf<float>(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<int8>(buf, m_currentColour1);
- WriteSaveBuf<int8>(buf, m_currentColour2);
- SkipSaveBuf(buf, 2);
- WriteSaveBuf<int16>(buf, m_nAlarmState);
- SkipSaveBuf(buf, 42);
- WriteSaveBuf<uint8>(buf, m_nNumMaxPassengers);
- SkipSaveBuf(buf, 3);
- WriteSaveBuf<float>(buf, field_1D0[0]);
- WriteSaveBuf<float>(buf, field_1D0[1]);
- WriteSaveBuf<float>(buf, field_1D0[2]);
- WriteSaveBuf<float>(buf, field_1D0[3]);
- SkipSaveBuf(buf, 8);
- WriteSaveBuf<float>(buf, m_fSteerAngle);
- WriteSaveBuf<float>(buf, m_fGasPedal);
- WriteSaveBuf<float>(buf, m_fBrakePedal);
- WriteSaveBuf<uint8>(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<uint8>(buf, flags);
- SkipSaveBuf(buf, 10);
- WriteSaveBuf<float>(buf, m_fHealth);
- WriteSaveBuf<uint8>(buf, m_nCurrentGear);
- SkipSaveBuf(buf, 3);
- WriteSaveBuf<float>(buf, m_fChangeGearTime);
- SkipSaveBuf(buf, 12);
- WriteSaveBuf<uint32>(buf, m_nTimeOfDeath);
- SkipSaveBuf(buf, 2);
- WriteSaveBuf<int16>(buf, m_nBombTimer);
- SkipSaveBuf(buf, 12);
- WriteSaveBuf<int8>(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