Skip to content

Commit c137bf1

Browse files
Solution to build most splits using SN alternative assembler
Now most of the project splits can be built using the actual assembler used by the game by passing `-sn_as/--sn_assembler` on `configure.py` when building the game as matching, also capped Spimdisasm version as last version broke matching building for some reason As always big shout out to the big @Mc-muffin for helping with this solution
1 parent 95b7f40 commit c137bf1

4 files changed

Lines changed: 127 additions & 12 deletions

File tree

configs/sym.txt

Lines changed: 36 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,41 @@ D_0045345C = 0x0045345c; // type:s32
66
D_004534C8 = 0x004534c8; // type:s32
77
D_004534CC = 0x004534cc; // type:s32 size:8
88
D_004537F0 = 0x004537f0; // type:s32
9+
D_00453282 = 0x00453282;
10+
D_00453284 = 0x00453284;
11+
D_00453286 = 0x00453286;
12+
D_00453288 = 0x00453288;
13+
D_0045328A = 0x0045328A;
14+
D_0045328C = 0x0045328C;
15+
D_0045328E = 0x0045328E;
16+
17+
18+
func_001F9CD0 = 0x001F9CD0; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
19+
func_00234A28 = 0x00234A28; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
20+
func_00147650 = 0x00147650; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
21+
func_00110A08 = 0x00110A08; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
22+
func_001134A0 = 0x001134A0; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
23+
func_00113B10 = 0x00113B10; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
24+
func_00116250 = 0x00116250; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
25+
func_0017A110 = 0x0017A110; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
26+
func_00131970 = 0x00131970; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
27+
func_00169B38 = 0x00169B38; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
28+
func_001E86F8 = 0x001E86F8; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
29+
func_00104DA0 = 0x00104DA0; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
30+
func_0017EBF8 = 0x0017EBF8; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
31+
func_002EAD28 = 0x002EAD28; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
32+
func_002EA480 = 0x002EA480; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
33+
func_002EBFC8 = 0x002EBFC8; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
34+
func_002EB508 = 0x002EB508; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
35+
func_002EB958 = 0x002EB958; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
36+
func_002E3E60 = 0x002E3E60; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
37+
func_002E1680 = 0x002E1680; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
38+
func_002886B0 = 0x002886B0; // note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
39+
40+
41+
42+
43+
944

1045
// Functions
1146
entry = 0x00100008; // type:func
@@ -1377,7 +1412,7 @@ _$_14LegIKAnimation = 0x002E15B8; // type:func
13771412
_$_21IKSingleStepAnimation = 0x002E27E8; // type:func
13781413
_$_17IKAmblerAnimation = 0x002E3C78; // type:func
13791414
_$_17TurnFlexAnimation = 0x002E5550; // type:func
1380-
func_002E55A8__17TurnFlexAnimation = 0x002E55A8; // type:func
1415+
func_002E55A8__17TurnFlexAnimation = 0x002E55A8; // type:func note - function noted in `PROBLEMATIC_FUNCS` list at `configure.py`
13811416
__tf19WalkingBobAnimation = 0x002e5e70;
13821417
__tf22WalkingParamsAnimation = 0x002E5F20;
13831418
_$_23AnimVarWalkingAnimation = 0x002E5F70; // type:func

configure.py

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,13 @@
7070
"src/text_00310BE8.cpp"
7171
]
7272

73+
UNCOMPATIBLE_SN_AS_SPLITS = [
74+
"src/text_002421F8.cpp",
75+
"src/text_0031FC50.cpp",
76+
"src/text_00330930.cpp",
77+
"src/text_00334BD0.cpp"
78+
]
79+
7380
COMPLETED_SPLITS = [
7481
]
7582

@@ -96,7 +103,7 @@ def clean():
96103
shutil.rmtree("target", ignore_errors=True)
97104
shutil.rmtree(BUILD_DIR, ignore_errors=True)
98105

99-
def ninja_build(linker_entries: List[LinkerEntry], objdiff_mode: bool, skip_checksum: bool):
106+
def ninja_build(linker_entries: List[LinkerEntry], objdiff_mode: bool, skip_checksum: bool, use_sn_as: bool = False):
100107

101108
if objdiff_mode:
102109
ninja_file = ninja_syntax.Writer(open("matching.ninja", "w", encoding="utf-8"), width=9999)
@@ -168,10 +175,17 @@ def ninja_build(linker_entries: List[LinkerEntry], objdiff_mode: bool, skip_chec
168175

169176
split_state = ""
170177

171-
for split in COMPLETED_SPLITS:
172-
if split == str(entry.src_paths[0]):
173-
split_state = "-snas"
174-
break
178+
if use_sn_as:
179+
split_state = "-snas"
180+
for split in UNCOMPATIBLE_SN_AS_SPLITS:
181+
if split == str(entry.src_paths[0]):
182+
split_state = ""
183+
break
184+
else:
185+
for split in COMPLETED_SPLITS:
186+
if split == str(entry.src_paths[0]):
187+
split_state = "-snas"
188+
break
175189

176190
# Matching file
177191
match seg.type:
@@ -279,6 +293,58 @@ def ninja_build(linker_entries: List[LinkerEntry], objdiff_mode: bool, skip_chec
279293
else:
280294
print("Skipping checksum step")
281295

296+
COMMENT_PART = r"\/\* (.+) ([0-9A-Z]{2})([0-9A-Z]{2})([0-9A-Z]{2})([0-9A-Z]{2}) \*\/"
297+
INSTRUCTION_PART = r"(\b(vadda\.xyz)\b.*)"
298+
OPCODE_PATTERN = re.compile(f"{COMMENT_PART} {INSTRUCTION_PART}")
299+
300+
PROBLEMATIC_FUNCS = {
301+
"func_001F9CD0",
302+
"func_00234A28",
303+
"func_00147650",
304+
"func_00110A08",
305+
"func_001134A0",
306+
"func_00113B10",
307+
"func_00116250",
308+
"func_0017A110",
309+
"func_00131970",
310+
"func_00169B38",
311+
"func_001E86F8",
312+
"func_00104DA0",
313+
"func_0017EBF8",
314+
"func_002EAD28",
315+
"func_002EA480",
316+
"func_002EBFC8",
317+
"func_002EB508",
318+
"func_002EB958",
319+
"func_002E55A8__17TurnFlexAnimation",
320+
"func_002E3E60",
321+
"func_002E1680",
322+
"func_002886B0"
323+
}
324+
325+
def replace_instructions_with_opcodes(asm_folder: Path) -> None:
326+
nm_folder = ROOT / asm_folder / "nonmatchings"
327+
for p in nm_folder.rglob("*.s"):
328+
329+
if p.stem not in PROBLEMATIC_FUNCS:
330+
continue
331+
332+
with p.open("r") as file:
333+
content = file.read()
334+
335+
if re.search(OPCODE_PATTERN, content):
336+
# Reference found
337+
# Embed the opcode, we have to swap byte order for correct endianness
338+
content = re.sub(
339+
OPCODE_PATTERN,
340+
r"/* \1 \2\3\4\5 */ .word 0x\5\4\3\2 /* \6 */",
341+
content,
342+
)
343+
344+
# Write the updated content back to the file
345+
with p.open("w") as file:
346+
file.write(content)
347+
282348
def main():
283349
parser = argparse.ArgumentParser(description="Configure the project")
284350
parser.add_argument(
@@ -299,6 +365,12 @@ def main():
299365
help="Skip the checksum step",
300366
action="store_true",
301367
)
368+
parser.add_argument(
369+
"-sn_as",
370+
"--sn_assembler",
371+
help="Build the entire game and engine using the alternative SN Assembler",
372+
action="store_true",
373+
)
302374
parser.add_argument(
303375
"-diff",
304376
"--objdiff",
@@ -310,6 +382,7 @@ def main():
310382
do_clean = (args.clean or args.clean_only) or False
311383
do_skip_checksum = args.skip_checksum or False
312384
do_objects = args.objdiff or False
385+
use_sn_as = args.sn_assembler or False
313386

314387
if do_clean:
315388
clean()
@@ -319,11 +392,13 @@ def main():
319392

320393
split.main([YAML_FILE], modes="all", verbose=False, disassemble_all=True, make_full_disasm_for_code=do_objects)
321394

322-
ninja_build(split.linker_writer.entries, do_objects, do_skip_checksum)
395+
ninja_build(split.linker_writer.entries, do_objects, do_skip_checksum, use_sn_as)
323396

324397
if do_objects:
325398
subprocess.call(["ninja", "-f", "objdiff.ninja"])
326399

400+
if use_sn_as:
401+
replace_instructions_with_opcodes(split.config["options"]["asm_path"])
327402

328403
if __name__ == "__main__":
329404
main()

include/labels.inc

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,10 @@
11
# This file is used by the original compiler/assembler.
22
# Defines the expected assembly macros.
33

4+
.macro c1 label
5+
cop1 \label
6+
.endm
7+
48
# A function symbol.
59
.macro glabel label, visibility=global
610
.\visibility \label
@@ -11,7 +15,7 @@
1115

1216
# The end of a function symbol.
1317
.macro endlabel label
14-
.size \label, . - \label
18+
#.size \label, . - \label
1519
.end \label
1620
.endm
1721

@@ -51,8 +55,8 @@
5155

5256
# Label to signal the symbol haven't been matched yet.
5357
.macro nonmatching label, size=1
54-
.global \label\().NON_MATCHING
55-
.type \label\().NON_MATCHING, @object
56-
.size \label\().NON_MATCHING, \size
57-
\label\().NON_MATCHING:
58+
#.global \label\().NON_MATCHING
59+
#.type \label\().NON_MATCHING, @object
60+
#.size \label\().NON_MATCHING, \size
61+
#\label\().NON_MATCHING:
5862
.endm

requirements.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
spimdisasm<1.40.1
12
splat64[mips]>=0.37.1,<1.0.0
23
ninja
34
ninja_syntax

0 commit comments

Comments
 (0)