mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2024-11-25 13:35:12 +00:00
c428612a9e
* Properly set Mario's y vel to 0 on popping * Change 0 to 0.0f, just in case * Re-introduce a few vanilla bugs under gBehaviorValues The Shell Mario glitch was patched as a side effect to patching a different bug, but several romhacks use it so I need it back. The ability to collect multiple normal caps at once is needed for hat-in-hand using the hat factory glitch. * Fix Shell Mario fix Found the actual reason why the glitch doesn't work and figured that this change shouldn't affect anything else, so I removed its entry from gBehaviorValues. * Add InfiniteRenderDistance to gBehaviorValues I'm well aware that disabling the infinite render distance will be very desync prone, however a few glitches, most notably cloning and chuckya double jump, need objects load and unload from render distance. * Allow mods to disable the camera centering from romhack camera * Allow mods to disable romhack camera centering Done again * Update on network shutdown * Remove a line which I have no idea why it returned * Add set_exclamation_box_contents() No way this is memory safe or even well made but I did what I could * Added (most of) peachy's suggestions Still need to figure out how to stop the game from reading further than the size of the array without using a hardcoded number * Added more of peachy's suggestions I figured a good way to cap how far the exclamation box reads is to pass in the length of the array as well
1112 lines
36 KiB
Python
1112 lines
36 KiB
Python
import os
|
|
import re
|
|
from extract_functions import *
|
|
from common import *
|
|
|
|
rejects = ""
|
|
integer_types = ["u8", "u16", "u32", "u64", "s8", "s16", "s32", "s64", "int"]
|
|
number_types = ["f32", "float", "f64", "double"]
|
|
param_override_build = {}
|
|
out_filename = 'src/pc/lua/smlua_functions_autogen.c'
|
|
out_filename_docs = 'docs/lua/functions%s.md'
|
|
out_filename_defs = 'autogen/lua_definitions/functions.lua'
|
|
|
|
in_files = [
|
|
"src/audio/external.h",
|
|
"src/engine/math_util.h",
|
|
"src/engine/surface_collision.h",
|
|
"src/engine/surface_load.h",
|
|
"src/game/camera.h",
|
|
"src/game/characters.h",
|
|
"src/game/mario_actions_airborne.c",
|
|
"src/game/mario_actions_automatic.c",
|
|
"src/game/mario_actions_cutscene.c",
|
|
"src/game/mario_actions_moving.c",
|
|
"src/game/mario_actions_object.c",
|
|
"src/game/mario_actions_stationary.c",
|
|
"src/game/mario_actions_submerged.c",
|
|
"src/game/mario_step.h",
|
|
"src/game/mario.h",
|
|
"src/game/rumble_init.c",
|
|
"src/pc/djui/djui_popup.h",
|
|
"src/pc/network/network_utils.h",
|
|
"src/pc/djui/djui_chat_message.h",
|
|
"src/game/interaction.h",
|
|
"src/game/level_info.h",
|
|
"src/game/save_file.h",
|
|
"src/game/sound_init.h",
|
|
"src/pc/djui/djui_hud_utils.h",
|
|
"src/pc/network/network_player.h",
|
|
"src/pc/network/lag_compensation.h",
|
|
"include/behavior_table.h",
|
|
"src/pc/lua/utils/smlua_obj_utils.h",
|
|
"src/pc/lua/utils/smlua_misc_utils.h",
|
|
"src/pc/lua/utils/smlua_collision_utils.h",
|
|
"src/pc/lua/utils/smlua_math_utils.h",
|
|
"src/pc/lua/utils/smlua_model_utils.h",
|
|
"src/pc/lua/utils/smlua_text_utils.h",
|
|
"src/pc/lua/utils/smlua_audio_utils.h",
|
|
"src/pc/lua/utils/smlua_level_utils.h",
|
|
"src/pc/lua/utils/smlua_anim_utils.h",
|
|
"src/pc/lua/utils/smlua_deprecated.h",
|
|
"src/game/object_helpers.c",
|
|
"src/game/obj_behaviors.c",
|
|
"src/game/obj_behaviors_2.c",
|
|
"src/game/spawn_sound.c",
|
|
"src/game/object_list_processor.h",
|
|
"src/game/behavior_actions.h",
|
|
"src/game/mario_misc.h",
|
|
"src/pc/mods/mod_storage.c.h",
|
|
"src/pc/utils/misc.h",
|
|
"src/game/level_update.h",
|
|
"src/game/area.h",
|
|
"src/engine/level_script.h",
|
|
"src/game/ingame_menu.h"
|
|
]
|
|
|
|
override_allowed_functions = {
|
|
"src/audio/external.h": [ " play_", "fade", "current_background", "stop_", "sound_banks", "drop_queued_background_music" ],
|
|
"src/game/rumble_init.c": [ "queue_rumble_", "reset_rumble_timers" ],
|
|
"src/pc/djui/djui_popup.h" : [ "create" ],
|
|
"src/game/save_file.h": [ "save_file_get_", "save_file_set_flags", "save_file_clear_flags", "save_file_reload", "save_file_erase_current_backup_save", "save_file_set_star_flags", "save_file_is_cannon_unlocked", "touch_coin_score_age", "save_file_set_course_coin_score", "save_file_do_save" ],
|
|
"src/pc/lua/utils/smlua_model_utils.h": [ "smlua_model_util_get_id" ],
|
|
"src/game/object_list_processor.h": [ "set_object_respawn_info_bits" ],
|
|
"src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*" ],
|
|
"src/pc/utils/misc.h": [ "update_all_mario_stars" ],
|
|
"src/game/level_update.h": [ "level_trigger_warp", "get_painting_warp_node", "initiate_painting_warp" ],
|
|
"src/game/area.h": [ "area_get_warp_node" ],
|
|
"src/engine/level_script.h": [ "area_create_warp_node" ],
|
|
"src/game/ingame_menu.h": [ "set_min_dialog_width", "set_dialog_override_pos", "reset_dialog_override_pos", "set_dialog_override_color", "reset_dialog_override_color" ]
|
|
}
|
|
|
|
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_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_.*" ],
|
|
"src/game/mario_actions_cutscene.c": [ "^[us]32 act_.*", " geo_", "spawn_obj" ],
|
|
"src/game/mario_actions_moving.c": [ "^[us]32 act_.*" ],
|
|
"src/game/mario_actions_object.c": [ "^[us]32 act_.*" ],
|
|
"src/game/mario_actions_stationary.c": [ "^[us]32 act_.*" ],
|
|
"src/game/mario_actions_submerged.c": [ "^[us]32 act_.*" ],
|
|
"src/game/mario_step.h": [ " stub_mario_step", "transfer_bully_speed"],
|
|
"src/game/mario.h": [ " init_mario" ],
|
|
"src/pc/djui/djui_chat_message.h": [ "create_from" ],
|
|
"src/game/interaction.h": [ "process_interactions", "_handle_" ],
|
|
"src/game/sound_init.h": [ "_loop_", "thread4_", "set_sound_mode" ],
|
|
"src/pc/network/network_utils.h": [ "network_get_player_text_color[^_]" ],
|
|
"src/pc/network/network_player.h": [ "_init", "_connected[^_]", "_shutdown", "_disconnected", "_update", "construct_player_popup" ],
|
|
"src/game/object_helpers.c": [ "spawn_obj", "^bhv_", "abs[fi]", "^bit_shift", "_debug$", "^stub_", "_set_model" ],
|
|
"src/game/obj_behaviors.c": [ "debug_" ],
|
|
"src/game/obj_behaviors_2.c": [ "wiggler_jumped_on_attack_handler", "huge_goomba_weakly_attacked" ],
|
|
"src/game/spawn_sound.c": [ "spawner" ],
|
|
"src/pc/lua/utils/smlua_obj_utils.h": [ "spawn_object_remember_field", "set_exclamation_box_new_contents", "get_exclamation_box_new_contents_pointer", "get_exclamation_box_new_contents_size" ],
|
|
"src/game/camera.h": [ "update_camera", "init_camera", "stub_camera", "^reset_camera", "move_point_along_spline" ],
|
|
"src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room" ],
|
|
"src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override", "audio_custom_shutdown"],
|
|
"src/pc/djui/djui_hud_utils.h": [ "djui_hud_render_texture", "djui_hud_render_texture_raw", "djui_hud_render_texture_tile", "djui_hud_render_texture_tile_raw" ],
|
|
"src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ],
|
|
"src/pc/lua/utils/smlua_anim_utils.h": [ "smlua_anim_util_reset", "smlua_anim_util_register_animation" ],
|
|
"src/pc/network/lag_compensation.h": [ "lag_compensation_clear", "lag_compensation_store" ]
|
|
}
|
|
|
|
override_hide_functions = {
|
|
"smlua_deprecated.h" : [ ".*" ],
|
|
}
|
|
|
|
override_function_version_excludes = {
|
|
"bhv_play_music_track_when_touched_loop": "VERSION_JP",
|
|
"play_knockback_sound": "VERSION_JP",
|
|
"cur_obj_spawn_star_at_y_offset": "VERSION_JP"
|
|
}
|
|
|
|
lua_function_params = {
|
|
"src/pc/lua/utils/smlua_obj_utils.h::spawn_object_sync::objSetupFunction": [ "struct Object*" ]
|
|
}
|
|
|
|
###########################################################
|
|
|
|
template = """/* THIS FILE IS AUTOGENERATED */
|
|
/* SHOULD NOT BE MANUALLY CHANGED */
|
|
|
|
#include "smlua.h"
|
|
|
|
$[INCLUDES]
|
|
|
|
$[FUNCTIONS]
|
|
|
|
void smlua_bind_functions_autogen(void) {
|
|
lua_State* L = gLuaState;
|
|
$[BINDS]
|
|
}
|
|
"""
|
|
|
|
###########################################################
|
|
|
|
param_vec3f_before_call = """
|
|
f32* $[IDENTIFIER] = smlua_get_vec3f_from_buffer();
|
|
$[IDENTIFIER][0] = smlua_get_number_field($[INDEX], "x");
|
|
$[IDENTIFIER][1] = smlua_get_number_field($[INDEX], "y");
|
|
$[IDENTIFIER][2] = smlua_get_number_field($[INDEX], "z");
|
|
"""
|
|
|
|
param_vec3f_after_call = """
|
|
smlua_push_number_field($[INDEX], "x", $[IDENTIFIER][0]);
|
|
smlua_push_number_field($[INDEX], "y", $[IDENTIFIER][1]);
|
|
smlua_push_number_field($[INDEX], "z", $[IDENTIFIER][2]);
|
|
"""
|
|
|
|
param_override_build['Vec3f'] = {
|
|
'before': param_vec3f_before_call,
|
|
'after': param_vec3f_after_call
|
|
}
|
|
|
|
param_vec3s_before_call = """
|
|
s16* $[IDENTIFIER] = smlua_get_vec3s_from_buffer();
|
|
$[IDENTIFIER][0] = smlua_get_integer_field($[INDEX], "x");
|
|
$[IDENTIFIER][1] = smlua_get_integer_field($[INDEX], "y");
|
|
$[IDENTIFIER][2] = smlua_get_integer_field($[INDEX], "z");
|
|
"""
|
|
|
|
param_vec3s_after_call = """
|
|
smlua_push_integer_field($[INDEX], "x", $[IDENTIFIER][0]);
|
|
smlua_push_integer_field($[INDEX], "y", $[IDENTIFIER][1]);
|
|
smlua_push_integer_field($[INDEX], "z", $[IDENTIFIER][2]);
|
|
"""
|
|
|
|
param_override_build['Vec3s'] = {
|
|
'before': param_vec3s_before_call,
|
|
'after': param_vec3s_after_call
|
|
}
|
|
|
|
param_vec4f_before_call = """
|
|
f32* $[IDENTIFIER] = smlua_get_vec4f_from_buffer();
|
|
$[IDENTIFIER][0] = smlua_get_number_field($[INDEX], "x");
|
|
$[IDENTIFIER][1] = smlua_get_number_field($[INDEX], "y");
|
|
$[IDENTIFIER][2] = smlua_get_number_field($[INDEX], "z");
|
|
$[IDENTIFIER][3] = smlua_get_number_field($[INDEX], "w");
|
|
"""
|
|
|
|
param_vec4f_after_call = """
|
|
smlua_push_number_field($[INDEX], "x", $[IDENTIFIER][0]);
|
|
smlua_push_number_field($[INDEX], "y", $[IDENTIFIER][1]);
|
|
smlua_push_number_field($[INDEX], "z", $[IDENTIFIER][2]);
|
|
smlua_push_number_field($[INDEX], "w", $[IDENTIFIER][3]);
|
|
"""
|
|
|
|
param_override_build['Vec4f'] = {
|
|
'before': param_vec4f_before_call,
|
|
'after': param_vec4f_after_call
|
|
}
|
|
|
|
param_vec4s_before_call = """
|
|
s16* $[IDENTIFIER] = smlua_get_vec4s_from_buffer();
|
|
$[IDENTIFIER][0] = smlua_get_integer_field($[INDEX], "x");
|
|
$[IDENTIFIER][1] = smlua_get_integer_field($[INDEX], "y");
|
|
$[IDENTIFIER][2] = smlua_get_integer_field($[INDEX], "z");
|
|
$[IDENTIFIER][3] = smlua_get_integer_field($[INDEX], "w");
|
|
"""
|
|
|
|
param_vec4s_after_call = """
|
|
smlua_push_integer_field($[INDEX], "x", $[IDENTIFIER][0]);
|
|
smlua_push_integer_field($[INDEX], "y", $[IDENTIFIER][1]);
|
|
smlua_push_integer_field($[INDEX], "z", $[IDENTIFIER][2]);
|
|
smlua_push_integer_field($[INDEX], "w", $[IDENTIFIER][3]);
|
|
"""
|
|
|
|
param_override_build['Vec4s'] = {
|
|
'before': param_vec4s_before_call,
|
|
'after': param_vec4s_after_call
|
|
}
|
|
|
|
param_mat4_before_call = """
|
|
Mat4 $[IDENTIFIER];
|
|
$[IDENTIFIER][0][0] = smlua_get_number_field($[INDEX], "a");
|
|
$[IDENTIFIER][0][1] = smlua_get_number_field($[INDEX], "b");
|
|
$[IDENTIFIER][0][2] = smlua_get_number_field($[INDEX], "c");
|
|
$[IDENTIFIER][0][3] = smlua_get_number_field($[INDEX], "d");
|
|
$[IDENTIFIER][1][0] = smlua_get_number_field($[INDEX], "e");
|
|
$[IDENTIFIER][1][1] = smlua_get_number_field($[INDEX], "f");
|
|
$[IDENTIFIER][1][2] = smlua_get_number_field($[INDEX], "g");
|
|
$[IDENTIFIER][1][3] = smlua_get_number_field($[INDEX], "h");
|
|
$[IDENTIFIER][2][0] = smlua_get_number_field($[INDEX], "i");
|
|
$[IDENTIFIER][2][1] = smlua_get_number_field($[INDEX], "j");
|
|
$[IDENTIFIER][2][2] = smlua_get_number_field($[INDEX], "k");
|
|
$[IDENTIFIER][2][3] = smlua_get_number_field($[INDEX], "l");
|
|
$[IDENTIFIER][3][0] = smlua_get_number_field($[INDEX], "m");
|
|
$[IDENTIFIER][3][1] = smlua_get_number_field($[INDEX], "n");
|
|
$[IDENTIFIER][3][2] = smlua_get_number_field($[INDEX], "o");
|
|
$[IDENTIFIER][3][3] = smlua_get_number_field($[INDEX], "p");
|
|
"""
|
|
|
|
param_mat4_after_call = """
|
|
smlua_push_number_field($[INDEX], "a", $[IDENTIFIER][0][0]);
|
|
smlua_push_number_field($[INDEX], "b", $[IDENTIFIER][0][1]);
|
|
smlua_push_number_field($[INDEX], "c", $[IDENTIFIER][0][2]);
|
|
smlua_push_number_field($[INDEX], "d", $[IDENTIFIER][0][3]);
|
|
smlua_push_number_field($[INDEX], "e", $[IDENTIFIER][1][0]);
|
|
smlua_push_number_field($[INDEX], "f", $[IDENTIFIER][1][1]);
|
|
smlua_push_number_field($[INDEX], "g", $[IDENTIFIER][1][2]);
|
|
smlua_push_number_field($[INDEX], "h", $[IDENTIFIER][1][3]);
|
|
smlua_push_number_field($[INDEX], "i", $[IDENTIFIER][2][0]);
|
|
smlua_push_number_field($[INDEX], "j", $[IDENTIFIER][2][1]);
|
|
smlua_push_number_field($[INDEX], "k", $[IDENTIFIER][2][2]);
|
|
smlua_push_number_field($[INDEX], "l", $[IDENTIFIER][2][3]);
|
|
smlua_push_number_field($[INDEX], "m", $[IDENTIFIER][3][0]);
|
|
smlua_push_number_field($[INDEX], "n", $[IDENTIFIER][3][1]);
|
|
smlua_push_number_field($[INDEX], "o", $[IDENTIFIER][3][2]);
|
|
smlua_push_number_field($[INDEX], "p", $[IDENTIFIER][3][3]);
|
|
"""
|
|
|
|
param_override_build['Mat4'] = {
|
|
'before': param_mat4_before_call,
|
|
'after': param_mat4_after_call
|
|
}
|
|
|
|
param_color_before_call = """
|
|
u8* $[IDENTIFIER] = smlua_get_color_from_buffer();
|
|
$[IDENTIFIER][0] = smlua_get_integer_field($[INDEX], "r");
|
|
$[IDENTIFIER][1] = smlua_get_integer_field($[INDEX], "g");
|
|
$[IDENTIFIER][2] = smlua_get_integer_field($[INDEX], "b");
|
|
"""
|
|
|
|
param_color_after_call = """
|
|
smlua_push_integer_field($[INDEX], "r", $[IDENTIFIER][0]);
|
|
smlua_push_integer_field($[INDEX], "g", $[IDENTIFIER][1]);
|
|
smlua_push_integer_field($[INDEX], "b", $[IDENTIFIER][2]);
|
|
"""
|
|
|
|
param_override_build['Color'] = {
|
|
'before': param_color_before_call,
|
|
'after': param_color_after_call
|
|
}
|
|
|
|
############################################################################
|
|
|
|
manual_index_documentation = """
|
|
- manually written functions
|
|
- [define_custom_obj_fields](#define_custom_obj_fields)
|
|
- [network_init_object](#network_init_object)
|
|
- [network_send_object](#network_send_object)
|
|
- [network_send_to](#network_send_to)
|
|
- [network_send](#network_send)
|
|
- [djui_hud_render_texture](#djui_hud_render_texture)
|
|
- [get_texture_info](#get_texture_info)
|
|
- [djui_hud_render_texture_interpolated](#djui_hud_render_texture_interpolated)
|
|
|
|
<br />
|
|
|
|
"""
|
|
manual_documentation = """
|
|
---
|
|
# manually written functions
|
|
|
|
<br />
|
|
|
|
## [define_custom_obj_fields](#define_custom_obj_fields)
|
|
|
|
Defines a custom set of overlapping object fields.
|
|
|
|
The `fieldTable` table's keys must start with the letter `o` and the values must be either `u32`, `s32`, or `f32`.
|
|
|
|
### Lua Example
|
|
`define_custom_obj_fields({ oCustomField1 = 'u32', oCustomField2 = 's32', oCustomField3 = 'f32' })`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| fieldTable | `Lua Table` |
|
|
|
|
### C Prototype
|
|
`N/A`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
## [network_init_object](#network_init_object)
|
|
|
|
Enables synchronization on an object.
|
|
|
|
- Setting `standardSync` to `true` will automatically synchronize the object at a rate that is determined based on player distance. The commonly used object fields will be automatically synchronized.
|
|
- Setting `standardSync` to `false` will not automatically synchronize the object, or add commonly used object fields. The mod must manually call `network_send_object()` when fields have changed.
|
|
|
|
The `fieldTable` parameter can be `nil`, or a list of object fields.
|
|
|
|
### Lua Example
|
|
`network_init_object(obj, true, { 'oCustomField1', 'oCustomField2', 'oCustomField3' })`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| object | [Object](structs.md#Object) |
|
|
| standardSync | `bool` |
|
|
| fieldTable | `Lua Table` |
|
|
|
|
### C Prototype
|
|
`N/A`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
## [network_send_object](#network_send_object)
|
|
|
|
Sends a packet that synchronizes an object. This does not need to be called when `standardSync` is enabled.
|
|
|
|
The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
|
|
|
|
### Lua Example
|
|
`network_send_object(obj, false)`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| object | [Object](structs.md#Object) |
|
|
| reliable | `bool` |
|
|
|
|
### C Prototype
|
|
`N/A`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
## [network_send_to](#network_send_to)
|
|
|
|
Sends a packet to a particular player (using their local index) containing whatever data you want.
|
|
|
|
`dataTable` can only contain strings, integers, numbers, booleans, and nil
|
|
|
|
The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
|
|
|
|
### Lua Example
|
|
`network_send_to(localPlayerIndex, reliable, { data1 = 'hello', data2 = 10})`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| localPlayerIndex | `integer` |
|
|
| reliable | `bool` |
|
|
| dataTable | `table` |
|
|
|
|
### C Prototype
|
|
`N/A`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
## [network_send](#network_send)
|
|
|
|
Sends a packet to all players containing whatever data you want.
|
|
|
|
`dataTable` can only contain strings, integers, numbers, booleans, and nil
|
|
|
|
The `reliable` field will ensure that the packet arrives, but should be used sparingly and only when missing a packet would cause a desync.
|
|
|
|
### Lua Example
|
|
`network_send(reliable, { data1 = 'hello', data2 = 10})`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| reliable | `bool` |
|
|
| dataTable | `table` |
|
|
|
|
### C Prototype
|
|
`N/A`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
## [djui_hud_render_texture](#djui_hud_render_texture)
|
|
|
|
Renders a texture to the screen.
|
|
|
|
### Lua Example
|
|
`djui_hud_render_texture(texInfo, x, y, scaleW, scaleH)`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| texInfo | [TextureInfo](structs.md#TextureInfo) |
|
|
| x | `number` |
|
|
| y | `number` |
|
|
| scaleW | `number` |
|
|
| scaleH | `number` |
|
|
|
|
### Returns
|
|
- None
|
|
|
|
### C Prototype
|
|
`void djui_hud_render_texture(struct TextureInfo* texInfo, f32 x, f32 y, f32 scaleW, f32 scaleH);`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
## [get_texture_info](#get_texture_info)
|
|
|
|
Retrieves a texture by name.
|
|
|
|
### Lua Example
|
|
`get_texture_info(textureName)`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| textureName | `string` |
|
|
|
|
### Returns
|
|
- [TextureInfo](structs.md#TextureInfo)
|
|
|
|
### C Prototype
|
|
`N/A`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
## [djui_hud_render_texture_interpolated](#djui_hud_render_texture_interpolated)
|
|
|
|
### Lua Example
|
|
`djui_hud_render_texture_interpolated(texInfo, prevX, prevY, prevScaleW, prevScaleH, x, y, scaleW, scaleH)`
|
|
|
|
### Parameters
|
|
| Field | Type |
|
|
| ----- | ---- |
|
|
| texInfo | [TextureInfo](structs.md#TextureInfo) |
|
|
| prevX | `number` |
|
|
| prevY | `number` |
|
|
| prevScaleW | `number` |
|
|
| prevScaleH | `number` |
|
|
| x | `number` |
|
|
| y | `number` |
|
|
| scaleW | `number` |
|
|
| scaleH | `number` |
|
|
|
|
### Returns
|
|
- None
|
|
|
|
### C Prototype
|
|
`void djui_hud_render_texture_interpolated(struct TextureInfo* texInfo, f32 prevX, f32 prevY, f32 prevScaleW, f32 prevScaleH, f32 x, f32 y, f32 scaleW, f32 scaleH);`
|
|
|
|
[:arrow_up_small:](#)
|
|
|
|
<br />
|
|
|
|
"""
|
|
|
|
############################################################################
|
|
|
|
total_functions = 0
|
|
header_h = ""
|
|
|
|
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):
|
|
if 'char' not in t:
|
|
t = t.replace('const', '')
|
|
|
|
t = t.strip()
|
|
if ' ' in t:
|
|
parts = t.split(' ', 1)
|
|
t = parts[0] + ' ' + parts[1].replace(' ', '')
|
|
return t
|
|
|
|
def alter_type(t):
|
|
if t.startswith('enum '):
|
|
return 'int'
|
|
return t
|
|
|
|
|
|
############################################################################
|
|
|
|
def build_param(param, i):
|
|
ptype = alter_type(param['type'])
|
|
pid = param['identifier']
|
|
|
|
if ptype in param_override_build:
|
|
return param_override_build[ptype]['before'].replace('$[IDENTIFIER]', str(pid)).replace('$[INDEX]', str(i))
|
|
elif ptype == 'bool':
|
|
return ' %s %s = smlua_to_boolean(L, %d);\n' % (ptype, pid, i)
|
|
elif 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 == 'const char*':
|
|
return ' %s %s = smlua_to_string(L, %d);\n' % (ptype, pid, i)
|
|
elif ptype == 'LuaFunction':
|
|
return ' %s %s = smlua_to_lua_function(L, %d);\n' % (ptype, pid, i)
|
|
elif translate_type_to_lot(ptype) == 'LOT_POINTER':
|
|
lvt = translate_type_to_lvt(ptype)
|
|
return ' %s %s = (%s)smlua_to_cpointer(L, %d, %s);\n' % (ptype, pid, ptype, i, lvt)
|
|
else:
|
|
lot = translate_type_to_lot(ptype)
|
|
s = ' %s %s = (%s)smlua_to_cobject(L, %d, %s);' % (ptype, pid, ptype, i, lot)
|
|
|
|
if '???' in lot:
|
|
s = '//' + s + ' <--- UNIMPLEMENTED'
|
|
else:
|
|
s = ' ' + s
|
|
|
|
return s + '\n'
|
|
|
|
def build_param_after(param, i):
|
|
ptype = param['type']
|
|
pid = param['identifier']
|
|
|
|
if ptype in param_override_build:
|
|
return param_override_build[ptype]['after'].replace('$[IDENTIFIER]', str(pid)).replace('$[INDEX]', str(i))
|
|
else:
|
|
return ''
|
|
|
|
def build_call(function):
|
|
ftype = alter_type(function['type'])
|
|
fid = function['identifier']
|
|
|
|
ccall = '%s(%s)' % (fid, ', '.join([x['identifier'] for x in function['params']]))
|
|
|
|
if ftype == 'void':
|
|
return ' %s;\n' % ccall
|
|
# We can't possibly know the type of a void pointer,
|
|
# So we just don't return anything from it
|
|
elif ftype == 'void *':
|
|
return ' %s;\n' % ccall
|
|
|
|
flot = translate_type_to_lot(ftype)
|
|
|
|
lfunc = 'UNIMPLEMENTED -->'
|
|
if ftype in integer_types:
|
|
lfunc = 'lua_pushinteger'
|
|
elif ftype in number_types:
|
|
lfunc = 'lua_pushnumber'
|
|
elif ftype == 'bool':
|
|
lfunc = 'lua_pushboolean'
|
|
elif ftype == 'char*':
|
|
lfunc = 'lua_pushstring'
|
|
elif ftype == 'const char*':
|
|
lfunc = 'lua_pushstring'
|
|
elif translate_type_to_lot(ftype) == 'LOT_POINTER':
|
|
lvt = translate_type_to_lvt(ftype)
|
|
return ' smlua_push_pointer(L, %s, (void*)%s);\n' % (lvt, ccall)
|
|
elif '???' not in flot and flot != 'LOT_NONE':
|
|
return ' smlua_push_object(L, %s, %s);\n' % (flot, ccall)
|
|
|
|
return ' %s(L, %s);\n' % (lfunc, ccall)
|
|
|
|
def build_function(function, do_extern):
|
|
s = ''
|
|
fid = function['identifier']
|
|
|
|
if fid in override_function_version_excludes:
|
|
s += '#ifndef ' + override_function_version_excludes[fid] + '\n'
|
|
|
|
if len(function['params']) <= 0:
|
|
s += 'int smlua_func_%s(UNUSED lua_State* L) {\n' % function['identifier']
|
|
else:
|
|
s += 'int smlua_func_%s(lua_State* L) {\n' % function['identifier']
|
|
|
|
# make sure the bhv functions have a current object
|
|
fname = function['filename']
|
|
if fname == 'behavior_actions.h' or fname == 'obj_behaviors_2.h' or fname == 'obj_behaviors.h':
|
|
if 'bhv_' in fid:
|
|
s += ' if (!gCurrentObject) { return 0; }\n'
|
|
|
|
s += """ if (L == NULL) { return 0; }\n
|
|
int top = lua_gettop(L);
|
|
if (top != %d) {
|
|
LOG_LUA_LINE("Improper param count for '%%s': Expected %%u, Received %%u", "%s", %d, top);
|
|
return 0;
|
|
}\n\n""" % (len(function['params']), function['identifier'], len(function['params']))
|
|
|
|
i = 1
|
|
for param in function['params']:
|
|
s += build_param(param, i)
|
|
s += ' if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %%u for function \'%%s\'", %d, "%s"); return 0; }\n' % (i, fid)
|
|
i += 1
|
|
s += '\n'
|
|
|
|
if do_extern:
|
|
s += ' extern %s\n' % function['line']
|
|
|
|
s += build_call(function)
|
|
|
|
i = 1
|
|
for param in function['params']:
|
|
s += build_param_after(param, i)
|
|
i += 1
|
|
s += '\n'
|
|
|
|
s += ' return 1;\n}\n'
|
|
|
|
if fid in override_function_version_excludes:
|
|
s += '#endif\n'
|
|
|
|
function['implemented'] = 'UNIMPLEMENTED' not in s
|
|
if 'UNIMPLEMENTED' in s:
|
|
s = "/*\n" + s + "*/\n"
|
|
else:
|
|
global total_functions
|
|
total_functions += 1
|
|
|
|
return s + "\n"
|
|
|
|
def build_functions(processed_files):
|
|
s = ''
|
|
for processed_file in processed_files:
|
|
s += gen_comment_header(processed_file['filename'])
|
|
|
|
for function in processed_file['functions']:
|
|
function['filename'] = processed_file['filename']
|
|
s += build_function(function, processed_file['extern'])
|
|
return s
|
|
|
|
def build_bind(function):
|
|
fid = function['identifier']
|
|
s = 'smlua_bind_function(L, "%s", smlua_func_%s);' % (fid, fid)
|
|
if function['implemented']:
|
|
s = ' ' + s
|
|
# There is no point in adding the ifndef statement if the function is commented out here anyways.
|
|
# So we only do it on implemented functions.
|
|
if fid in override_function_version_excludes:
|
|
s = '#ifndef ' + override_function_version_excludes[fid] + '\n' + s
|
|
s += '\n#endif'
|
|
else:
|
|
s = ' //' + s + ' <--- UNIMPLEMENTED'
|
|
return s + "\n"
|
|
|
|
def build_binds(processed_files):
|
|
s = ''
|
|
for processed_file in processed_files:
|
|
s += "\n // " + processed_file['filename'] + "\n"
|
|
|
|
for function in processed_file['functions']:
|
|
s += build_bind(function)
|
|
return s
|
|
|
|
def build_includes():
|
|
s = ''
|
|
for f in in_files:
|
|
if not f.endswith('.h'):
|
|
continue
|
|
s += '#include "%s"\n' % f
|
|
return s
|
|
|
|
############################################################################
|
|
|
|
def process_function(fname, line):
|
|
if fname in override_allowed_functions:
|
|
found_match = False
|
|
for pattern in override_allowed_functions[fname]:
|
|
if re.search(pattern, line) != None:
|
|
found_match = True
|
|
break
|
|
if not found_match:
|
|
return None
|
|
|
|
if fname in override_disallowed_functions:
|
|
for pattern in override_disallowed_functions[fname]:
|
|
if re.search(pattern, line) != None:
|
|
return None
|
|
|
|
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:
|
|
param_index = 0
|
|
for param_str in params_str.split(','):
|
|
param = {}
|
|
param_str = param_str.strip()
|
|
if param_str.endswith('*') or ' ' not in param_str:
|
|
param['type'] = normalize_type(param_str)
|
|
param['identifier'] = 'arg%d' % param_index
|
|
else:
|
|
match = re.search('[a-zA-Z0-9_\[\]]+$', param_str)
|
|
if match == None:
|
|
return None
|
|
param['type'] = normalize_type(param_str[0:match.span()[0]])
|
|
param['identifier'] = match.group()
|
|
|
|
# override Vec3s/f
|
|
if param['identifier'] == 'pos':
|
|
if param['type'].replace(' ', '') == 'f32*':
|
|
param['type'] = 'Vec3f'
|
|
if param['type'].replace(' ', '') == 's16*':
|
|
param['type'] = 'Vec3s'
|
|
|
|
# remember lua function params
|
|
lf_key = fname + '::' + function['identifier'] + '::' + param['identifier']
|
|
if param['type'] == 'LuaFunction' and lf_key in lua_function_params:
|
|
param['lua_function_params'] = lua_function_params[lf_key]
|
|
|
|
function['params'].append(param)
|
|
param_index += 1
|
|
|
|
return function
|
|
|
|
def process_functions(fname, file_str):
|
|
functions = []
|
|
for line in file_str.splitlines():
|
|
if reject_line(line):
|
|
global rejects
|
|
rejects += line + '\n'
|
|
continue
|
|
fn = process_function(fname, line)
|
|
if fn == None:
|
|
continue
|
|
functions.append(fn)
|
|
|
|
functions = sorted(functions, key=lambda d: d['identifier'])
|
|
return functions
|
|
|
|
def process_file(fname):
|
|
processed_file = {}
|
|
processed_file['filename'] = fname.replace('\\', '/').split('/')[-1]
|
|
processed_file['extern'] = fname.endswith('.c')
|
|
|
|
extracted_str = extract_functions(fname)
|
|
processed_file['functions'] = process_functions(fname, extracted_str)
|
|
|
|
return processed_file
|
|
|
|
def process_files():
|
|
processed_files = []
|
|
files = sorted(in_files, key=lambda d: d.split('/')[-1])
|
|
for f in files:
|
|
processed_files.append(process_file(f))
|
|
return processed_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):
|
|
first = True
|
|
comment = ' -- '
|
|
fid = function['identifier']
|
|
|
|
line = ' function() return ' + fid + '('
|
|
|
|
for param in function['params']:
|
|
if first:
|
|
first = False
|
|
else:
|
|
line += ', '
|
|
comment += ', '
|
|
pid = param['identifier']
|
|
ptype = param['type']
|
|
ptype, plink = translate_type_to_lua(ptype)
|
|
|
|
if '(' in pid or '[' in pid or ']' in pid:
|
|
continue
|
|
|
|
line += translate_type_to_rnd(ptype)
|
|
|
|
comment += ptype
|
|
|
|
line += ') end,\n'
|
|
#if len(line) >= 80:
|
|
# line = line + '\n ' + comment + '\n'
|
|
#else:
|
|
# line = line.ljust(80) + comment + '\n'
|
|
|
|
global fuzz_functions
|
|
fuzz_functions += line
|
|
|
|
def output_fuzz_file():
|
|
global fuzz_functions
|
|
with open(fuzz_from) as f:
|
|
file_str = f.read()
|
|
with open(fuzz_to, 'w') as f:
|
|
f.write(file_str.replace('-- $[FUNCS]', fuzz_functions))
|
|
|
|
############################################################################
|
|
|
|
def doc_should_document(fname, identifier):
|
|
if fname in override_hide_functions:
|
|
found_match = False
|
|
for pattern in override_hide_functions[fname]:
|
|
if re.search(pattern, identifier) != None:
|
|
found_match = True
|
|
break
|
|
return not found_match
|
|
return True
|
|
|
|
def doc_page_link(page_num):
|
|
if page_num == 1:
|
|
return 'functions.md'
|
|
else:
|
|
return 'functions-%d.md' % page_num
|
|
|
|
def doc_function_index(processed_files):
|
|
s = '# Supported Functions\n'
|
|
s += manual_index_documentation
|
|
count = 0
|
|
for processed_file in processed_files:
|
|
page_num = processed_file['page_num']
|
|
s += '- %s\n' % processed_file['filename']
|
|
for function in processed_file['functions']:
|
|
if not function['implemented']:
|
|
continue
|
|
if not doc_should_document(processed_file['filename'], function['identifier']):
|
|
continue
|
|
|
|
s += ' - [%s](%s#%s)\n' % (function['identifier'], doc_page_link(page_num), function['identifier'])
|
|
s += '\n<br />\n\n'
|
|
|
|
return s
|
|
|
|
def doc_lua_func_param(param):
|
|
s = 'LuaFunction('
|
|
|
|
lfp = param['lua_function_params']
|
|
first_lfp = True
|
|
|
|
for lfp_type in lfp:
|
|
if not first_lfp:
|
|
lfp_type += ', '
|
|
first_lfp = False
|
|
|
|
lfp_type, lfp_link = translate_type_to_lua(lfp_type)
|
|
|
|
if lfp_link:
|
|
s += '[%s](%s)' % (lfp_type, lfp_link)
|
|
else:
|
|
s += lfp_type
|
|
|
|
s += ')'
|
|
return s
|
|
|
|
def doc_function(fname, function):
|
|
if not function['implemented']:
|
|
return ''
|
|
|
|
# debug print out lua nuke functions
|
|
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
|
|
output_fuzz_function(fname, function)
|
|
|
|
if not doc_should_document(fname, function['identifier']):
|
|
return ''
|
|
|
|
fid = function['identifier']
|
|
s = '\n## [%s](#%s)\n' % (fid, fid)
|
|
|
|
rtype, rlink = translate_type_to_lua(function['type'])
|
|
param_str = ', '.join([x['identifier'] for x in function['params']])
|
|
|
|
s += "\n### Lua Example\n"
|
|
if rtype != None:
|
|
s += "`local %sValue = %s(%s)`\n" % (rtype.replace('`', '').split(' ')[0], fid, param_str)
|
|
else:
|
|
s += "`%s(%s)`\n" % (fid, param_str)
|
|
|
|
s += '\n### Parameters\n'
|
|
if len(function['params']) > 0:
|
|
s += '| Field | Type |\n'
|
|
s += '| ----- | ---- |\n'
|
|
for param in function['params']:
|
|
pid = param['identifier']
|
|
ptype = param['type']
|
|
ptype, plink = translate_type_to_lua(ptype)
|
|
|
|
# build lua function params
|
|
if param['type'] == 'LuaFunction' and 'lua_function_params' in param:
|
|
ptype = doc_lua_func_param(param)
|
|
|
|
if plink:
|
|
s += '| %s | [%s](%s) |\n' % (pid, ptype, plink)
|
|
continue
|
|
|
|
s += '| %s | %s |\n' % (pid, ptype)
|
|
|
|
else:
|
|
s += '- None\n'
|
|
|
|
s += '\n### Returns\n'
|
|
if rtype != None:
|
|
if rlink:
|
|
s += '[%s](%s)\n' % (rtype, rlink)
|
|
else:
|
|
s += '- %s\n' % rtype
|
|
else:
|
|
s += '- None\n'
|
|
|
|
|
|
s += '\n### C Prototype\n'
|
|
s += '`%s`\n' % function['line'].strip()
|
|
|
|
s += '\n[:arrow_up_small:](#)\n\n<br />\n'
|
|
|
|
return s
|
|
|
|
def doc_functions(fname, functions):
|
|
s = ''
|
|
for function in functions:
|
|
s += doc_function(fname, function)
|
|
return s
|
|
|
|
def doc_files(processed_files):
|
|
pages = {}
|
|
page_num = 1
|
|
page_len_limit = 150000
|
|
extra_space = 25000
|
|
|
|
s = '## [:rewind: Lua Reference](lua.md)\n\n'
|
|
s += '---\n\n$[FUNCTION_NAV_HERE]\n\n---\n\n'
|
|
s += '$[FUNCTION_INDEX_HERE]'
|
|
s += manual_documentation
|
|
for processed_file in processed_files:
|
|
s_file = '\n---'
|
|
s_file += '\n# functions from %s\n\n<br />\n\n' % processed_file['filename']
|
|
s_file += doc_functions(processed_file['filename'], processed_file['functions'])
|
|
|
|
if len(s) + len(s_file) + extra_space > page_len_limit:
|
|
s += '---\n\n$[FUNCTION_NAV_HERE]\n\n'
|
|
pages[page_num] = s
|
|
s = '## [:rewind: Lua Functions](functions.md)\n\n'
|
|
s += '---\n\n$[FUNCTION_NAV_HERE]\n\n'
|
|
page_num += 1
|
|
extra_space = 0
|
|
|
|
s += s_file
|
|
processed_file['page_num'] = page_num
|
|
|
|
s += '\n---\n\n$[FUNCTION_NAV_HERE]\n\n'
|
|
pages[page_num] = s
|
|
|
|
for pnum in pages:
|
|
buffer = pages[pnum]
|
|
page_name = ''
|
|
if pnum == 1:
|
|
buffer = buffer.replace('$[FUNCTION_INDEX_HERE]', doc_function_index(processed_files))
|
|
page_name = ''
|
|
else:
|
|
page_name = '-%d' % pnum
|
|
|
|
# build up nav
|
|
function_nav = ''
|
|
if (pnum - 1) in pages:
|
|
function_nav += '[< prev](%s) | ' % doc_page_link(pnum - 1)
|
|
for pnum_nav in pages:
|
|
if pnum_nav == pnum:
|
|
function_nav += '%d' % pnum_nav
|
|
else:
|
|
function_nav += '[%d](%s)' % (pnum_nav, doc_page_link(pnum_nav))
|
|
|
|
if (pnum_nav + 1) in pages:
|
|
function_nav += ' | '
|
|
if (pnum + 1) in pages:
|
|
function_nav += ' | [next >](%s)' % doc_page_link(pnum + 1)
|
|
|
|
buffer = buffer.replace('$[FUNCTION_NAV_HERE', function_nav)
|
|
|
|
with open(get_path(out_filename_docs % page_name), 'w', newline='\n') as out:
|
|
out.write(buffer)
|
|
|
|
############################################################################
|
|
|
|
def_pointers = []
|
|
|
|
def def_function(function):
|
|
s = ''
|
|
if not function['implemented']:
|
|
return ''
|
|
|
|
fid = function['identifier']
|
|
rtype, rlink = translate_type_to_lua(function['type'])
|
|
param_str = ', '.join([x['identifier'] for x in function['params']])
|
|
|
|
if rtype == None:
|
|
rtype = 'nil'
|
|
|
|
for param in function['params']:
|
|
pid = param['identifier']
|
|
ptype = param['type']
|
|
ptype, plink = translate_type_to_lua(ptype)
|
|
|
|
ptype = translate_to_def(ptype)
|
|
if ptype.startswith('Pointer_') and ptype not in def_pointers:
|
|
def_pointers.append(ptype)
|
|
|
|
s += '--- @param %s %s\n' % (pid, ptype)
|
|
|
|
rtype = translate_to_def(rtype)
|
|
if rtype.startswith('Pointer_') and rtype not in def_pointers:
|
|
def_pointers.append(rtype)
|
|
|
|
s += '--- @return %s\n' % rtype
|
|
s += "function %s(%s)\n -- ...\nend\n\n" % (fid, param_str)
|
|
|
|
return s
|
|
|
|
|
|
def def_files(processed_files):
|
|
s = '-- AUTOGENERATED FOR CODE EDITORS -- \n--- @meta\n--- @diagnostic disable\n\n'
|
|
for processed_file in processed_files:
|
|
for function in processed_file['functions']:
|
|
s += def_function(function)
|
|
|
|
for def_pointer in def_pointers:
|
|
s += '--- @class %s\n' % def_pointer
|
|
|
|
with open(get_path(out_filename_defs), 'w', newline='\n') as out:
|
|
out.write(s)
|
|
|
|
############################################################################
|
|
|
|
def main():
|
|
processed_files = process_files()
|
|
|
|
built_functions = build_functions(processed_files)
|
|
built_binds = build_binds(processed_files)
|
|
built_includes = build_includes()
|
|
|
|
filename = get_path(out_filename)
|
|
|
|
gen = template \
|
|
.replace("$[FUNCTIONS]", built_functions) \
|
|
.replace("$[BINDS]", built_binds) \
|
|
.replace("$[INCLUDES]", built_includes)
|
|
|
|
with open(filename, 'w', newline='\n') as out:
|
|
out.write(gen)
|
|
|
|
print('REJECTS:\n%s' % rejects)
|
|
|
|
doc_files(processed_files)
|
|
def_files(processed_files)
|
|
|
|
global total_functions
|
|
print('Total functions: ' + str(total_functions))
|
|
|
|
if len(sys.argv) >= 2 and sys.argv[1] == 'fuzz':
|
|
output_fuzz_file()
|
|
|
|
if __name__ == '__main__':
|
|
main()
|