1. Project Overview & Quickstart (zeldaret/oot)
File: README.md
The Legend of Zelda: Ocarina of Time
- WARNING! -
This repository is a work in progress, and while it can be used to make certain changes, it's still
constantly evolving. If you use it for modding purposes in its current state, please be aware that
the codebase can drastically change at any time. Also note that some parts of the ROM may not be
'shiftable' yet, so modifying them could be difficult at this point.This is a WIP decompilation of The Legend of Zelda: Ocarina of Time. The purpose of the project is to recreate a source code base for the game from scratch, using information found inside the game along with static and/or dynamic analysis. It is not producing a PC port. For more information you can get in touch with the team on our Discord server.
It builds the following versions:
| Name | Build timestamp | Description | MD5 hash of input ROM(s) |
|---|---|---|---|
| ntsc-1.0 | 98-10-21 04:56:31 | NTSC 1.0 (Japan/US) | 9f04c8e68534b870f707c247fa4b50fc``5bd1fe107bf8106b2ab6650abecd54d6 |
| ntsc-1.1 | 98-10-26 10:58:45 | NTSC 1.1 (Japan/US) | 1bf5f42b98c3e97948f01155f12e2d88``721fdcc6f5f34be55c43a807f2a16af4 |
| pal-1.0 | 98-11-10 14:34:22 | PAL 1.0 (Europe) | e040de91a74b61e3201db0e2323f768a |
| ntsc-1.2 | 98-11-12 18:17:03 | NTSC 1.2 (Japan/US) | 2258052847bdd056c8406a9ef6427f13``57a9719ad547c516342e1a15d5c28c3d |
| pal-1.1 | 98-11-18 17:36:49 | PAL 1.1 (Europe) | d714580dd74c2c033f5e1b6dc0aeac77 |
| gc-jp | 02-10-29 23:49:53 | GameCube Japan | 33fb7852c180b18ea0b9620b630f413f |
| gc-jp-mq | 02-10-30 00:15:15 | GameCube Japan Master Quest | 69895c5c78442260f6eafb2506dc482a |
| gc-us | 02-12-19 13:28:09 | GameCube US | cd09029edcfb7c097ac01986a0f83d3f |
| gc-us-mq | 02-12-19 14:05:42 | GameCube US Master Quest | da35577fe54579f6a266931cc75f512d |
| gc-eu-dbg-2 | 03-02-13 19:46:49 | GameCube Europe/PAL Debug (earlier build) | ab1ca59d0039e3b34d82db650b54d7b9``2814fde8d6cfe23a220de6be955b4196 |
| gc-eu-mq-dbg | 03-02-21 00:16:31 | GameCube Europe/PAL Master Quest Debug | 75e344f41c26ec2ec5ad92caa9e25629``8ca71e87de4ce5e9f6ec916202a623e9``f751d1a097764e2337b1ac9ba1e27699``dde376d47187b931820d5b2957cded14 |
| gc-eu-dbg | 03-02-21 00:49:18 | GameCube Europe/PAL Debug | 3c10b67a76616ae2c162def7528724cf``382dc484e317d6522745c95387e7d5b9 |
| gc-eu | 03-02-21 20:12:23 | GameCube Europe/PAL | 2c27b4e000e85fd78dbca551f1b1c965 |
| gc-eu-mq | 03-02-21 20:37:19 | GameCube Europe/PAL Master Quest | 1618403427e4344a57833043db5ce3c3 |
| gc-jp-ce | 03-10-08 21:53:00 | GameCube Japan (Collector's Edition Disc) | 0c13e0449a28ea5b925cdb8af8d29768 |
| ique-cn | 03-10-22 16:23:19 | iQue Player (Simplified Chinese) | 0ab48b2d44a74b3bb2d384f6170c2742 |
The default version is gc-eu-mq-dbg, i.e. the GameCube Europe/PAL Master Quest Debug ROM.
Note: This repository does not include any of the assets necessary to build the ROM. A prior copy of the game is required to extract the needed assets.
Website: https://zelda.deco.mp
Discord: https://discord.zelda.deco.mp
Installation
We recommend using WSL on Windows, or native Linux, which the rest of this readme describes. We currently have instructions for
(These will also depend on the Linux instructions.)
Some of these may also be out of date or unmaintained; usually our contributors use WSL, Linux, and macOS, so these instructions should be up to date.
Windows
For Windows 10 or 11, install WSL and a distribution by following this
WSL Installation Guide.
We recommend using Ubuntu as the Linux distribution.
For older versions of Windows, install a Linux VM or refer to Docker instructions.
Linux (Native or under WSL / VM)
1. Install build dependencies
The build process has the following package requirements:
- git
- build-essential
- curl
- python3
- python3-pip
- python3-venv
- libxml2-dev
Python 3.10+ is required.
Under Debian / Ubuntu (which we recommend using), you can install them with the following commands:
sudo apt-get update
sudo apt-get install git build-essential curl python3 python3-pip python3-venv libxml2-devIn addition to these packages, a MIPS binutils installation is required. The project aims to support a couple of commonly-encountered MIPS toolchains out-of-the-box, only one is required and is automatically detected:
- mips64-ultra-elf- or mips64- from the practicerom toolchain
- mips64-elf- from the libdragon n64 homebrew library
- mips-linux-gnu- or mips64-linux-gnu- found in common distribution package managers as e.g.
binutils-mips-linux-gnu
If none of these are available to install, the makefile exposes MIPS_BINUTILS_PREFIX as a means to set your own toolchain prefix. Otherwise, consider building one of the first two options from source.
If you are using GCC as the compiler for Ocarina of Time, you will also need the corresponding gcc compiler for the chosen toolchain. For the first two options above, gcc is included automatically. For mips-linux-gnu- or mips64-linux-gnu- it is often a separate package, e.g. gcc-mips-linux-gnu.
2. Clone the repository
N.B. If using WSL, we strongly encourage you to clone into WSL's Linux filesystem using Linux's git.
Cloning into the Windows filesystem will result in much slower read/write speeds, and often causes issues when Windows copies the files with the wrong line endings, which the compiler IDO cannot handle correctly.
Clone https://github.com/zeldaret/oot.git where you wish to have the project, with a command such as:
git clone https://github.com/zeldaret/oot.gitThis will copy the GitHub repository contents into a new folder in the current directory called oot. Change into this directory before doing anything else:
cd oot3. Prepare a base ROM
First, pick the version of the game you want to build.
The supported versions and ROM checksums can be found in the table above.
As an example, the ntsc-1.0 version will be used in these instructions.
Place a copy of the ROM inside the baseroms// folder for your version of choice.
For example for ntsc-1.0, inside the baseroms/ntsc-1.0/ folder.
If you are under WSL, you can run the command explorer.exe . to open the current directory in the Windows file explorer.
Rename the file to baserom.z64, baserom.n64 or baserom.v64, depending on the original extension.
4. Setup the ROM and build process
Setup and extract everything from your ROM with the following command:
make setup VERSION=For example for ntsc-1.0, run make setup VERSION=ntsc-1.0.
This downloads some dependencies (from pip), and compiles tools for the build process.
Then it generates a new ROM baseroms//baserom-decompressed.z64.
For retail (non-debug) versions, that ROM will be the decompressed equivalent of the ROM.
For the gc-eu-mq-dbg version, that ROM will have the overdump removed and the header patched.
The other debug ROMs gc-eu-dbg-2 and gc-eu-dbg will also have the overdump removed.
It will also extract the individual assets from the ROM.
5. Build the ROM
Run make to build the ROM.
Make sure your path to the project is not too long, otherwise this process may error.
make VERSION=For example for ntsc-1.0, run make VERSION=ntsc-1.0
If all goes well, a new ROM should be built at build//oot-.z64 (for example build/ntsc-1.0/oot-ntsc-1.0.z64), and the following text printed:
build//oot-.z64: OKIf you instead see the following:
build//oot-.z64: FAILED
md5sum: WARNING: 1 computed checksum did NOT matchThis means that the built ROM isn't the same as the base one, so something went wrong or some part of the code doesn't match.
NOTE: to speed up the build, you can either:
- pass
-jNtomake setupandmake, where N is the number of threads to use in the build. The generally-accepted wisdom is to use the number of virtual cores your computer has. - pass
-jtomake setupandmake, to use as many threads as possible, but beware that this can use too much memory on lower-end systems.
Both of these have the disadvantage that the ordering of the terminal output is scrambled, so for debugging it is best to stick to one thread (i.e. not pass -j or -jN).
Changing build options
By default, if you don't specify a version to build with VERSION= in the make commands, the gc-eu-mq-dbg version is used.
This default can be changed in the Makefile.
The project Makefile is fairly configurable and can also be used to prepare the repo for modding.
See the options outlined at the top of the Makefile for more information.
Contributing
All contributions are welcome. This is a group effort, and even small contributions can make a difference.
Some tasks also don't require much knowledge to get started.
Most discussions happen on our Discord Server, where you are welcome to ask if you need help getting started, or if you have any questions regarding this project and other decompilation projects.
File: docs/audio/Samplebank_XML.md
Samplebank XML Format Specification
Samplebank XMLs describe a samplebank file that contains compressed waveform data. It specifies which sample files to include as well as certain global properties such as the index of this samplebank.
<SampleBank
Name="<C Indentifier>"
Index=""
Medium="<Medium>"
CachePolicy="<CachePolicy>"
BufferBug="[bool]"
>Begins a new samplebank.
Attributes
- Name: The name of the samplebank.
- Index: The index of the samplebank for the samplebank table. Must be a unique index for all samplebanks and pointers.
- Medium: The storage medium, from the
SampleMediumenum. - CachePolicy: The cache policy, from the
AudioCacheLoadTypeenum. - [Optional] BufferBug: Whether this samplebank suffers from a buffer clearing bug present in the original audio tools. For matching only.
Tags
- xml
" />Create an alternate index that refers to this samplebank.
Attributes
- Index: The alternative index, must be unique among all samplebanks and pointers.
- xml
<Sample Name="<C Identifier>" Path="" />Adds a compressed sample file to the samplebank. The sample should be single-channel and big-endian, in a format that is recognizable by the audio driver such as: pcm16, vadpcm, or half-frame vadpcm.
Attributes
- Name: Name of this sample. Must be a valid C language identifier.
- Path: Path to aifc file relative to the project root (typically in
$(BUILD_DIR)/assets/audio/samples/)
- xml
" Path="" />Adds a binary blob to the samplebank. Intended for matching only when data cannot be identified.
Attributes
- Name: Name of this blob. Must be a valid C language identifier.
- Path: Path to binary file, relative to the project root (typically in
$(BUILD_DIR)/assets/audio/samples/)
</SampleBank>File: docs/audio/Soundfont_XML.md
Soundfont XML Format Specification
Soundfont XMLs describe the layout of a single soundfont. These package raw samples together into instruments, of which there are three kinds:
- Effects: These are simple sound effects that just play a single sample without any modulation.
- Drums: These define a MIDI-style percussion key map.
- Instruments: These are instruments that may be played at any key with up to three voices and may be modulated by an envelope.
In the specification, Note Names can be either a MIDI note name e.g. C4 or it may be a Zelda64 note number, which are related to MIDI note numbers ($n$) by $(n - 21) \mod 128$.
<Soundfont
Name="<C Identifier>"
Index=""
Medium="<Medium>"
CachePolicy="<CachePolicy>"
SampleBank=""
Indirect="[uint]"
SampleBankDD="[Path]"
IndirectDD="[uint]"
LoopsHaveFrames="[bool]"
PadToSize="[uint]"
NumInstruments="[uint]"
>Begins a new soundfont.
Attributes
- Name: Soundfont symbol name. Must be a valid C identifier.
- Index: Soundfont index. Must be an integer.
- Medium: Storage medium. Must be an enum name from
SampleMedium. - CachePolicy: Cache policy. Must be an enum name from
AudioCacheLoadType. - SampleBank: Path to samplebank xml used by this soundfont.
- [Optional] Indirect: Pointer index if the samplebank is referenced indirectly.
- [Optional] SampleBankDD: Path to samplebank xml used for DD medium.
- [Optional] IndirectDD: Pointer index if the DD samplebank is referenced indirectly.
- [Optional] LoopsHaveFrames: Whether loops in this soundfont store the total frame count of the sample. Must be a boolean.
- [Optional] PadToSize: For matching only. Specifies the total file size the result output should be padded to.
- [Optional] NumInstruments: For matching only. Specifies the total number of instrument pointers. Usually this is automatically assigned based on
max(program_number) + 1but some vanilla banks don't match this way.
Tags
- xml
<Envelopes>Lists envelopes defined in this soundfont.
Attributes
N/A
Tags
- xml
<Envelope Name="<C Identifier>" Release="" >Starts a new envelope.
Attributes
- Name: Unique name for this envelope. Must be a valid C identifier.
- Release: Release rate index (into
gAudioCtx.adsrDecayTable) for this envelope
Tags
- xml
" Arg="<s16>" />Add a point to the envelope at (delay, arg)
Attributes
- Delay: Duration until the next point
- Arg: Value of the envelope at this point
- xml
<Disable/>Insert a ADSR_DISABLE command
- xml
<Hang/>Insert a ADSR_HANG command
- xml
<Goto Index="" />Insert a ADSR_GOTO command
Attributes
- Index: Index of the envelope point to jump to
xml</Envelope>
xml</Envelopes>
- xml
<Samples IsDD="[Bool]" Cached="[Bool]" >Begins a list of samples used in this Soundfont.
Attributes
- [Optional] IsDD: Whether all the samples in the list are on the Disk Drive. The sample data will come from the samplebank
SampleBankDD. Default isfalse. NOTE this is not fully implemented, it should always befalse. - [Optional] Cached: Whether all the samples in the list should be added to the
usedSamplescache. Default isfalse.
Tags
- xml
<Sample Name="<C Identifier>" SampleRate="[Sample Rate]" BaseNote="[Note Name]" FineTune="[Fine Tune]" IsDD="[Bool]" Cached="[Bool]" />Declares a sample used in this soundfont.
Attributes
- Name: The name of this sample. A sample with this name must be present in the samplebank used by the soundfont.
- [Optional] SampleRate: An overriding sample rate for this sample. Default comes from the sample file.
- [Optional] BaseNote: An overriding root key for this sample. Default comes from the sample file.
- [Optional] FineTune: An overriding fine tuning for this sample, in cents, in the range [-100, 100]. Default comes from the sample file.
- [Optional] IsDD: Whether this sample is on the Disk Drive. The sample data will come from the samplebank
SampleBankDD. Default isfalse. NOTE this is not fully implemented, it should always befalse. - [Optional] Cached: Whether this sample should be added to the
usedSamplescache. Default isfalse.
xml</Samples>
- [Optional] IsDD: Whether all the samples in the list are on the Disk Drive. The sample data will come from the samplebank
- xml
<Effects>Begins a list of sound effects to define for this soundfont. Sound effects correspond to simple sounds that cannot be played at different keys.
Attributes
N/A
Tags
- xml
<Effect Name="<C Identifier>" Sample="<Sample Name>" SampleRate="[Sample Rate]" BaseNote="[Note Name]" FineTune="[Fine Tune]" />Defines a single sound effect.
Attributes
- Name: The name of the sound effect, the name is made available in sequence files in the form
SF{n}_{name}wherenis the index of this soundfont andnameis this name. For example, ifn=0andname=ExampleEffectthe name to use in sequence files isSF0_ExampleEffect. - Sample: The name of the sample associated with this effect.
- [Optional] SampleRate: An overriding sample rate for this effect. Default comes from the sample definition.
- [Optional] BaseNote: An overriding root key for this effect. Default comes from the sample definition.
- [Optional] FineTune: An overriding fine tuning for this effect, in cents, in the range [-100, 100]. Default comes from the sample definition.
- Name: The name of the sound effect, the name is made available in sequence files in the form
xml</Effects>
- xml
<Drums>Begins the percussion definitions for this soundfont. Percussion corresponds to the MIDI notion of percussion, where single samples are mapped across a range of keys.
Attributes
N/A
Tags
- xml
<Drum Name="<C Identifier>" Note="[Note Name]" NoteStart="[Note Name]" NoteEnd="[Note Name]" Pan="" Envelope="<Envelope Name>" Release="[u8]" Sample="<Sample Name>" SampleRate="[Sample Rate]" BaseNote="[Note Name]" FineTune="[Fine Tune]" />Defines a single percussion range.
Attributes
- Name: The name of this sound. Definitions are emitted for sequence files in the form
SF{n}_{name}_{note}for every note covered by this sound. - [Optional] Note: The key to map this sound to. Should not overlap with other definitions. If this field is left unspecified,
NoteStartandNoteEndbecome required. - [Optional] NoteStart: The first key that is mapped to this sound. Should not overlap with other definitions. If this field is left unspecified,
Notebecomes required. If this field is specified,NoteEndmust also be specified. - [Optional] NoteEnd: The last key that is mapped to this sound. Should not overlap with other definitions. If this field is left unspecified,
Notebecomes required. If this field is specified,NoteStartmust also be specified. - Pan: The stereo weight for this sound. Center=
64. - Envelope: The envelope to modulate the volume over time with. Must be defined in the
Envelopeslist. - [Optional] Release: An override for the envelope release rate. Default is the release rate specified in the envelope definition
- Sample: The name of the sample to use.
- [Optional] SampleRate: An overriding sample rate for this sound. Default comes from the sample definition.
- [Optional] BaseNote: An overriding root key for this sound. Default comes from the sample definition.
- [Optional] FineTune: An overriding fine tuning for this sound, in cents, in the range [-100, 100]. Default comes from the sample definition.
- Name: The name of this sound. Definitions are emitted for sequence files in the form
xml</Drums>
- xml
Begins the instrument definitions for this soundfont. Instruments correspond to the MIDI notion of instruments, with up to 3 samples (voices) per instrument that must map to contiguous ranges of notes.
Attributes
N/A
Tags
- xml
" Name="<C Identifier>" Envelope="<Envelope Name>" Release="[u8]" Sample="<Sample Name>" SampleRate="[Sample Rate]" BaseNote="[Note Name]" FineTune="[Fine Tune]" RangeLo="[Note Name]" SampleLo="[Sample Name]" SampleRateLo="[Sample Rate]" BaseNoteLo="[Note Name]" FineTuneLo="[Fine Tune]" RangeHi="[Note Name]" SampleHi="[Sample Name]" SampleRateHi="[Sample Rate]" BaseNoteHi="[Note Name]" FineTuneHi="[Fine Tune]" />Defines an instrument.
Attributes
- ProgramNumber: MIDI Program Number for this instrument. Must be in the range
0 <= n <= 125 - Name: The name of this instrument.
- Envelope: Envelope to use, identified by name.
- [Optional] Release: Release rate index override. Default release rate comes from the chosen envelope.
- Sample: The name of the middle sample to use for this instrument.
- [Optional] SampleRate: Sample rate override for the middle sample. Default is sourced from the sample properties.
- [Optional] BaseNote: Base note override for the middle sample. Default is sourced from the sample properties.
- [Optional] FineTune: Fine tuning override for the middle sample, in cents, in the range [-100, 100]. Default is sourced from the sample properties.
- [Optional] RangeLo: The largest note for SampleLo. SampleLo will be used instead of Sample for keys in the range [0, RangeLo]. If left unspecified, SampleLo must not be specified. If specified, SampleLo must be specified.
- [Optional] SampleLo: The name of the low sample to use for this instrument.
- [Optional] SampleRateLo: Sample rate override for the low sample. Default is sourced from the sample properties.
- [Optional] BaseNoteLo: Base note override for the low sample. Default is sourced from the sample properties.
- [Optional] FineTuneLo: Fine tuning override for the low sample, in cents, in the range [-100, 100]. Default is sourced from the sample properties.
- [Optional] RangeHi: The smallest note for SampleHi. SampleHi will be used instead of Sample for keys in the range [RangeHi, 127]. If left unspecified, SampleHi must not be specified. If specified, SampleHi must be specified.
- [Optional] SampleHi: The name of the high sample to use for this instrument.
- [Optional] SampleRateHi: Sample rate override for the high sample. Default is sourced from the sample properties.
- [Optional] BaseNoteHi: Base note override for the high sample. Default is sourced from the sample properties.
- [Optional] FineTuneHi: Fine tuning override for the high sample, in cents, in the range [-100, 100]. Default is sourced from the sample properties.
- ProgramNumber: MIDI Program Number for this instrument. Must be in the range
xml
</Soundfont>File: docs/BUILDING_DOCKER.md
Building using Docker
1. Setup requirements
To use Docker, you'll need either Docker Desktop or Docker Toolbox installed and setup based on your system.
On Ubuntu, Docker and required tools can be installed with: sudo apt install docker.io docker-compose docker-buildx
You'll also need to prepare a local version of the project with a copied base ROM (see steps 2 and 3 of the Linux instructions).
2. Create and start the Docker image build
From the root of your local project, run the following command:
docker-compose up --buildThis should immediately begin steps 4 and 5 within the Docker container.
3. Shell into the 'oot' container
To exec into the oot Docker image at any time, run the following command either during or after the build:
docker-compose exec oot bashFile: docs/BUILDING_MACOS.md
Building on macOS
N.B. C++17 is required to build the asset processing program that we use (ZAPD), so check your OS version can support this before proceeding.
1. Dependencies
For macOS, use Homebrew to install the following dependencies:
- coreutils
- make
- python3
- bash
- clang-format
- libxml2
- libiconv
You can install them with the following commands:
brew update
brew install coreutils make python3 bash clang-format libxml2 libiconv(The repository expects Homebrew-installed programs to be either linked correctly in $PATH etc. or in their default locations.)
2. Building mips-linux-binutils
The following instructions are written for MacOS users but should apply to any Unix-like system, with maybe some modifications at the end regarding the bash_profile.
Create destination dir for binutils
sudo mkdir -p /opt/crossCreate and enter local working dir
mkdir ~/binutils-tmp
cd ~/binutils-tmpGet and extract binutils source
curl -O https://ftp.gnu.org/gnu/binutils/binutils-2.46.0.tar.xz
tar xjf binutils-2.46.0.tar.xzCreate and enter a build directory
mkdir build-binutils
cd build-binutilsConfigure the build
../binutils-2.46.0/configure --target=mips-linux-gnu --prefix=/opt/cross --with-system-zlib --disable-gprof --disable-gdb --disable-werrorMake and install binutils
make -j$(nproc)
sudo make installEdit your ~/.bash_profile/~/.zprofile (or whichever shell you use) to add the new binutils binaries to the system PATH
echo 'export PATH="$PATH:/opt/cross/bin"' >> ~/.bash_profileReload ~/.bash_profile (or just launch a new terminal tab)
source ~/.bash_profileIf this worked, you can now delete the temporary directory ~/binutils-tmp.
3. Final note
Apple's version of make is very out-of-date, so you should use the brew-installed gmake in place of make in this repo from now on.
You should now be able to continue from step 2 of the Linux instructions.
4. Building GCC (optional)
If you'd like to compile with GCC instead of IDO (e.g. for modding), you can build it from source similarly to how we built binutils:
Install dependences
brew install gcc@15 gmp isl libmpc mpfrCreate and enter local working dir
mkdir ~/gcc-tmp
cd ~/gcc-tmpGet and extract gcc source
curl -O https://ftp.gnu.org/gnu/gcc/gcc-15.2.0/gcc-15.2.0.tar.xz
tar xvf gcc-15.2.0.tar.xzCreate and enter a build directory
mkdir build-gcc
cd build-gccConfigure the build
CC=gcc-15 CXX=g++-15 ../gcc-15.2.0/configure --target=mips-linux-gnu --prefix=/opt/cross --disable-nls --enable-languages=c --with-gmp=$(brew --prefix)/opt/gmp --with-mpfr=$(brew --prefix)/opt/mpfr --with-mpc=$(brew --prefix)/opt/libmpc --with-isl=$(brew --prefix)/opt/islMake and install gcc
CC=gcc-15 CXX=g++-15 make all-gcc -j$(nproc)
sudo make install-gccIf this worked, you can now delete the temporary directory ~/gcc-tmp.
File: docs/compilers.md
Compilers
Ocarina of Time was written mostly in C, compiled to MIPS machine code. For the
N64 and GameCube versions, all code was compiled with the IDO compiler. For the
iQue Player versions, some of the code (namely libultra, and some game files
such as those related to Chinese text) was compiled with the EGCS compiler instead.
IDO
Ocarina of Time was originally developed on
Silicon Graphics "Indy" workstations,
and IDO (IRIS Development Option) was the C compiler toolchain that shipped with
these. Two different versions of IDO were used for Ocarina of Time: IDO 5.3 was
used for some libraries (namely libultra, libleo, and the JPEG library) while
IDO 7.1 was used for the other libraries and all of the "main" game code.
These Silicon Graphics workstations ran the MIPS-based IRIX operating system, so
the original compiler binaries can't run on modern systems. Originally this
project used qemu-irix (now
unmaintained) to run emulate IRIX on modern systems, but nowadays we use the
more lightweight
ido-static-recomp instead.
EGCS
EGCS (Experimental/Enhanced GNU Compiler System)
was a fork of the GCC compiler. The Linux-based iQue SDK included a patched
version of EGCS release 1.1.2. The original compiler can still run on modern Linux
systems, but we use a
modified version
that includes Mac support and a few other minor improvements (such as anonymous
struct/union support).
This version of the EGCS compiler has a bug where code that indexes into an array member can
fail to compile if the array member is at a large (>= 0x8000) offset in a struct. For
example, when run on the source code
struct Foo {
char a[0x8000];
int b[1];
};
int test(struct Foo* foo, int i) {
return foo->b[i];
}the compiler errors with
Compiler error: src.c: In function `test':
src.c:8: internal error--unrecognizable insn:
(insn 20 18 22 (set (reg:SI 85)
(plus:SI (reg:SI 81)
(const_int 32768))) -1 (nil)
(nil))
../../gcc/toplev.c:1367: Internal compiler error in function fatal_insnIn some recompiled files, the game developers had to modify the code to work
around this bug, for example by storing a pointer to the array in a temporary
variable before indexing into it.
File: docs/decompiling_tutorial.md
This repository used to contain a tutorial for how to do
decompilation work in the repo.
It has been less useful as more and more was decompiled,
and also more of a chore to keep up-to-date, so it has been
removed from the repo.
It is still interesting for historical purposes or for
curiosity, you can find the last version of it in revision
9963e7f5d5fa8caee329f6b40e393d8a2c45390b.
File: docs/Documenting.md
Documentation Style Guide
This project uses Doxygen to generate documentation pages from comments found in the source files. This guide focuses on writing compatible comments and ensuring consistency across the codebase.
However to keep the documentation readable in text and favor consistency, the Doxygen commands that should be used are restricted to what this document mentions.
To generate a doxygen manual for the project, ensure you have doxygen installed and then cd into the project root directory and run doxygen Doxyfile.
The documentation can then be browsed by opening docs/doxygen/html/index.html in a web browser.
Documenting Functions
Any comments inside functions, except bugs (see below), should use //-style comments, even if spanning over multiple lines.
A simple example of documenting a function with just a description (note the leading /**):
/**
* Update the crawl sound timer, and play the crawling sound when it reaches 0.
*/
void EnInsect_UpdateCrawlSfx(EnInsect* this) {A more complete example:
/**
* Request to either increase or consume magic.
*
* @param amount the positive-valued amount to either increase or decrease magic by
* @param type how the magic is increased or consumed.
*
* @return false if the request failed
*/
s32 Magic_RequestChange(PlayState* play, s16 amount, s16 type) {Note:
- Documentation for self-explanatory arguments (
@param) and return values (@return) may be omitted. @paramcommands should not have empty lines in between.- Different commands (main description,
@param,@return, ...) should be separated by empty lines.
Other directives that may be used for documenting functions:
@seeto reference something else (see below).@noteto bring attention to some of the function behavior.
Documenting Variables
In case the name of a variable isn't completely clear, documentation can provide a description.
If applicable, it may refer to a set of defines or enumerations that should be used with it (those should be linked with @see, see below).
/**
* My description of this variable
*/
s32 foo;Documenting Files
File documentation should be located at the top of the file, above #includes.
File documentation should only feature information that is general to the file or the system it implements.
/**
* @file z_fcurve_data_skelanime.c
* @brief Curve skeleton animation system
*
* A curve skeleton has a fixed number of limbs, ...
...
*/Other
Documenting Bugs:
Bugs should be documented on the line above where the bug begins.
//! @bug Missing early returnBug described on multiple lines should still use the //! syntax, over multiple lines. For example:
//! @bug this code was clearly meaning to print `abs(camera->camDataIdx)` as a
//! one-or-two-digit number, instead of `i`.Linking related information:
@see should be used to provide links to related information where appropriate, for example:
/**
* Sets the next framebuffer to the framebuffer associated to `task`.
* If there is no current buffer or it is time to swap, this buffer will be swapped to
* immediately, otherwise it will be swapped to later in Sched_HandleRetrace.
*
* @see Sched_HandleRetrace
*/
void Sched_SetNextFramebufferFromTask(Scheduler* sc, OSScTask* task) {In the case of functions, @see should come before the first @param.
@see may also be used for documenting files or variables.
HTML and LaTeX
It is possible to include HTML and LaTeX in documentation comments.
However it is prefered not to do so, so that the raw text stays readable when looked at as plain text, for example when browsing the source code.
File: docs/libu64.md
libu64
This document explains the reasoning behind organizing the libu64 files.
libu64 is known about from the Animal Crossing (GameCube) map files.
Here is the relevant excerpt from the Doubutsu no Mori+ 1.0 map file (for .text):
/* Detailed source-code truncated for AI context efficiency. */This repository's debug.c (formerly logutils.c), gfxprint.c and pad.c (formerly padutils.c) line up with the map.
Note debug.c has additional debug-only functions in gc-eu-mq-dbg, hinting that there were two versions of libu64, a debug version and a non-debug version.
Additionally debug.c, gfxprint.c and pad.c all require compilation flags -O2 (instead of -O2 -g3) to match, as supplementary evidence these were part of a separately compiled library.
-O2 is also required for most files between gfxprint.c and pad.c in the code segment (see spec), hinting that these other files (loadfragment2_n64.c, loadfragment2_gc.c, mtxuty-cvt.c, relocation_gc.c, load_gc.c, system_heap.c) are also part of libu64.
Files rcp_utils.c and logseverity_gc.c do not strictly require -O2, but they do match with -O2.
padsetup.c also requires -O2.
On the other hand, the function Overlay_Load (in loadfragment2_n64.c or load_gc.c depending on game version) calls DmaMgr_RequestSync, a function that is not part of libu64.
This could suggest these files are not part of libu64, but the other evidence detailed above seems stronger.
It is also a possibility that libu64 expected users to provide the function, and it would have been an undefined symbol in the library.
All in all this suggests all files in code between the audio code and libc64, are part of libu64.
In the OoT boot segment, stackcheck.c is right next to debug.c and requires -O2: this hints stackcheck.c could be part of libu64 too. This is confirmed by looking at Majora's Mask n64-us, where stackcheck.c is in the middle of other libu64 files in the boot segment (see MM spec).
File: docs/retail_versions.md
Decompiling retail versions
The next decompilation target for OOT is NTSC version 1.2
(ntsc-1.2), because it is the N64 version that is most similar to the GC
versions. Unfortunately there are still a lot of differences,
but once this version is done, future
N64 versions should be much easier, as the changes between N64 versions are
small in comparison.
Instead of cping a matching build into expected/, the target ROM is disassembled as .s files then
reassembled as .o files directly into expected/build/ntsc-1.2 for diff tools.
This allows us to make progress matching code in parallel with solving other
problems (such as the build system, ROM organization, and BSS ordering). The
files in tools/disasm/ntsc-1.2 say how to split the source files and where the
functions and variables are in the target ROM, and these may need to be updated
if there are mistakes or if function names change due to documentation work.
Unfortunately, the disassembly is not perfect, so a "correct" decompilation might
still show diffs with data symbols. We might improve this later, but these data
diffs are fine to ignore for now.
For register and stack allocation differences, often the code can be tweaked so
that it matches both the retail ROM while continuing to match GC versions and the Debug ROM (for
example, by reordering assignments or moving a local variable declaration inside
an if block). Since retail MM versions currently target N64, checking MM decomp for similar code can help.
We can handle code that is different between versions by adding#if PLATFORM_N64 ... #endif or #if PLATFORM_GC ... #endif around these parts of the
code. In order to keep the code readable, we should try to minimize the amount of#if noise whenever possible.
Setup
Copy your target JP NTSC 1.2 ROM to
baseroms/ntsc-1.2/baserom.z64Build the non-matching test ROM by running
shmake setup -jN VERSION=ntsc-1.2 make -jN VERSION=ntsc-1.2where
Nis the number of cores on your machine. This will build intobuild/ntsc-1.2and producebuild/ntsc-1.2/oot-ntsc-1.2.z64.If you later want to delete all output files, run
shmake clean VERSION=ntsc-1.2Disassemble the target ROM by running
shmake disasm VERSION=ntsc-1.2The outputs will be written to
expected/build/ntsc-1.2.Note that if you need to copy a matching build for another version, you can use e.g.
shmkdir -p expected/build cp -r build/gc-eu-mq-dbg expected/buildto avoid clobbering the disassembly.
Diff Tools
Note that many tools will require activating the Python virtual environment
in your terminal session. To do this, run:
source .venv/bin/activateretail_progress.py
Running ./retail_progress.py path/to/file.c will attempt to figure out which functions
in a file still need to match for ntsc-1.2. To get an overview of diffs for
all files, run ./retail_progress.py with no arguments.
asm-differ / diff.py
To diff assembly for a single function in ntsc-1.2, run e.g.
./diff.py -mwo3 -v ntsc-1.2 Math3D_CylTriVsIntersectThe -v flag tells diff.py to compare between build/ntsc-1.2 andexpected/build/ntsc-1.2, and to use make VERSION=ntsc-1.2 when rebuilding.
You may also want to diff versions gc-eu-mq and/or gc-eu-mq-dbg in another terminal
to ensure any changes still match there.
Permuter and decomp.me
Disassembly for individual functions is written toexpected/build/ntsc-1.2/functions, so to get a decomp.me scratch you can run
e.g.
decomp-permuter/import.py \
src/code/sys_math3d.c \
expected/build/ntsc-1.2/functions/src/code/sys_math3d/Math3D_CylTriVsIntersect.s \
VERSION=ntsc-1.2 --decompme2. Official Technical Reference & Guides (zeldaret/website)
ZeldaRET Website
This project was generated with Angular CLI version 12.2.10.
Development server
Run ng serve for a dev server. Navigate to http://localhost:4200/. The app will automatically reload if you change any of the source files.
Code scaffolding
Run ng generate component component-name to generate a new component. You can also use ng generate directive|pipe|service|class|guard|interface|enum|module.
Build
Run ng build to build the project. The build artifacts will be stored in the dist/ directory.
Running unit tests
Run ng test to execute the unit tests via Karma.
Running end-to-end tests
Run ng e2e to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
Further help
To get more help on the Angular CLI use ng help or go check out the Angular CLI Overview and Command Reference page.