A Moonmap for Legend of Zelda

Col. G. L. Sicherman. Last revised 2001-05-27. Links updated 2024-01-10.

For game maps, see my Legend of Zelda page.

[ Introduction | General Information | PPU Transfers | Patterns | Layouts | Scrolling | Sound | References ]

Introduction

In 1986 Nintendo introduced the game Legend of Zelda for its Nintendo Entertainment System (N.E.S.). It was played by directing an elflike warrior around a land full of monsters and dungeons to rescue the princess Zelda from the evil Gannon. The game was very popular and did much to promote the N.E.S.

The game cartridge used standard N.E.S. technology. It contained battery-backed RAM for saving up to 3 games between sessions. The code and data resided in ROM.

Nintendo no longer makes the N.E.S. and Legend of Zelda. However, emulators have been written for the N.E.S., and unauthorized ROM dumps of N.E.S. cartridges are available on the World-Wide Web. The Legend of Zelda is commonly found in "iNES" format: 16 bytes of header information; 512 bytes of trainer if present; a dump of ROM, byte by byte; a dump of VROM, byte by byte, and an optional 128-byte trailer with the name of the cartridge, null-filled.

General Information

The image for Legend of Zelda contains 8 ROM segments of $4000 bytes and no VROM. The cartridge uses the MMC1 mapper, in which the last ROM segment, at $1c000, is always mapped to memory at $c000-$ffff. The battery-backed RAM is mapped to $6000-$7fff. The mapping for memory at $8000-$bfff is set by writing the five bits of a segment number, from low to high, to a ROM address in the range $e000-$ffff. Zelda does this with a subroutine at $1ffac.

In this moonmap, a five-digit address denotes RAM or ROM. A four-digit address denotes CPU or PPU memory, with the prefix "P" denoting PPU.

Saved games take up little space in the battery RAM. Most of the space is used for utility routines and data. When the game starts, it calls a subroutine at $04d00 to copy ROM $06500-$0776f to battery RAM $6c90-$7eff.

A computed go-to subroutine resides at $1e5e2. When you call it, it uses A as an index into a table of addresses following the call, and jumps to the address indicated.

PPU Transfers

The program uses code at the beginning of segment $1a000 to load blocks of PPU memory from the cartridge. Each block is prefixed by a three-byte header.

If bit 7 of byte 2 is set, the bytes are to be loaded vertically; that is, at every 32nd byte of PPU memory. Otherwise they are to be loaded contiguously.

If bit 6 of byte 2 is set, the header is followed by a single byte. It is to be replicated into the specified number of PPU locations.

A count of 0 denotes 64 locations.

PPU load blocks are often constructed as needed, usually starting at $0302.

Tagged load blocks are not used for the pattern spaces, which are loaded expressly from large blocks of memory.

Patterns

The fixed patterns are defined at the beginning of segment $08000. The pattern space at P$1000 is used for tiles as follows:

The character set is stored contiguously at $0877f, and the extended miscellaneous graphics are at $08e7f.

Sprites are double; it takes two to make a 16x16 monster. The pattern space at P$0000 is used for sprites as follows:

The fixed sprites are stored contiguously at $0807f.

Segment $0c000 contains the variable patterns for the overworld and underworld, with the code for loading them.

For the overworld, the variable tile patterns are loaded from $0c93b and the sprites from $0d15b.

For the underworld, the variable tile patterns are loaded from $0c11b. The variable sprite space is divided into three sections:

The complete image of sprite memory is maintained at $0200. It is always loaded by DMA transfer using the register at $4014.

The pointers for the dungeons' 3 monster and 3 boss groups reside in two arrays from 0 to 9 at the beginning of segment $0c000. The groups are mutually exclusive except that zols belong to two groups. Thus a dungeon cannot have both goriyas and gibdoes, because they belong to different monster groups. The monsters common to all dungeons are bubble, gel, trap, keese (bat), and the old man who gives hints.

At $04d00 reside the code and pointers for the title-screen patterns. Locations $04d3b and $04d3d point to the variable sprite patterns (at $04db4) and the variable tile patterns (at $056b4). The tile layout for the title screen begins at $1a869. The 28 decorative sprites for the title screen begin at $090ee.

Layouts

General

At $18000 are 31 pointers to general descriptors for the over- and under-worlds. The first 10 point to $300-byte blocks for the overworld and the 9 dungeons. Each $300-byte block contains six $80-byte blocks with a byte for each scene. The next 10, starting at $18014, point to $100-byte blocks. At $18028 is a pointer to a separate descriptor. The last 10, starting at $1802a, point to alternate $300-byte blocks for the overworld and the 9 dungeons.

Overworld

The Overworld is defined by a series of 128-byte tables beginning at $18400. (At run time they are copied into battery RAM at $687E so that the Underworld can share the code.) The screens run from the northwest corner, west to east and north to south.

In the table at $18580, bits 6-0 identify the layout number for the screen. Layout numbers run from $00 to $78 and index a block of 121 sixteen-byte arrays starting at $15418. Each of the 16 bytes defines one column of the layout.

The high nybble of each byte specifies a group of column sequences. The low nybble defines a sequence within the group. There are 16 groups; their addresses are stored starting at $19d0f. The group data begin at $15bd8.

A group consists of a sequence of bytes. The first byte and 8 or 9 others have bit 7 set to denote the start of a sequence. Sequences are designed to overlap to save space, so a sequence seldom begins where the previous sequence ends. Bits 5-0 specify a cluster of four tile codes. Bit 6 is a repeat flag; it means use the cluster twice.

If a cluster code is less than $10, it specifies an explicit set of four tile codes in the array starting at $169b4. If it is $10 or greater, it specifies the starting pattern code for the cluster, in an array based (from $00) at $1697c; the other three pattern codes are the three that follow it in the pattern space.

Serial pattern codes from $e5 to $ea are special and represent mutable quads like bombable caves and burnable trees.

Underworld

Of each $100-byte dungeon descriptor only $fc bytes are used:
$00-$23
PPU load sequence for 8 palettes
$24-$28
miscellaneous data
$29-$2c
preset coordinate pairs for items in rooms
$2d
offset from 16x8 map to player map
$2e
dungeon offset in 16x8 map
$2f
coordinates of entrance room in 16x8 map
$30
coordinates of triforce room in 16x8 map
$31-$32
miscellaneous data
$33
level number tile (in quest 2, may differ from internal number)
$34-$3d
miscellaneous data
$3e
coordinates of boss room in 16x8 map
$3f-$42
null data
$43-$4a
map layout as a columnwise bitmap
$4b-$4e
miscellaneous data
$4f-$db
PPU load sequence for the inset map
$dc-$fb
series of 8 palettes for darkening

The room descriptions are compacted to save space. Dungeons 1 to 6 fit together neatly into a 16-by-8 block; so do dungeons 7 to 9.

        Quest 1, Dungeons 1-6
        
        +-------+ +---+   +-------+---+
        |4 4 4 4| |5 5|   |6 6 6 6|2 2|
        |       +-+   +-+-+       +-+ +-+
        |4 4 4 4|5 5 5 5|6 6 6 6 6 6|2 2|
        |   +---+       |   +---+   |   |
        |4 4|1 1|5 5 5 5|6 6|3 3|6 6|2 2|
        |   +-+ | +---+ |   +-+ | +-+   |
        |4 4 4|1|5|1 1|5|6 6 6|3|6|3|2 2|
        | +---+ +-+ +-+ | +---+ +-+ |   |
        |4|1 1 1 1 1|5 5|6|3 3 3 3 3|2 2|
        | +-+     +-+   | |         |   |
        |4 4|1 1 1|5 5 5|6|3 3 3 3 3|2 2|
        +-+ +-+ +-+     | | +-+ +---+   | 
          |4 4|1|5 5 5 5|6|3|6|3|2 2 2 2|
        +-+ +-+ +-+-+   | +-+ | +-+   +-+
        |4 4|1 1 1| |5 5|6 6 6|3 3|2 2|
        +---+-----+ +---+-----+---+---+
        
        Quest 1, Dungeons 7-9
        
          +-------------+-----------+-+
          |9 9 9 9 9 9 9|7 7 7 7 7 7|8|
        +-+             |         +-+ +-+
        |9 9 9 9 9 9 9 9|7 7 7 7 7|8 8 8|
        |               |       +-+   +-+
        |9 9 9 9 9 9 9 9|7 7 7 7|8 8 8|
        |               |     +-+     +-+
        |9 9 9 9 9 9 9 9|7 7 7|8 8 8 8 8|
        |               |   +-+       +-+
        |9 9 9 9 9 9 9 9|7 7| |8 8 8 8|
        |               |   +-+-+     +-+
        |9 9 9 9 9 9 9 9|7 7 7 7|8 8 8 8|
        +-+           +-+       +---+ +-+
          |9 9 9 9 9 9| |7 7 7 7 7 7|8|
          | +-+   +-+ | |     +-+---+ +-|
          |9| |9 9| |9| |7 7 7| |8 8 8 8|
          +-+ +---+ +-+ +-----+ +-------+
        
        Quest 2, Dungeons 1-6
        
        +-----+ +-----+---+ +-+ +-----+
        |5 5 5| |6 6 6|1 1| |2| |4 4 4|
        |     +-+ +-+ |   +-+ +-+     +-+
        |5 5 5|6 6|3|6|1 1|2 2 2|4 4 4 4|
        +-+-+ |   | | | +-+     |       |
        |3| |5|6 6|3|6|1| |2 2 2|4 4 4 4|
        | +-+ |   | | | +-+     |       |
        |3|5 5|6 6|3|6|1 1|2 2 2|4 4 4 4|
        +-+ +-+   | +-+   |     |       |
        |5 5|6 6 6|3| |1 1|2 2 2|4 4 4 4|
        | +-+     | | | +-+     |       |
        |5|6 6 6 6|3| |1| |2 2 2|4 4 4 4|
        | +---+   | +-+ +-+ +-+ |       |
        |5 5 5|6 6|3 3|1 1|2| |2|4 4 4 4|
        |     +-+ |   |   | | | |     +-+
        |5 5 5| |6|3 3|1 1|2| |2|4 4 4|
        +-----+ +-+---+---+-+ +-+-----+
        
        Quest 2, Dungeons 7-9
        
        +---+       +---+---------------+
        |9 9|       |9 9|8 8 8 8 8 8 8 8|
        |   +-------+   |   +---------+ |
        |9 9 9 9 9 9 9 9|8 8|7 7 7 7 7|8|
        +---+       +---+   | +---+-+ | |
            |9 9 9 9|   |8 8|7|   |8|7|8|
          +-+       +-+ |   | +---+ | | |
          |9 9 9 9 9 9| |8 8|7 7 7|8|7|8|
        +-+           +-+   |     | | | |
        |9 9 9 9 9 9 9 9|8 8|7 7 7|8|7|8|
        |               |   |     | | | |
        |9 9 9 9 9 9 9 9|8 8|7 7 7|8|7|8|
        +-+           +-+   +-----+ | | |
          |9 9 9 9 9 9| |8 8 8 8 8 8|7|8|
          +---+   +---+ +-----------+ | |
              |9 9|     |7 7 7 7 7 7 7|8|
              +---+     +-------------+-+

The unused spots are used to specify subterranean passages. There are six $80-byte descriptor blocks for each matrix.

The layout of a dungeon room is specified in 32 vertical rasters of 22 tiles. The common layout of the outer walls is defined beginning at $15fa0. The 12-by-7 interior is defined by the fourth $80-byte block. Each byte is an index into a block of 12-byte groups at $160de. As with the overworld, a column specifier uses the high nybble to identify a sequence of quad-tile specifiers, and the low nybble to identify the start of a column within the sequence. Addresses of the ten sequences begin at $16704. Bit 7 is the tab flag, indicating the start of a column. Bits 6 to 4 are the repetition count: 0 means 1 copy of the quadtile, 6 means 7 copies. Bits 2 to 0 identify the quad-tile. The eight underworld quad-tiles are defined in an array of starting pattern numbers at $16718: 0=block, 1=floor, 2=goblin, 3=dragon, 4=stair, 5=sand, 6=water, 7=hole.

The doors are defined in the first two $80-byte blocks. In block 0, bits 7-5 define the north wall and bits 4-2 define the south wall. Bits 1-0 are not used. In block 1, bits 7-5 define the west wall and bits 4-2 define the east wall. Bits 1-0 specify one of the dungeon's four tile palettes. The wall encoding is: 0=open, 1=wall, 2=phantom, 4=bombable, 5=locked, 7=magic.

Blocks 4 and 5 specify and locate preset items, and characterize what happens (if anything) when you kill all the monsters.

For passages, block 0 defines the map coordinates of the room at the left end, and block 1 the right end if any. Block 2 defines the quad coordinates at which Link emerges into a room from the passage. Block 3 contains $3f for a single-ended passage or $3e for a double-ended passage.

Scrolling

Legend of Zelda uses split scrolling for overworld and underworld scenes. The scene itself scrolls, but the 64-line status header does not.

The program achieves this by modifying the scroll register or the PPU address register while the PPU is redrawing the screen. Sprite 0, which triggers the hit flag in PPU status register $2002, is a bomb symbol drawn under the bomb tile in the header. At the end of the Vblank interval, the scrolling registers contain zeroes. For special scrolling, the program waits till the bomb sprite triggers the hit flag, delays with a loop while the PPU completes the status header, then sets the registers to scroll the scene as needed.

This method is hard to emulate, because it relies on the hit flag and CPU timing. It is used in many games, including Zelda II.

Sound

Legend of Zelda uses all 5 channels, though channel 5 (for sound effects) is off most of the time. Sounds and sound code reside in segment $00000. The digitized noises take up over half of page $1c000, starting with Link's flying sword.

The pitch table for musical tones begins at $01f00. It contains 57 wave lengths, stored as two-byte values with the high byte first. The highest is 33, or the third A-flat above middle C. The lowest is 1357, or the third E below middle C. They are not stored in order of pitch. The oscillator frequency is 3579545 hz for N.T.S.C. or 3546895 hz for P.A.L.; divide by 32 to get the unit of time.

Five 8-byte duration tables for musical tones are stored contiguously beginning at $01fd1. The units are video scan cycles, 1/60th of a second for N.T.S.C., 1/50th for P.A.L.

The decay envelopes for musical notes are stored in reverse order beginning at $01f92. The high nybbles are for soft music and the low nybbles are for loud music.

At $00d60 resides a block of 36 byte offsets, not all distinct, from $00d60 to 28 music descriptors. The lowest is $24 ($00d84) and the highest is $f5 ($00e55). The structure is:

0
Offset into block of duration arrays at $01fd1.
1-2
Address of music, beginning with channel 2.
3
Offset into music for channel 3.
4
Offset into music for channel 1.
5
Offset into music for channel 4.
6
Intensity: $01 for soft, $80 for loud.
7
Vibrato flag for channel 1. It appears to be used whenever channels 1 and 2 are staggered, as with the dungeon music.

Some descriptors have fewer than 8 bytes.

For channels 1-3, the music is coded as a series of durations and pitches. If a byte's high bit is set, the low 3 bits identify the duration in the selected 8-byte duration table. If the high bit is clear, the value is a byte offset into the pitch table. The music for channel 2 ends with a null byte. The music for the other channels ends implicitly when the music for channel 2 ends. The music for channel 3 may contain repeat signs. A byte of $fX indicates X iterations; a byte of $f0 marks the end of the iterated sequence.

Channel 4 is used for percussion. The music encoding is: bits 5 and 4 encode the noise parameters (duration and intensity), and bits 0, 7, 6 encode the length of the interval, using the duration array for the segment. A noise code of 0 denotes silence. A zero byte denotes the end of the rhythmic unit.

Channel 2 is also used for incidental music. The offset table is at $01a55 and has eight entries, including the famous 8-note sting. Metabytes are controls; the low nybble denotes duration.

References

The classic reference for the N.E.S. is Marat Fayzullin's N.E.S. Architecture, version 2.6. A more complete reference is J.D.C.'s N. E. S. Documentation, version 1.00. (He released a Version 2.00. I do not know where to find it.) Here are a few additions and corrections:

Fayzullin's description of how double sprites are processed is wrong. J.D.C. gives a correct algorithm:

For example, $f2 denotes patterns $f2 and $f3 in the pattern space 0; $f3 denotes patterns $f2 and $f3 in pattern space 1.

Fayzullin gives few details of sound processing. The channels are:

  1. square wave
  2. square wave
  3. sawtooth wave
  4. white noise
  5. digital input
Apparently the intensity of a channel is set by writing into the low nybble of its 0th register. The wavelength is set by writing the low 8 bits into the 2nd register, and the high 3 bits into the 3rd register. If the 2nd and 3rd registers are 0, the channel is silent. For the sawtooth wave, the specified length is for a half period, making the frequency an octave lower than normal.

J.D.C. gives the basic usage for channel 5. Its registers can be used in two ways:

  1. Write an 8-bit pulse-code-modulation value into register 1 ($4011) under program control.
  2. Write a sampling frequency (4 bits) into register 0 ($4010), the address of a block of data into register 2 ($4012) and the length of the block into register 3 ($4013). The address is understood to be %11xxxxxxxx000000 in ROM. The length is in multiples of $10 bytes. Each byte consists of 8 single bit pulses, low bit first.

Zeldit is a ROM editor for Legend of Zelda. Much specific information about locations and code numbers is available at the Zeldit Hacking Page in Zophar's Domain.


Back to Legend of Zelda < Crude ASCII Maps
Col. G. L. Sicherman [ HOME | MAIL ]