diff --git a/autogen/convert_constants.py b/autogen/convert_constants.py index 5d1ab198c..404414a27 100644 --- a/autogen/convert_constants.py +++ b/autogen/convert_constants.py @@ -57,15 +57,49 @@ exclude_constants = { "src/game/obj_behaviors.c": [ "^o$" ], "src/pc/djui/djui_console.h": [ "CONSOLE_MAX_TMP_BUFFER" ], "src/pc/lua/smlua_hooks.h": [ "MAX_HOOKED_MOD_MENU_ELEMENTS" ], - "src/pc/djui/djui_panel_menu.h": [ "RAINBOW_TEXT_LEN" ], - "include/PR/gbi.h": ["RM_AA_", "G_RM_", "G_CC_"] + "src/pc/djui/djui_panel_menu.h": [ "RAINBOW_TEXT_LEN" ] } include_constants = { "include/geo_commands.h": [ "BACKGROUND" ], "include/level_commands.h": [ "WARP_CHECKPOINT", "WARP_NO_CHECKPOINT" ], "src/audio/external.h": [ "SEQ_PLAYER", "DS_" ], - "src/pc/mods/mod_storage.h": [ "MAX_KEYS", "MAX_KEY_VALUE_LENGTH" ] + "src/pc/mods/mod_storage.h": [ "MAX_KEYS", "MAX_KEY_VALUE_LENGTH" ], + "include/PR/gbi.h": [ + "^G_NOOP$", + "^G_SETOTHERMODE_H$", + "^G_SETOTHERMODE_L$", + "^G_ENDDL$", + "^G_DL$", + "^G_MOVEMEM$", + "^G_MOVEWORD$", + "^G_MTX$", + "^G_GEOMETRYMODE$", + "^G_POPMTX$", + "^G_TEXTURE$", + "^G_COPYMEM$", + "^G_VTX$", + "^G_TRI1$", + "^G_TRI2$", + "^G_SETCIMG$", + "^G_SETZIMG$", + "^G_SETTIMG$", + "^G_SETCOMBINE$", + "^G_SETENVCOLOR$", + "^G_SETPRIMCOLOR$", + "^G_SETBLENDCOLOR$", + "^G_SETFOGCOLOR$", + "^G_SETFILLCOLOR$", + "^G_FILLRECT$", + "^G_SETTILE$", + "^G_LOADTILE$", + "^G_LOADBLOCK$", + "^G_SETTILESIZE$", + "^G_LOADTLUT$", + "^G_SETSCISSOR$", + "^G_TEXRECTFLIP$", + "^G_TEXRECT$", + ] } pretend_find = [ @@ -80,6 +114,13 @@ overrideConstant = { 'VERSION_REGION': '"US"', } forced_defines = ['F3DEX_GBI_2'] +defined_values = { + 'VERSION_US': True, + 'VERSION_EU': False, + 'VERSION_JP': False, + 'VERSION_SH': False, + 'F3DEX_GBI_2': True, +} ############################################################################ @@ -384,7 +425,7 @@ def doc_files(processed_files): ############################################################################ -def def_constant(processed_constant): +def def_constant(processed_constant, skip_constant): global totalConstants constants = processed_constant s = '' @@ -393,7 +434,7 @@ def def_constant(processed_constant): if is_enum: constants = processed_constant['constants'] if len(constants) == 0: - return '' + return '', skip_constant id = translate_to_def(processed_constant['identifier']) klen = 0 vlen = 0 @@ -407,10 +448,18 @@ def def_constant(processed_constant): s += '\n--- @alias %s\n' % id for c in constants: s += '--- | `%s`\n' % c[0] - return s + return s, skip_constant for c in [processed_constant]: if c[0].startswith('#'): + if c[0].startswith('#ifdef'): + skip_constant = not defined_values[c[0].split()[1]] + elif c[0].startswith('#else'): + skip_constant = not skip_constant + elif c[0].startswith('#endif'): + skip_constant = False + continue + if skip_constant: continue if '"' in c[1]: s += '\n--- @type string\n' @@ -419,7 +468,7 @@ def def_constant(processed_constant): s += '%s = %s\n' % (c[0], c[1]) totalConstants += 1 - return s + return s, skip_constant def build_to_def(processed_files): s = '-- AUTOGENERATED FOR CODE EDITORS --\n\n' @@ -429,8 +478,10 @@ def build_to_def(processed_files): for file in processed_files: constants = file['constants'] + skip_constant = False for c in constants: - s += def_constant(c) + cs, skip_constant = def_constant(c, skip_constant) + s += cs return s diff --git a/autogen/convert_functions.py b/autogen/convert_functions.py index eba7c0193..ab836c52e 100644 --- a/autogen/convert_functions.py +++ b/autogen/convert_functions.py @@ -125,6 +125,7 @@ override_disallowed_functions = { "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" ], "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" ], @@ -758,11 +759,30 @@ N/A ## [gfx_set_command](#gfx_set_command) -Sets the specified display list command on the display list given. +Sets a display list command on the display list given. -### Lua Example +If `command` includes parameter specifiers (subsequences beginning with `%`), the additional arguments following `command` are converted and inserted in `command` replacing their respective specifiers. + +The number of provided parameters must be equal to the number of specifiers in `command`, and the order of parameters must be the same as the specifiers. + +The following specifiers are allowed: +- `%i` for an `integer` parameter +- `%s` for a `string` parameter +- `%v` for a `Vtx` parameter +- `%t` for a `Texture` parameter +- `%g` for a `Gfx` parameter + +### Lua Examples + +Plain string: ```lua -gfx_set_command(gfx, "gsDPSetEnvColor", 0x00, 0xFF, 0x00, 0xFF) +gfx_set_command(gfx, "gsDPSetEnvColor(0x00, 0xFF, 0x00, 0xFF)") +``` + +With parameter specifiers: +```lua +r, g, b, a = 0x00, 0xFF, 0x00, 0xFF +gfx_set_command(gfx, "gsDPSetEnvColor(%i, %i, %i, %i)", r, g, b, a) ``` ### Parameters @@ -770,7 +790,7 @@ gfx_set_command(gfx, "gsDPSetEnvColor", 0x00, 0xFF, 0x00, 0xFF) | ----- | ---- | | gfx | [Gfx](structs.md#Gfx) | | command | `string` | -| (Any number of arguments) | `integer` | +| parameters... | any of `integer`, `string`, `Gfx`, `Texture`, `Vtx` | ### Returns - None diff --git a/autogen/convert_structs.py b/autogen/convert_structs.py index 40e882c15..cb2e9dfde 100644 --- a/autogen/convert_structs.py +++ b/autogen/convert_structs.py @@ -165,7 +165,7 @@ sLuaManuallyDefinedStructs = [{ override_types = { "Gwords": "Gfx", - "Vtx_t": "Vtx" + "Vtx_L": "Vtx" } reversed_override_types = {v: k for k, v in override_types.items()} @@ -275,6 +275,7 @@ def table_to_string(table): def parse_struct(struct_str, sortFields = True): struct = {} + struct_str = strip_anonymous_blocks(struct_str) # Allow unions and sub-structs to be accessed match = re.match(r"struct\s*(\w+)?\s*{(.*?)}\s*(\w+)?\s*", struct_str.replace("typedef ", ""), re.DOTALL) struct_name, body, trailing_name = match.groups() identifier = struct_name if struct_name else trailing_name diff --git a/autogen/lua_definitions/constants.lua b/autogen/lua_definitions/constants.lua index cda368310..e2bd806b2 100644 --- a/autogen/lua_definitions/constants.lua +++ b/autogen/lua_definitions/constants.lua @@ -2610,9 +2610,6 @@ DS_NONE = 0xff --- @type DialogSound --- | `DS_MAX` --- | `DS_NONE` ---- @type integer -DS_DIFF = DS_KOOPA - --- @type integer DS_DIFF = DS_TUXIE @@ -2631,30 +2628,18 @@ G_COPYMEM = 0xd2 --- @type integer G_NOOP = 0x00 ---- @type integer -G_RDPHALF_2 = 0xf1 - --- @type integer G_SETOTHERMODE_H = 0xe3 --- @type integer G_SETOTHERMODE_L = 0xe2 ---- @type integer -G_RDPHALF_1 = 0xe1 - ---- @type integer -G_SPNOOP = 0xe0 - --- @type integer G_ENDDL = 0xdf --- @type integer G_DL = 0xde ---- @type integer -G_LOAD_UCODE = 0xdd - --- @type integer G_MOVEMEM = 0xdc @@ -2673,123 +2658,15 @@ G_POPMTX = 0xd8 --- @type integer G_TEXTURE = 0xd7 ---- @type integer -G_DMA_IO = 0xd6 - ---- @type integer -G_SPECIAL_1 = 0xd5 - ---- @type integer -G_SPECIAL_2 = 0xd4 - ---- @type integer -G_SPECIAL_3 = 0xd3 - --- @type integer G_VTX = 0x01 ---- @type integer -G_MODIFYVTX = 0x02 - ---- @type integer -G_CULLDL = 0x03 - ---- @type integer -G_BRANCH_Z = 0x04 - --- @type integer G_TRI1 = 0x05 --- @type integer G_TRI2 = 0x06 ---- @type integer -G_QUAD = 0x07 - ---- @type integer -G_LINE3D = 0x08 - ---- @type integer -G_SPNOOP = 0 - ---- @type integer -G_MTX = 1 - ---- @type integer -G_RESERVED0 = 2 - ---- @type integer -G_MOVEMEM = 3 - ---- @type integer -G_VTX = 4 - ---- @type integer -G_RESERVED1 = 5 - ---- @type integer -G_DL = 6 - ---- @type integer -G_RESERVED2 = 7 - ---- @type integer -G_RESERVED3 = 8 - ---- @type integer -G_SPRITE2D_BASE = 9 - ---- @type integer -G_IMMFIRST = -65 - ---- @type integer -G_TRI1 = (G_IMMFIRST-0) - ---- @type integer -G_CULLDL = (G_IMMFIRST-1) - ---- @type integer -G_POPMTX = (G_IMMFIRST-2) - ---- @type integer -G_MOVEWORD = (G_IMMFIRST-3) - ---- @type integer -G_TEXTURE = (G_IMMFIRST-4) - ---- @type integer -G_SETOTHERMODE_H = (G_IMMFIRST-5) - ---- @type integer -G_SETOTHERMODE_L = (G_IMMFIRST-6) - ---- @type integer -G_ENDDL = (G_IMMFIRST-7) - ---- @type integer -G_SETGEOMETRYMODE = (G_IMMFIRST-8) - ---- @type integer -G_CLEARGEOMETRYMODE = (G_IMMFIRST-9) - ---- @type integer -G_LINE3D = (G_IMMFIRST-10) - ---- @type integer -G_RDPHALF_1 = (G_IMMFIRST-11) - ---- @type integer -G_RDPHALF_2 = (G_IMMFIRST-12) - ---- @type integer -G_SPRITE2D_SCALEFLIP = (G_IMMFIRST-1) - ---- @type integer -G_SPRITE2D_DRAW = (G_IMMFIRST-2) - ---- @type integer -G_NOOP = 0xc0 - --- @type integer G_SETCIMG = 0xff @@ -2835,936 +2712,15 @@ G_SETTILESIZE = 0xf2 --- @type integer G_LOADTLUT = 0xf0 ---- @type integer -G_RDPSETOTHERMODE = 0xef - ---- @type integer -G_SETPRIMDEPTH = 0xee - --- @type integer G_SETSCISSOR = 0xed ---- @type integer -G_SETCONVERT = 0xec - ---- @type integer -G_SETKEYR = 0xeb - ---- @type integer -G_SETKEYGB = 0xea - ---- @type integer -G_RDPFULLSYNC = 0xe9 - ---- @type integer -G_RDPTILESYNC = 0xe8 - ---- @type integer -G_RDPPIPESYNC = 0xe7 - ---- @type integer -G_RDPLOADSYNC = 0xe6 - --- @type integer G_TEXRECTFLIP = 0xe5 --- @type integer G_TEXRECT = 0xe4 ---- @type integer -G_TRI_FILL = 0xc8 - ---- @type integer -G_TRI_SHADE = 0xcc - ---- @type integer -G_TRI_TXTR = 0xca - ---- @type integer -G_TRI_SHADE_TXTR = 0xce - ---- @type integer -G_TRI_FILL_ZBUFF = 0xc9 - ---- @type integer -G_TRI_SHADE_ZBUFF = 0xcd - ---- @type integer -G_TRI_TXTR_ZBUFF = 0xcb - ---- @type integer -G_TRI_SHADE_TXTR_ZBUFF = 0xcf - ---- @type integer -G_RDP_TRI_FILL_MASK = 0x08 - ---- @type integer -G_RDP_TRI_SHADE_MASK = 0x04 - ---- @type integer -G_RDP_TRI_TXTR_MASK = 0x02 - ---- @type integer -G_RDP_TRI_ZBUFF_MASK = 0x01 - ---- @type integer -BOWTIE_VAL = 0 - ---- @type integer -G_RDP_ADDR_FIXUP = 3 - ---- @type integer -G_DMACMDSIZ = 128 - ---- @type integer -G_IMMCMDSIZ = 64 - ---- @type integer -G_RDPCMDSIZ = 64 - ---- @type integer -G_TEXTURE_IMAGE_FRAC = 2 - ---- @type integer -G_TEXTURE_SCALE_FRAC = 16 - ---- @type integer -G_SCALE_FRAC = 8 - ---- @type integer -G_ROTATE_FRAC = 16 - ---- @type integer -G_MAXFBZ = 0x3fff - ---- @type integer -G_ZBUFFER = 0x00000001 - ---- @type integer -G_SHADE = 0x00000004 - ---- @type integer -G_FOG = 0x00010000 - ---- @type integer -G_LIGHTING = 0x00020000 - ---- @type integer -G_TEXTURE_GEN = 0x00040000 - ---- @type integer -G_TEXTURE_GEN_LINEAR = 0x00080000 - ---- @type integer -G_LOD = 0x00100000 - ---- @type integer -G_IM_FMT_RGBA = 0 - ---- @type integer -G_IM_FMT_YUV = 1 - ---- @type integer -G_IM_FMT_CI = 2 - ---- @type integer -G_IM_FMT_IA = 3 - ---- @type integer -G_IM_FMT_I = 4 - ---- @type integer -G_IM_SIZ_4b = 0 - ---- @type integer -G_IM_SIZ_8b = 1 - ---- @type integer -G_IM_SIZ_16b = 2 - ---- @type integer -G_IM_SIZ_32b = 3 - ---- @type integer -G_IM_SIZ_DD = 5 - ---- @type integer -G_IM_SIZ_4b_BYTES = 0 - ---- @type integer -G_IM_SIZ_8b_BYTES = 1 - ---- @type integer -G_IM_SIZ_16b_BYTES = 2 - ---- @type integer -G_IM_SIZ_32b_BYTES = 4 - ---- @type integer -G_IM_SIZ_32b_TILE_BYTES = 2 - ---- @type integer -G_IM_SIZ_32b_LINE_BYTES = 2 - ---- @type integer -G_IM_SIZ_4b_SHIFT = 2 - ---- @type integer -G_IM_SIZ_8b_SHIFT = 1 - ---- @type integer -G_IM_SIZ_16b_SHIFT = 0 - ---- @type integer -G_IM_SIZ_32b_SHIFT = 0 - ---- @type integer -G_IM_SIZ_4b_INCR = 3 - ---- @type integer -G_IM_SIZ_8b_INCR = 1 - ---- @type integer -G_IM_SIZ_16b_INCR = 0 - ---- @type integer -G_IM_SIZ_32b_INCR = 0 - ---- @type integer -G_CCMUX_COMBINED = 0 - ---- @type integer -G_CCMUX_TEXEL0 = 1 - ---- @type integer -G_CCMUX_TEXEL1 = 2 - ---- @type integer -G_CCMUX_PRIMITIVE = 3 - ---- @type integer -G_CCMUX_SHADE = 4 - ---- @type integer -G_CCMUX_ENVIRONMENT = 5 - ---- @type integer -G_CCMUX_CENTER = 6 - ---- @type integer -G_CCMUX_SCALE = 6 - ---- @type integer -G_CCMUX_COMBINED_ALPHA = 7 - ---- @type integer -G_CCMUX_TEXEL0_ALPHA = 8 - ---- @type integer -G_CCMUX_TEXEL1_ALPHA = 9 - ---- @type integer -G_CCMUX_PRIMITIVE_ALPHA = 10 - ---- @type integer -G_CCMUX_SHADE_ALPHA = 11 - ---- @type integer -G_CCMUX_ENV_ALPHA = 12 - ---- @type integer -G_CCMUX_LOD_FRACTION = 13 - ---- @type integer -G_CCMUX_PRIM_LOD_FRAC = 14 - ---- @type integer -G_CCMUX_NOISE = 7 - ---- @type integer -G_CCMUX_K4 = 7 - ---- @type integer -G_CCMUX_K5 = 15 - ---- @type integer -G_CCMUX_1 = 6 - ---- @type integer -G_CCMUX_0 = 31 - ---- @type integer -G_ACMUX_COMBINED = 0 - ---- @type integer -G_ACMUX_TEXEL0 = 1 - ---- @type integer -G_ACMUX_TEXEL1 = 2 - ---- @type integer -G_ACMUX_PRIMITIVE = 3 - ---- @type integer -G_ACMUX_SHADE = 4 - ---- @type integer -G_ACMUX_ENVIRONMENT = 5 - ---- @type integer -G_ACMUX_LOD_FRACTION = 0 - ---- @type integer -G_ACMUX_PRIM_LOD_FRAC = 6 - ---- @type integer -G_ACMUX_1 = 6 - ---- @type integer -G_ACMUX_0 = 7 - ---- @type integer -G_MDSFT_ALPHACOMPARE = 0 - ---- @type integer -G_MDSFT_ZSRCSEL = 2 - ---- @type integer -G_MDSFT_RENDERMODE = 3 - ---- @type integer -G_MDSFT_BLENDER = 16 - ---- @type integer -G_MDSFT_BLENDMASK = 0 - ---- @type integer -G_MDSFT_ALPHADITHER = 4 - ---- @type integer -G_MDSFT_RGBDITHER = 6 - ---- @type integer -G_MDSFT_COMBKEY = 8 - ---- @type integer -G_MDSFT_TEXTCONV = 9 - ---- @type integer -G_MDSFT_TEXTFILT = 12 - ---- @type integer -G_MDSFT_TEXTLUT = 14 - ---- @type integer -G_MDSFT_TEXTLOD = 16 - ---- @type integer -G_MDSFT_TEXTDETAIL = 17 - ---- @type integer -G_MDSFT_TEXTPERSP = 19 - ---- @type integer -G_MDSFT_CYCLETYPE = 20 - ---- @type integer -G_MDSFT_COLORDITHER = 22 - ---- @type integer -G_MDSFT_PIPELINE = 23 - ---- @type integer -G_PM_1PRIMITIVE = (1 << G_MDSFT_PIPELINE) - ---- @type integer -G_PM_NPRIMITIVE = (0 << G_MDSFT_PIPELINE) - ---- @type integer -G_CYC_1CYCLE = (0 << G_MDSFT_CYCLETYPE) - ---- @type integer -G_CYC_2CYCLE = (1 << G_MDSFT_CYCLETYPE) - ---- @type integer -G_CYC_COPY = (2 << G_MDSFT_CYCLETYPE) - ---- @type integer -G_CYC_FILL = (3 << G_MDSFT_CYCLETYPE) - ---- @type integer -G_TP_NONE = (0 << G_MDSFT_TEXTPERSP) - ---- @type integer -G_TP_PERSP = (1 << G_MDSFT_TEXTPERSP) - ---- @type integer -G_TD_CLAMP = (0 << G_MDSFT_TEXTDETAIL) - ---- @type integer -G_TD_SHARPEN = (1 << G_MDSFT_TEXTDETAIL) - ---- @type integer -G_TD_DETAIL = (2 << G_MDSFT_TEXTDETAIL) - ---- @type integer -G_TL_TILE = (0 << G_MDSFT_TEXTLOD) - ---- @type integer -G_TL_LOD = (1 << G_MDSFT_TEXTLOD) - ---- @type integer -G_TT_NONE = (0 << G_MDSFT_TEXTLUT) - ---- @type integer -G_TT_RGBA16 = (2 << G_MDSFT_TEXTLUT) - ---- @type integer -G_TT_IA16 = (3 << G_MDSFT_TEXTLUT) - ---- @type integer -G_TF_POINT = (0 << G_MDSFT_TEXTFILT) - ---- @type integer -G_TF_AVERAGE = (3 << G_MDSFT_TEXTFILT) - ---- @type integer -G_TF_BILERP = (2 << G_MDSFT_TEXTFILT) - ---- @type integer -G_TC_CONV = (0 << G_MDSFT_TEXTCONV) - ---- @type integer -G_TC_FILTCONV = (5 << G_MDSFT_TEXTCONV) - ---- @type integer -G_TC_FILT = (6 << G_MDSFT_TEXTCONV) - ---- @type integer -G_CK_NONE = (0 << G_MDSFT_COMBKEY) - ---- @type integer -G_CK_KEY = (1 << G_MDSFT_COMBKEY) - ---- @type integer -G_CD_MAGICSQ = (0 << G_MDSFT_RGBDITHER) - ---- @type integer -G_CD_BAYER = (1 << G_MDSFT_RGBDITHER) - ---- @type integer -G_CD_NOISE = (2 << G_MDSFT_RGBDITHER) - ---- @type integer -G_CD_DISABLE = (3 << G_MDSFT_RGBDITHER) - ---- @type integer -G_CD_ENABLE = G_CD_NOISE - ---- @type integer -G_CD_ENABLE = (1 << G_MDSFT_COLORDITHER) - ---- @type integer -G_CD_DISABLE = (0 << G_MDSFT_COLORDITHER) - ---- @type integer -G_AD_PATTERN = (0 << G_MDSFT_ALPHADITHER) - ---- @type integer -G_AD_NOTPATTERN = (1 << G_MDSFT_ALPHADITHER) - ---- @type integer -G_AD_NOISE = (2 << G_MDSFT_ALPHADITHER) - ---- @type integer -G_AD_DISABLE = (3 << G_MDSFT_ALPHADITHER) - ---- @type integer -G_AC_NONE = (0 << G_MDSFT_ALPHACOMPARE) - ---- @type integer -G_AC_THRESHOLD = (1 << G_MDSFT_ALPHACOMPARE) - ---- @type integer -G_AC_DITHER = (3 << G_MDSFT_ALPHACOMPARE) - ---- @type integer -G_ZS_PIXEL = (0 << G_MDSFT_ZSRCSEL) - ---- @type integer -G_ZS_PRIM = (1 << G_MDSFT_ZSRCSEL) - ---- @type integer -AA_EN = 0x8 - ---- @type integer -Z_CMP = 0x10 - ---- @type integer -Z_UPD = 0x20 - ---- @type integer -IM_RD = 0x40 - ---- @type integer -CLR_ON_CVG = 0x80 - ---- @type integer -CVG_DST_CLAMP = 0 - ---- @type integer -CVG_DST_WRAP = 0x100 - ---- @type integer -CVG_DST_FULL = 0x200 - ---- @type integer -CVG_DST_SAVE = 0x300 - ---- @type integer -ZMODE_OPA = 0 - ---- @type integer -ZMODE_INTER = 0x400 - ---- @type integer -ZMODE_XLU = 0x800 - ---- @type integer -ZMODE_DEC = 0xc00 - ---- @type integer -CVG_X_ALPHA = 0x1000 - ---- @type integer -ALPHA_CVG_SEL = 0x2000 - ---- @type integer -FORCE_BL = 0x4000 - ---- @type integer -TEX_EDGE = 0x0000 - ---- @type integer -G_BL_CLR_IN = 0 - ---- @type integer -G_BL_CLR_MEM = 1 - ---- @type integer -G_BL_CLR_BL = 2 - ---- @type integer -G_BL_CLR_FOG = 3 - ---- @type integer -G_BL_1MA = 0 - ---- @type integer -G_BL_A_MEM = 1 - ---- @type integer -G_BL_A_IN = 0 - ---- @type integer -G_BL_A_FOG = 1 - ---- @type integer -G_BL_A_SHADE = 2 - ---- @type integer -G_BL_1 = 2 - ---- @type integer -G_BL_0 = 3 - ---- @type integer -G_CV_K0 = 175 - ---- @type integer -G_CV_K1 = -43 - ---- @type integer -G_CV_K2 = -89 - ---- @type integer -G_CV_K3 = 222 - ---- @type integer -G_CV_K4 = 114 - ---- @type integer -G_CV_K5 = 42 - ---- @type integer -G_SC_NON_INTERLACE = 0 - ---- @type integer -G_SC_ODD_INTERLACE = 3 - ---- @type integer -G_SC_EVEN_INTERLACE = 2 - ---- @type integer -G_DL_PUSH = 0x00 - ---- @type integer -G_DL_NOPUSH = 0x01 - ---- @type integer -G_MW_MATRIX = 0x00 - ---- @type integer -G_MW_NUMLIGHT = 0x02 - ---- @type integer -G_MW_CLIP = 0x04 - ---- @type integer -G_MW_SEGMENT = 0x06 - ---- @type integer -G_MW_FOG = 0x08 - ---- @type integer -G_MW_LIGHTCOL = 0x0a - ---- @type integer -G_MW_PERSPNORM = 0x0e - ---- @type integer -G_MWO_NUMLIGHT = 0x00 - ---- @type integer -G_MWO_CLIP_RNX = 0x04 - ---- @type integer -G_MWO_CLIP_RNY = 0x0c - ---- @type integer -G_MWO_CLIP_RPX = 0x14 - ---- @type integer -G_MWO_CLIP_RPY = 0x1c - ---- @type integer -G_MWO_SEGMENT_0 = 0x00 - ---- @type integer -G_MWO_SEGMENT_1 = 0x01 - ---- @type integer -G_MWO_SEGMENT_2 = 0x02 - ---- @type integer -G_MWO_SEGMENT_3 = 0x03 - ---- @type integer -G_MWO_SEGMENT_4 = 0x04 - ---- @type integer -G_MWO_SEGMENT_5 = 0x05 - ---- @type integer -G_MWO_SEGMENT_6 = 0x06 - ---- @type integer -G_MWO_SEGMENT_7 = 0x07 - ---- @type integer -G_MWO_SEGMENT_8 = 0x08 - ---- @type integer -G_MWO_SEGMENT_9 = 0x09 - ---- @type integer -G_MWO_SEGMENT_A = 0x0a - ---- @type integer -G_MWO_SEGMENT_B = 0x0b - ---- @type integer -G_MWO_SEGMENT_C = 0x0c - ---- @type integer -G_MWO_SEGMENT_D = 0x0d - ---- @type integer -G_MWO_SEGMENT_E = 0x0e - ---- @type integer -G_MWO_SEGMENT_F = 0x0f - ---- @type integer -G_MWO_FOG = 0x00 - ---- @type integer -G_MWO_aLIGHT_1 = 0x00 - ---- @type integer -G_MWO_bLIGHT_1 = 0x04 - ---- @type integer -G_MWO_aLIGHT_2 = 0x18 - ---- @type integer -G_MWO_bLIGHT_2 = 0x1c - ---- @type integer -G_MWO_aLIGHT_3 = 0x30 - ---- @type integer -G_MWO_bLIGHT_3 = 0x34 - ---- @type integer -G_MWO_aLIGHT_4 = 0x48 - ---- @type integer -G_MWO_bLIGHT_4 = 0x4c - ---- @type integer -G_MWO_aLIGHT_5 = 0x60 - ---- @type integer -G_MWO_bLIGHT_5 = 0x64 - ---- @type integer -G_MWO_aLIGHT_6 = 0x78 - ---- @type integer -G_MWO_bLIGHT_6 = 0x7c - ---- @type integer -G_MWO_aLIGHT_7 = 0x90 - ---- @type integer -G_MWO_bLIGHT_7 = 0x94 - ---- @type integer -G_MWO_aLIGHT_8 = 0xa8 - ---- @type integer -G_MWO_bLIGHT_8 = 0xac - ---- @type integer -G_MWO_aLIGHT_2 = 0x20 - ---- @type integer -G_MWO_bLIGHT_2 = 0x24 - ---- @type integer -G_MWO_aLIGHT_3 = 0x40 - ---- @type integer -G_MWO_bLIGHT_3 = 0x44 - ---- @type integer -G_MWO_aLIGHT_4 = 0x60 - ---- @type integer -G_MWO_bLIGHT_4 = 0x64 - ---- @type integer -G_MWO_aLIGHT_5 = 0x80 - ---- @type integer -G_MWO_bLIGHT_5 = 0x84 - ---- @type integer -G_MWO_aLIGHT_6 = 0xa0 - ---- @type integer -G_MWO_bLIGHT_6 = 0xa4 - ---- @type integer -G_MWO_aLIGHT_7 = 0xc0 - ---- @type integer -G_MWO_bLIGHT_7 = 0xc4 - ---- @type integer -G_MWO_aLIGHT_8 = 0xe0 - ---- @type integer -G_MWO_bLIGHT_8 = 0xe4 - ---- @type integer -G_MWO_MATRIX_XX_XY_I = 0x00 - ---- @type integer -G_MWO_MATRIX_XZ_XW_I = 0x04 - ---- @type integer -G_MWO_MATRIX_YX_YY_I = 0x08 - ---- @type integer -G_MWO_MATRIX_YZ_YW_I = 0x0c - ---- @type integer -G_MWO_MATRIX_ZX_ZY_I = 0x10 - ---- @type integer -G_MWO_MATRIX_ZZ_ZW_I = 0x14 - ---- @type integer -G_MWO_MATRIX_WX_WY_I = 0x18 - ---- @type integer -G_MWO_MATRIX_WZ_WW_I = 0x1c - ---- @type integer -G_MWO_MATRIX_XX_XY_F = 0x20 - ---- @type integer -G_MWO_MATRIX_XZ_XW_F = 0x24 - ---- @type integer -G_MWO_MATRIX_YX_YY_F = 0x28 - ---- @type integer -G_MWO_MATRIX_YZ_YW_F = 0x2c - ---- @type integer -G_MWO_MATRIX_ZX_ZY_F = 0x30 - ---- @type integer -G_MWO_MATRIX_ZZ_ZW_F = 0x34 - ---- @type integer -G_MWO_MATRIX_WX_WY_F = 0x38 - ---- @type integer -G_MWO_MATRIX_WZ_WW_F = 0x3c - ---- @type integer -G_MWO_POINT_RGBA = 0x10 - ---- @type integer -G_MWO_POINT_ST = 0x14 - ---- @type integer -G_MWO_POINT_XYSCREEN = 0x18 - ---- @type integer -G_MWO_POINT_ZSCREEN = 0x1c - ---- @type integer -FR_NEG_FRUSTRATIO_1 = 0x00000001 - ---- @type integer -FR_POS_FRUSTRATIO_1 = 0x0000ffff - ---- @type integer -FR_NEG_FRUSTRATIO_2 = 0x00000002 - ---- @type integer -FR_POS_FRUSTRATIO_2 = 0x0000fffe - ---- @type integer -FR_NEG_FRUSTRATIO_3 = 0x00000003 - ---- @type integer -FR_POS_FRUSTRATIO_3 = 0x0000fffd - ---- @type integer -FR_NEG_FRUSTRATIO_4 = 0x00000004 - ---- @type integer -FR_POS_FRUSTRATIO_4 = 0x0000fffc - ---- @type integer -FR_NEG_FRUSTRATIO_5 = 0x00000005 - ---- @type integer -FR_POS_FRUSTRATIO_5 = 0x0000fffb - ---- @type integer -FR_NEG_FRUSTRATIO_6 = 0x00000006 - ---- @type integer -FR_POS_FRUSTRATIO_6 = 0x0000fffa - ---- @type integer -NUMLIGHTS_0 = 1 - ---- @type integer -NUMLIGHTS_1 = 1 - ---- @type integer -NUMLIGHTS_2 = 2 - ---- @type integer -NUMLIGHTS_3 = 3 - ---- @type integer -NUMLIGHTS_4 = 4 - ---- @type integer -NUMLIGHTS_5 = 5 - ---- @type integer -NUMLIGHTS_6 = 6 - ---- @type integer -NUMLIGHTS_7 = 7 - ---- @type integer -LIGHT_1 = 1 - ---- @type integer -LIGHT_2 = 2 - ---- @type integer -LIGHT_3 = 3 - ---- @type integer -LIGHT_4 = 4 - ---- @type integer -LIGHT_5 = 5 - ---- @type integer -LIGHT_6 = 6 - ---- @type integer -LIGHT_7 = 7 - ---- @type integer -LIGHT_8 = 8 - ---- @type integer -G_TX_LOADTILE = 7 - ---- @type integer -G_TX_RENDERTILE = 0 - ---- @type integer -G_TX_NOMIRROR = 0 - ---- @type integer -G_TX_WRAP = 0 - ---- @type integer -G_TX_MIRROR = 0x1 - ---- @type integer -G_TX_CLAMP = 0x2 - ---- @type integer -G_TX_NOMASK = 0 - ---- @type integer -G_TX_NOLOD = 0 - ---- @type integer -G_TX_DXT_FRAC = 11 - ---- @type integer -G_TX_LDBLK_MAX_TXL = 4095 - ---- @type integer -G_TX_LDBLK_MAX_TXL = 2047 - --- @type integer BACKGROUND_OCEAN_SKY = 0 @@ -10365,9 +9321,6 @@ SOUND_GENERAL_CLAM_SHELL2 = SOUND_ARG_LOAD(SOUND_BANK_GENERAL, 0x26, 0x40, SOUND --- @type integer SOUND_GENERAL_CLAM_SHELL3 = SOUND_ARG_LOAD(SOUND_BANK_GENERAL, 0x27, 0x40, SOUND_DISCRETE) ---- @type integer -SOUND_GENERAL_PAINTING_EJECT = SOUND_ARG_LOAD(SOUND_BANK_GENERAL, 0x28, 0x00, SOUND_CONSTANT_FREQUENCY | SOUND_DISCRETE) - --- @type integer SOUND_GENERAL_PAINTING_EJECT = SOUND_ARG_LOAD(SOUND_BANK_GENERAL, 0x28, 0x00, SOUND_NO_VOLUME_LOSS | SOUND_CONSTANT_FREQUENCY | SOUND_DISCRETE) diff --git a/autogen/lua_definitions/functions.lua b/autogen/lua_definitions/functions.lua index 6dff8c3dc..d2ed82d09 100644 --- a/autogen/lua_definitions/functions.lua +++ b/autogen/lua_definitions/functions.lua @@ -9698,50 +9698,135 @@ function gfx_parse(cmd, func) -- ... end ---- @param gfx Pointer_Gfx ---- @param offset integer +--- @param cmd Pointer_Gfx +--- @return integer +--- Gets the op of the display list command +function gfx_get_op(cmd) + -- ... +end + +--- @param cmd Pointer_Gfx +--- @return Pointer_Gfx +--- Gets the display list from a display list command if it has the op `G_DL` +function gfx_get_display_list(cmd) + -- ... +end + +--- @param cmd Pointer_Gfx --- @return Pointer_Vtx ---- Gets a vertex from a display list command if it has the correct op. Intended to be used with `gfx_parse` -function gfx_get_vtx(gfx, offset) +--- Gets the vertex buffer from a display list command if it has the op `G_VTX` +function gfx_get_vertex_buffer(cmd) -- ... end --- @param cmd Pointer_Gfx --- @return integer ---- Gets the number of vertices from a display list command if it has the correct op -function gfx_get_vtx_count(cmd) +--- Gets the number of vertices from a display list command if it has the op `G_VTX` +function gfx_get_vertex_count(cmd) -- ... end --- @param gfx Pointer_Gfx ---- @param a0 integer ---- @param b0 integer ---- @param c0 integer ---- @param d0 integer ---- @param Aa0 integer ---- @param Ab0 integer ---- @param Ac0 integer ---- @param Ad0 integer ---- @param a1 integer ---- @param b1 integer ---- @param c1 integer ---- @param d1 integer ---- @param Aa1 integer ---- @param Ab1 integer ---- @param Ac1 integer ---- @param Ad1 integer ---- Sets the display list combine mode. you can fill this function with G_CCMUX_* and G_ACMUX_* constants -function gfx_set_combine_lerp(gfx, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1) +--- @return integer +--- Gets the max length of a display list +function gfx_get_length(gfx) -- ... end --- @param gfx Pointer_Gfx ---- @param format integer ---- @param size integer ---- @param width integer ---- @param texture Pointer_integer ---- Sets the display list texture image. Pass in textureInfo.texture as `texture` -function gfx_set_texture_image(gfx, format, size, width, texture) +--- @param offset integer +--- @return Pointer_Gfx +--- Gets a command of a display list at position `offset` +function gfx_get_command(gfx, offset) + -- ... +end + +--- @param gfx Pointer_Gfx +--- @return Pointer_Gfx +--- Gets the next command of a given display list pointer. Intended to use in a for loop +function gfx_get_next_command(gfx) + -- ... +end + +--- @param dest Pointer_Gfx +--- @param src Pointer_Gfx +--- @param length integer +--- Copies `length` commands from display list `src` to display list `dest` +function gfx_copy(dest, src, length) + -- ... +end + +--- @param name string +--- @param length integer +--- @return Pointer_Gfx +--- Creates a new named display list of `length` commands +function gfx_new(name, length) + -- ... +end + +--- @param gfx Pointer_Gfx +--- @param newLength integer +--- @return Pointer_Gfx +--- Reallocates a display list created by `gfx_new` to modify its length +function gfx_realloc(gfx, newLength) + -- ... +end + +--- @param gfx Pointer_Gfx +--- Deletes a display list created by `gfx_new` +function gfx_delete(gfx) + -- ... +end + +--- @param vtx Pointer_Vtx +--- @return integer +--- Gets the max count of vertices of a vertex buffer +function vtx_get_count(vtx) + -- ... +end + +--- @param vtx Pointer_Vtx +--- @param offset integer +--- @return Pointer_Vtx +--- Gets a vertex of a vertex buffer at position `offset` +function vtx_get_vertex(vtx, offset) + -- ... +end + +--- @param vtx Pointer_Vtx +--- @return Pointer_Vtx +--- Gets the next vertex of a given vertex pointer. Intended to use in a for loop +function vtx_get_next_vertex(vtx) + -- ... +end + +--- @param dest Pointer_Vtx +--- @param src Pointer_Vtx +--- @param count integer +--- Copies `count` vertices from vertex buffer `src` to vertex buffer `dest` +function vtx_copy(dest, src, count) + -- ... +end + +--- @param name string +--- @param count integer +--- @return Pointer_Vtx +--- Creates a new named vertex buffer of `count` vertices +function vtx_new(name, count) + -- ... +end + +--- @param vtx Pointer_Vtx +--- @param newCount integer +--- @return Pointer_Vtx +--- Reallocates a vertex buffer created by `vtx_new` to modify its count +function vtx_realloc(vtx, newCount) + -- ... +end + +--- @param vtx Pointer_Vtx +--- Deletes a vertex buffer created by `vtx_new` +function vtx_delete(vtx) -- ... end diff --git a/autogen/lua_definitions/manual.lua b/autogen/lua_definitions/manual.lua index 65bef6f64..76ad0d265 100644 --- a/autogen/lua_definitions/manual.lua +++ b/autogen/lua_definitions/manual.lua @@ -451,8 +451,39 @@ end --- @param gfx Gfx --- @param command string ---- @vararg integer Parameters for the command ---- Sets the specified display list command on the display list given +--- @vararg integer | string | Gfx | Texture | Vtx Parameters for the command +--- Sets a display list command on the display list given. +--- +--- If `command` includes parameter specifiers (subsequences beginning with `%`), the additional arguments +--- following `command` are converted and inserted in `command` replacing their respective specifiers. +--- +--- The number of provided parameters must be equal to the number of specifiers in `command`, +--- and the order of parameters must be the same as the specifiers. +--- +--- The following specifiers are allowed: +--- - `%i` for an `integer` parameter +--- - `%s` for a `string` parameter +--- - `%v` for a `Vtx` parameter +--- - `%t` for a `Texture` parameter +--- - `%g` for a `Gfx` parameter function gfx_set_command(gfx, command, ...) -- ... end + +--- @param name string +--- @return Pointer_Gfx +--- @return integer +--- Gets a display list of the current mod from its name. +--- Returns a pointer to the display list and its length +function gfx_get_from_name(name) + -- ... +end + +--- @param name string +--- @return Pointer_Vtx +--- @return integer +--- Gets a vertex buffer of the current mod from its name. +--- Returns a pointer to the vertex buffering and its vertex count +function vtx_get_from_name(name) + -- ... +end diff --git a/autogen/lua_definitions/structs.lua b/autogen/lua_definitions/structs.lua index 44cb2e080..bcf290e43 100644 --- a/autogen/lua_definitions/structs.lua +++ b/autogen/lua_definitions/structs.lua @@ -2333,10 +2333,19 @@ --- @field public posYaw integer --- @class Vtx ---- @field public cn integer[] +--- @field public a integer +--- @field public b integer --- @field public flag integer ---- @field public ob number[] ---- @field public tc integer[] +--- @field public g integer +--- @field public nx integer +--- @field public ny integer +--- @field public nz integer +--- @field public r integer +--- @field public tu integer +--- @field public tv integer +--- @field public x number +--- @field public y number +--- @field public z number --- @class Vtx_Interp --- @field public n string diff --git a/data/dynos.c.h b/data/dynos.c.h index f6739ef53..aa50611c0 100644 --- a/data/dynos.c.h +++ b/data/dynos.c.h @@ -6,6 +6,7 @@ #include "types.h" #include "engine/behavior_script.h" #include "game/moving_texture.h" +#include "lua.h" void *dynos_swap_cmd(void *cmd); @@ -79,16 +80,29 @@ struct GraphNode* dynos_model_load_dl(u32* aId, enum ModelPool aModelPool, u8 aL struct GraphNode* dynos_model_store_geo(u32* aId, enum ModelPool aModelPool, void* aAsset, struct GraphNode* aGraphNode); struct GraphNode* dynos_model_get_geo(u32 aId); void dynos_model_overwrite_slot(u32 srcSlot, u32 dstSlot); -Gfx *dynos_model_get_writable_display_list(Gfx* gfx); -void dynos_model_restore_vanilla_display_lists(); u32 dynos_model_get_id_from_asset(void* aAsset); u32 dynos_model_get_id_from_graph_node(struct GraphNode* aGraphNode); void dynos_model_clear_pool(enum ModelPool aModelPool); +// -- gfx -- // +Gfx *dynos_gfx_get_writable_display_list(Gfx* gfx); +Gfx *dynos_gfx_get(const char *name, u32 *outLength); +Gfx *dynos_gfx_new(const char *name, u32 length); +Gfx *dynos_gfx_realloc(Gfx *gfx, u32 newLength); +bool dynos_gfx_delete(Gfx *gfx); +Vtx *dynos_vtx_get(const char *name, u32 *outCount); +Vtx *dynos_vtx_new(const char *name, u32 count); +Vtx *dynos_vtx_realloc(Vtx *vtx, u32 newCount); +bool dynos_vtx_delete(Vtx *vtx); + // -- other -- // void dynos_mod_shutdown(void); void dynos_pending_scroll_targets_clear(void); void dynos_add_scroll_target(u32 index, const char *name, u32 offset, u32 size); +// -- smlua -- // +bool dynos_smlua_parse_gfx_command(lua_State *L, Gfx *gfx, const char *command, bool hasSpecifiers, char *errorMsg, u32 errorSize); +void dynos_smlua_clear_gfx_command_cache(); + #endif #endif diff --git a/data/dynos.cpp.h b/data/dynos.cpp.h index 64aed1e37..d8fa549de 100644 --- a/data/dynos.cpp.h +++ b/data/dynos.cpp.h @@ -556,6 +556,7 @@ struct GfxData : NoCopy { DataNodes mMovtexs; DataNodes mMovtexQCs; DataNodes mRooms; + DataNodes mRawPointers; // Animation data Array *> mAnimValues; @@ -661,6 +662,10 @@ struct LvlCmd { u8 mSize; }; +// modIndex -> itemName -> (itemPointer, itemSize) +template +using ModData = std::map>>; + // // Utils // @@ -886,6 +891,7 @@ void DynOS_Pack_AddTex(PackData* aPackData, DataNode* aTexData); // Actor Manager // +std::map &DynOS_Actor_GetValidActors(); void DynOS_Actor_AddCustom(s32 aModIndex, 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, const char **outToken); @@ -974,10 +980,30 @@ struct GraphNode* DynOS_Model_GetGeo(u32 aId); u32 DynOS_Model_GetIdFromAsset(void* asset); u32 DynOS_Model_GetIdFromGraphNode(struct GraphNode* aNode); void DynOS_Model_OverwriteSlot(u32 srcSlot, u32 dstSlot); -Gfx *DynOS_Model_GetWritableDisplayList(Gfx* aGfx); -void DynOS_Model_RestoreVanillaDisplayLists(); void DynOS_Model_ClearPool(enum ModelPool aModelPool); +// +// Gfx Manager +// + +Gfx *DynOS_Gfx_GetWritableDisplayList(Gfx *aGfx); +Gfx *DynOS_Gfx_Get(const char *aName, u32 *outLength); +Gfx *DynOS_Gfx_New(const char *aName, u32 aLength); +Gfx *DynOS_Gfx_Realloc(Gfx *aGfx, u32 aNewLength); +bool DynOS_Gfx_Delete(Gfx *aGfx); +Vtx *DynOS_Vtx_Get(const char *aName, u32 *outCount); +Vtx *DynOS_Vtx_New(const char *aName, u32 aCount); +Vtx *DynOS_Vtx_Realloc(Vtx *aVtx, u32 aNewCount); +bool DynOS_Vtx_Delete(Vtx *aVtx); +void DynOS_Gfx_ModShutdown(); + +// +// Mod Data Manager +// + +// template functions +#include "dynos_mgr_moddata.hpp" + // // Bin // diff --git a/data/dynos.h b/data/dynos.h index 7f6b1b1da..536e4668b 100644 --- a/data/dynos.h +++ b/data/dynos.h @@ -17,6 +17,7 @@ #include #include #include +#include extern "C" { #endif #include "config.h" diff --git a/data/dynos_bin_gfx.cpp b/data/dynos_bin_gfx.cpp index 07da2f1e5..677f1fd6c 100644 --- a/data/dynos_bin_gfx.cpp +++ b/data/dynos_bin_gfx.cpp @@ -1,8 +1,31 @@ #include "dynos.cpp.h" +#include extern "C" { #include #include "sm64.h" #include "include/textures.h" +#include "src/pc/lua/smlua.h" +#include "src/pc/lua/utils/smlua_gfx_utils.h" +} + +static std::map> sGfxCommandCache; +static char *sGfxCommandErrorMsg = NULL; +static u32 sGfxCommandErrorSize = 0; + +#define PrintDataErrorGfx(...) { \ + if (sGfxCommandErrorMsg) { \ + snprintf(sGfxCommandErrorMsg, sGfxCommandErrorSize, __VA_ARGS__); \ + aGfxData->mErrorCount++; \ + } else { \ + PrintDataError(__VA_ARGS__); \ + } \ +} + +#define CHECK_TOKEN_INDEX(tokenIndex, returnValue) { \ + if (tokenIndex >= aNode->mTokens.Count()) { \ + PrintDataErrorGfx(" ERROR: Invalid token index: %llu, tokens count is: %d", tokenIndex, aNode->mTokens.Count()); \ + return returnValue; \ + } \ } #pragma GCC diagnostic push @@ -403,6 +426,7 @@ s64 DynOS_Gfx_ParseGfxConstants(const String& _Arg, bool* found) { static s64 ParseGfxSymbolArg(GfxData* aGfxData, DataNode* aNode, u64* pTokenIndex, const char *aPrefix) { assert(aPrefix != NULL); + if (pTokenIndex != NULL) { CHECK_TOKEN_INDEX(*pTokenIndex, 0); } String _Token = (pTokenIndex != NULL ? aNode->mTokens[(*pTokenIndex)++] : ""); String _Arg("%s%s", aPrefix, _Token.begin()); @@ -419,6 +443,13 @@ static s64 ParseGfxSymbolArg(GfxData* aGfxData, DataNode* aNode, u64* pToke return constantValue; } + // Pointers + for (auto& _Node : aGfxData->mRawPointers) { + if (_Arg == _Node->mName) { + return (s64) _Node->mData; + } + } + // Offset s32 _Offset = 0; s32 _Plus = _Arg.Find('+'); @@ -534,11 +565,11 @@ static s64 ParseGfxSymbolArg(GfxData* aGfxData, DataNode* aNode, u64* pToke bool rdSuccess = false; s64 rdValue = DynOS_RecursiveDescent_Parse(_Arg.begin(), &rdSuccess, DynOS_Gfx_ParseGfxConstants); if (rdSuccess) { - return (LevelScript)rdValue; + return rdValue; } // Unknown - PrintDataError(" ERROR: Unknown gfx arg: %s", _Arg.begin()); + PrintDataErrorGfx(" ERROR: Unknown gfx arg: %s", _Arg.begin()); return 0; } @@ -653,10 +684,11 @@ static s64 ParseGfxSymbolArg(GfxData* aGfxData, DataNode* aNode, u64* pToke return; \ } -#define gfx_arg_with_suffix(argname, suffix) \ +#define gfx_arg_with_suffix(argname, suffix) \ + CHECK_TOKEN_INDEX(aTokenIndex,); \ const String& argname##_token = aNode->mTokens[aTokenIndex]; \ - String _Token##suffix = String("%s%s", argname##_token.begin(), #suffix); \ - s64 argname = ParseGfxSymbolArg(aGfxData, aNode, NULL, _Token##suffix.begin()); \ + String _Token##suffix = String("%s%s", argname##_token.begin(), #suffix); \ + s64 argname = ParseGfxSymbolArg(aGfxData, aNode, NULL, _Token##suffix.begin()); \ #define STR_VALUE_2(...) #__VA_ARGS__ #define STR_VALUE(...) STR_VALUE_2(__VA_ARGS__) @@ -731,11 +763,12 @@ static String ConvertSetCombineModeArgToString(GfxData *aGfxData, const String& gfx_set_combine_mode_arg(G_CC_HILITERGBA2); gfx_set_combine_mode_arg(G_CC_HILITERGBDECALA2); gfx_set_combine_mode_arg(G_CC_HILITERGBPASSA2); - PrintDataError(" ERROR: Unknown gfx gsDPSetCombineMode arg: %s", _Arg.begin()); + PrintDataErrorGfx(" ERROR: Unknown gfx gsDPSetCombineMode arg: %s", _Arg.begin()); return ""; } static Array ParseGfxSetCombineMode(GfxData* aGfxData, DataNode* aNode, u64* pTokenIndex) { + CHECK_TOKEN_INDEX(*pTokenIndex, Array()); String _Buffer = ConvertSetCombineModeArgToString(aGfxData, aNode->mTokens[(*pTokenIndex)++]); Array _Args; String _Token; @@ -751,7 +784,7 @@ static Array ParseGfxSetCombineMode(GfxData* aGfxData, DataNode* aNode } } if (_Args.Count() < 8) { - PrintDataError(" ERROR: gsDPSetCombineMode %s: Not enough arguments", _Buffer.begin()); + PrintDataErrorGfx(" ERROR: gsDPSetCombineMode %s: Not enough arguments", _Buffer.begin()); } return _Args; } @@ -763,6 +796,13 @@ static void UpdateTextureInfo(GfxData* aGfxData, s64 *aTexPtr, s32 aFormat, s32 return; } + // Skip raw pointers + for (const auto &ptrNode : aGfxData->mRawPointers) { + if ((void *) *aTexPtr == ptrNode->mData) { + return; + } + } + aGfxData->mGfxContext.mCurrentTexture = (DataNode*) (*aTexPtr); } @@ -787,6 +827,7 @@ extern "C" { #define define_gfx_symbol(symb, params, ...) gfx_symbol_##params(symb, ##__VA_ARGS__) static void ParseGfxSymbol(GfxData* aGfxData, DataNode* aNode, Gfx*& aHead, u64& aTokenIndex) { + CHECK_TOKEN_INDEX(aTokenIndex,); const String& _Symbol = aNode->mTokens[aTokenIndex++]; // Simple symbols @@ -1073,20 +1114,22 @@ static void ParseGfxSymbol(GfxData* aGfxData, DataNode* aNode, Gfx*& aHead, } // Unknown - PrintDataError(" ERROR: Unknown gfx symbol: %s", _Symbol.begin()); + PrintDataErrorGfx(" ERROR: Unknown gfx symbol: %s", _Symbol.begin()); } DataNode* DynOS_Gfx_Parse(GfxData* aGfxData, DataNode* aNode) { if (aNode->mData) return aNode; // Display list data - aNode->mData = New(aNode->mTokens.Count() * DISPLAY_LIST_SIZE_PER_TOKEN); + u32 _Length = aNode->mTokens.Count() * DISPLAY_LIST_SIZE_PER_TOKEN; + aNode->mData = gfx_allocate_internal(_Length); Gfx* _Head = aNode->mData; for (u64 _TokenIndex = 0; _TokenIndex < aNode->mTokens.Count();) { // Don't increment _TokenIndex here! ParseGfxSymbol(aGfxData, aNode, _Head, _TokenIndex); } aNode->mSize = (u32) (_Head - aNode->mData); aNode->mLoadIndex = aGfxData->mLoadIndex++; + memmove(aNode->mData + aNode->mSize, aNode->mData + _Length, sizeof(Gfx)); // Move the sentinel to the true end of the display list return aNode; } @@ -1128,7 +1171,7 @@ void DynOS_Gfx_Load(BinFile *aFile, GfxData *aGfxData) { // Data _Node->mSize = aFile->Read(); - _Node->mData = New(_Node->mSize); + _Node->mData = gfx_allocate_internal(_Node->mSize); for (u32 i = 0; i != _Node->mSize; ++i) { u32 _WordsW0 = aFile->Read(); u32 _WordsW1 = aFile->Read(); @@ -1144,4 +1187,254 @@ void DynOS_Gfx_Load(BinFile *aFile, GfxData *aGfxData) { // Append aGfxData->mDisplayLists.Add(_Node); +} + + ///////// + // Lua // +///////// + +// +// Parameter specifiers for gfx_set_command: +// +// %i -> integer +// %s -> string +// %v -> Vtx pointer +// %t -> Texture pointer +// %g -> Gfx pointer +// + +static String CreateRawPointerDataNode(GfxData *aGfxData, void *pointer) { + String ptrNodeName = String("PTR_%016llX", (u64) pointer); + DataNode *ptrNode = New>(); + ptrNode->mName = ptrNodeName; + ptrNode->mData = pointer; + aGfxData->mRawPointers.Add(ptrNode); + return ptrNodeName; +} + +template +static String ConvertParam(lua_State *L, GfxData *aGfxData, u32 paramIndex, const char *typeName, const SmluaToFunc &smluaToFunc, const ReturnFunc &returnFunc) { + T value = smluaToFunc(L, paramIndex); + if (!gSmLuaConvertSuccess) { + PrintDataErrorGfx(" ERROR: Failed to convert parameter %u to %s", paramIndex, typeName); + return ""; + } + return returnFunc(value); +} + +static String ResolveParam(lua_State *L, GfxData *aGfxData, u32 paramIndex, char paramType) { + switch (paramType) { + + // Integer + case 'i': return ConvertParam( + L, aGfxData, paramIndex, + "integer", + [] (lua_State *L, u32 paramIndex) { return smlua_to_integer(L, paramIndex); }, + [] (s64 integer) { return String("%lld", integer); } + ); + + // String + case 's': return ConvertParam( + L, aGfxData, paramIndex, + "string", + [] (lua_State *L, u32 paramIndex) { return smlua_to_string(L, paramIndex); }, + [] (const char *string) { return String(string); } + ); + + // Vtx pointer + case 'v': return ConvertParam( + L, aGfxData, paramIndex, + "Vtx pointer", + [] (lua_State *L, u32 paramIndex) { return (Vtx *) smlua_to_cobject(L, paramIndex, LOT_VTX); }, + [&aGfxData] (Vtx *vtx) { return CreateRawPointerDataNode(aGfxData, vtx); } + ); + + // Texture pointer + case 't': return ConvertParam( + L, aGfxData, paramIndex, + "Texture pointer", + [] (lua_State *L, u32 paramIndex) { return (Texture *) smlua_to_cpointer(L, paramIndex, LVT_U8_P); }, + [&aGfxData] (Texture *texture) { return CreateRawPointerDataNode(aGfxData, texture); } + ); + + // Gfx pointer + case 'g': return ConvertParam( + L, aGfxData, paramIndex, + "Gfx pointer", + [] (lua_State *L, u32 paramIndex) { return (Gfx *) smlua_to_cobject(L, paramIndex, LOT_GFX); }, + [&aGfxData] (Gfx *gfx) { return CreateRawPointerDataNode(aGfxData, gfx); } + ); + } + PrintDataErrorGfx(" ERROR: Unknown parameter type: '%c'", paramType); + return ""; +} + +static std::string ResolveGfxCommand(lua_State *L, GfxData *aGfxData, const char *command) { + std::string output; + for (u32 paramIndex = 3; *command; command++) { + char c = *command; + if (c == '%') { + char paramType = *(++command); + String value = ResolveParam(L, aGfxData, paramIndex++, paramType); + if (aGfxData->mErrorCount > 0) { + return ""; + } + output.append(value.begin()); + } else { + output += c; + } + } + return output; +} + +static Array TokenizeGfxCommand(const std::string &command) { + Array tokens; + String token; + for (u32 i = 0, scope = 0; i < command.length(); ++i) { + char c = command[i]; + + // Remove whitespaces + if (c <= ' ') { + continue; + } + + if (c == '(') { + + // End of the command name, beginning of the arguments + if (scope == 0) { + if (!token.Empty()) { + tokens.Add(token); + token.Clear(); + } + } + + // That's an argument + else { + token.Add(c); + } + + scope++; + } + + else if (c == ')') { + scope--; + + // End of the command + if (scope == 0) { + break; + } + + // That's an argument + else { + token.Add(c); + } + } + + // End of an argument + else if (c == ',') { + if (!token.Empty()) { + tokens.Add(token); + token.Clear(); + } + } + + else { + token.Add(c); + } + } + if (!token.Empty()) { + tokens.Add(token); + } + return tokens; +} + +static bool CheckGfxLength(GfxData *aGfxData, Gfx *gfx, u32 lengthToWrite) { + if (lengthToWrite > 1) { + u32 gfxLength = gfx_get_length(gfx); + if (gfxLength < lengthToWrite) { + PrintDataErrorGfx(" ERROR: Cannot write %u commands to display list of length: %u", lengthToWrite, gfxLength); + return false; + } + } + return true; +} + +static bool ParseGfxCommand(lua_State *L, GfxData *aGfxData, Gfx *gfx, const char *command, bool hasSpecifiers) { + + // Resolve command + std::string resolved = hasSpecifiers ? ResolveGfxCommand(L, aGfxData, command) : command; + if (aGfxData->mErrorCount > 0) { + return false; + } + + // Check cache + const auto &it = sGfxCommandCache.find(resolved); + if (it != sGfxCommandCache.end()) { + const Gfx *src = it->second.first; + u32 length = it->second.second; + if (!CheckGfxLength(aGfxData, gfx, length)) { + return false; + } + memcpy(gfx, src, length * sizeof(Gfx)); + return true; + } + + // Tokenize command + DataNode aNode; + aNode.mTokens = TokenizeGfxCommand(resolved); + if (aGfxData->mErrorCount > 0) { + return false; + } + + // Parse tokenized command + u64 aTokenIndex = 0; + Gfx gfxBuffer[16] = {0}; + Gfx *gfxHead = gfxBuffer; + ParseGfxSymbol(aGfxData, &aNode, gfxHead, aTokenIndex); + if (aGfxData->mErrorCount > 0) { + return false; + } + + // Cache parsed command + u32 commandLength = (u32) (gfxHead - gfxBuffer); + size_t commandSize = commandLength * sizeof(Gfx); + Gfx *cached = (Gfx *) malloc(commandSize); + memcpy(cached, gfxBuffer, commandSize); + sGfxCommandCache[resolved] = { cached, commandLength }; + + // Copy buffer to gfx + if (!CheckGfxLength(aGfxData, gfx, commandLength)) { + return false; + } + memcpy(gfx, gfxBuffer, commandLength * sizeof(Gfx)); + return true; +} + +extern "C" { + +bool dynos_smlua_parse_gfx_command(lua_State *L, Gfx *gfx, const char *command, bool hasSpecifiers, char *errorMsg, u32 errorSize) { + + // Parse command + GfxData aGfxData; + sGfxCommandErrorMsg = errorMsg; + sGfxCommandErrorSize = errorSize; + bool ok = ParseGfxCommand(L, &aGfxData, gfx, command, hasSpecifiers); + + // Clear stuff + sGfxCommandErrorMsg = NULL; + sGfxCommandErrorSize = 0; + for (auto &ptrNode : aGfxData.mRawPointers) { + Delete(ptrNode); + } + + return ok; +} + +void dynos_smlua_clear_gfx_command_cache() { + for (auto &cached : sGfxCommandCache) { + free(cached.second.first); + } + sGfxCommandCache.clear(); +} + } diff --git a/data/dynos_bin_vtx.cpp b/data/dynos_bin_vtx.cpp index 838e1ffbd..b3b7f578e 100644 --- a/data/dynos_bin_vtx.cpp +++ b/data/dynos_bin_vtx.cpp @@ -1,6 +1,7 @@ #include "dynos.cpp.h" extern "C" { #include "engine/graph_node.h" +#include "pc/lua/utils/smlua_gfx_utils.h" } #define F32VTX_SENTINEL_0 0x3346 @@ -34,7 +35,7 @@ DataNode* DynOS_Vtx_Parse(GfxData* aGfxData, DataNode* aNode) { // Vertex data aNode->mSize = (u32) (aNode->mTokens.Count() / 10); - aNode->mData = New(aNode->mSize); + aNode->mData = vtx_allocate_internal(aNode->mSize); for (u32 i = 0; i != aNode->mSize; ++i) { f32 px = (f32) aNode->mTokens[10 * i + 0].ParseFloat(); f32 py = (f32) aNode->mTokens[10 * i + 1].ParseFloat(); @@ -115,7 +116,7 @@ void DynOS_Vtx_Load(BinFile *aFile, GfxData *aGfxData) { // Data bool isUsingF32Vtx = false; _Node->mSize = aFile->Read(); - _Node->mData = New(_Node->mSize); + _Node->mData = vtx_allocate_internal(_Node->mSize); for (u32 i = 0; i != _Node->mSize; ++i) { if (isUsingF32Vtx) { _Node->mData[i].n.ob[0] = aFile->Read(); diff --git a/data/dynos_c.cpp b/data/dynos_c.cpp index eca2ff90a..2ac11970c 100644 --- a/data/dynos_c.cpp +++ b/data/dynos_c.cpp @@ -270,12 +270,42 @@ void dynos_model_overwrite_slot(u32 srcSlot, u32 dstSlot) { DynOS_Model_OverwriteSlot(srcSlot, dstSlot); } -Gfx *dynos_model_get_writable_display_list(Gfx* gfx) { - return DynOS_Model_GetWritableDisplayList(gfx); +// -- gfx -- // + +Gfx *dynos_gfx_get_writable_display_list(Gfx* gfx) { + return DynOS_Gfx_GetWritableDisplayList(gfx); } -void dynos_model_restore_vanilla_display_lists() { - return DynOS_Model_RestoreVanillaDisplayLists(); +Gfx *dynos_gfx_get(const char *name, u32 *outLength) { + return DynOS_Gfx_Get(name, outLength); +} + +Gfx *dynos_gfx_new(const char *name, u32 length) { + return DynOS_Gfx_New(name, length); +} + +Gfx *dynos_gfx_realloc(Gfx *gfx, u32 newLength) { + return DynOS_Gfx_Realloc(gfx, newLength); +} + +bool dynos_gfx_delete(Gfx *gfx) { + return DynOS_Gfx_Delete(gfx); +} + +Vtx *dynos_vtx_get(const char *name, u32 *outCount) { + return DynOS_Vtx_Get(name, outCount); +} + +Vtx *dynos_vtx_new(const char *name, u32 count) { + return DynOS_Vtx_New(name, count); +} + +Vtx *dynos_vtx_realloc(Vtx *vtx, u32 newCount) { + return DynOS_Vtx_Realloc(vtx, newCount); +} + +bool dynos_vtx_delete(Vtx *vtx) { + return DynOS_Vtx_Delete(vtx); } // -- other -- // diff --git a/data/dynos_main.cpp b/data/dynos_main.cpp index c8ea20509..6d11ccb1b 100644 --- a/data/dynos_main.cpp +++ b/data/dynos_main.cpp @@ -45,6 +45,7 @@ void DynOS_Mod_Update() { DynOS_Bhv_ModShutdown(); DynOS_MovtexQC_ModShutdown(); DynOS_Tex_ModShutdown(); + DynOS_Gfx_ModShutdown(); } } diff --git a/data/dynos_mgr_actor.cpp b/data/dynos_mgr_actor.cpp index e4e60ccfe..b49027e91 100644 --- a/data/dynos_mgr_actor.cpp +++ b/data/dynos_mgr_actor.cpp @@ -24,6 +24,10 @@ static Array>& DynosCustomActors() { // TODO: the cleanup/refactor didn't really go as planned. // clean up the actor management code more +std::map &DynOS_Actor_GetValidActors() { + return DynosValidActors(); +} + void DynOS_Actor_AddCustom(s32 aModIndex, const SysPath &aFilename, const char *aActorName) { const void* georef = DynOS_Builtin_Actor_GetFromName(aActorName); diff --git a/data/dynos_mgr_gfx.cpp b/data/dynos_mgr_gfx.cpp new file mode 100644 index 000000000..84833b389 --- /dev/null +++ b/data/dynos_mgr_gfx.cpp @@ -0,0 +1,230 @@ +#include "dynos.cpp.h" + +extern "C" { +#include "pc/lua/smlua.h" +#include "pc/lua/utils/smlua_gfx_utils.h" +} + +static ModData sModDisplayLists; +static ModData sModVertexBuffers; + +// Maps read-only Gfx and Vtx buffers to their writable duplicates +static std::map> sRomToRamGfxVtxMap; + +static Vtx *DynOS_Vtx_Duplicate(Vtx *aVtx, u32 vtxCount, bool shouldDuplicate) { + if (!aVtx) { return NULL; } + + // Return duplicate if it already exists + auto it = sRomToRamGfxVtxMap.find(aVtx); + if (it != sRomToRamGfxVtxMap.end()) { + return (Vtx *) it->second.first; + } + + // Duplicate vertex buffer and return the copy + if (shouldDuplicate) { + size_t vtxSize = vtxCount * sizeof(Vtx); + Vtx *vtxDuplicate = vtx_allocate_internal(vtxCount); + memcpy(vtxDuplicate, aVtx, vtxSize); + DynOS_Find_Pending_Scroll_Target(aVtx, vtxDuplicate); + sRomToRamGfxVtxMap[aVtx] = { (void *) vtxDuplicate, vtxSize }; + return vtxDuplicate; + } + + return aVtx; +} + +static Gfx *DynOS_Gfx_Duplicate(Gfx *aGfx, bool shouldDuplicate) { + if (!aGfx) { return NULL; } + + // Return duplicate if it already exists + auto it = sRomToRamGfxVtxMap.find(aGfx); + if (it != sRomToRamGfxVtxMap.end()) { + return (Gfx *) it->second.first; + } + + // Check if it's vanilla + if (!shouldDuplicate) { + shouldDuplicate = (DynOS_Builtin_Gfx_GetFromData(aGfx) != NULL); + } + + // Duplicate display list + Gfx *gfxDuplicate = aGfx; + u32 gfxLength = shouldDuplicate ? gfx_get_length_no_sentinel(aGfx) : gfx_get_length(aGfx); + if (shouldDuplicate) { + size_t gfxSize = gfxLength * sizeof(Gfx); + gfxDuplicate = gfx_allocate_internal(gfxLength); + memcpy(gfxDuplicate, aGfx, gfxSize); + sRomToRamGfxVtxMap[aGfx] = { (void *) gfxDuplicate, gfxSize }; + } + + // Look for other display lists or vertices + for (u32 i = 0; i < gfxLength; i++) { + Gfx *cmd = gfxDuplicate + i; + u32 op = GFX_OP(cmd); + + // Duplicate referenced display lists + if (op == G_DL) { + cmd->words.w1 = (uintptr_t) DynOS_Gfx_Duplicate((Gfx *) cmd->words.w1, shouldDuplicate); + if (C0(cmd, 16, 1) == G_DL_NOPUSH) { break; } // This is a branch (jump), end of display list + } + + // Duplicate referenced vertices + if (op == G_VTX) { + cmd->words.w1 = (uintptr_t) DynOS_Vtx_Duplicate((Vtx *) cmd->words.w1, C0(cmd, 12, 8), shouldDuplicate); + } + } + + return gfxDuplicate; +} + +// Get a writable display list so it can be modified by mods +// If it's a vanilla display list, duplicate it, so it can be restored later +Gfx *DynOS_Gfx_GetWritableDisplayList(Gfx *aGfx) { + return DynOS_Gfx_Duplicate(aGfx, false); +} + +Gfx *DynOS_Gfx_Get(const char *aName, u32 *outLength) { + if (!aName) { return NULL; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + // Check mod data + Gfx *gfx = DynOS_ModData_Get(sModDisplayLists, modIndex, aName, outLength); + if (gfx) { + return gfx; + } + + // Check levels + for (auto &lvl : DynOS_Lvl_GetArray()) { + if (modIndex == -1 || lvl.second->mModIndex == modIndex) { + for (auto &gfx : lvl.second->mDisplayLists) { + if (gfx->mName == aName) { + *outLength = gfx->mSize; + return gfx->mData; + } + } + } + } + + // Check loaded actors + for (auto &actor : DynOS_Actor_GetValidActors()) { + if (modIndex == -1 || actor.second.mGfxData->mModIndex == modIndex) { + for (auto &gfx : actor.second.mGfxData->mDisplayLists) { + if (gfx->mName == aName) { + *outLength = gfx->mSize; + return gfx->mData; + } + } + } + } + + // Check vanilla display lists + const Gfx *gfxVanilla = DynOS_Builtin_Gfx_GetFromName(aName); + if (gfxVanilla) { + auto it = sRomToRamGfxVtxMap.find(gfxVanilla); + + // If not found, duplicate the display list now + if (it == sRomToRamGfxVtxMap.end()) { + DynOS_Gfx_Duplicate((Gfx *) gfxVanilla, true); + it = sRomToRamGfxVtxMap.find(gfxVanilla); + } + + *outLength = it->second.second / sizeof(Gfx); + return (Gfx *) it->second.first; + } + + return NULL; +} + +Gfx *DynOS_Gfx_New(const char *aName, u32 aLength) { + if (!aName || !aLength) { return NULL; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + return DynOS_ModData_New(sModDisplayLists, modIndex, aName, aLength, gfx_allocate_internal); +} + +Gfx *DynOS_Gfx_Realloc(Gfx *aGfx, u32 aNewLength) { + if (!aGfx || !aNewLength) { return NULL; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + return DynOS_ModData_Realloc(sModDisplayLists, modIndex, aGfx, aNewLength, gfx_allocate_internal, free); +} + +bool DynOS_Gfx_Delete(Gfx *aGfx) { + if (!aGfx) { return false; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + return DynOS_ModData_Delete(sModDisplayLists, modIndex, aGfx, free); +} + +Vtx *DynOS_Vtx_Get(const char *aName, u32 *outCount) { + if (!aName) { return NULL; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + // Check mod data + Vtx *vtx = DynOS_ModData_Get(sModVertexBuffers, modIndex, aName, outCount); + if (vtx) { + return vtx; + } + + // Check levels + for (auto &lvl : DynOS_Lvl_GetArray()) { + if (modIndex == -1 || lvl.second->mModIndex == modIndex) { + for (auto &vtx : lvl.second->mVertices) { + if (vtx->mName == aName) { + *outCount = vtx->mSize; + return vtx->mData; + } + } + } + } + + // Check loaded actors + for (auto &actor : DynOS_Actor_GetValidActors()) { + if (modIndex == -1 || actor.second.mGfxData->mModIndex == modIndex) { + for (auto &vtx : actor.second.mGfxData->mVertices) { + if (vtx->mName == aName) { + *outCount = vtx->mSize; + return vtx->mData; + } + } + } + } + + return NULL; +} + +Vtx *DynOS_Vtx_New(const char *aName, u32 aCount) { + if (!aName || !aCount) { return NULL; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + return DynOS_ModData_New(sModVertexBuffers, modIndex, aName, aCount, vtx_allocate_internal); +} + +Vtx *DynOS_Vtx_Realloc(Vtx *aVtx, u32 aNewCount) { + if (!aVtx || !aNewCount) { return NULL; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + return DynOS_ModData_Realloc(sModVertexBuffers, modIndex, aVtx, aNewCount, vtx_allocate_internal, free); +} + +bool DynOS_Vtx_Delete(Vtx *aVtx) { + if (!aVtx) { return false; } + s32 modIndex = (gLuaActiveMod ? gLuaActiveMod->index : -1); + + return DynOS_ModData_Delete(sModVertexBuffers, modIndex, aVtx, free); +} + +void DynOS_Gfx_ModShutdown() { + + // Delete all allocated display lists and vertex buffers + DynOS_ModData_DeleteAll(sModDisplayLists, free); + DynOS_ModData_DeleteAll(sModVertexBuffers, free); + + // Restore vanilla display lists + for (auto &it : sRomToRamGfxVtxMap) { + const void *original = it.first; + void *duplicate = it.second.first; + size_t size = it.second.second; + memcpy(duplicate, original, size); + } +} diff --git a/data/dynos_mgr_moddata.hpp b/data/dynos_mgr_moddata.hpp new file mode 100644 index 000000000..fb15cd60a --- /dev/null +++ b/data/dynos_mgr_moddata.hpp @@ -0,0 +1,104 @@ + +template +T *DynOS_ModData_Get(ModData &aModData, s32 aModIndex, const char *aName, u32 *outCount) { + if (!aName) { return NULL; } + + auto itMod = aModData.find(aModIndex); + if (itMod == aModData.end()) { + return NULL; + } + + auto itItem = itMod->second.find(aName); + if (itItem == itMod->second.end()) { + return NULL; + } + + if (outCount) { + *outCount = itItem->second.second; + } + return itItem->second.first; +} + +template +bool DynOS_ModData_Find(ModData &aModData, s32 aModIndex, T *aPointer, std::string &outName) { + if (!aPointer) { return false; } + + auto itMod = aModData.find(aModIndex); + if (itMod == aModData.end()) { + return false; + } + + for (auto &modItem : itMod->second) { + if (modItem.second.first == aPointer) { + outName = modItem.first; + return true; + } + } + + return false; +} + +template +T *DynOS_ModData_New(ModData &aModData, s32 aModIndex, const char *aName, u32 aCount, Allocator aAllocator) { + if (!aName || !aCount) { return NULL; } + + if (DynOS_ModData_Get(aModData, aModIndex, aName, NULL)) { + return NULL; + } + + auto itMod = aModData.find(aModIndex); + if (itMod == aModData.end()) { + aModData[aModIndex] = {}; + } + + T *newItem = aAllocator(aCount); + aModData[aModIndex][aName] = { newItem, aCount }; + return newItem; +} + +template +T *DynOS_ModData_Realloc(ModData &aModData, s32 aModIndex, T *aPointer, u32 aNewCount, Allocator aAllocator, Deallocator aDeallocator) { + if (!aPointer) { return NULL; } + + std::string itemName; + if (!DynOS_ModData_Find(aModData, aModIndex, aPointer, itemName)) { + return NULL; + } + + // No need to shrink the existing buffer + auto &modItem = aModData[aModIndex][itemName]; + u32 itemCount = modItem.second; + if (aNewCount < itemCount) { + return modItem.first; + } + + T *newItem = aAllocator(aNewCount); + memcpy(newItem, aPointer, itemCount * sizeof(T)); + aDeallocator(aPointer); + aModData[aModIndex][itemName] = { newItem, aNewCount }; + return newItem; +} + +template +bool DynOS_ModData_Delete(ModData &aModData, s32 aModIndex, T *aPointer, Deallocator aDeallocator) { + if (!aPointer) { return false; } + + std::string itemName; + if (!DynOS_ModData_Find(aModData, aModIndex, aPointer, itemName)) { + return false; + } + + aDeallocator(aPointer); + aModData[aModIndex].erase(itemName); + return true; +} + +template +void DynOS_ModData_DeleteAll(ModData &aModData, Deallocator aDeallocator) { + for (auto &modItems : aModData) { + for (auto &modItem : modItems.second) { + aDeallocator(modItem.second.first); + } + } + aModData.clear(); +} diff --git a/data/dynos_mgr_models.cpp b/data/dynos_mgr_models.cpp index 2d9972cf8..1190a681c 100644 --- a/data/dynos_mgr_models.cpp +++ b/data/dynos_mgr_models.cpp @@ -1,4 +1,3 @@ -#include #include #include "dynos.cpp.h" @@ -7,8 +6,6 @@ extern "C" { #include "engine/graph_node.h" #include "model_ids.h" #include "pc/lua/utils/smlua_model_utils.h" -#include "engine/display_list.h" -#include "dynos_mgr_builtin_externs.h" } enum ModelLoadType { @@ -30,9 +27,6 @@ static std::map sAssetMap[MODEL_POOL_MAX]; static std::map> sIdMap; static std::map sOverwriteMap; -// Maps read-only Gfx and Vtx buffers to their writable duplicates -static std::map> sRomToRamGfxVtxMap; - static u32 find_empty_id(bool aIsPermanent) { u32 id = aIsPermanent ? 9999 : VANILLA_ID_END + 1; s8 dir = aIsPermanent ? -1 : 1; @@ -247,87 +241,6 @@ void DynOS_Model_OverwriteSlot(u32 srcSlot, u32 dstSlot) { sOverwriteMap[srcSlot] = dstSlot; } -static Vtx *DynOS_Model_DuplicateVtx(Vtx *aVtx, u32 vtxCount, bool shouldDuplicate) { - if (!aVtx) { return NULL; } - - // Return duplicate if it already exists - auto it = sRomToRamGfxVtxMap.find((void *) aVtx); - if (it != sRomToRamGfxVtxMap.end()) { - return (Vtx *) it->second.first; - } - - // Duplicate vertex buffer and return the copy - if (shouldDuplicate) { - size_t vtxSize = vtxCount * sizeof(Vtx); - Vtx *vtxDuplicate = (Vtx *) malloc(vtxSize); - memcpy(vtxDuplicate, aVtx, vtxSize); - DynOS_Find_Pending_Scroll_Target(aVtx, vtxDuplicate); - sRomToRamGfxVtxMap[(void *) aVtx] = { (void *) vtxDuplicate, vtxSize }; - return vtxDuplicate; - } - - return aVtx; -} - -static Gfx *DynOS_Model_DuplicateDisplayList(Gfx *aGfx, bool shouldDuplicate) { - if (!aGfx) { return NULL; } - - // Return duplicate if it already exists - auto it = sRomToRamGfxVtxMap.find((void *) aGfx); - if (it != sRomToRamGfxVtxMap.end()) { - return (Gfx *) it->second.first; - } - - // Check if it's vanilla - if (!shouldDuplicate) { - shouldDuplicate = (DynOS_Builtin_Gfx_GetFromData(aGfx) != NULL); - } - - // Duplicate display list - Gfx *gfxDuplicate = aGfx; - u32 gfxLength = gfx_get_size(aGfx); - if (shouldDuplicate) { - size_t gfxSize = gfxLength * sizeof(Gfx); - gfxDuplicate = (Gfx *) malloc(gfxSize); - memcpy(gfxDuplicate, aGfx, gfxSize); - sRomToRamGfxVtxMap[(void *) aGfx] = { (void *) gfxDuplicate, gfxSize }; - } - - // Look for other display lists or vertices - for (u32 i = 0; i < gfxLength; i++) { - Gfx *cmd = gfxDuplicate + i; - u32 op = cmd->words.w0 >> 24; - - // Duplicate referenced display lists - if (op == G_DL) { - cmd->words.w1 = (uintptr_t) DynOS_Model_DuplicateDisplayList((Gfx *) cmd->words.w1, shouldDuplicate); - if (C0(cmd, 16, 1) == G_DL_NOPUSH) { break; } // This is a branch (jump), end of display list - } - - // Duplicate referenced vertices - if (op == G_VTX) { - cmd->words.w1 = (uintptr_t) DynOS_Model_DuplicateVtx((Vtx *) cmd->words.w1, C0(cmd, 12, 8), shouldDuplicate); - } - } - - return gfxDuplicate; -} - -// Get a writable display list so it can be modified by mods -// If it's a vanilla display list, duplicate it, so it can be restored later -Gfx *DynOS_Model_GetWritableDisplayList(Gfx *aGfx) { - return DynOS_Model_DuplicateDisplayList(aGfx, false); -} - -void DynOS_Model_RestoreVanillaDisplayLists() { - for (auto &it : sRomToRamGfxVtxMap) { - const void *original = it.first; - void *duplicate = it.second.first; - size_t size = it.second.second; - memcpy(duplicate, original, size); - } -} - void DynOS_Model_ClearPool(enum ModelPool aModelPool) { if (!sModelPools[aModelPool]) { return; } diff --git a/data/dynos_mgr_tex.cpp b/data/dynos_mgr_tex.cpp index 96e36f926..f517b184c 100644 --- a/data/dynos_mgr_tex.cpp +++ b/data/dynos_mgr_tex.cpp @@ -35,6 +35,11 @@ static Array *>& DynosScheduledInvalidTextures() { return sDynosScheduledInvalidTextures; } +static Array*>>& DynosCustomTexs() { + static Array*>> sDynosCustomTexs; + return sDynosCustomTexs; +} + static bool sDynosDumpTextureCache = false; // @@ -329,6 +334,15 @@ static DataNode *DynOS_Tex_RetrieveNode(void *aPtr) { if (_ValidTextures.find((DataNode*)aPtr) != _ValidTextures.end()) { return (DataNode*)aPtr; } + + auto& _DynosCustomTexs = DynosCustomTexs(); + for (auto &_DynosCustomTex : _DynosCustomTexs) { + auto& _Node = _DynosCustomTex.second; + if (aPtr == (void *) _Node->mData->mRawData.begin()) { + return _Node; + } + } + return NULL; } @@ -360,11 +374,6 @@ bool DynOS_Tex_Import(void **aOutput, void *aPtr, s32 aTile, void *aGfxRApi, voi // Custom Textures // ///////////////////// -static Array*>>& DynosCustomTexs() { - static Array*>> sDynosCustomTexs; - return sDynosCustomTexs; -} - void DynOS_Tex_Activate(DataNode* aNode, bool aCustomTexture) { if (!aNode) { return; } diff --git a/docs/lua/constants.md b/docs/lua/constants.md index 1d343fc60..ecaff1332 100644 --- a/docs/lua/constants.md +++ b/docs/lua/constants.md @@ -1237,58 +1237,30 @@ ## [gbi.h](#gbi.h) - G_COPYMEM - G_NOOP -- G_RDPHALF_2 - G_SETOTHERMODE_H - G_SETOTHERMODE_L -- G_RDPHALF_1 -- G_SPNOOP - G_ENDDL - G_DL -- G_LOAD_UCODE - G_MOVEMEM - G_MOVEWORD - G_MTX - G_GEOMETRYMODE - G_POPMTX - G_TEXTURE -- G_DMA_IO -- G_SPECIAL_1 -- G_SPECIAL_2 -- G_SPECIAL_3 - G_VTX -- G_MODIFYVTX -- G_CULLDL -- G_BRANCH_Z - G_TRI1 - G_TRI2 -- G_QUAD -- G_LINE3D -- G_SPNOOP - G_MTX -- G_RESERVED0 - G_MOVEMEM - G_VTX -- G_RESERVED1 - G_DL -- G_RESERVED2 -- G_RESERVED3 -- G_SPRITE2D_BASE -- G_IMMFIRST - G_TRI1 -- G_CULLDL - G_POPMTX - G_MOVEWORD - G_TEXTURE - G_SETOTHERMODE_H - G_SETOTHERMODE_L - G_ENDDL -- G_SETGEOMETRYMODE -- G_CLEARGEOMETRYMODE -- G_LINE3D -- G_RDPHALF_1 -- G_RDPHALF_2 -- G_SPRITE2D_SCALEFLIP -- G_SPRITE2D_DRAW - G_NOOP - G_SETCIMG - G_SETZIMG @@ -1305,316 +1277,9 @@ - G_LOADBLOCK - G_SETTILESIZE - G_LOADTLUT -- G_RDPSETOTHERMODE -- G_SETPRIMDEPTH - G_SETSCISSOR -- G_SETCONVERT -- G_SETKEYR -- G_SETKEYGB -- G_RDPFULLSYNC -- G_RDPTILESYNC -- G_RDPPIPESYNC -- G_RDPLOADSYNC - G_TEXRECTFLIP - G_TEXRECT -- G_TRI_FILL -- G_TRI_SHADE -- G_TRI_TXTR -- G_TRI_SHADE_TXTR -- G_TRI_FILL_ZBUFF -- G_TRI_SHADE_ZBUFF -- G_TRI_TXTR_ZBUFF -- G_TRI_SHADE_TXTR_ZBUFF -- G_RDP_TRI_FILL_MASK -- G_RDP_TRI_SHADE_MASK -- G_RDP_TRI_TXTR_MASK -- G_RDP_TRI_ZBUFF_MASK -- BOWTIE_VAL -- G_RDP_ADDR_FIXUP -- G_DMACMDSIZ -- G_IMMCMDSIZ -- G_RDPCMDSIZ -- G_TEXTURE_IMAGE_FRAC -- G_TEXTURE_SCALE_FRAC -- G_SCALE_FRAC -- G_ROTATE_FRAC -- G_MAXFBZ -- G_ZBUFFER -- G_SHADE -- G_FOG -- G_LIGHTING -- G_TEXTURE_GEN -- G_TEXTURE_GEN_LINEAR -- G_LOD -- G_IM_FMT_RGBA -- G_IM_FMT_YUV -- G_IM_FMT_CI -- G_IM_FMT_IA -- G_IM_FMT_I -- G_IM_SIZ_4b -- G_IM_SIZ_8b -- G_IM_SIZ_16b -- G_IM_SIZ_32b -- G_IM_SIZ_DD -- G_IM_SIZ_4b_BYTES -- G_IM_SIZ_8b_BYTES -- G_IM_SIZ_16b_BYTES -- G_IM_SIZ_32b_BYTES -- G_IM_SIZ_32b_TILE_BYTES -- G_IM_SIZ_32b_LINE_BYTES -- G_IM_SIZ_4b_SHIFT -- G_IM_SIZ_8b_SHIFT -- G_IM_SIZ_16b_SHIFT -- G_IM_SIZ_32b_SHIFT -- G_IM_SIZ_4b_INCR -- G_IM_SIZ_8b_INCR -- G_IM_SIZ_16b_INCR -- G_IM_SIZ_32b_INCR -- G_CCMUX_COMBINED -- G_CCMUX_TEXEL0 -- G_CCMUX_TEXEL1 -- G_CCMUX_PRIMITIVE -- G_CCMUX_SHADE -- G_CCMUX_ENVIRONMENT -- G_CCMUX_CENTER -- G_CCMUX_SCALE -- G_CCMUX_COMBINED_ALPHA -- G_CCMUX_TEXEL0_ALPHA -- G_CCMUX_TEXEL1_ALPHA -- G_CCMUX_PRIMITIVE_ALPHA -- G_CCMUX_SHADE_ALPHA -- G_CCMUX_ENV_ALPHA -- G_CCMUX_LOD_FRACTION -- G_CCMUX_PRIM_LOD_FRAC -- G_CCMUX_NOISE -- G_CCMUX_K4 -- G_CCMUX_K5 -- G_CCMUX_1 -- G_CCMUX_0 -- G_ACMUX_COMBINED -- G_ACMUX_TEXEL0 -- G_ACMUX_TEXEL1 -- G_ACMUX_PRIMITIVE -- G_ACMUX_SHADE -- G_ACMUX_ENVIRONMENT -- G_ACMUX_LOD_FRACTION -- G_ACMUX_PRIM_LOD_FRAC -- G_ACMUX_1 -- G_ACMUX_0 -- G_MDSFT_ALPHACOMPARE -- G_MDSFT_ZSRCSEL -- G_MDSFT_RENDERMODE -- G_MDSFT_BLENDER -- G_MDSFT_BLENDMASK -- G_MDSFT_ALPHADITHER -- G_MDSFT_RGBDITHER -- G_MDSFT_COMBKEY -- G_MDSFT_TEXTCONV -- G_MDSFT_TEXTFILT -- G_MDSFT_TEXTLUT -- G_MDSFT_TEXTLOD -- G_MDSFT_TEXTDETAIL -- G_MDSFT_TEXTPERSP -- G_MDSFT_CYCLETYPE -- G_MDSFT_COLORDITHER -- G_MDSFT_PIPELINE -- G_PM_1PRIMITIVE -- G_PM_NPRIMITIVE -- G_CYC_1CYCLE -- G_CYC_2CYCLE -- G_CYC_COPY -- G_CYC_FILL -- G_TP_NONE -- G_TP_PERSP -- G_TD_CLAMP -- G_TD_SHARPEN -- G_TD_DETAIL -- G_TL_TILE -- G_TL_LOD -- G_TT_NONE -- G_TT_RGBA16 -- G_TT_IA16 -- G_TF_POINT -- G_TF_AVERAGE -- G_TF_BILERP -- G_TC_CONV -- G_TC_FILTCONV -- G_TC_FILT -- G_CK_NONE -- G_CK_KEY -- G_CD_MAGICSQ -- G_CD_BAYER -- G_CD_NOISE -- G_CD_DISABLE -- G_CD_ENABLE -- G_CD_ENABLE -- G_CD_DISABLE -- G_AD_PATTERN -- G_AD_NOTPATTERN -- G_AD_NOISE -- G_AD_DISABLE -- G_AC_NONE -- G_AC_THRESHOLD -- G_AC_DITHER -- G_ZS_PIXEL -- G_ZS_PRIM -- AA_EN -- Z_CMP -- Z_UPD -- IM_RD -- CLR_ON_CVG -- CVG_DST_CLAMP -- CVG_DST_WRAP -- CVG_DST_FULL -- CVG_DST_SAVE -- ZMODE_OPA -- ZMODE_INTER -- ZMODE_XLU -- ZMODE_DEC -- CVG_X_ALPHA -- ALPHA_CVG_SEL -- FORCE_BL -- TEX_EDGE -- G_BL_CLR_IN -- G_BL_CLR_MEM -- G_BL_CLR_BL -- G_BL_CLR_FOG -- G_BL_1MA -- G_BL_A_MEM -- G_BL_A_IN -- G_BL_A_FOG -- G_BL_A_SHADE -- G_BL_1 -- G_BL_0 -- G_CV_K0 -- G_CV_K1 -- G_CV_K2 -- G_CV_K3 -- G_CV_K4 -- G_CV_K5 -- G_SC_NON_INTERLACE -- G_SC_ODD_INTERLACE -- G_SC_EVEN_INTERLACE -- G_DL_PUSH -- G_DL_NOPUSH -- G_MW_MATRIX -- G_MW_NUMLIGHT -- G_MW_CLIP -- G_MW_SEGMENT -- G_MW_FOG -- G_MW_LIGHTCOL -- G_MW_PERSPNORM -- G_MWO_NUMLIGHT -- G_MWO_CLIP_RNX -- G_MWO_CLIP_RNY -- G_MWO_CLIP_RPX -- G_MWO_CLIP_RPY -- G_MWO_SEGMENT_0 -- G_MWO_SEGMENT_1 -- G_MWO_SEGMENT_2 -- G_MWO_SEGMENT_3 -- G_MWO_SEGMENT_4 -- G_MWO_SEGMENT_5 -- G_MWO_SEGMENT_6 -- G_MWO_SEGMENT_7 -- G_MWO_SEGMENT_8 -- G_MWO_SEGMENT_9 -- G_MWO_SEGMENT_A -- G_MWO_SEGMENT_B -- G_MWO_SEGMENT_C -- G_MWO_SEGMENT_D -- G_MWO_SEGMENT_E -- G_MWO_SEGMENT_F -- G_MWO_FOG -- G_MWO_aLIGHT_1 -- G_MWO_bLIGHT_1 -- G_MWO_aLIGHT_2 -- G_MWO_bLIGHT_2 -- G_MWO_aLIGHT_3 -- G_MWO_bLIGHT_3 -- G_MWO_aLIGHT_4 -- G_MWO_bLIGHT_4 -- G_MWO_aLIGHT_5 -- G_MWO_bLIGHT_5 -- G_MWO_aLIGHT_6 -- G_MWO_bLIGHT_6 -- G_MWO_aLIGHT_7 -- G_MWO_bLIGHT_7 -- G_MWO_aLIGHT_8 -- G_MWO_bLIGHT_8 -- G_MWO_aLIGHT_2 -- G_MWO_bLIGHT_2 -- G_MWO_aLIGHT_3 -- G_MWO_bLIGHT_3 -- G_MWO_aLIGHT_4 -- G_MWO_bLIGHT_4 -- G_MWO_aLIGHT_5 -- G_MWO_bLIGHT_5 -- G_MWO_aLIGHT_6 -- G_MWO_bLIGHT_6 -- G_MWO_aLIGHT_7 -- G_MWO_bLIGHT_7 -- G_MWO_aLIGHT_8 -- G_MWO_bLIGHT_8 -- G_MWO_MATRIX_XX_XY_I -- G_MWO_MATRIX_XZ_XW_I -- G_MWO_MATRIX_YX_YY_I -- G_MWO_MATRIX_YZ_YW_I -- G_MWO_MATRIX_ZX_ZY_I -- G_MWO_MATRIX_ZZ_ZW_I -- G_MWO_MATRIX_WX_WY_I -- G_MWO_MATRIX_WZ_WW_I -- G_MWO_MATRIX_XX_XY_F -- G_MWO_MATRIX_XZ_XW_F -- G_MWO_MATRIX_YX_YY_F -- G_MWO_MATRIX_YZ_YW_F -- G_MWO_MATRIX_ZX_ZY_F -- G_MWO_MATRIX_ZZ_ZW_F -- G_MWO_MATRIX_WX_WY_F -- G_MWO_MATRIX_WZ_WW_F -- G_MWO_POINT_RGBA -- G_MWO_POINT_ST -- G_MWO_POINT_XYSCREEN -- G_MWO_POINT_ZSCREEN -- FR_NEG_FRUSTRATIO_1 -- FR_POS_FRUSTRATIO_1 -- FR_NEG_FRUSTRATIO_2 -- FR_POS_FRUSTRATIO_2 -- FR_NEG_FRUSTRATIO_3 -- FR_POS_FRUSTRATIO_3 -- FR_NEG_FRUSTRATIO_4 -- FR_POS_FRUSTRATIO_4 -- FR_NEG_FRUSTRATIO_5 -- FR_POS_FRUSTRATIO_5 -- FR_NEG_FRUSTRATIO_6 -- FR_POS_FRUSTRATIO_6 -- NUMLIGHTS_0 -- NUMLIGHTS_1 -- NUMLIGHTS_2 -- NUMLIGHTS_3 -- NUMLIGHTS_4 -- NUMLIGHTS_5 -- NUMLIGHTS_6 -- NUMLIGHTS_7 -- LIGHT_1 -- LIGHT_2 -- LIGHT_3 -- LIGHT_4 -- LIGHT_5 -- LIGHT_6 -- LIGHT_7 -- LIGHT_8 -- G_TX_LOADTILE -- G_TX_RENDERTILE -- G_TX_NOMIRROR -- G_TX_WRAP -- G_TX_MIRROR -- G_TX_CLAMP -- G_TX_NOMASK -- G_TX_NOLOD -- G_TX_DXT_FRAC -- G_TX_LDBLK_MAX_TXL -- G_TX_LDBLK_MAX_TXL [:arrow_up_small:](#) diff --git a/docs/lua/examples/gfx-vtx-demo/a-math.lua b/docs/lua/examples/gfx-vtx-demo/a-math.lua new file mode 100644 index 000000000..0362c24cc --- /dev/null +++ b/docs/lua/examples/gfx-vtx-demo/a-math.lua @@ -0,0 +1,155 @@ +-- +-- Math stuff +-- Don't mind this file, it's not relevant to the purpose of this demo. +-- + +local SHAPE_SIZE = 100 +local SHAPE_TEXTURE_SIZE = 512 + +---------- +-- Cube -- +---------- + +local CUBE_ROTATIONS = { + { x = 0x0000, y = 0x0000, z = 0 }, + { x = 0x0000, y = 0x4000, z = 0 }, + { x = 0x0000, y = 0x8000, z = 0 }, + { x = 0x0000, y = 0xC000, z = 0 }, + { x = 0x4000, y = 0x0000, z = 0 }, + { x = 0xC000, y = 0x0000, z = 0 }, +} + +local CUBE_POINTS = { + { x = -1, y = -1, z = -1, tu = 0, tv = (SHAPE_TEXTURE_SIZE - 1) << 5 }, + { x = 1, y = -1, z = -1, tu = 0, tv = 0 }, + { x = -1, y = 1, z = -1, tu = (SHAPE_TEXTURE_SIZE - 1) << 5, tv = (SHAPE_TEXTURE_SIZE - 1) << 5 }, + { x = 1, y = 1, z = -1, tu = (SHAPE_TEXTURE_SIZE - 1) << 5, tv = 0 }, +} + +function get_cube_vertices() + vertices = {} + for _, r in ipairs(CUBE_ROTATIONS) do + for _, p in ipairs(CUBE_POINTS) do + local v = { x = p.x * SHAPE_SIZE, y = p.y * SHAPE_SIZE, z = p.z * SHAPE_SIZE } + vec3f_rotate_zxy(v, r) + table.insert(vertices, { x = v.x, y = v.y, z = v.z, tu = p.tu, tv = p.tv, r = 0xFF, g = 0xFF, b = 0xFF }) + end + end + return vertices +end + +function get_cube_triangles() + local triangles = {} + for i = 0, 5 do + local offset = 4 * i + table.insert(triangles, { + offset + 0, offset + 1, offset + 2, + offset + 2, offset + 1, offset + 3 + }) + end + return triangles +end + +function get_cube_geometry_mode() + return "G_TEXTURE_GEN | G_CULL_BOTH | G_LIGHTING", "0" +end + +function get_cube_texture_scaling() + return 0xFFFF +end + +---------------- +-- Octahedron -- +---------------- + +function get_octahedron_vertices() + local vertices = {} + table.insert(vertices, { x = 0, y = -SHAPE_SIZE, z = 0, tu = 0, tv = (SHAPE_TEXTURE_SIZE / 2) << 5, r = 0xFF, g = 0xFF, b = 0xFF }) + table.insert(vertices, { x = 0, y = SHAPE_SIZE, z = 0, tu = (SHAPE_TEXTURE_SIZE - 1) << 5, tv = (SHAPE_TEXTURE_SIZE / 2) << 5, r = 0xFF, g = 0xFF, b = 0xFF }) + for i = 0, 3 do + local sina = sins(0x4000 * i) * SHAPE_SIZE + local cosa = coss(0x4000 * i) * SHAPE_SIZE + table.insert(vertices, { x = sina, y = 0, z = cosa, tu = (SHAPE_TEXTURE_SIZE - 1) << 5, tv = (SHAPE_TEXTURE_SIZE - 1) << 5, r = 0xFF, g = 0xFF, b = 0xFF }) + table.insert(vertices, { x = sina, y = 0, z = cosa, tu = (SHAPE_TEXTURE_SIZE - 1) << 5, tv = 0, r = 0xFF, g = 0xFF, b = 0xFF }) + table.insert(vertices, { x = sina, y = 0, z = cosa, tu = 0, tv = (SHAPE_TEXTURE_SIZE - 1) << 5, r = 0xFF, g = 0xFF, b = 0xFF }) + table.insert(vertices, { x = sina, y = 0, z = cosa, tu = 0, tv = 0, r = 0xFF, g = 0xFF, b = 0xFF }) + end + return vertices +end + +function get_octahedron_triangles() + local triangles = {} + for i = 0, 3 do + table.insert(triangles, { + 0, 2 + i * 4 + 0, 2 + ((i + 1) % 4) * 4 + 1, + 1, 2 + i * 4 + 2, 2 + ((i + 1) % 4) * 4 + 3 + }) + end + return triangles +end + +function get_octahedron_geometry_mode() + return "G_TEXTURE_GEN | G_CULL_BOTH | G_LIGHTING", "0" +end + +function get_octahedron_texture_scaling() + return 0xFFFF +end + +---------- +-- Star -- +---------- + +local STAR_POINTS = { + { x = 0, y = 8, z = -90, r = 0x00, g = 0x07, b = 0x82 }, + { x = 190, y = -201, z = 0, r = 0x55, g = 0xa3, b = 0x00 }, + { x = 0, y = -129, z = 0, r = 0x00, g = 0x82, b = 0x00 }, + { x = 146, y = -42, z = 0, r = 0x7c, g = 0xe7, b = 0x00 }, + { x = 0, y = 8, z = 90, r = 0x00, g = 0x07, b = 0x7e }, + { x = 256, y = 84, z = 0, r = 0x68, g = 0x47, b = 0x00 }, + { x = -146, y = -42, z = 0, r = 0x84, g = 0xe7, b = 0x00 }, + { x = -190, y = -201, z = 0, r = 0xaa, g = 0xa3, b = 0x00 }, + { x = -256, y = 84, z = 0, r = 0x97, g = 0x47, b = 0x00 }, + { x = 0, y = 246, z = 0, r = 0x00, g = 0x7e, b = 0x00 }, + { x = 96, y = 99, z = 0, r = 0x3d, g = 0x6f, b = 0x00 }, + { x = -96, y = 99, z = 0, r = 0xc3, g = 0x6f, b = 0x00 }, +} + +local STAR_TRIANGLES = { + { 0, 1, 2, 0, 3, 1 }, + { 2, 1, 4, 1, 3, 4 }, + { 5, 3, 0, 4, 3, 5 }, + { 6, 7, 4, 7, 2, 4 }, + { 8, 6, 4, 9, 4, 10 }, + { 9, 11, 4, 4, 5, 10 }, + { 11, 8, 4, 0, 2, 7 }, + { 0, 7, 6, 0, 6, 8 }, + { 0, 8, 11, 0, 11, 9 }, + { 10, 5, 0, 10, 0, 9 }, +} + +function get_star_vertices() + local vertices = {} + for _, p in ipairs(STAR_POINTS) do + table.insert(vertices, { + x = p.x * SHAPE_SIZE / 256, + y = p.y * SHAPE_SIZE / 256, + z = p.z * SHAPE_SIZE / 256, + tu = 0, tv = 0, + r = p.r, g = p.g, b = p.b + }) + end + return vertices +end + +function get_star_triangles() + return STAR_TRIANGLES +end + +function get_star_geometry_mode() + return "G_CULL_BOTH", "G_LIGHTING | G_TEXTURE_GEN" +end + +function get_star_texture_scaling() + return 0x7FC0 +end diff --git a/docs/lua/examples/gfx-vtx-demo/actors/shape/geo.inc.c b/docs/lua/examples/gfx-vtx-demo/actors/shape/geo.inc.c new file mode 100644 index 000000000..580096544 --- /dev/null +++ b/docs/lua/examples/gfx-vtx-demo/actors/shape/geo.inc.c @@ -0,0 +1,8 @@ +const GeoLayout shape_geo[] = { + GEO_NODE_START(), + GEO_OPEN_NODE(), + GEO_ASM(0, geo_update_shape), + GEO_DISPLAY_LIST(LAYER_OPAQUE, shape_template_dl), + GEO_CLOSE_NODE(), + GEO_END(), +}; diff --git a/docs/lua/examples/gfx-vtx-demo/actors/shape/model.inc.c b/docs/lua/examples/gfx-vtx-demo/actors/shape/model.inc.c new file mode 100644 index 000000000..e29ce377a --- /dev/null +++ b/docs/lua/examples/gfx-vtx-demo/actors/shape/model.inc.c @@ -0,0 +1,19 @@ +// The template display list. +// Some values are placeholders that will be filled during the custom GEO ASM function. +Gfx shape_template_dl[] = { +/* [00] */ gsSPGeometryMode(0, 0), +/* [01] */ gsDPSetCombineMode(G_CC_DECALRGBA, G_CC_DECALRGBA), +/* [02] */ gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_ON), +/* [03] */ gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_32b_LOAD_BLOCK, 1, NULL), +/* [04] */ gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_32b_LOAD_BLOCK, 0, 0, G_TX_LOADTILE, 0 , G_TX_CLAMP, 0, G_TX_NOLOD, G_TX_CLAMP, 0, G_TX_NOLOD), +/* [05] */ gsDPLoadSync(), +/* [06] */ gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 0, 0), +/* [07] */ gsDPPipeSync(), +/* [08] */ gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_32b, 128, 0, G_TX_RENDERTILE, 0, G_TX_CLAMP, 0, G_TX_NOLOD, G_TX_CLAMP, 0, G_TX_NOLOD), +/* [09] */ gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, 511 << G_TEXTURE_IMAGE_FRAC, 511 << G_TEXTURE_IMAGE_FRAC), +/* [10] */ gsSPVertex(NULL, 0, 0), +/* [11] */ gsSPDisplayList(NULL), +/* [12] */ gsSPTexture(0xFFFF, 0xFFFF, 0, G_TX_RENDERTILE, G_OFF), +/* [13] */ gsDPSetCombineMode(G_CC_SHADE, G_CC_SHADE), +/* [14] */ gsSPEndDisplayList(), +}; diff --git a/docs/lua/examples/gfx-vtx-demo/main.lua b/docs/lua/examples/gfx-vtx-demo/main.lua new file mode 100644 index 000000000..2e4ab586c --- /dev/null +++ b/docs/lua/examples/gfx-vtx-demo/main.lua @@ -0,0 +1,182 @@ +-- name: Gfx and Vtx manipulation demo +-- description: Press X to move the shape in front of Mario.\nPress Y to change the shape. + +local SHAPE_TEXTURES = {} +for i = 0, 10 do + SHAPE_TEXTURES[i] = get_texture_info("matrix_" .. i) +end + +SHAPES = { + { + name = "Cube", + get_vertices = get_cube_vertices, + get_triangles = get_cube_triangles, + get_geometry_mode = get_cube_geometry_mode, + get_texture_scaling = get_cube_texture_scaling, + }, + { + name = "Octahedron", + get_vertices = get_octahedron_vertices, + get_triangles = get_octahedron_triangles, + get_geometry_mode = get_octahedron_geometry_mode, + get_texture_scaling = get_octahedron_texture_scaling, + }, + { + name = "Star", + get_vertices = get_star_vertices, + get_triangles = get_star_triangles, + get_geometry_mode = get_star_geometry_mode, + get_texture_scaling = get_star_texture_scaling, + } +} + +--- @param gfx Gfx +--- Set the geometry mode of the current shape. +local function set_geometry_mode(gfx) + local clear, set = SHAPES[current_shape + 1].get_geometry_mode() + gfx_set_command(gfx, "gsSPGeometryMode(%s, %s)", clear, set) +end + +--- @param gfx Gfx +--- @param on integer +--- Toggle on/off the texture rendering and set the texture scaling. +local function set_texture_scaling(gfx, on) + local scaling = SHAPES[current_shape + 1].get_texture_scaling() + gfx_set_command(gfx, "gsSPTexture(%i, %i, 0, G_TX_RENDERTILE, %i)", scaling, scaling, on) +end + +--- @param gfx Gfx +--- @param obj Object +--- Update the texture of the current shape. +local function update_texture(gfx, obj) + local texture = SHAPE_TEXTURES[obj.oAnimState].texture + gfx_set_command(gfx, "gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_32b, 1, %t)", texture) +end + +--- @param gfx Gfx +--- @param obj Object +--- Compute the vertices of the current shape and fill the vertex buffer. +local function compute_vertices(gfx, obj) + local vertices = SHAPES[current_shape + 1].get_vertices() + local num_vertices = #vertices + + -- Create a new or retrieve an existing vertex buffer for the shape + -- Use the object pointer to form a unique identifier + local vtx_name = "shape_vertices_" .. tostring(obj._pointer) + local vtx = vtx_get_from_name(vtx_name) + if vtx == nil then + vtx = vtx_new(vtx_name, num_vertices) + else + vtx = vtx_realloc(vtx, num_vertices) + end + + -- Update the vertex command + gfx_set_command(gfx, "gsSPVertex(%v, %i, 0)", vtx, num_vertices) + + -- Fill the vertex buffer + for _, vertex in ipairs(vertices) do + vtx.x = vertex.x + vtx.y = vertex.y + vtx.z = vertex.z + vtx.tu = vertex.tu + vtx.tv = vertex.tv + vtx.r = vertex.r + vtx.g = vertex.g + vtx.b = vertex.b + vtx.a = 0xFF + vtx = vtx_get_next_vertex(vtx) + end +end + +--- @param gfx Gfx +--- @param obj Object +--- Build the triangles for the current shape. +local function build_triangles(gfx, obj) + local triangles = SHAPES[current_shape + 1].get_triangles() + local num_triangles = #triangles + + -- Create a new or retrieve an existing triangles display list for the shape + -- Use the object pointer to form a unique identifier + local tris_name = "shape_triangles_" .. tostring(obj._pointer) + local tris = gfx_get_from_name(tris_name) + if tris == nil then + tris = gfx_new(tris_name, num_triangles + 1) -- +1 for the gsSPEndDisplayList command + else + tris = gfx_realloc(tris, num_triangles + 1) + end + + -- Update the triangles command + gfx_set_command(gfx, "gsSPDisplayList(%g)", tris) + + -- Fill the triangles display list + for _, indices in ipairs(triangles) do + if #indices == 6 then + gfx_set_command(tris, "gsSP2Triangles(%i, %i, %i, 0, %i, %i, %i, 0)", + indices[1], indices[2], indices[3], + indices[4], indices[5], indices[6] + ) + elseif #indices == 3 then + gfx_set_command(tris, "gsSP1Triangle(%i, %i, %i, 0)", + indices[1], indices[2], indices[3] + ) + end + tris = gfx_get_next_command(tris) + end + gfx_set_command(tris, "gsSPEndDisplayList()") +end + +--- @param node GraphNode +--- @param matStackIndex integer +--- The custom GEO ASM function. +function geo_update_shape(node, matStackIndex) + local obj = geo_get_current_object() + + -- Create a new display list that will be attached to the display list node + -- To get a different display list for each object, we can use the object pointer to form a unique identifier + local gfx_name = "shape_dl_" .. tostring(obj._pointer) + local gfx = gfx_get_from_name(gfx_name) + if gfx == nil then + + -- Get and copy the template to the newly created display list + local gfx_template = gfx_get_from_name("shape_template_dl") + local gfx_template_length = gfx_get_length(gfx_template) + gfx = gfx_new(gfx_name, gfx_template_length) + gfx_copy(gfx, gfx_template, gfx_template_length) + end + + -- Now fill the display list with the appropriate commands (see actors/shape/model.inc.c) + -- We can retrieve the commands directly with `gfx_get_command` + -- Index | Command | What to do + -- ------|----------------------|---------------------------------------- + -- [00] | gsSPGeometryMode | Change the geometry mode + -- [02] | gsSPTexture | Change the texture scaling + -- [03] | gsDPSetTextureImage | Update the texture + -- [10] | gsSPVertex | Compute vertices + -- [11] | gsSPDisplayList | Build triangles + -- [12] | gsSPTexture | Change the texture scaling + + -- Change the geometry mode + local cmd_geometry_mode = gfx_get_command(gfx, 0) + set_geometry_mode(cmd_geometry_mode) + + -- Change the texture scaling + local cmd_texture_scaling_1 = gfx_get_command(gfx, 2) + set_texture_scaling(cmd_texture_scaling_1, 1) + local cmd_texture_scaling_2 = gfx_get_command(gfx, 12) + set_texture_scaling(cmd_texture_scaling_2, 0) + + -- Update texture + local cmd_texture = gfx_get_command(gfx, 3) + update_texture(cmd_texture, obj) + + -- Compute vertices + local cmd_vertices = gfx_get_command(gfx, 10) + compute_vertices(cmd_vertices, obj) + + -- Build triangles + local cmd_triangles = gfx_get_command(gfx, 11) + build_triangles(cmd_triangles, obj) + + -- Update the graph node display list + cast_graph_node(node.next).displayList = gfx +end diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_0.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_0.png new file mode 100644 index 000000000..048856ba5 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_0.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_1.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_1.png new file mode 100644 index 000000000..3f380cf37 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_1.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_10.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_10.png new file mode 100644 index 000000000..6ea989c3f Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_10.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_2.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_2.png new file mode 100644 index 000000000..02b64419e Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_2.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_3.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_3.png new file mode 100644 index 000000000..d9c4480e8 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_3.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_4.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_4.png new file mode 100644 index 000000000..da46162e5 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_4.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_5.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_5.png new file mode 100644 index 000000000..97a79137c Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_5.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_6.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_6.png new file mode 100644 index 000000000..51477af50 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_6.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_7.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_7.png new file mode 100644 index 000000000..158adc6e9 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_7.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_8.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_8.png new file mode 100644 index 000000000..9a9fb46e4 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_8.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/textures/matrix_9.png b/docs/lua/examples/gfx-vtx-demo/textures/matrix_9.png new file mode 100644 index 000000000..03b8e40b3 Binary files /dev/null and b/docs/lua/examples/gfx-vtx-demo/textures/matrix_9.png differ diff --git a/docs/lua/examples/gfx-vtx-demo/update.lua b/docs/lua/examples/gfx-vtx-demo/update.lua new file mode 100644 index 000000000..956e80f02 --- /dev/null +++ b/docs/lua/examples/gfx-vtx-demo/update.lua @@ -0,0 +1,48 @@ +-- +-- Custom object and Mario update +-- Don't mind this file, it's not relevant to the purpose of this demo. +-- + +current_shape = 0 + +local E_MODEL_SHAPE = smlua_model_util_get_id("shape_geo") + +local function bhv_shape_init(o) + o.oFlags = o.oFlags | OBJ_FLAG_UPDATE_GFX_POS_AND_ANGLE + o.oAnimState = 0 +end + +local function bhv_shape_loop(o) + o.oFaceAngleYaw = o.oFaceAngleYaw - 0x100 + if o.oTimer % 2 == 0 then + o.oAnimState = (o.oAnimState + 1) % 11 + end +end + +local id_bhvShape = hook_behavior(nil, OBJ_LIST_DEFAULT, true, bhv_shape_init, bhv_shape_loop, "bhvShape") + +local function mario_update(m) + if m.playerIndex == 0 then + if m.controller.buttonPressed & X_BUTTON ~= 0 then + local obj = obj_get_first_with_behavior_id(id_bhvShape) + if obj == nil then + obj = spawn_non_sync_object(id_bhvShape, E_MODEL_SHAPE, 0, 0, 0, nil) + end + obj.oPosX = m.pos.x + 200 * sins(m.faceAngle.y) + obj.oPosY = m.pos.y + 150 + obj.oPosZ = m.pos.z + 200 * coss(m.faceAngle.y) + elseif m.controller.buttonPressed & Y_BUTTON ~= 0 then + current_shape = (current_shape + 1) % #SHAPES + end + end +end + +local function on_hud_render() + djui_hud_set_resolution(RESOLUTION_DJUI) + djui_hud_set_font(FONT_MENU) + djui_hud_set_color(0xFF, 0xFF, 0x00, 0xFF) + djui_hud_print_text(SHAPES[current_shape + 1].name, 8, djui_hud_get_screen_height() - 64, 1) +end + +hook_event(HOOK_MARIO_UPDATE, mario_update) +hook_event(HOOK_ON_HUD_RENDER, on_hud_render) diff --git a/docs/lua/examples/lighting-engine-demo/main.lua b/docs/lua/examples/lighting-engine-demo/main.lua index 6df460431..68103887d 100644 --- a/docs/lua/examples/lighting-engine-demo/main.lua +++ b/docs/lua/examples/lighting-engine-demo/main.lua @@ -8,7 +8,7 @@ function geo_hide_if_dnc(node) local dl = cast_graph_node(node.next) gfx_parse(dl.displayList, function(cmd, op) if op == G_SETENVCOLOR then - gfx_set_command(cmd, "gsDPSetEnvColor", 255, 255, 255, if_then_else(_G.dayNightCycleApi ~= nil and _G.dayNightCycleApi.is_dnc_enabled(), 0, 255)) + gfx_set_command(cmd, "gsDPSetEnvColor(255, 255, 255, %i)", if_then_else(_G.dayNightCycleApi ~= nil and _G.dayNightCycleApi.is_dnc_enabled(), 0, 255)) end end) end diff --git a/docs/lua/functions-6.md b/docs/lua/functions-6.md index 7ca49e558..240ee850d 100644 --- a/docs/lua/functions-6.md +++ b/docs/lua/functions-6.md @@ -468,43 +468,19 @@ Traverses a display list. Takes a Lua function as a parameter, which is called b - None ### C Prototype -`void gfx_parse(Gfx* cmd, LuaFunction func);` +`void gfx_parse(Gfx *cmd, LuaFunction func);` [:arrow_up_small:](#)
-## [gfx_get_vtx](#gfx_get_vtx) +## [gfx_get_op](#gfx_get_op) ### Description -Gets a vertex from a display list command if it has the correct op. Intended to be used with `gfx_parse` +Gets the op of the display list command ### Lua Example -`local PointerValue = gfx_get_vtx(gfx, offset)` - -### Parameters -| Field | Type | -| ----- | ---- | -| gfx | `Pointer` <`Gfx`> | -| offset | `integer` | - -### Returns -- `Pointer` <`Vtx`> - -### C Prototype -`Vtx *gfx_get_vtx(Gfx* gfx, u16 offset);` - -[:arrow_up_small:](#) - -
- -## [gfx_get_vtx_count](#gfx_get_vtx_count) - -### Description -Gets the number of vertices from a display list command if it has the correct op - -### Lua Example -`local integerValue = gfx_get_vtx_count(cmd)` +`local integerValue = gfx_get_op(cmd)` ### Parameters | Field | Type | @@ -515,73 +491,408 @@ Gets the number of vertices from a display list command if it has the correct op - `integer` ### C Prototype -`u16 gfx_get_vtx_count(Gfx* cmd);` +`u32 gfx_get_op(Gfx *cmd);` [:arrow_up_small:](#)
-## [gfx_set_combine_lerp](#gfx_set_combine_lerp) +## [gfx_get_display_list](#gfx_get_display_list) ### Description -Sets the display list combine mode. you can fill this function with G_CCMUX_* and G_ACMUX_* constants +Gets the display list from a display list command if it has the op `G_DL` ### Lua Example -`gfx_set_combine_lerp(gfx, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1)` +`local PointerValue = gfx_get_display_list(cmd)` ### Parameters | Field | Type | | ----- | ---- | -| gfx | `Pointer` <`Gfx`> | -| a0 | `integer` | -| b0 | `integer` | -| c0 | `integer` | -| d0 | `integer` | -| Aa0 | `integer` | -| Ab0 | `integer` | -| Ac0 | `integer` | -| Ad0 | `integer` | -| a1 | `integer` | -| b1 | `integer` | -| c1 | `integer` | -| d1 | `integer` | -| Aa1 | `integer` | -| Ab1 | `integer` | -| Ac1 | `integer` | -| Ad1 | `integer` | +| cmd | `Pointer` <`Gfx`> | ### Returns -- None +- `Pointer` <`Gfx`> ### C Prototype -`void gfx_set_combine_lerp(Gfx* gfx, u32 a0, u32 b0, u32 c0, u32 d0, u32 Aa0, u32 Ab0, u32 Ac0, u32 Ad0, u32 a1, u32 b1, u32 c1, u32 d1, u32 Aa1, u32 Ab1, u32 Ac1, u32 Ad1);` +`Gfx *gfx_get_display_list(Gfx *cmd);` [:arrow_up_small:](#)
-## [gfx_set_texture_image](#gfx_set_texture_image) +## [gfx_get_vertex_buffer](#gfx_get_vertex_buffer) ### Description -Sets the display list texture image. Pass in textureInfo.texture as `texture` +Gets the vertex buffer from a display list command if it has the op `G_VTX` ### Lua Example -`gfx_set_texture_image(gfx, format, size, width, texture)` +`local PointerValue = gfx_get_vertex_buffer(cmd)` + +### Parameters +| Field | Type | +| ----- | ---- | +| cmd | `Pointer` <`Gfx`> | + +### Returns +- `Pointer` <`Vtx`> + +### C Prototype +`Vtx *gfx_get_vertex_buffer(Gfx *cmd);` + +[:arrow_up_small:](#) + +
+ +## [gfx_get_vertex_count](#gfx_get_vertex_count) + +### Description +Gets the number of vertices from a display list command if it has the op `G_VTX` + +### Lua Example +`local integerValue = gfx_get_vertex_count(cmd)` + +### Parameters +| Field | Type | +| ----- | ---- | +| cmd | `Pointer` <`Gfx`> | + +### Returns +- `integer` + +### C Prototype +`u16 gfx_get_vertex_count(Gfx *cmd);` + +[:arrow_up_small:](#) + +
+ +## [gfx_get_length](#gfx_get_length) + +### Description +Gets the max length of a display list + +### Lua Example +`local integerValue = gfx_get_length(gfx)` ### Parameters | Field | Type | | ----- | ---- | | gfx | `Pointer` <`Gfx`> | -| format | `integer` | -| size | `integer` | -| width | `integer` | -| texture | `Pointer` <`integer`> | + +### Returns +- `integer` + +### C Prototype +`u32 gfx_get_length(Gfx *gfx);` + +[:arrow_up_small:](#) + +
+ +## [gfx_get_command](#gfx_get_command) + +### Description +Gets a command of a display list at position `offset` + +### Lua Example +`local PointerValue = gfx_get_command(gfx, offset)` + +### Parameters +| Field | Type | +| ----- | ---- | +| gfx | `Pointer` <`Gfx`> | +| offset | `integer` | + +### Returns +- `Pointer` <`Gfx`> + +### C Prototype +`Gfx *gfx_get_command(Gfx *gfx, u32 offset);` + +[:arrow_up_small:](#) + +
+ +## [gfx_get_next_command](#gfx_get_next_command) + +### Description +Gets the next command of a given display list pointer. Intended to use in a for loop + +### Lua Example +`local PointerValue = gfx_get_next_command(gfx)` + +### Parameters +| Field | Type | +| ----- | ---- | +| gfx | `Pointer` <`Gfx`> | + +### Returns +- `Pointer` <`Gfx`> + +### C Prototype +`Gfx *gfx_get_next_command(Gfx *gfx);` + +[:arrow_up_small:](#) + +
+ +## [gfx_copy](#gfx_copy) + +### Description +Copies `length` commands from display list `src` to display list `dest` + +### Lua Example +`gfx_copy(dest, src, length)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dest | `Pointer` <`Gfx`> | +| src | `Pointer` <`Gfx`> | +| length | `integer` | ### Returns - None ### C Prototype -`void gfx_set_texture_image(Gfx* gfx, u32 format, u32 size, u32 width, u8* texture);` +`void gfx_copy(Gfx *dest, Gfx *src, u32 length);` + +[:arrow_up_small:](#) + +
+ +## [gfx_new](#gfx_new) + +### Description +Creates a new named display list of `length` commands + +### Lua Example +`local PointerValue = gfx_new(name, length)` + +### Parameters +| Field | Type | +| ----- | ---- | +| name | `string` | +| length | `integer` | + +### Returns +- `Pointer` <`Gfx`> + +### C Prototype +`Gfx *gfx_new(const char *name, u32 length);` + +[:arrow_up_small:](#) + +
+ +## [gfx_realloc](#gfx_realloc) + +### Description +Reallocates a display list created by `gfx_new` to modify its length + +### Lua Example +`local PointerValue = gfx_realloc(gfx, newLength)` + +### Parameters +| Field | Type | +| ----- | ---- | +| gfx | `Pointer` <`Gfx`> | +| newLength | `integer` | + +### Returns +- `Pointer` <`Gfx`> + +### C Prototype +`Gfx *gfx_realloc(Gfx *gfx, u32 newLength);` + +[:arrow_up_small:](#) + +
+ +## [gfx_delete](#gfx_delete) + +### Description +Deletes a display list created by `gfx_new` + +### Lua Example +`gfx_delete(gfx)` + +### Parameters +| Field | Type | +| ----- | ---- | +| gfx | `Pointer` <`Gfx`> | + +### Returns +- None + +### C Prototype +`void gfx_delete(Gfx *gfx);` + +[:arrow_up_small:](#) + +
+ +## [vtx_get_count](#vtx_get_count) + +### Description +Gets the max count of vertices of a vertex buffer + +### Lua Example +`local integerValue = vtx_get_count(vtx)` + +### Parameters +| Field | Type | +| ----- | ---- | +| vtx | `Pointer` <`Vtx`> | + +### Returns +- `integer` + +### C Prototype +`u32 vtx_get_count(Vtx *vtx);` + +[:arrow_up_small:](#) + +
+ +## [vtx_get_vertex](#vtx_get_vertex) + +### Description +Gets a vertex of a vertex buffer at position `offset` + +### Lua Example +`local PointerValue = vtx_get_vertex(vtx, offset)` + +### Parameters +| Field | Type | +| ----- | ---- | +| vtx | `Pointer` <`Vtx`> | +| offset | `integer` | + +### Returns +- `Pointer` <`Vtx`> + +### C Prototype +`Vtx *vtx_get_vertex(Vtx *vtx, u32 offset);` + +[:arrow_up_small:](#) + +
+ +## [vtx_get_next_vertex](#vtx_get_next_vertex) + +### Description +Gets the next vertex of a given vertex pointer. Intended to use in a for loop + +### Lua Example +`local PointerValue = vtx_get_next_vertex(vtx)` + +### Parameters +| Field | Type | +| ----- | ---- | +| vtx | `Pointer` <`Vtx`> | + +### Returns +- `Pointer` <`Vtx`> + +### C Prototype +`Vtx *vtx_get_next_vertex(Vtx *vtx);` + +[:arrow_up_small:](#) + +
+ +## [vtx_copy](#vtx_copy) + +### Description +Copies `count` vertices from vertex buffer `src` to vertex buffer `dest` + +### Lua Example +`vtx_copy(dest, src, count)` + +### Parameters +| Field | Type | +| ----- | ---- | +| dest | `Pointer` <`Vtx`> | +| src | `Pointer` <`Vtx`> | +| count | `integer` | + +### Returns +- None + +### C Prototype +`void vtx_copy(Vtx *dest, Vtx *src, u32 count);` + +[:arrow_up_small:](#) + +
+ +## [vtx_new](#vtx_new) + +### Description +Creates a new named vertex buffer of `count` vertices + +### Lua Example +`local PointerValue = vtx_new(name, count)` + +### Parameters +| Field | Type | +| ----- | ---- | +| name | `string` | +| count | `integer` | + +### Returns +- `Pointer` <`Vtx`> + +### C Prototype +`Vtx *vtx_new(const char *name, u32 count);` + +[:arrow_up_small:](#) + +
+ +## [vtx_realloc](#vtx_realloc) + +### Description +Reallocates a vertex buffer created by `vtx_new` to modify its count + +### Lua Example +`local PointerValue = vtx_realloc(vtx, newCount)` + +### Parameters +| Field | Type | +| ----- | ---- | +| vtx | `Pointer` <`Vtx`> | +| newCount | `integer` | + +### Returns +- `Pointer` <`Vtx`> + +### C Prototype +`Vtx *vtx_realloc(Vtx *vtx, u32 newCount);` + +[:arrow_up_small:](#) + +
+ +## [vtx_delete](#vtx_delete) + +### Description +Deletes a vertex buffer created by `vtx_new` + +### Lua Example +`vtx_delete(vtx)` + +### Parameters +| Field | Type | +| ----- | ---- | +| vtx | `Pointer` <`Vtx`> | + +### Returns +- None + +### C Prototype +`void vtx_delete(Vtx *vtx);` [:arrow_up_small:](#) diff --git a/docs/lua/functions.md b/docs/lua/functions.md index 363d14d99..ef5742e68 100644 --- a/docs/lua/functions.md +++ b/docs/lua/functions.md @@ -1785,10 +1785,24 @@ - [get_skybox_color](functions-6.md#get_skybox_color) - [set_skybox_color](functions-6.md#set_skybox_color) - [gfx_parse](functions-6.md#gfx_parse) - - [gfx_get_vtx](functions-6.md#gfx_get_vtx) - - [gfx_get_vtx_count](functions-6.md#gfx_get_vtx_count) - - [gfx_set_combine_lerp](functions-6.md#gfx_set_combine_lerp) - - [gfx_set_texture_image](functions-6.md#gfx_set_texture_image) + - [gfx_get_op](functions-6.md#gfx_get_op) + - [gfx_get_display_list](functions-6.md#gfx_get_display_list) + - [gfx_get_vertex_buffer](functions-6.md#gfx_get_vertex_buffer) + - [gfx_get_vertex_count](functions-6.md#gfx_get_vertex_count) + - [gfx_get_length](functions-6.md#gfx_get_length) + - [gfx_get_command](functions-6.md#gfx_get_command) + - [gfx_get_next_command](functions-6.md#gfx_get_next_command) + - [gfx_copy](functions-6.md#gfx_copy) + - [gfx_new](functions-6.md#gfx_new) + - [gfx_realloc](functions-6.md#gfx_realloc) + - [gfx_delete](functions-6.md#gfx_delete) + - [vtx_get_count](functions-6.md#vtx_get_count) + - [vtx_get_vertex](functions-6.md#vtx_get_vertex) + - [vtx_get_next_vertex](functions-6.md#vtx_get_next_vertex) + - [vtx_copy](functions-6.md#vtx_copy) + - [vtx_new](functions-6.md#vtx_new) + - [vtx_realloc](functions-6.md#vtx_realloc) + - [vtx_delete](functions-6.md#vtx_delete)
@@ -2563,11 +2577,30 @@ N/A ## [gfx_set_command](#gfx_set_command) -Sets the specified display list command on the display list given. +Sets a display list command on the display list given. -### Lua Example +If `command` includes parameter specifiers (subsequences beginning with `%`), the additional arguments following `command` are converted and inserted in `command` replacing their respective specifiers. + +The number of provided parameters must be equal to the number of specifiers in `command`, and the order of parameters must be the same as the specifiers. + +The following specifiers are allowed: +- `%i` for an `integer` parameter +- `%s` for a `string` parameter +- `%v` for a `Vtx` parameter +- `%t` for a `Texture` parameter +- `%g` for a `Gfx` parameter + +### Lua Examples + +Plain string: ```lua -gfx_set_command(gfx, "gsDPSetEnvColor", 0x00, 0xFF, 0x00, 0xFF) +gfx_set_command(gfx, "gsDPSetEnvColor(0x00, 0xFF, 0x00, 0xFF)") +``` + +With parameter specifiers: +```lua +r, g, b, a = 0x00, 0xFF, 0x00, 0xFF +gfx_set_command(gfx, "gsDPSetEnvColor(%i, %i, %i, %i)", r, g, b, a) ``` ### Parameters @@ -2575,7 +2608,7 @@ gfx_set_command(gfx, "gsDPSetEnvColor", 0x00, 0xFF, 0x00, 0xFF) | ----- | ---- | | gfx | [Gfx](structs.md#Gfx) | | command | `string` | -| (Any number of arguments) | `integer` | +| parameters... | any of `integer`, `string`, `Gfx`, `Texture`, `Vtx` | ### Returns - None diff --git a/docs/lua/structs.md b/docs/lua/structs.md index 8bb810723..bf7524f33 100644 --- a/docs/lua/structs.md +++ b/docs/lua/structs.md @@ -3249,10 +3249,19 @@ | Field | Type | Access | | ----- | ---- | ------ | -| cn | `Array` <`integer`> | | +| a | `integer` | | +| b | `integer` | | | flag | `integer` | | -| ob | `Array` <`number`> | | -| tc | `Array` <`integer`> | | +| g | `integer` | | +| nx | `integer` | | +| ny | `integer` | | +| nz | `integer` | | +| r | `integer` | | +| tu | `integer` | | +| tv | `integer` | | +| x | `number` | | +| y | `number` | | +| z | `number` | | [:arrow_up_small:](#) diff --git a/include/PR/gbi.h b/include/PR/gbi.h index ae51a9c7d..5d107b4c6 100644 --- a/include/PR/gbi.h +++ b/include/PR/gbi.h @@ -95,6 +95,10 @@ # define GBI_FLOATS #endif +#ifndef GBI_NO_MULTI_COMMANDS +# define GBI_NO_MULTI_COMMANDS +#endif + #ifdef F3DEX_GBI_2 # ifndef F3DEX_GBI # define F3DEX_GBI @@ -1133,10 +1137,33 @@ typedef struct { unsigned char a; /* alpha */ } Vtx_tn; +typedef struct { + float x; + float y; + float z; + unsigned short flag; + short tu; + short tv; + union { + unsigned char r; + signed char nx; + }; + union { + unsigned char g; + signed char ny; + }; + union { + unsigned char b; + signed char nz; + }; + unsigned char a; +} Vtx_L; + typedef union { - Vtx_t v; /* Use this one for colors */ - Vtx_tn n; /* Use this one for normals */ - long long int force_structure_alignment; + Vtx_t v; /* Use this one for colors */ + Vtx_tn n; /* Use this one for normals */ + Vtx_L l; /* Use this one for Lua */ + long long int force_structure_alignment; } Vtx; /* @@ -4457,6 +4484,22 @@ typedef union { }} /* Fraction never used in fill */ +#ifdef GBI_NO_MULTI_COMMANDS + +#define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ +{ \ + Gfx *_g = (Gfx *) pkt; \ + _g->words.w0 = _SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((uly), 12, 12) | _SHIFTL((lry), 0, 12); \ + _g->words.w1 = _SHIFTL((ulx), 16, 16) | _SHIFTL((lrx), 0, 16); \ +} + +#define gsDPFillRectangle(ulx, uly, lrx, lry) \ +{{ \ + _SHIFTL(G_FILLRECT, 24, 8) | _SHIFTL((uly), 12, 12) | _SHIFTL((lry), 0, 12), \ + _SHIFTL((ulx), 16, 16) | _SHIFTL((lrx), 0, 16), \ +}} + +#else #ifdef F3DEX_GBI_2E #define gDPFillRectangle(pkt, ulx, uly, lrx, lry) \ { \ @@ -4492,6 +4535,7 @@ typedef union { (_SHIFTL((ulx), 14, 10) | _SHIFTL((uly), 2, 10)) \ }} #endif +#endif /* like gDPFillRectangle but accepts negative arguments */ #ifndef F3DEX_GBI_2E @@ -4590,6 +4634,7 @@ typedef union { * under normal circumstances (use gsSPTextureRectangle()). * That is also why there is no gDPTextureRectangle() macros. */ +#if 0 // DO NOT USE #define gsDPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ {{ \ (_SHIFTL(G_TEXRECT, 24, 8) | _SHIFTL(xh, 12, 12) | \ @@ -4637,7 +4682,50 @@ typedef union { _g->words.w0 = (_SHIFTL(s, 16, 16) | _SHIFTL(t, 0, 16)); \ _g->words.w1 = (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16)); \ } +#endif +#ifdef GBI_NO_MULTI_COMMANDS + +#define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *) (pkt); \ + _g->words.w0 = _SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL((xh) >> 2, 13, 11) | \ + _SHIFTL((yh) >> 2, 4, 9) | \ + _SHIFTL((dtdy) >> 6, 0, 4); /* decimal part */ \ + _g->words.w1 = _SHIFTL((xl) >> 2, 21, 11) | \ + _SHIFTL((yl) >> 2, 12, 9) | \ + _SHIFTL((dsdx) >> 6, 4, 8) | \ + _SHIFTL((dtdy) >> 10, 0, 4); /* integer part */ \ +} + +#define gsSPTextureRectangle(xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{{ \ + _SHIFTL(G_TEXRECT, 24, 8) | \ + _SHIFTL((xh) >> 2, 13, 11) | \ + _SHIFTL((yh) >> 2, 4, 9) | \ + _SHIFTL((dtdy) >> 6, 0, 4), /* decimal part */ \ +\ + _SHIFTL((xl) >> 2, 21, 11) | \ + _SHIFTL((yl) >> 2, 12, 9) | \ + _SHIFTL((dsdx) >> 6, 4, 8) | \ + _SHIFTL((dtdy) >> 10, 0, 4) /* integer part */ \ +}} + +#define gSPTextureRectangleFlip(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy) \ +{ \ + Gfx *_g = (Gfx *) (pkt); \ + _g->words.w0 = _SHIFTL(G_TEXRECTFLIP, 24, 8) | \ + _SHIFTL((xh) >> 2, 13, 11) | \ + _SHIFTL((yh) >> 2, 4, 9) | \ + _SHIFTL((dtdy) >> 6, 0, 4); /* decimal part */ \ + _g->words.w1 = _SHIFTL((xl) >> 2, 21, 11) | \ + _SHIFTL((yl) >> 2, 12, 9) | \ + _SHIFTL((dsdx) >> 6, 4, 8) | \ + _SHIFTL((dtdy) >> 10, 0, 4); /* integer part */ \ +} + +#else #ifdef F3D_OLD # define gSPTextureRectangle(pkt, xl, yl, xh, yh, tile, s, t, dsdx, dtdy)\ { \ @@ -4809,6 +4897,7 @@ typedef union { gImmp1(pkt, G_RDPHALF_2, (_SHIFTL(dsdx, 16, 16) | _SHIFTL(dtdy, 0, 16))); \ } #endif +#endif #define gsDPWord(wordhi, wordlo) \ gsImmp1(G_RDPHALF_1, (uintptr_t)(wordhi)), \ diff --git a/src/engine/display_list.c b/src/engine/display_list.c deleted file mode 100644 index dbc9c911d..000000000 --- a/src/engine/display_list.c +++ /dev/null @@ -1,25 +0,0 @@ -#include "display_list.h" - -// Get the size of a display list by iterating -// until gsSPEndDisplayList or gsSPBranchList is found -u32 gfx_get_size(const Gfx* gfx) { - for (u32 i = 0;;) { - u32 op = (gfx + i)->words.w0 >> 24; - u32 cmdSize = 1; - switch (op) { - case G_DL: - if (C0(gfx + i, 16, 1) == G_DL_NOPUSH) { return i + 1; } // For displaylists that end with branches (jumps) - break; - case G_ENDDL: - return i + 1; - case G_TEXRECT: - case G_TEXRECTFLIP: - cmdSize = 3; - break; - case G_FILLRECT: - cmdSize = 2; - break; - } - i += cmdSize; - } -} diff --git a/src/engine/display_list.h b/src/engine/display_list.h deleted file mode 100644 index c663b5949..000000000 --- a/src/engine/display_list.h +++ /dev/null @@ -1,5 +0,0 @@ -#include - -#define C0(cmd, pos, width) (((cmd)->words.w0 >> (pos)) & ((1U << width) - 1)) - -u32 gfx_get_size(const Gfx* gfx); diff --git a/src/engine/graph_node.c b/src/engine/graph_node.c index 024133b75..7716efb0c 100644 --- a/src/engine/graph_node.c +++ b/src/engine/graph_node.c @@ -235,7 +235,7 @@ init_graph_node_translation_rotation(struct DynamicPool *pool, vec3s_copy(graphNode->translation, translation); vec3s_copy(graphNode->rotation, rotation); graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; @@ -257,7 +257,7 @@ struct GraphNodeTranslation *init_graph_node_translation(struct DynamicPool *poo vec3s_copy(graphNode->translation, translation); graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; @@ -278,7 +278,7 @@ struct GraphNodeRotation *init_graph_node_rotation(struct DynamicPool *pool, init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_ROTATION); vec3s_copy(graphNode->rotation, rotation); graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; @@ -299,7 +299,7 @@ struct GraphNodeScale *init_graph_node_scale(struct DynamicPool *pool, graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); graphNode->scale = scale; graphNode->prevScale = scale; - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; @@ -369,7 +369,7 @@ struct GraphNodeAnimatedPart *init_graph_node_animated_part(struct DynamicPool * init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_ANIMATED_PART); vec3s_copy(graphNode->translation, translation); graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; @@ -390,7 +390,7 @@ struct GraphNodeBillboard *init_graph_node_billboard(struct DynamicPool *pool, init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_BILLBOARD); vec3s_copy(graphNode->translation, translation); graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; @@ -409,7 +409,7 @@ struct GraphNodeDisplayList *init_graph_node_display_list(struct DynamicPool *po if (graphNode != NULL) { init_scene_graph_node_links(&graphNode->node, GRAPH_NODE_TYPE_DISPLAY_LIST); graphNode->node.flags = (drawingLayer << 8) | (graphNode->node.flags & 0xFF); - graphNode->displayList = dynos_model_get_writable_display_list(displayList); + graphNode->displayList = dynos_gfx_get_writable_display_list(displayList); } return graphNode; diff --git a/src/engine/level_script.c b/src/engine/level_script.c index ecdbe63ad..106da957a 100644 --- a/src/engine/level_script.c +++ b/src/engine/level_script.c @@ -384,6 +384,9 @@ static void level_reset_globals(void) { // free models stored in dynos dynos_model_clear_pool(MODEL_POOL_LEVEL); + + // clear the gfx command cache filled by gfx_set_command + dynos_smlua_clear_gfx_command_cache(); } static void level_cmd_alloc_level_pool(void) { diff --git a/src/pc/gfx/gfx_pc.c b/src/pc/gfx/gfx_pc.c index 865677be0..fc6bffd57 100644 --- a/src/pc/gfx/gfx_pc.c +++ b/src/pc/gfx/gfx_pc.c @@ -770,6 +770,8 @@ static float gfx_adjust_x_for_aspect_ratio(float x) { } static void OPTIMIZE_O3 gfx_sp_vertex(size_t n_vertices, size_t dest_index, const Vtx *vertices, bool luaVertexColor) { + if (!vertices) { return; } + float globalLightCached[2][3]; float vertexColorCached[3]; if (rsp.geometry_mode & G_LIGHTING) { @@ -1635,6 +1637,8 @@ static inline void *seg_addr(uintptr_t w1) { #define C1(pos, width) ((cmd->words.w1 >> (pos)) & ((1U << width) - 1)) static void OPTIMIZE_O3 gfx_run_dl(Gfx* cmd) { + if (!cmd) { return; } + for (;;) { uint32_t opcode = cmd->words.w0 >> 24; @@ -1788,6 +1792,16 @@ static void OPTIMIZE_O3 gfx_run_dl(Gfx* cmd) { int32_t lrx, lry, tile, ulx, uly; uint32_t uls, ult, dsdx, dtdy; tile = 0; +#ifdef GBI_NO_MULTI_COMMANDS + lrx = (int32_t) (C0(13, 11) << 21) >> 19; + lry = (int32_t) (C0(4, 9) << 23) >> 21; + ulx = (int32_t) (C1(21, 11) << 21) >> 19; + uly = (int32_t) (C1(12, 9) << 23) >> 21; + uls = 0; + ult = 0; + dsdx = C1(4, 8) << 6; + dtdy = (C1(0, 4) << 10) | (C0(0, 4) << 6); +#else #ifdef F3DEX_GBI_2E lrx = (int32_t)(C0(0, 24) << 8) >> 8; lry = (int32_t)(C1(0, 24) << 8) >> 8; @@ -1811,11 +1825,23 @@ static void OPTIMIZE_O3 gfx_run_dl(Gfx* cmd) { ++cmd; dsdx = C1(16, 16); dtdy = C1(0, 16); +#endif #endif gfx_dp_texture_rectangle(ulx, uly, lrx, lry, tile, uls, ult, dsdx, dtdy, opcode == G_TEXRECTFLIP); break; } case G_FILLRECT: +#ifdef GBI_NO_MULTI_COMMANDS + { + int32_t lrx, lry, ulx, uly; + uly = (int32_t) (C0(12, 12) << 20) >> 18; + lry = (int32_t) (C0(0, 12) << 20) >> 18; + ulx = (int32_t) (C1(16, 16) << 16) >> 14; + lrx = (int32_t) (C1(0, 16) << 16) >> 14; + gfx_dp_fill_rectangle(ulx, uly, lrx, lry); + break; + } +#else #ifdef F3DEX_GBI_2E { int32_t lrx, lry, ulx, uly; @@ -1830,6 +1856,7 @@ static void OPTIMIZE_O3 gfx_run_dl(Gfx* cmd) { #else gfx_dp_fill_rectangle(C1(12, 12), C1(0, 12), C0(12, 12), C0(0, 12)); break; +#endif #endif case G_SETSCISSOR: gfx_dp_set_scissor(C1(24, 2), C0(12, 12), C0(0, 12), C1(12, 12), C1(0, 12)); diff --git a/src/pc/lua/smlua_cobject_autogen.c b/src/pc/lua/smlua_cobject_autogen.c index b1e5d88ef..b53aea946 100644 --- a/src/pc/lua/smlua_cobject_autogen.c +++ b/src/pc/lua/smlua_cobject_autogen.c @@ -2703,12 +2703,21 @@ static struct LuaObjectField sTransitionInfoFields[LUA_TRANSITION_INFO_FIELD_COU { "posYaw", LVT_S16, offsetof(struct TransitionInfo, posYaw), false, LOT_NONE, 1, sizeof(s16) }, }; -#define LUA_VTX_FIELD_COUNT 4 +#define LUA_VTX_FIELD_COUNT 13 static struct LuaObjectField sVtxFields[LUA_VTX_FIELD_COUNT] = { - { "cn", LVT_U8, offsetof(Vtx_t, cn), false, LOT_NONE, 4, sizeof(unsigned char) }, - { "flag", LVT_U16, offsetof(Vtx_t, flag), false, LOT_NONE, 1, sizeof(unsigned short) }, - { "ob", LVT_F32, offsetof(Vtx_t, ob), false, LOT_NONE, 3, sizeof(float) }, - { "tc", LVT_S16, offsetof(Vtx_t, tc), false, LOT_NONE, 2, sizeof(short) }, + { "a", LVT_U8, offsetof(Vtx_L, a), false, LOT_NONE, 1, sizeof(unsigned char) }, + { "b", LVT_U8, offsetof(Vtx_L, b), false, LOT_NONE, 1, sizeof(unsigned char) }, + { "flag", LVT_U16, offsetof(Vtx_L, flag), false, LOT_NONE, 1, sizeof(unsigned short) }, + { "g", LVT_U8, offsetof(Vtx_L, g), false, LOT_NONE, 1, sizeof(unsigned char) }, + { "nx", LVT_S8, offsetof(Vtx_L, nx), false, LOT_NONE, 1, sizeof(signed char) }, + { "ny", LVT_S8, offsetof(Vtx_L, ny), false, LOT_NONE, 1, sizeof(signed char) }, + { "nz", LVT_S8, offsetof(Vtx_L, nz), false, LOT_NONE, 1, sizeof(signed char) }, + { "r", LVT_U8, offsetof(Vtx_L, r), false, LOT_NONE, 1, sizeof(unsigned char) }, + { "tu", LVT_S16, offsetof(Vtx_L, tu), false, LOT_NONE, 1, sizeof(short) }, + { "tv", LVT_S16, offsetof(Vtx_L, tv), false, LOT_NONE, 1, sizeof(short) }, + { "x", LVT_F32, offsetof(Vtx_L, x), false, LOT_NONE, 1, sizeof(float) }, + { "y", LVT_F32, offsetof(Vtx_L, y), false, LOT_NONE, 1, sizeof(float) }, + { "z", LVT_F32, offsetof(Vtx_L, z), false, LOT_NONE, 1, sizeof(float) }, }; #define LUA_VTX__INTERP_FIELD_COUNT 2 diff --git a/src/pc/lua/smlua_constants_autogen.c b/src/pc/lua/smlua_constants_autogen.c index 5e4c6361a..19d8ac6bb 100644 --- a/src/pc/lua/smlua_constants_autogen.c +++ b/src/pc/lua/smlua_constants_autogen.c @@ -1313,59 +1313,31 @@ char gSmluaConstants[] = "" "G_COPYMEM=0xd2\n" #ifdef F3DEX_GBI_2 "G_NOOP=0x00\n" -"G_RDPHALF_2=0xf1\n" "G_SETOTHERMODE_H=0xe3\n" "G_SETOTHERMODE_L=0xe2\n" -"G_RDPHALF_1=0xe1\n" -"G_SPNOOP=0xe0\n" "G_ENDDL=0xdf\n" "G_DL=0xde\n" -"G_LOAD_UCODE=0xdd\n" "G_MOVEMEM=0xdc\n" "G_MOVEWORD=0xdb\n" "G_MTX=0xda\n" "G_GEOMETRYMODE=0xd9\n" "G_POPMTX=0xd8\n" "G_TEXTURE=0xd7\n" -"G_DMA_IO=0xd6\n" -"G_SPECIAL_1=0xd5\n" -"G_SPECIAL_2=0xd4\n" -"G_SPECIAL_3=0xd3\n" "G_VTX=0x01\n" -"G_MODIFYVTX=0x02\n" -"G_CULLDL=0x03\n" -"G_BRANCH_Z=0x04\n" "G_TRI1=0x05\n" "G_TRI2=0x06\n" -"G_QUAD=0x07\n" -"G_LINE3D=0x08\n" #else // #ifdef F3DEX_GBI_2 -"G_SPNOOP=0\n" "G_MTX=1\n" -"G_RESERVED0=2\n" "G_MOVEMEM=3\n" "G_VTX=4\n" -"G_RESERVED1=5\n" "G_DL=6\n" -"G_RESERVED2=7\n" -"G_RESERVED3=8\n" -"G_SPRITE2D_BASE=9\n" -"G_IMMFIRST=-65\n" "G_TRI1=(G_IMMFIRST-0)\n" -"G_CULLDL=(G_IMMFIRST-1)\n" "G_POPMTX=(G_IMMFIRST-2)\n" "G_MOVEWORD=(G_IMMFIRST-3)\n" "G_TEXTURE=(G_IMMFIRST-4)\n" "G_SETOTHERMODE_H=(G_IMMFIRST-5)\n" "G_SETOTHERMODE_L=(G_IMMFIRST-6)\n" "G_ENDDL=(G_IMMFIRST-7)\n" -"G_SETGEOMETRYMODE=(G_IMMFIRST-8)\n" -"G_CLEARGEOMETRYMODE=(G_IMMFIRST-9)\n" -"G_LINE3D=(G_IMMFIRST-10)\n" -"G_RDPHALF_1=(G_IMMFIRST-11)\n" -"G_RDPHALF_2=(G_IMMFIRST-12)\n" -"G_SPRITE2D_SCALEFLIP=(G_IMMFIRST-1)\n" -"G_SPRITE2D_DRAW=(G_IMMFIRST-2)\n" "G_NOOP=0xc0\n" #endif // #ifdef F3DEX_GBI_2 "G_SETCIMG=0xff\n" @@ -1383,325 +1355,9 @@ char gSmluaConstants[] = "" "G_LOADBLOCK=0xf3\n" "G_SETTILESIZE=0xf2\n" "G_LOADTLUT=0xf0\n" -"G_RDPSETOTHERMODE=0xef\n" -"G_SETPRIMDEPTH=0xee\n" "G_SETSCISSOR=0xed\n" -"G_SETCONVERT=0xec\n" -"G_SETKEYR=0xeb\n" -"G_SETKEYGB=0xea\n" -"G_RDPFULLSYNC=0xe9\n" -"G_RDPTILESYNC=0xe8\n" -"G_RDPPIPESYNC=0xe7\n" -"G_RDPLOADSYNC=0xe6\n" "G_TEXRECTFLIP=0xe5\n" "G_TEXRECT=0xe4\n" -"G_TRI_FILL=0xc8\n" -"G_TRI_SHADE=0xcc\n" -"G_TRI_TXTR=0xca\n" -"G_TRI_SHADE_TXTR=0xce\n" -"G_TRI_FILL_ZBUFF=0xc9\n" -"G_TRI_SHADE_ZBUFF=0xcd\n" -"G_TRI_TXTR_ZBUFF=0xcb\n" -"G_TRI_SHADE_TXTR_ZBUFF=0xcf\n" -"G_RDP_TRI_FILL_MASK=0x08\n" -"G_RDP_TRI_SHADE_MASK=0x04\n" -"G_RDP_TRI_TXTR_MASK=0x02\n" -"G_RDP_TRI_ZBUFF_MASK=0x01\n" -"BOWTIE_VAL=0\n" -"G_RDP_ADDR_FIXUP=3\n" -"G_DMACMDSIZ=128\n" -"G_IMMCMDSIZ=64\n" -"G_RDPCMDSIZ=64\n" -"G_TEXTURE_IMAGE_FRAC=2\n" -"G_TEXTURE_SCALE_FRAC=16\n" -"G_SCALE_FRAC=8\n" -"G_ROTATE_FRAC=16\n" -"G_MAXFBZ=0x3fff\n" -"G_ZBUFFER=0x00000001\n" -"G_SHADE=0x00000004\n" -"G_FOG=0x00010000\n" -"G_LIGHTING=0x00020000\n" -"G_TEXTURE_GEN=0x00040000\n" -"G_TEXTURE_GEN_LINEAR=0x00080000\n" -"G_LOD=0x00100000\n" -"G_IM_FMT_RGBA=0\n" -"G_IM_FMT_YUV=1\n" -"G_IM_FMT_CI=2\n" -"G_IM_FMT_IA=3\n" -"G_IM_FMT_I=4\n" -"G_IM_SIZ_4b=0\n" -"G_IM_SIZ_8b=1\n" -"G_IM_SIZ_16b=2\n" -"G_IM_SIZ_32b=3\n" -"G_IM_SIZ_DD=5\n" -"G_IM_SIZ_4b_BYTES=0\n" -"G_IM_SIZ_8b_BYTES=1\n" -"G_IM_SIZ_16b_BYTES=2\n" -"G_IM_SIZ_32b_BYTES=4\n" -"G_IM_SIZ_32b_TILE_BYTES=2\n" -"G_IM_SIZ_32b_LINE_BYTES=2\n" -"G_IM_SIZ_4b_SHIFT=2\n" -"G_IM_SIZ_8b_SHIFT=1\n" -"G_IM_SIZ_16b_SHIFT=0\n" -"G_IM_SIZ_32b_SHIFT=0\n" -"G_IM_SIZ_4b_INCR=3\n" -"G_IM_SIZ_8b_INCR=1\n" -"G_IM_SIZ_16b_INCR=0\n" -"G_IM_SIZ_32b_INCR=0\n" -"G_CCMUX_COMBINED=0\n" -"G_CCMUX_TEXEL0=1\n" -"G_CCMUX_TEXEL1=2\n" -"G_CCMUX_PRIMITIVE=3\n" -"G_CCMUX_SHADE=4\n" -"G_CCMUX_ENVIRONMENT=5\n" -"G_CCMUX_CENTER=6\n" -"G_CCMUX_SCALE=6\n" -"G_CCMUX_COMBINED_ALPHA=7\n" -"G_CCMUX_TEXEL0_ALPHA=8\n" -"G_CCMUX_TEXEL1_ALPHA=9\n" -"G_CCMUX_PRIMITIVE_ALPHA=10\n" -"G_CCMUX_SHADE_ALPHA=11\n" -"G_CCMUX_ENV_ALPHA=12\n" -"G_CCMUX_LOD_FRACTION=13\n" -"G_CCMUX_PRIM_LOD_FRAC=14\n" -"G_CCMUX_NOISE=7\n" -"G_CCMUX_K4=7\n" -"G_CCMUX_K5=15\n" -"G_CCMUX_1=6\n" -"G_CCMUX_0=31\n" -"G_ACMUX_COMBINED=0\n" -"G_ACMUX_TEXEL0=1\n" -"G_ACMUX_TEXEL1=2\n" -"G_ACMUX_PRIMITIVE=3\n" -"G_ACMUX_SHADE=4\n" -"G_ACMUX_ENVIRONMENT=5\n" -"G_ACMUX_LOD_FRACTION=0\n" -"G_ACMUX_PRIM_LOD_FRAC=6\n" -"G_ACMUX_1=6\n" -"G_ACMUX_0=7\n" -"G_MDSFT_ALPHACOMPARE=0\n" -"G_MDSFT_ZSRCSEL=2\n" -"G_MDSFT_RENDERMODE=3\n" -"G_MDSFT_BLENDER=16\n" -"G_MDSFT_BLENDMASK=0\n" -"G_MDSFT_ALPHADITHER=4\n" -"G_MDSFT_RGBDITHER=6\n" -"G_MDSFT_COMBKEY=8\n" -"G_MDSFT_TEXTCONV=9\n" -"G_MDSFT_TEXTFILT=12\n" -"G_MDSFT_TEXTLUT=14\n" -"G_MDSFT_TEXTLOD=16\n" -"G_MDSFT_TEXTDETAIL=17\n" -"G_MDSFT_TEXTPERSP=19\n" -"G_MDSFT_CYCLETYPE=20\n" -"G_MDSFT_COLORDITHER=22\n" -"G_MDSFT_PIPELINE=23\n" -"G_PM_1PRIMITIVE=(1 << G_MDSFT_PIPELINE)\n" -"G_PM_NPRIMITIVE=(0 << G_MDSFT_PIPELINE)\n" -"G_CYC_1CYCLE=(0 << G_MDSFT_CYCLETYPE)\n" -"G_CYC_2CYCLE=(1 << G_MDSFT_CYCLETYPE)\n" -"G_CYC_COPY=(2 << G_MDSFT_CYCLETYPE)\n" -"G_CYC_FILL=(3 << G_MDSFT_CYCLETYPE)\n" -"G_TP_NONE=(0 << G_MDSFT_TEXTPERSP)\n" -"G_TP_PERSP=(1 << G_MDSFT_TEXTPERSP)\n" -"G_TD_CLAMP=(0 << G_MDSFT_TEXTDETAIL)\n" -"G_TD_SHARPEN=(1 << G_MDSFT_TEXTDETAIL)\n" -"G_TD_DETAIL=(2 << G_MDSFT_TEXTDETAIL)\n" -"G_TL_TILE=(0 << G_MDSFT_TEXTLOD)\n" -"G_TL_LOD=(1 << G_MDSFT_TEXTLOD)\n" -"G_TT_NONE=(0 << G_MDSFT_TEXTLUT)\n" -"G_TT_RGBA16=(2 << G_MDSFT_TEXTLUT)\n" -"G_TT_IA16=(3 << G_MDSFT_TEXTLUT)\n" -"G_TF_POINT=(0 << G_MDSFT_TEXTFILT)\n" -"G_TF_AVERAGE=(3 << G_MDSFT_TEXTFILT)\n" -"G_TF_BILERP=(2 << G_MDSFT_TEXTFILT)\n" -"G_TC_CONV=(0 << G_MDSFT_TEXTCONV)\n" -"G_TC_FILTCONV=(5 << G_MDSFT_TEXTCONV)\n" -"G_TC_FILT=(6 << G_MDSFT_TEXTCONV)\n" -"G_CK_NONE=(0 << G_MDSFT_COMBKEY)\n" -"G_CK_KEY=(1 << G_MDSFT_COMBKEY)\n" -"G_CD_MAGICSQ=(0 << G_MDSFT_RGBDITHER)\n" -"G_CD_BAYER=(1 << G_MDSFT_RGBDITHER)\n" -"G_CD_NOISE=(2 << G_MDSFT_RGBDITHER)\n" -#ifndef _HW_VERSION_1 -"G_CD_DISABLE=(3 << G_MDSFT_RGBDITHER)\n" -"G_CD_ENABLE=G_CD_NOISE\n" -#else // #ifndef _HW_VERSION_1 -"G_CD_ENABLE=(1 << G_MDSFT_COLORDITHER)\n" -"G_CD_DISABLE=(0 << G_MDSFT_COLORDITHER)\n" -#endif // #ifndef _HW_VERSION_1 -"G_AD_PATTERN=(0 << G_MDSFT_ALPHADITHER)\n" -"G_AD_NOTPATTERN=(1 << G_MDSFT_ALPHADITHER)\n" -"G_AD_NOISE=(2 << G_MDSFT_ALPHADITHER)\n" -"G_AD_DISABLE=(3 << G_MDSFT_ALPHADITHER)\n" -"G_AC_NONE=(0 << G_MDSFT_ALPHACOMPARE)\n" -"G_AC_THRESHOLD=(1 << G_MDSFT_ALPHACOMPARE)\n" -"G_AC_DITHER=(3 << G_MDSFT_ALPHACOMPARE)\n" -"G_ZS_PIXEL=(0 << G_MDSFT_ZSRCSEL)\n" -"G_ZS_PRIM=(1 << G_MDSFT_ZSRCSEL)\n" -"AA_EN=0x8\n" -"Z_CMP=0x10\n" -"Z_UPD=0x20\n" -"IM_RD=0x40\n" -"CLR_ON_CVG=0x80\n" -"CVG_DST_CLAMP=0\n" -"CVG_DST_WRAP=0x100\n" -"CVG_DST_FULL=0x200\n" -"CVG_DST_SAVE=0x300\n" -"ZMODE_OPA=0\n" -"ZMODE_INTER=0x400\n" -"ZMODE_XLU=0x800\n" -"ZMODE_DEC=0xc00\n" -"CVG_X_ALPHA=0x1000\n" -"ALPHA_CVG_SEL=0x2000\n" -"FORCE_BL=0x4000\n" -"TEX_EDGE=0x0000\n" -"G_BL_CLR_IN=0\n" -"G_BL_CLR_MEM=1\n" -"G_BL_CLR_BL=2\n" -"G_BL_CLR_FOG=3\n" -"G_BL_1MA=0\n" -"G_BL_A_MEM=1\n" -"G_BL_A_IN=0\n" -"G_BL_A_FOG=1\n" -"G_BL_A_SHADE=2\n" -"G_BL_1=2\n" -"G_BL_0=3\n" -"G_CV_K0=175\n" -"G_CV_K1=-43\n" -"G_CV_K2=-89\n" -"G_CV_K3=222\n" -"G_CV_K4=114\n" -"G_CV_K5=42\n" -"G_SC_NON_INTERLACE=0\n" -"G_SC_ODD_INTERLACE=3\n" -"G_SC_EVEN_INTERLACE=2\n" -"G_DL_PUSH=0x00\n" -"G_DL_NOPUSH=0x01\n" -"G_MW_MATRIX=0x00\n" -"G_MW_NUMLIGHT=0x02\n" -"G_MW_CLIP=0x04\n" -"G_MW_SEGMENT=0x06\n" -"G_MW_FOG=0x08\n" -"G_MW_LIGHTCOL=0x0a\n" -"G_MW_PERSPNORM=0x0e\n" -"G_MWO_NUMLIGHT=0x00\n" -"G_MWO_CLIP_RNX=0x04\n" -"G_MWO_CLIP_RNY=0x0c\n" -"G_MWO_CLIP_RPX=0x14\n" -"G_MWO_CLIP_RPY=0x1c\n" -"G_MWO_SEGMENT_0=0x00\n" -"G_MWO_SEGMENT_1=0x01\n" -"G_MWO_SEGMENT_2=0x02\n" -"G_MWO_SEGMENT_3=0x03\n" -"G_MWO_SEGMENT_4=0x04\n" -"G_MWO_SEGMENT_5=0x05\n" -"G_MWO_SEGMENT_6=0x06\n" -"G_MWO_SEGMENT_7=0x07\n" -"G_MWO_SEGMENT_8=0x08\n" -"G_MWO_SEGMENT_9=0x09\n" -"G_MWO_SEGMENT_A=0x0a\n" -"G_MWO_SEGMENT_B=0x0b\n" -"G_MWO_SEGMENT_C=0x0c\n" -"G_MWO_SEGMENT_D=0x0d\n" -"G_MWO_SEGMENT_E=0x0e\n" -"G_MWO_SEGMENT_F=0x0f\n" -"G_MWO_FOG=0x00\n" -"G_MWO_aLIGHT_1=0x00\n" -"G_MWO_bLIGHT_1=0x04\n" -#ifdef F3DEX_GBI_2 -"G_MWO_aLIGHT_2=0x18\n" -"G_MWO_bLIGHT_2=0x1c\n" -"G_MWO_aLIGHT_3=0x30\n" -"G_MWO_bLIGHT_3=0x34\n" -"G_MWO_aLIGHT_4=0x48\n" -"G_MWO_bLIGHT_4=0x4c\n" -"G_MWO_aLIGHT_5=0x60\n" -"G_MWO_bLIGHT_5=0x64\n" -"G_MWO_aLIGHT_6=0x78\n" -"G_MWO_bLIGHT_6=0x7c\n" -"G_MWO_aLIGHT_7=0x90\n" -"G_MWO_bLIGHT_7=0x94\n" -"G_MWO_aLIGHT_8=0xa8\n" -"G_MWO_bLIGHT_8=0xac\n" -#else // #ifdef F3DEX_GBI_2 -"G_MWO_aLIGHT_2=0x20\n" -"G_MWO_bLIGHT_2=0x24\n" -"G_MWO_aLIGHT_3=0x40\n" -"G_MWO_bLIGHT_3=0x44\n" -"G_MWO_aLIGHT_4=0x60\n" -"G_MWO_bLIGHT_4=0x64\n" -"G_MWO_aLIGHT_5=0x80\n" -"G_MWO_bLIGHT_5=0x84\n" -"G_MWO_aLIGHT_6=0xa0\n" -"G_MWO_bLIGHT_6=0xa4\n" -"G_MWO_aLIGHT_7=0xc0\n" -"G_MWO_bLIGHT_7=0xc4\n" -"G_MWO_aLIGHT_8=0xe0\n" -"G_MWO_bLIGHT_8=0xe4\n" -#endif // #ifdef F3DEX_GBI_2 -"G_MWO_MATRIX_XX_XY_I=0x00\n" -"G_MWO_MATRIX_XZ_XW_I=0x04\n" -"G_MWO_MATRIX_YX_YY_I=0x08\n" -"G_MWO_MATRIX_YZ_YW_I=0x0c\n" -"G_MWO_MATRIX_ZX_ZY_I=0x10\n" -"G_MWO_MATRIX_ZZ_ZW_I=0x14\n" -"G_MWO_MATRIX_WX_WY_I=0x18\n" -"G_MWO_MATRIX_WZ_WW_I=0x1c\n" -"G_MWO_MATRIX_XX_XY_F=0x20\n" -"G_MWO_MATRIX_XZ_XW_F=0x24\n" -"G_MWO_MATRIX_YX_YY_F=0x28\n" -"G_MWO_MATRIX_YZ_YW_F=0x2c\n" -"G_MWO_MATRIX_ZX_ZY_F=0x30\n" -"G_MWO_MATRIX_ZZ_ZW_F=0x34\n" -"G_MWO_MATRIX_WX_WY_F=0x38\n" -"G_MWO_MATRIX_WZ_WW_F=0x3c\n" -"G_MWO_POINT_RGBA=0x10\n" -"G_MWO_POINT_ST=0x14\n" -"G_MWO_POINT_XYSCREEN=0x18\n" -"G_MWO_POINT_ZSCREEN=0x1c\n" -"FR_NEG_FRUSTRATIO_1=0x00000001\n" -"FR_POS_FRUSTRATIO_1=0x0000ffff\n" -"FR_NEG_FRUSTRATIO_2=0x00000002\n" -"FR_POS_FRUSTRATIO_2=0x0000fffe\n" -"FR_NEG_FRUSTRATIO_3=0x00000003\n" -"FR_POS_FRUSTRATIO_3=0x0000fffd\n" -"FR_NEG_FRUSTRATIO_4=0x00000004\n" -"FR_POS_FRUSTRATIO_4=0x0000fffc\n" -"FR_NEG_FRUSTRATIO_5=0x00000005\n" -"FR_POS_FRUSTRATIO_5=0x0000fffb\n" -"FR_NEG_FRUSTRATIO_6=0x00000006\n" -"FR_POS_FRUSTRATIO_6=0x0000fffa\n" -"NUMLIGHTS_0=1\n" -"NUMLIGHTS_1=1\n" -"NUMLIGHTS_2=2\n" -"NUMLIGHTS_3=3\n" -"NUMLIGHTS_4=4\n" -"NUMLIGHTS_5=5\n" -"NUMLIGHTS_6=6\n" -"NUMLIGHTS_7=7\n" -"LIGHT_1=1\n" -"LIGHT_2=2\n" -"LIGHT_3=3\n" -"LIGHT_4=4\n" -"LIGHT_5=5\n" -"LIGHT_6=6\n" -"LIGHT_7=7\n" -"LIGHT_8=8\n" -"G_TX_LOADTILE=7\n" -"G_TX_RENDERTILE=0\n" -"G_TX_NOMIRROR=0\n" -"G_TX_WRAP=0\n" -"G_TX_MIRROR=0x1\n" -"G_TX_CLAMP=0x2\n" -"G_TX_NOMASK=0\n" -"G_TX_NOLOD=0\n" -"G_TX_DXT_FRAC=11\n" -#ifdef _HW_VERSION_1 -"G_TX_LDBLK_MAX_TXL=4095\n" -#else // #ifdef _HW_VERSION_1 -"G_TX_LDBLK_MAX_TXL=2047\n" -#endif // #ifdef _HW_VERSION_1 "BACKGROUND_OCEAN_SKY=0\n" "BACKGROUND_FLAMING_SKY=1\n" "BACKGROUND_UNDERWATER_CITY=2\n" diff --git a/src/pc/lua/smlua_functions.c b/src/pc/lua/smlua_functions.c index 936eb9386..e48c5e6f2 100644 --- a/src/pc/lua/smlua_functions.c +++ b/src/pc/lua/smlua_functions.c @@ -1067,44 +1067,78 @@ int smlua_func_get_uncolored_string(lua_State* L) { // display list // ////////////////// -#define HANDLE_PARAM(paramNum) \ -s64 arg##paramNum = smlua_to_integer(L, 2 + paramNum); \ -if (!gSmLuaConvertSuccess) { \ - LOG_LUA("gfx_set_command: '%s' failed to convert parameter " #paramNum ".", symbolName); \ - return 0; \ -} - -#define GET_ARG(paramNum) arg##paramNum -#define CALL_SYMB(symb, ...) symb(__VA_ARGS__) - -// Uses macro iterators to dynamically handle the correct number of parameters -#define define_gfx_symbol(symb, params, ...) \ -if (strcmp(command, #symb) == 0) { \ - if (paramCount != params) { LOG_LUA("gfx_set_command: '" #symb "' received incorrect number of parameters. Received %u, expected %u", paramCount, params); return 0; } \ - UNUSED const char symbolName[] = #symb; \ - REPEAT(HANDLE_PARAM, params); \ - const Gfx _Gfx[] = { CALL_SYMB(symb, LIST_ARGS(GET_ARG, params)) }; \ - memcpy(gfx, _Gfx, sizeof(_Gfx)); \ - return 1; \ +static int get_gfx_command_specifiers_count(const char *command) { + int count = 0; + for (; *command; count += (*command == '%'), command++); + return count; } int smlua_func_gfx_set_command(lua_State* L) { int top = lua_gettop(L); if (top < 2) { - LOG_LUA_LINE("Improper param count: Expected at least 2, Received %u", top); + LOG_LUA_LINE("gfx_set_command: Improper param count: Expected at least 2, Received %u", top); return 0; } Gfx* gfx = smlua_to_cobject(L, 1, LOT_GFX); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_set_command"); return 0; } + if (!gSmLuaConvertSuccess) { + LOG_LUA("gfx_set_command: Failed to convert parameter %u", 1); + return 0; + } const char *command = smlua_to_string(L, 2); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_set_command"); return 0; } + if (!gSmLuaConvertSuccess) { + LOG_LUA("gfx_set_command: Failed to convert parameter %u", 2); + return 0; + } - u16 paramCount = top - 2; + // Compare the number of provided parameters to the number of specifiers in the command + int paramCount = top - 2; + int specifiersCount = get_gfx_command_specifiers_count(command); + if (specifiersCount != paramCount) { + LOG_LUA_LINE("gfx_set_command: Command \"%s\": Invalid number of command parameters: Expected %u, provided %u", command, specifiersCount, paramCount); + return 0; + } - // Handle commands using the define_gfx_symbol macro - GFX_SYMBOLS(); + // Parse the command + const u32 errorSize = 0x400; + char errorMsg[errorSize]; + if (!dynos_smlua_parse_gfx_command(L, gfx, command, specifiersCount != 0, errorMsg, errorSize)) { + LOG_LUA_LINE("gfx_set_command: Command \"%s\": %s", command, errorMsg); + return 0; + } + + return 1; +} + +int smlua_func_gfx_get_from_name(lua_State *L) { + if (!smlua_functions_valid_param_count(L, 1)) { return 0; } + + const char *name = smlua_to_string(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("gfx_get_from_name: Failed to convert parameter 1"); return 0; } + + u32 length = 0; + Gfx *gfx = dynos_gfx_get(name, &length); + + smlua_push_object(L, LOT_GFX, gfx, NULL); + lua_pushinteger(L, length); + + return 2; +} + +int smlua_func_vtx_get_from_name(lua_State *L) { + if (!smlua_functions_valid_param_count(L, 1)) { return 0; } + + const char *name = smlua_to_string(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("vtx_get_from_name: Failed to convert parameter 1"); return 0; } + + u32 count = 0; + Vtx *vtx = dynos_vtx_get(name, &count); + + smlua_push_object(L, LOT_VTX, vtx, NULL); + lua_pushinteger(L, count); + + return 2; } ////////// @@ -1139,4 +1173,6 @@ void smlua_bind_functions(void) { smlua_bind_function(L, "cast_graph_node", smlua_func_cast_graph_node); smlua_bind_function(L, "get_uncolored_string", smlua_func_get_uncolored_string); smlua_bind_function(L, "gfx_set_command", smlua_func_gfx_set_command); + smlua_bind_function(L, "gfx_get_from_name", smlua_func_gfx_get_from_name); + smlua_bind_function(L, "vtx_get_from_name", smlua_func_vtx_get_from_name); } diff --git a/src/pc/lua/smlua_functions_autogen.c b/src/pc/lua/smlua_functions_autogen.c index ff830ba37..8d3111d19 100644 --- a/src/pc/lua/smlua_functions_autogen.c +++ b/src/pc/lua/smlua_functions_autogen.c @@ -30125,7 +30125,7 @@ int smlua_func_gfx_parse(lua_State* L) { } if (lua_isnil(L, 1)) { return 0; } - Gfx* cmd = (Gfx*)smlua_to_cobject(L, 1, LOT_GFX); + Gfx * cmd = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_parse"); return 0; } LuaFunction func = smlua_to_lua_function(L, 2); if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_parse"); return 0; } @@ -30135,116 +30135,346 @@ int smlua_func_gfx_parse(lua_State* L) { return 1; } -int smlua_func_gfx_get_vtx(lua_State* L) { - if (L == NULL) { return 0; } - - int top = lua_gettop(L); - if (top != 2) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_vtx", 2, top); - return 0; - } - - if (lua_isnil(L, 1)) { return 0; } - Gfx* gfx = (Gfx*)smlua_to_cobject(L, 1, LOT_GFX); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_vtx"); return 0; } - u16 offset = smlua_to_integer(L, 2); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_get_vtx"); return 0; } - - smlua_push_object(L, LOT_VTX, gfx_get_vtx(gfx, offset), NULL); - - return 1; -} - -int smlua_func_gfx_get_vtx_count(lua_State* L) { +int smlua_func_gfx_get_op(lua_State* L) { if (L == NULL) { return 0; } int top = lua_gettop(L); if (top != 1) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_vtx_count", 1, top); + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_op", 1, top); return 0; } if (lua_isnil(L, 1)) { return 0; } - Gfx* cmd = (Gfx*)smlua_to_cobject(L, 1, LOT_GFX); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_vtx_count"); return 0; } + Gfx * cmd = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_op"); return 0; } - lua_pushinteger(L, gfx_get_vtx_count(cmd)); + lua_pushinteger(L, gfx_get_op(cmd)); return 1; } -int smlua_func_gfx_set_combine_lerp(lua_State* L) { +int smlua_func_gfx_get_display_list(lua_State* L) { if (L == NULL) { return 0; } int top = lua_gettop(L); - if (top != 17) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_set_combine_lerp", 17, top); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_display_list", 1, top); return 0; } if (lua_isnil(L, 1)) { return 0; } - Gfx* gfx = (Gfx*)smlua_to_cobject(L, 1, LOT_GFX); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_set_combine_lerp"); return 0; } - u32 a0 = smlua_to_integer(L, 2); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_set_combine_lerp"); return 0; } - u32 b0 = smlua_to_integer(L, 3); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "gfx_set_combine_lerp"); return 0; } - u32 c0 = smlua_to_integer(L, 4); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "gfx_set_combine_lerp"); return 0; } - u32 d0 = smlua_to_integer(L, 5); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "gfx_set_combine_lerp"); return 0; } - u32 Aa0 = smlua_to_integer(L, 6); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 6, "gfx_set_combine_lerp"); return 0; } - u32 Ab0 = smlua_to_integer(L, 7); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 7, "gfx_set_combine_lerp"); return 0; } - u32 Ac0 = smlua_to_integer(L, 8); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 8, "gfx_set_combine_lerp"); return 0; } - u32 Ad0 = smlua_to_integer(L, 9); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 9, "gfx_set_combine_lerp"); return 0; } - u32 a1 = smlua_to_integer(L, 10); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 10, "gfx_set_combine_lerp"); return 0; } - u32 b1 = smlua_to_integer(L, 11); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 11, "gfx_set_combine_lerp"); return 0; } - u32 c1 = smlua_to_integer(L, 12); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 12, "gfx_set_combine_lerp"); return 0; } - u32 d1 = smlua_to_integer(L, 13); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 13, "gfx_set_combine_lerp"); return 0; } - u32 Aa1 = smlua_to_integer(L, 14); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 14, "gfx_set_combine_lerp"); return 0; } - u32 Ab1 = smlua_to_integer(L, 15); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 15, "gfx_set_combine_lerp"); return 0; } - u32 Ac1 = smlua_to_integer(L, 16); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 16, "gfx_set_combine_lerp"); return 0; } - u32 Ad1 = smlua_to_integer(L, 17); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 17, "gfx_set_combine_lerp"); return 0; } + Gfx * cmd = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_display_list"); return 0; } - gfx_set_combine_lerp(gfx, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1); + smlua_push_object(L, LOT_GFX, gfx_get_display_list(cmd), NULL); return 1; } -int smlua_func_gfx_set_texture_image(lua_State* L) { +int smlua_func_gfx_get_vertex_buffer(lua_State* L) { if (L == NULL) { return 0; } int top = lua_gettop(L); - if (top != 5) { - LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_set_texture_image", 5, top); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_vertex_buffer", 1, top); return 0; } if (lua_isnil(L, 1)) { return 0; } - Gfx* gfx = (Gfx*)smlua_to_cobject(L, 1, LOT_GFX); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_set_texture_image"); return 0; } - u32 format = smlua_to_integer(L, 2); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_set_texture_image"); return 0; } - u32 size = smlua_to_integer(L, 3); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "gfx_set_texture_image"); return 0; } - u32 width = smlua_to_integer(L, 4); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 4, "gfx_set_texture_image"); return 0; } - u8* texture = (u8*)smlua_to_cpointer(L, 5, LVT_U8_P); - if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 5, "gfx_set_texture_image"); return 0; } + Gfx * cmd = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_vertex_buffer"); return 0; } - gfx_set_texture_image(gfx, format, size, width, texture); + smlua_push_object(L, LOT_VTX, gfx_get_vertex_buffer(cmd), NULL); + + return 1; +} + +int smlua_func_gfx_get_vertex_count(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_vertex_count", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * cmd = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_vertex_count"); return 0; } + + lua_pushinteger(L, gfx_get_vertex_count(cmd)); + + return 1; +} + +int smlua_func_gfx_get_length(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_length", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * gfx = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_length"); return 0; } + + lua_pushinteger(L, gfx_get_length(gfx)); + + return 1; +} + +int smlua_func_gfx_get_command(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_command", 2, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * gfx = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_command"); return 0; } + u32 offset = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_get_command"); return 0; } + + smlua_push_object(L, LOT_GFX, gfx_get_command(gfx, offset), NULL); + + return 1; +} + +int smlua_func_gfx_get_next_command(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_get_next_command", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * gfx = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_get_next_command"); return 0; } + + smlua_push_object(L, LOT_GFX, gfx_get_next_command(gfx), NULL); + + return 1; +} + +int smlua_func_gfx_copy(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_copy", 3, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * dest = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_copy"); return 0; } + if (lua_isnil(L, 2)) { return 0; } + Gfx * src = (Gfx *)smlua_to_cobject(L, 2, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_copy"); return 0; } + u32 length = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "gfx_copy"); return 0; } + + gfx_copy(dest, src, length); + + return 1; +} + +int smlua_func_gfx_new(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_new", 2, top); + return 0; + } + + const char* name = smlua_to_string(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_new"); return 0; } + u32 length = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_new"); return 0; } + + smlua_push_object(L, LOT_GFX, gfx_new(name, length), NULL); + + return 1; +} + +int smlua_func_gfx_realloc(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_realloc", 2, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * gfx = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_realloc"); return 0; } + u32 newLength = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "gfx_realloc"); return 0; } + + smlua_push_object(L, LOT_GFX, gfx_realloc(gfx, newLength), NULL); + + return 1; +} + +int smlua_func_gfx_delete(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "gfx_delete", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Gfx * gfx = (Gfx *)smlua_to_cobject(L, 1, LOT_GFX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "gfx_delete"); return 0; } + + gfx_delete(gfx); + + return 1; +} + +int smlua_func_vtx_get_count(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_get_count", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Vtx * vtx = (Vtx *)smlua_to_cobject(L, 1, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_get_count"); return 0; } + + lua_pushinteger(L, vtx_get_count(vtx)); + + return 1; +} + +int smlua_func_vtx_get_vertex(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_get_vertex", 2, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Vtx * vtx = (Vtx *)smlua_to_cobject(L, 1, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_get_vertex"); return 0; } + u32 offset = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "vtx_get_vertex"); return 0; } + + smlua_push_object(L, LOT_VTX, vtx_get_vertex(vtx, offset), NULL); + + return 1; +} + +int smlua_func_vtx_get_next_vertex(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_get_next_vertex", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Vtx * vtx = (Vtx *)smlua_to_cobject(L, 1, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_get_next_vertex"); return 0; } + + smlua_push_object(L, LOT_VTX, vtx_get_next_vertex(vtx), NULL); + + return 1; +} + +int smlua_func_vtx_copy(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 3) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_copy", 3, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Vtx * dest = (Vtx *)smlua_to_cobject(L, 1, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_copy"); return 0; } + if (lua_isnil(L, 2)) { return 0; } + Vtx * src = (Vtx *)smlua_to_cobject(L, 2, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "vtx_copy"); return 0; } + u32 count = smlua_to_integer(L, 3); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 3, "vtx_copy"); return 0; } + + vtx_copy(dest, src, count); + + return 1; +} + +int smlua_func_vtx_new(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_new", 2, top); + return 0; + } + + const char* name = smlua_to_string(L, 1); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_new"); return 0; } + u32 count = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "vtx_new"); return 0; } + + smlua_push_object(L, LOT_VTX, vtx_new(name, count), NULL); + + return 1; +} + +int smlua_func_vtx_realloc(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 2) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_realloc", 2, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Vtx * vtx = (Vtx *)smlua_to_cobject(L, 1, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_realloc"); return 0; } + u32 newCount = smlua_to_integer(L, 2); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 2, "vtx_realloc"); return 0; } + + smlua_push_object(L, LOT_VTX, vtx_realloc(vtx, newCount), NULL); + + return 1; +} + +int smlua_func_vtx_delete(lua_State* L) { + if (L == NULL) { return 0; } + + int top = lua_gettop(L); + if (top != 1) { + LOG_LUA_LINE("Improper param count for '%s': Expected %u, Received %u", "vtx_delete", 1, top); + return 0; + } + + if (lua_isnil(L, 1)) { return 0; } + Vtx * vtx = (Vtx *)smlua_to_cobject(L, 1, LOT_VTX); + if (!gSmLuaConvertSuccess) { LOG_LUA("Failed to convert parameter %u for function '%s'", 1, "vtx_delete"); return 0; } + + vtx_delete(vtx); return 1; } @@ -35626,10 +35856,24 @@ void smlua_bind_functions_autogen(void) { smlua_bind_function(L, "get_skybox_color", smlua_func_get_skybox_color); smlua_bind_function(L, "set_skybox_color", smlua_func_set_skybox_color); smlua_bind_function(L, "gfx_parse", smlua_func_gfx_parse); - smlua_bind_function(L, "gfx_get_vtx", smlua_func_gfx_get_vtx); - smlua_bind_function(L, "gfx_get_vtx_count", smlua_func_gfx_get_vtx_count); - smlua_bind_function(L, "gfx_set_combine_lerp", smlua_func_gfx_set_combine_lerp); - smlua_bind_function(L, "gfx_set_texture_image", smlua_func_gfx_set_texture_image); + smlua_bind_function(L, "gfx_get_op", smlua_func_gfx_get_op); + smlua_bind_function(L, "gfx_get_display_list", smlua_func_gfx_get_display_list); + smlua_bind_function(L, "gfx_get_vertex_buffer", smlua_func_gfx_get_vertex_buffer); + smlua_bind_function(L, "gfx_get_vertex_count", smlua_func_gfx_get_vertex_count); + smlua_bind_function(L, "gfx_get_length", smlua_func_gfx_get_length); + smlua_bind_function(L, "gfx_get_command", smlua_func_gfx_get_command); + smlua_bind_function(L, "gfx_get_next_command", smlua_func_gfx_get_next_command); + smlua_bind_function(L, "gfx_copy", smlua_func_gfx_copy); + smlua_bind_function(L, "gfx_new", smlua_func_gfx_new); + smlua_bind_function(L, "gfx_realloc", smlua_func_gfx_realloc); + smlua_bind_function(L, "gfx_delete", smlua_func_gfx_delete); + smlua_bind_function(L, "vtx_get_count", smlua_func_vtx_get_count); + smlua_bind_function(L, "vtx_get_vertex", smlua_func_vtx_get_vertex); + smlua_bind_function(L, "vtx_get_next_vertex", smlua_func_vtx_get_next_vertex); + smlua_bind_function(L, "vtx_copy", smlua_func_vtx_copy); + smlua_bind_function(L, "vtx_new", smlua_func_vtx_new); + smlua_bind_function(L, "vtx_realloc", smlua_func_vtx_realloc); + smlua_bind_function(L, "vtx_delete", smlua_func_vtx_delete); // smlua_level_utils.h smlua_bind_function(L, "smlua_level_util_change_area", smlua_func_smlua_level_util_change_area); diff --git a/src/pc/lua/utils/smlua_gfx_utils.c b/src/pc/lua/utils/smlua_gfx_utils.c index 389aa0e58..9d5995f25 100644 --- a/src/pc/lua/utils/smlua_gfx_utils.c +++ b/src/pc/lua/utils/smlua_gfx_utils.c @@ -3,7 +3,6 @@ #include "game/rendering_graph_node.h" #include "game/skybox.h" #include "geo_commands.h" -#include "engine/display_list.h" void set_override_fov(f32 fov) { gOverrideFOV = fov; @@ -108,16 +107,70 @@ void set_skybox_color(u8 index, u8 value) { gSkyboxColor[index] = value; } -/// + /////////////////// + // Display lists // +/////////////////// + +// +// The following code and functions assume the current microcode +// is Fast3DEX2 Extended, and all commands are of size 1 +// + +#ifndef GBI_NO_MULTI_COMMANDS +#error "GBI_NO_MULTI_COMMANDS not set: All GBI commands must be of size 1" +#endif +#ifndef F3DEX_GBI_2E +#error "F3DEX_GBI_2E not set: Microcode must be set to `f3dex2e`" +#endif + +// +// Sentinel values for dynamically allocated Gfx and Vtx buffers +// It will prevent out-of-bounds accesses and buffer overflows +// +// SENTINEL_GFX is a gsSPEndDisplayList() with all other bits set +// SENTINEL_VTX bits are all set, which results in a bunch of NaN when treated as a Vtx +// + +static const Gfx SENTINEL_GFX[1] = {{{ _SHIFTL(G_ENDDL, 24, 8) | _SHIFTL(UINT32_MAX, 0, 24), UINT32_MAX }}}; +static const u8 SENTINEL_VTX[sizeof(Vtx)] = {[0 ... sizeof(Vtx) - 1] = UINT8_MAX}; + +Gfx *gfx_allocate_internal(u32 length) { + if (!length) { return NULL; } + Gfx *gfx = calloc(length + 1, sizeof(Gfx)); + memcpy(gfx + length, SENTINEL_GFX, sizeof(Gfx)); + return gfx; +} + +Vtx *vtx_allocate_internal(u32 count) { + if (!count) { return NULL; } + Vtx *vtx = calloc(count + 1, sizeof(Vtx)); + memcpy(vtx + count, SENTINEL_VTX, sizeof(Vtx)); + return vtx; +} + +// Get the size of a display list by iterating +// until gsSPEndDisplayList or gsSPBranchList is found +u32 gfx_get_length_no_sentinel(const Gfx *gfx) { + if (!gfx) { return 0; } + for (u32 i = 0;; ++i) { + u32 op = GFX_OP(gfx + i); + switch (op) { + case G_DL: + if (C0(gfx + i, 16, 1) == G_DL_NOPUSH) { return i + 1; } // For displaylists that end with branches (jumps) + break; + case G_ENDDL: + return i + 1; + } + } +} -// Assumes the current microcode is Fast3DEX2 Extended (default for pc port) void gfx_parse(Gfx* cmd, LuaFunction func) { if (!cmd) { return; } if (func == 0) { return; } lua_State* L = gLuaState; - while (true) { - u32 op = cmd->words.w0 >> 24; + for (;; cmd++) { + u32 op = GFX_OP(cmd); switch (op) { case G_DL: if (C0(cmd, 16, 1) == G_DL_PUSH) { @@ -127,16 +180,10 @@ void gfx_parse(Gfx* cmd, LuaFunction func) { --cmd; } break; + case (uint8_t) G_ENDDL: return; // Reached end of display list - case G_TEXRECT: - case G_TEXRECTFLIP: - ++cmd; - ++cmd; - break; - case G_FILLRECT: - ++cmd; - break; + default: lua_rawgeti(L, LUA_REGISTRYINDEX, func); smlua_push_object(L, LOT_GFX, cmd, NULL); @@ -149,37 +196,196 @@ void gfx_parse(Gfx* cmd, LuaFunction func) { } break; } - ++cmd; } } -Vtx *gfx_get_vtx(Gfx* cmd, u16 offset) { +u32 gfx_get_op(Gfx *cmd) { + if (!cmd) { return G_NOOP; } + + return GFX_OP(cmd); +} + +Gfx *gfx_get_display_list(Gfx *cmd) { if (!cmd) { return NULL; } - u32 op = cmd->words.w0 >> 24; + u32 op = GFX_OP(cmd); + if (op != G_DL) { return NULL; } + if (cmd->words.w1 == 0) { return NULL; } + + return (Gfx *) cmd->words.w1; +} + +Vtx *gfx_get_vertex_buffer(Gfx *cmd) { + if (!cmd) { return NULL; } + u32 op = GFX_OP(cmd); if (op != G_VTX) { return NULL; } if (cmd->words.w1 == 0) { return NULL; } - u16 numVertices = C0(cmd, 12, 8); - if (offset >= numVertices) { return NULL; } - - return &((Vtx *) cmd->words.w1)[offset]; + return (Vtx *) cmd->words.w1; } -u16 gfx_get_vtx_count(Gfx* cmd) { +u16 gfx_get_vertex_count(Gfx *cmd) { if (!cmd) { return 0; } - u32 op = cmd->words.w0 >> 24; + u32 op = GFX_OP(cmd); if (op != G_VTX) { return 0; } if (cmd->words.w1 == 0) { return 0; } return C0(cmd, 12, 8); } -void gfx_set_combine_lerp(Gfx* gfx, u32 a0, u32 b0, u32 c0, u32 d0, u32 Aa0, u32 Ab0, u32 Ac0, u32 Ad0, u32 a1, u32 b1, u32 c1, u32 d1, u32 Aa1, u32 Ab1, u32 Ac1, u32 Ad1) { - if (!gfx) { return; } - gDPSetCombineLERPNoString(gfx, a0, b0, c0, d0, Aa0, Ab0, Ac0, Ad0, a1, b1, c1, d1, Aa1, Ab1, Ac1, Ad1); +u32 gfx_get_length(Gfx *gfx) { + if (!gfx) { return 0; } + + u32 length = 0; + for (; memcmp(gfx, SENTINEL_GFX, sizeof(Gfx)) != 0; ++length, gfx++); + return length; } -void gfx_set_texture_image(Gfx* gfx, u32 format, u32 size, u32 width, u8* texture) { - if (!gfx) { return; } - gDPSetTextureImage(gfx, format, size, width, texture); +Gfx *gfx_get_command(Gfx *gfx, u32 offset) { + if (!gfx) { return NULL; } + if (offset >= gfx_get_length(gfx)) { return NULL; } + + return &gfx[offset]; +} + +Gfx *gfx_get_next_command(Gfx *gfx) { + if (!gfx) { return NULL; } + + gfx++; + return memcmp(gfx, SENTINEL_GFX, sizeof(Gfx)) != 0 ? gfx : NULL; +} + +void gfx_copy(Gfx *dest, Gfx *src, u32 length) { + if (!src || !dest || !length) { return; } + + u32 srcLength = gfx_get_length(src); + if (length > srcLength) { + LOG_LUA_LINE("gfx_copy: Cannot copy %u commands from a display list of length: %u", length, srcLength); + return; + } + + u32 destLength = gfx_get_length(dest); + if (length > destLength) { + LOG_LUA_LINE("gfx_copy: Cannot copy %u commands to a display list of length: %u", length, srcLength); + return; + } + + memcpy(dest, src, length * sizeof(Gfx)); +} + +Gfx *gfx_new(const char *name, u32 length) { + if (!name || !length) { return NULL; } + + // Make sure to not take the name of a level/model/vanilla display list + u32 outLength; + if (dynos_gfx_get(name, &outLength)) { + LOG_LUA_LINE("gfx_new: Display list `%s` already exists", name); + return NULL; + } + + Gfx *gfx = dynos_gfx_new(name, length); + if (!gfx) { + LOG_LUA_LINE("gfx_new: Display list `%s` already exists", name); + return NULL; + } + + return gfx; +} + +Gfx *gfx_realloc(Gfx *gfx, u32 newLength) { + if (!gfx || !newLength) { return NULL; } + + Gfx *newGfx = dynos_gfx_realloc(gfx, newLength); + if (!newGfx) { + LOG_LUA_LINE("gfx_realloc: Display list was not allocated by `gfx_new`"); + return NULL; + } + + return newGfx; +} + +void gfx_delete(Gfx *gfx) { + if (!gfx) { return; } + + if (!dynos_gfx_delete(gfx)) { + LOG_LUA_LINE("gfx_delete: Display list was not allocated by `gfx_new`"); + } +} + +u32 vtx_get_count(Vtx *vtx) { + if (!vtx) { return 0; } + + u32 count = 0; + for (; memcmp(vtx, SENTINEL_VTX, sizeof(Vtx)) != 0; ++count, vtx++); + return count; +} + +Vtx *vtx_get_vertex(Vtx *vtx, u32 offset) { + if (!vtx) { return NULL; } + if (offset >= vtx_get_count(vtx)) { return NULL; } + + return &vtx[offset]; +} + +Vtx *vtx_get_next_vertex(Vtx *vtx) { + if (!vtx) { return NULL; } + + vtx++; + return memcmp(vtx, SENTINEL_VTX, sizeof(Vtx)) != 0 ? vtx : NULL; +} + +void vtx_copy(Vtx *dest, Vtx *src, u32 count) { + if (!src || !dest || !count) { return; } + + u32 srcLength = vtx_get_count(src); + if (count > srcLength) { + LOG_LUA_LINE("vtx_copy: Cannot copy %u vertices from a vertex buffer of count: %u", count, srcLength); + return; + } + + u32 destLength = vtx_get_count(dest); + if (count > destLength) { + LOG_LUA_LINE("vtx_copy: Cannot copy %u vertices to a vertex buffer of count: %u", count, srcLength); + return; + } + + memcpy(dest, src, count * sizeof(Vtx)); +} + +Vtx *vtx_new(const char *name, u32 count) { + if (!name || !count) { return NULL; } + + // Make sure to not take the name of a level/model/vanilla vertex buffer + u32 outCount; + if (dynos_vtx_get(name, &outCount)) { + LOG_LUA_LINE("vtx_new: Vertex buffer `%s` already exists", name); + return NULL; + } + + Vtx *vtx = dynos_vtx_new(name, count); + if (!vtx) { + LOG_LUA_LINE("vtx_new: Vertex buffer `%s` already exists", name); + return NULL; + } + + return vtx; +} + +Vtx *vtx_realloc(Vtx *vtx, u32 newCount) { + if (!vtx || !newCount) { return NULL; } + + Vtx *newVtx = dynos_vtx_realloc(vtx, newCount); + if (!newVtx) { + LOG_LUA_LINE("vtx_realloc: Vertex buffer was not allocated by `vtx_new`"); + return NULL; + } + + return newVtx; +} + +void vtx_delete(Vtx *vtx) { + if (!vtx) { return; } + + if (!dynos_vtx_delete(vtx)) { + LOG_LUA_LINE("vtx_delete: Vertex buffer was not allocated by `vtx_new`"); + } } diff --git a/src/pc/lua/utils/smlua_gfx_utils.h b/src/pc/lua/utils/smlua_gfx_utils.h index cbac3271e..b17407a7e 100644 --- a/src/pc/lua/utils/smlua_gfx_utils.h +++ b/src/pc/lua/utils/smlua_gfx_utils.h @@ -4,6 +4,13 @@ #include "pc/lua/smlua.h" #include "types.h" +#define C0(cmd, pos, width) (((cmd)->words.w0 >> (pos)) & ((1U << width) - 1)) +#define GFX_OP(cmd) C0(cmd, 24, 8) + +Gfx *gfx_allocate_internal(u32 length); +Vtx *vtx_allocate_internal(u32 count); +u32 gfx_get_length_no_sentinel(const Gfx *gfx); + /* |description|Sets the override FOV|descriptionEnd| */ void set_override_fov(f32 fov); /* |description|Sets the override near plane|descriptionEnd| */ @@ -49,14 +56,44 @@ u8 get_skybox_color(u8 index); void set_skybox_color(u8 index, u8 value); /* |description|Traverses a display list. Takes a Lua function as a parameter, which is called back for each command in the display list with the parameters `cmd` (display list pointer), and `op`|descriptionEnd| */ -void gfx_parse(Gfx* cmd, LuaFunction func); -/* |description|Gets a vertex from a display list command if it has the correct op. Intended to be used with `gfx_parse`|descriptionEnd| */ -Vtx *gfx_get_vtx(Gfx* gfx, u16 offset); -/* |description|Gets the number of vertices from a display list command if it has the correct op|descriptionEnd| */ -u16 gfx_get_vtx_count(Gfx* cmd); -/* |description|Sets the display list combine mode. you can fill this function with G_CCMUX_* and G_ACMUX_* constants|descriptionEnd| */ -void gfx_set_combine_lerp(Gfx* gfx, u32 a0, u32 b0, u32 c0, u32 d0, u32 Aa0, u32 Ab0, u32 Ac0, u32 Ad0, u32 a1, u32 b1, u32 c1, u32 d1, u32 Aa1, u32 Ab1, u32 Ac1, u32 Ad1); -/* |description|Sets the display list texture image. Pass in textureInfo.texture as `texture`|descriptionEnd| */ -void gfx_set_texture_image(Gfx* gfx, u32 format, u32 size, u32 width, u8* texture); +void gfx_parse(Gfx *cmd, LuaFunction func); +/* |description|Gets the op of the display list command|descriptionEnd| */ +u32 gfx_get_op(Gfx *cmd); +/* |description|Gets the display list from a display list command if it has the op `G_DL`|descriptionEnd| */ +Gfx *gfx_get_display_list(Gfx *cmd); +/* |description|Gets the vertex buffer from a display list command if it has the op `G_VTX`|descriptionEnd| */ +Vtx *gfx_get_vertex_buffer(Gfx *cmd); +/* |description|Gets the number of vertices from a display list command if it has the op `G_VTX`|descriptionEnd| */ +u16 gfx_get_vertex_count(Gfx *cmd); + +/* |description|Gets the max length of a display list|descriptionEnd| */ +u32 gfx_get_length(Gfx *gfx); +/* |description|Gets a command of a display list at position `offset`|descriptionEnd| */ +Gfx *gfx_get_command(Gfx *gfx, u32 offset); +/* |description|Gets the next command of a given display list pointer. Intended to use in a for loop|descriptionEnd| */ +Gfx *gfx_get_next_command(Gfx *gfx); +/* |description|Copies `length` commands from display list `src` to display list `dest`|descriptionEnd| */ +void gfx_copy(Gfx *dest, Gfx *src, u32 length); +/* |description|Creates a new named display list of `length` commands|descriptionEnd| */ +Gfx *gfx_new(const char *name, u32 length); +/* |description|Reallocates a display list created by `gfx_new` to modify its length|descriptionEnd| */ +Gfx *gfx_realloc(Gfx *gfx, u32 newLength); +/* |description|Deletes a display list created by `gfx_new`|descriptionEnd| */ +void gfx_delete(Gfx *gfx); + +/* |description|Gets the max count of vertices of a vertex buffer|descriptionEnd| */ +u32 vtx_get_count(Vtx *vtx); +/* |description|Gets a vertex of a vertex buffer at position `offset`|descriptionEnd| */ +Vtx *vtx_get_vertex(Vtx *vtx, u32 offset); +/* |description|Gets the next vertex of a given vertex pointer. Intended to use in a for loop|descriptionEnd| */ +Vtx *vtx_get_next_vertex(Vtx *vtx); +/* |description|Copies `count` vertices from vertex buffer `src` to vertex buffer `dest`|descriptionEnd| */ +void vtx_copy(Vtx *dest, Vtx *src, u32 count); +/* |description|Creates a new named vertex buffer of `count` vertices|descriptionEnd| */ +Vtx *vtx_new(const char *name, u32 count); +/* |description|Reallocates a vertex buffer created by `vtx_new` to modify its count|descriptionEnd| */ +Vtx *vtx_realloc(Vtx *vtx, u32 newCount); +/* |description|Deletes a vertex buffer created by `vtx_new`|descriptionEnd| */ +void vtx_delete(Vtx *vtx); #endif diff --git a/src/pc/network/network.c b/src/pc/network/network.c index 422a397a9..ea9de270e 100644 --- a/src/pc/network/network.c +++ b/src/pc/network/network.c @@ -668,7 +668,6 @@ void network_shutdown(bool sendLeaving, bool exiting, bool popup, bool reconnect if (exiting) { return; } dynos_model_clear_pool(MODEL_POOL_SESSION); - dynos_model_restore_vanilla_display_lists(); // reset other stuff extern u8* gOverrideEeprom;