SEGA Genesis format

From Princed Wiki
Revision as of 14:51, 26 November 2016 by David (talk | contribs) (Added trigger 0xFFFE.)
Jump to: navigation, search

This document describes the format of data in Prince of Persia 1 for the SEGA Genesis, also known as the SEGA Mega Drive.

The game has two versions: One for the USA (Genesis), and one for Europe (Mega Drive). They have data at different offsets, and I will always note which offsets are for which versions.

General

Byte order: Big-endian (Motorola, network) byte order is used, unless noted otherwise. This is the native endianness of the Motorola 68k CPU in the SEGA Genesis.

Numbering of bits: The least significant bit of a byte is bit 0, the most significant bit of a byte is bit 7.

Addresses: Since the CPU is 32-bit, there are no segments, banks, paging, or anything like that. You can just use each address as it is. (Only the bottom 24 bits are used by the hardware. The top 8 bits are usually 0, though.)

Compression: The European version of the game uses RNC compression for some graphics. This is a popular library by Rob Northen Computing.

Hardware: You can find some documentation about the SEGA Genesis at Zophar's Domain.

Levels

The level table

Starting address

Game version Address of level table Address of starting place table Number of levels
USA 0x6A5C 0x20140 13 levels
Europe 0x358C2 0x504B2 17 levels

Contents of the level table

The table stores 20 bytes about each level:

Size Contents
2 bytes Level's height, in pixels. Must be a multiple of 192, the height of a room. Divide by 64 to get the height in tiles.
2 bytes Level's width, in pixels. Must be a multiple of 320, the width of a room. Divide by 32 to get the width in tiles.
2 bytes Size of each level map, in tiles (bytes). (width * height)
4 bytes Start address of level's #Graphics map.
4 bytes Start address of level's #Objects map.
2 bytes Y coordinate of the top of the starting room, in pixels. Subject to the same restrictions as level height.
2 bytes X coordinate of the left of the starting room, in pixels. Subject to the same restrictions as level width.
2 bytes Level type: 0=dungeon, 1=palace.

Contents of the starting place table

The table stores 6 bytes about each level:

  • 2 bytes: starting Y coordinate, in pixels (bottom)
  • 2 bytes: starting X coordinate, in pixels (left)
  • 2 bytes: starting direction: 0=left, 0x800=right

Maps

Both maps store tiles in column-major order. That is, you start from the top-left corner of the level, and go down. After you finished a column, you continue at the top of the next column.

Note that maps are not split into rooms (only when displayed), and therefore there are no room links or room numbers.

Graphics map

Each byte tells which #Level graphics block is to be displayed here. The same index is used for both layers.

Objects map

Each byte tells what object is in the corresponding tile.

The possible values are:

  • 0x00: empty
  • 0x01: wall
  • 0x02: floor (and all objects below include a floor)
  • 0x03: opener button (*)
  • 0x04: closer button (*)
  • 0x05: gate (*)
  • 0x06: loose floor (*)
  • 0x07: spikes (*)
  • 0x08: chomper (*)
  • 0x09: potion (*)
  • 0x0A: level door (*)
  • 0x0B: sword

Further info about objects marked with (*) (and also guards) can be found in the #Object tables.

Object tables

type of object USA address Europe address bytes per object
opener buttons 0x1E592 0x4E8F6 14
closer buttons 0x1EBFC 0x4F138 14
spikes 0x25F94 0x56612 8
potions 0x27BAE 0x581B0 10
chompers 0x228DE 0x52D86 10
loose floors 0x1CD3E 0x4CF3C 10
gates 0x5B96 0x61CE 12
level doors 0x41DE 0x46C2 10
guards 0x1FAC 0x2B02 24

Each table has a header. The header contains 6 bytes per level:

  • 2 bytes for the number of objects on that level,
  • 4 bytes for the start address of the sub-table of the objects on this level. (It's 0 if the count is 0.)

(The two bytes before the header always contain 0x4E75. This is the RTS instruction that ends the preceding subroutine.)

The contents of each table depend on the type of the object.

All coordinates are in pixels.

opener and closer buttons

  • 2 bytes: 1
  • 2 bytes: Y coordinate (bottom)
  • 2 bytes: X coordinate (left)
  • 2 bytes: 0
  • 2 bytes: first trigger
  • 2 bytes: second trigger
  • 2 bytes: third trigger

The triggers can have these values:

  • 0-based index into gates table
  • 0xFFFF = exit door
  • 0xFFFE = used for the button that opens the level 4 exit (=mirror?)
  • 0xFFFD = none

spikes

  • 2 bytes: 1
  • 2 bytes: Y coordinate (bottom)
  • 2 bytes: X coordinate (left)
  • 2 bytes: 0xFFFF

potions

  • 2 bytes: bubble colors: 1 (red) or 3 (green)
    • Even values (like 0 or 2) will make the potion gone.
  • 2 bytes: Y coordinate (bottom)
  • 2 bytes: X coordinate (left)
  • 2 bytes: 0
  • 2 bytes: effect:
    • 0 = heal (+1 HP)
    • 1 = life (extra HP)
    • 2 = hurt (-1 HP)
    • 3 = slow-fall
    • 4 = shake screen and drop all loose floors in the whole level
    • 5 = stop time temporarily
    • 6..9 = extra time (+5 minutes)

Potion effects 4..9 are available only in the European version.

chompers

  • 2 bytes: 1
  • 2 bytes: Y coordinate (top)
  • 2 bytes: X coordinate (left)
  • 2 bytes: 0
  • 2 bytes: 0

loose floors

  • 2 bytes: 1 (other values hang the game)
  • 2 bytes: Y coordinate (bottom)
  • 2 bytes: X coordinate (left)
  • 2 bytes: 0 (animation frame)
  • 2 bytes: 0

gates

  • 2 bytes: state: (animation)
    • 0=closed
    • 1=open on start (not used)
    • 3=open
    • 7=close on start
  • 2 bytes: Y coordinate (top)
  • 2 bytes: X coordinate (left edge of the gate's tile, but the gate is on the right edge of this tile)
  • 2 bytes: state: (amount of openness)
    • 0=closed
    • 1..0x0B=partially open (not used)
    • 0x0C=open / close on start
  • 2 bytes: state: (time before gate starts closing)
    • 0=closed / close on start
    • 0xFFFF=open
  • 2 bytes: unknown, 0 or 1

level doors

  • 2 bytes: type: 0=start, 2=exit door
  • 2 bytes: Y coordinate (top)
  • 2 bytes: X coordinate (left)
  • 2 bytes: 0
  • 2 bytes: 0

guards

  • 2 bytes: 0
  • 2 bytes: Y coordinate (bottom)
  • 2 bytes: X coordinate (left)
  • 2 bytes: direction: 0=left, 0x800=right
  • 2 bytes: 0
  • 4 bytes: guard sprite (values below are for USA / Europe) (unused?)
    • 0x23838 / 0x53C8C = regular guard
    • 0x23954 / 0x53DA2 = skeleton
    • 0x23DD8 / 0x54226 = fat
    • 0x24000 / 0x54448 = shadow
    • 0x241B2 / 0x545FA = Jaffar
  • 2 bytes: guard type
    • 0 = regular guard
    • 1 = skeleton
    • 2 = fat
    • 3 = shadow
    • 4 = Jaffar
  • 2 bytes: skill
  • 2 bytes: hit points
  • 2 bytes: 0
  • 2 bytes: 0

Level graphics

USA:

Level type Palette addr Tiles addr Blocks addr Number of tiles
0 (dungeon) 0x47B20 0x40AC0 0xDCEE 898
1 (palace) 0x4E680 0x47B40 0x154EE 858

Europe:

Level type Palette addr Tiles addr Blocks addr Number of tiles
0 (dungeon) 0x7976C 0x732D6 0x3DEEC 898
1 (palace) 0x7FA38 0x797AC 0x456EC 858

Palettes

A palette contains 16 colors. Each color is stored on 16 bits (2 bytes), in X:R:G:B = 4:4:4:4 bits format. (This means that a palette takes up 32 bytes.)

But each level graphics has two palettes, so there are 32 colors (64 bytes) at the pointed address!

Tiles

Each tile has 8*8 pixels. Each pixel is stored on 4 adjacent bits. (This means that each tile takes up 32 bytes.)

Within a byte, bits 7..4 store the left pixel, and bits 3..0 store the right pixel. (There is no interleaving or separated planes, as on some other hardware. (SNES, etc.))

Color 0 is transparent!

Blocks

There are 2*256 blocks. The first 256 are for the back layer, the next 256 for the front layer. Block with the same index from the two layers are always used together.

Each block is 4 tiles (32 pixels) wide and 8 tiles (64 pixels) high.

Each tile-position is stored on 2 bytes (16 bits):

bits mask meaning
15 0x8000 Priority. 0 = behind sprites, 1 = in front of sprites.
14..13 0x6000 Palette index (0..3). For level graphics, only 0 and 1 are used, corresponding to the two palettes mentioned in #Palettes.
12 0x1000 Vertical flip.
11 0x0800 Horizontal flip.
10..0 0x07FF Tile number.

TODO

  • Texts
  • Sprites
  • Full-screen images
  • Sound samples?
  • (Music???)