Wonder Boy III: Monster Lair (Genesis)/Notes: Difference between revisions

From Data Crystal
Jump to navigation Jump to search
(Created page with "{{notes|game=Wonderboy III: Monster Lair (Genesis)}} == Gfx format == == Sprites == == Tilemaps == == Palettes ==")
 
mNo edit summary
 
(5 intermediate revisions by 2 users not shown)
Line 2: Line 2:


== Gfx format ==
== Gfx format ==
Gfx data (tiles) are organized by levels (0 to 11). Pointers to each level data are stored from 0x43000 to 0x4302c. Then, for each level, gfx are stored by chunk.
For example, pointer to level 3 chunks is 0x432cc (read at 0x4300c). Then, at 0x432cc, there are pointers to 4 chunks : 0x00000000 (null chunk), 0x432e0, 0x43188, 0x433aa, 0x433aa.
Each chunk is a list of 16 bytes entries, terminated by a 0000 :
* 1 word: number of tiles - 1
* 1 long: pointer to actual data
* 1 word: 1 if gfx uses color indices 0 to 7 (x = 0 in the following), -1 if gfx uses color indices 8 to 15 (x = 1 in the following).
Actual tile data is stored in 3bpp interleaved format:
* 1 byte: a7 a6 a5 a4 a3 a2 a1 a0
* 1 byte: b7 b6 b5 b4 b3 b2 b1 b0
* 1 byte: c7 c6 c5 c4 c3 c2 c1 c0
gives :
* 1 byte (2 pixels): (x a7 b7 c7) (x a6 b6 c6)
* 1 byte (2 pixels): (x a5 b5 c5) (x a4 b4 c4)
* 1 byte (2 pixels): (x a3 b3 c3) (x a2 b2 c2)
* 1 byte (2 pixels): (x a1 b1 c1) (x a0 b0 c0)
{| class="wikitable" style="margin:auto"
!||Chunk 0||Chunk 1||Chunk 2||Chunk 3||Chunk 4||Chunk 5
|-
| Level 0
| 0x4303e
| 0x43060
| 0x43092
|
|
|
|-
| Level 1
| 0x430d6
| 0x43188
| 0x43192
| 0x43192
|
|
|-
| Level 2
| 00000000
| 0x431e0
| 0x43188
| 0x4328a
| 0x4328a
|
|-
| Level 3
| 00000000
| 0x432e0
| 0x43188
| 0x433aa
| 0x433aa
|
|-
| Level 4
| 00000000
| 0x433fc
| 0x4347e
| 0x43188
| 0x43188
| 0x434a8
|-
| Level 5
| 00000000
| 0x434f6
| 0x43188
| 0x43598
| 0x43598
|
|-
| Level 6
| 00000000
| 0x435e6
| 0x43188
| 0x43698
| 0x43698
|
|-
| Level 7
| 00000000
| 0x436e6
| 0x43188
| 0x43790
| 0x43790
|
|-
| Level 8
| 00000000
| 0x437ee
| 0x43188
| 0x438c0
| 0x438c0
|
|-
| Level 9
| 00000000
| 0x43916
| 0x439a8
| 0x439b2
| 0x439b2
|
|-
| Level 10
| 00000000
| 0x439fe
|
|
|
|
|-
| Level 11
| 0x43034
|
|
|
|
|
|}


== Sprites ==
== Sprites ==
For some reason, projectiles sprites are not handled the same way as other (regular) sprites.
===Regular Objects===
Sprite frames are built using 2 tables for each Sprite.
placementTable contains placement and size information. It starts too with an offset (word) to the frame id, then :
* 1 word: number of HW sprites
** 1 word: 00000000 0000WWHH (W=width, H=height)
** 1 signed byte: delta y
** 1 signed byte: delta x
mapTable contains tile information and flip flags. It starts with an offset (word) to the frame id, then, for each HW sprite, the tile attributes in the standard format pccvhnnn nnnnnnnn (p=priority, c=palette, v=vflip, h=hflip, n=tile id).
Note there's no counter in mapTable table, but there are as many tile attributes as the number of HW sprites given in placementTable.
For example, Leo's tables are located at 0x20588 (placementTable) and 0x202c4 (mapTable). Frame 3 (walking frame) is given by the 4th word of both tables (0xa0 for placementTable and 0x4c for mapTable) which leads to 0x20628 and 0x20310.
The data in the placementTable is then:
* 0003: there are 3 HW sprites
* 1st HW sprite:
** 0009: size is (24, 16)
** 00f0: delta y = -16
** 00f4: delta x = -12
* 2nd HW sprite:
** 0008: size is (24, 8)
** 0000: delta y = 0
** 00f4: delta x = -12
* 3rd HW sprite:
** 0008: size is (24,8)
** 0008: delta y = 8
** 00f4: delta x = -12
The tile information in mapTable is:
* 00c9: 1st HW sprite uses tiles id from 0xc9 to 0xce
* 00cf: 2nd HW sprite uses tiles id from 0xcf to 0xd1
* 00d2: 3rd HW sprite uses tiles id from 0xd2 to 0xd4
{| class="wikitable" style="margin:auto"
!Object||Nb of frames||mapTable||placementTable||GFX data
|-
| Leo
| 20
| 0x202c4
| 0x20588
| 0x473a0
|-
| Kiwi
| 3
| 0x1f06e
| 0x1fbc4
| 0x53ab0
|-
| Carot
| 2
| 0x1f074
| 0x1fbca
| 0x53bd0
|-
| Tomato
| 3
| 0x1f078
| 0x1fbce
| 0x53c90
|-
| Sweat
| 2
| 0x1f07e
| 0x1fbd4
| 0x53e70
|-
| Grape
| 2
| 0x1f092
| 0x1fbfc
| 0x541e8
|-
| Lemon
| 3
| 0x1f09c
| 0x1fc12
| 0x54890
|-
| Beam capsule
| 1
| 0x1f500
| 0x1fbc2
| 0x4d300
|-
| Missile capsule
| 1
| 0x1f502
| 0x1fbc2
| 0x430b2
|-
| Wide ring capsule
| 1
| 0x1f504
| 0x1fbc2
| 0x4d300
|-
| Spiral capsule
| 1,
| 0x1f506
| 0x1fbc2
| 0x4d300
|-
| Fireball capsule
| 1
| 0x1f4fe
| 0x1fbc2
| 0x4d300
|-
| Big Fire capsule
| 1
| 0x1f4fc
| 0x1fbc2
| 0x4d300
|-
| Whelk
| 2
| 0x20e1a
| 0x1fdc2
| 0x68c30
|-
| Whelk death
| 1
| 0x20e1e
| 0x1fe92
| 0x68c30
|-
| Snail
| 2
| 0x20e26
| 0x1fdc6
| 0x68810
|-
| Snail death
| 1
| 0x20e2a
| 0x1fe94
| 0x68810
|-
| Walrus
| 4
| 0x20e38
| 0x1fdca
| 0x69290
|-
| Dead Walrus
| 1
| 0x20e40
| 0x1fe96
| 0x69290
|-
| Octopus
| 2
| 0x20e56
| 0x1fdd2
| 0x697e8
|-
| Climbing Snail
| 2
| 0x20e5e
| 0x1fdc6
| 0x68a20
|-
| Dead Climbing Snail
| 1
| 0x20e62
| 0x1fe92
| 0x68a20
|-
| Pelican
| 2
| 0x20e6a
| 0x1fdd6
| 0x69050
|-
| Explosion
| 2
| 0x21da0
| 0x1feb4
| 0x4d300
|-
| Moving rock
| 1
| 0x1e89a
| 0x1fc20
| 0x56450
|}
===Projectiles===
For projectiles, there's only 1 table, starting with offsets, each frame being described :
* 1 word: counter
** 1 word: 00000000 0000WWHH (W=width, H=height)
** 1 signed byte: delta y
** 1 signed byte: delta x
** 1 word: pccvhnnn nnnnnnnn (p=priority, c=color, v=vflip, h=hflip, n=tile id)
{| class="wikitable" style="margin:auto"
!Object||Nb of frames||table||GFX data
|-
| Normal shot
| 1
| 0x1d528
| 0x4d300
|-
| Fireball
| 2
| 0x1d652
| 0x4d300
|-
| Spiral Shot
| 1
| 0x1d532
| 0x4d300
|-
| Wide Ring Blaster
| 4
| 0x1d5e8
| 0x4d300
|-
| Beam
| 3
| 0x1d66c
| 0x4d300
|-
| Missile(*)
| 7
| 0x1d53c
| 0x430b2
|}


(*) Missile needs to preload its tileset.
== Tilemaps ==
== Tilemaps ==
Tilemaps are splitted by chunks of 8*32 tiles. A map is a list of pointers to each chunk, terminated by a -1 signed long (0xffffffff). A special value of 0x0000ffff indicates that you have to insert the exit background (see fig) there.
Each chunk is a list of 8 words offset from this entry to actual data.
Chunk data is encoded up to down, left to right, with a simple RLE scheme; each entry is a word :
* if the word if of the form 0xffXX, then XX is a counter, and the next word is repeated (counter + 1) times,
* else the word is directly written
For example, level 1 background A is located at 0x3224a :
  0x3224a : 0002fc9e  0002fc9e 00030548...
up to
  0x3237a: ffffffff
First chunk is located at 0x2fc9e :
  0x2fc9e: 0010 0026 0046 0066 0086 00a6 00c6 00dc
First column data is at 0x2fc9e + 0x0010 = 0x2fcae, second column data is at 0x2fca0 + 0x26 = 0x2fcc6, etc.
First column data is :
  0x2fcae:
    ff15 0020
    235b
    235f
    2363
    2335
    c402
    c3b4
    c3b6
    c3b8
    ff01 c3ba
which decompress to
  0020 0020 0020 0020 0020 0020 0020 0020
  0020 0020 0020 0020 0020 0020 0020 0020
  0020 0020 0020 0020 0020 0020 235b 235f
  2363 2335 c402 c3b4 c3b6 c3b8 c3ba c3ba


== Palettes ==
== Palettes ==
{{Internal Data}}

Latest revision as of 03:49, 24 October 2024

Chip tiny.png The following article is a Notes Page for Wonder Boy III: Monster Lair (Genesis).

Gfx format

Gfx data (tiles) are organized by levels (0 to 11). Pointers to each level data are stored from 0x43000 to 0x4302c. Then, for each level, gfx are stored by chunk.

For example, pointer to level 3 chunks is 0x432cc (read at 0x4300c). Then, at 0x432cc, there are pointers to 4 chunks : 0x00000000 (null chunk), 0x432e0, 0x43188, 0x433aa, 0x433aa.

Each chunk is a list of 16 bytes entries, terminated by a 0000 :

  • 1 word: number of tiles - 1
  • 1 long: pointer to actual data
  • 1 word: 1 if gfx uses color indices 0 to 7 (x = 0 in the following), -1 if gfx uses color indices 8 to 15 (x = 1 in the following).

Actual tile data is stored in 3bpp interleaved format:

  • 1 byte: a7 a6 a5 a4 a3 a2 a1 a0
  • 1 byte: b7 b6 b5 b4 b3 b2 b1 b0
  • 1 byte: c7 c6 c5 c4 c3 c2 c1 c0

gives :

  • 1 byte (2 pixels): (x a7 b7 c7) (x a6 b6 c6)
  • 1 byte (2 pixels): (x a5 b5 c5) (x a4 b4 c4)
  • 1 byte (2 pixels): (x a3 b3 c3) (x a2 b2 c2)
  • 1 byte (2 pixels): (x a1 b1 c1) (x a0 b0 c0)
Chunk 0 Chunk 1 Chunk 2 Chunk 3 Chunk 4 Chunk 5
Level 0 0x4303e 0x43060 0x43092
Level 1 0x430d6 0x43188 0x43192 0x43192
Level 2 00000000 0x431e0 0x43188 0x4328a 0x4328a
Level 3 00000000 0x432e0 0x43188 0x433aa 0x433aa
Level 4 00000000 0x433fc 0x4347e 0x43188 0x43188 0x434a8
Level 5 00000000 0x434f6 0x43188 0x43598 0x43598
Level 6 00000000 0x435e6 0x43188 0x43698 0x43698
Level 7 00000000 0x436e6 0x43188 0x43790 0x43790
Level 8 00000000 0x437ee 0x43188 0x438c0 0x438c0
Level 9 00000000 0x43916 0x439a8 0x439b2 0x439b2
Level 10 00000000 0x439fe
Level 11 0x43034

Sprites

For some reason, projectiles sprites are not handled the same way as other (regular) sprites.

Regular Objects

Sprite frames are built using 2 tables for each Sprite.

placementTable contains placement and size information. It starts too with an offset (word) to the frame id, then :

  • 1 word: number of HW sprites
    • 1 word: 00000000 0000WWHH (W=width, H=height)
    • 1 signed byte: delta y
    • 1 signed byte: delta x

mapTable contains tile information and flip flags. It starts with an offset (word) to the frame id, then, for each HW sprite, the tile attributes in the standard format pccvhnnn nnnnnnnn (p=priority, c=palette, v=vflip, h=hflip, n=tile id).

Note there's no counter in mapTable table, but there are as many tile attributes as the number of HW sprites given in placementTable.

For example, Leo's tables are located at 0x20588 (placementTable) and 0x202c4 (mapTable). Frame 3 (walking frame) is given by the 4th word of both tables (0xa0 for placementTable and 0x4c for mapTable) which leads to 0x20628 and 0x20310.

The data in the placementTable is then:

  • 0003: there are 3 HW sprites
  • 1st HW sprite:
    • 0009: size is (24, 16)
    • 00f0: delta y = -16
    • 00f4: delta x = -12
  • 2nd HW sprite:
    • 0008: size is (24, 8)
    • 0000: delta y = 0
    • 00f4: delta x = -12
  • 3rd HW sprite:
    • 0008: size is (24,8)
    • 0008: delta y = 8
    • 00f4: delta x = -12

The tile information in mapTable is:

  • 00c9: 1st HW sprite uses tiles id from 0xc9 to 0xce
  • 00cf: 2nd HW sprite uses tiles id from 0xcf to 0xd1
  • 00d2: 3rd HW sprite uses tiles id from 0xd2 to 0xd4
Object Nb of frames mapTable placementTable GFX data
Leo 20 0x202c4 0x20588 0x473a0
Kiwi 3 0x1f06e 0x1fbc4 0x53ab0
Carot 2 0x1f074 0x1fbca 0x53bd0
Tomato 3 0x1f078 0x1fbce 0x53c90
Sweat 2 0x1f07e 0x1fbd4 0x53e70
Grape 2 0x1f092 0x1fbfc 0x541e8
Lemon 3 0x1f09c 0x1fc12 0x54890
Beam capsule 1 0x1f500 0x1fbc2 0x4d300
Missile capsule 1 0x1f502 0x1fbc2 0x430b2
Wide ring capsule 1 0x1f504 0x1fbc2 0x4d300
Spiral capsule 1, 0x1f506 0x1fbc2 0x4d300
Fireball capsule 1 0x1f4fe 0x1fbc2 0x4d300
Big Fire capsule 1 0x1f4fc 0x1fbc2 0x4d300
Whelk 2 0x20e1a 0x1fdc2 0x68c30
Whelk death 1 0x20e1e 0x1fe92 0x68c30
Snail 2 0x20e26 0x1fdc6 0x68810
Snail death 1 0x20e2a 0x1fe94 0x68810
Walrus 4 0x20e38 0x1fdca 0x69290
Dead Walrus 1 0x20e40 0x1fe96 0x69290
Octopus 2 0x20e56 0x1fdd2 0x697e8
Climbing Snail 2 0x20e5e 0x1fdc6 0x68a20
Dead Climbing Snail 1 0x20e62 0x1fe92 0x68a20
Pelican 2 0x20e6a 0x1fdd6 0x69050
Explosion 2 0x21da0 0x1feb4 0x4d300
Moving rock 1 0x1e89a 0x1fc20 0x56450

Projectiles

For projectiles, there's only 1 table, starting with offsets, each frame being described :

  • 1 word: counter
    • 1 word: 00000000 0000WWHH (W=width, H=height)
    • 1 signed byte: delta y
    • 1 signed byte: delta x
    • 1 word: pccvhnnn nnnnnnnn (p=priority, c=color, v=vflip, h=hflip, n=tile id)
Object Nb of frames table GFX data
Normal shot 1 0x1d528 0x4d300
Fireball 2 0x1d652 0x4d300
Spiral Shot 1 0x1d532 0x4d300
Wide Ring Blaster 4 0x1d5e8 0x4d300
Beam 3 0x1d66c 0x4d300
Missile(*) 7 0x1d53c 0x430b2

(*) Missile needs to preload its tileset.

Tilemaps

Tilemaps are splitted by chunks of 8*32 tiles. A map is a list of pointers to each chunk, terminated by a -1 signed long (0xffffffff). A special value of 0x0000ffff indicates that you have to insert the exit background (see fig) there.

Each chunk is a list of 8 words offset from this entry to actual data.

Chunk data is encoded up to down, left to right, with a simple RLE scheme; each entry is a word :

  • if the word if of the form 0xffXX, then XX is a counter, and the next word is repeated (counter + 1) times,
  • else the word is directly written

For example, level 1 background A is located at 0x3224a :

 0x3224a : 0002fc9e  0002fc9e 00030548... 

up to

 0x3237a: ffffffff

First chunk is located at 0x2fc9e :

 0x2fc9e: 0010 0026 0046 0066 0086 00a6 00c6 00dc

First column data is at 0x2fc9e + 0x0010 = 0x2fcae, second column data is at 0x2fca0 + 0x26 = 0x2fcc6, etc.

First column data is :

 0x2fcae:
   ff15 0020 
   235b 
   235f 
   2363 
   2335 
   c402 
   c3b4 
   c3b6 
   c3b8 
   ff01 c3ba

which decompress to

 0020 0020 0020 0020 0020 0020 0020 0020 
 0020 0020 0020 0020 0020 0020 0020 0020 
 0020 0020 0020 0020 0020 0020 235b 235f 
 2363 2335 c402 c3b4 c3b6 c3b8 c3ba c3ba

Palettes