From f07f5e54333d21a978c9c3e3dce0696a96c20122 Mon Sep 17 00:00:00 2001 From: Isaac0-dev <62234577+Isaac0-dev@users.noreply.github.com> Date: Sat, 28 Oct 2023 09:42:27 +1000 Subject: [PATCH] custom level fixes and fixes from other pr (#483) clean up custom level code fixed a bug where custom level course numbers weren't used by dynos warps removed a bunch of unused dynos code fix demos triggering incorrectly allowed the right Ctrl key to be used when opening the in game console fixed a softlock that was possible to experience when talking to the snowman in CCM fixed the bug where you can permanently lose your cap (bug created by my own PR from beta 32) fix the moderator feature I made a while back; I am amazed it even worked at all before fixed dynos warp initial actions being skipped (read ec8aabc for explanation) completely changed the way star names and course names work --- autogen/convert_constants.py | 2 +- autogen/convert_functions.py | 2 + autogen/convert_structs.py | 6 +- autogen/lua_definitions/functions.lua | 81 ++- data/dynos.c.h | 3 +- data/dynos.cpp.h | 35 +- data/dynos_bin_vtx.cpp | 2 +- data/dynos_c.cpp | 9 +- data/dynos_level.cpp | 590 ++------------- data/dynos_main.cpp | 22 - data/dynos_mgr_anim.cpp | 2 +- data/dynos_mgr_builtin.cpp | 52 +- data/dynos_mgr_lvl.cpp | 4 +- data/dynos_mgr_models.cpp | 4 - data/dynos_opt.cpp | 749 -------------------- data/dynos_opt_config.cpp | 67 -- data/dynos_opt_cont.cpp | 75 -- data/dynos_opt_render.cpp | 309 -------- data/dynos_opt_vanilla.cpp | 159 ----- data/dynos_opt_vanilla_c.c | 72 -- data/dynos_warps.cpp | 111 +-- docs/lua/functions-4.md | 64 ++ docs/lua/functions-5.md | 184 ++++- docs/lua/functions.md | 12 +- src/engine/surface_load.c | 81 +-- src/game/behaviors/camera_lakitu.inc.c | 4 +- src/game/behaviors/snowman.inc.c | 17 +- src/game/behaviors/spawn_star.inc.c | 10 +- src/game/camera.c | 12 +- src/game/game_init.c | 1 - src/game/hardcoded.c | 5 +- src/game/ingame_menu.c | 120 +--- src/game/interaction.c | 9 +- src/game/level_info.c | 132 ++-- src/game/level_info.h | 2 + src/game/level_update.c | 46 +- src/game/level_update.h | 2 +- src/game/mario.c | 1 + src/game/mario_actions_cutscene.c | 27 +- src/game/options_menu.h | 8 - src/game/paintings.c | 8 +- src/game/save_file.c | 8 +- src/menu/star_select.c | 29 +- src/pc/chat_commands.c | 34 +- src/pc/cliopts.c | 2 +- src/pc/configfile.c | 4 +- src/pc/crash_handler.c | 9 +- src/pc/discord/discord_activity.c | 4 +- src/pc/djui/djui_panel.h | 2 + src/pc/lua/smlua_functions_autogen.c | 234 +++++- src/pc/lua/smlua_utils.c | 15 +- src/pc/lua/utils/smlua_collision_utils.c | 13 + src/pc/lua/utils/smlua_collision_utils.h | 4 + src/pc/lua/utils/smlua_level_utils.c | 11 + src/pc/lua/utils/smlua_level_utils.h | 3 +- src/pc/lua/utils/smlua_text_utils.c | 232 +++--- src/pc/lua/utils/smlua_text_utils.h | 21 + src/pc/mods/mods.c | 1 + src/pc/network/moderator_list.c | 2 - src/pc/network/network.c | 4 +- src/pc/network/network_player.h | 1 + src/pc/network/network_utils.c | 3 +- src/pc/network/packets/packet_chat.c | 2 +- src/pc/network/packets/packet_command_mod.c | 79 +-- src/pc/network/packets/packet_object.c | 4 +- src/pc/pc_main.c | 223 ++---- src/pc/pc_main.h | 60 ++ src/pc/utils/misc.c | 23 +- 68 files changed, 1262 insertions(+), 2866 deletions(-) delete mode 100644 data/dynos_opt.cpp delete mode 100644 data/dynos_opt_config.cpp delete mode 100644 data/dynos_opt_cont.cpp delete mode 100644 data/dynos_opt_render.cpp delete mode 100644 data/dynos_opt_vanilla.cpp delete mode 100644 data/dynos_opt_vanilla_c.c delete mode 100644 src/game/options_menu.h diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index 020e0312..3993363c 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -166,7 +166,7 @@ def process_define(filename, line): continue p = re.sub(r'0x[a-fA-F0-9]+', '', p) if re.search('[a-z]', p) != None and 'VERSION_TEXT' not in line: - if 'gCurrentObject' not in line: + if 'gCurrentObject' not in line and 'gNetworkType' not in line: print('UNRECOGNIZED DEFINE: ' + line) return None diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 73fc9370..5065228d 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -102,12 +102,14 @@ override_disallowed_functions = { "src/game/obj_behaviors.c": [ "debug_" ], "src/game/obj_behaviors_2.c": [ "wiggler_jumped_on_attack_handler", "huge_goomba_weakly_attacked" ], "src/game/spawn_sound.c": [ "spawner" ], + "src/game/level_info.h": [ "_name_table" ], "src/pc/lua/utils/smlua_obj_utils.h": [ "spawn_object_remember_field", "set_exclamation_box_new_contents", "get_exclamation_box_new_contents_pointer", "get_exclamation_box_new_contents_size" ], "src/game/camera.h": [ "update_camera", "init_camera", "stub_camera", "^reset_camera", "move_point_along_spline" ], "src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room" ], "src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override", "audio_custom_shutdown"], "src/pc/djui/djui_hud_utils.h": [ "djui_hud_render_texture", "djui_hud_render_texture_raw", "djui_hud_render_texture_tile", "djui_hud_render_texture_tile_raw" ], "src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ], + "src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_reset_all" ], "src/pc/lua/utils/smlua_anim_utils.h": [ "smlua_anim_util_reset", "smlua_anim_util_register_animation" ], "src/pc/network/lag_compensation.h": [ "lag_compensation_clear", "lag_compensation_store" ] } diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 65343d78..b3b7045f 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -79,7 +79,7 @@ override_field_mutable = { override_field_invisible = { "Mod": [ "files" ], "MarioState": [ "visibleToEnemies" ], - "NetworkPlayer": [ "gag"], + "NetworkPlayer": [ "gag", "moderator"], "GraphNode": [ "_guard1", "_guard2" ], } @@ -371,11 +371,11 @@ def build_struct(struct): if sid in override_field_invisible: if fid in override_field_invisible[sid]: continue - + version = None row = [] - + startStr = '' endStr = ' },' if fid in override_field_version_excludes: diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index dfa50e0b..7e9f255a 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -8190,6 +8190,22 @@ function smlua_audio_utils_reset_all() -- ... end +--- @param x number +--- @param y number +--- @param z number +--- @return Surface +function collision_find_ceil(x, y, z) + -- ... +end + +--- @param x number +--- @param y number +--- @param z number +--- @return Surface +function collision_find_floor(x, y, z) + -- ... +end + --- @param startX number --- @param startY number --- @param startZ number @@ -8254,6 +8270,12 @@ function smlua_level_util_get_info(levelNum) -- ... end +--- @param courseNum integer +--- @return CustomLevelInfo +function smlua_level_util_get_info_from_course_num(courseNum) + -- ... +end + --- @param shortName string --- @return CustomLevelInfo function smlua_level_util_get_info_from_short_name(shortName) @@ -9096,6 +9118,35 @@ function spawn_sync_object(behaviorId, modelId, x, y, z, objSetupFunction) -- ... end +--- @param courseNum integer +--- @param actNum integer +--- @return string +function smlua_text_utils_act_name_get(courseNum, actNum) + -- ... +end + +--- @param courseNum integer +--- @param actNum integer +--- @return boolean +function smlua_text_utils_act_name_is_modified(courseNum, actNum) + -- ... +end + +--- @param courseNum integer +--- @param actNum integer +--- @param name string +--- @return nil +function smlua_text_utils_act_name_replace(courseNum, actNum, name) + -- ... +end + +--- @param courseNum integer +--- @param actNum integer +--- @return nil +function smlua_text_utils_act_name_reset(courseNum, actNum) + -- ... +end + --- @param name string --- @return nil function smlua_text_utils_castle_secret_stars_replace(name) @@ -9115,6 +9166,31 @@ function smlua_text_utils_course_acts_replace(courseNum, courseName, act1, act2, -- ... end +--- @param courseNum integer +--- @return string +function smlua_text_utils_course_name_get(courseNum) + -- ... +end + +--- @param courseNum integer +--- @return integer +function smlua_text_utils_course_name_mod_index(courseNum) + -- ... +end + +--- @param courseNum integer +--- @param name string +--- @return nil +function smlua_text_utils_course_name_replace(courseNum, name) + -- ... +end + +--- @param courseNum integer +--- @return nil +function smlua_text_utils_course_name_reset(courseNum) + -- ... +end + --- @param dialogId DialogId --- @param unused integer --- @param linesPerBox integer @@ -9138,11 +9214,6 @@ function smlua_text_utils_get_language() -- ... end ---- @return nil -function smlua_text_utils_reset_all() - -- ... -end - --- @param courseNum integer --- @param courseName string --- @return nil diff --git a/data/dynos.c.h b/data/dynos.c.h index e63c1cd6..a632cbc1 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -12,7 +12,6 @@ void *dynos_swap_cmd(void *cmd); // -- built in -- // void *dynos_update_cmd(void *cmd); void dynos_update_gfx(); -void dynos_update_opt(void *pad); s32 dynos_tex_import(void **output, void *ptr, s32 tile, void *grapi, void **hashmap, void *pool, s32 *poolpos, s32 poolsize); void dynos_gfx_swap_animations(void *ptr); @@ -59,7 +58,7 @@ const char* dynos_level_get_token(u32 index); Trajectory* dynos_level_get_trajectory(const char* name); void dynos_level_load_background(void *ptr); u64 dynos_level_cmd_get(void *cmd, u64 offset); -void dynos_level_cmd_next(void *cmd, u64 cmdsize); +void dynos_level_cmd_next(void *cmd); void dynos_level_parse_script(const void *script, s32 (*aPreprocessFunction)(u8, void *)); void* dynos_level_get_script(s32 level); s32 dynos_level_get_mod_index(s32 level); diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index b07ea6b5..aff4a2c6 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -656,6 +656,11 @@ struct BuiltinTexInfo { s32 bitSize; }; +struct LvlCmd { + u8 mType; + u8 mSize; +}; + // // Utils // @@ -783,23 +788,6 @@ void DynOS_Mod_Update(); void DynOS_Mod_Shutdown(); void DynOS_ReturnToMainMenu(); -// -// Opt -// - -s32 DynOS_Opt_GetValue(const String &aName); -void DynOS_Opt_SetValue(const String &aName, s32 aValue); -void DynOS_Opt_AddAction(const String &aFuncName, bool (*aFuncPtr)(const char *), bool aOverwrite); -void DynOS_Opt_Init(); -void DynOS_Opt_InitVanilla(DynosOption *&aOptionsMenu); -void DynOS_Opt_Update(OSContPad *aPad); -bool DynOS_Opt_ControllerUpdate(DynosOption *aOpt, void *aData); -s32 DynOS_Opt_ControllerGetKeyPressed(); -void DynOS_Opt_LoadConfig(DynosOption *aMenu); -void DynOS_Opt_SaveConfig(DynosOption *aMenu); -void DynOS_Opt_DrawMenu(DynosOption *aCurrentOption, DynosOption *aCurrentMenu, DynosOption *aOptionsMenu, DynosOption *aDynosMenu); -void DynOS_Opt_DrawPrompt(DynosOption *aCurrentMenu, DynosOption *aOptionsMenu, DynosOption *aDynosMenu); - // // Gfx // @@ -826,22 +814,18 @@ s32 DynOS_String_Width(const u8 *aStr64); // Levels // -s32 DynOS_Level_GetCount(); -const s32 *DynOS_Level_GetList(); -s32 DynOS_Level_GetCourse(s32 aLevel); +void DynOS_Level_Init(); +s8 DynOS_Level_GetCourse(s32 aLevel); void DynOS_Level_Override(void* originalScript, void* newScript, s32 modIndex); void DynOS_Level_Unoverride(); const void *DynOS_Level_GetScript(s32 aLevel); s32 DynOS_Level_GetModIndex(s32 aLevel); bool DynOS_Level_IsVanillaLevel(s32 aLevel); -const u8 *DynOS_Level_GetName(s32 aLevel, bool aDecaps, bool aAddCourseNumber); -const u8 *DynOS_Level_GetActName(s32 aLevel, s32 aAct, bool aDecaps, bool aAddStarNumber); -const u8 *DynOS_Level_GetAreaName(s32 aLevel, s32 aArea, bool aDecaps); s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId); s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea); s16 *DynOS_Level_GetWarpDeath(s32 aLevel, s32 aArea); u64 DynOS_Level_CmdGet(void *aCmd, u64 aOffset); -void *DynOS_Level_CmdNext(void *aCmd, u64 aCmdSize); +LvlCmd *DynOS_Level_CmdNext(LvlCmd *aCmd); void DynOS_Level_ParseScript(const void *aScript, s32 (*aPreprocessFunction)(u8, void *)); // @@ -854,8 +838,6 @@ bool DynOS_Warp_ToLevel(s32 aLevel, s32 aArea, s32 aAct); bool DynOS_Warp_RestartLevel(); bool DynOS_Warp_ExitLevel(s32 aDelay); bool DynOS_Warp_ToCastle(s32 aLevel); -void DynOS_Warp_SetParam(s32 aLevel, s32 aIndex); -const char *DynOS_Warp_GetParamName(s32 aLevel, s32 aIndex); // // Builtin @@ -988,7 +970,6 @@ u32 DynOS_Model_GetIdFromAsset(void* asset); u32 DynOS_Model_GetIdFromGraphNode(struct GraphNode* aNode); void DynOS_Model_OverwriteSlot(u32 srcSlot, u32 dstSlot); void DynOS_Model_ClearPool(enum ModelPool aModelPool); -void DynOS_Model_Update(); // // Bin diff --git a/data/dynos_bin_vtx.cpp b/data/dynos_bin_vtx.cpp index d1cdc406..a42767f2 100644 --- a/data/dynos_bin_vtx.cpp +++ b/data/dynos_bin_vtx.cpp @@ -10,7 +10,7 @@ extern "C" { static inline bool ShouldUseF32Vtx(DataNode* aNode) { for (u32 i = 0; i != aNode->mSize; ++i) { for (u32 j = 0; j != 3; ++j) { - if (aNode->mData[i].n.ob[j] < -0x7FFF || + if (aNode->mData[i].n.ob[j] < -0x7FFF || aNode->mData[i].n.ob[j] > +0x7FFF) { return true; } diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index 3d3da3f2..ff1d9a0d 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -14,14 +14,9 @@ void *dynos_update_cmd(void *cmd) { } void dynos_update_gfx() { - DynOS_Model_Update(); return DynOS_UpdateGfx(); } -void dynos_update_opt(void *pad) { - return DynOS_UpdateOpt(pad); -} - s32 dynos_tex_import(void **output, void *ptr, s32 tile, void *grapi, void **hashmap, void *pool, s32 *poolpos, s32 poolsize) { return DynOS_Tex_Import(output, ptr, tile, grapi, hashmap, pool, (u32 *) poolpos, (u32) poolsize); } @@ -185,8 +180,8 @@ u64 dynos_level_cmd_get(void *cmd, u64 offset) { return DynOS_Level_CmdGet(cmd, offset); } -void dynos_level_cmd_next(void *cmd, u64 cmdsize) { - DynOS_Level_CmdNext(cmd, cmdsize); +void dynos_level_cmd_next(void *cmd) { + DynOS_Level_CmdNext((LvlCmd*) cmd); } void dynos_level_parse_script(const void *script, s32 (*aPreprocessFunction)(u8, void *)) { diff --git a/data/dynos_level.cpp b/data/dynos_level.cpp index 983f80ff..181a02ef 100644 --- a/data/dynos_level.cpp +++ b/data/dynos_level.cpp @@ -5,10 +5,6 @@ extern "C" { #include "levels/scripts.h" #include "pc/lua/utils/smlua_level_utils.h" -#ifdef VERSION_EU -#include "eu_translation.h" -#endif - } // @@ -20,20 +16,6 @@ extern const BehaviorScript *sWarpBhvSpawnTable[]; #include "engine/level_script.h" } -#define DYNOS_LEVEL_TEXT_EMPTY "" -#define DYNOS_LEVEL_TEXT_CASTLE "CASTLE" -#define DYNOS_LEVEL_TEXT_BOWSER_1 "BOWSER 1" -#define DYNOS_LEVEL_TEXT_BOWSER_2 "BOWSER 2" -#define DYNOS_LEVEL_TEXT_BOWSER_3 "BOWSER 3" -#define DYNOS_LEVEL_TEXT_100_COINS_STAR "100 COINS STAR" -#define DYNOS_LEVEL_TEXT_RED_COINS_STAR "RED COINS STAR" -#define DYNOS_LEVEL_TEXT_ONE_SECRET_STAR "ONE OF THE CASTLE'S SECRET STARS!" - -static void SetConvertedTextToBuffer(u8 *aBuffer, const char *aText) { - u8 *_ConvertedText = DynOS_String_Convert(aText, false); - memcpy(aBuffer, _ConvertedText, DynOS_String_Length(_ConvertedText) + 1); -} - // // Data // @@ -59,18 +41,18 @@ struct DynosLevelScript { #define DYNOS_LEVEL_MOD_INDEX_VANILLA (-1) static DynosLevelScript sDynosLevelScripts[LEVEL_COUNT] = { { NULL, DYNOS_LEVEL_MOD_INDEX_VANILLA } }; -static void *sDynosLevelScriptsOriginal[LEVEL_COUNT] = { NULL }; +extern void *gDynosLevelScriptsOriginal[LEVEL_COUNT]; static Array sDynosLevelWarps[LEVEL_COUNT] = { Array() }; -static Array sDynosLevelList = Array(); // Ordered by Course Id, COURSE_NONE excluded u64 DynOS_Level_CmdGet(void *aCmd, u64 aOffset) { u64 _Offset = (((aOffset) & 3llu) | (((aOffset) & ~3llu) << (sizeof(void *) >> 3llu))); return *((u64 *) (u64(aCmd) + _Offset)); } -void *DynOS_Level_CmdNext(void *aCmd, u64 aCmdSize) { +LvlCmd *DynOS_Level_CmdNext(LvlCmd *aCmd) { + u64 aCmdSize = aCmd->mSize; u64 _Offset = (((aCmdSize) & 3llu) | (((aCmdSize) & ~3llu) << (sizeof(void *) >> 3llu))); - return (void *) (u64(aCmd) + _Offset); + return (LvlCmd*) (u64(aCmd) + _Offset); } void DynOS_Level_ParseScript(const void *aScript, s32 (*aPreprocessFunction)(u8, void *)); @@ -83,15 +65,7 @@ static s32 DynOS_Level_PreprocessMasterScript(u8 aType, void *aCmd) { static bool sDynosScriptExecLevelTable = false; static s32 sDynosLevelNum = -1; - if (!sDynosScriptExecLevelTable) { - - // JUMP_LINK - if (aType == 0x06) { - sDynosScriptExecLevelTable = true; - return 0; - } - - } else { + if (sDynosScriptExecLevelTable) { // JUMP_IF if (aType == 0x0C) { @@ -105,21 +79,19 @@ static s32 DynOS_Level_PreprocessMasterScript(u8 aType, void *aCmd) { if (sDynosLevelNum >= 0 && sDynosLevelNum < LEVEL_COUNT && !sDynosLevelScripts[sDynosLevelNum].mLevelScript) { sDynosLevelScripts[sDynosLevelNum].mLevelScript = _Script; sDynosLevelScripts[sDynosLevelNum].mModIndex = DYNOS_LEVEL_MOD_INDEX_VANILLA; - sDynosLevelScriptsOriginal[sDynosLevelNum] = _Script; + gDynosLevelScriptsOriginal[sDynosLevelNum] = _Script; } sDynosLevelNum = -1; return 2; } - // EXIT - if (aType == 0x02) { - return 3; - } - - // SLEEP - if (aType == 0x03) { + // EXIT or SLEEP + if (aType == 0x02 || aType == 0x03) { return 3; } + } else if (aType == 0x06) { // JUMP_LINK + sDynosScriptExecLevelTable = true; + return 0; } return 0; } @@ -184,8 +156,7 @@ static s32 DynOS_Level_PreprocessScript(u8 aType, void *aCmd) { } } - // SLEEP - // SLEEP_BEFORE_EXIT + // SLEEP or SLEEP_BEFORE_EXIT else if (aType == 0x03 || aType == 0x04) { return 3; } @@ -194,30 +165,19 @@ static s32 DynOS_Level_PreprocessScript(u8 aType, void *aCmd) { } // Runs only once -static void DynOS_Level_Init() { +void DynOS_Level_Init() { static bool sInited = false; if (!sInited) { - // Level scripts - DynOS_Level_ParseScript(level_main_scripts_entry, DynOS_Level_PreprocessMasterScript); - // Level warps for (sDynosCurrentLevelNum = 0; sDynosCurrentLevelNum != LEVEL_COUNT; ++sDynosCurrentLevelNum) { + sDynosLevelScripts[sDynosCurrentLevelNum].mLevelScript = gDynosLevelScriptsOriginal[sDynosCurrentLevelNum]; + sDynosLevelScripts[sDynosCurrentLevelNum].mModIndex = DYNOS_LEVEL_MOD_INDEX_VANILLA; if (sDynosLevelScripts[sDynosCurrentLevelNum].mLevelScript) { DynOS_Level_ParseScript(sDynosLevelScripts[sDynosCurrentLevelNum].mLevelScript, DynOS_Level_PreprocessScript); } } - // Level list ordered by course id - for (s32 i = COURSE_MIN; i <= COURSE_MAX; ++i) { - if (i == COURSE_CAKE_END) continue; - for (s32 j = 1; j != LEVEL_COUNT; ++j) { - if (get_level_course_num(j - 1) == i) { - sDynosLevelList.Add(j); - } - } - } - // Done sInited = true; } @@ -227,20 +187,8 @@ static void DynOS_Level_Init() { // Common // -s32 DynOS_Level_GetCount() { - DynOS_Level_Init(); - return sDynosLevelList.Count(); -} - -const s32 *DynOS_Level_GetList() { - DynOS_Level_Init(); - return sDynosLevelList.begin(); -} - -s32 DynOS_Level_GetCourse(s32 aLevel) { - u32 index = aLevel - 1; - if (index >= LEVEL_COUNT) { return COURSE_NONE; } - return (s32) gLevelToCourseNumTable[index]; +s8 DynOS_Level_GetCourse(s32 aLevel) { + return get_level_course_num(aLevel); } void DynOS_Level_Override(void* originalScript, void* newScript, s32 modIndex) { @@ -260,7 +208,7 @@ void DynOS_Level_Unoverride() { for (s32 i = 0; i < LEVEL_COUNT; i++) { sDynosCurrentLevelNum = i; sDynosLevelWarps[i].Clear(); - sDynosLevelScripts[i].mLevelScript = sDynosLevelScriptsOriginal[i]; + sDynosLevelScripts[i].mLevelScript = gDynosLevelScriptsOriginal[i]; sDynosLevelScripts[i].mModIndex = DYNOS_LEVEL_MOD_INDEX_VANILLA; DynOS_Level_ParseScript(sDynosLevelScripts[i].mLevelScript, DynOS_Level_PreprocessScript); } @@ -289,205 +237,21 @@ s32 DynOS_Level_GetModIndex(s32 aLevel) { } bool DynOS_Level_IsVanillaLevel(s32 aLevel) { - if (aLevel >= 0 && aLevel < LEVEL_COUNT) { - return sDynosLevelScripts[aLevel].mLevelScript == sDynosLevelScriptsOriginal[aLevel]; + DynOS_Level_Init(); + + if (aLevel >= LEVEL_MIN && aLevel < LEVEL_COUNT) { + return sDynosLevelScripts[aLevel].mLevelScript == gDynosLevelScriptsOriginal[aLevel]; } return false; } -// -// Course name -// - -const u8 *DynOS_Level_GetName(s32 aLevel, bool aDecaps, bool aAddCourseNumber) { - DynOS_Level_Init(); - static u8 sBuffer[256]; - memset(sBuffer, 0xFF, 256); - s32 _Course = DynOS_Level_GetCourse(aLevel); - - // Level name - if (aLevel == LEVEL_BOWSER_1) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_BOWSER_1); - } else if (aLevel == LEVEL_BOWSER_2) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_BOWSER_2); - } else if (aLevel == LEVEL_BOWSER_3) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_BOWSER_3); - } else if (_Course < COURSE_BOB) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_CASTLE); - } else if (_Course >= COURSE_CAKE_END) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_CASTLE); - } else { -#ifdef VERSION_EU - const u8 *_CourseName = ((const u8 **) course_name_table_eu_en)[_Course - COURSE_BOB] + 3; -#else - const u8 *_CourseName = ((const u8 **) seg2_course_name_table)[_Course - COURSE_BOB] + 3; -#endif - memcpy(sBuffer, _CourseName, DynOS_String_Length(_CourseName)); - } - - // Decaps - if (aDecaps) { - DynOS_String_Decapitalize(sBuffer); - } - - // Course number - if (aAddCourseNumber && (_Course >= COURSE_BOB) && (_Course <= COURSE_STAGES_MAX)) { - memmove(sBuffer + 5, sBuffer, DynOS_String_Length(sBuffer)); - sBuffer[0] = ((_Course / 10) == 0 ? 158 : (_Course / 10)); - sBuffer[1] = (_Course % 10); - sBuffer[2] = 158; - sBuffer[3] = 159; - sBuffer[4] = 158; - } - - return sBuffer; -} - -// -// Act/Star name -// - -const u8 *DynOS_Level_GetActName(s32 aLevel, s32 aAct, bool aDecaps, bool aAddStarNumber) { - DynOS_Level_Init(); - static u8 sBuffer[256]; - memset(sBuffer, 0xFF, 256); - s32 _Course = DynOS_Level_GetCourse(aLevel); - - // Star name - if (_Course < COURSE_BOB) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_ONE_SECRET_STAR); - } else if (aLevel == LEVEL_BITDW) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_RED_COINS_STAR); - } else if (aLevel == LEVEL_BITFS) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_RED_COINS_STAR); - } else if (aLevel == LEVEL_BITS) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_RED_COINS_STAR); - } else if (_Course > COURSE_STAGES_MAX) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_EMPTY); - } else if (aAct >= 7) { - SetConvertedTextToBuffer(sBuffer, DYNOS_LEVEL_TEXT_100_COINS_STAR); - } else { -#ifdef VERSION_EU - const u8 *_ActName = ((const u8 **) act_name_table_eu_en)[(_Course - COURSE_BOB) * 6 + (aAct - 1)]; -#else - const u8 *_ActName = ((const u8 **) seg2_act_name_table)[(_Course - COURSE_BOB) * 6 + (aAct - 1)]; -#endif - memcpy(sBuffer, _ActName, DynOS_String_Length(_ActName)); - } - - // Decaps - if (aDecaps) { - DynOS_String_Decapitalize(sBuffer); - } - - // Star number - if (aAddStarNumber && (_Course >= COURSE_BOB) && (_Course <= COURSE_STAGES_MAX)) { - memmove(sBuffer + 5, sBuffer, DynOS_String_Length(sBuffer)); - sBuffer[0] = ((aAct / 10) == 0 ? 158 : (aAct / 10)); - sBuffer[1] = (aAct % 10); - sBuffer[2] = 158; - sBuffer[3] = 159; - sBuffer[4] = 158; - } - - return sBuffer; -} - -const u8 *DynOS_Level_GetAreaName(s32 aLevel, s32 aArea, bool aDecaps) { - DynOS_Level_Init(); - static const char *sAreaNamesPerLevel[][4] = { - { "", "", "", "" }, - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* BoB */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* WF */ - { "MAIN AREA", "SUNKEN SHIP", "NOT AVAILABLE", "NOT AVAILABLE" }, /* JRB */ - { "MAIN AREA", "COTTAGE SLIDE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* CCM */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* BBH */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* HMC */ - { "MAIN AREA", "VOLCANO", "NOT AVAILABLE", "NOT AVAILABLE" }, /* LLL */ - { "MAIN AREA", "PYRAMID", "EYEROCK'S ROOM", "NOT AVAILABLE" }, /* SSL */ - { "MAIN AREA", "DOCKS", "NOT AVAILABLE", "NOT AVAILABLE" }, /* DDD */ - { "MAIN AREA", "IGLOO", "NOT AVAILABLE", "NOT AVAILABLE" }, /* SL */ - { "MAIN AREA", "DOWNTOWN", "NOT AVAILABLE", "NOT AVAILABLE" }, /* WDW */ - { "MAIN AREA", "SECRET SLIDE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* TTM */ - { "HUGE ISLAND", "TINY ISLAND", "WIGGLER'S ROOM", "NOT AVAILABLE" }, /* THI */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* TTC */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* RR */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* BITDW */ - { "BOWSER BATTLE", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* Bowser 1 */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* BITFS */ - { "BOWSER BATTLE", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* Bowser 2 */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* BITS */ - { "BOWSER BATTLE", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* Bowser 3 */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* PSS */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* TOTWC */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* COTMC */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* VCUTM */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* WMOTR */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* SA */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* Castle grounds */ - { "FIRST FLOOR", "SECOND FLOOR", "BASEMENT", "NOT AVAILABLE" }, /* Castle inside */ - { "MAIN AREA", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* Castle courtyard */ - { "ENDING", "NOT AVAILABLE", "NOT AVAILABLE", "NOT AVAILABLE" }, /* Ending */ - }; - static u8 sBuffer[256]; - memset(sBuffer, 0xFF, 256); - - // Area name - switch (aLevel) { - case LEVEL_BOB: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[1][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_WF: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[2][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_JRB: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[3][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_CCM: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[4][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BBH: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[5][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_HMC: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[6][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_LLL: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[7][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_SSL: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[8][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_DDD: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[9][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_SL: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[10][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_WDW: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[11][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_TTM: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[12][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_THI: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[13][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_TTC: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[14][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_RR: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[15][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BITDW: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[16][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BOWSER_1: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[17][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BITFS: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[18][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BOWSER_2: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[19][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BITS: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[20][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_BOWSER_3: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[21][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_PSS: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[22][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_TOTWC: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[23][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_COTMC: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[24][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_VCUTM: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[25][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_WMOTR: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[26][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_SA: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[27][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_CASTLE_GROUNDS: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[28][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_CASTLE: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[29][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_CASTLE_COURTYARD: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[30][MIN(MAX(aArea - 1, 0), 3)]); break; - case LEVEL_ENDING: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[31][MIN(MAX(aArea - 1, 0), 3)]); break; - default: SetConvertedTextToBuffer(sBuffer, sAreaNamesPerLevel[0][MIN(MAX(aArea - 1, 0), 3)]); break; - } - - // Decaps - if (aDecaps) { - DynOS_String_Decapitalize(sBuffer); - } - return sBuffer; -} - // // Level Script Preprocessing -// By default, // - Ifs are always true // - Skips are always false // - Loops break after the first loop // -struct LvlCmd { - u8 mType; - u8 mSize; -}; - struct Stack { u64 mData[32]; s32 mBaseIndex; @@ -512,7 +276,7 @@ static T StackPop(Stack& aStack) { } static LvlCmd *DynOS_Level_CmdExecute(Stack &aStack, LvlCmd *aCmd) { - StackPush(aStack, DynOS_Level_CmdNext(aCmd, aCmd->mSize)); + StackPush(aStack, DynOS_Level_CmdNext(aCmd)); StackPush(aStack, aStack.mBaseIndex); aStack.mBaseIndex = aStack.mTopIndex; return (LvlCmd *) DynOS_Level_CmdGet(aCmd, 12); @@ -529,20 +293,12 @@ static LvlCmd *DynOS_Level_CmdExit(Stack &aStack, LvlCmd *aCmd) { return StackPop(aStack); } -static LvlCmd *DynOS_Level_CmdSleep(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSleepBeforeExit(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - static LvlCmd *DynOS_Level_CmdJump(Stack &aStack, LvlCmd *aCmd) { return (LvlCmd *) DynOS_Level_CmdGet(aCmd, 4); } static LvlCmd *DynOS_Level_CmdJumpLink(Stack &aStack, LvlCmd *aCmd) { - StackPush(aStack, DynOS_Level_CmdNext(aCmd, aCmd->mSize)); + StackPush(aStack, DynOS_Level_CmdNext(aCmd)); return (LvlCmd *) DynOS_Level_CmdGet(aCmd, 4); } @@ -551,248 +307,40 @@ static LvlCmd *DynOS_Level_CmdReturn(Stack &aStack, UNUSED LvlCmd *aCmd) { } static LvlCmd *DynOS_Level_CmdJumpLinkPushArg(Stack &aStack, LvlCmd *aCmd) { - StackPush(aStack, DynOS_Level_CmdNext(aCmd, aCmd->mSize)); + StackPush(aStack, DynOS_Level_CmdNext(aCmd)); StackPush(aStack, DynOS_Level_CmdGet(aCmd, 2)); - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); + return DynOS_Level_CmdNext(aCmd); } static LvlCmd *DynOS_Level_CmdJumpRepeat(Stack &aStack, LvlCmd *aCmd) { aStack.mTopIndex -= 2; - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); + return DynOS_Level_CmdNext(aCmd); } static LvlCmd *DynOS_Level_CmdLoopBegin(Stack &aStack, LvlCmd *aCmd) { - StackPush(aStack, DynOS_Level_CmdNext(aCmd, aCmd->mSize)); + StackPush(aStack, DynOS_Level_CmdNext(aCmd)); StackPush(aStack, 0); - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); + return DynOS_Level_CmdNext(aCmd); } static LvlCmd *DynOS_Level_CmdLoopUntil(Stack &aStack, LvlCmd *aCmd) { aStack.mTopIndex -= 2; - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); + return DynOS_Level_CmdNext(aCmd); } static LvlCmd *DynOS_Level_CmdJumpIf(Stack &aStack, LvlCmd *aCmd) { - StackPush(aStack, DynOS_Level_CmdNext(aCmd, aCmd->mSize)); /* Not an error, that's intentional */ + StackPush(aStack, DynOS_Level_CmdNext(aCmd)); /* Not an error, that's intentional */ return (LvlCmd *) DynOS_Level_CmdGet(aCmd, 8); } static LvlCmd *DynOS_Level_CmdJumpLinkIf(Stack &aStack, LvlCmd *aCmd) { - StackPush(aStack, DynOS_Level_CmdNext(aCmd, aCmd->mSize)); + StackPush(aStack, DynOS_Level_CmdNext(aCmd)); return (LvlCmd *) DynOS_Level_CmdGet(aCmd, 8); } -static LvlCmd *DynOS_Level_CmdSkipIf(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSkip(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSkipNop(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdCall(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdCallLoop(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetRegister(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdPushPool(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdPopPool(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadFixed(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadRaw(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadMIO0(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadMarioHead(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadMIO0Texture(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdInitLevel(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdClearLevel(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdAllocLevelPool(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdFreeLevelPool(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdBeginArea(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdEndArea(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadModelFromDL(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadModelFromGeo(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_Cmd23(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdMario(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdObject(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdWarpNode(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdInstantWarp(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetTerrainType(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdPaintingWarpNode(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_Cmd3A(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetWhirlpool(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetBlackout(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetGamma(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetTerrain(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetRooms(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdMacroObjects(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadArea(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdUnloadArea(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetMarioStartPos(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_Cmd2C(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_Cmd2D(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetTransition(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdNop(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdShowDialog(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetBackgroundMusic(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdSetMenuMusic(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdStopMusic(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdGetOrSet(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdAdvanceDemo(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdClearDemoPointer(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdPlaceObjectExt(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdPlaceObjectExt2(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - -static LvlCmd *DynOS_Level_CmdLoadModelFromGeoExt(Stack &aStack, LvlCmd *aCmd) { - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); -} - static LvlCmd *DynOS_Level_CmdJumpArea(Stack &aStack, LvlCmd *aCmd, s32 (*aPreprocessFunction)(u8, void *)) { DynOS_Level_ParseScript((const void *) DynOS_Level_CmdGet(aCmd, 8), aPreprocessFunction); - return (LvlCmd *) DynOS_Level_CmdNext(aCmd, aCmd->mSize); + return DynOS_Level_CmdNext(aCmd); } void DynOS_Level_ParseScript(const void *aScript, s32 (*aPreprocessFunction)(u8, void *)) { @@ -808,8 +356,6 @@ void DynOS_Level_ParseScript(const void *aScript, s32 (*aPreprocessFunction)(u8, case 0x00: _Cmd = DynOS_Level_CmdExecute(_Stack, _Cmd); break; case 0x01: _Cmd = DynOS_Level_CmdExitAndExecute(_Stack, _Cmd); break; case 0x02: _Cmd = DynOS_Level_CmdExit(_Stack, _Cmd); break; - case 0x03: _Cmd = DynOS_Level_CmdSleep(_Stack, _Cmd); break; - case 0x04: _Cmd = DynOS_Level_CmdSleepBeforeExit(_Stack, _Cmd); break; case 0x05: _Cmd = DynOS_Level_CmdJump(_Stack, _Cmd); break; case 0x06: _Cmd = DynOS_Level_CmdJumpLink(_Stack, _Cmd); break; case 0x07: _Cmd = DynOS_Level_CmdReturn(_Stack, _Cmd); break; @@ -819,64 +365,15 @@ void DynOS_Level_ParseScript(const void *aScript, s32 (*aPreprocessFunction)(u8, case 0x0B: _Cmd = DynOS_Level_CmdLoopUntil(_Stack, _Cmd); break; case 0x0C: _Cmd = DynOS_Level_CmdJumpIf(_Stack, _Cmd); break; case 0x0D: _Cmd = DynOS_Level_CmdJumpLinkIf(_Stack, _Cmd); break; - case 0x0E: _Cmd = DynOS_Level_CmdSkipIf(_Stack, _Cmd); break; - case 0x0F: _Cmd = DynOS_Level_CmdSkip(_Stack, _Cmd); break; - case 0x10: _Cmd = DynOS_Level_CmdSkipNop(_Stack, _Cmd); break; - case 0x11: _Cmd = DynOS_Level_CmdCall(_Stack, _Cmd); break; - case 0x12: _Cmd = DynOS_Level_CmdCallLoop(_Stack, _Cmd); break; - case 0x13: _Cmd = DynOS_Level_CmdSetRegister(_Stack, _Cmd); break; - case 0x14: _Cmd = DynOS_Level_CmdPushPool(_Stack, _Cmd); break; - case 0x15: _Cmd = DynOS_Level_CmdPopPool(_Stack, _Cmd); break; - case 0x16: _Cmd = DynOS_Level_CmdLoadFixed(_Stack, _Cmd); break; - case 0x17: _Cmd = DynOS_Level_CmdLoadRaw(_Stack, _Cmd); break; - case 0x18: _Cmd = DynOS_Level_CmdLoadMIO0(_Stack, _Cmd); break; - case 0x19: _Cmd = DynOS_Level_CmdLoadMarioHead(_Stack, _Cmd); break; - case 0x1A: _Cmd = DynOS_Level_CmdLoadMIO0Texture(_Stack, _Cmd); break; - case 0x1B: _Cmd = DynOS_Level_CmdInitLevel(_Stack, _Cmd); break; - case 0x1C: _Cmd = DynOS_Level_CmdClearLevel(_Stack, _Cmd); break; - case 0x1D: _Cmd = DynOS_Level_CmdAllocLevelPool(_Stack, _Cmd); break; - case 0x1E: _Cmd = DynOS_Level_CmdFreeLevelPool(_Stack, _Cmd); break; - case 0x1F: _Cmd = DynOS_Level_CmdBeginArea(_Stack, _Cmd); break; - case 0x20: _Cmd = DynOS_Level_CmdEndArea(_Stack, _Cmd); break; - case 0x21: _Cmd = DynOS_Level_CmdLoadModelFromDL(_Stack, _Cmd); break; - case 0x22: _Cmd = DynOS_Level_CmdLoadModelFromGeo(_Stack, _Cmd); break; - case 0x23: _Cmd = DynOS_Level_Cmd23(_Stack, _Cmd); break; - case 0x24: _Cmd = DynOS_Level_CmdObject(_Stack, _Cmd); break; - case 0x25: _Cmd = DynOS_Level_CmdMario(_Stack, _Cmd); break; - case 0x26: _Cmd = DynOS_Level_CmdWarpNode(_Stack, _Cmd); break; - case 0x27: _Cmd = DynOS_Level_CmdPaintingWarpNode(_Stack, _Cmd); break; - case 0x28: _Cmd = DynOS_Level_CmdInstantWarp(_Stack, _Cmd); break; - case 0x29: _Cmd = DynOS_Level_CmdLoadArea(_Stack, _Cmd); break; - case 0x2A: _Cmd = DynOS_Level_CmdUnloadArea(_Stack, _Cmd); break; - case 0x2B: _Cmd = DynOS_Level_CmdSetMarioStartPos(_Stack, _Cmd); break; - case 0x2C: _Cmd = DynOS_Level_Cmd2C(_Stack, _Cmd); break; - case 0x2D: _Cmd = DynOS_Level_Cmd2D(_Stack, _Cmd); break; - case 0x2E: _Cmd = DynOS_Level_CmdSetTerrain(_Stack, _Cmd); break; - case 0x2F: _Cmd = DynOS_Level_CmdSetRooms(_Stack, _Cmd); break; - case 0x30: _Cmd = DynOS_Level_CmdShowDialog(_Stack, _Cmd); break; - case 0x31: _Cmd = DynOS_Level_CmdSetTerrainType(_Stack, _Cmd); break; - case 0x32: _Cmd = DynOS_Level_CmdNop(_Stack, _Cmd); break; - case 0x33: _Cmd = DynOS_Level_CmdSetTransition(_Stack, _Cmd); break; - case 0x34: _Cmd = DynOS_Level_CmdSetBlackout(_Stack, _Cmd); break; - case 0x35: _Cmd = DynOS_Level_CmdSetGamma(_Stack, _Cmd); break; - case 0x36: _Cmd = DynOS_Level_CmdSetBackgroundMusic(_Stack, _Cmd); break; - case 0x37: _Cmd = DynOS_Level_CmdSetMenuMusic(_Stack, _Cmd); break; - case 0x38: _Cmd = DynOS_Level_CmdStopMusic(_Stack, _Cmd); break; - case 0x39: _Cmd = DynOS_Level_CmdMacroObjects(_Stack, _Cmd); break; - case 0x3A: _Cmd = DynOS_Level_Cmd3A(_Stack, _Cmd); break; - case 0x3B: _Cmd = DynOS_Level_CmdSetWhirlpool(_Stack, _Cmd); break; - case 0x3C: _Cmd = DynOS_Level_CmdGetOrSet(_Stack, _Cmd); break; - case 0x3D: _Cmd = DynOS_Level_CmdAdvanceDemo(_Stack, _Cmd); break; - case 0x3E: _Cmd = DynOS_Level_CmdClearDemoPointer(_Stack, _Cmd); break; + // coop - case 0x3F: _Cmd = DynOS_Level_CmdPlaceObjectExt(_Stack, _Cmd); break; - case 0x40: _Cmd = DynOS_Level_CmdPlaceObjectExt2(_Stack, _Cmd); break; - case 0x41: _Cmd = DynOS_Level_CmdLoadModelFromGeoExt(_Stack, _Cmd); break; case 0x42: _Cmd = DynOS_Level_CmdJumpArea(_Stack, _Cmd, aPreprocessFunction); break; + + default: _Cmd = DynOS_Level_CmdNext(_Cmd); break; } break; case 1: - _Cmd = (LvlCmd *) DynOS_Level_CmdNext(_Cmd, _Cmd->mSize); + _Cmd = DynOS_Level_CmdNext(_Cmd); break; case 2: @@ -900,10 +397,8 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId) { sDynosCurrentLevelNum = 1; DynOS_Level_ParseScript(info->script, DynOS_Level_PreprocessScript); for (const auto &_Warp : sDynosLevelWarps[1]) { - if (_Warp.mArea == aArea) { - if (_Warp.mId == aWarpId) { - return (s16 *) &_Warp; - } + if (_Warp.mArea == aArea && _Warp.mId == aWarpId) { + return (s16 *) &_Warp; } } return NULL; @@ -912,10 +407,8 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId) { DynOS_Level_Init(); if (aLevel >= 0 && aLevel < LEVEL_COUNT) { for (const auto &_Warp : sDynosLevelWarps[aLevel]) { - if (_Warp.mArea == aArea) { - if (_Warp.mId == aWarpId) { - return (s16 *) &_Warp; - } + if (_Warp.mArea == aArea && _Warp.mId == aWarpId) { + return (s16 *) &_Warp; } } } @@ -924,7 +417,6 @@ s16 *DynOS_Level_GetWarp(s32 aLevel, s32 aArea, u8 aWarpId) { s16 *DynOS_Level_GetWarpEntry(s32 aLevel, s32 aArea) { DynOS_Level_Init(); - if (aLevel == LEVEL_TTM && aArea > 2) return NULL; // override vanilla castle warps if (DynOS_Level_GetCourse(aLevel) == COURSE_NONE && aLevel >= 0 && aLevel < LEVEL_COUNT) { diff --git a/data/dynos_main.cpp b/data/dynos_main.cpp index 4470530a..a2b107e6 100644 --- a/data/dynos_main.cpp +++ b/data/dynos_main.cpp @@ -3,7 +3,6 @@ extern "C" { #include "sm64.h" #include "level_commands.h" #include "game/level_update.h" -#include "game/options_menu.h" #include "game/object_list_processor.h" extern s16 gMenuMode; extern s8 gDialogBoxState; @@ -17,38 +16,17 @@ extern void omm_opt_init(); // void DynOS_ReturnToMainMenu() { - optmenu_toggle(); level_set_transition(0, NULL); gDialogBoxState = 0; gMenuMode = -1; fade_into_special_warp(-2, 0); } -// -// Init -// - -DYNOS_AT_STARTUP void DynOS_Init() { -#ifdef OMM_DEFINES_H - omm_opt_init(); -#endif - DynOS_Opt_Init(); -} - // // Update // static bool sDynosIsLevelEntry = false; -void DynOS_UpdateOpt(void *aPad) { - if (sDynosIsLevelEntry) { - DynOS_Warp_SetParam(gCurrLevelNum, -1); - sDynosIsLevelEntry = false; - } - DynOS_Opt_Update((OSContPad *) aPad); - gPrevFrameObjectCount = 0; -} - void *DynOS_SwapCmd(void *aCmd) { return DynOS_Lvl_Override(aCmd); } diff --git a/data/dynos_mgr_anim.cpp b/data/dynos_mgr_anim.cpp index 02b74f7b..472ffdc0 100644 --- a/data/dynos_mgr_anim.cpp +++ b/data/dynos_mgr_anim.cpp @@ -43,7 +43,7 @@ void DynOS_Anim_Swap(void *aPtr) { static Animation *pDefaultAnimation = NULL; static Animation sGfxDataAnimation; - // Does the object has a model? + // Does the object have a model? struct Object *_Object = (struct Object *) aPtr; if (!_Object->header.gfx.sharedChild) { return; diff --git a/data/dynos_mgr_builtin.cpp b/data/dynos_mgr_builtin.cpp index 928881b9..96e0b20d 100644 --- a/data/dynos_mgr_builtin.cpp +++ b/data/dynos_mgr_builtin.cpp @@ -100,7 +100,7 @@ extern "C" { } \ } \ return NULL; - + #define MGR_FIND_DATA_FROM_TABLES(_DataTable, _DataTable2, _Cast) \ size_t _count = sizeof(_DataTable) / (2 * sizeof(_DataTable[0])); \ for (u32 _i = 0; _i < _count; _i++) { \ @@ -183,6 +183,48 @@ static const void* sDynosBuiltinScriptPtrs[] = { define_builtin(level_main_menu_entry_1), }; +#define define_level_original(lvl, script) (void*) script + +void* gDynosLevelScriptsOriginal[LEVEL_COUNT] = { + define_level_original(0, NULL), + define_level_original(LEVEL_UNKNOWN_1, NULL), + define_level_original(LEVEL_UNKNOWN_2, NULL), + define_level_original(LEVEL_UNKNOWN_3, NULL), + define_level_original(LEVEL_BBH, level_bbh_entry), + define_level_original(LEVEL_CCM, level_ccm_entry), + define_level_original(LEVEL_CASTLE, level_castle_inside_entry), + define_level_original(LEVEL_HMC, level_hmc_entry), + define_level_original(LEVEL_SSL, level_ssl_entry), + define_level_original(LEVEL_BOB, level_bob_entry), + define_level_original(LEVEL_SL, level_sl_entry), + define_level_original(LEVEL_WDW, level_wdw_entry), + define_level_original(LEVEL_JRB, level_jrb_entry), + define_level_original(LEVEL_THI, level_thi_entry), + define_level_original(LEVEL_TTC, level_ttc_entry), + define_level_original(LEVEL_RR, level_rr_entry), + define_level_original(LEVEL_CASTLE_GROUNDS, level_castle_grounds_entry), + define_level_original(LEVEL_BITDW, level_bitdw_entry), + define_level_original(LEVEL_VCUTM, level_vcutm_entry), + define_level_original(LEVEL_BITFS, level_bitfs_entry), + define_level_original(LEVEL_SA, level_sa_entry), + define_level_original(LEVEL_BITS, level_bits_entry), + define_level_original(LEVEL_LLL, level_lll_entry), + define_level_original(LEVEL_DDD, level_ddd_entry), + define_level_original(LEVEL_WF, level_wf_entry), + define_level_original(LEVEL_ENDING, level_ending_entry), + define_level_original(LEVEL_CASTLE_COURTYARD, level_castle_courtyard_entry), + define_level_original(LEVEL_PSS, level_pss_entry), + define_level_original(LEVEL_COTMC, level_cotmc_entry), + define_level_original(LEVEL_TOTWC, level_totwc_entry), + define_level_original(LEVEL_BOWSER_1, level_bowser_1_entry), + define_level_original(LEVEL_WMOTR, level_wmotr_entry), + define_level_original(LEVEL_UNKNOWN_32, NULL), + define_level_original(LEVEL_BOWSER_2, level_bowser_2_entry), + define_level_original(LEVEL_BOWSER_3, level_bowser_3_entry), + define_level_original(LEVEL_UNKNOWN_35, NULL), + define_level_original(LEVEL_TTM, level_ttm_entry), +}; + const void* DynOS_Builtin_ScriptPtr_GetFromName(const char* aDataName) { MGR_FIND_DATA(sDynosBuiltinScriptPtrs, (const void*)); } @@ -1089,7 +1131,7 @@ static const void* sDynosBuiltinCols[] = { define_builtin(wf_seg7_collision_trapezoid), define_builtin(wf_seg7_collision_tumbling_bridge), define_builtin(wmotr_seg7_collision), - + // Actor Collisions define_builtin(bbh_seg7_collision_coffin), define_builtin(bbh_seg7_collision_haunted_bookshelf), @@ -1356,7 +1398,7 @@ static const void* sDynosBuiltinFuncs[] = { define_builtin(geo_movtex_draw_water_regions_ext), define_builtin(lvl_init_or_update), define_builtin(geo_choose_area_ext), - + // Behaviors define_builtin(bhv_cap_switch_loop), define_builtin(bhv_tiny_star_particles_init), @@ -1909,13 +1951,13 @@ static const void* sDynosBuiltinFuncs[] = { define_builtin(bhv_dust_smoke_loop), define_builtin(bhv_yoshi_loop), define_builtin(bhv_volcano_trap_loop), - + // mario_misc.h define_builtin(bhv_toad_message_init), define_builtin(bhv_toad_message_loop), define_builtin(bhv_unlock_door_star_init), define_builtin(bhv_unlock_door_star_loop), - + // Other define_builtin(load_object_collision_model), define_builtin(obj_set_secondary_camera_focus), diff --git a/data/dynos_mgr_lvl.cpp b/data/dynos_mgr_lvl.cpp index c9a11113..44ef9bd8 100644 --- a/data/dynos_mgr_lvl.cpp +++ b/data/dynos_mgr_lvl.cpp @@ -56,7 +56,7 @@ void DynOS_Lvl_Activate(s32 modIndex, const SysPath &aFilename, const char *aLev auto& _OverrideLevelScripts = DynosOverrideLevelScripts(); // make sure vanilla levels were parsed - DynOS_Level_GetCount(); + DynOS_Level_Init(); // check for duplicates for (s32 i = 0; i < _CustomLevelScripts.Count(); ++i) { @@ -121,7 +121,7 @@ const char* DynOS_Lvl_GetToken(u32 index) { if (index >= gfxData->mLuaTokenList.Count()) { return NULL; } - + return gfxData->mLuaTokenList[index].begin(); } diff --git a/data/dynos_mgr_models.cpp b/data/dynos_mgr_models.cpp index 64d42393..0901be39 100644 --- a/data/dynos_mgr_models.cpp +++ b/data/dynos_mgr_models.cpp @@ -234,7 +234,3 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool) { assetMap.clear(); } - -void DynOS_Model_Update() { - -} \ No newline at end of file diff --git a/data/dynos_opt.cpp b/data/dynos_opt.cpp deleted file mode 100644 index a0aab992..00000000 --- a/data/dynos_opt.cpp +++ /dev/null @@ -1,749 +0,0 @@ -#include "dynos.cpp.h" -extern "C" { -#include "pc/configfile.h" -#include "audio/external.h" -#include "game/game_init.h" -#include "pc/controller/controller_keyboard.h" -#ifdef BETTERCAMERA -#include "game/bettercamera.h" -#endif -} - -// -// Data -// - -static DynosOption *sPrevOpt = NULL; -static DynosOption *sDynosMenu = NULL; -static DynosOption *sOptionsMenu = NULL; -static DynosOption *sCurrentMenu = NULL; -static DynosOption *sCurrentOpt = NULL; -extern s32 sBindingState; - -// -// Action list -// - -typedef bool (*DynosActionFunction)(const char *); -struct DynosAction : NoCopy { - String mFuncName; - DynosActionFunction mAction; -}; - -STATIC_STORAGE(Array, DynosActions); -#define sDynosActions __DynosActions() - -static DynosActionFunction DynOS_Opt_GetAction(const String& aFuncName) { - for (auto &_DynosAction : sDynosActions) { - if (_DynosAction->mFuncName == aFuncName) { - return _DynosAction->mAction; - } - } - return NULL; -} - -void DynOS_Opt_AddAction(const String& aFuncName, bool (*aFuncPtr)(const char *), bool aOverwrite) { - for (auto &_DynosAction : sDynosActions) { - if (_DynosAction->mFuncName == aFuncName) { - if (aOverwrite) { - _DynosAction->mAction = aFuncPtr; - } - return; - } - } - DynosAction *_DynosAction = New(); - _DynosAction->mFuncName = aFuncName; - _DynosAction->mAction = aFuncPtr; - sDynosActions.Add(_DynosAction); -} - -// -// Constructors -// - -static DynosOption *DynOS_Opt_GetExistingOption(DynosOption *aOpt, const String &aName) { - while (aOpt) { - if (aOpt->mName == aName) { - return aOpt; - } - if (aOpt->mType == DOPT_SUBMENU) { - DynosOption *_Opt = DynOS_Opt_GetExistingOption(aOpt->mSubMenu.mChild, aName); - if (_Opt) { - return _Opt; - } - } - aOpt = aOpt->mNext; - } - return NULL; -} - -static DynosOption *DynOS_Opt_NewOption(const String &aName, const String &aConfigName, const String &aLabel, const String &aTitle) { - - // Check if the option already exists - static DynosOption sDummyOpt; - if (DynOS_Opt_GetExistingOption(sDynosMenu, aName)) { - return &sDummyOpt; - } - - // Create a new option - DynosOption *_Opt = New(); - _Opt->mName = aName; - _Opt->mConfigName = aConfigName; - _Opt->mLabel = { aLabel, NULL }; - _Opt->mTitle = { aTitle, NULL }; - _Opt->mDynos = true; - if (sPrevOpt == NULL) { // The very first option - _Opt->mPrev = NULL; - _Opt->mNext = NULL; - _Opt->mParent = NULL; - sDynosMenu = _Opt; - } else { - if (sPrevOpt->mType == DOPT_SUBMENU && sPrevOpt->mSubMenu.mEmpty) { // First option of a sub-menu - _Opt->mPrev = NULL; - _Opt->mNext = NULL; - _Opt->mParent = sPrevOpt; - sPrevOpt->mSubMenu.mChild = _Opt; - sPrevOpt->mSubMenu.mEmpty = false; - } else { - _Opt->mPrev = sPrevOpt; - _Opt->mNext = NULL; - _Opt->mParent = sPrevOpt->mParent; - sPrevOpt->mNext = _Opt; - } - } - sPrevOpt = _Opt; - return _Opt; -} - -static void DynOS_Opt_EndSubMenu() { - if (sPrevOpt && sPrevOpt->mParent) { - if (sPrevOpt->mType == DOPT_SUBMENU && sPrevOpt->mSubMenu.mEmpty) { // ENDMENU command following a SUBMENU command - sPrevOpt->mSubMenu.mEmpty = false; - } else { - sPrevOpt = sPrevOpt->mParent; - } - } -} - -static void DynOS_Opt_CreateSubMenu(const String &aName, const String &aLabel, const String &aTitle) { - DynosOption *_Opt = DynOS_Opt_NewOption(aName, "", aLabel, aTitle); - _Opt->mType = DOPT_SUBMENU; - _Opt->mSubMenu.mChild = NULL; - _Opt->mSubMenu.mEmpty = true; -} - -static void DynOS_Opt_CreateToggle(const String &aName, const String &aConfigName, const String &aLabel, s32 aValue) { - DynosOption *_Opt = DynOS_Opt_NewOption(aName, aConfigName, aLabel, aLabel); - _Opt->mType = DOPT_TOGGLE; - _Opt->mToggle.mTog = New(); - *_Opt->mToggle.mTog = (bool) aValue; -} - -static void DynOS_Opt_CreateScroll(const String &aName, const String &aConfigName, const String &aLabel, s32 aMin, s32 aMax, s32 aStep, s32 aValue) { - DynosOption *_Opt = DynOS_Opt_NewOption(aName, aConfigName, aLabel, aLabel); - _Opt->mType = DOPT_SCROLL; - _Opt->mScroll.mMin = aMin; - _Opt->mScroll.mMax = aMax; - _Opt->mScroll.mStep = aStep; - _Opt->mScroll.mValue = New(); - *_Opt->mScroll.mValue = aValue; -} - -static void DynOS_Opt_CreateChoice(const String &aName, const String &aConfigName, const String &aLabel, const Array& aChoices, s32 aValue) { - DynosOption *_Opt = DynOS_Opt_NewOption(aName, aConfigName, aLabel, aLabel); - _Opt->mType = DOPT_CHOICE; - _Opt->mChoice.mIndex = New(); - *_Opt->mChoice.mIndex = aValue; - for (const auto &_Choice : aChoices) { - _Opt->mChoice.mChoices.Add({ _Choice, NULL }); - } -} - -static void DynOS_Opt_CreateButton(const String &aName, const String &aLabel, const String& aFuncName) { - DynosOption *_Opt = DynOS_Opt_NewOption(aName, "", aLabel, aLabel); - _Opt->mType = DOPT_BUTTON; - _Opt->mButton.mFuncName = aFuncName; -} - -static void DynOS_Opt_CreateBind(const String &aName, const String &aConfigName, const String &aLabel, u32 aMask, u32 aBind0, u32 aBind1, u32 aBind2) { - DynosOption *_Opt = DynOS_Opt_NewOption(aName, aConfigName, aLabel, aLabel); - _Opt->mType = DOPT_BIND; - _Opt->mBind.mMask = aMask; - _Opt->mBind.mBinds = New(3); - _Opt->mBind.mBinds[0] = aBind0; - _Opt->mBind.mBinds[1] = aBind1; - _Opt->mBind.mBinds[2] = aBind2; - _Opt->mBind.mIndex = 0; -} - -// -// Loop through DynosOptions -// - -DynosOption *DynOS_Opt_Loop(DynosOption *aOpt, DynosLoopFunc aFunc, void *aData) { - while (aOpt) { - if (aFunc(aOpt, aData)) { - return aOpt; - } else if (aOpt->mType == DOPT_SUBMENU) { - DynosOption *_Opt = DynOS_Opt_Loop(aOpt->mSubMenu.mChild, aFunc, aData); - if (_Opt) { - return _Opt; - } - } - aOpt = aOpt->mNext; - } - return NULL; -} - -// -// Get/Set values -// - -static bool DynOS_Opt_Get(DynosOption *aOpt, void *aData) { - return aOpt->mName == (const char *) aData; -} - -s32 DynOS_Opt_GetValue(const String &aName) { - DynosOption *_Opt = DynOS_Opt_Loop(sDynosMenu, DynOS_Opt_Get, (void *) aName.begin()); - if (_Opt) { - switch (_Opt->mType) { - case DOPT_TOGGLE: return *_Opt->mToggle.mTog; - case DOPT_CHOICE: return *_Opt->mChoice.mIndex; - case DOPT_CHOICELEVEL: return *_Opt->mChoice.mIndex; - case DOPT_CHOICEAREA: return *_Opt->mChoice.mIndex; - case DOPT_CHOICESTAR: return *_Opt->mChoice.mIndex; - case DOPT_CHOICEPARAM: return *_Opt->mChoice.mIndex; - case DOPT_SCROLL: return *_Opt->mScroll.mValue; - default: break; - } - } - return 0; -} - -void DynOS_Opt_SetValue(const String &aName, s32 aValue) { - DynosOption *_Opt = DynOS_Opt_Loop(sDynosMenu, DynOS_Opt_Get, (void *) aName.begin()); - if (_Opt) { - switch (_Opt->mType) { - case DOPT_TOGGLE: *_Opt->mToggle.mTog = aValue; break; - case DOPT_CHOICE: *_Opt->mChoice.mIndex = aValue; break; - case DOPT_CHOICELEVEL: *_Opt->mChoice.mIndex = aValue; break; - case DOPT_CHOICEAREA: *_Opt->mChoice.mIndex = aValue; break; - case DOPT_CHOICESTAR: *_Opt->mChoice.mIndex = aValue; break; - case DOPT_CHOICEPARAM: *_Opt->mChoice.mIndex = aValue; break; - case DOPT_SCROLL: *_Opt->mScroll.mValue = aValue; break; - default: break; - } - } -} - -// -// Processing -// - -#define SOUND_DYNOS_SAVED (SOUND_MENU_MARIO_CASTLE_WARP2 | (0xFF << 8)) -#define SOUND_DYNOS_SELECT (SOUND_MENU_CHANGE_SELECT | (0xF8 << 8)) -#define SOUND_DYNOS_OK (SOUND_MENU_CHANGE_SELECT | (0xF8 << 8)) -#define SOUND_DYNOS_CANCEL (SOUND_MENU_CAMERA_BUZZ | (0xFC << 8)) - -enum { - INPUT_LEFT, - INPUT_RIGHT, - INPUT_A, - INPUT_Z -}; - -enum { - RESULT_NONE, - RESULT_OK, - RESULT_CANCEL -}; - -static s32 DynOS_Opt_ProcessInput(DynosOption *aOpt, s32 input) { - switch (aOpt->mType) { - case DOPT_TOGGLE: - if (input == INPUT_LEFT) { - *aOpt->mToggle.mTog = false; - return RESULT_OK; - } - if (input == INPUT_RIGHT) { - *aOpt->mToggle.mTog = true; - return RESULT_OK; - } - if (input == INPUT_A) { - *aOpt->mToggle.mTog = !(*aOpt->mToggle.mTog); - return RESULT_OK; - } - break; - - case DOPT_CHOICE: - if (input == INPUT_LEFT) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + aOpt->mChoice.mChoices.Count() - 1) % (aOpt->mChoice.mChoices.Count()); - return RESULT_OK; - } - if (input == INPUT_RIGHT || input == INPUT_A) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 1) % (aOpt->mChoice.mChoices.Count()); - return RESULT_OK; - } - break; - - case DOPT_CHOICELEVEL: - if (input == INPUT_LEFT) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + DynOS_Level_GetCount() - 1) % (DynOS_Level_GetCount()); - return RESULT_OK; - } - if (input == INPUT_RIGHT || input == INPUT_A) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 1) % (DynOS_Level_GetCount()); - return RESULT_OK; - } - break; - - case DOPT_CHOICEAREA: - if (input == INPUT_LEFT) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 3) % (4); - return RESULT_OK; - } - if (input == INPUT_RIGHT || input == INPUT_A) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 1) % (4); - return RESULT_OK; - } - break; - - case DOPT_CHOICESTAR: - if (input == INPUT_LEFT) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 5) % (6); - return RESULT_OK; - } - if (input == INPUT_RIGHT || input == INPUT_A) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 1) % (6); - return RESULT_OK; - } - break; - - case DOPT_CHOICEPARAM: - if (input == INPUT_LEFT) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 4) % (5); - return RESULT_OK; - } - if (input == INPUT_RIGHT || input == INPUT_A) { - *aOpt->mChoice.mIndex = (*aOpt->mChoice.mIndex + 1) % (5); - return RESULT_OK; - } - break; - - case DOPT_SCROLL: - if (input == INPUT_LEFT) { - *aOpt->mScroll.mValue = MAX(aOpt->mScroll.mMin, *aOpt->mScroll.mValue - aOpt->mScroll.mStep * (gPlayer1Controller->buttonDown & A_BUTTON ? 5 : 1)); - return RESULT_OK; - } - if (input == INPUT_RIGHT) { - *aOpt->mScroll.mValue = MIN(aOpt->mScroll.mMax, *aOpt->mScroll.mValue + aOpt->mScroll.mStep * (gPlayer1Controller->buttonDown & A_BUTTON ? 5 : 1)); - return RESULT_OK; - } - break; - - case DOPT_BIND: - if (input == INPUT_LEFT) { - aOpt->mBind.mIndex = MAX(0, aOpt->mBind.mIndex - 1); - return RESULT_OK; - } - if (input == INPUT_RIGHT) { - aOpt->mBind.mIndex = MIN(2, aOpt->mBind.mIndex + 1); - return RESULT_OK; - } - if (input == INPUT_Z) { - aOpt->mBind.mBinds[aOpt->mBind.mIndex] = VK_INVALID; - return RESULT_OK; - } - if (input == INPUT_A) { - aOpt->mBind.mBinds[aOpt->mBind.mIndex] = VK_INVALID; - sBindingState = 1; - controller_get_raw_key(); - return RESULT_OK; - } - break; - - case DOPT_BUTTON: - if (input == INPUT_A) { - DynosActionFunction _Action = DynOS_Opt_GetAction(aOpt->mButton.mFuncName); - if (_Action != NULL && _Action(aOpt->mName.begin())) { - return RESULT_OK; - } - return RESULT_CANCEL; - } - break; - - case DOPT_SUBMENU: - if (input == INPUT_A) { - if (aOpt->mSubMenu.mChild != NULL) { - sCurrentOpt = aOpt->mSubMenu.mChild; - return RESULT_OK; - } - return RESULT_CANCEL; - } - break; - } - return RESULT_NONE; -} - -static void DynOS_Opt_Open(DynosOption *aMenu) { - play_sound(SOUND_DYNOS_SELECT, gGlobalSoundSource); - sCurrentMenu = aMenu; - sCurrentOpt = aMenu; -} - -static void DynOS_Opt_Close(bool aPlaySavedSfx) { - if (sCurrentMenu != NULL) { - if (aPlaySavedSfx) { - play_sound(SOUND_DYNOS_SAVED, gGlobalSoundSource); - } -#ifdef BETTERCAMERA - newcam_init_settings(); -#endif - controller_reconfigure(); - configfile_save(configfile_name()); - DynOS_Opt_SaveConfig(sDynosMenu); - sCurrentMenu = NULL; - } -} - -static void DynOS_Opt_ProcessInputs() { - static s32 sStickTimer = 0; - static bool sPrevStick = 0; - - // Stick values - f32 _StickX = gPlayer1Controller->stickX; - f32 _StickY = gPlayer1Controller->stickY; - if (absx(_StickX) > 60 || absx(_StickY) > 60) { - if (sStickTimer == 0) { - sStickTimer = (sPrevStick ? 2 : 9); - } else { - _StickX = 0; - _StickY = 0; - sStickTimer--; - } - sPrevStick = true; - } else { - sStickTimer = 0; - sPrevStick = false; - } - - // Key binding - if (sBindingState != 0) { - u32 _Key = (sCurrentOpt->mDynos ? (u32) DynOS_Opt_ControllerGetKeyPressed() : controller_get_raw_key()); - if (_Key != VK_INVALID) { - play_sound(SOUND_DYNOS_SELECT, gGlobalSoundSource); - sCurrentOpt->mBind.mBinds[sCurrentOpt->mBind.mIndex] = _Key; - sBindingState = false; - } - return; - } - - if (sCurrentMenu != NULL) { - - // Up - if (_StickY > +60) { - if (sCurrentOpt->mPrev != NULL) { - sCurrentOpt = sCurrentOpt->mPrev; - } else { - while (sCurrentOpt->mNext) sCurrentOpt = sCurrentOpt->mNext; - } - play_sound(SOUND_DYNOS_SELECT, gGlobalSoundSource); - return; - } - - // Down - if (_StickY < -60) { - if (sCurrentOpt->mNext != NULL) { - sCurrentOpt = sCurrentOpt->mNext; - } else { - while (sCurrentOpt->mPrev) sCurrentOpt = sCurrentOpt->mPrev; - } - play_sound(SOUND_DYNOS_SELECT, gGlobalSoundSource); - return; - } - - // Left - if (_StickX < -60) { - switch (DynOS_Opt_ProcessInput(sCurrentOpt, INPUT_LEFT)) { - case RESULT_OK: play_sound(SOUND_DYNOS_OK, gGlobalSoundSource); break; - case RESULT_CANCEL: play_sound(SOUND_DYNOS_CANCEL, gGlobalSoundSource); break; - case RESULT_NONE: break; - } - return; - } - - // Right - if (_StickX > +60) { - switch (DynOS_Opt_ProcessInput(sCurrentOpt, INPUT_RIGHT)) { - case RESULT_OK: play_sound(SOUND_DYNOS_OK, gGlobalSoundSource); break; - case RESULT_CANCEL: play_sound(SOUND_DYNOS_CANCEL, gGlobalSoundSource); break; - case RESULT_NONE: break; - } - return; - } - - // A - if (gPlayer1Controller->buttonPressed & A_BUTTON) { - switch (DynOS_Opt_ProcessInput(sCurrentOpt, INPUT_A)) { - case RESULT_OK: play_sound(SOUND_DYNOS_OK, gGlobalSoundSource); break; - case RESULT_CANCEL: play_sound(SOUND_DYNOS_CANCEL, gGlobalSoundSource); break; - case RESULT_NONE: break; - } - return; - } - - // B - if (gPlayer1Controller->buttonPressed & B_BUTTON) { - if (sCurrentOpt->mParent != NULL) { - sCurrentOpt = sCurrentOpt->mParent; - play_sound(SOUND_DYNOS_SELECT, gGlobalSoundSource); - } else { - DynOS_Opt_Close(true); - } - return; - } - - // Z - if (gPlayer1Controller->buttonPressed & Z_TRIG) { - switch (DynOS_Opt_ProcessInput(sCurrentOpt, INPUT_Z)) { - case RESULT_OK: play_sound(SOUND_DYNOS_OK, gGlobalSoundSource); break; - case RESULT_CANCEL: play_sound(SOUND_DYNOS_CANCEL, gGlobalSoundSource); break; - case RESULT_NONE: - if (sCurrentMenu == sDynosMenu) { - DynOS_Opt_Close(true); - } else { - DynOS_Opt_Open(sDynosMenu); - } break; - } - return; - } - - // R - if (gPlayer1Controller->buttonPressed & R_TRIG) { - if (sCurrentMenu == sOptionsMenu) { - DynOS_Opt_Close(true); - } else { - DynOS_Opt_Open(sOptionsMenu); - } - return; - } - - // Start - if (gPlayer1Controller->buttonPressed & START_BUTTON) { - DynOS_Opt_Close(true); - return; - } - } else if (gPlayer1Controller->buttonPressed & R_TRIG) { - DynOS_Opt_Open(sOptionsMenu); - } else if (gPlayer1Controller->buttonPressed & Z_TRIG) { - DynOS_Opt_Open(sDynosMenu); - } -} - -// -// Init -// - -static void DynOS_Opt_CreateWarpToLevelSubMenu() { - DynOS_Opt_CreateSubMenu("dynos_warp_to_level_submenu", "Warp to Level", "WARP TO LEUEL"); - - // Level select - { - DynosOption *aOpt = DynOS_Opt_NewOption("dynos_warp_level", "", "Level Select", ""); - aOpt->mType = DOPT_CHOICELEVEL; - aOpt->mChoice.mIndex = New(); - *aOpt->mChoice.mIndex = 0; - } - - // Area select - { - DynosOption *aOpt = DynOS_Opt_NewOption("dynos_warp_area", "", "Area Select", ""); - aOpt->mType = DOPT_CHOICEAREA; - aOpt->mChoice.mIndex = New(); - *aOpt->mChoice.mIndex = 0; - } - - // Star select - { - DynosOption *aOpt = DynOS_Opt_NewOption("dynos_warp_act", "", "Star Select", ""); - aOpt->mType = DOPT_CHOICESTAR; - aOpt->mChoice.mIndex = New(); - *aOpt->mChoice.mIndex = 0; - } - - // Param select - { - DynosOption *aOpt = DynOS_Opt_NewOption("dynos_warp_param", "", "Param Select", ""); - aOpt->mType = DOPT_CHOICEPARAM; - aOpt->mChoice.mIndex = New(); - *aOpt->mChoice.mIndex = 0; - } - - DynOS_Opt_CreateButton("dynos_warp_to_level", "Warp", "DynOS_Opt_WarpToLevel"); - DynOS_Opt_EndSubMenu(); -} - -static void DynOS_Opt_CreateWarpToCastleSubMenu() { - DynOS_Opt_CreateSubMenu("dynos_warp_to_castle_submenu", "Warp to Castle", "WARP TO CASTLE"); - - // Level select - { - DynosOption *aOpt = DynOS_Opt_NewOption("dynos_warp_castle", "", "Level Exit", ""); - aOpt->mType = DOPT_CHOICELEVEL; - aOpt->mChoice.mIndex = New(); - *aOpt->mChoice.mIndex = 0; - } - - DynOS_Opt_CreateButton("dynos_warp_to_castle", "Warp", "DynOS_Opt_WarpToCastle"); - DynOS_Opt_EndSubMenu(); -} - -static u32 DynOS_Opt_GetHash(const String& aStr) { - u32 _Hash = 5381u; - for (char c : aStr) { _Hash += c + (_Hash << 5); } - return _Hash; -} - -static void DynOS_Opt_CreateModelPacksSubMenu() { - /*Array _Packs = DynOS_Gfx_Init(); - if (_Packs.Count() == 0) { - return; - } - - DynOS_Opt_CreateSubMenu("dynos_model_loader_submenu", "Model Packs", "MODEL PACKS"); - for (s32 i = 0; i != _Packs.Count(); ++i) { - DynOS_Opt_CreateToggle(String("dynos_pack_%d", i), String("dynos_pack_%08X", DynOS_Opt_GetHash(_Packs[i])), _Packs[i], false); - } - DynOS_Opt_CreateButton("dynos_packs_disable_all", "Disable all packs", "DynOS_Opt_DisableAllPacks"); - DynOS_Opt_EndSubMenu();*/ -} - -void DynOS_Opt_Init() { - -#ifdef COOP -#else - // Convert options menu - DynOS_Opt_InitVanilla(sOptionsMenu); - - // Warp to level - DynOS_Opt_CreateWarpToLevelSubMenu(); - - // Warp to castle - DynOS_Opt_CreateWarpToCastleSubMenu(); - - // Restart level - DynOS_Opt_CreateButton("dynos_restart_level", "Restart Level", "DynOS_Opt_RestartLevel"); - - // Exit level - DynOS_Opt_CreateButton("dynos_exit_level", "Exit Level", "DynOS_Opt_ExitLevel"); - - // Return to main menu - DynOS_Opt_CreateButton("dynos_return_to_main_menu", "Return to Main Menu", "DynOS_Opt_ReturnToMainMenu"); - - // Model loader - DynOS_Opt_CreateModelPacksSubMenu(); - - // Init config - DynOS_Opt_LoadConfig(sDynosMenu); -#endif -} - -// -// Update -// - -void DynOS_Opt_Update(OSContPad *aPad) { - DynOS_Opt_Loop(sDynosMenu, DynOS_Opt_ControllerUpdate, (void *) aPad); -#ifndef COOP - if (DynOS_IsTransitionActive()) { - aPad->button = 0; - aPad->stick_x = 0; - aPad->stick_y = 0; - aPad->ext_stick_x = 0; - aPad->ext_stick_y = 0; - } -#endif -} - -// -// Hijack -// This is C code -// - -extern "C" { - -u8 optmenu_open = 0; - -void optmenu_toggle(void) { - DynOS_Opt_Close(false); - optmenu_open = 0; -} - -void optmenu_draw(void) { - DynOS_Opt_DrawMenu(sCurrentOpt, sCurrentMenu, sOptionsMenu, sDynosMenu); -} - -void optmenu_draw_prompt(void) { - DynOS_Opt_DrawPrompt(sCurrentMenu, sOptionsMenu, sDynosMenu); - DynOS_Opt_ProcessInputs(); - optmenu_open = (sCurrentMenu != NULL); -} - -void optmenu_check_buttons(void) { -} - -} - -// -// Built-in options -// - -#define DYNOS_DEFINE_ACTION(func) \ -DYNOS_AT_STARTUP static void DynOS_Opt_AddAction_##func() { \ - DynOS_Opt_AddAction(#func, func, false); \ -} - -#ifndef COOP - -static bool DynOS_Opt_ReturnToMainMenu(UNUSED const char *optName) { - DynOS_ReturnToMainMenu(); - return true; -} -DYNOS_DEFINE_ACTION(DynOS_Opt_ReturnToMainMenu); - -static bool DynOS_Opt_WarpToLevel(UNUSED const char *optName) { - s32 _Level = DynOS_Level_GetList()[DynOS_Opt_GetValue("dynos_warp_level")]; - s32 _Area = DynOS_Opt_GetValue("dynos_warp_area") + 1; - s32 _Act = DynOS_Opt_GetValue("dynos_warp_act") + 1; - return DynOS_Warp_ToLevel(_Level, _Area, _Act); -} -DYNOS_DEFINE_ACTION(DynOS_Opt_WarpToLevel); - -static bool DynOS_Opt_WarpToCastle(UNUSED const char *optName) { - s32 _Level = DynOS_Level_GetList()[DynOS_Opt_GetValue("dynos_warp_castle")]; - return DynOS_Warp_ToCastle(_Level); -} -DYNOS_DEFINE_ACTION(DynOS_Opt_WarpToCastle); - -static bool DynOS_Opt_RestartLevel(UNUSED const char *optName) { - return DynOS_Warp_RestartLevel(); -} -DYNOS_DEFINE_ACTION(DynOS_Opt_RestartLevel); - -static bool DynOS_Opt_ExitLevel(UNUSED const char *optName) { - return DynOS_Warp_ExitLevel(30); -} -DYNOS_DEFINE_ACTION(DynOS_Opt_ExitLevel); - -static bool DynOS_Opt_DisableAllPacks(UNUSED const char *optName) { - const Array &pDynosPacks = DynOS_Gfx_GetPacks(); - for (s32 i = 0; i != pDynosPacks.Count(); ++i) { - DynOS_Opt_SetValue(String("dynos_pack_%d", i), false); - } - return true; -} -DYNOS_DEFINE_ACTION(DynOS_Opt_DisableAllPacks); - -#endif - -#undef DYNOS_DEFINE_ACTION diff --git a/data/dynos_opt_config.cpp b/data/dynos_opt_config.cpp deleted file mode 100644 index c6d48a2a..00000000 --- a/data/dynos_opt_config.cpp +++ /dev/null @@ -1,67 +0,0 @@ -#include "dynos.cpp.h" - -extern DynosOption *DynOS_Opt_Loop(DynosOption *aOpt, DynosLoopFunc aFunc, void *aData); - -static bool DynOS_Opt_ReadConfig(DynosOption *aOpt, void *aData) { - return (aOpt->mConfigName == (const char *) aData); -} - -void DynOS_Opt_LoadConfig(DynosOption *aMenu) { - SysPath _Filename = fstring("%s/%s", DYNOS_USER_FOLDER, DYNOS_CONFIG_FILENAME); - FILE *_File = fopen(_Filename.c_str(), "r"); - if (_File) { - char _Buffer[1024]; - while (fgets(_Buffer, 1024, _File)) { - - // Option strings - char *_NameBegin = _Buffer; - char *_DataBegin = strchr(_NameBegin, '='); - if (_NameBegin && _DataBegin) { - *(_DataBegin++) = 0; - - // Option name - String _OptName = String(_NameBegin); - DynosOption *_Opt = DynOS_Opt_Loop(aMenu, DynOS_Opt_ReadConfig, (void *) _OptName.begin()); - if (_Opt) { - - // Option values - switch (_Opt->mType) { - case DOPT_TOGGLE: { - unsigned char boolValue = 0; - sscanf(_DataBegin, "%hhu\n", &boolValue); - _Opt->mToggle.mTog[0] = boolValue; - break; - } - case DOPT_CHOICE: sscanf(_DataBegin, "%d\n", &_Opt->mChoice.mIndex[0]); break; - case DOPT_SCROLL: sscanf(_DataBegin, "%d\n", &_Opt->mScroll.mValue[0]); break; - case DOPT_BIND: sscanf(_DataBegin, "%04X;%04X;%04X\n", &_Opt->mBind.mBinds[0], &_Opt->mBind.mBinds[1], &_Opt->mBind.mBinds[2]); break; - } - } - } - } - fclose(_File); - } -} - -static bool DynOS_Opt_WriteConfig(DynosOption *aOpt, void *aData) { - if (aOpt->mConfigName.Length() != 0 && - aOpt->mConfigName != "null" && - aOpt->mConfigName != "NULL") { - switch (aOpt->mType) { - case DOPT_TOGGLE: fprintf((FILE *) aData, "%s=%hhu\n", aOpt->mConfigName.begin(), aOpt->mToggle.mTog[0]); break; - case DOPT_CHOICE: fprintf((FILE *) aData, "%s=%d\n", aOpt->mConfigName.begin(), aOpt->mChoice.mIndex[0]); break; - case DOPT_SCROLL: fprintf((FILE *) aData, "%s=%d\n", aOpt->mConfigName.begin(), aOpt->mScroll.mValue[0]); break; - case DOPT_BIND: fprintf((FILE *) aData, "%s=%04X;%04X;%04X\n", aOpt->mConfigName.begin(), aOpt->mBind.mBinds[0], aOpt->mBind.mBinds[1], aOpt->mBind.mBinds[2]); break; - } - } - return false; -} - -void DynOS_Opt_SaveConfig(DynosOption *aMenu) { - SysPath _Filename = fstring("%s/%s", DYNOS_USER_FOLDER, DYNOS_CONFIG_FILENAME); - FILE *_File = fopen(_Filename.c_str(), "w"); - if (_File) { - DynOS_Opt_Loop(aMenu, DynOS_Opt_WriteConfig, (void *) _File); - fclose(_File); - } -} diff --git a/data/dynos_opt_cont.cpp b/data/dynos_opt_cont.cpp deleted file mode 100644 index e50dd977..00000000 --- a/data/dynos_opt_cont.cpp +++ /dev/null @@ -1,75 +0,0 @@ -#include "dynos.cpp.h" -extern "C" { -#include "pc/controller/controller_api.h" -} - -static bool DynOS_Opt_ControllerIsKeyDown(s32 aCont, s32 aKey) { -#ifdef HAVE_SDL2 - // Keyboard - if (aCont == 0 && aKey >= 0 && aKey < SDL_NUM_SCANCODES) { - return SDL_GetKeyboardState(NULL)[aKey]; - } - - // Game Controller - else if (aKey >= 0x1000) { - - // Button - s32 _Button = (aKey - 0x1000); - if (_Button < SDL_CONTROLLER_BUTTON_MAX) { - return SDL_GameControllerGetButton(SDL_GameControllerOpen(aCont - 1), SDL_GameControllerButton(_Button)); - } - - // Axis - s32 _Axis = (aKey - 0x1000 - SDL_CONTROLLER_BUTTON_MAX); - if (_Axis < SDL_CONTROLLER_AXIS_MAX * 2) { - s32 _AxisValue = SDL_GameControllerGetAxis(SDL_GameControllerOpen(aCont - 1), SDL_GameControllerAxis(_Axis / 2)); - if (_Axis & 1) return (_AxisValue < (SHRT_MIN / 2)); - else return (_AxisValue > (SHRT_MAX / 2)); - } - } - // Invalid -#endif - return false; -} - -#define MAX_CONTS 8 -bool DynOS_Opt_ControllerUpdate(DynosOption *aOpt, void *aData) { -#ifdef HAVE_SDL2 - if (aOpt->mType == DOPT_BIND) { - OSContPad *pad = (OSContPad *) aData; - for (s32 _Cont = 0; _Cont < MAX_CONTS; ++_Cont) - for (s32 _Bind = 0; _Bind < 3; ++_Bind) { - pad->button |= aOpt->mBind.mMask * DynOS_Opt_ControllerIsKeyDown(_Cont, aOpt->mBind.mBinds[_Bind]); - } - } -#endif - return false; -} - -#define MAX_GKEYS (SDL_CONTROLLER_BUTTON_MAX + SDL_CONTROLLER_AXIS_MAX * 2) -s32 sBindingState = 0; // 0 = No bind, 1 = Wait for all keys released, 2 = Return first pressed key -s32 DynOS_Opt_ControllerGetKeyPressed() { -#ifdef HAVE_SDL2 - - // Keyboard - for (s32 _Key = 0; _Key < SDL_NUM_SCANCODES; ++_Key) { - if (DynOS_Opt_ControllerIsKeyDown(0, _Key)) { - if (sBindingState == 1) return VK_INVALID; - return _Key; - } - } - - // Game Controller - for (s32 _Cont = 1; _Cont < MAX_CONTS; ++_Cont) - for (s32 _Key = 0; _Key < MAX_GKEYS; ++_Key) { - if (DynOS_Opt_ControllerIsKeyDown(_Cont, _Key + 0x1000)) { - if (sBindingState == 1) return VK_INVALID; - return _Key + 0x1000; - } - } - - // No key - sBindingState = 2; -#endif - return VK_INVALID; -} diff --git a/data/dynos_opt_render.cpp b/data/dynos_opt_render.cpp deleted file mode 100644 index d644a51a..00000000 --- a/data/dynos_opt_render.cpp +++ /dev/null @@ -1,309 +0,0 @@ -#include "dynos.cpp.h" -extern "C" { -#include "course_table.h" -#include "game/game_init.h" -#include "game/ingame_menu.h" -#include "game/segment2.h" -#include "pc/controller/controller_api.h" -#include "gfx_dimensions.h" -} - -extern s32 sBindingState; - -#define DYNOS_TEXT_DYNOS_MENU { "DYNOS MENU", NULL } -#define DYNOS_TEXT_A { "([A]) >", NULL } -#define DYNOS_TEXT_OPEN_LEFT { "[Z] DynOS", NULL } -#define DYNOS_TEXT_CLOSE_LEFT { "[Z] Return", NULL } -#define DYNOS_TEXT_OPTIONS_MENU { "OPTIONS", NULL } -#define DYNOS_TEXT_DISABLED { "Disabled", NULL } -#define DYNOS_TEXT_ENABLED { "Enabled", NULL } -#define DYNOS_TEXT_NONE { "NONE", NULL } -#define DYNOS_TEXT_DOT_DOT_DOT { "...", NULL } -#define DYNOS_TEXT_OPEN_RIGHT { "[R] Options", NULL } -#define DYNOS_TEXT_CLOSE_RIGHT { "[R] Return", NULL } - -static void RenderString(const u8 *aStr64, s32 aX, s32 aY) { - create_dl_translation_matrix(MENU_MTX_PUSH, aX, aY, 0); - for (; *aStr64 != DIALOG_CHAR_TERMINATOR; ++aStr64) { - if (*aStr64 != DIALOG_CHAR_SPACE) { - void **fontLUT = (void **) segmented_to_virtual(main_font_lut); - void *packedTexture = segmented_to_virtual(fontLUT[*aStr64]); - gDPPipeSync(gDisplayListHead++); - gDPSetTextureImage(gDisplayListHead++, G_IM_FMT_IA, G_IM_SIZ_16b, 1, VIRTUAL_TO_PHYSICAL(packedTexture)); - gSPDisplayList(gDisplayListHead++, dl_ia_text_tex_settings); - } - create_dl_translation_matrix(MENU_MTX_NOPUSH, DynOS_String_WidthChar64(*aStr64), 0, 0); - } - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); -} - -static void PrintString(const Label& aLabel, s32 aX, s32 aY, u32 aFrontColorRGBA, u32 aBackColorRGBA, bool aAlignLeft) { - const u8 *_Str64 = (aLabel.second ? aLabel.second : DynOS_String_Convert(aLabel.first.begin(), false)); - - gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); - if ((aBackColorRGBA & 0xFF) != 0) { - gDPSetEnvColor(gDisplayListHead++, ((aBackColorRGBA >> 24) & 0xFF), ((aBackColorRGBA >> 16) & 0xFF), ((aBackColorRGBA >> 8) & 0xFF), ((aBackColorRGBA >> 0) & 0xFF)); - if (aAlignLeft) { - RenderString(_Str64, GFX_DIMENSIONS_FROM_LEFT_EDGE(aX) + 1, aY - 1); - } else { - RenderString(_Str64, GFX_DIMENSIONS_FROM_RIGHT_EDGE(aX + DynOS_String_Width(_Str64) - 1), aY - 1); - } - } - if ((aFrontColorRGBA & 0xFF) != 0) { - gDPSetEnvColor(gDisplayListHead++, ((aFrontColorRGBA >> 24) & 0xFF), ((aFrontColorRGBA >> 16) & 0xFF), ((aFrontColorRGBA >> 8) & 0xFF), ((aFrontColorRGBA >> 0) & 0xFF)); - if (aAlignLeft) { - RenderString(_Str64, GFX_DIMENSIONS_FROM_LEFT_EDGE(aX), aY); - } else { - RenderString(_Str64, GFX_DIMENSIONS_FROM_RIGHT_EDGE(aX + DynOS_String_Width(_Str64)), aY); - } - } - gSPDisplayList(gDisplayListHead++, dl_ia_text_end); - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); -} - -static void PrintBox(s32 aX, s32 aY, s32 aWidth, s32 aHeight, u32 aColorRGBA, bool aAlignLeft) { - if ((aColorRGBA & 0xFF) != 0) { - Mtx *_Matrix = (Mtx *) alloc_display_list(sizeof(Mtx)); - if (!_Matrix) return; - if (aAlignLeft) { - create_dl_translation_matrix(MENU_MTX_PUSH, GFX_DIMENSIONS_FROM_LEFT_EDGE(aX), aY + aHeight, 0); - } else { - create_dl_translation_matrix(MENU_MTX_PUSH, GFX_DIMENSIONS_FROM_RIGHT_EDGE(aX + aWidth), aY + aHeight, 0); - } - guScale(_Matrix, (f32) aWidth / 130.f, (f32) aHeight / 80.f, 1.f); - gSPMatrix(gDisplayListHead++, VIRTUAL_TO_PHYSICAL(_Matrix), G_MTX_MODELVIEW | G_MTX_MUL | G_MTX_NOPUSH); - gDPSetEnvColor(gDisplayListHead++, ((aColorRGBA >> 24) & 0xFF), ((aColorRGBA >> 16) & 0xFF), ((aColorRGBA >> 8) & 0xFF), ((aColorRGBA >> 0) & 0xFF)); - gSPDisplayList(gDisplayListHead++, dl_draw_text_bg_box); - gSPPopMatrix(gDisplayListHead++, G_MTX_MODELVIEW); - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); - } -} - -static const char *IntToString(const char *fmt, s32 x) { - static char sBuffer[16]; - snprintf(sBuffer, 16, fmt, x); - return sBuffer; -} - -#define get_label(opt) (opt->mLabel) -#define get_title(opt) (opt->mTitle) -#define get_choice(opt) (opt->mChoice.mChoices[*opt->mChoice.mIndex]) -#define get_dec_number(n) { "", DynOS_String_Convert(IntToString("%d", n), false) } -#define get_hex_number(n) { "", DynOS_String_Convert(IntToString("%04X", n), false) } -#define get_level(opt) { "", DynOS_Level_GetName(DynOS_Level_GetList()[*opt->mChoice.mIndex], true, true) } -#define get_star(opt) { "", DynOS_Level_GetActName(DynOS_Level_GetList()[DynOS_Opt_GetValue("dynos_warp_level")], *opt->mChoice.mIndex + 1, true, true) } -#define get_param(opt) { DynOS_Warp_GetParamName(DynOS_Level_GetList()[DynOS_Opt_GetValue("dynos_warp_level")], *opt->mChoice.mIndex), NULL } - -static s32 GetCurrentOptionCount(DynosOption *aCurrentOpt) { - s32 _Count = 0; - while (aCurrentOpt->mPrev) { aCurrentOpt = aCurrentOpt->mPrev; } - while (aCurrentOpt) { aCurrentOpt = aCurrentOpt->mNext; _Count++; } - return _Count; -} - -static s32 GetCurrentOptionIndex(DynosOption *aCurrentOpt) { - s32 _Index = 0; - while (aCurrentOpt->mPrev) { aCurrentOpt = aCurrentOpt->mPrev; _Index++; } - return _Index; -} - -#define PREV(opt) (opt == NULL ? NULL : opt->mPrev) -#define NEXT(opt) (opt == NULL ? NULL : opt->mNext) -static DynosOption **GetCurrentOptions(DynosOption *aCurrentOpt) { - static DynosOption *sOptionList[13]; - - sOptionList[6] = aCurrentOpt; - sOptionList[5] = PREV(sOptionList[6]); - sOptionList[4] = PREV(sOptionList[5]); - sOptionList[3] = PREV(sOptionList[4]); - sOptionList[2] = PREV(sOptionList[3]); - sOptionList[1] = PREV(sOptionList[2]); - sOptionList[0] = PREV(sOptionList[1]); - sOptionList[7] = NEXT(sOptionList[6]); - sOptionList[8] = NEXT(sOptionList[7]); - sOptionList[9] = NEXT(sOptionList[8]); - sOptionList[10] = NEXT(sOptionList[9]); - sOptionList[11] = NEXT(sOptionList[10]); - sOptionList[12] = NEXT(sOptionList[11]); - - s32 _StartIndex = 12, _EndIndex = 0; - for (s32 i = 0; i != 13; ++i) { - if (sOptionList[i] != NULL) { - _StartIndex = MIN(_StartIndex, i); - _EndIndex = MAX(_EndIndex, i); - } - } - - if (_EndIndex - _StartIndex < 7) { - return &sOptionList[_StartIndex]; - } - if (_EndIndex <= 9) { - return &sOptionList[_EndIndex - 6]; - } - if (_StartIndex >= 3) { - return &sOptionList[_StartIndex]; - } - return &sOptionList[3]; -} -#undef PREV -#undef NEXT - -#define COLOR_WHITE 0xFFFFFFFF -#define COLOR_BLACK 0x000000FF -#define COLOR_GRAY 0xA0A0A0FF -#define COLOR_DARK_GRAY 0x808080FF -#define COLOR_SELECT 0x80E0FFFF -#define COLOR_SELECT_BOX 0x00FFFF20 -#define COLOR_ENABLED 0x20E020FF -#define COLOR_DISABLED 0xFF2020FF -#define OFFSET_FROM_LEFT_EDGE (20.f * sqr(GFX_DIMENSIONS_ASPECT_RATIO)) -#define OFFSET_FROM_RIGHT_EDGE (20.f * sqr(GFX_DIMENSIONS_ASPECT_RATIO)) -#define SCROLL_BAR_SIZE ((s32) (45.f * GFX_DIMENSIONS_ASPECT_RATIO)) - -static void DynOS_Opt_DrawOption(DynosOption *aOpt, DynosOption *aCurrentOpt, s32 aY) { - if (aOpt == NULL) { - return; - } - - // Selected box - if (aOpt == aCurrentOpt) { - u8 _Alpha = (u8) ((coss(gGlobalTimer * 0x800) + 1.f) * 0x20); - PrintBox(OFFSET_FROM_LEFT_EDGE - 4, aY - 2, GFX_DIMENSIONS_FROM_RIGHT_EDGE(OFFSET_FROM_RIGHT_EDGE) - GFX_DIMENSIONS_FROM_LEFT_EDGE(OFFSET_FROM_LEFT_EDGE) + 8, 20, COLOR_SELECT_BOX + _Alpha, 1); - } - - // Label - if (aOpt == aCurrentOpt) { - PrintString(get_label(aOpt), OFFSET_FROM_LEFT_EDGE, aY, COLOR_SELECT, COLOR_BLACK, 1); - } else { - PrintString(get_label(aOpt), OFFSET_FROM_LEFT_EDGE, aY, COLOR_WHITE, COLOR_BLACK, 1); - } - - // Values - switch (aOpt->mType) { - case DOPT_TOGGLE: { - if (*aOpt->mToggle.mTog) { - PrintString(DYNOS_TEXT_ENABLED, OFFSET_FROM_RIGHT_EDGE, aY, COLOR_ENABLED, COLOR_BLACK, 0); - } else { - PrintString(DYNOS_TEXT_DISABLED, OFFSET_FROM_RIGHT_EDGE, aY, COLOR_DISABLED, COLOR_BLACK, 0); - } - } break; - - case DOPT_CHOICE: { - PrintString(get_choice(aOpt), OFFSET_FROM_RIGHT_EDGE, aY, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, COLOR_BLACK, 0); - } break; - - case DOPT_CHOICELEVEL: { - PrintString(get_level(aOpt), OFFSET_FROM_RIGHT_EDGE, aY, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, COLOR_BLACK, 0); - } break; - - case DOPT_CHOICEAREA: { - s32 _Level = DynOS_Level_GetList()[DynOS_Opt_GetValue("dynos_warp_level")]; - s32 _Area = *aOpt->mChoice.mIndex + 1; - const u8 *_Name = DynOS_Level_GetAreaName(_Level, _Area, true); - if (DynOS_Level_GetWarpEntry(_Level, _Area)) { - PrintString({ "", _Name }, OFFSET_FROM_RIGHT_EDGE, aY, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, COLOR_BLACK, 0); - } else { - PrintString({ "", _Name }, OFFSET_FROM_RIGHT_EDGE, aY, COLOR_GRAY, COLOR_BLACK, 0); - } - } break; - - case DOPT_CHOICESTAR: { - s32 _Course = DynOS_Level_GetCourse(DynOS_Level_GetList()[DynOS_Opt_GetValue("dynos_warp_level")]); - if (_Course >= COURSE_MIN && _Course <= COURSE_STAGES_MAX) { - PrintString(get_star(aOpt), OFFSET_FROM_RIGHT_EDGE, aY, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, COLOR_BLACK, 0); - } - } break; - - case DOPT_CHOICEPARAM: { - PrintString(get_param(aOpt), OFFSET_FROM_RIGHT_EDGE, aY, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, COLOR_BLACK, 0); - } break; - - case DOPT_SCROLL: { - s32 _Width = (s32) (SCROLL_BAR_SIZE * (f32) (*aOpt->mScroll.mValue - aOpt->mScroll.mMin) / (f32) (aOpt->mScroll.mMax - aOpt->mScroll.mMin)); - PrintString(get_dec_number(*aOpt->mScroll.mValue), OFFSET_FROM_RIGHT_EDGE, aY, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, COLOR_BLACK, 0); - PrintBox(OFFSET_FROM_RIGHT_EDGE + 28, aY + 4, SCROLL_BAR_SIZE + 2, 8, COLOR_DARK_GRAY, 0); - PrintBox(OFFSET_FROM_RIGHT_EDGE + 29 + SCROLL_BAR_SIZE - _Width, aY + 5, _Width, 6, aOpt == aCurrentOpt ? COLOR_SELECT : COLOR_WHITE, 0); - } break; - - case DOPT_BIND: { - for (s32 i = 0; i != 3; ++i) { - u32 _Bind = aOpt->mBind.mBinds[i]; - if (aOpt == aCurrentOpt && i == aOpt->mBind.mIndex) { - if (sBindingState != 0) { - PrintString(DYNOS_TEXT_DOT_DOT_DOT, OFFSET_FROM_RIGHT_EDGE + (2 - i) * 36, aY, COLOR_SELECT, COLOR_BLACK, 0); - } else if (_Bind == VK_INVALID) { - PrintString(DYNOS_TEXT_NONE, OFFSET_FROM_RIGHT_EDGE + (2 - i) * 36, aY, COLOR_SELECT, COLOR_BLACK, 0); - } else { - PrintString(get_hex_number(_Bind), OFFSET_FROM_RIGHT_EDGE + (2 - i) * 36, aY, COLOR_SELECT, COLOR_BLACK, 0); - } - } else { - if (_Bind == VK_INVALID) { - PrintString(DYNOS_TEXT_NONE, OFFSET_FROM_RIGHT_EDGE + (2 - i) * 36, aY, COLOR_GRAY, COLOR_BLACK, 0); - } else { - PrintString(get_hex_number(_Bind), OFFSET_FROM_RIGHT_EDGE + (2 - i) * 36, aY, COLOR_WHITE, COLOR_BLACK, 0); - } - } - } - } break; - - case DOPT_BUTTON: { - } break; - - case DOPT_SUBMENU: { - if (aOpt == aCurrentOpt) { - PrintString(DYNOS_TEXT_A, OFFSET_FROM_RIGHT_EDGE, aY, COLOR_SELECT, COLOR_BLACK, 0); - } - } break; - } -} - -void DynOS_Opt_DrawMenu(DynosOption *aCurrentOption, DynosOption *aCurrentMenu, DynosOption *aOptionsMenu, DynosOption *aDynosMenu) { - if (aCurrentMenu == NULL) { - return; - } - - // Colorful label - Label _Title; - if (aCurrentOption->mParent) { - _Title = get_title(aCurrentOption->mParent); - } else if (aCurrentMenu == aDynosMenu) { - _Title = DYNOS_TEXT_DYNOS_MENU; - } else if (aCurrentMenu == aOptionsMenu) { - _Title = DYNOS_TEXT_OPTIONS_MENU; - } - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); - gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); - if (!_Title.second) _Title.second = DynOS_String_Convert(_Title.first.begin(), false); - print_hud_lut_string(HUD_LUT_GLOBAL, (SCREEN_WIDTH / 2 - DynOS_String_Length(_Title.second) * 6), 40, _Title.second); - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_end); - - // Display options - DynosOption **_Options = GetCurrentOptions(aCurrentOption); - for (s32 i = 0; i != 7; ++i) { - DynOS_Opt_DrawOption(_Options[i], aCurrentOption, 156 - 20 * i); - } - - // Scroll bar - s32 _OptCount = GetCurrentOptionCount(aCurrentOption); - s32 _OptIndex = GetCurrentOptionIndex(aCurrentOption); - if (_OptCount > 7) { - s32 _Height = (s32) (134.f * sqrtf(1.f / (_OptCount - 6))); - s32 _Y = 37 + (134 - _Height) * (1.f - MAX(0.f, MIN(1.f, (f32)(_OptIndex - 3) / (f32)(_OptCount - 6)))); - PrintBox(OFFSET_FROM_RIGHT_EDGE - 16, 36, 8, 136, COLOR_DARK_GRAY, 0); - PrintBox(OFFSET_FROM_RIGHT_EDGE - 15, _Y, 6, _Height, COLOR_WHITE, 0); - } -} - -#define PROMPT_OFFSET (56.25f * GFX_DIMENSIONS_ASPECT_RATIO) -void DynOS_Opt_DrawPrompt(DynosOption *aCurrentMenu, DynosOption *aOptionsMenu, DynosOption *aDynosMenu) { - if (aCurrentMenu == aOptionsMenu) { - PrintString(DYNOS_TEXT_OPEN_LEFT, PROMPT_OFFSET, 212, COLOR_WHITE, COLOR_BLACK, 1); - PrintString(DYNOS_TEXT_CLOSE_RIGHT, PROMPT_OFFSET, 212, COLOR_WHITE, COLOR_BLACK, 0); - } else if (aCurrentMenu == aDynosMenu) { - PrintString(DYNOS_TEXT_CLOSE_LEFT, PROMPT_OFFSET, 212, COLOR_WHITE, COLOR_BLACK, 1); - PrintString(DYNOS_TEXT_OPEN_RIGHT, PROMPT_OFFSET, 212, COLOR_WHITE, COLOR_BLACK, 0); - } else { - PrintString(DYNOS_TEXT_OPEN_LEFT, PROMPT_OFFSET, 212, COLOR_WHITE, COLOR_BLACK, 1); - PrintString(DYNOS_TEXT_OPEN_RIGHT, PROMPT_OFFSET, 212, COLOR_WHITE, COLOR_BLACK, 0); - } -} diff --git a/data/dynos_opt_vanilla.cpp b/data/dynos_opt_vanilla.cpp deleted file mode 100644 index 2e17c136..00000000 --- a/data/dynos_opt_vanilla.cpp +++ /dev/null @@ -1,159 +0,0 @@ -#include "dynos.cpp.h" - -static DynosOption *sPrevOpt = NULL; -static DynosOption *sOptionsMenu = NULL; - -// -// Vanilla actions -// - -typedef void (*VanillaActionFunction)(struct Option *, s32); -typedef struct VanillaAction { - String mFuncName; - VanillaActionFunction mAction; -} VanillaAction; - -STATIC_STORAGE(Array, VanillaActions); -#define sVanillaActions __VanillaActions() - -static VanillaActionFunction DynOS_Opt_GetVanillaAction(const String& aFuncName) { - for (auto &_DynosAction : sVanillaActions) { - if (_DynosAction->mFuncName == aFuncName) { - return _DynosAction->mAction; - } - } - return NULL; -} - -static void DynOS_Opt_AddVanillaAction(const String& aFuncName, void (*aFuncPtr)(struct Option *, s32)) { - for (auto &_DynosAction : sVanillaActions) { - if (_DynosAction->mFuncName == aFuncName) { - return; - } - } - VanillaAction *_DynosAction = New(); - _DynosAction->mFuncName = aFuncName; - _DynosAction->mAction = aFuncPtr; - sVanillaActions.Add(_DynosAction); -} - -static bool DynOS_Opt_CallVanillaAction(const char *aOptName) { - VanillaActionFunction _Func = DynOS_Opt_GetVanillaAction(aOptName); - if (_Func) { - _Func(NULL, 0); - return true; - } - return false; -} - -// -// Convert classic options menu into DynOS menu -// - -static DynosOption *DynOS_Opt_ConvertOption(const u8 *aLabel, const u8 *aTitle) { - static u32 sOptIdx = 0; - DynosOption *_Opt = New(); - _Opt->mName = String("vanilla_opt_%08X", sOptIdx++); - _Opt->mConfigName = ""; - _Opt->mLabel = { "", aLabel }; - _Opt->mTitle = { "", aTitle }; - _Opt->mDynos = false; - if (sPrevOpt == NULL) { // The very first option - _Opt->mPrev = NULL; - _Opt->mNext = NULL; - _Opt->mParent = NULL; - sOptionsMenu = _Opt; - } else { - if (sPrevOpt->mType == DOPT_SUBMENU && sPrevOpt->mSubMenu.mEmpty) { // First option of a sub-menu - _Opt->mPrev = NULL; - _Opt->mNext = NULL; - _Opt->mParent = sPrevOpt; - sPrevOpt->mSubMenu.mChild = _Opt; - sPrevOpt->mSubMenu.mEmpty = false; - } else { - _Opt->mPrev = sPrevOpt; - _Opt->mNext = NULL; - _Opt->mParent = sPrevOpt->mParent; - sPrevOpt->mNext = _Opt; - } - } - sPrevOpt = _Opt; - return _Opt; -} - -static void DynOS_Opt_EndSubMenu() { - if (sPrevOpt) { - if (sPrevOpt->mType == DOPT_SUBMENU && sPrevOpt->mSubMenu.mEmpty) { // ENDMENU command following a SUBMENU command - sPrevOpt->mSubMenu.mEmpty = false; - } else { - sPrevOpt = sPrevOpt->mParent; - } - } -} - -static void DynOS_Opt_ConvertSubMenu(const u8 *aLabel, const u8 *aTitle) { - DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aTitle); - _Opt->mType = DOPT_SUBMENU; - _Opt->mSubMenu.mChild = NULL; - _Opt->mSubMenu.mEmpty = true; -} - -static void DynOS_Opt_ConvertToggle(const u8 *aLabel, bool *pValue) { - DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel); - _Opt->mType = DOPT_TOGGLE; - _Opt->mToggle.mTog = (bool *) pValue; -} - -static void DynOS_Opt_ConvertScroll(const u8 *aLabel, s32 aMin, s32 aMax, s32 aStep, u32 *pValue) { - DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel); - _Opt->mType = DOPT_SCROLL; - _Opt->mScroll.mMin = aMin; - _Opt->mScroll.mMax = aMax; - _Opt->mScroll.mStep = aStep; - _Opt->mScroll.mValue = (s32 *) pValue; -} - -static void DynOS_Opt_ConvertChoice(const u8 *aLabel, const u8 **aChoices, s32 aCount, u32 *pValue) { - DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel); - _Opt->mType = DOPT_CHOICE; - _Opt->mChoice.mIndex = (s32 *) pValue; - for (s32 i = 0; i != aCount; ++i) { - _Opt->mChoice.mChoices.Add({ "", aChoices[i] }); - } -} - -static void DynOS_Opt_ConvertButton(const u8 *aLabel, VanillaActionFunction aAction) { - DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel); - _Opt->mType = DOPT_BUTTON; - _Opt->mButton.mFuncName = "DynOS_Opt_CallVanillaAction"; - DynOS_Opt_AddVanillaAction(_Opt->mName, aAction); -} - -static void DynOS_Opt_ConvertBind(const u8 *aLabel, u32 *pBinds) { - DynosOption *_Opt = DynOS_Opt_ConvertOption(aLabel, aLabel); - _Opt->mType = DOPT_BIND; - _Opt->mBind.mMask = 0; - _Opt->mBind.mBinds = pBinds; - _Opt->mBind.mIndex = 0; -} - -#ifndef COOP -extern "C" { -extern void dynos_opt_convert_vanilla_main_menu(); -void dynos_opt_end_submenu() { return DynOS_Opt_EndSubMenu(); } -void dynos_opt_convert_submenu(const u8 *label, const u8 *title) { return DynOS_Opt_ConvertSubMenu(label, title); } -void dynos_opt_convert_toggle(const u8 *label, bool *bval) { return DynOS_Opt_ConvertToggle(label, bval); } -void dynos_opt_convert_scroll(const u8 *label, s32 min, s32 max, s32 step, u32 *uval) { return DynOS_Opt_ConvertScroll(label, min, max, step, uval); } -void dynos_opt_convert_choice(const u8 *label, const u8 **choices, s32 numChoices, u32 *uval) { return DynOS_Opt_ConvertChoice(label, choices, numChoices, uval); } -void dynos_opt_convert_button(const u8 *label, void *action) { return DynOS_Opt_ConvertButton(label, (VanillaActionFunction) action); } -void dynos_opt_convert_bind(const u8 *label, u32 *uval) { return DynOS_Opt_ConvertBind(label, uval); } -} -#endif -void DynOS_Opt_InitVanilla(DynosOption *&aOptionsMenu) { - sPrevOpt = NULL; -#ifndef COOP - dynos_opt_convert_vanilla_main_menu(); -#endif - DynOS_Opt_AddAction("DynOS_Opt_CallVanillaAction", DynOS_Opt_CallVanillaAction, true); - aOptionsMenu = sOptionsMenu; -} diff --git a/data/dynos_opt_vanilla_c.c b/data/dynos_opt_vanilla_c.c deleted file mode 100644 index d9cb3796..00000000 --- a/data/dynos_opt_vanilla_c.c +++ /dev/null @@ -1,72 +0,0 @@ - -#ifndef COOP -// Not my problem -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wsizeof-pointer-div" -#pragma GCC diagnostic ignored "-Wdiscarded-qualifiers" -#pragma GCC diagnostic ignored "-Wpointer-sign" -#pragma GCC diagnostic ignored "-Wsign-compare" -#define optmenu_toggle optmenu_toggle_unused -#define optmenu_draw optmenu_draw_unused -#define optmenu_draw_prompt optmenu_draw_prompt_unused -#define optmenu_check_buttons optmenu_check_buttons_unused -#define optmenu_open optmenu_open_unused -#define DYNOS_INL -#include "game/options_menu.c" -#undef DYNOS_INL -#undef optmenu_toggle -#undef optmenu_draw -#undef optmenu_draw_prompt -#undef optmenu_check_buttons -#undef optmenu_open -#pragma GCC diagnostic pop -// Now, that's my problem - -extern void dynos_opt_end_submenu(); -extern void dynos_opt_convert_submenu(const u8 *label, const u8 *title); -extern void dynos_opt_convert_toggle(const u8 *label, bool *bval); -extern void dynos_opt_convert_scroll(const u8 *label, s32 min, s32 max, s32 step, u32 *uval); -extern void dynos_opt_convert_choice(const u8 *label, const u8 **choices, s32 numChoices, u32 *uval); -extern void dynos_opt_convert_button(const u8 *label, void *action); -extern void dynos_opt_convert_bind(const u8 *label, u32 *uval); - -static void dynos_opt_convert_menu(struct SubMenu *submenu) { - for (s32 i = 0; i != submenu->numOpts; ++i) { - struct Option *opt = &submenu->opts[i]; - switch (opt->type) { - case OPT_TOGGLE: - dynos_opt_convert_toggle(opt->label, opt->bval); - break; - - case OPT_CHOICE: - dynos_opt_convert_choice(opt->label, opt->choices, opt->numChoices, opt->uval); - break; - - case OPT_SCROLL: - dynos_opt_convert_scroll(opt->label, opt->scrMin, opt->scrMax, opt->scrStep, opt->uval); - break; - - case OPT_SUBMENU: - dynos_opt_convert_submenu(opt->label, opt->nextMenu->label); - dynos_opt_convert_menu(opt->nextMenu); - dynos_opt_end_submenu(); - break; - - case OPT_BIND: - dynos_opt_convert_bind(opt->label, opt->uval); - break; - - case OPT_BUTTON: - dynos_opt_convert_button(opt->label, opt->actionFn); - break; - - default: - break; - } - } -} - -void dynos_opt_convert_vanilla_main_menu() { - dynos_opt_convert_menu(&menuMain); -} -#endif \ No newline at end of file diff --git a/data/dynos_warps.cpp b/data/dynos_warps.cpp index 9a2a95c0..1900604f 100644 --- a/data/dynos_warps.cpp +++ b/data/dynos_warps.cpp @@ -10,7 +10,6 @@ extern "C" { #include "game/level_update.h" #include "game/sound_init.h" #include "game/object_list_processor.h" -#include "game/options_menu.h" #include "pc/network/packets/packet.h" #include "pc/lua/smlua_hooks.h" extern s8 gDialogBoxState; @@ -82,19 +81,18 @@ bool DynOS_Warp_RestartLevel() { // bool DynOS_Warp_ExitLevel(s32 aDelay) { - if (DynOS_Level_GetCourse(gCurrLevelNum) == COURSE_NONE) { + if (DynOS_Level_GetCourse(gCurrLevelNum) == COURSE_NONE || !DynOS_Level_GetWarpDeath(gCurrLevelNum, gCurrAreaIndex)) { return false; } // Close the pause menu if it was open - optmenu_toggle(); level_set_transition(0, NULL); gDialogBoxState = 0; gMenuMode = -1; // Cancel out every music/sound/sequence for (u16 seqid = 0; seqid != SEQ_COUNT; ++seqid) { - stop_background_music(seqid); + stop_background_music(seqid); } play_shell_music(); stop_shell_music(); @@ -106,7 +104,7 @@ bool DynOS_Warp_ExitLevel(s32 aDelay) { // Play Mario head transition, and change play mode to avoid getting stuck on the pause menu aDelay = MAX(1, aDelay); gMarioState->invincTimer = -1; - play_transition(WARP_TRANSITION_FADE_INTO_MARIO, aDelay, 0x00, 0x00, 0x00); + play_transition(WARP_TRANSITION_FADE_INTO_COLOR, aDelay, 0x00, 0x00, 0x00); set_play_mode(0); sDynosExitLevelNum = gCurrLevelNum; sDynosExitAreaNum = gCurrAreaIndex; @@ -114,19 +112,18 @@ bool DynOS_Warp_ExitLevel(s32 aDelay) { } bool DynOS_Warp_ToCastle(s32 aLevel) { - if (DynOS_Level_GetCourse(aLevel) == COURSE_NONE) { + if (DynOS_Level_GetCourse(aLevel) == COURSE_NONE || !DynOS_Level_GetWarpDeath(aLevel, 1)) { return false; } // Close the pause menu if it was open - optmenu_toggle(); level_set_transition(0, NULL); gDialogBoxState = 0; gMenuMode = -1; // Cancel out every music/sound/sequence for (u16 seqid = 0; seqid != SEQ_COUNT; ++seqid) { - stop_background_music(seqid); + stop_background_music(seqid); } play_shell_music(); stop_shell_music(); @@ -142,79 +139,6 @@ bool DynOS_Warp_ToCastle(s32 aLevel) { return true; } -// -// Params -// - -const char *DynOS_Warp_GetParamName(s32 aLevel, s32 aIndex) { - static const char *sLevelParams[][5] = { - { "", "", "", "", "" }, - { "None", "No Submarine, No Poles", "Submarine Only", "Poles Only", "Submarine And Poles" }, - { "None", "Water Level: Lowest", "Water Level: Low", "Water Level: High", "Water Level: Highest" }, - { "None", "Top Flooded", "Top Drained", "Top Flooded", "Top Drained" }, - { "None", "Clock Speed: Stopped", "Clock Speed: Slow", "Clock Speed: Fast", "Clock Speed: Random" }, - }; - switch (aLevel) { - case LEVEL_DDD: return sLevelParams[1][MIN(4, aIndex)]; - case LEVEL_WDW: return sLevelParams[2][MIN(4, aIndex)]; - case LEVEL_THI: return sLevelParams[3][MIN(4, aIndex)]; - case LEVEL_TTC: return sLevelParams[4][MIN(4, aIndex)]; - } - return sLevelParams[0][MIN(4, aIndex)]; -} - -// Called thrice -// Pass -1 to use the previous value (only once) -void DynOS_Warp_SetParam(s32 aLevel, s32 aIndex) { - static s32 sDynosWarpPrevParamIndex = -1; - if (aIndex == -1) { - aIndex = sDynosWarpPrevParamIndex; - sDynosWarpPrevParamIndex = -1; - } else { - sDynosWarpPrevParamIndex = aIndex; - } - - switch (aLevel) { - case LEVEL_DDD: - switch (aIndex) { - case 1: gDDDBowsersSub = 0; gDDDPoles = 0; break; - case 2: gDDDBowsersSub = 1; gDDDPoles = 0; break; - case 3: gDDDBowsersSub = 0; gDDDPoles = 1; break; - case 4: gDDDBowsersSub = 1; gDDDPoles = 1; break; - } - break; - - case LEVEL_WDW: - if (gEnvironmentRegions && gEnvironmentRegionsLength > 6) { - switch (aIndex) { - case 1: gEnvironmentRegions[6] = *gEnvironmentLevels = 31; gWdwWaterLevelSet = 1; break; - case 2: gEnvironmentRegions[6] = *gEnvironmentLevels = 1024; gWdwWaterLevelSet = 1; break; - case 3: gEnvironmentRegions[6] = *gEnvironmentLevels = 1792; gWdwWaterLevelSet = 1; break; - case 4: gEnvironmentRegions[6] = *gEnvironmentLevels = 2816; gWdwWaterLevelSet = 1; break; - } - } - break; - - case LEVEL_THI: - switch (aIndex) { - case 1: gTHIWaterDrained = 0; break; - case 2: gTHIWaterDrained = 1; break; - case 3: gTHIWaterDrained = 0; break; - case 4: gTHIWaterDrained = 1; break; - } - break; - - case LEVEL_TTC: - switch (aIndex) { - case 1: gTTCSpeedSetting = TTC_SPEED_STOPPED; break; - case 2: gTTCSpeedSetting = TTC_SPEED_SLOW; break; - case 3: gTTCSpeedSetting = TTC_SPEED_FAST; break; - case 4: gTTCSpeedSetting = TTC_SPEED_RANDOM; break; - } - break; - } -} - // // Update // @@ -226,14 +150,13 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) { if (sDynosWarpTargetArea == -1) { // Close the pause menu if it was open - optmenu_toggle(); level_set_transition(0, NULL); gDialogBoxState = 0; gMenuMode = -1; // Cancel out every music/sound/sequence for (u16 seqid = 0; seqid != SEQ_COUNT; ++seqid) { - stop_background_music(seqid); + stop_background_music(seqid); } play_shell_music(); stop_shell_music(); @@ -259,13 +182,10 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) { gCurrLevelNum = sDynosWarpLevelNum; gCurrCourseNum = DynOS_Level_GetCourse(gCurrLevelNum); gSavedCourseNum = gCurrCourseNum; - gCurrActNum = MAX(1, sDynosWarpActNum * (gCurrCourseNum <= COURSE_STAGES_MAX)); + gCurrActNum = MAX(0, sDynosWarpActNum * (gCurrCourseNum <= COURSE_STAGES_MAX)); gDialogCourseActNum = gCurrActNum; gCurrAreaIndex = sDynosWarpAreaNum; gCurrActStarNum = sDynosWarpActNum; -#ifndef COOP - DynOS_Warp_SetParam(gCurrLevelNum, DynOS_Opt_GetValue("dynos_warp_param")); -#endif sDynosWarpTargetArea = gCurrAreaIndex; // Set up new level script @@ -285,7 +205,7 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) { } // Phase 3 - End level initialization - if (aIsLevelInitDone) { + if (aIsLevelInitDone && gMarioObjects[0]) { // Get Warp s16 *_Warp; @@ -306,9 +226,6 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) { gMarioSpawnInfo->areaIndex = gCurrAreaIndex; init_mario(); set_mario_initial_action(gMarioState, sDynosWarpSpawnType, 0); -#ifndef COOP - DynOS_Warp_SetParam(gCurrLevelNum, DynOS_Opt_GetValue("dynos_warp_param")); -#endif // Init transition if (gCurrentArea != NULL) { @@ -447,7 +364,7 @@ static void *DynOS_Warp_UpdateExit(void *aCmd, bool aIsLevelInitDone) { } // Phase 3 - End level initialization - if (sDynosExitTargetWarp && aIsLevelInitDone) { + if (sDynosExitTargetWarp && aIsLevelInitDone && gMarioObjects[0]) { // Find target position // Because of course, every hack has its own warp distances and orientations... @@ -471,14 +388,18 @@ static void *DynOS_Warp_UpdateExit(void *aCmd, bool aIsLevelInitDone) { set_mario_initial_action(gMarioState, MARIO_SPAWN_UNKNOWN_02, 0); // Init transition - reset_camera(gCurrentArea->camera); - init_camera(gCurrentArea->camera); + if (gCurrentArea != NULL) { + reset_camera(gCurrentArea->camera); + init_camera(gCurrentArea->camera); + } sDelayedWarpOp = WARP_OP_NONE; play_transition(WARP_TRANSITION_FADE_FROM_STAR, 15, 0x00, 0x00, 0x00); play_sound(SOUND_MENU_MARIO_CASTLE_WARP, gGlobalSoundSource); // Set music - set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0); + if (gCurrentArea != NULL) { + set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0); + } sDynosExitTargetWarp = NULL; // lua hooks diff --git a/docs/lua/functions-4.md b/docs/lua/functions-4.md index 06aca719..15194a50 100644 --- a/docs/lua/functions-4.md +++ b/docs/lua/functions-4.md @@ -7384,6 +7384,50 @@
+## [collision_find_ceil](#collision_find_ceil) + +### Lua Example +`local SurfaceValue = collision_find_ceil(x, y, z)` + +### Parameters +| Field | Type | +| ----- | ---- | +| x | `number` | +| y | `number` | +| z | `number` | + +### Returns +[Surface](structs.md#Surface) + +### C Prototype +`struct Surface* collision_find_ceil(f32 x, f32 y, f32 z);` + +[:arrow_up_small:](#) + +
+ +## [collision_find_floor](#collision_find_floor) + +### Lua Example +`local SurfaceValue = collision_find_floor(x, y, z)` + +### Parameters +| Field | Type | +| ----- | ---- | +| x | `number` | +| y | `number` | +| z | `number` | + +### Returns +[Surface](structs.md#Surface) + +### C Prototype +`struct Surface* collision_find_floor(f32 x, f32 y, f32 z);` + +[:arrow_up_small:](#) + +
+ ## [collision_find_surface_on_ray](#collision_find_surface_on_ray) ### Lua Example @@ -7564,6 +7608,26 @@
+## [smlua_level_util_get_info_from_course_num](#smlua_level_util_get_info_from_course_num) + +### Lua Example +`local CustomLevelInfoValue = smlua_level_util_get_info_from_course_num(courseNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | + +### Returns +[CustomLevelInfo](structs.md#CustomLevelInfo) + +### C Prototype +`struct CustomLevelInfo* smlua_level_util_get_info_from_course_num(u8 courseNum);` + +[:arrow_up_small:](#) + +
+ ## [smlua_level_util_get_info_from_short_name](#smlua_level_util_get_info_from_short_name) ### Lua Example diff --git a/docs/lua/functions-5.md b/docs/lua/functions-5.md index bcb5f24d..4a76c5a4 100644 --- a/docs/lua/functions-5.md +++ b/docs/lua/functions-5.md @@ -2384,6 +2384,91 @@
+## [smlua_text_utils_act_name_get](#smlua_text_utils_act_name_get) + +### Lua Example +`local stringValue = smlua_text_utils_act_name_get(courseNum, actNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | +| actNum | `integer` | + +### Returns +- `string` + +### C Prototype +`const char* smlua_text_utils_act_name_get(s16 courseNum, u8 actNum);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_act_name_is_modified](#smlua_text_utils_act_name_is_modified) + +### Lua Example +`local booleanValue = smlua_text_utils_act_name_is_modified(courseNum, actNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | +| actNum | `integer` | + +### Returns +- `boolean` + +### C Prototype +`bool smlua_text_utils_act_name_is_modified(s16 courseNum, u8 actNum);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_act_name_replace](#smlua_text_utils_act_name_replace) + +### Lua Example +`smlua_text_utils_act_name_replace(courseNum, actNum, name)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | +| actNum | `integer` | +| name | `string` | + +### Returns +- None + +### C Prototype +`void smlua_text_utils_act_name_replace(s16 courseNum, u8 actNum, const char* name);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_act_name_reset](#smlua_text_utils_act_name_reset) + +### Lua Example +`smlua_text_utils_act_name_reset(courseNum, actNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | +| actNum | `integer` | + +### Returns +- None + +### C Prototype +`void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum);` + +[:arrow_up_small:](#) + +
+ ## [smlua_text_utils_castle_secret_stars_replace](#smlua_text_utils_castle_secret_stars_replace) ### Lua Example @@ -2431,6 +2516,87 @@
+## [smlua_text_utils_course_name_get](#smlua_text_utils_course_name_get) + +### Lua Example +`local stringValue = smlua_text_utils_course_name_get(courseNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | + +### Returns +- `string` + +### C Prototype +`const char* smlua_text_utils_course_name_get(s16 courseNum);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_course_name_mod_index](#smlua_text_utils_course_name_mod_index) + +### Lua Example +`local integerValue = smlua_text_utils_course_name_mod_index(courseNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | + +### Returns +- `integer` + +### C Prototype +`s32 smlua_text_utils_course_name_mod_index(s16 courseNum);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_course_name_replace](#smlua_text_utils_course_name_replace) + +### Lua Example +`smlua_text_utils_course_name_replace(courseNum, name)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | +| name | `string` | + +### Returns +- None + +### C Prototype +`void smlua_text_utils_course_name_replace(s16 courseNum, const char* name);` + +[:arrow_up_small:](#) + +
+ +## [smlua_text_utils_course_name_reset](#smlua_text_utils_course_name_reset) + +### Lua Example +`smlua_text_utils_course_name_reset(courseNum)` + +### Parameters +| Field | Type | +| ----- | ---- | +| courseNum | `integer` | + +### Returns +- None + +### C Prototype +`void smlua_text_utils_course_name_reset(s16 courseNum);` + +[:arrow_up_small:](#) + +
+ ## [smlua_text_utils_dialog_replace](#smlua_text_utils_dialog_replace) ### Lua Example @@ -2495,24 +2661,6 @@
-## [smlua_text_utils_reset_all](#smlua_text_utils_reset_all) - -### Lua Example -`smlua_text_utils_reset_all()` - -### Parameters -- None - -### Returns -- None - -### C Prototype -`void smlua_text_utils_reset_all(void);` - -[:arrow_up_small:](#) - -
- ## [smlua_text_utils_secret_star_replace](#smlua_text_utils_secret_star_replace) ### Lua Example diff --git a/docs/lua/functions.md b/docs/lua/functions.md index f4cddf94..ff947990 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1521,6 +1521,8 @@
- smlua_collision_utils.h + - [collision_find_ceil](functions-4.md#collision_find_ceil) + - [collision_find_floor](functions-4.md#collision_find_floor) - [collision_find_surface_on_ray](functions-4.md#collision_find_surface_on_ray) - [collision_get_temp_wall_collision_data](functions-4.md#collision_get_temp_wall_collision_data) - [get_water_surface_pseudo_floor](functions-4.md#get_water_surface_pseudo_floor) @@ -1537,6 +1539,7 @@ - [level_register](functions-4.md#level_register) - [smlua_level_util_change_area](functions-4.md#smlua_level_util_change_area) - [smlua_level_util_get_info](functions-4.md#smlua_level_util_get_info) + - [smlua_level_util_get_info_from_course_num](functions-4.md#smlua_level_util_get_info_from_course_num) - [smlua_level_util_get_info_from_short_name](functions-4.md#smlua_level_util_get_info_from_short_name) - [warp_exit_level](functions-4.md#warp_exit_level) - [warp_restart_level](functions-4.md#warp_restart_level) @@ -1690,12 +1693,19 @@
- smlua_text_utils.h + - [smlua_text_utils_act_name_get](functions-5.md#smlua_text_utils_act_name_get) + - [smlua_text_utils_act_name_is_modified](functions-5.md#smlua_text_utils_act_name_is_modified) + - [smlua_text_utils_act_name_replace](functions-5.md#smlua_text_utils_act_name_replace) + - [smlua_text_utils_act_name_reset](functions-5.md#smlua_text_utils_act_name_reset) - [smlua_text_utils_castle_secret_stars_replace](functions-5.md#smlua_text_utils_castle_secret_stars_replace) - [smlua_text_utils_course_acts_replace](functions-5.md#smlua_text_utils_course_acts_replace) + - [smlua_text_utils_course_name_get](functions-5.md#smlua_text_utils_course_name_get) + - [smlua_text_utils_course_name_mod_index](functions-5.md#smlua_text_utils_course_name_mod_index) + - [smlua_text_utils_course_name_replace](functions-5.md#smlua_text_utils_course_name_replace) + - [smlua_text_utils_course_name_reset](functions-5.md#smlua_text_utils_course_name_reset) - [smlua_text_utils_dialog_replace](functions-5.md#smlua_text_utils_dialog_replace) - [smlua_text_utils_extra_text_replace](functions-5.md#smlua_text_utils_extra_text_replace) - [smlua_text_utils_get_language](functions-5.md#smlua_text_utils_get_language) - - [smlua_text_utils_reset_all](functions-5.md#smlua_text_utils_reset_all) - [smlua_text_utils_secret_star_replace](functions-5.md#smlua_text_utils_secret_star_replace)
diff --git a/src/engine/surface_load.c b/src/engine/surface_load.c index 2422a548..188078c0 100644 --- a/src/engine/surface_load.c +++ b/src/engine/surface_load.c @@ -154,32 +154,14 @@ static void add_surface_to_cell(s16 dynamic, s16 cellX, s16 cellZ, struct Surfac /** * Returns the lowest of three values. */ -static s16 min_3(s16 a0, s16 a1, s16 a2) { - if (a1 < a0) { - a0 = a1; - } - if (a2 < a0) { - a0 = a2; - } - - return a0; -} +#define min_3(a0, a1, a2) MIN(MIN(a0, a1), a2) /** * Returns the highest of three values. */ -static s16 max_3(s16 a0, s16 a1, s16 a2) { - if (a1 > a0) { - a0 = a1; - } - if (a2 > a0) { - a0 = a2; - } - - return a0; -} +#define max_3(a0, a1, a2) MAX(MAX(a0, a1), a2) /** * Every level is split into 16 * 16 cells of surfaces (to limit computing @@ -378,48 +360,25 @@ static struct Surface *read_surface_data(s16 *vertexData, s16 **vertexIndices) { * Returns whether a surface has exertion/moves Mario * based on the surface type. */ -static s32 surface_has_force(s16 surfaceType) { - s32 hasForce = FALSE; - - switch (surfaceType) { - case SURFACE_0004: // Unused - case SURFACE_FLOWING_WATER: - case SURFACE_DEEP_MOVING_QUICKSAND: - case SURFACE_SHALLOW_MOVING_QUICKSAND: - case SURFACE_MOVING_QUICKSAND: - case SURFACE_HORIZONTAL_WIND: - case SURFACE_INSTANT_MOVING_QUICKSAND: - hasForce = TRUE; - break; - - default: - break; - } - return hasForce; +static bool surface_has_force(s16 surfaceType) { + return surfaceType == SURFACE_0004 || + surfaceType == SURFACE_FLOWING_WATER || + surfaceType == SURFACE_HORIZONTAL_WIND || + surfaceType == SURFACE_MOVING_QUICKSAND || + surfaceType == SURFACE_DEEP_MOVING_QUICKSAND || + surfaceType == SURFACE_SHALLOW_MOVING_QUICKSAND || + surfaceType == SURFACE_INSTANT_MOVING_QUICKSAND; } /** * Returns whether a surface should have the * SURFACE_FLAG_NO_CAM_COLLISION flag. */ -static s32 surf_has_no_cam_collision(s16 surfaceType) { - s32 flags = 0; - - switch (surfaceType) { - case SURFACE_RAYCAST: - case SURFACE_NO_CAM_COLLISION: - case SURFACE_NO_CAM_COLLISION_77: // Unused - case SURFACE_NO_CAM_COL_VERY_SLIPPERY: - case SURFACE_VANISH_CAP_WALLS: - case SURFACE_SWITCH: - flags = SURFACE_FLAG_NO_CAM_COLLISION; - break; - - default: - break; - } - - return flags; +static bool surf_has_no_cam_collision(s16 surfaceType) { + return surfaceType == SURFACE_SWITCH || + surfaceType == SURFACE_NO_CAM_COLLISION || + surfaceType == SURFACE_NO_CAM_COLLISION_77 || + surfaceType == SURFACE_NO_CAM_COL_VERY_SLIPPERY; } /** @@ -427,17 +386,16 @@ static s32 surf_has_no_cam_collision(s16 surfaceType) { * exertion, and room. */ static void load_static_surfaces(s16 **data, s16 *vertexData, s16 surfaceType, s8 **surfaceRooms) { - s32 i; s32 numSurfaces; struct Surface *surface; s8 room = 0; - s16 hasForce = surface_has_force(surfaceType); - s16 flags = surf_has_no_cam_collision(surfaceType); + bool hasForce = surface_has_force(surfaceType); + bool flags = surf_has_no_cam_collision(surfaceType); numSurfaces = *(*data); *data += 1; - for (i = 0; i < numSurfaces; i++) { + for (s32 i = 0; i < numSurfaces; i++) { if (*surfaceRooms != NULL) { room = *(*surfaceRooms); *surfaceRooms += 1; @@ -486,7 +444,6 @@ static s16 *read_vertex_data(s16 **data) { */ static void load_environmental_regions(s16 **data) { s32 numRegions; - s32 i; gEnvironmentRegionsLength = 0; gEnvironmentRegions = *data; @@ -497,7 +454,7 @@ static void load_environmental_regions(s16 **data) { numRegions = 20; } - for (i = 0; i < numRegions; i++) { + for (s32 i = 0; i < numRegions; i++) { UNUSED s16 val, loX, loZ, hiX, hiZ; s16 height; diff --git a/src/game/behaviors/camera_lakitu.inc.c b/src/game/behaviors/camera_lakitu.inc.c index eec0059b..51eea749 100644 --- a/src/game/behaviors/camera_lakitu.inc.c +++ b/src/game/behaviors/camera_lakitu.inc.c @@ -30,7 +30,7 @@ static void bhv_camera_lakitu_on_received_post(u8 localIndex) { void bhv_camera_lakitu_init(void) { if (o->oBehParams2ndByte != CAMERA_LAKITU_BP_FOLLOW_CAMERA) { // Despawn unless this is the very beginning of the game - if (gNeverEnteredCastle != TRUE) { + if (!gNeverEnteredCastle) { obj_mark_for_deletion(o); return; } @@ -38,7 +38,7 @@ void bhv_camera_lakitu_init(void) { spawn_object_relative_with_scale(CLOUD_BP_LAKITU_CLOUD, 0, 0, 0, 2.0f, o, MODEL_MIST, bhvCloud); } lakituTargetLocalIndex = UNKNOWN_LOCAL_INDEX; - + if (!sync_object_is_initialized(o->oSyncID)) { struct SyncObject *so = sync_object_init(o, 4000.0f); if (so) { diff --git a/src/game/behaviors/snowman.inc.c b/src/game/behaviors/snowman.inc.c index 86d0e7ad..65ea5def 100644 --- a/src/game/behaviors/snowman.inc.c +++ b/src/game/behaviors/snowman.inc.c @@ -131,23 +131,20 @@ static u8 bhv_snowmans_bottom_loop_continue_dialog(void) { } void bhv_snowmans_bottom_loop(void) { - s16 sp1E; - struct MarioState* marioState = nearest_mario_state_to_object(o); switch (o->oAction) { case 0: if (marioState + && marioState->playerIndex == 0 && should_start_or_continue_dialog(marioState, o) && (is_point_within_radius_of_mario(o->oPosX, o->oPosY, o->oPosZ, 400) == 1) - && set_mario_npc_dialog(&gMarioStates[0], 1, bhv_snowmans_bottom_loop_continue_dialog) == 2) { - sp1E = cutscene_object_with_dialog(CUTSCENE_DIALOG, o, gBehaviorValues.dialogs.SnowmanHeadBodyDialog); - if (sp1E) { - o->oForwardVel = 10.0f; - o->oAction = 1; - set_mario_npc_dialog(&gMarioStates[0], 0, NULL); - network_send_object(o); - } + && set_mario_npc_dialog(&gMarioStates[0], 1, bhv_snowmans_bottom_loop_continue_dialog) + && cutscene_object_with_dialog(CUTSCENE_DIALOG, o, gBehaviorValues.dialogs.SnowmanHeadBodyDialog)) { + o->oForwardVel = 10.0f; + o->oAction = 1; + set_mario_npc_dialog(&gMarioStates[0], 0, NULL); + network_send_object(o); } break; diff --git a/src/game/behaviors/spawn_star.inc.c b/src/game/behaviors/spawn_star.inc.c index 0ddcbb1e..195549a6 100644 --- a/src/game/behaviors/spawn_star.inc.c +++ b/src/game/behaviors/spawn_star.inc.c @@ -59,10 +59,10 @@ static struct ObjectHitbox sCollectStarHitbox = { }; void bhv_collect_star_init(void) { - s8 starId; + s16 starId; u8 currentLevelStarFlags; - starId = (o->oBehParams >> 24) & 0xFF; + starId = o->oBehParams >> 24; currentLevelStarFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1); if (currentLevelStarFlags & (1 << starId)) { cur_obj_set_model(MODEL_TRANSPARENT_STAR); @@ -256,7 +256,7 @@ struct Object *spawn_no_exit_star(f32 x, f32 y, f32 z) { /** * A special star spawning routine just for a networked stars. * These stars require the global index for a network player for proper - * cutscene functionality. + * cutscene functionality. */ struct Object *spawn_networked_default_star(f32 x, f32 y, f32 z, u8 networkPlayerIndex) { if (sCurrPlayMode != PLAY_MODE_NORMAL && sCurrPlayMode != PLAY_MODE_PAUSED) { return NULL; } @@ -298,7 +298,7 @@ void bhv_hidden_red_coin_star_init(void) { if (gCurrentArea) { o->oHiddenStarTriggerCounter = gCurrentArea->numRedCoins - redCoins; } - + // We haven't interacted with a player yet. // We also don't sync this as not only is it not required // but it also is only set for an interaction. @@ -306,7 +306,7 @@ void bhv_hidden_red_coin_star_init(void) { // and if it wasn't. You couldn't of possibly been the one // who last interacted to begin with. o->oHiddenStarLastInteractedObject = NULL; - + if (!sync_object_is_initialized(o->oSyncID)) { struct SyncObject *so = sync_object_init(o, SYNC_DISTANCE_ONLY_EVENTS); if (so) { diff --git a/src/game/camera.c b/src/game/camera.c index b96fb212..29829310 100644 --- a/src/game/camera.c +++ b/src/game/camera.c @@ -3112,10 +3112,12 @@ void update_lakitu(struct Camera *c) { gLakituState.defMode = c->defMode; } +extern bool gIsDemoActive; static void update_romhack_camera_override(struct Camera *c) { if (gOverrideRomhackCamera == RCO_NONE) { return; } if (c->mode == CAMERA_MODE_ROM_HACK) { return; } if (dynos_level_is_vanilla_level(gCurrLevelNum)) { return; } + if (gIsDemoActive) { return; } if (gOverrideRomhackCamera == RCO_ALL_EXCEPT_BOWSER) { if (gCurrLevelNum == LEVEL_BOWSER_1 || gCurrLevelNum == LEVEL_BOWSER_2 || gCurrLevelNum == LEVEL_BOWSER_3) { @@ -3516,7 +3518,7 @@ void init_camera(struct Camera *c) { // Make sure Bowser is in a state that we'd start speaking to him in. obj = find_object_with_behavior(bhvBowser); if (obj != NULL && obj->oAction != 5) { break; } - + start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA); } else if (gSecondCameraFocus != NULL) { gSecondCameraFocus->oBowserUnk88 = 2; @@ -3525,7 +3527,7 @@ void init_camera(struct Camera *c) { // Make sure Bowser is in a state that we'd start speaking to him in. obj = find_object_with_behavior(bhvBowser); if (obj != NULL && obj->oAction != 5) { break; } - + start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA); #endif break; @@ -3533,14 +3535,14 @@ void init_camera(struct Camera *c) { // Make sure Bowser is in a state that we'd start speaking to him in. obj = find_object_with_behavior(bhvBowser); if (obj != NULL && obj->oAction != 5) { break; } - + start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA); break; case LEVEL_BOWSER_3: // Make sure Bowser is in a state that we'd start speaking to him in. obj = find_object_with_behavior(bhvBowser); if (obj != NULL && obj->oAction != 5) { break; } - + start_cutscene(c, CUTSCENE_ENTER_BOWSER_ARENA); break; @@ -9605,7 +9607,7 @@ BAD_RETURN(s32) cutscene_non_painting_set_cam_pos(struct Camera *c) { BAD_RETURN(s32) cutscene_non_painting_set_cam_focus(struct Camera *c) { if (!c) { return; } offset_rotated(c->focus, sCutsceneVars[7].point, sCutsceneVars[6].point, sCutsceneVars[7].angle); - + if (dynos_level_is_vanilla_level(gCurrLevelNum) && ((gPrevLevel == LEVEL_COTMC) || (gPrevLevel == LEVEL_HMC) || (gPrevLevel == LEVEL_RR) || (gPrevLevel == LEVEL_WMOTR))) { c->focus[0] = c->pos[0] + (sMarioCamState->pos[0] - c->pos[0]) * 0.7f; c->focus[1] = c->pos[1] + (sMarioCamState->pos[1] - c->pos[1]) * 0.4f; diff --git a/src/game/game_init.c b/src/game/game_init.c index c4c36e0d..f8f1ad3c 100644 --- a/src/game/game_init.c +++ b/src/game/game_init.c @@ -468,7 +468,6 @@ void read_controller_inputs(void) { if (gControllerBits) { osRecvMesg(&gSIEventMesgQueue, &D_80339BEC, OS_MESG_BLOCK); osContGetReadData(gInteractableOverridePad ? &gInteractablePad : &gControllerPads[0]); - dynos_update_opt((void *) &gControllerPads[0]); } run_demo_inputs(); diff --git a/src/game/hardcoded.c b/src/game/hardcoded.c index 7ada52d2..c66b73c1 100644 --- a/src/game/hardcoded.c +++ b/src/game/hardcoded.c @@ -34,6 +34,8 @@ #include "levels/wf/header.h" #include "levels/wmotr/header.h" +#include "src/pc/pc_main.h" + extern Trajectory sThiHugeMetalBallTraj[]; extern Trajectory sThiTinyMetalBallTraj[]; @@ -308,8 +310,7 @@ struct PaintingValues gPaintingValues = { 0 }; // functions // /////////////// -__attribute__((constructor)) -void hardcoded_reset_default_values(void) { +AT_STARTUP void hardcoded_reset_default_values(void) { gLevelValues = gDefaultLevelValues; gBehaviorValues = gDefaultBehaviorValues; diff --git a/src/game/ingame_menu.c b/src/game/ingame_menu.c index 8287a60b..182d1e0a 100644 --- a/src/game/ingame_menu.c +++ b/src/game/ingame_menu.c @@ -39,6 +39,7 @@ #ifdef BETTERCAMERA #include "bettercamera.h" #endif +#include "level_info.h" u16 gDialogColorFadeTimer; s8 gLastDialogLineNum; @@ -2515,38 +2516,13 @@ void render_pause_my_score_coins(void) { u8 textUnfilledStar[] = { TEXT_UNFILLED_STAR }; u8 strCourseNum[4]; - void **courseNameTbl; - u8 *courseName; - void **actNameTbl; - u8 *actName = NULL; - u8 courseIndex; + u8 courseIndex = gCurrCourseNum - 1; + u8 *courseName = (u8*) get_level_name_sm64(gCurrCourseNum, gCurrLevelNum, gCurrAreaIndex, 1); + u8 *actName = (u8*) get_star_name_sm64(gCurrCourseNum, gDialogCourseActNum, 1); u8 starFlags; -#ifndef VERSION_EU - courseNameTbl = segmented_to_virtual(seg2_course_name_table); - actNameTbl = segmented_to_virtual(seg2_act_name_table); -#endif - - courseIndex = gCurrCourseNum - 1; starFlags = save_file_get_star_flags(gCurrSaveFileNum - 1, gCurrCourseNum - 1); -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - actNameTbl = segmented_to_virtual(act_name_table_eu_en); - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - actNameTbl = segmented_to_virtual(act_name_table_eu_fr); - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - actNameTbl = segmented_to_virtual(act_name_table_eu_de); - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#endif - gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); @@ -2564,8 +2540,6 @@ void render_pause_my_score_coins(void) { print_generic_string(MYSCORE_X, 121, textMyScore); } - courseName = segmented_to_virtual(courseNameTbl[courseIndex]); - if (courseIndex < COURSE_STAGES_COUNT) { #ifdef VERSION_EU print_generic_string(48, 157, gTextCourseArr[gInGameLanguage]); @@ -2579,10 +2553,6 @@ void render_pause_my_score_coins(void) { print_generic_string(CRS_NUM_X1, 157, strCourseNum); #endif - if (gDialogCourseActNum >= 1 && gDialogCourseActNum <= 6) { - actName = segmented_to_virtual(actNameTbl[(gCurrCourseNum - 1) * 6 + gDialogCourseActNum - 1]); - } - if (starFlags & (1 << (gDialogCourseActNum - 1))) { print_generic_string(TXT_STAR_X, 140, textStar); } else { @@ -2838,11 +2808,7 @@ void render_pause_castle_course_stars(s16 x, s16 y, s16 fileNum, s16 courseNum) } void render_pause_castle_main_strings(s16 x, s16 y) { -#ifdef VERSION_EU - void **courseNameTbl; -#else - void **courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif + void **courseNameTbl = get_course_name_table(); #ifdef VERSION_EU u8 textCoin[] = { TEXT_COIN }; @@ -2856,20 +2822,6 @@ void render_pause_castle_main_strings(s16 x, s16 y) { u8 strVal[8]; s16 starNum = gDialogLineNum; -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#endif - handle_menu_scrolling(MENU_SCROLL_VERTICAL, &gDialogLineNum, -1, COURSE_STAGES_COUNT + 1); if (gDialogLineNum == COURSE_STAGES_COUNT + 1) { @@ -2936,7 +2888,7 @@ void render_pause_castle_main_strings(s16 x, s16 y) { static u32 pause_castle_get_stars(s32 index) { // Main courses (0-14), Secret courses (15-24) - if (index >= 0 && index < INDEX_CASTLE_STARS) { + if (COURSE_IS_VALID_COURSE(index)) { return save_file_get_star_flags(gCurrSaveFileNum - 1, index); } @@ -3061,24 +3013,8 @@ void render_pause_castle_main_strings_extended(s16 x, s16 y) { gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, gDialogTextAlpha); - - void **courseNameTbl = NULL; - -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#else - courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif + + void **courseNameTbl = get_course_name_table(); // Main courses (0-14) if (gDialogLineNum < COURSE_STAGES_COUNT) { @@ -3098,7 +3034,7 @@ void render_pause_castle_main_strings_extended(s16 x, s16 y) { render_pause_castle_course_name(courseName + 3, 160, y + 30); render_pause_castle_course_stars_extended(x + 20, y); } - + // Castle stars (25) else if (gDialogLineNum == INDEX_CASTLE_STARS) { const u8 *courseName = courseNameTbl[COURSE_MAX]; @@ -3150,7 +3086,7 @@ s16 render_pause_courses_and_castle(void) { play_sound(SOUND_MENU_PAUSE_HIGHPRIO, gGlobalSoundSource); #endif - if (gCurrCourseNum >= COURSE_MIN && gCurrCourseNum <= COURSE_MAX) { + if (COURSE_IS_VALID_COURSE(gCurrCourseNum)) { change_dialog_camera_angle(); gDialogBoxState = DIALOG_STATE_VERTICAL; } else { @@ -3227,14 +3163,9 @@ s16 render_pause_courses_and_castle(void) { } if (gDjuiPanelPauseCreated) { shade_screen(); } - if (gPlayer1Controller->buttonPressed & R_TRIG) + if (gPlayer1Controller->buttonPressed & R_TRIG) { djui_panel_pause_create(NULL); - -#ifndef COOP - // call into DynOS's menu system - optmenu_draw(); - optmenu_draw_prompt(); -#endif + } return 0; } @@ -3384,33 +3315,12 @@ void render_course_complete_lvl_info_and_hud_str(void) { u8 textSymStar[] = { GLYPH_STAR, GLYPH_SPACE }; #endif - void **actNameTbl; - void **courseNameTbl; + void **actNameTbl = get_act_name_table(); + void **courseNameTbl = get_course_name_table(); u8 *name; u8 strCourseNum[4]; -#ifdef VERSION_EU - s16 centerX; - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - actNameTbl = segmented_to_virtual(act_name_table_eu_en); - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - actNameTbl = segmented_to_virtual(act_name_table_eu_fr); - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - actNameTbl = segmented_to_virtual(act_name_table_eu_de); - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#else - actNameTbl = segmented_to_virtual(seg2_act_name_table); - courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif - if (gLastCompletedCourseNum <= COURSE_STAGES_MAX) { print_hud_course_complete_coins(118, 103); play_star_fanfare_and_flash_hud(1, 1 << (gLastCompletedStarNum - 1)); @@ -3435,7 +3345,7 @@ void render_course_complete_lvl_info_and_hud_str(void) { gSPDisplayList(gDisplayListHead++, dl_ia_text_begin); gDPSetEnvColor(gDisplayListHead++, 0, 0, 0, gDialogTextAlpha); #ifdef VERSION_EU - centerX = get_str_x_pos_from_center(153, name, 12.0f); + s16 centerX = get_str_x_pos_from_center(153, name, 12.0f); #endif print_generic_string(TXT_NAME_X1, 130, name); #ifndef VERSION_EU diff --git a/src/game/interaction.c b/src/game/interaction.c index 9a70c06b..956c8bb7 100644 --- a/src/game/interaction.c +++ b/src/game/interaction.c @@ -923,12 +923,7 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O u8 stayInLevelCommon = !(gCurrLevelNum == LEVEL_BOWSER_1 || gCurrLevelNum == LEVEL_BOWSER_2 || gCurrLevelNum == LEVEL_BOWSER_3); if (stayInLevelCommon && gServerSettings.stayInLevelAfterStar) { noExit = TRUE; } - - if (o->behavior == bhvBowserKey) { - gLastCollectedStarOrKey = 1; - } else { - gLastCollectedStarOrKey = 0; - } + gLastCollectedStarOrKey = o->behavior == bhvBowserKey; if (m->health >= 0x100) { @@ -981,7 +976,7 @@ u32 interact_star_or_key(struct MarioState *m, UNUSED u32 interactType, struct O m->interactObj = o; m->usedObj = o; - starIndex = (o->oBehParams >> 24) & 0x1F; + starIndex = o->oBehParams >> 24; if (m == &gMarioStates[0]) { // sync the star collection diff --git a/src/game/level_info.c b/src/game/level_info.c index 7af399d9..547420cc 100644 --- a/src/game/level_info.c +++ b/src/game/level_info.c @@ -9,6 +9,7 @@ #include "save_file.h" #include "types.h" #include "pc/lua/utils/smlua_level_utils.h" +#include "pc/lua/utils/smlua_text_utils.h" #ifdef VERSION_EU extern s32 gInGameLanguage; @@ -39,7 +40,7 @@ static const struct { const char *str; u8 c; } sSm64CharMap[] = { { "p", 0x33 }, { "q", 0x34 }, { "r", 0x35 }, { "s", 0x36 }, { "t", 0x37 }, { "u", 0x38 }, { "v", 0x39 }, { "w", 0x3A }, { "x", 0x3B }, { "y", 0x3C }, { "z", 0x3D }, - + // Punctuation { "...", 0xE6 }, // ellipsis { ")(", 0xE2 }, // close-open parentheses @@ -57,7 +58,7 @@ static const struct { const char *str; u8 c; } sSm64CharMap[] = { { "%", 0xF3 }, // percent { "?", 0xF4 }, // question mark { "~", 0xF7 }, // tilde - + // Symbols { "[A]", 0x54 }, // bold A { "[B]", 0x55 }, // bold B @@ -107,7 +108,7 @@ static void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii) { *str64 = 0xFF; } -static void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64) { +void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64) { for (; *str64 != 0xFF; str64++) { strAscii = sm64_to_ascii_char(strAscii, str64); } @@ -158,12 +159,40 @@ static void decapitalize_string_sm64(u8 *str64) { } } +void *get_course_name_table() { + void **courseNameTbl = segmented_to_virtual(seg2_course_name_table); + +#ifdef VERSION_EU + switch (gInGameLanguage) { + case LANGUAGE_ENGLISH: courseNameTbl = segmented_to_virtual(course_name_table_eu_en); break; + case LANGUAGE_FRENCH: courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); break; + case LANGUAGE_GERMAN: courseNameTbl = segmented_to_virtual(course_name_table_eu_de); break; + } +#endif + + return courseNameTbl; +} + +void *get_act_name_table() { + void **actNameTbl = segmented_to_virtual(seg2_act_name_table); + +#ifdef VERSION_EU + switch (gInGameLanguage) { + case LANGUAGE_ENGLISH: actNameTbl = segmented_to_virtual(act_name_table_eu_en); break; + case LANGUAGE_FRENCH: actNameTbl = segmented_to_virtual(act_name_table_eu_fr); break; + case LANGUAGE_GERMAN: actNameTbl = segmented_to_virtual(act_name_table_eu_de); break; + } +#endif + + return actNameTbl; +} + +extern struct CourseName *gReplacedActNameTable[]; + const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 charCase) { static char output[256]; - // Valid course: BOB to RR, Bowser stages and Secret courses - // There is no course name for Cake Ending, make it defaults to "Peach's Castle" - + // Custom course bool hasCustomName = false; if (levelNum >= CUSTOM_LEVEL_NUM_START) { struct CustomLevelInfo* info = smlua_level_util_get_info(levelNum); @@ -173,41 +202,39 @@ const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 } } - if (!hasCustomName && courseNum >= COURSE_MIN && courseNum < COURSE_MAX) { - void **courseNameTbl = NULL; -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: courseNameTbl = segmented_to_virtual(course_name_table_eu_en); break; - case LANGUAGE_FRENCH: courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); break; - case LANGUAGE_GERMAN: courseNameTbl = segmented_to_virtual(course_name_table_eu_de); break; - } -#else - courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif - const u8 *courseName = segmented_to_virtual(courseNameTbl[courseNum - COURSE_BOB]); - convert_string_sm64_to_ascii(output, courseName + 3); + if (gReplacedActNameTable[courseNum]->modIndex != -1) { + snprintf(output, 256, "%s", gReplacedActNameTable[courseNum]->name); } - - // Castle level - else if (!hasCustomName && courseNum == COURSE_NONE) { - switch (levelNum) { - case LEVEL_CASTLE: { - switch (areaIndex) { - case 1: snprintf(output, 256, "Castle Main Floor"); break; - case 2: snprintf(output, 256, "Castle Upper Floor"); break; - case 3: snprintf(output, 256, "Castle Basement"); break; - default: snprintf(output, 256, "Castle Purgatory"); break; - } - } break; - case LEVEL_CASTLE_GROUNDS: snprintf(output, 256, "Castle Grounds"); break; - case LEVEL_CASTLE_COURTYARD: snprintf(output, 256, "Castle Courtyard"); break; - default: snprintf(output, 256, "Peach's Castle"); - } - } - - // Default + else if (!hasCustomName) { - snprintf(output, 256, "Peach's Castle"); + if (COURSE_IS_VALID_COURSE(courseNum)) { + void **courseNameTbl = get_course_name_table(); + const u8 *courseName = segmented_to_virtual(courseNameTbl[courseNum - COURSE_BOB]); + convert_string_sm64_to_ascii(output, courseName + 3); + charCase = MIN(charCase, 0); // Don't need to capitalize vanilla course names + } + + // Castle level + else if (courseNum == COURSE_NONE) { + switch (levelNum) { + case LEVEL_CASTLE: { + switch (areaIndex) { + case 1: snprintf(output, 256, "Castle Main Floor"); break; + case 2: snprintf(output, 256, "Castle Upper Floor"); break; + case 3: snprintf(output, 256, "Castle Basement"); break; + default: snprintf(output, 256, "Castle Purgatory"); break; + } + } break; + case LEVEL_CASTLE_GROUNDS: snprintf(output, 256, "Castle Grounds"); break; + case LEVEL_CASTLE_COURTYARD: snprintf(output, 256, "Castle Courtyard"); break; + default: snprintf(output, 256, "Peach's Castle"); + } + } + + // Default + else { + snprintf(output, 256, "Peach's Castle"); + } } // Capitalize or decapitalize text @@ -221,7 +248,8 @@ const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 const u8 *get_level_name_sm64(s16 courseNum, s16 levelNum, s16 areaIndex, s16 charCase) { static u8 output[256]; - const char *levelName = get_level_name_ascii(courseNum, levelNum, areaIndex, charCase); + char levelName[256]; + snprintf(levelName, 256, " %d %s", courseNum, (char*) get_level_name_ascii(courseNum, levelNum, areaIndex, charCase)); convert_string_ascii_to_sm64(output, levelName); return output; } @@ -233,28 +261,24 @@ const char *get_level_name(s16 courseNum, s16 levelNum, s16 areaIndex) { const char *get_star_name_ascii(s16 courseNum, s16 starNum, s16 charCase) { static char output[256]; + if (gReplacedActNameTable[courseNum]->actName && gReplacedActNameTable[courseNum]->actName[starNum - 1].isModified) { + snprintf(output, 256, "%s", gReplacedActNameTable[courseNum]->actName[starNum - 1].name); + } + // Main courses: BOB to RR - if (COURSE_IS_MAIN_COURSE(courseNum)) { + else if (COURSE_IS_MAIN_COURSE(courseNum)) { if (starNum >= 1 && starNum <= 6) { - void **actNameTable = NULL; -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: actNameTable = segmented_to_virtual(act_name_table_eu_en); break; - case LANGUAGE_FRENCH: actNameTable = segmented_to_virtual(act_name_table_eu_fr); break; - case LANGUAGE_GERMAN: actNameTable = segmented_to_virtual(act_name_table_eu_de); break; - } -#else - actNameTable = segmented_to_virtual(seg2_act_name_table); -#endif + void **actNameTable = get_act_name_table(); const u8 *starName = segmented_to_virtual(actNameTable[(courseNum - COURSE_BOB) * 6 + (starNum - 1)]); convert_string_sm64_to_ascii(output, starName); + charCase = MIN(charCase, 0); // Don't need to capitalize vanilla act names } else if (starNum == 7) { - snprintf(output, 256, "%d Coins Star", (s32) gLevelValues.coinsRequiredForCoinStar); + snprintf(output, 256, "%d Coins Star", gLevelValues.coinsRequiredForCoinStar); } else { snprintf(output, 256, "A Secret Star!"); } } - + // Castle stars: Toads' and Mips' else if (courseNum == COURSE_NONE) { switch (starNum) { @@ -271,7 +295,7 @@ const char *get_star_name_ascii(s16 courseNum, s16 starNum, s16 charCase) { else if (courseNum <= COURSE_MAX) { snprintf(output, 256, "Star %d", starNum); } - + // Default else { snprintf(output, 256, "A Secret Star!"); diff --git a/src/game/level_info.h b/src/game/level_info.h index b0c81722..372921d2 100644 --- a/src/game/level_info.h +++ b/src/game/level_info.h @@ -3,6 +3,8 @@ #include +void *get_course_name_table(); +void *get_act_name_table(); const char *get_level_name_ascii(s16 courseNum, s16 levelNum, s16 areaIndex, s16 charCase); const u8 *get_level_name_sm64(s16 courseNum, s16 levelNum, s16 areaIndex, s16 charCase); const char *get_level_name(s16 courseNum, s16 levelNum, s16 areaIndex); diff --git a/src/game/level_update.c b/src/game/level_update.c index 53de7810..b409522a 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -69,7 +69,7 @@ s16 gChangeLevelTransition = -1; s16 gChangeActNum = -1; static bool sFirstCastleGroundsMenu = true; -static bool sIsDemoActive = false; +bool gIsDemoActive = false; bool gInPlayerMenu = false; static u16 gDemoCountdown = 0; static int sDemoNumber = -1; @@ -201,7 +201,7 @@ s32 sDelayedWarpArg; s16 unusedEULevelUpdateBss1; #endif s8 sTimerRunning; -s8 gNeverEnteredCastle; +bool gNeverEnteredCastle; struct MarioState *gMarioState = &gMarioStates[0]; u8 unused1[4] = { 0 }; @@ -1158,10 +1158,10 @@ bool find_demo_number(void) { } static void start_demo(void) { - if (sIsDemoActive) { - sIsDemoActive = false; + if (gIsDemoActive) { + gIsDemoActive = false; } else { - sIsDemoActive = true; + gIsDemoActive = true; if (find_demo_number()) { gChangeLevel = gCurrLevelNum; @@ -1173,14 +1173,14 @@ static void start_demo(void) { load_patchable_table(&gDemo, sDemoNumber); gCurrDemoInput = ((struct DemoInput *) gDemo.targetAnim); } else { - sIsDemoActive = false; + gIsDemoActive = false; } } } void stop_demo(UNUSED struct DjuiBase* caller) { - if (sIsDemoActive) { - sIsDemoActive = false; + if (gIsDemoActive) { + gIsDemoActive = false; gCurrDemoInput = NULL; gChangeLevel = gCurrLevelNum; gDemoCountdown = 0; @@ -1197,22 +1197,26 @@ s32 play_mode_normal(void) { if (gCurrDemoInput != NULL) { print_intro_text(); if (gPlayer1Controller->buttonPressed & END_DEMO) { - level_trigger_warp(gMarioState, - gCurrLevelNum == LEVEL_PSS ? WARP_OP_DEMO_END : WARP_OP_DEMO_NEXT); - } else if (!gWarpTransition.isActive && sDelayedWarpOp == WARP_OP_NONE - && (gPlayer1Controller->buttonPressed & START_BUTTON)) { + level_trigger_warp(gMarioState, gCurrLevelNum == LEVEL_PSS ? WARP_OP_DEMO_END : WARP_OP_DEMO_NEXT); + } else if (!gWarpTransition.isActive && sDelayedWarpOp == WARP_OP_NONE && (gPlayer1Controller->buttonPressed & START_BUTTON)) { gPressedStart = 1; level_trigger_warp(gMarioState, WARP_OP_DEMO_NEXT); } } } else { - if (gDjuiInMainMenu && gCurrDemoInput == NULL && configMenuDemos && !gInPlayerMenu) { - if ((++gDemoCountdown) == PRESS_START_DEMO_TIMER && (find_demo_number() && (sDemoNumber <= 6 && sDemoNumber > -1))) { - start_demo(); - } + if (gDjuiInMainMenu && + gCurrDemoInput == NULL && + configMenuDemos && + !gInPlayerMenu && + (++gDemoCountdown) == PRESS_START_DEMO_TIMER && + (find_demo_number() && (sDemoNumber <= 6 && sDemoNumber > -1)) && + gNetworkType == NT_NONE) { + start_demo(); } - if (((gCurrDemoInput != NULL) && (gPlayer1Controller->buttonPressed & END_DEMO || !sIsDemoActive || !gDjuiInMainMenu || gNetworkType != NT_NONE || gInPlayerMenu)) || (gCurrDemoInput == NULL && sIsDemoActive)) { + if (((gCurrDemoInput != NULL) && + (gPlayer1Controller->buttonPressed & END_DEMO || !gIsDemoActive || !gDjuiInMainMenu || gNetworkType != NT_NONE || gInPlayerMenu)) || + (gCurrDemoInput == NULL && gIsDemoActive)) { gPlayer1Controller->buttonPressed &= ~END_DEMO; stop_demo(NULL); } @@ -1442,7 +1446,7 @@ void update_menu_level(void) { // warp to level, this feels buggy if (gCurrLevelNum != curLevel) { - if (sIsDemoActive) { + if (gIsDemoActive) { stop_demo(NULL); } @@ -1450,7 +1454,7 @@ void update_menu_level(void) { gChangeActNum = 6; gDemoCountdown = 0; } - if (sIsDemoActive) { + if (gIsDemoActive) { return; } @@ -1462,7 +1466,7 @@ void update_menu_level(void) { // set sFirstCastleGroundsMenu to false to prevent wall hugging bug if (curLevel != LEVEL_CASTLE_GROUNDS) { - sFirstCastleGroundsMenu = false; + sFirstCastleGroundsMenu = false; } struct Object *o; @@ -1837,7 +1841,7 @@ s32 lvl_set_current_level(UNUSED s16 arg0, s32 levelNum) { sWarpCheckpointActive = FALSE; gCurrLevelNum = levelNum; - gCurrCourseNum = get_level_course_num(levelNum - 1); + gCurrCourseNum = get_level_course_num(levelNum); bool foundHook = false; bool hookUseActSelect = false; diff --git a/src/game/level_update.h b/src/game/level_update.h index dbc72957..336b6a7b 100644 --- a/src/game/level_update.h +++ b/src/game/level_update.h @@ -124,7 +124,7 @@ struct HudDisplay { }; extern struct HudDisplay gHudDisplay; -extern s8 gNeverEnteredCastle; +extern bool gNeverEnteredCastle; extern u32 gControlTimerStartNat; extern u32 gControlTimerStopNat; diff --git a/src/game/mario.c b/src/game/mario.c index f06407f0..272c3040 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -1577,6 +1577,7 @@ copyPlayerGoto:; if (m == m2) { continue; } find_floor(m2->pos[0], m2->pos[1], m2->pos[2], &floor2); if (floor2 == NULL) { continue; } + LOG_INFO("OOB! teleporting to player with local index %d", i); vec3f_copy(m->pos, m2->pos); copiedPlayer = TRUE; goto copyPlayerGoto; diff --git a/src/game/mario_actions_cutscene.c b/src/game/mario_actions_cutscene.c index 66e409be..64a75618 100644 --- a/src/game/mario_actions_cutscene.c +++ b/src/game/mario_actions_cutscene.c @@ -349,6 +349,7 @@ void cutscene_put_cap_on(struct MarioState *m) { m->flags &= ~MARIO_CAP_IN_HAND; m->flags |= MARIO_CAP_ON_HEAD; play_sound(SOUND_ACTION_UNKNOWN43E, m->marioObj->header.gfx.cameraToObject); + m->cap = 0; } /** @@ -524,10 +525,10 @@ s32 act_disappeared(struct MarioState *m) { s32 act_reading_automatic_dialog(struct MarioState *m) { if (m == NULL) { return TRUE; } - + // Increment our action state to continue our 'cutscene'. m->actionState++; - + if (m->actionState == 2) { enable_time_stop_if_alone(); } @@ -556,7 +557,7 @@ s32 act_reading_automatic_dialog(struct MarioState *m) { } else if (m->actionState == 25) { // finished action disable_time_stop(); if (gNeverEnteredCastle) { - gNeverEnteredCastle = FALSE; + gNeverEnteredCastle = false; play_cutscene_music(SEQUENCE_ARGS(0, SEQ_LEVEL_INSIDE_CASTLE)); } if (m->prevAction == ACT_STAR_DANCE_WATER) { @@ -567,7 +568,7 @@ s32 act_reading_automatic_dialog(struct MarioState *m) { } } } - + // apply head turn vec3s_set(m->marioBodyState->headAngle, m->actionTimer, 0, 0); return FALSE; @@ -575,9 +576,9 @@ s32 act_reading_automatic_dialog(struct MarioState *m) { s32 act_reading_sign(struct MarioState *m) { if (m == NULL) { return TRUE; } - + struct Object *marioObj = m->marioObj; - + // If anybody but us is reading a sign, // Don't handle their action state. if (m->playerIndex != 0) { @@ -628,11 +629,11 @@ s32 act_reading_sign(struct MarioState *m) { s32 act_debug_free_move(struct MarioState *m) { if (m == NULL) { return TRUE; } - + u32 action = ACT_IDLE; #ifndef DEVELOPMENT - if (gNetworkType == NT_SERVER && gServerSettings.enableCheats == 0 && m->action == ACT_DEBUG_FREE_MOVE) { + if (gServerSettings.enableCheats == 0) { if (m->pos[1] <= m->waterLevel - 100) { action = ACT_WATER_IDLE; } else { @@ -690,7 +691,7 @@ s32 act_debug_free_move(struct MarioState *m) { void general_star_dance_handler(struct MarioState *m, s32 isInWater) { if (m == NULL) { return; } - + if (m->actionState == 0) { switch (++m->actionTimer) { case 1: @@ -1149,7 +1150,7 @@ s32 act_warp_door_spawn(struct MarioState *m) { } } else if (m->usedObj == NULL || (m->usedObj->oAction == 0 || m->usedObj->oAction == 100)) { if (m->playerIndex == 0) { - if (gNeverEnteredCastle == TRUE && gCurrLevelNum == LEVEL_CASTLE) { + if (gNeverEnteredCastle && gCurrLevelNum == LEVEL_CASTLE) { set_mario_action(m, ACT_READING_AUTOMATIC_DIALOG, gBehaviorValues.dialogs.CastleEnterDialog); } else { set_mario_action(m, ACT_IDLE, 0); @@ -1722,7 +1723,7 @@ s32 act_shocked(struct MarioState *m) { s32 act_squished(struct MarioState *m) { if (m == NULL) { return TRUE; } - + f32 spaceUnderCeil; s16 surfAngle; s32 underSteepSurf = FALSE; // seems to be responsible for setting velocity? @@ -2534,7 +2535,7 @@ static void end_peach_cutscene_dialog_1(struct MarioState *m) { #endif sEndPeachAnimation = 6; break; - + #ifdef VERSION_SH case 111: #else @@ -2638,7 +2639,7 @@ static void end_peach_cutscene_dialog_2(struct MarioState *m) { #ifdef VERSION_SH case 65: -#else +#else case 45: #endif D_8032CBE8 = 1; diff --git a/src/game/options_menu.h b/src/game/options_menu.h deleted file mode 100644 index 9a174351..00000000 --- a/src/game/options_menu.h +++ /dev/null @@ -1,8 +0,0 @@ -#ifndef OPTIONS_MENU_H -#define OPTIONS_MENU_H - -void optmenu_draw(void); -void optmenu_draw_prompt(void); -void optmenu_toggle(void); - -#endif \ No newline at end of file diff --git a/src/game/paintings.c b/src/game/paintings.c index 5a32782d..a08b00ee 100644 --- a/src/game/paintings.c +++ b/src/game/paintings.c @@ -309,7 +309,7 @@ void patch_paintings_interpolated(f32 delta) { if (currPItem == NULL || currPItem == &paintingZero) { break; } - + } } @@ -916,7 +916,7 @@ void painting_update_floors(struct Painting *painting) { if (!consider) { continue; } - // floorEntered is true iff currFloor is true and lastFloor is false + // floorEntered is true if currFloor is true and lastFloor is false // (Mario just entered the floor on this frame) s8 entered = (painting->ripples.lastFloors[i] ^ painting->ripples.currFloors[i]) & painting->ripples.currFloors[i]; if (entered) { @@ -1023,7 +1023,7 @@ s16 calculate_ripple_at_point(struct Painting *painting, f32 posX, f32 posY) { // For calculating the highest ripple, ans needs to start extremely low otherwise ripples under 0 won't be counted s16 ans = multiRippleMode == HIGHEST_RIPPLE ? -32000 : 0; bool flat = true; - + if (multiRippleMode != SINGLE_RIPPLE) { // If multi ripple mode for (s32 i = 0; i < MAX_PLAYERS + 1; i++) { @@ -1791,7 +1791,7 @@ Gfx *geo_painting_update(s32 callContext, UNUSED struct GraphNode *node, UNUSED } else { gLastPaintingUpdateCounter = gPaintingUpdateCounter; gPaintingUpdateCounter = gAreaUpdateCounter; - + // Store Mario's floor and position if (gMarioObject) { find_floor(gMarioObject->oPosX, gMarioObject->oPosY, gMarioObject->oPosZ, &surface); diff --git a/src/game/save_file.c b/src/game/save_file.c index 5b013770..b981b4fb 100644 --- a/src/game/save_file.c +++ b/src/game/save_file.c @@ -63,6 +63,8 @@ s8 get_level_course_num(s16 levelNum) { return (info ? info->courseNum : COURSE_NONE); } + levelNum = levelNum - 1; + if (INVALID_LEVEL_NUM(levelNum)) { return COURSE_NONE; } @@ -392,7 +394,7 @@ void save_file_do_save(s32 fileIndex, s8 forceSave) { // Write to EEPROM write_eeprom_savefile(fileIndex, 0, 2); - + gSaveFileModified = FALSE; } save_main_menu_data(); @@ -412,7 +414,7 @@ void save_file_erase(s32 fileIndex) { void save_file_reload(u8 load_all) { gSaveFileModified = TRUE; update_all_mario_stars(); - + if (load_all == TRUE) { save_file_load_all(TRUE); save_file_do_save(gCurrSaveFileNum-1, TRUE); @@ -818,7 +820,7 @@ void check_if_should_set_warp_checkpoint(struct WarpNode *warpNode) { */ s32 check_warp_checkpoint(struct WarpNode *warpNode) { s16 warpCheckpointActive = FALSE; - s16 currCourseNum = get_level_course_num((warpNode->destLevel & 0x7F) - 1); + s16 currCourseNum = get_level_course_num(warpNode->destLevel & 0x7F); // gSavedCourseNum is only used in this function. if (gWarpCheckpoint.courseNum != COURSE_NONE && gSavedCourseNum == currCourseNum diff --git a/src/menu/star_select.c b/src/menu/star_select.c index d1d993ca..d0aaafec 100644 --- a/src/menu/star_select.c +++ b/src/menu/star_select.c @@ -25,6 +25,7 @@ #include "pc/network/network.h" #include "engine/math_util.h" #include "game/print.h" +#include "game/level_info.h" /** * @file star_select.c @@ -278,15 +279,9 @@ void print_act_selector_strings(void) { #endif unsigned char starNumbers[] = { TEXT_ZERO }; -#ifdef VERSION_EU - u8 **levelNameTbl; - u8 *currLevelName; - u8 **actNameTbl; -#else - u8 **levelNameTbl = segmented_to_virtual(seg2_course_name_table); + u8 **levelNameTbl = get_course_name_table(); u8 *currLevelName = segmented_to_virtual(levelNameTbl[gCurrCourseNum - 1]); - u8 **actNameTbl = segmented_to_virtual(seg2_act_name_table); -#endif + u8 **actNameTbl = get_act_name_table(); u8 *selectedActName; #ifndef VERSION_EU s16 lvlNameX; @@ -299,24 +294,6 @@ void print_act_selector_strings(void) { create_dl_ortho_matrix(); -#ifdef VERSION_EU - switch (language) { - case LANGUAGE_ENGLISH: - actNameTbl = segmented_to_virtual(act_name_table_eu_en); - levelNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - actNameTbl = segmented_to_virtual(act_name_table_eu_fr); - levelNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - actNameTbl = segmented_to_virtual(act_name_table_eu_de); - levelNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } - currLevelName = segmented_to_virtual(levelNameTbl[gCurrCourseNum - 1]); -#endif - // Print the coin highscore. gSPDisplayList(gDisplayListHead++, dl_rgba16_text_begin); gDPSetEnvColor(gDisplayListHead++, 255, 255, 255, 255); diff --git a/src/pc/chat_commands.c b/src/pc/chat_commands.c index a1039547..989c7ef6 100644 --- a/src/pc/chat_commands.c +++ b/src/pc/chat_commands.c @@ -13,7 +13,6 @@ #include "dev/chat.h" #endif -extern bool gIsModerator; static enum ChatConfirmCommand sConfirming = CCC_NONE; static u8 sConfirmPlayerIndex = 0; @@ -55,14 +54,15 @@ static void chat_construct_player_message(struct NetworkPlayer* np, char* msg) { } bool exec_chat_command(char* command) { + struct NetworkPlayer* npl = &gNetworkPlayers[0]; enum ChatConfirmCommand ccc = sConfirming; sConfirming = CCC_NONE; if (ccc != CCC_NONE && strcmp("/confirm", command) == 0) { - if (gNetworkType == NT_SERVER || gIsModerator) { + struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex]; + if (!np->connected) return true; + if (gNetworkType == NT_SERVER || npl->moderator) { if (ccc == CCC_KICK) { - struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex]; - if (!np->connected) { return true; } chat_construct_player_message(np, DLANG(CHAT, KICKING)); if (gNetworkType == NT_SERVER) { network_send_kick(np->localIndex, EKT_KICKED); @@ -73,10 +73,8 @@ bool exec_chat_command(char* command) { return true; } } - if (gNetworkType == NT_SERVER || gIsModerator) { + if (gNetworkType == NT_SERVER || npl->moderator) { if (ccc == CCC_BAN) { - struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex]; - if (!np->connected) { return true; } chat_construct_player_message(np, DLANG(CHAT, BANNING)); if (gNetworkType == NT_SERVER) { network_send_kick(np->localIndex, EKT_BANNED); @@ -89,8 +87,6 @@ bool exec_chat_command(char* command) { } } if (gNetworkType == NT_SERVER && ccc == CCC_PERMBAN) { - struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex]; - if (!np->connected) { return true; } chat_construct_player_message(np, DLANG(CHAT, PERM_BANNING)); network_send_kick(np->localIndex, EKT_BANNED); ban_list_add(gNetworkSystem->get_id_str(np->localIndex), true); @@ -98,9 +94,8 @@ bool exec_chat_command(char* command) { return true; } if (gNetworkType == NT_SERVER && ccc == CCC_MODERATOR) { - struct NetworkPlayer* np = &gNetworkPlayers[sConfirmPlayerIndex]; - if (!np->connected) { return true; } chat_construct_player_message(np, DLANG(CHAT, ADD_MODERATOR)); + np->moderator = true; network_send_moderator(np->localIndex); moderator_list_add(gNetworkSystem->get_id_str(np->localIndex), true); return true; @@ -125,7 +120,7 @@ bool exec_chat_command(char* command) { } if (str_starts_with("/kick ", command)) { - if (gNetworkType != NT_SERVER && !gIsModerator) { + if (gNetworkType != NT_SERVER && !npl->moderator) { djui_chat_message_create(DLANG(CHAT, NO_PERMS)); return true; } @@ -148,7 +143,7 @@ bool exec_chat_command(char* command) { } if (str_starts_with("/ban ", command)) { - if (gNetworkType != NT_SERVER && !gIsModerator) { + if (gNetworkType != NT_SERVER && !npl->moderator) { djui_chat_message_create(DLANG(CHAT, NO_PERMS)); return true; } @@ -171,7 +166,7 @@ bool exec_chat_command(char* command) { } if (str_starts_with("/permban ", command)) { - if (gNetworkType != NT_SERVER && !gIsModerator) { + if (gNetworkType != NT_SERVER && !npl->moderator) { djui_chat_message_create(DLANG(CHAT, NO_PERMS)); return true; } @@ -226,15 +221,18 @@ bool exec_chat_command(char* command) { void display_chat_commands(void) { djui_chat_message_create(DLANG(CHAT, PLAYERS_DESC)); - if (gNetworkType == NT_SERVER || gIsModerator) { + if (gNetworkType == NT_SERVER || gNetworkPlayers[0].moderator) { djui_chat_message_create(DLANG(CHAT, KICK_DESC)); djui_chat_message_create(DLANG(CHAT, BAN_DESC)); - djui_chat_message_create(DLANG(CHAT, PERM_BAN_DESC)); - djui_chat_message_create(DLANG(CHAT, MOD_DESC)); + + if (gNetworkType == NT_SERVER) { + djui_chat_message_create(DLANG(CHAT, PERM_BAN_DESC)); + djui_chat_message_create(DLANG(CHAT, MOD_DESC)); + } } #if defined(DEVELOPMENT) dev_display_chat_commands(); #endif if (sConfirming != CCC_NONE) { djui_chat_message_create("/confirm"); } smlua_display_chat_commands(); -} \ No newline at end of file +} diff --git a/src/pc/cliopts.c b/src/pc/cliopts.c index 3b8fec98..04cf0cd7 100644 --- a/src/pc/cliopts.c +++ b/src/pc/cliopts.c @@ -43,7 +43,7 @@ static inline int arg_uint(UNUSED const char *name, const char *value, unsigned return 1; } -void parse_cli_opts(int argc, char* argv[]) { +inline void parse_cli_opts(int argc, char* argv[]) { // Initialize options with false values. memset(&gCLIOpts, 0, sizeof(gCLIOpts)); diff --git a/src/pc/configfile.c b/src/pc/configfile.c index 25169cca..9c9cef4b 100644 --- a/src/pc/configfile.c +++ b/src/pc/configfile.c @@ -113,8 +113,8 @@ unsigned int configCameraPan = 0; unsigned int configCameraDegrade = 50; // 0 - 100% bool configCameraInvertX = false; bool configCameraInvertY = true; -bool configEnableCamera = true; -bool configCameraAnalog = true; +bool configEnableCamera = false; +bool configCameraAnalog = false; bool configCameraMouse = false; #endif bool configSkipIntro = 0; diff --git a/src/pc/crash_handler.c b/src/pc/crash_handler.c index 5e431c06..d5e5b59e 100644 --- a/src/pc/crash_handler.c +++ b/src/pc/crash_handler.c @@ -27,6 +27,7 @@ char gLastRemoteBhv[256] = ""; #include "pc/gfx/gfx_rendering_api.h" #include "pc/mods/mods.h" #include "pc/debuglog.h" +#include "pc/pc_main.h" typedef struct { s32 x, y; @@ -659,16 +660,12 @@ static void crash_handler(const int signalNum, siginfo_t *info, ucontext_t *cont // Main loop while (true) { -#if defined(WAPI_SDL1) || defined(WAPI_SDL2) - gfx_sdl.main_loop(crash_handler_produce_one_frame); -#elif defined(WAPI_DXGI) - gfx_dxgi.main_loop(crash_handler_produce_one_frame); -#endif + WAPI.main_loop(crash_handler_produce_one_frame); } exit(0); } -__attribute__((constructor)) static void init_crash_handler() { +AT_STARTUP static void init_crash_handler() { #ifdef _WIN32 // Windows SetUnhandledExceptionFilter(crash_handler); diff --git a/src/pc/discord/discord_activity.c b/src/pc/discord/discord_activity.c index bcac8025..f1bc9bdc 100644 --- a/src/pc/discord/discord_activity.c +++ b/src/pc/discord/discord_activity.c @@ -136,18 +136,18 @@ void discord_activity_update(void) { } void discord_activity_update_check(void) { +#ifdef COOPNET if (sQueuedLobby > 0) { if (--sQueuedLobby == 0) { -#ifdef COOPNET gCoopNetDesiredLobby = sQueuedLobbyId; snprintf(gCoopNetPassword, 64, "%s", sQueuedLobbyPassword); network_reset_reconnect_and_rehost(); network_set_system(NS_COOPNET); network_init(NT_CLIENT, false); djui_panel_join_message_create(NULL); -#endif } } +#endif if (gNetworkType == NT_NONE) { return; } bool shouldUpdate = false; diff --git a/src/pc/djui/djui_panel.h b/src/pc/djui/djui_panel.h index ec184f70..fa5c22c6 100644 --- a/src/pc/djui/djui_panel.h +++ b/src/pc/djui/djui_panel.h @@ -3,11 +3,13 @@ #define DJUI_DEFAULT_PANEL_WIDTH (500.0f + (16 * 2.0f)) #define DJUI_PANEL_HEADER_OFFSET (-16) +#define DJUI_PANEL_MOVE_MAX 1.0f struct DjuiPanel { struct DjuiBase* base; struct DjuiPanel* parent; struct DjuiBase* defaultElementBase; + bool temporary; void (*on_panel_destroy)(struct DjuiBase*); }; diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index 728315e8..643bfe04 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -27294,6 +27294,48 @@ int smlua_func_smlua_audio_utils_reset_all(UNUSED lua_State* L) { // smlua_collision_utils.h // ///////////////////////////// +int smlua_func_collision_find_ceil(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "collision_find_ceil", 3, top); + return 0; + } + + f32 x = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "collision_find_ceil"); return 0; } + f32 y = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "collision_find_ceil"); return 0; } + f32 z = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "collision_find_ceil"); return 0; } + + smlua_push_object(L, LOT_SURFACE, collision_find_ceil(x, y, z)); + + return 1; +} + +int smlua_func_collision_find_floor(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "collision_find_floor", 3, top); + return 0; + } + + f32 x = smlua_to_number(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "collision_find_floor"); return 0; } + f32 y = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "collision_find_floor"); return 0; } + f32 z = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "collision_find_floor"); return 0; } + + smlua_push_object(L, LOT_SURFACE, collision_find_floor(x, y, z)); + + return 1; +} + int smlua_func_collision_find_surface_on_ray(lua_State* L) { if (L == NULL) { return 0; } @@ -27475,6 +27517,23 @@ int smlua_func_smlua_level_util_get_info(lua_State* L) { return 1; } +int smlua_func_smlua_level_util_get_info_from_course_num(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_level_util_get_info_from_course_num", 1, top); + return 0; + } + + u8 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_level_util_get_info_from_course_num"); return 0; } + + smlua_push_object(L, LOT_CUSTOMLEVELINFO, smlua_level_util_get_info_from_course_num(courseNum)); + + return 1; +} + int smlua_func_smlua_level_util_get_info_from_short_name(lua_State* L) { if (L == NULL) { return 0; } @@ -29844,6 +29903,84 @@ int smlua_func_spawn_sync_object(lua_State* L) { // smlua_text_utils.h // //////////////////////// +int smlua_func_smlua_text_utils_act_name_get(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_act_name_get", 2, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_act_name_get"); return 0; } + u8 actNum = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "smlua_text_utils_act_name_get"); return 0; } + + lua_pushstring(L, smlua_text_utils_act_name_get(courseNum, actNum)); + + return 1; +} + +int smlua_func_smlua_text_utils_act_name_is_modified(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_act_name_is_modified", 2, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_act_name_is_modified"); return 0; } + u8 actNum = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "smlua_text_utils_act_name_is_modified"); return 0; } + + lua_pushboolean(L, smlua_text_utils_act_name_is_modified(courseNum, actNum)); + + return 1; +} + +int smlua_func_smlua_text_utils_act_name_replace(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_act_name_replace", 3, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_act_name_replace"); return 0; } + u8 actNum = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "smlua_text_utils_act_name_replace"); return 0; } + const char* name = smlua_to_string(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "smlua_text_utils_act_name_replace"); return 0; } + + smlua_text_utils_act_name_replace(courseNum, actNum, name); + + return 1; +} + +int smlua_func_smlua_text_utils_act_name_reset(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_act_name_reset", 2, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_act_name_reset"); return 0; } + u8 actNum = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "smlua_text_utils_act_name_reset"); return 0; } + + smlua_text_utils_act_name_reset(courseNum, actNum); + + return 1; +} + int smlua_func_smlua_text_utils_castle_secret_stars_replace(lua_State* L) { if (L == NULL) { return 0; } @@ -29892,6 +30029,76 @@ int smlua_func_smlua_text_utils_course_acts_replace(lua_State* L) { return 1; } +int smlua_func_smlua_text_utils_course_name_get(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_course_name_get", 1, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_course_name_get"); return 0; } + + lua_pushstring(L, smlua_text_utils_course_name_get(courseNum)); + + return 1; +} + +int smlua_func_smlua_text_utils_course_name_mod_index(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_course_name_mod_index", 1, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_course_name_mod_index"); return 0; } + + lua_pushinteger(L, smlua_text_utils_course_name_mod_index(courseNum)); + + return 1; +} + +int smlua_func_smlua_text_utils_course_name_replace(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_course_name_replace", 2, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_course_name_replace"); return 0; } + const char* name = smlua_to_string(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "smlua_text_utils_course_name_replace"); return 0; } + + smlua_text_utils_course_name_replace(courseNum, name); + + return 1; +} + +int smlua_func_smlua_text_utils_course_name_reset(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_course_name_reset", 1, top); + return 0; + } + + s16 courseNum = smlua_to_integer(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "smlua_text_utils_course_name_reset"); return 0; } + + smlua_text_utils_course_name_reset(courseNum); + + return 1; +} + int smlua_func_smlua_text_utils_dialog_replace(lua_State* L) { if (L == NULL) { return 0; } @@ -29953,21 +30160,6 @@ int smlua_func_smlua_text_utils_get_language(UNUSED lua_State* L) { return 1; } -int smlua_func_smlua_text_utils_reset_all(UNUSED lua_State* L) { - if (L == NULL) { return 0; } - - int top = lua_gettop(L); - if (top != 0) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "smlua_text_utils_reset_all", 0, top); - return 0; - } - - - smlua_text_utils_reset_all(); - - return 1; -} - int smlua_func_smlua_text_utils_secret_star_replace(lua_State* L) { if (L == NULL) { return 0; } @@ -32135,6 +32327,8 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "smlua_audio_utils_reset_all", smlua_func_smlua_audio_utils_reset_all); // smlua_collision_utils.h + smlua_bind_function(L, "collision_find_ceil", smlua_func_collision_find_ceil); + smlua_bind_function(L, "collision_find_floor", smlua_func_collision_find_floor); smlua_bind_function(L, "collision_find_surface_on_ray", smlua_func_collision_find_surface_on_ray); smlua_bind_function(L, "collision_get_temp_wall_collision_data", smlua_func_collision_get_temp_wall_collision_data); smlua_bind_function(L, "get_water_surface_pseudo_floor", smlua_func_get_water_surface_pseudo_floor); @@ -32148,6 +32342,7 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "level_register", smlua_func_level_register); smlua_bind_function(L, "smlua_level_util_change_area", smlua_func_smlua_level_util_change_area); smlua_bind_function(L, "smlua_level_util_get_info", smlua_func_smlua_level_util_get_info); + smlua_bind_function(L, "smlua_level_util_get_info_from_course_num", smlua_func_smlua_level_util_get_info_from_course_num); smlua_bind_function(L, "smlua_level_util_get_info_from_short_name", smlua_func_smlua_level_util_get_info_from_short_name); smlua_bind_function(L, "warp_exit_level", smlua_func_warp_exit_level); smlua_bind_function(L, "warp_restart_level", smlua_func_warp_restart_level); @@ -32291,12 +32486,19 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "spawn_sync_object", smlua_func_spawn_sync_object); // smlua_text_utils.h + smlua_bind_function(L, "smlua_text_utils_act_name_get", smlua_func_smlua_text_utils_act_name_get); + smlua_bind_function(L, "smlua_text_utils_act_name_is_modified", smlua_func_smlua_text_utils_act_name_is_modified); + smlua_bind_function(L, "smlua_text_utils_act_name_replace", smlua_func_smlua_text_utils_act_name_replace); + smlua_bind_function(L, "smlua_text_utils_act_name_reset", smlua_func_smlua_text_utils_act_name_reset); smlua_bind_function(L, "smlua_text_utils_castle_secret_stars_replace", smlua_func_smlua_text_utils_castle_secret_stars_replace); smlua_bind_function(L, "smlua_text_utils_course_acts_replace", smlua_func_smlua_text_utils_course_acts_replace); + smlua_bind_function(L, "smlua_text_utils_course_name_get", smlua_func_smlua_text_utils_course_name_get); + smlua_bind_function(L, "smlua_text_utils_course_name_mod_index", smlua_func_smlua_text_utils_course_name_mod_index); + smlua_bind_function(L, "smlua_text_utils_course_name_replace", smlua_func_smlua_text_utils_course_name_replace); + smlua_bind_function(L, "smlua_text_utils_course_name_reset", smlua_func_smlua_text_utils_course_name_reset); smlua_bind_function(L, "smlua_text_utils_dialog_replace", smlua_func_smlua_text_utils_dialog_replace); smlua_bind_function(L, "smlua_text_utils_extra_text_replace", smlua_func_smlua_text_utils_extra_text_replace); smlua_bind_function(L, "smlua_text_utils_get_language", smlua_func_smlua_text_utils_get_language); - smlua_bind_function(L, "smlua_text_utils_reset_all", smlua_func_smlua_text_utils_reset_all); smlua_bind_function(L, "smlua_text_utils_secret_star_replace", smlua_func_smlua_text_utils_secret_star_replace); // sound_init.h diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c index f4bf9cd3..52346d84 100644 --- a/src/pc/lua/smlua_utils.c +++ b/src/pc/lua/smlua_utils.c @@ -417,13 +417,15 @@ void smlua_push_object(lua_State* L, u16 lot, void* p) { lua_pushnil(L); return; } + u64 pointer = (uintptr_t) p; + // add to allowlist - smlua_cobject_allowlist_add(lot, (u64)(intptr_t)p); + smlua_cobject_allowlist_add(lot, pointer); // get a cobject from a function lua_getglobal(L, "_NewCObject"); // Get the function by its global name lua_pushinteger(L, lot); - lua_pushinteger(L, (u64)(intptr_t)p); + lua_pushinteger(L, pointer); if (lua_pcall(L, 2, 1, 0) != LUA_OK) { LOG_ERROR("Error calling Lua function: %s\n", lua_tostring(L, -1)); @@ -436,12 +438,13 @@ void smlua_push_pointer(lua_State* L, u16 lvt, void* p) { return; } - smlua_cpointer_allowlist_add(lvt, (u64)(intptr_t)p); + u64 pointer = (uintptr_t) p; + smlua_cpointer_allowlist_add(lvt, pointer); // get a cpointer from a function lua_getglobal(L, "_NewCPointer"); // Get the function by its global name lua_pushinteger(L, lvt); - lua_pushinteger(L, (u64)(intptr_t)p); + lua_pushinteger(L, pointer); if (lua_pcall(L, 2, 1, 0) != LUA_OK) { LOG_ERROR("Error calling Lua function: %s\n", lua_tostring(L, -1)); } @@ -550,7 +553,7 @@ s64 smlua_get_integer_mod_variable(u16 modIndex, const char* variable) { LOG_ERROR("Could not find mod list entry for modIndex: %u", modIndex); return 0; } - + u8 prevSuppress = gSmLuaSuppressErrors; int prevTop = lua_gettop(L); @@ -601,7 +604,7 @@ LuaFunction smlua_get_function_mod_variable(u16 modIndex, const char *variable) LOG_ERROR("Could not find mod list entry for modIndex: %u", modIndex); return 0; } - + u8 prevSuppress = gSmLuaSuppressErrors; int prevTop = lua_gettop(L); diff --git a/src/pc/lua/utils/smlua_collision_utils.c b/src/pc/lua/utils/smlua_collision_utils.c index 7b4ca407..7a643928 100644 --- a/src/pc/lua/utils/smlua_collision_utils.c +++ b/src/pc/lua/utils/smlua_collision_utils.c @@ -1,6 +1,7 @@ #include "types.h" #include "src/engine/surface_collision.h" +#include "include/surface_terrains.h" #include "game/mario_step.h" #include "pc/lua/smlua.h" @@ -164,6 +165,18 @@ struct RayIntersectionInfo* collision_find_surface_on_ray(f32 startX, f32 startY return &info; } +struct Surface* collision_find_floor(f32 x, f32 y, f32 z) { + static struct Surface *surface; + find_floor(x, y, z, &surface); + return surface; +} + +struct Surface* collision_find_ceil(f32 x, f32 y, f32 z) { + static struct Surface *surface; + find_ceil(x, y, z, &surface); + return surface; +} + struct Surface* get_water_surface_pseudo_floor(void) { return &gWaterSurfacePseudoFloor; } diff --git a/src/pc/lua/utils/smlua_collision_utils.h b/src/pc/lua/utils/smlua_collision_utils.h index 47827a30..432c7548 100644 --- a/src/pc/lua/utils/smlua_collision_utils.h +++ b/src/pc/lua/utils/smlua_collision_utils.h @@ -116,6 +116,10 @@ extern struct GlobalObjectCollisionData gGlobalObjectCollisionData; struct RayIntersectionInfo* collision_find_surface_on_ray(f32 startX, f32 startY, f32 startZ, f32 dirX, f32 dirY, f32 dirZ); +struct Surface* collision_find_floor(f32 x, f32 y, f32 z); + +struct Surface* collision_find_ceil(f32 x, f32 y, f32 z); + struct Surface* get_water_surface_pseudo_floor(void); Collision* smlua_collision_util_get(const char* name); diff --git a/src/pc/lua/utils/smlua_level_utils.c b/src/pc/lua/utils/smlua_level_utils.c index 49ce6d65..fcd06ab7 100644 --- a/src/pc/lua/utils/smlua_level_utils.c +++ b/src/pc/lua/utils/smlua_level_utils.c @@ -73,6 +73,17 @@ static struct CustomLevelInfo* smlua_level_util_get_info_from_script(char* scrip return NULL; } +struct CustomLevelInfo* smlua_level_util_get_info_from_course_num(u8 courseNum) { + struct CustomLevelInfo* node = sCustomLevelHead; + while (node != NULL) { + if (node->courseNum == courseNum) { + return node; + } + node = node->next; + } + return NULL; +} + s16 level_register(const char* scriptEntryName, s16 courseNum, const char* fullName, const char* shortName, u32 acousticReach, u32 echoLevel1, u32 echoLevel2, u32 echoLevel3) { // validate params if (scriptEntryName == NULL) { diff --git a/src/pc/lua/utils/smlua_level_utils.h b/src/pc/lua/utils/smlua_level_utils.h index 4bfa5a72..4d43b984 100644 --- a/src/pc/lua/utils/smlua_level_utils.h +++ b/src/pc/lua/utils/smlua_level_utils.h @@ -21,7 +21,8 @@ struct CustomLevelInfo { void smlua_level_util_reset(void); void smlua_level_util_change_area(s32 areaIndex); struct CustomLevelInfo* smlua_level_util_get_info(s16 levelNum); -struct CustomLevelInfo* smlua_level_util_get_info_from_short_name(const char* shortName); +struct CustomLevelInfo* smlua_level_util_get_info_from_short_name(char* shortName); +struct CustomLevelInfo* smlua_level_util_get_info_from_course_num(u8 courseNum); s16 level_register(const char* scriptEntryName, s16 courseNum, const char* fullName, const char* shortName, u32 acousticReach, u32 echoLevel1, u32 echoLevel2, u32 echoLevel3); bool level_is_vanilla_level(s16 levelNum); bool warp_to_warpnode(s32 aLevel, s32 aArea, s32 aAct, s32 aWarpId); diff --git a/src/pc/lua/utils/smlua_text_utils.c b/src/pc/lua/utils/smlua_text_utils.c index b8f8407c..f4563604 100644 --- a/src/pc/lua/utils/smlua_text_utils.c +++ b/src/pc/lua/utils/smlua_text_utils.c @@ -5,6 +5,11 @@ #include "game/ingame_menu.h" #include "game/save_file.h" #include "game/segment2.h" +#include "game/level_info.h" +#include "pc/pc_main.h" +#include "../smlua.h" +#include "smlua_level_utils.h" +#include "smlua_text_utils.h" #ifdef VERSION_EU extern s32 gInGameLanguage; @@ -15,6 +20,42 @@ static bool sReplacedDialog[DIALOG_COUNT] = { 0 }; static bool sReplacedCourseName[COURSE_COUNT+2] = { 0 }; static bool sReplacedActName[(COURSE_RR+2)*6] = { 0 }; +#define INVALID_COURSE_NUM(courseNum) (smlua_level_util_get_info_from_course_num(courseNum) == NULL && !COURSE_IS_VALID_COURSE(courseNum)) + +void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64); + +struct CourseName *gReplacedActNameTable[COURSE_COUNT]; + +// Save all vanilla act names and course names +AT_STARTUP static void smlua_text_utils_init() { + void **actNameTbl = get_act_name_table(); + void **courseNameTbl = get_course_name_table(); + char courseBuffer[50]; + char actBuffer[50]; + + for (s16 courseNum = 0; courseNum < COURSE_COUNT; courseNum++) { + const u8 *courseName = segmented_to_virtual(courseNameTbl[courseNum]); + convert_string_sm64_to_ascii(courseBuffer, courseName); + gReplacedActNameTable[courseNum] = malloc(sizeof(struct CourseName)); + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + snprintf(courseActNames->name, 50, "%s", courseBuffer); + snprintf(courseActNames->orig, 50, "%s", courseBuffer); + courseActNames->modIndex = -1; + + // Individual acts + if (COURSE_IS_MAIN_COURSE(courseNum)) { + courseActNames->actName = calloc(6, sizeof(struct ActName)); + for (s16 actNum = 0; actNum < 6; actNum++) { + const u8 *starName = segmented_to_virtual(actNameTbl[courseNum * 6 + actNum]); + convert_string_sm64_to_ascii(actBuffer, starName); + snprintf(courseActNames->actName[actNum].name, 50, "%s", actBuffer); + snprintf(courseActNames->actName[actNum].orig, 50, "%s", actBuffer); + courseActNames->actName[actNum].isModified = false; + } + } + } +} + static u8* smlua_text_utils_convert(const char* str) { s32 len = strlen(str); u8* dialogStr = calloc(len + 2, sizeof(u8)); @@ -29,7 +70,7 @@ void smlua_text_utils_reset_all(void) { void **dialogTableOrg = NULL; void **actNameTblOrg = NULL; void **courseNameTblOrg = NULL; - + #ifdef VERSION_EU switch (gInGameLanguage) { case LANGUAGE_ENGLISH: @@ -87,13 +128,27 @@ void smlua_text_utils_reset_all(void) { actNameTbl[i] = segmented_to_virtual(actNameTblOrg[i]); sReplacedActName[i] = false; } + + for (s32 courseNum = 0; courseNum < COURSE_COUNT; courseNum++) { + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + snprintf(courseActNames->name, 50, "%s", courseActNames->orig); + courseActNames->modIndex = -1; + + // Individual acts + if (COURSE_IS_MAIN_COURSE(courseNum)) { + for (s16 actNum = 0; actNum < 6; actNum++) { + snprintf(courseActNames->actName[actNum].name, 50, "%s", courseActNames->actName[actNum].orig); + courseActNames->actName[actNum].isModified = false; + } + } + } } void smlua_text_utils_dialog_replace(enum DialogId dialogId, UNUSED u32 unused, s8 linesPerBox, s16 leftOffset, s16 width, const char* str) { if (dialogId >= DIALOG_COUNT) { return; } - + void **dialogTable = NULL; - + #ifdef VERSION_EU switch (gInGameLanguage) { case LANGUAGE_ENGLISH: @@ -124,75 +179,88 @@ void smlua_text_utils_dialog_replace(enum DialogId dialogId, UNUSED u32 unused, sReplacedDialog[dialogId] = true; } +#define REPLACE_ACT_NAME(i) \ + snprintf(courseActNames->actName[i-1].name, 256, "%s", act##i); \ + courseActNames->actName[i-1].isModified = true; \ + void smlua_text_utils_course_acts_replace(s16 courseNum, const char* courseName, const char* act1, const char* act2, const char* act3, const char* act4, const char* act5, const char* act6) { if (courseNum <= 0 || courseNum > COURSE_RR) { return; } - s16 courseOffset = courseNum - 1; - - void **actNameTbl = NULL; - void **courseNameTbl = NULL; - -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - actNameTbl = segmented_to_virtual(act_name_table_eu_en); - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - actNameTbl = segmented_to_virtual(act_name_table_eu_fr); - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - actNameTbl = segmented_to_virtual(act_name_table_eu_de); - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#else - actNameTbl = segmented_to_virtual(seg2_act_name_table); - courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + snprintf(courseActNames->name, 256, "%s", courseName + 3); + courseActNames->modIndex = gLuaActiveMod->index; - // replace course name - if (sReplacedCourseName[courseOffset]) { - free(courseNameTbl[courseOffset]); - } - courseNameTbl[courseOffset] = smlua_text_utils_convert(courseName); - sReplacedCourseName[courseOffset] = true; + REPLACE_ACT_NAME(1); + REPLACE_ACT_NAME(2); + REPLACE_ACT_NAME(3); + REPLACE_ACT_NAME(4); + REPLACE_ACT_NAME(5); + REPLACE_ACT_NAME(6); - // replace act names - const char* newActs[] = { act1, act2, act3, act4, act5, act6 }; - for (s32 i = 0; i < 6; i++) { - s32 index = (courseOffset * 6 + i); + LOG_INFO("%d (%s) replacing act names 1-6 of course %d, (%s), act 1: %s", courseActNames->modIndex, gLuaActiveMod->name, courseNum, courseName, act1); +} - if (sReplacedActName[index]) { - free(actNameTbl[index]); - } +void smlua_text_utils_course_name_replace(s16 courseNum, const char* name) { + if (INVALID_COURSE_NUM(courseNum)) { return; } - actNameTbl[index] = smlua_text_utils_convert(newActs[i]); - sReplacedActName[index] = true; - } + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + snprintf(courseActNames->name, 256, "%s", name); + courseActNames->modIndex = gLuaActiveMod->index; +} + +const char* smlua_text_utils_course_name_get(s16 courseNum) { + if (INVALID_COURSE_NUM(courseNum)) { return NULL; } + + return gReplacedActNameTable[courseNum]->name; +} + +s32 smlua_text_utils_course_name_mod_index(s16 courseNum) { + if (INVALID_COURSE_NUM(courseNum)) { return -1; } + + return gReplacedActNameTable[courseNum]->modIndex; +} + +void smlua_text_utils_course_name_reset(s16 courseNum) { + if (INVALID_COURSE_NUM(courseNum)) { return; } + + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + snprintf(courseActNames->name, 50, "%s", courseActNames->orig); + courseActNames->modIndex = -1; +} + +void smlua_text_utils_act_name_replace(s16 courseNum, u8 actNum, const char* name) { + if (INVALID_COURSE_NUM(courseNum) || actNum > 7) { return; } + + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + + snprintf(courseActNames->actName[actNum].name, 256, "%s", name); + courseActNames->actName[actNum].isModified = true; +} + +const char* smlua_text_utils_act_name_get(s16 courseNum, u8 actNum) { + if (INVALID_COURSE_NUM(courseNum) || actNum > 7) { return NULL; } + + return gReplacedActNameTable[courseNum]->actName[actNum].name; +} + +bool smlua_text_utils_act_name_is_modified(s16 courseNum, u8 actNum) { + if (INVALID_COURSE_NUM(courseNum) || actNum > 7) { return false; } + + return gReplacedActNameTable[courseNum]->actName[actNum].isModified; +} + +void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum) { + if (INVALID_COURSE_NUM(courseNum) || actNum > 7) { return; } + + struct CourseName* courseActNames = gReplacedActNameTable[courseNum]; + snprintf(courseActNames->actName[actNum].name, 50, "%s", courseActNames->actName[actNum].orig); + courseActNames->actName[actNum].isModified = false; } void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) { if (courseNum <= COURSE_RR || courseNum > COURSE_COUNT) { return; } s16 courseOffset = courseNum - 1; - - void **courseNameTbl = NULL; - -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#else - courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif + + void **courseNameTbl = get_course_name_table(); if (sReplacedCourseName[courseOffset]) { free(courseNameTbl[courseOffset]); @@ -204,24 +272,8 @@ void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName) void smlua_text_utils_castle_secret_stars_replace(const char* name) { s16 courseOffset = COURSE_COUNT; - - void **courseNameTbl = NULL; - -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - courseNameTbl = segmented_to_virtual(course_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - courseNameTbl = segmented_to_virtual(course_name_table_eu_de); - break; - } -#else - courseNameTbl = segmented_to_virtual(seg2_course_name_table); -#endif + + void **courseNameTbl = get_course_name_table(); if (sReplacedCourseName[courseOffset]) { free(courseNameTbl[courseOffset]); @@ -234,24 +286,8 @@ void smlua_text_utils_castle_secret_stars_replace(const char* name) { void smlua_text_utils_extra_text_replace(s16 index, const char* text) { if (index < 0 || index > 6) { return; } index = (COURSE_RR * 6 + index); - - void **actNameTbl = NULL; - -#ifdef VERSION_EU - switch (gInGameLanguage) { - case LANGUAGE_ENGLISH: - actNameTbl = segmented_to_virtual(act_name_table_eu_en); - break; - case LANGUAGE_FRENCH: - actNameTbl = segmented_to_virtual(act_name_table_eu_fr); - break; - case LANGUAGE_GERMAN: - actNameTbl = segmented_to_virtual(act_name_table_eu_de); - break; - } -#else - actNameTbl = segmented_to_virtual(seg2_act_name_table); -#endif + + void **actNameTbl = get_act_name_table(); if (sReplacedActName[index]) { free(actNameTbl[index]); @@ -263,4 +299,4 @@ void smlua_text_utils_extra_text_replace(s16 index, const char* text) { const char* smlua_text_utils_get_language(void) { return configLanguage; -} \ No newline at end of file +} diff --git a/src/pc/lua/utils/smlua_text_utils.h b/src/pc/lua/utils/smlua_text_utils.h index 52d9d692..52486e84 100644 --- a/src/pc/lua/utils/smlua_text_utils.h +++ b/src/pc/lua/utils/smlua_text_utils.h @@ -4,10 +4,31 @@ #include "types.h" #include "dialog_ids.h" +struct ActName { + char name[256]; + char orig[256]; + bool isModified; +}; + +struct CourseName { + struct ActName *actName; + char name[256]; + char orig[256]; + s32 modIndex; +}; + void smlua_text_utils_reset_all(void); void smlua_text_utils_dialog_replace(enum DialogId dialogId, u32 unused, s8 linesPerBox, s16 leftOffset, s16 width, const char* str); void smlua_text_utils_course_acts_replace(s16 courseNum, const char* courseName, const char* act1, const char* act2, const char* act3, const char* act4, const char* act5, const char* act6); void smlua_text_utils_secret_star_replace(s16 courseNum, const char* courseName); +void smlua_text_utils_course_name_replace(s16 courseNum, const char* name); +const char* smlua_text_utils_course_name_get(s16 courseNum); +s32 smlua_text_utils_course_name_mod_index(s16 courseNum); +void smlua_text_utils_course_name_reset(s16 courseNum); +void smlua_text_utils_act_name_replace(s16 courseNum, u8 actNum, const char* name); +const char* smlua_text_utils_act_name_get(s16 courseNum, u8 actNum); +bool smlua_text_utils_act_name_is_modified(s16 courseNum, u8 actNum); +void smlua_text_utils_act_name_reset(s16 courseNum, u8 actNum); void smlua_text_utils_castle_secret_stars_replace(const char* name); void smlua_text_utils_extra_text_replace(s16 index, const char* text); const char* smlua_text_utils_get_language(void); diff --git a/src/pc/mods/mods.c b/src/pc/mods/mods.c index c3611c43..b03fe146 100644 --- a/src/pc/mods/mods.c +++ b/src/pc/mods/mods.c @@ -4,6 +4,7 @@ #include "mod_cache.h" #include "data/dynos.c.h" #include "pc/debuglog.h" +#include "pc/pc_main.h" #define MAX_SESSION_CHARS 7 diff --git a/src/pc/network/moderator_list.c b/src/pc/network/moderator_list.c index f9891dd2..87cbf85f 100644 --- a/src/pc/network/moderator_list.c +++ b/src/pc/network/moderator_list.c @@ -32,9 +32,7 @@ void moderator_list_add(char* address, bool perm) { gModerator = malloc(sizeof(bool) * gModeratorCount); } else { gModeratorAddresses = realloc(gModeratorAddresses, sizeof(char*) * gModeratorCount); - assert(gModeratorAddresses != NULL); gModerator = realloc(gModerator, sizeof(bool) * gModeratorCount); - assert(gModerator != NULL); } if (gModeratorAddresses == NULL) { LOG_ERROR("Failed to allocate gModeratorAddresses"); diff --git a/src/pc/network/network.c b/src/pc/network/network.c index e1d9689a..ea1df1dd 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -373,6 +373,7 @@ void network_send(struct Packet* p) { } void network_receive(u8 localIndex, void* addr, u8* data, u16 dataLength) { + // receive packet struct Packet p = { .localIndex = localIndex, @@ -681,9 +682,6 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect extern s16 gMenuMode; gMenuMode = -1; - extern bool gIsModerator; - gIsModerator = false; - djui_panel_shutdown(); extern bool gDjuiInMainMenu; if (!gDjuiInMainMenu) { diff --git a/src/pc/network/network_player.h b/src/pc/network/network_player.h index 92589f1c..ef3b1e75 100644 --- a/src/pc/network/network_player.h +++ b/src/pc/network/network_player.h @@ -25,6 +25,7 @@ struct NetworkPlayer { u8 type; u8 localIndex; u8 globalIndex; + bool moderator; f32 lastReceived; f32 lastSent; f32 lastPingSent; diff --git a/src/pc/network/network_utils.c b/src/pc/network/network_utils.c index a1e0dcda..aafe2b64 100644 --- a/src/pc/network/network_utils.c +++ b/src/pc/network/network_utils.c @@ -27,8 +27,7 @@ bool network_is_server(void) { } bool network_is_moderator(void) { - extern bool gIsModerator; - return gIsModerator; + return gNetworkPlayers[0].moderator; } u8* network_get_player_text_color(u8 localIndex) { diff --git a/src/pc/network/packets/packet_chat.c b/src/pc/network/packets/packet_chat.c index 59ee2de2..fc6e9742 100644 --- a/src/pc/network/packets/packet_chat.c +++ b/src/pc/network/packets/packet_chat.c @@ -100,7 +100,7 @@ void network_receive_chat(struct Packet* p) { // add the message djui_chat_message_create_from(globalIndex, remoteMessage); - if (gNetworkSystem && gNetworkSystem->get_id_str && np) { + if (gNetworkSystem && gNetworkSystem->get_id_str && np->connected && strlen(np->name) > 0) { LOG_CONSOLE("[%s] %s: %s", gNetworkSystem->get_id_str(np->localIndex), np->name, remoteMessage); LOG_INFO("[%s] %s: %s", gNetworkSystem->get_id_str(np->localIndex), np->name, remoteMessage); } else { diff --git a/src/pc/network/packets/packet_command_mod.c b/src/pc/network/packets/packet_command_mod.c index 76b735d2..ce3fa0ba 100644 --- a/src/pc/network/packets/packet_command_mod.c +++ b/src/pc/network/packets/packet_command_mod.c @@ -4,53 +4,55 @@ #include "pc/djui/djui_chat_message.h" #include "pc/network/ban_list.h" #include "pc/network/moderator_list.h" - -bool gIsModerator = false; +#include "pc/debuglog.h" void network_send_chat_command(u8 globalIndex, enum ChatConfirmCommand ccc) { - if (gIsModerator) { - u8 cccType = ccc; - struct Packet p = { 0 }; - packet_init(&p, PACKET_COMMAND, false, PLMT_NONE); - packet_write(&p, &globalIndex, sizeof(u8)); - packet_write(&p, &cccType, sizeof(u8)); - network_send_to(gNetworkPlayerServer->localIndex, &p); - } + if (!gNetworkPlayers[0].moderator) return; + + u8 cccType = ccc; struct Packet p = { 0 }; + LOG_INFO("sending chat command to host with type: %d", cccType); + packet_init(&p, PACKET_COMMAND, false, PLMT_NONE); + packet_write(&p, &globalIndex, sizeof(u8)); + packet_write(&p, &cccType, sizeof(u8)); + network_send_to(gNetworkPlayerServer->localIndex, &p); } void network_receive_chat_command(struct Packet *p) { - if (!moderator_list_contains(gNetworkSystem->get_id_str(p->localIndex))) { + if (gNetworkType != NT_SERVER) { + LOG_ERROR("recieved chat command as non server"); return; } - enum ChatConfirmCommand CCC; - u8 player; + + if (!moderator_list_contains(gNetworkSystem->get_id_str(p->localIndex))) { + LOG_ERROR("recieved moderator command from non moderator"); + return; + } + u8 CCC; u8 player; packet_read(p, &player, sizeof(u8)); packet_read(p, &CCC, sizeof(u8)); - if (gNetworkType == NT_SERVER && CCC == CCC_KICK) { - struct NetworkPlayer *np = &gNetworkPlayers[player]; - if (!np->connected) { - return; - } - network_send_kick(np->localIndex, EKT_KICKED); - network_player_disconnected(np->localIndex); - char message[256] = { 0 }; - snprintf(message, 256, "\\#fff982\\Kicked '%s%s\\#fff982\\'!", - network_get_player_text_color_string(np->localIndex), np->name); - djui_chat_message_create(message); + + if (CCC != CCC_KICK && CCC != CCC_BAN) { + LOG_ERROR("recieved an invalid chat command: %d", CCC); + return; } - if (gNetworkType == NT_SERVER && CCC == CCC_BAN) { - struct NetworkPlayer *np = &gNetworkPlayers[player]; - if (!np->connected) { - return; - } + + struct NetworkPlayer *np = &gNetworkPlayers[player]; + if (!np->connected) { + LOG_ERROR("recieved player that isn't connected"); + return; + } + char message[256] = { 0 }; + if (CCC == CCC_KICK) { + network_send_kick(np->localIndex, EKT_KICKED); + snprintf(message, 256, "\\#fff982\\Kicked '%s%s\\#fff982\\'!", network_get_player_text_color_string(np->localIndex), np->name); + } + if (CCC == CCC_BAN) { network_send_kick(np->localIndex, EKT_BANNED); ban_list_add(gNetworkSystem->get_id_str(np->localIndex), false); - network_player_disconnected(np->localIndex); - char message[256] = { 0 }; - snprintf(message, 256, "\\#fff982\\Banned '%s%s\\#fff982\\'!", - network_get_player_text_color_string(np->localIndex), np->name); - djui_chat_message_create(message); + snprintf(message, 256, "\\#fff982\\Banned '%s%s\\#fff982\\'!", network_get_player_text_color_string(np->localIndex), np->name); } + network_player_disconnected(np->localIndex); + djui_chat_message_create(message); } void network_send_moderator(u8 localIndex) { @@ -60,10 +62,7 @@ void network_send_moderator(u8 localIndex) { } void network_receive_moderator(struct Packet *p) { - if ((gIsModerator) || (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER)) { - return; - } - - gIsModerator = true; + if (gNetworkPlayers[0].moderator || (network_player_any_connected() && gNetworkPlayers[p->localIndex].type != NPT_SERVER)) return; + gNetworkPlayers[0].moderator = true; djui_chat_message_create(DLANG(CHAT, MOD_GRANTED)); -} \ No newline at end of file +} diff --git a/src/pc/network/packets/packet_object.c b/src/pc/network/packets/packet_object.c index 8f8ead86..5d21637b 100644 --- a/src/pc/network/packets/packet_object.c +++ b/src/pc/network/packets/packet_object.c @@ -468,7 +468,9 @@ void network_update_objects(void) { // check for stale sync object if (so->o->oSyncID != so->id) { - LOG_ERROR("sync id mismatch: %d vs %d (behavior %d)", so->o->oSyncID, so->id, get_id_from_behavior(so->o->behavior)); + enum BehaviorId bhvId = get_id_from_behavior(so->o->behavior); + const char* bhvName = get_behavior_name_from_id(bhvId); + LOG_ERROR("sync id mismatch: %d vs %d (behavior %s, %d)", so->o->oSyncID, so->id, bhvName != NULL ? bhvName : "NULL", bhvId); sync_object_forget(so->id); continue; } diff --git a/src/pc/pc_main.c b/src/pc/pc_main.c index da57d227..b60c1a57 100644 --- a/src/pc/pc_main.c +++ b/src/pc/pc_main.c @@ -12,16 +12,6 @@ #include "network/network.h" #include "lua/smlua.h" -#include "gfx/gfx_pc.h" - -#include "gfx/gfx_opengl.h" -#include "gfx/gfx_direct3d11.h" -#include "gfx/gfx_direct3d12.h" - -#include "gfx/gfx_dxgi.h" -#include "gfx/gfx_sdl.h" -#include "gfx/gfx_dummy.h" - #include "audio/audio_api.h" #include "audio/audio_sdl.h" #include "audio/audio_null.h" @@ -87,25 +77,22 @@ static f64 sLastFrameTimeStart; static f32 sAvgFrames = 1; static f32 sAvgFps = 0; +bool gGameInited = false; +bool gGfxInited = false; + static struct AudioAPI *audio_api; -struct GfxWindowManagerAPI *wm_api; -static struct GfxRenderingAPI *rendering_api; +struct GfxWindowManagerAPI *wm_api = &WAPI; extern void gfx_run(Gfx *commands); extern void thread5_game_loop(void *arg); extern void create_next_audio_buffer(s16 *samples, u32 num_samples); void game_loop_one_iteration(void); -void dispatch_audio_sptask(UNUSED struct SPTask *spTask) { -} - -void set_vblank_handler(UNUSED s32 index, UNUSED struct VblankHandler *handler, UNUSED OSMesgQueue *queue, UNUSED OSMesg *msg) { -} - -static bool inited = false; +void dispatch_audio_sptask(UNUSED struct SPTask *spTask) {} +void set_vblank_handler(UNUSED s32 index, UNUSED struct VblankHandler *handler, UNUSED OSMesgQueue *queue, UNUSED OSMesg *msg) {} void send_display_list(struct SPTask *spTask) { - if (!inited) return; + if (!gGameInited) { return; } gfx_run((Gfx *)spTask->task.t.data_ptr); } @@ -117,17 +104,29 @@ void send_display_list(struct SPTask *spTask) { #define SAMPLES_LOW 528 #endif +extern void patch_mtx_before(void); +extern void patch_screen_transition_before(void); +extern void patch_title_screen_before(void); +extern void patch_dialog_before(void); +extern void patch_hud_before(void); +extern void patch_paintings_before(void); +extern void patch_bubble_particles_before(void); +extern void patch_snow_particles_before(void); +extern void patch_djui_before(void); +extern void patch_djui_hud_before(void); + +extern void patch_mtx_interpolated(f32 delta); +extern void patch_screen_transition_interpolated(f32 delta); +extern void patch_title_screen_interpolated(f32 delta); +extern void patch_dialog_interpolated(f32 delta); +extern void patch_hud_interpolated(f32 delta); +extern void patch_paintings_interpolated(f32 delta); +extern void patch_bubble_particles_interpolated(f32 delta); +extern void patch_snow_particles_interpolated(f32 delta); +extern void patch_djui_interpolated(f32 delta); +extern void patch_djui_hud(f32 delta); + static void patch_interpolations_before(void) { - extern void patch_mtx_before(void); - extern void patch_screen_transition_before(void); - extern void patch_title_screen_before(void); - extern void patch_dialog_before(void); - extern void patch_hud_before(void); - extern void patch_paintings_before(void); - extern void patch_bubble_particles_before(void); - extern void patch_snow_particles_before(void); - extern void patch_djui_before(void); - extern void patch_djui_hud_before(void); patch_mtx_before(); patch_screen_transition_before(); patch_title_screen_before(); @@ -141,16 +140,6 @@ static void patch_interpolations_before(void) { } static inline void patch_interpolations(f32 delta) { - extern void patch_mtx_interpolated(f32 delta); - extern void patch_screen_transition_interpolated(f32 delta); - extern void patch_title_screen_interpolated(f32 delta); - extern void patch_dialog_interpolated(f32 delta); - extern void patch_hud_interpolated(f32 delta); - extern void patch_paintings_interpolated(f32 delta); - extern void patch_bubble_particles_interpolated(f32 delta); - extern void patch_snow_particles_interpolated(f32 delta); - extern void patch_djui_interpolated(f32 delta); - extern void patch_djui_hud(f32 delta); patch_mtx_interpolated(delta); patch_screen_transition_interpolated(delta); patch_title_screen_interpolated(delta); @@ -163,19 +152,17 @@ static inline void patch_interpolations(f32 delta) { patch_djui_hud(delta); } - void produce_interpolation_frames_and_delay(void) { + u64 frames = 0; + f64 curTime = clock_elapsed_f64(); + gRenderingInterpolated = true; // sanity check target time to deal with hangs and such - f64 curTime = clock_elapsed_f64(); - if (fabs(sFrameTargetTime - curTime) > 1) { - sFrameTargetTime = curTime - 0.01f; - } + if (fabs(sFrameTargetTime - curTime) > 1) { sFrameTargetTime = curTime - 0.01f; } - u64 frames = 0; + // interpolate and render while ((curTime = clock_elapsed_f64()) < sFrameTargetTime) { - // interpolate and render gfx_start_frame(); f32 delta = MIN((curTime - sFrameTimeStart) / (sFrameTargetTime - sFrameTimeStart), 1); gRenderingDelta = delta; @@ -185,12 +172,12 @@ void produce_interpolation_frames_and_delay(void) { // delay if (!configUncappedFramerate) { - f64 targetDelta = 1.0 / (f64)configFrameLimit; + f64 targetDelta = 1.0 / (f64) configFrameLimit; f64 now = clock_elapsed_f64(); f64 actualDelta = now - curTime; if (actualDelta < targetDelta) { f64 delay = ((targetDelta - actualDelta) * 1000.0); - wm_api->delay((u32)delay); + WAPI.delay((u32) delay); } } @@ -207,50 +194,35 @@ void produce_interpolation_frames_and_delay(void) { //printf(">>> fpt: %llu, fps: %f :: %f\n", frames, sAvgFps, fps); } -void produce_one_frame(void) { - CTX_BEGIN(CTX_NETWORK); - network_update(); - CTX_END(CTX_NETWORK); +inline static void buffer_audio(void) { + int samples_left = audio_api->buffered(); + u32 num_audio_samples = samples_left < audio_api->get_desired_buffered() ? SAMPLES_HIGH : SAMPLES_LOW; + s16 audio_buffer[SAMPLES_HIGH * 2 * 2]; + for (s32 i = 0; i < 2; i++) { + create_next_audio_buffer(audio_buffer + i * (num_audio_samples * 2), num_audio_samples); + } + audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4); +} - CTX_BEGIN(CTX_INTERP); - patch_interpolations_before(); - CTX_END(CTX_INTERP); +void produce_one_frame(void) { + CTX_EXTENT(CTX_NETWORK, network_update); + + CTX_EXTENT(CTX_INTERP, patch_interpolations_before); const f32 master_mod = (f32)configMasterVolume / 127.0f; set_sequence_player_volume(SEQ_PLAYER_LEVEL, (f32)configMusicVolume / 127.0f * master_mod); set_sequence_player_volume(SEQ_PLAYER_SFX, (f32)configSfxVolume / 127.0f * master_mod); set_sequence_player_volume(SEQ_PLAYER_ENV, (f32)configEnvVolume / 127.0f * master_mod); - CTX_BEGIN(CTX_GAME_LOOP); - game_loop_one_iteration(); - CTX_END(CTX_GAME_LOOP); + CTX_EXTENT(CTX_GAME_LOOP, game_loop_one_iteration); - CTX_BEGIN(CTX_SMLUA); - smlua_update(); - CTX_END(CTX_SMLUA); + CTX_EXTENT(CTX_SMLUA, smlua_update); thread6_rumble_loop(NULL); - CTX_BEGIN(CTX_AUDIO); - int samples_left = audio_api->buffered(); - u32 num_audio_samples = samples_left < audio_api->get_desired_buffered() ? SAMPLES_HIGH : SAMPLES_LOW; - //printf("Audio samples: %d %u\n", samples_left, num_audio_samples); - s16 audio_buffer[SAMPLES_HIGH * 2 * 2]; - for (s32 i = 0; i < 2; i++) { - /*if (audio_cnt-- == 0) { - audio_cnt = 2; - } - u32 num_audio_samples = audio_cnt < 2 ? 528 : 544;*/ - create_next_audio_buffer(audio_buffer + i * (num_audio_samples * 2), num_audio_samples); - } - //printf("Audio samples before submitting: %d\n", audio_api->buffered()); + CTX_EXTENT(CTX_AUDIO, buffer_audio); - audio_api->play((u8 *)audio_buffer, 2 * num_audio_samples * 4); - CTX_END(CTX_AUDIO); - - CTX_BEGIN(CTX_RENDER); - produce_interpolation_frames_and_delay(); - CTX_END(CTX_RENDER); + CTX_EXTENT(CTX_RENDER, produce_interpolation_frames_and_delay); } void audio_shutdown(void) { @@ -270,7 +242,7 @@ void game_deinit(void) { network_shutdown(true, true, false, false); smlua_shutdown(); mods_shutdown(); - inited = false; + gGameInited = false; } void game_exit(void) { @@ -279,10 +251,6 @@ void game_exit(void) { exit(0); } -void inthand(UNUSED int signum) { - game_exit(); -} - void main_func(void) { const char *gamedir = gCLIOpts.GameDir[0] ? gCLIOpts.GameDir : FS_BASEDIR; const char *userpath = gCLIOpts.SavePath[0] ? gCLIOpts.SavePath : sys_user_path(); @@ -315,62 +283,30 @@ void main_func(void) { if (configPlayerModel >= CT_MAX) { configPlayerModel = 0; } - if (gCLIOpts.FullScreen == 1) - configWindow.fullscreen = true; - else if (gCLIOpts.FullScreen == 2) - configWindow.fullscreen = false; + if (gCLIOpts.FullScreen == 1) { configWindow.fullscreen = true; } + else if (gCLIOpts.FullScreen == 2) { configWindow.fullscreen = false; } - #if defined(WAPI_SDL1) || defined(WAPI_SDL2) - wm_api = &gfx_sdl; - #elif defined(WAPI_DXGI) - wm_api = &gfx_dxgi; - #elif defined(WAPI_DUMMY) - wm_api = &gfx_dummy_wm_api; - #else - #error No window API! - #endif - - #if defined(RAPI_D3D11) - rendering_api = &gfx_direct3d11_api; - # define RAPI_NAME "DirectX 11" - #elif defined(RAPI_D3D12) - rendering_api = &gfx_direct3d12_api; - # define RAPI_NAME "DirectX 12" - #elif defined(RAPI_GL) || defined(RAPI_GL_LEGACY) - rendering_api = &gfx_opengl_api; - # ifdef USE_GLES - # define RAPI_NAME "OpenGL ES" - # else - # define RAPI_NAME "OpenGL" - # endif - #elif defined(RAPI_DUMMY) - rendering_api = &gfx_dummy_renderer_api; - #else - #error No rendering API! - #endif - - const char* version = get_version_local(); - char window_title[96] = { 0 }; -#ifdef GIT_HASH - snprintf(window_title, 96, "sm64ex-coop: %s [%s]", version, GIT_HASH); -#else - snprintf(window_title, 96, "sm64ex-coop: %s", version); -#endif - - gfx_init(wm_api, rendering_api, window_title); - wm_api->set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up, keyboard_on_text_input); - - #if defined(AAPI_SDL1) || defined(AAPI_SDL2) - if (audio_api == NULL && audio_sdl.init()) - audio_api = &audio_sdl; - #endif - - if (audio_api == NULL) { - audio_api = &audio_null; + // incase the loading screen failed, or is disabled + if (!gGfxInited) { + gfx_init(&WAPI, &RAPI, TITLE); + WAPI.set_keyboard_callbacks(keyboard_on_key_down, keyboard_on_key_up, keyboard_on_all_keys_up, keyboard_on_text_input); } +#if defined(AAPI_SDL1) || defined(AAPI_SDL2) + if (audio_api == NULL && audio_sdl.init()) { audio_api = &audio_sdl; } +#endif + if (audio_api == NULL) { audio_api = &audio_null; } + + audio_init(); + sound_init(); + bassh_init(); + network_player_init(); + + thread5_game_loop(NULL); + djui_init_late(); + // init network if (gCLIOpts.Network == NT_CLIENT) { network_set_system(NS_SOCKET); snprintf(gGetHostName, MAX_CONFIG_STRING, "%s", gCLIOpts.JoinIp); @@ -387,15 +323,6 @@ void main_func(void) { network_init(NT_NONE, false); } - audio_init(); - sound_init(); - bassh_init(); - network_player_init(); - - thread5_game_loop(NULL); - - inited = true; - #ifdef EXTERNAL_DATA // precache data if needed if (configPrecacheRes) { @@ -405,10 +332,12 @@ void main_func(void) { } #endif + gGameInited = true; + while (true) { debug_context_reset(); CTX_BEGIN(CTX_FRAME); - wm_api->main_loop(produce_one_frame); + WAPI.main_loop(produce_one_frame); #ifdef DISCORD_SDK discord_update(); #endif diff --git a/src/pc/pc_main.h b/src/pc/pc_main.h index 7f6e1624..f6d00894 100644 --- a/src/pc/pc_main.h +++ b/src/pc/pc_main.h @@ -5,6 +5,66 @@ extern "C" { #endif +#include "gfx/gfx_pc.h" + +#include "gfx/gfx_opengl.h" +#include "gfx/gfx_direct3d11.h" +#include "gfx/gfx_direct3d12.h" + +#include "gfx/gfx_dxgi.h" +#include "gfx/gfx_sdl.h" +#include "gfx/gfx_dummy.h" + +#if defined(WAPI_SDL1) || defined(WAPI_SDL2) +# define WAPI gfx_sdl +#elif defined(WAPI_DXGI) +# define WAPI gfx_dxgi +#elif defined(WAPI_DUMMY) +# define WAPI gfx_dummy_wm_api +#else +# error No window API! +#endif + +#if defined(RAPI_D3D11) +# define RAPI gfx_direct3d11_api +# define RAPI_NAME "DirectX 11" +#elif defined(RAPI_D3D12) +# define RAPI gfx_direct3d12_api +# define RAPI_NAME "DirectX 12" +#elif defined(RAPI_GL) || defined(RAPI_GL_LEGACY) +# define RAPI gfx_opengl_api +# ifdef USE_GLES +# define RAPI_NAME "OpenGL ES" +# else +# define RAPI_NAME "OpenGL" +# endif +#elif defined(RAPI_DUMMY) +# define RAPI gfx_dummy_renderer_api +#else +# error No rendering API! +#endif + +// For IDEs with syntax highlighting +#ifndef WAPI +#define WAPI gfx_dummy_wm_api +#endif +#ifndef RAPI +#define RAPI gfx_dummy_renderer_api +#endif + +#ifdef GIT_HASH +#define TITLE ({ char title[96] = ""; snprintf(title, 96, "sm64ex-coop: %s [%s]", get_version_local(), GIT_HASH); title; }) +#else +#define TITLE ({ char title[96] = ""; snprintf(title, 96, "sm64ex-coop: %s", get_version_local()); title; }) +#endif + +#define LOAD_STEPS 6 + +#define AT_STARTUP __attribute__((constructor)) + +extern bool gGameInited; +extern bool gGfxInited; + extern struct GfxWindowManagerAPI* wm_api; void game_deinit(void); void game_exit(void); diff --git a/src/pc/utils/misc.c b/src/pc/utils/misc.c index 1f29afbc..ac7fd21d 100644 --- a/src/pc/utils/misc.c +++ b/src/pc/utils/misc.c @@ -168,17 +168,6 @@ void delta_interpolate_rgba(u8* res, u8* a, u8* b, f32 delta) { res[3] = ((a[3] * antiDelta) + (b[3] * delta)); } -/* -void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta) { - f32 antiDelta = 1.0f - delta; - for (s32 i = 0; i < 4; i++) { - for (s32 j = 0; j < 4; j++) { - out->m[i][j] = (a->m[i][j] * antiDelta) + (b->m[i][j] * delta); - } - } -} -*/ - static f32 get_quat_compo_abs(f32 xPiece, f32 yPiece, f32 zPiece) { return sqrt((1.0f + xPiece + yPiece + zPiece) * 0.25f); } @@ -308,7 +297,7 @@ static void rot_quat_slerp(Vec4f out, Vec4f a, Vec4f b, f32 t) { } // removes scaling from the shear value -static f32 unmat_unscale_shear(f32 shear, f32 scale) { +inline static f32 unmat_unscale_shear(f32 shear, f32 scale) { if (scale == 0.0f) { // assume no shear return 0.0f; @@ -325,14 +314,14 @@ static f32 unmat_unscale_shear(f32 shear, f32 scale) { // // matrix perspective is not used in SM64, so those indices are stripped from the output parameter // return value was related to if matrix was non-singular, which was necessary for perspective -// since perspective is not used, the return value is also strippped +// since perspective is not used, the return value is also stripped // // additionally, rotation is not converted to euler angles // instead, it is converted to a quaternion to avoid gimbal lock // // tranfs is returned as follows: // scale(x, y, z), shear(xy, xz, zy), rotation(a, b, c, d), translation(x, y, z) -static void unmatrix(Mtx * mat, f32 tranfs[13]) { +OPTIMIZE_O3 static void unmatrix(Mtx * mat, f32 tranfs[13]) { int i = 0; Vec3f axisVecs[3] = { 0 }; Vec3f yzCross = { 0 }; @@ -433,7 +422,7 @@ static void unmatrix(Mtx * mat, f32 tranfs[13]) { // builds a transformation matrix from a decomposed sequence from unmatrix // see unmatrix for what tranfs means -static void rematrix(Mtx * mat, f32 tranfs[13]) { +OPTIMIZE_O3 static void rematrix(Mtx * mat, f32 tranfs[13]) { int i; Vec3f rotAxes[3] = { 0 }; Mat4 rotMat = { 0 }; @@ -479,7 +468,7 @@ static void rematrix(Mtx * mat, f32 tranfs[13]) { } } -void delta_interpolate_mtx_accurate(Mtx* out, Mtx* a, Mtx* b, f32 delta) { +OPTIMIZE_O3 inline static void delta_interpolate_mtx_accurate(Mtx* out, Mtx* a, Mtx* b, f32 delta) { int i = 0; f32 matTranfsA[13] = { 0 }; f32 matTranfsB[13] = { 0 }; @@ -502,7 +491,7 @@ void delta_interpolate_mtx_accurate(Mtx* out, Mtx* a, Mtx* b, f32 delta) { rematrix(out, matTranfsB); } -void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta) { +OPTIMIZE_O3 void delta_interpolate_mtx(Mtx* out, Mtx* a, Mtx* b, f32 delta) { // HACK: Limit accurate interpolation to 64-bit builds if (sizeof(void*) > 4) { if (configInterpolationMode) {