From 1e234ebe38ff5b9147f24a9e94fc8337d4452314 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 22:07:07 -0800 Subject: [PATCH 01/96] Increase patch capacity --- src/internal/tickable.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/tickable.h b/src/internal/tickable.h index 0b4a15e0..caa1e2d4 100644 --- a/src/internal/tickable.h +++ b/src/internal/tickable.h @@ -27,7 +27,7 @@ namespace tickable { // Capacity of the tickable manager vector, increase if needed // This only stores pointers, so memory impact should be low -constexpr size_t PATCH_CAPACITY = 32; +constexpr size_t PATCH_CAPACITY = 48; // Represents a patch, or code that ticks every frame struct Tickable { From bf7416d8f78639a0c9d6d2da2a55fa62933371e0 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 22:21:32 -0800 Subject: [PATCH 02/96] Make non-default values enable patches --- src/config/config.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/config/config.cpp b/src/config/config.cpp index 9f90ab68..18698395 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -136,6 +136,7 @@ void parse_function_toggles(char* buf) { // Set the enabled to the parsed value, if it differes from the default passed value if (parsed_value != tickable->active_value) { + tickable->enabled = true; tickable->active_value = parsed_value; break; } From 03f4ebadb8f5197bf47124726f525c0a18989add Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 22:33:04 -0800 Subject: [PATCH 03/96] Re-add stage-author-names to config (oops) --- configs/default-config.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/configs/default-config.txt b/configs/default-config.txt index a97adc46..b5ea19f1 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -193,6 +193,7 @@ enable-menu-reflections: disabled custom-world-count: 10 stobj-draw-fix: disabled + stage-author-names: disabled fix-view-stage: disabled four-digit-banana-counter: disabled fix-minimap-color: disabled From 6a955b8e3260d416e0b02b4f6b0b3839c279adcc Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:15:46 -0800 Subject: [PATCH 04/96] Update Storm continue platform fix --- src/assembly/rain_ripple_fix.s | 17 ----------------- 1 file changed, 17 deletions(-) delete mode 100644 src/assembly/rain_ripple_fix.s diff --git a/src/assembly/rain_ripple_fix.s b/src/assembly/rain_ripple_fix.s deleted file mode 100644 index de621531..00000000 --- a/src/assembly/rain_ripple_fix.s +++ /dev/null @@ -1,17 +0,0 @@ -.global fix_rain_ripple -.extern sub_mode - -fix_rain_ripple: - lis r4, sub_mode@h - ori r4, r4, sub_mode@l - lwz r0, 0x0(r4) - cmplwi r0, 66 - beq end - stwu r1, -0x40(r1) - lis r0, 0x802d - ori r0, r0, 0xe1d8 - mtctr r0 - bctr - - end: - blr From 5b387d91f660222693dfd1b1bf1c9c24c89ebf35 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:17:05 -0800 Subject: [PATCH 05/96] Update Storm continue platform fix for real --- .../fixes/fix_storm_continue_platform.cpp | 26 +++++++++++++------ .../fixes/fix_storm_continue_platform.h | 2 +- 2 files changed, 19 insertions(+), 9 deletions(-) diff --git a/src/patches/fixes/fix_storm_continue_platform.cpp b/src/patches/fixes/fix_storm_continue_platform.cpp index 724d82d1..97b4ce2b 100644 --- a/src/patches/fixes/fix_storm_continue_platform.cpp +++ b/src/patches/fixes/fix_storm_continue_platform.cpp @@ -1,9 +1,6 @@ #include "fix_storm_continue_platform.h" - -#include "internal/assembly.h" #include "internal/patch.h" #include "internal/tickable.h" -#include "utils/ppcutil.h" // Fixes an issue with rain droplets not appearing correctly on the continue platform in the storm theme. namespace fix_storm_continue_platform { @@ -11,11 +8,24 @@ namespace fix_storm_continue_platform { TICKABLE_DEFINITION(( .name = "fix-storm-continue-platform", .description = "Storm continue platform patch", - .init_main_loop = init_main_loop, )) + .tick = tick, )) -void init_main_loop() { - patch::write_branch(reinterpret_cast(mkb::effect_bgstm_rainripple_disp), - reinterpret_cast(main::fix_rain_ripple)); +void tick() { + // Check if we're entering or on the continue screen + if ((mkb::sub_mode ==(mkb::SMD_GAME_CONTINUE_MAIN) || mkb::sub_mode == (mkb::SMD_GAME_CONTINUE_INIT)) && (mkb::sub_mode_frame_counter >= 2)) { // frame counter check helps prevent race conditions + // Nop some branches to code which handle rotating the storm raindrops + patch::write_nop(reinterpret_cast(0x802de2e4)); + patch::write_nop(reinterpret_cast(0x802de2ec)); + patch::write_nop(reinterpret_cast(0x802de2f4)); + patch::write_nop(reinterpret_cast(0x802de2fc)); + } + else { + // Original instructions + patch::write_word(reinterpret_cast(0x802de2e4), 0x4bd84c4d); + patch::write_word(reinterpret_cast(0x802de2ec), 0x4bd84bd1); + patch::write_word(reinterpret_cast(0x802de2f4), 0x4bd84cc9); + patch::write_word(reinterpret_cast(0x802de2fc), 0x4bd84bc1); + } } -}// namespace fix_storm_continue_platform +}// namespace fix_storm_continue_platform \ No newline at end of file diff --git a/src/patches/fixes/fix_storm_continue_platform.h b/src/patches/fixes/fix_storm_continue_platform.h index fe63e86e..05589015 100644 --- a/src/patches/fixes/fix_storm_continue_platform.h +++ b/src/patches/fixes/fix_storm_continue_platform.h @@ -2,6 +2,6 @@ namespace fix_storm_continue_platform { -void init_main_loop(); +void tick(); }// namespace fix_storm_continue_platform \ No newline at end of file From 1448ed3bb8b34de31a7cffa9a6109009ca370500 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:17:52 -0800 Subject: [PATCH 06/96] Actually nop the correct 1UP instruction for death counter --- src/patches/extensions/death_counter.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/extensions/death_counter.cpp b/src/patches/extensions/death_counter.cpp index a494fb32..7a70a022 100644 --- a/src/patches/extensions/death_counter.cpp +++ b/src/patches/extensions/death_counter.cpp @@ -71,7 +71,7 @@ void init_main_game() { mkb::memset(death_count, 0, sizeof(death_count)); patch::write_nop(reinterpret_cast(0x808fa4f4)); - patch::write_nop(reinterpret_cast(0x808f509c)); + patch::write_nop(reinterpret_cast(0x802b8210)); patch::write_branch_bl(reinterpret_cast(0x808fa560), reinterpret_cast(update_death_count)); patch::write_branch(reinterpret_cast(mkb::sprite_monkey_counter_tick), From 179b9579c44a3321aff836190d59afc32f97c9f6 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:35:05 -0800 Subject: [PATCH 07/96] Update ghidra.h --- src/mkb/mkb2.us.lst | 7 +++++++ src/mkb/mkb2_ghidra.h | 43 +++++++++++++++++++++++++------------------ 2 files changed, 32 insertions(+), 18 deletions(-) diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index d4bbc4c7..2dce359f 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -8206,6 +8206,7 @@ 804727A8:switchdataD_8039c560 804727EC:switchdataD_8039c5a4 80472824:switchdataD_8039c5dc +80472A28:ball_colors 80472A80:switchdataD_8039c838 80472F40:switchdataD_8039ccf8 80473100:g_fog_type @@ -8769,6 +8770,7 @@ 8061CC60:storymode_save_files 8061CF58:g_storymode_unlock_entries_copy 8061CF65:g_cm_unlock_entries_copy +8061CF7B:autosave 8061FB20:g_some_string 8061FC10:g_some_pad_motor_array1 8061FC20:g_some_pad_motor_array2 @@ -9385,8 +9387,13 @@ 8097F4F8:g_are_story_select_sprites_visible 8097F4FC:g_amount_of_stages_per_world 8097F4FE:g_amount_of_beaten_stages_in_world +8097F508:g_story_select_sprites_anim_state +8097F50A:g_story_select_sprites_timer 8097F50C:some_ape_float 8097F510:some_ape_float2 +8097F514:g_some_story_select_sprite_timer +8097F518:g_some_story_select_sprite_timer_2 +8097F51C:g_some_story_select_sprite_initial_timer 8097F534:some_ape_float3 8097F750:g_storymode_preview_textures 8098005C:g_storymode_stageselect_state diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index d5dac5ce..f88330f9 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5664,7 +5664,7 @@ extern "C" { extern float FLOAT0; extern float FLOAT1; extern float FLOAT400; - extern undefined1 pausemenu_entry_counts[8]; + extern undefined1 pausemenu_entry_counts; extern undefined4 g_something_with_camera; extern double g_related_to_camera_turn_rate_and_stage_tilt; extern float camera_near_clip_z; @@ -5780,6 +5780,7 @@ extern "C" { extern undefined * switchdataD_8039c560; extern undefined * switchdataD_8039c5a4; extern pointer switchdataD_8039c5dc; + extern struct GXColor ball_colors[10]; extern undefined * switchdataD_8039c838; extern pointer switchdataD_8039ccf8; extern undefined1 g_fog_type; @@ -6275,6 +6276,7 @@ extern "C" { extern struct StoryModeSaveFile storymode_save_files[3]; extern undefined1 g_storymode_unlock_entries_copy; extern undefined1 g_cm_unlock_entries_copy; + extern bool autosave; extern undefined g_some_string; extern struct GSomethingWithPadMotorsStruct g_some_pad_motor_array1[4]; extern struct GSomethingWithPadMotorsStruct g_some_pad_motor_array2[4]; @@ -6413,8 +6415,13 @@ extern "C" { extern undefined4 g_are_story_select_sprites_visible; extern undefined2 g_amount_of_stages_per_world; extern undefined2 g_amount_of_beaten_stages_in_world; + extern undefined2 g_story_select_sprites_anim_state; + extern undefined2 g_story_select_sprites_timer; extern float some_ape_float; extern float some_ape_float2; + extern undefined4 g_some_story_select_sprite_timer; + extern undefined4 g_some_story_select_sprite_timer_2; + extern undefined4 g_some_story_select_sprite_initial_timer; extern float some_ape_float3; extern struct SpriteTex g_storymode_preview_textures; extern StoryModeStageSelectState g_storymode_stageselect_state; @@ -6860,7 +6867,7 @@ extern "C" { void DMAErrorHandler(undefined4 param_1, undefined4 * param_2); void __OSCacheInit(void); undefined8 __OSLoadFPUContext(undefined8 param_1, undefined4 param_2, int param_3); - void __OSSaveFPUContext(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, double param_7, double param_8, undefined4 param_9, undefined4 param_10, int param_11); + void __OSSaveFPUContext(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, undefined8 param_9, undefined8 param_10, undefined8 param_11_00, undefined8 param_12, undefined8 param_13, undefined4 param_14, undefined4 param_15, int param_16); void OSSetCurrentContext(struct OSContext * context); OSContext * OSGetCurrentContext(void); undefined4 OSSaveContext(int param_1); @@ -7008,20 +7015,20 @@ extern "C" { void __DBExceptionDestination(void); uint __DBIsExceptionMarked(uint param_1); void DBPrintf(void); - undefined8 PSMTXIdentity(undefined4 * param_1); - undefined8 PSMTXCopy(float * param_1, float * param_2); - undefined8 PSMTXConcat(float * param_1, float * param_2, float * param_3); - undefined4 PSMTXInverse(float * param_1, float * param_2); + undefined8 PSMTXIdentity(int param_1); + undefined8 PSMTXCopy(int param_1, int param_2); + undefined8 PSMTXConcat(int param_1, int param_2, int param_3); + undefined4 PSMTXInverse(int param_1, int param_2); void PSMTXScale(double param_1, double param_2, double param_3, float * param_4); void C_MTXLookAt(Mtx * mtx, struct Vec * cam_pos, struct Vec * cam_up, struct Vec * target); void C_MTXFrustum(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, float * param_7); void C_MTXPerspective(Mtx44 * m, double fovy, double aspect, double n, double f); void C_MTXOrtho(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, float * m); - void PSVECAdd(float * param_1, float * param_2, float * param_3); - void PSVECSubtract(float * param_1, float * param_2, float * param_3); - void PSVECScale(double param_1, float * param_2, float * param_3); - undefined8 PSVECNormalize(float * param_1, float * param_2); - undefined8 PSVECCrossProduct(float * param_1, float * param_2, float * param_3); + void PSVECAdd(int param_1, int param_2, int param_3); + void PSVECSubtract(int param_1, int param_2, int param_3); + void PSVECScale(undefined8 param_1, int param_2, int param_3); + undefined8 PSVECNormalize(int param_1, int param_2); + undefined8 PSVECCrossProduct(int param_1, int param_2, int param_3); void __DVDInitWA(void); void AlarmHandlerForTimeout(undefined4 param_1, struct OSContext * param_2); void Read(undefined4 param_1, uint param_2, uint param_3, undefined4 param_4); @@ -7451,9 +7458,9 @@ extern "C" { void GXSetProjection(f32 mtx[4][4], GXProjectionType type); void GXSetProjectionv(f32 * ptr); void GXGetProjectionv(float * ptr); - undefined8 WriteMTXPS4x3(float * param_1, float * param_2); - void WriteMTXPS3x3from3x4(float * param_1, float * param_2); - undefined8 WriteMTXPS4x2(float * param_1, float * param_2); + undefined8 WriteMTXPS4x3(int param_1, undefined4 param_2); + void WriteMTXPS3x3from3x4(int param_1, undefined4 * param_2); + undefined8 WriteMTXPS4x2(int param_1, undefined4 param_2); void GXLoadPosMtxImm(float mtxPtr[3][4], u32 id); void GXLoadNrmMtxImm(float mtxPtr[3][4], u32 id); void GXSetCurrentMtx(u32 id); @@ -7803,7 +7810,7 @@ extern "C" { undefined4 g_something_with_sound8_wrapper(int param_1); undefined4 ReverbHICreate(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, void * param_7); undefined4 ReverbHIModify(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, void * param_7); - void DoCrossTalk(double param_1, double param_2, uint * param_3, uint * param_4); + void DoCrossTalk(undefined8 param_1, undefined8 param_2, uint * param_3, uint * param_4); void HandleReverb(uint * param_1, int param_2, int param_3); void ReverbHICallback(uint * param_1, uint * param_2, uint * param_3, int param_4); void ReverbHIFree(int param_1); @@ -7874,7 +7881,7 @@ extern "C" { void mtxa_from_rotate_y(short angle); void mtxa_from_rotate_z(short angle); void mtxa_from_mtxb_translate(struct Vec * vec); - double mtxa_from_mtxb_translate_xyz(double param_1, double param_2, double param_3); + double mtxa_from_mtxb_translate_xyz(undefined8 param_1, undefined8 param_2, undefined8 param_3); void mtxa_normalize_basis(void); undefined8 mtxa_push(void); void mtxa_pop(void); @@ -7917,7 +7924,7 @@ extern "C" { void mtxa_rotate_z_sin_cos(float sin_z_angle, float cos_z_angle); void mtxa_from_quat(struct Quat * quat); void quat_mult(struct Quat * dest, struct Quat * quat1, struct Quat * quat2); - undefined8 g_math_smth1(float * param_1); + undefined8 g_math_smth1(int param_1); void g_math_unk6(float * param_1); void g_math_unk7(double param_1, struct Quat * param_2, float * param_3, float * param_4); void g_math_unk8(double param_1, struct Quat * param_2, float * param_3, float * param_4); @@ -8025,7 +8032,7 @@ extern "C" { void g_maybe_something_with_normals(int param_1); void g_init_gma(struct GmaBuffer * gma_buffer, struct Gma * gma_header, struct TplBuffer * tpl); int g_init_gma_model_materials(struct GmaModel * model, struct TplBuffer * tpl, struct GXTexObj * texobj_array); - void g_memcpy_using_locked_cache(void * dest, void * curr_src_1_1_1_1_1_1_1_1_1_1, size_t count); + void g_memcpy_using_locked_cache(void * dest, void * curr_src_1_1_1_1_1_1_1_1_1_1_1, size_t count); void g_something_with_locked_cache_2(void * param_1, uint param_2, uint param_3); void memcpy2(void * dest, void * src, size_t count); int * __va_arg(char * param_1, int param_2); From 83ed305c56748e88db45eb855438c663e3cc2cf8 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:39:16 -0800 Subject: [PATCH 08/96] Add transparency and texture scroll fixes to fix-view-stage (needs changes...) --- src/patches/fixes/fix_view_stage.cpp | 104 ++++++++++++++++++++++++++- src/patches/fixes/fix_view_stage.h | 1 - 2 files changed, 103 insertions(+), 2 deletions(-) diff --git a/src/patches/fixes/fix_view_stage.cpp b/src/patches/fixes/fix_view_stage.cpp index 879e1e67..0f53b92a 100644 --- a/src/patches/fixes/fix_view_stage.cpp +++ b/src/patches/fixes/fix_view_stage.cpp @@ -9,11 +9,113 @@ namespace fix_view_stage { TICKABLE_DEFINITION(( .name = "fix-view-stage", .description = "Various 'View Stage' fixes", + .enabled = true, .init_main_game = init_main_game, )) +void new_render_func(void) { + float fVar1; + bool bVar4; + mkb::uint uVar2; + mkb::GmaModel* pGVar3; + int* piVar5; + mkb::StagedefStageModelPtrB* pSVar6; + int iVar7; + mkb::StagedefStageModelInstance* pSVar8; + int iVar9; + mkb::StagedefColiHeader* pSVar10; + mkb::Itemgroup* pIVar11; + double dVar12; + mkb::g_set_some_draw_values(1.0, 1.0, 1.0); + mkb::mtxa_from_mtxb(); + mkb::mtxa_translate(&mkb::stagedef->start->position); + mkb::mtxa_rotate_y((s16) ((int) mkb::view_stage_timer << 9)); + mkb::load_gx_pos_nrm_mtx(mkb::mtxa, 0); + mkb::avdisp_draw_model_culled_sort_auto(mkb::init_common_gma->model_entries[0x4d].model); + mkb::g_some_draw_func(); + if (mkb::stage_gma != (mkb::GmaBuffer*) 0x0) { + pSVar10 = mkb::stagedef->coli_header_list; + pIVar11 = mkb::itemgroups; + for (iVar9 = 0; iVar9 < (int) mkb::stagedef->coli_header_count; iVar9 = iVar9 + 1) { + mkb::mtxa_from_mtxb(); + if (0 < iVar9) { + mkb::mtxa_mult_right((mkb::Mtx*) pIVar11->transform); + } + mkb::load_gx_pos_nrm_mtx(mkb::mtxa, 0); + pSVar6 = pSVar10->stage_model_b_list; + for (iVar7 = 0; iVar7 < (int) pSVar10->stage_model_b_count; iVar7 = iVar7 + 1) { + if (((pSVar6->stage_model_a->some_effect_bitflag & mkb::EFFECT_TRANSPARENCY_A) == mkb::EFFECT_NULL) && (pGVar3 = (mkb::GmaModel*) mkb::g_some_draw_func2((int) pSVar6->stage_model_a), + pGVar3 != (mkb::GmaModel*) 0x0)) { + if (pSVar10->texture_scroll != (mkb::StagedefTextureScroll*) 0x0) { + mkb::g_something_with_texture_scroll(pSVar10->texture_scroll); + } + if ((pSVar6->stage_model_a->some_effect_bitflag & mkb::EFFECT_TRANSPARENCY_B) == mkb::EFFECT_NULL) { + mkb::avdisp_draw_model_culled_sort_never(pGVar3); + } + else { + mkb::g_smth_with_rendefc_reflective_height(400.0); + mkb::avdisp_draw_model_unculled_sort_always(pGVar3); + mkb::g_smth_with_rendefc_reflective_height(0.0); + } + } + pSVar6 = pSVar6 + 1; + } + uVar2 = mkb::g_smth_with_challenge_mode_var_and_3p(); + pSVar8 = mkb::stagedef->coli_header_list[iVar9].stage_model_instance_list; + mkb::mtxa_push(); + for (iVar7 = 0; iVar7 < (int) mkb::stagedef->coli_header_list[iVar9].stage_model_instance_count; + iVar7 = iVar7 + 1) { + if (((mkb::ushort) pSVar8->g_not_padding & uVar2) == 0) { + mkb::mtxa_peek(); + mkb::mtxa_translate(&pSVar8->position); + mkb::mtxa_rotate_z((pSVar8->rotation).z); + mkb::mtxa_rotate_y((pSVar8->rotation).y); + mkb::mtxa_rotate_x((pSVar8->rotation).x); + mkb::mtxa_scale(&pSVar8->scale); + if ((pSVar8->scale).x <= (pSVar8->scale).y) { + fVar1 = (pSVar8->scale).y; + } + else { + fVar1 = (pSVar8->scale).x; + } + dVar12 = (double) fVar1; + if (dVar12 < (double) (pSVar8->scale).z) { + dVar12 = (double) (pSVar8->scale).z; + } + mkb::g_some_draw_func3(dVar12); + pGVar3 = (mkb::GmaModel*) mkb::g_some_draw_func4(dVar12, (int) pSVar8->stage_model_a); + if ((pGVar3 != (mkb::GmaModel*) 0x0) && + (bVar4 = mkb::g_is_sphere_visible((double) (float) ((double) pGVar3->bound_sphere_radius * + dVar12), + &pGVar3->bound_sphere_center), + bVar4)) { + mkb::load_gx_pos_nrm_mtx(mkb::mtxa, 0); + if ((pSVar6->stage_model_a->some_effect_bitflag & mkb::EFFECT_TRANSPARENCY_B) == mkb::EFFECT_NULL) + mkb::avdisp_draw_model_unculled_sort_never(pGVar3); + } + } + pSVar8 = pSVar8 + 1; + } + mkb::mtxa_pop(); + pIVar11 = pIVar11 + 1; + pSVar10 = pSVar10 + 1; + } + } + if (mkb::g_some_draw_var != (int*) 0x0) { + mkb::mtxa_from_mtxb(); + for (piVar5 = mkb::g_some_draw_var; *piVar5 != 0; piVar5 = piVar5 + 6) { + mkb::g_some_draw_func5((int*) piVar5[5]); + } + } + mkb::g_draw_collision_triangles(); + return; +} + void init_main_game() { // Prevent background animations from animating twice as fast in 'View Stage' - patch::write_word(reinterpret_cast(0x80912d90), PPC_INSTR_NOP()); + patch::write_nop(reinterpret_cast(0x80912d90)); + patch::write_branch( + reinterpret_cast(mkb::g_smth_with_rendering_models_for_reflective_surfaces), + reinterpret_cast(new_render_func)); } }// namespace fix_view_stage diff --git a/src/patches/fixes/fix_view_stage.h b/src/patches/fixes/fix_view_stage.h index 7117af74..05845439 100644 --- a/src/patches/fixes/fix_view_stage.h +++ b/src/patches/fixes/fix_view_stage.h @@ -2,7 +2,6 @@ namespace fix_view_stage { -void init_main_loop(); void init_main_game(); }// namespace fix_view_stage From d39a0bdcde249493afb9141b1697711447a873f4 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:49:30 -0800 Subject: [PATCH 09/96] Rename stage-author-names to stage-name-subtitles --- configs/default-config.txt | 2 +- ...ault-authors.txt => default-subtitles.txt} | 0 src/patches/extensions/stage_author_names.h | 8 -- ...hor_names.cpp => stage_name_subtitles.cpp} | 80 +++++++++---------- src/patches/extensions/stage_name_subtitles.h | 8 ++ 5 files changed, 49 insertions(+), 49 deletions(-) rename configs/{default-authors.txt => default-subtitles.txt} (100%) delete mode 100644 src/patches/extensions/stage_author_names.h rename src/patches/extensions/{stage_author_names.cpp => stage_name_subtitles.cpp} (54%) create mode 100644 src/patches/extensions/stage_name_subtitles.h diff --git a/configs/default-config.txt b/configs/default-config.txt index b5ea19f1..3661f21c 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -193,7 +193,7 @@ enable-menu-reflections: disabled custom-world-count: 10 stobj-draw-fix: disabled - stage-author-names: disabled + stage-name-subtitles: disabled fix-view-stage: disabled four-digit-banana-counter: disabled fix-minimap-color: disabled diff --git a/configs/default-authors.txt b/configs/default-subtitles.txt similarity index 100% rename from configs/default-authors.txt rename to configs/default-subtitles.txt diff --git a/src/patches/extensions/stage_author_names.h b/src/patches/extensions/stage_author_names.h deleted file mode 100644 index 27ff6af1..00000000 --- a/src/patches/extensions/stage_author_names.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace stage_author_names { - -void init_main_loop(); -void init_exoption(); - -}// namespace stage_author_names \ No newline at end of file diff --git a/src/patches/extensions/stage_author_names.cpp b/src/patches/extensions/stage_name_subtitles.cpp similarity index 54% rename from src/patches/extensions/stage_author_names.cpp rename to src/patches/extensions/stage_name_subtitles.cpp index edbd1a83..c5b74214 100644 --- a/src/patches/extensions/stage_author_names.cpp +++ b/src/patches/extensions/stage_name_subtitles.cpp @@ -1,4 +1,4 @@ -#include "stage_author_names.h" +#include "stage_name_subtitles.h" #include "internal/heap.h" #include "internal/log.h" @@ -7,35 +7,35 @@ #include "mkb/mkb.h" -// Allows for stage author names to be displayed under the stage name. -namespace stage_author_names { +// Allows for subtitles to be displayed under the stage name. +namespace stage_name_subtitles { TICKABLE_DEFINITION(( - .name = "stage-author-names", - .description = "Stage author name display", + .name = "stage-name-subtitles", + .description = "Stage name subtitles", .init_main_loop = init_main_loop, .init_exoption = init_exoption, )) -static char author_file_path[] = "/stgname/authors.str"; -static char author_fallback_name = '\0'; -static char* author_file_buf = nullptr; +static char subtitle_file_path[] = "/stgname/subtitles.str"; +static char fallback_subtitle = '\0'; +static char* subtitle_file_buf = nullptr; static constexpr u16 STAGE_COUNT = 421; -static char author_list[STAGE_COUNT][64]; +static char subtitle_list[STAGE_COUNT][64]; void sprite_init(float x, float y) { - char* author_name; + char* subtitle; if (mkb::current_stage_id >= 0 && mkb::current_stage_id < STAGE_COUNT) { if (mkb::main_mode != mkb::MD_EXOPT) { - author_name = author_list[mkb::current_stage_id];// Handle the name to load in most cases + subtitle = subtitle_list[mkb::current_stage_id];// Handle the subtitle to load in most cases } else { - author_name = author_list[mkb::g_replay_stage_id_to_load];// Handle the name to load when loading a replay + subtitle = subtitle_list[mkb::g_replay_stage_id_to_load];// Handle the subtitle to load when loading a replay } } else { - author_name = &author_fallback_name; + subtitle = &fallback_subtitle; } mkb::Sprite* sprite = mkb::create_sprite(); @@ -56,7 +56,7 @@ void sprite_init(float x, float y) { sprite->field22_0x24 = 1.0; sprite->g_flags1 = sprite->g_flags1 | 0xa1000000; sprite->widescreen_translation_x = 0x60; - mkb::sprintf(sprite->text, author_name); + mkb::sprintf(sprite->text, subtitle); sprite->tick_func = mkb::sprite_hud_stage_name_tick; } @@ -78,49 +78,49 @@ void sprite_init(float x, float y) { sprite_shadow->field22_0x24 = 0; sprite_shadow->g_flags1 = sprite->g_flags1 | 0xa1000000; sprite_shadow->widescreen_translation_x = 0x60; - mkb::sprintf(sprite_shadow->text, author_name); + mkb::sprintf(sprite_shadow->text, subtitle); sprite_shadow->tick_func = mkb::sprite_hud_stage_name_tick; } } void init_main_loop() { - // Read the author file. This should only be run once. - if (author_file_buf == nullptr) { - mkb::DVDFileInfo author_file_info; - int author_file_length = mkb::DVDOpen(author_file_path, &author_file_info); + // Read the subtitle file. This should only be run once. + if (subtitle_file_buf == nullptr) { + mkb::DVDFileInfo subtitle_file_info; + int subtitle_file_length = mkb::DVDOpen(subtitle_file_path, &subtitle_file_info); - MOD_ASSERT_MSG(author_file_length != 0, - "Author name file (stgname/authors.str) failed to load from disc"); + MOD_ASSERT_MSG(subtitle_file_length != 0, + "Subtitle file (stgname/subtitles.str) failed to load from disc"); - // Round the length of the author file to a multiple of 32, necessary for DVDReadAsyncPrio - author_file_length = (author_file_info.length + 0x1f) & 0xffffffe0; - author_file_buf = static_cast(heap::alloc(author_file_length)); - author_file_length = mkb::read_entire_file_using_dvdread_prio_async(&author_file_info, author_file_buf, - author_file_length, 0); - char* eof = author_file_buf + author_file_info.length; + // Round the length of the subtitle file to a multiple of 32, necessary for DVDReadAsyncPrio + subtitle_file_length = (subtitle_file_info.length + 0x1f) & 0xffffffe0; + subtitle_file_buf = static_cast(heap::alloc(subtitle_file_length)); + subtitle_file_length = mkb::read_entire_file_using_dvdread_prio_async(&subtitle_file_info, subtitle_file_buf, + subtitle_file_length, 0); + char* eof = subtitle_file_buf + subtitle_file_info.length; - MOD_ASSERT_MSG(author_file_length != 0, - "Author name file (stgname/authors.str) failed to load from disc"); + MOD_ASSERT_MSG(subtitle_file_length != 0, + "Subtitle file (stgname/subtitles.str) failed to load from disc"); - LOG("Now parsing stage author list file..."); + LOG("Now parsing stage subtitle list file..."); u16 current_stage_id = 0; do { char name[128] = {0}; - char* name_end = mkb::strchr(author_file_buf, '\n'); + char* name_end = mkb::strchr(subtitle_file_buf, '\n'); MOD_ASSERT_MSG(name_end != nullptr, - "Author name author_file_buf ended unexpectedly, please ensure there are 421 lines in the author_file_buf"); - MOD_ASSERT_MSG((name_end - author_file_buf) < 128, - "Author name for a stage is greater than the limit of 127 characters"); + "Subtitle subtitle_file_buf ended unexpectedly, please ensure there are 421 lines in the subtitle_file_buf"); + MOD_ASSERT_MSG((name_end - subtitle_file_buf) < 128, + "Subtitle for a stage is greater than the limit of 127 characters"); - mkb::strncpy(name, author_file_buf, (name_end - author_file_buf)); + mkb::strncpy(name, subtitle_file_buf, (name_end - subtitle_file_buf)); - mkb::strcpy(author_list[current_stage_id], name); + mkb::strcpy(subtitle_list[current_stage_id], name); current_stage_id++; - author_file_buf = name_end + 1; - } while (current_stage_id < STAGE_COUNT && author_file_buf <= eof); + subtitle_file_buf = name_end + 1; + } while (current_stage_id < STAGE_COUNT && subtitle_file_buf <= eof); - mkb::DVDClose(&author_file_info); + mkb::DVDClose(&subtitle_file_info); } static patch::Tramp s_stage_name_tramp; @@ -142,4 +142,4 @@ void init_exoption() { }); } -}// namespace stage_author_names +}// namespace stage_name_subtitles diff --git a/src/patches/extensions/stage_name_subtitles.h b/src/patches/extensions/stage_name_subtitles.h new file mode 100644 index 00000000..0aa9b65b --- /dev/null +++ b/src/patches/extensions/stage_name_subtitles.h @@ -0,0 +1,8 @@ +#pragma once + +namespace stage_name_subtitles { + +void init_main_loop(); +void init_exoption(); + +}// namespace stage_name_subtitles \ No newline at end of file From b4dbe677b7a0afc16b35c2a9efd3cb846d585ab5 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 8 Jan 2025 23:59:05 -0800 Subject: [PATCH 10/96] Add type B scroll fix --- ...fix_transparency_type_b_texture_scroll.cpp | 21 +++++++++++++++++++ .../fix_transparency_type_b_texture_scroll.h | 7 +++++++ 2 files changed, 28 insertions(+) create mode 100644 src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp create mode 100644 src/patches/fixes/fix_transparency_type_b_texture_scroll.h diff --git a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp new file mode 100644 index 00000000..c42765b9 --- /dev/null +++ b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp @@ -0,0 +1,21 @@ +#include "fix_transparency_type_b_texture_scroll.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace fix_transparency_type_b_texture_scroll { + +TICKABLE_DEFINITION(( + .name = "fix-transparency-type-b-texture-scroll", + .description = "Transparency Type B texture scroll fix", + .enabled = true, + .init_main_loop = init_main_loop, )) + +// Always return 'true' for a specific instruction that checks if the texture should +// scroll or not on transparency type B stage models +void init_main_loop() { + patch::write_word(reinterpret_cast(0x802c8ce4), PPC_INSTR_LI(PPC_R3, 0x1)); +} + +}// namespace fix_transparency_type_b_texture_scroll diff --git a/src/patches/fixes/fix_transparency_type_b_texture_scroll.h b/src/patches/fixes/fix_transparency_type_b_texture_scroll.h new file mode 100644 index 00000000..a9c4dd38 --- /dev/null +++ b/src/patches/fixes/fix_transparency_type_b_texture_scroll.h @@ -0,0 +1,7 @@ +#pragma once + +namespace fix_transparency_type_b_texture_scroll { + +void init_main_loop(); + +}// namespace fix_transparency_type_b_texture_scroll \ No newline at end of file From ec7db163eb5d3e95acb6a6a68a58255191c8afa3 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 9 Jan 2025 00:36:19 -0800 Subject: [PATCH 11/96] Add options to skip-cutscenes --- configs/default-config.txt | 2 +- ...fix_transparency_type_b_texture_scroll.cpp | 1 - src/patches/fixes/fix_view_stage.cpp | 1 - src/patches/story/story_skip_cutscenes.h | 7 ---- .../skip_cutscenes.cpp} | 38 +++++++++++++++++-- src/patches/tweaks/skip_cutscenes.h | 7 ++++ 6 files changed, 42 insertions(+), 14 deletions(-) delete mode 100644 src/patches/story/story_skip_cutscenes.h rename src/patches/{story/story_skip_cutscenes.cpp => tweaks/skip_cutscenes.cpp} (73%) create mode 100644 src/patches/tweaks/skip_cutscenes.h diff --git a/configs/default-config.txt b/configs/default-config.txt index 3661f21c..ad4675a0 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -185,7 +185,7 @@ skip-intro-movie: disabled smb1-camera-toggle: disabled fix-missing-w: disabled - skip-cutscenes: disabled + skip-cutscenes: 0 remove-playpoints: disabled fix-storm-continue-platform: disabled fix-any-percent-crash: disabled diff --git a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp index c42765b9..9198eede 100644 --- a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp +++ b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp @@ -9,7 +9,6 @@ namespace fix_transparency_type_b_texture_scroll { TICKABLE_DEFINITION(( .name = "fix-transparency-type-b-texture-scroll", .description = "Transparency Type B texture scroll fix", - .enabled = true, .init_main_loop = init_main_loop, )) // Always return 'true' for a specific instruction that checks if the texture should diff --git a/src/patches/fixes/fix_view_stage.cpp b/src/patches/fixes/fix_view_stage.cpp index 0f53b92a..25a48cbb 100644 --- a/src/patches/fixes/fix_view_stage.cpp +++ b/src/patches/fixes/fix_view_stage.cpp @@ -9,7 +9,6 @@ namespace fix_view_stage { TICKABLE_DEFINITION(( .name = "fix-view-stage", .description = "Various 'View Stage' fixes", - .enabled = true, .init_main_game = init_main_game, )) void new_render_func(void) { diff --git a/src/patches/story/story_skip_cutscenes.h b/src/patches/story/story_skip_cutscenes.h deleted file mode 100644 index 5fa0b675..00000000 --- a/src/patches/story/story_skip_cutscenes.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace story_skip_cutscenes { - -void init_main_game(); - -}// namespace story_skip_cutscenes \ No newline at end of file diff --git a/src/patches/story/story_skip_cutscenes.cpp b/src/patches/tweaks/skip_cutscenes.cpp similarity index 73% rename from src/patches/story/story_skip_cutscenes.cpp rename to src/patches/tweaks/skip_cutscenes.cpp index 32a2ea2a..07e05451 100644 --- a/src/patches/story/story_skip_cutscenes.cpp +++ b/src/patches/tweaks/skip_cutscenes.cpp @@ -1,21 +1,27 @@ -#include "story_skip_cutscenes.h" +#include "skip_cutscenes.h" #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" +#include "utils/ppcutil.h" -namespace story_skip_cutscenes { +namespace skip_cutscenes { + +static u16 DEFAULT_CUTSCENE_SKIP_SETTING = 0; TICKABLE_DEFINITION(( .name = "skip-cutscenes", .description = "Cutscene skip patch", + .active_value = DEFAULT_CUTSCENE_SKIP_SETTING, + .lower_bound = 0, + .upper_bound = 3, .init_main_game = init_main_game, )) constexpr auto WORLD_COUNT = 10;// TODO: attach to patch that changes this // Skips cutscenes in story mode. -// TODO: Maybe fade the screen out so the transition screen color is not based off the world fog +// TODO: Maybe fade the screen out so the transition screen color is not based off the world fog // Variable for keeping track of the 'state' of the current story mode game. // This basically represents the active world, except world 11 is the credits sequence, @@ -119,6 +125,24 @@ void handle_preloading() { } void init_main_game() { + // 1 skips Story cutscenes only, 2 skips Challenge cutscenes only, 3 skips both + if (active_tickable_ptr->active_value == 1) { + patch::write_branch(reinterpret_cast(mkb::dmd_scen_newgame_main), + reinterpret_cast(dmd_scen_newgame_main_patch)); + patch::write_branch(reinterpret_cast(mkb::dmd_scen_sceneplay_init), + reinterpret_cast(dmd_scen_sceneplay_init_patch)); + patch::write_branch(reinterpret_cast(mkb::dmd_scen_sel_floor_init), + reinterpret_cast(dmd_scen_sel_floor_init_patch)); + patch::write_branch(reinterpret_cast(mkb::g_preload_next_stage_files), + reinterpret_cast(handle_preloading)); + } + else if (active_tickable_ptr->active_value == 2) { + // In the function which handles what to do when you goal, start the credits + // sequence instead of the ending cutscene in Challenge Mode + patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); + patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); + } + else if (active_tickable_ptr->active_value == 3) { patch::write_branch(reinterpret_cast(mkb::dmd_scen_newgame_main), reinterpret_cast(dmd_scen_newgame_main_patch)); patch::write_branch(reinterpret_cast(mkb::dmd_scen_sceneplay_init), @@ -127,6 +151,12 @@ void init_main_game() { reinterpret_cast(dmd_scen_sel_floor_init_patch)); patch::write_branch(reinterpret_cast(mkb::g_preload_next_stage_files), reinterpret_cast(handle_preloading)); + patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); + patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); + } + else { + return; + } } -}// namespace story_skip_cutscenes +}// namespace skip_cutscenes diff --git a/src/patches/tweaks/skip_cutscenes.h b/src/patches/tweaks/skip_cutscenes.h new file mode 100644 index 00000000..ff00478e --- /dev/null +++ b/src/patches/tweaks/skip_cutscenes.h @@ -0,0 +1,7 @@ +#pragma once + +namespace skip_cutscenes { + +void init_main_game(); + +}// namespace skip_cutscenes \ No newline at end of file From e5068570e0628907f0768809be740173b15c2d3d Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 9 Jan 2025 22:20:28 -0800 Subject: [PATCH 12/96] Death counter now skips Gameplay Settings screen --- src/patches/extensions/death_counter.cpp | 10 +++++++++- src/patches/extensions/death_counter.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/patches/extensions/death_counter.cpp b/src/patches/extensions/death_counter.cpp index 7a70a022..2d638aeb 100644 --- a/src/patches/extensions/death_counter.cpp +++ b/src/patches/extensions/death_counter.cpp @@ -7,7 +7,8 @@ namespace death_counter { TICKABLE_DEFINITION((.name = "challenge-mode-death-count", .description = "Challenge mode death count", - .init_main_game = init_main_game)) + .init_main_game = init_main_game, + .init_sel_ngc = init_sel_ngc)) // Death count for each of the four players static u32 death_count[4]; @@ -78,4 +79,11 @@ void init_main_game() { reinterpret_cast(death_counter_sprite_tick)); } +// In the function which handles inputs on the Challenge Mode level select +// menu, change the check for unlocked monkeys to be less than 3 to less than +// 255, effectively never displaying the Gameplay Settings menu +void init_sel_ngc() { + patch::write_word(reinterpret_cast(0x808ffb14), 0x2c0300ff); // cmpwi r3, 255 +} + }// namespace death_counter diff --git a/src/patches/extensions/death_counter.h b/src/patches/extensions/death_counter.h index 8a301ecc..d1d06edc 100644 --- a/src/patches/extensions/death_counter.h +++ b/src/patches/extensions/death_counter.h @@ -4,4 +4,5 @@ namespace death_counter { void init_main_game(); +void init_sel_ngc(); }// namespace death_counter \ No newline at end of file From 5683bd91381855a1563a0fa91593ec9579796252 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 9 Jan 2025 22:25:13 -0800 Subject: [PATCH 13/96] Add some UI fixes to fix-widescreen --- src/patches/extensions/death_counter.cpp | 2 +- src/patches/fixes/fix_widescreen.cpp | 199 ++++++++++++++++++++++- 2 files changed, 198 insertions(+), 3 deletions(-) diff --git a/src/patches/extensions/death_counter.cpp b/src/patches/extensions/death_counter.cpp index 2d638aeb..b34901e4 100644 --- a/src/patches/extensions/death_counter.cpp +++ b/src/patches/extensions/death_counter.cpp @@ -80,7 +80,7 @@ void init_main_game() { } // In the function which handles inputs on the Challenge Mode level select -// menu, change the check for unlocked monkeys to be less than 3 to less than +// menu, change the check for unlocked monkeys to be less than 4 to less than // 255, effectively never displaying the Gameplay Settings menu void init_sel_ngc() { patch::write_word(reinterpret_cast(0x808ffb14), 0x2c0300ff); // cmpwi r3, 255 diff --git a/src/patches/fixes/fix_widescreen.cpp b/src/patches/fixes/fix_widescreen.cpp index 2e468b4a..b8c19ea0 100644 --- a/src/patches/fixes/fix_widescreen.cpp +++ b/src/patches/fixes/fix_widescreen.cpp @@ -9,11 +9,195 @@ namespace fix_widescreen { TICKABLE_DEFINITION(( .name = "fix-widescreen", .description = "Widescreen fixes", + .init_main_loop = init_main_loop, .tick = tick, )) +// Fixed create sprite functions. Setting the second digit of the sprite's flag +// to 1 makes the sprite scale in widescreen +void create_new_bonus_sprite(u8* status, mkb::Sprite* sprite) { + + mkb::Sprite* pSVar1; + + pSVar1 = mkb::create_sprite(); + if (pSVar1 != (mkb::Sprite*) 0x0) { + (pSVar1->pos).x = 320.0; + (pSVar1->pos).y = 240.0; + pSVar1->depth = 0.05; + pSVar1->font = mkb::FONT_ASC_72x64; + pSVar1->alignment = mkb::ALIGN_CENTER; + pSVar1->g_counter = 0; + pSVar1->para1 = 1; + pSVar1->widescreen_translation_x = 0x140; + pSVar1->g_flags1 = pSVar1->g_flags1 | 0x1000000; + pSVar1->tick_func = mkb::sprite_bonus_finish_or_perfect_tick; + mkb::strcpy(pSVar1->text, "PERFECT"); + } + return; +} +void create_new_bonus_finish_sprite(u8* status, mkb::Sprite* sprite) { + + mkb::Sprite* pSVar1; + + pSVar1 = mkb::create_sprite(); + if (pSVar1 != (mkb::Sprite*) 0x0) { + (pSVar1->pos).x = 320.0; + (pSVar1->pos).y = 240.0; + pSVar1->depth = 0.05; + pSVar1->font = mkb::FONT_ASC_72x64; + pSVar1->alignment = mkb::ALIGN_CENTER; + pSVar1->g_counter = 0; + pSVar1->para1 = 0; + pSVar1->mult_color.red = 0xff; + pSVar1->mult_color.green = 0x80; + pSVar1->mult_color.blue = 0; + pSVar1->width = 0.8; + pSVar1->height = 0.8; + pSVar1->widescreen_translation_x = 0x140; + pSVar1->g_flags1 = pSVar1->g_flags1 | 0x1001000; + pSVar1->tick_func = mkb::sprite_bonus_finish_or_perfect_tick; + mkb::strcpy(pSVar1->text, "BONUS FINISH"); + } + return; +} +void create_new_pausemenu_sprite(u8* status, mkb::Sprite* sprite) { + + sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->unique_id = 0x4; + (sprite->pos).x = 315.0; + (sprite->pos).y = -128.0; + sprite->type = mkb::SPRT_BMP; + sprite->font = mkb::FONT_ASC_24x24; + sprite->alignment = mkb::ALIGN_CENTER; + sprite->depth = 0.005; + sprite->para1 = 1; + sprite->g_flags1 = 0x1000000; + sprite->widescreen_translation_x = 0x140; + sprite->fpara1 = 0.0; + sprite->alpha = 0.5; + sprite->mult_color.red = '\0'; + sprite->mult_color.green = '\0'; + sprite->mult_color.blue = '\0'; + sprite->width = 0.0; + sprite->height = 0.0; + sprite->g_counter = 1; + sprite->disp_func = mkb::sprite_pausemenu_disp; + mkb::strcpy(sprite->text, "pause menu"); + } + return; +} +// The fallout check allows the sprite to properly align with the GOAL or FALL OUT +// sprite when in widescreen, as their positions are different compared to playing +// in 4:3 +void create_new_replay_sprite(u8* status, mkb::Sprite* sprite) { + + sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { + (sprite->pos).x = 760.0; + (sprite->pos).y = 460.0; + sprite->font = mkb::FONT_ASC_16x16; + sprite->alignment = mkb::ALIGN_UPPER_LEFT; + sprite->depth = 0.09; + sprite->width = 1.25; + sprite->height = 1.25; + sprite->g_counter = 222; + sprite->g_flags1 = 0x1000000; + if (mkb::did_ball_fallout(mkb::current_ball) == true) { + sprite->widescreen_translation_x = 0x280; + } + else { + sprite->widescreen_translation_x = 0x215; + } + sprite->tick_func = mkb::sprite_replay_tick; + mkb::strcpy(sprite->text, "REPLAY"); + } + sprite = mkb::get_sprite_with_unique_id(0xe); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->para1 = 0xf; + } + return; +} +void create_new_1up_sprite(u8* status, mkb::Sprite* sprite) { + + sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->unique_id = 0x10; + (sprite->pos).x = 320.0; + (sprite->pos).y = 300.0; + sprite->font = mkb::FONT_ASC_72x64; + sprite->alignment = mkb::ALIGN_CENTER; + sprite->alpha = 0.0; + sprite->g_counter = 150; + sprite->g_flags1 = 0x1000000; + sprite->widescreen_translation_x = 0x140; + sprite->para1 = 120; + sprite->tick_func = mkb::sprite_1up_tick; + mkb::strcpy(sprite->text, "1UP"); + } + return; +} +// The main_game_mode check prevents the sprite from appearing in Story Mode +// after a one-stage difficulty is played +void create_new_final_stage_sprite(u8* status, mkb::Sprite* sprite) { + sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->unique_id = 14; + (sprite->pos).x = 320.0; + (sprite->pos).y = 300.0; + sprite->font = mkb::FONT_ASC_72x64; + sprite->alignment = mkb::ALIGN_CENTER; + sprite->width = 0.5; + sprite->height = 0.5; + sprite->g_counter = 0x96; + sprite->g_flags1 = sprite->g_flags1 | 0x1001000; + sprite->widescreen_translation_x = 0x140; + sprite->tick_func = mkb::sprite_final_stage_tick; + sprite->disp_func = mkb::sprite_final_stage_disp; + if (mkb::main_game_mode == mkb::STORY_MODE) { + mkb::strcpy(sprite->text, ""); + } + else { + mkb::strcpy(sprite->text, mkb::LOADIN_TEXT_FINAL_STAGE); + } + } +} + +// Call our fixed create sprite functions in place of the originals, then +// enlargen the pausemenu's dim area. Then, handle sprite type changes for +// the "JUMP TO STAGE" sprite and continues remaining sprite +void init_main_loop() { + patch::write_branch( + reinterpret_cast(mkb::create_bonus_finish_or_perfect_sprite), + reinterpret_cast(create_new_bonus_sprite)); + patch::write_branch( + reinterpret_cast(mkb::create_pausemenu_sprite), + reinterpret_cast(create_new_pausemenu_sprite)); + patch::write_branch( + reinterpret_cast(mkb::create_replay_sprite), + reinterpret_cast(create_new_replay_sprite)); + patch::write_branch( + reinterpret_cast(mkb::create_1up_sprite), + reinterpret_cast(create_new_1up_sprite)); + patch::write_branch( + reinterpret_cast(mkb::create_bonus_finish_sprite), + reinterpret_cast(create_new_bonus_finish_sprite)); + patch::write_branch( + reinterpret_cast(mkb::create_final_stage_sprite), + reinterpret_cast(create_new_final_stage_sprite)); + patch::write_word(reinterpret_cast(0x803e7a28), 0x43b40000); + patch::write_word(reinterpret_cast(0x8032e0e4), (0x6400a100)); + patch::write_word(reinterpret_cast(0x8032e798), (0x6400a100)); + patch::write_word(reinterpret_cast(0x8032f268), (0x6400a100)); +} + + // The SEL_NGC check fixes less being visible vertically when playing in widescreen. -// It only activates when we're not in menus as the calibration menu's visuals break otherwise. -// The MD_GAME check fixes the View Stage aspect ratio when in widescreen. +// It only activates when we're not in menus as calibration breaks visually otherwise. +// The MD_GAME check fixes the View Stage aspect ratio when in widescreen. The STORY_MODE +// check nulls out the FINAL STAGE text for the load-in to prevent it from displaying +// when one-stage difficulties are present and the rest changes the JUMP TO STAGE and +// continues remaining sprite position pointers and values in widescreen since there's +// not enough space in their create functions to add a widescreen translation field void tick() { if (mkb::sub_mode == mkb::SMD_SEL_NGC_MAIN) { @@ -30,6 +214,17 @@ void tick() { mkb::view_stage_aspect_ratio = 1.777777777f; } } + if (mkb::widescreen_mode == 0) { + patch::write_word(reinterpret_cast(0x8032e048), (0xc01f0038)); + patch::write_word(reinterpret_cast(0x8032e6b0), (0xc01f0038)); + patch::write_word(reinterpret_cast(0x803e7cf4), (0x43f50000)); + } + else { + patch::write_word(reinterpret_cast(0x8032e048), (0xc01f00ac)); + patch::write_word(reinterpret_cast(0x803e7a3c), (0x43d98000)); + patch::write_word(reinterpret_cast(0x8032e6b0), (0xc01f00ac)); + patch::write_word(reinterpret_cast(0x803e7cf4), (0x4414c000)); + } } }// namespace fix_widescreen \ No newline at end of file From 3b4727df18687dc128ffb0dd6f6fe76420679456 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 9 Jan 2025 22:42:09 -0800 Subject: [PATCH 14/96] Add pause cooldown patch --- src/patches/tweaks/pause_cooldown.cpp | 22 ++++++++++++++++++++++ src/patches/tweaks/pause_cooldown.h | 7 +++++++ 2 files changed, 29 insertions(+) create mode 100644 src/patches/tweaks/pause_cooldown.cpp create mode 100644 src/patches/tweaks/pause_cooldown.h diff --git a/src/patches/tweaks/pause_cooldown.cpp b/src/patches/tweaks/pause_cooldown.cpp new file mode 100644 index 00000000..b8c3f207 --- /dev/null +++ b/src/patches/tweaks/pause_cooldown.cpp @@ -0,0 +1,22 @@ +#include "pause_cooldown.h" + +#include "internal/patch.h" +#include "internal/tickable.h" + +namespace pause_cooldown { + +TICKABLE_DEFINITION(( + .name = "pause-cooldown", + .description = "Pause cooldown", + .tick = tick, )) + +// When the game is paused, set the pause cooldown to 60 frames +// every frame, ensuring even once unpaused the player must wait +// a full second before pausing again +void tick() { + if (mkb::g_pause_status == 2) { + mkb::g_repause_cooldown_counter = 0x3c; + } +} + +}// namespace pause_cooldown diff --git a/src/patches/tweaks/pause_cooldown.h b/src/patches/tweaks/pause_cooldown.h new file mode 100644 index 00000000..94fd45e2 --- /dev/null +++ b/src/patches/tweaks/pause_cooldown.h @@ -0,0 +1,7 @@ +#pragma once + +namespace pause_cooldown { + +void tick(); + +}// namespace pause_cooldown \ No newline at end of file From 8581f15354781b52b34c5c1516706f3ab7e32dad Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 9 Jan 2025 23:14:19 -0800 Subject: [PATCH 15/96] Add monkey counter sprite fix patch --- src/patches/fixes/fix_monkey_counter.cpp | 24 ++++++++++++++++++++++++ src/patches/fixes/fix_monkey_counter.h | 7 +++++++ 2 files changed, 31 insertions(+) create mode 100644 src/patches/fixes/fix_monkey_counter.cpp create mode 100644 src/patches/fixes/fix_monkey_counter.h diff --git a/src/patches/fixes/fix_monkey_counter.cpp b/src/patches/fixes/fix_monkey_counter.cpp new file mode 100644 index 00000000..5cb15be3 --- /dev/null +++ b/src/patches/fixes/fix_monkey_counter.cpp @@ -0,0 +1,24 @@ +#include "fix_monkey_counter.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace fix_monkey_counter { + +TICKABLE_DEFINITION(( + .name = "fix-monkey-counter", + .description = "Monkey counter sprite fix", + .enabled = true, + .init_main_loop = init_main_loop, )) + +// In the function responsible for displaying the monkey +// counter sprite, check for if monkey count is less than +// 255 instead of 4, effectively never executing leftover +// sprite code from SMB1 +void init_main_loop() { + patch::write_word(reinterpret_cast(0x80332874), 0x2c0000ff); // cmpwi r0, 255 + patch::write_word(reinterpret_cast(0x80332f94), 0x2c0000ff); // cmpwi r0, 255 +} + +}// namespace fix_monkey_counter diff --git a/src/patches/fixes/fix_monkey_counter.h b/src/patches/fixes/fix_monkey_counter.h new file mode 100644 index 00000000..d6acfed4 --- /dev/null +++ b/src/patches/fixes/fix_monkey_counter.h @@ -0,0 +1,7 @@ +#pragma once + +namespace fix_monkey_counter { + +void init_main_loop(); + +}// namespace fix_monkey_counter \ No newline at end of file From 127ba75a80ac3d240efe48482f0617fb45eab047 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Sat, 11 Jan 2025 15:28:37 -0800 Subject: [PATCH 16/96] Add patch to remove stage slot hardcodes + remove Bonus Wave drawing code from fix-view-stage --- src/patches/fixes/fix_monkey_counter.cpp | 1 - src/patches/fixes/fix_view_stage.cpp | 8 ++--- src/patches/tweaks/remove_hardcodes.cpp | 38 ++++++++++++++++++++++++ src/patches/tweaks/remove_hardcodes.h | 8 +++++ 4 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 src/patches/tweaks/remove_hardcodes.cpp create mode 100644 src/patches/tweaks/remove_hardcodes.h diff --git a/src/patches/fixes/fix_monkey_counter.cpp b/src/patches/fixes/fix_monkey_counter.cpp index 5cb15be3..4d04f6d7 100644 --- a/src/patches/fixes/fix_monkey_counter.cpp +++ b/src/patches/fixes/fix_monkey_counter.cpp @@ -9,7 +9,6 @@ namespace fix_monkey_counter { TICKABLE_DEFINITION(( .name = "fix-monkey-counter", .description = "Monkey counter sprite fix", - .enabled = true, .init_main_loop = init_main_loop, )) // In the function responsible for displaying the monkey diff --git a/src/patches/fixes/fix_view_stage.cpp b/src/patches/fixes/fix_view_stage.cpp index 25a48cbb..1b73dbf4 100644 --- a/src/patches/fixes/fix_view_stage.cpp +++ b/src/patches/fixes/fix_view_stage.cpp @@ -16,7 +16,6 @@ void new_render_func(void) { bool bVar4; mkb::uint uVar2; mkb::GmaModel* pGVar3; - int* piVar5; mkb::StagedefStageModelPtrB* pSVar6; int iVar7; mkb::StagedefStageModelInstance* pSVar8; @@ -101,20 +100,17 @@ void new_render_func(void) { } if (mkb::g_some_draw_var != (int*) 0x0) { mkb::mtxa_from_mtxb(); - for (piVar5 = mkb::g_some_draw_var; *piVar5 != 0; piVar5 = piVar5 + 6) { - mkb::g_some_draw_func5((int*) piVar5[5]); - } } mkb::g_draw_collision_triangles(); return; } void init_main_game() { - // Prevent background animations from animating twice as fast in 'View Stage' - patch::write_nop(reinterpret_cast(0x80912d90)); patch::write_branch( reinterpret_cast(mkb::g_smth_with_rendering_models_for_reflective_surfaces), reinterpret_cast(new_render_func)); + // Prevent background animations from animating twice as fast in 'View Stage' + patch::write_nop(reinterpret_cast(0x80912d90)); } }// namespace fix_view_stage diff --git a/src/patches/tweaks/remove_hardcodes.cpp b/src/patches/tweaks/remove_hardcodes.cpp new file mode 100644 index 00000000..8cce3e5d --- /dev/null +++ b/src/patches/tweaks/remove_hardcodes.cpp @@ -0,0 +1,38 @@ +#include "remove_hardcodes.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace remove_hardcodes { + +TICKABLE_DEFINITION(( + .name = "remove-stage-slot-hardcodes", + .description = "Remove stage slot hardcodes", + .init_main_loop = init_main_loop, + .init_main_game = init_main_game, )) + +void init_main_loop() { + // Nop a call to handle hardcoded stage object drawing for + // SMB2 stages + patch::write_nop(reinterpret_cast(0x802c96d8)); + // Nop a call to handle hardcoded stage lights leftover from + // SMB1 + patch::write_nop(reinterpret_cast(0x802945d8)); + // In the function which handles Bonus Wave's collision, nop + // the part which decides what space has hardcoded collision + patch::write_nop(reinterpret_cast(0x802c79b4)); + // In an array for hardcoded camera settings, check for stage ID + // 0xffffffff instead of any used stage slots + patch::write_word(reinterpret_cast(0x8044b208), 0xffffffff); + patch::write_word(reinterpret_cast(0x8044b1e0), 0xffffffff); + patch::write_word(reinterpret_cast(0x8044b1f4), 0xffffffff); +} + +void init_main_game() { + // Nop a call to handle hardcoded stage object drawing for + // SMB2 stages + patch::write_nop(reinterpret_cast(0x809140f4)); +} + +}// namespace remove_hardcodes diff --git a/src/patches/tweaks/remove_hardcodes.h b/src/patches/tweaks/remove_hardcodes.h new file mode 100644 index 00000000..13987aee --- /dev/null +++ b/src/patches/tweaks/remove_hardcodes.h @@ -0,0 +1,8 @@ +#pragma once + +namespace remove_hardcodes { + +void init_main_loop(); +void init_main_game(); + +}// namespace remove_hardcodes \ No newline at end of file From a857e55ee676bc91775893c47e4ece03c036fab5 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 00:10:54 -0800 Subject: [PATCH 17/96] Add Challenge Mode retry patch + fix type B scroll fix --- src/mkb/mkb2.us.lst | 3 + src/mkb/mkb2_ghidra.h | 5 +- src/patches/extensions/challenge_retry.cpp | 148 ++++++++++++++++++ src/patches/extensions/challenge_retry.h | 5 + src/patches/extensions/death_counter.h | 1 + ...fix_transparency_type_b_texture_scroll.cpp | 2 +- 6 files changed, 162 insertions(+), 2 deletions(-) create mode 100644 src/patches/extensions/challenge_retry.cpp create mode 100644 src/patches/extensions/challenge_retry.h diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 2dce359f..3fcbbaf5 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -8313,6 +8313,9 @@ 8047EA48:switchdataD_803a8800 8047EADC:switchdataD_803a8894 8047EB14:switchdataD_803a88cc +8047EED4:challenge_play_pausemenu_entries +8047EF94:goal_pausemenu_entries +8047F4A4:pausemenu_entry_pointers 8047F770:LOADIN_TEXT_ROUND 8047F77C:LOADIN_TEXT_WORLD 8047F788:LOADIN_TEXT_MASTER_EX diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index f88330f9..212c451a 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5664,7 +5664,7 @@ extern "C" { extern float FLOAT0; extern float FLOAT1; extern float FLOAT400; - extern undefined1 pausemenu_entry_counts; + extern byte pausemenu_entry_counts[8]; extern undefined4 g_something_with_camera; extern double g_related_to_camera_turn_rate_and_stage_tilt; extern float camera_near_clip_z; @@ -5878,6 +5878,9 @@ extern "C" { extern pointer switchdataD_803a8800; extern pointer switchdataD_803a8894; extern undefined * switchdataD_803a88cc; + extern char * challenge_play_pausemenu_entries[24]; + extern char * goal_pausemenu_entries[24]; + extern char * * pausemenu_entry_pointers[16]; extern char LOADIN_TEXT_ROUND[9]; extern char LOADIN_TEXT_WORLD[12]; extern char LOADIN_TEXT_MASTER_EX[12]; diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp new file mode 100644 index 00000000..2319da5b --- /dev/null +++ b/src/patches/extensions/challenge_retry.cpp @@ -0,0 +1,148 @@ +#include "challenge_retry.h" +#include "../internal/pad.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" +#include "death_counter.h" + +namespace challenge_retry { + +TICKABLE_DEFINITION(( + .name = "challenge-mode-retry", + .description = "Challenge Mode retry", + .enabled = true, + .init_main_loop = init)) + +static patch::Tramp s_pause_game_tramp; + +int original_pausemenu_selection; + +void pausemenu_handler() { + int ball_index; + mkb::Ball* ball; + + const int total_size = 30; // Adjust size based on gaps and strings + const int gap_size = 5; // Gap of nullptrs between each string (game expects these to be localized strings) + + // Array of pointers to strings + static char* menu_options_1[total_size] = { nullptr }; + static char* menu_options_2[total_size] = { nullptr }; + + // Strings to be stored in the array + char* options_1[] = { + // Menu strings during gameplay + "Continue game", + "Retry", + "View stage", + "How to play", + "Exit game" + }; + char* options_2[] = { + // Menu strings during replay + "Continue game", + "Retry", + "Save replay", + "How to play", + "Exit game" + }; + + // Fill the array with strings and gaps of nullptrs + int current_index = 0; + for (int i = 0; i < 5; ++i) { + menu_options_1[current_index] = options_1[i]; + menu_options_2[current_index] = options_2[i]; + current_index += gap_size + 1; // Move index by 1 (string) + gap size + } + + if (mkb::main_game_mode == mkb::CHALLENGE_MODE) { + if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN || + mkb::sub_mode == mkb::SMD_GAME_GOAL_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_MAIN || + mkb::sub_mode == mkb::SMD_GAME_READY_INIT || mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || + mkb::mode_info.ball_mode == mkb::BALLMODE_ON_BONUS_STAGE || mkb::num_players != 1 || + mkb::balls[0].monkey_count < 2 || (mkb::mode_info.ball_mode & mkb::BALLMODE_GOALED)) { + mkb::pausemenu_entry_counts[1] = 4; + mkb::g_current_pause_menu_entry_count = 4; + mkb::pausemenu_entry_pointers[9] = mkb::goal_pausemenu_entries; + mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; + patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004); // in the instruction which handles pausemenu input, Exit Game when option 4 is selected + } + else if ((mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || mkb::sub_mode == mkb::SMD_GAME_READY_INIT) && mkb::mode_info.attempt_count > 1) { + mkb::pausemenu_entry_counts[1] = 4; + mkb::g_current_pause_menu_entry_count = 4; + mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; + patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004); // in the instruction which handles pausemenu input, Exit Game when option 4 is selected + } + else if (mkb::sub_mode == mkb::SMD_GAME_ROLL_INIT || mkb::sub_mode == mkb::SMD_GAME_ROLL_MAIN) { + // The credits minigame uses the same main game mode as Challenge Mode, so we need a special case to set its respective menu + mkb::pausemenu_type = 7; + } + else { + // Okay, things get messy here... + // The vanilla pausemenu function is messy in itself, so the idea is to fakematch each visual selection with its internal selection + // The bitflag check on these has something to do with if we're in a subscreen of the pausemenu + + // View stage + if (mkb::g_current_focused_pause_menu_entry == 2 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_current_focused_pause_menu_entry = 1; + original_pausemenu_selection = 2; + } + // How to play + else if (mkb::g_current_focused_pause_menu_entry == 3 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_current_focused_pause_menu_entry = 2; + original_pausemenu_selection = 3; + } + // Retry + else if (mkb::g_current_focused_pause_menu_entry == 1 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_current_focused_pause_menu_entry = 5; + // If death count is enabled, increment the death counter + // Otherwise, decrement the life counter + if (tickable::get_tickable_manager().get_tickable_status("challenge-mode-death-count")) { + death_counter::update_death_count(); + } + else { + mkb::Ball* ball = mkb::balls; + for (int idx = 0; idx < 4; idx++) { + if (ball->status == mkb::STAT_NORMAL) { + ball->monkey_count--; + } + ball++; + } + } + mkb::mode_info.attempt_count = mkb::mode_info.attempt_count + 1; + ball = mkb::balls; + ball_index = mkb::curr_player_idx; + for (ball_index = 0; ball_index < 8; ball_index = ball_index + 1) { + if (ball->status == mkb::STAT_NORMAL) { + ball->phys_flags = ball->phys_flags; + ball->g_effect_flags = ball->g_effect_flags | 0x80; + } + ball = ball + 1; + } + mkb::sub_mode_request = mkb::SMD_GAME_READY_INIT; + mkb::g_fade_track_volume(100, '\n'); + } + // Return our original visual selection once we exit a subscreen of the pausemenu + if (mkb::g_some_pausemenu_var != 0xffffffff) { + mkb::g_current_focused_pause_menu_entry = original_pausemenu_selection; + } + // Repoint menu entries to our expanded ones + mkb::pausemenu_entry_pointers[1] = menu_options_1; + mkb::pausemenu_entry_pointers[9] = menu_options_2; + patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000005); // in the instruction which handles pausemenu input, Exit Game when option 5 is selected + // Expand entry count + mkb::pausemenu_entry_counts[1] = 5; + mkb::g_current_pause_menu_entry_count = 5; + // Set the pausemenu type to 'normal' Challenge Mode's + mkb::pausemenu_type = 1; + } + } +} + +void init() { + patch::hook_function(s_pause_game_tramp, mkb::pause_game, []() { + s_pause_game_tramp.dest(); + pausemenu_handler(); + }); +} + +}// namespace challenge_retry \ No newline at end of file diff --git a/src/patches/extensions/challenge_retry.h b/src/patches/extensions/challenge_retry.h new file mode 100644 index 00000000..880c2377 --- /dev/null +++ b/src/patches/extensions/challenge_retry.h @@ -0,0 +1,5 @@ +#pragma once + +namespace challenge_retry { +void init(); +}// namespace challenge_retry \ No newline at end of file diff --git a/src/patches/extensions/death_counter.h b/src/patches/extensions/death_counter.h index d1d06edc..2bfd95b6 100644 --- a/src/patches/extensions/death_counter.h +++ b/src/patches/extensions/death_counter.h @@ -5,4 +5,5 @@ namespace death_counter { void init_main_game(); void init_sel_ngc(); +u32 update_death_count(); }// namespace death_counter \ No newline at end of file diff --git a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp index 9198eede..19385170 100644 --- a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp +++ b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp @@ -14,7 +14,7 @@ TICKABLE_DEFINITION(( // Always return 'true' for a specific instruction that checks if the texture should // scroll or not on transparency type B stage models void init_main_loop() { - patch::write_word(reinterpret_cast(0x802c8ce4), PPC_INSTR_LI(PPC_R3, 0x1)); + patch::write_word(reinterpret_cast(0x802c94f8), PPC_INSTR_LI(PPC_R3, 0x1)); } }// namespace fix_transparency_type_b_texture_scroll From 25485d7c2bbcc5ef340241debcfe034966813603 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 14:50:19 -0800 Subject: [PATCH 18/96] Add patch to fix goal readings on stages with numerous goals --- src/patches/extensions/challenge_retry.cpp | 1 - src/patches/fixes/fix_goal_types.cpp | 23 ++++++++++++++++++++++ src/patches/fixes/fix_goal_types.h | 7 +++++++ 3 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 src/patches/fixes/fix_goal_types.cpp create mode 100644 src/patches/fixes/fix_goal_types.h diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index 2319da5b..4bce0291 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -10,7 +10,6 @@ namespace challenge_retry { TICKABLE_DEFINITION(( .name = "challenge-mode-retry", .description = "Challenge Mode retry", - .enabled = true, .init_main_loop = init)) static patch::Tramp s_pause_game_tramp; diff --git a/src/patches/fixes/fix_goal_types.cpp b/src/patches/fixes/fix_goal_types.cpp new file mode 100644 index 00000000..4162e7e7 --- /dev/null +++ b/src/patches/fixes/fix_goal_types.cpp @@ -0,0 +1,23 @@ +#include "fix_goal_types.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace fix_goal_types { + +TICKABLE_DEFINITION(( + .name = "fix-goal-types", + .description = "Goal type fix", + .init_main_loop = init_main_loop, )) + +// In functions responsible for calculating goal score and +// type, check for goal IDs up to 255 instead of up to 3, +// preventing score and warp issues on stages with loads of +// goals +void init_main_loop() { + patch::write_word(reinterpret_cast(0x802d81a8), 0x2c0800ff); // cmpwi r8, 255 + patch::write_word(reinterpret_cast(0x8031373c), 0x2c0500ff); // cmpwi r5, 255 +} + +}// namespace fix_goal_types diff --git a/src/patches/fixes/fix_goal_types.h b/src/patches/fixes/fix_goal_types.h new file mode 100644 index 00000000..8961ca76 --- /dev/null +++ b/src/patches/fixes/fix_goal_types.h @@ -0,0 +1,7 @@ +#pragma once + +namespace fix_goal_types { + +void init_main_loop(); + +}// namespace fix_goal_types \ No newline at end of file From a1311aa8873c545e95adffcd2827c91b172a8196 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 15:15:22 -0800 Subject: [PATCH 19/96] Add patch to remove extras --- src/patches/tweaks/remove_extras.cpp | 20 ++++++++++++++++++++ src/patches/tweaks/remove_extras.h | 7 +++++++ 2 files changed, 27 insertions(+) create mode 100644 src/patches/tweaks/remove_extras.cpp create mode 100644 src/patches/tweaks/remove_extras.h diff --git a/src/patches/tweaks/remove_extras.cpp b/src/patches/tweaks/remove_extras.cpp new file mode 100644 index 00000000..9c092e14 --- /dev/null +++ b/src/patches/tweaks/remove_extras.cpp @@ -0,0 +1,20 @@ +#include "remove_extras.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace remove_extras { + +TICKABLE_DEFINITION(( + .name = "remove-extras", + .description = "Remove extras", + .init_main_game = init_main_game, )) + +// Always return 'false' in the function which handles what to do +// once you enter a goal +void init_main_game() { + patch::write_word(reinterpret_cast(0x808f61a8), PPC_INSTR_LI(PPC_R4, 0x0)); +} + +}// namespace remove_extras diff --git a/src/patches/tweaks/remove_extras.h b/src/patches/tweaks/remove_extras.h new file mode 100644 index 00000000..e9a41619 --- /dev/null +++ b/src/patches/tweaks/remove_extras.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_extras { + +void init_main_game(); + +}// namespace remove_extras \ No newline at end of file From 2774517a1a291472dd6c62f4091055e5c83fb77d Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 15:21:25 -0800 Subject: [PATCH 20/96] Add patch to remove 1UP sprite --- src/patches/tweaks/remove_1up_sprite.cpp | 18 ++++++++++++++++++ src/patches/tweaks/remove_1up_sprite.h | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 src/patches/tweaks/remove_1up_sprite.cpp create mode 100644 src/patches/tweaks/remove_1up_sprite.h diff --git a/src/patches/tweaks/remove_1up_sprite.cpp b/src/patches/tweaks/remove_1up_sprite.cpp new file mode 100644 index 00000000..76a2da0e --- /dev/null +++ b/src/patches/tweaks/remove_1up_sprite.cpp @@ -0,0 +1,18 @@ +#include "remove_1up_sprite.h" + +#include "internal/patch.h" +#include "internal/tickable.h" + +namespace remove_1up_sprite { + +TICKABLE_DEFINITION(( + .name = "remove-1up-sprite", + .description = "1UP sprite removal", + .init_main_loop = init_main_loop, )) + +// Nops a call to the function which draws the 1UP sprite +void init_main_loop() { + patch::write_nop(reinterpret_cast(0x802b8264)); +} + +}// namespace remove_1up_sprite diff --git a/src/patches/tweaks/remove_1up_sprite.h b/src/patches/tweaks/remove_1up_sprite.h new file mode 100644 index 00000000..81fa7839 --- /dev/null +++ b/src/patches/tweaks/remove_1up_sprite.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_1up_sprite { + +void init_main_loop(); + +}// namespace remove_1up_sprite \ No newline at end of file From dfbee8ce7aa0b45f61711b465c8c0f68b708a657 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 15:44:56 -0800 Subject: [PATCH 21/96] Add removal folder to patches + merge Revolution and Labyrinth fixes into remove-hardcodes --- src/patches/fixes/fix_labyrinth_camera.h | 7 ---- src/patches/fixes/fix_revolution_slot.cpp | 20 ---------- src/patches/fixes/fix_revolution_slot.h | 7 ---- .../remove_1up_sprite.cpp | 0 .../{tweaks => removals}/remove_1up_sprite.h | 0 .../remove_desert_haze.cpp | 0 .../{tweaks => removals}/remove_desert_haze.h | 0 .../{tweaks => removals}/remove_extras.cpp | 0 .../{tweaks => removals}/remove_extras.h | 0 .../remove_hardcodes.cpp} | 39 ++++++++++++++----- .../{tweaks => removals}/remove_hardcodes.h | 0 .../remove_hurry_up_music.cpp} | 8 ++-- src/patches/removals/remove_hurry_up_music.h | 8 ++++ .../remove_intro_cutscene.cpp} | 10 ++--- src/patches/removals/remove_intro_cutscene.h | 7 ++++ .../remove_playpoints.cpp | 0 .../{tweaks => removals}/remove_playpoints.h | 0 .../remove_story_cutscenes.cpp} | 10 ++--- src/patches/removals/remove_story_cutscenes.h | 7 ++++ .../remove_tutorial.cpp} | 8 ++-- src/patches/removals/remove_tutorial.h | 7 ++++ .../remove_volume_decrease_on_pause.cpp} | 8 ++-- .../remove_volume_decrease_on_pause.h | 7 ++++ src/patches/tweaks/disable_tutorial.h | 7 ---- src/patches/tweaks/no_hurry_up_music.h | 8 ---- src/patches/tweaks/pause_volume_fix.h | 7 ---- src/patches/tweaks/remove_hardcodes.cpp | 38 ------------------ src/patches/tweaks/skip_cutscenes.h | 7 ---- src/patches/tweaks/skip_intro_movie.h | 7 ---- 29 files changed, 88 insertions(+), 139 deletions(-) delete mode 100644 src/patches/fixes/fix_labyrinth_camera.h delete mode 100644 src/patches/fixes/fix_revolution_slot.cpp delete mode 100644 src/patches/fixes/fix_revolution_slot.h rename src/patches/{tweaks => removals}/remove_1up_sprite.cpp (100%) rename src/patches/{tweaks => removals}/remove_1up_sprite.h (100%) rename src/patches/{tweaks => removals}/remove_desert_haze.cpp (100%) rename src/patches/{tweaks => removals}/remove_desert_haze.h (100%) rename src/patches/{tweaks => removals}/remove_extras.cpp (100%) rename src/patches/{tweaks => removals}/remove_extras.h (100%) rename src/patches/{fixes/fix_labyrinth_camera.cpp => removals/remove_hardcodes.cpp} (51%) rename src/patches/{tweaks => removals}/remove_hardcodes.h (100%) rename src/patches/{tweaks/no_hurry_up_music.cpp => removals/remove_hurry_up_music.cpp} (83%) create mode 100644 src/patches/removals/remove_hurry_up_music.h rename src/patches/{tweaks/skip_intro_movie.cpp => removals/remove_intro_cutscene.cpp} (71%) create mode 100644 src/patches/removals/remove_intro_cutscene.h rename src/patches/{tweaks => removals}/remove_playpoints.cpp (100%) rename src/patches/{tweaks => removals}/remove_playpoints.h (100%) rename src/patches/{tweaks/skip_cutscenes.cpp => removals/remove_story_cutscenes.cpp} (96%) create mode 100644 src/patches/removals/remove_story_cutscenes.h rename src/patches/{tweaks/disable_tutorial.cpp => removals/remove_tutorial.cpp} (75%) create mode 100644 src/patches/removals/remove_tutorial.h rename src/patches/{tweaks/pause_volume_fix.cpp => removals/remove_volume_decrease_on_pause.cpp} (64%) create mode 100644 src/patches/removals/remove_volume_decrease_on_pause.h delete mode 100644 src/patches/tweaks/disable_tutorial.h delete mode 100644 src/patches/tweaks/no_hurry_up_music.h delete mode 100644 src/patches/tweaks/pause_volume_fix.h delete mode 100644 src/patches/tweaks/remove_hardcodes.cpp delete mode 100644 src/patches/tweaks/skip_cutscenes.h delete mode 100644 src/patches/tweaks/skip_intro_movie.h diff --git a/src/patches/fixes/fix_labyrinth_camera.h b/src/patches/fixes/fix_labyrinth_camera.h deleted file mode 100644 index c939aa91..00000000 --- a/src/patches/fixes/fix_labyrinth_camera.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace fix_labyrinth_camera { - -void init_main_loop(); - -}// namespace fix_labyrinth_camera \ No newline at end of file diff --git a/src/patches/fixes/fix_revolution_slot.cpp b/src/patches/fixes/fix_revolution_slot.cpp deleted file mode 100644 index f4818491..00000000 --- a/src/patches/fixes/fix_revolution_slot.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "fix_revolution_slot.h" - -#include "internal/patch.h" -#include "internal/tickable.h" -#include "utils/ppcutil.h" - -namespace fix_revolution_slot { - -TICKABLE_DEFINITION(( - .name = "fix-revolution-slot", - .description = "Revolution stage slot fix", - .init_main_loop = init_main_loop, )) - -// Always return 'false' for a specific function that checks if the stage ID -// is 348 when determining whether or not to handle level loading specially -void init_main_loop() { - patch::write_word(reinterpret_cast(0x802ca9fc), PPC_INSTR_LI(PPC_R3, 0x0)); -} - -}// namespace fix_revolution_slot diff --git a/src/patches/fixes/fix_revolution_slot.h b/src/patches/fixes/fix_revolution_slot.h deleted file mode 100644 index 43928686..00000000 --- a/src/patches/fixes/fix_revolution_slot.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace fix_revolution_slot { - -void init_main_loop(); - -}// namespace fix_revolution_slot \ No newline at end of file diff --git a/src/patches/tweaks/remove_1up_sprite.cpp b/src/patches/removals/remove_1up_sprite.cpp similarity index 100% rename from src/patches/tweaks/remove_1up_sprite.cpp rename to src/patches/removals/remove_1up_sprite.cpp diff --git a/src/patches/tweaks/remove_1up_sprite.h b/src/patches/removals/remove_1up_sprite.h similarity index 100% rename from src/patches/tweaks/remove_1up_sprite.h rename to src/patches/removals/remove_1up_sprite.h diff --git a/src/patches/tweaks/remove_desert_haze.cpp b/src/patches/removals/remove_desert_haze.cpp similarity index 100% rename from src/patches/tweaks/remove_desert_haze.cpp rename to src/patches/removals/remove_desert_haze.cpp diff --git a/src/patches/tweaks/remove_desert_haze.h b/src/patches/removals/remove_desert_haze.h similarity index 100% rename from src/patches/tweaks/remove_desert_haze.h rename to src/patches/removals/remove_desert_haze.h diff --git a/src/patches/tweaks/remove_extras.cpp b/src/patches/removals/remove_extras.cpp similarity index 100% rename from src/patches/tweaks/remove_extras.cpp rename to src/patches/removals/remove_extras.cpp diff --git a/src/patches/tweaks/remove_extras.h b/src/patches/removals/remove_extras.h similarity index 100% rename from src/patches/tweaks/remove_extras.h rename to src/patches/removals/remove_extras.h diff --git a/src/patches/fixes/fix_labyrinth_camera.cpp b/src/patches/removals/remove_hardcodes.cpp similarity index 51% rename from src/patches/fixes/fix_labyrinth_camera.cpp rename to src/patches/removals/remove_hardcodes.cpp index 0e7447e6..57394ab2 100644 --- a/src/patches/fixes/fix_labyrinth_camera.cpp +++ b/src/patches/removals/remove_hardcodes.cpp @@ -1,20 +1,35 @@ -#include "fix_labyrinth_camera.h" +#include "remove_hardcodes.h" #include "internal/patch.h" #include "internal/tickable.h" #include "utils/ppcutil.h" -namespace fix_labyrinth_camera { +namespace remove_hardcodes { TICKABLE_DEFINITION(( - .name = "fix-labyrinth-camera", - .description = "Labyrinth stage slot fix", - .init_main_loop = init_main_loop, )) + .name = "remove-stage-slot-hardcodes", + .description = "Remove stage slot hardcodes", + .init_main_loop = init_main_loop, + .init_main_game = init_main_game, )) -// Always compare the stage ID to 0xFFFF when these camera functions check -// if the current stage ID is 0x15a when determining specific constants. -// 0x2c00ffff = cmpwi r0. 0xFFFF void init_main_loop() { + // Nop a call to handle hardcoded stage object drawing for + // SMB2 stages + patch::write_nop(reinterpret_cast(0x802c96d8)); + // Nop a call to handle hardcoded stage lights leftover from + // SMB1 + patch::write_nop(reinterpret_cast(0x802945d8)); + // In the function which handles Bonus Wave's collision, nop + // the part which decides what space has hardcoded collision + patch::write_nop(reinterpret_cast(0x802c79b4)); + // In an array for hardcoded camera settings, check for stage ID + // 0xffffffff instead of any used stage slots + patch::write_word(reinterpret_cast(0x8044b208), 0xffffffff); + patch::write_word(reinterpret_cast(0x8044b1e0), 0xffffffff); + patch::write_word(reinterpret_cast(0x8044b1f4), 0xffffffff); + // Always compare the stage ID to 0xFFFF when these camera functions check + // if the current stage ID is 0x15a when determining specific constants. + // 0x2c00ffff = cmpwi r0. 0xFFFF patch::write_word(reinterpret_cast(0x802858D4), 0x2c00ffff); patch::write_word(reinterpret_cast(0x802874BC), 0x2c00ffff); patch::write_word(reinterpret_cast(0x8028751C), 0x2c00ffff); @@ -36,4 +51,10 @@ void init_main_loop() { patch::write_word(reinterpret_cast(0x80291AEC), 0x2c00ffff); } -}// namespace fix_labyrinth_camera +void init_main_game() { + // Nop a call to handle hardcoded stage object drawing for + // SMB2 stages + patch::write_nop(reinterpret_cast(0x809140f4)); +} + +}// namespace remove_hardcodes diff --git a/src/patches/tweaks/remove_hardcodes.h b/src/patches/removals/remove_hardcodes.h similarity index 100% rename from src/patches/tweaks/remove_hardcodes.h rename to src/patches/removals/remove_hardcodes.h diff --git a/src/patches/tweaks/no_hurry_up_music.cpp b/src/patches/removals/remove_hurry_up_music.cpp similarity index 83% rename from src/patches/tweaks/no_hurry_up_music.cpp rename to src/patches/removals/remove_hurry_up_music.cpp index 29aff607..45828be4 100644 --- a/src/patches/tweaks/no_hurry_up_music.cpp +++ b/src/patches/removals/remove_hurry_up_music.cpp @@ -1,13 +1,13 @@ -#include "no_hurry_up_music.h" +#include "remove_hurry_up_music.h" #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" -namespace no_hurry_up_music { +namespace remove_hurry_up_music { TICKABLE_DEFINITION(( - .name = "no-hurry-up-music", + .name = "remove-hurry-up-music", .description = "Hurry up music removal", .init_main_game = init_main_game, .tick = tick, )) @@ -25,4 +25,4 @@ void tick() { mkb::g_SoftStreamStart_with_some_defaults_2(0x2c); } } -}// namespace no_hurry_up_music +}// namespace remove_hurry_up_music diff --git a/src/patches/removals/remove_hurry_up_music.h b/src/patches/removals/remove_hurry_up_music.h new file mode 100644 index 00000000..8dcdd910 --- /dev/null +++ b/src/patches/removals/remove_hurry_up_music.h @@ -0,0 +1,8 @@ +#pragma once + +namespace remove_hurry_up_music { + +void init_main_game(); +void tick(); + +}// namespace remove_hurry_up_music \ No newline at end of file diff --git a/src/patches/tweaks/skip_intro_movie.cpp b/src/patches/removals/remove_intro_cutscene.cpp similarity index 71% rename from src/patches/tweaks/skip_intro_movie.cpp rename to src/patches/removals/remove_intro_cutscene.cpp index c49e98d8..8afe25d2 100644 --- a/src/patches/tweaks/skip_intro_movie.cpp +++ b/src/patches/removals/remove_intro_cutscene.cpp @@ -1,14 +1,14 @@ -#include "skip_intro_movie.h" +#include "remove_intro_cutscene.h" #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" -namespace skip_intro_movie { +namespace remove_intro_cutscene { TICKABLE_DEFINITION(( - .name = "skip-intro-movie", - .description = "Skip intro movie patch", + .name = "remove-intro-cutscene", + .description = "Intro cutscene removal", .init_main_loop = init_main_loop, )) // Immediately goes to the title screen @@ -22,4 +22,4 @@ void init_main_loop() { } -}// namespace skip_intro_movie +}// namespace remove_intro_cutscene diff --git a/src/patches/removals/remove_intro_cutscene.h b/src/patches/removals/remove_intro_cutscene.h new file mode 100644 index 00000000..9a48c78f --- /dev/null +++ b/src/patches/removals/remove_intro_cutscene.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_intro_cutscene { + +void init_main_loop(); + +}// namespace remove_intro_cutscene \ No newline at end of file diff --git a/src/patches/tweaks/remove_playpoints.cpp b/src/patches/removals/remove_playpoints.cpp similarity index 100% rename from src/patches/tweaks/remove_playpoints.cpp rename to src/patches/removals/remove_playpoints.cpp diff --git a/src/patches/tweaks/remove_playpoints.h b/src/patches/removals/remove_playpoints.h similarity index 100% rename from src/patches/tweaks/remove_playpoints.h rename to src/patches/removals/remove_playpoints.h diff --git a/src/patches/tweaks/skip_cutscenes.cpp b/src/patches/removals/remove_story_cutscenes.cpp similarity index 96% rename from src/patches/tweaks/skip_cutscenes.cpp rename to src/patches/removals/remove_story_cutscenes.cpp index 07e05451..2f32dc1c 100644 --- a/src/patches/tweaks/skip_cutscenes.cpp +++ b/src/patches/removals/remove_story_cutscenes.cpp @@ -1,4 +1,4 @@ -#include "skip_cutscenes.h" +#include "remove_story_cutscenes.h" #include "internal/patch.h" #include "internal/tickable.h" @@ -6,13 +6,13 @@ #include "utils/ppcutil.h" -namespace skip_cutscenes { +namespace remove_story_cutscenes { static u16 DEFAULT_CUTSCENE_SKIP_SETTING = 0; TICKABLE_DEFINITION(( - .name = "skip-cutscenes", - .description = "Cutscene skip patch", + .name = "remove-story-cutscenes", + .description = "Story Mode cutscene removal", .active_value = DEFAULT_CUTSCENE_SKIP_SETTING, .lower_bound = 0, .upper_bound = 3, @@ -159,4 +159,4 @@ void init_main_game() { } } -}// namespace skip_cutscenes +}// namespace remove_story_cutscenes diff --git a/src/patches/removals/remove_story_cutscenes.h b/src/patches/removals/remove_story_cutscenes.h new file mode 100644 index 00000000..499f19d4 --- /dev/null +++ b/src/patches/removals/remove_story_cutscenes.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_story_cutscenes { + +void init_main_game(); + +}// namespace remove_story_cutscenes \ No newline at end of file diff --git a/src/patches/tweaks/disable_tutorial.cpp b/src/patches/removals/remove_tutorial.cpp similarity index 75% rename from src/patches/tweaks/disable_tutorial.cpp rename to src/patches/removals/remove_tutorial.cpp index 786f6583..6532ed92 100644 --- a/src/patches/tweaks/disable_tutorial.cpp +++ b/src/patches/removals/remove_tutorial.cpp @@ -1,13 +1,13 @@ -#include "disable_tutorial.h" +#include "remove_tutorial.h" #include "internal/patch.h" #include "internal/tickable.h" #include "utils/ppcutil.h" -namespace disable_tutorial { +namespace remove_tutorial { TICKABLE_DEFINITION(( - .name = "disable-how-to-play-screen", + .name = "remove-tutorial", .description = "Tutorial sequence removal", .init_main_loop = init_main_loop, )) @@ -17,4 +17,4 @@ void init_main_loop() { patch::write_nop(reinterpret_cast(0x8027bbb0)); } -}// namespace disable_tutorial +}// namespace remove_tutorial diff --git a/src/patches/removals/remove_tutorial.h b/src/patches/removals/remove_tutorial.h new file mode 100644 index 00000000..20572839 --- /dev/null +++ b/src/patches/removals/remove_tutorial.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_tutorial { + +void init_main_loop(); + +}// namespace remove_tutorial \ No newline at end of file diff --git a/src/patches/tweaks/pause_volume_fix.cpp b/src/patches/removals/remove_volume_decrease_on_pause.cpp similarity index 64% rename from src/patches/tweaks/pause_volume_fix.cpp rename to src/patches/removals/remove_volume_decrease_on_pause.cpp index 657007b5..a29bc7fa 100644 --- a/src/patches/tweaks/pause_volume_fix.cpp +++ b/src/patches/removals/remove_volume_decrease_on_pause.cpp @@ -1,12 +1,12 @@ -#include "pause_volume_fix.h" +#include "remove_volume_decrease_on_pause.h" #include "internal/patch.h" #include "internal/tickable.h" -namespace pause_volume_fix { +namespace remove_volume_decrease_on_pause { TICKABLE_DEFINITION(( - .name = "no-music-vol-decrease-on-pause", + .name = "remove-volume-decrease-on-pause", .description = "No music volume decrease on pause", .init_main_loop = init_main_loop, )) @@ -15,4 +15,4 @@ void init_main_loop() { patch::write_nop(reinterpret_cast(0x802a32a8)); } -}// namespace pause_volume_fix +}// namespace remove_volume_decrease_on_pause diff --git a/src/patches/removals/remove_volume_decrease_on_pause.h b/src/patches/removals/remove_volume_decrease_on_pause.h new file mode 100644 index 00000000..49d217aa --- /dev/null +++ b/src/patches/removals/remove_volume_decrease_on_pause.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_volume_decrease_on_pause { + +void init_main_loop(); + +}// namespace remove_volume_decrease_on_pause \ No newline at end of file diff --git a/src/patches/tweaks/disable_tutorial.h b/src/patches/tweaks/disable_tutorial.h deleted file mode 100644 index 488fb3c8..00000000 --- a/src/patches/tweaks/disable_tutorial.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace disable_tutorial { - -void init_main_loop(); - -}// namespace disable_tutorial \ No newline at end of file diff --git a/src/patches/tweaks/no_hurry_up_music.h b/src/patches/tweaks/no_hurry_up_music.h deleted file mode 100644 index 972ad5cd..00000000 --- a/src/patches/tweaks/no_hurry_up_music.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace no_hurry_up_music { - -void init_main_game(); -void tick(); - -}// namespace no_hurry_up_music \ No newline at end of file diff --git a/src/patches/tweaks/pause_volume_fix.h b/src/patches/tweaks/pause_volume_fix.h deleted file mode 100644 index 9dc7546d..00000000 --- a/src/patches/tweaks/pause_volume_fix.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace pause_volume_fix { - -void init_main_loop(); - -}// namespace pause_volume_fix \ No newline at end of file diff --git a/src/patches/tweaks/remove_hardcodes.cpp b/src/patches/tweaks/remove_hardcodes.cpp deleted file mode 100644 index 8cce3e5d..00000000 --- a/src/patches/tweaks/remove_hardcodes.cpp +++ /dev/null @@ -1,38 +0,0 @@ -#include "remove_hardcodes.h" - -#include "internal/patch.h" -#include "internal/tickable.h" -#include "utils/ppcutil.h" - -namespace remove_hardcodes { - -TICKABLE_DEFINITION(( - .name = "remove-stage-slot-hardcodes", - .description = "Remove stage slot hardcodes", - .init_main_loop = init_main_loop, - .init_main_game = init_main_game, )) - -void init_main_loop() { - // Nop a call to handle hardcoded stage object drawing for - // SMB2 stages - patch::write_nop(reinterpret_cast(0x802c96d8)); - // Nop a call to handle hardcoded stage lights leftover from - // SMB1 - patch::write_nop(reinterpret_cast(0x802945d8)); - // In the function which handles Bonus Wave's collision, nop - // the part which decides what space has hardcoded collision - patch::write_nop(reinterpret_cast(0x802c79b4)); - // In an array for hardcoded camera settings, check for stage ID - // 0xffffffff instead of any used stage slots - patch::write_word(reinterpret_cast(0x8044b208), 0xffffffff); - patch::write_word(reinterpret_cast(0x8044b1e0), 0xffffffff); - patch::write_word(reinterpret_cast(0x8044b1f4), 0xffffffff); -} - -void init_main_game() { - // Nop a call to handle hardcoded stage object drawing for - // SMB2 stages - patch::write_nop(reinterpret_cast(0x809140f4)); -} - -}// namespace remove_hardcodes diff --git a/src/patches/tweaks/skip_cutscenes.h b/src/patches/tweaks/skip_cutscenes.h deleted file mode 100644 index ff00478e..00000000 --- a/src/patches/tweaks/skip_cutscenes.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace skip_cutscenes { - -void init_main_game(); - -}// namespace skip_cutscenes \ No newline at end of file diff --git a/src/patches/tweaks/skip_intro_movie.h b/src/patches/tweaks/skip_intro_movie.h deleted file mode 100644 index 88fb49d5..00000000 --- a/src/patches/tweaks/skip_intro_movie.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace skip_intro_movie { - -void init_main_loop(); - -}// namespace skip_intro_movie \ No newline at end of file From 7880c73bb5ee7dd3c7c2834715ae5a59c4af8d3e Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 15:47:44 -0800 Subject: [PATCH 22/96] Separate Story and Challenge cutscene removal --- .../removals/remove_challenge_cutscenes.cpp | 21 +++++++++++++++ .../removals/remove_challenge_cutscenes.h | 7 +++++ .../removals/remove_story_cutscenes.cpp | 27 ------------------- 3 files changed, 28 insertions(+), 27 deletions(-) create mode 100644 src/patches/removals/remove_challenge_cutscenes.cpp create mode 100644 src/patches/removals/remove_challenge_cutscenes.h diff --git a/src/patches/removals/remove_challenge_cutscenes.cpp b/src/patches/removals/remove_challenge_cutscenes.cpp new file mode 100644 index 00000000..e253e4a0 --- /dev/null +++ b/src/patches/removals/remove_challenge_cutscenes.cpp @@ -0,0 +1,21 @@ +#include "remove_challenge_cutscenes.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" +#include "utils/ppcutil.h" + + +namespace remove_challenge_cutscenes { + +TICKABLE_DEFINITION(( + .name = "remove-challenge-cutscenes", + .description = "Challenge Mode cutscene removal", + .init_main_game = init_main_game, )) + +void init_main_game() { + patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); + patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); +} + +}// namespace remove_challenge_cutscenes diff --git a/src/patches/removals/remove_challenge_cutscenes.h b/src/patches/removals/remove_challenge_cutscenes.h new file mode 100644 index 00000000..4ceae198 --- /dev/null +++ b/src/patches/removals/remove_challenge_cutscenes.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_challenge_cutscenes { + +void init_main_game(); + +}// namespace remove_challenge_cutscenes \ No newline at end of file diff --git a/src/patches/removals/remove_story_cutscenes.cpp b/src/patches/removals/remove_story_cutscenes.cpp index 2f32dc1c..6828862f 100644 --- a/src/patches/removals/remove_story_cutscenes.cpp +++ b/src/patches/removals/remove_story_cutscenes.cpp @@ -13,9 +13,6 @@ static u16 DEFAULT_CUTSCENE_SKIP_SETTING = 0; TICKABLE_DEFINITION(( .name = "remove-story-cutscenes", .description = "Story Mode cutscene removal", - .active_value = DEFAULT_CUTSCENE_SKIP_SETTING, - .lower_bound = 0, - .upper_bound = 3, .init_main_game = init_main_game, )) constexpr auto WORLD_COUNT = 10;// TODO: attach to patch that changes this @@ -125,8 +122,6 @@ void handle_preloading() { } void init_main_game() { - // 1 skips Story cutscenes only, 2 skips Challenge cutscenes only, 3 skips both - if (active_tickable_ptr->active_value == 1) { patch::write_branch(reinterpret_cast(mkb::dmd_scen_newgame_main), reinterpret_cast(dmd_scen_newgame_main_patch)); patch::write_branch(reinterpret_cast(mkb::dmd_scen_sceneplay_init), @@ -135,28 +130,6 @@ void init_main_game() { reinterpret_cast(dmd_scen_sel_floor_init_patch)); patch::write_branch(reinterpret_cast(mkb::g_preload_next_stage_files), reinterpret_cast(handle_preloading)); - } - else if (active_tickable_ptr->active_value == 2) { - // In the function which handles what to do when you goal, start the credits - // sequence instead of the ending cutscene in Challenge Mode - patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); - patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); - } - else if (active_tickable_ptr->active_value == 3) { - patch::write_branch(reinterpret_cast(mkb::dmd_scen_newgame_main), - reinterpret_cast(dmd_scen_newgame_main_patch)); - patch::write_branch(reinterpret_cast(mkb::dmd_scen_sceneplay_init), - reinterpret_cast(dmd_scen_sceneplay_init_patch)); - patch::write_branch(reinterpret_cast(mkb::dmd_scen_sel_floor_init), - reinterpret_cast(dmd_scen_sel_floor_init_patch)); - patch::write_branch(reinterpret_cast(mkb::g_preload_next_stage_files), - reinterpret_cast(handle_preloading)); - patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); - patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); - } - else { - return; - } } }// namespace remove_story_cutscenes From ff81055ddee3c39ce6465f9d0d1e0b686ddf0c63 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Mon, 13 Jan 2025 17:27:42 -0800 Subject: [PATCH 23/96] Merge wormhole surface fix with remove hardcodes --- src/patches/fixes/fix_wormhole_surfaces.cpp | 20 -------------------- src/patches/fixes/fix_wormhole_surfaces.h | 7 ------- src/patches/removals/remove_hardcodes.cpp | 5 +++++ 3 files changed, 5 insertions(+), 27 deletions(-) delete mode 100644 src/patches/fixes/fix_wormhole_surfaces.cpp delete mode 100644 src/patches/fixes/fix_wormhole_surfaces.h diff --git a/src/patches/fixes/fix_wormhole_surfaces.cpp b/src/patches/fixes/fix_wormhole_surfaces.cpp deleted file mode 100644 index bf7d45fb..00000000 --- a/src/patches/fixes/fix_wormhole_surfaces.cpp +++ /dev/null @@ -1,20 +0,0 @@ -#include "fix_wormhole_surfaces.h" - -#include "internal/patch.h" -#include "internal/tickable.h" -#include "utils/ppcutil.h" - -namespace fix_wormhole_surfaces { - -TICKABLE_DEFINITION(( - .name = "fix-wormhole-surfaces", - .description = "Party game stage slot fix", - .init_main_loop = init_main_loop, )) - -// Always return 'true' for a specific function that checks if the stage ID -// belongs to a slot normally used for party games. -void init_main_loop() { - patch::write_word(reinterpret_cast(0x802c8ce4), PPC_INSTR_LI(PPC_R0, 0x1)); -} - -}// namespace fix_wormhole_surfaces diff --git a/src/patches/fixes/fix_wormhole_surfaces.h b/src/patches/fixes/fix_wormhole_surfaces.h deleted file mode 100644 index a5c9971a..00000000 --- a/src/patches/fixes/fix_wormhole_surfaces.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -namespace fix_wormhole_surfaces { - -void init_main_loop(); - -}// namespace fix_wormhole_surfaces \ No newline at end of file diff --git a/src/patches/removals/remove_hardcodes.cpp b/src/patches/removals/remove_hardcodes.cpp index 57394ab2..1cf8c280 100644 --- a/src/patches/removals/remove_hardcodes.cpp +++ b/src/patches/removals/remove_hardcodes.cpp @@ -27,6 +27,7 @@ void init_main_loop() { patch::write_word(reinterpret_cast(0x8044b208), 0xffffffff); patch::write_word(reinterpret_cast(0x8044b1e0), 0xffffffff); patch::write_word(reinterpret_cast(0x8044b1f4), 0xffffffff); + // Labyrinth camera removal // Always compare the stage ID to 0xFFFF when these camera functions check // if the current stage ID is 0x15a when determining specific constants. // 0x2c00ffff = cmpwi r0. 0xFFFF @@ -49,6 +50,10 @@ void init_main_loop() { patch::write_word(reinterpret_cast(0x80291960), 0x2c00ffff); patch::write_word(reinterpret_cast(0x8029198C), 0x2c00ffff); patch::write_word(reinterpret_cast(0x80291AEC), 0x2c00ffff); + // Wormhole surface fix + // Always return 'true' for a specific function that checks if the stage ID + // belongs to a slot normally used for party games. + patch::write_word(reinterpret_cast(0x802c8ce4), PPC_INSTR_LI(PPC_R0, 0x1)); } void init_main_game() { From a0b2aaff7cde2f1e154fd64fe02cfc591c1c22f9 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Tue, 14 Jan 2025 15:27:33 -0800 Subject: [PATCH 24/96] Add final stage fix patch --- src/mkb/mkb2.us.lst | 1 + src/mkb/mkb2_ghidra.h | 1 + src/patches/fixes/fix_final_stage.cpp | 155 ++++++++++++++++++++++++++ src/patches/fixes/fix_final_stage.h | 9 ++ src/patches/tweaks/perfect_bonus.cpp | 2 +- 5 files changed, 167 insertions(+), 1 deletion(-) create mode 100644 src/patches/fixes/fix_final_stage.cpp create mode 100644 src/patches/fixes/fix_final_stage.h diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 3fcbbaf5..e953afa5 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -8338,6 +8338,7 @@ 80494208:HUD_TEXT_WORLD_STAGE_NO 80494210:HUD_TEXT_STAGE_NO 80494214:HUD_TEXT_STAGE_NAME +80494288:SPRITE_TEXT_FINAL_STAGE 8049440C:sprite_banana_count_fmt_string 80494444:g_minimap_mode 8049445C:minimap_zoom_level diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index 212c451a..b51a3cec 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5902,6 +5902,7 @@ extern "C" { extern char HUD_TEXT_WORLD_STAGE_NO[6]; extern char HUD_TEXT_STAGE_NO[3]; extern char HUD_TEXT_STAGE_NAME[3]; + extern char SPRITE_TEXT_FINAL_STAGE[12]; extern char sprite_banana_count_fmt_string[5]; extern MinimapMode g_minimap_mode; extern undefined4 minimap_zoom_level; diff --git a/src/patches/fixes/fix_final_stage.cpp b/src/patches/fixes/fix_final_stage.cpp new file mode 100644 index 00000000..ef624473 --- /dev/null +++ b/src/patches/fixes/fix_final_stage.cpp @@ -0,0 +1,155 @@ +#include "fix_final_stage.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace fix_final_stage { + +TICKABLE_DEFINITION(( + .name = "fix-final-stage", + .description = "Final stage fixes", + .init_main_loop = init_main_loop, + .init_main_game = init_main_game, + .tick = tick )) + + +void tick() { + // Fix FINAL STAGE sprite appearing if Story Mode is played following a one-stage difficulty + if (mkb::main_game_mode == mkb::STORY_MODE) { + mkb::strcpy(mkb::LOADIN_TEXT_FINAL_STAGE, ""); + mkb::strcpy(mkb::SPRITE_TEXT_FINAL_STAGE, ""); + } + else { + mkb::strcpy(mkb::LOADIN_TEXT_FINAL_STAGE, "FINAL STAGE"); + mkb::strcpy(mkb::SPRITE_TEXT_FINAL_STAGE, "FINAL STAGE"); + } + // Stuff for if a FINAL and BONUS stage overlap + if (((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE))) { + // Fade the FINAL STAGE sprite ourselves when a replay starts + if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_INIT) { + mkb::Sprite *sprite; + sprite = mkb::get_sprite_with_unique_id(0xf); + if (sprite != (mkb::Sprite *)0x0) { + sprite->para1 = 0xf; + } + } + // Initiate PERFECT if the perfect bonus patch is enabled + if (tickable::get_tickable_manager().get_tickable_status("perfect-bonus-completion")) { + if (mkb::mode_info.bananas_remaining == 0) { + if ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_FINAL_STAGE)) { + if (mkb::sub_mode == mkb::SMD_GAME_PLAY_MAIN) { + mkb::mode_info.ball_mode |= mkb::BALLMODE_CLEARED_BONUS_PERFECT; + } + else { + mkb::mode_info.ball_mode &= ~mkb::BALLMODE_CLEARED_BONUS_PERFECT; + } + } + } + } + } +} +void fix_final_stage_sprite_position() { + if ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE)) { + // Repoint sprite positions if we're on a FINAL and BONUS stage + // Any values written here overwrite unused portions in memory + patch::write_word(reinterpret_cast(0x8032bf10), 0xc01f012c); + patch::write_word(reinterpret_cast(0x803e7abc), 0x43a50000); + patch::write_word(reinterpret_cast(0x8032d1e4), 0xc01f0244); + patch::write_word(reinterpret_cast(0x803e7bd4), 0x43eb0000); + patch::write_word(reinterpret_cast(0x8032d268), 0xc87f00b8); + patch::write_word(reinterpret_cast(0x803e7a48), 0x4073e000); + patch::write_word(reinterpret_cast(0x803e7a4c), 0x00000000); + // By default, the function to fade the FINAL or BONUS stage sprite + // only fades one at a time, so overwrite the special ID of the FINAL + // stage one to something else so we can fade it ourselves + // This special ID is used by a different sprite at other times, so we have to + // reset it later + patch::write_word(reinterpret_cast(0x8032bf00), 0x3800000f); + } + else { + // Undo repoints + patch::write_word(reinterpret_cast(0x8032bf10), 0xc01f00f0); + patch::write_word(reinterpret_cast(0x8032d1e4), 0xc01f023c); + patch::write_word(reinterpret_cast(0x8032d268), 0xc87f0248); + // Reset special ID + patch::write_word(reinterpret_cast(0x8032bf00), 0x3800000e); + } +} +void handle_final_bonus() { + // If the final stage is a bonus and we get a Bonus Finish or Time Over, do end of difficulty or extra stuff + if (((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE)) + && (mkb::in_practice_mode == false)) { + bool start_extras = false; + if (((mkb::mode_flags & mkb::MF_0x1) != mkb::MF_NONE) && (mkb::mode_info.field13_0x2a == 0)) { + start_extras = true; + } + if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_EXTRA_COURSE) != mkb::MF_NONE)) && + (mkb::curr_difficulty != mkb::DIFF_EXPERT)) { + start_extras = false; + } + if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_NOEX_COURSE) != mkb::MF_NONE)) && + (mkb::curr_difficulty != mkb::DIFF_EXPERT)) { + start_extras = false; + } + if ((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_EX_COURSE) != mkb::MF_NONE)) { + start_extras = false; + } + if (mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) { + if (mkb::mode_info.ball_mode & mkb::BALLMODE_OUT_OF_TIME_RINGOUT | mkb::BALLMODE_FALLEN_OUT | mkb::BALLMODE_CLEARED_BONUS_PERFECT) { + if (!start_extras || tickable::get_tickable_manager().get_tickable_status("remove-extras")) { + if (mkb::sub_mode_frame_counter == 0x3c) { + mkb::fade_screen_to_color(0x101, 0, 0x3d); + mkb::g_fade_track_volume(0x3c, '\x02'); + } + if (mkb::sub_mode_frame_counter < 1) { + mkb::g_smth_with_ending_course(); + mkb::g_smth_with_ending_course_2(); + mkb::g_change_music_volume(0xc, 0x3c, '\0'); + mkb::main_mode_request = mkb::MD_AUTHOR; + mkb::sub_mode_request = mkb::SMD_AUTHOR_PLAY_ENDING_INIT; + mkb::mode_flags = mkb::mode_flags | 0x100040; + } + } + else { + if (mkb::sub_mode_frame_counter == 0x3c) { + mkb::fade_screen_to_color(0x101, 0, 0x3d); + mkb::g_fade_track_volume(0x3c, '\x02'); + } + if (mkb::sub_mode_frame_counter < 1) { + mkb::sub_mode_request = mkb::SMD_GAME_EXTRA_INIT; + } + } + } + } + } +} + +static patch::Tramp s_smd_game_ringout_tick_tramp; +static patch::Tramp s_smd_game_timeover_tick_tramp; +static patch::Tramp s_smd_game_bonus_clear_tick_tramp; +static patch::Tramp s_create_stage_loadin_text_sprites_tramp; + +void init_main_loop() { + patch::hook_function(s_create_stage_loadin_text_sprites_tramp, mkb::create_stage_loadin_text_sprites, []() { + fix_final_stage_sprite_position(); + s_create_stage_loadin_text_sprites_tramp.dest(); + }); +} + +void init_main_game() { + patch::hook_function(s_smd_game_ringout_tick_tramp, mkb::smd_game_ringout_tick, []() { + s_smd_game_ringout_tick_tramp.dest(); + handle_final_bonus(); + }); + patch::hook_function(s_smd_game_timeover_tick_tramp, mkb::smd_game_timeover_tick, []() { + s_smd_game_timeover_tick_tramp.dest(); + handle_final_bonus(); + }); + patch::hook_function(s_smd_game_bonus_clear_tick_tramp, mkb::smd_game_bonus_clear_tick, []() { + s_smd_game_bonus_clear_tick_tramp.dest(); + handle_final_bonus(); + }); +} + +}// namespace fix_final_stage diff --git a/src/patches/fixes/fix_final_stage.h b/src/patches/fixes/fix_final_stage.h new file mode 100644 index 00000000..f0c1080c --- /dev/null +++ b/src/patches/fixes/fix_final_stage.h @@ -0,0 +1,9 @@ +#pragma once + +namespace fix_final_stage { + +void init_main_loop(); +void init_main_game(); +void tick(); + +}// namespace fix_final_stage diff --git a/src/patches/tweaks/perfect_bonus.cpp b/src/patches/tweaks/perfect_bonus.cpp index 7aefac15..32d31211 100644 --- a/src/patches/tweaks/perfect_bonus.cpp +++ b/src/patches/tweaks/perfect_bonus.cpp @@ -28,4 +28,4 @@ void init_main_loop() { }); } -}// namespace perfect_bonus +}// namespace perfect_bonus \ No newline at end of file From c6c9b6cfd64a335b8fad0cb50b3ecc696d49e7ce Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Tue, 14 Jan 2025 15:38:14 -0800 Subject: [PATCH 25/96] Add patch to remove ball rolling sound --- .../removals/remove_ball_rolling_sound.cpp | 18 ++++++++++++++++++ .../removals/remove_ball_rolling_sound.h | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 src/patches/removals/remove_ball_rolling_sound.cpp create mode 100644 src/patches/removals/remove_ball_rolling_sound.h diff --git a/src/patches/removals/remove_ball_rolling_sound.cpp b/src/patches/removals/remove_ball_rolling_sound.cpp new file mode 100644 index 00000000..678eae78 --- /dev/null +++ b/src/patches/removals/remove_ball_rolling_sound.cpp @@ -0,0 +1,18 @@ +#include "remove_ball_rolling_sound.h" + +#include "internal/patch.h" +#include "internal/tickable.h" + +namespace remove_ball_rolling_sound { + +TICKABLE_DEFINITION(( + .name = "remove-ball-rolling-sound", + .description = "Ball rolling sound removal", + .init_main_loop = init_main_loop, )) + +// Nops a call to the function which plays ball rolling sounds +void init_main_loop() { + patch::write_nop(reinterpret_cast(0x802bca7c)); +} + +}// namespace remove_ball_rolling_sound diff --git a/src/patches/removals/remove_ball_rolling_sound.h b/src/patches/removals/remove_ball_rolling_sound.h new file mode 100644 index 00000000..201d1c71 --- /dev/null +++ b/src/patches/removals/remove_ball_rolling_sound.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_ball_rolling_sound { + +void init_main_loop(); + +}// namespace remove_ball_rolling_sound \ No newline at end of file From 2d6c39521ddadc12ee6186a57e755f284b2173d3 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Tue, 14 Jan 2025 16:37:21 -0800 Subject: [PATCH 26/96] Add patch to fix bonus stage sprite --- src/patches/fixes/fix_bonus_sprite.cpp | 50 ++++++++++++++++++++++++++ src/patches/fixes/fix_bonus_sprite.h | 7 ++++ 2 files changed, 57 insertions(+) create mode 100644 src/patches/fixes/fix_bonus_sprite.cpp create mode 100644 src/patches/fixes/fix_bonus_sprite.h diff --git a/src/patches/fixes/fix_bonus_sprite.cpp b/src/patches/fixes/fix_bonus_sprite.cpp new file mode 100644 index 00000000..f68384a5 --- /dev/null +++ b/src/patches/fixes/fix_bonus_sprite.cpp @@ -0,0 +1,50 @@ +#include "fix_bonus_sprite.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace fix_bonus_sprite { + +TICKABLE_DEFINITION(( + .name = "fix-bonus-stage-sprite", + .description = "Bonus stage sprite fix", + .init_main_loop = init_main_loop, )) + +static patch::Tramp s_create_hud_sprites_tramp; + +void create_bonus_sprite(void) { + // Check if we're on a bonus stage and if the sprite already exists + mkb::Sprite *special_stage_text_sprite = mkb::get_sprite_with_unique_id(mkb::SPRITE_SPECIAL_STAGE); + if ((special_stage_text_sprite == (mkb::Sprite *)0x0) && + ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE) != mkb::BALLMODE_NONE)) { + // Create the sprite + mkb::Sprite *sprite; + sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->unique_id = mkb::SPRITE_SPECIAL_STAGE; + (sprite->pos).x = 500.0; + (sprite->pos).y = 452.0; + (sprite->mult_color).red = 0xff; + (sprite->mult_color).green = 0x80; + (sprite->mult_color).blue = '\0'; + sprite->font = mkb::FONT_ASC_72x64; + sprite->alignment = mkb::ALIGN_CENTER; + sprite->width = 0.3; + sprite->height = 0.3; + sprite->g_flags1 = sprite->g_flags1 | 0x1001000; + sprite->widescreen_translation_x = 0x27f; + mkb::strcpy(sprite->text, "BONUS STAGE"); + } + } +} + +void init_main_loop() { + // Hook the function which creates HUD sprites and call our new sprite create function + patch::hook_function(s_create_hud_sprites_tramp, mkb::create_hud_sprites, []() { + create_bonus_sprite(); + s_create_hud_sprites_tramp.dest(); + }); +} + +}// namespace fix_bonus_sprite diff --git a/src/patches/fixes/fix_bonus_sprite.h b/src/patches/fixes/fix_bonus_sprite.h new file mode 100644 index 00000000..99a6deb7 --- /dev/null +++ b/src/patches/fixes/fix_bonus_sprite.h @@ -0,0 +1,7 @@ +#pragma once + +namespace fix_bonus_sprite { + +void init_main_loop(); + +}// namespace fix_bonus_sprite \ No newline at end of file From 64b434040a06b5999ba31910c559ee586c065259 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Tue, 14 Jan 2025 23:09:25 -0800 Subject: [PATCH 27/96] Fix bonus sprite not fading --- src/patches/fixes/fix_bonus_sprite.cpp | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/patches/fixes/fix_bonus_sprite.cpp b/src/patches/fixes/fix_bonus_sprite.cpp index f68384a5..f7385484 100644 --- a/src/patches/fixes/fix_bonus_sprite.cpp +++ b/src/patches/fixes/fix_bonus_sprite.cpp @@ -13,6 +13,15 @@ TICKABLE_DEFINITION(( static patch::Tramp s_create_hud_sprites_tramp; +void new_bonus_sprite_tick(u8 *status, mkb::Sprite *sprite) { + if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN) { + sprite->alpha -= 0.07; + } + if (sprite->alpha < 0) { + sprite-> alpha = 0; + } +} + void create_bonus_sprite(void) { // Check if we're on a bonus stage and if the sprite already exists mkb::Sprite *special_stage_text_sprite = mkb::get_sprite_with_unique_id(mkb::SPRITE_SPECIAL_STAGE); @@ -34,6 +43,7 @@ void create_bonus_sprite(void) { sprite->height = 0.3; sprite->g_flags1 = sprite->g_flags1 | 0x1001000; sprite->widescreen_translation_x = 0x27f; + sprite->tick_func = new_bonus_sprite_tick; mkb::strcpy(sprite->text, "BONUS STAGE"); } } @@ -42,8 +52,8 @@ void create_bonus_sprite(void) { void init_main_loop() { // Hook the function which creates HUD sprites and call our new sprite create function patch::hook_function(s_create_hud_sprites_tramp, mkb::create_hud_sprites, []() { - create_bonus_sprite(); s_create_hud_sprites_tramp.dest(); + create_bonus_sprite(); }); } From 22b245f2d38cba2d7f3dc749c2e05a4aa4e1b5dc Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 15 Jan 2025 12:22:17 -0800 Subject: [PATCH 28/96] Run clang-dormat --- src/patches/extensions/challenge_retry.cpp | 160 +++++++++--------- src/patches/extensions/death_counter.cpp | 2 +- .../extensions/stage_name_subtitles.cpp | 2 +- src/patches/fixes/fix_bonus_sprite.cpp | 48 +++--- src/patches/fixes/fix_final_stage.cpp | 133 ++++++++------- src/patches/fixes/fix_goal_types.cpp | 4 +- src/patches/fixes/fix_monkey_counter.cpp | 6 +- .../fixes/fix_storm_continue_platform.cpp | 15 +- src/patches/fixes/fix_widescreen.cpp | 4 +- .../removals/remove_challenge_cutscenes.cpp | 4 +- 10 files changed, 189 insertions(+), 189 deletions(-) diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index 4bce0291..f9516826 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -1,9 +1,9 @@ #include "challenge_retry.h" #include "../internal/pad.h" +#include "death_counter.h" #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" -#include "death_counter.h" namespace challenge_retry { @@ -20,12 +20,12 @@ void pausemenu_handler() { int ball_index; mkb::Ball* ball; - const int total_size = 30; // Adjust size based on gaps and strings - const int gap_size = 5; // Gap of nullptrs between each string (game expects these to be localized strings) + const int total_size = 30;// Adjust size based on gaps and strings + const int gap_size = 5; // Gap of nullptrs between each string (game expects these to be localized strings) // Array of pointers to strings - static char* menu_options_1[total_size] = { nullptr }; - static char* menu_options_2[total_size] = { nullptr }; + static char* menu_options_1[total_size] = {nullptr}; + static char* menu_options_2[total_size] = {nullptr}; // Strings to be stored in the array char* options_1[] = { @@ -34,107 +34,105 @@ void pausemenu_handler() { "Retry", "View stage", "How to play", - "Exit game" - }; + "Exit game"}; char* options_2[] = { // Menu strings during replay "Continue game", "Retry", "Save replay", "How to play", - "Exit game" - }; + "Exit game"}; // Fill the array with strings and gaps of nullptrs int current_index = 0; for (int i = 0; i < 5; ++i) { menu_options_1[current_index] = options_1[i]; menu_options_2[current_index] = options_2[i]; - current_index += gap_size + 1; // Move index by 1 (string) + gap size + current_index += gap_size + 1;// Move index by 1 (string) + gap size } if (mkb::main_game_mode == mkb::CHALLENGE_MODE) { - if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN || - mkb::sub_mode == mkb::SMD_GAME_GOAL_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_MAIN || - mkb::sub_mode == mkb::SMD_GAME_READY_INIT || mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || - mkb::mode_info.ball_mode == mkb::BALLMODE_ON_BONUS_STAGE || mkb::num_players != 1 || - mkb::balls[0].monkey_count < 2 || (mkb::mode_info.ball_mode & mkb::BALLMODE_GOALED)) { - mkb::pausemenu_entry_counts[1] = 4; - mkb::g_current_pause_menu_entry_count = 4; - mkb::pausemenu_entry_pointers[9] = mkb::goal_pausemenu_entries; - mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; - patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004); // in the instruction which handles pausemenu input, Exit Game when option 4 is selected - } - else if ((mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || mkb::sub_mode == mkb::SMD_GAME_READY_INIT) && mkb::mode_info.attempt_count > 1) { - mkb::pausemenu_entry_counts[1] = 4; - mkb::g_current_pause_menu_entry_count = 4; - mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; - patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004); // in the instruction which handles pausemenu input, Exit Game when option 4 is selected + if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN || + mkb::sub_mode == mkb::SMD_GAME_GOAL_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_MAIN || + mkb::sub_mode == mkb::SMD_GAME_READY_INIT || mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || + mkb::mode_info.ball_mode == mkb::BALLMODE_ON_BONUS_STAGE || mkb::num_players != 1 || + mkb::balls[0].monkey_count < 2 || (mkb::mode_info.ball_mode & mkb::BALLMODE_GOALED)) { + mkb::pausemenu_entry_counts[1] = 4; + mkb::g_current_pause_menu_entry_count = 4; + mkb::pausemenu_entry_pointers[9] = mkb::goal_pausemenu_entries; + mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; + patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004);// in the instruction which handles pausemenu input, Exit Game when option 4 is selected + } + else if ((mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || mkb::sub_mode == mkb::SMD_GAME_READY_INIT) && mkb::mode_info.attempt_count > 1) { + mkb::pausemenu_entry_counts[1] = 4; + mkb::g_current_pause_menu_entry_count = 4; + mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; + patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004);// in the instruction which handles pausemenu input, Exit Game when option 4 is selected + } + else if (mkb::sub_mode == mkb::SMD_GAME_ROLL_INIT || mkb::sub_mode == mkb::SMD_GAME_ROLL_MAIN) { + // The credits minigame uses the same main game mode as Challenge Mode, so we need a special case to set its respective menu + mkb::pausemenu_type = 7; + } + else { + // Okay, things get messy here... + // The vanilla pausemenu function is messy in itself, so the idea is to fakematch each visual selection with its internal selection + // The bitflag check on these has something to do with if we're in a subscreen of the pausemenu + + // View stage + if (mkb::g_current_focused_pause_menu_entry == 2 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_current_focused_pause_menu_entry = 1; + original_pausemenu_selection = 2; } - else if (mkb::sub_mode == mkb::SMD_GAME_ROLL_INIT || mkb::sub_mode == mkb::SMD_GAME_ROLL_MAIN) { - // The credits minigame uses the same main game mode as Challenge Mode, so we need a special case to set its respective menu - mkb::pausemenu_type = 7; + // How to play + else if (mkb::g_current_focused_pause_menu_entry == 3 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_current_focused_pause_menu_entry = 2; + original_pausemenu_selection = 3; } - else { - // Okay, things get messy here... - // The vanilla pausemenu function is messy in itself, so the idea is to fakematch each visual selection with its internal selection - // The bitflag check on these has something to do with if we're in a subscreen of the pausemenu - - // View stage - if (mkb::g_current_focused_pause_menu_entry == 2 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { - mkb::g_current_focused_pause_menu_entry = 1; - original_pausemenu_selection = 2; + // Retry + else if (mkb::g_current_focused_pause_menu_entry == 1 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_current_focused_pause_menu_entry = 5; + // If death count is enabled, increment the death counter + // Otherwise, decrement the life counter + if (tickable::get_tickable_manager().get_tickable_status("challenge-mode-death-count")) { + death_counter::update_death_count(); } - // How to play - else if (mkb::g_current_focused_pause_menu_entry == 3 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { - mkb::g_current_focused_pause_menu_entry = 2; - original_pausemenu_selection = 3; - } - // Retry - else if (mkb::g_current_focused_pause_menu_entry == 1 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { - mkb::g_current_focused_pause_menu_entry = 5; - // If death count is enabled, increment the death counter - // Otherwise, decrement the life counter - if (tickable::get_tickable_manager().get_tickable_status("challenge-mode-death-count")) { - death_counter::update_death_count(); - } - else { - mkb::Ball* ball = mkb::balls; - for (int idx = 0; idx < 4; idx++) { - if (ball->status == mkb::STAT_NORMAL) { - ball->monkey_count--; - } - ball++; - } - } - mkb::mode_info.attempt_count = mkb::mode_info.attempt_count + 1; - ball = mkb::balls; - ball_index = mkb::curr_player_idx; - for (ball_index = 0; ball_index < 8; ball_index = ball_index + 1) { + else { + mkb::Ball* ball = mkb::balls; + for (int idx = 0; idx < 4; idx++) { if (ball->status == mkb::STAT_NORMAL) { - ball->phys_flags = ball->phys_flags; - ball->g_effect_flags = ball->g_effect_flags | 0x80; + ball->monkey_count--; } - ball = ball + 1; + ball++; } - mkb::sub_mode_request = mkb::SMD_GAME_READY_INIT; - mkb::g_fade_track_volume(100, '\n'); } - // Return our original visual selection once we exit a subscreen of the pausemenu - if (mkb::g_some_pausemenu_var != 0xffffffff) { - mkb::g_current_focused_pause_menu_entry = original_pausemenu_selection; + mkb::mode_info.attempt_count = mkb::mode_info.attempt_count + 1; + ball = mkb::balls; + ball_index = mkb::curr_player_idx; + for (ball_index = 0; ball_index < 8; ball_index = ball_index + 1) { + if (ball->status == mkb::STAT_NORMAL) { + ball->phys_flags = ball->phys_flags; + ball->g_effect_flags = ball->g_effect_flags | 0x80; + } + ball = ball + 1; } - // Repoint menu entries to our expanded ones - mkb::pausemenu_entry_pointers[1] = menu_options_1; - mkb::pausemenu_entry_pointers[9] = menu_options_2; - patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000005); // in the instruction which handles pausemenu input, Exit Game when option 5 is selected - // Expand entry count - mkb::pausemenu_entry_counts[1] = 5; - mkb::g_current_pause_menu_entry_count = 5; - // Set the pausemenu type to 'normal' Challenge Mode's - mkb::pausemenu_type = 1; + mkb::sub_mode_request = mkb::SMD_GAME_READY_INIT; + mkb::g_fade_track_volume(100, '\n'); + } + // Return our original visual selection once we exit a subscreen of the pausemenu + if (mkb::g_some_pausemenu_var != 0xffffffff) { + mkb::g_current_focused_pause_menu_entry = original_pausemenu_selection; } + // Repoint menu entries to our expanded ones + mkb::pausemenu_entry_pointers[1] = menu_options_1; + mkb::pausemenu_entry_pointers[9] = menu_options_2; + patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000005);// in the instruction which handles pausemenu input, Exit Game when option 5 is selected + // Expand entry count + mkb::pausemenu_entry_counts[1] = 5; + mkb::g_current_pause_menu_entry_count = 5; + // Set the pausemenu type to 'normal' Challenge Mode's + mkb::pausemenu_type = 1; } + } } void init() { diff --git a/src/patches/extensions/death_counter.cpp b/src/patches/extensions/death_counter.cpp index b34901e4..725a3eab 100644 --- a/src/patches/extensions/death_counter.cpp +++ b/src/patches/extensions/death_counter.cpp @@ -83,7 +83,7 @@ void init_main_game() { // menu, change the check for unlocked monkeys to be less than 4 to less than // 255, effectively never displaying the Gameplay Settings menu void init_sel_ngc() { - patch::write_word(reinterpret_cast(0x808ffb14), 0x2c0300ff); // cmpwi r3, 255 + patch::write_word(reinterpret_cast(0x808ffb14), 0x2c0300ff);// cmpwi r3, 255 } }// namespace death_counter diff --git a/src/patches/extensions/stage_name_subtitles.cpp b/src/patches/extensions/stage_name_subtitles.cpp index c5b74214..c7c01b8c 100644 --- a/src/patches/extensions/stage_name_subtitles.cpp +++ b/src/patches/extensions/stage_name_subtitles.cpp @@ -96,7 +96,7 @@ void init_main_loop() { subtitle_file_length = (subtitle_file_info.length + 0x1f) & 0xffffffe0; subtitle_file_buf = static_cast(heap::alloc(subtitle_file_length)); subtitle_file_length = mkb::read_entire_file_using_dvdread_prio_async(&subtitle_file_info, subtitle_file_buf, - subtitle_file_length, 0); + subtitle_file_length, 0); char* eof = subtitle_file_buf + subtitle_file_info.length; MOD_ASSERT_MSG(subtitle_file_length != 0, diff --git a/src/patches/fixes/fix_bonus_sprite.cpp b/src/patches/fixes/fix_bonus_sprite.cpp index f7385484..59cdcfa7 100644 --- a/src/patches/fixes/fix_bonus_sprite.cpp +++ b/src/patches/fixes/fix_bonus_sprite.cpp @@ -13,40 +13,42 @@ TICKABLE_DEFINITION(( static patch::Tramp s_create_hud_sprites_tramp; -void new_bonus_sprite_tick(u8 *status, mkb::Sprite *sprite) { +void new_bonus_sprite_tick(u8* status, mkb::Sprite* sprite) { + // We need to handle fading the sprite when the REPLAY sprite spawns, + // since the original tick always assumes we're on load in if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN) { sprite->alpha -= 0.07; } if (sprite->alpha < 0) { - sprite-> alpha = 0; + sprite->alpha = 0; } } void create_bonus_sprite(void) { // Check if we're on a bonus stage and if the sprite already exists - mkb::Sprite *special_stage_text_sprite = mkb::get_sprite_with_unique_id(mkb::SPRITE_SPECIAL_STAGE); - if ((special_stage_text_sprite == (mkb::Sprite *)0x0) && - ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE) != mkb::BALLMODE_NONE)) { + mkb::Sprite* special_stage_text_sprite = mkb::get_sprite_with_unique_id(mkb::SPRITE_SPECIAL_STAGE); + if ((special_stage_text_sprite == (mkb::Sprite*) 0x0) && + ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE) != mkb::BALLMODE_NONE)) { // Create the sprite - mkb::Sprite *sprite; - sprite = mkb::create_sprite(); - if (sprite != (mkb::Sprite*) 0x0) { - sprite->unique_id = mkb::SPRITE_SPECIAL_STAGE; - (sprite->pos).x = 500.0; - (sprite->pos).y = 452.0; - (sprite->mult_color).red = 0xff; - (sprite->mult_color).green = 0x80; - (sprite->mult_color).blue = '\0'; - sprite->font = mkb::FONT_ASC_72x64; - sprite->alignment = mkb::ALIGN_CENTER; - sprite->width = 0.3; - sprite->height = 0.3; - sprite->g_flags1 = sprite->g_flags1 | 0x1001000; - sprite->widescreen_translation_x = 0x27f; - sprite->tick_func = new_bonus_sprite_tick; - mkb::strcpy(sprite->text, "BONUS STAGE"); + mkb::Sprite* sprite; + sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->unique_id = mkb::SPRITE_SPECIAL_STAGE; + (sprite->pos).x = 500.0; + (sprite->pos).y = 452.0; + (sprite->mult_color).red = 0xff; + (sprite->mult_color).green = 0x80; + (sprite->mult_color).blue = '\0'; + sprite->font = mkb::FONT_ASC_72x64; + sprite->alignment = mkb::ALIGN_CENTER; + sprite->width = 0.3; + sprite->height = 0.3; + sprite->g_flags1 = sprite->g_flags1 | 0x1001000; + sprite->widescreen_translation_x = 0x27f; + sprite->tick_func = new_bonus_sprite_tick; + mkb::strcpy(sprite->text, "BONUS STAGE"); + } } - } } void init_main_loop() { diff --git a/src/patches/fixes/fix_final_stage.cpp b/src/patches/fixes/fix_final_stage.cpp index ef624473..18cd9a0a 100644 --- a/src/patches/fixes/fix_final_stage.cpp +++ b/src/patches/fixes/fix_final_stage.cpp @@ -11,7 +11,7 @@ TICKABLE_DEFINITION(( .description = "Final stage fixes", .init_main_loop = init_main_loop, .init_main_game = init_main_game, - .tick = tick )) + .tick = tick)) void tick() { @@ -28,47 +28,47 @@ void tick() { if (((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE))) { // Fade the FINAL STAGE sprite ourselves when a replay starts if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_INIT) { - mkb::Sprite *sprite; - sprite = mkb::get_sprite_with_unique_id(0xf); - if (sprite != (mkb::Sprite *)0x0) { - sprite->para1 = 0xf; - } + mkb::Sprite* sprite; + sprite = mkb::get_sprite_with_unique_id(0xf); + if (sprite != (mkb::Sprite*) 0x0) { + sprite->para1 = 0xf; + } } // Initiate PERFECT if the perfect bonus patch is enabled - if (tickable::get_tickable_manager().get_tickable_status("perfect-bonus-completion")) { - if (mkb::mode_info.bananas_remaining == 0) { - if ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_FINAL_STAGE)) { - if (mkb::sub_mode == mkb::SMD_GAME_PLAY_MAIN) { - mkb::mode_info.ball_mode |= mkb::BALLMODE_CLEARED_BONUS_PERFECT; - } - else { - mkb::mode_info.ball_mode &= ~mkb::BALLMODE_CLEARED_BONUS_PERFECT; + if (tickable::get_tickable_manager().get_tickable_status("perfect-bonus-completion")) { + if (mkb::mode_info.bananas_remaining == 0) { + if ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_FINAL_STAGE)) { + if (mkb::sub_mode == mkb::SMD_GAME_PLAY_MAIN) { + mkb::mode_info.ball_mode |= mkb::BALLMODE_CLEARED_BONUS_PERFECT; + } + else { + mkb::mode_info.ball_mode &= ~mkb::BALLMODE_CLEARED_BONUS_PERFECT; + } } } - } - } } -} + } +} void fix_final_stage_sprite_position() { if ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE)) { // Repoint sprite positions if we're on a FINAL and BONUS stage // Any values written here overwrite unused portions in memory - patch::write_word(reinterpret_cast(0x8032bf10), 0xc01f012c); - patch::write_word(reinterpret_cast(0x803e7abc), 0x43a50000); - patch::write_word(reinterpret_cast(0x8032d1e4), 0xc01f0244); - patch::write_word(reinterpret_cast(0x803e7bd4), 0x43eb0000); - patch::write_word(reinterpret_cast(0x8032d268), 0xc87f00b8); - patch::write_word(reinterpret_cast(0x803e7a48), 0x4073e000); - patch::write_word(reinterpret_cast(0x803e7a4c), 0x00000000); - // By default, the function to fade the FINAL or BONUS stage sprite - // only fades one at a time, so overwrite the special ID of the FINAL - // stage one to something else so we can fade it ourselves - // This special ID is used by a different sprite at other times, so we have to - // reset it later - patch::write_word(reinterpret_cast(0x8032bf00), 0x3800000f); + patch::write_word(reinterpret_cast(0x8032bf10), 0xc01f012c); + patch::write_word(reinterpret_cast(0x803e7abc), 0x43a50000); + patch::write_word(reinterpret_cast(0x8032d1e4), 0xc01f0244); + patch::write_word(reinterpret_cast(0x803e7bd4), 0x43eb0000); + patch::write_word(reinterpret_cast(0x8032d268), 0xc87f00b8); + patch::write_word(reinterpret_cast(0x803e7a48), 0x4073e000); + patch::write_word(reinterpret_cast(0x803e7a4c), 0x00000000); + // By default, the function to fade the FINAL or BONUS stage sprite + // only fades one at a time, so overwrite the special ID of the FINAL + // stage one to something else so we can fade it ourselves + // This special ID is used by a different sprite at other times, so we have to + // reset it later + patch::write_word(reinterpret_cast(0x8032bf00), 0x3800000f); } else { - // Undo repoints + // Undo repoints patch::write_word(reinterpret_cast(0x8032bf10), 0xc01f00f0); patch::write_word(reinterpret_cast(0x8032d1e4), 0xc01f023c); patch::write_word(reinterpret_cast(0x8032d268), 0xc87f0248); @@ -78,50 +78,49 @@ void fix_final_stage_sprite_position() { } void handle_final_bonus() { // If the final stage is a bonus and we get a Bonus Finish or Time Over, do end of difficulty or extra stuff - if (((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE)) - && (mkb::in_practice_mode == false)) { + if (((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE)) && (mkb::in_practice_mode == false)) { bool start_extras = false; - if (((mkb::mode_flags & mkb::MF_0x1) != mkb::MF_NONE) && (mkb::mode_info.field13_0x2a == 0)) { + if (((mkb::mode_flags & mkb::MF_0x1) != mkb::MF_NONE) && (mkb::mode_info.field13_0x2a == 0)) { start_extras = true; - } - if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_EXTRA_COURSE) != mkb::MF_NONE)) && - (mkb::curr_difficulty != mkb::DIFF_EXPERT)) { - start_extras = false; - } - if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_NOEX_COURSE) != mkb::MF_NONE)) && - (mkb::curr_difficulty != mkb::DIFF_EXPERT)) { - start_extras = false; - } - if ((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_EX_COURSE) != mkb::MF_NONE)) { - start_extras = false; - } - if (mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) { - if (mkb::mode_info.ball_mode & mkb::BALLMODE_OUT_OF_TIME_RINGOUT | mkb::BALLMODE_FALLEN_OUT | mkb::BALLMODE_CLEARED_BONUS_PERFECT) { - if (!start_extras || tickable::get_tickable_manager().get_tickable_status("remove-extras")) { - if (mkb::sub_mode_frame_counter == 0x3c) { - mkb::fade_screen_to_color(0x101, 0, 0x3d); - mkb::g_fade_track_volume(0x3c, '\x02'); } - if (mkb::sub_mode_frame_counter < 1) { - mkb::g_smth_with_ending_course(); - mkb::g_smth_with_ending_course_2(); - mkb::g_change_music_volume(0xc, 0x3c, '\0'); - mkb::main_mode_request = mkb::MD_AUTHOR; - mkb::sub_mode_request = mkb::SMD_AUTHOR_PLAY_ENDING_INIT; - mkb::mode_flags = mkb::mode_flags | 0x100040; + if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_EXTRA_COURSE) != mkb::MF_NONE)) && + (mkb::curr_difficulty != mkb::DIFF_EXPERT)) { + start_extras = false; } + if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_NOEX_COURSE) != mkb::MF_NONE)) && + (mkb::curr_difficulty != mkb::DIFF_EXPERT)) { + start_extras = false; } - else { - if (mkb::sub_mode_frame_counter == 0x3c) { - mkb::fade_screen_to_color(0x101, 0, 0x3d); - mkb::g_fade_track_volume(0x3c, '\x02'); + if ((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_EX_COURSE) != mkb::MF_NONE)) { + start_extras = false; } - if (mkb::sub_mode_frame_counter < 1) { - mkb::sub_mode_request = mkb::SMD_GAME_EXTRA_INIT; + if (mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) { + if (mkb::mode_info.ball_mode & mkb::BALLMODE_OUT_OF_TIME_RINGOUT | mkb::BALLMODE_FALLEN_OUT | mkb::BALLMODE_CLEARED_BONUS_PERFECT) { + if (!start_extras || tickable::get_tickable_manager().get_tickable_status("remove-extras")) { + if (mkb::sub_mode_frame_counter == 0x3c) { + mkb::fade_screen_to_color(0x101, 0, 0x3d); + mkb::g_fade_track_volume(0x3c, '\x02'); + } + if (mkb::sub_mode_frame_counter < 1) { + mkb::g_smth_with_ending_course(); + mkb::g_smth_with_ending_course_2(); + mkb::g_change_music_volume(0xc, 0x3c, '\0'); + mkb::main_mode_request = mkb::MD_AUTHOR; + mkb::sub_mode_request = mkb::SMD_AUTHOR_PLAY_ENDING_INIT; + mkb::mode_flags = mkb::mode_flags | 0x100040; + } + } + else { + if (mkb::sub_mode_frame_counter == 0x3c) { + mkb::fade_screen_to_color(0x101, 0, 0x3d); + mkb::g_fade_track_volume(0x3c, '\x02'); + } + if (mkb::sub_mode_frame_counter < 1) { + mkb::sub_mode_request = mkb::SMD_GAME_EXTRA_INIT; + } + } } } - } - } } } diff --git a/src/patches/fixes/fix_goal_types.cpp b/src/patches/fixes/fix_goal_types.cpp index 4162e7e7..37d4938c 100644 --- a/src/patches/fixes/fix_goal_types.cpp +++ b/src/patches/fixes/fix_goal_types.cpp @@ -16,8 +16,8 @@ TICKABLE_DEFINITION(( // preventing score and warp issues on stages with loads of // goals void init_main_loop() { - patch::write_word(reinterpret_cast(0x802d81a8), 0x2c0800ff); // cmpwi r8, 255 - patch::write_word(reinterpret_cast(0x8031373c), 0x2c0500ff); // cmpwi r5, 255 + patch::write_word(reinterpret_cast(0x802d81a8), 0x2c0800ff);// cmpwi r8, 255 + patch::write_word(reinterpret_cast(0x8031373c), 0x2c0500ff);// cmpwi r5, 255 } }// namespace fix_goal_types diff --git a/src/patches/fixes/fix_monkey_counter.cpp b/src/patches/fixes/fix_monkey_counter.cpp index 4d04f6d7..c9a77494 100644 --- a/src/patches/fixes/fix_monkey_counter.cpp +++ b/src/patches/fixes/fix_monkey_counter.cpp @@ -13,11 +13,11 @@ TICKABLE_DEFINITION(( // In the function responsible for displaying the monkey // counter sprite, check for if monkey count is less than -// 255 instead of 4, effectively never executing leftover +// 255 instead of 4, effectively never executing leftover // sprite code from SMB1 void init_main_loop() { - patch::write_word(reinterpret_cast(0x80332874), 0x2c0000ff); // cmpwi r0, 255 - patch::write_word(reinterpret_cast(0x80332f94), 0x2c0000ff); // cmpwi r0, 255 + patch::write_word(reinterpret_cast(0x80332874), 0x2c0000ff);// cmpwi r0, 255 + patch::write_word(reinterpret_cast(0x80332f94), 0x2c0000ff);// cmpwi r0, 255 } }// namespace fix_monkey_counter diff --git a/src/patches/fixes/fix_storm_continue_platform.cpp b/src/patches/fixes/fix_storm_continue_platform.cpp index 97b4ce2b..c5c4afba 100644 --- a/src/patches/fixes/fix_storm_continue_platform.cpp +++ b/src/patches/fixes/fix_storm_continue_platform.cpp @@ -11,21 +11,22 @@ TICKABLE_DEFINITION(( .tick = tick, )) void tick() { - // Check if we're entering or on the continue screen - if ((mkb::sub_mode ==(mkb::SMD_GAME_CONTINUE_MAIN) || mkb::sub_mode == (mkb::SMD_GAME_CONTINUE_INIT)) && (mkb::sub_mode_frame_counter >= 2)) { // frame counter check helps prevent race conditions - // Nop some branches to code which handle rotating the storm raindrops + // Check if we're entering or on the continue screen + // Frame counter check helps prevent race conditions + if ((mkb::sub_mode == (mkb::SMD_GAME_CONTINUE_MAIN) || mkb::sub_mode == (mkb::SMD_GAME_CONTINUE_INIT)) && (mkb::sub_mode_frame_counter >= 2)) { + // Nop some branches to code which handle rotating the storm raindrops patch::write_nop(reinterpret_cast(0x802de2e4)); patch::write_nop(reinterpret_cast(0x802de2ec)); patch::write_nop(reinterpret_cast(0x802de2f4)); patch::write_nop(reinterpret_cast(0x802de2fc)); - } - else { - // Original instructions + } + else { + // Original instructions patch::write_word(reinterpret_cast(0x802de2e4), 0x4bd84c4d); patch::write_word(reinterpret_cast(0x802de2ec), 0x4bd84bd1); patch::write_word(reinterpret_cast(0x802de2f4), 0x4bd84cc9); patch::write_word(reinterpret_cast(0x802de2fc), 0x4bd84bc1); - } + } } }// namespace fix_storm_continue_platform \ No newline at end of file diff --git a/src/patches/fixes/fix_widescreen.cpp b/src/patches/fixes/fix_widescreen.cpp index b8c19ea0..ff609ba8 100644 --- a/src/patches/fixes/fix_widescreen.cpp +++ b/src/patches/fixes/fix_widescreen.cpp @@ -201,10 +201,10 @@ void init_main_loop() { void tick() { if (mkb::sub_mode == mkb::SMD_SEL_NGC_MAIN) { - patch::write_word(reinterpret_cast(0x80287cf8), 0x418200a8); // original instruction + patch::write_word(reinterpret_cast(0x80287cf8), 0x418200a8);// original instruction } else { - patch::write_nop(reinterpret_cast(0x80287cf8)); // nops a branch to the FOV-modifying code + patch::write_nop(reinterpret_cast(0x80287cf8));// nops a branch to the FOV-modifying code } if (mkb::main_mode == mkb::MD_GAME) { if (mkb::widescreen_mode == 0) { diff --git a/src/patches/removals/remove_challenge_cutscenes.cpp b/src/patches/removals/remove_challenge_cutscenes.cpp index e253e4a0..93857add 100644 --- a/src/patches/removals/remove_challenge_cutscenes.cpp +++ b/src/patches/removals/remove_challenge_cutscenes.cpp @@ -14,8 +14,8 @@ TICKABLE_DEFINITION(( .init_main_game = init_main_game, )) void init_main_game() { - patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); - patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); + patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); + patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); } }// namespace remove_challenge_cutscenes From 5721bb087665b0a110d04984d9f31b3079ec9c32 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 15 Jan 2025 16:05:18 -0800 Subject: [PATCH 29/96] Add goal texture scroll patch --- src/mkb/mkb2_ghidra.h | 2 +- .../extensions/goal_texture_scroll.cpp | 82 +++++++++++++++++++ src/patches/extensions/goal_texture_scroll.h | 7 ++ .../removals/remove_story_cutscenes.cpp | 2 - 4 files changed, 90 insertions(+), 3 deletions(-) create mode 100644 src/patches/extensions/goal_texture_scroll.cpp create mode 100644 src/patches/extensions/goal_texture_scroll.h diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index b51a3cec..056b11c6 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -9581,7 +9581,7 @@ extern "C" { int g_get_debug_level_select_loading_left_asterisks(void); undefined4 g_swapDiscQueueGroup(undefined4 newValue); void g_fill_some_memory_with_0x0_and_0xff(void * ptr); - void g_some_shadow_draw_func(int * param_1); + void g_some_shadow_draw_func(void * pointer); undefined4 g_check_some_condition(ushort param_1); void debug_draw_shadow_textures(void); void md_mini_func(void); diff --git a/src/patches/extensions/goal_texture_scroll.cpp b/src/patches/extensions/goal_texture_scroll.cpp new file mode 100644 index 00000000..38be9a2e --- /dev/null +++ b/src/patches/extensions/goal_texture_scroll.cpp @@ -0,0 +1,82 @@ +#include "goal_texture_scroll.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace goal_texture_scroll { + +TICKABLE_DEFINITION((.name = "goal-texture-scroll", + .description = "Goal texture scroll", + .init_main_loop = init_main_loop)) + +void new_draw_goalpost_models() { + int cond; + bool bVar1; + int iVar3; + mkb::StagedefGoal* stagedef_goal; + mkb::GmaModel* goal_model; + int coli_header_idx; + mkb::StagedefColiHeader* coli_header; + mkb::Itemgroup* itemgroup; + mkb::StagedefGoal* local_68; + mkb::undefined2 local_64; + mkb::undefined2 local_62; + mkb::GmaModel* local_60; + mkb::Mtx mtx; + + local_64 = 0x40; + local_62 = 4; + cond = mkb::g_check_some_condition(0x40); + coli_header = mkb::stagedef->coli_header_list; + itemgroup = mkb::itemgroups; + for (coli_header_idx = 0; coli_header_idx < (int) mkb::stagedef->coli_header_count; + coli_header_idx = coli_header_idx + 1) { + if (coli_header->goal_count != 0) { + mkb::mtxa_from_mtxb(); + if (0 < coli_header_idx) { + mkb::mtxa_mult_right(&itemgroup->transform); + } + mkb::mtxa_to_mtx(&mtx); + stagedef_goal = coli_header->goal_list; + for (iVar3 = 0; iVar3 < (int) coli_header->goal_count; iVar3 = iVar3 + 1) { + mkb::mtxa_from_mtx(&mtx); + mkb::mtxa_translate(&stagedef_goal->position); + mkb::mtxa_rotate_z((stagedef_goal->rotation).z); + mkb::mtxa_rotate_y((stagedef_goal->rotation).y); + mkb::mtxa_rotate_x((stagedef_goal->rotation).x); + goal_model = mkb::goal_gma_models[(char) stagedef_goal->type]; + // Scroll the texture if the IG has texture scroll parameters set + if (coli_header->texture_scroll != (mkb::StagedefTextureScroll*) 0x0) { + mkb::g_something_with_texture_scroll(coli_header->texture_scroll); + } + if ((goal_model != (mkb::GmaModel*) 0x0) && + (bVar1 = mkb::g_is_sphere_visible((double) goal_model->bound_sphere_radius, + &goal_model->bound_sphere_center), + bVar1)) { + mkb::load_gx_pos_nrm_mtx(mkb::mtxa, 0); + mkb::avdisp_draw_model_unculled_sort_auto(goal_model); + local_60 = goal_model; + /* This is meant to allow goals to receive shadows but is crashing at the moment + if (cond != 0) { + local_68 = stagedef_goal; + mkb::g_some_shadow_draw_func(&local_68); + } + */ + } + stagedef_goal = stagedef_goal + 1; + } + } + itemgroup = itemgroup + 1; + coli_header = coli_header + 1; + } + return; +} + +void init_main_loop() { + patch::write_branch( + reinterpret_cast(mkb::g_draw_goalpost_models), + reinterpret_cast(new_draw_goalpost_models)); +} + +}// namespace goal_texture_scroll \ No newline at end of file diff --git a/src/patches/extensions/goal_texture_scroll.h b/src/patches/extensions/goal_texture_scroll.h new file mode 100644 index 00000000..6403879a --- /dev/null +++ b/src/patches/extensions/goal_texture_scroll.h @@ -0,0 +1,7 @@ +#pragma once + +#include "mkb/mkb.h" + +namespace goal_texture_scroll { +void init_main_loop(); +}// namespace goal_texture_scroll \ No newline at end of file diff --git a/src/patches/removals/remove_story_cutscenes.cpp b/src/patches/removals/remove_story_cutscenes.cpp index 6828862f..185a9aa2 100644 --- a/src/patches/removals/remove_story_cutscenes.cpp +++ b/src/patches/removals/remove_story_cutscenes.cpp @@ -8,8 +8,6 @@ namespace remove_story_cutscenes { -static u16 DEFAULT_CUTSCENE_SKIP_SETTING = 0; - TICKABLE_DEFINITION(( .name = "remove-story-cutscenes", .description = "Story Mode cutscene removal", From 379c2ded7f83c49b73139a70277556f601f8f76e Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 15 Jan 2025 22:01:56 -0800 Subject: [PATCH 30/96] Add double stage select patch --- src/mkb/mkb2.us.lst | 6 +- src/mkb/mkb2_ghidra.h | 6 +- src/patches/extensions/challenge_retry.cpp | 2 +- src/patches/tweaks/double_stage_select.cpp | 75 ++++++++++++++++++++++ src/patches/tweaks/double_stage_select.h | 6 ++ 5 files changed, 92 insertions(+), 3 deletions(-) create mode 100644 src/patches/tweaks/double_stage_select.cpp create mode 100644 src/patches/tweaks/double_stage_select.h diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index e953afa5..f5e776cb 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -8313,8 +8313,12 @@ 8047EA48:switchdataD_803a8800 8047EADC:switchdataD_803a8894 8047EB14:switchdataD_803a88cc +8047EDF4:PAUSEMENU_EXIT_GAME_STRING 8047EED4:challenge_play_pausemenu_entries -8047EF94:goal_pausemenu_entries +8047EF94:challenge_goal_pausemenu_entries +8047F02C:PAUSEMENU_STAGE_SELECT_STRING +8047F33C:story_play_pausemenu_entries +8047F3CC:story_goal_pausemenu_entries 8047F4A4:pausemenu_entry_pointers 8047F770:LOADIN_TEXT_ROUND 8047F77C:LOADIN_TEXT_WORLD diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index 056b11c6..c381d679 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5878,8 +5878,12 @@ extern "C" { extern pointer switchdataD_803a8800; extern pointer switchdataD_803a8894; extern undefined * switchdataD_803a88cc; + extern char PAUSEMENU_EXIT_GAME_STRING[10]; extern char * challenge_play_pausemenu_entries[24]; - extern char * goal_pausemenu_entries[24]; + extern char * challenge_goal_pausemenu_entries[24]; + extern char PAUSEMENU_STAGE_SELECT_STRING[13]; + extern char * story_play_pausemenu_entries[36]; + extern char * story_goal_pausemenu_entries[36]; extern char * * pausemenu_entry_pointers[16]; extern char LOADIN_TEXT_ROUND[9]; extern char LOADIN_TEXT_WORLD[12]; diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index f9516826..f57e28d1 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -59,7 +59,7 @@ void pausemenu_handler() { mkb::balls[0].monkey_count < 2 || (mkb::mode_info.ball_mode & mkb::BALLMODE_GOALED)) { mkb::pausemenu_entry_counts[1] = 4; mkb::g_current_pause_menu_entry_count = 4; - mkb::pausemenu_entry_pointers[9] = mkb::goal_pausemenu_entries; + mkb::pausemenu_entry_pointers[9] = mkb::challenge_goal_pausemenu_entries; mkb::pausemenu_entry_pointers[1] = mkb::challenge_play_pausemenu_entries; patch::write_word(reinterpret_cast(0x80273cc8), 0x2c000004);// in the instruction which handles pausemenu input, Exit Game when option 4 is selected } diff --git a/src/patches/tweaks/double_stage_select.cpp b/src/patches/tweaks/double_stage_select.cpp new file mode 100644 index 00000000..e150fb81 --- /dev/null +++ b/src/patches/tweaks/double_stage_select.cpp @@ -0,0 +1,75 @@ +#include "double_stage_select.h" +#include "../internal/pad.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" + +namespace double_stage_select { + +TICKABLE_DEFINITION(( + .name = "double-stage-select", + .description = "Double stage select", + .init_main_loop = init, + .tick = tick)) + +static patch::Tramp s_check_pause_menu_input_tramp; + +// While we can easily edit a few values in the function which handles pausemenu selections to +// get most of the desired behavior, some of it has to be recreated manually + +void pausemenu_handler(mkb::Sprite* pause_sprite) { + if (mkb::main_game_mode == mkb::STORY_MODE) { + // Stage select + if (mkb::g_current_focused_pause_menu_entry == 5 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_related_to_pause_menu_input = 0x3c; + if (pause_sprite != (mkb::Sprite*) 0x0) { + pause_sprite->para1 = 2; + } + // Fade the music out only if the music fix isn't enabled + if (!tickable::get_tickable_manager().get_tickable_status("story-mode-music-fix")) { + mkb::g_fade_track_volume(0x3b, '\x02'); + } + mkb::g_screenfade_color = 0xffffff; + } + // Exit game + else if (mkb::g_current_focused_pause_menu_entry == 3 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + mkb::g_related_to_pause_menu_input = 0x3c; + if (pause_sprite != (mkb::Sprite*) 0x0) { + pause_sprite->para1 = 3; + } + mkb::g_fade_track_volume(0x3c, '\x02'); + mkb::g_load_stage_for_menu_bg(-1, 1); + } + } +} + +void init() { + // Edits behaviors in the function which handles pausemenu selections + patch::write_nop(reinterpret_cast(0x802745a4)); + patch::write_nop(reinterpret_cast(0x8027457c)); + patch::write_word(reinterpret_cast(0x8027459c), 0x2c000003);// cmpwi r0, 3 + // Hook into the function which checks input in the pausemenu for our recreated behaviors + patch::hook_function(s_check_pause_menu_input_tramp, mkb::check_pause_menu_input, [](mkb::Sprite* pause_sprite) { + s_check_pause_menu_input_tramp.dest(pause_sprite); + pausemenu_handler(pause_sprite); + }); + // Text changes + mkb::story_play_pausemenu_entries[18] = mkb::PAUSEMENU_EXIT_GAME_STRING; + mkb::story_goal_pausemenu_entries[18] = mkb::PAUSEMENU_EXIT_GAME_STRING; + mkb::story_play_pausemenu_entries[30] = mkb::PAUSEMENU_STAGE_SELECT_STRING; + mkb::story_goal_pausemenu_entries[30] = mkb::PAUSEMENU_STAGE_SELECT_STRING; +} + +void tick() { + // Rids and rearranges some vanilla behaviors for pausemenu selections when in Story Mode + if (mkb::main_game_mode == mkb::STORY_MODE && mkb::sub_mode != mkb::SMD_GAME_SCENARIO_MAIN) { + patch::write_word(reinterpret_cast(0x8027513c), 0x3803fffd); + patch::write_nop(reinterpret_cast(0x80273ad0)); + } + else { + // Original instructions + patch::write_word(reinterpret_cast(0x8027513c), 0x3803ffff); + patch::write_word(reinterpret_cast(0x80273ad0), 0x3803ffff); + } +} +}// namespace double_stage_select \ No newline at end of file diff --git a/src/patches/tweaks/double_stage_select.h b/src/patches/tweaks/double_stage_select.h new file mode 100644 index 00000000..2a059f50 --- /dev/null +++ b/src/patches/tweaks/double_stage_select.h @@ -0,0 +1,6 @@ +#pragma once + +namespace double_stage_select { +void init(); +void tick(); +}// namespace double_stage_select \ No newline at end of file From ad8a711d9660ca7192e5d0b8460d1ed19beadca4 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Wed, 15 Jan 2025 22:39:46 -0800 Subject: [PATCH 31/96] Pause cooldown only activates during gameplay --- src/patches/tweaks/pause_cooldown.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/patches/tweaks/pause_cooldown.cpp b/src/patches/tweaks/pause_cooldown.cpp index b8c3f207..3cfd1e5b 100644 --- a/src/patches/tweaks/pause_cooldown.cpp +++ b/src/patches/tweaks/pause_cooldown.cpp @@ -14,8 +14,10 @@ TICKABLE_DEFINITION(( // every frame, ensuring even once unpaused the player must wait // a full second before pausing again void tick() { - if (mkb::g_pause_status == 2) { - mkb::g_repause_cooldown_counter = 0x3c; + if (mkb::sub_mode == mkb::SMD_GAME_PLAY_MAIN) { + if (mkb::g_pause_status == 2) { + mkb::g_repause_cooldown_counter = 0x3c; + } } } From 8403c95a87deb41e3ecbfb75431da3c98e7608d9 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 16 Jan 2025 15:28:56 -0800 Subject: [PATCH 32/96] Add patch to remove ice fog --- src/patches/removals/remove_ice_fog.cpp | 17 +++++++++++++++++ src/patches/removals/remove_ice_fog.h | 7 +++++++ 2 files changed, 24 insertions(+) create mode 100644 src/patches/removals/remove_ice_fog.cpp create mode 100644 src/patches/removals/remove_ice_fog.h diff --git a/src/patches/removals/remove_ice_fog.cpp b/src/patches/removals/remove_ice_fog.cpp new file mode 100644 index 00000000..7a5e1d7b --- /dev/null +++ b/src/patches/removals/remove_ice_fog.cpp @@ -0,0 +1,17 @@ +#include "remove_ice_fog.h" + +#include "internal/patch.h" +#include "internal/tickable.h" + +namespace remove_ice_fog { + +TICKABLE_DEFINITION(( + .name = "remove-ice-fog", + .description = "Ice fog removal", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + mkb::ICE_FOG_THEME_ID = 0xff; +} + +}// namespace remove_ice_fog diff --git a/src/patches/removals/remove_ice_fog.h b/src/patches/removals/remove_ice_fog.h new file mode 100644 index 00000000..76e79712 --- /dev/null +++ b/src/patches/removals/remove_ice_fog.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_ice_fog { + +void init_main_loop(); + +}// namespace remove_ice_fog \ No newline at end of file From a9b1b7d5e377d79c0eedbf6e8d5181365bfe5535 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 16 Jan 2025 16:22:04 -0800 Subject: [PATCH 33/96] Fix replay issues with custom music IDs --- src/assembly/music_id_per_stage.s | 20 +++++++++++++++++--- src/internal/assembly.h | 3 --- 2 files changed, 17 insertions(+), 6 deletions(-) diff --git a/src/assembly/music_id_per_stage.s b/src/assembly/music_id_per_stage.s index 7f33b9cb..08e383cb 100644 --- a/src/assembly/music_id_per_stage.s +++ b/src/assembly/music_id_per_stage.s @@ -1,12 +1,26 @@ .global get_bgm_id_hook -.extern bgm_id_lookup, g_current_stage_id +.extern bgm_id_lookup, g_current_stage_id, g_replay_stage_id_to_load, sub_mode get_bgm_id_hook: - lis r0, bgm_id_lookup@h - ori r0, r0, bgm_id_lookup@l + lis r4, sub_mode@h + ori r4, r4, sub_mode@l + lwz r4, 0(r4) + cmpwi r4, 258 + bne default_path + + lis r3, g_replay_stage_id_to_load@h + ori r3, r3, g_replay_stage_id_to_load@l + lwz r3, 0(r3) + b skip + +default_path: lis r3, g_current_stage_id@h ori r3, r3, g_current_stage_id@l lwz r3, 0(r3) + +skip: + lis r0, bgm_id_lookup@h + ori r0, r0, bgm_id_lookup@l mulli r3, r3, 0x2 add r3, r0, r3 lhz r0, 0(r3) diff --git a/src/internal/assembly.h b/src/internal/assembly.h index 795e24cd..3ca753ff 100644 --- a/src/internal/assembly.h +++ b/src/internal/assembly.h @@ -40,9 +40,6 @@ void get_theme_id_hook_2(); // story_mode_char_select void get_monkey_id_hook(); - -extern mkb::SubMode sub_mode; -void fix_rain_ripple(); } }// namespace main From 0869d55a61b27681028318fcd2a9a61a793e901d Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 16 Jan 2025 16:36:12 -0800 Subject: [PATCH 34/96] Add menu stage ID patch --- src/patches/custom/menu_stage_id.cpp | 35 ++++++++++++++++++++++++++++ src/patches/custom/menu_stage_id.h | 8 +++++++ 2 files changed, 43 insertions(+) create mode 100644 src/patches/custom/menu_stage_id.cpp create mode 100644 src/patches/custom/menu_stage_id.h diff --git a/src/patches/custom/menu_stage_id.cpp b/src/patches/custom/menu_stage_id.cpp new file mode 100644 index 00000000..87f5c117 --- /dev/null +++ b/src/patches/custom/menu_stage_id.cpp @@ -0,0 +1,35 @@ +#include "menu_stage_id.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace menu_stage_id { + +u16 stage_id; + +// Always enabled + +TICKABLE_DEFINITION(( + .name = "menu-stage-id", + .description = "Menu stage ID", + .active_value = stage_id, + .lower_bound = 1, + .upper_bound = 420, + .init_main_loop = init_main_loop, + .init_main_game = init_main_game)) + +// In functions which handle the menu stage to load, use our stage ID +void init_main_loop() { + stage_id = *active_tickable_ptr->active_value;// Get our stage ID + patch::write_word(reinterpret_cast(0x80282c10), PPC_INSTR_LI(PPC_R31, stage_id)); + patch::write_word(reinterpret_cast(0x80282c20), PPC_INSTR_LI(PPC_R31, stage_id)); +} + +void init_main_game() { + patch::write_word(reinterpret_cast(0x808fd958), PPC_INSTR_LI(PPC_R3, stage_id)); + patch::write_word(reinterpret_cast(0x808fe7d8), PPC_INSTR_LI(PPC_R3, stage_id)); +} + +}// namespace menu_stage_id diff --git a/src/patches/custom/menu_stage_id.h b/src/patches/custom/menu_stage_id.h new file mode 100644 index 00000000..6625839f --- /dev/null +++ b/src/patches/custom/menu_stage_id.h @@ -0,0 +1,8 @@ +#pragma once + +namespace menu_stage_id { + +void init_main_loop(); +void init_main_game(); + +}// namespace menu_stage_id \ No newline at end of file From 939f0ac0afd05c144c8d247dcbf7bb9979b635f0 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Thu, 16 Jan 2025 21:32:38 -0800 Subject: [PATCH 35/96] Add patch to load extra BG files --- .../extensions/load_extra_bg_files.cpp | 23 +++++++++++++++++++ src/patches/extensions/load_extra_bg_files.h | 7 ++++++ 2 files changed, 30 insertions(+) create mode 100644 src/patches/extensions/load_extra_bg_files.cpp create mode 100644 src/patches/extensions/load_extra_bg_files.h diff --git a/src/patches/extensions/load_extra_bg_files.cpp b/src/patches/extensions/load_extra_bg_files.cpp new file mode 100644 index 00000000..ecd494a4 --- /dev/null +++ b/src/patches/extensions/load_extra_bg_files.cpp @@ -0,0 +1,23 @@ +#include "load_extra_bg_files.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace load_extra_bg_files { + +TICKABLE_DEFINITION(( + .name = "load-extra-bg-files", + .description = "Extra BG file loading", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + mkb::g_bg_filename_list[1] = "bg_lav"; + mkb::g_bg_filename_list[12] = "bg_bil"; + mkb::g_bg_filename_list[30] = "bg_bil2"; + mkb::g_bg_filename_list[31] = "bg_boa2"; + mkb::g_bg_filename_list[34] = "bg_au_pot2"; + mkb::g_bg_filename_list[41] = "bg_au_bow2"; +} + +}// namespace load_extra_bg_files diff --git a/src/patches/extensions/load_extra_bg_files.h b/src/patches/extensions/load_extra_bg_files.h new file mode 100644 index 00000000..1f3acbd7 --- /dev/null +++ b/src/patches/extensions/load_extra_bg_files.h @@ -0,0 +1,7 @@ +#pragma once + +namespace load_extra_bg_files { + +void init_main_loop(); + +}// namespace load_extra_bg_files \ No newline at end of file From 503f2d3318e765a5339c3fc0760bd97ca88c4bd4 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Sat, 18 Jan 2025 13:31:28 -0800 Subject: [PATCH 36/96] Add menu option toggle patch, tidy things up for release --- src/config/config.cpp | 47 ++++++---- src/internal/version.cpp | 2 +- src/mkb/mkb2.us.lst | 3 + src/mkb/mkb2_ghidra.h | 3 + src/patches/custom/menu_option_toggle.cpp | 90 +++++++++++++++++++ src/patches/custom/menu_option_toggle.h | 14 +++ src/patches/custom/menu_stage_id.cpp | 2 +- src/patches/custom/party_game_toggle.cpp | 57 ------------ src/patches/custom/party_game_toggle.h | 10 --- src/patches/fixes/fix_widescreen.cpp | 9 +- src/patches/removals/remove_playpoints.cpp | 6 ++ src/patches/removals/remove_playpoints.h | 1 + src/patches/story/story_char_select.cpp | 2 +- .../story_double_stage_select.cpp} | 8 +- src/patches/story/story_double_stage_select.h | 6 ++ src/patches/tweaks/double_stage_select.h | 6 -- src/patches/tweaks/menu_reflections.cpp | 2 - 17 files changed, 164 insertions(+), 104 deletions(-) create mode 100644 src/patches/custom/menu_option_toggle.cpp create mode 100644 src/patches/custom/menu_option_toggle.h delete mode 100644 src/patches/custom/party_game_toggle.cpp delete mode 100644 src/patches/custom/party_game_toggle.h rename src/patches/{tweaks/double_stage_select.cpp => story/story_double_stage_select.cpp} (94%) create mode 100644 src/patches/story/story_double_stage_select.h delete mode 100644 src/patches/tweaks/double_stage_select.h diff --git a/src/config/config.cpp b/src/config/config.cpp index 18698395..3f2930b0 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -4,7 +4,7 @@ #include "internal/heap.h" #include "internal/log.h" #include "internal/tickable.h" -#include "patches/custom/party_game_toggle.h" +#include "patches/custom/menu_option_toggle.h" #define STREQ(x, y) (mkb::strcmp(const_cast(x), const_cast(y)) == 0) #define KEY_ENABLED(x) (STREQ(key, x) && STREQ(value, "enabled")) @@ -42,7 +42,7 @@ u16* parse_stageid_list(char* buf, u16* array) { return array; } -void parse_party_game_toggles(char* buf) { +void parse_menu_option_toggles(char* buf) { buf = mkb::strchr(buf, '\n') + 1; char* end_of_section; @@ -59,30 +59,43 @@ void parse_party_game_toggles(char* buf) { mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); if KEY_ENABLED ("monkey-race") - party_game_toggle::party_game_bitflag |= 0x1; + menu_option_toggle::party_game_bitflag |= 0x1; else if KEY_ENABLED ("monkey-fight") - party_game_toggle::party_game_bitflag |= 0x2; + menu_option_toggle::party_game_bitflag |= 0x2; else if KEY_ENABLED ("monkey-target") - party_game_toggle::party_game_bitflag |= 0x4; + menu_option_toggle::party_game_bitflag |= 0x4; else if KEY_ENABLED ("monkey-billiards") - party_game_toggle::party_game_bitflag |= 0x8; + menu_option_toggle::party_game_bitflag |= 0x8; else if KEY_ENABLED ("monkey-bowling") - party_game_toggle::party_game_bitflag |= 0x10; + menu_option_toggle::party_game_bitflag |= 0x10; else if KEY_ENABLED ("monkey-golf") - party_game_toggle::party_game_bitflag |= 0x20; + menu_option_toggle::party_game_bitflag |= 0x20; else if KEY_ENABLED ("monkey-boat") - party_game_toggle::party_game_bitflag |= 0x40; + menu_option_toggle::party_game_bitflag |= 0x40; else if KEY_ENABLED ("monkey-shot") - party_game_toggle::party_game_bitflag |= 0x80; + menu_option_toggle::party_game_bitflag |= 0x80; else if KEY_ENABLED ("monkey-dogfight") - party_game_toggle::party_game_bitflag |= 0x100; + menu_option_toggle::party_game_bitflag |= 0x100; else if KEY_ENABLED ("monkey-soccer") - party_game_toggle::party_game_bitflag |= 0x200; + menu_option_toggle::party_game_bitflag |= 0x200; else if KEY_ENABLED ("monkey-baseball") - party_game_toggle::party_game_bitflag |= 0x400; + menu_option_toggle::party_game_bitflag |= 0x400; else if KEY_ENABLED ("monkey-tennis") - party_game_toggle::party_game_bitflag |= 0x800; - + menu_option_toggle::party_game_bitflag |= 0x800; + else if KEY_ENABLED ("party-games") + menu_option_toggle::mode_bitflag &= ~0x2; + else if KEY_ENABLED ("challenge-mode") + menu_option_toggle::main_game_bitflag &= ~0x2; + else if KEY_ENABLED ("story-mode") + menu_option_toggle::main_game_bitflag &= ~0x1; + else if KEY_ENABLED ("beginner") + menu_option_toggle::level_bitflag &= ~0x1; + else if KEY_ENABLED ("advanced") + menu_option_toggle::level_bitflag &= ~0x2; + else if KEY_ENABLED ("expert") + menu_option_toggle::level_bitflag &= ~0x4; + else if KEY_ENABLED ("master") + menu_option_toggle::level_bitflag &= ~0x8; buf = end_of_line + 1; mkb::memset(key, '\0', 64); mkb::memset(value, '\0', 64); @@ -189,8 +202,8 @@ void parse_config() { parse_function_toggles(section_end); } - else if (STREQ(section, "Party Game Toggles")) { - parse_party_game_toggles(section_end); + else if (STREQ(section, "Menu Option Toggles")) { + parse_menu_option_toggles(section_end); } else if (STREQ(section, "Theme IDs")) { diff --git a/src/internal/version.cpp b/src/internal/version.cpp index 2afb801c..6b157005 100644 --- a/src/internal/version.cpp +++ b/src/internal/version.cpp @@ -2,7 +2,7 @@ namespace version { -const SemVer WSMOD_VERSION = {0, 3, 1}; +const SemVer WSMOD_VERSION = {1, 0, 0}; s32 compare(const SemVer& v1, const SemVer& v2) { if (v1.major < v2.major) return -1; diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index f5e776cb..3e1d4d47 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -10027,6 +10027,7 @@ 8091E980:switchdataD_805748e8 8091EA90:switchdataD_805749f8 8091EC48:switchdataD_80574bb0 +8091ED98:CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING 8091EF54:menu_mode_select_entries 8091F098:CAN_PLAY_NUM_PARTY_GAMES_STRING 8091FA7C:menu_party_game_select_entries @@ -10040,6 +10041,8 @@ 80920A24:menu_character_select_1_entries 80920AF4:CHARACTER_SELECT_DESCRIPTION_UNUSED 80920BA0:menu_character_select_2_entries +809216D4:MENU_STORY_DESCRIPTION_TEXT +80921824:MENU_CHALLENGE_DESCRIPTION_TEXT 80921A20:menu_main_game_select_entries 80921D00:menu_level_select_1_entries 80921DAC:menu_level_select_2_entries diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index c381d679..a7af4051 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -6472,6 +6472,7 @@ extern "C" { extern pointer switchdataD_805748e8; extern pointer switchdataD_805749f8; extern pointer switchdataD_80574bb0; + extern char CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING[124]; extern struct MenuEntry menu_mode_select_entries; extern char CAN_PLAY_NUM_PARTY_GAMES_STRING[49]; extern undefined menu_party_game_select_entries; @@ -6485,6 +6486,8 @@ extern "C" { extern struct MenuEntry menu_character_select_1_entries[4]; extern char CHARACTER_SELECT_DESCRIPTION_UNUSED[76]; extern struct MenuEntry menu_character_select_2_entries[4]; + extern char MENU_STORY_DESCRIPTION_TEXT[151]; + extern char MENU_CHALLENGE_DESCRIPTION_TEXT[135]; extern struct MenuEntry menu_main_game_select_entries[3]; extern undefined menu_level_select_1_entries; extern undefined menu_level_select_2_entries; diff --git a/src/patches/custom/menu_option_toggle.cpp b/src/patches/custom/menu_option_toggle.cpp new file mode 100644 index 00000000..54a62bbf --- /dev/null +++ b/src/patches/custom/menu_option_toggle.cpp @@ -0,0 +1,90 @@ +#include "menu_option_toggle.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" +#include "utils/ppcutil.h" + +// Allows for menu options to be toggled with a config option. +namespace menu_option_toggle { + +TICKABLE_DEFINITION(( + .name = "menu-option-toggle", + .description = "Menu option toggle patch", + .init_sel_ngc = init_sel_ngc, + .tick = tick)) + +u16 mode_bitflag = 2; +u16 main_game_bitflag = 3; +u16 level_bitflag = 15; +u16 party_game_bitflag = 0; + +// Variable-precision SWAR algorithm +// Source: https://stackoverflow.com/a/109025 +u32 number_of_unlocked_party_games(u32 i) { + i = i - ((i >> 1) & 0x55555555); // add pairs of bits + i = (i & 0x33333333) + ((i >> 2) & 0x33333333);// quads + i = (i + (i >> 4)) & 0x0F0F0F0F; // groups of 8 + return (i * 0x01010101) >> 24; // horizontal sum of bytes +} + +// Party game IDs do not match their menu positions, hence this ugly mess +u32 determine_party_game_unlock_status(int id) { + switch (id) { + case 0xa: + return (party_game_bitflag & 0x40); + case 0x9: + return (party_game_bitflag & 0x80); + case 0xd: + return (party_game_bitflag & 0x100); + case 0xc: + return (party_game_bitflag & 0x200); + case 0xf: + return (party_game_bitflag & 0x400); + case 0x10: + return (party_game_bitflag & 0x800); + default: + return 0; + } +} + +void init_sel_ngc() { + patch::hook_function(mkb::g_check_if_partygame_unlocked, determine_party_game_unlock_status); + patch::write_word(reinterpret_cast(0x808f9154), PPC_INSTR_LI(PPC_R0, (~party_game_bitflag & 0x3f))); + patch::write_word(reinterpret_cast(0x808ff800), PPC_INSTR_LI(PPC_R0, (main_game_bitflag + 0x4))); + patch::write_word(reinterpret_cast(0x808ff80c), PPC_INSTR_LI(PPC_R0, (main_game_bitflag))); + + mkb::strcpy(mkb::CANNOT_SELECT_PARTY_GAME_STRING, "You cannot play this game\n in this custom pack."); + mkb::strcpy(mkb::CAN_PURCHASE_PARTY_GAME_STRING, "You cannot unlock this game\n in this custom pack."); + if (mode_bitflag == 0x2) { + mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_STRING, "Play the Main Game!", + number_of_unlocked_party_games(party_game_bitflag)); + mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING, "Play the Main Game!", + number_of_unlocked_party_games(party_game_bitflag)); + } + else { + mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_STRING, "You can play /bcff8000/%d/bcffff00/ party games!", + number_of_unlocked_party_games(party_game_bitflag)); + mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING, "You can play /bcff8000/%d/bcffff00/ party games!", + number_of_unlocked_party_games(party_game_bitflag)); + } + if (main_game_bitflag |= 0x1) { + mkb::sprintf(mkb::MENU_STORY_DESCRIPTION_TEXT, "Play Challenge Mode!"); + } + else if (main_game_bitflag |= 0x2) { + mkb::sprintf(mkb::MENU_CHALLENGE_DESCRIPTION_TEXT, "Play Story Mode!"); + } +} + +void tick() { + if (mkb::main_mode == mkb::MD_SEL) { + if (mkb::g_currently_visible_menu_screen == mkb::MENUSCREEN_MODE_SELECT) { + mkb::locked_menu_items = mode_bitflag; + } + else if (mkb::g_currently_visible_menu_screen == mkb::MENUSCREEN_LEVEL_SELECT_NOMASTER || mkb::g_currently_visible_menu_screen == mkb::MENUSCREEN_LEVEL_SELECT_WITHMASTER) { + mkb::locked_menu_items = level_bitflag; + } + } +} + +}// namespace menu_option_toggle diff --git a/src/patches/custom/menu_option_toggle.h b/src/patches/custom/menu_option_toggle.h new file mode 100644 index 00000000..0d9cabd7 --- /dev/null +++ b/src/patches/custom/menu_option_toggle.h @@ -0,0 +1,14 @@ +#pragma once + +#include "mkb/mkb.h" + +namespace menu_option_toggle { + +void init_sel_ngc(); +void tick(); +extern u16 mode_bitflag; +extern u16 main_game_bitflag; +extern u16 level_bitflag; +extern u16 party_game_bitflag; + +}// namespace menu_option_toggle \ No newline at end of file diff --git a/src/patches/custom/menu_stage_id.cpp b/src/patches/custom/menu_stage_id.cpp index 87f5c117..57996d83 100644 --- a/src/patches/custom/menu_stage_id.cpp +++ b/src/patches/custom/menu_stage_id.cpp @@ -7,7 +7,7 @@ namespace menu_stage_id { -u16 stage_id; +u16 stage_id = 201; // Always enabled diff --git a/src/patches/custom/party_game_toggle.cpp b/src/patches/custom/party_game_toggle.cpp deleted file mode 100644 index 50e13079..00000000 --- a/src/patches/custom/party_game_toggle.cpp +++ /dev/null @@ -1,57 +0,0 @@ -#include "party_game_toggle.h" - -#include "internal/patch.h" -#include "internal/tickable.h" -#include "mkb/mkb.h" -#include "utils/ppcutil.h" - -// Allows for party games to be toggled with a config option. -namespace party_game_toggle { - -TICKABLE_DEFINITION(( - .name = "party-game-toggle", - .description = "Party game toggle patch", - .init_sel_ngc = init_sel_ngc, )) - -u16 party_game_bitflag = 0; - -// Variable-precision SWAR algorithm -// Source: https://stackoverflow.com/a/109025 -u32 number_of_unlocked_party_games(u32 i) { - i = i - ((i >> 1) & 0x55555555); // add pairs of bits - i = (i & 0x33333333) + ((i >> 2) & 0x33333333);// quads - i = (i + (i >> 4)) & 0x0F0F0F0F; // groups of 8 - return (i * 0x01010101) >> 24; // horizontal sum of bytes -} - -// Party game IDs do not match their menu positions, hence this ugly mess -u32 determine_party_game_unlock_status(int id) { - switch (id) { - case 0xa: - return (party_game_bitflag & 0x40); - case 0x9: - return (party_game_bitflag & 0x80); - case 0xd: - return (party_game_bitflag & 0x100); - case 0xc: - return (party_game_bitflag & 0x200); - case 0xf: - return (party_game_bitflag & 0x400); - case 0x10: - return (party_game_bitflag & 0x800); - default: - return 0; - } -} - -void init_sel_ngc() { - patch::hook_function(mkb::g_check_if_partygame_unlocked, determine_party_game_unlock_status); - patch::write_word(reinterpret_cast(0x808f9154), PPC_INSTR_LI(PPC_R0, (~party_game_bitflag & 0x3f))); - - mkb::strcpy(mkb::CANNOT_SELECT_PARTY_GAME_STRING, "You cannot play this game\n in this custom pack."); - mkb::strcpy(mkb::CAN_PURCHASE_PARTY_GAME_STRING, "You cannot unlock this game\n in this custom pack."); - mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_STRING, "You can play /bcff8000/%d/bcffff00/ party games!", - number_of_unlocked_party_games(party_game_bitflag)); -} - -}// namespace party_game_toggle diff --git a/src/patches/custom/party_game_toggle.h b/src/patches/custom/party_game_toggle.h deleted file mode 100644 index 152525b2..00000000 --- a/src/patches/custom/party_game_toggle.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -#include "mkb/mkb.h" - -namespace party_game_toggle { - -void init_sel_ngc(); -extern u16 party_game_bitflag; - -}// namespace party_game_toggle \ No newline at end of file diff --git a/src/patches/fixes/fix_widescreen.cpp b/src/patches/fixes/fix_widescreen.cpp index ff609ba8..eab6b7d3 100644 --- a/src/patches/fixes/fix_widescreen.cpp +++ b/src/patches/fixes/fix_widescreen.cpp @@ -193,11 +193,10 @@ void init_main_loop() { // The SEL_NGC check fixes less being visible vertically when playing in widescreen. // It only activates when we're not in menus as calibration breaks visually otherwise. -// The MD_GAME check fixes the View Stage aspect ratio when in widescreen. The STORY_MODE -// check nulls out the FINAL STAGE text for the load-in to prevent it from displaying -// when one-stage difficulties are present and the rest changes the JUMP TO STAGE and -// continues remaining sprite position pointers and values in widescreen since there's -// not enough space in their create functions to add a widescreen translation field +// The MD_GAME check fixes the View Stage aspect ratio when in widescreen.The rest +// changes the JUMP TO STAGE and continues remaining sprite position pointers and values +// in widescreen since there's not enough space in their create functions to add a +// widescreen translation field void tick() { if (mkb::sub_mode == mkb::SMD_SEL_NGC_MAIN) { diff --git a/src/patches/removals/remove_playpoints.cpp b/src/patches/removals/remove_playpoints.cpp index d4bf6bb7..f21d3a53 100644 --- a/src/patches/removals/remove_playpoints.cpp +++ b/src/patches/removals/remove_playpoints.cpp @@ -11,6 +11,7 @@ TICKABLE_DEFINITION(( .name = "remove-playpoints", .description = "Playpoint removal patch", .init_main_game = init_main_game, + .init_sel_ngc = init_sel_ngc, .tick = tick, )) void init_main_game() { @@ -26,6 +27,11 @@ void init_main_game() { patch::write_nop(reinterpret_cast(0x80274c94)); } +void init_sel_ngc() { + // Disables gift menu + patch::write_nop(reinterpret_cast(0x808f9890)); +} + void tick() { mkb::unlock_info.party_games = 0x0001b600; } diff --git a/src/patches/removals/remove_playpoints.h b/src/patches/removals/remove_playpoints.h index 694d79a8..2d2421b9 100644 --- a/src/patches/removals/remove_playpoints.h +++ b/src/patches/removals/remove_playpoints.h @@ -3,6 +3,7 @@ namespace remove_playpoints { void init_main_game(); +void init_sel_ngc(); void tick(); }// namespace remove_playpoints \ No newline at end of file diff --git a/src/patches/story/story_char_select.cpp b/src/patches/story/story_char_select.cpp index 8edca099..daba527e 100644 --- a/src/patches/story/story_char_select.cpp +++ b/src/patches/story/story_char_select.cpp @@ -116,4 +116,4 @@ void init_sel_ngc() { }); } -}// namespace story_char_select +}// namespace story_char_select \ No newline at end of file diff --git a/src/patches/tweaks/double_stage_select.cpp b/src/patches/story/story_double_stage_select.cpp similarity index 94% rename from src/patches/tweaks/double_stage_select.cpp rename to src/patches/story/story_double_stage_select.cpp index e150fb81..2739b2e1 100644 --- a/src/patches/tweaks/double_stage_select.cpp +++ b/src/patches/story/story_double_stage_select.cpp @@ -1,14 +1,14 @@ -#include "double_stage_select.h" +#include "story_double_stage_select.h" #include "../internal/pad.h" #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" -namespace double_stage_select { +namespace story_double_stage_select { TICKABLE_DEFINITION(( .name = "double-stage-select", - .description = "Double stage select", + .description = "Story mode double stage select", .init_main_loop = init, .tick = tick)) @@ -72,4 +72,4 @@ void tick() { patch::write_word(reinterpret_cast(0x80273ad0), 0x3803ffff); } } -}// namespace double_stage_select \ No newline at end of file +}// namespace story_double_stage_select \ No newline at end of file diff --git a/src/patches/story/story_double_stage_select.h b/src/patches/story/story_double_stage_select.h new file mode 100644 index 00000000..bf71bb09 --- /dev/null +++ b/src/patches/story/story_double_stage_select.h @@ -0,0 +1,6 @@ +#pragma once + +namespace story_double_stage_select { +void init(); +void tick(); +}// namespace story_double_stage_select \ No newline at end of file diff --git a/src/patches/tweaks/double_stage_select.h b/src/patches/tweaks/double_stage_select.h deleted file mode 100644 index 2a059f50..00000000 --- a/src/patches/tweaks/double_stage_select.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace double_stage_select { -void init(); -void tick(); -}// namespace double_stage_select \ No newline at end of file diff --git a/src/patches/tweaks/menu_reflections.cpp b/src/patches/tweaks/menu_reflections.cpp index e7feb8a9..e7eb9071 100644 --- a/src/patches/tweaks/menu_reflections.cpp +++ b/src/patches/tweaks/menu_reflections.cpp @@ -5,8 +5,6 @@ #include "mkb/mkb.h" // Enables reflective surfaces on the menu. Experimental and I don't really know why this works. -// Assumes the menu stage slot is 3 or 201. -// TODO: If/when I make a patch/toggle for changing the menu BG stage slots, don't hardcode the value. namespace menu_reflections { TICKABLE_DEFINITION(( From 33c599070046b89fadc46188349c853336632f27 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Sat, 18 Jan 2025 13:51:32 -0800 Subject: [PATCH 37/96] Some patch renames for consistency --- src/patches/fixes/fix_stobj_draw.cpp | 2 +- src/patches/story/story_any_percent_fix.cpp | 2 +- src/patches/story/story_double_stage_select.cpp | 2 +- src/patches/story/story_missing_w_fix.cpp | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/patches/fixes/fix_stobj_draw.cpp b/src/patches/fixes/fix_stobj_draw.cpp index 608dbd9e..bb4383f4 100644 --- a/src/patches/fixes/fix_stobj_draw.cpp +++ b/src/patches/fixes/fix_stobj_draw.cpp @@ -13,7 +13,7 @@ namespace fix_stobj_draw { */ TICKABLE_DEFINITION(( - .name = "stobj-draw-fix", + .name = "fix-stobj-draw", .description = "Stobj draw fix patch", .init_main_loop = init_main_loop, )) diff --git a/src/patches/story/story_any_percent_fix.cpp b/src/patches/story/story_any_percent_fix.cpp index 822d8079..8d13260a 100644 --- a/src/patches/story/story_any_percent_fix.cpp +++ b/src/patches/story/story_any_percent_fix.cpp @@ -8,7 +8,7 @@ namespace story_any_percent_fix { TICKABLE_DEFINITION(( - .name = "fix-any-percent-crash", + .name = "story-any-percent-fix", .description = "Story mode any-percent crash fix", .init_main_loop = init_main_loop, .tick = tick, )) diff --git a/src/patches/story/story_double_stage_select.cpp b/src/patches/story/story_double_stage_select.cpp index 2739b2e1..5f2e48a1 100644 --- a/src/patches/story/story_double_stage_select.cpp +++ b/src/patches/story/story_double_stage_select.cpp @@ -7,7 +7,7 @@ namespace story_double_stage_select { TICKABLE_DEFINITION(( - .name = "double-stage-select", + .name = "story-double-stage-select", .description = "Story mode double stage select", .init_main_loop = init, .tick = tick)) diff --git a/src/patches/story/story_missing_w_fix.cpp b/src/patches/story/story_missing_w_fix.cpp index 7838929b..ba277168 100644 --- a/src/patches/story/story_missing_w_fix.cpp +++ b/src/patches/story/story_missing_w_fix.cpp @@ -8,7 +8,7 @@ namespace story_missing_w_fix { TICKABLE_DEFINITION(( - .name = "fix-missing-w", + .name = "story-fix-missing-w", .description = "Missing 'w' patch", .init_main_game = init_main_game, )) From 599011ca44e27ab9a6e56741aa1e33ace01ca562 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Sat, 18 Jan 2025 14:15:23 -0800 Subject: [PATCH 38/96] Update theme ID list and config --- configs/default-config.txt | 207 +++++++++++++++++++++++++------------ docs/theme-id-list.txt | 12 +-- 2 files changed, 149 insertions(+), 70 deletions(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index ad4675a0..67d8d0cc 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 0.3.1! +// This is the config file for Workshop Mod 1.0.0! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // @@ -22,14 +22,13 @@ // remove-desert-haze // // Removes the heat haze on levels in theme ID 7 (sand). -// Indirectly fixes the widescreen issue with heat haze. // story-mode-music-fix // // Prevents the world music from being interrupted by the stage select music // in Story Mode. -// no-music-vol-decrease-on-pause +// remove-music-vol-decrease-on-pause // // Prevents the music volume from being lowered when the game is paused. @@ -37,33 +36,20 @@ // // Allows the player to select between the four playable monkeys in Story Mode. -// no-hurry-up-music +// remove-hurry-up-music // // Stops the 'hurry up' music from playing. -// fix-revolution-slot -// -// Removes hardcoded elements from Revolution's level slot. - -// fix-labyrinth-camera -// -// Fixes the lower-angle camera hardcoded to Labyrinth's level slot. - // challenge-mode-death-count // // Challenge mode has infinite lives, and the life counter is converted into // a counter that tracks the number of deaths. -// disable-how-to-play-screen +// remove-how-to-play-screen // // Disables the tutorial/ranking sequence that shows up when the player goes // idle at the title screen. -// fix-wormhole-surfaces -// -// Fixes an issue where wormhole surfaces do not appear on stage IDs 130 -// through 180, and stage ID 199. - // fix-stage-object-reflection // // Fixes an issue where goal posts would not reflect properly, and makes any @@ -86,7 +72,7 @@ // Draws theme ID data from a per-stage list, defined below, instead of using // the built-in list. -// skip-intro-movie +// remove-intro-movie // // Skips the AV logo and intro movie sequence on game start, immediately // skipping to the title screen. @@ -95,12 +81,12 @@ // // Allows for the SMB1 camera to be toggled with the Z button mid-game. -// fix-missing-w +// story-fix-missing-w // // Replaces the misplaced 't' letter in the story mode data entry screen with // the correct letter, a lowercase 'w'. -// skip-cutscenes +// remove-story-cutscenes // // Skips the cutscenes in story mode. @@ -114,15 +100,15 @@ // Fixes an issue with the storm theme where rain droplet splashes would not appear // correctly on the continue platform. -// fix-any-percent-crash +// story-any-percent-fix // // Fixes an issue where skipping more than two or three stages in story mode with the // any% skip glitch would lead to the game crashing. Please note that this allows for // up to 99 skips to be performed. -// party-game-toggle +// menu-option-toggle // -// Permanently enables or disables party games based off the Party Game Toggles +// Permanently enables or disables various menu options based off the Menu Option Toggles // list, defined below. // enable-menu-reflections @@ -136,7 +122,7 @@ // the end cutscene will play, or the credits sequence will start if the cutscene skip // patch is enabled. The minimum value is 1, and the maximum value is 10. -// stobj-draw-fix +// fix-stobj-draw // // Stage objects (stobjs) like party balls and goaltapes may show up incorrectly // or not at all if they reside on an itemgroup whose index is >127. This patch @@ -159,7 +145,82 @@ // // Fixes an issue where widescreen would display less vertically compared to // 4:3. Additionally fixes View Stage stretching and Sand's haze breaking in -// widescreen. Sprites will be fixed in the future. +// widescreen. More sprites will be fixed in the future. + +// stage-name-subtitles +// +// Allows subtitles for stagenames to be displayed underneath the lower-left +// stagename. Subtitles are read from stgname/subtitles.txt + +// challenge-mode-retry +// +// Adds a retry option to Challenge Mode's pausemenu. Only accessible during +// gameplay, when the player has fallen out or when the player has ran out of time + +// goal-texture-scroll +// +// Allows goal models to have texture scroll based on their Item Group's texture scroll +// values + +// load-extra-bg-files +// +// Allows extra background .gma and .tpls to be read for theme IDs which were missing them +// as well as separate multiple theme IDs which read the same set of background files to load +// their own + +// fix-bonus-sprite +// +// Fixes an issue where the 'BONUS STAGE' sprite would disappear upon respawn on a bonus stage +// in Practice Mode + +// fix-goal-types +// +// Fixes an issue with goal type reading on stages with more than three goals + +// fix-monkey-counter +// +// Fix weird animation issues with the monkey counter when going from 4 to 3 lives +// as well as its missing shadow + +// fix-transparency-type-b-texture-scroll +// +// Fix an issue where stage models with bitflag 0x10 would not support texture scroll + +// remove-1up-sprite +// +// Remove the intrusive 1UP sprite + +// remove-ball-rolling-sound +// +// Removes the ball rolling sound during gameplay, similar to SMBDX + +// remove-challenge-cutscenes +// +// Removes the ending cutscenes from Challenge Mode + +// remove-extras +// +// Removes extras when playing Challenge Mode + +// remove-stage-slot-hardcodes +// +// Removes various stage slot hardcodes which made certain slots 'unusable' +// when creating custom stages + +// remove-ice-fog +// +// Removes hardcoded fog from the Ice theme (theme ID 8) + +// story-double-stage-select +// +// Adds an extra 'Stage select' button to Story Mode's pausemenu in place +// of the 'Exit game' button and moves the 'Exit game' button to replace +// 'How to play' + +// pause-cooldown +// +// Adds a one-second interval where the player cannot pause after pausing once +// during gameplay // ---------------------------------------------------------------------------- @@ -167,37 +228,48 @@ // 'disabled' - Does not apply the patch # REL Patches { - perfect-bonus-completion: disabled - remove-desert-haze: disabled - story-mode-music-fix: disabled - no-music-vol-decrease-on-pause: disabled - story-mode-char-select: disabled - no-hurry-up-music: disabled - fix-revolution-slot: disabled - fix-labyrinth-camera: disabled - challenge-mode-death-count: disabled - disable-how-to-play-screen: disabled - fix-wormhole-surfaces: disabled - fix-stage-object-reflection: disabled - enhance-reflective-surfaces: disabled custom-music-id: disabled custom-theme-id: disabled - skip-intro-movie: disabled + menu-option-toggle: disabled + menu-stage-id: 201 + challenge-mode-retry: disabled + challenge-mode-death-count: disabled + four-digit-banana-counter: disabled + goal-texture-scroll: disabled + load-extra-bg-files: disabled smb1-camera-toggle: disabled - fix-missing-w: disabled - skip-cutscenes: 0 - remove-playpoints: disabled - fix-storm-continue-platform: disabled - fix-any-percent-crash: disabled - party-game-toggle: disabled - enable-menu-reflections: disabled - custom-world-count: 10 - stobj-draw-fix: disabled stage-name-subtitles: disabled - fix-view-stage: disabled - four-digit-banana-counter: disabled + fix-bonus-sprite: disabled + fix-final-stage: disabled + fix-goal-types: disabled fix-minimap-color: disabled + fix-monkey-counter: disabled + fix-stobj-draw: disabled + fix-stage-object-reflection: disabled + fix-storm-continue-platform: disabled + fix-transparency-type-b-texture-scroll: disabled + fix-view-stage: disabled fix-widescreen: disabled + remove-1up-sprite: disabled + remove-ball-rolling-sound: disabled + remove-challenge-cutscenes: disabled + remove-desert-haze: disabled + remove-extras: disabled + remove-stage-slot-hardcodes: disabled + remove-hurry-up-music: disabled + remove-ice-fog: disabled + remove-intro-cutscene: disabled + remove-playpoints: disabled + remove-story-cutscenes: disabled + remove-tutorial: disabled + remove-volume-decrease-on-pause: disabled + story-any-percent-fix: disabled + story-mode-char-select: disabled + story-mode-music-fix: disabled + story-double-stage-select: disabled + story-fix-missing-w: disabled + pause-cooldown: disabled + perfect-bonus-completion: disabled } // Toggles which party games are accessible from the party game menu. @@ -205,19 +277,26 @@ // cannot be unlocked or accessed. // Requires the patch 'party-game-toggle' to be enabled. -# Party Game Toggles { - monkey-race: disabled - monkey-fight: disabled - monkey-target: disabled - monkey-billiards: disabled - monkey-bowling: disabled - monkey-golf: disabled - monkey-boat: disabled - monkey-shot: disabled - monkey-dogfight: disabled - monkey-soccer: disabled - monkey-baseball: disabled - monkey-tennis: disabled +# Menu Option Toggles { + party-games: enabled + story-mode: enabled + challenge-mode: enabled + beginner: enabled + advanced: enabled + expert: enabled + master: enabled + monkey-race: enabled + monkey-fight: enabled + monkey-target: enabled + monkey-billiards: enabled + monkey-bowling: enabled + monkey-golf: enabled + monkey-boat: enabled + monkey-shot: enabled + monkey-dogfight: enabled + monkey-soccer: enabled + monkey-baseball: enabled + monkey-tennis: enabled } // Stage ID to theme ID mapping. Theme IDs are in decimal. diff --git a/docs/theme-id-list.txt b/docs/theme-id-list.txt index 35efebbf..53e1f7ff 100644 --- a/docs/theme-id-list.txt +++ b/docs/theme-id-list.txt @@ -1,7 +1,7 @@ Credits to Eucalyptus for this list. Background file names in parentheses. 00 Default - Background objects don't load. -01 Early Volcanic Magma - Background objects don't load. +01 Early Volcanic Magma - Does not load a background .gma/.tpl; will load (bg_lav) with load-extra-bg-files 02 Jungle (bg_jun) - Has lens flare. 03 Water (bg_wat) - Has water effects. 04 Night (bg_nig) - Texture scroll on background and foreground objects is weird in this theme ID. @@ -12,7 +12,7 @@ Credits to Eucalyptus for this list. Background file names in parentheses. 09 Storm (bg_stm) - Has rain, flame objects appear inside bumpers. Crashes if BG does not contain flame objects 10 Bonus 1 (bg_bns) - Crashes unless the .lz references BNS_MAIN. 11 Monkey Target (bg_pil) - Crashes unless the .lz references PIL_SEA_A. -12 Monkey Billiards - Does not load a background .gma/.tpl. +12 Monkey Billiards - Does not load a background .gma/.tpl; will load (bg_bil) with load-extra-bg-files 13 Monkey Golf (bg_gol) - bg_gol.gma/.tpl needs to manually be added in. 14 Monkey Bowling (bg_bow) 15 Master (bg_mst) @@ -30,15 +30,15 @@ Credits to Eucalyptus for this list. Background file names in parentheses. 27 Monkey Soccer (bg_fut2) - Crashes in debug mode stage select, works during gameplay. 28 Monkey Bowling 2 (bg_bow2) 29 Monkey Target 2 (bg_tar2) - Crashes unless the .lz references TAR_SEA_A. -30 Monkey Billiards 2 - Does not load a background .gma/.tpl. -31 Monkey Boat - Does not load a background .gma/.tpl. +30 Monkey Billiards 2 - Does not load a background .gma/.tpl; will load (bg_bil2) with load-extra-bg-files +31 Monkey Boat - Does not load a background .gma/.tpl; will load (bg_boa2) with load-extra-bg-files 32 Inside A Whale (bg_wha2) - Has special lighting rules. 33 Monkey Golf 2 (bg_gol2) -34 Monkey Fight 2 - Boiling Pot (bg_pot2) +34 Monkey Fight 2 - Boiling Pot (bg_pot2); will load (bg_au_pot2) with load-extra-bg-files 35 Jungle Village (bg_vil2) - bg_vil2.gma/.tpl needs to manually be added in. 36 Cutscene - Bubbly Washing Machine (bg_au_bub2) 37 Cutscene - Amusement Park (bg_au_par2) 38 Cutscene - Clock Tower Factory (bg_au_gea2) - Stages should not switch between the vanilla background and custom. 39 Cutscene - Under The Ocean (bg_au_wat2) - Has water and particle effects. 40 Cutscene - Monkey Target 2 (bg_au_tar2) - Crashes unless the .lz references TAR_SEA_A. -41 Cutscene - Monkey Bowling 2 (bg_bow2) \ No newline at end of file +41 Cutscene - Monkey Bowling 2 (bg_bow2); will load (bg_au_bow2) with load-extra-bg-files \ No newline at end of file From a4e5c10abfcc8aea71365b4fb6cc162deef4cf7f Mon Sep 17 00:00:00 2001 From: Eucalyptus <118875105+Eucalyptusmoon@users.noreply.github.com> Date: Sat, 18 Jan 2025 14:19:50 -0800 Subject: [PATCH 39/96] Update README.md --- README.md | 17 +++-------------- 1 file changed, 3 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 9b185cbc..d718c7d2 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ # :confetti_ball: SMB2 Workshop Mod -An extension of ComplexPlane's [Super Monkey Ball 2 mod, ApeSphere](htps://github.com/ComplexPlane/ApeSphere), adding -features useful to custom pack creators. Includes the original practice mod, as well as quality-of-life and +A variant of ComplexPlane's [Super Monkey Ball 2 mod, PracticeMod](htps://github.com/ComplexPlane/SMB2PracticeMod), adding +features useful to custom pack creators. Includes quality-of-life and feature-adding patches, and easier options for tweaking in-game variables. Features include: @@ -14,21 +14,10 @@ Features include: * Patch that automatically skips story mode cutscenes * And more miscellaneous patches! -Original ApeSphere features included: - -* Console savestates -* An RTA timer that tracks time spent paused -* An individual-world practice mode -* Frame advance -* [Jump mod](https://www.youtube.com/watch?v=kWAunK6Av-Q) - -...and more to come! - Planned upcoming features: * Difficulty rearrangement in configuration file * Lighting modification in configuration file -* Double 'Stage Select' REL patch * Ultimate mode patch * Custom party game configuration (lap timer, course names, etc) * Custom stage timers @@ -40,7 +29,7 @@ Instructions for setup and usage of this mod are located in the [relevant section](https://docs.google.com/document/d/194QZxrimkjHEzSSMKbafs86PnmiYmFBZUnoaEnks4es/edit#heading=h.t4unx1ftb63d) of the Super Monkey Ball Custom Level Guide. -# Original ApeSphere Credits +# Original PracticeMod Credits Thank you to: From 7a3d892d17af28e6754a3bdd6b6541a47a7d476b Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Sun, 19 Jan 2025 11:05:12 -0800 Subject: [PATCH 40/96] Fix issue with locked main game options --- src/config/config.cpp | 4 ++-- src/patches/custom/menu_option_toggle.cpp | 10 ++++------ 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/src/config/config.cpp b/src/config/config.cpp index 3f2930b0..fdc1aa3b 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -84,10 +84,10 @@ void parse_menu_option_toggles(char* buf) { menu_option_toggle::party_game_bitflag |= 0x800; else if KEY_ENABLED ("party-games") menu_option_toggle::mode_bitflag &= ~0x2; - else if KEY_ENABLED ("challenge-mode") - menu_option_toggle::main_game_bitflag &= ~0x2; else if KEY_ENABLED ("story-mode") menu_option_toggle::main_game_bitflag &= ~0x1; + else if KEY_ENABLED ("challenge-mode") + menu_option_toggle::main_game_bitflag &= ~0x2; else if KEY_ENABLED ("beginner") menu_option_toggle::level_bitflag &= ~0x1; else if KEY_ENABLED ("advanced") diff --git a/src/patches/custom/menu_option_toggle.cpp b/src/patches/custom/menu_option_toggle.cpp index 54a62bbf..af3838d7 100644 --- a/src/patches/custom/menu_option_toggle.cpp +++ b/src/patches/custom/menu_option_toggle.cpp @@ -57,10 +57,8 @@ void init_sel_ngc() { mkb::strcpy(mkb::CANNOT_SELECT_PARTY_GAME_STRING, "You cannot play this game\n in this custom pack."); mkb::strcpy(mkb::CAN_PURCHASE_PARTY_GAME_STRING, "You cannot unlock this game\n in this custom pack."); if (mode_bitflag == 0x2) { - mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_STRING, "Play the Main Game!", - number_of_unlocked_party_games(party_game_bitflag)); - mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING, "Play the Main Game!", - number_of_unlocked_party_games(party_game_bitflag)); + mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_STRING, "Play the Main Game!"); + mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING, "Play the Main Game!"); } else { mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_STRING, "You can play /bcff8000/%d/bcffff00/ party games!", @@ -68,10 +66,10 @@ void init_sel_ngc() { mkb::sprintf(mkb::CAN_PLAY_NUM_PARTY_GAMES_NEED_UNLOCK_STRING, "You can play /bcff8000/%d/bcffff00/ party games!", number_of_unlocked_party_games(party_game_bitflag)); } - if (main_game_bitflag |= 0x1) { + if (main_game_bitflag & 0x1) { mkb::sprintf(mkb::MENU_STORY_DESCRIPTION_TEXT, "Play Challenge Mode!"); } - else if (main_game_bitflag |= 0x2) { + else if (main_game_bitflag & 0x2) { mkb::sprintf(mkb::MENU_CHALLENGE_DESCRIPTION_TEXT, "Play Story Mode!"); } } From 1e16cc32df840a76fa2e6d0ce510ebedb44df4f6 Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Sun, 19 Jan 2025 11:09:51 -0800 Subject: [PATCH 41/96] Update config --- configs/default-config.txt | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index 67d8d0cc..726063b3 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 1.0.0! +// This is the config file for Workshop Mod 1.0.1! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // @@ -55,7 +55,7 @@ // Fixes an issue where goal posts would not reflect properly, and makes any // stage object with the effect bitflag 0x4 reflect in a reflective stage object. -// enhance-reflective-surfaces +// enhance-reflective-surfaces (CURRENTLY UNAVAILABLE) // // Allows for arbitrarily many mirror planes on a stage, rendering the mirror plane // from the origin of the reflective object nearest to the player. Also applies the @@ -111,12 +111,12 @@ // Permanently enables or disables various menu options based off the Menu Option Toggles // list, defined below. -// enable-menu-reflections +// enable-menu-reflections (CURRENTLY UNAVAILABLE) // // Allows for the stages that appear in the background of the menu, stages 3 and 201, // to have mirrors in the background. This is experimental and may cause issues. -// custom-world-count +// custom-world-count (CURRENTLY UNAVAILABLE) // // Allows for the number of worlds in story mode to be modified. After the final world, // the end cutscene will play, or the credits sequence will start if the cutscene skip @@ -173,6 +173,11 @@ // Fixes an issue where the 'BONUS STAGE' sprite would disappear upon respawn on a bonus stage // in Practice Mode +// fix-final-stage +// +// Fixes various issues with final stage, such as the sprite appearing in Story Mode under certain +// conditions and issues when a final stage is a bonus stage + // fix-goal-types // // Fixes an issue with goal type reading on stages with more than three goals @@ -272,10 +277,10 @@ perfect-bonus-completion: disabled } -// Toggles which party games are accessible from the party game menu. -// Party games marked with 'disabled' will be permanently disabled, and +// Toggles which menu options are accessible. +// Options marked with 'disabled' will be permanently disabled, and // cannot be unlocked or accessed. -// Requires the patch 'party-game-toggle' to be enabled. +// Requires the patch 'menu-option-toggle' to be enabled. # Menu Option Toggles { party-games: enabled From 769f9e2ee6c37e1b4a7075014ab53d4adf8e34dc Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Tue, 21 Jan 2025 21:30:56 -0800 Subject: [PATCH 42/96] Update subtitles --- configs/default-subtitles.txt | 842 +++++++++++++++++----------------- 1 file changed, 421 insertions(+), 421 deletions(-) diff --git a/configs/default-subtitles.txt b/configs/default-subtitles.txt index cd5e4638..c84919c4 100644 --- a/configs/default-subtitles.txt +++ b/configs/default-subtitles.txt @@ -1,421 +1,421 @@ -by: STAGE 0 -by: STAGE 1 -by: STAGE 2 -by: STAGE 3 -by: STAGE 4 -by: STAGE 5 -by: STAGE 6 -by: STAGE 7 -by: STAGE 8 -by: STAGE 9 -by: STAGE 10 -by: STAGE 11 -by: STAGE 12 -by: STAGE 13 -by: STAGE 14 -by: STAGE 15 -by: STAGE 16 -by: STAGE 17 -by: STAGE 18 -by: STAGE 19 -by: STAGE 20 -by: STAGE 21 -by: STAGE 22 -by: STAGE 23 -by: STAGE 24 -by: STAGE 25 -by: STAGE 26 -by: STAGE 27 -by: STAGE 28 -by: STAGE 29 -by: STAGE 30 -by: STAGE 31 -by: STAGE 32 -by: STAGE 33 -by: STAGE 34 -by: STAGE 35 -by: STAGE 36 -by: STAGE 37 -by: STAGE 38 -by: STAGE 39 -by: STAGE 40 -by: STAGE 41 -by: STAGE 42 -by: STAGE 43 -by: STAGE 44 -by: STAGE 45 -by: STAGE 46 -by: STAGE 47 -by: STAGE 48 -by: STAGE 49 -by: STAGE 50 -by: STAGE 51 -by: STAGE 52 -by: STAGE 53 -by: STAGE 54 -by: STAGE 55 -by: STAGE 56 -by: STAGE 57 -by: STAGE 58 -by: STAGE 59 -by: STAGE 60 -by: STAGE 61 -by: STAGE 62 -by: STAGE 63 -by: STAGE 64 -by: STAGE 65 -by: STAGE 66 -by: STAGE 67 -by: STAGE 68 -by: STAGE 69 -by: STAGE 70 -by: STAGE 71 -by: STAGE 72 -by: STAGE 73 -by: STAGE 74 -by: STAGE 75 -by: STAGE 76 -by: STAGE 77 -by: STAGE 78 -by: STAGE 79 -by: STAGE 80 -by: STAGE 81 -by: STAGE 82 -by: STAGE 83 -by: STAGE 84 -by: STAGE 85 -by: STAGE 86 -by: STAGE 87 -by: STAGE 88 -by: STAGE 89 -by: STAGE 90 -by: STAGE 91 -by: STAGE 92 -by: STAGE 93 -by: STAGE 94 -by: STAGE 95 -by: STAGE 96 -by: STAGE 97 -by: STAGE 98 -by: STAGE 99 -by: STAGE 100 -by: STAGE 101 -by: STAGE 102 -by: STAGE 103 -by: STAGE 104 -by: STAGE 105 -by: STAGE 106 -by: STAGE 107 -by: STAGE 108 -by: STAGE 109 -by: STAGE 110 -by: STAGE 111 -by: STAGE 112 -by: STAGE 113 -by: STAGE 114 -by: STAGE 115 -by: STAGE 116 -by: STAGE 117 -by: STAGE 118 -by: STAGE 119 -by: STAGE 120 -by: STAGE 121 -by: STAGE 122 -by: STAGE 123 -by: STAGE 124 -by: STAGE 125 -by: STAGE 126 -by: STAGE 127 -by: STAGE 128 -by: STAGE 129 -by: STAGE 130 -by: STAGE 131 -by: STAGE 132 -by: STAGE 133 -by: STAGE 134 -by: STAGE 135 -by: STAGE 136 -by: STAGE 137 -by: STAGE 138 -by: STAGE 139 -by: STAGE 140 -by: STAGE 141 -by: STAGE 142 -by: STAGE 143 -by: STAGE 144 -by: STAGE 145 -by: STAGE 146 -by: STAGE 147 -by: STAGE 148 -by: STAGE 149 -by: STAGE 150 -by: STAGE 151 -by: STAGE 152 -by: STAGE 153 -by: STAGE 154 -by: STAGE 155 -by: STAGE 156 -by: STAGE 157 -by: STAGE 158 -by: STAGE 159 -by: STAGE 160 -by: STAGE 161 -by: STAGE 162 -by: STAGE 163 -by: STAGE 164 -by: STAGE 165 -by: STAGE 166 -by: STAGE 167 -by: STAGE 168 -by: STAGE 169 -by: STAGE 170 -by: STAGE 171 -by: STAGE 172 -by: STAGE 173 -by: STAGE 174 -by: STAGE 175 -by: STAGE 176 -by: STAGE 177 -by: STAGE 178 -by: STAGE 179 -by: STAGE 180 -by: STAGE 181 -by: STAGE 182 -by: STAGE 183 -by: STAGE 184 -by: STAGE 185 -by: STAGE 186 -by: STAGE 187 -by: STAGE 188 -by: STAGE 189 -by: STAGE 190 -by: STAGE 191 -by: STAGE 192 -by: STAGE 193 -by: STAGE 194 -by: STAGE 195 -by: STAGE 196 -by: STAGE 197 -by: STAGE 198 -by: STAGE 199 -by: STAGE 200 -by: STAGE 201 -by: STAGE 202 -by: STAGE 203 -by: STAGE 204 -by: STAGE 205 -by: STAGE 206 -by: STAGE 207 -by: STAGE 208 -by: STAGE 209 -by: STAGE 210 -by: STAGE 211 -by: STAGE 212 -by: STAGE 213 -by: STAGE 214 -by: STAGE 215 -by: STAGE 216 -by: STAGE 217 -by: STAGE 218 -by: STAGE 219 -by: STAGE 220 -by: STAGE 221 -by: STAGE 222 -by: STAGE 223 -by: STAGE 224 -by: STAGE 225 -by: STAGE 226 -by: STAGE 227 -by: STAGE 228 -by: STAGE 229 -by: STAGE 230 -by: STAGE 231 -by: STAGE 232 -by: STAGE 233 -by: STAGE 234 -by: STAGE 235 -by: STAGE 236 -by: STAGE 237 -by: STAGE 238 -by: STAGE 239 -by: STAGE 240 -by: STAGE 241 -by: STAGE 242 -by: STAGE 243 -by: STAGE 244 -by: STAGE 245 -by: STAGE 246 -by: STAGE 247 -by: STAGE 248 -by: STAGE 249 -by: STAGE 250 -by: STAGE 251 -by: STAGE 252 -by: STAGE 253 -by: STAGE 254 -by: STAGE 255 -by: STAGE 256 -by: STAGE 257 -by: STAGE 258 -by: STAGE 259 -by: STAGE 260 -by: STAGE 261 -by: STAGE 262 -by: STAGE 263 -by: STAGE 264 -by: STAGE 265 -by: STAGE 266 -by: STAGE 267 -by: STAGE 268 -by: STAGE 269 -by: STAGE 270 -by: STAGE 271 -by: STAGE 272 -by: STAGE 273 -by: STAGE 274 -by: STAGE 275 -by: STAGE 276 -by: STAGE 277 -by: STAGE 278 -by: STAGE 279 -by: STAGE 280 -by: STAGE 281 -by: STAGE 282 -by: STAGE 283 -by: STAGE 284 -by: STAGE 285 -by: STAGE 286 -by: STAGE 287 -by: STAGE 288 -by: STAGE 289 -by: STAGE 290 -by: STAGE 291 -by: STAGE 292 -by: STAGE 293 -by: STAGE 294 -by: STAGE 295 -by: STAGE 296 -by: STAGE 297 -by: STAGE 298 -by: STAGE 299 -by: STAGE 300 -by: STAGE 301 -by: STAGE 302 -by: STAGE 303 -by: STAGE 304 -by: STAGE 305 -by: STAGE 306 -by: STAGE 307 -by: STAGE 308 -by: STAGE 309 -by: STAGE 310 -by: STAGE 311 -by: STAGE 312 -by: STAGE 313 -by: STAGE 314 -by: STAGE 315 -by: STAGE 316 -by: STAGE 317 -by: STAGE 318 -by: STAGE 319 -by: STAGE 320 -by: STAGE 321 -by: STAGE 322 -by: STAGE 323 -by: STAGE 324 -by: STAGE 325 -by: STAGE 326 -by: STAGE 327 -by: STAGE 328 -by: STAGE 329 -by: STAGE 330 -by: STAGE 331 -by: STAGE 332 -by: STAGE 333 -by: STAGE 334 -by: STAGE 335 -by: STAGE 336 -by: STAGE 337 -by: STAGE 338 -by: STAGE 339 -by: STAGE 340 -by: STAGE 341 -by: STAGE 342 -by: STAGE 343 -by: STAGE 344 -by: STAGE 345 -by: STAGE 346 -by: STAGE 347 -by: STAGE 348 -by: STAGE 349 -by: STAGE 350 -by: STAGE 351 -by: STAGE 352 -by: STAGE 353 -by: STAGE 354 -by: STAGE 355 -by: STAGE 356 -by: STAGE 357 -by: STAGE 358 -by: STAGE 359 -by: STAGE 360 -by: STAGE 361 -by: STAGE 362 -by: STAGE 363 -by: STAGE 364 -by: STAGE 365 -by: STAGE 366 -by: STAGE 367 -by: STAGE 368 -by: STAGE 369 -by: STAGE 370 -by: STAGE 371 -by: STAGE 372 -by: STAGE 373 -by: STAGE 374 -by: STAGE 375 -by: STAGE 376 -by: STAGE 377 -by: STAGE 378 -by: STAGE 379 -by: STAGE 380 -by: STAGE 381 -by: STAGE 382 -by: STAGE 383 -by: STAGE 384 -by: STAGE 385 -by: STAGE 386 -by: STAGE 387 -by: STAGE 388 -by: STAGE 389 -by: STAGE 390 -by: STAGE 391 -by: STAGE 392 -by: STAGE 393 -by: STAGE 394 -by: STAGE 395 -by: STAGE 396 -by: STAGE 397 -by: STAGE 398 -by: STAGE 399 -by: STAGE 400 -by: STAGE 401 -by: STAGE 402 -by: STAGE 403 -by: STAGE 404 -by: STAGE 405 -by: STAGE 406 -by: STAGE 407 -by: STAGE 408 -by: STAGE 409 -by: STAGE 410 -by: STAGE 411 -by: STAGE 412 -by: STAGE 413 -by: STAGE 414 -by: STAGE 415 -by: STAGE 416 -by: STAGE 417 -by: STAGE 418 -by: STAGE 419 -by: STAGE 420 +STAGE 0 +STAGE 1 +STAGE 2 +STAGE 3 +STAGE 4 +STAGE 5 +STAGE 6 +STAGE 7 +STAGE 8 +STAGE 9 +STAGE 10 +STAGE 11 +STAGE 12 +STAGE 13 +STAGE 14 +STAGE 15 +STAGE 16 +STAGE 17 +STAGE 18 +STAGE 19 +STAGE 20 +STAGE 21 +STAGE 22 +STAGE 23 +STAGE 24 +STAGE 25 +STAGE 26 +STAGE 27 +STAGE 28 +STAGE 29 +STAGE 30 +STAGE 31 +STAGE 32 +STAGE 33 +STAGE 34 +STAGE 35 +STAGE 36 +STAGE 37 +STAGE 38 +STAGE 39 +STAGE 40 +STAGE 41 +STAGE 42 +STAGE 43 +STAGE 44 +STAGE 45 +STAGE 46 +STAGE 47 +STAGE 48 +STAGE 49 +STAGE 50 +STAGE 51 +STAGE 52 +STAGE 53 +STAGE 54 +STAGE 55 +STAGE 56 +STAGE 57 +STAGE 58 +STAGE 59 +STAGE 60 +STAGE 61 +STAGE 62 +STAGE 63 +STAGE 64 +STAGE 65 +STAGE 66 +STAGE 67 +STAGE 68 +STAGE 69 +STAGE 70 +STAGE 71 +STAGE 72 +STAGE 73 +STAGE 74 +STAGE 75 +STAGE 76 +STAGE 77 +STAGE 78 +STAGE 79 +STAGE 80 +STAGE 81 +STAGE 82 +STAGE 83 +STAGE 84 +STAGE 85 +STAGE 86 +STAGE 87 +STAGE 88 +STAGE 89 +STAGE 90 +STAGE 91 +STAGE 92 +STAGE 93 +STAGE 94 +STAGE 95 +STAGE 96 +STAGE 97 +STAGE 98 +STAGE 99 +STAGE 100 +STAGE 101 +STAGE 102 +STAGE 103 +STAGE 104 +STAGE 105 +STAGE 106 +STAGE 107 +STAGE 108 +STAGE 109 +STAGE 110 +STAGE 111 +STAGE 112 +STAGE 113 +STAGE 114 +STAGE 115 +STAGE 116 +STAGE 117 +STAGE 118 +STAGE 119 +STAGE 120 +STAGE 121 +STAGE 122 +STAGE 123 +STAGE 124 +STAGE 125 +STAGE 126 +STAGE 127 +STAGE 128 +STAGE 129 +STAGE 130 +STAGE 131 +STAGE 132 +STAGE 133 +STAGE 134 +STAGE 135 +STAGE 136 +STAGE 137 +STAGE 138 +STAGE 139 +STAGE 140 +STAGE 141 +STAGE 142 +STAGE 143 +STAGE 144 +STAGE 145 +STAGE 146 +STAGE 147 +STAGE 148 +STAGE 149 +STAGE 150 +STAGE 151 +STAGE 152 +STAGE 153 +STAGE 154 +STAGE 155 +STAGE 156 +STAGE 157 +STAGE 158 +STAGE 159 +STAGE 160 +STAGE 161 +STAGE 162 +STAGE 163 +STAGE 164 +STAGE 165 +STAGE 166 +STAGE 167 +STAGE 168 +STAGE 169 +STAGE 170 +STAGE 171 +STAGE 172 +STAGE 173 +STAGE 174 +STAGE 175 +STAGE 176 +STAGE 177 +STAGE 178 +STAGE 179 +STAGE 180 +STAGE 181 +STAGE 182 +STAGE 183 +STAGE 184 +STAGE 185 +STAGE 186 +STAGE 187 +STAGE 188 +STAGE 189 +STAGE 190 +STAGE 191 +STAGE 192 +STAGE 193 +STAGE 194 +STAGE 195 +STAGE 196 +STAGE 197 +STAGE 198 +STAGE 199 +STAGE 200 +STAGE 201 +STAGE 202 +STAGE 203 +STAGE 204 +STAGE 205 +STAGE 206 +STAGE 207 +STAGE 208 +STAGE 209 +STAGE 210 +STAGE 211 +STAGE 212 +STAGE 213 +STAGE 214 +STAGE 215 +STAGE 216 +STAGE 217 +STAGE 218 +STAGE 219 +STAGE 220 +STAGE 221 +STAGE 222 +STAGE 223 +STAGE 224 +STAGE 225 +STAGE 226 +STAGE 227 +STAGE 228 +STAGE 229 +STAGE 230 +STAGE 231 +STAGE 232 +STAGE 233 +STAGE 234 +STAGE 235 +STAGE 236 +STAGE 237 +STAGE 238 +STAGE 239 +STAGE 240 +STAGE 241 +STAGE 242 +STAGE 243 +STAGE 244 +STAGE 245 +STAGE 246 +STAGE 247 +STAGE 248 +STAGE 249 +STAGE 250 +STAGE 251 +STAGE 252 +STAGE 253 +STAGE 254 +STAGE 255 +STAGE 256 +STAGE 257 +STAGE 258 +STAGE 259 +STAGE 260 +STAGE 261 +STAGE 262 +STAGE 263 +STAGE 264 +STAGE 265 +STAGE 266 +STAGE 267 +STAGE 268 +STAGE 269 +STAGE 270 +STAGE 271 +STAGE 272 +STAGE 273 +STAGE 274 +STAGE 275 +STAGE 276 +STAGE 277 +STAGE 278 +STAGE 279 +STAGE 280 +STAGE 281 +STAGE 282 +STAGE 283 +STAGE 284 +STAGE 285 +STAGE 286 +STAGE 287 +STAGE 288 +STAGE 289 +STAGE 290 +STAGE 291 +STAGE 292 +STAGE 293 +STAGE 294 +STAGE 295 +STAGE 296 +STAGE 297 +STAGE 298 +STAGE 299 +STAGE 300 +STAGE 301 +STAGE 302 +STAGE 303 +STAGE 304 +STAGE 305 +STAGE 306 +STAGE 307 +STAGE 308 +STAGE 309 +STAGE 310 +STAGE 311 +STAGE 312 +STAGE 313 +STAGE 314 +STAGE 315 +STAGE 316 +STAGE 317 +STAGE 318 +STAGE 319 +STAGE 320 +STAGE 321 +STAGE 322 +STAGE 323 +STAGE 324 +STAGE 325 +STAGE 326 +STAGE 327 +STAGE 328 +STAGE 329 +STAGE 330 +STAGE 331 +STAGE 332 +STAGE 333 +STAGE 334 +STAGE 335 +STAGE 336 +STAGE 337 +STAGE 338 +STAGE 339 +STAGE 340 +STAGE 341 +STAGE 342 +STAGE 343 +STAGE 344 +STAGE 345 +STAGE 346 +STAGE 347 +STAGE 348 +STAGE 349 +STAGE 350 +STAGE 351 +STAGE 352 +STAGE 353 +STAGE 354 +STAGE 355 +STAGE 356 +STAGE 357 +STAGE 358 +STAGE 359 +STAGE 360 +STAGE 361 +STAGE 362 +STAGE 363 +STAGE 364 +STAGE 365 +STAGE 366 +STAGE 367 +STAGE 368 +STAGE 369 +STAGE 370 +STAGE 371 +STAGE 372 +STAGE 373 +STAGE 374 +STAGE 375 +STAGE 376 +STAGE 377 +STAGE 378 +STAGE 379 +STAGE 380 +STAGE 381 +STAGE 382 +STAGE 383 +STAGE 384 +STAGE 385 +STAGE 386 +STAGE 387 +STAGE 388 +STAGE 389 +STAGE 390 +STAGE 391 +STAGE 392 +STAGE 393 +STAGE 394 +STAGE 395 +STAGE 396 +STAGE 397 +STAGE 398 +STAGE 399 +STAGE 400 +STAGE 401 +STAGE 402 +STAGE 403 +STAGE 404 +STAGE 405 +STAGE 406 +STAGE 407 +STAGE 408 +STAGE 409 +STAGE 410 +STAGE 411 +STAGE 412 +STAGE 413 +STAGE 414 +STAGE 415 +STAGE 416 +STAGE 417 +STAGE 418 +STAGE 419 +STAGE 420 From 755205c14bf108fd813404d7161ed81752e0ca9f Mon Sep 17 00:00:00 2001 From: Eucalyptus Date: Tue, 21 Jan 2025 21:33:55 -0800 Subject: [PATCH 43/96] Fix issues with Revolution slot when using remove-stage-slot-hardcodes --- src/patches/removals/remove_hardcodes.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/patches/removals/remove_hardcodes.cpp b/src/patches/removals/remove_hardcodes.cpp index 1cf8c280..2547a486 100644 --- a/src/patches/removals/remove_hardcodes.cpp +++ b/src/patches/removals/remove_hardcodes.cpp @@ -16,6 +16,10 @@ void init_main_loop() { // Nop a call to handle hardcoded stage object drawing for // SMB2 stages patch::write_nop(reinterpret_cast(0x802c96d8)); + // Revolution hardcode removal + // Always return 'false' for a specific function that checks if the stage ID + // is 348 when determining whether or not to handle level loading specially + patch::write_word(reinterpret_cast(0x802ca9fc), PPC_INSTR_LI(PPC_R3, 0x0)); // Nop a call to handle hardcoded stage lights leftover from // SMB1 patch::write_nop(reinterpret_cast(0x802945d8)); From 0efc973df8cf4c596afaeefeb1f8e631475aa564 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 6 Mar 2025 14:29:38 -0800 Subject: [PATCH 44/96] Update version --- src/internal/version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/version.cpp b/src/internal/version.cpp index 6b157005..8e8cf6f2 100644 --- a/src/internal/version.cpp +++ b/src/internal/version.cpp @@ -2,7 +2,7 @@ namespace version { -const SemVer WSMOD_VERSION = {1, 0, 0}; +const SemVer WSMOD_VERSION = {1, 0, 3}; s32 compare(const SemVer& v1, const SemVer& v2) { if (v1.major < v2.major) return -1; From 97026a359618577092a02c0a77e68700e5bf27d0 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 6 Mar 2025 14:33:04 -0800 Subject: [PATCH 45/96] Make init_main_loop declarations consistent --- src/patches/extensions/challenge_retry.cpp | 4 ++-- src/patches/extensions/challenge_retry.h | 2 +- src/patches/story/story_double_stage_select.cpp | 4 ++-- src/patches/story/story_double_stage_select.h | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index f57e28d1..900fe491 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -10,7 +10,7 @@ namespace challenge_retry { TICKABLE_DEFINITION(( .name = "challenge-mode-retry", .description = "Challenge Mode retry", - .init_main_loop = init)) + .init_main_loop = init_main_loop)) static patch::Tramp s_pause_game_tramp; @@ -135,7 +135,7 @@ void pausemenu_handler() { } } -void init() { +void init_main_loop() { patch::hook_function(s_pause_game_tramp, mkb::pause_game, []() { s_pause_game_tramp.dest(); pausemenu_handler(); diff --git a/src/patches/extensions/challenge_retry.h b/src/patches/extensions/challenge_retry.h index 880c2377..07950587 100644 --- a/src/patches/extensions/challenge_retry.h +++ b/src/patches/extensions/challenge_retry.h @@ -1,5 +1,5 @@ #pragma once namespace challenge_retry { -void init(); +void init_main_loop(); }// namespace challenge_retry \ No newline at end of file diff --git a/src/patches/story/story_double_stage_select.cpp b/src/patches/story/story_double_stage_select.cpp index 5f2e48a1..05209efa 100644 --- a/src/patches/story/story_double_stage_select.cpp +++ b/src/patches/story/story_double_stage_select.cpp @@ -9,7 +9,7 @@ namespace story_double_stage_select { TICKABLE_DEFINITION(( .name = "story-double-stage-select", .description = "Story mode double stage select", - .init_main_loop = init, + .init_main_loop = init_main_loop, .tick = tick)) static patch::Tramp s_check_pause_menu_input_tramp; @@ -43,7 +43,7 @@ void pausemenu_handler(mkb::Sprite* pause_sprite) { } } -void init() { +void init_main_loop() { // Edits behaviors in the function which handles pausemenu selections patch::write_nop(reinterpret_cast(0x802745a4)); patch::write_nop(reinterpret_cast(0x8027457c)); diff --git a/src/patches/story/story_double_stage_select.h b/src/patches/story/story_double_stage_select.h index bf71bb09..af00a8ca 100644 --- a/src/patches/story/story_double_stage_select.h +++ b/src/patches/story/story_double_stage_select.h @@ -1,6 +1,6 @@ #pragma once namespace story_double_stage_select { -void init(); +void init_main_loop(); void tick(); }// namespace story_double_stage_select \ No newline at end of file From 580b1d9e8d5043da54ce0af977a04c8c72377ce5 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 6 Mar 2025 14:34:05 -0800 Subject: [PATCH 46/96] Fix issue when using stage 201 as menu BG --- src/patches/custom/menu_stage_id.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/custom/menu_stage_id.cpp b/src/patches/custom/menu_stage_id.cpp index 57996d83..d104e81e 100644 --- a/src/patches/custom/menu_stage_id.cpp +++ b/src/patches/custom/menu_stage_id.cpp @@ -7,7 +7,7 @@ namespace menu_stage_id { -u16 stage_id = 201; +u16 stage_id = 0; // Always enabled From 615fd36bef9a22197a7fdb3f508b3836d172a25a Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 6 Mar 2025 14:42:35 -0800 Subject: [PATCH 47/96] Fix issue with PERFECT bonus completion when using Challenge Mode retry --- src/patches/extensions/challenge_retry.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index 900fe491..b4169b9d 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -55,7 +55,7 @@ void pausemenu_handler() { if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN || mkb::sub_mode == mkb::SMD_GAME_GOAL_INIT || mkb::sub_mode == mkb::SMD_GAME_GOAL_MAIN || mkb::sub_mode == mkb::SMD_GAME_READY_INIT || mkb::sub_mode == mkb::SMD_GAME_READY_MAIN || - mkb::mode_info.ball_mode == mkb::BALLMODE_ON_BONUS_STAGE || mkb::num_players != 1 || + mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE || mkb::num_players != 1 || mkb::balls[0].monkey_count < 2 || (mkb::mode_info.ball_mode & mkb::BALLMODE_GOALED)) { mkb::pausemenu_entry_counts[1] = 4; mkb::g_current_pause_menu_entry_count = 4; From 9f632b189a1e39a40623acbf2dea7bf4e8592bd8 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 6 Mar 2025 14:45:17 -0800 Subject: [PATCH 48/96] Update scratch --- src/patches/scratch.cpp | 11 ++++++++--- src/patches/scratch.h | 5 ++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/src/patches/scratch.cpp b/src/patches/scratch.cpp index e856de15..eef8db8f 100644 --- a/src/patches/scratch.cpp +++ b/src/patches/scratch.cpp @@ -7,11 +7,16 @@ TICKABLE_DEFINITION(( .name = "scratch", .description = "Scratch", .enabled = false, - .init_main_loop = init, + .init_main_loop = init_main_loop, + .init_main_game = init_main_game, + .init_sel_ngc = init_sel_ngc, + .init_exoption = init_exoption, .tick = tick)) -void init() {} +void init_main_loop() {} +void init_main_game() {} +void init_sel_ngc() {} +void init_exoption() {} void tick() {} -void disp() {} }// namespace scratch diff --git a/src/patches/scratch.h b/src/patches/scratch.h index 35196958..f6878a77 100644 --- a/src/patches/scratch.h +++ b/src/patches/scratch.h @@ -2,7 +2,10 @@ namespace scratch { -void init(); +void init_main_loop(); +void init_main_game(); +void init_sel_ngc(); +void init_exoption(); void tick(); void disp(); From 7680a85769d5bd7def24bde5bf97a5472ebc7d0b Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 13:39:56 -0700 Subject: [PATCH 49/96] Disable Story Mode option in debug menu --- src/internal/tickable.h | 2 +- src/main.cpp | 17 +++++++++++++++++ src/mkb/mkb2.us.lst | 3 +++ src/mkb/mkb2_ghidra.h | 11 +++++++---- 4 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/internal/tickable.h b/src/internal/tickable.h index caa1e2d4..1636884d 100644 --- a/src/internal/tickable.h +++ b/src/internal/tickable.h @@ -27,7 +27,7 @@ namespace tickable { // Capacity of the tickable manager vector, increase if needed // This only stores pointers, so memory impact should be low -constexpr size_t PATCH_CAPACITY = 48; +constexpr size_t PATCH_CAPACITY = 64; // Represents a patch, or code that ticks every frame struct Tickable { diff --git a/src/main.cpp b/src/main.cpp index b2ef2462..6869a317 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -9,6 +9,7 @@ #include "internal/ui/ui_manager.h" #include "internal/version.h" #include "mkb/mkb.h" +#include "utils/ppcutil.h" namespace main { static patch::Tramp s_process_inputs_tramp; @@ -29,6 +30,21 @@ since it reports every frame, and thus clutters the console */ patch::write_nop(reinterpret_cast(0x80299f54)); } +static void disable_debug_story() { + // In the functions which handles selections on the title screen debug menu, + // rid the code which is meant to take us to (broken) Story Mode + patch::write_nop(reinterpret_cast(0x80272120)); + patch::write_nop(reinterpret_cast(0x80272128)); + patch::write_nop(reinterpret_cast(0x80272130)); + patch::write_nop(reinterpret_cast(0x8027211c)); + // Rename the STORY MODE menu option + mkb::DEBUG_MENU_OPTION_NAMES[2] = "Stan Meghan Trainor"; + // Expand the box which holds the menu options + patch::write_word(reinterpret_cast(0x80272310), PPC_INSTR_LI(PPC_R3, 0x23)); + patch::write_word(reinterpret_cast(0x80272360), 0x2c1d0017);// cmpwi r29, 23 + patch::write_word(reinterpret_cast(0x802722d8), 0x2c1d0017);// cmpwi r29, 23 +} + void init() { LOG("SMB2 Workshop Mod v%d.%d.%d loaded", version::WSMOD_VERSION.major, @@ -39,6 +55,7 @@ void init() { modlink::write(); perform_assembly_patches(); + disable_debug_story(); // Load our config file config::parse_config(); diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 3e1d4d47..5a6cd75a 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -8447,6 +8447,7 @@ 8054DB64:g_some_tpl_buffer 8054DB70:g_init_common_tpl_buf 8054DB7C:g_some_nl_model_buffer_2 +8054DB80:g_stage_nl_buf 8054DB88:g_init_common_gma_buf 8054DBB8:scen_info 8054DBBA:active_story_mode_func @@ -8531,6 +8532,7 @@ 8054DF9A:stageselect_storymode_world_idx 8054DF9B:stageselect_course_stage_idx 8054DFA5:stageselect_story_world_stage_idx +8054DFAF:stageselect_category_selected 8054DFE1:g_last_selected_bowling_difficulty 8054DFF0:g_auto_reload_setting 8054E02C:menu_tick_func @@ -9305,6 +9307,7 @@ 809158E0:s_NewApeAllPreLoad:%d 809160E0:switchdataD_804ee064 809162D8:story_mode_funcs +80916E78:ape_story_select_anim_table 80916EE4:switchdataD_804eee68 80916F04:switchdataD_804eee88 80916FEC:switchdataD_804eef70 diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index a7af4051..6e544e25 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5725,7 +5725,7 @@ extern "C" { extern undefined * MAIN_MODE_NAMES[8]; extern undefined * SUB_MODE_NAMES[265]; extern struct RelBufferInfo additional_rel_buffer_info; - extern undefined * DEBUG_MENU_OPTION_NAMES[7]; + extern char * DEBUG_MENU_OPTION_NAMES[7]; extern undefined * switchdataD_80370704; extern undefined * switchdataD_80370758; extern undefined * switchdataD_80370794; @@ -5984,6 +5984,7 @@ extern "C" { extern undefined g_some_tpl_buffer; extern undefined g_init_common_tpl_buf; extern undefined g_some_nl_model_buffer_2; + extern struct NlBuffer * g_stage_nl_buf; extern struct NlBuffer * * g_init_common_gma_buf; extern struct ScenInfo scen_info; extern Mtx * g_ord_tbl_stuff; @@ -6056,6 +6057,7 @@ extern "C" { extern bool stageselect_is_storymode; extern s8 stageselect_course_idx[2]; extern s8 stageselect_course_stage_idx[2][10]; + extern undefined1 stageselect_category_selected; extern undefined1 g_last_selected_bowling_difficulty; extern undefined4 g_auto_reload_setting; extern undefined4 menu_tick_func; @@ -6170,7 +6172,7 @@ extern "C" { extern struct StagedefFileHeader * stagedef; extern undefined2 seesaw_count; extern undefined1 g_something_with_wl; - extern undefined4 stage_tpl; + extern struct TplBuffer * stage_tpl; extern struct GmaBuffer * stage_gma; extern undefined2 current_stage_id; extern char current_stage_name[128]; @@ -6333,6 +6335,7 @@ extern "C" { extern float view_stage_aspect_ratio; extern pointer switchdataD_804ee064; extern undefined * story_mode_funcs; + extern undefined1 ape_story_select_anim_table; extern pointer switchdataD_804eee68; extern pointer switchdataD_804eee88; extern pointer switchdataD_804eef70; @@ -10100,7 +10103,7 @@ extern "C" { void menu_main_game_select_tick(void); void menu_level_select_tick(void); void g_get_some_challenge_mode_difficulty_info(int param_1); - void g_get_some_category_count(int flag, undefined4 * g_out_1, int * g_out_2); + void g_get_some_category_count(int flag, int * g_out_1, int * g_out_2); void menu_stage_select_tick(void); void menu_start_story_mode(void); void menu_start_challenge_mode(void); @@ -10163,7 +10166,7 @@ extern "C" { void sprite_game_settings_tick(u8 * status, struct Sprite * sprite); void sprite_game_settings_disp(struct Sprite * param_1); void sprite_practice_stage_select_tick(u8 * status, struct Sprite * sprite); - void sprite_practice_stage_select_disp(int param_1); + void sprite_practice_stage_select_disp(struct Sprite * sprite); void sprite_fight_stage_select_tick(u8 * status, struct Sprite * sprite); void sprite_fight_stage_select_disp(struct Sprite * param_1); void sprite_button_tick(u8 * status, struct Sprite * sprite); From 00d65ddc2de053e575fb0719bdd801e981defe13 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 15:07:17 -0700 Subject: [PATCH 50/96] Remove 8-4 Story Mode stage select camera hardcode with remove-stage-slot-hardcodes --- dep/ppc-inject/ppc-inject.cabal | 2 +- src/mkb/mkb2.us.lst | 5 +++-- src/mkb/mkb2_ghidra.h | 12 ++++++++++++ src/patches/removals/remove_hardcodes.cpp | 3 +++ 4 files changed, 19 insertions(+), 3 deletions(-) diff --git a/dep/ppc-inject/ppc-inject.cabal b/dep/ppc-inject/ppc-inject.cabal index b6fa97b4..aa2a6144 100755 --- a/dep/ppc-inject/ppc-inject.cabal +++ b/dep/ppc-inject/ppc-inject.cabal @@ -1,4 +1,4 @@ -cabal-version: 1.12 +cabal-version: 1.12 -- This file has been generated from package.yaml by hpack version 0.34.4. -- diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 5a6cd75a..3d0a62a1 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -7980,7 +7980,7 @@ 803DC4E4:clear_unlock_info 803DC520:FUN_803062e8 803DC55C:FUN_80306324 -803DC598:FUN_80306360 +803DC598:unlock_master 803DC5B0:g_is_master_unlocked 803DC5FC:FUN_803063c4 803DC64C:FUN_80306414 @@ -9307,6 +9307,7 @@ 809158E0:s_NewApeAllPreLoad:%d 809160E0:switchdataD_804ee064 809162D8:story_mode_funcs +809168A0:MAIN_GAME_STORY_STAGE_PREVIEW_PARAMS 80916E78:ape_story_select_anim_table 80916EE4:switchdataD_804eee68 80916F04:switchdataD_804eee88 @@ -9941,7 +9942,7 @@ 80912264:FUN_805681cc 80912294:FUN_805681fc 80912510:FUN_80568478 -80912748:FUN_805686b0 +80912748:create_fight_stage_preview_sprites 80912AC4:FUN_80568a2c 80912B24:FUN_80568a8c 80912D1C:FUN_80568c84 diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index 6e544e25..c0f9889a 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -3132,6 +3132,15 @@ struct S32Vec { } __attribute__((__packed__)); static_assert(sizeof(S32Vec) == 0x8); +typedef struct StoryStagePreviewParam StoryStagePreviewParam, *PStoryStagePreviewParam; + +struct StoryStagePreviewParam { /* Used for each stage preview on the Story Mode Stage Select screen */ + s16 stage_id; /* Only used when generating previews through Debug Mode */ + undefined2 field0x2; /* Seems to usually be 0x1000 or 0x1800 */ + float scale; /* Usually 1 with the exception of Entangled Path */ +} __attribute__((__packed__)); +static_assert(sizeof(StoryStagePreviewParam) == 0x8); + enum { OF_G_SMTH_WITH_CAMERA=2, OF_GAME_PAUSED=8 @@ -6335,6 +6344,7 @@ extern "C" { extern float view_stage_aspect_ratio; extern pointer switchdataD_804ee064; extern undefined * story_mode_funcs; + extern struct StoryStagePreviewParam MAIN_GAME_STORY_STAGE_PREVIEW_PARAMS[100]; extern undefined1 ape_story_select_anim_table; extern pointer switchdataD_804eee68; extern pointer switchdataD_804eee88; @@ -9868,6 +9878,7 @@ extern "C" { void g_load_stageselect_after_cutscene(void); void g_preload_next_stage_files(int param_1, int param_2, int param_3); void clear_unlock_info(void); + void unlock_master(void); byte g_is_master_unlocked(void); void empty_function(void); void g_set_unlockables_status(void); @@ -10186,6 +10197,7 @@ extern "C" { void sprite_practice_stage_preview_disp(struct Sprite * sprite); void sprite_practice_stage_preview_mask_disp(u8 * status, struct Sprite * sprite); void create_practice_mode_preview_sprites(void); + void create_fight_stage_preview_sprites(void); void sprite_gamedata_disp(int param_1); void create_gamedata_sprite(void); void menu_option_game_data_tick_child(void); diff --git a/src/patches/removals/remove_hardcodes.cpp b/src/patches/removals/remove_hardcodes.cpp index 2547a486..059a3586 100644 --- a/src/patches/removals/remove_hardcodes.cpp +++ b/src/patches/removals/remove_hardcodes.cpp @@ -64,6 +64,9 @@ void init_main_game() { // Nop a call to handle hardcoded stage object drawing for // SMB2 stages patch::write_nop(reinterpret_cast(0x809140f4)); + // In the array of Story Mode preview settings, normalize Entangled Path's + // scale + mkb::MAIN_GAME_STORY_STAGE_PREVIEW_PARAMS[73].scale = 1; } }// namespace remove_hardcodes From 2176ed824c7efaf25f2097830a0dff3d9fe754cc Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 15:38:21 -0700 Subject: [PATCH 51/96] Allow default behavior with menu stage ID, update config --- configs/default-config.txt | 9 +++++++-- src/config/config.cpp | 2 +- src/patches/custom/menu_stage_id.cpp | 8 ++++---- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index 726063b3..023ccc78 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 1.0.1! +// This is the config file for Workshop Mod 1.0.3! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // @@ -227,6 +227,11 @@ // Adds a one-second interval where the player cannot pause after pausing once // during gameplay +// menu-stage-id +// +// Changes the stage ID used on the main menu. Setting this to -1 will lead to +// default behavior (where the menu stage ID also uses more than one stage ID) + // ---------------------------------------------------------------------------- // 'enabled' - Applies the patch @@ -236,7 +241,7 @@ custom-music-id: disabled custom-theme-id: disabled menu-option-toggle: disabled - menu-stage-id: 201 + menu-stage-id: -1 challenge-mode-retry: disabled challenge-mode-death-count: disabled four-digit-banana-counter: disabled diff --git a/src/config/config.cpp b/src/config/config.cpp index fdc1aa3b..03e1bf2a 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -237,4 +237,4 @@ void parse_config() { } } -}// namespace config +}// namespace config \ No newline at end of file diff --git a/src/patches/custom/menu_stage_id.cpp b/src/patches/custom/menu_stage_id.cpp index d104e81e..05f5956f 100644 --- a/src/patches/custom/menu_stage_id.cpp +++ b/src/patches/custom/menu_stage_id.cpp @@ -7,20 +7,20 @@ namespace menu_stage_id { -u16 stage_id = 0; - -// Always enabled +int stage_id = -1; TICKABLE_DEFINITION(( .name = "menu-stage-id", .description = "Menu stage ID", .active_value = stage_id, - .lower_bound = 1, + .lower_bound = -1, .upper_bound = 420, .init_main_loop = init_main_loop, .init_main_game = init_main_game)) // In functions which handle the menu stage to load, use our stage ID +// If the passed value is 0, the patch is disabled and default behavior +// is used (more than one stage ID is used for these in vanilla) void init_main_loop() { stage_id = *active_tickable_ptr->active_value;// Get our stage ID patch::write_word(reinterpret_cast(0x80282c10), PPC_INSTR_LI(PPC_R31, stage_id)); From 3085f83ec294dcbc6de840193e5fa9c03bb10d83 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 15:39:44 -0700 Subject: [PATCH 52/96] Fix comment --- src/patches/custom/menu_stage_id.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/patches/custom/menu_stage_id.cpp b/src/patches/custom/menu_stage_id.cpp index 05f5956f..903700a9 100644 --- a/src/patches/custom/menu_stage_id.cpp +++ b/src/patches/custom/menu_stage_id.cpp @@ -19,7 +19,7 @@ TICKABLE_DEFINITION(( .init_main_game = init_main_game)) // In functions which handle the menu stage to load, use our stage ID -// If the passed value is 0, the patch is disabled and default behavior +// If the passed value is -1, the patch is disabled and default behavior // is used (more than one stage ID is used for these in vanilla) void init_main_loop() { stage_id = *active_tickable_ptr->active_value;// Get our stage ID From 74fdefc7ac37844ba961626156e2227069ae16ca Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 18:05:00 -0700 Subject: [PATCH 53/96] Fix world count patch --- src/patches/custom/custom_world_count.cpp | 31 ++++++++----------- src/patches/custom/custom_world_count.h | 1 + .../removals/remove_story_cutscenes.cpp | 2 +- 3 files changed, 15 insertions(+), 19 deletions(-) diff --git a/src/patches/custom/custom_world_count.cpp b/src/patches/custom/custom_world_count.cpp index c1a007d1..a3261f2d 100644 --- a/src/patches/custom/custom_world_count.cpp +++ b/src/patches/custom/custom_world_count.cpp @@ -8,43 +8,38 @@ // Allows for the number of worlds in story mode to be customized. namespace custom_world_count { -static u16 DEFAULT_WORLD_COUNT = 10; +static u16 world_count = 10; TICKABLE_DEFINITION(( .name = "custom-world-count", .description = "Custom world count patch", - .active_value = DEFAULT_WORLD_COUNT, + .active_value = world_count, .lower_bound = 1, .upper_bound = 10, + .init_main_loop = init_main_loop, .init_main_game = init_main_game, .init_sel_ngc = init_sel_ngc, )) static patch::Tramp s_sceneplay_init_tramp; -u16 get_world_count() { - if (!active_tickable_ptr->enabled) { - return DEFAULT_WORLD_COUNT; - } - else { - return *active_tickable_ptr->active_value; - } -} void dmd_scen_sceneplay_init_patch() { - if (mkb::scen_info.next_world == get_world_count()) { + if (mkb::main_mode != mkb::MD_AUTHOR) { + if (mkb::scen_info.next_world == world_count) { mkb::scen_info.next_world = 10; + mkb::scen_info.world = 10; + } } s_sceneplay_init_tramp.dest(); } -void init_main_game() { - // mkb::OSReport("set world count to %d\n", get_world_count()); - if (tickable::get_tickable_manager().get_tickable_status("skip-cutscenes")) { - // mkb::OSReport("hooking sceneplay\n"); +void init_main_loop() { + world_count = *active_tickable_ptr->active_value; +} +void init_main_game() { patch::hook_function(s_sceneplay_init_tramp, mkb::dmd_scen_sceneplay_init, dmd_scen_sceneplay_init_patch); - } } void init_sel_ngc() { @@ -52,10 +47,10 @@ void init_sel_ngc() { // Visually update the indicator patch::write_word(reinterpret_cast(0x8090dbd0), - (0x2c1a0000 | *active_tickable_ptr->active_value)); + (0x2c1a0000 | world_count)); // Update the indicator logic patch::write_word(reinterpret_cast(0x80900f08), - PPC_INSTR_LI(PPC_R29, *active_tickable_ptr->active_value)); + PPC_INSTR_LI(PPC_R29, world_count)); } }// namespace custom_world_count diff --git a/src/patches/custom/custom_world_count.h b/src/patches/custom/custom_world_count.h index 6f14a3a1..601b4a2b 100644 --- a/src/patches/custom/custom_world_count.h +++ b/src/patches/custom/custom_world_count.h @@ -4,6 +4,7 @@ namespace custom_world_count { +void init_main_loop(); void init_main_game(); void init_sel_ngc(); u16 get_world_count(); diff --git a/src/patches/removals/remove_story_cutscenes.cpp b/src/patches/removals/remove_story_cutscenes.cpp index 185a9aa2..ba71e3be 100644 --- a/src/patches/removals/remove_story_cutscenes.cpp +++ b/src/patches/removals/remove_story_cutscenes.cpp @@ -13,7 +13,7 @@ TICKABLE_DEFINITION(( .description = "Story Mode cutscene removal", .init_main_game = init_main_game, )) -constexpr auto WORLD_COUNT = 10;// TODO: attach to patch that changes this +constexpr auto WORLD_COUNT = 10; // Skips cutscenes in story mode. // TODO: Maybe fade the screen out so the transition screen color is not based off the world fog From 87112ec74407417bf7b9fb4e9bea5c6be4066213 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 19:10:04 -0700 Subject: [PATCH 54/96] Fix race conditions with Story Mode character select patch for real --- src/patches/story/story_char_select.cpp | 73 ++++++++++--------------- src/patches/story/story_char_select.h | 1 + 2 files changed, 30 insertions(+), 44 deletions(-) diff --git a/src/patches/story/story_char_select.cpp b/src/patches/story/story_char_select.cpp index daba527e..7c1afa8c 100644 --- a/src/patches/story/story_char_select.cpp +++ b/src/patches/story/story_char_select.cpp @@ -13,7 +13,8 @@ TICKABLE_DEFINITION(( .description = "Story mode character select", .init_main_loop = init_main_loop, .init_main_game = init_main_game, - .init_sel_ngc = init_sel_ngc, )) + .init_sel_ngc = init_sel_ngc, + .tick = tick, )) static mkb::undefined4* AIAI[] = {&mkb::CHAR_A, &mkb::CHAR_I, &mkb::CHAR_A, &mkb::CHAR_I, &mkb::CHAR_SPACE, &mkb::CHAR_SPACE}; @@ -27,8 +28,6 @@ static mkb::undefined4* HIHI[] = {&mkb::CHAR_H, &mkb::CHAR_I, &mkb::CHAR_H, &mkb &mkb::CHAR_SPACE}; static mkb::undefined4** monkey_name_lookup[] = {AIAI, MEEMEE, BABY, GONGON, HIHI}; -static bool is_entering_story = false; - // Overrides the return value of certain functions to force the chosen monkey to be // preloaded in place of AiAi void init_main_loop() { @@ -62,13 +61,6 @@ void init_main_game() { patch::write_nop(reinterpret_cast(0x80906370)); patch::write_nop(reinterpret_cast(0x80906374)); patch::write_nop(reinterpret_cast(0x80906378)); - - // Lets the sel_ngc portion of the patch know we aren't entering story anymore - // Also sets menu_stack_ptr to 1, ensuring we return to the Mode Select screen - if (is_entering_story) { - is_entering_story = false; - mkb::sel_menu_info.menu_stack_ptr = 1; - } } // Assign the correct 'next screen' variables to redirect Story Mode to the @@ -77,43 +69,36 @@ void init_main_game() { void init_sel_ngc() { // Patches the 'next screen ID' for the 'STORY MODE' button in the Mode Select screen mkb::menu_main_game_select_entries[0].next_screen_id = mkb::MENUSCREEN_CHARACTER_SELECT_2; - for (int i = 0; i < 4; i++) { - // Patches each of the character button's 'next screen ID' in the character select screen - mkb::menu_character_select_2_entries[i].next_screen_id = mkb::MENUSCREEN_STORY_MODE_SELECTED; - } - static patch::Tramp s_character_select_tick; - patch::hook_function( - s_character_select_tick, - mkb::menu_character_select_tick, []() { - if (mkb::g_currently_visible_menu_screen == mkb::MENUSCREEN_CHARACTER_SELECT_2) { - // If we press A, then we are going to start the process of entering story mode - // We need to update our current position on the menu stack with the character select menu - constexpr size_t ORIGINAL_STACK_INDEX = 2; + // Terminate the description string for Story Mode before the 'Gameplay will begin' mention + patch::write_word(reinterpret_cast(0x8092174b), 0x00000000); +} - if (pad::button_pressed(mkb::PAD_BUTTON_A)) { - mkb::sel_menu_info.menu_stack[ORIGINAL_STACK_INDEX] = mkb::MENUSCREEN_CHARACTER_SELECT_2; - is_entering_story = true; - } - // If we press B, then we are cancelling the process of entering story mode - // We need to clean up since the stack pointer is changed after calling the tick function - // So, we restore the pointer to the original '2' - if (pad::button_pressed(mkb::PAD_BUTTON_B)) { - if (is_entering_story) { - mkb::sel_menu_info.menu_stack_ptr = ORIGINAL_STACK_INDEX; - mkb::g_next_menu_screen = mkb::MENUSCREEN_MAIN_GAME_SELECT; - } - is_entering_story = false; - } - } +void tick() { + // Overwriting the next screen value for the default Practice Mode option causes + // transitions to not work and a few other oddities, so this is a little more + // messy than expected + if (mkb::main_mode == mkb::MD_SEL) { + // If Story Mode is selected on the menu... + if (mkb::g_focused_maingame_menu == 0) { + // ...change the screen stack check for what next screen to throw us at to 0xff + patch::write_word(reinterpret_cast(0x808fbec8), 0x2c0000ff); + // Change the screen stack check for what next screen to throw us at to the Mode Select menu + patch::write_word(reinterpret_cast(0x808fc8a0), 0x2c000007); + // Change the next screen value to the one for entering Story Mode + patch::write_word(reinterpret_cast(0x808fc8e0), 0x38a0000c); - s_character_select_tick.dest(); + } + else { + // Original instructions + // Change the screen stack check for what next screen to throw us at to the Mode Select menu + patch::write_word(reinterpret_cast(0x808fbec8), 0x2c000007); + // Change the screen stack check for what next screen to throw us at to the Bowling menu + patch::write_word(reinterpret_cast(0x808fc8a0), 0x2c000024); + // Change the next screen value to the one for entering Bowling + patch::write_word(reinterpret_cast(0x808fc8e0), 0x38a00027); - if (mkb::g_currently_visible_menu_screen == mkb::MENUSCREEN_CHARACTER_SELECT_2) { - // We have to do this hacky nonsense to get the game to think we are entering story mode - // Otherwise, it will display (or rather, attempt to display) the Practice Mode stage select screen - if (is_entering_story) mkb::sel_menu_info.menu_stack_ptr = 1; - } - }); + } + } } }// namespace story_char_select \ No newline at end of file diff --git a/src/patches/story/story_char_select.h b/src/patches/story/story_char_select.h index cd7ef419..bfce92ff 100644 --- a/src/patches/story/story_char_select.h +++ b/src/patches/story/story_char_select.h @@ -5,5 +5,6 @@ namespace story_char_select { void init_main_loop(); void init_main_game(); void init_sel_ngc(); +void tick(); }// namespace story_char_select \ No newline at end of file From 35bb854c7ba71884dfacfbdfe98a91bb436d164a Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 19:28:08 -0700 Subject: [PATCH 55/96] Tidy up string edit for Story Mode character select --- src/patches/story/story_char_select.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/patches/story/story_char_select.cpp b/src/patches/story/story_char_select.cpp index 7c1afa8c..94ff3ba9 100644 --- a/src/patches/story/story_char_select.cpp +++ b/src/patches/story/story_char_select.cpp @@ -5,6 +5,7 @@ #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" +#include "custom/menu_option_toggle.h" namespace story_char_select { @@ -69,8 +70,11 @@ void init_main_game() { void init_sel_ngc() { // Patches the 'next screen ID' for the 'STORY MODE' button in the Mode Select screen mkb::menu_main_game_select_entries[0].next_screen_id = mkb::MENUSCREEN_CHARACTER_SELECT_2; - // Terminate the description string for Story Mode before the 'Gameplay will begin' mention - patch::write_word(reinterpret_cast(0x8092174b), 0x00000000); + // Remove the 'Gameplay will begin' portion of the Story Mode menu description text + if ((menu_option_toggle::main_game_bitflag & 0x1) == 0) { + mkb::strcpy(mkb::MENU_STORY_DESCRIPTION_TEXT, "This mode is only for 1 player. The next world\nwill be available if you clear 10 stages.\n*You will receive Play Points."); + } + } void tick() { From c1cd85ac6980bca8171b5ab580fc8e7deaf08d83 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Mon, 7 Apr 2025 19:28:46 -0700 Subject: [PATCH 56/96] Update config --- configs/default-config.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index 023ccc78..1e613260 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -116,7 +116,7 @@ // Allows for the stages that appear in the background of the menu, stages 3 and 201, // to have mirrors in the background. This is experimental and may cause issues. -// custom-world-count (CURRENTLY UNAVAILABLE) +// custom-world-count // // Allows for the number of worlds in story mode to be modified. After the final world, // the end cutscene will play, or the credits sequence will start if the cutscene skip @@ -240,6 +240,7 @@ # REL Patches { custom-music-id: disabled custom-theme-id: disabled + custom-world-count: 10 menu-option-toggle: disabled menu-stage-id: -1 challenge-mode-retry: disabled From e874c6c3a765b352f0e8f3a3d8b848152896ab00 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 8 Apr 2025 11:20:32 -0700 Subject: [PATCH 57/96] clang-format --- src/main.cpp | 2 +- src/patches/custom/custom_world_count.cpp | 12 ++++++------ src/patches/story/story_char_select.cpp | 20 +++++++++----------- 3 files changed, 16 insertions(+), 18 deletions(-) diff --git a/src/main.cpp b/src/main.cpp index 6869a317..ced2af2e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,7 +31,7 @@ since it reports every frame, and thus clutters the console */ } static void disable_debug_story() { - // In the functions which handles selections on the title screen debug menu, + // In the function which handles selections on the title screen debug menu, // rid the code which is meant to take us to (broken) Story Mode patch::write_nop(reinterpret_cast(0x80272120)); patch::write_nop(reinterpret_cast(0x80272128)); diff --git a/src/patches/custom/custom_world_count.cpp b/src/patches/custom/custom_world_count.cpp index a3261f2d..3af86486 100644 --- a/src/patches/custom/custom_world_count.cpp +++ b/src/patches/custom/custom_world_count.cpp @@ -24,10 +24,10 @@ static patch::Tramp s_sceneplay_init_tr void dmd_scen_sceneplay_init_patch() { if (mkb::main_mode != mkb::MD_AUTHOR) { - if (mkb::scen_info.next_world == world_count) { - mkb::scen_info.next_world = 10; - mkb::scen_info.world = 10; - } + if (mkb::scen_info.next_world == world_count) { + mkb::scen_info.next_world = 10; + mkb::scen_info.world = 10; + } } s_sceneplay_init_tramp.dest(); } @@ -38,8 +38,8 @@ void init_main_loop() { } void init_main_game() { - patch::hook_function(s_sceneplay_init_tramp, - mkb::dmd_scen_sceneplay_init, dmd_scen_sceneplay_init_patch); + patch::hook_function(s_sceneplay_init_tramp, + mkb::dmd_scen_sceneplay_init, dmd_scen_sceneplay_init_patch); } void init_sel_ngc() { diff --git a/src/patches/story/story_char_select.cpp b/src/patches/story/story_char_select.cpp index 94ff3ba9..c2fb18e0 100644 --- a/src/patches/story/story_char_select.cpp +++ b/src/patches/story/story_char_select.cpp @@ -1,11 +1,11 @@ #include "story_char_select.h" +#include "custom/menu_option_toggle.h" #include "internal/assembly.h" #include "internal/pad.h" #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" -#include "custom/menu_option_toggle.h" namespace story_char_select { @@ -74,7 +74,6 @@ void init_sel_ngc() { if ((menu_option_toggle::main_game_bitflag & 0x1) == 0) { mkb::strcpy(mkb::MENU_STORY_DESCRIPTION_TEXT, "This mode is only for 1 player. The next world\nwill be available if you clear 10 stages.\n*You will receive Play Points."); } - } void tick() { @@ -82,25 +81,24 @@ void tick() { // transitions to not work and a few other oddities, so this is a little more // messy than expected if (mkb::main_mode == mkb::MD_SEL) { + // These all change values in menu_character_select_tick // If Story Mode is selected on the menu... - if (mkb::g_focused_maingame_menu == 0) { + if (mkb::g_focused_maingame_menu == 0) { // ...change the screen stack check for what next screen to throw us at to 0xff - patch::write_word(reinterpret_cast(0x808fbec8), 0x2c0000ff); + patch::write_word(reinterpret_cast(0x808fbec8), 0x2c0000ff); // Change the screen stack check for what next screen to throw us at to the Mode Select menu - patch::write_word(reinterpret_cast(0x808fc8a0), 0x2c000007); + patch::write_word(reinterpret_cast(0x808fc8a0), 0x2c000007); // Change the next screen value to the one for entering Story Mode - patch::write_word(reinterpret_cast(0x808fc8e0), 0x38a0000c); - + patch::write_word(reinterpret_cast(0x808fc8e0), 0x38a0000c); } else { // Original instructions // Change the screen stack check for what next screen to throw us at to the Mode Select menu - patch::write_word(reinterpret_cast(0x808fbec8), 0x2c000007); + patch::write_word(reinterpret_cast(0x808fbec8), 0x2c000007); // Change the screen stack check for what next screen to throw us at to the Bowling menu - patch::write_word(reinterpret_cast(0x808fc8a0), 0x2c000024); + patch::write_word(reinterpret_cast(0x808fc8a0), 0x2c000024); // Change the next screen value to the one for entering Bowling - patch::write_word(reinterpret_cast(0x808fc8e0), 0x38a00027); - + patch::write_word(reinterpret_cast(0x808fc8e0), 0x38a00027); } } } From 76750085d8c3e6c7e238de0b72eb5b7321506be1 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Apr 2025 10:55:51 -0700 Subject: [PATCH 58/96] Fix issues with remove-1up-sprite --- src/mkb/mkb2.us.lst | 1 + src/mkb/mkb2_ghidra.h | 1 + src/patches/fixes/fix_widescreen.cpp | 7 ++++++- src/patches/removals/remove_1up_sprite.cpp | 7 +++++-- 4 files changed, 13 insertions(+), 3 deletions(-) diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 3d0a62a1..7d925164 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -8331,6 +8331,7 @@ 8047F7D0:LOADIN_TEXT_FINAL_STAGE 8047F7DC:stage_name_tilde_fmt_string 8047F940:switchdataD_803a96f8 +8047F97C:SPRITE_1UP_TEXT_STRING 804800B4:switchdataD_803a9e6c 804800EC:switchdataD_803a9ea4 80480130:switchdataD_803a9ee8 diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index c0f9889a..a8555a52 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5905,6 +5905,7 @@ extern "C" { extern char LOADIN_TEXT_FINAL_STAGE[12]; extern undefined stage_name_tilde_fmt_string; extern undefined * switchdataD_803a96f8; + extern char SPRITE_1UP_TEXT_STRING[4]; extern undefined * switchdataD_803a9e6c; extern pointer switchdataD_803a9ea4; extern undefined * switchdataD_803a9ee8; diff --git a/src/patches/fixes/fix_widescreen.cpp b/src/patches/fixes/fix_widescreen.cpp index eab6b7d3..bf52d4fe 100644 --- a/src/patches/fixes/fix_widescreen.cpp +++ b/src/patches/fixes/fix_widescreen.cpp @@ -132,7 +132,12 @@ void create_new_1up_sprite(u8* status, mkb::Sprite* sprite) { sprite->widescreen_translation_x = 0x140; sprite->para1 = 120; sprite->tick_func = mkb::sprite_1up_tick; - mkb::strcpy(sprite->text, "1UP"); + if (tickable::get_tickable_manager().get_tickable_status("remove-1up-sprite")) { + mkb::strcpy(sprite->text, ""); + } + else { + mkb::strcpy(sprite->text, "1UP"); + } } return; } diff --git a/src/patches/removals/remove_1up_sprite.cpp b/src/patches/removals/remove_1up_sprite.cpp index 76a2da0e..64128fef 100644 --- a/src/patches/removals/remove_1up_sprite.cpp +++ b/src/patches/removals/remove_1up_sprite.cpp @@ -2,6 +2,7 @@ #include "internal/patch.h" #include "internal/tickable.h" +#include "mkb/mkb.h" namespace remove_1up_sprite { @@ -10,9 +11,11 @@ TICKABLE_DEFINITION(( .description = "1UP sprite removal", .init_main_loop = init_main_loop, )) -// Nops a call to the function which draws the 1UP sprite +// Null the 1UP sprite's text string +// Some functions associated with the sprite play sound effects, so this is +// The best removal method void init_main_loop() { - patch::write_nop(reinterpret_cast(0x802b8264)); + mkb::strcpy(mkb::SPRITE_1UP_TEXT_STRING, ""); } }// namespace remove_1up_sprite From b7273ca172749a4879e77189a2dc53a6f2c3f054 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Apr 2025 11:07:01 -0700 Subject: [PATCH 59/96] Add 'custom' prefix to menu-stage-id --- configs/default-config.txt | 4 ++-- .../{menu_stage_id.cpp => custom_menu_stage_id.cpp} | 8 ++++---- src/patches/custom/custom_menu_stage_id.h | 8 ++++++++ src/patches/custom/menu_stage_id.h | 8 -------- src/patches/removals/remove_1up_sprite.cpp | 2 +- 5 files changed, 15 insertions(+), 15 deletions(-) rename src/patches/custom/{menu_stage_id.cpp => custom_menu_stage_id.cpp} (86%) create mode 100644 src/patches/custom/custom_menu_stage_id.h delete mode 100644 src/patches/custom/menu_stage_id.h diff --git a/configs/default-config.txt b/configs/default-config.txt index 1e613260..43d79ea5 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -227,7 +227,7 @@ // Adds a one-second interval where the player cannot pause after pausing once // during gameplay -// menu-stage-id +// custom-menu-stage-id // // Changes the stage ID used on the main menu. Setting this to -1 will lead to // default behavior (where the menu stage ID also uses more than one stage ID) @@ -238,11 +238,11 @@ // 'disabled' - Does not apply the patch # REL Patches { + custom-menu-stage-id: -1 custom-music-id: disabled custom-theme-id: disabled custom-world-count: 10 menu-option-toggle: disabled - menu-stage-id: -1 challenge-mode-retry: disabled challenge-mode-death-count: disabled four-digit-banana-counter: disabled diff --git a/src/patches/custom/menu_stage_id.cpp b/src/patches/custom/custom_menu_stage_id.cpp similarity index 86% rename from src/patches/custom/menu_stage_id.cpp rename to src/patches/custom/custom_menu_stage_id.cpp index 903700a9..7bcc55aa 100644 --- a/src/patches/custom/menu_stage_id.cpp +++ b/src/patches/custom/custom_menu_stage_id.cpp @@ -5,13 +5,13 @@ #include "internal/tickable.h" #include "utils/ppcutil.h" -namespace menu_stage_id { +namespace custom_menu_stage_id { int stage_id = -1; TICKABLE_DEFINITION(( - .name = "menu-stage-id", - .description = "Menu stage ID", + .name = "custom-menu-stage-id", + .description = "Custom menu stage ID patch", .active_value = stage_id, .lower_bound = -1, .upper_bound = 420, @@ -32,4 +32,4 @@ void init_main_game() { patch::write_word(reinterpret_cast(0x808fe7d8), PPC_INSTR_LI(PPC_R3, stage_id)); } -}// namespace menu_stage_id +}// namespace custom_menu_stage_id diff --git a/src/patches/custom/custom_menu_stage_id.h b/src/patches/custom/custom_menu_stage_id.h new file mode 100644 index 00000000..561f6115 --- /dev/null +++ b/src/patches/custom/custom_menu_stage_id.h @@ -0,0 +1,8 @@ +#pragma once + +namespace custom_menu_stage_id { + +void init_main_loop(); +void init_main_game(); + +}// namespace custom_menu_stage_id \ No newline at end of file diff --git a/src/patches/custom/menu_stage_id.h b/src/patches/custom/menu_stage_id.h deleted file mode 100644 index 6625839f..00000000 --- a/src/patches/custom/menu_stage_id.h +++ /dev/null @@ -1,8 +0,0 @@ -#pragma once - -namespace menu_stage_id { - -void init_main_loop(); -void init_main_game(); - -}// namespace menu_stage_id \ No newline at end of file diff --git a/src/patches/removals/remove_1up_sprite.cpp b/src/patches/removals/remove_1up_sprite.cpp index 64128fef..6e3ed331 100644 --- a/src/patches/removals/remove_1up_sprite.cpp +++ b/src/patches/removals/remove_1up_sprite.cpp @@ -13,7 +13,7 @@ TICKABLE_DEFINITION(( // Null the 1UP sprite's text string // Some functions associated with the sprite play sound effects, so this is -// The best removal method +// the best removal method void init_main_loop() { mkb::strcpy(mkb::SPRITE_1UP_TEXT_STRING, ""); } From b4c7ce0e7aa8d6c268020cd90da765800d54e4ac Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Apr 2025 11:13:38 -0700 Subject: [PATCH 60/96] Fix 'issue' with story-mode-char-select's string replacement --- src/patches/custom/custom_menu_stage_id.cpp | 2 +- src/patches/story/story_char_select.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/patches/custom/custom_menu_stage_id.cpp b/src/patches/custom/custom_menu_stage_id.cpp index 7bcc55aa..caa6c211 100644 --- a/src/patches/custom/custom_menu_stage_id.cpp +++ b/src/patches/custom/custom_menu_stage_id.cpp @@ -1,4 +1,4 @@ -#include "menu_stage_id.h" +#include "custom_menu_stage_id.h" #include "internal/assembly.h" #include "internal/patch.h" diff --git a/src/patches/story/story_char_select.cpp b/src/patches/story/story_char_select.cpp index c2fb18e0..515a14ce 100644 --- a/src/patches/story/story_char_select.cpp +++ b/src/patches/story/story_char_select.cpp @@ -71,7 +71,7 @@ void init_sel_ngc() { // Patches the 'next screen ID' for the 'STORY MODE' button in the Mode Select screen mkb::menu_main_game_select_entries[0].next_screen_id = mkb::MENUSCREEN_CHARACTER_SELECT_2; // Remove the 'Gameplay will begin' portion of the Story Mode menu description text - if ((menu_option_toggle::main_game_bitflag & 0x1) == 0) { + if ((!tickable::get_tickable_manager().get_tickable_status("menu-option-toggle")) || ((menu_option_toggle::main_game_bitflag & 0x1) == 0)) { mkb::strcpy(mkb::MENU_STORY_DESCRIPTION_TEXT, "This mode is only for 1 player. The next world\nwill be available if you clear 10 stages.\n*You will receive Play Points."); } } From ec9a9f4bf44b5629c8c0fd84a586a1c7f4e14bcb Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Apr 2025 12:16:35 -0700 Subject: [PATCH 61/96] Allow Master to be unlocked when using remove-extras + fix issues with fix-final-stage when using remove-extras --- src/mkb/mkb2.us.lst | 2 +- src/mkb/mkb2_ghidra.h | 4 ++-- src/patches/fixes/fix_final_stage.cpp | 11 ++++++++++- src/patches/removals/remove_extras.cpp | 25 +++++++++++++++++++++++-- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 7d925164..37412607 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -7981,7 +7981,7 @@ 803DC520:FUN_803062e8 803DC55C:FUN_80306324 803DC598:unlock_master -803DC5B0:g_is_master_unlocked +803DC5B0:is_master_unlocked 803DC5FC:FUN_803063c4 803DC64C:FUN_80306414 803DC680:FUN_80306448 diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index a8555a52..ede36172 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -3034,7 +3034,7 @@ struct ModeInfo { /* I don't know what to call this, but there's some important undefined2 g_some_stage_jump_distance; undefined4 bananas_remaining; undefined2 field12_0x28; - undefined2 field13_0x2a; + undefined2 continues_used; undefined2 g_next_stage_id2; s16 cm_stage_id; /* Current challenge mode stage id, updated immediately after finishing stage */ undefined2 field16_0x30; @@ -9880,7 +9880,7 @@ extern "C" { void g_preload_next_stage_files(int param_1, int param_2, int param_3); void clear_unlock_info(void); void unlock_master(void); - byte g_is_master_unlocked(void); + byte is_master_unlocked(void); void empty_function(void); void g_set_unlockables_status(void); void g_handle_goal(void); diff --git a/src/patches/fixes/fix_final_stage.cpp b/src/patches/fixes/fix_final_stage.cpp index 18cd9a0a..7b442ac0 100644 --- a/src/patches/fixes/fix_final_stage.cpp +++ b/src/patches/fixes/fix_final_stage.cpp @@ -80,7 +80,7 @@ void handle_final_bonus() { // If the final stage is a bonus and we get a Bonus Finish or Time Over, do end of difficulty or extra stuff if (((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE) == (mkb::BALLMODE_ON_BONUS_STAGE | mkb::BALLMODE_ON_FINAL_STAGE)) && (mkb::in_practice_mode == false)) { bool start_extras = false; - if (((mkb::mode_flags & mkb::MF_0x1) != mkb::MF_NONE) && (mkb::mode_info.field13_0x2a == 0)) { + if (((mkb::mode_flags & mkb::MF_0x1) != mkb::MF_NONE) && (mkb::mode_info.continues_used == 0)) { start_extras = true; } if (((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_EXTRA_COURSE) != mkb::MF_NONE)) && @@ -94,6 +94,15 @@ void handle_final_bonus() { if ((start_extras) && ((mkb::mode_flags & mkb::MF_PLAYING_MASTER_EX_COURSE) != mkb::MF_NONE)) { start_extras = false; } + if (tickable::get_tickable_manager().get_tickable_status("remove-extras")) { + start_extras = false; + if ((mkb::curr_difficulty == mkb::DIFF_EXPERT) && (mkb::mode_info.continues_used == 0)) { + char is_master_unlocked = mkb::is_master_unlocked(); + if (is_master_unlocked == 0) { + mkb::unlock_master(); + } + } + } if (mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) { if (mkb::mode_info.ball_mode & mkb::BALLMODE_OUT_OF_TIME_RINGOUT | mkb::BALLMODE_FALLEN_OUT | mkb::BALLMODE_CLEARED_BONUS_PERFECT) { if (!start_extras || tickable::get_tickable_manager().get_tickable_status("remove-extras")) { diff --git a/src/patches/removals/remove_extras.cpp b/src/patches/removals/remove_extras.cpp index 9c092e14..34f78dd1 100644 --- a/src/patches/removals/remove_extras.cpp +++ b/src/patches/removals/remove_extras.cpp @@ -11,10 +11,31 @@ TICKABLE_DEFINITION(( .description = "Remove extras", .init_main_game = init_main_game, )) -// Always return 'false' in the function which handles what to do -// once you enter a goal + +void unlock_master() { + if (mkb::main_game_mode == mkb::CHALLENGE_MODE) { + if (mkb::curr_difficulty == mkb::DIFF_EXPERT) { + if ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_FINAL_STAGE) && (mkb::mode_info.continues_used == 0)) { + char is_master_unlocked = mkb::is_master_unlocked(); + if (is_master_unlocked == 0) { + mkb::unlock_master(); + } + } + } + } +} +static patch::Tramp s_smd_game_goal_replay_tick_tramp; + void init_main_game() { + // Always return 'false' for if we're entering the extras + // in the function which handles what to do once you enter a goal patch::write_word(reinterpret_cast(0x808f61a8), PPC_INSTR_LI(PPC_R4, 0x0)); + // The method used for unlocking Master in the vanilla game relies on playing Extras, + // so use our own check + patch::hook_function(s_smd_game_goal_replay_tick_tramp, mkb::smd_game_goal_replay_tick, []() { + s_smd_game_goal_replay_tick_tramp.dest(); + unlock_master(); + }); } }// namespace remove_extras From e666f2465a883638bfdc5e3c680a87081172b995 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Apr 2025 16:02:57 -0700 Subject: [PATCH 62/96] perfect-bonus-completion now adds goal score --- src/patches/tweaks/perfect_bonus.cpp | 20 +++++++++++++++++++- src/patches/tweaks/perfect_bonus.h | 1 + 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/patches/tweaks/perfect_bonus.cpp b/src/patches/tweaks/perfect_bonus.cpp index 32d31211..16b6d648 100644 --- a/src/patches/tweaks/perfect_bonus.cpp +++ b/src/patches/tweaks/perfect_bonus.cpp @@ -10,7 +10,18 @@ namespace perfect_bonus { TICKABLE_DEFINITION(( .name = "perfect-bonus-completion", .description = "Perfect bonus completion", - .init_main_loop = init_main_loop, )) + .init_main_loop = init_main_loop, + .init_main_game = init_main_game)) + +static patch::Tramp s_smd_game_bonus_clear_init_tramp; + +// We want to have the score you'd get for a blue goal to be added so +// there isn't a tradeoff between not getting a banana and going for +// the goal instead +void add_goal_score() { + mkb::mode_info.g_some_timer_frame_remaining_count = mkb::mode_info.stage_time_frames_remaining; + mkb::increment_score(2, 0); +} // If the stage is a bonus stage (ball mode 0x40) and no bananas remain, // end the stage with a perfect (|= 0x228) @@ -28,4 +39,11 @@ void init_main_loop() { }); } +void init_main_game() { + patch::hook_function(s_smd_game_bonus_clear_init_tramp, mkb::smd_game_bonus_clear_init, []() { + add_goal_score(); + s_smd_game_bonus_clear_init_tramp.dest(); + }); +} + }// namespace perfect_bonus \ No newline at end of file diff --git a/src/patches/tweaks/perfect_bonus.h b/src/patches/tweaks/perfect_bonus.h index 2682120a..a3f07179 100644 --- a/src/patches/tweaks/perfect_bonus.h +++ b/src/patches/tweaks/perfect_bonus.h @@ -3,5 +3,6 @@ namespace perfect_bonus { void init_main_loop(); +void init_main_game(); }// namespace perfect_bonus \ No newline at end of file From 324cbde90ad4aa83ce0106ce58dc87127a19e658 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Apr 2025 16:11:10 -0700 Subject: [PATCH 63/96] Update version --- configs/default-config.txt | 2 +- src/internal/version.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index 43d79ea5..cdfed8a5 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 1.0.3! +// This is the config file for Workshop Mod 1.0.4! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // diff --git a/src/internal/version.cpp b/src/internal/version.cpp index 8e8cf6f2..bd2b1f93 100644 --- a/src/internal/version.cpp +++ b/src/internal/version.cpp @@ -2,7 +2,7 @@ namespace version { -const SemVer WSMOD_VERSION = {1, 0, 3}; +const SemVer WSMOD_VERSION = {1, 0, 4}; s32 compare(const SemVer& v1, const SemVer& v2) { if (v1.major < v2.major) return -1; From a46c9985b17c96595c266965d3b8265a8e1c9b3a Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 17 Jun 2025 13:58:22 -0700 Subject: [PATCH 64/96] Various fixes --- src/mkb/mkb2_ghidra.h | 2 +- src/patches/fixes/fix_view_stage.cpp | 18 +++++++++++++++--- .../removals/remove_challenge_cutscenes.cpp | 2 ++ src/patches/tweaks/perfect_bonus.cpp | 4 ++++ 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index ede36172..ac0d2d21 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -798,7 +798,7 @@ struct Replay { /* Unknown size atm */ u8 floorNum; u8 monkey; undefined field_0x7[0x9]; - u32 field16_0x10; + u32 score; undefined field_0x14[0x4]; s16 g_stageTimeLimit1; s16 g_duration; diff --git a/src/patches/fixes/fix_view_stage.cpp b/src/patches/fixes/fix_view_stage.cpp index 1b73dbf4..b37e1174 100644 --- a/src/patches/fixes/fix_view_stage.cpp +++ b/src/patches/fixes/fix_view_stage.cpp @@ -41,11 +41,21 @@ void new_render_func(void) { mkb::load_gx_pos_nrm_mtx(mkb::mtxa, 0); pSVar6 = pSVar10->stage_model_b_list; for (iVar7 = 0; iVar7 < (int) pSVar10->stage_model_b_count; iVar7 = iVar7 + 1) { - if (((pSVar6->stage_model_a->some_effect_bitflag & mkb::EFFECT_TRANSPARENCY_A) == mkb::EFFECT_NULL) && (pGVar3 = (mkb::GmaModel*) mkb::g_some_draw_func2((int) pSVar6->stage_model_a), - pGVar3 != (mkb::GmaModel*) 0x0)) { + if (mkb::g_some_render_flag == 0x6) { + if ((pSVar6->stage_model_a->some_effect_bitflag & 0x4) == 0) { + pSVar6 = pSVar6 + 1; + continue; + } + } + + if (((pSVar6->stage_model_a->some_effect_bitflag & mkb::EFFECT_TRANSPARENCY_A) == mkb::EFFECT_NULL) && + (pGVar3 = (mkb::GmaModel*) mkb::g_some_draw_func2((int) pSVar6->stage_model_a), + pGVar3 != (mkb::GmaModel*) 0x0)) { + if (pSVar10->texture_scroll != (mkb::StagedefTextureScroll*) 0x0) { mkb::g_something_with_texture_scroll(pSVar10->texture_scroll); } + if ((pSVar6->stage_model_a->some_effect_bitflag & mkb::EFFECT_TRANSPARENCY_B) == mkb::EFFECT_NULL) { mkb::avdisp_draw_model_culled_sort_never(pGVar3); } @@ -55,8 +65,10 @@ void new_render_func(void) { mkb::g_smth_with_rendefc_reflective_height(0.0); } } + pSVar6 = pSVar6 + 1; } + uVar2 = mkb::g_smth_with_challenge_mode_var_and_3p(); pSVar8 = mkb::stagedef->coli_header_list[iVar9].stage_model_instance_list; mkb::mtxa_push(); @@ -113,4 +125,4 @@ void init_main_game() { patch::write_nop(reinterpret_cast(0x80912d90)); } -}// namespace fix_view_stage +}// namespace fix_view_stage \ No newline at end of file diff --git a/src/patches/removals/remove_challenge_cutscenes.cpp b/src/patches/removals/remove_challenge_cutscenes.cpp index 93857add..f67c3150 100644 --- a/src/patches/removals/remove_challenge_cutscenes.cpp +++ b/src/patches/removals/remove_challenge_cutscenes.cpp @@ -15,7 +15,9 @@ TICKABLE_DEFINITION(( void init_main_game() { patch::write_word(reinterpret_cast(0x808f6274), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); + patch::write_word(reinterpret_cast(0x808f6a70), PPC_INSTR_LI(PPC_R0, mkb::MD_GAME)); patch::write_word(reinterpret_cast(0x808f6284), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); + patch::write_word(reinterpret_cast(0x808f6a80), PPC_INSTR_LI(PPC_R0, mkb::SMD_GAME_ROLL_INIT)); } }// namespace remove_challenge_cutscenes diff --git a/src/patches/tweaks/perfect_bonus.cpp b/src/patches/tweaks/perfect_bonus.cpp index 16b6d648..31a098d6 100644 --- a/src/patches/tweaks/perfect_bonus.cpp +++ b/src/patches/tweaks/perfect_bonus.cpp @@ -19,8 +19,12 @@ static patch::Tramp s_smd_game_bonus_ // there isn't a tradeoff between not getting a banana and going for // the goal instead void add_goal_score() { + int goal_score; + int stored_scores[4]; mkb::mode_info.g_some_timer_frame_remaining_count = mkb::mode_info.stage_time_frames_remaining; mkb::increment_score(2, 0); + goal_score = mkb::get_goal_score(0, stored_scores); + mkb::replay->score += goal_score; } // If the stage is a bonus stage (ball mode 0x40) and no bananas remain, From 37f43ca6bf091fa027dfd7b221e20297ae6dc9fd Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 17 Jun 2025 13:58:55 -0700 Subject: [PATCH 65/96] Update version --- src/internal/version.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/internal/version.cpp b/src/internal/version.cpp index bd2b1f93..2478675b 100644 --- a/src/internal/version.cpp +++ b/src/internal/version.cpp @@ -2,7 +2,7 @@ namespace version { -const SemVer WSMOD_VERSION = {1, 0, 4}; +const SemVer WSMOD_VERSION = {1, 0, 5}; s32 compare(const SemVer& v1, const SemVer& v2) { if (v1.major < v2.major) return -1; From 80a55d21a1cd862ed5a85e52d5625c1b514d6406 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 15:35:50 -0700 Subject: [PATCH 66/96] smb1-camera-toggle now uses a pausemenu option instead of the Z trigger; story-double-stage-select no longer replaces menu options --- src/mkb/mkb2.us.lst | 13 +- src/mkb/mkb2_ghidra.h | 68 ++++++---- src/patches/extensions/challenge_retry.cpp | 45 ++++--- src/patches/extensions/smb1_camera_toggle.cpp | 119 ++++++++++++++++-- .../story/story_double_stage_select.cpp | 81 ++++++++++-- 5 files changed, 268 insertions(+), 58 deletions(-) diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 37412607..8e114d8c 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -5568,7 +5568,7 @@ 8031F328:destroy_sprite_with_unique_id 8031F3E0:dest_all_sprites 8031F47C:get_sprite_with_unique_id -8031F4E0:FUN_802492a8 +8031F4E0:calc_sprite_bounds 8031F9A0:switchD 8031F9A4:caseD_1 8031F9A4:caseD_4 @@ -6246,7 +6246,7 @@ 803399D8:sprite_score_disp 80339B48:FUN_80263910 80339CEC:sprite_timer_ball_tick -8033A02C:FUN_80263df4 +8033A02C:sprite_speed_tick 8033A190:sprite_current_stage_display_tick 8033A2BC:sprite_current_stage_display_disp 8033A908:sprite_hud_stage_name_tick @@ -7062,7 +7062,7 @@ 8037A558:FUN_802a4320 8037A578:FUN_802a4340 8037A5E8:FUN_802a43b0 -8037A608:FUN_802a43d0 +8037A608:g_some_cleanup_func 8037A63C:g_something_with_texture_scroll_2 8037A6A4:FUN_802a446c 8037A6FC:g_stores_doubles @@ -8317,9 +8317,14 @@ 8047EED4:challenge_play_pausemenu_entries 8047EF94:challenge_goal_pausemenu_entries 8047F02C:PAUSEMENU_STAGE_SELECT_STRING +8047F08C:practice_play_pausemenu_entries +8047F11C:practice_goal_pausemenu_entries +8047F20C:PAUSEMENU_GUIDE_STRING 8047F33C:story_play_pausemenu_entries 8047F3CC:story_goal_pausemenu_entries 8047F4A4:pausemenu_entry_pointers +8047F4E4:PAUSEMENU_ON_STRING +8047F4E8:PAUSEMENU_OFF_STRING 8047F770:LOADIN_TEXT_ROUND 8047F77C:LOADIN_TEXT_WORLD 8047F788:LOADIN_TEXT_MASTER_EX @@ -8566,6 +8571,8 @@ 8055399C:g_next_stage_id 8055399E:g_some_cm_stage_id 805539A2:g_some_stage_id +805539AC:practice_best_score +805539B0:is_practice_score_new_best 80553AD8:g_bg_gma 80553ADC:g_bg_tpl 805542EC:active_sprite_draw_req_count diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index ac0d2d21..38fca304 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -1574,10 +1574,10 @@ struct Sprite { f32 fpara3; /* Arbitrary float param 3 */ struct Sprite * prev_sprite; struct Sprite * next_sprite; - undefined4 g_maybe_pos_x; - undefined4 g_maybe_pos_y; - undefined4 field47_0x74; - undefined4 field48_0x78; + s32 left; + s32 top; + s32 right; + s32 bottom; undefined field_0x7c[0x4]; float alpha; /* called trnsl in game? */ struct Rgb24 add_color; @@ -3339,27 +3339,37 @@ typedef undefined4 StageModelEffectBitfield; typedef struct Effect Effect, *PEffect; struct Effect { - word g_idx; + word pool_id; short id; - undefined field_0x4[0x4]; + u32 flags; EffectType type; - undefined field_0xa[0x2]; - s32 field9_0xc; - undefined field_0x10[0x4]; - undefined2 g_ball_idx; - s16 field15_0x16; - undefined field_0x18[0xc]; - struct Vec g_scale; - s32 g_pointer_to_some_struct; - struct Vec g_pos; - struct Vec g_some_vec; - struct S16Vec g_some_rot; - undefined field_0x52[0x6]; + s16 state; + s32 timer; + s32 g_other_timer; + s16 ball_idx; + u16 cameras; + float field9_0x18; + float field10_0x1c; + float field11_0x20; + struct Vec scale; + struct GmaModel * model; + struct Vec pos; + struct Vec vel; + struct S16Vec rot; + s16 field17_0x52; + s16 field18_0x54; + s16 field19_0x56; struct Vec g_prev_pos; - undefined field_0x64[0x28]; - struct Vec g_some_vec2; - struct Vec g_some_vec3; - undefined field_0xa4[0xc]; + struct Vec field21_0x64; + struct Vec field22_0x70; + struct Vec field23_0x7c; + struct Vec field24_0x88; + struct Vec field25_0x94; + s16 field26_0xa0; + s16 field27_0xa2; + s16 field28_0xa4; + float color_factor; + undefined field_0xaa[0x6]; } __attribute__((__packed__)); static_assert(sizeof(Effect) == 0xb0); @@ -3368,7 +3378,7 @@ enum { PMT_CHALLENGE=1, PMT_PRACTICE=2, PMT_UNKNOWN3=3, - PMT_UNKNOWN4=4, + PMT_BILLIARDS=4, PMT_STORY_STAGE_SELECT=5, PMT_STORY_PLAY=6, PMT_UNKNOWN7=7 @@ -5464,7 +5474,7 @@ extern "C" { extern undefined thermal_management_interrupt_exception_handler; extern undefined4 osStringTablePtr; extern pointer switchdataD_80081a8c; - extern struct FontDefinition FONT_DEFINITIONS[64]; + extern struct FontDefinition FONT_DEFINITIONS[144]; extern undefined fullscreen_texture_buf; extern pointer switchdataD_80110c1c; extern undefined * switchdataD_80111e20; @@ -5891,9 +5901,14 @@ extern "C" { extern char * challenge_play_pausemenu_entries[24]; extern char * challenge_goal_pausemenu_entries[24]; extern char PAUSEMENU_STAGE_SELECT_STRING[13]; + extern char * practice_play_pausemenu_entries[36]; + extern char * practice_goal_pausemenu_entries[36]; + extern char PAUSEMENU_GUIDE_STRING[6]; extern char * story_play_pausemenu_entries[36]; extern char * story_goal_pausemenu_entries[36]; extern char * * pausemenu_entry_pointers[16]; + extern char PAUSEMENU_ON_STRING[3]; + extern char PAUSEMENU_OFF_STRING[4]; extern char LOADIN_TEXT_ROUND[9]; extern char LOADIN_TEXT_WORLD[12]; extern char LOADIN_TEXT_MASTER_EX[12]; @@ -6090,6 +6105,8 @@ extern "C" { extern u32 gx_fifo_use_size; extern BOOL32 g_video_mode_change_requested; extern struct ModeInfo mode_info; + extern undefined4 practice_best_score; + extern undefined4 is_practice_score_new_best; extern struct GmaBuffer * g_bg_gma; extern struct TplBuffer * g_bg_tpl; extern undefined4 active_sprite_draw_req_count; @@ -9397,6 +9414,7 @@ extern "C" { void destroy_sprite_with_unique_id(SpriteUniqueID unique_id); void dest_all_sprites(void); Sprite * get_sprite_with_unique_id(SpriteUniqueID unique_id); + void calc_sprite_bounds(struct Sprite * sprite, s32 * left, s32 * top, s32 * right, s32 * bottom); void g_get_font_char_width(char * character, Font32 font, struct FontDefinition * g_font_struct); double g_get_font_char_width_scaling(char * character, Font32 font); void textdraw_reset(void); @@ -9548,6 +9566,7 @@ extern "C" { void sprite_score_tick(u8 * status, struct Sprite * sprite); void sprite_score_disp(struct Sprite * sprite); void sprite_timer_ball_tick(u8 * status, struct Sprite * sprite); + void sprite_speed_tick(u8 * status, struct Sprite * sprite); void sprite_current_stage_display_tick(u8 * status, struct Sprite * sprite); void sprite_current_stage_display_disp(struct Sprite * sprite); void sprite_hud_stage_name_tick(u8 * status, struct Sprite * sprite); @@ -9744,6 +9763,7 @@ extern "C" { void g_some_draw_func3(double param_1); void call_g_avdisp_set_ambient(double param_1, double param_2, double param_3); void avdisp_set_alpha(float param_1); + void g_some_cleanup_func(undefined param_1, undefined param_2, undefined param_3); undefined4 g_something_with_texture_scroll_2(int param_1); void g_stores_doubles(double param_1, double param_2, double param_3, double param_4); void g_stores_doubles2(double param_1, double param_2, double param_3, double param_4); diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index b4169b9d..43df202a 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -10,6 +10,7 @@ namespace challenge_retry { TICKABLE_DEFINITION(( .name = "challenge-mode-retry", .description = "Challenge Mode retry", + .enabled = true, .init_main_loop = init_main_loop)) static patch::Tramp s_pause_game_tramp; @@ -28,20 +29,36 @@ void pausemenu_handler() { static char* menu_options_2[total_size] = {nullptr}; // Strings to be stored in the array - char* options_1[] = { - // Menu strings during gameplay - "Continue game", - "Retry", - "View stage", - "How to play", - "Exit game"}; - char* options_2[] = { - // Menu strings during replay - "Continue game", - "Retry", - "Save replay", - "How to play", - "Exit game"}; + char* options_1[5]; + char* options_2[5]; + + if (!tickable::get_tickable_manager().get_tickable_status("smb1-camera-toggle")) { + options_1[0] = "Continue game"; + options_1[1] = "Retry"; + options_1[2] = "View stage"; + options_1[3] = "How to play"; + options_1[4] = "Exit game"; + + options_2[0] = "Continue game"; + options_2[1] = "Retry"; + options_2[2] = "Save replay"; + options_2[3] = "How to play"; + options_2[4] = "Exit game"; + } + else { + options_1[0] = "Continue game"; + options_1[1] = "Retry"; + options_1[2] = "View stage"; + options_1[3] = "Camera"; + options_1[4] = "Exit game"; + + options_2[0] = "Continue game"; + options_2[1] = "Retry"; + options_2[2] = "Save replay"; + options_2[3] = "Camera"; + options_2[4] = "Exit game"; + } + // Fill the array with strings and gaps of nullptrs int current_index = 0; diff --git a/src/patches/extensions/smb1_camera_toggle.cpp b/src/patches/extensions/smb1_camera_toggle.cpp index 040680bb..aeeac0c7 100644 --- a/src/patches/extensions/smb1_camera_toggle.cpp +++ b/src/patches/extensions/smb1_camera_toggle.cpp @@ -16,14 +16,58 @@ TICKABLE_DEFINITION(( static bool smb1_cam_toggled; +void remove_how_to() { + // Intended behavior for when A is pressed on the ON/OFF menu option + mkb::g_some_pausemenu_var = 0; + mkb::destroy_sprite_with_unique_id(mkb::SPRITE_PAUSE_MENU); + mkb::g_fade_track_volume(100, '\n'); + mkb::g_some_status_bitflag_maybe_pause_related |= 0x20; +} + +void fix_on_off() { + // The code to actually swap between ON/OFF is in the billiards .rel, so we manually recreate it elsewhere + if (mkb::main_mode != mkb::MD_MINI) { + mkb::g_some_status_bitflag_maybe_pause_related ^= 8; + } + // Original function call we branched (plays the sound effect when switching) + mkb::call_SoundReqID_arg_1(0x169); +} + void init_main_loop() { - smb1_cam_toggled = false; + // Remove default behavior of the How to play menu option in... + // Challenge + patch::write_branch_bl(reinterpret_cast(0x80273e5c), reinterpret_cast(remove_how_to)); + patch::write_nop(reinterpret_cast(0x80273df0)); + patch::write_nop(reinterpret_cast(0x80273e00)); + patch::write_nop(reinterpret_cast(0x80273e58)); + patch::write_nop(reinterpret_cast(0x80273e6c)); + // Practice + patch::write_branch_bl(reinterpret_cast(0x80274148), reinterpret_cast(remove_how_to)); + patch::write_nop(reinterpret_cast(0x802740dc)); + patch::write_nop(reinterpret_cast(0x802740ec)); + patch::write_nop(reinterpret_cast(0x80274144)); + patch::write_nop(reinterpret_cast(0x80274158)); + // Story + patch::write_branch_bl(reinterpret_cast(0x802747e0), reinterpret_cast(remove_how_to)); + patch::write_nop(reinterpret_cast(0x80274774)); + patch::write_nop(reinterpret_cast(0x80274784)); + patch::write_nop(reinterpret_cast(0x802747dc)); + patch::write_nop(reinterpret_cast(0x802747f0)); + // Rename the menu option + mkb::challenge_play_pausemenu_entries[12] = "Camera"; + mkb::challenge_goal_pausemenu_entries[12] = "Camera"; + mkb::story_play_pausemenu_entries[18] = "Camera"; + mkb::story_goal_pausemenu_entries[18] = "Camera"; + mkb::practice_play_pausemenu_entries[18] = "Camera"; + mkb::practice_goal_pausemenu_entries[18] = "Camera"; + // Branch to our own code in the function which handles the ON/OFF pausemenu option + patch::write_branch_bl(reinterpret_cast(0x80273878), reinterpret_cast(fix_on_off)); } -// The write_word statement moves the camera's angle down by 2.8 degrees to match SMB1's angle -// Everything else brings the camera position/pivot values in-line with SMB1's values -// Camera mode 1 enables SMB1-like vertical camera tracking, camera mode 0x4c is SMB2's default void tick() { + // The write_word statement moves the camera's angle down by 2.8 degrees to match SMB1's angle + // Everything else brings the camera position/pivot values in-line with SMB1's values + // Camera mode 1 enables SMB1-like vertical camera tracking, camera mode 0x4c is SMB2's default if (mkb::main_mode == mkb::MD_GAME && (mkb::sub_mode == mkb::SMD_GAME_PLAY_MAIN || mkb::sub_mode == mkb::SMD_GAME_READY_MAIN)) { if (smb1_cam_toggled) { @@ -41,9 +85,70 @@ void tick() { mkb::camera_height = 0.8; } } - - if (pad::button_pressed(mkb::PAD_TRIGGER_Z)) { - smb1_cam_toggled = !smb1_cam_toggled; + // This is how ON/OFF is checked in vanilla + if (mkb::g_some_status_bitflag_maybe_pause_related & 8) { + smb1_cam_toggled = true; + } + else { + smb1_cam_toggled = false; + } + // In functions which handle when to display the ON/OFF menu option and when it behaves, + // alter them to check for our current pausemenu and only overwrite the text when not in + // Billiards + if (mkb::pausemenu_type == mkb::PMT_CHALLENGE) { + if ((mkb::g_some_status_bitflag_maybe_pause_related & 4) != 0) { + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0009); + } + else { + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0001); + } + if (mkb::g_current_pause_menu_entry_count == 5) { + // Special handler for CM retry + patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0003); + patch::write_word(reinterpret_cast(0x80273678), 0x2c000003); + } + else { + patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0002); + patch::write_word(reinterpret_cast(0x80273678), 0x2c000002); + } + patch::write_word(reinterpret_cast(0x80273664), 0x2c000001); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, " 1"); + mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "2"); + } + else if (mkb::pausemenu_type == mkb::PMT_STORY_PLAY) { + if ((mkb::g_some_status_bitflag_maybe_pause_related & 4) != 0) { + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b000e); + } + else { + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0006); + } + patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0003); + patch::write_word(reinterpret_cast(0x80273664), 0x2c000006); + patch::write_word(reinterpret_cast(0x80273678), 0x2c000003); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, " 1"); + mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "2"); + } + else if (mkb::pausemenu_type == mkb::PMT_PRACTICE) { + if ((mkb::g_some_status_bitflag_maybe_pause_related & 4) != 0) { + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b000a); + } + else { + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0002); + } + patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0003); + patch::write_word(reinterpret_cast(0x80273664), 0x2c000002); + patch::write_word(reinterpret_cast(0x80273678), 0x2c000003); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, " 1"); + mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "2"); + } + else { + // Original instructions (Billiards) + patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0004); + patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0001); + patch::write_word(reinterpret_cast(0x80273664), 0x2c000004); + patch::write_word(reinterpret_cast(0x80273678), 0x2c000001); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, "ON"); + mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "OFF"); } } }// namespace smb1_camera_toggle diff --git a/src/patches/story/story_double_stage_select.cpp b/src/patches/story/story_double_stage_select.cpp index 05209efa..ffed9c09 100644 --- a/src/patches/story/story_double_stage_select.cpp +++ b/src/patches/story/story_double_stage_select.cpp @@ -20,7 +20,7 @@ static patch::Tramp s_check_pause_menu_i void pausemenu_handler(mkb::Sprite* pause_sprite) { if (mkb::main_game_mode == mkb::STORY_MODE) { // Stage select - if (mkb::g_current_focused_pause_menu_entry == 5 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + if (((mkb::g_current_focused_pause_menu_entry == 5) || (mkb::g_current_focused_pause_menu_entry == 6)) && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { mkb::g_related_to_pause_menu_input = 0x3c; if (pause_sprite != (mkb::Sprite*) 0x0) { pause_sprite->para1 = 2; @@ -32,7 +32,7 @@ void pausemenu_handler(mkb::Sprite* pause_sprite) { mkb::g_screenfade_color = 0xffffff; } // Exit game - else if (mkb::g_current_focused_pause_menu_entry == 3 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { + else if (mkb::g_current_focused_pause_menu_entry == 4 && pad::button_pressed(mkb::PAD_BUTTON_A) && mkb::g_some_status_bitflag_maybe_pause_related != 00000000) { mkb::g_related_to_pause_menu_input = 0x3c; if (pause_sprite != (mkb::Sprite*) 0x0) { pause_sprite->para1 = 3; @@ -44,32 +44,93 @@ void pausemenu_handler(mkb::Sprite* pause_sprite) { } void init_main_loop() { + const int total_size = 42;// Adjust size based on gaps and strings + const int gap_size = 5; // Gap of nullptrs between each string (game expects these to be localized strings) + + // Array of pointers to strings + static char* menu_options_1[total_size] = {nullptr}; + static char* menu_options_2[total_size] = {nullptr}; + + // Strings to be stored in the array + char* options_1[7]; + char* options_2[7]; + + if (!tickable::get_tickable_manager().get_tickable_status("smb1-camera-toggle")) { + options_1[0] = "Continue game"; + options_1[1] = "Retry"; + options_1[2] = "View stage"; + options_1[3] = "How to play"; + options_1[4] = "Exit game"; + options_1[5] = "Stage select"; + options_1[6] = "Stage select"; + + options_2[0] = "Continue game"; + options_2[1] = "Retry"; + options_2[2] = "Save replay"; + options_2[3] = "How to play"; + options_2[4] = "Exit game"; + options_2[5] = "Stage select"; + options_2[6] = "Stage select"; + } + else { + options_1[0] = "Continue game"; + options_1[1] = "Retry"; + options_1[2] = "View stage"; + options_1[3] = "Camera"; + options_1[4] = "Exit game"; + options_1[5] = "Stage select"; + options_1[6] = "Stage select"; + + options_2[0] = "Continue game"; + options_2[1] = "Retry"; + options_2[2] = "Save replay"; + options_2[3] = "Camera"; + options_2[4] = "Exit game"; + options_2[5] = "Stage select"; + options_2[6] = "Stage select"; + } + + + // Fill the array with strings and gaps of nullptrs + int current_index = 0; + for (int i = 0; i < 7; ++i) { + menu_options_1[current_index] = options_1[i]; + menu_options_2[current_index] = options_2[i]; + current_index += gap_size + 1;// Move index by 1 (string) + gap size + } + + mkb::pausemenu_entry_pointers[6] = menu_options_1; + mkb::pausemenu_entry_pointers[14] = menu_options_2; + // Expand entry count + mkb::pausemenu_entry_counts[6] = 7; // Edits behaviors in the function which handles pausemenu selections patch::write_nop(reinterpret_cast(0x802745a4)); - patch::write_nop(reinterpret_cast(0x8027457c)); - patch::write_word(reinterpret_cast(0x8027459c), 0x2c000003);// cmpwi r0, 3 + patch::write_word(reinterpret_cast(0x8027459c), 0x2c000004);// cmpwi r0, 4 // Hook into the function which checks input in the pausemenu for our recreated behaviors patch::hook_function(s_check_pause_menu_input_tramp, mkb::check_pause_menu_input, [](mkb::Sprite* pause_sprite) { s_check_pause_menu_input_tramp.dest(pause_sprite); pausemenu_handler(pause_sprite); }); - // Text changes - mkb::story_play_pausemenu_entries[18] = mkb::PAUSEMENU_EXIT_GAME_STRING; - mkb::story_goal_pausemenu_entries[18] = mkb::PAUSEMENU_EXIT_GAME_STRING; - mkb::story_play_pausemenu_entries[30] = mkb::PAUSEMENU_STAGE_SELECT_STRING; - mkb::story_goal_pausemenu_entries[30] = mkb::PAUSEMENU_STAGE_SELECT_STRING; } void tick() { - // Rids and rearranges some vanilla behaviors for pausemenu selections when in Story Mode if (mkb::main_game_mode == mkb::STORY_MODE && mkb::sub_mode != mkb::SMD_GAME_SCENARIO_MAIN) { + // Rids and rearranges some vanilla behaviors for pausemenu selections when in Story Mode patch::write_word(reinterpret_cast(0x8027513c), 0x3803fffd); patch::write_nop(reinterpret_cast(0x80273ad0)); + // In the function which handles displaying the pausemenu sprite, edit some values so seven + // options at once display properly + patch::write_word(reinterpret_cast(0x8032a5a0), 0x2c000007); + patch::write_word(reinterpret_cast(0x8032a760), 0x2c000007); + patch::write_word(reinterpret_cast(0x8032a768), 0x1c7c0019); } else { // Original instructions patch::write_word(reinterpret_cast(0x8027513c), 0x3803ffff); patch::write_word(reinterpret_cast(0x80273ad0), 0x3803ffff); + patch::write_word(reinterpret_cast(0x8032a5a0), 0x2c000006); + patch::write_word(reinterpret_cast(0x8032a760), 0x2c000006); + patch::write_word(reinterpret_cast(0x8032a768), 0x1c7c001e); } } }// namespace story_double_stage_select \ No newline at end of file From 76868f860c7d2468ad20deb93421bc0314c5db0a Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 15:40:16 -0700 Subject: [PATCH 67/96] Fix minimap bubble and How to play menu in widescreen --- src/patches/fixes/fix_widescreen.cpp | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/patches/fixes/fix_widescreen.cpp b/src/patches/fixes/fix_widescreen.cpp index bf52d4fe..4ab444d3 100644 --- a/src/patches/fixes/fix_widescreen.cpp +++ b/src/patches/fixes/fix_widescreen.cpp @@ -167,6 +167,17 @@ void create_new_final_stage_sprite(u8* status, mkb::Sprite* sprite) { } } +// The mtxa calls in these are the original function calls we branched from +void fix_minimap() { + mkb::mtxa_from_mtxb(); + mkb::g_scale_sprite_for_widescreen(0x248); +} + +void fix_how_to() { + mkb::mtxa_from_identity(); + mkb::g_scale_sprite_for_widescreen(0x140); +} + // Call our fixed create sprite functions in place of the originals, then // enlargen the pausemenu's dim area. Then, handle sprite type changes for // the "JUMP TO STAGE" sprite and continues remaining sprite @@ -189,6 +200,12 @@ void init_main_loop() { patch::write_branch( reinterpret_cast(mkb::create_final_stage_sprite), reinterpret_cast(create_new_final_stage_sprite)); + patch::write_branch_bl( + reinterpret_cast(0x8033c39c), + reinterpret_cast(fix_minimap)); + patch::write_branch_bl( + reinterpret_cast(0x80338050), + reinterpret_cast(fix_how_to)); patch::write_word(reinterpret_cast(0x803e7a28), 0x43b40000); patch::write_word(reinterpret_cast(0x8032e0e4), (0x6400a100)); patch::write_word(reinterpret_cast(0x8032e798), (0x6400a100)); @@ -198,10 +215,11 @@ void init_main_loop() { // The SEL_NGC check fixes less being visible vertically when playing in widescreen. // It only activates when we're not in menus as calibration breaks visually otherwise. -// The MD_GAME check fixes the View Stage aspect ratio when in widescreen.The rest +// The MD_GAME check fixes the View Stage aspect ratio when in widescreen. The rest // changes the JUMP TO STAGE and continues remaining sprite position pointers and values // in widescreen since there's not enough space in their create functions to add a -// widescreen translation field +// widescreen translation field, apart from the last two which edit values in the +// How to play menu void tick() { if (mkb::sub_mode == mkb::SMD_SEL_NGC_MAIN) { @@ -222,12 +240,16 @@ void tick() { patch::write_word(reinterpret_cast(0x8032e048), (0xc01f0038)); patch::write_word(reinterpret_cast(0x8032e6b0), (0xc01f0038)); patch::write_word(reinterpret_cast(0x803e7cf4), (0x43f50000)); + patch::write_word(reinterpret_cast(0x803e82f8), (0x40590000)); + patch::write_word(reinterpret_cast(0x803e8404), (0x44200000)); } else { patch::write_word(reinterpret_cast(0x8032e048), (0xc01f00ac)); patch::write_word(reinterpret_cast(0x803e7a3c), (0x43d98000)); patch::write_word(reinterpret_cast(0x8032e6b0), (0xc01f00ac)); patch::write_word(reinterpret_cast(0x803e7cf4), (0x4414c000)); + patch::write_word(reinterpret_cast(0x803e82f8), (0x405b8000)); + patch::write_word(reinterpret_cast(0x803e8404), (0x44558000)); } } From d87779b0b2eab8ac191d75aa891aa54f4ca72cab Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 15:45:24 -0700 Subject: [PATCH 68/96] Fix Play Point sprites appearing on Continue screen --- src/patches/removals/remove_playpoints.cpp | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/patches/removals/remove_playpoints.cpp b/src/patches/removals/remove_playpoints.cpp index f21d3a53..e0705bcd 100644 --- a/src/patches/removals/remove_playpoints.cpp +++ b/src/patches/removals/remove_playpoints.cpp @@ -25,6 +25,10 @@ void init_main_game() { // Removes playpoint screen when saving game data in story mode. patch::write_nop(reinterpret_cast(0x80274c94)); + + // Removes playpoint message on continue screen. + patch::write_nop(reinterpret_cast(0x808f653c)); + patch::write_word(reinterpret_cast(0x803dcae0), 0x38600001); } void init_sel_ngc() { @@ -34,5 +38,15 @@ void init_sel_ngc() { void tick() { mkb::unlock_info.party_games = 0x0001b600; + // We have to do this hacky stuff to get some Continue screen sprites to work properly + if (mkb::sub_mode == mkb::SMD_GAME_CONTINUE_INIT) { + mkb::g_playpoint_msg_counter = 0x1; + } + else if (mkb::sub_mode == mkb::SMD_GAME_RESTART_INIT || mkb::sub_mode == mkb::SMD_GAME_NAMEENTRY_READY_INIT || mkb::sub_mode == mkb::SMD_GAME_ROLL_INIT) { + mkb::g_playpoint_msg_counter = 0x0; + } + else { + return; + } } -}// namespace remove_playpoints +}// namespace remove_playpoints \ No newline at end of file From 16951f4bb0954223fd7eea470123261a22dd0f94 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 15:48:40 -0700 Subject: [PATCH 69/96] Update version --- src/internal/version.cpp | 2 +- src/patches/extensions/challenge_retry.cpp | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/src/internal/version.cpp b/src/internal/version.cpp index 2478675b..aa8c8c64 100644 --- a/src/internal/version.cpp +++ b/src/internal/version.cpp @@ -2,7 +2,7 @@ namespace version { -const SemVer WSMOD_VERSION = {1, 0, 5}; +const SemVer WSMOD_VERSION = {1, 0, 6}; s32 compare(const SemVer& v1, const SemVer& v2) { if (v1.major < v2.major) return -1; diff --git a/src/patches/extensions/challenge_retry.cpp b/src/patches/extensions/challenge_retry.cpp index 43df202a..ec8a53c9 100644 --- a/src/patches/extensions/challenge_retry.cpp +++ b/src/patches/extensions/challenge_retry.cpp @@ -10,7 +10,6 @@ namespace challenge_retry { TICKABLE_DEFINITION(( .name = "challenge-mode-retry", .description = "Challenge Mode retry", - .enabled = true, .init_main_loop = init_main_loop)) static patch::Tramp s_pause_game_tramp; From e6ebd1585292cdc727f06d17e0ce0facd6b8689f Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 15:50:43 -0700 Subject: [PATCH 70/96] Update config --- configs/default-config.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index cdfed8a5..954418b6 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 1.0.4! +// This is the config file for Workshop Mod 1.0.6! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // From aaa8a48068b2fe771dab39da8173d434dd749d17 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 16:04:48 -0700 Subject: [PATCH 71/96] Remove hardcodes on stage IDs 190 and 200 --- src/patches/removals/remove_hardcodes.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/patches/removals/remove_hardcodes.cpp b/src/patches/removals/remove_hardcodes.cpp index 059a3586..185ab948 100644 --- a/src/patches/removals/remove_hardcodes.cpp +++ b/src/patches/removals/remove_hardcodes.cpp @@ -23,6 +23,10 @@ void init_main_loop() { // Nop a call to handle hardcoded stage lights leftover from // SMB1 patch::write_nop(reinterpret_cast(0x802945d8)); + // Check for stage 0xffff instead of 190 for what stage's .gma/.tpl not to load + patch::write_word(reinterpret_cast(0x802c7350), 0x2c1fffff); + // Check for stage 0xffffffff when enabling a lighting hardcode instead of 200 + patch::write_word(reinterpret_cast(0x80455ff8), 0xffffffff); // In the function which handles Bonus Wave's collision, nop // the part which decides what space has hardcoded collision patch::write_nop(reinterpret_cast(0x802c79b4)); From 367b8a22b4ff50db5f56485a6fc964def2eb8441 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 16 Jul 2025 16:08:09 -0700 Subject: [PATCH 72/96] Update config --- configs/default-config.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index 954418b6..4280a94b 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -79,7 +79,8 @@ // smb1-camera-toggle // -// Allows for the SMB1 camera to be toggled with the Z button mid-game. +// Allows for the SMB1 camera to be toggled through the pausemenu, replacing +// How to play. // story-fix-missing-w // @@ -218,9 +219,8 @@ // story-double-stage-select // -// Adds an extra 'Stage select' button to Story Mode's pausemenu in place -// of the 'Exit game' button and moves the 'Exit game' button to replace -// 'How to play' +// Adds an extra 'Stage select' button to Story Mode's pausemenu at the very bottom +// and moves the 'Exit game' button above both // pause-cooldown // From 9aea8268b696a838aded5df3baa7c5261a14cb5a Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 20 Jan 2026 21:44:01 -0800 Subject: [PATCH 73/96] Update ghidra.h --- src/mkb/mkb2.us.lst | 61 ++-- src/mkb/mkb2_ghidra.h | 432 +++++++++++++++------------ src/patches/fixes/fix_view_stage.cpp | 4 +- 3 files changed, 276 insertions(+), 221 deletions(-) diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 8e114d8c..daec5d97 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -3525,6 +3525,7 @@ 80277FFC:g_draw_func_init 80278044:g_something_with_view_stage 80278130:FUN_801a1ef8 +80278154:fade_color_base_default 80278154:g_some_draw_func 802781CC:FUN_801a1f94 8027820C:FUN_801a1fd4 @@ -4460,14 +4461,14 @@ 802BA5E4:ball_physics_g_something_w_postgoal_blast_up2 802BA6CC:g_move_and_collide 802BA718:g_apply_ball_velocity -802BAA90:collide_with_stage +802BAA90:handle_ball_stage_coli 802BAB98:position_ball 802BAFA0:FUN_801e4d68 802BB120:FUN_801e4ee8 802BB8B0:set_ball_properties 802BB958:ball_collision_stars 802BBF04:init_physicsball_from_ball -802BBFA0:g_copy_physicsball_to_ball +802BBFA0:apply_physicsball_to_ball 802BC004:g_ball_ape_rotation 802BC168:spawn_postgoal_ball_sparkle 802BC30C:g_some_ballfunc @@ -4507,25 +4508,25 @@ 802BF558:caseD_9 802BF558:caseD_b 802BF558:caseD_c -802BF8E8:g_some_ball_stage_coli_func +802BF8E8:collide_ball_with_stage 802BF8E8:stcoli_sub01 -802BFDE4:meshcoli_grid_lookup +802BFDE4:tri_coli_grid_lookup 802BFDE4:stcoli_sub02 -802BFF10:stcoli_sub03 -802C01D0:stcoli_sub04 -802C0518:stcoli_sub05 -802C07B8:stcoli_sub06 -802C096C:stcoli_sub07 +802BFF10:collide_ball_with_tri_face +802C01D0:collide_ball_with_tri_edges +802C0518:collide_ball_with_tri_edge +802C07B8:collide_ball_with_tri_vertices +802C096C:collide_ball_with_tri_vertex 802C0A84:g_some_jamabar_coli_func 802C0A84:stcoli_sub08 -802C1078:g_cylinder_coli_something +802C1078:collide_ball_with_cylinder 802C1078:stcoli_sub09 802C1348:stcoli_sub10 -802C15A0:g_sphere_coli_something +802C15A0:collide_ball_with_sphere 802C15A0:stcoli_sub11 -802C16DC:g_cone_coli_something +802C16DC:collide_ball_with_cone 802C16DC:stcoli_sub12 -802C19AC:g_something_with_physicsball_restitution +802C19AC:collide_ball_with_plane 802C19AC:stcoli_sub13 802C1CEC:line_intersects_rect 802C1CEC:stcoli_sub14 @@ -4541,10 +4542,10 @@ 802C2C8C:stcoli_sub19 802C2EA4:raycast_cylinder 802C2EA4:stcoli_sub20 -802C3254:g_goal_coli_something +802C3254:collide_ball_with_goal 802C3254:stcoli_sub21 -802C34C4:stcoli_sub22 -802C3760:stcoli_sub24 +802C34C4:g_goal_coli_func1 +802C3760:g_goal_coli_func2 802C39A8:stcoli_sub25 802C3DC8:g_draw_stage_collision 802C3DC8:stcoli_sub26 @@ -4558,8 +4559,8 @@ 802C4A18:tf_physball_to_itemgroup_space 802C4A18:stcoli_sub32 802C4C38:FUN_801eea00 -802C4C58:g_something_w_ig_and_coli_headers -802C4CD0:g_something_w_ig_and_coli_headers_2 +802C4C58:g_is_ball_in_ig_coli_range +802C4CD0:g_ball_ig_bound_sphere_overlap 802C4D3C:event_world_init 802C4DE4:event_world_tick 802C4E68:switchD @@ -4589,7 +4590,7 @@ 802C608C:event_stage_init 802C60C8:event_stage_tick 802C631C:event_stage_dest -802C635C:g_advance_itemgroup_anim_frame +802C635C:advance_itemgroup_anim 802C6654:g_advance_stage_animation 802C6AC8:g_transform_some_itemgroup_vec 802C6B64:get_GmaBuffer_entry @@ -4615,7 +4616,7 @@ 802C8464:g_smth_with_stage_anim_groups 802C857C:g_smth_with_buttons 802C85F0:g_init_smth_with_seesaws -802C8694:FUN_801f245c +802C8694:collide_ball_with_seesaws 802C8924:get_seesaw_replay_state_size 802C8940:FUN_801f2708 802C897C:g_smth_with_stage_fog @@ -4758,7 +4759,7 @@ 802D5D9C:FUN_801ffb64 802D5E80:FUN_801ffc48 802D5EC4:FUN_801ffc8c -802D5F24:FUN_801ffcec +802D5F24:g_get_replay_time 802D5F38:FUN_801ffd00 802D61A8:FUN_801fff70 802D62F0:rle_encode @@ -5123,7 +5124,7 @@ 802F5D50:FUN_8021fb18 802F6330:FUN_802200f8 802F6560:FUN_80220328 -802F68AC:FUN_80220674 +802F68AC:wat2_draw_caustics 802F6EB0:FUN_80220c78 802F7264:FUN_8022102c 802F72F4:FUN_802210bc @@ -7056,6 +7057,7 @@ 8037A3BC:g_some_ord_node_func2 8037A498:FUN_802a4260 8037A4D8:FUN_802a42a0 +8037A518:avdisp_set_scale_factor 8037A518:g_some_draw_func3 8037A528:call_g_avdisp_set_ambient 8037A548:avdisp_set_alpha @@ -7065,6 +7067,7 @@ 8037A608:g_some_cleanup_func 8037A63C:g_something_with_texture_scroll_2 8037A6A4:FUN_802a446c +8037A6FC:set_post_mult_color 8037A6FC:g_stores_doubles 8037A74C:g_stores_doubles2 8037A79C:FUN_802a4564 @@ -8241,6 +8244,7 @@ 804742C2:g_something_with_world_theme_5 804742C4:BGApeTable 804742D8:g_smth_with_bg_models +804742EC:background_colors 80474760:bg_init_funcs 8047480C:bg_tick_funcs 804748B8:bg_dest_funcs @@ -8335,8 +8339,11 @@ 8047F7C4:LOADIN_TEXT_FINAL_ROUND 8047F7D0:LOADIN_TEXT_FINAL_STAGE 8047F7DC:stage_name_tilde_fmt_string +8047F804:JUMP_TO_STAGE_STRING 8047F940:switchdataD_803a96f8 8047F97C:SPRITE_1UP_TEXT_STRING +8047FFB4:GO_TO_THE_STAGE_STRING +8048004C:POSTGOAL_SPRITES_STAGE_STRING 804800B4:switchdataD_803a9e6c 804800EC:switchdataD_803a9ea4 80480130:switchdataD_803a9ee8 @@ -8465,6 +8472,7 @@ 8054DBD0:g_some_storymode_func_ptr 8054DBDA:curr_storymode_save_file_idx 8054DBF0:g_ord_tbl_stuff +8054DBF0:ord_tbl_data 8054DBF8:is_more_than_24_mib 8054DC04:g_some_buffer_ptr 8054DC08:g_some_other_heap_lo @@ -8541,6 +8549,9 @@ 8054DFAF:stageselect_category_selected 8054DFE1:g_last_selected_bowling_difficulty 8054DFF0:g_auto_reload_setting +8054E010:bat_first_setting +8054E011:number_of_innings_setting +8054E012:baseball_com_level_setting 8054E02C:menu_tick_func 8054E030:menu_draw_func 8054E034:g_some_sel_ngc_rel_buffer @@ -8661,6 +8672,7 @@ 805BD914:current_world_info 805BD918:g_some_frame_counter 805BD91C:g_some_frame_counter_float +805BD924:g_some_coli_nonsense1 805BD934:g_some_gameplay_flags 805BD974:g_some_draw_var 805BD97C:itemgroups @@ -8911,7 +8923,7 @@ 808FAAAC:smd_game_force_over_init 808FAB2C:smd_game_force_over_tick 808FABA4:FUN_804d2b2c -808FAE68:FUN_804d2df0 +808FAE68:g_maybe_some_goal_func 808FB12C:g_preload_stage_or_results 808FB250:FUN_804d31d8 808FB274:FUN_804d31fc @@ -10121,8 +10133,9 @@ 80929EB0:menu_option_game_data_entries 80929EE4:menu_option_controller_entries 80929F18:menu_option_screen_entries -80929F84:menu_screen_list +80929F80:menu_screen_list 8092AC08:switchdataD_80580b70 +8092ACB4:menu_bmp_ids 8092B45C:SPRITE_BUTTON_LESSON_TEXT 8092B464:SPRITE_BUTTON_TUTORIAL_TEXT 8092D894:switchdataD_805837fc diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index 38fca304..336de21f 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -142,12 +142,16 @@ typedef undefined2 StobjType; typedef struct Vec Vec, *PVec; +typedef struct ColiPlane ColiPlane, *PColiPlane; + typedef struct GmaModel GmaModel, *PGmaModel; typedef struct S16Vec S16Vec, *PS16Vec; typedef signed char s8; +typedef ushort u16; + enum { /* Per-GMA model attributes */ GCMF_ATTR_16BIT=1, GCMF_ATTR_STITCHING_MODEL=4, @@ -156,8 +160,6 @@ enum { /* Per-GMA model attributes */ }; typedef undefined4 GcmfAttributes; -typedef ushort u16; - typedef struct GXTexObj GXTexObj, *PGXTexObj; typedef short s16; @@ -192,6 +194,21 @@ enum { }; typedef undefined4 GXTexFmt; +struct Vec { + float x; + float y; + float z; +} __attribute__((__packed__)); +static_assert(sizeof(Vec) == 0xc); + +struct ColiPlane { + struct Vec point; + struct Vec normal; + u16 g_flags1; + u16 g_flags2; +} __attribute__((__packed__)); +static_assert(sizeof(ColiPlane) == 0x1c); + struct S16Vec { /* Often used for rotations */ s16 x; s16 y; @@ -231,13 +248,6 @@ struct GXTexObj { } __attribute__((__packed__)); static_assert(sizeof(GXTexObj) == 0x20); -struct Vec { - float x; - float y; - float z; -} __attribute__((__packed__)); -static_assert(sizeof(Vec) == 0xc); - struct PhysicsBall { /* A representation of a Ball with just the physics/collision-related info */ dword flags; struct Vec pos; @@ -246,12 +256,10 @@ struct PhysicsBall { /* A representation of a Ball with just the physics/collisi float radius; float acceleration; float restitution; - dword g_jerk; - undefined field_0x38[0xc]; - struct Vec g_some_vec; - undefined field_0x50[0x4]; - dword field25_0x54; - float field26_0x58; + dword hardest_coli_speed; + struct ColiPlane hardest_coli_plane; + dword hardest_coli_ig_idx; + float friction; dword itemgroup_idx; /* The itemgroup that this PhysicsBall is relative to, aka in the local space of */ } __attribute__((__packed__)); static_assert(sizeof(PhysicsBall) == 0x60); @@ -315,6 +323,8 @@ static_assert(sizeof(GmaModel) == 0x40); typedef struct MenuScreen MenuScreen, *PMenuScreen; +typedef uchar u8; + typedef struct MenuEntry MenuEntry, *PMenuEntry; typedef uint uint32_t; @@ -350,10 +360,12 @@ enum { typedef undefined1 MenuScreenID; struct MenuScreen { - struct MenuEntry * menu_entries; /* Nullable */ + u8 field0_0x0; + u8 entry_count; + undefined field_0x2[0x2]; + struct MenuEntry * entries; void * tick; - u32 g_some_bitflag; /* 0x40 repositions stuff and makes stuff up/down controls */ - undefined field_0xc[0x4]; + u32 bitflag; /* 0x40 repositions stuff and makes stuff up/down controls */ } __attribute__((__packed__)); static_assert(sizeof(MenuScreen) == 0x10); @@ -790,8 +802,6 @@ typedef undefined4 DipSwitch; typedef struct Replay Replay, *PReplay; -typedef uchar u8; - struct Replay { /* Unknown size atm */ undefined field_0x0[0x4]; u8 difficulty; @@ -1578,7 +1588,8 @@ struct Sprite { s32 top; s32 right; s32 bottom; - undefined field_0x7c[0x4]; + u16 rot; + u16 field50_0x7e; float alpha; /* called trnsl in game? */ struct Rgb24 add_color; undefined field_0x87[0x1]; @@ -2185,7 +2196,7 @@ struct Ball { int field48_0x108; struct Vec ape_facedir_point; /* The point of interest that the monkey looks at (goal, banana, etc) */ float something_with_ape_facedir; /* Approaches 1 the closer you are to the point of interest */ - struct Vec g_last_collision_normal; /* Maybe inverse of the normal of the last triangle collided with? */ + struct Vec g_last_coli_normal; /* Maybe inverse of the normal of the last triangle collided with? */ undefined field_0x128[0x4]; dword g_race_flags; short g_other_counter; @@ -2293,7 +2304,7 @@ typedef struct Itemgroup Itemgroup, *PItemgroup; struct Itemgroup { /* Contains the current animation-related state of each item group in a stage (each thing corresponding to a collision header in the stagedef) */ dword playback_state; /* Corresponding to the switch playback type which is controlling the item group, see PlaybackState */ - dword anim_frame; + s32 anim_frame; struct Vec position; struct Vec prev_position; struct S16Vec rotation; @@ -3033,7 +3044,7 @@ struct ModeInfo { /* I don't know what to call this, but there's some important undefined2 cm_course_stage_num; /* Current course stage num, updated immediately after completing stage */ undefined2 g_some_stage_jump_distance; undefined4 bananas_remaining; - undefined2 field12_0x28; + u16 death_count; undefined2 continues_used; undefined2 g_next_stage_id2; s16 cm_stage_id; /* Current challenge mode stage id, updated immediately after finishing stage */ @@ -3339,37 +3350,27 @@ typedef undefined4 StageModelEffectBitfield; typedef struct Effect Effect, *PEffect; struct Effect { - word pool_id; + word g_idx; short id; - u32 flags; + undefined field_0x4[0x4]; EffectType type; - s16 state; - s32 timer; - s32 g_other_timer; - s16 ball_idx; - u16 cameras; - float field9_0x18; - float field10_0x1c; - float field11_0x20; - struct Vec scale; - struct GmaModel * model; - struct Vec pos; - struct Vec vel; - struct S16Vec rot; - s16 field17_0x52; - s16 field18_0x54; - s16 field19_0x56; + undefined field_0xa[0x2]; + s32 field9_0xc; + undefined field_0x10[0x4]; + undefined2 g_ball_idx; + s16 field15_0x16; + undefined field_0x18[0xc]; + struct Vec g_scale; + s32 g_pointer_to_some_struct; + struct Vec g_pos; + struct Vec g_some_vec; + struct S16Vec g_some_rot; + undefined field_0x52[0x6]; struct Vec g_prev_pos; - struct Vec field21_0x64; - struct Vec field22_0x70; - struct Vec field23_0x7c; - struct Vec field24_0x88; - struct Vec field25_0x94; - s16 field26_0xa0; - s16 field27_0xa2; - s16 field28_0xa4; - float color_factor; - undefined field_0xaa[0x6]; + undefined field_0x64[0x28]; + struct Vec g_some_vec2; + struct Vec g_some_vec3; + undefined field_0xa4[0xc]; } __attribute__((__packed__)); static_assert(sizeof(Effect) == 0xb0); @@ -3385,6 +3386,16 @@ enum { }; typedef undefined4 PauseMenuType; +typedef struct ShadowReceive ShadowReceive, *PShadowReceive; + +struct ShadowReceive { + void * ptr1; + u16 val1; + u16 val2; + void * ptr2; +} __attribute__((__packed__)); +static_assert(sizeof(ShadowReceive) == 0xc); + typedef struct ytgut ytgut, *Pytgut; struct ytgut { @@ -3442,6 +3453,21 @@ enum { }; typedef undefined2 PlaybackState; +typedef struct OrdTblData OrdTblData, *POrdTblData; + +struct OrdTblData { + Mtx matrices[5]; + struct OrdTblNode * entries; + s32 max_entries; + float depth_offset; + float min_depth; + float max_depth; + struct OrdTblNode * last_entry; + struct OrdTblNode * first_entry; + float depth_range; +} __attribute__((__packed__)); +static_assert(sizeof(OrdTblData) == 0x110); + enum { /* Options for rendering text with font */ TEXTDRAW_FLAG_BORDER=536870912, TEXTDRAW_FLAG_DROP_SHADOW=1073741824, @@ -3800,7 +3826,7 @@ typedef undefined2 StagedefAnimType; typedef struct StagedefColiTri StagedefColiTri, *PStagedefColiTri; -typedef struct StagedefMystery5 StagedefMystery5, *PStagedefMystery5; +typedef struct GStagedefBoundSphere GStagedefBoundSphere, *PGStagedefBoundSphere; typedef struct StagedefBackgroundAnim2Header StagedefBackgroundAnim2Header, *PStagedefBackgroundAnim2Header; @@ -3917,15 +3943,6 @@ struct StagedefBanana { } __attribute__((__packed__)); static_assert(sizeof(StagedefBanana) == 0x10); -struct StagedefMystery5 { - undefined field_0x0[0x4]; - float field4_0x4; - float field5_0x8; - float field6_0xc; - float field7_0x10; -} __attribute__((__packed__)); -static_assert(sizeof(StagedefMystery5) == 0x14); - struct StagedefColiCone { struct Vec position; struct S16Vec rotation; @@ -3972,6 +3989,15 @@ struct StagedefColiTri { } __attribute__((__packed__)); static_assert(sizeof(StagedefColiTri) == 0x40); +struct GStagedefBoundSphere { + undefined field_0x0[0x4]; + float field4_0x4; + float field5_0x8; + float field6_0xc; + float field7_0x10; +} __attribute__((__packed__)); +static_assert(sizeof(GStagedefBoundSphere) == 0x14); + struct StagedefGoal { struct Vec position; struct S16Vec rotation; @@ -4143,15 +4169,15 @@ struct StagedefColiHeader { u32 button_count; struct StagedefButton * button_list; undefined field_0xb0[0x4]; - struct StagedefMystery5 * mystery5; + struct GStagedefBoundSphere * g_bound_sphere; float seesaw_sensitivity; /* Higher is more sensitive, negative makes the seesaw reversed */ float seesaw_friction; /* Lower is looser */ float seesaw_spring; /* 0 prevents the seesaw from resetting */ u32 wormhole_count; struct StagedefWormhole * wormhole_list; u32 initial_playback_state; /* Should this be split into 2x padding bytes + PlaybackState enum? */ - undefined field_0xd0[0x4]; - float anim_loop_point_seconds; + float loop_start_sec; + float loop_end_sec; struct StagedefTextureScroll * texture_scroll; undefined field_0xdc[0x3c0]; } __attribute__((__packed__)); @@ -5581,7 +5607,9 @@ extern "C" { extern f32 projection_near_clip; extern f32 projection_far_clip; extern Mtx44 g_some_projection_matrix; - extern undefined4 g_some_gmaflag_1; + extern undefined1 g_some_gmaflag_1; + extern undefined1 g_some_gmaflag_2; + extern undefined1 g_some_gmaflag_3; extern pointer INIT_REL_PATHS[2]; extern OSHeapHandle currentHeap; extern undefined4 arena_lo; @@ -5828,6 +5856,7 @@ extern "C" { extern undefined2 g_something_with_world_theme_5; extern struct Ape * * BGApeTable; extern undefined4 g_smth_with_bg_models; + extern struct GXColor background_colors[42]; extern undefined bg_init_funcs; extern undefined bg_tick_funcs; extern undefined bg_dest_funcs; @@ -5919,8 +5948,11 @@ extern "C" { extern char LOADIN_TEXT_FINAL_ROUND[12]; extern char LOADIN_TEXT_FINAL_STAGE[12]; extern undefined stage_name_tilde_fmt_string; + extern char JUMP_TO_STAGE_STRING[17]; extern undefined * switchdataD_803a96f8; extern char SPRITE_1UP_TEXT_STRING[4]; + extern char GO_TO_THE_STAGE_STRING[6]; + extern char POSTGOAL_SPRITES_STAGE_STRING[15]; extern undefined * switchdataD_803a9e6c; extern pointer switchdataD_803a9ea4; extern undefined * switchdataD_803a9ee8; @@ -6012,7 +6044,8 @@ extern "C" { extern struct NlBuffer * g_stage_nl_buf; extern struct NlBuffer * * g_init_common_gma_buf; extern struct ScenInfo scen_info; - extern Mtx * g_ord_tbl_stuff; + extern struct OrdTblData * g_ord_tbl_stuff; + extern struct OrdTblData * ord_tbl_data; extern undefined4 is_more_than_24_mib; extern undefined4 g_some_buffer_ptr; extern undefined4 g_some_other_heap_lo; @@ -6085,6 +6118,9 @@ extern "C" { extern undefined1 stageselect_category_selected; extern undefined1 g_last_selected_bowling_difficulty; extern undefined4 g_auto_reload_setting; + extern undefined1 bat_first_setting; + extern undefined1 number_of_innings_setting; + extern undefined1 baseball_com_level_setting; extern undefined4 menu_tick_func; extern undefined4 menu_draw_func; extern struct RelBufferInfo g_some_sel_ngc_rel_buffer; @@ -6193,6 +6229,7 @@ extern "C" { extern undefined4 current_world_info; extern int g_some_frame_counter; extern float g_some_frame_counter_float; + extern undefined1 g_some_coli_nonsense1; extern undefined4 g_some_gameplay_flags; extern int * g_some_draw_var; extern struct Itemgroup * itemgroups; @@ -6585,8 +6622,9 @@ extern "C" { extern undefined menu_option_game_data_entries; extern undefined menu_option_controller_entries; extern undefined menu_option_screen_entries; - extern struct MenuScreen menu_screen_list[87]; + extern struct MenuScreen menu_screen_list[88]; extern pointer switchdataD_80580b70; + extern undefined menu_bmp_ids; extern char SPRITE_BUTTON_LESSON_TEXT[7]; extern char SPRITE_BUTTON_TUTORIAL_TEXT[9]; extern undefined * switchdataD_805837fc; @@ -6758,7 +6796,7 @@ extern "C" { void load_run_main_loop_parent1(void); uint read_and_set_os_string_table(void); void load_main_loop_rel_and_run(char * rel_filepath, struct RelBufferInfo * buffer_info); - OSModuleInfo * * unload_main_loop_rel(struct OSModuleInfo * * mainLoopBufPtrs); + int * unload_main_loop_rel(int * mainLoopBufPtrs); void load_common_gma_tpl(void); void set_init_rel_index(u32 index); undefined4 g_clear_prev_GX_settings_something1(void); @@ -6799,7 +6837,7 @@ extern "C" { void GXSetNumChans_cached(u8 nChans); void opti_GXSetChanCtrl(GXChannelID chan, GXBool enable, GXColorSrc amb_src, GXColorSrc mat_src, u32 light_mask, GXDiffuseFn diff_fn, GXAttnFn attn_fn); void GXSetZMode_cached(GXBool compare_enable, GXCompare func, GXBool update_enable); - void g_read_something_from_prev_GX_settings(undefined * param_1, undefined4 * param_2, undefined * param_3); + void g_read_something_from_prev_GX_settings(undefined1 * param_1, undefined4 * param_2, undefined1 * param_3); void g_set_some_gx_settings(void); void g_draw_something(double param_1, double param_2, double param_3, ushort * param_4); void mark_finished_waiting_for_dvdread(s32 result, struct DVDFileInfo * file_info); @@ -6909,7 +6947,7 @@ extern "C" { void DMAErrorHandler(undefined4 param_1, undefined4 * param_2); void __OSCacheInit(void); undefined8 __OSLoadFPUContext(undefined8 param_1, undefined4 param_2, int param_3); - void __OSSaveFPUContext(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, undefined8 param_9, undefined8 param_10, undefined8 param_11_00, undefined8 param_12, undefined8 param_13, undefined4 param_14, undefined4 param_15, int param_16); + void __OSSaveFPUContext(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, double param_7, double param_8, undefined4 param_9, undefined4 param_10, int param_11); void OSSetCurrentContext(struct OSContext * context); OSContext * OSGetCurrentContext(void); undefined4 OSSaveContext(int param_1); @@ -6973,9 +7011,9 @@ extern "C" { undefined4 __OSSyncSram(void); uint __OSReadROM(void * param_1, u32 param_2, int param_3); u32 OSGetSoundMode(void); - void OSSetSoundMode(uint param_1); + void OSSetSoundMode(byte param_1); u32 OSGetProgressiveMode(void); - void OSSetProgressiveMode(uint param_1); + void OSSetProgressiveMode(char param_1); undefined2 OSGetWirelessID(int param_1); void OSSetWirelessID(int param_1, short param_2); void __OSInitSystemCall(void); @@ -7024,7 +7062,7 @@ extern "C" { uint SIDisablePolling(uint param_1); bool SIGetResponseRaw(int param_1); int SIGetResponse(int param_1, undefined4 * param_2); - undefined4 SITransfer(uint param_1, undefined4 * param_2, int param_3, undefined4 param_4, int param_5, int param_6, uint param_7, uint param_8); + undefined4 SITransfer(uint param_1, undefined4 * param_2, int param_3, undefined4 param_4, int param_5, int param_6, int param_7, uint param_8); void GetTypeCallback(uint param_1, uint param_2); int SIGetType(uint param_1); int SIGetTypeAsync(uint param_1, undefined * param_2); @@ -7049,7 +7087,7 @@ extern "C" { undefined4 EXILock(int param_1, int param_2, int param_3); undefined4 EXIUnlock(int param_1); undefined4 sndReadFlag(int param_1); - undefined4 EXIGetID(int param_1, int param_2, undefined4 * param_3); + undefined4 EXIGetID(int param_1, int param_2, byte * param_3); undefined4 InitializeUART(void); undefined4 WriteUARTN(byte * param_1, uint param_2); void DBInit(void); @@ -7057,20 +7095,20 @@ extern "C" { void __DBExceptionDestination(void); uint __DBIsExceptionMarked(uint param_1); void DBPrintf(void); - undefined8 PSMTXIdentity(int param_1); - undefined8 PSMTXCopy(int param_1, int param_2); - undefined8 PSMTXConcat(int param_1, int param_2, int param_3); - undefined4 PSMTXInverse(int param_1, int param_2); + undefined8 PSMTXIdentity(short * param_1); + undefined8 PSMTXCopy(float * param_1, float * param_2); + undefined8 PSMTXConcat(float * param_1, float * param_2, float * param_3); + undefined4 PSMTXInverse(float * param_1, float * param_2); void PSMTXScale(double param_1, double param_2, double param_3, float * param_4); void C_MTXLookAt(Mtx * mtx, struct Vec * cam_pos, struct Vec * cam_up, struct Vec * target); void C_MTXFrustum(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, float * param_7); void C_MTXPerspective(Mtx44 * m, double fovy, double aspect, double n, double f); void C_MTXOrtho(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, float * m); - void PSVECAdd(int param_1, int param_2, int param_3); - void PSVECSubtract(int param_1, int param_2, int param_3); - void PSVECScale(undefined8 param_1, int param_2, int param_3); - undefined8 PSVECNormalize(int param_1, int param_2); - undefined8 PSVECCrossProduct(int param_1, int param_2, int param_3); + void PSVECAdd(float * param_1, float * param_2, float * param_3); + void PSVECSubtract(float * param_1, float * param_2, float * param_3); + void PSVECScale(double param_1, float * param_2, float * param_3); + undefined8 PSVECNormalize(float * param_1, float * param_2); + undefined8 PSVECCrossProduct(float * param_1, float * param_2, float * param_3); void __DVDInitWA(void); void AlarmHandlerForTimeout(undefined4 param_1, struct OSContext * param_2); void Read(undefined4 param_1, uint param_2, uint param_3, undefined4 param_4); @@ -7147,7 +7185,7 @@ extern "C" { void __DVDPrepareResetAsync(undefined * param_1); void __DVDClearWaitingQueue(void); undefined4 __DVDPushWaitingQueue(int param_1, undefined4 * param_2); - int * * __DVDPopWaitingQueue(void); + int * __DVDPopWaitingQueue(void); undefined4 __DVDCheckWaitingQueue(void); undefined4 __DVDDequeueWaitingQueue(int * param_1); char ErrorCode2Num(uint param_1); @@ -7210,7 +7248,7 @@ extern "C" { void __AICallbackStackSwitch(undefined * param_1); void __AI_SRC_INIT(void); ushort ARGetDMAStatus(void); - void ARStartDMA(int param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4); + void ARStartDMA(short param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4); undefined4 ARInit(undefined4 param_1, undefined4 param_2); undefined4 ARGetBaseAddress(void); void __ARHandler(undefined4 param_1, struct OSContext * param_2); @@ -7271,7 +7309,7 @@ extern "C" { int __CARDEraseSector(int param_1, uint param_2, int param_3); void CARDInit(void); void __CARDSetDiskID(undefined * param_1); - undefined4 __CARDGetControlBlock(int param_1, int * * param_2); + undefined4 __CARDGetControlBlock(int param_1, undefined4 * param_2); int __CARDPutControlBlock(int * param_1, int param_2); s32 CARDGetResultCode(int param_1); int CARDFreeBlocks(int param_1, int * param_2, int * param_3); @@ -7322,7 +7360,7 @@ extern "C" { undefined4 return_0(void); void CreateCallbackFat(int param_1, int param_2); void CARDCreateAsync(s32 chan, char * fileName, u32 size, struct CARDFileInfo * fileInfo, void * callback); - int __CARDSeek(int * param_1, int param_2, uint param_3, int * * param_4); + int __CARDSeek(int * param_1, int param_2, uint param_3, undefined4 * param_4); void ReadCallback(int param_1, int param_2); s32 CARDReadAsync(struct CARDFileInfo * fileInfo, void * buf, s32 length, s32 offset, void * callback); void WriteCallback(int param_1, int param_2); @@ -7443,7 +7481,7 @@ extern "C" { GXTexWrapMode GXGetTexObjWrapS(struct GXTexObj * obj); GXTexWrapMode GXGetTexObjWrapT(struct GXTexObj * obj); GXBool GXGetTexObjMipMap(struct GXTexObj * obj); - void g_GX_something(uint * param_1, uint * param_2, uint * param_3, float * param_4, float * param_5, float * param_6, byte * param_7, undefined * param_8, uint * param_9); + void g_GX_something(uint * param_1, uint * param_2, uint * param_3, float * param_4, float * param_5, float * param_6, byte * param_7, undefined1 * param_8, uint * param_9); void GXLoadTexObjPreLoaded(struct GXTexObj * obj, struct GXTexRegion * region, GXTexMapID id); void GXLoadTexObj(struct GXTexObj * obj, GXTexMapID id); void GXInitTexCacheRegion(struct GXTexRegion * region, GXBool is_32b_mipmap, u32 tmem_even, GXTexCacheSize size_even, u32 tmem_odd, GXTexCacheSize size_odd); @@ -7500,9 +7538,9 @@ extern "C" { void GXSetProjection(f32 mtx[4][4], GXProjectionType type); void GXSetProjectionv(f32 * ptr); void GXGetProjectionv(float * ptr); - undefined8 WriteMTXPS4x3(int param_1, undefined4 param_2); - void WriteMTXPS3x3from3x4(int param_1, undefined4 * param_2); - undefined8 WriteMTXPS4x2(int param_1, undefined4 param_2); + undefined8 WriteMTXPS4x3(float * param_1, float * param_2); + void WriteMTXPS3x3from3x4(float * param_1, float * param_2); + undefined8 WriteMTXPS4x2(float * param_1, float * param_2); void GXLoadPosMtxImm(float mtxPtr[3][4], u32 id); void GXLoadNrmMtxImm(float mtxPtr[3][4], u32 id); void GXSetCurrentMtx(u32 id); @@ -7523,7 +7561,7 @@ extern "C" { BOOL32 ARCOpen(struct ARCHandle * arc_handle, char * file, struct ArcFileInfo * arcFileInfo); uint arc_path_to_entrynum(struct ARCHandle * arcHandle, char * file); void arc_get_dir(int param_1, int param_2, int param_3); - int ARCGetStartAddrInMem(int * * param_1); + int ARCGetStartAddrInMem(undefined4 * param_1); undefined4 arcGetLength(struct ArcFileInfo * fileInfo); undefined4 return_1(void); void g_some_perf_init_func(void); @@ -7553,7 +7591,7 @@ extern "C" { uint GetPublicId(int param_1); uint seqGetPrivateId(uint param_1); void empty_function(void); - uint seqStartPlay(int * param_1, int * param_2, int param_3, int * param_4, uint * param_5, undefined param_6, undefined2 param_7); + uint seqStartPlay(int param_1, int param_2, int param_3, int * param_4, uint * param_5, undefined1 param_6, undefined2 param_7); void HandleMasterTrack(uint param_1); void StartPause(int * param_1); void seqPause(uint param_1); @@ -7576,10 +7614,10 @@ extern "C" { void synthSetBpm(int param_1, byte param_2, uint param_3); undefined4 synthGetTicksPerSecond(int param_1); void synthInitPortamento(int param_1); - int * do_voice_portamento(byte param_1, char param_2, char param_3, int param_4, undefined4 * param_5); - int * StartLayer(undefined2 param_1, int param_2, undefined4 param_3, undefined4 param_4, uint param_5, byte param_6, uint param_7, uint param_8, byte param_9, undefined param_10, ushort param_11, undefined2 param_12, int param_13, undefined param_14, undefined param_15, int param_16); - int * StartKeymap(undefined2 param_1, short param_2, undefined4 param_3, undefined4 param_4, uint param_5, byte param_6, uint param_7, uint param_8, byte param_9, undefined param_10, ushort param_11, undefined2 param_12, uint param_13, undefined param_14, undefined param_15, int param_16); - int * synthStartSound(uint param_1, int param_2, undefined4 param_3, uint param_4, byte param_5, uint param_6, uint param_7, uint param_8, undefined param_9, ushort param_10, undefined2 param_11, undefined param_12, short param_13, undefined param_14, int param_15); + uint do_voice_portamento(byte param_1, char param_2, char param_3, int param_4, undefined4 * param_5); + uint StartLayer(undefined2 param_1, int param_2, undefined4 param_3, undefined4 param_4, uint param_5, byte param_6, uint param_7, uint param_8, byte param_9, undefined1 param_10, ushort param_11, undefined2 param_12, int param_13, undefined1 param_14, undefined1 param_15, int param_16); + int * StartKeymap(undefined2 param_1, short param_2, undefined4 param_3, undefined4 param_4, uint param_5, byte param_6, uint param_7, uint param_8, byte param_9, undefined1 param_10, ushort param_11, undefined2 param_12, uint param_13, undefined1 param_14, undefined1 param_15, int param_16); + int * synthStartSound(uint param_1, int param_2, undefined4 param_3, uint param_4, byte param_5, uint param_6, uint param_7, uint param_8, undefined1 param_9, ushort param_10, undefined2 param_11, undefined1 param_12, short param_13, undefined1 param_14, int param_15); void synthAddJob(int * param_1, int * param_2, uint param_3); void synthStartSynthJobHandling(int * param_1); void synthForceLowPrecisionUpdate(int * param_1); @@ -7587,14 +7625,14 @@ extern "C" { void HandleJobQueue(int * param_1, undefined * param_2); void HandleFaderTermination(int param_1); void synthHandle(uint param_1); - int * synthFXStart(undefined2 param_1, byte param_2, uint param_3, undefined param_4, int param_5); + int * synthFXStart(undefined2 param_1, byte param_2, uint param_3, undefined1 param_4, uint param_5); undefined4 synthFXSetCtrl(uint param_1, byte param_2, byte param_3); undefined4 synthFXSetCtrl14(uint param_1, byte param_2, uint param_3); void synthFXCloneMidiSetup(int param_1, int param_2); undefined4 synthSendKeyOff(uint param_1); - void synthVolume(uint param_1, uint param_2, uint param_3, undefined param_4, undefined4 param_5); + void synthVolume(uint param_1, uint param_2, uint param_3, undefined1 param_4, undefined4 param_5); undefined4 synthIsFadeOutActive(uint param_1); - void synthSetMusicVolumeType(uint param_1, undefined param_2); + void synthSetMusicVolumeType(uint param_1, undefined1 param_2); void synthInit(undefined4 param_1, int param_2); void sndSeqSpeed(uint param_1, undefined2 param_2); void sndSeqContinue(uint param_1); @@ -7610,7 +7648,7 @@ extern "C" { void sndVolume(uint param_1, uint param_2, uint param_3); void sndMasterVolume(uint param_1, uint param_2, char param_3, char param_4); void sndSetAuxProcessingCallbacks(uint param_1, int param_2, undefined4 param_3, char param_4, uint param_5, int param_6, undefined4 param_7, char param_8, uint param_9); - void synthActivateStudio(uint param_1, undefined param_2, undefined4 param_3); + void synthActivateStudio(uint param_1, undefined1 param_2, undefined4 param_3); void synthDeactivateStudio(uint param_1); void synthAddStudioInput(uint param_1, byte * param_2); void synthRemoveStudioInput(uint param_1, int param_2); @@ -7620,8 +7658,8 @@ extern "C" { void streamKill(int param_1); int GetPrivateIndex(int param_1); void sndStreamARAMUpdate(int param_1, uint param_2, uint param_3, uint param_4, uint param_5); - void CheckOutputMode(undefined * param_1, undefined * param_2); - int sndStreamAllocEx(undefined param_1, undefined4 param_2, int param_3, undefined4 param_4, undefined param_5, undefined param_6, undefined param_7, undefined param_8, undefined param_9, undefined param_10, uint param_11, undefined4 param_12, undefined4 param_13, undefined2 * param_14); + void CheckOutputMode(undefined1 * param_1, undefined1 * param_2); + int sndStreamAllocEx(undefined1 param_1, undefined4 param_2, int param_3, undefined4 param_4, undefined1 param_5, undefined1 param_6, undefined1 param_7, undefined1 param_8, undefined1 param_9, undefined1 param_10, uint param_11, undefined4 param_12, undefined4 param_13, undefined2 * param_14); uint sndStreamAllocLength(int param_1, uint param_2); void sndStreamADPCMParameter(int param_1, undefined2 * param_2); void sndStreamFrq(int param_1, undefined4 param_2); @@ -7678,13 +7716,13 @@ extern "C" { void UnYieldMacro(int * param_1, int param_2); void macMakeActive(int * param_1); void macMakeInactive(int param_1, int param_2); - int * macStart(uint param_1, byte param_2, byte param_3, short param_4, byte param_5, undefined param_6, undefined param_7, uint param_8, byte param_9, undefined param_10, ushort param_11, undefined param_12, byte param_13, undefined param_14, undefined param_15, int param_16); + uint macStart(uint param_1, byte param_2, byte param_3, short param_4, byte param_5, undefined1 param_6, undefined1 param_7, uint param_8, byte param_9, undefined1 param_10, ushort param_11, undefined1 param_12, byte param_13, undefined1 param_14, undefined1 param_15, int param_16); void macInit(void); int vidInit(void); undefined4 * get_vidlist(uint param_1); void vidRemoveVoiceReferences(int param_1); undefined4 vidMakeRoot(int param_1); - int * vidMakeNew(int param_1, int param_2); + uint vidMakeNew(int param_1, int param_2); undefined4 vidGetInternalId(uint param_1); void voiceRemovePriority(int param_1); void voiceSetPriority(int param_1, byte param_2); @@ -7721,11 +7759,11 @@ extern "C" { void ScanIDListReverse(ushort * param_1, int * param_2, byte param_3, int param_4); undefined4 sndPushGroup(int * param_1, short param_2, undefined4 param_3, int * param_4, int * param_5); undefined4 sndPopGroup(void); - uint seqPlaySong(short param_1, short param_2, int * param_3, uint * param_4, char param_5, undefined param_6); - void sndSeqPlayEx(short param_1, short param_2, int * param_3, uint * param_4, undefined param_5); + uint seqPlaySong(short param_1, short param_2, int * param_3, uint * param_4, char param_5, undefined1 param_6); + void sndSeqPlayEx(short param_1, short param_2, int * param_3, uint * param_4, undefined1 param_5); undefined4 salInitDspCtrl(byte param_1, byte param_2, int param_3); void salInitHRTFBuffer(void); - void salActivateStudio(uint param_1, undefined param_2, undefined4 param_3); + void salActivateStudio(uint param_1, undefined1 param_2, undefined4 param_3); void salDeactivateStudio(uint param_1); undefined4 salCheckVolErrorAndResetDelta(undefined2 * param_1, undefined2 * param_2, short * param_3, short param_4, int param_5, ushort param_6); void HandleDepopVoice(int param_1, int * param_2); @@ -7750,7 +7788,7 @@ extern "C" { void StartContinousEmitters(void); void s3dHandle(void); void s3dInit(uint param_1); - int sndInit(byte param_1, undefined param_2, undefined param_3, byte param_4, uint param_5, int param_6); + int sndInit(byte param_1, undefined1 param_2, undefined1 param_3, byte param_4, uint param_5, int param_6); void salApplyMatrix(float * param_1, float * param_2, float * param_3); void salNormalizeVector(float * param_1); void inpSetGlobalMIDIDirtyFlag(uint param_1, uint param_2, uint param_3); @@ -7763,8 +7801,8 @@ extern "C" { void inpResetChannelDefaults(uint param_1, uint param_2); void inpAddCtrl(int param_1, uint param_2, undefined4 param_3, byte param_4, int param_5); void inpFXCopyCtrl(uint param_1, int param_2, int param_3); - void inpSetMidiLastNote(uint param_1, uint param_2, undefined param_3); - void inpGetMidiLastNote(uint param_1, uint param_2); + void inpSetMidiLastNote(uint param_1, uint param_2, undefined1 param_3); + undefined1 inpGetMidiLastNote(uint param_1, uint param_2); uint _GetInputValue(int param_1, byte * param_2, uint param_3, uint param_4); void inpInit(int param_1); uint inpTranslateExCtrl(uint param_1); @@ -7786,18 +7824,18 @@ extern "C" { uint sndConvert2Ms(uint param_1); void snd_handle_irq(void); undefined4 hwInit(undefined4 * param_1, byte param_2, byte param_3, uint param_4); - void hwSetTimeOffset(undefined param_1); - void WPADGetDpdSensitivity(void); + void hwSetTimeOffset(undefined1 param_1); + undefined1 WPADGetDpdSensitivity(void); bool hwIsActive(int param_1); void hwSetPriority(int param_1, undefined4 param_2); void hwInitSamplePlayback(int param_1, undefined2 param_2, undefined4 * param_3, int param_4, undefined4 param_5, undefined4 param_6, int param_7, char param_8); void hwBreak(int param_1); void hwSetADSR(int param_1, uint * param_2, byte param_3); void hwSetVirtualSampleLoopBuffer(int param_1, undefined4 param_2, undefined4 param_3); - void hwGetVirtualSampleState(int param_1); - void hwGetVirtualSampleState(int param_1); + undefined1 hwGetVirtualSampleState(int param_1); + undefined1 hwGetVirtualSampleState(int param_1); undefined2 hwGetSampleID(int param_1); - void hwSetStreamLoopPS(int param_1, undefined param_2); + void hwSetStreamLoopPS(int param_1, undefined1 param_2); void hwStart(int param_1, byte param_2); void hwKeyOff(int param_1); void hwSetPitch(int param_1, ushort param_2); @@ -7815,7 +7853,7 @@ extern "C" { void hwTransAddr(void); void hwFrq2Pitch(undefined4 param_1); void hwInitSampleMem(undefined4 param_1, int param_2); - void hwSaveSample(int * param_1, void * * param_2); + void hwSaveSample(int * param_1, int * param_2); void hwRemoveSample(int param_1, undefined4 param_2); void hwSyncSampleMem(void); void empty_function(void); @@ -7852,12 +7890,12 @@ extern "C" { undefined4 g_something_with_sound8_wrapper(int param_1); undefined4 ReverbHICreate(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, void * param_7); undefined4 ReverbHIModify(double param_1, double param_2, double param_3, double param_4, double param_5, double param_6, void * param_7); - void DoCrossTalk(undefined8 param_1, undefined8 param_2, uint * param_3, uint * param_4); + void DoCrossTalk(double param_1, double param_2, uint * param_3, uint * param_4); void HandleReverb(uint * param_1, int param_2, int param_3); void ReverbHICallback(uint * param_1, uint * param_2, uint * param_3, int param_4); void ReverbHIFree(int param_1); - void do_src1(int * * param_1); - void do_src2(int * * param_1); + void do_src1(undefined4 * param_1); + void do_src2(undefined4 * param_1); undefined4 sndAuxCallbackUpdateSettingsChorus(int param_1); undefined4 sndAuxCallbackPrepareChorus(int * param_1); undefined4 sndAuxCallbackShutdownChorus(void); @@ -7923,7 +7961,7 @@ extern "C" { void mtxa_from_rotate_y(short angle); void mtxa_from_rotate_z(short angle); void mtxa_from_mtxb_translate(struct Vec * vec); - double mtxa_from_mtxb_translate_xyz(undefined8 param_1, undefined8 param_2, undefined8 param_3); + double mtxa_from_mtxb_translate_xyz(double param_1, double param_2, double param_3); void mtxa_normalize_basis(void); undefined8 mtxa_push(void); void mtxa_pop(void); @@ -7966,7 +8004,7 @@ extern "C" { void mtxa_rotate_z_sin_cos(float sin_z_angle, float cos_z_angle); void mtxa_from_quat(struct Quat * quat); void quat_mult(struct Quat * dest, struct Quat * quat1, struct Quat * quat2); - undefined8 g_math_smth1(int param_1); + undefined8 g_math_smth1(float * param_1); void g_math_unk6(float * param_1); void g_math_unk7(double param_1, struct Quat * param_2, float * param_3, float * param_4); void g_math_unk8(double param_1, struct Quat * param_2, float * param_3, float * param_4); @@ -8011,7 +8049,7 @@ extern "C" { void g_init_gx(BOOL32 make_second_fifo, u32 fifo_size, int g_something_with_alpha); void g_init_locked_cache_mtx_stack(int matrix_stack, int param_2); void * allocate_mem_from_arena(int size); - void g_set_some_func_ptrs2(DVDFileInfo * (** param_1)(void)); + void g_set_some_func_ptrs2(undefined4 * param_1); void g_set_some_dvd_func_ptrs(void); void * (* set_alloc_from_heap_func_ptr(void * (* new_func)(u32)))(u32); void (* set_free_to_heap_func_ptr(void (* new_func)(void *)))(void *); @@ -8057,7 +8095,7 @@ extern "C" { undefined8 g_some_GmaSomeStruct_func5(struct GmaShape * gma_struct); void g_some_GmaSomeStruct_func4(struct GmaShape * param_1); void g_free_some_memory(void); - Mtx * draw_poly(int param_1, Mtx * * param_2); + Mtx * draw_poly(int param_1, undefined4 * param_2); uint pointer_range_advance(byte * g_frame_pointer, int * toset); void g_avdisp_draw_model_now1(struct GmaModel * model); void g_avdisp_draw_model_now2(struct GmaModel * model); @@ -8074,7 +8112,7 @@ extern "C" { void g_maybe_something_with_normals(int param_1); void g_init_gma(struct GmaBuffer * gma_buffer, struct Gma * gma_header, struct TplBuffer * tpl); int g_init_gma_model_materials(struct GmaModel * model, struct TplBuffer * tpl, struct GXTexObj * texobj_array); - void g_memcpy_using_locked_cache(void * dest, void * curr_src_1_1_1_1_1_1_1_1_1_1_1, size_t count); + void g_memcpy_using_locked_cache(void * dest, void * curr_src_1_1_1_1_1_1_1_1_1_1_1_1_1, size_t count); void g_something_with_locked_cache_2(void * param_1, uint param_2, uint param_3); void memcpy2(void * dest, void * src, size_t count); int * __va_arg(char * param_1, int param_2); @@ -8168,9 +8206,9 @@ extern "C" { void __unregister_fragment(int param_1); undefined4 __register_fragment(undefined4 param_1, undefined4 param_2); void free(int * * __ptr); - void deallocate_from_fixed_pools(int * * param_1, int * * param_2, uint param_3); + void deallocate_from_fixed_pools(undefined4 * param_1, int * param_2, uint param_3); uint * soft_allocate_from_var_pools(int * param_1, int param_2, uint * param_3); - void SubBlock_merge_next(uint * param_1, uint * * param_2); + void SubBlock_merge_next(uint * param_1, uint * param_2); void Block_link(int param_1, uint * param_2); undefined4 __flush_all(void); void __close_all(void); @@ -8179,8 +8217,8 @@ extern "C" { void __num2dec_internal(double param_1, char * param_2); uint __equals_dec(int param_1, int param_2); void __two_exp(undefined4 * param_1, ushort param_2); - void __timesdec(undefined * param_1, int param_2, int param_3); - void __ull2dec(undefined * param_1, undefined4 param_2, uint param_3, uint param_4); + void __timesdec(undefined1 * param_1, int param_2, int param_3); + void __ull2dec(undefined1 * param_1, undefined4 param_2, int param_3, int param_4); int __count_trailing_zerol(uint param_1); int __flush_buffer(undefined4 * param_1, undefined4 * param_2); void __prep_buffer(int param_1); @@ -8214,13 +8252,13 @@ extern "C" { byte * float2str(double param_1, int param_2, int param_3); void round_decimal(int param_1, int param_2); char * double2hex(double param_1, int param_2, int param_3); - char * longlong2str(uint param_1, uint param_2, int param_3, char * param_4); + char * longlong2str(uint param_1, int param_2, int param_3, char * param_4); char * long2str(uint param_1, int param_2, char * param_3); char * parse_format(int param_1, char * param_2, uint * param_3); void qsort(void * __base, size_t __nmemb, size_t __size, __compar_fn_t __compar); void srand(u32 seed); int rand(void); - byte * __StringRead(byte * * param_1, byte * param_2, int param_3); + uint __StringRead(int * param_1, uint param_2, int param_3); char * strstr(char * __haystack, char * __needle); char * strchr(char * __s, int __c); int strncmp(char * __s1, char * __s2, size_t __n); @@ -8261,7 +8299,7 @@ extern "C" { float cosf(float __x); void TRKNubMainLoop(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); void TRKDestructEvent(int param_1); - void TRKConstructEvent(undefined * param_1, undefined param_2); + void TRKConstructEvent(undefined1 * param_1, undefined1 param_2); undefined4 TRKPostEvent(int param_1); undefined4 TRKGetNextEvent(int param_1); undefined4 TRKInitializeEventQueue(void); @@ -8269,19 +8307,19 @@ extern "C" { undefined4 TRKTerminateNub(void); int TRKInitializeNub(void); void TRKMessageSend(int param_1); - void TRKReadBuffer_ui32(int param_1, undefined * param_2, int param_3); + void TRKReadBuffer_ui32(int param_1, undefined1 * param_2, int param_3); void TRKReadBuffer_ui8(int param_1, int param_2, int param_3); - int TRKReadBuffer1_ui64(int param_1, undefined * param_2); - int TRKReadBuffer1_ui32(int param_1, undefined * param_2); - int TRKReadBuffer1_ui16(int param_1, undefined * param_2); + int TRKReadBuffer1_ui64(int param_1, undefined1 * param_2); + int TRKReadBuffer1_ui32(int param_1, undefined1 * param_2); + int TRKReadBuffer1_ui16(int param_1, undefined1 * param_2); undefined4 TRKReadBuffer1_ui8(int param_1, int param_2); void TRKAppendBuffer_ui32(int param_1, undefined4 * param_2, int param_3); - int TRKAppendBuffer_ui8(int param_1, undefined * param_2, int param_3); + int TRKAppendBuffer_ui8(int param_1, undefined1 * param_2, int param_3); void TRKAppendBuffer1_ui64(int param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4); void TRKAppendBuffer1_ui32(int param_1, undefined4 param_2); void TRKAppendBuffer1_ui16(int param_1, undefined2 param_2); undefined4 TRKReadBuffer(int param_1, int param_2, uint param_3); - undefined4 TRKAppendBuffer(int param_1, undefined * param_2, uint param_3); + undefined4 TRKAppendBuffer(int param_1, undefined1 * param_2, uint param_3); undefined4 TRKSetBufferPosition(int param_1, uint param_2); void TRKResetBuffer(int param_1, char param_2); void TRKReleaseBuffer(int param_1); @@ -8313,11 +8351,11 @@ extern "C" { int TRKDoDisconnect(int param_1); void TRKDoConnect(int param_1); void TRKDoUnsupported(int param_1); - void TRKStandardACK(int param_1, undefined param_2, undefined param_3); + void TRKStandardACK(int param_1, undefined1 param_2, undefined1 param_3); void SetTRKConnected(undefined4 param_1); - int HandlePositionFileSupportRequest(undefined4 param_1, undefined4 * param_2, undefined param_3, undefined * param_4); - int HandleCloseFileSupportRequest(undefined4 param_1, undefined * param_2); - int HandleOpenFileSupportRequest(char * param_1, undefined param_2, undefined4 * param_3, undefined * param_4); + int HandlePositionFileSupportRequest(undefined4 param_1, undefined4 * param_2, undefined1 param_3, undefined1 * param_4); + int HandleCloseFileSupportRequest(undefined4 param_1, undefined1 * param_2); + int HandleOpenFileSupportRequest(char * param_1, undefined1 param_2, undefined4 * param_3, undefined1 * param_4); int TRKRequestSend(int param_1, int * param_2, uint param_3, int param_4, int param_5); int TRKSuppAccessFile(int param_1, int param_2, uint * param_3, char * param_4, int param_5, int param_6); undefined4 return_0(void); @@ -8340,9 +8378,9 @@ extern "C" { void TRKTargetAddExceptionInfo(int param_1); void TRKTargetAddStopInfo(int param_1); int TRKTargetInterrupt(byte * param_1); - undefined4 TRKTargetCPUType(undefined * param_1); - undefined4 TRKTargetSupportMask(undefined * param_1); - undefined4 TRKTargetVersions(undefined * param_1); + undefined4 TRKTargetCPUType(undefined1 * param_1); + undefined4 TRKTargetSupportMask(undefined1 * param_1); + undefined4 TRKTargetVersions(undefined1 * param_1); int TRKTargetAccessExtended2(uint param_1, uint param_2, int param_3, int * param_4, int param_5); uint TRKTargetAccessExtended1(uint param_1, uint param_2, int param_3, int * param_4, int param_5); int TRKTargetAccessFP(uint param_1, uint param_2, int param_3, int * param_4, int param_5); @@ -8366,15 +8404,15 @@ extern "C" { void TRK_board_display(char * param_1); void UnreserveEXI2Port(void); void UnreserveEXI2Port(void); - int TRKReadUARTPoll(undefined * param_1); - undefined4 WriteUART1(undefined param_1); + int TRKReadUARTPoll(undefined1 * param_1); + undefined4 WriteUART1(undefined1 param_1); int WriteUARTFlush(void); void UnreserveEXI2Port(void); undefined4 TRKInitializeIntDrivenUART(void); void InitMetroTRKCommTable(int param_1); void TRKEXICallBack(undefined4 param_1, undefined4 * param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); undefined4 TRKTargetContinue(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); - void SetUseSerialIO(undefined param_1); + void SetUseSerialIO(undefined1 param_1); undefined4 __position_file(void); undefined4 __close_file(void); undefined4 __write_file(undefined4 param_1, undefined4 param_2, undefined4 * param_3); @@ -8454,7 +8492,7 @@ extern "C" { void g_smth_with_bg_color_drawing(struct GXColor param_1); void g_draw_func_init(void); void g_something_with_view_stage(void); - void g_some_draw_func(void); + void fade_color_base_default(void); void take_pausemenu_screenshot(void * out_image_buffer, undefined4 src_left_px, undefined4 src_top_px, short width_px, short height_px, GXTexFmt fmt); void init_pausemenu_screenshot_texobj(struct GXTexObj * param_1); void g_draw_pausemenu_screenshot(struct GXTexObj * tex); @@ -8511,7 +8549,7 @@ extern "C" { void init_cameras(void); void event_camera_init(void); void event_camera_tick(void); - void g_some_camera_parent_func(undefined param_1, undefined param_2, undefined param_3, undefined param_4, undefined param_5, undefined param_6, undefined param_7, undefined param_8, undefined4 param_9, undefined4 param_10, undefined4 param_11, undefined8 param_12, undefined8 param_13, undefined8 param_14, undefined8 param_15, undefined4 param_16, undefined4 param_17); + void g_some_camera_parent_func(void); void event_camera_dest(void); void enable_camera(int camera_idx); void disable_all_cameras(void); @@ -8691,7 +8729,7 @@ extern "C" { void event_sound_dest(void); double g_smth_called_by_event_tick_sound_1(char param_1, short param_2); void g_smth_called_by_event_tick_sound_2(void); - void g_set_smth_with_sound(undefined param_1); + void g_set_smth_with_sound(undefined1 param_1); void g_smth_calls_sndFXStartParaInfo(struct GSoundCue * cue); int g_something_with_volume(uint * param_1, int param_2, int param_3); undefined4 g_something_calls_sndFXKeyOff(uint param_1, int param_2, int param_3); @@ -8749,8 +8787,8 @@ extern "C" { void g_something_with_sound6(void); void g_something_with_sound11(void); void empty_function(void); - uint g_something_with_sound4(undefined * param_1, undefined4 param_2, undefined param_3, undefined param_4, undefined param_5, undefined param_6); - int g_smgr_allocate_stereo(undefined4 param_1, undefined4 param_2, undefined param_3, undefined param_4, char * param_5, char * param_6, char param_7); + uint g_something_with_sound4(undefined1 * param_1, undefined4 param_2, undefined1 param_3, undefined1 param_4, undefined1 param_5, undefined1 param_6); + int g_smgr_allocate_stereo(undefined4 param_1, undefined4 param_2, undefined1 param_3, undefined1 param_4, char * param_5, char * param_6, char param_7); void g_some_dvd_read_async_sound_callback(s32 result, struct DVDFileInfo * file_info); void event_adx_init(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, undefined4 param_9, undefined4 param_10, undefined4 param_11, undefined4 param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); void event_adx_tick(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); @@ -8818,12 +8856,12 @@ extern "C" { void ball_physics_g_something_w_postgoal_blast_up2(struct Ball * ball); void g_move_and_collide(struct Ball * ball, struct PhysicsBall * physicsBall); void g_apply_ball_velocity(struct Ball * ball); - void collide_with_stage(struct Ball * ball, struct PhysicsBall * physicsball); + void handle_ball_stage_coli(struct Ball * ball, struct PhysicsBall * physicsball); void position_ball(struct Ball * ball, struct PhysicsBall * phys_ball); void set_ball_properties(struct Ball * ball, int constants_idx); void ball_collision_stars(struct Ball * ball); void init_physicsball_from_ball(struct Ball * ball, struct PhysicsBall * physicsball); - void g_copy_physicsball_to_ball(struct Ball * ball, struct PhysicsBall * physicsball); + void apply_physicsball_to_ball(struct Ball * ball, struct PhysicsBall * physicsball); void g_ball_ape_rotation(struct Ball * ball); void spawn_postgoal_ball_sparkle(void); void g_some_ballfunc(struct Ball * param_1); @@ -8832,19 +8870,19 @@ extern "C" { void set_visual_scale(struct Ball * ball); void g_draw_ball_and_ape(void); void g_something_with_view_stage_and_ball(void); - undefined4 * g_some_ball_stage_coli_func(struct PhysicsBall * physicsball, struct StagedefFileHeader * stagedef); - undefined4 meshcoli_grid_lookup(float x, float z, struct StagedefColiHeader * coli_header); - void stcoli_sub03(struct PhysicsBall * physicsball, struct StagedefColiTri * tri); - void stcoli_sub04(struct PhysicsBall * physball, struct StagedefColiTri * tri); - void stcoli_sub05(struct PhysicsBall * param_1, struct Vec * param_2, struct Vec * param_3, float * param_4); - void stcoli_sub06(struct PhysicsBall * physball, struct StagedefColiTri * tri); - undefined8 stcoli_sub07(struct PhysicsBall * param_1, float * param_2, float * param_3); + void collide_ball_with_stage(struct PhysicsBall * physicsball, struct StagedefFileHeader * stagedef); + short * tri_coli_grid_lookup(float x, float z, struct StagedefColiHeader * coli_header); + void collide_ball_with_tri_face(struct PhysicsBall * physicsball, struct StagedefColiTri * tri); + void collide_ball_with_tri_edges(struct PhysicsBall * physball, struct StagedefColiTri * tri); + void collide_ball_with_tri_edge(struct PhysicsBall * param_1, struct Vec * param_2, struct Vec * param_3, float * param_4); + void collide_ball_with_tri_vertices(struct PhysicsBall * physball, struct StagedefColiTri * tri); + undefined8 collide_ball_with_tri_vertex(struct PhysicsBall * param_1, float * param_2, float * param_3); void g_some_jamabar_coli_func(struct PhysicsBall * physicsball, float * param_2); - void g_cylinder_coli_something(struct PhysicsBall * physball, struct StagedefColiCylinder * cylinder); + void collide_ball_with_cylinder(struct PhysicsBall * physball, struct StagedefColiCylinder * cylinder); void stcoli_sub10(struct PhysicsBall * param_1, struct Vec * param_2); - void g_sphere_coli_something(struct PhysicsBall * param_1, struct StagedefColiSphere * param_2); - void g_cone_coli_something(struct PhysicsBall * param_1, struct StagedefColiCone * param_2); - void g_something_with_physicsball_restitution(struct PhysicsBall * physicsball, struct Vec * param_2); + void collide_ball_with_sphere(struct PhysicsBall * param_1, struct StagedefColiSphere * param_2); + void collide_ball_with_cone(struct PhysicsBall * param_1, struct StagedefColiCone * param_2); + void collide_ball_with_plane(struct PhysicsBall * physicsball, struct ColiPlane * plane); BOOL32 line_intersects_rect(struct Vec * lineStart, struct Vec * lineEnd, struct Rect * rect); void stobj_jamabar_child_coli(struct PhysicsBall * physicsball, struct Stobj * stobj); void raycast_stage_down(struct Vec * origin, struct RaycastHit * out_hit, struct Vec * out_vel_at_point); @@ -8852,9 +8890,9 @@ extern "C" { BOOL32 raycast_cone(struct Vec * line_origin, undefined4 line_dir, struct StagedefColiCone * cone, struct Vec * out_hit_pos, struct Vec * out_hit_normal); BOOL32 raycast_sphere(struct Vec * line_origin, struct Vec * line_dir, struct StagedefColiSphere * sphere, struct Vec * out_hit_pos, struct Vec * out_hit_normal); BOOL32 raycast_cylinder(undefined4 line_origin, undefined4 line_dir, struct StagedefColiCylinder * cylinder, undefined4 out_hit_pos, undefined4 out_hit_normal); - uint g_goal_coli_something(struct PhysicsBall * param_1, struct StagedefGoal * param_2); - void stcoli_sub22(struct PhysicsBall * param_1, struct Vec * param_2); - void stcoli_sub24(struct PhysicsBall * param_1, struct Vec * param_2); + uint collide_ball_with_goal(struct PhysicsBall * physicsball, struct StagedefGoal * goal_def); + void g_goal_coli_func1(struct PhysicsBall * param_1, struct Vec * param_2); + void g_goal_coli_func2(struct PhysicsBall * param_1, struct Vec * param_2); void stcoli_sub25(struct PhysicsBall * param_1, int param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); void g_draw_stage_collision(void); void stcoli_sub27(int param_1); @@ -8862,9 +8900,9 @@ extern "C" { void stcoli_sub29(float * param_1, float * param_2, float * param_3, float * param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); void tf_physicsball_by_mtxa(struct PhysicsBall * physicsball1, struct PhysicsBall * physicsball2); void inv_tf_physicsball_by_mtxa(struct PhysicsBall * src_physicsball, struct PhysicsBall * dest_physicsball); - void tf_physball_to_itemgroup_space(struct PhysicsBall * physicsball, int itemgroup_idx); - uint g_something_w_ig_and_coli_headers(struct Itemgroup * ig_list, struct StagedefColiHeader * coli_header_list, undefined4 param_3, struct Vec * physicsball_x); - undefined4 g_something_w_ig_and_coli_headers_2(struct Itemgroup * ig_list, struct StagedefColiHeader * coli_header_list, struct Vec * physicsball_pos); + void tf_physball_to_itemgroup_space(struct PhysicsBall * physicsball, int dest_ig_idx); + uint g_is_ball_in_ig_coli_range(struct Itemgroup * ig_list, struct StagedefColiHeader * coli_header_list, undefined4 param_3, struct Vec * physicsball_x); + BOOL32 g_ball_ig_bound_sphere_overlap(struct Itemgroup * ig_anim, struct StagedefColiHeader * ig_def, struct Vec * physicsball_pos); void event_world_init(void); void event_world_tick(void); void event_world_dest(void); @@ -8872,7 +8910,7 @@ extern "C" { void event_stage_init(void); void event_stage_tick(void); void event_stage_dest(void); - double g_advance_itemgroup_anim_frame(struct Itemgroup * itemgroup, struct StagedefColiHeader * colis_header); + float advance_itemgroup_anim(struct Itemgroup * itemgroup, struct StagedefColiHeader * colis_header); void g_advance_stage_animation(void); void g_transform_some_itemgroup_vec(void); GmaModel * get_GmaBuffer_entry(struct GmaBuffer * buffer, char * name); @@ -8891,6 +8929,7 @@ extern "C" { void g_smth_with_stage_anim_groups(int anim_group_id, uint param_2); BOOL32 g_smth_with_buttons(int anim_group_id, uint param_2); void g_init_smth_with_seesaws(void); + void collide_ball_with_seesaws(undefined2 param_1, undefined2 g_ball_idx, struct PhysicsBall * param_3); undefined4 get_seesaw_replay_state_size(struct SeesawInfo * seesaw_info); void g_smth_with_stage_fog(double param_1); bool is_stage_id_not_for_party_game(int stage_id); @@ -8953,6 +8992,7 @@ extern "C" { void empty_function(void); void g_something_with_score(void); void g_advance_replay2(double replay_frames_remaining, float * param_2); + short g_get_replay_time(void); uint rle_encode(void * input, void * output, uint inputSize); uint get_compressed_replay_size(void); uint compress_replay(void * outCompressedReplay); @@ -9191,6 +9231,7 @@ extern "C" { void bg_wat2_item_coin_coli(void); void empty_function(void); void empty_function(void); + void wat2_draw_caustics(void * some_pointer); void bg_pil2_init(void); void bg_pil2_tick(void); void bg_pil2_dest(void); @@ -9326,7 +9367,7 @@ extern "C" { void item_coin_dest(void); void item_coin_replay_init(struct Item * item); void item_debug_coin(struct Item * item); - GmaModel * g_something_with_coins(int * * param_1); + GmaModel * g_something_with_coins(undefined4 * param_1); void event_stobj_collision_init(void); void event_stobj_collision_tick(void); void event_stobj_collision_dest(void); @@ -9545,7 +9586,7 @@ extern "C" { void sprite_save_tick(u8 * status, struct Sprite * sprite); void sprite_save_disp(struct Sprite * sprite); void sprite_monkey_counter_icon_disp(struct Sprite * sprite); - undefined4 g_smth_with_get_active_monkey_icon(undefined4 param_1, int param_2, int param_3); + undefined4 g_smth_with_get_active_monkey_icon(int param_1, int param_2, int param_3); void create_how_to_sprite(void); void sprite_how_to_tick(u8 * status, struct Sprite * sprite); void g_how_to_sprite_draw_controller_tooltips(int param_1, int param_2, struct SpriteDrawRequest * param_3); @@ -9621,7 +9662,7 @@ extern "C" { int g_get_debug_level_select_loading_left_asterisks(void); undefined4 g_swapDiscQueueGroup(undefined4 newValue); void g_fill_some_memory_with_0x0_and_0xff(void * ptr); - void g_some_shadow_draw_func(void * pointer); + void g_some_shadow_draw_func(struct ShadowReceive * shadow_receive); undefined4 g_check_some_condition(ushort param_1); void debug_draw_shadow_textures(void); void md_mini_func(void); @@ -9646,16 +9687,16 @@ extern "C" { void event_rend_efc_dest(void); void g_something_with_rend_efc(uint param_1); void g_init_rendefc_for_stage(void); - void g_smth_with_loading_reflective_stgobjs(undefined * param_1); + void g_smth_with_loading_reflective_stgobjs(undefined1 * param_1); void g_smth_calling_reflective_obj_draw_hdlr(int g_some_flag, int * param_2); void g_reflective_object_draw_handler(int g_some_flag, int * g_some_ptr); void g_reflective_object_draw_handler_2(undefined4 param_1, int param_2); - void g_some_rendefc_func_1(undefined * param_1); - void g_smth_with_pil2_ref(undefined * param_1); + void g_some_rendefc_func_1(undefined1 * param_1); + void g_smth_with_pil2_ref(undefined1 * param_1); void g_something_with_stage_heap_and_target_theme(int param_1); void g_some_rendefc_func_2(int param_1, int param_2); void g_smth_with_reflective_models(undefined4 param_1, int param_2); - void g_smth_with_wormhole_surfaces(undefined * param_1); + void g_smth_with_wormhole_surfaces(undefined1 * param_1); void fog_main(void); void g_set_something3(char param_1); void smd_mini_commend_init(void); @@ -9697,18 +9738,18 @@ extern "C" { void g_something_with_card6(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8); byte g_check_some_memcard_field(void); undefined4 g_get_result_code(void); - void g_get_some_memcard_var(void); + undefined1 g_get_some_memcard_var(void); void g_sprintf_memcard_error(int param_1, char * param_2); - void g_get_last_used_memcard_slot(void); + undefined1 g_get_last_used_memcard_slot(void); void g_save_game_data(void); void g_some_loading_function(void); void smd_game_over_save_child(void); void g_something_with_card2(int card_chan, int param_2); - void * g_some_replay_func(void * * param_1, uint * param_2); + void * g_some_replay_func(undefined4 * param_1, uint * param_2); undefined4 g_some_replay_func2(byte * param_1); char * g_some_replay_func3(byte * param_1, char * param_2); uint g_something_with_fonts(void); - void g_some_printf_function_6(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, int param_9, int param_10, int param_11, char * param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); + void g_some_printf_function_6(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, undefined4 param_9, undefined4 param_10, undefined4 param_11, char * param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); void smd_mini_ranking_init(void); void smd_mini_ranking_tick(void); void g_load_preview_texture(struct SpriteTex * sprite_tex, char * file_path, undefined4 param_3, u16 width, u16 height, GXTexFmt format); @@ -9760,14 +9801,14 @@ extern "C" { void avdisp_draw_model_culled_sort_always(struct GmaModel * gma_model); void g_some_ord_node_func1(int param_1); void g_some_ord_node_func2(int param_1); - void g_some_draw_func3(double param_1); + void avdisp_set_scale_factor(float scale); void call_g_avdisp_set_ambient(double param_1, double param_2, double param_3); void avdisp_set_alpha(float param_1); - void g_some_cleanup_func(undefined param_1, undefined param_2, undefined param_3); + void g_some_cleanup_func(undefined1 param_1, undefined1 param_2, undefined1 param_3); undefined4 g_something_with_texture_scroll_2(int param_1); - void g_stores_doubles(double param_1, double param_2, double param_3, double param_4); + void set_post_mult_color(double param_1, double param_2, double param_3, double param_4); void g_stores_doubles2(double param_1, double param_2, double param_3, double param_4); - void avdisp_set_fog_params(double param_1, double param_2, undefined param_3); + void avdisp_set_fog_params(double param_1, double param_2, undefined1 param_3); void avdisp_set_fog_color(u8 r, u8 g, u8 b); void g_yet_another_unk_draw_func(undefined4 param_1); void g_avdisp_reset_alpha_and_bound_sphere_scale(void); @@ -9796,7 +9837,7 @@ extern "C" { uint g_table_index(struct SKLRoot * param1, char * str); void load_ape_body(int ape_index, int game_index); void gan_setanim_estagebegin(struct Ape * ape, int chara_index, int scene_index); - void g_something_freeing_chara_heap_3(void * * param_1); + void g_something_freeing_chara_heap_3(int * param_1); void g_something_with_new_ape(struct Ape * ape, int chara_index, int scene_index); ulonglong event_ape_init(void); void event_ape_tick(void); @@ -9907,7 +9948,7 @@ extern "C" { void empty_function(void); void compare_play_points_with_99999_after_exit_game(void); dword get_play_point_count(void); - void g_display_playpoint_or_gift_message(double g_x_pos, double g_y_pos, undefined param_3); + void g_display_playpoint_or_gift_message(double g_x_pos, double g_y_pos, undefined1 param_3); void g_playpoint_or_gift_msg_disp(undefined8 param_1_00, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, int * param_9, undefined4 param_10, undefined4 param_11, undefined4 param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); bool is_able_to_unlock_party_game(void); void unlock_party_game(int party_game); @@ -9985,6 +10026,7 @@ extern "C" { void smd_game_scenscnplay_return(void); void smd_game_force_over_init(void); void smd_game_force_over_tick(void); + void g_maybe_some_goal_func(void); void g_preload_stage_or_results(void); void g_challenge_mode_start(struct Ball * ball); void challenge_mode_physics(struct Ball * ball); @@ -10327,7 +10369,7 @@ extern "C" { void test_adx_draw_func(void); void test_newmotion_draw_func(void); void g_something_freeing_something_from_main_heap_2(void); - void gan_setanim_e5(struct ArcFileInfo * * param_1, char * param_2, void * * param_3); + void gan_setanim_e5(undefined4 * param_1, char * param_2, int * param_3); void gan_set_anim_e6(int param_1); void gan_setanim_e7(int param_1, undefined4 param_2, int param_3); void gan_setanim_e8(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, int param_5); @@ -10370,8 +10412,8 @@ extern "C" { void boat_unlinked_func(void); void g_load_boat(void); void shooting_unlinked_func(void); - void g_read_something_for_shooting_from_dvd(char * param_1, struct ArcFileInfo * * param_2, int * param_3); - void g_read_something_for_shooting_2(struct SKLFile * * param_1, char * param_2, struct SKLRoot * * param_3); + void g_read_something_for_shooting_from_dvd(char * param_1, undefined4 * param_2, int * param_3); + void g_read_something_for_shooting_2(undefined4 * param_1, char * param_2, int * param_3); void mini_futsal_unlinked_func(void); void empty_function(void); void empty_function(void); @@ -10399,7 +10441,7 @@ extern "C" { void empty_function(void); void empty_function(void); void empty_function(void); - void g_load_baseball(byte player_id, BallMode param_2, undefined param_3, byte param_4, byte param_5, uint param_6, void * param_7, int param_8); + void g_load_baseball(byte player_id, BallMode param_2, undefined1 param_3, byte param_4, byte param_5, uint param_6, void * param_7, int param_8); void empty_function(void); void empty_function(void); void empty_function(void); diff --git a/src/patches/fixes/fix_view_stage.cpp b/src/patches/fixes/fix_view_stage.cpp index b37e1174..45182577 100644 --- a/src/patches/fixes/fix_view_stage.cpp +++ b/src/patches/fixes/fix_view_stage.cpp @@ -29,7 +29,7 @@ void new_render_func(void) { mkb::mtxa_rotate_y((s16) ((int) mkb::view_stage_timer << 9)); mkb::load_gx_pos_nrm_mtx(mkb::mtxa, 0); mkb::avdisp_draw_model_culled_sort_auto(mkb::init_common_gma->model_entries[0x4d].model); - mkb::g_some_draw_func(); + mkb::fade_color_base_default(); if (mkb::stage_gma != (mkb::GmaBuffer*) 0x0) { pSVar10 = mkb::stagedef->coli_header_list; pIVar11 = mkb::itemgroups; @@ -91,7 +91,7 @@ void new_render_func(void) { if (dVar12 < (double) (pSVar8->scale).z) { dVar12 = (double) (pSVar8->scale).z; } - mkb::g_some_draw_func3(dVar12); + mkb::avdisp_set_scale_factor(dVar12); pGVar3 = (mkb::GmaModel*) mkb::g_some_draw_func4(dVar12, (int) pSVar8->stage_model_a); if ((pGVar3 != (mkb::GmaModel*) 0x0) && (bVar4 = mkb::g_is_sphere_visible((double) (float) ((double) pGVar3->bound_sphere_radius * From 8b886f6fc74771f46b219f04678e9b7d342808d3 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 20 Jan 2026 21:46:53 -0800 Subject: [PATCH 74/96] Add fix spooky action patch --- src/patches/fixes/fix_spooky_action.cpp | 124 ++++++++++++++++++++++++ src/patches/fixes/fix_spooky_action.h | 5 + src/utils/vecutil.h | 1 + 3 files changed, 130 insertions(+) create mode 100644 src/patches/fixes/fix_spooky_action.cpp create mode 100644 src/patches/fixes/fix_spooky_action.h diff --git a/src/patches/fixes/fix_spooky_action.cpp b/src/patches/fixes/fix_spooky_action.cpp new file mode 100644 index 00000000..b3640102 --- /dev/null +++ b/src/patches/fixes/fix_spooky_action.cpp @@ -0,0 +1,124 @@ +#include "fix_spooky_action.h" + +#include "patch.h" +#include "tickable.h" +#include "vecutil.h" +#include + +namespace { + +// Our special collision flag that's reset for each itemgroup +constexpr u32 COLI_FLAG_IG = 1 << 7; + +patch::Tramp s_init_physicsball_tramp; +patch::Tramp s_tf_physicsball_tramp; +patch::Tramp s_collide_physicsball_tramp; +// void stobj_bumper_coli(struct Stobj * stobj, struct PhysicsBall * physicsball); +patch::Tramp s_stobj_bumper_coli_tramp; +// void stobj_goalbag_coli(struct Stobj * stobj, struct PhysicsBall * physicsball); +patch::Tramp s_stobj_goalbag_coli_tramp; +// void stobj_goaltape_coli(struct Stobj * stobj, struct PhysicsBall * physicsball); +patch::Tramp s_stobj_goaltape_coli_tramp; +// void stobj_returngate_coli(struct Stobj * stobj, struct PhysicsBall * physicsball); +patch::Tramp s_stobj_returngate_coli_tramp; + +mkb::PhysicsBall s_clean_physicsball; + +void init_physicsball_from_ball(mkb::Ball* ball, mkb::PhysicsBall* physicsball) { + s_init_physicsball_tramp.dest(ball, physicsball); + s_clean_physicsball = *physicsball; +} + +void tf_physicsball_to_itemgroup_space(mkb::PhysicsBall* physicsball, int dest_ig_idx) { + if (physicsball->flags & COLI_FLAG_IG) { + physicsball->flags &= ~COLI_FLAG_IG; + s_clean_physicsball = *physicsball; + } + else { + *physicsball = s_clean_physicsball; + } + s_tf_physicsball_tramp.dest(physicsball, dest_ig_idx); +} + +void collide_ball_with_plane(mkb::PhysicsBall* physicsball, mkb::ColiPlane* plane) { + Vec prev_pos = physicsball->pos; + Vec prev_vel = physicsball->vel; + s_collide_physicsball_tramp.dest(physicsball, plane); + if (!VEC_EQUAL_EXACT(prev_pos, physicsball->pos) || + !VEC_EQUAL_EXACT(prev_vel, physicsball->vel)) { + physicsball->flags |= COLI_FLAG_IG; + } +} + +// Bumper collision +void bumper_coli(mkb::Stobj* stobj, mkb::PhysicsBall* physicsball) { + Vec prev_pos = physicsball->pos; + Vec prev_vel = physicsball->vel; + s_stobj_bumper_coli_tramp.dest(stobj, physicsball); + if (!VEC_EQUAL_EXACT(prev_pos, physicsball->pos) || + !VEC_EQUAL_EXACT(prev_vel, physicsball->vel)) { + physicsball->flags |= COLI_FLAG_IG; + } +} + +// Party Ball collision +void goalbag_coli(mkb::Stobj* stobj, mkb::PhysicsBall* physicsball) { + Vec prev_pos = physicsball->pos; + Vec prev_vel = physicsball->vel; + s_stobj_goalbag_coli_tramp.dest(stobj, physicsball); + if (!VEC_EQUAL_EXACT(prev_pos, physicsball->pos) || + !VEC_EQUAL_EXACT(prev_vel, physicsball->vel)) { + physicsball->flags |= COLI_FLAG_IG; + } +} + +// Goal tape resistance +void goaltape_coli(mkb::Stobj* stobj, mkb::PhysicsBall* physicsball) { + Vec prev_pos = physicsball->pos; + Vec prev_vel = physicsball->vel; + s_stobj_goaltape_coli_tramp.dest(stobj, physicsball); + if (!VEC_EQUAL_EXACT(prev_pos, physicsball->pos) || + !VEC_EQUAL_EXACT(prev_vel, physicsball->vel)) { + physicsball->flags |= COLI_FLAG_IG; + } +} + +// Wormhole surface resistance +void returngate_coli(mkb::Stobj* stobj, mkb::PhysicsBall* physicsball) { + Vec prev_pos = physicsball->pos; + Vec prev_vel = physicsball->vel; + s_stobj_returngate_coli_tramp.dest(stobj, physicsball); + if (!VEC_EQUAL_EXACT(prev_pos, physicsball->pos) || + !VEC_EQUAL_EXACT(prev_vel, physicsball->vel)) { + physicsball->flags |= COLI_FLAG_IG; + } +} + +}// namespace + +namespace fix_spooky_action { + +TICKABLE_DEFINITION(( + .name = "fix-spooky-action", + .description = "Prevent accumulated floating point error from transforming ball during collision", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + + patch::hook_function(s_init_physicsball_tramp, mkb::init_physicsball_from_ball, + init_physicsball_from_ball); + patch::hook_function(s_tf_physicsball_tramp, mkb::tf_physball_to_itemgroup_space, + tf_physicsball_to_itemgroup_space); + patch::hook_function(s_collide_physicsball_tramp, mkb::collide_ball_with_plane, + collide_ball_with_plane); + patch::hook_function(s_stobj_bumper_coli_tramp, mkb::stobj_bumper_coli, + bumper_coli); + patch::hook_function(s_stobj_goalbag_coli_tramp, mkb::stobj_goalbag_coli, + goalbag_coli); + patch::hook_function(s_stobj_goaltape_coli_tramp, mkb::stobj_goaltape_coli, + goaltape_coli); + patch::hook_function(s_stobj_returngate_coli_tramp, mkb::stobj_returngate_coli, + returngate_coli); +} + +}// namespace fix_spooky_action \ No newline at end of file diff --git a/src/patches/fixes/fix_spooky_action.h b/src/patches/fixes/fix_spooky_action.h new file mode 100644 index 00000000..2748ed1c --- /dev/null +++ b/src/patches/fixes/fix_spooky_action.h @@ -0,0 +1,5 @@ +#pragma once + +namespace fix_spooky_action { +void init_main_loop(); +} \ No newline at end of file diff --git a/src/utils/vecutil.h b/src/utils/vecutil.h index 7f93fcc4..b52845ff 100644 --- a/src/utils/vecutil.h +++ b/src/utils/vecutil.h @@ -13,3 +13,4 @@ #define VEC_DOT(v1, v2) ((v1).x * (v2).x + (v1).y * (v2).y + (v1).z * (v2).z) #define VEC_LEN_SQ(v) (VEC_DOT((v), (v))) #define VEC_ZERO (Vec3f{0, 0, 0}) +#define VEC_EQUAL_EXACT(v1, v2) ((v1.x == v2.x && v1.y == v2.y && v1.z == v2.z)) \ No newline at end of file From 823fdcd7d4c19468825d04befdc53ed1f6764726 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 20 Jan 2026 21:49:07 -0800 Subject: [PATCH 75/96] Add goal type sprites patch --- src/patches/extensions/goal_type_sprites.cpp | 151 +++++++++++++++++++ src/patches/extensions/goal_type_sprites.h | 7 + 2 files changed, 158 insertions(+) create mode 100644 src/patches/extensions/goal_type_sprites.cpp create mode 100644 src/patches/extensions/goal_type_sprites.h diff --git a/src/patches/extensions/goal_type_sprites.cpp b/src/patches/extensions/goal_type_sprites.cpp new file mode 100644 index 00000000..ace881cc --- /dev/null +++ b/src/patches/extensions/goal_type_sprites.cpp @@ -0,0 +1,151 @@ +#include "goal_type_sprites.h" + +#include "internal/heap.h" +#include "internal/log.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" + +namespace goal_type_sprites { + +TICKABLE_DEFINITION(( + .name = "goal-type-sprites", + .description = "Goal type sprites", + .enabled = true, + .init_main_loop = init_main_loop, )) + + +void create_goal_type_sprites() { + + mkb::StagedefColiHeader* itemgroup; + // Literal strings with Shift-JIS bytes + char* open_star = "\x81\x9b"; + char* full_star = "\x81\x9c"; + bool has_blue_goal = false; + bool has_green_goal = false; + bool has_red_goal = false; + + itemgroup = mkb::stagedef->coli_header_list; + + for (int itemgroup_idx = 0; itemgroup_idx < (int) mkb::stagedef->coli_header_count; itemgroup_idx++, itemgroup++) { + if (itemgroup->goal_count > 0) { + mkb::StagedefGoal* goal = itemgroup->goal_list; + for (int goal_idx = 0; goal_idx < (int) itemgroup->goal_count; goal_idx++, goal++) { + switch (goal->type) { + case mkb::Blue: + has_blue_goal = true; + break; + case mkb::Green: + has_green_goal = true; + break; + case mkb::Red: + has_red_goal = true; + break; + } + } + } + } + + mkb::Sprite* blue_sprite = mkb::create_sprite(); + if (blue_sprite != nullptr) { + blue_sprite->pos.x = 16.0; + blue_sprite->pos.y = 49.0; + blue_sprite->font = mkb::FONT_ASC_24x24; + blue_sprite->fpara1 = 1.0; + blue_sprite->fpara2 = 0.0; + blue_sprite->alpha = 1.0; + blue_sprite->mult_color.red = 0x00; + blue_sprite->mult_color.green = 0x00; + if (has_blue_goal) { + blue_sprite->mult_color.blue = 0xff; + } + else { + blue_sprite->mult_color.blue = 0x40; + } + blue_sprite->width = 0.8; + blue_sprite->height = 0.8; + blue_sprite->field21_0x20 = 1.0; + blue_sprite->field22_0x24 = 1.0; + blue_sprite->g_flags1 |= 0xa1000000; + blue_sprite->widescreen_translation_x = 0x60; + if (has_blue_goal) { + mkb::strcpy(blue_sprite->text, full_star); + } + else { + mkb::strcpy(blue_sprite->text, open_star); + } + } + + mkb::Sprite* green_sprite = mkb::create_sprite(); + if (green_sprite != nullptr) { + green_sprite->pos.x = 36.0; + green_sprite->pos.y = 49.0; + green_sprite->font = mkb::FONT_ASC_24x24; + green_sprite->fpara1 = 1.0; + green_sprite->fpara2 = 0.0; + green_sprite->alpha = 1.0; + green_sprite->mult_color.red = 0x00; + if (has_green_goal) { + green_sprite->mult_color.green = 0xff; + } + else { + green_sprite->mult_color.green = 0x40; + } + green_sprite->mult_color.blue = 0x00; + green_sprite->width = 0.8; + green_sprite->height = 0.8; + green_sprite->field21_0x20 = 1.0; + green_sprite->field22_0x24 = 1.0; + green_sprite->g_flags1 |= 0xa1000000; + green_sprite->widescreen_translation_x = 0x60; + if (has_green_goal) { + mkb::strcpy(green_sprite->text, full_star); + } + else { + mkb::strcpy(green_sprite->text, open_star); + } + } + + mkb::Sprite* red_sprite = mkb::create_sprite(); + if (red_sprite != nullptr) { + red_sprite->pos.x = 56.0; + red_sprite->pos.y = 49.0; + red_sprite->font = mkb::FONT_ASC_24x24; + red_sprite->fpara1 = 1.0; + red_sprite->fpara2 = 0.0; + red_sprite->alpha = 1.0; + if (has_red_goal) { + red_sprite->mult_color.red = 0xff; + } + else { + red_sprite->mult_color.red = 0x40; + } + red_sprite->mult_color.green = 0x00; + red_sprite->mult_color.blue = 0x00; + red_sprite->width = 0.8; + red_sprite->height = 0.8; + red_sprite->field21_0x20 = 1.0; + red_sprite->field22_0x24 = 1.0; + red_sprite->g_flags1 |= 0xa1000000; + red_sprite->widescreen_translation_x = 0x60; + if (has_red_goal) { + mkb::strcpy(red_sprite->text, full_star); + } + else { + mkb::strcpy(red_sprite->text, open_star); + } + } +} + +void init_main_loop() { + + static patch::Tramp s_score_sprites_tramp; + patch::hook_function( + s_score_sprites_tramp, + mkb::create_score_sprites, [](float x, float y) { + s_score_sprites_tramp.dest(x, y); + create_goal_type_sprites(); + }); +} + +}// namespace goal_type_sprites diff --git a/src/patches/extensions/goal_type_sprites.h b/src/patches/extensions/goal_type_sprites.h new file mode 100644 index 00000000..3645d0e8 --- /dev/null +++ b/src/patches/extensions/goal_type_sprites.h @@ -0,0 +1,7 @@ +#pragma once + +namespace goal_type_sprites { + +void init_main_loop(); + +}// namespace goal_type_sprites \ No newline at end of file From f1bbd6d6d04bedf18c934c576da5957a9ce47976 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 20 Jan 2026 23:42:24 -0800 Subject: [PATCH 76/96] Add custom starting monkey count patch --- .../custom/custom_starting_monkey_count.cpp | 27 +++++++++++++++++++ .../custom/custom_starting_monkey_count.h | 7 +++++ src/patches/extensions/goal_type_sprites.cpp | 1 - 3 files changed, 34 insertions(+), 1 deletion(-) create mode 100644 src/patches/custom/custom_starting_monkey_count.cpp create mode 100644 src/patches/custom/custom_starting_monkey_count.h diff --git a/src/patches/custom/custom_starting_monkey_count.cpp b/src/patches/custom/custom_starting_monkey_count.cpp new file mode 100644 index 00000000..d9654053 --- /dev/null +++ b/src/patches/custom/custom_starting_monkey_count.cpp @@ -0,0 +1,27 @@ +#include "custom_starting_monkey_count.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_starting_monkey_count { + +int monkey_count = 3; + +TICKABLE_DEFINITION(( + .name = "custom-starting-monkey-count", + .description = "Custom starting monkey count patch", + .active_value = monkey_count, + .lower_bound = 1, + .upper_bound = 99, + .init_main_loop = init_main_loop, )) + +// In the function which sets the number of unlocked monkeys to 3 on boot, set it to our +// custom monkey count instead +void init_main_loop() { + monkey_count = *active_tickable_ptr->active_value;// Get our monkey count + patch::write_word(reinterpret_cast(0x803DD450), PPC_INSTR_LI(PPC_R0, monkey_count)); +} + +}// namespace custom_starting_monkey_count diff --git a/src/patches/custom/custom_starting_monkey_count.h b/src/patches/custom/custom_starting_monkey_count.h new file mode 100644 index 00000000..1a90f5f5 --- /dev/null +++ b/src/patches/custom/custom_starting_monkey_count.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_starting_monkey_count { + +void init_main_loop(); + +}// namespace custom_starting_monkey_count \ No newline at end of file diff --git a/src/patches/extensions/goal_type_sprites.cpp b/src/patches/extensions/goal_type_sprites.cpp index ace881cc..e6df8654 100644 --- a/src/patches/extensions/goal_type_sprites.cpp +++ b/src/patches/extensions/goal_type_sprites.cpp @@ -11,7 +11,6 @@ namespace goal_type_sprites { TICKABLE_DEFINITION(( .name = "goal-type-sprites", .description = "Goal type sprites", - .enabled = true, .init_main_loop = init_main_loop, )) From afda55b6bf83af7798cba9a15e1e59dd142fedc2 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 21 Jan 2026 20:48:54 -0800 Subject: [PATCH 77/96] Add Challenge Mode Game Settings removal patch --- .../remove_challenge_game_settings.cpp | 21 +++++++++++++++++++ .../removals/remove_challenge_game_settings.h | 7 +++++++ 2 files changed, 28 insertions(+) create mode 100644 src/patches/removals/remove_challenge_game_settings.cpp create mode 100644 src/patches/removals/remove_challenge_game_settings.h diff --git a/src/patches/removals/remove_challenge_game_settings.cpp b/src/patches/removals/remove_challenge_game_settings.cpp new file mode 100644 index 00000000..e478c666 --- /dev/null +++ b/src/patches/removals/remove_challenge_game_settings.cpp @@ -0,0 +1,21 @@ +#include "remove_challenge_game_settings.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" +#include "utils/ppcutil.h" + +namespace remove_challenge_game_settings { + +TICKABLE_DEFINITION(( + .name = "remove-challenge-game-settings-screen", + .description = "Challenge Mode Game Settings removal", + .init_sel_ngc = init_sel_ngc, )) + +// In the function which handles what screen to take us to after selecting a difficulty, +// replace the Game Settings menu call with one to start Challenge Mode +void init_sel_ngc() { + patch::write_word(reinterpret_cast(0x808FFB40), PPC_INSTR_LI(PPC_R6, mkb::MENUSCREEN_CHALLENGE_DIFFICULTY)); +} + +}// namespace remove_challenge_game_settings diff --git a/src/patches/removals/remove_challenge_game_settings.h b/src/patches/removals/remove_challenge_game_settings.h new file mode 100644 index 00000000..81a19b30 --- /dev/null +++ b/src/patches/removals/remove_challenge_game_settings.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_challenge_game_settings { + +void init_sel_ngc(); + +}// namespace remove_challenge_game_settings \ No newline at end of file From 4a8b0b214d002775feffa5457da36b32d7e911a5 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 21 Jan 2026 21:08:59 -0800 Subject: [PATCH 78/96] Add patch to enable autosave by default --- src/patches/tweaks/enable_autosave.cpp | 18 ++++++++++++++++++ src/patches/tweaks/enable_autosave.h | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 src/patches/tweaks/enable_autosave.cpp create mode 100644 src/patches/tweaks/enable_autosave.h diff --git a/src/patches/tweaks/enable_autosave.cpp b/src/patches/tweaks/enable_autosave.cpp new file mode 100644 index 00000000..dee342ae --- /dev/null +++ b/src/patches/tweaks/enable_autosave.cpp @@ -0,0 +1,18 @@ +#include "enable_autosave.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" + +namespace enable_autosave { + +TICKABLE_DEFINITION(( + .name = "autosave-on-by-default", + .description = "Autosave on by default", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + mkb::autosave = true; +} + +}// namespace enable_autosave diff --git a/src/patches/tweaks/enable_autosave.h b/src/patches/tweaks/enable_autosave.h new file mode 100644 index 00000000..6aa43044 --- /dev/null +++ b/src/patches/tweaks/enable_autosave.h @@ -0,0 +1,7 @@ +#pragma once + +namespace enable_autosave { + +void init_main_loop(); + +}// namespace enable_autosave \ No newline at end of file From 127bf125c1380da4b997ebb634c79f75313635f9 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 21 Jan 2026 21:11:50 -0800 Subject: [PATCH 79/96] Add patch to unlock Master by default --- src/patches/tweaks/unlock_master.cpp | 18 ++++++++++++++++++ src/patches/tweaks/unlock_master.h | 7 +++++++ 2 files changed, 25 insertions(+) create mode 100644 src/patches/tweaks/unlock_master.cpp create mode 100644 src/patches/tweaks/unlock_master.h diff --git a/src/patches/tweaks/unlock_master.cpp b/src/patches/tweaks/unlock_master.cpp new file mode 100644 index 00000000..8aabcba6 --- /dev/null +++ b/src/patches/tweaks/unlock_master.cpp @@ -0,0 +1,18 @@ +#include "unlock_master.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" + +namespace unlock_master { + +TICKABLE_DEFINITION(( + .name = "master-unlocked-by-default", + .description = "Master unlocked by default", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + mkb::unlock_info_ptr->master_unlocked = 1; +} + +}// namespace unlock_master diff --git a/src/patches/tweaks/unlock_master.h b/src/patches/tweaks/unlock_master.h new file mode 100644 index 00000000..5b873d79 --- /dev/null +++ b/src/patches/tweaks/unlock_master.h @@ -0,0 +1,7 @@ +#pragma once + +namespace unlock_master { + +void init_main_loop(); + +}// namespace unlock_master \ No newline at end of file From c9543a9ad90f406585a99048d2ffcf8d5afa800b Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 21 Jan 2026 21:37:09 -0800 Subject: [PATCH 80/96] Add custom bananas per 1UP patch --- .../custom/custom_banana_count_per_1up.cpp | 27 +++++++++++++++++++ .../custom/custom_banana_count_per_1up.h | 7 +++++ src/utils/ppcutil.h | 6 ++++- 3 files changed, 39 insertions(+), 1 deletion(-) create mode 100644 src/patches/custom/custom_banana_count_per_1up.cpp create mode 100644 src/patches/custom/custom_banana_count_per_1up.h diff --git a/src/patches/custom/custom_banana_count_per_1up.cpp b/src/patches/custom/custom_banana_count_per_1up.cpp new file mode 100644 index 00000000..e64f71cb --- /dev/null +++ b/src/patches/custom/custom_banana_count_per_1up.cpp @@ -0,0 +1,27 @@ +#include "custom_banana_count_per_1up.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_banana_count_per_1up { + +int banana_count = 100; + +TICKABLE_DEFINITION(( + .name = "custom-banana-count-per-1up", + .description = "Custom bananas per 1UP patch", + .active_value = banana_count, + .lower_bound = 1, + .upper_bound = 999, + .init_main_loop = init_main_loop, )) + +// In add_bananas, change the amount of bananas to add a life + subtract to our custom count +void init_main_loop() { + banana_count = *active_tickable_ptr->active_value;// Get our banana count + patch::write_word(reinterpret_cast(0x802B8240), PPC_INSTR_CMPWI(PPC_R0, banana_count)); + patch::write_word(reinterpret_cast(0x802B8258), PPC_INSTR_SUBI(PPC_R0, PPC_R3, banana_count)); +} + +}// namespace custom_banana_count_per_1up diff --git a/src/patches/custom/custom_banana_count_per_1up.h b/src/patches/custom/custom_banana_count_per_1up.h new file mode 100644 index 00000000..9dbbd7b4 --- /dev/null +++ b/src/patches/custom/custom_banana_count_per_1up.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_banana_count_per_1up { + +void init_main_loop(); + +}// namespace custom_banana_count_per_1up \ No newline at end of file diff --git a/src/utils/ppcutil.h b/src/utils/ppcutil.h index 12861032..2a2f91cd 100644 --- a/src/utils/ppcutil.h +++ b/src/utils/ppcutil.h @@ -16,7 +16,11 @@ #define PPC_INSTR_NOP() (0x60000000) -// TODO: PPC_INSR_CMPWI +#define PPC_INSTR_CMPWI(rA, imm) (0x2C000000u + ((u32) (rA) << 16) + (u16) (imm)) + +#define PPC_INSTR_SUBI(dest_register, src_register, value) \ + (0x38000000u + ((u32) (dest_register) << 21) + ((u32) (src_register) << 16) + (u16) (-(s16) (value))) + #define PPC_R0 0 #define PPC_R1 1 From 3ae7af89a0cc3d65ed2e09ffe48bd560d6a8d997 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 22 Jan 2026 14:11:51 -0800 Subject: [PATCH 81/96] Add patches to set custom reflection resolutions --- .../custom/custom_reflection_res_height.cpp | 27 +++++++++++++++++++ .../custom/custom_reflection_res_height.h | 7 +++++ .../custom/custom_reflection_res_width.cpp | 27 +++++++++++++++++++ .../custom/custom_reflection_res_width.h | 7 +++++ 4 files changed, 68 insertions(+) create mode 100644 src/patches/custom/custom_reflection_res_height.cpp create mode 100644 src/patches/custom/custom_reflection_res_height.h create mode 100644 src/patches/custom/custom_reflection_res_width.cpp create mode 100644 src/patches/custom/custom_reflection_res_width.h diff --git a/src/patches/custom/custom_reflection_res_height.cpp b/src/patches/custom/custom_reflection_res_height.cpp new file mode 100644 index 00000000..413f1d1c --- /dev/null +++ b/src/patches/custom/custom_reflection_res_height.cpp @@ -0,0 +1,27 @@ +#include "custom_reflection_res_height.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_reflection_res_height { + +int height = 448; + +TICKABLE_DEFINITION(( + .name = "custom-reflection-resolution-height", + .description = "Custom reflection resolution height", + .active_value = height, + .lower_bound = 1, + .upper_bound = 448, + .init_main_loop = init_main_loop, )) + +// In the function which loads reflective stage objects, change the reflection resolution's height +// to our custom height +void init_main_loop() { + height = *active_tickable_ptr->active_value;// Get our height + patch::write_word(reinterpret_cast(0x8034aee0), PPC_INSTR_LI(PPC_R0, height)); +} + +}// namespace custom_reflection_res_height diff --git a/src/patches/custom/custom_reflection_res_height.h b/src/patches/custom/custom_reflection_res_height.h new file mode 100644 index 00000000..2bfa5cda --- /dev/null +++ b/src/patches/custom/custom_reflection_res_height.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_reflection_res_height { + +void init_main_loop(); + +}// namespace custom_reflection_res_height \ No newline at end of file diff --git a/src/patches/custom/custom_reflection_res_width.cpp b/src/patches/custom/custom_reflection_res_width.cpp new file mode 100644 index 00000000..7ff2c902 --- /dev/null +++ b/src/patches/custom/custom_reflection_res_width.cpp @@ -0,0 +1,27 @@ +#include "custom_reflection_res_width.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_reflection_res_width { + +int width = 640; + +TICKABLE_DEFINITION(( + .name = "custom-reflection-resolution-width", + .description = "Custom reflection resolution width", + .active_value = width, + .lower_bound = 1, + .upper_bound = 640, + .init_main_loop = init_main_loop, )) + +// In the function which loads reflective stage objects, change the reflection resolution's width +// to our custom width +void init_main_loop() { + width = *active_tickable_ptr->active_value;// Get our width + patch::write_word(reinterpret_cast(0x8034aed8), PPC_INSTR_LI(PPC_R0, width)); +} + +}// namespace custom_reflection_res_width diff --git a/src/patches/custom/custom_reflection_res_width.h b/src/patches/custom/custom_reflection_res_width.h new file mode 100644 index 00000000..7d39fd73 --- /dev/null +++ b/src/patches/custom/custom_reflection_res_width.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_reflection_res_width { + +void init_main_loop(); + +}// namespace custom_reflection_res_width \ No newline at end of file From fc0c5432f3a538f11717024f35b2470bdb7ec435 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 22 Jan 2026 14:41:15 -0800 Subject: [PATCH 82/96] Add SMB1 score count patch --- src/patches/tweaks/smb1_score_count.cpp | 57 +++++++++++++++++++++++++ src/patches/tweaks/smb1_score_count.h | 7 +++ 2 files changed, 64 insertions(+) create mode 100644 src/patches/tweaks/smb1_score_count.cpp create mode 100644 src/patches/tweaks/smb1_score_count.h diff --git a/src/patches/tweaks/smb1_score_count.cpp b/src/patches/tweaks/smb1_score_count.cpp new file mode 100644 index 00000000..6c030876 --- /dev/null +++ b/src/patches/tweaks/smb1_score_count.cpp @@ -0,0 +1,57 @@ +#include "smb1_score_count.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "mkb/mkb.h" + +namespace smb1_score_count { + +TICKABLE_DEFINITION(( + .name = "smb1-score-count", + .description = "SMB1 score count", + .init_main_loop = init_main_loop, )) + +int frame_counter = 0; +int lerp_duration; + +void sprite_tick(u8* status, mkb::Sprite* sprite) { + float score = (float) mkb::balls[mkb::curr_player_idx].score; + float old_score = sprite->fpara1; + float delta = score - old_score; + float displayed; + int final_score; + + if (mkb::sub_mode != mkb::SMD_GAME_GOAL_REPLAY_MAIN) { + lerp_duration = 30; + } + else { + lerp_duration = 120; + } + + if (score > old_score) { + if (frame_counter < lerp_duration) { + displayed = old_score + frame_counter * (delta / lerp_duration); + frame_counter++; + if (mkb::sub_mode == mkb::SMD_GAME_GOAL_REPLAY_MAIN && (frame_counter % 4 == 0)) { + mkb::call_SoundReqID_arg_2(46); + } + } + else { + sprite->fpara1 = score; + frame_counter = 0; + } + } + else { + displayed = score; + } + + final_score = mkb::__cvt_fp2unsigned((double) displayed); + mkb::sprintf(sprite->text, "%d", final_score); + return; +} + +void init_main_loop() { + patch::hook_function(mkb::sprite_score_tick, sprite_tick); +} + +}// namespace smb1_score_count diff --git a/src/patches/tweaks/smb1_score_count.h b/src/patches/tweaks/smb1_score_count.h new file mode 100644 index 00000000..0e69e554 --- /dev/null +++ b/src/patches/tweaks/smb1_score_count.h @@ -0,0 +1,7 @@ +#pragma once + +namespace smb1_score_count { + +void init_main_loop(); + +}// namespace smb1_score_count \ No newline at end of file From b788f038fc037b4e16116302ce80acab17b5c49e Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 22 Jan 2026 19:57:21 -0800 Subject: [PATCH 83/96] Add custom Story Mode layout patch --- src/config/config.cpp | 114 ++++++++++++++++++++ src/internal/assembly.cpp | 1 + src/internal/assembly.h | 12 +++ src/patches/custom/custom_story_entries.cpp | 46 ++++++++ src/patches/custom/custom_story_entries.h | 7 ++ 5 files changed, 180 insertions(+) create mode 100644 src/patches/custom/custom_story_entries.cpp create mode 100644 src/patches/custom/custom_story_entries.h diff --git a/src/config/config.cpp b/src/config/config.cpp index 03e1bf2a..fe4d1ba6 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -102,6 +102,116 @@ void parse_menu_option_toggles(char* buf) { } while (buf < end_of_section); } +static void skip_spaces(char*& p) { + while (*p == ' ' || *p == '\t') p++; +} + +static bool parse_csv_ints(char* value, int* out, int count) { + char* p = value; + + for (int i = 0; i < count; ++i) { + skip_spaces(p); + + // Parse integer + out[i] = mkb::atoi(p); + + // Find next comma if more values expected + if (i + 1 < count) { + p = mkb::strchr(p, ','); + if (!p) return false; + p++;// skip comma + } + } + + return true; +} + + +// Parses W- +static bool parse_world_stage_key(const char* key, int& world_idx, int& stage_idx) { + if (key == nullptr || key[0] != 'W') return false; + + // world starts after 'W' + int w = mkb::atoi(const_cast(key + 1)); + + // find '-' + char* dash = mkb::strchr(const_cast(key), '-'); + if (!dash) return false; + + // stage starts after '-' + int s = mkb::atoi(dash + 1); + + if (w < 1 || w > main::WORLD_COUNT) return false; + if (s < 1 || s > main::STAGES_PER_WORLD) return false; + + world_idx = w - 1; + stage_idx = s - 1; + return true; +} + + +void parse_story_mode_entries(char* buf) { + buf = mkb::strchr(buf, '\n') + 1; + + char* end_of_section = mkb::strchr(buf, '}'); + char key[64] = {0}; + char value[128] = {0}; + + do { + char *key_start, *key_end, *end_of_line; + key_start = mkb::strchr(buf, '\t') + 1; + key_end = mkb::strchr(buf, ':'); + MOD_ASSERT_MSG(key_start < key_end, + "Key start after key end, did you start your key with a tab and not spaces?"); + end_of_line = mkb::strchr(buf, '\n'); + + mkb::strncpy(key, key_start, (key_end - key_start)); + mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); + + int world_idx = 0, stage_idx = 0; + MOD_ASSERT_MSG( + parse_world_stage_key(key, world_idx, stage_idx), + "Invalid story key format (expected W<1-10>-<1-10>)"); + + int vals[3] = {0}; + + MOD_ASSERT_MSG( + parse_csv_ints(value, vals, 3), + "Invalid story value format (expected: stage ID, time limit, difficulty)"); + + int stage_id_i = vals[0]; + int time_limit_i = vals[1]; + int difficulty_i = vals[2]; + + + MOD_ASSERT_MSG(stage_id_i >= 0 && stage_id_i <= 420, "Stage ID out of range (0-420)"); + MOD_ASSERT_MSG(time_limit_i >= 0 && time_limit_i <= 360, "Time limit out of range (0-360)"); + MOD_ASSERT_MSG(difficulty_i >= 0 && difficulty_i <= 10, "Difficulty out of range (0-10)"); + + main::NewStoryStageEntry& entry = + main::new_story_entries[world_idx][stage_idx]; + + MOD_ASSERT_MSG(!entry.set, "Duplicate Story Mode entry for same world/stage"); + + entry.stage_id = static_cast(stage_id_i); + entry.time_limit = static_cast(time_limit_i); + entry.difficulty = static_cast(difficulty_i); + entry.set = true; + + buf = end_of_line + 1; + mkb::memset(key, '\0', sizeof(key)); + mkb::memset(value, '\0', sizeof(value)); + } while (buf < end_of_section); + + for (int w = 0; w < main::WORLD_COUNT; ++w) { + for (int s = 0; s < main::STAGES_PER_WORLD; ++s) { + MOD_ASSERT_MSG(main::new_story_entries[w][s].set, "Missing Story Mode entry"); + } + } + + LOG("Story Mode Entries loaded at: 0x%X", &main::new_story_entries); +} + void parse_function_toggles(char* buf) { // Enters from section parsing, so skip to the next line buf = mkb::strchr(buf, '\n') + 1; @@ -220,6 +330,10 @@ void parse_config() { LOG("Music ID list loaded at: 0x%X", &main::bgm_id_lookup); } + else if (STREQ(section, "Story Mode Entries")) { + parse_story_mode_entries(section_end); + } + else { LOG("Unknown category %s found in config!", section); } diff --git a/src/internal/assembly.cpp b/src/internal/assembly.cpp index 114d7dfb..1096f3b5 100644 --- a/src/internal/assembly.cpp +++ b/src/internal/assembly.cpp @@ -5,5 +5,6 @@ namespace main { // TODO: make dyanmic u16 bgm_id_lookup[421] = {0}; u16 theme_id_lookup[421] = {0}; +NewStoryStageEntry new_story_entries[WORLD_COUNT][STAGES_PER_WORLD]; }// namespace main diff --git a/src/internal/assembly.h b/src/internal/assembly.h index 3ca753ff..d7079d1a 100644 --- a/src/internal/assembly.h +++ b/src/internal/assembly.h @@ -4,6 +4,18 @@ namespace main { +struct NewStoryStageEntry { + u16 stage_id; // 0 to 420 + u8 difficulty; // 0 to 10 + u16 time_limit;// 0 to 360 seconds + bool set; // to detect missing/duplicate entries +}; + +static constexpr int WORLD_COUNT = 10; +static constexpr int STAGES_PER_WORLD = 10; + +extern NewStoryStageEntry new_story_entries[WORLD_COUNT][STAGES_PER_WORLD]; + extern "C" { // Assembly overwrite functions diff --git a/src/patches/custom/custom_story_entries.cpp b/src/patches/custom/custom_story_entries.cpp new file mode 100644 index 00000000..6f24ff6a --- /dev/null +++ b/src/patches/custom/custom_story_entries.cpp @@ -0,0 +1,46 @@ +#include "custom_story_entries.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_story_entries { + +TICKABLE_DEFINITION(( + .name = "custom-story-mode-entries", + .description = "Custom Story Mode entries", + .init_main_loop = init_main_loop, )) + +int get_new_story_timers(int world, int world_stage) { + return (int) main::new_story_entries[world][world_stage].time_limit * 60; +} + +void init_main_loop() { + mkb::SmStageInfo* const worlds[main::WORLD_COUNT] = { + mkb::sm_stage_infos_world1, + mkb::sm_stage_infos_world2, + mkb::sm_stage_infos_world3, + mkb::sm_stage_infos_world4, + mkb::sm_stage_infos_world5, + mkb::sm_stage_infos_world6, + mkb::sm_stage_infos_world7, + mkb::sm_stage_infos_world8, + mkb::sm_stage_infos_world9, + mkb::sm_stage_infos_world10, + }; + + for (int w = 0; w < main::WORLD_COUNT; ++w) { + for (int s = 0; s < main::STAGES_PER_WORLD; ++s) { + const main::NewStoryStageEntry& src = main::new_story_entries[w][s]; + + worlds[w][s].stage_id = src.stage_id; + worlds[w][s].difficulty = src.difficulty; + } + } + + patch::write_branch( + reinterpret_cast(mkb::get_storymode_stage_time_limit), + reinterpret_cast(get_new_story_timers)); +} +}// namespace custom_story_entries diff --git a/src/patches/custom/custom_story_entries.h b/src/patches/custom/custom_story_entries.h new file mode 100644 index 00000000..7fad661e --- /dev/null +++ b/src/patches/custom/custom_story_entries.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_story_entries { + +void init_main_loop(); + +}// namespace custom_story_entries \ No newline at end of file From f1e97fe99c344031fbcb95abb279d249e7934590 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Thu, 22 Jan 2026 20:33:59 -0800 Subject: [PATCH 84/96] Implement PPC_INSTR_CMPWI --- src/patches/custom/custom_world_count.cpp | 4 +- src/patches/extensions/death_counter.cpp | 3 +- .../extensions/four_digit_banana_counter.cpp | 2 +- src/patches/extensions/smb1_camera_toggle.cpp | 53 +++++++++++-------- src/patches/fixes/fix_goal_types.cpp | 4 +- src/patches/fixes/fix_monkey_counter.cpp | 4 +- src/patches/removals/remove_desert_haze.cpp | 4 +- src/patches/removals/remove_hardcodes.cpp | 42 +++++++-------- .../story/story_double_stage_select.cpp | 3 +- 9 files changed, 65 insertions(+), 54 deletions(-) diff --git a/src/patches/custom/custom_world_count.cpp b/src/patches/custom/custom_world_count.cpp index 3af86486..bff7c7de 100644 --- a/src/patches/custom/custom_world_count.cpp +++ b/src/patches/custom/custom_world_count.cpp @@ -46,8 +46,8 @@ void init_sel_ngc() { // Update the practice mode story mode display counter to show the proper number of worlds // Visually update the indicator - patch::write_word(reinterpret_cast(0x8090dbd0), - (0x2c1a0000 | world_count)); + patch::write_word(reinterpret_cast(0x8090DBD0), + PPC_INSTR_CMPWI(PPC_R26, world_count)); // Update the indicator logic patch::write_word(reinterpret_cast(0x80900f08), PPC_INSTR_LI(PPC_R29, world_count)); diff --git a/src/patches/extensions/death_counter.cpp b/src/patches/extensions/death_counter.cpp index 725a3eab..f822737f 100644 --- a/src/patches/extensions/death_counter.cpp +++ b/src/patches/extensions/death_counter.cpp @@ -2,6 +2,7 @@ #include "internal/patch.h" #include "internal/tickable.h" +#include "utils/ppcutil.h" namespace death_counter { @@ -83,7 +84,7 @@ void init_main_game() { // menu, change the check for unlocked monkeys to be less than 4 to less than // 255, effectively never displaying the Gameplay Settings menu void init_sel_ngc() { - patch::write_word(reinterpret_cast(0x808ffb14), 0x2c0300ff);// cmpwi r3, 255 + patch::write_word(reinterpret_cast(0x808ffb14), PPC_INSTR_CMPWI(PPC_R3, 255)); } }// namespace death_counter diff --git a/src/patches/extensions/four_digit_banana_counter.cpp b/src/patches/extensions/four_digit_banana_counter.cpp index 13548ac5..49656bee 100644 --- a/src/patches/extensions/four_digit_banana_counter.cpp +++ b/src/patches/extensions/four_digit_banana_counter.cpp @@ -106,7 +106,7 @@ void create_new_banana_counter_sprites(u8* status, mkb::Sprite* pSVar1) { // sprite create function calling our sprite create function instead. void init_main_loop() { // In add_bananas, return if the current count after adding is less than 9999 instead of 999 - patch::write_word(reinterpret_cast(0x802b8284), 0x2c00270f);// cmpwi r0, 9999 + patch::write_word(reinterpret_cast(0x802b8284), PPC_INSTR_CMPWI(PPC_R0, 9999)); // In add_bananas, cap the max banana count to 9999 instead of 999 patch::write_word(reinterpret_cast(0x802b828c), PPC_INSTR_LI(PPC_R0, 9999)); diff --git a/src/patches/extensions/smb1_camera_toggle.cpp b/src/patches/extensions/smb1_camera_toggle.cpp index aeeac0c7..19de2115 100644 --- a/src/patches/extensions/smb1_camera_toggle.cpp +++ b/src/patches/extensions/smb1_camera_toggle.cpp @@ -97,56 +97,65 @@ void tick() { // Billiards if (mkb::pausemenu_type == mkb::PMT_CHALLENGE) { if ((mkb::g_some_status_bitflag_maybe_pause_related & 4) != 0) { - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0009); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 9)); } else { - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0001); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 1)); } + if (mkb::g_current_pause_menu_entry_count == 5) { // Special handler for CM retry - patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0003); - patch::write_word(reinterpret_cast(0x80273678), 0x2c000003); + patch::write_word(reinterpret_cast(0x8032a91c), PPC_INSTR_CMPWI(PPC_R28, 3)); + patch::write_word(reinterpret_cast(0x80273678), PPC_INSTR_CMPWI(PPC_R0, 3)); } else { - patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0002); - patch::write_word(reinterpret_cast(0x80273678), 0x2c000002); + patch::write_word(reinterpret_cast(0x8032a91c), PPC_INSTR_CMPWI(PPC_R28, 2)); + patch::write_word(reinterpret_cast(0x80273678), PPC_INSTR_CMPWI(PPC_R0, 2)); } - patch::write_word(reinterpret_cast(0x80273664), 0x2c000001); + + patch::write_word(reinterpret_cast(0x80273664), PPC_INSTR_CMPWI(PPC_R0, 1)); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, " 1"); mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "2"); } + else if (mkb::pausemenu_type == mkb::PMT_STORY_PLAY) { if ((mkb::g_some_status_bitflag_maybe_pause_related & 4) != 0) { - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b000e); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 14)); } else { - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0006); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 6)); } - patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0003); - patch::write_word(reinterpret_cast(0x80273664), 0x2c000006); - patch::write_word(reinterpret_cast(0x80273678), 0x2c000003); + + patch::write_word(reinterpret_cast(0x8032a91c), PPC_INSTR_CMPWI(PPC_R28, 3)); + patch::write_word(reinterpret_cast(0x80273664), PPC_INSTR_CMPWI(PPC_R0, 6)); + patch::write_word(reinterpret_cast(0x80273678), PPC_INSTR_CMPWI(PPC_R0, 3)); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, " 1"); mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "2"); } + else if (mkb::pausemenu_type == mkb::PMT_PRACTICE) { if ((mkb::g_some_status_bitflag_maybe_pause_related & 4) != 0) { - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b000a); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 10)); } else { - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0002); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 2)); } - patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0003); - patch::write_word(reinterpret_cast(0x80273664), 0x2c000002); - patch::write_word(reinterpret_cast(0x80273678), 0x2c000003); + + patch::write_word(reinterpret_cast(0x8032a91c), PPC_INSTR_CMPWI(PPC_R28, 3)); + patch::write_word(reinterpret_cast(0x80273664), PPC_INSTR_CMPWI(PPC_R0, 2)); + patch::write_word(reinterpret_cast(0x80273678), PPC_INSTR_CMPWI(PPC_R0, 3)); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, " 1"); mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "2"); } else { - // Original instructions (Billiards) - patch::write_word(reinterpret_cast(0x8032a914), 0x2c1b0004); - patch::write_word(reinterpret_cast(0x8032a91c), 0x2c1c0001); - patch::write_word(reinterpret_cast(0x80273664), 0x2c000004); - patch::write_word(reinterpret_cast(0x80273678), 0x2c000001); + patch::write_word(reinterpret_cast(0x8032a914), PPC_INSTR_CMPWI(PPC_R27, 4)); + patch::write_word(reinterpret_cast(0x8032a91c), PPC_INSTR_CMPWI(PPC_R28, 1)); + patch::write_word(reinterpret_cast(0x80273664), PPC_INSTR_CMPWI(PPC_R0, 4)); + patch::write_word(reinterpret_cast(0x80273678), PPC_INSTR_CMPWI(PPC_R0, 1)); + mkb::strcpy(mkb::PAUSEMENU_ON_STRING, "ON"); mkb::strcpy(mkb::PAUSEMENU_OFF_STRING, "OFF"); } diff --git a/src/patches/fixes/fix_goal_types.cpp b/src/patches/fixes/fix_goal_types.cpp index 37d4938c..643a4cd9 100644 --- a/src/patches/fixes/fix_goal_types.cpp +++ b/src/patches/fixes/fix_goal_types.cpp @@ -16,8 +16,8 @@ TICKABLE_DEFINITION(( // preventing score and warp issues on stages with loads of // goals void init_main_loop() { - patch::write_word(reinterpret_cast(0x802d81a8), 0x2c0800ff);// cmpwi r8, 255 - patch::write_word(reinterpret_cast(0x8031373c), 0x2c0500ff);// cmpwi r5, 255 + patch::write_word(reinterpret_cast(0x802d81a8), PPC_INSTR_CMPWI(PPC_R8, 255)); + patch::write_word(reinterpret_cast(0x8031373c), PPC_INSTR_CMPWI(PPC_R5, 255)); } }// namespace fix_goal_types diff --git a/src/patches/fixes/fix_monkey_counter.cpp b/src/patches/fixes/fix_monkey_counter.cpp index c9a77494..1a82ebb3 100644 --- a/src/patches/fixes/fix_monkey_counter.cpp +++ b/src/patches/fixes/fix_monkey_counter.cpp @@ -16,8 +16,8 @@ TICKABLE_DEFINITION(( // 255 instead of 4, effectively never executing leftover // sprite code from SMB1 void init_main_loop() { - patch::write_word(reinterpret_cast(0x80332874), 0x2c0000ff);// cmpwi r0, 255 - patch::write_word(reinterpret_cast(0x80332f94), 0x2c0000ff);// cmpwi r0, 255 + patch::write_word(reinterpret_cast(0x80332874), PPC_INSTR_CMPWI(PPC_R0, 255)); + patch::write_word(reinterpret_cast(0x80332f94), PPC_INSTR_CMPWI(PPC_R0, 255)); } }// namespace fix_monkey_counter diff --git a/src/patches/removals/remove_desert_haze.cpp b/src/patches/removals/remove_desert_haze.cpp index facb8d84..2b267e5d 100644 --- a/src/patches/removals/remove_desert_haze.cpp +++ b/src/patches/removals/remove_desert_haze.cpp @@ -2,6 +2,7 @@ #include "internal/patch.h" #include "internal/tickable.h" +#include "utils/ppcutil.h" namespace remove_desert_haze { @@ -14,9 +15,8 @@ TICKABLE_DEFINITION(( // proper fix soon. In a function that sets a parameter that enables heat // haze for the specific desert theme ID, the theme ID is compared to 0xffff // instead of 0x7. -// 0x2c00ffff = cmpwi r0, 0xffff void init_main_loop() { - patch::write_word(reinterpret_cast(0x802e4ed8), 0x2c00ffff); + patch::write_word(reinterpret_cast(0x802e4ed8), PPC_INSTR_CMPWI(PPC_R0, -1)); } }// namespace remove_desert_haze diff --git a/src/patches/removals/remove_hardcodes.cpp b/src/patches/removals/remove_hardcodes.cpp index 185ab948..8255160b 100644 --- a/src/patches/removals/remove_hardcodes.cpp +++ b/src/patches/removals/remove_hardcodes.cpp @@ -24,7 +24,7 @@ void init_main_loop() { // SMB1 patch::write_nop(reinterpret_cast(0x802945d8)); // Check for stage 0xffff instead of 190 for what stage's .gma/.tpl not to load - patch::write_word(reinterpret_cast(0x802c7350), 0x2c1fffff); + patch::write_word(reinterpret_cast(0x802c7350), PPC_INSTR_CMPWI(PPC_R31, -1)); // Check for stage 0xffffffff when enabling a lighting hardcode instead of 200 patch::write_word(reinterpret_cast(0x80455ff8), 0xffffffff); // In the function which handles Bonus Wave's collision, nop @@ -38,26 +38,26 @@ void init_main_loop() { // Labyrinth camera removal // Always compare the stage ID to 0xFFFF when these camera functions check // if the current stage ID is 0x15a when determining specific constants. - // 0x2c00ffff = cmpwi r0. 0xFFFF - patch::write_word(reinterpret_cast(0x802858D4), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x802874BC), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x8028751C), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x802880EC), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x802881D4), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x802883B4), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x802886B8), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x8028BF44), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x8028C1CC), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x8028C650), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x8028CA84), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291338), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291420), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291664), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291904), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291930), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291960), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x8029198C), 0x2c00ffff); - patch::write_word(reinterpret_cast(0x80291AEC), 0x2c00ffff); + patch::write_word(reinterpret_cast(0x802858D4), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x802874BC), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x8028751C), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x802880EC), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x802881D4), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x802883B4), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x802886B8), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x8028BF44), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x8028C1CC), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x8028C650), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x8028CA84), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291338), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291420), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291664), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291904), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291930), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291960), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x8029198C), PPC_INSTR_CMPWI(PPC_R0, -1)); + patch::write_word(reinterpret_cast(0x80291AEC), PPC_INSTR_CMPWI(PPC_R0, -1)); + // Wormhole surface fix // Always return 'true' for a specific function that checks if the stage ID // belongs to a slot normally used for party games. diff --git a/src/patches/story/story_double_stage_select.cpp b/src/patches/story/story_double_stage_select.cpp index ffed9c09..119ab77b 100644 --- a/src/patches/story/story_double_stage_select.cpp +++ b/src/patches/story/story_double_stage_select.cpp @@ -3,6 +3,7 @@ #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" +#include "utils/ppcutil.h" namespace story_double_stage_select { @@ -105,7 +106,7 @@ void init_main_loop() { mkb::pausemenu_entry_counts[6] = 7; // Edits behaviors in the function which handles pausemenu selections patch::write_nop(reinterpret_cast(0x802745a4)); - patch::write_word(reinterpret_cast(0x8027459c), 0x2c000004);// cmpwi r0, 4 + patch::write_word(reinterpret_cast(0x8027459c), PPC_INSTR_CMPWI(PPC_R0, 4)); // Hook into the function which checks input in the pausemenu for our recreated behaviors patch::hook_function(s_check_pause_menu_input_tramp, mkb::check_pause_menu_input, [](mkb::Sprite* pause_sprite) { s_check_pause_menu_input_tramp.dest(pause_sprite); From 48f7737f524025077105c6c3673ad5d0bf7e51f4 Mon Sep 17 00:00:00 2001 From: Nambo0 Date: Wed, 11 Mar 2026 23:57:59 -0400 Subject: [PATCH 85/96] Add custom font color patch --- src/config/config.cpp | 145 ++++++-------------------- src/patches/custom/font_color.cpp | 72 +++++++++++++ src/patches/custom/font_color.h | 6 ++ src/patches/custom/font_primary.cpp | 29 ++++++ src/patches/custom/font_primary.h | 6 ++ src/patches/custom/font_secondary.cpp | 29 ++++++ src/patches/custom/font_secondary.h | 6 ++ src/utils/ppcutil.h | 1 + 8 files changed, 179 insertions(+), 115 deletions(-) create mode 100644 src/patches/custom/font_color.cpp create mode 100644 src/patches/custom/font_color.h create mode 100644 src/patches/custom/font_primary.cpp create mode 100644 src/patches/custom/font_primary.h create mode 100644 src/patches/custom/font_secondary.cpp create mode 100644 src/patches/custom/font_secondary.h diff --git a/src/config/config.cpp b/src/config/config.cpp index fe4d1ba6..f660bc27 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -16,6 +16,33 @@ static mkb::DVDFileInfo config_file_info; static char* config_file_buf; static char config_file_path[] = "/config.txt"; +u32 parse_hex_value(char* value) { + u32 parsed_value = 0; + for(u8 i=1; i <= 8; i++) { // Only check the first 8 characters after the # + if(value[i] == '\0') return parsed_value; // string is done + u8 current_val = 0; + switch(value[i]) { + case '1': current_val = 1; break; + case '2': current_val = 2; break; + case '3': current_val = 3; break; + case '4': current_val = 4; break; + case '5': current_val = 5; break; + case '6': current_val = 6; break; + case '7': current_val = 7; break; + case '8': current_val = 8; break; + case '9': current_val = 9; break; + case 'A': case 'a': current_val = 10; break; + case 'B': case 'b': current_val = 11; break; + case 'C': case 'c': current_val = 12; break; + case 'D': case 'd': current_val = 13; break; + case 'E': case 'e': current_val = 14; break; + case 'F': case 'f': current_val = 15; break; + } + parsed_value = parsed_value * 16 + current_val; + } + return parsed_value; +} + u16* parse_stageid_list(char* buf, u16* array) { buf = mkb::strchr(buf, '\n') + 1; @@ -102,116 +129,6 @@ void parse_menu_option_toggles(char* buf) { } while (buf < end_of_section); } -static void skip_spaces(char*& p) { - while (*p == ' ' || *p == '\t') p++; -} - -static bool parse_csv_ints(char* value, int* out, int count) { - char* p = value; - - for (int i = 0; i < count; ++i) { - skip_spaces(p); - - // Parse integer - out[i] = mkb::atoi(p); - - // Find next comma if more values expected - if (i + 1 < count) { - p = mkb::strchr(p, ','); - if (!p) return false; - p++;// skip comma - } - } - - return true; -} - - -// Parses W- -static bool parse_world_stage_key(const char* key, int& world_idx, int& stage_idx) { - if (key == nullptr || key[0] != 'W') return false; - - // world starts after 'W' - int w = mkb::atoi(const_cast(key + 1)); - - // find '-' - char* dash = mkb::strchr(const_cast(key), '-'); - if (!dash) return false; - - // stage starts after '-' - int s = mkb::atoi(dash + 1); - - if (w < 1 || w > main::WORLD_COUNT) return false; - if (s < 1 || s > main::STAGES_PER_WORLD) return false; - - world_idx = w - 1; - stage_idx = s - 1; - return true; -} - - -void parse_story_mode_entries(char* buf) { - buf = mkb::strchr(buf, '\n') + 1; - - char* end_of_section = mkb::strchr(buf, '}'); - char key[64] = {0}; - char value[128] = {0}; - - do { - char *key_start, *key_end, *end_of_line; - key_start = mkb::strchr(buf, '\t') + 1; - key_end = mkb::strchr(buf, ':'); - MOD_ASSERT_MSG(key_start < key_end, - "Key start after key end, did you start your key with a tab and not spaces?"); - end_of_line = mkb::strchr(buf, '\n'); - - mkb::strncpy(key, key_start, (key_end - key_start)); - mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); - - int world_idx = 0, stage_idx = 0; - MOD_ASSERT_MSG( - parse_world_stage_key(key, world_idx, stage_idx), - "Invalid story key format (expected W<1-10>-<1-10>)"); - - int vals[3] = {0}; - - MOD_ASSERT_MSG( - parse_csv_ints(value, vals, 3), - "Invalid story value format (expected: stage ID, time limit, difficulty)"); - - int stage_id_i = vals[0]; - int time_limit_i = vals[1]; - int difficulty_i = vals[2]; - - - MOD_ASSERT_MSG(stage_id_i >= 0 && stage_id_i <= 420, "Stage ID out of range (0-420)"); - MOD_ASSERT_MSG(time_limit_i >= 0 && time_limit_i <= 360, "Time limit out of range (0-360)"); - MOD_ASSERT_MSG(difficulty_i >= 0 && difficulty_i <= 10, "Difficulty out of range (0-10)"); - - main::NewStoryStageEntry& entry = - main::new_story_entries[world_idx][stage_idx]; - - MOD_ASSERT_MSG(!entry.set, "Duplicate Story Mode entry for same world/stage"); - - entry.stage_id = static_cast(stage_id_i); - entry.time_limit = static_cast(time_limit_i); - entry.difficulty = static_cast(difficulty_i); - entry.set = true; - - buf = end_of_line + 1; - mkb::memset(key, '\0', sizeof(key)); - mkb::memset(value, '\0', sizeof(value)); - } while (buf < end_of_section); - - for (int w = 0; w < main::WORLD_COUNT; ++w) { - for (int s = 0; s < main::STAGES_PER_WORLD; ++s) { - MOD_ASSERT_MSG(main::new_story_entries[w][s].set, "Missing Story Mode entry"); - } - } - - LOG("Story Mode Entries loaded at: 0x%X", &main::new_story_entries); -} - void parse_function_toggles(char* buf) { // Enters from section parsing, so skip to the next line buf = mkb::strchr(buf, '\n') + 1; @@ -248,7 +165,9 @@ void parse_function_toggles(char* buf) { // 'value' is some integer, set the value and initialize the patch if it differs from the default else { - parsed_value = mkb::atoi(value); + if(value[0] == '.') parsed_value = parse_hex_value(value); + else parsed_value = mkb::atoi(value); + //parsed_value = mkb::atoi(value); // Only set value on tickables that have a defined default active value if (!tickable->active_value.has_value()) break; @@ -330,10 +249,6 @@ void parse_config() { LOG("Music ID list loaded at: 0x%X", &main::bgm_id_lookup); } - else if (STREQ(section, "Story Mode Entries")) { - parse_story_mode_entries(section_end); - } - else { LOG("Unknown category %s found in config!", section); } diff --git a/src/patches/custom/font_color.cpp b/src/patches/custom/font_color.cpp new file mode 100644 index 00000000..93f4b7aa --- /dev/null +++ b/src/patches/custom/font_color.cpp @@ -0,0 +1,72 @@ +#include "font_color.h" + +#include "../internal/patch.h" +#include "../internal/tickable.h" +#include "../mkb/mkb.h" +#include "../utils/ppcutil.h" +#include "font_primary.h" +#include "font_secondary.h" + +namespace font_color { + +TICKABLE_DEFINITION(( + .name = "custom-font-color", + .description = "Font Color", + .init_main_loop = init, + .init_main_game = init_main_game,)) + +// void textdraw_set_mul_color(uint param_1); +static patch::Tramp s_textdraw_set_mul_color_tramp; + +void replace_lis_color(int reg, u32 loc, u32 color) { + patch::write_word(reinterpret_cast(loc), PPC_INSTR_LIS(reg, (color >> 16) & 0xff));// RR + patch::write_word(reinterpret_cast(loc + 4), PPC_INSTR_ORI(reg, (color & 0xffff)));// GGBB +} + +void replace_3pt_color(u32 loc, u32 color) { + patch::write_word(reinterpret_cast(loc), 0x38000000 + ((color >> 16) & 0xff)); // RR + patch::write_word(reinterpret_cast(loc + 8), 0x38000000 + ((color >> 8) & 0xff));// GG + patch::write_word(reinterpret_cast(loc + 16), 0x38000000 + (color & 0xff)); // BB +} + +u32 form_color(u8 red, u8 blue, u8 green) { + return (red << 16) + (blue << 8) + green; +} + +u32 convert_color(u32 color) { + u8 red = (color >> 16) & 0xff; + u8 green = (color >> 8) & 0xff; + u8 blue = color & 0xff; + u32 new_color = color; + if (blue == 0 && red > 0 && green > 0 && red >= green) {// Orange & yellow (b=0, r>=g>0) + u8 red_1 = (font_primary::get_color() >> 16) & 0xff; + u8 green_1 = (font_primary::get_color() >> 8) & 0xff; + u8 blue_1 = font_primary::get_color() & 0xff; + u8 red_2 = (font_secondary::get_color() >> 16) & 0xff; + u8 green_2 = (font_secondary::get_color() >> 8) & 0xff; + u8 blue_2 = font_secondary::get_color() & 0xff; + float percent_primary = (1 - ((float)(red - green) / (red/2))); + new_color = form_color((u8)(((float)red/0xff) * ((red_1 * percent_primary) + (red_2 * (1-percent_primary)))), + (u8)(((float)red/0xff) * ((green_1 * percent_primary) + (green_2 * (1-percent_primary)))), + (u8)(((float)red/0xff) * ((blue_1 * percent_primary) + (blue_2 * (1-percent_primary))))); + } + return new_color; +} + +void init() { + patch::hook_function(s_textdraw_set_mul_color_tramp, mkb::textdraw_set_mul_color, [](u32 color) { + s_textdraw_set_mul_color_tramp.dest(convert_color(color)); + }); +} + +void init_main_game() { + replace_3pt_color(0x80338c84, font_primary::get_color());// Stage number RGB color + replace_3pt_color(0x80338e74, font_primary::get_color());// Stage name RGB color + replace_3pt_color(0x80338A84, font_primary::get_color());// EX color + replace_3pt_color(0x8032caa0, convert_color(0xffc000));// READY text color + replace_3pt_color(0x8032d944, font_secondary::get_color());// GO text color + replace_3pt_color(0x8032bbb8, font_primary::get_color());// STAGE/WORLD spin in color + replace_3pt_color(0x8032E91C, font_secondary::get_color());// FALLOUT color +} + +}// namespace font_color \ No newline at end of file diff --git a/src/patches/custom/font_color.h b/src/patches/custom/font_color.h new file mode 100644 index 00000000..61cb132a --- /dev/null +++ b/src/patches/custom/font_color.h @@ -0,0 +1,6 @@ +#pragma once + +namespace font_color { +void init(); +void init_main_game(); +}// namespace font_color \ No newline at end of file diff --git a/src/patches/custom/font_primary.cpp b/src/patches/custom/font_primary.cpp new file mode 100644 index 00000000..cef5ebc5 --- /dev/null +++ b/src/patches/custom/font_primary.cpp @@ -0,0 +1,29 @@ +#include "font_primary.h" + +#include "../internal/patch.h" +#include "../internal/tickable.h" +#include "../mkb/mkb.h" +#include "../utils/ppcutil.h" + +namespace font_primary { + +int primary_color = 0xffff00; + +// Patch slot holding primary color for font-color +TICKABLE_DEFINITION(( + .name = "font-primary", + .description = "Font Primary", + .active_value = primary_color, + .lower_bound = 0x000000, + .upper_bound = 0xffffff, + .init_main_loop = init,)) + +int get_color() { + return primary_color; +} + +void init() { + primary_color = *active_tickable_ptr->active_value; +} + +}// namespace font_primary \ No newline at end of file diff --git a/src/patches/custom/font_primary.h b/src/patches/custom/font_primary.h new file mode 100644 index 00000000..657ff92c --- /dev/null +++ b/src/patches/custom/font_primary.h @@ -0,0 +1,6 @@ +#pragma once + +namespace font_primary { + int get_color(); + void init(); +}// namespace font_primary \ No newline at end of file diff --git a/src/patches/custom/font_secondary.cpp b/src/patches/custom/font_secondary.cpp new file mode 100644 index 00000000..21a33eea --- /dev/null +++ b/src/patches/custom/font_secondary.cpp @@ -0,0 +1,29 @@ +#include "font_secondary.h" + +#include "../internal/patch.h" +#include "../internal/tickable.h" +#include "../mkb/mkb.h" +#include "../utils/ppcutil.h" + +namespace font_secondary { + +int secondary_color = 0xff8000; + +// Patch slot holding secondary color for font-color +TICKABLE_DEFINITION(( + .name = "font-secondary", + .description = "Font Secondary", + .active_value = secondary_color, + .lower_bound = 0x000000, + .upper_bound = 0xffffff, + .init_main_loop = init,)) + +int get_color() { + return secondary_color; +} + +void init() { + secondary_color = *active_tickable_ptr->active_value; +} + +}// namespace font_secondary \ No newline at end of file diff --git a/src/patches/custom/font_secondary.h b/src/patches/custom/font_secondary.h new file mode 100644 index 00000000..3a085f97 --- /dev/null +++ b/src/patches/custom/font_secondary.h @@ -0,0 +1,6 @@ +#pragma once + +namespace font_secondary { + int get_color(); + void init(); +}// namespace font_secondary \ No newline at end of file diff --git a/src/utils/ppcutil.h b/src/utils/ppcutil.h index 2a2f91cd..c05f58be 100644 --- a/src/utils/ppcutil.h +++ b/src/utils/ppcutil.h @@ -13,6 +13,7 @@ #define PPC_INSTR_LI(dest_register, value) (0x38000000 + (((u32) (dest_register)) << 21) + ((u16) value)) #define PPC_INSTR_LIS(dest_register, value) (0x3C000000 + (((u32) (dest_register)) << 21) + ((u16) value)) +#define PPC_INSTR_ORI(dest_register, value) ((0b011000 << 26) + (((u32) (dest_register)) << 21) + (((u32) (dest_register)) << 16) + ((u16) value)) #define PPC_INSTR_NOP() (0x60000000) From c5015e712d05ca3c4dd41362f8c985e3cec0e54b Mon Sep 17 00:00:00 2001 From: Nambo0 Date: Thu, 12 Mar 2026 00:04:55 -0400 Subject: [PATCH 86/96] Update default-config.txt --- configs/default-config.txt | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/configs/default-config.txt b/configs/default-config.txt index 4280a94b..a83f67b9 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -232,6 +232,14 @@ // Changes the stage ID used on the main menu. Setting this to -1 will lead to // default behavior (where the menu stage ID also uses more than one stage ID) +// custom-font-color +// font-primary +// font-secondary +// +// Changes the colors of most yellow/orange text in the menus to the designated +// primary & secondary color hex codes +// hex codes have a period (.) in front, such as: .ff0000 (for red) + // ---------------------------------------------------------------------------- // 'enabled' - Applies the patch @@ -281,6 +289,9 @@ story-fix-missing-w: disabled pause-cooldown: disabled perfect-bonus-completion: disabled + custom-font-color: enabled + font-primary: .ffff00 + font-secondary: .ff8000 } // Toggles which menu options are accessible. From 10eb1178772faca6fb4aadbd35f9baa4f3d2cb2d Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 9 Jun 2026 00:45:52 -0700 Subject: [PATCH 87/96] Make font colors work with custom story entries; expand font color patch --- configs/default-config.txt | 138 ++- src/config/config.cpp | 227 ++++- src/mkb/mkb2.us.lst | 1027 ++++++++++++++++++++-- src/mkb/mkb2_ghidra.h | 849 ++++++++++-------- src/patches/custom/custom_font_color.cpp | 159 ++++ src/patches/custom/custom_font_color.h | 25 + src/patches/custom/font_color.cpp | 72 -- src/patches/custom/font_color.h | 6 - src/patches/custom/font_primary.cpp | 29 - src/patches/custom/font_primary.h | 6 - src/patches/custom/font_secondary.cpp | 29 - src/patches/custom/font_secondary.h | 6 - src/patches/fixes/fix_bonus_sprite.cpp | 24 +- src/patches/fixes/fix_bonus_sprite.h | 1 + src/patches/fixes/fix_widescreen.cpp | 16 +- src/patches/fixes/fix_widescreen.h | 1 + 16 files changed, 2009 insertions(+), 606 deletions(-) create mode 100644 src/patches/custom/custom_font_color.cpp create mode 100644 src/patches/custom/custom_font_color.h delete mode 100644 src/patches/custom/font_color.cpp delete mode 100644 src/patches/custom/font_color.h delete mode 100644 src/patches/custom/font_primary.cpp delete mode 100644 src/patches/custom/font_primary.h delete mode 100644 src/patches/custom/font_secondary.cpp delete mode 100644 src/patches/custom/font_secondary.h diff --git a/configs/default-config.txt b/configs/default-config.txt index a83f67b9..a5895db6 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 1.0.6! +// This is the config file for Workshop Mod 1.5.0! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // @@ -249,20 +249,28 @@ custom-menu-stage-id: -1 custom-music-id: disabled custom-theme-id: disabled + custom-story-mode-entries: disabled custom-world-count: 10 + custom-font-color: disabled + custom-starting-monkey-count: 3 + custom-banana-count-per-1up: 100 + custom-reflection-resolution-width: 640 + custom-reflection-resolution-height: 448 menu-option-toggle: disabled challenge-mode-retry: disabled challenge-mode-death-count: disabled four-digit-banana-counter: disabled goal-texture-scroll: disabled + goal-type-sprites: disabled load-extra-bg-files: disabled smb1-camera-toggle: disabled stage-name-subtitles: disabled - fix-bonus-sprite: disabled + fix-bonus-stage-sprite: disabled fix-final-stage: disabled fix-goal-types: disabled fix-minimap-color: disabled fix-monkey-counter: disabled + fix-spooky-action: disabled fix-stobj-draw: disabled fix-stage-object-reflection: disabled fix-storm-continue-platform: disabled @@ -272,6 +280,7 @@ remove-1up-sprite: disabled remove-ball-rolling-sound: disabled remove-challenge-cutscenes: disabled + remove-challenge-game-settings: disabled remove-desert-haze: disabled remove-extras: disabled remove-stage-slot-hardcodes: disabled @@ -287,11 +296,11 @@ story-mode-music-fix: disabled story-double-stage-select: disabled story-fix-missing-w: disabled + autosave-on-by-default: disabled pause-cooldown: disabled perfect-bonus-completion: disabled - custom-font-color: enabled - font-primary: .ffff00 - font-secondary: .ff8000 + smb1-score-count: disabled + master-unlocked-by-default: disabled } // Toggles which menu options are accessible. @@ -321,6 +330,22 @@ monkey-tennis: enabled } +# Font Colors { + menu-primary: 0xFFC000 + menu-secondary: 0xFFFF00 + menu-option-name: 0x0000C0 + current-stage-info: 0xFFFF00 + ready: 0xFFC800 + go: 0x0080FF + fallout-time-over: 0xFF8C00 + spin-in-info: 0xFFFF00 + final-stage-beginner: 0x00D000 + final-stage-advanced: 0x0000E0 + final-stage-expert: 0xFFC000 + final-stage-master: 0xFFC000 + bonus-stage: 0xFF8000 +} + // Stage ID to theme ID mapping. Theme IDs are in decimal. // The default, vanilla theme ID list is provided for your convenience. // A theme ID list is included with the download of this mod. @@ -1184,3 +1209,106 @@ STAGE 419: 0 STAGE 420: 61 } + +# Story Mode Entries { + W1-1: 201, 60, 1 + W1-2: 202, 60, 2 + W1-3: 203, 60, 1 + W1-4: 204, 60, 2 + W1-5: 1, 60, 6 + W1-6: 2, 60, 3 + W1-7: 3, 60, 2 + W1-8: 4, 60, 8 + W1-9: 5, 60, 6 + W1-10: 6, 60, 2 + W2-1: 7, 60, 2 + W2-2: 8, 60, 5 + W2-3: 9, 60, 3 + W2-4: 10, 60, 6 + W2-5: 11, 60, 7 + W2-6: 12, 60, 3 + W2-7: 13, 60, 7 + W2-8: 14, 60, 6 + W2-9: 15, 60, 8 + W2-10: 16, 60, 6 + W3-1: 231, 60, 3 + W3-2: 232, 60, 8 + W3-3: 233, 60, 6 + W3-4: 234, 60, 6 + W3-5: 235, 60, 4 + W3-6: 236, 60, 3 + W3-7: 237, 60, 3 + W3-8: 238, 60, 8 + W3-9: 239, 60, 3 + W3-10: 17, 60, 3 + W4-1: 18, 60, 2 + W4-2: 19, 60, 8 + W4-3: 20, 60, 5 + W4-4: 21, 60, 1 + W4-5: 22, 60, 6 + W4-6: 23, 60, 9 + W4-7: 24, 60, 6 + W4-8: 25, 60, 8 + W4-9: 26, 60, 8 + W4-10: 27, 60, 10 + W5-1: 28, 60, 3 + W5-2: 29, 60, 7 + W5-3: 30, 30, 4 + W5-4: 31, 60, 8 + W5-5: 32, 60, 3 + W5-6: 33, 60, 5 + W5-7: 34, 60, 2 + W5-8: 35, 60, 6 + W5-9: 36, 60, 10 + W5-10: 37, 60, 4 + W6-1: 38, 60, 8 + W6-2: 39, 60, 8 + W6-3: 40, 60, 5 + W6-4: 41, 60, 5 + W6-5: 42, 60, 5 + W6-6: 43, 60, 9 + W6-7: 44, 60, 9 + W6-8: 45, 60, 5 + W6-9: 46, 60, 9 + W6-10: 47, 60, 2 + W7-1: 281, 60, 4 + W7-2: 282, 60, 5 + W7-3: 283, 60, 7 + W7-4: 284, 60, 6 + W7-5: 285, 60, 4 + W7-6: 286, 60, 8 + W7-7: 287, 60, 9 + W7-8: 288, 60, 9 + W7-9: 289, 60, 10 + W7-10: 48, 60, 5 + W8-1: 49, 60, 9 + W8-2: 50, 60, 8 + W8-3: 51, 60, 10 + W8-4: 52, 60, 9 + W8-5: 53, 60, 8 + W8-6: 54, 60, 9 + W8-7: 55, 60, 10 + W8-8: 56, 60, 10 + W8-9: 57, 60, 6 + W8-10: 58, 60, 7 + W9-1: 59, 60, 10 + W9-2: 60, 60, 10 + W9-3: 61, 60, 8 + W9-4: 62, 60, 9 + W9-5: 63, 60, 10 + W9-6: 64, 60, 7 + W9-7: 65, 60, 8 + W9-8: 66, 60, 8 + W9-9: 67, 60, 6 + W9-10: 68, 60, 10 + W10-1: 341, 60, 8 + W10-2: 342, 60, 9 + W10-3: 343, 60, 9 + W10-4: 344, 60, 9 + W10-5: 345, 60, 8 + W10-6: 346, 60, 9 + W10-7: 347, 60, 7 + W10-8: 348, 60, 8 + W10-9: 349, 60, 9 + W10-10: 350, 60, 6 +} diff --git a/src/config/config.cpp b/src/config/config.cpp index f660bc27..89b8476a 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -4,6 +4,7 @@ #include "internal/heap.h" #include "internal/log.h" #include "internal/tickable.h" +#include "patches/custom/custom_font_color.h" #include "patches/custom/menu_option_toggle.h" #define STREQ(x, y) (mkb::strcmp(const_cast(x), const_cast(y)) == 0) @@ -18,31 +19,23 @@ static char config_file_path[] = "/config.txt"; u32 parse_hex_value(char* value) { u32 parsed_value = 0; - for(u8 i=1; i <= 8; i++) { // Only check the first 8 characters after the # - if(value[i] == '\0') return parsed_value; // string is done - u8 current_val = 0; - switch(value[i]) { - case '1': current_val = 1; break; - case '2': current_val = 2; break; - case '3': current_val = 3; break; - case '4': current_val = 4; break; - case '5': current_val = 5; break; - case '6': current_val = 6; break; - case '7': current_val = 7; break; - case '8': current_val = 8; break; - case '9': current_val = 9; break; - case 'A': case 'a': current_val = 10; break; - case 'B': case 'b': current_val = 11; break; - case 'C': case 'c': current_val = 12; break; - case 'D': case 'd': current_val = 13; break; - case 'E': case 'e': current_val = 14; break; - case 'F': case 'f': current_val = 15; break; - } - parsed_value = parsed_value * 16 + current_val; + + // Skip "0x" + for (char* p = value + 2; *p != '\0'; ++p) { + u8 current_val; + + if (*p >= '0' && *p <= '9') current_val = *p - '0'; + else if (*p >= 'A' && *p <= 'F') current_val = *p - 'A' + 10; + else if (*p >= 'a' && *p <= 'f') current_val = *p - 'a' + 10; + else break; + + parsed_value = (parsed_value << 4) | current_val; } + return parsed_value; } + u16* parse_stageid_list(char* buf, u16* array) { buf = mkb::strchr(buf, '\n') + 1; @@ -129,6 +122,178 @@ void parse_menu_option_toggles(char* buf) { } while (buf < end_of_section); } +static void skip_spaces(char*& p) { + while (*p == ' ' || *p == '\t') p++; +} + +static bool parse_csv_ints(char* value, int* out, int count) { + char* p = value; + + for (int i = 0; i < count; ++i) { + skip_spaces(p); + + // Parse integer + out[i] = mkb::atoi(p); + + // Find next comma if more values expected + if (i + 1 < count) { + p = mkb::strchr(p, ','); + if (!p) return false; + p++;// skip comma + } + } + + return true; +} + + +// Parses W- +static bool parse_world_stage_key(const char* key, int& world_idx, int& stage_idx) { + if (key == nullptr || key[0] != 'W') return false; + + // world starts after 'W' + int w = mkb::atoi(const_cast(key + 1)); + + // find '-' + char* dash = mkb::strchr(const_cast(key), '-'); + if (!dash) return false; + + // stage starts after '-' + int s = mkb::atoi(dash + 1); + + if (w < 1 || w > main::WORLD_COUNT) return false; + if (s < 1 || s > main::STAGES_PER_WORLD) return false; + + world_idx = w - 1; + stage_idx = s - 1; + return true; +} + + +void parse_story_mode_entries(char* buf) { + buf = mkb::strchr(buf, '\n') + 1; + + char* end_of_section = mkb::strchr(buf, '}'); + char key[64] = {0}; + char value[128] = {0}; + + do { + char *key_start, *key_end, *end_of_line; + key_start = mkb::strchr(buf, '\t') + 1; + key_end = mkb::strchr(buf, ':'); + MOD_ASSERT_MSG(key_start < key_end, + "Key start after key end, did you start your key with a tab and not spaces?"); + end_of_line = mkb::strchr(buf, '\n'); + + mkb::strncpy(key, key_start, (key_end - key_start)); + mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); + + int world_idx = 0, stage_idx = 0; + MOD_ASSERT_MSG( + parse_world_stage_key(key, world_idx, stage_idx), + "Invalid story key format (expected W<1-10>-<1-10>)"); + + int vals[3] = {0}; + + MOD_ASSERT_MSG( + parse_csv_ints(value, vals, 3), + "Invalid story value format (expected: stage ID, time limit, difficulty)"); + + int stage_id_i = vals[0]; + int time_limit_i = vals[1]; + int difficulty_i = vals[2]; + + + MOD_ASSERT_MSG(stage_id_i >= 0 && stage_id_i <= 420, "Stage ID out of range (0-420)"); + MOD_ASSERT_MSG(time_limit_i >= 0 && time_limit_i <= 360, "Time limit out of range (0-360)"); + MOD_ASSERT_MSG(difficulty_i >= 0 && difficulty_i <= 10, "Difficulty out of range (0-10)"); + + main::NewStoryStageEntry& entry = + main::new_story_entries[world_idx][stage_idx]; + + MOD_ASSERT_MSG(!entry.set, "Duplicate Story Mode entry for same world/stage"); + + entry.stage_id = static_cast(stage_id_i); + entry.time_limit = static_cast(time_limit_i); + entry.difficulty = static_cast(difficulty_i); + entry.set = true; + + buf = end_of_line + 1; + mkb::memset(key, '\0', sizeof(key)); + mkb::memset(value, '\0', sizeof(value)); + } while (buf < end_of_section); + + for (int w = 0; w < main::WORLD_COUNT; ++w) { + for (int s = 0; s < main::STAGES_PER_WORLD; ++s) { + MOD_ASSERT_MSG(main::new_story_entries[w][s].set, "Missing Story Mode entry"); + } + } + + LOG("Story Mode Entries loaded at: 0x%X", &main::new_story_entries); +} + +void parse_font_colors(char* buf) { + buf = mkb::strchr(buf, '\n') + 1; + + char* end_of_section; + char key[64] = {0}; + char value[64] = {0}; + end_of_section = mkb::strchr(buf, '}'); + + do { + char *key_start, *key_end, *end_of_line; + key_start = mkb::strchr(buf, '\t') + 1; + key_end = mkb::strchr(buf, ':'); + MOD_ASSERT_MSG(key_start < key_end, + "Key start after key end, did you start your key with a tab and not spaces?"); + end_of_line = mkb::strchr(buf, '\n'); + + mkb::strncpy(key, key_start, (key_end - key_start)); + mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); + + u32 parsed_value = 0; + if ((value[0] == '0') && (value[1] == 'x' || value[1] == 'X')) { + parsed_value = parse_hex_value(value); + } + else { + parsed_value = mkb::atoi(value); + } + + if (STREQ(key, "menu-primary")) + custom_font_color::menu_primary_color = parsed_value; + else if (STREQ(key, "menu-secondary")) + custom_font_color::menu_secondary_color = parsed_value; + else if (STREQ(key, "menu-option-name")) + custom_font_color::menu_option_name_color = parsed_value; + else if (STREQ(key, "current-stage-info")) + custom_font_color::current_stage_info_color = parsed_value; + else if (STREQ(key, "ready")) + custom_font_color::ready_color = parsed_value; + else if (STREQ(key, "go")) + custom_font_color::go_color = parsed_value; + else if (STREQ(key, "fallout-time-over")) + custom_font_color::fallout_time_over_color = parsed_value; + else if (STREQ(key, "spin-in-info")) + custom_font_color::spin_in_info_color = parsed_value; + else if (STREQ(key, "final-stage-beginner")) + custom_font_color::final_stage_beginner_color = parsed_value; + else if (STREQ(key, "final-stage-advanced")) + custom_font_color::final_stage_advanced_color = parsed_value; + else if (STREQ(key, "final-stage-expert")) + custom_font_color::final_stage_expert_color = parsed_value; + else if (STREQ(key, "final-stage-master")) + custom_font_color::final_stage_master_color = parsed_value; + else if (STREQ(key, "bonus-stage")) + custom_font_color::bonus_stage_color = parsed_value; + else + LOG("Unknown font color key %s found in config!", key); + + buf = end_of_line + 1; + mkb::memset(key, '\0', 64); + mkb::memset(value, '\0', 64); + } while (buf < end_of_section); +} + void parse_function_toggles(char* buf) { // Enters from section parsing, so skip to the next line buf = mkb::strchr(buf, '\n') + 1; @@ -165,9 +330,13 @@ void parse_function_toggles(char* buf) { // 'value' is some integer, set the value and initialize the patch if it differs from the default else { - if(value[0] == '.') parsed_value = parse_hex_value(value); - else parsed_value = mkb::atoi(value); - //parsed_value = mkb::atoi(value); + // Detect hex (0x or 0X) + if ((value[0] == '0') && (value[1] == 'x' || value[1] == 'X')) { + parsed_value = parse_hex_value(value); + } + else { + parsed_value = mkb::atoi(value); + } // Only set value on tickables that have a defined default active value if (!tickable->active_value.has_value()) break; @@ -176,7 +345,7 @@ void parse_function_toggles(char* buf) { MOD_ASSERT_MSG(parsed_value >= tickable->lower_bound, "Passed value for patch smaller than minimum value"); MOD_ASSERT_MSG(parsed_value <= tickable->upper_bound, "Passed value for patch larger than maximum value"); - // Set the enabled to the parsed value, if it differes from the default passed value + // Set the enabled to the parsed value, if it differs from the default passed value if (parsed_value != tickable->active_value) { tickable->enabled = true; tickable->active_value = parsed_value; @@ -235,6 +404,10 @@ void parse_config() { parse_menu_option_toggles(section_end); } + else if (STREQ(section, "Font Colors")) { + parse_font_colors(section_end); + } + else if (STREQ(section, "Theme IDs")) { parse_stageid_list(section_end, main::theme_id_lookup); LOG("Theme ID list loaded at: 0x%X", &main::theme_id_lookup); @@ -249,6 +422,10 @@ void parse_config() { LOG("Music ID list loaded at: 0x%X", &main::bgm_id_lookup); } + else if (STREQ(section, "Story Mode Entries")) { + parse_story_mode_entries(section_end); + } + else { LOG("Unknown category %s found in config!", section); } diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index daec5d97..547440fb 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -67,6 +67,7 @@ 80006B08:load_run_main_loop_parent1 80006B78:read_and_set_os_string_table 80006C04:load_main_loop_rel_and_run +80006C68:prt_80006c68_cc17ecd5 80006D50:unload_main_loop_rel 80006DA8:load_common_gma_tpl 80006DF8:set_init_rel_index @@ -154,6 +155,7 @@ 8000A7F0:aram_font_to_mram_font_callback 8000A7FC:g_load_aram_font 8000A8D0:gARAMFont_DVDRead +8000A920:prt_8000a920_f3434af 8000A9E8:g_some_arq_request 8000AA50:aram_font_to_mram_font 8000AB6C:memcpy_handler @@ -404,11 +406,13 @@ 80016038:EXIDeselect 80016148:FUN_80016148 80016210:TCIntrruptHandler +80016428:FUN_80016428 800164F0:EXIInit 80016604:EXILock 800166F8:EXIUnlock 800167D4:sndReadFlag 800167D4:sndReadFlag +800167EC:FUN_800167ec 80016814:EXIGetID 80016B90:InitializeUART 80016C00:WriteUARTN @@ -432,6 +436,7 @@ 8001752C:PSVECNormalize 80017570:PSVECCrossProduct 800175AC:__DVDInitWA +800175EC:FUN_800175ec 800178E0:FUN_800178e0 80017964:AlarmHandlerForTimeout 800179D4:Read @@ -470,6 +475,8 @@ 80018FFC:DVDPrepareStreamAsync 800190E8:cbForReadAsync 80019118:DVDInit +80019214:FUN_80019214 +80019268:FUN_80019268 800192E8:cbForStateError 80019390:stateTimeout 8001942C:stateGettingError @@ -483,6 +490,7 @@ 80019B00:stateCheckID3 80019B34:stateCheckID2 80019B6C:cbForStateCheckID1 +80019C80:FUN_80019c80 80019D24:cbForStateCheckID3 80019E20:FUN_80019e20 80019E64:stateCoverClosed @@ -519,6 +527,7 @@ 8001A584:caseD_d 8001A5AC:caseD_e 8001A5D4:caseD_0 +8001A5E4:FUN_8001a5e4 8001ABB8:DVDReadAbsAsyncPrio 8001AC94:DVDReadAbsAsyncForBS 8001AD64:DVDReadDiskID @@ -617,8 +626,10 @@ 8001D834:VIGetDTVStatus 8001D870:UpdateOrigin 8001DA14:PADOriginCallback +8001DAD8:FUN_8001dad8 8001DB98:PADProbeCallback 8001DC70:PADTypeAndStatusCallback +8001DF9C:FUN_8001df9c 8001E0D0:PADReset 8001E1D0:PADRecalibrate 8001E2D4:PADInit @@ -630,6 +641,7 @@ 8001EBC0:SPEC1_MakeStatus 8001ED34:SPEC2_MakeStatus 8001F12C:PADSetAnalogMode +8001F1A0:FUN_8001f1a0 8001F334:SamplingHandler 8001F394:PADSetSamplingCallback 8001F3E8:__PADDisableRecalibration @@ -653,6 +665,7 @@ 8001F8E0:AIGetStreamVolRight 8001F8F0:AIInit 8001FA54:__AISHandler +8001FAD0:FUN_8001fad0 8001FB60:__AICallbackStackSwitch 8001FBB8:__AI_SRC_INIT 8001FD9C:FUN_8001fd9c @@ -693,7 +706,13 @@ 80021698:__DSP_boot_task 80021824:__DSP_insert_task 800218C4:__DSP_remove_task +80021974:FUN_80021974 +800219F8:FUN_800219f8 +80021A70:FUN_80021a70 +80021C6C:FUN_80021c6c 80021CB4:__DTKCallbackForFlush +80021D34:FUN_80021d34 +80021D84:FUN_80021d84 80021DDC:FUN_80021ddc 80021E34:DTKInit 80021EAC:DTKQueueTrack @@ -795,6 +814,7 @@ 80029170:FUN_80029170 80029194:GXInit 80029960:__GXInitGX +8002A1E4:FUN_8002a1e4 8002A320:GXInitFifoBase 8002A38C:GXInitFifoPtrs 8002A3FC:GXInitFifoLimits @@ -1364,6 +1384,7 @@ 800333C4:return_1 800333CC:g_some_perf_init_func 80033474:PERFGetAllMemMetrics +8003357C:FUN_8003357c 800337FC:PERFInit 80033A24:PERFSetEvent 80033A70:PERFStartFrame @@ -1372,6 +1393,7 @@ 80033EC8:PERFEventEnd 8003400C:PERFStartAutoSample 80034154:PERFEndAutoSample +80034214:FUN_80034214 8003479C:PERFStartAutoSampling 80034828:PERFStopAutoSampling 800348BC:__PERFDrawInit @@ -1437,6 +1459,9 @@ 8003A9F4:StartLayer 8003ADB4:StartKeymap 8003B014:synthStartSound +8003B20C:FUN_8003b20c +8003B9C0:FUN_8003b9c0 +8003C070:FUN_8003c070 8003C200:synthAddJob 8003C350:synthStartSynthJobHandling 8003C3B4:synthForceLowPrecisionUpdate @@ -1452,6 +1477,7 @@ 8003CD48:synthVolume 8003D158:synthIsFadeOutActive 8003D1AC:synthSetMusicVolumeType +8003D1D4:FUN_8003d1d4 8003D2A4:synthInit 8003D7E8:sndSeqSpeed 8003D830:sndSeqContinue @@ -1841,6 +1867,7 @@ 80051250:FUN_80051250 8005125C:hwGetVirtualSampleID 80051284:hwVoiceInStartup +800512A4:FUN_800512a4 8005133C:aramUploadData 80051510:aramSyncTransferQueue 80051528:aramInit @@ -1853,6 +1880,7 @@ 80051A7C:aramFreeStreamBuffer 80051B78:salCallback 80051C1C:Destroy +80051C2C:FUN_80051c2c 80051C94:salInitAi 80051D60:salStartAi 80051D80:salAiGetDest @@ -1975,6 +2003,7 @@ 80058BC8:FUN_80058bc8 80058C04:empty_function 80058C08:FUN_80058c08 +80058CBC:FUN_80058cbc 80058CE0:FUN_80058ce0 80058CE8:FUN_80058ce8 80058D0C:FUN_80058d0c @@ -1998,6 +2027,7 @@ 80059030:FUN_80059030 80059118:FUN_80059118 800592E4:FUN_800592e4 +800594B0:FUN_800594b0 800595A0:FUN_800595a0 80059744:FUN_80059744 8005977C:FUN_8005977c @@ -2063,11 +2093,14 @@ 8005B5F0:FUN_8005b5f0 8005B610:FUN_8005b610 8005B630:FUN_8005b630 +8005B6BC:FUN_8005b6bc 8005B6E0:FUN_8005b6e0 8005B834:FUN_8005b834 8005B984:FUN_8005b984 8005BC5C:FUN_8005bc5c 8005BF20:FUN_8005bf20 +8005BFE0:FUN_8005bfe0 +8005C058:FUN_8005c058 8005C1C8:FUN_8005c1c8 8005C210:g_create_some_threads 8005C3AC:mwidle_thread_entrypoint @@ -2128,6 +2161,7 @@ 8005E170:FUN_8005e170 8005E178:FUN_8005e178 8005E488:FUN_8005e488 +8005E4B8:FUN_8005e4b8 8005E574:FUN_8005e574 8005E708:FUN_8005e708 8005E7D4:FUN_8005e7d4 @@ -2156,9 +2190,15 @@ 8005F964:FUN_8005f964 8005F9B0:FUN_8005f9b0 8005F9F8:FUN_8005f9f8 +8005FADC:FUN_8005fadc 8005FB30:FUN_8005fb30 8005FB4C:FUN_8005fb4c 8005FB6C:FUN_8005fb6c +8005FBA4:FUN_8005fba4 +8005FC20:FUN_8005fc20 +8005FDF0:FUN_8005fdf0 +8005FF6C:FUN_8005ff6c +80060114:FUN_80060114 8006025C:FUN_8006025c 80060264:FUN_80060264 8006026C:FUN_8006026c @@ -2167,6 +2207,7 @@ 80060320:FUN_80060320 800603FC:FUN_800603fc 80060420:FUN_80060420 +8006054C:prt_8006054c_aee7b64a 8006065C:FUN_8006065c 80060704:FUN_80060704 8006076C:FUN_8006076c @@ -2176,6 +2217,7 @@ 800609F4:FUN_800609f4 80060A98:FUN_80060a98 80060CF4:FUN_80060cf4 +80060F50:prt_80060f50_aee7b64a 800610F0:FUN_800610f0 80061234:FUN_80061234 800612D4:FUN_800612d4 @@ -2190,6 +2232,8 @@ 8006174C:FUN_8006174c 80061754:FUN_80061754 800617C8:FUN_800617c8 +80061808:prt_80061808_c32105f2 +8006185C:prt_8006185c_c32105f2 800618B8:FUN_800618b8 80061914:FUN_80061914 800619F4:FUN_800619f4 @@ -3038,8 +3082,15 @@ 8007DE34:FUN_8007de34 8007DEA0:FUN_8007dea0 8007DF20:FUN_8007df20 +8007DF88:FUN_8007df88 8007DFD8:FUN_8007dfd8 8007E018:FUN_8007e018 +8007E058:FUN_8007e058 +8007E098:FUN_8007e098 +8007E154:FUN_8007e154 +8007E180:FUN_8007e180 +8007E288:FUN_8007e288 +8007E544:FUN_8007e544 8007E6F4:empty_function 8007E6F8:empty_function 8007E6FC:empty_function @@ -3287,6 +3338,7 @@ 80270558:main_loop_prolog 80270BB8:main_loop_epilog 80270BFC:main_loop_unlinked_func +80270C50:prt_8019aa18_92f7eb37 80270CA8:g_something_with_sound6_and_stop_pad_motors_callback 80270CCC:g_something_with_card_callback 80270CF8:g_something_with_sound11_callback @@ -3322,9 +3374,11 @@ 80272170:caseD_5 802721A0:caseD_6 802721B8:caseD_7 +8027226C:prt_8019c034_5a79192f 80272390:handle_start_button_with_debug_mode 80272730:handle_start_button_no_debug_mode 80272898:smd_null +802728D0:prt_8019c698_c32105f2 802728E4:set_sub_mode_destination 80272948:call_then_reset_sub_mode_destination 80272990:get_next_player_idx @@ -3434,9 +3488,12 @@ 80275374:event_dest 802753F0:event_freeze 8027540C:event_restart +80275478:prt_8019f240_c32105f2 8027548C:dest_all_events 80275540:FUN_8019f308 80275560:polydisp_main +80275604:prt_8019f3cc_e1cdc648 +80275620:prt_8019f3e8_e1cdc648 80275870:draw_func_handler 802758A8:switchD 802758AC:caseD_8 @@ -3545,6 +3602,7 @@ 80279F70:init_pausemenu_screenshot_texobj 80279FE0:g_draw_pausemenu_screenshot 8027A564:md_adv_func +8027A5BC:prt_801a4384_5924ca76 8027A6A4:empty_function 8027A6A8:empty_function 8027A6AC:smd_adv_logo_init @@ -3561,6 +3619,7 @@ 8027B8F0:smd_adv_title_reinit 8027BA60:smd_adv_title_tick 8027BBF8:smd_adv_info_init +8027BE90:prt_801a5c58_f3434af 8027BF34:smd_adv_info_tick 8027C2C4:switchD 8027C2C8:caseD_ff @@ -3580,11 +3639,13 @@ 8027C56C:FUN_801a6334 8027C5BC:smd_adv_game_ready_init 8027C988:smd_adv_game_ready_tick +8027CB40:prt_801a6908_812cd95f 8027CB80:smd_adv_game_play_init 8027CCD4:smd_adv_game_play_tick 8027CE6C:FUN_801a6c34 8027CEBC:smd_adv_ranking_init 8027CF08:smd_adv_ranking_tick +8027D694:prt_801a745c_812cd95f 8027D954:FUN_801a771c 8027DA78:FUN_801a7840 8027DC0C:FUN_801a79d4 @@ -3644,6 +3705,7 @@ 80282798:FUN_801ac560 80282914:FUN_801ac6dc 80282A90:md_sel_func +80282AE8:prt_801ac8b0_5924ca76 80282B28:FUN_801ac8f0 80282B4C:smd_sel_ngc_dest 80282B70:g_return_to_sel_ngc @@ -3895,6 +3957,13 @@ 802947E4:caseD_3 802947E4:caseD_5 802947E4:caseD_7 +802948D4:prt_801be69c_f51c8b33 +80294904:prt_801be6cc_e40233a0 +8029491C:prt_801be6e4_a65c839 +80294934:prt_801be6fc_a65c839 +80294958:prt_801be720_7ef5064e +80294970:prt_801be738_a65c839 +80294984:prt_801be74c_f99573c8 80294A44:g_some_stage_init_func 80294BF4:FUN_801be9bc 80294C70:g_set_active_light_group @@ -3942,6 +4011,9 @@ 80297E8C:g_set_goaled 80297FA4:FUN_801c1d6c 80298018:sprite_bonus_plus000_tick +80298090:prt_801c1e58_8d2134c3 +802980B4:prt_801c1e7c_8d2134c3 +802980CC:prt_801c1e94_8d2134c3 802980E0:sprite_bonus_banana_tick 80298118:sprite_ranking_tick 802983D0:sprite_ranking_disp @@ -4013,12 +4085,17 @@ 8029C130:g_perf_start_frame 8029C2C0:g_reset_draw_perf_counters 8029C2F0:g_printf_sound_error +8029C3B8:prt_801c6180_f3434af 8029C3E0:try_alloc_memory_for_sound 8029C41C:g_OSFree_wrapper 8029C44C:init_sound 8029C79C:g_something_with_music_fading 8029C83C:hwExit_wrapper 8029C85C:ReadMusyXData +8029C8F8:prt_801c66c0_f3434af +8029C90C:prt_801c66d4_f3434af +8029C920:prt_801c66e8_f3434af +8029C934:prt_801c66fc_f3434af 8029D424:g_something_calls_sndPopGroup 8029D594:g_something_calls_sndPopGroup_2 8029D6B0:event_sound_init @@ -4058,11 +4135,16 @@ 8029DFF0:caseD_c 8029E188:g_set_smth_with_sound 8029E198:g_smth_calls_sndFXStartParaInfo +8029E604:prt_801c83cc_6b83f2ba +8029E630:prt_801c83f8_f1635ab 8029E64C:g_something_with_volume 8029EA54:g_something_calls_sndFXKeyOff 8029EC64:SoundReq +8029ED7C:prt_801c8b44_f3434af 8029EFE4:SoundReqDirect +8029F10C:prt_801c8ed4_f3434af 8029F2E0:SoundReqID +8029F550:prt_801c9318_f3434af 8029F6F8:call_SoundReqID_arg_0 8029F71C:call_SoundReqID_arg_1 8029F740:call_SoundReqID_arg_2 @@ -4086,21 +4168,36 @@ 8029FB60:caseD_c 802A07F4:FUN_801ca5bc 802A0860:SoundOff +802A0908:prt_801ca6d0_f3434af 802A0A1C:SoundVol +802A0AC8:prt_801ca890_f3434af 802A0BC0:SoundPan +802A0C78:prt_801caa40_f3434af 802A0DB0:SoundPitch +802A0E5C:prt_801cac24_f3434af 802A0F54:SoundDop +802A1000:prt_801cadc8_f3434af 802A10F8:SoundMod +802A11A4:prt_801caf6c_f3434af 802A129C:SoundRev +802A1348:prt_801cb110_f3434af 802A1440:SoundCho +802A14EC:prt_801cb2b4_f3434af 802A15E4:SoundOffID +802A1770:prt_801cb538_f3434af 802A187C:SoundVolID +802A1A10:prt_801cb7d8_f3434af 802A1AFC:SoundPanID +802A1C98:prt_801cba60_f3434af 802A1DBC:SoundRevID +802A1F50:prt_801cbd18_f3434af 802A203C:SoundChoID +802A21D0:prt_801cbf98_f3434af 802A22BC:SoundCheckStateID +802A2448:prt_801cc210_f3434af 802A2510:FUN_801cc2d8 802A254C:SoundIcsReq +802A2658:prt_801cc420_f3434af 802A2FA0:FUN_801ccd68 802A3004:g_fade_track_volume 802A3124:switchD @@ -4124,6 +4221,8 @@ 802A3F98:FUN_801cdd60 802A403C:FUN_801cde04 802A4138:SoftStreamSEReq +802A4234:prt_801cdffc_f3434af +802A454C:prt_801ce314_6b83f2ba 802A45CC:empty_function 802A45D0:FUN_801ce398 802A4604:FUN_801ce3cc @@ -4133,12 +4232,20 @@ 802A4A00:FUN_801ce7c8 802A4C00:FUN_801ce9c8 802A4C88:FUN_801cea50 +802A4CBC:prt_801cea84_f3434af 802A4CD4:FUN_801cea9c +802A4D08:prt_801cead0_f3434af 802A4D20:FUN_801ceae8 802A4DE0:FUN_801ceba8 802A4E68:g_some_dvd_read_async_sound_callback2 802A4F0C:FUN_801cecd4 802A50F0:SoftStreamStart +802A520C:prt_801cefd4_f3434af +802A5220:prt_801cefe8_f3434af +802A5264:prt_801cf02c_f3434af +802A5278:prt_801cf040_f3434af +802A5290:prt_801cf058_f3434af +802A52A4:prt_801cf06c_f3434af 802A5AC0:empty_function 802A5AC4:g_SoftStreamStart_with_some_defaults 802A5AF0:FUN_801cf8b8 @@ -4154,7 +4261,9 @@ 802A65A0:FUN_801d0368 802A6600:g_check_current_track 802A6660:FUN_801d0428 +802A66A8:prt_801d0470_f3434af 802A66C0:FUN_801d0488 +802A66F4:prt_801d04bc_f3434af 802A670C:FUN_801d04d4 802A6728:FUN_801d04f0 802A6784:FUN_801d054c @@ -4228,6 +4337,7 @@ 802ABAB4:FUN_801d587c 802ABB54:FUN_801d591c 802ABB60:g_adx_error_call_back +802ABBBC:prt_801d5984_c32105f2 802ABBD8:FUN_801d59a0 802ABCD0:FUN_801d5a98 802AC444:switchD @@ -4272,6 +4382,11 @@ 802ACBA4:caseD_19 802ACBC8:caseD_1a 802ACBFC:caseD_1e +802ACC4C:prt_801d6a14_489bdb77 +802ACC90:prt_801d6a58_489bdb77 +802ACCD4:prt_801d6a9c_489bdb77 +802ACD18:prt_801d6ae0_489bdb77 +802ACD5C:prt_801d6b24_489bdb77 802ACD64:caseD_1f 802ACD9C:caseD_20 802ACDD0:caseD_21 @@ -4284,6 +4399,7 @@ 802AD048:draw_debugtext 802AD4D4:window_init 802AD5A0:g_something_with_replays3 +802AE1F4:prt_801d7fbc_c32105f2 802AE2C0:debug_textdraw_set_pos 802AE2D8:FUN_801d80a0 802AE314:FUN_801d80dc @@ -4304,10 +4420,32 @@ 802AF79C:g_is_sjis_and_more_than_24_mib 802AF7F4:FUN_801d95bc 802AF888:g_debug_print_ape +802AF904:prt_801d96cc_52cf6a3c +802AF920:prt_801d96e8_89d499d9 +802AF970:prt_801d9738_b17b4fee +802AF98C:prt_801d9754_89d499d9 +802AFA08:prt_801d97d0_89d499d9 +802AFA24:prt_801d97ec_afdf77ff +802AFB40:prt_801d9908_89d499d9 802AFCE4:FUN_801d9aac +802AFD9C:prt_801d9b64_c138f0d1 +802AFDBC:prt_801d9b84_c138f0d1 +802AFDD0:prt_801d9b98_eefbee0d +802AFDE4:prt_801d9bac_89d499d9 802AFE18:FUN_801d9be0 +802AFEEC:prt_801d9cb4_7c9e0e97 +802AFF1C:prt_801d9ce4_7c9e0e97 +802AFF64:prt_801d9d2c_f3434af +802AFF90:prt_801d9d58_f3434af 802AFFC8:FUN_801d9d90 +802B0070:prt_801d9e38_7c9e0e97 +802B00A0:prt_801d9e68_7c9e0e97 +802B00E8:prt_801d9eb0_f3434af +802B0114:prt_801d9edc_f3434af 802B014C:debug_overlay_draw_fifo +802B0194:prt_801d9f5c_b17b4fee +802B01D0:prt_801d9f98_b17b4fee +802B0278:prt_801da040_b17b4fee 802B0310:unset_all_dip_switches 802B0324:g_check_debug_mode_input 802B065C:pool_init @@ -4598,9 +4736,19 @@ 802C6C98:init_itemgroups 802C6DF0:empty_function 802C6DF4:load_stage +802C6FB8:prt_801f0d80_37e266fb 802C70CC:unload_stage 802C71B8:queue_stage_load +802C7200:prt_801f0fc8_8d2134c3 +802C721C:prt_801f0fe4_8d2134c3 +802C7230:prt_801f0ff8_8d2134c3 +802C7294:prt_801f105c_8d2134c3 +802C72A8:prt_801f1070_8d2134c3 802C72DC:g_load_stage_gma_tpl_lz +802C7368:prt_801f1130_8d2134c3 +802C737C:prt_801f1144_8d2134c3 +802C73E4:prt_801f11ac_8d2134c3 +802C73F8:prt_801f11c0_8d2134c3 802C7448:FUN_801f1210 802C75B4:FUN_801f137c 802C77D8:FUN_801f15a0 @@ -4663,6 +4811,7 @@ 802CC7E4:FUN_801f65ac 802CCC34:FUN_801f69fc 802CCD20:g_load_stgname_file +802CCD74:prt_801f6b3c_f3434af 802CCDD0:g_load_stgname_dvd_entrynum 802CCF04:g_get_scen_stgname_buffer_size 802CCF20:g_queue_stage_name_load @@ -4670,11 +4819,15 @@ 802CD028:read_stage_name_from_dvd 802CD128:FUN_801f6ef0 802CD170:load_stage_models +802CD260:prt_801f7028_c32105f2 +802CD35C:prt_801f7124_c32105f2 +802CD464:prt_801f722c_c32105f2 802CD8CC:FUN_801f7694 802CD99C:init_seesaws 802CD99C:init_seesaws 802CDA68:g_zero_monkey 802CDB58:load_stagedef +802CDB8C:prt_801f7954_8d2134c3 802CF930:g_free_stage 802CFB08:FUN_801f98d0 802CFBC4:FUN_801f998c @@ -4733,7 +4886,9 @@ 802D3628:FUN_801fd3f0 802D36D4:g_something_with_replays 802D3AB4:g_something_with_bundled_replays +802D3B20:prt_801fd8e8_f3434af 802D3C18:g_LoadRecFile +802D3C50:prt_801fda18_812cd95f 802D3D9C:FUN_801fdb64 802D3F98:g_something_with_replays2 802D412C:FUN_801fdef4 @@ -4890,7 +5045,15 @@ 802DFE4C:g_draw_bg 802DFEE0:g_something_with_world_themes 802E004C:g_something_with_init_or_maybe_leftover_from_smb1 +802E00B4:prt_80209e7c_f3434af +802E00C8:prt_80209e90_f3434af +802E011C:prt_80209ee4_f3434af +802E0130:prt_80209ef8_f3434af 802E0168:g_something_with_stage_world_themes2 +802E02D8:prt_8020a0a0_f3434af +802E02EC:prt_8020a0b4_f3434af +802E0364:prt_8020a12c_f3434af +802E0378:prt_8020a140_f3434af 802E0440:FUN_8020a208 802E0468:FUN_8020a230 802E0494:g_something_with_view_stage_and_bg @@ -5424,6 +5587,8 @@ 80314308:update_course_progress 803146E0:g_something_with_cm_player_progress 80314854:sprite_debug_course_display_disp +8031496C:prt_8023e734_28f463b0 +80314CA4:prt_8023ea6c_28f463b0 80314D64:g_save_cm_unlock_entries 80314D9C:g_load_cm_unlock_entries 80314DD4:FUN_8023eb9c @@ -5468,6 +5633,7 @@ 80316D5C:item_coin_dest 80316D60:item_coin_replay_init 80316F00:item_debug_coin +80316F50:prt_80240d18_eefbee0d 80316F6C:g_something_with_coins 803170C0:event_stobj_collision_init 803170C4:event_stobj_collision_tick @@ -5486,6 +5652,7 @@ 8031820C:FUN_80241fd4 80318378:FUN_80242140 803183F8:g_something_with_bumper_LODs +803185BC:prt_80242384_8d2134c3 80318800:FUN_802425c8 80318934:load_bumper_stobjs 80318BA4:load_jamabar_stobjs @@ -5521,6 +5688,7 @@ 8031AA54:stobj_button_dest 8031AA58:stobj_button_cb_f 8031AA5C:load_goaltape_and_goalbag_stobjs +8031AAF0:prt_802448b8_5924ca76 8031ACEC:stobj_goaltape_init 8031AFB4:stobj_goaltape_tick 8031B880:stobj_goaltape_disp @@ -5559,6 +5727,7 @@ 8031E968:g_smth_with_drawing_all_sprites 8031EB74:FUN_8024893c 8031EBF4:draw_sprite +8031ED28:prt_80248af0_f3434af 8031ED78:FUN_80248b40 8031ED98:load_bmp_by_id 8031EDB8:call_free_bmp_by_id @@ -5570,6 +5739,7 @@ 8031F3E0:dest_all_sprites 8031F47C:get_sprite_with_unique_id 8031F4E0:calc_sprite_bounds +8031F7C0:prt_80249588_f3434af 8031F9A0:switchD 8031F9A4:caseD_1 8031F9A4:caseD_4 @@ -5592,7 +5762,7 @@ 8031FA50:caseD_6 8031FAF0:g_get_font_char_width 8031FC14:g_get_font_char_width_scaling -8031FE7C:FUN_80249c44 +8031FE7C:textdraw_parse_control_code 8031FFE8:switchD 8031FFEC:caseD_30 8031FFF4:caseD_31 @@ -5706,6 +5876,7 @@ 80323188:FUN_8024cf50 803231AC:FUN_8024cf74 803231E0:draw_sprite_draw_request +80323820:prt_8024d5e8_f3434af 80323DEC:FUN_8024dbb4 80323E38:g_scale_sprite_for_widescreen 80323F5C:g_reset_sprite_mtx_for_widescreen @@ -6066,10 +6237,18 @@ 8032B8D0:sprite_title_disp 8032B9D8:g_create_some_controls_description_sprite 8032BAF0:create_stage_loadin_text_sprites +8032BC7C:prt_80255a44_8d2134c3 +8032BCF0:prt_80255ab8_e40233a0 +8032BD48:prt_80255b10_8d2134c3 +8032BDA0:prt_80255b68_8d2134c3 +8032BDF8:prt_80255bc0_8d2134c3 +8032BE0C:prt_80255bd4_8d2134c3 8032BFB0:sprite_loadin_stage_name_tick 8032C090:sprite_loadin_stage_name_disp +8032C5AC:prt_80256374_f3434af 8032C84C:sprite_player_num_tick 8032C914:create_player_num_and_ready_sprites +8032CA48:prt_80256810_8d2134c3 8032CB18:sprite_ready_tick 8032CCB4:sprite_bonus_stage_tick 8032CEE4:sprite_final_stage_tick @@ -6078,6 +6257,7 @@ 8032D9D0:sprite_go_tick 8032DCE0:sprite_go_disp 8032DF68:create_goal_and_jump_to_stage_sprites +8032E118:prt_80257ee0_8d2134c3 8032E134:sprite_goal_disp 8032E5E4:sprite_jump_to_stage_tick 8032E828:sprite_jump_to_stage_duplicate_tick @@ -6103,6 +6283,7 @@ 8032F6CC:caseD_4 8032F930:FUN_802596f8 8032F9F8:g_create_some_game_over_and_player_num_sprites +8032FC04:prt_802599cc_8d2134c3 8032FC24:create_game_over_letter_sprite 8032FD38:sprite_game_over_tick 803301BC:create_1up_sprite @@ -6111,10 +6292,15 @@ 80330488:create_replay_sprite 8033054C:sprite_replay_tick 803305EC:create_go_to_extra_or_master_stages_sprites +803308C8:prt_8025a690_aee7b64a 8033097C:g_sprite_extra_all_mask_tick 80330AB8:g_sprite_go_to_the_tick 80330AC8:g_sprite_go_to_the_disp 80330E50:create_postgoal_score_sprites +80330F84:prt_8025ad4c_8d2134c3 +80331050:prt_8025ae18_8d2134c3 +80331070:prt_8025ae38_8d2134c3 +803311C0:prt_8025af88_8d2134c3 803311DC:sprite_clear_score_disp 80331488:sprite_warp_bonus_disp 80331714:sprite_time_bonus_disp @@ -6201,7 +6387,9 @@ 80335098:caseD_e 80335B08:g_how_to_sprite_draw_controller_tooltips 803362E0:g_how_to_sprite_draw_rules_page +80336C60:prt_80260a28_3ccf2761 80337114:sprite_how_to_disp +8033744C:prt_80261214_95990a7d 80337A00:switchD 80337A04:caseD_3 80337A68:caseD_4 @@ -6239,23 +6427,39 @@ 8033843C:create_timer_sprites 803386B8:create_speed_sprites 80338794:create_hud_stage_name_sprites +80338C10:prt_802629d8_e40233a0 +80338C28:prt_802629f0_8d2134c3 +80338D1C:prt_80262ae4_e40233a0 +80338D34:prt_80262afc_8d2134c3 +80338E20:prt_80262be8_f3434af +80338ED4:prt_80262c9c_f3434af 80338F14:create_banana_counter_sprites 803391C0:create_monkey_counter_sprites +8033958C:prt_80263354_8d2134c3 +80339644:prt_8026340c_8d2134c3 +803396D4:prt_8026349c_8d2134c3 80339700:create_final_stage_sprite 803397AC:create_debug_course_display_sprites 80339834:sprite_score_tick +803399C0:prt_80263788_8d2134c3 803399D8:sprite_score_disp 80339B48:FUN_80263910 +80339C2C:prt_802639f4_3ccf2761 +80339CC8:prt_80263a90_3ccf2761 80339CEC:sprite_timer_ball_tick 8033A02C:sprite_speed_tick +8033A0F4:prt_80263ebc_33cfa187 +8033A170:prt_80263f38_33cfa187 8033A190:sprite_current_stage_display_tick 8033A2BC:sprite_current_stage_display_disp 8033A908:sprite_hud_stage_name_tick 8033A98C:sprite_banana_icon_tick 8033ABE4:sprite_banana_icon_shadow_tick 8033ABF4:sprite_banana_count_tick +8033AC30:prt_802649f8_8d2134c3 8033AC44:g_banana_disp_efc_req 8033AD00:sprite_monkey_counter_tick +8033AD80:prt_80264b48_8d2134c3 8033AD94:sprite_hud_player_num_disp 8033AFF4:event_minimap_init 8033B118:event_minimap_tick @@ -6299,9 +6503,22 @@ 8033F2E8:caseD_6 8033F2E8:caseD_7 8033F908:FUN_802696d0 +8033FD6C:prt_80269b34_3ccf2761 +8033FDD8:prt_80269ba0_3ccf2761 80340338:FUN_8026a100 80340490:FUN_8026a258 +803406A8:prt_8026a470_3ccf2761 +8034070C:prt_8026a4d4_3ccf2761 +80340860:prt_8026a628_3ccf2761 +803408C8:prt_8026a690_3ccf2761 +80340A1C:prt_8026a7e4_3ccf2761 +80340A84:prt_8026a84c_3ccf2761 +80340BD8:prt_8026a9a0_3ccf2761 +80340C40:prt_8026aa08_3ccf2761 80340C5C:FUN_8026aa24 +80340D80:prt_8026ab48_8d2134c3 +80340DF0:prt_8026abb8_8d2134c3 +80341008:prt_8026add0_8d2134c3 8034109C:FUN_8026ae64 8034117C:FUN_8026af44 803413F8:FUN_8026b1c0 @@ -6313,6 +6530,10 @@ 803415A8:FUN_8026b370 80341654:FUN_8026b41c 80341710:g_replay_screen_stage_name +803417D4:prt_8026b59c_e40233a0 +80341938:prt_8026b700_b77dbcc8 +80341968:prt_8026b730_b77dbcc8 +80341994:prt_8026b75c_407e704c 80341A00:FUN_8026b7c8 80341AD8:FUN_8026b8a0 80341BD4:FUN_8026b99c @@ -6320,6 +6541,7 @@ 80341D10:FUN_8026bad8 80341D30:FUN_8026baf8 80341F80:FUN_8026bd48 +80342080:prt_8026be48_9f181aee 803420E4:empty_function 803420E8:set_global_ape_LOD_1 803420FC:empty_function @@ -6351,11 +6573,11 @@ 80342E7C:g_some_arq_callback 80342E90:load_disc_queue 803432D0:g_something_with_dvd -80343378:dvd_open_file -80343448:dvd_close -8034348C:g_some_ARQPostRequest_callback -803434A0:dvd_read_file_into_buffer -80343574:get_file_size +80343378:file_open +80343448:file_close +8034348C:ARQPostRequest_on_finish +803434A0:file_read +80343574:file_size 80343594:FUN_8026d35c 803435B4:g_some_dvd_callback 803436B4:g_something_with_dvd2 @@ -6390,6 +6612,7 @@ 803459FC:FUN_8026f7c4 80345C0C:debug_draw_shadow_textures 80345E88:md_mini_func +80345EE0:prt_8026fca8_5924ca76 80345F20:g_set_minigame_specific_funcs 80345F54:FUN_8026fd1c 80345F84:g_smd_mini_generic_init @@ -6402,6 +6625,8 @@ 803466F8:smd_mini_ending_init 803467A8:smd_mini_ending_tick 803469AC:mini_ending_draw_func +803469FC:prt_802707c4_5924ca76 +80346A14:prt_802707dc_5924ca76 80346A30:smd_mini_s_roll_init 80346A6C:smd_mini_s_roll_tick 80346A8C:mini_nameentry_draw_func @@ -6543,6 +6768,7 @@ 80354208:caseD_e 8035426C:FUN_8027e034 803542C4:g_mini_commend_draw_func +80354310:prt_8027e0d8_6523bb0e 80354380:FUN_8027e148 8035475C:FUN_8027e524 803548E0:FUN_8027e6a8 @@ -6772,11 +6998,14 @@ 8035EBB4:g_something_with_card4 8035F0FC:g_something_with_card8 8035F3D4:g_something_with_card6 +8035FC64:prt_80289a2c_8d2134c3 +8035FD3C:prt_80289b04_8d2134c3 8035FFD0:g_check_some_memcard_field 8036002C:g_get_result_code 8036003C:FUN_80289e04 803600A8:g_get_some_memcard_var 803600B8:g_sprintf_memcard_error +80360130:prt_80289ef8_aee7b64a 80360144:FUN_80289f0c 80360188:FUN_80289f50 8036019C:g_get_last_used_memcard_slot @@ -6793,9 +7022,15 @@ 80360524:FUN_8028a2ec 80360558:FUN_8028a320 803605C0:g_some_replay_func +80360750:prt_8028a518_de160641 +80360908:prt_8028a6d0_407e704c +803609A4:prt_8028a76c_475ee52d +803609F4:prt_8028a7bc_475ee52d +80360A44:prt_8028a80c_475ee52d 80360AA0:FUN_8028a868 80360B0C:g_some_replay_func2 80360C34:g_some_replay_func3 +80360C84:prt_8028aa4c_cdc47a83 80360CC4:FUN_8028aa8c 80360F3C:g_something_with_fonts 80361024:FUN_8028adec @@ -6803,6 +7038,7 @@ 80361498:g_some_printf_function_6 8036155C:smd_mini_ranking_init 803615FC:smd_mini_ranking_tick +80361648:prt_8028b410_6523bb0e 80361838:adsrSetup 80361A6C:cPlayer::PostPhysicsUpdate(void) 80361A8C:cPlayer::PostPhysicsUpdate(void) @@ -6812,13 +7048,38 @@ 803627C4:adsrSetup 80362C24:FUN_8028c9ec 80362D94:FUN_8028cb5c +80362FB0:prt_8028cd78_3af5b9f0 +80363048:prt_8028ce10_3af5b9f0 +8036327C:prt_8028d044_3af5b9f0 +80363328:prt_8028d0f0_3af5b9f0 8036335C:FUN_8028d124 +803634F0:prt_8028d2b8_3ccf2761 +80363550:prt_8028d318_3ccf2761 +803635D8:prt_8028d3a0_3ccf2761 +80363628:prt_8028d3f0_3ccf2761 803637CC:FUN_8028d594 803638D0:FUN_8028d698 +80363CB0:prt_8028da78_3ccf2761 803645C4:FUN_8028e38c +803649B4:prt_8028e77c_3ccf2761 +80364BF8:prt_8028e9c0_3ccf2761 +80364C8C:prt_8028ea54_3ccf2761 80365100:FUN_8028eec8 +803654E0:prt_8028f2a8_3ccf2761 +8036575C:prt_8028f524_3ccf2761 +803657F0:prt_8028f5b8_3ccf2761 +80365A68:prt_8028f830_3ccf2761 +80365AFC:prt_8028f8c4_3ccf2761 80365E64:FUN_8028fc2c +8036625C:prt_80290024_3ccf2761 +803664E4:prt_802902ac_3ccf2761 +8036657C:prt_80290344_3ccf2761 +80366728:prt_802904f0_3ccf2761 +803667C0:prt_80290588_3ccf2761 +80366968:prt_80290730_3ccf2761 +80366A00:prt_802907c8_3ccf2761 80366C74:FUN_80290a3c +80367054:prt_80290e1c_3ccf2761 8036796C:FUN_80291734 80367B30:FUN_802918f8 80367CA4:FUN_80291a6c @@ -6833,11 +7094,17 @@ 80368624:FUN_802923ec 803686E0:FUN_802924a8 80368760:FUN_80292528 +80368870:prt_80292638_afa153d6 80368888:FUN_80292650 +80368928:prt_802926f0_6e5c842b 80368940:FUN_80292708 +803689D0:prt_80292798_6e5c842b 803689E8:FUN_802927b0 +80368A78:prt_80292840_6e5c842b 80368A90:FUN_80292858 +80368B60:prt_80292928_65a573f6 80368B78:FUN_80292940 +80368C88:prt_80292a50_afa153d6 80368CA0:FUN_80292a68 80368E74:FUN_80292c3c 80369070:FUN_80292e38 @@ -6856,6 +7123,8 @@ 80369FF4:FUN_80293dbc 8036A084:FUN_80293e4c 8036A370:g_maybe_save_previews +8036A798:prt_80294560_891e8130 +8036A82C:prt_802945f4_c32105f2 8036A848:g_something_with_smb1_ranking_main_game_defaults_wrapper 8036A868:event_name_entry_init 8036AB44:event_name_entry_tick @@ -6875,6 +7144,7 @@ 8036B458:caseD_0 8036BA1C:event_name_entry_dest 8036BA40:g_something_with_name_entry +8036BD88:prt_80295b50_3ccf2761 8036C004:FUN_80295dcc 8036C054:FUN_80295e1c 8036C1D4:FUN_80295f9c @@ -7027,11 +7297,17 @@ 80379708:FUN_802a34d0 8037980C:switchD 80379810:caseD_70 +80379824:prt_802a35ec_8d2134c3 8037982C:caseD_74 +80379840:prt_802a3608_8d2134c3 80379848:caseD_6e +8037985C:prt_802a3624_8d2134c3 80379864:caseD_63 +80379878:prt_802a3640_8d2134c3 80379880:caseD_62 +80379894:prt_802a365c_8d2134c3 8037989C:caseD_6d +803798B0:prt_802a3678_8d2134c3 803798B8:caseD_64 803798B8:caseD_65 803798B8:caseD_66 @@ -7095,18 +7371,17 @@ 8037B418:apply_wormhole_tf_to_quat 8037B460:empty_function 8037B464:FUN_802a522c -8037B4DC:g_load_skl -8037B7F0:g_handL_SKL_func -8037B828:FUN_802a55f0 -8037B850:gan_setanim_wrapper -8037B8A4:gan_setAnim -8037B8A4:gan_setAnim -8037BCDC:gan_setanim_edance +8037B4DC:init_component_state +8037B7F0:g_init_some_handl_component_stuff +8037B828:g_init_mta +8037B850:g_some_ape_anim_init_wrapper +8037B8A4:g_init_skeleton_animation +8037BCDC:g_unk_ape_anim1 8037C014:FUN_802a5ddc 8037C170:FUN_802a5f38 8037C1C0:FUN_802a5f88 -8037C288:g_init_floatthing -8037C2DC:gan_incframe +8037C288:g_init_bone_state_subA +8037C2DC:g_unk_ape_anim2 8037C438:g_set_more_ape_state 8037C474:g_smth_with_quat_slerp 8037C770:FUN_802a6538 @@ -7114,24 +7389,41 @@ 8037D2B8:FUN_802a7080 8037D710:cPlayer::PostPhysicsUpdate(void) 8037D9D0:FUN_802a7798 -8037E164:g_something_arc +8037E164:ape_archive_offsets_to_pointers 8037E1B4:FUN_802a7f7c 8037E220:g_table_index 8037E2B0:FUN_802a8078 8037E56C:FUN_802a8334 8037E790:FUN_802a8558 8037EC08:FUN_802a89d0 -8037ED24:load_ape_body -8037F1C4:gan_setanim_estagebegin +8037ED24:g_load_ape_mtas +8037ED94:prt_802a8b5c_aee7b64a +8037EE44:prt_802a8c0c_f3434af +8037EF00:prt_802a8cc8_f3434af +8037EFA8:prt_802a8d70_f3434af +8037EFF0:prt_802a8db8_f3434af +8037F0AC:prt_802a8e74_f3434af +8037F0FC:prt_802a8ec4_f3434af +8037F18C:prt_802a8f54_f3434af +8037F1C4:g_init_mtas 8037F484:g_something_freeing_chara_heap_3 -8037F648:g_something_with_new_ape +8037F648:g_load_ape_mals +8037F6CC:prt_802a9494_f3434af +8037F844:prt_802a960c_aee7b64a 8037F974:FUN_802a973c 8037FA1C:event_ape_init +8037FB88:prt_802a9950_f3434af +8037FC58:prt_802a9a20_f3434af +8037FD28:prt_802a9af0_f3434af +8037FDF8:prt_802a9bc0_f3434af 8037FEE8:event_ape_tick 8037FF90:g_ape_default_draw 8037FFBC:event_ape_dest 80380038:load_ape -803806F4:load_ape_s +80380318:prt_802aa0e0_aee7b64a +8038036C:prt_802aa134_f3434af +80380408:prt_802aa1d0_aee7b64a +803806F4:g_load_ape_variant0 80380718:load_ape_gameplay 8038076C:switchD 80380770:caseD_3 @@ -7148,9 +7440,9 @@ 80380820:caseD_4 80380820:caseD_b 80380820:caseD_e -80380898:load_ape_gameplay_LOD +80380898:g_load_ape_gameplay_variant0 803808BC:draw_ape_subroutine -803808E8:g_draw_ape1 +803808E8:g_draw_ape 80380A80:dip_ape_facedir 803814D8:g_check_apenum_dipswitch 80381530:no_anim @@ -7161,16 +7453,21 @@ 80381C54:g_ape_anim_body 80381D8C:GetOneTimerLeadGroundContactAnims(void) 80382AB4:g_load_mal_files_from_disc +80382B8C:prt_802ac954_aee7b64a +80382BE0:prt_802ac9a8_f3434af +80382C7C:prt_802aca44_aee7b64a +80382CDC:prt_802acaa4_f3434af +80382DA0:prt_802acb68_aee7b64a 80382E78:g_something_freeing_chara_heap_4 8038319C:g_something_freeing_chara_heap_2 -803832B4:assign_model_pointers +803832B4:assign_ape_assets 80383368:FUN_802ad130 803834A8:FUN_802ad270 803835E8:FUN_802ad3b0 80383734:FUN_802ad4fc 80383768:FUN_802ad530 8038377C:FUN_802ad544 -80383790:gan_getsomeframe +80383790:g_get_ape_anim_smth 803837C0:FUN_802ad588 803837CC:body_frame_add72 803837D8:FUN_802ad5a0 @@ -7180,11 +7477,19 @@ 803838C4:FUN_802ad68c 80383900:FUN_802ad6c8 80383940:FUN_802ad708 -80383948:get_ape_game_string +80383948:get_ape_scene_name 803839B0:FUN_802ad778 80383A14:get_ape_anim_flags 80383AA8:preload_ape -80383B9C:g_load_ape_mta_mal_files +80383B14:prt_802ad8dc_aee7b64a +80383B4C:prt_802ad914_aee7b64a +80383B70:prt_802ad938_f3434af +80383B9C:g_queue_ape_mta_mal_load +80383BE8:prt_802ad9b0_aee7b64a +80383C0C:prt_802ad9d4_f3434af +80383C30:prt_802ad9f8_f3434af +80383C74:prt_802ada3c_f3434af +80383CA4:prt_802ada6c_aee7b64a 80383CCC:FUN_802ada94 80383D40:g_something_with_comparing_strings 80383DB4:FUN_802adb7c @@ -7192,20 +7497,21 @@ 80383EC4:FUN_802adc8c 80383F48:register_ape 80383FDC:unregister_ape -80383FFC:get_ape_index +80383FFC:get_ape_by_idx 80384014:dip_apenum_draw +80384048:prt_802ade10_8d2134c3 8038413C:FUN_802adf04 803841D0:FUN_802adf98 -8038425C:get_ape_name_string +8038425C:get_ape_chara_name 80384294:get_ape_lod_string -803842CC:FUN_802ae094 -80384308:get_ape_face_string +803842CC:g_get_ape_skinning_or_stitching_name +80384308:get_ape_face_expr_name 8038438C:seek 803843B0:FUN_802ae178 80384790:FUN_802ae558 80384834:FUN_802ae5fc 8038487C:FUN_802ae644 -80384890:g_load_models +80384890:assign_ape_models 80384DF4:FUN_802aebbc 80384F30:g_get_structure_from_ape_common_mal_struct 8038526C:FUN_802af034 @@ -7220,7 +7526,7 @@ 80385A74:FUN_802af83c 80385AB4:g_alloc_some_ape_state_0x8 80385B38:FUN_802af900 -80385BEC:gan_setanim_e4 +80385BEC:g_ape_anim_unk3 80385CF4:FUN_802afabc 80385F94:FUN_802afd5c 80386090:FUN_802afe58 @@ -7230,7 +7536,7 @@ 80386C70:g_set_ape_dance_state1 80386EA8:g_set_ape_dance_state2 803871F0:FUN_802b0fb8 -80387344:gan_setAnim2 +80387344:g_ape_anim_unk4 803874A0:FUN_802b1268 80387584:g_some_ape_anim_func2 80387778:FUN_802b1540 @@ -7250,28 +7556,39 @@ 8038846C:g_init_rankings_to_defaults 803886DC:FUN_802b24a4 803888B8:g_smth_with_ending_course_2 +803889E0:prt_802b27a8_f51c8b33 80388D84:FUN_802b2b4c 80388E14:g_NameEntry2_InitFirst +80388F64:prt_802b2d2c_37e266fb 8038903C:FUN_802b2e04 +80389368:prt_802b3130_37e266fb +8038937C:prt_802b3144_37e266fb +80389390:prt_802b3158_37e266fb 803893CC:FUN_802b3194 80389974:FUN_802b373c +80389CB8:prt_802b3a80_b38a9774 80389CF4:FUN_802b3abc +80389F3C:prt_802b3d04_37e266fb +80389F4C:prt_802b3d14_37e266fb 8038A390:FUN_802b4158 8038A464:FUN_802b422c 8038A97C:FUN_802b4744 8038ACB4:g_nameentry2_init 8038BE28:FUN_802b5bf0 +8038C1DC:prt_802b5fa4_6e5c842b 8038C204:FUN_802b5fcc 8038C278:game_nameentry_draw_func 8038C758:FUN_802b6520 8038C7BC:FUN_802b6584 8038C8D8:ape_assignment +8038C9C8:prt_802b6790_a65c839 8038CA0C:switchD 8038CA10:caseD_0 8038CC1C:caseD_1 8038D6C4:caseD_2 8038D718:caseD_3 8038D7FC:caseD_4 +8038DC38:prt_802b7a00_65a573f6 8038DC64:caseD_5 8038DD0C:caseD_6 8038DF08:caseD_7 @@ -7282,6 +7599,7 @@ 8038E57C:FUN_802b8344 8038E5D0:FUN_802b8398 8038E968:FUN_802b8730 +8038EF90:prt_802b8d58_37e266fb 8038F1FC:FUN_802b8fc4 8038F400:switchD 8038F404:caseD_b @@ -7291,9 +7609,12 @@ 803900DC:caseD_e 803901AC:caseD_f 80390244:caseD_10 +8039043C:prt_802ba204_37e266fb 80390578:caseD_11 8039059C:cPlayer::PostPhysicsUpdate(void) 80390740:caseD_12 +803907CC:prt_802ba594_37e266fb +803907E0:prt_802ba5a8_37e266fb 80390814:caseD_13 80390860:caseD_14 803908D8:caseD_15 @@ -7313,6 +7634,8 @@ 80392E38:FUN_802bcc00 80392F80:FUN_802bcd48 8039317C:FUN_802bcf44 +80393224:prt_802bcfec_37e266fb +80393274:prt_802bd03c_37e266fb 80393434:FUN_802bd1fc 80393604:FUN_802bd3cc 8039406C:FUN_802bde34 @@ -7321,18 +7644,51 @@ 803944A4:FUN_802be26c 80394580:FUN_802be348 8039465C:FUN_802be424 +80394960:prt_802be728_3ccf2761 +8039499C:prt_802be764_3ccf2761 803949C4:FUN_802be78c +80394DF4:prt_802bebbc_3af5b9f0 +80394E58:prt_802bec20_3af5b9f0 80394E94:FUN_802bec5c +8039561C:prt_802bf3e4_3ccf2761 +80395654:prt_802bf41c_3ccf2761 80395684:FUN_802bf44c +803959A4:prt_802bf76c_8d2134c3 +80395A84:prt_802bf84c_8d2134c3 80395CEC:FUN_802bfab4 +80395E0C:prt_802bfbd4_8d2134c3 +80395F90:prt_802bfd58_8d2134c3 80396068:FUN_802bfe30 8039643C:FUN_802c0204 +80396B20:prt_802c08e8_8d2134c3 +80396BEC:prt_802c09b4_1be26b86 +80396CF8:prt_802c0ac0_8d2134c3 +80396DF8:prt_802c0bc0_8d2134c3 +80396F24:prt_802c0cec_8d2134c3 +80396FEC:prt_802c0db4_8d2134c3 +80397178:prt_802c0f40_8d2134c3 +80397248:prt_802c1010_8d2134c3 +803973D4:prt_802c119c_8d2134c3 803974A4:prt_802c126c_8d2134c3 80397568:FUN_802c1330 +80398478:prt_802c2240_8d2134c3 +80398520:prt_802c22e8_1be26b86 +80398678:prt_802c2440_8d2134c3 803987C0:FUN_802c2588 80398804:FUN_802c25cc 80398AD4:FUN_802c289c +80399040:prt_802c2e08_1be26b86 +8039920C:prt_802c2fd4_8d2134c3 +803993CC:prt_802c3194_8d2134c3 +803995B8:prt_802c3380_8d2134c3 +803996B0:prt_802c3478_8d2134c3 +8039989C:prt_802c3664_8d2134c3 +8039999C:prt_802c3764_8d2134c3 +80399B88:prt_802c3950_8d2134c3 +80399C88:prt_802c3a50_8d2134c3 80399DB4:FUN_802c3b7c +8039AA6C:prt_802c4834_3ccf2761 +8039AAC0:prt_802c4888_3ccf2761 8039AB6C:FUN_802c4934 8039ABD8:FUN_802c49a0 8039AC44:FUN_802c4a0c @@ -7344,33 +7700,99 @@ 8039BD1C:GoalOverlay::SceneCreated(void) 8039BE64:GoalOverlay::SceneCreated(void) 8039BF80:GoalOverlay::SceneCreated(void) +8039C848:prt_802c6610_1be26b86 +8039C998:prt_802c6760_8d2134c3 +8039CA24:prt_802c67ec_8d2134c3 8039CDC8:FUN_802c6b90 +8039E620:prt_802c83e8_8d2134c3 8039E690:DrawableCharacter::GetAnimController( 8039EAB0:FUN_802c8878 +803A0308:prt_802ca0d0_3ccf2761 +803A0348:prt_802ca110_3ccf2761 803A0840:FUN_802ca608 803A0C44:cPlayer::PostPhysicsUpdate(void) +803A28EC:prt_802cc6b4_3ccf2761 +803A2944:prt_802cc70c_3ccf2761 +803A29A8:prt_802cc770_3ccf2761 +803A2A00:prt_802cc7c8_3ccf2761 +803A2A84:prt_802cc84c_3ccf2761 +803A2AF0:prt_802cc8b8_3ccf2761 803A2D88:FUN_802ccb50 +803A470C:prt_802ce4d4_1be26b86 +803A4874:prt_802ce63c_8d2134c3 +803A4900:prt_802ce6c8_8d2134c3 803A4C74:FUN_802cea3c 803A624C:cPlayer::PostPhysicsUpdate(void) +803A64BC:prt_802d0284_8d2134c3 803A693C:FUN_802d0704 +803A81AC:prt_802d1f74_8d2134c3 803A863C:FUN_802d2404 +803A8944:prt_802d270c_1be26b86 +803A8AC8:prt_802d2890_8d2134c3 +803A8BA8:prt_802d2970_8d2134c3 +803A9034:prt_802d2dfc_8d2134c3 +803A9124:prt_802d2eec_1be26b86 +803A92A8:prt_802d3070_8d2134c3 +803A9388:prt_802d3150_8d2134c3 803A974C:EXIGetState 803A9764:CBGetBytesAvailableForRead +803A9888:prt_802d3650_1be26b86 +803A9A30:prt_802d37f8_8d2134c3 +803A9AFC:prt_802d38c4_8d2134c3 803A9EB8:FUN_802d3c80 +803AA238:prt_802d4000_3ccf2761 +803AA270:prt_802d4038_3ccf2761 +803AA308:prt_802d40d0_3af5b9f0 +803AA360:prt_802d4128_3af5b9f0 +803AA3E8:prt_802d41b0_8d2134c3 803AA6B8:FUN_802d4480 +803AAA38:prt_802d4800_3ccf2761 +803AAA70:prt_802d4838_3ccf2761 +803AAB08:prt_802d48d0_3af5b9f0 +803AAB60:prt_802d4928_3af5b9f0 +803AAB94:prt_802d495c_8d2134c3 803AAED4:FUN_802d4c9c +803AB2AC:prt_802d5074_3ccf2761 +803AB2E4:prt_802d50ac_3ccf2761 +803AB37C:prt_802d5144_3af5b9f0 +803AB3D4:prt_802d519c_3af5b9f0 +803AB434:prt_802d51fc_8d2134c3 +803AB4CC:prt_802d5294_8d2134c3 +803AB57C:prt_802d5344_8d2134c3 803AB734:FUN_802d54fc +803ABA3C:prt_802d5804_1be26b86 +803ABBC0:prt_802d5988_8d2134c3 +803ABCA0:prt_802d5a68_8d2134c3 +803AC0BC:prt_802d5e84_8d2134c3 +803AC1AC:prt_802d5f74_1be26b86 +803AC330:prt_802d60f8_8d2134c3 +803AC410:prt_802d61d8_8d2134c3 +803AC8A4:prt_802d666c_1be26b86 +803ACA4C:prt_802d6814_8d2134c3 +803ACB18:prt_802d68e0_8d2134c3 803ACE68:FUN_802d6c30 +803AD208:prt_802d6fd0_3ccf2761 +803AD270:prt_802d7038_3ccf2761 +803AD300:prt_802d70c8_3af5b9f0 +803AD370:prt_802d7138_3af5b9f0 +803AD3DC:prt_802d71a4_8d2134c3 803AD724:FUN_802d74ec +803ADAC4:prt_802d788c_3ccf2761 +803ADB2C:prt_802d78f4_3ccf2761 +803ADBBC:prt_802d7984_3af5b9f0 +803ADC2C:prt_802d79f4_3af5b9f0 +803ADC98:prt_802d7a60_8d2134c3 803ADFE0:FUN_802d7da8 803AE354:FUN_802d811c 803AE594:FUN_802d835c 803AE824:FUN_802d85ec 803AEAE0:FUN_802d88a8 +803AED4C:prt_802d8b14_812cd95f 803AEDE4:FUN_802d8bac 803AF114:FUN_802d8edc 803AF34C:FUN_802d9114 803AF5CC:FUN_802d9394 +803AF84C:prt_802d9614_37e266fb 803AF870:FUN_802d9638 803AF890:FUN_802d9658 803AF9B8:sprite_rank_tick @@ -7495,6 +7917,8 @@ 803B3BCC:FUN_802dd994 803B3E98:FUN_802ddc60 803B3ECC:g_something_to_do_with_soft_fx +803B3F10:prt_802ddcd8_37e266fb +803B3F58:prt_802ddd20_37e266fb 803B4040:FUN_802dde08 803B410C:FUN_802dded4 803B4190:FUN_802ddf58 @@ -7631,6 +8055,7 @@ 803C150C:FUN_802eb2d4 803C1A7C:FUN_802eb844 803C1AF0:FUN_802eb8b8 +803C1B54:prt_802eb91c_f3434af 803C1BBC:empty_function 803C1BC0:FUN_802eb988 803C1D94:FUN_802ebb5c @@ -7851,6 +8276,8 @@ 803D2790:FUN_802fc558 803D27CC:FUN_802fc594 803D29DC:load_dialog_tbl +803D2A3C:prt_802fc804_aee7b64a +803D2A68:prt_802fc830_aee7b64a 803D2B50:FUN_802fc918 803D2B7C:g_smth_with_dialog2 803D2BA8:FUN_802fc970 @@ -7863,6 +8290,9 @@ 803D2F00:empty_function 803D2F04:FUN_802fcccc 803D3070:FUN_802fce38 +803D3158:prt_802fcf20_37e266fb +803D31A8:prt_802fcf70_37e266fb +803D31FC:prt_802fcfc4_37e266fb 803D3370:FUN_802fd138 803D36A4:FUN_802fd46c 803D38D8:FUN_802fd6a0 @@ -7934,8 +8364,14 @@ 803D9B58:smd_author_select_init 803D9B9C:smd_author_select_tick 803D9E14:g_print_author_debug_data +803D9E78:prt_80303c40_272b6414 +803D9E8C:prt_80303c54_5924ca76 +803D9EA0:prt_80303c68_5924ca76 +803D9EB4:prt_80303c7c_5924ca76 +803D9EC8:prt_80303c90_5924ca76 803D9F34:smd_author_play_init 803DA0AC:smd_author_play_tick +803DA174:prt_80303f3c_37e266fb 803DA384:smd_author_play_story_init 803DA3E0:FUN_803041a8 803DA518:smd_author_play_ending_init @@ -7944,7 +8380,9 @@ 803DA834:smd_author_play_ret_sel 803DA858:FUN_80304620 803DA9B8:md_author_func +803DAA10:prt_803047d8_5924ca76 803DAA50:author_draw_func +803DAB1C:prt_803048e4_5924ca76 803DABA8:FUN_80304970 803DABD8:FUN_803049a0 803DABE8:g_assign_new_main_and_sub_mode_for_play_tick @@ -8387,17 +8825,27 @@ 804A8980:cFielder::UpdatePlay(float) 804A89D0:nw4hbm::ut::TextWriterBase::GetCharSpace(void) 804A9838:switchdataD_803d35f0 -804AE854:postfix_table -804AE864:postfix_table_s -804AE8F8:ape_name_enum +804A9C88:g_mini_race_scene +804A9C90:g_mini_target_scene +804A9C98:g_mini_bowling_scene +804A9C9C:g_mini_billiards_scene +804A9D94:g_aiai_lod0_skel_def2_list +804A9ED4:g_aiai_lod1_skel_def2_list +804AA02C:g_aiai_lod3_lod4_skel_def2_list +804AE61C:g_component_defs +804AE854:ape_lod_names +804AE864:g_ape_lod_names2 +804AE8F8:chara_names 804AE908:storymode_ape_enum 804AE958:ape_lod_enum +804AE9B0:g_mesh_type_name 804AE9F0:eye_string_table -804AED70:eye_name_table -804AEF0C:game_name_enum -804AEFFC:enum_face_types +804AEC08:aiai_eye_model_names +804AED70:g_per_chara_blink_models +804AEF0C:scene_names +804AEFFC:ape_face_names 804AF0E0:ape_face_enum_alt -804AF154:ape_face_enum_monkey +804AF154:ape_face_expr_names 804AF31C:s_%s_%s.mta 804AF328:s_new_ape.c 804AF344:s_%s_main.mta @@ -8780,8 +9228,9 @@ 80615A30:disc_queue_start 80615A34:disc_queue_end 80615A90:discQueueGroup -80615AB4:g_cached_file_entries +80615AB4:file_cache_entries 806162B4:g_last_filename_attempted_to_open +806162B8:g_aram_read_pending 8061A994:g_minigame_tick_func 8061A998:g_mini_draw_func_ptr 8061BA68:g_haze_type @@ -8808,27 +9257,28 @@ 80620AAC:g_avdisp_bound_sphere_scale 80620AD0:g_avdisp_material_alpha 80620AF4:avdisp_tex_mtx -80621630:main_mta_storage -806216F8:face_bones -806216FC:face_mta_storage -806217C4:handR_bones -806217C8:hand_mta_storage -80621890:tailBone +80621628:g_main_components +80621630:g_main_components +806216F4:g_face_components +806217C0:g_handr_components +806217C8:g_hand_components +8062188C:g_tail_component +80621890:g_madh_tail_component 80621894:tail_mta_storage -8062189C:handLbones +80621898:g_handl_components 806218A0:g_chara_storage2 80621964:common_anim_storage 806219A8:game_mal_storage -806219EC:arc_location +806219EC:skel_ska 806219F0:common_mal_sizes 80621A34:game_mal_sizes 80621A78:ape_tpls 80621B88:rep_tpl_table 80621BCC:ape_gma_table -80621CDC:ape_skl_arc_handle -80621CF8:ape_skl_arc_data -80621CFC:g_common_mtx -80621D2C:g_some_floats +80621CDC:arc_file_handle +80621CF8:skl_arc +80621CFC:g_common_ape_mtx +80621D2C:g_ape_floats 80621E2C:ape_ref_count_table 8062204C:registered_apes 8062214C:total_apes_registered @@ -8853,10 +9303,14 @@ 808F40B8:main_game_rel_prolog 808F4110:main_game_rel_epilog 808F4170:main_game_rel_unlinked +808F41C4:prt_804cc14c_92f7eb37 808F421C:md_game_func +808F4274:prt_804cc1fc_5924ca76 808F42B4:smd_game_first_init 808F45C0:smd_game_restart_init 808F465C:smd_game_ready_init +808F4928:prt_804cc8b0_812cd95f +808F4990:prt_804cc918_37e266fb 808F4BA0:smd_game_ready_tick 808F4D98:smd_game_play_init 808F4F78:smd_game_play_tick @@ -9033,6 +9487,7 @@ 80900A70:g_sprite_world_info_disp 80900BF8:sprite_scen_stagesel_stage_name_tick 80900D3C:sprite_scen_stagesel_stage_name_disp +80900E18:prt_804d8da0_f3434af 8090107C:sprite_story_difficulty_tick 80901080:sprite_story_difficulty_disp 809013F8:g_draw_story_stage_preview_ball @@ -9054,6 +9509,7 @@ 8090246C:FUN_804da3f4 809024D0:FUN_804da458 809028D0:g_draw_now_loading_text +809029AC:prt_804da934_1be26b86 80902B10:FUN_804daa98 80902C24:FUN_804dabac 80902C74:FUN_804dabfc @@ -9122,6 +9578,11 @@ 80906FB4:caseD_a 80907000:caseD_b 80907028:draw_storymode_save_file +8090725C:prt_804df1e4_3ccf2761 +80907508:prt_804df490_3ccf2761 +80907598:prt_804df520_9f181aee +8090767C:prt_804df604_f1582bad +809076A8:prt_804df630_3ccf2761 80907914:FUN_804df89c 80908680:g_related_to_loading_dataselect_menu 809088F0:dmd_scen_loadgame_main_child @@ -9152,6 +9613,9 @@ 8090A48C:caseD_2 8090A5F4:caseD_3 8090A638:caseD_4 +8090A700:prt_804e2688_812cd95f +8090A718:prt_804e26a0_37e266fb +8090A8B4:prt_804e283c_37e266fb 8090A8BC:caseD_5 8090A974:caseD_6 8090A9F4:caseD_7 @@ -9183,6 +9647,7 @@ 8090BA70:caseD_1 8090BA70:caseD_4 8090BA88:g_staff_roll_name_align +8090BAF0:prt_804e3a78_37e266fb 8090C4AC:FUN_804e4434 8090C7AC:FUN_804e4734 8090CA68:FUN_804e49f0 @@ -9235,8 +9700,17 @@ 8090F840:FUN_804e77c8 8090FA84:FUN_804e7a0c 8090FB04:staff_roll_results_draw_final_score +8090FCFC:prt_804e7c84_8d2134c3 +8090FDCC:prt_804e7d54_8d2134c3 +8090FE48:prt_804e7dd0_9f181aee +8090FE8C:prt_804e7e14_9f181aee +80910160:prt_804e80e8_8d2134c3 8091019C:FUN_804e8124 80910314:staff_roll_results_draw_monkey_rating +809103B8:prt_804e8340_9f181aee +809103FC:prt_804e8384_9f181aee +809106A0:prt_804e8628_9f181aee +809106D8:prt_804e8660_9f181aee 80910704:staff_roll_results_draw_banana_count 80910920:switchD 80910924:caseD_0 @@ -9465,6 +9939,7 @@ 808F40B8:sel_ngc_prolog 808F4154:sel_ngc_epilog 808F41A4:sel_ngc_unlinked_func +808F41F8:prt_8054a160_92f7eb37 808F4250:FUN_8054a1b8 808F428C:switchD 808F4290:caseD_b @@ -9639,6 +10114,21 @@ 808FAC40:FUN_80550ba8 808FAF80:FUN_80550ee8 808FB2C0:menu_character_select_tick +808FE414:prt_8055437c_28f463b0 +808FE460:prt_805543c8_28f463b0 +808FE4B4:prt_8055441c_28f463b0 +808FE500:prt_80554468_28f463b0 +808FE60C:prt_80554574_28f463b0 +808FE658:prt_805545c0_28f463b0 +808FE7C4:prt_8055472c_28f463b0 +808FE810:prt_80554778_28f463b0 +808FE8A0:prt_80554808_28f463b0 +808FE8F0:prt_80554858_28f463b0 +808FEA00:prt_80554968_3ccf2761 +808FEA3C:prt_805549a4_3ccf2761 +808FEC88:prt_80554bf0_3ccf2761 +808FECC4:prt_80554c2c_3ccf2761 +808FF2CC:prt_80555234_3ccf2761 808FF324:menu_gameplay_settings_tick 808FF440:switchD 808FF444:caseD_b @@ -9829,18 +10319,42 @@ 809051E4:menu_option_screen_tick 80905254:FUN_8055b1bc 809052C4:g_handle_starting_monkeys_count +80905404:prt_8055b36c_8d2134c3 80905448:FUN_8055b3b0 +80905668:prt_8055b5d0_8d2134c3 +8090574C:prt_8055b6b4_f3434af +809057F8:prt_8055b760_f3434af +809058A4:prt_8055b80c_f3434af 809058F8:FUN_8055b860 80905918:FUN_8055b880 8090593C:FUN_8055b8a4 +80905B24:prt_8055ba8c_f3434af +80905C1C:prt_8055bb84_8d2134c3 80905C70:FUN_8055bbd8 +80905E1C:prt_8055bd84_8d2134c3 +80905F8C:prt_8055bef4_8d2134c3 +80906038:prt_8055bfa0_f3434af 8090608C:FUN_8055bff4 +809061F0:prt_8055c158_f3434af +809062E4:prt_8055c24c_8d2134c3 +80906460:prt_8055c3c8_f3434af 8090649C:FUN_8055c404 +809066A0:prt_8055c608_f3434af 809066FC:FUN_8055c664 +80906958:prt_8055c8c0_8d2134c3 +80906AA8:prt_8055ca10_f3434af +80906B5C:prt_8055cac4_f3434af +80906C10:prt_8055cb78_f3434af 80906C64:FUN_8055cbcc 80906C84:FUN_8055cbec 80906CA8:FUN_8055cc10 +80906DCC:prt_8055cd34_f3434af +80906E8C:prt_8055cdf4_f3434af +80906F4C:prt_8055ceb4_f3434af +8090700C:prt_8055cf74_f3434af 80907060:FUN_8055cfc8 +80907240:prt_8055d1a8_8cf8befb +809073D4:prt_8055d33c_f3434af 80907428:FUN_8055d390 809075BC:switchD 809075C0:caseD_14 @@ -9861,10 +10375,23 @@ 809075EC:caseD_11 809075EC:caseD_12 809075EC:caseD_13 +8090768C:prt_8055d5f4_8cf8befb +80907858:prt_8055d7c0_f3434af 8090788C:FUN_8055d7f4 +80907A68:prt_8055d9d0_f3434af +80907B34:prt_8055da9c_8d2134c3 +80907C04:prt_8055db6c_8d2134c3 +80907CA4:prt_8055dc0c_f3434af 80907CE0:FUN_8055dc48 +80907E4C:prt_8055ddb4_8d2134c3 +80907F24:prt_8055de8c_8d2134c3 +8090809C:prt_8055e004_f3434af +80908148:prt_8055e0b0_f3434af 80908184:FUN_8055e0ec 80908204:create_main_menu_sprites +80908600:prt_8055e568_8d2134c3 +809086A8:prt_8055e610_8d2134c3 +80908760:prt_8055e6c8_8d2134c3 809088B0:g_display_game_settings_sprite 80908990:create_practice_mode_stage_select_sprite 80908A50:FUN_8055e9b8 @@ -9922,6 +10449,7 @@ 8090A1E8:caseD_26 8090A1E8:caseD_27 8090A344:sprite_menu_basic_disp +8090B3E0:prt_80561348_3ccf2761 8090BF14:FUN_80561e7c 8090C038:sprite_menu_basic_stack_tick 8090C26C:sprite_menu_basic_title_tick @@ -9931,6 +10459,10 @@ 8090CB68:sprite_game_settings_disp 8090D374:sprite_practice_stage_select_tick 8090D518:sprite_practice_stage_select_disp +8090DBC8:prt_80563b30_3ccf2761 +8090E184:prt_805640ec_3ccf2761 +8090E35C:prt_805642c4_3ccf2761 +8090E52C:prt_80564494_d53b43c0 8090E578:sprite_fight_stage_select_tick 8090E750:sprite_fight_stage_select_disp 8090EAA8:FUN_80564a10 @@ -9963,14 +10495,25 @@ 80912294:FUN_805681fc 80912510:FUN_80568478 80912748:create_fight_stage_preview_sprites +809128C0:prt_80568828_8d2134c3 +80912994:prt_805688fc_8d2134c3 +80912A8C:prt_805689f4_8d2134c3 80912AC4:FUN_80568a2c 80912B24:FUN_80568a8c 80912D1C:FUN_80568c84 +80912D88:prt_80568cf0_f3434af +80912E7C:prt_80568de4_8d2134c3 80912EC0:FUN_80568e28 80912F48:FUN_80568eb0 80912FF8:FUN_80568f60 8091301C:FUN_80568f84 8091304C:sprite_gamedata_disp +80913418:prt_80569380_9f181aee +80913444:prt_805693ac_9f181aee +80913660:prt_805695c8_f8ad41d4 +80913684:prt_805695ec_6523bb0e +809136A8:prt_80569610_6523bb0e +809136CC:prt_80569634_6523bb0e 809137DC:create_gamedata_sprite 80913864:menu_option_game_data_tick_child 809138A8:switchD @@ -9985,10 +10528,15 @@ 809141B8:caseD_8 8091425C:destroy_gamedata_sprite 80914280:FUN_8056a1e8 +80914600:prt_8056a568_9f181aee 809146D0:FUN_8056a638 80914750:FUN_8056a6b8 80914AE0:FUN_8056aa48 80914B04:FUN_8056aa6c +80914F48:prt_8056aeb0_b9bdbf23 +80915738:prt_8056b6a0_b9bdbf23 +809157C8:prt_8056b730_9f181aee +809157FC:prt_8056b764_9f181aee 809158D4:FUN_8056b83c 80915A60:FUN_8056b9c8 80915D38:g_draw_controller_sprites @@ -10003,6 +10551,8 @@ 80917F60:FUN_8056dec8 8091836C:FUN_8056e2d4 809183B4:FUN_8056e31c +809185B0:prt_8056e518_9f181aee +8091865C:prt_8056e5c4_9f181aee 809186E4:FUN_8056e64c 809187A0:FUN_8056e708 809187F0:switchD @@ -10025,6 +10575,8 @@ 80919910:FUN_8056f878 80919DB4:FUN_8056fd1c 80919E28:FUN_8056fd90 +80919ED4:prt_8056fe3c_f3434af +80919F00:prt_8056fe68_8cf8befb 80919F84:FUN_8056feec 8091A4CC:switchD 8091A4D0:caseD_0 @@ -10037,12 +10589,22 @@ 8091A508:caseD_7 8091A510:caseD_8 8091A520:caseD_9 +8091A570:prt_805704d8_501d7b2a +8091A588:prt_805704f0_b9bdbf23 +8091A5C4:prt_8057052c_501d7b2a +8091A5DC:prt_80570544_b9bdbf23 8091AFF8:FUN_80570f60 8091B078:FUN_80570fe0 +8091B20C:prt_80571174_2fa6598f +8091B228:prt_80571190_2fa6598f +8091B2C0:prt_80571228_2fa6598f +8091B474:prt_805713dc_2fa6598f 8091B79C:FUN_80571704 8091B838:FUN_805717a0 8091B85C:FUN_805717c4 8091B968:g_draw_gift_menu +8091C634:prt_8057259c_2fa6598f +8091CA60:prt_805729c8_d53b43c0 8091CDE8:FUN_80572d50 8091D184:FUN_805730ec 8091E59C:switchdataD_80574504 @@ -10160,6 +10722,7 @@ 808F40B0:FUN_8058e5e0 808F40FC:empty_function 808F4100:sel_stage_unlinked_func +808F4154:prt_8058e684_92f7eb37 808F41AC:FUN_8058e6dc 808F4398:g_references_420_03 808F4540:switchD @@ -10176,7 +10739,14 @@ 808F4B4C:caseD_a 808F5120:FUN_8058f650 808F5258:FUN_8058f788 +808F5310:prt_8058f840_f3434af 808F5324:FUN_8058f854 +808F536C:prt_8058f89c_8cf8befb +808F5400:prt_8058f930_9f7dad44 +808F5444:prt_8058f974_e40233a0 +808F5488:prt_8058f9b8_e40233a0 +808F54CC:prt_8058f9fc_e40233a0 +808F54F8:prt_8058fa28_e40233a0 808F550C:FUN_8058fa3c 808F5B20:switchdataD_80590050 808F40B8:bowling_rel_prolog @@ -10451,6 +11021,7 @@ 808F40B8:FUN_805cdee0 808F4108:FUN_805cdf30 808F4128:mini_billiards_unlinked_func +808F417C:prt_805cdfa4_92f7eb37 808F41D4:FUN_805cdffc 808F490C:FUN_805ce734 808F4AA0:FUN_805ce8c8 @@ -10458,6 +11029,8 @@ 808F5D88:FUN_805cfbb0 808F5FEC:FUN_805cfe14 808F6030:FUN_805cfe58 +808F60BC:prt_805cfee4_5924ca76 +808F60DC:prt_805cff04_5924ca76 808F6F58:switchD 808F6F5C:caseD_0 808F6F64:caseD_2 @@ -10591,6 +11164,9 @@ 80905CDC:caseD_12 80905D4C:FUN_805dfb74 80905F68:FUN_805dfd90 +809060F8:prt_805dff20_72bc6a39 +809063A0:prt_805e01c8_d91d26e6 +80906434:prt_805e025c_24b05c0f 8090690C:FUN_805e0734 80906A20:FUN_805e0848 80906A70:FUN_805e0898 @@ -10602,6 +11178,13 @@ 80908A64:FUN_805e288c 80908CB8:FUN_805e2ae0 80909144:FUN_805e2f6c +80909FD4:prt_805e3dfc_5924ca76 +8090A258:prt_805e4080_5924ca76 +8090AC28:prt_805e4a50_96a4d247 +8090AEA0:prt_805e4cc8_b81c78fc +8090B2D4:prt_805e50fc_96a4d247 +8090B834:prt_805e565c_be5daca9 +8090B880:prt_805e56a8_b494f950 8090CEFC:FUN_805e6d24 8090DD08:FUN_805e7b30 8090EA70:FUN_805e8898 @@ -10621,20 +11204,66 @@ 8090F4B8:FUN_805e92e0 809103FC:FUN_805ea224 809107C4:FUN_805ea5ec +80910D04:prt_805eab2c_4da71cc5 80910D38:FUN_805eab60 +80910FEC:prt_805eae14_5924ca76 +80911064:prt_805eae8c_5924ca76 +809110DC:prt_805eaf04_5924ca76 +80911154:prt_805eaf7c_5924ca76 +809111CC:prt_805eaff4_5924ca76 +80911244:prt_805eb06c_5924ca76 +809112BC:prt_805eb0e4_5924ca76 +80911334:prt_805eb15c_5924ca76 +809113AC:prt_805eb1d4_5924ca76 +80911424:prt_805eb24c_5924ca76 +8091149C:prt_805eb2c4_5924ca76 +80911514:prt_805eb33c_5924ca76 +8091158C:prt_805eb3b4_5924ca76 +80911600:prt_805eb428_5924ca76 +80911864:prt_805eb68c_5924ca76 80914AA0:FUN_805ee8c8 80914CC4:FUN_805eeaec 80915288:FUN_805ef0b0 +80915EA8:prt_805efcd0_5924ca76 809185A4:FUN_805f23cc +809187D0:prt_805f25f8_8d2134c3 +8091937C:prt_805f31a4_3ccf2761 +80919444:prt_805f326c_3ccf2761 +80919774:prt_805f359c_e40233a0 +8091992C:prt_805f3754_8d2134c3 +80919ACC:prt_805f38f4_8d2134c3 +80919C54:prt_805f3a7c_8d2134c3 +80919DDC:prt_805f3c04_8d2134c3 +80919FC4:prt_805f3dec_8d2134c3 +8091A23C:prt_805f4064_8d2134c3 +8091A2D0:prt_805f40f8_8d2134c3 +8091A48C:prt_805f42b4_8d2134c3 +8091A850:prt_805f4678_8d2134c3 8091AC84:switchD 8091AC88:caseD_0 +8091AE28:prt_805f4c50_e40233a0 +8091AE88:prt_805f4cb0_891e8130 8091AEAC:caseD_1 +8091B04C:prt_805f4e74_e40233a0 +8091B0AC:prt_805f4ed4_891e8130 8091B0D0:caseD_2 +8091B288:prt_805f50b0_e40233a0 +8091B2E8:prt_805f5110_891e8130 8091B30C:caseD_d +8091B55C:prt_805f5384_8d2134c3 +8091B590:prt_805f53b8_e40233a0 8091B5B4:caseD_6 +8091B708:prt_805f5530_8d2134c3 +8091B764:prt_805f558c_e40233a0 8091B788:caseD_7 +8091B8DC:prt_805f5704_8d2134c3 +8091B938:prt_805f5760_e40233a0 8091B95C:caseD_8 +8091BAB0:prt_805f58d8_8d2134c3 +8091BB0C:prt_805f5934_e40233a0 8091BB30:caseD_f +8091BCB0:prt_805f5ad8_e40233a0 +8091BD38:prt_805f5b60_891e8130 8091BD58:caseD_3 8091BD58:caseD_4 8091BD58:caseD_5 @@ -10643,9 +11272,30 @@ 8091BD58:caseD_b 8091BD58:caseD_c 8091BD58:caseD_e +8091C290:prt_805f60b8_8d2134c3 +8091C3B0:prt_805f61d8_8d2134c3 +8091C4EC:prt_805f6314_8d2134c3 +8091C674:prt_805f649c_8d2134c3 +8091C8CC:prt_805f66f4_8d2134c3 +8091CA90:prt_805f68b8_e40233a0 +8091CC50:prt_805f6a78_8d2134c3 +8091CE10:prt_805f6c38_8d2134c3 +8091CFD4:prt_805f6dfc_e40233a0 +8091D158:prt_805f6f80_8d2134c3 +8091D2DC:prt_805f7104_8d2134c3 +8091D460:prt_805f7288_8d2134c3 +8091D5E4:prt_805f740c_8d2134c3 +8091D7E0:prt_805f7608_8d2134c3 +8091D7FC:prt_805f7624_e40233a0 +8091D818:prt_805f7640_e40233a0 +8091D834:prt_805f765c_e40233a0 +8091D944:prt_805f776c_8d2134c3 +8091D95C:prt_805f7784_8d2134c3 8091DC9C:FUN_805f7ac4 8091DE80:FUN_805f7ca8 8091E32C:FUN_805f8154 +8091E610:prt_805f8438_d53b43c0 +8091E62C:prt_805f8454_d53b43c0 8091E728:FUN_805f8550 8091E744:FUN_805f856c 8091E938:FUN_805f8760 @@ -10675,6 +11325,7 @@ 8092AD38:switchdataD_80604b5c 8092B3EC:switchdataD_80605210 808F40B8:FUN_80663720 +808F4198:prt_80663800_a65c839 808F4450:FUN_80663ab8 808F44C0:FUN_80663b28 808F4540:FUN_80663ba8 @@ -10760,6 +11411,8 @@ 808FE9A0:FUN_8066e008 808FEA40:FUN_8066e0a8 808FEB20:FUN_8066e188 +808FFF54:prt_8066f5bc_66828c07 +80900124:prt_8066f78c_66828c07 80900410:FUN_8066fa78 809004A0:FUN_8066fb08 80900588:FUN_8066fbf0 @@ -10868,9 +11521,11 @@ 80907A30:race2_rel_prolog 80907B28:race2_rel_epilog 80907BA0:race2_rel_unresolved +80907BF4:prt_8067725c_92f7eb37 80907C4C:FUN_806772b4 80907DA8:FUN_80677410 80907E5C:race2_tick +80907F90:prt_806775f8_6d295636 809081C4:FUN_8067782c 80908224:FUN_8067788c 809082A4:FUN_8067790c @@ -10922,6 +11577,8 @@ 8090CD64:FUN_8067c3cc 8090CF5C:FUN_8067c5c4 8090D4D8:FUN_8067cb40 +8090D66C:prt_8067ccd4_f3434af +8090D7F8:prt_8067ce60_f3434af 8090D8A0:FUN_8067cf08 8090DA54:FUN_8067d0bc 8090DB68:FUN_8067d1d0 @@ -10939,53 +11596,88 @@ 8090E594:FUN_8067dbfc 8090E670:g_draw_race_timer_ui 8090E8B0:g_print_race_time_remaining +8090E8F4:prt_8067df5c_8d2134c3 8090E908:FUN_8067df70 8090EB00:FUN_8067e168 +8090EB68:prt_8067e1d0_e40233a0 8090EB7C:FUN_8067e1e4 8090EE04:FUN_8067e46c +8090EE74:prt_8067e4dc_8d2134c3 8090EE88:FUN_8067e4f0 8090EF0C:FUN_8067e574 8090F03C:FUN_8067e6a4 +8090F22C:prt_8067e894_3ccf2761 +8090F394:prt_8067e9fc_f1582bad 8090F3D8:FUN_8067ea40 +8090F528:prt_8067eb90_891e8130 8090F53C:FUN_8067eba4 8090F7A8:FUN_8067ee10 +8090F88C:prt_8067eef4_8d2134c3 8090F8A4:FUN_8067ef0c +8090FA80:prt_8067f0e8_1be26b86 8090FB2C:FUN_8067f194 +8090FC08:prt_8067f270_8d2134c3 8090FC1C:FUN_8067f284 +8090FDC4:prt_8067f42c_8d2134c3 8090FDE0:FUN_8067f448 80910014:FUN_8067f67c 809102B0:FUN_8067f918 +8091052C:prt_8067fb94_8d2134c3 80910548:FUN_8067fbb0 80910B2C:FUN_80680194 +80910BD8:prt_80680240_8d2134c3 80910DEC:FUN_80680454 80910F5C:FUN_806805c4 80911368:FUN_806809d0 +809116F0:prt_80680d58_3ccf2761 +80911780:prt_80680de8_3ccf2761 +80911798:prt_80680e00_3ccf2761 +80911818:prt_80680e80_3ccf2761 +80911840:prt_80680ea8_3ccf2761 +80911874:prt_80680edc_f1582bad 80911AA8:FUN_80681110 +80911E50:prt_806814b8_8d2134c3 +80911FF4:prt_8068165c_891e8130 +809120CC:prt_80681734_8d2134c3 +809120E4:prt_8068174c_8d2134c3 +809121DC:prt_80681844_8d2134c3 +80912208:prt_80681870_8d2134c3 80912244:FUN_806818ac 80912344:FUN_806819ac 8091248C:FUN_80681af4 80912524:FUN_80681b8c 80912648:FUN_80681cb0 809126CC:FUN_80681d34 +80912B78:prt_806821e0_8d2134c3 +80912BA4:prt_8068220c_8d2134c3 80912BC0:FUN_80682228 80912C3C:FUN_806822a4 80912D78:FUN_806823e0 +80912EB0:prt_80682518_891e8130 80912FD0:FUN_80682638 80913058:FUN_806826c0 809130F8:FUN_80682760 8091319C:FUN_80682804 80913254:FUN_806828bc 809134DC:FUN_80682b44 +80913730:prt_80682d98_3ccf2761 +809137BC:prt_80682e24_3ccf2761 +809137D4:prt_80682e3c_3ccf2761 +80913840:prt_80682ea8_3ccf2761 +80913868:prt_80682ed0_3ccf2761 80913894:FUN_80682efc +80913B38:prt_806831a0_8d2134c3 80913B64:FUN_806831cc 80913C28:FUN_80683290 80913D14:FUN_8068337c 80913E58:FUN_806834c0 +80914078:prt_806836e0_8d2134c3 8091409C:FUN_80683704 809143EC:FUN_80683a54 809145D4:FUN_80683c3c 809146AC:FUN_80683d14 80914844:FUN_80683eac +80914D2C:prt_80684394_891e8130 80914D58:FUN_806843c0 80914EF4:FUN_8068455c 809151CC:FUN_80684834 @@ -10998,9 +11690,29 @@ 808F4134:FUN_8068cc64 808F4190:FUN_8068ccc0 808F41BC:golf2_unlinked_func +808F4210:prt_8068cd40_92f7eb37 808F4268:FUN_8068cd98 808F42A8:g_golf_init +808F473C:prt_8068d26c_fc73770a +808F4750:prt_8068d280_fc73770a +808F4764:prt_8068d294_fc73770a 808F49B0:FUN_8068d4e0 +808F4E30:prt_8068d960_37e266fb +808F4E64:prt_8068d994_37e266fb +808F4E98:prt_8068d9c8_37e266fb +808F4EBC:prt_8068d9ec_37e266fb +808F502C:prt_8068db5c_37e266fb +808F5060:prt_8068db90_37e266fb +808F5094:prt_8068dbc4_37e266fb +808F50B8:prt_8068dbe8_37e266fb +808F57DC:prt_8068e30c_37e266fb +808F5810:prt_8068e340_37e266fb +808F5844:prt_8068e374_37e266fb +808F5868:prt_8068e398_37e266fb +808F59F0:prt_8068e520_37e266fb +808F5A24:prt_8068e554_37e266fb +808F5A58:prt_8068e588_37e266fb +808F5A7C:prt_8068e5ac_37e266fb 808F5D74:switchD 808F5D78:caseD_fffffff6 808F5D84:caseD_fffffffd @@ -11029,7 +11741,27 @@ 808F6048:caseD_fffffffa 808F6048:caseD_fffffffb 808F6048:caseD_fffffffc +808F7E44:prt_80690974_72bc6a39 +808F7ECC:prt_806909fc_37e266fb +808FB320:prt_80693e50_fc73770a +808FB49C:prt_80693fcc_fc73770a +808FB4B0:prt_80693fe0_fc73770a +808FC470:prt_80694fa0_37e266fb +808FCBBC:prt_806956ec_37e266fb +808FCBF0:prt_80695720_37e266fb +808FCC24:prt_80695754_37e266fb +808FCC48:prt_80695778_37e266fb 808FD510:FUN_80696040 +808FDAE4:prt_80696614_8d2134c3 +808FDB38:prt_80696668_8d2134c3 +808FDBC8:prt_806966f8_8d2134c3 +808FDC90:prt_806967c0_8d2134c3 +808FDCD8:prt_80696808_8d2134c3 +808FDD40:prt_80696870_8d2134c3 +808FDDC0:prt_806968f0_8d2134c3 +808FDE08:prt_80696938_8d2134c3 +808FDE70:prt_806969a0_8d2134c3 +808FDEDC:prt_80696a0c_8d2134c3 808FE48C:switchD 808FE490:caseD_0 808FE4AC:caseD_1 @@ -11086,8 +11818,19 @@ 808FECF0:caseD_c 809006D8:FUN_80699208 809019FC:FUN_8069a52c +80901DFC:prt_8069a92c_37e266fb +80901E30:prt_8069a960_37e266fb +80901E64:prt_8069a994_37e266fb +80901E88:prt_8069a9b8_37e266fb +80902024:prt_8069ab54_37e266fb 80902214:FUN_8069ad44 +809022EC:prt_8069ae1c_fc73770a +80902300:prt_8069ae30_fc73770a +80902314:prt_8069ae44_fc73770a 80902354:FUN_8069ae84 +809023E8:prt_8069af18_fc73770a +809023FC:prt_8069af2c_fc73770a +80902410:prt_8069af40_fc73770a 8090265C:FUN_8069b18c 80902828:FUN_8069b358 80902A58:FUN_8069b588 @@ -11150,6 +11893,7 @@ 8090B298:FUN_806a3dc8 8090B328:switchD 8090B32C:caseD_0 +8090B334:prt_806a3e64_1ff94186 8090B33C:caseD_1 8090B34C:caseD_2 8090B35C:caseD_3 @@ -11186,6 +11930,7 @@ 8090C7D0:FUN_806a5300 8090CE28:FUN_806a5958 8090D0B4:FUN_806a5be4 +8090D9B0:prt_806a64e0_493d5350 8090DD60:FUN_806a6890 8090DFD4:FUN_806a6b04 8090E6C0:FUN_806a71f0 @@ -11219,14 +11964,25 @@ 80911C40:FUN_806aa770 809120B4:FUN_806aabe4 809121B4:FUN_806aace4 +8091253C:prt_806ab06c_8d2134c3 80912570:FUN_806ab0a0 80912844:FUN_806ab374 +80912CC0:prt_806ab7f0_8d2134c3 +80912CD8:prt_806ab808_8d2134c3 +80912D0C:prt_806ab83c_8d2134c3 +80912D24:prt_806ab854_8d2134c3 80912D4C:FUN_806ab87c +8091382C:prt_806ac35c_8d2134c3 +80913878:prt_806ac3a8_8d2134c3 809138AC:FUN_806ac3dc 80913B2C:FUN_806ac65c 80913DD0:FUN_806ac900 80914908:FUN_806ad438 80919358:FUN_806b1e88 +8091DCF4:prt_806b6824_8d2134c3 +8091DD50:prt_806b6880_8d2134c3 +80921BC4:prt_806ba6f4_8d2134c3 +80921C20:prt_806ba750_8d2134c3 80921C70:FUN_806ba7a0 80921DF4:FUN_806ba924 80921F14:FUN_806baa44 @@ -11358,6 +12114,7 @@ 808F40B0:FUN_806ce3c0 808F4110:FUN_806ce420 808F4150:mini_fight2_unlinked_func +808F41A4:prt_806ce4b4_92f7eb37 808F41FC:FUN_806ce50c 808F423C:FUN_806ce54c 808F4270:FUN_806ce580 @@ -11633,7 +12390,9 @@ 8091A1DC:FUN_806f44ec 8091A6BC:FUN_806f49cc 8091A848:FUN_806f4b58 +8091A9FC:prt_806f4d0c_8d2134c3 8091ABB4:FUN_806f4ec4 +8091AC44:prt_806f4f54_8d2134c3 8091AD74:FUN_806f5084 8091AFE0:FUN_806f52f0 8091B218:FUN_806f5528 @@ -11648,6 +12407,8 @@ 8091C690:FUN_806f69a0 8091CB1C:FUN_806f6e2c 8091CD90:FUN_806f70a0 +8091CE20:prt_806f7130_3ccf2761 +8091CEBC:prt_806f71cc_3ccf2761 8091CEE0:FUN_806f71f0 8091D2E8:FUN_806f75f8 8091D360:FUN_806f7670 @@ -11683,6 +12444,7 @@ 808F40B0:FUN_80727360 808F4100:FUN_807273b0 808F412C:pilot2_unlinked_func +808F4180:prt_80727430_92f7eb37 808F41D8:FUN_80727488 808F4340:FUN_807275f0 808F43B4:FUN_80727664 @@ -11701,6 +12463,9 @@ 808F4674:caseD_7 808F4778:FUN_80727a28 808F47FC:FUN_80727aac +808F486C:prt_80727b1c_5924ca76 +808F4884:prt_80727b34_5924ca76 +808F48B0:prt_80727b60_5924ca76 808F49E0:FUN_80727c90 808F4C98:FUN_80727f48 808F5338:FUN_807285e8 @@ -11798,17 +12563,28 @@ 808FF224:FUN_807324d4 808FF278:FUN_80732528 808FF370:FUN_80732620 +808FF594:prt_80732844_3ccf2761 808FF6F0:FUN_807329a0 +808FFAE4:prt_80732d94_3ccf2761 +808FFC88:prt_80732f38_28f463b0 808FFCD8:FUN_80732f88 +808FFF5C:prt_8073320c_3ccf2761 +808FFFC4:prt_80733274_3ccf2761 8090000C:FUN_807332bc 809003A4:FUN_80733654 80900520:FUN_807337d0 809005C0:FUN_80733870 +80900A08:prt_80733cb8_3ccf2761 80900AC0:FUN_80733d70 +80900C90:prt_80733f40_3ccf2761 +80900CB8:prt_80733f68_3ccf2761 80900D20:FUN_80733fd0 80900DA4:FUN_80734054 80901100:FUN_807343b0 +8090128C:prt_8073453c_3ccf2761 809012D8:FUN_80734588 +809013C0:prt_80734670_3ccf2761 +80901480:prt_80734730_3ccf2761 809014B8:FUN_80734768 809016FC:FUN_807349ac 809017C8:FUN_80734a78 @@ -11816,6 +12592,7 @@ 80901C04:FUN_80734eb4 80901D50:FUN_80735000 80901D84:FUN_80735034 +80902224:prt_807354d4_3ccf2761 80902264:FUN_80735514 809023F4:FUN_807356a4 8090252C:FUN_807357dc @@ -11890,8 +12667,10 @@ 808F40BC:FUN_8073ef24 808F4100:FUN_8073ef68 808F4144:boat_unlinked_func +808F4198:prt_8073f000_92f7eb37 808F41F0:FUN_8073f058 808F472C:FUN_8073f594 +808F489C:prt_8073f704_40b12258 808F4B88:FUN_8073f9f0 808F4BA8:FUN_8073fa10 808F4C80:FUN_8073fae8 @@ -11920,6 +12699,8 @@ 808F73B4:FUN_8074221c 808F74A0:FUN_80742308 808F74D0:FUN_80742338 +808F8094:prt_80742efc_66828c07 +808F810C:prt_80742f74_5a79192f 808F8754:FUN_807435bc 808F87D0:FUN_80743638 808F88C0:FUN_80743728 @@ -11936,7 +12717,9 @@ 808F9B98:FUN_80744a00 808F9CB0:FUN_80744b18 808F9EC8:FUN_80744d30 +808F9F94:prt_80744dfc_5a79192f 808F9FD0:FUN_80744e38 +808FA0A0:prt_80744f08_5a79192f 808FA0DC:FUN_80744f44 808FA114:FUN_80744f7c 808FA1F4:FUN_8074505c @@ -11945,9 +12728,13 @@ 808FA4E4:FUN_8074534c 808FA69C:FUN_80745504 808FA794:FUN_807455fc +808FB898:prt_80746700_37e266fb +808FB8B0:prt_80746718_a65c839 +808FB8C8:prt_80746730_a65c839 808FB954:FUN_807467bc 808FB960:FUN_807467c8 808FB9A8:FUN_80746810 +808FBBF4:prt_80746a5c_a65c839 808FBC08:FUN_80746a70 808FC374:FUN_807471dc 808FC820:FUN_80747688 @@ -12038,6 +12825,8 @@ 80906BDC:FUN_80751a44 80906CAC:FUN_80751b14 80906D34:FUN_80751b9c +80906DD0:prt_80751c38_8d2134c3 +80906E10:prt_80751c78_8d2134c3 80906FF4:FUN_80751e5c 809071FC:FUN_80752064 8090778C:FUN_807525f4 @@ -12099,6 +12888,8 @@ 8090D3C4:FUN_8075822c 8090D5D8:FUN_80758440 8090D6D0:FUN_80758538 +8090D854:prt_807586bc_f3434af +8090DA14:prt_8075887c_f3434af 8090DACC:FUN_80758934 8090DC80:FUN_80758ae8 8090DD94:FUN_80758bfc @@ -12106,21 +12897,28 @@ 8090E000:FUN_80758e68 8090E19C:FUN_80759004 8090E274:FUN_807590dc +8090E650:prt_807594b8_891e8130 8090E680:FUN_807594e8 8090E71C:FUN_80759584 8090E7A4:FUN_8075960c 8090E9D0:FUN_80759838 8090EC70:FUN_80759ad8 +8090ECB0:prt_80759b18_8d2134c3 8090ECC4:FUN_80759b2c 8090EDCC:FUN_80759c34 8090EEB0:FUN_80759d18 8090EF88:FUN_80759df0 8090F184:FUN_80759fec +8090F1C8:prt_8075a030_e40233a0 8090F1DC:FUN_8075a044 +8090F3B8:prt_8075a220_1be26b86 +8090F438:prt_8075a2a0_8d2134c3 8090F464:FUN_8075a2cc +8090F534:prt_8075a39c_8d2134c3 8090F548:FUN_8075a3b0 8090F608:FUN_8075a470 8090F874:FUN_8075a6dc +8090F964:prt_8075a7cc_8d2134c3 8090F97C:FUN_8075a7e4 8090FDB8:FUN_8075ac20 8090FFB8:FUN_8075ae20 @@ -12128,33 +12926,57 @@ 80910688:FUN_8075b4f0 809108DC:FUN_8075b744 80910A14:FUN_8075b87c +80910BD8:prt_8075ba40_3ccf2761 +80910C28:prt_8075ba90_f1582bad 80910C74:FUN_8075badc 80910EFC:FUN_8075bd64 +80910F64:prt_8075bdcc_8d2134c3 80910F78:FUN_8075bde0 +80910FC8:prt_8075be30_891e8130 80910FDC:FUN_8075be44 80911248:FUN_8075c0b0 80911438:FUN_8075c2a0 8091146C:FUN_8075c2d4 80911754:FUN_8075c5bc 809118A4:FUN_8075c70c +80911D74:prt_8075cbdc_8d2134c3 +80911D8C:prt_8075cbf4_8d2134c3 80911DB4:FUN_8075cc1c 80911E4C:FUN_8075ccb4 80912080:FUN_8075cee8 +80912434:prt_8075d29c_e40233a0 80912460:FUN_8075d2c8 8091252C:FUN_8075d394 +8091276C:prt_8075d5d4_8d2134c3 +80912784:prt_8075d5ec_8d2134c3 +80912870:prt_8075d6d8_8d2134c3 +80912888:prt_8075d6f0_8d2134c3 8091290C:FUN_8075d774 80912B98:FUN_8075da00 80912C3C:FUN_8075daa4 80912CD4:FUN_8075db3c 80912E78:FUN_8075dce0 809130D0:FUN_8075df38 +809132E8:prt_8075e150_3ccf2761 +80913380:prt_8075e1e8_3ccf2761 +80913398:prt_8075e200_3ccf2761 +809133E0:prt_8075e248_3ccf2761 +809133F4:prt_8075e25c_3ccf2761 80913410:FUN_8075e278 809135B4:FUN_8075e41c 80913704:FUN_8075e56c 80913874:FUN_8075e6dc +80913B1C:prt_8075e984_3ccf2761 +80913BAC:prt_8075ea14_3ccf2761 +80913BC4:prt_8075ea2c_3ccf2761 +80913C24:prt_8075ea8c_3ccf2761 +80913C38:prt_8075eaa0_3ccf2761 +80913C6C:prt_8075ead4_f1582bad 80913CE4:FUN_8075eb4c +80914020:prt_8075ee88_891e8130 809140CC:FUN_8075ef34 809141DC:FUN_8075f044 +80914430:prt_8075f298_8d2134c3 80914454:FUN_8075f2bc 8091499C:FUN_8075f804 80914BD4:FUN_8075fa3c @@ -12198,9 +13020,11 @@ 808F40B0:FUN_80772d60 808F4130:FUN_80772de0 808F4174:shooting_unlinked_func +808F41C8:prt_80772e78_92f7eb37 808F4220:FUN_80772ed0 808F4A5C:FUN_8077370c 808F4AAC:FUN_8077375c +808F5244:prt_80773ef4_4922f787 808F528C:FUN_80773f3c 808F5328:FUN_80773fd8 808F5424:FUN_807740d4 @@ -12213,6 +13037,8 @@ 808F6A2C:FUN_807756dc 808F6DBC:FUN_80775a6c 808F71B4:FUN_80775e64 +808F737C:prt_8077602c_812cd95f +808F73A8:prt_80776058_812cd95f 808F7658:FUN_80776308 808F7844:FUN_807764f4 808F7B7C:FUN_8077682c @@ -12244,8 +13070,17 @@ 808FB934:FUN_8077a5e4 808FBEB0:FUN_8077ab60 808FC2F8:FUN_8077afa8 +808FC504:prt_8077b1b4_9f181aee +808FC5B4:prt_8077b264_3ccf2761 +808FC670:prt_8077b320_3ccf2761 +808FC804:prt_8077b4b4_3ccf2761 +808FC914:prt_8077b5c4_3ccf2761 +808FCA04:prt_8077b6b4_3ccf2761 +808FCAF4:prt_8077b7a4_3ccf2761 +808FCC88:prt_8077b938_3ccf2761 808FCCB4:FUN_8077b964 808FDFBC:FUN_8077cc6c +808FE410:prt_8077d0c0_28f463b0 808FE450:FUN_8077d100 808FE7C0:FUN_8077d470 808FEAC8:FUN_8077d778 @@ -12293,6 +13128,8 @@ 80902D60:FUN_80781a10 80903004:FUN_80781cb4 80903384:FUN_80782034 +80903404:prt_807820b4_b81c78fc +80903438:prt_807820e8_482af33c 80903494:FUN_80782144 8090352C:FUN_807821dc 8090358C:FUN_8078223c @@ -12312,15 +13149,20 @@ 809051C0:FUN_80783e70 80905264:FUN_80783f14 80905308:FUN_80783fb8 +80905380:prt_80784030_b81c78fc +809053B4:prt_80784064_482af33c 80905428:FUN_807840d8 80906000:FUN_80784cb0 809066FC:FUN_807853ac 80906D18:FUN_807859c8 80906DB4:FUN_80785a64 80907408:FUN_807860b8 +80907A8C:prt_8078673c_37e266fb 80907BA0:FUN_80786850 80907C74:FUN_80786924 80907CD8:FUN_80786988 +80907D40:prt_807869f0_5924ca76 +80907D6C:prt_80786a1c_5a79192f 80907E0C:FUN_80786abc 8090810C:FUN_80786dbc 809084C4:FUN_80787174 @@ -12445,6 +13287,7 @@ 80918EF4:FUN_80797ba4 80918F28:FUN_80797bd8 80918F58:FUN_80797c08 +80919174:prt_80797e24_37e266fb 809191EC:switchD 809191F0:caseD_0 80919220:caseD_1 @@ -12684,8 +13527,10 @@ 80926E9C:FUN_807a5b4c 80927048:FUN_807a5cf8 80927204:FUN_807a5eb4 +80927260:prt_807a5f10_37e266fb 80927290:FUN_807a5f40 809272AC:FUN_807a5f5c +809272D0:prt_807a5f80_37e266fb 80927300:FUN_807a5fb0 809273C4:FUN_807a6074 8092740C:FUN_807a60bc @@ -13076,6 +13921,7 @@ 808F40B0:FUN_808333a0 808F4108:FUN_808333f8 808F4128:mini_futsal_unlinked_func +808F417C:prt_8083346c_92f7eb37 808F41D4:FUN_808334c4 808F4800:g_load_bg_ape 808F48B0:FUN_80833ba0 @@ -13095,6 +13941,7 @@ 808F6F4C:FUN_8083623c 808F7218:FUN_80836508 808F7570:FUN_80836860 +808F7AD0:prt_80836dc0_b5fa0de7 808F7BE0:switchD 808F7BE4:caseD_0 808F7BEC:caseD_1 @@ -13163,6 +14010,8 @@ 809032A8:FUN_80842598 809035E0:FUN_808428d0 80904074:FUN_80843364 +80904364:prt_80843654_482af33c +80904444:prt_80843734_482af33c 80904468:switchD 8090446C:caseD_0 80904478:caseD_1 @@ -13223,6 +14072,9 @@ 8090877C:FUN_80847a6c 80908ABC:FUN_80847dac 80908B00:FUN_80847df0 +80908FA0:prt_80848290_522b5a22 +80908FDC:prt_808482cc_888aa7a9 +80909000:prt_808482f0_37e266fb 80909024:FUN_80848314 80909294:FUN_80848584 80909850:FUN_80848b40 @@ -13250,13 +14102,25 @@ 8090D828:FUN_8084cb18 8090DA68:FUN_8084cd58 8090DB3C:FUN_8084ce2c +8090DC4C:prt_8084cf3c_66828c07 8090DCC0:FUN_8084cfb0 8090DEE0:FUN_8084d1d0 8090E0AC:FUN_8084d39c 8090E438:FUN_8084d728 +8090F090:prt_8084e380_5924ca76 +8090F0A4:prt_8084e394_5924ca76 +8090F234:prt_8084e524_5924ca76 +8090F3B4:prt_8084e6a4_5924ca76 +8090F5E0:prt_8084e8d0_5924ca76 +8090F6B4:prt_8084e9a4_4dcfdee9 +8090F964:prt_8084ec54_f8ad41d4 +8090FECC:prt_8084f1bc_cee7fd32 80911508:FUN_808507f8 809118CC:FUN_80850bbc 80911C44:FUN_80850f34 +8091213C:prt_8085142c_3ccf2761 +80912194:prt_80851484_3ccf2761 +80912278:prt_80851568_3ccf2761 809128C0:FUN_80851bb0 80912990:FUN_80851c80 80912BAC:FUN_80851e9c @@ -13306,7 +14170,7 @@ 8091A168:FUN_80859458 8091A210:FUN_80859500 8091A47C:FUN_8085976c -8091A524:load_bg_ape +8091A524:FUN_80859814 8091A774:FUN_80859a64 8091AA88:FUN_80859d78 8091AC28:FUN_80859f18 @@ -13377,6 +14241,7 @@ 808F40B0:FUN_808c50a0 808F4118:FUN_808c5108 808F4158:dogfight_unlinked_func +808F41AC:prt_808c519c_92f7eb37 808F4204:FUN_808c51f4 808F4528:FUN_808c5518 808F45C8:FUN_808c55b8 @@ -13387,6 +14252,7 @@ 808F4950:FUN_808c5940 808F4BD8:FUN_808c5bc8 808F4C6C:FUN_808c5c5c +808F4D44:prt_808c5d34_5924ca76 808F4FCC:FUN_808c5fbc 808F53DC:FUN_808c63cc 808F55E0:FUN_808c65d0 @@ -13467,13 +14333,22 @@ 808FEC74:FUN_808cfc64 808FEE64:FUN_808cfe54 808FF1EC:FUN_808d01dc +808FF550:prt_808d0540_3ccf2761 808FF930:FUN_808d0920 +808FFB70:prt_808d0b60_3ccf2761 808FFD74:FUN_808d0d64 808FFEB8:FUN_808d0ea8 +8090015C:prt_808d114c_3ccf2761 809001E8:FUN_808d11d8 +80900374:prt_808d1364_3ccf2761 809003B4:FUN_808d13a4 80900440:FUN_808d1430 +80900A00:prt_808d19f0_3ccf2761 +80900A20:prt_808d1a10_3ccf2761 +80900A54:prt_808d1a44_3ccf2761 80900AD0:FUN_808d1ac0 +80900CF8:prt_808d1ce8_3ccf2761 +80900D20:prt_808d1d10_3ccf2761 80900DF0:FUN_808d1de0 80900F10:FUN_808d1f00 809014A8:FUN_808d2498 @@ -13486,6 +14361,7 @@ 80901DE0:FUN_808d2dd0 80901E30:FUN_808d2e20 80901F84:FUN_808d2f74 +8090236C:prt_808d335c_3ccf2761 809023BC:FUN_808d33ac 809024C8:FUN_808d34b8 809025B0:FUN_808d35a0 @@ -13493,6 +14369,7 @@ 80902828:FUN_808d3818 80902AAC:FUN_808d3a9c 80902B80:FUN_808d3b70 +80902BF4:prt_808d3be4_8d2134c3 80902DF8:FUN_808d3de8 80902F04:FUN_808d3ef4 80902F90:FUN_808d3f80 @@ -13590,7 +14467,13 @@ 808E8390:g_baseball_prolog 808E83E8:FUN_808f0eb8 808E8414:baseball_unlinked_func +808E8468:prt_808f0f38_92f7eb37 808E84C0:FUN_808f0f90 +808E84F4:prt_808f0fc4_cc17ecd5 +808E8514:prt_808f0fe4_cc17ecd5 +808E8534:prt_808f1004_cc17ecd5 +808E8554:prt_808f1024_cc17ecd5 +808E8574:prt_808f1044_cc17ecd5 808E858C:FUN_808f105c 808E85EC:FUN_808f10bc 808E8600:empty_function @@ -13606,6 +14489,10 @@ 808E872C:FUN_808f11fc 808E874C:empty_function 808E8750:FUN_808f1220 +808E879C:prt_808f126c_e721d485 +808E87C8:prt_808f1298_e721d485 +808E87F4:prt_808f12c4_e721d485 +808E8820:prt_808f12f0_e721d485 808E8838:FUN_808f1308 808E8860:FUN_808f1330 808E8888:g_baseball_game_loop @@ -13666,6 +14553,12 @@ 808E9F20:FUN_808f29f0 808EA2D0:FUN_808f2da0 808EA340:FUN_808f2e10 +808EA378:prt_808f2e48_37e266fb +808EA38C:prt_808f2e5c_37e266fb +808EA3A0:prt_808f2e70_37e266fb +808EA3B4:prt_808f2e84_37e266fb +808EA3C8:prt_808f2e98_37e266fb +808EA3DC:prt_808f2eac_37e266fb 808EA844:FUN_808f3314 808EA894:FUN_808f3364 808EA9DC:FUN_808f34ac @@ -13924,6 +14817,12 @@ 808F8C48:FUN_80901718 808F8DAC:FUN_8090187c 808F8F94:FUN_80901a64 +808F9254:prt_80901d24_66828c07 +808F9270:prt_80901d40_66828c07 +808F928C:prt_80901d5c_66828c07 +808F92CC:prt_80901d9c_66828c07 +808F930C:prt_80901ddc_66828c07 +808F934C:prt_80901e1c_66828c07 808F9378:FUN_80901e48 808F9424:FUN_80901ef4 808F9520:FUN_80901ff0 @@ -14001,6 +14900,7 @@ 808FCDB0:FUN_80905880 808FCDDC:FUN_809058ac 808FCE28:cPlayer::PostPhysicsUpdate(void) +808FCE70:prt_80905940_37e266fb 808FCE84:FUN_80905954 808FCF40:FUN_80905a10 808FD008:FUN_80905ad8 @@ -14248,10 +15148,15 @@ 80909DC4:FUN_80912894 80909DF8:FUN_809128c8 80909E38:FUN_80912908 +80909E88:prt_80912958_f3434af 80909EDC:FUN_809129ac 80909F48:FUN_80912a18 80909F74:FUN_80912a44 8090A1FC:FUN_80912ccc +8090A250:prt_80912d20_f3434af +8090A318:prt_80912de8_f3434af +8090A3E0:prt_80912eb0_f3434af +8090A4A8:prt_80912f78_f3434af 8090A60C:FUN_809130dc 8090A6CC:FUN_8091319c 8090A72C:FUN_809131fc @@ -14274,6 +15179,7 @@ 8090BF58:FUN_80914a28 8090C4F4:FUN_80914fc4 8090CC2C:FUN_809156fc +8090CF54:prt_80915a24_95990a7d 8090D518:FUN_80915fe8 8090D53C:FUN_8091600c 8090D628:FUN_809160f8 @@ -14834,6 +15740,9 @@ 8090D560:FUN_809df008 8090D58C:FUN_809df034 8090D814:FUN_809df2bc +8090D930:prt_809df3d8_c32105f2 +8090D9F8:prt_809df4a0_c32105f2 +8090DAC0:prt_809df568_c32105f2 8090DC24:FUN_809df6cc 8090DCE4:FUN_809df78c 8090DE80:FUN_809df928 @@ -14872,7 +15781,9 @@ 808F40B0:exoption_prolog 808F4104:exoption_epilog 808F4150:exoption_unlinked_func +808F41A4:prt_809ee6b4_92f7eb37 808F41FC:FUN_809ee70c +808F4248:prt_809ee758_37e266fb 808F428C:FUN_809ee79c 808F4340:FUN_809ee850 808F437C:switchD @@ -14890,11 +15801,19 @@ 808F543C:exoption_draw_func 808F545C:create_replay_hud_sprites 808F54C8:create_replay_stage_name_sprites +808F58B8:prt_809efdc8_e40233a0 +808F58D0:prt_809efde0_8d2134c3 +808F5980:prt_809efe90_e40233a0 +808F5998:prt_809efea8_8d2134c3 +808F5A84:prt_809eff94_f3434af +808F5B38:prt_809f0048_f3434af 808F5B78:FUN_809f0088 808F5CA4:FUN_809f01b4 808F6244:FUN_809f0754 808F62C8:FUN_809f07d8 +808F633C:prt_809f084c_8d2134c3 808F64E8:FUN_809f09f8 +808F6590:prt_809f0aa0_33cfa187 808F6754:FUN_809f0c64 808F68B8:FUN_809f0dc8 808F6AA0:FUN_809f0fb0 diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index 336de21f..7541dc68 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -42,23 +42,23 @@ struct SeesawState { static_assert(sizeof(SeesawState) == 0x78); enum { /* The character associated with an Ape */ - APE_AIAI=0, - APE_MEEMEE=1, - APE_BABY=2, - APE_GONGON=3, - APE_MADH=4, - APE_KOBUN=5, - APE_MALE=6, - APE_FEMALE=7, - APE_JIJI=8, - APE_BABA=9, - APE_MADSPA=10, - APE_MADFRG=11, - APE_MADNKD=12, - APE_ROB=13, - APE_WHALE=14, - APE_MADCRS=15, - APE_KOBSPA=16 + CHARA_AIAI=0, + CHARA_MEEMEE=1, + CHARA_BABY=2, + CHARA_GONGON=3, + CHARA_MADH=4, + CHARA_KOBUN=5, + CHARA_MALE=6, + CHARA_FEMALE=7, + CHARA_JIJI=8, + CHARA_BABA=9, + CHARA_MADSPA=10, + CHARA_MADFRG=11, + CHARA_MADNKD=12, + CHARA_ROB=13, + CHARA_WHALE=14, + CHARA_MADCRS=15, + CHARA_KOBSPA=16 }; typedef undefined4 ApeCharacter; @@ -859,61 +859,65 @@ typedef struct SomeApeState SomeApeState, *PSomeApeState; typedef struct Mal Mal, *PMal; -typedef struct SKLRoot SKLRoot, *PSKLRoot; +typedef struct ApeArchive ApeArchive, *PApeArchive; -typedef struct ArcFileInfo ArcFileInfo, *PArcFileInfo; - -typedef struct SKLFile SKLFile, *PSKLFile; +typedef struct Component Component, *PComponent; -typedef struct GApeAnim GApeAnim, *PGApeAnim; +typedef struct GComponentDefList GComponentDefList, *PGComponentDefList; typedef struct GmaBuffer GmaBuffer, *PGmaBuffer; enum { - GAME_COMMON=0, - GAME_MAIN=1, - GAME_DUMMY1=2, - GAME_DUMMY2=3, - GAME_DUMMY3=4, - GAME_DUMMY4=5, - GAME_DUMMY5=6, - GAME_DUMMY6=7, - GAME_DUMMY7=8, - GAME_DUMMY8=9, - GAME_DUMMY9=10, - GAME_DUMMY10=11, - GAME_RACE=12, - GAME_FGT=13, - GAME_PILOT=14, - GAME_GOLF=15, - GAME_BOWL=16, - GAME_BILL=17, - GAME_BOAT=18, - GAME_DOGF=19, - GAME_TENNIS=20, - GAME_BBALL=21, - GAME_GUNS=22, - GAME_ADV=23, - GAME_SEL=24, - GAME_COMMEND=25, - GAME_SCENE1A=26, - GAME_SCENE1B=27, - GAME_SCENE2=28, - GAME_SCENE3=29, - GAME_SCENE4=30, - GAME_SCENE5=31, - GAME_SCENE6=32, - GAME_SCENE7=33, - GAME_SCENE8=34, - GAME_SCENE9=35, - GAME_SCENE10=36, - GAME_LASTSCENE=37, - GAME_ENDING1=38, - GAME_ENDING2=39, - GAME_ENDING3=40, - GAME_ENDING4=41 -}; -typedef undefined2 ApeGame; + SCENE16_COMMON=0, + SCENE16_MAIN=1, + SCENE16_DUMMY1=2, + SCENE16_DUMMY2=3, + SCENE16_DUMMY3=4, + SCENE16_DUMMY4=5, + SCENE16_DUMMY5=6, + SCENE16_DUMMY6=7, + SCENE16_DUMMY7=8, + SCENE16_DUMMY8=9, + SCENE16_DUMMY9=10, + SCENE16_DUMMY10=11, + SCENE16_RACE=12, + SCENE16_FGT=13, + SCENE16_PILOT=14, + SCENE16_GOLF=15, + SCENE16_BOWL=16, + SCENE16_BILL=17, + SCENE16_BOAT=18, + SCENE16_DOGF=19, + SCENE16_TENNIS=20, + SCENE16_BBALL=21, + SCENE16_GUNS=22, + SCENE16_ADV=23, + SCENE16_SEL=24, + SCENE16_COMMEND=25, + SCENE16_SCENE1A=26, + SCENE16_SCENE1B=27, + SCENE16_SCENE2=28, + SCENE16_SCENE3=29, + SCENE16_SCENE4=30, + SCENE16_SCENE5=31, + SCENE16_SCENE6=32, + SCENE16_SCENE7=33, + SCENE16_SCENE8=34, + SCENE16_SCENE9=35, + SCENE16_SCENE10=36, + SCENE16_LASTSCENE=37, + SCENE16_ENDING1=38, + SCENE16_ENDING2=39, + SCENE16_ENDING3=40, + SCENE16_ENDING4=41 +}; +typedef undefined2 SceneId16; + +enum { /* Whether ape models are skinning or stitching? */ + DEFORM_SKINNING=0, + DEFORM_STITCHING=1 +}; +typedef undefined1 DeformType8; enum { FACE_BASE=0, @@ -939,53 +943,23 @@ enum { }; typedef undefined4 ApeLOD; -typedef struct SKLInfo SKLInfo, *PSKLInfo; - -typedef struct gFloats gFloats, *PgFloats; +typedef struct ArcFileInfo ArcFileInfo, *PArcFileInfo; -typedef struct ARCHandle ARCHandle, *PARCHandle; +typedef struct SkeletonState SkeletonState, *PSkeletonState; -typedef struct SKLBone SKLBone, *PSKLBone; +typedef struct SkeletonDef SkeletonDef, *PSkeletonDef; -typedef struct g_thing g_thing, *Pg_thing; +typedef struct GComponentDef GComponentDef, *PGComponentDef; typedef struct GmaModelEntry GmaModelEntry, *PGmaModelEntry; -struct Quat { - f32 x; - f32 y; - f32 z; - f32 w; -} __attribute__((__packed__)); -static_assert(sizeof(Quat) == 0x10); +typedef struct ARCHandle ARCHandle, *PARCHandle; -struct gFloats { - short field0_0x0; - short field1_0x2; - short field2_0x4; - short field3_0x6; - struct Vec vec3; -} __attribute__((__packed__)); -static_assert(sizeof(gFloats) == 0x14); +typedef struct BoneState BoneState, *PBoneState; -struct SKLRoot { - ushort bone_count; - ushort g_flag; /* Created by retype action */ - float g_some_float; - struct SKLInfo * bones; - struct Quat rotation1; - struct Quat rotation2; - char * g_bone_name; - struct Vec translation; - undefined field_0x3c[0x4]; - struct gFloats float_thing1; - undefined field_0x54[0x4]; - struct gFloats float_thing2; - undefined field_0x6c[0x4]; - struct SKLInfo * gBoneData; - undefined field_0x74[0x100]; -} __attribute__((__packed__)); -static_assert(sizeof(SKLRoot) == 0x174); +typedef struct GSkeletonStateSubA GSkeletonStateSubA, *PGSkeletonStateSubA; + +typedef struct BoneKeyframe BoneKeyframe, *PBoneKeyframe; struct SomeApeState { u8 g_chara_idx; @@ -1002,21 +976,11 @@ struct SomeApeState { } __attribute__((__packed__)); static_assert(sizeof(SomeApeState) == 0x60); -struct SKLBone { - short parentNumber; - short g_maybe_flag; - struct Quat Rotation1; - struct Quat Rotation2; - struct Vec Translation; +struct ApeArchive { /* Extremely simple archive format used for packing Ape skeleton/animation files into a single file. List of pointers/offsets to objects immediately follows/ */ + u32 count; /* Number of objects in the archive (e.g. skeletons for .ska) */ + char * name_table; /* Pointer/offset to packed object name string list */ } __attribute__((__packed__)); -static_assert(sizeof(SKLBone) == 0x30); - -struct SKLFile { - short bone_count; - undefined2 padding; - struct SKLBone bone_section; -} __attribute__((__packed__)); -static_assert(sizeof(SKLFile) == 0x34); +static_assert(sizeof(ApeArchive) == 0x8); struct ArcFileInfo { struct ARCHandle * Handle; @@ -1025,12 +989,11 @@ struct ArcFileInfo { } __attribute__((__packed__)); static_assert(sizeof(ArcFileInfo) == 0xc); -struct g_thing { - undefined field_0x0[0x8]; - char * Name; - undefined field_0xc[0x1c]; +struct GComponentDefList { + struct GComponentDef * list; + u32 count; } __attribute__((__packed__)); -static_assert(sizeof(g_thing) == 0x28); +static_assert(sizeof(GComponentDefList) == 0x8); struct GmaBuffer { /* Represents the first 32 bytes of buffer allocated for loaded GMA files. The first 32 bytes are extra; not part of the original GMA file */ s32 model_count; @@ -1042,24 +1005,61 @@ struct GmaBuffer { /* Represents the first 32 bytes of buffer allocated for load } __attribute__((__packed__)); static_assert(sizeof(GmaBuffer) == 0x20); -struct SKLInfo { - char * bone_name; - short g_flag; - short parentNumber; - struct Vec vec3f1; - float vec3f1_len; /* Created by retype action */ - struct Vec vec3f1copy; - float g_float; - Mtx g_mtx1; - undefined1 g_mtx2; /* Created by retype action */ - undefined field_0x59[0x2f]; - Mtx matrix; /* Created by retype action */ - struct Vec vec3f3; /* Created by retype action */ - undefined field_0xc4[0xc]; - float g_float2; - undefined field_0xd4[0xa0]; +struct BoneKeyframe { + undefined field_0x0[0x8]; +} __attribute__((__packed__)); +static_assert(sizeof(BoneKeyframe) == 0x8); + +struct GSkeletonStateSubA { + short field0_0x0; + short field1_0x2; + short g_anim_duration; + short field3_0x6; + undefined field_0x8[0x4]; + float field8_0xc; + float field9_0x10; + short field10_0x14; + undefined field_0x16[0x2]; +} __attribute__((__packed__)); +static_assert(sizeof(GSkeletonStateSubA) == 0x18); + +struct SkeletonState { /* Bone state array is allocated after this */ + u16 bone_count; + u16 flags; + float field2_0x4; + struct BoneState * bone_states; + float field4_0xc; + float field5_0x10; + float field6_0x14; + undefined4 field7_0x18; + undefined4 field8_0x1c; + undefined4 field9_0x20; + struct ApeArchive * mta; + undefined4 field11_0x28; + undefined4 field12_0x2c; + undefined4 field13_0x30; + undefined4 field14_0x34; + undefined4 field15_0x38; + void * field16_0x3c; + struct GSkeletonStateSubA g_skeleton_state_subA_1; + struct GSkeletonStateSubA g_skeleton_state_subA_2; +} __attribute__((__packed__)); +static_assert(sizeof(SkeletonState) == 0x70); + +struct GComponentDef { + undefined field_0x0[0x8]; + char * g_name; + undefined field_0xc[0x1c]; } __attribute__((__packed__)); -static_assert(sizeof(SKLInfo) == 0x174); +static_assert(sizeof(GComponentDef) == 0x28); + +struct Quat { + f32 x; + f32 y; + f32 z; + f32 w; +} __attribute__((__packed__)); +static_assert(sizeof(Quat) == 0x10); struct ARCHandle { /* I don't actually know the struct contents in the slightest */ void * arc_data; @@ -1072,58 +1072,51 @@ struct ARCHandle { /* I don't actually know the struct contents in the slightest } __attribute__((__packed__)); static_assert(sizeof(ARCHandle) == 0x1c); -struct GApeAnim { /* Unknown length -Crafted */ - u8 field0_0x0; - undefined field_0x1[0x3]; - struct g_thing * count; - struct GApeAnim * ape; - s32 * field6_0xc; /* Ptr to some struct? */ - undefined field_0x10[0xc]; - s32 g_either_motion_or_skel2; - undefined field_0x20[0x8]; +struct SkeletonDef { /* Bone definitions immediately follow */ + short bone_count; + undefined2 padding; } __attribute__((__packed__)); -static_assert(sizeof(GApeAnim) == 0x28); +static_assert(sizeof(SkeletonDef) == 0x4); + +struct Component { /* Subcomponent of an Ape, like body, face, hands, eyes */ + struct SkeletonState * skeleton_state; + struct SkeletonDef * skeleton_def; + struct ApeArchive * mta; /* Animation definitions */ +} __attribute__((__packed__)); +static_assert(sizeof(Component) == 0xc); struct Ape { struct SomeApeState * g_some_ape_state; - struct Mal * common_mal; /* Was originally ushort -Crafted */ - void * game_mal; /* It's not, a lot of these labels were confusingly wrong?? - bomb Is this even a float? -Crafted */ - struct SKLRoot * frame_ptr; - struct ArcFileInfo * arc_location; - float g_some_ptr; - struct SKLRoot * faceSKLStorage; - struct SKLFile * faceSKLFile; - void * faceMTA; - struct SKLRoot * handRSKLStorage; - struct SKLFile * handRSKLFile; - void * handrMTA; - struct SKLRoot * handLSKLStorage; - struct SKLFile * handLSKLFile; - void * handlMTA; - struct SKLRoot * tailSKLStorage; - struct SKLFile * tailSKLFile; - struct GApeAnim * animLengthBytes; /* Created by retype action */ - struct SKLRoot * g_some_skl; - struct GmaBuffer * GMABuffer; - struct TplBuffer * TPLBuffer; - undefined2 field21_0x54; + struct Mal * common_mal; + void * game_mal; + void * field3_0xc; + struct ApeArchive * g_skel_ska; /* Pointer to contents of "skel.ska", which has one skeleton per character */ + void * field5_0x14; + struct Component g_face_component; + struct Component g_handr_component; + struct Component g_handl_component; + struct Component g_tail_component; + struct GComponentDefList * g_component_defs; + struct GmaBuffer * gma; + struct TplBuffer * tpl; + undefined2 field13_0x54; undefined field_0x56[0x2]; - undefined2 field24_0x58; + undefined2 field16_0x58; undefined field_0x5a[0x2]; void * anim_func; /* Created by retype action */ float float_0x60; undefined field_0x64[0x10]; - ApeGame game; /* Created by retype action */ - char g_ape_variant; + SceneId16 scene_id; /* Created by retype action */ + DeformType8 g_deform_type; undefined field_0x77[0x1]; - int g_smth_with_game; /* Created by retype action */ - undefined4 field49_0x7c; - undefined2 field50_0x80; + int g_smth_with_scene; /* Created by retype action */ + undefined4 field41_0x7c; + undefined2 field42_0x80; undefined field_0x82[0x2]; - short field53_0x84; + short field45_0x84; u8 chara_anim_type; /* Some value that changes the type of animation the character is doing. From standing still, to walking, to the "I lost" state, etc */ byte g_anim_step; - int ape_total_index; /* Something to do with character spinning post-goal */ + int g_next_ape_idx; /* Something to do with character spinning post-goal */ ushort g_handr_short; ushort g_handl_short; ApeFace face; @@ -1134,93 +1127,105 @@ struct Ape { ushort some_flag_1; undefined field_0xa4[0x4]; int g_some_length1; - int field75_0xac; - float field76_0xb0; - undefined4 field77_0xb4; - undefined4 field78_0xb8; - undefined4 field79_0xbc; - int field80_0xc0; - void * g_frames1[40]; - void * field82_0x164; - void * field83_0x168; - void * field84_0x16c; - void * field85_0x170; - void * field86_0x174; - void * field87_0x178; - void * field88_0x17c; - void * field89_0x180; - void * field90_0x184; - void * field91_0x188; - void * field92_0x18c; - void * field93_0x190; - void * field94_0x194; - void * field95_0x198; - void * field96_0x19c; - void * field97_0x1a0; - void * field98_0x1a4; - void * field99_0x1a8; - void * field100_0x1ac; - void * field101_0x1b0; - void * field102_0x1b4; - void * field103_0x1b8; - void * field104_0x1bc; - undefined field_0x1c0[0x1c]; - void * expression_models[9]; - undefined field_0x200[0x4]; - void * HandL_GHA_model; - void * HandL_PHA_model; - void * HandR_GHA_model; - void * HANDR_PHA_model; + int field67_0xac; + float field68_0xb0; + undefined4 field69_0xb4; + undefined4 field70_0xb8; + undefined4 field71_0xbc; + int field72_0xc0; + struct GmaModel * g_component_models[40]; + struct GmaModel * g_eye_models1[15]; /* Not unique models, repeated! Blink pattern? */ + struct GmaModel * g_eye_models2[15]; /* Same underlying models as above, but blink pattern may differ between characters?!? */ + struct GmaModel * face_models[10]; + struct GmaModel * hand_l_fist_model; + struct GmaModel * hand_l_flat_model; + struct GmaModel * hand_r_fist_model; + struct GmaModel * hand_r_flat_model; float float_0x214; - short field143_0x218; + short field82_0x218; undefined field_0x21a[0x2]; char flag2; undefined field_0x21d[0x3]; uint flag3; uint flag4; undefined field_0x228[0x14]; - undefined4 field172_0x23c; - undefined4 field173_0x240; - int character; + undefined4 field111_0x23c; + undefined4 field112_0x240; + ApeCharacter chara; u32 flag1; - undefined4 field176_0x24c; - undefined4 field177_0x250; - undefined4 field178_0x254; + undefined4 field115_0x24c; + undefined4 field116_0x250; + undefined4 field117_0x254; struct Vec pos; struct Vec some_vec3; - undefined4 field181_0x270; - undefined4 field182_0x274; - undefined4 field183_0x278; - undefined4 field184_0x27c; + undefined4 field120_0x270; + undefined4 field121_0x274; + undefined4 field122_0x278; + undefined4 field123_0x27c; float scale; undefined field_0x284[0x4]; - struct Quat chara_rotation; - int ape_index; - undefined4 field192_0x29c; + struct Quat ape_rotation; + int ape_idx; + undefined4 field131_0x29c; ApeLOD lod; - undefined4 field194_0x2a4; + undefined4 field133_0x2a4; float g_smth_w_velocity1; float g_smth_w_velocity2; float g_smth_w_velocity3; float g_smth_w_velocity4; - undefined4 field199_0x2b8; + undefined4 field138_0x2b8; int color_index; undefined field_0x2c0[0x8]; char ball_idx; /* Created by retype action */ byte camera_visible_bitmask; undefined field_0x2ca[0x2]; - float field213_0x2cc; - float field214_0x2d0; - float field215_0x2d4; - float field216_0x2d8; - float field217_0x2dc; - float field218_0x2e0; - float field219_0x2e4; - float field220_0x2e8; - float field221_0x2ec; + float field152_0x2cc; + float field153_0x2d0; + float field154_0x2d4; + float field155_0x2d8; + float field156_0x2dc; + float field157_0x2e0; + float field158_0x2e4; + float field159_0x2e8; + float field160_0x2ec; } __attribute__((__packed__)); static_assert(sizeof(Ape) == 0x2f0); +struct BoneState { + char * bone_name; + short flags; + short parent_id; + struct Vec translation; + float translation_distance; /* Created by retype action */ + struct Vec g_translation_copy; + float g_float1; + Mtx g_rotation_mtx1; + Mtx g_rotation_mtx2; /* Created by retype action */ + Mtx mtx; /* Created by retype action */ + struct Vec g_vec; /* Created by retype action */ + undefined field_0xc4[0xc]; + undefined4 field23_0xd0; + short g_keyframe_a_count[3]; + undefined field_0xda[0x6]; + short g_keyframe_b_count[3]; + undefined field_0xe6[0x6]; + short g_keyframe_c_count[3]; + undefined field_0xf2[0x6]; + short g_keyframe_a_unk[3]; + undefined field_0xfe[0x6]; + short g_keyframe_b_unk[3]; + undefined field_0x10a[0x6]; + short g_keyframe_c_unk[3]; + undefined field_0x116[0x6]; + struct BoneKeyframe * g_keyframes_a[3]; + undefined field_0x128[0xc]; + struct BoneKeyframe * g_keyframes_b[3]; + undefined field_0x140[0xc]; + struct BoneKeyframe * g_keyframes_c[3]; + undefined field_0x158[0x1c]; +} __attribute__((__packed__)); +static_assert(sizeof(BoneState) == 0x174); + struct Mal { /* Structure of common_mal ape animation files? Header size unknown atm */ undefined field_0x0[0x21]; u8 g_some_count; @@ -1623,10 +1628,9 @@ struct DVDFileInfo { /* Not entirely sure about this one... I've filled in some struct DVDCommandBlock cb; u32 startAddr; u32 length; - struct DVDFileInfo * next; void (* callback)(s32, struct DVDFileInfo *); } __attribute__((__packed__)); -static_assert(sizeof(DVDFileInfo) == 0x40); +static_assert(sizeof(DVDFileInfo) == 0x3c); struct DVDDiskID { char gameName[4]; @@ -1652,6 +1656,7 @@ struct SpriteTex { GXTexFmt format; OSHeapHandle heap; struct DVDFileInfo dvd_file; + undefined field_0x78[0x4]; } __attribute__((__packed__)); static_assert(sizeof(SpriteTex) == 0x7c); @@ -1800,16 +1805,6 @@ enum { }; typedef undefined2 StoryModeStageSelectState; -typedef struct GCachedFileEntry GCachedFileEntry, *PGCachedFileEntry; - -struct GCachedFileEntry { - undefined field_0x0[0x4]; - int dvd_entrynum; - struct DVDCommandBlock * next; /* Created by retype action */ - struct DVDCommandBlock * prev; -} __attribute__((__packed__)); -static_assert(sizeof(GCachedFileEntry) == 0x10); - enum { MF_NONE=0, MF_0x1=1, @@ -2122,6 +2117,33 @@ struct UnlockInfo { /* Info about which stuff in the game is unlocked, such as m } __attribute__((__packed__)); static_assert(sizeof(UnlockInfo) == 0x84); +typedef struct DigitalInputGroup DigitalInputGroup, *PDigitalInputGroup; + +enum { /* These are normally just #defines in the SDK's PAD library */ + PAD_BUTTON_LEFT=1, + PAD_BUTTON_RIGHT=2, + PAD_BUTTON_DOWN=4, + PAD_BUTTON_UP=8, + PAD_TRIGGER_Z=16, + PAD_TRIGGER_R=32, + PAD_TRIGGER_L=64, + PAD_BUTTON_A=256, + PAD_BUTTON_B=512, + PAD_BUTTON_X=1024, + PAD_BUTTON_Y=2048, + PAD_BUTTON_START=4096 +}; +typedef undefined2 PadDigitalInput; + +struct DigitalInputGroup { /* Consolidated bitfields for digital button inputs corresponding to the five PadStatusGroup types */ + PadDigitalInput raw; + PadDigitalInput prev_tick; + PadDigitalInput pressed; + PadDigitalInput released; + PadDigitalInput repeated; +} __attribute__((__packed__)); +static_assert(sizeof(DigitalInputGroup) == 0xa); + typedef struct Ball Ball, *PBall; enum { @@ -2225,6 +2247,25 @@ struct Ball { } __attribute__((__packed__)); static_assert(sizeof(Ball) == 0x1b0); +typedef struct File File, *PFile; + +typedef struct FileCacheEntry FileCacheEntry, *PFileCacheEntry; + +struct FileCacheEntry { + s32 has_data; + s32 entry_num; + u32 aram_addr; + u32 aram_size; +} __attribute__((__packed__)); +static_assert(sizeof(FileCacheEntry) == 0x10); + +struct File { + BOOL32 is_cached; + struct DVDFileInfo dvd_file_info; + struct FileCacheEntry cache_entry; +} __attribute__((__packed__)); +static_assert(sizeof(File) == 0x50); + typedef struct SmWorldInfo SmWorldInfo, *PSmWorldInfo; typedef struct SmStageInfo SmStageInfo, *PSmStageInfo; @@ -2242,6 +2283,52 @@ struct SmStageInfo { /* A list of 10 of these is used to define a world */ } __attribute__((__packed__)); static_assert(sizeof(SmStageInfo) == 0x4); +enum { + SCENE_COMMON=0, + SCENE_MAIN=1, + SCENE_DUMMY1=2, + SCENE_DUMMY2=3, + SCENE_DUMMY3=4, + SCENE_DUMMY4=5, + SCENE_DUMMY5=6, + SCENE_DUMMY6=7, + SCENE_DUMMY7=8, + SCENE_DUMMY8=9, + SCENE_DUMMY9=10, + SCENE_DUMMY10=11, + SCENE_RACE=12, + SCENE_FGT=13, + SCENE_PILOT=14, + SCENE_GOLF=15, + SCENE_BOWL=16, + SCENE_BILL=17, + SCENE_BOAT=18, + SCENE_DOGF=19, + SCENE_TENNIS=20, + SCENE_BBALL=21, + SCENE_GUNS=22, + SCENE_ADV=23, + SCENE_SEL=24, + SCENE_COMMEND=25, + SCENE_SCENE1A=26, + SCENE_SCENE1B=27, + SCENE_SCENE2=28, + SCENE_SCENE3=29, + SCENE_SCENE4=30, + SCENE_SCENE5=31, + SCENE_SCENE6=32, + SCENE_SCENE7=33, + SCENE_SCENE8=34, + SCENE_SCENE9=35, + SCENE_SCENE10=36, + SCENE_LASTSCENE=37, + SCENE_ENDING1=38, + SCENE_ENDING2=39, + SCENE_ENDING3=40, + SCENE_ENDING4=41 +}; +typedef undefined4 SceneId32; + enum { DMD_SCEN_1ST_INIT=0, DMD_SCEN_RETURN_INIT=1, @@ -2349,14 +2436,24 @@ struct StoryModeSaveFile { } __attribute__((__packed__)); static_assert(sizeof(StoryModeSaveFile) == 0x84); -typedef struct GBone GBone, *PGBone; +typedef struct BoneChannel BoneChannel, *PBoneChannel; -struct GBone { - struct SKLFile * SKLData; - void * MTAData; - void * UnknownPtr; +struct BoneChannel { + u16 keyframe_count; + u16 padding; } __attribute__((__packed__)); -static_assert(sizeof(GBone) == 0xc); +static_assert(sizeof(BoneChannel) == 0x4); + +typedef struct BoneDef BoneDef, *PBoneDef; + +struct BoneDef { /* Null-terminated bone name directly follows, followed by 4(?) byte-aligned next bone */ + short parent_bone_id; + short flags; + struct Quat g_rotation1; + struct Quat g_rotation2; + struct Vec translation; +} __attribute__((__packed__)); +static_assert(sizeof(BoneDef) == 0x30); typedef struct RankingEntry RankingEntry, *PRankingEntry; @@ -2380,6 +2477,14 @@ struct GTableEntry { } __attribute__((__packed__)); static_assert(sizeof(GTableEntry) == 0xc); +typedef struct BoneAnim BoneAnim, *PBoneAnim; + +struct BoneAnim { + ushort channels_bitfield; + undefined2 field1_0x2; +} __attribute__((__packed__)); +static_assert(sizeof(BoneAnim) == 0x4); + typedef struct theme_light theme_light, *Ptheme_light; typedef short int16_t; @@ -2858,34 +2963,10 @@ struct MemCardInfo { /* Some struct that seems to hold per-memcard info; there a } __attribute__((__packed__)); static_assert(sizeof(MemCardInfo) == 0x44); -typedef struct GSomeFileStruct GSomeFileStruct, *PGSomeFileStruct; - -struct GSomeFileStruct { - BOOL32 dvd_entrynum; - struct DVDFileInfo dvdFileInfo; -} __attribute__((__packed__)); -static_assert(sizeof(GSomeFileStruct) == 0x44); - typedef struct PadStatusGroup PadStatusGroup, *PPadStatusGroup; typedef struct PADStatus PADStatus, *PPADStatus; -enum { /* These are normally just #defines in the SDK's PAD library */ - PAD_BUTTON_LEFT=1, - PAD_BUTTON_RIGHT=2, - PAD_BUTTON_DOWN=4, - PAD_BUTTON_UP=8, - PAD_TRIGGER_Z=16, - PAD_TRIGGER_R=32, - PAD_TRIGGER_L=64, - PAD_BUTTON_A=256, - PAD_BUTTON_B=512, - PAD_BUTTON_X=1024, - PAD_BUTTON_Y=2048, - PAD_BUTTON_START=4096 -}; -typedef undefined2 PadDigitalInput; - struct PADStatus { PadDigitalInput button; /* Or-ed PAD_BUTTON_* and PAD_TRIGGER_* bits */ s8 stickX; /* -128 <= stickX <= 127 */ @@ -2910,17 +2991,6 @@ struct PadStatusGroup { /* A set of PADStatus structs for a given controller, wi } __attribute__((__packed__)); static_assert(sizeof(PadStatusGroup) == 0x3c); -typedef struct DigitalInputGroup DigitalInputGroup, *PDigitalInputGroup; - -struct DigitalInputGroup { /* Consolidated bitfields for digital button inputs corresponding to the five PadStatusGroup types */ - PadDigitalInput raw; - PadDigitalInput prev_tick; - PadDigitalInput pressed; - PadDigitalInput released; - PadDigitalInput repeated; -} __attribute__((__packed__)); -static_assert(sizeof(DigitalInputGroup) == 0xa); - enum { /* Some flags that get set during render loops, perhaps? */ RENDERFLAG_NONE=0, RENDERFLAG_DISP=8, @@ -2982,6 +3052,14 @@ enum { }; typedef undefined1 WidescreenMode; +typedef struct SkeletonAnim SkeletonAnim, *PSkeletonAnim; + +struct SkeletonAnim { + short g_unk1; + short bone_count; +} __attribute__((__packed__)); +static_assert(sizeof(SkeletonAnim) == 0x4); + typedef struct MemCardFile MemCardFile, *PMemCardFile; typedef struct CARDFileInfo CARDFileInfo, *PCARDFileInfo; @@ -3310,6 +3388,29 @@ enum { /* Abbreviated "ET" in the game */ }; typedef undefined2 EffectType; +typedef struct GApeAnim GApeAnim, *PGApeAnim; + +typedef struct g_thing g_thing, *Pg_thing; + +struct g_thing { + undefined field_0x0[0x8]; + char * Name; + undefined field_0xc[0x1c]; +} __attribute__((__packed__)); +static_assert(sizeof(g_thing) == 0x28); + +struct GApeAnim { /* Unknown length -Crafted */ + u8 field0_0x0; + undefined field_0x1[0x3]; + struct g_thing * count; + struct GApeAnim * ape; + s32 * field6_0xc; /* Ptr to some struct? */ + undefined field_0x10[0xc]; + s32 g_either_motion_or_skel2; + undefined field_0x20[0x8]; +} __attribute__((__packed__)); +static_assert(sizeof(GApeAnim) == 0x28); + enum { GX_USAGE_NONE=0, GX_USAGE_LOCKED_CACHE_ENABLED=2, @@ -3374,6 +3475,12 @@ struct Effect { } __attribute__((__packed__)); static_assert(sizeof(Effect) == 0xb0); +enum { /* Whether ape models are skinning or stitching? */ + DEFORM32_SKINNING=0, + DEFORM32_STITCHING=1 +}; +typedef undefined4 DeformType32; + enum { PMT_UNKNOWN0=0, PMT_CHALLENGE=1, @@ -5989,17 +6096,26 @@ extern "C" { extern pointer switchdataD_803d1624; extern pointer switchdataD_803d1c2c; extern undefined * switchdataD_803d35f0; - extern undefined * postfix_table; - extern undefined * postfix_table_s; - extern undefined * ape_name_enum; + extern undefined4 g_mini_race_scene; + extern undefined4 g_mini_target_scene; + extern undefined4 g_mini_bowling_scene; + extern undefined4 g_mini_billiards_scene; + extern struct GComponentDef g_aiai_lod0_skel_def2_list[8]; + extern struct GComponentDef g_aiai_lod1_skel_def2_list[8]; + extern struct GComponentDef g_aiai_lod3_lod4_skel_def2_list[7]; + extern struct GComponentDefList g_component_defs[68]; + extern char * ape_lod_names[8]; + extern undefined * chara_names; extern undefined * storymode_ape_enum; extern undefined * ape_lod_enum; + extern pointer g_mesh_type_name; extern undefined * eye_string_table; - extern char * * eye_name_table[17]; - extern undefined * game_name_enum; - extern char * enum_face_types[9]; + extern undefined * aiai_eye_model_names; + extern char * * g_per_chara_blink_models[17]; + extern undefined * scene_names; + extern char * ape_face_names[9]; extern undefined * ape_face_enum_alt; - extern undefined * ape_face_enum_monkey; + extern undefined * ape_face_expr_names; extern char s_ape[4]; extern undefined * switchdataD_803d9220; extern char DIP_APENUM_FORMAT[5]; @@ -6332,8 +6448,9 @@ extern "C" { extern undefined4 disc_queue_start; extern undefined4 disc_queue_end; extern undefined4 discQueueGroup; - extern struct GCachedFileEntry g_cached_file_entries[128]; + extern struct FileCacheEntry file_cache_entries[128]; extern undefined4 g_last_filename_attempted_to_open; + extern undefined4 g_aram_read_pending; extern undefined4 g_minigame_tick_func; extern undefined4 g_mini_draw_func_ptr; extern undefined1 g_haze_type; @@ -6358,24 +6475,24 @@ extern "C" { extern float g_avdisp_bound_sphere_scale; extern float g_avdisp_material_alpha; extern Mtx avdisp_tex_mtx; - extern undefined main_mta_storage; - extern struct GBone face_bones[16]; - extern struct GBone handR_bones[16]; - extern struct GBone tailBone; - extern struct GBone handLbones[16]; + extern struct Component g_main_components[17]; + extern struct Component g_face_components[17]; + extern struct Component g_handr_components[17]; + extern struct Component g_tail_component; + extern struct Component g_handl_components[17]; extern void * common_anim_storage[17]; extern void * game_mal_storage[17]; - extern struct ArcFileInfo * arc_location; + extern struct ApeArchive * skel_ska; extern void * common_mal_sizes[17]; extern int game_mal_sizes[17]; extern void * ape_tpls[68]; extern void * rep_tpl_table[17]; extern void * ape_gma_table[68]; - extern struct ARCHandle ape_skl_arc_handle; - extern void * ape_skl_arc_data; - extern Mtx g_common_mtx; - extern float g_some_floats[64]; - extern undefined ape_ref_count_table; + extern struct ARCHandle arc_file_handle; + extern void * skl_arc; + extern Mtx g_common_ape_mtx; + extern float g_ape_floats[64]; + extern int ape_ref_count_table[136]; extern struct Ape * registered_apes[64]; extern undefined4 total_apes_registered; extern undefined4 g_ptr_to_something; @@ -7558,10 +7675,10 @@ extern "C" { void GXInitXfRasMetric(void); void GXReadXfRasMetric(undefined4 * param_1, undefined4 * param_2, undefined4 * param_3, undefined4 * param_4); undefined4 ARCInitHandle(void * arc_data, struct ARCHandle * out_arc_handle); - BOOL32 ARCOpen(struct ARCHandle * arc_handle, char * file, struct ArcFileInfo * arcFileInfo); + BOOL32 ARCOpen(struct ARCHandle * arc_handle, void * filebuf, struct ArcFileInfo * arcFileInfo); uint arc_path_to_entrynum(struct ARCHandle * arcHandle, char * file); void arc_get_dir(int param_1, int param_2, int param_3); - int ARCGetStartAddrInMem(undefined4 * param_1); + void * ARCGetStartAddrInMem(struct ArcFileInfo * af); undefined4 arcGetLength(struct ArcFileInfo * fileInfo); undefined4 return_1(void); void g_some_perf_init_func(void); @@ -7710,7 +7827,7 @@ extern "C" { void macHandleActive(int * param_1); void macHandle(uint param_1); void macSampleEndNotify(int * param_1); - uint macSetExternalKeyoff(int * param_1); + int macSetExternalKeyoff(int * param_1); void macSetPedalState(int * param_1, int param_2); void TimeQueueAdd(int param_1); void UnYieldMacro(int * param_1, int param_2); @@ -8112,7 +8229,7 @@ extern "C" { void g_maybe_something_with_normals(int param_1); void g_init_gma(struct GmaBuffer * gma_buffer, struct Gma * gma_header, struct TplBuffer * tpl); int g_init_gma_model_materials(struct GmaModel * model, struct TplBuffer * tpl, struct GXTexObj * texobj_array); - void g_memcpy_using_locked_cache(void * dest, void * curr_src_1_1_1_1_1_1_1_1_1_1_1_1_1, size_t count); + void g_memcpy_using_locked_cache(void * dest, void * curr_src_1_1_1_1_1_1_1_1_1_1_1_1_1_1_1, size_t count); void g_something_with_locked_cache_2(void * param_1, uint param_2, uint param_3); void memcpy2(void * dest, void * src, size_t count); int * __va_arg(char * param_1, int param_2); @@ -8496,7 +8613,7 @@ extern "C" { void take_pausemenu_screenshot(void * out_image_buffer, undefined4 src_left_px, undefined4 src_top_px, short width_px, short height_px, GXTexFmt fmt); void init_pausemenu_screenshot_texobj(struct GXTexObj * param_1); void g_draw_pausemenu_screenshot(struct GXTexObj * tex); - void md_adv_func(void); + uint md_adv_func(void); void empty_function(void); void empty_function(void); void smd_adv_logo_init(void); @@ -8537,7 +8654,7 @@ extern "C" { void create_demo_mask_sprites(void); void sprite_demo_mask_banana_tick(u8 * status, struct Sprite * sprite); void g_set_lots_of_initial_state(void); - void md_sel_func(void); + uint md_sel_func(void); void smd_sel_ngc_dest(void); void g_return_to_sel_ngc(undefined4 param_1); void g_load_stage_for_menu_bg(char param_1, int param_2); @@ -8793,7 +8910,7 @@ extern "C" { void event_adx_init(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, undefined4 param_9, undefined4 param_10, undefined4 param_11, undefined4 param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); void event_adx_tick(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, undefined4 param_5, undefined4 param_6, undefined4 param_7, undefined4 param_8); void event_adx_dest(void); - void g_adx_error_call_back(undefined4 param_1, undefined4 param_2); + void g_adx_error_call_back(undefined4 param_1, char * param_2); void g_draw_ingame_debug_menu(uint * param_1, int param_2); void g_draw_debug_window_boundaries(uint * param_1); void draw_debugtext(void); @@ -9458,6 +9575,7 @@ extern "C" { void calc_sprite_bounds(struct Sprite * sprite, s32 * left, s32 * top, s32 * right, s32 * bottom); void g_get_font_char_width(char * character, Font32 font, struct FontDefinition * g_font_struct); double g_get_font_char_width_scaling(char * character, Font32 font); + undefined * textdraw_parse_control_code(uint * state, byte * text, uint * color, int * consumed, uint * font); void textdraw_reset(void); void textdraw_set_font(Font32 font_type); void textdraw_set_mul_color(uint param_1); @@ -9575,7 +9693,7 @@ extern "C" { void g_sprite_extra_all_mask_tick(u8 * status, struct Sprite * sprite); void g_sprite_go_to_the_tick(u8 * status, struct Sprite * sprite); void g_sprite_go_to_the_disp(struct Sprite * sprite); - void create_postgoal_score_sprites(undefined4 param_1, undefined4 param_2, uint param_3); + void create_postgoal_score_sprites(int param_1, int param_2, uint param_3); void sprite_clear_score_disp(struct Sprite * sprite); void sprite_warp_bonus_disp(struct Sprite * sprite); void sprite_time_bonus_disp(struct Sprite * sprite); @@ -9646,11 +9764,11 @@ extern "C" { void g_some_arq_callback(u32 pointerToARQRequest); void load_disc_queue(void); BOOL32 g_something_with_dvd(s32 entry_num, undefined4 * param_2); - BOOL32 dvd_open_file(char * file_path, struct GSomeFileStruct * fileStruct); - BOOL32 dvd_close(struct GSomeFileStruct * file); - void g_some_ARQPostRequest_callback(void); - u32 dvd_read_file_into_buffer(int * dvdEntrynum, void * buffer, u32 length, int offset); - int get_file_size(struct GSomeFileStruct * file_struct); + BOOL32 file_open(char * file_path, struct File * file); + BOOL32 file_close(struct File * file); + void ARQPostRequest_on_finish(void); + u32 file_read(struct File * file, void * buffer, u32 length, int offset); + int file_size(struct File * file); void g_some_dvd_callback(s32 result, struct DVDFileInfo * fileInfo); void g_something_with_dvd2(uint param_1, int param_2); int add_one_wrap_if_over127(int num); @@ -9665,7 +9783,7 @@ extern "C" { void g_some_shadow_draw_func(struct ShadowReceive * shadow_receive); undefined4 g_check_some_condition(ushort param_1); void debug_draw_shadow_textures(void); - void md_mini_func(void); + uint md_mini_func(void); void g_set_minigame_specific_funcs(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4); void g_smd_mini_generic_init(void); void g_smd_mini_generic_tick(void); @@ -9824,30 +9942,31 @@ extern "C" { void g_apply_wormhole_pos_to_camera(struct Vec * camera_pos, struct Vec * camera_vel, Mtx * mtx); void apply_wormhole_tf_to_quat(struct Quat * quat, Mtx * wormhole_tf); void empty_function(void); - void g_load_skl(struct SKLRoot * sklRoot, struct SKLInfo * boneData, struct SKLFile * sklFile); - void g_handL_SKL_func(void * param_1, int param_2); - void gan_setanim_wrapper(void * param_1, char * param_2); - void gan_setAnim(void * mal, undefined * param_2, short animation_number); - void gan_setanim_edance(undefined4 param_1, undefined param_2, uint param_3, uint param_4, uint param_5); - void g_init_floatthing(struct gFloats * param_1); - void gan_incframe(double g_speed, struct Ape * ape); + void init_component_state(struct SkeletonState * component_state, struct BoneState * bone_states, struct SkeletonDef * skl); + void g_init_some_handl_component_stuff(struct SkeletonState * component_state, undefined4 * param_2); + void g_init_mta(struct SkeletonState * skeleton_state, struct ApeArchive * mta); + void g_some_ape_anim_init_wrapper(void * param_1, char * param_2); + void g_init_skeleton_animation(struct SkeletonState * skeleton_state, void * param_2, short g_anim_id); + void g_unk_ape_anim1(undefined4 param_1, undefined param_2, uint param_3, uint param_4, uint param_5); + void g_init_bone_state_subA(struct GSkeletonStateSubA * param_1); + void g_unk_ape_anim2(double g_speed, struct Ape * ape); void g_set_more_ape_state(undefined2 * param_1, undefined2 * param_2); void g_smth_with_quat_slerp(ushort * param_1); - void g_something_arc(struct ArcFileInfo * fileInfo); - uint g_table_index(struct SKLRoot * param1, char * str); - void load_ape_body(int ape_index, int game_index); - void gan_setanim_estagebegin(struct Ape * ape, int chara_index, int scene_index); + void ape_archive_offsets_to_pointers(struct ApeArchive * g_ska); + uint g_table_index(undefined param1, char * str); + void g_load_ape_mtas(ApeCharacter chara, SceneId32 scene_id); + void g_init_mtas(struct Ape * ape, ApeCharacter chara, SceneId32 scene_id); void g_something_freeing_chara_heap_3(int * param_1); - void g_something_with_new_ape(struct Ape * ape, int chara_index, int scene_index); - ulonglong event_ape_init(void); + void g_load_ape_mals(struct Ape * ape, ApeCharacter chara, SceneId32 scene_id); + void event_ape_init(void); void event_ape_tick(void); void event_ape_dest(void); - Ape * load_ape(int chara_index, ApeLOD LOD, int game_index, int s_mal); - Ape * load_ape_s(int chara_id, int LOD, int game_index); - Ape * load_ape_gameplay(int monkey_id, undefined4 LOD, int g_variant); - Ape * load_ape_gameplay_LOD(int monkey_id, ApeLOD LOD); + Ape * load_ape(ApeCharacter chara, ApeLOD ape_lod, SceneId32 scene_id, DeformType32 deform_type); + Ape * g_load_ape_variant0(ApeCharacter chara, ApeLOD lod, SceneId32 scene_id); + Ape * load_ape_gameplay(ApeCharacter chara, undefined4 lod, int g_ape_variant); + Ape * g_load_ape_gameplay_variant0(ApeCharacter chara, ApeLOD lod); void draw_ape_subroutine(int param_1); - void g_draw_ape1(double param_1, struct Ape * ape2); + void g_draw_ape(double param_1, struct Ape * ape); void draw_ape(struct Ape * ape); void g_something_with_freeing_chara_heap_ape(struct Ape * ape); void ape_default_anim(struct Ape * ape); @@ -9855,31 +9974,32 @@ extern "C" { void g_load_mal_files_from_disc(int chara_index, int LOD, int s_mal, int game_index); void g_something_freeing_chara_heap_4(int param_1, int param_2, int param_3); void g_something_freeing_chara_heap_2(int param_1, int param_2); - void assign_model_pointers(struct Ape * ape, ApeLOD lod); - int gan_getsomeframe(struct Ape * ape, int index); + void assign_ape_assets(struct Ape * ape, ApeLOD lod); + BoneState * g_get_ape_anim_smth(struct Ape * ape, int index); double body_frame_add72(struct Ape * ape); - undefined * get_ape_game_string(struct Ape * ape); + char * get_ape_scene_name(struct Ape * ape); int get_ape_anim_flags(struct Ape * ape, undefined4 param_2, int param_3); - void preload_ape(int chara_index, int LOD, int s_mal, int game_index); - void g_load_ape_mta_mal_files(int game_index, int chara_index); + void preload_ape(ApeCharacter chara, ApeLOD lod, int s_mal, int scene_id); + void g_queue_ape_mta_mal_load(int scene_id, ApeCharacter chara); uint g_something_with_comparing_strings(undefined4 param_1, char * param_2); void register_ape(struct Ape * ape); void unregister_ape(struct Ape * ape); - Ape get_ape_index(struct Ape * __return_storage_ptr__, int index); + Ape * get_ape_by_idx(int param_1); void dip_apenum_draw(struct Ape * ape); - char * get_ape_name_string(struct Ape * ape); + char * get_ape_chara_name(struct Ape * ape); char * get_ape_lod_string(struct Ape * ape); - char * get_ape_face_string(struct Ape * ape); + char * g_get_ape_skinning_or_stitching_name(struct Ape * ape); + char * get_ape_face_expr_name(struct Ape * ape); int seek(char * param_1); - void g_load_models(struct Ape * ape); + void assign_ape_models(struct Ape * ape); SomeApeState * g_get_structure_from_ape_common_mal_struct(struct Mal * common_mal); void g_something_freeing_heap_3(void * param_1); int g_get_ape_flag(struct Ape * ape, undefined4 g_something_with_game, int param_3); undefined4 g_alloc_some_ape_state_0x8(struct SomeApeState * g_some_ape_state, int chara_idx); - void gan_setanim_e4(struct Ape * ape); + void g_ape_anim_unk3(struct Ape * ape); void g_set_ape_dance_state1(int param_1, int param_2, undefined2 param_3, int param_4, undefined4 param_5, undefined4 param_6, int param_7); void g_set_ape_dance_state2(struct SomeApeState * g_some_ape_state, uint param_2, uint param_3, int param_4, int param_5, undefined4 param_6, undefined4 param_7, int param_8); - void gan_setAnim2(struct Ape * ape, int param_2, short * param_3); + void g_ape_anim_unk4(struct Ape * ape, int param_2, short * param_3); int g_some_ape_anim_func2(int param_1, int param_2, undefined4 param_3, undefined4 param_4, int param_5); void g_set_ape_stuff_in_chara_heap(undefined2 * param_1, undefined2 * param_2); void g_something_with_GXPeekZ(void); @@ -9927,7 +10047,7 @@ extern "C" { void smd_author_play_ending_init(void); void smd_author_play_from_sel(void); void smd_author_play_ret_sel(void); - void md_author_func(void); + uint md_author_func(void); void author_draw_func(void); void g_assign_new_main_and_sub_mode_for_play_tick(MainMode param_1, SubMode param_2); void g_set_some_author_tick_func(undefined4 param_1); @@ -9972,7 +10092,7 @@ extern "C" { void main_game_rel_prolog(void); void main_game_rel_epilog(void); void main_game_rel_unlinked(void); - void md_game_func(void); + uint md_game_func(void); void smd_game_first_init(void); void smd_game_restart_init(void); void smd_game_ready_init(void); @@ -10287,7 +10407,7 @@ extern "C" { void test_mode_unlinked_func(void); void smd_test_select_init(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, undefined4 param_9, undefined4 param_10, undefined4 param_11, undefined4 param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); void smd_test_select_main(void); - void test_select_draw_func(void); + undefined2 * test_select_draw_func(void); void smd_test_dip_init(void); void smd_test_dip_main(void); void smd_test_input_init(void); @@ -10369,10 +10489,10 @@ extern "C" { void test_adx_draw_func(void); void test_newmotion_draw_func(void); void g_something_freeing_something_from_main_heap_2(void); - void gan_setanim_e5(undefined4 * param_1, char * param_2, int * param_3); - void gan_set_anim_e6(int param_1); - void gan_setanim_e7(int param_1, undefined4 param_2, int param_3); - void gan_setanim_e8(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, int param_5); + void g_ape_anim_unk5(undefined4 * param_1, char * param_2, int * param_3); + void g_ape_anim_unk6(int param_1); + uint g_ape_anim_unk7(int param_1, undefined4 param_2, int param_3); + void g_ape_anim_unk8(undefined4 param_1, undefined4 param_2, undefined4 param_3, undefined4 param_4, int param_5); void option_prolog(void); void option_epilog(void); void option_unlinked_func(void); @@ -10417,7 +10537,6 @@ extern "C" { void mini_futsal_unlinked_func(void); void empty_function(void); void empty_function(void); - void load_bg_ape(void); void dogfight_unlinked_func(void); void g_load_dog(void); void g_some_printf_function_10(undefined8 param_1, undefined8 param_2, undefined8 param_3, undefined8 param_4, undefined8 param_5, undefined8 param_6, undefined8 param_7, undefined8 param_8, char * param_9, undefined4 param_10, undefined4 param_11, undefined4 param_12, undefined4 param_13, undefined4 param_14, undefined4 param_15, undefined4 param_16); diff --git a/src/patches/custom/custom_font_color.cpp b/src/patches/custom/custom_font_color.cpp new file mode 100644 index 00000000..2c499f2f --- /dev/null +++ b/src/patches/custom/custom_font_color.cpp @@ -0,0 +1,159 @@ +#include "custom_font_color.h" + +#include "../internal/patch.h" +#include "../internal/tickable.h" +#include "../mkb/mkb.h" +#include "../utils/ppcutil.h" + +namespace custom_font_color { + +TICKABLE_DEFINITION(( + .name = "custom-font-color", + .description = "Custom font colors", + .init_main_loop = init_main_loop, + .init_main_game = init_main_game, + .init_sel_ngc = init_sel_ngc, + .tick = tick, )) + + +mkb::u32 menu_primary_color = 0xFFC000; +mkb::u32 menu_secondary_color = 0xFFFF00; +mkb::u32 menu_option_name_color = 0x0000C0; +mkb::u32 current_stage_info_color = 0xFFC000; +mkb::u32 ready_color = 0xFFC800; +mkb::u32 go_color = 0x0080FF; +mkb::u32 fallout_time_over_color = 0xFF8C00; +mkb::u32 spin_in_info_color = 0xFFFF00; +mkb::u32 final_stage_beginner_color = 0x00D000; +mkb::u32 final_stage_advanced_color = 0x0000E0; +mkb::u32 final_stage_expert_color = 0xFFC000; +mkb::u32 final_stage_master_color = 0xFFC000; +mkb::u32 bonus_stage_color = 0xFF8000; + +static patch::Tramp s_textdraw_set_mul_color_tramp; + +void replace_lis_color(int reg, u32 loc, u32 color) { + patch::write_word(reinterpret_cast(loc), PPC_INSTR_LIS(reg, (color >> 16) & 0xff));// RR + patch::write_word(reinterpret_cast(loc + 4), PPC_INSTR_ORI(reg, (color & 0xffff)));// GGBB +} + +void replace_3pt_color(u32 loc, u32 color) { + patch::write_word(reinterpret_cast(loc), 0x38000000 + ((color >> 16) & 0xff)); // RR + patch::write_word(reinterpret_cast(loc + 8), 0x38000000 + ((color >> 8) & 0xff));// GG + patch::write_word(reinterpret_cast(loc + 16), 0x38000000 + (color & 0xff)); // BB +} + +u32 form_color(u8 red, u8 green, u8 blue) { + return (red << 16) + (green << 8) + blue; +} + +u32 convert_color(u32 color) { + u8 red = (color >> 16) & 0xff; + u8 green = (color >> 8) & 0xff; + u8 blue = color & 0xff; + u32 new_color = color; + + if (blue == 0 && red > 0 && green > 0 && red >= green) {// Orange & yellow (b=0, r>=g>0) + u8 red_1 = (menu_primary_color >> 16) & 0xff; + u8 green_1 = (menu_primary_color >> 8) & 0xff; + u8 blue_1 = menu_primary_color & 0xff; + + u8 red_2 = (menu_secondary_color >> 16) & 0xff; + u8 green_2 = (menu_secondary_color >> 8) & 0xff; + u8 blue_2 = menu_secondary_color & 0xff; + + float percent_primary = (1 - ((float) (red - green) / (red / 2))); + + new_color = form_color( + (u8) (((float) red / 0xff) * ((red_1 * percent_primary) + (red_2 * (1 - percent_primary)))), + (u8) (((float) red / 0xff) * ((green_1 * percent_primary) + (green_2 * (1 - percent_primary)))), + (u8) (((float) red / 0xff) * ((blue_1 * percent_primary) + (blue_2 * (1 - percent_primary))))); + } + + return new_color; +} + + +static patch::Tramp s_parse_avtext_color_codes_tramp; + +mkb::u32 parse_avtext_color_codes_hook(char* string, mkb::SpriteDrawRequest* sprite_draw_req) { + mkb::u32 ret = s_parse_avtext_color_codes_tramp.dest(string, sprite_draw_req); + + if (sprite_draw_req != nullptr && ret != 0) { + if (sprite_draw_req->mult_color == 0xFF8000) { + sprite_draw_req->mult_color = menu_secondary_color; + } + else if (sprite_draw_req->mult_color == 0xFFFF00) { + sprite_draw_req->mult_color = menu_primary_color; + } + } + + return ret; +} + +void set_menu_title_color() { + mkb::textdraw_set_mul_color(menu_option_name_color); +} +void set_some_stagename_colors() { + mkb::textdraw_set_mul_color(current_stage_info_color); +} +void init_main_loop() { + patch::hook_function(s_textdraw_set_mul_color_tramp, mkb::textdraw_set_mul_color, [](u32 color) { + if (mkb::textdraw_font == mkb::FONT_ASC_24x24) { + s_textdraw_set_mul_color_tramp.dest(convert_color(color)); + } + else { + s_textdraw_set_mul_color_tramp.dest(color); + } + }); + patch::hook_function( + s_parse_avtext_color_codes_tramp, + mkb::parse_avtext_color_codes, + parse_avtext_color_codes_hook); + patch::write_branch_bl( + reinterpret_cast(0x8032C588), + reinterpret_cast(set_some_stagename_colors)); + + replace_3pt_color(0x80338c84, current_stage_info_color); // Stage number RGB color + replace_3pt_color(0x80338e74, current_stage_info_color); // Stage name RGB color + replace_3pt_color(0x80338A84, current_stage_info_color); // EX color + replace_3pt_color(0x8032caa0, ready_color); // READY text color + replace_3pt_color(0x8032d944, go_color); // GO text color + replace_3pt_color(0x8032bbb8, spin_in_info_color); // STAGE/WORLD spin in color + replace_3pt_color(0x8032E91C, fallout_time_over_color); // FALLOUT color + replace_3pt_color(0x8032ED18, fallout_time_over_color); // TIME OVER color + replace_3pt_color(0x8032F01C, fallout_time_over_color); // BONUS FINISH color + replace_3pt_color(0x8032CF20, final_stage_beginner_color);// Beginner FINAL STAGE color + replace_3pt_color(0x8032CF50, final_stage_advanced_color);// Advanced FINAL STAGE color + replace_3pt_color(0x8032BE70, bonus_stage_color); // BONUS STAGE color +} + +void init_main_game() { + patch::write_branch_bl( + reinterpret_cast(0x80900DF8), + reinterpret_cast(set_some_stagename_colors)); +} + +void init_sel_ngc() { + patch::write_branch_bl( + reinterpret_cast(0x8090C5F0), + reinterpret_cast(set_menu_title_color)); + patch::write_branch_bl( + reinterpret_cast(0x8090C7E8), + reinterpret_cast(set_menu_title_color)); +} + +void tick() { + if (((mkb::main_game_mode == mkb::PRACTICE_MODE) && + ((mkb::g_mode_flags2 & (mkb::MF_PLAYING_MASTER_EX_COURSE | + mkb::MF_PLAYING_MASTER_NOEX_COURSE)) != mkb::MF_NONE)) || + ((mkb::mode_flags & (mkb::MF_PLAYING_MASTER_EX_COURSE | + mkb::MF_PLAYING_MASTER_NOEX_COURSE)) != mkb::MF_NONE)) { + replace_3pt_color(0x8032CF6C, final_stage_master_color); + } + else { + replace_3pt_color(0x8032CF6C, final_stage_expert_color); + } +} + +}// namespace custom_font_color \ No newline at end of file diff --git a/src/patches/custom/custom_font_color.h b/src/patches/custom/custom_font_color.h new file mode 100644 index 00000000..76eeacae --- /dev/null +++ b/src/patches/custom/custom_font_color.h @@ -0,0 +1,25 @@ +#pragma once +#include "../mkb/mkb.h" + +namespace custom_font_color { +void init_main_loop(); +void init_main_game(); +void init_sel_ngc(); +void tick(); + +extern mkb::u32 menu_primary_color; +extern mkb::u32 menu_secondary_color; +extern mkb::u32 menu_option_name_color; +extern mkb::u32 current_stage_info_color; +extern mkb::u32 ready_color; +extern mkb::u32 go_color; +extern mkb::u32 fallout_time_over_color; +extern mkb::u32 spin_in_info_color; +extern mkb::u32 final_stage_beginner_color; +extern mkb::u32 final_stage_advanced_color; +extern mkb::u32 final_stage_expert_color; +extern mkb::u32 final_stage_master_color; +extern mkb::u32 bonus_stage_color; + + +}// namespace custom_font_color \ No newline at end of file diff --git a/src/patches/custom/font_color.cpp b/src/patches/custom/font_color.cpp deleted file mode 100644 index 93f4b7aa..00000000 --- a/src/patches/custom/font_color.cpp +++ /dev/null @@ -1,72 +0,0 @@ -#include "font_color.h" - -#include "../internal/patch.h" -#include "../internal/tickable.h" -#include "../mkb/mkb.h" -#include "../utils/ppcutil.h" -#include "font_primary.h" -#include "font_secondary.h" - -namespace font_color { - -TICKABLE_DEFINITION(( - .name = "custom-font-color", - .description = "Font Color", - .init_main_loop = init, - .init_main_game = init_main_game,)) - -// void textdraw_set_mul_color(uint param_1); -static patch::Tramp s_textdraw_set_mul_color_tramp; - -void replace_lis_color(int reg, u32 loc, u32 color) { - patch::write_word(reinterpret_cast(loc), PPC_INSTR_LIS(reg, (color >> 16) & 0xff));// RR - patch::write_word(reinterpret_cast(loc + 4), PPC_INSTR_ORI(reg, (color & 0xffff)));// GGBB -} - -void replace_3pt_color(u32 loc, u32 color) { - patch::write_word(reinterpret_cast(loc), 0x38000000 + ((color >> 16) & 0xff)); // RR - patch::write_word(reinterpret_cast(loc + 8), 0x38000000 + ((color >> 8) & 0xff));// GG - patch::write_word(reinterpret_cast(loc + 16), 0x38000000 + (color & 0xff)); // BB -} - -u32 form_color(u8 red, u8 blue, u8 green) { - return (red << 16) + (blue << 8) + green; -} - -u32 convert_color(u32 color) { - u8 red = (color >> 16) & 0xff; - u8 green = (color >> 8) & 0xff; - u8 blue = color & 0xff; - u32 new_color = color; - if (blue == 0 && red > 0 && green > 0 && red >= green) {// Orange & yellow (b=0, r>=g>0) - u8 red_1 = (font_primary::get_color() >> 16) & 0xff; - u8 green_1 = (font_primary::get_color() >> 8) & 0xff; - u8 blue_1 = font_primary::get_color() & 0xff; - u8 red_2 = (font_secondary::get_color() >> 16) & 0xff; - u8 green_2 = (font_secondary::get_color() >> 8) & 0xff; - u8 blue_2 = font_secondary::get_color() & 0xff; - float percent_primary = (1 - ((float)(red - green) / (red/2))); - new_color = form_color((u8)(((float)red/0xff) * ((red_1 * percent_primary) + (red_2 * (1-percent_primary)))), - (u8)(((float)red/0xff) * ((green_1 * percent_primary) + (green_2 * (1-percent_primary)))), - (u8)(((float)red/0xff) * ((blue_1 * percent_primary) + (blue_2 * (1-percent_primary))))); - } - return new_color; -} - -void init() { - patch::hook_function(s_textdraw_set_mul_color_tramp, mkb::textdraw_set_mul_color, [](u32 color) { - s_textdraw_set_mul_color_tramp.dest(convert_color(color)); - }); -} - -void init_main_game() { - replace_3pt_color(0x80338c84, font_primary::get_color());// Stage number RGB color - replace_3pt_color(0x80338e74, font_primary::get_color());// Stage name RGB color - replace_3pt_color(0x80338A84, font_primary::get_color());// EX color - replace_3pt_color(0x8032caa0, convert_color(0xffc000));// READY text color - replace_3pt_color(0x8032d944, font_secondary::get_color());// GO text color - replace_3pt_color(0x8032bbb8, font_primary::get_color());// STAGE/WORLD spin in color - replace_3pt_color(0x8032E91C, font_secondary::get_color());// FALLOUT color -} - -}// namespace font_color \ No newline at end of file diff --git a/src/patches/custom/font_color.h b/src/patches/custom/font_color.h deleted file mode 100644 index 61cb132a..00000000 --- a/src/patches/custom/font_color.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace font_color { -void init(); -void init_main_game(); -}// namespace font_color \ No newline at end of file diff --git a/src/patches/custom/font_primary.cpp b/src/patches/custom/font_primary.cpp deleted file mode 100644 index cef5ebc5..00000000 --- a/src/patches/custom/font_primary.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "font_primary.h" - -#include "../internal/patch.h" -#include "../internal/tickable.h" -#include "../mkb/mkb.h" -#include "../utils/ppcutil.h" - -namespace font_primary { - -int primary_color = 0xffff00; - -// Patch slot holding primary color for font-color -TICKABLE_DEFINITION(( - .name = "font-primary", - .description = "Font Primary", - .active_value = primary_color, - .lower_bound = 0x000000, - .upper_bound = 0xffffff, - .init_main_loop = init,)) - -int get_color() { - return primary_color; -} - -void init() { - primary_color = *active_tickable_ptr->active_value; -} - -}// namespace font_primary \ No newline at end of file diff --git a/src/patches/custom/font_primary.h b/src/patches/custom/font_primary.h deleted file mode 100644 index 657ff92c..00000000 --- a/src/patches/custom/font_primary.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace font_primary { - int get_color(); - void init(); -}// namespace font_primary \ No newline at end of file diff --git a/src/patches/custom/font_secondary.cpp b/src/patches/custom/font_secondary.cpp deleted file mode 100644 index 21a33eea..00000000 --- a/src/patches/custom/font_secondary.cpp +++ /dev/null @@ -1,29 +0,0 @@ -#include "font_secondary.h" - -#include "../internal/patch.h" -#include "../internal/tickable.h" -#include "../mkb/mkb.h" -#include "../utils/ppcutil.h" - -namespace font_secondary { - -int secondary_color = 0xff8000; - -// Patch slot holding secondary color for font-color -TICKABLE_DEFINITION(( - .name = "font-secondary", - .description = "Font Secondary", - .active_value = secondary_color, - .lower_bound = 0x000000, - .upper_bound = 0xffffff, - .init_main_loop = init,)) - -int get_color() { - return secondary_color; -} - -void init() { - secondary_color = *active_tickable_ptr->active_value; -} - -}// namespace font_secondary \ No newline at end of file diff --git a/src/patches/custom/font_secondary.h b/src/patches/custom/font_secondary.h deleted file mode 100644 index 3a085f97..00000000 --- a/src/patches/custom/font_secondary.h +++ /dev/null @@ -1,6 +0,0 @@ -#pragma once - -namespace font_secondary { - int get_color(); - void init(); -}// namespace font_secondary \ No newline at end of file diff --git a/src/patches/fixes/fix_bonus_sprite.cpp b/src/patches/fixes/fix_bonus_sprite.cpp index 59cdcfa7..1e546116 100644 --- a/src/patches/fixes/fix_bonus_sprite.cpp +++ b/src/patches/fixes/fix_bonus_sprite.cpp @@ -2,6 +2,7 @@ #include "internal/patch.h" #include "internal/tickable.h" +#include "patches/custom/custom_font_color.h" #include "utils/ppcutil.h" namespace fix_bonus_sprite { @@ -25,20 +26,31 @@ void new_bonus_sprite_tick(u8* status, mkb::Sprite* sprite) { } void create_bonus_sprite(void) { - // Check if we're on a bonus stage and if the sprite already exists - mkb::Sprite* special_stage_text_sprite = mkb::get_sprite_with_unique_id(mkb::SPRITE_SPECIAL_STAGE); + mkb::Sprite* special_stage_text_sprite = + mkb::get_sprite_with_unique_id(mkb::SPRITE_SPECIAL_STAGE); + if ((special_stage_text_sprite == (mkb::Sprite*) 0x0) && ((mkb::mode_info.ball_mode & mkb::BALLMODE_ON_BONUS_STAGE) != mkb::BALLMODE_NONE)) { - // Create the sprite + mkb::Sprite* sprite; sprite = mkb::create_sprite(); + if (sprite != (mkb::Sprite*) 0x0) { sprite->unique_id = mkb::SPRITE_SPECIAL_STAGE; (sprite->pos).x = 500.0; (sprite->pos).y = 452.0; - (sprite->mult_color).red = 0xff; - (sprite->mult_color).green = 0x80; - (sprite->mult_color).blue = '\0'; + + if (tickable::get_tickable_manager().get_tickable_status("custom-font-color")) { + sprite->mult_color.red = (custom_font_color::bonus_stage_color >> 16) & 0xff; + sprite->mult_color.green = (custom_font_color::bonus_stage_color >> 8) & 0xff; + sprite->mult_color.blue = custom_font_color::bonus_stage_color & 0xff; + } + else { + sprite->mult_color.red = 0xff; + sprite->mult_color.green = 0x80; + sprite->mult_color.blue = 0; + } + sprite->font = mkb::FONT_ASC_72x64; sprite->alignment = mkb::ALIGN_CENTER; sprite->width = 0.3; diff --git a/src/patches/fixes/fix_bonus_sprite.h b/src/patches/fixes/fix_bonus_sprite.h index 99a6deb7..fe3d3dfc 100644 --- a/src/patches/fixes/fix_bonus_sprite.h +++ b/src/patches/fixes/fix_bonus_sprite.h @@ -1,4 +1,5 @@ #pragma once +#include "../mkb/mkb.h" namespace fix_bonus_sprite { diff --git a/src/patches/fixes/fix_widescreen.cpp b/src/patches/fixes/fix_widescreen.cpp index 4ab444d3..2dd3820b 100644 --- a/src/patches/fixes/fix_widescreen.cpp +++ b/src/patches/fixes/fix_widescreen.cpp @@ -3,6 +3,7 @@ #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" +#include "patches/custom/custom_font_color.h" namespace fix_widescreen { @@ -47,9 +48,18 @@ void create_new_bonus_finish_sprite(u8* status, mkb::Sprite* sprite) { pSVar1->alignment = mkb::ALIGN_CENTER; pSVar1->g_counter = 0; pSVar1->para1 = 0; - pSVar1->mult_color.red = 0xff; - pSVar1->mult_color.green = 0x80; - pSVar1->mult_color.blue = 0; + + if (tickable::get_tickable_manager().get_tickable_status("custom-font-color")) { + pSVar1->mult_color.red = (custom_font_color::fallout_time_over_color >> 16) & 0xff; + pSVar1->mult_color.green = (custom_font_color::fallout_time_over_color >> 8) & 0xff; + pSVar1->mult_color.blue = custom_font_color::fallout_time_over_color & 0xff; + } + else { + pSVar1->mult_color.red = 0xff; + pSVar1->mult_color.green = 0x80; + pSVar1->mult_color.blue = 0; + } + pSVar1->width = 0.8; pSVar1->height = 0.8; pSVar1->widescreen_translation_x = 0x140; diff --git a/src/patches/fixes/fix_widescreen.h b/src/patches/fixes/fix_widescreen.h index 6c37f0d7..55b4f5ce 100644 --- a/src/patches/fixes/fix_widescreen.h +++ b/src/patches/fixes/fix_widescreen.h @@ -1,4 +1,5 @@ #pragma once +#include "../mkb/mkb.h" namespace fix_widescreen { From 1b96b37e5160e9d1946dee3256ad34f75169cef3 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 9 Jun 2026 00:50:40 -0700 Subject: [PATCH 88/96] Make stage name subtitle patch accommodate custom stagename colors --- src/patches/extensions/stage_name_subtitles.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/patches/extensions/stage_name_subtitles.cpp b/src/patches/extensions/stage_name_subtitles.cpp index c7c01b8c..ea713b7b 100644 --- a/src/patches/extensions/stage_name_subtitles.cpp +++ b/src/patches/extensions/stage_name_subtitles.cpp @@ -5,6 +5,7 @@ #include "internal/patch.h" #include "internal/tickable.h" #include "mkb/mkb.h" +#include "patches/custom/custom_font_color.h" // Allows for subtitles to be displayed under the stage name. @@ -47,9 +48,16 @@ void sprite_init(float x, float y) { sprite->fpara1 = 1.0; sprite->fpara2 = 0.0; sprite->alpha = 0.0; - (sprite->mult_color).red = 0xff; - (sprite->mult_color).green = 0xff; - (sprite->mult_color).blue = 0x00; + if (tickable::get_tickable_manager().get_tickable_status("custom-font-color")) { + sprite->mult_color.red = (custom_font_color::current_stage_info_color >> 16) & 0xff; + sprite->mult_color.green = (custom_font_color::current_stage_info_color >> 8) & 0xff; + sprite->mult_color.blue = custom_font_color::current_stage_info_color & 0xff; + } + else { + sprite->mult_color.red = 0xff; + sprite->mult_color.green = 0xff; + sprite->mult_color.blue = 0x00; + } sprite->width = 0.6; sprite->height = 0.6; sprite->field21_0x20 = 1.0; From 1b152f041117ea9b42491bcc6631e1a8c5b0782a Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 9 Jun 2026 10:35:45 -0700 Subject: [PATCH 89/96] Add custom world name patch --- src/config/config.cpp | 52 +++++++++++++++++++++++ src/internal/assembly.cpp | 13 ++++++ src/internal/assembly.h | 2 + src/mkb/mkb2.us.lst | 3 +- src/mkb/mkb2_ghidra.h | 3 +- src/patches/custom/custom_world_names.cpp | 21 +++++++++ src/patches/custom/custom_world_names.h | 9 ++++ 7 files changed, 101 insertions(+), 2 deletions(-) create mode 100644 src/patches/custom/custom_world_names.cpp create mode 100644 src/patches/custom/custom_world_names.h diff --git a/src/config/config.cpp b/src/config/config.cpp index 89b8476a..906a5dc1 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -232,6 +232,54 @@ void parse_story_mode_entries(char* buf) { LOG("Story Mode Entries loaded at: 0x%X", &main::new_story_entries); } +void parse_world_names(char* buf) { + buf = mkb::strchr(buf, '\n') + 1; + + char* end_of_section = mkb::strchr(buf, '}'); + char key[64] = {0}; + char value[64] = {0}; + bool seen[main::WORLD_COUNT] = {false}; + + do { + char *key_start, *key_end, *end_of_line; + key_start = mkb::strchr(buf, '\t') + 1; + key_end = mkb::strchr(buf, ':'); + MOD_ASSERT_MSG(key_start < key_end, + "Key start after key end, did you start your key with a tab and not spaces?"); + end_of_line = mkb::strchr(buf, '\n'); + + mkb::strncpy(key, key_start, key_end - key_start); + mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); + + MOD_ASSERT_MSG(key[0] == 'W', "Invalid world name key format, expected W<1-10>"); + + int world_idx = mkb::atoi(key + 1) - 1; + + MOD_ASSERT_MSG(world_idx >= 0 && world_idx < main::WORLD_COUNT, + "World name index out of range"); + MOD_ASSERT_MSG(!seen[world_idx], + "Duplicate World Name entry"); + + mkb::strncpy( + main::world_names[world_idx], + value, + sizeof(main::world_names[world_idx]) - 1); + + main::world_names[world_idx][sizeof(main::world_names[world_idx]) - 1] = '\0'; + seen[world_idx] = true; + + buf = end_of_line + 1; + mkb::memset(key, '\0', sizeof(key)); + mkb::memset(value, '\0', sizeof(value)); + } while (buf < end_of_section); + + for (int i = 0; i < main::WORLD_COUNT; ++i) { + MOD_ASSERT_MSG(seen[i], "Missing World Name entry"); + } + + LOG("World Names loaded at: 0x%X", &main::world_names); +} + void parse_font_colors(char* buf) { buf = mkb::strchr(buf, '\n') + 1; @@ -426,6 +474,10 @@ void parse_config() { parse_story_mode_entries(section_end); } + else if (STREQ(section, "World Names")) { + parse_world_names(section_end); + } + else { LOG("Unknown category %s found in config!", section); } diff --git a/src/internal/assembly.cpp b/src/internal/assembly.cpp index 1096f3b5..e95f9643 100644 --- a/src/internal/assembly.cpp +++ b/src/internal/assembly.cpp @@ -7,4 +7,17 @@ u16 bgm_id_lookup[421] = {0}; u16 theme_id_lookup[421] = {0}; NewStoryStageEntry new_story_entries[WORLD_COUNT][STAGES_PER_WORLD]; +char world_names[WORLD_COUNT][64] = { + "Jungle Island", + "Volcanic Magma", + "Under the Ocean", + "Inside a Whale", + "Amusement Park", + "Boiling Pot", + "Bubbly Washing Machine", + "Clock Tower Factory", + "Space Colony", + "Dr. BAD-BOON's Base", +}; + }// namespace main diff --git a/src/internal/assembly.h b/src/internal/assembly.h index d7079d1a..df52f9db 100644 --- a/src/internal/assembly.h +++ b/src/internal/assembly.h @@ -16,6 +16,8 @@ static constexpr int STAGES_PER_WORLD = 10; extern NewStoryStageEntry new_story_entries[WORLD_COUNT][STAGES_PER_WORLD]; +extern char world_names[WORLD_COUNT][64]; + extern "C" { // Assembly overwrite functions diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 547440fb..752aed91 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -5762,7 +5762,7 @@ 8031FA50:caseD_6 8031FAF0:g_get_font_char_width 8031FC14:g_get_font_char_width_scaling -8031FE7C:textdraw_parse_control_code +8031FE7C:g_some_textdraw_control_code_parse 8031FFE8:switchD 8031FFEC:caseD_30 8031FFF4:caseD_31 @@ -9802,6 +9802,7 @@ 809160E0:switchdataD_804ee064 809162D8:story_mode_funcs 809168A0:MAIN_GAME_STORY_STAGE_PREVIEW_PARAMS +80916D38:world_names 80916E78:ape_story_select_anim_table 80916EE4:switchdataD_804eee68 80916F04:switchdataD_804eee88 diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index 7541dc68..bfcfaca2 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -6517,6 +6517,7 @@ extern "C" { extern pointer switchdataD_804ee064; extern undefined * story_mode_funcs; extern struct StoryStagePreviewParam MAIN_GAME_STORY_STAGE_PREVIEW_PARAMS[100]; + extern char * world_names[60]; extern undefined1 ape_story_select_anim_table; extern pointer switchdataD_804eee68; extern pointer switchdataD_804eee88; @@ -9575,7 +9576,7 @@ extern "C" { void calc_sprite_bounds(struct Sprite * sprite, s32 * left, s32 * top, s32 * right, s32 * bottom); void g_get_font_char_width(char * character, Font32 font, struct FontDefinition * g_font_struct); double g_get_font_char_width_scaling(char * character, Font32 font); - undefined * textdraw_parse_control_code(uint * state, byte * text, uint * color, int * consumed, uint * font); + undefined * g_some_textdraw_control_code_parse(uint * state, byte * text, uint * color, int * consumed, uint * font); void textdraw_reset(void); void textdraw_set_font(Font32 font_type); void textdraw_set_mul_color(uint param_1); diff --git a/src/patches/custom/custom_world_names.cpp b/src/patches/custom/custom_world_names.cpp new file mode 100644 index 00000000..868bf57a --- /dev/null +++ b/src/patches/custom/custom_world_names.cpp @@ -0,0 +1,21 @@ +#include "custom_world_names.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_world_names { + +TICKABLE_DEFINITION(( + .name = "custom-world-names", + .description = "Custom world names", + .init_main_game = init_main_game, )) + + +void init_main_game() { + for (int i = 0; i < main::WORLD_COUNT; ++i) { + mkb::world_names[i * 6] = main::world_names[i]; + } +} +}// namespace custom_world_names diff --git a/src/patches/custom/custom_world_names.h b/src/patches/custom/custom_world_names.h new file mode 100644 index 00000000..71d89df8 --- /dev/null +++ b/src/patches/custom/custom_world_names.h @@ -0,0 +1,9 @@ +#pragma once + +#include "mkb/mkb.h" + +namespace custom_world_names { + +void init_main_game(); + +}// namespace custom_world_names \ No newline at end of file From f844fd509b7a6573b2796ab34b404d10ea4645da Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Tue, 9 Jun 2026 11:24:19 -0700 Subject: [PATCH 90/96] Add patch to remove brown color on menu icons --- .../removals/remove_menu_icon_brown_color.cpp | 17 +++++++++++++++++ .../removals/remove_menu_icon_brown_color.h | 7 +++++++ 2 files changed, 24 insertions(+) create mode 100644 src/patches/removals/remove_menu_icon_brown_color.cpp create mode 100644 src/patches/removals/remove_menu_icon_brown_color.h diff --git a/src/patches/removals/remove_menu_icon_brown_color.cpp b/src/patches/removals/remove_menu_icon_brown_color.cpp new file mode 100644 index 00000000..eab0fa9c --- /dev/null +++ b/src/patches/removals/remove_menu_icon_brown_color.cpp @@ -0,0 +1,17 @@ +#include "remove_menu_icon_brown_color.h" + +#include "internal/patch.h" +#include "internal/tickable.h" + +namespace remove_menu_icon_brown_color { + +TICKABLE_DEFINITION(( + .name = "remove-menu-icon-brown-color", + .description = "Remove menu icon brown color", + .init_sel_ngc = init_sel_ngc, )) + +void init_sel_ngc() { + patch::write_nop(reinterpret_cast(0x8090AC4C)); +} + +}// namespace remove_menu_icon_brown_color diff --git a/src/patches/removals/remove_menu_icon_brown_color.h b/src/patches/removals/remove_menu_icon_brown_color.h new file mode 100644 index 00000000..c3a31b93 --- /dev/null +++ b/src/patches/removals/remove_menu_icon_brown_color.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_menu_icon_brown_color { + +void init_sel_ngc(); + +}// namespace remove_menu_icon_brown_color \ No newline at end of file From ddc6168c0249b8905802a0f621090f2778a16abc Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 10 Jun 2026 12:00:51 -0700 Subject: [PATCH 91/96] Add custom lighting patch --- configs/default-config.txt | 48 +++++++++++ src/config/config.cpp | 96 +++++++++++++++++++++- src/internal/assembly.cpp | 2 + src/internal/assembly.h | 19 +++++ src/patches/custom/custom_theme_lights.cpp | 36 ++++++++ src/patches/custom/custom_theme_lights.h | 8 ++ 6 files changed, 207 insertions(+), 2 deletions(-) create mode 100644 src/patches/custom/custom_theme_lights.cpp create mode 100644 src/patches/custom/custom_theme_lights.h diff --git a/configs/default-config.txt b/configs/default-config.txt index a5895db6..1d6f2c36 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -249,6 +249,7 @@ custom-menu-stage-id: -1 custom-music-id: disabled custom-theme-id: disabled + custom-theme-lights: disabled custom-story-mode-entries: disabled custom-world-count: 10 custom-font-color: disabled @@ -287,6 +288,7 @@ remove-hurry-up-music: disabled remove-ice-fog: disabled remove-intro-cutscene: disabled + remove-menu-icon-brown-color: disabled remove-playpoints: disabled remove-story-cutscenes: disabled remove-tutorial: disabled @@ -1312,3 +1314,49 @@ W10-9: 349, 60, 9 W10-10: 350, 60, 6 } + +# Theme Lights { + 0: 0.80, 0.80, 0.80, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 1: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 2: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 3: 0.28, 0.48, 0.63, 0.60, 0.85, 1.00, 0x2000, 0x6000 + 4: 0.40, 0.40, 0.70, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 5: 0.40, 0.40, 0.70, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 6: 0.50, 0.45, 0.60, 1.00, 1.00, 1.00, 0x7200, 0x4500 + 7: 0.45, 0.40, 0.25, 1.00, 1.00, 1.00, 0x6000, 0x6000 + 8: 0.55, 0.60, 0.85, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 9: 0.30, 0.30, 0.45, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 10: 0.60, 0.70, 0.80, 0.80, 0.80, 0.80, 0xD200, 0x5580 + 11: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 12: 0.40, 0.40, 0.55, 0.00, 0.00, 0.00, 0x2000, 0x6000 + 13: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 14: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x1000, 0x6000 + 15: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 16: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 17: 0.25, 0.25, 0.35, 0.55, 0.40, 0.40, 0x3000, 0x5500 + 18: 0.30, 0.40, 0.60, 0.48, 0.60, 1.00, 0x2180, 0x7500 + 19: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 20: 0.50, 0.50, 0.50, 1.00, 0.90, 0.80, 0x2180, 0x2400 + 21: 0.40, 0.40, 0.40, 0.80, 0.80, 0.80, 0x4E80, 0x6F00 + 22: 0.40, 0.40, 0.45, 0.60, 0.55, 0.70, 0x7000, 0x5500 + 23: 0.30, 0.60, 0.55, 0.75, 1.00, 0.90, 0x2000, 0x6000 + 24: 0.55, 0.50, 0.70, 1.00, 0.70, 0.00, 0x0900, 0x7100 + 25: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0xAA00 + 26: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 27: 0.40, 0.40, 0.40, 0.88, 0.88, 0.84, 0x2680, 0xAA80 + 28: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x1000, 0x6000 + 29: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 30: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x6980, 0x1900 + 31: 0.56, 0.54, 0.60, 1.00, 1.00, 0.96, 0x2800, 0x7800 + 32: 0.25, 0.30, 0.40, 0.55, 0.70, 0.80, 0x5600, 0x7C80 + 33: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x1400, 0x6700 + 34: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x4E80, 0x6F00 + 35: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 36: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0xAA00 + 37: 0.50, 0.50, 0.50, 1.00, 0.90, 0.80, 0x2180, 0x2400 + 38: 0.55, 0.50, 0.70, 1.00, 0.70, 0.00, 0x0900, 0x7100 + 39: 0.30, 0.40, 0.60, 0.48, 0.60, 1.00, 0x2180, 0x7500 + 40: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x2000, 0x6000 + 41: 0.60, 0.60, 0.60, 1.00, 1.00, 1.00, 0x1000, 0x6000 +} + diff --git a/src/config/config.cpp b/src/config/config.cpp index 906a5dc1..fb81bdbb 100644 --- a/src/config/config.cpp +++ b/src/config/config.cpp @@ -146,8 +146,6 @@ static bool parse_csv_ints(char* value, int* out, int count) { return true; } - -// Parses W- static bool parse_world_stage_key(const char* key, int& world_idx, int& stage_idx) { if (key == nullptr || key[0] != 'W') return false; @@ -169,6 +167,35 @@ static bool parse_world_stage_key(const char* key, int& world_idx, int& stage_id return true; } +static bool parse_csv_lighting(char* value, float* floats, int* hexes) { + char* p = value; + + for (int i = 0; i < 6; ++i) { + skip_spaces(p); + floats[i] = mkb::atof(p); + + p = mkb::strchr(p, ','); + if (!p) return false; + p++; + } + + for (int i = 0; i < 2; ++i) { + skip_spaces(p); + + MOD_ASSERT_MSG(p[0] == '0' && (p[1] == 'x' || p[1] == 'X'), + "Lighting angle values must be hex"); + + hexes[i] = parse_hex_value(p); + + if (i + 1 < 2) { + p = mkb::strchr(p, ','); + if (!p) return false; + p++; + } + } + + return true; +} void parse_story_mode_entries(char* buf) { buf = mkb::strchr(buf, '\n') + 1; @@ -342,6 +369,67 @@ void parse_font_colors(char* buf) { } while (buf < end_of_section); } +void parse_theme_lights(char* buf) { + buf = mkb::strchr(buf, '\n') + 1; + + char* end_of_section = mkb::strchr(buf, '}'); + char key[64] = {0}; + char value[128] = {0}; + + do { + char *key_start, *key_end, *end_of_line; + key_start = mkb::strchr(buf, '\t') + 1; + key_end = mkb::strchr(buf, ':'); + end_of_line = mkb::strchr(buf, '\n'); + + MOD_ASSERT_MSG(key_start < key_end, + "Key start after key end, did you start your key with a tab and not spaces?"); + + mkb::strncpy(key, key_start, key_end - key_start); + mkb::strncpy(value, key_end + 2, (end_of_line - key_end) - 2); + + int idx = mkb::atoi(key); + + MOD_ASSERT_MSG(idx >= 0 && idx < main::THEME_LIGHT_COUNT, + "Theme light index out of range"); + + main::CustomThemeLight& light = main::custom_theme_lights[idx]; + + MOD_ASSERT_MSG(!light.set, "Duplicate Theme Light entry"); + + float f[6] = {0}; + int h[2] = {0}; + + MOD_ASSERT_MSG( + parse_csv_lighting(value, f, h), + "Invalid theme light format"); + + for (int i = 0; i < 6; ++i) { + MOD_ASSERT_MSG(f[i] >= 0.0f && f[i] <= 1.0f, + "Lighting RGB value out of range, expected 0.00 to 1.00"); + } + + light.light_group_r = f[0]; + light.light_group_g = f[1]; + light.light_group_b = f[2]; + + light.light_param_r = f[3]; + light.light_param_g = f[4]; + light.light_param_b = f[5]; + + light.xa = static_cast(h[0]); + light.ya = static_cast(h[1]); + + light.set = true; + + buf = end_of_line + 1; + mkb::memset(key, '\0', sizeof(key)); + mkb::memset(value, '\0', sizeof(value)); + } while (buf < end_of_section); + + LOG("Theme Lights loaded at: 0x%X", &main::custom_theme_lights); +} + void parse_function_toggles(char* buf) { // Enters from section parsing, so skip to the next line buf = mkb::strchr(buf, '\n') + 1; @@ -478,6 +566,10 @@ void parse_config() { parse_world_names(section_end); } + else if (STREQ(section, "Theme Lights")) { + parse_theme_lights(section_end); + } + else { LOG("Unknown category %s found in config!", section); } diff --git a/src/internal/assembly.cpp b/src/internal/assembly.cpp index e95f9643..9271c060 100644 --- a/src/internal/assembly.cpp +++ b/src/internal/assembly.cpp @@ -20,4 +20,6 @@ char world_names[WORLD_COUNT][64] = { "Dr. BAD-BOON's Base", }; +CustomThemeLight custom_theme_lights[THEME_LIGHT_COUNT]; + }// namespace main diff --git a/src/internal/assembly.h b/src/internal/assembly.h index df52f9db..f143450b 100644 --- a/src/internal/assembly.h +++ b/src/internal/assembly.h @@ -18,6 +18,25 @@ extern NewStoryStageEntry new_story_entries[WORLD_COUNT][STAGES_PER_WORLD]; extern char world_names[WORLD_COUNT][64]; +static constexpr int THEME_LIGHT_COUNT = 42; + +struct CustomThemeLight { + float light_group_r; + float light_group_g; + float light_group_b; + + float light_param_r; + float light_param_g; + float light_param_b; + + s16 xa; + s16 ya; + + bool set; +}; + +extern CustomThemeLight custom_theme_lights[THEME_LIGHT_COUNT]; + extern "C" { // Assembly overwrite functions diff --git a/src/patches/custom/custom_theme_lights.cpp b/src/patches/custom/custom_theme_lights.cpp new file mode 100644 index 00000000..4fe947f9 --- /dev/null +++ b/src/patches/custom/custom_theme_lights.cpp @@ -0,0 +1,36 @@ +#include "custom_theme_lights.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_theme_lights { + +TICKABLE_DEFINITION(( + .name = "custom-theme-lights", + .description = "Custom lighting patch", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + for (int i = 0; i < main::THEME_LIGHT_COUNT; ++i) { + main::CustomThemeLight& custom = main::custom_theme_lights[i]; + + if (!custom.set) { + continue; + } + + mkb::theme_lights[i].light_group_r = custom.light_group_r; + mkb::theme_lights[i].light_group_g = custom.light_group_g; + mkb::theme_lights[i].light_group_b = custom.light_group_b; + + mkb::theme_lights[i].light_param_r = custom.light_param_r; + mkb::theme_lights[i].light_param_g = custom.light_param_g; + mkb::theme_lights[i].light_param_b = custom.light_param_b; + + mkb::theme_lights[i].xa = custom.xa; + mkb::theme_lights[i].ya = custom.ya; + } +} + +}// namespace custom_theme_lights diff --git a/src/patches/custom/custom_theme_lights.h b/src/patches/custom/custom_theme_lights.h new file mode 100644 index 00000000..7b99a547 --- /dev/null +++ b/src/patches/custom/custom_theme_lights.h @@ -0,0 +1,8 @@ +#pragma once +#include "mkb/mkb.h" + +namespace custom_theme_lights { + +void init_main_loop(); + +}// namespace custom_theme_lights \ No newline at end of file From 36dd090c1978a5120cde14df3a3124526e1ba273 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 10 Jun 2026 15:02:37 -0700 Subject: [PATCH 92/96] Fix type B scroll patch --- .../fix_transparency_type_b_texture_scroll.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp index 19385170..a48913df 100644 --- a/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp +++ b/src/patches/fixes/fix_transparency_type_b_texture_scroll.cpp @@ -11,10 +11,18 @@ TICKABLE_DEFINITION(( .description = "Transparency Type B texture scroll fix", .init_main_loop = init_main_loop, )) -// Always return 'true' for a specific instruction that checks if the texture should -// scroll or not on transparency type B stage models +static patch::Tramp s_g_something_with_texture_scroll_tramp; + +// g_something_with_texture_scroll updates the scroll matrix, but does not enable +// the texture matrix flag used by sorted draw nodes. Transparency type B models +// use sort_always, so we enable texture scrolling before the original function builds +// the matrix so the sorted draw node accounts for it + void init_main_loop() { - patch::write_word(reinterpret_cast(0x802c94f8), PPC_INSTR_LI(PPC_R3, 0x1)); + patch::hook_function(s_g_something_with_texture_scroll_tramp, mkb::g_something_with_texture_scroll, [](mkb::StagedefTextureScroll* tex_scroll) { + mkb::g_something_with_texture_scroll_2(1); + s_g_something_with_texture_scroll_tramp.dest(tex_scroll); + }); } }// namespace fix_transparency_type_b_texture_scroll From d19c927ef22f6ddbd02f82c5b9a49218a513fa42 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 10 Jun 2026 15:49:55 -0700 Subject: [PATCH 93/96] Add patch which removes secondary theme lights --- .../remove_secondary_theme_lights.cpp | 26 +++++++++++++++++++ .../removals/remove_secondary_theme_lights.h | 7 +++++ 2 files changed, 33 insertions(+) create mode 100644 src/patches/removals/remove_secondary_theme_lights.cpp create mode 100644 src/patches/removals/remove_secondary_theme_lights.h diff --git a/src/patches/removals/remove_secondary_theme_lights.cpp b/src/patches/removals/remove_secondary_theme_lights.cpp new file mode 100644 index 00000000..f573ecd8 --- /dev/null +++ b/src/patches/removals/remove_secondary_theme_lights.cpp @@ -0,0 +1,26 @@ +#include "remove_secondary_theme_lights.h" + +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace remove_secondary_theme_lights { + +TICKABLE_DEFINITION(( + .name = "remove-secondary-theme-lights", + .description = "Remove secondary theme lights", + .init_main_loop = init_main_loop, )) + +void init_main_loop() { + // In arrays which check for hardcoded light theme IDs and settings, + // check for themes 0xffffffff instead of Volcanic Magma and Dr. + // BAD-BOON's Base + patch::write_word(reinterpret_cast(0x804551B8), 0xffffffff); + patch::write_word(reinterpret_cast(0x80455208), 0xffffffff); + // Overwrite Dr. BAD-BOON's Base's display/tick functions with + // the defaults + patch::write_word(reinterpret_cast(0x804749C0), 0x802E11BC); + patch::write_word(reinterpret_cast(0x80474868), 0x802E111C); +} + +}// namespace remove_secondary_theme_lights diff --git a/src/patches/removals/remove_secondary_theme_lights.h b/src/patches/removals/remove_secondary_theme_lights.h new file mode 100644 index 00000000..07a98811 --- /dev/null +++ b/src/patches/removals/remove_secondary_theme_lights.h @@ -0,0 +1,7 @@ +#pragma once + +namespace remove_secondary_theme_lights { + +void init_main_loop(); + +}// namespace remove_secondary_theme_lights \ No newline at end of file From 1a20b950d0053c40d79fefde9ac3316112f8a5af Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 10 Jun 2026 16:27:07 -0700 Subject: [PATCH 94/96] Add patches for custom credits/name entry stage IDs --- .../custom/custom_credits_stage_id.cpp | 26 +++++++++++++++++++ src/patches/custom/custom_credits_stage_id.h | 7 +++++ .../custom/custom_name_entry_stage_id.cpp | 26 +++++++++++++++++++ .../custom/custom_name_entry_stage_id.h | 7 +++++ 4 files changed, 66 insertions(+) create mode 100644 src/patches/custom/custom_credits_stage_id.cpp create mode 100644 src/patches/custom/custom_credits_stage_id.h create mode 100644 src/patches/custom/custom_name_entry_stage_id.cpp create mode 100644 src/patches/custom/custom_name_entry_stage_id.h diff --git a/src/patches/custom/custom_credits_stage_id.cpp b/src/patches/custom/custom_credits_stage_id.cpp new file mode 100644 index 00000000..85ba5392 --- /dev/null +++ b/src/patches/custom/custom_credits_stage_id.cpp @@ -0,0 +1,26 @@ +#include "custom_credits_stage_id.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_credits_stage_id { + +int stage_id = 197; + +TICKABLE_DEFINITION(( + .name = "custom-credits-stage-id", + .description = "Custom credits stage ID patch", + .active_value = stage_id, + .lower_bound = 0, + .upper_bound = 420, + .init_main_game = init_main_game, )) + +// In the function which initiates the credits sequence, load our custom stage ID +void init_main_game() { + stage_id = *active_tickable_ptr->active_value;// Get our stage ID + patch::write_word(reinterpret_cast(0x8090A004), PPC_INSTR_LI(PPC_R3, stage_id)); +} + +}// namespace custom_credits_stage_id diff --git a/src/patches/custom/custom_credits_stage_id.h b/src/patches/custom/custom_credits_stage_id.h new file mode 100644 index 00000000..5be5e7fd --- /dev/null +++ b/src/patches/custom/custom_credits_stage_id.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_credits_stage_id { + +void init_main_game(); + +}// namespace custom_credits_stage_id \ No newline at end of file diff --git a/src/patches/custom/custom_name_entry_stage_id.cpp b/src/patches/custom/custom_name_entry_stage_id.cpp new file mode 100644 index 00000000..cc96278f --- /dev/null +++ b/src/patches/custom/custom_name_entry_stage_id.cpp @@ -0,0 +1,26 @@ +#include "custom_name_entry_stage_id.h" + +#include "internal/assembly.h" +#include "internal/patch.h" +#include "internal/tickable.h" +#include "utils/ppcutil.h" + +namespace custom_name_entry_stage_id { + +int stage_id = 200; + +TICKABLE_DEFINITION(( + .name = "custom-name-entry-stage-id", + .description = "Custom name entry stage ID patch", + .active_value = stage_id, + .lower_bound = 0, + .upper_bound = 420, + .init_main_loop = init_main_loop, )) + +// In the function which initiates the name entry sequence, load our custom stage ID +void init_main_loop() { + stage_id = *active_tickable_ptr->active_value;// Get our stage ID + patch::write_word(reinterpret_cast(0x8038ACFC), PPC_INSTR_LI(PPC_R3, stage_id)); +} + +}// namespace custom_name_entry_stage_id diff --git a/src/patches/custom/custom_name_entry_stage_id.h b/src/patches/custom/custom_name_entry_stage_id.h new file mode 100644 index 00000000..8a928dfb --- /dev/null +++ b/src/patches/custom/custom_name_entry_stage_id.h @@ -0,0 +1,7 @@ +#pragma once + +namespace custom_name_entry_stage_id { + +void init_main_loop(); + +}// namespace custom_name_entry_stage_id \ No newline at end of file From 60931b93e3d19cde01f2e93e99cad45dfb1cc177 Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 10 Jun 2026 16:33:29 -0700 Subject: [PATCH 95/96] Update version --- src/internal/version.cpp | 2 +- src/mkb/mkb2.us.lst | 2 +- src/mkb/mkb2_ghidra.h | 3 ++- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/internal/version.cpp b/src/internal/version.cpp index aa8c8c64..d225bd7b 100644 --- a/src/internal/version.cpp +++ b/src/internal/version.cpp @@ -2,7 +2,7 @@ namespace version { -const SemVer WSMOD_VERSION = {1, 0, 6}; +const SemVer WSMOD_VERSION = {2, 0, 0}; s32 compare(const SemVer& v1, const SemVer& v2) { if (v1.major < v2.major) return -1; diff --git a/src/mkb/mkb2.us.lst b/src/mkb/mkb2.us.lst index 752aed91..073bb95d 100644 --- a/src/mkb/mkb2.us.lst +++ b/src/mkb/mkb2.us.lst @@ -4789,7 +4789,7 @@ 802CA1E0:g_draw_start_position_marker 802CA460:g_draw_stage 802CA770:g_draw_collision_triangles -802CA828:FUN_801f45f0 +802CA828:g_draw_transparency_type_a_models 802CA9E4:is_stage_id_348_revolution 802CAA0C:g_special_handler_for_st348_revolution 802CAA2C:g_handle_hardcoded_special_case_stages diff --git a/src/mkb/mkb2_ghidra.h b/src/mkb/mkb2_ghidra.h index bfcfaca2..195e9ccd 100644 --- a/src/mkb/mkb2_ghidra.h +++ b/src/mkb/mkb2_ghidra.h @@ -5903,7 +5903,7 @@ extern "C" { extern undefined * switchdataD_8037ed54; extern pointer switchdataD_8037ed78; extern undefined * switchdataD_8037edf8; - extern struct theme_light theme_lights[41]; + extern struct theme_light theme_lights[42]; extern char init_common_p_lz[17]; extern char init_common_lz[15]; extern struct BmpInfo bmp_infos[25]; @@ -9065,6 +9065,7 @@ extern "C" { void g_draw_start_position_marker(void); void g_draw_stage(void); void g_draw_collision_triangles(void); + void g_draw_transparency_type_a_models(void); bool is_stage_id_348_revolution(void); void g_special_handler_for_st348_revolution(void); void g_handle_hardcoded_special_case_stages(void); From 983c73e8a8d089cb2999bd80e2d8f09e8907339f Mon Sep 17 00:00:00 2001 From: Eucalyptusmoon Date: Wed, 10 Jun 2026 17:57:08 -0700 Subject: [PATCH 96/96] Update config --- configs/default-config.txt | 148 +++++++++++++++++++++-- src/assembly/theme_id_per_stage.s | 2 +- src/patches/custom/custom_font_color.cpp | 2 +- 3 files changed, 138 insertions(+), 14 deletions(-) diff --git a/configs/default-config.txt b/configs/default-config.txt index 1d6f2c36..fe206cc3 100644 --- a/configs/default-config.txt +++ b/configs/default-config.txt @@ -1,4 +1,4 @@ -// This is the config file for Workshop Mod 1.5.0! +// This is the config file for Workshop Mod 2.0.0! // Place this in the root of your game directory, and name it config.txt // It should be in the same folder as the included REL file, mkb2.rel_sample.rel // @@ -28,7 +28,7 @@ // Prevents the world music from being interrupted by the stage select music // in Story Mode. -// remove-music-vol-decrease-on-pause +// remove-volume-decrease-on-pause // // Prevents the music volume from being lowered when the game is paused. @@ -45,7 +45,7 @@ // Challenge mode has infinite lives, and the life counter is converted into // a counter that tracks the number of deaths. -// remove-how-to-play-screen +// remove-tutorial // // Disables the tutorial/ranking sequence that shows up when the player goes // idle at the title screen. @@ -72,7 +72,7 @@ // Draws theme ID data from a per-stage list, defined below, instead of using // the built-in list. -// remove-intro-movie +// remove-intro-cutscene // // Skips the AV logo and intro movie sequence on game start, immediately // skipping to the title screen. @@ -169,7 +169,7 @@ // as well as separate multiple theme IDs which read the same set of background files to load // their own -// fix-bonus-sprite +// fix-bonus-stage-sprite // // Fixes an issue where the 'BONUS STAGE' sprite would disappear upon respawn on a bonus stage // in Practice Mode @@ -232,13 +232,94 @@ // Changes the stage ID used on the main menu. Setting this to -1 will lead to // default behavior (where the menu stage ID also uses more than one stage ID) -// custom-font-color -// font-primary -// font-secondary +// custom-font-colors // -// Changes the colors of most yellow/orange text in the menus to the designated -// primary & secondary color hex codes -// hex codes have a period (.) in front, such as: .ff0000 (for red) +// Changes the colors of most text in the menus and in-game to custom colors based off the +// Font Colors list, defined below. + +// custom-theme-lights +// +// Allows the lighting for each theme ID to be user-defined based off the Theme Lights +// list, defined below. + +// custom-story-mode-entries +// +// Allows the stage IDs, time limits, and difficulties for Story Mode stages to be user-defined +// based off the Story Mode Entries list, defined below. + +// custom-world-names +// +// Allows the names for the 10 worlds in Story Mode to be user-defined based off the +// World Names list, defined below. + +// custom-credits-stage-id +// +// Changes the stage ID used during the credits minigame. + +// custom-name-entry-stage-id +// +// Changes the stage ID used during the name entry sequence. + +// custom-starting-monkey-count +// +// Changes the default number of monkeys unlocked. + +// custom-banana-count-per-1up +// +// Changes the amount of bananas needed for a 1UP. + +// custom-reflection-resolution-width +// +// Changes the width of the image used for stage mirrors. +// Smaller values free up heap and may prevent crashing, but +// do not save on performance. + +// custom-reflection-resolution-height +// +// Changes the height of the image used for stage mirrors. +// Smaller values free up heap and may prevent crashing, but +// do not save on performance. + +// goal-type-sprites +// +// Adds in-game sprites underneath the SCORE which indicate which goal types +// exist on the current stage. + +// fix-spooky-action +// +// Fixes an issue where accumulated floating-point error during collision +// calculations may apply a small undesired position/velocity to the ball. This is +// most noticeable on stages with many, fast, or very rotational animations. + +// remove-challenge-game-settings +// +// Prevents the Game Settings screen which allows the player to set monkey +// count from appearing when starting Challenge Mode. Useful for locking +// the monkey count or when using the death counter patch. + +// remove-menu-icon-brown-color +// +// Prevents icons on the Main Game Select and Number of Players screen from +// forcefully being turned brown, regardless of their texture's color. + +// remove-secondary-theme-lights +// +// Disables the hardcoded secondary lighting effects in the Volcanic Magma and +// Dr. BAD-BOON's Base themes. Useful for custom lighting. + +// autosave-on-by-default +// +// Enables autosave by default, not requiring the user to enable it themselves. + +// smb1-score-count +// +// Makes the Main Game score sprite act like SMB1's, playing the sound effect +// as well. + +// master-unlocked-by-default +// +// Unlocks Master by default. + // ---------------------------------------------------------------------------- @@ -247,12 +328,15 @@ # REL Patches { custom-menu-stage-id: -1 + custom-credits-stage-id: 197 + custom-name-entry-stage-id: 200 custom-music-id: disabled custom-theme-id: disabled custom-theme-lights: disabled custom-story-mode-entries: disabled custom-world-count: 10 - custom-font-color: disabled + custom-world-names: disabled + custom-font-colors: disabled custom-starting-monkey-count: 3 custom-banana-count-per-1up: 100 custom-reflection-resolution-width: 640 @@ -290,6 +374,7 @@ remove-intro-cutscene: disabled remove-menu-icon-brown-color: disabled remove-playpoints: disabled + remove-secondary-theme-lights: disabled remove-story-cutscenes: disabled remove-tutorial: disabled remove-volume-decrease-on-pause: disabled @@ -332,6 +417,11 @@ monkey-tennis: enabled } +// Font color mapping. +// The default, vanilla font colors are provided for your convenience. +// Each color is formatted as a hex RGB value. +// Requires the patch 'custom-font-colors' to be enabled. + # Font Colors { menu-primary: 0xFFC000 menu-secondary: 0xFFFF00 @@ -1212,6 +1302,14 @@ STAGE 420: 61 } +// Story Mode mapping. +// Regardless of custom world count, all 100 default entries +// should be present. +// Format is as follows: +// ,