# Part of the Fifteen-Thieves Project
# Chris Xiong 2020
# License: Expat (MIT)
import sys
import xv.util
import xv.amap
wavenames = ['None']
def dfs_checkpopulated(node):
node.populated = False
for ch in node.children_nodes:
if node.template.is_aggregate_node:
if type(ch) == list:
for el in ch:
node.populated |= dfs_checkpopulated(el)
else:
node.populated |= dfs_checkpopulated(ch)
else:
for a in node.get_data():
if a != 0xff:
node.populated = True
break
return node.populated
def dfs_print(node, level=0, instance=None):
if not node.populated:
return
ba_rep = ''.join([format(x, "02x") for x in xv.util.padbelist(xv.util.int2b7belist(node.base_address))])
print(f"{ba_rep}{level*' '} {node.template.name}{'['+str(instance)+']' if instance is not None else ''}")
for child in node.children_nodes:
if node.template.is_aggregate_node:
if type(child) == list:
for i, element in enumerate(child):
dfs_print(element, level + 1, i)
else:
dfs_print(child, level + 1)
else:
if type(child) == list:
if child[0].name == "name":
print(f"{ba_rep}{(level + 1)*' '} {child[0].name} {node.data[child[0].offset:child[0].offset + 12].decode()}")
else:
for i, element in enumerate(child):
ba_rep = ''.join([format(x, "02x") for x in xv.util.padbelist(xv.util.int2b7belist(element.offset))])
print(f"{ba_rep}{(level + 1)*' '} {element.name}[{i}] {xv.amap.get_leaf_data(node.data, element)}")
else:
ba_rep = ''.join([format(x, "02x") for x in xv.util.padbelist(xv.util.int2b7belist(child.offset))])
if child.name.startswith("wave_number"):
try:
print(f"{ba_rep}{(level + 1)*' '} {child.name} {xv.amap.get_leaf_data(node.data, child)}: {wavenames[xv.amap.get_leaf_data(node.data, child)]}")
except IndexError:
print(f"{ba_rep}{(level + 1)*' '} {child.name} {xv.amap.get_leaf_data(node.data, child)}: unknown")
else:
print(f"{ba_rep}{(level + 1)*' '} {child.name} {xv.amap.get_leaf_data(node.data, child)}")
if __name__ == "__main__":
if len(sys.argv) < 2:
print(f"Usage: {sys.argv[0]} <memoryregion file>")
print("loading address mapping...", flush=True, file=sys.stderr)
m = xv.amap.AddrMapTemplate("amaps/sd-80.amap")
t = xv.amap.create_addr_map_tree(m)
t.data[:] = [0xff for i in range(0, len(t.data))]
print("loading wave names...", file=sys.stderr)
with open("data/sdwavelist","r") as f:
for l in f:
wavenames += [l.split('\t')[1].strip()]
print("loading memoryregion...", file=sys.stderr)
mr = xv.util.load_memoryregion(sys.argv[1])
for addr, data in mr:
ra = xv.util.b7belist2int(addr)
t.data[ra:ra + len(data)] = data
dfs_checkpopulated(t)
dfs_print(t)