SNES format
This file describes the format of data in PoP1 for SNES.
This document is far from complete. I will continuously add information to it.
Contents
The resource tables
There are 3 resource tables in the ROM, at the following addresses:
Address | Count | Contents |
---|---|---|
0x20000 | 91 or 92 | Levels, Graphics |
0x78000 | 1485 | Sprites |
0xE8000 | 36 or 37 | Sounds, Musics |
A resource table is an array of addresses. Each address is in the following form: A word telling the offset and a byte telling the segment (also called "bank"). Segments are in the range 0x00..0x1F, offsets are in the range 0x8000..0xFFFF. address=segment*0x8000+offset-0x8000
e.g. 0x14 0x81 0x04 means offset=0x8114, segment=0x04, address=0x04*0x8000+0x0114=0x20114 Note that some ROM images have a 0x200 byte header.
The size or type of the resource is not stored.
Contents of the first resource table: (0x20000)
00: menu/intro font 01..40: the 10 enviroments (each type has four resources: background, blocks background, blocks foreground, palette) 0: 01,02,03,04: blue dungeon 1: 05,06,07,08: pink palace 2: 09,10,11,12: grey palace 3: 13,14,15,16: red dungeon 4: 17,18,19,20: green palace 5: 21,22,23,24: brown dungeon 6: 25,26,27,28: red palace 7: 29,30,31,32: level 20 8: 33,34,35,36: jaffar 9: 37,38,39,40: demo red palace 41..67: the 27 levels: level 1-20, jaffar, demo, training 1-5 68: sprite palettes 69: screen palettes 70: hitpoint tiles 71: princess room screen 72: princess room arches screen 73: torch tiles 74: ending font 75: Masiya logo screen 76: stars screen (big) 77: torture screen (big) 78: garden screen (big) 79: title screen 80: title things screen 81: pattern screen 82: game name screen 83: main menu background screen 84: where Jafar walks screen (big) 85: ending: prince at sultan screen 86: ending: prince and princess at window with people screen 87: ending: prince and princess at window with sundown screen 88: ending: sundown screen 89: ending: sundown 2 screen 90: Japanese characters screen 91: Konami logo screen (Europe/USA versions only)
Contents of the second resource table: (0x78000)
0000..1248: regular sprites
1249..1394: sprites that are put into the background (traps, buttons, doors), 48*64 pixels
1395..1484: masks, 48*64 pixels
Contents of the third resource table: (0xE8000)
(needs description)
Resource formats
Tiles
The SNES uses planar tiles, which can be 2- or 4-bit.
(needs further description)
Palettes
The SNES uses 5:5:5 RGB palettes, each entry is a word in the following format:
0bbbbbgggggrrrrr
Environments
(needs description)
Levels
Levels are compressed.
I'll try to explain the algorithm:
procedure decompress_a_part(input:stream of bytes,output:stream of bytes,LEN:integer) clear output repeat while you don't have LEN bytes in the output: read a byte to X if X>=128 then copy X-128 bytes from input to output else read a byte to Y, if Y=0 then Y:=256 if X=1: read a byte to D, write D to output Y times if X=2: read a byte to D, write D,D+1,D+2,... to output, Y bytes total if X=3: read a byte to D, write D,D-1,D-2,... to output, Y bytes total if X=4: read a byte to A, copy Y bytes from the A-th byte of the output to after the end of the output if X=5: read a 2-byte integer to A, copy Y bytes from the A-th byte of the output to after the end of the output // note that the source and destination may overlap in the above two cases otherwise: error end if end repeat end procedure You have to call the above procedure with these values of LEN, and concatenate the outputs: 720,720,720,256,256,256,256,244,256,256 Each input part begins directly after the end of the previous. Calling with LEN=3940 at once won't work, because at the X=4 and X=5 cases, A is counted from the beginning of the current part, not the beginning of the whole level data.
Parts of the level:
Size Contents -------------- 720 background layer 720 blocks layer 720 modifiers layer 256 block layer 1 graphics 256 block layer 2 graphics 256 block objects 256 block flags 244 room links, starting position, guards 256 door events 1 256 door events 2
Background layer
One byte for each tile. Selects which background graphics should be used for this tile.
Blocks layer
One byte for each tile. Selects which block should be used for this tile.
Informations about blocks are found in the four parts whose names begin with "block".
Some blocks are used for special purposes:
Block 255 is used for nonexistent rooms. (Room link=255) It is usually a wall.
Block 254 is used for buttons that are permanently triggered by a dead guard or loose floor. It is usually a floor.
Reason: Button blocks don't have floor graphics, because the button object draws it for them.
If a button is triggered permanently, it needs to be changed into a regular floor, which does need floor graphics.
The only way this can be done is placing a different block into the place of the button.
Modifiers layer
One byte for each tile. Selects which modifier should be used for this tile.
Its meaning depends on the object used.
Block layer 1 graphics
One byte for each block type. Selects which background graphics should be used for this block type.
Block layer 2 graphics
One byte for each block type. Selects which foreground graphics should be used for this block type.
Block objects
One byte for each block type. Selects which object should be used for this block type.
value object type --------------------- 0x00 (none) 0x01 (unused) 0x02 loose floor 0x03 (unused) 0x04 open button 0x05 close button 0x06 door 0x07 leveldoor end 0x08 mirror 0x09 skeleton 0x0A sword 0x0B torch 0x0C chomper 0x0D guillotine 0x0E spike 0x0F (unused) 0x10 crusher 0x11 (unused) 0x12 heal potion 0x13 life potion 0x14 hurt potion 0x15 upside down potion 0x16 slow fall potion 0x17 debris 0x18 door top 0x19 fire 0x1A potion of warp 0x1B down only 0x1C kill potion 0x1D torch 0x1E spinning log 0x1F (unused) 0x20 stars 0x21 torch 0x22 torch 0x23 teleport 0x24 leveldoor begin 0x25 (unused) 0x26 (unused) 0x27 lava 0x28 skeleton continue 0x29 skull? 0x2A conveyor belt >>> 0x2B conveyor belt <<<
Notes:
There are four torch objects. They differ in the position of the flames.
The potion of warp will take the player to room 17, tile 11, turned left.
"skeleton continue" means that if a skeleton falls into this room then it will appear here.
"down only": if added to a block that has floor, the player can fall through it, but can't jump/climb up through it.
If the modifier is in the 1..4 range, the transparent floor you can see after the shadow fight will appear.
Lava: falling onto this tile from any height will kill the prince.
Meaning of the modifier for each object:
For the loose floor, chomper, guillotine, spike, crusher, down only, spinning log, stars objects,
the modifier selects the animation frame to be displayed. It should be zero.
For the open and close buttons, the modifier selects the door event to be triggered.
For doors, the modifier specifies how much the door is open, in 1/4 pixels.
Teleports: Entering a teleport will take to the other teleport with the same modifier.
Block flags
One byte for each block type. Determines if the current block type is a floor or a wall.
If bit 0 is set then this block type is a floor.
If bit 1 is set then this block type is a wall.
The meaning of other bits (if any) is unknown.
Room links, starting position, guards
Size Contents -------------- 24*4 Room links 1 Starting room 1 Starting position in room 1 Starting direction 1 unused 24 Guard position in room 24 Guard type and direction 4*24 unknown
Room links: For every room, the room to the left, right, above and below the current room is given, in this order.
The rooms are numbered 0..23.
255 means that no room is in the given direction.
For the "above" link, 254 means the same, plus that the 4-pixel part of the room above (which would have walls) is not shown.
This is used for special "outdoor" rooms.
Note: rooms are numbered 0..23, which is different from the DOS version.
Starting room: The room the player starts in. Can be 0..23.
Starting position in room: row*10+column. (0..29)
Starting direction: 0xFF=left, 0x00=right.
Guard position in room: row*10+column (0..29), or 0xFF if there is no guard in this room.
Guard type and direction: The bottom 7 bits specify the guard type, the top bit specifes the direction. 1=left, 0=right.
value guard type --------------------- 0x02 dead purple 0x03 skeleton 0x04 brown skeleton 0x05 golden skeleton 0x06 girl 0x07 fat 0x08 shadow 0x09 green 0x0A greenish blue 0x0B blue 0x0C red 0x0D purple 0x0E blueface 0x0F red knight 0x10 blue knight 0x11 monster 0x12 Jaffar 0x13 dead
Other values may display garbage or may even hang the game.
Door events 1 and 2
(same format as in DOS version) ------------------------- 7 6 5 4 3 2 1 0 <-bits byte from door events 1 | NX R1 R0 L4 L3 L2 L1 L0 byte from door events 2 | R4 R3 R2 0 0 0 0 0
R4 R3 R2 R1 R0: The number of the room. (0..23)
L4 L3 L2 L1 L0: The location in the room. (0..29)
NX: If zero then trigger next door event, if one then don't.
Screens
Screens are compressed.
(needs further description)
screen=32*28 tiles
big screen=64*56 tiles
Sprites
Sprites are compressed.
(needs further description)
Musics
(needs description)