From 611852a3f0ade9ae0f758856d6e7115cf28e4057 Mon Sep 17 00:00:00 2001 From: Phillip Stephens Date: Sat, 22 Nov 2025 10:13:27 -0800 Subject: [PATCH] Particle and RasterFont progress --- config/GM8E01_00/symbols.txt | 18 +- config/GM8E01_01/symbols.txt | 8 +- configure.py | 2 +- include/Kyoto/CFrameDelayedKiller.hpp | 5 + .../Kyoto/Particles/CElectricDescription.hpp | 20 +- include/Kyoto/Particles/CGenDescription.hpp | 4 +- .../Kyoto/Particles/CParticleDataFactory.hpp | 11 + .../Particles/CSpawnSystemKeyframeData.hpp | 3 + include/Kyoto/Particles/CVectorElement.hpp | 137 +++++- include/Kyoto/Text/CDrawStringOptions.hpp | 6 +- include/Kyoto/Text/CRasterFont.hpp | 31 +- include/rstl/prereserved_vector.hpp | 25 + src/Kyoto/Particles/CElectricDescription.cpp | 39 ++ src/Kyoto/Particles/CParticleDataFactory.cpp | 428 +++++++++++++++++- src/Kyoto/Text/CRasterFont.cpp | 112 ++++- src/Kyoto/Text/CTextRenderBuffer.cpp | 128 ++++++ 16 files changed, 935 insertions(+), 42 deletions(-) create mode 100644 include/rstl/prereserved_vector.hpp create mode 100644 src/Kyoto/Particles/CElectricDescription.cpp create mode 100644 src/Kyoto/Text/CTextRenderBuffer.cpp diff --git a/config/GM8E01_00/symbols.txt b/config/GM8E01_00/symbols.txt index a86f7d1f..fa50fe3c 100644 --- a/config/GM8E01_00/symbols.txt +++ b/config/GM8E01_00/symbols.txt @@ -13252,9 +13252,9 @@ GetLineMargin__11CRasterFontFv = .text:0x802FFF5C; // type:function size:0x8 sco GetBaseLine__11CRasterFontCFv = .text:0x802FFF64; // type:function size:0x8 scope:global SetupRenderState__11CRasterFontFv = .text:0x802FFF6C; // type:function size:0x114 scope:global FRasterFontFactory__FRC10SObjectTagR12CInputStreamRC15CVParamTransfer = .text:0x80300080; // type:function size:0x98 scope:global -fn_80300118 = .text:0x80300118; // type:function size:0xA4 -fn_803001BC = .text:0x803001BC; // type:function size:0x2C -fn_803001E8 = .text:0x803001E8; // type:function size:0x9C +__ct<11CRasterFont>__16CFactoryFnReturnFP11CRasterFont = .text:0x80300118; // type:function size:0xA4 +GetIObjObjectFor__21TToken<11CRasterFont>FRCQ24rstl23auto_ptr<11CRasterFont> = .text:0x803001BC; // type:function size:0x2C +GetNewDerivedObject__39TObjOwnerDerivedFromIObj<11CRasterFont>FRCQ24rstl23auto_ptr<11CRasterFont> = .text:0x803001E8; // type:function size:0x9C fn_80300284 = .text:0x80300284; // type:function size:0x64 InternalGetGlyph__11CRasterFontCFw = .text:0x803002E8; // type:function size:0xD8 scope:global SinglePassDrawString__11CRasterFontCFRC18CDrawStringOptionsiiRiRiP17CTextRenderBufferPCwi = .text:0x803003C0; // type:function size:0x140 scope:global @@ -13989,7 +13989,7 @@ GetInt__20CParticleDataFactoryFR12CInputStream = .text:0x80328408; // type:funct GetBool__20CParticleDataFactoryFR12CInputStream = .text:0x80328428; // type:function size:0x34 scope:global GetClassID__20CParticleDataFactoryFR12CInputStream = .text:0x8032845C; // type:function size:0x20 scope:global CreateGPSM__20CParticleDataFactoryFP15CGenDescriptionR12CInputStreamRQ24rstl37vectorP11CSimplePool = .text:0x8032847C; // type:function size:0x15C8 scope:global -fn_80329A44 = .text:0x80329A44; // type:function size:0x48 scope:global +__as__Q24rstl38single_ptr<24CSpawnSystemKeyframeData>FP24CSpawnSystemKeyframeData = .text:0x80329A44; // type:function size:0x48 scope:global __dt__24CSpawnSystemKeyframeDataFv = .text:0x80329A8C; // type:function size:0x58 fn_80329AE4 = .text:0x80329AE4; // type:function size:0x8C fn_80329B70 = .text:0x80329B70; // type:function size:0x50 @@ -14217,7 +14217,7 @@ __dt__16CVEColorToVectorFv = .text:0x8033490C; // type:function size:0xA0 scope: __ct__16CVEColorToVectorFP13CColorElement = .text:0x803349AC; // type:function size:0x2C scope:global GetValue__11CVESubtractCFiR9CVector3f = .text:0x803349D8; // type:function size:0xD4 scope:global __dt__11CVESubtractFv = .text:0x80334AAC; // type:function size:0xC0 scope:global -__ct__10CVESubractFP14CVectorElementP14CVectorElement = .text:0x80334B6C; // type:function size:0x30 scope:global +__ct__11CVESubtractFP14CVectorElementP14CVectorElement = .text:0x80334B6C; // type:function size:0x30 scope:global GetValue__28CVEParticleSystemTranslationCFiR9CVector3f = .text:0x80334B9C; // type:function size:0x5C scope:global GetValue__33CVEParticleSystemOrientationRightCFiR9CVector3f = .text:0x80334BF8; // type:function size:0x5C scope:global GetValue__30CVEParticleSystemOrientationUpCFiR9CVector3f = .text:0x80334C54; // type:function size:0x5C scope:global @@ -15312,8 +15312,8 @@ fn_8036C9D0 = .text:0x8036C9D0; // type:function size:0x94 __dl__8IElementFPvUl = .text:0x8036CA64; // type:function size:0x20 scope:global __nw__8IElementFUlPCcPCc = .text:0x8036CA84; // type:function size:0x20 scope:global fn_8036CAA4 = .text:0x8036CAA4; // type:function size:0x8 -fn_8036CAAC = .text:0x8036CAAC; // type:function size:0xC -fn_8036CAB8 = .text:0x8036CAB8; // type:function size:0x2C +fn_8036CAAC__19CFrameDelayedKillerFUi = .text:0x8036CAAC; // type:function size:0xC +fn_8036CAB8__19CFrameDelayedKillerFUiUi = .text:0x8036CAB8; // type:function size:0x2C fn_8036CAE4 = .text:0x8036CAE4; // type:function size:0x10 fn_8036CAF4 = .text:0x8036CAF4; // type:function size:0x34 fn_8036CB28 = .text:0x8036CB28; // type:function size:0x28 @@ -17800,7 +17800,7 @@ lbl_803D6E50 = .rodata:0x803D6E50; // type:object size:0x8 lbl_803D6E58 = .rodata:0x803D6E58; // type:object size:0x8 lbl_803D6E60 = .rodata:0x803D6E60; // type:object size:0x8 lbl_803D6E68 = .rodata:0x803D6E68; // type:object size:0x18 -lbl_803D6E80 = .rodata:0x803D6E80; // type:object size:0x8 +@stringBase0 = .rodata:0x803D6E80; // type:object size:0x8 scope:local data:string_table @stringBase0 = .rodata:0x803D6E88; // type:object size:0x7 scope:local data:string_table lbl_803D6E90 = .rodata:0x803D6E90; // type:object size:0x8 @stringBase0 = .rodata:0x803D6E98; // type:object size:0x7 scope:local data:string_table @@ -21986,7 +21986,7 @@ lbl_805A947C = .sbss:0x805A947C; // type:object size:0x1 data:byte lbl_805A9480 = .sbss:0x805A9480; // type:object size:0x1 data:byte lbl_805A9484 = .sbss:0x805A9484; // type:object size:0x1 data:byte lbl_805A9485 = .sbss:0x805A9485; // type:object size:0x1 data:byte -lbl_805A9488 = .sbss:0x805A9488; // type:object size:0x4 data:4byte +g805A9488__19CFrameDelayedKiller = .sbss:0x805A9488; // type:object size:0x4 data:4byte lbl_805A948C = .sbss:0x805A948C; // type:object size:0x4 data:4byte mParticleLifetime__16CParticleGlobals = .sbss:0x805A9490; // type:object size:0x4 scope:global data:4byte mParticleLifetimeReal__16CParticleGlobals = .sbss:0x805A9494; // type:object size:0x4 scope:global align:4 data:float diff --git a/config/GM8E01_01/symbols.txt b/config/GM8E01_01/symbols.txt index d82ce6a6..da2ac539 100644 --- a/config/GM8E01_01/symbols.txt +++ b/config/GM8E01_01/symbols.txt @@ -13252,9 +13252,9 @@ GetLineMargin__11CRasterFontFv = .text:0x8030003C; // type:function size:0x8 sco GetBaseLine__11CRasterFontCFv = .text:0x80300044; // type:function size:0x8 scope:global SetupRenderState__11CRasterFontFv = .text:0x8030004C; // type:function size:0x114 scope:global FRasterFontFactory__FRC10SObjectTagR12CInputStreamRC15CVParamTransfer = .text:0x80300160; // type:function size:0x98 scope:global -fn_80300118 = .text:0x803001F8; // type:function size:0xA4 scope:global -fn_803001BC = .text:0x8030029C; // type:function size:0x2C scope:global -fn_803001E8 = .text:0x803002C8; // type:function size:0x9C scope:global +__ct<11CRasterFont>__16CFactoryFnReturnFP11CRasterFont = .text:0x803001F8; // type:function size:0xA4 scope:global +GetIObjObjectFor__21TToken<11CRasterFont>FRCQ24rstl23auto_ptr<11CRasterFont> = .text:0x8030029C; // type:function size:0x2C scope:global +GetNewDerivedObject__39TObjOwnerDerivedFromIObj<11CRasterFont>FRCQ24rstl23auto_ptr<11CRasterFont> = .text:0x803002C8; // type:function size:0x9C scope:global fn_80300284 = .text:0x80300364; // type:function size:0x64 scope:global InternalGetGlyph__11CRasterFontCFw = .text:0x803003C8; // type:function size:0xD8 scope:global SinglePassDrawString__11CRasterFontCFRC18CDrawStringOptionsiiRiRiP17CTextRenderBufferPCwi = .text:0x803004A0; // type:function size:0x140 scope:global @@ -13989,7 +13989,7 @@ GetInt__20CParticleDataFactoryFR12CInputStream = .text:0x803284E8; // type:funct GetBool__20CParticleDataFactoryFR12CInputStream = .text:0x80328508; // type:function size:0x34 scope:global GetClassID__20CParticleDataFactoryFR12CInputStream = .text:0x8032853C; // type:function size:0x20 scope:global CreateGPSM__20CParticleDataFactoryFP15CGenDescriptionR12CInputStreamRQ24rstl37vectorP11CSimplePool = .text:0x8032855C; // type:function size:0x15C8 scope:global -fn_80329A44 = .text:0x80329B24; // type:function size:0x48 scope:global +__as__Q24rstl38single_ptr<24CSpawnSystemKeyframeData>FP24CSpawnSystemKeyframeData = .text:0x80329B24; // type:function size:0x48 scope:global __dt__24CSpawnSystemKeyframeDataFv = .text:0x80329B6C; // type:function size:0x58 scope:global fn_80329AE4 = .text:0x80329BC4; // type:function size:0x8C scope:global fn_80329B70 = .text:0x80329C50; // type:function size:0x50 scope:global diff --git a/configure.py b/configure.py index 9b0da49f..bcc071c5 100755 --- a/configure.py +++ b/configure.py @@ -1079,7 +1079,7 @@ config.libs = [ Object(MatchingFor("GM8E01_00", "GM8E01_01", "GM8E01_48"), "Kyoto/Animation/CHalfTransition.cpp"), Object(NonMatching, "Kyoto/Particles/CElectricDescription.cpp"), Object(MatchingFor("GM8E01_00", "GM8E01_01", "GM8E01_48"), "Kyoto/Particles/CSwooshDescription.cpp"), - Object(MatchingFor("GM8E01_00"), "Kyoto/Particles/CGenDescription.cpp"), + Object(NonMatching, "Kyoto/Particles/CGenDescription.cpp"), Object(NonMatching, "Kyoto/CPakFile.cpp"), Object(NonMatching, "Kyoto/Animation/CPoseAsTransformsVariableSize.cpp"), Object(NonMatching, "Kyoto/Input/CRumbleVoice.cpp"), diff --git a/include/Kyoto/CFrameDelayedKiller.hpp b/include/Kyoto/CFrameDelayedKiller.hpp index af9cb2f7..aa58f134 100644 --- a/include/Kyoto/CFrameDelayedKiller.hpp +++ b/include/Kyoto/CFrameDelayedKiller.hpp @@ -5,11 +5,16 @@ class CFrameDelayedKiller { public: + static uint g805A9488; static void Initialize(); static void ShutDown(); static void fn_8036CB90(); static void fn_8036CC1C(bool unk1, void* unk2); + static uint fn_8036CAAC(uint v); + static void fn_8036CAB8(uint a, uint b); + static uint Get805A9488() { return g805A9488; } + static uint someInline() { return g805A9488 ? fn_8036CAAC(g805A9488) : 0; } }; #endif // _CFRAMEDELAYEDKILLER diff --git a/include/Kyoto/Particles/CElectricDescription.hpp b/include/Kyoto/Particles/CElectricDescription.hpp index e075625b..c1d15cb3 100644 --- a/include/Kyoto/Particles/CElectricDescription.hpp +++ b/include/Kyoto/Particles/CElectricDescription.hpp @@ -1,20 +1,22 @@ #ifndef _CELECTRICDESCRIPTION #define _CELECTRICDESCRIPTION +#include "Kyoto/Particles/CGenDescription.hpp" #include "Kyoto/Particles/CParticleDataFactory.hpp" +#include "Kyoto/Particles/CSwooshDescription.hpp" +#include "Kyoto/TToken.hpp" +#include "rstl/optional_object.hpp" class CColorElement; class CEmitterElement; class CIntElement; class CRealElement; -// using SParticleModel = STokenDesc; -// using SChildGeneratorDesc = STokenDesc; -// using SSwooshGeneratorDesc = STokenDesc; -// using SElectricGeneratorDesc = STokenDesc; - class CElectricDescription { public: + CElectricDescription(); + ~CElectricDescription(); + CIntElement* x0_LIFE; CIntElement* x4_SLIF; CRealElement* x8_GRAT; @@ -31,10 +33,10 @@ public: CColorElement* x34_LCL1; CColorElement* x38_LCL2; CColorElement* x3c_LCL3; - // SSwooshGeneratorDesc x40_SSWH; - // SChildGeneratorDesc x50_GPSM; - // SChildGeneratorDesc x60_EPSM; - // bool x70_ZERY = false; + rstl::optional_object< TCachedToken< CSwooshDescription > > x40_SSWH; + rstl::optional_object< TCachedToken< CGenDescription > > x50_GPSM; + rstl::optional_object< TCachedToken< CGenDescription > > x60_EPSM; + bool x70_ZERY; }; #endif // _CELECTRICDESCRIPTION diff --git a/include/Kyoto/Particles/CGenDescription.hpp b/include/Kyoto/Particles/CGenDescription.hpp index 4ce671b5..49ba1e27 100644 --- a/include/Kyoto/Particles/CGenDescription.hpp +++ b/include/Kyoto/Particles/CGenDescription.hpp @@ -48,8 +48,8 @@ public: bool x31_29_VMD2 : 1; bool x31_30_VMD3 : 1; bool x31_31_VMD4 : 1; - bool x32_25_OPTS : 1; bool x32_24_CIND : 1; + bool x32_25_OPTS : 1; IElement* x34_MBSP; IElement* x38_SIZE; IElement* x3c_ROTA; @@ -76,7 +76,7 @@ public: rstl::optional_object< TCachedToken< CSwooshDescription > > xc0_SSWH; IElement* xd0_SSSD; IElement* xd4_SSPO; - rstl::optional_object< CToken > xd8_SELC; + rstl::optional_object< TToken< CElectricDescription > > xd8_SELC; IElement* xe4_SESD; IElement* xe8_SEPO; IElement* xec_LTYP; diff --git a/include/Kyoto/Particles/CParticleDataFactory.hpp b/include/Kyoto/Particles/CParticleDataFactory.hpp index c851f23f..3cd16c46 100644 --- a/include/Kyoto/Particles/CParticleDataFactory.hpp +++ b/include/Kyoto/Particles/CParticleDataFactory.hpp @@ -1,6 +1,8 @@ #ifndef _CPARTICLEDATAFACTORY #define _CPARTICLEDATAFACTORY +#include "Kyoto/CSimplePool.hpp" +#include "Kyoto/Particles/CElectricDescription.hpp" #include "Kyoto/Particles/CGenDescription.hpp" #include "Kyoto/Particles/IElement.hpp" #include "Kyoto/SObjectTag.hpp" @@ -12,6 +14,8 @@ public: static CGenDescription* GetGeneratorDesc(CInputStream& in, CSimplePool* pool, uint offset); static CGenDescription* CreateGeneratorDescription(CInputStream&, rstl::vector< uint >& assets, uint offset, CSimplePool* pool); + static bool CreateGPSM(CGenDescription* desc, CInputStream& in, + rstl::vector< CAssetId >& resources, CSimplePool* pool); static CUVElement* GetTextureElement(CInputStream& in, CSimplePool* resPool); static CColorElement* GetColorElement(CInputStream& in); static CModVectorElement* GetModVectorElement(CInputStream& in); @@ -24,6 +28,13 @@ public: static int GetInt(CInputStream& in); static bool GetBool(CInputStream& in); static FourCC GetClassID(CInputStream& in); + static rstl::optional_object< TToken< CModel > > GetModel(CInputStream& in, CSimplePool* pool); + static rstl::optional_object< TToken< CGenDescription > > + GetChildGeneratorDesc(CInputStream& in, CSimplePool* pool, rstl::vector< CAssetId >& resources); + static rstl::optional_object< TToken< CSwooshDescription > > + GetSwooshGeneratorDesc(CInputStream& in, CSimplePool* pool); + static rstl::optional_object< TToken< CElectricDescription > > + GetElectricGeneratorDesc(CInputStream& in, CSimplePool* pool); }; #endif // _CPARTICLEDATAFACTORY diff --git a/include/Kyoto/Particles/CSpawnSystemKeyframeData.hpp b/include/Kyoto/Particles/CSpawnSystemKeyframeData.hpp index c8e32907..bbfd9527 100644 --- a/include/Kyoto/Particles/CSpawnSystemKeyframeData.hpp +++ b/include/Kyoto/Particles/CSpawnSystemKeyframeData.hpp @@ -5,6 +5,7 @@ #include class CInputStream; +class CSimplePool; class CSpawnSystemKeyframeData { public: class CSpawnSystemKeyframeInfo { @@ -14,6 +15,8 @@ public: CSpawnSystemKeyframeData(CInputStream& in); ~CSpawnSystemKeyframeData() {} + void LoadAllSpawnedSystemTokens(CSimplePool* pool); + private: int mUnknown1; int mUnknown2; diff --git a/include/Kyoto/Particles/CVectorElement.hpp b/include/Kyoto/Particles/CVectorElement.hpp index 0145bd99..cdf7c75e 100644 --- a/include/Kyoto/Particles/CVectorElement.hpp +++ b/include/Kyoto/Particles/CVectorElement.hpp @@ -1,6 +1,7 @@ #ifndef _CVECTORELEMENT #define _CVECTORELEMENT +#include "Kyoto/Streams/CInputStream.hpp" #include "types.h" #include "Kyoto/Math/CVector3f.hpp" @@ -73,6 +74,21 @@ public: CRealElement* xc_z; }; +class CVECircleCluster : public CVectorElement { +public: + CVECircleCluster(CVectorElement* circleOffset, CVectorElement* circleNormal, + CIntElement* cycleFrames, CRealElement* randomFactor); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CVectorElement* mCircleOffset; + CVector3f mXVec; + CVector3f mYVec; + CIntElement* mCycleFrames; + CRealElement* mRandomFactor; +}; + class CVECone : public CVectorElement { CVectorElement* x4_direction; CRealElement* x8_magnitude; @@ -86,17 +102,126 @@ public: }; class CVEAngleCone : public CVectorElement { - CRealElement* x4_angleXConstant; - CRealElement* x8_angleYConstant; - CRealElement* xc_angleXRange; - CRealElement* x10_angleYRange; - CRealElement* x14_magnitude; - public: CVEAngleCone(CRealElement* angleXConstant, CRealElement* angleYConstant, CRealElement* angleXRange, CRealElement* angleYRange, CRealElement* magnitude); ~CVEAngleCone(); bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CRealElement* x4_angleXConstant; + CRealElement* x8_angleYConstant; + CRealElement* xc_angleXRange; + CRealElement* x10_angleYRange; + CRealElement* x14_magnitude; }; +class CVECircle : public CVectorElement { +public: + CVECircle(CVectorElement* circleOffset, CVectorElement* circleNormal, CRealElement* angleConstant, + CRealElement* angleLinear, CRealElement* radius); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CVectorElement* mCircleOffset; + CVector3f mXVec; + CVector3f mYVec; + CRealElement* mAngleConstant; + CRealElement* mAngleLinear; + CRealElement* mRadius; +}; + +class CVEKeyframeEmitter : public CVectorElement { +public: + CVEKeyframeEmitter(CInputStream& in); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + uint mPercent; + uint mUnk1; + bool mLoop; + bool mUnk2; + uint mLoopEnd; + uint mLoopStart; + rstl::vector< CVector3f > mKeys; +}; + +class CVEAdd : public CVectorElement { +public: + CVEAdd(CVectorElement* a, CVectorElement* b); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CVectorElement* mA; + CVectorElement* mB; +}; + +class CVEMultiply : public CVectorElement { +public: + CVEMultiply(CVectorElement* a, CVectorElement* b); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CVectorElement* mA; + CVectorElement* mB; +}; + +class CVETimeChain : public CVectorElement { +public: + CVETimeChain(CVectorElement* a, CVectorElement* b, CIntElement* mSwitchFrame); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CVectorElement* mA; + CVectorElement* mB; + CIntElement* mSwitchFrame; +}; + +class CVEPulse : public CVectorElement { +public: + CVEPulse(CIntElement* durationA, CIntElement* durationB, CVectorElement* a, CVectorElement* b); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CIntElement* mDurationA; + CIntElement* mDurationB; + CVectorElement* mA; + CVectorElement* mB; +}; +class CVERealToVector : public CVectorElement { +public: + CVERealToVector(CRealElement* value); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CRealElement* mValue; +}; + +class CVESubtract : public CVectorElement { +public: + CVESubtract(CVectorElement* a, CVectorElement* b); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CVectorElement* mA; + CVectorElement* mB; +}; + +class CVEColorToVector : public CVectorElement { +public: + CVEColorToVector(CColorElement* value); + + bool GetValue(int frame, CVector3f& valOut) const override; + +private: + CColorElement* mValue; +}; #endif // _CVECTORELEMENT diff --git a/include/Kyoto/Text/CDrawStringOptions.hpp b/include/Kyoto/Text/CDrawStringOptions.hpp index 40e25652..5b861926 100644 --- a/include/Kyoto/Text/CDrawStringOptions.hpp +++ b/include/Kyoto/Text/CDrawStringOptions.hpp @@ -2,8 +2,8 @@ #define _CDRAWSTRINGOPTIONS #include "Kyoto/Graphics/CColor.hpp" -#include "rstl/reserved_vector.hpp" #include "Kyoto/Text/TextCommon.hpp" +#include "rstl/reserved_vector.hpp" class CDrawStringOptions { public: @@ -12,9 +12,11 @@ public: void SetTextDirection(ETextDirection dir) { x0_direction = dir; } ETextDirection GetTextDirection() const { return x0_direction; } void SetPaletteEntry(int idx, uint color) { x4_colors[idx] = color; } + uint GetPaletteEntry(int idx) const { return x4_colors[idx]; } + private: ETextDirection x0_direction; - rstl::reserved_vector x4_colors; + rstl::reserved_vector< u32, 16 > x4_colors; }; #endif // _CDRAWSTRINGOPTIONS diff --git a/include/Kyoto/Text/CRasterFont.hpp b/include/Kyoto/Text/CRasterFont.hpp index b40710b0..b0e8e315 100644 --- a/include/Kyoto/Text/CRasterFont.hpp +++ b/include/Kyoto/Text/CRasterFont.hpp @@ -105,18 +105,35 @@ public: ~CRasterFont(); EFontMode GetMode() const; - void GetSize(const CDrawStringOptions&, int&, int&, const wchar_t*, int) const; - void SetTexture(TToken< CTexture > token) { x80_texture = token; } - inline TToken< CTexture > GetTexture() { return *x80_texture; } - - bool IsFinishedLoading(); - void DrawString(const CDrawStringOptions& options, int x, int y, int& xOut, int& yOut, - CTextRenderBuffer* buffer, const wchar_t* str, int length) const; int GetMonoWidth() const; int GetMonoHeight() const; + int GetCarriageAdvance(); + + const CGlyph* GetGlyph(wchar_t c) const; + + void GetSize(const CDrawStringOptions&, int&, int&, const wchar_t*, int) const; + void SetTexture(TToken< CTexture > token); + inline TToken< CTexture > GetTexture() { return *x80_texture; } + + void DrawString(const CDrawStringOptions& options, int x, int y, int& xOut, int& yOut, + CTextRenderBuffer* buffer, const wchar_t* str, int length) const; + void DrawSpace(const CDrawStringOptions& options, int x, int y, int& xOut, int& yOut, + int length) const; + + void SinglePassDrawString(const CDrawStringOptions& options, int x, int y, int& xOut, int& yOut, + CTextRenderBuffer* buffer, const wchar_t* str, s32 length) const; + + void SetupRenderState(); + + int GetBaseLine() const; + int GetLineMargin(); + bool IsFinishedLoading(); private: + static int KernLookup(const rstl::vector< CKernPair >& kerning, int a, const int b); + const CGlyph* InternalGetGlyph(wchar_t c) const; + bool x0_initialized; int x4_monoWidth; int x8_monoHeight; diff --git a/include/rstl/prereserved_vector.hpp b/include/rstl/prereserved_vector.hpp new file mode 100644 index 00000000..9402e6f0 --- /dev/null +++ b/include/rstl/prereserved_vector.hpp @@ -0,0 +1,25 @@ +#ifndef _RSTL_PRERESERVED_VECTOR +#define _RSTL_PRERESERVED_VECTOR + +#include + +namespace rstl { +template < typename T > +class prereserved_vector { +public: + prereserved_vector() : mData(nullptr), mSize(0) {} + + uint size() const { return mSize; } + void set_size(uint size) { mSize = size; } + void set_data(T* data) { mData = data; } + + T& operator[](uint idx) { return mData[idx]; } + const T& operator[](uint idx) const { return mData[idx]; } + +private: + T* mData; + uint mSize; +}; +}; // namespace rstl + +#endif // _RSTL_PRERESERVED_VECTOR diff --git a/src/Kyoto/Particles/CElectricDescription.cpp b/src/Kyoto/Particles/CElectricDescription.cpp new file mode 100644 index 00000000..bf7cf9b2 --- /dev/null +++ b/src/Kyoto/Particles/CElectricDescription.cpp @@ -0,0 +1,39 @@ +#include "Kyoto/Particles/CElectricDescription.hpp" + +CElectricDescription::CElectricDescription() +: x0_LIFE(nullptr) +, x4_SLIF(nullptr) +, x8_GRAT(nullptr) +, xc_SCNT(nullptr) +, x10_SSEG(nullptr) +, x14_COLR(nullptr) +, x18_IEMT(nullptr) +, x1c_FEMT(nullptr) +, x20_AMPL(nullptr) +, x24_AMPD(nullptr) +, x28_LWD1(nullptr) +, x2c_LWD2(nullptr) +, x30_LWD3(nullptr) +, x34_LCL1(nullptr) +, x38_LCL2(nullptr) +, x3c_LCL3(nullptr) +, x70_ZERY(false) {} + +CElectricDescription::~CElectricDescription() { + delete x0_LIFE; + delete x4_SLIF; + delete x8_GRAT; + delete xc_SCNT; + delete x10_SSEG; + delete x14_COLR; + delete x18_IEMT; + delete x1c_FEMT; + delete x20_AMPL; + delete x24_AMPD; + delete x28_LWD1; + delete x2c_LWD2; + delete x30_LWD3; + delete x34_LCL1; + delete x38_LCL2; + delete x3c_LCL3; +} diff --git a/src/Kyoto/Particles/CParticleDataFactory.cpp b/src/Kyoto/Particles/CParticleDataFactory.cpp index 28be5bf2..304a5268 100644 --- a/src/Kyoto/Particles/CParticleDataFactory.cpp +++ b/src/Kyoto/Particles/CParticleDataFactory.cpp @@ -1,6 +1,8 @@ #include "Kyoto/Particles/CParticleDataFactory.hpp" #include "Kyoto/CFactoryFnReturn.hpp" +#include "Kyoto/CFrameDelayedKiller.hpp" +#include "Kyoto/CRandom16.hpp" #include "Kyoto/CSimplePool.hpp" #include "Kyoto/CVParamTransfer.hpp" #include "Kyoto/Particles/CGenDescription.hpp" @@ -8,8 +10,14 @@ #include "Kyoto/Particles/CModVectorElement.hpp" #include "Kyoto/Particles/CRealElement.hpp" #include "Kyoto/Particles/CSpawnSystemKeyframeData.hpp" +#include "Kyoto/Particles/CSwooshDescription.hpp" +#include "Kyoto/Particles/CVectorElement.hpp" #include "Kyoto/Particles/IElement.hpp" +#include "Kyoto/SObjectTag.hpp" #include "Kyoto/Streams/CInputStream.hpp" +#include "Kyoto/TToken.hpp" +#include "dolphin/types.h" +#include "rstl/optional_object.hpp" #define SBIG(v) v CFactoryFnReturn FParticleFactory(const SObjectTag& tag, CInputStream& in, @@ -32,6 +40,276 @@ CGenDescription* CParticleDataFactory::CreateGeneratorDescription(CInputStream& return nullptr; } +bool CParticleDataFactory::CreateGPSM(CGenDescription* desc, CInputStream& in, + rstl::vector< CAssetId >& resources, CSimplePool* pool) { + bool done = false; + CRandom16 _(99); + CGlobalRandom __(_); + while (!done) { + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('PSIV'): + delete GetVectorElement(in); + break; + case SBIG('PSVM'): + delete GetModVectorElement(in); + break; + case SBIG('PSOV'): + delete GetVectorElement(in); + break; + case SBIG('PSTS'): + desc->x8_PSTS = GetRealElement(in); + break; + case SBIG('PSLT'): + desc->x0_PSLT = GetIntElement(in); + break; + case SBIG('PSWT'): + desc->x4_PSWT = GetIntElement(in); + break; + case SBIG('LIT_'): + desc->x30_29_LIT_ = GetBool(in); + break; + case SBIG('ORNT'): + desc->x30_30_ORNT = GetBool(in); + break; + case SBIG('RSOP'): + desc->x30_31_RSOP = GetBool(in); + break; + case SBIG('AAPH'): + desc->x30_26_AAPH = GetBool(in); + break; + case SBIG('ZBUF'): + desc->x30_27_ZBUF = GetBool(in); + break; + case SBIG('SORT'): + desc->x30_28_SORT = GetBool(in); + break; + case SBIG('MBLR'): + desc->x31_24_MBLR = GetBool(in); + break; + case SBIG('MBSP'): + desc->x34_MBSP = GetIntElement(in); + break; + case SBIG('MAXP'): + desc->x1c_MAXP = GetIntElement(in); + break; + case SBIG('GRTE'): + desc->x20_GRTE = GetRealElement(in); + break; + case SBIG('ILOC'): + delete GetVectorElement(in); + break; + case SBIG('IVEC'): + delete GetVectorElement(in); + break; + case SBIG('EMTR'): + desc->x2c_EMTR = GetEmitterElement(in); + break; + case SBIG('SIZE'): + desc->x38_SIZE = GetRealElement(in); + break; + case SBIG('COLR'): + desc->x24_COLR = GetColorElement(in); + break; + case SBIG('POFS'): + desc->xc_POFS = GetVectorElement(in); + break; + case SBIG('VMD1'): + desc->x31_28_VMD1 = GetBool(in); + break; + case SBIG('VMD2'): + desc->x31_29_VMD2 = GetBool(in); + break; + case SBIG('VMD3'): + desc->x31_30_VMD3 = GetBool(in); + break; + case SBIG('VMD4'): + desc->x31_31_VMD4 = GetBool(in); + break; + case SBIG('VEL1'): + desc->x68_VEL1 = GetModVectorElement(in); + break; + case SBIG('VEL2'): + desc->x6c_VEL2 = GetModVectorElement(in); + break; + case SBIG('VEL3'): + desc->x70_VEL3 = GetModVectorElement(in); + break; + case SBIG('VEL4'): + desc->x74_VEL4 = GetModVectorElement(in); + break; + case SBIG('LTME'): + desc->x28_LTME = GetIntElement(in); + break; + case SBIG('ROTA'): + desc->x3c_ROTA = GetRealElement(in); + break; + case SBIG('LENG'): + desc->x14_LENG = GetRealElement(in); + break; + case SBIG('WIDT'): + desc->x18_WIDT = GetRealElement(in); + break; + case SBIG('TEXR'): + desc->x40_TEXR = GetTextureElement(in, pool); + break; + case SBIG('TIND'): + desc->x44_TIND = GetTextureElement(in, pool); + break; + case SBIG('CIND'): + desc->x32_24_CIND = GetBool(in); + break; + case SBIG('PMDL'): + rstl::optional_object< TToken< CModel > > model(GetModel(in, pool)); + if (model) { + TCachedToken< CModel > tok = *model; + desc->x48_PMDL = tok; + } + break; + case SBIG('PMOP'): + desc->x58_PMOP = GetVectorElement(in); + break; + case SBIG('PMRT'): + desc->x5c_PMRT = GetVectorElement(in); + break; + case SBIG('PMSC'): + desc->x60_PMSC = GetVectorElement(in); + break; + case SBIG('PMCL'): + desc->x64_PMCL = GetColorElement(in); + break; + case SBIG('PMAB'): + desc->x31_25_PMAB = GetBool(in); + break; + case SBIG('PMUS'): + desc->x31_26_PMUS = GetBool(in); + break; + case SBIG('PMOO'): + desc->x31_27_PMOO = GetBool(in); + break; + case SBIG('SEED'): + desc->x10_SEED = GetIntElement(in); + break; + case SBIG('ICTS'): { + desc->x78_ICTS = *GetChildGeneratorDesc(in, pool, resources); + break; + } + case SBIG('NCSY'): + desc->x88_NCSY = GetIntElement(in); + break; + case SBIG('CSSD'): + desc->x8c_CSSD = GetIntElement(in); + break; + case SBIG('IDTS'): { + desc->x90_IDTS = *GetChildGeneratorDesc(in, pool, resources); + break; + } + case SBIG('NDSY'): + desc->xa0_NDSY = GetIntElement(in); + break; + case SBIG('IITS'): { + desc->xa4_IITS = *GetChildGeneratorDesc(in, pool, resources); + break; + } + case SBIG('PISY'): + desc->xb4_PISY = GetIntElement(in); + break; + case SBIG('SISY'): + desc->xb8_SISY = GetIntElement(in); + break; + case SBIG('SSWH'): { + desc->xc0_SSWH = *GetSwooshGeneratorDesc(in, pool); + break; + } + case SBIG('SSSD'): + desc->xd0_SSSD = GetIntElement(in); + break; + case SBIG('SSPO'): + desc->xd4_SSPO = GetVectorElement(in); + break; + case SBIG('SELC'): + desc->xd8_SELC = GetElectricGeneratorDesc(in, pool); + break; + case SBIG('SESD'): + desc->xe4_SESD = GetIntElement(in); + break; + case SBIG('SEPO'): + desc->xe8_SEPO = GetVectorElement(in); + break; + case SBIG('KSSM'): + if (GetClassID(in) == SBIG('CNST')) { + desc->xbc_KSSM = rs_new CSpawnSystemKeyframeData(in); + desc->xbc_KSSM->LoadAllSpawnedSystemTokens(pool); + } + break; + case SBIG('LINE'): + desc->x30_24_LINE = GetBool(in); + break; + case SBIG('FXLL'): + desc->x30_25_FXLL = GetBool(in); + break; + case SBIG('LTYP'): + desc->xec_LTYP = GetIntElement(in); + break; + case SBIG('LCLR'): + desc->xf0_LCLR = GetColorElement(in); + break; + case SBIG('LINT'): + desc->xf4_LINT = GetRealElement(in); + break; + case SBIG('LOFF'): + desc->xf8_LOFF = GetVectorElement(in); + break; + case SBIG('LDIR'): + desc->xfc_LDIR = GetVectorElement(in); + break; + case SBIG('LFOT'): + desc->x100_LFOT = GetIntElement(in); + break; + case SBIG('LFOR'): + desc->x104_LFOR = GetRealElement(in); + break; + case SBIG('LSLA'): + desc->x108_LSLA = GetRealElement(in); + break; + case SBIG('OPTS'): + desc->x32_25_OPTS = GetBool(in); + break; + case SBIG('ADV1'): + desc->x10c_ADV1 = GetRealElement(in); + break; + case SBIG('ADV2'): + desc->x110_ADV2 = GetRealElement(in); + break; + case SBIG('ADV3'): + desc->x114_ADV3 = GetRealElement(in); + break; + case SBIG('ADV4'): + desc->x118_ADV4 = GetRealElement(in); + break; + case SBIG('ADV5'): + desc->x11c_ADV5 = GetRealElement(in); + break; + case SBIG('ADV6'): + desc->x120_ADV6 = GetRealElement(in); + break; + case SBIG('ADV7'): + desc->x124_ADV7 = GetRealElement(in); + break; + case SBIG('ADV8'): + desc->x128_ADV8 = GetRealElement(in); + break; + case SBIG('_END'): + done = true; + break; + default: + return false; + } + } + + return true; +} + FourCC CParticleDataFactory::GetClassID(CInputStream& in) { return in.ReadLong(); } bool CParticleDataFactory::GetBool(CInputStream& in) { @@ -325,7 +603,155 @@ CRealElement* CParticleDataFactory::GetRealElement(CInputStream& in) { return nullptr; } -CVectorElement* CParticleDataFactory::GetVectorElement(CInputStream& in) { return nullptr; } +CVectorElement* CParticleDataFactory::GetVectorElement(CInputStream& in) { + CVectorElement* ret; + FourCC clsId = GetClassID(in); + switch (clsId) { + case SBIG('NONE'): + ret = nullptr; + break; + case SBIG('CNST'): { + uint iVar1 = CFrameDelayedKiller::Get805A9488(); + uint iVar2 = CFrameDelayedKiller::someInline(); + CRealElement* x = GetRealElement(in); + CRealElement* y = GetRealElement(in); + CRealElement* z = GetRealElement(in); + if (x && y && z) { + if (x->IsConstant() && y->IsConstant() && z->IsConstant()) { + float xf, yf, zf; + x->GetValue(0, xf); + y->GetValue(0, yf); + z->GetValue(0, zf); + + delete x; + delete y; + delete z; + + if (iVar1 != 0 && iVar1 == CFrameDelayedKiller::Get805A9488()) { + CFrameDelayedKiller::fn_8036CAB8(iVar1, CFrameDelayedKiller::fn_8036CAAC(iVar1) - iVar2); + } + ret = rs_new CVEFastConstant(xf, yf, zf); + break; + } + } + ret = rs_new CVEConstant(x, y, z); + break; + } + case SBIG('KEYE'): + case SBIG('KEYP'): + ret = rs_new CVEKeyframeEmitter(in); + break; + case SBIG('ANGC'): { + CRealElement* angleXBias = GetRealElement(in); + CRealElement* angleYBias = GetRealElement(in); + CRealElement* angleXRange = GetRealElement(in); + CRealElement* angleYRange = GetRealElement(in); + CRealElement* magnitude = GetRealElement(in); + ret = rs_new CVEAngleCone(angleXBias, angleYBias, angleXRange, angleYRange, magnitude); + break; + } + case SBIG('CONE'): { + CVectorElement* direction = GetVectorElement(in); + CRealElement* baseRadius = GetRealElement(in); + ret = rs_new CVECone(direction, baseRadius); + break; + } + case SBIG('CIRC'): { + CVectorElement* circleOffset = GetVectorElement(in); + CVectorElement* circleNormal = GetVectorElement(in); + CRealElement* angleConstant = GetRealElement(in); + CRealElement* angleLinear = GetRealElement(in); + CRealElement* radius = GetRealElement(in); + ret = rs_new CVECircle(circleOffset, circleNormal, angleConstant, angleLinear, radius); + break; + } + case SBIG('CCLU'): { + CVectorElement* circleOffset = GetVectorElement(in); + CVectorElement* circleNormal = GetVectorElement(in); + CIntElement* cycleFrames = GetIntElement(in); + CRealElement* randomFactor = GetRealElement(in); + + ret = rs_new CVECircleCluster(circleOffset, circleNormal, cycleFrames, randomFactor); + break; + } + case SBIG('ADD_'): { + CVectorElement* a = GetVectorElement(in); + CVectorElement* b = GetVectorElement(in); + ret = rs_new CVEAdd(a, b); + break; + } + case SBIG('MULT'): { + CVectorElement* a = GetVectorElement(in); + CVectorElement* b = GetVectorElement(in); + ret = rs_new CVEMultiply(a, b); + break; + } + case SBIG('CHAN'): { + CVectorElement* a = GetVectorElement(in); + CVectorElement* b = GetVectorElement(in); + CIntElement* switchFrame = GetIntElement(in); + + ret = rs_new CVETimeChain(a, b, switchFrame); + break; + } + case SBIG('PULS'): { + CIntElement* durationA = GetIntElement(in); + CIntElement* durationB = GetIntElement(in); + CVectorElement* a = GetVectorElement(in); + CVectorElement* b = GetVectorElement(in); + ret = rs_new CVEPulse(durationA, durationB, a, b); + break; + } + case SBIG('RTOV'): { + CRealElement* value = GetRealElement(in); + ret = rs_new CVERealToVector(value); + break; + } + case SBIG('PLOC'): { + ret = rs_new CVEParticleLocation(); + break; + } + case SBIG('PLCO'): { + ret = rs_new CVEParticleColor(); + break; + } + case SBIG('PVEL'): { + ret = rs_new CVEParticleVelocity(); + break; + } + case SBIG('PSOF'): { + ret = rs_new CVEParticleSystemOrientationFront(); + break; + } + case SBIG('PSOU'): { + ret = rs_new CVEParticleSystemOrientationUp(); + break; + } + case SBIG('PSOR'): { + ret = rs_new CVEParticleSystemOrientationRight(); + break; + } + case SBIG('PSTR'): { + ret = rs_new CVEParticleSystemTranslation(); + break; + } + case SBIG('SUB_'): { + CVectorElement* a = GetVectorElement(in); + CVectorElement* b = GetVectorElement(in); + ret = rs_new CVESubtract(a, b); + break; + } + case SBIG('CTVC'): { + CColorElement* value = GetColorElement(in); + ret = rs_new CVEColorToVector(value); + break; + } + default: + ret = nullptr; + break; + } + return ret; +} CEmitterElement* CParticleDataFactory::GetEmitterElement(CInputStream& in) { return nullptr; } diff --git a/src/Kyoto/Text/CRasterFont.cpp b/src/Kyoto/Text/CRasterFont.cpp index c00f0585..3f8bd939 100644 --- a/src/Kyoto/Text/CRasterFont.cpp +++ b/src/Kyoto/Text/CRasterFont.cpp @@ -1,9 +1,19 @@ #include "Kyoto/Text/CRasterFont.hpp" +#include "Kyoto/CFactoryFnReturn.hpp" +#include "Kyoto/CSimplePool.hpp" +#include "Kyoto/CVParamTransfer.hpp" +#include "Kyoto/Graphics/CColor.hpp" +#include "Kyoto/Graphics/CGraphicsPalette.hpp" #include "Kyoto/Streams/CInputStream.hpp" +#include "Kyoto/Text/CDrawStringOptions.hpp" +#include "Kyoto/Text/CTextRenderBuffer.hpp" +#include "Kyoto/Graphics/CGX.hpp" +#include "Kyoto/Text/TextCommon.hpp" #include "rstl/algorithm.hpp" #include "rstl/string.hpp" +#include "rstl/vector.hpp" CRasterFont::CRasterFont(CInputStream& in, IObjectStore* store) : x0_initialized(false) @@ -21,7 +31,7 @@ CRasterFont::CRasterFont(CInputStream& in, IObjectStore* store) } else { x8c_baseline = x8_monoHeight; } - + if (version >= 2) { x90_lineMargin = in.ReadInt32(); } @@ -92,3 +102,103 @@ CRasterFont::CRasterFont(CInputStream& in, IObjectStore* store) EFontMode CRasterFont::GetMode() const { return x2c_mode; } void CRasterFont::GetSize(const CDrawStringOptions&, int&, int&, const wchar_t*, int) const {} +int CRasterFont::GetMonoWidth() const { return x4_monoWidth; } +int CRasterFont::GetMonoHeight() const { return x8_monoHeight; } +int CRasterFont::GetCarriageAdvance() { return GetMonoHeight() + GetLineMargin(); } + +const CGlyph* CRasterFont::GetGlyph(wchar_t c) const { return InternalGetGlyph(c); } + +void CRasterFont::DrawString(const CDrawStringOptions& options, int x, int y, int& xOut, int& yOut, + CTextRenderBuffer* buffer, const wchar_t* str, int length) const { + if (!x0_initialized) { + return; + } + + if (buffer != nullptr) { + CGraphicsPalette pal(kPF_RGB5A3, 4); + ushort* data = reinterpret_cast< ushort* >(pal.Lock()); + data[0] = CColor(0.f, 0.f, 0.f, 0.f).ToRGB5A3(); + data[1] = CColor(options.GetPaletteEntry(0)).ToRGB5A3(); + data[2] = CColor(options.GetPaletteEntry(1)).ToRGB5A3(); + data[3] = CColor(0.f, 0.f, 0.f, 0.f).ToRGB5A3(); + pal.UnLock(); + buffer->AddPaletteChange(pal); + } + + SinglePassDrawString(options, x, y, xOut, yOut, buffer, str, length); +} + +void CRasterFont::DrawSpace(const CDrawStringOptions& options, int x, int y, int& xOut, int& yOut, + int length) const { + if (options.GetTextDirection() != kTD_Horizontal) { + return; + } + + xOut = x + length; + yOut = y; +} + +int CRasterFont::KernLookup(const rstl::vector< CKernPair >& kern, const int start, const int chr) { + + rstl::vector< CKernPair >::const_iterator it = kern.begin() + start; + for (; it != kern.end() && it->GetFirst() == kern[start].GetFirst(); ++it) { + if (it->GetSecond() == chr) { + return it->GetHowMuch(); + } + } + + return 0; +} + +const CGlyph* CRasterFont::InternalGetGlyph(wchar_t chr) const { + rstl::vector< rstl::pair< wchar_t, CGlyph > >::const_iterator it = + rstl::find_by_key(xc_glyphs, chr); + + if (it == xc_glyphs.end()) { + return nullptr; + } + + return &it->second; +} +#pragma inline_max_size(110) +CFactoryFnReturn FRasterFontFactory(const SObjectTag& tag, CInputStream& in, + const CVParamTransfer& xfer) { + const rstl::rc_ptr< IVParamObj > obj = xfer.x0_obj; + CSimplePool* pool = static_cast< TObjOwnerParam< CSimplePool* >* >(obj.GetPtr())->GetData(); + + return rs_new CRasterFont(in, pool); +} + +void CRasterFont::SetupRenderState() { + static const GXVtxDescList skDescList[] = { + {GX_VA_POS, GX_DIRECT}, + {GX_VA_TEX0, GX_DIRECT}, + {GX_VA_NULL, GX_NONE}, + }; + + TLockedToken< CTexture > texture = *x80_texture; + texture->Load(GX_TEXMAP0, CTexture::kCM_Clamp); + CGX::SetTevKAlphaSel(GX_TEVSTAGE0, GX_TEV_KASEL_K0_A); + CGX::SetTevKColorSel(GX_TEVSTAGE0, GX_TEV_KCSEL_K0); + CGX::SetTevColorIn(GX_TEVSTAGE0, GX_CC_ZERO, GX_CC_TEXC, GX_CC_KONST, GX_CC_ZERO); + CGX::SetTevAlphaIn(GX_TEVSTAGE0, GX_CA_ZERO, GX_CA_TEXA, GX_CA_KONST, GX_CA_ZERO); + CGX::SetStandardTevColorAlphaOp(GX_TEVSTAGE0); + CGX::SetTevDirect(GX_TEVSTAGE0); + CGX::SetVtxDescv(skDescList); + CGX::SetNumChans(0); + CGX::SetNumTexGens(1); + CGX::SetNumTevStages(1); + CGX::SetNumIndStages(0); + CGX::SetTevOrder(GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR_NULL); + CGX::SetTexCoordGen(GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_TEX0, GX_IDENTITY, GX_FALSE, GX_PTIDENTITY); +} + +int CRasterFont::GetBaseLine() const { return x8c_baseline; } +int CRasterFont::GetLineMargin() { return x90_lineMargin; } + +bool CRasterFont::IsFinishedLoading() { return x80_texture && x80_texture->IsLoaded(); } + +void CRasterFont::SetTexture(TToken< CTexture > texture) { + x80_texture = texture; + x80_texture->Lock(); +} diff --git a/src/Kyoto/Text/CTextRenderBuffer.cpp b/src/Kyoto/Text/CTextRenderBuffer.cpp new file mode 100644 index 00000000..417aeaf7 --- /dev/null +++ b/src/Kyoto/Text/CTextRenderBuffer.cpp @@ -0,0 +1,128 @@ +#include "Kyoto/Text/CTextRenderBuffer.hpp" +#include "Kyoto/Graphics/CColor.hpp" +#include "Kyoto/Graphics/CGraphicsPalette.hpp" +#include "Kyoto/Streams/CMemoryStreamOut.hpp" +#include "Kyoto/Text/CFontImageDef.hpp" +#include "Kyoto/Text/CTextColor.hpp" +#include + +CTextRenderBuffer::CTextRenderBuffer(EMode mode) +: mMode(mode) +, mBlobSize(0) +, mCurBytecodeOffset(0) +, mActiveFont(-1) +, mActivePalette(-1) +, mQueuedFont(-1) +, mQueuedPalette(-1) +, mNextPalette(0) {} + +CGraphicsPalette* CTextRenderBuffer::GetNextAvailablePalette() const { + if (mNextPalette >= 64) { + mNextPalette = 0; + } else { + mPalettes.push_back(rstl::auto_ptr< CGraphicsPalette >(rs_new CGraphicsPalette(kPF_RGB5A3, 4))); + } + + ++mNextPalette; + CGraphicsPalette* ret = mPalettes[mNextPalette - 1].get(); + return ret; +} + +int CTextRenderBuffer::GetMatchingPaletteIndex(const CGraphicsPalette& palette) const { + for (int i = 0; i < mPalettes.size(); ++i) { + if (!memcmp(mPalettes[i]->GetPaletteData(), palette.GetPaletteData(), 8)) { + return i; + } + } + return -1; +} + +void CTextRenderBuffer::AddFontChange(const TToken< CRasterFont >& font) { + if (mMode == kM_BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::kOS_NotOwned, 64); + bool found = false; + + for (int fontIndex = 0; fontIndex < mFonts.size(); ++fontIndex) { + if (mFonts[fontIndex].GetRef() == font.GetRef()) { + out.WriteUint8(kC_FontChange); + out.WriteInt8(fontIndex); + found = true; + break; + } + } + + if (!found) { + mFonts.reserve(mFonts.size() + 1); + int fontIndex = mFonts.size(); + mFonts.push_back(font); + out.WriteUint8(kC_FontChange); + out.WriteInt8(fontIndex); + } + mCurBytecodeOffset += out.GetWrittenBytes(); + } else { + // Command + index + mBlobSize += sizeof(char) + sizeof(char); + } +} + +void CTextRenderBuffer::AddPaletteChange(const CGraphicsPalette& palette) { + if (mMode == kM_BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::kOS_NotOwned, 64); + + int paletteIndex = GetMatchingPaletteIndex(palette); + if (paletteIndex == -1) { + GetNextAvailablePalette(); + paletteIndex = mNextPalette - 1; + CGraphicsPalette* destPalette = mPalettes[paletteIndex].get(); + void* data = destPalette->Lock(); + memcpy(data, palette.GetPaletteData(), 8); + destPalette->UnLock(); + } + + out.WriteUint8(kC_PaletteChange); + out.WriteInt8(paletteIndex); + mCurBytecodeOffset += out.GetWrittenBytes(); + } else { + // Command + index + mBlobSize += sizeof(char) + sizeof(char); + } +} + +void CTextRenderBuffer::AddCharacter(const CVector2i& offset, short chr, uint color) { + if (mMode == kM_BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::kOS_NotOwned, 64); + int tmp = mCurBytecodeOffset; + mPrimOffsets.reserve(mPrimOffsets.size() + 1); + mPrimOffsets.push_back(tmp); + out.WriteUint8(kC_CharacterRender); + out.WriteInt16(offset.GetX()); + out.WriteInt16(offset.GetY()); + out.WriteInt16(chr); + out.WriteInt32(color); + mCurBytecodeOffset += out.GetWrittenBytes(); + } else { + // Command + x + y + char + color + mBlobSize += sizeof(char) + sizeof(short) + sizeof(short) + sizeof(short) + sizeof(CTextColor); + } +} + +void CTextRenderBuffer::AddImage(const CVector2i& offset, const CFontImageDef& image) { + if (mMode == kM_BufferFill) { + CMemoryStreamOut out(GetOutStream(), GetCurLen(), CMemoryStreamOut::kOS_NotOwned, 64); + int tmp = mCurBytecodeOffset; + mPrimOffsets.reserve(mPrimOffsets.size() + 1); + mPrimOffsets.push_back(tmp); + mImages.reserve(mImages.size() + 1); + int imageIdx = mImages.size(); + mImages.push_back(image); + out.WriteUint8(kC_ImageRender); + out.WriteInt16(offset.GetX()); + out.WriteInt16(offset.GetY()); + out.WriteInt8(imageIdx); + out.WriteUint32(CColor::White().GetColor_u32()); + mCurBytecodeOffset += out.GetWrittenBytes(); + } else { + // Command + x + y + index + color + mBlobSize += sizeof(char) + sizeof(short) + sizeof(short) + sizeof(char) + sizeof(uint); + } +}