CScriptMidi and work on CGameArea loading

This commit is contained in:
Jack Andersen 2017-02-26 19:25:14 -10:00
parent 628e5b41df
commit e923d83617
28 changed files with 446 additions and 112 deletions

View File

@ -70,6 +70,10 @@ void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPo
if (poolIdx > 65535) if (poolIdx > 65535)
Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex"); Log.report(logvisor::Fatal, "AROT bitmap exceeds 16-bit node addressing; area too complex");
uint32_t childCount = AROTChildCounts[flags];
nodeOff = curOff;
nodeSz = childCount * 2 + 4;
curOff += nodeSz;
if (childNodes.size()) if (childNodes.size())
{ {
for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i) for (int i=0 ; i < 1 + ((flags & 0x1) != 0) ; ++i)
@ -82,10 +86,6 @@ void AROTBuilder::Node::nodeCount(size_t& sz, size_t& idxRefs, BitmapPool& bmpPo
} }
} }
} }
uint32_t childCount = AROTChildCounts[flags];
nodeOff = curOff;
nodeSz = childCount * 2 + 4;
curOff += nodeSz;
idxRefs += childCount; idxRefs += childCount;
} }
} }

View File

@ -270,7 +270,8 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
{ {
addedPaths.insert(path.hash()); addedPaths.insert(path.hash());
urde::SObjectTag tag = g_curSpec->BuildTagFromPath(path, btok); urde::SObjectTag tag = g_curSpec->BuildTagFromPath(path, btok);
areaOut.deps.emplace_back(tag.id, tag.type); if (tag.id != -1)
areaOut.deps.emplace_back(tag.id, tag.type);
} }
} }
} }
@ -308,12 +309,14 @@ bool MLVL::Cook(const hecl::ProjectPath& outPath, const hecl::ProjectPath& inPat
{ {
addedPaths.insert(path.hash()); addedPaths.insert(path.hash());
urde::SObjectTag tag = g_curSpec->BuildTagFromPath(path, btok); urde::SObjectTag tag = g_curSpec->BuildTagFromPath(path, btok);
areaOut.deps.emplace_back(tag.id, tag.type); if (tag.id != -1)
areaOut.deps.emplace_back(tag.id, tag.type);
} }
} }
urde::SObjectTag tag = g_curSpec->BuildTagFromPath(areaPath, btok); urde::SObjectTag tag = g_curSpec->BuildTagFromPath(areaPath, btok);
areaOut.deps.emplace_back(tag.id, tag.type); if (tag.id != -1)
areaOut.deps.emplace_back(tag.id, tag.type);
} }
++areaIdx; ++areaIdx;

View File

@ -518,7 +518,7 @@ bool MREA::PCCook(const hecl::ProjectPath& outPath,
} }
} }
if (!good) if (!good)
secs.emplace_back(0, 0); secs.emplace_back(4, 0);
} }
/* PATH */ /* PATH */

View File

@ -13,11 +13,11 @@ struct Midi : IScriptObject
{ {
DECL_YAML DECL_YAML
String<-1> name; String<-1> name;
Value<bool> unknown1; Value<bool> active;
UniqueID32 song; UniqueID32 song;
Value<float> unknown2; Value<float> fadeInTime;
Value<float> unknown3; Value<float> fadeOutTime;
Value<atUint32> unknown4; Value<atUint32> volume;
void nameIDs(PAKRouter<PAKBridge>& pakRouter) const void nameIDs(PAKRouter<PAKBridge>& pakRouter) const
{ {

View File

@ -532,10 +532,19 @@ void ProjectResourceFactoryBase::AsyncTask::CookComplete()
/* Ready for buffer transaction at this point */ /* Ready for buffer transaction at this point */
u32 availSz = std::max(0, s32(fr.length()) - s32(x14_resOffset)); u32 availSz = std::max(0, s32(fr.length()) - s32(x14_resOffset));
x14_resSize = std::min(x14_resSize, availSz); x14_resSize = std::min(x14_resSize, availSz);
x10_loadBuffer.reset(new u8[x14_resSize]); if (xc_targetDataRawPtr)
m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath, {
x10_loadBuffer.get(), m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath,
x14_resSize, x14_resOffset); xc_targetDataRawPtr,
x14_resSize, x14_resOffset);
}
else
{
x10_loadBuffer.reset(new u8[x14_resSize]);
m_bufTransaction = m_parent.m_clientProc.addBufferTransaction(m_cookedPath,
x10_loadBuffer.get(),
x14_resSize, x14_resOffset);
}
} }
bool ProjectResourceFactoryBase::AsyncTask::AsyncPump() bool ProjectResourceFactoryBase::AsyncTask::AsyncPump()
@ -778,6 +787,17 @@ ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag,
std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second; std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second;
} }
std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>
ProjectResourceFactoryBase::LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, u8* target)
{
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
Log.report(logvisor::Fatal, "attempted to access null id");
if (m_asyncLoadList.find(tag) != m_asyncLoadList.end())
return {};
return m_asyncLoadList.emplace(std::make_pair(tag,
std::make_shared<AsyncTask>(*this, tag, target, size, off))).first->second;
}
std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag) std::unique_ptr<u8[]> ProjectResourceFactoryBase::LoadResourceSync(const urde::SObjectTag& tag)
{ {
if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id) if ((tag.id & 0xffffffff) == 0xffffffff || !tag.id)
@ -986,6 +1006,13 @@ bool ProjectResourceFactoryBase::AsyncPumpTask(
task.x0_tag.type.toString().c_str(), task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id)); u32(task.x0_tag.id));
} }
else if (task.xc_targetDataRawPtr)
{
/* Buffer only raw */
Log.report(logvisor::Info, "async-loaded %.4s %08X",
task.x0_tag.type.toString().c_str(),
u32(task.x0_tag.id));
}
} }
it = m_asyncLoadList.erase(it); it = m_asyncLoadList.erase(it);

View File

@ -27,6 +27,7 @@ public:
SObjectTag x0_tag; SObjectTag x0_tag;
//IDvdRequest* x8_dvdReq = nullptr; //IDvdRequest* x8_dvdReq = nullptr;
std::unique_ptr<u8[]>* xc_targetDataPtr = nullptr; std::unique_ptr<u8[]>* xc_targetDataPtr = nullptr;
u8* xc_targetDataRawPtr = nullptr;
IObj** xc_targetObjPtr = nullptr; IObj** xc_targetObjPtr = nullptr;
std::unique_ptr<u8[]> x10_loadBuffer; std::unique_ptr<u8[]> x10_loadBuffer;
u32 x14_resSize = UINT32_MAX; u32 x14_resSize = UINT32_MAX;
@ -50,6 +51,11 @@ public:
: m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr), x14_resSize(size), : m_parent(parent), x0_tag(tag), xc_targetDataPtr(&ptr), x14_resSize(size),
x14_resOffset(off) {} x14_resOffset(off) {}
AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag,
u8* ptr, u32 size, u32 off)
: m_parent(parent), x0_tag(tag), xc_targetDataRawPtr(ptr), x14_resSize(size),
x14_resOffset(off) {}
AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag, AsyncTask(ProjectResourceFactoryBase& parent, const SObjectTag& tag,
IObj** ptr, const CVParamTransfer& xfer, CObjectReference* selfRef) IObj** ptr, const CVParamTransfer& xfer, CObjectReference* selfRef)
: m_parent(parent), x0_tag(tag), xc_targetObjPtr(ptr), x18_cvXfer(xfer), m_selfRef(selfRef) {} : m_parent(parent), x0_tag(tag), xc_targetObjPtr(ptr), x18_cvXfer(xfer), m_selfRef(selfRef) {}
@ -131,6 +137,7 @@ public:
u32 ResourceSize(const SObjectTag& tag); u32 ResourceSize(const SObjectTag& tag);
std::shared_ptr<AsyncTask> LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target); std::shared_ptr<AsyncTask> LoadResourceAsync(const urde::SObjectTag& tag, std::unique_ptr<u8[]>& target);
std::shared_ptr<AsyncTask> LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target); std::shared_ptr<AsyncTask> LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, std::unique_ptr<u8[]>& target);
std::shared_ptr<AsyncTask> LoadResourcePartAsync(const urde::SObjectTag& tag, u32 size, u32 off, u8* target);
std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag); std::unique_ptr<u8[]> LoadResourceSync(const urde::SObjectTag& tag);
std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off); std::unique_ptr<u8[]> LoadResourcePartSync(const urde::SObjectTag& tag, u32 size, u32 off);

View File

@ -28,6 +28,7 @@
#include "Runtime/CScannableObjectInfo.hpp" #include "Runtime/CScannableObjectInfo.hpp"
#include "Audio/CAudioGroupSet.hpp" #include "Audio/CAudioGroupSet.hpp"
#include "Audio/CSfxManager.hpp" #include "Audio/CSfxManager.hpp"
#include "Audio/CMidiManager.hpp"
#include "Runtime/CDependencyGroup.hpp" #include "Runtime/CDependencyGroup.hpp"
#include "DataSpec/DNACommon/TXTR.hpp" #include "DataSpec/DNACommon/TXTR.hpp"
#include "CSimplePool.hpp" #include "CSimplePool.hpp"
@ -109,6 +110,7 @@ ProjectResourceFactoryMP1::ProjectResourceFactoryMP1(hecl::ClientProcess& client
m_factoryMgr.AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory)); m_factoryMgr.AddFactory(FOURCC('DCLN'), FFactoryFunc(FCollidableOBBTreeGroupFactory));
m_factoryMgr.AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory)); m_factoryMgr.AddFactory(FOURCC('DGRP'), FFactoryFunc(FDependencyGroupFactory));
m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory)); m_factoryMgr.AddFactory(FOURCC('AGSC'), FMemFactoryFunc(FAudioGroupSetDataFactory));
m_factoryMgr.AddFactory(FOURCC('CSNG'), FFactoryFunc(FMidiDataFactory));
m_factoryMgr.AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory)); m_factoryMgr.AddFactory(FOURCC('ATBL'), FFactoryFunc(FAudioTranslationTableFactory));
m_factoryMgr.AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory)); m_factoryMgr.AddFactory(FOURCC('STRG'), FFactoryFunc(FStringTableFactory));
m_factoryMgr.AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory)); m_factoryMgr.AddFactory(FOURCC('HINT'), FFactoryFunc(FHintFactory));

View File

@ -3,9 +3,58 @@
namespace urde namespace urde
{ {
std::unordered_set<CMidiHandle> CMidiManager::m_MidiWrappers = {};
void CMidiManager::StopAll() void CMidiManager::StopAll()
{ {
for (auto it = m_MidiWrappers.begin() ; it != m_MidiWrappers.end() ;)
it = Stop(it, 0);
}
void CMidiManager::Stop(const CMidiHandle& handle, float fadeTime)
{
handle->GetAudioSysHandle()->stopSong(fadeTime);
m_MidiWrappers.erase(handle);
}
std::unordered_set<CMidiHandle>::iterator
CMidiManager::Stop(std::unordered_set<CMidiHandle>::iterator handle, float fadeTime)
{
const CMidiHandle& h = *handle;
h->GetAudioSysHandle()->stopSong(fadeTime);
return m_MidiWrappers.erase(handle);
}
CMidiHandle CMidiManager::Play(const CMidiData& data, float fadeTime, bool stopExisting, float volume)
{
if (stopExisting)
for (auto it = m_MidiWrappers.begin() ; it != m_MidiWrappers.end() ;)
it = Stop(it, fadeTime);
CMidiHandle handle = *m_MidiWrappers.insert(std::make_shared<CMidiWrapper>()).first;
handle->SetAudioSysHandle(CAudioSys::GetAmuseEngine().seqPlay(
data.GetGroupId(), data.GetSetupId(), data.GetArrData()));
handle->GetAudioSysHandle()->setVolume(volume, fadeTime);
handle->SetSongId(data.GetSetupId());
return handle;
}
CMidiManager::CMidiData::CMidiData(CInputStream& in)
{
in.readUint32Big();
x0_setupId = in.readUint32Big();
x2_groupId = in.readUint32Big();
x4_agscId = in.readUint32Big();
u32 length = in.readUint32Big();
x8_arrData.reset(new u8[length]);
in.readUBytesToBuf(x8_arrData.get(), length);
}
CFactoryFnReturn FMidiDataFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& parms,
CObjectReference* selfRef)
{
return TToken<CMidiManager::CMidiData>::GetIObjObjectFor(std::make_unique<CMidiManager::CMidiData>(in));
} }
} }

View File

@ -1,15 +1,62 @@
#ifndef __URDE_CMIDIMANAGER_HPP__ #ifndef __URDE_CMIDIMANAGER_HPP__
#define __URDE_CMIDIMANAGER_HPP__ #define __URDE_CMIDIMANAGER_HPP__
#include "CSfxManager.hpp"
namespace urde namespace urde
{ {
class CMidiManager class CMidiManager
{ {
public: public:
class CMidiData
{
u16 x0_setupId;
u16 x2_groupId;
ResId x4_agscId;
std::unique_ptr<u8[]> x8_arrData;
public:
u16 GetSetupId() const { return x0_setupId; }
u16 GetGroupId() const { return x2_groupId; }
ResId GetAGSCAssetId() const { return x4_agscId; }
const u8* GetArrData() const { return x8_arrData.get(); }
CMidiData(CInputStream& in);
};
class CMidiWrapper
{
std::shared_ptr<amuse::Sequencer> x0_sequencer;
//CSfxHandle x4_handle;
u16 x8_songId;
bool xa_available = true;
public:
const std::shared_ptr<amuse::Sequencer>& GetAudioSysHandle() const { return x0_sequencer; }
void SetAudioSysHandle(const std::shared_ptr<amuse::Sequencer>& sequencer) { x0_sequencer = sequencer; }
//const CSfxHandle& GetManagerHandle() const { return x4_handle; }
//void SetMidiHandle(const CSfxHandle& handle) { x4_handle = handle; }
bool IsAvailable() const { return xa_available; }
void SetAvailable(bool available) { xa_available = available; }
u16 GetSongId() const { return x8_songId; }
void SetSongId(u16 songId) { x8_songId = songId; }
};
using CMidiHandle = std::shared_ptr<CMidiWrapper>;
static void StopAll(); static void StopAll();
static void Stop(const CMidiHandle& handle, float fadeTime);
static std::unordered_set<CMidiHandle>::iterator
Stop(std::unordered_set<CMidiHandle>::iterator handle, float fadeTime);
static CMidiHandle Play(const CMidiData& data, float fadeTime, bool stopExisting, float volume);
private:
static std::unordered_set<CMidiHandle> m_MidiWrappers;
}; };
CFactoryFnReturn FMidiDataFactory(const SObjectTag& tag, CInputStream& in,
const CVParamTransfer& parms,
CObjectReference* selfRef);
using CMidiHandle = CMidiManager::CMidiHandle;
} }
#endif // __URDE_CMIDIMANAGER_HPP__ #endif // __URDE_CMIDIMANAGER_HPP__

View File

@ -16,14 +16,14 @@ public:
{ {
float x0_fadeIn, x4_fadeOut, x8_volume; float x0_fadeIn, x4_fadeOut, x8_volume;
std::string xc_fileName; std::string xc_fileName;
u32 x1c_handle; ResId x1c_res;
Audio(float fadeIn, float fadeOut, float vol, const std::string& fileName, u32 handle) Audio(float fadeIn, float fadeOut, float vol, const std::string& fileName, u32 handle)
: x0_fadeIn(fadeIn), x4_fadeOut(fadeOut), x8_volume(vol), xc_fileName(fileName), x1c_handle(handle) {} : x0_fadeIn(fadeIn), x4_fadeOut(fadeOut), x8_volume(vol), xc_fileName(fileName), x1c_res(handle) {}
float GetFadeIn() const { return x0_fadeIn; } float GetFadeIn() const { return x0_fadeIn; }
float GetFadeOut() const { return x4_fadeOut; } float GetFadeOut() const { return x4_fadeOut; }
float GetVolume() const { return x8_volume; } float GetVolume() const { return x8_volume; }
const std::string& GetFileName() const { return xc_fileName; } const std::string& GetFileName() const { return xc_fileName; }
u32 GetHandle() const { return x1c_handle; } ResId GetResId() const { return x1c_res; }
static Audio None() { return Audio{0.f, 0.f, 0.f, "", 0}; } static Audio None() { return Audio{0.f, 0.f, 0.f, "", 0}; }
}; };
enum class EType enum class EType

View File

@ -703,14 +703,14 @@ void CStateManager::InitializeState(ResId mlvlId, TAreaId aid, ResId mreaId)
bool hadRandom = x900_activeRandom != nullptr; bool hadRandom = x900_activeRandom != nullptr;
SetActiveRandomToDefault(); SetActiveRandomToDefault();
if (xb3c_initPhase == InitPhase::LoadWorld) if (xb3c_initPhase == EInitPhase::LoadWorld)
{ {
CreateStandardGameObjects(); CreateStandardGameObjects();
x850_world.reset(new CWorld(*g_SimplePool, *g_ResFactory, mlvlId)); x850_world.reset(new CWorld(*g_SimplePool, *g_ResFactory, mlvlId));
xb3c_initPhase = InitPhase::LoadFirstArea; xb3c_initPhase = EInitPhase::LoadFirstArea;
} }
if (xb3c_initPhase == InitPhase::LoadFirstArea) if (xb3c_initPhase == EInitPhase::LoadFirstArea)
{ {
if (!x8f0_shadowTex.IsLoaded()) if (!x8f0_shadowTex.IsLoaded())
return; return;
@ -725,7 +725,7 @@ void CStateManager::InitializeState(ResId mlvlId, TAreaId aid, ResId mreaId)
area->StartStreamIn(*this); area->StartStreamIn(*this);
return; return;
} }
xb3c_initPhase = InitPhase::Done; xb3c_initPhase = EInitPhase::Done;
} }
SetCurrentAreaId(x8cc_nextAreaId); SetCurrentAreaId(x8cc_nextAreaId);

View File

@ -147,12 +147,12 @@ class CStateManager
std::set<std::string> xab4_uniqueInstanceNames; std::set<std::string> xab4_uniqueInstanceNames;
enum class InitPhase enum class EInitPhase
{ {
LoadWorld, LoadWorld,
LoadFirstArea, LoadFirstArea,
Done Done
} xb3c_initPhase = InitPhase::LoadWorld; } xb3c_initPhase = EInitPhase::LoadWorld;
CFinalInput xb54_finalInput; CFinalInput xb54_finalInput;
CCameraFilterPass xb84_camFilterPasses[9]; CCameraFilterPass xb84_camFilterPasses[9];

View File

@ -99,10 +99,10 @@ void CAreaOctTree::SwapTreeNode(u8* ptr, Node::ETreeType type)
} }
} }
CAreaOctTree::CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, u8* buf, std::unique_ptr<u8[]>&& treeBuf, CAreaOctTree::CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, const u8* buf, std::unique_ptr<u8[]>&& treeBuf,
u32 matCount, u32* materials, u8* vertMats, u8* edgeMats, u8* polyMats, u32 matCount, const u32* materials, const u8* vertMats, const u8* edgeMats, const u8* polyMats,
u32 edgeCount, CCollisionEdge* edges, u32 polyCount, u16* polyEdges, u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges,
u32 vertCount, zeus::CVector3f* verts) u32 vertCount, const zeus::CVector3f* verts)
: x0_aabb(aabb), x18_treeType(treeType), x1c_buf(buf), x20_treeBuf(std::move(treeBuf)), : x0_aabb(aabb), x18_treeType(treeType), x1c_buf(buf), x20_treeBuf(std::move(treeBuf)),
x24_matCount(matCount), x2c_vertMats(vertMats), x24_matCount(matCount), x2c_vertMats(vertMats),
x30_edgeMats(edgeMats), x34_polyMats(polyMats), x38_edgeCount(edgeCount), x30_edgeMats(edgeMats), x34_polyMats(polyMats), x38_edgeCount(edgeCount),
@ -140,7 +140,7 @@ CAreaOctTree::CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, u
} }
} }
std::unique_ptr<CAreaOctTree> CAreaOctTree::MakeFromMemory(void* buf, unsigned int size) std::unique_ptr<CAreaOctTree> CAreaOctTree::MakeFromMemory(const void* buf, unsigned int size)
{ {
athena::io::MemoryReader r(buf, size); athena::io::MemoryReader r(buf, size);
r.readUint32Big(); r.readUint32Big();
@ -149,48 +149,48 @@ std::unique_ptr<CAreaOctTree> CAreaOctTree::MakeFromMemory(void* buf, unsigned i
aabb.readBoundingBoxBig(r); aabb.readBoundingBoxBig(r);
Node::ETreeType nodeType = Node::ETreeType(r.readUint32Big()); Node::ETreeType nodeType = Node::ETreeType(r.readUint32Big());
u32 treeSize = r.readUint32Big(); u32 treeSize = r.readUint32Big();
u8* cur = reinterpret_cast<u8*>(buf) + r.position(); const u8* cur = reinterpret_cast<const u8*>(buf) + r.position();
std::unique_ptr<u8[]> treeBuf(new u8[treeSize]); std::unique_ptr<u8[]> treeBuf(new u8[treeSize]);
memmove(treeBuf.get(), cur, treeSize); memmove(treeBuf.get(), cur, treeSize);
cur += treeSize; cur += treeSize;
u32 matCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 matCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
u32* matBuf = reinterpret_cast<u32*>(cur); const u32* matBuf = reinterpret_cast<const u32*>(cur);
cur += 4 * matCount; cur += 4 * matCount;
u32 vertMatsCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 vertMatsCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
u8* vertMatsBuf = cur; const u8* vertMatsBuf = cur;
cur += vertMatsCount; cur += vertMatsCount;
u32 edgeMatsCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 edgeMatsCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
u8* edgeMatsBuf = cur; const u8* edgeMatsBuf = cur;
cur += edgeMatsCount; cur += edgeMatsCount;
u32 polyMatsCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 polyMatsCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
u8* polyMatsBuf = cur; const u8* polyMatsBuf = cur;
cur += polyMatsCount; cur += polyMatsCount;
u32 edgeCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 edgeCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
CCollisionEdge* edgeBuf = reinterpret_cast<CCollisionEdge*>(cur); const CCollisionEdge* edgeBuf = reinterpret_cast<const CCollisionEdge*>(cur);
cur += edgeCount * sizeof(edgeCount); cur += edgeCount * sizeof(edgeCount);
u32 polyCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 polyCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
u16* polyBuf = reinterpret_cast<u16*>(cur); const u16* polyBuf = reinterpret_cast<const u16*>(cur);
cur += polyCount * 2; cur += polyCount * 2;
u32 vertCount = hecl::SBig(*reinterpret_cast<u32*>(cur)); u32 vertCount = hecl::SBig(*reinterpret_cast<const u32*>(cur));
cur += 4; cur += 4;
zeus::CVector3f* vertBuf = reinterpret_cast<zeus::CVector3f*>(cur); const zeus::CVector3f* vertBuf = reinterpret_cast<const zeus::CVector3f*>(cur);
cur += polyCount * 2; cur += polyCount * 2;
return std::make_unique<CAreaOctTree>(aabb, nodeType, reinterpret_cast<u8*>(buf), std::move(treeBuf), return std::make_unique<CAreaOctTree>(aabb, nodeType, reinterpret_cast<const u8*>(buf), std::move(treeBuf),
matCount, matBuf, vertMatsBuf, edgeMatsBuf, polyMatsBuf, matCount, matBuf, vertMatsBuf, edgeMatsBuf, polyMatsBuf,
edgeCount, edgeBuf, polyCount, polyBuf, vertCount, vertBuf); edgeCount, edgeBuf, polyCount, polyBuf, vertCount, vertBuf);
} }

View File

@ -94,13 +94,13 @@ public:
zeus::CAABox x0_aabb; zeus::CAABox x0_aabb;
Node::ETreeType x18_treeType; Node::ETreeType x18_treeType;
u8* x1c_buf; const u8* x1c_buf;
std::unique_ptr<u8[]> x20_treeBuf; std::unique_ptr<u8[]> x20_treeBuf;
u32 x24_matCount; u32 x24_matCount;
std::vector<u32> x28_materials; std::vector<u32> x28_materials;
u8* x2c_vertMats; const u8* x2c_vertMats;
u8* x30_edgeMats; const u8* x30_edgeMats;
u8* x34_polyMats; const u8* x34_polyMats;
u32 x38_edgeCount; u32 x38_edgeCount;
std::vector<CCollisionEdge> x3c_edges; std::vector<CCollisionEdge> x3c_edges;
u32 x40_polyCount; u32 x40_polyCount;
@ -111,10 +111,10 @@ public:
void SwapTreeNode(u8* ptr, Node::ETreeType type); void SwapTreeNode(u8* ptr, Node::ETreeType type);
public: public:
CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, u8* buf, std::unique_ptr<u8[]>&& treeBuf, CAreaOctTree(const zeus::CAABox& aabb, Node::ETreeType treeType, const u8* buf, std::unique_ptr<u8[]>&& treeBuf,
u32 matCount, u32* materials, u8* vertMats, u8* edgeMats, u8* polyMats, u32 matCount, const u32* materials, const u8* vertMats, const u8* edgeMats, const u8* polyMats,
u32 edgeCount, CCollisionEdge* edges, u32 polyCount, u16* polyEdges, u32 edgeCount, const CCollisionEdge* edges, u32 polyCount, const u16* polyEdges,
u32 vertCount, zeus::CVector3f* verts); u32 vertCount, const zeus::CVector3f* verts);
Node GetRootNode() const { return Node(x20_treeBuf.get(), x0_aabb, *this, x18_treeType); } Node GetRootNode() const { return Node(x20_treeBuf.get(), x0_aabb, *this, x18_treeType); }
const u8* GetTreeMemory() const { return x20_treeBuf.get(); } const u8* GetTreeMemory() const { return x20_treeBuf.get(); }
@ -129,7 +129,7 @@ public:
const u16* GetTriangleVertexIndices(u16 idx) const; const u16* GetTriangleVertexIndices(u16 idx) const;
const u16* GetTriangleEdgeIndices(u16 idx) const; const u16* GetTriangleEdgeIndices(u16 idx) const;
static std::unique_ptr<CAreaOctTree> MakeFromMemory(void* buf, unsigned int size); static std::unique_ptr<CAreaOctTree> MakeFromMemory(const void* buf, unsigned int size);
}; };
} }

View File

@ -353,5 +353,12 @@ bool CInGameGuiManager::GetIsGameDraw() const
return x3c_pauseScreen->GetX50_25(); return x3c_pauseScreen->GetX50_25();
} }
std::string CInGameGuiManager::GetIdentifierForMidiEvent(ResId world, ResId area,
const std::string& midiObj)
{
return hecl::Format("World %8.8x Area %8.8x MidiObject: %s",
u32(world), u32(area), midiObj.c_str());
}
} }
} }

View File

@ -135,6 +135,7 @@ public:
bool IsInGame() const { return x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame; } bool IsInGame() const { return x1c0_nextState >= EInGameGuiState::Zero && x1c0_nextState <= EInGameGuiState::InGame; }
bool IsInSaveUI() const { return x1f8_27_inSaveUI; } bool IsInSaveUI() const { return x1f8_27_inSaveUI; }
bool GetIsGameDraw() const; bool GetIsGameDraw() const;
static std::string GetIdentifierForMidiEvent(ResId world, ResId area, const std::string& midiObj);
}; };
} }

View File

@ -379,7 +379,7 @@ CIOWin::EMessageReturn CMFGameLoader::OnMessage(const CArchitectureMessage& msg,
wldState.GetLayerState()); wldState.GetLayerState());
} }
if (x14_stateMgr->xb3c_initPhase != CStateManager::InitPhase::Done) if (x14_stateMgr->xb3c_initPhase != CStateManager::EInitPhase::Done)
{ {
CWorldState& wldState = g_GameState->CurrentWorldState(); CWorldState& wldState = g_GameState->CurrentWorldState();
x14_stateMgr->InitializeState(wldState.GetWorldAssetId(), x14_stateMgr->InitializeState(wldState.GetWorldAssetId(),

View File

@ -53,6 +53,7 @@ CENTITY_TYPES = (
('CScriptPointOfInterest', 'World/CScriptPointOfInterest.hpp'), ('CScriptPointOfInterest', 'World/CScriptPointOfInterest.hpp'),
('CScriptRoomAcoustics', 'World/CScriptRoomAcoustics.hpp'), ('CScriptRoomAcoustics', 'World/CScriptRoomAcoustics.hpp'),
('CScriptSound', 'World/CScriptSound.hpp'), ('CScriptSound', 'World/CScriptSound.hpp'),
('CScriptMidi', 'World/CScriptMidi.hpp'),
('CScriptSpawnPoint', 'World/CScriptSpawnPoint.hpp'), ('CScriptSpawnPoint', 'World/CScriptSpawnPoint.hpp'),
('CScriptSpecialFunction', 'World/CScriptSpecialFunction.hpp'), ('CScriptSpecialFunction', 'World/CScriptSpecialFunction.hpp'),
('CScriptSpiderBallAttractionSurface', 'World/CScriptSpiderBallAttractionSurface.hpp'), ('CScriptSpiderBallAttractionSurface', 'World/CScriptSpiderBallAttractionSurface.hpp'),

View File

@ -9,27 +9,29 @@
namespace urde namespace urde
{ {
CAreaRenderOctTree::CAreaRenderOctTree(std::unique_ptr<u8[]>&& buf) static logvisor::Module Log("CGameArea");
: x0_buf(std::move(buf))
CAreaRenderOctTree::CAreaRenderOctTree(const u8* buf)
: x0_buf(buf)
{ {
athena::io::MemoryReader r(x0_buf.get() + 8, INT32_MAX); athena::io::MemoryReader r(x0_buf + 8, INT32_MAX);
x8_bitmapCount = r.readUint32Big(); x8_bitmapCount = r.readUint32Big();
xc_meshCount = r.readUint32Big(); xc_meshCount = r.readUint32Big();
x10_nodeCount = r.readUint32Big(); x10_nodeCount = r.readUint32Big();
x14_bitmapWordCount = (xc_meshCount + 31) / 32; x14_bitmapWordCount = (xc_meshCount + 31) / 32;
x18_aabb.readBoundingBoxBig(r); x18_aabb.readBoundingBoxBig(r);
x30_bitmaps = reinterpret_cast<u32*>(x0_buf.get() + 64); x30_bitmaps = reinterpret_cast<const u32*>(x0_buf + 64);
u32 wc = x14_bitmapWordCount * x8_bitmapCount; u32 wc = x14_bitmapWordCount * x8_bitmapCount;
for (u32 i=0 ; i<wc ; ++i) for (u32 i=0 ; i<wc ; ++i)
x30_bitmaps[i] = hecl::SBig(x30_bitmaps[i]); const_cast<u32*>(x30_bitmaps)[i] = hecl::SBig(x30_bitmaps[i]);
x34_indirectionTable = x30_bitmaps + wc; x34_indirectionTable = x30_bitmaps + wc;
x38_entries = reinterpret_cast<u8*>(x34_indirectionTable) + x10_nodeCount; x38_entries = reinterpret_cast<const u8*>(x34_indirectionTable + x10_nodeCount);
for (u32 i=0 ; i<x10_nodeCount ; ++i) for (u32 i=0 ; i<x10_nodeCount ; ++i)
{ {
x34_indirectionTable[i] = hecl::SBig(x34_indirectionTable[i]); const_cast<u32*>(x34_indirectionTable)[i] = hecl::SBig(x34_indirectionTable[i]);
Node* n = reinterpret_cast<Node*>(x38_entries + x34_indirectionTable[i]); Node* n = reinterpret_cast<Node*>(const_cast<u8*>(x38_entries) + x34_indirectionTable[i]);
n->x0_bitmapIdx = hecl::SBig(n->x0_bitmapIdx); n->x0_bitmapIdx = hecl::SBig(n->x0_bitmapIdx);
n->x2_flags = hecl::SBig(n->x2_flags); n->x2_flags = hecl::SBig(n->x2_flags);
if (n->x2_flags) if (n->x2_flags)
@ -596,42 +598,42 @@ bool CGameArea::StartStreamingMainArea()
switch (xf4_phase) switch (xf4_phase)
{ {
case Phase::LoadHeader: case EPhase::LoadHeader:
{ {
x110_mreaSecBufs.reserve(3); x110_mreaSecBufs.reserve(3);
AllocNewAreaData(0, 96); AllocNewAreaData(0, 96);
x12c_postConstructed.reset(new CPostConstructed()); x12c_postConstructed.reset(new CPostConstructed());
xf4_phase = Phase::LoadSecSizes; xf4_phase = EPhase::LoadSecSizes;
break; break;
} }
case Phase::LoadSecSizes: case EPhase::LoadSecSizes:
{ {
CullDeadAreaRequests(); CullDeadAreaRequests();
if (xf8_loadTransactions.size()) if (xf8_loadTransactions.size())
break; break;
MREAHeader header = VerifyHeader(); MREAHeader header = VerifyHeader();
AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(header.secCount * 4)); AllocNewAreaData(x110_mreaSecBufs[0].second, ROUND_UP_32(header.secCount * 4));
xf4_phase = Phase::ReserveSections; xf4_phase = EPhase::ReserveSections;
break; break;
} }
case Phase::ReserveSections: case EPhase::ReserveSections:
{ {
CullDeadAreaRequests(); CullDeadAreaRequests();
if (xf8_loadTransactions.size()) if (xf8_loadTransactions.size())
break; break;
x110_mreaSecBufs.reserve(GetNumPartSizes() + 2); //x110_mreaSecBufs.reserve(GetNumPartSizes() + 2);
x124_secCount = 0; x124_secCount = 0;
x128_mreaDataOffset = x110_mreaSecBufs[0].second + x110_mreaSecBufs[1].second; x128_mreaDataOffset = x110_mreaSecBufs[0].second + x110_mreaSecBufs[1].second;
xf4_phase = Phase::LoadDataSections; xf4_phase = EPhase::LoadDataSections;
break; break;
} }
case Phase::LoadDataSections: case EPhase::LoadDataSections:
{ {
CullDeadAreaRequests(); CullDeadAreaRequests();
u32 totalSz = 0; u32 totalSz = 0;
u32 secCount = GetNumPartSizes(); u32 secCount = GetNumPartSizes();
for (u32 i=2 ; i<secCount ; ++i) for (u32 i=0 ; i<secCount ; ++i)
totalSz += hecl::SBig(reinterpret_cast<u32*>(x110_mreaSecBufs[1].first.get())[i]); totalSz += hecl::SBig(reinterpret_cast<u32*>(x110_mreaSecBufs[1].first.get())[i]);
AllocNewAreaData(x128_mreaDataOffset, totalSz); AllocNewAreaData(x128_mreaDataOffset, totalSz);
@ -641,17 +643,17 @@ bool CGameArea::StartStreamingMainArea()
m_resolvedBufs.emplace_back(x110_mreaSecBufs[1].first.get(), x110_mreaSecBufs[1].second); m_resolvedBufs.emplace_back(x110_mreaSecBufs[1].first.get(), x110_mreaSecBufs[1].second);
u32 curOff = 0; u32 curOff = 0;
for (u32 i=2 ; i<secCount ; ++i) for (u32 i=0 ; i<secCount ; ++i)
{ {
u32 size = hecl::SBig(reinterpret_cast<u32*>(x110_mreaSecBufs[1].first.get())[i]); u32 size = hecl::SBig(reinterpret_cast<u32*>(x110_mreaSecBufs[1].first.get())[i]);
m_resolvedBufs.emplace_back(x110_mreaSecBufs[2].first.get() + curOff, size); m_resolvedBufs.emplace_back(x110_mreaSecBufs[2].first.get() + curOff, size);
curOff += size; curOff += size;
} }
xf4_phase = Phase::WaitForFinish; xf4_phase = EPhase::WaitForFinish;
break; break;
} }
case Phase::WaitForFinish: case EPhase::WaitForFinish:
{ {
CullDeadAreaRequests(); CullDeadAreaRequests();
if (xf8_loadTransactions.size()) if (xf8_loadTransactions.size())
@ -684,7 +686,7 @@ void CGameArea::AllocNewAreaData(int offset, int size)
xf8_loadTransactions.push_back( xf8_loadTransactions.push_back(
static_cast<ProjectResourceFactoryBase*>(g_ResFactory)-> static_cast<ProjectResourceFactoryBase*>(g_ResFactory)->
LoadResourcePartAsync(SObjectTag{FOURCC('MREA'), x84_mrea}, size, offset, LoadResourcePartAsync(SObjectTag{FOURCC('MREA'), x84_mrea}, size, offset,
x110_mreaSecBufs.back().first)); x110_mreaSecBufs.back().first.get()));
} }
bool CGameArea::Invalidate(CStateManager& mgr) bool CGameArea::Invalidate(CStateManager& mgr)
@ -707,6 +709,32 @@ void CGameArea::CullDeadAreaRequests()
void CGameArea::StartStreamIn(CStateManager& mgr) void CGameArea::StartStreamIn(CStateManager& mgr)
{ {
if (xf0_24_postConstructed || xf0_27_paused)
return;
VerifyTokenList(mgr);
if (!xf0_26_tokensReady)
{
u32 notLoaded = 0;
for (CToken& tok : xdc_tokens)
{
tok.Lock();
if (!tok.IsLoaded())
++notLoaded;
}
if (notLoaded)
return;
xf0_26_tokensReady = true;
}
StartStreamingMainArea();
if (xf4_phase != EPhase::WaitForFinish)
return;
CullDeadAreaRequests();
if (xf8_loadTransactions.size())
return;
Validate(mgr);
} }
void CGameArea::Validate(CStateManager& mgr) void CGameArea::Validate(CStateManager& mgr)
@ -774,7 +802,7 @@ void CGameArea::LoadScriptObjects(CStateManager& mgr)
mgr.InitScriptObjects(objIds); mgr.InitScriptObjects(objIds);
} }
std::pair<u8*, u32> CGameArea::GetLayerScriptBuffer(int layer) std::pair<const u8*, u32> CGameArea::GetLayerScriptBuffer(int layer)
{ {
if (!xf0_24_postConstructed) if (!xf0_24_postConstructed)
return {}; return {};
@ -785,32 +813,35 @@ void CGameArea::PostConstructArea()
{ {
MREAHeader header = VerifyHeader(); MREAHeader header = VerifyHeader();
auto secIt = x110_mreaSecBufs.begin() + 2; auto secIt = m_resolvedBufs.begin() + 2;
/* Materials */
++secIt;
u32 sec = 3;
/* Models */ /* Models */
if (header.modelCount) for (u32 i=0 ; i<header.modelCount ; ++i)
{ {
for (u32 i=0 ; i<header.modelCount ; ++i) u32 surfCount = hecl::SBig(*reinterpret_cast<const u32*>((secIt+4)->first));
{ secIt += 5 + surfCount;
u32 surfCount = hecl::SBig(*reinterpret_cast<u32*>((secIt+6)->first.get())); sec += 5 + surfCount;
secIt += 7 + surfCount;
}
} }
/* Render octree */ /* Render octree */
if (header.version == 15 && header.arotSecIdx != -1) if (header.version == 15 && header.arotSecIdx != -1)
{ {
x12c_postConstructed->xc_octTree.emplace(std::move(secIt->first)); x12c_postConstructed->xc_octTree.emplace(secIt->first);
++secIt; ++secIt;
} }
/* Scriptable layer section */ /* Scriptable layer section */
x12c_postConstructed->x10c8_sclyBuf = std::move(secIt->first); x12c_postConstructed->x10c8_sclyBuf = secIt->first;
x12c_postConstructed->x10d0_sclySize = secIt->second; x12c_postConstructed->x10d0_sclySize = secIt->second;
++secIt; ++secIt;
/* Collision section */ /* Collision section */
std::unique_ptr<CAreaOctTree> collision = CAreaOctTree::MakeFromMemory(secIt->first.get(), secIt->second); std::unique_ptr<CAreaOctTree> collision = CAreaOctTree::MakeFromMemory(secIt->first, secIt->second);
if (collision) if (collision)
{ {
x12c_postConstructed->x0_collision = std::move(collision); x12c_postConstructed->x0_collision = std::move(collision);
@ -824,7 +855,7 @@ void CGameArea::PostConstructArea()
/* Lights section */ /* Lights section */
if (header.version > 6) if (header.version > 6)
{ {
athena::io::MemoryReader r(secIt->first.get(), secIt->second); athena::io::MemoryReader r(secIt->first, secIt->second);
u32 magic = r.readUint32Big(); u32 magic = r.readUint32Big();
if (magic == 0xBABEDEAD) if (magic == 0xBABEDEAD)
{ {
@ -855,7 +886,7 @@ void CGameArea::PostConstructArea()
/* PVS section */ /* PVS section */
if (header.version > 7) if (header.version > 7)
{ {
athena::io::MemoryReader r(secIt->first.get(), secIt->second); athena::io::MemoryReader r(secIt->first, secIt->second);
u32 magic = r.readUint32Big(); u32 magic = r.readUint32Big();
if (magic == 'VISI') if (magic == 'VISI')
{ {
@ -864,7 +895,7 @@ void CGameArea::PostConstructArea()
{ {
x12c_postConstructed->x1108_29_ = r.readBool(); x12c_postConstructed->x1108_29_ = r.readBool();
x12c_postConstructed->x1108_30_ = r.readBool(); x12c_postConstructed->x1108_30_ = r.readBool();
x12c_postConstructed->xa0_pvs = std::make_unique<CPVSAreaSet>(secIt->first.get() + r.position(), x12c_postConstructed->xa0_pvs = std::make_unique<CPVSAreaSet>(secIt->first + r.position(),
secIt->second - r.position()); secIt->second - r.position());
} }
} }
@ -875,7 +906,7 @@ void CGameArea::PostConstructArea()
/* Pathfinding section */ /* Pathfinding section */
if (header.version > 9) if (header.version > 9)
{ {
athena::io::MemoryReader r(secIt->first.get(), secIt->second); athena::io::MemoryReader r(secIt->first, secIt->second);
ResId pathId = r.readUint32Big(); ResId pathId = r.readUint32Big();
x12c_postConstructed->x10ac_path = g_SimplePool->GetObj(SObjectTag{FOURCC('PATH'), pathId}); x12c_postConstructed->x10ac_path = g_SimplePool->GetObj(SObjectTag{FOURCC('PATH'), pathId});
++secIt; ++secIt;
@ -889,7 +920,7 @@ void CGameArea::PostConstructArea()
/* Resolve layer pointers */ /* Resolve layer pointers */
if (x12c_postConstructed->x10c8_sclyBuf) if (x12c_postConstructed->x10c8_sclyBuf)
{ {
athena::io::MemoryReader r(x12c_postConstructed->x10c8_sclyBuf.get(), x12c_postConstructed->x10d0_sclySize); athena::io::MemoryReader r(x12c_postConstructed->x10c8_sclyBuf, x12c_postConstructed->x10d0_sclySize);
u32 magic = r.readUint32Big(); u32 magic = r.readUint32Big();
if (magic == 'SCLY') if (magic == 'SCLY')
{ {
@ -898,7 +929,7 @@ void CGameArea::PostConstructArea()
x12c_postConstructed->x110c_layerPtrs.resize(layerCount); x12c_postConstructed->x110c_layerPtrs.resize(layerCount);
for (u32 l=0 ; l<layerCount ; ++l) for (u32 l=0 ; l<layerCount ; ++l)
x12c_postConstructed->x110c_layerPtrs[l].second = r.readUint32Big(); x12c_postConstructed->x110c_layerPtrs[l].second = r.readUint32Big();
u8* ptr = x12c_postConstructed->x10c8_sclyBuf.get() + r.position(); const u8* ptr = x12c_postConstructed->x10c8_sclyBuf + r.position();
for (u32 l=0 ; l<layerCount ; ++l) for (u32 l=0 ; l<layerCount ; ++l)
{ {
x12c_postConstructed->x110c_layerPtrs[l].first = ptr; x12c_postConstructed->x110c_layerPtrs[l].first = ptr;
@ -967,6 +998,9 @@ CGameArea::MREAHeader CGameArea::VerifyHeader() const
MREAHeader header; MREAHeader header;
athena::io::MemoryReader r(x110_mreaSecBufs[0].first.get() + 4, INT32_MAX); athena::io::MemoryReader r(x110_mreaSecBufs[0].first.get() + 4, INT32_MAX);
u32 version = r.readUint32Big(); u32 version = r.readUint32Big();
if (!(version & 0x10000))
Log.report(logvisor::Fatal, "Attempted to load non-URDE MREA");
version &= ~0x10000;
header.version = (version >= 12 && version <= 15) ? version : 0; header.version = (version >= 12 && version <= 15) ? version : 0;
if (!header.version) if (!header.version)
return {}; return {};

View File

@ -61,17 +61,17 @@ struct CAreaRenderOctTree
const zeus::CAABox& testAABB) const; const zeus::CAABox& testAABB) const;
}; };
std::unique_ptr<u8[]> x0_buf; const u8* x0_buf;
u32 x8_bitmapCount; u32 x8_bitmapCount;
u32 xc_meshCount; u32 xc_meshCount;
u32 x10_nodeCount; u32 x10_nodeCount;
u32 x14_bitmapWordCount; u32 x14_bitmapWordCount;
zeus::CAABox x18_aabb; zeus::CAABox x18_aabb;
u32* x30_bitmaps; const u32* x30_bitmaps;
u32* x34_indirectionTable; const u32* x34_indirectionTable;
u8* x38_entries; const u8* x38_entries;
CAreaRenderOctTree(std::unique_ptr<u8[]>&& buf); CAreaRenderOctTree(const u8* buf);
void FindOverlappingModels(std::vector<u32>& out, const zeus::CAABox& testAABB) const; void FindOverlappingModels(std::vector<u32>& out, const zeus::CAABox& testAABB) const;
}; };
@ -110,14 +110,14 @@ class CGameArea : public IGameArea
u8 _dummy = 0; u8 _dummy = 0;
}; };
enum class Phase enum class EPhase
{ {
LoadHeader, LoadHeader,
LoadSecSizes, LoadSecSizes,
ReserveSections, ReserveSections,
LoadDataSections, LoadDataSections,
WaitForFinish WaitForFinish
} xf4_phase = Phase::LoadHeader; } xf4_phase = EPhase::LoadHeader;
std::list<std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>> xf8_loadTransactions; std::list<std::shared_ptr<ProjectResourceFactoryBase::AsyncTask>> xf8_loadTransactions;
@ -187,7 +187,7 @@ public:
u32 x10bc_ = 0; u32 x10bc_ = 0;
std::unique_ptr<CAreaObjectList> x10c0_areaObjs; std::unique_ptr<CAreaObjectList> x10c0_areaObjs;
std::unique_ptr<CAreaFog> x10c4_areaFog; std::unique_ptr<CAreaFog> x10c4_areaFog;
std::unique_ptr<u8[]> x10c8_sclyBuf; const u8* x10c8_sclyBuf = nullptr;
u32 x10d0_sclySize = 0; u32 x10d0_sclySize = 0;
u32 x10d4_ = 0; u32 x10d4_ = 0;
const CScriptAreaAttributes* x10d8_areaAttributes = nullptr; const CScriptAreaAttributes* x10d8_areaAttributes = nullptr;
@ -213,7 +213,7 @@ public:
}; };
u8 _dummy = 0; u8 _dummy = 0;
}; };
std::vector<std::pair<u8*, u32>> x110c_layerPtrs; std::vector<std::pair<const u8*, u32>> x110c_layerPtrs;
float x111c_thermalCurrent = 0.f; float x111c_thermalCurrent = 0.f;
float x1120_thermalSpeed = 0.f; float x1120_thermalSpeed = 0.f;
float x1124_thermalTarget = 0.f; float x1124_thermalTarget = 0.f;
@ -226,7 +226,7 @@ public:
}; };
private: private:
std::vector<std::pair<std::unique_ptr<u8[]>, int>> x110_mreaSecBufs; std::vector<std::pair<std::unique_ptr<u8[]>, int>> x110_mreaSecBufs;
std::vector<std::pair<u8*, int>> m_resolvedBufs; std::vector<std::pair<const u8*, int>> m_resolvedBufs;
u32 x124_secCount = 0; u32 x124_secCount = 0;
u32 x128_mreaDataOffset = 0; u32 x128_mreaDataOffset = 0;
std::unique_ptr<CPostConstructed> x12c_postConstructed; std::unique_ptr<CPostConstructed> x12c_postConstructed;
@ -303,7 +303,7 @@ public:
void StartStreamIn(CStateManager& mgr); void StartStreamIn(CStateManager& mgr);
void Validate(CStateManager& mgr); void Validate(CStateManager& mgr);
void LoadScriptObjects(CStateManager& mgr); void LoadScriptObjects(CStateManager& mgr);
std::pair<u8*, u32> GetLayerScriptBuffer(int layer); std::pair<const u8*, u32> GetLayerScriptBuffer(int layer);
void PostConstructArea(); void PostConstructArea();
void FillInStaticGeometry(); void FillInStaticGeometry();
void VerifyTokenList(CStateManager& stateMgr); void VerifyTokenList(CStateManager& stateMgr);

View File

@ -74,6 +74,7 @@ set(WORLD_SOURCES
CScriptRoomAcoustics.hpp CScriptRoomAcoustics.cpp CScriptRoomAcoustics.hpp CScriptRoomAcoustics.cpp
CScriptColorModulate.hpp CScriptColorModulate.cpp CScriptColorModulate.hpp CScriptColorModulate.cpp
CScriptStreamedMusic.hpp CScriptStreamedMusic.cpp CScriptStreamedMusic.hpp CScriptStreamedMusic.cpp
CScriptMidi.hpp CScriptMidi.cpp
CRepulsor.hpp CRepulsor.cpp CRepulsor.hpp CRepulsor.cpp
CScriptGunTurret.hpp CScriptGunTurret.cpp CScriptGunTurret.hpp CScriptGunTurret.cpp
CScriptCameraPitchVolume.hpp CScriptCameraPitchVolume.cpp CScriptCameraPitchVolume.hpp CScriptCameraPitchVolume.cpp

View File

@ -0,0 +1,89 @@
#include "CScriptMidi.hpp"
#include "TCastTo.hpp"
#include "CSimplePool.hpp"
#include "GameGlobalObjects.hpp"
#include "CStateManager.hpp"
#include "MP1/CInGameGuiManager.hpp"
#include "CInGameTweakManagerBase.hpp"
namespace urde
{
CScriptMidi::CScriptMidi(TUniqueId id, const CEntityInfo& info, const std::string& name,
bool active, ResId csng, float fadeIn, float fadeOut, s32 volume)
: CEntity(id, info, active, name), x40_fadeInTime(fadeIn), x44_fadeOutTime(fadeOut),
x48_volume(volume)
{
x34_song = g_SimplePool->GetObj(SObjectTag{FOURCC('CSNG'), csng});
}
void CScriptMidi::StopInternal(float fadeTime)
{
if (x3c_handle)
{
CMidiManager::Stop(x3c_handle, fadeTime);
x3c_handle.reset();
}
}
void CScriptMidi::Stop(CStateManager& mgr, float fadeTime)
{
const CWorld* wld = mgr.GetWorld();
const CGameArea* area = wld->GetAreaAlways(x4_areaId);
std::string twkName = MP1::CInGameGuiManager::GetIdentifierForMidiEvent(wld->IGetWorldAssetId(),
area->GetAreaAssetId(),
x10_name);
if (g_TweakManager->HasTweakValue(twkName))
{
const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio();
fadeTime = audio.GetFadeOut();
}
StopInternal(fadeTime);
}
void CScriptMidi::Play(CStateManager& mgr, float fadeTime)
{
u32 volume = x48_volume;
const CWorld* wld = mgr.GetWorld();
const CGameArea* area = wld->GetAreaAlways(x4_areaId);
std::string twkName = MP1::CInGameGuiManager::GetIdentifierForMidiEvent(wld->IGetWorldAssetId(),
area->GetAreaAssetId(),
x10_name);
if (g_TweakManager->HasTweakValue(twkName))
{
const CTweakValue::Audio& audio = g_TweakManager->GetTweakValue(twkName)->GetAudio();
x34_song = g_SimplePool->GetObj(SObjectTag{FOURCC('CSNG'), audio.GetResId()});
fadeTime = audio.GetFadeIn();
volume = audio.GetVolume() * 127.f;
}
x3c_handle = CMidiManager::Play(*x34_song, fadeTime, false, volume / 127.f);
}
void CScriptMidi::Accept(IVisitor& visitor)
{
visitor.Visit(this);
}
void CScriptMidi::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr)
{
CEntity::AcceptScriptMsg(msg, objId, stateMgr);
switch (msg)
{
case EScriptObjectMessage::Play:
if (GetActive())
Play(stateMgr, x40_fadeInTime);
break;
case EScriptObjectMessage::Stop:
if (GetActive())
Stop(stateMgr, x44_fadeOutTime);
break;
case EScriptObjectMessage::Deactivate:
StopInternal(0.f);
break;
default: break;
}
}
}

View File

@ -0,0 +1,33 @@
#ifndef __URDE_CSCRIPTMIDI_HPP__
#define __URDE_CSCRIPTMIDI_HPP__
#include "CEntity.hpp"
#include "CToken.hpp"
#include "Audio/CMidiManager.hpp"
namespace urde
{
class CScriptMidi : public CEntity
{
TToken<CMidiManager::CMidiData> x34_song;
CMidiHandle x3c_handle;
float x40_fadeInTime;
float x44_fadeOutTime;
u16 x48_volume;
void StopInternal(float fadeTime);
public:
CScriptMidi(TUniqueId id, const CEntityInfo& info, const std::string& name,
bool active, ResId csng, float, float, s32);
void Stop(CStateManager& mgr, float fadeTime);
void Play(CStateManager& mgr, float fadeTime);
void Accept(IVisitor& visitor);
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId objId, CStateManager& stateMgr);
};
}
#endif // __URDE_CSCRIPTSTREAMEDMUSIC_HPP__

View File

@ -64,6 +64,7 @@
#include "MP1/World/CActorContraption.hpp" #include "MP1/World/CActorContraption.hpp"
#include "CScriptShadowProjector.hpp" #include "CScriptShadowProjector.hpp"
#include "CScriptStreamedMusic.hpp" #include "CScriptStreamedMusic.hpp"
#include "CScriptMidi.hpp"
#include "CScriptRoomAcoustics.hpp" #include "CScriptRoomAcoustics.hpp"
#include "CPatternedInfo.hpp" #include "CPatternedInfo.hpp"
#include "CSimplePool.hpp" #include "CSimplePool.hpp"
@ -1916,7 +1917,16 @@ CEntity* ScriptLoader::LoadThardusRockProjectile(CStateManager& mgr, CInputStrea
CEntity* ScriptLoader::LoadMidi(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) CEntity* ScriptLoader::LoadMidi(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
{ {
return nullptr; if (!EnsurePropertyCount(propCount, 6, "Midi"))
return nullptr;
std::string name = mgr.HashInstanceName(in);
bool active = in.readBool();
u32 csng = in.readUint32Big();
float fadeIn = in.readFloatBig();
float fadeOut = in.readFloatBig();
u32 vol = in.readUint32Big();
return new CScriptMidi(mgr.AllocateUniqueId(), info, name, active, csng, fadeIn, fadeOut, vol);
} }
CEntity* ScriptLoader::LoadStreamedAudio(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info) CEntity* ScriptLoader::LoadStreamedAudio(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)

2
amuse

@ -1 +1 @@
Subproject commit 5c8fa2e8ab76cb95dad7a6add9efd8ecb9bfbbfe Subproject commit a23af16349383be647494e9ae245568cc5194eae

View File

@ -4,7 +4,6 @@
#define VISI_MIN_LENGTH 8.0 #define VISI_MIN_LENGTH 8.0
static logvisor::Module Log("VISIBuilder"); static logvisor::Module Log("VISIBuilder");
const VISIBuilder::Leaf VISIBuilder::NullLeaf = {};
VISIBuilder::PVSRenderCache::PVSRenderCache(VISIRenderer& renderer) VISIBuilder::PVSRenderCache::PVSRenderCache(VISIRenderer& renderer)
: m_renderer(renderer) : m_renderer(renderer)
@ -245,7 +244,10 @@ void VISIBuilder::Node::calculateSizesAndOffs(size_t& cur, size_t leafSz)
} }
else else
{ {
cur += leafSz; if (!leaf)
flags &= ~0x8;
else
cur += leafSz;
} }
} }
@ -294,7 +296,7 @@ void VISIBuilder::Node::writeNodes(athena::io::MemoryWriter& w, size_t leafBytes
childNodes[nodeSel].writeNodes(w, leafBytes); childNodes[nodeSel].writeNodes(w, leafBytes);
} }
} }
else else if (leaf)
{ {
leaf.write(w, leafBytes); leaf.write(w, leafBytes);
} }

View File

@ -77,7 +77,6 @@ struct VISIBuilder
} }
} }
}; };
static const Leaf NullLeaf;
class PVSRenderCache class PVSRenderCache
{ {
@ -113,7 +112,7 @@ struct VISIBuilder
bool operator==(const Node& other) const bool operator==(const Node& other) const
{ {
if (!leaf || !other.leaf) if ((flags & 0x7) || (other.flags & 0x7))
return false; return false;
return leaf == other.leaf; return leaf == other.leaf;
} }

View File

@ -296,6 +296,10 @@ void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bo
zeus::CFrustum frustum; zeus::CFrustum frustum;
frustum.updatePlanes(mv, g_Proj); frustum.updatePlanes(mv, g_Proj);
// Fill depth buffer with backfaces initially
glCullFace(GL_FRONT);
glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
for (const Model& model : m_models) for (const Model& model : m_models)
{ {
if (!frustum.aabbFrustumTest(model.aabb)) if (!frustum.aabbFrustumTest(model.aabb))
@ -311,6 +315,24 @@ void VISIRenderer::RenderPVSOpaque(RGBA8* bufOut, const zeus::CVector3f& pos, bo
needTransparent = true; needTransparent = true;
} }
} }
// Draw frontfaces
glCullFace(GL_BACK);
glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
for (const Model& model : m_models)
{
if (!frustum.aabbFrustumTest(model.aabb))
continue;
glBindVertexArray(model.vao);
for (const Model::Surface& surf : model.surfaces)
{
// Non-transparents first
if (!surf.transparent)
glDrawElements(model.topology, surf.count, GL_UNSIGNED_INT,
reinterpret_cast<void*>(uintptr_t(surf.first * 4)));
}
}
} }
//m_swapFunc(); //m_swapFunc();