Skip to content

Commit 2a08381

Browse files
committed
Allow IDO 7.1 to be used for certain files
1 parent 23e3721 commit 2a08381

File tree

2 files changed

+61
-27
lines changed

2 files changed

+61
-27
lines changed

docs/Guide.md

+4-1
Original file line numberDiff line numberDiff line change
@@ -355,10 +355,13 @@ The flag combinations currently known for the decomp are:
355355
- `-O2 -g3` - The default. Used for almost everything.
356356
- `-O2 -g0` - Used for compiling *modified* libultra code.
357357
- `-O1 -g0` - Used for compiling *unmodified* libultra code.
358+
- `-O1 -g2` - Used for libnaudio code.
358359

359360
Sometimes, to get a function to match you will need to change the optimization and debugging levels that the containing file is compiled with. This can be done by adding the comment `// @DECOMP_OPT_FLAGS=<opt flags>` to the top of the file. For example, `// @DECOMP_OPT_FLAGS=-O1` would compile the file with the optimization flag `-O1` instead of the default.
360361

361-
> Note: The build script must be re-configured for the new optimization flags to take effect (`./dino.py configure`).
362+
Additionally, you may need a different version of IDO. This can be set by adding the comment `// @DECOMP_IDO_VERSION=<version>` to the top of the file. Only versions `5.3` (default) and `7.1` are available currently.
363+
364+
> Note: The build script must be re-configured for the new optimization flags/compiler to take effect (`./dino.py configure`).
362365

363366

364367
## 6. DLL Decompilation

tools/configure.py

+57-26
Original file line numberDiff line numberDiff line change
@@ -20,18 +20,29 @@
2020
SCRIPT_DIR = Path(os.path.dirname(os.path.realpath(__file__)))
2121

2222
opt_flags_pattern = re.compile(r"@DECOMP_OPT_FLAGS\s*=\s*(.*)\s*")
23+
ido_version_pattern = re.compile(r"@DECOMP_IDO_VERSION\s*=\s*(.*)\s*")
24+
25+
IDO_VAR_MAP = {
26+
"5.3": "$IDO_53",
27+
"7.1": "$IDO_71"
28+
}
29+
30+
class BuildFileConfig:
31+
def __init__(self, opt: "str | None", ido_version: "str | None"):
32+
self.opt = opt
33+
self.ido_version = ido_version
2334

2435
class BuildFileType(Enum):
2536
C = 1
2637
ASM = 2
2738
BIN = 3
2839

2940
class BuildFile:
30-
def __init__(self, src_path: str, obj_path: str, type: BuildFileType, opt: "str | None"=None):
41+
def __init__(self, src_path: str, obj_path: str, type: BuildFileType, config: BuildFileConfig | None=None):
3142
self.src_path = src_path
3243
self.obj_path = obj_path
3344
self.type = type
34-
self.opt = opt
45+
self.config = config
3546

3647
class DLL:
3748
def __init__(self, number: str, dir: str, files: "list[BuildFile]"):
@@ -178,19 +189,17 @@ def __write_prelude(self):
178189
# Write tools
179190
cross = self.__detect_cross()
180191
exe_suffix = ".exe" if sys.platform == "win32" else ""
192+
ido_recomp_platform = "windows" if sys.platform == "win32" else "linux"
181193

182194
self.writer.comment("Tools")
183195
self.writer.variable("AS", f"{cross}as{exe_suffix}")
184196
self.writer.variable("LD", f"{cross}ld{exe_suffix}")
185197
self.writer.variable("OBJCOPY", f"{cross}objcopy{exe_suffix}")
186-
if sys.platform == "win32":
187-
self.writer.variable("CC", "tools/ido_recomp/windows/5.3/cc.exe")
188-
else:
189-
self.writer.variable("CC", "tools/ido_recomp/linux/5.3/cc")
198+
self.writer.variable("IDO_53", f"tools/ido_recomp/{ido_recomp_platform}/5.3/cc{exe_suffix}")
199+
self.writer.variable("IDO_71", f"tools/ido_recomp/{ido_recomp_platform}/7.1/cc{exe_suffix}")
200+
self.writer.variable("CC", "$IDO_53")
190201
self.writer.variable("ASM_PROCESSOR", "python3 tools/asm_processor/build.py")
191202
self.writer.variable("HEADER_DEPS", "python3 tools/header_deps.py")
192-
self.writer.variable("CC_PREPROCESSED", "$ASM_PROCESSOR $CC -- $AS $AS_FLAGS --")
193-
self.writer.variable("CC_PREPROCESSED_DLL", "$ASM_PROCESSOR $CC -- $AS $AS_FLAGS_DLL --")
194203
self.writer.variable("ELF2DLL", "python3 tools/elf2dll.py")
195204
self.writer.variable("DINODLL", "python3 tools/dino_dll.py")
196205

@@ -199,11 +208,11 @@ def __write_prelude(self):
199208
# Write rules
200209
self.writer.comment("Rules")
201210
self.writer.rule("cc",
202-
"$HEADER_DEPS $CC_PREPROCESSED -c $CC_FLAGS $OPT_FLAGS -o $out $in",
211+
"$HEADER_DEPS $ASM_PROCESSOR $CC -- $AS $AS_FLAGS -- -c $CC_FLAGS $OPT_FLAGS -o $out $in",
203212
"Compiling $in...",
204213
depfile="$out.d")
205214
self.writer.rule("cc_dll",
206-
"$HEADER_DEPS $CC_PREPROCESSED_DLL -c $CC_FLAGS_DLL $OPT_FLAGS -o $out $in",
215+
"$HEADER_DEPS $ASM_PROCESSOR $CC -- $AS $AS_FLAGS_DLL -- -c $CC_FLAGS_DLL $OPT_FLAGS -o $out $in",
207216
"Compiling $in...",
208217
depfile="$out.d")
209218
self.writer.rule("as", "$AS $AS_FLAGS -o $out $in", "Assembling $in...")
@@ -231,10 +240,7 @@ def __write_file_builds(self):
231240

232241
for file in self.input.files:
233242
# Determine variables
234-
variables: dict[str, str] = {}
235-
opt = file.opt
236-
if opt is not None and opt != self.config.default_opt_flags:
237-
variables["OPT_FLAGS"] = opt
243+
variables: dict[str, str] = self.__file_config_to_variables(file.config)
238244

239245
# Determine command
240246
command: str
@@ -267,10 +273,7 @@ def __write_dll_builds(self):
267273
dll_link_deps: "list[str]" = []
268274
for file in dll.files:
269275
# Determine variables
270-
variables: dict[str, str] = {}
271-
opt = file.opt
272-
if opt is not None and opt != self.config.default_opt_flags:
273-
variables["OPT_FLAGS"] = opt
276+
variables: dict[str, str] = self.__file_config_to_variables(file.config)
274277

275278
# Determine command
276279
command: str
@@ -392,6 +395,17 @@ def __detect_cross(self) -> str:
392395
else:
393396
return "mips-linux-gnu-"
394397

398+
def __file_config_to_variables(self, file_config: BuildFileConfig | None):
399+
variables: dict[str, str] = {}
400+
401+
if file_config != None:
402+
if file_config.opt != None:
403+
variables["OPT_FLAGS"] = file_config.opt
404+
if file_config.ido_version != None:
405+
variables["CC"] = IDO_VAR_MAP[file_config.ido_version]
406+
407+
return variables
408+
395409
class ObjDiffConfigWriter:
396410
def __init__(self, output_file: TextIO, input: BuildFiles, config: BuildConfig):
397411
self.output_file = output_file
@@ -462,8 +476,8 @@ def __scan_c_files(self):
462476
paths = [Path(path) for path in glob.glob("src/**/*.c", recursive=True) if not Path(path).is_relative_to(Path("src/dlls"))]
463477
for src_path in paths:
464478
obj_path = self.__make_obj_path(src_path)
465-
opt = self.__get_optimization_level(src_path)
466-
self.files.append(BuildFile(str(src_path), str(obj_path), BuildFileType.C, opt))
479+
file_config = self.__get_file_config(src_path)
480+
self.files.append(BuildFile(str(src_path), str(obj_path), BuildFileType.C, file_config))
467481

468482
def __scan_asm_files(self):
469483
# Exclude splat nonmatchings, those are compiled in with their respective C file
@@ -510,8 +524,8 @@ def __scan_dlls(self):
510524

511525
for src_path in c_paths:
512526
obj_path = self.__make_obj_path(src_path)
513-
opt = self.__get_optimization_level(src_path)
514-
files.append(BuildFile(str(src_path), str(obj_path), BuildFileType.C, opt))
527+
file_config = self.__get_file_config(src_path)
528+
files.append(BuildFile(str(src_path), str(obj_path), BuildFileType.C, file_config))
515529

516530
for src_path in asm_paths:
517531
obj_path = self.__make_obj_path(src_path)
@@ -533,18 +547,35 @@ def __scan_dlls(self):
533547
def __make_obj_path(self, path: Path) -> str:
534548
return path.with_suffix('.o')
535549

536-
def __get_optimization_level(self, path: Path) -> str:
550+
def __get_file_config(self, path: Path) -> BuildFileConfig:
551+
opt_flags: "str | None" = None
552+
ido_version: "str | None" = None
553+
537554
with open(path, "r", encoding="utf-8") as file:
555+
found_comments = False
538556
while True:
539557
line = file.readline().strip()
540-
if len(line) == 0:
558+
if len(line) == 0 and found_comments:
559+
# End on empty line after comment block
541560
break
542561
if line.startswith("//"):
562+
found_comments = True
563+
543564
opt_match = opt_flags_pattern.search(line)
544565
if opt_match != None:
545-
return opt_match.group(1)
566+
opt_flags = opt_match.group(1)
567+
continue
568+
ido_match = ido_version_pattern.search(line)
569+
if ido_match != None:
570+
ido_version = ido_match.group(1)
571+
continue
572+
else:
573+
# End on non-empty non-comment line
574+
break
546575

547-
return self.config.default_opt_flags
576+
return BuildFileConfig(
577+
opt=opt_flags,
578+
ido_version=ido_version)
548579

549580
def __get_dll_config(self, dll_dir: Path, number: int) -> DLLBuildConfig | None:
550581
yaml_path = dll_dir.joinpath("dll.yaml")

0 commit comments

Comments
 (0)