diff --git a/config/SOUE01/rels/d_t_gate_to_groundNP/symbols.txt b/config/SOUE01/rels/d_t_gate_to_groundNP/symbols.txt index 00eb2edf..49256b1d 100644 --- a/config/SOUE01/rels/d_t_gate_to_groundNP/symbols.txt +++ b/config/SOUE01/rels/d_t_gate_to_groundNP/symbols.txt @@ -10,7 +10,7 @@ draw__17dTgGateToGround_cFv = .text:0x000002F0; // type:function size:0x8 __dt__17dTgGateToGround_cFv = .text:0x00000300; // type:function size:0x70 _ctors = .ctors:0x00000000; // type:label scope:global _dtors = .dtors:0x00000000; // type:label scope:global -@20562 = .rodata:0x00000000; // type:object size:0x4 data:float scope:local +@20562 = .rodata:0x00000000; // type:object size:0x4 scope:local data:float g_profile_GATE2GND_TAG = .data:0x00000000; // type:object size:0x10 @20583 = .data:0x00000010; // type:object size:0xC scope:local __vt__17dTgGateToGround_c = .data:0x0000001C; // type:object size:0x74 diff --git a/config/SOUE01/splits.txt b/config/SOUE01/splits.txt index f07e4a94..ed79ad30 100644 --- a/config/SOUE01/splits.txt +++ b/config/SOUE01/splits.txt @@ -309,10 +309,13 @@ d/d_cursor_hit_check.cpp: .sbss start:0x80575260 end:0x80575268 .sdata2 start:0x80577938 end:0x80577958 -toBeSorted/d_rumble.cpp: +d/d_rumble.cpp: .text start:0x800664F0 end:0x80066F58 align:16 .ctors start:0x804DB6A0 end:0x804DB6A4 + .data start:0x8050DFA0 end:0x8050DFAC .sbss start:0x80575268 end:0x80575270 + .sdata2 start:0x80577958 end:0x80577994 + .bss start:0x805A0778 end:0x805A0868 toBeSorted/string_util.cpp: .text start:0x80066F60 end:0x80066FB0 align:16 diff --git a/config/SOUE01/symbols.txt b/config/SOUE01/symbols.txt index c438e780..aae9a997 100644 --- a/config/SOUE01/symbols.txt +++ b/config/SOUE01/symbols.txt @@ -2886,17 +2886,17 @@ getCursorPos__18dCursorInterface_cFv = .text:0x80066480; // type:function size:0 __dt__18dCursorInterface_cFv = .text:0x80066490; // type:function size:0x40 getType__20dCursorHitCheckLyt_cFv = .text:0x800664D0; // type:function size:0xC getType__19dCursorHitCheckCC_cFv = .text:0x800664E0; // type:function size:0xC -fn_800664F0 = .text:0x800664F0; // type:function size:0x10 -fn_80066500 = .text:0x80066500; // type:function size:0x48 -fn_80066550 = .text:0x80066550; // type:function size:0x54 -fn_800665B0 = .text:0x800665B0; // type:function size:0x4B8 -fn_80066A70 = .text:0x80066A70; // type:function size:0x90 -fn_80066B00 = .text:0x80066B00; // type:function size:0x224 -fn_80066D30 = .text:0x80066D30; // type:function size:0x54 -fn_80066D90 = .text:0x80066D90; // type:function size:0x10 -fn_80066DA0 = .text:0x80066DA0; // type:function size:0x5C -fn_80066E00 = .text:0x80066E00; // type:function size:0x44 -fn_80066E50 = .text:0x80066E50; // type:function size:0x108 +__ct__9dRumble_cFv = .text:0x800664F0; // type:function size:0x10 +__dt__9dRumble_cFv = .text:0x80066500; // type:function size:0x48 +create__9dRumble_cFv = .text:0x80066550; // type:function size:0x54 +execute__9dRumble_cFv = .text:0x800665B0; // type:function size:0x4B8 +remove__9dRumble_cFv = .text:0x80066A70; // type:function size:0x90 +start__9dRumble_cFRC14dRumbleEntry_cUl = .text:0x80066B00; // type:function size:0x224 +stop__9dRumble_cFl = .text:0x80066D30; // type:function size:0x54 +__ct__14dRumbleEntry_cFlUlf = .text:0x80066D90; // type:function size:0x10 +start__12dRumbleIdx_cFRC14dRumbleEntry_cUl = .text:0x80066DA0; // type:function size:0x5C +stop__12dRumbleIdx_cFv = .text:0x80066E00; // type:function size:0x44 +__sinit_\d_rumble_cpp = .text:0x80066E50; // type:function size:0x108 scope:local fn_80066F60 = .text:0x80066F60; // type:function size:0x50 lzSafeDecompress__FPCvUlPv = .text:0x80066FB0; // type:function size:0x64 matrixCreateFromPosRotYScale__FR6mMtx_cRC7mVec3_c4mAngRC7mVec3_cP6mMtx_cf = .text:0x80067020; // type:function size:0x138 @@ -14106,7 +14106,7 @@ __dt__30sFStateFct_c<14dAcBoomerang_c>Fv = .text:0x80260FD0; // type:function si __dt__83sStateMgr_c<14dAcBoomerang_c,20sStateMethodUsr_FI_c,12sFStateFct_c,13sStateIDChk_c>Fv = .text:0x80261040; // type:function size:0xA0 __dt__53sFStateMgr_c<14dAcBoomerang_c,20sStateMethodUsr_FI_c>Fv = .text:0x802610E0; // type:function size:0xA4 areaCallback__FP12dAcObjBase_cP7mVec3_cUl = .text:0x80261190; // type:function size:0x18 -hitCallback__14dAcBoomerang_cFP8cCcD_ObjP12dAcObjBase_cP8cCcD_Obj = .text:0x802611B0; // type:function size:0x290 +atHitCallback__14dAcBoomerang_cFP8cCcD_ObjP12dAcObjBase_cP8cCcD_Obj = .text:0x802611B0; // type:function size:0x290 fn_80261440 = .text:0x80261440; // type:function size:0x10 dAcBoomerang_atHitCallback__FP12dAcObjBase_cP8cCcD_ObjP12dAcObjBase_cP8cCcD_Obj = .text:0x80261450; // type:function size:0x24 AcBoomerang__assignBeetleModel = .text:0x80261480; // type:function size:0x5C @@ -30867,7 +30867,7 @@ __vt__18dCursorInterface_c = .data:0x8050DF60; // type:object size:0x10 __vt__20dCursorHitCheckLyt_c = .data:0x8050DF70; // type:object size:0x14 __vt__24dCsCheckLyt_BoundingData = .data:0x8050DF84; // type:object size:0xC __vt__19dCursorHitCheckCC_c = .data:0x8050DF90; // type:object size:0x10 -lbl_8050DFA0 = .data:0x8050DFA0; // type:object size:0x10 +__vt__9dRumble_c = .data:0x8050DFA0; // type:object size:0xC lbl_8050DFB0 = .data:0x8050DFB0; // type:object size:0xC lbl_8050DFBC = .data:0x8050DFBC; // type:object size:0xC lbl_8050DFC8 = .data:0x8050DFC8; // type:object size:0xC @@ -40617,7 +40617,7 @@ lbl_8057406C = .sdata:0x8057406C; // type:object size:0x4 data:4byte lbl_80574070 = .sdata:0x80574070; // type:object size:0x8 lbl_80574078 = .sdata:0x80574078; // type:object size:0x8 lbl_80574080 = .sdata:0x80574080; // type:object size:0x8 -lbl_80574088 = .sdata:0x80574088; // type:object size:0x4 scope:local data:4byte +@14637 = .sdata:0x80574088; // type:object size:0x4 scope:local data:4byte lbl_80574090 = .sdata:0x80574090; // type:object size:0x8 lbl_80574098 = .sdata:0x80574098; // type:object size:0x4 lbl_8057409C = .sdata:0x8057409C; // type:object size:0x4 @@ -41337,8 +41337,8 @@ dSystem__s_NewMEM1ArenaHi = .sbss:0x80575240; // type:object size:0x8 data:4byte dSystem__myDylinkInitPhase = .sbss:0x80575248; // type:object size:0x8 sInstance__18ArcCallbackHandler = .sbss:0x80575250; // type:object size:0x8 data:4byte aspectRatio = .sbss:0x80575258; // type:object size:0x4 align:4 data:float -sInstance__8dCsMgr_c = .sbss:0x80575260; // type:object size:0x8 data:4byte -lbl_80575268 = .sbss:0x80575268; // type:object size:0x8 data:4byte +sInstance__8dCsMgr_c = .sbss:0x80575260; // type:object size:0x4 data:4byte +spInstance__9dRumble_c = .sbss:0x80575268; // type:object size:0x4 data:4byte someColor = .sbss:0x80575270; // type:object size:0x1 data:byte reloadColorFaderPtr = .sbss:0x80575274; // type:object size:0x4 data:4byte sInstance__22CurrentStageArcManager = .sbss:0x80575278; // type:object size:0x4 data:4byte @@ -43334,20 +43334,19 @@ lbl_80577948 = .sdata2:0x80577948; // type:object size:0x4 align:4 data:float lbl_8057794C = .sdata2:0x8057794C; // type:object size:0x4 align:4 data:float lbl_80577950 = .sdata2:0x80577950; // type:object size:0x4 align:4 data:float lbl_80577954 = .sdata2:0x80577954; // type:object size:0x4 align:4 data:float -lbl_80577958 = .sdata2:0x80577958; // type:object size:0x4 data:4byte -lbl_8057795C = .sdata2:0x8057795C; // type:object size:0x4 data:4byte -lbl_80577960 = .sdata2:0x80577960; // type:object size:0x4 align:4 data:float -lbl_80577964 = .sdata2:0x80577964; // type:object size:0x4 align:4 data:float -lbl_80577968 = .sdata2:0x80577968; // type:object size:0x4 align:4 data:float -lbl_8057796C = .sdata2:0x8057796C; // type:object size:0x4 align:4 data:float -lbl_80577970 = .sdata2:0x80577970; // type:object size:0x8 align:8 data:double -lbl_80577978 = .sdata2:0x80577978; // type:object size:0x4 align:4 data:float -lbl_8057797C = .sdata2:0x8057797C; // type:object size:0x4 align:4 data:float -lbl_80577980 = .sdata2:0x80577980; // type:object size:0x4 align:4 data:float -lbl_80577984 = .sdata2:0x80577984; // type:object size:0x4 align:4 data:float -lbl_80577988 = .sdata2:0x80577988; // type:object size:0x4 align:4 data:float -lbl_8057798C = .sdata2:0x8057798C; // type:object size:0x4 align:4 data:float -lbl_80577990 = .sdata2:0x80577990; // type:object size:0x4 align:4 data:float +@13148 = .sdata2:0x80577958; // type:object size:0x8 scope:local data:4byte +@13500 = .sdata2:0x80577960; // type:object size:0x4 scope:local align:4 data:float +@13501 = .sdata2:0x80577964; // type:object size:0x4 scope:local align:4 data:float +@13502 = .sdata2:0x80577968; // type:object size:0x4 scope:local align:4 data:float +@13503 = .sdata2:0x8057796C; // type:object size:0x4 scope:local align:4 data:float +@13505 = .sdata2:0x80577970; // type:object size:0x8 scope:local align:8 data:double +@13590 = .sdata2:0x80577978; // type:object size:0x4 scope:local align:4 data:float +@13591 = .sdata2:0x8057797C; // type:object size:0x4 scope:local align:4 data:float +@13592 = .sdata2:0x80577980; // type:object size:0x4 scope:local align:4 data:float +@13593 = .sdata2:0x80577984; // type:object size:0x4 scope:local align:4 data:float +@13594 = .sdata2:0x80577988; // type:object size:0x4 scope:local align:4 data:float +@13595 = .sdata2:0x8057798C; // type:object size:0x4 scope:local align:4 data:float +@13596 = .sdata2:0x80577990; // type:object size:0x4 scope:local align:4 data:float lbl_80577998 = .sdata2:0x80577998; // type:object size:0x4 align:4 data:float lbl_8057799C = .sdata2:0x8057799C; // type:object size:0x4 align:4 data:float lbl_805779A0 = .sdata2:0x805779A0; // type:object size:0x4 align:4 data:float @@ -48327,14 +48326,14 @@ lbl_8057D284 = .sdata2:0x8057D284; // type:object size:0x4 align:4 data:float lbl_8057D288 = .sdata2:0x8057D288; // type:object size:0x4 align:4 data:float lbl_8057D28C = .sdata2:0x8057D28C; // type:object size:0x4 align:4 data:float lbl_8057D290 = .sdata2:0x8057D290; // type:object size:0x4 align:4 data:float -lbl_8057D298 = .sdata2:0x8057D298; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D29C = .sdata2:0x8057D29C; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D2A0 = .sdata2:0x8057D2A0; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D2A4 = .sdata2:0x8057D2A4; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D2A8 = .sdata2:0x8057D2A8; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D2AC = .sdata2:0x8057D2AC; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D2B0 = .sdata2:0x8057D2B0; // type:object size:0x4 scope:local align:4 data:float -lbl_8057D2B4 = .sdata2:0x8057D2B4; // type:object size:0x4 scope:local align:4 data:float +@15358 = .sdata2:0x8057D298; // type:object size:0x4 scope:local align:4 data:float +@15812 = .sdata2:0x8057D29C; // type:object size:0x4 scope:local align:4 data:float +@15813 = .sdata2:0x8057D2A0; // type:object size:0x4 scope:local align:4 data:float +@15814 = .sdata2:0x8057D2A4; // type:object size:0x4 scope:local align:4 data:float +@15815 = .sdata2:0x8057D2A8; // type:object size:0x4 scope:local align:4 data:float +@15816 = .sdata2:0x8057D2AC; // type:object size:0x4 scope:local align:4 data:float +@15817 = .sdata2:0x8057D2B0; // type:object size:0x4 scope:local align:4 data:float +@15818 = .sdata2:0x8057D2B4; // type:object size:0x4 scope:local align:4 data:float lbl_8057D2B8 = .sdata2:0x8057D2B8; // type:object size:0x4 align:4 data:float lbl_8057D2C0 = .sdata2:0x8057D2C0; // type:object size:0x4 align:4 data:float lbl_8057D2C4 = .sdata2:0x8057D2C4; // type:object size:0x4 align:4 data:float @@ -50385,18 +50384,20 @@ sHandMats = .bss:0x805A06C8; // type:object size:0xE scope:local data:byte @7070 = .bss:0x805A06F0; // type:object size:0xC scope:local sFader__8dScene_c = .bss:0x805A06FC; // type:object size:0x24 data:4byte SysConfig = .bss:0x805A0720; // type:object size:0x58 data:4byte -lbl_805A0778 = .bss:0x805A0778; // type:object size:0xC data:4byte -lbl_805A0784 = .bss:0x805A0784; // type:object size:0xC data:4byte -lbl_805A0790 = .bss:0x805A0790; // type:object size:0xC data:4byte -lbl_805A079C = .bss:0x805A079C; // type:object size:0xC data:4byte -lbl_805A07A8 = .bss:0x805A07A8; // type:object size:0xC data:4byte -lbl_805A07B4 = .bss:0x805A07B4; // type:object size:0xC data:4byte -lbl_805A07C0 = .bss:0x805A07C0; // type:object size:0x18 data:4byte -lbl_805A07D8 = .bss:0x805A07D8; // type:object size:0xC -lbl_805A07E4 = .bss:0x805A07E4; // type:object size:0xC -lbl_805A07F0 = .bss:0x805A07F0; // type:object size:0xC -lbl_805A07FC = .bss:0x805A07FC; // type:object size:0x44 data:byte -lbl_805A0840 = .bss:0x805A0840; // type:object size:0x28 data:byte +sRumblePreset0__9dRumble_c = .bss:0x805A0778; // type:object size:0xC data:4byte +...bss.0 = .bss:0x805A0778; // type:label scope:local +sRumblePreset1__9dRumble_c = .bss:0x805A0784; // type:object size:0xC data:4byte +sRumblePreset2__9dRumble_c = .bss:0x805A0790; // type:object size:0xC data:4byte +sRumblePreset3__9dRumble_c = .bss:0x805A079C; // type:object size:0xC data:4byte +sRumblePreset4__9dRumble_c = .bss:0x805A07A8; // type:object size:0xC data:4byte +sRumblePreset5__9dRumble_c = .bss:0x805A07B4; // type:object size:0xC data:4byte +sRumblePreset6__9dRumble_c = .bss:0x805A07C0; // type:object size:0xC data:4byte +sRumblePreset7__9dRumble_c = .bss:0x805A07CC; // type:object size:0xC data:4byte +sRumblePreset8__9dRumble_c = .bss:0x805A07D8; // type:object size:0xC data:4byte +sRumblePreset9__9dRumble_c = .bss:0x805A07E4; // type:object size:0xC data:4byte +sRumblePreset10__9dRumble_c = .bss:0x805A07F0; // type:object size:0xC data:4byte +@LOCAL@play__9dRumble_cFv@rumble_strings = .bss:0x805A07FC; // type:object size:0x42 scope:local data:byte +@LOCAL@start__9dRumble_cFRC14dRumbleEntry_cUl@rumble_string = .bss:0x805A0840; // type:object size:0x21 scope:local data:byte @LOCAL@getCurrentStageDirectory__22CurrentStageArcManagerFv@sStageDirTmp = .bss:0x805A0868; // type:object size:0x40 scope:local data:byte s_roomArcTmp = .bss:0x805A08A8; // type:object size:0x20 scope:local data:byte lbl_805A08C8 = .bss:0x805A08C8; // type:object size:0x138 data:2byte diff --git a/configure.py b/configure.py index 5f129583..96451bbb 100644 --- a/configure.py +++ b/configure.py @@ -424,7 +424,7 @@ config.libs = [ Object(Matching, "toBeSorted/arc_callback_handler.cpp"), Object(NonMatching, "d/d_video.cpp"), Object(NonMatching, "d/d_cursor_hit_check.cpp"), - Object(NonMatching, "toBeSorted/d_rumble.cpp"), + Object(Matching, "d/d_rumble.cpp"), Object(NonMatching, "toBeSorted/string_util.cpp"), Object(NonMatching, "toBeSorted/cx_util.cpp"), Object(NonMatching, "toBeSorted/area_math.cpp"), diff --git a/include/d/d_camera.h b/include/d/d_camera.h index d641e098..f57fb520 100644 --- a/include/d/d_camera.h +++ b/include/d/d_camera.h @@ -29,6 +29,10 @@ public: return fn_800918E0(field_0xDA0, a1, a2); } + void setScreenShakeIntensity(f32 val) { + mScreenShakeIntensity = val; + } + private: /* 0x068 */ u8 _0x068[0x6C - 0x068]; /* 0x06C */ mVec3_c mPositionMaybe; @@ -37,6 +41,8 @@ private: /* 0xD98 */ void *field_0xD98; /* 0xD9C */ u8 _0xD9C[0xDA0 - 0xD9C]; /* 0xDA0 */ void *field_0xDA0; + /* 0xDA4 */ u8 _0xDA4[0xDB0 - 0xDA4]; + /* 0xDB0 */ f32 mScreenShakeIntensity; }; #endif diff --git a/include/d/d_rumble.h b/include/d/d_rumble.h new file mode 100644 index 00000000..034be95d --- /dev/null +++ b/include/d/d_rumble.h @@ -0,0 +1,104 @@ +#ifndef D_RUMBLE_H +#define D_RUMBLE_H + +#include "common.h" + +class dRumbleEntry_c { + friend class dRumble_c; + +public: + dRumbleEntry_c(s32 length, u32 bits, f32 intensity); + +private: + /* 0x00 */ s32 mLength; + /* 0x04 */ s32 mBits; + /* 0x08 */ f32 mIntensity; +}; + +class dRumbleIdx_c { +public: + ~dRumbleIdx_c() { + stop(); + } + + /* Queues the entry into the Rumble Manager */ + bool start(const dRumbleEntry_c &entry, u32 flags); + + /* Removes the entry from the Rumble Manager*/ + void stop(); + + bool isActive() const { + return mIdx != -1; + } + void setIdx(s32 idx) { + mIdx = idx; + } + s32 getIdx() const { + return mIdx; + } + +private: + s32 mIdx; +}; + +/** + * Made-up name. + * Size: 0x54 + */ +class dRumble_c { +public: + enum Flags_c { + FLAG_SLOT0 = 0x1, + FLAG_SLOT1 = 0x2, + FLAG_ACTIVE = 0x10, + FLAG_INITIALIZE = 0x200, + }; + + struct RumbleData { + /* 0x00 */ s32 mLength; + /* 0x04 */ s32 mBitsLeft; + /* 0x08 */ s32 mRumbleBits; + /* 0x0C */ u32 mFlags; + /* 0x10 */ f32 mIntensity; + }; + +public: + /** Generates the single instance */ + static void create(); + + /** Deletes the single instance */ + static void remove(); + + /** Runs the rumble instances */ + static void execute(); + + /** inserts a rumble instance into the manager. returns the index */ + static s32 start(const dRumbleEntry_c &entry, u32 flags); + + /** Stops one of the data instances (sets length to 0). -1 means to stop all */ + static void stop(s32 idx); + + virtual ~dRumble_c(); + + /** Rumble Presets */ + static dRumbleEntry_c sRumblePreset0; + static dRumbleEntry_c sRumblePreset1; + static dRumbleEntry_c sRumblePreset2; + static dRumbleEntry_c sRumblePreset3; + static dRumbleEntry_c sRumblePreset4; + static dRumbleEntry_c sRumblePreset5; + static dRumbleEntry_c sRumblePreset6; + static dRumbleEntry_c sRumblePreset7; + static dRumbleEntry_c sRumblePreset8; + static dRumbleEntry_c sRumblePreset9; + static dRumbleEntry_c sRumblePreset10; + +private: + RumbleData mRumbleData[4]; + +private: + dRumble_c(); + static dRumble_c *spInstance; +}; + +#endif diff --git a/src/d/a/obj/d_a_obj_boomerang.cpp b/src/d/a/obj/d_a_obj_boomerang.cpp index 1f908925..23d8e695 100644 --- a/src/d/a/obj/d_a_obj_boomerang.cpp +++ b/src/d/a/obj/d_a_obj_boomerang.cpp @@ -47,9 +47,18 @@ void dAcBoomerang_c::atHitCallback(cCcD_Obj *i_objInfA, dAcObjBase_c *i_actorB, setChrAnimation(RB_HOLD); mAnmChr[0].setRate(0.f); mAnmChr[0].setFrameOnly(i_actorB->GetLinkage().field_0x24); + return; } } } + + if (mStateMgr.isState(StateID_MoveCancelWait)) { + return; + } + + if (i_objInfB->ChkTgBit23()) { + setChrAnimation(RB_CUT); + } } bool dAcBoomerang_atHitCallback( diff --git a/src/d/a/obj/d_a_obj_switch.cpp b/src/d/a/obj/d_a_obj_switch.cpp index fd5cd444..efb49d97 100644 --- a/src/d/a/obj/d_a_obj_switch.cpp +++ b/src/d/a/obj/d_a_obj_switch.cpp @@ -4,6 +4,7 @@ #include "d/col/bg/d_bg_s.h" #include "d/col/bg/d_bg_w.h" #include "d/d_linkage.h" +#include "d/d_rumble.h" #include "d/flag/sceneflag_manager.h" #include "nw4r/g3d/res/g3d_resfile.h" #include "s/s_Math.h" @@ -257,11 +258,9 @@ void dAcOsw_c::executeState_On() { } } -extern char lbl_805A0790[]; -extern "C" void fn_80066B00(void *, bool); void dAcOsw_c::finalizeState_On() { playSound(0xA18); - fn_80066B00(lbl_805A0790, true); + dRumble_c::start(dRumble_c::sRumblePreset2, 0x1); } void dAcOsw_c::initializeState_OffWait() { diff --git a/src/d/d_rumble.cpp b/src/d/d_rumble.cpp new file mode 100644 index 00000000..bc5dcd12 --- /dev/null +++ b/src/d/d_rumble.cpp @@ -0,0 +1,263 @@ +#include "d/d_rumble.h" + +#include "common.h" +#include "d/d_sc_game.h" +#include "d/lyt/d_lyt_control_game.h" +#include "m/m_pad.h" +#include "toBeSorted/reload_color_fader.h" + +dRumbleEntry_c dRumble_c::sRumblePreset0(8, 0b11000000000000000000000000000000, 2.f); +dRumbleEntry_c dRumble_c::sRumblePreset1(9, 0b11010000000000000000000000000000, 4.f); +dRumbleEntry_c dRumble_c::sRumblePreset2(10, 0b11101100000000000000000000000000, 6.f); +dRumbleEntry_c dRumble_c::sRumblePreset3(12, 0b11101101000000000000000000000000, 8.f); +dRumbleEntry_c dRumble_c::sRumblePreset4(12, 0b11101110110000000000000000000000, 10.f); +dRumbleEntry_c dRumble_c::sRumblePreset5(16, 0b11011101101100000000000000000000, 12.f); +dRumbleEntry_c dRumble_c::sRumblePreset6(16, 0b11101111111011000000000000000000, 14.f); +dRumbleEntry_c dRumble_c::sRumblePreset7(32, 0b11111110111111000000000000000000, 14.f); +dRumbleEntry_c dRumble_c::sRumblePreset8(8, 0b11100000000000000000000000000000, 2.f); +dRumbleEntry_c dRumble_c::sRumblePreset9(16, 0b11100000000000000000000000000000, 2.f); +dRumbleEntry_c dRumble_c::sRumblePreset10(24, 0b11100000000000000000000000000000, 2.f); + +dRumble_c *dRumble_c::spInstance; + +dRumble_c::dRumble_c() {} + +dRumble_c::~dRumble_c() { + spInstance = nullptr; +} + +void dRumble_c::create() { + spInstance = new dRumble_c(); + + spInstance->mRumbleData[0].mBitsLeft = 0; + spInstance->mRumbleData[1].mBitsLeft = 0; + spInstance->mRumbleData[2].mBitsLeft = 0; + spInstance->mRumbleData[3].mBitsLeft = 0; +} + +void dRumble_c::execute() { + // If the game is not being controlled, do not do anything + if (dLytControlGame_c::getInstance()) { + if (!dLytControlGame_c::getInstance()->isStateNormal()) { + return; + } + } + + // I am guessing on any reload screen or homebutton menu? + if (ReloadColorFader::GetInstance()->is1Or5()) { + mPad::g_core[0]->stopRumbleMgr(); + mPad::g_core[1]->stopRumbleMgr(); + return; + } + + // These structs are only used here. + // No need to make them global + struct Entry { + u32 bits; + s32 length; + bool isActive; + } entries[2] = {}; + struct Info { + u32 mBits; + f32 intensities[4]; + s32 combinedLength; + s32 _unused; + } info = {}; + + for (s32 i = 0; i < 4; ++i) { + RumbleData &data = spInstance->mRumbleData[i]; + if (data.mBitsLeft == 0) { + continue; + } + + u32 bit = data.mLength - data.mBitsLeft; + if (data.mFlags & FLAG_ACTIVE) { + info.mBits |= data.mRumbleBits << bit; + if (data.mFlags & FLAG_INITIALIZE) { + info.intensities[i] = data.mIntensity; + } else { + info.intensities[i] = data.mIntensity * ((f32)data.mBitsLeft / data.mLength); + } + if (info.combinedLength < data.mBitsLeft) { + info.combinedLength = data.mBitsLeft; + } + } else { + info.intensities[i] = 0.f; + } + + if (data.mFlags & FLAG_SLOT0) { + entries[0].bits |= data.mRumbleBits << bit; + + if (entries[0].length < data.mBitsLeft) { + entries[0].length = data.mBitsLeft; + } + if (bit == 0) { + entries[0].isActive = true; + } + } + + if (data.mFlags & FLAG_SLOT1) { + entries[1].bits |= data.mRumbleBits << bit; + + if (entries[1].length < data.mBitsLeft) { + entries[1].length = data.mBitsLeft; + } + if (bit == 0) { + entries[1].isActive = true; + } + } + + if (--data.mBitsLeft == 0) { + if (data.mFlags & FLAG_INITIALIZE) { + data.mBitsLeft = data.mLength; + } + } + } + + if (info.combinedLength != 0) { + struct { + s32 slot; + f32 shake; + } s = {0, 0.1f}; + for (s32 i = 0; i < 4; i++) { + if (s.shake < info.intensities[i]) { + s.shake = info.intensities[i]; + s.slot = i; + } + } + + f32 shake = 0.f; + for (s32 i = 0; i < 4; i++) { + if (i == s.slot) { + shake += info.intensities[i]; + } else { + f32 tmp = info.intensities[i]; + shake += tmp * (tmp / s.shake); + } + } + + f32 modifier = 0.f; + if ((info.mBits << 0) & 0x80000000) { + modifier += 0.6f; + } + if ((info.mBits << 1) & 0x80000000) { + modifier += 0.3f; + } + if ((info.mBits << 2) & 0x80000000) { + modifier += 0.1f; + } + + if (dScGame_c::getCamera(0)) { + dScGame_c::getCamera(0)->setScreenShakeIntensity(shake * modifier); + } + } + + static char rumble_strings[2][32 + 1]; + for (s32 i = 0; i < 2; i++) { + if (entries[i].isActive) { + s32 j = 0; + for (; j < entries[i].length && j < 32; j++) { + rumble_strings[i][j] = (entries[i].bits << j) & 0x80000000 ? '*' : '-'; + } + rumble_strings[i][j] = '\0'; + + mPad::g_core[0]->stopRumbleMgr(); + mPad::g_core[0]->startPatternRumble(rumble_strings[i], entries[i].length, false); + } + } +} + +void dRumble_c::remove() { + if (spInstance != nullptr) { + spInstance->mRumbleData[0].mBitsLeft = 0; + spInstance->mRumbleData[1].mBitsLeft = 0; + spInstance->mRumbleData[2].mBitsLeft = 0; + spInstance->mRumbleData[3].mBitsLeft = 0; + mPad::g_core[0]->stopRumbleMgr(); + mPad::g_core[1]->stopRumbleMgr(); + + delete spInstance; + spInstance = nullptr; + } +} + +s32 dRumble_c::start(const dRumbleEntry_c &entry, u32 flags) { + static char rumble_string[32 + 1]; + if (dLytControlGame_c::getInstance()) { + if (!dLytControlGame_c::getInstance()->isStateNormal()) { + s32 j = 0; + for (; j < entry.mLength && j < 32; j++) { + rumble_string[j] = (entry.mBits << j) & 0x80000000 ? '*' : '-'; + } + rumble_string[j] = '\0'; + + mPad::g_core[0]->stopRumbleMgr(); + mPad::g_core[0]->startPatternRumble(rumble_string, entry.mLength, false); + return -1; + } + } + s32 idx = 0; + for (s32 i = 0; i < 4; i++) { + if (spInstance->mRumbleData[i].mBitsLeft == 0) { + idx = i; + break; + } + + s32 bitsLeft = (spInstance->mRumbleData[i].mFlags & FLAG_INITIALIZE) ? + (spInstance->mRumbleData[i].mLength * 10) : + (spInstance->mRumbleData[i].mBitsLeft); + if (bitsLeft < 9999) { + idx = i; + } + } + + spInstance->mRumbleData[idx].mLength = entry.mLength; + spInstance->mRumbleData[idx].mBitsLeft = entry.mLength; + spInstance->mRumbleData[idx].mRumbleBits = entry.mBits; + spInstance->mRumbleData[idx].mIntensity = entry.mIntensity; + spInstance->mRumbleData[idx].mFlags = flags; + + return idx; +} + +void dRumble_c::stop(s32 idx) { + if (spInstance == nullptr) { + return; + } + + // -1 means stop all + if (idx == -1) { + spInstance->mRumbleData[0].mBitsLeft = 0; + spInstance->mRumbleData[1].mBitsLeft = 0; + spInstance->mRumbleData[2].mBitsLeft = 0; + spInstance->mRumbleData[3].mBitsLeft = 0; + return; + } + + if (idx > ARRAY_LENGTH(spInstance->mRumbleData) - 1) { + return; + } + + spInstance->mRumbleData[idx].mBitsLeft = 0; +} + +dRumbleEntry_c::dRumbleEntry_c(s32 length, u32 bits, f32 intensity) { + mLength = length; + mBits = bits; + mIntensity = intensity; +} + +bool dRumbleIdx_c::start(const dRumbleEntry_c &entry, u32 flags) { + if (isActive()) { + return false; + } + setIdx(dRumble_c::start(entry, flags | dRumble_c::FLAG_INITIALIZE)); + return isActive(); +} + +void dRumbleIdx_c::stop() { + if (isActive()) { + dRumble_c::stop(getIdx()); + setIdx(-1); + } +} diff --git a/src/d/d_scene.cpp b/src/d/d_scene.cpp index 60829bbc..3a5bb4a0 100644 --- a/src/d/d_scene.cpp +++ b/src/d/d_scene.cpp @@ -2,6 +2,7 @@ #include "common.h" #include "d/d_base.h" +#include "d/d_rumble.h" #include "f/f_base.h" #include "f/f_profile_name.h" #include "m/m_fader_base.h" @@ -14,7 +15,6 @@ static bool gameStateIsActive = true; extern "C" u32 lbl_80574FA0; extern "C" u32 lbl_80574FA4; extern "C" void fn_801942F0(int, int); -extern "C" void fn_80066D30(int); dFader_c dScene_c::sFader; @@ -49,7 +49,7 @@ int dScene_c::preExecute() { } else if (sFader.isStatus(mFaderBase_c::FADED_OUT)) { deleteRequest(); resetFlags(); - fn_80066D30(-1); + dRumble_c::stop(-1); } return NOT_READY; } else { diff --git a/src/d/d_stage.cpp b/src/d/d_stage.cpp index f2452e80..0d26e2b5 100644 --- a/src/d/d_stage.cpp +++ b/src/d/d_stage.cpp @@ -5,6 +5,7 @@ #include "d/d_base.h" #include "d/d_bzs_types.h" #include "d/d_room.h" +#include "d/d_rumble.h" #include "d/d_sc_game.h" #include "d/d_sc_title.h" #include "d/d_stage_mgr.h" @@ -54,7 +55,6 @@ extern "C" void ScrapperPickupMgr__update(void *); extern "C" void ScrapperPickupMgr__dtor(); extern "C" void fn_80028A80(); extern "C" void fn_80028EC0(); -extern "C" void fn_80066D30(s32); extern "C" void setPCAMpos2(const PCAM *); int dStage_c::create() { @@ -100,7 +100,7 @@ int dStage_c::create() { int dStage_c::doDelete() { fn_80028EC0(); - fn_80066D30(-1); + dRumble_c::stop(-1); ScrapperPickupMgr__dtor(); return SUCCEEDED; }