mirror of
https://github.com/zeldaret/oot
synced 2026-08-18 13:43:14 -04:00
Document Collision_Check (#468)
* Darkmeiro decompilation Bg_Gnd_Darkmeiro decompiled, matched, and documented. * give this a shot * fix conflict * one more try * could be useful * whoops * some decomp * still playing around with this * rename functions * ZAP again * ZAP again * the renaming begins * more renaming. hopefully didn't break anything * change all the things * this and then merge * and done * one little thing * small docs, small rename * changed mind on cylinder and quad elements * something * more stuff * more docs * more adjustments * Fixed some types * more fixes * all sorts of cleanup * now with flags * match! * names and such * update tools * damage tables * ColChkInfo * one more thing * formatting * more formatting * anime merge * some stuff * damage table * again * changes * .s * changes * oc2 type * a couple things * format * un-name magic arrows, not enough proof yet * fix damage table script and remove old one * EnAObj * changes Co-authored-by: petrie911 <pmontag@DESKTOP-LG8A167.localdomain> Co-authored-by: Fig02 <fig02srl@gmail.com>
This commit is contained in:
@@ -1,22 +0,0 @@
|
||||
import struct
|
||||
|
||||
ROM_ADDR = 0xDA3210
|
||||
COUNT = 1
|
||||
|
||||
rom = open("../../baserom.z64", "rb")
|
||||
rom.seek(ROM_ADDR)
|
||||
data = bytearray(rom.read(0x20 * COUNT))
|
||||
rom.close()
|
||||
|
||||
valFormat = "0x{:02X}"
|
||||
sfmt = ""
|
||||
for i in range(4):
|
||||
sfmt += valFormat + ", "
|
||||
|
||||
for i in range(3):
|
||||
sfmt += sfmt
|
||||
|
||||
sfmt = "{{ {{ " + sfmt + "}} }},"
|
||||
for i in range(COUNT):
|
||||
line = struct.unpack_from(">32B", data, i * 0x20)
|
||||
print(sfmt.format(*line))
|
||||
@@ -6,24 +6,24 @@ import argparse
|
||||
from filemap import FileResult, GetFromVRam, GetFromRom
|
||||
|
||||
T_DEFAULT = ''
|
||||
T_SET3 = '_Set3'
|
||||
TType1 = 'Type1'
|
||||
T_ACTOR = '_Actor'
|
||||
|
||||
TYPE_ENUM = [
|
||||
"COLTYPE_UNK0",
|
||||
"COLTYPE_UNK1",
|
||||
"COLTYPE_UNK2",
|
||||
"COLTYPE_UNK3",
|
||||
"COLTYPE_UNK4",
|
||||
"COLTYPE_UNK5",
|
||||
"COLTYPE_UNK6",
|
||||
"COLTYPE_UNK7",
|
||||
"COLTYPE_UNK8",
|
||||
"COLTYPE_METAL_SHIELD",
|
||||
"COLTYPE_UNK10",
|
||||
"COLTYPE_WOODEN_SHIELD",
|
||||
"COLTYPE_UNK12",
|
||||
"COLTYPE_UNK13" ]
|
||||
"COLTYPE_HIT0",
|
||||
"COLTYPE_HIT1",
|
||||
"COLTYPE_HIT2",
|
||||
"COLTYPE_HIT3",
|
||||
"COLTYPE_HIT4",
|
||||
"COLTYPE_HIT5",
|
||||
"COLTYPE_HIT6",
|
||||
"COLTYPE_HIT7",
|
||||
"COLTYPE_HIT8",
|
||||
"COLTYPE_METAL",
|
||||
"COLTYPE_NONE",
|
||||
"COLTYPE_WOOD",
|
||||
"COLTYPE_HARD",
|
||||
"COLTYPE_TREE" ]
|
||||
|
||||
SHAPE_ENUM = [
|
||||
"COLSHAPE_JNTSPH",
|
||||
@@ -31,35 +31,188 @@ SHAPE_ENUM = [
|
||||
"COLSHAPE_TRIS",
|
||||
"COLSHAPE_QUAD" ]
|
||||
|
||||
ELEMTYPE_UNKENUM = [
|
||||
"ELEMTYPE_UNK0",
|
||||
"ELEMTYPE_UNK1",
|
||||
"ELEMTYPE_UNK2",
|
||||
"ELEMTYPE_UNK3",
|
||||
"ELEMTYPE_UNK4",
|
||||
"ELEMTYPE_UNK5",
|
||||
"ELEMTYPE_UNK6"]
|
||||
|
||||
ATFLAGS_ENUM = [
|
||||
"AT_ON",
|
||||
"AT_HIT",
|
||||
"AT_BOUNCED",
|
||||
"AT_TYPE_PLAYER",
|
||||
"AT_TYPE_ENEMY",
|
||||
"AT_TYPE_OTHER",
|
||||
"AT_SELF"]
|
||||
|
||||
ACFLAGS_ENUM = [
|
||||
"AC_ON",
|
||||
"AC_HIT",
|
||||
"AC_HARD",
|
||||
"AC_TYPE_PLAYER",
|
||||
"AC_TYPE_ENEMY",
|
||||
"AC_TYPE_OTHER",
|
||||
"AC_NO_DAMAGE",
|
||||
"AC_BOUNCED"]
|
||||
|
||||
OCFLAGS_ENUM = [
|
||||
"OC1_ON",
|
||||
"OC1_HIT",
|
||||
"OC1_NO_PUSH",
|
||||
"OC1_TYPE_PLAYER",
|
||||
"OC1_TYPE_1",
|
||||
"OC1_TYPE_2"]
|
||||
|
||||
OCTYPE_ENUM = [
|
||||
"OC2_HIT_PLAYER",
|
||||
"OC2_UNK1",
|
||||
"OC2_UNK2",
|
||||
"OC2_TYPE_PLAYER",
|
||||
"OC2_TYPE_1",
|
||||
"OC2_TYPE_2",
|
||||
"OC2_FIRST_ONLY"]
|
||||
|
||||
TOUCHERFLAGS_ENUM = [
|
||||
"TOUCH_ON",
|
||||
"TOUCH_HIT",
|
||||
"TOUCH_NEAREST",
|
||||
"TOUCH_SFX_HARD",
|
||||
"TOUCH_SFX_WOOD",
|
||||
"TOUCH_AT_HITMARK",
|
||||
"TOUCH_DREW_HITMARK",
|
||||
"TOUCH_UNK7"]
|
||||
|
||||
BUMPERFLAGS_ENUM = [
|
||||
"BUMP_ON",
|
||||
"BUMP_HIT",
|
||||
"BUMP_HOOKABLE",
|
||||
"BUMP_NO_AT_INFO",
|
||||
"BUMP_NO_DAMAGE",
|
||||
"BUMP_NO_SWORD_SFX",
|
||||
"BUMP_NO_HITMARK",
|
||||
"BUMP_DRAW_HITMARK"]
|
||||
|
||||
OCELEMFLAGS_ENUM = [
|
||||
"OCELEM_ON",
|
||||
"OCELEM_HIT",
|
||||
"OCELEM_UNK2",
|
||||
"OCELEM_UNK3",
|
||||
"OCELEM_UNK4",
|
||||
"OCELEM_UNK5",
|
||||
"OCELEM_UNK6",
|
||||
"OCELEM_UNK7",]
|
||||
|
||||
sf_ColliderInit = ">BBBBBB"
|
||||
sf_ColliderInit_Set3 = ">BBBBB"
|
||||
sf_ColliderInit_Actor = ">IBBBB"
|
||||
sf_ColliderInitType1 = ">BBBBB"
|
||||
sf_ColliderInitToActor = ">IBBBB"
|
||||
sf_ColliderBodyInit = ">B3xIBB2xIBB2xBBB"
|
||||
sf_JntSph = ">II"
|
||||
sf_JntSphItem = ">Bx5h"
|
||||
sf_JntSphElement = ">Bx5h"
|
||||
sf_Cylinder16 = ">6h"
|
||||
sf_Tris = ">II"
|
||||
sf_TrisItem = ">9f"
|
||||
sf_TrisElement = ">9f"
|
||||
sf_Quad = ">12f"
|
||||
|
||||
f_ColliderInit = "{{ {0}, 0x{1:02X}, 0x{2:02X}, 0x{3:02X}, 0x{4:02X}, {5} }}"
|
||||
f_ColliderInit_Set3 = "{{ {0}, 0x{1:02X}, 0x{2:02X}, 0x{3:02X}, {4} }}"
|
||||
f_ColliderInit_Actor = "{{ {0}, 0x{1:02X}, 0x{2:02X}, 0x{3:02X}, {4} }}"
|
||||
f_ColliderBodyInit = "{{ 0x{0:02X}, {{ 0x{1:08X}, 0x{2:02X}, 0x{3:02X} }}, {{ 0x{4:08X}, 0x{5:02X}, 0x{6:02X} }}, 0x{7:02X}, 0x{8:02X}, 0x{9:02X} }}"
|
||||
f_ColliderInit = "{{ {0}, {1}, {2}, {3}, {4}, {5}, }}"
|
||||
f_ColliderInitType1 = "{{ {0}, {1}, {2}, {3}, {4}, }}"
|
||||
f_ColliderInitToActor = "{{ {0}, {1}, {2}, {3}, {4}, }}"
|
||||
f_ColliderBodyInit = "{{ {0}, {{ 0x{1:08X}, 0x{2:02X}, 0x{3:02X} }}, {{ 0x{4:08X}, 0x{5:02X}, 0x{6:02X} }}, {7}, {8}, {9}, }}"
|
||||
f_JntSph = "{0}, D_{1:08X}"
|
||||
f_JntSphItem = "{{ {0}, {{ {{ {1}, {2}, {3} }}, {4} }}, {5} }}"
|
||||
f_JntSphElement = "{{ {0}, {{ {{ {1}, {2}, {3} }}, {4} }}, {5} }}"
|
||||
f_Cylinder16 = "{{ {0}, {1}, {2}, {{ {3}, {4}, {5} }} }}"
|
||||
f_Tris = "{0}, D_{1:08X}"
|
||||
f_TrisItem = "{{ {{ {{ {0}f, {1}f, {2}f }}, {{ {3}f, {4}f, {5}f }}, {{ {6}f, {7}f, {8}f }} }} }}"
|
||||
f_TrisElement = "{{ {{ {{ {0}f, {1}f, {2}f }}, {{ {3}f, {4}f, {5}f }}, {{ {6}f, {7}f, {8}f }} }} }}"
|
||||
f_Quad = "{{ {{ {{ {0}f, {1}f, {2}f }}, {{ {3}f, {4}f, {5}f }}, {{ {6}f, {7}f, {8}f }}, {{ {9}f, {10}f, {11}f }} }} }}"
|
||||
|
||||
def GetATflags(at):
|
||||
for i, flag in enumerate(ATFLAGS_ENUM):
|
||||
if(i == 0):
|
||||
if(at & (1 << i)):
|
||||
output = "AT_ON"
|
||||
else:
|
||||
output = "AT_NONE"
|
||||
elif(at & (1 << i)):
|
||||
output += " | " + flag
|
||||
return output.replace("AT_TYPE_PLAYER | AT_TYPE_ENEMY | AT_TYPE_OTHER","AT_TYPE_ALL")
|
||||
|
||||
def GetACflags(at):
|
||||
for i, flag in enumerate(ACFLAGS_ENUM):
|
||||
if(i == 0):
|
||||
if(at & (1 << i)):
|
||||
output = "AC_ON"
|
||||
else:
|
||||
output = "AC_NONE"
|
||||
elif(at & (1 << i)):
|
||||
output += " | " + flag
|
||||
return output.replace("AC_TYPE_OTHER | AC_TYPE_ENEMY | AC_TYPE_PLAYER","AC_TYPE_ALL")
|
||||
|
||||
def GetOCflags(at):
|
||||
for i, flag in enumerate(OCFLAGS_ENUM):
|
||||
if(i == 0):
|
||||
if(at & (1 << i)):
|
||||
output = "OC1_ON"
|
||||
else:
|
||||
output = "OC1_NONE"
|
||||
elif(at & (1 << i)):
|
||||
output += " | " + flag
|
||||
return output.replace("OC1_TYPE_PLAYER | OC1_TYPE_1 | OC1_TYPE_2","OC1_TYPE_ALL")
|
||||
|
||||
def GetOCtype(at):
|
||||
output = ""
|
||||
for i, flag in enumerate(OCTYPE_ENUM):
|
||||
if(at & (1 << i)):
|
||||
output = " | " + flag + output
|
||||
if(output == ""):
|
||||
return "OC2_NONE"
|
||||
else:
|
||||
return output.strip(" | ")
|
||||
|
||||
def GetToucherFlags(at):
|
||||
for i, flag in enumerate(TOUCHERFLAGS_ENUM):
|
||||
if(i == 0):
|
||||
if(at & (1 << i)):
|
||||
output = "TOUCH_ON"
|
||||
else:
|
||||
output = "TOUCH_NONE"
|
||||
elif(at & (1 << i)):
|
||||
output += " | " + flag
|
||||
if(i == 4 and output.find("SFX") == -1 and output.find("OFF") == -1):
|
||||
output += " | TOUCH_SFX_NORMAL"
|
||||
return output.replace("TOUCH_SFX_HARD | TOUCH_SFX_WOOD", "TOUCH_SFX_NONE")
|
||||
|
||||
def GetBumperFlags(at):
|
||||
for i, flag in enumerate(BUMPERFLAGS_ENUM):
|
||||
if(i == 0):
|
||||
if(at & (1 << i)):
|
||||
output = "BUMP_ON"
|
||||
else:
|
||||
output = "BUMP_NONE"
|
||||
elif(at & (1 << i)):
|
||||
output += " | " + flag
|
||||
return output
|
||||
|
||||
def GetOcElemFlags(at):
|
||||
for i, flag in enumerate(OCELEMFLAGS_ENUM):
|
||||
if(i == 0):
|
||||
if(at & (1 << i)):
|
||||
output = "OCELEM_ON"
|
||||
else:
|
||||
output = "OCELEM_NONE"
|
||||
elif(at & (1 << i)):
|
||||
output += " | " + flag
|
||||
return output
|
||||
|
||||
def GetColliderFormat(type):
|
||||
if type == T_DEFAULT:
|
||||
return (sf_ColliderInit, f_ColliderInit)
|
||||
if type == T_SET3:
|
||||
return (sf_ColliderInit_Set3, f_ColliderInit_Set3)
|
||||
if type == TType1:
|
||||
return (sf_ColliderInitType1, f_ColliderInitType1)
|
||||
if type == T_ACTOR:
|
||||
return (sf_ColliderInit_Actor, f_ColliderInit_Actor)
|
||||
return (sf_ColliderInitToActor, f_ColliderInitToActor)
|
||||
return None
|
||||
|
||||
def GetColliderStr(data, off, type):
|
||||
@@ -76,9 +229,15 @@ def GetColliderStr(data, off, type):
|
||||
else:
|
||||
cBase[0] = '0x{0:02X}'.format(cBase[0])
|
||||
|
||||
i = 4
|
||||
cBase[1] = GetATflags(cBase[1])
|
||||
cBase[2] = GetACflags(cBase[2])
|
||||
cBase[3] = GetOCflags(cBase[3])
|
||||
|
||||
if type == T_DEFAULT:
|
||||
cBase[4] = GetOCtype(cBase[4])
|
||||
i = 5
|
||||
else:
|
||||
i = 4
|
||||
|
||||
if cBase[i] < 4:
|
||||
cBase[i] = SHAPE_ENUM[cBase[i]]
|
||||
@@ -91,8 +250,18 @@ def GetItems(data, off, count, structf, fmt, size):
|
||||
result = ''
|
||||
for i in range(count):
|
||||
ioff = (i * size)
|
||||
cBody = struct.unpack_from(sf_ColliderBodyInit, data, off + ioff)
|
||||
cBody = list(struct.unpack_from(sf_ColliderBodyInit, data, off + ioff))
|
||||
cItem = struct.unpack_from(structf, data, off + 0x18 + ioff)
|
||||
|
||||
if cBody[0] < 7:
|
||||
cBody[0] = ELEMTYPE_UNKENUM[cBody[0]]
|
||||
else:
|
||||
cBody[0] = '0x{0:02X}'.format(cBody[0])
|
||||
|
||||
cBody[7] = GetToucherFlags(cBody[7])
|
||||
cBody[8] = GetBumperFlags(cBody[8])
|
||||
cBody[9] = GetOcElemFlags(cBody[9])
|
||||
|
||||
result += '''
|
||||
{{
|
||||
{0},
|
||||
@@ -100,10 +269,10 @@ def GetItems(data, off, count, structf, fmt, size):
|
||||
}},'''.format(f_ColliderBodyInit.format(*cBody), fmt.format(*cItem))
|
||||
return result
|
||||
|
||||
def GetJntSphItems(data, off, count):
|
||||
items = GetItems(data, off, count, sf_JntSphItem, f_JntSphItem, 0x24)
|
||||
print('''
|
||||
static ColliderJntSphItemInit sJntSphItemsInit[{0}] = {{{1}
|
||||
def GetJntSphElements(data, off, count):
|
||||
items = GetItems(data, off, count, sf_JntSphElement, f_JntSphElement, 0x24)
|
||||
return('''
|
||||
static ColliderJntSphElementInit sJntSphElementsInit[{0}] = {{{1}
|
||||
}};
|
||||
'''.format(count, items))
|
||||
|
||||
@@ -111,79 +280,147 @@ def GetJntSph(data, off, type):
|
||||
sBase = GetColliderStr(data, off, type)
|
||||
cJntSph = struct.unpack_from(sf_JntSph, data, off + 8)
|
||||
|
||||
print('''
|
||||
static ColliderJntSphInit{0} sJntSphInit =
|
||||
{{
|
||||
return('''
|
||||
static ColliderJntSphInit{0} sJntSphInit = {{
|
||||
{1},
|
||||
{2},
|
||||
}};
|
||||
'''.format(type, sBase, f_JntSph.format(*cJntSph)))
|
||||
'''.format(type, sBase, f_JntSph.format(*cJntSph)))
|
||||
|
||||
|
||||
def GetTrisItems(data, off, count):
|
||||
items = GetItems(data, off, count, sf_TrisItem, f_TrisItem, 0x3C)
|
||||
print('''
|
||||
static ColliderTrisItemInit sTrisItemsInit[{0}] = {{{1}
|
||||
def GetTrisElements(data, off, count):
|
||||
items = GetItems(data, off, count, sf_TrisElement, f_TrisElement, 0x3C)
|
||||
return('''
|
||||
static ColliderTrisElementInit sTrisElementsInit[{0}] = {{{1}
|
||||
}};
|
||||
'''.format(count, items))
|
||||
|
||||
|
||||
def GetCylinder(data, off, type):
|
||||
sBase = GetColliderStr(data, off, type)
|
||||
cBody = struct.unpack_from(sf_ColliderBodyInit, data, off + 0x08)
|
||||
cBody = list(struct.unpack_from(sf_ColliderBodyInit, data, off + 0x08))
|
||||
cCyl16 = struct.unpack_from(sf_Cylinder16, data, off + 0x20)
|
||||
|
||||
print('''
|
||||
static ColliderCylinderInit{0} sCylinderInit =
|
||||
{{
|
||||
if cBody[0] < 7:
|
||||
cBody[0] = ELEMTYPE_UNKENUM[cBody[0]]
|
||||
else:
|
||||
cBody[0] = '0x{0:02X}'.format(cBody[0])
|
||||
|
||||
cBody[7] = GetToucherFlags(cBody[7])
|
||||
cBody[8] = GetBumperFlags(cBody[8])
|
||||
cBody[9] = GetOcElemFlags(cBody[9])
|
||||
|
||||
return('''
|
||||
static ColliderCylinderInit{0} sCylinderInit = {{
|
||||
{1},
|
||||
{2},
|
||||
{3},
|
||||
}};
|
||||
'''.format(type, sBase, f_ColliderBodyInit.format(*cBody),f_Cylinder16.format(*cCyl16)))
|
||||
'''.format(type,sBase,f_ColliderBodyInit.format(*cBody),f_Cylinder16.format(*cCyl16)))
|
||||
|
||||
def GetTris(data, off, type):
|
||||
sBase = GetColliderStr(data, off, type)
|
||||
cTris = struct.unpack_from(sf_Tris, data, off + 8)
|
||||
|
||||
print('''
|
||||
static ColliderTrisInit{0} sTrisInit =
|
||||
{{
|
||||
return('''
|
||||
static ColliderTrisInit{0} sTrisInit = {{
|
||||
{1},
|
||||
{2},
|
||||
}};
|
||||
'''.format(type, sBase, f_Tris.format(*cTris)))
|
||||
'''.format(type, sBase, f_Tris.format(*cTris)))
|
||||
|
||||
def GetQuad(data, off, type):
|
||||
sBase = GetColliderStr(data, off, type)
|
||||
cBody = struct.unpack_from(sf_ColliderBodyInit, data, off + 0x08)
|
||||
cBody = list(struct.unpack_from(sf_ColliderBodyInit, data, off + 0x08))
|
||||
cQuad = struct.unpack_from(sf_Quad, data, off + 0x20)
|
||||
print('''
|
||||
static ColliderQuadInit{0} sQuadInit =
|
||||
{{
|
||||
|
||||
if cBody[0] < 7:
|
||||
cBody[0] = ELEMTYPE_UNKENUM[cBody[0]]
|
||||
else:
|
||||
cBody[0] = '0x{0:02X}'.format(cBody[0])
|
||||
|
||||
cBody[7] = GetToucherFlags(cBody[7])
|
||||
cBody[8] = GetBumperFlags(cBody[8])
|
||||
cBody[9] = GetOcElemFlags(cBody[9])
|
||||
|
||||
return('''
|
||||
static ColliderQuadInit{0} sQuadInit = {{
|
||||
{1},
|
||||
{2},
|
||||
{3},
|
||||
}};
|
||||
'''.format(type, sBase, f_ColliderBodyInit.format(*cBody), f_Quad.format(*cQuad)))
|
||||
'''.format(type, sBase, f_ColliderBodyInit.format(*cBody), f_Quad.format(*cQuad)))
|
||||
|
||||
TYPE_DICT = {
|
||||
'ColliderJntSphInit' : (GetJntSph, 'Shape', T_DEFAULT),
|
||||
'ColliderCylinderInit' : (GetCylinder, 'Shape', T_DEFAULT),
|
||||
'ColliderTrisInit': (GetTris, 'Shape', T_DEFAULT),
|
||||
'ColliderQuadInit': (GetQuad, 'Shape', T_DEFAULT),
|
||||
'ColliderJntSphItemInit' : (GetJntSphItems, 'Item'),
|
||||
'ColliderTrisItemInit' : (GetTrisItems, 'Item')
|
||||
}
|
||||
def GetColliderInit(address, type, num, path):
|
||||
TYPE_DICT = {
|
||||
'ColliderJntSphInit' : (GetJntSph, 'Shape', T_DEFAULT),
|
||||
'ColliderCylinderInit' : (GetCylinder, 'Shape', T_DEFAULT),
|
||||
'ColliderTrisInit': (GetTris, 'Shape', T_DEFAULT),
|
||||
'ColliderQuadInit': (GetQuad, 'Shape', T_DEFAULT),
|
||||
'ColliderJntSphElementInit' : (GetJntSphElements, 'Item'),
|
||||
'ColliderTrisElementInit' : (GetTrisElements, 'Item')
|
||||
}
|
||||
|
||||
update = [(k, v[0]) for k,v in TYPE_DICT.items() if v[1] == 'Shape']
|
||||
for i in update:
|
||||
for j in (TType1, T_ACTOR):
|
||||
TYPE_DICT[i[0] + j] = (i[1], 'Shape', j)
|
||||
|
||||
fileResult = None
|
||||
|
||||
if address >= 0x80000000:
|
||||
fileResult = GetFromVRam(address)
|
||||
else:
|
||||
fileResult = GetFromRom(address)
|
||||
|
||||
if fileResult is None:
|
||||
return("Invalid address")
|
||||
|
||||
print(fileResult)
|
||||
|
||||
selectedType = TYPE_DICT[type]
|
||||
arg2 = None
|
||||
if selectedType[1] == 'Shape':
|
||||
arg2 = selectedType[2]
|
||||
elif num > 0:
|
||||
arg2 = num
|
||||
else:
|
||||
return("ItemInit type must specify number of elements")
|
||||
|
||||
ovlFile = open(path + "/baserom/" + fileResult.name, "rb")
|
||||
ovlData = bytearray(ovlFile.read())
|
||||
ovlFile.close()
|
||||
|
||||
return selectedType[0](ovlData, fileResult.offset, arg2)
|
||||
|
||||
def GetColliderInitFull(address, type, num, path):
|
||||
if(type.find('Element') != -1):
|
||||
return GetColliderInit(address, type, num, path)
|
||||
|
||||
base = GetColliderInit(address, type, 0, path)
|
||||
|
||||
if(type.find('JntSph') != -1):
|
||||
[num, address2, dummy] = base.split('\n')[3].split(',')
|
||||
hexaddress = int(address2.strip(' D_'), 16)
|
||||
if(hexaddress == 0):
|
||||
return base.replace(address2,' NULL')
|
||||
else:
|
||||
elements = GetColliderInit(hexaddress, 'ColliderJntSphElementInit', int(num), path)
|
||||
return elements + base.replace(address2,' sJntSphElementsInit')
|
||||
elif(type.find('Tris') != -1):
|
||||
[num, address2, dummy] = base.split('\n')[3].split(',')
|
||||
hexaddress = int(address2.strip(' D_'), 16)
|
||||
if(hexaddress == 0):
|
||||
return base.replace(address2,' NULL')
|
||||
else:
|
||||
elements = GetColliderInit(hexaddress, 'ColliderTrisElementInit', int(num), path)
|
||||
return elements + base.replace(address2,' sTrisElementsInit')
|
||||
else:
|
||||
return base
|
||||
|
||||
update = [(k, v[0]) for k,v in TYPE_DICT.items() if v[1] == 'Shape']
|
||||
for i in update:
|
||||
for j in (T_SET3, T_ACTOR):
|
||||
TYPE_DICT[i[0] + j] = (i[1], 'Shape', j)
|
||||
|
||||
#ovlName = 'ovl_Obj_Comb'
|
||||
#address = 0x000780
|
||||
#inputType = 'ColliderJntSphItemInit'
|
||||
#address = 0x000780
|
||||
#inputType = 'ColliderJntSphElementInit'
|
||||
|
||||
#ovlName = 'ovl_En_Boom'
|
||||
#address = 0x0007D0
|
||||
@@ -201,33 +438,40 @@ parser.add_argument('num', nargs='?', default=0, type=HexParse, help="Number of
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
fileResult = None
|
||||
scriptDir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
if args.address >= 0x80000000:
|
||||
fileResult = GetFromVRam(args.address)
|
||||
else:
|
||||
fileResult = GetFromRom(args.address)
|
||||
repo = scriptDir + os.sep + ".." + os.sep + ".."
|
||||
|
||||
if fileResult is None:
|
||||
print("Invalid address")
|
||||
exit()
|
||||
print(GetColliderInitFull(args.address, args.type, args.num, repo))
|
||||
# print(GetColliderInit(args.address, args.type, args.num, "../.."))
|
||||
|
||||
print(fileResult)
|
||||
# fileResult = None
|
||||
|
||||
selectedType = TYPE_DICT[args.type]
|
||||
arg2 = None
|
||||
if selectedType[1] == 'Shape':
|
||||
arg2 = selectedType[2]
|
||||
elif args.num > 0:
|
||||
arg2 = args.num
|
||||
else:
|
||||
print("ItemInit type must specify number of elements")
|
||||
exit()
|
||||
# if args.address >= 0x80000000:
|
||||
# fileResult = GetFromVRam(args.address)
|
||||
# else:
|
||||
# fileResult = GetFromRom(args.address)
|
||||
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
# if fileResult is None:
|
||||
# print("Invalid address")
|
||||
# exit()
|
||||
|
||||
ovlFile = open(script_dir + "/../../baserom/" + fileResult.name, "rb")
|
||||
ovlData = bytearray(ovlFile.read())
|
||||
ovlFile.close()
|
||||
# print(fileResult)
|
||||
|
||||
selectedType[0](ovlData, fileResult.offset, arg2)
|
||||
# selectedType = TYPE_DICT[args.type]
|
||||
# arg2 = None
|
||||
# if selectedType[1] == 'Shape':
|
||||
# arg2 = selectedType[2]
|
||||
# elif args.num > 0:
|
||||
# arg2 = args.num
|
||||
# else:
|
||||
# print("ItemInit type must specify number of elements")
|
||||
# exit()
|
||||
|
||||
# script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
# ovlFile = open(script_dir + "/../../baserom/" + fileResult.name, "rb")
|
||||
# ovlData = bytearray(ovlFile.read())
|
||||
# ovlFile.close()
|
||||
|
||||
# selectedType[0](ovlData, fileResult.offset, arg2)
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import argparse
|
||||
from filemap import FileResult, GetFromVRam, GetFromRom
|
||||
|
||||
damage_types = [
|
||||
'Deku nut',
|
||||
'Deku stick',
|
||||
'Slingshot',
|
||||
'Explosive',
|
||||
'Boomerang',
|
||||
'Normal arrow',
|
||||
'Hammer swing',
|
||||
'Hookshot',
|
||||
'Kokiri sword',
|
||||
'Master sword',
|
||||
"Giant's Knife",
|
||||
'Fire arrow',
|
||||
'Ice arrow',
|
||||
'Light arrow',
|
||||
'Unk arrow 1',
|
||||
'Unk arrow 2',
|
||||
'Unk arrow 3',
|
||||
'Fire magic',
|
||||
'Ice magic',
|
||||
'Light magic',
|
||||
'Shield',
|
||||
'Mirror Ray',
|
||||
'Kokiri spin',
|
||||
'Giant spin',
|
||||
'Master spin',
|
||||
'Kokiri jump',
|
||||
'Giant jump',
|
||||
'Master jump',
|
||||
'Unknown 1',
|
||||
'Unblockable',
|
||||
'Hammer jump',
|
||||
'Unknown 2'
|
||||
]
|
||||
|
||||
def convert_dmg_table_str(dmg_table_str):
|
||||
split_data = dmg_table_str.replace(' ','').replace('\n','').replace('{',',').replace('}',',').split(',')
|
||||
hex_data = [int(x, 16) for x in split_data if '0x' in x]
|
||||
|
||||
name = dmg_table_str.split('=')[0].split()[-1]
|
||||
|
||||
return make_table(name, hex_data)
|
||||
|
||||
def replace_damage_table_all(repo):
|
||||
actors = 'src' + os.sep + 'overlays' + os.sep + 'actors'
|
||||
for subdir, dirs, files in os.walk(repo + os.sep + actors):
|
||||
for filename in files:
|
||||
if(filename.endswith('.c')):
|
||||
file = subdir + os.sep + filename
|
||||
status = replace_damage_table(file)
|
||||
if(status < 0):
|
||||
print('Encountered error in', file)
|
||||
elif(status > 0):
|
||||
print('Updated', status, 'table' + ('s' if status > 1 else ''), file)
|
||||
return 1
|
||||
|
||||
def replace_damage_table(src):
|
||||
with open(src, 'r', encoding = 'utf-8') as srcfile:
|
||||
srcdata = srcfile.readlines()
|
||||
read_table = False
|
||||
replacements = []
|
||||
|
||||
for i, line in enumerate(srcdata):
|
||||
if("DamageTable" in line and "= {" in line):
|
||||
if(read_table):
|
||||
print('Bad formatting in', file, 'at line', i)
|
||||
return -1
|
||||
else:
|
||||
read_table = True
|
||||
start = i
|
||||
|
||||
if(read_table and "DMG_" in line):
|
||||
read_table = False
|
||||
|
||||
if(read_table and ";" in line):
|
||||
dmg_table_str = "".join(srcdata[start:i+1])
|
||||
damage_table = convert_dmg_table_str(dmg_table_str)
|
||||
replacements += [[dmg_table_str, damage_table]]
|
||||
read_table = False
|
||||
|
||||
if len(replacements) == 0:
|
||||
return 0
|
||||
|
||||
with open(src,'r', encoding = 'utf-8') as srcfile:
|
||||
srcstr = srcfile.read()
|
||||
for replace in replacements:
|
||||
srcstr = srcstr.replace(replace[0], replace[1])
|
||||
with open(src,'w', encoding = 'utf-8', newline = '\n') as outfile:
|
||||
outfile.write(srcstr)
|
||||
return len(replacements)
|
||||
|
||||
def make_table(name, data):
|
||||
damage_table = "DamageTable " + name + " = {\n"
|
||||
linestart = " /* "
|
||||
padlen = max([len(x) for x in damage_types])
|
||||
for i, dbyte in enumerate(data):
|
||||
typestr = damage_types[i]
|
||||
typestr += ' ' * (padlen - len(typestr)) + ' */ '
|
||||
damage_table += linestart + typestr + format_damage_byte(dbyte)
|
||||
damage_table += '};\n'
|
||||
|
||||
return damage_table
|
||||
|
||||
def format_damage_byte(dbyte):
|
||||
effect = (dbyte >> 4) & 0xF
|
||||
damage = dbyte & 0xF
|
||||
|
||||
effstr = format(effect, 'X')
|
||||
dstr = str(damage)
|
||||
|
||||
dtentry = 'DMG_ENTRY(' + dstr + ' , 0x' + effstr + '),\n'
|
||||
|
||||
return dtentry
|
||||
|
||||
def get_damage_bytes(address, repo):
|
||||
file_result = None
|
||||
|
||||
if address >= 0x80000000:
|
||||
file_result = GetFromVRam(address)
|
||||
else:
|
||||
file_result = GetFromRom(address)
|
||||
|
||||
if file_result is None:
|
||||
print("Invalid address")
|
||||
exit()
|
||||
|
||||
print(file_result)
|
||||
|
||||
with open(repo + os.sep + "baserom" + os.sep + file_result.name, "rb") as ovl_file:
|
||||
ovl_data = bytearray(ovl_file.read())
|
||||
|
||||
damage_data = ovl_data[file_result.offset:file_result.offset+0x20]
|
||||
|
||||
damage_table = make_table('D_' + format(address, 'X'), damage_data)
|
||||
|
||||
return damage_table
|
||||
|
||||
def hex_parse(s):
|
||||
return int(s, 16)
|
||||
|
||||
parser = argparse.ArgumentParser(description = "Converts raw bytes into a formatted damage table")
|
||||
parser.add_argument('-a', metavar='address', dest='address', help="VRam or Rom address of the damage table", type=hex_parse)
|
||||
parser.add_argument('-f', metavar='file', dest='file', help='C file with unformatted damage tables')
|
||||
|
||||
if __name__ == "__main__":
|
||||
args = parser.parse_args()
|
||||
script_dir = os.path.dirname(os.path.realpath(__file__))
|
||||
repo = script_dir + os.sep + ".." + os.sep + ".."
|
||||
if(args.address):
|
||||
print(get_damage_bytes(args.address, repo))
|
||||
elif(args.file):
|
||||
replace_damage_table(args.file)
|
||||
else:
|
||||
print('Error: address or file required. Use -h for more detail.')
|
||||
Reference in New Issue
Block a user