;
;       Disassembled by:
;               DASMx object code disassembler
;               (c) Copyright 1996-1999   Conquest Consultants
;               Version 1.30 (Oct  6 1999)
;       Commented by:
;               Annotate 1.44 beta (10 Nov 2007) by Amigan Software
;               (and by hand)
;
;       File:           CarRaces!.bin
;       Size:           2048 bytes
;       Date:           Sun Oct 14 20:50:24 2007
;       CPU:            Signetics 2650 (2650 family)
;       Platform:       Interton VC 4000 family, type "A" (2K ROM + 0K RAM)
;
;$VER: 1.0 (17.9.2010)
;Disassembled and patched by Amigan Software in November 2007 and
; August-September 2010.
;Please inform us of any mistakes found...
;URL:   http://amigan.classicgaming.gamespy.com/
;EMail: amigansoftware@gmail.com
;
;This patch (NEW vs. OLD) enables the game to be played under Ami/
; WinArcadia 14.41. You still need to have "use compatibility hacks?"
; enabled, however.
;Basically the problem is that interrupts are sometimes inhibited at the
; time they occur.
;
;Hardware Equates/Memory Map----------------------------------------------
;                   $0000..$07FF: (R/-)  2K of ROM
;                   $0800..$15FF: (-/-)  unused
;                   $1600..$17FF:        mirror of $1E00..$1FFF
;                   $1800..$1DFF: (-/-)  unused
;                   $1E00..$1E7F: (-/-)  unused
NOISE           equ $1E80        ;(?/W)  noise register
;    bits 7..6:                          unused?
;    bit  5:                             bkgrnd colour inversion on/off
;    bit  4:                             noise on/off
;    bit  3:                             unknown
;    bit  2:                             tones on/off?
;    bits 1..0:                          unused?
;                   $1E81..$1E87: (-/-)  unmapped
P1LEFTKEYS      equ $1E88        ;(R/-)
;    bit  7:                             p1 (left)  '1' button
;    bit  6:                             p1 (left)  '4' button
;    bit  5:                             p1 (left)  '7' button
;    bit  4:                             p1 (left)  'C' button (Clear)
;    bits 3..0:                          unused
P1MIDDLEKEYS    equ $1E89        ;(R/-)
;    bit  7:                             p1 (left)  '2' button
;    bit  6:                             p1 (left)  '5' button
;    bit  5:                             p1 (left)  '8' button
;    bit  4:                             p1 (left)  '0' button
;    bits 3..0:                          unused
P1RIGHTKEYS     equ $1E8A        ;(R/-)
;    bit  7:                             p1 (left)  '3' button
;    bit  6:                             p1 (left)  '6' button
;    bit  5:                             p1 (left)  '9' button
;    bit  4:                             p1 (left)  'E' button (Enter)
;    bits 3..0:                          unused
CONSOLE         equ $1E8B        ;(R/-)
;    bit  7:                             'SELECT'       button
;    bit  6:                             'START'        button
;    bit  5:                             unused
;    bit  4:                             unused
;    bits 3..0:                          unused
P2LEFTKEYS      equ $1E8C        ;(R/-)
;    bit  7:                             p2 (right) '1' button
;    bit  6:                             p2 (right) '4' button
;    bit  5:                             p2 (right) '7' button
;    bit  4:                             p2 (right) 'C' button (Clear)
;    bits 3..0:                          unused
P2MIDDLEKEYS    equ $1E8D        ;(R/-)
;    bit  7:                             p2 (right) '2' button
;    bit  6:                             p2 (right) '5' button
;    bit  5:                             p2 (right) '8' button
;    bit  4:                             p2 (right) '0' button
;    bits 3..0:                          unused
P2RIGHTKEYS     equ $1E8E        ;(R/-)
;    bit  7:                             p2 (right) '3' button
;    bit  6:                             p2 (right) '6' button
;    bit  5:                             p2 (right) '9' button
;    bit  4:                             p2 (right) 'E' button (Enter)
;    bits 3..0:                          unused
;                   $1E8F..$1E97  (-/-)  unmapped
;                   $1E98..$1E9B  (R/-)  mirror of $1E88..$1E8B
;                   $1E9C..$1EA7  (-/-)  unmapped
;                   $1EA8..$1EAE  (R/-)  mirror of $1E88..$1E8E
;                   $1EAF..$1EB7  (-/-)  unmapped
;                   $1EB8..$1EBB  (R/-)  mirror of $1E88..$1E8B
;                   $1EBC..$1EC7  (-/-)  unmapped
;                   $1EC8..$1ECE  (R/-)  mirror of $1E88..$1E8E
;                   $1ECF..$1ED7  (-/-)  unmapped
;                   $1ED8..$1EDB  (R/-)  mirror of $1E88..$1E8B
;                   $1EDC..$1EE7  (-/-)  unmapped
;                   $1EE8..$1EEE  (R/-)  mirror of $1E88..$1E8E
;                   $1EEF..$1EF7  (-/-)  unmapped
;                   $1EF8..$1EFB  (R/-)  mirror of $1E88..$18EB
;                   $1EFC..$1EFF  (-/-)  unmapped
;                   $1F00..$1F09: (R/W)  imagery for sprite #0 (8*10)
SPRITE0AX       equ $1F0A        ;(R/W)
SPRITE0BX       equ $1F0B        ;(R/W)
SPRITE0AY       equ $1F0C        ;(R/W)
SPRITE0BY       equ $1F0D        ;(R/W)
;                   $1F0E..$1F0F: (R/W)  motherboard RAM
;                   $1F10..$1F19: (R/W)  imagery for sprite #1 (8*10)
SPRITE1AX       equ $1F1A        ;(R/W)
SPRITE1BX       equ $1F1B        ;(R/W)
SPRITE1AY       equ $1F1C        ;(R/W)
SPRITE1BY       equ $1F1D        ;(R/W)
;                   $1F1E..$1F1F: (R/W)  motherboard RAM
;                   $1F20..$1F29: (R/W)  imagery for sprite #2 (8*10)
SPRITE2AX       equ $1F2A        ;(R/W)
SPRITE2BX       equ $1F2B        ;(R/W)
SPRITE2AY       equ $1F2C        ;(R/W)
SPRITE2BY       equ $1F2D        ;(R/W)
;                   $1F2E..$1F3F: (-/-)  unmapped
;                   $1F40..$1F49: (R/W)  imagery for sprite #3 (8*10)
SPRITE3AX       equ $1F4A        ;(R/W)
SPRITE3BX       equ $1F4B        ;(R/W)
SPRITE3AY       equ $1F4C        ;(R/W)
SPRITE3BY       equ $1F4D        ;(R/W)
;                   $1F4E..$1F6D: (R/W)  motherboard RAM
;                   $1F6E..$1F7F: (-/-)  unmapped
;                   $1F80..$1FA7 ;(R/W)  vertical grid
HORIZ1          equ $1FA8        ;(R/W)  horizontal grid #1
HORIZ2          equ $1FA9        ;(R/W)  horizontal grid #2
HORIZ3          equ $1FAA        ;(R/W)  horizontal grid #3
HORIZ4          equ $1FAB        ;(R/W)  horizontal grid #4
HORIZ5          equ $1FAC        ;(R/W)  horizontal grid #5
;                   $1FAD:        (R/W)  motherboard RAM
;                   $1FAE..$1FBF: (-/-)  unmapped
SIZES           equ $1FC0        ;(-/W)
SPR01COLOURS    equ $1FC1        ;(-/W)
;    bits 7..6:                          unused
;    bits 5..3:                          colour of sprite #0
;                                        (inverted RGB mask)
;    bits 2..0:                          colour of sprite #1
;                                        (inverted RGB mask)
SPR23COLOURS    equ $1FC2        ;(-/W)
;    bits 7..6:                          unused
;    bits 5..3:                          colour of sprite #2
;                                        (inverted RGB mask)
;    bits 2..0:                          colour of sprite #3
;                                        (inverted RGB mask)
SCORECTRL       equ $1FC3        ;(-/W)
;    bits 7..2:                          unused
;    bit  1:                             score format
;                                        0 = 2 groups of 2 digits
;                                        1 = 1 group  of 4 digits
;    bit  0:                             score position
;                                        0 = top    of screen
;                                        1 = bottom of screen
;                   $1FC4..$1FC5: (-/-)  unused
BGCOLOUR        equ $1FC6        ;(-/W)
;    bit  7:                             unused
;    bits 6..4:                          grid colour (normal RGB HB mask)
;    bit  3:                             grid/background enable flag
;                                        (0=off, 1=on)
;    bits 2..0:                          screen colour (normal RGB HB
;                                        mask) (black if bit 3 is clear)
PITCH           equ $1FC7        ;(-/W)
;    bits 7..0:                          pitch
SCORELT         equ $1FC8        ;(-/W)  left digit pair
;    bits 7..4:                          BCD value of 1st digit
;    bits 3..0:                          BCD value of 2nd digit
SCORERT         equ $1FC9        ;(-/W)  right digit pair
;    bits 7..4:                          BCD value of 3rd digit
;    bits 3..0:                          BCD value of 4th digit
BGCOLLIDE       equ $1FCA        ;(R/-)  read-once!
;    bit  7:                             sprite #0 collision with bkgrnd
;    bit  6:                             sprite #1 collision with bkgrnd
;    bit  5:                             sprite #2 collision with bkgrnd
;    bit  4:                             sprite #3 collision with bkgrnd
;    bit  3:                             sprite #0 display complete
;    bit  2:                             sprite #1 display complete
;    bit  1:                             sprite #2 display complete
;    bit  0:                             sprite #3 display complete
SPRITECOLLIDE   equ $1FCB        ;(R/-)  read-once!
;    bit  7:                             unused
;    bit  6:                             vertical reset flag
;    bit  5:                             sprites #0/#1 collision
;    bit  4:                             sprites #0/#2 collision
;    bit  3:                             sprites #0/#3 collision
;    bit  2:                             sprites #1/#2 collision
;    bit  1:                             sprites #1/#3 collision
;    bit  0:                             sprites #2/#3 collision
P1PADDLE        equ $1FCC        ;(R/-)
P2PADDLE        equ $1FCD        ;(R/-)
;                   $1FCE..$1FCF ;(-/-)  unused
;                   $1FD0..$1FDF:        semi-mirror of $1FC0..$1FCF
;                   $1FE0..$1FEF:        semi-mirror of $1FC0..$1FCF
;                   $1FF0..$1FFF:        semi-mirror of $1FC0..$1FCF
;                   $2000..$3FFF:        mirror of $0000..$1FFF
;                   $4000..$5FFF:        mirror of $0000..$1FFF
;                   $6000..$7FFF:        mirror of $0000..$1FFF
;2650 Equates-------------------------------------------------------------
z               equ 0
eq              equ z
p               equ 1
gt              equ p
n               equ 2
lt              equ n
un              equ 3
;User Variables-----------------------------------------------------------
;Of the 37 RAM bytes:
; 33 are named.
;  2 we have some idea about.
;  2 are totally unknown.

PRESERVER0      equ $1F0E
PRESERVEPSL     equ $1F0F
OPTION          equ $1F1E ;$00 = "01", $01 = "02", etc. to $09 = "10"
GAME            equ $1F1F ;GAME = OPTION / 2;
                          ;$00 = "01"/"02" (grand prix)
                          ;$01 = "03"/"04" (rally)
                          ;$02 = "05"/"06" (easy slalom)
                          ;$03 = "07"/"08" (med. slalom)
                          ;$04 = "09"/"10" (hard slalom)
BGCOLCOPY       equ $1F4E
SPRCOLCOPY      equ $1F4F
LTDRAWN         equ $1F50 ;$00..$04
RTDRAWN         equ $1F51 ;$00..$04
PLAYER1X        equ $1F52 ;$0A..$BE
PLAYER2X        equ $1F53 ;$0A..$BE
PLAYER1SPEED    equ $1F54
PLAYER2SPEED    equ $1F55
P1COLLIDE       equ $1F56 ;= $32 when colliding, then counts down to 0
P2COLLIDE       equ $1F57 ;= $32 when colliding, then counts down to 0
MONOTONIC_L     equ $1F58 ;monotonic decrementor, low  (less significant) byte
MONOTONIC_H     equ $1F59 ;monotonic decrementor, high (more significant) byte
INVERTCOLOURS   equ $1F5A ;bit 3 (%00010000) = playing game yes/no
                          ;bit 5 (%00000100) = inverted colours yes/no
                   ;$1F5B is?
P1CRASHES       equ $1F5C ;how many times player 1 has crashed
P2CRASHES       equ $1F5D ;how many times player 2 has crashed
SOUNDVAR        equ $1F5E
                   ;$1F5F is?
P1VAR           equ $1F60
P2VAR           equ $1F61
P1DISTANCE_H    equ $1F62
P2DISTANCE_H    equ $1F63
P1DISTANCE_L    equ $1F64
P2DISTANCE_L    equ $1F65
LEFTREDX        equ $1F66 ;X-position of left  red    enemy ($00..$7F) (starts as $32)
LEFTGREENX      equ $1F67 ;X-position of left  green  enemy ($00..$7F) (starts as $B7).
LEFTPURPLEX     equ $1F68 ;X-position of left  purple enemy ($00..$7F) (starts as $32).
LEFTYELLOWX     equ $1F69 ;X-position of left  yellow enemy ($00..$7F) (starts as $AD).
RIGHTPURPLEX    equ $1F6A ;X-position of right purple enemy ($80..$FF) (starts as $B2).
RIGHTREDX       equ $1F6B ;X-position of right red    enemy ($80..$FF) (starts as $2D).
RIGHTBLUEX      equ $1F6C ;X-position of right blue   enemy ($80..$FF) (starts as $B2).
RIGHTCYANX      equ $1F6D ;X-position of right cyan   enemy ($80..$FF) (starts as $37).
;The high bit of $1F66..$1F6D seems to be ignored (or, more likely, used
; for another purpose).
;These are correct for the title screen but perhaps they rotate during
; play?
CLEARBITS       equ $1FAD
;-------------------------------------------------------------------------
        org     $0000
;
L0000:
        eorz    r0           ;r0 = 0;                                 ;2,1
        bctr,un BOOT         ;goto BOOT;                              ;3,2
L0003:
        bcta,un INTERRUPT    ;goto INTERRUPT;                         ;3,3
;-------------------------------------------------------------------------
BOOT:                                                                  ;$6
        strz    r2           ;r2 = r0 [0];                            ;2,1
        strz    r3           ;r3 = r0 [0];                            ;2,1
        lpsu                 ;PSU = r0 [%0,0,0,000,000];              ;2,1
        lodi,r0 $02          ;r0 = $02;                               ;2,2
        lpsl                 ;PSL = r0 [%0,0,0,0,0,0,1,0]; // use logical (unsigned) compare
                                                                      ;2,1
        rrl,r0               ;r0 <<= 1;                               ;2,1
        stra,r0 NOISE        ;NOISE = r0 [4]; // noise generator      ;4,3
;execution flows into the following code section
;-------------------------------------------------------------------------
TITLESCREEN:                                                          ;$10

;$10..$5E is as follows:
;inhibit interrupts (finally!) and set Stack Pointer to 7 (why?)
;*($1F00..$1FFF) = 0; // clear RAM
;INVERTCOLOURS = r3;
;OPTION = (r2 >> 1) & %00001111;
;GAME   =  r2;
;if (rally)
;{   ; // do nothing
;} elif (grand prix)
;{   for (r3 = 40; r3 >= 1; r3 -= 4)
;    {   *($1F7F + r3) = 2;            // vertical grid
;        *($1F7E + r3) = $81 - OPTION; // vertical grid
;                     // $81 for option "01", $80 for option "02"
;        *($1F7D + r3) = 2;            // vertical grid
;        *($1F7C + r3) = $80;          // vertical grid
;    }
;    HORIZ1..HORIZ5 = $3F;
;} elif (easy slalom)
;{   *($1F80..$1FAC) = *($35F..$38B); // vertical and horizontal grid
;} elif (medium slalom)
;{   *($1F80..$1FAC) = *($38C..$3B8); // vertical and horizontal grid
;} elif (hard slalom)
;{   *($1F80..$1FAC) = *($3B9..$3E3); // vertical and horizontal grid
;}
        ppsu    $27          ;PSU |= %0,0,1,00,111;                   ;3,2
        eorz    r0           ;r0 = 0;                                 ;2,1
        strz    r1           ;r1 = r0 [256]; // loop iterator         ;2,1
TITLESCREEN_1:                                                        ;$14
        stra,r0 $1F00,r1     ;*($1F00 + r1) = r0 [0];                 ;4,3
        bdrr,r1 TITLESCREEN_1;if (--r1 != 0) goto TITLESCREEN_1;      ;3,2
        stra,r3 INVERTCOLOURS;INVERTCOLOURS = r3; // motherboard RAM  ;4,3
        stra,r2 OPTION       ;OPTION = r2; // motherboard RAM         ;4,3
        rrr,r2               ;r2 >>= 1;                               ;2,1
        andi,r2 $0F          ;r2 &= %00001111;                        ;2,2
        stra,r2 GAME         ;GAME = r2; // motherboard RAM           ;4,3
        loda,r0 $018F,r2     ;r0 = *($018F + r2);                     ;4,3
        bctr,eq TITLESCREEN_8;if == goto TITLESCREEN_8;               ;3,2
        comi,r0 $FF          ;compare r0 against $FF;                 ;2,2
        bctr,eq TITLESCREEN_3;if == goto TITLESCREEN_3;               ;3,2
        strz    r2           ;r2 = r0;                                ;2,1
        lodi,r3 $2D          ;r3 = $2D; // loop iterator              ;2,2
TITLESCREEN_2:                                                        ;$31
        loda,r0 $035F,r2-    ;r0 = *($035F + --r2);                   ;4,3
        stra,r0 $1F7F,r3     ;*($1F7F + r3) = r0;                     ;4,3
        bdrr,r3 TITLESCREEN_2;if (--r3 != 0) goto TITLESCREEN_2;      ;3,2
        bctr,un TITLESCREEN_8;goto TITLESCREEN_8;                     ;3,2
TITLESCREEN_3:                                                        ;$3B
        lodi,r1 $81          ;r1 = $81;                               ;2,2
        subr,r1 *$001D       ;r1 -= *(*($001D)); // ROM               ;3,2
                             ;or, r1 -= OPTION; // motherboard RAM
        lodi,r2 $01          ;r2 = $01;                               ;2,2
        lodi,r3 $28          ;r3 = $28; // loop iterator              ;2,2
TITLESCREEN_4:                                                        ;$43
        lodi,r0 $02          ;r0 = $02;                               ;2,2
        stra,r0 $1F7F,r3     ;*($1F7F + r3) = r0 [2];                 ;4,3
        brnr,r2 TITLESCREEN_5;if (r2 != 0) goto TITLESCREEN_5;        ;3,2
        lodi,r0 $80          ;r0 = $80;                               ;2,2
        bctr,un TITLESCREEN_6;goto TITLESCREEN_6;                     ;3,2
TITLESCREEN_5:                                                        ;$4E
        lodz    r1           ;r0 = r1;                                ;2,1
TITLESCREEN_6:                                                        ;$4F
        stra,r0 $1F7F,r3-    ;*($1F7F + --r3) = r0;                   ;4,3
        eori,r2 $01          ;r2 ^= %00000001;                        ;2,2
        bdrr,r3 TITLESCREEN_4;if (--r3 != 0) goto TITLESCREEN_4;      ;3,2
        lodi,r3 $05          ;r3 = $05; // loop iterator              ;2,2
TITLESCREEN_7:                                                        ;$58
        lodi,r0 $3F          ;r0 = $3F;                               ;2,2
        stra,r0 $1FA7,r3     ;*($1FA7 + r3) = r0 [$3F];               ;4,3
        bdrr,r3 TITLESCREEN_7;if (--r3 != 0) goto TITLESCREEN_7;      ;3,2

;$5F..$97 is as follows:
;for (r1 = 3; r1 >= 0; r1--) // for each of the 4 sprites
;{   CLEARBITS = r1;
;    r2 = (r1 * 3) + *($194 + GAME);
;    r3 = *($440 + r1); // offset into sprite data area ($00/$10/$20/$40)
;    *($1F00 + r3) = *($444 + r2);
;    r2++;
;    *($1F02 + r3) = *($444 + r2);
;    *($1F03 + r3) = #######.;
;    if (r1 <= 2 || (OPTION & 1 == 0))
;    {   r2++;
;        r2 = *($444 + r2);
;        gosub $294;
;    }
;    r1 = CLEARBITS;
;}
TITLESCREEN_8:                                                        ;$5F
        lodi,r1 $03          ;r1 = $03; // loop iterator              ;2,2
TITLESCREEN_9:                                                        ;$61
        stra,r1 CLEARBITS    ;CLEARBITS = r1; // motherboard RAM      ;4,3
        lodz    r1           ;r0 = r1;                                ;2,1
        rrl,r0               ;r0 <<= 1;                               ;2,1
        addz    r1           ;r0 += r1;                               ;2,1
        lodr,r2 *$0099       ;r2 = *(*($0099)); // ROM opcode         ;3,2
                             ;or, r2 = GAME; // RAM
        adda,r0 $0194,r2     ;r0 += *($0194 + r2);                    ;4,3
        strz    r2           ;r2 = r0;                                ;2,1
        loda,r0 $0440,r1     ;r0 = *($0440 + r1);                     ;4,3
        strz    r3           ;r3 = r0;                                ;2,1
        loda,r0 $0444,r2     ;r0 = *($0444 + r2);                     ;4,3
        stra,r0 $1F00,r3     ;*($1F00 + r3) = r0;                     ;4,3
        loda,r0 $0444,r2+    ;r0 = *($0444 + ++r2);                   ;4,3
        stra,r0 $1F02,r3     ;*($1F02 + r3) = r0;                     ;4,3
        lodi,r0 $FE          ;r0 = $FE;                               ;2,2
        stra,r0 $1F03,r3     ;*($1F03 + r3) = r0 [$FE];               ;4,3
        comi,r1 $03          ;compare r1 against $03;                 ;2,2
        bctr,lt TITLESCREEN_10;if < goto TITLESCREEN_10;              ;3,2
        lodr,r0 *$00C0       ;r0 = *(*($00C0)); // ROM operand        ;3,2
                             ;or, r0 = OPTION; // motherboard RAM
        rrr,r0               ;r0 >>= 1;                               ;2,1
        bctr,lt TITLESCREEN_11;if < goto TITLESCREEN_11;              ;3,2
TITLESCREEN_10:                                                       ;$8B
        loda,r0 $0444,r2+    ;r0 = *($0444 + ++r2);                   ;4,3
        strz    r2           ;r2 = r0;                                ;2,1
        bsta,un L0294        ;gosub L0294;                            ;3,3
TITLESCREEN_11:                                                       ;$92
        lodr,r1 *$0062       ;r1 = *(*($0062)); // ROM                ;3,2
                             ;or, r1 = CLEARBITS; // motherboard RAM
        subi,r1 $01          ;r1--;                                   ;2,2
        bcfr,lt TITLESCREEN_9;if >= goto TITLESCREEN_9;               ;3,2

;BGCOLOUR     = *( $46C +  GAME     );
;SIZES        = *(($471 + (GAME * 4));
;SPR01COLOURS = *(($472 + (GAME * 4));
;SPR23COLOURS = *(($473 + (GAME * 4));
;SCORECTRL    = *(($474 + (GAME * 4));
        loda,r2 GAME         ;r2 = GAME; // motherboard RAM           ;4,3
        loda,r0 $046C,r2     ;r0 = *($046C + r2);                     ;4,3
        stra,r0 BGCOLOUR     ;BGCOLOUR = r0; // hardware registers    ;4,3
        rrl,r2               ;r2 <<= 1;                               ;2,1
        rrl,r2               ;r2 <<= 1;                               ;2,1
        lodi,r3 $FC          ;r3 = $FC;                               ;2,2
TITLESCREEN_12:                                                       ;$A5
        loda,r0 $0470,r2+    ;r0 = *($0470 + ++r2);                   ;4,3

;this is the instruction that sets SPR23COLOURS to %00,110,101
;(sprite #2 = blue, sprite #3 = green)
        stra,r0 $1EC4,r3     ;*($1EC4 + r3) = r0;                     ;4,3

        birr,r3 TITLESCREEN_12;if (++r3 != 0) goto TITLESCREEN_12;    ;3,2

        lodr,r2 *$0099       ;r2 = *(*($0099)); // ROM operands       ;3,2
                             ;or, r2 = GAME; // motherboard RAM
        comi,r2 $01          ;compare r2 against $01;                 ;2,2
        bctr,gt TITLESCREEN_16;if > goto TITLESCREEN_16;              ;3,2
        brnr,r2 TITLESCREEN_14;if (r2 != 0) goto TITLESCREEN_14;      ;3,2
        lodi,r3 $08          ;r3 = $08;                               ;2,2
TITLESCREEN_13:                                                       ;$B7
        loda,r0 $0198,r3     ;r0 = *($0198 + r3);                     ;4,3
        stra,r0 P2DISTANCE_L,r3;*(&P2DISTANCE_L + r3) = r0;           ;4,3
        bdrr,r3 TITLESCREEN_13;if (--r3 != 0) goto TITLESCREEN_13;    ;3,2
        loda,r0 OPTION       ;r0 = OPTION; // motherboard RAM         ;4,3
        bctr,eq TITLESCREEN_16;if == goto TITLESCREEN_16;             ;3,2
        lodi,r0 $55          ;r0 = $55;                               ;2,2
        stra,r0 SPRITE2AX    ;SPRITE2AX = r0; // hardware registers   ;4,3
        bctr,un TITLESCREEN_16;goto TITLESCREEN_16;                   ;3,2
;
TITLESCREEN_14:                                                       ;$CB
        lodi,r0 $09          ;r0 = $09;                               ;2,2
        stra,r0 SPRITE0BY    ;SPRITE0BY = r0; // hardware registers   ;4,3
        stra,r0 SPRITE1BY    ;SPRITE1BY = r0; // hardware registers   ;4,3
        lodi,r3 $0E          ;r3 = $0E;                               ;2,2
        lodi,r0 $60          ;r0 = $60;                               ;2,2
TITLESCREEN_15:                                                       ;$D7
        stra,r0 $1F7F,r3     ;*($1F7F + r3) = r0;                     ;4,3
        bdrr,r3 TITLESCREEN_15;if (--r3 != 0) goto TITLESCREEN_15;    ;3,2
        lodi,r0 $0A          ;r0 = $0A;                               ;2,2
        stra,r0 RIGHTPURPLEX ;RIGHTPURPLEX = r0 [10]; // mobo RAM     ;4,3
TITLESCREEN_16:                                                       ;$E1
        loda,r0 INVERTCOLOURS;r0 = INVERTCOLOURS; // motherboard RAM  ;4,3
        tmi,r0  $10          ;test bits %00010000 of r0;              ;3,2
        bctr,eq TITLESCREEN_17;if == goto TITLESCREEN_17;             ;3,2
        eorz    r0           ;r0 = 0;                                 ;2,1
        stra,r0 SCORECTRL    ;SCORECTRL = r0; // hardware registers   ;4,3
        lodi,r0 $FF          ;r0 = $FF;                               ;2,2
        stra,r0 SCORELT      ;SCORELT = r0 ['  ']; // hardware regs   ;4,3
        lodr,r0 *$00C0       ;r0 = *(*($00C0)); // ROM                ;3,2
                             ;or, r0 = OPTION; // motherboard RAM
        addi,r0 $67          ;r0 += $67;                              ;2,2
        dar,r0               ;r0 = BCD(r0);                           ;3,1
        stra,r0 SCORERT      ;SCORERT = r0; // hardware registers     ;4,3
TITLESCREEN_17:                                                       ;$F9
        lodi,r0 $E2          ;r0 = $E2;                               ;2,2
        stra,r0 P1COLLIDE    ;P1COLLIDE = r0 [$E2]; // motherboard RAM;4,3
        cpsu    $20          ;PSU &= %11011111; // enable interrupts  ;3,2
TITLESCREEN_18:                                                      ;$100

;while (P1COLLIDE & %10000000); // only an interrupt can save us
;BGCOLCOPY = SPRCOLCOPY = P1COLLIDE;
        lodr,r0 *$00FC       ;r0 = *(*($00FC)); // ROM operand        ;3,2
                             ;or, r0 = P1COLLIDE; // motherboard RAM
        bctr,lt TITLESCREEN_18;if < goto TITLESCREEN_18;              ;3,2
        stra,r0 BGCOLCOPY    ;BGCOLCOPY = r0; // motherboard RAM      ;4,3
        stra,r0 SPRCOLCOPY   ;SPRCOLCOPY = r0; // motherboard RAM     ;4,3

TITLESCREEN_19:                                                      ;$10A
;wait for start of game
;while (!(INVERTCOLOURS & %00010000)); // only an interrupt can save us
        loda,r1 INVERTCOLOURS;r1 = INVERTCOLOURS; // motherboard RAM  ;4,3
        tmi,r1  $10          ;test bits %00010000 of r1;              ;3,2
        bctr,lt TITLESCREEN_19;if < goto TITLESCREEN_19;              ;3,2

;*($1F5F) += 49;
        loda,r0 $1F5F        ;r0 = *($1F5F); // motherboard RAM       ;4,3
        addi,r0 $31          ;r0 += $31;                              ;2,2
        strr,r0 *$0112       ;*(*($0112)) = r0; // ROM                ;3,2
                             ;or, *($1F5F) = r0;

        lodi,r0 $08          ;r0 = $08;                               ;2,2
        lodi,r1 $00          ;r1 = $00;                               ;2,2
        bstr,un HANDLESPRITE ;gosub HANDLESPRITE(%00001000, 0);       ;3,2
        lodi,r0 $04          ;r0 = $04;                               ;2,2
        lodi,r1 $01          ;r1 = $01;                               ;2,2
        bstr,un HANDLESPRITE ;gosub HANDLESPRITE(%00000100, 1);       ;3,2
        lodi,r0 $02          ;r0 = $02;                               ;2,2
        strz    r1           ;r1 = r0 [2];                            ;2,1
        bstr,un HANDLESPRITE ;gosub HANDLESPRITE(%00000010, 2);       ;3,2
        loda,r0 OPTION       ;r0 = OPTION; // motherboard RAM         ;4,3
        rrr,r0               ;r0 >>= 1;                               ;2,1
        bctr,lt TITLESCREEN_19;if < goto TITLESCREEN_19;              ;3,2
        lodi,r0 $01          ;r0 = $01;                               ;2,2
        lodi,r1 $03          ;r1 = $03;                               ;2,2
        bstr,un HANDLESPRITE ;gosub HANDLESPRITE(%00000001, 3);       ;3,2
        bctr,un TITLESCREEN_19;goto TITLESCREEN_19;                   ;3,2
;Mainline Subroutine HANDLESPRITE-----------------------------------------
HANDLESPRITE:                                                        ;$137

;r0 and r1 are arguments to this subroutine.
;r0 is which bit of BGCOLCOPY to clear.
; it is %00001000 for sprite #0 display complete
; it is %00000100 for sprite #1 display complete
; it is %00000010 for sprite #2 display complete
; it is %00000001 for sprite #3 display complete
;r1 is which sprite we are interested in (0..3).

;CLEARBITS = r0;
;if ((BGCOLCOPY & CLEARBITS) == 0) // nothing to clear
;{   return;
;} else // something to clear
;{   BGCOLCOPY &= (CLEARBITS ^ %11111111);
;}
        bsta,un CLEARBGBITS  ;gosub CLEARBGBITS;                      ;3,3
        retc,eq              ;if == return;                           ;3,1

;r0 = r3 = *($440 + r1); // ROM data (sprite data offsets)
;*($1F5B) = r1;
;if (r1 >= 2) // player 1 or 2
;{   r1 -= 2;
;    *($1F5B) = r1;
;    gosub CHECKCOLLIDE;
;    CLEARBITS = r0;
;    if (r0 != 0)
;    {   *($1F54 + r1) = 0;
;        PnVAR         =
;        r0            = 15;
;}   }
        loda,r0 $0440,r1     ;r0 = *($0440 + r1);                     ;4,3
        strz    r3           ;r3 = r0;                                ;2,1
        stra,r1 $1F5B        ;*($1F5B) = r1; // motherboard RAM       ;4,3
        comi,r1 $02          ;compare r1 against $02;                 ;2,2
        bcta,lt L048F        ;if < goto L048F;                        ;3,3
        subi,r1 $02          ;r1 -= $02;                              ;2,2
        strr,r1 *$0140       ;*(*($0140)) = r1; // ROM                ;3,2
                             ;or, *($1F5B) = r1; // motherboard RAM
        bsta,un CHECKCOLLIDE ;gosub CHECKCOLLIDE;                     ;3,3
        stra,r0 CLEARBITS    ;CLEARBITS = r0; // motherboard RAM      ;4,3
        bctr,eq HANDLESPRITE_1;if == goto HANDLESPRITE_1;             ;3,2
        eorz    r0           ;r0 = 0;                                 ;2,1
        stra,r0 $1F54,r1     ;*($1F54 + r1) = r0;                     ;4,3
        lodi,r0 $0F          ;r0 = $0F;                               ;2,2
        stra,r0 P1VAR,r1     ;*(&P1VAR + r1) = r0;                    ;4,3

HANDLESPRITE_1:                                                      ;$15C
;if (GAME >= 2) // slalom
;{   goto SLALOM;
;} // implied else
;if (Flag)
;{   goto HANDLESPRITE_2;
;} // implied else
;r2 = PnDISTANCE_L;
;PnDISTANCE_L += *(1F54 + r1);
;if (PnDISTANCE_L >= r2)
;{   goto HANDLESPRITE_2;
;} // implied else
;PnDISTANCE_H = BCD(PnDISTANCE_H + 1);
;if ((OPTION >> 1) >= 1 && (OPTION >> 1) <= 127) // ie. OPTION of 2/4/6/8
;{   SCORERT = PnDISTANCE_H;
;}
        loda,r2 GAME         ;r2 = GAME; // motherboard RAM           ;4,3
        comi,r2 $01          ;compare r2 against $01;                 ;2,2
        bcta,gt SLALOM       ;if > goto SLALOM;                       ;3,3
        tpsu    $40          ;test bit .F...... of PSU;               ;3,2
        bctr,eq HANDLESPRITE_2;if == goto HANDLESPRITE_2;             ;3,2
        loda,r0 P1DISTANCE_L,r1;r0 = *(&P1DISTANCE_L + r1);           ;4,3
        strz    r2           ;r2 = r0;                                ;2,1
        adda,r0 $1F54,r1     ;r0 += *($1F54 + r1);                    ;4,3
        stra,r0 P1DISTANCE_L,r1;*(&P1DISTANCE_L + r1) = r0;           ;4,3
        comz    r2           ;compare r0 against r2;                  ;2,1
        bcfr,lt HANDLESPRITE_2;if >= goto HANDLESPRITE_2;             ;3,2
        loda,r0 P1DISTANCE_H,r1;r0 = *(&P1DISTANCE_H + r1);           ;4,3
        addi,r0 $67          ;r0 += $67;                              ;2,2
        dar,r0               ;r0 = BCD(r0);                           ;3,1
        stra,r0 P1DISTANCE_H,r1;*(&P1DISTANCE_H + r1) = r0;           ;4,3
        loda,r2 OPTION       ;r2 = OPTION; // motherboard RAM         ;4,3
        rrr,r2               ;r2 >>= 1;                               ;2,1
        bcfr,lt HANDLESPRITE_2;if >= goto HANDLESPRITE_2;             ;3,2
        stra,r0 SCORERT      ;SCORERT = r0; // hardware registers     ;4,3

HANDLESPRITE_2:                                                      ;$187
;if (GAME == 0) // grand prix
;{   goto CHECKBOUNDS;
;} else
;{   goto L0341;
;}
        lodr,r0 *$015D       ;r0 = *(*($015D)); // ROM                ;3,2
                             ;or, r0 = GAME; // motherboard RAM
        brna,r0 L0341        ;if (r0 != 0) goto L0341;                ;3,3
        bcta,un CHECKBOUNDS  ;goto CHECKBOUNDS;                       ;3,3
;Data for Code Section TITLESCREEN----------------------------------------
X018F:
;offsets into ROM data tables
        db      $FF ;grand prix
        db      $00 ;rally
        db      $2D ;easy slalom
        db      $5A ;med. slalom
        db      $87 ;hard slalom

X0194:
;offsets into ROM data tables
        db      $00 ;grand prix
        db      $0C ;rally
        db      $18 ;easy slalom
        db      $18 ;med. slalom
X0198:
        db      $18 ;hard slalom

        db      $32, $B7, $32
        db      $AD, $B2, $2D, $B2
        db      $37

;With regard to TITLESCREEN:
;grand prix sprite #0: r2 =  0;
;grand prix sprite #1: r2 =  3;
;grand prix sprite #2: r2 =  6;
;grand prix sprite #3: r2 =  9;
;rally      sprite #0: r2 = 12;
;rally      sprite #1: r2 = 15;
;rally      sprite #2: r2 = 18;
;rally      sprite #3: r2 = 21;
;slalom     sprite #0: r2 = 24;
;slalom     sprite #1: r2 = 27;
;slalom     sprite #2: r2 = 30;
;slalon     sprite #3: r2 = 33;

;Code Section SLALOM------------------------------------------------------
SLALOM:                                                              ;$1A1

;if (CLEARBITS != 0)
;{   *($1F00 + r3) = PnDISTANCE_H;
;    *($1F02 + r3) = PnDISTANCE_L;
;} else
;{   PnDISTANCE_H  = *($1F00 + r3);
;    PnDISTANCE_L  = *($1F02 + r3);
;}
        loda,r0 CLEARBITS    ;r0 = CLEARBITS; // motherboard RAM      ;4,3
        bctr,eq SLALOM_1     ;if == goto SLALOM_1;                    ;3,2
        loda,r0 P1DISTANCE_H,r1;r0 = *(&P1DISTANCE_H + r1);           ;4,3
        stra,r0 $1F00,r3     ;*($1F00 + r3) = r0;                     ;4,3
        loda,r0 P1DISTANCE_L,r1;r0 = *(&P1DISTANCE_L + r1);           ;4,3
        stra,r0 $1F02,r3     ;*($1F02 + r3) = r0;                     ;4,3
        bctr,un SLALOM_2     ;goto SLALOM_2;                          ;3,2
SLALOM_1:                                                            ;$1B4
        loda,r0 $1F00,r3     ;r0 = *($1F00 + r3);                     ;4,3
        stra,r0 P1DISTANCE_H,r1;*(&P1DISTANCE_H + r1) = r0;           ;4,3
        loda,r0 $1F02,r3     ;r0 = *($1F02 + r3);                     ;4,3
        stra,r0 P1DISTANCE_L,r1;*(&P1DISTANCE_L + r1) = r0;           ;4,3

SLALOM_2:                                                            ;$1C0
        loda,r0 $1F66,r1     ;r0 = *($1F66 + r1);                     ;4,3
        bctr,eq SLALOM_3     ;if == goto SLALOM_3;                    ;3,2
        subi,r0 $01          ;r0--;                                   ;2,2
        stra,r0 $1F66,r1     ;*($1F66 + r1) = r0;                     ;4,3
        bctr,un SLALOM_7     ;goto SLALOM_7;                          ;3,2
SLALOM_3:                                                            ;$1CC
        loda,r0 $1F54,r1     ;r0 = *($1F54 + r1);                     ;4,3
        bctr,gt SLALOM_4     ;if > goto SLALOM_4;                     ;3,2
        lodr,r2 *$01A2       ;r2 = *(*($01A2)); // ROM operand        ;3,2
                             ;r2 = CLEARBITS; // motherboard RAM
        bctr,eq SLALOM_7     ;if == goto SLALOM_7;                    ;3,2
SLALOM_4:                                                            ;$1D5
        lodi,r0 $1A          ;r0 = $1A;                               ;2,2
        stra,r0 $1F66,r1     ;*($1F66 + r1) = r0;                     ;4,3
        loda,r0 PLAYER1X,r1  ;r0 = *($1F52 + r1);                     ;4,3
        comi,r0 $30          ;compare r0 against $30;                 ;2,2
        bctr,lt SLALOM_5     ;if < goto SLALOM_5;                     ;3,2
        comi,r0 $96          ;compare r0 against $96;                 ;2,2
        bctr,lt SLALOM_7     ;if < goto SLALOM_7;                     ;3,2
        lodi,r0 $01          ;r0 = $01;                               ;2,2
        bctr,un SLALOM_6     ;goto SLALOM_6;                          ;3,2
SLALOM_5:                                                            ;$1E9
        lodi,r0 $FF          ;r0 = $FF;                               ;2,2
SLALOM_6:                                                            ;$1EB
        adda,r0 $1F6C,r1     ;r0 += *($1F6C + r1);                    ;4,3
        andi,r0 $07          ;r0 &= %00000111;                        ;2,2
        stra,r0 $1F6C,r1     ;*($1F6C + r1) = r0;                     ;4,3
        loda,r0 $026C,r0     ;r0 = *($026C + r0);                     ;4,3
        strz    r2           ;r2 = r0;                                ;2,1
        addi,r1 $02          ;r1 += $02;                              ;2,2
        bsta,un L0294        ;gosub L0294;                            ;3,3
        loda,r1 $1F5B        ;r1 = *($1F5B); // motherboard RAM       ;4,3
SLALOM_7:                                                            ;$1FF
        loda,r0 $0442,r1     ;r0 = *($0442 + r1);                     ;4,3
        strz    r3           ;r3 = r0;                                ;2,1
        loda,r0 $1F68,r1     ;r0 = *($1F68 + r1);                     ;4,3
        bctr,eq SLALOM_11    ;if == goto SLALOM_11;                   ;3,2
        strz    r2           ;r2 = r0;                                ;2,1
        andi,r0 $F0          ;r0 &= %11110000;                        ;2,2
        bctr,eq SLALOM_8     ;if == goto SLALOM_8;                    ;3,2
        lodz    r2           ;r0 = r2;                                ;2,1
        subi,r0 $10          ;r0 -= $10;                              ;2,2
        bctr,un SLALOM_12    ;goto SLALOM_12;                         ;3,2
SLALOM_8:                                                            ;$212
        loda,r0 $1F6C,r1     ;r0 = *($1F6C + r1);                     ;4,3
        comi,r0 $07          ;compare r0 against $07;                 ;2,2
        bctr,eq SLALOM_9     ;if == goto SLALOM_9;                    ;3,2
        comi,r0 $01          ;compare r0 against $01;                 ;2,2
        bctr,gt SLALOM_10    ;if > goto SLALOM_10;                    ;3,2
SLALOM_9:                                                            ;$21D
        eori,r2 $FF          ;r2 ^= %11111111;                        ;2,2
        addi,r2 $01          ;r2++;                                   ;2,2
SLALOM_10:                                                           ;$221
        loda,r0 $1F00,r3     ;r0 = *($1F00 + r3);                     ;4,3
        addz    r2           ;r0 += r2;                               ;2,1
        stra,r0 $1F00,r3     ;*($1F00 + r3) = r0;                     ;4,3
SLALOM_11:                                                           ;$228
        loda,r0 $1F6C,r1     ;r0 = *($1F6C + r1);                     ;4,3
        loda,r0 $0274,r0     ;r0 = *($0274 + r0);                     ;4,3
        bctr,eq SLALOM_12    ;if == goto SLALOM_12;                   ;3,2
        adda,r0 $1F54,r1     ;r0 += *($1F54 + r1);                    ;4,3
        loda,r0 $0283,r0     ;r0 = *($0283 + r0);                     ;4,3
SLALOM_12:                                                           ;$236
        stra,r0 $1F68,r1     ;*($1F68 + r1) = r0;                     ;4,3
        loda,r0 $1F6A,r1     ;r0 = *($1F6A + r1);                     ;4,3
        bctr,eq SLALOM_15    ;if == goto SLALOM_15;                   ;3,2
        strz    r2           ;r2 = r0;                                ;2,1
        andi,r0 $F0          ;r0 &= %11110000;                        ;2,2
        bctr,eq SLALOM_13    ;if == goto SLALOM_13;                   ;3,2
        lodz    r2           ;r0 = r2;                                ;2,1
        subi,r0 $10          ;r0 -= $10;                              ;2,2
        bctr,un SLALOM_16    ;goto SLALOM_16;                         ;3,2
SLALOM_13:                                                           ;$248
        loda,r0 $1F6C,r1     ;r0 = *($1F6C + r1);                     ;4,3
        comi,r0 $04          ;compare r0 against $04;                 ;2,2
        bctr,gt SLALOM_14    ;if > goto SLALOM_14;                    ;3,2
        eori,r2 $FF          ;r2 ^= %11111111;                        ;2,2
        addi,r2 $01          ;r2++;                                   ;2,2
SLALOM_14:                                                           ;$253
        loda,r0 $1F02,r3     ;r0 = *($1F02 + r3);                     ;4,3
        addz    r2           ;r0 += r2;                               ;2,1
        stra,r0 $1F02,r3     ;*($1F02 + r3) = r0;                     ;4,3
SLALOM_15:                                                           ;$25A
        loda,r0 $1F6C,r1     ;r0 = *($1F6C + r1);                     ;4,3
        loda,r0 $027C,r0     ;r0 = *($027C + r0);                     ;4,3
        bctr,eq SLALOM_16    ;if == goto SLALOM_16;                   ;3,2
        adda,r0 $1F54,r1     ;r0 += *($1F54 + r1);                    ;4,3
        loda,r0 $0283,r0     ;r0 = *($0283 + r0);                     ;4,3
SLALOM_16:                                                           ;$268
        stra,r0 $1F6A,r1     ;*($1F6A + r1) = r0;                     ;4,3
        retc,un              ;return;                                 ;3,1
;Data for Code Section SLALOM---------------------------------------------
X026C:
        db      $1E, $28, $32, $3C
        db      $46, $BC, $B2, $A8
X0274:
        db      $01, $09, $00, $09
        db      $01, $09, $00, $09
X027C:
        db      $00, $0D, $05, $0D
        db      $00, $0D, $05
X0283:
        db      $0D, $00, $51, $31
        db      $11, $00, $21, $11
        db      $01, $00, $71, $51
        db      $31, $00, $31, $21
        db      $11
;Subroutine L0294---------------------------------------------------------
L0294:

;This entire subroutine is:
;r1 = r0 = *($440 + r1);
;if (r2 & $80) // if high bit is set
;{   r2 &= $7F; // clear high bit
;    for (r3 = 10; r3 >= 1; r3--)
;    {   r2++;
;        r1--;
;        *($1F00 + r1) = *($3DB + r2);
;}   }
;else
;{   for (r3 = 10; r3 >= 1; r3--)
;    {   r2--;
;        r1--;
;        *($1F00 + r1) = *($3E6 + r2);
;    }
;}
;return;
        loda,r0 $0440,r1     ;r0 = *($0440 + r1);                     ;4,3
        strz    r1           ;r1 = r0;                                ;2,1
        lodi,r3 $0A          ;r3 = $0A;                               ;2,2
        tmi,r2  $80          ;test bits %10000000 of r2;              ;3,2
        bctr,eq L02A7        ;if == goto L02A7;                       ;3,2
L029E:
        loda,r0 $03E6,r2-    ;r0 = *($03E6 + --r2);                   ;4,3
        stra,r0 $1F00,r1-    ;*($1F00 + --r1) = r0;                   ;4,3
        bdrr,r3 L029E        ;if (--r3 != 0) goto L029E;              ;3,2
        retc,un              ;return;                                 ;3,1
L02A7:
        andi,r2 $7F          ;r2 &= %01111111;                        ;2,2
L02A9:
        loda,r0 $03DB,r2+    ;r0 = *($03DB + ++r2);                   ;4,3
        stra,r0 $1F00,r1-    ;*($1F00 + --r1) = r0;                   ;4,3
        bdrr,r3 L02A9        ;if (--r3 != 0) goto L02A9;              ;3,2
        retc,un              ;return;                                 ;3,1
;End of Subroutine L0294--------------------------------------------------
;Mainline Subroutine CLEARBGBITS------------------------------------------
CLEARBGBITS:                                                         ;$2B2
;called from HANDLESPRITE or $2DB
        lodi,r2 $00          ;r2 = $00;                               ;2,2
        bctr,un L02B8        ;goto L02B8;                             ;3,2

CLEARSPRBITS:                                                        ;$2B6
;alternate external entry point (from $2E8)
        lodi,r2 $01          ;r2 = $01;                               ;2,2

L02B8:

;r2 is an argument, it is always 0 or 1 here
;r0 is an argument, and is also the return code

;NEW:
        nop                  ;;                                       ;2,1
        nop                  ;;                                       ;2,1
;OLD:
;       ppsu    $20          ;PSU |= ..I.....; // inhibit interrupts  ;3,2

;this is the only time, except during bootstrap (and of course during
;interrupt code), when interrupts are inhibited.

        stra,r0 CLEARBITS    ;CLEARBITS = r0; // motherboard RAM      ;4,3
        anda,r0 $1F4E,r2     ;r0 &= *($1F4E + r2);                    ;4,3

;This is mainline code. rete,eq is used in the interests of efficiency.
        rete,eq              ;if == then { PSU &= ~PSU_II; return; }  ;3,1

;*($1F4E + r2) &= (CLEARBITS ^ %11111111);
        lodr,r0 *$02BB       ;r0 = *(*($02BB)); // ROM operand        ;3,2
                             ;r0 = CLEARBITS; // motherboard RAM
        eori,r0 $FF          ;r0 ^= %11111111;                        ;2,2
        anda,r0 $1F4E,r2     ;r0 &= *($1F4E + r2);                    ;4,3
        stra,r0 $1F4E,r2     ;*($1F4E + r2) = r0;                     ;4,3

;This is mainline code. rete,eq is used in the interests of efficiency.
        lodi,r0 $01          ;r0 = $01;                               ;2,2
        rete,un              ;PSU &= ~PSU_II; return;                 ;3,1
;End of Mainline Subroutine-----------------------------------------------
;Mainline Subroutine CHECKCOLLIDE-----------------------------------------
CHECKCOLLIDE:                                                        ;$2CE
;r0 is the return code
;r1 will be 0 or 1 here (for which player)

;if (PnCOLLIDE != 0) // PnCOLLIDE
;{   PnCOLLIDE--;
;}
;if this player's car (sprite #2/#3) has collided with the background
;{   clear the relevant bit in BGCOLCOPY
;} else
;{   for p1: CLEARBITS = *($31A + OPTION     );
;    for p2: CLEARBITS = *($31A + OPTION + 10);
;    if ((SPRCOLCOPY & CLEARBITS) == 0) // nothing to clear
;    {   return;
;    } // implied else // something to clear
;    SPRCOLCOPY &= (CLEARBITS ^ %11111111);
;    if (GAME == slalom)
;    {   SOUNDVAR = PnCOLLIDE = 50;
;        return;
;}   }
;if (PnCOLLIDE >= 1 && PnCOLLIDE <= 127)
;{   return;
;} // implied else
;PnCRASHES = BCD(PnCRASHES + 1);
;SCORELT/SCORERT = BCD(PnCRASHES);
;if (SCORELT/SCORERT >= $99)
;{   MONOTONIC = $0204;
;}
;SOUNDVAR = PnCOLLIDE = 50;
;return;
        loda,r0 P1COLLIDE,r1 ;r0 = *(&P1COLLIDE + r1);                ;4,3
        bctr,eq L02D8        ;if == goto L02D8;                       ;3,2
        subi,r0 $01          ;r0--;                                   ;2,2
        stra,r0 P1COLLIDE,r1 ;*(&P1COLLIDE + r1) = r0;                ;4,3
L02D8:
        loda,r0 $0318,r1     ;r0 = *($0318 + r1); // $20/$10          ;4,3
        bstr,un CLEARBGBITS  ;gosub CLEARBGBITS;                      ;3,2
;To enable the trainer, you should change this from bctr,gt to bctr,un
        bctr,gt L02F2        ;if > goto L02F2;                        ;3,2
        loda,r0 OPTION       ;r0 = OPTION; // motherboard RAM         ;4,3
        adda,r0 $032D,r1     ;r0 += *($032D + r1); // 0 or 10         ;4,3
        loda,r0 $031A,r0     ;r0 = *($031A + r0);                     ;4,3
        bstr,un CLEARSPRBITS ;gosub CLEARSPRBITS;                     ;3,2
        retc,eq              ;if == return;                           ;3,1
                             ;or, if (r0 == 0) return;
        loda,r0 GAME         ;r0 = GAME; // motherboard RAM           ;4,3
        comi,r0 $01          ;compare r0 against $01;                 ;2,2
        bctr,gt L030F        ;if > goto L030F;                        ;3,2
L02F2:
        loda,r0 P1COLLIDE,r1 ;r0 = *(&P1COLLIDE + r1); // PnCOLLIDE   ;4,3
        retc,gt              ;if > return;                            ;3,1
        loda,r0 $1F5C,r1     ;r0 = *($1F5C + r1); // PnCRASHES        ;4,3
        addi,r0 $67          ;r0 += $67;                              ;2,2
        dar,r0               ;r0 = BCD(r0);                           ;3,1
        stra,r0 $1F5C,r1     ;*($1F5C + r1) = r0;                     ;4,3
        stra,r0 $1FC8,r1     ;SCORELT/SCORERT = r0; // hardware regs  ;4,3
        comi,r0 $99          ;compare r0 against $99;                 ;2,2
        bctr,lt L030F        ;if < goto L030F;                        ;3,2
        lodi,r0 $02          ;r0 = $02;                               ;2,2
        stra,r0 MONOTONIC_H  ;MONOTONIC_H = r0 [2]; // motherboard RAM;4,3
        rrl,r0               ;r0 <<= 1;                               ;2,1
        stra,r0 MONOTONIC_L  ;MONOTONIC_L = r0 [4]; // motherboard RAM;4,3
L030F:
        lodi,r0 $32          ;r0 = $32;                               ;2,2
        stra,r0 SOUNDVAR     ;SOUNDVAR = r0 [50]; // motherboard RAM  ;4,3
        stra,r0 P1COLLIDE,r1 ;*(&P1COLLIDE + r1) = r0 [50];           ;4,3
        retc,un              ;return;                                 ;3,1
;Data for Mainline Subroutine CHECKCOLLIDE--------------------------------
X0318:
        db      $20          ;p1 sprite-background collision bit (%00100000)
        db      $10          ;p2 sprite-background collision bit (%00010000)

X031A:
;This table shows the sprite-sprite vulnerabilities.
; Option "01" (2-player grand prix):
;  p1: your car (#2) is vulnerable to left  enemy cars (#0).
;  p2: your car (#3) is vulnerable to right enemy cars (#1).
; Option "02" (1-player grand prix):
;  p1: your car (#2) is vulnerable to left  (#0) and right (#1) enemy cars.
; Option "03" (2-player rally):
;  p1: your car (#2) is vulnerable to sprites #0 and #1.
;  p2: your car (#3) is vulnerable to sprites #0 and #1.
; Option "04" (1-player rally):
;  p1: your car (#2) is vulnerable to sprites #0 and #1.
; Options "05", "07", "09" (2-player slaloms):
;  ?
; Options "06", "08", "10" (1-player slaloms):
;  ?
        db      $10          ;option "01", p1 (0,0,010000) #0/#2
        db      $14          ;option "02", p1 (0,0,010100) #0/#2 & #1/#2
        db      $14          ;option "03", p1 (0,0,010100) #0/#2 & #1/#2
        db      $14          ;option "04", p1 (0,0,010100) #0/#2 & #1/#2
        db      $01          ;option "05", p1 (0,0,000001) #2/#3
        db      $00          ;option "06", p1
        db      $01          ;option "07", p1 (0,0,000001) #2/#3
        db      $00          ;option "08", p1
        db      $01          ;option "09", p1 (0,0,000001) #2/#3
        db      $00          ;option "10", p1
        db      $02          ;option "01", p2 (0,0,000010) #1/#3
        db      $00          ;option "02", p2 (impossible)
        db      $0A          ;option "03", p2 (0,0,001010) #0/#3 & #1/#3
        db      $00          ;option "04", p2 (impossible)
        db      $20          ;option "05", p2 (0,0,100000) #0/#1
        db      $00          ;option "06", p2 (impossible)
        db      $20          ;option "07", p2 (0,0,100000) #0/#1
        db      $00          ;option "08", p2 (impossible)
        db      $20          ;option "09", p2 (0,0,100000) #0/#1
X032D:
        db      $00          ;option "10", p2 (impossible). player 1 table offset
        db      $0A          ;player 2 table offset
;End of Data for Mainline Subroutine CHECKCOLLIDE-------------------------
;Subroutine L032F---------------------------------------------------------
L032F:

;if   (SPRITE0AY < 7)  r2/r5 =  r0 * 3     ;
;elif (SPRITE0AY < 14) r2/r5 = (r0 * 3) + 1;
;else                  r2/r5 = (r0 * 3) + 2;
;return;
        strz    r2           ;r2/r5 = r0;                             ;2,1
        rrl,r0               ;r0 <<= 1;                               ;2,1
        addz    r2           ;r0 += r2/r5;                            ;2,1
        strz    r2           ;r2/r5 = r0;                             ;2,1
        loda,r0 SPRITE0AY    ;r0 = SPRITE0AY; // hardware registers   ;4,3
        comi,r0 $07          ;compare r0 against $07;                 ;2,2
        retc,lt              ;if < return;                            ;3,1
        addi,r2 $01          ;r2/r5++;                                ;2,2
        comi,r0 $0E          ;compare r0 against $0E;                 ;2,2
        retc,lt              ;if < return;                            ;3,1
        addi,r2 $01          ;r2/r5++;                                ;2,2
        retc,un              ;return;                                 ;3,1
;End of Subroutine L032F--------------------------------------------------
;SubEnd L0341-------------------------------------------------------------
L0341:
;draw slalom?
        lodi,r0 $0B          ;r0 = $0B;                               ;2,2
        bsta,un L032F        ;gosub L032F;                            ;3,3
        loda,r0 $1F8B        ;r0 = *($1F8B); // vertical grid         ;4,3
        subz    r2           ;r0 -= r2;                               ;2,1
        coma,r0 PLAYER1X,r1  ;compare r0 against *($1F52 + r1);       ;4,3
        bctr,gt L035B        ;if > goto L035B;                        ;3,2
        addz    r2           ;r0 += r2;                               ;2,1
        addz    r2           ;r0 += r2;                               ;2,1
        subi,r0 $07          ;r0 -= $07;                              ;2,2
        coma,r0 PLAYER1X,r1  ;compare r0 against *($1F52 + r1);       ;4,3
        bctr,lt L035B        ;if < goto L035B;                        ;3,2
        loda,r0 PLAYER1X,r1  ;r0 = *($1F52 + r1);                     ;4,3
L035B:
        stra,r0 $1F00,r3     ;*($1F00 + r3) = r0;                     ;4,3
        retc,un              ;return;                                 ;3,1
;End of SubEnd L0341------------------------------------------------------
;Data for Code Section TITLESCREEN----------------------------------------
X035F:
;easy slalom vertical grid
        db      $FF, $FE, $80, $01
        db      $80, $01, $80, $01
        db      $3F, $F8, $A0, $01
        db      $A0, $01, $A0, $01
        db      $0F, $FE, $A8, $41
        db      $A8, $41, $A9, $41
        db      $00, $18, $A1, $15
        db      $3F, $F8, $80, $01
        db      $80, $01, $80, $01
        db      $FF, $FE, $00, $00
;easy slalom horizontal grid
        db      $41, $41, $41, $49
        db      $48
;medium slalom vertical grid
        db      $FF, $FE, $88
        db      $81, $88, $81, $88
        db      $81, $00, $38, $AA
        db      $91, $AA, $91, $AA
        db      $91, $00, $06, $AA
        db      $91, $00, $C0, $A2
        db      $11, $00, $18, $A2
        db      $15, $3F, $F8, $80
        db      $01, $80, $01, $80
        db      $01, $FF, $FE, $00
        db      $00
;medium slalom horizontal grid
        db      $41, $41, $49
        db      $49, $48
;hard slalom vertical grid
        db      $FF, $FE
        db      $84, $11, $84, $11
        db      $A4, $91, $A0, $85
        db      $A0, $85, $3F, $F8
        db      $A0, $85, $00, $81
        db      $82, $A1, $FC, $3E
        db      $80, $81, $3F, $18
        db      $A0, $95, $00, $F8
        db      $A4, $01, $84, $01
X03DB:
        db      $84, $01, $FF, $FE
        db      $00, $00
;hard slalom horizontal grid
        db      $41, $48
        db      $48, $49, $48
;-------------------------------------------------------------------------
X03E6:

;sprite imagery
        db      $18 ;...##... car
        db      $18 ;...##...
        db      $DB ;##.##.##
        db      $FF ;########
        db      $DB ;##.##.##
        db      $18 ;...##...
        db      $18 ;...##...
        db      $DB ;##.##.##
        db      $FF ;########
        db      $DB ;##.##.##

        db      $AA ;#.#.#.#. checkpoint (for slalom)
        db      $55 ;.#.#.#.#
        db      $AA ;#.#.#.#.
        db      $55 ;.#.#.#.#
        db      $AA ;#.#.#.#.
        db      $55 ;.#.#.#.#
        db      $AA ;#.#.#.#.
        db      $55 ;.#.#.#.#
        db      $AA ;#.#.#.#.
        db      $55 ;.#.#.#.#

        db      $00 ;........ car facing west
        db      $00 ;........
        db      $48 ;.#..#...
        db      $48 ;.#..#...
        db      $F8 ;#####...
        db      $F8 ;#####...
        db      $48 ;.#..#...
        db      $48 ;.#..#...
        db      $00 ;........
        db      $00 ;........

        db      $00 ;........ car facing northwest
        db      $A0 ;#.#.....
        db      $E0 ;###.....
        db      $40 ;.#......
        db      $E8 ;###.#...
        db      $B8 ;#.###...
        db      $10 ;...#....
        db      $30 ;..##....
        db      $20 ;..#.....
        db      $00 ;........

        db      $20 ;..#..... car facing north
        db      $20 ;..#.....
        db      $70 ;.###....
        db      $70 ;.###....
        db      $20 ;..#.....
        db      $20 ;..#.....
        db      $20 ;..#.....
        db      $20 ;..#.....
        db      $70 ;.###....
        db      $70 ;.###....

        db      $00 ;........ car facing northeast
        db      $28 ;..#.#...
        db      $38 ;..###...
        db      $10 ;...#....
        db      $B8 ;#.###...
        db      $E8 ;###.#...
        db      $40 ;.#......
        db      $60 ;.##.....
        db      $20 ;..#.....
        db      $00 ;........

        db      $00 ;........ car facing east
        db      $00 ;........
        db      $90 ;#..#....
        db      $90 ;#..#....
        db      $F8 ;#####...
        db      $F8 ;#####...
        db      $90 ;#..#....
        db      $90 ;#..#....
        db      $00 ;........
        db      $00 ;........

        db      $08 ;....#... arrow (for slalom)
        db      $10 ;...#....
        db      $20 ;..#.....
        db      $40 ;.#......
        db      $FF ;########
        db      $40 ;.#......
        db      $20 ;..#.....
        db      $10 ;...#....
        db      $08 ;....#...
        db      $00 ;........

        db      $E0 ;###..... barrier (for rally)
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....
        db      $E0 ;###.....

X0440:
;sprite data offsets
        db      $0A, $1A
X0442:
        db      $2A, $4A

X0444:
        db      $32 ;..##..#. 1st line of grand prix sprite #0?
        db      $00 ;........ 3rd line of grand prix sprite #0?
        db      $0A ;....#.#.
        db      $6E ;.##.###.
        db      $00 ;........
        db      $0A ;....#.#.
        db      $3C ;..####..
        db      $D2 ;##.#..#.
        db      $0A, $74, $D2, $0A
        db      $60, $00, $5A, $60
        db      $00, $5A, $5C, $E0
        db      $0A, $5C, $ED, $0A
        db      $78, $8C, $14, $69
        db      $AF, $50, $77, $A5
        db      $1E, $77, $B9, $1E

X0468:
;Values for PITCH
        db      $3F, $3D, $3B, $39

X046C:
        db      $6F ;BGCOLOUR for variants "01"/"02" (grand prix)
        db      $19 ;BGCOLOUR for variants "03"/"04" (rally)
        db      $1F ;BGCOLOUR for variants "05"/"06" (easy slalom)
        db      $79 ;BGCOLOUR for variants "07"/"08" (med. slalom)
X0470:
        db      $6C ;BGCOLOUR for variants "09"/"10" (hard slalom)

X0471:
        db      $00 ;SIZES for grand prix
X0472:
        db      $1A ;sprites #0 and #1 colours, options "01"/"02"
        db      $35 ;sprites #2 and #3 colours, options "01"/"02"
        db      $00 ;SCORECTRL for grand prix
        db      $00 ;SIZES for rally
        db      $00 ;sprites #0 and #1 colours, options "03"/"04"
        db      $19 ;sprites #2 and #3 colours, options "03"/"04"
        db      $00 ;SCORECTRL for rally
        db      $01 ;SIZES for easy slalom
        db      $3F ;sprites #0 and #1 colours, options "05"/"06"
        db      $2B ;sprites #2 and #3 colours, options "05"/"06"
        db      $01 ;SCORECTRL for easy slalom
        db      $01 ;SIZES for medium slalom
        db      $00 ;sprites #0 and #1 colours, options "07"/"08"
        db      $2B ;sprites #2 and #3 colours, options "07"/"08"
        db      $01 ;SCORECTRL for medium slalom
        db      $01 ;SIZES for hard slalom
        db      $00 ;sprites #0 and #1 colours, options "09"/"10"
        db      $25 ;sprites #2 and #3 colours, options "09"/"10"
        db      $01 ;SCORECTRL for hard slalom

LTCOLOURS:                                                           ;$485
;or could be considered SPR0COLOURS
;colours for sprite #0 (left cars)
        db      $18 ;%00,011,000 %011 deinverts to Rgb (red   ) (1st left  car)
        db      $28 ;%00,101,000 %101 deinverts to rGb (green ) (2nd left  car)
        db      $10 ;%00,010,000 %010 deinverts to RgB (purple) (3rd left  car)
        db      $08 ;%00,001,000 %001 deinverts to RGb (yellow) (4th left  car)
        db      $08 ;%00,001,000 %001 deinverts to RGb (yellow) (4th left  car)

RTCOLOURS:                                                           ;$48A
;or could be considered SPR1COLOURS
;colours for sprite #1 (right cars)
        db      $02 ;%00,000,010 %010 deinverts to RgB (purple) (1st right car)
        db      $03 ;%00,000,011 %011 deinverts to Rgb (red   ) (2nd right car)
        db      $06 ;%00,000,110 %110 deinverts to rgB (blue  ) (3rd right car)
        db      $04 ;%00,000,100 %100 deinverts to rGB (cyan  ) (4th right car)
        db      $04 ;%00,000,100 %100 deinverts to rGB (cyan  ) (4th right car)
;SubEnd L048F-------------------------------------------------------------
;r1 and r3 are passed as arguments.
;r1 is always 0 or 1.
;r3 is always $0A (sprite #0) or $1A (sprite #1).

;if (OPTION != 0 && OPTION == r1)
;{   return;
;} // implied else
;SPRITEnAY += *($4F3 + PLAYERnSPEED);
;if (OPTION != 0) // if 1 player
;{   SPRITE1AY = SPRITEnAY; // move 2nd set of enemies by the same amount
;}
L048F:
        loda,r0 OPTION       ;r0 = OPTION; // motherboard RAM         ;4,3
        bctr,eq L0496        ;if == goto L0496;                       ;3,2
        comz    r1           ;compare r0 against r1;                  ;2,1
        retc,eq              ;if == return;                           ;3,1
L0496:
        loda,r0 $1F54,r1     ;r0 = *($1F54 + r1);                     ;4,3
        loda,r0 $04F3,r0     ;r0 = *($04F3 + r0);                     ;4,3
        adda,r0 $1F02,r3     ;r0 += *($1F02 + r3);                    ;4,3
;this line is responsible for adjusting SPRITE0AY and SPRITE1AY during play
        stra,r0 $1F02,r3     ;*($1F02 + r3) = r0;                     ;4,3
        lodr,r2 *$0490       ;r2 = *(*($0490)); // ROM operand        ;3,2
                             ;or, r2 = OPTION; // motherboard RAM
        bctr,eq L04A9        ;if == goto L04A9;                       ;3,2
        stra,r0 SPRITE1AY    ;SPRITE1AY = r0; // hardware registers   ;4,3

;$4A9..$4F2 is:
;do
;{   for (r2 = 4; r2 >= 1; r2--)
;    {   *($1F5F) >>= 1;
;        r0 = *($4F7 + (*($1F5F) & 3));
;        if ((*($1F5F) & 3) == 3)
;        {   r3 = r2 + *($4FB + r1);
;            r1 += OPTION * 2;
;            r0 = *(&P2DISTANCE_L + r3);
;            if (r0 < $80)
;            {   r0--;
;                if (r0 == *($4FD + r1))
;                {   r0 ^= %10000000;
;                } else
;                {   if (*($1F5F) <= 8)
;                    {   r0 ^= %10000000;
;            }   }   }
;            else
;            {   r0++;
;                if (r0 == *($501 + r1))
;                {   r0 ^= %10000000;
;                } else
;                {   if (*($1F5F) <= 8)
;                    {   r0 ^= %10000000;
;            }   }   }
;            *(&P2DISTANCE_L + r3) = r0;
;            r1 = *($1F5B);
;    }   }
;    if (OPTION == 0 || OPTION == r1)
;    {   *($1F5B) = r1 = 1;
;}   }
;while (OPTION == 0 || OPTION == r1);
;return;
L04A9:
        lodi,r2 $04          ;r2 = $04;                               ;2,2
L04AB:
        loda,r3 $1F5F        ;r3 = *($1F5F); // motherboard RAM       ;4,3
        rrr,r3               ;r3 >>= 1;                               ;2,1
        strr,r3 *$04AC       ;*(*($04AC)) = r3; // ROM                ;3,2
                             ;or, *($1F5F) = r3; // motherboard RAM
        andi,r3 $03          ;r3 &= %00000011;                        ;2,2
        loda,r0 $04F7,r3     ;r0 = *($04F7 + r3);                     ;4,3
        bctr,eq L04E4        ;if == goto L04E4;                       ;3,2
        lodz    r2           ;r0 = r2;                                ;2,1
        adda,r0 $04FB,r1     ;r0 += *($04FB + r1);                    ;4,3
        strz    r3           ;r3 = r0;                                ;2,1
        addr,r1 *$04E7       ;r1 += *(*($04E7)); // ROM               ;3,2
                             ;or, r1 += OPTION; // motherboard RAM
        addr,r1 *$04E7       ;r1 += *(*($04E7)); // ROM               ;3,2
                             ;or, r1 += OPTION; // motherboard RAM
        loda,r0 P2DISTANCE_L,r3;r0 = *(&P2DISTANCE_L + r3);           ;4,3
        bctr,lt L04CF        ;if < goto L04CF;                        ;3,2
        subi,r0 $01          ;r0--;                                   ;2,2
        coma,r0 $04FD,r1     ;compare r0 against *($04FD + r1);       ;4,3
        bctr,eq L04DC        ;if == goto L04DC;                       ;3,2
        bctr,un L04D6        ;goto L04D6;                             ;3,2
L04CF:
        addi,r0 $01          ;r0++;                                   ;2,2
        coma,r0 $0501,r1     ;compare r0 against *($0501 + r1);       ;4,3
        bctr,eq L04DC        ;if == goto L04DC;                       ;3,2
L04D6:
        lodr,r1 *$04AC       ;r1 = *(*($04AC)); // ROM                ;3,2
                             ;or, r1 = *($1F5F); // motherboard RAM
        comi,r1 $08          ;compare r1 against $08;                 ;2,2
        bctr,gt L04DE        ;if > goto L04DE;                        ;3,2
L04DC:
        eori,r0 $80          ;r0 ^= %10000000;                        ;2,2
L04DE:
        stra,r0 P2DISTANCE_L,r3;*(&P2DISTANCE_L + r3) = r0;           ;4,3
        loda,r1 $1F5B        ;r1 = *($1F5B); // motherboard RAM       ;4,3
L04E4:
        bdrr,r2 L04AB        ;if (--r2 != 0) goto L04AB;              ;3,2
;end of loop
        loda,r0 OPTION       ;r0 = OPTION; // motherboard RAM         ;4,3
        retc,eq              ;if == return;                           ;3,1
        comz    r1           ;compare r0 against r1;                  ;2,1
        retc,eq              ;if == return;                           ;3,1
        lodi,r1 $01          ;r1 = $01;                               ;2,2
        strr,r1 *$04E2       ;*(*($04E2)) = r1; // ROM                ;3,2
                             ;or, *($1F5B) = r1; // motherboard RAM
        bcta,un L04A9        ;goto L04A9;                             ;3,3
;End of SubEnd L048F------------------------------------------------------
;Data---------------------------------------------------------------------
X04F3:
        db      $FF ;when PLAYERnSPEED == 0, enemies move up   by 1 each time
        db      $01 ;when PLAYERnSPEED == 1, enemies move down by 1 each time
        db      $02 ;when PLAYERnSPEED == 2, enemies move down by 2 each time
        db      $03 ;when PLAYERnSPEED == 3, enemies move down by 3 each time

X04F7:
        db      $00 ;when (*($1F5F) & 3) == 0
        db      $00 ;when (*($1F5F) & 3) == 1
        db      $00 ;when (*($1F5F) & 3) == 2
        db      $01 ;when (*($1F5F) & 3) == 3
X04FB:
        db      $00, $04
X04FD:
        db      $27, $27, $27, $23
X0501:
        db      $CF, $CF, $D3, $CF
;SubEnd CHECKBOUNDS-------------------------------------------------------
CHECKBOUNDS:                                                         ;$505
;This is only used in grand prix mode.
;r1 and r3 are passed as arguments.
;r3 is $2A or $4A, meaning SPRITE2AX or SPRITE3AX.
;r0 and r2 are scratch.

;if (2 players)
;{   r0 = ((*($1F52 + r1) >> 2) & %00111111) + 35;
;} else // 1 player
;{   r0 =   *($1F52 + r1);
;}
;if (r0 < 38)
;{   r0 = 38;
;} elif (r0 > 80 or 136) // for 2 or 1 players respectively
;{   r0 = 80 or 136; // for 2 or 1 players respectively
;}
;if (r1 == 1)
;{   r0 += 56;
;}
;*($1F00 + r3) = r0; // SPRITEnAX
;return;
        loda,r0 PLAYER1X,r1  ;r0 = *($1F52 + r1);                     ;4,3
        lodr,r2 *$04E7       ;r2 = *(*($04E7)); // ROM                ;3,2
                             ;or, r2 = OPTION; // motherboard RAM
        bctr,gt CHECKBOUNDS_1;if > goto CHECKBOUNDS_1;                ;3,2
        rrr,r0               ;r0 >>= 1;                               ;2,1
        rrr,r0               ;r0 >>= 1;                               ;2,1
        andi,r0 $3F          ;r0 &= %00111111;                        ;2,2
        addi,r0 $23          ;r0 += $23;                              ;2,2
CHECKBOUNDS_1:                                                       ;$512
        comi,r0 $26          ;compare r0 against $26;                 ;2,2
        bctr,lt CHECKBOUNDS_4;if < goto CHECKBOUNDS_4;                ;3,2
        coma,r0 $052E,r2     ;compare r0 against *($052E + r2);       ;4,3
        bctr,gt CHECKBOUNDS_5;if > goto CHECKBOUNDS_5;                ;3,2
CHECKBOUNDS_2:                                                       ;$51B
        comi,r1 $01          ;compare r1 against $01;                 ;2,2
        bcfr,eq CHECKBOUNDS_3;if != goto CHECKBOUNDS_3;               ;3,2
        addi,r0 $38          ;r0 += $38;                              ;2,2
CHECKBOUNDS_3:                                                       ;$521
        stra,r0 $1F00,r3     ;*($1F00 + r3) = r0;                     ;4,3
        retc,un              ;return;                                 ;3,1
CHECKBOUNDS_4:                                                       ;$525
        lodi,r0 $26          ;r0 = $26;                               ;2,2
        bctr,un CHECKBOUNDS_2;goto CHECKBOUNDS_2;                     ;3,2
CHECKBOUNDS_5:                                                       ;$529
        loda,r0 $052E,r2     ;r0 = *($052E + r2);                     ;4,3
        bctr,un CHECKBOUNDS_2;goto CHECKBOUNDS_2;                     ;3,2
;Data for Code Section CHECKBOUNDS----------------------------------------
X052E:
        db      $50          ;2 players
        db      $88          ;1 player
;Interrupt Handler--------------------------------------------------------
INTERRUPT:                                                           ;$530
        stra,r0 PRESERVER0   ;PRESERVER0 = r0; // motherboard RAM     ;4,3
        ppsl    $10          ;PSL |= %00010000; // use alt. reg. bank ;3,2
        spsl                 ;r0 = PSL;                               ;2,1
        stra,r0 PRESERVEPSL  ;PRESERVEPSL = r0 [PSL]; // mobo RAM     ;4,3

;if (SPRITECOLLIDE & %00000001) // if sprites #2/#3 have collided (ie. player cars)
;{   SPRCOLCOPY |= SPRITECOLLIDE | %00100000; // set sprites #0/#1 collision bit
;} else
;{   SPRCOLCOPY |= SPRITECOLLIDE;
;}
        loda,r0 SPRITECOLLIDE;r0 = SPRITECOLLIDE; // hardware regs    ;4,3
        tmi,r0  $01          ;test bits %00000001 of r0;              ;3,2
        bctr,lt L0542        ;if < goto L0542;                        ;3,2
        iori,r0 $20          ;r0 |= %00100000;                        ;2,2
L0542:
        iora,r0 SPRCOLCOPY   ;r0 |= SPRCOLCOPY; // motherboard RAM    ;4,3
        strr,r0 *$0543       ;*(*($0543)) = r0; // ROM                ;3,2
                             ;or, SPRCOLCOPY = r0; // motherboard RAM

;BGCOLCOPY |= (BGCOLLIDE & %11110011); // mask out sprite #0/#1 display complete
;r5 = BGCOLLIDE; // used later
        loda,r0 BGCOLLIDE    ;r0 = BGCOLLIDE; // hardware registers   ;4,3
        strz    r2           ;r5 = r0;                                ;2,1
        andi,r0 $F3          ;r0 &= %11110011;                        ;2,2
        iora,r0 BGCOLCOPY    ;r0 |= BGCOLCOPY; // motherboard RAM     ;4,3
        strr,r0 *$054E       ;*(*($054E)) = r0; // ROM                ;3,2
                             ;or, BGCOLCOPY = r0;

;test for vblank
        tpsu    $80          ;test bits %10000000 of PSU; // Sense    ;3,2
        bcta,lt NOTVBLANK    ;if < goto NOTVBLANK;                    ;3,3

;yes, we are in vblank
;vblank code does the following:
; (a) read and handle paddles (if game in progress)
; (b) play sounds
; (c) read and handle console keys
; (d) decrement monotonic decrementor (and invert colours if necessary)
; (e) handle score display

;$557..$5F4 is:
;if (INVERTCOLOURS & $10)
;{   for (r6 = 2; r6 >= 1; r6--)
;    {   if (Flag)
;        {   if (*($1F5F + r6) != 0)
;            {   r0 = *($1F5F + r6);
;            } else
;            {   if ((((PnPADDLE << 3) & %00000111) ^ %11111111) + 4) >= $80) // if pushing backwards (decelerating)
;$00..$1F -> $03          forwards
;$20..$3F -> $02          forwards
;$40..$5F -> $01          forwards
;$60..$7F -> $00
;$80..$9F -> $FF (ie. -1) backwards
;$A0..$BF -> $FE (ie. -2) backwards
;$C0..$DF -> $FD (ie. -3) backwards
;$E0..$FF -> $FC (ie. -4) backwards
;                {   r5 = 0;
;                } else
;                {   r5 = (((PnPADDLE << 3) & %00000111) ^ %11111111) + 4;
;                }
;                if (PLAYERnSPEED == r5)
;                {   continue;
;                }
;                if (PLAYERnSPEED >  r5)
;                {   PLAYERnSPEED--; // coast to a stop because of friction
;                } else
;                {   // assert(PLAYERnSPEED < r5);
;                    PLAYERnSPEED++;
;                }
;                r0 = *($6DF + GAME); // $6DF..$6E3
;            }
;            *($1F5F + r6) = r0 - 1;
;        } else
;        {   if (*($1FCB + r6) < 10) // PnPADDLE
;            {   *($1F51 + r6) = 10; // PLAYERnX
;            } elif (*($1FCB + r6) < $BE) // PnPADDLE
;            {   *($1F51 + r6) = *($1FCB + r6); // PLAYERnX
;            } else
;            {   // assert(*($1FCB + r6) >= $BE);
;                *($1F51 + r6) = $BE; // PLAYERnX
;    }   }   }
;    PSU ^= .F......;
;    if (OPTION & 1) // if a 2-player game
;    {   LTDRAWN = ((PLAYER1SPEED + PLAYER2SPEED) >> 1) & %00001111;
;    } else // a 1-player game
;    {   LTDRAWN = PLAYER1SPEED;
;    }
;    if (SOUNDVAR != 0)
;    {   SOUNDVAR--;
;        if (SOUNDVAR < 49)
;        {   if (SOUNDVAR == 47)
;            {   NOISE = 0;
;        }   }
;        else
;        {   NOISE = $10;
;    }   }
;    else
;    {   PITCH = *($468 + r6);
;        if (PLAYER1SPEED == 0)
;        {   if (r5 == 0 && PLAYER2SPEED != 0)
;            {   NOISE = $88;
;            } else
;            {   NOISE = $C8;
;        }   }
;        else
;        {   if (r5 == 0 && PLAYER2SPEED != 0)
;            {   NOISE = $48;
;            } else
;            {   NOISE = $88;
;}   }   }   }
        loda,r1 INVERTCOLOURS;r4 = INVERTCOLOURS; // motherboard RAM  ;4,3
        tmi,r1  $10          ;test bits %00010000 of r4;              ;3,2
        bcta,lt L05F5        ;if < goto L05F5;                        ;3,3   
        lodi,r3 $02          ;r6 = $02; // loop iterator              ;2,2
L0561:
        loda,r0 $1FCB,r3     ;r0 = *($1FCB + r6); // PnPADDLE         ;4,3
        tpsu    $40          ;test bits .F...... of PSU; // Flag bit  ;3,2
        bctr,lt L059D        ;if < goto L059D;                        ;3,2
        strz    r2           ;r5 = r0;                                ;2,1
        loda,r0 $1F5F,r3     ;r0 = *($1F5F + r6); // motherboard RAM  ;4,3
        bcfr,eq L0592        ;if != goto L0592;                       ;3,2
        rrl,r2               ;r5 <<= 1;                               ;2,1
        rrl,r2               ;r5 <<= 1;                               ;2,1
        rrl,r2               ;r5 <<= 1;                               ;2,1
        andi,r2 $07          ;r5 &= %00000111;                        ;2,2
        eori,r2 $FF          ;r5 ^= %11111111;                        ;2,2
        addi,r2 $04          ;r5 += $04;                              ;2,2
        bcfr,lt L057B        ;if >= goto L057B;                       ;3,2
        lodi,r2 $00          ;r5 = $00;                               ;2,2
L057B:
        loda,r0 $1F53,r3     ;r0 = *($1F53 + r6);                     ;4,3
        comz    r2           ;compare r0 against r5;                  ;2,1
        bctr,eq L05AA        ;if == goto L05AA;                       ;3,2

        bctr,gt L0587        ;if > goto L0587;                        ;3,2
        addi,r0 $01          ;r0++;                                   ;2,2
        bctr,un L0589        ;goto L0589;                             ;3,2
L0587:
        subi,r0 $01          ;r0--;                                   ;2,2
L0589:
        stra,r0 $1F53,r3     ;*($1F53 + r6) = r0;                     ;4,3
        loda,r0 GAME         ;r0 = GAME; // motherboard RAM           ;4,3
        loda,r0 $06DF,r0     ;r0 = *($06DF + r0);                     ;4,3
L0592:
        subi,r0 $01          ;r0--;                                   ;2,2
        stra,r0 $1F5F,r3     ;*($1F5F + r6) = r0;                     ;4,3
        bctr,un L05AA        ;goto L05AA;                             ;3,2
L0599:
        lodi,r0 $0A          ;r0 = $0A;                               ;2,2
        bctr,un L05A7        ;goto L05A7;                             ;3,2
L059D:
        comi,r0 $0A          ;compare r0 against $0A;                 ;2,2
        bctr,lt L0599        ;if < goto L0599;                        ;3,2
        comi,r0 $BE          ;compare r0 against $BE;                 ;2,2
        bctr,lt L05A7        ;if < goto L05A7;                        ;3,2
        lodi,r0 $BE          ;r0 = $BE;                               ;2,2
L05A7:
        stra,r0 $1F51,r3     ;*($1F51 + r6) = r0;                     ;4,3
L05AA:
        bdra,r3 L0561        ;if (--r6 != 0) goto L0561;              ;3,3
;end of loop
        spsu                 ;r0 = PSU;                               ;2,1
        eori,r0 $40          ;r0 ^= .F......; // flip paddle interpolation
                                                                      ;2,2
        lpsu                 ;PSU = r0;                               ;2,1
        loda,r3 PLAYER1SPEED ;r6 = PLAYER1SPEED; // motherboard RAM   ;4,3
        loda,r2 OPTION       ;r5 = OPTION; // motherboard RAM         ;4,3
        andi,r2 $01          ;r5 &= %00000001;                        ;2,2
        bctr,gt L05C1        ;if > goto L05C1;                        ;3,2
        adda,r3 PLAYER2SPEED ;r6 += PLAYER2SPEED; // motherboard RAM  ;4,3
        rrr,r3               ;r6 >>= 1;                               ;2,1
        andi,r3 $0F          ;r6 &= %00001111;                        ;2,2
L05C1:
        stra,r3 LTDRAWN      ;LTDRAWN = r6; // motherboard RAM        ;4,3
        loda,r0 SOUNDVAR     ;r0 = SOUNDVAR; // motherboard RAM       ;4,3
        bctr,eq L05DC        ;if == goto L05DC;                       ;3,2
        subi,r0 $01          ;r0--;                                   ;2,2
        strr,r0 *$05C5       ;*(*($05C5)) = r0; // ROM                ;3,2
                             ;or, SOUNDVAR = r0; // motherboard RAM
        comi,r0 $31          ;compare r0 against $31;                 ;2,2
        bctr,lt L05D5        ;if < goto L05D5;                        ;3,2
        lodi,r0 $10          ;r0 = $10;                               ;2,2
        bctr,un L05F2        ;goto L05F2;                             ;3,2
L05D5:
        comi,r0 $2F          ;compare r0 against $2F;                 ;2,2
        bcfr,eq L05F5        ;if != goto L05F5;                       ;3,2
        eorz    r0           ;r0 = 0;                                 ;2,1
        bctr,un L05F2        ;goto L05F2;                             ;3,2
L05DC:
        loda,r0 $0468,r3     ;r0 = *($0468 + r6);                     ;4,3
        stra,r0 PITCH        ;PITCH = r0; // hardware registers       ;4,3
        lodi,r0 $C8          ;r0 = $C8;                               ;2,2
        lodr,r3 *$05B2       ;r6 = *(*($05B2)); // ROM operand        ;3,2
                             ;or, r6 = PLAYER1SPEED; // motherboard RAM
        bctr,eq L05EA        ;if == goto L05EA;                       ;3,2
        subi,r0 $40          ;r0 -= $40;                              ;2,2
L05EA:
        brnr,r2 L05F2        ;if (r5 != 0) goto L05F2;                ;3,2
        lodr,r3 *$05BC       ;r6 = *(*($05BC)); // ROM                ;3,2
                             ;or, r6 = PLAYER2SPEED; // motherboard RAM
        bctr,eq L05F2        ;if == goto L05F2;                       ;3,2
        subi,r0 $40          ;r0 -= $40;                              ;2,2
L05F2:
        stra,r0 NOISE        ;NOISE = r0; // noise generator          ;4,3

L05F5:

;$5F5..$600 is:
;if (P1COLLIDE < $80)
;{   P1COLLIDE++;
;    goto L06B8;
;}
        loda,r0 P1COLLIDE    ;r0 = P1COLLIDE; // motherboard RAM      ;4,3
        bcfr,lt L0601        ;if >= goto L0601;                       ;3,2
        addi,r0 $01          ;r0++;                                   ;2,2
        strr,r0 *$05F6       ;*(*($05F6)) = r0; // ROM                ;3,2
                             ;or, P1COLLIDE; // motherboard RAM
        bcta,un L06B8        ;goto L06B8;                             ;3,3

;$601..$634 is:
;if (CONSOLE & $80) // SELECT key is down
;{   if ((r4 & $02) != 0)
;    {   r4 |= $02;
;        r6 <<= 1;
;        if ((r6 & $80) == 0)
;        {   r4 &= %11111110;
;        } else
;        {   if ((r4 & 1) != 0)
;            {   r4 |= 1;
;            } else
;            {   r3 = $10;
;                r2 = OPTION + 1;
;                goto TITLESCREEN;
;    }   }   }
;    else
;    {   // increase option
;        if (OPTION + 1 < 10)
;        {   r2 = OPTION + 1;
;        } else
;        {   r2 = 0;
;        }
;        r3 = 0;
;        goto TITLESCREEN;
;}   }
;else
;{   r4 &= %11111101;
;    r6 <<= 1;
;    if ((r6 & $80) == 0)
;    {   r4 &= %11111110;
;    } else
;    {   if ((r4 & 1) != 0)
;        {   r4 |= 1;
;        } else
;        {   r3 = $10;
;            r2 = OPTION + 1;
;            goto TITLESCREEN;
;}   }   }
L0601:
        loda,r0 OPTION       ;r0 = OPTION; // motherboard RAM         ;4,3
        loda,r3 CONSOLE      ;r6 = CONSOLE; // hardware registers     ;4,3
        bctr,lt L060D        ;if < goto L060D;                        ;3,2
        andi,r1 $FD          ;r4 &= %11111101;                        ;2,2
        bctr,un L0620        ;goto L0620;                             ;3,2
;
L060D:
        tmi,r1  $02          ;test bits %00000010 of r4;              ;3,2
        bctr,lt L061E        ;if < goto L061E;                        ;3,2
        cpsl    $10          ;PSL &= %11101111; // use main reg. bank ;3,2
        addi,r0 $01          ;r0++;                                   ;2,2
        comi,r0 $0A          ;compare r0 against $0A;                 ;2,2
        bctr,lt L061A        ;if < goto L061A;                        ;3,2
        eorz    r0           ;r0 = 0;                                 ;2,1
L061A:
        lodi,r3 $00          ;r3 = $00;                               ;2,2
        bctr,un L062F        ;goto L062F;                             ;3,2
;
L061E:
        iori,r1 $02          ;r4 |= %00000010;                        ;2,2
L0620:
        rrl,r3               ;r6 <<= 1;                               ;2,1
        bctr,lt L0627        ;if < goto L0627;                        ;3,2
        andi,r1 $FE          ;r4 &= %11111110;                        ;2,2
        bctr,un L0635        ;goto L0635;                             ;3,2
;
L0627:
        tmi,r1  $01          ;test bits %00000001 of r4;              ;3,2
        bctr,lt L0633        ;if < goto L0633;                        ;3,2
        cpsl    $10          ;PSL &= %11101111; // use main reg. bank ;3,2
        lodi,r3 $10          ;r3 = $10;                               ;2,2
L062F:
        strz    r2           ;r2 = r0;                                ;2,1
        bcta,un TITLESCREEN  ;goto TITLESCREEN;                       ;3,3
L0633:
        iori,r1 $01          ;r4 |= %00000001;                        ;2,2

L0635:
;$635..$691 is:
;MONOTONIC_L -= 4;
;if (MONOTONIC_L == 0)
;{   MONOTONIC_H -= 2;
;    if (MONOTONIC_H == 0)
;    {   if (!(r4 & $20))
;        {   r4 |= $20;
;            if (OPTION == 0)
;            {   r4 |= %01000000;
;                SPRITE0AY = SPRITE1AY = 240;
;        }   }
;        if (r4 & $10)
;        {   r4 &= %11101111;
;            PITCH = 0;
;            MONOTONIC_H = 20;
;        } else
;        {   r4 ^= %00000100;
;            if (r4 & 4)
;            {   BGCOLOUR = *($46C + GAME) ^ %11110111;
;            } else
;            {   BGCOLOUR = *($46C + GAME);
;            }
;            if (r4 & 4)
;            {   SPR01COLOURS = *($471 + (GAME << 2) + 1) ^ %11111111;
;                SPR23COLOURS = *($471 + (GAME << 2) + 2) ^ %11111111;
;            } else
;            {   SPR01COLOURS = *($471 + (GAME << 2) + 1);
;                SPR23COLOURS = *($471 + (GAME << 2) + 2);
;}   }   }   }
        loda,r0 MONOTONIC_L  ;r0 = MONOTONIC_L; // motherboard RAM    ;4,3
        subi,r0 $04          ;r0 -= $04;                              ;2,2
        strr,r0 *$0636       ;*(*($0636)) = r0; // ROM operand        ;3,2
                             ;or, MONOTONIC_L = r0; // motherboard RAM
        bcfa,eq L0692        ;if != goto L0692;                       ;3,3

        loda,r0 MONOTONIC_H  ;r0 = MONOTONIC_H; // motherboard RAM    ;4,3
        subi,r0 $02          ;r0 -= $02;                              ;2,2
        bcfa,eq L068F        ;if != goto L068F;                       ;3,3
        tmi,r1  $20          ;test bits %00100000 of r4;              ;3,2
        bctr,eq L065C        ;if == goto L065C;                       ;3,2
        iori,r1 $20          ;r4 |= %00100000;                        ;2,2
        loda,r2 OPTION       ;r5 = OPTION; // motherboard RAM         ;4,3
        bctr,gt L065C        ;if > goto L065C;                        ;3,2
        iori,r1 $40          ;r4 |= %01000000;                        ;2,2
        lodi,r0 $E0          ;r0 = $E0;                               ;2,2
        stra,r0 SPRITE0AY    ;SPRITE0AY = r0 [$E0]; // h/w regs       ;4,3
        stra,r0 SPRITE1AY    ;SPRITE1AY = r0 [$E0]; // h/w regs       ;4,3
L065C:
        tmi,r1  $10          ;test bits %00010000 of r4;              ;3,2
        bctr,lt L066A        ;if < goto L066A;                        ;3,2
        andi,r1 $EF          ;r4 &= %11101111;                        ;2,2
        eorz    r0           ;r0 = 0;                                 ;2,1
        stra,r0 PITCH        ;PITCH = r0 [0]; // hardware registers   ;4,3
        lodi,r0 $14          ;r0 = $14;                               ;2,2
        bctr,un L068F        ;goto L068F;                             ;3,2
L066A:
        eori,r1 $04          ;r4 ^= %00000100;                        ;2,2
        loda,r2 GAME         ;r5 = GAME; // motherboard RAM           ;4,3
        loda,r0 $046C,r2     ;r0 = *($046C + r5);                     ;4,3
        tmi,r1  $04          ;test bits %00000100 of r4;              ;3,2
        bctr,lt L0678        ;if < goto L0678;                        ;3,2
        eori,r0 $F7          ;r0 ^= %11110111;                        ;2,2
L0678:
        stra,r0 BGCOLOUR     ;BGCOLOUR = r0; // hardware registers    ;4,3
        rrl,r2               ;r5 <<= 1;                               ;2,1
        rrl,r2               ;r5 <<= 1;                               ;2,1
        lodi,r3 $FE          ;r6 = $FE; // loop twice                 ;2,2
L067F:
        loda,r0 $0471,r2+    ;r0 = *($0471 + ++r5);                   ;4,3
        tmi,r1  $04          ;test bits %00000100 of r4;              ;3,2
        bctr,lt L0688        ;if < goto L0688;                        ;3,2
        eori,r0 $FF          ;r0 ^= %11111111;                        ;2,2
L0688:
        stra,r0 $1EC3,r3     ;*($1EC3 + r6) = r0;                     ;4,3
        birr,r3 L067F        ;if (++r6 != 0) goto L067F;              ;3,2
;end of loop
        lodi,r0 $02          ;r0 = $02;                               ;2,2
L068F:
        stra,r0 MONOTONIC_H  ;MONOTONIC_H = r0; // motherboard RAM    ;4,3

L0692:
;$692..$6B7 is:
;if (!(r4 & $40))
;{   SCORELT = P1CRASHES;
;    SCORERT = P2CRASHES;
;    SCORECTRL = %000000,0,0; // 2 groups of 2 digits at top    of screen
;    for (i = 0; i < 512; i++);
;    SCORELT = P1DISTANCE_H;
;    SCORERT = P2DISTANCE_H;
;    SCORECTRL = %000000,0,1; // 2 groups of 2 digits at bottom of screen
;}
        tmi,r1  $40          ;test bits %01000000 of r4;              ;3,2
        bctr,lt L06B8        ;if < goto L06B8;                        ;3,2
        loda,r0 $1F5C        ;r0 = *($1F5C); // motherboard RAM       ;4,3
        stra,r0 SCORELT      ;SCORELT = r0; // hardware registers     ;4,3
        loda,r0 $1F5D        ;r0 = *($1F5D); // motherboard RAM       ;4,3
        stra,r0 SCORERT      ;SCORERT = r0; // hardware registers     ;4,3
        eorz    r0           ;r0 = 0;                                 ;2,1
        stra,r0 SCORECTRL    ;SCORECTRL = r0 [0]; // h/w regs         ;4,3
L06A6:
        bdrr,r0 L06A6        ;if (--r0 != 0) goto L06A6;              ;3,2
L06A8:
        bdrr,r0 L06A8        ;if (--r0 != 0) goto L06A8;              ;3,2
        loda,r0 P1DISTANCE_H ;r0 = P1DISTANCE_H;                      ;4,3
        strr,r0 *$069A       ;*(*($069A)) = r0; // ROM                ;3,2
                             ;or, SCORELT = r0; // hardware registers
        loda,r0 P2DISTANCE_H ;r0 = P2DISTANCE_H;                      ;4,3
        strr,r0 *$06A0       ;*(*($06A0)) = r0; // ROM                ;3,2
                             ;or, SCORERT = r0; // hardware registers
        lodi,r0 $01          ;r0 = $01;                               ;2,2
        strr,r0 *$06A4       ;*(*($06A4)) = r0; // ROM                ;3,2
                             ;or, SCORECTRL = r0 [%000000,0,1]; // h/w regs

L06B8:
;$6B8..$6DE is:
;if (GAME < 1)
;{   SPRITE0BY = SPRITE1BY = 28;
;    r0 = %00,011,010;
;    gosub SETSPRITECOLS;
;}
;if (GAME != 1)
;{   INVERTCOLOURS = r4;
;    LTDRAWN = RTDRAWN = 0;
;}
;if (GAME == 1)
;{   goto RALLY;
;} else
;{   while (Sense);
;    return;
;}
        loda,r0 GAME         ;r0 = GAME; // motherboard RAM           ;4,3
        comi,r0 $01          ;compare r0 against $01;                 ;2,2
        bctr,gt L06CE        ;if > goto L06CE;                        ;3,2
        bctr,eq RALLY        ;if == goto RALLY;                       ;3,2
        lodi,r0 $1C          ;r0 = $1C;                               ;2,2
        stra,r0 SPRITE0BY    ;SPRITE0BY = r0 [28]; // h/w regs        ;4,3
        stra,r0 SPRITE1BY    ;SPRITE1BY = r0 [28]; // h/w regs        ;4,3
;inefficient, lodi,r0 $1A would make more sense!
        loda,r0 $0472        ;r0 = *($0472); // ROM data              ;4,3
                             ;or, r0 = $1A [%00,011,010];
        bstr,un SETSPR01COLS ;gosub SETSPR01COLS;                     ;3,2
L06CE:
        stra,r1 INVERTCOLOURS;INVERTCOLOURS = r4; // motherboard RAM  ;4,3
        eorz    r0           ;r0 = 0;                                 ;2,1
        stra,r0 LTDRAWN      ;LTDRAWN = r0 [0]; // motherboard RAM    ;4,3
        stra,r0 RTDRAWN      ;RTDRAWN = r0 [0]; // motherboard RAM    ;4,3
;wait for the end of vertical blanking
L06D8:
        tpsu    $80          ;test bits %10000000 of PSU; // Sense bit;3,2
        bctr,eq L06D8        ;if == goto L06D8;                       ;3,2
;end of loop
        bcta,un INTERRUPT_END;goto INTERRUPT_END;                     ;3,3
;End of Code Section------------------------------------------------------
;Data for Interrupt Handler INTERRUPT-------------------------------------
X06DF:
        db      $0A ;for options "01"/"02"
        db      $32 ;for options "03"/"04"
        db      $14 ;for options "05"/"06"
        db      $14 ;for options "07"/"08"
        db      $14 ;for options "09"/"10"
;Subroutine SETSPR01COLS--------------------------------------------------
SETSPR01COLS:                                                        ;$6E4
;r0 and r4 are arguments to this subroutine.
;When called from $6CC, r0 = %00,011,010;
;                   and r4 = usually based on INVERTCOLOURS?
;When called from $7C6, r0 = *(&LTCOLOURS + LTDRAWN) + *(&RTCOLOURS + RTDRAWN);
;                   and r4 = INVERTCOLOURS;

;if (r4 & %00000100) // "invert colours" bit
;{   SPR01COLOURS = r0 ^ %11111111;
;} else
;{   SPR01COLOURS = r0;
;}
        tmi,r1  $04          ;test bits %00000100 of r4;              ;3,2
        bctr,lt L06EA        ;if < goto L06EA;                        ;3,2
        eori,r0 $FF          ;r0 ^= %11111111;                        ;2,2
L06EA:
        stra,r0 SPR01COLOURS ;SPR01COLOURS = r0; // hardware registers;4,3
        retc,un              ;return;                                 ;3,1
;End of Subroutine SETSPR01COLS-------------------------------------------
RALLY:                                                               ;$6EE
;this subroutine is only for when GAME == 1 (ie. options "03" and "04").
        tmi,r1  $10          ;test bits %00010000 of r4;              ;3,2
        bctr,lt L06CE        ;if < goto L06CE;                        ;3,2
        loda,r0 P1COLLIDE    ;r0 = P1COLLIDE; // motherboard RAM      ;4,3
        bctr,lt L06CE        ;if < goto L06CE;                        ;3,2
        loda,r0 SPRITE0AY    ;r0 = SPRITE0AY; // hardware registers   ;4,3
        adda,r0 LEFTREDX     ;r0 += LEFTREDX; // motherboard RAM      ;4,3
        comi,r0 $14          ;compare r0 against $14;                 ;2,2
        bctr,lt RALLY_1      ;if < goto RALLY_1;                      ;3,2
        eorz    r0           ;r0 = 0;                                 ;2,1
RALLY_1:                                                             ;$702
        strr,r0 *$06F8       ;*(*($06F8)) = r0; // ROM                ;3,2
                             ;or, SPRITE0AY = r0; // hardware registers
        stra,r0 SPRITE1AY    ;SPRITE1AY = r0; // hardware registers   ;4,3
        eorz    r0           ;r0 = 0;                                 ;2,1
        bsta,un L032F        ;gosub L032F;                            ;3,3

;SPRITE0AX = *($1F80) - r5;
        loda,r0 $1F80        ;r0 = *($1F80); // vertical grid         ;4,3
        subz    r2           ;r0 -= r5;                               ;2,1
        stra,r0 SPRITE0AX    ;SPRITE0AX = r0; // hardware registers   ;4,3

;SPRITE1AX = *($1F80) + r5;
        addz    r2           ;r0 += r5;                               ;2,1
        addz    r2           ;r0 += r5;                               ;2,1
        stra,r0 SPRITE1AX    ;SPRITE1AX = r0; // hardware registers   ;4,3

        loda,r0 RIGHTPURPLEX ;r0 = RIGHTPURPLEX; // motherboard RAM   ;4,3
        bdra,r0 RALLY_7      ;if (--r0 != 0) goto RALLY_7;            ;3,3
        lodi,r2 $0D          ;r5 = $0D;                               ;2,2
RALLY_2:                                                             ;$71F
        loda,r0 $1F7F,r2     ;r0 = *($1F7F + r5);                     ;4,3
        stra,r0 $1F80,r2     ;*($1F80 + r5) = r0;                     ;4,3
        bdrr,r2 RALLY_2      ;if (--r5 != 0) goto RALLY_2;            ;3,2
        loda,r0 *$070C       ;r0 = *(*($070C)); // ROM                ;4,3
                             ;or, r0 = *($1F80); // vertical grid
        loda,r2 $1F69        ;r5 = *($1F69); // motherboard RAM       ;4,3
        bctr,gt RALLY_3      ;if > goto RALLY_3;                      ;3,2
        subi,r0 $0C          ;r0 -= $0C;                              ;2,2
        bctr,un RALLY_4      ;goto RALLY_4;                           ;3,2
;
RALLY_3:                                                             ;$733
        addi,r0 $0C          ;r0 += $0C;                              ;2,2
RALLY_4:                                                             ;$735

;if (r0 < 40 || r0 > 150 || *($1F5F) < 16)
;{   *($1F69) = r5 ^ %00000001; // motherboard RAM
;} else
;{   *($1F80) = r0; // vertical grid
;}
        comi,r0 $28          ;compare r0 against $28 [40];            ;2,2
        bctr,lt RALLY_5      ;if < goto RALLY_5;                      ;3,2
        comi,r0 $96          ;compare r0 against $96 [150];           ;2,2
        bctr,gt RALLY_5      ;if > goto RALLY_5;                      ;3,2
        loda,r3 $1F5F        ;r6 = *($1F5F); // motherboard RAM       ;4,3
        comi,r3 $10          ;compare r6 against $10 [16];            ;2,2
        bctr,lt RALLY_5      ;if < goto RALLY_5;                      ;3,2
        stra,r0 $1F80        ;*($1F80) = r0; // vertical grid         ;4,3
        bctr,un RALLY_6      ;goto RALLY_6;                           ;3,2
RALLY_5:                                                             ;$749
        eori,r2 $01          ;r5 ^= %00000001;                        ;2,2
        strr,r2 *$072B       ;*(*($072B)) = r5; // ROM operand        ;3,2
                             ;or, *($1F69) = r5; // motherboard RAM

RALLY_6:                                                             ;$74D

;LEFTREDX = *($75F + LTDRAWN);
        loda,r2 $1F50        ;r5 = LTDRAWN; // motherboard RAM        ;4,3
        loda,r0 $075F,r2     ;r0 = *($075F + r5);                     ;4,3
        stra,r0 LEFTREDX     ;LEFTREDX = r0; // motherboard RAM       ;4,3

;RIGHTPURPLEX = *($763 + LTDRAWN);
        loda,r0 $0763,r2     ;r0 = *($0763 + r5);                     ;4,3
RALLY_7:                                                             ;$759
        stra,r0 RIGHTPURPLEX ;RIGHTPURPLEX = r0; // motherboard RAM   ;4,3

        bcta,un L06CE        ;goto L06CE;                             ;3,3
;Data for RALLY-----------------------------------------------------------
X075F:
        db      $02, $03, $04, $05
X0763:
        db      $0A, $07, $05, $04
;Interrupt Subroutine REUSEENEMY------------------------------------------
REUSEENEMY:                                                          ;$767
;r4 is an argument to this subroutine. It is always either 0 or 1.
;(This is which sprite we want to reuse.)

;This entire subroutine can be summarized as follows:
;*($1F01 + *($440 + r4)) = (*($1F67 + (*($1F50) + r4) + *($7CB + r4))) & %01111111) + *($7CD + r4);
;*($1F50 + r4)++;
;if (*($1F50 + r4) == 3)
;{   *($1F03 + *($440 + r4)) = $FE;
;} elif (*($1F50 + r4) != 1)
;{   if (r4 != 0)
;    {   BGCOLCOPY |= %00000100;
;    } else
;    {   BGCOLCOPY |= %00001000;
;    }
;    *($1F00 + *($440 + r4)) = (*($1F66 + *($7CB + r4)) & %01111111) + *($7CD + r4);
;}

;So, for the case where r4 == 0:
;*($1F01 + *($440)) = (*($1F67 + (LTDRAWN + *($7CB))) & %01111111) + *($7CD);
;LTDRAWN++;
;if (LTDRAWN == 3)
;{   *($1F03 + *($440)) = $FE;
;} elif (LTDRAWN != 1)
;{   BGCOLCOPY |= %00001000;
;    *($1F00 + *($440)) = (*($1F66 + *($7CB)) & %01111111) + *($7CD);
;}

;...and for the case where r4 == 1:
;*($1F01 + *($441)) = (*($1F67 + (RTDRAWN + *($7CC))) & %01111111) + *($7CE);
;RTDRAWN++;
;if (RTDRAWN == 3)
;{   *($1F03 + *($441)) = $FE;
;} elif (RTDRAWN != 1)
;{   BGCOLCOPY |= %00000100;
;    *($1F00 + *($441)) = (*($1F66 + *($7CC)) & %01111111) + *($7CE);
;}

;To maximally simplify the case where r4 == 0:
;SPRITE0BX = *($1F67 + LTDRAWN) & %01111111;
;LTDRAWN++; // mobo RAM
;if (LTDRAWN <= 1)
;{   BGCOLCOPY |= %00001000; // set "sprite display #0 complete" flag
;    SPRITE0AX = (LEFTREDX & %01111111);
;} elif (LTDRAWN == 3)
;{   SPRITE0BY = $FE;
;}

;To maximally simplify the case where r4 == 1:
;SPRITE1BX = (*($1F6B + RTDRAWN) & %01111111) + 56;
;RTDRAWN++; // mobo RAM
;if (RTDRAWN <= 1)
;{   BGCOLCOPY |= %00000100; // set "sprite display #1 complete" flag
;    SPRITE1AX = (RIGHTPURPLEX & %01111111) + 56;
;} elif (RTDRAWN == 3)
;{   SPRITE1BY = $FE;
;}

;*($1F01 + *($440 + r4)) = (*($1F67 + (*($1F50 + r4) + *($7CB + r4))) & %01111111) + *($7CD + r4);
        loda,r0 $0440,r1     ;r0 = *($0440 + r4);                     ;4,3
        strz    r3           ;r6 = r0;                                ;2,1
        loda,r0 $1F50,r1     ;r0 = *($1F50 + r4);                     ;4,3
        adda,r0 $07CB,r1     ;r0 += *($07CB + r4);                    ;4,3
        loda,r0 $1F67,r0     ;r0 = *($1F67 + r0);                     ;4,3
        andi,r0 $7F          ;r0 &= %01111111;                        ;2,2
        adda,r0 $07CD,r1     ;r0 += *($07CD + r4);                    ;4,3
        stra,r0 $1F01,r3     ;*($1F01 + r6) = r0;                     ;4,3

;*($1F50 + r4)++;
        loda,r0 $1F50,r1     ;r0 = *($1F50 + r4);                     ;4,3
        addi,r0 $01          ;r0++;                                   ;2,2
        stra,r0 $1F50,r1     ;*($1F50 + r4) = r0;                     ;4,3

;if (*($1F50 + r4) == 3)
;{   *($1F03 + *($440 + r4)) = $FE;
;    return;
;} elif (*($1F50 + r4) == 1)
;{   return;
;}
        comi,r0 $03          ;compare r0 against $03;                 ;2,2
        bctr,eq L07A4        ;if == goto L07A4;                       ;3,2
        comi,r0 $01          ;compare r0 against $01;                 ;2,2
        retc,gt              ;if > return;                            ;3,1

;if (r4 != 0)
;{   BGCOLCOPY |= %00000100;
;} else
;{   BGCOLCOPY |= %00001000;
;}
        lodi,r0 $04          ;r0 = $04;                               ;2,2
        brnr,r1 L0790        ;if (r4 != 0) goto L0790;                ;3,2
        rrl,r0               ;r0 <<= 1;                               ;2,1
L0790:
        iora,r0 BGCOLCOPY    ;r0 |= BGCOLCOPY; // motherboard RAM     ;4,3
        strr,r0 *$0791       ;*(*($0791)) = r0; // ROM operand        ;3,2
                             ;or, BGCOLCOPY = r0; // motherboard RAM

;*($1F00 + *($440 + r4)) = (*($1F66 + *($7CB + r4)) & %01111111) + *($7CD + r4);
        loda,r0 $07CB,r1     ;r0 = *($07CB + r4);                     ;4,3
        loda,r0 $1F66,r0     ;r0 = *($1F66 + r0);                     ;4,3
        andi,r0 $7F          ;r0 &= %01111111;                        ;2,2
        adda,r0 $07CD,r1     ;r0 += *($07CD + r4);                    ;4,3
        stra,r0 $1F00,r3     ;*($1F00 + r6) = r0;                     ;4,3

        retc,un              ;return;                                 ;3,1
L07A4:
        lodi,r0 $FE          ;r0 = $FE;                               ;2,2
        stra,r0 $1F03,r3     ;*($1F03 + r6) = r0 [254];               ;4,3
        retc,un              ;return;                                 ;3,1
;End of Interrupt Subroutine REUSEENEMY-----------------------------------
;Interrupt Subroutine ENEMYDRAWN------------------------------------------
ENEMYDRAWN:                                                          ;$7AA

;r5 is an argument (it holds a copy of BGCOLLIDE).
;this subroutine is just for options "01" and "02" (grand prix).

;reposition sprite(s)

;if (r5 & %00001000) // if sprite #0 has completed drawing
;{   r4 = 0;
;    gosub REUSEENEMY;
;} elif (r5 & %00000100) // if sprite #1 has completed drawing
;{   r4 = 1;
;    gosub REUSEENEMY;
;}
        lodi,r1 $00          ;r4 = $00;                               ;2,2
        tmi,r2  $08          ;test bits %00001000 of r5;              ;3,2
        bsta,eq REUSEENEMY   ;if == gosub REUSEENEMY;                 ;3,3
        lodi,r1 $01          ;r4 = $01;                               ;2,2
        tmi,r2  $04          ;test bits %00000100 of r5;              ;3,2
        bstr,eq *$07AF       ;if == gosub *($07AF); // ROM operand    ;3,2
                             ;or, if == gosub REUSEENEMY;

;now fix up colours

;r0 = *(&LTCOLOURS + LTDRAWN) + *(&RTCOLOURS + RTDRAWN);
        loda,r1 LTDRAWN      ;r4 = LTDRAWN; // motherboard RAM        ;4,3
        loda,r0 LTCOLOURS,r1 ;r0 = *($0485 + r4); // ROM data         ;4,3
        loda,r1 RTDRAWN      ;r4 = RTDRAWN; // motherboard RAM        ;4,3
        adda,r0 RTCOLOURS,r1 ;r0 += *($048A + r4); // ROM data        ;4,3
  
        loda,r1 INVERTCOLOURS;r4 = INVERTCOLOURS; // motherboard RAM  ;4,3
        bsta,un SETSPR01COLS ;gosub SETSPR01COLS;                     ;3,3

        bctr,un INTERRUPT_END;goto INTERRUPT_END;                     ;3,2
;Data for Subroutine REUSEENEMY-------------------------------------------
X07CB:
        db      $00, $04
X07CD:
        db      $00, $38
;End of Data for Subroutine REUSEENEMY------------------------------------
NOTVBLANK:                                                           ;$7CF
;This is really just part of INTERRUPT.
;r5 holds a copy of BGCOLLIDE.

;if (sprite #0 or #1 display is complete)
;{   switch (game)
;    {
;    case grand prix:
;        goto ENEMYDRAWN;
;    acase rally:
;        LTDRAWN++;
;        if     (SPRITE0AY < 7)
;        {   SPRITE0BX = *($1F80 + LTDRAWN) - (LTDRAWN * 3)    ; // left  barrier
;            SPRITE1BX = *($1F80 + LTDRAWN) + (LTDRAWN * 3)    ; // right barrier
;        } elif (SPRITE0AY < 14)
;        {   SPRITE0BX = *($1F80 + LTDRAWN) - (LTDRAWN * 3) - 1; // left  barrier
;            SPRITE1BX = *($1F80 + LTDRAWN) + (LTDRAWN * 3) + 1; // right barrier
;        } else
;        {   SPRITE0BX = *($1F80 + LTDRAWN) - (LTDRAWN * 3) - 2; // left  barrier
;            SPRITE1BX = *($1F80 + LTDRAWN) + (LTDRAWN * 3) + 2; // right barrier
;}   }   }
        andi,r2 $0C          ;r5 &= %00001100;                        ;2,2
        bctr,eq INTERRUPT_END;if == goto INTERRUPT_END;               ;3,2
        loda,r0 GAME         ;r0 = GAME; // motherboard RAM           ;4,3
        bctr,eq ENEMYDRAWN;  ;if == goto ENEMYDRAWN;                  ;3,2
        comi,r0 $01          ;compare r0 against $01;                 ;2,2
        bctr,gt INTERRUPT_END;if > goto INTERRUPT_END;                ;3,2
        loda,r1 LTDRAWN      ;r4 = LTDRAWN; // motherboard RAM        ;4,3
        addi,r1 $01          ;r4++;                                   ;2,2
        strr,r1 *$07DD       ;*(*($07DD)) = r4; // ROM operand        ;3,2
                             ;or, LTDRAWN = r4; // motherboard RAM
        lodz    r1           ;r0 = r4;                                ;2,1
        bsta,un L032F        ;gosub L032F;                            ;3,3
        loda,r0 $1F80,r1     ;r0 = *($1F80 + r4);                     ;4,3
        subz    r2           ;r0 -= r5;                               ;2,1
        stra,r0 SPRITE0BX    ;SPRITE0BX = r0; // hardware registers   ;4,3
        addz    r2           ;r0 += r5;                               ;2,1
        addz    r2           ;r0 += r5;                               ;2,1
        stra,r0 SPRITE1BX    ;SPRITE1BX = r0; // hardware registers   ;4,3

INTERRUPT_END:                                                       ;$7F3
;clean up and return to mainline code
        loda,r0 PRESERVEPSL  ;r0 = PRESERVEPSL; // motherboard RAM    ;4,3
        strz    r1           ;r4 = r0;                                ;2,1
        lpsl                 ;PSL = r0 [PRESERVEPSL];                 ;2,1
        loda,r0 PRESERVER0   ;r0 = PRESERVER0; // motherboard RAM     ;4,3
        andi,r1 $C0          ;r4 &= %11000000;                        ;2,2
        cpsl    $10          ;PSL &= %11101111; // use main reg. bank ;3,2
        rete,un              ;PSU &= ~PSU_II; return;                 ;3,1

        end

The alternate register bank (r4..r6) is used only by interrupt code.

Cars are as follows:
    left red    enemy     right purple enemy  (SPR01COLOURS of $1A)
    left green  enemy     right red    enemy  (SPR01COLOURS of $2B)
    left purple enemy     right blue   enemy  (SPR01COLOURS of $16)
    left yellow enemy     right cyan   enemy  (SPR01COLOURS of $0C)
         yellow                 blue          (SPR01COLOURS of $0E) - bad frames only?
    left blue   player    right green  player (SPR23COLOURS of $35)

Sprite #0 handles the left  enemy cars.
Sprite #1 handles the right enemy cars.
Sprite #2 handles the left  player.
Sprite #3 handles the right player.

Note that this disassembly focusses mostly on the default game option
("01"). Variables may have other uses in other modes.

Options are as follows:
                                 SCORELT      SCORERT
"01" - 2 players grand prix  - p1 distance, p2 distance
"02" - 1 player  grand prix  - p1 crashes,  p1 distance
"03" - 2 players rally       - ?,           ?
"04" - 1 player  rally       - p1 crashes,  p1 distance
"05" - 2 players easy slalom
"06" - 1 player  easy slalom
"07" - 2 players med. slalom
"08" - 1 player  med. slalom
"09" - 2 players hard slalom
"10" - 1 player  hard slalom

On a good frame:
 draw original enemies      (red,    purple)
 draw 1st duplicate enemies (green,  red   )
 draw 2nd duplicate enemies (purple, blue  )
 draw 3rd duplicate         (yellow, cyan  )

On a bad frame:
 none of the enemy duplicates are shown.
 also the colours of the enemy originals are wrong:
  yellow instead of red    for left  enemy original
  cyan   instead of purple for right enemy original
 ie. cars are using the colours that are "left over" from doing the last
  duplicates of previous frame.
 so, at the time of drawing the sprite, the new colour hasn't been written
  to the register.
 on some frames it writes $0E to SPRITE01COLOURS; why is this?
  because LTDRAWN is becoming $05.

The ROM is organized as follows:

Code Sections BOOT+TITLESCREEN         $000..$136 M
Mainline Subroutine HANDLESPRITE       $137..$18E M
Data for Code Section TITLESCREEN      $18F..$1A0 -
Code Section SLALOM                    $1A1..$26B ?
Data for Code Section SLALOM           $26C..$293 -
Subroutine L0294                       $294..$2B1 ?
Mainline Subroutine CLEARBG/SPRCOLBITS $2B2..$2CD M
Mainline Subroutine CHECKCOLLIDE       $2CE..$317 M
Data for Subroutine CHECKCOLLIDE       $318..$32E -
Subroutine L032F                       $32F..$340 both?
SubEnd L0341                           $341..$35E ?
Data for Code Section TITLESCREEN      $35F..$3E5 -
Data                                   $3E6..$48E -
SubEnd L048F                           $48F..$4F2 ?
Data                                   $4F3..$504 -
SubEnd CHECKBOUNDS                     $505..$52D ?
Data for SubEnd CHECKBOUNDS            $52E..$52F -
Interrupt Handler INTERRUPT            $530..$6DE I
Data for Interrupt Handler INTERRUPT   $6DF..$6E3 -
Subroutine SETSPR01COLS                $6E4..$6ED ?
RALLY                                  $6EE..$75E ?
Data for RALLY                         $75F..$766 -
Interrupt Subroutine REUSEENEMY        $767..$7A9 I
Interrupt Subroutine ENEMYDRAWN        $7AA..$7CA I
Data for Subroutine REUSEENEMY         $7CB..$7CE -
Interrupt Handler NOTVBLANK/INTERRUPT  $7CF..$7FF I

M = Mainline, I = Interrupt

Mainline Subroutine CLEARBGBITS:
 gosub()ed by: HANDLESPRITE, CHECKCOLLIDE
 entry points: CLEARBGBITS  (from $137 in HANDLESPRITE, $2DB in CHECKCOLLIDE)
               CLEARSPRBITS (from $2E8 in CHECKCOLLIDE)
 arguments:    r0
 calls:        nothing
 ends via:     rete
 result code:  r0
 scratch:      r2
 preserved:    r1, r3..r6
 pseudocode:
    inhibit interrupts;
    CLEARBITS = r0;
    switch (entrypoint)
    {
    case CLEARBGBITS:
        r0 &= BGCOLCOPY; // ie. r0 = CLEARBITS & BGCOLCOPY;
        if (r0 != 0) // something to clear
        {   BGCOLCOPY &= (CLEARBITS ^ %11111111);
            r0 = TRUE;
        }
    acase CLEARSPRBITS:
        r0 &= SPRCOLCOPY; // ie. r0 = CLEARBITS & BGCOLCOPY;
        if (r0 != 0) // something to clear
        {   SPRCOLCOPY &= (CLEARBITS ^ %11111111);
            r0 = TRUE;
    }   }
    enable interrupts; return r0;

Mainline Subroutine CHECKCOLLIDE:
 gosub()ed by: HANDLESPRITE
 entry point:  $2CE (from $14B in HANDLESPRITE)
 calls:        gosub to CLEARSPRBITS in CLEARBGBITS
 ends via:     retc

Definitions:
 Code Section: is goto()ed  to, and ends in goto().
 Subroutine:   is gosub()ed to, and ends in return().
 SubStart:     is gosub()ed to, and ends in goto().
 SubEnd:       is goto()ed  to, and ends in return().

at raster 280, $5C1 writes $0 to LTDRAWN
 sets SPRITE0BX for appropriate enemy car
at raster  17, $781 writes $1 to LTDRAWN
 sets SPRITE0BX for appropriate enemy car
 sets "sprite display #0" complete flag
 sets SPRITE0AX for left red enemy car
at raster  56, $781 writes $2 to LTDRAWN
 sets SPRITE0BX for appropriate enemy car
at raster  95, $781 writes $3 to LTDRAWN
 sets SPRITE0BX for appropriate enemy car
 sets SPRITE0BY = 254
at raster 134, $781 writes $4 to LTDRAWN
 sets SPRITE0BX for appropriate enemy car
at raster 280, $5C1 writes $0 to LTDRAWN, etc.
 sets SPRITE0BX for appropriate enemy car

SPRITEnAX and SPRITEnAY change according to the position of the left red
and right purple enemy cars.
  SPRITEnBX changes according to the positions of the following cars.
  Enemy cars are always a fixed vertical distance apart (SPRITEnBY of 28),
in the same order (with the left red and right purple cars at the top),
with respect to one another.

When the vblank interrupt is successfully generated, the next frame will
 be good.
When the vblank interrupt is suppressed, the next frame will be bad.
