summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/control/CarGen.cpp136
-rw-r--r--src/control/CarGen.h4
-rw-r--r--src/control/PathFind.cpp18
-rw-r--r--src/control/PathFind.h4
-rw-r--r--src/control/Phones.cpp43
-rw-r--r--src/control/Phones.h4
-rw-r--r--src/control/Pickups.cpp50
-rw-r--r--src/control/Pickups.h4
-rw-r--r--src/core/CutsceneMgr.cpp44
-rw-r--r--src/core/Streaming.cpp18
-rw-r--r--src/core/common.h51
-rw-r--r--src/core/config.h1
-rw-r--r--src/peds/PedType.cpp57
-rw-r--r--src/peds/PedType.h4
-rw-r--r--src/render/MoneyMessages.cpp86
-rw-r--r--src/render/MoneyMessages.h24
-rw-r--r--src/render/SpecialFX.cpp87
-rw-r--r--src/render/SpecialFX.h26
-rw-r--r--src/vehicles/Train.cpp2
19 files changed, 340 insertions, 323 deletions
diff --git a/src/control/CarGen.cpp b/src/control/CarGen.cpp
index 65a23c8c..49a96f50 100644
--- a/src/control/CarGen.cpp
+++ b/src/control/CarGen.cpp
@@ -187,48 +187,57 @@ bool CCarGenerator::CheckIfWithinRangeOfAnyPlayer()
return DotProduct2D(direction, FindPlayerSpeed()) <= 0;
}
-void CCarGenerator::Save(uint8* buffer)
+void CCarGenerator::Save(uint8 *&buffer)
{
- *(uint32*)(buffer) = m_nModelIndex;
- *(CVector*)(buffer + 4) = m_vecPos;
- *(float*)(buffer + 16) = m_fAngle;
- *(int16*)(buffer + 20) = m_nColor1;
- *(int16*)(buffer + 22) = m_nColor2;
- *(bool*)(buffer + 24) = m_bForceSpawn;
- *(uint8*)(buffer + 25) = m_nAlarm;
- *(uint8*)(buffer + 26) = m_nDoorlock;
- *(uint8*)(buffer + 27) = 0;
- *(uint16*)(buffer + 28) = m_nMinDelay;
- *(uint16*)(buffer + 30) = m_nMaxDelay;
- *(uint32*)(buffer + 32) = m_nTimer;
- *(int32*)(buffer + 36) = m_nVehicleHandle;
- *(uint16*)(buffer + 40) = m_nUsesRemaining;
- *(bool*)(buffer + 42) = m_bIsBlocking;
- *(uint8*)(buffer + 43) = 0;
- *(CVector*)(buffer + 44) = m_vecInf;
- *(CVector*)(buffer + 56) = m_vecSup;
- *(float*)(buffer + 68) = m_fSize;
+ WriteSaveBuf(buffer, m_nModelIndex);
+ WriteSaveBuf(buffer, m_vecPos);
+ WriteSaveBuf(buffer, m_fAngle);
+ WriteSaveBuf(buffer, m_nColor1);
+ WriteSaveBuf(buffer, m_nColor2);
+ WriteSaveBuf(buffer, m_bForceSpawn);
+ WriteSaveBuf(buffer, m_nAlarm);
+ WriteSaveBuf(buffer, m_nDoorlock);
+ WriteSaveBuf(buffer, (uint8)0);
+ WriteSaveBuf(buffer, m_nMinDelay);
+ WriteSaveBuf(buffer, m_nMaxDelay);
+ WriteSaveBuf(buffer, m_nTimer);
+ WriteSaveBuf(buffer, m_nVehicleHandle);
+ WriteSaveBuf(buffer, m_nUsesRemaining);
+ WriteSaveBuf(buffer, m_bIsBlocking);
+ WriteSaveBuf(buffer, (uint8)0);
+ WriteSaveBuf(buffer, m_vecInf);
+ WriteSaveBuf(buffer, m_vecSup);
+ WriteSaveBuf(buffer, m_fSize);
+
+ // or
+ //WriteSaveBuf(buffer, *this);
+
}
-void CCarGenerator::Load(uint8* buffer)
+void CCarGenerator::Load(uint8 *&buffer)
{
- m_nModelIndex = *(uint32*)(buffer);
- m_vecPos = *(CVector*)(buffer + 4);
- m_fAngle = *(float*)(buffer + 16);
- m_nColor1 = *(int16*)(buffer + 20);
- m_nColor2 = *(int16*)(buffer + 22);
- m_bForceSpawn = *(bool*)(buffer + 24);
- m_nAlarm = *(uint8*)(buffer + 25);
- m_nDoorlock = *(uint8*)(buffer + 26);
- m_nMinDelay = *(uint16*)(buffer + 28);
- m_nMaxDelay = *(uint16*)(buffer + 30);
- m_nTimer = *(uint32*)(buffer + 32);
- m_nVehicleHandle = *(int32*)(buffer + 36);
- m_nUsesRemaining = *(uint16*)(buffer + 40);
- m_bIsBlocking = *(bool*)(buffer + 42);
- m_vecInf = *(CVector*)(buffer + 44);
- m_vecSup = *(CVector*)(buffer + 56);
- m_fSize = *(float*)(buffer + 68);
+ m_nModelIndex = ReadSaveBuf<uint32>(buffer);
+ m_vecPos = ReadSaveBuf<CVector>(buffer);
+ m_fAngle = ReadSaveBuf<float>(buffer);
+ m_nColor1 = ReadSaveBuf<int16>(buffer);
+ m_nColor2 = ReadSaveBuf<int16>(buffer);
+ m_bForceSpawn = ReadSaveBuf<uint8>(buffer);
+ m_nAlarm = ReadSaveBuf<uint8>(buffer);
+ m_nDoorlock = ReadSaveBuf<uint8>(buffer);
+ ReadSaveBuf<uint8>(buffer);
+ m_nMinDelay = ReadSaveBuf<uint16>(buffer);
+ m_nMaxDelay = ReadSaveBuf<uint16>(buffer);
+ m_nTimer = ReadSaveBuf<uint32>(buffer);
+ m_nVehicleHandle = ReadSaveBuf<int32>(buffer);
+ m_nUsesRemaining = ReadSaveBuf<uint16>(buffer);
+ m_bIsBlocking = ReadSaveBuf<bool>(buffer);
+ ReadSaveBuf<uint8>(buffer);
+ m_vecInf = ReadSaveBuf<CVector>(buffer);
+ m_vecSup = ReadSaveBuf<CVector>(buffer);
+ m_fSize = ReadSaveBuf<float>(buffer);
+
+ // or
+ //*this = ReadSaveBuf<CCarGenerator>(buffer);
}
void CTheCarGenerators::Process()
@@ -259,45 +268,40 @@ void CTheCarGenerators::Init()
void CTheCarGenerators::SaveAllCarGenerators(uint8 *buffer, uint32 *size)
{
- *size = 28 + 72 * NUM_CARGENS;
- buffer[0] = 'C';
- buffer[1] = 'G';
- buffer[2] = 'N';
- buffer[3] = '\0';
- *(uint32*)(buffer + 4) = *size - 8;
- *(uint32*)(buffer + 8) = 12; /* what is this? */
- *(uint32*)(buffer + 12) = NumOfCarGenerators;
- *(uint32*)(buffer + 16) = CurrentActiveCount;
- *(uint8*)(buffer + 20) = ProcessCounter;
- *(uint8*)(buffer + 21) = GenerateEvenIfPlayerIsCloseCounter;
- *(uint16*)(buffer + 22) = 0;
- *(uint32*)(buffer + 24) = 72 * NUM_CARGENS;
- buffer += 28;
+ *size = 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE;
+INITSAVEBUF
+ WriteSaveHeader(buffer, 'C','G','N','\0', *size - SAVE_HEADER_SIZE);
+
+ WriteSaveBuf(buffer, 12); /* what is this? */
+ WriteSaveBuf(buffer, NumOfCarGenerators);
+ WriteSaveBuf(buffer, CurrentActiveCount);
+ WriteSaveBuf(buffer, ProcessCounter);
+ WriteSaveBuf(buffer, GenerateEvenIfPlayerIsCloseCounter);
+ WriteSaveBuf(buffer, (int16)0);
+ WriteSaveBuf(buffer, sizeof(CarGeneratorArray));
for (int i = 0; i < NUM_CARGENS; i++){
CarGeneratorArray[i].Save(buffer);
- buffer += 72;
}
+VALIDATESAVEBUF(*size)
}
void CTheCarGenerators::LoadAllCarGenerators(uint8* buffer, uint32 size)
{
Init();
- assert(size == 28 + NUM_CARGENS * 72);
- assert(buffer[0] == 'C');
- assert(buffer[1] == 'G');
- assert(buffer[2] == 'N');
- assert(buffer[3] == '\0');
- assert(*(uint32*)(buffer + 4) == size - 8);
- NumOfCarGenerators = *(uint32*)(buffer + 12);
- CurrentActiveCount = *(uint32*)(buffer + 16);
- ProcessCounter = *(uint8*)(buffer + 20);
- GenerateEvenIfPlayerIsCloseCounter = *(uint8*)(buffer + 21);
- assert(*(uint32*)(buffer + 24) == 72 * NUM_CARGENS);
- buffer += 28;
+INITSAVEBUF
+ assert(size == 20 + sizeof(CarGeneratorArray) + SAVE_HEADER_SIZE);
+ CheckSaveHeader(buffer, 'C','G','N','\0', size - SAVE_HEADER_SIZE);
+ ReadSaveBuf<uint32>(buffer);
+ NumOfCarGenerators = ReadSaveBuf<uint32>(buffer);
+ CurrentActiveCount = ReadSaveBuf<uint32>(buffer);
+ ProcessCounter = ReadSaveBuf<uint8>(buffer);
+ GenerateEvenIfPlayerIsCloseCounter = ReadSaveBuf<uint8>(buffer);
+ ReadSaveBuf<int16>(buffer);
+ assert(ReadSaveBuf<uint32>(buffer) == sizeof(CarGeneratorArray));
for (int i = 0; i < NUM_CARGENS; i++) {
CarGeneratorArray[i].Load(buffer);
- buffer += 72;
}
+VALIDATESAVEBUF(size)
}
STARTPATCHES
diff --git a/src/control/CarGen.h b/src/control/CarGen.h
index c1ca304c..75acdd56 100644
--- a/src/control/CarGen.h
+++ b/src/control/CarGen.h
@@ -34,8 +34,8 @@ public:
void Setup(float x, float y, float z, float angle, int32 mi, int16 color1, int16 color2, uint8 force, uint8 alarm, uint8 lock, uint16 min_delay, uint16 max_delay);
bool CheckForBlockage();
bool CheckIfWithinRangeOfAnyPlayer();
- void Save(uint8*);
- void Load(uint8*);
+ void Save(uint8*&);
+ void Load(uint8*&);
void SetUsesRemaining(uint16 uses) { m_nUsesRemaining = uses; }
};
diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp
index e9b33395..e9276dde 100644
--- a/src/control/PathFind.cpp
+++ b/src/control/PathFind.cpp
@@ -1409,40 +1409,40 @@ CPathFind::TestCoorsCloseness(CVector target, uint8 type, CVector start)
}
void
-CPathFind::Save(uint8 *buffer, uint32 *length)
+CPathFind::Save(uint8 *buf, uint32 *size)
{
int i;
int n = m_numPathNodes/8 + 1;
- *length = 2*n;
+ *size = 2*n;
for(i = 0; i < m_numPathNodes; i++)
if(m_pathNodes[i].bDisabled)
- buffer[i/8] |= 1 << i%8;
+ buf[i/8] |= 1 << i%8;
else
- buffer[i/8] &= ~(1 << i%8);
+ buf[i/8] &= ~(1 << i%8);
for(i = 0; i < m_numPathNodes; i++)
if(m_pathNodes[i].bBetweenLevels)
- buffer[i/8 + n] |= 1 << i%8;
+ buf[i/8 + n] |= 1 << i%8;
else
- buffer[i/8 + n] &= ~(1 << i%8);
+ buf[i/8 + n] &= ~(1 << i%8);
}
void
-CPathFind::Load(uint8 *buffer, uint32 length)
+CPathFind::Load(uint8 *buf, uint32 size)
{
int i;
int n = m_numPathNodes/8 + 1;
for(i = 0; i < m_numPathNodes; i++)
- if(buffer[i/8] & (1 << i%8))
+ if(buf[i/8] & (1 << i%8))
m_pathNodes[i].bDisabled = true;
else
m_pathNodes[i].bDisabled = false;
for(i = 0; i < m_numPathNodes; i++)
- if(buffer[i/8 + n] & (1 << i%8))
+ if(buf[i/8 + n] & (1 << i%8))
m_pathNodes[i].bBetweenLevels = true;
else
m_pathNodes[i].bBetweenLevels = false;
diff --git a/src/control/PathFind.h b/src/control/PathFind.h
index 91e2e0b1..de30d70b 100644
--- a/src/control/PathFind.h
+++ b/src/control/PathFind.h
@@ -186,8 +186,8 @@ public:
void FindNextNodeWandering(uint8, CVector, CPathNode**, CPathNode**, uint8, uint8*);
void DoPathSearch(uint8 type, CVector start, int32 startNodeId, CVector target, CPathNode **nodes, int16 *numNodes, int16 maxNumNodes, CVehicle *vehicle, float *dist, float distLimit, int32 forcedTargetNode);
bool TestCoorsCloseness(CVector target, uint8 type, CVector start);
- void Save(uint8 *buffer, uint32 *length);
- void Load(uint8 *buffer, uint32 length);
+ void Save(uint8 *buf, uint32 *size);
+ void Load(uint8 *buf, uint32 size);
};
static_assert(sizeof(CPathFind) == 0x49bf4, "CPathFind: error");
diff --git a/src/control/Phones.cpp b/src/control/Phones.cpp
index e2a9ee13..f8005899 100644
--- a/src/control/Phones.cpp
+++ b/src/control/Phones.cpp
@@ -65,27 +65,19 @@ CPhoneInfo::IsMessageBeingDisplayed(int phoneId)
}
void
-CPhoneInfo::Load(CPhoneInfo *source, uint8 buffer)
+CPhoneInfo::Load(uint8 *buf, uint32 size)
{
- // Buffer isn't used.
-
- m_nMax = source->m_nMax;
- m_nNum = source->m_nNum;
- for (int phoneId = 0; phoneId < 50; phoneId++) {
- CPhone *phone = &source->m_aPhones[phoneId];
-
- m_aPhones[phoneId].m_vecPos = phone->m_vecPos;
- memcpy(m_aPhones[phoneId].m_apMessages, phone->m_apMessages, sizeof(wchar*) * 6);
- m_aPhones[phoneId].m_lastTimeRepeatedMsgShown = phone->m_lastTimeRepeatedMsgShown;
- m_aPhones[phoneId].m_pEntity = phone->m_pEntity;
- m_aPhones[phoneId].m_nState = phone->m_nState;
- m_aPhones[phoneId].field_30 = phone->field_30;
-
+INITSAVEBUF
+ m_nMax = ReadSaveBuf<int32>(buf);
+ m_nNum = ReadSaveBuf<int32>(buf);
+ for (int i = 0; i < 50; i++) {
+ m_aPhones[i] = ReadSaveBuf<CPhone>(buf);
// It's saved as building pool index in save file, convert it to true entity
- if (phone->m_pEntity) {
- m_aPhones[phoneId].m_pEntity = CPools::GetBuildingPool()->GetSlot((int)phone->m_pEntity - 1);
+ if (m_aPhones[i].m_pEntity) {
+ m_aPhones[i].m_pEntity = CPools::GetBuildingPool()->GetSlot((int)m_aPhones[i].m_pEntity - 1);
}
}
+VALIDATESAVEBUF(size)
}
void
@@ -174,26 +166,21 @@ CPhoneInfo::Initialise(void)
}
void
-CPhoneInfo::Save(CPhoneInfo *destination, uint32 *size)
+CPhoneInfo::Save(uint8 *buf, uint32 *size)
{
*size = sizeof(CPhoneInfo);
- destination->m_nMax = this->m_nMax;
- destination->m_nNum = m_nNum;
+INITSAVEBUF
+ WriteSaveBuf(buf, m_nMax);
+ WriteSaveBuf(buf, m_nNum);
for(int phoneId = 0; phoneId < 50; phoneId++) {
- CPhone* phone = &destination->m_aPhones[phoneId];
-
- phone->m_vecPos = m_aPhones[phoneId].m_vecPos;
- memcpy(phone->m_apMessages, m_aPhones[phoneId].m_apMessages, sizeof(wchar*) * 6);
- phone->m_lastTimeRepeatedMsgShown = m_aPhones[phoneId].m_lastTimeRepeatedMsgShown;
- phone->m_pEntity = m_aPhones[phoneId].m_pEntity;
- phone->m_nState = m_aPhones[phoneId].m_nState;
- phone->field_30 = m_aPhones[phoneId].field_30;
+ 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((CBuilding*)phone->m_pEntity) + 1);
}
}
+VALIDATESAVEBUF(*size)
}
void
diff --git a/src/control/Phones.h b/src/control/Phones.h
index 35389f3f..6842eef4 100644
--- a/src/control/Phones.h
+++ b/src/control/Phones.h
@@ -49,12 +49,12 @@ public:
bool PhoneAtThisPosition(CVector);
bool HasMessageBeenDisplayed(int);
bool IsMessageBeingDisplayed(int);
- void Load(CPhoneInfo *source, uint8 buffer);
+ void Load(uint8 *buf, uint32 size);
+ void Save(uint8 *buf, uint32 *size);
void SetPhoneMessage_JustOnce(int phoneId, wchar *msg1, wchar *msg2, wchar *msg3, wchar *msg4, wchar *msg5, wchar *msg6);
void SetPhoneMessage_Repeatedly(int phoneId, wchar *msg1, wchar *msg2, wchar *msg3, wchar *msg4, wchar *msg5, wchar *msg6);
int GrabPhone(float, float);
void Initialise(void);
- void Save(CPhoneInfo*, uint32*);
void Shutdown(void);
};
diff --git a/src/control/Pickups.cpp b/src/control/Pickups.cpp
index 8a67e248..0646e0f6 100644
--- a/src/control/Pickups.cpp
+++ b/src/control/Pickups.cpp
@@ -18,7 +18,7 @@
#include "Garages.h"
#include "Explosion.h"
#include "WaterLevel.h"
-#include "MoneyMessages.h"
+#include "SpecialFX.h"
#include "PointLights.h"
#include "Sprite.h"
#include "Font.h"
@@ -961,53 +961,47 @@ CPickups::RenderPickUpText()
}
void
-CPickups::Load(uint8 *buffer, uint32 size)
+CPickups::Load(uint8 *buf, uint32 size)
{
+INITSAVEBUF
+
for (int32 i = 0; i < NUMPICKUPS; i++) {
- CPickup *buf_pickup = (CPickup*)buffer;
- aPickUps[i] = *buf_pickup;
+ aPickUps[i] = ReadSaveBuf<CPickup>(buf);
if (aPickUps[i].m_eType != PICKUP_NONE && aPickUps[i].m_pObject != nil)
aPickUps[i].m_pObject = CPools::GetObjectPool()->GetSlot((int32)aPickUps[i].m_pObject - 1);
-
- buffer += sizeof(CPickup);
}
- CollectedPickUpIndex = *(uint16*)buffer;
- buffer += sizeof(uint16);
+ CollectedPickUpIndex = ReadSaveBuf<uint16>(buf);
+ ReadSaveBuf<uint16>(buf);
NumMessages = 0;
- buffer += sizeof(uint16);
- for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
- aPickUpsCollected[i] = *(int32*)buffer;
- buffer += sizeof(int32);
- }
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ aPickUpsCollected[i] = ReadSaveBuf<int32>(buf);
+
+VALIDATESAVEBUF(size)
}
void
-CPickups::Save(uint8 *buffer, uint32 *size)
+CPickups::Save(uint8 *buf, uint32 *size)
{
- *size = sizeof(CPickup) * NUMPICKUPS;
- *size += sizeof(uint32) * NUMCOLLECTEDPICKUPS + 4;
+ *size = sizeof(CPickup) * NUMPICKUPS + sizeof(uint16) + sizeof(uint16) + sizeof(uint32) * NUMCOLLECTEDPICKUPS;
+
+INITSAVEBUF
for (int32 i = 0; i < NUMPICKUPS; i++) {
- CPickup *buf_pickup = (CPickup*)buffer;
- *buf_pickup = aPickUps[i];
+ 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(buf_pickup->m_pObject) + 1);
-
- buffer += sizeof(CPickup);
}
- *(uint16*)buffer = CollectedPickUpIndex;
- buffer += sizeof(uint16);
- *(uint16*)buffer = 0; // possibly was NumMessages
- buffer += sizeof(uint16);
+ WriteSaveBuf(buf, CollectedPickUpIndex);
+ WriteSaveBuf(buf, (uint16)0); // possibly was NumMessages
- for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++) {
- *(int32*)buffer = aPickUpsCollected[i];
- buffer += sizeof(int32);
- }
+ for (uint16 i = 0; i < NUMCOLLECTEDPICKUPS; i++)
+ WriteSaveBuf(buf, aPickUpsCollected[i]);
+
+VALIDATESAVEBUF(*size)
}
STARTPATCHES
diff --git a/src/control/Pickups.h b/src/control/Pickups.h
index b49a5544..cbf3f245 100644
--- a/src/control/Pickups.h
+++ b/src/control/Pickups.h
@@ -86,8 +86,8 @@ public:
static int32 GetNewUniquePickupIndex(int32 slot);
static void PassTime(uint32 time);
static bool GivePlayerGoodiesWithPickUpMI(int16 modelIndex, int playerIndex);
- static void Load(uint8 *buffer, uint32 size);
- static void Save(uint8 *buffer, uint32 *size);
+ static void Load(uint8 *buf, uint32 size);
+ static void Save(uint8 *buf, uint32 *size);
static CPickup(&aPickUps)[NUMPICKUPS];
diff --git a/src/core/CutsceneMgr.cpp b/src/core/CutsceneMgr.cpp
index 1461c858..b446cd5d 100644
--- a/src/core/CutsceneMgr.cpp
+++ b/src/core/CutsceneMgr.cpp
@@ -129,7 +129,20 @@ CVector &CCutsceneMgr::ms_cutsceneOffset = *(CVector*)0x8F2C0C;
float &CCutsceneMgr::ms_cutsceneTimer = *(float*)0x941548;
uint32 &CCutsceneMgr::ms_cutsceneLoadStatus = *(uint32*)0x95CB40;
-WRAPPER RpAtomic* CalculateBoundingSphereRadiusCB(RpAtomic * atomic, void *data) { EAXJMP(0x404B40); }
+RpAtomic *
+CalculateBoundingSphereRadiusCB(RpAtomic *atomic, void *data)
+{
+ float radius = RpAtomicGetBoundingSphereMacro(atomic)->radius;
+ RwV3d center = RpAtomicGetBoundingSphereMacro(atomic)->center;
+
+ for (RwFrame *frame = RpAtomicGetFrame(atomic); RwFrameGetParent(frame); frame = RwFrameGetParent(frame))
+ RwV3dTransformPoints(&center, &center, 1, RwFrameGetMatrix(frame));
+
+ float size = RwV3dLength(&center) + radius;
+ if (size > *(float *)data)
+ *(float *)data = size;
+ return atomic;
+}
void
CCutsceneMgr::Initialise(void)
@@ -312,7 +325,7 @@ CCutsceneMgr::CreateCutsceneObject(int modelId)
pModelInfo->SetColModel(pColModel);
clump = (RpClump*)pModelInfo->GetRwObject();
assert(RwObjectGetType(clump) == rpCLUMP);
- RpClumpForAllAtomics(clump, (RpAtomicCallBack)CalculateBoundingSphereRadiusCB, &radius);
+ RpClumpForAllAtomics(clump, CalculateBoundingSphereRadiusCB, &radius);
pColModel->boundingSphere.radius = radius;
pColModel->boundingBox.min = CVector(-radius, -radius, -radius);
@@ -409,17 +422,18 @@ CCutsceneMgr::Update(void)
bool CCutsceneMgr::HasCutsceneFinished(void) { return TheCamera.GetPositionAlongSpline() == 1.0f; }
STARTPATCHES
-InjectHook(0x4045D0, &CCutsceneMgr::Initialise, PATCH_JUMP);
-InjectHook(0x404630, &CCutsceneMgr::Shutdown, PATCH_JUMP);
-InjectHook(0x404650, &CCutsceneMgr::LoadCutsceneData, PATCH_JUMP);
-InjectHook(0x405140, &CCutsceneMgr::FinishCutscene, PATCH_JUMP);
-InjectHook(0x404D80, &CCutsceneMgr::SetHeadAnim, PATCH_JUMP);
-InjectHook(0x404DC0, &CCutsceneMgr::SetupCutsceneToStart, PATCH_JUMP);
-InjectHook(0x404D20, &CCutsceneMgr::SetCutsceneAnim, PATCH_JUMP);
-InjectHook(0x404CD0, &CCutsceneMgr::AddCutsceneHead, PATCH_JUMP);
-InjectHook(0x404BE0, &CCutsceneMgr::CreateCutsceneObject, PATCH_JUMP);
-InjectHook(0x4048E0, &CCutsceneMgr::DeleteCutsceneData, PATCH_JUMP);
-InjectHook(0x404EE0, &CCutsceneMgr::Update, PATCH_JUMP);
-InjectHook(0x4051B0, &CCutsceneMgr::GetCutsceneTimeInMilleseconds, PATCH_JUMP);
-InjectHook(0x4051F0, &CCutsceneMgr::HasCutsceneFinished, PATCH_JUMP);
+ InjectHook(0x4045D0, &CCutsceneMgr::Initialise, PATCH_JUMP);
+ InjectHook(0x404630, &CCutsceneMgr::Shutdown, PATCH_JUMP);
+ InjectHook(0x404650, &CCutsceneMgr::LoadCutsceneData, PATCH_JUMP);
+ InjectHook(0x405140, &CCutsceneMgr::FinishCutscene, PATCH_JUMP);
+ InjectHook(0x404D80, &CCutsceneMgr::SetHeadAnim, PATCH_JUMP);
+ InjectHook(0x404DC0, &CCutsceneMgr::SetupCutsceneToStart, PATCH_JUMP);
+ InjectHook(0x404D20, &CCutsceneMgr::SetCutsceneAnim, PATCH_JUMP);
+ InjectHook(0x404CD0, &CCutsceneMgr::AddCutsceneHead, PATCH_JUMP);
+ InjectHook(0x404BE0, &CCutsceneMgr::CreateCutsceneObject, PATCH_JUMP);
+ InjectHook(0x4048E0, &CCutsceneMgr::DeleteCutsceneData, PATCH_JUMP);
+ InjectHook(0x404EE0, &CCutsceneMgr::Update, PATCH_JUMP);
+ InjectHook(0x4051B0, &CCutsceneMgr::GetCutsceneTimeInMilleseconds, PATCH_JUMP);
+ InjectHook(0x4051F0, &CCutsceneMgr::HasCutsceneFinished, PATCH_JUMP);
+ InjectHook(0x404B40, &CalculateBoundingSphereRadiusCB, PATCH_JUMP);
ENDPATCHES \ No newline at end of file
diff --git a/src/core/Streaming.cpp b/src/core/Streaming.cpp
index e59b2b39..d9dc8628 100644
--- a/src/core/Streaming.cpp
+++ b/src/core/Streaming.cpp
@@ -2401,28 +2401,28 @@ CStreaming::LoadScene(const CVector &pos)
}
void
-CStreaming::MemoryCardSave(uint8 *buffer, uint32 *length)
+CStreaming::MemoryCardSave(uint8 *buf, uint32 *size)
{
int i;
- *length = NUM_DEFAULT_MODELS;
+ *size = NUM_DEFAULT_MODELS;
for(i = 0; i < NUM_DEFAULT_MODELS; i++)
if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)
- buffer[i] = ms_aInfoForModel[i].m_flags;
+ buf[i] = ms_aInfoForModel[i].m_flags;
else
- buffer[i] = 0xFF;
+ buf[i] = 0xFF;
}
void
-CStreaming::MemoryCardLoad(uint8 *buffer, uint32 length)
+CStreaming::MemoryCardLoad(uint8 *buf, uint32 size)
{
uint32 i;
- assert(length == NUM_DEFAULT_MODELS);
- for(i = 0; i < length; i++)
+ assert(size == NUM_DEFAULT_MODELS);
+ for(i = 0; i < size; i++)
if(ms_aInfoForModel[i].m_loadState == STREAMSTATE_LOADED)
- if(buffer[i] != 0xFF)
- ms_aInfoForModel[i].m_flags = buffer[i];
+ if(buf[i] != 0xFF)
+ ms_aInfoForModel[i].m_flags = buf[i];
}
void
diff --git a/src/core/common.h b/src/core/common.h
index caa305d6..3ea37071 100644
--- a/src/core/common.h
+++ b/src/core/common.h
@@ -317,3 +317,54 @@ _TWEEKCLASS(CTweakUInt32, uint32);
_TWEEKCLASS(CTweakFloat, float);
#undef _TWEEKCLASS
+
+#ifdef VALIDATE_SAVE_SIZE
+static int32 _bufBytesRead;
+#define INITSAVEBUF _bufBytesRead = 0;
+#define VALIDATESAVEBUF(b) assert(_bufBytesRead == b);
+#else
+#define INITSAVEBUF
+#define VALIDATESAVEBUF(b)
+#endif
+
+inline void SkipSaveBuf(uint8 *&buf, int32 skip)
+{
+ buf += skip;
+#ifdef VALIDATE_SAVE_SIZE
+ _bufBytesRead += skip;
+#endif
+}
+
+template<typename T>
+inline const T ReadSaveBuf(uint8 *&buf)
+{
+ T &value = *(T*)buf;
+ SkipSaveBuf(buf, sizeof(T));
+ return value;
+}
+
+template<typename T>
+inline T *WriteSaveBuf(uint8 *&buf, const T &value)
+{
+ T *p = (T*)buf;
+ *p = value;
+ SkipSaveBuf(buf, sizeof(T));
+ return p;
+}
+
+
+#define SAVE_HEADER_SIZE (4*sizeof(char)+sizeof(uint32))
+
+#define WriteSaveHeader(buf,a,b,c,d,size) \
+ WriteSaveBuf(buf, a);\
+ WriteSaveBuf(buf, b);\
+ WriteSaveBuf(buf, c);\
+ WriteSaveBuf(buf, d);\
+ WriteSaveBuf(buf, size);
+
+#define CheckSaveHeader(buf,a,b,c,d,size)\
+ assert(ReadSaveBuf<char>(buf) == a);\
+ assert(ReadSaveBuf<char>(buf) == b);\
+ assert(ReadSaveBuf<char>(buf) == c);\
+ assert(ReadSaveBuf<char>(buf) == d);\
+ assert(ReadSaveBuf<uint32>(buf) == size); \ No newline at end of file
diff --git a/src/core/config.h b/src/core/config.h
index a3fbac1b..08ddd007 100644
--- a/src/core/config.h
+++ b/src/core/config.h
@@ -126,6 +126,7 @@ enum Config {
// only in master builds
#else
// not in master builds
+ #define VALIDATE_SAVE_SIZE
#endif
#ifdef FINAL
diff --git a/src/peds/PedType.cpp b/src/peds/PedType.cpp
index 66eb49a1..a8e052c7 100644
--- a/src/peds/PedType.cpp
+++ b/src/peds/PedType.cpp
@@ -181,56 +181,25 @@ CPedType::FindPedFlag(char *type)
}
void
-CPedType::Save(uint8 *buffer, uint32 *length)
+CPedType::Save(uint8 *buf, uint32 *size)
{
- int i;
-
- *length = 8 + NUM_PEDTYPES*32;
-
- buffer[0] = 'P';
- buffer[1] = 'T';
- buffer[2] = 'P';
- buffer[3] = '\0';
- *(uint32*)(buffer+4) = *length - 8;
- buffer += 8;
-
- for(i = 0; i < NUM_PEDTYPES; i++){
- *(uint32*)(buffer) = ms_apPedType[i]->m_flag;
- *(float*)(buffer+4) = ms_apPedType[i]->unknown1;
- *(float*)(buffer+8) = ms_apPedType[i]->unknown2;
- *(float*)(buffer+12) = ms_apPedType[i]->unknown3;
- *(float*)(buffer+16) = ms_apPedType[i]->unknown4;
- *(float*)(buffer+20) = ms_apPedType[i]->unknown5;
- *(uint32*)(buffer+24) = ms_apPedType[i]->m_threats;
- *(uint32*)(buffer+28) = ms_apPedType[i]->m_avoid;
- buffer += 32;
- }
+ *size = sizeof(CPedType) * NUM_PEDTYPES + SAVE_HEADER_SIZE;
+INITSAVEBUF
+ WriteSaveHeader(buf, 'P','T','P','\0', *size - SAVE_HEADER_SIZE);
+ for(int i = 0; i < NUM_PEDTYPES; i++)
+ WriteSaveBuf(buf, *ms_apPedType[i]);
+VALIDATESAVEBUF(*size)
}
void
-CPedType::Load(uint8 *buffer, uint32 length)
+CPedType::Load(uint8 *buf, uint32 size)
{
- int i;
-
- assert(length == 8 + NUM_PEDTYPES*32);
- assert(buffer[0] == 'P');
- assert(buffer[1] == 'T');
- assert(buffer[2] == 'P');
- assert(buffer[3] == '\0');
- assert(*(uint32*)(buffer+4) == length - 8);
- buffer += 8;
+INITSAVEBUF
+ CheckSaveHeader(buf, 'P','T','P','\0', size - SAVE_HEADER_SIZE);
- for(i = 0; i < NUM_PEDTYPES; i++){
- ms_apPedType[i]->m_flag = *(uint32*)(buffer);
- ms_apPedType[i]->unknown1 = *(float*)(buffer+4);
- ms_apPedType[i]->unknown2 = *(float*)(buffer+8);
- ms_apPedType[i]->unknown3 = *(float*)(buffer+12);
- ms_apPedType[i]->unknown4 = *(float*)(buffer+16);
- ms_apPedType[i]->unknown5 = *(float*)(buffer+20);
- ms_apPedType[i]->m_threats = *(uint32*)(buffer+24);
- ms_apPedType[i]->m_avoid = *(uint32*)(buffer+28);
- buffer += 32;
- }
+ for(int i = 0; i < NUM_PEDTYPES; i++)
+ *ms_apPedType[i] = ReadSaveBuf<CPedType>(buf);
+VALIDATESAVEBUF(size)
}
STARTPATCHES
diff --git a/src/peds/PedType.h b/src/peds/PedType.h
index 455d8d8d..9d284318 100644
--- a/src/peds/PedType.h
+++ b/src/peds/PedType.h
@@ -79,8 +79,8 @@ public:
static void LoadPedData(void);
static int32 FindPedType(char *type);
static uint32 FindPedFlag(char *type);
- static void Save(uint8 *buffer, uint32 *length);
- static void Load(uint8 *buffer, uint32 length);
+ static void Save(uint8 *buf, uint32 *size);
+ static void Load(uint8 *buf, uint32 size);
static uint32 GetFlag(int type) { return ms_apPedType[type]->m_flag; }
static uint32 GetAvoid(int type) { return ms_apPedType[type]->m_avoid; }
diff --git a/src/render/MoneyMessages.cpp b/src/render/MoneyMessages.cpp
deleted file mode 100644
index 53d6db58..00000000
--- a/src/render/MoneyMessages.cpp
+++ /dev/null
@@ -1,86 +0,0 @@
-#include "common.h"
-#include "patcher.h"
-#include "MoneyMessages.h"
-#include "Timer.h"
-#include "Sprite.h"
-#include "Font.h"
-#include "Text.h"
-
-#define MONEY_MESSAGE_LIFETIME_MS 2000
-
-CMoneyMessage CMoneyMessages::aMoneyMessages[NUMMONEYMESSAGES];
-
-void
-CMoneyMessage::Render()
-{
- const float MAX_SCALE = 4.0f;
- uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered;
- if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) m_nTimeRegistered = 0;
- else {
- float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS;
- RwV3d vecOut;
- float fDistX, fDistY;
- if (CSprite::CalcScreenCoors(m_vecPosition + CVector(0.0f, 0.0f, fLifeTime), &vecOut, &fDistX, &fDistY, true)) {
- fDistX *= (0.7 * fLifeTime + 2.0) * m_fSize;
- fDistY *= (0.7 * fLifeTime + 2.0) * m_fSize;
- CFont::SetPropOn();
- CFont::SetBackgroundOff();
-
- float fScaleY = fDistY / 100.0f;
- if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
-
- float fScaleX = fDistX / 100.0f;
- if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
-
- CFont::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here?
- CFont::SetCentreOn();
- CFont::SetCentreSize(SCREEN_WIDTH);
- CFont::SetJustifyOff();
- CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity));
- CFont::SetBackGroundOnlyTextOff();
- CFont::SetFontStyle(FONT_BANK);
- CFont::PrintString(vecOut.x, vecOut.y, m_aText);
- }
- }
-}
-
-void
-CMoneyMessages::Init()
-{
- for (int32 i = 0; i < NUMMONEYMESSAGES; i++)
- aMoneyMessages[i].m_nTimeRegistered = 0;
-}
-
-void
-CMoneyMessages::Render()
-{
- for (int32 i = 0; i < NUMMONEYMESSAGES; i++) {
- if (aMoneyMessages[i].m_nTimeRegistered != 0)
- aMoneyMessages[i].Render();
- }
-}
-
-void
-CMoneyMessages::RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity)
-{
- uint32 nIndex = 0;
- while (aMoneyMessages[nIndex].m_nTimeRegistered != 0) {
- if (++nIndex >= NUMMONEYMESSAGES) return;
- }
-
- // Add data of this money message to the array
- AsciiToUnicode(pText, aMoneyMessages[nIndex].m_aText);
-
- aMoneyMessages[nIndex].m_nTimeRegistered = CTimer::GetTimeInMilliseconds();
- aMoneyMessages[nIndex].m_vecPosition = vecPos;
- aMoneyMessages[nIndex].m_Colour.red = bRed;
- aMoneyMessages[nIndex].m_Colour.green = bGreen;
- aMoneyMessages[nIndex].m_Colour.blue = bBlue;
- aMoneyMessages[nIndex].m_fSize = fSize;
- aMoneyMessages[nIndex].m_fOpacity = fOpacity;
-}
-
-STARTPATCHES
- InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP);
- InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP);
-ENDPATCHES
diff --git a/src/render/MoneyMessages.h b/src/render/MoneyMessages.h
deleted file mode 100644
index f0a48a84..00000000
--- a/src/render/MoneyMessages.h
+++ /dev/null
@@ -1,24 +0,0 @@
-#pragma once
-
-class CMoneyMessage
-{
- friend class CMoneyMessages;
-
- uint32 m_nTimeRegistered;
- CVector m_vecPosition;
- wchar m_aText[16];
- CRGBA m_Colour;
- float m_fSize;
- float m_fOpacity;
-public:
- void Render();
-};
-
-class CMoneyMessages
-{
- static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];
-public:
- static void Init();
- static void Render();
- static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
-}; \ No newline at end of file
diff --git a/src/render/SpecialFX.cpp b/src/render/SpecialFX.cpp
index bed5af50..44e1e029 100644
--- a/src/render/SpecialFX.cpp
+++ b/src/render/SpecialFX.cpp
@@ -1,6 +1,10 @@
#include "common.h"
#include "patcher.h"
#include "SpecialFX.h"
+#include "Timer.h"
+#include "Sprite.h"
+#include "Font.h"
+#include "Text.h"
WRAPPER void CSpecialFX::Render(void) { EAXJMP(0x518DC0); }
@@ -13,4 +17,85 @@ WRAPPER void CBulletTraces::Init(void) { EAXJMP(0x518DE0); }
WRAPPER void CBrightLights::RegisterOne(CVector pos, CVector up, CVector right, CVector fwd, uint8 type, uint8 unk1, uint8 unk2, uint8 unk3) { EAXJMP(0x51A410); }
-WRAPPER void C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { EAXJMP(0x51BB80); } \ No newline at end of file
+WRAPPER void C3dMarkers::PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate) { EAXJMP(0x51BB80); }
+
+
+
+#define MONEY_MESSAGE_LIFETIME_MS 2000
+
+CMoneyMessage CMoneyMessages::aMoneyMessages[NUMMONEYMESSAGES];
+
+void
+CMoneyMessage::Render()
+{
+ const float MAX_SCALE = 4.0f;
+ uint32 nLifeTime = CTimer::GetTimeInMilliseconds() - m_nTimeRegistered;
+ if (nLifeTime >= MONEY_MESSAGE_LIFETIME_MS) m_nTimeRegistered = 0;
+ else {
+ float fLifeTime = (float)nLifeTime / MONEY_MESSAGE_LIFETIME_MS;
+ RwV3d vecOut;
+ float fDistX, fDistY;
+ if (CSprite::CalcScreenCoors(m_vecPosition + CVector(0.0f, 0.0f, fLifeTime), &vecOut, &fDistX, &fDistY, true)) {
+ fDistX *= (0.7 * fLifeTime + 2.0) * m_fSize;
+ fDistY *= (0.7 * fLifeTime + 2.0) * m_fSize;
+ CFont::SetPropOn();
+ CFont::SetBackgroundOff();
+
+ float fScaleY = fDistY / 100.0f;
+ if (fScaleY > MAX_SCALE) fScaleY = MAX_SCALE;
+
+ float fScaleX = fDistX / 100.0f;
+ if (fScaleX > MAX_SCALE) fScaleX = MAX_SCALE;
+
+ CFont::SetScale(fScaleX, fScaleY); // maybe use SCREEN_SCALE_X and SCREEN_SCALE_Y here?
+ CFont::SetCentreOn();
+ CFont::SetCentreSize(SCREEN_WIDTH);
+ CFont::SetJustifyOff();
+ CFont::SetColor(CRGBA(m_Colour.r, m_Colour.g, m_Colour.b, (255.0f - 255.0f * fLifeTime) * m_fOpacity));
+ CFont::SetBackGroundOnlyTextOff();
+ CFont::SetFontStyle(FONT_BANK);
+ CFont::PrintString(vecOut.x, vecOut.y, m_aText);
+ }
+ }
+}
+
+void
+CMoneyMessages::Init()
+{
+ for (int32 i = 0; i < NUMMONEYMESSAGES; i++)
+ aMoneyMessages[i].m_nTimeRegistered = 0;
+}
+
+void
+CMoneyMessages::Render()
+{
+ for (int32 i = 0; i < NUMMONEYMESSAGES; i++) {
+ if (aMoneyMessages[i].m_nTimeRegistered != 0)
+ aMoneyMessages[i].Render();
+ }
+}
+
+void
+CMoneyMessages::RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity)
+{
+ uint32 nIndex = 0;
+ while (aMoneyMessages[nIndex].m_nTimeRegistered != 0) {
+ if (++nIndex >= NUMMONEYMESSAGES) return;
+ }
+
+ // Add data of this money message to the array
+ AsciiToUnicode(pText, aMoneyMessages[nIndex].m_aText);
+
+ aMoneyMessages[nIndex].m_nTimeRegistered = CTimer::GetTimeInMilliseconds();
+ aMoneyMessages[nIndex].m_vecPosition = vecPos;
+ aMoneyMessages[nIndex].m_Colour.red = bRed;
+ aMoneyMessages[nIndex].m_Colour.green = bGreen;
+ aMoneyMessages[nIndex].m_Colour.blue = bBlue;
+ aMoneyMessages[nIndex].m_fSize = fSize;
+ aMoneyMessages[nIndex].m_fOpacity = fOpacity;
+}
+
+STARTPATCHES
+ InjectHook(0x51AF70, CMoneyMessages::Init, PATCH_JUMP);
+ InjectHook(0x51B030, CMoneyMessages::Render, PATCH_JUMP);
+ENDPATCHES
diff --git a/src/render/SpecialFX.h b/src/render/SpecialFX.h
index 9c61c0fb..bdd74bee 100644
--- a/src/render/SpecialFX.h
+++ b/src/render/SpecialFX.h
@@ -39,5 +39,27 @@ class C3dMarkers
{
public:
static void PlaceMarkerSet(uint32 id, uint16 type, CVector& pos, float size, uint8 r, uint8 g, uint8 b, uint8 a, uint16 pulsePeriod, float pulseFraction, int16 rotateRate);
-};
-
+};
+
+class CMoneyMessage
+{
+ friend class CMoneyMessages;
+
+ uint32 m_nTimeRegistered;
+ CVector m_vecPosition;
+ wchar m_aText[16];
+ CRGBA m_Colour;
+ float m_fSize;
+ float m_fOpacity;
+public:
+ void Render();
+};
+
+class CMoneyMessages
+{
+ static CMoneyMessage aMoneyMessages[NUMMONEYMESSAGES];
+public:
+ static void Init();
+ static void Render();
+ static void RegisterOne(CVector vecPos, const char *pText, uint8 bRed, uint8 bGreen, uint8 bBlue, float fSize, float fOpacity);
+}; \ No newline at end of file
diff --git a/src/vehicles/Train.cpp b/src/vehicles/Train.cpp
index 4c07a63a..f3a669d6 100644
--- a/src/vehicles/Train.cpp
+++ b/src/vehicles/Train.cpp
@@ -52,7 +52,7 @@ CTrain::CTrain(int32 id, uint8 CreatedBy)
m_bProcessDoor = true;
m_bTrainStopping = false;
-
+ m_nTrackId = TRACK_ELTRAIN;
m_nNumMaxPassengers = 5;
m_nDoorTimer = CTimer::GetTimeInMilliseconds();
m_nDoorState = TRAIN_DOOR_CLOSED;