From 3b64bd1b4a5008b14b54edb257d4e8a5a8277c26 Mon Sep 17 00:00:00 2001 From: aap Date: Tue, 18 Jun 2019 09:50:26 +0200 Subject: finished CFileLoader, except a crash! --- src/CdStream.cpp | 12 +-- src/FileLoader.cpp | 252 ++++++++++++++++++++++++++++++++++++++++++- src/FileLoader.h | 8 ++ src/World.cpp | 2 + src/World.h | 1 + src/control/ObjectData.cpp | 5 + src/control/ObjectData.h | 7 ++ src/control/PathFind.cpp | 6 ++ src/control/PathFind.h | 5 + src/entities/Building.h | 5 +- src/entities/Dummy.h | 3 + src/entities/DummyObject.cpp | 13 +++ src/entities/DummyObject.h | 7 +- src/entities/Entity.cpp | 2 +- src/entities/Entity.h | 2 +- src/main.cpp | 24 +++++ src/main.h | 4 + 17 files changed, 345 insertions(+), 13 deletions(-) create mode 100644 src/control/ObjectData.cpp create mode 100644 src/control/ObjectData.h create mode 100644 src/entities/DummyObject.cpp (limited to 'src') diff --git a/src/CdStream.cpp b/src/CdStream.cpp index f0cefda5..506e14e9 100644 --- a/src/CdStream.cpp +++ b/src/CdStream.cpp @@ -456,12 +456,12 @@ CdStreamAddImage(char const *path) SetLastError(0); gImgFiles[gNumImages] = CreateFile(path, - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - _gdwCdStreamFlags | FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_READONLY, - NULL); + GENERIC_READ, + FILE_SHARE_READ, + NULL, + OPEN_EXISTING, + _gdwCdStreamFlags | FILE_FLAG_RANDOM_ACCESS | FILE_ATTRIBUTE_READONLY, + NULL); ASSERT( gImgFiles[gNumImages] != NULL ); if ( gImgFiles[gNumImages] == NULL ) diff --git a/src/FileLoader.cpp b/src/FileLoader.cpp index dc70234d..69d8a483 100644 --- a/src/FileLoader.cpp +++ b/src/FileLoader.cpp @@ -1,9 +1,12 @@ #include "common.h" #include "main.h" #include "patcher.h" +#include "math/Quaternion.h" #include "ModelInfo.h" #include "ModelIndices.h" #include "TempColModels.h" +#include "VisibilityPlugins.h" +#include "FileMgr.h" #include "HandlingDataMgr.h" #include "CarCtrl.h" #include "PedType.h" @@ -14,8 +17,12 @@ #include "NodeName.h" #include "TxdStore.h" #include "PathFind.h" -#include "VisibilityPlugins.h" -#include "FileMgr.h" +#include "ObjectData.h" +#include "DummyObject.h" +#include "World.h" +#include "Zones.h" +#include "CullZones.h" +#include "CdStream.h" #include "FileLoader.h" char CFileLoader::ms_line[256]; @@ -85,6 +92,21 @@ CFileLoader::LoadLevel(const char *filename) }else if(strncmp(line, "IDE", 3) == 0){ LoadingScreenLoadingFile(line + 4); LoadObjectTypes(line + 4); + }else if(strncmp(line, "IPL", 3) == 0){ + if(!objectsLoaded){ + // CModelInfo::ConstructMloClumps(); + CObjectData::Initialise("DATA\\OBJECT.DAT"); + objectsLoaded = true; + } + LoadingScreenLoadingFile(line + 4); + LoadObjectInstance(line + 4); + }else if(strncmp(line, "MAPZONE", 7) == 0){ + LoadingScreenLoadingFile(line + 8); + LoadMapZones(line + 8); + }else if(strncmp(line, "SPLASH", 6) == 0){ + LoadSplash(GetRandomSplashScreen()); + }else if(strncmp(line, "CDIMAGE", 7) == 0){ + CdStreamAddImage(line + 8); } } @@ -489,7 +511,7 @@ CFileLoader::LoadObjectTypes(const char *filename) int id, pathType; // int mlo; - section = 0; + section = NONE; pathIndex = -1; // mlo = 0; debug("Loading object types from %s...\n", filename); @@ -907,8 +929,225 @@ CFileLoader::Load2dEffect(const char *line) CTxdStore::PopCurrentTxd(); } +void +CFileLoader::LoadScene(const char *filename) +{ + enum { + NONE, + INST, + ZONE, + CULL, + PICK, + PATH, + }; + char *line; + int fd; + int section; + int pathIndex; + char pathTypeStr[20]; + + section = NONE; + pathIndex = -1; + debug("Creating objects from %s...\n", filename); + + fd = CFileMgr::OpenFile(filename, "rb"); + for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){ + if(*line == '\0' || *line == '#') + continue; + + if(section == NONE){ + if(strncmp(line, "inst", 4) == 0) section = INST; + else if(strncmp(line, "zone", 4) == 0) section = ZONE; + else if(strncmp(line, "cull", 4) == 0) section = CULL; + else if(strncmp(line, "pick", 4) == 0) section = PICK; + else if(strncmp(line, "path", 4) == 0) section = PATH; + }else if(strncmp(line, "end", 3) == 0){ + section = NONE; + }else switch(section){ + case INST: + LoadObjectInstance(line); + break; + case ZONE: + LoadZone(line); + break; + case CULL: + LoadCullZone(line); + break; + case PICK: + // unused + LoadPickup(line); + break; + case PATH: + // unfinished in the game + if(pathIndex == -1){ + LoadPathHeader(line, pathTypeStr); + // type not set + pathIndex = 0; + }else{ + // nodes not loaded + pathIndex++; + if(pathIndex == 12) + pathIndex = -1; + } + break; + } + } + CFileMgr::CloseFile(fd); + + debug("Finished loading IPL\n"); +} + +void +CFileLoader::LoadObjectInstance(const char *line) +{ + int id; + char name[24]; + RwV3d trans, scale, axis; + float angle; + CSimpleModelInfo *mi; + RwMatrix *xform; + CEntity *entity; + + if(sscanf(line, "%d %s %f %f %f %f %f %f %f %f %f %f", + &id, name, + &trans.x, &trans.y, &trans.z, + &scale.x, &scale.y, &scale.z, + &axis.x, &axis.y, &axis.z, &angle) != 12) + return; + + mi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(id); + if(mi == nil) + return; + assert(mi->IsSimple()); + + angle = -RADTODEG(2.0f * acosf(angle)); + xform = RwMatrixCreate(); + RwMatrixRotate(xform, &axis, angle, rwCOMBINEREPLACE); + RwMatrixTranslate(xform, &trans, rwCOMBINEPOSTCONCAT); + + if(mi->GetObjectID() == -1){ + if(ThePaths.IsPathObject(id)){ + entity = new CTreadable; + ThePaths.RegisterMapObject((CTreadable*)entity); + }else + entity = new CBuilding; + entity->SetModelIndexNoCreate(id); + entity->GetMatrix() = CMatrix(xform); + entity->m_level = CTheZones::GetLevelFromPosition(entity->GetPosition()); + if(mi->IsSimple()){ + if(mi->m_isBigBuilding) + entity->SetupBigBuilding(); + if(mi->m_isSubway) + entity->bIsSubway = true; + } + if(mi->GetLargestLodDistance() < 2.0f) + entity->bIsVisible = false; + CWorld::Add(entity); + }else{ + entity = new CDummyObject; + entity->SetModelIndexNoCreate(id); + entity->GetMatrix() = CMatrix(xform); + CWorld::Add(entity); + if(IsGlass(entity->GetModelIndex())) + entity->bIsVisible = false; + entity->m_level = CTheZones::GetLevelFromPosition(entity->GetPosition()); + } + + RwMatrixDestroy(xform); +} + +void +CFileLoader::LoadZone(const char *line) +{ + char name[24]; + int type, level; + float minx, miny, minz; + float maxx, maxy, maxz; + + if(sscanf(line, "%s %d %f %f %f %f %f %f %d", name, &type, &minx, &miny, &minz, &maxx, &maxy, &maxz, &level) == 9) + CTheZones::CreateZone(name, (eZoneType)type, minx, miny, minz, maxx, maxy, maxz, (eLevelName)level); +} + +void +CFileLoader::LoadCullZone(const char *line) +{ + CVector pos; + float minx, miny, minz; + float maxx, maxy, maxz; + int flags; + int wantedLevelDrop = 0; + + sscanf(line, "%f %f %f %f %f %f %f %f %f %d %d", + &pos.x, &pos.y, &pos.z, + &minx, &miny, &minz, + &maxx, &maxy, &maxz, + &flags, &wantedLevelDrop); + CCullZones::AddCullZone(pos, minx, maxx, miny, maxy, minz, maxy, flags, wantedLevelDrop); +} + +// unused +void +CFileLoader::LoadPickup(const char *line) +{ + int id; + float x, y, z; + + sscanf(line, "%d %f %f %f", &id, &x, &y, &z); +} + +void +CFileLoader::LoadMapZones(const char *filename) +{ + enum { + NONE, + INST, + ZONE, + CULL, + PICK, + PATH, + }; + char *line; + int fd; + int section; + + section = NONE; + debug("Creating zones from %s...\n", filename); + + fd = CFileMgr::OpenFile(filename, "rb"); + for(line = CFileLoader::LoadLine(fd); line; line = CFileLoader::LoadLine(fd)){ + if(*line == '\0' || *line == '#') + continue; + + if(section == NONE){ + if(strncmp(line, "zone", 4) == 0) section = ZONE; + }else if(strncmp(line, "end", 3) == 0){ + section = NONE; + }else switch(section){ + case ZONE: { + char name[24]; + int type, level; + float minx, miny, minz; + float maxx, maxy, maxz; + if(sscanf(line, "%s %d %f %f %f %f %f %f %d", + &name, &type, + &minx, &miny, &minz, + &maxx, &maxy, &maxz, + &level) == 9) + CTheZones::CreateMapZone(name, (eZoneType)type, minx, miny, minz, maxx, maxy, maxz, (eLevelName)level); + } + break; + } + } + CFileMgr::CloseFile(fd); + + debug("Finished loading IPL\n"); +} + STARTPATCHES + // this makes my game crash in CGarage! + //InjectHook(0x476290, CFileLoader::LoadLevel, PATCH_JUMP); + InjectHook(0x476520, CFileLoader::LoadCollisionFromDatFile, PATCH_JUMP); InjectHook(0x4761D0, CFileLoader::LoadLine, PATCH_JUMP); InjectHook(0x4765B0, CFileLoader::LoadTexDictionary, PATCH_JUMP); @@ -933,4 +1172,11 @@ STARTPATCHES InjectHook(0x477FF0, CFileLoader::LoadCarPathNode, PATCH_JUMP); InjectHook(0x477F00, CFileLoader::LoadPedPathNode, PATCH_JUMP); InjectHook(0x4780E0, CFileLoader::Load2dEffect, PATCH_JUMP); + + InjectHook(0x478370, CFileLoader::LoadScene, PATCH_JUMP); + InjectHook(0x4786B0, CFileLoader::LoadObjectInstance, PATCH_JUMP); + InjectHook(0x478A00, CFileLoader::LoadZone, PATCH_JUMP); + InjectHook(0x478A90, CFileLoader::LoadCullZone, PATCH_JUMP); + + InjectHook(0x478550, CFileLoader::LoadMapZones, PATCH_JUMP); ENDPATCHES diff --git a/src/FileLoader.h b/src/FileLoader.h index 0aad884d..f9121ace 100644 --- a/src/FileLoader.h +++ b/src/FileLoader.h @@ -31,4 +31,12 @@ public: static void LoadPedPathNode(const char *line, int id, int node); static void LoadCarPathNode(const char *line, int id, int node); static void Load2dEffect(const char *line); + + static void LoadScene(const char *filename); + static void LoadObjectInstance(const char *line); + static void LoadZone(const char *line); + static void LoadCullZone(const char *line); + static void LoadPickup(const char *line); + + static void LoadMapZones(const char *filename); }; diff --git a/src/World.cpp b/src/World.cpp index 1d45dcc8..b5b7ae5c 100644 --- a/src/World.cpp +++ b/src/World.cpp @@ -7,6 +7,8 @@ #include "TempColModels.h" #include "World.h" +WRAPPER void CWorld::Add(CEntity *entity) { EAXJMP(0x4AE930); } + CPtrList *CWorld::ms_bigBuildingsList = (CPtrList*)0x6FAB60; CPtrList &CWorld::ms_listMovingEntityPtrs = *(CPtrList*)0x8F433C; CSector (*CWorld::ms_aSectors)[NUMSECTORS_X] = (CSector (*)[NUMSECTORS_Y])0x665608; diff --git a/src/World.h b/src/World.h index 77e0fd99..c1d870e2 100644 --- a/src/World.h +++ b/src/World.h @@ -55,6 +55,7 @@ public: static bool &bForceProcessControl; static bool &bProcessCutsceneOnly; + static void Add(CEntity *entity); static CSector *GetSector(int x, int y) { return &ms_aSectors[y][x]; } static CPtrList &GetBigBuildingList(eLevelName i) { return ms_bigBuildingsList[i]; } diff --git a/src/control/ObjectData.cpp b/src/control/ObjectData.cpp new file mode 100644 index 00000000..28c34658 --- /dev/null +++ b/src/control/ObjectData.cpp @@ -0,0 +1,5 @@ +#include "common.h" +#include "patcher.h" +#include "ObjectData.h" + +WRAPPER void CObjectData::Initialise(const char *filename) { EAXJMP(0x4BC0E0); } diff --git a/src/control/ObjectData.h b/src/control/ObjectData.h new file mode 100644 index 00000000..7df1c845 --- /dev/null +++ b/src/control/ObjectData.h @@ -0,0 +1,7 @@ +#pragma once + +class CObjectData +{ +public: + static void Initialise(const char *filename); +}; diff --git a/src/control/PathFind.cpp b/src/control/PathFind.cpp index 8cfc17e7..c3af2e30 100644 --- a/src/control/PathFind.cpp +++ b/src/control/PathFind.cpp @@ -76,6 +76,12 @@ CPathFind::StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, InfoForTileCars[i].numRightLanes = numRight; } +void +CPathFind::RegisterMapObject(CTreadable *mapObject) +{ + m_mapObjects[m_numMapObjects++] = mapObject; +} + void CPathFind::PreparePathData(void) { diff --git a/src/control/PathFind.h b/src/control/PathFind.h index ed3c7e9f..83b89953 100644 --- a/src/control/PathFind.h +++ b/src/control/PathFind.h @@ -67,6 +67,8 @@ struct CPathInfoForObject int8 numRightLanes; uint8 crossing : 1; }; +extern CPathInfoForObject *&InfoForTileCars; +extern CPathInfoForObject *&InfoForTilePeds; struct CTempNode { @@ -125,6 +127,9 @@ public: void CalcNodeCoors(int16 x, int16 y, int16 z, int32 id, CVector *out); void StoreNodeInfoPed(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, bool crossing); void StoreNodeInfoCar(int16 id, int16 node, int8 type, int8 next, int16 x, int16 y, int16 z, int16 width, int8 numLeft, int8 numRight); + void RegisterMapObject(CTreadable *mapObject); + + bool IsPathObject(int id) { return id < PATHNODESIZE && (InfoForTileCars[id*12].type != 0 || InfoForTilePeds[id*12].type != 0); } }; static_assert(sizeof(CPathFind) == 0x4c8f4, "CPathFind: error"); diff --git a/src/entities/Building.h b/src/entities/Building.h index d33aaa4f..612e0fb3 100644 --- a/src/entities/Building.h +++ b/src/entities/Building.h @@ -6,7 +6,10 @@ class CBuilding : public CEntity { public: // TODO: ReplaceWithNewModel - // TODO: ctor + CBuilding(void) { + m_type = ENTITY_TYPE_BUILDING; + bUsesCollision = true; + } static void *operator new(size_t); static void operator delete(void*, size_t); diff --git a/src/entities/Dummy.h b/src/entities/Dummy.h index e7506617..034d4c57 100644 --- a/src/entities/Dummy.h +++ b/src/entities/Dummy.h @@ -8,6 +8,9 @@ class CDummy : public CEntity public: CEntryInfoList m_entryInfoList; + CDummy(void) { m_type = ENTITY_TYPE_DUMMY; } + // TODO: Add, Remove + static void *operator new(size_t); static void operator delete(void*, size_t); }; diff --git a/src/entities/DummyObject.cpp b/src/entities/DummyObject.cpp new file mode 100644 index 00000000..083ad6c6 --- /dev/null +++ b/src/entities/DummyObject.cpp @@ -0,0 +1,13 @@ +#include "common.h" +#include "patcher.h" +#include "DummyObject.h" +#include "Pools.h" + +CDummyObject::CDummyObject(CObject *obj) +{ + SetModelIndexNoCreate(obj->GetModelIndex()); + if(obj->m_rwObject) + AttachToRwObject(obj->m_rwObject); + obj->DetachFromRwObject(); + m_level = obj->m_level; +} diff --git a/src/entities/DummyObject.h b/src/entities/DummyObject.h index 7bfe3a57..d4dce609 100644 --- a/src/entities/DummyObject.h +++ b/src/entities/DummyObject.h @@ -2,7 +2,12 @@ #include "Dummy.h" -class CDummyObject : CDummy +class CObject; + +class CDummyObject : public CDummy { +public: + CDummyObject(void) {} + CDummyObject(CObject *obj); }; static_assert(sizeof(CDummyObject) == 0x68, "CDummyObject: error"); diff --git a/src/entities/Entity.cpp b/src/entities/Entity.cpp index 2338f627..0ab1488d 100644 --- a/src/entities/Entity.cpp +++ b/src/entities/Entity.cpp @@ -48,7 +48,7 @@ CEntity::CEntity(void) bHasHitWall = false; bImBeingRendered = false; m_flagD8 = false; - m_flagD10 = false; + bIsSubway = false; bDrawLast = false; m_flagD40 = false; m_flagD80 = false; diff --git a/src/entities/Entity.h b/src/entities/Entity.h index 73a2c668..95294ed8 100644 --- a/src/entities/Entity.h +++ b/src/entities/Entity.h @@ -79,7 +79,7 @@ public: uint32 bHasHitWall : 1; uint32 bImBeingRendered : 1; uint32 m_flagD8 : 1; - uint32 m_flagD10 : 1; + uint32 bIsSubway : 1; // set when subway, but maybe different meaning? uint32 bDrawLast : 1; uint32 m_flagD40 : 1; uint32 m_flagD80 : 1; // CObject visibility? diff --git a/src/main.cpp b/src/main.cpp index 8f6a9b29..9bdb41fc 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -1,6 +1,7 @@ #include "common.h" #include "patcher.h" #include "main.h" +#include "General.h" #include "RwHelper.h" #include "Clouds.h" #include "Draw.h" @@ -579,6 +580,29 @@ ResetLoadingScreenBar(void) NumberOfChunksLoaded = 0.0f; } +char* +GetRandomSplashScreen(void) +{ + int index; + static int index2 = 0; + static char splashName[128]; + static int splashIndex[24] = { + 25, 22, 4, 13, + 1, 21, 14, 16, + 10, 12, 5, 9, + 11, 18, 3, 2, + 19, 23, 7, 17, + 15, 6, 8, 20 + }; + + index = splashIndex[4*index2 + CGeneral::GetRandomNumberInRange(0, 3)]; + index2++; + if(index2 == 6) + index2 = 0; + sprintf(splashName, "loadsc%d", index); + return splashName; +} + #include "rwcore.h" #include "rpworld.h" #include "rpmatfx.h" diff --git a/src/main.h b/src/main.h index eba79117..45948b34 100644 --- a/src/main.h +++ b/src/main.h @@ -11,4 +11,8 @@ extern uint8 work_buff[55000]; extern char gString[256]; extern wchar *gUString; +class CSprite2d; + void LoadingScreen(const char *str1, const char *str2, const char *splashscreen); +CSprite2d *LoadSplash(const char *name); +char *GetRandomSplashScreen(void); -- cgit v1.2.3