This commit is contained in:
Emily♥ 2025-10-23 17:35:05 -04:00
commit e870880b8e
159 changed files with 39950 additions and 11323 deletions

View file

@ -1,7 +1,7 @@
#!/usr/bin/env bash
python3 ./autogen/gen_math.py $1
python3 ./autogen/convert_functions.py $1
python3 ./autogen/convert_structs.py $1
python3 ./autogen/gen_hooks.py $1
python3 ./autogen/convert_functions.py $1
python3 ./autogen/convert_constants.py $1
python3 ./autogen/extract_display_lists.py $1

View file

@ -4,7 +4,8 @@ from vec_types import *
usf_types = ['u8', 'u16', 'u32', 'u64', 's8', 's16', 's32', 's64', 'f32', 'f64']
vec_types = list(VEC_TYPES.keys())
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision', 'LevelScript', 'Trajectory']
typedef_pointers = ['BehaviorScript', 'ObjectAnimPointer', 'Collision', 'LevelScript', 'Trajectory', 'Texture']
cobject_function_identifier = 'FUNCTION'
type_mappings = {
'char': 's8',
@ -117,6 +118,12 @@ def translate_type_to_lvt(ptype, allowArrays=False):
if ptype == "LuaFunction":
return "LVT_LUAFUNCTION"
if ptype == "LuaTable":
return "LVT_LUATABLE"
if ptype == cobject_function_identifier:
return "LVT_FUNCTION"
if "struct" in ptype:
if pointerLvl > 1:
return "LVT_???"
@ -194,6 +201,12 @@ def translate_type_to_lot(ptype, allowArrays=True):
if ptype == 'LuaFunction':
return 'LOT_NONE'
if ptype == 'LuaTable':
return 'LOT_NONE'
if ptype == cobject_function_identifier:
return 'LOT_NONE'
if ptype in override_types:
return 'LOT_' + ptype.upper()
@ -280,6 +293,12 @@ def translate_type_to_lua(ptype):
if ptype == 'LuaFunction':
return '`Lua Function` ()', None
if ptype == 'LuaTable':
return '`table`', None
if ptype == cobject_function_identifier:
return cobject_function_identifier, None
if ptype.count('*') == 1 and '???' not in translate_type_to_lvt(ptype):
ptype = ptype.replace('const', '').replace('*', '').strip()
s = '`Pointer` <`%s`>' % translate_type_to_lua(ptype)[0].replace('`', '').strip()

View file

@ -67,7 +67,7 @@ exclude_constants = {
"src/pc/djui/djui_console.h": [ "CONSOLE_MAX_TMP_BUFFER" ],
"src/pc/lua/smlua_hooks.h": [ "MAX_HOOKED_MOD_MENU_ELEMENTS", "^HOOK_RETURN_.*", "^ACTION_HOOK_.*", "^MOD_MENU_ELEMENT_.*" ],
"src/pc/djui/djui_panel_menu.h": [ "RAINBOW_TEXT_LEN" ],
"src/pc/mods/mod_fs.h": [ "MOD_FS_DIRECTORY", "MOD_FS_EXTENSION", "MOD_FS_VERSION", "INT_TYPE_MAX", "FLOAT_TYPE_MAX", "FILE_SEEK_MAX" ],
"src/pc/mods/mod_fs.h": [ "INT_TYPE_MAX", "FLOAT_TYPE_MAX", "FILE_SEEK_MAX" ],
}
include_constants = {
@ -139,6 +139,7 @@ defined_values = {
'VERSION_JP': False,
'VERSION_SH': False,
'F3DEX_GBI_2': True,
'DEVELOPMENT': False,
}
############################################################################
@ -255,15 +256,17 @@ def process_define(filename, line, inIfBlock):
val = val.replace('(u8)', '')
val = val.replace('(u64)', '')
val = re.sub(r'\.\d+f', '', val)
val = val.strip()
for p in val.split(' '):
if p.startswith('0x'):
continue
p = re.sub(r'0x[a-fA-F0-9]+', '', p)
if re.search(r'[a-z]', p) != None and "VERSION_TEXT" not in line and "SM64COOPDX_VERSION" not in line:
if 'gCurrentObject' not in line and verbose:
print('UNRECOGNIZED DEFINE: ' + line)
return None
if not (val.startswith('"') and val.endswith('"') and '"' not in val[1:-1]):
for p in val.split(' '):
if p.startswith('0x'):
continue
p = re.sub(r'0x[a-fA-F0-9]+', '', p)
if re.search(r'[a-z]', p) != None and "VERSION_TEXT" not in line and "SM64COOPDX_VERSION" not in line:
if 'gCurrentObject' not in line and verbose:
print('UNRECOGNIZED DEFINE: ' + line)
return None
if not allowed_identifier(filename, ident):
return None

View file

@ -138,6 +138,8 @@ override_disallowed_functions = {
"src/game/first_person_cam.h": [ "first_person_update" ],
"src/pc/lua/utils/smlua_collision_utils.h": [ "collision_find_surface_on_ray" ],
"src/engine/behavior_script.h": [ "stub_behavior_script_2", "cur_obj_update" ],
"src/pc/mods/mod_storage.h": [ "mod_storage_shutdown" ],
"src/pc/mods/mod_fs.h": [ "mod_fs_read_file_from_uri", "mod_fs_shutdown" ],
"src/pc/utils/misc.h": [ "str_.*", "file_get_line", "delta_interpolate_(normal|rgba|mtx)", "detect_and_skip_mtx_interpolation", "precise_delay_f64" ],
"src/engine/lighting_engine.h": [ "le_calculate_vertex_lighting", "le_clear", "le_shutdown" ],
}
@ -813,6 +815,8 @@ def build_param(fid, param, i):
return ' %s %s = smlua_to_bytestring(L, %d);\n' % (ptype, pid, i)
elif ptype == 'LuaFunction':
return ' %s %s = smlua_to_lua_function(L, %d);\n' % (ptype, pid, i)
elif ptype == 'LuaTable':
return ' %s %s = smlua_to_lua_table(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)
@ -868,6 +872,8 @@ def build_call(function):
lfunc = 'lua_pushstring'
elif ftype == 'ByteString':
lfunc = 'smlua_push_bytestring'
elif ftype == 'LuaTable':
lfunc = 'smlua_push_lua_table'
elif translate_type_to_lot(ftype) == 'LOT_POINTER':
lvt = translate_type_to_lvt(ftype)
return ' smlua_push_pointer(L, %s, (void*)%s, NULL);\n' % (lvt, ccall)

View file

@ -96,6 +96,7 @@ override_field_invisible = {
"Object": [ "firstSurface" ],
"Animation": [ "unusedBoneCount" ],
"ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail" ],
"Painting": [ "normalDisplayList", "textureMaps", "rippleDisplayList", "ripples" ],
"DialogEntry": [ "str" ],
"ModFsFile": [ "data", "capacity" ],
"ModFs": [ "files" ],
@ -141,6 +142,7 @@ override_field_immutable = {
"DialogEntry": [ "unused", "linesPerBox", "leftOffset", "width", "str", "text", "replaced"],
"ModFsFile": [ "*" ],
"ModFs": [ "*" ],
"StaticObjectCollision": [ "*" ],
}
override_field_version_excludes = {
@ -321,6 +323,14 @@ def parse_struct(struct_str, sortFields = False):
field['identifier'] = field_id.strip()
field['field_str'] = field_str
# handle function members
if field['type'].startswith(cobject_function_identifier):
field_function = field['identifier']
field_type, field_id = field['type'].split()
field['type'] = field_type.strip()
field['identifier'] = field_id.strip('"').strip()
field['function'] = field_function.strip()
struct['fields'].append(field)
if identifier == 'Object':
@ -484,6 +494,9 @@ def get_struct_field_info(struct, field):
if fid in override_field_mutable[sid] or '*' in override_field_mutable[sid]:
fimmutable = 'false'
if ftype == cobject_function_identifier:
fimmutable = 'true'
if not ('char' in ftype and '[' in ftype and 'unsigned' not in ftype):
array_match = re.search(r'\[([^\]]+)\]', ftype)
if array_match:
@ -506,6 +519,7 @@ def build_struct(struct):
# build up table and track column width
field_table = []
field_functions = []
for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot, size = get_struct_field_info(struct, field)
@ -531,22 +545,40 @@ def build_struct(struct):
startStr += '#ifndef ' + override_field_version_excludes[fid] + '\n'
endStr += '\n#endif'
startStr += ' { '
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('offsetof(%s%s, %s), ' % (struct_str, name, field['identifier']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(%s)' % ftype )
row.append(endStr )
if ftype == cobject_function_identifier:
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('(size_t) FUNCTION__%s, ' % (field['function']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(const char *)' )
row.append(endStr )
field_functions.append(field['function'])
else:
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('offsetof(%s%s, %s), ' % (struct_str, name, field['identifier']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(%s)' % ftype )
row.append(endStr )
field_table.append(row)
field_table_str, field_count = table_to_string(field_table)
field_count_define = 'LUA_%s_FIELD_COUNT' % identifier_to_caps(sid)
struct_lot = 'LOT_%s' % sid.upper()
s = "#define %s $[STRUCTFIELDCOUNT]\n" % field_count_define
s = ''
if field_functions:
for field_function in field_functions:
s += 'static const char FUNCTION__%s[] = "%s";\n' % (field_function, field_function)
s += '\n'
s += "#define %s $[STRUCTFIELDCOUNT]\n" % field_count_define
s += "static struct LuaObjectField s%sFields[%s] = {\n" % (sid, field_count_define)
s += field_table_str
s += '};\n'
@ -646,6 +678,21 @@ def build_includes():
############################################################################
# HACK: Parse docs/functions.md to find the page where the function is documented
function_links = {}
def doc_find_function_link(function):
if not function_links:
with open('docs/lua/functions.md') as f:
lines = f.readlines()
for line in lines:
line = line.replace(' ', '').strip()
res, n = re.subn(r'^-\[(.*)\]\((.*)\)', '\\1,\\2', line)
if n != 0:
fname, flink = res.split(',')
function_links[fname] = flink
return function_links.get(function, '')
def doc_struct_index(structs):
s = '# Supported Structs\n'
for struct in structs:
@ -662,26 +709,30 @@ def doc_struct_field(struct, field):
sid = struct['identifier']
if sid in override_field_invisible:
if fid in override_field_invisible[sid]:
return ''
return '', False
if sid in override_field_deprecated:
if fid in override_field_deprecated[sid]:
return ''
return '', False
if '???' in lvt or '???' in lot:
return ''
return '', False
ftype, flink = translate_type_to_lua(ftype)
if ftype == cobject_function_identifier:
flink = doc_find_function_link(field['function'])
return '| %s | [`%s`](%s) |\n' % (fid, field['function'], flink), True
restrictions = ('', 'read-only')[fimmutable == 'true']
global total_fields
total_fields += 1
if flink:
return '| %s | [%s](%s) | %s |\n' % (fid, ftype, flink, restrictions)
return '| %s | [%s](%s) | %s |\n' % (fid, ftype, flink, restrictions), False
return '| %s | %s | %s |\n' % (fid, ftype, restrictions)
return '| %s | %s | %s |\n' % (fid, ftype, restrictions), False
def doc_struct_object_fields(struct):
@ -696,7 +747,8 @@ def doc_struct_object_fields(struct):
s += "| Field | Type | Access |\n"
s += "| ----- | ---- | ------ |\n"
s += doc_struct_field(struct, field)
line, _ = doc_struct_field(struct, field)
s += line
return s
@ -707,17 +759,27 @@ def doc_struct(struct):
s += "| Field | Type | Access |\n"
s += "| ----- | ---- | ------ |\n"
# build doc table
field_table = []
field_functions = ''
for field in struct['fields']:
if 'object_field' in field and field['object_field'] == True:
continue
s += doc_struct_field(struct, field)
line, isFunction = doc_struct_field(struct, field)
if isFunction:
field_functions += line
else:
s += line
if sid == 'Object':
s += doc_struct_object_fields(struct)
# functions
if field_functions:
s += '\n**Functions:**\n\n'
s += "| Name | Reference |\n"
s += "| ---- | --------- |\n"
s += field_functions
s += '\n[:arrow_up_small:](#)\n\n<br />\n'
return s
@ -740,6 +802,32 @@ def doc_structs(structs):
def_pointers = []
# HACK: Parse autogen/lua_definitions/functions.lua to find the function signature
function_signatures = {}
def get_function_signature(function):
if not function_signatures:
with open('autogen/lua_definitions/functions.lua') as f:
lines = f.readlines()
function_params = []
function_return = None
for line in lines:
if line.startswith('--- @param'):
function_params.append(line.split()[2:4])
elif line.startswith('--- @return'):
function_return = line.split()[2]
elif line.startswith('function'):
sig = 'fun('
sig += ', '.join(['%s: %s' % (param_name, param_type) for param_name, param_type in function_params])
sig += ')'
if function_return:
sig += ': %s' % (function_return)
function_name = line.replace('(', ' ').split()[1]
function_signatures[function_name] = sig
function_params.clear()
function_return = None
return function_signatures.get(function, 'function')
def def_struct(struct):
sid = struct['identifier']
@ -761,7 +849,12 @@ def def_struct(struct):
ftype, flink = translate_type_to_lua(ftype)
ftype = translate_to_def(ftype)
# try to get the function signature
if ftype == cobject_function_identifier:
ftype = get_function_signature(field['function'])
else:
ftype = translate_to_def(ftype)
if ftype.startswith('Pointer_') and ftype not in def_pointers:
def_pointers.append(ftype)

View file

@ -1,6 +1,7 @@
import os
import re
import sys
from common import cobject_function_identifier
def extract_structs(filename):
with open(filename) as file:
@ -36,6 +37,9 @@ def extract_structs(filename):
while (' ' in txt):
txt = txt.replace(' ', ' ')
# handle function members (NOT function pointers)
txt = re.sub(f'{cobject_function_identifier}\\((.*),(.*)\\)', f'{cobject_function_identifier} \\1 \\2', txt)
# strip macros
txt = re.sub(r'[^a-zA-Z0-9_][A-Z0-9_]+\(.*\)', '', txt)

View file

@ -309,17 +309,20 @@ def main():
name=input["name"]
)
n_outputs = len(hook_event["outputs"])
generated += SMLUA_CALL_EVENT_HOOKS_CALLBACK.format(
n_inputs=len(hook_event["inputs"]) - mod_index_found,
n_outputs=len(hook_event["outputs"]),
n_outputs=n_outputs,
hook_type=hook_event["type"],
set_hook_result=set_hook_result
)
# Note: relative indexes for return values are reversed in the Lua stack
# -1 is the last value, -2 the penultimate, ... and -N the first
for i, output in enumerate(hook_event["outputs"]):
generated += SMLUA_TYPES[output["type"]]["output"].format(
name=output["name"],
output_index=i+1,
output_index=n_outputs - i,
return_on_output_set=return_on_output_set
)

View file

@ -1,39 +1,70 @@
import sys
VEC3X_TO_VEC3Y = """
VECX_TO_VECY = """
/* |description|
Converts a 3D {{desc}} vector `a` into a 3D {{desc_2}} vector and stores the result in `dest`
Converts a {{size}}D {{desc}} vector `a` into a {{size}}D {{desc_2}} vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec3{{suffix_2}}p vec3{{suffix}}_to_vec3{{suffix_2}}(OUT Vec3{{suffix_2}} dest, Vec3{{suffix}} a) {
dest[0] = a[0]{{rounding_0}};
dest[1] = a[1]{{rounding_1}};
dest[2] = a[2]{{rounding_2}};
INLINE OPTIMIZE_O3 Vec{{size}}{{suffix_2}}p vec{{size}}{{suffix}}_to_vec{{size}}{{suffix_2}}(OUT Vec{{size}}{{suffix_2}} dest, Vec{{size}}{{suffix}} a) {
{{body}}
return dest;
}
"""
ROUNDING_FORMULA = " + ((a[%d] > 0) ? 0.5f : -0.5f)"
ROUNDING_FORMULA = " + ((a[{i}] > 0) ? 0.5f : -0.5f)"
def vec3_write_conversion_functions(generated: str, curr_template: dict, templates: list, size: int) -> str:
def vec_write_conversion_functions(generated: str, curr_template: dict, templates: list, size: int) -> str:
for template in templates:
if template["suffix"] == curr_template["suffix"]:
continue
generated += VEC3X_TO_VEC3Y \
body = "\n ".join([
"dest[{i}] = a[{i}]{rounding};".format(
i=i,
rounding=ROUNDING_FORMULA.format(i=i) if curr_template["rounding"] else ""
) for i in range(size)
])
generated += VECX_TO_VECY \
.replace("{{size}}", str(size)) \
.replace("{{desc}}", curr_template["desc"]) \
.replace("{{suffix}}", curr_template["suffix"]) \
.replace("{{desc_2}}", template["desc"]) \
.replace("{{suffix_2}}", template["suffix"])
for i in range(size):
rounding_i = "{{rounding_%d}}" % (i)
generated = generated.replace(rounding_i, ROUNDING_FORMULA % (i) if curr_template["rounding"] else "")
.replace("{{suffix_2}}", template["suffix"]) \
.replace("{{body}}", body)
return generated
TEMPLATES = {
"src/engine/math_util_vec2.tmpl": {
"size": 2,
"templates": [
{
"desc": "floating-point",
"type": "f32",
"suffix": "f",
"rounding": True
},
{
"desc": "integer",
"type": "s32",
"suffix": "i",
"rounding": False
},
{
"desc": "short integer",
"type": "s16",
"suffix": "s",
"rounding": False
}
],
"post-template": {
"function": vec_write_conversion_functions,
"args": {
"size": 2
}
}
},
"src/engine/math_util_vec3.tmpl": {
"size": 3,
"templates": [
@ -57,7 +88,7 @@ TEMPLATES = {
}
],
"post-template": {
"function": vec3_write_conversion_functions,
"function": vec_write_conversion_functions,
"args": {
"size": 3
}

View file

@ -2999,6 +2999,9 @@ GRAPH_RENDER_PLAYER = (1 << 7)
--- @type integer
GRAPH_EXTRA_FORCE_3D = (1 << 0)
--- @type integer
GRAPH_EXTRA_ROTATE_HELD = (1 << 1)
--- @type integer
GRAPH_NODE_TYPE_FUNCTIONAL = 0x100
@ -4554,14 +4557,20 @@ GRAB_POS_BOWSER = 3 --- @type MarioGrabPosGSCId
--- | `GRAB_POS_BOWSER`
--- @type integer
MOD_FS_MAX_SIZE = 0x1000000
MOD_FS_MAX_SIZE = 0x2000000
--- @type integer
MOD_FS_MAX_FILES = 0x100
MOD_FS_MAX_FILES = 0x200
--- @type integer
MOD_FS_MAX_PATH = 0x100
--- @type string
MOD_FS_URI_PREFIX = "modfs:/"
--- @type string
MOD_FS_URI_FORMAT = "modfs:/%s/%s"
INT_TYPE_U8 = 0 --- @type ModFsFileIntType
INT_TYPE_U16 = 1 --- @type ModFsFileIntType
INT_TYPE_U32 = 2 --- @type ModFsFileIntType
@ -6755,6 +6764,9 @@ R_CBUTTONS = CONT_F
--- @type integer
D_CBUTTONS = CONT_D
--- @type string
PALETTES_DIRECTORY = "palettes"
--- @type integer
MAX_PRESET_PALETTES = 128
@ -10953,6 +10965,9 @@ SURFACE_FLAG_DYNAMIC = (1 << 0)
--- @type integer
SURFACE_FLAG_NO_CAM_COLLISION = (1 << 1)
--- @type integer
SURFACE_FLAG_INTANGIBLE = (1 << 2)
--- @type integer
SURFACE_FLAG_X_PROJECTION = (1 << 3)
@ -11163,5 +11178,11 @@ VERSION_NUMBER = 41
--- @type integer
MINOR_VERSION_NUMBER = 0
--- @type string
GAME_NAME = "sm64coopdx"
--- @type string
WINDOW_NAME = "Super Mario 64 Coop Deluxe"
--- @type integer
MAX_VERSION_LENGTH = 128

View file

@ -7435,25 +7435,6 @@ function mod_fs_create()
-- ...
end
--- @return boolean
--- Deletes the modfs object of the active mod if it exists. Returns true on success
function mod_fs_delete()
-- ...
end
--- @return boolean
--- Saves the modfs object of the active mod if it exists. Returns true on success
function mod_fs_save()
-- ...
end
--- @param pub boolean
--- @return boolean
--- Marks the modfs object of the active mod as public (i.e. readable by other mods) if it exists. Returns true on success
function mod_fs_set_public(pub)
-- ...
end
--- @param modFs ModFs
--- @param index integer
--- @return string
@ -7514,6 +7495,28 @@ function mod_fs_clear(modFs)
-- ...
end
--- @param modFs ModFs
--- @return boolean
--- Saves the provided `modFs` to persistent storage. Returns true on success
function mod_fs_save(modFs)
-- ...
end
--- @param modFs ModFs
--- @return boolean
--- Removes the provided `modFs` from persistent storage and deletes its object. Returns true on success
function mod_fs_delete(modFs)
-- ...
end
--- @param modFs ModFs
--- @param pub boolean
--- @return boolean
--- Marks the provided `modFs` as public (i.e. readable by other mods). Returns true on success
function mod_fs_set_public(modFs, pub)
-- ...
end
--- @param file ModFsFile
--- @return boolean
--- Reads a boolean from a binary modfs `file`
@ -7618,6 +7621,13 @@ function mod_fs_file_seek(file, offset, origin)
-- ...
end
--- @param file ModFsFile
--- @return boolean
--- Sets the current position of a modfs `file` to its beginning. Returns true on success
function mod_fs_file_rewind(file)
-- ...
end
--- @param file ModFsFile
--- @return boolean
--- Returns true if the provided modfs `file` has reached its end of file
@ -7642,6 +7652,14 @@ function mod_fs_file_erase(file, length)
-- ...
end
--- @param file ModFsFile
--- @param text boolean
--- @return boolean
--- Marks the provided modfs `file` as text. Returns true on success
function mod_fs_file_set_text_mode(file, text)
-- ...
end
--- @param file ModFsFile
--- @param pub boolean
--- @return boolean
@ -7707,6 +7725,12 @@ function mod_storage_load_bool(key)
-- ...
end
--- @return table
--- Loads all keys and values in mod storage as strings and returns them as a table
function mod_storage_load_all()
-- ...
end
--- @param key string
--- @return boolean
--- Checks if a `key` is in mod storage
@ -10776,12 +10800,19 @@ function gfx_get_vertex_count(cmd)
end
--- @param cmd Pointer_Gfx
--- @return Pointer_integer
--- @return Pointer_Texture
--- Gets the texture from a display list command if it has an image related op
function gfx_get_texture(cmd)
-- ...
end
--- @param gfx Pointer_Gfx
--- @return string
--- Gets the name of a display list
function gfx_get_name(gfx)
-- ...
end
--- @param gfx Pointer_Gfx
--- @return integer
--- Gets the max length of a display list
@ -10838,6 +10869,13 @@ function gfx_delete_all()
-- ...
end
--- @param vtx Pointer_Vtx
--- @return string
--- Gets the name of a vertex buffer
function vtx_get_name(vtx)
-- ...
end
--- @param vtx Pointer_Vtx
--- @return integer
--- Gets the max count of vertices of a vertex buffer
@ -11514,12 +11552,19 @@ function geo_get_current_held_object()
-- ...
end
--- @param tex Pointer_integer
--- Converts a texture's pixels to a Lua table. Returns nil if failed. Otherwise, returns a table as a pure memory buffer. Supports rgba16 and rgba32 textures.
--- @param tex Pointer_Texture
--- Converts a texture's pixels to a Lua table. Returns nil if failed. Otherwise, returns a table as a pure memory buffer. Supports rgba16 and rgba32 textures
function texture_to_lua_table(tex)
-- ...
end
--- @param tex Pointer_Texture
--- @return string
--- Gets the name of the provided texture pointer `tex`
function get_texture_name(tex)
-- ...
end
--- @param name string
--- @return ModelExtendedId
--- Gets the extended model ID for the `name` of a `GeoLayout`
@ -12274,6 +12319,27 @@ function load_object_collision_model()
-- ...
end
--- @return StaticObjectCollision
--- Loads the object's collision data into static collision. You may run this only once to capture the object's collision at that frame.
function load_static_object_collision()
-- ...
end
--- @param col StaticObjectCollision
--- @param tangible boolean
--- Toggles a collection of static object surfaces
function toggle_static_object_collision(col, tangible)
-- ...
end
--- @param col StaticObjectCollision
--- @param index integer
--- @return Surface
--- Gets a surface corresponding to `index` from the static object collision
function get_static_object_surface(col, index)
-- ...
end
--- @param o Object
--- @param index integer
--- @return Surface
@ -12318,6 +12384,7 @@ end
--- @alias Pointer_Collision Collision
--- @alias Pointer_Gfx Gfx
--- @alias Pointer_Vtx Vtx
--- @alias Pointer_Texture Texture
--- @alias Vec2fp Vec2f
--- @alias Vec3fp Vec3f
--- @alias Vec4fp Vec4f

View file

@ -1280,7 +1280,7 @@
--- @field public customBehaviorIndex integer
--- @class ModAudio
--- @field public file ModFile
--- @field public filepath string
--- @field public isStream boolean
--- @field public baseVolume number
--- @field public loaded boolean
@ -1304,6 +1304,16 @@
--- @field public numFiles integer
--- @field public totalSize integer
--- @field public isPublic boolean
--- @field public get_filename fun(modFs: ModFs, index: integer): string
--- @field public get_file fun(modFs: ModFs, filepath: string): ModFsFile
--- @field public create_file fun(modFs: ModFs, filepath: string, text: boolean): ModFsFile
--- @field public move_file fun(modFs: ModFs, oldpath: string, newpath: string, overwriteExisting: boolean): boolean
--- @field public copy_file fun(modFs: ModFs, srcpath: string, dstpath: string, overwriteExisting: boolean): boolean
--- @field public delete_file fun(modFs: ModFs, filepath: string): boolean
--- @field public clear fun(modFs: ModFs): boolean
--- @field public save fun(modFs: ModFs): boolean
--- @field public delete fun(modFs: ModFs): boolean
--- @field public set_public fun(modFs: ModFs, pub: boolean): boolean
--- @class ModFsFile
--- @field public modFs ModFs
@ -1312,6 +1322,25 @@
--- @field public offset integer
--- @field public isText boolean
--- @field public isPublic boolean
--- @field public read_bool fun(file: ModFsFile): boolean
--- @field public read_integer fun(file: ModFsFile, intType: ModFsFileIntType): integer
--- @field public read_number fun(file: ModFsFile, floatType: ModFsFileFloatType): number
--- @field public read_bytes fun(file: ModFsFile, length: integer): string
--- @field public read_string fun(file: ModFsFile): string
--- @field public read_line fun(file: ModFsFile): string
--- @field public write_bool fun(file: ModFsFile, value: boolean): boolean
--- @field public write_integer fun(file: ModFsFile, value: integer, intType: ModFsFileIntType): boolean
--- @field public write_number fun(file: ModFsFile, value: number, floatType: ModFsFileFloatType): boolean
--- @field public write_bytes fun(file: ModFsFile, bytestring: string): boolean
--- @field public write_string fun(file: ModFsFile, str: string): boolean
--- @field public write_line fun(file: ModFsFile, str: string): boolean
--- @field public seek fun(file: ModFsFile, offset: integer, origin: ModFsFileSeek): boolean
--- @field public rewind fun(file: ModFsFile): boolean
--- @field public is_eof fun(file: ModFsFile): boolean
--- @field public fill fun(file: ModFsFile, byte: integer, length: integer): boolean
--- @field public erase fun(file: ModFsFile, length: integer): boolean
--- @field public set_text_mode fun(file: ModFsFile, text: boolean): boolean
--- @field public set_public fun(file: ModFsFile, pub: boolean): boolean
--- @class ModeTransitionInfo
--- @field public newMode integer
@ -2176,10 +2205,9 @@
--- @field public rippleTimer number
--- @field public rippleX number
--- @field public rippleY number
--- @field public normalDisplayList Pointer_Gfx
--- @field public textureArray Pointer_Texture[]
--- @field public textureWidth integer
--- @field public textureHeight integer
--- @field public rippleDisplayList Pointer_Gfx
--- @field public rippleTrigger integer
--- @field public alpha integer
--- @field public marioWasUnder integer
@ -2338,6 +2366,10 @@
--- @field public dialog5 integer
--- @field public dialog6 integer
--- @class StaticObjectCollision
--- @field public index integer
--- @field public length integer
--- @class Surface
--- @field public type integer
--- @field public flags integer
@ -2357,7 +2389,7 @@
--- @field public object Object
--- @class TextureInfo
--- @field public texture Pointer_integer
--- @field public texture Pointer_Texture
--- @field public name string
--- @field public width integer
--- @field public height integer
@ -2528,3 +2560,5 @@
--- @alias Pointer_Mat4 Mat4
--- @alias Pointer_Vec4s Vec4s
--- @alias Pointer_BehaviorScript BehaviorScript
--- @alias Pointer_Texture[] Texture[]
--- @alias Pointer_Texture Texture

View file

@ -67,7 +67,7 @@ const f32 font_aliased_widths[] = {
/* 0 1 2 3 4 5 6 7 8 9 */
14, 12, 13, 14, 14, 14, 14, 13, 14, 14,
/* : ; < = > ? @ */
6, 8, 10, 12, 10, 11, 18,
8, 8, 10, 12, 10, 11, 18,
/* A B C D E F G H I J K L M N O P Q R S T U V W X Y Z */
12, 12, 12, 12, 11, 10, 12, 12, 9, 12, 12, 10, 16, 16, 12, 11, 12, 12, 12, 10, 12, 10, 16, 14, 12, 12,
/* [ \ ] ^ _ ` */
@ -75,7 +75,7 @@ const f32 font_aliased_widths[] = {
/* a b c d e f g h i j k l m n o p q r s t u v w x y z */
10, 10, 10, 10, 9, 8, 12, 10, 7, 9, 10, 4, 13, 10, 9, 9, 10, 9, 10, 9, 10, 9, 14, 12, 10, 10,
/* { | } ~ DEL */
10, 8, 10, 16, 10,
10, 8, 10, 16, 16,
};
//////////////////////////////////////////////////////////

View file

@ -558,6 +558,8 @@ const struct BehaviorTableEntry gBehaviorTable[id_bhv_max_count] = {
enum BehaviorId get_id_from_behavior(const BehaviorScript* behavior) {
if (behavior == NULL) { return id_bhv_max_count; }
if ((behavior[0] >> 24) != 0x00) { return id_bhv_max_count; } // check for BEGIN
if ((behavior[1] >> 24) != 0x39) { return id_bhv_max_count; } // check for ID
return (enum BehaviorId)(behavior[1] & 0xFFFF);
}

View file

@ -37,17 +37,17 @@ void dynos_generate_packs(const char* directory);
// -- geos -- //
void dynos_actor_override(struct Object* obj, void** aSharedChild);
void dynos_add_actor_custom(s32 modIndex, s32 modFileIndex, const char *filePath, const char* geoName);
bool dynos_add_actor_custom(s32 modIndex, s32 modFileIndex, const char *filePath, const char* geoName);
const void* dynos_geolayout_get(const char *name);
bool dynos_actor_get_mod_index_and_token(struct GraphNode *graphNode, u32 tokenIndex, s32 *modIndex, s32 *modFileIndex, const char **token);
void dynos_actor_register_modified_graph_node(struct GraphNode *node);
// -- collisions -- //
void dynos_add_collision(const char *filePath, const char* collisionName);
bool dynos_add_collision(const char *filePath, const char* collisionName);
Collision* dynos_collision_get(const char* collisionName);
// -- textures -- //
void dynos_add_texture(const char *filePath, const char* textureName);
bool dynos_add_texture(const char *filePath, const char* textureName);
bool dynos_texture_get(const char* textureName, struct TextureInfo* outTextureInfo);
bool dynos_texture_get_from_data(const Texture *tex, struct TextureInfo* outTextureInfo);
void dynos_texture_override_set(const char* textureName, struct TextureInfo* overrideTextureInfo);
@ -90,11 +90,13 @@ void dynos_model_clear_pool(enum ModelPool aModelPool);
// -- gfx -- //
Gfx *dynos_gfx_get_writable_display_list(Gfx* gfx);
Gfx *dynos_gfx_get(const char *name, u32 *outLength);
const char *dynos_gfx_get_name(Gfx *gfx);
Gfx *dynos_gfx_create(const char *name, u32 length);
bool dynos_gfx_resize(Gfx *gfx, u32 newLength);
bool dynos_gfx_delete(Gfx *gfx);
void dynos_gfx_delete_all();
Vtx *dynos_vtx_get(const char *name, u32 *outCount);
const char *dynos_vtx_get_name(Vtx *vtx);
Vtx *dynos_vtx_create(const char *name, u32 count);
bool dynos_vtx_resize(Vtx *vtx, u32 newCount);
bool dynos_vtx_delete(Vtx *vtx);

View file

@ -897,7 +897,7 @@ void DynOS_Pack_AddTex(PackData* aPackData, DataNode<TexData>* aTexData);
//
std::map<const void *, ActorGfx> &DynOS_Actor_GetValidActors();
void DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFilename, const char *aActorName);
bool DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFilename, const char *aActorName);
const void *DynOS_Actor_GetLayoutFromName(const char *aActorName);
bool DynOS_Actor_GetModIndexAndToken(const GraphNode *aGraphNode, u32 aTokenIndex, s32 *outModIndex, s32 *outModFileIndex, const char **outToken);
ActorGfx* DynOS_Actor_GetActorGfx(const GraphNode* aGraphNode);
@ -925,7 +925,7 @@ u8 *DynOS_Tex_ConvertToRGBA32(const u8 *aData, u64 aLength, s32 aFormat, s32 aSi
bool DynOS_Tex_Import(void **aOutput, void *aPtr, s32 aTile, void *aGfxRApi, void **aHashMap, void *aPool, u32 *aPoolPos, u32 aPoolSize);
void DynOS_Tex_Activate(DataNode<TexData>* aNode, bool aCustomTexture);
void DynOS_Tex_Deactivate(DataNode<TexData>* aNode);
void DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName);
bool DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName);
bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo);
bool DynOS_Tex_GetFromData(const Texture *aTex, struct TextureInfo* aOutTexInfo);
void DynOS_Tex_Override_Set(const char* textureName, struct TextureInfo* aOverrideTexInfo);
@ -963,7 +963,7 @@ void DynOS_Bhv_ModShutdown();
// Col Manager
//
void DynOS_Col_Activate(const SysPath &aFilePath, const char *aCollisionName);
bool DynOS_Col_Activate(const SysPath &aFilePath, const char *aCollisionName);
Collision* DynOS_Col_Get(const char* collisionName);
void DynOS_Col_ModShutdown();
@ -996,11 +996,13 @@ void DynOS_Model_ClearPool(enum ModelPool aModelPool);
Gfx *DynOS_Gfx_GetWritableDisplayList(Gfx *aGfx);
Gfx *DynOS_Gfx_Get(const char *aName, u32 *outLength);
const char *DynOS_Gfx_GetName(Gfx *aGfx);
Gfx *DynOS_Gfx_Create(const char *aName, u32 aLength);
bool DynOS_Gfx_Resize(Gfx *aGfx, u32 aNewLength);
bool DynOS_Gfx_Delete(Gfx *aGfx);
void DynOS_Gfx_DeleteAll();
Vtx *DynOS_Vtx_Get(const char *aName, u32 *outCount);
const char *DynOS_Vtx_GetName(Vtx *aVtx);
Vtx *DynOS_Vtx_Create(const char *aName, u32 aCount);
bool DynOS_Vtx_Resize(Vtx *aVtx, u32 aNewCount);
bool DynOS_Vtx_Delete(Vtx *aVtx);

View file

@ -1,6 +1,10 @@
#include "dynos.cpp.h"
#include <zlib.h>
extern "C" {
#include "pc/mods/mod_fs.h"
}
static const u64 DYNOS_BIN_COMPRESS_MAGIC = 0x4E4942534F4E5944llu;
static FILE *sFile = NULL;
static u8 *sBufferUncompressed = NULL;
@ -154,9 +158,75 @@ bool DynOS_Bin_Compress(const SysPath &aFilename) {
return true;
}
static BinFile *DynOS_Bin_Decompress_ModFs(const SysPath &aFilename) {
DynOS_Bin_Compress_Init();
// Read file data
void *_Buffer = NULL;
u32 _Size = 0;
if (!mod_fs_read_file_from_uri(aFilename.c_str(), &_Buffer, &_Size)) {
DynOS_Bin_Compress_Free();
return NULL;
}
sBufferCompressed = (u8 *) _Buffer;
sLengthCompressed = _Size;
// Check file length
u64 _LengthHeader = (u64) (sizeof(u64) + sizeof(u64));
if (!DynOS_Bin_Compress_Check(
sLengthCompressed >= _LengthHeader,
__FUNCTION__, aFilename.c_str(), "Empty file"
)) return NULL;
// Compare with magic constant
// If not equal, it's not a compressed file
u64 _Magic = ((u64 *) _Buffer)[0];
if (_Magic != DYNOS_BIN_COMPRESS_MAGIC) {
BinFile *_BinFile = BinFile::OpenB(sBufferCompressed, sLengthCompressed);
DynOS_Bin_Compress_Free();
return _BinFile;
}
PrintNoNewLine("Decompressing file \"%s\"...", aFilename.c_str());
// Read expected uncompressed file size
sLengthUncompressed = ((u64 *) _Buffer)[1];
sLengthCompressed -= _LengthHeader;
u8 *_BufferCompressed = sBufferCompressed + _LengthHeader;
// Allocate memory for uncompressed buffer
if (!DynOS_Bin_Compress_Check(
(sBufferUncompressed = (u8 *) calloc(sLengthUncompressed, sizeof(u8))) != NULL,
__FUNCTION__, aFilename.c_str(), "Cannot allocate memory for decompression"
)) return NULL;
// Uncompress data
uLongf _LengthUncompressed = (uLongf)sLengthUncompressed;
int uncompressRc = uncompress(sBufferUncompressed, &_LengthUncompressed, _BufferCompressed, sLengthCompressed);
sLengthUncompressed = _LengthUncompressed;
if (!DynOS_Bin_Compress_Check(
uncompressRc == Z_OK,
__FUNCTION__, aFilename.c_str(), "Cannot uncompress data"
)) {
PrintError("ERROR: uncompress rc: %d, length uncompressed: %lu, length compressed: %lu, length header: %lu", uncompressRc, sLengthUncompressed, sLengthCompressed, _LengthHeader);
return NULL;
}
Print("uncompress rc: %d, length uncompressed: %lu, length compressed: %lu, length header: %lu", uncompressRc, sLengthUncompressed, sLengthCompressed, _LengthHeader);
// Return uncompressed data as a BinFile
BinFile *_BinFile = BinFile::OpenB(sBufferUncompressed, sLengthUncompressed);
DynOS_Bin_Compress_Free();
Print(" Done.");
return _BinFile;
}
BinFile *DynOS_Bin_Decompress(const SysPath &aFilename) {
DynOS_Bin_Compress_Init();
// Check modfs
if (is_mod_fs_file(aFilename.c_str())) {
return DynOS_Bin_Decompress_ModFs(aFilename);
}
// Open input file
if (!DynOS_Bin_Compress_Check(
(sFile = f_open_r(aFilename.c_str())) != NULL,

View file

@ -405,6 +405,9 @@ s64 DynOS_Gfx_ParseGfxConstants(const String& _Arg, bool* found) {
gfx_constant(G_LIGHT_MAP_EXT);
gfx_constant(G_LIGHTING_ENGINE_EXT);
gfx_constant(G_PACKED_NORMALS_EXT);
gfx_constant(G_CULL_INVERT_EXT);
gfx_constant(G_FRESNEL_COLOR_EXT);
gfx_constant(G_FRESNEL_ALPHA_EXT);
gfx_constant(G_COL_PRIM);
gfx_constant(G_COL_ENV);
@ -1211,7 +1214,7 @@ static String ResolveParam(lua_State *L, GfxData *aGfxData, u32 paramIndex, char
case GFX_PARAM_TYPE_TEX: return ConvertParam<Texture *>(
L, aGfxData, paramIndex,
"Texture pointer",
[] (lua_State *L, u32 paramIndex) { return (Texture *) smlua_to_cpointer(L, paramIndex, LVT_U8_P); },
[] (lua_State *L, u32 paramIndex) { return (Texture *) smlua_to_cpointer(L, paramIndex, LVT_TEXTURE_P); },
[&aGfxData] (Texture *texture) { return CreateRawPointerDataNode(aGfxData, texture); }
);

View file

@ -641,6 +641,15 @@ static LevelScript ParseLevelScriptSymbolArg(GfxData* aGfxData, DataNode<LevelSc
return; \
}
static LevelScript ParseLevelScriptObjectSymbolArgInternal(GfxData* aGfxData, DataNode<LevelScript>* aNode, u64& aTokenIndex, u32 *luaParams, u32 luaParamFlag) {
bool foundParam = true;
LevelScript value = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundParam);
if (!foundParam) {
*luaParams |= luaParamFlag;
}
return value;
}
static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNode, LevelScript*& aHead, u64& aTokenIndex, Array<u64>& aSwitchNodes) {
const String& _Symbol = aNode->mTokens[aTokenIndex++];
@ -711,7 +720,6 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(CMD2D);
lvl_symbol_1(TERRAIN, 1);
lvl_symbol_1(ROOMS, 1);
lvl_symbol_2(SHOW_DIALOG, 0, 0);
lvl_symbol_1(TERRAIN_TYPE, 0);
lvl_symbol_0(NOP);
@ -733,75 +741,75 @@ static void ParseLevelScriptSymbol(GfxData* aGfxData, DataNode<LevelScript>* aNo
lvl_symbol_0(ADV_DEMO);
lvl_symbol_0(CLEAR_DEMO_PTR);
// object
if (_Symbol == "OBJECT") {
// dialog
if (_Symbol == "SHOW_DIALOG") {
u64 topTokenIndex = aTokenIndex;
u32 luaParams = 0;
LevelScript index = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, SHOW_DIALOG_EXT_LUA_INDEX);
LevelScript dialogId = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, SHOW_DIALOG_EXT_LUA_DIALOG);
bool foundModel = true;
bool foundBeh = true;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh);
if (luaParams != 0) {
LevelScript finalIndex = (luaParams & SHOW_DIALOG_EXT_LUA_INDEX) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : index;
LevelScript finalDialogId = (luaParams & SHOW_DIALOG_EXT_LUA_DIALOG) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : dialogId;
if (foundModel && foundBeh) {
aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else if (foundModel) {
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex) };
LevelScript _Ls[] = { SHOW_DIALOG_EXT(luaParams, finalIndex, finalDialogId) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]);
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_EXT2(modelIndex, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex) };
LevelScript _Ls[] = { SHOW_DIALOG(index, dialogId) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
// object with acts
if (_Symbol == "OBJECT_WITH_ACTS") {
// object
if (_Symbol == "OBJECT" || _Symbol == "OBJECT_WITH_ACTS") {
u64 topTokenIndex = aTokenIndex;
bool foundModel = true;
bool foundBeh = true;
LevelScript model = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundModel);
LevelScript posX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript posZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleX = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleY = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript angleZ = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript behParam = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
LevelScript beh = ParseLevelScriptSymbolArgInternal(aGfxData, aNode, aTokenIndex, &foundBeh);
LevelScript acts = ParseLevelScriptSymbolArg(aGfxData, aNode, aTokenIndex);
u32 luaParams = 0;
LevelScript model = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_MODEL);
LevelScript posX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_X);
LevelScript posY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Y);
LevelScript posZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_POS_Z);
LevelScript angleX = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_X);
LevelScript angleY = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Y);
LevelScript angleZ = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ANGLE_Z);
LevelScript behParam = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEH_PARAMS);
LevelScript beh = ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_BEHAVIOR);
LevelScript acts = (_Symbol == "OBJECT_WITH_ACTS") ? ParseLevelScriptObjectSymbolArgInternal(aGfxData, aNode, aTokenIndex, &luaParams, OBJECT_EXT_LUA_ACTS) : 0x1F;
if (foundModel && foundBeh) {
// At least one parameter is a Lua variable, use OBJECT_EXT_LUA_PARAMS
if (luaParams != 0) {
// Remember behavior pointer if it's not a Lua param
if (!(luaParams & OBJECT_EXT_LUA_BEHAVIOR)) {
aGfxData->mPointerList.Add(aHead + 9);
}
LevelScript finalModel = (luaParams & OBJECT_EXT_LUA_MODEL) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 1, aNode->mTokens[topTokenIndex + 0]) : model;
LevelScript finalPosX = (luaParams & OBJECT_EXT_LUA_POS_X) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 2, aNode->mTokens[topTokenIndex + 1]) : posX;
LevelScript finalPosY = (luaParams & OBJECT_EXT_LUA_POS_Y) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 3, aNode->mTokens[topTokenIndex + 2]) : posY;
LevelScript finalPosZ = (luaParams & OBJECT_EXT_LUA_POS_Z) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 4, aNode->mTokens[topTokenIndex + 3]) : posZ;
LevelScript finalAngleX = (luaParams & OBJECT_EXT_LUA_ANGLE_X) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 4]) : angleX;
LevelScript finalAngleY = (luaParams & OBJECT_EXT_LUA_ANGLE_Y) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 5]) : angleY;
LevelScript finalAngleZ = (luaParams & OBJECT_EXT_LUA_ANGLE_Z) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 7, aNode->mTokens[topTokenIndex + 6]) : angleZ;
LevelScript finalBehParam = (luaParams & OBJECT_EXT_LUA_BEH_PARAMS) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 8, aNode->mTokens[topTokenIndex + 7]) : behParam;
LevelScript finalBeh = (luaParams & OBJECT_EXT_LUA_BEHAVIOR) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 9, aNode->mTokens[topTokenIndex + 8]) : beh;
LevelScript finalActs = (luaParams & OBJECT_EXT_LUA_ACTS) ? DynOS_Lua_RememberVariable(aGfxData, aHead + 10, aNode->mTokens[topTokenIndex + 9]) : acts;
LevelScript _Ls[] = { OBJECT_EXT_LUA_PARAMS(luaParams, finalModel, finalPosX, finalPosY, finalPosZ, finalAngleX, finalAngleY, finalAngleZ, finalBehParam, finalBeh, finalActs) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
// No Lua parameter, use OBJECT_WITH_ACTS
else {
aGfxData->mPointerList.Add(aHead + 5);
LevelScript _Ls[] = { OBJECT_WITH_ACTS(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else if (foundModel) {
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT(model, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
} else {
u32 modelIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 5, aNode->mTokens[topTokenIndex + 0]);
u32 behIndex = DynOS_Lua_RememberVariable(aGfxData, aHead + 6, aNode->mTokens[topTokenIndex + 8]);
LevelScript _Ls[] = { OBJECT_WITH_ACTS_EXT2(modelIndex, posX, posY, posZ, angleX, angleY, angleZ, behParam, behIndex, acts) };
memcpy(aHead, _Ls, sizeof(_Ls));
aHead += (sizeof(_Ls) / sizeof(_Ls[0]));
}
return;
}
@ -1063,12 +1071,12 @@ static DataNode<LevelScript>* DynOS_Lvl_Load(BinFile *aFile, GfxData *aGfxData)
void *_Ptr = DynOS_Pointer_Load(aFile, aGfxData, _Value, FUNCTION_LVL, &_Node->mFlags);
if (_Ptr) {
if (!requirePointer) {
if (!requirePointer && _Value != LUA_VAR_CODE) {
PrintError("Didn't expect a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value);
}
_Node->mData[i] = (uintptr_t) _Ptr;
} else {
if (requirePointer) {
if (requirePointer && _Value != LUA_VAR_CODE) {
PrintError("Expected a pointer while reading level script: %s, %u", _Node->mName.begin(), _Value);
_Node->mData[i] = 0;
} else {

View file

@ -134,6 +134,8 @@ static void LvlCmd_Init() {
ADD_COMMAND(OBJECT_EXT2(POINTER, 0, 0, 0, 0, 0, 0, 0, POINTER));
ADD_COMMAND(LOAD_MODEL_FROM_GEO_EXT(0, POINTER));
ADD_COMMAND(JUMP_AREA_EXT(0, 0, POINTER));
ADD_COMMAND(OBJECT_EXT_LUA_PARAMS(0, 0, 0, 0, 0, 0, 0, 0, 0, POINTER, 0));
ADD_COMMAND(SHOW_DIALOG_EXT(0, 0, 0))
}
void DynOS_Lvl_Validate_Begin() {

View file

@ -2,8 +2,11 @@
extern "C" {
#define STB_IMAGE_WRITE_IMPLEMENTATION
#include "stb/stb_image_write.h"
#include "pc/mods/mod_fs.h"
}
#define PNG_SIGNATURE 0x0A1A0A0D474E5089llu
///////////
// Utils //
///////////
@ -304,46 +307,67 @@ DataNode<TexData>* DynOS_Tex_LoadFromBinary(const SysPath &aPackFolder, const Sy
// Load data from binary file
DataNode<TexData>* _TexNode = NULL;
BinFile *_File = BinFile::OpenR(aFilename.c_str());
BinFile *_File = NULL;
if (is_mod_fs_file(aFilename.c_str())) {
void *_Buffer = NULL;
u32 _Size = 0;
if (mod_fs_read_file_from_uri(aFilename.c_str(), &_Buffer, &_Size)) {
_File = BinFile::OpenB((const u8 *) _Buffer, _Size);
free(_Buffer);
}
} else {
_File = BinFile::OpenR(aFilename.c_str());
}
if (!_File) { return NULL; }
u8 type = _File->Read<u8>();
if (type == DATA_TYPE_TEXTURE) {
// load png-texture
_TexNode = New<DataNode<TexData>>();
_TexNode->mData = New<TexData>();
_TexNode->mName.Read(_File);
_TexNode->mData = New<TexData>();
_TexNode->mData->mPngData.Read(_File);
BinFile::Close(_File);
} else if (type == DATA_TYPE_TEXTURE_RAW) {
// load raw-texture
_TexNode = New<DataNode<TexData>>();
_TexNode->mName.Read(_File);
_TexNode->mData = New<TexData>();
_TexNode->mData->mRawFormat = _File->Read<s32>();
_TexNode->mData->mRawSize = _File->Read<s32>();
_TexNode->mData->mRawWidth = _File->Read<s32>();
_TexNode->mData->mRawHeight = _File->Read<s32>();
_TexNode->mData->mRawData.Read(_File);
} else if ((_File->SetOffset(0), _File->Read<u64>() == PNG_SIGNATURE)) {
_File->SetOffset(0);
// load PNG file
_TexNode = New<DataNode<TexData>>();
_TexNode->mName = aFilename.c_str();
_TexNode->mData = New<TexData>();
_TexNode->mData->mPngData.Resize(_File->Size());
_File->Read<u8>(_TexNode->mData->mPngData.begin(), _File->Size());
}
BinFile::Close(_File);
if (_TexNode) {
// For some reason texture nodes are indexed to DynosCustomTexs by their node name,
// and not by `aTexName`, but DynOS_Tex_Get searches for `aTexName`...
// Normally, this doesn't cause any issue, but things go wrong when `aTexName`
// is not the same as the texture node name (which is the case for modfs files).
if (is_mod_fs_file(aFilename.c_str())) {
_TexNode->mName = aTexName;
}
if (aAddToPack) {
if (!_Pack) { _Pack = DynOS_Pack_Add(aPackFolder); }
DynOS_Pack_AddTex(_Pack, _TexNode);
}
return _TexNode;
} else if (type != DATA_TYPE_TEXTURE_RAW) {
BinFile::Close(_File);
return NULL;
}
// load raw-texture
_TexNode = New<DataNode<TexData>>();
_TexNode->mData = New<TexData>();
_TexNode->mName.Read(_File);
_TexNode->mData->mRawFormat = _File->Read<s32>();
_TexNode->mData->mRawSize = _File->Read<s32>();
_TexNode->mData->mRawWidth = _File->Read<s32>();
_TexNode->mData->mRawHeight = _File->Read<s32>();
_TexNode->mData->mRawData.Read(_File);
BinFile::Close(_File);
if (aAddToPack) {
if (!_Pack) { _Pack = DynOS_Pack_Add(aPackFolder); }
DynOS_Pack_AddTex(_Pack, _TexNode);
}
return _TexNode;

View file

@ -115,8 +115,8 @@ void dynos_actor_override(struct Object* obj, void** aSharedChild) {
DynOS_Actor_Override(obj, aSharedChild);
}
void dynos_add_actor_custom(s32 modIndex, s32 modFileIndex, const char *filePath, const char* geoName) {
DynOS_Actor_AddCustom(modIndex, modFileIndex, filePath, geoName);
bool dynos_add_actor_custom(s32 modIndex, s32 modFileIndex, const char *filePath, const char* geoName) {
return DynOS_Actor_AddCustom(modIndex, modFileIndex, filePath, geoName);
}
const void* dynos_geolayout_get(const char *name) {
@ -133,8 +133,8 @@ void dynos_actor_register_modified_graph_node(struct GraphNode *node) {
// -- collisions -- //
void dynos_add_collision(const char *filePath, const char* collisionName) {
DynOS_Col_Activate(filePath, collisionName);
bool dynos_add_collision(const char *filePath, const char* collisionName) {
return DynOS_Col_Activate(filePath, collisionName);
}
Collision* dynos_collision_get(const char* collisionName) {
@ -143,9 +143,9 @@ Collision* dynos_collision_get(const char* collisionName) {
// -- textures -- //
void dynos_add_texture(const char *filePath, const char* textureName) {
bool dynos_add_texture(const char *filePath, const char* textureName) {
SysPath _FilePath = filePath;
DynOS_Tex_AddCustom(_FilePath, textureName);
return DynOS_Tex_AddCustom(_FilePath, textureName);
}
bool dynos_texture_get(const char* textureName, struct TextureInfo* outTextureInfo) {
@ -292,6 +292,10 @@ Gfx *dynos_gfx_get(const char *name, u32 *outLength) {
return DynOS_Gfx_Get(name, outLength);
}
const char *dynos_gfx_get_name(Gfx *gfx) {
return DynOS_Gfx_GetName(gfx);
}
Gfx *dynos_gfx_create(const char *name, u32 length) {
return DynOS_Gfx_Create(name, length);
}
@ -312,6 +316,10 @@ Vtx *dynos_vtx_get(const char *name, u32 *outCount) {
return DynOS_Vtx_Get(name, outCount);
}
const char *dynos_vtx_get_name(Vtx *vtx) {
return DynOS_Vtx_GetName(vtx);
}
Vtx *dynos_vtx_create(const char *name, u32 count) {
return DynOS_Vtx_Create(name, count);
}

View file

@ -9,6 +9,7 @@ extern "C" {
#include "game/object_list_processor.h"
#include "pc/configfile.h"
#include "pc/lua/smlua_hooks.h"
#include "pc/mods/mod_fs.h"
}
// Static maps/arrays
@ -31,7 +32,7 @@ std::map<const void *, ActorGfx> &DynOS_Actor_GetValidActors() {
return DynosValidActors();
}
void DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFilename, const char *aActorName) {
bool DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFilename, const char *aActorName) {
const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName);
u16 actorLen = strlen(aActorName);
@ -42,7 +43,7 @@ void DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFil
if (!_GfxData) {
PrintError(" ERROR: Couldn't load Actor Binary \"%s\" from \"%s\"", actorName, aFilename.c_str());
free(actorName);
return;
return false;
}
_GfxData->mModIndex = aModIndex;
_GfxData->mModFileIndex = aModFileIndex;
@ -51,7 +52,7 @@ void DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFil
if (!geoLayout) {
PrintError(" ERROR: Couldn't load geo layout for \"%s\"", actorName);
free(actorName);
return;
return false;
}
// Alloc and init the actors gfx list
@ -63,7 +64,7 @@ void DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFil
if (!actorGfx.mGraphNode) {
PrintError(" ERROR: Couldn't load graph node for \"%s\"", actorName);
free(actorName);
return;
return false;
}
actorGfx.mGraphNode->georef = georef;
@ -76,6 +77,7 @@ void DynOS_Actor_AddCustom(s32 aModIndex, s32 aModFileIndex, const SysPath &aFil
// Add to list
DynOS_Actor_Valid(georef, actorGfx);
free(actorName);
return true;
}
const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) {
@ -115,6 +117,13 @@ const void *DynOS_Actor_GetLayoutFromName(const char *aActorName) {
}
}
// check modfs file
if (is_mod_fs_file(aActorName)) {
if (DynOS_Actor_AddCustom(gLuaActiveMod->index, -1, aActorName, aActorName)) {
return DynOS_Actor_GetLayoutFromName(aActorName);
}
}
return NULL;
}
@ -222,7 +231,6 @@ void DynOS_Actor_Override(struct Object* obj, void** aSharedChild) {
}
}
*aSharedChild = (void*)it->second.mGraphNode;
}

View file

@ -1,17 +1,21 @@
#include "dynos.cpp.h"
extern "C" {
#include "pc/mods/mod_fs.h"
}
static Array<Pair<const char*, DataNode<Collision>*>>& DynosCollisions() {
static Array<Pair<const char*, DataNode<Collision>*>> sDynosCollisions;
return sDynosCollisions;
}
void DynOS_Col_Activate(const SysPath &aFilename, const char *aCollisionName) {
bool DynOS_Col_Activate(const SysPath &aFilename, const char *aCollisionName) {
auto& _DynosCollisions = DynosCollisions();
// check for duplicates
for (s32 i = 0; i < _DynosCollisions.Count(); ++i) {
if (!strcmp(_DynosCollisions[i].first, aCollisionName)) {
return;
return true;
}
}
@ -24,11 +28,12 @@ void DynOS_Col_Activate(const SysPath &aFilename, const char *aCollisionName) {
DataNode<Collision>* _Node = DynOS_Col_LoadFromBinary(aFilename, collisionName);
if (!_Node) {
free(collisionName);
return;
return false;
}
// Add to collisions
_DynosCollisions.Add({ collisionName, _Node });
return true;
}
Collision* DynOS_Col_Get(const char* collisionName) {
@ -51,6 +56,13 @@ Collision* DynOS_Col_Get(const char* collisionName) {
}
}
// check modfs file
if (is_mod_fs_file(collisionName)) {
if (DynOS_Col_Activate(collisionName, collisionName)) {
return DynOS_Col_Get(collisionName);
}
}
// check builtin collisions
return (Collision*)DynOS_Builtin_Col_GetFromName(collisionName);
}

View file

@ -3,6 +3,7 @@
extern "C" {
#include "pc/lua/smlua.h"
#include "pc/lua/utils/smlua_gfx_utils.h"
#include "pc/mods/mods.h"
}
struct MapNode {
@ -13,6 +14,7 @@ struct MapNode {
// Maps read-only Gfx and Vtx buffers to their writable duplicates
static std::map<const void *, struct MapNode> sRomToRamGfxVtxMap;
static std::map<const void *, const void *> sRamToRomGfxVtxMap; // Reverse map for duplicate to vanilla lookup
static Vtx *DynOS_Vtx_Duplicate(Vtx *aVtx, u32 vtxCount, bool shouldDuplicate) {
if (!aVtx) { return NULL; }
@ -29,6 +31,7 @@ static Vtx *DynOS_Vtx_Duplicate(Vtx *aVtx, u32 vtxCount, bool shouldDuplicate) {
Vtx *vtxDuplicate = vtx_allocate_internal(NULL, vtxCount);
memcpy(vtxDuplicate, aVtx, vtxSize);
sRomToRamGfxVtxMap[aVtx] = { (void *) vtxDuplicate, vtxSize, NULL };
sRamToRomGfxVtxMap[vtxDuplicate] = aVtx;
return vtxDuplicate;
}
@ -81,6 +84,7 @@ static Gfx *DynOS_Gfx_Duplicate(Gfx *aGfx, bool shouldDuplicate) {
Gfx *gfxCopy = (Gfx *) malloc(gfxSize);
memcpy(gfxCopy, gfxDuplicate, gfxSize);
sRomToRamGfxVtxMap[aGfx] = { (void *) gfxDuplicate, gfxSize, gfxCopy };
sRamToRomGfxVtxMap[gfxDuplicate] = aGfx;
}
return gfxDuplicate;
@ -136,24 +140,20 @@ Gfx *DynOS_Gfx_Get(const char *aName, u32 *outLength) {
// Check levels
for (auto &lvl : DynOS_Lvl_GetArray()) {
if (modIndex == -1 || lvl.second->mModIndex == modIndex) {
for (auto &gfx : lvl.second->mDisplayLists) {
if (gfx->mName == aName) {
*outLength = gfx->mSize;
return gfx->mData;
}
for (auto &gfx : lvl.second->mDisplayLists) {
if (gfx->mName == aName) {
*outLength = gfx->mSize;
return gfx->mData;
}
}
}
// Check loaded actors
for (auto &actor : DynOS_Actor_GetValidActors()) {
if (modIndex == -1 || actor.second.mGfxData->mModIndex == modIndex) {
for (auto &gfx : actor.second.mGfxData->mDisplayLists) {
if (gfx->mName == aName) {
*outLength = gfx->mSize;
return gfx->mData;
}
for (auto &gfx : actor.second.mGfxData->mDisplayLists) {
if (gfx->mName == aName) {
*outLength = gfx->mSize;
return gfx->mData;
}
}
}
@ -176,6 +176,42 @@ Gfx *DynOS_Gfx_Get(const char *aName, u32 *outLength) {
return NULL;
}
const char *DynOS_Gfx_GetName(Gfx *aGfx) {
if (!aGfx) { return NULL; }
s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1);
// Check mod data
static std::string outName;
if (sModsDisplayLists.GetName(modIndex, aGfx, outName)) {
return outName.c_str();
}
// Check levels
for (auto &lvl : DynOS_Lvl_GetArray()) {
for (auto &gfx : lvl.second->mDisplayLists) {
if (gfx->mData == aGfx) {
return gfx->mName.begin();
}
}
}
// Check loaded actors
for (auto &actor : DynOS_Actor_GetValidActors()) {
for (auto &gfx : actor.second.mGfxData->mDisplayLists) {
if (gfx->mData == aGfx) {
return gfx->mName.begin();
}
}
}
// Check vanilla display lists
auto it = sRamToRomGfxVtxMap.find(aGfx);
if (it != sRamToRomGfxVtxMap.end()) {
return DynOS_Builtin_Gfx_GetFromData((const Gfx *) it->second);
}
return DynOS_Builtin_Gfx_GetFromData(aGfx);
}
Gfx *DynOS_Gfx_Create(const char *aName, u32 aLength) {
s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1);
return sModsDisplayLists.Create(modIndex, aName, aLength);
@ -240,24 +276,51 @@ Vtx *DynOS_Vtx_Get(const char *aName, u32 *outCount) {
// Check levels
for (auto &lvl : DynOS_Lvl_GetArray()) {
if (modIndex == -1 || lvl.second->mModIndex == modIndex) {
for (auto &vtx : lvl.second->mVertices) {
if (vtx->mName == aName) {
*outCount = vtx->mSize;
return vtx->mData;
}
for (auto &vtx : lvl.second->mVertices) {
if (vtx->mName == aName) {
*outCount = vtx->mSize;
return vtx->mData;
}
}
}
// Check loaded actors
for (auto &actor : DynOS_Actor_GetValidActors()) {
if (modIndex == -1 || actor.second.mGfxData->mModIndex == modIndex) {
for (auto &vtx : actor.second.mGfxData->mVertices) {
if (vtx->mName == aName) {
*outCount = vtx->mSize;
return vtx->mData;
}
for (auto &vtx : actor.second.mGfxData->mVertices) {
if (vtx->mName == aName) {
*outCount = vtx->mSize;
return vtx->mData;
}
}
}
return NULL;
}
const char *DynOS_Vtx_GetName(Vtx *aVtx) {
if (!aVtx) { return NULL; }
s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1);
// Check mod data
static std::string outName;
if (sModsVertexBuffers.GetName(modIndex, aVtx, outName)) {
return outName.c_str();
}
// Check levels
for (auto &lvl : DynOS_Lvl_GetArray()) {
for (auto &vtx : lvl.second->mVertices) {
if (vtx->mData == aVtx) {
return vtx->mName.begin();
}
}
}
// Check loaded actors
for (auto &actor : DynOS_Actor_GetValidActors()) {
for (auto &vtx : actor.second.mGfxData->mVertices) {
if (vtx->mData == aVtx) {
return vtx->mName.begin();
}
}
}

View file

@ -135,7 +135,6 @@ public:
mMapNameToItem.clear();
}
private:
ModDataResult<ModDataItem<T> *> Find(T *aPointer, std::string &outName) {
if (!aPointer) {
return { NULL, DYNOS_MOD_DATA_ERROR_POINTER_IS_NULL };
@ -151,6 +150,7 @@ private:
return { NULL, 0 };
}
private:
ModDataResult<ModDataItem<T> *> FindAvailableItem() {
// Create pool if it doesn't exist yet
@ -212,6 +212,16 @@ public:
return getResult.first->mBuffer;
}
bool GetName(s32 aModIndex, T *aPointer, std::string &outName) {
ModDataT *modData = GetModData(aModIndex);
auto findResult = modData->Find(aPointer, outName);
if (!findResult.first) {
gDynosModDataLastError = findResult.second;
return false;
}
return true;
}
T *Create(s32 aModIndex, const char *aName, u32 aSize) {
ModDataT *modData = GetModData(aModIndex);
auto createResult = modData->Create(aName, aSize);

View file

@ -4,6 +4,7 @@
extern "C" {
#include "pc/gfx/gfx.h"
#include "pc/gfx/gfx_rendering_api.h"
#include "pc/mods/mod_fs.h"
}
struct OverrideTexture {
@ -423,13 +424,13 @@ void DynOS_Tex_Deactivate(DataNode<TexData>* aNode) {
_Schedule.Add(aNode);
}
void DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName) {
bool DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName) {
auto& _DynosCustomTexs = DynosCustomTexs();
// check for duplicates
for (s32 i = 0; i < _DynosCustomTexs.Count(); ++i) {
if (!strcmp(_DynosCustomTexs[i].first, aTexName)) {
return;
return true;
}
}
@ -444,7 +445,9 @@ void DynOS_Tex_AddCustom(const SysPath &aFilename, const char *aTexName) {
free(_TexName);
if (_Node) {
DynOS_Tex_Activate(_Node, true);
return true;
}
return false;
}
#define CONVERT_TEXINFO(texName) { \
@ -488,6 +491,13 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) {
}
}
// check modfs file
if (is_mod_fs_file(aTexName)) {
if (DynOS_Tex_AddCustom(aTexName, aTexName)) {
return DynOS_Tex_Get(aTexName, aOutTexInfo);
}
}
// check builtin textures
const struct BuiltinTexInfo* info = DynOS_Builtin_Tex_GetInfoFromName(aTexName);
if (!info) {
@ -503,7 +513,7 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) {
aOutTexInfo->bitSize = info->bitSize;
aOutTexInfo->width = info->width;
aOutTexInfo->height = info->height;
aOutTexInfo->texture = (u8*)info->pointer;
aOutTexInfo->texture = (Texture*)info->pointer;
aOutTexInfo->name = aTexName;
return true;
}
@ -522,7 +532,7 @@ bool DynOS_Tex_GetFromData(const Texture *aTex, struct TextureInfo* aOutTexInfo)
aOutTexInfo->bitSize = info->bitSize;
aOutTexInfo->width = info->width;
aOutTexInfo->height = info->height;
aOutTexInfo->texture = (u8*)info->pointer;
aOutTexInfo->texture = (Texture*)info->pointer;
aOutTexInfo->name = info->identifier;
return true;
}

View file

@ -1,190 +0,0 @@
import os, sys, re
MOD_FS_MAGIC = "MODFSSM64COOPDX"
MOD_FS_HEADER_SIZE = 32
MOD_FS_EXTENSION = ".modfs"
MOD_FS_VERSION = 1
MOD_FS_MAX_SIZE = 0x1000000
MOD_FS_MAX_FILES = 0x100
MOD_FS_MAX_PATH = 0x100
def usage():
print("""
Directory to modfs:
python dir2modfs.py <dirpath> [--set-public] [--set-file-public <files>...]
Parameters:
dirpath Path to directory to turn into a .modfs file
Options:
--set-public Set modfs file as public (readable by other mods)
--set-file-public <files> Set the provided files as public (readable by other mods)
modfs to directory:
python dir2modfs.py <filepath> --extract
Parameters:
filepath Path to modfs file to extract files from
""")
exit(0)
def is_binary_file(bytes: bytes):
textchars = bytearray({0x07, 0x08, 0x09, 0x0A, 0x0C, 0x0D, 0x1B} | set(range(0x20, 0x100)) - {0x7F})
return bool(bytes.translate(None, textchars))
def get_files(dirpath: str, public_files: list):
files = []
for root, _, filenames in os.walk(dirpath):
for filename in filenames:
relpath = os.path.join(root, filename)
filepath = relpath.removeprefix(dirpath).strip("/\\").replace('\\', '/')
is_public = False
for public_file in public_files:
if re.match(public_file, relpath) or re.match(public_file, filepath):
is_public = True
break
files.append({
"relpath": relpath,
"filepath": filepath,
"is_public": is_public,
"is_text": False,
"data": None
})
return files
def convert(dirpath: str, set_public: bool, public_files: list):
dirpath = dirpath.rstrip("/\\")
files = sorted(get_files(dirpath, public_files), key=lambda file: file["filepath"])
if len(files) > MOD_FS_MAX_FILES:
raise Exception(f"Max number of files exceeded: {len(files)} (max is: {MOD_FS_MAX_FILES})")
total_size = 0
for file in files:
filepath = file["filepath"]
if len(filepath) >= MOD_FS_MAX_PATH:
raise Exception(f"{filepath} - Exceeded filepath length: {len(filepath)} (max is: {MOD_FS_MAX_PATH-1})")
with open(file["relpath"], "rb") as f:
data = f.read()
total_size += len(data)
if total_size > MOD_FS_MAX_SIZE:
raise Exception(f"{filepath} - Total size exceeded: {total_size} (max is: {MOD_FS_MAX_SIZE})")
file["data"] = data
file["is_text"] = not is_binary_file(data)
# write file
destpath = dirpath + MOD_FS_EXTENSION
with open(destpath, "wb") as f:
# magic + version
f.write(MOD_FS_MAGIC.encode())
f.write(MOD_FS_VERSION.to_bytes(1, byteorder="little", signed=False))
# header
f.write(len(files).to_bytes(2, byteorder="little", signed=False))
f.write(set_public.to_bytes(1, byteorder="little", signed=False))
# padding (empty space for future versions)
padding = MOD_FS_HEADER_SIZE - f.tell()
f.write(b'\0' * padding)
# files
for file in files:
# filepath
f.write(len(file["filepath"]).to_bytes(2, byteorder="little", signed=False))
f.write(file["filepath"].encode())
# data
f.write(len(file["data"]).to_bytes(4, byteorder="little", signed=False))
f.write(file["is_public"].to_bytes(1, byteorder="little", signed=False))
f.write(file["is_text"].to_bytes(1, byteorder="little", signed=False))
f.write(file["data"])
# summary
print("")
print(f"Directory: {dirpath}")
print(f"Num files: {len(files)}")
print(f"Total size: {total_size}")
print(f"Is public: {set_public}")
filepaths_max = max(8, len(max([file["filepath"] for file in files], key=len)))
sizes_max = max(4, len(max([str(len(file["data"])) for file in files], key=len)))
print("")
print(f"{'FILEPATH'.ljust(filepaths_max)} {'SIZE'.rjust(sizes_max)} {'TEXT'.rjust(5)} {'PUBLIC'.rjust(6)}")
print(f"{'--------'.ljust(filepaths_max)} {'----'.rjust(sizes_max)} {'----'.rjust(5)} {'------'.rjust(6)}")
for file in files:
filepath = file["filepath"]
size = str(len(file["data"]))
is_text = str(file["is_text"])
is_public = str(file["is_public"])
print(f"{filepath.ljust(filepaths_max)} {size.rjust(sizes_max)} {is_text.rjust(5)} {is_public.rjust(6)}")
def extract(filepath: str):
if not filepath.endswith(MOD_FS_EXTENSION):
raise Exception("Not a modfs file")
with open(filepath, "rb") as f:
# magic + version
magic = f.read(len(MOD_FS_MAGIC)).decode()
if magic != MOD_FS_MAGIC:
raise Exception("Not a modfs file")
version = int.from_bytes(f.read(1), byteorder="little", signed=False)
if version != MOD_FS_VERSION:
raise Exception("Version mismatch")
# header
num_files = int.from_bytes(f.read(2), byteorder="little", signed=False)
is_public = bool.from_bytes(f.read(1), byteorder="little", signed=False)
# padding (empty space for future versions)
f.seek(MOD_FS_HEADER_SIZE, 0)
# create directory
dirpath = filepath.removesuffix(MOD_FS_EXTENSION)
os.makedirs(dirpath, exist_ok=True)
# files
for _ in range(num_files):
# filepath
filepath_len = int.from_bytes(f.read(2), byteorder="little", signed=False)
filepath = os.path.join(dirpath, f.read(filepath_len).decode())
# data
file_size = int.from_bytes(f.read(4), byteorder="little", signed=False)
file_is_public = bool.from_bytes(f.read(1), byteorder="little", signed=False)
file_is_text = bool.from_bytes(f.read(1), byteorder="little", signed=False)
file_data = f.read(file_size)
# write file
os.makedirs(os.path.dirname(filepath), exist_ok=True)
with open(filepath, "wb") as g:
g.write(file_data)
print(f"Extracted file of size {file_size} to: {filepath}")
def main(argc: int, argv: list):
if argc < 2:
usage()
if "--extract" in argv:
extract(argv[1])
else:
set_public = "--set-public" in argv
set_file_public_index = argv.index("--set-file-public") if "--set-file-public" in argv else argc
convert(argv[1], set_public, argv[set_file_public_index+1:])
if __name__ == "__main__":
main(len(sys.argv), sys.argv)

View file

@ -1335,6 +1335,7 @@
- GRAPH_RENDER_CYLBOARD
- GRAPH_RENDER_PLAYER
- GRAPH_EXTRA_FORCE_3D
- GRAPH_EXTRA_ROTATE_HELD
- GRAPH_NODE_TYPE_FUNCTIONAL
- GRAPH_NODE_TYPE_400
- GRAPH_NODE_TYPE_ROOT
@ -2143,6 +2144,8 @@
- MOD_FS_MAX_SIZE
- MOD_FS_MAX_FILES
- MOD_FS_MAX_PATH
- MOD_FS_URI_PREFIX
- MOD_FS_URI_FORMAT
### [enum ModFsFileIntType](#ModFsFileIntType)
| Identifier | Value |
@ -2969,6 +2972,7 @@
<br />
## [player_palette.h](#player_palette.h)
- PALETTES_DIRECTORY
- MAX_PRESET_PALETTES
### [enum PlayerPart](#PlayerPart)
@ -4619,6 +4623,7 @@
- SURFACE_CLASS_NOT_SLIPPERY
- SURFACE_FLAG_DYNAMIC
- SURFACE_FLAG_NO_CAM_COLLISION
- SURFACE_FLAG_INTANGIBLE
- SURFACE_FLAG_X_PROJECTION
- HAZARD_TYPE_LAVA_FLOOR
- HAZARD_TYPE_LAVA_WALL
@ -4720,6 +4725,12 @@
- VERSION_TEXT
- VERSION_NUMBER
- MINOR_VERSION_NUMBER
- GAME_NAME
- WINDOW_NAME
- GAME_NAME
- WINDOW_NAME
- GAME_NAME
- WINDOW_NAME
- MAX_VERSION_LENGTH
[:arrow_up_small:](#)

View file

@ -15,5 +15,6 @@ Gfx shape_template_dl[] = {
/* [11] */ gsSPDisplayList(NULL),
/* [12] */ gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF),
/* [13] */ gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE),
/* [14] */ gsSPEndDisplayList(),
/* [14] */ gsSPLoadGeometryMode(G_LIGHTING | G_CULL_BACK),
/* [15] */ gsSPEndDisplayList(),
};

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1354,9 +1354,6 @@
- [mod_fs_get](functions-5.md#mod_fs_get)
- [mod_fs_reload](functions-5.md#mod_fs_reload)
- [mod_fs_create](functions-5.md#mod_fs_create)
- [mod_fs_delete](functions-5.md#mod_fs_delete)
- [mod_fs_save](functions-5.md#mod_fs_save)
- [mod_fs_set_public](functions-5.md#mod_fs_set_public)
- [mod_fs_get_filename](functions-5.md#mod_fs_get_filename)
- [mod_fs_get_file](functions-5.md#mod_fs_get_file)
- [mod_fs_create_file](functions-5.md#mod_fs_create_file)
@ -1364,6 +1361,9 @@
- [mod_fs_copy_file](functions-5.md#mod_fs_copy_file)
- [mod_fs_delete_file](functions-5.md#mod_fs_delete_file)
- [mod_fs_clear](functions-5.md#mod_fs_clear)
- [mod_fs_save](functions-5.md#mod_fs_save)
- [mod_fs_delete](functions-5.md#mod_fs_delete)
- [mod_fs_set_public](functions-5.md#mod_fs_set_public)
- [mod_fs_file_read_bool](functions-5.md#mod_fs_file_read_bool)
- [mod_fs_file_read_integer](functions-5.md#mod_fs_file_read_integer)
- [mod_fs_file_read_number](functions-5.md#mod_fs_file_read_number)
@ -1377,9 +1377,11 @@
- [mod_fs_file_write_string](functions-5.md#mod_fs_file_write_string)
- [mod_fs_file_write_line](functions-5.md#mod_fs_file_write_line)
- [mod_fs_file_seek](functions-5.md#mod_fs_file_seek)
- [mod_fs_file_rewind](functions-5.md#mod_fs_file_rewind)
- [mod_fs_file_is_eof](functions-5.md#mod_fs_file_is_eof)
- [mod_fs_file_fill](functions-5.md#mod_fs_file_fill)
- [mod_fs_file_erase](functions-5.md#mod_fs_file_erase)
- [mod_fs_file_set_text_mode](functions-5.md#mod_fs_file_set_text_mode)
- [mod_fs_file_set_public](functions-5.md#mod_fs_file_set_public)
- [mod_fs_hide_errors](functions-5.md#mod_fs_hide_errors)
- [mod_fs_get_last_error](functions-5.md#mod_fs_get_last_error)
@ -1393,6 +1395,7 @@
- [mod_storage_load](functions-5.md#mod_storage_load)
- [mod_storage_load_number](functions-5.md#mod_storage_load_number)
- [mod_storage_load_bool](functions-5.md#mod_storage_load_bool)
- [mod_storage_load_all](functions-5.md#mod_storage_load_all)
- [mod_storage_exists](functions-5.md#mod_storage_exists)
- [mod_storage_remove](functions-5.md#mod_storage_remove)
- [mod_storage_clear](functions-5.md#mod_storage_clear)
@ -1516,232 +1519,232 @@
<br />
- object_helpers.c
- [clear_move_flag](functions-5.md#clear_move_flag)
- [set_room_override](functions-5.md#set_room_override)
- [obj_update_pos_from_parent_transformation](functions-5.md#obj_update_pos_from_parent_transformation)
- [obj_apply_scale_to_matrix](functions-5.md#obj_apply_scale_to_matrix)
- [create_transformation_from_matrices](functions-5.md#create_transformation_from_matrices)
- [obj_set_held_state](functions-5.md#obj_set_held_state)
- [lateral_dist_between_objects](functions-5.md#lateral_dist_between_objects)
- [dist_between_objects](functions-5.md#dist_between_objects)
- [dist_between_object_and_point](functions-5.md#dist_between_object_and_point)
- [cur_obj_forward_vel_approach_upward](functions-5.md#cur_obj_forward_vel_approach_upward)
- [approach_f32_signed](functions-5.md#approach_f32_signed)
- [approach_f32_symmetric](functions-5.md#approach_f32_symmetric)
- [approach_s16_symmetric](functions-5.md#approach_s16_symmetric)
- [cur_obj_rotate_yaw_toward](functions-5.md#cur_obj_rotate_yaw_toward)
- [obj_angle_to_object](functions-5.md#obj_angle_to_object)
- [obj_pitch_to_object](functions-5.md#obj_pitch_to_object)
- [obj_angle_to_point](functions-5.md#obj_angle_to_point)
- [obj_turn_toward_object](functions-5.md#obj_turn_toward_object)
- [obj_set_parent_relative_pos](functions-5.md#obj_set_parent_relative_pos)
- [obj_set_pos](functions-5.md#obj_set_pos)
- [obj_set_angle](functions-5.md#obj_set_angle)
- [obj_set_move_angle](functions-5.md#obj_set_move_angle)
- [obj_set_face_angle](functions-5.md#obj_set_face_angle)
- [obj_set_gfx_angle](functions-5.md#obj_set_gfx_angle)
- [obj_set_gfx_pos](functions-5.md#obj_set_gfx_pos)
- [obj_set_gfx_scale](functions-5.md#obj_set_gfx_scale)
- [spawn_water_droplet](functions-5.md#spawn_water_droplet)
- [obj_build_relative_transform](functions-5.md#obj_build_relative_transform)
- [cur_obj_move_using_vel](functions-5.md#cur_obj_move_using_vel)
- [obj_copy_graph_y_offset](functions-5.md#obj_copy_graph_y_offset)
- [obj_copy_pos_and_angle](functions-5.md#obj_copy_pos_and_angle)
- [obj_copy_pos](functions-5.md#obj_copy_pos)
- [obj_copy_angle](functions-5.md#obj_copy_angle)
- [obj_set_gfx_pos_from_pos](functions-5.md#obj_set_gfx_pos_from_pos)
- [obj_init_animation](functions-5.md#obj_init_animation)
- [linear_mtxf_mul_vec3f](functions-5.md#linear_mtxf_mul_vec3f)
- [linear_mtxf_transpose_mul_vec3f](functions-5.md#linear_mtxf_transpose_mul_vec3f)
- [obj_apply_scale_to_transform](functions-5.md#obj_apply_scale_to_transform)
- [obj_copy_scale](functions-5.md#obj_copy_scale)
- [obj_scale_xyz](functions-5.md#obj_scale_xyz)
- [obj_scale](functions-5.md#obj_scale)
- [cur_obj_scale](functions-5.md#cur_obj_scale)
- [cur_obj_init_animation](functions-5.md#cur_obj_init_animation)
- [cur_obj_init_animation_with_sound](functions-5.md#cur_obj_init_animation_with_sound)
- [obj_init_animation_with_accel_and_sound](functions-5.md#obj_init_animation_with_accel_and_sound)
- [cur_obj_init_animation_with_accel_and_sound](functions-5.md#cur_obj_init_animation_with_accel_and_sound)
- [obj_init_animation_with_sound](functions-5.md#obj_init_animation_with_sound)
- [cur_obj_enable_rendering_and_become_tangible](functions-5.md#cur_obj_enable_rendering_and_become_tangible)
- [cur_obj_enable_rendering](functions-5.md#cur_obj_enable_rendering)
- [cur_obj_disable_rendering_and_become_intangible](functions-5.md#cur_obj_disable_rendering_and_become_intangible)
- [cur_obj_disable_rendering](functions-5.md#cur_obj_disable_rendering)
- [cur_obj_unhide](functions-5.md#cur_obj_unhide)
- [cur_obj_hide](functions-5.md#cur_obj_hide)
- [cur_obj_set_pos_relative](functions-5.md#cur_obj_set_pos_relative)
- [cur_obj_set_pos_relative_to_parent](functions-5.md#cur_obj_set_pos_relative_to_parent)
- [cur_obj_enable_rendering_2](functions-5.md#cur_obj_enable_rendering_2)
- [cur_obj_unused_init_on_floor](functions-5.md#cur_obj_unused_init_on_floor)
- [obj_set_face_angle_to_move_angle](functions-5.md#obj_set_face_angle_to_move_angle)
- [get_object_list_from_behavior](functions-5.md#get_object_list_from_behavior)
- [cur_obj_nearest_object_with_behavior](functions-5.md#cur_obj_nearest_object_with_behavior)
- [cur_obj_dist_to_nearest_object_with_behavior](functions-5.md#cur_obj_dist_to_nearest_object_with_behavior)
- [cur_obj_find_nearest_pole](functions-5.md#cur_obj_find_nearest_pole)
- [cur_obj_find_nearest_object_with_behavior](functions-5.md#cur_obj_find_nearest_object_with_behavior)
- [cur_obj_count_objects_with_behavior](functions-5.md#cur_obj_count_objects_with_behavior)
- [find_unimportant_object](functions-5.md#find_unimportant_object)
- [count_unimportant_objects](functions-5.md#count_unimportant_objects)
- [count_objects_with_behavior](functions-5.md#count_objects_with_behavior)
- [find_object_with_behavior](functions-5.md#find_object_with_behavior)
- [cur_obj_find_nearby_held_actor](functions-5.md#cur_obj_find_nearby_held_actor)
- [cur_obj_reset_timer_and_subaction](functions-5.md#cur_obj_reset_timer_and_subaction)
- [cur_obj_change_action](functions-5.md#cur_obj_change_action)
- [cur_obj_set_vel_from_mario_vel](functions-5.md#cur_obj_set_vel_from_mario_vel)
- [cur_obj_reverse_animation](functions-5.md#cur_obj_reverse_animation)
- [cur_obj_extend_animation_if_at_end](functions-5.md#cur_obj_extend_animation_if_at_end)
- [cur_obj_check_if_near_animation_end](functions-5.md#cur_obj_check_if_near_animation_end)
- [cur_obj_check_if_at_animation_end](functions-5.md#cur_obj_check_if_at_animation_end)
- [cur_obj_check_anim_frame](functions-5.md#cur_obj_check_anim_frame)
- [cur_obj_check_anim_frame_in_range](functions-5.md#cur_obj_check_anim_frame_in_range)
- [cur_obj_check_frame_prior_current_frame](functions-5.md#cur_obj_check_frame_prior_current_frame)
- [mario_is_in_air_action](functions-5.md#mario_is_in_air_action)
- [mario_is_dive_sliding](functions-5.md#mario_is_dive_sliding)
- [cur_obj_set_y_vel_and_animation](functions-5.md#cur_obj_set_y_vel_and_animation)
- [cur_obj_unrender_and_reset_state](functions-5.md#cur_obj_unrender_and_reset_state)
- [cur_obj_move_after_thrown_or_dropped](functions-5.md#cur_obj_move_after_thrown_or_dropped)
- [cur_obj_get_thrown_or_placed](functions-5.md#cur_obj_get_thrown_or_placed)
- [cur_obj_get_dropped](functions-5.md#cur_obj_get_dropped)
- [mario_set_flag](functions-5.md#mario_set_flag)
- [cur_obj_clear_interact_status_flag](functions-5.md#cur_obj_clear_interact_status_flag)
- [obj_mark_for_deletion](functions-5.md#obj_mark_for_deletion)
- [cur_obj_disable](functions-5.md#cur_obj_disable)
- [cur_obj_become_intangible](functions-5.md#cur_obj_become_intangible)
- [cur_obj_become_tangible](functions-5.md#cur_obj_become_tangible)
- [obj_become_tangible](functions-5.md#obj_become_tangible)
- [cur_obj_update_floor_height](functions-5.md#cur_obj_update_floor_height)
- [cur_obj_update_floor_height_and_get_floor](functions-5.md#cur_obj_update_floor_height_and_get_floor)
- [apply_drag_to_value](functions-5.md#apply_drag_to_value)
- [cur_obj_apply_drag_xz](functions-5.md#cur_obj_apply_drag_xz)
- [cur_obj_move_xz](functions-5.md#cur_obj_move_xz)
- [cur_obj_move_update_underwater_flags](functions-5.md#cur_obj_move_update_underwater_flags)
- [cur_obj_move_update_ground_air_flags](functions-5.md#cur_obj_move_update_ground_air_flags)
- [cur_obj_move_y_and_get_water_level](functions-5.md#cur_obj_move_y_and_get_water_level)
- [cur_obj_move_y](functions-5.md#cur_obj_move_y)
- [cur_obj_unused_resolve_wall_collisions](functions-5.md#cur_obj_unused_resolve_wall_collisions)
- [abs_angle_diff](functions-5.md#abs_angle_diff)
- [cur_obj_move_xz_using_fvel_and_yaw](functions-5.md#cur_obj_move_xz_using_fvel_and_yaw)
- [cur_obj_move_y_with_terminal_vel](functions-5.md#cur_obj_move_y_with_terminal_vel)
- [cur_obj_compute_vel_xz](functions-5.md#cur_obj_compute_vel_xz)
- [increment_velocity_toward_range](functions-5.md#increment_velocity_toward_range)
- [obj_check_if_collided_with_object](functions-5.md#obj_check_if_collided_with_object)
- [cur_obj_set_behavior](functions-5.md#cur_obj_set_behavior)
- [obj_set_behavior](functions-5.md#obj_set_behavior)
- [cur_obj_has_behavior](functions-5.md#cur_obj_has_behavior)
- [obj_has_behavior](functions-5.md#obj_has_behavior)
- [cur_obj_lateral_dist_from_obj_to_home](functions-5.md#cur_obj_lateral_dist_from_obj_to_home)
- [cur_obj_lateral_dist_from_mario_to_home](functions-5.md#cur_obj_lateral_dist_from_mario_to_home)
- [cur_obj_lateral_dist_to_home](functions-5.md#cur_obj_lateral_dist_to_home)
- [cur_obj_outside_home_square](functions-5.md#cur_obj_outside_home_square)
- [cur_obj_outside_home_rectangle](functions-5.md#cur_obj_outside_home_rectangle)
- [cur_obj_set_pos_to_home](functions-5.md#cur_obj_set_pos_to_home)
- [cur_obj_set_pos_to_home_and_stop](functions-5.md#cur_obj_set_pos_to_home_and_stop)
- [cur_obj_shake_y](functions-5.md#cur_obj_shake_y)
- [cur_obj_start_cam_event](functions-5.md#cur_obj_start_cam_event)
- [set_mario_interact_hoot_if_in_range](functions-5.md#set_mario_interact_hoot_if_in_range)
- [obj_set_billboard](functions-5.md#obj_set_billboard)
- [obj_set_cylboard](functions-5.md#obj_set_cylboard)
- [cur_obj_set_billboard_if_vanilla_cam](functions-5.md#cur_obj_set_billboard_if_vanilla_cam)
- [obj_set_hitbox_radius_and_height](functions-5.md#obj_set_hitbox_radius_and_height)
- [obj_set_hurtbox_radius_and_height](functions-5.md#obj_set_hurtbox_radius_and_height)
- [cur_obj_set_hitbox_radius_and_height](functions-5.md#cur_obj_set_hitbox_radius_and_height)
- [cur_obj_set_hurtbox_radius_and_height](functions-5.md#cur_obj_set_hurtbox_radius_and_height)
- [obj_spawn_loot_coins](functions-5.md#obj_spawn_loot_coins)
- [obj_spawn_loot_blue_coins](functions-5.md#obj_spawn_loot_blue_coins)
- [obj_spawn_loot_yellow_coins](functions-5.md#obj_spawn_loot_yellow_coins)
- [cur_obj_spawn_loot_coin_at_mario_pos](functions-5.md#cur_obj_spawn_loot_coin_at_mario_pos)
- [cur_obj_abs_y_dist_to_home](functions-5.md#cur_obj_abs_y_dist_to_home)
- [cur_obj_advance_looping_anim](functions-5.md#cur_obj_advance_looping_anim)
- [cur_obj_detect_steep_floor](functions-5.md#cur_obj_detect_steep_floor)
- [cur_obj_resolve_wall_collisions](functions-5.md#cur_obj_resolve_wall_collisions)
- [cur_obj_update_floor](functions-5.md#cur_obj_update_floor)
- [cur_obj_update_floor_and_resolve_wall_collisions](functions-5.md#cur_obj_update_floor_and_resolve_wall_collisions)
- [cur_obj_update_floor_and_walls](functions-5.md#cur_obj_update_floor_and_walls)
- [cur_obj_move_standard](functions-5.md#cur_obj_move_standard)
- [cur_obj_within_12k_bounds](functions-5.md#cur_obj_within_12k_bounds)
- [cur_obj_move_using_vel_and_gravity](functions-5.md#cur_obj_move_using_vel_and_gravity)
- [cur_obj_move_using_fvel_and_gravity](functions-5.md#cur_obj_move_using_fvel_and_gravity)
- [obj_set_pos_relative](functions-5.md#obj_set_pos_relative)
- [cur_obj_angle_to_home](functions-5.md#cur_obj_angle_to_home)
- [obj_set_gfx_pos_at_obj_pos](functions-5.md#obj_set_gfx_pos_at_obj_pos)
- [obj_translate_local](functions-5.md#obj_translate_local)
- [obj_build_transform_from_pos_and_angle](functions-5.md#obj_build_transform_from_pos_and_angle)
- [obj_set_throw_matrix_from_transform](functions-5.md#obj_set_throw_matrix_from_transform)
- [obj_build_transform_relative_to_parent](functions-5.md#obj_build_transform_relative_to_parent)
- [obj_create_transform_from_self](functions-5.md#obj_create_transform_from_self)
- [cur_obj_rotate_move_angle_using_vel](functions-5.md#cur_obj_rotate_move_angle_using_vel)
- [cur_obj_rotate_face_angle_using_vel](functions-5.md#cur_obj_rotate_face_angle_using_vel)
- [cur_obj_set_face_angle_to_move_angle](functions-5.md#cur_obj_set_face_angle_to_move_angle)
- [cur_obj_follow_path](functions-5.md#cur_obj_follow_path)
- [chain_segment_init](functions-5.md#chain_segment_init)
- [random_f32_around_zero](functions-5.md#random_f32_around_zero)
- [obj_scale_random](functions-5.md#obj_scale_random)
- [obj_translate_xyz_random](functions-5.md#obj_translate_xyz_random)
- [obj_translate_xz_random](functions-5.md#obj_translate_xz_random)
- [obj_build_vel_from_transform](functions-5.md#obj_build_vel_from_transform)
- [cur_obj_set_pos_via_transform](functions-5.md#cur_obj_set_pos_via_transform)
- [cur_obj_reflect_move_angle_off_wall](functions-5.md#cur_obj_reflect_move_angle_off_wall)
- [cur_obj_spawn_particles](functions-5.md#cur_obj_spawn_particles)
- [obj_set_hitbox](functions-5.md#obj_set_hitbox)
- [signum_positive](functions-5.md#signum_positive)
- [cur_obj_wait_then_blink](functions-5.md#cur_obj_wait_then_blink)
- [cur_obj_is_mario_ground_pounding_platform](functions-5.md#cur_obj_is_mario_ground_pounding_platform)
- [obj_is_mario_ground_pounding_platform](functions-5.md#obj_is_mario_ground_pounding_platform)
- [spawn_mist_particles](functions-5.md#spawn_mist_particles)
- [spawn_mist_particles_with_sound](functions-5.md#spawn_mist_particles_with_sound)
- [cur_obj_push_mario_away](functions-5.md#cur_obj_push_mario_away)
- [cur_obj_push_mario_away_from_cylinder](functions-5.md#cur_obj_push_mario_away_from_cylinder)
- [bhv_dust_smoke_loop](functions-5.md#bhv_dust_smoke_loop)
- [stub_obj_helpers_3](functions-5.md#stub_obj_helpers_3)
- [cur_obj_scale_over_time](functions-5.md#cur_obj_scale_over_time)
- [cur_obj_set_pos_to_home_with_debug](functions-5.md#cur_obj_set_pos_to_home_with_debug)
- [stub_obj_helpers_4](functions-5.md#stub_obj_helpers_4)
- [cur_obj_is_mario_on_platform](functions-5.md#cur_obj_is_mario_on_platform)
- [cur_obj_is_any_player_on_platform](functions-5.md#cur_obj_is_any_player_on_platform)
- [cur_obj_shake_y_until](functions-5.md#cur_obj_shake_y_until)
- [cur_obj_move_up_and_down](functions-5.md#cur_obj_move_up_and_down)
- [spawn_star_with_no_lvl_exit](functions-5.md#spawn_star_with_no_lvl_exit)
- [spawn_base_star_with_no_lvl_exit](functions-5.md#spawn_base_star_with_no_lvl_exit)
- [bit_shift_left](functions-5.md#bit_shift_left)
- [cur_obj_mario_far_away](functions-5.md#cur_obj_mario_far_away)
- [is_mario_moving_fast_or_in_air](functions-5.md#is_mario_moving_fast_or_in_air)
- [is_item_in_array](functions-5.md#is_item_in_array)
- [bhv_init_room](functions-5.md#bhv_init_room)
- [cur_obj_enable_rendering_if_mario_in_room](functions-5.md#cur_obj_enable_rendering_if_mario_in_room)
- [cur_obj_set_hitbox_and_die_if_attacked](functions-5.md#cur_obj_set_hitbox_and_die_if_attacked)
- [obj_explode_and_spawn_coins](functions-5.md#obj_explode_and_spawn_coins)
- [cur_obj_if_hit_wall_bounce_away](functions-5.md#cur_obj_if_hit_wall_bounce_away)
- [cur_obj_hide_if_mario_far_away_y](functions-5.md#cur_obj_hide_if_mario_far_away_y)
- [obj_is_hidden](functions-5.md#obj_is_hidden)
- [enable_time_stop](functions-5.md#enable_time_stop)
- [enable_time_stop_if_alone](functions-5.md#enable_time_stop_if_alone)
- [disable_time_stop](functions-5.md#disable_time_stop)
- [set_time_stop_flags](functions-5.md#set_time_stop_flags)
- [set_time_stop_flags_if_alone](functions-5.md#set_time_stop_flags_if_alone)
- [clear_time_stop_flags](functions-5.md#clear_time_stop_flags)
- [cur_obj_can_mario_activate_textbox](functions-5.md#cur_obj_can_mario_activate_textbox)
- [cur_obj_can_mario_activate_textbox_2](functions-5.md#cur_obj_can_mario_activate_textbox_2)
- [cur_obj_end_dialog](functions-5.md#cur_obj_end_dialog)
- [cur_obj_has_model](functions-5.md#cur_obj_has_model)
- [cur_obj_align_gfx_with_floor](functions-5.md#cur_obj_align_gfx_with_floor)
- [mario_is_within_rectangle](functions-5.md#mario_is_within_rectangle)
- [cur_obj_shake_screen](functions-5.md#cur_obj_shake_screen)
- [obj_attack_collided_from_other_object](functions-5.md#obj_attack_collided_from_other_object)
- [cur_obj_was_attacked_or_ground_pounded](functions-5.md#cur_obj_was_attacked_or_ground_pounded)
- [obj_copy_behavior_params](functions-5.md#obj_copy_behavior_params)
- [cur_obj_init_animation_and_anim_frame](functions-5.md#cur_obj_init_animation_and_anim_frame)
- [cur_obj_init_animation_and_check_if_near_end](functions-5.md#cur_obj_init_animation_and_check_if_near_end)
- [cur_obj_init_animation_and_extend_if_at_end](functions-5.md#cur_obj_init_animation_and_extend_if_at_end)
- [cur_obj_check_grabbed_mario](functions-5.md#cur_obj_check_grabbed_mario)
- [player_performed_grab_escape_action](functions-5.md#player_performed_grab_escape_action)
- [cur_obj_unused_play_footstep_sound](functions-5.md#cur_obj_unused_play_footstep_sound)
- [enable_time_stop_including_mario](functions-5.md#enable_time_stop_including_mario)
- [disable_time_stop_including_mario](functions-5.md#disable_time_stop_including_mario)
- [cur_obj_check_interacted](functions-5.md#cur_obj_check_interacted)
- [cur_obj_spawn_loot_blue_coin](functions-5.md#cur_obj_spawn_loot_blue_coin)
- [cur_obj_spawn_star_at_y_offset](functions-5.md#cur_obj_spawn_star_at_y_offset)
- [cur_obj_set_home_once](functions-5.md#cur_obj_set_home_once)
- [get_trajectory_length](functions-5.md#get_trajectory_length)
- [clear_move_flag](functions-6.md#clear_move_flag)
- [set_room_override](functions-6.md#set_room_override)
- [obj_update_pos_from_parent_transformation](functions-6.md#obj_update_pos_from_parent_transformation)
- [obj_apply_scale_to_matrix](functions-6.md#obj_apply_scale_to_matrix)
- [create_transformation_from_matrices](functions-6.md#create_transformation_from_matrices)
- [obj_set_held_state](functions-6.md#obj_set_held_state)
- [lateral_dist_between_objects](functions-6.md#lateral_dist_between_objects)
- [dist_between_objects](functions-6.md#dist_between_objects)
- [dist_between_object_and_point](functions-6.md#dist_between_object_and_point)
- [cur_obj_forward_vel_approach_upward](functions-6.md#cur_obj_forward_vel_approach_upward)
- [approach_f32_signed](functions-6.md#approach_f32_signed)
- [approach_f32_symmetric](functions-6.md#approach_f32_symmetric)
- [approach_s16_symmetric](functions-6.md#approach_s16_symmetric)
- [cur_obj_rotate_yaw_toward](functions-6.md#cur_obj_rotate_yaw_toward)
- [obj_angle_to_object](functions-6.md#obj_angle_to_object)
- [obj_pitch_to_object](functions-6.md#obj_pitch_to_object)
- [obj_angle_to_point](functions-6.md#obj_angle_to_point)
- [obj_turn_toward_object](functions-6.md#obj_turn_toward_object)
- [obj_set_parent_relative_pos](functions-6.md#obj_set_parent_relative_pos)
- [obj_set_pos](functions-6.md#obj_set_pos)
- [obj_set_angle](functions-6.md#obj_set_angle)
- [obj_set_move_angle](functions-6.md#obj_set_move_angle)
- [obj_set_face_angle](functions-6.md#obj_set_face_angle)
- [obj_set_gfx_angle](functions-6.md#obj_set_gfx_angle)
- [obj_set_gfx_pos](functions-6.md#obj_set_gfx_pos)
- [obj_set_gfx_scale](functions-6.md#obj_set_gfx_scale)
- [spawn_water_droplet](functions-6.md#spawn_water_droplet)
- [obj_build_relative_transform](functions-6.md#obj_build_relative_transform)
- [cur_obj_move_using_vel](functions-6.md#cur_obj_move_using_vel)
- [obj_copy_graph_y_offset](functions-6.md#obj_copy_graph_y_offset)
- [obj_copy_pos_and_angle](functions-6.md#obj_copy_pos_and_angle)
- [obj_copy_pos](functions-6.md#obj_copy_pos)
- [obj_copy_angle](functions-6.md#obj_copy_angle)
- [obj_set_gfx_pos_from_pos](functions-6.md#obj_set_gfx_pos_from_pos)
- [obj_init_animation](functions-6.md#obj_init_animation)
- [linear_mtxf_mul_vec3f](functions-6.md#linear_mtxf_mul_vec3f)
- [linear_mtxf_transpose_mul_vec3f](functions-6.md#linear_mtxf_transpose_mul_vec3f)
- [obj_apply_scale_to_transform](functions-6.md#obj_apply_scale_to_transform)
- [obj_copy_scale](functions-6.md#obj_copy_scale)
- [obj_scale_xyz](functions-6.md#obj_scale_xyz)
- [obj_scale](functions-6.md#obj_scale)
- [cur_obj_scale](functions-6.md#cur_obj_scale)
- [cur_obj_init_animation](functions-6.md#cur_obj_init_animation)
- [cur_obj_init_animation_with_sound](functions-6.md#cur_obj_init_animation_with_sound)
- [obj_init_animation_with_accel_and_sound](functions-6.md#obj_init_animation_with_accel_and_sound)
- [cur_obj_init_animation_with_accel_and_sound](functions-6.md#cur_obj_init_animation_with_accel_and_sound)
- [obj_init_animation_with_sound](functions-6.md#obj_init_animation_with_sound)
- [cur_obj_enable_rendering_and_become_tangible](functions-6.md#cur_obj_enable_rendering_and_become_tangible)
- [cur_obj_enable_rendering](functions-6.md#cur_obj_enable_rendering)
- [cur_obj_disable_rendering_and_become_intangible](functions-6.md#cur_obj_disable_rendering_and_become_intangible)
- [cur_obj_disable_rendering](functions-6.md#cur_obj_disable_rendering)
- [cur_obj_unhide](functions-6.md#cur_obj_unhide)
- [cur_obj_hide](functions-6.md#cur_obj_hide)
- [cur_obj_set_pos_relative](functions-6.md#cur_obj_set_pos_relative)
- [cur_obj_set_pos_relative_to_parent](functions-6.md#cur_obj_set_pos_relative_to_parent)
- [cur_obj_enable_rendering_2](functions-6.md#cur_obj_enable_rendering_2)
- [cur_obj_unused_init_on_floor](functions-6.md#cur_obj_unused_init_on_floor)
- [obj_set_face_angle_to_move_angle](functions-6.md#obj_set_face_angle_to_move_angle)
- [get_object_list_from_behavior](functions-6.md#get_object_list_from_behavior)
- [cur_obj_nearest_object_with_behavior](functions-6.md#cur_obj_nearest_object_with_behavior)
- [cur_obj_dist_to_nearest_object_with_behavior](functions-6.md#cur_obj_dist_to_nearest_object_with_behavior)
- [cur_obj_find_nearest_pole](functions-6.md#cur_obj_find_nearest_pole)
- [cur_obj_find_nearest_object_with_behavior](functions-6.md#cur_obj_find_nearest_object_with_behavior)
- [cur_obj_count_objects_with_behavior](functions-6.md#cur_obj_count_objects_with_behavior)
- [find_unimportant_object](functions-6.md#find_unimportant_object)
- [count_unimportant_objects](functions-6.md#count_unimportant_objects)
- [count_objects_with_behavior](functions-6.md#count_objects_with_behavior)
- [find_object_with_behavior](functions-6.md#find_object_with_behavior)
- [cur_obj_find_nearby_held_actor](functions-6.md#cur_obj_find_nearby_held_actor)
- [cur_obj_reset_timer_and_subaction](functions-6.md#cur_obj_reset_timer_and_subaction)
- [cur_obj_change_action](functions-6.md#cur_obj_change_action)
- [cur_obj_set_vel_from_mario_vel](functions-6.md#cur_obj_set_vel_from_mario_vel)
- [cur_obj_reverse_animation](functions-6.md#cur_obj_reverse_animation)
- [cur_obj_extend_animation_if_at_end](functions-6.md#cur_obj_extend_animation_if_at_end)
- [cur_obj_check_if_near_animation_end](functions-6.md#cur_obj_check_if_near_animation_end)
- [cur_obj_check_if_at_animation_end](functions-6.md#cur_obj_check_if_at_animation_end)
- [cur_obj_check_anim_frame](functions-6.md#cur_obj_check_anim_frame)
- [cur_obj_check_anim_frame_in_range](functions-6.md#cur_obj_check_anim_frame_in_range)
- [cur_obj_check_frame_prior_current_frame](functions-6.md#cur_obj_check_frame_prior_current_frame)
- [mario_is_in_air_action](functions-6.md#mario_is_in_air_action)
- [mario_is_dive_sliding](functions-6.md#mario_is_dive_sliding)
- [cur_obj_set_y_vel_and_animation](functions-6.md#cur_obj_set_y_vel_and_animation)
- [cur_obj_unrender_and_reset_state](functions-6.md#cur_obj_unrender_and_reset_state)
- [cur_obj_move_after_thrown_or_dropped](functions-6.md#cur_obj_move_after_thrown_or_dropped)
- [cur_obj_get_thrown_or_placed](functions-6.md#cur_obj_get_thrown_or_placed)
- [cur_obj_get_dropped](functions-6.md#cur_obj_get_dropped)
- [mario_set_flag](functions-6.md#mario_set_flag)
- [cur_obj_clear_interact_status_flag](functions-6.md#cur_obj_clear_interact_status_flag)
- [obj_mark_for_deletion](functions-6.md#obj_mark_for_deletion)
- [cur_obj_disable](functions-6.md#cur_obj_disable)
- [cur_obj_become_intangible](functions-6.md#cur_obj_become_intangible)
- [cur_obj_become_tangible](functions-6.md#cur_obj_become_tangible)
- [obj_become_tangible](functions-6.md#obj_become_tangible)
- [cur_obj_update_floor_height](functions-6.md#cur_obj_update_floor_height)
- [cur_obj_update_floor_height_and_get_floor](functions-6.md#cur_obj_update_floor_height_and_get_floor)
- [apply_drag_to_value](functions-6.md#apply_drag_to_value)
- [cur_obj_apply_drag_xz](functions-6.md#cur_obj_apply_drag_xz)
- [cur_obj_move_xz](functions-6.md#cur_obj_move_xz)
- [cur_obj_move_update_underwater_flags](functions-6.md#cur_obj_move_update_underwater_flags)
- [cur_obj_move_update_ground_air_flags](functions-6.md#cur_obj_move_update_ground_air_flags)
- [cur_obj_move_y_and_get_water_level](functions-6.md#cur_obj_move_y_and_get_water_level)
- [cur_obj_move_y](functions-6.md#cur_obj_move_y)
- [cur_obj_unused_resolve_wall_collisions](functions-6.md#cur_obj_unused_resolve_wall_collisions)
- [abs_angle_diff](functions-6.md#abs_angle_diff)
- [cur_obj_move_xz_using_fvel_and_yaw](functions-6.md#cur_obj_move_xz_using_fvel_and_yaw)
- [cur_obj_move_y_with_terminal_vel](functions-6.md#cur_obj_move_y_with_terminal_vel)
- [cur_obj_compute_vel_xz](functions-6.md#cur_obj_compute_vel_xz)
- [increment_velocity_toward_range](functions-6.md#increment_velocity_toward_range)
- [obj_check_if_collided_with_object](functions-6.md#obj_check_if_collided_with_object)
- [cur_obj_set_behavior](functions-6.md#cur_obj_set_behavior)
- [obj_set_behavior](functions-6.md#obj_set_behavior)
- [cur_obj_has_behavior](functions-6.md#cur_obj_has_behavior)
- [obj_has_behavior](functions-6.md#obj_has_behavior)
- [cur_obj_lateral_dist_from_obj_to_home](functions-6.md#cur_obj_lateral_dist_from_obj_to_home)
- [cur_obj_lateral_dist_from_mario_to_home](functions-6.md#cur_obj_lateral_dist_from_mario_to_home)
- [cur_obj_lateral_dist_to_home](functions-6.md#cur_obj_lateral_dist_to_home)
- [cur_obj_outside_home_square](functions-6.md#cur_obj_outside_home_square)
- [cur_obj_outside_home_rectangle](functions-6.md#cur_obj_outside_home_rectangle)
- [cur_obj_set_pos_to_home](functions-6.md#cur_obj_set_pos_to_home)
- [cur_obj_set_pos_to_home_and_stop](functions-6.md#cur_obj_set_pos_to_home_and_stop)
- [cur_obj_shake_y](functions-6.md#cur_obj_shake_y)
- [cur_obj_start_cam_event](functions-6.md#cur_obj_start_cam_event)
- [set_mario_interact_hoot_if_in_range](functions-6.md#set_mario_interact_hoot_if_in_range)
- [obj_set_billboard](functions-6.md#obj_set_billboard)
- [obj_set_cylboard](functions-6.md#obj_set_cylboard)
- [cur_obj_set_billboard_if_vanilla_cam](functions-6.md#cur_obj_set_billboard_if_vanilla_cam)
- [obj_set_hitbox_radius_and_height](functions-6.md#obj_set_hitbox_radius_and_height)
- [obj_set_hurtbox_radius_and_height](functions-6.md#obj_set_hurtbox_radius_and_height)
- [cur_obj_set_hitbox_radius_and_height](functions-6.md#cur_obj_set_hitbox_radius_and_height)
- [cur_obj_set_hurtbox_radius_and_height](functions-6.md#cur_obj_set_hurtbox_radius_and_height)
- [obj_spawn_loot_coins](functions-6.md#obj_spawn_loot_coins)
- [obj_spawn_loot_blue_coins](functions-6.md#obj_spawn_loot_blue_coins)
- [obj_spawn_loot_yellow_coins](functions-6.md#obj_spawn_loot_yellow_coins)
- [cur_obj_spawn_loot_coin_at_mario_pos](functions-6.md#cur_obj_spawn_loot_coin_at_mario_pos)
- [cur_obj_abs_y_dist_to_home](functions-6.md#cur_obj_abs_y_dist_to_home)
- [cur_obj_advance_looping_anim](functions-6.md#cur_obj_advance_looping_anim)
- [cur_obj_detect_steep_floor](functions-6.md#cur_obj_detect_steep_floor)
- [cur_obj_resolve_wall_collisions](functions-6.md#cur_obj_resolve_wall_collisions)
- [cur_obj_update_floor](functions-6.md#cur_obj_update_floor)
- [cur_obj_update_floor_and_resolve_wall_collisions](functions-6.md#cur_obj_update_floor_and_resolve_wall_collisions)
- [cur_obj_update_floor_and_walls](functions-6.md#cur_obj_update_floor_and_walls)
- [cur_obj_move_standard](functions-6.md#cur_obj_move_standard)
- [cur_obj_within_12k_bounds](functions-6.md#cur_obj_within_12k_bounds)
- [cur_obj_move_using_vel_and_gravity](functions-6.md#cur_obj_move_using_vel_and_gravity)
- [cur_obj_move_using_fvel_and_gravity](functions-6.md#cur_obj_move_using_fvel_and_gravity)
- [obj_set_pos_relative](functions-6.md#obj_set_pos_relative)
- [cur_obj_angle_to_home](functions-6.md#cur_obj_angle_to_home)
- [obj_set_gfx_pos_at_obj_pos](functions-6.md#obj_set_gfx_pos_at_obj_pos)
- [obj_translate_local](functions-6.md#obj_translate_local)
- [obj_build_transform_from_pos_and_angle](functions-6.md#obj_build_transform_from_pos_and_angle)
- [obj_set_throw_matrix_from_transform](functions-6.md#obj_set_throw_matrix_from_transform)
- [obj_build_transform_relative_to_parent](functions-6.md#obj_build_transform_relative_to_parent)
- [obj_create_transform_from_self](functions-6.md#obj_create_transform_from_self)
- [cur_obj_rotate_move_angle_using_vel](functions-6.md#cur_obj_rotate_move_angle_using_vel)
- [cur_obj_rotate_face_angle_using_vel](functions-6.md#cur_obj_rotate_face_angle_using_vel)
- [cur_obj_set_face_angle_to_move_angle](functions-6.md#cur_obj_set_face_angle_to_move_angle)
- [cur_obj_follow_path](functions-6.md#cur_obj_follow_path)
- [chain_segment_init](functions-6.md#chain_segment_init)
- [random_f32_around_zero](functions-6.md#random_f32_around_zero)
- [obj_scale_random](functions-6.md#obj_scale_random)
- [obj_translate_xyz_random](functions-6.md#obj_translate_xyz_random)
- [obj_translate_xz_random](functions-6.md#obj_translate_xz_random)
- [obj_build_vel_from_transform](functions-6.md#obj_build_vel_from_transform)
- [cur_obj_set_pos_via_transform](functions-6.md#cur_obj_set_pos_via_transform)
- [cur_obj_reflect_move_angle_off_wall](functions-6.md#cur_obj_reflect_move_angle_off_wall)
- [cur_obj_spawn_particles](functions-6.md#cur_obj_spawn_particles)
- [obj_set_hitbox](functions-6.md#obj_set_hitbox)
- [signum_positive](functions-6.md#signum_positive)
- [cur_obj_wait_then_blink](functions-6.md#cur_obj_wait_then_blink)
- [cur_obj_is_mario_ground_pounding_platform](functions-6.md#cur_obj_is_mario_ground_pounding_platform)
- [obj_is_mario_ground_pounding_platform](functions-6.md#obj_is_mario_ground_pounding_platform)
- [spawn_mist_particles](functions-6.md#spawn_mist_particles)
- [spawn_mist_particles_with_sound](functions-6.md#spawn_mist_particles_with_sound)
- [cur_obj_push_mario_away](functions-6.md#cur_obj_push_mario_away)
- [cur_obj_push_mario_away_from_cylinder](functions-6.md#cur_obj_push_mario_away_from_cylinder)
- [bhv_dust_smoke_loop](functions-6.md#bhv_dust_smoke_loop)
- [stub_obj_helpers_3](functions-6.md#stub_obj_helpers_3)
- [cur_obj_scale_over_time](functions-6.md#cur_obj_scale_over_time)
- [cur_obj_set_pos_to_home_with_debug](functions-6.md#cur_obj_set_pos_to_home_with_debug)
- [stub_obj_helpers_4](functions-6.md#stub_obj_helpers_4)
- [cur_obj_is_mario_on_platform](functions-6.md#cur_obj_is_mario_on_platform)
- [cur_obj_is_any_player_on_platform](functions-6.md#cur_obj_is_any_player_on_platform)
- [cur_obj_shake_y_until](functions-6.md#cur_obj_shake_y_until)
- [cur_obj_move_up_and_down](functions-6.md#cur_obj_move_up_and_down)
- [spawn_star_with_no_lvl_exit](functions-6.md#spawn_star_with_no_lvl_exit)
- [spawn_base_star_with_no_lvl_exit](functions-6.md#spawn_base_star_with_no_lvl_exit)
- [bit_shift_left](functions-6.md#bit_shift_left)
- [cur_obj_mario_far_away](functions-6.md#cur_obj_mario_far_away)
- [is_mario_moving_fast_or_in_air](functions-6.md#is_mario_moving_fast_or_in_air)
- [is_item_in_array](functions-6.md#is_item_in_array)
- [bhv_init_room](functions-6.md#bhv_init_room)
- [cur_obj_enable_rendering_if_mario_in_room](functions-6.md#cur_obj_enable_rendering_if_mario_in_room)
- [cur_obj_set_hitbox_and_die_if_attacked](functions-6.md#cur_obj_set_hitbox_and_die_if_attacked)
- [obj_explode_and_spawn_coins](functions-6.md#obj_explode_and_spawn_coins)
- [cur_obj_if_hit_wall_bounce_away](functions-6.md#cur_obj_if_hit_wall_bounce_away)
- [cur_obj_hide_if_mario_far_away_y](functions-6.md#cur_obj_hide_if_mario_far_away_y)
- [obj_is_hidden](functions-6.md#obj_is_hidden)
- [enable_time_stop](functions-6.md#enable_time_stop)
- [enable_time_stop_if_alone](functions-6.md#enable_time_stop_if_alone)
- [disable_time_stop](functions-6.md#disable_time_stop)
- [set_time_stop_flags](functions-6.md#set_time_stop_flags)
- [set_time_stop_flags_if_alone](functions-6.md#set_time_stop_flags_if_alone)
- [clear_time_stop_flags](functions-6.md#clear_time_stop_flags)
- [cur_obj_can_mario_activate_textbox](functions-6.md#cur_obj_can_mario_activate_textbox)
- [cur_obj_can_mario_activate_textbox_2](functions-6.md#cur_obj_can_mario_activate_textbox_2)
- [cur_obj_end_dialog](functions-6.md#cur_obj_end_dialog)
- [cur_obj_has_model](functions-6.md#cur_obj_has_model)
- [cur_obj_align_gfx_with_floor](functions-6.md#cur_obj_align_gfx_with_floor)
- [mario_is_within_rectangle](functions-6.md#mario_is_within_rectangle)
- [cur_obj_shake_screen](functions-6.md#cur_obj_shake_screen)
- [obj_attack_collided_from_other_object](functions-6.md#obj_attack_collided_from_other_object)
- [cur_obj_was_attacked_or_ground_pounded](functions-6.md#cur_obj_was_attacked_or_ground_pounded)
- [obj_copy_behavior_params](functions-6.md#obj_copy_behavior_params)
- [cur_obj_init_animation_and_anim_frame](functions-6.md#cur_obj_init_animation_and_anim_frame)
- [cur_obj_init_animation_and_check_if_near_end](functions-6.md#cur_obj_init_animation_and_check_if_near_end)
- [cur_obj_init_animation_and_extend_if_at_end](functions-6.md#cur_obj_init_animation_and_extend_if_at_end)
- [cur_obj_check_grabbed_mario](functions-6.md#cur_obj_check_grabbed_mario)
- [player_performed_grab_escape_action](functions-6.md#player_performed_grab_escape_action)
- [cur_obj_unused_play_footstep_sound](functions-6.md#cur_obj_unused_play_footstep_sound)
- [enable_time_stop_including_mario](functions-6.md#enable_time_stop_including_mario)
- [disable_time_stop_including_mario](functions-6.md#disable_time_stop_including_mario)
- [cur_obj_check_interacted](functions-6.md#cur_obj_check_interacted)
- [cur_obj_spawn_loot_blue_coin](functions-6.md#cur_obj_spawn_loot_blue_coin)
- [cur_obj_spawn_star_at_y_offset](functions-6.md#cur_obj_spawn_star_at_y_offset)
- [cur_obj_set_home_once](functions-6.md#cur_obj_set_home_once)
- [get_trajectory_length](functions-6.md#get_trajectory_length)
<br />
@ -1934,6 +1937,7 @@
- [gfx_get_vertex_buffer](functions-6.md#gfx_get_vertex_buffer)
- [gfx_get_vertex_count](functions-6.md#gfx_get_vertex_count)
- [gfx_get_texture](functions-6.md#gfx_get_texture)
- [gfx_get_name](functions-6.md#gfx_get_name)
- [gfx_get_length](functions-6.md#gfx_get_length)
- [gfx_get_command](functions-6.md#gfx_get_command)
- [gfx_get_next_command](functions-6.md#gfx_get_next_command)
@ -1942,6 +1946,7 @@
- [gfx_resize](functions-6.md#gfx_resize)
- [gfx_delete](functions-6.md#gfx_delete)
- [gfx_delete_all](functions-6.md#gfx_delete_all)
- [vtx_get_name](functions-6.md#vtx_get_name)
- [vtx_get_count](functions-6.md#vtx_get_count)
- [vtx_get_vertex](functions-6.md#vtx_get_vertex)
- [vtx_get_next_vertex](functions-6.md#vtx_get_next_vertex)
@ -1954,240 +1959,244 @@
<br />
- smlua_level_utils.h
- [smlua_level_util_change_area](functions-6.md#smlua_level_util_change_area)
- [smlua_level_util_get_info](functions-6.md#smlua_level_util_get_info)
- [smlua_level_util_get_info_from_short_name](functions-6.md#smlua_level_util_get_info_from_short_name)
- [smlua_level_util_get_info_from_course_num](functions-6.md#smlua_level_util_get_info_from_course_num)
- [level_register](functions-6.md#level_register)
- [level_is_vanilla_level](functions-6.md#level_is_vanilla_level)
- [warp_to_warpnode](functions-6.md#warp_to_warpnode)
- [warp_to_level](functions-6.md#warp_to_level)
- [warp_restart_level](functions-6.md#warp_restart_level)
- [warp_to_start_level](functions-6.md#warp_to_start_level)
- [warp_exit_level](functions-6.md#warp_exit_level)
- [warp_to_castle](functions-6.md#warp_to_castle)
- [smlua_level_util_change_area](functions-7.md#smlua_level_util_change_area)
- [smlua_level_util_get_info](functions-7.md#smlua_level_util_get_info)
- [smlua_level_util_get_info_from_short_name](functions-7.md#smlua_level_util_get_info_from_short_name)
- [smlua_level_util_get_info_from_course_num](functions-7.md#smlua_level_util_get_info_from_course_num)
- [level_register](functions-7.md#level_register)
- [level_is_vanilla_level](functions-7.md#level_is_vanilla_level)
- [warp_to_warpnode](functions-7.md#warp_to_warpnode)
- [warp_to_level](functions-7.md#warp_to_level)
- [warp_restart_level](functions-7.md#warp_restart_level)
- [warp_to_start_level](functions-7.md#warp_to_start_level)
- [warp_exit_level](functions-7.md#warp_exit_level)
- [warp_to_castle](functions-7.md#warp_to_castle)
<br />
- smlua_misc_utils.h
- [get_network_area_timer](functions-6.md#get_network_area_timer)
- [get_area_update_counter](functions-6.md#get_area_update_counter)
- [get_temp_s32_pointer](functions-6.md#get_temp_s32_pointer)
- [deref_s32_pointer](functions-6.md#deref_s32_pointer)
- [djui_popup_create_global](functions-6.md#djui_popup_create_global)
- [djui_is_popup_disabled](functions-6.md#djui_is_popup_disabled)
- [djui_set_popup_disabled_override](functions-6.md#djui_set_popup_disabled_override)
- [djui_reset_popup_disabled_override](functions-6.md#djui_reset_popup_disabled_override)
- [djui_is_playerlist_open](functions-6.md#djui_is_playerlist_open)
- [djui_attempting_to_open_playerlist](functions-6.md#djui_attempting_to_open_playerlist)
- [djui_get_playerlist_page_index](functions-6.md#djui_get_playerlist_page_index)
- [djui_menu_get_font](functions-6.md#djui_menu_get_font)
- [djui_menu_get_theme](functions-6.md#djui_menu_get_theme)
- [djui_is_playerlist_ping_visible](functions-6.md#djui_is_playerlist_ping_visible)
- [get_dialog_box_state](functions-6.md#get_dialog_box_state)
- [get_dialog_id](functions-6.md#get_dialog_id)
- [get_last_star_or_key](functions-6.md#get_last_star_or_key)
- [set_last_star_or_key](functions-6.md#set_last_star_or_key)
- [get_last_completed_course_num](functions-6.md#get_last_completed_course_num)
- [set_last_completed_course_num](functions-6.md#set_last_completed_course_num)
- [get_last_completed_star_num](functions-6.md#get_last_completed_star_num)
- [set_last_completed_star_num](functions-6.md#set_last_completed_star_num)
- [get_got_file_coin_hi_score](functions-6.md#get_got_file_coin_hi_score)
- [set_got_file_coin_hi_score](functions-6.md#set_got_file_coin_hi_score)
- [get_save_file_modified](functions-6.md#get_save_file_modified)
- [set_save_file_modified](functions-6.md#set_save_file_modified)
- [hud_hide](functions-6.md#hud_hide)
- [hud_show](functions-6.md#hud_show)
- [hud_is_hidden](functions-6.md#hud_is_hidden)
- [hud_get_value](functions-6.md#hud_get_value)
- [hud_set_value](functions-6.md#hud_set_value)
- [hud_render_power_meter](functions-6.md#hud_render_power_meter)
- [hud_render_power_meter_interpolated](functions-6.md#hud_render_power_meter_interpolated)
- [hud_get_flash](functions-6.md#hud_get_flash)
- [hud_set_flash](functions-6.md#hud_set_flash)
- [act_select_hud_hide](functions-6.md#act_select_hud_hide)
- [act_select_hud_show](functions-6.md#act_select_hud_show)
- [act_select_hud_is_hidden](functions-6.md#act_select_hud_is_hidden)
- [is_game_paused](functions-6.md#is_game_paused)
- [is_transition_playing](functions-6.md#is_transition_playing)
- [allocate_mario_action](functions-6.md#allocate_mario_action)
- [get_hand_foot_pos_x](functions-6.md#get_hand_foot_pos_x)
- [get_hand_foot_pos_y](functions-6.md#get_hand_foot_pos_y)
- [get_hand_foot_pos_z](functions-6.md#get_hand_foot_pos_z)
- [get_mario_anim_part_pos](functions-6.md#get_mario_anim_part_pos)
- [get_current_save_file_num](functions-6.md#get_current_save_file_num)
- [save_file_get_using_backup_slot](functions-6.md#save_file_get_using_backup_slot)
- [save_file_set_using_backup_slot](functions-6.md#save_file_set_using_backup_slot)
- [movtexqc_register](functions-6.md#movtexqc_register)
- [get_water_level](functions-6.md#get_water_level)
- [set_water_level](functions-6.md#set_water_level)
- [course_is_main_course](functions-6.md#course_is_main_course)
- [get_ttc_speed_setting](functions-6.md#get_ttc_speed_setting)
- [set_ttc_speed_setting](functions-6.md#set_ttc_speed_setting)
- [get_time](functions-6.md#get_time)
- [get_date_and_time](functions-6.md#get_date_and_time)
- [get_envfx](functions-6.md#get_envfx)
- [set_override_envfx](functions-6.md#set_override_envfx)
- [get_global_timer](functions-6.md#get_global_timer)
- [get_dialog_response](functions-6.md#get_dialog_response)
- [get_local_discord_id](functions-6.md#get_local_discord_id)
- [get_coopnet_id](functions-6.md#get_coopnet_id)
- [get_volume_master](functions-6.md#get_volume_master)
- [get_volume_level](functions-6.md#get_volume_level)
- [get_volume_sfx](functions-6.md#get_volume_sfx)
- [get_volume_env](functions-6.md#get_volume_env)
- [set_volume_master](functions-6.md#set_volume_master)
- [set_volume_level](functions-6.md#set_volume_level)
- [set_volume_sfx](functions-6.md#set_volume_sfx)
- [set_volume_env](functions-6.md#set_volume_env)
- [get_environment_region](functions-6.md#get_environment_region)
- [set_environment_region](functions-6.md#set_environment_region)
- [mod_file_exists](functions-6.md#mod_file_exists)
- [get_active_mod](functions-6.md#get_active_mod)
- [set_window_title](functions-6.md#set_window_title)
- [reset_window_title](functions-6.md#reset_window_title)
- [get_os_name](functions-6.md#get_os_name)
- [geo_get_current_root](functions-6.md#geo_get_current_root)
- [geo_get_current_master_list](functions-6.md#geo_get_current_master_list)
- [geo_get_current_perspective](functions-6.md#geo_get_current_perspective)
- [geo_get_current_camera](functions-6.md#geo_get_current_camera)
- [geo_get_current_held_object](functions-6.md#geo_get_current_held_object)
- [texture_to_lua_table](functions-6.md#texture_to_lua_table)
- [get_network_area_timer](functions-7.md#get_network_area_timer)
- [get_area_update_counter](functions-7.md#get_area_update_counter)
- [get_temp_s32_pointer](functions-7.md#get_temp_s32_pointer)
- [deref_s32_pointer](functions-7.md#deref_s32_pointer)
- [djui_popup_create_global](functions-7.md#djui_popup_create_global)
- [djui_is_popup_disabled](functions-7.md#djui_is_popup_disabled)
- [djui_set_popup_disabled_override](functions-7.md#djui_set_popup_disabled_override)
- [djui_reset_popup_disabled_override](functions-7.md#djui_reset_popup_disabled_override)
- [djui_is_playerlist_open](functions-7.md#djui_is_playerlist_open)
- [djui_attempting_to_open_playerlist](functions-7.md#djui_attempting_to_open_playerlist)
- [djui_get_playerlist_page_index](functions-7.md#djui_get_playerlist_page_index)
- [djui_menu_get_font](functions-7.md#djui_menu_get_font)
- [djui_menu_get_theme](functions-7.md#djui_menu_get_theme)
- [djui_is_playerlist_ping_visible](functions-7.md#djui_is_playerlist_ping_visible)
- [get_dialog_box_state](functions-7.md#get_dialog_box_state)
- [get_dialog_id](functions-7.md#get_dialog_id)
- [get_last_star_or_key](functions-7.md#get_last_star_or_key)
- [set_last_star_or_key](functions-7.md#set_last_star_or_key)
- [get_last_completed_course_num](functions-7.md#get_last_completed_course_num)
- [set_last_completed_course_num](functions-7.md#set_last_completed_course_num)
- [get_last_completed_star_num](functions-7.md#get_last_completed_star_num)
- [set_last_completed_star_num](functions-7.md#set_last_completed_star_num)
- [get_got_file_coin_hi_score](functions-7.md#get_got_file_coin_hi_score)
- [set_got_file_coin_hi_score](functions-7.md#set_got_file_coin_hi_score)
- [get_save_file_modified](functions-7.md#get_save_file_modified)
- [set_save_file_modified](functions-7.md#set_save_file_modified)
- [hud_hide](functions-7.md#hud_hide)
- [hud_show](functions-7.md#hud_show)
- [hud_is_hidden](functions-7.md#hud_is_hidden)
- [hud_get_value](functions-7.md#hud_get_value)
- [hud_set_value](functions-7.md#hud_set_value)
- [hud_render_power_meter](functions-7.md#hud_render_power_meter)
- [hud_render_power_meter_interpolated](functions-7.md#hud_render_power_meter_interpolated)
- [hud_get_flash](functions-7.md#hud_get_flash)
- [hud_set_flash](functions-7.md#hud_set_flash)
- [act_select_hud_hide](functions-7.md#act_select_hud_hide)
- [act_select_hud_show](functions-7.md#act_select_hud_show)
- [act_select_hud_is_hidden](functions-7.md#act_select_hud_is_hidden)
- [is_game_paused](functions-7.md#is_game_paused)
- [is_transition_playing](functions-7.md#is_transition_playing)
- [allocate_mario_action](functions-7.md#allocate_mario_action)
- [get_hand_foot_pos_x](functions-7.md#get_hand_foot_pos_x)
- [get_hand_foot_pos_y](functions-7.md#get_hand_foot_pos_y)
- [get_hand_foot_pos_z](functions-7.md#get_hand_foot_pos_z)
- [get_mario_anim_part_pos](functions-7.md#get_mario_anim_part_pos)
- [get_current_save_file_num](functions-7.md#get_current_save_file_num)
- [save_file_get_using_backup_slot](functions-7.md#save_file_get_using_backup_slot)
- [save_file_set_using_backup_slot](functions-7.md#save_file_set_using_backup_slot)
- [movtexqc_register](functions-7.md#movtexqc_register)
- [get_water_level](functions-7.md#get_water_level)
- [set_water_level](functions-7.md#set_water_level)
- [course_is_main_course](functions-7.md#course_is_main_course)
- [get_ttc_speed_setting](functions-7.md#get_ttc_speed_setting)
- [set_ttc_speed_setting](functions-7.md#set_ttc_speed_setting)
- [get_time](functions-7.md#get_time)
- [get_date_and_time](functions-7.md#get_date_and_time)
- [get_envfx](functions-7.md#get_envfx)
- [set_override_envfx](functions-7.md#set_override_envfx)
- [get_global_timer](functions-7.md#get_global_timer)
- [get_dialog_response](functions-7.md#get_dialog_response)
- [get_local_discord_id](functions-7.md#get_local_discord_id)
- [get_coopnet_id](functions-7.md#get_coopnet_id)
- [get_volume_master](functions-7.md#get_volume_master)
- [get_volume_level](functions-7.md#get_volume_level)
- [get_volume_sfx](functions-7.md#get_volume_sfx)
- [get_volume_env](functions-7.md#get_volume_env)
- [set_volume_master](functions-7.md#set_volume_master)
- [set_volume_level](functions-7.md#set_volume_level)
- [set_volume_sfx](functions-7.md#set_volume_sfx)
- [set_volume_env](functions-7.md#set_volume_env)
- [get_environment_region](functions-7.md#get_environment_region)
- [set_environment_region](functions-7.md#set_environment_region)
- [mod_file_exists](functions-7.md#mod_file_exists)
- [get_active_mod](functions-7.md#get_active_mod)
- [set_window_title](functions-7.md#set_window_title)
- [reset_window_title](functions-7.md#reset_window_title)
- [get_os_name](functions-7.md#get_os_name)
- [geo_get_current_root](functions-7.md#geo_get_current_root)
- [geo_get_current_master_list](functions-7.md#geo_get_current_master_list)
- [geo_get_current_perspective](functions-7.md#geo_get_current_perspective)
- [geo_get_current_camera](functions-7.md#geo_get_current_camera)
- [geo_get_current_held_object](functions-7.md#geo_get_current_held_object)
- [texture_to_lua_table](functions-7.md#texture_to_lua_table)
- [get_texture_name](functions-7.md#get_texture_name)
<br />
- smlua_model_utils.h
- [smlua_model_util_get_id](functions-6.md#smlua_model_util_get_id)
- [smlua_model_util_get_id](functions-7.md#smlua_model_util_get_id)
<br />
- smlua_obj_utils.h
- [spawn_sync_object](functions-6.md#spawn_sync_object)
- [spawn_non_sync_object](functions-6.md#spawn_non_sync_object)
- [obj_has_behavior_id](functions-6.md#obj_has_behavior_id)
- [obj_has_model_extended](functions-6.md#obj_has_model_extended)
- [obj_get_model_id_extended](functions-6.md#obj_get_model_id_extended)
- [obj_set_model_extended](functions-6.md#obj_set_model_extended)
- [get_trajectory](functions-6.md#get_trajectory)
- [geo_get_current_object](functions-6.md#geo_get_current_object)
- [get_current_object](functions-6.md#get_current_object)
- [get_dialog_object](functions-6.md#get_dialog_object)
- [get_cutscene_focus](functions-6.md#get_cutscene_focus)
- [get_secondary_camera_focus](functions-6.md#get_secondary_camera_focus)
- [set_cutscene_focus](functions-6.md#set_cutscene_focus)
- [set_secondary_camera_focus](functions-6.md#set_secondary_camera_focus)
- [obj_get_first](functions-6.md#obj_get_first)
- [obj_get_first_with_behavior_id](functions-6.md#obj_get_first_with_behavior_id)
- [obj_get_first_with_behavior_id_and_field_s32](functions-6.md#obj_get_first_with_behavior_id_and_field_s32)
- [obj_get_first_with_behavior_id_and_field_f32](functions-6.md#obj_get_first_with_behavior_id_and_field_f32)
- [obj_get_next](functions-6.md#obj_get_next)
- [obj_get_next_with_same_behavior_id](functions-6.md#obj_get_next_with_same_behavior_id)
- [obj_get_next_with_same_behavior_id_and_field_s32](functions-6.md#obj_get_next_with_same_behavior_id_and_field_s32)
- [obj_get_next_with_same_behavior_id_and_field_f32](functions-6.md#obj_get_next_with_same_behavior_id_and_field_f32)
- [obj_get_nearest_object_with_behavior_id](functions-6.md#obj_get_nearest_object_with_behavior_id)
- [obj_count_objects_with_behavior_id](functions-6.md#obj_count_objects_with_behavior_id)
- [obj_get_collided_object](functions-6.md#obj_get_collided_object)
- [obj_get_field_u32](functions-6.md#obj_get_field_u32)
- [obj_get_field_s32](functions-6.md#obj_get_field_s32)
- [obj_get_field_f32](functions-6.md#obj_get_field_f32)
- [obj_get_field_s16](functions-6.md#obj_get_field_s16)
- [obj_set_field_u32](functions-6.md#obj_set_field_u32)
- [obj_set_field_s32](functions-6.md#obj_set_field_s32)
- [obj_set_field_f32](functions-6.md#obj_set_field_f32)
- [obj_set_field_s16](functions-6.md#obj_set_field_s16)
- [obj_get_temp_spawn_particles_info](functions-6.md#obj_get_temp_spawn_particles_info)
- [get_temp_object_hitbox](functions-6.md#get_temp_object_hitbox)
- [obj_is_attackable](functions-6.md#obj_is_attackable)
- [obj_is_breakable_object](functions-6.md#obj_is_breakable_object)
- [obj_is_bully](functions-6.md#obj_is_bully)
- [obj_is_coin](functions-6.md#obj_is_coin)
- [obj_is_exclamation_box](functions-6.md#obj_is_exclamation_box)
- [obj_is_grabbable](functions-6.md#obj_is_grabbable)
- [obj_is_mushroom_1up](functions-6.md#obj_is_mushroom_1up)
- [obj_is_secret](functions-6.md#obj_is_secret)
- [obj_is_valid_for_interaction](functions-6.md#obj_is_valid_for_interaction)
- [obj_check_hitbox_overlap](functions-6.md#obj_check_hitbox_overlap)
- [obj_check_overlap_with_hitbox_params](functions-6.md#obj_check_overlap_with_hitbox_params)
- [obj_set_vel](functions-6.md#obj_set_vel)
- [obj_move_xyz](functions-6.md#obj_move_xyz)
- [set_whirlpools](functions-6.md#set_whirlpools)
- [spawn_sync_object](functions-7.md#spawn_sync_object)
- [spawn_non_sync_object](functions-7.md#spawn_non_sync_object)
- [obj_has_behavior_id](functions-7.md#obj_has_behavior_id)
- [obj_has_model_extended](functions-7.md#obj_has_model_extended)
- [obj_get_model_id_extended](functions-7.md#obj_get_model_id_extended)
- [obj_set_model_extended](functions-7.md#obj_set_model_extended)
- [get_trajectory](functions-7.md#get_trajectory)
- [geo_get_current_object](functions-7.md#geo_get_current_object)
- [get_current_object](functions-7.md#get_current_object)
- [get_dialog_object](functions-7.md#get_dialog_object)
- [get_cutscene_focus](functions-7.md#get_cutscene_focus)
- [get_secondary_camera_focus](functions-7.md#get_secondary_camera_focus)
- [set_cutscene_focus](functions-7.md#set_cutscene_focus)
- [set_secondary_camera_focus](functions-7.md#set_secondary_camera_focus)
- [obj_get_first](functions-7.md#obj_get_first)
- [obj_get_first_with_behavior_id](functions-7.md#obj_get_first_with_behavior_id)
- [obj_get_first_with_behavior_id_and_field_s32](functions-7.md#obj_get_first_with_behavior_id_and_field_s32)
- [obj_get_first_with_behavior_id_and_field_f32](functions-7.md#obj_get_first_with_behavior_id_and_field_f32)
- [obj_get_next](functions-7.md#obj_get_next)
- [obj_get_next_with_same_behavior_id](functions-7.md#obj_get_next_with_same_behavior_id)
- [obj_get_next_with_same_behavior_id_and_field_s32](functions-7.md#obj_get_next_with_same_behavior_id_and_field_s32)
- [obj_get_next_with_same_behavior_id_and_field_f32](functions-7.md#obj_get_next_with_same_behavior_id_and_field_f32)
- [obj_get_nearest_object_with_behavior_id](functions-7.md#obj_get_nearest_object_with_behavior_id)
- [obj_count_objects_with_behavior_id](functions-7.md#obj_count_objects_with_behavior_id)
- [obj_get_collided_object](functions-7.md#obj_get_collided_object)
- [obj_get_field_u32](functions-7.md#obj_get_field_u32)
- [obj_get_field_s32](functions-7.md#obj_get_field_s32)
- [obj_get_field_f32](functions-7.md#obj_get_field_f32)
- [obj_get_field_s16](functions-7.md#obj_get_field_s16)
- [obj_set_field_u32](functions-7.md#obj_set_field_u32)
- [obj_set_field_s32](functions-7.md#obj_set_field_s32)
- [obj_set_field_f32](functions-7.md#obj_set_field_f32)
- [obj_set_field_s16](functions-7.md#obj_set_field_s16)
- [obj_get_temp_spawn_particles_info](functions-7.md#obj_get_temp_spawn_particles_info)
- [get_temp_object_hitbox](functions-7.md#get_temp_object_hitbox)
- [obj_is_attackable](functions-7.md#obj_is_attackable)
- [obj_is_breakable_object](functions-7.md#obj_is_breakable_object)
- [obj_is_bully](functions-7.md#obj_is_bully)
- [obj_is_coin](functions-7.md#obj_is_coin)
- [obj_is_exclamation_box](functions-7.md#obj_is_exclamation_box)
- [obj_is_grabbable](functions-7.md#obj_is_grabbable)
- [obj_is_mushroom_1up](functions-7.md#obj_is_mushroom_1up)
- [obj_is_secret](functions-7.md#obj_is_secret)
- [obj_is_valid_for_interaction](functions-7.md#obj_is_valid_for_interaction)
- [obj_check_hitbox_overlap](functions-7.md#obj_check_hitbox_overlap)
- [obj_check_overlap_with_hitbox_params](functions-7.md#obj_check_overlap_with_hitbox_params)
- [obj_set_vel](functions-7.md#obj_set_vel)
- [obj_move_xyz](functions-7.md#obj_move_xyz)
- [set_whirlpools](functions-7.md#set_whirlpools)
<br />
- smlua_text_utils.h
- [smlua_text_utils_reset_all](functions-6.md#smlua_text_utils_reset_all)
- [smlua_text_utils_dialog_get](functions-6.md#smlua_text_utils_dialog_get)
- [smlua_text_utils_dialog_replace](functions-6.md#smlua_text_utils_dialog_replace)
- [smlua_text_utils_dialog_restore](functions-6.md#smlua_text_utils_dialog_restore)
- [smlua_text_utils_dialog_is_replaced](functions-6.md#smlua_text_utils_dialog_is_replaced)
- [smlua_text_utils_allocate_dialog](functions-6.md#smlua_text_utils_allocate_dialog)
- [smlua_text_utils_course_acts_replace](functions-6.md#smlua_text_utils_course_acts_replace)
- [smlua_text_utils_secret_star_replace](functions-6.md#smlua_text_utils_secret_star_replace)
- [smlua_text_utils_course_name_replace](functions-6.md#smlua_text_utils_course_name_replace)
- [smlua_text_utils_course_name_get](functions-6.md#smlua_text_utils_course_name_get)
- [smlua_text_utils_course_name_mod_index](functions-6.md#smlua_text_utils_course_name_mod_index)
- [smlua_text_utils_course_name_reset](functions-6.md#smlua_text_utils_course_name_reset)
- [smlua_text_utils_act_name_replace](functions-6.md#smlua_text_utils_act_name_replace)
- [smlua_text_utils_act_name_get](functions-6.md#smlua_text_utils_act_name_get)
- [smlua_text_utils_act_name_mod_index](functions-6.md#smlua_text_utils_act_name_mod_index)
- [smlua_text_utils_act_name_reset](functions-6.md#smlua_text_utils_act_name_reset)
- [smlua_text_utils_castle_secret_stars_replace](functions-6.md#smlua_text_utils_castle_secret_stars_replace)
- [smlua_text_utils_castle_secret_stars_get](functions-6.md#smlua_text_utils_castle_secret_stars_get)
- [smlua_text_utils_castle_secret_stars_mod_index](functions-6.md#smlua_text_utils_castle_secret_stars_mod_index)
- [smlua_text_utils_castle_secret_stars_reset](functions-6.md#smlua_text_utils_castle_secret_stars_reset)
- [smlua_text_utils_extra_text_replace](functions-6.md#smlua_text_utils_extra_text_replace)
- [smlua_text_utils_extra_text_get](functions-6.md#smlua_text_utils_extra_text_get)
- [smlua_text_utils_extra_text_mod_index](functions-6.md#smlua_text_utils_extra_text_mod_index)
- [smlua_text_utils_extra_text_reset](functions-6.md#smlua_text_utils_extra_text_reset)
- [smlua_text_utils_get_language](functions-6.md#smlua_text_utils_get_language)
- [smlua_text_utils_reset_all](functions-7.md#smlua_text_utils_reset_all)
- [smlua_text_utils_dialog_get](functions-7.md#smlua_text_utils_dialog_get)
- [smlua_text_utils_dialog_replace](functions-7.md#smlua_text_utils_dialog_replace)
- [smlua_text_utils_dialog_restore](functions-7.md#smlua_text_utils_dialog_restore)
- [smlua_text_utils_dialog_is_replaced](functions-7.md#smlua_text_utils_dialog_is_replaced)
- [smlua_text_utils_allocate_dialog](functions-7.md#smlua_text_utils_allocate_dialog)
- [smlua_text_utils_course_acts_replace](functions-7.md#smlua_text_utils_course_acts_replace)
- [smlua_text_utils_secret_star_replace](functions-7.md#smlua_text_utils_secret_star_replace)
- [smlua_text_utils_course_name_replace](functions-7.md#smlua_text_utils_course_name_replace)
- [smlua_text_utils_course_name_get](functions-7.md#smlua_text_utils_course_name_get)
- [smlua_text_utils_course_name_mod_index](functions-7.md#smlua_text_utils_course_name_mod_index)
- [smlua_text_utils_course_name_reset](functions-7.md#smlua_text_utils_course_name_reset)
- [smlua_text_utils_act_name_replace](functions-7.md#smlua_text_utils_act_name_replace)
- [smlua_text_utils_act_name_get](functions-7.md#smlua_text_utils_act_name_get)
- [smlua_text_utils_act_name_mod_index](functions-7.md#smlua_text_utils_act_name_mod_index)
- [smlua_text_utils_act_name_reset](functions-7.md#smlua_text_utils_act_name_reset)
- [smlua_text_utils_castle_secret_stars_replace](functions-7.md#smlua_text_utils_castle_secret_stars_replace)
- [smlua_text_utils_castle_secret_stars_get](functions-7.md#smlua_text_utils_castle_secret_stars_get)
- [smlua_text_utils_castle_secret_stars_mod_index](functions-7.md#smlua_text_utils_castle_secret_stars_mod_index)
- [smlua_text_utils_castle_secret_stars_reset](functions-7.md#smlua_text_utils_castle_secret_stars_reset)
- [smlua_text_utils_extra_text_replace](functions-7.md#smlua_text_utils_extra_text_replace)
- [smlua_text_utils_extra_text_get](functions-7.md#smlua_text_utils_extra_text_get)
- [smlua_text_utils_extra_text_mod_index](functions-7.md#smlua_text_utils_extra_text_mod_index)
- [smlua_text_utils_extra_text_reset](functions-7.md#smlua_text_utils_extra_text_reset)
- [smlua_text_utils_get_language](functions-7.md#smlua_text_utils_get_language)
<br />
- sound_init.h
- [reset_volume](functions-6.md#reset_volume)
- [raise_background_noise](functions-6.md#raise_background_noise)
- [lower_background_noise](functions-6.md#lower_background_noise)
- [disable_background_sound](functions-6.md#disable_background_sound)
- [enable_background_sound](functions-6.md#enable_background_sound)
- [play_menu_sounds](functions-6.md#play_menu_sounds)
- [play_painting_eject_sound](functions-6.md#play_painting_eject_sound)
- [play_infinite_stairs_music](functions-6.md#play_infinite_stairs_music)
- [set_background_music](functions-6.md#set_background_music)
- [fadeout_music](functions-6.md#fadeout_music)
- [fadeout_level_music](functions-6.md#fadeout_level_music)
- [play_cutscene_music](functions-6.md#play_cutscene_music)
- [play_shell_music](functions-6.md#play_shell_music)
- [stop_shell_music](functions-6.md#stop_shell_music)
- [play_cap_music](functions-6.md#play_cap_music)
- [fadeout_cap_music](functions-6.md#fadeout_cap_music)
- [stop_cap_music](functions-6.md#stop_cap_music)
- [reset_volume](functions-7.md#reset_volume)
- [raise_background_noise](functions-7.md#raise_background_noise)
- [lower_background_noise](functions-7.md#lower_background_noise)
- [disable_background_sound](functions-7.md#disable_background_sound)
- [enable_background_sound](functions-7.md#enable_background_sound)
- [play_menu_sounds](functions-7.md#play_menu_sounds)
- [play_painting_eject_sound](functions-7.md#play_painting_eject_sound)
- [play_infinite_stairs_music](functions-7.md#play_infinite_stairs_music)
- [set_background_music](functions-7.md#set_background_music)
- [fadeout_music](functions-7.md#fadeout_music)
- [fadeout_level_music](functions-7.md#fadeout_level_music)
- [play_cutscene_music](functions-7.md#play_cutscene_music)
- [play_shell_music](functions-7.md#play_shell_music)
- [stop_shell_music](functions-7.md#stop_shell_music)
- [play_cap_music](functions-7.md#play_cap_music)
- [fadeout_cap_music](functions-7.md#fadeout_cap_music)
- [stop_cap_music](functions-7.md#stop_cap_music)
<br />
- spawn_sound.h
- [cur_obj_play_sound_1](functions-6.md#cur_obj_play_sound_1)
- [cur_obj_play_sound_2](functions-6.md#cur_obj_play_sound_2)
- [create_sound_spawner](functions-6.md#create_sound_spawner)
- [calc_dist_to_volume_range_1](functions-6.md#calc_dist_to_volume_range_1)
- [calc_dist_to_volume_range_2](functions-6.md#calc_dist_to_volume_range_2)
- [cur_obj_play_sound_1](functions-7.md#cur_obj_play_sound_1)
- [cur_obj_play_sound_2](functions-7.md#cur_obj_play_sound_2)
- [create_sound_spawner](functions-7.md#create_sound_spawner)
- [calc_dist_to_volume_range_1](functions-7.md#calc_dist_to_volume_range_1)
- [calc_dist_to_volume_range_2](functions-7.md#calc_dist_to_volume_range_2)
<br />
- surface_collision.h
- [find_wall_collisions](functions-6.md#find_wall_collisions)
- [find_ceil_height](functions-6.md#find_ceil_height)
- [find_floor_height](functions-6.md#find_floor_height)
- [find_water_level](functions-6.md#find_water_level)
- [find_poison_gas_level](functions-6.md#find_poison_gas_level)
- [set_find_wall_direction](functions-6.md#set_find_wall_direction)
- [closest_point_to_triangle](functions-6.md#closest_point_to_triangle)
- [find_wall_collisions](functions-7.md#find_wall_collisions)
- [find_ceil_height](functions-7.md#find_ceil_height)
- [find_floor_height](functions-7.md#find_floor_height)
- [find_water_level](functions-7.md#find_water_level)
- [find_poison_gas_level](functions-7.md#find_poison_gas_level)
- [set_find_wall_direction](functions-7.md#set_find_wall_direction)
- [closest_point_to_triangle](functions-7.md#closest_point_to_triangle)
<br />
- surface_load.h
- [load_object_collision_model](functions-6.md#load_object_collision_model)
- [obj_get_surface_from_index](functions-6.md#obj_get_surface_from_index)
- [surface_has_force](functions-6.md#surface_has_force)
- [load_object_collision_model](functions-7.md#load_object_collision_model)
- [load_static_object_collision](functions-7.md#load_static_object_collision)
- [toggle_static_object_collision](functions-7.md#toggle_static_object_collision)
- [get_static_object_surface](functions-7.md#get_static_object_surface)
- [obj_get_surface_from_index](functions-7.md#obj_get_surface_from_index)
- [surface_has_force](functions-7.md#surface_has_force)
<br />

View file

@ -1,3 +1,5 @@
## [:rewind: Lua Reference](../lua.md)
# How to use the Lighting Engine
## Section 1: Preparation

View file

@ -1,3 +1,5 @@
## [:rewind: Lua Reference](../lua.md)
# How to use `gMarioStates`
## Section 1: What is `gMarioStates`?

272
docs/lua/guides/modfs.md Normal file
View file

@ -0,0 +1,272 @@
## [:rewind: Lua Reference](../lua.md)
# ModFS
`ModFS` enables a small, sandboxed file system for mods. It allows to store and retrieve binary and text files, no matter their content.<br>
Each mod has its own file system, and can allow other mods to read its files.
<br>
## Specs
### File system
Each ModFS file system:
- Has a maximum size of **32 MB** (`MOD_FS_MAX_SIZE`). Files can be any size, as long as the cumulative sum of file sizes doesn't exceed this limit.
- Can store at most **512 files** (`MOD_FS_MAX_FILES`).
- Is stored on disk as a `.modfs` file, which is a ZIP file, containing all files written in it.
The ModFS files are located in the `sav` directory at the usual save file location:
- Windows: `%appdata%/sm64coopdx`
- Linux: `~/.local/share/sm64coopdx`
- MacOS: `~/Library/Application Support/sm64coopdx`
### Files
- The maximum filepath length is **256 characters** (`MOD_FS_MAX_PATH`), including the NUL terminator.
- Filepaths have the following restrictions:
- Cannot start, end or have two or more consecutive `/`
- Can contain only valid ASCII characters, no `*` or `\`
- Cannot be called `properties.json` (this name is reserved for ModFS internal properties)
- Only the following extensions (and extension-less files) are allowed:
- text: `.txt`, `.json`, `.ini`, `.sav`
- actors: `.bin`, `.col`
- behaviors: `.bhv`
- textures: `.tex`, `.png`
- levels: `.lvl`
- audio: `.m64`, `.aiff`, `.mp3`, `.ogg`
<br>
## [`ModFs`](../structs.md#ModFs)
The object holding the file system of the mod.
### Fields
All fields are immutable.
| Name | Type |
| ----- | ---- |
| mod | [Mod](../structs.md#Mod) |
| modPath | `string` |
| numFiles | `integer` |
| totalSize | `integer` |
| isPublic | `boolean` |
Fields can be accessed in Lua with the dot `.` character:
```lua
print("The ModFS " .. modFs.modPath .. " contains " .. modFs.numFiles .. " files.")
```
### Methods
| Name | Reference |
| ---- | --------- |
| get_filename | [`mod_fs_get_filename`](../functions-5.md#mod_fs_get_filename) |
| get_file | [`mod_fs_get_file`](../functions-5.md#mod_fs_get_file) |
| create_file | [`mod_fs_create_file`](../functions-5.md#mod_fs_create_file) |
| move_file | [`mod_fs_move_file`](../functions-5.md#mod_fs_move_file) |
| copy_file | [`mod_fs_copy_file`](../functions-5.md#mod_fs_copy_file) |
| delete_file | [`mod_fs_delete_file`](../functions-5.md#mod_fs_delete_file) |
| clear | [`mod_fs_clear`](../functions-5.md#mod_fs_clear) |
| save | [`mod_fs_save`](../functions-5.md#mod_fs_save) |
| delete | [`mod_fs_delete`](../functions-5.md#mod_fs_delete) |
| set_public | [`mod_fs_set_public`](../functions-5.md#mod_fs_set_public) |
Methods can be called in Lua with the colon `:` character:
```lua
print("The first file of ModFS " .. modFs.modPath .. " is named " .. modFs:get_filename(0) .. ".")
```
<br>
## [`ModFsFile`](../structs.md#ModFsFile)
A handle to a ModFS file.
### Fields
All fields are immutable.
| Field | Type |
| ----- | ---- |
| modFs | [ModFs](../structs.md#ModFs) |
| filepath | `string` |
| size | `integer` |
| offset | `integer` |
| isText | `boolean` |
| isPublic | `boolean` |
Fields can be accessed in Lua with the dot `.` character:
```lua
print("The ModFS file " .. file.filepath .. " is " .. file.size .. " bytes long.")
```
### Methods
| Name | Reference |
| ---- | --------- |
| read_bool | [`mod_fs_file_read_bool`](../functions-5.md#mod_fs_file_read_bool) |
| read_integer | [`mod_fs_file_read_integer`](../functions-5.md#mod_fs_file_read_integer) |
| read_number | [`mod_fs_file_read_number`](../functions-5.md#mod_fs_file_read_number) |
| read_bytes | [`mod_fs_file_read_bytes`](../functions-5.md#mod_fs_file_read_bytes) |
| read_string | [`mod_fs_file_read_string`](../functions-5.md#mod_fs_file_read_string) |
| read_line | [`mod_fs_file_read_line`](../functions-5.md#mod_fs_file_read_line) |
| write_bool | [`mod_fs_file_write_bool`](../functions-5.md#mod_fs_file_write_bool) |
| write_integer | [`mod_fs_file_write_integer`](../functions-5.md#mod_fs_file_write_integer) |
| write_number | [`mod_fs_file_write_number`](../functions-5.md#mod_fs_file_write_number) |
| write_bytes | [`mod_fs_file_write_bytes`](../functions-5.md#mod_fs_file_write_bytes) |
| write_string | [`mod_fs_file_write_string`](../functions-5.md#mod_fs_file_write_string) |
| write_line | [`mod_fs_file_write_line`](../functions-5.md#mod_fs_file_write_line) |
| seek | [`mod_fs_file_seek`](../functions-5.md#mod_fs_file_seek) |
| rewind | [`mod_fs_file_rewind`](../functions-5.md#mod_fs_file_rewind) |
| is_eof | [`mod_fs_file_is_eof`](../functions-5.md#mod_fs_file_is_eof) |
| fill | [`mod_fs_file_fill`](../functions-5.md#mod_fs_file_fill) |
| erase | [`mod_fs_file_erase`](../functions-5.md#mod_fs_file_erase) |
| set_text_mode | [`mod_fs_file_set_text_mode`](../functions-5.md#mod_fs_file_set_text_mode) |
| set_public | [`mod_fs_file_set_public`](../functions-5.md#mod_fs_file_set_public) |
Methods can be called in Lua with the colon `:` character:
```lua
file:erase(file.size)
print("The ModFS file " .. file.filepath .. " is now empty.")
```
<br>
## Error handling
All errors coming from ModFS functions are not blocking. However, they appear in the console and raise the "Mod has script errors" message.
- The function [`mod_fs_hide_errors`](../functions-5.md#mod_fs_hide_errors) can suppress the ModFS errors from the console.
- Use the function [`mod_fs_get_last_error`](../functions-5.md#mod_fs_get_last_error) to retrieve the last error raised by ModFS. This function always return an error message if an error occurred, even if errors are hidden.
<br>
## Usage with other sm64coopdx features
One of the strengths of this feature is its interactions with other existing features of sm64coopdx:
- Load models with `smlua_model_util_get_id`
- Load textures with `get_texture_info`
- Load collisions with `smlua_collision_util_get`
- Load sequences with `smlua_audio_utils_replace_sequence`
- Load audio streams with `audio_stream_load`
- Load audio samples with `audio_sample_load`
These functions can take a **ModFS URI** as argument instead of a resource name.<br>
Generate a ModFS URI from a `ModFs` object with the following code:
```lua
local uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "<filepath>")
```
Here are some examples:
```lua
-- Models
local custom_geo_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "custom_geo.bin")
local E_MODEL_CUSTOM = smlua_model_util_get_id(custom_geo_uri)
-- Textures (both PNG and TEX)
local texture_png_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "texture.png")
local TEXTURE_PNG = get_texture_info(texture_png_uri)
local texture_tex_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "texture.tex")
local TEXTURE_TEX = get_texture_info(texture_tex_uri)
-- Collisions
local custom_col_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "custom_col.col")
local COL_CUSTOM = smlua_collision_util_get(custom_col_uri)
-- Sequences
local custom_m64_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "custom.m64")
smlua_audio_utils_replace_sequence(SEQ_LEVEL_GRASS, 0x11, 0x80, custom_m64_uri)
-- Streams
local custom_stream_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "custom_stream.mp3")
local custom_stream = audio_stream_load(custom_stream_uri)
-- Samples
local custom_sample_uri = string.format(MOD_FS_URI_FORMAT, modFs.modPath, "custom_sample.mp3")
local custom_sample = audio_sample_load(custom_sample_uri)
```
<br>
## Good practices
### Always valid `ModFs` object
Use the following piece of code to always retrieve a valid `ModFs` object:
```lua
local modFs = mod_fs_get() or mod_fs_create()
```
If the ModFS for the current mod doesn't exist, it will create one.
<br>
### Always valid `ModFsFile` object
Use the following piece of code to always retrieve a valid `ModFsFile` object:
```lua
local file = modFs:get_file("myfile.txt") or modFs:create_file("myfile.txt", true)
```
Like previously, if the file doesn't exist, it will create one.<br>
To make sure the file is empty when requested, add the following line to clear the existing file content.
```lua
file:erase(file.size)
```
<br>
### Correctly initialize a file
The `get_file` method of a `ModFs` object opens a file only if the file is not loaded yet. Subsequent calls with the same filename will return the file handle without resetting its offset or mode.<br>
For example, one function could write to a file while another could read from the same file, so it's better to set the appropriate file offset and mode when it's needed before starting reading/writing:
```lua
local file = modFs:get_file("myfile.txt")
file:set_text_mode(true) -- Set mode to text
file:rewind() -- Reset offset to the beginning of the file
```
<br>
### Methods over functions
Always use `ModFs` and `ModFsFile` objects methods over regular functions.<br>
It's more clear that way and helps to reduce errors:
```lua
-- Don't
local file = mod_fs_create_file(modFs, "myfile.txt", true)
-- Do
local file = modFs:create_file("myfile.txt", true)
```
```lua
-- Don't
mod_fs_file_write_string(file, "some text")
-- Do
file:write_string("some text")
```
<br>
### Handle possible failures
In addition to error messages that can be retrieved with [`mod_fs_get_last_error`](../functions-5.md#mod_fs_get_last_error), almost all ModFS functions have a boolean return value indicating if the function succeeded or failed.
```lua
if not modFs:delete_file("somefile") then
print(mod_fs_get_last_error())
end
```
<br>
### Don't forget to save
ModFS are not saved automatically when writing to files.<br>
The mod has to explicitly call the method `save` to save its ModFS on the disk.
```lua
modFs:save()
```

View file

@ -1,3 +1,5 @@
## [:rewind: Lua Reference](../lua.md)
# Every Behavior's Object List
| Behavior | Object List |

View file

@ -34,6 +34,8 @@ Save file locations:
- [Hooks](guides/hooks.md)
- [gMarioStates](guides/mario-state.md)
- [Behavior Object Lists](guides/object-lists.md)
- [Lighting Engine](guides/lighting-engine.md)
- [ModFS](guides/modfs.md)
## Important notes on player indices
@ -69,7 +71,11 @@ All of this is a holdover from when there were only two players. It was a reason
- [Custom HUD Texture](examples/custom-hud-texture)
- [Custom Audio Test](examples/audio-test)
- [Custom Texture Overriding](examples/texture-override)
- [Custom Animations (DynOS)](examples/custom-animations-dynos)
- [Custom Animations (Lua)](examples/custom-animations-lua)
- [Bytestring Packet Example](examples/bytestring-packet-example.lua)
- [Gfx/Vtx Demo](examples/gfx-vtx-demo)
- [Lighting Engine Demo](examples/lighting-engine-demo)
## Example Lua mods (large)
- [Hide and Seek Gamemode](../../mods/hide-and-seek.lua)

View file

@ -105,6 +105,7 @@
- [SpawnParticlesInfo](#SpawnParticlesInfo)
- [StarPositions](#StarPositions)
- [StarsNeededForDialog](#StarsNeededForDialog)
- [StaticObjectCollision](#StaticObjectCollision)
- [Surface](#Surface)
- [TextureInfo](#TextureInfo)
- [TransitionInfo](#TransitionInfo)
@ -1955,7 +1956,7 @@
| Field | Type | Access |
| ----- | ---- | ------ |
| file | [ModFile](structs.md#ModFile) | |
| filepath | `string` | read-only |
| isStream | `boolean` | read-only |
| baseVolume | `number` | |
| loaded | `boolean` | read-only |
@ -2001,6 +2002,21 @@
| totalSize | `integer` | read-only |
| isPublic | `boolean` | read-only |
**Functions:**
| Name | Reference |
| ---- | --------- |
| get_filename | [`mod_fs_get_filename`](functions-5.md#mod_fs_get_filename) |
| get_file | [`mod_fs_get_file`](functions-5.md#mod_fs_get_file) |
| create_file | [`mod_fs_create_file`](functions-5.md#mod_fs_create_file) |
| move_file | [`mod_fs_move_file`](functions-5.md#mod_fs_move_file) |
| copy_file | [`mod_fs_copy_file`](functions-5.md#mod_fs_copy_file) |
| delete_file | [`mod_fs_delete_file`](functions-5.md#mod_fs_delete_file) |
| clear | [`mod_fs_clear`](functions-5.md#mod_fs_clear) |
| save | [`mod_fs_save`](functions-5.md#mod_fs_save) |
| delete | [`mod_fs_delete`](functions-5.md#mod_fs_delete) |
| set_public | [`mod_fs_set_public`](functions-5.md#mod_fs_set_public) |
[:arrow_up_small:](#)
<br />
@ -2016,6 +2032,30 @@
| isText | `boolean` | read-only |
| isPublic | `boolean` | read-only |
**Functions:**
| Name | Reference |
| ---- | --------- |
| read_bool | [`mod_fs_file_read_bool`](functions-5.md#mod_fs_file_read_bool) |
| read_integer | [`mod_fs_file_read_integer`](functions-5.md#mod_fs_file_read_integer) |
| read_number | [`mod_fs_file_read_number`](functions-5.md#mod_fs_file_read_number) |
| read_bytes | [`mod_fs_file_read_bytes`](functions-5.md#mod_fs_file_read_bytes) |
| read_string | [`mod_fs_file_read_string`](functions-5.md#mod_fs_file_read_string) |
| read_line | [`mod_fs_file_read_line`](functions-5.md#mod_fs_file_read_line) |
| write_bool | [`mod_fs_file_write_bool`](functions-5.md#mod_fs_file_write_bool) |
| write_integer | [`mod_fs_file_write_integer`](functions-5.md#mod_fs_file_write_integer) |
| write_number | [`mod_fs_file_write_number`](functions-5.md#mod_fs_file_write_number) |
| write_bytes | [`mod_fs_file_write_bytes`](functions-5.md#mod_fs_file_write_bytes) |
| write_string | [`mod_fs_file_write_string`](functions-5.md#mod_fs_file_write_string) |
| write_line | [`mod_fs_file_write_line`](functions-5.md#mod_fs_file_write_line) |
| seek | [`mod_fs_file_seek`](functions-5.md#mod_fs_file_seek) |
| rewind | [`mod_fs_file_rewind`](functions-5.md#mod_fs_file_rewind) |
| is_eof | [`mod_fs_file_is_eof`](functions-5.md#mod_fs_file_is_eof) |
| fill | [`mod_fs_file_fill`](functions-5.md#mod_fs_file_fill) |
| erase | [`mod_fs_file_erase`](functions-5.md#mod_fs_file_erase) |
| set_text_mode | [`mod_fs_file_set_text_mode`](functions-5.md#mod_fs_file_set_text_mode) |
| set_public | [`mod_fs_file_set_public`](functions-5.md#mod_fs_file_set_public) |
[:arrow_up_small:](#)
<br />
@ -2947,10 +2987,9 @@
| rippleTimer | `number` | |
| rippleX | `number` | |
| rippleY | `number` | |
| normalDisplayList | `Pointer` <`Gfx`> | read-only |
| textureArray | `Array` <`Pointer` <`Texture`>> | read-only |
| textureWidth | `integer` | read-only |
| textureHeight | `integer` | read-only |
| rippleDisplayList | `Pointer` <`Gfx`> | read-only |
| rippleTrigger | `integer` | |
| alpha | `integer` | |
| marioWasUnder | `integer` | |
@ -3211,6 +3250,17 @@
<br />
## [StaticObjectCollision](#StaticObjectCollision)
| Field | Type | Access |
| ----- | ---- | ------ |
| index | `integer` | read-only |
| length | `integer` | read-only |
[:arrow_up_small:](#)
<br />
## [Surface](#Surface)
| Field | Type | Access |
@ -3240,7 +3290,7 @@
| Field | Type | Access |
| ----- | ---- | ------ |
| texture | `Pointer` <`integer`> | read-only |
| texture | `Pointer` <`Texture`> | read-only |
| name | `string` | read-only |
| width | `integer` | read-only |
| height | `integer` | read-only |

View file

@ -7,6 +7,9 @@
#define G_LIGHT_MAP_EXT 0x00000800
#define G_LIGHTING_ENGINE_EXT 0x00004000
#define G_PACKED_NORMALS_EXT 0x00000080
#define G_CULL_INVERT_EXT 0x00000100
#define G_FRESNEL_COLOR_EXT 0x00000040
#define G_FRESNEL_ALPHA_EXT 0x00400000
//////////
// DJUI //
@ -118,3 +121,50 @@
(_SHIFTL(G_PPARTTOCOLOR, 24, 8)) | (_SHIFTL(color, 16, 8)), \
((2 * ((part) + 1)) + 1 + offset) \
}}
////////////////////
//// G_MOVEWORD ////
////////////////////
#define G_MW_FX 0x00 /* replaces G_MW_MATRIX which is no longer supported */
#define G_MWO_FRESNEL 0x0C
/**
* Fresnel - Feature suggested by thecozies
* Enabled with the G_FRESNEL bit in geometry mode.
* The dot product between a vertex normal and the vector from the vertex to the
* camera is computed. The offset and scale here convert this to a shade alpha
* value. This is useful for making surfaces fade between transparent when
* viewed straight-on and opaque when viewed at a large angle, or for applying a
* fake "outline" around the border of meshes.
*
* If using Fresnel, you need to set the camera world position whenever you set
* the VP matrix, viewport, etc. See SPCameraWorld.
*
* The RSP does:
* s16 dotProduct = dot(vertex normal, camera pos - vertex pos);
* dotProduct = abs(dotProduct); // 0 = points to side, 7FFF = points at or away
* s32 factor = ((scale * dotProduct) >> 15) + offset;
* s16 result = clamp(factor << 8, 0, 7FFF);
* color_or_alpha = result >> 7;
*
* At dotMax, color_or_alpha = FF, result = 7F80, factor = 7F
* At dotMin, color_or_alpha = 00, result = 0, factor = 0
* 7F = ((scale * dotMax) >> 15) + offset
* 00 = ((scale * dotMin) >> 15) + offset
* Subtract: 7F = (scale * (dotMax - dotMin)) >> 15
* 3F8000 = scale * (dotMax - dotMin)
* scale = 3F8000 / (dotMax - dotMin) <--
* offset = -(((3F8000 / (dotMax - dotMin)) * dotMin) >> 15)
* offset = -((7F * dotMin) / (dotMax - dotMin)) <--
*
* To convert in the opposite direction:
* ((7F - offset) << 15) / scale = dotMax
* ((00 - offset) << 15) / scale = dotMin
*/
#define gSPFresnel(pkt, scale, offset) \
gMoveWd(pkt, G_MW_FX, G_MWO_FRESNEL, \
(_SHIFTL((scale), 16, 16) | _SHIFTL((offset), 0, 16)))
#define gsSPFresnel(scale, offset) \
gsMoveWd(G_MW_FX, G_MWO_FRESNEL, \
(_SHIFTL((scale), 16, 16) | _SHIFTL((offset), 0, 16)))

View file

@ -56,6 +56,7 @@ define_gfx_symbol(gsMoveWd, 3, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GF
define_gfx_symbol(gsSPLoadGeometryMode, 1, false, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsSPVertexNonGlobal, 3, true, GFX_PARAM_TYPE_VTX, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsSPCopyPlayerPartToColor, 3, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsSPFresnel, 2, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol_manual(gsSPTexture, 5, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol_manual(gsSPSetGeometryMode, 1, false, GFX_PARAM_TYPE_INT);

View file

@ -30,6 +30,34 @@
#define WHIRLPOOL_COND_BOWSER2_BEATEN 2
#define WHIRLPOOL_COND_AT_LEAST_SECOND_STAR 3
#define OBJECT_EXT_LUA_MODEL (1 << 0)
#define OBJECT_EXT_LUA_POS_X (1 << 1)
#define OBJECT_EXT_LUA_POS_Y (1 << 2)
#define OBJECT_EXT_LUA_POS_Z (1 << 3)
#define OBJECT_EXT_LUA_ANGLE_X (1 << 4)
#define OBJECT_EXT_LUA_ANGLE_Y (1 << 5)
#define OBJECT_EXT_LUA_ANGLE_Z (1 << 6)
#define OBJECT_EXT_LUA_BEH_PARAMS (1 << 7)
#define OBJECT_EXT_LUA_BEHAVIOR (1 << 8)
#define OBJECT_EXT_LUA_ACTS (1 << 9)
#define OBJECT_EXT_LUA_MODEL_OFFSET(type) (type == 0x3F ? 3 : (type == 0x40 ? 20 : 4))
#define OBJECT_EXT_LUA_POS_X_OFFSET(type) (type == 0x3F ? 4 : (type == 0x40 ? 4 : 8))
#define OBJECT_EXT_LUA_POS_Y_OFFSET(type) (type == 0x3F ? 6 : (type == 0x40 ? 6 : 12))
#define OBJECT_EXT_LUA_POS_Z_OFFSET(type) (type == 0x3F ? 8 : (type == 0x40 ? 8 : 16))
#define OBJECT_EXT_LUA_ANGLE_X_OFFSET(type) (type == 0x3F ? 10 : (type == 0x40 ? 10 : 20))
#define OBJECT_EXT_LUA_ANGLE_Y_OFFSET(type) (type == 0x3F ? 12 : (type == 0x40 ? 12 : 24))
#define OBJECT_EXT_LUA_ANGLE_Z_OFFSET(type) (type == 0x3F ? 14 : (type == 0x40 ? 14 : 28))
#define OBJECT_EXT_LUA_BEH_PARAMS_OFFSET(type) (type == 0x3F ? 16 : (type == 0x40 ? 16 : 32))
#define OBJECT_EXT_LUA_BEHAVIOR_OFFSET(type) (type == 0x3F ? 20 : (type == 0x40 ? 24 : 36))
#define OBJECT_EXT_LUA_ACTS_OFFSET(type) (type == 0x3F ? 2 : (type == 0x40 ? 2 : 40))
#define SHOW_DIALOG_EXT_LUA_INDEX (1 << 0)
#define SHOW_DIALOG_EXT_LUA_DIALOG (1 << 1)
#define SHOW_DIALOG_EXT_LUA_INDEX_OFFSET(type) (4)
#define SHOW_DIALOG_EXT_LUA_DIALOG_OFFSET(type) (8)
// Head defines
#define REGULAR_FACE 0x0002
#define DIZZY_FACE 0x0003
@ -324,6 +352,30 @@
CMD_W(arg), \
CMD_PTR(target)
// This command is used when parameters are Lua variables.
// The flags parameter describes which parameter is a Lua variable.
// See OBJECT_EXT_LUA flags at the top of this file.
#define OBJECT_EXT_LUA_PARAMS(flags, model, posX, posY, posZ, angleX, angleY, angleZ, behParam, beh, acts) \
CMD_BBH(0x43, 0x2C, flags), \
CMD_PTR(model), \
CMD_PTR(posX), \
CMD_PTR(posY), \
CMD_PTR(posZ), \
CMD_PTR(angleX), \
CMD_PTR(angleY), \
CMD_PTR(angleZ), \
CMD_PTR(behParam), \
CMD_PTR(beh), \
CMD_PTR(acts)
// This command is used when parameters are Lua variables.
// The flags parameter describes which parameter is a Lua variable.
// See SHOW_DIALOG_EXT flags at the top of this file.
#define SHOW_DIALOG_EXT(flags, index, dialogId) \
CMD_BBBB(0x44, 0x0C, flags, 0x00), \
CMD_PTR(index), \
CMD_PTR(dialogId)
// README //
// README //
// README //

View file

@ -163,6 +163,7 @@
#define SURFACE_FLAG_DYNAMIC (1 << 0)
#define SURFACE_FLAG_NO_CAM_COLLISION (1 << 1)
#define SURFACE_FLAG_INTANGIBLE (1 << 2)
#define SURFACE_FLAG_X_PROJECTION (1 << 3)
#define HAZARD_TYPE_LAVA_FLOOR 1

View file

@ -577,7 +577,7 @@ struct MarioState
struct TextureInfo
{
u8 *texture;
Texture *texture;
const char *name;
u32 width;
u32 height;

View file

@ -1255,57 +1255,57 @@ static const Gfx inside_castle_seg7_painting_dl_070235B8[] = {
gsSPBranchList(inside_castle_seg7_painting_dl_07023580),
};
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235C0[] = {
inside_castle_seg7_texture_0700B800, inside_castle_seg7_texture_0700A800,
};
#define inside_castle_seg7_painting_textures_070235C0 { \
inside_castle_seg7_texture_0700B800, inside_castle_seg7_texture_0700A800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235C8[] = {
inside_castle_seg7_texture_0700D800, inside_castle_seg7_texture_0700C800,
};
#define inside_castle_seg7_painting_textures_070235C8 { \
inside_castle_seg7_texture_0700D800, inside_castle_seg7_texture_0700C800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235D0[] = {
inside_castle_seg7_texture_0700F800, inside_castle_seg7_texture_0700E800,
};
#define inside_castle_seg7_painting_textures_070235D0 { \
inside_castle_seg7_texture_0700F800, inside_castle_seg7_texture_0700E800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235D8[] = {
inside_castle_seg7_texture_07011800, inside_castle_seg7_texture_07010800,
};
#define inside_castle_seg7_painting_textures_070235D8 { \
inside_castle_seg7_texture_07011800, inside_castle_seg7_texture_07010800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235E0[] = {
inside_castle_seg7_texture_07012800, inside_castle_seg7_texture_07013800,
};
#define inside_castle_seg7_painting_textures_070235E0 { \
inside_castle_seg7_texture_07012800, inside_castle_seg7_texture_07013800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235E8[] = {
inside_castle_seg7_texture_07015800, inside_castle_seg7_texture_07014800,
};
#define inside_castle_seg7_painting_textures_070235E8 { \
inside_castle_seg7_texture_07015800, inside_castle_seg7_texture_07014800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235F0[] = {
inside_castle_seg7_texture_07016800,
};
#define inside_castle_seg7_painting_textures_070235F0 { \
inside_castle_seg7_texture_07016800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235F4[] = {
inside_castle_seg7_texture_07017000,
};
#define inside_castle_seg7_painting_textures_070235F4 { \
inside_castle_seg7_texture_07017000, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_070235F8[] = {
inside_castle_seg7_texture_07018800, inside_castle_seg7_texture_07017800,
};
#define inside_castle_seg7_painting_textures_070235F8 { \
inside_castle_seg7_texture_07018800, inside_castle_seg7_texture_07017800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023600[] = {
inside_castle_seg7_texture_0701A800, inside_castle_seg7_texture_07019800,
};
#define inside_castle_seg7_painting_textures_07023600 { \
inside_castle_seg7_texture_0701A800, inside_castle_seg7_texture_07019800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023608[] = {
inside_castle_seg7_texture_0701C800, inside_castle_seg7_texture_0701B800,
};
#define inside_castle_seg7_painting_textures_07023608 { \
inside_castle_seg7_texture_0701C800, inside_castle_seg7_texture_0701B800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023610[] = {
inside_castle_seg7_texture_0701E800, inside_castle_seg7_texture_0701D800,
};
#define inside_castle_seg7_painting_textures_07023610 { \
inside_castle_seg7_texture_0701E800, inside_castle_seg7_texture_0701D800, \
}
ALIGNED8 const Texture *const inside_castle_seg7_painting_textures_07023618[] = {
inside_castle_seg7_texture_07020800, inside_castle_seg7_texture_0701F800,
};
#define inside_castle_seg7_painting_textures_07023618 { \
inside_castle_seg7_texture_07020800, inside_castle_seg7_texture_0701F800, \
}
// 0x07023620 - 0x07023698
struct Painting bob_painting = {

View file

@ -505,9 +505,9 @@ static const Gfx hmc_seg7_painting_dl_070254E0[] = {
};
// 0x07025518 - 0x07025594
const Texture *const hmc_seg7_painting_textures_07025518[] = {
hmc_seg7_texture_07024CE0,
};
#define hmc_seg7_painting_textures_07025518 { \
hmc_seg7_texture_07024CE0, \
}
// 0x0702551C (PaintingData)
struct Painting cotmc_painting = {

View file

@ -537,9 +537,9 @@ static const Gfx ttm_seg7_painting_dl_07012E98[] = {
};
// 0x07012EF8 - 0x07012F78
ALIGNED8 const Texture *const ttm_seg7_painting_textures_07012EF8[] = {
ttm_seg7_texture_07004000, ttm_seg7_texture_07003000,
};
#define ttm_seg7_painting_textures_07012EF8 { \
ttm_seg7_texture_07004000, ttm_seg7_texture_07003000, \
}
// 0x07012F00 (PaintingData)
struct Painting ttm_slide_painting = {

View file

@ -99,51 +99,95 @@ local PALETTE_FL_WALUIGI = {
-- Sounds --
local DJ_TOAD_SOUNDS = {
SOUND_MARIO_YAH_WAH_HOO,
SOUND_MARIO_HOOHOO,
SOUND_MARIO_YAHOO,
SOUND_MARIO_UH,
SOUND_MARIO_HRMM,
SOUND_MARIO_WAH2,
SOUND_MARIO_WHOA,
SOUND_MARIO_EEUH,
SOUND_MARIO_ATTACKED,
SOUND_MARIO_OOOF,
SOUND_MARIO_OOOF2,
SOUND_MARIO_HERE_WE_GO,
SOUND_MARIO_YAWNING,
SOUND_MARIO_SNORING1,
SOUND_MARIO_SNORING2,
SOUND_MARIO_WAAAOOOW,
SOUND_MARIO_HAHA,
SOUND_MARIO_HAHA_2,
SOUND_MARIO_UH2,
SOUND_MARIO_UH2_2,
SOUND_MARIO_ON_FIRE,
SOUND_MARIO_DYING,
SOUND_MARIO_PANTING_COLD,
SOUND_MARIO_PANTING,
SOUND_MARIO_COUGHING1,
SOUND_MARIO_COUGHING2,
SOUND_MARIO_COUGHING3,
SOUND_MARIO_PUNCH_YAH,
SOUND_MARIO_PUNCH_HOO,
SOUND_MARIO_MAMA_MIA,
SOUND_MARIO_GROUND_POUND_WAH,
SOUND_MARIO_DROWNING,
SOUND_MARIO_PUNCH_WAH,
SOUND_MARIO_YAHOO_WAHA_YIPPEE,
SOUND_MARIO_DOH,
SOUND_MARIO_GAME_OVER,
SOUND_MARIO_HELLO,
SOUND_MARIO_PRESS_START_TO_PLAY,
SOUND_MARIO_TWIRL_BOUNCE,
SOUND_MARIO_SNORING3,
SOUND_MARIO_SO_LONGA_BOWSER,
SOUND_MARIO_IMA_TIRED,
SOUND_MARIO_LETS_A_GO,
SOUND_MARIO_OKEY_DOKEY
local MARIO_SOUNDS = {
[CHAR_SOUND_OKEY_DOKEY] = SOUND_MARIO_OKEY_DOKEY,
[CHAR_SOUND_LETS_A_GO] = SOUND_MARIO_LETS_A_GO,
[CHAR_SOUND_PUNCH_YAH] = SOUND_MARIO_PUNCH_YAH,
[CHAR_SOUND_PUNCH_WAH] = SOUND_MARIO_PUNCH_WAH,
[CHAR_SOUND_WAH2] = SOUND_MARIO_WAH2,
[CHAR_SOUND_PUNCH_HOO] = SOUND_MARIO_PUNCH_HOO,
[CHAR_SOUND_YAH_WAH_HOO] = SOUND_MARIO_YAH_WAH_HOO,
[CHAR_SOUND_HOOHOO] = SOUND_MARIO_HOOHOO,
[CHAR_SOUND_YAHOO_WAHA_YIPPEE] = SOUND_MARIO_YAHOO_WAHA_YIPPEE,
[CHAR_SOUND_UH] = SOUND_MARIO_UH,
[CHAR_SOUND_UH2] = SOUND_MARIO_UH2,
[CHAR_SOUND_UH2_2] = SOUND_MARIO_UH2_2,
[CHAR_SOUND_HAHA] = SOUND_MARIO_HAHA,
[CHAR_SOUND_HAHA_2] = SOUND_MARIO_HAHA_2,
[CHAR_SOUND_YAHOO] = SOUND_MARIO_YAHOO,
[CHAR_SOUND_DOH] = SOUND_MARIO_DOH,
[CHAR_SOUND_WHOA] = SOUND_MARIO_WHOA,
[CHAR_SOUND_EEUH] = SOUND_MARIO_EEUH,
[CHAR_SOUND_WAAAOOOW] = SOUND_MARIO_WAAAOOOW,
[CHAR_SOUND_TWIRL_BOUNCE] = SOUND_MARIO_TWIRL_BOUNCE,
[CHAR_SOUND_GROUND_POUND_WAH] = SOUND_MARIO_GROUND_POUND_WAH,
[CHAR_SOUND_HRMM] = SOUND_MARIO_HRMM,
[CHAR_SOUND_HERE_WE_GO] = SOUND_MARIO_HERE_WE_GO,
[CHAR_SOUND_SO_LONGA_BOWSER] = SOUND_MARIO_SO_LONGA_BOWSER,
[CHAR_SOUND_OOOF] = SOUND_MARIO_OOOF,
[CHAR_SOUND_OOOF2] = SOUND_MARIO_OOOF2,
[CHAR_SOUND_ATTACKED] = SOUND_MARIO_ATTACKED,
[CHAR_SOUND_PANTING] = SOUND_MARIO_PANTING,
[CHAR_SOUND_PANTING_COLD] = SOUND_MARIO_PANTING_COLD,
[CHAR_SOUND_ON_FIRE] = SOUND_MARIO_ON_FIRE,
[CHAR_SOUND_IMA_TIRED] = SOUND_MARIO_IMA_TIRED,
[CHAR_SOUND_YAWNING] = SOUND_MARIO_YAWNING,
[CHAR_SOUND_SNORING1] = SOUND_MARIO_SNORING1,
[CHAR_SOUND_SNORING2] = SOUND_MARIO_SNORING2,
[CHAR_SOUND_SNORING3] = SOUND_MARIO_SNORING3,
[CHAR_SOUND_COUGHING1] = SOUND_MARIO_COUGHING1,
[CHAR_SOUND_COUGHING2] = SOUND_MARIO_COUGHING2,
[CHAR_SOUND_COUGHING3] = SOUND_MARIO_COUGHING3,
[CHAR_SOUND_DYING] = SOUND_MARIO_DYING,
[CHAR_SOUND_DROWNING] = SOUND_MARIO_DROWNING,
[CHAR_SOUND_MAMA_MIA] = SOUND_MARIO_MAMA_MIA,
[CHAR_SOUND_GAME_OVER] = SOUND_MARIO_GAME_OVER,
[CHAR_SOUND_HELLO] = SOUND_MARIO_HELLO,
[CHAR_SOUND_PRESS_START_TO_PLAY] = SOUND_MARIO_PRESS_START_TO_PLAY
}
local VOICETABLE_CJ_LUIGI = {
[CHAR_SOUND_OKEY_DOKEY] = '0B_cj_luigi_okey_dokey.aiff',
[CHAR_SOUND_LETS_A_GO] = '1A_cj_luigi_lets_a_go.aiff',
[CHAR_SOUND_PUNCH_YAH] = '08_cj_luigi_punch_yah.aiff',
[CHAR_SOUND_PUNCH_WAH] = '01_cj_luigi_jump_wah.aiff',
[CHAR_SOUND_WAH2] = '07_cj_luigi_wah2.aiff',
[CHAR_SOUND_PUNCH_HOO] = '09_cj_luigi_punch_hoo.aiff',
[CHAR_SOUND_YAH_WAH_HOO] = { '00_cj_luigi_jump_hoo.aiff', '01_cj_luigi_jump_wah.aiff', '02_cj_luigi_yah.aiff' },
[CHAR_SOUND_HOOHOO] = '01_cj_luigi_hoohoo.aiff',
[CHAR_SOUND_YAHOO_WAHA_YIPPEE] = { '04_cj_luigi_yahoo.aiff', '18_cj_luigi_waha.aiff', '19_cj_luigi_yippee.aiff' },
[CHAR_SOUND_UH] = '05_cj_luigi_uh.aiff',
[CHAR_SOUND_UH2] = '05_cj_luigi_uh2.aiff',
[CHAR_SOUND_UH2_2] = '05_cj_luigi_uh2.aiff',
[CHAR_SOUND_HAHA] = '03_cj_luigi_haha.aiff',
[CHAR_SOUND_HAHA_2] = '03_cj_luigi_haha.aiff',
[CHAR_SOUND_YAHOO] = '04_cj_luigi_yahoo.aiff',
[CHAR_SOUND_DOH] = '10_cj_luigi_doh.aiff',
[CHAR_SOUND_WHOA] = '08_cj_luigi_whoa.aiff',
[CHAR_SOUND_EEUH] = '09_cj_luigi_eeuh.aiff',
[CHAR_SOUND_WAAAOOOW] = '00_cj_luigi_waaaooow.aiff',
[CHAR_SOUND_TWIRL_BOUNCE] = '14_cj_luigi_twirl_bounce.aiff',
[CHAR_SOUND_GROUND_POUND_WAH] = '07_cj_luigi_wah2.aiff',
[CHAR_SOUND_HRMM] = '06_cj_luigi_hrmm.aiff',
[CHAR_SOUND_HERE_WE_GO] = '0C_cj_luigi_here_we_go.aiff',
[CHAR_SOUND_SO_LONGA_BOWSER] = '16_cj_luigi_so_longa_bowser.aiff',
[CHAR_SOUND_OOOF] = '0B_cj_luigi_ooof.aiff',
[CHAR_SOUND_OOOF2] = '0B_cj_luigi_ooof.aiff',
[CHAR_SOUND_ATTACKED] = '0A_cj_luigi_attacked.aiff',
[CHAR_SOUND_PANTING] = '02_cj_luigi_panting.aiff',
[CHAR_SOUND_PANTING_COLD] = '02_cj_luigi_panting.aiff',
[CHAR_SOUND_ON_FIRE] = '04_cj_luigi_on_fire.aiff',
[CHAR_SOUND_IMA_TIRED] = '17_cj_luigi_ima_tired.aiff',
[CHAR_SOUND_YAWNING] = '0D_cj_luigi_yawning.aiff',
[CHAR_SOUND_SNORING1] = '0E_cj_luigi_snoring1.aiff',
[CHAR_SOUND_SNORING2] = '0F_cj_luigi_snoring2.aiff',
[CHAR_SOUND_SNORING3] = '15_cj_luigi_snoring3.aiff',
[CHAR_SOUND_COUGHING1] = '06_cj_luigi_coughing.aiff',
[CHAR_SOUND_COUGHING2] = '06_cj_luigi_coughing.aiff',
[CHAR_SOUND_COUGHING3] = '06_cj_luigi_coughing.aiff',
[CHAR_SOUND_DYING] = '03_cj_luigi_dying.aiff',
[CHAR_SOUND_DROWNING] = '0C_cj_luigi_drowning.aiff',
[CHAR_SOUND_MAMA_MIA] = '0A_cj_luigi_mama_mia.aiff'
}
-- Loading Characters --
@ -161,14 +205,24 @@ local function on_character_select_load()
charSelect.character_add_palette_preset(E_MODEL_FLUFFA_WARIO, PALETTE_FL_WARIO)
charSelect.character_add_palette_preset(E_MODEL_KEEB_WALUIGI, PALETTE_KB_WALUIGI)
charSelect.character_add_palette_preset(E_MODEL_FLUFFA_WALUIGI, PALETTE_FL_WALUIGI)
charSelect.character_add_voice(E_MODEL_CJ_LUIGI, VOICETABLE_CJ_LUIGI)
charSelect.config_character_sounds()
end
-- Djoslin Toad Sound
--- @param m MarioState
--- @param sound CharacterSound
--- Pitched up Mario voice
local MODEL_FREQ_TABLE = {
[E_MODEL_DJOSLIN_TOAD] = 1.25,
[E_MODEL_VL_TONE_LUIGI] = 1.1
}
local function character_sound(m, sound)
if obj_get_model_id_extended(m.marioObj) == E_MODEL_DJOSLIN_TOAD then
play_sound_with_freq_scale(DJ_TOAD_SOUNDS[sound + 1], m.marioObj.header.gfx.cameraToObject, 1.25)
local extendedModelId = obj_get_model_id_extended(m.marioObj)
local freqScale = MODEL_FREQ_TABLE[extendedModelId]
if freqScale then
play_sound_with_freq_scale(MARIO_SOUNDS[sound], m.marioObj.header.gfx.cameraToObject, freqScale)
return NO_SOUND
end
end

View file

@ -20,6 +20,7 @@
// Extra, custom, flags
#define GRAPH_EXTRA_FORCE_3D (1 << 0)
#define GRAPH_EXTRA_ROTATE_HELD (1 << 1)
// Whether the node type has a function pointer of type GraphNodeFunc
#define GRAPH_NODE_TYPE_FUNCTIONAL 0x100

View file

@ -18,6 +18,7 @@
#include "goddard/renderer.h"
#include "geo_layout.h"
#include "graph_node.h"
#include "level_commands.h"
#include "level_script.h"
#include "level_misc_macros.h"
#include "macro_presets.h"
@ -501,8 +502,7 @@ static void level_cmd_23(void) {
}
static void level_cmd_init_mario(void) {
u32 behaviorArg = CMD_GET(u32, 4);
behaviorArg = behaviorArg;
UNUSED u32 behaviorArg = CMD_GET(u32, 4);
void* behaviorScript = CMD_GET(void*, 8);
u16 slot = CMD_GET(u8, 3);
struct GraphNode* unk18 = dynos_model_get_geo(slot);
@ -918,124 +918,94 @@ static void level_cmd_cleardemoptr(void)
sCurrentCmd = CMD_NEXT;
}
//
// coop
static void level_cmd_place_object_ext(void) {
u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo;
//
u16 modIndex = gLevelScriptModIndex;
const char* behStr = dynos_level_get_token(CMD_GET(u32, 20));
static bool find_lua_param(uintptr_t *param, u32 offset, u32 luaParams, u32 luaParamFlag) {
*param = CMD_GET(uintptr_t, offset);
if (luaParams & luaParamFlag) {
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
return false;
}
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr);
if (!gSmLuaConvertSuccess) {
const char *paramStr = dynos_level_get_token(*param);
gSmLuaConvertSuccess = true;
behId = smlua_get_any_integer_mod_variable(behStr);
*param = smlua_get_integer_mod_variable(gLevelScriptModIndex, paramStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
*param = smlua_get_any_integer_mod_variable(paramStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to execute level command, could not find parameter '%s'", paramStr);
return false;
}
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr);
sCurrentCmd = CMD_NEXT;
return;
}
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
u16 model = CMD_GET(u8, 3);
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
spawnInfo->startPos[1] = CMD_GET(s16, 6);
spawnInfo->startPos[2] = CMD_GET(s16, 8);
spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180;
spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180;
spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180;
spawnInfo->areaIndex = sCurrAreaIndex;
spawnInfo->activeAreaIndex = sCurrAreaIndex;
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
spawnInfo->unk18 = dynos_model_get_geo(model);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
? spawnInfo->next->syncID + 10
: 10;
gAreas[sCurrAreaIndex].objectSpawnInfos = spawnInfo;
area_check_red_coin_or_secret(spawnInfo->behaviorScript, false);
}
sCurrentCmd = CMD_NEXT;
return true;
}
static void level_cmd_place_object_ext2(void) {
#define get_lua_param(name, type, flag) \
uintptr_t name##Param; \
if (!find_lua_param(&name##Param, flag##_OFFSET(cmdType), luaParams, flag)) { \
sCurrentCmd = CMD_NEXT; \
return; \
} \
type name = (type) name##Param;
static void level_cmd_place_object_ext_lua_params(void) {
u8 val7 = 1 << (gCurrActNum - 1);
struct SpawnInfo *spawnInfo;
u16 modIndex = gLevelScriptModIndex;
const char* modelStr = dynos_level_get_token(CMD_GET(u32, 20));
const char* behStr = dynos_level_get_token(CMD_GET(u32, 24));
u8 cmdType = sCurrentCmd->type;
u16 luaParams = (
cmdType == 0x3F ? OBJECT_EXT_LUA_BEHAVIOR : (
cmdType == 0x40 ? OBJECT_EXT_LUA_BEHAVIOR | OBJECT_EXT_LUA_MODEL : (
CMD_GET(u16, 2)
)));
if (gLevelScriptModIndex == -1) {
LOG_ERROR("Could not find level script mod index");
sCurrentCmd = CMD_NEXT;
return;
}
get_lua_param(acts, u8, OBJECT_EXT_LUA_ACTS);
gSmLuaConvertSuccess = true;
enum ModelExtendedId modelId = smlua_get_integer_mod_variable(modIndex, modelStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
modelId = smlua_get_any_integer_mod_variable(modelStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find model '%s'", modelStr);
sCurrentCmd = CMD_NEXT;
return;
}
gSmLuaConvertSuccess = true;
enum BehaviorId behId = smlua_get_integer_mod_variable(modIndex, behStr);
if (!gSmLuaConvertSuccess) {
gSmLuaConvertSuccess = true;
behId = smlua_get_any_integer_mod_variable(behStr);
}
if (!gSmLuaConvertSuccess) {
LOG_LUA("Failed to place custom object, could not find behavior '%s'", behStr);
sCurrentCmd = CMD_NEXT;
return;
}
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (CMD_GET(u8, 2) & val7) || CMD_GET(u8, 2) == 0x1F)) {
if (sCurrAreaIndex != -1 && (gLevelValues.disableActs || (acts & val7) || acts == 0x1F)) {
spawnInfo = dynamic_pool_alloc(gLevelPool, sizeof(struct SpawnInfo));
spawnInfo->startPos[0] = CMD_GET(s16, 4);
spawnInfo->startPos[1] = CMD_GET(s16, 6);
spawnInfo->startPos[2] = CMD_GET(s16, 8);
get_lua_param(modelId, u32, OBJECT_EXT_LUA_MODEL);
get_lua_param(posX, s16, OBJECT_EXT_LUA_POS_X);
get_lua_param(posY, s16, OBJECT_EXT_LUA_POS_Y);
get_lua_param(posZ, s16, OBJECT_EXT_LUA_POS_Z);
get_lua_param(angleX, s16, OBJECT_EXT_LUA_ANGLE_X);
get_lua_param(angleY, s16, OBJECT_EXT_LUA_ANGLE_Y);
get_lua_param(angleZ, s16, OBJECT_EXT_LUA_ANGLE_Z);
get_lua_param(behParam, u32, OBJECT_EXT_LUA_BEH_PARAMS);
get_lua_param(behavior, uintptr_t, OBJECT_EXT_LUA_BEHAVIOR);
spawnInfo->startAngle[0] = CMD_GET(s16, 10) * 0x8000 / 180;
spawnInfo->startAngle[1] = CMD_GET(s16, 12) * 0x8000 / 180;
spawnInfo->startAngle[2] = CMD_GET(s16, 14) * 0x8000 / 180;
spawnInfo->startPos[0] = posX;
spawnInfo->startPos[1] = posY;
spawnInfo->startPos[2] = posZ;
spawnInfo->startAngle[0] = (angleX * 0x8000) / 180;
spawnInfo->startAngle[1] = (angleY * 0x8000) / 180;
spawnInfo->startAngle[2] = (angleZ * 0x8000) / 180;
spawnInfo->areaIndex = sCurrAreaIndex;
spawnInfo->activeAreaIndex = sCurrAreaIndex;
spawnInfo->behaviorArg = CMD_GET(u32, 16);
spawnInfo->behaviorArg = behParam;
if (luaParams & OBJECT_EXT_LUA_MODEL) {
u16 slot = smlua_model_util_load((enum ModelExtendedId) modelId);
spawnInfo->unk18 = dynos_model_get_geo(slot);
} else {
spawnInfo->unk18 = dynos_model_get_geo(modelId);
}
if (luaParams & OBJECT_EXT_LUA_BEHAVIOR) {
spawnInfo->behaviorScript = (BehaviorScript *) get_behavior_from_id((enum BehaviorId) behavior);
} else {
spawnInfo->behaviorScript = (BehaviorScript *) behavior;
}
spawnInfo->behaviorScript = (BehaviorScript*)get_behavior_from_id(behId);
u16 slot = smlua_model_util_load(modelId);
spawnInfo->unk18 = dynos_model_get_geo(slot);
spawnInfo->next = gAreas[sCurrAreaIndex].objectSpawnInfos;
spawnInfo->syncID = spawnInfo->next
@ -1064,6 +1034,21 @@ static void level_cmd_jump_area_ext(void) {
}
}
static void level_cmd_show_dialog_ext(void) {
if (sCurrAreaIndex != -1 && !gDjuiInMainMenu) {
u8 luaParams = CMD_GET(u8, 2);
get_lua_param(index, u8, SHOW_DIALOG_EXT_LUA_INDEX);
get_lua_param(dialogId, s32, SHOW_DIALOG_EXT_LUA_DIALOG);
if (index < 2) {
gAreas[sCurrAreaIndex].dialog[index] = dialogId;
}
}
sCurrentCmd = CMD_NEXT;
}
static void (*LevelScriptJumpTable[])(void) = {
/*00*/ level_cmd_load_and_execute,
/*01*/ level_cmd_exit_and_execute,
@ -1130,10 +1115,12 @@ static void (*LevelScriptJumpTable[])(void) = {
/*3E*/ level_cmd_cleardemoptr,
// coop
/*3F*/ level_cmd_place_object_ext,
/*40*/ level_cmd_place_object_ext2,
/*3F*/ level_cmd_place_object_ext_lua_params,
/*40*/ level_cmd_place_object_ext_lua_params,
/*41*/ level_cmd_load_model_from_geo_ext,
/*42*/ level_cmd_jump_area_ext,
/*43*/ level_cmd_place_object_ext_lua_params,
/*44*/ level_cmd_show_dialog_ext
};
struct LevelCommand *level_script_execute(struct LevelCommand *cmd) {

View file

@ -233,6 +233,30 @@ OPTIMIZE_O3 s32 anim_spline_poll(struct MarioState* m, OUT Vec3f result) {
return hasEnded;
}
///////////
// Vec2f //
///////////
Vec2f gVec2fZero = { 0.0f, 0.0f };
Vec2f gVec2fOne = { 1.0f, 1.0f };
///////////
// Vec2i //
///////////
Vec2i gVec2iZero = { 0, 0 };
Vec2i gVec2iOne = { 1, 1 };
///////////
// Vec2s //
///////////
Vec2s gVec2sZero = { 0, 0 };
Vec2s gVec2sOne = { 1, 1 };
///////////
// Vec3f //
///////////

View file

@ -87,6 +87,12 @@ extern f32 gCosineTable[];
#endif
extern Vec2f gVec2fZero;
extern Vec2i gVec2iZero;
extern Vec2s gVec2sZero;
extern Vec2f gVec2fOne;
extern Vec2i gVec2iOne;
extern Vec2s gVec2sOne;
extern Vec3f gVec3fZero;
extern Vec3i gVec3iZero;
extern Vec3s gVec3sZero;
@ -143,6 +149,24 @@ Advances the spline-based animation associated with `m` and stores the current i
|descriptionEnd| */
OPTIMIZE_O3 s32 anim_spline_poll(struct MarioState* m, OUT Vec3f result);
///////////
// Vec2f //
///////////
#include "math_util_vec2f.inl"
///////////
// Vec2i //
///////////
#include "math_util_vec2i.inl"
///////////
// Vec2s //
///////////
#include "math_util_vec2s.inl"
///////////
// Vec3f //
///////////

View file

@ -0,0 +1,157 @@
#pragma once
/* |description|
Sets the components of the 2D {{desc}} vector `v` to 0
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_zero(OUT Vec2{{suffix}} v) {
memset(v, 0, sizeof(Vec2{{suffix}}));
return v;
}
/* |description|
Copies the contents of a 2D {{desc}} vector (`src`) into another 2D {{desc}} vector (`dest`)
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_copy(OUT Vec2{{suffix}} dest, Vec2{{suffix}} src) {
dest[0] = src[0];
dest[1] = src[1];
return dest;
}
/* |description|
Sets the values of the 2D {{desc}} vector `dest` to the given x and y values
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_set(OUT Vec2{{suffix}} dest, {{type}} x, {{type}} y) {
dest[0] = x;
dest[1] = y;
return dest;
}
/* |description|
Adds the components of the 2D {{desc}} vector `a` to `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_add(OUT Vec2{{suffix}} dest, Vec2{{suffix}} a) {
dest[0] += a[0];
dest[1] += a[1];
return dest;
}
/* |description|
Adds the components of two 2D {{desc}} vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_sum(OUT Vec2{{suffix}} dest, Vec2{{suffix}} a, Vec2{{suffix}} b) {
dest[0] = a[0] + b[0];
dest[1] = a[1] + b[1];
return dest;
}
/* |description|
Subtracts the components of the 2D {{desc}} vector `a` from `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_sub(OUT Vec2{{suffix}} dest, Vec2{{suffix}} a) {
dest[0] -= a[0];
dest[1] -= a[1];
return dest;
}
/* |description|
Subtracts the components of the 2D {{desc}} vector `b` from the components of `a` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_dif(OUT Vec2{{suffix}} dest, Vec2{{suffix}} a, Vec2{{suffix}} b) {
dest[0] = a[0] - b[0];
dest[1] = a[1] - b[1];
return dest;
}
/* |description|
Multiplies each component of the 2D {{desc}} vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_mul(OUT Vec2{{suffix}} dest, f32 a) {
dest[0] *= a;
dest[1] *= a;
return dest;
}
/* |description|
Multiplies the components of the 2D {{desc}} vector `dest` with the components of `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_mult(OUT Vec2{{suffix}} dest, Vec2{{suffix}} a) {
dest[0] *= a[0];
dest[1] *= a[1];
return dest;
}
/* |description|
Multiplies the components of two 2D {{desc}} vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_prod(OUT Vec2{{suffix}} dest, Vec2{{suffix}} a, Vec2{{suffix}} b) {
dest[0] = a[0] * b[0];
dest[1] = a[1] * b[1];
return dest;
}
/* |description|
Divides each component of the 2D {{desc}} vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_div(OUT Vec2{{suffix}} dest, f32 a) {
if (a == 0) { return dest; }
dest[0] /= a;
dest[1] /= a;
return dest;
}
/* |description|
Calculates the length (magnitude) of the 2D {{desc}} vector `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2{{suffix}}_length(Vec2{{suffix}} a) {
return sqrtf(a[0] * a[0] + a[1] * a[1]);
}
/* |description|
Normalizes the 2D {{desc}} vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_normalize(OUT Vec2{{suffix}} v) {
f32 mag = vec2{{suffix}}_length(v);
vec2{{suffix}}_div(v, mag);
return v;
}
/* |description|
Sets the length (magnitude) of 2D {{desc}} vector `v`, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_set_magnitude(OUT Vec2{{suffix}} v, f32 mag) {
vec2{{suffix}}_normalize(v);
vec2{{suffix}}_mul(v, mag);
return v;
}
/* |description|
Computes the dot product of the two 2D {{desc}} vectors `a` and `b`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2{{suffix}}_dot(Vec2{{suffix}} a, Vec2{{suffix}} b) {
return (f32) (a[0] * b[0] + a[1] * b[1]);
}
/* |description|
Takes two 2D {{desc}} vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2{{suffix}}p vec2{{suffix}}_combine(OUT Vec2{{suffix}} dest, Vec2{{suffix}} vecA, Vec2{{suffix}} vecB, f32 sclA, f32 sclB) {
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
return dest;
}
/* |description|
Calculates the distance between two 2D {{desc}} vectors `v1` and `v2`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2{{suffix}}_dist(Vec2{{suffix}} v1, Vec2{{suffix}} v2) {
Vec2{{suffix}} diff;
vec2{{suffix}}_dif(diff, v1, v2);
return vec2{{suffix}}_length(diff);
}
/* |description|
Returns `true` if all components of the 2D {{desc}} vector `v` are zero
|descriptionEnd| */
INLINE OPTIMIZE_O3 bool vec2{{suffix}}_is_zero(Vec2{{suffix}} v) {
return memcmp(v, gVec2{{suffix}}Zero, sizeof(Vec2{{suffix}})) == 0;
}

View file

@ -0,0 +1,178 @@
/* THIS FILE IS AUTO-GENERATED */
/* DO NOT EDIT IT MANUALLY */
#pragma once
/* |description|
Sets the components of the 2D floating-point vector `v` to 0
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_zero(OUT Vec2f v) {
memset(v, 0, sizeof(Vec2f));
return v;
}
/* |description|
Copies the contents of a 2D floating-point vector (`src`) into another 2D floating-point vector (`dest`)
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_copy(OUT Vec2f dest, Vec2f src) {
dest[0] = src[0];
dest[1] = src[1];
return dest;
}
/* |description|
Sets the values of the 2D floating-point vector `dest` to the given x and y values
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_set(OUT Vec2f dest, f32 x, f32 y) {
dest[0] = x;
dest[1] = y;
return dest;
}
/* |description|
Adds the components of the 2D floating-point vector `a` to `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_add(OUT Vec2f dest, Vec2f a) {
dest[0] += a[0];
dest[1] += a[1];
return dest;
}
/* |description|
Adds the components of two 2D floating-point vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_sum(OUT Vec2f dest, Vec2f a, Vec2f b) {
dest[0] = a[0] + b[0];
dest[1] = a[1] + b[1];
return dest;
}
/* |description|
Subtracts the components of the 2D floating-point vector `a` from `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_sub(OUT Vec2f dest, Vec2f a) {
dest[0] -= a[0];
dest[1] -= a[1];
return dest;
}
/* |description|
Subtracts the components of the 2D floating-point vector `b` from the components of `a` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_dif(OUT Vec2f dest, Vec2f a, Vec2f b) {
dest[0] = a[0] - b[0];
dest[1] = a[1] - b[1];
return dest;
}
/* |description|
Multiplies each component of the 2D floating-point vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_mul(OUT Vec2f dest, f32 a) {
dest[0] *= a;
dest[1] *= a;
return dest;
}
/* |description|
Multiplies the components of the 2D floating-point vector `dest` with the components of `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_mult(OUT Vec2f dest, Vec2f a) {
dest[0] *= a[0];
dest[1] *= a[1];
return dest;
}
/* |description|
Multiplies the components of two 2D floating-point vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_prod(OUT Vec2f dest, Vec2f a, Vec2f b) {
dest[0] = a[0] * b[0];
dest[1] = a[1] * b[1];
return dest;
}
/* |description|
Divides each component of the 2D floating-point vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_div(OUT Vec2f dest, f32 a) {
if (a == 0) { return dest; }
dest[0] /= a;
dest[1] /= a;
return dest;
}
/* |description|
Calculates the length (magnitude) of the 2D floating-point vector `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2f_length(Vec2f a) {
return sqrtf(a[0] * a[0] + a[1] * a[1]);
}
/* |description|
Normalizes the 2D floating-point vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_normalize(OUT Vec2f v) {
f32 mag = vec2f_length(v);
vec2f_div(v, mag);
return v;
}
/* |description|
Sets the length (magnitude) of 2D floating-point vector `v`, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_set_magnitude(OUT Vec2f v, f32 mag) {
vec2f_normalize(v);
vec2f_mul(v, mag);
return v;
}
/* |description|
Computes the dot product of the two 2D floating-point vectors `a` and `b`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2f_dot(Vec2f a, Vec2f b) {
return (f32) (a[0] * b[0] + a[1] * b[1]);
}
/* |description|
Takes two 2D floating-point vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2f_combine(OUT Vec2f dest, Vec2f vecA, Vec2f vecB, f32 sclA, f32 sclB) {
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
return dest;
}
/* |description|
Calculates the distance between two 2D floating-point vectors `v1` and `v2`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2f_dist(Vec2f v1, Vec2f v2) {
Vec2f diff;
vec2f_dif(diff, v1, v2);
return vec2f_length(diff);
}
/* |description|
Returns `true` if all components of the 2D floating-point vector `v` are zero
|descriptionEnd| */
INLINE OPTIMIZE_O3 bool vec2f_is_zero(Vec2f v) {
return memcmp(v, gVec2fZero, sizeof(Vec2f)) == 0;
}
/* |description|
Converts a 2D floating-point vector `a` into a 2D integer vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2f_to_vec2i(OUT Vec2i dest, Vec2f a) {
dest[0] = a[0] + ((a[0] > 0) ? 0.5f : -0.5f);
dest[1] = a[1] + ((a[1] > 0) ? 0.5f : -0.5f);
return dest;
}
/* |description|
Converts a 2D floating-point vector `a` into a 2D short integer vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2f_to_vec2s(OUT Vec2s dest, Vec2f a) {
dest[0] = a[0] + ((a[0] > 0) ? 0.5f : -0.5f);
dest[1] = a[1] + ((a[1] > 0) ? 0.5f : -0.5f);
return dest;
}

View file

@ -0,0 +1,178 @@
/* THIS FILE IS AUTO-GENERATED */
/* DO NOT EDIT IT MANUALLY */
#pragma once
/* |description|
Sets the components of the 2D integer vector `v` to 0
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_zero(OUT Vec2i v) {
memset(v, 0, sizeof(Vec2i));
return v;
}
/* |description|
Copies the contents of a 2D integer vector (`src`) into another 2D integer vector (`dest`)
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_copy(OUT Vec2i dest, Vec2i src) {
dest[0] = src[0];
dest[1] = src[1];
return dest;
}
/* |description|
Sets the values of the 2D integer vector `dest` to the given x and y values
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_set(OUT Vec2i dest, s32 x, s32 y) {
dest[0] = x;
dest[1] = y;
return dest;
}
/* |description|
Adds the components of the 2D integer vector `a` to `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_add(OUT Vec2i dest, Vec2i a) {
dest[0] += a[0];
dest[1] += a[1];
return dest;
}
/* |description|
Adds the components of two 2D integer vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_sum(OUT Vec2i dest, Vec2i a, Vec2i b) {
dest[0] = a[0] + b[0];
dest[1] = a[1] + b[1];
return dest;
}
/* |description|
Subtracts the components of the 2D integer vector `a` from `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_sub(OUT Vec2i dest, Vec2i a) {
dest[0] -= a[0];
dest[1] -= a[1];
return dest;
}
/* |description|
Subtracts the components of the 2D integer vector `b` from the components of `a` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_dif(OUT Vec2i dest, Vec2i a, Vec2i b) {
dest[0] = a[0] - b[0];
dest[1] = a[1] - b[1];
return dest;
}
/* |description|
Multiplies each component of the 2D integer vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_mul(OUT Vec2i dest, f32 a) {
dest[0] *= a;
dest[1] *= a;
return dest;
}
/* |description|
Multiplies the components of the 2D integer vector `dest` with the components of `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_mult(OUT Vec2i dest, Vec2i a) {
dest[0] *= a[0];
dest[1] *= a[1];
return dest;
}
/* |description|
Multiplies the components of two 2D integer vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_prod(OUT Vec2i dest, Vec2i a, Vec2i b) {
dest[0] = a[0] * b[0];
dest[1] = a[1] * b[1];
return dest;
}
/* |description|
Divides each component of the 2D integer vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_div(OUT Vec2i dest, f32 a) {
if (a == 0) { return dest; }
dest[0] /= a;
dest[1] /= a;
return dest;
}
/* |description|
Calculates the length (magnitude) of the 2D integer vector `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2i_length(Vec2i a) {
return sqrtf(a[0] * a[0] + a[1] * a[1]);
}
/* |description|
Normalizes the 2D integer vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_normalize(OUT Vec2i v) {
f32 mag = vec2i_length(v);
vec2i_div(v, mag);
return v;
}
/* |description|
Sets the length (magnitude) of 2D integer vector `v`, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_set_magnitude(OUT Vec2i v, f32 mag) {
vec2i_normalize(v);
vec2i_mul(v, mag);
return v;
}
/* |description|
Computes the dot product of the two 2D integer vectors `a` and `b`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2i_dot(Vec2i a, Vec2i b) {
return (f32) (a[0] * b[0] + a[1] * b[1]);
}
/* |description|
Takes two 2D integer vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2i_combine(OUT Vec2i dest, Vec2i vecA, Vec2i vecB, f32 sclA, f32 sclB) {
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
return dest;
}
/* |description|
Calculates the distance between two 2D integer vectors `v1` and `v2`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2i_dist(Vec2i v1, Vec2i v2) {
Vec2i diff;
vec2i_dif(diff, v1, v2);
return vec2i_length(diff);
}
/* |description|
Returns `true` if all components of the 2D integer vector `v` are zero
|descriptionEnd| */
INLINE OPTIMIZE_O3 bool vec2i_is_zero(Vec2i v) {
return memcmp(v, gVec2iZero, sizeof(Vec2i)) == 0;
}
/* |description|
Converts a 2D integer vector `a` into a 2D floating-point vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2i_to_vec2f(OUT Vec2f dest, Vec2i a) {
dest[0] = a[0];
dest[1] = a[1];
return dest;
}
/* |description|
Converts a 2D integer vector `a` into a 2D short integer vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2i_to_vec2s(OUT Vec2s dest, Vec2i a) {
dest[0] = a[0];
dest[1] = a[1];
return dest;
}

View file

@ -0,0 +1,178 @@
/* THIS FILE IS AUTO-GENERATED */
/* DO NOT EDIT IT MANUALLY */
#pragma once
/* |description|
Sets the components of the 2D short integer vector `v` to 0
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_zero(OUT Vec2s v) {
memset(v, 0, sizeof(Vec2s));
return v;
}
/* |description|
Copies the contents of a 2D short integer vector (`src`) into another 2D short integer vector (`dest`)
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_copy(OUT Vec2s dest, Vec2s src) {
dest[0] = src[0];
dest[1] = src[1];
return dest;
}
/* |description|
Sets the values of the 2D short integer vector `dest` to the given x and y values
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_set(OUT Vec2s dest, s16 x, s16 y) {
dest[0] = x;
dest[1] = y;
return dest;
}
/* |description|
Adds the components of the 2D short integer vector `a` to `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_add(OUT Vec2s dest, Vec2s a) {
dest[0] += a[0];
dest[1] += a[1];
return dest;
}
/* |description|
Adds the components of two 2D short integer vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_sum(OUT Vec2s dest, Vec2s a, Vec2s b) {
dest[0] = a[0] + b[0];
dest[1] = a[1] + b[1];
return dest;
}
/* |description|
Subtracts the components of the 2D short integer vector `a` from `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_sub(OUT Vec2s dest, Vec2s a) {
dest[0] -= a[0];
dest[1] -= a[1];
return dest;
}
/* |description|
Subtracts the components of the 2D short integer vector `b` from the components of `a` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_dif(OUT Vec2s dest, Vec2s a, Vec2s b) {
dest[0] = a[0] - b[0];
dest[1] = a[1] - b[1];
return dest;
}
/* |description|
Multiplies each component of the 2D short integer vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_mul(OUT Vec2s dest, f32 a) {
dest[0] *= a;
dest[1] *= a;
return dest;
}
/* |description|
Multiplies the components of the 2D short integer vector `dest` with the components of `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_mult(OUT Vec2s dest, Vec2s a) {
dest[0] *= a[0];
dest[1] *= a[1];
return dest;
}
/* |description|
Multiplies the components of two 2D short integer vectors `a` and `b` and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_prod(OUT Vec2s dest, Vec2s a, Vec2s b) {
dest[0] = a[0] * b[0];
dest[1] = a[1] * b[1];
return dest;
}
/* |description|
Divides each component of the 2D short integer vector `dest` by the scalar value `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_div(OUT Vec2s dest, f32 a) {
if (a == 0) { return dest; }
dest[0] /= a;
dest[1] /= a;
return dest;
}
/* |description|
Calculates the length (magnitude) of the 2D short integer vector `a`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2s_length(Vec2s a) {
return sqrtf(a[0] * a[0] + a[1] * a[1]);
}
/* |description|
Normalizes the 2D short integer vector `v` so that its length (magnitude) becomes 1, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_normalize(OUT Vec2s v) {
f32 mag = vec2s_length(v);
vec2s_div(v, mag);
return v;
}
/* |description|
Sets the length (magnitude) of 2D short integer vector `v`, while retaining its direction
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_set_magnitude(OUT Vec2s v, f32 mag) {
vec2s_normalize(v);
vec2s_mul(v, mag);
return v;
}
/* |description|
Computes the dot product of the two 2D short integer vectors `a` and `b`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2s_dot(Vec2s a, Vec2s b) {
return (f32) (a[0] * b[0] + a[1] * b[1]);
}
/* |description|
Takes two 2D short integer vectors `vecA` and `vecB`, multiplies them by `sclA` and `sclB` respectively, adds the scaled vectors together and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2sp vec2s_combine(OUT Vec2s dest, Vec2s vecA, Vec2s vecB, f32 sclA, f32 sclB) {
dest[0] = vecA[0] * sclA + vecB[0] * sclB;
dest[1] = vecA[1] * sclA + vecB[1] * sclB;
return dest;
}
/* |description|
Calculates the distance between two 2D short integer vectors `v1` and `v2`
|descriptionEnd| */
INLINE OPTIMIZE_O3 f32 vec2s_dist(Vec2s v1, Vec2s v2) {
Vec2s diff;
vec2s_dif(diff, v1, v2);
return vec2s_length(diff);
}
/* |description|
Returns `true` if all components of the 2D short integer vector `v` are zero
|descriptionEnd| */
INLINE OPTIMIZE_O3 bool vec2s_is_zero(Vec2s v) {
return memcmp(v, gVec2sZero, sizeof(Vec2s)) == 0;
}
/* |description|
Converts a 2D short integer vector `a` into a 2D floating-point vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2fp vec2s_to_vec2f(OUT Vec2f dest, Vec2s a) {
dest[0] = a[0];
dest[1] = a[1];
return dest;
}
/* |description|
Converts a 2D short integer vector `a` into a 2D integer vector and stores the result in `dest`
|descriptionEnd| */
INLINE OPTIMIZE_O3 Vec2ip vec2s_to_vec2i(OUT Vec2i dest, Vec2s a) {
dest[0] = a[0];
dest[1] = a[1];
return dest;
}

View file

@ -137,9 +137,8 @@ static s32 find_wall_collisions_from_list(struct SurfaceNode *surfaceNode,
surfaceNode = surfaceNode->next;
// Exclude a large number of walls immediately to optimize.
if (y < surf->lowerY || y > surf->upperY) {
continue;
}
if (y < surf->lowerY || y > surf->upperY) { continue; }
if (surf->flags & SURFACE_FLAG_INTANGIBLE) { continue; }
if (gLevelValues.fixCollisionBugs && gLevelValues.fixCollisionBugsRoundedCorners && !gFindWallDirectionAirborne) {
// Check AABB to exclude walls before doing expensive triangle check
@ -399,6 +398,8 @@ static struct Surface *find_ceil_from_list(struct SurfaceNode *surfaceNode, s32
surf = surfaceNode->surface;
surfaceNode = surfaceNode->next;
if (surf->flags & SURFACE_FLAG_INTANGIBLE) { continue; }
x1 = surf->vertex1[0];
z1 = surf->vertex1[2];
z2 = surf->vertex2[2];
@ -622,7 +623,8 @@ static struct Surface *find_floor_from_list(struct SurfaceNode *surfaceNode, s32
if (surf == NULL) { break; }
surfaceNode = surfaceNode->next;
interpolate = gInterpolatingSurfaces;
if (surf->flags & SURFACE_FLAG_INTANGIBLE) { continue; }
if (gCheckingSurfaceCollisionsForObject != NULL) {
if (surf->object != gCheckingSurfaceCollisionsForObject) {
continue;

View file

@ -38,6 +38,12 @@ struct FloorGeometry
f32 originOffset;
};
struct StaticObjectCollision
{
u32 index;
u16 length;
};
extern Vec3f gFindWallDirection;
extern u8 gFindWallDirectionActive;
extern u8 gFindWallDirectionAirborne;

View file

@ -28,12 +28,48 @@
SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS];
SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS];
/**
* The total number of surface nodes allocated (a node is allocated for each
* spatial partition cell that a surface intersects).
*/
s32 gSurfaceNodesAllocated;
/**
* The total number of surfaces allocated.
*/
s32 gSurfacesAllocated;
/**
* The number of nodes that have been created for static surfaces.
*/
s32 gNumStaticSurfaceNodes;
/**
* The number of static surfaces in the pool.
*/
s32 gNumStaticSurfaces;
/**
* The number of nodes that have been created for static object collision surfaces.
*/
s32 gNumSOCSurfaceNodes;
/**
* The number of static object collision surfaces in the pool.
*/
s32 gNumSOCSurfaces;
/**
* Pools of data to contain either surface nodes or surfaces.
*/
static struct GrowingArray *sSurfaceNodePool = NULL;
static struct GrowingArray *sSurfacePool = NULL;
/**
* Pool of data for static object collisions.
*/
static struct GrowingArray *sSOCPool = NULL;
/**
* Allocate the part of the surface node pool to contain a surface node.
*/
@ -51,6 +87,10 @@ static struct Surface *alloc_surface(void) {
return growing_array_alloc(sSurfacePool, sizeof(struct Surface));
}
static struct StaticObjectCollision *alloc_static_object_collision(void) {
return growing_array_alloc(sSOCPool, sizeof(struct StaticObjectCollision));
}
/**
* Iterates through the entire partition, clearing the surfaces.
*/
@ -71,6 +111,7 @@ static void clear_spatial_partition(SpatialPartitionCell *cells) {
*/
static void clear_static_surfaces(void) {
clear_spatial_partition(&gStaticSurfacePartition[0][0]);
sSOCPool = growing_array_init(sSOCPool, 0x100, malloc, smlua_free_soc);
}
/**
@ -479,6 +520,8 @@ void alloc_surface_pools(void) {
gSurfacesAllocated = 0;
gNumStaticSurfaceNodes = 0;
gNumStaticSurfaces = 0;
gNumSOCSurfaceNodes = 0;
gNumSOCSurfaces = 0;
gCCMEnteredSlide = 0;
reset_red_coins_collected();
@ -586,6 +629,8 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
gNumStaticSurfaceNodes = gSurfaceNodesAllocated;
gNumStaticSurfaces = gSurfacesAllocated;
gNumSOCSurfaceNodes = 0;
gNumSOCSurfaces = 0;
}
/**
@ -593,8 +638,8 @@ void load_area_terrain(s16 index, s16 *data, s8 *surfaceRooms, s16 *macroObjects
*/
void clear_dynamic_surfaces(void) {
if (!(gTimeStopState & TIME_STOP_ACTIVE)) {
gSurfacesAllocated = gNumStaticSurfaces;
gSurfaceNodesAllocated = gNumStaticSurfaceNodes;
gSurfacesAllocated = gNumStaticSurfaces + gNumSOCSurfaces;
gSurfaceNodesAllocated = gNumStaticSurfaceNodes + gNumSOCSurfaceNodes;
clear_spatial_partition(&gDynamicSurfacePartition[0][0]);
@ -650,7 +695,7 @@ void transform_object_vertices(s16 **data, s16 *vertexData) {
/**
* Load in the surfaces for the gCurrentObject. This includes setting the flags, exertion, and room.
*/
void load_object_surfaces(s16** data, s16* vertexData) {
void load_object_surfaces(s16** data, s16* vertexData, bool isSOC) {
if (!gCurrentObject) { return; }
s32 surfaceType;
s32 i;
@ -682,15 +727,16 @@ void load_object_surfaces(s16** data, s16* vertexData) {
struct Surface* surface = read_surface_data(vertexData, data);
if (surface != NULL) {
// Set index of first surface
if (gCurrentObject->firstSurface == 0) {
gCurrentObject->firstSurface = gSurfacesAllocated - 1;
if (!isSOC) {
// Set index of first surface
if (gCurrentObject->firstSurface == 0) {
gCurrentObject->firstSurface = gSurfacesAllocated - 1;
}
// Increase surface count
gCurrentObject->numSurfaces++;
}
// Increase surface count
gCurrentObject->numSurfaces++;
surface->object = gCurrentObject;
surface->type = surfaceType;
@ -702,7 +748,7 @@ void load_object_surfaces(s16** data, s16* vertexData) {
surface->flags |= flags;
surface->room = (s8)room;
add_surface(surface, TRUE);
add_surface(surface, !isSOC);
}
if (hasForce) {
@ -716,9 +762,12 @@ void load_object_surfaces(s16** data, s16* vertexData) {
/**
* Transform an object's vertices, reload them, and render the object.
*/
void load_object_collision_model(void) {
static void load_object_collision_model_internal(bool isSOC) {
static bool sIsLoadingCollision = false;
if (!gCurrentObject) { return; }
if (gCurrentObject->collisionData == NULL) { return; }
if (sIsLoadingCollision) { return; }
s32 numVertices = 64;
if (gCurrentObject->collisionData[0] == COL_INIT()) {
@ -736,6 +785,9 @@ void load_object_collision_model(void) {
static s32 sVertexDataCount = 0;
static s16* sVertexData = NULL;
// start loading collision
sIsLoadingCollision = true;
// allocate vertex data
if (numVertices > sVertexDataCount || sVertexData == NULL) {
if (sVertexData) { free(sVertexData); }
@ -746,39 +798,99 @@ void load_object_collision_model(void) {
}
s16* collisionData = gCurrentObject->collisionData;
f32 tangibleDist = gCurrentObject->oCollisionDistance;
u8 anyPlayerInTangibleRange = FALSE;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
f32 dist = dist_between_objects(gCurrentObject, gMarioStates[i].marioObj);
if (dist < tangibleDist) { anyPlayerInTangibleRange = TRUE; }
if (!isSOC) {
f32 tangibleDist = gCurrentObject->oCollisionDistance;
for (s32 i = 0; i < MAX_PLAYERS; i++) {
f32 dist = dist_between_objects(gCurrentObject, gMarioStates[i].marioObj);
if (dist < tangibleDist) { anyPlayerInTangibleRange = TRUE; }
}
// If the object collision is supposed to be loaded more than the
// drawing distance of 4000, extend the drawing range.
if (gCurrentObject->oCollisionDistance > 4000.0f) {
gCurrentObject->oDrawingDistance = gCurrentObject->oCollisionDistance;
}
}
// If the object collision is supposed to be loaded more than the
// drawing distance of 4000, extend the drawing range.
if (gCurrentObject->oCollisionDistance > 4000.0f) {
gCurrentObject->oDrawingDistance = gCurrentObject->oCollisionDistance;
}
// Update if no Time Stop, in range, and in the current room.
if (!(gTimeStopState & TIME_STOP_ACTIVE)
// Update if no Time Stop, in range, and in the current room. (or if static)
if (isSOC ||
(!(gTimeStopState & TIME_STOP_ACTIVE)
&& (anyPlayerInTangibleRange)
&& !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM)) {
&& !(gCurrentObject->activeFlags & ACTIVE_FLAG_IN_DIFFERENT_ROOM))
) {
collisionData++;
transform_object_vertices(&collisionData, sVertexData);
// TERRAIN_LOAD_CONTINUE acts as an "end" to the terrain data.
while (*collisionData != TERRAIN_LOAD_CONTINUE) {
load_object_surfaces(&collisionData, sVertexData);
load_object_surfaces(&collisionData, sVertexData, isSOC);
}
}
f32 marioDist = dist_between_objects(gCurrentObject, gMarioStates[0].marioObj);
if (marioDist < gCurrentObject->oDrawingDistance * draw_distance_scalar()) {
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
} else {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
if (!isSOC) {
f32 marioDist = dist_between_objects(gCurrentObject, gMarioStates[0].marioObj);
if (marioDist < gCurrentObject->oDrawingDistance * draw_distance_scalar()) {
gCurrentObject->header.gfx.node.flags |= GRAPH_RENDER_ACTIVE;
} else {
gCurrentObject->header.gfx.node.flags &= ~GRAPH_RENDER_ACTIVE;
}
}
// stop loading collision
sIsLoadingCollision = false;
}
void load_object_collision_model(void) {
load_object_collision_model_internal(false);
}
struct StaticObjectCollision *load_static_object_collision() {
struct StaticObjectCollision *col;
u32 lastSurfaceIndex = gSurfacesAllocated;
u32 lastSurfaceNodeIndex = gSurfaceNodesAllocated;
u32 lastSOCSurfaceIndex = gNumStaticSurfaces + gNumSOCSurfaces;
u32 lastSOCSurfaceNodeIndex = gNumStaticSurfaceNodes + gNumSOCSurfaceNodes;
load_object_collision_model_internal(true);
// Reorder surfaces and nodes and update SOC variables
u32 addedSurfaces = gSurfacesAllocated - lastSurfaceIndex;
u32 addedSurfaceNodes = gSurfaceNodesAllocated - lastSurfaceNodeIndex;
if (addedSurfaces > 0) {
growing_array_move(sSurfacePool, lastSurfaceIndex, lastSOCSurfaceIndex, addedSurfaces);
gNumSOCSurfaces += addedSurfaces;
}
if (addedSurfaceNodes > 0) {
growing_array_move(sSurfaceNodePool, lastSurfaceNodeIndex, lastSOCSurfaceNodeIndex, addedSurfaceNodes);
gNumSOCSurfaceNodes += addedSurfaceNodes;
}
col = alloc_static_object_collision();
col->index = lastSOCSurfaceIndex;
col->length = addedSurfaces;
return col;
}
void toggle_static_object_collision(struct StaticObjectCollision *col, bool tangible) {
for (s32 i = 0; i < col->length; i++) {
struct Surface *surf = sSurfacePool->buffer[col->index + i];
if (tangible) {
surf->flags &= ~SURFACE_FLAG_INTANGIBLE;
} else {
surf->flags |= SURFACE_FLAG_INTANGIBLE;
}
}
}
struct Surface *get_static_object_surface(struct StaticObjectCollision *col, u32 index) {
if (!col) { return NULL; }
if (index >= col->length) { return NULL; }
struct Surface *surf = sSurfacePool->buffer[col->index + index];
return surf;
}
struct Surface *obj_get_surface_from_index(struct Object *o, u32 index) {

View file

@ -27,6 +27,13 @@ typedef struct SurfaceNode SpatialPartitionCell[3];
extern SpatialPartitionCell gStaticSurfacePartition[NUM_CELLS][NUM_CELLS];
extern SpatialPartitionCell gDynamicSurfacePartition[NUM_CELLS][NUM_CELLS];
extern s32 gSurfaceNodesAllocated;
extern s32 gSurfacesAllocated;
extern s32 gNumStaticSurfaceNodes;
extern s32 gNumStaticSurfaces;
extern s32 gNumSOCSurfaceNodes;
extern s32 gNumSOCSurfaces;
void alloc_surface_pools(void);
u32 get_area_terrain_size(s16 *data);
@ -38,6 +45,15 @@ Loads the object's collision data into dynamic collision.
You must run this every frame in your object's behavior loop for it to have collision
|descriptionEnd| */
void load_object_collision_model(void);
/* |description|
Loads the object's collision data into static collision.
You may run this only once to capture the object's collision at that frame.
|descriptionEnd| */
struct StaticObjectCollision *load_static_object_collision();
/* |description|Toggles a collection of static object surfaces|descriptionEnd| */
void toggle_static_object_collision(struct StaticObjectCollision *col, bool tangible);
/* |description|Gets a surface corresponding to `index` from the static object collision|descriptionEnd| */
struct Surface *get_static_object_surface(struct StaticObjectCollision *col, u32 index);
/* |description|Gets a surface corresponding to `index` from the surface pool buffer|descriptionEnd| */
struct Surface *obj_get_surface_from_index(struct Object *o, u32 index);
/* |description|Checks if a surface has force|descriptionEnd| */

View file

@ -79,9 +79,9 @@ struct Area
/*0x24*/ struct Camera *camera;
/*0x28*/ struct UnusedArea28 *unused28; // Filled by level script 0x3A, but is unused.
/*0x2C*/ struct Whirlpool *whirlpools[2];
/*0x34*/ u8 dialog[2]; // Level start dialog number (set by level script cmd 0x30)
/*0x36*/ u16 musicParam;
/*0x38*/ u16 musicParam2;
/*0x34*/ s32 dialog[2]; // Level start dialog number (set by level script cmd 0x30 and 0x44)
/*0x3C*/ u16 musicParam;
/*0x40*/ u16 musicParam2;
/*????*/ u32 localAreaTimer;
/*????*/ u8 *macroObjectsAltered;
/*????*/ u8 numRedCoins;

Some files were not shown because too many files have changed in this diff Show more