diff options
Diffstat (limited to 'src/core/Zones.cpp')
-rw-r--r-- | src/core/Zones.cpp | 334 |
1 files changed, 98 insertions, 236 deletions
diff --git a/src/core/Zones.cpp b/src/core/Zones.cpp index 4bce3e79..804708b4 100644 --- a/src/core/Zones.cpp +++ b/src/core/Zones.cpp @@ -1,5 +1,5 @@ #include "common.h" -#include "patcher.h" + #include <ctype.h> #include "Zones.h" @@ -8,18 +8,18 @@ #include "Text.h" #include "World.h" -eLevelName &CTheZones::m_CurrLevel = *(eLevelName*)0x8F2BC8; -CZone *&CTheZones::m_pPlayersZone = *(CZone**)0x8F254C; -int16 &CTheZones::FindIndex = *(int16*)0x95CC40; +eLevelName CTheZones::m_CurrLevel; +CZone *CTheZones::m_pPlayersZone; +int16 CTheZones::FindIndex; -uint16 &CTheZones::NumberOfAudioZones = *(uint16*)0x95CC84; -int16 *CTheZones::AudioZoneArray = (int16*)0x713BC0; -uint16 &CTheZones::TotalNumberOfMapZones = *(uint16*)0x95CC74; -uint16 &CTheZones::TotalNumberOfZones = *(uint16*)0x95CC36; -CZone *CTheZones::ZoneArray = (CZone*)0x86BEE0; -CZone *CTheZones::MapZoneArray = (CZone*)0x663EC0; -uint16 &CTheZones::TotalNumberOfZoneInfos = *(uint16*)0x95CC3C; -CZoneInfo *CTheZones::ZoneInfoArray = (CZoneInfo*)0x714400; +uint16 CTheZones::NumberOfAudioZones; +int16 CTheZones::AudioZoneArray[NUMAUDIOZONES]; +uint16 CTheZones::TotalNumberOfMapZones; +uint16 CTheZones::TotalNumberOfZones; +CZone CTheZones::ZoneArray[NUMZONES]; +CZone CTheZones::MapZoneArray[NUMMAPZONES]; +uint16 CTheZones::TotalNumberOfZoneInfos; +CZoneInfo CTheZones::ZoneInfoArray[2*NUMZONES]; #define SWAPF(a, b) { float t; t = a; a = b; b = t; } @@ -625,251 +625,113 @@ CTheZones::InitialiseAudioZoneArray(void) } void -CTheZones::SaveAllZones(uint8 *buffer, uint32 *length) +CTheZones::SaveAllZones(uint8 *buffer, uint32 *size) { + INITSAVEBUF int i; - *length = 8 + 12 + - NUMZONES*56 + 2*NUMZONES*58 + 4 + - NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4; - - buffer[0] = 'Z'; - buffer[1] = 'N'; - buffer[2] = 'S'; - buffer[3] = '\0'; - *(uint32*)(buffer+4) = *length - 8; - buffer += 8; - - *(int32*)(buffer) = GetIndexForZonePointer(m_pPlayersZone); - *(int32*)(buffer+4) = m_CurrLevel; - *(int16*)(buffer+8) = FindIndex; - *(int16*)(buffer+10) = 0; - buffer += 12; - - for(i = 0; i < NUMZONES; i++){ - memcpy(buffer, ZoneArray[i].name, 8); - *(float*)(buffer+8) = ZoneArray[i].minx; - *(float*)(buffer+12) = ZoneArray[i].miny; - *(float*)(buffer+16) = ZoneArray[i].minz; - *(float*)(buffer+20) = ZoneArray[i].maxx; - *(float*)(buffer+24) = ZoneArray[i].maxy; - *(float*)(buffer+28) = ZoneArray[i].maxz; - *(int32*)(buffer+32) = ZoneArray[i].type; - *(int32*)(buffer+36) = ZoneArray[i].level; - *(int16*)(buffer+40) = ZoneArray[i].zoneinfoDay; - *(int16*)(buffer+42) = ZoneArray[i].zoneinfoNight; - *(int32*)(buffer+44) = GetIndexForZonePointer(ZoneArray[i].child); - *(int32*)(buffer+48) = GetIndexForZonePointer(ZoneArray[i].parent); - *(int32*)(buffer+52) = GetIndexForZonePointer(ZoneArray[i].next); - buffer += 56; + *size = SAVE_HEADER_SIZE + + sizeof(int32) // GetIndexForZonePointer + + sizeof(m_CurrLevel) + sizeof(FindIndex) + + sizeof(int16) // padding + + sizeof(ZoneArray) + sizeof(ZoneInfoArray) + + sizeof(TotalNumberOfZones) + sizeof(TotalNumberOfZoneInfos) + + sizeof(MapZoneArray) + sizeof(AudioZoneArray) + + sizeof(TotalNumberOfMapZones) + sizeof(NumberOfAudioZones); + + WriteSaveHeader(buffer, 'Z', 'N', 'S', '\0', *size - SAVE_HEADER_SIZE); + + WriteSaveBuf(buffer, GetIndexForZonePointer(m_pPlayersZone)); + WriteSaveBuf(buffer, m_CurrLevel); + WriteSaveBuf(buffer, FindIndex); + WriteSaveBuf(buffer, (int16)0); // padding + + for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ + 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); } - for(i = 0; i < 2*NUMZONES; i++){ - *(int16*)(buffer) = ZoneInfoArray[i].carDensity; - *(int16*)(buffer+2) = ZoneInfoArray[i].carThreshold[0]; - *(int16*)(buffer+4) = ZoneInfoArray[i].carThreshold[1]; - *(int16*)(buffer+6) = ZoneInfoArray[i].carThreshold[2]; - *(int16*)(buffer+8) = ZoneInfoArray[i].carThreshold[3]; - *(int16*)(buffer+10) = ZoneInfoArray[i].carThreshold[4]; - *(int16*)(buffer+12) = ZoneInfoArray[i].carThreshold[5]; - *(int16*)(buffer+14) = ZoneInfoArray[i].copThreshold; - *(int16*)(buffer+16) = ZoneInfoArray[i].gangThreshold[0]; - *(int16*)(buffer+18) = ZoneInfoArray[i].gangThreshold[1]; - *(int16*)(buffer+20) = ZoneInfoArray[i].gangThreshold[2]; - *(int16*)(buffer+22) = ZoneInfoArray[i].gangThreshold[3]; - *(int16*)(buffer+24) = ZoneInfoArray[i].gangThreshold[4]; - *(int16*)(buffer+26) = ZoneInfoArray[i].gangThreshold[5]; - *(int16*)(buffer+28) = ZoneInfoArray[i].gangThreshold[6]; - *(int16*)(buffer+30) = ZoneInfoArray[i].gangThreshold[7]; - *(int16*)(buffer+32) = ZoneInfoArray[i].gangThreshold[8]; - *(uint16*)(buffer+34) = ZoneInfoArray[i].pedDensity; - *(uint16*)(buffer+36) = ZoneInfoArray[i].copDensity; - *(uint16*)(buffer+38) = ZoneInfoArray[i].gangDensity[0]; - *(uint16*)(buffer+40) = ZoneInfoArray[i].gangDensity[1]; - *(uint16*)(buffer+42) = ZoneInfoArray[i].gangDensity[2]; - *(uint16*)(buffer+44) = ZoneInfoArray[i].gangDensity[3]; - *(uint16*)(buffer+46) = ZoneInfoArray[i].gangDensity[4]; - *(uint16*)(buffer+48) = ZoneInfoArray[i].gangDensity[5]; - *(uint16*)(buffer+50) = ZoneInfoArray[i].gangDensity[6]; - *(uint16*)(buffer+52) = ZoneInfoArray[i].gangDensity[7]; - *(uint16*)(buffer+54) = ZoneInfoArray[i].gangDensity[8]; - *(uint16*)(buffer+56) = ZoneInfoArray[i].pedGroup; - buffer += 58; + for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) + WriteSaveBuf(buffer, ZoneInfoArray[i]); + + WriteSaveBuf(buffer, TotalNumberOfZones); + WriteSaveBuf(buffer, TotalNumberOfZoneInfos); + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++) { + CZone* zone = WriteSaveBuf(buffer, MapZoneArray[i]); + + /* + The call of GetIndexForZonePointer is wrong, as it is + meant for a different array, but the game doesn't brake + if those fields are nil. Let's make sure they are. + */ + assert(MapZoneArray[i].child == nil); + assert(MapZoneArray[i].parent == nil); + assert(MapZoneArray[i].next == nil); + zone->child = (CZone*)GetIndexForZonePointer(MapZoneArray[i].child); + zone->parent = (CZone*)GetIndexForZonePointer(MapZoneArray[i].parent); + zone->next = (CZone*)GetIndexForZonePointer(MapZoneArray[i].next); } - *(uint16*)(buffer) = TotalNumberOfZones; - *(uint16*)(buffer+2) = TotalNumberOfZoneInfos; - buffer += 4; - - for(i = 0; i < NUMMAPZONES; i++){ - memcpy(buffer, MapZoneArray[i].name, 8); - *(float*)(buffer+8) = MapZoneArray[i].minx; - *(float*)(buffer+12) = MapZoneArray[i].miny; - *(float*)(buffer+16) = MapZoneArray[i].minz; - *(float*)(buffer+20) = MapZoneArray[i].maxx; - *(float*)(buffer+24) = MapZoneArray[i].maxy; - *(float*)(buffer+28) = MapZoneArray[i].maxz; - *(int32*)(buffer+32) = MapZoneArray[i].type; - *(int32*)(buffer+36) = MapZoneArray[i].level; - *(int16*)(buffer+40) = MapZoneArray[i].zoneinfoDay; - *(int16*)(buffer+42) = MapZoneArray[i].zoneinfoNight; -#ifdef STANDALONE - // BUG: GetIndexForZonePointer uses ZoneArray - // so indices will be unpredictable with different memory layout - assert(0); -#endif - *(int32*)(buffer+44) = GetIndexForZonePointer(MapZoneArray[i].child); - *(int32*)(buffer+48) = GetIndexForZonePointer(MapZoneArray[i].parent); - *(int32*)(buffer+52) = GetIndexForZonePointer(MapZoneArray[i].next); - buffer += 56; - } + for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) + WriteSaveBuf(buffer, AudioZoneArray[i]); - for(i = 0; i < NUMAUDIOZONES; i++){ - *(int16*)buffer = AudioZoneArray[i]; - buffer += 2; - } + WriteSaveBuf(buffer, TotalNumberOfMapZones); + WriteSaveBuf(buffer, NumberOfAudioZones); - *(uint16*)(buffer) = TotalNumberOfMapZones; - *(uint16*)(buffer+2) = NumberOfAudioZones; + VALIDATESAVEBUF(*size) } void -CTheZones::LoadAllZones(uint8 *buffer, uint32 length) +CTheZones::LoadAllZones(uint8 *buffer, uint32 size) { + INITSAVEBUF int i; - assert(length == 8 + 12 + - NUMZONES*56 + 2*NUMZONES*58 + 4 + - NUMMAPZONES*56 + NUMAUDIOZONES*2 + 4); - assert(buffer[0] == 'Z'); - assert(buffer[1] == 'N'); - assert(buffer[2] == 'S'); - assert(buffer[3] == '\0'); - assert(*(uint32*)(buffer+4) == length - 8); - buffer += 8; - - m_pPlayersZone = GetPointerForZoneIndex(*(int32*)(buffer)); - m_CurrLevel = (eLevelName)*(int32*)(buffer+4); - FindIndex = *(int16*)(buffer+8); - assert(*(int16*)(buffer+10) == 0); - buffer += 12; - - for(i = 0; i < NUMZONES; i++){ - memcpy(ZoneArray[i].name, buffer, 8); - ZoneArray[i].minx = *(float*)(buffer+8); - ZoneArray[i].miny = *(float*)(buffer+12); - ZoneArray[i].minz = *(float*)(buffer+16); - ZoneArray[i].maxx = *(float*)(buffer+20); - ZoneArray[i].maxy = *(float*)(buffer+24); - ZoneArray[i].maxz = *(float*)(buffer+28); - ZoneArray[i].type = (eZoneType)*(int32*)(buffer+32); - ZoneArray[i].level = (eLevelName)*(int32*)(buffer+36); - ZoneArray[i].zoneinfoDay = *(int16*)(buffer+40); - ZoneArray[i].zoneinfoNight = *(int16*)(buffer+42); - ZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44)); - ZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48)); - ZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52)); - buffer += 56; - } + CheckSaveHeader(buffer, 'Z', 'N', 'S', '\0', size - SAVE_HEADER_SIZE); - for(i = 0; i < 2*NUMZONES; i++){ - ZoneInfoArray[i].carDensity = *(int16*)(buffer); - ZoneInfoArray[i].carThreshold[0] = *(int16*)(buffer+2); - ZoneInfoArray[i].carThreshold[1] = *(int16*)(buffer+4); - ZoneInfoArray[i].carThreshold[2] = *(int16*)(buffer+6); - ZoneInfoArray[i].carThreshold[3] = *(int16*)(buffer+8); - ZoneInfoArray[i].carThreshold[4] = *(int16*)(buffer+10); - ZoneInfoArray[i].carThreshold[5] = *(int16*)(buffer+12); - ZoneInfoArray[i].copThreshold = *(int16*)(buffer+14); - ZoneInfoArray[i].gangThreshold[0] = *(int16*)(buffer+16); - ZoneInfoArray[i].gangThreshold[1] = *(int16*)(buffer+18); - ZoneInfoArray[i].gangThreshold[2] = *(int16*)(buffer+20); - ZoneInfoArray[i].gangThreshold[3] = *(int16*)(buffer+22); - ZoneInfoArray[i].gangThreshold[4] = *(int16*)(buffer+24); - ZoneInfoArray[i].gangThreshold[5] = *(int16*)(buffer+26); - ZoneInfoArray[i].gangThreshold[6] = *(int16*)(buffer+28); - ZoneInfoArray[i].gangThreshold[7] = *(int16*)(buffer+30); - ZoneInfoArray[i].gangThreshold[8] = *(int16*)(buffer+32); - ZoneInfoArray[i].pedDensity = *(uint16*)(buffer+34); - ZoneInfoArray[i].copDensity = *(uint16*)(buffer+36); - ZoneInfoArray[i].gangDensity[0] = *(uint16*)(buffer+38); - ZoneInfoArray[i].gangDensity[1] = *(uint16*)(buffer+40); - ZoneInfoArray[i].gangDensity[2] = *(uint16*)(buffer+42); - ZoneInfoArray[i].gangDensity[3] = *(uint16*)(buffer+44); - ZoneInfoArray[i].gangDensity[4] = *(uint16*)(buffer+46); - ZoneInfoArray[i].gangDensity[5] = *(uint16*)(buffer+48); - ZoneInfoArray[i].gangDensity[6] = *(uint16*)(buffer+50); - ZoneInfoArray[i].gangDensity[7] = *(uint16*)(buffer+52); - ZoneInfoArray[i].gangDensity[8] = *(uint16*)(buffer+54); - ZoneInfoArray[i].pedGroup = *(uint16*)(buffer+56); - buffer += 58; - } + m_pPlayersZone = GetPointerForZoneIndex(ReadSaveBuf<int32>(buffer)); + m_CurrLevel = ReadSaveBuf<eLevelName>(buffer); + FindIndex = ReadSaveBuf<int16>(buffer); + ReadSaveBuf<int16>(buffer); - TotalNumberOfZones = *(uint16*)(buffer); - TotalNumberOfZoneInfos = *(uint16*)(buffer+2); - buffer += 4; + for(i = 0; i < ARRAY_SIZE(ZoneArray); i++){ + ZoneArray[i] = ReadSaveBuf<CZone>(buffer); - for(i = 0; i < NUMMAPZONES; i++){ - memcpy(MapZoneArray[i].name, buffer, 8); - MapZoneArray[i].minx = *(float*)(buffer+8); - MapZoneArray[i].miny = *(float*)(buffer+12); - MapZoneArray[i].minz = *(float*)(buffer+16); - MapZoneArray[i].maxx = *(float*)(buffer+20); - MapZoneArray[i].maxy = *(float*)(buffer+24); - MapZoneArray[i].maxz = *(float*)(buffer+28); - MapZoneArray[i].type = (eZoneType)*(int32*)(buffer+32); - MapZoneArray[i].level = (eLevelName)*(int32*)(buffer+36); - MapZoneArray[i].zoneinfoDay = *(int16*)(buffer+40); - MapZoneArray[i].zoneinfoNight = *(int16*)(buffer+42); -#ifdef STANDALONE - // BUG: GetPointerForZoneIndex uses ZoneArray - // so pointers will be unpredictable with different memory layout - assert(0); -#endif - MapZoneArray[i].child = GetPointerForZoneIndex(*(int32*)(buffer+44)); - MapZoneArray[i].parent = GetPointerForZoneIndex(*(int32*)(buffer+48)); - MapZoneArray[i].next = GetPointerForZoneIndex(*(int32*)(buffer+52)); - buffer += 56; + ZoneArray[i].child = GetPointerForZoneIndex((int32)ZoneArray[i].child); + ZoneArray[i].parent = GetPointerForZoneIndex((int32)ZoneArray[i].parent); + ZoneArray[i].next = GetPointerForZoneIndex((int32)ZoneArray[i].next); } - for(i = 0; i < NUMAUDIOZONES; i++){ - AudioZoneArray[i] = *(int16*)buffer; - buffer += 2; + for(i = 0; i < ARRAY_SIZE(ZoneInfoArray); i++) + ZoneInfoArray[i] = ReadSaveBuf<CZoneInfo>(buffer); + + TotalNumberOfZones = ReadSaveBuf<int16>(buffer); + TotalNumberOfZoneInfos = ReadSaveBuf<int16>(buffer); + + for(i = 0; i < ARRAY_SIZE(MapZoneArray); i++){ + MapZoneArray[i] = ReadSaveBuf<CZone>(buffer); + + /* + The call of GetPointerForZoneIndex is wrong, as it is + meant for a different array, but the game doesn't brake + if save data stored is -1. + */ + MapZoneArray[i].child = GetPointerForZoneIndex((int32)MapZoneArray[i].child); + MapZoneArray[i].parent = GetPointerForZoneIndex((int32)MapZoneArray[i].parent); + MapZoneArray[i].next = GetPointerForZoneIndex((int32)MapZoneArray[i].next); + assert(MapZoneArray[i].child == nil); + assert(MapZoneArray[i].parent == nil); + assert(MapZoneArray[i].next == nil); } - TotalNumberOfMapZones = *(uint16*)(buffer); - NumberOfAudioZones = *(uint16*)(buffer+2); -} + for(i = 0; i < ARRAY_SIZE(AudioZoneArray); i++) + AudioZoneArray[i] = ReadSaveBuf<int16>(buffer); + TotalNumberOfMapZones = ReadSaveBuf<uint16>(buffer); + NumberOfAudioZones = ReadSaveBuf<uint16>(buffer); -STARTPATCHES - InjectHook(0x4B5DD0, &CZone::GetTranslatedName, PATCH_JUMP); - InjectHook(0x4B5DE0, CTheZones::Init, PATCH_JUMP); - InjectHook(0x4B61D0, CTheZones::Update, PATCH_JUMP); - InjectHook(0x4B6210, CTheZones::CreateZone, PATCH_JUMP); - InjectHook(0x4B6380, CTheZones::CreateMapZone, PATCH_JUMP); - InjectHook(0x4B64C0, CTheZones::PostZoneCreation, PATCH_JUMP); - InjectHook(0x4B6500, CTheZones::InsertZoneIntoZoneHierarchy, PATCH_JUMP); - InjectHook(0x4B6530, CTheZones::InsertZoneIntoZoneHierRecursive, PATCH_JUMP); - InjectHook(0x4B65F0, CTheZones::ZoneIsEntirelyContainedWithinOtherZone, PATCH_JUMP); - InjectHook(0x4B6710, CTheZones::PointLiesWithinZone, PATCH_JUMP); - InjectHook(0x4B6910, CTheZones::GetLevelFromPosition, PATCH_JUMP); - InjectHook(0x4B69B0, CTheZones::FindSmallestZonePosition, PATCH_JUMP); - InjectHook(0x4B6790, CTheZones::FindSmallestZonePositionType, PATCH_JUMP); - InjectHook(0x4B6890, CTheZones::FindSmallestZonePositionILN, PATCH_JUMP); - InjectHook(0x4B6800, CTheZones::FindZoneByLabelAndReturnIndex, PATCH_JUMP); - InjectHook(0x4B6FA0, CTheZones::GetZone, PATCH_JUMP); - InjectHook(0x4B84F0, CTheZones::GetPointerForZoneIndex, PATCH_JUMP); - InjectHook(0x4B6A10, CTheZones::GetZoneInfo, PATCH_JUMP); - InjectHook(0x4B6FB0, CTheZones::GetZoneInfoForTimeOfDay, PATCH_JUMP); - InjectHook(0x4B6A50, CTheZones::SetZoneCarInfo, PATCH_JUMP); - InjectHook(0x4B6DC0, CTheZones::SetZonePedInfo, PATCH_JUMP); - InjectHook(0x4B6EB0, CTheZones::SetCarDensity, PATCH_JUMP); - InjectHook(0x4B6F00, CTheZones::SetPedDensity, PATCH_JUMP); - InjectHook(0x4B6F50, CTheZones::SetPedGroup, PATCH_JUMP); - InjectHook(0x4B83E0, CTheZones::FindAudioZone, PATCH_JUMP); - InjectHook(0x4B8430, CTheZones::FindZoneForPoint, PATCH_JUMP); - InjectHook(0x4B8340, CTheZones::AddZoneToAudioZoneArray, PATCH_JUMP); - InjectHook(0x4B8510, CTheZones::SaveAllZones, PATCH_JUMP); - InjectHook(0x4B8950, CTheZones::LoadAllZones, PATCH_JUMP); -ENDPATCHES + VALIDATESAVEBUF(size) +} |