diff --git a/lib/g3d/include/nn/g3d/g3d_ResFile.h b/lib/g3d/include/nn/g3d/g3d_ResFile.h index 19ab7ed3..98c1f05e 100644 --- a/lib/g3d/include/nn/g3d/g3d_ResFile.h +++ b/lib/g3d/include/nn/g3d/g3d_ResFile.h @@ -6,9 +6,16 @@ #include -#include #include +#include #include +#include + +#include +#include +#include + +#include namespace nn { @@ -18,53 +25,66 @@ class TDevice; } namespace g3d { + class ResModel; class ResMaterialAnim; class ResShapeAnim; class ResSceneAnim; -typedef void* TextureRef; +class ResSkeletalAnim; +class ResBoneVisibilityAnim; + +struct ResFileData { + util::BinaryFileHeader fileHeader; + util::BinTPtr pFileName; + util::BinTPtr pModels; + util::BinTPtr pModelDict; + util::BinTPtr pSkeletalAnims; + util::BinTPtr pSkeletalAnimDict; + util::BinTPtr pMaterialAnims; + util::BinTPtr pMaterialAnimsDict; + util::BinTPtr pBoneVisibilityAnims; + util::BinTPtr pBoneVisiDict; + util::BinTPtr pShapeAnims; + util::BinTPtr pShapeAnimDict; + util::BinTPtr pSceneAnims; + util::BinTPtr pSceneAnimDict; + util::BinTPtr pMemoryPool; + util::BinTPtr pMemoryPoolInfo; + uint64_t embeddedFilesOffset; + util::BinTPtr pEmbeddedFilesDict; + uint64_t padding; + uint64_t strTableOffset; + uint32_t strTableSize; + uint16_t modelCount; + uint16_t skeletalAnimCount; + uint16_t materialAnimCount; + uint16_t boneAnimCount; + uint16_t shapeAnimCount; + uint16_t sceneAnimCount; + uint16_t externalFileCount; +}; -class ResFile : public nn::util::BinaryFileHeader { +class ResFile : public nn::util::AccessorBase { public: + static const int64_t Signature = 0x2020202053455246; // "FRES " + static bool IsValid(void const* modelSrc); + void Relocate(); void Unrelocate(); + static nn::g3d::ResFile* ResCast(void*); - int32_t BindTexture(nn::g3d::TextureRef (*ref)(char const*, void*), void*); + + int32_t BindTexture(TextureBindCallback callback, void* callbackArg); void ReleaseTexture(); + void Setup(gfx::Device*); void Setup(gfx::Device*, gfx::MemoryPool*, int64_t, uint64_t); + void Cleanup(gfx::Device*); void Reset(); - - uint64_t mFileNameLength; // _20 - nn::g3d::ResModel* mModels; // _28 - uint64_t mModelDictOffset; // _30 - uint64_t mSkeleAnimOffset; // _38 - uint64_t mSkeleAnimDictOffset; // _40 - nn::g3d::ResMaterialAnim* mMatAnims; // _48 - uint64_t mMatAnimsDictOffset; // _50 - uint64_t mBoneVisiOffset; // _58 - uint64_t mBoneVisiDictOffset; // _60 - nn::g3d::ResShapeAnim* mShapeAnims; // _68 - uint64_t mShapeAnimDictOffset; // _70 - nn::g3d::ResSceneAnim* mSceneAnims; // _78 - uint64_t mSceneAnimDictOffset; // _80 - uint64_t mMemoryPool; // _88 - uint64_t mBufferSection; // _90 - uint64_t mEmbeddedFilesOffset; // _98 - uint64_t mEmbeddedFilesDictOffset; // _A0 - uint64_t mPadding; // _A8 - uint64_t mStrTableOffset; // _B0 - uint32_t mStrTableSize; // _B8 - uint16_t mModelCount; // _BC - uint16_t mSkeleAnimCount; // _BE - uint16_t mMatAnimCount; // _C0 - uint16_t mBoneAnimCount; // _C2 - uint16_t mShapeAnimCount; // _C4 - uint16_t mSceneAnimCount; // _C6 - uint16_t mExternalFileCount; // _C8 - uint8_t mPad[0x6]; // _CA }; +static_assert(sizeof(ResFile) == 0xd0); + } // namespace g3d } // namespace nn diff --git a/lib/g3d/include/nn/g3d/g3d_ResMaterialAnim.h b/lib/g3d/include/nn/g3d/g3d_ResMaterialAnim.h index 93d3fb53..5af854a1 100644 --- a/lib/g3d/include/nn/g3d/g3d_ResMaterialAnim.h +++ b/lib/g3d/include/nn/g3d/g3d_ResMaterialAnim.h @@ -6,15 +6,17 @@ #include -namespace nn::g3d { +#include -typedef void* TextureRef; +namespace nn::g3d { class ResMaterialAnim { public: void ReleaseTexture(); - int32_t BindTexture(nn::g3d::TextureRef (*)(char const*, void*), void*); + int32_t BindTexture(TextureBindCallback, void*); void Reset(); + + uint8_t _0[0x78]; }; } // namespace nn::g3d diff --git a/lib/g3d/include/nn/g3d/g3d_ResModel.h b/lib/g3d/include/nn/g3d/g3d_ResModel.h index 3af30db9..a6362265 100644 --- a/lib/g3d/include/nn/g3d/g3d_ResModel.h +++ b/lib/g3d/include/nn/g3d/g3d_ResModel.h @@ -6,25 +6,27 @@ #pragma once #include + #include +#include + namespace nn::g3d { class ResMaterial; -typedef void* TextureRef; - class ResModel { public: - uint64_t BindTexture(nn::g3d::TextureRef (*)(char const*, void*), void*); + int32_t BindTexture(TextureBindCallback, void*); void ForceBindTexture(nn::g3d::TextureRef const&, char const*); void ReleaseTexture(); void Setup(gfx::Device*); + void Setup(gfx::Device*, gfx::MemoryPool*, int64_t); void Cleanup(gfx::Device*); void Reset(); void Reset(uint32_t); nn::g3d::ResMaterial* FindMaterial(char const* materialName) const; - uint8_t _0[0x70]; + uint8_t _0[0x78]; }; } // namespace nn::g3d diff --git a/lib/g3d/include/nn/g3d/g3d_ResSceneAnim.h b/lib/g3d/include/nn/g3d/g3d_ResSceneAnim.h index 273008ec..040da216 100644 --- a/lib/g3d/include/nn/g3d/g3d_ResSceneAnim.h +++ b/lib/g3d/include/nn/g3d/g3d_ResSceneAnim.h @@ -6,21 +6,20 @@ #include +#include + namespace nn::g3d { class ResLightAnim; class ResFogAnim; class BindFuncTable; -class ResSceneAnim { +class ResSceneAnim : public util::BinaryBlockHeader { public: int32_t Bind(nn::g3d::BindFuncTable const&); void Release(); void Reset(); - char mMagic[4]; // _0 - int32_t mBlockOffset; // _4 - uint64_t mBlockSize; // _8 uint64_t mNameOffset; // _10 uint64_t mPathOffset; // _18 uint64_t mCameraAnimOffset; // _20 diff --git a/lib/g3d/include/nn/g3d/g3d_ResShapeAnim.h b/lib/g3d/include/nn/g3d/g3d_ResShapeAnim.h index 07816c35..28eb04ba 100644 --- a/lib/g3d/include/nn/g3d/g3d_ResShapeAnim.h +++ b/lib/g3d/include/nn/g3d/g3d_ResShapeAnim.h @@ -4,11 +4,15 @@ #pragma once +#include + namespace nn::g3d { -class ResShapeAnim { +class ResShapeAnim : public util::BinaryBlockHeader { public: void Reset(); + + uint8_t _0[0x50]; }; } // namespace nn::g3d diff --git a/lib/g3d/include/nn/g3d/g3d_ResSkeletalAnim.h b/lib/g3d/include/nn/g3d/g3d_ResSkeletalAnim.h index 8c3eaf45..2ed61045 100644 --- a/lib/g3d/include/nn/g3d/g3d_ResSkeletalAnim.h +++ b/lib/g3d/include/nn/g3d/g3d_ResSkeletalAnim.h @@ -4,11 +4,15 @@ #pragma once +#include + namespace nn::g3d { class ResSkeletalAnim { public: void Reset(); + + uint8_t _0[0x60]; }; } // namespace nn::g3d diff --git a/lib/g3d/include/nn/g3d/g3d_TextureRef.h b/lib/g3d/include/nn/g3d/g3d_TextureRef.h new file mode 100644 index 00000000..759bcb91 --- /dev/null +++ b/lib/g3d/include/nn/g3d/g3d_TextureRef.h @@ -0,0 +1,9 @@ +#pragma once + +namespace nn::g3d { + +struct TextureRef {}; // TODO + +using TextureBindCallback = nn::g3d::TextureRef (*)(const char*, void*); + +} // namespace nn::g3d diff --git a/lib/g3d/src/g3d/g3d_ResFile.cpp b/lib/g3d/src/g3d/g3d_ResFile.cpp new file mode 100644 index 00000000..fcee7a4b --- /dev/null +++ b/lib/g3d/src/g3d/g3d_ResFile.cpp @@ -0,0 +1,120 @@ +#include + +#include + +#include +#include +#include +#include +#include + +namespace nn::g3d { + +NN_MIDDLEWARE(g_MiddlewareInfo, "Nintendo", "NintendoWare_G3d" NN_SDK_BUILD_STR); + +bool ResFile::IsValid(const void* modelSrc) { + return static_cast(modelSrc)->IsValid(Signature, 8, 0, 0); +} + +void ResFile::Relocate() { + if (!fileHeader.IsRelocated()) + fileHeader.GetRelocationTable()->Relocate(); +} + +void ResFile::Unrelocate() { + if (fileHeader.IsRelocated()) + fileHeader.GetRelocationTable()->Unrelocate(); +} + +ResFile* ResFile::ResCast(void* ptr) { + auto* file = static_cast(ptr); + + if (ptr != nullptr) { + file->Relocate(); + file->fileHeader.IsEndianReverse(); + } + + return file; +} + +int32_t ResFile::BindTexture(TextureBindCallback callback, void* callbackArg) { + int32_t result = 0; + + int32_t mdlCount = modelCount; + for (int32_t i{0}; i < mdlCount; ++i) + result |= pModels.Get()[i].BindTexture(callback, callbackArg); + + int32_t matAnimCount = materialAnimCount; + for (int32_t i{0}; i < matAnimCount; ++i) + result |= pMaterialAnims.Get()[i].BindTexture(callback, callbackArg); + + return result; +} + +void ResFile::ReleaseTexture() { + int32_t mdlCount = modelCount; + for (int32_t i{0}; i < mdlCount; ++i) + pModels.Get()[i].ReleaseTexture(); + + int32_t matAnimCount = materialAnimCount; + for (int32_t i{0}; i < matAnimCount; ++i) + pMaterialAnims.Get()[i].ReleaseTexture(); +} + +void ResFile::Setup(gfx::Device* device) { + nn::util::ReferSymbol(g_MiddlewareInfo); + + if (pMemoryPool.Get() != nullptr && pMemoryPoolInfo.Get() != nullptr) + pMemoryPool.Get()->Initialize(device, *pMemoryPoolInfo.Get(), "g3d"); + + int32_t mdlCount = modelCount; + for (int32_t i{0}; i < mdlCount; ++i) + pModels.Get()[i].Setup(device); +} + +void ResFile::Setup(gfx::Device* device, gfx::MemoryPool* memPool, int64_t bufferOffset, + [[maybe_unused]] uint64_t) { + if (pMemoryPool.Get() != nullptr && pMemoryPoolInfo.Get() != nullptr) + bufferOffset = reinterpret_cast(pMemoryPoolInfo.Get()->GetPoolMemory()) + + (bufferOffset - reinterpret_cast(this)); + + int32_t mdlCount = modelCount; + for (int32_t i{0}; i < mdlCount; ++i) + pModels.Get()[i].Setup(device, memPool, bufferOffset); +} + +void ResFile::Cleanup(gfx::Device* device) { + int32_t mdlCount = modelCount; + for (int32_t i{0}; i < mdlCount; ++i) + pModels.Get()[i].Cleanup(device); + + if (pMemoryPoolInfo.Get() != nullptr && + pMemoryPool.Get()->ToData()->state != gfx::MemoryPool::DataType::State_NotInitialized) + pMemoryPool.Get()->Finalize(device); +} + +void ResFile::Reset() { + int32_t mdlCount = modelCount; + for (int32_t i{0}; i < mdlCount; ++i) + pModels.Get()[i].Reset(); + + int32_t sklAnimCount = skeletalAnimCount; + for (int32_t i{0}; i < sklAnimCount; ++i) + pSkeletalAnims.Get()[i].Reset(); + + int32_t matAnimCount = materialAnimCount; + for (int32_t i{0}; i < matAnimCount; ++i) + pMaterialAnims.Get()[i].Reset(); + + int32_t shpAnimCount = shapeAnimCount; + for (int32_t i{0}; i < shpAnimCount; ++i) + pShapeAnims.Get()[i].Reset(); + + int32_t scnAnimCount = sceneAnimCount; + for (int32_t i{0}; i < scnAnimCount; ++i) + pSceneAnims.Get()[i].Reset(); + + padding = 0; +} + +} // namespace nn::g3d diff --git a/lib/g3d/src/g3d/g3d_Stub.cpp b/lib/g3d/src/g3d/g3d_Stub.cpp deleted file mode 100644 index 70b786d1..00000000 --- a/lib/g3d/src/g3d/g3d_Stub.cpp +++ /dev/null @@ -1 +0,0 @@ -// TODO