Skip to content

Instantly share code, notes, and snippets.

@JayFoxRox
Created January 7, 2018 05:41
Show Gist options
  • Save JayFoxRox/5eaa45b374a44ce27143388bab1753b7 to your computer and use it in GitHub Desktop.
Save JayFoxRox/5eaa45b374a44ce27143388bab1753b7 to your computer and use it in GitHub Desktop.
N64 ROM (z64) to ELF
#!/usr/bin/bash
# Get entry point from N64 ROM
dd if=test.z64 bs=1 skip=8 count=4 of=entrypoint >& /dev/null
# Convert entrypoint to little endian
#mips-elf-objcopy -I binary -O binary --reverse-bytes=4 entrypoint entrypoint
# Construct an ELF
mips-elf-objcopy -I binary test.z64 -O elf32-bigmips -B mips --adjust-section-vma .data+0x80000000 foo.elf
# Patch to MIPS III
printf '\x20\x00\x00\x00' | dd bs=1 seek=36 count=4 conv=notrunc of=foo.elf >& /dev/null
# Set entrypoint
dd if=entrypoint bs=1 seek=24 count=4 conv=notrunc of=foo.elf >& /dev/null
rm entrypoint
# Dump the headers
mips-elf-objdump -x foo.elf
@JayFoxRox
Copy link
Author

JayFoxRox commented Jul 23, 2025

I don't remember creating this script at all, but I probably uploaded it for OpenSWE1R / Star Wars Episode 1 Racer ROM.
So I also don't know why I created it either, but it was probably used to load the ROM into Ghidra or some other tool for disassembly.

It's also possible that someone else actually created the script and I just dumped it here.


As to how it works (in terms of usage):

  1. Have your N64 ROM as test.z64 file in a folder
  2. Run this bash script in that folder (will dump to temporary file "entrypoint" and generate a final "foo.elf".

The generated ELF is merely a wrapper for the ROM contents (nothing is parsed, interpreted or even converted).

The script requires mips binutils and dd. dd should be available in almost any linux distribution. The mips binutils are probably a bit more specific, but if you want to use this tool, you probably also have a working mips toolchain / binutils.


As to how it works (in terms of operations):

An LLM can probably describe the same as I'll do here, so I'll keep it brief:
It uses dd to extract the 32 bit entrypoint of the ROM from offset 8 (to the "entrypoint" file), then creates a new ELF ("foo.elf") with the contents of the ROM. Once the new ELF exists, the CPU type in the ELF header is patched using dd (at offset 36). I assume I was too lazy to figure out how to do this with binutils, or it wasn't possible at the time. Finally the previously extracted entrypoint is patched into the ELF at offset 24, again using dd, before removing the temporary "entrypoint" file.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment