-
Notifications
You must be signed in to change notification settings - Fork 53
Quickstart Elf
Note
This quickstart is written with PS2 ELFs in mind, relocatable ELFs are not supported. It is also assumed that you are using Ubuntu 22.04 either natively, via WSL2 or via Docker.
For the purposes of this quickstart, we will assume that we are going to split a game called mygame and we have the ELF from the iso named SLUS_XXX.YY.
Create a directory for ~/mygame and cd into it:
mkdir -p ${HOME}/mygame && cd ${HOME}/mygameCopy the SLUS_XXX.YY file into the mygame directory inside your home directory.
Ensure you are have Python 3.9 or higher installed:
$ python3 --version
Python 3.9.10If you get bash: python3: command not found install it with the following command:
sudo apt update && sudo apt install -y python3 python3-pipEnsure you have a MIPS binutils installed in your PC. Specifically we'll need a MIPS objcopy.
$ mips-linux-gnu-objcopy --version
GNU objcopy (GNU Binutils for Ubuntu) 2.38If you get an error then install it with the following command:
sudo apt install binutils-mips-linux-gnuWe'll install splat using pip and enable its mips dependencies:
python3 -m pip install -U splat64[mips]splat has a script that will generate a yaml file based in the ELF file.
python3 -m splat create_config SLUS_XXX.YYThis command generates a few files, from which the most important ones are the SLUS_XXX.YY.rom and the SLUS_XXX.YY.yaml.
The original ELF file contains the game code and a lot of extra metadata which we don't care about.
To get rid of the extra metadata the create_config script generated a ROM that only contains the game code and data, and the generated yaml is used to split this ROM instead of splitting the original ELF, making the splitting and build process a lot more cleaner.
To generate this ROM the create_config script uses objcopy. You can (and should) integrate this ROM generation step into your setup script / configure script. create_config tells you exactly what command it used to generate the ROM, which should look similar to the following:
mips-linux-gnu-objcopy -O binary --gap-fill=0x00 SLUS_XXX.YY SLUS_XXX.YY.romThis approach has a few pros and cons. The biggest pro is being able to generate an ELF with proper metadata as part of your build system, making a lot easier to achieve shiftability eventually. Note only this is not enough for shiftability, other factors must be worked out, like symbol alignment, fake symbols, etc.
create_config generates a yaml file which describes how the ROM is structured, what parts are code, data, etc. It also includes configuration values for splat.
Below is an example of what a generated yaml may look like:
# name: Your game name here!
sha1: 6da2d0a02aafe3bfba71ca8ba859174756ba3f5e
options:
basename: SLUS_206.24
target_path: SLUS_206.24.rom
elf_path: build/SLUS_206.24.elf
base_path: .
platform: ps2
compiler: EEGCC
gp_value: 0x003A0EF0
ld_gp_expression: cod_SBSS_START + 0x7FF0
# asm_path: asm
# src_path: src
# build_path: build
ld_script_path: SLUS_206.24.ld
ld_dependencies: True
ld_wildcard_sections: True
ld_bss_contains_common: True
create_asm_dependencies: True
find_file_boundaries: False
o_as_suffix: True
symbol_addrs_path:
- symbol_addrs.txt
reloc_addrs_path:
- reloc_addrs.txt
# undefined_funcs_auto_path: undefined_funcs_auto.txt
# undefined_syms_auto_path: undefined_syms_auto.txt
extensions_path: tools/splat_ext
string_encoding: ASCII
data_string_encoding: ASCII
rodata_string_guesser_level: 2
data_string_guesser_level: 2
named_regs_for_c_funcs: False
section_order:
- .text
# - .vutext
- .data
- .rodata
- .gcc_except_table
- .sbss
- .bss
auto_link_sections:
- .data
- .rodata
- .gcc_except_table
- .sbss
- .bss
segments:
- name: cod
type: code
start: 0x000000
vram: 0x00100000
bss_size: 0x6907C
subalign: null
subsegments:
- [0x000000, asm, cod/000000] # .text
- [0x3209C0, textbin, cod/3209C0] # .vutext
- [0x324680, data, cod/324680] # .data
- [0x350100, rodata, cod/350100] # .rodata
- [0x3B0780, gcc_except_table, cod/3B0780] # .gcc_except_table
- { type: sbss, vram: 0x004B0880, name: cod/004B0880 } # .sbss
- { type: bss, vram: 0x004B0F80, name: cod/004B0F80 } # .bss
- [0x3B0864]This is a bare-bones configuration and there is a lot of work required to map out the different sections of the ROM.
python3 -m splat split SLUS_XXX.YY.yamlThe output will look something like this:
splat 0.36.2 (powered by spimdisasm 1.38.0)
Loading symbols (symbol_addrs): 100%|█████████████████████████| 2/2 [00:00<00:00, 9868.95it/s]
Scanning cod: 0%| | 0/1 [00:00<?, ?it/s]
Rodata segment 'cod/350100' may belong to the text segment 'cod/000000'
Based on the usage from the function func_00102E48 to the symbol D_00450308
Scanning cod: 100%|█████████████████████████████████████████████| 1/1 [00:26<00:00, 26.62s/it]
Splitting cod: 100%|████████████████████████████████████████████| 1/1 [00:14<00:00, 14.77s/it]
Linker script cod: 100%|███████████████████████████████████████| 1/1 [00:00<00:00, 447.54it/s]
Split 3 MB (85.17%) in defined segments
asm: 3 MB (84.76%) 1 split, 0 cached
textbin: 15 KB (0.40%) 1 split, 0 cached
unknown: 0 B (0.00%) from unknown bin files
It's up to you to figure out the layout of the ROM, finding proper file splits.
The reassembly of the ROM is currently out of scope of this quickstart, as is switching out the asm segments for c or cpp.
You can find a general workflow for using splat at General Workflow
Please feel free to improve this guide!