diff --git a/include/d/actor/d_a_npc_maro.h b/include/d/actor/d_a_npc_maro.h index 0883942344c..367d1929f8f 100644 --- a/include/d/actor/d_a_npc_maro.h +++ b/include/d/actor/d_a_npc_maro.h @@ -179,52 +179,16 @@ private: STATIC_ASSERT(sizeof(daNpc_Maro_c) == 0x1140); +struct daNpc_Maro_HIOParam { + /* 0x00 */ daNpcT_HIOParam common; + /* 0x8C */ u32 field_0x8c; +}; + class daNpc_Maro_Param_c { public: /* 805649B0 */ virtual ~daNpc_Maro_Param_c() {} - struct Data { - /* 0x00 */ f32 field_0x00; - /* 0x04 */ f32 field_0x04; - /* 0x08 */ f32 field_0x08; - /* 0x0C */ f32 field_0x0c; - /* 0x10 */ f32 field_0x10; - /* 0x14 */ f32 field_0x14; - /* 0x18 */ f32 field_0x18; - /* 0x1C */ f32 field_0x1c; - /* 0x20 */ f32 field_0x20; - /* 0x24 */ f32 field_0x24; - /* 0x28 */ f32 field_0x28; - /* 0x2C */ f32 field_0x2c; - /* 0x30 */ f32 field_0x30; - /* 0x34 */ f32 field_0x34; - /* 0x38 */ f32 field_0x38; - /* 0x3C */ f32 field_0x3c; - /* 0x40 */ f32 field_0x40; - /* 0x44 */ f32 field_0x44; - /* 0x48 */ s16 field_0x48; - /* 0x4A */ s16 field_0x4a; - /* 0x4C */ s16 field_0x4c; - /* 0x4E */ s16 field_0x4e; - /* 0x50 */ f32 field_0x50; - /* 0x54 */ u32 field_0x54; - /* 0x58 */ u32 field_0x58; - /* 0x5C */ u32 field_0x5c; - /* 0x60 */ u32 field_0x60; - /* 0x64 */ u32 field_0x64; - /* 0x68 */ u32 field_0x68; - /* 0x6C */ f32 field_0x6c; - /* 0x70 */ f32 field_0x70; - /* 0x74 */ f32 field_0x74; - /* 0x78 */ f32 field_0x78; - /* 0x7C */ f32 field_0x7c; - /* 0x80 */ f32 field_0x80; - /* 0x84 */ f32 field_0x84; - /* 0x88 */ f32 field_0x88; - /* 0x8C */ u32 field_0x8c; - }; - - static const Data m; + static const daNpc_Maro_HIOParam m; }; diff --git a/src/d/actor/d_a_npc_maro.cpp b/src/d/actor/d_a_npc_maro.cpp index 86ea08076d6..3ac47991227 100644 --- a/src/d/actor/d_a_npc_maro.cpp +++ b/src/d/actor/d_a_npc_maro.cpp @@ -187,34 +187,40 @@ daNpc_Maro_c::~daNpc_Maro_c() { /* ############################################################################################## */ /* 80564BAC-80564C3C 000000 0090+00 15/15 0/0 0/0 .rodata m__18daNpc_Maro_Param_c */ -daNpc_Maro_Param_c::Data const daNpc_Maro_Param_c::m = { +const daNpc_Maro_HIOParam daNpc_Maro_Param_c::m = { 100.0f, -3.0f, 1.0f, 400.0f, - /* 0x10 */ 255.0f, + 255.0f, 80.0f, 35.0f, 30.0f, - /* 0x20 */ 0.0f, + 0.0f, 0.0f, 10.0f, -10.0f, - /* 0x30 */ 30.0f, + 30.0f, -10.0f, 30.0f, -30.0f, - /* 0x40 */ 0.6f, + 0.6f, 12.0f, - 3, 6, - 5, 6, + 3, + 6, + 5, + 6, 110.0f, - 0x00000000, - 0x00000000, - 0x00000000, - 0x003C0008, - 0x00000000, - 0x00000000, + 0.0f, + 0.0f, + 0.0f, + 60, + 8, + 0, + 0, + 0, + 0, + 0, 4.0f, -15.0f, 0.0f, @@ -264,7 +270,7 @@ int daNpc_Maro_c::create() { mAcch.Set(fopAcM_GetPosition_p(this), fopAcM_GetOldPosition_p(this), this, 1, &mAcchCir, fopAcM_GetSpeed_p(this), fopAcM_GetAngle_p(this), fopAcM_GetShapeAngle_p(this)); - mCcStts.Init(daNpc_Maro_Param_c::m.field_0x10, 0, this); + mCcStts.Init(daNpc_Maro_Param_c::m.common.weight, 0, this); mCyl1.Set(mCcDCyl); mCyl1.SetStts(&mCcStts); mCyl1.SetTgHitCallback(tgHitCallBack); @@ -634,10 +640,10 @@ void daNpc_Maro_c::setParam() { srchActors(); u32 uVar7 = 10; - s16 sVar10 = daNpc_Maro_Param_c::m.field_0x48; - s16 sVar9 = daNpc_Maro_Param_c::m.field_0x4a; - s16 sVar8 = daNpc_Maro_Param_c::m.field_0x4c; - s16 sVar7 = daNpc_Maro_Param_c::m.field_0x4e; + s16 sVar10 = daNpc_Maro_Param_c::m.common.talk_distance; + s16 sVar9 = daNpc_Maro_Param_c::m.common.talk_angle; + s16 sVar8 = daNpc_Maro_Param_c::m.common.attention_distance; + s16 sVar7 = daNpc_Maro_Param_c::m.common.attention_angle; if (&daNpc_Maro_c::swdTutorial == field_0x110c) { sVar10 = 11; sVar9 = 6; @@ -677,18 +683,18 @@ void daNpc_Maro_c::setParam() { attention_info.distances[3] = daNpcT_getDistTableIdx(sVar10, sVar9); attention_info.flags = uVar7; - scale.set(daNpc_Maro_Param_c::m.field_0x08, daNpc_Maro_Param_c::m.field_0x08, - daNpc_Maro_Param_c::m.field_0x08); - mCcStts.SetWeight(daNpc_Maro_Param_c::m.field_0x10); - mCylH = daNpc_Maro_Param_c::m.field_0x14; - mWallR = daNpc_Maro_Param_c::m.field_0x1c; - mAttnFovY = daNpc_Maro_Param_c::m.field_0x50; + scale.set(daNpc_Maro_Param_c::m.common.scale, daNpc_Maro_Param_c::m.common.scale, + daNpc_Maro_Param_c::m.common.scale); + mCcStts.SetWeight(daNpc_Maro_Param_c::m.common.weight); + mCylH = daNpc_Maro_Param_c::m.common.height; + mWallR = daNpc_Maro_Param_c::m.common.width; + mAttnFovY = daNpc_Maro_Param_c::m.common.fov; mAcchCir.SetWallR(mWallR); - mAcchCir.SetWallH(daNpc_Maro_Param_c::m.field_0x18); - field_0xde8 = daNpc_Maro_Param_c::m.field_0x0c; - field_0xa80 = daNpc_Maro_Param_c::m.field_0x6c; - mMorfFrames = daNpc_Maro_Param_c::m.field_0x44; - gravity = daNpc_Maro_Param_c::m.field_0x04; + mAcchCir.SetWallH(daNpc_Maro_Param_c::m.common.knee_length); + field_0xde8 = daNpc_Maro_Param_c::m.common.real_shadow_size; + field_0xa80 = daNpc_Maro_Param_c::m.common.expression_morf_frame; + mMorfFrames = daNpc_Maro_Param_c::m.common.morf_frame; + gravity = daNpc_Maro_Param_c::m.common.gravity; } /* 8055CB14-8055CC9C 001674 0188+00 1/0 0/0 0/0 .text checkChangeEvt__12daNpc_Maro_cFv */ @@ -1015,11 +1021,11 @@ void daNpc_Maro_c::setAttnPos() { f32 dVar8 = cM_s2rad(mCurAngle.y - field_0xd7e.y); mJntAnm.setParam( this, mpMorf[0]->getModel(), &eyeOffset, getBackboneJointNo(), getNeckJointNo(), - getHeadJointNo(), daNpc_Maro_Param_c::m.field_0x24, daNpc_Maro_Param_c::m.field_0x20, - daNpc_Maro_Param_c::m.field_0x2c, daNpc_Maro_Param_c::m.field_0x28, - daNpc_Maro_Param_c::m.field_0x34, daNpc_Maro_Param_c::m.field_0x30, - daNpc_Maro_Param_c::m.field_0x3c, daNpc_Maro_Param_c::m.field_0x38, - daNpc_Maro_Param_c::m.field_0x40, 0.0f, NULL); + getHeadJointNo(), daNpc_Maro_Param_c::m.common.body_angleX_min, daNpc_Maro_Param_c::m.common.body_angleX_max, + daNpc_Maro_Param_c::m.common.body_angleY_min, daNpc_Maro_Param_c::m.common.body_angleY_max, + daNpc_Maro_Param_c::m.common.head_angleX_min, daNpc_Maro_Param_c::m.common.head_angleX_max, + daNpc_Maro_Param_c::m.common.head_angleY_min, daNpc_Maro_Param_c::m.common.head_angleY_max, + daNpc_Maro_Param_c::m.common.neck_rotation_ratio, 0.0f, NULL); mJntAnm.calcJntRad(0.2f, 1.0f, (float)dVar8); setMtx(); mDoMtx_stack_c::copy(mpMorf[0]->getModel()->getAnmMtx(getHeadJointNo())); @@ -1027,7 +1033,7 @@ void daNpc_Maro_c::setAttnPos() { mJntAnm.setEyeAngleX(eyePos, 1.0f, 0); mJntAnm.setEyeAngleY(eyePos, mCurAngle.y, 0, 1.0f, 0); eyeOffset.set(0.0f, 0.0f, 0.0f); - eyeOffset.y = daNpc_Maro_Param_c::m.field_0x00; + eyeOffset.y = daNpc_Maro_Param_c::m.common.attention_offset; mDoMtx_stack_c::YrotS(mCurAngle.y); mDoMtx_stack_c::multVec(&eyeOffset, &eyeOffset); attention_info.position = current.pos + eyeOffset; @@ -2936,10 +2942,10 @@ int daNpc_Maro_c::wait(void* param_0) { actor_p = (daNpc_Len_c*)mActorMngr[8].getActorP(); if (actor_p != NULL && ((daNpc_Len_c*) actor_p)->checkStartDemo13StbEvt( - this, daNpc_Maro_Param_c::m.field_0x70, daNpc_Maro_Param_c::m.field_0x74, - daNpc_Maro_Param_c::m.field_0x78, daNpc_Maro_Param_c::m.field_0x7c, - daNpc_Maro_Param_c::m.field_0x80, daNpc_Maro_Param_c::m.field_0x84, - daNpc_Maro_Param_c::m.field_0x88)) + this, daNpc_Maro_Param_c::m.common.box_min_x, daNpc_Maro_Param_c::m.common.box_min_y, + daNpc_Maro_Param_c::m.common.box_min_z, daNpc_Maro_Param_c::m.common.box_max_x, + daNpc_Maro_Param_c::m.common.box_max_y, daNpc_Maro_Param_c::m.common.box_max_z, + daNpc_Maro_Param_c::m.common.box_offset)) { mEvtNo = 7; field_0x1133 = 1; diff --git a/tools/utilities/beautify_anm_data.py b/tools/utilities/beautify_anm_data.py index 63c5f2d044f..2f22f618ab9 100644 --- a/tools/utilities/beautify_anm_data.py +++ b/tools/utilities/beautify_anm_data.py @@ -5,6 +5,7 @@ # Used for decompiling d_a_npc_ETC TUs. # +import fire import os import re import sys @@ -30,6 +31,11 @@ PARAM_TYPE = "::m" PARAM_PATTERN = r'SECTION_RODATA u8 const (\w+_Param_c)::m\[\d+\] = {' +def unsigned_val(hexstr): + value = int(hexstr, 16) + return value + + def twos_complement(hexstr, bits): # https://stackoverflow.com/questions/6727875/hex-string-to-signed-int-in-python value = int(hexstr, 16) @@ -61,10 +67,156 @@ def hex_to_float(hex_str): def float_to_hex(f): [d] = struct.unpack(">I", struct.pack(">f", f)) - return f"0x{d:X}" + return f"{d:08X}" -def build_anm_struct(byte_collection, anm_type, param_name): +def handle_npc_param(byte_collection, param_name, type): + my_len = len(byte_collection) + if my_len % 4 != 0: + print(f"Error: len() = '{my_len}' isn't divisble by 4") + sys.exit(1) + + # Special handling. + instr_arr = [] + common_name = "" + if type is None: + print("ERROR: --type must be specified") + sys.exit(1) + elif type == "daNpcT": + common_name = "daNpcT_HIOParam" + instr_arr = [ + "f4", # attention_offset; + "f4", # gravity; + "f4", # scale; + "f4", # real_shadow_size; + "f4", # weight; + "f4", # height; + "f4", # knee_length; + "f4", # width; + "f4", # body_angleX_max; + "f4", # body_angleX_min; + "f4", # body_angleY_max; + "f4", # body_angleY_min; + "f4", # head_angleX_max; + "f4", # head_angleX_min; + "f4", # head_angleY_max; + "f4", # head_angleY_min; + "f4", # neck_rotation_ratio; + "f4", # morf_frame; + "s2", # talk_distance; + "s2", # talk_angle; + "s2", # attention_distance; + "s2", # attention_angle; + "f4", # fov; + "f4", # search_distance; + "f4", # search_height; + "f4", # search_depth; + "s2", # attention_time; + "s2", # damage_time; + "s2", # face_expression; + "s2", # motion; + "s2", # look_mode; + "u1", # debug_mode_ON; + "u1", # debug_info_ON; + "f4", # expression_morf_frame; + "f4", # box_min_x; + "f4", # box_min_y; + "f4", # box_min_z; + "f4", # box_max_x; + "f4", # box_max_y; + "f4", # box_max_z; + "f4", # box_offset; + ] + elif type == "daNpcF": + # TODO + print("ERROR: --type daNpcF is currently unsupported.") + print(" You can try to implement it yourself.") + print(" If you need help with this, please seek the help of yunatasavior on Discord.") + sys.exit(1) + else: + print(f"ERROR: --type {type} is unsupported. Please review the script to see which are supported.") + sys.exit(1) + + ptr = 0 + cur_instr = 0 + hexstr = "" + res_array = [] + common_size = 0 + while ptr < my_len: + curbyte = byte_collection[ptr] + ptr += 1 + if curbyte[:2] != "0x" or len(curbyte) != 4: + print(f"Error: '{curbyte}' isn't formatted as a byte") + sys.exit(1) + + hexstr += curbyte[-2:] + my_type = "h" + exp_bytes = 4 + if cur_instr < len(instr_arr): + my_type = instr_arr[cur_instr][0] + exp_bytes = int(instr_arr[cur_instr][1]) + + if len(hexstr) / 2 == exp_bytes: + if my_type == 'u': + val = unsigned_val(hexstr) + res_array.append(val) + elif my_type == 's': + val = twos_complement(hexstr, exp_bytes*8) + res_array.append(val) + elif my_type == 'h': + res_array.append("0x" + hexstr) + elif my_type == 'f': + fvalue = hex_to_float(hexstr) + fvalue = round(fvalue, 6) + chk_val = float_to_hex(fvalue) + assert chk_val == hexstr, f"fvalue({fvalue}): chk_val {chk_val} != hexstr {hexstr}" + res_array.append(fvalue) + else: + print(f"Error: unknown type '{my_type}'") + sys.exit(1) + + hexstr = "" + if common_size == 0: + cur_instr += 1 + + if cur_instr == len(instr_arr): + if common_size == 0: + common_size = ptr + + assert common_size != 0, "Param array is too short for specified type" + hio_name = re.sub(r'_Param_c$', '_HIOParam', param_name) + res_str = "// Must be put OUTSIDE {}:\n".format(param_name) + res_str += "struct {} {{\n".format(hio_name) + idx = common_size + res_str += " /* 0x00 */ {} common;\n".format(common_name) + while idx < my_len: + upper = f'{idx:02X}' + lower = f'{idx:02x}' + res_str += " /* 0x{} */ u32 field_0x{};\n".format(upper, lower) + idx += 4 + + res_str += "};\n\n" + res_str += "// Must be put INSIDE {}:\n".format(param_name) + res_str += "static const {} m;\n\n".format(hio_name) + res_str += "const {} {}::m".format(hio_name, param_name) + + res_str += " = {\n" + for value in res_array: + res_str += " " + + if isinstance(value, int): + res_str += str(value) + elif isinstance(value, float): + res_str += str(value) + "f" + else: + res_str += value + res_str += ",\n" + + res_str += "};\n" + print(res_str) + + +def build_anm_struct(byte_collection, anm_type): my_len = len(byte_collection) piece_size = 1 instr_arr = [] @@ -103,7 +255,6 @@ def build_anm_struct(byte_collection, anm_type, param_name): hexstr = "" full_res_arr = [] pos_arr = [] - prms_is_float: list[bool] = [] while ptr < my_len: curbyte = byte_collection[ptr] ptr += 1 @@ -122,8 +273,6 @@ def build_anm_struct(byte_collection, anm_type, param_name): if anm_type is HEAP_SIZE_TYPE: trimmed = hexstr.lstrip('0') hexstr = trimmed if trimmed else '0' - elif anm_type is PARAM_TYPE: - prms_is_float.append(prm_is_float(hexstr)) pos_arr.append("0x" + hexstr) else: print(f"Error: unknown type '{my_type}'") @@ -137,20 +286,7 @@ def build_anm_struct(byte_collection, anm_type, param_name): pos_arr.clear() res_str = "" - if anm_type is PARAM_TYPE: - res_str += "struct Data {\n" - idx = 0 - while idx < my_len: - upper = f'{idx:02X}' - lower = f'{idx:02x}' - mych = 'f' if (prms_is_float[int(idx / 4)] is True) else 'u' - res_str += " /* 0x{} */ {}32 field_0x{};\n".format(upper, mych, lower) - idx += 4 - res_str += "};\n" - res_str += "static const Data m;\n\n" - res_str += "{}::Data const {}::m".format(param_name, param_name) - else: - res_str += "static {}".format(anm_type) + res_str += "static {}".format(anm_type) res_len = my_len / piece_size cutoff_num = 1 @@ -159,11 +295,7 @@ def build_anm_struct(byte_collection, anm_type, param_name): elif anm_type is HEAP_SIZE_TYPE: cutoff_num = 4 - if anm_type is not PARAM_TYPE: - res_str += "[{}]".format(int(res_len)) - - prmfloat_dbg = False - + res_str += "[{}]".format(int(res_len)) res_str += " = {\n" cur_in_line = 0 cur_idx = 0 @@ -186,17 +318,7 @@ def build_anm_struct(byte_collection, anm_type, param_name): elif isinstance(value, float): res_str += str(value) + "f" else: - if anm_type is PARAM_TYPE and prms_is_float[cur_idx] is True: - fvalue = hex_to_float(value[2:]) - fvalue = round(fvalue, 6) - res_str += f"{fvalue}f" - chk_val = float_to_hex(fvalue) - # Sanity check in case rounding is too aggressive: - assert chk_val == value, f"chk_val {chk_val} != value {value}" - if prmfloat_dbg is True: - res_str += f" // {value}" - else: - res_str += value + res_str += value if is_array is True: res_str += "}" @@ -218,7 +340,12 @@ def build_anm_struct(byte_collection, anm_type, param_name): print(res_str) -def run_beautify_anm_data(in_file): +def run_beautify_anm_data(in_file, type=None): + # Check if the file exists + if not os.path.isfile(in_file): + print(f"Error: File '{in_file}' not found.") + sys.exit(1) + fDesc = open(in_file, 'r') fConts = fDesc.read() lines = fConts.splitlines() @@ -257,7 +384,10 @@ def run_beautify_anm_data(in_file): param_name = match.group(1) else: if words[0] == '};': - build_anm_struct(byte_collection, anm_type, param_name) + if anm_type == PARAM_TYPE: + handle_npc_param(byte_collection, param_name, type) + else: + build_anm_struct(byte_collection, anm_type) in_byte_array = False byte_collection.clear() else: @@ -272,15 +402,4 @@ def run_beautify_anm_data(in_file): if __name__ == "__main__": - if len(sys.argv) < 2: - print("Usage: python3 beautify_anm_data.py ") - sys.exit(1) - - in_file = sys.argv[1] - - # Check if the file exists - if not os.path.isfile(in_file): - print(f"Error: File '{in_file}' not found.") - sys.exit(1) - - run_beautify_anm_data(in_file) + fire.Fire(run_beautify_anm_data)