From CloudModding OoT Wiki
Jump to: navigation, search

Overlays are code files which are loaded dynamically into ram due to an inadequate amount of physical memory to increase address space (for its respective target system). Therefor, it is essentially a memory management technique. Mind you, the follow figure is not an accurate representation in relation to Ocarina of Time, but is merely here to hopefully establish a spacial imprint as, of course, the purpose of it is identical:

Instruction            Larger
Address Space        Address Space
+-----------+        +-----------+
|   misc    |        |           |
+-----------+        | overlay 1 |
|  Physical |        |           |
|    RAM    |   .----|           |
+-----------+   |    +-----------+
|   Stack   |   |    |           |
+-----------+   |    |           |
|           |   |    |           |
|   Data    |   |  .-| overlay 2 |
| Structure |   |  | |           |
+-----------+   |  | +-----------+
|           | <-'  | |           |
|  overlay  |  <---' | overlay 3 |
|  section  |<-------|           |
|           |<--.    +-----------+
+-----------+    `---| overlay 4 |
|   misc    |        |           |
+-----------+        |           |

Overlay Tables

For a complete list of overlays, see Overlay Tables.


Overlay files have a single header defining their properties, which is pointed to by the last word of the file. The overlay structure is similar to the elf file structure, in the sense that there are the following parts:

Text block mips r4000 machine code
Data block Read/Write data
(Initialized variables)
This can also include inline model data, as seen in element arrows and Ganon to name a few.
Rodata block Read-Only Data
(Constant variables)
Usually contains text used with the n64 debugging print function (0x80002130) and thus contains empty format strings.
BSS block Zero-Initialized Data Everything that has static allocation and is initialized to zero is kept within this section. The BSS block is created at run-time, allocated immediately after the overlay's data
Relocation block Remaps virtual ram to ram

Locating the header

The last word in an overlay file contains a seek up value that points to the header for the overlay, which in turn points to the start of these blocks.

In ovl_En_Test (0002, Stalfos) for example, the last word in the overlay file is 0x00000640, the file length is 0x58B0 bytes, and the file end in rom is at address 0xC33CD0. Therefore the header is located at...

 0x58B0     0xC33CD0
-0x0640    -0x000640
=0x5270    =0xC33690

...within the actor file and rom respectively.

Block Table

Overlays contain a table that map out the location of all 5 blocks within the file. At offset 0x5270 within ovl_En_Test, you'll find the following 5 words which correspond to the overlay's five blocks.

(Offset 0x5270)
Text block 00004EC0 ( .text) Size in bytes of the text block. Block located at the start of the file.
Data block 000001F0 (.data) Size in bytes of read/write data block following the text block.
Rodata block 000001C0 (.rodata) Size in bytes of the read-only block following the data block.
BSS block 00000000 Size in bytes of the BSS block. It's common for actors to not have a BSS block defined
Relocation block 00000187 Count of one-word long entries of relocation data. Relocation block immediately follows this table.

Relocation Entry Format

Relocation entries are one word (4 bytes) each and are composed of the following:

  1. Section ID
  2. Relocation type
  3. Offset (section relative)


int SectionId; // & C000 0000
int RelocationType; // & 3F00 0000
int Offset; // & 00FF FFFF

S = Section ID

1 = .text
2 = .data
3 = .rodata
4 = .bss

T = Relocation Type

2 = 32 bit pointer
4 = jump target
5 = lui/ori pt. 1
6 = lui/ori pt. 2

(read program Macros below)

O = Offset - relative to start of section s

In relation to (T) the relocation type, the following Macros are from the ELF header on your computer that are used by OoT:

#define R_MIPS_32               2       /* Direct 32 bit         */
#define R_MIPS_26               4       /* Direct 26 bit shifted */
#define R_MIPS_HI16             5       /* High 16 bit           */
#define R_MIPS_LO16             6       /* Low 16 bit            */

Note: There's room for more, but these are the only ones that OoT seems to actualize. Example implementation on 47-50

Arithmetic to acquire above values

The example is 0x44001210, and "w" is the relocation word.

w >> 30 = section: 1         
(w >> 24) & 0x3F = type: 4 
w & 0x00FFFFFF = address: 0x1210

>> is the symbol for a right bitshift operation
& in this context works on the bits instead of the truth values the operands produce (in both instances)

Custom Actors

ZZT32 decided to get off his ass one day and write nOVL, a tool which converts MIPS elf binaries to Zelda 64 overlays. Few actors have been (re)written using mips-gcc + nOVL, but there are a few:

  • En_Anim [1] - An actor written to load any animation.
  • En_AnimVar [2] - A fork of the above actor, uses variables.
  • en_vase [3] - The simplest actor in OoT, re-written in C to test nOVL and to document functions.
  • En_Bird [4] - The simplest animated actor in OoT, re-written for the same reason as En_Vase.

zovldis is the opposite of nOVL - it takes an overlay and disassembles it to an assembly file, which, combined with a proper makefile, produces an identical actor as the one which was disassembled. This makes hacking existing actors much more convenient. An example of actor modification using this approach is seen here (video)
nOvl Windows executable (i686)

When compiling binaries for use as an overlay, you must add the switch -G 0 to prevent it from putting symbols in the small data section, as $gp relative relocations are obviously unimplemented. When linking a binary into an ELF file that is to be converted to an overlay, you must remember to retain all the relocation information with the flag --emit-relocs.

Deathbasket the benevolent says he will further elaborate for nOvl's usage in Majora's Mask, and map functions the actors use.