Skip to content

Commit f591d89

Browse files
committed
Some tooling to extract assets
Run: restool.py decode to extract assets into assets/defs/* Run: restool.py compile to compile the assets back into a rom
1 parent 9680714 commit f591d89

33 files changed

+23357
-565
lines changed

assets/.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
/__pycache__/
2+
/defs/*
3+
/out.bin
4+
/out_is_set.bin

assets/animtiles_decode.py

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
from decode_common import *
2+
3+
BANK = 0x87
4+
5+
kInstructionSet = {
6+
0x8780b2: ('Delete', ''),
7+
0x8780b7: ('Goto', 'G'),
8+
0x87813f: ('GotoIfEventHappened', 'HG'),
9+
0x878150: ('SetEventHappened', 'H'),
10+
0x8781ba: ('WaitUntilAreaBossDead_DoubleRet', ''),
11+
0x878303: ('GotoIfBossBitSetInArea', 'BBG'),
12+
0x878320: ('SpawnTourianStatueEyeGlow', 'H'),
13+
0x87832f: ('SpawnTourianStatueSoul', 'H'),
14+
0x87833e: ('GotoIfTourianStatueBusy', 'G'),
15+
0x878349: ('TourianStatueSetState', 'H'),
16+
0x878352: ('TourianStatueClearState', 'H'),
17+
0x87835b: ('Clear3PaletteColors', 'H'),
18+
0x878372: ('SpawnPalfxObj', 'H'),
19+
0x87837f: ('Write8PaletteColors', 'H'),
20+
}
21+
22+
kCommandByName = {v[0] : (k, v[1]) for k, v in kInstructionSet.items()}
23+
24+
class AnimtilesParser(InstrParserCommon):
25+
instruction_set = kInstructionSet
26+
instruction_set_term = {0x8780b7, 0x8780b2}
27+
TAG = 'animtiles'
28+
29+
def __init__(self):
30+
super().__init__()
31+
self.current_array_size = None
32+
33+
def handle_draw_command(self, ins, ea):
34+
drawp = get_word(ea + 2) | (BANK << 16)
35+
assert self.current_array_size != None
36+
self.blobs[drawp] = self.current_array_size
37+
self.print_line(ea, f' {ins} ! {get_ea_name(drawp)}')
38+
return 4
39+
40+
def visit(self, ea, cur_size = None):
41+
if cur_size == None:
42+
super().visit(ea)
43+
return
44+
self.current_array_size = cur_size
45+
super().visit(ea)
46+
self.process_queue(final = False)
47+
48+
def process_queue_entry(self, ea):
49+
assert ea & 0x8000
50+
while ea not in self.visited:
51+
self.visited.add(ea)
52+
ins = get_word(ea)
53+
if ins & 0x8000:
54+
ea_org = ea
55+
ins = (BANK << 16) | ins
56+
if ins not in self.instruction_set:
57+
raise Exception(f'Ins {ins:X} not in iset at {ea:X}')
58+
name, operands = self.instruction_set[ins]
59+
ea += 2
60+
r = []
61+
for op in operands:
62+
if op == 'B':
63+
r.append('%d' % get_byte(ea))
64+
ea += 1
65+
elif op == 'H':
66+
r.append('%d' % get_word(ea))
67+
ea += 2
68+
elif op == 'G':
69+
addr = (BANK << 16) | get_word(ea)
70+
r.append(get_ea_name(addr, short_label=True))
71+
self.visit(addr)
72+
ea += 2
73+
else:
74+
assert 0
75+
self.print_line(ea_org, f' {name}({", ".join(r)})')
76+
if ins in self.instruction_set_term:
77+
self.print_line(ea_org + 1, '')
78+
break
79+
else:
80+
ea += self.handle_draw_command(ins, ea)

0 commit comments

Comments
 (0)