diff --git a/config/GAFE01_00/config.yml b/config/GAFE01_00/config.yml index 76193259..e58fe69a 100644 --- a/config/GAFE01_00/config.yml +++ b/config/GAFE01_00/config.yml @@ -25422,3 +25422,37 @@ modules: binary: assets/act_ball_d_3_tex.bin header: assets/act_ball_d_3_tex.inc header_type: raw + + - symbol: act_ball_s_pal + binary: assets/act_ball_s_pal.bin + header: assets/act_ball_s_pal.inc + header_type: none + custom_type: pal16 + + - symbol: act_ball_s_5_tex + binary: assets/act_ball_s_5_tex.bin + header: assets/act_ball_s_5_tex.inc + header_type: raw + + - symbol: act_ball_s_v + binary: assets/act_ball_s_v.bin + header: assets/act_ball_s_v.inc + header_type: none + custom_type: vtx + + - symbol: act_balloon_wire_tex_txt + binary: assets/act_balloon_wire_tex_txt.bin + header: assets/act_balloon_wire_tex_txt.inc + header_type: raw + + - symbol: act_balloon_head_tex_rgb_ia8 + binary: assets/act_balloon_head_tex_rgb_ia8.bin + header: assets/act_balloon_head_tex_rgb_ia8.inc + header_type: raw + + - symbol: act_balloon_v + binary: assets/act_balloon_v.bin + header: assets/act_balloon_v.inc + header_type: none + custom_type: vtx + diff --git a/config/GAFE01_00/foresta/splits.txt b/config/GAFE01_00/foresta/splits.txt index 1497fd5a..6dff76f9 100644 --- a/config/GAFE01_00/foresta/splits.txt +++ b/config/GAFE01_00/foresta/splits.txt @@ -3684,10 +3684,10 @@ data/model/act_ball_b.c: data/model/act_ball_d.c: .data start:0x0009FFD8 end:0x000A0738 -data/dataobject/dataobject_A0738: +data/model/act_ball_s.c: .data start:0x000A0738 end:0x000A1120 -data/dataobject/dataobject_A1120: +data/model/act_balloon.c: .data start:0x000A1120 end:0x000A1B78 data/npc/model/mdl/bea_1.c: diff --git a/configure.py b/configure.py index 5113d5db..4dc38512 100644 --- a/configure.py +++ b/configure.py @@ -2636,6 +2636,8 @@ config.libs = [ Object(Matching, "data/model/glider.c"), Object(Matching, "data/model/act_ball_b.c"), Object(Matching, "data/model/act_ball_d.c"), + Object(Matching, "data/model/act_ball_s.c"), + Object(Matching, "data/model/act_balloon.c"), ], ), ] diff --git a/src/data/model/act_ball_s.c b/src/data/model/act_ball_s.c new file mode 100644 index 00000000..dcb59f5a --- /dev/null +++ b/src/data/model/act_ball_s.c @@ -0,0 +1,75 @@ +#include "libforest/gbi_extensions.h" +#include "PR/gbi.h" +#include "evw_anime.h" + +u16 act_ball_s_pal[] = { +#include "assets/act_ball_s_pal.inc" +}; + +u8 act_ball_s_5_tex[] = { +#include "assets/act_ball_s_5_tex.inc" +}; + +Vtx act_ball_s_v[] = { +#include "assets/act_ball_s_v.inc" +}; + +Gfx act_ball_s_model[] = { + gsSPTexture(65535, 65535, 0, G_TX_RENDERTILE, G_ON), + gsDPPipeSync(), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_OPA_SURF2), + gsDPSetCombineLERP(TEXEL0, 0, SHADE, 0, 0, 0, 0, TEXEL0, PRIMITIVE, 0, COMBINED, 0, 0, 0, 0, COMBINED), + gsDPSetTextureLUT(G_TT_RGBA16), + gsDPSetTextureImage(G_IM_FMT_RGBA, G_IM_SIZ_16b, 1, act_ball_s_pal), + gsDPTileSync(), + gsDPSetTile(G_IM_FMT_RGBA, G_IM_SIZ_4b, 0, 496, G_TX_LOADTILE, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, + G_TX_NOLOD, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMASK, G_TX_NOLOD), + gsDPLoadSync(), + gsDPLoadTLUTCmd(G_TX_LOADTILE, 15), + gsDPPipeSync(), + gsDPSetTextureImage(G_IM_FMT_CI, G_IM_SIZ_16b, 1, act_ball_s_5_tex), + gsDPSetTile(G_IM_FMT_CI, G_IM_SIZ_16b, 0, 0, G_TX_LOADTILE, 0, G_TX_MIRROR | G_TX_CLAMP, 5, G_TX_NOLOD, + G_TX_MIRROR | G_TX_WRAP, 4, G_TX_NOLOD), + gsDPLoadSync(), + gsDPLoadBlock(G_TX_LOADTILE, 0, 0, 127, 2048), + gsDPPipeSync(), + gsDPSetTile(G_IM_FMT_CI, G_IM_SIZ_4b, 1, 0, G_TX_RENDERTILE, 15, G_TX_MIRROR | G_TX_CLAMP, 5, G_TX_NOLOD, + G_TX_MIRROR | G_TX_WRAP, 4, G_TX_NOLOD), + gsDPSetTileSize(G_TX_RENDERTILE, 0, 0, 60, 124), + gsDPSetPrimColor(0, 128, 255, 255, 255, 255), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_LIGHTING | G_SHADING_SMOOTH), + gsSPVertex(act_ball_s_v, 32, 0), + gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0), + gsSP2Triangles(6, 7, 8, 0, 9, 10, 11, 0), + gsSP2Triangles(12, 13, 14, 0, 15, 16, 2, 0), + gsSP2Triangles(17, 18, 5, 0, 19, 20, 14, 0), + gsSP2Triangles(21, 22, 8, 0, 23, 24, 11, 0), + gsSP2Triangles(25, 26, 27, 0, 25, 27, 28, 0), + gsSP1Triangle(25, 28, 29, 0), + gsSPVertex(&act_ball_s_v[30], 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(0, 3, 4, 0, 5, 6, 7, 0), + gsSP2Triangles(5, 7, 8, 0, 5, 8, 9, 0), + gsSP2Triangles(10, 11, 12, 0, 10, 12, 13, 0), + gsSP2Triangles(10, 13, 14, 0, 15, 16, 17, 0), + gsSP2Triangles(15, 17, 18, 0, 15, 18, 19, 0), + gsSP2Triangles(20, 21, 22, 0, 20, 22, 23, 0), + gsSP2Triangles(20, 23, 24, 0, 25, 26, 27, 0), + gsSP2Triangles(25, 27, 28, 0, 25, 28, 29, 0), + gsSPVertex(&act_ball_s_v[60], 32, 0), + gsSP2Triangles(0, 1, 2, 0, 0, 2, 3, 0), + gsSP2Triangles(0, 3, 4, 0, 5, 6, 7, 0), + gsSP2Triangles(5, 7, 8, 0, 5, 8, 9, 0), + gsSP2Triangles(10, 11, 12, 0, 10, 12, 13, 0), + gsSP2Triangles(10, 13, 14, 0, 15, 16, 17, 0), + gsSP2Triangles(15, 17, 18, 0, 15, 18, 19, 0), + gsSP2Triangles(20, 21, 22, 0, 20, 22, 23, 0), + gsSP2Triangles(20, 23, 24, 0, 25, 26, 27, 0), + gsSP1Triangle(28, 29, 30, 0), + gsSPVertex(&act_ball_s_v[91], 21, 0), + gsSP2Triangles(0, 1, 2, 0, 3, 4, 5, 0), + gsSP2Triangles(6, 7, 8, 0, 0, 9, 10, 0), + gsSP2Triangles(11, 12, 13, 0, 14, 15, 16, 0), + gsSP2Triangles(3, 17, 18, 0, 6, 19, 20, 0), + gsSPEndDisplayList() +}; diff --git a/src/data/model/act_balloon.c b/src/data/model/act_balloon.c new file mode 100644 index 00000000..b0732312 --- /dev/null +++ b/src/data/model/act_balloon.c @@ -0,0 +1,97 @@ +#include "libforest/gbi_extensions.h" +#include "PR/gbi.h" +#include "evw_anime.h" +#include "c_keyframe.h" + +u8 act_balloon_wire_tex_txt[] ATTRIBUTE_ALIGN(32) = { +#include "assets/act_balloon_wire_tex_txt.inc" +}; + +u8 act_balloon_head_tex_rgb_ia8[] ATTRIBUTE_ALIGN(32) = { +#include "assets/act_balloon_head_tex_rgb_ia8.inc" +}; + +Vtx act_balloon_v[] = { +#include "assets/act_balloon_v.inc" +}; + +Gfx act_balloon_head_model[] = { + gsSPTexture(4000, 4000, 0, G_TX_RENDERTILE, G_ON), + gsDPSetCombineLERP(PRIMITIVE, ENVIRONMENT, TEXEL0, ENVIRONMENT, 0, 0, 0, TEXEL0, COMBINED, 0, SHADE, 0, 0, 0, 0, + COMBINED), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_TEX_EDGE2), + gsDPSetTextureImage_Dolphin(G_IM_FMT_IA, G_IM_SIZ_8b, 32, 32, act_balloon_head_tex_rgb_ia8), + gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 0, GX_CLAMP, GX_CLAMP, 1, 1), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_LIGHTING | G_TEXTURE_GEN | G_SHADING_SMOOTH), + gsSPVertex(act_balloon_v, 26, 0), + gsSPNTrianglesInit_5b(36, 0, 1, 2, 1, 3, 2, 3, 4, 2), + gsSPNTriangles_5b(5, 4, 3, 6, 5, 3, 7, 6, 3, 8, 9, 10), + gsSPNTriangles_5b(9, 11, 10, 11, 4, 10, 10, 4, 5, 12, 10, 5), + gsSPNTriangles_5b(13, 12, 5, 14, 15, 11, 15, 16, 11, 16, 4, 11), + gsSPNTriangles_5b(2, 4, 16, 17, 2, 16, 18, 17, 16, 19, 17, 18), + gsSPNTriangles_5b(19, 20, 17, 19, 21, 20, 22, 21, 19, 22, 19, 15), + gsSPNTriangles_5b(22, 15, 14, 23, 12, 13, 23, 24, 12, 23, 21, 24), + gsSPNTriangles_5b(24, 21, 22, 24, 22, 9, 24, 9, 8, 25, 6, 7), + gsSPNTriangles_5b(25, 23, 6, 25, 21, 23, 20, 21, 25, 20, 25, 1), + gsSPNTriangles_5b(20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0), + gsSPEndDisplayList() +}; + +Gfx act_balloon_wireB_model[] = { + gsSPTexture(0, 0, 0, G_TX_RENDERTILE, G_ON), + gsDPSetCombineLERP(PRIMITIVE, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED), + gsDPSetPrimColor(0, 255, 255, 255, 255, 100), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_TEX_EDGE2), + gsSPMatrix(anime_6_txt, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW), + gsDPSetTextureImage_Dolphin(G_IM_FMT_I, G_IM_SIZ_4b, 16, 16, act_balloon_wire_tex_txt), + gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_CULL_BACK | G_FOG | G_LIGHTING | G_SHADING_SMOOTH), + gsSPVertex(&act_balloon_v[26], 4, 0), + gsSPMatrix(anime_6_txt + 0x40, G_MTX_NOPUSH | G_MTX_LOAD | G_MTX_MODELVIEW), + gsDPSetTextureImage_Dolphin(G_IM_FMT_I, G_IM_SIZ_4b, 16, 16, act_balloon_wire_tex_txt), + gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_FOG | G_LIGHTING | G_SHADING_SMOOTH), + gsSPVertex(&act_balloon_v[30], 14, 4), + gsSPNTrianglesInit_5b(4, 0, 1, 4, 1, 6, 5, 2, 3, 7), + gsSPNTriangles_5b(3, 9, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0), + gsSPNTrianglesInit_5b(4, 10, 11, 12, 10, 12, 13, 14, 15, 16), + gsSPNTriangles_5b(14, 16, 17, 0, 0, 0, 0, 0, 0, 0, 0, 0), + gsSPEndDisplayList() +}; + +Gfx act_balloon_wireA_model[] = { + gsSPTexture(0, 0, 0, G_TX_RENDERTILE, G_ON), + gsDPSetCombineLERP(PRIMITIVE, 0, SHADE, 0, TEXEL0, 0, PRIMITIVE, 0, 0, 0, 0, COMBINED, 0, 0, 0, COMBINED), + gsDPSetPrimColor(0, 255, 255, 255, 255, 100), + gsDPSetRenderMode(G_RM_FOG_SHADE_A, G_RM_AA_ZB_TEX_EDGE2), + gsDPSetTextureImage_Dolphin(G_IM_FMT_I, G_IM_SIZ_4b, 16, 16, act_balloon_wire_tex_txt), + gsDPSetTile_Dolphin(G_DOLPHIN_TLUT_DEFAULT_MODE, 0, 15, GX_MIRROR, GX_MIRROR, 0, 0), + gsSPLoadGeometryMode(G_ZBUFFER | G_SHADE | G_FOG | G_LIGHTING | G_SHADING_SMOOTH), + gsSPVertex(&act_balloon_v[44], 8, 0), + gsSPNTrianglesInit_5b(4, 0, 1, 2, 0, 2, 3, 4, 5, 6), + gsSPNTriangles_5b(4, 6, 7, 0, 0, 0, 0, 0, 0, 0, 0, 0), + gsSPEndDisplayList() +}; + +u8 cKF_ckcb_r_act_balloon_tbl[] = { 0, 3, 3, 3 }; + +s16 cKF_kn_act_balloon_tbl[] = { 5, 5, 5, 5, 4, 4 }; + +s16 cKF_c_act_balloon_tbl[] = { 0, 1500, 0, 0, 0, 900, 0, 0, 0 }; + +s16 cKF_ds_act_balloon_tbl[] = { 1, -100, 20, 10, -57, 252, 32, 99, -38, 60, -99, -38, 61, -100, + -20, 1, 100, -20, 10, 57, -252, 32, -99, 38, 60, 99, 38, 61, + 100, 20, 1, 100, -20, 10, 57, -252, 32, -99, 38, 60, 99, 38, + 61, 100, 20, 1, -100, 20, 10, -57, 252, 32, 99, -38, 60, -99, + -38, 61, -100, -20, 1, 24, 130, 14, 47, -54, 43, -49, 37, 61, + 24, 136, 1, -24, -130, 14, -47, 54, 43, 49, -37, 61, -24, -136 }; + +cKF_Animation_R_c cKF_ba_r_act_balloon[] = { { cKF_ckcb_r_act_balloon_tbl, cKF_ds_act_balloon_tbl, + cKF_kn_act_balloon_tbl, cKF_c_act_balloon_tbl, -1, 61 } }; + +cKF_Joint_R_c cKF_je_r_act_balloon_tbl[] = { { NULL, 1, cKF_JOINT_FLAG_DISP_OPA, { 0, 1500, 0 } }, + { act_balloon_wireA_model, 1, cKF_JOINT_FLAG_DISP_OPA, { 0, 0, 0 } }, + { act_balloon_wireB_model, 1, cKF_JOINT_FLAG_DISP_OPA, { 1250, 0, 0 } }, + { act_balloon_head_model, 0, cKF_JOINT_FLAG_DISP_OPA, { 1250, 0, 0 } } }; + +cKF_Skeleton_R_c cKF_bs_r_act_balloon[] = { { ARRAY_COUNT(cKF_je_r_act_balloon_tbl), 3, cKF_je_r_act_balloon_tbl } }; diff --git a/tools/converters/assetdis.py b/tools/converters/assetdis.py index d4ea8193..461f12b8 100644 --- a/tools/converters/assetdis.py +++ b/tools/converters/assetdis.py @@ -5,15 +5,15 @@ import struct @dataclass -class EVW_REF: +class struct_ref: symbol_name: str symbol_type: str @dataclass -class EVW_ANIME_result: +class struct_parse_result: formatted_str: str - referenced_objects: list[EVW_REF] + referenced_objects: list[struct_ref] def anim_type_conv(anim_type: int): @@ -27,117 +27,202 @@ def anim_type_conv(anim_type: int): }.get(anim_type, str(anim_type)) -def parse_evw_anime_data(buff: bytes, symbols: list[str]) -> EVW_ANIME_result: - BUFF_SIZE = 8 +def parse_bin_formatted(buff: bytes, in_format: list[tuple[str, str]], _symbols: dict[int, str], val_conv: callable = None, type_conv: callable = None): + struct_format = ">" + symbols_offsets = {} + symbol_order = [] + reloc_symbols = set() + + for format_pair in in_format: + if format_pair == None: + struct_format += "x" + continue + + this_offset = struct.calcsize(struct_format) + struct_type, name = format_pair + + if struct_type == "p": + reloc_symbols.add(name) + struct_type = "xxxx" + + struct_format += struct_type + symbols_offsets[name] = this_offset + symbol_order.append(name) + + BUFF_SIZE = struct.calcsize(struct_format) assert ((len(buff) % BUFF_SIZE) == 0) found_syms = [] - out_data = "" + out_c_data = [] i = 0 - while True: + for i in range(0, len(buff), BUFF_SIZE): b = buff[i:i+BUFF_SIZE] - i += BUFF_SIZE if len(b) < BUFF_SIZE: break - (segment, anim_type) = struct.unpack(">bxhxxxx", b) - anim_type = anim_type_conv(anim_type) - this_symbol_name = symbols.pop(0) - vals = (segment, anim_type, this_symbol_name) - out_data += f"\t{{ {', '.join([str(x) for x in vals])} }},\n" - found_syms.append(EVW_REF(this_symbol_name, anim_type)) - return EVW_ANIME_result(out_data, found_syms) + extracted_data: list[int] = list(struct.unpack(struct_format, b)) + + collapsed_data = {} + + for this_symbol_name in symbol_order: + if this_symbol_name in reloc_symbols: + ref_name = _symbols.get( + i + symbols_offsets[this_symbol_name], "NULL") + + collapsed_data[this_symbol_name] = ref_name + else: + collapsed_data[this_symbol_name] = extracted_data.pop(0) + + new_converted_vals = {} + + if val_conv: + for name, val in collapsed_data.items(): + new_val = val_conv(name, val, dict(collapsed_data)) + if new_val != None: + new_converted_vals[name] = new_val + + collapsed_data.update(new_converted_vals) + + if type_conv: + for name, value in collapsed_data.items(): + new_type = type_conv(name, dict(collapsed_data)) + if new_type != None: + found_syms.append(struct_ref(value, new_type)) + + vals = collapsed_data.values() + out_c_data.append(f"\t{{ {', '.join([str(x) for x in vals])} }}") + + return struct_parse_result(",\n".join(out_c_data), found_syms) -def parse_evw_anime_col_prim(buff: bytes, symbols: list[str]): - BUFF_SIZE = 5 - assert ((len(buff) % BUFF_SIZE) == 0) - out_data = "" - i = 0 - while True: - b = buff[i:i+BUFF_SIZE] - i += BUFF_SIZE - if len(b) < BUFF_SIZE: - break - vals = struct.unpack(">BBBBB", b) - out_data += f"\t{{ {', '.join([str(x) for x in vals])} }},\n" - return EVW_ANIME_result(out_data, []) +def parse_evw_anime_data(buff: bytes, symbols) -> struct_parse_result: + this_format = [("b", "segment"), None, ("h", "anim_type"), + ("p", "this_symbol_name")] + + def vcf(name, value, all_values): + if name == "anim_type": + return anim_type_conv(value) + + def tcf(name, all_values): + if name == "this_symbol_name": + return all_values["anim_type"] + + return parse_bin_formatted(buff, this_format, symbols, vcf, tcf) + + +def parse_evw_anime_col_prim(buff: bytes, symbols): + this_format = [("B", "r"), ("B", "g"), ("B", "b"), ("B", "a"), ("B", "l")] + return parse_bin_formatted(buff, this_format, symbols) def parse_evw_anime_col_env(buff: bytes, symbols: list[str]): - BUFF_SIZE = 4 - assert ((len(buff) % BUFF_SIZE) == 0) - out_data = "" - i = 0 - while True: - b = buff[i:i+BUFF_SIZE] - i += BUFF_SIZE - if len(b) < BUFF_SIZE: - break - vals = struct.unpack(">BBBB", b) - out_data += f"\t{{ {', '.join([str(x) for x in vals])} }},\n" - return EVW_ANIME_result(out_data, []) + this_format = [("B", "r"), ("B", "g"), ("B", "b"), ("B", "a")] + return parse_bin_formatted(buff, this_format, symbols) def parse_evw_anime_colreg(buff: bytes, symbols: list[str]): - BUFF_SIZE = 0x10 - assert ((len(buff) % BUFF_SIZE) == 0) - found_syms = [] - out_data = "" - i = 0 - while True: - b = buff[i:i+BUFF_SIZE] - i += BUFF_SIZE - if len(b) < BUFF_SIZE: - break - (frame_count, key_count) = struct.unpack(">HHxxxxxxxxxxxx", b) - prim_colors = symbols.pop(0) - env_colors = symbols.pop(0) - keyframes = symbols.pop(0) - vals = (frame_count, key_count, prim_colors, env_colors, keyframes) - out_data += f"\t{{ {', '.join([str(x) for x in vals])} }},\n" - found_syms.append(EVW_REF(prim_colors, "EVW_ANIME_COL_PRIM")) - found_syms.append(EVW_REF(env_colors, "EVW_ANIME_COL_ENV")) - found_syms.append(EVW_REF(keyframes, "u16")) - return EVW_ANIME_result(out_data, found_syms) + this_format = [("H", "prim_colors"), ("H", "key_count"), + ("p", "prim_colors"), ("p", "env_colors"), ("p", "keyframes")] + + def tcf(name, symbols): + return { + "prim_colors": "EVW_ANIME_COL_PRIM", + "env_colors": "EVW_ANIME_COL_ENV", + "keyframes": "u16", + }.get(name, None) + return parse_bin_formatted(buff, this_format, symbols, type_conv=tcf) def parse_evw_anime_scroll(buff: bytes, symbols: list[str]): - BUFF_SIZE = 4 - assert ((len(buff) % BUFF_SIZE) == 0) - found_syms = [] - out_data = "" - i = 0 - while True: - b = buff[i:i+BUFF_SIZE] - i += BUFF_SIZE - if len(b) < BUFF_SIZE: - break - vals = struct.unpack(">bbBB", b) - out_data += f"\t{{ {', '.join([str(x) for x in vals])} }},\n" - return EVW_ANIME_result(out_data, found_syms) + this_format = [("b", "x"), ("b", "y"), ("B", "width"), ("B", "height")] + return parse_bin_formatted(buff, this_format, symbols) def parse_evw_texanime(buff: bytes, symbols: list[str]): - BUFF_SIZE = 0x10 - assert ((len(buff) % BUFF_SIZE) == 0) - found_syms = [] - out_data = "" - i = 0 - while True: - b = buff[i:i+BUFF_SIZE] - i += BUFF_SIZE - if len(b) < BUFF_SIZE: - break - (frame_count, key_count) = struct.unpack(">HHxxxxxxxxxxxx", b) - texture_tbl = symbols.pop(0) - animation_pattern = symbols.pop(0) - keyframes = symbols.pop(0) - vals = (frame_count, key_count, texture_tbl, - animation_pattern, keyframes) - out_data += f"\t{{ {', '.join([str(x) for x in vals])} }},\n" - found_syms.append(EVW_REF(texture_tbl, "VOID*_LIST")) - found_syms.append(EVW_REF(animation_pattern, "u8")) - found_syms.append(EVW_REF(keyframes, "u16")) - return EVW_ANIME_result(out_data, found_syms) + this_format = [("H", "frame_count"), ("H", "key_count"), ("p", + "texture_tbl"), ("p", "animation_pattern"), ("p", "keyframes")] + + def tcf(name, symbols): + return { + "texture_tbl": "VOID*_LIST", + "animation_pattern": "u8", + "keyframes": "u16", + }.get(name, None) + return parse_bin_formatted(buff, this_format, symbols, type_conv=tcf) + + +def parse_cKF_Skeleton_R_c(buff: bytes, symbols: list[str]): + this_format = [("B", "num_joints"), ("B", "num_shown_joints"), + None, None, ("p", "joint_table")] + + def tcf(name, symbols): + return { + "joint_table": "cKF_Joint_R_c", + }.get(name, None) + + def vcf(name, value, symbols): + if name == "num_joints": + return f"ARRAY_COUNT({symbols["joint_table"]})" + + return parse_bin_formatted(buff, this_format, symbols, vcf, tcf) + + +def parse_cKF_Animation_R_c(buff: bytes, symbols: list[str]): + this_format = [("p", "flag_table"), ("p", "data_table"), + ("p", "key_table"), ("p", "fixed_table"), ("h", "pad"), ("h", "frames")] + + def tcf(name, symbols): + return { + "flag_table": "u8", + "data_table": "s16", + "key_table": "s16", + "fixed_table": "s16", + }.get(name, None) + + def vcf(name, value, symbols): + if name == "x": + return f"{{ {value}" + if name == "z": + return f"{value} }}" + return parse_bin_formatted(buff, this_format, symbols, vcf, tcf) + + +def parse_cKF_Joint_R_c(buff: bytes, symbols: list[str]): + this_format = [("p", "model"), ("B", "child"), + ("B", "flags"), ("H", "x"), ("H", "y"), ("H", "z")] + + def tcf(name, symbols): + return { + "joint_table": "Gfx", + }.get(name, None) + + def vcf(name, value, symbols): + if name == "x": + return f"{{ {value}" + if name == "z": + return f"{value} }}" + if name == "flags": + return { + 0: "cKF_JOINT_FLAG_DISP_OPA", + 1: "cKF_JOINT_FLAG_DISP_XLU" + }.get(value, None) + return parse_bin_formatted(buff, this_format, symbols, vcf, tcf) + + +def parse_u16(buff: bytes, symbols: list[str]): + vals = struct.unpack(">" + "H" * (len(buff) // 2), buff) + out_str = ",\n".join(str(x) for x in vals) + return struct_parse_result(out_str, []) + + +def parse_s16(buff: bytes, symbols: list[str]): + vals = struct.unpack(">" + "h" * (len(buff) // 2), buff) + out_str = ",\n".join(str(x) for x in vals) + return struct_parse_result(out_str, []) + + +def parse_u8(buff: bytes, symbols: list[str]): + vals = struct.unpack(">" + "B" * len(buff), buff) + out_str = ",\n".join(str(x) for x in vals) + return struct_parse_result(out_str, []) def lookup_bins_and_symbols(lines: list[str], name: str): @@ -162,7 +247,42 @@ def lookup_bins_and_symbols(lines: list[str], name: str): out_symbols.append(data) elif ".rel" in line: out_bin.extend(b'\0\0\0\0') - out_symbols.append(f"&{line.split(".rel ")[1].split(",")[0]}[xxx]") + out_symbols.append(f"&{line.split(".rel ")[1].split(",")[0]}[0]") + return out_bin, out_symbols + + +def lookup_bins_and_symbols2(lines: list[str], name: str): + out_bin = bytearray() + out_symbols = {} + begin_ind = 0 + end_ind = 0 + for i, line in enumerate(lines): + if line.startswith(f".obj {name}"): + begin_ind = i + if line.startswith(f".endobj {name}"): + end_ind = i + data_lines = lines[begin_ind+1:end_ind] + offset_count = 0 + for line in data_lines: + if ".4byte" in line: + data = line.split(".4byte ")[1] + try: + out_bin.extend(int(data, 16).to_bytes(4, 'big')) + except Exception as e: + out_bin.extend(b'\0\0\0\0') + out_symbols[offset_count] = data + offset_count += 4 + elif ".2byte" in line: + data = line.split(".2byte ")[1] + out_bin.extend(int(data, 16).to_bytes(2, 'big')) + offset_count += 4 + elif ".rel" in line: + out_bin.extend(b'\0\0\0\0') + data = f"&{line.split(".rel ")[1].split(",")[0]}[xxx]" + out_symbols[offset_count] = data + offset_count += 4 + else: + assert (False), line return out_bin, out_symbols @@ -170,7 +290,8 @@ def convert_source_to_gfx_c_source(src_file, dest_path): with open(src_file) as f: lines = f.read().split("\n") - includes = ["libforest/gbi_extensions.h", "PR/gbi.h", "evw_anime.h"] + includes = ["libforest/gbi_extensions.h", + "PR/gbi.h", "evw_anime.h", "c_keyframe.h"] header = "\n".join([f'#include "{x}"' for x in includes]) + "\n" @@ -192,12 +313,33 @@ def convert_source_to_gfx_c_source(src_file, dest_path): found_types.append((this_obj, "PAL")) elif this_obj.endswith("_tex"): found_types.append((this_obj, "TEX")) + elif this_obj.startswith("cKF_bs_r"): + found_types.append((this_obj, "cKF_Skeleton_R_c")) + elif this_obj.startswith("cKF_ba_r"): + found_types.append((this_obj, "cKF_Animation_R_c")) # we now have a list of all objects, and we have a partial mapping of what type they could have # what we want to do is go through all the objects we know, and get the out-data # there are some objs that will add to this list, we can queue them onto the list converted_types = {} + lookup_table = { + "EVW_ANIME_DATA": parse_evw_anime_data, + "EVW_ANIME_TYPE_SCROLL1": parse_evw_anime_scroll, + "EVW_ANIME_TYPE_SCROLL2": parse_evw_anime_scroll, + "EVW_ANIME_TYPE_COLREG_MANUAL": parse_evw_anime_colreg, + "EVW_ANIME_TYPE_COLREG_LINEAR": parse_evw_anime_colreg, + "EVW_ANIME_TYPE_COLREG_NONLINEAR": parse_evw_anime_colreg, + "EVW_ANIME_TYPE_TEXANIME": parse_evw_texanime, + "EVW_ANIME_COL_PRIM": parse_evw_anime_col_prim, + "EVW_ANIME_COL_ENV": parse_evw_anime_col_env, + "cKF_Skeleton_R_c": parse_cKF_Skeleton_R_c, + "cKF_Joint_R_c": parse_cKF_Joint_R_c, + "cKF_Animation_R_c": parse_cKF_Animation_R_c, + "u8": parse_u8, + "u16": parse_u16, + "s16": parse_s16, + } # we now have a list of objects+type while len(found_types) > 0: obj_name, type = found_types.pop() @@ -212,84 +354,24 @@ def convert_source_to_gfx_c_source(src_file, dest_path): converted_types[obj_name] = (type, data, "") elif type == "PAL": data = f'#include "assets/{obj_name}.inc"' - converted_types[obj_name] = ("u16", data, "ATTRIBUTE_ALIGN(32)") + converted_types[obj_name] = ("u16", data, "") elif type == "TEX": data = f'#include "assets/{obj_name}.inc"' - converted_types[obj_name] = ("u8", data, "ATTRIBUTE_ALIGN(32)") - elif type == "EVW_ANIME_DATA": - res = parse_evw_anime_data( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) + converted_types[obj_name] = ("u8", data, "") - elif type in ["EVW_ANIME_TYPE_SCROLL1", "EVW_ANIME_TYPE_SCROLL2"]: - res = parse_evw_anime_scroll( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = ("EVW_ANIME_SCROLL", data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "EVW_ANIME_TYPE_COLREG_MANUAL": - res = parse_evw_anime_colreg( - *lookup_bins_and_symbols(lines, obj_name)) + elif type in lookup_table: + res: struct_parse_result = lookup_table[type]( + *lookup_bins_and_symbols2(lines, obj_name)) data = res.formatted_str converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "EVW_ANIME_TYPE_COLREG_LINEAR": - res = parse_evw_anime_colreg( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "EVW_ANIME_TYPE_COLREG_NONLINEAR": - res = parse_evw_anime_colreg( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "EVW_ANIME_TYPE_TEXANIME": - res = parse_evw_texanime( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "EVW_ANIME_COL_PRIM": - res = parse_evw_anime_col_prim( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "EVW_ANIME_COL_ENV": - res = parse_evw_anime_col_env( - *lookup_bins_and_symbols(lines, obj_name)) - data = res.formatted_str - converted_types[obj_name] = (type, data, "") - for ref in res.referenced_objects: - found_types.insert( - 0, (ref.symbol_name, ref.symbol_type)) - elif type == "u16": - assert (False) - elif type == "u8": - assert (False) + if len(res.referenced_objects) > 0: + found_types = [(ref.symbol_name, ref.symbol_type) + for ref in res.referenced_objects] + found_types out = header + "\n\n" for obj in all_objs: this_type, out_data, align = converted_types.get( - obj, (None, None, None)) + obj, ("u8", f'#include "assets/{obj}.inc"', "")) out += f"{this_type} {obj}[] {align}= {{ \n{out_data}\n}};\n\n" # print(out) with open(dest_path, "w") as f: diff --git a/tools/converters/gfxdis.py b/tools/converters/gfxdis.py index 05255d2f..02983ce3 100644 --- a/tools/converters/gfxdis.py +++ b/tools/converters/gfxdis.py @@ -1633,6 +1633,17 @@ def gfx_gsDPSetTileSize(data): ) +def gfx_gsSp1Triangle(data): + def _C(v): + return str(v//2) + return gf_call("gsSP1Triangle", data, + B2A(16, 8, DU, _C), + B2A(8, 8, DU, _C), + B2A(0, 8, DU, _C), + B2A(0, 1, DU, lambda _: "0") + ) + + def gfx_gsDPSetTile_Dolphin(data): return gf_call("gsDPSetTile_Dolphin", data, B2A(20, 4, DU, strarg_dolphintile), B2A(16, 3, DU), B2A(12, 4, DU), B2A(10, 2, DU, strarg_texwrap), B2A(8, 2, DU, strarg_texwrap), B2A(4, 4, DU), B2A(4, 4, DU)) @@ -1687,6 +1698,7 @@ extended_func = None def gfx_gsSPNTrianglesInit(data): + global triangle_count, extended_func assert (extract_data_lower(data, 0, 1) == 0) # if extract_data_lower(data, 0, 1) == 0: # count = extract_data_upper(data, 17, 7) + 1 @@ -1765,6 +1777,7 @@ GFX_LOOKUP = { G_SETTILE: gfx_gsDPSetTile, G_LOADBLOCK: gfx_gsDPLoadBlock, G_SETTILESIZE: gfx_gsDPSetTileSize, + G_TRI1: gfx_gsSp1Triangle, }