Difference between revisions of "Game Boy format"
(guards, start on level) |
(texts, sprites, maps, sounds) |
||
Line 51: | Line 51: | ||
<pre> | <pre> | ||
repeat while you don't have enough output bytes: | repeat while you don't have enough output bytes: | ||
− | read 1 byte; | + | read 1 byte from input; |
if the byte appears in "left": | if the byte appears in "left": | ||
count := 1; | count := 1; | ||
repeat: | repeat: | ||
− | read 4 bits through a 8-bit queue into value; | + | read 4 bits from input through a 8-bit queue into value; |
+ | That is: | ||
+ | first time, you read a byte from input and use bits 7..4; | ||
+ | second time, you use bits 3..0 of the already read byte and discard the byte. | ||
count := count + value; | count := count + value; | ||
while value = 0xF; | while value = 0xF; | ||
Line 220: | Line 223: | ||
== Palettes (GBC) == | == Palettes (GBC) == | ||
+ | |||
+ | A palette is 64 bytes long, and contains 32 colors, grouped into 8 sets of 4 colors each. | ||
Each color is stored on 16 bits (2 bytes): | Each color is stored on 16 bits (2 bytes): | ||
Line 228: | Line 233: | ||
Offsets: | Offsets: | ||
− | * 0x087D0..0x0880F: level palette: 1 set of 32 colors, referenced from [[#Level settings]] | + | * 0x087D0..0x0880F: level background palette: 1 set of 32 colors, referenced from [[#Level settings]] |
− | * 0x09BB4..0x09BF3: level palette: 1 set of 32 colors, referenced from [[#Level settings]] | + | * 0x09BB4..0x09BF3: level background palette: 1 set of 32 colors, referenced from [[#Level settings]] |
− | * 0x0AEE0..0x0B19F: level palettes: 11 sets of 32 colors, referenced from [[#Level settings]] | + | * 0x0AEE0..0x0B19F: level background palettes: 11 sets of 32 colors, referenced from [[#Level settings]] |
− | * 0x0B1A0..0x0B31F: sprite palettes: 6 sets of 32 colors, referenced from [[#Level settings]] | + | * 0x0B1A0..0x0B31F: level sprite palettes: 6 sets of 32 colors, referenced from [[#Level settings]] |
− | * 0x1137F..0x113AE: title screen palette | + | * 0x1137F..0x113AE: title screen background palette |
− | * 0x12B96..0x12BC5: | + | * 0x12B96..0x12BC5: story frame+text background palette |
− | * 0x2925C..0x2929B: copyrights screen palette (Red Orb) | + | * 0x2925C..0x2929B: copyrights screen background palette (Red Orb) |
+ | |||
+ | == Texts == | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! version !! story texts table offset !! copyrights text offset !! credits texts offsets !! story text languages | ||
+ | |- | ||
+ | | GBC || 0x12FEE || see [[#Other graphics (GBC)]] || 0x13016, 0x13033, 0x1304B, 0x13070, 0x1308F || German, French, Spanish, English, Italian | ||
+ | |- | ||
+ | | GB EU || 0x13087 || 0x130AF || 0x131DE, 0x131F9, 0x1321D, 0x1323C, 0x1325D || German, English, Spanish, French, Italian | ||
+ | |- | ||
+ | | GB JP || 0x13087 || 0x130AF || 0x13205, 0x1322A, 0x1324E, 0x1326D, 0x1328E || (ununsed), Japanese, (unused), (unused), (unused) | ||
+ | |} | ||
+ | |||
+ | The story texts table contains 20 offsets (2 bytes each) for each 4 occasions (intro 1, intro 2, bad ending, good ending) and for each 5 languages. | ||
+ | |||
+ | Fonts are stored in [[#Tilesets]]. | ||
+ | |||
+ | === European === | ||
+ | |||
+ | The decoding of European texts: | ||
+ | * Repeat until you meet the end of text marker: | ||
+ | ** Read a byte. | ||
+ | ** Subtract 0x20 and truncate the result to a byte. | ||
+ | ** The lower 6 bits tell the index of the character within the font. | ||
+ | ** The upper 2 bits tell what is after the character: | ||
+ | *** 00 = nothing | ||
+ | *** 01 = new line | ||
+ | *** 10 = space | ||
+ | *** 11 = end of text | ||
+ | |||
+ | The character set: | ||
+ | <pre> | ||
+ | !"Ñ$Ç&'®®©+,-./ | ||
+ | 0123456789:Ù¡=¿? | ||
+ | ÄABCDEFGHIJKLMNO | ||
+ | PQRSTUVWXYZÖÜÀÈÌ | ||
+ | </pre> | ||
+ | * This mostly corresponds to range 0x20..0x5F from ASCII, but most symbols were replaced with accented letters or other symbols. | ||
+ | * The zero is used for Ø in BRØDERBUND's name. | ||
+ | * The two instances of ® are the top and bottom halves. | ||
+ | |||
+ | === Japanese === | ||
+ | |||
+ | This is only for story texts, the others are encoded as European. | ||
+ | |||
+ | The decoding of Japanese texts: | ||
+ | * Repeat until you meet the end of text marker: | ||
+ | ** Read a byte. | ||
+ | ** It can have the following values: | ||
+ | *** 0x00..0x7F = The index of the character within the font. | ||
+ | *** 0xFE = new line | ||
+ | *** 0xFF = end of text | ||
+ | |||
+ | The character set: | ||
+ | <pre> | ||
+ | んわらやまはなたさかあゃぁりみ | ||
+ | ひにちしきいぃるゆむふぬつすくう | ||
+ | ゅっれめへねてせけえぇをろよもほ | ||
+ | のとそこおょぉンワラヤマハナタサ | ||
+ | カアャァリミヒニチシキイィルユム | ||
+ | フヌツスクウュッレメヘネテセケエ | ||
+ | ェヲロヨモホノトソコオョォ?!゛ | ||
+ | ゜」「…、。ゥー60 | ||
+ | </pre> | ||
+ | * This is different from all encodings that I've seen so far. | ||
+ | * There is some logic if you compare it with the usual syllable tables: | ||
+ | ** Elsewhere, the syllables are ordered first by consonant (-,K,S,T,N,H,M,Y,R,W), and then by vowel (A,I,U,E,O). | ||
+ | ** Here, the syllables are ordered first by vowel (A,I,U,E,O), and then by consonant, but in reverse order (W,R,Y,M,H,N,T,S,K,-). | ||
+ | |||
+ | == Sprites (GBC) == | ||
+ | |||
+ | {| class="wikitable" | ||
+ | ! start address !! size of each item !! contents | ||
+ | |- | ||
+ | | 0x28000 || 2 bytes || map offset (b/w) | ||
+ | |- | ||
+ | | 0x28168 || 2 bytes || map offset (color) | ||
+ | |- | ||
+ | | 0x282D0 || 2 bytes || tiles offset (b/w) | ||
+ | |- | ||
+ | | 0x28438 || 2 bytes || tiles offset (color) | ||
+ | |- | ||
+ | | 0x285A0 || 1 byte || bank for map and tiles (b/w) | ||
+ | |- | ||
+ | | 0x28654 || 1 byte || bank for map and tiles (color) | ||
+ | |- | ||
+ | | 0x28708 || 1 byte || X offset in tiles (+ = backwards) | ||
+ | |- | ||
+ | | 0x287BC || 1 byte || X hit test? | ||
+ | |- | ||
+ | | 0x28870 || 1 byte || Y offset in tiles (+ = up) | ||
+ | |- | ||
+ | | 0x28924 || 1 byte || Y hit test? | ||
+ | |- | ||
+ | | 0x289D8 || 2 bytes || offset of associated sound effect (in bank 0x0F), see [[#Sound effects (GBC)]] | ||
+ | |- | ||
+ | | 0x28B40 || 1 byte || ? | ||
+ | |- | ||
+ | | 0x28BF4 || 1 byte || ? | ||
+ | |- | ||
+ | | 0x28CA8 || 1 byte || flags | ||
+ | * bit 0: unknown | ||
+ | * bit 1: unknown | ||
+ | * bit 2: Does the char press the floor? Used with loose floors and buttons. | ||
+ | * bit 3: unknown | ||
+ | |} | ||
+ | * Every table has 0xB4 = 180 items. | ||
+ | * It seems that the Color version can run in b/w mode as well, with different graphics. Change the byte at offset 0x143 to 0x00 for this. | ||
+ | * Offsets and banks can be all zero, in this case there are no sprites in this group. | ||
+ | |||
+ | At the map offset there is the following data: | ||
+ | * 1 byte: number of images in sprite group | ||
+ | * 1 byte: width of each image | ||
+ | * 1 byte: height of each image | ||
+ | * for each image: | ||
+ | ** for each row: | ||
+ | *** for each column: | ||
+ | **** 1 byte: 1-based index of tile, or 0 for none | ||
+ | |||
+ | At the tile offset there is the following data: | ||
+ | * 1 byte: compression marker | ||
+ | * 1 byte: number of tiles | ||
+ | * for each tile: | ||
+ | ** 4 bits: compressed size of tile in bytes (first read bits 7..4, then read bits 3..0) | ||
+ | ** Possible values are 9..15, and 0 which means 16. | ||
+ | * (pad to whole byte using 0 bits, if necessary) | ||
+ | * for each tile: | ||
+ | ** for each pixel row: (0..7) | ||
+ | *** Read 1 byte. | ||
+ | *** If it's equal to the compression marker, repeat the last two bytes. | ||
+ | *** Otherwise, output the byte, read another byte, and output it as well. | ||
+ | |||
+ | == Tiles == | ||
+ | |||
+ | The Game Boy (Color) uses 2-bit planar tiles. | ||
+ | |||
+ | Tiles are in this format: (after decompression) | ||
+ | <pre> | ||
+ | for B=0..7: | ||
+ | byte B of plane 0 | ||
+ | byte B of plane 1 | ||
+ | </pre> | ||
+ | |||
+ | To get the color index of a pixel, from X and Y coordinates: | ||
+ | <pre> | ||
+ | color = 0 | ||
+ | for P=0..1: | ||
+ | read bit 7-X of byte Y of plane P of the tile, and write it into bit P of color | ||
+ | </pre> | ||
+ | This color index can be further modified by colormaps. See [[#Maps]]. | ||
− | == Various hacks == | + | == Other graphics (GBC) == |
+ | |||
+ | === Tilesets === | ||
+ | |||
+ | They use the same compression as sprite tiles. | ||
+ | * 0x08810: color dungeon | ||
+ | * 0x09BF4: color palace | ||
+ | * 0x0AA57: status bar | ||
+ | * 0x101B8: b/w intro+font | ||
+ | * 0x113BF: color intro+font | ||
+ | * 0x1240E: b/w font+frame | ||
+ | * 0x12BD6: color font+frame | ||
+ | * 0x20004: b/w spikes | ||
+ | * 0x20023: b/w spikes? | ||
+ | * 0x20045: b/w spikes? | ||
+ | * 0x20066: color spikes | ||
+ | * 0x20087: color spikes? | ||
+ | * 0x200AE: color spikes? | ||
+ | * 0x200D7: ??? dungeon button | ||
+ | * 0x20143: ??? palace button | ||
+ | * 0x201B4: ??? dungeon button | ||
+ | * 0x2021D: ??? palace button | ||
+ | * 0x22306: b/w dungeon | ||
+ | * 0x231D2: b/w palace | ||
+ | * 0x2929C: Red Orb credits | ||
+ | |||
+ | === Maps === | ||
+ | |||
+ | * Tilesets are from the list above. | ||
+ | * Maps are not compressed. | ||
+ | * Colormaps: the lower 3 bits of each byte contain which 4-color group of the palette (0..7) to use for each tile. | ||
+ | ** I.e. bits 4..2 of the color index come from the colormap, while bits 1..0 come from the tile itself. | ||
+ | {| class="wikitable" | ||
+ | ! tileset offset !! map offset !! colormap offset !! width !! height !! contents | ||
+ | |- | ||
+ | | 0x08810 || 0x08000 || 0x083E8 || 2 || 5*100 || color dungeon tiles | ||
+ | |- | ||
+ | | 0x09BF4 || 0x093E4 || 0x097CC || 2 || 5*100 || color palace tiles | ||
+ | |- | ||
+ | | 0x101B8 || 0x10050 || - || 20 || 18 || b/w title | ||
+ | |- | ||
+ | | 0x113BF || 0x1105F || 0x11217 || 20 || 18 || color title | ||
+ | |- | ||
+ | | 0x1240E || 0x122A6 || - || 20 || 18 || b/w story frame | ||
+ | |- | ||
+ | | 0x12BD6 || 0x12876 || 0x12A2E || 20 || 18 || color story frame | ||
+ | |- | ||
+ | | 0x22306 || 0x21F1E || - || 2 || 5*100 || b/w dungeon tiles | ||
+ | |- | ||
+ | | 0x231D2 || 0x22DEA || - || 2 || 5*100 || b/w palace tiles | ||
+ | |- | ||
+ | | 0x2929C || 0x28D5C || 0x28FDC || 20 || 32 || Red Orb credits | ||
+ | |} | ||
+ | |||
+ | === Other === | ||
+ | |||
+ | There is an unused sprite group with map offset = 0x3B444, tiles offset = 0x3B523. | ||
+ | It seems to show a pile of bones becoming a guard!? | ||
+ | |||
+ | Offsets 0xA9DF..0xAA56 contain various bits that can appear in the status bar. To be used with the tileset at 0x0AA57. | ||
+ | |||
+ | At offset 0xB320 there is some data compressed using the same method as the levels. | ||
+ | If forms a nice 32*32 array, and it seems to be used in room drawing. | ||
+ | |||
+ | == Sound effects (GBC) == | ||
+ | |||
+ | Sound effects are stored at offsets 0x3C000..0x3C0B3. | ||
+ | |||
+ | Format: | ||
+ | * Read 1 byte: | ||
+ | ** 0x01 = fill sound registers 0xFF10..0xFF14 from the next 5 bytes (sound channel 1) | ||
+ | ** 0x02 = fill sound registers 0xFF16..0xFF19 from the next 4 bytes (sound channel 2) | ||
+ | ** 0x04 = fill sound registers 0xFF20..0xFF23 from the next 4 bytes (sound channel 4) | ||
+ | ** otherwise (usually 0x00) = end | ||
+ | |||
+ | The meaning of each register can be found in various Game Boy hardware specifications. | ||
+ | |||
+ | == Various hacks (GBC) == | ||
− | |||
{| class="wikitable" | {| class="wikitable" | ||
! meaning !! offset !! size !! default value !! new value | ! meaning !! offset !! size !! default value !! new value | ||
Line 255: | Line 486: | ||
== TODO == | == TODO == | ||
− | + | * (Music?) | |
− | |||
− | * ( |
Revision as of 17:27, 18 December 2016
This document describes the format of data in Prince of Persia 1 for the Game Boy (GB) and the Game Boy Color (GBC).
Contents
General
Byte order: Little-endian (Intel) byte order is used, unless noted otherwise.
Numbering of bits: The least significant bit of a byte is bit 0, the most significant bit of a byte is bit 7.
Addresses: The Game Boy (Color) uses banked ROM.
- Offsets 0x0000..0x3FFF always refer to the first 16 kB of the ROM.
- Offsets 0x4000..0x7FFF refer to the currenly paged 16 kB bank.
- Linear Address = Bank * 0x4000 + (Offset - 0x4000) = (Bank << 14) | (Offset & 0x3FFF)
Versions:
- Game Boy Color, Europe
- Game Boy, Europe
- Game Boy, Japan
- Game Boy, USA
Levels
The level table
Offset:
- GBC: 0x1DC2C..0x1DC51, 19 levels
- GB (EU/JP/US): 0x1E189..0x1E1A8, 16 levels
For each level, there is a 2-byte offset, to be understood in the same Bank where the table is (Bank 7).
The levels are numbered as:
- Level 0: Various. (Palace in the #Level settings, i.e. used for princess room.)
- Room 1: menu (select new game, continue, or training)
- Room 2: password (linked from room 1)
- Room 5: princess room (intro and cutscenes) (the starting position points here)
- Room 6: language select (EU only) (also exists in the JP version, but not used)
- Room 8 (GBC): left of princess room (linked from room 5)
- Levels 1-14 match the DOS version.
- Level 15 (GBC): Princess room. (ending)
- Level 16 (GBC) / Level 15 (GB): Same offset as level 0. (But it's dungeon in the #Level settings, i.e. used for the other rooms of that level.)
- Level 17 (GBC): Training part 1.
- Level 18 (GBC): Training part 2.
Compression
- 1 byte: Number of replacement pairs.
- For each replacement pair:
- 1 byte: "left"
- 1 byte: "right"
- 2 byte: Length after decompression.
- Compressed data follows:
repeat while you don't have enough output bytes: read 1 byte from input; if the byte appears in "left": count := 1; repeat: read 4 bits from input through a 8-bit queue into value; That is: first time, you read a byte from input and use bits 7..4; second time, you use bits 3..0 of the already read byte and discard the byte. count := count + value; while value = 0xF; output the byte, repeated count times; else if the byte appears in "right": output the corresponding "left" byte; else: output the byte as is; end if; end repeat;
Level format
Tiles:
- For each 24 rooms:
- For each 30 tiles:
- 1 byte: Tile. The bottom 5 bits are the tile type (0x00..0x1F); the top 3 bits are the modifier (0..7). See #Tile types.
- Or: A single 0xFF byte, meaning that all tiles are 0x00. (This is a second layer of compression.)
- For each 30 tiles:
Room links:
- For each 24 rooms:
- For each direction in left, right, above, below:
- 1 byte: The room adjacent in that direction.
- Bottom 7 bits: room number. (1..24, or 0 for no room.)
- Top 1 bit (GBC): if 1, the next level will start when the prince exits the room in that direction. (Used on levels 6, 12, 14, 17.)
Starting place:
- 1 byte: Starting room. (1..24)
- 1 byte: Starting tilepos. (0..29)
- 1 byte: Starting direction. (0x00=right, 0xFF=left)
Guards:
- For each 24 rooms:
- 1 byte: Guard info. The bottom 7 bits are the tilepos. (0..29, or 30 if there is no guard) The top 1 bit is the direction. (0=right, 1=left)
Door links:
- For each door link:
- 1 byte: button room (1..24)
- 1 byte: button tilepos (0..29)
- 1 byte: effect: 0 = close, 1 = open
- 1 byte: target room (1..24)
- 1 byte: target tilepos (0..29)
- 1 byte: 0xFF, marks the end of door links and level data.
Tile types
These mostly match the DOS version.
Modifiers were usually copied from (the bottom 3 bits of) the modifiers the DOS levels, even for tiles where this makes no difference. For example, many empty tiles have 7 as modifier where the DOS level had 0xFF.
tile id | tile type | modifiers and notes |
---|---|---|
0x00 | empty | 0 = nothing, 1 or 2 = wall pattern (in dungeon), 3 = window |
0x01 | floor | 0 = nothing, 1 = wall pattern (in dungeon) |
0x02 | spikes | |
0x03 | column | |
0x04 | gate | 1 = open, 2 = closed, others = open (not used) |
0x05 | mirror after jump | Palace only. Not used in level data: 0x0D becomes this after the prince jumps through it. Same as 0x0D, except: No reflection. No black rectangle. The prince won't lose HP if he jumps through it. |
0x06 | close button | The modifier is ignored, door links are stored differently from the DOS version. |
0x07 | gate top with floor | 0 = with arch, 1 = black, 2 = with pattern |
0x08 | big column bottom | |
0x09 | big column top | |
0x0A | potion | 0 = used in password room (+1 hp), 1 = heal (+1 hp), 2 = life, 3 = float, 4 = appears on level 9 where the DOS version has the flip potions (+1 hp), 5 = hurt (-1 hp), 6 or 7 = (not used) (+1 hp) |
0x0B | loose floor | |
0x0C | gate top without floor | 0 = with arch, 1 = black, 2 = with pattern |
0x0D | mirror | Palace only. Not used in level data: Placed on level 4 when the exit door opens. Different from DOS: it occupies the right edge of the tile, and the rest is covered by a black rectangle to cover the reflection. Reflection appears only on level 4 room 4. |
0x0E | broken floor | |
0x0F | open button | The modifier is ignored, door links are stored differently from the DOS version. |
0x10 | level door left | 0 = open (language/menu rooms), 2 = closed (regular levels), others = open (not used) |
0x11 | level door right | |
0x12 | chomper | |
0x13 | torch | |
0x14 | wall | |
0x15 | skeleton | |
0x16 | sword | Dungeon only. |
0x17 | mirror left | Palace only. Not used in level data. Placed on left side of mirror to cover the mirror image, and there it appears as a black rectangle. |
0x18 | balcony | Appears as a regular floor. Used on level 6 and 14 where the DOS version has the right half of balconies. |
0x19 | arch column | |
0x1A | arch down | Palace only. |
0x1B | small arch | Palace only. |
0x1C | big arch left | Palace only. |
0x1D | big arch right | Palace only. |
0x1E | torch with broken floor | Not used in level data: a regular torch becomes this when a loose floor lands on it. |
0x1F | shadow floor | Appears only when you step on it. Used on level 12. |
Level settings
GB:
- 0x000CE..0x000DC: guard HPs, indexed by level
- 0x000DD..0x000EB: guard move(?) probability, indexed by level
- 0x000EC..0x000FA: guard move(?) delay, indexed by level
- 0x1E1A9..0x1E1B8: Level types: 0 = dungeon, 1 = palace
- 0x1E1B9..0x1E1C8: type of level entry?
- 0x05 = short run (level 1)
- 0x08 = long run (level 13)
- 0x2C = fall (level 7)
- 0x67 = standing (most levels)
- 0x7B = princess (level 0)
GBC:
- 0x00041..0x00047: guard colors, indexed by HP
- 0x000BA..0x000CC: guard HPs, indexed by level
- 0x000CD..0x000DF: guard move(?) probability, indexed by level
- 0x000E0..0x000F2: guard move(?) delay, indexed by level
- 0x1DC52..0x1DC64: Level types: 0 = dungeon, 1 = palace, 2 = dungeon (training), 3 = palace (princess room)
- 0x1DC65..0x1DC8A: level palette selection (2-byte offsets, to be understood in Bank 2)
- 0x47D0 = (dungeon) blue (level 1, 12, 13, 16)
- 0x5BB4 = (palace) orange (level 4)
- 0x6EE0 = (dungeon) red (level 17, 18)
- 0x6F20 = (palace) pink (level 0, 14, 15)
- 0x6F60 = (dungeon) green (level 7)
- 0x6FA0 = (dungeon) brown (level 2)
- 0x6FE0 = (dungeon) purple (level 3)
- 0x7020 = (dungeon) teal (level 8)
- 0x7060 = (dungeon) maroon (level 9)
- 0x70A0 = (palace) green (level 6)
- 0x70E0 = (palace) blue (level 5)
- 0x7120 = (palace) red (level 10)
- 0x7160 = (palace) yellow (level 11)
- 0x1DC8B..0x1DCB0: sprite palette selection (2-byte offsets, to be understood in Bank 2)
- 0x71A0 = (most levels)
- 0x71E0 = (level 6, 7)
- 0x7220 = (level 5)
- 0x7260 = (level 10)
- 0x72A0 = (level 11)
- 0x72E0 = (level 14)
- 0x1DCB1..0x1DCC3: Type of level entry:
- 0x05 = short run (level 1, 15, 18)
- 0x08 = long run (level 13)
- 0x2E = fall (level 7)
- 0x6A = standing (most levels)
- 0xA4 = princess (level 0)
Palettes (GBC)
A palette is 64 bytes long, and contains 32 colors, grouped into 8 sets of 4 colors each.
Each color is stored on 16 bits (2 bytes):
- Bits 0..4: Red Intensity. (0x00..0x1F)
- Bits 5..9: Green Intensity. (0x00..0x1F)
- Bits 10..14: Blue Intensity. (0x00..0x1F)
- Bit 15: Unused.
Offsets:
- 0x087D0..0x0880F: level background palette: 1 set of 32 colors, referenced from #Level settings
- 0x09BB4..0x09BF3: level background palette: 1 set of 32 colors, referenced from #Level settings
- 0x0AEE0..0x0B19F: level background palettes: 11 sets of 32 colors, referenced from #Level settings
- 0x0B1A0..0x0B31F: level sprite palettes: 6 sets of 32 colors, referenced from #Level settings
- 0x1137F..0x113AE: title screen background palette
- 0x12B96..0x12BC5: story frame+text background palette
- 0x2925C..0x2929B: copyrights screen background palette (Red Orb)
Texts
version | story texts table offset | copyrights text offset | credits texts offsets | story text languages |
---|---|---|---|---|
GBC | 0x12FEE | see #Other graphics (GBC) | 0x13016, 0x13033, 0x1304B, 0x13070, 0x1308F | German, French, Spanish, English, Italian |
GB EU | 0x13087 | 0x130AF | 0x131DE, 0x131F9, 0x1321D, 0x1323C, 0x1325D | German, English, Spanish, French, Italian |
GB JP | 0x13087 | 0x130AF | 0x13205, 0x1322A, 0x1324E, 0x1326D, 0x1328E | (ununsed), Japanese, (unused), (unused), (unused) |
The story texts table contains 20 offsets (2 bytes each) for each 4 occasions (intro 1, intro 2, bad ending, good ending) and for each 5 languages.
Fonts are stored in #Tilesets.
European
The decoding of European texts:
- Repeat until you meet the end of text marker:
- Read a byte.
- Subtract 0x20 and truncate the result to a byte.
- The lower 6 bits tell the index of the character within the font.
- The upper 2 bits tell what is after the character:
- 00 = nothing
- 01 = new line
- 10 = space
- 11 = end of text
The character set:
!"Ñ$Ç&'®®©+,-./ 0123456789:Ù¡=¿? ÄABCDEFGHIJKLMNO PQRSTUVWXYZÖÜÀÈÌ
- This mostly corresponds to range 0x20..0x5F from ASCII, but most symbols were replaced with accented letters or other symbols.
- The zero is used for Ø in BRØDERBUND's name.
- The two instances of ® are the top and bottom halves.
Japanese
This is only for story texts, the others are encoded as European.
The decoding of Japanese texts:
- Repeat until you meet the end of text marker:
- Read a byte.
- It can have the following values:
- 0x00..0x7F = The index of the character within the font.
- 0xFE = new line
- 0xFF = end of text
The character set:
んわらやまはなたさかあゃぁりみ ひにちしきいぃるゆむふぬつすくう ゅっれめへねてせけえぇをろよもほ のとそこおょぉンワラヤマハナタサ カアャァリミヒニチシキイィルユム フヌツスクウュッレメヘネテセケエ ェヲロヨモホノトソコオョォ?!゛ ゜」「…、。ゥー60
- This is different from all encodings that I've seen so far.
- There is some logic if you compare it with the usual syllable tables:
- Elsewhere, the syllables are ordered first by consonant (-,K,S,T,N,H,M,Y,R,W), and then by vowel (A,I,U,E,O).
- Here, the syllables are ordered first by vowel (A,I,U,E,O), and then by consonant, but in reverse order (W,R,Y,M,H,N,T,S,K,-).
Sprites (GBC)
start address | size of each item | contents |
---|---|---|
0x28000 | 2 bytes | map offset (b/w) |
0x28168 | 2 bytes | map offset (color) |
0x282D0 | 2 bytes | tiles offset (b/w) |
0x28438 | 2 bytes | tiles offset (color) |
0x285A0 | 1 byte | bank for map and tiles (b/w) |
0x28654 | 1 byte | bank for map and tiles (color) |
0x28708 | 1 byte | X offset in tiles (+ = backwards) |
0x287BC | 1 byte | X hit test? |
0x28870 | 1 byte | Y offset in tiles (+ = up) |
0x28924 | 1 byte | Y hit test? |
0x289D8 | 2 bytes | offset of associated sound effect (in bank 0x0F), see #Sound effects (GBC) |
0x28B40 | 1 byte | ? |
0x28BF4 | 1 byte | ? |
0x28CA8 | 1 byte | flags
|
- Every table has 0xB4 = 180 items.
- It seems that the Color version can run in b/w mode as well, with different graphics. Change the byte at offset 0x143 to 0x00 for this.
- Offsets and banks can be all zero, in this case there are no sprites in this group.
At the map offset there is the following data:
- 1 byte: number of images in sprite group
- 1 byte: width of each image
- 1 byte: height of each image
- for each image:
- for each row:
- for each column:
- 1 byte: 1-based index of tile, or 0 for none
- for each column:
- for each row:
At the tile offset there is the following data:
- 1 byte: compression marker
- 1 byte: number of tiles
- for each tile:
- 4 bits: compressed size of tile in bytes (first read bits 7..4, then read bits 3..0)
- Possible values are 9..15, and 0 which means 16.
- (pad to whole byte using 0 bits, if necessary)
- for each tile:
- for each pixel row: (0..7)
- Read 1 byte.
- If it's equal to the compression marker, repeat the last two bytes.
- Otherwise, output the byte, read another byte, and output it as well.
- for each pixel row: (0..7)
Tiles
The Game Boy (Color) uses 2-bit planar tiles.
Tiles are in this format: (after decompression)
for B=0..7: byte B of plane 0 byte B of plane 1
To get the color index of a pixel, from X and Y coordinates:
color = 0 for P=0..1: read bit 7-X of byte Y of plane P of the tile, and write it into bit P of color
This color index can be further modified by colormaps. See #Maps.
Other graphics (GBC)
Tilesets
They use the same compression as sprite tiles.
- 0x08810: color dungeon
- 0x09BF4: color palace
- 0x0AA57: status bar
- 0x101B8: b/w intro+font
- 0x113BF: color intro+font
- 0x1240E: b/w font+frame
- 0x12BD6: color font+frame
- 0x20004: b/w spikes
- 0x20023: b/w spikes?
- 0x20045: b/w spikes?
- 0x20066: color spikes
- 0x20087: color spikes?
- 0x200AE: color spikes?
- 0x200D7: ??? dungeon button
- 0x20143: ??? palace button
- 0x201B4: ??? dungeon button
- 0x2021D: ??? palace button
- 0x22306: b/w dungeon
- 0x231D2: b/w palace
- 0x2929C: Red Orb credits
Maps
- Tilesets are from the list above.
- Maps are not compressed.
- Colormaps: the lower 3 bits of each byte contain which 4-color group of the palette (0..7) to use for each tile.
- I.e. bits 4..2 of the color index come from the colormap, while bits 1..0 come from the tile itself.
tileset offset | map offset | colormap offset | width | height | contents |
---|---|---|---|---|---|
0x08810 | 0x08000 | 0x083E8 | 2 | 5*100 | color dungeon tiles |
0x09BF4 | 0x093E4 | 0x097CC | 2 | 5*100 | color palace tiles |
0x101B8 | 0x10050 | - | 20 | 18 | b/w title |
0x113BF | 0x1105F | 0x11217 | 20 | 18 | color title |
0x1240E | 0x122A6 | - | 20 | 18 | b/w story frame |
0x12BD6 | 0x12876 | 0x12A2E | 20 | 18 | color story frame |
0x22306 | 0x21F1E | - | 2 | 5*100 | b/w dungeon tiles |
0x231D2 | 0x22DEA | - | 2 | 5*100 | b/w palace tiles |
0x2929C | 0x28D5C | 0x28FDC | 20 | 32 | Red Orb credits |
Other
There is an unused sprite group with map offset = 0x3B444, tiles offset = 0x3B523. It seems to show a pile of bones becoming a guard!?
Offsets 0xA9DF..0xAA56 contain various bits that can appear in the status bar. To be used with the tileset at 0x0AA57.
At offset 0xB320 there is some data compressed using the same method as the levels. If forms a nice 32*32 array, and it seems to be used in room drawing.
Sound effects (GBC)
Sound effects are stored at offsets 0x3C000..0x3C0B3.
Format:
- Read 1 byte:
- 0x01 = fill sound registers 0xFF10..0xFF14 from the next 5 bytes (sound channel 1)
- 0x02 = fill sound registers 0xFF16..0xFF19 from the next 4 bytes (sound channel 2)
- 0x04 = fill sound registers 0xFF20..0xFF23 from the next 4 bytes (sound channel 4)
- otherwise (usually 0x00) = end
The meaning of each register can be found in various Game Boy hardware specifications.
Various hacks (GBC)
meaning | offset | size | default value | new value |
---|---|---|---|---|
Starting minutes | 0x0191 | 1 byte | 0x3C = 60 | |
Starting HP (for both new game and training) | 0x080D | 1 byte | 0x03 = 3 | |
Training level number - 1 | 0x0664 | 1 byte | 0x10 = 16 = level 17 | |
Skip most of the intro and start the training level directly. | 0x02E3 | 3 bytes | 0xCD 0x5F 0x20 | 0xC3 0x63 0x06 |
Skip Red Orb screen. | 0x023E | 2 bytes | 0x38 0xF7 | 0x18 0x19 |
TODO
- (Music?)