diff --git a/configure.py b/configure.py index f83f5234..31888c80 100755 --- a/configure.py +++ b/configure.py @@ -56,7 +56,7 @@ LIBS = [ ["MetroidPrime/CExplosion", True], ["MetroidPrime/CEffect", True], "MetroidPrime/Cameras/CGameCamera", - "MetroidPrime/CGameArea", + ["MetroidPrime/CGameArea", False], "MetroidPrime/HUD/CSamusHud", ["MetroidPrime/CAnimationDatabaseGame", False], "MetroidPrime/CTransitionDatabaseGame", diff --git a/include/Kyoto/CPakFile.hpp b/include/Kyoto/CPakFile.hpp index f125113e..3a1918c2 100644 --- a/include/Kyoto/CPakFile.hpp +++ b/include/Kyoto/CPakFile.hpp @@ -10,7 +10,7 @@ #include "Kyoto/CResLoader.hpp" #include "Kyoto/IObjectStore.hpp" -class IDvdRequest; +class CDvdRequest; class CPakFile : CDvdFile { public: @@ -26,7 +26,7 @@ private: bool x28_26_worldPak : 1; bool x28_27_stashedInARAM : 1; int x2c_asyncLoadPhase; // EAsyncPhase - rstl::auto_ptr< IDvdRequest > x30_dvdReq; + rstl::auto_ptr< CDvdRequest > x30_dvdReq; rstl::vector< uchar > x38_headerData; uint x48_resTableOffset; uint x4c_resTableCount; diff --git a/include/Kyoto/CResLoader.hpp b/include/Kyoto/CResLoader.hpp index b9bd1ee2..1ccff5ad 100644 --- a/include/Kyoto/CResLoader.hpp +++ b/include/Kyoto/CResLoader.hpp @@ -9,6 +9,7 @@ #include "Kyoto/IObjectStore.hpp" class CPakFile; +class CARAMDvdRequest; struct SResInfo { CAssetId x0_id; @@ -26,6 +27,8 @@ public: void AsyncIdlePakLoading(); bool AreAllPaksLoaded() const; CInputStream* LoadNewResourceSync(const SObjectTag& tag, char* extBuf); + CARAMDvdRequest* LoadResourcePartAsync(const SObjectTag& tag, int, int, void*); + FourCC GetResourceTypeById(CAssetId) const; uint ResourceSize(const SObjectTag& tag) const; diff --git a/include/MetroidPrime/CGameArea.hpp b/include/MetroidPrime/CGameArea.hpp index 07f45d5b..16f71277 100644 --- a/include/MetroidPrime/CGameArea.hpp +++ b/include/MetroidPrime/CGameArea.hpp @@ -44,7 +44,7 @@ enum EChain { class Dock; class CToken; -class IDvdRequest; +class CDvdRequest; class CScriptAreaAttributes; class CWorldLight; class CPVSAreaSet; @@ -117,7 +117,15 @@ public: void SetAreaAttributes(const CScriptAreaAttributes* areaAttributes); bool TryTakingOutOfARAM(); + bool StartStreamingMainArea(); + private: + void AllocNewAreaData(int, int); + void CullDeadAreaRequests(); + void VerifyHeader() const; + int GetNumPartSizes() const; + + enum EPhase { kP_LoadHeader, kP_LoadSecSizes, @@ -145,7 +153,7 @@ private: bool xf0_27_loadPaused : 1; bool xf0_28_validated : 1; EPhase xf4_phase; - rstl::list< rstl::rc_ptr< IDvdRequest > > xf8_loadTransactions; + rstl::list< rstl::rc_ptr< CDvdRequest > > xf8_loadTransactions; public: enum EOcclusionState { kOS_Occluded, kOS_Visible }; @@ -160,6 +168,7 @@ public: const u8* x10d4_firstMatPtr; const CScriptAreaAttributes* x10d8_areaAttributes; EOcclusionState x10dc_occlusionState; + uchar x10e0_pad[0x60]; }; CAssetId GetAreaAssetId() const { return x84_mrea; } @@ -171,10 +180,15 @@ public: const CPVSAreaSet* GetAreaVisSet() const { return x12c_postConstructed->xa0_pvs; } private: - uchar x110_pad[0x1c]; + rstl::vector< rstl::pair< rstl::auto_ptr, int> > x110_mreaSecBufs; + int x120_unk; + int x124_secCount; + int x128_mreaDataOffset; rstl::single_ptr< CPostConstructed > x12c_postConstructed; }; +NESTED_CHECK_SIZEOF(CGameArea, CPostConstructed, 0x1140) + // CHECK_SIZEOF(CGamearea::CAreaFog, 0x38) #endif // _CGAMEAREA diff --git a/include/MetroidPrime/CWorld.hpp b/include/MetroidPrime/CWorld.hpp index 5a9acdf6..97641864 100644 --- a/include/MetroidPrime/CWorld.hpp +++ b/include/MetroidPrime/CWorld.hpp @@ -36,7 +36,7 @@ public: class CGameArea; class CRelay; class CSoundGroupData; -class IDvdRequest; +class CDvdRequest; class IFactory; class CRelay { @@ -115,7 +115,7 @@ private: CAssetId x24_mapwId; CMapWorld* x28_mapWorld; rstl::vector< CRelay > x2c_relays; - rstl::rc_ptr< IDvdRequest > x3c_loadToken; + rstl::rc_ptr< CDvdRequest > x3c_loadToken; rstl::single_ptr< uchar > x40_loadBuf; uint x44_bufSz; uint x48_chainCount; diff --git a/src/MetroidPrime/CGameArea.cpp b/src/MetroidPrime/CGameArea.cpp new file mode 100644 index 00000000..797042e9 --- /dev/null +++ b/src/MetroidPrime/CGameArea.cpp @@ -0,0 +1,82 @@ +#include "MetroidPrime/CGameArea.hpp" + +#include "Kyoto/CResFactory.hpp" +#include "Kyoto/CDvdRequest.hpp" + +#define ROUND_UP_32(val) (((val) + 31) & ~31) + +bool CGameArea::StartStreamingMainArea() { + if (xf0_24_postConstructed) + return false; + + switch (xf4_phase) { + case kP_LoadHeader: { + x110_mreaSecBufs.reserve(3); + AllocNewAreaData(0, 96); + x12c_postConstructed = new CPostConstructed(); + xf4_phase = kP_LoadSecSizes; + break; + } + case kP_LoadSecSizes: { + CullDeadAreaRequests(); + if (xf8_loadTransactions.size()) + break; + VerifyHeader(); + AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(GetNumPartSizes() * 4)); + xf4_phase = kP_ReserveSections; + break; + } + case kP_ReserveSections: { + CullDeadAreaRequests(); + if (xf8_loadTransactions.size() == 0) { + x110_mreaSecBufs.reserve(GetNumPartSizes() + 2); + x124_secCount = 0; + x128_mreaDataOffset = x110_mreaSecBufs[0].second + x110_mreaSecBufs[1].second; + xf4_phase = kP_LoadDataSections; + } + break; + } + case kP_LoadDataSections: { + CullDeadAreaRequests(); + + uint totalSz = 0; + uint secCount = GetNumPartSizes(); + // for (uint i = 0; i < secCount; ++i) + // totalSz += CBasics::SwapBytes(reinterpret_cast(x110_mreaSecBufs[1].first.get())[i]); + + // AllocNewAreaData(x128_mreaDataOffset, totalSz); + + // m_resolvedBufs.reserve(secCount); + // m_resolvedBufs.emplace_back(x110_mreaSecBufs[0].first.get(), x110_mreaSecBufs[0].second); + // m_resolvedBufs.emplace_back(x110_mreaSecBufs[1].first.get(), x110_mreaSecBufs[1].second); + + // uint curOff = 0; + // for (uint i = 0; i < secCount; ++i) { + // uint size = CBasics::SwapBytes(reinterpret_cast(x110_mreaSecBufs[1].first.get())[i]); + // m_resolvedBufs.emplace_back(x110_mreaSecBufs[2].first.get() + curOff, size); + // curOff += size; + // } + + SObjectTag tag('MREA', x84_mrea); + void* buf = CMemory::Alloc(totalSz, IAllocator::kHI_RoundUpLen); + xf8_loadTransactions.push_back( + rstl::rc_ptr< CDvdRequest >(gpResourceFactory->GetResLoader().LoadResourcePartAsync(tag, x128_mreaDataOffset, totalSz, buf)) + ); + x128_mreaDataOffset += totalSz; + // x110_mreaSecBufs.push_back(buf); + + xf4_phase = kP_WaitForFinish; + break; + } + case kP_WaitForFinish: { + CullDeadAreaRequests(); + if (xf8_loadTransactions.size()) + break; + return false; + } + default: + break; + } + + return true; +}