Merge branch 'coopdx.-dev-sept25' of https://github.com/iZePlayzYT/sm64coopdx into coopdx.-dev-sept25

This commit is contained in:
iZePlayz 2025-11-21 18:21:12 +01:00
commit 78ad942ad5
164 changed files with 44787 additions and 16791 deletions

View file

@ -208,7 +208,7 @@ jobs:
build-macos-intel:
if: ${{ github.event_name == 'workflow_dispatch' || contains(github.event.head_commit.message, '[build]') }}
runs-on: macos-13
runs-on: macos-15-intel
steps:
- name: Checkout repository
uses: actions/checkout@v4

2
.gitignore vendored
View file

@ -17,7 +17,6 @@
# Libraries
*.lib
*.a
*.la
*.lo
@ -91,3 +90,4 @@ todo-old.txt
*.DS_Store
tools/ido5.3_compiler/usr/lib/libc.so.1
/.vs
tools/audiofile/libaudiofile.a

View file

@ -978,11 +978,11 @@ ifeq ($(COOPNET),1)
ifeq ($(shell uname -m),arm64)
LDFLAGS += -Wl,-rpath,@loader_path -L./lib/coopnet/mac_arm/ -l coopnet
COOPNET_LIBS += ./lib/coopnet/mac_arm/libcoopnet.dylib
COOPNET_LIBS += ./lib/coopnet/mac_arm/libjuice.1.2.2.dylib
COOPNET_LIBS += ./lib/coopnet/mac_arm/libjuice.1.6.2.dylib
else
LDFLAGS += -Wl,-rpath,@loader_path -L./lib/coopnet/mac_intel/ -l coopnet
COOPNET_LIBS += ./lib/coopnet/mac_intel/libcoopnet.dylib
COOPNET_LIBS += ./lib/coopnet/mac_intel/libjuice.1.2.2.dylib
COOPNET_LIBS += ./lib/coopnet/mac_intel/libjuice.1.6.2.dylib
endif
else ifeq ($(TARGET_RPI),1)
ifneq (,$(findstring aarch64,$(machine)))

View file

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

View file

@ -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',
@ -16,13 +17,38 @@ type_mappings = {
'double': 'f64',
'uintptr_t': 'u64', # this is assumed
'size_t': 'u64', # this is assumed
}
exclude_structs = [
'SPTask',
'VblankHandler',
'AnimationTable',
'BullyCollisionData',
'CameraFOVStatus',
'CameraStoredInfo',
'CameraTrigger',
'Cutscene',
'CutsceneSplinePoint',
'CutsceneVariable',
'FloorGeometry',
'GraphNode_802A45E4',
'HandheldShakePoint',
'LinearTransitionPoint',
'MarioAnimDmaRelatedThing',
'ModAudioSampleCopies',
'ModFile',
'ModeTransitionInfo',
'OffsetSizePair',
'PaintingMeshVertex',
'ParallelTrackingPoint',
'PlayerGeometry',
'SPTask',
'SoundState',
'TransitionInfo',
'UnusedArea28',
'VblankHandler',
'Vtx_Interp',
'WarpTransition',
'WarpTransitionData',
]
override_types = { "Gfx", "Vtx" }
@ -117,6 +143,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 +226,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 +318,12 @@ def translate_type_to_lua(ptype):
if ptype == 'LuaFunction':
return '`Lua Function` ()', None
if ptype == 'LuaTable':
return '`table`', None
if ptype == cobject_function_identifier:
return cobject_function_identifier, None
if ptype.count('*') == 1 and '???' not in translate_type_to_lvt(ptype):
ptype = ptype.replace('const', '').replace('*', '').strip()
s = '`Pointer` <`%s`>' % translate_type_to_lua(ptype)[0].replace('`', '').strip()

View file

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

View file

@ -88,15 +88,15 @@ override_allowed_functions = {
"src/pc/djui/djui_popup.h": [ "create" ],
"src/pc/djui/djui_language.h": [ "djui_language_get" ],
"src/pc/djui/djui_panel_menu.h": [ "djui_menu_get_rainbow_string_color" ],
"src/game/save_file.h": [ "get_level_", "save_file_get_", "save_file_set_flags", "save_file_clear_flags", "save_file_reload", "save_file_erase_current_backup_save", "save_file_set_star_flags", "save_file_is_cannon_unlocked", "touch_coin_score_age", "save_file_set_course_coin_score", "save_file_do_save", "save_file_remove_star_flags", "save_file_erase" ],
"src/game/save_file.h": [ "get_level_", "save_file_get_", "save_file_set_flags", "save_file_clear_flags", "save_file_reload", "save_file_erase_current_backup_save", "save_file_set_star_flags", "save_file_is_cannon_unlocked", "save_file_set_cannon_unlocked", "touch_coin_score_age", "save_file_set_course_coin_score", "save_file_do_save", "save_file_remove_star_flags", "save_file_erase" ],
"src/pc/lua/utils/smlua_model_utils.h": [ "smlua_model_util_get_id" ],
"src/game/object_list_processor.h": [ "set_object_respawn_info_bits" ],
"src/game/platform_displacement.h": [ "apply_platform_displacement" ],
"src/game/mario_misc.h": [ "bhv_toad.*", "bhv_unlock_door.*", "geo_get_.*_state" ],
"src/game/level_update.h": [ "level_trigger_warp", "get_painting_warp_node", "initiate_painting_warp", "warp_special", "lvl_set_current_level", "level_control_timer_running", "fade_into_special_warp", "get_instant_warp" ],
"src/game/level_update.h": [ "level_trigger_warp", "get_painting_warp_node", "initiate_painting_warp", "warp_special", "lvl_set_current_level", "level_control_timer_running", "pressed_pause", "fade_into_special_warp", "get_instant_warp" ],
"src/game/area.h": [ "get_mario_spawn_type", "area_get_warp_node", "area_get_any_warp_node", "play_transition" ],
"src/engine/level_script.h": [ "area_create_warp_node" ],
"src/game/ingame_menu.h": [ "set_min_dialog_width", "set_dialog_override_pos", "reset_dialog_override_pos", "set_dialog_override_color", "reset_dialog_override_color", "set_menu_mode", "create_dialog_box", "create_dialog_box_with_var", "create_dialog_inverted_box", "create_dialog_box_with_response", "reset_dialog_render_state", "set_dialog_box_state", ],
"src/game/ingame_menu.h": [ "set_min_dialog_width", "set_dialog_override_pos", "reset_dialog_override_pos", "set_dialog_override_color", "reset_dialog_override_color", "set_menu_mode", "create_dialog_box", "create_dialog_box_with_var", "create_dialog_inverted_box", "create_dialog_box_with_response", "reset_dialog_render_state", "set_dialog_box_state", "handle_special_dialog_text" ],
"src/audio/seqplayer.h": [ "sequence_player_set_tempo", "sequence_player_set_tempo_acc", "sequence_player_set_transposition", "sequence_player_get_tempo", "sequence_player_get_tempo_acc", "sequence_player_get_transposition", "sequence_player_get_volume", "sequence_player_get_fade_volume", "sequence_player_get_mute_volume_scale" ],
"src/pc/network/sync_object.h": [ "sync_object_is_initialized", "sync_object_is_owned_locally", "sync_object_get_object" ],
}
@ -129,15 +129,16 @@ override_disallowed_functions = {
"src/game/camera.h": [ "update_camera", "init_camera", "stub_camera", "^reset_camera", "move_point_along_spline", "romhack_camera_init_settings", "romhack_camera_reset_settings" ],
"src/game/behavior_actions.h": [ "bhv_dust_smoke_loop", "bhv_init_room" ],
"src/pc/lua/utils/smlua_audio_utils.h": [ "smlua_audio_utils_override", "audio_custom_shutdown", "smlua_audio_custom_deinit", "audio_sample_destroy_pending_copies", "audio_custom_update_volume" ],
"src/pc/djui/djui_hud_utils.h": [ "djui_hud_render_texture_raw", "djui_hud_render_texture_tile_raw" ],
"src/pc/lua/utils/smlua_level_utils.h": [ "smlua_level_util_reset" ],
"src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown", "get_dialog_text_ascii", "smlua_text_utils_dialog_get_unmodified"],
"src/pc/lua/utils/smlua_text_utils.h": [ "smlua_text_utils_init", "smlua_text_utils_shutdown", "smlua_text_utils_dialog_get_unmodified"],
"src/pc/lua/utils/smlua_anim_utils.h": [ "smlua_anim_util_reset", "smlua_anim_util_register_animation" ],
"src/pc/lua/utils/smlua_gfx_utils.h": [ "gfx_allocate_internal", "vtx_allocate_internal", "gfx_get_length_no_sentinel" ],
"src/pc/network/lag_compensation.h": [ "lag_compensation_clear" ],
"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 +814,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 +871,8 @@ def build_call(function):
lfunc = 'lua_pushstring'
elif ftype == 'ByteString':
lfunc = 'smlua_push_bytestring'
elif ftype == 'LuaTable':
lfunc = 'smlua_push_lua_table'
elif translate_type_to_lot(ftype) == 'LOT_POINTER':
lvt = translate_type_to_lvt(ftype)
return ' smlua_push_pointer(L, %s, (void*)%s, NULL);\n' % (lvt, ccall)

View file

@ -89,13 +89,15 @@ override_field_invisible = {
"Mod": [ "files", "showedScriptWarning" ],
"Camera": [ "paletteEditorCapState" ],
"MarioState": [ "visibleToEnemies" ],
"NetworkPlayer": [ "gag", "moderator", "discordId" ],
"NetworkPlayer": [ "gag", "moderator", "discordId", "rxPacketHash", "rxSeqIds" ],
"GraphNode": [ "_guard1", "_guard2", "padding" ],
"GraphNodeRoot": ["unk15", "views"],
"GraphNodeMasterList": [ "listHeads", "listTails" ],
"FnGraphNode": [ "luaTokenIndex" ],
"Object": [ "firstSurface" ],
"Animation": [ "unusedBoneCount" ],
"ModAudio": [ "sound", "decoder", "buffer", "bufferSize", "sampleCopiesTail" ],
"Painting": [ "normalDisplayList", "textureMaps", "rippleDisplayList", "ripples" ],
"DialogEntry": [ "str" ],
"ModFsFile": [ "data", "capacity" ],
"ModFs": [ "files" ],
@ -112,9 +114,10 @@ override_field_immutable = {
"Character": [ "*" ],
"NetworkPlayer": [ "*" ],
"TextureInfo": [ "*" ],
"Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType", "numSurfaces" ],
"Object": ["oSyncID", "coopFlags", "oChainChompSegments", "oWigglerSegments", "oHauntedChairUnk100", "oTTCTreadmillBigSurface", "oTTCTreadmillSmallSurface", "bhvStackIndex", "respawnInfoType", "numSurfaces", "bhvStack" ],
"GlobalObjectAnimations": [ "*"],
"SpawnParticlesInfo": [ "model" ],
"WaterDropletParams": [ "model" ],
"MarioBodyState": [ "updateTorsoTime", "updateHeadPosTime", "animPartsPos", "currAnimPart" ],
"Area": [ "localAreaTimer", "nextSyncID", "objectSpawnInfos", "paintingWarpNodes", "warpNodes" ],
"Mod": [ "*" ],
@ -141,6 +144,7 @@ override_field_immutable = {
"DialogEntry": [ "unused", "linesPerBox", "leftOffset", "width", "str", "text", "replaced"],
"ModFsFile": [ "*" ],
"ModFs": [ "*" ],
"StaticObjectCollision": [ "*" ],
}
override_field_version_excludes = {
@ -321,6 +325,14 @@ def parse_struct(struct_str, sortFields = False):
field['identifier'] = field_id.strip()
field['field_str'] = field_str
# handle function members
if field['type'].startswith(cobject_function_identifier):
field_function = field['identifier']
field_type, field_id = field['type'].split()
field['type'] = field_type.strip()
field['identifier'] = field_id.strip('"').strip()
field['function'] = field_function.strip()
struct['fields'].append(field)
if identifier == 'Object':
@ -484,6 +496,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:
@ -492,6 +507,8 @@ def get_struct_field_info(struct, field):
size = int(array_size)
elif array_size.startswith("0x") and all(c in "0123456789abcdef" for c in array_size[2:]):
size = int(array_size, 16)
elif array_size != "":
size = array_size
else:
lvt, lot = 'LVT_???', "LOT_???" # array size not provided, so not supported
@ -506,6 +523,7 @@ def build_struct(struct):
# build up table and track column width
field_table = []
field_functions = []
for field in struct['fields']:
fid, ftype, fimmutable, lvt, lot, size = get_struct_field_info(struct, field)
@ -531,22 +549,40 @@ def build_struct(struct):
startStr += '#ifndef ' + override_field_version_excludes[fid] + '\n'
endStr += '\n#endif'
startStr += ' { '
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('offsetof(%s%s, %s), ' % (struct_str, name, field['identifier']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(%s)' % ftype )
row.append(endStr )
if ftype == cobject_function_identifier:
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('(size_t) FUNCTION__%s, ' % (field['function']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(const char *)' )
row.append(endStr )
field_functions.append(field['function'])
else:
row.append(startStr )
row.append('"%s", ' % fid )
row.append('%s, ' % lvt )
row.append('offsetof(%s%s, %s), ' % (struct_str, name, field['identifier']))
row.append('%s, ' % fimmutable )
row.append('%s, ' % lot )
row.append('%s, ' % size )
row.append('sizeof(%s)' % ftype )
row.append(endStr )
field_table.append(row)
field_table_str, field_count = table_to_string(field_table)
field_count_define = 'LUA_%s_FIELD_COUNT' % identifier_to_caps(sid)
struct_lot = 'LOT_%s' % sid.upper()
s = "#define %s $[STRUCTFIELDCOUNT]\n" % field_count_define
s = ''
if field_functions:
for field_function in field_functions:
s += 'static const char FUNCTION__%s[] = "%s";\n' % (field_function, field_function)
s += '\n'
s += "#define %s $[STRUCTFIELDCOUNT]\n" % field_count_define
s += "static struct LuaObjectField s%sFields[%s] = {\n" % (sid, field_count_define)
s += field_table_str
s += '};\n'
@ -646,10 +682,27 @@ 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:
sid = struct['identifier']
if sid in exclude_structs:
continue
s += '- [%s](#%s)\n' % (sid, sid)
global total_structs
total_structs += 1
@ -662,26 +715,30 @@ def doc_struct_field(struct, field):
sid = struct['identifier']
if sid in override_field_invisible:
if fid in override_field_invisible[sid]:
return ''
return '', False
if sid in override_field_deprecated:
if fid in override_field_deprecated[sid]:
return ''
return '', False
if '???' in lvt or '???' in lot:
return ''
return '', False
ftype, flink = translate_type_to_lua(ftype)
if ftype == cobject_function_identifier:
flink = doc_find_function_link(field['function'])
return '| %s | [`%s`](%s) |\n' % (fid, field['function'], flink), True
restrictions = ('', 'read-only')[fimmutable == 'true']
global total_fields
total_fields += 1
if flink:
return '| %s | [%s](%s) | %s |\n' % (fid, ftype, flink, restrictions)
return '| %s | [%s](%s) | %s |\n' % (fid, ftype, flink, restrictions), False
return '| %s | %s | %s |\n' % (fid, ftype, restrictions)
return '| %s | %s | %s |\n' % (fid, ftype, restrictions), False
def doc_struct_object_fields(struct):
@ -696,7 +753,8 @@ def doc_struct_object_fields(struct):
s += "| Field | Type | Access |\n"
s += "| ----- | ---- | ------ |\n"
s += doc_struct_field(struct, field)
line, _ = doc_struct_field(struct, field)
s += line
return s
@ -707,17 +765,27 @@ def doc_struct(struct):
s += "| Field | Type | Access |\n"
s += "| ----- | ---- | ------ |\n"
# build doc table
field_table = []
field_functions = ''
for field in struct['fields']:
if 'object_field' in field and field['object_field'] == True:
continue
s += doc_struct_field(struct, field)
line, isFunction = doc_struct_field(struct, field)
if isFunction:
field_functions += line
else:
s += line
if sid == 'Object':
s += doc_struct_object_fields(struct)
# functions
if field_functions:
s += '\n**Functions:**\n\n'
s += "| Name | Reference |\n"
s += "| ---- | --------- |\n"
s += field_functions
s += '\n[:arrow_up_small:](#)\n\n<br />\n'
return s
@ -740,6 +808,32 @@ def doc_structs(structs):
def_pointers = []
# HACK: Parse autogen/lua_definitions/functions.lua to find the function signature
function_signatures = {}
def get_function_signature(function):
if not function_signatures:
with open('autogen/lua_definitions/functions.lua') as f:
lines = f.readlines()
function_params = []
function_return = None
for line in lines:
if line.startswith('--- @param'):
function_params.append(line.split()[2:4])
elif line.startswith('--- @return'):
function_return = line.split()[2]
elif line.startswith('function'):
sig = 'fun('
sig += ', '.join(['%s: %s' % (param_name, param_type) for param_name, param_type in function_params])
sig += ')'
if function_return:
sig += ': %s' % (function_return)
function_name = line.replace('(', ' ').split()[1]
function_signatures[function_name] = sig
function_params.clear()
function_return = None
return function_signatures.get(function, 'function')
def def_struct(struct):
sid = struct['identifier']
@ -761,7 +855,12 @@ def def_struct(struct):
ftype, flink = translate_type_to_lua(ftype)
ftype = translate_to_def(ftype)
# try to get the function signature
if ftype == cobject_function_identifier:
ftype = get_function_signature(field['function'])
else:
ftype = translate_to_def(ftype)
if ftype.startswith('Pointer_') and ftype not in def_pointers:
def_pointers.append(ftype)

View file

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

View file

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

View file

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

View file

@ -3615,12 +3615,6 @@ function rotate_camera_around_walls(c, cPos, avoidYaw, yawRange)
-- ...
end
--- @param pg PlayerGeometry
--- Finds the floor and ceiling directly above and below Mario's position. Updates Mario's geometry information for camera calculations
function find_mario_floor_and_ceil(pg)
-- ...
end
--- @param cutscene integer
--- @return integer
--- Starts a cutscene focused on an object without requiring focus to remain locked. This is useful for dynamic events where the camera adjusts freely
@ -3914,8 +3908,14 @@ function djui_hud_get_raw_mouse_y()
-- ...
end
--- @return boolean
--- Checks if the cursor is locked to the window
function djui_hud_is_mouse_locked()
-- ...
end
--- @param locked boolean
--- Sets if the cursor is hidden and constrainted to the window
--- Locks (or unlocks) the cursor to the window
function djui_hud_set_mouse_locked(locked)
-- ...
end
@ -3954,12 +3954,12 @@ end
--- @param y number
--- @param width number
--- @param height number
--- Sets the viewport to the specified position and size, this will resize
--- Sets the viewport to the specified position and size, this will resize any subsequent DJUI graphics
function djui_hud_set_viewport(x, y, width, height)
-- ...
end
--- put the description here
--- Resets the viewport to a fullscreen state
function djui_hud_reset_viewport()
-- ...
end
@ -3968,12 +3968,12 @@ end
--- @param y number
--- @param width number
--- @param height number
--- put the description here
--- Sets the scissor rectangle to the specified position and size, this will cut off any subsequent DJUI graphics not within the rectangle
function djui_hud_set_scissor(x, y, width, height)
-- ...
end
--- put the description here
--- Resets the scissor rectangle to a fullscreen state
function djui_hud_reset_scissor()
-- ...
end
@ -4444,6 +4444,12 @@ function set_menu_mode(mode)
-- ...
end
--- @param dialogID integer
--- The internal function used by SM64 which plays a tune whenever boss, KtQ, etc dialog is read.
function handle_special_dialog_text(dialogID)
-- ...
end
--- @param width integer
--- Dialog box customization: Sets the minimum width for a dialog box
function set_min_dialog_width(width)
@ -4987,6 +4993,12 @@ function level_control_timer_running()
-- ...
end
--- @return boolean
--- Checks if the start button has been pressed as well as some other conditions for opening the pause menu depending on if pause anywhere is enabled
function pressed_pause()
-- ...
end
--- @param arg integer
--- @param color integer
--- Fades into a special warp with `arg` and using `color`
@ -6393,17 +6405,6 @@ function mario_bonk_reflection(m, negateSpeed)
-- ...
end
--- @param data BullyCollisionData
--- @param posX number
--- @param posZ number
--- @param forwardVel number
--- @param yaw integer
--- @param conversionRatio number
--- @param radius number
function init_bully_collision_data(data, posX, posZ, forwardVel, yaw, conversionRatio, radius)
-- ...
end
--- @param m MarioState
--- @param sinkingSpeed number
--- @return integer
@ -6443,14 +6444,14 @@ end
--- @param m MarioState
--- @return integer
--- Performs a full Mario stationary physics step (4 substeps) and returns an `GROUND_STEP_*` result
--- Performs a full Mario stationary physics step (4 substeps) and returns a `GROUND_STEP_*` result
function stationary_ground_step(m)
-- ...
end
--- @param m MarioState
--- @return integer
--- Performs a full Mario ground physics step (4 substeps) and returns an `GROUND_STEP_*` result
--- Performs a full Mario ground physics step (4 substeps) and returns a `GROUND_STEP_*` result
function perform_ground_step(m)
-- ...
end
@ -7435,25 +7436,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 +7496,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 +7622,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 +7653,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 +7726,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
@ -8802,13 +8827,6 @@ function cur_obj_init_animation_with_accel_and_sound(animIndex, accel)
-- ...
end
--- @param obj Object
--- @param animations AnimationTable
--- @param animIndex integer
function obj_init_animation_with_sound(obj, animations, animIndex)
-- ...
end
--- @param obj Object
function cur_obj_enable_rendering_and_become_tangible(obj)
-- ...
@ -9990,6 +10008,11 @@ function save_file_is_cannon_unlocked(fileIndex, courseIndex)
-- ...
end
--- Unlocks the cannon in the current course
function save_file_set_cannon_unlocked()
-- ...
end
--- @param capPos Vec3s
--- @return integer
--- Retrieves the current position of Mario's cap, if it is on the ground in the current level and area. The position is stored in the provided `capPos` parameter. Useful for tracking the cap's location after it has been dropped or lost
@ -10005,7 +10028,7 @@ end
--- @param player integer
--- @return integer
--- Gets the tempo of `player`
--- Gets the `tempo` of `player`
function sequence_player_get_tempo(player)
-- ...
end
@ -10019,7 +10042,7 @@ end
--- @param player integer
--- @return integer
--- Gets the tempoAcc (tempo accumulation) of `player`
--- Gets the `tempoAcc` (tempo accumulation) of `player`
function sequence_player_get_tempo_acc(player)
-- ...
end
@ -10033,7 +10056,7 @@ end
--- @param player integer
--- @return integer
--- Gets the transposition (pitch) of `player`
--- Gets the `transposition` (pitch) of `player`
function sequence_player_get_transposition(player)
-- ...
end
@ -11069,6 +11092,12 @@ function djui_get_playerlist_page_index()
-- ...
end
--- @return boolean
--- Checks if the DJUI chatbox is open
function djui_is_chatbox_open()
-- ...
end
--- @return DjuiFontType
--- Gets the DJUI menu font
function djui_menu_get_font()
@ -11250,6 +11279,28 @@ function is_game_paused()
-- ...
end
--- @return boolean
--- Gets if the pause menu elements are hidden, useful for creating custom pause menus
function is_pause_menu_hidden()
-- ...
end
--- @param hidden boolean
--- Sets if the pause menu elements are hidden, useful for creating custom pause menus
function set_pause_menu_hidden(hidden)
-- ...
end
--- Pauses the game
function game_pause()
-- ...
end
--- Unpauses the game
function game_unpause()
-- ...
end
--- @return boolean
--- Checks if a screen transition is playing
function is_transition_playing()
@ -11529,7 +11580,8 @@ function geo_get_current_held_object()
end
--- @param tex Pointer_Texture
--- Converts a texture's pixels to a Lua table. Returns nil if failed. Otherwise, returns a table as a pure memory buffer. Supports rgba16 and rgba32 textures
--- @return table
--- Converts a texture's pixels to a Lua table. Returns nil if failed. Otherwise, returns a 1-indexed table of RGBA pixels
function texture_to_lua_table(tex)
-- ...
end
@ -11811,6 +11863,14 @@ function obj_get_temp_spawn_particles_info(modelId)
-- ...
end
--- @param modelId ModelExtendedId
--- @param behaviorId BehaviorId
--- @return WaterDropletParams
--- Returns a temporary water droplet params pointer with its model and behavior loaded in from `modelId` and `behaviorId`
function obj_get_temp_water_droplet_params(modelId, behaviorId)
-- ...
end
--- @return ObjectHitbox
--- Returns a temporary object hitbox pointer
function get_temp_object_hitbox()
@ -12295,6 +12355,27 @@ function load_object_collision_model()
-- ...
end
--- @return StaticObjectCollision
--- Loads the object's collision data into static collision. You may run this only once to capture the object's collision at that frame.
function load_static_object_collision()
-- ...
end
--- @param col StaticObjectCollision
--- @param tangible boolean
--- Toggles a collection of static object surfaces
function toggle_static_object_collision(col, tangible)
-- ...
end
--- @param col StaticObjectCollision
--- @param index integer
--- @return Surface
--- Gets a surface corresponding to `index` from the static object collision
function get_static_object_surface(col, index)
-- ...
end
--- @param o Object
--- @param index integer
--- @return Surface

View file

@ -300,62 +300,6 @@ function get_texture_info(textureName)
-- ...
end
--- @param texInfo TextureInfo The texture
--- @param x number Where the texture is horizontally (left anchored)
--- @param y number Where the texture is vertically (top anchored)
--- @param scaleW number The scaled width of the texture
--- @param scaleH number The scaled height of the texture
--- Renders a texture to the screen
function djui_hud_render_texture(texInfo, x, y, scaleW, scaleH)
-- ...
end
--- @param texInfo TextureInfo The texture
--- @param x number Where the texture is horizontally (left anchored)
--- @param y number Where the texture is vertically (top anchored)
--- @param scaleW number The scaled width of the texture
--- @param scaleH number The scaled height of the texture
--- @param tileX number Where the tile is horizontally (left anchored)
--- @param tileY number Where the tile is vertically (top anchored)
--- @param tileW number The width of the tile
--- @param tileH number The height of the tile
--- Renders a tile of a texture to the screen
function djui_hud_render_texture_tile(texInfo, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH)
-- ...
end
--- @param texInfo TextureInfo The texture
--- @param prevX number Where the texture previously was horizontally (left anchored)
--- @param prevY number Where the texture previously was vertically (top anchored)
--- @param prevScaleW number The previous scaled width of the texture
--- @param prevScaleH number The previous scaled height of the texture
--- @param x number Where the texture is horizontally (left anchored)
--- @param y number Where the texture is vertically (top anchored)
--- @param scaleW number The scaled width of the texture
--- @param scaleH number The scaled height of the texture
--- Renders an interpolated texture to the screen
function djui_hud_render_texture_interpolated(texInfo, prevX, prevY, prevScaleW, prevScaleH, x, y, scaleW, scaleH)
-- ...
end
--- @param texInfo TextureInfo The texture
--- @param prevX number Where the texture previously was horizontally (left anchored)
--- @param prevY number Where the texture previously was vertically (top anchored)
--- @param prevScaleW number The previous scaled width of the texture
--- @param prevScaleH number The previous scaled height of the texture
--- @param x number Where the texture is horizontally (left anchored)
--- @param y number Where the texture is vertically (top anchored)
--- @param scaleW number The scaled width of the texture
--- @param scaleH number The scaled height of the texture
--- @param tileX number Where the tile is horizontally (left anchored)
--- @param tileY number Where the tile is vertically (top anchored)
--- @param tileW number The width of the tile
--- @param tileH number The height of the tile
--- Renders an interpolated tile of a texture to the screen
function djui_hud_render_texture_tile_interpolated(texInfo, prevX, prevY, prevScaleW, prevScaleH, x, y, scaleW, scaleH, tileX, tileY, tileW, tileH)
-- ...
end
--- @param textureName string The name of the texture
--- @param overrideTexInfo TextureInfo The texture to override with
--- Overrides a texture with a custom `TextureInfo`

View file

@ -25,9 +25,6 @@
--- @field public valuesLength integer
--- @field public indexLength integer
--- @class AnimationTable
--- @field public count integer
--- @class Area
--- @field public index integer
--- @field public flags integer
@ -203,14 +200,6 @@
--- @field public dialogs BehaviorDialogs
--- @field public trajectories BehaviorTrajectories
--- @class BullyCollisionData
--- @field public conversionRatio number
--- @field public radius number
--- @field public posX number
--- @field public posZ number
--- @field public velX number
--- @field public velZ number
--- @class Camera
--- @field public mode integer
--- @field public defMode integer
@ -228,36 +217,6 @@
--- @field public areaCenY number
--- @field public mtx Mat4
--- @class CameraFOVStatus
--- @field public fovFunc integer
--- @field public fov number
--- @field public fovOffset number
--- @field public unusedIsSleeping integer
--- @field public shakeAmplitude number
--- @field public shakePhase integer
--- @field public shakeSpeed integer
--- @field public decay integer
--- @class CameraOverride
--- @field public value integer
--- @field public override boolean
--- @class CameraStoredInfo
--- @field public pos Vec3f
--- @field public focus Vec3f
--- @field public panDist number
--- @field public cannonYOffset number
--- @class CameraTrigger
--- @field public area integer
--- @field public centerX integer
--- @field public centerY integer
--- @field public centerZ integer
--- @field public boundsX integer
--- @field public boundsY integer
--- @field public boundsZ integer
--- @field public boundsYaw integer
--- @class ChainSegment
--- @field public posX number
--- @field public posY number
@ -494,6 +453,7 @@
--- @field public animReturnFromStarDance integer
--- @field public animForwardSpinningFlip integer
--- @field public animTripleJumpFly integer
--- @field public anims integer[]
--- @field public soundFreqScale number
--- @field public soundYahWahHoo integer
--- @field public soundHoohoo integer
@ -539,6 +499,7 @@
--- @field public soundImaTired integer
--- @field public soundLetsAGo integer
--- @field public soundOkeyDokey integer
--- @field public sounds integer[]
--- @class Controller
--- @field public port integer
@ -567,21 +528,6 @@
--- @field public modIndex integer
--- @field public next CustomLevelInfo
--- @class Cutscene
--- @field public duration integer
--- @class CutsceneSplinePoint
--- @field public index integer
--- @field public speed integer
--- @field public point Vec3s
--- @class CutsceneVariable
--- @field public unused1 integer
--- @field public point Vec3f
--- @field public unusedPoint Vec3f
--- @field public angle Vec3s
--- @field public unused2 integer
--- @class DateTime
--- @field public year integer
--- @field public month integer
@ -651,13 +597,6 @@
--- @field public fov number
--- @field public offset Vec3f
--- @class FloorGeometry
--- @field public unused number[]
--- @field public normalX number
--- @field public normalY number
--- @field public normalZ number
--- @field public originOffset number
--- @class FnGraphNode
--- @field public node GraphNode
@ -1015,19 +954,6 @@
--- @field public translation Vec3s
--- @field public rotation Vec3s
--- @class GraphNode_802A45E4
--- @field public unk18 integer
--- @field public unk1A integer
--- @field public unk1C integer
--- @field public unk1E integer
--- @field public unk20 integer
--- @field public unk22 integer
--- @class HandheldShakePoint
--- @field public index integer
--- @field public pad integer
--- @field public point Vec3s
--- @class HudUtilsRotation
--- @field public rotation number
--- @field public rotationDiff number
@ -1139,13 +1065,6 @@
--- @field public floorNormalMinY number
--- @field public ceilNormalMaxY number
--- @class LinearTransitionPoint
--- @field public focus Vec3f
--- @field public pos Vec3f
--- @field public dist number
--- @field public pitch integer
--- @field public yaw integer
--- @class MarioAnimation
--- @field public currentAnimAddr Pointer_integer
--- @field public targetAnim Animation
@ -1165,6 +1084,7 @@
--- @field public headPos Vec3f
--- @field public torsoPos Vec3f
--- @field public heldObjLastPosition Vec3f
--- @field public animPartsPos Vec3f[]
--- @field public currAnimPart integer
--- @field public updateTorsoTime integer
--- @field public updateHeadPosTime integer
@ -1277,33 +1197,31 @@
--- @field public renderBehindHud boolean
--- @field public pausable boolean
--- @field public ignoreScriptWarnings boolean
--- @field public size integer
--- @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
--- @class ModAudioSampleCopies
--- @field public next ModAudioSampleCopies
--- @field public prev ModAudioSampleCopies
--- @field public parent ModAudio
--- @class ModFile
--- @field public relativePath string
--- @field public modifiedTimestamp integer
--- @field public isLoadedLuaModule boolean
--- @field public wroteBytes integer
--- @field public dataHash integer[]
--- @field public cachedPath string
--- @class ModFs
--- @field public mod Mod
--- @field public modPath string
--- @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,14 +1230,25 @@
--- @field public offset integer
--- @field public isText boolean
--- @field public isPublic boolean
--- @class ModeTransitionInfo
--- @field public newMode integer
--- @field public lastMode integer
--- @field public max integer
--- @field public frame integer
--- @field public transitionStart LinearTransitionPoint
--- @field public transitionEnd LinearTransitionPoint
--- @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 NametagsSettings
--- @field public showHealth boolean
@ -1369,6 +1298,7 @@
--- @field public collisionData Pointer_Collision
--- @field public behavior Pointer_BehaviorScript
--- @field public curBhvCommand Pointer_BehaviorScript
--- @field public bhvStack integer[]
--- @field public bhvStackIndex integer
--- @field public bhvDelayTimer integer
--- @field public activeFlags integer
@ -2144,10 +2074,6 @@
--- @field public object Object
--- @field public next ObjectWarpNode
--- @class OffsetSizePair
--- @field public offset integer
--- @field public size integer
--- @class Painting
--- @field public id integer
--- @field public imageCount integer
@ -2176,10 +2102,9 @@
--- @field public rippleTimer number
--- @field public rippleX number
--- @field public rippleY number
--- @field public normalDisplayList Pointer_Gfx
--- @field public textureArray Pointer_Texture[]
--- @field public textureWidth integer
--- @field public textureHeight integer
--- @field public rippleDisplayList Pointer_Gfx
--- @field public rippleTrigger integer
--- @field public alpha integer
--- @field public marioWasUnder integer
@ -2187,10 +2112,6 @@
--- @field public marioWentUnder integer
--- @field public size number
--- @class PaintingMeshVertex
--- @field public pos integer[]
--- @field public norm integer[]
--- @class PaintingValues
--- @field public cotmc_painting Painting
--- @field public bob_painting Painting
@ -2209,12 +2130,6 @@
--- @field public thi_huge_painting Painting
--- @field public ttm_slide_painting Painting
--- @class ParallelTrackingPoint
--- @field public startOfPath integer
--- @field public pos Vec3f
--- @field public distThresh number
--- @field public zoom number
--- @class PlayerCameraState
--- @field public action integer
--- @field public pos Vec3f
@ -2224,22 +2139,8 @@
--- @field public cameraEvent integer
--- @field public usedObj Object
--- @class PlayerGeometry
--- @field public currFloor Surface
--- @field public currFloorHeight number
--- @field public currFloorType integer
--- @field public currCeil Surface
--- @field public currCeilType integer
--- @field public currCeilHeight number
--- @field public prevFloor Surface
--- @field public prevFloorHeight number
--- @field public prevFloorType integer
--- @field public prevCeil Surface
--- @field public prevCeilHeight number
--- @field public prevCeilType integer
--- @field public waterHeight number
--- @class PlayerPalette
--- @field public parts Color[]
--- @class RayIntersectionInfo
--- @field public surface Surface
@ -2272,12 +2173,6 @@
--- @field public maxPlayers integer
--- @field public pauseAnywhere integer
--- @class SoundState
--- @field public playSound integer
--- @field public animFrame1 integer
--- @field public animFrame2 integer
--- @field public soundMagic integer
--- @class SpawnInfo
--- @field public startPos Vec3s
--- @field public startAngle Vec3s
@ -2338,6 +2233,10 @@
--- @field public dialog5 integer
--- @field public dialog6 integer
--- @class StaticObjectCollision
--- @field public index integer
--- @field public length integer
--- @class Surface
--- @field public type integer
--- @field public flags integer
@ -2361,18 +2260,8 @@
--- @field public name string
--- @field public width integer
--- @field public height integer
--- @field public bitSize integer
--- @class TransitionInfo
--- @field public posPitch integer
--- @field public posYaw integer
--- @field public posDist number
--- @field public focPitch integer
--- @field public focYaw integer
--- @field public focDist number
--- @field public framesLeft integer
--- @field public marioPos Vec3f
--- @field public pad integer
--- @field public format integer
--- @field public size integer
--- @class Vtx
--- @field public x number
@ -2389,10 +2278,6 @@
--- @field public nz integer
--- @field public a integer
--- @class Vtx_Interp
--- @field public ob number[]
--- @field public n string
--- @class WallCollisionData
--- @field public x number
--- @field public y number
@ -2411,25 +2296,6 @@
--- @field public destArea integer
--- @field public destNode integer
--- @class WarpTransition
--- @field public isActive integer
--- @field public type integer
--- @field public time integer
--- @field public pauseRendering integer
--- @field public data WarpTransitionData
--- @class WarpTransitionData
--- @field public red integer
--- @field public green integer
--- @field public blue integer
--- @field public startTexRadius integer
--- @field public endTexRadius integer
--- @field public startTexX integer
--- @field public startTexY integer
--- @field public endTexX integer
--- @field public endTexY integer
--- @field public texTimer integer
--- @class WaterDropletParams
--- @field public flags integer
--- @field public model integer
@ -2528,4 +2394,5 @@
--- @alias Pointer_Mat4 Mat4
--- @alias Pointer_Vec4s Vec4s
--- @alias Pointer_BehaviorScript BehaviorScript
--- @alias Pointer_Texture[] Texture[]
--- @alias Pointer_Texture Texture

View file

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

View file

@ -37,21 +37,22 @@ 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);
void dynos_texture_override_reset(const char* textureName);
u8 *dynos_texture_convert_to_rgba32(const Texture *tex, u32 width, u32 height, u8 fmt, u8 siz);
// -- movtexqcs -- //
void dynos_movtexqc_register(const char* name, s16 level, s16 area, s16 type);

View file

@ -653,15 +653,6 @@ struct DynosOption : NoCopy {
};
typedef bool (*DynosLoopFunc)(DynosOption *, void *);
struct BuiltinTexInfo {
const char* identifier;
const void* pointer;
const char* path;
s32 width;
s32 height;
s32 bitSize;
};
struct LvlCmd {
u8 mType;
u8 mSize;
@ -866,8 +857,8 @@ const char * DynOS_Builtin_Anim_GetFromData(const Animation *aData);
const Texture* DynOS_Builtin_Tex_GetFromName(const char* aDataName);
const char* DynOS_Builtin_Tex_GetFromData(const Texture* aData);
const char* DynOS_Builtin_Tex_GetNameFromFileName(const char* aDataName);
const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromName(const char* aDataName);
const struct BuiltinTexInfo* DynOS_Builtin_Tex_GetInfoFromData(const Texture* aData);
const struct TextureInfo* DynOS_Builtin_Tex_GetInfoFromName(const char* aDataName);
const struct TextureInfo* DynOS_Builtin_Tex_GetInfoFromData(const Texture* aData);
const void* DynOS_Builtin_Func_GetFromName(const char* aDataName, u8 aFuncType);
const void* DynOS_Builtin_Func_GetFromIndex(s32 aIndex, u8 aFuncType);
const char * DynOS_Builtin_Func_GetNameFromIndex(s32 aIndex, u8 aFuncType);
@ -897,7 +888,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 +916,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 +954,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();

View file

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

View file

@ -405,6 +405,7 @@ s64 DynOS_Gfx_ParseGfxConstants(const String& _Arg, bool* found) {
gfx_constant(G_LIGHT_MAP_EXT);
gfx_constant(G_LIGHTING_ENGINE_EXT);
gfx_constant(G_PACKED_NORMALS_EXT);
gfx_constant(G_CULL_INVERT_EXT);
gfx_constant(G_FRESNEL_COLOR_EXT);
gfx_constant(G_FRESNEL_ALPHA_EXT);
@ -1234,12 +1235,36 @@ struct GfxParamInfo {
const GfxParamType *types;
};
// Allow whitespaces before and after the command symbol name
static const char *ExtractGfxSymbol(const char *command, size_t *symbolLength) {
const char *symbol = NULL;
*symbolLength = 0;
for (; *command != 0; command++) {
if ((u8) *command <= (u8) ' ' || *command == '(') {
if (symbol != NULL) {
return symbol;
}
} else {
if (symbol == NULL) {
symbol = command;
}
(*symbolLength)++;
}
}
return symbol;
}
static const struct GfxParamInfo *GetGfxParamInfo(const char *command) {
#define define_gfx_symbol(symb, params, addPtr, ...) \
static const GfxParamType types_##symb[] = { __VA_ARGS__ }; \
static struct GfxParamInfo info_##symb = { .count = params, .types = types_##symb }; \
static_assert(sizeof(types_##symb) == params, "Parameter count does not match for gfx command."); \
if (!strncmp(#symb, command, strlen(#symb))) { return &info_##symb; }
size_t symbolLength = 0;
const char *symbol = ExtractGfxSymbol(command, &symbolLength);
if (symbol == NULL) { return NULL; }
#define define_gfx_symbol(symb, params, addPtr, ...) \
{ \
static const GfxParamType types_##symb[] = { __VA_ARGS__ }; \
static struct GfxParamInfo info_##symb = { .count = params, .types = types_##symb }; \
static_assert(sizeof(types_##symb) == params, "Parameter count does not match for gfx symbol: " #symb); \
if (symbolLength == sizeof(#symb) - 1 && !memcmp(symbol, #symb, symbolLength)) { return &info_##symb; } \
}
#define define_gfx_symbol_manual(...) define_gfx_symbol(__VA_ARGS__)
#include "gfx_symbols.h"
#undef define_gfx_symbol

View file

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

View file

@ -115,8 +115,8 @@ void dynos_actor_override(struct Object* obj, void** aSharedChild) {
DynOS_Actor_Override(obj, aSharedChild);
}
void dynos_add_actor_custom(s32 modIndex, s32 modFileIndex, const char *filePath, const char* geoName) {
DynOS_Actor_AddCustom(modIndex, modFileIndex, filePath, geoName);
bool dynos_add_actor_custom(s32 modIndex, s32 modFileIndex, const char *filePath, const char* geoName) {
return DynOS_Actor_AddCustom(modIndex, modFileIndex, filePath, geoName);
}
const void* dynos_geolayout_get(const char *name) {
@ -133,8 +133,8 @@ void dynos_actor_register_modified_graph_node(struct GraphNode *node) {
// -- collisions -- //
void dynos_add_collision(const char *filePath, const char* collisionName) {
DynOS_Col_Activate(filePath, collisionName);
bool dynos_add_collision(const char *filePath, const char* collisionName) {
return DynOS_Col_Activate(filePath, collisionName);
}
Collision* dynos_collision_get(const char* collisionName) {
@ -143,9 +143,9 @@ Collision* dynos_collision_get(const char* collisionName) {
// -- textures -- //
void dynos_add_texture(const char *filePath, const char* textureName) {
bool dynos_add_texture(const char *filePath, const char* textureName) {
SysPath _FilePath = filePath;
DynOS_Tex_AddCustom(_FilePath, textureName);
return DynOS_Tex_AddCustom(_FilePath, textureName);
}
bool dynos_texture_get(const char* textureName, struct TextureInfo* outTextureInfo) {
@ -164,6 +164,16 @@ void dynos_texture_override_reset(const char* textureName) {
DynOS_Tex_Override_Reset(textureName);
}
u8 *dynos_texture_convert_to_rgba32(const Texture *tex, u32 width, u32 height, u8 fmt, u8 siz) {
switch (siz) {
case G_IM_SIZ_4b: return DynOS_Tex_ConvertToRGBA32(tex, (width * height) / 2, fmt, siz, NULL);
case G_IM_SIZ_8b: return DynOS_Tex_ConvertToRGBA32(tex, width * height, fmt, siz, NULL);
case G_IM_SIZ_16b: return DynOS_Tex_ConvertToRGBA32(tex, width * height * 2, fmt, siz, NULL);
case G_IM_SIZ_32b: return DynOS_Tex_ConvertToRGBA32(tex, width * height * 4, fmt, siz, NULL);
}
return NULL;
}
// -- movtexqcs -- //
void dynos_movtexqc_register(const char* name, s16 level, s16 area, s16 type) {

View file

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

File diff suppressed because it is too large Load diff

View file

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

View file

@ -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,19 +445,16 @@ 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) { \
/* translate bit size */ \
switch (_Data->mRawSize) { \
case G_IM_SIZ_8b: aOutTexInfo->bitSize = 8; break; \
case G_IM_SIZ_16b: aOutTexInfo->bitSize = 16; break; \
case G_IM_SIZ_32b: aOutTexInfo->bitSize = 32; break; \
default: return false; \
} \
aOutTexInfo->width = _Data->mRawWidth; \
aOutTexInfo->height = _Data->mRawHeight; \
aOutTexInfo->format = _Data->mRawFormat; \
aOutTexInfo->size = _Data->mRawSize; \
aOutTexInfo->texture = _Data->mRawData.begin(); \
aOutTexInfo->name = texName; \
}
@ -488,8 +486,15 @@ 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);
const struct TextureInfo* info = DynOS_Builtin_Tex_GetInfoFromName(aTexName);
if (!info) {
for (DataNode<TexData>* _Node : DynosValidTextures()) { // check valid textures
if (_Node->mName == aTexName) {
@ -500,11 +505,7 @@ bool DynOS_Tex_Get(const char* aTexName, struct TextureInfo* aOutTexInfo) {
}
return false;
}
aOutTexInfo->bitSize = info->bitSize;
aOutTexInfo->width = info->width;
aOutTexInfo->height = info->height;
aOutTexInfo->texture = (Texture*)info->pointer;
aOutTexInfo->name = aTexName;
*aOutTexInfo = *info;
return true;
}
@ -517,13 +518,9 @@ bool DynOS_Tex_GetFromData(const Texture *aTex, struct TextureInfo* aOutTexInfo)
}
// check builtin textures
const struct BuiltinTexInfo* info = DynOS_Builtin_Tex_GetInfoFromData(aTex);
const struct TextureInfo* info = DynOS_Builtin_Tex_GetInfoFromData(aTex);
if (info) {
aOutTexInfo->bitSize = info->bitSize;
aOutTexInfo->width = info->width;
aOutTexInfo->height = info->height;
aOutTexInfo->texture = (Texture*)info->pointer;
aOutTexInfo->name = info->identifier;
*aOutTexInfo = *info;
return true;
}

View file

@ -250,13 +250,10 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
}
// Set music
if (sDynosWarpNodeNum == -1 || (sWarpDest.type != WARP_TYPE_SAME_AREA && sWarpDest.type != WARP_TYPE_NOT_WARPING)) {
if ((sWarpDest.type != WARP_TYPE_SAME_AREA && sWarpDest.type != WARP_TYPE_NOT_WARPING)) {
if (gCurrentArea != NULL) {
set_background_music(gCurrentArea->musicParam, gCurrentArea->musicParam2, 0);
}
if (gMarioState->flags & MARIO_METAL_CAP) play_cap_music(SEQUENCE_ARGS(4, gLevelValues.metalCapSequence));
if (gMarioState->flags & MARIO_VANISH_CAP) play_cap_music(SEQUENCE_ARGS(4, gLevelValues.vanishCapSequence));
if (gMarioState->flags & MARIO_WING_CAP) play_cap_music(SEQUENCE_ARGS(4, gLevelValues.wingCapSequence));
if (gCurrLevelNum == LEVEL_BOWSER_1 ||
gCurrLevelNum == LEVEL_BOWSER_2 ||
gCurrLevelNum == LEVEL_BOWSER_3) {
@ -264,6 +261,11 @@ static void *DynOS_Warp_UpdateWarp(void *aCmd, bool aIsLevelInitDone) {
}
}
// Enable power-up cap music
if (gMarioState->flags & MARIO_METAL_CAP) play_cap_music(SEQUENCE_ARGS(4, gLevelValues.metalCapSequence));
if (gMarioState->flags & MARIO_VANISH_CAP) play_cap_music(SEQUENCE_ARGS(4, gLevelValues.vanishCapSequence));
if (gMarioState->flags & MARIO_WING_CAP) play_cap_music(SEQUENCE_ARGS(4, gLevelValues.wingCapSequence));
// lua hooks
smlua_call_event_hooks(HOOK_ON_WARP, sBackupWarpDest.type, sDynosWarpLevelNum, sDynosWarpAreaNum, sDynosWarpNodeNum, sBackupWarpDest.arg);

View file

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

View file

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

View file

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

View file

@ -2121,29 +2121,6 @@ Rotates the camera to avoid walls or other obstructions. Ensures clear visibilit
<br />
## [find_mario_floor_and_ceil](#find_mario_floor_and_ceil)
### Description
Finds the floor and ceiling directly above and below Mario's position. Updates Mario's geometry information for camera calculations
### Lua Example
`find_mario_floor_and_ceil(pg)`
### Parameters
| Field | Type |
| ----- | ---- |
| pg | [PlayerGeometry](structs.md#PlayerGeometry) |
### Returns
- None
### C Prototype
`void find_mario_floor_and_ceil(struct PlayerGeometry *pg);`
[:arrow_up_small:](#)
<br />
## [start_object_cutscene_without_focus](#start_object_cutscene_without_focus)
### Description
@ -3140,10 +3117,31 @@ Returns the y coordinate of the mouse relative to the screen
<br />
## [djui_hud_is_mouse_locked](#djui_hud_is_mouse_locked)
### Description
Checks if the cursor is locked to the window
### Lua Example
`local booleanValue = djui_hud_is_mouse_locked()`
### Parameters
- None
### Returns
- `boolean`
### C Prototype
`bool djui_hud_is_mouse_locked(void);`
[:arrow_up_small:](#)
<br />
## [djui_hud_set_mouse_locked](#djui_hud_set_mouse_locked)
### Description
Sets if the cursor is hidden and constrainted to the window
Locks (or unlocks) the cursor to the window
### Lua Example
`djui_hud_set_mouse_locked(locked)`
@ -3271,7 +3269,7 @@ Returns the amount scrolled vertically (-down/up+)
## [djui_hud_set_viewport](#djui_hud_set_viewport)
### Description
Sets the viewport to the specified position and size, this will resize
Sets the viewport to the specified position and size, this will resize any subsequent DJUI graphics
### Lua Example
`djui_hud_set_viewport(x, y, width, height)`
@ -3297,7 +3295,7 @@ Sets the viewport to the specified position and size, this will resize
## [djui_hud_reset_viewport](#djui_hud_reset_viewport)
### Description
put the description here
Resets the viewport to a fullscreen state
### Lua Example
`djui_hud_reset_viewport()`
@ -3318,7 +3316,7 @@ put the description here
## [djui_hud_set_scissor](#djui_hud_set_scissor)
### Description
put the description here
Sets the scissor rectangle to the specified position and size, this will cut off any subsequent DJUI graphics not within the rectangle
### Lua Example
`djui_hud_set_scissor(x, y, width, height)`
@ -3344,7 +3342,7 @@ put the description here
## [djui_hud_reset_scissor](#djui_hud_reset_scissor)
### Description
put the description here
Resets the scissor rectangle to a fullscreen state
### Lua Example
`djui_hud_reset_scissor()`
@ -4933,6 +4931,29 @@ Sets the in-game menu state. 0-1 is the courses box with the castle secret stars
<br />
## [handle_special_dialog_text](#handle_special_dialog_text)
### Description
The internal function used by SM64 which plays a tune whenever boss, KtQ, etc dialog is read.
### Lua Example
`handle_special_dialog_text(dialogID)`
### Parameters
| Field | Type |
| ----- | ---- |
| dialogID | `integer` |
### Returns
- None
### C Prototype
`void handle_special_dialog_text(s32 dialogID);`
[:arrow_up_small:](#)
<br />
## [set_min_dialog_width](#set_min_dialog_width)
### Description
@ -6586,6 +6607,27 @@ Returns if the level timer is running
<br />
## [pressed_pause](#pressed_pause)
### Description
Checks if the start button has been pressed as well as some other conditions for opening the pause menu depending on if pause anywhere is enabled
### Lua Example
`local booleanValue = pressed_pause()`
### Parameters
- None
### Returns
- `boolean`
### C Prototype
`bool pressed_pause(void);`
[:arrow_up_small:](#)
<br />
## [fade_into_special_warp](#fade_into_special_warp)
### Description
@ -6746,561 +6788,6 @@ Sets the level number and handles the act select screen. `param` is used for ove
[:arrow_up_small:](#)
<br />
---
# functions from lighting_engine.h
<br />
## [le_is_enabled](#le_is_enabled)
### Description
Gets whether the lighting engine has been enabled or not. It becomes enabled once a light is added or the ambient color is set
### Lua Example
`local booleanValue = le_is_enabled()`
### Parameters
- None
### Returns
- `boolean`
### C Prototype
`bool le_is_enabled(void);`
[:arrow_up_small:](#)
<br />
## [le_set_mode](#le_set_mode)
### Description
Sets the lighting engine mode to `mode`
### Lua Example
`le_set_mode(mode)`
### Parameters
| Field | Type |
| ----- | ---- |
| mode | [enum LEMode](constants.md#enum-LEMode) |
### Returns
- None
### C Prototype
`void le_set_mode(enum LEMode mode);`
[:arrow_up_small:](#)
<br />
## [le_get_mode](#le_get_mode)
### Description
Gets the lighting engine mode
### Lua Example
`local enumValue = le_get_mode()`
### Parameters
- None
### Returns
[enum LEMode](constants.md#enum-LEMode)
### C Prototype
`enum LEMode le_get_mode(void);`
[:arrow_up_small:](#)
<br />
## [le_set_tone_mapping](#le_set_tone_mapping)
### Description
Sets the lighting engine's tone mapping mode to `toneMapping`
### Lua Example
`le_set_tone_mapping(toneMapping)`
### Parameters
| Field | Type |
| ----- | ---- |
| toneMapping | [enum LEToneMapping](constants.md#enum-LEToneMapping) |
### Returns
- None
### C Prototype
`void le_set_tone_mapping(enum LEToneMapping toneMapping);`
[:arrow_up_small:](#)
<br />
## [le_get_ambient_color](#le_get_ambient_color)
### Description
Outputs the lighting engine's ambient color to `out`
### Lua Example
`le_get_ambient_color(out)`
### Parameters
| Field | Type |
| ----- | ---- |
| out | [Color](structs.md#Color) |
### Returns
- None
### C Prototype
`void le_get_ambient_color(OUT Color out);`
[:arrow_up_small:](#)
<br />
## [le_set_ambient_color](#le_set_ambient_color)
### Description
Sets the lighting engine ambient color
### Lua Example
`le_set_ambient_color(r, g, b)`
### Parameters
| Field | Type |
| ----- | ---- |
| r | `integer` |
| g | `integer` |
| b | `integer` |
### Returns
- None
### C Prototype
`void le_set_ambient_color(u8 r, u8 g, u8 b);`
[:arrow_up_small:](#)
<br />
## [le_calculate_lighting_color](#le_calculate_lighting_color)
### Description
Calculates the lighting with `lightIntensityScalar` at a position and outputs the color in `out`
### Lua Example
`le_calculate_lighting_color(pos, out, lightIntensityScalar)`
### Parameters
| Field | Type |
| ----- | ---- |
| pos | [Vec3f](structs.md#Vec3f) |
| out | [Color](structs.md#Color) |
| lightIntensityScalar | `number` |
### Returns
- None
### C Prototype
`void le_calculate_lighting_color(Vec3f pos, OUT Color out, f32 lightIntensityScalar);`
[:arrow_up_small:](#)
<br />
## [le_calculate_lighting_color_with_normal](#le_calculate_lighting_color_with_normal)
### Description
Calculates the lighting with `lightIntensityScalar` at a position and with a normal and outputs the color in `out`
### Lua Example
`le_calculate_lighting_color_with_normal(pos, normal, out, lightIntensityScalar)`
### Parameters
| Field | Type |
| ----- | ---- |
| pos | [Vec3f](structs.md#Vec3f) |
| normal | [Vec3f](structs.md#Vec3f) |
| out | [Color](structs.md#Color) |
| lightIntensityScalar | `number` |
### Returns
- None
### C Prototype
`void le_calculate_lighting_color_with_normal(Vec3f pos, Vec3f normal, OUT Color out, f32 lightIntensityScalar);`
[:arrow_up_small:](#)
<br />
## [le_calculate_lighting_dir](#le_calculate_lighting_dir)
### Description
Calculates the lighting direction from a position and outputs the result in `out`
### Lua Example
`le_calculate_lighting_dir(pos, out)`
### Parameters
| Field | Type |
| ----- | ---- |
| pos | [Vec3f](structs.md#Vec3f) |
| out | [Vec3f](structs.md#Vec3f) |
### Returns
- None
### C Prototype
`void le_calculate_lighting_dir(Vec3f pos, OUT Vec3f out);`
[:arrow_up_small:](#)
<br />
## [le_add_light](#le_add_light)
### Description
Adds a lighting engine point light at `x`, `y`, `z` with color `r`, `g`, `b` and `radius` with `intensity`
### Lua Example
`local integerValue = le_add_light(x, y, z, r, g, b, radius, intensity)`
### Parameters
| Field | Type |
| ----- | ---- |
| x | `number` |
| y | `number` |
| z | `number` |
| r | `integer` |
| g | `integer` |
| b | `integer` |
| radius | `number` |
| intensity | `number` |
### Returns
- `integer`
### C Prototype
`s16 le_add_light(f32 x, f32 y, f32 z, u8 r, u8 g, u8 b, f32 radius, f32 intensity);`
[:arrow_up_small:](#)
<br />
## [le_remove_light](#le_remove_light)
### Description
Removes a lighting engine point light corresponding to `id`
### Lua Example
`le_remove_light(id)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
### Returns
- None
### C Prototype
`void le_remove_light(s16 id);`
[:arrow_up_small:](#)
<br />
## [le_get_light_count](#le_get_light_count)
### Description
Gets the total number of lights currently loaded in the lighting engine
### Lua Example
`local integerValue = le_get_light_count()`
### Parameters
- None
### Returns
- `integer`
### C Prototype
`s16 le_get_light_count(void);`
[:arrow_up_small:](#)
<br />
## [le_light_exists](#le_light_exists)
### Description
Checks if a lighting engine point light corresponding to `id` exists
### Lua Example
`local booleanValue = le_light_exists(id)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
### Returns
- `boolean`
### C Prototype
`bool le_light_exists(s16 id);`
[:arrow_up_small:](#)
<br />
## [le_get_light_pos](#le_get_light_pos)
### Description
Outputs a lighting engine point light's position to `out`
### Lua Example
`le_get_light_pos(id, out)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| out | [Vec3f](structs.md#Vec3f) |
### Returns
- None
### C Prototype
`void le_get_light_pos(s16 id, OUT Vec3f out);`
[:arrow_up_small:](#)
<br />
## [le_set_light_pos](#le_set_light_pos)
### Description
Sets a lighting engine point light's position to `x`, `y`, `z`
### Lua Example
`le_set_light_pos(id, x, y, z)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| x | `number` |
| y | `number` |
| z | `number` |
### Returns
- None
### C Prototype
`void le_set_light_pos(s16 id, f32 x, f32 y, f32 z);`
[:arrow_up_small:](#)
<br />
## [le_get_light_color](#le_get_light_color)
### Description
Outputs a lighting engine point light's color to `out`
### Lua Example
`le_get_light_color(id, out)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| out | [Color](structs.md#Color) |
### Returns
- None
### C Prototype
`void le_get_light_color(s16 id, OUT Color out);`
[:arrow_up_small:](#)
<br />
## [le_set_light_color](#le_set_light_color)
### Description
Sets a lighting engine point light's color to `r`, `g`, `b`
### Lua Example
`le_set_light_color(id, r, g, b)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| r | `integer` |
| g | `integer` |
| b | `integer` |
### Returns
- None
### C Prototype
`void le_set_light_color(s16 id, u8 r, u8 g, u8 b);`
[:arrow_up_small:](#)
<br />
## [le_get_light_radius](#le_get_light_radius)
### Description
Gets a lighting engine point light's `radius`
### Lua Example
`local numberValue = le_get_light_radius(id)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
### Returns
- `number`
### C Prototype
`f32 le_get_light_radius(s16 id);`
[:arrow_up_small:](#)
<br />
## [le_set_light_radius](#le_set_light_radius)
### Description
Sets a lighting engine point light's `radius`
### Lua Example
`le_set_light_radius(id, radius)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| radius | `number` |
### Returns
- None
### C Prototype
`void le_set_light_radius(s16 id, f32 radius);`
[:arrow_up_small:](#)
<br />
## [le_get_light_intensity](#le_get_light_intensity)
### Description
Gets a lighting engine point light's `intensity`
### Lua Example
`local numberValue = le_get_light_intensity(id)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
### Returns
- `number`
### C Prototype
`f32 le_get_light_intensity(s16 id);`
[:arrow_up_small:](#)
<br />
## [le_set_light_intensity](#le_set_light_intensity)
### Description
Sets a lighting engine point light's `intensity`
### Lua Example
`le_set_light_intensity(id, intensity)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| intensity | `number` |
### Returns
- None
### C Prototype
`void le_set_light_intensity(s16 id, f32 intensity);`
[:arrow_up_small:](#)
<br />
## [le_get_light_use_surface_normals](#le_get_light_use_surface_normals)
### Description
Gets whether a lighting engine point light will use a surface's normals to determine its brightness with `useSurfaceNormals`
### Lua Example
`local booleanValue = le_get_light_use_surface_normals(id)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
### Returns
- `boolean`
### C Prototype
`bool le_get_light_use_surface_normals(s16 id);`
[:arrow_up_small:](#)
<br />
## [le_set_light_use_surface_normals](#le_set_light_use_surface_normals)
### Description
Sets whether a lighting engine point light will use a surface's normals to determine its brightness with `useSurfaceNormals`
### Lua Example
`le_set_light_use_surface_normals(id, useSurfaceNormals)`
### Parameters
| Field | Type |
| ----- | ---- |
| id | `integer` |
| useSurfaceNormals | `boolean` |
### Returns
- None
### C Prototype
`void le_set_light_use_surface_normals(s16 id, bool useSurfaceNormals);`
[:arrow_up_small:](#)
<br />
---

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

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

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

View file

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

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

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

View file

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

View file

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

View file

@ -3,25 +3,16 @@
# Supported Structs
- [AnimInfo](#AnimInfo)
- [Animation](#Animation)
- [AnimationTable](#AnimationTable)
- [Area](#Area)
- [BehaviorDialogs](#BehaviorDialogs)
- [BehaviorTrajectories](#BehaviorTrajectories)
- [BehaviorValues](#BehaviorValues)
- [BullyCollisionData](#BullyCollisionData)
- [Camera](#Camera)
- [CameraFOVStatus](#CameraFOVStatus)
- [CameraOverride](#CameraOverride)
- [CameraStoredInfo](#CameraStoredInfo)
- [CameraTrigger](#CameraTrigger)
- [ChainSegment](#ChainSegment)
- [Character](#Character)
- [Color](#Color)
- [Controller](#Controller)
- [CustomLevelInfo](#CustomLevelInfo)
- [Cutscene](#Cutscene)
- [CutsceneSplinePoint](#CutsceneSplinePoint)
- [CutsceneVariable](#CutsceneVariable)
- [DateTime](#DateTime)
- [DialogEntry](#DialogEntry)
- [DisplayListNode](#DisplayListNode)
@ -32,7 +23,6 @@
- [DjuiThreePanelTheme](#DjuiThreePanelTheme)
- [ExclamationBoxContent](#ExclamationBoxContent)
- [FirstPersonCamera](#FirstPersonCamera)
- [FloorGeometry](#FloorGeometry)
- [FnGraphNode](#FnGraphNode)
- [Gfx](#Gfx)
- [GlobalObjectAnimations](#GlobalObjectAnimations)
@ -63,53 +53,38 @@
- [GraphNodeSwitchCase](#GraphNodeSwitchCase)
- [GraphNodeTranslation](#GraphNodeTranslation)
- [GraphNodeTranslationRotation](#GraphNodeTranslationRotation)
- [GraphNode_802A45E4](#GraphNode_802A45E4)
- [HandheldShakePoint](#HandheldShakePoint)
- [HudUtilsRotation](#HudUtilsRotation)
- [InstantWarp](#InstantWarp)
- [LakituState](#LakituState)
- [LevelValues](#LevelValues)
- [LinearTransitionPoint](#LinearTransitionPoint)
- [MarioAnimDmaRelatedThing](#MarioAnimDmaRelatedThing)
- [MarioAnimation](#MarioAnimation)
- [MarioBodyState](#MarioBodyState)
- [MarioState](#MarioState)
- [Mat4](#Mat4)
- [Mod](#Mod)
- [ModAudio](#ModAudio)
- [ModAudioSampleCopies](#ModAudioSampleCopies)
- [ModFile](#ModFile)
- [ModFs](#ModFs)
- [ModFsFile](#ModFsFile)
- [ModeTransitionInfo](#ModeTransitionInfo)
- [NametagsSettings](#NametagsSettings)
- [NetworkPlayer](#NetworkPlayer)
- [Object](#Object)
- [ObjectHitbox](#ObjectHitbox)
- [ObjectNode](#ObjectNode)
- [ObjectWarpNode](#ObjectWarpNode)
- [OffsetSizePair](#OffsetSizePair)
- [Painting](#Painting)
- [PaintingMeshVertex](#PaintingMeshVertex)
- [PaintingValues](#PaintingValues)
- [ParallelTrackingPoint](#ParallelTrackingPoint)
- [PlayerCameraState](#PlayerCameraState)
- [PlayerGeometry](#PlayerGeometry)
- [PlayerPalette](#PlayerPalette)
- [RayIntersectionInfo](#RayIntersectionInfo)
- [RomhackCameraSettings](#RomhackCameraSettings)
- [SPTask](#SPTask)
- [ServerSettings](#ServerSettings)
- [SoundState](#SoundState)
- [SpawnInfo](#SpawnInfo)
- [SpawnParticlesInfo](#SpawnParticlesInfo)
- [StarPositions](#StarPositions)
- [StarsNeededForDialog](#StarsNeededForDialog)
- [StaticObjectCollision](#StaticObjectCollision)
- [Surface](#Surface)
- [TextureInfo](#TextureInfo)
- [TransitionInfo](#TransitionInfo)
- [UnusedArea28](#UnusedArea28)
- [VblankHandler](#VblankHandler)
- [Vec2f](#Vec2f)
- [Vec2i](#Vec2i)
- [Vec2s](#Vec2s)
@ -120,11 +95,8 @@
- [Vec4i](#Vec4i)
- [Vec4s](#Vec4s)
- [Vtx](#Vtx)
- [Vtx_Interp](#Vtx_Interp)
- [WallCollisionData](#WallCollisionData)
- [WarpNode](#WarpNode)
- [WarpTransition](#WarpTransition)
- [WarpTransitionData](#WarpTransitionData)
- [WaterDropletParams](#WaterDropletParams)
- [Waypoint](#Waypoint)
- [Whirlpool](#Whirlpool)
@ -170,16 +142,6 @@
<br />
## [AnimationTable](#AnimationTable)
| Field | Type | Access |
| ----- | ---- | ------ |
| count | `integer` | read-only |
[:arrow_up_small:](#)
<br />
## [Area](#Area)
| Field | Type | Access |
@ -383,21 +345,6 @@
<br />
## [BullyCollisionData](#BullyCollisionData)
| Field | Type | Access |
| ----- | ---- | ------ |
| conversionRatio | `number` | |
| radius | `number` | |
| posX | `number` | |
| posZ | `number` | |
| velX | `number` | |
| velZ | `number` | |
[:arrow_up_small:](#)
<br />
## [Camera](#Camera)
| Field | Type | Access |
@ -422,64 +369,6 @@
<br />
## [CameraFOVStatus](#CameraFOVStatus)
| Field | Type | Access |
| ----- | ---- | ------ |
| fovFunc | `integer` | |
| fov | `number` | |
| fovOffset | `number` | |
| unusedIsSleeping | `integer` | |
| shakeAmplitude | `number` | |
| shakePhase | `integer` | |
| shakeSpeed | `integer` | |
| decay | `integer` | |
[:arrow_up_small:](#)
<br />
## [CameraOverride](#CameraOverride)
| Field | Type | Access |
| ----- | ---- | ------ |
| value | `integer` | |
| override | `boolean` | |
[:arrow_up_small:](#)
<br />
## [CameraStoredInfo](#CameraStoredInfo)
| Field | Type | Access |
| ----- | ---- | ------ |
| pos | [Vec3f](structs.md#Vec3f) | read-only |
| focus | [Vec3f](structs.md#Vec3f) | read-only |
| panDist | `number` | |
| cannonYOffset | `number` | |
[:arrow_up_small:](#)
<br />
## [CameraTrigger](#CameraTrigger)
| Field | Type | Access |
| ----- | ---- | ------ |
| area | `integer` | |
| centerX | `integer` | |
| centerY | `integer` | |
| centerZ | `integer` | |
| boundsX | `integer` | |
| boundsY | `integer` | |
| boundsZ | `integer` | |
| boundsYaw | `integer` | |
[:arrow_up_small:](#)
<br />
## [ChainSegment](#ChainSegment)
| Field | Type | Access |
@ -726,6 +615,7 @@
| animReturnFromStarDance | `integer` | read-only |
| animForwardSpinningFlip | `integer` | read-only |
| animTripleJumpFly | `integer` | read-only |
| anims | `Array` <`integer`> | read-only |
| soundFreqScale | `number` | read-only |
| soundYahWahHoo | `integer` | read-only |
| soundHoohoo | `integer` | read-only |
@ -771,6 +661,7 @@
| soundImaTired | `integer` | read-only |
| soundLetsAGo | `integer` | read-only |
| soundOkeyDokey | `integer` | read-only |
| sounds | `Array` <`integer`> | read-only |
[:arrow_up_small:](#)
@ -829,42 +720,6 @@
<br />
## [Cutscene](#Cutscene)
| Field | Type | Access |
| ----- | ---- | ------ |
| duration | `integer` | |
[:arrow_up_small:](#)
<br />
## [CutsceneSplinePoint](#CutsceneSplinePoint)
| Field | Type | Access |
| ----- | ---- | ------ |
| index | `integer` | |
| speed | `integer` | |
| point | [Vec3s](structs.md#Vec3s) | read-only |
[:arrow_up_small:](#)
<br />
## [CutsceneVariable](#CutsceneVariable)
| Field | Type | Access |
| ----- | ---- | ------ |
| unused1 | `integer` | |
| point | [Vec3f](structs.md#Vec3f) | read-only |
| unusedPoint | [Vec3f](structs.md#Vec3f) | read-only |
| angle | [Vec3s](structs.md#Vec3s) | read-only |
| unused2 | `integer` | |
[:arrow_up_small:](#)
<br />
## [DateTime](#DateTime)
| Field | Type | Access |
@ -1004,20 +859,6 @@
<br />
## [FloorGeometry](#FloorGeometry)
| Field | Type | Access |
| ----- | ---- | ------ |
| unused | `Array` <`number`> | |
| normalX | `number` | |
| normalY | `number` | |
| normalZ | `number` | |
| originOffset | `number` | |
[:arrow_up_small:](#)
<br />
## [FnGraphNode](#FnGraphNode)
| Field | Type | Access |
@ -1585,33 +1426,6 @@
<br />
## [GraphNode_802A45E4](#GraphNode_802A45E4)
| Field | Type | Access |
| ----- | ---- | ------ |
| unk18 | `integer` | |
| unk1A | `integer` | |
| unk1C | `integer` | |
| unk1E | `integer` | |
| unk20 | `integer` | |
| unk22 | `integer` | |
[:arrow_up_small:](#)
<br />
## [HandheldShakePoint](#HandheldShakePoint)
| Field | Type | Access |
| ----- | ---- | ------ |
| index | `integer` | |
| pad | `integer` | |
| point | [Vec3s](structs.md#Vec3s) | read-only |
[:arrow_up_small:](#)
<br />
## [HudUtilsRotation](#HudUtilsRotation)
| Field | Type | Access |
@ -1751,20 +1565,6 @@
<br />
## [LinearTransitionPoint](#LinearTransitionPoint)
| Field | Type | Access |
| ----- | ---- | ------ |
| focus | [Vec3f](structs.md#Vec3f) | read-only |
| pos | [Vec3f](structs.md#Vec3f) | read-only |
| dist | `number` | |
| pitch | `integer` | |
| yaw | `integer` | |
[:arrow_up_small:](#)
<br />
## [MarioAnimation](#MarioAnimation)
| Field | Type | Access |
@ -1794,6 +1594,7 @@
| headPos | [Vec3f](structs.md#Vec3f) | read-only |
| torsoPos | [Vec3f](structs.md#Vec3f) | read-only |
| heldObjLastPosition | [Vec3f](structs.md#Vec3f) | read-only |
| animPartsPos | `Array` <`Vec3f`> | read-only |
| currAnimPart | `integer` | read-only |
| updateTorsoTime | `integer` | read-only |
| updateHeadPosTime | `integer` | read-only |
@ -1945,6 +1746,7 @@
| renderBehindHud | `boolean` | read-only |
| pausable | `boolean` | read-only |
| ignoreScriptWarnings | `boolean` | read-only |
| size | `integer` | read-only |
| customBehaviorIndex | `integer` | read-only |
[:arrow_up_small:](#)
@ -1955,7 +1757,7 @@
| Field | Type | Access |
| ----- | ---- | ------ |
| file | [ModFile](structs.md#ModFile) | |
| filepath | `string` | read-only |
| isStream | `boolean` | read-only |
| baseVolume | `number` | |
| loaded | `boolean` | read-only |
@ -1964,33 +1766,6 @@
<br />
## [ModAudioSampleCopies](#ModAudioSampleCopies)
| Field | Type | Access |
| ----- | ---- | ------ |
| next | [ModAudioSampleCopies](structs.md#ModAudioSampleCopies) | |
| prev | [ModAudioSampleCopies](structs.md#ModAudioSampleCopies) | |
| parent | [ModAudio](structs.md#ModAudio) | |
[:arrow_up_small:](#)
<br />
## [ModFile](#ModFile)
| Field | Type | Access |
| ----- | ---- | ------ |
| relativePath | `string` | read-only |
| modifiedTimestamp | `integer` | read-only |
| isLoadedLuaModule | `boolean` | read-only |
| wroteBytes | `integer` | read-only |
| dataHash | `Array` <`integer`> | read-only |
| cachedPath | `string` | read-only |
[:arrow_up_small:](#)
<br />
## [ModFs](#ModFs)
| Field | Type | Access |
@ -2001,6 +1776,21 @@
| totalSize | `integer` | read-only |
| isPublic | `boolean` | read-only |
**Functions:**
| Name | Reference |
| ---- | --------- |
| get_filename | [`mod_fs_get_filename`](functions-5.md#mod_fs_get_filename) |
| get_file | [`mod_fs_get_file`](functions-5.md#mod_fs_get_file) |
| create_file | [`mod_fs_create_file`](functions-5.md#mod_fs_create_file) |
| move_file | [`mod_fs_move_file`](functions-5.md#mod_fs_move_file) |
| copy_file | [`mod_fs_copy_file`](functions-5.md#mod_fs_copy_file) |
| delete_file | [`mod_fs_delete_file`](functions-5.md#mod_fs_delete_file) |
| clear | [`mod_fs_clear`](functions-5.md#mod_fs_clear) |
| save | [`mod_fs_save`](functions-5.md#mod_fs_save) |
| delete | [`mod_fs_delete`](functions-5.md#mod_fs_delete) |
| set_public | [`mod_fs_set_public`](functions-5.md#mod_fs_set_public) |
[:arrow_up_small:](#)
<br />
@ -2016,20 +1806,29 @@
| isText | `boolean` | read-only |
| isPublic | `boolean` | read-only |
[:arrow_up_small:](#)
**Functions:**
<br />
## [ModeTransitionInfo](#ModeTransitionInfo)
| Field | Type | Access |
| ----- | ---- | ------ |
| newMode | `integer` | |
| lastMode | `integer` | |
| max | `integer` | |
| frame | `integer` | |
| transitionStart | [LinearTransitionPoint](structs.md#LinearTransitionPoint) | read-only |
| transitionEnd | [LinearTransitionPoint](structs.md#LinearTransitionPoint) | read-only |
| 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:](#)
@ -2097,6 +1896,7 @@
| collisionData | `Pointer` <`Collision`> | |
| behavior | `Pointer` <`BehaviorScript`> | read-only |
| curBhvCommand | `Pointer` <`BehaviorScript`> | read-only |
| bhvStack | `Array` <`integer`> | read-only |
| bhvStackIndex | `integer` | read-only |
| bhvDelayTimer | `integer` | |
| activeFlags | `integer` | |
@ -2905,17 +2705,6 @@
<br />
## [OffsetSizePair](#OffsetSizePair)
| Field | Type | Access |
| ----- | ---- | ------ |
| offset | `integer` | |
| size | `integer` | |
[:arrow_up_small:](#)
<br />
## [Painting](#Painting)
| Field | Type | Access |
@ -2947,10 +2736,9 @@
| rippleTimer | `number` | |
| rippleX | `number` | |
| rippleY | `number` | |
| normalDisplayList | `Pointer` <`Gfx`> | read-only |
| textureArray | `Array` <`Pointer` <`Texture`>> | read-only |
| textureWidth | `integer` | read-only |
| textureHeight | `integer` | read-only |
| rippleDisplayList | `Pointer` <`Gfx`> | read-only |
| rippleTrigger | `integer` | |
| alpha | `integer` | |
| marioWasUnder | `integer` | |
@ -2962,17 +2750,6 @@
<br />
## [PaintingMeshVertex](#PaintingMeshVertex)
| Field | Type | Access |
| ----- | ---- | ------ |
| pos | `Array` <`integer`> | |
| norm | `Array` <`integer`> | |
[:arrow_up_small:](#)
<br />
## [PaintingValues](#PaintingValues)
| Field | Type | Access |
@ -2998,19 +2775,6 @@
<br />
## [ParallelTrackingPoint](#ParallelTrackingPoint)
| Field | Type | Access |
| ----- | ---- | ------ |
| startOfPath | `integer` | |
| pos | [Vec3f](structs.md#Vec3f) | read-only |
| distThresh | `number` | |
| zoom | `number` | |
[:arrow_up_small:](#)
<br />
## [PlayerCameraState](#PlayerCameraState)
| Field | Type | Access |
@ -3027,32 +2791,11 @@
<br />
## [PlayerGeometry](#PlayerGeometry)
| Field | Type | Access |
| ----- | ---- | ------ |
| currFloor | [Surface](structs.md#Surface) | |
| currFloorHeight | `number` | |
| currFloorType | `integer` | |
| currCeil | [Surface](structs.md#Surface) | |
| currCeilType | `integer` | |
| currCeilHeight | `number` | |
| prevFloor | [Surface](structs.md#Surface) | |
| prevFloorHeight | `number` | |
| prevFloorType | `integer` | |
| prevCeil | [Surface](structs.md#Surface) | |
| prevCeilHeight | `number` | |
| prevCeilType | `integer` | |
| waterHeight | `number` | |
[:arrow_up_small:](#)
<br />
## [PlayerPalette](#PlayerPalette)
| Field | Type | Access |
| ----- | ---- | ------ |
| parts | `Array` <`Color`> | read-only |
[:arrow_up_small:](#)
@ -3110,19 +2853,6 @@
<br />
## [SoundState](#SoundState)
| Field | Type | Access |
| ----- | ---- | ------ |
| playSound | `integer` | |
| animFrame1 | `integer` | |
| animFrame2 | `integer` | |
| soundMagic | `integer` | |
[:arrow_up_small:](#)
<br />
## [SpawnInfo](#SpawnInfo)
| Field | Type | Access |
@ -3211,6 +2941,17 @@
<br />
## [StaticObjectCollision](#StaticObjectCollision)
| Field | Type | Access |
| ----- | ---- | ------ |
| index | `integer` | read-only |
| length | `integer` | read-only |
[:arrow_up_small:](#)
<br />
## [Surface](#Surface)
| Field | Type | Access |
@ -3244,25 +2985,8 @@
| name | `string` | read-only |
| width | `integer` | read-only |
| height | `integer` | read-only |
| bitSize | `integer` | read-only |
[:arrow_up_small:](#)
<br />
## [TransitionInfo](#TransitionInfo)
| Field | Type | Access |
| ----- | ---- | ------ |
| posPitch | `integer` | |
| posYaw | `integer` | |
| posDist | `number` | |
| focPitch | `integer` | |
| focYaw | `integer` | |
| focDist | `number` | |
| framesLeft | `integer` | |
| marioPos | [Vec3f](structs.md#Vec3f) | read-only |
| pad | `integer` | |
| format | `integer` | read-only |
| size | `integer` | read-only |
[:arrow_up_small:](#)
@ -3398,17 +3122,6 @@
<br />
## [Vtx_Interp](#Vtx_Interp)
| Field | Type | Access |
| ----- | ---- | ------ |
| ob | `Array` <`number`> | |
| n | `string` | |
[:arrow_up_small:](#)
<br />
## [WallCollisionData](#WallCollisionData)
| Field | Type | Access |
@ -3441,45 +3154,12 @@
<br />
## [WarpTransition](#WarpTransition)
| Field | Type | Access |
| ----- | ---- | ------ |
| isActive | `integer` | |
| type | `integer` | |
| time | `integer` | |
| pauseRendering | `integer` | |
| data | [WarpTransitionData](structs.md#WarpTransitionData) | read-only |
[:arrow_up_small:](#)
<br />
## [WarpTransitionData](#WarpTransitionData)
| Field | Type | Access |
| ----- | ---- | ------ |
| red | `integer` | |
| green | `integer` | |
| blue | `integer` | |
| startTexRadius | `integer` | |
| endTexRadius | `integer` | |
| startTexX | `integer` | |
| startTexY | `integer` | |
| endTexX | `integer` | |
| endTexY | `integer` | |
| texTimer | `integer` | |
[:arrow_up_small:](#)
<br />
## [WaterDropletParams](#WaterDropletParams)
| Field | Type | Access |
| ----- | ---- | ------ |
| flags | `integer` | |
| model | `integer` | |
| model | `integer` | read-only |
| behavior | `Pointer` <`BehaviorScript`> | read-only |
| moveAngleRange | `integer` | |
| moveRange | `integer` | |

View file

@ -1,12 +1,56 @@
#pragma once
//
// GFX COMMANDS FREE SLOTS
//
// The following op codes are free to use for G_ commands.
// For RSP commands, use incrementing numbers starting from 00.
// For RDP commands, use decrementing numbers starting from ff.
// Please update the following table when implementing a new command.
//
// RSP -> 09 0a 0b 0c 0d 0e 0f
// 10 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f
// 20 21 22 23 24 25 26 27 28 29 2a 2b 2c 2d 2e 2f
// 30 31 32 33 34 35 36 37 38 39 3a 3b 3c 3d 3e 3f
// 40 41 42 43 44 45 46 47 48 49 4a 4b 4c 4d 4e 4f
// 50 51 52 53 54 55 56 57 58 59 5a 5b 5c 5d 5e 5f
// 60 61 62 63 64 65 66 67 68 69 6a 6b 6c 6d 6e 6f
// 70 71 72 73 74 75 76 77 78 79 7a 7b 7c 7d 7e 7f
// 80 81 82 83 84 85 86 87 88 89 8a 8b 8c 8d 8e 8f
// 90 91 92 93 94 95 96 97 98 99 9a 9b 9c 9d 9e 9f
// a0 a1 a2 a3 a4 a5 a6 a7 a8 a9 aa ab ac ad ae af
// b0 b1 b2 b3 b4 b5 b6 b7 b8 b9 ba bb bc bd be bf
// c0 c1 c2 c3 c4 c5 c6 c7
// d0 <- RDP
//
//
///////////////////////
// G_SETGEOMETRYMODE //
///////////////////////
//
// GEOMETRY MODES FREE FLAGS
//
// The following flags are free to use for geometry modes.
// Please remove the corresponding flag from the list below when implementing a new geometry mode.
// Note: geometry mode flags have only 24 bits, the 8 upper bits cannot be used.
//
// 0x00000002
// 0x00000008
// 0x00000010
// 0x00000020
// 0x00001000
// 0x00002000
// 0x00008000
// 0x00080000 // G_TEXTURE_GEN_LINEAR, but not implemented
// 0x00100000 // G_LOD, but not implemented
// 0x00800000 // G_CLIPPING, but not implemented
#define G_LIGHT_MAP_EXT 0x00000800
#define G_LIGHTING_ENGINE_EXT 0x00004000
#define G_PACKED_NORMALS_EXT 0x00000080
#define G_CULL_INVERT_EXT 0x00000100
#define G_FRESNEL_COLOR_EXT 0x00000040
#define G_FRESNEL_ALPHA_EXT 0x00400000
@ -36,11 +80,11 @@
_g->words.w1 = _SHIFTL(x2, 16, 8) | _SHIFTL(y2, 8, 8); \
}
#define gSetOverrideDjui(pkt, cmd, texture, w, h, bitSize) \
#define gSetOverrideDjui(pkt, cmd, texture, w, h, fmt, siz) \
{ \
Gfx *_g = (Gfx *)(pkt); \
_g->words.w0 = _SHIFTL(cmd, 24, 8) | _SHIFTL(w, 16, 8) | \
_SHIFTL(h, 8, 8) | _SHIFTL(bitSize, 0, 8); \
_SHIFTL(h, 8, 8) | _SHIFTL(fmt, 4, 4) | _SHIFTL(siz, 0, 4); \
_g->words.w1 = (uintptr_t)(texture); \
}
@ -93,8 +137,19 @@
((height)-1) << G_TEXTURE_IMAGE_FRAC) \
}
#define gDPSetTextureClippingDjui(pkt, x1, y1, x2, y2) gSetClippingDjui(pkt, G_TEXCLIP_DJUI, x1, y1, x2, y2)
#define gDPSetTextureOverrideDjui(pkt, texture, w, h, bitSize) gSetOverrideDjui(pkt, G_TEXOVERRIDE_DJUI, texture, w, h, bitSize)
#define gDPSetTextureClippingDjui(pkt, x1, y1, x2, y2) gSetClippingDjui(pkt, G_TEXCLIP_DJUI, x1, y1, x2, y2)
#define gDPSetTextureOverrideDjui(pkt, texture, w, h, fmt, siz) gSetOverrideDjui(pkt, G_TEXOVERRIDE_DJUI, texture, w, h, fmt, siz)
/////////////////
// G_SETENVRGB //
/////////////////
#define G_SETENVRGB 0xd1
#define gDPSetEnvRGB(pkt, r, g, b) \
DPRGBColor(pkt, G_SETENVRGB, r,g,b,255)
#define gsDPSetEnvRGB(r, g, b) \
sDPRGBColor(G_SETENVRGB, r,g,b,255)
////////////////////
// G_PPARTTOCOLOR //
@ -121,9 +176,9 @@
((2 * ((part) + 1)) + 1 + offset) \
}}
////////////////////
//// G_MOVEWORD ////
////////////////////
////////////////
// G_MOVEWORD //
////////////////
#define G_MW_FX 0x00 /* replaces G_MW_MATRIX which is no longer supported */
#define G_MWO_FRESNEL 0x0C

View file

@ -33,6 +33,7 @@ define_gfx_symbol(gsSPGeometryMode, 2, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE
define_gfx_symbol(gsSPGeometryModeSetFirst, 2, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsDPSetPrimColor, 6, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsDPSetEnvColor, 4, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsDPSetEnvRGB, 3, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsDPSetFogColor, 4, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsSPFogPosition, 2, false, GFX_PARAM_TYPE_INT, GFX_PARAM_TYPE_INT);
define_gfx_symbol(gsDPSetAlphaCompare, 1, false, GFX_PARAM_TYPE_INT);

View file

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

View file

@ -577,11 +577,12 @@ struct MarioState
struct TextureInfo
{
Texture *texture;
const Texture *texture;
const char *name;
u32 width;
u32 height;
u8 bitSize;
u8 format;
u8 size;
};
#define PLAY_MODE_NORMAL 0

View file

@ -1,7 +1,7 @@
[NOTIF]
CONNECTED = "@ подключился"
DISCONNECTED = "@ отключился"
LEFT_THIS_LEVEL = "@ покинул уровень"
LEFT_THIS_LEVEL = "@ вышел из уровня"
ENTERED_THIS_LEVEL = "@ вошел в уровень"
ENTERED = "@ вошел в\n#"
SERVER_CLOSED = "\\#ffa0a0\\Отключение:\\#dcdcdc\\ сервер закрыт"
@ -14,7 +14,7 @@ DISCONNECT_REJOIN = "\\#ffa0a0\\Отключение:\\#dcdcdc\\ перепод
DISCONNECT_CLOSED = "\\#ffa0a0\\Отключение:\\#dcdcdc\\ Хост закрыл соединение."
DISCONNECT_BIG_MOD = "На сервере слишком большой мод.\nВыходим."
DIED = "@ умер"
DEBUG_FLY = "@ вошел в состояние свободного полета отладки"
DEBUG_FLY = "@ вошел в режим полета при отладке"
IMPORT_MOD_SUCCESS = "\\#a0ffa0\\Импортирован мод\n\\#dcdcdc\\'@'"
IMPORT_DYNOS_SUCCESS = "\\#a0ffa0\\Импортированнан пакет DynOS\n\\#dcdcdc\\'@'"
IMPORT_PALETTE_SUCCESS = "\\#a0ffa0\\Импортированный предустановленный набор палитр\n\\#dcdcdc\\'@'"
@ -146,7 +146,7 @@ INVERT_RIGHT_Y = "Инвертировать правый стик по оси Y
[DISPLAY]
DISPLAY = "DISPLAY"
FULLSCREEN = "Полноэкранный режим"
FORCE_4BY3 = "Экран 4:3"
FORCE_4BY3 = "Режим 4:3"
PRELOAD_TEXTURES = "Предварительная загрузка текстур"
VSYNC = "Вертикальная синхронизация"
FRAMERATE_MODE = "Тип частоты кадров"
@ -187,7 +187,7 @@ FONT_NORMAL = "Обычный"
FONT_ALIASED = "Гладкий"
LIGHT_THEME = "Свет"
DARK_THEME = "Темный"
MARIO_THEME = "Mario"
MARIO_THEME = "Марио"
ODYSSEY_THEME = "Одиссеи"
FILE_SELECT_THEME = "Выбор файла"

View file

@ -7,7 +7,7 @@ ENTERED = "@ ha entrado a \n#"
SERVER_CLOSED = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ El servidor ha sido cerrado."
DISCORD_ERROR = "Discord ha lanzado un error.\nPara solucionarlo, intenta: \n1. Cerrar el juego.\n2. Reiniciar Discord.\n3. Iniciar el juego."
DISCORD_DETECT = "\\#ffa0a0\\Error:\\#dcdcdc\\ No se ha podido detectar Discord.\n\\#a0a0a0\\Prueba a cerrar el juego, reiniciar Discord, e iniciar el juego otra vez."
DISCONNECT_FULL = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ La partida está llena"
DISCONNECT_FULL = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ La partida está llena."
DISCONNECT_KICK = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ has sido\nexpulsado del servidor"
DISCONNECT_BAN = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ has sido\nbaneado del servidor"
DISCONNECT_REJOIN = "\\#ffa0a0\\Desconectado:\\#dcdcdc\\ Uniéndose de nuevo..."
@ -17,7 +17,7 @@ DIED = "@ ha muerto."
DEBUG_FLY = "@ Está en estado de vuelo libre debug."
IMPORT_MOD_SUCCESS = "El mod \\#dcdcdc\\'@'\\#a0ffa0\\\nha sido importado con éxito."
IMPORT_DYNOS_SUCCESS = "El pack de DynOS \\#dcdcdc\\'@'\\#a0ffa0\\\nha sido importado con éxito."
IMPORT_PALETTE_SUCCESS = "\\#a0ffa0\\Ajuste preestablecido de paleta importado\n\\#dcdcdc\\'@'"
IMPORT_PALETTE_SUCCESS = "\\#a0ffa0\\Paleta importada\n\\#dcdcdc\\'@'"
IMPORT_FAIL = "\n\\#ffa0a0\\Error al importar el archivo. \\#dcdcdc\\\n'@'"
IMPORT_FAIL_INGAME = "\\#ffa0a0\\No se pueden importar archivos\nen medio de una partida."
COOPNET_CONNECTION_FAILED = "\\#ffa0a0\\¡No se ha podido conectar a CoopNet!"
@ -34,28 +34,28 @@ LATEST_VERSION = "Última versión"
YOUR_VERSION = "Su versión"
[CHAT]
KICKING = "¡'@' ha sido expulsado!"
BANNING = "¡'@' ha sido baneado!"
KICKING = "'@' ha sido expulsado."
BANNING = "'@' ha sido baneado."
SERVER_ONLY = "Solo el anfitrión puede usar este comando."
PERM_BANNING = "¡'@' ha sido baneado permanentemente!"
ADD_MODERATOR = "¡'@' ahora es un moderador!"
PERM_BANNING = "'@' ha sido baneado permanentemente."
ADD_MODERATOR = "'@' ahora es moderador."
PLAYERS = "Jugadores"
NO_PERMS = "No tienes permiso para usar este comando."
PLAYER_NOT_FOUND = "No se ha podido encontrar al jugador."
NAMETAGS_MISSING_PARAMETERS = "Parámetros faltantes: [OPCIÓN]"
SELF_KICK = "No te puedes expulsar a tí mismo."
SELF_BAN = "No te puedes banear a tí mismo."
SELF_MOD = "No puedes hacerte moderador a tí mismo."
SELF_KICK = "No puedes expulsarte a ti mismo."
SELF_BAN = "No puedes banearte a ti mismo."
SELF_MOD = "No puedes hacerte moderador a ti mismo."
KICK_CONFIRM = "¿Seguro que quieres expulsar a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para expulsar."
BAN_CONFIRM = "¿Seguro que quieres banear a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para banear."
PERM_BAN_CONFIRM = "¿Seguro que quieres banear permanentemente a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\' para banear."
MOD_CONFIRM = "¿Seguro que quieres hacer moderador a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\'."
MOD_CONFIRM = "¿Seguro que quieres volver moderador a '@'?\nEscribe '\\#a0ffa0\\/confirm\\#fff982\\'."
PLAYERS_DESC = "/players - Muestra la lista de todos los jugadores y sus IDs."
KICK_DESC = "/kick [NAME|ID] - Expulsa al jugador de la partida actual."
BAN_DESC = "/ban [NAME|ID] - Banea al jugador de la partida actual."
PERM_BAN_DESC = "/permban [NAME|ID] - Banea al jugador de todas tus partidas."
MOD_DESC = "/moderator [NAME|ID] - Permite a un jugador usar comandos como /kick, /ban o /permban de cualquier partida que crees."
NAMETAGS_DESC = "/nametags [show-tag|show-health] - Cambia si ves tu propia etiqueta y si ves la salud"
KICK_DESC = "/kick [NOMBRE|ID] - Expulsa a un jugador de la partida actual."
BAN_DESC = "/ban [NOMBRE|ID] - Banea a un jugador de la partida actual."
PERM_BAN_DESC = "/permban [NOMBRE|ID] - Banea a un jugador de todas tus partidas permanentemente."
MOD_DESC = "/moderator [NOMBRE|ID] - Permite a un jugador usar comandos como /kick o /ban de cualquier partida que crees."
NAMETAGS_DESC = "/nametags [show-tag|show-health] - Cambia si ves tu propia etiqueta y si ves la salud de los demás."
UNRECOGNIZED = "Comando desconocido."
MOD_GRANTED = "\\#fff982\\Ahora eres moderador."
ALL_COMMANDS = "Todos los comandos"
@ -72,25 +72,25 @@ CAMERA = "CÁMARA"
FREE_CAMERA = "Cámara libre"
ANALOG_CAMERA = "Cámara analógica"
FREE_CAMERA_TITLE = "CÁMARA LIBRE"
FREE_CAMERA_L_CENTERING = "Centrado L"
FREE_CAMERA_USE_DPAD = "Comportamiento del DPad"
FREE_CAMERA_COLLISION = "Colisiones de la cámara"
ROMHACK_CAMERA_TITLE = "CÁMARA\nROMHACK"
ROMHACK_CAMERA = "Cámara Romhack"
ROMHACK_CAMERA_AUTOMATIC = "Automática"
ROMHACK_CAMERA_ON = "Encendida"
ROMHACK_CAMERA_OFF = "Apagada"
FREE_CAMERA_L_CENTERING = "Centrar con L"
FREE_CAMERA_USE_DPAD = "Mover con Dpad"
FREE_CAMERA_COLLISION = "Colisiones de cámara"
ROMHACK_CAMERA_TITLE = "CÁMARA DE ROMHACK"
ROMHACK_CAMERA = "Cámara de Romhack"
ROMHACK_CAMERA_AUTOMATIC = "Automático"
ROMHACK_CAMERA_ON = "Activada"
ROMHACK_CAMERA_OFF = "Desactivada"
ROMHACK_CAMERA_IN_BOWSER = "Usar en peleas con Bowser"
ROMHACK_CAMERA_COLLISION = "Colisiones de cámara"
ROMHACK_CAMERA_L_CENTERING = "Centrado L"
ROMHACK_CAMERA_USE_DPAD = "Comportamiento del DPad"
ROMHACK_CAMERA_SLOW_FALL = "Caída lenta"
CAMERA_TOXIC_GAS = "Ajuste para gases tóxicos"
MOUSE_LOOK = "Movimiento con mouse"
ROMHACK_CAMERA_L_CENTERING = "Centrar con L"
ROMHACK_CAMERA_USE_DPAD = "Mover con Dpad"
ROMHACK_CAMERA_SLOW_FALL = "Descender lentamente"
CAMERA_TOXIC_GAS = "Ajustar para gases tóxicos"
MOUSE_LOOK = "Mover con el ratón"
INVERT_X = "Invertir eje X"
INVERT_Y = "Invertir eje Y"
X_SENSITIVITY = "Sensibilidad eje X"
Y_SENSITIVITY = "Sensibilidad eje Y"
X_SENSITIVITY = "Sensibilidad del eje X"
Y_SENSITIVITY = "Sensibilidad del eje Y"
AGGRESSION = "Agresión"
PAN_LEVEL = "Nivel de seguimiento"
DECELERATION = "Deceleración"
@ -101,7 +101,7 @@ CONTROLS = "CONTROLES"
N64_BINDS = "Botones de N64"
EXTRA_BINDS = "Botones Adicionales"
BACKGROUND_GAMEPAD = "Mando en segundo plano"
DISABLE_GAMEPADS = "Desactivar gamepads"
DISABLE_GAMEPADS = "Desactivar mandos"
GAMEPAD = "Mando"
DEADZONE = "Zona muerta"
RUMBLE_STRENGTH = "Intensidad de vibración"
@ -109,14 +109,14 @@ RUMBLE_STRENGTH = "Intensidad de vibración"
CHAT = "Chat"
CHAT_COMMAND = "Chat (Comando)"
PLAYERS = "Jugadores"
D_UP = "Cruz Arriba"
D_DOWN = "Cruz Abajo"
D_LEFT = "Cruz Izquierda"
D_RIGHT = "Cruz Derecha"
D_UP = "Dpad Arriba"
D_DOWN = "Dpad Abajo"
D_LEFT = "Dpad Izquierda"
D_RIGHT = "Dpad Derecha"
X = "X"
Y = "Y"
CONSOLE = "Consola"
PREV = "Pagina Ant."
PREV = "Página Ant."
NEXT = "Sig. Página"
DISCONNECT = "Desconectar"
@ -137,12 +137,12 @@ C_RIGHT = "C Derecha"
ANALOG_STICK_OPTIONS = "Opciones del mando analógico"
ROTATE_LEFT = "Gira el stick izquierdo 90 grados"
INVERT_LEFT_X = "Invertir eje X del stick izquierdo"
INVERT_LEFT_Y = "Invertir eje Y del stick izquierdo"
ROTATE_RIGHT = "Gira el stick derecho 90 grados"
INVERT_RIGHT_X = "Invertir Stick derecho eje X"
INVERT_RIGHT_Y = "Invertir el eje Y del stick derecho"
ROTATE_LEFT = "Girar la palanca izquierda 90 grados"
INVERT_LEFT_X = "Invertir eje X de la palanca izquierda"
INVERT_LEFT_Y = "Invertir eje Y de la palanca izquierda"
ROTATE_RIGHT = "Girar la palanca derecha 90 grados"
INVERT_RIGHT_X = "Invertir eje X de la palanca derecha"
INVERT_RIGHT_Y = "Invertir eje Y de la palanca derecha"
[DISPLAY]
DISPLAY = "PANTALLA"
@ -169,10 +169,10 @@ D3X = "3x"
D10X = "10x"
D100X = "100x"
DRAW_DISTANCE = "Distancia de dibujado"
DYNOS_PACKS = "Packs de DynOS"
DYNOS_PACKS = "Packs DynOS"
ANTIALIASING = "Anti-aliasing"
OFF = "Desactivado"
MUST_RESTART = "Tienes que reiniciar el juego para que algunos cambios surtan efecto."
MUST_RESTART = "Tienes que reiniciar el juego para aplicar los cambios."
SHOW_FPS = "Mostrar FPS"
SHOW_PING = "Mostrar Ping"
@ -194,51 +194,51 @@ FILE_SELECT_THEME = "Selección de archivo"
[DYNOS]
DYNOS = "DYNOS"
LOCAL_PLAYER_MODEL_ONLY = "Solo modelo de jugador local"
LOCAL_PLAYER_MODEL_ONLY = "Solo reemplazar el modelo del jugador local"
[HOST_MESSAGE]
INFO_TITLE = "INFO"
WARN_DISCORD = "Invita a amigos haciendo click derecho en su nombre en Discord y seleccionando\n'\\#d0d0ff\\Invitar a unirse\\#dcdcdc\\'.\n\nPuedes invitar en canales de un servidor también presionando el botón \\#d0d0ff\\+\\#dcdcdc\\ al lado del cuadro de texto del chat.\n\nEl estado de Actividad Actual \\#ffa0a0\\debe estar\\#dcdcdc\\ activado en tus ajustes de Discord.\n\nEstar invisible \\#ffa0a0\\te prevendrá\\#dcdcdc\\ de crear invitaciones."
WARN_DISCORD2 = "\\#ffa0a0\\Error:\\#dcdcdc\\ No se ha detectado Discord.\n\n\\#a0a0a0\\Prueba a cerrar el juego,\nreiniciar Discord,\ny abrir el juego de nuevo."
WARN_SOCKET = "Asegúrate de que tu firewall esté configurado correctamente.\nLas conexiones directas \\#ffa0a0\\requieren que\\#dcdcdc\\ configures el reenvío de puertos en tu router para aceptar conexiones entrantes IPv4.\n\nReenvía el puerto '\\#d0d0ff\\%d\\#dcdcdc\\' para UDP. IPv6 también es suportado."
WARN_SOCKET = "Asegúrate de que tu firewall esté configurado correctamente.\nLas conexiones directas \\#ffa0a0\\requieren que\\#dcdcdc\\ configures el reenvío de puertos en tu router para aceptar conexiones entrantes IPv4.\n\nReenvía el puerto '\\#d0d0ff\\%d\\#dcdcdc\\' para UDP. IPv6 también es compatible."
HOST = "Crear"
[HOST_MODS]
MODS = "MODS"
CATEGORIES = "Categorías"
CATEGORIES = "Categoría"
WARNING = "\\#ffffa0\\Advertencia:\\#dcdcdc\\ Tienes 10 o más mods activados, por favor desactiva algunos para prevenir inestabilidad o lag."
NO_MODS_FOUND = "No se han encontrado mods."
[HOST_MOD_CATEGORIES]
ALL = "Todos"
MISC = "Varios"
MISC = "Otros"
ROMHACKS = "Romhacks"
GAMEMODES = "Modos de juego"
MOVESETS = "Conjuntos de movimientos"
MOVESETS = "Movimientos"
CHARACTER_SELECT = "Character Select"
[HOST_SAVE]
SAVE_TITLE = "RANURAS DE\nGUARDADO"
SAVE_TITLE = "ARCHIVOS DE\nGUARDADO"
ERASE_TITLE = "BORRAR"
CONFIRM = "¿Seguro que quieres borrar esta partida?"
CONFIRM = "¿Seguro que quieres borrar este archivo?"
ERASE = "Borrar"
EDIT = "Editar"
EDIT_TITLE = "EDITAR"
EDIT_NAME = "Editar nombre del archivo guardado @:"
EDIT_NAME = "Editar nombre del archivo @:"
[HOST_SETTINGS]
SETTINGS = "AJUSTES"
NONSOLID = "No Sólida"
NONSOLID = "Ninguna"
SOLID = "Sólida"
FRIENDLY_FIRE = "Fuego Amigo"
PLAYER_INTERACTION = "Interacción entre jugadores"
WEAK = "Poca"
WEAK = "Ligera"
NORMAL = "Normal"
TOO_MUCH = "Demasiada"
TOO_MUCH = "Extrema"
KNOCKBACK_STRENGTH = "Fuerza de retroceso"
CLASSIC_PVP = "Clásico"
REVAMPED_PVP = "Revisado"
PVP_MODE = "Modo Jugador contra Jugador"
CLASSIC_PVP = "Clasico"
REVAMPED_PVP = "Renovado"
PVP_MODE = "Modo de PVP"
LEAVE_LEVEL = "Salir del nivel"
STAY_IN_LEVEL = "Seguir en el nivel"
NONSTOP = "Sin parar"
@ -248,12 +248,12 @@ ENABLE_CHEATS = "Habilitar trucos"
BUBBLE_ON_DEATH = "Burbuja al morir"
NAMETAGS = "Etiquetas de nombre"
MOD_DEV_MODE = "Modo de desarrollo de mods"
BOUNCY_BOUNDS_ON_CAP = "Encendido (Limitado)"
BOUNCY_BOUNDS_ON = "Encendido"
BOUNCY_BOUNDS_OFF = "Apagado"
BOUNCY_LEVEL_BOUNDS = "Límites de Nivel Rebote"
BOUNCY_BOUNDS_ON_CAP = "Activado (Limitado)"
BOUNCY_BOUNDS_ON = "Activado"
BOUNCY_BOUNDS_OFF = "Desactivado"
BOUNCY_LEVEL_BOUNDS = "Límites del nivel rebotantes"
AMOUNT_OF_PLAYERS = "Número de jugadores"
PAUSE_ANYWHERE = "Pausa en cualquier lugar"
PAUSE_ANYWHERE = "Pausa en cualquier momento"
[HOST]
SERVER_TITLE = "PARTIDA"
@ -264,10 +264,10 @@ DIRECT_CONNECTION = "Conexión Directa"
NETWORK_SYSTEM = "Modo de conexión"
PORT = "Puerto"
PASSWORD = "Contraseña"
SAVE_SLOT = "Ranuras"
SAVE_SLOT = "Archivos"
SETTINGS = "Ajustes"
MODS = "Mods"
ROMHACKS = "Rom-Hacks"
ROMHACKS = "Romhacks"
APPLY = "Aplicar"
HOST = "Crear"
@ -285,11 +285,11 @@ DIRECT = "Conexión Directa"
[RULES]
RULES_TITLE = "REGLAS"
RULE_1 = "1. Debes tener 13 años o más para usar CoopNet."
RULE_2 = "2. Abstente de acosar, incitar al odio, emplear insultos, u otro tipo de lenguaje ofensivo."
RULE_3 = "3. Solo debes utilizar versiones sin modificar de sm64coopdx en CoopNet."
RULE_1 = "1. Debes tener 13 años o más para jugar en CoopNet."
RULE_2 = "2. Abstente de acosar, incitar al odio, utilizar insultos graves u otro tipo de lenguaje ofensivo."
RULE_3 = "3. Solo se permite utilizar versiones no modificadas de sm64coopdx en CoopNet."
RULE_4 = "4. Está estrictamente prohibido utilizar herramientas externas para hacer trampas en el juego."
RULE_5 = "5. No utilices mods sin publicar sin consentimiento de los autores."
RULE_5 = "5. No utilices mods sin publicar sin consentimiento de los autores originales."
RULE_6 = "6. No se tolerará el contenido pornográfico o fetichista. Esto incluye, pero no se limita, a mods, personajes, o roleplay erótico."
SUBJECT_TO_CHANGE = "Estas reglas están sujetas a cambios en futuras actualizaciones."
NOTICE = "Al conectarte a CoopNet, aceptas a cumplir estas normas mientras juegas en partidas públicas."
@ -304,12 +304,12 @@ OPTIONS = "Opciones"
QUIT = "Salir"
[MENU_OPTIONS]
MENU_TITLE = "MENÚ"
MENU_TITLE = "MENU"
LEVEL = "Nivel"
STAFF_ROLL = "Créditos Finales"
STAFF_ROLL = "Mostrar los créditos"
MUSIC = "Música"
RANDOM_STAGE = "Nivel aleatorio"
PLAY_VANILLA_DEMOS = "Demos originales"
PLAY_VANILLA_DEMOS = "Mostrar las demos"
[MISC]
DEBUG_TITLE = "DEPURACIÓN"
@ -378,7 +378,7 @@ APPDATA = "Abrir AppData"
[PAUSE]
QUIT_TITLE = "SALIR"
QUIT_HOST = "¿Seguro que quieres acabar la partida?"
QUIT_CLIENT = "¿Seguro que te quieres desconectar?"
QUIT_CLIENT = "¿Seguro que quieres desconectarte?"
PAUSE_TITLE = "PAUSA"
PLAYER = "Jugador"
DYNOS_PACKS = "Packs de DynOS"
@ -409,17 +409,17 @@ GREEN = "Verde"
BLUE = "Azul"
PLAYER = "Jugador"
NAME = "Nombre"
MODEL = "Modelo"
PALETTE_PRESET = "Paletas predeterminadas"
MODEL = "Personaje"
PALETTE_PRESET = "Paletas"
EDIT_PALETTE = "Editar Paleta"
ACTIVE_PALETTE = "Guardar la paleta actual como determinada"
PRESET_NAME = "Nombre"
DELETE_PRESET = "Eliminar"
SAVE_PRESET = "Guardar"
CAP_TOGGLE = "Pulsa Z para poner o quitar la gorra."
CAP_TOGGLE = "Presiona Z para ponerte o quitarte la gorra."
[PALETTE]
CUSTOM = "Personalizado"
CUSTOM = "Personalizada"
[PLAYER_LIST]
PLAYERS = "JUGADORES"
@ -429,12 +429,12 @@ ACT = "acto"
[SOUND]
SOUND = "SONIDO"
MASTER_VOLUME = "Volumen General"
MUSIC_VOLUME = "Volumen de Música"
SFX_VOLUME = "Volumen de Efectos de Sonido"
ENV_VOLUME = "Volumen de Entorno"
FADEOUT = "Disminuir sonidos lejanos"
MUTE_FOCUS_LOSS = "Silenciar sonido cuando la ventana está desenfocada"
MASTER_VOLUME = "Volumen general"
MUSIC_VOLUME = "Volumen de la música"
SFX_VOLUME = "Volumen de los sonidos"
ENV_VOLUME = "Volumen del entorno"
FADEOUT = "Silenciar sonidos lejanos"
MUTE_FOCUS_LOSS = "Silenciar sonido cuando la ventana esté desenfocada"
[LANGUAGE]
LANGUAGE = "IDIOMA"
@ -454,7 +454,7 @@ PUBLIC_LOBBIES = "PARTIDAS\nPÚBLICAS"
PRIVATE_LOBBIES = "PARTIDAS\nPRIVADAS"
REFRESH = "Refrescar"
REFRESHING = "Refrescando..."
ENTER_PASSWORD = "Introduce la contraseña de la partida privada:"
ENTER_PASSWORD = "Escribe la contraseña de la partida privada:"
SEARCH = "Buscar"
NO_LOBBIES_FOUND = "No se han encontrado partidas."

View file

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

View file

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

View file

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

View file

@ -5,6 +5,7 @@
#include <cstdint>
extern "C" {
class Connection;
class Lobby;
#endif
#include <stdbool.h>
@ -43,7 +44,8 @@ typedef struct {
uint64_t (*DestIdFunction)(uint64_t aInput);
#if defined(__cplusplus)
bool (*ConnectionIsAllowed)(Connection*, bool);
void (*OnReceiveInfoBits)(Connection* aConnection, uint64_t aDestId, uint64_t aInfoBits, const char* aName);
bool (*LobbyConnectionIsAllowed)(Connection*, Lobby*);
void (*OnReceiveInfoBits)(Connection* aConnection, uint64_t aDestId, uint64_t aInfoBits, uint64_t aHash, const char* aName);
#endif
} CoopNetCallbacks;

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -15,15 +15,15 @@ void sequence_channel_set_volume(struct SequenceChannel *seqChannel, u8 volume);
void process_sequences(s32 iterationsRemaining);
void init_sequence_player(u32 player);
void init_sequence_players(void);
/* |description|Gets the tempo of `player`|descriptionEnd| */
/* |description|Gets the `tempo` of `player`|descriptionEnd| */
u16 sequence_player_get_tempo(u8 player);
/* |description|Sets the `tempo` of `player`. Resets when another sequence is played|descriptionEnd| */
void sequence_player_set_tempo(u8 player, u16 tempo);
/* |description|Gets the tempoAcc (tempo accumulation) of `player`|descriptionEnd| */
/* |description|Gets the `tempoAcc` (tempo accumulation) of `player`|descriptionEnd| */
u16 sequence_player_get_tempo_acc(u8 player);
/* |description|Sets the `tempoAcc` (tempo accumulation) of `player`. Resets when another sequence is played|descriptionEnd| */
void sequence_player_set_tempo_acc(u8 player, u16 tempoAcc);
/* |description|Gets the transposition (pitch) of `player`|descriptionEnd| */
/* |description|Gets the `transposition` (pitch) of `player`|descriptionEnd| */
u16 sequence_player_get_transposition(u8 player);
/* |description|Sets the `transposition` (pitch) of `player`. Resets when another sequence is played|descriptionEnd| */
void sequence_player_set_transposition(u8 player, u16 transposition);

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

@ -3,6 +3,7 @@ static u32 networkBowserAnimationIndex = 0;
static u8 bowserIsDying = FALSE;
static u8 bowserCutscenePlayed = FALSE;
static u8 bowserIsCutscenePlayer = FALSE;
static u8 bowserCutsceneGlobalIndex = UNKNOWN_GLOBAL_INDEX;
void bowser_tail_anchor_act_0(void) {
struct Object* bowser = o->parentObj;
@ -777,6 +778,10 @@ void bowser_act_thrown_dropped(void)
o->oAction = 4;
else
o->oAction = 12;
if (is_nearest_mario_state_to_object(gMarioState, o)) {
network_send_object(o);
}
}
}
@ -1125,8 +1130,17 @@ void bowser_act_ride_tilting_platform(void) {
cur_obj_extend_animation_if_at_end();
}
void bowser_act_nothing(void) {
void bowser_act_nothing(void) { // start moving if cutscene player is inactive
if (bowserCutsceneGlobalIndex == UNKNOWN_GLOBAL_INDEX) {
return;
}
struct NetworkPlayer* np = network_player_from_global_index(bowserCutsceneGlobalIndex);
if (np == NULL || !is_player_active(&gMarioStates[np->localIndex])) {
bowserCutscenePlayed = TRUE;
bowser_initialize_action();
return;
}
}
s32 bowser_check_fallen_off_stage(void) // bowser off stage?
@ -1232,6 +1246,7 @@ void bowser_held_update(void) {
return;
}
o->parentObj = player;
o->oBowserUnkF4 &= ~0x20000;
cur_obj_become_intangible();
@ -1385,6 +1400,13 @@ static u8 bhv_bowser_ignore_if_true(void) {
return FALSE;
}
static void bhv_bowser_on_received_post(UNUSED u8 localIndex) {
// prevent sync from putting bowser in text action instead of nothing action
if (!(bowserIsCutscenePlayer || bowserCutscenePlayed) && (o->oAction == 5 || o->oAction == 6)) {
o->oAction = 20;
}
}
void bhv_bowser_init(void) {
bowserIsDying = FALSE;
s32 level; // 0 is dw, 1 is fs, 2 is sky
@ -1408,9 +1430,11 @@ void bhv_bowser_init(void) {
// Make sure we're the first to trigger Bowser.
if (!is_other_player_active()) {
bowserIsCutscenePlayer = TRUE;
bowserCutsceneGlobalIndex = gNetworkPlayerLocal->globalIndex;
o->oAction = 5; // bowser_act_text_wait
} else { // If we aren't do nothing till we get our sync.
bowserIsCutscenePlayer = FALSE;
bowserCutsceneGlobalIndex = UNKNOWN_GLOBAL_INDEX;
o->oAction = 20; // bowser_act_nothing
}
@ -1419,9 +1443,11 @@ void bhv_bowser_init(void) {
if (so) {
so->override_ownership = bhv_bowser_override_ownership;
so->ignore_if_true = bhv_bowser_ignore_if_true;
so->on_received_post = bhv_bowser_on_received_post;
so->fullObjectSync = TRUE;
sync_object_init_field_with_size(o, &o->header.gfx.node.flags, 16);
sync_object_init_field_with_size(o, &o->header.gfx.animInfo.animFrame, 16);
sync_object_init_field_with_size(o, &bowserCutsceneGlobalIndex, 8);
sync_object_init_field(o, &networkBowserAnimationIndex);
sync_object_init_field(o, &o->header.gfx.scale[0]);
sync_object_init_field(o, &o->header.gfx.scale[1]);

View file

@ -23,7 +23,7 @@ void bhv_heave_ho_throw_mario_loop(void) {
if (player) {
player->oInteractStatus |= INT_STATUS_MARIO_UNK2;
}
if (marioState) {
if (marioState && marioState->action == ACT_GRABBED) {
marioState->forwardVel = -45.0f;
marioState->vel[1] = 95.0f;
}

View file

@ -101,7 +101,7 @@ inline static s16 newcam_adjust_value(f32 var, f32 val, f32 limit) {
inline static s32 newcam_ivrt(u8 axis) {
return (
axis == 0 ?
(gNewCamera.invertX ? 1 : -1) :
(gNewCamera.invertX ? -1 : 1) :
(gNewCamera.invertY ? -1 : 1)
);
}
@ -313,7 +313,7 @@ static void newcam_zoom_button(void) {
// When you press L, set the flag for centering the camera. Afterwards, start setting the yaw to the Player's yaw at the time.
if (gNewCamera.LCentering && (gPlayer1Controller->buttonDown & L_TRIG)) {
gNewCamera.yawTarget = -gMarioState->faceAngle[1] - 0x4000;
gNewCamera.yawTarget = -gMarioState->statusForCamera->faceAngle[1] - 0x4000;
gNewCamera.centering = true;
}
@ -346,24 +346,24 @@ static void newcam_update_values(void) {
if (gNewCamera.turnWait > 0 && gMarioState->vel[1] == 0) {
gNewCamera.turnWait--;
} else if (gMarioState->intendedMag > 0 && gMarioState->vel[1] == 0) {
gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, -gMarioState->faceAngle[1] - 0x4000, ((gNewCamera.aggression * (ABS(gPlayer1Controller->rawStickX / 10.f))) * (gMarioState->forwardVel / 32.f)));
gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, -gMarioState->statusForCamera->faceAngle[1] - 0x4000, ((gNewCamera.aggression * (ABS(gPlayer1Controller->rawStickX / 10.f))) * (gMarioState->forwardVel / 32.f)));
} else {
gNewCamera.turnWait = 10;
}
// During slide actions in slide levels, force centering
if (gNewCamera.isSlide && (
gMarioState->action == ACT_BUTT_SLIDE ||
gMarioState->action == ACT_STOMACH_SLIDE ||
gMarioState->action == ACT_HOLD_BUTT_SLIDE ||
gMarioState->action == ACT_HOLD_STOMACH_SLIDE)
gMarioState->statusForCamera->action == ACT_BUTT_SLIDE ||
gMarioState->statusForCamera->action == ACT_STOMACH_SLIDE ||
gMarioState->statusForCamera->action == ACT_HOLD_BUTT_SLIDE ||
gMarioState->statusForCamera->action == ACT_HOLD_STOMACH_SLIDE)
) {
centering = (gMarioState->forwardVel > 8);
ycentering = false;
}
// Force centering when flying
if ((gMarioState->action & ACT_FLAG_FLYING) == ACT_FLAG_FLYING) {
if ((gMarioState->statusForCamera->action & ACT_FLAG_FLYING) == ACT_FLAG_FLYING) {
centering = true;
}
@ -371,12 +371,12 @@ static void newcam_update_values(void) {
// Place the camera behind Mario during the ACT_SHOT_FROM_CANNON action
static u32 sLastAction = 0;
static bool sForceCentering = false;
if (sLastAction != gMarioState->action) {
sLastAction = gMarioState->action;
if (sLastAction != gMarioState->statusForCamera->action) {
sLastAction = gMarioState->statusForCamera->action;
sForceCentering = true;
switch (gMarioState->action) {
switch (gMarioState->statusForCamera->action) {
case ACT_SHOT_FROM_CANNON:
gNewCamera.yaw = -gMarioState->faceAngle[1] - 0x4000;
gNewCamera.yaw = -gMarioState->statusForCamera->faceAngle[1] - 0x4000;
break;
}
}
@ -392,14 +392,14 @@ static void newcam_update_values(void) {
}
// Force centering during non-still swimming actions
if (gMarioState->action & ACT_FLAG_SWIMMING && gMarioState->forwardVel > 2) {
if (gMarioState->statusForCamera->action & ACT_FLAG_SWIMMING && gMarioState->forwardVel > 2) {
centering = true;
}
if (centering) {
gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, -gMarioState->faceAngle[1] - 0x4000, gMarioState->forwardVel * 128);
gNewCamera.yaw = approach_s16_symmetric(gNewCamera.yaw, -gMarioState->statusForCamera->faceAngle[1] - 0x4000, gMarioState->forwardVel * 128);
if (gMarioState->forwardVel > 1 && ycentering) {
gNewCamera.tilt = approach_s16_symmetric(gNewCamera.tilt, (-gMarioState->faceAngle[0] * 0.8f) + NEWCAM_TILT_CENTERING, gMarioState->forwardVel * 32);
gNewCamera.tilt = approach_s16_symmetric(gNewCamera.tilt, (-gMarioState->statusForCamera->faceAngle[0] * 0.8f) + NEWCAM_TILT_CENTERING, gMarioState->forwardVel * 32);
} else {
gNewCamera.tilt = approach_s16_symmetric(gNewCamera.tilt, NEWCAM_TILT_CENTERING, 32);
}
@ -508,12 +508,12 @@ static void newcam_set_pan(void) {
}
// Apply panning values based on Mario's direction.
if (gMarioState->action != ACT_HOLDING_BOWSER &&
gMarioState->action != ACT_SLEEPING &&
gMarioState->action != ACT_START_SLEEPING
if (gMarioState->statusForCamera->action != ACT_HOLDING_BOWSER &&
gMarioState->statusForCamera->action != ACT_SLEEPING &&
gMarioState->statusForCamera->action != ACT_START_SLEEPING
) {
approach_f32_asymptotic_bool(&gNewCamera.panX, newcam_lengthdir_x((160.f * gNewCamera.panLevel) / 100.f, -gMarioState->faceAngle[1] - 0x4000), 0.05f);
approach_f32_asymptotic_bool(&gNewCamera.panZ, newcam_lengthdir_y((160.f * gNewCamera.panLevel) / 100.f, -gMarioState->faceAngle[1] - 0x4000), 0.05f);
approach_f32_asymptotic_bool(&gNewCamera.panX, newcam_lengthdir_x((160.f * gNewCamera.panLevel) / 100.f, -gMarioState->statusForCamera->faceAngle[1] - 0x4000), 0.05f);
approach_f32_asymptotic_bool(&gNewCamera.panZ, newcam_lengthdir_y((160.f * gNewCamera.panLevel) / 100.f, -gMarioState->statusForCamera->faceAngle[1] - 0x4000), 0.05f);
} else {
approach_f32_asymptotic_bool(&gNewCamera.panX, 0, 0.05f);
approach_f32_asymptotic_bool(&gNewCamera.panZ, 0, 0.05f);
@ -538,7 +538,7 @@ static void newcam_level_bounds(void) {
static void newcam_position_cam(void) {
f32 floorY = 0;
f32 floorY2 = 0;
if (!(gMarioState->action & ACT_FLAG_SWIMMING)) {
if (!(gMarioState->statusForCamera->action & ACT_FLAG_SWIMMING)) {
calc_y_to_curr_floor(&floorY, 1.f, 200.f, &floorY2, 0.9f, 200.f);
}
@ -549,9 +549,9 @@ static void newcam_position_cam(void) {
// Fetch Mario's current position.
// Not hardcoded just for the sake of flexibility, though this specific bit is temp,
// because it won't always want to be focusing on Mario.
gNewCamera.posTarget[0] = gMarioState->pos[0];
gNewCamera.posTarget[1] = gMarioState->pos[1] + NEWCAM_MARIO_HEIGHT;
gNewCamera.posTarget[2] = gMarioState->pos[2];
gNewCamera.posTarget[0] = gMarioState->statusForCamera->pos[0];
gNewCamera.posTarget[1] = gMarioState->statusForCamera->pos[1] + NEWCAM_MARIO_HEIGHT;
gNewCamera.posTarget[2] = gMarioState->statusForCamera->pos[2];
// These will set the position of the camera to where Mario is supposed to be,
// minus adjustments for where the camera should be, on top of.
@ -607,7 +607,7 @@ static void newcam_apply_values(struct Camera *c) {
// The ingame cutscene system is such a spaghetti mess I actually have to resort to something as stupid as this to cover every base.
static void newcam_update_camera_yaw(struct Camera *c, bool useMarioYaw) {
if (useMarioYaw) {
gNewCamera.yaw = -gMarioState->faceAngle[1] - 0x4000;
gNewCamera.yaw = -gMarioState->statusForCamera->faceAngle[1] - 0x4000;
} else {
gNewCamera.yaw = -c->yaw + 0x4000;
}

View file

@ -1633,6 +1633,12 @@ s32 update_boss_fight_camera(struct Camera *c, Vec3f focus, Vec3f pos) {
if ((o = gSecondCameraFocus) != NULL) {
object_pos_to_vec3f(secondFocus, o);
heldState = o->oHeldState;
// for coop: if bowser is being held by someone else, don't alter the camera to prevent camera oscillations
if (gMarioStates[0].heldObj == NULL) {
heldState = 0;
}
} else {
// If no boss is there, just rotate around the area's center point.
secondFocus[0] = c->areaCenX;
@ -10947,10 +10953,12 @@ void cutscene_palette_editor(struct Camera *c) {
return;
}
bool capMissing = !(m->flags & (MARIO_CAP_ON_HEAD | MARIO_CAP_IN_HAND));
// Press the Z bind to toggle cap
static bool pressed = false;
if (gInteractablePad.button & PAD_BUTTON_Z) {
if (!pressed && m->action == ACT_IDLE) {
if (!capMissing && !pressed && m->action == ACT_IDLE) {
set_mario_action(m, ACT_PALETTE_EDITOR_CAP, (m->flags & MARIO_CAP_ON_HEAD) != 0);
}
pressed = true;
@ -10962,8 +10970,10 @@ void cutscene_palette_editor(struct Camera *c) {
if (gDjuiPaletteToggle) {
djui_base_set_visible(
&gDjuiPaletteToggle->base,
m->action == ACT_IDLE ||
m->action == ACT_PALETTE_EDITOR_CAP
(
m->action == ACT_IDLE ||
m->action == ACT_PALETTE_EDITOR_CAP
) && !capMissing
);
}
@ -12249,7 +12259,7 @@ static u8 rom_hack_cam_can_see_mario(Vec3f desiredPos) {
f32 mDist;
s16 mPitch;
s16 mYaw;
vec3f_get_dist_and_angle(desiredPos, gMarioStates[0].pos, &mDist, &mPitch, &mYaw);
vec3f_get_dist_and_angle(desiredPos, sMarioCamState->pos, &mDist, &mPitch, &mYaw);
s16 degreeMult = sRomHackZoom ? 7 : 5;
@ -12379,7 +12389,7 @@ void mode_rom_hack_camera(struct Camera *c) {
// Thank you hackersm64
if (gRomhackCameraSettings.dpad) {
if (gMarioStates[0].controller->buttonPressed & U_JPAD) {
sRomHackYaw = DEGREES(180 + 90) - gMarioStates[0].faceAngle[1];
sRomHackYaw = DEGREES(180 + 90) - sMarioCamState->faceAngle[1];
} else if (gMarioStates[0].controller->buttonDown & L_JPAD) {
sRomHackYaw -= DEGREES(0.5) * (camera_config_is_x_inverted() ? 1 : -1);
} else if (gMarioStates[0].controller->buttonDown & R_JPAD) {
@ -12408,7 +12418,7 @@ void mode_rom_hack_camera(struct Camera *c) {
// figure out desired position
f32 desiredDist = sRomHackZoom ? gRomhackCameraSettings.zoomedInDist : gRomhackCameraSettings.zoomedOutDist;
f32 desiredHeight = sRomHackZoom ? gRomhackCameraSettings.zoomedInHeight : gRomhackCameraSettings.zoomedOutHeight;
f32* mPos = &gMarioStates[0].pos[0];
f32* mPos = &sMarioCamState->pos[0];
pos[0] = mPos[0] + coss(sRomHackYaw) * desiredDist;
pos[1] = mPos[1] + desiredHeight;
pos[2] = mPos[2] + sins(sRomHackYaw) * desiredDist;
@ -12443,9 +12453,9 @@ void mode_rom_hack_camera(struct Camera *c) {
vec3f_normalize(dir);
// start at mario
c->pos[0] = gMarioStates[0].pos[0];
c->pos[1] = gMarioStates[0].pos[1] + 150;
c->pos[2] = gMarioStates[0].pos[2];
c->pos[0] = sMarioCamState->pos[0];
c->pos[1] = sMarioCamState->pos[1] + 150;
c->pos[2] = sMarioCamState->pos[2];
rom_hack_cam_walk(c->pos, dir, desiredDist);
}
@ -12489,8 +12499,8 @@ s32 update_rom_hack_camera(struct Camera *c, Vec3f focus, Vec3f pos) {
// if rom hack camera was just set, figure out the yaw to use
if (!sRomHackIsUpdate) {
sRomHackYaw = DEGREES(90) - atan2s(
c->pos[2] - gMarioStates[0].pos[2],
c->pos[0] - gMarioStates[0].pos[0]);
c->pos[2] - sMarioCamState->pos[2],
c->pos[0] - sMarioCamState->pos[0]);
sRomHackYaw = (sRomHackYaw / DEGREES(45)) * DEGREES(45);
}

View file

@ -35,7 +35,7 @@ struct Character gCharacters[CT_MAX] = {
.type = CT_MARIO,
.name = "Mario",
.hudHead = '(',
.hudHeadTexture = { .texture = (Texture*)texture_hud_char_mario_head, .bitSize = 8, .width = 16, .height = 16, .name = "texture_hud_char_mario_head" },
.hudHeadTexture = { .texture = texture_hud_char_mario_head, .width = 16, .height = 16, .format = G_IM_FMT_RGBA, .size = G_IM_SIZ_16b, .name = "texture_hud_char_mario_head" },
.cameraHudHead = GLYPH_CAM_MARIO_HEAD,
.modelId = MODEL_MARIO,
.capModelId = MODEL_MARIOS_CAP,
@ -101,7 +101,7 @@ struct Character gCharacters[CT_MAX] = {
.type = CT_LUIGI,
.name = "Luigi",
.hudHead = ')',
.hudHeadTexture = { .texture = (Texture*)texture_hud_char_luigi_head, .bitSize = 8, .width = 16, .height = 16, .name = "texture_hud_char_luigi_head" },
.hudHeadTexture = { .texture = texture_hud_char_luigi_head, .width = 16, .height = 16, .format = G_IM_FMT_RGBA, .size = G_IM_SIZ_16b, .name = "texture_hud_char_luigi_head" },
.cameraHudHead = GLYPH_CAM_LUIGI_HEAD,
.modelId = MODEL_LUIGI,
.capModelId = MODEL_LUIGIS_CAP,
@ -167,7 +167,7 @@ struct Character gCharacters[CT_MAX] = {
.type = CT_TOAD,
.name = "Toad",
.hudHead = '|',
.hudHeadTexture = { .texture = (Texture*)texture_hud_char_toad_head, .bitSize = 8, .width = 16, .height = 16, .name = "texture_hud_char_toad_head" },
.hudHeadTexture = { .texture = texture_hud_char_toad_head, .width = 16, .height = 16, .format = G_IM_FMT_RGBA, .size = G_IM_SIZ_16b, .name = "texture_hud_char_toad_head" },
.cameraHudHead = GLYPH_CAM_TOAD_HEAD,
.modelId = MODEL_TOAD_PLAYER,
.capModelId = MODEL_TOADS_CAP,
@ -233,7 +233,7 @@ struct Character gCharacters[CT_MAX] = {
.type = CT_WALUIGI,
.name = "Waluigi",
.hudHead = ']',
.hudHeadTexture = { .texture = (Texture*)texture_hud_char_waluigi_head, .bitSize = 8, .width = 16, .height = 16, .name = "texture_hud_char_waluigi_head" },
.hudHeadTexture = { .texture = texture_hud_char_waluigi_head, .width = 16, .height = 16, .format = G_IM_FMT_RGBA, .size = G_IM_SIZ_16b, .name = "texture_hud_char_waluigi_head" },
.cameraHudHead = GLYPH_CAM_WALUIGI_HEAD,
.modelId = MODEL_WALUIGI,
.capModelId = MODEL_WALUIGIS_CAP,
@ -299,7 +299,7 @@ struct Character gCharacters[CT_MAX] = {
.type = CT_WARIO,
.name = "Wario",
.hudHead = '[',
.hudHeadTexture = { .texture = (Texture*)texture_hud_char_wario_head, .bitSize = 8, .width = 16, .height = 16, .name = "texture_hud_char_wario_head" },
.hudHeadTexture = { .texture = texture_hud_char_wario_head, .width = 16, .height = 16, .format = G_IM_FMT_RGBA, .size = G_IM_SIZ_16b, .name = "texture_hud_char_wario_head" },
.cameraHudHead = GLYPH_CAM_WARIO_HEAD,
.modelId = MODEL_WARIO,
.capModelId = MODEL_WARIOS_CAP,

View file

@ -63,8 +63,6 @@ static void first_person_camera_update(void) {
struct MarioState *m = &gMarioStates[0];
f32 sensX = 0.3f * camera_config_get_x_sensitivity();
f32 sensY = 0.4f * camera_config_get_y_sensitivity();
s16 invX = camera_config_is_x_inverted() ? 1 : -1;
s16 invY = camera_config_is_y_inverted() ? 1 : -1;
if (mouse_relative_enabled) {
// hack: make c buttons work for moving the camera
@ -79,7 +77,7 @@ static void first_person_camera_update(void) {
// update pitch
if (!gFirstPersonCamera.forcePitch) {
gFirstPersonCamera.pitch -= sensY * (invY * extStickY - 1.5f * mouse_y);
gFirstPersonCamera.pitch -= sensY * (extStickY - 1.5f * mouse_y);
gFirstPersonCamera.pitch = clamp(gFirstPersonCamera.pitch, -0x3F00, 0x3F00);
}
@ -88,7 +86,7 @@ static void first_person_camera_update(void) {
if (m->controller->buttonDown & L_TRIG && gFirstPersonCamera.centerL) {
gFirstPersonCamera.yaw = m->faceAngle[1] + 0x8000;
} else {
gFirstPersonCamera.yaw += sensX * (invX * extStickX - 1.5f * mouse_x);
gFirstPersonCamera.yaw += sensX * (extStickX - 1.5f * mouse_x);
}
}
}

View file

@ -141,6 +141,8 @@ u8 gMenuHoldKeyIndex = 0;
u8 gMenuHoldKeyTimer = 0;
s32 gDialogResponse = 0;
bool gPauseMenuHidden = false;
#if defined(VERSION_JP) || defined(VERSION_SH) || defined(VERSION_EU)
#ifdef VERSION_EU
#define CHCACHE_BUFLEN (8 * 8) // EU only converts 8x8
@ -471,9 +473,10 @@ f32 get_generic_dialog_width(u8* dialog) {
}
f32 get_generic_ascii_string_width(const char* ascii) {
u8 dialog[256] = { DIALOG_CHAR_TERMINATOR };
convert_string_ascii_to_sm64(dialog, ascii, false);
return get_generic_dialog_width(dialog);
u8 *str = convert_string_ascii_to_sm64(NULL, ascii, false);
f32 width = get_generic_dialog_width(str);
free(str);
return width;
}
f32 get_generic_dialog_height(u8* dialog) {
@ -487,15 +490,16 @@ f32 get_generic_dialog_height(u8* dialog) {
}
f32 get_generic_ascii_string_height(const char* ascii) {
u8 dialog[256] = { DIALOG_CHAR_TERMINATOR };
convert_string_ascii_to_sm64(dialog, ascii, false);
return get_generic_dialog_height(dialog);
u8 *str = convert_string_ascii_to_sm64(NULL, ascii, false);
f32 height = get_generic_dialog_height(str);
free(str);
return height;
}
void print_generic_ascii_string(s16 x, s16 y, const char* ascii) {
u8 dialog[256] = { DIALOG_CHAR_TERMINATOR };
convert_string_ascii_to_sm64(dialog, ascii, false);
print_generic_string(x, y, dialog);
u8 *str = convert_string_ascii_to_sm64(NULL, ascii, false);
print_generic_string(x, y, str);
free(str);
}
#if defined(VERSION_JP) || defined(VERSION_SH)
@ -1077,9 +1081,8 @@ void handle_special_dialog_text(s32 dialogID) { // dialog ID tables, in order
}
}
static u8 sHookString[255];
static bool sOverrideDialogString = false;
void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu);
static u8 *sOverrideDialogHookString = NULL;
bool handle_dialog_hook(s32 dialogId) {
bool openDialogBox = true;
const char *dialogTextOverride = NULL;
@ -1088,8 +1091,13 @@ bool handle_dialog_hook(s32 dialogId) {
if (gCamera->cutscene == CUTSCENE_READ_MESSAGE) { gCamera->cutscene = 0; }
return false;
}
sOverrideDialogString = dialogTextOverride != NULL;
if (sOverrideDialogString) { convert_string_ascii_to_sm64(sHookString, dialogTextOverride, false); }
free(sOverrideDialogHookString);
if (dialogTextOverride != NULL) {
sOverrideDialogHookString = convert_string_ascii_to_sm64(NULL, dialogTextOverride, false);
} else {
sOverrideDialogHookString = NULL;
}
return true;
}
@ -1443,7 +1451,7 @@ void handle_dialog_text_and_pages(s8 colorMode, struct DialogEntry *dialog, s8 l
u8 strChar;
u8 *str = sOverrideDialogString ? sHookString : segmented_to_virtual(dialog->str);
u8 *str = sOverrideDialogHookString != NULL ? sOverrideDialogHookString : segmented_to_virtual(dialog->str);
s8 lineNum = 1;
s8 totalLines;
@ -2179,7 +2187,7 @@ void do_cutscene_handler(void) {
void print_peach_letter_message(void) {
struct DialogEntry *dialog = dialog_table_get(gDialogID);
const u8* str = sOverrideDialogString ? sHookString : dialog->str;
const u8* str = sOverrideDialogHookString != NULL ? sOverrideDialogHookString : dialog->str;
create_dl_translation_matrix(MENU_MTX_PUSH, 97.0f, 118.0f, 0);
@ -2969,7 +2977,7 @@ s16 render_pause_courses_and_castle(void) {
}
break;
case DIALOG_STATE_VERTICAL:
if (!gDjuiPanelPauseCreated) {
if (!gDjuiPanelPauseCreated && !gPauseMenuHidden) {
shade_screen();
render_pause_my_score_coins();
render_pause_red_coins();
@ -3010,7 +3018,7 @@ s16 render_pause_courses_and_castle(void) {
}
break;
case DIALOG_STATE_HORIZONTAL:
if (!gDjuiPanelPauseCreated) {
if (!gDjuiPanelPauseCreated && !gPauseMenuHidden) {
shade_screen();
print_hud_pause_colorful_str();

View file

@ -111,6 +111,7 @@ enum DialogSpecialChars {
DIALOG_CHAR_TERMINATOR = 0xFF
};
extern s8 gDialogBoxState;
extern s32 gDialogResponse;
extern u16 gDialogColorFadeTimer;
extern s8 gLastDialogLineNum;
@ -133,13 +134,13 @@ extern u8 gDialogTextColorG;
extern u8 gDialogTextColorB;
extern u8 gDialogTextColorA;
extern s16 gMenuMode;
void create_dl_identity_matrix(void);
void create_dl_translation_matrix(s8 pushOp, f32 x, f32 y, f32 z);
void create_dl_rotation_matrix(s8 pushOp, f32 a, f32 x, f32 y, f32 z);
void create_dl_ortho_matrix(void);
void render_generic_char(u8 c);
u8 str_ascii_char_to_dialog(char c);
void str_ascii_to_dialog(const char* string, u8* dialog, u16 length);
f32 get_generic_dialog_width(u8* dialog);
f32 get_generic_ascii_string_width(const char* ascii);
f32 get_generic_dialog_height(u8* dialog);
@ -184,6 +185,8 @@ void do_cutscene_handler(void);
void render_hud_cannon_reticle(void);
void reset_red_coins_collected(void);
s16 render_menus_and_dialogs(void);
/* |description|The internal function used by SM64 which plays a tune whenever boss, KtQ, etc dialog is read.|descriptionEnd| */
void handle_special_dialog_text(s32 dialogID);
void create_dl_scale_matrix(s8 pushOp, f32 x, f32 y, f32 z);
/* |description|Dialog box customization: Sets the minimum width for a dialog box|descriptionEnd| */
void set_min_dialog_width(s16 width);

View file

@ -456,6 +456,7 @@ void mario_retrieve_cap(struct MarioState* m) {
if (!m) { return; }
mario_drop_held_object(m);
save_file_clear_flags(SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_UKIKI);
m->cap &= ~(SAVE_FLAG_CAP_ON_KLEPTO | SAVE_FLAG_CAP_ON_UKIKI);
m->flags &= ~MARIO_CAP_ON_HEAD;
m->flags |= MARIO_NORMAL_CAP | MARIO_CAP_IN_HAND;
}
@ -2156,6 +2157,10 @@ u32 interact_cap(struct MarioState *m, UNUSED u32 interactType, struct Object *o
capTime = gLevelValues.wingCapDuration;
capMusic = SEQUENCE_ARGS(4, gLevelValues.wingCapSequence);
break;
case MARIO_NORMAL_CAP:
m->cap = 0;
break;
}
if (capTime > m->capTimer) {

View file

@ -17,107 +17,229 @@ extern s32 gInGameLanguage;
#include "eu_translation.h"
#endif
const struct { const char *str; u8 c; u8 menu; } sSm64CharMap[] = {
// Digits
{ "0", 0x00, 1 }, { "1", 0x01, 1 }, { "2", 0x02, 1 }, { "3", 0x03, 1 }, { "4", 0x04, 1 },
{ "5", 0x05, 1 }, { "6", 0x06, 1 }, { "7", 0x07, 1 }, { "8", 0x08, 1 }, { "9", 0x09, 1 },
// Capital letters
{ "A", 0x0A, 1 }, { "B", 0x0B, 1 }, { "C", 0x0C, 1 }, { "D", 0x0D, 1 }, { "E", 0x0E, 1 },
{ "F", 0x0F, 1 }, { "G", 0x10, 1 }, { "H", 0x11, 1 }, { "I", 0x12, 1 }, { "J", 0x13, 1 },
{ "K", 0x14, 1 }, { "L", 0x15, 1 }, { "M", 0x16, 1 }, { "N", 0x17, 1 }, { "O", 0x18, 1 },
{ "P", 0x19, 1 }, { "Q", 0x1A, 1 }, { "R", 0x1B, 1 }, { "S", 0x1C, 1 }, { "T", 0x1D, 1 },
{ "U", 0x1E, 1 }, { "V", 0x1F, 1 }, { "W", 0x20, 1 }, { "X", 0x21, 1 }, { "Y", 0x22, 1 },
{ "Z", 0x23, 1 },
// Letters
{ "a", 0x24, 0 }, { "b", 0x25, 0 }, { "c", 0x26, 0 }, { "d", 0x27, 0 }, { "e", 0x28, 0 },
{ "f", 0x29, 0 }, { "g", 0x2A, 0 }, { "h", 0x2B, 0 }, { "i", 0x2C, 0 }, { "j", 0x2D, 0 },
{ "k", 0x2E, 0 }, { "l", 0x2F, 0 }, { "m", 0x30, 0 }, { "n", 0x31, 0 }, { "o", 0x32, 0 },
{ "p", 0x33, 0 }, { "q", 0x34, 0 }, { "r", 0x35, 0 }, { "s", 0x36, 0 }, { "t", 0x37, 0 },
{ "u", 0x38, 0 }, { "v", 0x39, 0 }, { "w", 0x3A, 0 }, { "x", 0x3B, 0 }, { "y", 0x3C, 0 },
{ "z", 0x3D, 0 },
// Punctuation
{ ":", 0xE6, 0 }, // colon
{ ")(", 0xE2, 0 }, // close-open parentheses
{ "<<", 0xF5, 0 }, // double quote open
{ ">>", 0xF6, 0 }, // double quote close
{ "\'", 0x3E, 1 }, // apostrophe
{ ".", 0x3F, 1 }, // period
{ ",", 0x6F, 1 }, // comma
{ " ", 0x9E, 1 }, // space
{ "-", 0x9F, 1 }, // dash
{ "(", 0xE1, 0 }, // open parentheses
{ ")", 0xE3, 0 }, // close parentheses
{ "&", 0xE5, 1 }, // ampersand
{ "!", 0xF2, 1 }, // exclamation mark
{ "%", 0xF3, 0 }, // percent
{ "?", 0xF4, 1 }, // question mark
{ "~", 0xF7, 0 }, // tilde
// Symbols
{ "/", 0xD0, 0 },
{ "the", 0xD1, 0 },
{ "you", 0xD2, 0 },
{ "[%]", 0xE0, 0 }, // The number of extra stars required to unlock a star door
{ "[A]", 0x54, 0 }, // bold A
{ "[B]", 0x55, 0 }, // bold B
{ "[C]", 0x56, 0 }, // bold C
{ "[Z]", 0x57, 0 }, // bold Z
{ "[R]", 0x58, 0 }, // bold R
{ "+", 0xE4, 0 }, // left-right arrow
{ "^", 0x50, 0 }, // up arrow
{ "|", 0x51, 0 }, // down arrow
{ "<", 0x52, 0 }, // left arrow
{ ">", 0x53, 0 }, // right arrow
{ "$", 0xF9, 1 }, // coin
{ "", 0xFA, 1 }, // star filled
{ "@", 0xFA, 1 }, // star filled (both ★ and @ match 0xFA)
{ "*", 0xFB, 1 }, // multiply
{ "", 0xFC, 0 }, // interpunct (unused)
{ "=", 0xFD, 0 }, // star empty
{ "\n", 0xFE, 1 }, // New line
{ NULL, 0xFF, 1 }, // Null terminator
struct Sm64Char {
const char *str;
u32 len;
u8 c;
bool menu;
};
#define SM64_CHAR(_str, _c, _menu) { \
.str = _str, \
.len = sizeof(_str) - 1, \
.c = _c, \
.menu = _menu, \
}
static const struct Sm64Char sSm64CharMap[] = {
// Digits
SM64_CHAR("0", 0x00, true),
SM64_CHAR("1", 0x01, true),
SM64_CHAR("2", 0x02, true),
SM64_CHAR("3", 0x03, true),
SM64_CHAR("4", 0x04, true),
SM64_CHAR("5", 0x05, true),
SM64_CHAR("6", 0x06, true),
SM64_CHAR("7", 0x07, true),
SM64_CHAR("8", 0x08, true),
SM64_CHAR("9", 0x09, true),
// Capital letters
SM64_CHAR("A", 0x0A, true),
SM64_CHAR("B", 0x0B, true),
SM64_CHAR("C", 0x0C, true),
SM64_CHAR("D", 0x0D, true),
SM64_CHAR("E", 0x0E, true),
SM64_CHAR("F", 0x0F, true),
SM64_CHAR("G", 0x10, true),
SM64_CHAR("H", 0x11, true),
SM64_CHAR("I", 0x12, true),
SM64_CHAR("J", 0x13, true),
SM64_CHAR("K", 0x14, true),
SM64_CHAR("L", 0x15, true),
SM64_CHAR("M", 0x16, true),
SM64_CHAR("N", 0x17, true),
SM64_CHAR("O", 0x18, true),
SM64_CHAR("P", 0x19, true),
SM64_CHAR("Q", 0x1A, true),
SM64_CHAR("R", 0x1B, true),
SM64_CHAR("S", 0x1C, true),
SM64_CHAR("T", 0x1D, true),
SM64_CHAR("U", 0x1E, true),
SM64_CHAR("V", 0x1F, true),
SM64_CHAR("W", 0x20, true),
SM64_CHAR("X", 0x21, true),
SM64_CHAR("Y", 0x22, true),
SM64_CHAR("Z", 0x23, true),
// Letters
SM64_CHAR("a", 0x24, false),
SM64_CHAR("b", 0x25, false),
SM64_CHAR("c", 0x26, false),
SM64_CHAR("d", 0x27, false),
SM64_CHAR("e", 0x28, false),
SM64_CHAR("f", 0x29, false),
SM64_CHAR("g", 0x2A, false),
SM64_CHAR("h", 0x2B, false),
SM64_CHAR("i", 0x2C, false),
SM64_CHAR("j", 0x2D, false),
SM64_CHAR("k", 0x2E, false),
SM64_CHAR("l", 0x2F, false),
SM64_CHAR("m", 0x30, false),
SM64_CHAR("n", 0x31, false),
SM64_CHAR("o", 0x32, false),
SM64_CHAR("p", 0x33, false),
SM64_CHAR("q", 0x34, false),
SM64_CHAR("r", 0x35, false),
SM64_CHAR("s", 0x36, false),
SM64_CHAR("t", 0x37, false),
SM64_CHAR("u", 0x38, false),
SM64_CHAR("v", 0x39, false),
SM64_CHAR("w", 0x3A, false),
SM64_CHAR("x", 0x3B, false),
SM64_CHAR("y", 0x3C, false),
SM64_CHAR("z", 0x3D, false),
// Punctuation
SM64_CHAR(":", 0xE6, false), // colon
SM64_CHAR(")(", 0xE2, false), // close-open parentheses
SM64_CHAR("<<", 0xF5, false), // double quote open
SM64_CHAR(">>", 0xF6, false), // double quote close
SM64_CHAR("\'", 0x3E, true ), // apostrophe
SM64_CHAR(".", 0x3F, true ), // period
SM64_CHAR(",", 0x6F, true ), // comma
SM64_CHAR(" ", 0x9E, true ), // space
SM64_CHAR("-", 0x9F, true ), // dash
SM64_CHAR("(", 0xE1, false), // open parentheses
SM64_CHAR(")", 0xE3, false), // close parentheses
SM64_CHAR("&", 0xE5, true ), // ampersand
SM64_CHAR("!", 0xF2, true ), // exclamation mark
SM64_CHAR("%", 0xF3, false), // percent
SM64_CHAR("?", 0xF4, true ), // question mark
SM64_CHAR("~", 0xF7, false), // tilde
// Symbols
SM64_CHAR("/", 0xD0, false),
SM64_CHAR("the", 0xD1, false),
SM64_CHAR("you", 0xD2, false),
SM64_CHAR("[%]", 0xE0, false), // The number of extra stars required to unlock a star door
SM64_CHAR("[A]", 0x54, false), // bold A
SM64_CHAR("[B]", 0x55, false), // bold B
SM64_CHAR("[C]", 0x56, false), // bold C
SM64_CHAR("[Z]", 0x57, false), // bold Z
SM64_CHAR("[R]", 0x58, false), // bold R
SM64_CHAR("+", 0xE4, false), // left-right arrow
SM64_CHAR("^", 0x50, false), // up arrow
SM64_CHAR("|", 0x51, false), // down arrow
SM64_CHAR("<", 0x52, false), // left arrow
SM64_CHAR(">", 0x53, false), // right arrow
SM64_CHAR("$", 0xF9, true ), // coin
SM64_CHAR("", 0xFA, true ), // star filled
SM64_CHAR("@", 0xFA, true ), // star filled (both ★ and @ match 0xFA)
SM64_CHAR("*", 0xFB, true ), // multiply
SM64_CHAR("", 0xFC, false), // interpunct (unused)
SM64_CHAR("=", 0xFD, false), // star empty
SM64_CHAR("\n", 0xFE, true ), // New line
// SM64_CHAR(NULL, 0xFF, true ), // Null terminator
};
#define ASCII_TO_SM64_MAX_CHAR_SIZE 1
#define SM64_TO_ASCII_MAX_CHAR_SIZE 4
static const char *ascii_to_sm64_char(u8 *str64, const char *strAscii, bool menu) {
for (s32 i = 0; sSm64CharMap[i].str != NULL; ++i) {
if (menu && !sSm64CharMap[i].menu) { continue; }
if (strstr(strAscii, sSm64CharMap[i].str) == strAscii) {
*str64 = sSm64CharMap[i].c;
return strAscii + strlen(sSm64CharMap[i].str);
for (u32 i = 0; i < ARRAY_COUNT(sSm64CharMap); ++i) {
const struct Sm64Char *ch = &sSm64CharMap[i];
if (menu && !ch->menu) {
continue;
}
if (memcmp(strAscii, ch->str, ch->len) == 0) {
*str64 = ch->c;
return strAscii + ch->len;
}
}
*str64 = 0x9E;
return strAscii + 1;
}
static char *sm64_to_ascii_char(char *strAscii, const u8 *str64) {
for (s32 i = 0; sSm64CharMap[i].str != NULL; ++i) {
if (sSm64CharMap[i].c == *str64) {
s32 l = strlen(sSm64CharMap[i].str);
memcpy(strAscii, sSm64CharMap[i].str, l);
return strAscii + l;
static char *sm64_to_ascii_char(char *strAscii, u8 c) {
for (u32 i = 0; i < ARRAY_COUNT(sSm64CharMap); ++i) {
const struct Sm64Char *ch = &sSm64CharMap[i];
if (ch->c == c) {
memcpy(strAscii, ch->str, ch->len);
return strAscii + ch->len;
}
}
*strAscii = ' ';
return strAscii + 1;
}
void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu) {
for (; *strAscii != 0; str64++) {
strAscii = ascii_to_sm64_char(str64, strAscii, menu);
u8 *convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu) {
if (!strAscii) { return str64; }
// allocate string with maximum size
bool shouldResizeString = false;
if (!str64) {
str64 = malloc(ASCII_TO_SM64_MAX_CHAR_SIZE * strlen(strAscii) + 1);
if (!str64) {
return NULL;
}
shouldResizeString = true;
}
*str64 = 0xFF;
// convert string
u8 *str64End = str64;
for (; *strAscii != 0; str64End++) {
strAscii = ascii_to_sm64_char(str64End, strAscii, menu);
}
*(str64End++) = 0xFF;
// resize string if it was allocated by this function
if (shouldResizeString) {
u8 *resizedStr64 = realloc(str64, (size_t) (str64End - str64));
if (resizedStr64) {
str64 = resizedStr64;
}
}
return str64;
}
void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64) {
for (; *str64 != 0xFF; str64++) {
strAscii = sm64_to_ascii_char(strAscii, str64);
static inline size_t strlen64(const u8 *str64) {
const u8 *str64Begin = str64;
for (; *str64 != 0xFF; str64++);
return (size_t) (str64 - str64Begin);
}
char *convert_string_sm64_to_ascii(char *strAscii, const u8 *str64) {
if (!str64) { return strAscii; }
// allocate string with maximum size
bool shouldResizeString = false;
if (!strAscii) {
strAscii = malloc(SM64_TO_ASCII_MAX_CHAR_SIZE * strlen64(str64) + 1);
if (!strAscii) {
return NULL;
}
shouldResizeString = true;
}
*strAscii = 0;
// convert string
char *strAsciiEnd = strAscii;
for (; *str64 != 0xFF; str64++) {
strAsciiEnd = sm64_to_ascii_char(strAsciiEnd, *str64);
}
*(strAsciiEnd++) = 0;
// resize string if it was allocated by this function
if (shouldResizeString) {
char *resizedStrAscii = realloc(strAscii, (size_t) (strAsciiEnd - strAscii));
if (resizedStrAscii) {
strAscii = resizedStrAscii;
}
}
return strAscii;
}
static void capitalize_string_ascii(char *strAscii) {

View file

@ -7,8 +7,8 @@ void **get_course_name_table(void);
void **get_course_name_table_original(void);
void **get_act_name_table(void);
void **get_act_name_table_original(void);
void convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu);
void convert_string_sm64_to_ascii(char *strAscii, const u8 *str64);
u8 *convert_string_ascii_to_sm64(u8 *str64, const char *strAscii, bool menu);
char *convert_string_sm64_to_ascii(char *strAscii, const u8 *str64);
/* |description|
Returns the name of the level corresponding to `courseNum`, `levelNum` and `areaIndex` as an ASCII (human readable) string.
Set `charCase` to 1 to capitalize or -1 to decapitalize the returned string

View file

@ -249,7 +249,7 @@ u16 level_control_timer(s32 timerOp) {
return gHudDisplay.timer;
}
u32 pressed_pause(void) {
bool pressed_pause(void) {
if (gServerSettings.pauseAnywhere) {
if (get_dialog_id() == DIALOG_NONE && sCurrPlayMode == PLAY_MODE_NORMAL && sDelayedWarpOp == WARP_OP_NONE) {
return gPlayer1Controller->buttonPressed & START_BUTTON;
@ -264,7 +264,7 @@ u32 pressed_pause(void) {
}
}
return FALSE;
return false;
}
void set_play_mode(s16 playMode) {

View file

@ -178,6 +178,8 @@ enum HUDDisplayFlag {
/* |description|Returns if the level timer is running|descriptionEnd| */
u8 level_control_timer_running(void);
u16 level_control_timer(s32 timerOp);
/* |description|Checks if the start button has been pressed as well as some other conditions for opening the pause menu depending on if pause anywhere is enabled|descriptionEnd|*/
bool pressed_pause(void);
/* |description|Fades into a special warp with `arg` and using `color`|descriptionEnd| */
void fade_into_special_warp(u32 arg, u32 color);
void load_level_init_text(u32 arg);

View file

@ -370,7 +370,6 @@ void cutscene_put_cap_on(struct MarioState *m) {
m->flags &= ~MARIO_CAP_IN_HAND;
m->flags |= MARIO_CAP_ON_HEAD;
play_sound(SOUND_ACTION_UNKNOWN43E, m->marioObj->header.gfx.cameraToObject);
m->cap = 0;
}
/**

View file

@ -1162,13 +1162,20 @@ s32 act_first_person(struct MarioState *m) {
}
s32 mario_exit_palette_editor(struct MarioState *m, struct Camera *c) {
if (!(m->flags & (MARIO_CAP_ON_HEAD | MARIO_CAP_IN_HAND))) {
return FALSE;
}
switch (c->paletteEditorCapState) {
case 0: return FALSE;
case 1: cutscene_put_cap_on(m); break;
case 2: cutscene_take_cap_off(m); break;
}
c->paletteEditorCapState = 0;
return set_mario_action(m, ACT_IDLE, 0);
if (m->action == ACT_PALETTE_EDITOR_CAP) {
set_mario_action(m, ACT_IDLE, 0);
}
return TRUE;
}
s32 act_palette_editor_cap(struct MarioState *m) {

View file

@ -788,8 +788,11 @@ static Gfx *geo_mario_create_player_colors_dl(s32 index, Gfx *capEnemyGfx, Gfx *
if (gfx) {
Gfx *gfxp = gfx;
for (s32 part = 0; part != PLAYER_PART_MAX; ++part) {
gSPLight(gfxp++, &gNetworkPlayerColors[index].parts[part].l, (2 * (part + 1)) + 1);
gSPLight(gfxp++, &gNetworkPlayerColors[index].parts[part].a, (2 * (part + 1)) + 2);
Lights1 *light = alloc_display_list(sizeof(Lights1));
if (!light) { return NULL; }
*light = gNetworkPlayerColors[index].parts[part];
gSPLight(gfxp++, &light->l, (2 * (part + 1)) + 1);
gSPLight(gfxp++, &light->a, (2 * (part + 1)) + 2);
}
if (capEnemyGfx) { gSPDisplayList(gfxp++, capEnemyGfx); }
if (capEnemyDecalGfx) { gSPDisplayList(gfxp++, capEnemyDecalGfx); }

View file

@ -36,9 +36,9 @@ u32 mario_update_moving_sand(struct MarioState *m);
u32 mario_update_windy_ground(struct MarioState *m);
/* |description|Sets all of Mario's velocity variables to 0 and sets his Y position to the floor height|descriptionEnd| */
void stop_and_set_height_to_floor(struct MarioState *m);
/* |description|Performs a full Mario stationary physics step (4 substeps) and returns an `GROUND_STEP_*` result|descriptionEnd| */
/* |description|Performs a full Mario stationary physics step (4 substeps) and returns a `GROUND_STEP_*` result|descriptionEnd| */
s32 stationary_ground_step(struct MarioState *m);
/* |description|Performs a full Mario ground physics step (4 substeps) and returns an `GROUND_STEP_*` result|descriptionEnd| */
/* |description|Performs a full Mario ground physics step (4 substeps) and returns a `GROUND_STEP_*` result|descriptionEnd| */
s32 perform_ground_step(struct MarioState *m);
/* |description|Performs a full Mario air physics step (4 substeps) and returns an `AIR_STEP_*` result|descriptionEnd| */
s32 perform_air_step(struct MarioState *m, u32 stepArg);

View file

@ -220,6 +220,32 @@ void *growing_array_alloc(struct GrowingArray *array, u32 size) {
return NULL;
}
void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count) {
if (array && array->buffer && count > 0 &&
(to < from || to > from + count) &&
(from + count) <= array->count && to <= array->count) {
void **temp = malloc(sizeof(void *) * count);
if (!temp) { return; }
// Copy elements to move to temporary buffer
memcpy(temp, array->buffer + from, sizeof(void *) * count);
// Remove copied elements from the array
memmove(array->buffer + from, array->buffer + (from + count), sizeof(void *) * (array->count - (from + count)));
// Make place for the copied elements
// If moving left to right, account for the removed elements
if (to > from) { to -= count; }
memmove(array->buffer + (to + count), array->buffer + to, sizeof(void *) * (array->count - (to + count)));
// Insert copied elements
memcpy(array->buffer + to, temp, sizeof(void *) * count);
free(temp);
}
}
void growing_array_free(struct GrowingArray **array) {
if (*array) {
for (u32 i = 0; i != (*array)->capacity; ++i) {

View file

@ -77,6 +77,7 @@ void growing_pool_free_pool(struct GrowingPool *pool);
struct GrowingArray *growing_array_init(struct GrowingArray *array, u32 capacity, GrowingArrayAllocFunc alloc, GrowingArrayFreeFunc free);
void *growing_array_alloc(struct GrowingArray *array, u32 size);
void growing_array_move(struct GrowingArray *array, u32 from, u32 to, u32 count);
void growing_array_free(struct GrowingArray **array);
void growing_array_debug_print(struct GrowingArray *array, const char *name, s32 x, s32 y);

View file

@ -122,27 +122,6 @@ const BehaviorScript *gCurBhvCommand;
*/
s16 gPrevFrameObjectCount;
/**
* The total number of surface nodes allocated (a node is allocated for each
* spatial partition cell that a surface intersects).
*/
s32 gSurfaceNodesAllocated;
/**
* The total number of surfaces allocated.
*/
s32 gSurfacesAllocated;
/**
* The number of nodes that have been created for surfaces.
*/
s32 gNumStaticSurfaceNodes;
/**
* The number of surfaces in the pool.
*/
s32 gNumStaticSurfaces;
struct Object* gCheckingSurfaceCollisionsForObject = NULL;
s16 gCheckingSurfaceCollisionsForCamera;
s16 gFindFloorIncludeSurfaceIntangible;

View file

@ -91,11 +91,6 @@ extern struct Object *gCurrentObject;
extern const BehaviorScript *gCurBhvCommand;
extern s16 gPrevFrameObjectCount;
extern s32 gSurfaceNodesAllocated;
extern s32 gSurfacesAllocated;
extern s32 gNumStaticSurfaceNodes;
extern s32 gNumStaticSurfaces;
extern struct Object* gCheckingSurfaceCollisionsForObject;
extern s16 gCheckingSurfaceCollisionsForCamera;
extern s16 gFindFloorIncludeSurfaceIntangible;

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