From 8cd367c43bb63076d1c8a431ef91c08ea6166ae2 Mon Sep 17 00:00:00 2001 From: petrie911 <69443847+petrie911@users.noreply.github.com> Date: Mon, 4 Jan 2021 11:06:51 -0600 Subject: [PATCH] Automatic object xml creation (#596) * new tool * fixes Co-authored-by: petrie911 --- data/overlays/actors/z_en_geldb.reloc.s | 13 -- spec | 6 +- .../ovl_Bg_Jya_Haheniron/z_bg_jya_haheniron.c | 39 ++-- tools/xmlcreate.py | 213 ++++++++++++++++++ 4 files changed, 238 insertions(+), 33 deletions(-) delete mode 100644 data/overlays/actors/z_en_geldb.reloc.s create mode 100644 tools/xmlcreate.py diff --git a/data/overlays/actors/z_en_geldb.reloc.s b/data/overlays/actors/z_en_geldb.reloc.s deleted file mode 100644 index aabd82e5a9..0000000000 --- a/data/overlays/actors/z_en_geldb.reloc.s +++ /dev/null @@ -1,13 +0,0 @@ -.include "macro.inc" - - # assembler directives - .set noat # allow manual use of $at - .set noreorder # don't insert nops after branches - .set gp=64 # allow use of 64-bit general purpose registers - -.section .rodata - -.balign 16 - -glabel D_80A3A2E0 - .incbin "baserom/ovl_En_GeldB", 0x4FD0, 0x00000470 diff --git a/spec b/spec index 95b3b18a2c..f9a185c7d7 100644 --- a/spec +++ b/spec @@ -2345,11 +2345,7 @@ endseg beginseg name "ovl_En_GeldB" include "build/src/overlays/actors/ovl_En_GeldB/z_en_geldb.o" - #ifdef NON_MATCHING - include "build/src/overlays/actors/ovl_En_GeldB/ovl_En_GeldB_reloc.o" - #else - include "build/data/overlays/actors/z_en_geldb.reloc.o" - #endif + include "build/src/overlays/actors/ovl_En_GeldB/ovl_En_GeldB_reloc.o" endseg beginseg diff --git a/src/overlays/actors/ovl_Bg_Jya_Haheniron/z_bg_jya_haheniron.c b/src/overlays/actors/ovl_Bg_Jya_Haheniron/z_bg_jya_haheniron.c index 06a7117841..f027aa244f 100644 --- a/src/overlays/actors/ovl_Bg_Jya_Haheniron/z_bg_jya_haheniron.c +++ b/src/overlays/actors/ovl_Bg_Jya_Haheniron/z_bg_jya_haheniron.c @@ -56,16 +56,17 @@ static InitChainEntry sInitChain[] = { ICHAIN_F32(uncullZoneDownward, 1000, ICHAIN_STOP), }; -f32 D_80898794[] = { 0.13f, 0.1f, 0.1f }; +static f32 D_80898794[] = { 0.13f, 0.1f, 0.1f }; -Vec3f D_808987A0[] = { 0.0f, 14.0f, 0.0f }; +static Vec3f D_808987A0[] = { 0.0f, 14.0f, 0.0f }; -Vec3f D_808987AC[] = { 0.0f, 8.0f, 0.0f }; +static Vec3f D_808987AC[] = { 0.0f, 8.0f, 0.0f }; extern Gfx D_06000880[]; void BgJyaHaheniron_ColliderInit(BgJyaHaheniron* this, GlobalContext* globalCtx) { s32 pad; + Collider_InitJntSph(globalCtx, &this->collider); Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &D_80898764, this->colliderItems); } @@ -104,23 +105,28 @@ void BgJyaHaheniron_SpawnFragments(GlobalContext* globalCtx, Vec3f* vec1, Vec3f* } void BgJyaHaheniron_Init(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; BgJyaHaheniron* this = THIS; - Actor_ProcessInitChain(thisx, sInitChain); + + Actor_ProcessInitChain(&this->actor, sInitChain); Actor_SetScale(&this->actor, D_80898794[this->actor.params]); - if (thisx->params == 0) { + if (this->actor.params == 0) { BgJyaHaheniron_ColliderInit(this, globalCtx); - thisx->shape.rot.z = (Rand_ZeroOne() * 65535.0f); + this->actor.shape.rot.z = (Rand_ZeroOne() * 65535.0f); BgJyaHaheniron_SetupChairCrumble(this); - } else if (thisx->params == 1) { + } else if (this->actor.params == 1) { BgJyaHaheniron_SetupPillarCrumble(this); - } else if (thisx->params == 2) { + } else if (this->actor.params == 2) { BgJyaHaheniron_SetupRubbleCollide(this); } } void BgJyaHaheniron_Destroy(Actor* thisx, GlobalContext* globalCtx) { - if (thisx->params == 0) { - Collider_DestroyJntSph(globalCtx, &THIS->collider); + s32 pad; + BgJyaHaheniron* this = THIS; + + if (this->actor.params == 0) { + Collider_DestroyJntSph(globalCtx, &this->collider); } } @@ -133,14 +139,14 @@ void BgJyaHaheniron_ChairCrumble(BgJyaHaheniron* this, GlobalContext* globalCtx) Actor_MoveForward(&this->actor); func_8002E4B4(globalCtx, &this->actor, 5.0f, 8.0f, 0.0f, 0x85); - if ((this->actor.bgCheckFlags & 9) || - ((this->collider.base.atFlags & 2) && (this->collider.base.at) && (this->collider.base.at->type == 2))) { + if ((this->actor.bgCheckFlags & 9) || ((this->collider.base.atFlags & 2) && (this->collider.base.at != NULL) && + (this->collider.base.at->type == ACTORTYPE_PLAYER))) { vec.x = -Rand_ZeroOne() * this->actor.velocity.x; vec.y = -Rand_ZeroOne() * this->actor.velocity.y; vec.z = -Rand_ZeroOne() * this->actor.velocity.z; BgJyaHaheniron_SpawnFragments(globalCtx, &this->actor.posRot, &vec); Actor_Kill(&this->actor); - } else if (this->timer >= 61) { + } else if (this->timer > 60) { Actor_Kill(&this->actor); } else { CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider); @@ -177,17 +183,20 @@ void BgJyaHaheniron_RubbleCollide(BgJyaHaheniron* this, GlobalContext* globalCtx } void BgJyaHaheniron_Update(Actor* thisx, GlobalContext* globalCtx) { + s32 pad; BgJyaHaheniron* this = THIS; + this->timer++; this->actionFunc(this, globalCtx); } void BgJyaHaheniron_Draw(Actor* thisx, GlobalContext* globalCtx) { static Gfx* dLists[] = { 0x06000880, 0x06000AE0, 0x06000600 }; + s32 pad; BgJyaHaheniron* this = THIS; - if (thisx->params == 0) { + if (this->actor.params == 0) { func_800628A4(0, &this->collider); } - Gfx_DrawDListOpa(globalCtx, dLists[thisx->params]); + Gfx_DrawDListOpa(globalCtx, dLists[this->actor.params]); } diff --git a/tools/xmlcreate.py b/tools/xmlcreate.py new file mode 100644 index 0000000000..a23c9ac57e --- /dev/null +++ b/tools/xmlcreate.py @@ -0,0 +1,213 @@ +#!/usr/bin/python3 +import os +import argparse + +offsets = set() +replacements = {} +global_name = '' + +name_fmt = 'g{0}{1}_{2}' +spec_fmt = ' include "build/assets/objects/{0}/{0}.o"\n number 6\n' + +dlist_xml = '' +collision_xml = '' +animation_xml = '' +skeleton_xml = '' +unknown_xml = '' + +def set_globals(new_name): + global offsets + global global_name + global replacements + + offsets = set() + replacements = {} + global_name = new_name + return 0 + + +def dlist_to_xml(var_name,offset): + + return dlist_xml.format(var_name,offset.lstrip('0')) + +def collision_to_xml(var_name,offset): + + return collision_xml.format(var_name,offset.lstrip('0')) + +def animation_to_xml(var_name,offset): + + return animation_xml.format(var_name,offset.lstrip('0')) + +def skeleton_to_xml(var_name,offset, type): + skel_type = "Flex" if "Flex" in type else "Standard" + limb_type = "Standard" + + return skeleton_xml.format(var_name, offset.lstrip('0'), skel_type, limb_type) + +def unknown_to_xml(var_name,offset, type): + + return unknown_xml.format(var_name,offset.lstrip('0'),type) + +def make_xml_line(offset, type): + if 'Gfx' in type: + var_name = name_fmt.format(global_name,'DL',offset) + xml_line = dlist_to_xml(var_name, offset) + elif 'Col' in type: + var_name = name_fmt.format(global_name,'Col',offset) + xml_line = collision_to_xml(var_name, offset) + elif 'Animation' in type: + var_name = name_fmt.format(global_name,'Anim',offset) + xml_line = animation_to_xml(var_name, offset) + elif 'Skeleton' in type: + var_name = name_fmt.format(global_name,'Skel',offset) + xml_line = skeleton_to_xml(var_name, offset, type) + else: + var_name = name_fmt.format(global_name,'Unknown',offset) + xml_line = unknown_to_xml(var_name, offset, type) + print('Unknown type at offset', offset) + replacements['06'+offset] = var_name + return xml_line + +def extern_to_xml(line): + global offsets + + type = line.split()[1] + sym = line.split()[2] + offset = sym[4:10] + if(offset in offsets): + return '' + else: + offsets.add(offset) + + xml_line = ' ' * 8 + xml_line += make_xml_line(offset, type) + # make_replace(offset, type) + + return xml_line + '\n' + +def find_type(srcdata, i): + j = i + while(j >= 0 and ' = {' not in srcdata[j]): + j -= 1 + if(j < 0): + return 'UNKNOWN' + else: + return srcdata[j].split(' = {')[0].split()[-2] + +def other_to_xml(srcdata, i): + xml_data = '' + line = srcdata[i] + + index = line.find('0x060') + while(index < len(line) and '0x060' in line[index:]): + offset = line[index+4:index+10] + type = find_type(srcdata, i) + if(offset not in offsets): + offsets.add(offset) + xml_data += ' ' * 8 + make_xml_line(offset, type) + '\n' + # make_replace(offset, type) + index += line[index+10:].find('0x060') + 10 + return xml_data + +def find_object(src): + with open(src,'r',encoding='utf-8') as srcfile: + srcdata = srcfile.readlines() + for i, line in enumerate(srcdata): + if 'OBJECT_' in line and ' FLAGS,' in srcdata[i-1]: + object = line.strip().strip(',') + return object.lower() + + print('Object not found in', src) + object = '' + return object + +def create_xml(src, name): + set_globals(name) + with open(src,'r',encoding='utf-8') as srcfile: + srcdata = srcfile.readlines() + object = find_object(src) + xml = '\n \n' + symbols = {} + for i, line in enumerate(srcdata): + if '0x060' in line or 'D_060' in line: + if 'extern' in line: + xml += extern_to_xml(line) + elif '0x060' in line: + xml += other_to_xml(srcdata, i) + xml += ' \n\n' + return xml + +def add_header(src): + object = find_object(src) + if(object == ''): + return 0 + with open(src,'r', encoding='utf-8') as srcfile: + srcdata = srcfile.readlines() + for i, line in enumerate(srcdata): + if('#include' in line): + break + srcdata = srcdata[0:i+1] + ['#include "objects/' + object + '/' + object + '.h"\n'] + srcdata[i+1:] + with open(src,'w',encoding='utf-8', newline = '\n') as outfile: + outfile.writelines(srcdata) + return 1 + +def replace_src(src): + global replacements + global global_name + + add_header(src) + with open(src,'r', encoding='utf-8') as srcfile: + srcdata = srcfile.read() + for key in list(replacements.keys()): + srcdata = srcdata.replace(key, replacements.get(key)) + srcdata = srcdata.replace('D_g' + global_name, 'g' + global_name) + if('Gfx' in replacements.get(key)): + srcdata = srcdata.replace('0xg' + global_name, 'g' + global_name) + else: + srcdata = srcdata.replace('0xg' + global_name, '&g' + global_name) + with open(src,'w',encoding='utf-8', newline = '\n') as outfile: + outfile.write(srcdata) + return 1 + +def fix_spec(src, spec): + object = find_object(src) + fix = False + old = False + with open(spec, 'r') as specfile: + specdata = specfile.readlines() + for i, line in enumerate(specdata): + if ('"' + object + '"') in line: + if 'number' in specdata[i+3]: + old = True + else: + specdata[i+2] = spec_fmt.format(object) + fix = True + break + if old: + print('Already fixed', object, 'in', spec) + return 0 + if not fix: + print('Could not find',object,'in', spec) + return -1 + with open(spec, 'w', newline='\n') as outfile: + outfile.writelines(specdata) + return 1 + +parser = argparse.ArgumentParser(description="Generate an xml object file from a source file") +parser.add_argument('file', help="overlay file to generate xml from") +parser.add_argument('name', help='name to use for xml variables') +parser.add_argument('-r',action='store_true', help="replace variables in overlay with the new names") +parser.add_argument('-s',metavar = 'spec', dest = 'spec', help="spec file to update", default=None) +parser.add_argument('-o', metavar = 'outfile', dest = 'outfile', help = 'file to write xml to', default = None) + +if __name__ == "__main__": + args = parser.parse_args() + if args.outfile is None: + print(create_xml(args.file, args.name)) + else: + with open(args.outfile, 'w', encoding='utf-8',newline='\n') as outfile: + outfile.write(create_xml(args.file, args.name)) + if(args.r): + replace_src(args.file) + if(args.spec is not None): + fix_spec(args.file, args.spec)