From a321031cb2683eec3ace7918a30a6d45db9cdd04 Mon Sep 17 00:00:00 2001 From: Noah McQueen <67965519+Yotona@users.noreply.github.com> Date: Sat, 16 Sep 2023 08:23:36 -0600 Subject: [PATCH] Progress on J2DPane, JUTResFont (#39) --- include/JSystem/J2DGraph/J2DPane.h | 39 +-- include/JSystem/J2DGraph/J2DTextBox.h | 63 ++++ include/JSystem/JUtility/JUTFont.h | 26 +- include/JSystem/JUtility/JUTResFont.h | 73 +++-- src/JSystem/J2DGraph/J2DPane.cpp | 25 +- src/JSystem/JUtility/JUTResFont.cpp | 411 ++++++++++++++++++++++++-- 6 files changed, 508 insertions(+), 129 deletions(-) create mode 100644 include/JSystem/J2DGraph/J2DTextBox.h diff --git a/include/JSystem/J2DGraph/J2DPane.h b/include/JSystem/J2DGraph/J2DPane.h index e39ce88aa..654a80942 100644 --- a/include/JSystem/J2DGraph/J2DPane.h +++ b/include/JSystem/J2DGraph/J2DPane.h @@ -4,23 +4,10 @@ #include "JSystem/JGeometry.h" #include "JSystem/JSupport/JSUList.h" #include "SSystem/SComponent/c_xyz.h" -#include "dolphin/gx/GXEnum.h" #include "dolphin/mtx/mtx.h" -class J2DAnmBase; -class J2DAnmColor; -class J2DAnmTransform; -class J2DAnmTevRegKey; -class J2DAnmTextureSRTKey; -class J2DAnmVisibilityFull; -class J2DAnmVtxColor; class J2DGrafContext; -class J2DScreen; -class J2DAnmTexPattern; -class JKRArchive; class JSURandomInputStream; -struct ResFONT; -struct ResTIMG; enum J2DRotateAxis { /* 0x78 */ ROTATE_X = 'x', @@ -46,44 +33,26 @@ public: J2DPane(); J2DPane(J2DPane*, bool, u32, const JGeometry::TBox2&); J2DPane(u32, const JGeometry::TBox2&); - J2DPane(J2DPane* other, JSURandomInputStream* stream, u8 arg3); J2DPane(J2DPane*, JSURandomInputStream*); void initiate(); - void initialize(J2DPane*, bool, u64, const JGeometry::TBox2&); - void initialize(u64 tag, const JGeometry::TBox2& dim); void makePaneStream(J2DPane* other, JSURandomInputStream* stream); - void changeUseTrans(J2DPane* other); - bool appendChild(J2DPane* child); bool insertChild(J2DPane* before, J2DPane* child); void draw(f32 a1, f32 a2, const J2DGrafContext* ctx, bool a4); - void place(const JGeometry::TBox2& dim); - JGeometry::TBox2& getBounds(); - void rotate(f32 offsetX, f32 offsetY, J2DRotateAxis axis, f32 angle); - void rotate(f32 angle); void clip(const JGeometry::TBox2& bounds); void setBasePosition(J2DBasePosition position); - void setInfluencedAlpha(bool arg1, bool arg2); - JGeometry::TVec3 getGlbVtx(u8 arg1) const; - J2DPane* getFirstChildPane(); - J2DPane* getNextChildPane(); - J2DPane* getParentPane(); - void makePaneExStream(J2DPane* other, JSURandomInputStream* stream); - void* getPointer(JSURandomInputStream* stream, u32 size, JKRArchive* archive); - void animationTransform(); - void updateTransform(const J2DAnmTransform* transform); virtual ~J2DPane(); + virtual u16 getTypeID() { return 16; } virtual void move(f32 x, f32 y); virtual void add(f32 x, f32 y); virtual void resize(f32 x, f32 y); virtual bool setConnectParent(bool connected); - virtual void update(); virtual void calcMtx(); + virtual void update(); virtual void drawSelf(f32 arg1, f32 arg2); virtual void drawSelf(f32 arg1, f32 arg2, Mtx* mtx){}; - virtual void makeMatrix(f32, f32); virtual J2DPane* search(u32 tag); - virtual u16 getTypeID() { return 16; } + virtual void makeMatrix(f32, f32); JSUTree* getFirstChild() { return mPaneTree.getFirstChild(); } JSUTree* getEndChild() { return mPaneTree.getEndChild(); } @@ -100,7 +69,7 @@ public: /* 0x6C */ Mtx mDrawMtx; /* 0x9C */ cXy mBasePosition; /* 0xA4 */ f32 mRotation; - /* 0xA8 */ u8 mRotationAxis; + /* 0xA8 */ s8 mRotationAxis; /* 0xA9 */ u8 m2DBasePosition; /* 0xAA */ bool mVisible; /* 0xAB */ u8 mCullMode; diff --git a/include/JSystem/J2DGraph/J2DTextBox.h b/include/JSystem/J2DGraph/J2DTextBox.h new file mode 100644 index 000000000..571fae458 --- /dev/null +++ b/include/JSystem/J2DGraph/J2DTextBox.h @@ -0,0 +1,63 @@ +#ifndef J2DTEXTBOX_H +#define J2DTEXTBOX_H + +#include "JSystem/J2DGraph/J2DPane.h" +#include "JSystem/JKernel/JKRArchive.h" +#include "JSystem/JUtility/JUTResFont.h" + +enum J2DTextBoxHBinding { + /* 0x0 */ HBIND_CENTER, + /* 0x1 */ HBIND_RIGHT, + /* 0x2 */ HBIND_LEFT +}; + +enum J2DTextBoxVBinding { + /* 0x0 */ VBIND_CENTER, + /* 0x1 */ VBIND_BOTTOM, + /* 0x2 */ VBIND_TOP +}; + +struct J2DTbxBlockHeader { + /* 0x00 */ u32 mMagic; + /* 0x04 */ s32 mSize; +}; + +class J2DTextBox : public J2DPane { +public: + J2DTextBox(const char*, const char*); + J2DTextBox(J2DPane*, JSURandomInputStream*); + J2DTextBox(u32, const JGeometry::TBox2&, const ResFONT*, const char*, J2DTextBoxHBinding, + J2DTextBoxVBinding); + + void initiate(const ResFONT*, const char*, J2DTextBoxHBinding, J2DTextBoxVBinding); + void setFont(JUTFont*); + void draw(f32, f32, f32, J2DTextBoxHBinding); + char* getStringPtr() const; + s32 setString(const char*, ...); + + virtual ~J2DTextBox(); + virtual bool setConnectParent(bool); + virtual void drawSelf(f32, f32); + virtual void drawSelf(f32, f32, Mtx*); + virtual void resize(f32, f32); + virtual u16 getTypeID() { return 19; }; + +private: + /* 0xCC */ JUTResFont* mpFont; + /* 0xD0 */ JUtility::TColor mGradientFirst; + /* 0xD4 */ JUtility::TColor mGradientSecond; + /* 0xD8 */ f32 field_0xd8; + /* 0xDC */ f32 field_0xdc; + /* 0xD0 */ f32 field_0xe0; + /* 0xE4 */ f32 mFontLeading; + /* 0xE8 */ f32 mFontWidth; + /* 0xEC */ f32 mFontHeight; + /* 0xF0 */ char* mStringPtr; + /* 0xF4 */ JUtility::TColor mTextColor; + /* 0xF8 */ JUtility::TColor mTextBGColor; + /* 0xFC */ u8 mBindingH; + /* 0xFD */ u8 mBindingV; + /* 0xFE */ bool mTextFontOwned; +}; // Size: 0x100 + +#endif /* J2DTEXTBOX_H */ \ No newline at end of file diff --git a/include/JSystem/JUtility/JUTFont.h b/include/JSystem/JUtility/JUTFont.h index b6cd3d90d..e91b9ed3a 100644 --- a/include/JSystem/JUtility/JUTFont.h +++ b/include/JSystem/JUtility/JUTFont.h @@ -4,10 +4,16 @@ #include "JSystem/JUtility/TColor.h" #include "MSL_C/string.h" +struct BlockHeader { + const BlockHeader* getNext() const { + return reinterpret_cast(reinterpret_cast(this) + size); + } + u32 magic; + u32 size; +}; + struct ResFONT { - struct INF1 { - /* 0x00 */ u32 magic; - /* 0x04 */ u32 size; + struct INF1 : BlockHeader { /* 0x08 */ u16 fontType; /* 0x0A */ u16 ascent; /* 0x0C */ u16 descent; @@ -16,17 +22,13 @@ struct ResFONT { /* 0x12 */ u16 defaultCode; }; - struct WID1 { - /* 0x00 */ u32 magic; - /* 0x04 */ u32 size; + struct WID1 : BlockHeader { /* 0x08 */ u16 startCode; /* 0x0A */ u16 endCode; /* 0x0C */ u8 mChunkNum[4]; }; - struct MAP1 { - /* 0x00 */ u32 magic; - /* 0x04 */ u32 size; + struct MAP1 : BlockHeader { /* 0x08 */ u16 mappingMethod; /* 0x0A */ u16 startCode; /* 0x0C */ u16 endCode; @@ -34,9 +36,7 @@ struct ResFONT { /* 0x10 */ u16 mLeading; }; - struct GLY1 { - /* 0x00 */ u32 magic; - /* 0x04 */ u32 size; + struct GLY1 : BlockHeader { /* 0x08 */ u16 startCode; /* 0x0A */ u16 endCode; /* 0x0C */ u16 cellWidth; @@ -80,7 +80,7 @@ public: /* 0x30 */ virtual int getCellWidth() const; /* 0x34 */ virtual s32 getCellHeight() const; /* 0x38 */ virtual int getFontType() const = 0; - /* 0x3C */ virtual ResFONT* getResFont() const = 0; + /* 0x3C */ virtual const ResFONT* getResFont() = 0; /* 0x40 */ virtual bool isLeadByte(int a1) const = 0; static bool isLeadByte_1Byte(int b); diff --git a/include/JSystem/JUtility/JUTResFont.h b/include/JSystem/JUtility/JUTResFont.h index 4e5a05794..c8200136e 100644 --- a/include/JSystem/JUtility/JUTResFont.h +++ b/include/JSystem/JUtility/JUTResFont.h @@ -8,42 +8,36 @@ class JKRHeap; typedef bool (*IsLeadByte_func)(int); -struct BlockHeader { - const BlockHeader* getNext() const { return reinterpret_cast(reinterpret_cast(this) + size); } - u32 magic; - u32 size; -}; - class JUTResFont : public JUTFont { public: - /* 802DF000 */ virtual ~JUTResFont(); - /* 802DF48C */ virtual void setGX(); - /* 802DF584 */ virtual void setGX(JUtility::TColor, JUtility::TColor); - /* 802DF7C4 */ virtual f32 drawChar_scale(f32, f32, f32, f32, int, bool); - /* 802DDFEC */ virtual int getLeading() const; - /* 802DE004 */ virtual s32 getAscent() const; - /* 802DE010 */ virtual s32 getDescent() const; - /* 802DE01C */ virtual s32 getHeight() const; - /* 802DDFF8 */ virtual s32 getWidth() const; - /* 802DFC64 */ virtual void getWidthEntry(int, JUTFont::TWidth*) const; - /* 802DFD0C */ virtual int getCellWidth() const; - /* 802DFD58 */ virtual s32 getCellHeight() const; - /* 802DDFE0 */ virtual int getFontType() const; - /* 802DDFD8 */ virtual ResFONT* getResFont() const; - /* 802DFDA4 */ virtual bool isLeadByte(int) const; - /* 802DFF60 */ virtual void loadImage(int, _GXTexMapID); - /* 802DF344 */ virtual void setBlock(); + virtual ~JUTResFont(); + virtual void setGX(); + virtual void setGX(JUtility::TColor, JUtility::TColor); + virtual f32 drawChar_scale(f32, f32, f32, f32, int, bool); + virtual int getLeading() const { return mInfoBlock->leading; } + virtual s32 getAscent() const { return mInfoBlock->ascent; } + virtual s32 getDescent() const { return mInfoBlock->descent; } + virtual s32 getHeight() const { return getAscent() + getDescent(); } + virtual s32 getWidth() const { return mInfoBlock->width; } + virtual void getWidthEntry(int, JUTFont::TWidth*) const; + virtual int getCellWidth() const; + virtual s32 getCellHeight() const; + virtual int getFontType() const { return mInfoBlock->fontType; } + virtual const ResFONT* getResFont() { return mResFont; } + virtual bool isLeadByte(int) const; + virtual void loadImage(int, _GXTexMapID); + virtual void setBlock(); - /* 802DEF94 */ JUTResFont(ResFONT const*, JKRHeap*); - /* 802DEF48 */ JUTResFont(); - /* 802DF08C */ void deleteMemBlocks_ResFont(); - /* 802DF0B0 */ void initialize_state(); - /* 802DF0DC */ bool initiate(ResFONT const*, JKRHeap*); - /* 802DF13C */ bool protected_initiate(ResFONT const*, JKRHeap*); - /* 802DF248 */ void countBlock(); - /* 802DFBE8 */ void loadFont(int, _GXTexMapID, JUTFont::TWidth*); - /* 802DFDD8 */ int getFontCode(int) const; - /* 802E00C4 */ int convertSjis(int, u16*) const; + JUTResFont(ResFONT const*, JKRHeap*); + JUTResFont(); + void deleteMemBlocks_ResFont(); + void initialize_state(); + bool initiate(ResFONT const*, JKRHeap*); + bool protected_initiate(ResFONT const*, JKRHeap*); + void countBlock(); + void loadFont(int, _GXTexMapID, JUTFont::TWidth*); + int getFontCode(int) const; + int convertSjis(int, u16*) const; inline void delete_and_initialize() { deleteMemBlocks_ResFont(); @@ -52,20 +46,19 @@ public: static IsLeadByte_func const saoAboutEncoding_[3]; - // some types uncertain, may need to be fixed /* 0x1C */ int mWidth; /* 0x20 */ int mHeight; /* 0x24 */ _GXTexObj field_0x24; - /* 0x44 */ int field_0x44; + /* 0x44 */ int mTexPageIdx; /* 0x48 */ const ResFONT* mResFont; - /* 0x4C */ ResFONT::INF1* mInf1Ptr; - /* 0x50 */ void** mMemBlocks; + /* 0x4C */ ResFONT::INF1* mInfoBlock; + /* 0x50 */ void** mpMemBlocks; /* 0x54 */ ResFONT::WID1** mpWidthBlocks; /* 0x58 */ ResFONT::GLY1** mpGlyphBlocks; /* 0x5C */ ResFONT::MAP1** mpMapBlocks; - /* 0x60 */ u16 mWid1BlockNum; - /* 0x62 */ u16 mGly1BlockNum; - /* 0x64 */ u16 mMap1BlockNum; + /* 0x60 */ u16 mWidthBlockNum; + /* 0x62 */ u16 mGlyphBlockNum; + /* 0x64 */ u16 mMapBlockNum; /* 0x66 */ u16 field_0x66; /* 0x68 */ u16 mMaxCode; /* 0x6C */ IsLeadByte_func* mIsLeadByte; diff --git a/src/JSystem/J2DGraph/J2DPane.cpp b/src/JSystem/J2DGraph/J2DPane.cpp index 09f060911..66b9a60d9 100644 --- a/src/JSystem/J2DGraph/J2DPane.cpp +++ b/src/JSystem/J2DGraph/J2DPane.cpp @@ -5,6 +5,7 @@ #include "JSystem/J2DGraph/J2DPane.h" #include "JSystem/JSupport/JSURandomInputStream.h" +#include "dolphin/gx/GXEnum.h" #include "dolphin/types.h" /* 802CF8F4-802CF984 .text __ct__7J2DPaneFv */ @@ -180,8 +181,18 @@ J2DPane* J2DPane::search(u32 tag) { } /* 802D0714-802D0800 .text makeMatrix__7J2DPaneFff */ -void J2DPane::makeMatrix(float, float) { - /* Nonmatching */ +void J2DPane::makeMatrix(f32 x, f32 y) { + Mtx stack1, stack2, stack3; + if (mRotation != 0.0f) { + MTXTrans(stack1, -mBasePosition.x, -mBasePosition.y, 0.0f); + f32 rot = mRotationAxis == ROTATE_Z ? -mRotation : mRotation; + MTXRotRad(stack2, mRotationAxis, rot * 0.017445329f); + MTXTrans(stack3, mBasePosition.x + x, mBasePosition.y + y, 0.0f); + MTXConcat(stack2, stack1, mMtx); + MTXConcat(stack3, mMtx, mMtx); + } else { + MTXTrans(mMtx, x, y, 0.0f); + } } /* 802D0800-802D08D8 .text setBasePosition__7J2DPaneF15J2DBasePosition */ @@ -209,13 +220,3 @@ void J2DPane::setBasePosition(J2DBasePosition pos) { mRotationAxis = ROTATE_Z; calcMtx(); } - -/* 802D08D8-802D08DC .text drawSelf__7J2DPaneFffPA3_A4_f */ -// void J2DPane::drawSelf(float, float, float (*)[3][4]) { -// /* Nonmatching */ -// } - -/* 802D08DC-802D08E4 .text getTypeID__7J2DPaneFv */ -// u16 J2DPane::getTypeID() { -// /* Nonmatching */ -// } diff --git a/src/JSystem/JUtility/JUTResFont.cpp b/src/JSystem/JUtility/JUTResFont.cpp index c9cb9e305..135861bce 100644 --- a/src/JSystem/JUtility/JUTResFont.cpp +++ b/src/JSystem/JUtility/JUTResFont.cpp @@ -4,104 +4,457 @@ // #include "JSystem/JUtility/JUTResFont.h" +#include "JSystem/JKernel/JKRHeap.h" +#include "JSystem/JUtility/JUTAssert.h" +#include "JSystem/JUtility/JUTConsole.h" +#include "dolphin/gx/GX.h" #include "dolphin/types.h" +// Only used for an assert +#define suAboutEncoding_ 3 + +IsLeadByte_func const JUTResFont::saoAboutEncoding_[3] = { + isLeadByte_1Byte, + isLeadByte_2Byte, + isLeadByte_ShiftJIS, +}; + /* 802C2044-802C2090 .text __ct__10JUTResFontFv */ JUTResFont::JUTResFont() { - /* Nonmatching */ + initialize_state(); + JUTFont::initialize_state(); } /* 802C2090-802C20F4 .text __ct__10JUTResFontFPC7ResFONTP7JKRHeap */ -JUTResFont::JUTResFont(const ResFONT*, JKRHeap*) { - /* Nonmatching */ +JUTResFont::JUTResFont(const ResFONT* pFont, JKRHeap* pHeap) { + initialize_state(); + initiate(pFont, pHeap); } /* 802C20F4-802C2180 .text __dt__10JUTResFontFv */ JUTResFont::~JUTResFont() { - /* Nonmatching */ + if (mValid) { + delete_and_initialize(); + JUTFont::initialize_state(); + } } /* 802C2180-802C21A4 .text deleteMemBlocks_ResFont__10JUTResFontFv */ void JUTResFont::deleteMemBlocks_ResFont() { - /* Nonmatching */ + delete[] mpMemBlocks; } /* 802C21A4-802C21D0 .text initialize_state__10JUTResFontFv */ void JUTResFont::initialize_state() { - /* Nonmatching */ + mResFont = NULL; + mpMemBlocks = NULL; + mpWidthBlocks = NULL; + mpGlyphBlocks = NULL; + mpMapBlocks = NULL; + mWidth = 0; + mHeight = 0; + mTexPageIdx = -1; } /* 802C21D0-802C2230 .text initiate__10JUTResFontFPC7ResFONTP7JKRHeap */ -void JUTResFont::initiate(const ResFONT*, JKRHeap*) { - /* Nonmatching */ +bool JUTResFont::initiate(const ResFONT* pFont, JKRHeap* pHeap) { + u8 initiated = protected_initiate(pFont, pHeap); + if (!initiated) { + delete_and_initialize(); + JUTFont::initialize_state(); + mValid = false; + return false; + } + return true; } /* 802C2230-802C233C .text protected_initiate__10JUTResFontFPC7ResFONTP7JKRHeap */ -void JUTResFont::protected_initiate(const ResFONT*, JKRHeap*) { - /* Nonmatching */ +bool JUTResFont::protected_initiate(const ResFONT* pFont, JKRHeap* pHeap) { + delete_and_initialize(); + JUTFont::initialize_state(); + if (pFont == NULL) { + return false; + } + mResFont = pFont; + mValid = true; + countBlock(); + + u32 blockNum = mWidthBlockNum + mGlyphBlockNum + mMapBlockNum; + mpMemBlocks = new (pHeap, 0) void*[blockNum]; + + void** block = mpMemBlocks; + + if (block == NULL) { + return false; + } else { + if (mWidthBlockNum != 0) { + mpWidthBlocks = (ResFONT::WID1**)block; + block += mWidthBlockNum; + } + if (mGlyphBlockNum != 0) { + mpGlyphBlocks = (ResFONT::GLY1**)block; + block += mGlyphBlockNum; + } + if (mMapBlockNum != 0) { + mpMapBlocks = (ResFONT::MAP1**)block; + } + setBlock(); + return true; + } } /* 802C233C-802C2438 .text countBlock__10JUTResFontFv */ void JUTResFont::countBlock() { - /* Nonmatching */ + mWidthBlockNum = 0; + mGlyphBlockNum = 0; + mMapBlockNum = 0; + + const BlockHeader* header = (BlockHeader*)mResFont->data; + for (u32 i = 0; i < mResFont->numBlocks; i++, header = header->getNext()) { + switch (header->magic) { + case 'WID1': + mWidthBlockNum++; + break; + case 'GLY1': + mGlyphBlockNum++; + break; + case 'MAP1': + mMapBlockNum++; + break; + case 'INF1': + break; + default: + JUTReportConsole("JUTResFont: Unknown data block\n"); + } + } } /* 802C2438-802C25C0 .text setBlock__10JUTResFontFv */ void JUTResFont::setBlock() { - /* Nonmatching */ + int widthNum = 0; + int glyphNum = 0; + int mapNum = 0; + mMaxCode = -1; + + const BlockHeader* header = (BlockHeader*)mResFont->data; + for (u32 i = 0; i < mResFont->numBlocks; i++, header = header->getNext()) { + switch (header->magic) { + case 'INF1': + mInfoBlock = (ResFONT::INF1*)header; + u32 u = mInfoBlock->fontType; + JUT_ASSERT(0xF3, u < suAboutEncoding_) + mIsLeadByte = (IsLeadByte_func*)&saoAboutEncoding_[u]; + break; + case 'WID1': + mpWidthBlocks[widthNum] = (ResFONT::WID1*)header; + widthNum++; + break; + case 'GLY1': + mpGlyphBlocks[glyphNum] = (ResFONT::GLY1*)header; + glyphNum++; + break; + case 'MAP1': + mpMapBlocks[mapNum] = (ResFONT::MAP1*)header; + if (mMaxCode > mpMapBlocks[mapNum]->startCode) { + mMaxCode = mpMapBlocks[mapNum]->startCode; + } + mapNum++; + break; + default: + JUTReportConsole("Unknown data block\n"); + break; + } + } } /* 802C25C0-802C26B8 .text setGX__10JUTResFontFv */ void JUTResFont::setGX() { - /* Nonmatching */ + GXSetNumChans(1); + GXSetNumTevStages(1); + GXSetNumTexGens(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0); + GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetTevOp(GX_TEVSTAGE0, GX_MODULATE); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_RGBA4, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBX8, 0xf); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); } /* 802C26B8-802C28F8 .text setGX__10JUTResFontFQ28JUtility6TColorQ28JUtility6TColor */ -void JUTResFont::setGX(JUtility::TColor, JUtility::TColor) { - /* Nonmatching */ +void JUTResFont::setGX(JUtility::TColor col1, JUtility::TColor col2) { + if (col1 == 0 && col2 == -1) { + setGX(); + } else { + GXSetNumChans(1); + GXSetNumTevStages(2); + GXSetNumTexGens(1); + GXSetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + GXSetChanCtrl(GX_COLOR0A0, false, GX_SRC_REG, GX_SRC_VTX, 0, GX_DF_NONE, GX_AF_NONE); + GXSetTevColor(GX_TEVREG0, col1); + GXSetTevColor(GX_TEVREG1, col2); + GXSetTevColorIn(GX_TEVSTAGE0, GX_CC_C0, GX_CC_C1, GX_CC_TEXC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE0, GX_CA_A0, GX_CA_A1, GX_CA_TEXA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE0, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + GXSetTevOrder(GX_TEVSTAGE1, GX_TEXCOORD_NULL, GX_TEXMAP_NULL, GX_COLOR0A0); + GXSetTevColorIn(GX_TEVSTAGE1, GX_CC_ZERO, GX_CC_CPREV, GX_CC_RASC, GX_CC_ZERO); + GXSetTevAlphaIn(GX_TEVSTAGE1, GX_CA_ZERO, GX_CA_APREV, GX_CA_RASA, GX_CA_ZERO); + GXSetTevColorOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + GXSetTevAlphaOp(GX_TEVSTAGE1, GX_TEV_ADD, GX_TB_ZERO, GX_CS_SCALE_1, true, GX_TEVPREV); + GXSetBlendMode(GX_BM_BLEND, GX_BL_SRC_ALPHA, GX_BL_INV_SRC_ALPHA, GX_LO_SET); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_CLR_RGBA, GX_RGBA4, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_CLR0, GX_CLR_RGBA, GX_RGBA8, 0); + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_TEX0, GX_CLR_RGBA, GX_RGBX8, 15); + GXClearVtxDesc(); + GXSetVtxDesc(GX_VA_POS, GX_DIRECT); + GXSetVtxDesc(GX_VA_CLR0, GX_DIRECT); + GXSetVtxDesc(GX_VA_TEX0, GX_DIRECT); + } } /* 802C28F8-802C2D6C .text drawChar_scale__10JUTResFontFffffib */ -void JUTResFont::drawChar_scale(float, float, float, float, int, bool) { +f32 JUTResFont::drawChar_scale(f32 posX, f32 posY, f32 scaleX, f32 scaleY, int chr, bool flag) { /* Nonmatching */ + JUTFont::TWidth width; + f32 posMinX; + f32 posMinY; + f32 scaledHeight; + f32 posMaxX; + + JUT_ASSERT(0x179, mValid) + loadFont(chr, GX_TEXMAP0, &width); + + if (mFixed || !flag) { + posMinX = posX; + } else { + posMinX = (posX - width.field_0x0 * (scaleX / getCellWidth())); + } + f32 retval = mFixedWidth * (scaleX / getCellWidth()); + if (!mFixed) { + if (!flag) { + retval = (width.field_0x1 + width.field_0x0) * (scaleX / getCellWidth()); + } else { + retval = width.field_0x1 * (scaleX / getCellWidth()); + } + } + posMaxX = posMinX + scaleX; + posMinY = posY - getAscent() * (scaleY / getHeight()); + scaledHeight = scaleY / getHeight(); + f32 descent = getDescent(); + f32 posMaxY = descent * scaledHeight + posY; + + // Glyph details + ResFONT::GLY1* used_glyphs = mpGlyphBlocks[field_0x66]; + u16 texWidth = used_glyphs->textureWidth; + u16 texHeight = used_glyphs->textureHeight; + int tWidth = mWidth; + int tHeight = mHeight; + int shiftWidth = (tWidth + used_glyphs->cellWidth) << 15; + int texMinX = (tWidth << 15) / texWidth; + int texMinY = (tHeight << 15) / texHeight; + int shiftHeight = (tHeight + used_glyphs->cellHeight) << 15; + s32 texMaxX = shiftWidth / texWidth; + s32 texMaxY = shiftHeight / texHeight; + + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_F32, 0); + GXBegin(GX_QUADS, GX_VTXFMT0, 4); + + // Bottom Left + GXPosition3f32(posMinX, posMinY, 0.0f); + GXColor1u32(mColor1); + GXTexCoord2s16(texMinX, texMinY); + + // Bottom Right + GXPosition3f32(posMaxX, posMinY, 0.0f); + GXColor1u32(mColor2); + GXTexCoord2s16(texMaxX, texMinY); + + // Top Right + GXPosition3f32(posMaxX, posMaxY, 0.0f); + GXColor1u32(mColor4); + GXTexCoord2s16(texMaxX, texMaxY); + + // Top Left + GXPosition3f32(posMinX, posMaxY, 0.0f); + GXColor1u32(mColor3); + GXTexCoord2s16(texMinX, texMaxY); + + GXSetVtxAttrFmt(GX_VTXFMT0, GX_VA_POS, GX_POS_XYZ, GX_S16, 0); + + return retval; } /* 802C2D6C-802C2DE8 .text loadFont__10JUTResFontFi11_GXTexMapIDPQ27JUTFont6TWidth */ -void JUTResFont::loadFont(int, _GXTexMapID, JUTFont::TWidth*) { - /* Nonmatching */ +void JUTResFont::loadFont(int code, _GXTexMapID texMapID, JUTFont::TWidth* pDstWidth) { + if (pDstWidth) { + getWidthEntry(code, pDstWidth); + } + u32 fontCode = getFontCode(code); + loadImage(fontCode, texMapID); } /* 802C2DE8-802C2E90 .text getWidthEntry__10JUTResFontCFiPQ27JUTFont6TWidth */ -void JUTResFont::getWidthEntry(int, JUTFont::TWidth*) const { +void JUTResFont::getWidthEntry(int code, JUTFont::TWidth* width) const { /* Nonmatching */ + int fontCode = getFontCode(code); + width->field_0x0 = 0; + width->field_0x1 = mInfoBlock->width; + + for (int i = 0; i < mWidthBlockNum; i++) { + ResFONT::WID1* block = mpWidthBlocks[i]; + if (block->startCode <= fontCode && fontCode <= block->endCode) { + int chunkNum = (fontCode - mpWidthBlocks[i]->startCode) * 2; + u8* ptr = &mpWidthBlocks[i]->mChunkNum[chunkNum]; + width->field_0x0 = ptr[0]; + width->field_0x1 = ptr[1]; + break; + } + } } /* 802C2E90-802C2EDC .text getCellWidth__10JUTResFontCFv */ -void JUTResFont::getCellWidth() const { - /* Nonmatching */ +int JUTResFont::getCellWidth() const { + if (mpGlyphBlocks) { + ResFONT::GLY1* glyph = *mpGlyphBlocks; + if (glyph) { + return glyph->cellWidth; + } + } + return getWidth(); } /* 802C2EDC-802C2F28 .text getCellHeight__10JUTResFontCFv */ -void JUTResFont::getCellHeight() const { - /* Nonmatching */ +s32 JUTResFont::getCellHeight() const { + if (mpGlyphBlocks) { + ResFONT::GLY1* glyph = *mpGlyphBlocks; + if (glyph) { + return glyph->cellHeight; + } + } + return getHeight(); } /* 802C2F28-802C2F5C .text isLeadByte__10JUTResFontCFi */ -void JUTResFont::isLeadByte(int) const { - /* Nonmatching */ +bool JUTResFont::isLeadByte(int chr) const { + return (*mIsLeadByte)(chr); } /* 802C2F5C-802C30E4 .text getFontCode__10JUTResFontCFi */ -void JUTResFont::getFontCode(int) const { +int JUTResFont::getFontCode(int chr) const { /* Nonmatching */ + static const u16 halftofull[95] = { + 0x8140, 0x8149, 0x8168, 0x8194, 0x8190, 0x8193, 0x8195, 0x8166, 0x8169, 0x816A, 0x8196, + 0x817B, 0x8143, 0x817C, 0x8144, 0x815E, 0x824F, 0x8250, 0x8251, 0x8252, 0x8253, 0x8254, + 0x8255, 0x8256, 0x8257, 0x8258, 0x8146, 0x8147, 0x8183, 0x8181, 0x8184, 0x8148, 0x8197, + 0x8260, 0x8261, 0x8262, 0x8263, 0x8264, 0x8265, 0x8266, 0x8267, 0x8268, 0x8269, 0x826A, + 0x826B, 0x826C, 0x826D, 0x826E, 0x826F, 0x8270, 0x8271, 0x8272, 0x8273, 0x8274, 0x8275, + 0x8276, 0x8277, 0x8278, 0x8279, 0x816D, 0x818F, 0x816E, 0x814F, 0x8151, 0x8165, 0x8281, + 0x8282, 0x8283, 0x8284, 0x8285, 0x8286, 0x8287, 0x8288, 0x8289, 0x828A, 0x828B, 0x828C, + 0x828D, 0x828E, 0x828F, 0x8290, 0x8291, 0x8292, 0x8293, 0x8294, 0x8295, 0x8296, 0x8297, + 0x8298, 0x8299, 0x829A, 0x816F, 0x8162, 0x8170, 0x8160, + }; + + int ret = mInfoBlock->defaultCode; + if ((getFontType() == 2) && (mMaxCode >= 0x8000u) && (chr >= 0x20) && (chr < 0x7Fu)) { + chr = halftofull[chr - 32]; + } + int j = 0; + for (int i = mMapBlockNum; i > 0; j++, i--) { + if ((mpMapBlocks[j]->startCode <= chr) && (chr <= mpMapBlocks[j]->endCode)) { + ResFONT::MAP1* map = mpMapBlocks[j]; + if (map->mappingMethod == 0) { + ret = chr - map->startCode; + break; + } else if (map->mappingMethod == 2) { + ret = *(&mpMapBlocks[j]->mLeading + ((chr - mpMapBlocks[j]->startCode))); + break; + } else if (map->mappingMethod == 3) { + u16* leading_temp = &map->mLeading; + int phi_r5 = 0; + int phi_r6_2 = map->numEntries - 1; + + while (phi_r6_2 >= phi_r5) { + u32 temp_r3 = phi_r6_2 + phi_r5; + int temp_r7 = (int)((temp_r3 >> 0x1FU) + phi_r6_2 + phi_r5) >> 1; + + if (chr < leading_temp[temp_r7 * 2]) { + phi_r6_2 = temp_r7 - 1; + continue; + } + + if (chr > leading_temp[temp_r7 * 2]) { + phi_r5 = temp_r7 + 1; + continue; + } + + ret = leading_temp[temp_r7 * 2 + 1]; + break; + } + } else if (map->mappingMethod == 1) { + u16* phi_r5_2 = NULL; + if (map->numEntries == 1) { + phi_r5_2 = &map->mLeading; + } + ret = JUTResFont::convertSjis(chr, phi_r5_2); + break; + } + break; + } + } + return ret; } /* 802C30E4-802C3248 .text loadImage__10JUTResFontFi11_GXTexMapID */ -void JUTResFont::loadImage(int, _GXTexMapID) { - /* Nonmatching */ +void JUTResFont::loadImage(int code, _GXTexMapID id) { + int i = 0; + for (; i < mGlyphBlockNum; i++) { + if (mpGlyphBlocks[i]->startCode <= code && code <= mpGlyphBlocks[i]->endCode) { + code -= mpGlyphBlocks[i]->startCode; + break; + } + } + + if (i == mGlyphBlockNum) + return; + + s32 pageNumCells = mpGlyphBlocks[i]->numRows * mpGlyphBlocks[i]->numColumns; + s32 pageIdx = code / pageNumCells; + s32 cellIdxInPage = code % pageNumCells; + s32 cellCol = (cellIdxInPage % mpGlyphBlocks[i]->numRows); + s32 cellRow = (cellIdxInPage / mpGlyphBlocks[i]->numRows); + mWidth = cellCol * mpGlyphBlocks[i]->cellWidth; + mHeight = cellRow * mpGlyphBlocks[i]->cellHeight; + + if (pageIdx != mTexPageIdx || i != field_0x66) { + GXInitTexObj(&field_0x24, &mpGlyphBlocks[i]->data[pageIdx * mpGlyphBlocks[i]->textureSize], + mpGlyphBlocks[i]->textureWidth, mpGlyphBlocks[i]->textureHeight, + (GXTexFmt)mpGlyphBlocks[i]->textureFormat, GX_CLAMP, GX_CLAMP, 0); + + GXInitTexObjLOD(&field_0x24, GX_LINEAR, GX_LINEAR, 0.0f, 0.0f, 0.0f, 0U, 0U, GX_ANISO_1); + mTexPageIdx = pageIdx; + field_0x66 = i; + } + + GXLoadTexObj(&field_0x24, id); } /* 802C3248-802C328C .text convertSjis__10JUTResFontCFiPUs */ -void JUTResFont::convertSjis(int, unsigned short*) const { +int JUTResFont::convertSjis(int inChar, u16* inLead) const { /* Nonmatching */ + int outChar = (u8)inChar; + inChar = inChar >> 8 & 0xFF; + outChar -= 0x40; + if (0x40 <= outChar) { + outChar--; + } + u16 lead = 0x31C; + if (inLead) { + lead = *inLead; + } + return outChar + (inChar - 0x88) * 0xBC + -0x5E + lead; }