Codetapper's Amiga Site

Stunt Car Racer

Geoff Crammond's fantastic game Stunt Car Racer (along with the American version Stunt Track Racer) renders the very tops of the tyres using sprites.

To fit everything in a single load, the game stores a large number of assets in a run-length-encoded format and depacks the data as required. This includes the static image of the dashboard, the grandstand pre-race view, all the race result screens (won, lost and crashed) plus the promotion screen when the racing division is won.

Once the race begins, the game depacks the dashboard into memory. Note that this version does not contain any wheel graphics. The extra graphics are drawn onto the display from a series of images:



The game renders the 3D world into the main gap in the dashboard, which is only 256 pixels wide by 128 pixels tall. Optional graphical objects such as sparks and dirt are drawn, followed by the wheels, engine and flames if necessary. And finally, sprites showing the very top part of the tyres sit on top of everything else.

Sprite animation frames

The two variants of tyre graphics are used depending on where the tyres are drawn by the game. When the tyres are drawn in their lowest position, the top set of sprites are used so they don't obscure the engine graphics, and the rest of the time the lower set of sprites are used.

The game locks the refresh rate to give a consistent display update every 6 frames. On a 50Hz PAL Amiga, this gives a frame rate of between 8 and 9 frames/second. This means that the bitmap graphics of the wheels would also remain for 6 frames until the next animation frame is drawn.

By updating the tyre graphics more frequently, the player is fooled into believing the game's running at a faster frame rate than it actually is. By overlaying 2 sprites, Geoff was able to update the tyre animations by simply updating the two sprite pointers SPR0PT and SPR1PT in the copperlist. On the Atari ST, the actual tyre bitmap graphics have to drawn every frame to give the same sense of speed as the Amiga version.

Chip Addr: Copper instructions ; Comments
$0000E74E: 00E0 0006 00E2 A594 ; BPL1PT = 0x0006A594
$0000E756: 00E4 0006 00E6 C4D4 ; BPL2PT = 0x0006C4D4
$0000E75E: 00E8 0006 00EA E414 ; BPL3PT = 0x0006E414
$0000E766: 00EC 0007 00EE 0354 ; BPL4PT = 0x00070354
$0000E76E: 0180 0000           ; COLOR00 = 0x0000
$0000E772: 0182 0997           ; COLOR01 = 0x0997
$0000E776: 0184 0BB9           ; COLOR02 = 0x0BB9
$0000E77A: 0186 0FF0           ; COLOR03 = 0x0FF0
$0000E77E: 0188 09B3           ; COLOR04 = 0x09B3
$0000E782: 018A 0577           ; COLOR05 = 0x0577
$0000E786: 018C 05BF           ; COLOR06 = 0x05BF
$0000E78A: 018E 059F           ; COLOR07 = 0x059F
$0000E78E: 0190 0357           ; COLOR08 = 0x0357
$0000E792: 0192 0500           ; COLOR09 = 0x0500
$0000E796: 0194 0733           ; COLOR10 = 0x0733
$0000E79A: 0196 0955           ; COLOR11 = 0x0955
$0000E79E: 0198 0D99           ; COLOR12 = 0x0D99
$0000E7A2: 019A 0775           ; COLOR13 = 0x0775
$0000E7A6: 019C 0BBB           ; COLOR14 = 0x0BBB
$0000E7AA: 019E 0FFF           ; COLOR15 = 0x0FFF
$0000E7AE: 01A0 0000           ; COLOR16 = 0x0000
$0000E7B2: 01A2 0000           ; COLOR17 = 0x0000
$0000E7B6: 01A4 0FFF           ; COLOR18 = 0x0FFF
$0000E7BA: 01A6 0C88           ; COLOR19 = 0x0C88
$0000E7BE: 01A8 0000           ; COLOR20 = 0x0000
$0000E7C2: 01AA 0000           ; COLOR21 = 0x0000
$0000E7C6: 01AC 0FFF           ; COLOR22 = 0x0FFF
$0000E7CA: 01AE 0C88           ; COLOR23 = 0x0C88
$0000E7CE: 01B0 0000           ; COLOR24 = 0x0000
$0000E7D2: 01B2 0000           ; COLOR25 = 0x0000
$0000E7D6: 01B4 0000           ; COLOR26 = 0x0000
$0000E7DA: 01B6 0000           ; COLOR27 = 0x0000
$0000E7DE: 01B8 0000           ; COLOR28 = 0x0000
$0000E7E2: 01BA 0000           ; COLOR29 = 0x0000
$0000E7E6: 01BC 0000           ; COLOR30 = 0x0000
$0000E7EA: 01BE 0000           ; COLOR31 = 0x0000
$0000E7EE: 0120 0000 0122 C3D8 ; SPR0PT = 0x0000C3D8
$0000E7F6: 0124 0000 0126 C540 ; SPR1PT = 0x0000C540
$0000E7FE: 0128 0000 012A F4B4 ; SPR2PT = 0x0000F4B4
$0000E806: 012C 0000 012E F4B4 ; SPR3PT = 0x0000F4B4
$0000E80E: 0130 0000 0132 F4B4 ; SPR4PT = 0x0000F4B4
$0000E816: 0134 0000 0136 F4B4 ; SPR5PT = 0x0000F4B4
$0000E81E: 0138 0000 013A F4B4 ; SPR6PT = 0x0000F4B4
$0000E826: 013C 0000 013E F4B4 ; SPR7PT = 0x0000F4B4
$0000E82E: FA01 FF00           ; Wait for vpos >= 0xFA
                               ; Destination Y coordinate reached!

Here's what the run-length-encoding depacking routine at $593f8 looks like:

                movea.l a1,a2
                move.w  #200-1,d6       ;Height of the display - 1 for DBF loop
.NextLine       move.w  #4-1,d5         ;Number of bitplanes - 1 for DBF loop
.NextPlane      movea.l a2,a1
                adda.l  #8000,a2
                move.w  #0,d3
.ReadNextByte   move.b  (a0)+,d0
                bpl.w   .PlainCopyBytes
                neg.b   d0
                bmi.w   .ReadNextByte
                andi.w  #$FF,d0
                move.b  (a0)+,d4
.CopyRunLoop    move.b  d4,(a1)+
                addq.b  #1,d3
                dbra    d0,.CopyRunLoop
                bra.w   .CheckFinished

.PlainCopyBytes andi.w  #$FF,d0
.CopyByteLoop   move.b  (a0)+,(a1)+
                addq.b  #1,d3
                dbra    d0,.CopyByteLoop
.CheckFinished  cmpi.b  #40,d3
                bne.w   .ReadNextByte
                dbra    d5,.NextPlane
                adda.l  #-31960,a2
                dbra    d6,.NextLine

Post your comment


  • Gravatar for mance

    I achieved mastery on Speccy in this game (it still looks and plays very well) but I always wanted more frames per second and greater draw distance.

    mance 02/05/2024 11:47am (25 days ago)

  • Gravatar for Codetapper

    @Charles: I have a few ideas for some AGA entries which I'll add when I get some time, but there were a few restrictions compared to OCS/ECS and I am not sure you could multiplex sprites across the screen horizontally when using 32-bit or 64-bit wide sprites unfortunately.

    Codetapper 21/02/2024 3:15am (3 months ago)

  • Gravatar for Charles

    Wonderful to see a new entry in this series, thank you for the detailed analysis! Do any AGA games use sprite tricks or did that practice fall out of favor after the OCS/ECS era?

    Charles 10/01/2024 9:31pm (5 months ago)

  • Gravatar for Code Tapper

    Sorry, here in NZ, Australia and the UK it's tyres not tires!

    Code Tapper 22/12/2023 10:28pm (5 months ago)

  • Gravatar for Swedish Pete

    Tires, please.

    Swedish Pete 22/12/2023 3:23am (5 months ago)

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

Popular Sprite Tricks

Stunt Car Racer

Jim Power

2 sprites are displayed then repositioned horizontally right across the screen to create the colourful static background. The remaining sprites are used for the main character, the status bar and player bullets.

Stunt Car Racer

Risky Woods

The 16-colour background layer was created by using all 8 hardware sprites and repositioning them across the screen. The same 64 pixel wide graphics are repeated across the entire play area.

Stunt Car Racer

Shadow of the Beast

One of the first jaw-droppingly beautiful Amiga games that still looks great today. Sprites were heavily re-used on the screen, along with priority changes to make them appear between the playfields.

Stunt Car Racer


The amazing tunnel sequence was created with a 6 frame animation sequence made with only 4 colours and mirrored vertically. The asteroid layer sits on top of this, with a status panel and player ship made of sprites sitting on top.