From 2083242b663e6421b3dfc962c9fef22b089793a5 Mon Sep 17 00:00:00 2001 From: MysterD Date: Mon, 15 May 2023 01:15:20 -0700 Subject: [PATCH] Fixed several crashes and errors found in static analysis --- autogen/common.py | 14 ++ autogen/convert_functions.py | 15 +- autogen/convert_structs.py | 90 ++++++-- autogen/fuzz_template.lua | 234 ++++++++++++++++----- autogen/lua_definitions/constants.lua | 3 + autogen/lua_definitions/structs.lua | 3 + data/dynos_bin_gfx.cpp | 2 +- data/dynos_mgr_actor.cpp | 3 +- data/dynos_mgr_pack.cpp | 4 +- data/dynos_misc.cpp | 24 --- developer/static-analysis.sh | 2 +- docs/lua/constants.md | 1 + docs/lua/structs.md | 53 ++--- grind.log | 39 ++++ include/types.h | 4 +- src/engine/behavior_script.c | 14 +- src/engine/math_util.c | 2 +- src/engine/surface_collision.h | 4 +- src/game/behaviors/bobomb.inc.c | 1 + src/game/behaviors/bowser.inc.c | 1 + src/game/behaviors/cannon.inc.c | 2 +- src/game/behaviors/collide_particles.inc.c | 6 +- src/game/behaviors/door.inc.c | 2 +- src/game/behaviors/fly_guy.inc.c | 2 +- src/game/behaviors/hoot.inc.c | 12 +- src/game/behaviors/jumping_box.inc.c | 4 +- src/game/behaviors/koopa_shell.inc.c | 56 ++--- src/game/behaviors/mips.inc.c | 3 +- src/game/behaviors/ttc_2d_rotator.inc.c | 2 +- src/game/behaviors/ttc_pit_block.inc.c | 4 +- src/game/behaviors/ttc_treadmill.inc.c | 4 +- src/game/behaviors/tuxie.inc.c | 27 ++- src/game/behaviors/ukiki.inc.c | 8 +- src/game/behaviors/water_objs.inc.c | 2 + src/game/hardcoded.c | 2 - src/game/level_update.c | 8 +- src/game/mario.c | 2 + src/game/mario_actions_moving.c | 13 +- src/game/mario_actions_stationary.c | 2 +- src/game/mario_actions_submerged.c | 2 +- src/game/memory.c | 2 +- src/game/obj_behaviors_2.c | 19 +- src/game/object_helpers.c | 12 +- src/game/object_list_processor.c | 4 +- src/game/scroll_targets.c | 1 + src/game/spawn_sound.c | 2 +- src/pc/configini.c | 3 +- src/pc/gfx/gfx_pc.c | 1 + src/pc/lua/smlua_cobject.c | 1 + src/pc/lua/smlua_cobject_autogen.c | 96 ++++----- src/pc/lua/smlua_constants_autogen.c | 1 + src/pc/lua/smlua_functions.c | 29 ++- src/pc/lua/utils/smlua_anim_utils.c | 6 +- src/pc/lua/utils/smlua_anim_utils.h | 2 +- src/pc/mods/mod_cache.c | 21 +- src/pc/mods/mod_storage.c | 2 +- 56 files changed, 591 insertions(+), 287 deletions(-) create mode 100644 grind.log diff --git a/autogen/common.py b/autogen/common.py index f16e7354..42bfe334 100644 --- a/autogen/common.py +++ b/autogen/common.py @@ -218,6 +218,20 @@ def translate_type_to_lua(ptype): return ptype, None +def translate_type_to_rnd(ltype): + if 'enum ' in ltype: + ltype = 'integer' + elif '[' in ltype: + ltype = 'null' + elif '{' in ltype: + ltype = 'null' + elif '}' in ltype: + ltype = 'null' + elif 'void*' in ltype: + ltype = 'null' + + return 'rnd_' + ltype.strip().replace('`', '').replace(' ', '').split('<')[-1].split('>')[0].split('(')[0].split('[')[0].split('*')[0] + '()' + def gen_comment_header(f): comment_h = "// " + f + " //" comment_l = "/" * len(comment_h) diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index 1f982d10..b9353abd 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -80,7 +80,7 @@ override_allowed_functions = { override_disallowed_functions = { "src/audio/external.h": [ " func_" ], "src/engine/math_util.h": [ "atan2s", "atan2f", "vec3s_sub" ], - "src/engine/surface_load.h", [ "alloc_surface_poools" ], + "src/engine/surface_load.h": [ "alloc_surface_poools" ], "src/engine/surface_collision.h": [ " debug_", "f32_find_wall_collision" ], "src/game/mario_actions_airborne.c": [ "^[us]32 act_.*" ], "src/game/mario_actions_automatic.c": [ "^[us]32 act_.*" ], @@ -800,6 +800,8 @@ def process_files(): ############################################################################ +fuzz_from = '/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua' +fuzz_to = '/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua' fuzz_functions = "" def output_fuzz_function(fname, function): @@ -819,9 +821,10 @@ def output_fuzz_function(fname, function): ptype = param['type'] ptype, plink = translate_type_to_lua(ptype) - if 'enum ' in ptype: - ptype = 'integer' - line += 'rnd_' + ptype.strip().replace('`', '').replace(' ', '').split('<')[-1].split('>')[0].split('(')[0] + '()' + if '(' in pid or '[' in pid or ']' in pid: + continue + + line += translate_type_to_rnd(ptype) comment += ptype @@ -836,9 +839,9 @@ def output_fuzz_function(fname, function): def output_fuzz_file(): global fuzz_functions - with open('./autogen/fuzz_template.lua') as f: + with open(fuzz_from) as f: file_str = f.read() - with open('/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua', 'w') as f: + with open(fuzz_to, 'w') as f: f.write(file_str.replace('-- $[FUNCS]', fuzz_functions)) ############################################################################ diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 07f228fc..6532e7e1 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -83,27 +83,29 @@ override_field_invisible = { } override_field_immutable = { - "MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera" ], + "MarioState": [ "playerIndex", "controller", "marioObj", "marioBodyState", "statusForCamera", "area" ], + "MarioAnimation": [ "animDmaTable" ], "ObjectNode": [ "next", "prev" ], "Character": [ "*" ], "NetworkPlayer": [ "*" ], "TextureInfo": [ "*" ], - "Object": ["oSyncID", "coopFlags"], + "Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType" ], "GlobalObjectAnimations": [ "*"], "SpawnParticlesInfo": [ "model" ], "MarioBodyState": [ "updateTorsoTime" ], - "Area": [ "localAreaTimer", "nextSyncID" ], + "Area": [ "localAreaTimer", "nextSyncID", "unk04" ], "Mod": [ "*" ], "ModFile": [ "*" ], "BassAudio": [ "*" ], "Painting": [ "id", "imageCount", "textureType", "textureWidth", "textureHeight" ], - "SpawnInfo": [ "syncID" ], + "SpawnInfo": [ "syncID", "next", "unk18" ], "CustomLevelInfo": [ "next" ], - "GraphNode": [ "next", "prev", "parent" ], + "GraphNode": [ "*" ], + "GraphNodeObject": [ "*" ], "ObjectWarpNode": [ "next "], - "SpawnInfo": [ "next" ], "Animation": [ "length" ], "AnimationTable": [ "count" ], + "Controller": [ "controllerData", "statusData" ], } override_field_version_excludes = { @@ -242,9 +244,34 @@ def parse_structs(extracted): ############################################################################ -def output_fuzz_struct(struct): +fuzz_from = './autogen/fuzz_template.lua' +fuzz_to = '/home/djoslin/.local/share/sm64ex-coop/mods/test-fuzz.lua' +fuzz_structs = "" +fuzz_structs_calls = "" +fuzz_template_str = None + +def output_fuzz_struct_calls(struct): sid = struct['identifier'] - print('function Nuke' + sid + "(struct)") + global fuzz_template_str + if fuzz_template_str == None: + with open(fuzz_from) as f: + fuzz_template_str = f.read() + + global fuzz_structs_calls + + rnd_call = 'rnd_' + sid + '()' + if rnd_call in fuzz_template_str: + fuzz_structs_calls += ' function() Fuzz' + sid + '(rnd_' + sid + '()) end,\n' + else: + fuzz_structs_calls += ' -- function() Fuzz' + sid + '(rnd_' + sid + '()) end,\n' + +def output_fuzz_struct(struct): + output_fuzz_struct_calls(struct) + sid = struct['identifier'] + + s_out = 'function Fuzz' + sid + "(struct)\n" + + s_out += ' local funcs = {\n' for field in struct['fields']: fid, ftype, fimmutable, lvt, lot = get_struct_field_info(struct, field) if fimmutable == 'true': @@ -252,14 +279,48 @@ def output_fuzz_struct(struct): if sid in override_field_invisible: if fid in override_field_invisible[sid]: continue + + if '(' in fid or '[' in fid or ']' in fid: + continue + + ptype, plink = translate_type_to_lua(ftype) + rnd_line = translate_type_to_rnd(ptype) + + s_out += ' function() ' + if lvt == 'LVT_COBJECT': - print(' Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')') + s_out += 'Fuzz' + ftype.replace('struct ', '') + '(struct.' + fid + ')' elif lvt == 'LVT_COBJECT_P': - print(' struct.' + fid + ' = nil') + s_out += 'struct.' + fid + ' = ' + rnd_line + '' else: - print(' struct.' + fid + ' = 0') - print('end') - print('') + s_out += 'struct.' + fid + ' = ' + rnd_line + '' + + s_out += ' end,\n' + s_out += ' }\n' + + s_out += """ + for i = #funcs, 2, -1 do + local j = math.random(i) + funcs[i], funcs[j] = funcs[j], funcs[i] + end + + for k,v in pairs(funcs) do + v() + end +""" + + s_out += 'end\n\n' + + global fuzz_structs + fuzz_structs += s_out + +def output_fuzz_file(): + global fuzz_structs + global fuzz_structs_calls + with open(fuzz_from) as f: + file_str = f.read() + with open(fuzz_to, 'w') as f: + f.write(file_str.replace('-- $[STRUCTS]', fuzz_structs).replace('-- $[FUZZ-STRUCTS]', fuzz_structs_calls)) ############################################################################ @@ -561,6 +622,9 @@ def build_files(): doc_structs(parsed) def_structs(parsed) + if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz': + output_fuzz_file() + global total_structs global total_fields diff --git a/autogen/fuzz_template.lua b/autogen/fuzz_template.lua index 236763e8..a5d920d9 100644 --- a/autogen/fuzz_template.lua +++ b/autogen/fuzz_template.lua @@ -1,53 +1,3 @@ --- $[STRUCTS] - --------- - -function FuzzVec3s(struct) - struct.x = 0 - struct.y = 0 - struct.z = 0 -end - -function FuzzVec3f(struct) - struct.x = 0 - struct.y = 0 - struct.z = 0 -end - -function FuzzVec4s(struct) - struct.x = 0 - struct.y = 0 - struct.z = 0 - struct.w = 0 -end - -function FuzzVec4f(struct) - struct.x = 0 - struct.y = 0 - struct.z = 0 - struct.w = 0 -end - -function FuzzMat4(struct) - struct.a = 0 - struct.b = 0 - struct.c = 0 - struct.d = 0 - struct.e = 0 - struct.f = 0 - struct.g = 0 - struct.h = 0 - struct.i = 0 - struct.j = 0 - struct.k = 0 - struct.l = 0 - struct.m = 0 - struct.n = 0 - struct.o = 0 - struct.p = 0 -end - --------- function rnd_string() t = { 0, "test", "this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string this is a very long string" } @@ -96,6 +46,14 @@ end function rnd_Object() t = { nil, gMarioStates[0].marioObj, gMarioStates[1].marioObj } + + for list in OBJ_LIST_PLAYER,NUM_OBJ_LISTS do + local obj = obj_get_first(list) + while obj ~= nil do + table.insert(t, obj) + obj = obj_get_next(obj) + end + end return t[math.random(#t)] end @@ -134,6 +92,143 @@ function rnd_Surface() return t[math.random(#t)] end +function rnd_Animation() + t = { nil, gMarioStates[0].animation.targetAnim } + return t[math.random(#t)] +end + +function rnd_null() + return nil +end + +function rnd_CameraEvent() + return nil +end + +function rnd_CutsceneShot() + return nil +end + +function rnd_Waypoint() + return nil +end + +function rnd_Painting() + t = { nil, gPaintingValues.bob_painting } + return t[math.random(#t)] +end + +function rnd_Trajectory() + t = { nil, gBehaviorValues.trajectories.BowlingBallBob2Trajectory, gBehaviorValues.trajectories.BowlingBallBobTrajectory, gBehaviorValues.trajectories.BowlingBallThiLargeTrajectory, gBehaviorValues.trajectories.BowlingBallThiSmallTrajectory, gBehaviorValues.trajectories.BowlingBallTtmTrajectory, gBehaviorValues.trajectories.KoopaBobTrajectory, gBehaviorValues.trajectories.KoopaThiTrajectory, gBehaviorValues.trajectories.Mips10Trajectory, gBehaviorValues.trajectories.Mips2Trajectory, gBehaviorValues.trajectories.Mips3Trajectory, gBehaviorValues.trajectories.Mips4Trajectory, gBehaviorValues.trajectories.Mips5Trajectory, gBehaviorValues.trajectories.Mips6Trajectory, gBehaviorValues.trajectories.Mips7Trajectory, gBehaviorValues.trajectories.Mips8Trajectory, gBehaviorValues.trajectories.Mips9Trajectory, gBehaviorValues.trajectories.MipsTrajectory, gBehaviorValues.trajectories.PlatformBitfsTrajectory, gBehaviorValues.trajectories.PlatformCcmTrajectory, gBehaviorValues.trajectories.PlatformHmcTrajectory, gBehaviorValues.trajectories.PlatformLll2Trajectory, gBehaviorValues.trajectories.PlatformLllTrajectory, gBehaviorValues.trajectories.PlatformRr2Trajectory, gBehaviorValues.trajectories.PlatformRr3Trajectory, gBehaviorValues.trajectories.PlatformRr4Trajectory, gBehaviorValues.trajectories.PlatformRrTrajectory, gBehaviorValues.trajectories.RacingPenguinTrajectory, gBehaviorValues.trajectories.SnowmanHeadTrajectory, gBehaviorValues.trajectories.Unagi2Trajectory, gBehaviorValues.trajectories.UnagiTrajectory } + return t[math.random(#t)] +end + +function rnd_InstantWarp() + t = { nil, gMarioStates[0].area.instantWarps } + return t[math.random(#t)] +end + +function rnd_SpawnInfo() + t = { nil, gMarioStates[0].area.objectSpawnInfos } + return t[math.random(#t)] +end + +function rnd_WarpNode() + t = { nil, gMarioStates[0].area.paintingWarpNodes } + return t[math.random(#t)] +end + +function rnd_Whirlpool() + t = { nil, gMarioStates[0].area.whirlpools } + return t[math.random(#t)] +end + +function rnd_UnusedArea28() + t = { nil, gMarioStates[0].area.unused28 } + return t[math.random(#t)] +end + +function rnd_ObjectWarpNode() + t = { nil, area_get_warp_node(0), area_get_warp_node(0x1F) } + return t[math.random(#t)] +end + +function rnd_Collision() + t = { nil, gGlobalObjectCollisionData.bbh_seg7_collision_coffin, gGlobalObjectCollisionData.bbh_seg7_collision_haunted_bookshelf, gGlobalObjectCollisionData.bbh_seg7_collision_merry_go_round, gGlobalObjectCollisionData.bbh_seg7_collision_mesh_elevator, gGlobalObjectCollisionData.bbh_seg7_collision_staircase_step, gGlobalObjectCollisionData.bbh_seg7_collision_tilt_floor_platform, gGlobalObjectCollisionData.bitdw_seg7_collision_moving_pyramid, gGlobalObjectCollisionData.bitfs_seg7_collision_inverted_pyramid, gGlobalObjectCollisionData.bitfs_seg7_collision_sinking_cage_platform, gGlobalObjectCollisionData.bitfs_seg7_collision_sinking_platform, gGlobalObjectCollisionData.bitfs_seg7_collision_squishable_platform, gGlobalObjectCollisionData.blue_coin_switch_seg8_collision_08000E98, gGlobalObjectCollisionData.bob_seg7_collision_chain_chomp_gate, gGlobalObjectCollisionData.bowser_2_seg7_collision_tilting_platform, gGlobalObjectCollisionData.breakable_box_seg8_collision_08012D70, gGlobalObjectCollisionData.cannon_lid_seg8_collision_08004950, gGlobalObjectCollisionData.capswitch_collision_050033D0, gGlobalObjectCollisionData.capswitch_collision_05003448, gGlobalObjectCollisionData.castle_grounds_seg7_collision_cannon_grill, gGlobalObjectCollisionData.castle_grounds_seg7_collision_moat_grills, gGlobalObjectCollisionData.checkerboard_platform_seg8_collision_0800D710, gGlobalObjectCollisionData.ddd_seg7_collision_bowser_sub_door, gGlobalObjectCollisionData.ddd_seg7_collision_submarine, gGlobalObjectCollisionData.door_seg3_collision_0301CE78, gGlobalObjectCollisionData.dorrie_seg6_collision_0600F644, gGlobalObjectCollisionData.dorrie_seg6_collision_0600FBB8, gGlobalObjectCollisionData.exclamation_box_outline_seg8_collision_08025F78, gGlobalObjectCollisionData.hmc_seg7_collision_controllable_platform, gGlobalObjectCollisionData.hmc_seg7_collision_controllable_platform_sub, gGlobalObjectCollisionData.hmc_seg7_collision_elevator, gGlobalObjectCollisionData.inside_castle_seg7_collision_floor_trap, gGlobalObjectCollisionData.inside_castle_seg7_collision_star_door, gGlobalObjectCollisionData.inside_castle_seg7_collision_water_level_pillar, gGlobalObjectCollisionData.jrb_seg7_collision_floating_box, gGlobalObjectCollisionData.jrb_seg7_collision_floating_platform, gGlobalObjectCollisionData.jrb_seg7_collision_in_sunken_ship, gGlobalObjectCollisionData.jrb_seg7_collision_in_sunken_ship_2, gGlobalObjectCollisionData.jrb_seg7_collision_in_sunken_ship_3, gGlobalObjectCollisionData.jrb_seg7_collision_pillar_base, gGlobalObjectCollisionData.jrb_seg7_collision_rock_solid, gGlobalObjectCollisionData.lll_hexagonal_mesh_seg3_collision_0301CECC, gGlobalObjectCollisionData.lll_seg7_collision_drawbridge, gGlobalObjectCollisionData.lll_seg7_collision_falling_wall, gGlobalObjectCollisionData.lll_seg7_collision_floating_block, gGlobalObjectCollisionData.lll_seg7_collision_hexagonal_platform, gGlobalObjectCollisionData.lll_seg7_collision_inverted_pyramid, gGlobalObjectCollisionData.lll_seg7_collision_octagonal_moving_platform, gGlobalObjectCollisionData.lll_seg7_collision_pitoune, gGlobalObjectCollisionData.lll_seg7_collision_puzzle_piece, gGlobalObjectCollisionData.lll_seg7_collision_rotating_fire_bars, gGlobalObjectCollisionData.lll_seg7_collision_rotating_platform, gGlobalObjectCollisionData.lll_seg7_collision_sinking_pyramids, gGlobalObjectCollisionData.lll_seg7_collision_slow_tilting_platform, gGlobalObjectCollisionData.lll_seg7_collision_wood_piece, gGlobalObjectCollisionData.metal_box_seg8_collision_08024C28, gGlobalObjectCollisionData.penguin_seg5_collision_05008B88, gGlobalObjectCollisionData.poundable_pole_collision_06002490, gGlobalObjectCollisionData.purple_switch_seg8_collision_0800C7A8, gGlobalObjectCollisionData.rr_seg7_collision_donut_platform, gGlobalObjectCollisionData.rr_seg7_collision_elevator_platform, gGlobalObjectCollisionData.rr_seg7_collision_pendulum, gGlobalObjectCollisionData.rr_seg7_collision_rotating_platform_with_fire, gGlobalObjectCollisionData.sl_seg7_collision_pound_explodes, gGlobalObjectCollisionData.sl_seg7_collision_sliding_snow_mound, gGlobalObjectCollisionData.springboard_collision_05001A28, gGlobalObjectCollisionData.ssl_seg7_collision_0702808C, gGlobalObjectCollisionData.ssl_seg7_collision_grindel, gGlobalObjectCollisionData.ssl_seg7_collision_pyramid_elevator, gGlobalObjectCollisionData.ssl_seg7_collision_pyramid_top, gGlobalObjectCollisionData.ssl_seg7_collision_spindel, gGlobalObjectCollisionData.ssl_seg7_collision_tox_box, gGlobalObjectCollisionData.thi_seg7_collision_top_trap, gGlobalObjectCollisionData.thwomp_seg5_collision_0500B7D0, gGlobalObjectCollisionData.thwomp_seg5_collision_0500B92C, gGlobalObjectCollisionData.ttc_seg7_collision_clock_main_rotation, gGlobalObjectCollisionData.ttc_seg7_collision_clock_pendulum, gGlobalObjectCollisionData.ttc_seg7_collision_clock_platform, gGlobalObjectCollisionData.ttc_seg7_collision_rotating_clock_platform2, gGlobalObjectCollisionData.ttc_seg7_collision_sliding_surface, gGlobalObjectCollisionData.ttm_seg7_collision_pitoune_2, gGlobalObjectCollisionData.ttm_seg7_collision_podium_warp, gGlobalObjectCollisionData.ttm_seg7_collision_ukiki_cage, gGlobalObjectCollisionData.unknown_seg8_collision_080262F8, gGlobalObjectCollisionData.warp_pipe_seg3_collision_03009AC8, gGlobalObjectCollisionData.wdw_seg7_collision_arrow_lift, gGlobalObjectCollisionData.wdw_seg7_collision_express_elevator_platform, gGlobalObjectCollisionData.wdw_seg7_collision_rect_floating_platform, gGlobalObjectCollisionData.wdw_seg7_collision_square_floating_platform, gGlobalObjectCollisionData.wf_seg7_collision_breakable_wall, gGlobalObjectCollisionData.wf_seg7_collision_breakable_wall_2, gGlobalObjectCollisionData.wf_seg7_collision_bullet_bill_cannon, gGlobalObjectCollisionData.wf_seg7_collision_clocklike_rotation, gGlobalObjectCollisionData.wf_seg7_collision_kickable_board, gGlobalObjectCollisionData.wf_seg7_collision_large_bomp, gGlobalObjectCollisionData.wf_seg7_collision_platform, gGlobalObjectCollisionData.wf_seg7_collision_sliding_brick_platform, gGlobalObjectCollisionData.wf_seg7_collision_small_bomp, gGlobalObjectCollisionData.wf_seg7_collision_tower, gGlobalObjectCollisionData.wf_seg7_collision_tower_door, gGlobalObjectCollisionData.whomp_seg6_collision_06020A0C, gGlobalObjectCollisionData.wooden_signpost_seg3_collision_0302DD80 } + return t[math.random(#t)] +end + +function rnd_MarioAnimation() + t = { nil, gMarioStates[0].animation } + return t[math.random(#t)] +end + +function rnd_Character() + t = { nil, gCharacters[math.random(0, CT_MAX)] } + return t[math.random(#t)] +end + +function rnd_ObjectAnimPointer() + t = { nil, gGlobalObjectAnimations.klepto_seg5_anims_05008CFC } + return t[math.random(#t)] +end + +function rnd_Waypoint() + t = { nil, gGlobalObjectAnimations.klepto_seg5_anims_05008CFC } + return t[math.random(#t)] +end + +-------- + +function FuzzVec3s(struct) + struct.x = rnd_integer() + struct.y = rnd_integer() + struct.z = rnd_integer() +end + +function FuzzVec3f(struct) + struct.x = rnd_number() + struct.y = rnd_number() + struct.z = rnd_number() +end + +function FuzzVec4s(struct) + struct.x = rnd_integer() + struct.y = rnd_integer() + struct.z = rnd_integer() + struct.w = rnd_integer() +end + +function FuzzVec4f(struct) + struct.x = rnd_number() + struct.y = rnd_number() + struct.z = rnd_number() + struct.w = rnd_number() +end + +function FuzzMat4(struct) + struct.a = rnd_number() + struct.b = rnd_number() + struct.c = rnd_number() + struct.d = rnd_number() + struct.e = rnd_number() + struct.f = rnd_number() + struct.g = rnd_number() + struct.h = rnd_number() + struct.i = rnd_number() + struct.j = rnd_number() + struct.k = rnd_number() + struct.l = rnd_number() + struct.m = rnd_number() + struct.n = rnd_number() + struct.o = rnd_number() + struct.p = rnd_number() +end + +-------- + +-- $[STRUCTS] + -------- function fuzz_functions() @@ -156,14 +251,48 @@ id_bhvFuncs = hook_behavior(nil, OBJ_LIST_DEFAULT, true, fuzz_functions, nil, 'i -------- function fuzz_structs() + local funcs = { +-- $[FUZZ-STRUCTS] + } + + for i = #funcs, 2, -1 do + local j = math.random(i) + funcs[i], funcs[j] = funcs[j], funcs[i] + end + + for k,v in pairs(funcs) do + v() + end end -------- local sCountDown = 0 local sLevel = 15 +local sAction = 0 + +function setup_obj(obj) + obj_set_model_extended(obj, math.random(0, E_MODEL_MAX)) + FuzzObject(obj) + if sAction < 20 then + obj.oAction = sAction + end +end + +function spawn_all() + for k=0,5 do + for i=0,id_bhv_max_count do + local x = ((i % 24) - 12) * 1000 + local z = (math.floor(i / 24) - 12) * 1000 + spawn_non_sync_object( + i, + E_MODEL_YELLOW_COIN, + x, gMarioStates[0].pos.y + 1000, z, setup_obj) + end + end + sAction = sAction + 1 +end function on_sync_valid() - fuzz_functions() for i=0,10 do spawn_non_sync_object(id_bhvFuncs, E_MODEL_SPINY_BALL, 0, 0, 0, nil) end @@ -186,5 +315,8 @@ hook_chat_command('fuzz-funcs', 'funcs', fuzz_functions) hook_chat_command('fuzz-structs', 'structs', fuzz_structs) hook_event(HOOK_UPDATE, update) hook_event(HOOK_ON_SYNC_VALID, on_sync_valid) +hook_event(HOOK_ON_SYNC_VALID, fuzz_functions) +hook_event(HOOK_ON_SYNC_VALID, fuzz_structs) +hook_event(HOOK_ON_SYNC_VALID, spawn_all) print('!') diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index cf4617af..1d61d252 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -11502,6 +11502,9 @@ COOP_OBJ_FLAG_NON_SYNC = (1 << 2) --- @type integer MAX_PLAYERS = 16 +--- @type integer +OBJECT_MAX_BHV_STACK = 16 + --- @type integer PLAY_MODE_CHANGE_AREA = 3 diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 289ca23a..ebf14903 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -1845,6 +1845,9 @@ --- @field public offsetY number --- @field public radius number --- @field public unused integer +--- @field public x number +--- @field public y number +--- @field public z number --- @class WarpNode --- @field public destArea integer diff --git a/data/dynos_bin_gfx.cpp b/data/dynos_bin_gfx.cpp index dbd520ac..66f24f46 100644 --- a/data/dynos_bin_gfx.cpp +++ b/data/dynos_bin_gfx.cpp @@ -930,7 +930,7 @@ static void ParseGfxSymbol(GfxData* aGfxData, DataNode* aNode, Gfx*& aHead, gDPLoadBlock(aHead++, G_TX_LOADTILE, 0, 0, (((_Arg3) * (_Arg4) + arg2_1) >> arg2_2) - 1, CALC_DXT(_Arg3, arg2_3)); gDPPipeSync(aHead++); gDPSetTile(aHead++, _Arg1, _Arg2, ((((_Arg3) * arg2_4) + 7) >> 3), 0, G_TX_RENDERTILE, _Arg5, _Arg7, _Arg9, _ArgB, _Arg6, _Arg8, _ArgA); - gDPSetTileSize(aHead++, G_TX_RENDERTILE, 0, 0, ((_Arg3) - 1) << G_TEXTURE_IMAGE_FRAC, ((_Arg4) - 1) << G_TEXTURE_IMAGE_FRAC); + gDPSetTileSize(aHead++, G_TX_RENDERTILE, 0, 0, (((u64)_Arg3) - 1) << G_TEXTURE_IMAGE_FRAC, (((u64)_Arg4) - 1) << G_TEXTURE_IMAGE_FRAC); return; } diff --git a/data/dynos_mgr_actor.cpp b/data/dynos_mgr_actor.cpp index c04da6fd..f54b16ec 100644 --- a/data/dynos_mgr_actor.cpp +++ b/data/dynos_mgr_actor.cpp @@ -59,12 +59,13 @@ void DynOS_Actor_AddCustom(const SysPath &aFilename, const char *aActorName) { // Add to custom actors if (georef == NULL) { - DynosCustomActors().Add({ actorName, geoLayout }); + DynosCustomActors().Add({ strdup(actorName), geoLayout }); georef = geoLayout; } // Add to list DynOS_Actor_Valid(georef, actorGfx); + free(actorName); } const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) { diff --git a/data/dynos_mgr_pack.cpp b/data/dynos_mgr_pack.cpp index facfa8ca..664c9883 100644 --- a/data/dynos_mgr_pack.cpp +++ b/data/dynos_mgr_pack.cpp @@ -25,7 +25,7 @@ static void ScanPackBins(struct PackData* aPack) { if (length > 4 && !strncmp(&_PackEnt->d_name[length - 4], ".bin", 4)) { String _ActorName = _PackEnt->d_name; _ActorName[length - 4] = '\0'; - DynOS_Actor_LoadFromBinary(aPack->mPath, strdup(_ActorName.begin()), _FileName, true); + DynOS_Actor_LoadFromBinary(aPack->mPath, _ActorName.begin(), _FileName, true); } // check for textures @@ -209,7 +209,7 @@ void DynOS_Pack_AddActor(PackData* aPackData, const char* aActorName, GfxData* a } s32 index = aPackData->mGfxData.Count(); - aPackData->mGfxData.Add({ aActorName, aGfxData }); + aPackData->mGfxData.Add({ strdup(aActorName), aGfxData }); if (aPackData->mEnabled) { DynOS_Pack_ActivateActor(aPackData->mIndex, aPackData->mGfxData[index]); diff --git a/data/dynos_misc.cpp b/data/dynos_misc.cpp index 57090653..4d0c3f46 100644 --- a/data/dynos_misc.cpp +++ b/data/dynos_misc.cpp @@ -113,30 +113,6 @@ s32 DynOS_String_Width(const u8 *aStr64) { return _Width; } -// -// Geo -// - -static void _RelocateGraphNodePointers(struct GraphNode *aHead, u64 aOffset) { - struct GraphNode *_Node = aHead; - do { - if (_Node->prev) { - _Node->prev = (struct GraphNode *) ((u64) _Node->prev + aOffset); - } - if (_Node->next) { - _Node->next = (struct GraphNode *) ((u64) _Node->next + aOffset); - } - if (_Node->parent) { - _Node->parent = (struct GraphNode *) ((u64) _Node->parent + aOffset); - } - if (_Node->children) { - _Node->children = (struct GraphNode *) ((u64) _Node->children + aOffset); - _RelocateGraphNodePointers(_Node->children, aOffset); - } - _Node = _Node->next; - } while (_Node != aHead); -} - // // Scroll Targets // diff --git a/developer/static-analysis.sh b/developer/static-analysis.sh index 3a76d7c4..991c463f 100755 --- a/developer/static-analysis.sh +++ b/developer/static-analysis.sh @@ -1,2 +1,2 @@ #!/bin/bash -make clean ; scan-build -disable-checker deadcode.DeadStores make BETTERCAMERA=1 NODRAWINGDISTANCE=1 DEBUG=1 IMMEDIATELOAD=1 DEVELOPMENT=1 STRICT=1 EXTRA_INCLUDES="-IC:/msys64/mingw64/include" -j +make clean ; scan-build -disable-checker deadcode.DeadStores make DEBUG=1 DEVELOPMENT=1 COMPILER=clang EXTRA_INCLUDES="-IC:/msys64/mingw64/include" -j diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 86f0ecc1..1f34b40f 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -4072,6 +4072,7 @@ - COOP_OBJ_FLAG_NETWORK - COOP_OBJ_FLAG_NON_SYNC - MAX_PLAYERS +- OBJECT_MAX_BHV_STACK - PLAY_MODE_CHANGE_AREA - PLAY_MODE_CHANGE_LEVEL - PLAY_MODE_FRAME_ADVANCE diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 85613026..db833cf2 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -810,13 +810,13 @@ | Field | Type | Access | | ----- | ---- | ------ | -| children | [GraphNode](structs.md#GraphNode) | | -| extraFlags | `integer` | | -| flags | `integer` | | +| children | [GraphNode](structs.md#GraphNode) | read-only | +| extraFlags | `integer` | read-only | +| flags | `integer` | read-only | | next | [GraphNode](structs.md#GraphNode) | read-only | | parent | [GraphNode](structs.md#GraphNode) | read-only | | prev | [GraphNode](structs.md#GraphNode) | read-only | -| type | `integer` | | +| type | `integer` | read-only | [:arrow_up_small:](#) @@ -826,32 +826,32 @@ | Field | Type | Access | | ----- | ---- | ------ | -| activeAreaIndex | `integer` | | +| activeAreaIndex | `integer` | read-only | | angle | [Vec3s](structs.md#Vec3s) | read-only | | animInfo | [AnimInfo](structs.md#AnimInfo) | read-only | -| areaIndex | `integer` | | +| areaIndex | `integer` | read-only | | cameraToObject | [Vec3f](structs.md#Vec3f) | read-only | -| disableAutomaticShadowPos | `boolean` | | +| disableAutomaticShadowPos | `boolean` | read-only | | node | [GraphNode](structs.md#GraphNode) | read-only | | pos | [Vec3f](structs.md#Vec3f) | read-only | | prevAngle | [Vec3s](structs.md#Vec3s) | read-only | | prevPos | [Vec3f](structs.md#Vec3f) | read-only | | prevScale | [Vec3f](structs.md#Vec3f) | read-only | -| prevScaleTimestamp | `integer` | | +| prevScaleTimestamp | `integer` | read-only | | prevShadowPos | [Vec3f](structs.md#Vec3f) | read-only | -| prevShadowPosTimestamp | `integer` | | +| prevShadowPosTimestamp | `integer` | read-only | | prevThrowMatrix | `Mat4` | read-only | -| prevThrowMatrixTimestamp | `integer` | | -| prevTimestamp | `integer` | | +| prevThrowMatrixTimestamp | `integer` | read-only | +| prevTimestamp | `integer` | read-only | | scale | [Vec3f](structs.md#Vec3f) | read-only | -| shadowInvisible | `boolean` | | +| shadowInvisible | `boolean` | read-only | | shadowPos | [Vec3f](structs.md#Vec3f) | read-only | -| sharedChild | [GraphNode](structs.md#GraphNode) | | -| skipInViewCheck | `boolean` | | -| skipInterpolationTimestamp | `integer` | | -| throwMatrix | `Pointer` <`Mat4`> | | -| throwMatrixPrev | `Pointer` <`Mat4`> | | -| unk4C | [SpawnInfo](structs.md#SpawnInfo) | | +| sharedChild | [GraphNode](structs.md#GraphNode) | read-only | +| skipInViewCheck | `boolean` | read-only | +| skipInterpolationTimestamp | `integer` | read-only | +| throwMatrix | `Pointer` <`Mat4`> | read-only | +| throwMatrixPrev | `Pointer` <`Mat4`> | read-only | +| unk4C | [SpawnInfo](structs.md#SpawnInfo) | read-only | [:arrow_up_small:](#) @@ -1046,7 +1046,7 @@ | actionTimer | `integer` | | | angleVel | [Vec3s](structs.md#Vec3s) | read-only | | animation | [MarioAnimation](structs.md#MarioAnimation) | | -| area | [Area](structs.md#Area) | | +| area | [Area](structs.md#Area) | read-only | | bounceSquishTimer | `integer` | | | bubbleObj | [Object](structs.md#Object) | | | cap | `integer` | | @@ -1220,7 +1220,7 @@ | areaTimerType | [enum AreaTimerType](constants.md#enum-AreaTimerType) | | | behavior | `Pointer` <`BehaviorScript`> | read-only | | bhvDelayTimer | `integer` | | -| bhvStackIndex | `integer` | | +| bhvStackIndex | `integer` | read-only | | collidedObjInteractTypes | `integer` | | | collisionData | `Pointer` <`Collision`> | | | coopFlags | `integer` | read-only | @@ -1239,7 +1239,7 @@ | parentObj | [Object](structs.md#Object) | | | platform | [Object](structs.md#Object) | | | prevObj | [Object](structs.md#Object) | | -| respawnInfoType | `integer` | | +| respawnInfoType | `integer` | read-only | | setHome | `integer` | | | transform | `Mat4` | read-only | | unused1 | `integer` | | @@ -1467,7 +1467,7 @@ | oCannonPlayerIndex | `integer` | | | oCapUnkF4 | `integer` | | | oCapUnkF8 | `integer` | | -| oChainChompSegments | [ChainSegment](structs.md#ChainSegment) | | +| oChainChompSegments | [ChainSegment](structs.md#ChainSegment) | read-only | | oChainChompMaxDistFromPivotPerChainPart | `number` | | | oChainChompMaxDistBetweenChainParts | `number` | | | oChainChompDistToPivot | `number` | | @@ -1961,7 +1961,7 @@ | oStrongWindParticlePenguinObj | [Object](structs.md#Object) | | | oWhompShakeVal | `integer` | | | oWigglerFallThroughFloorsHeight | `number` | | -| oWigglerSegments | [ChainSegment](structs.md#ChainSegment) | | +| oWigglerSegments | [ChainSegment](structs.md#ChainSegment) | read-only | | oWigglerWalkAnimSpeed | `number` | | | oWigglerSquishSpeed | `number` | | | oWigglerTimeUntilRandomTurn | `integer` | | @@ -2228,8 +2228,8 @@ | next | [SpawnInfo](structs.md#SpawnInfo) | read-only | | startAngle | [Vec3s](structs.md#Vec3s) | read-only | | startPos | [Vec3s](structs.md#Vec3s) | read-only | -| syncID | `integer` | | -| unk18 | [GraphNode](structs.md#GraphNode) | | +| syncID | `integer` | read-only | +| unk18 | [GraphNode](structs.md#GraphNode) | read-only | [:arrow_up_small:](#) @@ -2407,6 +2407,9 @@ | offsetY | `number` | | | radius | `number` | | | unused | `integer` | | +| x | `number` | | +| y | `number` | | +| z | `number` | | [:arrow_up_small:](#) diff --git a/grind.log b/grind.log new file mode 100644 index 00000000..5a9ac67c --- /dev/null +++ b/grind.log @@ -0,0 +1,39 @@ +==899764== exp-sgcheck, a stack and global array overrun detector +==899764== NOTE: This is an Experimental-Class Valgrind Tool +==899764== Copyright (C) 2003-2017, and GNU GPL'd, by OpenWorks Ltd et al. +==899764== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info +==899764== Command: ./build/us_pc/sm64.us.f3dex2e +==899764== Parent PID: 10640 +==899764== +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 +--899764-- warning: evaluate_Dwarf3_Expr: unhandled DW_OP_ 0x93 + +parse DIE(readdwarf3.c:3123): confused by: + <0><19f35>: Abbrev Number: 1 (DW_TAG_compile_unit) + DW_AT_producer : (indirect string, offset: 0x6663): clang LLVM (rustc version 1.39.0-nightly (6ef275e6c 2019-09-24)) + DW_AT_language : 28 + DW_AT_name : (indirect string, offset: 0x66a4): src/libstd/lib.rs + DW_AT_stmt_list : 46860 + DW_AT_comp_dir : (indirect string, offset: 0x66b6): /rustc/6ef275e6c3cb1384ec78128eceeb4963ff788dca/ + DW_AT_??? : 1 + DW_AT_low_pc : 0x0 + DW_AT_ranges : 240976 +parse_type_DIE: +--899764-- WARNING: Serious error when reading debug info +--899764-- When reading debug info from /home/djoslin/sm64ex-coop/lib/discordsdk/libdiscord_game_sdk.so: +--899764-- confused by the above DIE +==899764== Warning: noted but unhandled ioctl 0x6444 with no size/direction hints. +==899764== This could cause spurious value errors to appear. +==899764== See README_MISSING_SYSCALL_OR_IOCTL for guidance on writing a proper wrapper. +==899764== Warning: unimplemented fcntl command: 1033 +==899764== Warning: unimplemented fcntl command: 1033 +==899764== Warning: bogus DWARF3 info: overlapping stack blocks +==899764== Warning: bogus DWARF3 info: overlapping stack blocks +==899764== Warning: bogus DWARF3 info: overlapping stack blocks +==899764== Further instances of this message will not be shown diff --git a/include/types.h b/include/types.h index c21cecf5..3852af64 100644 --- a/include/types.h +++ b/include/types.h @@ -19,6 +19,8 @@ #define BAD_RETURN(cmd) cmd #endif +#define OBJECT_MAX_BHV_STACK 16 + struct Controller { /*0x00*/ s16 rawStickX; // @@ -211,7 +213,7 @@ struct Object /*0x1C8*/ u32 unused1; /*0x1CC*/ const BehaviorScript *curBhvCommand; /*0x1D0*/ u32 bhvStackIndex; - /*0x1D4*/ uintptr_t bhvStack[8]; + /*0x1D4*/ uintptr_t bhvStack[OBJECT_MAX_BHV_STACK]; /*0x1F4*/ s16 bhvDelayTimer; /*0x1F6*/ s16 respawnInfoType; /*0x1F8*/ f32 hitboxRadius; diff --git a/src/engine/behavior_script.c b/src/engine/behavior_script.c index 4d24b254..67afa4bd 100644 --- a/src/engine/behavior_script.c +++ b/src/engine/behavior_script.c @@ -128,18 +128,20 @@ void obj_update_gfx_pos_and_angle(struct Object *obj) { // Push the address of a behavior command to the object's behavior stack. static void cur_obj_bhv_stack_push(uintptr_t bhvAddr) { - gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex] = bhvAddr; + if (gCurrentObject->bhvStackIndex < OBJECT_MAX_BHV_STACK) { + gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex] = bhvAddr; + } gCurrentObject->bhvStackIndex++; - if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 8 - 1; } } // Retrieve the last behavior command address from the object's behavior stack. static uintptr_t cur_obj_bhv_stack_pop(void) { - uintptr_t bhvAddr; + uintptr_t bhvAddr = 0; gCurrentObject->bhvStackIndex--; - if (gCurrentObject->bhvStackIndex >= 8) { gCurrentObject->bhvStackIndex = 0; } - bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex]; + if (gCurrentObject->bhvStackIndex < OBJECT_MAX_BHV_STACK) { + bhvAddr = gCurrentObject->bhvStack[gCurrentObject->bhvStackIndex]; + } return bhvAddr; } @@ -1287,7 +1289,7 @@ void cur_obj_update(void) { // catch up the timer in total loop increments if (gCurrentObject->areaTimerType == AREA_TIMER_TYPE_LOOP) { u32 difference = (gNetworkAreaTimer - gCurrentObject->areaTimer); - if (difference >= gCurrentObject->areaTimerDuration) { + if (difference >= gCurrentObject->areaTimerDuration && gCurrentObject->areaTimerDuration) { u32 catchup = difference / gCurrentObject->areaTimerDuration; catchup *= gCurrentObject->areaTimerDuration; gCurrentObject->areaTimer += catchup; diff --git a/src/engine/math_util.c b/src/engine/math_util.c index dca6024e..021f2b55 100644 --- a/src/engine/math_util.c +++ b/src/engine/math_util.c @@ -196,7 +196,7 @@ void *vec3f_rotate_zxy(Vec3f dest, Vec3s rotate) { dest[1] = v[0] * (cx * sz) + v[1] * (cx * cz) + v[2] * -sx; dest[2] = v[0] * ((cysz * sx) - sycz) + v[1] * ((cycz * sx) + sysz) + v[2] * (cx * cy); - return &dest; + return dest; } #pragma GCC diagnostic pop diff --git a/src/engine/surface_collision.h b/src/engine/surface_collision.h index 67f5c6f2..84ae7964 100644 --- a/src/engine/surface_collision.h +++ b/src/engine/surface_collision.h @@ -17,7 +17,9 @@ struct WallCollisionData { - /*0x00*/ f32 x, y, z; + /*0x00*/ f32 x; + /*????*/ f32 y; + /*????*/ f32 z; /*0x0C*/ f32 offsetY; /*0x10*/ f32 radius; /*0x14*/ s16 unused; diff --git a/src/game/behaviors/bobomb.inc.c b/src/game/behaviors/bobomb.inc.c index 5bd90671..b00ec987 100644 --- a/src/game/behaviors/bobomb.inc.c +++ b/src/game/behaviors/bobomb.inc.c @@ -187,6 +187,7 @@ void bobomb_free_loop(void) { } void bobomb_held_loop(void) { + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; cur_obj_init_animation(1); struct Object* player = gMarioStates[o->heldByPlayerIndex].marioObj; diff --git a/src/game/behaviors/bowser.inc.c b/src/game/behaviors/bowser.inc.c index 6b57d6b7..5cc274a3 100644 --- a/src/game/behaviors/bowser.inc.c +++ b/src/game/behaviors/bowser.inc.c @@ -1223,6 +1223,7 @@ void bowser_free_update(void) { } void bowser_held_update(void) { + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex]; struct Object* player = marioState->marioObj; diff --git a/src/game/behaviors/cannon.inc.c b/src/game/behaviors/cannon.inc.c index dae4bf1e..8fa3887c 100644 --- a/src/game/behaviors/cannon.inc.c +++ b/src/game/behaviors/cannon.inc.c @@ -53,7 +53,7 @@ void opened_cannon_act_4(void) { o->oPosZ += (f32)((o->oTimer / 2 & 1) - 0.5) * 4; o->oAction = 6; } - if (o->oCannonPlayerIndex != 0 && o->oCannonPlayerIndex < MAX_PLAYERS) { + if (o->oCannonPlayerIndex > 0 && o->oCannonPlayerIndex < MAX_PLAYERS) { struct MarioState* controlledBy = &gMarioStates[o->oCannonPlayerIndex]; if (controlledBy && controlledBy->marioObj != NULL) { controlledBy->marioObj->oMarioCannonObjectYaw = o->oMoveAngleYaw; diff --git a/src/game/behaviors/collide_particles.inc.c b/src/game/behaviors/collide_particles.inc.c index 4e27586d..357c06ce 100644 --- a/src/game/behaviors/collide_particles.inc.c +++ b/src/game/behaviors/collide_particles.inc.c @@ -11,7 +11,7 @@ void bhv_punch_tiny_triangle_loop(void) { if (o->oTimer == 0) { sp1E = o->oMoveAngleYaw; o->oCollisionParticleUnkF4 = 1.28f; - cur_obj_set_pos_relative(o->parentObj, 0.0f, 60.0f, 100.0f); + if (o->parentObj) { cur_obj_set_pos_relative(o->parentObj, 0.0f, 60.0f, 100.0f); } o->oMoveAngleYaw = sp1E; } cur_obj_move_using_fvel_and_gravity(); @@ -29,7 +29,7 @@ void bhv_punch_tiny_triangle_init(void) { for (i = 0; i < 6; i++) { triangle = spawn_object(o, MODEL_DIRT_ANIMATION, bhvPunchTinyTriangle); if (triangle == NULL) { continue; } - triangle->oMoveAngleYaw = o->parentObj->oMoveAngleYaw + D_8032F2CC[2 * i] + 0x8000; + if (o->parentObj) { triangle->oMoveAngleYaw = o->parentObj->oMoveAngleYaw + D_8032F2CC[2 * i] + 0x8000; } triangle->oVelY = sins(D_8032F2CC[2 * i + 1]) * 25.0f; triangle->oForwardVel = coss(D_8032F2CC[2 * i + 1]) * 25.0f; } @@ -40,7 +40,7 @@ void bhv_wall_tiny_star_particle_loop(void) { if (o->oTimer == 0) { sp1E = o->oMoveAngleYaw; o->oCollisionParticleUnkF4 = 0.28f; - cur_obj_set_pos_relative(o->parentObj, 0.0f, 30.0f, 110.0f); + if (o->parentObj) { cur_obj_set_pos_relative(o->parentObj, 0.0f, 30.0f, 110.0f); } o->oMoveAngleYaw = sp1E; } cur_obj_move_using_fvel_and_gravity(); diff --git a/src/game/behaviors/door.inc.c b/src/game/behaviors/door.inc.c index 522e306c..237d63ea 100644 --- a/src/game/behaviors/door.inc.c +++ b/src/game/behaviors/door.inc.c @@ -30,7 +30,7 @@ u8 door_allow_walk_through(void) { } s32 cur = o->header.gfx.animInfo.animFrame; - s32 max = o->header.gfx.animInfo.curAnim->loopEnd - 2; + s32 max = o->header.gfx.animInfo.curAnim ? (o->header.gfx.animInfo.curAnim->loopEnd - 2) : 1; s32 min = max / 4; // make non-solid immediately for local actions so the camera doesn't glitch out diff --git a/src/game/behaviors/fly_guy.inc.c b/src/game/behaviors/fly_guy.inc.c index 6dfd7dff..0ea5ebda 100644 --- a/src/game/behaviors/fly_guy.inc.c +++ b/src/game/behaviors/fly_guy.inc.c @@ -50,7 +50,7 @@ static void fly_guy_act_idle(void) { o->oFlyGuyIdleTimer = 0; o->oAction = FLY_GUY_ACT_APPROACH_MARIO; } else { - o->oFlyGuyUnusedJitter = o->oMoveAngleYaw + sFlyGuyJitterAmounts[o->oFlyGuyIdleTimer]; + o->oFlyGuyUnusedJitter = o->oMoveAngleYaw + BHV_ARR(sFlyGuyJitterAmounts, o->oFlyGuyIdleTimer, s16); o->oFlyGuyIdleTimer += 1; } } diff --git a/src/game/behaviors/hoot.inc.c b/src/game/behaviors/hoot.inc.c index 84b7488e..0e60ff6b 100644 --- a/src/game/behaviors/hoot.inc.c +++ b/src/game/behaviors/hoot.inc.c @@ -92,6 +92,7 @@ void hoot_free_step(s16 fastOscY, s32 speed) { } void hoot_player_set_yaw(void) { + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex]; s16 stickX = marioState->controller->rawStickX; s16 stickY = marioState->controller->rawStickY; @@ -147,7 +148,9 @@ void hoot_surface_collision(f32 xPrev, UNUSED f32 yPrev, f32 zPrev) { o->oPosY = hitbox.y; o->oPosZ = hitbox.z; - gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */ + if (o->heldByPlayerIndex < MAX_PLAYERS) { + gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */ + } } floorY = find_floor_height_and_data(o->oPosX, o->oPosY, o->oPosZ, &sp44); @@ -223,8 +226,11 @@ void hoot_action_loop(void) { hoot_carry_step(20, xPrev, zPrev); - if (o->oTimer >= 61) - gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */ + if (o->oTimer >= 61) { + if (o->heldByPlayerIndex < MAX_PLAYERS) { + gMarioStates[o->heldByPlayerIndex].marioObj->oInteractStatus |= INT_STATUS_MARIO_UNK7; /* bit 7 */ + } + } break; } diff --git a/src/game/behaviors/jumping_box.inc.c b/src/game/behaviors/jumping_box.inc.c index 732348ac..97644895 100644 --- a/src/game/behaviors/jumping_box.inc.c +++ b/src/game/behaviors/jumping_box.inc.c @@ -55,7 +55,9 @@ void bhv_jumping_box_loop(void) { jumping_box_free_update(); break; case HELD_HELD: - obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj); + if (o->heldByPlayerIndex < MAX_PLAYERS) { + obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj); + } cur_obj_set_model(smlua_model_util_load(E_MODEL_BREAKABLE_BOX_SMALL)); cur_obj_unrender_and_reset_state(-1, 0); break; diff --git a/src/game/behaviors/koopa_shell.inc.c b/src/game/behaviors/koopa_shell.inc.c index 675aff45..27b3e635 100644 --- a/src/game/behaviors/koopa_shell.inc.c +++ b/src/game/behaviors/koopa_shell.inc.c @@ -16,11 +16,13 @@ void koopa_shell_spawn_water_drop(void) { UNUSED s32 unused; struct Object *drop; spawn_object(o, MODEL_WAVE_TRAIL, bhvObjectWaveTrail); - if (gMarioStates[o->heldByPlayerIndex].forwardVel > 10.0f) { - drop = spawn_object_with_scale(o, MODEL_WHITE_PARTICLE_SMALL, bhvWaterDroplet, 1.5f); - if (drop != NULL) { - drop->oVelY = random_float() * 30.0f; - obj_translate_xz_random(drop, 110.0f); + if (o->heldByPlayerIndex < MAX_PLAYERS) { + if (gMarioStates[o->heldByPlayerIndex].forwardVel > 10.0f) { + drop = spawn_object_with_scale(o, MODEL_WHITE_PARTICLE_SMALL, bhvWaterDroplet, 1.5f); + if (drop != NULL) { + drop->oVelY = random_float() * 30.0f; + obj_translate_xz_random(drop, 110.0f); + } } } } @@ -79,28 +81,30 @@ void bhv_koopa_shell_loop(void) { koopa_shell_spawn_sparkles(10.0f); break; case 1: - player = gMarioStates[o->heldByPlayerIndex].marioObj; - if (player) { - obj_copy_pos(o, player); - } - sp34 = cur_obj_update_floor_height_and_get_floor(); - if (absf(find_water_level(o->oPosX, o->oPosZ) - o->oPosY) < 10.0f) - koopa_shell_spawn_water_drop(); - else if (5.0f > absf(o->oPosY - o->oFloorHeight)) { - if (sp34 != NULL && sp34->type == 1) - bhv_koopa_shell_flame_spawn(); - else + if (o->heldByPlayerIndex < MAX_PLAYERS) { + player = gMarioStates[o->heldByPlayerIndex].marioObj; + if (player) { + obj_copy_pos(o, player); + } + sp34 = cur_obj_update_floor_height_and_get_floor(); + if (absf(find_water_level(o->oPosX, o->oPosZ) - o->oPosY) < 10.0f) + koopa_shell_spawn_water_drop(); + else if (5.0f > absf(o->oPosY - o->oFloorHeight)) { + if (sp34 != NULL && sp34->type == 1) + bhv_koopa_shell_flame_spawn(); + else + koopa_shell_spawn_sparkles(10.0f); + } else koopa_shell_spawn_sparkles(10.0f); - } else - koopa_shell_spawn_sparkles(10.0f); - if (player) { - o->oFaceAngleYaw = player->oMoveAngleYaw; - } - if (o->oInteractStatus & INT_STATUS_STOP_RIDING) { - o->heldByPlayerIndex = 0; - obj_mark_for_deletion(o); - spawn_mist_particles(); - o->oAction = 0; + if (player) { + o->oFaceAngleYaw = player->oMoveAngleYaw; + } + if (o->oInteractStatus & INT_STATUS_STOP_RIDING) { + o->heldByPlayerIndex = 0; + obj_mark_for_deletion(o); + spawn_mist_particles(); + o->oAction = 0; + } } break; } diff --git a/src/game/behaviors/mips.inc.c b/src/game/behaviors/mips.inc.c index 54f0aa28..aa60aaf3 100644 --- a/src/game/behaviors/mips.inc.c +++ b/src/game/behaviors/mips.inc.c @@ -152,7 +152,7 @@ void bhv_mips_act_follow_path(void) { // Retrieve current waypoint. pathBase = segmented_to_virtual(sMipsPaths[0]); s32 length = get_trajectory_length((Trajectory*)pathBase); - if (o->oMipsStartWaypointIndex >= length) { return; } + if (o->oMipsStartWaypointIndex >= length || o->oMipsStartWaypointIndex < 0) { return; } waypoint = segmented_to_virtual(pathBase[o->oMipsStartWaypointIndex]); // Set start waypoint and follow the path from there. @@ -267,6 +267,7 @@ static u8 bhv_mips_held_continue_dialog(void) { void bhv_mips_held(void) { s16 dialogID; + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct Object* player = gMarioStates[o->heldByPlayerIndex].marioObj; o->header.gfx.node.flags |= GRAPH_RENDER_INVISIBLE; diff --git a/src/game/behaviors/ttc_2d_rotator.inc.c b/src/game/behaviors/ttc_2d_rotator.inc.c index 68c843d2..abf61aef 100644 --- a/src/game/behaviors/ttc_2d_rotator.inc.c +++ b/src/game/behaviors/ttc_2d_rotator.inc.c @@ -37,7 +37,7 @@ static s16 sTTC2DRotatorTimeBetweenTurns[][4] = { * Init function for bhvTTC2DRotator. */ void bhv_ttc_2d_rotator_init(void) { - if (o->oBehParams2ndByte < 2 && gTTCSpeedSetting < 4) { + if (o->oBehParams2ndByte >= 0 && o->oBehParams2ndByte < 2 && gTTCSpeedSetting >= 0 && gTTCSpeedSetting < 4) { o->oTTC2DRotatorMinTimeUntilNextTurn = sTTC2DRotatorTimeBetweenTurns[o->oBehParams2ndByte][gTTCSpeedSetting]; o->oTTC2DRotatorIncrement = o->oTTC2DRotatorSpeed = sTTC2DRotatorSpeeds[o->oBehParams2ndByte]; } diff --git a/src/game/behaviors/ttc_pit_block.inc.c b/src/game/behaviors/ttc_pit_block.inc.c index c9882e4f..62a902c9 100644 --- a/src/game/behaviors/ttc_pit_block.inc.c +++ b/src/game/behaviors/ttc_pit_block.inc.c @@ -67,12 +67,12 @@ void bhv_ttc_pit_block_update(void) { if (clamp_f32(&o->oPosY, o->oHomeY, o->oTTCPitBlockPeakY)) { o->oTTCPitBlockDir = o->oTTCPitBlockDir ^ 0x1; - if (gTTCSpeedSetting < 4) { + if (gTTCSpeedSetting >= 0 && gTTCSpeedSetting < 4) { if ((o->oTTCPitBlockWaitTime = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir & 0x1].waitTime) < 0) { o->oTTCPitBlockWaitTime = random_mod_offset(10, 20, 6); } - if (o->oTTCPitBlockDir < 2) { + if (o->oTTCPitBlockDir >= 0 && o->oTTCPitBlockDir < 2) { o->oVelY = sTTCPitBlockProperties[gTTCSpeedSetting][o->oTTCPitBlockDir].speed; } } diff --git a/src/game/behaviors/ttc_treadmill.inc.c b/src/game/behaviors/ttc_treadmill.inc.c index ab8bbeee..bf269014 100644 --- a/src/game/behaviors/ttc_treadmill.inc.c +++ b/src/game/behaviors/ttc_treadmill.inc.c @@ -70,5 +70,7 @@ void bhv_ttc_treadmill_update(void) { } } - o->oForwardVel = 0.084f * *o->oTTCTreadmillBigSurface; + if (o->oTTCTreadmillBigSurface) { + o->oForwardVel = 0.084f * *o->oTTCTreadmillBigSurface; + } } diff --git a/src/game/behaviors/tuxie.inc.c b/src/game/behaviors/tuxie.inc.c index 910fd6ce..d7df6d94 100644 --- a/src/game/behaviors/tuxie.inc.c +++ b/src/game/behaviors/tuxie.inc.c @@ -167,9 +167,11 @@ void bhv_tuxies_mother_loop(void) { } void small_penguin_dive_with_mario(void) { - if (mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) { - o->oSmallPenguinUnk100 = o->oAction; - o->oAction = 3; + if (o->heldByPlayerIndex < MAX_PLAYERS) { + if (mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) { + o->oSmallPenguinUnk100 = o->oAction; + o->oAction = 3; + } } } @@ -212,9 +214,11 @@ void small_penguin_act_3(void) { if (o->oTimer == 6) cur_obj_play_sound_2(SOUND_OBJ_BABY_PENGUIN_DIVE); cur_obj_init_animation_with_sound(1); - if (o->oTimer > 25) - if (!mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) + if (o->oTimer > 25) { + if (o->heldByPlayerIndex < MAX_PLAYERS && !mario_is_dive_sliding(&gMarioStates[o->heldByPlayerIndex])) { o->oAction = 4; + } + } } } @@ -304,15 +308,18 @@ void bhv_small_penguin_loop(void) { break; case HELD_HELD: cur_obj_unrender_and_reset_state(0, 0); - if (cur_obj_has_behavior(bhvPenguinBaby)) + if (cur_obj_has_behavior(bhvPenguinBaby)) { obj_set_behavior(o, bhvSmallPenguin); - obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj); - if (gGlobalTimer % 30 == 0) + } + if (o->heldByPlayerIndex < MAX_PLAYERS) { + obj_copy_pos(o, gMarioStates[o->heldByPlayerIndex].marioObj); + if (gGlobalTimer % 30 == 0) #ifndef VERSION_JP - play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, gMarioStates[o->heldByPlayerIndex].marioObj->header.gfx.cameraToObject); + play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, gMarioStates[o->heldByPlayerIndex].marioObj->header.gfx.cameraToObject); #else - play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject); + play_sound(SOUND_OBJ2_BABY_PENGUIN_YELL, o->header.gfx.cameraToObject); #endif + } break; case HELD_THROWN: cur_obj_get_thrown_or_placed(0, 0, 0); diff --git a/src/game/behaviors/ukiki.inc.c b/src/game/behaviors/ukiki.inc.c index 67c4df73..d425dacb 100644 --- a/src/game/behaviors/ukiki.inc.c +++ b/src/game/behaviors/ukiki.inc.c @@ -542,6 +542,7 @@ static u8 cage_ukiki_held_default_continue_dialog(void) { * Called by the main behavior function for the cage ukiki whenever it is held. */ void cage_ukiki_held_loop(void) { + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex]; if (heldByMario->playerIndex != 0) { return; } @@ -593,6 +594,7 @@ u8 hat_ukiki_held_loop_2(void) { return o->oHeldState == HELD_HELD && o->oUkikiT * Called by the main behavior function for the cap ukiki whenever it is held. */ void cap_ukiki_held_loop(void) { + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct MarioState* heldByMario = &gMarioStates[o->heldByPlayerIndex]; if (heldByMario->playerIndex != 0) { return; } @@ -664,7 +666,6 @@ void bhv_ukiki_init(void) { * dependent on the held state and whick ukiki it is (cage or cap). */ void bhv_ukiki_loop(void) { - struct Object* heldByPlayer = gMarioStates[o->heldByPlayerIndex].marioObj; switch(o->oHeldState) { case HELD_FREE: @@ -675,7 +676,10 @@ void bhv_ukiki_loop(void) { case HELD_HELD: cur_obj_unrender_and_reset_state(UKIKI_ANIM_HELD, 0); - obj_copy_pos(o, heldByPlayer); + if (o->heldByPlayerIndex < MAX_PLAYERS) { + struct Object* heldByPlayer = gMarioStates[o->heldByPlayerIndex].marioObj; + obj_copy_pos(o, heldByPlayer); + } if (o->oBehParams2ndByte == UKIKI_CAP) { cap_ukiki_held_loop(); diff --git a/src/game/behaviors/water_objs.inc.c b/src/game/behaviors/water_objs.inc.c index b16d56e9..e829ebf2 100644 --- a/src/game/behaviors/water_objs.inc.c +++ b/src/game/behaviors/water_objs.inc.c @@ -71,7 +71,9 @@ void bhv_small_water_wave_loop(void) { } void bhv_bubble_player_loop(void) { + if (o->heldByPlayerIndex >= MAX_PLAYERS) { return; } struct MarioState* marioState = &gMarioStates[o->heldByPlayerIndex]; + if (!marioState) { return; } // set position o->oPosX = marioState->pos[0]; diff --git a/src/game/hardcoded.c b/src/game/hardcoded.c index f22774e9..66b77d50 100644 --- a/src/game/hardcoded.c +++ b/src/game/hardcoded.c @@ -270,7 +270,6 @@ struct BehaviorValues gBehaviorValues = { 0 }; struct PaintingValues gDefaultPaintingValues = { .cotmc_painting = &cotmc_painting, - .bob_painting = &bob_painting, .ccm_painting = &ccm_painting, .wf_painting = &wf_painting, @@ -285,7 +284,6 @@ struct PaintingValues gDefaultPaintingValues = { .ttc_painting = &ttc_painting, .sl_painting = &sl_painting, .thi_huge_painting = &thi_huge_painting, - .ttm_slide_painting = &ttm_slide_painting, }; diff --git a/src/game/level_update.c b/src/game/level_update.c index d0179aed..73e877b0 100644 --- a/src/game/level_update.c +++ b/src/game/level_update.c @@ -614,6 +614,7 @@ void warp_credits(void) { } void check_instant_warp(void) { + if (!gCurrentArea) { return; } s16 cameraAngle; struct Surface *floor; @@ -628,8 +629,7 @@ void check_instant_warp(void) { if ((floor = gMarioStates[0].floor) != NULL) { s32 index = floor->type - SURFACE_INSTANT_WARP_1B; - if (index >= INSTANT_WARP_INDEX_START && index < INSTANT_WARP_INDEX_STOP - && gCurrentArea->instantWarps != NULL) { + if (index >= INSTANT_WARP_INDEX_START && index < INSTANT_WARP_INDEX_STOP && gCurrentArea->instantWarps != NULL) { struct InstantWarp *warp = &gCurrentArea->instantWarps[index]; if (warp->id != 0) { if (gRejectInstantWarp > 0) { @@ -1161,7 +1161,7 @@ static void start_demo(void) { gChangeLevel = gCurrLevelNum; } - if (sDemoNumber <= 6 || sDemoNumber > -1) { + if (sDemoNumber <= 6 && sDemoNumber > -1) { gCurrDemoInput = NULL; alloc_anim_dma_table(&gDemo, gDemoInputs, gDemoTargetAnim); load_patchable_table(&gDemo, sDemoNumber); @@ -1201,7 +1201,7 @@ s32 play_mode_normal(void) { } } else { if (gDjuiInMainMenu && gCurrDemoInput == NULL && configMenuDemos && !gInPlayerMenu) { - if ((++gDemoCountdown) == PRESS_START_DEMO_TIMER && (find_demo_number() && (sDemoNumber <= 6 || sDemoNumber > -1))) { + if ((++gDemoCountdown) == PRESS_START_DEMO_TIMER && (find_demo_number() && (sDemoNumber <= 6 && sDemoNumber > -1))) { start_demo(); } } diff --git a/src/game/mario.c b/src/game/mario.c index d42465f9..49b01421 100644 --- a/src/game/mario.c +++ b/src/game/mario.c @@ -89,6 +89,7 @@ s16 set_mario_animation(struct MarioState *m, s32 targetAnimID) { struct Object *o = m->marioObj; if (!o || !m->animation) { return 0; } struct Animation *targetAnim = m->animation->targetAnim; + if (!targetAnim) { return 0; } if (load_patchable_table(m->animation, targetAnimID)) { targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); @@ -124,6 +125,7 @@ s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel) struct Object *o = m->marioObj; if (!o || !m->animation) { return 0; } struct Animation *targetAnim = m->animation->targetAnim; + if (!targetAnim) { return 0; } if (load_patchable_table(m->animation, targetAnimID)) { targetAnim->values = (void *) VIRTUAL_TO_PHYSICAL((u8 *) targetAnim + (uintptr_t) targetAnim->values); diff --git a/src/game/mario_actions_moving.c b/src/game/mario_actions_moving.c index 9bc5337b..daa70000 100644 --- a/src/game/mario_actions_moving.c +++ b/src/game/mario_actions_moving.c @@ -368,7 +368,7 @@ s32 apply_landing_accel(struct MarioState *m, f32 frictionFactor) { } void update_shell_speed(struct MarioState *m) { - if (!m) { return; } + if (!m || !m->floor) { return; } f32 maxTargetSpeed; f32 targetSpeed; @@ -538,7 +538,7 @@ s32 begin_braking_action(struct MarioState *m) { return set_mario_action(m, ACT_STANDING_AGAINST_WALL, 0); } - if (m->forwardVel >= 16.0f && m->floor->normal.y >= 0.17364818f) { + if (m->forwardVel >= 16.0f && m->floor && m->floor->normal.y >= 0.17364818f) { return set_mario_action(m, ACT_BRAKING, 0); } @@ -694,6 +694,9 @@ void anim_and_audio_for_hold_walk(struct MarioState *m) { val08 = FALSE; } break; + + default: + break; } } } @@ -1281,7 +1284,7 @@ s32 act_riding_shell_ground(struct MarioState *m) { } tilt_body_ground_shell(m, startYaw); - if (m->floor->type == SURFACE_BURNING) { + if (m->floor && m->floor->type == SURFACE_BURNING) { play_sound(SOUND_MOVING_RIDING_SHELL_LAVA, m->marioObj->header.gfx.cameraToObject); } else { play_sound(SOUND_MOVING_TERRAIN_RIDING_SHELL + m->terrainSoundAddend, @@ -1827,7 +1830,7 @@ u32 common_landing_action(struct MarioState *m, s16 animation, u32 airAction) { set_mario_animation(m, animation); play_mario_landing_sound_once(m, SOUND_ACTION_TERRAIN_LANDING); - if (m->floor->type >= SURFACE_SHALLOW_QUICKSAND && m->floor->type <= SURFACE_MOVING_QUICKSAND) { + if (m->floor && m->floor->type >= SURFACE_SHALLOW_QUICKSAND && m->floor->type <= SURFACE_MOVING_QUICKSAND) { m->quicksandDepth += (4 - m->actionTimer) * 3.5f - 0.5f; } @@ -1840,7 +1843,7 @@ s32 common_landing_cancels(struct MarioState *m, struct LandingAction *landingAc //! Everything here, including floor steepness, is checked before checking // if Mario is actually on the floor. This leads to e.g. remote sliding. - if (m->floor->normal.y < 0.2923717f) { + if (m->floor && m->floor->normal.y < 0.2923717f) { return mario_push_off_steep_floor(m, landingAction->verySteepAction, 0); } diff --git a/src/game/mario_actions_stationary.c b/src/game/mario_actions_stationary.c index 9a1722e3..be37a284 100644 --- a/src/game/mario_actions_stationary.c +++ b/src/game/mario_actions_stationary.c @@ -25,7 +25,7 @@ s32 check_common_idle_cancels(struct MarioState *m) { if (!m) { return 0; } mario_drop_held_object(m); - if (m->floor->normal.y < 0.29237169f) { + if (m->floor && m->floor->normal.y < 0.29237169f) { return mario_push_off_steep_floor(m, ACT_FREEFALL, 0); } diff --git a/src/game/mario_actions_submerged.c b/src/game/mario_actions_submerged.c index 1f926f90..139eed82 100644 --- a/src/game/mario_actions_submerged.c +++ b/src/game/mario_actions_submerged.c @@ -139,7 +139,7 @@ void apply_water_current(struct MarioState *m, Vec3f step) { s32 i; f32 whirlpoolRadius = 2000.0f; - if (m->floor->type == SURFACE_FLOWING_WATER) { + if (m->floor && m->floor->type == SURFACE_FLOWING_WATER) { s16 currentAngle = m->floor->force << 8; f32 currentSpeed = sWaterCurrentSpeeds[m->floor->force >> 8]; diff --git a/src/game/memory.c b/src/game/memory.c index 84f5361e..41415b3a 100644 --- a/src/game/memory.c +++ b/src/game/memory.c @@ -220,7 +220,7 @@ s32 load_patchable_table(struct MarioAnimation *a, u32 index) { u8* addr = sp20->srcAddr + sp20->anim[index].offset; u32 size = sp20->anim[index].size; - if (a->currentAnimAddr != addr) { + if (a->targetAnim && a->currentAnimAddr != addr) { memcpy(a->targetAnim, addr, size); a->currentAnimAddr = addr; return TRUE; diff --git a/src/game/obj_behaviors_2.c b/src/game/obj_behaviors_2.c index 0aac3258..602a7674 100644 --- a/src/game/obj_behaviors_2.c +++ b/src/game/obj_behaviors_2.c @@ -121,7 +121,7 @@ void obj_set_dist_from_home(f32 distFromHome) { } s32 obj_is_near_to_and_facing_mario(struct MarioState* m, f32 maxDist, s16 maxAngleDiff) { - if (!o) { return 0; } + if (!o || !m) { return 0; } struct Object* player = m->marioObj; s32 distanceToPlayer = dist_between_objects(o, player); s32 angleToPlayer = obj_angle_to_object(o, player); @@ -159,15 +159,14 @@ static BAD_RETURN(u32) obj_perform_position_op(s32 op) { void platform_on_track_update_pos_or_spawn_ball(s32 ballIndex, f32 x, f32 y, f32 z) { if (!o) { return; } - struct Object *trackBall; - struct Waypoint *initialPrevWaypoint; - struct Waypoint *nextWaypoint; - struct Waypoint *prevWaypoint; - UNUSED s32 unused; - f32 amountToMove; - f32 dx; - f32 dy; - f32 dz; + struct Object *trackBall = NULL; + struct Waypoint *initialPrevWaypoint = NULL; + struct Waypoint *nextWaypoint = NULL; + struct Waypoint *prevWaypoint = NULL; + f32 amountToMove = 0; + f32 dx = 0; + f32 dy = 0; + f32 dz = 0; f32 distToNextWaypoint = 100; if (ballIndex == 0 || ((u16)(o->oBehParams >> 16) & 0x0080)) { diff --git a/src/game/object_helpers.c b/src/game/object_helpers.c index a13963eb..c26527ce 100644 --- a/src/game/object_helpers.c +++ b/src/game/object_helpers.c @@ -2050,7 +2050,7 @@ f32 cur_obj_abs_y_dist_to_home(void) { s32 cur_obj_advance_looping_anim(void) { if (!o) { return 0; } s32 animFrame = o->header.gfx.animInfo.animFrame; - s32 loopEnd = o->header.gfx.animInfo.curAnim->loopEnd; + s32 loopEnd = o->header.gfx.animInfo.curAnim ? o->header.gfx.animInfo.curAnim->loopEnd : 1; s32 result; if (animFrame < 0) { @@ -2060,7 +2060,7 @@ s32 cur_obj_advance_looping_anim(void) { } else { animFrame++; } - + if (loopEnd == 0) { loopEnd = 1; } result = (animFrame << 16) / loopEnd; return result; @@ -3070,7 +3070,7 @@ void clear_time_stop_flags(s32 flags) { } s32 cur_obj_can_mario_activate_textbox(struct MarioState* m, f32 radius, f32 height, UNUSED s32 unused) { - if (!o) { return 0; } + if (!o || !m) { return 0; } if (!m->visibleToEnemies) { return FALSE; } if (o->oDistanceToMario < 1500.0f) { f32 latDistToMario = lateral_dist_between_objects(o, m->marioObj); @@ -3092,7 +3092,7 @@ s32 cur_obj_can_mario_activate_textbox_2(struct MarioState* m, f32 radius, f32 h } void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) { - if (!o) { return; } + if (!o || !m) { return; } if (m->playerIndex != 0) { return; } o->oDialogResponse = dialogResult; @@ -3104,7 +3104,7 @@ void cur_obj_end_dialog(struct MarioState* m, s32 dialogFlags, s32 dialogResult) } s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 dialogID, UNUSED s32 unused, u8 (*inContinueDialogFunction)(void)) { - if (!o) { return 0; } + if (!o || !m) { return 0; } s32 dialogResponse = 0; UNUSED s32 doneTurning = TRUE; @@ -3184,7 +3184,7 @@ s32 cur_obj_update_dialog(struct MarioState* m, s32 actionArg, s32 dialogFlags, } s32 cur_obj_update_dialog_with_cutscene(struct MarioState* m, s32 actionArg, s32 dialogFlags, s32 cutsceneTable, s32 dialogID, u8 (*inContinueDialogFunction)(void)) { - if (!o) { return 0; } + if (!o || !m) { return 0; } s32 dialogResponse = 0; s32 doneTurning = TRUE; diff --git a/src/game/object_list_processor.c b/src/game/object_list_processor.c index 0d6a02a5..f1499462 100644 --- a/src/game/object_list_processor.c +++ b/src/game/object_list_processor.c @@ -270,7 +270,7 @@ void bhv_mario_update(void) { // set mario state to the current player s32 stateIndex = (gCurrentObject->oBehParams - 1); - if (stateIndex > MAX_PLAYERS) { return; } + if (stateIndex >= MAX_PLAYERS || stateIndex < 0) { return; } gMarioState = &gMarioStates[stateIndex]; // sanity check torsoPos, it isn't updated off-screen otherwise @@ -477,7 +477,7 @@ void set_object_respawn_info_bits(struct Object *obj, u8 bits) { u16 *info16; u8 oldRespawnInfoBits = 0; u8 newRespawnInfoBits = 0; - if (!obj) { return; } + if (!obj || !obj->respawnInfo) { return; } switch (obj->respawnInfoType) { case RESPAWN_INFO_TYPE_32: diff --git a/src/game/scroll_targets.c b/src/game/scroll_targets.c index f67f61a0..5cd34c06 100644 --- a/src/game/scroll_targets.c +++ b/src/game/scroll_targets.c @@ -81,6 +81,7 @@ struct ScrollTarget* find_or_create_scroll_targets(u32 id) { */ void add_vtx_scroll_target(u32 id, Vtx *vtx, u32 size) { struct ScrollTarget *scroll = find_or_create_scroll_targets(id); + if (!scroll || !scroll->vertices) { return; } Vtx* *newArray; u32 oldSize = sizeof(void*) * scroll->size; u32 newSize = oldSize + (sizeof(void*) * size); diff --git a/src/game/spawn_sound.c b/src/game/spawn_sound.c index 9f05f5ed..45ccade9 100644 --- a/src/game/spawn_sound.c +++ b/src/game/spawn_sound.c @@ -18,7 +18,7 @@ void exec_anim_sound_state(struct SoundState *soundStates, u16 maxSoundStates) { if (!gCurrentObject) { return; } s32 stateIdx = gCurrentObject->oSoundStateID; - if (stateIdx >= maxSoundStates) { return; } + if (stateIdx < 0 || stateIdx >= maxSoundStates) { return; } switch (soundStates[stateIdx].playSound) { // since we have an array of sound states corresponding to diff --git a/src/pc/configini.c b/src/pc/configini.c index 7ef01907..2d87830c 100644 --- a/src/pc/configini.c +++ b/src/pc/configini.c @@ -1097,7 +1097,8 @@ ConfigRet ConfigRead(FILE *fp, Config **cfg) else { if ((ret = GetKeyVal(_cfg, p, &key, &val)) != CONFIG_OK) goto error; - + if (!sect) + goto error; if ((ret = ConfigAddString(_cfg, sect->name, key, val)) != CONFIG_OK) goto error; } diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 3e6fbb5a..732848f4 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -382,6 +382,7 @@ static bool gfx_texture_cache_lookup(int tile, struct TextureHashmapNode **n, co node = &gfx_texture_cache.hashmap[hash]; // puts("Clearing texture cache"); } + if (!node) { return false; } *node = &gfx_texture_cache.pool[gfx_texture_cache.pool_pos++]; if ((*node)->texture_addr == NULL) { (*node)->texture_id = gfx_rapi->new_texture(); diff --git a/src/pc/lua/smlua_cobject.c b/src/pc/lua/smlua_cobject.c index 86161bd2..f7086d69 100644 --- a/src/pc/lua/smlua_cobject.c +++ b/src/pc/lua/smlua_cobject.c @@ -80,6 +80,7 @@ struct LuaObjectField* smlua_get_object_field_from_ot(struct LuaObjectTable* ot, s32 max = ot->fieldCount - 1; s32 i = (min + max) / 2; while (true) { + if (!ot->fields[i].key) { return NULL; } s32 rc = strcmp(key, ot->fields[i].key); if (rc == 0) { return &ot->fields[i]; diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index 7accd057..188817ac 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -77,7 +77,7 @@ static struct LuaObjectField sAreaFields[LUA_AREA_FIELD_COUNT] = { { "surfaceRooms", LVT_S8_P, offsetof(struct Area, surfaceRooms), true, LOT_POINTER }, { "terrainData", LVT_S16_P, offsetof(struct Area, terrainData), true, LOT_POINTER }, { "terrainType", LVT_U16, offsetof(struct Area, terrainType), false, LOT_NONE }, -// { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), false, LOT_??? }, <--- UNIMPLEMENTED +// { "unk04", LVT_COBJECT_P, offsetof(struct Area, unk04), true, LOT_??? }, <--- UNIMPLEMENTED // { "unused28", LVT_COBJECT_P, offsetof(struct Area, unused28), false, LOT_??? }, <--- UNIMPLEMENTED { "warpNodes", LVT_COBJECT_P, offsetof(struct Area, warpNodes), false, LOT_OBJECTWARPNODE }, // { "whirlpools", LOT_???, offsetof(struct Area, whirlpools), false, LOT_??? }, <--- UNIMPLEMENTED @@ -388,13 +388,13 @@ static struct LuaObjectField sCharacterFields[LUA_CHARACTER_FIELD_COUNT] = { static struct LuaObjectField sControllerFields[LUA_CONTROLLER_FIELD_COUNT] = { { "buttonDown", LVT_U16, offsetof(struct Controller, buttonDown), false, LOT_NONE }, { "buttonPressed", LVT_U16, offsetof(struct Controller, buttonPressed), false, LOT_NONE }, -// { "controllerData", LVT_???, offsetof(struct Controller, controllerData), false, LOT_??? }, <--- UNIMPLEMENTED +// { "controllerData", LVT_???, offsetof(struct Controller, controllerData), true, LOT_??? }, <--- UNIMPLEMENTED { "extStickX", LVT_S16, offsetof(struct Controller, extStickX), false, LOT_NONE }, { "extStickY", LVT_S16, offsetof(struct Controller, extStickY), false, LOT_NONE }, { "port", LVT_S32, offsetof(struct Controller, port), false, LOT_NONE }, { "rawStickX", LVT_S16, offsetof(struct Controller, rawStickX), false, LOT_NONE }, { "rawStickY", LVT_S16, offsetof(struct Controller, rawStickY), false, LOT_NONE }, -// { "statusData", LVT_???, offsetof(struct Controller, statusData), false, LOT_??? }, <--- UNIMPLEMENTED +// { "statusData", LVT_???, offsetof(struct Controller, statusData), true, LOT_??? }, <--- UNIMPLEMENTED { "stickMag", LVT_F32, offsetof(struct Controller, stickMag), false, LOT_NONE }, { "stickX", LVT_F32, offsetof(struct Controller, stickX), false, LOT_NONE }, { "stickY", LVT_F32, offsetof(struct Controller, stickY), false, LOT_NONE }, @@ -632,44 +632,44 @@ static struct LuaObjectField sGlobalTexturesFields[LUA_GLOBAL_TEXTURES_FIELD_COU #define LUA_GRAPH_NODE_FIELD_COUNT 7 static struct LuaObjectField sGraphNodeFields[LUA_GRAPH_NODE_FIELD_COUNT] = { - { "children", LVT_COBJECT_P, offsetof(struct GraphNode, children), false, LOT_GRAPHNODE }, - { "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), false, LOT_NONE }, - { "flags", LVT_S16, offsetof(struct GraphNode, flags), false, LOT_NONE }, -// { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED - { "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE }, - { "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), true, LOT_GRAPHNODE }, - { "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), true, LOT_GRAPHNODE }, - { "type", LVT_S16, offsetof(struct GraphNode, type), false, LOT_NONE }, + { "children", LVT_COBJECT_P, offsetof(struct GraphNode, children), true, LOT_GRAPHNODE }, + { "extraFlags", LVT_U8, offsetof(struct GraphNode, extraFlags), true, LOT_NONE }, + { "flags", LVT_S16, offsetof(struct GraphNode, flags), true, LOT_NONE }, +// { "georef", LVT_???, offsetof(struct GraphNode, georef), true, LOT_??? }, <--- UNIMPLEMENTED + { "next", LVT_COBJECT_P, offsetof(struct GraphNode, next), true, LOT_GRAPHNODE }, + { "parent", LVT_COBJECT_P, offsetof(struct GraphNode, parent), true, LOT_GRAPHNODE }, + { "prev", LVT_COBJECT_P, offsetof(struct GraphNode, prev), true, LOT_GRAPHNODE }, + { "type", LVT_S16, offsetof(struct GraphNode, type), true, LOT_NONE }, }; #define LUA_GRAPH_NODE_OBJECT_FIELD_COUNT 26 static struct LuaObjectField sGraphNodeObjectFields[LUA_GRAPH_NODE_OBJECT_FIELD_COUNT] = { - { "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), false, LOT_NONE }, - { "angle", LVT_COBJECT, offsetof(struct GraphNodeObject, angle), true, LOT_VEC3S }, - { "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_ANIMINFO }, - { "areaIndex", LVT_S8, offsetof(struct GraphNodeObject, areaIndex), false, LOT_NONE }, - { "cameraToObject", LVT_COBJECT, offsetof(struct GraphNodeObject, cameraToObject), true, LOT_VEC3F }, - { "disableAutomaticShadowPos", LVT_BOOL, offsetof(struct GraphNodeObject, disableAutomaticShadowPos), false, LOT_NONE }, - { "node", LVT_COBJECT, offsetof(struct GraphNodeObject, node), true, LOT_GRAPHNODE }, - { "pos", LVT_COBJECT, offsetof(struct GraphNodeObject, pos), true, LOT_VEC3F }, - { "prevAngle", LVT_COBJECT, offsetof(struct GraphNodeObject, prevAngle), true, LOT_VEC3S }, - { "prevPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevPos), true, LOT_VEC3F }, - { "prevScale", LVT_COBJECT, offsetof(struct GraphNodeObject, prevScale), true, LOT_VEC3F }, - { "prevScaleTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevScaleTimestamp), false, LOT_NONE }, - { "prevShadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevShadowPos), true, LOT_VEC3F }, - { "prevShadowPosTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevShadowPosTimestamp), false, LOT_NONE }, - { "prevThrowMatrix", LVT_COBJECT, offsetof(struct GraphNodeObject, prevThrowMatrix), true, LOT_MAT4 }, - { "prevThrowMatrixTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevThrowMatrixTimestamp), false, LOT_NONE }, - { "prevTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevTimestamp), false, LOT_NONE }, - { "scale", LVT_COBJECT, offsetof(struct GraphNodeObject, scale), true, LOT_VEC3F }, - { "shadowInvisible", LVT_BOOL, offsetof(struct GraphNodeObject, shadowInvisible), false, LOT_NONE }, - { "shadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, shadowPos), true, LOT_VEC3F }, - { "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), false, LOT_GRAPHNODE }, - { "skipInViewCheck", LVT_BOOL, offsetof(struct GraphNodeObject, skipInViewCheck), false, LOT_NONE }, - { "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), false, LOT_NONE }, - { "throwMatrix", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrix), false, LOT_POINTER }, - { "throwMatrixPrev", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrixPrev), false, LOT_POINTER }, - { "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), false, LOT_SPAWNINFO }, + { "activeAreaIndex", LVT_S8, offsetof(struct GraphNodeObject, activeAreaIndex), true, LOT_NONE }, + { "angle", LVT_COBJECT, offsetof(struct GraphNodeObject, angle), true, LOT_VEC3S }, + { "animInfo", LVT_COBJECT, offsetof(struct GraphNodeObject, animInfo), true, LOT_ANIMINFO }, + { "areaIndex", LVT_S8, offsetof(struct GraphNodeObject, areaIndex), true, LOT_NONE }, + { "cameraToObject", LVT_COBJECT, offsetof(struct GraphNodeObject, cameraToObject), true, LOT_VEC3F }, + { "disableAutomaticShadowPos", LVT_BOOL, offsetof(struct GraphNodeObject, disableAutomaticShadowPos), true, LOT_NONE }, + { "node", LVT_COBJECT, offsetof(struct GraphNodeObject, node), true, LOT_GRAPHNODE }, + { "pos", LVT_COBJECT, offsetof(struct GraphNodeObject, pos), true, LOT_VEC3F }, + { "prevAngle", LVT_COBJECT, offsetof(struct GraphNodeObject, prevAngle), true, LOT_VEC3S }, + { "prevPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevPos), true, LOT_VEC3F }, + { "prevScale", LVT_COBJECT, offsetof(struct GraphNodeObject, prevScale), true, LOT_VEC3F }, + { "prevScaleTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevScaleTimestamp), true, LOT_NONE }, + { "prevShadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, prevShadowPos), true, LOT_VEC3F }, + { "prevShadowPosTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevShadowPosTimestamp), true, LOT_NONE }, + { "prevThrowMatrix", LVT_COBJECT, offsetof(struct GraphNodeObject, prevThrowMatrix), true, LOT_MAT4 }, + { "prevThrowMatrixTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevThrowMatrixTimestamp), true, LOT_NONE }, + { "prevTimestamp", LVT_U32, offsetof(struct GraphNodeObject, prevTimestamp), true, LOT_NONE }, + { "scale", LVT_COBJECT, offsetof(struct GraphNodeObject, scale), true, LOT_VEC3F }, + { "shadowInvisible", LVT_BOOL, offsetof(struct GraphNodeObject, shadowInvisible), true, LOT_NONE }, + { "shadowPos", LVT_COBJECT, offsetof(struct GraphNodeObject, shadowPos), true, LOT_VEC3F }, + { "sharedChild", LVT_COBJECT_P, offsetof(struct GraphNodeObject, sharedChild), true, LOT_GRAPHNODE }, + { "skipInViewCheck", LVT_BOOL, offsetof(struct GraphNodeObject, skipInViewCheck), true, LOT_NONE }, + { "skipInterpolationTimestamp", LVT_U32, offsetof(struct GraphNodeObject, skipInterpolationTimestamp), true, LOT_NONE }, + { "throwMatrix", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrix), true, LOT_POINTER }, + { "throwMatrixPrev", LVT_COBJECT_P, offsetof(struct GraphNodeObject, throwMatrixPrev), true, LOT_POINTER }, + { "unk4C", LVT_COBJECT_P, offsetof(struct GraphNodeObject, unk4C), true, LOT_SPAWNINFO }, }; #define LUA_GRAPH_NODE_802_A45_E4_FIELD_COUNT 6 @@ -793,7 +793,7 @@ static struct LuaObjectField sLinearTransitionPointFields[LUA_LINEAR_TRANSITION_ #define LUA_MARIO_ANIMATION_FIELD_COUNT 2 static struct LuaObjectField sMarioAnimationFields[LUA_MARIO_ANIMATION_FIELD_COUNT] = { -// { "animDmaTable", LVT_COBJECT_P, offsetof(struct MarioAnimation, animDmaTable), false, LOT_??? }, <--- UNIMPLEMENTED +// { "animDmaTable", LVT_COBJECT_P, offsetof(struct MarioAnimation, animDmaTable), true, LOT_??? }, <--- UNIMPLEMENTED { "currentAnimAddr", LVT_U8_P, offsetof(struct MarioAnimation, currentAnimAddr), true, LOT_POINTER }, // { "padding", LOT_???, offsetof(struct MarioAnimation, padding), false, LOT_??? }, <--- UNIMPLEMENTED { "targetAnim", LVT_COBJECT_P, offsetof(struct MarioAnimation, targetAnim), false, LOT_ANIMATION }, @@ -826,7 +826,7 @@ static struct LuaObjectField sMarioStateFields[LUA_MARIO_STATE_FIELD_COUNT] = { { "actionTimer", LVT_U16, offsetof(struct MarioState, actionTimer), false, LOT_NONE }, { "angleVel", LVT_COBJECT, offsetof(struct MarioState, angleVel), true, LOT_VEC3S }, { "animation", LVT_COBJECT_P, offsetof(struct MarioState, animation), false, LOT_MARIOANIMATION }, - { "area", LVT_COBJECT_P, offsetof(struct MarioState, area), false, LOT_AREA }, + { "area", LVT_COBJECT_P, offsetof(struct MarioState, area), true, LOT_AREA }, { "bounceSquishTimer", LVT_U8, offsetof(struct MarioState, bounceSquishTimer), false, LOT_NONE }, { "bubbleObj", LVT_COBJECT_P, offsetof(struct MarioState, bubbleObj), false, LOT_OBJECT }, { "cap", LVT_U32, offsetof(struct MarioState, cap), false, LOT_NONE }, @@ -983,7 +983,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "behavior", LVT_BEHAVIORSCRIPT_P, offsetof(struct Object, behavior), true, LOT_POINTER }, { "bhvDelayTimer", LVT_S16, offsetof(struct Object, bhvDelayTimer), false, LOT_NONE }, // { "bhvStack", LOT_???, offsetof(struct Object, bhvStack), false, LOT_??? }, <--- UNIMPLEMENTED - { "bhvStackIndex", LVT_U32, offsetof(struct Object, bhvStackIndex), false, LOT_NONE }, + { "bhvStackIndex", LVT_U32, offsetof(struct Object, bhvStackIndex), true, LOT_NONE }, { "collidedObjInteractTypes", LVT_U32, offsetof(struct Object, collidedObjInteractTypes), false, LOT_NONE }, // { "collidedObjs", LOT_???, offsetof(struct Object, collidedObjs), false, LOT_??? }, <--- UNIMPLEMENTED { "collisionData", LVT_COLLISION_P, offsetof(struct Object, collisionData), false, LOT_POINTER }, @@ -1147,7 +1147,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "oChainChompNumLunges", LVT_S32, offsetof(struct Object, oChainChompNumLunges), false, LOT_NONE }, { "oChainChompReleaseStatus", LVT_S32, offsetof(struct Object, oChainChompReleaseStatus), false, LOT_NONE }, { "oChainChompRestrictedByChain", LVT_S32, offsetof(struct Object, oChainChompRestrictedByChain), false, LOT_NONE }, - { "oChainChompSegments", LVT_COBJECT_P, offsetof(struct Object, oChainChompSegments), false, LOT_CHAINSEGMENT }, + { "oChainChompSegments", LVT_COBJECT_P, offsetof(struct Object, oChainChompSegments), true, LOT_CHAINSEGMENT }, { "oChainChompTargetPitch", LVT_S32, offsetof(struct Object, oChainChompTargetPitch), false, LOT_NONE }, { "oChainChompUnk104", LVT_F32, offsetof(struct Object, oChainChompUnk104), false, LOT_NONE }, { "oCheckerBoardPlatformUnk1AC", LVT_F32, offsetof(struct Object, oCheckerBoardPlatformUnk1AC), false, LOT_NONE }, @@ -1721,7 +1721,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { { "oWhitePuffUnkFC", LVT_S32, offsetof(struct Object, oWhitePuffUnkFC), false, LOT_NONE }, { "oWhompShakeVal", LVT_S32, offsetof(struct Object, oWhompShakeVal), false, LOT_NONE }, { "oWigglerFallThroughFloorsHeight", LVT_F32, offsetof(struct Object, oWigglerFallThroughFloorsHeight), false, LOT_NONE }, - { "oWigglerSegments", LVT_COBJECT_P, offsetof(struct Object, oWigglerSegments), false, LOT_CHAINSEGMENT }, + { "oWigglerSegments", LVT_COBJECT_P, offsetof(struct Object, oWigglerSegments), true, LOT_CHAINSEGMENT }, { "oWigglerSquishSpeed", LVT_F32, offsetof(struct Object, oWigglerSquishSpeed), false, LOT_NONE }, { "oWigglerTargetYaw", LVT_S32, offsetof(struct Object, oWigglerTargetYaw), false, LOT_NONE }, { "oWigglerTextStatus", LVT_S16, offsetof(struct Object, oWigglerTextStatus), false, LOT_NONE }, @@ -1743,7 +1743,7 @@ static struct LuaObjectField sObjectFields[LUA_OBJECT_FIELD_COUNT] = { // { "ptrData", LOT_???, offsetof(struct Object, ptrData), false, LOT_??? }, <--- UNIMPLEMENTED // { "rawData", LOT_???, offsetof(struct Object, rawData), false, LOT_??? }, <--- UNIMPLEMENTED // { "respawnInfo", LVT_???, offsetof(struct Object, respawnInfo), false, LOT_??? }, <--- UNIMPLEMENTED - { "respawnInfoType", LVT_S16, offsetof(struct Object, respawnInfoType), false, LOT_NONE }, + { "respawnInfoType", LVT_S16, offsetof(struct Object, respawnInfoType), true, LOT_NONE }, { "setHome", LVT_U8, offsetof(struct Object, setHome), false, LOT_NONE }, { "transform", LVT_COBJECT, offsetof(struct Object, transform), true, LOT_MAT4 }, { "unused1", LVT_U32, offsetof(struct Object, unused1), false, LOT_NONE }, @@ -1931,8 +1931,8 @@ static struct LuaObjectField sSpawnInfoFields[LUA_SPAWN_INFO_FIELD_COUNT] = { { "next", LVT_COBJECT_P, offsetof(struct SpawnInfo, next), true, LOT_SPAWNINFO }, { "startAngle", LVT_COBJECT, offsetof(struct SpawnInfo, startAngle), true, LOT_VEC3S }, { "startPos", LVT_COBJECT, offsetof(struct SpawnInfo, startPos), true, LOT_VEC3S }, - { "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), false, LOT_NONE }, - { "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), false, LOT_GRAPHNODE }, + { "syncID", LVT_U32, offsetof(struct SpawnInfo, syncID), true, LOT_NONE }, + { "unk18", LVT_COBJECT_P, offsetof(struct SpawnInfo, unk18), true, LOT_GRAPHNODE }, }; #define LUA_SPAWN_PARTICLES_INFO_FIELD_COUNT 12 @@ -2038,7 +2038,7 @@ static struct LuaObjectField sTransitionInfoFields[LUA_TRANSITION_INFO_FIELD_COU { "posYaw", LVT_S16, offsetof(struct TransitionInfo, posYaw), false, LOT_NONE }, }; -#define LUA_WALL_COLLISION_DATA_FIELD_COUNT 6 +#define LUA_WALL_COLLISION_DATA_FIELD_COUNT 9 static struct LuaObjectField sWallCollisionDataFields[LUA_WALL_COLLISION_DATA_FIELD_COUNT] = { { "normalAddition", LVT_COBJECT, offsetof(struct WallCollisionData, normalAddition), true, LOT_VEC3F }, { "normalCount", LVT_U8, offsetof(struct WallCollisionData, normalCount), false, LOT_NONE }, @@ -2047,7 +2047,9 @@ static struct LuaObjectField sWallCollisionDataFields[LUA_WALL_COLLISION_DATA_FI { "radius", LVT_F32, offsetof(struct WallCollisionData, radius), false, LOT_NONE }, { "unused", LVT_S16, offsetof(struct WallCollisionData, unused), false, LOT_NONE }, // { "walls", LOT_???, offsetof(struct WallCollisionData, walls), false, LOT_??? }, <--- UNIMPLEMENTED -// { "z", LVT_???, offsetof(struct WallCollisionData, z), false, LOT_??? }, <--- UNIMPLEMENTED + { "x", LVT_F32, offsetof(struct WallCollisionData, x), false, LOT_NONE }, + { "y", LVT_F32, offsetof(struct WallCollisionData, y), false, LOT_NONE }, + { "z", LVT_F32, offsetof(struct WallCollisionData, z), false, LOT_NONE }, }; #define LUA_WARP_NODE_FIELD_COUNT 4 diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index b7a14bdf..a3c51822 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -3998,6 +3998,7 @@ char gSmluaConstants[] = "" "TERRAIN_WATER = 0x0005\n" "TERRAIN_SLIDE = 0x0006\n" "TERRAIN_MASK = 0x0007\n" +"OBJECT_MAX_BHV_STACK = 16\n" "SPTASK_STATE_NOT_STARTED = 0\n" "SPTASK_STATE_RUNNING = 1\n" "SPTASK_STATE_INTERRUPTED = 2\n" diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index 3af72eb4..eda36287 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -602,6 +602,7 @@ s32 smlua_func_level_script_parse_callback(u8 type, void *cmd) { LOG_LUA("Failed to call the callback behaviors: %u", type); return 0; } + return 0; } void smlua_func_level_script_parse(lua_State* L) { @@ -667,10 +668,18 @@ static u16 *smlua_to_u16_list(lua_State* L, int index) { int indexValue = lua_gettop(L) - 0; s32 key = smlua_to_integer(L, indexKey); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_to_u16_list: Failed to convert table key"); return 0; } + if (!gSmLuaConvertSuccess) { + LOG_LUA("smlua_to_u16_list: Failed to convert table key"); + free(values); + return 0; + } u16 value = smlua_to_integer(L, indexValue); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_to_u16_list: Failed to convert table value"); return 0; } + if (!gSmLuaConvertSuccess) { + LOG_LUA("smlua_to_u16_list: Failed to convert table value"); + free(values); + return 0; + } values[key - 1] = value; lua_settop(L, top); @@ -683,28 +692,28 @@ int smlua_func_smlua_anim_util_register_animation(lua_State* L) { if (!smlua_functions_valid_param_count(L, 8)) { return 0; } const char *name = smlua_to_string(L, 1); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'name'"); return 0; } + if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "name"); return 0; } s16 flags = smlua_to_integer(L, 2); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'flags'"); return 0; } + if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "flags"); return 0; } s16 animYTransDivisor = smlua_to_integer(L, 3); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'animYTransDivisor'"); return 0; } + if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "animYTransDivisor"); return 0; } s16 startFrame = smlua_to_integer(L, 4); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'startFrame'"); return 0; } + if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "startFrame"); return 0; } s16 loopStart = smlua_to_integer(L, 5); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'loopStart'"); return 0; } + if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "loopStart"); return 0; } s16 loopEnd = smlua_to_integer(L, 6); - if (!gSmLuaConvertSuccess) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'loopEnd'"); return 0; } + if (!gSmLuaConvertSuccess) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "loopEnd"); return 0; } s16 *values = (s16 *) smlua_to_u16_list(L, 7); - if (!values) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'values'"); return 0; } + if (!values) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "values"); return 0; } u16 *index = (u16 *) smlua_to_u16_list(L, 8); - if (!index) { LOG_LUA("smlua_anim_util_register_animation: Failed to convert parameter 'index'"); return 0; } + if (!index) { LOG_LUA("%s: Failed to convert parameter '%s'", "smlua_anim_util_register_animation", "index"); free(values); return 0; } smlua_anim_util_register_animation(name, flags, animYTransDivisor, startFrame, loopStart, loopEnd, values, index); diff --git a/src/pc/lua/utils/smlua_anim_utils.c b/src/pc/lua/utils/smlua_anim_utils.c index ef98dfa9..2ebf9e8a 100644 --- a/src/pc/lua/utils/smlua_anim_utils.c +++ b/src/pc/lua/utils/smlua_anim_utils.c @@ -129,17 +129,21 @@ void smlua_anim_util_reset() { sCustomAnimationHead = NULL; } -void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, const s16 *values, const u16 *index) { +void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, s16 *values, u16 *index) { // NULL-checks if (!name) { LOG_LUA_LINE("smlua_anim_util_register_animation: Parameter 'name' is NULL"); + free(values); + free(index); return; } // Check if the name is not already taken if (get_custom_animation_node(name)) { LOG_LUA_LINE("smlua_anim_util_register_animation: An animation named '%s' already exists", name); + free(values); + free(index); return; } diff --git a/src/pc/lua/utils/smlua_anim_utils.h b/src/pc/lua/utils/smlua_anim_utils.h index 56c0ca1a..e627b354 100644 --- a/src/pc/lua/utils/smlua_anim_utils.h +++ b/src/pc/lua/utils/smlua_anim_utils.h @@ -67,7 +67,7 @@ struct GlobalObjectAnimations { extern struct GlobalObjectAnimations gGlobalObjectAnimations; void smlua_anim_util_reset(); -void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, const s16 *values, const u16 *index); +void smlua_anim_util_register_animation(const char *name, s16 flags, s16 animYTransDivisor, s16 startFrame, s16 loopStart, s16 loopEnd, s16 *values, u16 *index); void smlua_anim_util_set_animation(struct Object *obj, const char *name); const char *smlua_anim_util_get_current_animation_name(struct Object *obj); diff --git a/src/pc/mods/mod_cache.c b/src/pc/mods/mod_cache.c index 87a1329b..2d3de12a 100644 --- a/src/pc/mods/mod_cache.c +++ b/src/pc/mods/mod_cache.c @@ -125,14 +125,18 @@ struct ModCacheEntry* mod_cache_get_from_path(const char* path, bool validate) { return NULL; } -void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { +void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, char* inPath) { + char* path = strdup(inPath); + // sanity check if (path == NULL || strlen(path) == 0) { LOG_ERROR("Invalid path"); + free(path); return; } if (!fs_sys_file_exists(path)) { LOG_ERROR("File does not exist: %s", path); + free(path); return; } normalize_path((char*)path); @@ -146,6 +150,7 @@ void mod_cache_add_internal(u8* dataHash, u64 lastLoaded, const char* path) { } if (!foundNonZero) { LOG_ERROR("Hash was all zeros for path '%s'", path); + free(path); return; } @@ -215,13 +220,13 @@ void mod_cache_add(struct Mod* mod, struct ModFile* file, bool useFilePath) { struct ModCacheEntry* entry = mod_cache_get_from_path(file->cachedPath, false); if (useFilePath && entry) { memcpy(file->dataHash, entry->dataHash, 16); - mod_cache_add_internal(file->dataHash, 0, strdup(file->cachedPath)); + mod_cache_add_internal(file->dataHash, 0, (char*)file->cachedPath); return; } // hash and cache mod_cache_md5(file->cachedPath, file->dataHash); - mod_cache_add_internal(file->dataHash, 0, strdup(file->cachedPath)); + mod_cache_add_internal(file->dataHash, 0, (char*)file->cachedPath); } void mod_cache_update(struct Mod* mod, struct ModFile* file) { @@ -244,7 +249,7 @@ void mod_cache_update(struct Mod* mod, struct ModFile* file) { // hash and cache mod_cache_md5(file->cachedPath, file->dataHash); - mod_cache_add_internal(file->dataHash, 0, strdup(file->cachedPath)); + mod_cache_add_internal(file->dataHash, 0, (char*)file->cachedPath); } void mod_cache_load(void) { @@ -280,10 +285,12 @@ void mod_cache_load(void) { fread(&lastLoaded, sizeof(u64), 1, fp); fread(&pathLen, sizeof(u16), 1, fp); - const char* path = calloc(pathLen + 1, sizeof(char*)); - fread((char*)path, sizeof(char*), pathLen + 1, fp); + char* path = calloc(pathLen + 1, sizeof(char)); + fread((char*)path, sizeof(char), pathLen + 1, fp); - mod_cache_add_internal(dataHash, lastLoaded, path); + mod_cache_add_internal(dataHash, lastLoaded, (char*)path); + + free((void*)path); count++; } LOG_INFO("Loading mod cache complete"); diff --git a/src/pc/mods/mod_storage.c b/src/pc/mods/mod_storage.c index 1c138266..ab9b75c4 100644 --- a/src/pc/mods/mod_storage.c +++ b/src/pc/mods/mod_storage.c @@ -64,7 +64,7 @@ u32 key_count(char* filename) { return lines - 4; } -char *mod_storage_get_filename(char* dest) { +void mod_storage_get_filename(char* dest) { const char *path = sys_user_path(); // get base sm64ex-coop appdata dir snprintf(dest, SYS_MAX_PATH - 1, "%s/sav/%s", path, gLuaActiveMod->relativePath); // append sav folder strdelete(dest, ".lua"); // delete ".lua" from sav name