-
Notifications
You must be signed in to change notification settings - Fork 11
Expand file tree
/
Copy pathbuild_modded.py
More file actions
99 lines (78 loc) · 3.7 KB
/
build_modded.py
File metadata and controls
99 lines (78 loc) · 3.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/usr/bin/env python3
# Build script using DTK split objects for shiftability
import argparse
import subprocess
import sys
from pathlib import Path
import json
sys.path.append('tools')
from build_dol import build_dol
from build_rel import build_rel
from color_term import *
from project_settings import *
parser = argparse.ArgumentParser(description='Builds the game executables using DTK split object for shiftability.')
parser.add_argument('-v', help='Prints commands for debugging', action='store_true')
parser.add_argument('--game_folder', type=Path, help='Path to the root of the extracted ISO (will replace main.dol and the REL files)')
args = parser.parse_args()
def exec_cmd(*nargs, **kwargs):
global args
if args.v:
print(*nargs, **kwargs)
out = subprocess.run(*nargs, **kwargs)
if out.returncode != 0:
sys.exit(out.returncode)
Path(f'{BUILDDIR}/mod').mkdir(parents=True, exist_ok=True)
config_json = json.loads(open(BUILDDIR / 'dtkspl/config.json').read())
# Builds the main elf
def build_main(module_name, ldscript, units):
ldflags = '-proc gekko -fp hard'
out_file = f'mod/{module_name}'
file_names = []
for unit in units:
if unit['autogenerated']:
file_names.append(unit['object'])
else:
o_file = Path(f'{BUILDDIR}/compiled/{module_name}/{unit['name']}').with_suffix('.o')
file_names.append(o_file)
cmd = [] if sys.platform == 'win32' else ['wine']
cmd.extend([LD, *ldflags.split(' '), *file_names, '-lcf', ldscript, '-o', BUILDDIR / (out_file + '.elf')])
exec_cmd(cmd)
print_success(f'Linked {module_name}.elf.')
# Builds a module plf
def build_module_plf(module_name, ldscript, units):
ldflags = '-proc gekko -fp hard -sdata 0 -sdata2 0 -m _prolog -r1 -strip_partial'
out_file = f'mod/{module_name}'
out_plf = BUILDDIR / (out_file + '.plf')
file_names: list[Path] = []
for unit in units:
if unit['autogenerated']:
file_names.append(Path(unit['object']))
else:
o_file = Path(f'{BUILDDIR}/compiled/{module_name}/{unit['name']}').with_suffix('.o')
file_names.append(o_file)
cmd = [] if sys.platform == 'win32' else ['wine']
cmd.extend([LD, *ldflags.split(' '), *file_names, '-lcf', ldscript, '-o', out_plf])
exec_cmd(cmd)
print_success(f'Linked {module_name}.plf.')
modules = [BUILDDIR / f'mod/{config_json['name']}.elf', *[BUILDDIR / f'mod/{x['name']}.plf' for x in config_json['modules']]]
build_main(config_json['name'], config_json['ldscript'], config_json['units'])
for mods in config_json['modules']:
build_module_plf(mods['name'], Path(mods['ldscript']), mods['units'])
# Convert into Wii-specific file formats
dol_out_dir = (args.game_folder / 'sys') if args.game_folder else BUILDDIR / 'mod'
str_out_dir = (args.game_folder / 'files') if args.game_folder else BUILDDIR / 'mod'
rel_out_dir = (args.game_folder / 'files/rels') if args.game_folder else BUILDDIR / 'mod'
out_rel_names = [rel_out_dir / x.with_suffix('.plf').name for x in modules[1:]]
str_path = str_out_dir / f'{config_json['name']}.str'
str_path.write_bytes(b'\0'.join(str(p).replace('/', '\\').encode() for p in out_rel_names))
build_dol(BUILDDIR / 'mod' / (config_json['name'] + '.elf'), dol_out_dir / 'main.dol')
print_success('Built main.dol.')
for mod in config_json['modules']:
build_rel(modules[0], modules[1:], rel_out_dir / (mod['name'] + '.rel'), str_path)
print_success(f'Built {mod['name']}.rel.')
# Rename the old RELs from the game folder
if args.game_folder:
for mod in modules[1:]:
file: Path = args.game_folder / 'files/rels' / mod.with_suffix('.rel.LZ').name
if file.exists():
file.rename(file.with_suffix('.LZ.orig'))