Skip to content

Commit ce7f7ce

Browse files
committed
add codeflow script
1 parent c5ef533 commit ce7f7ce

File tree

6 files changed

+547340
-0
lines changed

6 files changed

+547340
-0
lines changed

rewrite/README.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,8 @@ This folder is an ongoing decompilation project for the PSX game Crash Team Raci
88

99
`src/tests/`: tests for each decompiled function.
1010

11+
`scripts/`: helpful misc scripts.
12+
1113
`../include/ctr/`: decompile headers.
1214

1315
`../symbols/gcc-syms-rewrite.txt`: original function addresses.

rewrite/scripts/codeflow/asm.py

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
from symbols import Syms, RAM_BASE
2+
3+
class ASMInstruction:
4+
def __init__(self, line: str, sym: Syms) -> None:
5+
self.failed_decoding = False
6+
try:
7+
self.return_address = int("0x" + line[0][:8], 0) + 8
8+
except Exception:
9+
self.failed_decoding = True
10+
return
11+
self.sym = sym
12+
self.instruction = line[2]
13+
self.destination = line[3]
14+
switch = {
15+
"jal" : self.case_jal,
16+
"jalr" : self.case_jalr,
17+
"jr" : self.case_jr
18+
}
19+
self.symbol = None
20+
self.has_returned = False
21+
self.returning = False
22+
self.func_call = False
23+
if self.instruction in switch:
24+
switch[self.instruction]()
25+
self.func_call = True
26+
27+
def case_jal(self):
28+
self.destination = int(self.destination[:10], 0)
29+
self.symbol = self.sym.get_symbol(self.destination)
30+
if self.symbol is None:
31+
name = str()
32+
if self.destination < RAM_BASE:
33+
name = "0" + hex(self.destination + RAM_BASE)[3:]
34+
else:
35+
name = hex(self.destination)[2:]
36+
self.symbol = "FUN_" + name
37+
38+
def case_jalr(self):
39+
self.destination = int("0x" + self.destination[4:12], 0)
40+
self.symbol = self.sym.get_symbol(self.destination)
41+
if self.symbol is None:
42+
name = str()
43+
if self.destination < RAM_BASE:
44+
name = "0" + hex(self.destination + RAM_BASE)[3:]
45+
else:
46+
name = hex(self.destination)[2:]
47+
self.symbol = "FUN_" + name
48+
49+
def case_jr(self):
50+
self.destination = int("0x" + self.destination[4:12], 0)
51+
self.returning = True
52+
53+
class ASMAnalyzer:
54+
def __init__(self, sym: Syms, output: str, space_size: int) -> None:
55+
self.sym = sym
56+
self.output = output
57+
self.space_size = space_size
58+
59+
def analyze_log(self, log: str, start_label: str) -> None:
60+
output = open(self.output, "w")
61+
buffer = start_label + "()\n"
62+
curr_spacing = self.space_size
63+
possible_func_calls = []
64+
with open(log, "r") as file:
65+
for line in file:
66+
line = line.split()
67+
if len(line) < 4:
68+
continue
69+
instruction = ASMInstruction(line, self.sym)
70+
if instruction.failed_decoding:
71+
continue
72+
if instruction.returning:
73+
for i in range(len(possible_func_calls) - 1, -1, -1):
74+
func_call = possible_func_calls[i][0]
75+
if (not func_call.has_returned) and (func_call.return_address == instruction.destination):
76+
possible_func_calls[i][0].has_returned = True
77+
curr_spacing = possible_func_calls[i][1]
78+
elif instruction.func_call:
79+
possible_func_calls.append([instruction, curr_spacing])
80+
curr_spacing += self.space_size
81+
82+
for pfc in possible_func_calls:
83+
func_call = pfc[0]
84+
if func_call.has_returned:
85+
spacing = pfc[1]
86+
buffer += (" " * spacing) + func_call.symbol + "()\n"
87+
88+
output.write(buffer)
89+
output.close()

0 commit comments

Comments
 (0)