Difference between revisions of "SEGA Genesis format"
(Created page with "This file 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), an...") |
(starting, sword) |
||
(4 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | This | + | 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 | + | 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 16: | Line 16: | ||
'''Compression''': The European version of the game uses RNC compression for some graphics. | '''Compression''': The European version of the game uses RNC compression for some graphics. | ||
− | This is a popular library by Rob Northen Computing. | + | This is a popular library by Rob Northen Computing. |
− | '''Hardware''': You can find some documentation about the SEGA Genesis | + | '''Hardware''': You can find some documentation about the SEGA Genesis at Zophar's Domain. |
== Levels == | == Levels == | ||
Line 27: | Line 27: | ||
{| class="wikitable" | {| class="wikitable" | ||
− | ! Game version !! | + | ! 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 | + | '''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: | ||
|} | |} | ||
− | + | '''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: | ||
− | + | * 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 | ||
− | |||
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 | + | * 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''' | '''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 | + | * 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 | + | * 2 bytes: state: (amount of openness) |
− | * 2 bytes: state: 0=closed | + | ** 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 | + | | 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.
Contents
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???)