From 82939548fb6eba7cbc9286078119778bb8d535c6 Mon Sep 17 00:00:00 2001 From: robojumper Date: Sun, 16 Mar 2025 16:35:42 +0100 Subject: [PATCH] TextureBuffer copied from OGWS with some changes --- config/SOUE01/splits.txt | 2 + config/SOUE01/symbols.txt | 24 ++-- configure.py | 2 +- include/egg/gfx/eggCapTexture.h | 4 + include/egg/gfx/eggCpuTexture.h | 4 +- include/egg/gfx/eggStateGX.h | 4 + include/egg/gfx/eggTextureBuffer.h | 56 +++++++- src/egg/gfx/eggTextureBuffer.cpp | 197 ++++++++++++++++++++++++++++- 8 files changed, 276 insertions(+), 17 deletions(-) diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 4cc3bc24..76c6db02 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -2307,6 +2307,8 @@ egg/gfx/eggStateGX.cpp: egg/gfx/eggTextureBuffer.cpp: .text start:0x804B53F0 end:0x804B59DC + .data start:0x8056F2B0 end:0x8056F2C0 + .sbss start:0x805768B8 end:0x805768D8 egg/audio/eggAudioArcPlayerMgr.cpp: .text start:0x804B59E0 end:0x804B641C diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index b9d8a2d0..d74986e8 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -26797,8 +26797,8 @@ initialize__Q23EGG13TextureBufferFUlPQ23EGG4Heap = .text:0x804B55E0; // type:fun getNotJoin__Q23EGG13TextureBufferFv = .text:0x804B5710; // type:function size:0x28 alloc__Q23EGG13TextureBufferFUl = .text:0x804B5740; // type:function size:0x164 alloc__Q23EGG13TextureBufferFUsUs9_GXTexFmt = .text:0x804B58B0; // type:function size:0xA4 -FUN_804b5960 = .text:0x804B5960; // type:function size:0x8 -FUN_804b5970 = .text:0x804B5970; // type:function size:0x8 +setIncludesHeader__Q23EGG13TextureBufferFb = .text:0x804B5960; // type:function size:0x8 +includesHeader__Q23EGG13TextureBufferFv = .text:0x804B5970; // type:function size:0x8 __dt__Q23EGG13TextureBufferFv = .text:0x804B5980; // type:function size:0x5C __ct__Q23EGG9ArcPlayerFPQ34nw4r3snd18SoundArchivePlayerPQ34nw4r3snd9SoundHeap = .text:0x804B59E0; // type:function size:0x88 __dt__Q23EGG9ArcPlayerFv = .text:0x804B5A70; // type:function size:0x74 @@ -37386,7 +37386,7 @@ sTVModeInfo__Q23EGG6Screen = .data:0x8056F230; // type:object size:0x24 data:2by EGG__Screen__vtable = .data:0x8056F254; // type:object size:0x14 __vt__Q23EGG16ScreenEffectBase = .data:0x8056F268; // type:object size:0xC lbl_8056F278 = .data:0x8056F278; // type:object size:0x38 -lbl_8056F2B0 = .data:0x8056F2B0; // type:object size:0x10 +__vt__Q23EGG13TextureBuffer = .data:0x8056F2B0; // type:object size:0x10 __vt__Q23EGG9ArcPlayer = .data:0x8056F2C0; // type:object size:0x5C __vt__Q23EGG14SimpleAudioMgr = .data:0x8056F320; // type:object size:0xA4 __vt__Q23EGG9IAudioMgr = .data:0x8056F3C8; // type:object size:0x10 scope:weak @@ -41184,16 +41184,16 @@ lbl_805768A0 = .sbss:0x805768A0; // type:object size:0x2 data:2byte lbl_805768A2 = .sbss:0x805768A2; // type:object size:0x2 data:2byte lbl_805768A4 = .sbss:0x805768A4; // type:object size:0x4 data:4byte lbl_805768A8 = .sbss:0x805768A8; // type:object size:0x4 data:4byte -lbl_805768AC = .sbss:0x805768AC; // type:object size:0x1 data:byte +sDefaultTexColor__Q23EGG7StateGX = .sbss:0x805768AC; // type:object size:0x1 data:byte s_flag__Q23EGG7StateGX = .sbss:0x805768B0; // type:object size:0x2 data:2byte s_commandFlag__Q23EGG7StateGX = .sbss:0x805768B2; // type:object size:0x6 data:2byte -lbl_805768B8 = .sbss:0x805768B8; // type:object size:0x4 data:4byte -lbl_805768BC = .sbss:0x805768BC; // type:object size:0x4 data:4byte -lbl_805768C0 = .sbss:0x805768C0; // type:object size:0x4 data:4byte -lbl_805768C4 = .sbss:0x805768C4; // type:object size:0x4 data:4byte -lbl_805768C8 = .sbss:0x805768C8; // type:object size:0x4 data:4byte -lbl_805768CC = .sbss:0x805768CC; // type:object size:0x4 data:4byte -lbl_805768D0 = .sbss:0x805768D0; // type:object size:0x8 data:byte +spHead__Q23EGG13TextureBuffer = .sbss:0x805768B8; // type:object size:0x4 data:4byte +spTailNotJoin__Q23EGG13TextureBuffer = .sbss:0x805768BC; // type:object size:0x4 data:4byte +spBufferAll__Q23EGG13TextureBuffer = .sbss:0x805768C0; // type:object size:0x4 data:4byte +sBufferAllSize__Q23EGG13TextureBuffer = .sbss:0x805768C4; // type:object size:0x4 data:4byte +sBufferSize__Q23EGG13TextureBuffer = .sbss:0x805768C8; // type:object size:0x4 data:4byte +sBufferRestSizeMin__Q23EGG13TextureBuffer = .sbss:0x805768CC; // type:object size:0x4 data:4byte +sIncludesHeader__Q23EGG13TextureBuffer = .sbss:0x805768D0; // type:object size:0x1 data:byte sAudioRmtSpeakerConnectCanncelSw__Q23EGG18AudioRmtSpeakerMgr = .sbss:0x805768D8; // type:object size:0x1 data:byte mTaskFinishCount__Q23EGG18AudioRmtSpeakerMgr = .sbss:0x805768DC; // type:object size:0x4 data:4byte mTaskRequestCount__Q23EGG18AudioRmtSpeakerMgr = .sbss:0x805768E0; // type:object size:0x4 data:4byte @@ -49814,7 +49814,7 @@ lbl_806750A0 = .bss:0x806750A0; // type:object size:0x20 lbl_806750C0 = .bss:0x806750C0; // type:object size:0xA8 data:4byte lbl_80675168 = .bss:0x80675168; // type:object size:0x18 lbl_80675180 = .bss:0x80675180; // type:object size:0x10 -lbl_80675190 = .bss:0x80675190; // type:object size:0x200 data:4byte +spBufferTable__Q23EGG13TextureBuffer = .bss:0x80675190; // type:object size:0x200 data:4byte sTasks__Q23EGG18AudioRmtSpeakerMgr = .bss:0x80675390; // type:object size:0xF0 sMoveParamMgr__Q23EGG12AudioUtility = .bss:0x80675480; // type:object size:0xC lbl_80675490 = .bss:0x80675490; // type:object size:0x10 diff --git a/configure.py b/configure.py index e6d9ba62..80c0611a 100644 --- a/configure.py +++ b/configure.py @@ -901,7 +901,7 @@ config.libs = [ Object(NonMatching, "egg/gfx/eggScreenEffectBlur.cpp"), # Unknown Guess Object(NonMatching, "egg/gfx/eggStateEfb.cpp"), Object(NonMatching, "egg/gfx/eggStateGX.cpp"), - Object(NonMatching, "egg/gfx/eggTextureBuffer.cpp"), + Object(Matching, "egg/gfx/eggTextureBuffer.cpp"), ], ), EGGLib( diff --git a/include/egg/gfx/eggCapTexture.h b/include/egg/gfx/eggCapTexture.h index 3cd05c55..cedc5ce1 100644 --- a/include/egg/gfx/eggCapTexture.h +++ b/include/egg/gfx/eggCapTexture.h @@ -27,6 +27,10 @@ public: } } + void setClearColor(const GXColor &clr) { + mClearColor = clr; + } + private: /* 0x18 */ u8 mCapFlags; /* 0x19 */ GXColor mClearColor; diff --git a/include/egg/gfx/eggCpuTexture.h b/include/egg/gfx/eggCpuTexture.h index 74d10326..2fac0978 100644 --- a/include/egg/gfx/eggCpuTexture.h +++ b/include/egg/gfx/eggCpuTexture.h @@ -132,8 +132,8 @@ public: return (Header *)((u8 *)dataPtr - sizeof(Header)); } - char *getBuffer() const { - return mpBuffer; + void *getBuffer() const { + return dataPtr; } void setBuffer(void *pBuffer); diff --git a/include/egg/gfx/eggStateGX.h b/include/egg/gfx/eggStateGX.h index fe712a3e..e575dcc8 100644 --- a/include/egg/gfx/eggStateGX.h +++ b/include/egg/gfx/eggStateGX.h @@ -2,6 +2,7 @@ #define EGG_STATE_GX_H #include "common.h" +#include "rvl/GX/GXTypes.h" #include "rvl/GX.h" // IWYU pragma: export namespace EGG { @@ -54,6 +55,8 @@ public: bool old; }; + static GXColor& getDefaultTexColor() { return sDefaultTexColor; } + static void initialize(u16, u16, GXColor, GXPixelFmt); static void frameInit(); static void textureInit(); // Guess for 804b4810 @@ -93,6 +96,7 @@ public: static u16 s_commandFlag; static u16 s_flag; + static GXColor sDefaultTexColor; }; } // namespace EGG diff --git a/include/egg/gfx/eggTextureBuffer.h b/include/egg/gfx/eggTextureBuffer.h index bf648ebb..3328a4ad 100644 --- a/include/egg/gfx/eggTextureBuffer.h +++ b/include/egg/gfx/eggTextureBuffer.h @@ -1,6 +1,60 @@ #ifndef EGG_TEXTURE_BUFFER_H #define EGG_TEXTURE_BUFFER_H -namespace EGG {} // namespace EGG +#include "egg/gfx/eggCapTexture.h" +#include "rvl/GX/GXTypes.h" + +namespace EGG { + +class TextureBuffer : public CapTexture { +public: + enum EBufferState { + STATE_FREE, + STATE_ALLOCED + }; + + static void initialize(u32, Heap *); + static TextureBuffer *getNotJoin(); + + static void append(TextureBuffer *buf) { + if (spTailNotJoin != NULL) { + spTailNotJoin->mpNext = buf; + } + + buf->mpPrev = spTailNotJoin; + buf->mpNext = NULL; + + spTailNotJoin = buf; + } + + TextureBuffer(); + virtual ~TextureBuffer() {} // at 0x8 + virtual void configure(); // at 0xC + + void alloc(u32 size); + static TextureBuffer *alloc(u16 w, u16 h, GXTexFmt fmt); + void free(); + +private: + static bool includesHeader(); + static void setIncludesHeader(bool); + + u32 mSize; // at 0x2C + EBufferState mState; // at 0x30 + TextureBuffer *mpNext; // at 0x34 + TextureBuffer *mpPrev; // at 0x38 + + static const int NUM_BUFFERS = 128; + static TextureBuffer *spHead; + static TextureBuffer *spTailNotJoin; + static char *spBufferAll; + static u32 sBufferAllSize; + static u32 sBufferSize; + static u32 sBufferRestSizeMin; + static bool sIncludesHeader; + static TextureBuffer *spBufferTable[NUM_BUFFERS]; +}; + +} // namespace EGG #endif diff --git a/src/egg/gfx/eggTextureBuffer.cpp b/src/egg/gfx/eggTextureBuffer.cpp index ed1b41e1..d8489705 100644 --- a/src/egg/gfx/eggTextureBuffer.cpp +++ b/src/egg/gfx/eggTextureBuffer.cpp @@ -1,3 +1,198 @@ #include "egg/gfx/eggTextureBuffer.h" -namespace EGG {} // namespace EGG +#include "common.h" +#include "egg/gfx/eggCpuTexture.h" +#include "egg/gfx/eggStateGX.h" +#include "rvl/GX/GXTexture.h" +#include "rvl/GX/GXTypes.h" + +namespace EGG { + +TextureBuffer::TextureBuffer() : mSize(0), mState(STATE_FREE), mpNext(nullptr), mpPrev(nullptr) {} + +void TextureBuffer::configure() { + CapTexture::configure(); + setClearColor(StateGX::getDefaultTexColor()); + setWrap(GX_CLAMP, GX_CLAMP); + setFilt(GX_LINEAR, GX_LINEAR); + setPixModeSync(true); +} + +// Allow buffer to be reclaimed +void TextureBuffer::free() { + mState = STATE_FREE; + sBufferSize += mSize; + + // Check if previous buffer is reclaimable + if (mpPrev != nullptr && mpPrev->mState == STATE_FREE) { + // Merge with previous buffer + mSize += mpPrev->mSize; + setBuffer((u8 *)getBuffer() - mpPrev->mSize); + + // Append reusable buffer + TextureBuffer *beforeAppend = mpPrev->mpPrev; + append(mpPrev); + + // Repair mpPrev link + mpPrev = beforeAppend; + if (beforeAppend != nullptr) { + beforeAppend->mpNext = this; + } else { + spHead = this; + } + } + + // Check if next buffer is reclaimable + if (mpNext != nullptr && mpNext->mState == STATE_FREE) { + // Merge with next buffer + mSize += mpNext->mSize; + + // Append reusable buffer + TextureBuffer *afterAppend = mpNext->mpNext; + append(mpNext); + + // Repair mpNext link + mpNext = afterAppend; + if (afterAppend != nullptr) { + afterAppend->mpPrev = this; + } + } +} + +// Alloc list buffer +void TextureBuffer::initialize(u32 size, Heap *heap_) { + Heap *heap = heap_ == nullptr ? Heap::getCurrentHeap() : heap_; + if (includesHeader()) { + size += 0x20; + } + + sBufferAllSize = size; + spBufferAll = new (heap, 32) char[size]; + + if (includesHeader()) { + spBufferAll += 0x20; + } + + sBufferSize = size; + sBufferRestSizeMin = size; + spTailNotJoin = nullptr; + for (int i = 0; i < NUM_BUFFERS; i++) { + spBufferTable[i] = new TextureBuffer(); + spBufferTable[i]->configure(); + append(spBufferTable[i]); + } + + // Initialize head + spHead = getNotJoin(); + spHead->mState = STATE_FREE; + spHead->mSize = size; + spHead->setBuffer(spBufferAll); +} + +// Remove and return buffer at list end +TextureBuffer *TextureBuffer::getNotJoin() { + TextureBuffer *p_buffer = spTailNotJoin; + + // Move list tail back + spTailNotJoin = spTailNotJoin->mpPrev; + if (spTailNotJoin != nullptr) { + spTailNotJoin->mpNext = nullptr; + } + + // Pop old tail + p_buffer->mpPrev = nullptr; + return p_buffer; +} + +// Attempt to alloc buffer of specified size +void TextureBuffer::alloc(u32 size) { + size = ROUND_UP(size, 0x20); + + sBufferSize -= size; + if (sBufferSize < sBufferRestSizeMin) { + sBufferRestSizeMin = sBufferSize; + } + + // Try to find a free buffer with at least the requested size + for (TextureBuffer *p_list = spHead; p_list != nullptr; p_list = p_list->mpNext) { + if (p_list->mState == STATE_FREE && p_list->mSize >= size) { + // Assign free buffer data to new buffer + mState = STATE_ALLOCED; + mSize = size; + + u8 *buffer = (u8 *)p_list->getBuffer(); + if (includesHeader()) { + setBuffer(buffer); + if (buffer != nullptr) { + setFlag(HAS_HEADER); + } + } else { + setBuffer(buffer); + } + + // Prepend new buffer before old buffer + mpNext = p_list; + TextureBuffer *oldPrev = p_list->mpPrev; + mpPrev = oldPrev; + + // Fix this->prev link + if (oldPrev != nullptr) { + oldPrev->mpNext = this; + } else { + // nullptr prev buffer must be list head + + spHead = this; + } + + // Remove requested size from old buffer + p_list->mSize -= size; + + // Free old buffer if now empty + if (p_list->mSize == 0) { + if (p_list->mpNext != nullptr) { + p_list->mpNext->mpPrev = this; + } + mpNext = p_list->mpNext; + append(p_list); + } + // Adjust old buffer by requested size + else { + p_list->setBuffer(buffer + size); + p_list->mpPrev = this; + } + + return; + } + } +} + +TextureBuffer *TextureBuffer::alloc(u16 width, u16 height, GXTexFmt fmt) { + if (width == 0 || height == 0) { + return nullptr; + } + TextureBuffer *tex = getNotJoin(); + tex->setWidth(width); + tex->setHeight(height); + tex->setFormat(fmt); + tex->configure(); + tex->alloc(GXGetTexBufferSize(tex->getWidth(), tex->getHeight(), tex->getFormat(), false, 1)); + return tex; +} + +void TextureBuffer::setIncludesHeader(bool b) { + sIncludesHeader = b; +} + +bool TextureBuffer::includesHeader() { + return sIncludesHeader; +} + +TextureBuffer *TextureBuffer::spHead; +TextureBuffer *TextureBuffer::spTailNotJoin; +char *TextureBuffer::spBufferAll; +u32 TextureBuffer::sBufferAllSize; +u32 TextureBuffer::sBufferSize; +u32 TextureBuffer::sBufferRestSizeMin; +bool TextureBuffer::sIncludesHeader; + +} // namespace EGG