Research / Sonic 2 / Lost sprites of Sonic 2 Beta

Lost sprites of Sonic 2 Beta:


*Submitted by Sonic Hachelle-Bee on June 26 2005.*

Restore the lost badnicks from Sonic 2 Beta:


Here, I will explain how to restore the lost sprites from Sonic 2 Beta to Sonic 2 Final or Sonic 2 & Knuckles.
Instead of using the Esrael patch to restore them (as usual), I will explain how to make that task manually with only an hex editor.
We will restore the batbot, the dinobot, the trycerobot, the crocobot, and the snailbot sprites.

The sprites code pointer table:


In both Sonic 2 Beta and Sonic 2 Final, you have a sprites code pointer table where all pointers for the code of each sprite are stored in a certain order.

Sonic 2 Beta sprites code pointer table: $D01A
Sonic 2 Final sprites code pointer table: $1600C
Sonic 2 & Knuckles sprites code pointer table: $3128FA

This huge table start with a first pointer of 4 bytes. This is the absolute address for the sprite ID $00 code. This is the Sonic sprite. Then, the second pointer of 4 bytes is the absolute address for the sprite ID $01 code, and that's the Tails sprite. Then, for each sprite ID, you have a pointer in order to jump to the right object code.

Several pointers in this table refers to nothing (the end of the table at $1637C). It's said that they are leftovers of some sprites you can see in earlier versions of Sonic 2. We will use these pointers to create our new sprites. As Sonic 2 Beta, and as Esrael patch, we will do this:

The batbot is ID $4C.
The trycerobot is ID $4D.
The crocobot is ID $4E.
The dinobot is ID $4F.
The snailbot is ID $62.

All these sprites ID are usually empty, and we will use them for our sprites.

For example, in Sonic 2 Final, the pointer that jumps to the batbot code is at $16138 and it's currently 00 01 63 7C (empty). The one for the trycerobot is next, and it's again 00 01 63 7C. You will have to change these pointers at the end, once you have your objects code in the ROM file.

Lost sprites code:


You have, for each sprite, to copy their code from Sonic 2 Beta and paste it somewhere in the Sonic 2 Final or Sonic 2 & Knuckles ROM file. Here is the addresses where to copy these sprites from the Sonic 2 Beta ROM file:

For the most lazy ones, I have done that boring part for you: click here for Sonic 2 or here for Sonic 2 & Knuckles.

Batbot: $1EE68 - $1F2EE
Trycerobot: $1D984 - $1DC52
Crocobot: $1F2F0 - $1F5E8
Dinobot: $1DEAC - $1E00E
Snailbot: $1F6E8 - $1F99C and $1EAF2 - $1EB8C
For the snailbot, paste the second part (animated fire) after the first (main) part. The result is $34E bytes in size.

Now, you can change your pointers in the sprites code pointer table to jump at each objects code.

Pointers to fix in each objects code:


Now that you copied the sprites codes from Sonic 2 Beta, we need to change some pointers into them. That's right, every pointer in the sprites codes are wrong and have to be updated to the right addresses from the final version of Sonic 2. This way, the game will use the right routines of Sonic 2 Final in replacement. In order to see where are these pointers to change, we will say that every sprite code start at address $0.

This is an extremely boring part, and then, for the most lazy ones, if you previously downloaded the zip archive to get the sprites codes, you will be happy to see that most pointers are already fixed! Some others however need to be fixed manually, because they are relative to the place you pasted the code. Just fix the pointers listed in green color below.

SpriteAddress of the pointer to fixPointer to fixNew pointer
Sonic 2Sonic 2 & Knuckles
Batbot$1421 7C 00 01 F1 06Sprite code internal pointer
Must jump to $29E
Data at this address: 00 1E 00 40 00 62 ...
$6443 F9 00 01 F0 D2Sprite code internal pointer
Must jump to $26A
Data at this address: 00 08 00 0C 00 1B ...
$7C4E B9 00 00 32 0A4E B9 00 00 33 B64E B9 00 30 2F 10
$D043 F9 00 01 F0 D2Sprite code internal pointer
Must jump to $26A
Data at this address: 00 08 00 0C 00 1B ...
$1C24E B9 00 00 32 0A4E B9 00 00 33 B64E B9 00 30 2F 10
$1EC4E B9 00 00 31 E44E B9 00 00 33 904E B9 00 30 2E EA
$4744E F9 00 00 D2 A04E F9 00 01 63 D24E F9 00 31 2C C0
$47A4E F9 00 00 D4 124E F9 00 01 65 444E F9 00 31 2D D0
$4804E F9 00 00 D2 7A4E F9 00 01 63 AC4E F9 00 31 2C 9A
Trycerobot$1221 7C 00 01 DA EESprite code internal pointer
Must jump to $16A
Data at this address: 00 10 00 3A 00 64 ...
$484E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$7043 F9 00 01 DA D2Sprite code internal pointer
Must jump to $14E
Data at this address: 00 06 00 14 00 17 ...
$AE4E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$2BC4E F9 00 00 D2 A04E F9 00 01 63 D24E F9 00 31 2C C0
$2C24E F9 00 00 D4 124E F9 00 01 65 444E F9 00 31 2D D0
$2C84E F9 00 00 D2 4E4E F9 00 01 63 804E F9 00 31 2C 6E
Crocobot$1221 7C 00 01 F4 20Sprite code internal pointer
Must jump to $130
Data at this address: 00 18 00 3A 00 5C ...
$484E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$7043 F9 00 01 F4 06Sprite code internal pointer
Must jump to $116
Data at this address: 00 06 00 0E 00 11 ...
$AE4E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$2E04E F9 00 00 D2 A04E F9 00 01 63 D24E F9 00 31 2C C0
$2E64E F9 00 00 D4 124E F9 00 01 65 444E F9 00 31 2D D0
$2EC4E F9 00 00 D2 4E4E F9 00 01 63 804E F9 00 31 2C 6E
$2F24E F9 00 00 D2 7A4E F9 00 01 63 AC4E F9 00 31 2C 9A
Dinobot$1421 7C 00 01 DF CASprite code internal pointer
Must jump to $11E
Data at this address: 00 06 00 10 00 1A ...
$4A4E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$7843 F9 00 01 DF BCSprite code internal pointer
Must jump to $110
Data at this address: 00 04 00 07 09 01 ...
$DC4E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$1444E F9 00 00 D3 C24E F9 00 01 64 F44E F9 00 31 2D 80
$14A4E F9 00 00 D3 B44E F9 00 01 64 E64E F9 00 31 2D 72
$1504E F9 00 00 D4 124E F9 00 01 65 444E F9 00 31 2D D0
$1564E F9 00 00 D2 4E4E F9 00 01 63 804E F9 00 31 2C 6E
$15C4E F9 00 00 D2 7A4E F9 00 01 63 AC4E F9 00 31 2C 9A
Snailbot$1821 7C 00 01 F9 38Sprite code internal pointer
Must jump to $250
Data at this address: 00 06 00 18 00 2A ...
$6023 7C 00 01 F9 38Sprite code internal pointer
Must jump to $250
Data at this address: 00 06 00 18 00 2A ...
$C04E B9 00 01 38 984E B9 00 01 ED FA4E B9 00 31 91 02
$D643 F9 00 01 F9 2CSprite code internal pointer
Must jump to $244
Data at this address: 00 04 00 08 05 00 ...
$F243 F9 00 01 F9 2CSprite code internal pointer
Must jump to $244
Data at this address: 00 04 00 08 05 00 ...
$15623 7C 00 01 EB 0ESprite code internal pointer
Must jump to $2D0
Data at this address: 00 0E 00 20 00 3A ...
$1D643 F9 00 01 EA F2Sprite code internal pointer
Must jump to $2B4
Data at this address: 00 08 00 0B 00 0F ...
$2844E F9 00 00 D3 B44E F9 00 01 64 E64E F9 00 31 2D 72
$28A4E F9 00 00 E7 884E F9 00 01 7F FA4E F9 00 31 3D 8E
$2904E F9 00 00 D4 124E F9 00 01 65 444E F9 00 31 2D D0
$2964E F9 00 00 DC 4C4E F9 00 01 6D 8A4E F9 00 21 6D 8A
$29C4E F9 00 00 D3 404E F9 00 01 64 724E F9 00 31 2D 44
$2A24E F9 00 00 DC 304E F9 00 01 6D 6E4E F9 00 21 6D 6E
$2A84E F9 00 00 D2 4E4E F9 00 01 63 804E F9 00 31 2C 6E
$2AE4E F9 00 00 D2 7A4E F9 00 01 63 AC4E F9 00 31 2C 9A


Pallet and VRAM position to fix for each object code:


Now, we need to fix their respective pallet line to use and VRAM position where the graphics will be loaded. Again, we will change something in the sprites codes.

All sprites that need a pallet and graphics have a 2 bytes value loaded into a register. This 2 bytes value tells the pallet line to use and the VRAM position for the graphics:

PV VV

P - Pallet line to use (0, 1, 2 or 3).
V - VRAM location where to load graphics. Actually, to obtain the exact 4 nybbles address, you have to take these 3 nybbles and multiply them by $20.

Hopefully, I have once again fixed all that myself in the files that are in the zip archive. You just have to pay attention on one thing listed in green color, because for some odd reasons, some emulators won't display the sprite of the snailbot properly, while others will.

Here is where and how to change everything for our sprites. Notice how the snailbot has 3 different parts (shell, body, and the animated fire):

SpriteAddress of the string to fixInitial string valueNew string value
Sonic 2Sonic 2 & Knuckles
Batbot$1C31 7C 25 3031 7C 23 B2
Trycerobot$1A31 7C 23 C431 7C 23 A0
Crocobot$1A31 7C 23 00
31 7C 25 00
Dinobot$1C31 7C 05 00Nothing to change here
Snailbot$20 (body)31 7C 04 0231 7C 05 4E
$68 (shell)33 7C 24 0233 7C 25 4E
$15E (animated fire)33 7C 03 E633 7C 03 D2General case:
33 7C 03 D2
With some emulators:
33 7C 07 A4


Sprites graphics and pattern load cues:


Now that we tell the game which pallet line to use and where are located the graphics to load from the VRAM, we have to actually load these graphics in VRAM, by decompressing what's already in the ROM file in Nemesis format. In order to make that, we will use the pattern load cues of the Sonic engine: they will do the work done for you.

First, we have to find the original graphics (compressed in Nemesis format) in the Sonic 2 Beta ROM file, and copy them into Sonic 2 Final (or Sonic 2 & Knuckles). Here are the locations for each sprite:

Batbot: $7A6A2
Trycerobot: $7AD18
Crocobot: $7A11A
Dinobot: $7B114
Snailbot: $7C514

For the most lazy ones (and because it's faster), here is the archive that contains all these graphics: click here.

Now, all you need to do is to edit the pattern load cues of the levels in which you want the sprites to appear. Here is the article that explains how things works. You have the graphics absolute addresses (it's the one where you pasted the graphics in Sonic 2 Final or Sonic 2 & Knuckles). Now, you need the VRAM position where to load these graphics in VRAM. Accordingly to every fixes we have done before, here is the VRAM position where to load the graphics for each sprite, in order to display them correctly on screen:

Batbot: $7640
Trycerobot: $7400
Crocobot: $A000
Dinobot: $A000
Snailbot: $7A40
The wasp graphics must be loaded just before it, for the animated fire.

Specific case for the snailbot:


The snailbot is a more complex sprite than the others as you can see. There is another thing to do if you want your sprite to display on screen. Actually, the old sprite ID for the snailbot of Sonic 2 Beta is $54 and not $62. Because of this, we will have to change directly some extra bytes in the sprite code. If you have previously downloaded the archive, then there is no further problem for you, you have finished. Else, here is the addresses where to change these bytes in the snailbot sprite code:

Address of the byte to changePrevious dataNew data
$5413 7C 00 5413 7C 00 62
$14A13 7C 00 5413 7C 00 62
$1A60C 11 00 540C 11 00 62
$2200C 11 00 540C 11 00 62


This put an end of this dreadful tutorial. Phew! ^_^

Back | Printer friendly
2. Metropolis zone warp tubes >>

© 2004, 2005 drx, www.hacking-cult.org. Don't copy without permission yadda yadda yadda.