diff --git a/config/sly1.yaml b/config/sly1.yaml index b91d33d2..e48b876f 100644 --- a/config/sly1.yaml +++ b/config/sly1.yaml @@ -411,9 +411,10 @@ segments: #- [0x, data, P2/jlo] - [0x163a50, data, P2/joy] - - [0x163e10, data] - #- [0x, data, P2/jt] + - [0x163e10, data] # TODO fix jt splits + #- [0x163e10, data, P2/jt] + #- [0x163e41, data] # TBD #- [0x, data, P2/jp] #- [0x, data, P2/jsg] @@ -492,7 +493,7 @@ segments: #- [0x, data, P2/stephide] #- [0x, data, P2/steppipe] #- [0x, data, P2/steppower] - #- [0x, data, P2/steprail] #? unconfirmed name + #- [0x175f90, data, P2/steprail] #- [0x, data, P2/steprun] #- [0x, data, P2/stepside] #- [0x, data, P2/stepzap] diff --git a/config/symbol_addrs.txt b/config/symbol_addrs.txt index 4d2b7d5d..efaf9899 100644 --- a/config/symbol_addrs.txt +++ b/config/symbol_addrs.txt @@ -80,7 +80,9 @@ InitAlo__FP3ALO = 0x123ED0; // type:func SnipAloObjects__FP3ALOiP4SNIP = 0x124DF8; // type:func UpdateAlo__FP3ALOf = 0x124FC0; // type:func LoadAloFromBrx__FP3ALOP18CBinaryInputStream = 0x1289C0; // type:func -SetAloTargetHitTest__FP3ALOi = 0x12AA28; // type:func +FadeAloIn__FP3ALOf = 0x126cb8 = 0x126CB8; // type:func +FadeAloOut__FP3ALOf = 0x126d60; // type:func +SetAloTargetHitTest__FP3ALOi = 0x12AA28; // type:func //////////////////////////////////////////////////////////////// // P2/binoc.c @@ -579,6 +581,14 @@ FIsJtSoundBase__FP2JT = 0x177E20; // type:func CollectJtPrize__FP2JT3PCKP3ALO = 0x177E70; // type:func PlayJtDialog__FP2JTP6DIALOG = 0x177F98; // type:func +g_pjt = 0x262e10; // size:0x4 + + +//////////////////////////////////////////////////////////////// +// P2/lo.c +//////////////////////////////////////////////////////////////// +FIsLoInWorld__FP2LO = 0x182fc8; // type:func + //////////////////////////////////////////////////////////////// // P2/main.c @@ -610,6 +620,12 @@ ClearPhase__Fv = 0x191EB0; // type:func g_phase = 0x269ba4; // size:0x4 +//////////////////////////////////////////////////////////////// +// P2/po.c +//////////////////////////////////////////////////////////////// +PpoCur__Fv = 0x1925f0; // type:func + + //////////////////////////////////////////////////////////////// // P2/prog.c //////////////////////////////////////////////////////////////// @@ -728,7 +744,7 @@ g_unkblot6 = 0x26dfc8; // size:0x280 g_unkblot7 = 0x26e248; // size:0x280 g_unkblot8 = 0x26e4e0; // size:0x280 g_unkblot9 = 0x26e760; // size:0x280 -g_unkblot10 = 0x26e9f8; // size:0x280 +g_note = 0x26e9f8; // size:0x280 g_unkblot11 = 0x26eed0; // size:0x280 g_totals = 0x26f138; // size:0x280 @@ -740,6 +756,19 @@ SetFsp__F3FSP = 0x1D29C8; // type:func UpdateJtActivePowerUp__FP2JTP3JOY = 0x1d2bb8; // type:func IRotatePowerUp__FP3JOYiiPi = 0x1d3100; // type:func +s_mpfspachz = 0x274f58; //size:0x1c +g_fsp = 0x274f74; //size:0x4 +// float[3] @ 0x274f78 +RT_JtSpeedUpClock = 0x274f84; // size:0x4 +RT_JtSlowDownClock = 0x274f88; // size:0x4 + + +//////////////////////////////////////////////////////////////// +// P2/steprail.c +//////////////////////////////////////////////////////////////// +func_001D32D8__FiP2JTl = 0x1D32D8; // type:func +func_001D31D0__FP2LOi = 0x1D31D0; // type:func + //////////////////////////////////////////////////////////////// // P2/sw.c diff --git a/include/alo.h b/include/alo.h index 28c80765..bffdb81a 100644 --- a/include/alo.h +++ b/include/alo.h @@ -82,6 +82,16 @@ void SnipAloObjects(ALO *palo, int csnip, SNIP *asnip); */ void UpdateAlo(ALO *palo, float dt); +/** + * Fades in an ALO + */ +void FadeAloIn(ALO *palo, float dtFade); + +/** + * Fades out an ALO + */ +void FadeAloOut(ALO *palo, float dtFade); + /** * @brief unknown */ diff --git a/include/clock.h b/include/clock.h index f3dc050b..f5f70076 100644 --- a/include/clock.h +++ b/include/clock.h @@ -24,6 +24,11 @@ struct CLOCK TICK tickFrame; }; +extern float g_rtClock; +extern float g_rtClockPowerUp; +extern CLOCK g_clock; +//extern TICK s_tickLastRaw;; // Should be static? + /** * @brief Sets the rate of the global clock. * diff --git a/include/common.h b/include/common.h index c38596cb..60923733 100644 --- a/include/common.h +++ b/include/common.h @@ -9,6 +9,7 @@ #include "include_asm.h" #include "include_rodata.h" #include "types.h" +#include "vtables.h" /** * @brief RGBA color value. diff --git a/include/game.h b/include/game.h index aed897b8..09e8b681 100644 --- a/include/game.h +++ b/include/game.h @@ -146,7 +146,7 @@ struct GS GRFVAULT grfvault; // Unlocked powerup flags unsigned int unlocked_cutscenes; unsigned int fgs; - int nPowerupLast; // Last selected powerup + int fspLast; // Last selected powerup }; /** diff --git a/include/jt.h b/include/jt.h index 939622fd..ed15149e 100644 --- a/include/jt.h +++ b/include/jt.h @@ -9,22 +9,108 @@ #include "common.h" #include +/** + * JT state. + * + * @note Based on May proto, may be inaccurate. + */ +enum JTS +{ + JTS_Stand = 0, + JTS_Run = 1, + JTS_Jump = 2, + JTS_Hang = 3, + JTS_Zap = 4, + JTS_Sidestep = 5, + JTS_Hide = 6, + JTS_Pipe = 7, + JTS_Edge = 8, + JTS_Celebrate = 9, + JTS_Rush = 10, + JTS_Puppet = 11, + JTS_Peek = 12, + JTS_Ski = 13, + JTS_Ball = 14, + JTS_Max = 15 +}; + +/** + * JT body state. + * + * @note Based on May proto, may be inaccurate. + */ +enum JTBS +{ + JTBS_Nil = -1, + JTBS_Jump_Init = 0, + JTBS_Jump_Rise = 1, + JTBS_Jump_Fall = 2, + JTBS_Jump_Boost = 3, + JTBS_Jump_In = 4, + JTBS_Jump_Out = 5, + JTBS_Jump_Thrown = 6, + JTBS_Jump_Smash = 7, + JTBS_Jump_Dive = 8, + JTBS_Jump_Target = 9, + JTBS_Jump_Spire = 10, + JTBS_Jump_Rail = 11, + JTBS_Jump_Hshape = 12, + JTBS_Jump_Hpnt = 13, + JTBS_Hide_Stand = 14, + JTBS_Hide_Sidestep = 15, + JTBS_Hide_PeekLeft = 16, + JTBS_Hide_PeekRight = 17, + JTBS_Hide_Run = 18, + JTBS_Hide_Spin = 19, + JTBS_Pipe_Init = 20, + JTBS_Pipe_Stay = 21, + JTBS_Pipe_Up = 22, + JTBS_Pipe_Down = 23, + JTBS_Pipe_Spin = 24, + JTBS_Celebrate_Key = 25, + JTBS_Celebrate_Timed = 26, + JTBS_Celebrate_UseKey = 27, + JTBS_Rush_Attack = 28, + JTBS_Rush_Bounce = 29, + JTBS_Peek_Enter = 30, + JTBS_Peek_Peek = 31, + JTBS_Peek_Exit = 32, + JTBS_Zap_Blunt = 33, + JTBS_Zap_Electric = 34, + JTBS_Zap_Fire = 35, + JTBS_Zap_Water = 36 +}; + /** * @brief Sly entity. * * JT = "jewel thief" = codename for Sly. * - * @todo Implement struct. + * @todo Match all structs it inherits from. */ struct JT : public STEP { - // ... + uchar padding[0x1248]; + LO *ploMine_1518; + uchar padding2[0xd03]; + int unk2220; + uchar padding3[0x52c]; + int unk2750; }; +/** + * @brief Sets the JT state and JT body state on the given JT. + * + * @param pjt Pointer to the JT instance. + * @param jts JT state value + * @param JTBS JT body state value + */ +void SetJtJts(JT *pjt, JTS jts, JTBS jtbs); + /** * @brief Stubbed, does nothing. * - * @param pjt Pointer to JT entity. + * @param pjt Pointer to JT instance. * @param fProfile Profile flag. * * @deprecated diff --git a/include/lo.h b/include/lo.h index 72675332..54e596d3 100644 --- a/include/lo.h +++ b/include/lo.h @@ -33,4 +33,9 @@ struct LO : public BASIC ulong dtickPerf; }; +/** + * Checks if the LO is currently in the world. + */ +int FIsLoInWorld(LO *PLO); + #endif // LO_H diff --git a/include/po.h b/include/po.h index a404b8ad..db0d0250 100644 --- a/include/po.h +++ b/include/po.h @@ -10,13 +10,18 @@ #include /** - * @brief TBD + * @brief Player object. * - * @todo Implement struct. + * @todo Implement struct fields. */ struct PO : public SO { // ... }; +/** + * @brief Gets a pointer to the current PO. + */ +PO *PpoCur(); + #endif // PO_H diff --git a/include/screen.h b/include/screen.h index c8843d1c..d30ac360 100644 --- a/include/screen.h +++ b/include/screen.h @@ -52,7 +52,10 @@ struct BLOTI struct BLOT { - void *pvtblot; + union { + VTBLOT *pvtblot; + VTNOTE *pvtnote; + }; CFont *pfont; char achzDraw[512]; RGBA rgba; @@ -142,9 +145,17 @@ extern TOTALS g_totals; struct NOTE : public BLOT { - // empty + u32 unk260; + u32 unk264; + u32 unk268; + u32 unk26C; + u32 unk270; + u32 unk274; + struct NOTE* unk278; }; +extern NOTE g_note; + // MARK: Letterbox struct LETTERBOX : public BLOT @@ -190,6 +201,12 @@ class CTextEdge RGBA m_rgba; }; +// Global blots +extern LIFECTR g_lifectr; +extern CLUECTR g_cluectr; +extern KEYCTR g_keyctr; +extern COINCTR g_coinctr; + void StartupScreen(); void PostBlotsLoad(); diff --git a/include/steppower.h b/include/steppower.h index 8c286506..b315a512 100644 --- a/include/steppower.h +++ b/include/steppower.h @@ -13,14 +13,33 @@ */ enum FSP { - FSP_Nil = -1, - FSP_Dive = 0, - FSP_SpeedUpClock = 1, - FSP_SlowDownClock = 2, - FSP_Ball = 3, - FSP_Max = 4 + FSP_Nil=-1, + FSP_Dive=0, + FSP_Ball=1, + FSP_SlowDownClock=2, + FSP_Mine=3, + FSP_SpeedUpClock=4, + FSP_Decoy=5, + FSP_Stun=6, + FSP_Max=7 }; +extern FSP g_fsp; + +/*static const char *s_mpfspachz[] = { + "&2T&.: Dive", + "&2T&.: Roll", + "&2T&.: Slow", + "&2T&.: Mine", + "&2T&.: Fast", + "&2T&.: Decoy", + "&2T&.: Stun" +};*/ +extern const char *s_mpfspachz[]; + +extern float RT_JtSpeedUpClock; +extern float RT_JtSlowDownClock; + /** * @brief Set the selected powerup. */ diff --git a/include/steprail.h b/include/steprail.h new file mode 100644 index 00000000..65ed6223 --- /dev/null +++ b/include/steprail.h @@ -0,0 +1,21 @@ +/** + * @file steprail.h + * + * @brief Rail behavior for STEP objects. + */ +#ifndef STEPRAIL_H +#define STEPRAIL_H +#include "common.h" +#include + +/** + * @brief Unknown function, more research needed. + */ +void func_001D31D0(LO *param_1, int param_2); + +/** + * @brief Unknown function, more research needed. + */ +void func_001D32D8(int param_1, JT *param_2, long param_3); + +#endif // STEPRAIL_H diff --git a/include/types.h b/include/types.h index 7ca8ab9d..755f228b 100644 --- a/include/types.h +++ b/include/types.h @@ -52,5 +52,6 @@ typedef float f32; typedef double f64; typedef uint size_t; +#define nullptr (void *)0x0 #endif // TYPES_H diff --git a/include/ui.h b/include/ui.h index f46d254d..709e4871 100644 --- a/include/ui.h +++ b/include/ui.h @@ -9,9 +9,38 @@ #include "common.h" #include -extern LIFECTR g_lifectr; -extern CLUECTR g_cluectr; -extern KEYCTR g_keyctr; -extern COINCTR g_coinctr; +/** + * @brief User interface state. + */ +enum UIS +{ + UIS_Nil = -1, + UIS_Splash = 0, + UIS_Attract = 1, + UIS_Playing = 2, + UIS_Pausing = 3, + UIS_Paused = 4, + UIS_Unpausing = 5, + UIS_WorldMap = 6, + //todo What is 7? + UIS_Wiping = 8, + UIS_Max = 9 +}; + +/** + * @brief User interface. + * + * @note Roughly based on May proto, may be inaccurate. + */ +struct UI +{ + UIS uis; + float tUis; + BLOT *apblotActive; + int cpblotActive; + UIS uisPlaying; + float rvolMusicPrepause; + float rvolEffectsPrepause; +}; #endif // UI_H diff --git a/include/vtables.h b/include/vtables.h new file mode 100644 index 00000000..11da9cfe --- /dev/null +++ b/include/vtables.h @@ -0,0 +1,52 @@ +#ifndef VTABLES_H +#define VTABLES_H + +struct BLOT; + +struct VTBLOT +{ + void (*pfnInitBlot)(BLOT *); + void (*pfnPostBlotLoad)(BLOT *); + void (*pfnUpdateBlot)(BLOT *); + void (*pfnOnBlotActive)(BLOT *); + void (*pfnUpdateBlotActive)(BLOT *); + void (*pfnOnBlotReset)(BLOT *); + void (*pfnOnBlotPush)(BLOT *); + void (*pfnOnBlotPop)(BLOT *); + void (*pfnSetBlotAchzDraw)(BLOT *, const char *); + void (*pfnDrawBlot)(BLOT *); + void (*pfnRenderBlot)(BLOT *); + void (*pfnDtAppearBlot)(BLOT *); + void (*pfnDtVisibleBlot)(BLOT *); + void (*pfnDtDisappearBlot)(BLOT *); + void (*pfnShowBlot)(BLOT *); + void (*pfnHideBlot)(BLOT *); + void (*pfnSetBlotBlots)(BLOT *); + void (*pfnSetBlotClock)(BLOT *); + int (*pfnFIncludeBlotForPeg)(BLOT *); +}; + +struct VTNOTE +{ + void (*pfnInitBlot)(BLOT *); + void (*pfnPostNoteLoad)(BLOT *); + void (*pfnUpdateBlot)(BLOT *); + void (*pfnOnBlotActive)(BLOT *); + void (*pfnUpdateBlotActive)(BLOT *); + void (*pfnOnBlotReset)(BLOT *); + void (*pfnOnBlotPush)(BLOT *); + void (*pfnOnBlotPop)(BLOT *); + void (*pfnSetNoteAchzDraw)(BLOT *, const char *); + void (*pfnDrawNote)(BLOT *); + void (*pfnRenderBlot)(BLOT *); + void (*pfnDtAppearBlot)(BLOT *); + void (*pfnDtVisibleBlot)(BLOT *); + void (*pfnDtDisappearBlot)(BLOT *); + void (*pfnShowBlot)(BLOT *); + void (*pfnHideBlot)(BLOT *); + void (*pfnSetBlotBlots)(BLOT *); + void (*pfnSetBlotClock)(BLOT *); + int (*pfnFIncludeBlotForPeg)(BLOT *); +}; + +#endif // VTABLES_H diff --git a/src/P2/steppower.c b/src/P2/steppower.c index f68842dc..99142494 100644 --- a/src/P2/steppower.c +++ b/src/P2/steppower.c @@ -1,7 +1,59 @@ #include "steppower.h" #include +#include +#include +#include +#include -INCLUDE_ASM(const s32, "P2/steppower", SetFsp__F3FSP); +void SetFsp(FSP fsp) { + // Cleanup current powerup + switch (g_fsp) { + case FSP_Ball: + // If cur powerup is roll, reset JT's body state + if (g_pjt != nullptr && g_pjt->unk2220 == 13) { + SetJtJts(g_pjt, JTS_Stand, JTBS_Nil); + } + break; + case FSP_Mine: + // If cur powerup is mine, fade out the mine + if (g_pjt != nullptr) { + LO *ploMine = g_pjt->ploMine_1518; + if ((ploMine != nullptr) && (FIsLoInWorld(ploMine))) { + FadeAloOut((ALO *)g_pjt->ploMine_1518, 0.5f); + } + } + break; + default: + break; + } + + if (g_pjt != nullptr) { + g_rtClockPowerUp = 1.0f; + if ((g_pjt->unk2750 != 0) && FIsLoInWorld((JT*)g_pjt->unk2750)) { + func_001D32D8(g_pjt->unk2750, g_pjt, 1); + } + + func_001D31D0(g_pjt, 0); + if (g_pjt != nullptr && g_pjt == PpoCur()) { + g_fsp = fsp; + } + } + + // If fsp is unchanged or invalid, return + int fspLast = g_pgsCur->fspLast; + if (fsp == fspLast || fsp >= (uint)FSP_Max) { + return; + } + + // Show note + SetBlotDtVisible((NOTE*)&g_note.unk278, (g_pjt != nullptr) && (g_pjt == PpoCur()) ? 3.0 : 8.0); + SetBlotFontScale(0.6, (NOTE*)&g_note.unk278); + ((NOTE*)&g_note.unk278)->pvtnote->pfnSetNoteAchzDraw((NOTE*)&g_note.unk278, s_mpfspachz[fsp]); + ((NOTE*)&g_note.unk278)->pvtnote->pfnShowBlot((NOTE*)&g_note.unk278); + + // Update last fsp in game state + g_pgsCur->fspLast = fsp; +} INCLUDE_ASM(const s32, "P2/steppower", UpdateJtActivePowerUp__FP2JTP3JOY); diff --git a/src/P2/steprail.c b/src/P2/steprail.c new file mode 100644 index 00000000..45341daf --- /dev/null +++ b/src/P2/steprail.c @@ -0,0 +1,6 @@ +/** + * @file steprail.c + * + * @brief Rail behavior for STEP objects. + */ +#include