Dragon Warrior IV (NES)/Map Data Format

From Data Crystal
Jump to navigation Jump to search

This is a sub-page of Dragon Warrior IV (NES).

This is the Map Data Format for Dragon Warrior IV as used in Towns and Caves, and not the overworld.

Getting the address of a map

There are two variables that determine a map, the Map Number ($63) and the Submap Number ($64).

See ROM Map, Bank 17 for more information, or ROM Map, Bank 09 for the map addresses.

Header

  • Byte 0: Map Width
  • Byte 1: Map Height
  • Byte 2: tttTTTTT
    • ttt = Number of bits per tile (0-7), usually 5
    • TTTTT = Border Tile (00-1F)

After reading Width and Height, calculate the number of bits required to store a map address.

Number of Bits Needed = Ceil(Log2(Width * Height))


Main Map Data

The main map data is composed of strings of bits. Most Significant Bit is first within a byte.

Reading a Tile number

You read a number of bits, usually 5 bits (for tile numbers 00-1F), but the bit count is determined by the header, and is changed again after entering Roof Mode.

Reading a Map Address

You read a number of bits based on the highest number that could fit into Map Width * Map Height. Again, number of bits = Ceil(Log2(Width * Height))

Clearing the Map

Before entering the Main Loop:

  • Read a tile number
  • Set the entire map to this tile number.

Main Loop

  • Read 2 bits.
    • Command 0 = Set Tile Number
    • Command 1 = Draw Box
    • Command 2 = Paint Mode
    • Command 3 = Plot an individual tile

Command 0 - Set Tile Number

  • Read a Tile Number, set Current Tile to this.
  • Read 2 bits.
  • If value is not zero, treat this as a command from the main loop, and proceed to that code.
  • Otherwise:
  • Read a bit
  • If it is zero
    • Set Large Tile Mode flag (Painting will use 4 tiles instead of 1)
    • Read three more tile numbers, return to Main Loop.
  • If it is 1, Exit the main loop.

Command 1 - Draw Box

  • Read a Map Address (Top-Left coordinate)
  • Read a second Map Address (Bottom-Right coordinate, Inclusive)
  • Fill the box (Either single tile, or Large Tile mode)
  • Return to Main Loop

Command 2 - Paint Mode

Variables used:

  • Cursor (a map address)
  • Paint Direction
    • 0 = Up
    • 1 = Right
    • 2 = Down
    • 3 = Left
  • A stack of 'cursor location' and 'direction'
  • A stack pointer

Entering Paint Mode:

  • Read Map Address to Cursor
  • Paint the tile on the map
  • Read two bits to Paint Direction

Loop:

  • Read one bit
    • If 0: goto Paint (painting in same direction)
    • If 1: Not same direction
  • Read two bits
    • If 0: Inc Direction, then goto Paint
    • If 1: Dec Direction, then goto Paint
    • If 2:
      • Push Cursor and Direction onto the stack
      • Read one bit:
        • If 0: Inc Direction, goto Paint
        • If 1: Dec Direction, goto Paint
    • If 3:
      • Read one bit:
        • If 0: Restart Paint Mode (picking a new map location)
        • If 1: Pop Cursor and Direction from the stack, then goto Loop
          • If stack is empty, instead exit and return to the Main Loop.

Paint:

  • Advance cursor in the current direction (If in large tile mode, advance cursor by 2 instead)
  • Paint tile on the map (possibly a large tile)
  • goto Loop

Command 3 - Plot one tile

  • Read a map address
  • Plot the tile on the map
  • Return to the Main Loop

Painting the Tile on the Map

When painting the tile, it's either a single tile, or a large tile (4 tiles).

This is also used for Roof Mode. If you are in Roof Mode, instead of assigning the tile, set the top 3 bits to the current roof number.

Roof Tiles

After exiting out of the Main Loop for the first time:

  • Read 2 bits
    • If 0, there are no roofs.
    • Otherwise, store this value (1-3) as the number of bits per tile.
    • Enter the Main Loop again, but we're painting on Roof Numbers instead of Tile Numbers


Smoothing Tiles

After the entire map has loaded, Smoothing Flags from the Tileset are used to change some tiles.

TODO: document this better

Three bits are are used for tile smoothing flags. These three bits are stored as part of the tileset when it is loaded, they are not in the map data.

  • 0 = No group
  • 1 = Group 1
  • 2 = Group 2
  • 3 = Group 3
  • 4 = not used
  • 5 = Front-Facing tile of Group 1
  • 6 = Front-Facing tile of Group 2
  • 7 = Front-Facing tile of Group 3

If a tile has a group, and the tile below it has NO group, then it is changed to the front-facing version of the tile.

Normally, this is used to change Wall Tiles into Front-Facing wall tiles.