diff --git a/Editor/ProjectResourceFactoryMP1.cpp b/Editor/ProjectResourceFactoryMP1.cpp index 1339549ab..aed22a0ec 100644 --- a/Editor/ProjectResourceFactoryMP1.cpp +++ b/Editor/ProjectResourceFactoryMP1.cpp @@ -15,6 +15,7 @@ #include "Runtime/Character/CAllFormatsAnimSource.hpp" #include "Runtime/Character/CAnimPOIData.hpp" #include "Runtime/Collision/CCollidableOBBTreeGroup.hpp" +#include "Audio/CAudioGroupSet.hpp" #include "Runtime/CDependencyGroup.hpp" #include "DataSpec/DNACommon/TXTR.hpp" @@ -42,6 +43,7 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client m_factoryMgr.AddFactory(FOURCC('EVNT'), FFactoryFunc(AnimPOIDataFactory)); m_factoryMgr.AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory)); m_factoryMgr.AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory)); + m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); } void ProjectResourceFactoryMP1::IndexMP1Resources(hecl::Database::Project& proj) diff --git a/Runtime/Audio/CAudioGroupSet.cpp b/Runtime/Audio/CAudioGroupSet.cpp new file mode 100644 index 000000000..8f433bc83 --- /dev/null +++ b/Runtime/Audio/CAudioGroupSet.cpp @@ -0,0 +1,39 @@ +#include "CAudioGroupSet.hpp" + +namespace urde +{ + +amuse::AudioGroupData CAudioGroupSet::LoadData() +{ + athena::io::MemoryReader r(m_buffer.get(), INT32_MAX); + x10_baseName = r.readString(); + x20_name = r.readString(); + + u8* buf = m_buffer.get() + r.position(); + uint32_t poolLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* pool = buf + 4; + buf += poolLen + 4; + uint32_t projLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* proj = buf + 4; + buf += projLen + 4; + uint32_t sampLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* samp = buf + 4; + buf += sampLen + 4; + uint32_t sdirLen = hecl::SBig(*reinterpret_cast(buf)); + unsigned char* sdir = buf + 4; + + return {proj, projLen, pool, poolLen, sdir, sdirLen, samp, sampLen, amuse::GCNDataTag{}}; +} + +CAudioGroupSet::CAudioGroupSet(std::unique_ptr&& in) +: m_buffer(std::move(in)), m_data(LoadData()) +{} + +CFactoryFnReturn FAudioGroupSetDataFactory(const urde::SObjectTag& tag, + std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms) +{ + return TToken::GetIObjObjectFor(std::make_unique(std::move(in))); +} + +} diff --git a/Runtime/Audio/CAudioGroupSet.hpp b/Runtime/Audio/CAudioGroupSet.hpp new file mode 100644 index 000000000..232e8b0c7 --- /dev/null +++ b/Runtime/Audio/CAudioGroupSet.hpp @@ -0,0 +1,32 @@ +#ifndef __URDE_CAUDIOGROUPSET_HPP__ +#define __URDE_CAUDIOGROUPSET_HPP__ + +#include "RetroTypes.hpp" +#include "CFactoryMgr.hpp" +#include "IObj.hpp" +#include "CToken.hpp" +#include "IOStreams.hpp" +#include "amuse/AudioGroupData.hpp" + +namespace urde +{ + +class CAudioGroupSet +{ + std::unique_ptr m_buffer; + std::string x10_baseName; + std::string x20_name; + amuse::AudioGroupData m_data; + amuse::AudioGroupData LoadData(); +public: + CAudioGroupSet(std::unique_ptr&& in); + const amuse::AudioGroupData& GetAudioGroupData() const {return m_data;} +}; + +CFactoryFnReturn FAudioGroupSetDataFactory(const urde::SObjectTag& tag, + std::unique_ptr&& in, u32 len, + const urde::CVParamTransfer& vparms); + +} + +#endif // __URDE_CAUDIOGROUPSET_HPP__ diff --git a/Runtime/Audio/CMakeLists.txt b/Runtime/Audio/CMakeLists.txt index 27dfc4710..8be468042 100644 --- a/Runtime/Audio/CMakeLists.txt +++ b/Runtime/Audio/CMakeLists.txt @@ -1,6 +1,7 @@ set(AUDIO_SOURCES CAudioSys.hpp CAudioSys.cpp CAudioStateWin.hpp CAudioStateWin.cpp + CAudioGroupSet.hpp CAudioGroupSet.cpp CSfxManager.hpp CSfxManager.cpp CSfxHandle.hpp CSfxHandle.cpp g721.c g721.h) diff --git a/Runtime/AutoMapper/CMapWorld.hpp b/Runtime/AutoMapper/CMapWorld.hpp index 241469555..73f8930e6 100644 --- a/Runtime/AutoMapper/CMapWorld.hpp +++ b/Runtime/AutoMapper/CMapWorld.hpp @@ -1,6 +1,8 @@ #ifndef __URDE_CMAPWORLD_HPP__ #define __URDE_CMAPWORLD_HPP__ +#include "RetroTypes.hpp" + namespace urde { class IWorld; @@ -8,7 +10,7 @@ class IWorld; class CMapWorld { public: - void SetWhichMapAreasLoaded(const IWorld&, int, int); + void SetWhichMapAreasLoaded(const IWorld&, int start, int count); bool IsMapAreasStreaming() const; }; diff --git a/Runtime/World/CWorld.cpp b/Runtime/World/CWorld.cpp index b4c90342b..8810221fa 100644 --- a/Runtime/World/CWorld.cpp +++ b/Runtime/World/CWorld.cpp @@ -9,6 +9,12 @@ namespace urde { +CWorld::CSoundGroupData::CSoundGroupData(int grpId, ResId agsc) +: x0_groupId(grpId), x4_agscId(agsc) +{ + x1c_groupData = g_SimplePool->GetObj(SObjectTag{FOURCC('AGSC'), agsc}); +} + CDummyWorld::CDummyWorld(ResId mlvlId, bool loadMap) : x4_loadMap(loadMap) { @@ -248,6 +254,14 @@ void CWorld::MoveToChain(CGameArea* area, EChain chain) { } +void CWorld::LoadSoundGroup(int groupId, ResId agscId, CSoundGroupData& data) +{ +} + +void CWorld::LoadSoundGroups() +{ +} + bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId) { if (mreaId != -1) @@ -284,7 +298,7 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId) { ResId skyboxId = r.readUint32Big(); if (skyboxId != -1 && mgr) - x84_skybox = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), skyboxId}); + x94_skybox = g_SimplePool->GetObj(SObjectTag{FOURCC('CMDL'), skyboxId}); } if (version >= 17) x2c_relays = CWorld::CRelay::ReadMemoryRelays(r); @@ -342,10 +356,64 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId) } case Phase::LoadingMap: { + if (!x28_mapWorld.IsLoaded() || !x28_mapWorld.GetObj()) + return false; + + if (x68_curAreaId == kInvalidAreaId) + x28_mapWorld->SetWhichMapAreasLoaded(*this, 0, 9999); + else + x28_mapWorld->SetWhichMapAreasLoaded(*this, x68_curAreaId, 3); + x4_phase = Phase::LoadingMapAreas; } case Phase::LoadingMapAreas: { + if (x28_mapWorld->IsMapAreasStreaming()) + return false; + + x4_phase = Phase::LoadingSkyBox; + } + case Phase::LoadingSkyBox: + { + x70_26_ = true; + x70_27_ = false; + + if (!x94_skybox.IsLoaded()) + return false; + + CModel* skybox = x94_skybox.GetObj(); + if (!skybox) + return false; + + skybox->Touch(0); + if (!skybox->IsLoaded(0)) + return false; + + xa4_skyboxB = x94_skybox; + + for (CSoundGroupData& group : x74_soundGroupData) + group.x1c_groupData.Lock(); + + x4_phase = Phase::LoadingSoundGroups; + } + case Phase::LoadingSoundGroups: + { + bool allLoaded = true; + for (CSoundGroupData& group : x74_soundGroupData) + { + bool loaded = group.x1c_groupData.IsLoaded(); + allLoaded &= loaded; + if (loaded) + { + CAudioGroupSet* groupData = group.x1c_groupData.GetObj(); + if (groupData) + LoadSoundGroup(group.x0_groupId, group.x4_agscId, group); + } + } + if (!allLoaded) + return false; + + LoadSoundGroups(); x4_phase = Phase::Done; } case Phase::Done: @@ -354,6 +422,7 @@ bool CWorld::CheckWorldComplete(CStateManager* mgr, TAreaId id, ResId mreaId) return false; } + return false; } bool CWorld::ICheckWorldComplete() diff --git a/Runtime/World/CWorld.hpp b/Runtime/World/CWorld.hpp index 844f34e47..15f6b8ebe 100644 --- a/Runtime/World/CWorld.hpp +++ b/Runtime/World/CWorld.hpp @@ -13,6 +13,7 @@ class IObjectStore; class CResFactory; class CMapWorld; class IGameArea; +class CAudioGroupSet; class IWorld { @@ -87,8 +88,12 @@ public: static std::vector ReadMemoryRelays(athena::io::MemoryReader& r); }; - class CSoundGroupData + struct CSoundGroupData { + int x0_groupId; + ResId x4_agscId; + std::string xc_name; + TCachedToken x1c_groupData; public: CSoundGroupData(int grpId, ResId agsc); }; @@ -100,8 +105,8 @@ private: Loading, LoadingMap, LoadingMapAreas, - - + LoadingSkyBox, + LoadingSoundGroups, Done, } x4_phase = Phase::Loading; ResId x8_mlvlId = -1; @@ -131,10 +136,15 @@ private: bool x70_26_ : 1; bool x70_27_ : 1; }; + u16 dummy = 0; }; std::vector x74_soundGroupData; std::string x84_defAudioTrack; - TLockedToken x84_skybox; + TLockedToken x94_skybox; + TLockedToken xa4_skyboxB; + + void LoadSoundGroup(int groupId, ResId agscId, CSoundGroupData& data); + void LoadSoundGroups(); public: