Sonic the Hedgehog Triple Trouble/Technical information

From Sonic Retro

Back to: Sonic the Hedgehog Triple Trouble.
Sonicretro-round.svg This article needs cleanup.

This article needs to be edited to conform to a higher standard of article quality.
After the article has been cleaned up, you may remove this message. See How to Edit a Page for help.


in the
$10000 Unc. Art-Sonic (340 tiles)
$29000 Unc. Art-Monitors (98 tiles)
$7C300 Unc. Art-Fang (348 tiles)


The original research by Doc Eggfan can be found here

in the
$3B71C Sega Screen 1 (32)
$3B79C Title screen palette (64)
$3B8DC Sega Screen 2 (32) (SPRITE)
$3BA5C Intro 2 (32)
$3BBDC Intro 1 (32)
$3BBFC Intro 2 (Robotnik) (32)
$3B7DC Character Select (Sonic Select) (32)
$3B7FC Character Select (Tails Select) (32)
$3B81C Character Select (Sonic Not select) (32)
$3B83C Character Select (Tails Not Select) (32)
$3B4A3 Title Card (Great Turquoise) (8)
$3BDDC Title Card 2 (32) (SPRITE)
$3BABC Great Turquoise (32)
$3BE3C Great Turquoise (water) (32)
$3BE5C Great Turquoise water sprites (32)
$3B99C Great Turquoise Boss sprite (32)
$589B Great Turquoise Boss sprite (2)
$3BEFC Signpost (32)
$3B89C End of act results (64)
$3BBBC Special Stage 1 (32)
$3BA9C Special Stage Sprite 1 (32)
$5CA37 Chaos Emerald 1 (6)
$3BC5C Special Stage 2 Sonic (32)
$3BC9C Special Stage 2 Tails (32)
$3BCDC Special Stage 2 sprite (32)
$9EA Special Stage 2 BG (32 - every 2nd word)
$5CA3D Chaos Emerald 2 (6)
$3B4AB Title Card (Sunset Park) (8)
$3BADC Sunset Park (32) ***Unknown Rotating Palette (0F00)***
$3B8FC Sunset Park Sprite (32)
$3885C Continue/Game Over (32)
$3BD9C Special Stage 3 (32)
$5CA43 Chaos Emerald 3 (6)
$3BC7C Special Stage 4 Sonic (32)
$3BCBC Special Stage 4 Tails (32)
$3BCFC Special Stage 4 Sprite (32)
$5CA49 Chaos Emerald 4 (6)
$3B4B3 Title Card (Meta Junglira) (8)
$3BAFC Meta Junglira (32)
$3B91C Meta Junglira Sprite (32)
$3B9DC Meta Junglira Boss Sprite (32)
$589F Meta Junglira Boss (2)
$3BA7C Meta Junglira Knuckles Sprite (32)
$3BDBC Special Stage 5 (32)
$5CA4F Chaos Emerald 5 (6)
$3B4BB Title Card (Robotnik Winter) (8)
$3BB1C Robotnik Winter (32)
$3B93C Robotnik Winter Sprite (32)
$3B9FC Robotnik Winter Boss Sprite (32)
$58A1 Robotnik Winter Boss Sprite (2)
$3B4C3 Title Card (Tidal Plant) (8)
$3BB3C Tidal Plant (32)
$3B95C Tidal Plant Sprite (32)
$3BEBC Tidal Plant Water (32)
$3BEDC Tidal Plant Water Sprite (32)
$3BC1C Tidal Plant Act 3 (32)
$3BA1C Tidal Plant Act 3 Sprite (32)
$3B4CB Title Card (Atomic Destroyer) (8)
$3BB5C Atomic Destroyer Act 1 (32) *3 Unknown Rotating Palettes (DD0F, FF0D, 6202)
$3B97C Atomic Destroyer Sprite (32)
$3BB7C Atomic Destroyer Act 2 (32)
$3BB9C Atomic Destroyer Act 3 (32)
$3BA3C Atomic Destroyer Metal Sonic Sprite (32)
$3BC3C Atomic Destroyer Fang Sprite (32)
$58A5 Atomic Destroyer Robotnik Boss Sprite (2)
$3BD5C End Sequence 1 (64)
$3F007 End Sequence BG 1 (32 - Every second word)


The original research by Rolken can be found here

The first point of interest in the ROM is the 8x8 tile methodology. The set of tile addresses is an index hardcoded in the ROM ($6B678), at which a set of seven bytes for each level give:

Tile Bank
LS Tile Address
MS Tile Address

Skip to that tile address, and you get

LS Number of Tiles
MS Number of Tiles
LS Guide Address (offset from Tile Address)
MS Guide Address (offset from Tile Address)
henceforth - Tile Data

For some reason Sonic Triple Trouble checks the game mode byte and if it sees Time Attack mode it overrides the usual zone/act tile selection and instead forces the address equivalent to level 29, whereas the Time Attack mode level itself is level 30. I can't see why they made that special case behaviour instead of just correcting the address for level 30, but they did.

You need to work with both the tile data and the "guide" data at the same time - the "guide" is a set of 2-bit flags, 4 per byte, from LS to MS, that indicate what to do with the tile data, as follows:

0 - The tile is blank and uses no data
1 - The tile is a direct uncompressed copy of 20 bytes
2 - The tile is compressed
3 - The tile is compressed and an xor scheme should be applied to it

The compression is of variable length, and as such there's no way to jump to a specific tile in the ROM; they have to be decompressed in order. The compression is relatively simple and consists of a 20-bit bitmask which indicates whether to load a byte of data or just push in 00. Here's an example, in which * indicates a compressed 0. Note that it processes bitmask word pairs "backwards", as with addresses.

         5        D        E        7        5        6        7        5
D57E6557 FF**FF**|C0**C03F|**3F3FC0|3FC0FF**|FC**FF**|**3FFF**|3FC0FF**|0F**FF**

The set of palette IDs are at $3BF1C, and this is just a straight list of two bytes per level, the background palette and the object palette. The palettes themselves are at $3B6FC, and adding the palette ID * 20 (the size of a palette) will take you to the one you're looking for.

The index of map data can be found at $434F. Add 2*zone bytes to that and you'll find the zone index; go to that address, add 2*act and you get the address of your level's map data. Here's what a complete set of STT.

      [block][ map ] wdth
TH1 - 1100 8012 C080 A800 58FF 9804 0000 0800 3014 3802 334D
TH2 - 1100 8012 B489 A800 58FF 9804 0000 0800 3014 3802 334D
TH3 - 1100 801A 49B0 4000 C0FF C001 0000 0800 3007 3802 034E

SP1 - 1180 9B12 5A92 A800 58FF 9804 0000 0800 3014 3802 334D
SP2 - 1180 9B12 159C 8000 80FF 8003 0000 0800 300F 3803 634D
SP3 - 1180 9B12 159C 8000 80FF 8003 0000 0800 300F 3803 634D

MJ1 - 1B00 8012 AAA5 8000 80FF 8003 0000 0800 300F 3803 634D
MJ2 - 1B00 8012 45AF 8000 80FF 8003 0000 0800 300F 3803 634D
MJ3 - 1B00 8014 80B2 4000 C0FF C001 0000 0800 3007 3803 034E

RW1 - 1400 8014 A5B5 8000 80FF 8003 0000 0800 300F 3803 634D
RW2 - 1400 8015 0080 8000 80FF 8003 0000 0800 300F 3803 634D
RW3 - 1400 8012 23B9 6000 A0FF A002 0000 0800 300B 3804 A34D

TP1 - 14E0 9915 6686 8000 80FF 8003 0000 0800 300F 3803 634D
TP2 - 14E0 9915 3490 3000 D0FF 5001 0000 0800 3005 3809 934E
TP3 - 14E0 9915 0B9A 4000 C0FF C001 0000 0800 3007 3801 034E

AD1 - 1B00 9C15 109B 8000 80FF 8003 0000 0800 300F 3803 634D
AD2 - 1B00 9C15 7AA5 6000 A0FF A002 0000 0800 300B 3804 A34D
AD3 - 1B00 9C15 E3AF A800 58FF 9804 0000 0800 3014 3802 334D

SS1 - 1940 8315 68B5 A800 58FF 9804 0000 0800 3014 3802 334D
SS3 - 1940 8315 3BB9 3000 D0FF 5001 0000 0800 3005 3809 934E
SS5 - 1940 831A ABB2 8000 80FF 8003 0000 0800 300F 3803 634D

Intro-1100 8012 0080 4000 C0FF C001 0000 0800 3007 3800 034E
End - 1100 8016 2AB1 A800 58FF 9804 0000 0800 3014 3802 334D

The block/map addresses are of the form

LS Address
MS Address

Note that Sunset Park 2-3 have the same map, and if you've played the game, you'll recall that there's not actually a transition between them unless you die.

Hit up that block address and you find a 200 byte collection of 2 byte offsets from the "main" block address. These 100 blocks correspond to the block numbers that will be used in the map; the first block is 00, second 01, etc. Some of the blocks will be identical offsets, which I assume is for the purpose of tagging them with additional effects such as breakability or hidden springage. At the offset is a collection of 20 bytes which form the actual block; each 2-byte segment defines a tile according to the SMS's specification found in the document I mentioned at the beginning, including the tile ID, palette, v/h flipping and bg/fg. The tile order is the same as printed English, left to right, top to bottom.

Sonic Triple Trouble map compression is a complicated; I just found the routine in the code and basically copied it word for word. It takes in a eight bit bitmask whenever its current bitmask runs dry; for each bit it tests, if that bit is 0 it copies in a byte of data, and if 1 that indicates that there is compressed data. The compression scheme works by copying data from a prior point in the map that has been already loaded. It reads in two bytes for directions: The MS half of the second byte + 3 indicates how many bytes to copy, and is then papered over with F so that the two bytes together can define the offset from the current position (which will always be backwards and less than 1000 because of the F and two's complement). If the two bytes are 0000, then the map is done.

Here's an example, from the first level of Sonic Triple Trouble:


So F1 is the bitmask control byte, which put backwards in binary according to how the game uses it would be 10001111. OK, so we're loading in one byte, doing three compressed sequences, then loading in four more.

So take in that FE. Now for the compression, we read in FFFF. That third F, the MS half of the second byte, indicates we're doing F+3 or 12 bytes of copying. It gets papered over with an F (no effect in this instance), so our offset is FFFF, or back one byte.

What this means is that it will copy the FE over one byte, then the "read from" address will move over into that FE that was just copied and the "copy to" address to the next empty space, and so repeating the process another 11 times we'll get 11 extra FEs. This behavioral quirk only happens when the offset is FFFF; otherwise you'd be copying in, say, the previous 2 bytes over and over if the offset was FEFF, the previous 3 if FDFF, or just a plain block if it was any offset larger than the number of bytes we're copying.

According to the next two bits in the bitmask, we're doing two more FFFF compression sequences, so that gives us 24 more FEs. The last four bits in the bitmask gives us four straight bytes, so we copy in FEFE0D05, and then we load in another bitmask and start the process again. The result so far is 27 FEs in a row, with 0D05 at the end.

Anyway, if you're interested in this compression scheme you can check out the source compression at the addresses mentioned in the big block of hex above, and the output uncompressed map you can see in Emukon or Mekaw by loading up the appropriate level and pointing the memory viewer to $C001, which is where it starts. I thought it was pretty nifty.

Loop XY motion data

Just like in Sonic 2 & Sonic Chaos, the player can't control Sonic or Tails while they move during loops. The game itself moves them, by using a few hex arrays. Two control the camera, and two more control their actual movement. $39B30 is where the array that controls the player while going forward through the loop is located. $3A010 is where the array that contains the camera's xy motion data while going forward through a loop is located. $3A1DF is where the array that contains the camera's XY motion data while going backwards through a loop is located. If you wanted to edit the movement, keep in mind you need to edit not just the player's movement, but the camera movement as well to get desired results.


Sonic the Hedgehog Triple Trouble
STT Title.png

Main page

Promotional material
Magazine articles
Video coverage

Hidden content
Technical information

Sonic Community Hacking Guide
SonED2 Manual | Subroutine Equivalency List
Sonic the Hedgehog (16-bit) | Sonic the Hedgehog (8-bit) | Sonic CD (prototype 510) | Sonic CD | Sonic CD (PC) | Sonic CD (2011) | Sonic 2 (Simon Wai prototype) | Sonic 2 (16-bit) | Sonic 2 (Master System) | Sonic 3 | Sonic 3 & Knuckles | Chaotix | Sonic Jam | Sonic Jam 6 | Sonic Adventure | Sonic Adventure DX: Director's Cut | Sonic Adventure DX: PC | Sonic Adventure (2010) | Sonic Adventure 2 | Sonic Adventure 2: Battle | Sonic Adventure 2 (PC) | Sonic Heroes | Sonic Riders | Sonic the Hedgehog (2006) | Sonic & Sega All-Stars Racing | Sonic Unleashed (Xbox 360/PS3) | Sonic Colours | Sonic Generations | Sonic Forces
Technical information
Sonic Eraser | Sonic 2 (Nick Arcade prototype) | Sonic CD (prototype; 1992-12-04) | Dr. Robotnik's Mean Bean Machine | Sonic Triple Trouble | Tails Adventures | Sonic Crackers | Sonic 3D: Flickies' Island | Sonic & Knuckles Collection | Sonic R | Sonic Shuffle | Sonic Advance | Sonic Advance 3 | Sonic Battle | Shadow the Hedgehog | Sonic Rush | Sonic Classic Collection | Sonic Free Riders | Sonic Lost World
Legacy Guides
The Nemesis Hacking Guides The Esrael Hacking Guides
ROM: Sonic 1 | Sonic 2 | Sonic 2 Beta | Sonic 3

Savestate: Sonic 1 | Sonic 2 Beta/Final | Sonic 3

Sonic 1 (English / Portuguese) | Sonic 2 Beta (English / Portuguese) | Sonic 2 and Knuckles (English / Portuguese)
Move to Sega Retro
Number Systems (or scrap) | Assembly Hacking Guide | 68000 Instruction Set | 68000 ASM-to-Hex Code Reference | SMPS Music Hacking Guide | Mega Drive technical information