World Maps - GameHackingDotOrg/FF4Hacking GitHub Wiki

Note: All ROM offsets in this document are hexadecimal offsets into an unheadered v1.1 ROM.

The Overworld, Underworld, and Moon maps are encoded and rendered the same way, and are thus referred to as "World Maps".

Tile Graphics

Graphics data consists of 8x8 blocks of pixels called characters. Pixels are 4 bits (4bpp), so each character is 32 bytes in length. The low-order bits are the "first" pixel, and the high-order bits the "second" pixel in each byte. Each World Map uses 256 characters, for a total of 8 KiB of graphics.

There are 64 total colors available for rendering World Maps, stored as 16-bit color values in the format xbbbbbgggggrrrrr (the high bit is ignored). Each character uses 16 consecutive colors from the overall palette. One byte per character specifies the offset of the first color for that character, and the other 15 follow. Note, Mode 7 allows for 256 total colors, but the rest of the colors are used for other things, like the player's character, airships, triggered event sprites, etc.

Tile Formations

World Maps use tilesets of 128 16x16 tiles, made up of 4 characters each. A table of 512 bytes defines the characters that make up each tile, but the character references are interleaved. The first 128 bytes are the upper-left character of each tile, the next 128 bytes are the upper-right character, then the lower-left, and finally the lower-right.

Additionally, each of the 128 tiles has a set of flags that define in-game properties of the tile, such as whether it can be walked on or landed on with the airship, etc. "Walk Plateau" is used to prevent the player from walking directly from a plateau tile to a ground tile. For the "ramp" tile on the Moon, both the Walk and Walk Plateau bits are set, so the player can walk from the ground onto the ramp or from the ramp onto the plateau. "Obscures Half" means the player character is half obscured by forest/water/etc.

Property Bit
Walk 0x0001
Chocobo Walk 0x0002
Black Chocobo Fly 0x0004
Black Chocobo Land 0x0008
Hovercraft 0x0010
Airship Fly 0x0020
Walk Plateau 0x0040
Big Whale Fly 0x0080
Obscures Half 0x0800
Airship Land 0x1000
Enemies Present 0x4000
Trigger 0x8000

Tile Data Offsets

Map CHR Graphics (8 KiB) Overall Palette (128 bytes) CHR Palettes (256 bytes) Tile Formations (512 bytes) Tile Properties (256 bytes)
Overworld 0x0E8000 0x0A0900 0x0A0600 0x0A0000 0x0A0A80
Underworld 0x0EA000 0x0A0980 0x0A0700 0x0A0200 0x0A0B80
Moon 0x0EC000 0x0A0A00 0x0A0800 0x0A0400 0x0A0C80

Tilemap Encoding

World Maps use Run-Length Encoding (RLE), but unlike Dungeon Maps, they are compressed one row at a time, as the SNES does not have enough memory to decompress the entire map at once. Pointers to the beginning of each row are stored at the beginning of the map data for each World Map. Each 2-byte row pointer is an offset from the beginning of the tilemap data itself, i.e. 0x0000 is the very beginning of the tilemap (this differs from the FF1 World Map, where the pointers are actual addresses into the world map's ROM bank).

Since a tileset contains 128 tiles, tile values range from 0x00 through 0x7F. A byte containing any of these values represents one tile. A byte from 0x80 through 0xFE represents a run of tiles, with the tile index being the value of the byte - 0x80 (i.e. with the high bit masked out). The following byte is the length of the run - 1, so 92 05 would be a run of 6 of tile 0x12. Rows are terminated with 0xFF, and as such, there is no way to encode a run of the 0x7F tile.

The Overworld has a special case for compressing snow-capped mountains. The 0x00, 0x10, 0x20, and 0x30 values all represent a run of 4 distinct tiles:

  • 0x00: 00 70 71 72
  • 0x10: 10 73 74 75
  • 0x20: 20 76 77 78
  • 0x30: 30 79 7A 7B

These special tiles are always placed adjacent to each other vertically, so they represent a 4x4 area of snow-capped mountain tiles in just 4 bytes. This tile formation is only found on the Overworld, and the Underworld and Moon maps do not use this encoding rule.

The Overworld and Underworld maps are 256x256 tiles, and the Moon map is 64x64. Though the Underworld has the same dimensions as the Overworld, it only really uses about half of the available horizontal and vertical space, so it compresses down to about half the size.

Tilemap Offsets

Map Row Pointers Start of Tilemap Allocated Space
Overworld 0x0B0000 0x0B0480 0x4000 bytes (16 KiB)
Underworld 0x0B0200 0x0B4480 0x1D00 bytes (7.25 KiB)
Moon 0x0B0400 0x0B6180 0x0A00 bytes (2.25 KiB)