Difference between revisions of "SEGA Genesis format"

From Princed Wiki
Jump to: navigation, search
(starting, sword)
 
(3 intermediate revisions by the same user not shown)
Line 1: Line 1:
This file describes the format of data in Prince of Persia 1 for the SEGA Genesis, also known as the SEGA Mega Drive.
+
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).
 
The game has two versions: One for the USA (Genesis), and one for Europe (Mega Drive).
Line 7: Line 7:
  
 
'''Byte order''': Big-endian (Motorola, network) byte order is used, unless noted otherwise.
 
'''Byte order''': Big-endian (Motorola, network) byte order is used, unless noted otherwise.
This is the native endianity of the Motorola 68k CPU in the SEGA Genesis.
+
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.
 
'''Numbering of bits''': The least significant bit of a byte is bit 0, the most significant bit of a byte is bit 7.
Line 27: Line 27:
  
 
{| class="wikitable"
 
{| class="wikitable"
! Game version !! Starting address !! Number of levels
+
! Game version !! Address of level table !! Address of starting place table !! Number of levels
 
|-
 
|-
| USA || 0x6A5C || 13 levels
+
| USA || 0x6A5C || 0x20140 || 13 levels
 
|-
 
|-
| Europe || 0x358C2 || 17 levels
+
| Europe || 0x358C2 || 0x504B2 || 17 levels
 
|}
 
|}
  
'''Contents for each level'''
+
'''Contents of the level table'''
  
 
The table stores 20 bytes about each level:
 
The table stores 20 bytes about each level:
Line 58: Line 58:
 
|}
 
|}
  
TODO: Starting position within starting room?
+
'''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 ===
 
=== Maps ===
Line 78: Line 84:
  
 
The possible values are:
 
The possible values are:
<pre>
+
* 0x00: empty
0x00: empty
+
* 0x01: wall
0x01: wall
+
* 0x02: floor (and all objects below include a floor)
0x02: floor (and all objects below include a floor)
+
* 0x03: opener button (*)
0x03: opener button (*)
+
* 0x04: closer button (*)
0x04: closer button (*)
+
* 0x05: gate (*)
0x05: gate (*)
+
* 0x06: loose floor (*)
0x06: loose floor (*)
+
* 0x07: spikes (*)
0x07: spikes (*)
+
* 0x08: chomper (*)
0x08: chomper (*)
+
* 0x09: potion (*)
0x09: potion (*)
+
* 0x0A: level door (*)
0x0A: level door (*)
+
* 0x0B: sword (See [[#The sword]] for further information.)
0x0B: sword
 
</pre>
 
  
 
Further info about objects marked with (*) (and also guards) can be found in the [[#Object tables]].
 
Further info about objects marked with (*) (and also guards) can be found in the [[#Object tables]].
Line 135: Line 139:
 
* 2 bytes: X coordinate (left)
 
* 2 bytes: X coordinate (left)
 
* 2 bytes: 0
 
* 2 bytes: 0
* 2 bytes: first triggered gate: 0-based index into gates table, or 0xFFFF = exit door
+
* 2 bytes: first trigger
* 2 bytes: second triggered gate, or 0xFFFD for none
+
* 2 bytes: second trigger
* 2 bytes: third triggered gate, or 0xFFFD for none
+
* 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'''
 
'''spikes'''
Line 147: Line 157:
 
'''potions'''
 
'''potions'''
 
* 2 bytes: bubble colors: 1 (red) or 3 (green)
 
* 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: Y coordinate (bottom)
 
* 2 bytes: X coordinate (left)
 
* 2 bytes: X coordinate (left)
 
* 2 bytes: 0
 
* 2 bytes: 0
 
* 2 bytes: effect:
 
* 2 bytes: effect:
** 0 = heal
+
** 0 = heal (+1 HP)
** 1 = life
+
** 1 = life (extra HP)
** 2 = hurt
+
** 2 = hurt (-1 HP)
 
** 3 = slow-fall
 
** 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'''
 
'''chompers'''
Line 164: Line 179:
  
 
'''loose floors'''
 
'''loose floors'''
* 2 bytes: 1
+
* 2 bytes: 1 (other values hang the game)
 
* 2 bytes: Y coordinate (bottom)
 
* 2 bytes: Y coordinate (bottom)
 
* 2 bytes: X coordinate (left)
 
* 2 bytes: X coordinate (left)
* 2 bytes: 0
+
* 2 bytes: 0 (animation frame)
 
* 2 bytes: 0
 
* 2 bytes: 0
  
 
'''gates'''
 
'''gates'''
* 2 bytes: state: 0=closed, 3=open
+
* 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: 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: X coordinate (left edge of the gate's tile, but the gate is on the ''right'' edge of this tile)
* 2 bytes: state: 0=closed, 0x0C=open
+
* 2 bytes: state: (amount of openness)
* 2 bytes: state: 0=closed, 0xFFFF=open
+
** 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
 
* 2 bytes: unknown, 0 or 1
  
Line 191: Line 215:
 
* 2 bytes: direction: 0=left, 0x800=right
 
* 2 bytes: direction: 0=left, 0x800=right
 
* 2 bytes: 0
 
* 2 bytes: 0
* 4 bytes: guard sprite (values below are for USA / Europe)
+
* 4 bytes: guard sprite (values below are for USA / Europe) (unused?)
 
** 0x23838 / 0x53C8C = regular guard
 
** 0x23838 / 0x53C8C = regular guard
 
** 0x23954 / 0x53DA2 = skeleton
 
** 0x23954 / 0x53DA2 = skeleton
Line 207: Line 231:
 
* 2 bytes: 0
 
* 2 bytes: 0
 
* 2 bytes: 0
 
* 2 bytes: 0
 +
 +
== Special events ==
 +
 +
=== Starting ===
 +
 +
{| class="wikitable"
 +
! meaning !! USA offset !! Europe offset !! size !! default
 +
|-
 +
| Starting time in frames = Minutes * 60 * Framerate - 1.
 +
Framerate is: USA: 60 / Europe: 50.
 +
|| 0x1DF9C || 0x4E29C || 4 bytes || USA: 0x00034BBF
 +
Europe: 0x0002BF1F
 +
 +
(60 minutes)
 +
|-
 +
| Starting level number - 1. || 0x1DFA6 || 0x4E2A6 || 2 bytes || 0x0000 = 0 = level 1
 +
|-
 +
| Starting hit points. || 0x1DFAE || 0x4E2C0 || 2 bytes || 0x0003 = 3
 +
|}
 +
 +
=== The sword ===
 +
 +
The sword is handled like a special event in this version.
 +
 +
{| class="wikitable"
 +
! meaning !! USA offset !! Europe offset !! size !! default
 +
|-
 +
| Level number - 1. || 0x26D88 || 0x57582 || 2 bytes || 0x0000 = 0 = level 1
 +
|-
 +
| Y coord of room's top edge = (Ypos div 3) * 192 || 0x26D94 || 0x5758E || 2 bytes || 0x00C0 = 192
 +
|-
 +
| X coord of room's left edge = (Xpos div 10) * 320 || 0x26DA0 || 0x5759A || 2 bytes || 0x0000 = 0
 +
|-
 +
| Y coord within level = Ypos * 64 + 55 || 0x26DB6 || 0x575F0 || 2 bytes || 0x0177 = 375
 +
|-
 +
| X coord within level = Xpos * 32 + 25 || 0x26DBC || 0x575B6 || 2 bytes || 0x0059 = 89
 +
|-
 +
| Address of the sword in the [[#Objects map]] in RAM.
 +
Address = Base + Xpos * levelheight + Ypos
 +
 +
Base is: USA: 0xFF15E0 / Europe: 0xFF167A
 +
|| 0x2230C || 0x526EC || 4 bytes || USA: 0x00FF15F7
 +
Europe: 0x00FF1691
 +
 +
(Xpos=2, levelheight=9, Ypos=5)
 +
|-
 +
| Level number - 1, where the prince starts without sword and thus can pick it up. || 0x200B6 || 0x5040A || 2 bytes || 0x0000 = 0 = level 1
 +
|}
  
 
== Level graphics ==
 
== Level graphics ==
Line 261: Line 333:
 
| 15 || 0x8000 || Priority. 0 = behind sprites, 1 = in front of sprites.
 
| 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]].
+
| 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.
 
| 12 || 0x1000 || Vertical flip.

Latest revision as of 11:06, 18 December 2016

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 (See #The sword for further information.)

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

Special events

Starting

meaning USA offset Europe offset size default
Starting time in frames = Minutes * 60 * Framerate - 1.

Framerate is: USA: 60 / Europe: 50.

0x1DF9C 0x4E29C 4 bytes USA: 0x00034BBF

Europe: 0x0002BF1F

(60 minutes)

Starting level number - 1. 0x1DFA6 0x4E2A6 2 bytes 0x0000 = 0 = level 1
Starting hit points. 0x1DFAE 0x4E2C0 2 bytes 0x0003 = 3

The sword

The sword is handled like a special event in this version.

meaning USA offset Europe offset size default
Level number - 1. 0x26D88 0x57582 2 bytes 0x0000 = 0 = level 1
Y coord of room's top edge = (Ypos div 3) * 192 0x26D94 0x5758E 2 bytes 0x00C0 = 192
X coord of room's left edge = (Xpos div 10) * 320 0x26DA0 0x5759A 2 bytes 0x0000 = 0
Y coord within level = Ypos * 64 + 55 0x26DB6 0x575F0 2 bytes 0x0177 = 375
X coord within level = Xpos * 32 + 25 0x26DBC 0x575B6 2 bytes 0x0059 = 89
Address of the sword in the #Objects map in RAM.

Address = Base + Xpos * levelheight + Ypos

Base is: USA: 0xFF15E0 / Europe: 0xFF167A

0x2230C 0x526EC 4 bytes USA: 0x00FF15F7

Europe: 0x00FF1691

(Xpos=2, levelheight=9, Ypos=5)

Level number - 1, where the prince starts without sword and thus can pick it up. 0x200B6 0x5040A 2 bytes 0x0000 = 0 = level 1

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???)