diff --git a/pyproject.toml b/pyproject.toml index c51deacf..106a75fe 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -20,6 +20,7 @@ dependencies = [ [project.optional-dependencies] mips = [ + # TODO: Wait for a version bump after https://github.com/Decompollaborate/spimdisasm/pull/209 "spimdisasm>=1.42.1,<2.0.0", # This value should be keep in sync with the version listed on disassembler/spimdisasm_disassembler.py "rabbitizer>=1.12.0,<2.0.0", "pygfxd>=1.0.5", diff --git a/requirements.txt b/requirements.txt index b6084600..01ca57a6 100644 --- a/requirements.txt +++ b/requirements.txt @@ -4,6 +4,7 @@ tqdm==4.67.1 intervaltree==3.1.0 colorama==0.4.6 # This value should be keep in sync with the version listed on disassembler/spimdisasm_disassembler.py and pyproject.toml +# TODO: Wait for a version bump after https://github.com/Decompollaborate/spimdisasm/pull/209 spimdisasm>=1.42.1 rabbitizer>=1.10.0 pygfxd>=1.0.5 diff --git a/src/splat/util/compiler.py b/src/splat/util/compiler.py index eeea374a..7b44bfbc 100644 --- a/src/splat/util/compiler.py +++ b/src/splat/util/compiler.py @@ -64,6 +64,13 @@ class Compiler: MWCCPS2 = Compiler("MWCCPS2", uses_include_asm=False) EEGCC = Compiler("EEGCC", align_on_branch_labels=True) +# PSP +SNC = Compiler( + "SNC", + align_on_branch_labels=True, + j_as_branch=True, +) + compiler_for_name: Dict[str, Compiler] = { x.name: x for x in [ @@ -75,6 +82,7 @@ class Compiler: PSYQ, MWCCPS2, EEGCC, + SNC, ] } diff --git a/src/splat/util/file_presets.py b/src/splat/util/file_presets.py index ea940ea6..66551626 100644 --- a/src/splat/util/file_presets.py +++ b/src/splat/util/file_presets.py @@ -56,6 +56,16 @@ def write_include_asm_h(): " .set at # maspsx-keep\\n" \\ ); \\ } +""" + elif options.opts.include_asm_macro_style == "snc": + include_asm_macro = """\ +#define INCLUDE_ASM(FOLDER, NAME) \\ + __asm__( \\ + ".section .text\\n" \\ + " .set noat\\n" \\ + " .include \\"" FOLDER "/" #NAME ".s\\"\\n" \\ + " .set at\\n" \\ + ) """ else: # default include_asm_macro = """\ diff --git a/src/splat/util/options.py b/src/splat/util/options.py index 9b51b491..d2e7887d 100644 --- a/src/splat/util/options.py +++ b/src/splat/util/options.py @@ -43,7 +43,8 @@ class SplatOpts: # Changes the definition of the generated `INCLUDE_ASM`. # default: The default one. # maspsx_hack: Use the maspsx hack workaround definition https://github.com/mkst/maspsx?tab=readme-ov-file#include_asm-reordering-workaround-hack - include_asm_macro_style: Literal["default", "maspsx_hack"] + # snc: Do not set `.set reorder` after the include. + include_asm_macro_style: Literal["default", "maspsx_hack", "snc"] # Directory to place the generated asm macros files. generated_asm_macros_directory: Path # Determines whether to use .o as the suffix for all binary files?... TODO document @@ -429,11 +430,11 @@ def parse_endianness() -> Literal["big", "little"]: else: raise ValueError(f"Invalid endianness: {endianness}") - def parse_include_asm_macro_style() -> Literal["default", "maspsx_hack"]: + def parse_include_asm_macro_style() -> Literal["default", "maspsx_hack", "snc"]: include_asm_macro_style = p.parse_opt_within( "include_asm_macro_style", str, - ["default", "maspsx_hack"], + ["default", "maspsx_hack", "snc"], "default", ) @@ -441,8 +442,10 @@ def parse_include_asm_macro_style() -> Literal["default", "maspsx_hack"]: return "default" elif include_asm_macro_style == "maspsx_hack": return "maspsx_hack" + elif include_asm_macro_style == "snc": + return "snc" else: - raise ValueError(f"Invalid endianness: {include_asm_macro_style}") + raise ValueError(f"Invalid include_asm_macro_style: {include_asm_macro_style}") default_ld_bss_is_noload = True if platform == "psx": diff --git a/src/splat/util/ps2/ps2elfinfo.py b/src/splat/util/ps2/ps2elfinfo.py index e7ec4e8f..ded87657 100755 --- a/src/splat/util/ps2/ps2elfinfo.py +++ b/src/splat/util/ps2/ps2elfinfo.py @@ -65,17 +65,21 @@ def get_info(elf_path: Path, elf_bytes: bytes) -> Optional[Ps2Elf]: spimdisasm.common.GlobalConfig.QUIET = True elf = Elf32File(elf_bytes) - if elf.header.type != Elf32ObjectFileType.EXEC.value: - log.write("Elf file is not an EXEC type.", status="warn") - return None if elf.header.machine != 8: # 8 corresponds to EM_MIPS # We only care about mips binaries. log.write("Elf file is not a MIPS binary.", status="warn") return None - if Elf32Constants.Elf32HeaderFlag._5900 not in elf.elfFlags: - log.write("Missing 5900 flag", status="warn") - return None + + # PSP (E)BOOT.BIN files use this type. + if elf.header.type != Elf32Constants.Elf32ObjectFileType.SCE_PSPRELEXEC.value: + if elf.header.type != Elf32ObjectFileType.EXEC.value: + log.write("Elf file is not an EXEC type.", status="warn") + return None + + if Elf32Constants.Elf32HeaderFlag._5900 not in elf.elfFlags and Elf32Constants.Elf32HeaderFlag.ARCH_2 not in elf.elfFlags: + log.write("Missing 5900 flag", status="warn") + return None if elf.reginfo is not None and elf.reginfo.gpValue != 0: gp = elf.reginfo.gpValue