mirror of
https://github.com/zeldaret/oot.git
synced 2025-05-12 12:03:48 +00:00
Automatic object xml creation (#596)
* new tool * fixes Co-authored-by: petrie911 <pmontag@DESKTOP-LG8A167.localdomain>
This commit is contained in:
parent
794538f6f7
commit
8cd367c43b
4 changed files with 238 additions and 33 deletions
|
@ -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
|
|
4
spec
4
spec
|
@ -2345,11 +2345,7 @@ endseg
|
||||||
beginseg
|
beginseg
|
||||||
name "ovl_En_GeldB"
|
name "ovl_En_GeldB"
|
||||||
include "build/src/overlays/actors/ovl_En_GeldB/z_en_geldb.o"
|
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"
|
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
|
|
||||||
endseg
|
endseg
|
||||||
|
|
||||||
beginseg
|
beginseg
|
||||||
|
|
|
@ -56,16 +56,17 @@ static InitChainEntry sInitChain[] = {
|
||||||
ICHAIN_F32(uncullZoneDownward, 1000, ICHAIN_STOP),
|
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[];
|
extern Gfx D_06000880[];
|
||||||
|
|
||||||
void BgJyaHaheniron_ColliderInit(BgJyaHaheniron* this, GlobalContext* globalCtx) {
|
void BgJyaHaheniron_ColliderInit(BgJyaHaheniron* this, GlobalContext* globalCtx) {
|
||||||
s32 pad;
|
s32 pad;
|
||||||
|
|
||||||
Collider_InitJntSph(globalCtx, &this->collider);
|
Collider_InitJntSph(globalCtx, &this->collider);
|
||||||
Collider_SetJntSph(globalCtx, &this->collider, &this->actor, &D_80898764, this->colliderItems);
|
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) {
|
void BgJyaHaheniron_Init(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
s32 pad;
|
||||||
BgJyaHaheniron* this = THIS;
|
BgJyaHaheniron* this = THIS;
|
||||||
Actor_ProcessInitChain(thisx, sInitChain);
|
|
||||||
|
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||||
Actor_SetScale(&this->actor, D_80898794[this->actor.params]);
|
Actor_SetScale(&this->actor, D_80898794[this->actor.params]);
|
||||||
if (thisx->params == 0) {
|
if (this->actor.params == 0) {
|
||||||
BgJyaHaheniron_ColliderInit(this, globalCtx);
|
BgJyaHaheniron_ColliderInit(this, globalCtx);
|
||||||
thisx->shape.rot.z = (Rand_ZeroOne() * 65535.0f);
|
this->actor.shape.rot.z = (Rand_ZeroOne() * 65535.0f);
|
||||||
BgJyaHaheniron_SetupChairCrumble(this);
|
BgJyaHaheniron_SetupChairCrumble(this);
|
||||||
} else if (thisx->params == 1) {
|
} else if (this->actor.params == 1) {
|
||||||
BgJyaHaheniron_SetupPillarCrumble(this);
|
BgJyaHaheniron_SetupPillarCrumble(this);
|
||||||
} else if (thisx->params == 2) {
|
} else if (this->actor.params == 2) {
|
||||||
BgJyaHaheniron_SetupRubbleCollide(this);
|
BgJyaHaheniron_SetupRubbleCollide(this);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BgJyaHaheniron_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
void BgJyaHaheniron_Destroy(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
if (thisx->params == 0) {
|
s32 pad;
|
||||||
Collider_DestroyJntSph(globalCtx, &THIS->collider);
|
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);
|
Actor_MoveForward(&this->actor);
|
||||||
func_8002E4B4(globalCtx, &this->actor, 5.0f, 8.0f, 0.0f, 0x85);
|
func_8002E4B4(globalCtx, &this->actor, 5.0f, 8.0f, 0.0f, 0x85);
|
||||||
if ((this->actor.bgCheckFlags & 9) ||
|
if ((this->actor.bgCheckFlags & 9) || ((this->collider.base.atFlags & 2) && (this->collider.base.at != NULL) &&
|
||||||
((this->collider.base.atFlags & 2) && (this->collider.base.at) && (this->collider.base.at->type == 2))) {
|
(this->collider.base.at->type == ACTORTYPE_PLAYER))) {
|
||||||
vec.x = -Rand_ZeroOne() * this->actor.velocity.x;
|
vec.x = -Rand_ZeroOne() * this->actor.velocity.x;
|
||||||
vec.y = -Rand_ZeroOne() * this->actor.velocity.y;
|
vec.y = -Rand_ZeroOne() * this->actor.velocity.y;
|
||||||
vec.z = -Rand_ZeroOne() * this->actor.velocity.z;
|
vec.z = -Rand_ZeroOne() * this->actor.velocity.z;
|
||||||
BgJyaHaheniron_SpawnFragments(globalCtx, &this->actor.posRot, &vec);
|
BgJyaHaheniron_SpawnFragments(globalCtx, &this->actor.posRot, &vec);
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
} else if (this->timer >= 61) {
|
} else if (this->timer > 60) {
|
||||||
Actor_Kill(&this->actor);
|
Actor_Kill(&this->actor);
|
||||||
} else {
|
} else {
|
||||||
CollisionCheck_SetAT(globalCtx, &globalCtx->colChkCtx, &this->collider);
|
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) {
|
void BgJyaHaheniron_Update(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
|
s32 pad;
|
||||||
BgJyaHaheniron* this = THIS;
|
BgJyaHaheniron* this = THIS;
|
||||||
|
|
||||||
this->timer++;
|
this->timer++;
|
||||||
this->actionFunc(this, globalCtx);
|
this->actionFunc(this, globalCtx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BgJyaHaheniron_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
void BgJyaHaheniron_Draw(Actor* thisx, GlobalContext* globalCtx) {
|
||||||
static Gfx* dLists[] = { 0x06000880, 0x06000AE0, 0x06000600 };
|
static Gfx* dLists[] = { 0x06000880, 0x06000AE0, 0x06000600 };
|
||||||
|
s32 pad;
|
||||||
BgJyaHaheniron* this = THIS;
|
BgJyaHaheniron* this = THIS;
|
||||||
|
|
||||||
if (thisx->params == 0) {
|
if (this->actor.params == 0) {
|
||||||
func_800628A4(0, &this->collider);
|
func_800628A4(0, &this->collider);
|
||||||
}
|
}
|
||||||
Gfx_DrawDListOpa(globalCtx, dLists[thisx->params]);
|
Gfx_DrawDListOpa(globalCtx, dLists[this->actor.params]);
|
||||||
}
|
}
|
||||||
|
|
213
tools/xmlcreate.py
Normal file
213
tools/xmlcreate.py
Normal file
|
@ -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 = '<DList Name="{0}" Offset="0x{1}"/>'
|
||||||
|
collision_xml = '<Collision Name="{0}" Offset="0x{1}"/>'
|
||||||
|
animation_xml = '<Animation Name="{0}" Offset="0x{1}"/>'
|
||||||
|
skeleton_xml = '<Skeleton Name="{0}" Type="{2}" LimbType="{3}" Offset="0x{1}"/>'
|
||||||
|
unknown_xml = '<!-- <{2} Name="{0}" Offset="0x{1}"/> -->'
|
||||||
|
|
||||||
|
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 = '<Root>\n <File Name="' + object + '" Segment="6">\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 += ' </File>\n</Root>\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)
|
Loading…
Add table
Reference in a new issue