#include "MetroidPrime/CGameArea.hpp" #include "Kyoto/CDvdRequest.hpp" #include "Kyoto/CResFactory.hpp" #define ROUND_UP_32(val) (((val) + 31) & ~31) rstl::pair< rstl::auto_ptr< uchar >, int > GetScriptingMemoryAlways(const IGameArea& area) { SObjectTag tag('MREA', area.IGetAreaAssetId()); rstl::auto_ptr< char > buf = rs_new char[0x60]; CInputStream* resource = gpResourceFactory->GetResLoader().LoadNewResourceSync(tag, 0, 0x60, buf.get()); if (!resource || *(uint*)(buf.get()) != 0xdeadbeef) { return rstl::pair< rstl::auto_ptr< uchar >, int >(nullptr, 0); } } CGameArea::CPostConstructed::CPostConstructed() {} CGameArea::CPostConstructed::~CPostConstructed() {} const CTransform4f& CGameArea::IGetTM() const { return xc_transform; } CAssetId CGameArea::IGetStringTableAssetId() const { return x8_nameSTRG; } uint CGameArea::IGetNumAttachedAreas() const { return x8c_attachedAreaIndices.size(); } TAreaId CGameArea::IGetAttachedAreaId(int i) const { return x8c_attachedAreaIndices[i]; } bool CGameArea::IIsActive() const { return xf0_25_active; } CAssetId CGameArea::IGetAreaAssetId() const { return x84_mrea; } int CGameArea::IGetAreaSaveId() const { return x88_areaId; } rstl::pair< rstl::auto_ptr< uchar >, int > CGameArea::IGetScriptingMemoryAlways() const { return GetScriptingMemoryAlways(*this); } bool CGameArea::StartStreamingMainArea() { if (xf0_24_postConstructed) return false; switch (xf4_phase) { case kP_LoadHeader: { x110_mreaSecBufs.reserve(3); AllocNewAreaData(0, 96); x12c_postConstructed.Set(rs_new CPostConstructed()); xf4_phase = kP_LoadSecSizes; break; } case kP_LoadSecSizes: { CullDeadAreaRequests(); if (!xf8_loadTransactions.empty()) break; VerifyHeader(); AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(GetNumPartSizes() * 4)); xf4_phase = kP_ReserveSections; break; } case kP_ReserveSections: { CullDeadAreaRequests(); if (xf8_loadTransactions.empty()) { 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(); int totalSz = 0; int secCount = x124_secCount; int partSizes = GetNumPartSizes(); SObjectTag tag('MREA', x84_mrea); // 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; // } int dif = partSizes - secCount; int targetSecCount = secCount; for (int i = secCount; i < partSizes; ++i) { int size = x110_mreaSecBufs[i].second; if (targetSecCount != secCount && 0x10000 < size + totalSz) break; totalSz += size; targetSecCount += 1; } rstl::auto_ptr< char > buf = (char*)CMemory::Alloc(totalSz, IAllocator::kHI_RoundUpLen); xf8_loadTransactions.push_back( rstl::rc_ptr< CDvdRequest >(gpResourceFactory->GetResLoader().LoadResourcePartAsync( tag, x128_mreaDataOffset, totalSz, buf.get()))); x128_mreaDataOffset += totalSz; x110_mreaSecBufs.push_back(rstl::pair< rstl::auto_ptr< char >, int >(buf, 0)); for (int i = secCount + 1; i < targetSecCount; ++i) { x110_mreaSecBufs.push_back(rstl::pair< rstl::auto_ptr< char >, int >(nullptr, 0)); } x124_secCount = targetSecCount; if (targetSecCount == partSizes) { x120_unk = x128_mreaDataOffset; xf4_phase = kP_WaitForFinish; } break; } case kP_WaitForFinish: { CullDeadAreaRequests(); if (xf8_loadTransactions.empty()) return false; break; } default: break; } return true; }