diff --git a/CMakeLists.txt b/CMakeLists.txt index 6ba619303..3ff00560b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -45,8 +45,8 @@ if(USE_LD_GOLD AND ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_ if("${LD_VERSION}" MATCHES "GNU gold") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -fuse-ld=gold -Wl,--disable-new-dtags") - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -flto=thin") + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -flto=thin") message(STATUS "GNU gold linker enabled.") else() message(WARNING "GNU gold linker isn't available, using the default system linker.") diff --git a/DataSpec/DNACommon/MAPA.cpp b/DataSpec/DNACommon/MAPA.cpp index d588960b2..d98d7fd66 100644 --- a/DataSpec/DNACommon/MAPA.cpp +++ b/DataSpec/DNACommon/MAPA.cpp @@ -92,18 +92,10 @@ bool ReadMAPAToBlender(hecl::BlenderConnection& conn, const typename PAKRouter::EntryType& entry, bool force) { - hecl::ProjectPath mapaPath; - if (pakRouter.isShared()) - /* Rename MAPA for consistency */ - mapaPath = hecl::ProjectPath(outPath.getParentPath(), _S("!map.blend")); - else - /* We're not in a world pak, so lets keep the original name */ - mapaPath = outPath; - - if (!force && mapaPath.isFile()) + if (!force && outPath.isFile()) return true; - if (!conn.createBlend(mapaPath, hecl::BlenderConnection::BlendType::MapArea)) + if (!conn.createBlend(outPath, hecl::BlenderConnection::BlendType::MapArea)) return false; hecl::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); diff --git a/DataSpec/DNACommon/MLVL.cpp b/DataSpec/DNACommon/MLVL.cpp index 1399061ce..6cfb9e80b 100644 --- a/DataSpec/DNACommon/MLVL.cpp +++ b/DataSpec/DNACommon/MLVL.cpp @@ -17,18 +17,11 @@ bool ReadMLVLToBlender(hecl::BlenderConnection& conn, bool force, std::function fileChanged) { - hecl::ProjectPath mlvlPath; - if (pakRouter.isShared()) - /* Rename MLVL for consistency */ - mlvlPath = hecl::ProjectPath(outPath.getParentPath(), _S("!world.blend")); - else - /* We're not in a world pak, so lets keep the original name */ - mlvlPath = outPath; - if (!force && mlvlPath.isFile()) + if (!force && outPath.isFile()) return true; /* Create World Blend */ - if (!conn.createBlend(mlvlPath, hecl::BlenderConnection::BlendType::World)) + if (!conn.createBlend(outPath, hecl::BlenderConnection::BlendType::World)) return false; hecl::BlenderConnection::PyOutStream os = conn.beginPythonOut(true); os.format("import bpy\n" diff --git a/DataSpec/DNACommon/PAK.cpp b/DataSpec/DNACommon/PAK.cpp index 30b3d2fc2..d1390507b 100644 --- a/DataSpec/DNACommon/PAK.cpp +++ b/DataSpec/DNACommon/PAK.cpp @@ -457,6 +457,17 @@ std::string PAKRouter::getBestEntryName(const EntryType& entry) cons for (const BRIDGETYPE& bridge : *m_bridges) { const typename BRIDGETYPE::PAKType& pak = bridge.getPAK(); + + if (isShared()) + { + if (entry.type == FOURCC('MLVL')) + return "!world"; + else if (entry.type == FOURCC('MREA')) + return "!area"; + else if (entry.type == FOURCC('MAPA')) + return "!map"; + } + bool named; name = pak.bestEntryName(entry, named); if (named) @@ -475,6 +486,17 @@ std::string PAKRouter::getBestEntryName(const IDType& entry) const const typename BRIDGETYPE::PAKType::Entry* e = pak.lookupEntry(entry); if (!e) continue; + + if (isShared()) + { + if (e->type == FOURCC('MLVL')) + return "!world"; + else if (e->type == FOURCC('MREA')) + return "!area"; + else if (e->type == FOURCC('MAPA')) + return "!map"; + } + bool named; name = pak.bestEntryName(*e, named); if (named) diff --git a/DataSpec/DNACommon/PAK.hpp b/DataSpec/DNACommon/PAK.hpp index 2145f1e05..0b96aabc7 100644 --- a/DataSpec/DNACommon/PAK.hpp +++ b/DataSpec/DNACommon/PAK.hpp @@ -189,7 +189,7 @@ public: hecl::ProjectPath getWorking(const IDType& id, bool silenceWarnings=false) const; hecl::ProjectPath getCooked(const EntryType* entry) const; hecl::ProjectPath getCooked(const IDType& id, bool silenceWarnings=false) const; - bool isShared() + bool isShared() const { const PAKType* pak = m_pak.get(); return pak ? !pak->m_noShare : false; diff --git a/DataSpec/DNAMP1/MREA.cpp b/DataSpec/DNAMP1/MREA.cpp index bb6b4a18c..55f0ee23e 100644 --- a/DataSpec/DNAMP1/MREA.cpp +++ b/DataSpec/DNAMP1/MREA.cpp @@ -65,15 +65,7 @@ bool MREA::Extract(const SpecBase& dataSpec, using RigPair = std::pair; RigPair dummy(nullptr, nullptr); - hecl::ProjectPath mreaPath; - if (pakRouter.isShared()) - /* Rename MREA for consistency */ - mreaPath = hecl::ProjectPath(outPath.getParentPath(), _S("!area.blend")); - else - /* We're not in a world pak, so lets keep the original name */ - mreaPath = outPath; - - if (!force && mreaPath.isFile()) + if (!force && outPath.isFile()) return true; /* Do extract */ @@ -82,7 +74,7 @@ bool MREA::Extract(const SpecBase& dataSpec, rs.seekAlign32(); hecl::BlenderConnection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(mreaPath, hecl::BlenderConnection::BlendType::Area)) + if (!conn.createBlend(outPath, hecl::BlenderConnection::BlendType::Area)) return false; /* Open Py Stream and read sections */ diff --git a/DataSpec/DNAMP2/MREA.cpp b/DataSpec/DNAMP2/MREA.cpp index 681b0386b..45e01bfa2 100644 --- a/DataSpec/DNAMP2/MREA.cpp +++ b/DataSpec/DNAMP2/MREA.cpp @@ -169,15 +169,7 @@ bool MREA::Extract(const SpecBase& dataSpec, using RigPair = std::pair; RigPair dummy(nullptr, nullptr); - hecl::ProjectPath mreaPath; - if (pakRouter.isShared()) - /* Rename MREA for consistency */ - mreaPath = hecl::ProjectPath(outPath.getParentPath(), _S("!area.blend")); - else - /* We're not in a world pak, so lets keep the original name */ - mreaPath = outPath; - - if (!force && mreaPath.isFile()) + if (!force && outPath.isFile()) return true; /* Do extract */ @@ -199,7 +191,7 @@ bool MREA::Extract(const SpecBase& dataSpec, /* Start up blender connection */ hecl::BlenderConnection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(mreaPath, hecl::BlenderConnection::BlendType::Area)) + if (!conn.createBlend(outPath, hecl::BlenderConnection::BlendType::Area)) return false; /* Calculate offset to EGMC section */ diff --git a/DataSpec/DNAMP3/MREA.cpp b/DataSpec/DNAMP3/MREA.cpp index 85d1b0cb9..1a12aa7d9 100644 --- a/DataSpec/DNAMP3/MREA.cpp +++ b/DataSpec/DNAMP3/MREA.cpp @@ -78,15 +78,7 @@ bool MREA::Extract(const SpecBase& dataSpec, using RigPair = std::pair; RigPair dummy(nullptr, nullptr); - hecl::ProjectPath mreaPath; - if (pakRouter.isShared()) - /* Rename MREA for consistency */ - mreaPath = hecl::ProjectPath(outPath.getParentPath(), _S("!area.blend")); - else - /* We're not in a world pak, so lets keep the original name */ - mreaPath = outPath; - - if (!force && mreaPath.isFile()) + if (!force && outPath.isFile()) return true; /* Do extract */ @@ -111,7 +103,7 @@ bool MREA::Extract(const SpecBase& dataSpec, /* Start up blender connection */ hecl::BlenderConnection& conn = btok.getBlenderConnection(); - if (!conn.createBlend(mreaPath, hecl::BlenderConnection::BlendType::Area)) + if (!conn.createBlend(outPath, hecl::BlenderConnection::BlendType::Area)) return false; /* Open Py Stream and read sections */ diff --git a/DataSpec/SpecBase.cpp b/DataSpec/SpecBase.cpp index c50cf1a0b..fd4d7209f 100644 --- a/DataSpec/SpecBase.cpp +++ b/DataSpec/SpecBase.cpp @@ -257,6 +257,12 @@ void SpecBase::doCook(const hecl::ProjectPath& path, const hecl::ProjectPath& co cookArea(cookedPath, path, ds, fast, btok, progress); break; } + case hecl::BlenderConnection::BlendType::World: + { + hecl::BlenderConnection::DataStream ds = conn.beginData(); + cookWorld(cookedPath, path, ds, fast, btok, progress); + break; + } default: break; } } diff --git a/DataSpec/SpecBase.hpp b/DataSpec/SpecBase.hpp index 3e27c22ba..35ca28372 100644 --- a/DataSpec/SpecBase.hpp +++ b/DataSpec/SpecBase.hpp @@ -67,6 +67,9 @@ struct SpecBase : hecl::Database::IDataSpec virtual void cookArea(const hecl::ProjectPath& out, const hecl::ProjectPath& in, BlendStream& ds, bool fast, hecl::BlenderToken& btok, FCookProgress progress)=0; + virtual void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, + BlendStream& ds, bool fast, hecl::BlenderToken& btok, + FCookProgress progress)=0; virtual void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, FCookProgress progress)=0; virtual void cookAudioGroup(const hecl::ProjectPath& out, const hecl::ProjectPath& in, diff --git a/DataSpec/SpecMP1.cpp b/DataSpec/SpecMP1.cpp index f01875bec..a5efd4005 100644 --- a/DataSpec/SpecMP1.cpp +++ b/DataSpec/SpecMP1.cpp @@ -444,6 +444,14 @@ struct SpecMP1 : SpecBase DNAMP1::MREA::Cook(out, in, meshCompiles, *colMesh, lights); } + void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, + BlendStream& ds, bool fast, hecl::BlenderToken& btok, + FCookProgress progress) + { + BlendStream::World world = ds.compileWorld(); + + } + void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, FCookProgress progress) { diff --git a/DataSpec/SpecMP2.cpp b/DataSpec/SpecMP2.cpp index ff6384135..7cd48190a 100644 --- a/DataSpec/SpecMP2.cpp +++ b/DataSpec/SpecMP2.cpp @@ -321,6 +321,12 @@ struct SpecMP2 : SpecBase { } + void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, + BlendStream& ds, bool fast, hecl::BlenderToken& btok, + FCookProgress progress) + { + } + void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, FCookProgress progress) { diff --git a/DataSpec/SpecMP3.cpp b/DataSpec/SpecMP3.cpp index 7fbccad74..06d560c17 100644 --- a/DataSpec/SpecMP3.cpp +++ b/DataSpec/SpecMP3.cpp @@ -507,6 +507,12 @@ struct SpecMP3 : SpecBase { } + void cookWorld(const hecl::ProjectPath& out, const hecl::ProjectPath& in, + BlendStream& ds, bool fast, hecl::BlenderToken& btok, + FCookProgress progress) + { + } + void cookYAML(const hecl::ProjectPath& out, const hecl::ProjectPath& in, athena::io::IStreamReader& fin, FCookProgress progress) { diff --git a/Runtime/AutoMapper/CMapWorldInfo.cpp b/Runtime/AutoMapper/CMapWorldInfo.cpp index e27212be2..14b963d37 100644 --- a/Runtime/AutoMapper/CMapWorldInfo.cpp +++ b/Runtime/AutoMapper/CMapWorldInfo.cpp @@ -1,4 +1,6 @@ #include "CMapWorldInfo.hpp" +#include "GameGlobalObjects.hpp" +#include "CMemoryCardSys.hpp" namespace urde { @@ -6,6 +8,15 @@ namespace urde CMapWorldInfo::CMapWorldInfo(CBitStreamReader& reader, const CSaveWorld& saveWorld, ResId mlvlId) { /* TODO: implement */ + + const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); + auto saveWorldMem = std::find_if(memWorlds.cbegin(), memWorlds.cend(), + [&](const auto& test) -> bool { return test.first == mlvlId; }); + + if (saveWorldMem != memWorlds.cend()) + { + } + } void CMapWorldInfo::SetDoorVisited(TEditorId eid, bool visited) diff --git a/Runtime/CGameOptions.cpp b/Runtime/CGameOptions.cpp index 88b1e2046..af1b04904 100644 --- a/Runtime/CGameOptions.cpp +++ b/Runtime/CGameOptions.cpp @@ -30,10 +30,10 @@ CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); size_t cinematicCount = 0; - for (const CSaveWorldMemory& world : memWorlds) + for (const auto& world : memWorlds) { TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.GetSaveWorldAssetId()}); + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.first}); cinematicCount += saveWorld->GetCinematicCount(); } @@ -42,15 +42,15 @@ CPersistentOptions::CPersistentOptions(CBitStreamReader& stream) for (size_t i=0 ; i saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.GetSaveWorldAssetId()}); + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), world.first}); auto stateIt = cinematicStates.cbegin(); for (TEditorId cineId : saveWorld->GetCinematics()) if (*stateIt++) - SetCinematicState(world.GetWorldAssetId(), cineId, true); + SetCinematicState(world.first, cineId, true); } } diff --git a/Runtime/CGameState.cpp b/Runtime/CGameState.cpp index 50ba70557..67ea7a410 100644 --- a/Runtime/CGameState.cpp +++ b/Runtime/CGameState.cpp @@ -33,15 +33,15 @@ CGameState::CGameState(CBitStreamReader& stream) for (u32 i = 0; i < 128; i++) stream.ReadEncoded(8); u32 tmp = stream.ReadEncoded(32); - double val1 = *(reinterpret_cast(&tmp)); + float val1 = reinterpret_cast(tmp); bool val2 = stream.ReadEncoded(1); stream.ReadEncoded(1); tmp = stream.ReadEncoded(32); - double val3 = *(reinterpret_cast(&tmp)); + float val3 = reinterpret_cast(tmp); tmp = stream.ReadEncoded(32); - double val4 = *(reinterpret_cast(&tmp)); + float val4 = reinterpret_cast(tmp); tmp = stream.ReadEncoded(32); - double val5 = *(reinterpret_cast(&tmp)); + float val5 = reinterpret_cast(tmp); x98_playerState = std::make_shared(stream); float currentHealth = x98_playerState->GetHealthInfo().GetHP(); @@ -49,13 +49,13 @@ CGameState::CGameState(CBitStreamReader& stream) x17c_gameOptions = CGameOptions(stream); x1f8_hintOptions = CHintOptions(stream); - const std::vector& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); + const auto& memWorlds = g_MemoryCardSys->GetMemoryWorlds(); x88_worldStates.reserve(memWorlds.size()); - for (const CSaveWorldMemory& memWorld : memWorlds) + for (const auto& memWorld : memWorlds) { TLockedToken saveWorld = - g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.GetSaveWorldAssetId()}); - x88_worldStates.emplace_back(stream, memWorld.GetWorldAssetId(), *saveWorld); + g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), memWorld.second.GetSaveWorldAssetId()}); + x88_worldStates.emplace_back(stream, memWorld.first, *saveWorld); } } diff --git a/Runtime/CGameState.hpp b/Runtime/CGameState.hpp index cc0204839..0cecea31e 100644 --- a/Runtime/CGameState.hpp +++ b/Runtime/CGameState.hpp @@ -15,6 +15,7 @@ class CSaveWorldMemory; /* TODO: Figure out */ class CWorldSomethingState { + friend class CSaveWorldIntermediate; std::vector x0_; u32 x10_bitCount = 0; std::vector x14_; @@ -50,9 +51,10 @@ public: CWorldState(CBitStreamReader& reader, ResId mlvlId, const CSaveWorld& saveWorld); ResId GetWorldAssetId() const {return x0_mlvlId;} void SetAreaId(TAreaId aid) { x4_areaId = aid; } - const TAreaId& GetCurrentAreaId() const { return x4_areaId; } - std::shared_ptr RelayTracker() { return x8_relayTracker; } - std::shared_ptr MapWorldInfo() { return xc_mapWorldInfo; } + TAreaId GetCurrentAreaId() const { return x4_areaId; } + const std::shared_ptr& RelayTracker() const { return x8_relayTracker; } + const std::shared_ptr& MapWorldInfo() const { return xc_mapWorldInfo; } + const std::shared_ptr& GetSomethingElse() const { return x14_; } }; class CGameState diff --git a/Runtime/CMemoryCardSys.cpp b/Runtime/CMemoryCardSys.cpp index 8645eed5f..a5c71d83e 100644 --- a/Runtime/CMemoryCardSys.cpp +++ b/Runtime/CMemoryCardSys.cpp @@ -1,35 +1,131 @@ #include "CMemoryCardSys.hpp" #include "GameGlobalObjects.hpp" #include "CSimplePool.hpp" +#include "CGameState.hpp" namespace urde { -CSaveWorldMemory::CSaveWorldMemory(ResId mlvl, ResId savw) +CSaveWorldIntermediate::CSaveWorldIntermediate(ResId mlvl, ResId savw) : x0_mlvlId(mlvl), x8_savwId(savw) { if (savw == -1) x2c_dummyWorld = std::make_unique(mlvl, false); else - x3c_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), savw}); + x34_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), savw}); +} + +bool CSaveWorldIntermediate::InitializePump() +{ + if (x2c_dummyWorld) + { + CDummyWorld& wld = *x2c_dummyWorld; + if (!wld.ICheckWorldComplete()) + return false; + + x4_strgId = wld.IGetStringTableAssetId(); + x8_savwId = wld.IGetSaveWorldAssetId(); + u32 areaCount = wld.IGetAreaCount(); + + xc_areaIds.reserve(areaCount); + for (u32 i=0 ; iIGetAreaId()); + } + + ResId mlvlId = wld.IGetWorldAssetId(); + CWorldState& mlvlState = g_GameState->StateForWorld(mlvlId); + x1c_ = mlvlState.GetSomethingElse()->x0_; + + x34_saveWorld = g_SimplePool->GetObj(SObjectTag{FOURCC('SAVW'), x8_savwId}); + x2c_dummyWorld.reset(); + } + else + { + if (!x34_saveWorld) + return true; + if (x34_saveWorld.IsLoaded() && x34_saveWorld.GetObj()) + return true; + } + + return false; } CMemoryCardSys::CMemoryCardSys() { xc_memoryWorlds.reserve(16); - x1c_.reserve(16); + x1c_worldInter.emplace(); + x1c_worldInter->reserve(16); g_ResFactory->EnumerateNamedResources([&](const std::string& name, const SObjectTag& tag) -> bool { if (tag.type == FOURCC('MLVL')) { auto existingSearch = - std::find_if(xc_memoryWorlds.cbegin(), xc_memoryWorlds.cend(), [&](const CSaveWorldMemory& wld) - { return wld.GetWorldAssetId() == tag.id; }); + std::find_if(xc_memoryWorlds.cbegin(), xc_memoryWorlds.cend(), [&](const auto& wld) + { return wld.first == tag.id; }); if (existingSearch == xc_memoryWorlds.cend()) - xc_memoryWorlds.emplace_back(tag.id, -1); + { + xc_memoryWorlds.emplace_back(tag.id, CSaveWorldMemory{}); + x1c_worldInter->emplace_back(tag.id, -1); + } } return true; }); } +bool CMemoryCardSys::InitializePump() +{ + if (!x1c_worldInter) + { + for (const auto& world : xc_memoryWorlds) + { + const CSaveWorldMemory& wld = world.second; + if (!wld.GetWorldName().IsLoaded() || + !wld.GetWorldName().GetObj()) + return false; + } + + if (!x0_hints.IsLoaded() || !x0_hints.GetObj()) + return false; + return true; + } + + bool done = true; + for (CSaveWorldIntermediate& world : *x1c_worldInter) + { + if (world.InitializePump()) + { + if (!world.x34_saveWorld) + continue; + + auto existingSearch = + std::find_if(xc_memoryWorlds.begin(), xc_memoryWorlds.end(), [&](const auto& test) + { return test.first == world.x0_mlvlId; }); + CSaveWorldMemory& wldMemOut = existingSearch->second; + wldMemOut.x4_savwId = world.x8_savwId; + wldMemOut.x0_strgId = world.x4_strgId; + wldMemOut.xc_areaIds = world.xc_areaIds; + wldMemOut.x1c_ = world.x1c_; + + CSaveWorld& savw = *world.x34_saveWorld; + wldMemOut.x8_areaCount = savw.GetAreaCount(); + + x20_scanStates.reserve(x20_scanStates.size() + savw.GetScans().size()); + for (const CSaveWorld::SScanState& scan : savw.GetScans()) + x20_scanStates[scan.x0_id] = scan.x4_category; + + wldMemOut.x3c_saveWorld = std::move(world.x34_saveWorld); + wldMemOut.x2c_worldName = g_SimplePool->GetObj(SObjectTag{FOURCC('STRG'), wldMemOut.x0_strgId}); + } + else + done = false; + } + + if (done) + x1c_worldInter = std::experimental::nullopt; + + return false; +} + } diff --git a/Runtime/CMemoryCardSys.hpp b/Runtime/CMemoryCardSys.hpp index f6b646b4d..1cc1d4b18 100644 --- a/Runtime/CMemoryCardSys.hpp +++ b/Runtime/CMemoryCardSys.hpp @@ -4,50 +4,61 @@ #include "CToken.hpp" #include "World/CWorld.hpp" #include "CGameHintInfo.hpp" +#include "CSaveWorld.hpp" #include namespace urde { class CDummyWorld; -class CSaveWorld; +class CStringTable; class CSaveWorldMemory { - ResId x0_mlvlId = -1; - ResId x4_unk = -1; - ResId x8_savwId; - std::vector xc_; - std::vector x1c_; - std::unique_ptr x2c_dummyWorld; - TLockedToken x3c_saveWorld; /* Used to be auto_ptr */ + friend class CMemoryCardSys; + ResId x0_strgId = -1; + ResId x4_savwId = -1; + u32 x8_areaCount; + std::vector xc_areaIds; /* 4 byte element */ + std::vector x1c_; /* 16 byte element */ + TLockedToken x2c_worldName; /* used to be optional */ + TLockedToken x3c_saveWorld; /* used to be optional */ public: - ResId GetWorldAssetId() const { return x0_mlvlId; } - ResId GetSaveWorldAssetId() const { return x8_savwId; } - CSaveWorldMemory(ResId mlvl, ResId savw); + ResId GetSaveWorldAssetId() const { return x4_savwId; } + u32 GetAreaCount() const { return x8_areaCount; } + + const TLockedToken& GetWorldName() const { return x2c_worldName; } + const TLockedToken& GetSaveWorld() const { return x3c_saveWorld; } }; -/* TODO: figure out */ -class CMemorySomethingElse +class CSaveWorldIntermediate { - u32 x0_; - u32 x4_; - u32 x8_; - std::vector xc_; + friend class CMemoryCardSys; + u32 x0_mlvlId; + u32 x4_strgId; + u32 x8_savwId; + std::vector xc_areaIds; std::vector x1c_; - std::unique_ptr x2c_; - std::unique_ptr x34_; + std::unique_ptr x2c_dummyWorld; + TLockedToken x34_saveWorld; /* Used to be auto_ptr */ + +public: + CSaveWorldIntermediate(ResId mlvl, ResId savw); + + bool InitializePump(); }; class CMemoryCardSys { TLockedToken x0_hints; - std::vector xc_memoryWorlds; - std::vector x1c_; /* used to be auto_ptr of vector */ + std::vector> xc_memoryWorlds; /* MLVL as key */ + std::experimental::optional> x1c_worldInter; /* used to be auto_ptr of vector */ + std::unordered_map x20_scanStates; public: const std::vector& GetHints() const { return x0_hints->GetHints(); } - const std::vector& GetMemoryWorlds() const { return xc_memoryWorlds; } + const std::vector>& GetMemoryWorlds() const { return xc_memoryWorlds; } CMemoryCardSys(); + bool InitializePump(); }; } diff --git a/Runtime/CSaveWorld.hpp b/Runtime/CSaveWorld.hpp index 14e9e7465..0dabc5205 100644 --- a/Runtime/CSaveWorld.hpp +++ b/Runtime/CSaveWorld.hpp @@ -36,6 +36,7 @@ public: u32 GetCinematicCount() const; s32 GetCinematicIndex(const TEditorId& id) const; const std::vector& GetCinematics() const { return x4_cinematics; } + const std::vector& GetScans() const { return x44_scans; } u32 GetRelayCount() const; s32 GetRelayIndex(const TEditorId& id) const; TEditorId GetRelayEditorId(u32 idx) const; diff --git a/Runtime/MP1/MP1.cpp b/Runtime/MP1/MP1.cpp index 9747d5b4b..fb2e06d15 100644 --- a/Runtime/MP1/MP1.cpp +++ b/Runtime/MP1/MP1.cpp @@ -23,8 +23,9 @@ URDE_DECL_SPECIALIZE_MULTI_BLEND_SHADER(CTexturedQuadFilterAlpha) namespace MP1 { -CGameArchitectureSupport::CGameArchitectureSupport(amuse::IBackendVoiceAllocator& backend) -: m_audioSys(backend, 0,0,0,0,0), +CGameArchitectureSupport::CGameArchitectureSupport(CMain& parent, amuse::IBackendVoiceAllocator& backend) +: m_parent(parent), + m_audioSys(backend, 0,0,0,0,0), m_inputGenerator(g_tweakPlayer->GetLeftLogicalThreshold(), g_tweakPlayer->GetRightLogicalThreshold()), m_guiSys(*g_ResFactory, *g_SimplePool, CGuiSys::EUsageMode::Zero) @@ -51,6 +52,9 @@ CGameArchitectureSupport::CGameArchitectureSupport(amuse::IBackendVoiceAllocator bool CGameArchitectureSupport::Update() { + if (!g_MemoryCardSys) + m_parent.x128_globalObjects.MemoryCardInitializePump(); + bool finished = false; m_inputGenerator.Update(1.0 / 60.0, m_archQueue); @@ -146,7 +150,7 @@ void CMain::Init(const hecl::Runtime::FileStoreManager& storeMgr, x128_globalObjects.PostInitialize(); x70_tweaks.RegisterTweaks(); x70_tweaks.RegisterResourceTweaks(); - m_archSupport.reset(new CGameArchitectureSupport(backend)); + m_archSupport.reset(new CGameArchitectureSupport(*this, backend)); g_archSupport = m_archSupport.get(); //g_TweakManager->ReadFromMemoryCard("AudioTweaks"); FillInAssetIDs(); diff --git a/Runtime/MP1/MP1.hpp b/Runtime/MP1/MP1.hpp index 7c515c5e4..2a706249f 100644 --- a/Runtime/MP1/MP1.hpp +++ b/Runtime/MP1/MP1.hpp @@ -45,6 +45,8 @@ class IObjectStore; namespace MP1 { +class CMain; + class CGameGlobalObjects { std::unique_ptr x0_memoryCardSys; @@ -72,8 +74,6 @@ public: : x4_resFactory(resFactory), xcc_simplePool(objStore) { g_ResFactory = &x4_resFactory; - x0_memoryCardSys.reset(new CMemoryCardSys()); - g_MemoryCardSys = x0_memoryCardSys.get(); g_SimplePool = &xcc_simplePool; g_CharFactoryBuilder = &xec_charFactoryBuilder; g_AiFuncMap = &x110_aiFuncMap; @@ -86,6 +86,17 @@ public: LoadStringTable(); m_renderer.reset(AllocateRenderer(xcc_simplePool, x4_resFactory)); } + + void MemoryCardInitializePump() + { + if (!g_MemoryCardSys) + { + if (!x0_memoryCardSys) + x0_memoryCardSys.reset(new CMemoryCardSys()); + if (x0_memoryCardSys->InitializePump()) + g_MemoryCardSys = x0_memoryCardSys.get(); + } + } }; #if MP1_USE_BOO @@ -94,6 +105,7 @@ class CGameArchitectureSupport : public boo::IWindowCallback class CGameArchitectureSupport #endif { + CMain& m_parent; CArchitectureQueue m_archQueue; CAudioSys m_audioSys; CInputGenerator m_inputGenerator; @@ -132,7 +144,7 @@ class CGameArchitectureSupport } public: - CGameArchitectureSupport(amuse::IBackendVoiceAllocator& backend); + CGameArchitectureSupport(CMain& parent, amuse::IBackendVoiceAllocator& backend); void PreloadAudio(); bool Update(); void Draw(); @@ -151,6 +163,7 @@ class CMain : public boo::IApplicationCallback, public IMain class CMain : public IMain #endif { + friend class CGameArchitectureSupport; #if MP1_USE_BOO boo::IWindow* mainWindow; int appMain(boo::IApplication* app); diff --git a/hecl b/hecl index 536a8e4f7..08a14f35b 160000 --- a/hecl +++ b/hecl @@ -1 +1 @@ -Subproject commit 536a8e4f7dfff11695585d910018211718ff7225 +Subproject commit 08a14f35bf8a6381f13f1fa4681e59b30eede946 diff --git a/nod b/nod index 213289524..38de2ec4a 160000 --- a/nod +++ b/nod @@ -1 +1 @@ -Subproject commit 2132895242586251712d40405dd755ff703da638 +Subproject commit 38de2ec4a1f1974c8a7b02a78c593907886ae3aa diff --git a/specter b/specter index 067c86a58..f6318521f 160000 --- a/specter +++ b/specter @@ -1 +1 @@ -Subproject commit 067c86a585cc43513c3e2c667612d82aacf9809f +Subproject commit f6318521f9f28de34051f8e519f7ba8069501468