mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-12-23 08:22:51 +00:00
ModFs improvements (#907)
Some checks failed
Build coop / build-linux (push) Has been cancelled
Build coop / build-steamos (push) Has been cancelled
Build coop / build-windows-opengl (push) Has been cancelled
Build coop / build-windows-directx (push) Has been cancelled
Build coop / build-macos-arm (push) Has been cancelled
Build coop / build-macos-intel (push) Has been cancelled
Some checks failed
Build coop / build-linux (push) Has been cancelled
Build coop / build-steamos (push) Has been cancelled
Build coop / build-windows-opengl (push) Has been cancelled
Build coop / build-windows-directx (push) Has been cancelled
Build coop / build-macos-arm (push) Has been cancelled
Build coop / build-macos-intel (push) Has been cancelled
* zip + json properties; check existing file in create file * smlua_audio_utils_replace_sequence * audio_stream_load, audio_sample_load, smlua_model_util_get_id * get_texture_info + can also load PNG files * smlua_collision_util_get * add wildcard in properties files + set text mode * filepath restrictions * Some mod_storage improvements - Cache mod storage files into a map to reduce file I/O - Fix a bug in mod_storage_save - Add mod_storage_load_all that returns all keys/values as a table * shutdown; fix buffer overflow; fix warnings; lua table * reject binary files starting with MZ or ELF * function members * better doc * adding file rewind * ModFS guide; replace yaml by ini; read string buffer changes
This commit is contained in:
parent
25838f13bc
commit
32f395fb0c
54 changed files with 37469 additions and 10542 deletions
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -5,6 +5,7 @@ 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', '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()
|
||||
|
|
|
|||
|
|
@ -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,7 +256,9 @@ def process_define(filename, line, inIfBlock):
|
|||
val = val.replace('(u8)', '')
|
||||
val = val.replace('(u64)', '')
|
||||
val = re.sub(r'\.\d+f', '', val)
|
||||
val = val.strip()
|
||||
|
||||
if not (val.startswith('"') and val.endswith('"') and '"' not in val[1:-1]):
|
||||
for p in val.split(' '):
|
||||
if p.startswith('0x'):
|
||||
continue
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -323,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':
|
||||
|
|
@ -486,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:
|
||||
|
|
@ -508,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)
|
||||
|
||||
|
|
@ -533,6 +545,18 @@ def build_struct(struct):
|
|||
startStr += '#ifndef ' + override_field_version_excludes[fid] + '\n'
|
||||
endStr += '\n#endif'
|
||||
startStr += ' { '
|
||||
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 )
|
||||
|
|
@ -548,7 +572,13 @@ def build_struct(struct):
|
|||
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'
|
||||
|
|
@ -648,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:
|
||||
|
|
@ -664,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):
|
||||
|
|
@ -698,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
|
||||
|
||||
|
|
@ -709,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
|
||||
|
|
@ -742,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']
|
||||
|
||||
|
|
@ -763,7 +849,12 @@ def def_struct(struct):
|
|||
|
||||
ftype, flink = translate_type_to_lua(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)
|
||||
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
|
|
@ -4557,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
|
||||
|
|
@ -6758,6 +6764,9 @@ R_CBUTTONS = CONT_F
|
|||
--- @type integer
|
||||
D_CBUTTONS = CONT_D
|
||||
|
||||
--- @type string
|
||||
PALETTES_DIRECTORY = "palettes"
|
||||
|
||||
--- @type integer
|
||||
MAX_PRESET_PALETTES = 128
|
||||
|
||||
|
|
@ -11169,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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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,47 +307,68 @@ 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);
|
||||
|
||||
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;
|
||||
}
|
||||
} else if (type == DATA_TYPE_TEXTURE_RAW) {
|
||||
|
||||
// load raw-texture
|
||||
_TexNode = New<DataNode<TexData>>();
|
||||
_TexNode->mData = New<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;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
@ -2144,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 |
|
||||
|
|
@ -2970,6 +2972,7 @@
|
|||
<br />
|
||||
|
||||
## [player_palette.h](#player_palette.h)
|
||||
- PALETTES_DIRECTORY
|
||||
- MAX_PRESET_PALETTES
|
||||
|
||||
### [enum PlayerPart](#PlayerPart)
|
||||
|
|
@ -4722,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:](#)
|
||||
|
|
|
|||
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
|
|
@ -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 />
|
||||
|
||||
|
|
@ -1956,234 +1959,234 @@
|
|||
<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_texture_name](functions-6.md#get_texture_name)
|
||||
- [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 />
|
||||
|
||||
|
|
|
|||
|
|
@ -1,3 +1,5 @@
|
|||
## [:rewind: Lua Reference](../lua.md)
|
||||
|
||||
# How to use the Lighting Engine
|
||||
|
||||
## Section 1: Preparation
|
||||
|
|
|
|||
|
|
@ -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
272
docs/lua/guides/modfs.md
Normal 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()
|
||||
```
|
||||
|
|
@ -1,3 +1,5 @@
|
|||
## [:rewind: Lua Reference](../lua.md)
|
||||
|
||||
# Every Behavior's Object List
|
||||
|
||||
| Behavior | Object List |
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -1956,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 |
|
||||
|
|
@ -2002,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 />
|
||||
|
|
@ -2017,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 />
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include "pc/network/moderator_list.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "pc/lua/utils/smlua_level_utils.h"
|
||||
#include "pc/mods/mods_utils.h"
|
||||
#include "level_table.h"
|
||||
#ifdef DEVELOPMENT
|
||||
#include "pc/dev/chat.h"
|
||||
|
|
@ -39,10 +40,6 @@ static struct NetworkPlayer* chat_get_network_player(const char* name) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static bool str_starts_with(const char* pre, const char* str) {
|
||||
return strncmp(pre, str, strlen(pre)) == 0;
|
||||
}
|
||||
|
||||
static void chat_construct_player_message(struct NetworkPlayer* np, char* msg) {
|
||||
char built[256] = { 0 };
|
||||
snprintf(built, 256, "\\#fff982\\");
|
||||
|
|
@ -124,7 +121,7 @@ bool exec_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/kick ", command)) {
|
||||
if (str_starts_with(command, "/kick ")) {
|
||||
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
||||
djui_chat_message_create(DLANG(CHAT, NO_PERMS));
|
||||
return true;
|
||||
|
|
@ -152,7 +149,7 @@ bool exec_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/ban ", command)) {
|
||||
if (str_starts_with(command, "/ban ")) {
|
||||
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
||||
djui_chat_message_create(DLANG(CHAT, NO_PERMS));
|
||||
return true;
|
||||
|
|
@ -180,7 +177,7 @@ bool exec_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/permban ", command)) {
|
||||
if (str_starts_with(command, "/permban ")) {
|
||||
if (gNetworkType != NT_SERVER && !npl->moderator) {
|
||||
djui_chat_message_create(DLANG(CHAT, NO_PERMS));
|
||||
return true;
|
||||
|
|
@ -208,7 +205,7 @@ bool exec_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/moderator ", command)) {
|
||||
if (str_starts_with(command, "/moderator ")) {
|
||||
if (gNetworkType != NT_SERVER) {
|
||||
djui_chat_message_create(DLANG(CHAT, SERVER_ONLY));
|
||||
return true;
|
||||
|
|
@ -237,7 +234,7 @@ bool exec_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/nametags ", command)) {
|
||||
if (str_starts_with(command, "/nametags ")) {
|
||||
char *option = &command[10];
|
||||
if (strcmp("show-tag", option) == 0) {
|
||||
gNametagsSettings.showSelfTag = !gNametagsSettings.showSelfTag;
|
||||
|
|
|
|||
|
|
@ -8,15 +8,12 @@
|
|||
#include "pc/network/moderator_list.h"
|
||||
#include "pc/debuglog.h"
|
||||
#include "pc/lua/utils/smlua_level_utils.h"
|
||||
#include "pc/mods/mods_utils.h"
|
||||
#include "level_table.h"
|
||||
#include "game/save_file.h"
|
||||
|
||||
#ifdef DEVELOPMENT
|
||||
|
||||
static bool str_starts_with(const char* pre, char* str) {
|
||||
return strncmp(pre, str, strlen(pre)) == 0;
|
||||
}
|
||||
|
||||
// For case insensitivity
|
||||
static const char *upper(char *str) {
|
||||
static char buffer[50];
|
||||
|
|
@ -74,7 +71,7 @@ bool exec_dev_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/warp ", command)) {
|
||||
if (str_starts_with(command, "/warp ")) {
|
||||
static const struct { const char *name; s32 num; } sLevelNumByName[] = {
|
||||
#undef STUB_LEVEL
|
||||
#undef DEFINE_LEVEL
|
||||
|
|
@ -169,7 +166,7 @@ bool exec_dev_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/lua ", command)) {
|
||||
if (str_starts_with(command, "/lua ")) {
|
||||
smlua_exec_str(&command[5]);
|
||||
return true;
|
||||
}
|
||||
|
|
@ -179,7 +176,7 @@ bool exec_dev_chat_command(char* command) {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (str_starts_with("/luaf ", command)) {
|
||||
if (str_starts_with(command, "/luaf ")) {
|
||||
smlua_exec_file(&command[6]);
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@
|
|||
#include "game/hardcoded.h"
|
||||
#include "pc/mods/mods.h"
|
||||
#include "pc/mods/mods_utils.h"
|
||||
#include "pc/mods/mod_storage.h"
|
||||
#include "pc/mods/mod_fs.h"
|
||||
#include "pc/crash_handler.h"
|
||||
#include "pc/lua/utils/smlua_text_utils.h"
|
||||
#include "pc/lua/utils/smlua_audio_utils.h"
|
||||
|
|
@ -352,7 +354,7 @@ void smlua_init(void) {
|
|||
for (int j = 0; j < mod->fileCount; j++) {
|
||||
struct ModFile* file = &mod->files[j];
|
||||
// skip loading non-lua files
|
||||
if (!(str_ends_with(file->relativePath, ".lua") || str_ends_with(file->relativePath, ".luac"))) {
|
||||
if (!(path_ends_with(file->relativePath, ".lua") || path_ends_with(file->relativePath, ".luac"))) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -418,6 +420,8 @@ void smlua_shutdown(void) {
|
|||
smlua_model_util_clear();
|
||||
smlua_level_util_reset();
|
||||
smlua_anim_util_reset();
|
||||
mod_storage_shutdown();
|
||||
mod_fs_shutdown();
|
||||
lua_State* L = gLuaState;
|
||||
if (L != NULL) {
|
||||
lua_close(L);
|
||||
|
|
|
|||
|
|
@ -13,4 +13,7 @@
|
|||
// Optional parameters must be contiguous until the last parameter (a mandatory parameter following an optional parameter is not allowed)
|
||||
#define OPTIONAL
|
||||
|
||||
// A macro to tell autogen the field `name` is a function member of the struct that calls `c_function`
|
||||
#define FUNCTION(name, c_function)
|
||||
|
||||
#endif // SMLUA_AUTOGEN_H
|
||||
|
|
|
|||
|
|
@ -98,7 +98,9 @@ static const char *sLuaLvtNames[] = {
|
|||
[LVT_TRAJECTORY_P] = "Trajectory Pointer",
|
||||
[LVT_TEXTURE_P] = "Texture Pointer",
|
||||
[LVT_LUAFUNCTION] = "LuaFunction",
|
||||
[LVT_LUATABLE] = "LuaTable",
|
||||
[LVT_POINTER] = "Pointer",
|
||||
[LVT_FUNCTION] = "Function",
|
||||
[LVT_MAX] = "Max",
|
||||
};
|
||||
|
||||
|
|
@ -549,6 +551,14 @@ static int smlua__get_field(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
// CObject function members
|
||||
if (data->valueType == LVT_FUNCTION) {
|
||||
const char *function = (const char *) data->valueOffset;
|
||||
lua_getglobal(L, function);
|
||||
LUA_STACK_CHECK_END(L);
|
||||
return 1;
|
||||
}
|
||||
|
||||
u8* p = ((u8*)(intptr_t)pointer) + data->valueOffset;
|
||||
if (data->count == 1) {
|
||||
if (smlua_push_field(L, p, data)) {
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
#ifndef SMLUA_COBJECT_H
|
||||
#define SMLUA_COBJECT_H
|
||||
|
||||
#include "lua.h"
|
||||
|
||||
enum LuaValueType {
|
||||
LVT_BOOL,
|
||||
LVT_BOOL_P,
|
||||
|
|
@ -31,7 +33,9 @@ enum LuaValueType {
|
|||
LVT_TRAJECTORY_P,
|
||||
LVT_TEXTURE_P,
|
||||
LVT_LUAFUNCTION,
|
||||
LVT_LUATABLE,
|
||||
LVT_POINTER,
|
||||
LVT_FUNCTION,
|
||||
LVT_MAX,
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1608,7 +1608,7 @@ static struct LuaObjectField sModFields[LUA_MOD_FIELD_COUNT] = {
|
|||
#define LUA_MOD_AUDIO_FIELD_COUNT 4
|
||||
static struct LuaObjectField sModAudioFields[LUA_MOD_AUDIO_FIELD_COUNT] = {
|
||||
{ "baseVolume", LVT_F32, offsetof(struct ModAudio, baseVolume), false, LOT_NONE, 1, sizeof(f32) },
|
||||
{ "file", LVT_COBJECT_P, offsetof(struct ModAudio, file), false, LOT_MODFILE, 1, sizeof(struct ModFile*) },
|
||||
{ "filepath", LVT_STRING_P, offsetof(struct ModAudio, filepath), true, LOT_NONE, 1, sizeof(const char*) },
|
||||
{ "isStream", LVT_BOOL, offsetof(struct ModAudio, isStream), true, LOT_NONE, 1, sizeof(bool) },
|
||||
{ "loaded", LVT_BOOL, offsetof(struct ModAudio, loaded), true, LOT_NONE, 1, sizeof(bool) },
|
||||
};
|
||||
|
|
@ -1634,23 +1634,83 @@ static struct LuaObjectField sModFileFields[LUA_MOD_FILE_FIELD_COUNT] = {
|
|||
{ "wroteBytes", LVT_U64, offsetof(struct ModFile, wroteBytes), true, LOT_NONE, 1, sizeof(u64) },
|
||||
};
|
||||
|
||||
#define LUA_MOD_FS_FIELD_COUNT 5
|
||||
static const char FUNCTION__mod_fs_clear[] = "mod_fs_clear";
|
||||
static const char FUNCTION__mod_fs_copy_file[] = "mod_fs_copy_file";
|
||||
static const char FUNCTION__mod_fs_create_file[] = "mod_fs_create_file";
|
||||
static const char FUNCTION__mod_fs_delete[] = "mod_fs_delete";
|
||||
static const char FUNCTION__mod_fs_delete_file[] = "mod_fs_delete_file";
|
||||
static const char FUNCTION__mod_fs_get_file[] = "mod_fs_get_file";
|
||||
static const char FUNCTION__mod_fs_get_filename[] = "mod_fs_get_filename";
|
||||
static const char FUNCTION__mod_fs_move_file[] = "mod_fs_move_file";
|
||||
static const char FUNCTION__mod_fs_save[] = "mod_fs_save";
|
||||
static const char FUNCTION__mod_fs_set_public[] = "mod_fs_set_public";
|
||||
|
||||
#define LUA_MOD_FS_FIELD_COUNT 15
|
||||
static struct LuaObjectField sModFsFields[LUA_MOD_FS_FIELD_COUNT] = {
|
||||
{ "clear", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_clear, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "copy_file", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_copy_file, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "create_file", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_create_file, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "delete", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_delete, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "delete_file", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_delete_file, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "get_file", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_get_file, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "get_filename", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_get_filename, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "isPublic", LVT_BOOL, offsetof(struct ModFs, isPublic), true, LOT_NONE, 1, sizeof(bool) },
|
||||
{ "mod", LVT_COBJECT_P, offsetof(struct ModFs, mod), true, LOT_MOD, 1, sizeof(struct Mod*) },
|
||||
{ "modPath", LVT_STRING, offsetof(struct ModFs, modPath), true, LOT_NONE, 1, sizeof(char) },
|
||||
{ "move_file", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_move_file, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "numFiles", LVT_U16, offsetof(struct ModFs, numFiles), true, LOT_NONE, 1, sizeof(u16) },
|
||||
{ "save", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_save, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "set_public", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_set_public, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "totalSize", LVT_U32, offsetof(struct ModFs, totalSize), true, LOT_NONE, 1, sizeof(u32) },
|
||||
};
|
||||
|
||||
#define LUA_MOD_FS_FILE_FIELD_COUNT 6
|
||||
static const char FUNCTION__mod_fs_file_erase[] = "mod_fs_file_erase";
|
||||
static const char FUNCTION__mod_fs_file_fill[] = "mod_fs_file_fill";
|
||||
static const char FUNCTION__mod_fs_file_is_eof[] = "mod_fs_file_is_eof";
|
||||
static const char FUNCTION__mod_fs_file_read_bool[] = "mod_fs_file_read_bool";
|
||||
static const char FUNCTION__mod_fs_file_read_bytes[] = "mod_fs_file_read_bytes";
|
||||
static const char FUNCTION__mod_fs_file_read_integer[] = "mod_fs_file_read_integer";
|
||||
static const char FUNCTION__mod_fs_file_read_line[] = "mod_fs_file_read_line";
|
||||
static const char FUNCTION__mod_fs_file_read_number[] = "mod_fs_file_read_number";
|
||||
static const char FUNCTION__mod_fs_file_read_string[] = "mod_fs_file_read_string";
|
||||
static const char FUNCTION__mod_fs_file_rewind[] = "mod_fs_file_rewind";
|
||||
static const char FUNCTION__mod_fs_file_seek[] = "mod_fs_file_seek";
|
||||
static const char FUNCTION__mod_fs_file_set_public[] = "mod_fs_file_set_public";
|
||||
static const char FUNCTION__mod_fs_file_set_text_mode[] = "mod_fs_file_set_text_mode";
|
||||
static const char FUNCTION__mod_fs_file_write_bool[] = "mod_fs_file_write_bool";
|
||||
static const char FUNCTION__mod_fs_file_write_bytes[] = "mod_fs_file_write_bytes";
|
||||
static const char FUNCTION__mod_fs_file_write_integer[] = "mod_fs_file_write_integer";
|
||||
static const char FUNCTION__mod_fs_file_write_line[] = "mod_fs_file_write_line";
|
||||
static const char FUNCTION__mod_fs_file_write_number[] = "mod_fs_file_write_number";
|
||||
static const char FUNCTION__mod_fs_file_write_string[] = "mod_fs_file_write_string";
|
||||
|
||||
#define LUA_MOD_FS_FILE_FIELD_COUNT 25
|
||||
static struct LuaObjectField sModFsFileFields[LUA_MOD_FS_FILE_FIELD_COUNT] = {
|
||||
{ "erase", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_erase, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "filepath", LVT_STRING, offsetof(struct ModFsFile, filepath), true, LOT_NONE, 1, sizeof(char) },
|
||||
{ "fill", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_fill, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "isPublic", LVT_BOOL, offsetof(struct ModFsFile, isPublic), true, LOT_NONE, 1, sizeof(bool) },
|
||||
{ "isText", LVT_BOOL, offsetof(struct ModFsFile, isText), true, LOT_NONE, 1, sizeof(bool) },
|
||||
{ "is_eof", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_is_eof, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "modFs", LVT_COBJECT_P, offsetof(struct ModFsFile, modFs), true, LOT_MODFS, 1, sizeof(struct ModFs*) },
|
||||
{ "offset", LVT_U32, offsetof(struct ModFsFile, offset), true, LOT_NONE, 1, sizeof(u32) },
|
||||
{ "read_bool", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_read_bool, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "read_bytes", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_read_bytes, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "read_integer", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_read_integer, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "read_line", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_read_line, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "read_number", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_read_number, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "read_string", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_read_string, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "rewind", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_rewind, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "seek", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_seek, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "set_public", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_set_public, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "set_text_mode", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_set_text_mode, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "size", LVT_U32, offsetof(struct ModFsFile, size), true, LOT_NONE, 1, sizeof(u32) },
|
||||
{ "write_bool", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_write_bool, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "write_bytes", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_write_bytes, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "write_integer", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_write_integer, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "write_line", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_write_line, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "write_number", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_write_number, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
{ "write_string", LVT_FUNCTION, (size_t) FUNCTION__mod_fs_file_write_string, true, LOT_NONE, 1, sizeof(const char *) },
|
||||
};
|
||||
|
||||
#define LUA_MODE_TRANSITION_INFO_FIELD_COUNT 6
|
||||
|
|
|
|||
|
|
@ -2239,9 +2239,11 @@ char gSmluaConstants[] = ""
|
|||
"GRAB_POS_LIGHT_OBJ=1\n"
|
||||
"GRAB_POS_HEAVY_OBJ=2\n"
|
||||
"GRAB_POS_BOWSER=3\n"
|
||||
"MOD_FS_MAX_SIZE=0x1000000\n"
|
||||
"MOD_FS_MAX_FILES=0x100\n"
|
||||
"MOD_FS_MAX_SIZE=0x2000000\n"
|
||||
"MOD_FS_MAX_FILES=0x200\n"
|
||||
"MOD_FS_MAX_PATH=0x100\n"
|
||||
"MOD_FS_URI_PREFIX='modfs:/'\n"
|
||||
"MOD_FS_URI_FORMAT='modfs:/%s/%s'\n"
|
||||
"INT_TYPE_U8=0\n"
|
||||
"INT_TYPE_U16=1\n"
|
||||
"INT_TYPE_U32=2\n"
|
||||
|
|
@ -2978,6 +2980,7 @@ char gSmluaConstants[] = ""
|
|||
"L_CBUTTONS=CONT_C\n"
|
||||
"R_CBUTTONS=CONT_F\n"
|
||||
"D_CBUTTONS=CONT_D\n"
|
||||
"PALETTES_DIRECTORY='palettes'\n"
|
||||
"MAX_PRESET_PALETTES=128\n"
|
||||
"PANTS=0\n"
|
||||
"SHIRT=1\n"
|
||||
|
|
@ -4621,5 +4624,7 @@ char gSmluaConstants[] = ""
|
|||
"VERSION_TEXT='v'\n"
|
||||
"VERSION_NUMBER=41\n"
|
||||
"MINOR_VERSION_NUMBER=0\n"
|
||||
"GAME_NAME='sm64coopdx'\n"
|
||||
"WINDOW_NAME='Super Mario 64 Coop Deluxe'\n"
|
||||
"MAX_VERSION_LENGTH=128\n"
|
||||
;
|
||||
|
|
@ -22481,53 +22481,6 @@ int smlua_func_mod_fs_create(UNUSED lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_delete(UNUSED lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 0) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_delete", 0, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lua_pushboolean(L, mod_fs_delete());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_save(UNUSED lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 0) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_save", 0, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
lua_pushboolean(L, mod_fs_save());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_set_public(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 1) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_set_public", 1, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool pub = smlua_to_boolean(L, 1);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_set_public"); return 0; }
|
||||
|
||||
lua_pushboolean(L, mod_fs_set_public(pub));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_get_filename(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -22669,6 +22622,59 @@ int smlua_func_mod_fs_clear(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_save(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 1) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_save", 1, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ModFs* modFs = (struct ModFs*)smlua_to_cobject(L, 1, LOT_MODFS);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_save"); return 0; }
|
||||
|
||||
lua_pushboolean(L, mod_fs_save(modFs));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_delete(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 1) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_delete", 1, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ModFs* modFs = (struct ModFs*)smlua_to_cobject(L, 1, LOT_MODFS);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_delete"); return 0; }
|
||||
|
||||
lua_pushboolean(L, mod_fs_delete(modFs));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_set_public(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 2) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_set_public", 2, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ModFs* modFs = (struct ModFs*)smlua_to_cobject(L, 1, LOT_MODFS);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_set_public"); return 0; }
|
||||
bool pub = smlua_to_boolean(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_set_public"); return 0; }
|
||||
|
||||
lua_pushboolean(L, mod_fs_set_public(modFs, pub));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_file_read_bool(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -22916,6 +22922,23 @@ int smlua_func_mod_fs_file_seek(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_file_rewind(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 1) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_file_rewind", 1, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_rewind"); return 0; }
|
||||
|
||||
lua_pushboolean(L, mod_fs_file_rewind(file));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_file_is_eof(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -22973,6 +22996,25 @@ int smlua_func_mod_fs_file_erase(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_file_set_text_mode(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 2) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_fs_file_set_text_mode", 2, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct ModFsFile* file = (struct ModFsFile*)smlua_to_cobject(L, 1, LOT_MODFSFILE);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "mod_fs_file_set_text_mode"); return 0; }
|
||||
bool text = smlua_to_boolean(L, 2);
|
||||
if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "mod_fs_file_set_text_mode"); return 0; }
|
||||
|
||||
lua_pushboolean(L, mod_fs_file_set_text_mode(file, text));
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_fs_file_set_public(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -23136,6 +23178,21 @@ int smlua_func_mod_storage_load_bool(lua_State* L) {
|
|||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_storage_load_all(UNUSED lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
int top = lua_gettop(L);
|
||||
if (top != 0) {
|
||||
LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "mod_storage_load_all", 0, top);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
smlua_push_lua_table(L, mod_storage_load_all());
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int smlua_func_mod_storage_exists(lua_State* L) {
|
||||
if (L == NULL) { return 0; }
|
||||
|
||||
|
|
@ -37904,9 +37961,6 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "mod_fs_get", smlua_func_mod_fs_get);
|
||||
smlua_bind_function(L, "mod_fs_reload", smlua_func_mod_fs_reload);
|
||||
smlua_bind_function(L, "mod_fs_create", smlua_func_mod_fs_create);
|
||||
smlua_bind_function(L, "mod_fs_delete", smlua_func_mod_fs_delete);
|
||||
smlua_bind_function(L, "mod_fs_save", smlua_func_mod_fs_save);
|
||||
smlua_bind_function(L, "mod_fs_set_public", smlua_func_mod_fs_set_public);
|
||||
smlua_bind_function(L, "mod_fs_get_filename", smlua_func_mod_fs_get_filename);
|
||||
smlua_bind_function(L, "mod_fs_get_file", smlua_func_mod_fs_get_file);
|
||||
smlua_bind_function(L, "mod_fs_create_file", smlua_func_mod_fs_create_file);
|
||||
|
|
@ -37914,6 +37968,9 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "mod_fs_copy_file", smlua_func_mod_fs_copy_file);
|
||||
smlua_bind_function(L, "mod_fs_delete_file", smlua_func_mod_fs_delete_file);
|
||||
smlua_bind_function(L, "mod_fs_clear", smlua_func_mod_fs_clear);
|
||||
smlua_bind_function(L, "mod_fs_save", smlua_func_mod_fs_save);
|
||||
smlua_bind_function(L, "mod_fs_delete", smlua_func_mod_fs_delete);
|
||||
smlua_bind_function(L, "mod_fs_set_public", smlua_func_mod_fs_set_public);
|
||||
smlua_bind_function(L, "mod_fs_file_read_bool", smlua_func_mod_fs_file_read_bool);
|
||||
smlua_bind_function(L, "mod_fs_file_read_integer", smlua_func_mod_fs_file_read_integer);
|
||||
smlua_bind_function(L, "mod_fs_file_read_number", smlua_func_mod_fs_file_read_number);
|
||||
|
|
@ -37927,9 +37984,11 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "mod_fs_file_write_string", smlua_func_mod_fs_file_write_string);
|
||||
smlua_bind_function(L, "mod_fs_file_write_line", smlua_func_mod_fs_file_write_line);
|
||||
smlua_bind_function(L, "mod_fs_file_seek", smlua_func_mod_fs_file_seek);
|
||||
smlua_bind_function(L, "mod_fs_file_rewind", smlua_func_mod_fs_file_rewind);
|
||||
smlua_bind_function(L, "mod_fs_file_is_eof", smlua_func_mod_fs_file_is_eof);
|
||||
smlua_bind_function(L, "mod_fs_file_fill", smlua_func_mod_fs_file_fill);
|
||||
smlua_bind_function(L, "mod_fs_file_erase", smlua_func_mod_fs_file_erase);
|
||||
smlua_bind_function(L, "mod_fs_file_set_text_mode", smlua_func_mod_fs_file_set_text_mode);
|
||||
smlua_bind_function(L, "mod_fs_file_set_public", smlua_func_mod_fs_file_set_public);
|
||||
smlua_bind_function(L, "mod_fs_hide_errors", smlua_func_mod_fs_hide_errors);
|
||||
smlua_bind_function(L, "mod_fs_get_last_error", smlua_func_mod_fs_get_last_error);
|
||||
|
|
@ -37941,6 +38000,7 @@ void smlua_bind_functions_autogen(void) {
|
|||
smlua_bind_function(L, "mod_storage_load", smlua_func_mod_storage_load);
|
||||
smlua_bind_function(L, "mod_storage_load_number", smlua_func_mod_storage_load_number);
|
||||
smlua_bind_function(L, "mod_storage_load_bool", smlua_func_mod_storage_load_bool);
|
||||
smlua_bind_function(L, "mod_storage_load_all", smlua_func_mod_storage_load_all);
|
||||
smlua_bind_function(L, "mod_storage_exists", smlua_func_mod_storage_exists);
|
||||
smlua_bind_function(L, "mod_storage_remove", smlua_func_mod_storage_remove);
|
||||
smlua_bind_function(L, "mod_storage_clear", smlua_func_mod_storage_clear);
|
||||
|
|
|
|||
|
|
@ -96,7 +96,7 @@ static struct ModFile* smlua_find_mod_file(const char* moduleName) {
|
|||
}
|
||||
|
||||
// only consider lua files
|
||||
if (!str_ends_with(file->relativePath, ".lua") && !str_ends_with(file->relativePath, ".luac")) {
|
||||
if (!path_ends_with(file->relativePath, ".lua") && !path_ends_with(file->relativePath, ".luac")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -118,7 +118,7 @@ static int smlua_custom_require(lua_State* L) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
if (str_ends_with(moduleName, "/") || str_ends_with(moduleName, "\\")) {
|
||||
if (path_ends_with(moduleName, "/") || path_ends_with(moduleName, "\\")) {
|
||||
LOG_LUA_LINE("cannot require a directory");
|
||||
return 0;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -156,6 +156,22 @@ LuaFunction smlua_to_lua_function(lua_State* L, int index) {
|
|||
return luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
LuaTable smlua_to_lua_table(lua_State* L, int index) {
|
||||
if (lua_type(L, index) == LUA_TNIL) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (lua_type(L, index) != LUA_TTABLE) {
|
||||
LOG_LUA_LINE("smlua_to_lua_table received improper type '%s'", luaL_typename(L, index));
|
||||
gSmLuaConvertSuccess = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
gSmLuaConvertSuccess = true;
|
||||
lua_pushvalue(L, index);
|
||||
return luaL_ref(L, LUA_REGISTRYINDEX);
|
||||
}
|
||||
|
||||
bool smlua_is_cobject(lua_State* L, int index, UNUSED u16 lot) {
|
||||
return lua_isuserdata(L, index);
|
||||
}
|
||||
|
|
@ -497,6 +513,14 @@ void smlua_push_table_field(int index, const char* name) {
|
|||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
void smlua_push_lua_table(lua_State* L, LuaTable table) {
|
||||
if (table != 0) {
|
||||
lua_rawgeti(L, LUA_REGISTRYINDEX, table);
|
||||
} else {
|
||||
lua_pushnil(L);
|
||||
}
|
||||
}
|
||||
|
||||
void smlua_push_bytestring(lua_State* L, ByteString bytestring) {
|
||||
if (bytestring.bytes) {
|
||||
lua_pushlstring(L, bytestring.bytes, bytestring.length);
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
|
||||
extern u8 gSmLuaConvertSuccess;
|
||||
typedef int LuaFunction;
|
||||
typedef int LuaTable;
|
||||
|
||||
typedef struct ByteString {
|
||||
const char *bytes;
|
||||
|
|
@ -27,6 +28,7 @@ lua_Number smlua_to_number(lua_State* L, int index);
|
|||
const char* smlua_to_string(lua_State* L, int index);
|
||||
ByteString smlua_to_bytestring(lua_State* L, int index);
|
||||
LuaFunction smlua_to_lua_function(lua_State* L, int index);
|
||||
LuaTable smlua_to_lua_table(lua_State* L, int index);
|
||||
bool smlua_is_cobject(lua_State* L, int index, u16 lot);
|
||||
void* smlua_to_cobject(lua_State* L, int index, u16 lot);
|
||||
void* smlua_to_cpointer(lua_State* L, int index, u16 lvt);
|
||||
|
|
@ -44,6 +46,7 @@ void smlua_push_string_field(int index, const char* name, const char* val);
|
|||
void smlua_push_nil_field(int index, const char* name);
|
||||
void smlua_push_table_field(int index, const char* name);
|
||||
|
||||
void smlua_push_lua_table(lua_State* L, LuaTable table);
|
||||
void smlua_push_bytestring(lua_State* L, ByteString bytestring);
|
||||
void smlua_push_lnt(struct LSTNetworkType* lnt);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@
|
|||
#include "game/camera.h"
|
||||
#include "engine/math_util.h"
|
||||
#include "pc/mods/mods.h"
|
||||
#include "pc/mods/mod_fs.h"
|
||||
#include "pc/lua/smlua.h"
|
||||
#include "pc/lua/utils/smlua_audio_utils.h"
|
||||
#include "pc/mods/mods_utils.h"
|
||||
|
|
@ -78,9 +79,14 @@ bool smlua_audio_utils_override(u8 sequenceId, s32* bankId, void** seqData) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static u8* buffer = NULL;
|
||||
static long int length = 0;
|
||||
u8* buffer = NULL;
|
||||
u32 length = 0;
|
||||
|
||||
if (is_mod_fs_file(override->filename)) {
|
||||
if (!mod_fs_read_file_from_uri(override->filename, (void **) &buffer, &length)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
FILE* fp = f_open_r(override->filename);
|
||||
if (!fp) { return false; }
|
||||
f_seek(fp, 0L, SEEK_END);
|
||||
|
|
@ -99,6 +105,11 @@ bool smlua_audio_utils_override(u8 sequenceId, s32* bankId, void** seqData) {
|
|||
|
||||
f_close(fp);
|
||||
f_delete(fp);
|
||||
}
|
||||
|
||||
if (!buffer || !length) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// cache
|
||||
override->loaded = true;
|
||||
|
|
@ -110,6 +121,17 @@ bool smlua_audio_utils_override(u8 sequenceId, s32* bankId, void** seqData) {
|
|||
return true;
|
||||
}
|
||||
|
||||
static void smlua_audio_utils_create_audio_override(u8 sequenceId, u8 bankId, u8 defaultVolume, const char *filepath) {
|
||||
struct AudioOverride* override = &sAudioOverrides[sequenceId];
|
||||
if (override->enabled) { audio_init(); }
|
||||
smlua_audio_utils_reset(override);
|
||||
LOG_INFO("Loading audio: %s", filepath);
|
||||
override->filename = strdup(filepath);
|
||||
override->enabled = true;
|
||||
override->bank = bankId;
|
||||
sound_set_background_music_default_volume(sequenceId, defaultVolume);
|
||||
}
|
||||
|
||||
void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, u8 defaultVolume, const char* m64Name) {
|
||||
if (gLuaActiveMod == NULL) { return; }
|
||||
if (sequenceId >= MAX_AUDIO_OVERRIDE) {
|
||||
|
|
@ -122,6 +144,11 @@ void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, u8 defaultVolu
|
|||
return;
|
||||
}
|
||||
|
||||
if (is_mod_fs_file(m64Name)) {
|
||||
smlua_audio_utils_create_audio_override(sequenceId, bankId, defaultVolume, m64Name);
|
||||
return;
|
||||
}
|
||||
|
||||
char m64path[SYS_MAX_PATH] = { 0 };
|
||||
if (snprintf(m64path, SYS_MAX_PATH-1, "sound/%s.m64", m64Name) < 0) {
|
||||
LOG_LUA_LINE("Could not concat m64path: %s", m64path);
|
||||
|
|
@ -134,19 +161,8 @@ void smlua_audio_utils_replace_sequence(u8 sequenceId, u8 bankId, u8 defaultVolu
|
|||
char relPath[SYS_MAX_PATH] = { 0 };
|
||||
snprintf(relPath, SYS_MAX_PATH-1, "%s", file->relativePath);
|
||||
normalize_path(relPath);
|
||||
if (str_ends_with(relPath, m64path)) {
|
||||
struct AudioOverride* override = &sAudioOverrides[sequenceId];
|
||||
if (override->enabled) { audio_init(); }
|
||||
smlua_audio_utils_reset(override);
|
||||
LOG_INFO("Loading audio: %s", file->cachedPath);
|
||||
override->filename = strdup(file->cachedPath);
|
||||
override->enabled = true;
|
||||
override->bank = bankId;
|
||||
#ifdef VERSION_EU
|
||||
//sBackgroundMusicDefaultVolume[sequenceId] = defaultVolume;
|
||||
#else
|
||||
sound_set_background_music_default_volume(sequenceId, defaultVolume);
|
||||
#endif
|
||||
if (path_ends_with(relPath, m64path)) {
|
||||
smlua_audio_utils_create_audio_override(sequenceId, bankId, defaultVolume, file->cachedPath);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
|
@ -174,12 +190,12 @@ static void smlua_audio_custom_init(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static struct ModAudio* find_mod_audio(struct ModFile* file) {
|
||||
static struct ModAudio* find_mod_audio(const char *filepath) {
|
||||
struct DynamicPoolNode* node = sModAudioPool->tail;
|
||||
while (node) {
|
||||
struct DynamicPoolNode* prev = node->prev;
|
||||
struct ModAudio* audio = node->ptr;
|
||||
if (audio->file == file) { return audio; }
|
||||
if (strcmp(filepath, audio->filepath) == 0) { return audio; }
|
||||
node = prev;
|
||||
}
|
||||
return NULL;
|
||||
|
|
@ -209,7 +225,7 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
|
|||
const char* fileTypes[] = { ".mp3", ".aiff", ".ogg", NULL };
|
||||
const char** ft = fileTypes;
|
||||
while (*ft != NULL) {
|
||||
if (str_ends_with((char*)filename, (char*)*ft)) {
|
||||
if (path_ends_with(filename, *ft)) {
|
||||
validFileType = true;
|
||||
break;
|
||||
}
|
||||
|
|
@ -220,13 +236,16 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
|
|||
return NULL;
|
||||
}
|
||||
|
||||
const char *filepath = filename;
|
||||
if (!is_mod_fs_file(filename)) {
|
||||
|
||||
// find mod file in mod list
|
||||
bool foundModFile = false;
|
||||
struct ModFile* modFile = NULL;
|
||||
u16 fileCount = gLuaActiveMod->fileCount;
|
||||
for (u16 i = 0; i < fileCount; i++) {
|
||||
struct ModFile* file = &gLuaActiveMod->files[i];
|
||||
if(str_ends_with(file->relativePath, (char*)filename)) {
|
||||
if(path_ends_with(file->relativePath, filename)) {
|
||||
foundModFile = true;
|
||||
modFile = file;
|
||||
break;
|
||||
|
|
@ -236,9 +255,11 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
|
|||
LOG_LUA_LINE("Could not find audio file: '%s'", filename);
|
||||
return NULL;
|
||||
}
|
||||
filepath = modFile->cachedPath;
|
||||
}
|
||||
|
||||
// find stream in ModAudio list
|
||||
struct ModAudio* audio = find_mod_audio(modFile);
|
||||
struct ModAudio* audio = find_mod_audio(filepath);
|
||||
if (audio) {
|
||||
if (isStream == audio->isStream) {
|
||||
return audio;
|
||||
|
|
@ -261,19 +282,29 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
|
|||
}
|
||||
|
||||
// remember file
|
||||
audio->file = modFile;
|
||||
audio->filepath = strdup(filepath);
|
||||
|
||||
void *buffer = NULL;
|
||||
u32 size = 0;
|
||||
|
||||
if (is_mod_fs_file(filepath)) {
|
||||
if (!mod_fs_read_file_from_uri(filepath, &buffer, &size)) {
|
||||
LOG_ERROR("failed to load audio file '%s': an error occurred with modfs", filename);
|
||||
return NULL;
|
||||
}
|
||||
} else {
|
||||
|
||||
// load audio
|
||||
FILE *f = f_open_r(modFile->cachedPath);
|
||||
FILE *f = f_open_r(filepath);
|
||||
if (!f) {
|
||||
LOG_ERROR("failed to load audio file '%s': file not found", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
f_seek(f, 0, SEEK_END);
|
||||
u32 size = f_tell(f);
|
||||
size = f_tell(f);
|
||||
f_rewind(f);
|
||||
void *buffer = calloc(size, 1);
|
||||
buffer = calloc(size, 1);
|
||||
if (!buffer) {
|
||||
f_close(f);
|
||||
f_delete(f);
|
||||
|
|
@ -291,6 +322,12 @@ struct ModAudio* audio_load_internal(const char* filename, bool isStream) {
|
|||
}
|
||||
f_close(f);
|
||||
f_delete(f);
|
||||
}
|
||||
|
||||
if (!buffer || !size) {
|
||||
LOG_ERROR("failed to load audio file '%s': failed to read audio data", filename);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// decode the audio buffer
|
||||
ma_result result = ma_decoder_init_memory(buffer, size, NULL, &audio->decoder);
|
||||
|
|
@ -604,6 +641,7 @@ void audio_custom_shutdown(void) {
|
|||
audio_sample_destroy_copies(audio);
|
||||
}
|
||||
ma_sound_uninit(&audio->sound);
|
||||
free((void *) audio->filepath);
|
||||
}
|
||||
dynamic_pool_free(sModAudioPool, audio);
|
||||
node = prev;
|
||||
|
|
|
|||
|
|
@ -22,7 +22,7 @@ struct ModAudioSampleCopies {
|
|||
};
|
||||
|
||||
struct ModAudio {
|
||||
struct ModFile* file;
|
||||
const char *filepath;
|
||||
ma_sound sound;
|
||||
ma_decoder decoder;
|
||||
void *buffer;
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ size_t mod_get_lua_size(struct Mod* mod) {
|
|||
|
||||
for (int i = 0; i < mod->fileCount; i++) {
|
||||
struct ModFile* file = &mod->files[i];
|
||||
if (!(str_ends_with(file->relativePath, ".lua") || str_ends_with(file->relativePath, ".luac"))) { continue; }
|
||||
if (!(path_ends_with(file->relativePath, ".lua") || path_ends_with(file->relativePath, ".luac"))) { continue; }
|
||||
size += file->size;
|
||||
}
|
||||
|
||||
|
|
@ -161,19 +161,19 @@ void mod_activate(struct Mod* mod) {
|
|||
mod_cache_update(mod, file);
|
||||
}
|
||||
|
||||
if (str_ends_with(file->relativePath, ".bin")) {
|
||||
if (path_ends_with(file->relativePath, ".bin")) {
|
||||
mod_activate_bin(mod, file);
|
||||
}
|
||||
if (str_ends_with(file->relativePath, ".col")) {
|
||||
if (path_ends_with(file->relativePath, ".col")) {
|
||||
mod_activate_col(file);
|
||||
}
|
||||
if (str_ends_with(file->relativePath, ".lvl")) {
|
||||
if (path_ends_with(file->relativePath, ".lvl")) {
|
||||
mod_activate_lvl(mod, file);
|
||||
}
|
||||
if (str_ends_with(file->relativePath, ".bhv")) {
|
||||
if (path_ends_with(file->relativePath, ".bhv")) {
|
||||
mod_activate_bhv(mod, file);
|
||||
}
|
||||
if (str_ends_with(file->relativePath, ".tex")) {
|
||||
if (path_ends_with(file->relativePath, ".tex")) {
|
||||
mod_activate_tex(file);
|
||||
}
|
||||
}
|
||||
|
|
@ -337,7 +337,7 @@ static bool mod_load_files_dir(struct Mod* mod, char* fullPath, const char* subD
|
|||
bool fileTypeMatch = false;
|
||||
const char** ft = fileTypes;
|
||||
while (*ft != NULL) {
|
||||
if (str_ends_with(path, (char*)*ft)) {
|
||||
if (path_ends_with(path, (char*)*ft)) {
|
||||
fileTypeMatch = true;
|
||||
}
|
||||
ft++;
|
||||
|
|
@ -562,7 +562,7 @@ bool mod_load(struct Mods* mods, char* basePath, char* modName) {
|
|||
bool isDirectory = fs_sys_dir_exists(fullPath);
|
||||
|
||||
// make sure mod is valid
|
||||
if (str_ends_with(modName, ".lua")) {
|
||||
if (path_ends_with(modName, ".lua")) {
|
||||
valid = true;
|
||||
} else if (fs_sys_dir_exists(fullPath)) {
|
||||
char tmpPath[SYS_MAX_PATH] = { 0 };
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -4,12 +4,13 @@
|
|||
#include "types.h"
|
||||
#include "src/pc/lua/smlua.h"
|
||||
|
||||
#define MOD_FS_MAX_SIZE 0x1000000 // 16 MB
|
||||
#define MOD_FS_MAX_FILES 0x100
|
||||
#define MOD_FS_MAX_SIZE 0x2000000 // 32 MB
|
||||
#define MOD_FS_MAX_FILES 0x200
|
||||
#define MOD_FS_MAX_PATH 0x100
|
||||
#define MOD_FS_DIRECTORY "sav"
|
||||
#define MOD_FS_EXTENSION ".modfs"
|
||||
#define MOD_FS_VERSION 1
|
||||
#define MOD_FS_URI_PREFIX "modfs:/"
|
||||
#define MOD_FS_URI_FORMAT "modfs:/%s/%s" // modPath, filepath
|
||||
|
||||
#define is_mod_fs_file(filepath) (memcmp(filepath, MOD_FS_URI_PREFIX, sizeof(MOD_FS_URI_PREFIX) - 1) == 0)
|
||||
|
||||
enum ModFsFileIntType {
|
||||
INT_TYPE_U8,
|
||||
|
|
@ -53,6 +54,26 @@ struct ModFsFile {
|
|||
u32 offset;
|
||||
bool isText;
|
||||
bool isPublic;
|
||||
|
||||
FUNCTION(read_bool, mod_fs_file_read_bool);
|
||||
FUNCTION(read_integer, mod_fs_file_read_integer);
|
||||
FUNCTION(read_number, mod_fs_file_read_number);
|
||||
FUNCTION(read_bytes, mod_fs_file_read_bytes);
|
||||
FUNCTION(read_string, mod_fs_file_read_string);
|
||||
FUNCTION(read_line, mod_fs_file_read_line);
|
||||
FUNCTION(write_bool, mod_fs_file_write_bool);
|
||||
FUNCTION(write_integer, mod_fs_file_write_integer);
|
||||
FUNCTION(write_number, mod_fs_file_write_number);
|
||||
FUNCTION(write_bytes, mod_fs_file_write_bytes);
|
||||
FUNCTION(write_string, mod_fs_file_write_string);
|
||||
FUNCTION(write_line, mod_fs_file_write_line);
|
||||
FUNCTION(seek, mod_fs_file_seek);
|
||||
FUNCTION(rewind, mod_fs_file_rewind);
|
||||
FUNCTION(is_eof, mod_fs_file_is_eof);
|
||||
FUNCTION(fill, mod_fs_file_fill);
|
||||
FUNCTION(erase, mod_fs_file_erase);
|
||||
FUNCTION(set_text_mode, mod_fs_file_set_text_mode);
|
||||
FUNCTION(set_public, mod_fs_file_set_public);
|
||||
};
|
||||
|
||||
struct ModFs {
|
||||
|
|
@ -62,6 +83,17 @@ struct ModFs {
|
|||
u16 numFiles;
|
||||
u32 totalSize;
|
||||
bool isPublic;
|
||||
|
||||
FUNCTION(get_filename, mod_fs_get_filename);
|
||||
FUNCTION(get_file, mod_fs_get_file);
|
||||
FUNCTION(create_file, mod_fs_create_file);
|
||||
FUNCTION(move_file, mod_fs_move_file);
|
||||
FUNCTION(copy_file, mod_fs_copy_file);
|
||||
FUNCTION(delete_file, mod_fs_delete_file);
|
||||
FUNCTION(clear, mod_fs_clear);
|
||||
FUNCTION(save, mod_fs_save);
|
||||
FUNCTION(delete, mod_fs_delete);
|
||||
FUNCTION(set_public, mod_fs_set_public);
|
||||
};
|
||||
|
||||
/* |description|
|
||||
|
|
@ -84,21 +116,6 @@ Creates a modfs object for the active mod if it doesn't exist. Returns the modfs
|
|||
|descriptionEnd| */
|
||||
struct ModFs *mod_fs_create();
|
||||
|
||||
/* |description|
|
||||
Deletes the modfs object of the active mod if it exists. Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_delete();
|
||||
|
||||
/* |description|
|
||||
Saves the modfs object of the active mod if it exists. Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_save();
|
||||
|
||||
/* |description|
|
||||
Marks the modfs object of the active mod as public (i.e. readable by other mods) if it exists. Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_set_public(bool pub);
|
||||
|
||||
/* |description|
|
||||
Gets the filename at position `index` of the provided `modFs`
|
||||
|descriptionEnd| */
|
||||
|
|
@ -134,6 +151,21 @@ Deletes all files of the provided `modFs`. Returns true on success
|
|||
|descriptionEnd| */
|
||||
bool mod_fs_clear(struct ModFs *modFs);
|
||||
|
||||
/* |description|
|
||||
Saves the provided `modFs` to persistent storage. Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_save(struct ModFs *modFs);
|
||||
|
||||
/* |description|
|
||||
Removes the provided `modFs` from persistent storage and deletes its object. Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_delete(struct ModFs *modFs);
|
||||
|
||||
/* |description|
|
||||
Marks the provided `modFs` as public (i.e. readable by other mods). Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_set_public(struct ModFs *modFs, bool pub);
|
||||
|
||||
/* |description|
|
||||
Reads a boolean from a binary modfs `file`
|
||||
|descriptionEnd| */
|
||||
|
|
@ -203,6 +235,12 @@ Returns true on success
|
|||
|descriptionEnd| */
|
||||
bool mod_fs_file_seek(struct ModFsFile *file, s32 offset, enum ModFsFileSeek origin);
|
||||
|
||||
/* |description|
|
||||
Sets the current position of a modfs `file` to its beginning.
|
||||
Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_file_rewind(struct ModFsFile *file);
|
||||
|
||||
/* |description|
|
||||
Returns true if the provided modfs `file` has reached its end of file
|
||||
|descriptionEnd| */
|
||||
|
|
@ -218,6 +256,11 @@ Erases `length` bytes or characters from a modfs `file`. Returns true on success
|
|||
|descriptionEnd| */
|
||||
bool mod_fs_file_erase(struct ModFsFile *file, u32 length);
|
||||
|
||||
/* |description|
|
||||
Marks the provided modfs `file` as text. Returns true on success
|
||||
|descriptionEnd| */
|
||||
bool mod_fs_file_set_text_mode(struct ModFsFile *file, bool text);
|
||||
|
||||
/* |description|
|
||||
Marks the provided modfs `file` as public (i.e. readable by other mods). Returns true on success
|
||||
|descriptionEnd| */
|
||||
|
|
@ -233,4 +276,9 @@ Returns the last error message generated by `mod_fs` functions or nil if no erro
|
|||
|descriptionEnd| */
|
||||
const char *mod_fs_get_last_error();
|
||||
|
||||
// Functions used by other C modules, not API
|
||||
|
||||
bool mod_fs_read_file_from_uri(const char *uri, void **buffer, u32 *length);
|
||||
void mod_fs_shutdown();
|
||||
|
||||
#endif // MOD_FS_H
|
||||
|
|
|
|||
|
|
@ -124,15 +124,15 @@ static bool mod_import_zip(char* path, bool* isLua, bool* isDynos) {
|
|||
return false;
|
||||
}
|
||||
|
||||
if (str_ends_with(file_stat.m_filename, ".lua") || str_ends_with(file_stat.m_filename, ".luac")) {
|
||||
if (path_ends_with(file_stat.m_filename, ".lua") || path_ends_with(file_stat.m_filename, ".luac")) {
|
||||
path_get_folder(file_stat.m_filename, luaPath);
|
||||
*isLua = true;
|
||||
break;
|
||||
} else if (str_ends_with(file_stat.m_filename, ".tex")) {
|
||||
} else if (path_ends_with(file_stat.m_filename, ".tex")) {
|
||||
*isDynos = true;
|
||||
} else if (str_ends_with(file_stat.m_filename, ".png")) {
|
||||
} else if (path_ends_with(file_stat.m_filename, ".png")) {
|
||||
*isDynos = true;
|
||||
} else if (str_ends_with(file_stat.m_filename, ".bin")) {
|
||||
} else if (path_ends_with(file_stat.m_filename, ".bin")) {
|
||||
*isDynos = true;
|
||||
}
|
||||
}
|
||||
|
|
@ -258,18 +258,18 @@ bool mod_import_file(char* path) {
|
|||
bool isPalette = false;
|
||||
bool ret = false;
|
||||
|
||||
if (gNetworkType != NT_NONE && !str_ends_with(path, ".ini")) {
|
||||
if (gNetworkType != NT_NONE && !path_ends_with(path, ".ini")) {
|
||||
djui_popup_create(DLANG(NOTIF, IMPORT_FAIL_INGAME), 2);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (str_ends_with(path, ".lua") || str_ends_with(path, ".luac")) {
|
||||
if (path_ends_with(path, ".lua") || path_ends_with(path, ".luac")) {
|
||||
isLua = true;
|
||||
ret = mod_import_lua(path);
|
||||
} else if (str_ends_with(path, ".ini")) {
|
||||
} else if (path_ends_with(path, ".ini")) {
|
||||
isPalette = true;
|
||||
ret = mod_import_palette(path);
|
||||
} else if (str_ends_with(path, ".zip")) {
|
||||
} else if (path_ends_with(path, ".zip")) {
|
||||
ret = mod_import_zip(path, &isLua, &isDynos);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@
|
|||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include "pc/mini.h"
|
||||
|
||||
extern "C" {
|
||||
|
|
@ -16,6 +17,8 @@ extern "C" {
|
|||
|
||||
#define C_FIELD extern "C"
|
||||
|
||||
static std::map<std::string, mINI::INIStructure> sModStorageFiles;
|
||||
|
||||
static void strdelete(char* string, const char* substr) {
|
||||
// i is used to loop through the string
|
||||
u16 i = 0;
|
||||
|
|
@ -43,7 +46,7 @@ static void strdelete(char* string, const char* substr) {
|
|||
string[i] = '\0';
|
||||
}
|
||||
|
||||
bool char_valid(const char* buffer, bool isKey) {
|
||||
static bool char_valid(const char* buffer, bool isKey) {
|
||||
if (buffer[0] == '\0') { return false; }
|
||||
|
||||
while (*buffer != '\0') {
|
||||
|
|
@ -57,7 +60,7 @@ bool char_valid(const char* buffer, bool isKey) {
|
|||
return true;
|
||||
}
|
||||
|
||||
void mod_storage_get_filename(char* dest) {
|
||||
static void mod_storage_get_filename(char* dest) {
|
||||
const char* path = fs_get_write_path(SAVE_DIRECTORY); // get user path
|
||||
snprintf(dest, SYS_MAX_PATH - 1, "%s/%s", path, gLuaActiveMod->relativePath); // append sav folder
|
||||
strdelete(dest, ".lua"); // delete ".lua" from sav name
|
||||
|
|
@ -65,63 +68,63 @@ void mod_storage_get_filename(char* dest) {
|
|||
normalize_path(dest); // fix any out of place slashes
|
||||
}
|
||||
|
||||
C_FIELD bool mod_storage_save(const char* key, const char* value) {
|
||||
if (gLuaActiveMod == NULL) { return false; }
|
||||
if (strlen(key) > MAX_KEY_VALUE_LENGTH || strlen(value) > MAX_KEY_VALUE_LENGTH) { return false; }
|
||||
if (!char_valid(key, true) || !char_valid(value, false)) { return false; }
|
||||
static bool mod_storage_check_inputs(const char *key, const char *value, char *filename) {
|
||||
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
// check active mod
|
||||
if (gLuaActiveMod == NULL) { return false; }
|
||||
|
||||
// retrieve filename
|
||||
mod_storage_get_filename(filename);
|
||||
|
||||
// ensure savPath exists
|
||||
// check key validity
|
||||
if (key != NULL) {
|
||||
if (strlen(key) > MAX_KEY_VALUE_LENGTH) { return false; }
|
||||
if (!char_valid(key, true)) { return false; }
|
||||
}
|
||||
|
||||
// check value validity
|
||||
if (value != NULL) {
|
||||
if (strlen(value) > MAX_KEY_VALUE_LENGTH) { return false; }
|
||||
if (!char_valid(value, false)) { return false; }
|
||||
|
||||
// write: ensure savPath exists
|
||||
const char* savPath = fs_get_write_path(SAVE_DIRECTORY);
|
||||
if (!fs_sys_dir_exists(savPath)) { fs_sys_mkdir(savPath); }
|
||||
}
|
||||
|
||||
mINI::INIFile file(filename);
|
||||
mINI::INIStructure ini;
|
||||
file.read(ini);
|
||||
|
||||
if (ini["storage"].size() > MAX_KEYS) { return false; }
|
||||
|
||||
ini["storage"][key] = value;
|
||||
|
||||
file.write(ini);
|
||||
file.generate(ini);
|
||||
// No value == read or delete, check if filename exists
|
||||
else {
|
||||
if (!fs_sys_path_exists(filename)) { return false; }
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
C_FIELD bool mod_storage_save_number(const char* key, f32 value) {
|
||||
// Store string results in a temporary buffer
|
||||
// this assumes mod_storage_load will only ever be called by Lua
|
||||
static char str[MAX_KEY_VALUE_LENGTH];
|
||||
if (floor(value) == value) {
|
||||
snprintf(str, MAX_KEY_VALUE_LENGTH, "%lld", (s64)value);
|
||||
} else {
|
||||
snprintf(str, MAX_KEY_VALUE_LENGTH, "%f", value);
|
||||
//////////
|
||||
// read //
|
||||
//////////
|
||||
|
||||
static mINI::INIStructure &mod_storage_read_file(const char *filename) {
|
||||
const auto &it = sModStorageFiles.find(filename);
|
||||
if (it != sModStorageFiles.end()) {
|
||||
return it->second;
|
||||
}
|
||||
|
||||
return mod_storage_save(key, str);
|
||||
}
|
||||
|
||||
C_FIELD bool mod_storage_save_bool(const char* key, bool value) {
|
||||
return mod_storage_save(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
C_FIELD const char* mod_storage_load(const char* key) {
|
||||
if (gLuaActiveMod == NULL) { return NULL; }
|
||||
if (strlen(key) > MAX_KEY_VALUE_LENGTH) { return NULL; }
|
||||
if (!char_valid(key, true)) { return NULL; }
|
||||
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
mod_storage_get_filename(filename);
|
||||
if (!fs_sys_path_exists(filename)) { return NULL; }
|
||||
|
||||
mINI::INIFile file(filename);
|
||||
mINI::INIStructure ini;
|
||||
file.read(ini);
|
||||
sModStorageFiles[filename] = ini;
|
||||
return sModStorageFiles[filename];
|
||||
}
|
||||
|
||||
std::string str = ini["storage"][key];
|
||||
C_FIELD const char* mod_storage_load(const char* key) {
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
if (!mod_storage_check_inputs(key, NULL, filename)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const mINI::INIStructure &ini = mod_storage_read_file(filename);
|
||||
std::string str = ini.get("storage").get(key);
|
||||
if (str.empty()) { return NULL; }
|
||||
|
||||
// Store string results in a temporary buffer
|
||||
|
|
@ -146,35 +149,83 @@ C_FIELD bool mod_storage_load_bool(const char* key) {
|
|||
}
|
||||
|
||||
C_FIELD bool mod_storage_exists(const char* key) {
|
||||
if (gLuaActiveMod == NULL) { return false; }
|
||||
if (strlen(key) > MAX_KEY_VALUE_LENGTH) { return false; }
|
||||
if (!char_valid(key, true)) { return false; }
|
||||
return mod_storage_load(key) != NULL;
|
||||
}
|
||||
|
||||
C_FIELD LuaTable mod_storage_load_all(void) {
|
||||
struct lua_State *L = gLuaState;
|
||||
if (!L) { return 0; }
|
||||
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
mod_storage_get_filename(filename);
|
||||
if (!fs_sys_path_exists(filename)) { return false; }
|
||||
if (!mod_storage_check_inputs(NULL, NULL, filename)) {
|
||||
lua_pushnil(L);
|
||||
return 0;
|
||||
}
|
||||
|
||||
const mINI::INIStructure &ini = mod_storage_read_file(filename);
|
||||
|
||||
LUA_STACK_CHECK_BEGIN_NUM(L, 1);
|
||||
|
||||
lua_newtable(L);
|
||||
for (const auto &kv : ini.get("storage")) {
|
||||
lua_pushstring(L, kv.first.c_str());
|
||||
lua_pushstring(L, kv.second.c_str());
|
||||
lua_settable(L, -3);
|
||||
}
|
||||
|
||||
LUA_STACK_CHECK_END(L);
|
||||
return smlua_to_lua_table(L, -1);
|
||||
}
|
||||
|
||||
///////////
|
||||
// write //
|
||||
///////////
|
||||
|
||||
C_FIELD bool mod_storage_save(const char* key, const char* value) {
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
if (!mod_storage_check_inputs(key, value, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mINI::INIStructure &ini = mod_storage_read_file(filename);
|
||||
if (!ini["storage"].has(key) && ini["storage"].size() >= MAX_KEYS) { return false; }
|
||||
|
||||
ini["storage"][key] = value;
|
||||
|
||||
mINI::INIFile file(filename);
|
||||
mINI::INIStructure ini;
|
||||
file.read(ini);
|
||||
file.write(ini);
|
||||
file.generate(ini);
|
||||
|
||||
return ini["storage"].has(key);
|
||||
return true;
|
||||
}
|
||||
|
||||
C_FIELD bool mod_storage_save_number(const char* key, f32 value) {
|
||||
// Store string results in a temporary buffer
|
||||
// this assumes mod_storage_load will only ever be called by Lua
|
||||
static char str[MAX_KEY_VALUE_LENGTH];
|
||||
if (floor(value) == value) {
|
||||
snprintf(str, MAX_KEY_VALUE_LENGTH, "%lld", (s64)value);
|
||||
} else {
|
||||
snprintf(str, MAX_KEY_VALUE_LENGTH, "%f", value);
|
||||
}
|
||||
|
||||
return mod_storage_save(key, str);
|
||||
}
|
||||
|
||||
C_FIELD bool mod_storage_save_bool(const char* key, bool value) {
|
||||
return mod_storage_save(key, value ? "true" : "false");
|
||||
}
|
||||
|
||||
C_FIELD bool mod_storage_remove(const char* key) {
|
||||
if (gLuaActiveMod == NULL) { return false; }
|
||||
if (strlen(key) > MAX_KEY_VALUE_LENGTH) { return false; }
|
||||
if (!char_valid(key, true)) { return false; }
|
||||
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
mod_storage_get_filename(filename);
|
||||
if (!fs_sys_path_exists(filename)) { return false; }
|
||||
if (!mod_storage_check_inputs(key, NULL, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mINI::INIFile file(filename);
|
||||
mINI::INIStructure ini;
|
||||
file.read(ini);
|
||||
mINI::INIStructure &ini = mod_storage_read_file(filename);
|
||||
|
||||
if (ini["storage"].remove(key)) {
|
||||
mINI::INIFile file(filename);
|
||||
file.write(ini);
|
||||
file.generate(ini);
|
||||
return true;
|
||||
|
|
@ -184,22 +235,26 @@ C_FIELD bool mod_storage_remove(const char* key) {
|
|||
}
|
||||
|
||||
C_FIELD bool mod_storage_clear(void) {
|
||||
if (gLuaActiveMod == NULL) { return false; }
|
||||
|
||||
char filename[SYS_MAX_PATH] = { 0 };
|
||||
mod_storage_get_filename(filename);
|
||||
if (!fs_sys_path_exists(filename)) { return false; }
|
||||
|
||||
mINI::INIFile file(filename);
|
||||
mINI::INIStructure ini;
|
||||
file.read(ini);
|
||||
if (!mod_storage_check_inputs(NULL, NULL, filename)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
mINI::INIStructure &ini = mod_storage_read_file(filename);
|
||||
if (ini["storage"].size() == 0) { return false; }
|
||||
|
||||
ini["storage"].clear();
|
||||
|
||||
mINI::INIFile file(filename);
|
||||
file.write(ini);
|
||||
file.generate(ini);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
C_FIELD void mod_storage_shutdown(void) {
|
||||
for (auto &file : sModStorageFiles) {
|
||||
file.second.clear();
|
||||
}
|
||||
sModStorageFiles.clear();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
#include "pc/lua/smlua_utils.h"
|
||||
|
||||
#define MAX_KEYS 4096
|
||||
#define MAX_KEY_VALUE_LENGTH 1024
|
||||
|
|
@ -25,6 +26,8 @@ const char *mod_storage_load(const char* key);
|
|||
f32 mod_storage_load_number(const char* key);
|
||||
/* |description|Loads a bool `value` from a `key` in mod storage|descriptionEnd| */
|
||||
bool mod_storage_load_bool(const char* key);
|
||||
/* |description|Loads all keys and values in mod storage as strings and returns them as a table|descriptionEnd| */
|
||||
LuaTable mod_storage_load_all(void);
|
||||
|
||||
/* |description|Checks if a `key` is in mod storage|descriptionEnd| */
|
||||
bool mod_storage_exists(const char* key);
|
||||
|
|
@ -33,6 +36,8 @@ bool mod_storage_remove(const char* key);
|
|||
/* |description|Clears the mod's data from mod storage|descriptionEnd| */
|
||||
bool mod_storage_clear(void);
|
||||
|
||||
void mod_storage_shutdown(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -160,21 +160,35 @@ bool mod_file_create_directories(struct Mod* mod, struct ModFile* modFile) {
|
|||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
bool str_ends_with(const char* string, const char* suffix) {
|
||||
bool str_starts_with(const char *string, const char *prefix) {
|
||||
if (string == NULL || prefix == NULL) { return false; }
|
||||
|
||||
return strncmp(string, prefix, strlen(prefix)) == 0;
|
||||
}
|
||||
|
||||
bool str_ends_with(const char *string, const char *suffix) {
|
||||
if (string == NULL || suffix == NULL) { return false; }
|
||||
|
||||
size_t stringLength = strlen(string);
|
||||
size_t suffixLength = strlen(suffix);
|
||||
return stringLength >= suffixLength && strncmp(string + stringLength - suffixLength, suffix, suffixLength) == 0;
|
||||
}
|
||||
|
||||
if (suffixLength > stringLength) { return false; }
|
||||
bool path_ends_with(const char* path, const char* suffix) {
|
||||
if (path == NULL || suffix == NULL) { return false; }
|
||||
|
||||
size_t pathLength = strlen(path);
|
||||
size_t suffixLength = strlen(suffix);
|
||||
|
||||
if (suffixLength > pathLength) { return false; }
|
||||
|
||||
#ifdef _WIN32
|
||||
// Paths on Windows are case-insensitive and might have
|
||||
// upper-case or mixed-case endings.
|
||||
return (0 == _stricmp(&(string[stringLength - suffixLength]), suffix));
|
||||
return (0 == _stricmp(&(path[pathLength - suffixLength]), suffix));
|
||||
#else
|
||||
// Always expecting lower-case file paths and extensions
|
||||
return (0 == strcmp(&(string[stringLength - suffixLength]), suffix));
|
||||
return (0 == strcmp(&(path[pathLength - suffixLength]), suffix));
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -12,7 +12,10 @@ void mods_delete_tmp(void);
|
|||
bool mod_file_full_path(char* destination, struct Mod* mod, struct ModFile* modFile);
|
||||
bool mod_file_create_directories(struct Mod* mod, struct ModFile* modFile);
|
||||
|
||||
bool str_ends_with(const char* string, const char* suffix);
|
||||
bool str_starts_with(const char *string, const char *prefix);
|
||||
bool str_ends_with(const char *string, const char *suffix);
|
||||
|
||||
bool path_ends_with(const char* path, const char* suffix);
|
||||
|
||||
char* extract_lua_field(char* fieldName, char* buffer);
|
||||
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
|
||||
extern "C" {
|
||||
#include "platform.h"
|
||||
#include "mods/mods_utils.h" // for str_ends_with
|
||||
#include "mods/mods_utils.h" // for path_ends_with
|
||||
#include "mods/mod_cache.h" // for md5 hashing
|
||||
#include "mods/mods.h"
|
||||
#include "loading.h"
|
||||
|
|
@ -81,7 +81,7 @@ static bool is_rom_valid(const std::string romPath) {
|
|||
inline static bool scan_path_for_rom(const char *dir) {
|
||||
for (const auto &entry: std::filesystem::directory_iterator(dir)) {
|
||||
std::string path = entry.path().generic_string();
|
||||
if (str_ends_with(path.c_str(), ".z64")) {
|
||||
if (path_ends_with(path.c_str(), ".z64")) {
|
||||
if (is_rom_valid(path)) { return true; }
|
||||
}
|
||||
}
|
||||
|
|
|
|||
25677
src/pc/utils/json.hpp
Normal file
25677
src/pc/utils/json.hpp
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Add table
Reference in a new issue