From f631f4d62f267adcaf7598dd5efc45e959632882 Mon Sep 17 00:00:00 2001 From: MysterD Date: Tue, 18 Jan 2022 18:51:06 -0800 Subject: [PATCH] More Lua improvements restrict lua libraries extended moveset: finish roll, dive hopping wrote a python script to codegen lua functions from C header files converted most of mario.h --- mods/convert_header.py | 178 ++++++++++ mods/test.lua | 105 +++--- src/game/mario.h | 2 +- src/pc/lua/smlua.c | 15 +- src/pc/lua/smlua_functions.c | 659 +++++++++++++++++++++++++++-------- src/pc/lua/smlua_utils.c | 163 ++++++--- src/pc/lua/smlua_utils.h | 12 +- 7 files changed, 898 insertions(+), 236 deletions(-) create mode 100644 mods/convert_header.py diff --git a/mods/convert_header.py b/mods/convert_header.py new file mode 100644 index 000000000..206b01431 --- /dev/null +++ b/mods/convert_header.py @@ -0,0 +1,178 @@ +import re + +rejects = "" +integer_types = ["u8", "u16", "u32", "u64", "s8", "s16", "s32", "s64", "int"] +number_types = ["f32", "float"] +cobject_types = ["struct MarioState*", "Vec3s", "Vec3f"] +cobject_lot_types = ["LOT_MARIO_STATE", "LOT_VEC3S", "LOT_VEC3F"] + +header_h = """ +s32 is_anim_at_end(struct MarioState *m); +s32 is_anim_past_end(struct MarioState *m); +s16 set_mario_animation(struct MarioState *m, s32 targetAnimID); +s16 set_mario_anim_with_accel(struct MarioState *m, s32 targetAnimID, s32 accel); +void set_anim_to_frame(struct MarioState *m, s16 animFrame); +s32 is_anim_past_frame(struct MarioState *m, s16 animFrame); +s16 find_mario_anim_flags_and_translation(struct Object *o, s32 yaw, Vec3s translation); +void update_mario_pos_for_anim(struct MarioState *m); +s16 return_mario_anim_y_translation(struct MarioState *m); +void play_sound_if_no_flag(struct MarioState *m, u32 soundBits, u32 flags); +void play_mario_jump_sound(struct MarioState *m); +void adjust_sound_for_speed(struct MarioState *m); +void play_sound_and_spawn_particles(struct MarioState *m, u32 soundBits, u32 waveParticleType); +void play_mario_action_sound(struct MarioState *m, u32 soundBits, u32 waveParticleType); +void play_mario_landing_sound(struct MarioState *m, u32 soundBits); +void play_mario_landing_sound_once(struct MarioState *m, u32 soundBits); +void play_mario_heavy_landing_sound(struct MarioState *m, u32 soundBits); +void play_mario_heavy_landing_sound_once(struct MarioState *m, u32 soundBits); +void play_mario_sound(struct MarioState *m, s32 primarySoundBits, s32 scondarySoundBits); +void mario_set_bubbled(struct MarioState* m); +void mario_set_forward_vel(struct MarioState *m, f32 speed); +s32 mario_get_floor_class(struct MarioState *m); +u32 mario_get_terrain_sound_addend(struct MarioState *m); +struct Surface *resolve_and_return_wall_collisions(Vec3f pos, f32 offset, f32 radius); +f32 vec3f_find_ceil(Vec3f pos, f32 height, struct Surface **ceil); +s32 mario_facing_downhill(struct MarioState *m, s32 turnYaw); +u32 mario_floor_is_slippery(struct MarioState *m); +s32 mario_floor_is_slope(struct MarioState *m); +s32 mario_floor_is_steep(struct MarioState *m); +f32 find_floor_height_relative_polar(struct MarioState *m, s16 angleFromMario, f32 distFromMario); +s16 find_floor_slope(struct MarioState *m, s16 yawOffset); +void update_mario_sound_and_camera(struct MarioState *m); +void set_steep_jump_action(struct MarioState *m); +u32 set_mario_action(struct MarioState *m, u32 action, u32 actionArg); +s32 set_jump_from_landing(struct MarioState *m); +s32 set_jumping_action(struct MarioState *m, u32 action, u32 actionArg); +s32 drop_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg); +s32 hurt_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg, s16 hurtCounter); +s32 check_common_action_exits(struct MarioState *m); +s32 check_common_hold_action_exits(struct MarioState *m); +s32 transition_submerged_to_walking(struct MarioState *m); +s32 set_water_plunge_action(struct MarioState *m); +s32 execute_mario_action(UNUSED struct Object *o); +s32 force_idle_state(struct MarioState* m); +void init_mario(void); +void init_mario_from_save_file(void); +""" + +functions = [] + +def reject_line(line): + if len(line) == 0: + return True + if '(' not in line: + return True + if ')' not in line: + return True + if ';' not in line: + return True + +def normalize_type(t): + t = t.strip() + if ' ' in t: + parts = t.split(' ', 1) + t = parts[0] + ' ' + parts[1].replace(' ', '') + return t + +def process_line(line): + function = {} + + line = line.strip() + function['line'] = line + + line = line.replace('UNUSED', '') + + match = re.search('[a-zA-Z0-9_]+\(', line) + function['type'] = normalize_type(line[0:match.span()[0]]) + function['identifier'] = match.group()[0:-1] + + function['params'] = [] + params_str = line.split('(', 1)[1].rsplit(')', 1)[0].strip() + if len(params_str) == 0 or params_str == 'void': + pass + else: + for param_str in params_str.split(','): + param = {} + param_str = param_str.strip() + match = re.search('[a-zA-Z0-9_]+$', param_str) + param['type'] = normalize_type(param_str[0:match.span()[0]]) + param['identifier'] = match.group() + function['params'].append(param) + + functions.append(function) + +def process_lines(): + for line in header_h.splitlines(): + if reject_line(line): + global rejects + rejects += line + '\n' + continue + process_line(line) + +def build_param(param, i): + ptype = param['type'] + pid = param['identifier'] + + if ptype in integer_types: + return ' %s %s = smlua_to_integer(L, %d);\n' % (ptype, pid, i) + elif ptype in number_types: + return ' %s %s = smlua_to_number(L, %d);\n' % (ptype, pid, i) + elif ptype in cobject_types: + index = cobject_types.index(ptype) + return ' %s %s = (%s)smlua_to_cobject(L, %d, %s);\n' % (ptype, pid, ptype, i, cobject_lot_types[index]) + else: + return ' ' + ptype + ' ' + pid + ' <--- UNIMPLEMENTED' + '\n' + +def build_return(function): + ftype = function['type'] + fid = function['identifier'] + + ccall = '%s(%s)' % (fid, ', '.join([x['identifier'] for x in function['params']])) + + if ftype == 'void': + return ' %s;\n' % ccall + + lfunc = 'UNIMPLEMENTED -->' + if ftype in integer_types: + lfunc = 'lua_pushinteger' + elif ftype in number_types: + lfunc = 'lua_pushnumber' + + return ' %s(L, %s);\n' % (lfunc, ccall) + +def build_function(function): + s = 'int smlua_func_%s(lua_State* L) {\n' % function['identifier'] + + i = 1 + for param in function['params']: + s += build_param(param, i) + s += ' if (!gSmLuaConvertSuccess) { return 0; }\n' + i += 1 + s += '\n' + + s += build_return(function) + s += ' return 1;\n}\n' + + function['implemented'] = not ('UNIMPLEMENTED' in s) + if 'UNIMPLEMENTED' in s: + s = "/*\n" + s + "*/\n" + + print(s) + +def build_functions(): + for function in functions: + build_function(function) + +process_lines() +build_functions() +print('') +print('-------------------') +for function in functions: + s = 'smlua_bind_function(L, "%s", smlua_func_%s);' % (function['identifier'], function['identifier']) + if function['implemented']: + print(' ' + s) + else: + print(' //' + s + ' <--- UNIMPLEMENTED') +print('-------------------') +print('REJECTS:') +print(rejects) \ No newline at end of file diff --git a/mods/test.lua b/mods/test.lua index 9742616e5..d4d2a8ece 100644 --- a/mods/test.lua +++ b/mods/test.lua @@ -1,16 +1,34 @@ --- initialize actions -ACT_ROLL = (0x05B | ACT_FLAG_MOVING | ACT_FLAG_BUTT_OR_STOMACH_SLIDE) -ACT_ROLL_AIR = (0x0BA | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) +------------------------ +-- initialize actions -- +------------------------ + +ACT_SPIN_POUND_LAND = (0x037 | ACT_FLAG_STATIONARY | ACT_FLAG_ATTACKING) +ACT_ROLL = (0x05B | ACT_FLAG_MOVING | ACT_FLAG_BUTT_OR_STOMACH_SLIDE) +ACT_GROUND_POUND_JUMP = (0x084 | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) +ACT_SPIN_JUMP = (0x08B | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) +ACT_SPIN_POUND = (0x08F | ACT_FLAG_AIR | ACT_FLAG_ATTACKING) +ACT_LEDGE_PARKOUR = (0x09D | ACT_FLAG_AIR) +ACT_ROLL_AIR = (0x0BA | ACT_FLAG_AIR | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) +ACT_WALL_SLIDE = (0x0BF | ACT_FLAG_AIR | ACT_FLAG_MOVING | ACT_FLAG_ALLOW_VERTICAL_WIND_ACTION) +ACT_WATER_GROUND_POUND = (0x0C9 | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT | ACT_FLAG_ATTACKING) +ACT_WATER_GROUND_POUND_LAND = (0x0CA | ACT_FLAG_STATIONARY | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT) +ACT_WATER_GROUND_POUND_STROKE = (0x0CB | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT) +ACT_WATER_GROUND_POUND_JUMP = (0x0CC | ACT_FLAG_MOVING | ACT_FLAG_SWIMMING | ACT_FLAG_SWIMMING_OR_FLYING | ACT_FLAG_WATER_OR_TEXT) + +----------------------------- +-- initialize extra fields -- +----------------------------- --- initialize extra fields gMarioStateExtras = {} for i=0,(MAX_PLAYERS-1) do gMarioStateExtras[i] = {} - gMarioStateExtras[i].spareFloat = 0 - gMarioStateExtras[i].spareInt = 0 + gMarioStateExtras[i].rotAngle = 0 + gMarioStateExtras[i].boostTimer = 0 end ---------------------------------------------------------- +--------------- +-- utilities -- +--------------- function sins(theta) return math.sin(theta * math.pi / (2 * 16384)) @@ -20,7 +38,9 @@ function coss(theta) return math.cos(theta * math.pi / (2 * 16384)) end ---------------------------------------------------------- +---------- +-- roll -- +---------- function increase_roll_yaw(m) local newFacingDYaw = m.faceAngle.y - m.slideYaw @@ -97,8 +117,6 @@ function update_roll_sliding(m, stopSpeed) return stopped end ---------------------------------------------------------- - function act_roll(m) local e = gMarioStateExtras[m.playerIndex] @@ -107,14 +125,14 @@ function act_roll(m) local ROLL_CANCEL_LOCKOUT_TIME = 10 local BOOST_LOCKOUT_TIME = 20 - -- e.spareFloat is used for Mario's rotation angle during the roll (persists when going into ACT_ROLL_AIR and back) - -- e.spareInt is used for the boost lockout timer (persists when going into ACT_ROLL_AIR and back) + -- e.rotAngle is used for Mario's rotation angle during the roll (persists when going into ACT_ROLL_AIR and back) + -- e.boostTimer is used for the boost lockout timer (persists when going into ACT_ROLL_AIR and back) -- m.actionTimer is used to lockout walk canceling out of rollout (reset each action switch) if m.actionTimer == 0 then if m.prevAction ~= ACT_ROLL_AIR then - e.spareFloat = 0 - e.spareInt = 0 + e.rotAngle = 0 + e.boostTimer = 0 end elseif m.actionTimer >= ROLL_CANCEL_LOCKOUT_TIME or m.actionArg == 1 then if (m.input & INPUT_Z_DOWN) == 0 then @@ -134,8 +152,8 @@ function act_roll(m) m.vel.y = 19.0; play_mario_sound(m, SOUND_ACTION_TERRAIN_JUMP, 0); - if e.spareInt >= BOOST_LOCKOUT_TIME then - e.spareInt = 0; + if e.boostTimer >= BOOST_LOCKOUT_TIME then + e.boostTimer = 0; if m.forwardVel < MAX_NORMAL_ROLL_SPEED then mario_set_forward_vel(m, math.min(m.forwardVel + ROLL_BOOST_GAIN, MAX_NORMAL_ROLL_SPEED)); @@ -159,13 +177,13 @@ function act_roll(m) common_slide_action(m, ACT_CROUCH_SLIDE, ACT_ROLL_AIR, MARIO_ANIM_FORWARD_SPINNING); - e.spareFloat = e.spareFloat + (0x80 * m.forwardVel); - if e.spareFloat > 0x10000 then - e.spareFloat = e.spareFloat - 0x10000; + e.rotAngle = e.rotAngle + (0x80 * m.forwardVel); + if e.rotAngle > 0x10000 then + e.rotAngle = e.rotAngle - 0x10000; end - set_anim_to_frame(m, 10 * e.spareFloat / 0x10000); + set_anim_to_frame(m, 10 * e.rotAngle / 0x10000); - e.spareInt = e.spareInt + 1; + e.boostTimer = e.boostTimer + 1; m.actionTimer = m.actionTimer + 1; @@ -179,8 +197,8 @@ function act_roll_air(m) if m.actionTimer == 0 then if m.prevAction ~= ACT_ROLL then - e.spareFloat = 0 - e.spareInt = 0 + e.rotAngle = 0 + e.boostTimer = 0 end end @@ -208,30 +226,20 @@ function act_roll_air(m) return set_mario_action(m, ACT_BACKWARD_AIR_KB, 0) end - e.spareFloat = e.spareFloat + 0x80 * m.forwardVel - if e.spareFloat > 0x10000 then - e.spareFloat = e.spareFloat - 0x10000 + e.rotAngle = e.rotAngle + 0x80 * m.forwardVel + if e.rotAngle > 0x10000 then + e.rotAngle = e.rotAngle - 0x10000 end - set_anim_to_frame(m, 10 * e.spareFloat / 0x10000) + set_anim_to_frame(m, 10 * e.rotAngle / 0x10000) - e.spareInt = e.spareInt + 1 + e.boostTimer = e.boostTimer + 1 m.actionTimer = m.actionTimer + 1 return false end - ---------------------------------------------------------- - -function update() -end - -function mario_update(m) - -- if m.vel.y > 0 then - -- m.vel.y = m.vel.y + 2 - -- end - +function update_roll(m) if m.action == ACT_DIVE_SLIDE then if (m.input & INPUT_ABOVE_SLIDE) == 0 then if (m.input & INPUT_Z_DOWN) ~= 0 and m.actionTimer < 2 then @@ -290,6 +298,25 @@ function mario_update(m) end end +--------------------------------------------------------- + +function update() +end + +function mario_update(m) + update_roll(m) + + -- dive hop + if (m.input & INPUT_B_PRESSED) ~= 0 and (m.input & INPUT_ABOVE_SLIDE) == 0 then + if m.action == ACT_FORWARD_ROLLOUT and m.prevAction == ACT_DIVE_SLIDE then + m.vel.y = 21.0 + return set_mario_action(m, ACT_DIVE, 1) + + end + end + +end + hook_event(HOOK_UPDATE, update) hook_event(HOOK_MARIO_UPDATE, mario_update) hook_mario_action(ACT_ROLL, act_roll) diff --git a/src/game/mario.h b/src/game/mario.h index 964d51f09..5c9d0e3cd 100644 --- a/src/game/mario.h +++ b/src/game/mario.h @@ -41,7 +41,7 @@ f32 find_floor_height_relative_polar(struct MarioState *m, s16 angleFromMario, f s16 find_floor_slope(struct MarioState *m, s16 yawOffset); void update_mario_sound_and_camera(struct MarioState *m); void set_steep_jump_action(struct MarioState *m); -u32 set_mario_action(struct MarioState *, u32 action, u32 actionArg); +u32 set_mario_action(struct MarioState *m, u32 action, u32 actionArg); s32 set_jump_from_landing(struct MarioState *m); s32 set_jumping_action(struct MarioState *m, u32 action, u32 actionArg); s32 drop_and_set_mario_action(struct MarioState *m, u32 action, u32 actionArg); diff --git a/src/pc/lua/smlua.c b/src/pc/lua/smlua.c index 96e3239cb..c561d3baa 100644 --- a/src/pc/lua/smlua.c +++ b/src/pc/lua/smlua.c @@ -120,8 +120,6 @@ bool smlua_call_action_hook(struct MarioState* m, s32* returnValue) { *returnValue = lua_tointeger(L, -1); lua_pop(L, 1); - printf(">> action hook return: %d\n", *returnValue); - fflush(stdout); return true; } } @@ -157,7 +155,18 @@ static void smlua_init_mario_states(void) { void smlua_init(void) { gLuaState = luaL_newstate(); lua_State* L = gLuaState; - luaL_openlibs(L); + + // load libraries + luaopen_base(L); + //luaopen_coroutine(L); + //luaopen_debug(L); + //luaopen_io(L); + luaL_requiref(L, "math", luaopen_math, 1); + //luaopen_os(L); + //luaopen_package(L); + luaL_requiref(L, "string", luaopen_string, 1); + luaL_requiref(L, "table", luaopen_table, 1); + //luaopen_utf8(L); lua_pushcfunction(L, smlua_hook_event); lua_setglobal(L, "hook_event"); diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index 5fc5b2475..3788185a8 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -6,64 +6,479 @@ #include "audio/external.h" #include "object_fields.h" -int smlua_set_mario_action(lua_State* L) { - u32 action = lua_tointeger(L, -2); - u32 actionArg = lua_tointeger(L, -1); +/////////////////////////////////////// - lua_getfield(L, -3, "playerIndex"); - int index = lua_tointeger(L, -1); - lua_pushinteger(L, set_mario_action(&gMarioStates[index], action, actionArg)); + + ///////////// + // mario.h // +///////////// + +int smlua_func_is_anim_at_end(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, is_anim_at_end(m)); return 1; } -int smlua_set_jumping_action(lua_State* L) { - u32 action = lua_tointeger(L, -2); - u32 actionArg = lua_tointeger(L, -1); +int smlua_func_is_anim_past_end(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } - lua_getfield(L, -3, "playerIndex"); - int index = lua_tointeger(L, -1); - - lua_pushinteger(L, set_jumping_action(&gMarioStates[index], action, actionArg)); + lua_pushinteger(L, is_anim_past_end(m)); return 1; } -int smlua_play_mario_sound(lua_State* L) { - s32 actionSound = lua_tointeger(L, -2); - s32 marioSound = lua_tointeger(L, -1); +int smlua_func_set_mario_animation(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s32 targetAnimID = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } - lua_getfield(L, -3, "playerIndex"); - int index = lua_tointeger(L, -1); - - play_mario_sound(&gMarioStates[index], actionSound, marioSound); + lua_pushinteger(L, set_mario_animation(m, targetAnimID)); return 1; } -int smlua_mario_set_forward_vel(lua_State* L) { - f32 forwardVel = lua_tonumber(L, -1); +int smlua_func_set_mario_anim_with_accel(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s32 targetAnimID = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + s32 accel = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } - lua_getfield(L, -2, "playerIndex"); - int index = lua_tointeger(L, -1); - - mario_set_forward_vel(&gMarioStates[index], forwardVel); + lua_pushinteger(L, set_mario_anim_with_accel(m, targetAnimID, accel)); return 1; } -int smlua_play_sound(lua_State* L) { - s32 soundsBits = lua_tointeger(L, -4); - f32 pos[3] = { lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1) }; - extern void play_sound(s32 soundBits, f32 * pos); - play_sound(soundsBits, pos); +int smlua_func_set_anim_to_frame(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s16 animFrame = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + set_anim_to_frame(m, animFrame); return 1; } -int smlua_set_mario_animation(lua_State* L) { - s32 targetAnimID = lua_tointeger(L, -1); +int smlua_func_is_anim_past_frame(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s16 animFrame = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } - lua_getfield(L, -2, "playerIndex"); - int index = lua_tointeger(L, -1); + lua_pushinteger(L, is_anim_past_frame(m, animFrame)); + return 1; +} - lua_pushinteger(L, set_mario_animation(&gMarioStates[index], targetAnimID)); +/* +int smlua_func_find_mario_anim_flags_and_translation(lua_State* L) { + struct Object* o <--- UNIMPLEMENTED + if (!gSmLuaConvertSuccess) { return 0; } + s32 yaw = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + Vec3s translation = (Vec3s)smlua_to_cobject(L, 3, LOT_VEC3S); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, find_mario_anim_flags_and_translation(o, yaw, translation)); + return 1; +} +*/ + +int smlua_func_update_mario_pos_for_anim(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + update_mario_pos_for_anim(m); + return 1; +} + +int smlua_func_return_mario_anim_y_translation(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, return_mario_anim_y_translation(m)); + return 1; +} + +int smlua_func_play_sound_if_no_flag(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 flags = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + play_sound_if_no_flag(m, soundBits, flags); + return 1; +} + +int smlua_func_play_mario_jump_sound(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_jump_sound(m); + return 1; +} + +int smlua_func_adjust_sound_for_speed(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + adjust_sound_for_speed(m); + return 1; +} + +int smlua_func_play_sound_and_spawn_particles(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 waveParticleType = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + play_sound_and_spawn_particles(m, soundBits, waveParticleType); + return 1; +} + +int smlua_func_play_mario_action_sound(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 waveParticleType = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_action_sound(m, soundBits, waveParticleType); + return 1; +} + +int smlua_func_play_mario_landing_sound(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_landing_sound(m, soundBits); + return 1; +} + +int smlua_func_play_mario_landing_sound_once(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_landing_sound_once(m, soundBits); + return 1; +} + +int smlua_func_play_mario_heavy_landing_sound(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_heavy_landing_sound(m, soundBits); + return 1; +} + +int smlua_func_play_mario_heavy_landing_sound_once(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 soundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_heavy_landing_sound_once(m, soundBits); + return 1; +} + +int smlua_func_play_mario_sound(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s32 primarySoundBits = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + s32 scondarySoundBits = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + play_mario_sound(m, primarySoundBits, scondarySoundBits); + return 1; +} + +int smlua_func_mario_set_bubbled(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + mario_set_bubbled(m); + return 1; +} + +int smlua_func_mario_set_forward_vel(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + f32 speed = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + mario_set_forward_vel(m, speed); + return 1; +} + +int smlua_func_mario_get_floor_class(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, mario_get_floor_class(m)); + return 1; +} + +int smlua_func_mario_get_terrain_sound_addend(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, mario_get_terrain_sound_addend(m)); + return 1; +} + +/* +int smlua_func_resolve_and_return_wall_collisions(lua_State* L) { + Vec3f pos = (Vec3f)smlua_to_cobject(L, 1, LOT_VEC3F); + if (!gSmLuaConvertSuccess) { return 0; } + f32 offset = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + f32 radius = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + UNIMPLEMENTED -->(L, resolve_and_return_wall_collisions(pos, offset, radius)); + return 1; +} +*/ + +/* +int smlua_func_vec3f_find_ceil(lua_State* L) { + Vec3f pos = (Vec3f)smlua_to_cobject(L, 1, LOT_VEC3F); + if (!gSmLuaConvertSuccess) { return 0; } + f32 height = smlua_to_number(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + struct Surface** ceil <--- UNIMPLEMENTED + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushnumber(L, vec3f_find_ceil(pos, height, ceil)); + return 1; +} +*/ + +int smlua_func_mario_facing_downhill(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s32 turnYaw = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, mario_facing_downhill(m, turnYaw)); + return 1; +} + +int smlua_func_mario_floor_is_slippery(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, mario_floor_is_slippery(m)); + return 1; +} + +int smlua_func_mario_floor_is_slope(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, mario_floor_is_slope(m)); + return 1; +} + +int smlua_func_mario_floor_is_steep(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, mario_floor_is_steep(m)); + return 1; +} + +int smlua_func_find_floor_height_relative_polar(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s16 angleFromMario = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + f32 distFromMario = smlua_to_number(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushnumber(L, find_floor_height_relative_polar(m, angleFromMario, distFromMario)); + return 1; +} + +int smlua_func_find_floor_slope(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + s16 yawOffset = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, find_floor_slope(m, yawOffset)); + return 1; +} + +int smlua_func_update_mario_sound_and_camera(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + update_mario_sound_and_camera(m); + return 1; +} + +int smlua_func_set_steep_jump_action(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + set_steep_jump_action(m); + return 1; +} + +int smlua_func_set_mario_action(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 action = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 actionArg = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, set_mario_action(m, action, actionArg)); + return 1; +} + +int smlua_func_set_jump_from_landing(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, set_jump_from_landing(m)); + return 1; +} + +int smlua_func_set_jumping_action(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 action = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 actionArg = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, set_jumping_action(m, action, actionArg)); + return 1; +} + +int smlua_func_drop_and_set_mario_action(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 action = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 actionArg = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, drop_and_set_mario_action(m, action, actionArg)); + return 1; +} + +int smlua_func_hurt_and_set_mario_action(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + u32 action = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { return 0; } + u32 actionArg = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { return 0; } + s16 hurtCounter = smlua_to_integer(L, 4); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, hurt_and_set_mario_action(m, action, actionArg, hurtCounter)); + return 1; +} + +int smlua_func_check_common_action_exits(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, check_common_action_exits(m)); + return 1; +} + +int smlua_func_check_common_hold_action_exits(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, check_common_hold_action_exits(m)); + return 1; +} + +int smlua_func_transition_submerged_to_walking(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, transition_submerged_to_walking(m)); + return 1; +} + +int smlua_func_set_water_plunge_action(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, set_water_plunge_action(m)); + return 1; +} + +/* +int smlua_func_execute_mario_action(lua_State* L) { + struct Object* o <--- UNIMPLEMENTED + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, execute_mario_action(o)); + return 1; +} +*/ + +int smlua_func_force_idle_state(lua_State* L) { + struct MarioState* m = (struct MarioState*)smlua_to_cobject(L, 1, LOT_MARIO_STATE); + if (!gSmLuaConvertSuccess) { return 0; } + + lua_pushinteger(L, force_idle_state(m)); + return 1; +} + +int smlua_func_init_mario(UNUSED lua_State* L) { + init_mario(); + return 1; +} + +int smlua_func_init_mario_from_save_file(UNUSED lua_State* L) { + init_mario_from_save_file(); + return 1; +} + + +/////////////////////////////////////// + +int smlua_get_camera_position(lua_State* L) { + if (gMarioStates[0].marioObj == NULL) { + if (gCamera == NULL) { + lua_pushnumber(L, 0); + lua_pushnumber(L, 0); + lua_pushnumber(L, 0); + return 0; + } + lua_pushnumber(L, gCamera->pos[0]); + lua_pushnumber(L, gCamera->pos[1]); + lua_pushnumber(L, gCamera->pos[2]); + return 0; + } + + f32* pos = &gMarioStates[0].marioObj->header.gfx.cameraToObject[0]; + lua_pushnumber(L, pos[0]); + lua_pushnumber(L, pos[1]); + lua_pushnumber(L, pos[2]); return 1; } @@ -91,16 +506,6 @@ int smlua_common_slide_action(lua_State* L) { return 1; } -int smlua_set_anim_to_frame(lua_State* L) { - s16 animFrame = lua_tonumber(L, -1); - - lua_getfield(L, -2, "playerIndex"); - int index = lua_tointeger(L, -1); - - set_anim_to_frame(&gMarioStates[index], animFrame); - return 1; -} - int smlua_update_sliding_angle(lua_State* L) { f32 accel = lua_tonumber(L, -2); f32 lossFactor = lua_tonumber(L, -1); @@ -113,14 +518,6 @@ int smlua_update_sliding_angle(lua_State* L) { return 1; } -int smlua_mario_floor_is_slope(lua_State* L) { - lua_getfield(L, -1, "playerIndex"); - int index = lua_tointeger(L, -1); - - lua_pushinteger(L, mario_floor_is_slope(&gMarioStates[index])); - return 1; -} - int smlua_perform_air_step(lua_State* L) { u32 stepArg = lua_tointeger(L, -1); @@ -154,102 +551,78 @@ int smlua_mario_bonk_reflection(lua_State* L) { return 1; } -int smlua_play_sound_and_spawn_particles(lua_State* L) { - u32 soundBits = lua_tointeger(L, -3); - u32 waveParticleType = lua_tointeger(L, -2); - - lua_getfield(L, -3, "playerIndex"); - int index = lua_tointeger(L, -1); - - extern void play_sound_and_spawn_particles(struct MarioState* m, u32 soundBits, u32 waveParticleType); - play_sound_and_spawn_particles(&gMarioStates[index], soundBits, waveParticleType); - return 1; -} - -int smlua_play_mario_landing_sound_once(lua_State* L) { - u32 soundBits = lua_tointeger(L, -1); - - lua_getfield(L, -2, "playerIndex"); - int index = lua_tointeger(L, -1); - - extern void play_mario_landing_sound_once(struct MarioState* m, u32 soundBits); - play_mario_landing_sound_once(&gMarioStates[index], soundBits); - return 1; -} - -int smlua_get_camera_position(lua_State* L) { - if (gMarioStates[0].marioObj == NULL) { - if (gCamera == NULL) { - lua_pushnumber(L, 0); - lua_pushnumber(L, 0); - lua_pushnumber(L, 0); - return 0; - } - lua_pushnumber(L, gCamera->pos[0]); - lua_pushnumber(L, gCamera->pos[1]); - lua_pushnumber(L, gCamera->pos[2]); - return 0; - } - - f32* pos = &gMarioStates[0].marioObj->header.gfx.cameraToObject[0]; - lua_pushnumber(L, pos[0]); - lua_pushnumber(L, pos[1]); - lua_pushnumber(L, pos[2]); +int smlua_play_sound(lua_State* L) { + s32 soundsBits = lua_tointeger(L, -4); + f32 pos[3] = { lua_tonumber(L, -3), lua_tonumber(L, -2), lua_tonumber(L, -1) }; + extern void play_sound(s32 soundBits, f32 * pos); + play_sound(soundsBits, pos); return 1; } void smlua_bind_functions(void) { lua_State* L = gLuaState; - lua_pushcfunction(L, smlua_set_mario_action); - lua_setglobal(L, "set_mario_action"); + ///////////// + // mario.h // + ///////////// - lua_pushcfunction(L, smlua_set_jumping_action); - lua_setglobal(L, "set_jumping_action"); + smlua_bind_function(L, "is_anim_at_end", smlua_func_is_anim_at_end); + smlua_bind_function(L, "is_anim_past_end", smlua_func_is_anim_past_end); + smlua_bind_function(L, "set_mario_animation", smlua_func_set_mario_animation); + smlua_bind_function(L, "set_mario_anim_with_accel", smlua_func_set_mario_anim_with_accel); + smlua_bind_function(L, "set_anim_to_frame", smlua_func_set_anim_to_frame); + smlua_bind_function(L, "is_anim_past_frame", smlua_func_is_anim_past_frame); + //smlua_bind_function(L, "find_mario_anim_flags_and_translation", smlua_func_find_mario_anim_flags_and_translation); <--- UNIMPLEMENTED + smlua_bind_function(L, "update_mario_pos_for_anim", smlua_func_update_mario_pos_for_anim); + smlua_bind_function(L, "return_mario_anim_y_translation", smlua_func_return_mario_anim_y_translation); + smlua_bind_function(L, "play_sound_if_no_flag", smlua_func_play_sound_if_no_flag); + smlua_bind_function(L, "play_mario_jump_sound", smlua_func_play_mario_jump_sound); + smlua_bind_function(L, "adjust_sound_for_speed", smlua_func_adjust_sound_for_speed); + smlua_bind_function(L, "play_sound_and_spawn_particles", smlua_func_play_sound_and_spawn_particles); + smlua_bind_function(L, "play_mario_action_sound", smlua_func_play_mario_action_sound); + smlua_bind_function(L, "play_mario_landing_sound", smlua_func_play_mario_landing_sound); + smlua_bind_function(L, "play_mario_landing_sound_once", smlua_func_play_mario_landing_sound_once); + smlua_bind_function(L, "play_mario_heavy_landing_sound", smlua_func_play_mario_heavy_landing_sound); + smlua_bind_function(L, "play_mario_heavy_landing_sound_once", smlua_func_play_mario_heavy_landing_sound_once); + smlua_bind_function(L, "play_mario_sound", smlua_func_play_mario_sound); + smlua_bind_function(L, "mario_set_bubbled", smlua_func_mario_set_bubbled); + smlua_bind_function(L, "mario_set_forward_vel", smlua_func_mario_set_forward_vel); + smlua_bind_function(L, "mario_get_floor_class", smlua_func_mario_get_floor_class); + smlua_bind_function(L, "mario_get_terrain_sound_addend", smlua_func_mario_get_terrain_sound_addend); + //smlua_bind_function(L, "resolve_and_return_wall_collisions", smlua_func_resolve_and_return_wall_collisions); <--- UNIMPLEMENTED + //smlua_bind_function(L, "vec3f_find_ceil", smlua_func_vec3f_find_ceil); <--- UNIMPLEMENTED + smlua_bind_function(L, "mario_facing_downhill", smlua_func_mario_facing_downhill); + smlua_bind_function(L, "mario_floor_is_slippery", smlua_func_mario_floor_is_slippery); + smlua_bind_function(L, "mario_floor_is_slope", smlua_func_mario_floor_is_slope); + smlua_bind_function(L, "mario_floor_is_steep", smlua_func_mario_floor_is_steep); + smlua_bind_function(L, "find_floor_height_relative_polar", smlua_func_find_floor_height_relative_polar); + smlua_bind_function(L, "find_floor_slope", smlua_func_find_floor_slope); + smlua_bind_function(L, "update_mario_sound_and_camera", smlua_func_update_mario_sound_and_camera); + smlua_bind_function(L, "set_steep_jump_action", smlua_func_set_steep_jump_action); + smlua_bind_function(L, "set_mario_action", smlua_func_set_mario_action); + smlua_bind_function(L, "set_jump_from_landing", smlua_func_set_jump_from_landing); + smlua_bind_function(L, "set_jumping_action", smlua_func_set_jumping_action); + smlua_bind_function(L, "drop_and_set_mario_action", smlua_func_drop_and_set_mario_action); + smlua_bind_function(L, "hurt_and_set_mario_action", smlua_func_hurt_and_set_mario_action); + smlua_bind_function(L, "check_common_action_exits", smlua_func_check_common_action_exits); + smlua_bind_function(L, "check_common_hold_action_exits", smlua_func_check_common_hold_action_exits); + smlua_bind_function(L, "transition_submerged_to_walking", smlua_func_transition_submerged_to_walking); + smlua_bind_function(L, "set_water_plunge_action", smlua_func_set_water_plunge_action); + //smlua_bind_function(L, "execute_mario_action", smlua_func_execute_mario_action); <--- UNIMPLEMENTED + smlua_bind_function(L, "force_idle_state", smlua_func_force_idle_state); + smlua_bind_function(L, "init_mario", smlua_func_init_mario); + smlua_bind_function(L, "init_mario_from_save_file", smlua_func_init_mario_from_save_file); - lua_pushcfunction(L, smlua_play_mario_sound); - lua_setglobal(L, "play_mario_sound"); - - lua_pushcfunction(L, smlua_mario_set_forward_vel); - lua_setglobal(L, "mario_set_forward_vel"); - - lua_pushcfunction(L, smlua_play_sound); - lua_setglobal(L, "play_sound"); - - lua_pushcfunction(L, smlua_set_mario_animation); - lua_setglobal(L, "set_mario_animation"); - - lua_pushcfunction(L, smlua_update_sliding); - lua_setglobal(L, "update_sliding"); - - lua_pushcfunction(L, smlua_common_slide_action); - lua_setglobal(L, "common_slide_action"); - - lua_pushcfunction(L, smlua_set_anim_to_frame); - lua_setglobal(L, "set_anim_to_frame"); - - lua_pushcfunction(L, smlua_update_sliding_angle); - lua_setglobal(L, "update_sliding_angle"); - - lua_pushcfunction(L, smlua_mario_floor_is_slope); - lua_setglobal(L, "mario_floor_is_slope"); - - lua_pushcfunction(L, smlua_perform_air_step); - lua_setglobal(L, "perform_air_step"); - - lua_pushcfunction(L, smlua_check_fall_damage_or_get_stuck); - lua_setglobal(L, "check_fall_damage_or_get_stuck"); - - lua_pushcfunction(L, smlua_mario_bonk_reflection); - lua_setglobal(L, "mario_bonk_reflection"); - - lua_pushcfunction(L, smlua_play_sound_and_spawn_particles); - lua_setglobal(L, "play_sound_and_spawn_particles"); - - lua_pushcfunction(L, smlua_play_mario_landing_sound_once); - lua_setglobal(L, "play_mario_landing_sound_once"); - - lua_pushcfunction(L, smlua_get_camera_position); - lua_setglobal(L, "get_camera_position"); + ////////// + // misc // + ////////// + smlua_bind_function(L, "get_camera_position", smlua_get_camera_position); + smlua_bind_function(L, "update_sliding", smlua_update_sliding); + smlua_bind_function(L, "common_slide_action", smlua_common_slide_action); + smlua_bind_function(L, "update_sliding_angle", smlua_update_sliding_angle); + smlua_bind_function(L, "perform_air_step", smlua_perform_air_step); + smlua_bind_function(L, "check_fall_damage_or_get_stuck", smlua_check_fall_damage_or_get_stuck); + smlua_bind_function(L, "mario_bonk_reflection", smlua_mario_bonk_reflection); + smlua_bind_function(L, "play_sound", smlua_play_sound); } \ No newline at end of file diff --git a/src/pc/lua/smlua_utils.c b/src/pc/lua/smlua_utils.c index 486a4c9b1..dca33b4a1 100644 --- a/src/pc/lua/smlua_utils.c +++ b/src/pc/lua/smlua_utils.c @@ -1,58 +1,70 @@ #include "smlua.h" -void smlua_dump_stack(void) { - lua_State* L = gLuaState; - int top = lua_gettop(L); - printf("--------------\n"); - for (int i = 1; i <= top; i++) { - printf("%d\t%s\t", i, luaL_typename(L, i)); - switch (lua_type(L, i)) { - case LUA_TNUMBER: - printf("%g\n", lua_tonumber(L, i)); - break; - case LUA_TSTRING: - printf("%s\n", lua_tostring(L, i)); - break; - case LUA_TBOOLEAN: - printf("%s\n", (lua_toboolean(L, i) ? "true" : "false")); - break; - case LUA_TNIL: - printf("%s\n", "nil"); - break; - default: - printf("%p\n", lua_topointer(L, i)); - break; - } - } - printf("--------------\n"); +u8 gSmLuaConvertSuccess = false; + +void smlua_bind_function(lua_State* L, const char* name, void* func) { + lua_pushcfunction(L, func); + lua_setglobal(L, name); } -void smlua_dump_globals(void) { - lua_State* L = gLuaState; - printf("--------------\n"); - lua_pushglobaltable(L); +////////////////////////////////////////////// - // table is in the stack at index 't' - lua_pushnil(L); // first key - while (lua_next(L, -2) != 0) { - // uses 'key' (at index -2) and 'value' (at index -1) - if (lua_type(L, -2) == LUA_TSTRING) { - printf("%s - %s\n", - lua_tostring(L, -2), - lua_typename(L, lua_type(L, -1))); - } else { - printf("%s - %s\n", - lua_typename(L, lua_type(L, -2)), - lua_typename(L, lua_type(L, -1))); - } - // removes 'value'; keeps 'key' for next iteration - lua_pop(L, 1); +lua_Integer smlua_to_integer(lua_State* L, int index) { + if (lua_type(L, index) != LUA_TNUMBER) { + LOG_LUA("LUA: smlua_to_integer received improper type '%d'", lua_type(L, index)); + gSmLuaConvertSuccess = false; + return 0; } - lua_pop(L, 1); // remove global table(-1) - printf("--------------\n"); + gSmLuaConvertSuccess = true; + lua_Integer val = lua_tointeger(L, index); + return (val == 0) ? lua_tonumber(L, index) : val; } -// --- // +lua_Number smlua_to_number(lua_State* L, int index) { + if (lua_type(L, index) != LUA_TNUMBER) { + LOG_LUA("LUA: smlua_to_number received improper type '%d'", lua_type(L, index)); + gSmLuaConvertSuccess = false; + return 0; + } + gSmLuaConvertSuccess = true; + return lua_tonumber(L, index); +} + +void* smlua_to_cobject(lua_State* L, int index, enum LuaObjectType lot) { + if (lua_type(L, index) != LUA_TTABLE) { + LOG_LUA("LUA: smlua_to_cobject received improper type '%d'", lua_type(L, index)); + gSmLuaConvertSuccess = false; + return 0; + } + + lua_getfield(L, index, "_lot"); + enum LuaObjectType objLot = smlua_to_integer(L, -1); + lua_pop(L, 1); + if (!gSmLuaConvertSuccess) { return NULL; } + + if (lot != objLot) { + LOG_LUA("LUA: smlua_to_cobject received improper LOT. Expected '%d', received '%d'", lot, objLot); + gSmLuaConvertSuccess = false; + return NULL; + } + + lua_getfield(L, index, "_pointer"); + void* pointer = (void*)smlua_to_integer(L, -1); + lua_pop(L, 1); + if (!gSmLuaConvertSuccess) { return NULL; } + // TODO: check address whitelists + + if (pointer == NULL) { + LOG_LUA("LUA: smlua_to_cobject received null pointer."); + gSmLuaConvertSuccess = false; + return NULL; + } + + gSmLuaConvertSuccess = true; + return pointer; +} + +////////////////////////////////////////////// void smlua_push_object(lua_State* L, enum LuaObjectType lot, void* p) { lua_newtable(L); @@ -76,7 +88,7 @@ void smlua_push_number_field(float val, char* name) { lua_setfield(gLuaState, t, name); } -// --- // +////////////////////////////////////////////// void smlua_get_u8_field(u8* val, char* name) { lua_getfield(gLuaState, -1, name); @@ -147,3 +159,58 @@ void smlua_get_number_field(float* val, char* name) { *val = lua_tonumber(gLuaState, -1); lua_pop(gLuaState, 1); } + +////////////////////////////////////////////// + +void smlua_dump_stack(void) { + lua_State* L = gLuaState; + int top = lua_gettop(L); + printf("--------------\n"); + for (int i = 1; i <= top; i++) { + printf("%d\t%s\t", i, luaL_typename(L, i)); + switch (lua_type(L, i)) { + case LUA_TNUMBER: + printf("%g\n", lua_tonumber(L, i)); + break; + case LUA_TSTRING: + printf("%s\n", lua_tostring(L, i)); + break; + case LUA_TBOOLEAN: + printf("%s\n", (lua_toboolean(L, i) ? "true" : "false")); + break; + case LUA_TNIL: + printf("%s\n", "nil"); + break; + default: + printf("%p\n", lua_topointer(L, i)); + break; + } + } + printf("--------------\n"); +} + +void smlua_dump_globals(void) { + lua_State* L = gLuaState; + printf("--------------\n"); + lua_pushglobaltable(L); + + // table is in the stack at index 't' + lua_pushnil(L); // first key + while (lua_next(L, -2) != 0) { + // uses 'key' (at index -2) and 'value' (at index -1) + if (lua_type(L, -2) == LUA_TSTRING) { + printf("%s - %s\n", + lua_tostring(L, -2), + lua_typename(L, lua_type(L, -1))); + } + else { + printf("%s - %s\n", + lua_typename(L, lua_type(L, -2)), + lua_typename(L, lua_type(L, -1))); + } + // removes 'value'; keeps 'key' for next iteration + lua_pop(L, 1); + } + lua_pop(L, 1); // remove global table(-1) + printf("--------------\n"); +} \ No newline at end of file diff --git a/src/pc/lua/smlua_utils.h b/src/pc/lua/smlua_utils.h index 30158f272..9cb2ecb2c 100644 --- a/src/pc/lua/smlua_utils.h +++ b/src/pc/lua/smlua_utils.h @@ -1,8 +1,13 @@ #ifndef SMLUA_UTILS_H #define SMLUA_UTILS_H -void smlua_dump_stack(void); -void smlua_dump_globals(void); +extern u8 gSmLuaConvertSuccess; + +void smlua_bind_function(lua_State* L, const char* name, void* func); + +lua_Integer smlua_to_integer(lua_State* L, int index); +lua_Number smlua_to_number(lua_State* L, int index); +void* smlua_to_cobject(lua_State* L, int index, enum LuaObjectType lot); void smlua_push_object(lua_State* L, enum LuaObjectType lot, void* p); void smlua_push_integer_field(lua_Integer val, char* name); @@ -16,4 +21,7 @@ void smlua_get_s16_field(s16* val, char* name); void smlua_get_s32_field(s32* val, char* name); void smlua_get_number_field(float* val, char* name); +void smlua_dump_stack(void); +void smlua_dump_globals(void); + #endif \ No newline at end of file