Codetapper's Amiga Site

Ruff'n'Tumble Map Ripping and Tile Replacement

In this tutorial, you will learn how to locate the tiles from level 1-1 of Ruff'n'Tumble, locate the map, then perform some tile replacements to alter the map.

Download

Ruff'n'Tumble Save State used in this tutorial

Part 1: Tile Ripping

Load Maptapper and select Open from the File menu. Open the Ruff'n'Tumble_Level1-1.uss file.

The save-state was created in WinUAE by collecting a couple of objects on the first screen, destroying all the baddies, then moving to the far left to have a clean screen. A screenshot was also created and that will be used later to match the tiles.

Maptapper will open the WinUAE savestate, decompress it (if required), copy the ECS colour palette, select a default 16x16 tiles and position the tile ripper at address $0:

Start pressing the Page Down button on your keyboard. We're hunting for anything resembling graphics. Address $20800 looks interesting:

Horizontal bands through the graphics are a good indicator that you are in the wrong mode. It looks like this game uses ILBM tiles instead of ACBM. Press M to switch modes and increase the bitplane count to 5 by pressing the E key 4 times. You will start to see some tiles appear:

The tiles are not quite aligned correctly, so do some fine adjustments by pressing the Right Arrow key. Notice that in ILBM mode, the colour palette changes (and wraps) every 5 arrow key presses. This is because you are operating in 5 bitplane mode.

Once you get to address $2083a, the tile graphics look correct, but the colour palette is wrong:

Press the Copperlist button to trace the active copperlist rather than using the colour entries in the WinUAE save state. Hoorah! The tiles now appear, and don't they look awesome? Robin Levy did a magnificent job on them!

Now you need to find the first tile. Let's guess that the first completely black tile is the start of the tiles, so press Shift and Right Arrow until the tile appears in the top left corner.

The current rip width has defaulted to 320 x 256, but there may be a lot more tiles in the tileset, so increase the width and/or height that you are ripping by using the T/G and Y/H keys. It will make your life easier if you make the tile width an even multiple of 256 pixels, as this is 16 tiles across (or $10 in hexadecimal). I have chosen a rip width of 512 pixels in this case, or 32 tiles across ($20 in hex). These numbers will help you later when dealing with masks!

Part 2: Map Ripping

Now you have all the tiles, we need to locate the map. You could manually adjust settings looking for the map, but it's far easier to use the built-in tools. Click on the Map Search tab:

Now you need to load a screenshot from the game. Click the ... button and select the file Ruff'n'Tumble_Level1-1.png.

At this stage it is best to check the palette matches nicely, so click the Replace colours that do not match the tile palette button (which is mainly purple with a magic wand on it). The status bar at the top of the screen will change to purple, indicating some kind of copperlist tricks are changing the palette for that section.

Click inside the selection and drag it over the top left corner of the tree in the middle of the screen, then expand it out as shown:

Press the Match Tiles button and wait a few seconds. If everything goes to plan, Maptapper will locate the tiles, re-align your selection perfectly and display all the tile indexes:

Now you have the tile indexes for that area, press the Search for Map button to automatically search the memory dump for a map:

Now this is interesting. Maptapper has found 3 possible matches, one with a width of 25 tiles, and 2 matches with a width of 130 tiles.

When you see a particularly small width, it is often a screen buffer that contains just enough tiles to display a screen, plus a few extras around the edges. The other common possibility is that the game uses smaller tiles to make larger blocks.

Switch to the Map Ripper and select the first choice from the match list at $e5ce4. You will see that this is not the entire level:

Now try the next match at $e9a7e. This one looks much better:

Finally, check the 3rd match at $f2130. This one is almost identical to the previous one, but if you look closely, you will see that the final map has a few of the collectable items missing. The most logical explanation is that the game stores a large map in memory of each level complete with bonus objects, and a second duplicate map is altered by replacing tiles when objects are collected.

It's up to you which map you wish to use. If you want to rip the level with all objects on it, the second match will be just what you need.

Select the second map and locate the top left corner using the arrow keys. Adjust the height using the W and S keys. The map appears to be 24 tiles high:

At this point, you can save the entire level as a PNG by pressing the Save Map button and you are done. Or are you?

Part 3: Replacement tiles

Anyone familiar with the game will know that there are generators that spawn baddies. Perhaps you would like to show the deactivated generators on the map instead?

Hover the mouse over the left generator tile in the map, and notice the status bar at the bottom of the screen. It says:

Map: $EA342: (94, 14) = $8414 = tile 20 ($14)

This is showing that the mouse is over address $ea342 in memory, which is co-ordinate (94, 14). The value in memory is $8414, and when combined with the shift value (0) and mask ($3ff), the output tile is 20 (or $14 in hexadecimal).

If you switch back to the Tile Ripper tab, hover over the deactivated generator tile:

Check the status bar and notice the text:

Tile Ripper: 84 ($54)

This tells you that tile 84 (or $54 in hex) is the left tile of a deactivated generator. Tile 85 ($55 in hex) is the right tile.

Switch back to the Map Ripper tab and click in the Replacement Tile section. Type in the following:

$8414=$54
$8415=$55

Now hit F5 to refresh the map. Suddenly the generators will change everywhere in the level:

By hovering over sections of the map, you can find out a huge amount of information about how the levels are constructed. Solid areas appear to have $400 set. Platforms you can jump up onto have $800 set. Hills have $4000 set. $8000 is some kind of special code too. By playing around with the mask value you can gain a great deal of understanding about how the level is made.

If you want a clean level, you can paste the following in:

2,4-5,8-$c,$e=0
$56-$5d=0
$8000-$8004,$8008-$800d=0
$8414=$54 ;Generator left
$8415=$55 ;Generator right

This will remove all the collectable items, replacing them with a blank tile. Enemy spawn positions will be hidden. Weapon collectables will be hidden. Dead generators will replace the existing tiles. You can alter the map quite significantly if required!

Tile Replacement Assembly Code

For those that are interested, here is the commented routine that is called when one of the special tiles is touched. This allows the game to call a routine such as adding to the score, increasing firepower or triggering baddies etc.

_db43c  move.w  (a1),d0         ;Read tile in memory
        and.w   #$83ff,d0       ;Mask off useful bits
        beq     _rts            ;If tile index is 0, bail out

        cmp.w   #$5e,d0         ;If the tile index is between 1 and $5d
        blt     _db44c          ;check for a replacement tile in the 
        bpl     _rts            ;table, otherwise bail out

_db44c  lea     _Tiles(pc),a2   ;Load tile replacement table into a2
_db450  tst.w   (a2)            ;Check if we're at the end and if so,
        beq     _rts            ;bail out

        cmp.w   (a2),d0         ;See if the tile index we read matches the
        beq     _db45e          ;lookup table. If so, continue!

        lea     (6,a2),a2       ;Skip 6 bytes ahead to the next entry
        bne     _db450
		
_db45e  move.w  (2,a2),(a1)     ;Write replacement tile index into memory
        move.w  (4,a2),d0       ;Check for routine to call
        beq     _db472          ;If not, skip ahead

        movem.l d2/a1,-(a7)     ;Save registers onto the stack and call
        jsr     (d0.w,a6)       ;the routine for this tile
        bra     _db476          ;And skip ahead

_db472  movem.l d2/a1,-(a7)     ;Save registers onto the stack
_db476  bsr     _dd6ba          ;Do something
        movem.l (a7)+,d2/a1     ;Restore registers from the stack
_rts    rts                     ;And exit!

; Replacement tile table. (1) = Original tile index
; At $db70a on level 1-1. (2) = Replacement tile index
;                         (3) = Routine to call upon replacement
;
;                (1)   (2)   (3)
_Tiles  dc.w    $0002,$0000,$ebfa 
        dc.w    $0004,$0000,$ec12 
        dc.w    $0005,$0000,$ec1e 
        dc.w    $0008,$0000,$ec48 
        dc.w    $0009,$0000,$ecb8 
        dc.w    $000b,$0000,$ee7a 
        dc.w    $000e,$0000,$ed00 
        dc.w    $000a,$0000,$ed14
        dc.w    $8009,$0000,$ec92 
        dc.w    $8008,$0000,$ec56 
        dc.w    $8000,$0000,$eb34 
        dc.w    $8001,$0000,$eb74 
        dc.w    $8002,$0000,$eb54 
        dc.w    $800a,$0000,$ebac 
        dc.w    $800b,$0000,$ebe0 
        dc.w    $800c,$0000,$ebc6
        dc.w    $8003,$0000,$eb94 
        dc.w    $8004,$0000,$eba0 
        dc.w    $800d,$0000,$ec78 
        dc.w    $000c,$0000,$ec62 
        dc.w    $0056,$0000,$ed24 
        dc.w    $0057,$0000,$ed24 
        dc.w    $0058,$0000,$ed24 
        dc.w    $0059,$0000,$ed24
        dc.w    $005a,$0000,$ed24 
        dc.w    $005b,$0000,$ed24 
        dc.w    $005c,$0000,$ed24 
        dc.w    $005d,$0000,$ed24 
        dc.w    $0000 

Post your comment

Comments

  • Gravatar for Sokolovic

    Do you think it may be possible with such a tools and a bit of coder skills to make an AGA enhanced version of RnT ? Using dual playfield to have a parallax and adding second but ton or CD32 pad will make this game even greater then It is !

    Sokolovic 27/10/2016 11:47am (10 months ago)

  • Gravatar for Theo

    Great work ! thank you ..

    Theo 20/10/2014 8:58am (3 years ago)

RSS feed for comments on this page | RSS feed for all comments

You may enjoy these articles...

Ruff'n'Tumble Map Ripping and Tile Replacement

Comedy

If you look inside many Amiga games, secret messages have been hidden by the programmers. Richard Aplin was the king of hiding messages in the startup-sequence file, and his Line of Fire and Final Fight startup-sequences have become legendary! The Sensible Software team were also prolific at hiding messages in their games.

Ruff'n'Tumble Map Ripping and Tile Replacement

Interviews

A collection of technical interviews with Amiga programmers that worked on commercial software in the glory days of the Amiga (late 1980s to early 1990s!)

Ruff'n'Tumble Map Ripping and Tile Replacement

Maptapper

The Ultimate Amiga Graphics, Level and Map Ripper!

Ruff'n'Tumble Map Ripping and Tile Replacement

Random Rants

A random assortment of rants relating to the Amiga!

Ruff'n'Tumble Map Ripping and Tile Replacement

Sprite Tricks

An explanation of how many famous Amiga games utilised sprites in weird and interesting ways