From 97f80eeb3f79bafac383fa6dd17765ae291e05d7 Mon Sep 17 00:00:00 2001 From: Roman971 <32455037+Roman971@users.noreply.github.com> Date: Sat, 27 Mar 2021 21:26:59 +0100 Subject: [PATCH] Update asm_processor and use static variables in En_Torch2 (#740) * Update asm_processor to current master * Update variables in En_Torch2 to actually be static This is now possible because asm_processor was updated to handle static symbols in GLOBAL_ASM * Update tutorial to reflect changes about static symbol limitations --- docs/tutorial/data.md | 6 +- .../actors/ovl_En_Torch2/z_en_torch2.c | 38 +++++------ tools/asm_processor/asm_processor.py | 66 ++++++++++++++++++- 3 files changed, 84 insertions(+), 26 deletions(-) diff --git a/docs/tutorial/data.md b/docs/tutorial/data.md index d001f4149d..986a47e1fa 100644 --- a/docs/tutorial/data.md +++ b/docs/tutorial/data.md @@ -23,8 +23,6 @@ Both approaches have their advantages and disadvantages. This way is good for smaller actors with little data. It is not really suitable for EnJj, for example, because of the enormous section of data labelled as `D_80A88164`. -An important thing to bear in mind is that data cannot be made static if it is used in an undecompiled file (i.e. one that is `#pragma`'d), so it is best to make everything static only after the whole actor is decompiled. - ### Example: `EnTg` We give a simple example of this approach with a small NPC actor, EnTg, that is, the spinning couple. @@ -165,10 +163,10 @@ static ColliderCylinderInit sCylinderInit = }; ``` -Copy this in below `D_80B18910`, delete the original words of data, and for now, remove `static` (in case it's used in other files that have not been decompiled), change the name back to `D_80B18910`, and put `sCylinderInit` commented out above it: +Copy this in below `D_80B18910`, delete the original words of data, change the name back to `D_80B18910`, and put `sCylinderInit` commented out above it: ```C // sCylinderInit -ColliderCylinderInit D_80B18910 = +static ColliderCylinderInit D_80B18910 = { { COLTYPE_UNK10, 0x00, 0x00, 0x39, 0x20, COLSHAPE_CYLINDER }, { 0x00, { 0x00000000, 0x00, 0x00 }, { 0x00000000, 0x00, 0x00 }, 0x00, 0x00, 0x01 }, diff --git a/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c b/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c index fd9da83afb..9d55460e95 100644 --- a/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c +++ b/src/overlays/actors/ovl_En_Torch2/z_en_torch2.c @@ -66,26 +66,26 @@ const ActorInit En_Torch2_InitVars = { (ActorFunc)EnTorch2_Draw, }; -/* static */ f32 sStickTilt = 0.0f; -/* static */ s16 sStickAngle = 0; -/* static */ f32 sSwordJumpHeight = 0.0f; -/* static */ s32 sHoldShieldTimer = 0; -/* static */ u8 sZTargetFlag = false; -/* static */ u8 sDeathFlag = false; +static f32 sStickTilt = 0.0f; +static s16 sStickAngle = 0; +static f32 sSwordJumpHeight = 0.0f; +static s32 sHoldShieldTimer = 0; +static u8 sZTargetFlag = false; +static u8 sDeathFlag = false; -/* static */ Input sInput; -/* static */ u8 sSwordJumpState; -/* static */ Vec3f sSpawnPoint; -/* static */ u8 sJumpslashTimer; -/* static */ u8 sJumpslashFlag; -/* static */ u8 sActionState; -/* static */ u8 sSwordJumpTimer; -/* static */ u8 sCounterState; -/* static */ u8 sDodgeRollState; -/* static */ u8 sStaggerCount; -/* static */ u8 sStaggerTimer; -/* static */ s8 sLastSwordAnim; -/* static */ u8 sAlpha; +static Input sInput; +static u8 sSwordJumpState; +static Vec3f sSpawnPoint; +static u8 sJumpslashTimer; +static u8 sJumpslashFlag; +static u8 sActionState; +static u8 sSwordJumpTimer; +static u8 sCounterState; +static u8 sDodgeRollState; +static u8 sStaggerCount; +static u8 sStaggerTimer; +static s8 sLastSwordAnim; +static u8 sAlpha; static DamageTable sDamageTable = { /* Deku nut */ DMG_ENTRY(0, 0x1), diff --git a/tools/asm_processor/asm_processor.py b/tools/asm_processor/asm_processor.py index ea18c384b5..9d5e6a749b 100644 --- a/tools/asm_processor/asm_processor.py +++ b/tools/asm_processor/asm_processor.py @@ -81,6 +81,9 @@ R_MIPS_26 = 4 R_MIPS_HI16 = 5 R_MIPS_LO16 = 6 +MIPS_DEBUG_ST_STATIC = 2 +MIPS_DEBUG_ST_STATIC_PROC = 14 + class ElfHeader: """ @@ -132,14 +135,19 @@ class Symbol: } Elf32_Sym; """ - def __init__(self, data, strtab): + def __init__(self, data, strtab, name=None): self.st_name, self.st_value, self.st_size, st_info, self.st_other, self.st_shndx = struct.unpack('>IIIBBH', data) assert self.st_shndx != SHN_XINDEX, "too many sections (SHN_XINDEX not supported)" self.bind = st_info >> 4 self.type = st_info & 15 - self.name = strtab.lookup_str(self.st_name) + self.name = name if name is not None else strtab.lookup_str(self.st_name) self.visibility = self.st_other & 3 + @staticmethod + def from_parts(st_name, st_value, st_size, st_info, st_other, st_shndx, strtab, name): + header = struct.pack('>IIIBBH', st_name, st_value, st_size, st_info, st_other, st_shndx) + return Symbol(header, strtab, name) + def to_bin(self): st_info = (self.bind << 4) | self.type return struct.pack('>IIIBBH', self.st_name, self.st_value, self.st_size, st_info, self.st_other, self.st_shndx) @@ -913,6 +921,7 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc): asm_objfile = ElfFile(f.read()) # Remove some clutter from objdump output + mdebug_section = objfile.find_section('.mdebug') objfile.drop_irrelevant_sections() # Unify reginfo sections @@ -1014,7 +1023,7 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc): # Move over symbols, deleting the temporary function labels. # Sometimes this naive procedure results in duplicate symbols, or UNDEF # symbols that are also defined the same .o file. Hopefully that's fine. - # Skip over local symbols that aren't used relocated against, to avoid + # Skip over local symbols that aren't relocated against, to avoid # conflicts. new_local_syms = [s for s in objfile.symtab.local_symbols() if not is_temp_name(s.name)] new_global_syms = [s for s in objfile.symtab.global_symbols() if not is_temp_name(s.name)] @@ -1039,6 +1048,57 @@ def fixup_objfile(objfile_name, functions, asm_prelude, assembler, output_enc): new_local_syms.append(s) else: new_global_syms.append(s) + + # Add static symbols from .mdebug, so they can be referred to from GLOBAL_ASM + local_sym_replacements = {} + if mdebug_section: + strtab_index = len(objfile.symtab.strtab.data) + new_strtab_data = [] + ifd_max, cb_fd_offset = struct.unpack('>II', mdebug_section.data[18*4 : 20*4]) + cb_sym_offset, = struct.unpack('>I', mdebug_section.data[9*4 : 10*4]) + cb_ss_offset, = struct.unpack('>I', mdebug_section.data[15*4 : 16*4]) + for i in range(ifd_max): + offset = cb_fd_offset + 18*4*i + iss_base, _, isym_base, csym = struct.unpack('>IIII', objfile.data[offset + 2*4 : offset + 6*4]) + for j in range(csym): + offset2 = cb_sym_offset + 12 * (isym_base + j) + iss, value, st_sc_index = struct.unpack('>III', objfile.data[offset2 : offset2 + 12]) + st = (st_sc_index >> 26) + sc = (st_sc_index >> 21) & 0x1f + if st in [MIPS_DEBUG_ST_STATIC, MIPS_DEBUG_ST_STATIC_PROC]: + symbol_name_offset = cb_ss_offset + iss_base + iss + symbol_name_offset_end = objfile.data.find(b'\0', symbol_name_offset) + assert symbol_name_offset_end != -1 + symbol_name = objfile.data[symbol_name_offset : symbol_name_offset_end + 1] + symbol_name_str = symbol_name[:-1].decode('latin1') + section_name = ['', '.text', '.data', '.bss'][sc] + section = objfile.find_section(section_name) + symtype = STT_FUNC if sc == 1 else STT_OBJECT + sym = Symbol.from_parts( + st_name=strtab_index, + st_value=value, + st_size=0, + st_info=(STB_LOCAL << 4 | symtype), + st_other=STV_DEFAULT, + st_shndx=section.index, + strtab=objfile.symtab.strtab, + name=symbol_name_str) + local_sym_replacements[symbol_name_str] = len(new_local_syms) + strtab_index += len(symbol_name) + new_strtab_data.append(symbol_name) + new_local_syms.append(sym) + objfile.symtab.strtab.data += b''.join(new_strtab_data) + + # To get the linker to use the local symbols, we have to get rid of UNDEF + # global ones. + newer_global_syms = [] + for s in new_global_syms: + if s.st_shndx == SHN_UNDEF and s.name in local_sym_replacements: + s.new_index = local_sym_replacements[s.name] + else: + newer_global_syms.append(s) + new_global_syms = newer_global_syms + new_syms = new_local_syms + new_global_syms for i, s in enumerate(new_syms): s.new_index = i