mirror of https://github.com/Nofated095/re-GTA.git
finish COMPATIBLE_SAVES and FIX_INCOMPATIBLE_SAVES
This commit is contained in:
parent
71f28c8cf5
commit
011aafa043
|
@ -50,41 +50,41 @@ 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(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);
|
||||
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);
|
||||
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);
|
||||
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)
|
||||
|
|
|
@ -26,13 +26,6 @@
|
|||
#include "World.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)
|
||||
|
@ -1883,11 +1876,12 @@ void CStoredCar::StoreCar(CVehicle* pVehicle)
|
|||
m_nRadioStation = pVehicle->m_nRadioStation;
|
||||
m_nVariationA = pVehicle->m_aExtras[0];
|
||||
m_nVariationB = pVehicle->m_aExtras[1];
|
||||
m_bBulletproof = pVehicle->bBulletProof;
|
||||
m_bFireproof = pVehicle->bFireProof;
|
||||
m_bExplosionproof = pVehicle->bExplosionProof;
|
||||
m_bCollisionproof = pVehicle->bCollisionProof;
|
||||
m_bMeleeproof = pVehicle->bMeleeProof;
|
||||
m_nFlags = 0;
|
||||
if (pVehicle->bBulletProof) m_nFlags |= FLAG_BULLETPROOF;
|
||||
if (pVehicle->bFireProof) m_nFlags |= FLAG_FIREPROOF;
|
||||
if (pVehicle->bExplosionProof) m_nFlags |= FLAG_EXPLOSIONPROOF;
|
||||
if (pVehicle->bCollisionProof) m_nFlags |= FLAG_COLLISIONPROOF;
|
||||
if (pVehicle->bMeleeProof) m_nFlags |= FLAG_MELEEPROOF;
|
||||
if (pVehicle->IsCar())
|
||||
m_nCarBombType = ((CAutomobile*)pVehicle)->m_bombType;
|
||||
}
|
||||
|
@ -1936,11 +1930,11 @@ CVehicle* CStoredCar::RestoreCar()
|
|||
}
|
||||
pVehicle->bHasBeenOwnedByPlayer = true;
|
||||
pVehicle->m_nDoorLock = CARLOCK_UNLOCKED;
|
||||
pVehicle->bBulletProof = m_bBulletproof;
|
||||
pVehicle->bFireProof = m_bFireproof;
|
||||
pVehicle->bExplosionProof = m_bExplosionproof;
|
||||
pVehicle->bCollisionProof = m_bCollisionproof;
|
||||
pVehicle->bMeleeProof = m_bMeleeproof;
|
||||
if (m_nFlags & FLAG_BULLETPROOF) pVehicle->bBulletProof = true;
|
||||
if (m_nFlags & FLAG_FIREPROOF) pVehicle->bFireProof = true;
|
||||
if (m_nFlags & FLAG_EXPLOSIONPROOF) pVehicle->bExplosionProof = true;
|
||||
if (m_nFlags & FLAG_COLLISIONPROOF) pVehicle->bCollisionProof = true;
|
||||
if (m_nFlags & FLAG_MELEEPROOF) pVehicle->bMeleeProof = true;
|
||||
return pVehicle;
|
||||
}
|
||||
|
||||
|
@ -2327,8 +2321,47 @@ void CGarages::Save(uint8 * buf, uint32 * size)
|
|||
WriteSaveBuf(buf, aCarsInSafeHouse2[i]);
|
||||
WriteSaveBuf(buf, aCarsInSafeHouse3[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].field_2);
|
||||
WriteSaveBuf(buf, aGarages[i].m_bClosingWithoutTargetCar);
|
||||
WriteSaveBuf(buf, aGarages[i].m_bDeactivated);
|
||||
WriteSaveBuf(buf, aGarages[i].m_bResprayHappened);
|
||||
ZeroSaveBuf(buf, 2);
|
||||
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_fX1);
|
||||
WriteSaveBuf(buf, aGarages[i].m_fX2);
|
||||
WriteSaveBuf(buf, aGarages[i].m_fY1);
|
||||
WriteSaveBuf(buf, aGarages[i].m_fY2);
|
||||
WriteSaveBuf(buf, aGarages[i].m_fZ1);
|
||||
WriteSaveBuf(buf, aGarages[i].m_fZ2);
|
||||
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 + 4);
|
||||
ZeroSaveBuf(buf, sizeof(aGarages[i].m_sStoredCar));
|
||||
#else
|
||||
WriteSaveBuf(buf, aGarages[i]);
|
||||
#endif
|
||||
}
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
VALIDATESAVEBUF(*size);
|
||||
#endif
|
||||
|
@ -2339,11 +2372,7 @@ const CStoredCar &CStoredCar::operator=(const CStoredCar & other)
|
|||
m_nModelIndex = other.m_nModelIndex;
|
||||
m_vecPos = other.m_vecPos;
|
||||
m_vecAngle = other.m_vecAngle;
|
||||
m_bBulletproof = other.m_bBulletproof;
|
||||
m_bFireproof = other.m_bFireproof;
|
||||
m_bExplosionproof = other.m_bExplosionproof;
|
||||
m_bCollisionproof = other.m_bCollisionproof;
|
||||
m_bMeleeproof = other.m_bMeleeproof;
|
||||
m_nFlags = other.m_nFlags;
|
||||
m_nPrimaryColor = other.m_nPrimaryColor;
|
||||
m_nSecondaryColor = other.m_nSecondaryColor;
|
||||
m_nRadioStation = other.m_nRadioStation;
|
||||
|
@ -2357,7 +2386,7 @@ void CGarages::Load(uint8* buf, uint32 size)
|
|||
{
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
INITSAVEBUF
|
||||
assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
||||
assert(size == (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage)));
|
||||
#else
|
||||
assert(size == 5484);
|
||||
#endif
|
||||
|
@ -2380,7 +2409,45 @@ void CGarages::Load(uint8* buf, uint32 size)
|
|||
ReadSaveBuf(&aCarsInSafeHouse3[i], buf);
|
||||
}
|
||||
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].field_2, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_bClosingWithoutTargetCar, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_bDeactivated, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_bResprayHappened, buf);
|
||||
SkipSaveBuf(buf, 2);
|
||||
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_fX1, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_fX2, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_fY1, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_fY2, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_fZ1, buf);
|
||||
ReadSaveBuf(&aGarages[i].m_fZ2, 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 + 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;
|
||||
|
|
|
@ -51,14 +51,17 @@ enum
|
|||
|
||||
class CStoredCar
|
||||
{
|
||||
enum {
|
||||
FLAG_BULLETPROOF = 0x1,
|
||||
FLAG_FIREPROOF = 0x2,
|
||||
FLAG_EXPLOSIONPROOF = 0x4,
|
||||
FLAG_COLLISIONPROOF = 0x8,
|
||||
FLAG_MELEEPROOF = 0x10,
|
||||
};
|
||||
int32 m_nModelIndex;
|
||||
CVector m_vecPos;
|
||||
CVector m_vecAngle;
|
||||
int32 m_bBulletproof : 1;
|
||||
int32 m_bFireproof : 1;
|
||||
int32 m_bExplosionproof : 1;
|
||||
int32 m_bCollisionproof : 1;
|
||||
int32 m_bMeleeproof : 1;
|
||||
int32 m_nFlags;
|
||||
int8 m_nPrimaryColor;
|
||||
int8 m_nSecondaryColor;
|
||||
int8 m_nRadioStation;
|
||||
|
@ -78,6 +81,13 @@ VALIDATE_SIZE(CStoredCar, 0x28);
|
|||
|
||||
#define SWITCH_GARAGE_DISTANCE_CLOSE 40.0f
|
||||
|
||||
#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)
|
||||
|
||||
class CGarage
|
||||
{
|
||||
public:
|
||||
|
@ -87,7 +97,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;
|
||||
|
|
|
@ -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
|
||||
|
@ -209,6 +215,22 @@ CPhoneInfo::IsMessageBeingDisplayed(int phoneId)
|
|||
return pPhoneDisplayingMessages == &m_aPhones[phoneId];
|
||||
}
|
||||
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
static inline void
|
||||
LoadPhone(CPhone &phone, uint8 *&buf)
|
||||
{
|
||||
ReadSaveBuf(&phone.m_vecPos, buf);
|
||||
SkipSaveBuf(buf, 6 * 4);
|
||||
ReadSaveBuf<uint32>(&phone.m_repeatedMessagePickupStart, buf);
|
||||
uint32 tmp;
|
||||
ReadSaveBuf(&tmp, buf);
|
||||
phone.m_pEntity = (CEntity*)(uintptr)tmp;
|
||||
ReadSaveBuf<PhoneState>(&phone.m_nState, buf);
|
||||
ReadSaveBuf<bool>(&phone.m_visibleToCam, buf);
|
||||
SkipSaveBuf(buf, 3);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CPhoneInfo::Load(uint8 *buf, uint32 size)
|
||||
{
|
||||
|
@ -226,7 +248,12 @@ INITSAVEBUF
|
|||
// We can do it without touching saves. We'll only load script phones, others are already loaded in Initialise
|
||||
for (int i = 0; i < 50; i++) {
|
||||
CPhone phoneToLoad;
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
phoneToLoad.m_apMessages[0]=phoneToLoad.m_apMessages[1]=phoneToLoad.m_apMessages[2]=phoneToLoad.m_apMessages[3]=phoneToLoad.m_apMessages[4]=phoneToLoad.m_apMessages[5] = nil;
|
||||
LoadPhone(phoneToLoad, buf);
|
||||
#else
|
||||
ReadSaveBuf(&phoneToLoad, buf);
|
||||
#endif
|
||||
|
||||
if (ignoreOtherPhones)
|
||||
continue;
|
||||
|
@ -252,7 +279,11 @@ INITSAVEBUF
|
|||
m_nScriptPhonesMax = scriptPhonesMax;
|
||||
|
||||
for (int i = 0; i < NUMPHONES; i++) {
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
LoadPhone(m_aPhones[i], buf);
|
||||
#else
|
||||
ReadSaveBuf(&m_aPhones[i], buf);
|
||||
#endif
|
||||
// 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);
|
||||
|
@ -376,7 +407,7 @@ 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);
|
||||
|
@ -385,12 +416,24 @@ INITSAVEBUF
|
|||
#else
|
||||
for (int phoneId = 0; phoneId < NUMPHONES; phoneId++) {
|
||||
#endif
|
||||
#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)
|
||||
}
|
||||
|
|
|
@ -32,6 +32,12 @@
|
|||
#include "WaterLevel.h"
|
||||
#include "World.h"
|
||||
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
#define PICKUPS_SAVE_SIZE 0x24C0
|
||||
#else
|
||||
#define PICKUPS_SAVE_SIZE sizeof(aPickUps)
|
||||
#endif
|
||||
|
||||
CPickup CPickups::aPickUps[NUMPICKUPS];
|
||||
int16 CPickups::NumMessages;
|
||||
int32 CPickups::aPickUpsCollected[NUMCOLLECTEDPICKUPS];
|
||||
|
@ -1000,10 +1006,23 @@ CPickups::Load(uint8 *buf, uint32 size)
|
|||
INITSAVEBUF
|
||||
|
||||
for (int32 i = 0; i < NUMPICKUPS; i++) {
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
ReadSaveBuf(&aPickUps[i].m_eType, buf);
|
||||
ReadSaveBuf(&aPickUps[i].m_bRemoved, buf);
|
||||
ReadSaveBuf(&aPickUps[i].m_nQuantity, buf);
|
||||
int32 tmp;
|
||||
ReadSaveBuf(&tmp, buf);
|
||||
aPickUps[i].m_pObject = aPickUps[i].m_eType != PICKUP_NONE && tmp != 0 ? CPools::GetObjectPool()->GetSlot(tmp - 1) : nil;
|
||||
ReadSaveBuf(&aPickUps[i].m_nTimer, buf);
|
||||
ReadSaveBuf(&aPickUps[i].m_eModelIndex, buf);
|
||||
ReadSaveBuf(&aPickUps[i].m_nIndex, buf);
|
||||
ReadSaveBuf(&aPickUps[i].m_vecPos, buf);
|
||||
#else
|
||||
ReadSaveBuf(&aPickUps[i], buf);
|
||||
|
||||
if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
|
||||
aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((uintptr)aPickUps[i].m_pObject - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
ReadSaveBuf(&CollectedPickUpIndex, buf);
|
||||
|
@ -1019,14 +1038,26 @@ VALIDATESAVEBUF(size)
|
|||
void
|
||||
CPickups::Save(uint8 *buf, uint32 *size)
|
||||
{
|
||||
*size = sizeof(aPickUps) + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
|
||||
*size = PICKUPS_SAVE_SIZE + sizeof(uint16) + sizeof(uint16) + sizeof(aPickUpsCollected);
|
||||
|
||||
INITSAVEBUF
|
||||
|
||||
for (int32 i = 0; i < NUMPICKUPS; i++) {
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
WriteSaveBuf(buf, aPickUps[i].m_eType);
|
||||
WriteSaveBuf(buf, aPickUps[i].m_bRemoved);
|
||||
WriteSaveBuf(buf, aPickUps[i].m_nQuantity);
|
||||
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);
|
||||
WriteSaveBuf(buf, aPickUps[i].m_nTimer);
|
||||
WriteSaveBuf(buf, aPickUps[i].m_eModelIndex);
|
||||
WriteSaveBuf(buf, aPickUps[i].m_nIndex);
|
||||
WriteSaveBuf(buf, aPickUps[i].m_vecPos);
|
||||
#else
|
||||
CPickup *buf_pickup = WriteSaveBuf(buf, aPickUps[i]);
|
||||
if (buf_pickup->m_eType != PICKUP_NONE && buf_pickup->m_pObject != nil)
|
||||
buf_pickup->m_pObject = (CObject*)(CPools::GetObjectPool()->GetJustIndex_NoFreeAssert(buf_pickup->m_pObject) + 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
WriteSaveBuf(buf, CollectedPickUpIndex);
|
||||
|
|
|
@ -2089,33 +2089,33 @@ VALIDATESAVEBUF(size)
|
|||
void CRunningScript::Save(uint8*& buf)
|
||||
{
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
SkipSaveBuf(buf, 8);
|
||||
ZeroSaveBuf(buf, 8);
|
||||
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 + NUM_TIMERS == 18, "Compatibility loss: NUM_LOCAL_VARS + NUM_TIMERS != 18");
|
||||
#endif
|
||||
for (int i = 0; i < NUM_LOCAL_VARS + NUM_TIMERS; i++)
|
||||
WriteSaveBuf<int32>(buf, m_anLocalVariables[i]);
|
||||
WriteSaveBuf<bool>(buf, m_bCondResult);
|
||||
WriteSaveBuf<bool>(buf, m_bIsMissionScript);
|
||||
WriteSaveBuf<bool>(buf, m_bSkipWakeTime);
|
||||
SkipSaveBuf(buf, 1);
|
||||
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_bCondResult);
|
||||
WriteSaveBuf(buf, m_bIsMissionScript);
|
||||
WriteSaveBuf(buf, m_bSkipWakeTime);
|
||||
ZeroSaveBuf(buf, 1);
|
||||
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
|
||||
|
|
|
@ -281,9 +281,9 @@ INITSAVEBUF
|
|||
#else
|
||||
if ((pVehicle->IsCar() || pVehicle->IsBoat()) && 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
|
||||
|
@ -292,7 +292,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));
|
||||
|
@ -303,7 +303,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));
|
||||
|
|
|
@ -10,6 +10,14 @@
|
|||
#include "Timer.h"
|
||||
#include "SaveBuf.h"
|
||||
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
#define ZONEARRAY_SAVE_SIZE 0xAF0
|
||||
#define MAPZONEARRAY_SAVE_SIZE 0x578
|
||||
#else
|
||||
#define ZONEARRAY_SAVE_SIZE sizeof(ZoneArray)
|
||||
#define MAPZONEARRAY_SAVE_SIZE sizeof(MapZoneArray)
|
||||
#endif
|
||||
|
||||
eLevelName CTheZones::m_CurrLevel;
|
||||
CZone *CTheZones::m_pPlayersZone;
|
||||
int16 CTheZones::FindIndex;
|
||||
|
@ -633,6 +641,28 @@ CTheZones::InitialiseAudioZoneArray(void)
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
static inline void
|
||||
SaveOneZone(CZone &zone, uint8 *&buffer)
|
||||
{
|
||||
memcpy(buffer, zone.name, sizeof(zone.name));
|
||||
SkipSaveBuf(buffer, sizeof(zone.name));
|
||||
WriteSaveBuf(buffer, zone.minx);
|
||||
WriteSaveBuf(buffer, zone.miny);
|
||||
WriteSaveBuf(buffer, zone.minz);
|
||||
WriteSaveBuf(buffer, zone.maxx);
|
||||
WriteSaveBuf(buffer, zone.maxy);
|
||||
WriteSaveBuf(buffer, zone.maxz);
|
||||
WriteSaveBuf(buffer, zone.type);
|
||||
WriteSaveBuf(buffer, zone.level);
|
||||
WriteSaveBuf(buffer, zone.zoneinfoDay);
|
||||
WriteSaveBuf(buffer, zone.zoneinfoNight);
|
||||
WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.child));
|
||||
WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.parent));
|
||||
WriteSaveBuf(buffer, (int32)CTheZones::GetIndexForZonePointer(zone.next));
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
|
||||
{
|
||||
|
@ -643,9 +673,9 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
|
|||
+ sizeof(int32) // GetIndexForZonePointer
|
||||
+ sizeof(m_CurrLevel) + sizeof(FindIndex)
|
||||
+ sizeof(int16) // padding
|
||||
+ sizeof(ZoneArray) + sizeof(ZoneInfoArray)
|
||||
+ ZONEARRAY_SAVE_SIZE + sizeof(ZoneInfoArray)
|
||||
+ sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos)
|
||||
+ sizeof(MapZoneArray) + sizeof(AudioZoneArray)
|
||||
+ MAPZONEARRAY_SAVE_SIZE + sizeof(AudioZoneArray)
|
||||
+ sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones);
|
||||
|
||||
WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE);
|
||||
|
@ -656,10 +686,14 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
|
|||
WriteSaveBuf(buffer, (int16)0); // padding
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
SaveOneZone(ZoneArray[i], buffer);
|
||||
#else
|
||||
CZone *zone = WriteSaveBuf(buffer, ZoneArray[i]);
|
||||
zone->child = (CZone*)GetIndexForZonePointer(ZoneArray[i].child);
|
||||
zone->parent = (CZone*)GetIndexForZonePointer(ZoneArray[i].parent);
|
||||
zone->next = (CZone*)GetIndexForZonePointer(ZoneArray[i].next);
|
||||
#endif
|
||||
}
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)
|
||||
|
@ -669,7 +703,9 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
|
|||
WriteSaveBuf(buffer, TotalNumberOfZoneInfos);
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) {
|
||||
#ifndef COMPATIBLE_SAVES
|
||||
CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]);
|
||||
#endif
|
||||
|
||||
/*
|
||||
The call of GetIndexForZonePointer is wrong, as it is
|
||||
|
@ -679,9 +715,13 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
|
|||
assert(MapZoneArray[i].child == nil);
|
||||
assert(MapZoneArray[i].parent == nil);
|
||||
assert(MapZoneArray[i].next == nil);
|
||||
#ifndef COMPATIBLE_SAVES
|
||||
zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child);
|
||||
zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent);
|
||||
zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next);
|
||||
#else
|
||||
SaveOneZone(MapZoneArray[i], buffer);
|
||||
#endif
|
||||
}
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++)
|
||||
|
@ -693,6 +733,32 @@ CTheZones::SaveAllZones(uint8 *buffer, uint32 *size)
|
|||
VALIDATESAVEBUF(*size)
|
||||
}
|
||||
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
static inline void
|
||||
LoadOneZone(CZone &zone, uint8 *&buffer)
|
||||
{
|
||||
memcpy(zone.name, buffer, sizeof(zone.name));
|
||||
SkipSaveBuf(buffer, sizeof(zone.name));
|
||||
ReadSaveBuf(&zone.minx, buffer);
|
||||
ReadSaveBuf(&zone.miny, buffer);
|
||||
ReadSaveBuf(&zone.minz, buffer);
|
||||
ReadSaveBuf(&zone.maxx, buffer);
|
||||
ReadSaveBuf(&zone.maxy, buffer);
|
||||
ReadSaveBuf(&zone.maxz, buffer);
|
||||
ReadSaveBuf(&zone.type, buffer);
|
||||
ReadSaveBuf(&zone.level, buffer);
|
||||
ReadSaveBuf(&zone.zoneinfoDay, buffer);
|
||||
ReadSaveBuf(&zone.zoneinfoNight, buffer);
|
||||
int32 tmp;
|
||||
ReadSaveBuf(&tmp, buffer);
|
||||
zone.child = CTheZones::GetPointerForZoneIndex(tmp);
|
||||
ReadSaveBuf(&tmp, buffer);
|
||||
zone.parent = CTheZones::GetPointerForZoneIndex(tmp);
|
||||
ReadSaveBuf(&tmp, buffer);
|
||||
zone.next = CTheZones::GetPointerForZoneIndex(tmp);
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
|
||||
{
|
||||
|
@ -708,11 +774,15 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
|
|||
SkipSaveBuf(buffer, 2);
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
LoadOneZone(ZoneArray[i], buffer);
|
||||
#else
|
||||
ReadSaveBuf(&ZoneArray[i], buffer);
|
||||
|
||||
ZoneArray[i].child = GetPointerForZoneIndex((uintptr)ZoneArray[i].child);
|
||||
ZoneArray[i].parent = GetPointerForZoneIndex((uintptr)ZoneArray[i].parent);
|
||||
ZoneArray[i].next = GetPointerForZoneIndex((uintptr)ZoneArray[i].next);
|
||||
#endif
|
||||
}
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++)
|
||||
|
@ -722,6 +792,9 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
|
|||
ReadSaveBuf(&TotalNumberOfZoneInfos, buffer);
|
||||
|
||||
for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
LoadOneZone(MapZoneArray[i], buffer);
|
||||
#else
|
||||
ReadSaveBuf(&MapZoneArray[i], buffer);
|
||||
|
||||
/*
|
||||
|
@ -732,6 +805,7 @@ CTheZones::LoadAllZones(uint8 *buffer, uint32 size)
|
|||
MapZoneArray[i].child = GetPointerForZoneIndex((uintptr)MapZoneArray[i].child);
|
||||
MapZoneArray[i].parent = GetPointerForZoneIndex((uintptr)MapZoneArray[i].parent);
|
||||
MapZoneArray[i].next = GetPointerForZoneIndex((uintptr)MapZoneArray[i].next);
|
||||
#endif
|
||||
assert(MapZoneArray[i].child == nil);
|
||||
assert(MapZoneArray[i].parent == nil);
|
||||
assert(MapZoneArray[i].next == nil);
|
||||
|
|
|
@ -237,7 +237,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
|
||||
|
@ -464,6 +465,7 @@ enum Config {
|
|||
#define THIS_IS_STUPID
|
||||
#undef MORE_LANGUAGES
|
||||
#undef COMPATIBLE_SAVES
|
||||
#undef FIX_INCOMPATIBLE_SAVES
|
||||
#undef LOAD_INI_SETTINGS
|
||||
|
||||
#undef ASPECT_RATIO_SCALE
|
||||
|
|
|
@ -732,7 +732,7 @@ CEntity::SaveEntityFlags(uint8*& buf)
|
|||
if (bZoneCulled) tmp |= BIT(30);
|
||||
if (bZoneCulled2) tmp |= BIT(31);
|
||||
|
||||
WriteSaveBuf<uint32>(buf, tmp);
|
||||
WriteSaveBuf(buf, tmp);
|
||||
|
||||
tmp = 0;
|
||||
|
||||
|
@ -748,7 +748,7 @@ CEntity::SaveEntityFlags(uint8*& buf)
|
|||
if (bDistanceFade) tmp |= BIT(8);
|
||||
if (m_flagE2) tmp |= BIT(9);
|
||||
|
||||
WriteSaveBuf<uint32>(buf, tmp);
|
||||
WriteSaveBuf(buf, tmp);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -10,6 +10,12 @@
|
|||
#include "DMAudio.h"
|
||||
#include "screendroplets.h"
|
||||
|
||||
#ifdef COMPATIBLE_SAVES
|
||||
#define PARTICLE_OBJECT_SIZEOF 0x88
|
||||
#else
|
||||
#define PARTICLE_OBJECT_SIZEOF sizeof(CParticleObject)
|
||||
#endif
|
||||
|
||||
|
||||
CParticleObject gPObjectArray[MAX_PARTICLEOBJECTS];
|
||||
|
||||
|
@ -1111,6 +1117,49 @@ 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
|
||||
{
|
||||
ZeroBuf(buffer, 4);
|
||||
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)
|
||||
{
|
||||
|
@ -1128,27 +1177,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 != NULL; 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 != NULL; 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;
|
||||
|
@ -1166,7 +1223,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 )
|
||||
|
@ -1177,14 +1234,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 == NULL )
|
||||
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;
|
||||
|
@ -1200,6 +1260,47 @@ 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
|
||||
{
|
||||
SkipBuf(buffer, 4);
|
||||
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++;
|
||||
}
|
||||
|
|
|
@ -8496,21 +8496,21 @@ CPed::renderLimb(int node)
|
|||
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, 351);
|
||||
ZeroSaveBuf(buf, 351);
|
||||
CopyToBuf(buf, m_fHealth);
|
||||
CopyToBuf(buf, m_fArmour);
|
||||
SkipSaveBuf(buf, 148);
|
||||
ZeroSaveBuf(buf, 148);
|
||||
for (int i = 0; i < 13; i++) // has to be hardcoded
|
||||
m_weapons[i].Save(buf);
|
||||
SkipSaveBuf(buf, 5);
|
||||
ZeroSaveBuf(buf, 5);
|
||||
CopyToBuf(buf, m_maxWeaponTypeAllowed);
|
||||
SkipSaveBuf(buf, 162);
|
||||
ZeroSaveBuf(buf, 162);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -1492,14 +1492,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, 116);
|
||||
ZeroSaveBuf(buf, 116);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -600,6 +600,552 @@ 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); // 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 == 1032)
|
||||
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 += 760; // skip everything before the first garage
|
||||
buf += save_type & SAVE_TYPE_32_BIT ? 28 : 40; // skip first garage up to m_fX1
|
||||
|
||||
// now the values we want to verify
|
||||
float fX1, fX2, fY1, fY2, fZ1, fZ2;
|
||||
|
||||
ReadBuf(buf, fX1);
|
||||
ReadBuf(buf, fX2);
|
||||
ReadBuf(buf, fY1);
|
||||
ReadBuf(buf, fY2);
|
||||
ReadBuf(buf, fZ1);
|
||||
ReadBuf(buf, fZ2);
|
||||
|
||||
if (fX1 == CRUSHER_GARAGE_X1 && fX2 == CRUSHER_GARAGE_X2 &&
|
||||
fY1 == CRUSHER_GARAGE_Y1 && fY2 == CRUSHER_GARAGE_Y2 &&
|
||||
fZ1 == CRUSHER_GARAGE_Z1 && fZ2 == CRUSHER_GARAGE_Z2)
|
||||
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: 5484
|
||||
// x86 msvc: 5240
|
||||
// x86 gcc: 5040
|
||||
// amd64 msvc: 5880
|
||||
// amd64 gcc: 5808
|
||||
|
||||
uint8 *buf_start = buf;
|
||||
uint8 *buf2_start = buf2;
|
||||
uint32 read;
|
||||
uint32 written = 5240;
|
||||
|
||||
if (save_type & SAVE_TYPE_32_BIT && save_type & SAVE_TYPE_GCC)
|
||||
read = 5040;
|
||||
else if (save_type & SAVE_TYPE_64_BIT && save_type & SAVE_TYPE_GCC)
|
||||
read = 5808;
|
||||
else
|
||||
read = 5880;
|
||||
|
||||
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++)
|
||||
{
|
||||
#define FixStoredCar(buf, buf2) \
|
||||
do { \
|
||||
CopyBuf(buf, buf2, 4 + sizeof(CVector) + sizeof(CVector)); \
|
||||
uint8 nFlags8; \
|
||||
ReadBuf(buf, nFlags8); \
|
||||
int32 nFlags32 = nFlags8; \
|
||||
WriteBuf(buf2, nFlags32); \
|
||||
CopyBuf(buf, buf2, 1 * 6); \
|
||||
SkipBuf(buf, 1); \
|
||||
SkipBuf(buf2, 2); \
|
||||
} while(0)
|
||||
|
||||
FixStoredCar(buf, buf2);
|
||||
FixStoredCar(buf, buf2);
|
||||
FixStoredCar(buf, buf2);
|
||||
|
||||
#undef FixStoredCar
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS);
|
||||
CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS);
|
||||
CopyBuf(buf, buf2, sizeof(CStoredCar) * NUM_GARAGE_STORED_CARS);
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < NUM_GARAGES; i++)
|
||||
{
|
||||
// skip the last 5 garages in 64bit builds without FIX_GARAGE_SIZE since they weren't actually saved and are unused
|
||||
if (save_type & SAVE_TYPE_64_BIT && *size == 5484 && i >= NUM_GARAGES - 5)
|
||||
{
|
||||
SkipBuf(buf, 160); // sizeof(CGarage) on x64
|
||||
SkipBuf(buf2, 140); // sizeof(CGarage) on x86
|
||||
}
|
||||
else
|
||||
{
|
||||
CopyBuf(buf, buf2, 1 * 6);
|
||||
SkipBoth(buf, buf2, 2);
|
||||
CopyBuf(buf, buf2, 4);
|
||||
SkipBuf(buf, ptrsize - 4); // write 4 bytes padding if 8 byte pointer, if not, write 0
|
||||
SkipBuf(buf, ptrsize * 2);
|
||||
SkipBuf(buf2, 4 * 2);
|
||||
CopyBuf(buf, buf2, 1 * 7);
|
||||
SkipBoth(buf, buf2, 1);
|
||||
CopyBuf(buf, buf2, 4 * 15 + 1);
|
||||
SkipBoth(buf, buf2, 3);
|
||||
SkipBuf(buf, ptrsize * 2);
|
||||
SkipBuf(buf2, 4 * 2);
|
||||
|
||||
if (save_type & SAVE_TYPE_GCC)
|
||||
SkipBuf(buf, save_type & SAVE_TYPE_64_BIT ? 36 + 4 : 36); // sizeof(CStoredCar) on gcc 64/32 before fix
|
||||
else
|
||||
SkipBuf(buf, sizeof(CStoredCar));
|
||||
|
||||
SkipBuf(buf2, sizeof(CStoredCar));
|
||||
}
|
||||
}
|
||||
|
||||
*size = 0;
|
||||
|
||||
assert(buf - buf_start == read);
|
||||
assert(buf2 - buf2_start == written);
|
||||
|
||||
#ifdef FIX_GARAGE_SIZE
|
||||
*size = (6 * sizeof(uint32) + TOTAL_COLLECTCARS_GARAGES * sizeof(*CGarages::CarTypesCollected) + sizeof(uint32) + 3 * NUM_GARAGE_STORED_CARS * sizeof(CStoredCar) + NUM_GARAGES * sizeof(CGarage));
|
||||
#else
|
||||
*size = 5484;
|
||||
#endif
|
||||
}
|
||||
|
||||
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) + 0x400; // 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, 15 * 4 + sizeof(CVector) * 3 + sizeof(CVector2D));
|
||||
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 = 0x3480 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // sizeof(aPickUps)
|
||||
uint32 written = 0x24C0 + sizeof(uint16) + sizeof(uint16) + sizeof(int32) * NUMCOLLECTEDPICKUPS; // see PICKUPS_SAVE_SIZE
|
||||
|
||||
for (int32 i = 0; i < NUMPICKUPS; i++)
|
||||
{
|
||||
CopyBuf(buf, buf2, 1 + 1 + 2);
|
||||
SkipBuf(buf, 4);
|
||||
CopyPtr(buf, buf2);
|
||||
CopyBuf(buf, buf2, 4 + 2 + 2 + sizeof(CVector));
|
||||
SkipBuf(buf, 4);
|
||||
}
|
||||
|
||||
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
|
||||
FixZones(uint8 save_type, uint8 *buf, uint8 *buf2, uint32 *size)
|
||||
{
|
||||
uint8 *buf_start = buf;
|
||||
uint8 *buf2_start = buf2;
|
||||
uint32 read = 11300; // see SaveAllZones
|
||||
uint32 written = 10100; // see SaveAllZones
|
||||
|
||||
CopyBuf(buf, buf2, 1 * 4);
|
||||
|
||||
SkipBuf(buf, 4);
|
||||
uint32 hdr_size = 10100 - (1 * 4 + 4); // see SaveAllZones
|
||||
WriteBuf(buf2, hdr_size);
|
||||
|
||||
CopyBuf(buf, buf2, 4 * 2 + 2);
|
||||
SkipBoth(buf, buf2, 2);
|
||||
|
||||
#define FixOneZone(buf, buf2) \
|
||||
do { \
|
||||
CopyBuf(buf, buf2, 8 + 8 * 4 + 2 * 2); \
|
||||
SkipBuf(buf, 4) |