diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index 37df5819..1a378d5a 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -289,6 +289,13 @@ f/f_manager.cpp: .sbss start:0x80575BB8 end:0x80575BC0 .bss start:0x805B84D8 end:0x805B8588 +m/m2d.cpp: + .text start:0x802E2D80 end:0x802E3E50 + .data start:0x805423E8 end:0x805424A0 + .sbss start:0x80575BC8 end:0x80575BD0 + .sdata2 start:0x8057CC98 end:0x8057CCB8 + .bss start:0x805B8588 end:0x805B85C0 + m/m3d/m3d.cpp: .text start:0x802E3E50 end:0x802E4714 .sbss start:0x80575BD0 end:0x80575BEC diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index 9df5e7aa..50ecf1a2 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -17366,50 +17366,50 @@ __arraydtor = .text:0x802E2BF0; // type:function size:0x1C scope:local walkPack__11fTrMgPTMF_cFv = .text:0x802E2C10; // type:function size:0x84 searchNodeByProfName__9fTrMgBa_cCFUsPC9fTrNdBa_c = .text:0x802E2CA0; // type:function size:0x68 searchNodeByGroupType__9fTrMgBa_cCFUcPC9fTrNdBa_c = .text:0x802E2D10; // type:function size:0x68 -fn_802E2D80 = .text:0x802E2D80; // type:function size:0x10 -fn_802E2D90 = .text:0x802E2D90; // type:function size:0x3C -fn_802E2DD0 = .text:0x802E2DD0; // type:function size:0x94 -fn_802E2E70 = .text:0x802E2E70; // type:function size:0x58 -fn_802E2ED0 = .text:0x802E2ED0; // type:function size:0x88 -fn_802E2F60 = .text:0x802E2F60; // type:function size:0x88 -fn_802E2FF0 = .text:0x802E2FF0; // type:function size:0xC -fn_802E3000 = .text:0x802E3000; // type:function size:0x50 -fn_802E3050 = .text:0x802E3050; // type:function size:0x40 -fn_802E3090 = .text:0x802E3090; // type:function size:0x88 -fn_802E3120 = .text:0x802E3120; // type:function size:0x8 -fn_802E3130 = .text:0x802E3130; // type:function size:0x4 -fn_802E3140 = .text:0x802E3140; // type:function size:0x8 -fn_802E3150 = .text:0x802E3150; // type:function size:0x8 -fn_802E3160 = .text:0x802E3160; // type:function size:0x40 -fn_802E31A0 = .text:0x802E31A0; // type:function size:0x94 -fn_802E3240 = .text:0x802E3240; // type:function size:0x64 -fn_802E32B0 = .text:0x802E32B0; // type:function size:0xC -fn_802E32C0 = .text:0x802E32C0; // type:function size:0x8 -fn_802E32D0 = .text:0x802E32D0; // type:function size:0x60 -fn_802E3330 = .text:0x802E3330; // type:function size:0x34 -fn_802E3370 = .text:0x802E3370; // type:function size:0x34 -fn_802E33B0 = .text:0x802E33B0; // type:function size:0x70 -fn_802E3420 = .text:0x802E3420; // type:function size:0x6C -fn_802E3490 = .text:0x802E3490; // type:function size:0x118 -fn_802E35B0 = .text:0x802E35B0; // type:function size:0x58 -fn_802E3610 = .text:0x802E3610; // type:function size:0x84 -fn_802E36A0 = .text:0x802E36A0; // type:function size:0x60 -fn_802E3700 = .text:0x802E3700; // type:function size:0x38 -fn_802E3740 = .text:0x802E3740; // type:function size:0x38 -fn_802E3780 = .text:0x802E3780; // type:function size:0x10 -fn_802E3790 = .text:0x802E3790; // type:function size:0x38 -fn_802E37D0 = .text:0x802E37D0; // type:function size:0x40 -fn_802E3810 = .text:0x802E3810; // type:function size:0x4 -fn_802E3820 = .text:0x802E3820; // type:function size:0x90 -fn_802E38B0 = .text:0x802E38B0; // type:function size:0x78 -fn_802E3930 = .text:0x802E3930; // type:function size:0xF8 -fn_802E3A30 = .text:0x802E3A30; // type:function size:0xC0 -fn_802E3AF0 = .text:0x802E3AF0; // type:function size:0x24 -fn_802E3B20 = .text:0x802E3B20; // type:function size:0x6C -fn_802E3B90 = .text:0x802E3B90; // type:function size:0x170 -fn_802E3D00 = .text:0x802E3D00; // type:function size:0x108 -fn_802E3E10 = .text:0x802E3E10; // type:function size:0x20 -fn_802E3E30 = .text:0x802E3E30; // type:function size:0x20 +reset__3m2dFv = .text:0x802E2D80; // type:function size:0x10 +init__3m2dFP12mAllocator_c = .text:0x802E2D90; // type:function size:0x3C +create__3m2dFPQ23EGG4HeapUl = .text:0x802E2DD0; // type:function size:0x94 +defaultSet__3m2dFv = .text:0x802E2E70; // type:function size:0x58 +draw__3m2dFUc = .text:0x802E2ED0; // type:function size:0x88 +drawBefore__3m2dFUc = .text:0x802E2F60; // type:function size:0x88 +getAllocator__3m2dFv = .text:0x802E2FF0; // type:function size:0xC +CreateAnimTransform__Q23m2d8Layout_cFPCvPQ34nw4r3lyt16ResourceAccessor = .text:0x802E3000; // type:function size:0x50 +__dt__Q23m2d14ResAccIfBase_cFv = .text:0x802E3050; // type:function size:0x40 +__dt__Q23m2d10ResAccIf_cFv = .text:0x802E3090; // type:function size:0x88 +getAccessor__Q23m2d10ResAccIf_cFv = .text:0x802E3120; // type:function size:0x8 +noop__Q23m2d10ResAccIf_cFv = .text:0x802E3130; // type:function size:0x4 +attach__Q23m2d10ResAccIf_cFPvPCc = .text:0x802E3140; // type:function size:0x8 +detach__Q23m2d10ResAccIf_cFv = .text:0x802E3150; // type:function size:0x8 +__dt__Q23m2d11FrameCtrl_cFv = .text:0x802E3160; // type:function size:0x40 +play__Q23m2d11FrameCtrl_cFv = .text:0x802E31A0; // type:function size:0x94 +set__Q23m2d11FrameCtrl_cFfUcff = .text:0x802E3240; // type:function size:0x64 +setFrame__Q23m2d11FrameCtrl_cFf = .text:0x802E32B0; // type:function size:0xC +setRate__Q23m2d11FrameCtrl_cFf = .text:0x802E32C0; // type:function size:0x8 +isStop__Q23m2d11FrameCtrl_cCFv = .text:0x802E32D0; // type:function size:0x60 +getEndFrame__Q23m2d11FrameCtrl_cCFv = .text:0x802E3330; // type:function size:0x34 +getEndFrame2__Q23m2d11FrameCtrl_cCFv = .text:0x802E3370; // type:function size:0x34 +isStop2__Q23m2d11FrameCtrl_cCFv = .text:0x802E33B0; // type:function size:0x70 +__dt__Q23m2d5Anm_cFv = .text:0x802E3420; // type:function size:0x6C +doSomething__Q23m2d5Anm_cFPCcPQ23m2d10ResAccIf_c = .text:0x802E3490; // type:function size:0x118 +__dt__Q23m2d8Layout_cFv = .text:0x802E35B0; // type:function size:0x58 +setTransform__Q23m2d5Anm_cFPQ34nw4r3lyt13AnimTransform = .text:0x802E3610; // type:function size:0x84 +destroySomething__Q23m2d5Anm_cFv = .text:0x802E36A0; // type:function size:0x60 +set__Q23m2d5Anm_cFfUcff = .text:0x802E3700; // type:function size:0x38 +setFrame__Q23m2d5Anm_cFf = .text:0x802E3740; // type:function size:0x38 +updateFrame__Q23m2d5Anm_cFv = .text:0x802E3780; // type:function size:0x10 +play__Q23m2d5Anm_cFv = .text:0x802E3790; // type:function size:0x38 +__dt__Q23m2d6Base_cFv = .text:0x802E37D0; // type:function size:0x40 +draw__Q23m2d6Base_cFv = .text:0x802E3810; // type:function size:0x4 +addToDrawList__Q23m2d6Base_cFv = .text:0x802E3820; // type:function size:0x90 +__dt__Q23m2d8Simple_cFv = .text:0x802E38B0; // type:function size:0x78 +__ct__Q23m2d8Simple_cFv = .text:0x802E3930; // type:function size:0xF8 +calc__Q23m2d8Simple_cFv = .text:0x802E3A30; // type:function size:0xC0 +calcBefore__Q23m2d8Simple_cFv = .text:0x802E3AF0; // type:function size:0x24 +calcAfter__Q23m2d8Simple_cFv = .text:0x802E3B20; // type:function size:0x6C +draw__Q23m2d8Simple_cFv = .text:0x802E3B90; // type:function size:0x170 +build__Q23m2d8Simple_cFPCcPQ23m2d10ResAccIf_c = .text:0x802E3D00; // type:function size:0x108 +bind__Q23m2d8Simple_cFPQ23m2d5Anm_c = .text:0x802E3E10; // type:function size:0x20 +unbind__Q23m2d8Simple_cFPQ23m2d5Anm_c = .text:0x802E3E30; // type:function size:0x20 create__3m3dFPQ23EGG4HeapUlUlUlUl = .text:0x802E3E50; // type:function size:0xEC create__3m3dFPQ23EGG4Heap11_GXPixelFmt8_GXColorUlUlUlUlUlUl = .text:0x802E3F40; // type:function size:0x17C createLightMgr__3m3dFPQ23EGG4HeapUsUsUcbi = .text:0x802E40C0; // type:function size:0x134 @@ -22197,7 +22197,7 @@ fn_803B8510 = .text:0x803B8510; // type:function size:0x12C fn_803B8640 = .text:0x803B8640; // type:function size:0xB0 fn_803B86F0 = .text:0x803B86F0; // type:function size:0x7C PSMTXTrans = .text:0x803B8770; // type:function size:0x34 -fn_803B87B0 = .text:0x803B87B0; // type:function size:0x4C +PSMTXTransApply = .text:0x803B87B0; // type:function size:0x4C PSMTXScale = .text:0x803B8800; // type:function size:0x28 fn_803B8830 = .text:0x803B8830; // type:function size:0x58 PSMTXQuat = .text:0x803B8890; // type:function size:0xA4 @@ -35678,13 +35678,13 @@ lbl_805423B4 = .data:0x805423B4; // type:object size:0xC data:4byte lbl_805423C0 = .data:0x805423C0; // type:object size:0xC data:4byte lbl_805423CC = .data:0x805423CC; // type:object size:0xC data:4byte lbl_805423D8 = .data:0x805423D8; // type:object size:0xC data:4byte -lbl_805423E8 = .data:0x805423E8; // type:object size:0x20 -lbl_80542408 = .data:0x80542408; // type:object size:0x18 -lbl_80542420 = .data:0x80542420; // type:object size:0x10 -lbl_80542430 = .data:0x80542430; // type:object size:0xC -lbl_8054243C = .data:0x8054243C; // type:object size:0xC -lbl_80542448 = .data:0x80542448; // type:object size:0x18 -lbl_80542460 = .data:0x80542460; // type:object size:0x40 +lbl_805423E8 = .data:0x805423E8; // type:object size:0x1C +__vt__Q23m2d8Simple_c = .data:0x80542408; // type:object size:0x18 +__vt__Q23m2d6Base_c = .data:0x80542420; // type:object size:0x10 +__vt__Q23m2d5Anm_c = .data:0x80542430; // type:object size:0xC +__vt__Q23m2d11FrameCtrl_c = .data:0x8054243C; // type:object size:0xC +__vt__Q23m2d10ResAccIf_c = .data:0x80542448; // type:object size:0x14 +__vt__Q23m2d8Layout_c = .data:0x80542460; // type:object size:0x40 __vt__Q23m3d6proc_c = .data:0x805424A0; // type:object size:0x2C __vt__Q23m3d8anmChr_c = .data:0x805424D0; // type:object size:0x18 __vt__Q23m3d13anmChrBlend_c = .data:0x805424E8; // type:object size:0x18 @@ -37207,7 +37207,7 @@ lbl_8056F1B0 = .data:0x8056F1B0; // type:object size:0x20 lbl_8056F1D0 = .data:0x8056F1D0; // type:object size:0x20 lbl_8056F1F0 = .data:0x8056F1F0; // type:object size:0x20 lbl_8056F210 = .data:0x8056F210; // type:object size:0x20 -lbl_8056F230 = .data:0x8056F230; // type:object size:0x24 data:2byte +sTVModeInfo__Q23EGG6Screen = .data:0x8056F230; // type:object size:0x24 data:2byte lbl_8056F254 = .data:0x8056F254; // type:object size:0x14 lbl_8056F268 = .data:0x8056F268; // type:object size:0x10 lbl_8056F278 = .data:0x8056F278; // type:object size:0x38 @@ -40294,8 +40294,8 @@ sLoadAsyncCallback__7fBase_c = .sbss:0x80575BB0; // type:object size:0x4 data:4b sUnloadCallback__7fBase_c = .sbss:0x80575BB4; // type:object size:0x4 data:4byte m_StopProcInf__10fManager_c = .sbss:0x80575BB8; // type:object size:0x4 data:4byte sProfileList__8fProfile = .sbss:0x80575BC0; // type:object size:0x8 data:4byte -lbl_80575BC8 = .sbss:0x80575BC8; // type:object size:0x4 data:4byte -lbl_80575BCC = .sbss:0x80575BCC; // type:object size:0x1 data:byte +l_allocator__3m2d = .sbss:0x80575BC8; // type:object size:0x4 data:4byte +@GUARD@doSomething__Q23m2d5Anm_cFPCcPQ23m2d10ResAccIf_c@l_layout = .sbss:0x80575BCC; // type:object size:0x1 data:byte l_allocator_p__Q23m3d8internal = .sbss:0x80575BD0; // type:object size:0x4 data:4byte l_scnRoot_p__Q23m3d8internal = .sbss:0x80575BD4; // type:object size:0x4 data:4byte l_numLightMgr__Q23m3d8internal = .sbss:0x80575BD8; // type:object size:0x4 data:4byte @@ -40997,7 +40997,7 @@ lbl_8057685C = .sbss:0x8057685C; // type:object size:0x1 data:byte lbl_80576860 = .sbss:0x80576860; // type:object size:0x1 data:byte lbl_80576861 = .sbss:0x80576861; // type:object size:0x7 data:byte lbl_80576868 = .sbss:0x80576868; // type:object size:0x8 data:float -lbl_80576870 = .sbss:0x80576870; // type:object size:0x4 data:4byte +sTVMode__Q23EGG6Screen = .sbss:0x80576870; // type:object size:0x4 data:4byte lbl_80576874 = .sbss:0x80576874; // type:object size:0x4 data:4byte lbl_80576878 = .sbss:0x80576878; // type:object size:0x4 data:4byte lbl_8057687C = .sbss:0x8057687C; // type:object size:0x4 data:4byte @@ -45833,7 +45833,7 @@ lbl_8057CC98 = .sdata2:0x8057CC98; // type:object size:0x4 data:float lbl_8057CC9C = .sdata2:0x8057CC9C; // type:object size:0x4 data:float lbl_8057CCA0 = .sdata2:0x8057CCA0; // type:object size:0x4 data:float lbl_8057CCA8 = .sdata2:0x8057CCA8; // type:object size:0x8 data:double -lbl_8057CCB0 = .sdata2:0x8057CCB0; // type:object size:0x8 data:float +lbl_8057CCB0 = .sdata2:0x8057CCB0; // type:object size:0x4 data:float lbl_8057CCB8 = .sdata2:0x8057CCB8; // type:object size:0x4 data:float lbl_8057CCC0 = .sdata2:0x8057CCC0; // type:object size:0x4 data:float lbl_8057CCC4 = .sdata2:0x8057CCC4; // type:object size:0x4 data:float @@ -49114,9 +49114,9 @@ m_executeManage__10fManager_c = .bss:0x805B84FC; // type:object size:0x14 data:4 m_drawManage__10fManager_c = .bss:0x805B8510; // type:object size:0x14 data:4byte m_deleteManage__10fManager_c = .bss:0x805B8524; // type:object size:0x14 data:4byte m_searchManage__10fManager_c = .bss:0x805B8548; // type:object size:0x40 -lbl_805B8588 = .bss:0x805B8588; // type:object size:0xC +l_list__3m2d = .bss:0x805B8588; // type:object size:0xC lbl_805B8594 = .bss:0x805B8594; // type:object size:0xC -lbl_805B85A0 = .bss:0x805B85A0; // type:object size:0x20 data:4byte +@LOCAL@doSomething__Q23m2d5Anm_cFPCcPQ23m2d10ResAccIf_c@l_layout = .bss:0x805B85A0; // type:object size:0x20 data:4byte s_UncompressInfoSZS__4mDvd = .bss:0x805B85C0; // type:object size:0xC data:4byte s_UncompressInfoLZ__4mDvd = .bss:0x805B85CC; // type:object size:0xC data:4byte s_UncompressInfoLH__4mDvd = .bss:0x805B85D8; // type:object size:0xC data:4byte diff --git a/configure.py b/configure.py index 6e806507..7e46bca0 100644 --- a/configure.py +++ b/configure.py @@ -374,6 +374,7 @@ def nw4rLib(lib_name, objects, extra_cflags=[]): Object(Matching, "m/m3d/m_mdl.cpp"), Object(Matching, "m/m3d/m_scnleaf.cpp"), Object(Matching, "m/m3d/m_smdl.cpp"), + Object(Matching, "m/m2d.cpp"), Object(Matching, "m/m_allocator.cpp"), Object(Matching, "m/m_angle.cpp"), Object(Matching, "m/m_color_fader.cpp"), diff --git a/include/egg/gfx/eggFrustum.h b/include/egg/gfx/eggFrustum.h index 770dd328..92c8579f 100644 --- a/include/egg/gfx/eggFrustum.h +++ b/include/egg/gfx/eggFrustum.h @@ -10,13 +10,41 @@ namespace EGG { class Frustum { public: enum CanvasMode {}; - enum ProjectionType {}; + enum ProjectionType { PROJ_ORTHO, PROJ_PERSP }; - u8 TODO_0x00[0x38]; +private: + /* 0x00 */ ProjectionType mProjType; + /* 0x04 */ CanvasMode mCanvasMode; + /* 0x08 */ nw4r::math::VEC2 mSize; + /* 0x10 */ f32 mFovY; + /* 0x14 */ f32 mTanFovY; + /* 0x18 */ f32 mNearZ; + /* 0x1C */ f32 mFarZ; + /* 0x20 */ nw4r::math::VEC2 mOffset; + /* 0x28 */ nw4r::math::VEC3 mScale; + /* 0x34 */ mutable u16 mFlags; + +public: // vt at 0x38 - virtual ~Frustum(); + virtual ~Frustum() {} virtual void SetProjectionGX() const; virtual void CopyToG3D(nw4r::g3d::Camera) const; + + ProjectionType GetProjectionType() const { + return mProjType; + } + void SetProjectionType(ProjectionType type) { + mProjType = type; + } + + void ResetOrthographic(f32, f32, f32, f32, f32, f32); + + void SetScale(const nw4r::math::VEC3 &scale) { + mScale = scale; + } + void SetOffset(const nw4r::math::VEC2 &offset) { + mOffset = offset; + } }; } // namespace EGG diff --git a/include/egg/gfx/eggScreen.h b/include/egg/gfx/eggScreen.h index b1b1c422..e5432150 100644 --- a/include/egg/gfx/eggScreen.h +++ b/include/egg/gfx/eggScreen.h @@ -12,7 +12,7 @@ class Screen : public Frustum { Screen(); Screen(f32, f32, f32, f32, Screen *, CanvasMode); - virtual ~Screen(); + virtual ~Screen() {} virtual void SetProjectionGX() const override; virtual void CopyToG3D(nw4r::g3d::Camera) const override; @@ -20,6 +20,64 @@ class Screen : public Frustum { static void SetTVModeDefault(); u8 TODO_0x3C[0x88 - 0x3C]; + + enum TVMode { TV_MODE_1, TV_MODE_2, TV_MODE_3, TV_MODE_4, TV_MODE_MAX }; + + struct TVModeInfo { + TVModeInfo() {} + u16 width; + u16 height; + f32 w_ratio; + f32 h_ratio; + }; + + struct DataEfb { + // Required for struct copy + struct Viewport { + f32 x1; // at 0x0 + f32 y1; // at 0x4 + f32 x2; // at 0x8 + f32 y2; // at 0xC + f32 z1; // at 0x10 + f32 z2; // at 0x14 + } vp; + + s32 sc_ox; // at 0x18 + s32 sc_oy; // at 0x1C + }; + + static u16 GetSizeXMax(TVMode mode) { + return sTVModeInfo[mode].width; + } + static u16 GetSizeYMax(TVMode mode) { + return sTVModeInfo[mode].height; + } + static u16 GetSizeXMax() { + return sTVModeInfo[sTVMode].width; + } + static u16 GetSizeYMax() { + return sTVModeInfo[sTVMode].height; + } + + static inline f32 GetAdjustScale() { + return (f32)sTVModeInfo[0].width / sTVModeInfo[Screen::sTVMode].width; + } + + static TVMode GetTVMode() { + return sTVMode; + } + + static TVMode sTVMode; + + static Screen *spRoot; + + typedef void (*ChangeTVModeFunc)(void *); + static ChangeTVModeFunc sChangeTVModeFunc; + static void *spChangeTVModeFuncInfo; + static TVModeInfo sTVModeInfo[Screen::TV_MODE_MAX]; + + static nw4r::math::VEC2 sCanvasScale; + static nw4r::math::VEC2 sCanvasOffset; }; } // namespace EGG diff --git a/include/m/m2d.h b/include/m/m2d.h new file mode 100644 index 00000000..968fabc0 --- /dev/null +++ b/include/m/m2d.h @@ -0,0 +1,153 @@ +#ifndef M_M2D_H +#define M_M2D_H + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +namespace m2d { + +extern nw4r::ut::List l_list; +extern mAllocator_c *l_allocator; + +class Layout_c : public nw4r::lyt::Layout { +public: + virtual ~Layout_c() {} + virtual nw4r::lyt::AnimTransform *CreateAnimTransform(const void *animResBuf, + nw4r::lyt::ResourceAccessor *pResAcsr) override; +}; + +class ResAccIfBase_c { +public: + ~ResAccIfBase_c(); +}; + +class ResAccIf_c : ResAccIfBase_c { +public: + virtual ~ResAccIf_c(); + virtual void noop(); + virtual nw4r::lyt::ArcResourceAccessor *getAccessor(); + + void attach(void *data, const char *name); + void detach(); + +private: + nw4r::lyt::ArcResourceAccessor mAccessor; +}; + +#define FLAG_NO_LOOP 1 +#define FLAG_BACKWARDS 2 + +class FrameCtrl_c { +public: + virtual ~FrameCtrl_c(); + + void play(); + void set(f32 endFrame, u8 flags, f32 rate, f32 currFrame); + void setFrame(f32 frame); + void setRate(f32 rate); + + bool isStop() const; + bool isStop2() const; + f32 getEndFrame() const; + f32 getEndFrame2() const; + + inline f32 getFrame() { + return mCurrFrame; + } + +private: + inline bool notLooping() const { + return (mFlags & FLAG_NO_LOOP) != 0; + } + + inline bool isBackwards() const { + return (mFlags & FLAG_BACKWARDS) != 0; + } + + f32 mEndFrame; + f32 mCurrFrame; + f32 mPrevFrame; + f32 mRate; + u8 mFlags; +}; + +class Anm_c { +public: + virtual ~Anm_c(); + + bool doSomething(const char *path, ResAccIf_c *acc); + void setTransform(nw4r::lyt::AnimTransform *transform); + void destroySomething(); + void set(f32 endFrame, u8 flags, f32 rate, f32 currFrame); + void setFrame(f32 frame); + void play(); + + inline nw4r::lyt::AnimTransform *getTransform() { + return mpTransform; + } + + inline void setBound() { + mFlags |= 1; + } + + inline void setUnbound() { + mFlags &= ~1; + } + +private: + void updateFrame(); + nw4r::lyt::AnimTransform *mpTransform; + FrameCtrl_c mFrameCtrl; + +public: + u8 mFlags; +}; + +class Base_c { +public: + Base_c(u8 priority) : mPriority(priority) {} + /* 0x00 */ nw4r::ut::Node mLink; + /* vt 0x04 */ + virtual ~Base_c(); + virtual void draw(); + /* 0x0C */ u8 mPriority; + + void addToDrawList(); +}; + +class Simple_c : public Base_c { +public: + Simple_c(); + virtual ~Simple_c(); + virtual void draw() override; + virtual void calc(); + virtual bool build(const char *name, ResAccIf_c *acc); + + void calcBefore(); + void calcAfter(); + + void bind(Anm_c *anm); + void unbind(Anm_c *anm); + + bool flagSet() { + return (field_0x94 & 1) ? 1 : 0; + } + +private: + Layout_c mLayout; + nw4r::lyt::DrawInfo mDrawInfo; + ResAccIf_c *mpResAcc; + mVec3_c mVec; + u32 field_0x94; +}; + +} // namespace m2d + +#endif diff --git a/include/nw4r/g3d/g3d_anmfog.h b/include/nw4r/g3d/g3d_anmfog.h index 565f1bd3..cb9f96da 100644 --- a/include/nw4r/g3d/g3d_anmfog.h +++ b/include/nw4r/g3d/g3d_anmfog.h @@ -1,7 +1,7 @@ #ifndef NW4R_G3D_ANMFOG_H #define NW4R_G3D_ANMFOG_H #include "common.h" -#include "ut_Color.h" +#include #include namespace nw4r { diff --git a/include/nw4r/lyt/lyt_layout.h b/include/nw4r/lyt/lyt_layout.h index 74b970ad..8f668e2f 100644 --- a/include/nw4r/lyt/lyt_layout.h +++ b/include/nw4r/lyt/lyt_layout.h @@ -43,6 +43,14 @@ class Layout { virtual void Animate(u32 option); // at 0x38 virtual void SetTagProcessor(ut::TagProcessorBase *pTagProcessor); // at 0x3C + ut::LinkList &GetAnimTransformList() { + return mAnimTransList; + } + + Pane *GetRootPane() const { + return mpRootPane; + } + private: ut::LinkList mAnimTransList; // at 0x04 Pane *mpRootPane; // at 0x10 diff --git a/src/m/m2d.cpp b/src/m/m2d.cpp new file mode 100644 index 00000000..dab95700 --- /dev/null +++ b/src/m/m2d.cpp @@ -0,0 +1,350 @@ +#include +#include +#include + +#include + +#include +#include + +namespace m2d { + +nw4r::ut::List l_list; +mAllocator_c *l_allocator; + +void reset() { + nw4r::ut::List_Init(&l_list, 0); +} + +bool init(mAllocator_c *allocator) { + nw4r::lyt::LytInit(); + l_allocator = allocator; + nw4r::lyt::Layout::mspAllocator = allocator; + reset(); + return true; +} + +void create(EGG::Heap *heap, u32 size) { + if (size != 0) { + heap = EGG::ExpHeap::create(size, heap, 0); + // Supposed to be 2D表示用ヒープ(m2d::create), but creates a linux compile issue + heap->setName("2D\x95\x5C示用ヒープ(m2d::create)"); + } + mAllocator_c *allocator = new (heap, 0x04) mAllocator_c(); + allocator->attach(heap, 4); + init(allocator); +} + +// TODO This is literally the first sbss2 symbol. +extern "C" GXColor lbl_8057FFA0; + +void defaultSet() { + GXSetCullMode(GX_CULL_NONE); + GXSetZMode(false, GX_ALWAYS, false); + GXSetFog(GX_FOG_NONE, lbl_8057FFA0, 0.0f, 0.0f, 0.0f, 0.0f); +} + +void draw(u8 priority) { + for (Base_c *base = static_cast(nw4r::ut::List_GetFirst(&l_list)); base != nullptr; + base = static_cast(nw4r::ut::List_GetNext(&l_list, base))) { + if (base->mPriority >= priority) { + break; + } + base->draw(); + } +} + +void drawBefore(u8 priority) { + for (Base_c *base = static_cast(nw4r::ut::List_GetFirst(&l_list)); base != nullptr; + base = static_cast(nw4r::ut::List_GetNext(&l_list, base))) { + if (base->mPriority > priority) { + base->draw(); + } + } +} + +// Despite the name this *updates* Lyt's allocator +void getAllocator() { + nw4r::lyt::Layout::mspAllocator = l_allocator; +} + +nw4r::lyt::AnimTransform *Layout_c::CreateAnimTransform(const void *animResBuf, nw4r::lyt::ResourceAccessor *pResAcsr) { + nw4r::lyt::AnimTransform *result = nw4r::lyt::Layout::CreateAnimTransform(animResBuf, pResAcsr); + if (result != nullptr) { + GetAnimTransformList().Erase(result); + } + return result; +} + +ResAccIfBase_c::~ResAccIfBase_c() {} +ResAccIf_c::~ResAccIf_c() {} + +nw4r::lyt::ArcResourceAccessor *ResAccIf_c::getAccessor() { + return &mAccessor; +} + +void ResAccIf_c::noop() {} + +void ResAccIf_c::attach(void *data, const char *name) { + mAccessor.Attach(data, name); +} +void ResAccIf_c::detach() { + mAccessor.Detach(); +} + +FrameCtrl_c::~FrameCtrl_c() {} + +void FrameCtrl_c::play() { + mPrevFrame = mCurrFrame; + f32 newFrame; + if (isBackwards()) { + if (mCurrFrame >= mRate) { + newFrame = mCurrFrame - mRate; + } else { + if (notLooping()) { + newFrame = 0.0f; + } else { + newFrame = mCurrFrame + (mEndFrame - mRate); + } + } + } else { + newFrame = mCurrFrame + mRate; + if (notLooping()) { + f32 forwardsEnd = mEndFrame - 1.0f; + if (newFrame > forwardsEnd) { + newFrame = forwardsEnd; + } + } else { + if (newFrame >= mEndFrame) { + newFrame = newFrame - mEndFrame; + } + } + } + + mCurrFrame = newFrame; +} + +void FrameCtrl_c::set(f32 endFrame, u8 flags, f32 rate, f32 currFrame) { + if (currFrame < 0.0f) { + currFrame = 0.0f; + } + mEndFrame = endFrame; + mCurrFrame = currFrame; + setRate(rate); + mFlags = flags; + mPrevFrame = mCurrFrame; +} + +void FrameCtrl_c::setFrame(f32 frame) { + mCurrFrame = frame; + mPrevFrame = frame; +} + +void FrameCtrl_c::setRate(f32 rate) { + mRate = rate; +} + +bool FrameCtrl_c::isStop() const { + f32 actualEnd; + switch (mFlags) { + case FLAG_NO_LOOP: + actualEnd = mEndFrame - 1.0f; + return mCurrFrame >= actualEnd; + case FLAG_NO_LOOP | FLAG_BACKWARDS: + return mCurrFrame <= 0; + default: + return false; + } +} + +f32 FrameCtrl_c::getEndFrame() const { + if (isBackwards()) { + if (notLooping()) { + return mEndFrame - 1.0f; + } + return mEndFrame; + } + + return 0.0f; +} + +f32 FrameCtrl_c::getEndFrame2() const { + if (isBackwards()) { + return 0.0f; + } + if (notLooping()) { + return mEndFrame - 1.0f; + } + return mEndFrame; +} + +bool FrameCtrl_c::isStop2() const { + if (isBackwards()) { + return mCurrFrame <= 0.0f; + } + if (notLooping()) { + f32 actualEnd = mEndFrame - 1.0f; + return mCurrFrame >= actualEnd; + } + return mCurrFrame >= mEndFrame; +} + +Anm_c::~Anm_c() { + destroySomething(); +} + +bool Anm_c::doSomething(const char *path, ResAccIf_c *acc) { + if (mpTransform != nullptr) { + destroySomething(); + } + + static Layout_c l_layout; + + void *resource = acc->getAccessor()->GetResource(0, path, nullptr); + nw4r::lyt::AnimTransform *transform = l_layout.CreateAnimTransform(resource, acc->getAccessor()); + if (transform == nullptr) { + return false; + } + + setTransform(transform); + return true; +} + +void Anm_c::setTransform(nw4r::lyt::AnimTransform *transform) { + mpTransform = transform; + u8 flags = 1; + if (mpTransform->IsLoopData()) { + flags = 0; + } + set(mpTransform->GetFrameSize(), flags, 1.0f, -1.0); +} + +void Anm_c::destroySomething() { + if (mpTransform != nullptr) { + mpTransform->~AnimTransform(); + nw4r::lyt::Layout::FreeMemory(mpTransform); + mpTransform = nullptr; + } +} + +void Anm_c::set(f32 endFrame, u8 flags, f32 rate, f32 currFrame) { + mFrameCtrl.set(endFrame, flags, rate, currFrame); + updateFrame(); +} + +void Anm_c::setFrame(f32 frame) { + mFrameCtrl.setFrame(frame); + updateFrame(); +} + +void Anm_c::updateFrame() { + mpTransform->SetFrame(mFrameCtrl.getFrame()); +} + +void Anm_c::play() { + mFrameCtrl.play(); + updateFrame(); +} + +Base_c::~Base_c() {} +void Base_c::draw() {} + +void Base_c::addToDrawList() { + Base_c *target = static_cast(nw4r::ut::List_GetFirst(&l_list)); + while (target != nullptr) { + if (target->mPriority > mPriority) { + nw4r::ut::List_Insert(&l_list, target, this); + return; + } + + target = static_cast(nw4r::ut::List_GetNext(&l_list, target)); + } + nw4r::ut::List_Append(&l_list, this); +} + +Simple_c::~Simple_c() {} +Simple_c::Simple_c() : Base_c(0x80), mLayout(), mDrawInfo(), mpResAcc(nullptr), mVec(0.0f, 0.0f, 0.0f), field_0x94(0) { + if (SCGetAspectRatio() == 1) { + mDrawInfo.SetLocationAdjustScale(nw4r::math::VEC2(EGG::Screen::GetAdjustScale(), 1.0f)); + mDrawInfo.SetLocationAdjust(true); + } +} + +void Simple_c::calc() { + calcBefore(); + nw4r::math::MTX34 mtx; + PSMTXIdentity(mtx.m); + // Probably inlines + mVec3_c v = mVec; + PSMTXTransApply(mtx.m, mtx.m, v.x, v.y, v.z); + mDrawInfo.SetViewMtx(mtx); + calcAfter(); +} + +void Simple_c::calcBefore() { + u32 flag = 0; + if ((field_0x94 & 1) != 0) { + flag = 1; + } + mLayout.Animate(flag); +} + +void Simple_c::calcAfter() { + mDrawInfo.SetViewRect(mLayout.GetLayoutRect()); + mLayout.CalculateMtx(mDrawInfo); +} + +void Simple_c::draw() { + nw4r::ut::Rect r = mLayout.GetLayoutRect(); + f32 near = 0.0f; + f32 far = 500.0f; + EGG::Screen s; + bool needsAdjust = EGG::Screen::GetTVMode() == EGG::Screen::TV_MODE_2; + f32 f1 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_2); + f32 f2 = EGG::Screen::GetSizeXMax(EGG::Screen::TV_MODE_1); + + f32 left = needsAdjust ? f1 * r.left / f2 : r.left; + f32 right = needsAdjust ? f1 * r.right / f2 : r.right; + s.SetProjectionType(EGG::Frustum::PROJ_ORTHO); + s.ResetOrthographic(r.top, r.bottom, left, right, near, far); + if (needsAdjust) { + s.SetScale(nw4r::math::VEC3(f2 / f1, 1.0f, 1.0f)); + } + s.SetProjectionGX(); + mLayout.Draw(mDrawInfo); +} + +bool Simple_c::build(const char *name, ResAccIf_c *acc) { + if (mLayout.GetRootPane() != nullptr) { + return true; + } + if (acc == nullptr) { + acc = mpResAcc; + if (acc == nullptr) { + return false; + } + } + + void *resource = acc->getAccessor()->GetResource(0, name, nullptr); + if (resource == nullptr) { + return false; + } else { + bool success = mLayout.Build(resource, acc->getAccessor()); + if (success) { + calc(); + } + return success; + } +} + +void Simple_c::bind(Anm_c *anm) { + anm->setBound(); + mLayout.BindAnimation(anm->getTransform()); +} + +void Simple_c::unbind(Anm_c *anm) { + anm->setUnbound(); + mLayout.UnbindAnimation(anm->getTransform()); +} + +} // namespace m2d