From 602ed2b570a1fe01236f59270084c98ac044eb0d Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Tue, 17 Oct 2023 11:26:21 -0700 Subject: [PATCH] Nearly match DolphinCTexture and various cleanups Former-commit-id: 76f3ff2603441ac6aa39fa009e7f466e84c8bc56 --- .vscode/settings.json | 3 +- config/GM8E01_00/symbols.txt | 14 +- config/GM8E01_01/symbols.txt | 2 +- include/Kyoto/CARAMToken.hpp | 1 + include/Kyoto/CResFactory.hpp | 5 +- include/Kyoto/CResLoader.hpp | 7 +- include/Kyoto/Graphics/CGraphicsPalette.hpp | 6 +- include/Kyoto/Graphics/CTexture.hpp | 70 ++- include/Kyoto/Math/CMath.hpp | 1 + include/Kyoto/Streams/CInputStream.hpp | 3 +- include/rstl/single_ptr.hpp | 1 - src/Dolphin/os/OSReboot.c | 53 +++ src/Kyoto/CARAMToken.cpp | 7 +- src/Kyoto/CDependencyGroup.cpp | 5 - src/Kyoto/Graphics/DolphinCGraphics.cpp | 2 +- src/Kyoto/Graphics/DolphinCPalette.cpp | 10 +- src/Kyoto/Graphics/DolphinCTexture.cpp | 480 +++++++++++++++++++- src/Kyoto/Text/CStringTable.cpp | 5 +- src/MetroidPrime/CProjectedShadow.cpp | 2 +- src/MetroidPrime/CWorldShadow.cpp | 5 +- 20 files changed, 603 insertions(+), 79 deletions(-) create mode 100644 src/Dolphin/os/OSReboot.c diff --git a/.vscode/settings.json b/.vscode/settings.json index 7296b1db..7c60be63 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,7 +12,8 @@ }, "clangd.fallbackFlags": [ "-I${workspaceFolder}/include", - "-I${workspaceFolder}/libc" + "-I${workspaceFolder}/libc", + "-D__MWERKS__", ], "editor.tabSize": 2, "files.associations": { diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index 01812678..fb1a941f 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -13550,7 +13550,7 @@ Load__16CGraphicsPaletteCFv = .text:0x8030DEC4; // type:function size:0x3C scope __dt__16CGraphicsPaletteFv = .text:0x8030DF00; // type:function size:0x88 scope:global __ct__16CGraphicsPaletteFR12CInputStream = .text:0x8030DF88; // type:function size:0xEC scope:global __ct__16CGraphicsPaletteF14EPaletteFormati = .text:0x8030E074; // type:function size:0x98 scope:global -fn_8030E10C = .text:0x8030E10C; // type:function size:0x3C +fn_8030E10C__8CTextureFv = .text:0x8030E10C; // type:function size:0x3C InvalidateTexmap__8CTextureF11_GXTexMapID = .text:0x8030E148; // type:function size:0x18 scope:global UncountMemory__8CTextureCFv = .text:0x8030E160; // type:function size:0x2C scope:global CountMemory__8CTextureCFv = .text:0x8030E18C; // type:function size:0x2C scope:global @@ -13570,7 +13570,7 @@ LoadToMRAM__8CTextureCFv = .text:0x8030EC28; // type:function size:0x50 scope:gl TryBuildReloadedBitmapData__Q28CTexture25CDumpedBitmapDataReloaderFR11CResFactory = .text:0x8030EC78; // type:function size:0x2F8 scope:global BeginReloadBitmapData__Q28CTexture25CDumpedBitmapDataReloaderFR11CResFactory = .text:0x8030EF70; // type:function size:0xF4 scope:global __ct__Q28CTexture25CDumpedBitmapDataReloaderFUiUib = .text:0x8030F064; // type:function size:0x24 scope:global -fn_8030F088 = .text:0x8030F088; // type:function size:0x7C +fn_8030F088__8CTextureCFv = .text:0x8030F088; // type:function size:0x7C TryReloadBitmapData__8CTextureCFR11CResFactory = .text:0x8030F104; // type:function size:0x100 scope:global UnloadBitmapData__8CTextureCFUi = .text:0x8030F204; // type:function size:0x194 scope:global LoadMipLevel__8CTextureCFi11_GXTexMapIDQ28CTexture10EClampMode = .text:0x8030F398; // type:function size:0x3A4 scope:global @@ -15804,7 +15804,7 @@ Run = .text:0x80382E28; // type:function size:0x10 scope:local Callback = .text:0x80382E38; // type:function size:0xC scope:local __OSReboot = .text:0x80382E44; // type:function size:0x1C8 scope:global OSSetSaveRegion = .text:0x8038300C; // type:function size:0xC scope:global -OSGetSaveRegion = .text:0x80383018; // type:function size:0x14 scope:global +OSGetSavedRegion = .text:0x80383018; // type:function size:0x14 scope:global OSRegisterResetFunction = .text:0x8038302C; // type:function size:0x84 scope:global __OSCallResetFunctions = .text:0x803830B0; // type:function size:0x8C scope:global Reset = .text:0x8038313C; // type:function size:0x70 scope:global @@ -17813,7 +17813,7 @@ vtxDescList$288 = .rodata:0x803D73B8; // type:object size:0x10 scope:local lbl_803D73C8 = .rodata:0x803D73C8; // type:object size:0x20 lbl_803D73E8 = .rodata:0x803D73E8; // type:object size:0x8 lbl_803D73F0 = .rodata:0x803D73F0; // type:object size:0x10 data:4byte -lbl_803D7400 = .rodata:0x803D7400; // type:object size:0x8 +@stringBase0 = .rodata:0x803D7400; // type:object size:0x8 scope:local data:string_table gkCRC32Table = .rodata:0x803D7408; // type:object size:0x400 scope:local @stringBase0 = .rodata:0x803D7808; // type:object size:0x18 scope:local data:string_table lbl_803D7820 = .rodata:0x803D7820; // type:object size:0x20 @@ -17928,7 +17928,7 @@ __THPAANScaleFactor = .rodata:0x803D8D20; // type:object size:0x40 scope:local lbl_803D8D60 = .data:0x803D8D60; // type:object size:0xC __vt__4IObj = .data:0x803D8D6C; // type:object size:0xC scope:global __vt__31CObjOwnerDerivedFromIObjUntyped = .data:0x803D8D78; // type:object size:0xC scope:global -lbl_803D8D84 = .data:0x803D8D84; // type:object size:0xC +__vt__35TObjOwnerDerivedFromIObj<8CTexture> = .data:0x803D8D84; // type:object size:0xC lbl_803D8D90 = .data:0x803D8D90; // type:object size:0x10C __vt__24IArchitectureMessageParm = .data:0x803D8E9C; // type:object size:0xC scope:global __vt__22CCameraShakerComponent = .data:0x803D8EA8; // type:object size:0x10 scope:global @@ -18718,7 +18718,7 @@ mViewport__9CGraphics = .data:0x803ED910; // type:object size:0x18 scope:global mLightTypes__9CGraphics = .data:0x803ED928; // type:object size:0x20 scope:global data:4byte jumptable_803ED948 = .data:0x803ED948; // type:object size:0x20 scope:local jumptable_803ED968 = .data:0x803ED968; // type:object size:0x2C scope:local -jumptable_803ED994 = .data:0x803ED994; // type:object size:0x2C scope:local +@344 = .data:0x803ED994; // type:object size:0x2C scope:local __vt__10IAllocator = .data:0x803ED9C0; // type:object size:0x40 scope:global lbl_803EDA00 = .data:0x803EDA00; // type:object size:0x10 __vt__18CCEKeyframeEmitter = .data:0x803EDA10; // type:object size:0x10 scope:global @@ -21933,7 +21933,7 @@ init$2340 = .sbss:0x805A9420; // type:object size:0x8 scope:global data:byte sCurrentFrameCount__16CGraphicsPalette = .sbss:0x805A9428; // type:object size:0x8 scope:global data:4byte sCurrentFrameCount__8CTexture = .sbss:0x805A9430; // type:object size:0x4 scope:global data:4byte sTotalAllocatedMemory__8CTexture = .sbss:0x805A9434; // type:object size:0x4 scope:global data:4byte -sMangleMips__8CTexture = .sbss:0x805A9438; // type:object size:0x8 scope:global data:byte +sMangleMips__8CTexture = .sbss:0x805A9438; // type:object size:0x1 scope:global data:byte svector2_Identity = .sbss:0x805A9440; // type:object size:0x8 scope:local lbl_805A9448 = .sbss:0x805A9448; // type:object size:0x4 data:float lbl_805A944C = .sbss:0x805A944C; // type:object size:0x1 data:byte diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index ea62e251..ebcdaa0e 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -13585,7 +13585,7 @@ LoadToMRAM__8CTextureCFv = .text:0x8030ED08; // type:function size:0x50 scope:gl TryBuildReloadedBitmapData__Q28CTexture25CDumpedBitmapDataReloaderFR11CResFactory = .text:0x8030ED58; // type:function size:0x2F8 scope:global BeginReloadBitmapData__Q28CTexture25CDumpedBitmapDataReloaderFR11CResFactory = .text:0x8030F050; // type:function size:0xF4 scope:global __ct__Q28CTexture25CDumpedBitmapDataReloaderFUiUib = .text:0x8030F144; // type:function size:0x24 scope:global -fn_8030F088 = .text:0x8030F168; // type:function size:0x7C scope:global +fn_8030F088__8CTextureCFv = .text:0x8030F168; // type:function size:0x7C scope:global TryReloadBitmapData__8CTextureCFR11CResFactory = .text:0x8030F1E4; // type:function size:0x100 scope:global UnloadBitmapData__8CTextureCFUi = .text:0x8030F2E4; // type:function size:0x194 scope:global LoadMipLevel__8CTextureCFi11_GXTexMapIDQ28CTexture10EClampMode = .text:0x8030F478; // type:function size:0x3A4 scope:global diff --git a/include/Kyoto/CARAMToken.hpp b/include/Kyoto/CARAMToken.hpp index dcee4352..e81951bc 100644 --- a/include/Kyoto/CARAMToken.hpp +++ b/include/Kyoto/CARAMToken.hpp @@ -22,6 +22,7 @@ public: ~CARAMToken(); void PostConstruct(void* ptr, uint len, int unk); CARAMToken& operator=(const CARAMToken& other); + const EStatus GetStatus() const { return x0_status; } bool LoadToMRAM(); bool LoadToARAM(); bool RefreshStatus(); diff --git a/include/Kyoto/CResFactory.hpp b/include/Kyoto/CResFactory.hpp index 0be5a39f..8fcef8c8 100644 --- a/include/Kyoto/CResFactory.hpp +++ b/include/Kyoto/CResFactory.hpp @@ -1,6 +1,7 @@ #ifndef _CRESFACTORY #define _CRESFACTORY +#include "Kyoto/Streams/CInputStream.hpp" #include "types.h" #include "rstl/list.hpp" @@ -36,7 +37,9 @@ public: CResLoader& GetResLoader() { return x4_resLoader; } FourCC GetResourceTypeById(CAssetId id) { return GetResLoader().GetResourceTypeById(id); } - + CInputStream* LoadResourceFromMemorySync(const SObjectTag& tag, const void* extBuf) { + return x4_resLoader.LoadResourceFromMemorySync(tag, extBuf); + } private: CResLoader x4_resLoader; CFactoryMgr x5c_factoryMgr; diff --git a/include/Kyoto/CResLoader.hpp b/include/Kyoto/CResLoader.hpp index 9b66e015..36a836bd 100644 --- a/include/Kyoto/CResLoader.hpp +++ b/include/Kyoto/CResLoader.hpp @@ -1,6 +1,7 @@ #ifndef _CRESLOADER #define _CRESLOADER +#include "Kyoto/SObjectTag.hpp" #include "types.h" #include "rstl/list.hpp" @@ -9,7 +10,7 @@ #include "Kyoto/IObjectStore.hpp" class CPakFile; -class CARAMDvdRequest; +class CDvdRequest; struct SResInfo { CAssetId x0_id; @@ -27,8 +28,10 @@ public: void AsyncIdlePakLoading(); bool AreAllPaksLoaded() const; CInputStream* LoadNewResourceSync(const SObjectTag& tag, char* extBuf); + CInputStream* LoadResourceFromMemorySync(const SObjectTag& tag, const void* extBuf); CInputStream* LoadNewResourceSync(const SObjectTag& tag, int, int, char* extBuf); - CARAMDvdRequest* LoadResourcePartAsync(const SObjectTag& tag, int, int, char*); + CDvdRequest* LoadResourcePartAsync(const SObjectTag& tag, int, int, char*); + CDvdRequest* LoadResourceAsync(const SObjectTag& tag, char*); FourCC GetResourceTypeById(CAssetId) const; uint ResourceSize(const SObjectTag& tag) const; diff --git a/include/Kyoto/Graphics/CGraphicsPalette.hpp b/include/Kyoto/Graphics/CGraphicsPalette.hpp index 6ae66bc5..1ed22de3 100644 --- a/include/Kyoto/Graphics/CGraphicsPalette.hpp +++ b/include/Kyoto/Graphics/CGraphicsPalette.hpp @@ -23,7 +23,7 @@ public: CGraphicsPalette(CInputStream& in); ~CGraphicsPalette(); - inline GXTlutFmt GetTlutFmt() const { return static_cast(x0_fmt); } + inline GXTlutFmt GetTlutFmt() const { return static_cast< GXTlutFmt >(x0_fmt); } ushort* GetPaletteData() { return xc_entries.get(); } const ushort* GetPaletteData() const { return xc_entries.get(); } void Load() const; @@ -39,4 +39,8 @@ private: bool x1c_locked; }; +static inline GXTlutFmt format_to_format(EPaletteFormat fmt) { + return static_cast< GXTlutFmt >(fmt); +} + #endif // _CGRAPHICSPALETTE diff --git a/include/Kyoto/Graphics/CTexture.hpp b/include/Kyoto/Graphics/CTexture.hpp index dc0a03af..dc810b57 100644 --- a/include/Kyoto/Graphics/CTexture.hpp +++ b/include/Kyoto/Graphics/CTexture.hpp @@ -1,6 +1,7 @@ #ifndef _CTEXTURE #define _CTEXTURE +#include "dolphin/gx/GXEnum.h" #include "types.h" #include "Kyoto/CARAMToken.hpp" @@ -8,6 +9,7 @@ #include +class CResFactory; class CDvdRequest; class CInputStream; class CGraphicsPalette; @@ -37,6 +39,14 @@ public: bool x10_; rstl::single_ptr< CDvdRequest > x14_; rstl::single_ptr< uchar > x18_; + + public: + CDumpedBitmapDataReloader(uint unk1, uint unk2, bool unk3); + + void BeginReloadBitmapData(CResFactory& factory); + void* TryBuildReloadedBitmapData(CResFactory& factory); + int GetStatus() const { return x0_; } + const bool GetX10() const { return x10_; } }; enum EClampMode { @@ -56,19 +66,15 @@ public: ~CTexture(); // Used in certain destructors - void sub_8030e10c(); - + void fn_8030E10C(); + void LoadMipLevel(int, GXTexMapID tex, EClampMode) const; void Load(GXTexMapID texMapId, EClampMode clampMode) const; - void UnLock(); - - void* GetBitMapData(int); - - void InitBitmapBuffers(ETexelFormat fmt, short w, short h, int mips); - void InitTextureObjects(); + bool HasPalette() const { return IsCITextureFormat(mTexelFormat); } + const void* GetConstBitMapData(const int mip) const; + void* GetBitMapData(int); ETexelFormat GetTexelFormat() const { return mTexelFormat; } - short GetWidth() const { return mWidth; } - short GetHeight() const { return mHeight; } - + const short GetWidth() const { return mWidth; } + const short GetHeight() const { return mHeight; } void* Lock() { mLocked = true; return GetBitMapData(0); @@ -78,35 +84,51 @@ public: void CountMemory() const; void UncountMemory() const; void SetFlag1(bool b) { mLocked = b; } + void MangleMipmap(int mip); + const char GetBitsPerPixel() const { return mBitsPerPixel; } + void UnloadBitmapData(uint unk) const; + bool TryReloadBitmapData(CResFactory& factory) const; + int fn_8030F088() const; + bool LoadToMRAM() const; + bool LoadToARAM() const; + bool IsARAMTransferInProgress() const; + static int TexelFormatBitsPerPixel(ETexelFormat fmt); + void InitBitmapBuffers(const ETexelFormat fmt, const short w, const short h, const int mips); + void InitTextureObjects(); + void UnLock(); - static uint TexelFormatBitsPerPixel(ETexelFormat fmt); static void InvalidateTexmap(GXTexMapID id); + static bool IsCITextureFormat(ETexelFormat fmt) { + return fmt == kTF_C4 ? true : fmt == kTF_C8 ? true : fmt == kTF_C14X2 ? true : false; + } + static void SetMangleMipmaps(bool v) { sMangleMips = true; } + static const bool GetMangleMipmaps() { return sMangleMips; } static int sCurrentFrameCount; static int sTotalAllocatedMemory; static bool sMangleMips; private: - ETexelFormat mTexelFormat; // TODO: Enum + ETexelFormat mTexelFormat; short mWidth; short mHeight; - uchar mNumMips; - uchar mBitsPerPixel; + char mNumMips; + char mBitsPerPixel; bool mLocked : 1; - bool mCanLoadPalette : 1; + mutable bool mCanLoadPalette : 1; bool mIsPowerOfTwo : 1; mutable bool mNoSwap : 1; mutable bool mCounted : 1; - uchar mCanLoadObj : 1; + mutable bool mCanLoadObj : 1; uint mMemoryAllocated; rstl::single_ptr< CGraphicsPalette > mGraphicsPalette; - rstl::single_ptr< CDumpedBitmapDataReloader > mBitmapReloader; - uint mNativeFormat; - uint mNativeCIFormat; - GXTexObj mTexObj; - EClampMode mClampMode; - CARAMToken mARAMToken; - uint mFrameAllocated; + mutable rstl::single_ptr< CDumpedBitmapDataReloader > mBitmapReloader; + GXTexFmt mNativeFormat; + GXCITexFmt mNativeCIFormat; + mutable GXTexObj mTexObj; + mutable EClampMode mClampMode; + mutable CARAMToken mARAMToken; + mutable uint mFrameAllocated; }; CHECK_SIZEOF(CTexture, 0x68) diff --git a/include/Kyoto/Math/CMath.hpp b/include/Kyoto/Math/CMath.hpp index d13b72dc..4c5cc734 100644 --- a/include/Kyoto/Math/CMath.hpp +++ b/include/Kyoto/Math/CMath.hpp @@ -78,6 +78,7 @@ public: // CeilingF__5CMathFf global // ArcTangentR__5CMathFf global // Swap__5CMathFRfRf weak + static int FloorPowerOfTwo(int v); }; #endif // _CMATH diff --git a/include/Kyoto/Streams/CInputStream.hpp b/include/Kyoto/Streams/CInputStream.hpp index 86eda00c..3b5862e1 100644 --- a/include/Kyoto/Streams/CInputStream.hpp +++ b/include/Kyoto/Streams/CInputStream.hpp @@ -44,7 +44,8 @@ public: // CIEKeyframeEmitter / rstl::vector(CInputStream&) // why? int ReadInt32() { return static_cast< uint >(Get(TType< int >())); } - u16 ReadUint16() { return Get(); } + ushort ReadUint16() { return Get(); } + short ReadInt16() { return Get(); } uint GetBlockOffset() const { return x4_blockOffset; } diff --git a/include/rstl/single_ptr.hpp b/include/rstl/single_ptr.hpp index 357489de..68cac0e8 100644 --- a/include/rstl/single_ptr.hpp +++ b/include/rstl/single_ptr.hpp @@ -35,7 +35,6 @@ public: single_ptr& Set(T* ptr); }; - template < typename T > single_ptr< T >& single_ptr< T >::Set(T* ptr) { return *this = ptr; diff --git a/src/Dolphin/os/OSReboot.c b/src/Dolphin/os/OSReboot.c new file mode 100644 index 00000000..a4395dad --- /dev/null +++ b/src/Dolphin/os/OSReboot.c @@ -0,0 +1,53 @@ +#include "dolphin/os.h" + +typedef struct ApploaderHeader { + // total size: 0x20 + char date[16]; // offset 0x0, size 0x10 + u32 entry; // offset 0x10, size 0x4 + u32 size; // offset 0x14, size 0x4 + u32 rebootSize; // offset 0x18, size 0x4 + u32 reserved2; // offset 0x1C, size 0x4 +} ApploaderHeader; + +static ApploaderHeader Header; + +extern void* __OSSavedRegionStart; +extern void* __OSSavedRegionEnd; + +static void* SaveStart = NULL; +static void* SaveEnd = NULL; + +static BOOL Prepared = FALSE; + +asm void Run() { + // clang-format off + nofralloc + sync + isync + mtlr r3 + blr + // clang-format on +} + +static void Callback() { + Prepared = TRUE; +} + +void __OSReboot(u32 resetCode, u32 bootDol) { + OSDisableInterrupts(); +} + +void OSSetSaveRegion(void* start, void* end) { + SaveStart = start; + SaveEnd = end; +} + +void OSGetSaveRegion(void** start, void** end) { + *start = SaveStart; + *end = SaveEnd; +} + +void OSGetSavedRegion(void** start, void** end) { + *start = __OSSavedRegionStart; + *end = __OSSavedRegionEnd; +} diff --git a/src/Kyoto/CARAMToken.cpp b/src/Kyoto/CARAMToken.cpp index 3b516b41..c96a070a 100644 --- a/src/Kyoto/CARAMToken.cpp +++ b/src/Kyoto/CARAMToken.cpp @@ -109,6 +109,8 @@ bool CARAMToken::LoadToMRAM() { MoveToList(kS_Three); break; } + default: + break; } return RefreshStatus(); @@ -143,8 +145,9 @@ bool CARAMToken::LoadToARAM() { MoveToList(kS_Two); break; } + default: + break; } - return RefreshStatus(); } @@ -176,6 +179,8 @@ bool CARAMToken::RefreshStatus() { MoveToList(kS_Zero); break; } + default: + break; } return true; diff --git a/src/Kyoto/CDependencyGroup.cpp b/src/Kyoto/CDependencyGroup.cpp index 0f9559fb..3323ccdd 100644 --- a/src/Kyoto/CDependencyGroup.cpp +++ b/src/Kyoto/CDependencyGroup.cpp @@ -29,11 +29,6 @@ int CDependencyGroup::GetCountForResType(FourCC type) const { /* this is such a hack... */ #pragma inline_max_size(250) -template <> -CFactoryFnReturn::CFactoryFnReturn(CDependencyGroup* ptr) -: obj(TToken< CDependencyGroup >::GetIObjObjectFor(rstl::auto_ptr< CDependencyGroup >(ptr)) - .release()) {} - CFactoryFnReturn FDependencyGroupFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& xfer) { return rs_new CDependencyGroup(in); diff --git a/src/Kyoto/Graphics/DolphinCGraphics.cpp b/src/Kyoto/Graphics/DolphinCGraphics.cpp index 6958c652..386585a6 100644 --- a/src/Kyoto/Graphics/DolphinCGraphics.cpp +++ b/src/Kyoto/Graphics/DolphinCGraphics.cpp @@ -773,7 +773,7 @@ void CGraphics::EndScene() { GXEnableBreakPt(writePtr); mLastFrameUsedAbove = mInterruptLastFrameUsedAbove; ++mFrameCounter; - CFrameDelayedKiller::sub_8036cb90(); + CFrameDelayedKiller::fn_8036CB90(); } void CGraphics::SetDepthWriteMode(bool test, ERglEnum comp, bool write) { diff --git a/src/Kyoto/Graphics/DolphinCPalette.cpp b/src/Kyoto/Graphics/DolphinCPalette.cpp index ac77d129..627552eb 100644 --- a/src/Kyoto/Graphics/DolphinCPalette.cpp +++ b/src/Kyoto/Graphics/DolphinCPalette.cpp @@ -8,16 +8,12 @@ uint CGraphicsPalette::sCurrentFrameCount = 0; -inline GXTlutFmt ConvertFormat(EPaletteFormat fmt) { - return static_cast(fmt); -} - CGraphicsPalette::CGraphicsPalette(EPaletteFormat format, int numEntries) : x0_fmt(format) , x8_entryCount(numEntries) , xc_entries((ushort*)CMemory::Alloc(numEntries * sizeof(ushort), IAllocator::kHI_RoundUpLen)) , x1c_locked(false) { - GXInitTlutObj(&x10_tlutObj, xc_entries.get(), ConvertFormat(x0_fmt), x8_entryCount); + GXInitTlutObj(&x10_tlutObj, xc_entries.get(), format_to_format(x0_fmt), x8_entryCount); } CGraphicsPalette::CGraphicsPalette(CInputStream& in) @@ -26,7 +22,7 @@ CGraphicsPalette::CGraphicsPalette(CInputStream& in) , xc_entries((ushort*)CMemory::Alloc(x8_entryCount * sizeof(ushort), IAllocator::kHI_RoundUpLen)) , x1c_locked(false) { in.Get(reinterpret_cast< uchar* >(xc_entries.get()), x8_entryCount * sizeof(ushort)); - GXInitTlutObj(&x10_tlutObj, xc_entries.get(), ConvertFormat(x0_fmt), x8_entryCount); + GXInitTlutObj(&x10_tlutObj, xc_entries.get(), format_to_format(x0_fmt), x8_entryCount); DCFlushRange(xc_entries.get(), x8_entryCount * sizeof(ushort)); } @@ -44,7 +40,7 @@ void CGraphicsPalette::Load() const { void CGraphicsPalette::UnLock() { DCStoreRange(xc_entries.get(), x8_entryCount * sizeof(ushort)); - GXInitTlutObj(&x10_tlutObj, xc_entries.get(), ConvertFormat(x0_fmt), x8_entryCount); + GXInitTlutObj(&x10_tlutObj, xc_entries.get(), format_to_format(x0_fmt), x8_entryCount); DCFlushRange(xc_entries.get(), x8_entryCount * sizeof(ushort)); x1c_locked = false; } diff --git a/src/Kyoto/Graphics/DolphinCTexture.cpp b/src/Kyoto/Graphics/DolphinCTexture.cpp index ba613dfd..b73e35da 100644 --- a/src/Kyoto/Graphics/DolphinCTexture.cpp +++ b/src/Kyoto/Graphics/DolphinCTexture.cpp @@ -1,16 +1,33 @@ +#include "Kyoto/Alloc/IAllocator.hpp" +#include "Kyoto/CARAMToken.hpp" +#include "Kyoto/CFrameDelayedKiller.hpp" #include "Kyoto/Graphics/CTexture.hpp" +#include "Kyoto/SObjectTag.hpp" +#include "dolphin/PPCArch.h" +#include "dolphin/gx/GXEnum.h" +#include "dolphin/gx/GXStruct.h" +#include "dolphin/gx/GXTexture.h" +#include "dolphin/os.h" +#include "dolphin/os/OSCache.h" +#include "rstl/single_ptr.hpp" +#include "types.h" -#include "Kyoto/CDvdRequest.hpp" -#include "Kyoto/Graphics/CGraphicsPalette.hpp" -#include "Kyoto/Alloc/CMemorySys.hpp" +#include +#include +#include +#include +#include +#include int CTexture::sCurrentFrameCount = 0; int CTexture::sTotalAllocatedMemory = 0; bool CTexture::sMangleMips = false; -static CTexture* sLoadedTextures[GX_MAX_TEXMAP]; +#define ROUND_UP_4(v) (((v) + 3) & ~3) -CTexture::CTexture(ETexelFormat fmt, short w, short h, int mips) +static const CTexture* sLoadedTextures[GX_MAX_TEXMAP]; + +CTexture::CTexture(ETexelFormat fmt, const short w, const short h, int mips) : mTexelFormat(fmt) , mWidth(w) , mHeight(h) @@ -31,15 +48,442 @@ CTexture::CTexture(ETexelFormat fmt, short w, short h, int mips) InitTextureObjects(); } -CTexture::CTexture(CInputStream& in, EAutoMipmap automip, EBlackKey blackKey) { +CTexture::CTexture(CInputStream& in, EAutoMipmap automip, EBlackKey blackKey) +: mTexelFormat(kTF_Invalid) +, mWidth(0) +, mHeight(0) +, mNumMips(0) +, mBitsPerPixel(0) +, mLocked(false) +, mCanLoadPalette(false) +, mIsPowerOfTwo(false) +, mNoSwap(true) +, mCounted(false) +, mCanLoadObj(false) +, mMemoryAllocated(0) +, mFrameAllocated(sCurrentFrameCount) +, mNativeFormat(GX_TF_RGB565) +, mNativeCIFormat(GX_TF_C8) +, mClampMode(kCM_Repeat) { + mTexelFormat = ETexelFormat(in.Get< uint >()); + mWidth = in.ReadUint16(); + mHeight = in.ReadUint16(); + mNumMips = in.ReadLong(); + if (IsCITextureFormat(mTexelFormat)) { + mGraphicsPalette = rs_new CGraphicsPalette(in); + mCanLoadPalette = true; + } + mBitsPerPixel = TexelFormatBitsPerPixel(mTexelFormat); + InitBitmapBuffers(mTexelFormat, mWidth, mHeight, mNumMips); + int bufLen = 0; + for (int i = 0; i < mNumMips;) { + int width = ((GetWidth() >> i) + 3) & ~3; + int height = ((GetHeight() >> i) + 3) & ~3; + int page = width * height; + i++; + bufLen += (GetBitsPerPixel() * page) >> 3; + } + + uchar* buf = (uchar*)mARAMToken.GetMRAMSafe(); + for (int off = 0, len = 0; off < bufLen; off += len) { + len = bufLen - off; + if (len > 256) { + len = 256; + } + + in.Get(buf + off, len); + DCFlushRangeNoSync(buf + off, OSRoundUp32B(len)); + } + + if (sMangleMips != false) { + for (int i = 1; i < mNumMips; ++i) { + MangleMipmap(i); + } + } + + InitTextureObjects(); + PPCSync(); +} + +CTexture::~CTexture() { UncountMemory(); } + +void CTexture::InitTextureObjects() { + mIsPowerOfTwo = + CMath::FloorPowerOfTwo(mWidth) == mWidth && CMath::FloorPowerOfTwo(mHeight) == mHeight; + + if (!mIsPowerOfTwo) { + mClampMode = kCM_Clamp; + } + bool hasMips = mNumMips > 1; + GXTexWrapMode wrap = (GXTexWrapMode)mClampMode; + short width = mWidth; + short height = mHeight; + void* buf = mARAMToken.GetMRAMSafe(); + CountMemory(); + + if (IsCITextureFormat(mTexelFormat)) { + GXInitTexObjCI(&mTexObj, buf, width, height, mNativeCIFormat, wrap, wrap, hasMips, 0); + } else { + GXInitTexObj(&mTexObj, buf, width, height, mNativeFormat, wrap, wrap, hasMips); + GXInitTexObjLOD(&mTexObj, mNumMips > 1 ? GX_LIN_MIP_LIN : GX_LINEAR, GX_LINEAR, 0.f, + mNumMips - 1.f, 0.f, false, false, mNumMips > 1 ? GX_ANISO_4 : GX_ANISO_1); + } + + mCanLoadObj = true; +} + +void CTexture::Load(GXTexMapID tex, EClampMode clamp) const { + if (sLoadedTextures[tex] != this || mCanLoadObj) { + void* ptr = mARAMToken.GetMRAMSafe(); + CountMemory(); + + if (!mGraphicsPalette.null()) { + mGraphicsPalette->Load(); + mCanLoadPalette = false; + } + + mCanLoadObj = false; + + if (mClampMode != clamp) { + if (!mIsPowerOfTwo) { + mClampMode = kCM_Clamp; + } else { + mClampMode = clamp; + } + + GXInitTexObjWrapMode(&mTexObj, (GXTexWrapMode)mClampMode, (GXTexWrapMode)mClampMode); + } + + GXInitTexObjData(&mTexObj, ptr); + GXLoadTexObj(&mTexObj, tex); + sLoadedTextures[tex] = this; + mFrameAllocated = sCurrentFrameCount; + } +} +void CTexture::LoadMipLevel(int mip, GXTexMapID tex, EClampMode clamp) const { + char* ptr = (char*)mARAMToken.GetMRAMSafe(); + GXTexObj obj = mTexObj; + int width = GetWidth(); + int height = GetHeight(); + int offset = 0; + GXTexWrapMode wrap = (GXTexWrapMode)clamp; + for (int i = 0; i < mip; i++) { + int w = ROUND_UP_4(width); + int h = ROUND_UP_4(height); + offset += OSRoundUp32B(((mBitsPerPixel * (w * h)) / 8)); + width /= 2; + height /= 2; + } + + GXInitTexObj(&obj, ptr + offset, width, height, mNativeFormat, wrap, wrap, false); + GXInitTexObjLOD(&obj, GX_LINEAR, GX_LINEAR, 0.f, 0.f, 0.f, false, false, GX_ANISO_1); + if (!mGraphicsPalette.null()) { + mGraphicsPalette->Load(); + mCanLoadPalette = false; + } + + GXLoadTexObj(&obj, tex); + sLoadedTextures[tex] = nullptr; + mFrameAllocated = sCurrentFrameCount; +} + +void CTexture::UnloadBitmapData(CAssetId textureId) const { + if (!mBitmapReloader.null()) { + bool b = mBitmapReloader->GetX10(); + mBitmapReloader = rs_new CDumpedBitmapDataReloader(textureId, mMemoryAllocated, b); + } else { + bool complete = mARAMToken.GetStatus() == CARAMToken::kS_Zero || + mARAMToken.GetStatus() == CARAMToken::kS_Two || + mARAMToken.GetStatus() == CARAMToken::kS_Five; + + mARAMToken = CARAMToken(); + mBitmapReloader = rs_new CDumpedBitmapDataReloader(textureId, mMemoryAllocated, complete); + } +} + +bool CTexture::TryReloadBitmapData(CResFactory& factory) const { + if (mBitmapReloader.null()) { + return true; + } + + mBitmapReloader->BeginReloadBitmapData(factory); + uchar* ptr = (uchar*)mBitmapReloader->TryBuildReloadedBitmapData(factory); + if (ptr != nullptr) { + + bool bVar1 = mBitmapReloader->GetX10(); + mBitmapReloader = nullptr; + + mARAMToken.PostConstruct(ptr, mMemoryAllocated, 1); + const_cast< CTexture& >(*this).InitTextureObjects(); + + if (bVar1) { + LoadToARAM(); + } + + return true; + } + return false; +} + +int CTexture::fn_8030F088() const { + if (!mBitmapReloader.null()) { + if (mBitmapReloader->GetStatus() == 0) { + return 2; + } + + return 5; + } + + switch (mARAMToken.GetStatus()) { + case CARAMToken::kS_Zero: + return 1; + case CARAMToken::kS_One: + return 0; + case CARAMToken::kS_Five: + case CARAMToken::kS_Two: + return 3; + case CARAMToken::kS_Three: + case CARAMToken::kS_Four: + return 4; + default: + return -1; + } +} + +CTexture::CDumpedBitmapDataReloader::CDumpedBitmapDataReloader(uint unk1, uint unk2, bool unk3) +: x0_(0), x4_(unk1), x8_(0), xc_(unk2), x10_(unk3) {} + +void CTexture::CDumpedBitmapDataReloader::BeginReloadBitmapData(CResFactory& factory) { + if (x0_ != 0) { + return; + } + SObjectTag tag('TXTR', x4_); + x8_ = factory.ResourceSize(tag); + x18_ = (uchar*)CMemory::Alloc(x8_, IAllocator::kHI_RoundUpLen); + x14_ = factory.GetResLoader().LoadResourceAsync(tag, (char*)x18_.get()); + x0_ = 1; +} + +void* CTexture::CDumpedBitmapDataReloader::TryBuildReloadedBitmapData(CResFactory& factory) { + if (x14_->IsComplete()) { + x0_ = 2; + x14_ = nullptr; + + SObjectTag tag('TXTR', x4_); + rstl::single_ptr< CInputStream > buf = factory.LoadResourceFromMemorySync(tag, x18_.get()); + CInputStream* in = buf.get(); + ETexelFormat format = ETexelFormat(in->ReadInt32()); + const int w = in->ReadInt16(); + const int h = in->ReadInt16(); + const int numMips = in->ReadInt32(); + const int bitsPerPixel = TexelFormatBitsPerPixel(format); + + if (IsCITextureFormat(format)) { + CGraphicsPalette tmp(*in); + } + + int bufLen = 0; + for (int i = 0; i < numMips;) { + int width = ((w >> i) + 3) & ~3; + int height = ((h >> i) + 3) & ~3; + int page = (width * height); + i++; + bufLen += (page * bitsPerPixel) >> 3; + } + + void* ptr = CMemory::Alloc(xc_, IAllocator::kHI_RoundUpLen); + + for (int off = 0, len = 0; off < bufLen; off += len) { + len = bufLen - off; + if (len > 256) { + len = 256; + } + + in->Get((char*)ptr + off, len); + DCFlushRangeNoSync((char*)ptr + off, OSRoundUp32B(len)); + } + PPCSync(); + x18_ = nullptr; + return ptr; + } + return nullptr; +} + +bool CTexture::LoadToMRAM() const { + if (mARAMToken.GetStatus() == CARAMToken::kS_Six) { + return false; + } + + mFrameAllocated = sCurrentFrameCount; + CountMemory(); + return mARAMToken.LoadToMRAM(); +} + +bool CTexture::LoadToARAM() const { + if (mARAMToken.GetStatus() == CARAMToken::kS_Six) { + return false; + } + + if (mNoSwap) { + return false; + } + + if (mFrameAllocated < sCurrentFrameCount - 1) { + bool ret = mARAMToken.LoadToARAM(); + + if (mARAMToken.GetStatus() != CARAMToken::kS_One) { + UncountMemory(); + mCanLoadObj = true; + } + return ret; + } + return false; +} + +bool CTexture::IsARAMTransferInProgress() const { + if (mNoSwap) { + return false; + } + return mARAMToken.GetStatus() >= CARAMToken::kS_Two && + mARAMToken.GetStatus() <= CARAMToken::kS_Five; +} + +int CTexture::TexelFormatBitsPerPixel(ETexelFormat fmt) { + switch (fmt) { + case kTF_I4: + case kTF_C4: + case kTF_CMPR: + return 4; + case kTF_I8: + case kTF_IA4: + case kTF_C8: + return 8; + case kTF_IA8: + case kTF_C14X2: + case kTF_RGB565: + case kTF_RGB5A3: + return 16; + case kTF_RGBA8: + return 32; + default: + return 0; + } +} + +void CTexture::InitBitmapBuffers(ETexelFormat fmt, short width, short height, int mips) { + switch (fmt) { + case kTF_C4: + mNativeCIFormat = GX_TF_C4; + break; + case kTF_C8: + mNativeCIFormat = GX_TF_C8; + break; + case kTF_C14X2: + mNativeCIFormat = GX_TF_C14X2; + break; + case kTF_I4: + mNativeFormat = GX_TF_I4; + break; + case kTF_I8: + mNativeFormat = GX_TF_I8; + break; + case kTF_IA4: + mNativeFormat = GX_TF_IA4; + break; + case kTF_IA8: + mNativeFormat = GX_TF_IA8; + break; + case kTF_RGB565: + mNativeFormat = GX_TF_RGB565; + break; + case kTF_RGB5A3: + mNativeFormat = GX_TF_RGB5A3; + break; + case kTF_RGBA8: + mNativeFormat = GX_TF_RGBA8; + break; + case kTF_CMPR: + mNativeFormat = GX_TF_CMPR; + break; + default: + break; + } + + bool hasMips = mips > 1; + mMemoryAllocated = GXGetTexBufferSize( + width, height, HasPalette() ? mNativeCIFormat : mNativeFormat, hasMips, hasMips ? 11 : 0); + mARAMToken.PostConstruct(CMemory::Alloc(mMemoryAllocated, IAllocator::kHI_RoundUpLen), + mMemoryAllocated, 1); + CountMemory(); +} + +void CTexture::UnLock() { + mLocked = false; + CountMemory(); + DCFlushRange(mARAMToken.GetMRAMSafe(), OSRoundUp32B(mMemoryAllocated)); +} + +CFactoryFnReturn FTextureFactory(const SObjectTag& tag, CInputStream& in, + const CVParamTransfer& xfer) { + return rs_new CTexture(in, CTexture::kAM_Zero, CTexture::kBK_Zero); +} + +const void* CTexture::GetConstBitMapData(const int mip) const { + int offset = 0; + for (int i = 0; i < mip; i++) { + offset += (GetBitsPerPixel() >> 3) * ((GetWidth() >> i) * (GetHeight() >> i)); + } + + return (const uchar*)mARAMToken.GetMRAMSafe() + offset; +} + +void* CTexture::GetBitMapData(int mip) { return const_cast< void* >(GetConstBitMapData(mip)); } + +void CTexture::MangleMipmap(int mip) { + static const uint kMangleColors[4] = {0x000000FF, 0x0000FF00, 0x00FF0000, 0x0000FFFF}; + + uint color1 = *(uint*)((uchar*)kMangleColors + (((mip - 1) * 4) & 12)); + uint color2 = color1 >> 8; + uint color3 = color2 & 0xf800 | (color1 >> 3) & 0x1f | (color1 >> 5) & 0x7e0; -} + int width = GetWidth(); + int height = GetHeight(); + + int offset = 0; + for (int i = 0; i < mip; i++) { + offset += (width * height); + width /= 2; + height /= 2; + } -CTexture::~CTexture() { - UncountMemory(); + switch (GetTexelFormat()) { + case kTF_RGB565: { + ushort* ptr = (ushort*)mARAMToken.GetMRAMSafe(); + for (int i = 0; i < width * height; ++i) { + ptr[i + offset] = color3; + } + break; + } + case kTF_RGB5A3: { + ushort* ptr = (ushort*)mARAMToken.GetMRAMSafe(); + for (int i = 0; i < width * height; ++i) { + if (ptr[i + offset] & 0x8000) { + ptr[i + offset] = ptr[i + offset] & 0xf000 | (color1 >> 12) | 0xf00 | (color1 >> 4) & 0xf | color2 & 0xf0; + } else { + ptr[i + offset] = (color1 >> 9) | 0x7c00 | (color1 >> 6) & 0x3e0 | (color1 >> 3) & 0x1f | 0x8000; + } + } + break; + } + case kTF_CMPR: { + ushort* ptr = (ushort*)mARAMToken.GetMRAMSafe(); + + } + default: + break; + } } - void CTexture::MakeSwappable() const { if (!mNoSwap) { return; @@ -47,29 +491,29 @@ void CTexture::MakeSwappable() const { mNoSwap = false; } + void CTexture::CountMemory() const { if (mCounted) { return; } mCounted = true; - sTotalAllocatedMemory += mMemoryAllocated; + sTotalAllocatedMemory += mMemoryAllocated; } - void CTexture::UncountMemory() const { if (!mCounted) { return; } mCounted = false; - sTotalAllocatedMemory -= mMemoryAllocated; + sTotalAllocatedMemory -= mMemoryAllocated; } -void CTexture::InvalidateTexmap(GXTexMapID texmap) { - sLoadedTextures[texmap] = nullptr; -} +void CTexture::InvalidateTexmap(GXTexMapID texmap) { sLoadedTextures[texmap] = nullptr; } -void CTexture::sub_8030e10c() { - +void CTexture::fn_8030E10C() { + if (mARAMToken.GetStatus() != CARAMToken::kS_Six) { + CFrameDelayedKiller::fn_8036CC1C(true, mARAMToken.ForceSyncMRAM()); + } } diff --git a/src/Kyoto/Text/CStringTable.cpp b/src/Kyoto/Text/CStringTable.cpp index 1d8fc9a9..c2715143 100644 --- a/src/Kyoto/Text/CStringTable.cpp +++ b/src/Kyoto/Text/CStringTable.cpp @@ -42,10 +42,7 @@ const wchar_t* CStringTable::GetString(int idx) const { return reinterpret_cast< const wchar_t* >(x4_data.get() + offset); } -template <> -CFactoryFnReturn::CFactoryFnReturn(CStringTable* ptr) -: obj(TToken< CStringTable >::GetIObjObjectFor(rstl::auto_ptr< CStringTable >(ptr)).release()) {} - +#pragma inline_max_size(250) CFactoryFnReturn FStringTableFactory(const SObjectTag& tag, CInputStream& in, const CVParamTransfer& xfer) { return rs_new CStringTable(in); diff --git a/src/MetroidPrime/CProjectedShadow.cpp b/src/MetroidPrime/CProjectedShadow.cpp index 447bbe2f..2121eaef 100644 --- a/src/MetroidPrime/CProjectedShadow.cpp +++ b/src/MetroidPrime/CProjectedShadow.cpp @@ -17,7 +17,7 @@ CProjectedShadow::CProjectedShadow(int w, int h, uchar persistent) {} CProjectedShadow::~CProjectedShadow() { - x0_texture.sub_8030e10c(); + x0_texture.fn_8030E10C(); } void CProjectedShadow::ModelDrawCallback(const float*, const float*, const SShadowDrawContext*) { diff --git a/src/MetroidPrime/CWorldShadow.cpp b/src/MetroidPrime/CWorldShadow.cpp index 4d5c901c..2c2c11f7 100644 --- a/src/MetroidPrime/CWorldShadow.cpp +++ b/src/MetroidPrime/CWorldShadow.cpp @@ -30,7 +30,7 @@ CWorldShadow::CWorldShadow(uint w, uint h, bool rgba8) CWorldShadow::~CWorldShadow() { if (x0_texture.get()) - x0_texture->sub_8030e10c(); + x0_texture->fn_8030E10C(); } void CWorldShadow::BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid, uint lightIdx, @@ -151,8 +151,7 @@ void CWorldShadow::BuildLightShadowTexture(const CStateManager& mgr, TAreaId aid } GXSetTexCopyDst(x0_texture->GetWidth(), x0_texture->GetHeight(), fmt, true); static int unkInt = 0; - x0_texture->SetFlag1(true); - void * dest = x0_texture->GetBitMapData(0); + void * dest = x0_texture->Lock(); GXCopyTex(dest, true); x0_texture->UnLock();