(back to project page)

PennyArcade Disassembly

                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   ; Penny Arcade, by Bill Budge                                                  ;
                   ; Copyright 1979 Apple Computer, Inc.                                          ;
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   ; The user interface is written in Applesoft BASIC.  The machine code is       ;
                   ; embedded in the BASIC program.  It appears to have been designed to work on  ;
                   ; a machine with as little as 16KB of RAM.                                     ;
                   ;                                                                              ;
                   ; Collision detection is performed on hi-res pixels.  The data structures that ;
                   ; hold the game fields are only used to draw it before the game starts.        ;
                   ; Collisions with the paddles are handled specially, because the ball's bounce ;
                   ; angle depends on where on the paddle the ball hit.                           ;
                   ;                                                                              ;
                   ; The game allows you to set a difficulty from 1 to 10.  This affects how      ;
                   ; often the paddle position is updated.                                        ;
                   ;                                                                              ;
                   ; Paddles are 3 pixels wide and 24 pixels high.                                ;
                   ;                                                                              ;
                   ; Hitting ESC has the same effect as the ball going out of bounds.  This can   ;
                   ; be used if the ball gets stuck.                                              ;
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   ; Disassembly by Andy McFadden, using 6502bench SourceGen v1.9.1.              ;
                   ; Last updated 2025/01/25                                                      ;
                   ;                                                                              ;
                   ; The binary was extracted with CiderPress II from a recording of an audio     ;
                   ; cassette.                                                                    ;
                   ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
                   line_ptr        .eq     $00    {addr/2}   ;pointer to hi-res line
                   byte_offset     .eq     $02               ;offset into the hi-res line (0-39)
                   pixel_mask      .eq     $03               ;pixel bit mask
                   draw_flag       .eq     $04               ;0=erase, nonzero=draw
                   coll_flag       .eq     $05
                   coll_ctr        .eq     $07               ;collision counter
                   hptr            .eq     $1a    {addr/2}
                   delta_x         .eq     $3e
                   delta_y         .eq     $3f
                   pdl_drw_ctr     .eq     $40               ;paddle draw counter
                   left_pdl_new_y  .eq     $41               ;target position of left paddle
                   right_pdl_new_y .eq     $42               ;target position of right paddle
                   left_pdl_y      .eq     $43               ;current position of left paddle (top)
                   right_pdl_y     .eq     $44               ;current position of right paddle (top)
                   gravity_ctr     .eq     $d0               ;gravity counter
                   line_st_x       .eq     $d1
                   line_st_y       .eq     $d2
                   line_len        .eq     $d3
                   line_xc         .eq     $d4
                   line_yc         .eq     $d5
                   ball_xc         .eq     $e0               ;X coordinate of ball (~0-255)
                   ball_yc         .eq     $e1               ;Y coordinate of ball (~0-159)
                   new_ball_xc     .eq     $e2               ;new X coordinate of ball
                   new_ball_yc     .eq     $e3               ;new Y coordinate of ball
                   ball_xvel       .eq     $e4               ;ball X velocity
                   ball_yvel       .eq     $e5               ;ball Y velocity
                   ball_x_frac     .eq     $e6               ;ball fractional X position
                   ball_y_frac     .eq     $e7               ;ball fractional Y position
                   snd_pitch       .eq     $e8
                   snd_dur         .eq     $e9
                   pdl_mv_ctr      .eq     $ea               ;paddle movement counter
                   KBD             .eq     $c000             ;R last key pressed + 128
                   KBDSTRB         .eq     $c010             ;RW keyboard strobe
                   SPKR            .eq     $c030             ;RW toggle speaker
                   TXTCLR          .eq     $c050             ;RW display graphics
                   MIXSET          .eq     $c053             ;RW display split screen
                   HIRES           .eq     $c057             ;RW display hi-res graphics
                   MON_PREAD       .eq     $fb1e             ;read paddle specifed by X-reg, return in Y-reg

                   ; 
                   ; Applesoft BASIC program.  It starts with this:
                   ; 
                   ;  1020  POKE 175,32: POKE 176,19: POKE 105,32: POKE 106,19
                   ;  1030  POKE 107,32: POKE 108,19: POKE 109,32: POKE 110,19
                   ; 
                   ; This sets PRGEND ($af-b0), VARTAB ($69-6a), ARYTAB ($6b-6c), and STREND ($6d-
                   ; 6e) to $1320.
                   ; 
                   ; The BASIC code POKEs and CALLs various locations in the assembly code.  This
                   ; is documented separately.
                   ; 
                                   .addrs  $0801
0801: 07 08 64 00+                 .bulk   $07,$08,$64,$00,$b2,$00,$1d,$08,$6e,$00,$b2,$20,$20,$20,$20,$50
                                    +      $45,$4e,$4e,$59,$20,$41,$52,$43,$41,$44,$45,$00,$23,$08,$78,$00
                                    +      $b2,$00,$40,$08,$82,$00,$b2,$20,$20,$20,$20,$20,$20,$20,$20,$20
                                    +      $20,$42,$59,$20,$42,$49,$4c,$4c,$20,$42,$55,$44,$47,$45,$00,$46
                                    +      $08,$8c,$00,$b2,$00,$6a,$08,$fc,$03,$b9,$31,$37,$35,$2c,$33,$32
                                    +      $3a,$b9,$31,$37,$36,$2c,$31,$39,$3a,$b9,$31,$30,$35,$2c,$33,$32
                                    +      $3a,$b9,$31,$30,$36,$2c,$31,$39,$00,$8e,$08,$06,$04,$b9,$31,$30
                                    +      $37,$2c,$33,$32,$3a,$b9,$31,$30,$38,$2c,$31,$39,$3a,$b9,$31,$30
                                    +      $39,$2c,$33,$32,$3a,$b9,$31,$31,$30,$2c,$31,$39,$00,$9e,$08,$10
                                    +      $04,$b9,$c9,$31,$36,$32,$39,$38,$2c,$30,$3a,$97,$00,$bb,$08,$1a
                                    +      $04,$b9,$32,$31,$36,$2c,$30,$3a,$b2,$20,$20,$4f,$46,$46,$20,$54
                                    +      $48,$45,$20,$4f,$4e,$20,$45,$52,$52,$00,$f2,$08,$4c,$04,$89,$3a
                                    +      $8c,$c9,$39,$33,$36,$3a,$ba,$3a,$ba,$3a,$ba,$3a,$ba,$3a,$ba,$3a
                                    +      $ba,$3a,$ba,$22,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20
                                    +      $20,$50,$45,$4e,$4e,$59,$20,$41,$52,$43,$41,$44,$45,$22,$3a,$ba
                                    +      $00,$32,$09,$56,$04,$ba,$22,$20,$20,$20,$20,$20,$20,$20,$20,$20
                                    +      $20,$20,$20,$20,$20,$20,$20,$20,$20,$42,$59,$22,$3a,$ba,$3a,$ba
                                    +      $22,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$20,$42
                                    +      $49,$4c,$4c,$20,$42,$55,$44,$47,$45,$22,$3a,$ba,$3a,$ba,$3a,$ba
                                    +      $00,$5f,$09,$60,$04,$ba,$22,$20,$20,$43,$4f,$50,$59,$52,$49,$47
                                    +      $48,$54,$20,$31,$39,$37,$39,$20,$20,$41,$50,$50,$4c,$45,$20,$43
                                    +      $4f,$4d,$50,$55,$54,$45,$52,$20,$49,$4e,$43,$2e,$22,$00,$a4,$09
                                    +      $6a,$04,$ba,$3a,$a2,$32,$33,$3a,$ba,$22,$20,$20,$20,$20,$20,$50
                                    +      $52,$45,$53,$53,$20,$27,$52,$45,$54,$55,$52,$4e,$27,$20,$54,$4f
                                    +      $20,$43,$4f,$4e,$54,$49,$4e,$55,$45,$2e,$2e,$2e,$22,$3b,$3a,$be
                                    +      $41,$24,$3a,$ad,$e6,$28,$41,$24,$29,$d1,$cf,$31,$33,$c4,$31,$31
                                    +      $33,$30,$00,$aa,$09,$74,$04,$97,$00,$cd,$09,$7e,$04,$a2,$33,$3a
                                    +      $96,$31,$31,$3a,$ba,$22,$2a,$2a,$2a,$20,$49,$4e,$53,$54,$52,$55
                                    +      $43,$54,$49,$4f,$4e,$53,$20,$2a,$2a,$2a,$22,$00,$d3,$09,$88,$04
                                    +      $ba,$00,$04,$0a,$d0,$07,$ba,$3a,$ba,$22,$20,$54,$48,$45,$20,$4f
                                    +      $42,$4a,$45,$43,$54,$20,$4f,$46,$20,$54,$48,$45,$20,$47,$41,$4d
                                    +      $45,$20,$49,$53,$20,$54,$4f,$20,$47,$45,$54,$20,$54,$48,$45,$22
                                    +      $3a,$ba,$00,$60,$0a,$da,$07,$ba,$22,$20,$42,$41,$4c,$4c,$20,$49
                                    +      $4e,$54,$4f,$20,$54,$48,$45,$20,$4f,$50,$50,$4f,$4e,$45,$4e,$54
                                    +      $53,$20,$47,$4f,$41,$4c,$2e,$20,$44,$4f,$20,$54,$48,$49,$53,$22
                                    +      $3a,$ba,$3a,$ba,$22,$20,$46,$49,$56,$45,$20,$54,$49,$4d,$45,$53
                                    +      $20,$41,$4e,$44,$20,$59,$4f,$55,$20,$57,$49,$4e,$21,$20,$20,$55
                                    +      $53,$45,$20,$54,$48,$45,$20,$47,$41,$4d,$45,$22,$3a,$ba,$00,$b2
                                    +      $0a,$e4,$07,$ba,$22,$20,$50,$41,$44,$44,$4c,$45,$53,$20,$54,$4f
                                    +      $20,$44,$45,$46,$45,$4e,$44,$20,$59,$4f,$55,$52,$20,$47,$4f,$41
                                    +      $4c,$2e,$22,$3a,$ba,$3a,$ba,$3a,$ba,$22,$20,$4e,$45,$58,$54,$20
                                    +      $59,$4f,$55,$20,$57,$49,$4c,$4c,$20,$42,$45,$20,$53,$48,$4f,$57
                                    +      $4e,$20,$41,$20,$53,$45,$52,$49,$45,$53,$20,$4f,$46,$22,$3a,$ba
                                    +      $00,$0e,$0b,$ee,$07,$ba,$22,$20,$50,$4c,$41,$59,$49,$4e,$47,$20
                                    +      $46,$49,$45,$4c,$44,$53,$20,$2d,$2d,$20,$54,$4f,$20,$53,$45,$4c
                                    +      $45,$43,$54,$20,$4f,$4e,$45,$2c,$20,$50,$52,$45,$53,$53,$22,$3a
                                    +      $ba,$3a,$ba,$22,$20,$41,$4e,$59,$20,$4b,$45,$59,$20,$57,$48,$45
                                    +      $4e,$20,$54,$48,$45,$20,$46,$49,$45,$4c,$44,$20,$54,$48,$41,$54
                                    +      $20,$59,$4f,$55,$20,$57,$41,$4e,$54,$22,$3a,$ba,$00,$24,$0b,$f8
                                    +      $07,$ba,$22,$20,$49,$53,$20,$44,$49,$53,$50,$4c,$41,$59,$45,$44
                                    +      $2e,$22,$00,$6a,$0b,$02,$08,$ba,$3a,$a2,$32,$33,$3a,$ba,$22,$20
                                    +      $20,$20,$20,$20,$20,$50,$52,$45,$53,$53,$20,$27,$52,$45,$54,$55
                                    +      $52,$4e,$27,$20,$54,$4f,$20,$43,$4f,$4e,$54,$49,$4e,$55,$45,$2e
                                    +      $2e,$2e,$22,$3b,$3a,$be,$41,$24,$3a,$ad,$e6,$28,$41,$24,$29,$d1
                                    +      $cf,$31,$33,$c4,$32,$30,$35,$30,$00,$74,$0b,$fa,$0f,$8c,$c9,$39
                                    +      $33,$36,$00,$97,$0b,$88,$13,$8c,$37,$30,$36,$32,$3a,$8c,$37,$34
                                    +      $36,$32,$3a,$81,$49,$d0,$31,$c1,$32,$30,$30,$30,$3a,$82,$49,$3a
                                    +      $8c,$37,$30,$36,$32,$00,$a1,$0b,$92,$13,$b0,$35,$39,$30,$30,$00
                                    +      $ac,$0b,$9c,$13,$47,$41,$4d,$45,$d0,$30,$00,$c1,$0b,$a6,$13,$b9
                                    +      $32,$32,$34,$2c,$31,$38,$32,$3a,$b9,$32,$32,$35,$2c,$32,$37,$00
                                    +      $cb,$0b,$b0,$13,$8c,$36,$39,$39,$34,$00,$e7,$0b,$ba,$13,$a2,$32
                                    +      $33,$3a,$96,$31,$33,$3a,$ba,$22,$42,$55,$4d,$50,$45,$52,$20,$50
                                    +      $4f,$4f,$4c,$20,$22,$00,$f1,$0b,$c4,$13,$b0,$35,$32,$30,$30,$00
                                    +      $05,$0c,$ce,$13,$b9,$32,$32,$34,$2c,$39,$38,$3a,$b9,$32,$32,$35
                                    +      $2c,$32,$38,$00,$0f,$0c,$d8,$13,$8c,$36,$39,$39,$34,$00,$2b,$0c
                                    +      $e2,$13,$a2,$32,$33,$3a,$96,$31,$33,$3a,$ba,$22,$20,$20,$20,$48
                                    +      $4f,$43,$4b,$45,$59,$20,$20,$20,$22,$00,$35,$0c,$ec,$13,$b0,$35
                                    +      $32,$30,$30,$00,$4a,$0c,$f6,$13,$b9,$32,$32,$34,$2c,$31,$35,$38
                                    +      $3a,$b9,$32,$32,$35,$2c,$32,$38,$00,$54,$0c,$00,$14,$8c,$36,$39
                                    +      $39,$34,$00,$71,$0c,$0a,$14,$a2,$32,$33,$3a,$96,$31,$33,$3a,$ba
                                    +      $22,$20,$20,$53,$43,$52,$41,$4d,$42,$4c,$45,$20,$20,$20,$22,$00
                                    +      $7b,$0c,$14,$14,$b0,$35,$32,$30,$30,$00,$90,$0c,$1e,$14,$b9,$32
                                    +      $32,$34,$2c,$32,$35,$30,$3a,$b9,$32,$32,$35,$2c,$32,$38,$00,$9a
                                    +      $0c,$28,$14,$8c,$36,$39,$39,$34,$00,$b6,$0c,$32,$14,$a2,$32,$33
                                    +      $3a,$96,$31,$33,$3a,$ba,$22,$20,$20,$20,$54,$45,$4e,$4e,$49,$53
                                    +      $20,$20,$20,$22,$00,$c0,$0c,$3c,$14,$b0,$35,$32,$30,$30,$00,$ca
                                    +      $0c,$46,$14,$ab,$35,$30,$32,$30,$00,$da,$0c,$50,$14,$47,$41,$4d
                                    +      $45,$d0,$47,$41,$4d,$45,$c8,$31,$00,$e7,$0c,$5a,$14,$81,$49,$d0
                                    +      $31,$c1,$31,$30,$30,$00,$f7,$0c,$64,$14,$58,$d0,$e2,$28,$c9,$31
                                    +      $36,$33,$38,$34,$29,$00,$05,$0d,$6e,$14,$b9,$c9,$31,$36,$33,$36
                                    +      $38,$2c,$30,$00,$16,$0d,$78,$14,$ad,$58,$d1,$d0,$31,$32,$37,$c4
                                    +      $35,$32,$37,$30,$00,$1c,$0d,$82,$14,$a1,$00,$26,$0d,$8c,$14,$ab
                                    +      $35,$33,$30,$30,$00,$2d,$0d,$96,$14,$82,$49,$00,$37,$0d,$a0,$14
                                    +      $8c,$37,$30,$36,$32,$00,$3d,$0d,$aa,$14,$b1,$00,$5a,$0d,$b4,$14
                                    +      $ba,$22,$57,$48,$41,$54,$20,$44,$49,$46,$46,$49,$43,$55,$4c,$54
                                    +      $59,$20,$4c,$45,$56,$45,$4c,$22,$00,$7d,$0d,$be,$14,$84,$22,$28
                                    +      $31,$2d,$45,$41,$53,$49,$45,$53,$54,$2c,$20,$31,$30,$2d,$48,$41
                                    +      $52,$44,$45,$53,$54,$29,$22,$3b,$44,$46,$46,$00,$94,$0d,$c8,$14
                                    +      $ad,$44,$46,$46,$cf,$31,$30,$ce,$44,$46,$46,$d1,$31,$c4,$35,$33
                                    +      $30,$30,$00,$a2,$0d,$d2,$14,$53,$31,$d0,$30,$3a,$53,$32,$d0,$30
                                    +      $00,$b6,$0d,$dc,$14,$b9,$32,$32,$38,$2c,$31,$32,$37,$3a,$b9,$32
                                    +      $32,$39,$2c,$30,$00,$c5,$0d,$e6,$14,$55,$50,$44,$4f,$57,$4e,$d0
                                    +      $31,$32,$30,$00,$d6,$0d,$f0,$14,$44,$46,$46,$d0,$31,$30,$c8,$44
                                    +      $46,$46,$ca,$35,$00,$ee,$0d,$fa,$14,$b9,$36,$37,$36,$32,$2c,$44
                                    +      $46,$46,$3a,$b9,$36,$38,$30,$30,$2c,$44,$46,$46,$00,$0c,$0e,$04
                                    +      $15,$b9,$36,$37,$32,$33,$2c,$55,$50,$44,$4f,$57,$4e,$3a,$b9,$36
                                    +      $37,$32,$37,$2c,$55,$50,$44,$4f,$57,$4e,$00,$32,$0e,$0e,$15,$b9
                                    +      $36,$37,$33,$32,$2c,$32,$35,$36,$c9,$55,$50,$44,$4f,$57,$4e,$3a
                                    +      $b9,$36,$37,$33,$36,$2c,$32,$35,$36,$c9,$55,$50,$44,$4f,$57,$4e
                                    +      $00,$43,$0e,$18,$15,$ad,$47,$41,$4d,$45,$d0,$32,$c4,$35,$34,$34
                                    +      $30,$00,$53,$0e,$22,$15,$4c,$45,$d0,$37,$3a,$52,$45,$d0,$32,$34
                                    +      $37,$00,$6b,$0e,$2c,$15,$b9,$36,$37,$37,$31,$2c,$31,$38,$39,$3a
                                    +      $b9,$36,$38,$33,$30,$2c,$31,$38,$39,$00,$75,$0e,$36,$15,$ab,$35
                                    +      $34,$36,$30,$00,$86,$0e,$40,$15,$4c,$45,$d0,$39,$30,$3a,$52,$45
                                    +      $d0,$31,$36,$36,$00,$9e,$0e,$4a,$15,$b9,$36,$37,$37,$31,$2c,$32
                                    +      $30,$33,$3a,$b9,$36,$38,$33,$30,$2c,$32,$30,$33,$00,$b4,$0e,$54
                                    +      $15,$b9,$36,$35,$38,$39,$2c,$4c,$45,$3a,$b9,$36,$36,$35,$32,$2c
                                    +      $52,$45,$00,$e4,$0e,$5e,$15,$b9,$36,$36,$38,$30,$2c,$4c,$45,$c9
                                    +      $33,$3a,$b9,$36,$36,$38,$34,$2c,$4c,$45,$c8,$33,$3a,$b9,$36,$36
                                    +      $38,$38,$2c,$52,$45,$c9,$33,$3a,$b9,$36,$36,$39,$32,$2c,$52,$45
                                    +      $c8,$33,$00,$07,$0f,$68,$15,$84,$22,$53,$48,$4f,$55,$4c,$44,$20
                                    +      $54,$48,$45,$52,$45,$20,$42,$45,$20,$47,$52,$41,$56,$49,$54,$59
                                    +      $3f,$22,$3b,$41,$24,$00,$0d,$0f,$6d,$15,$97,$00,$1f,$0f,$72,$15
                                    +      $b9,$36,$35,$2c,$32,$37,$3a,$b9,$36,$37,$2c,$32,$37,$00,$25,$0f
                                    +      $7c,$15,$ba,$00,$35,$0f,$86,$15,$81,$49,$d0,$32,$37,$c1,$31,$31
                                    +      $c7,$c9,$38,$00,$45,$0f,$90,$15,$b9,$36,$36,$2c,$49,$3a,$b9,$36
                                    +      $38,$2c,$49,$00,$4f,$0f,$9a,$15,$8c,$36,$35,$32,$36,$00,$56,$0f
                                    +      $a4,$15,$82,$49,$00,$5e,$0f,$a9,$15,$a2,$32,$33,$00,$81,$0f,$ae
                                    +      $15,$ba,$22,$50,$4c,$41,$59,$45,$52,$20,$23,$31,$22,$3b,$3a,$96
                                    +      $32,$37,$3a,$ba,$22,$50,$4c,$41,$59,$45,$52,$20,$23,$32,$22,$00
                                    +      $a7,$0f,$b8,$15,$b9,$32,$32,$34,$2c,$31,$32,$38,$3a,$b9,$32,$32
                                    +      $35,$2c,$33,$38,$3a,$b9,$32,$32,$36,$2c,$31,$32,$38,$3a,$b9,$32
                                    +      $32,$37,$2c,$33,$38,$00,$c0,$0f,$c2,$15,$a2,$32,$34,$3a,$96,$34
                                    +      $3a,$ba,$53,$31,$3b,$3a,$96,$33,$31,$3a,$ba,$53,$32,$3b,$00,$d4
                                    +      $0f,$cc,$15,$ad,$53,$31,$d0,$35,$ce,$53,$32,$d0,$35,$c4,$35,$38
                                    +      $34,$30,$00,$ea,$0f,$d6,$15,$ad,$e8,$28,$41,$24,$2c,$31,$29,$d0
                                    +      $22,$59,$22,$c4,$35,$37,$30,$30,$00,$f7,$0f,$e0,$15,$81,$49,$d0
                                    +      $31,$c1,$32,$30,$30,$00,$01,$10,$ea,$15,$8c,$36,$35,$32,$36,$00
                                    +      $08,$10,$f4,$15,$82,$49,$00,$12,$10,$fe,$15,$8c,$36,$37,$34,$38
                                    +      $00,$1c,$10,$08,$16,$b0,$35,$37,$35,$30,$00,$27,$10,$12,$16,$b9
                                    +      $32,$32,$39,$2c,$30,$00,$3f,$10,$1c,$16,$ad,$e2,$28,$32,$32,$34
                                    +      $29,$d1,$31,$32,$37,$c4,$53,$32,$d0,$53,$32,$c8,$31,$00,$57,$10
                                    +      $26,$16,$ad,$e2,$28,$32,$32,$34,$29,$cf,$31,$32,$37,$c4,$53,$31
                                    +      $d0,$53,$31,$c8,$31,$00,$61,$10,$30,$16,$8c,$36,$38,$38,$32,$00
                                    +      $6b,$10,$3a,$16,$ab,$35,$35,$36,$30,$00,$78,$10,$44,$16,$81,$49
                                    +      $d0,$31,$c1,$32,$30,$30,$00,$82,$10,$4e,$16,$8c,$36,$35,$32,$36
                                    +      $00,$89,$10,$58,$16,$82,$49,$00,$93,$10,$62,$16,$8c,$36,$37,$38
                                    +      $36,$00,$9d,$10,$6c,$16,$ab,$35,$36,$34,$30,$00,$a8,$10,$76,$16
                                    +      $81,$49,$d0,$31,$c1,$32,$00,$b4,$10,$80,$16,$81,$4a,$d0,$31,$c1
                                    +      $31,$30,$00,$ce,$10,$8a,$16,$5a,$d0,$e2,$28,$c9,$31,$36,$33,$33
                                    +      $36,$29,$c9,$e2,$28,$c9,$31,$36,$33,$33,$36,$29,$00,$d5,$10,$94
                                    +      $16,$82,$4a,$00,$e0,$10,$9e,$16,$81,$4a,$d0,$31,$c1,$35,$00,$0e
                                    +      $11,$a8,$16,$5a,$d0,$e2,$28,$c9,$31,$36,$33,$33,$36,$29,$c9,$e2
                                    +      $28,$c9,$31,$36,$33,$33,$36,$29,$c8,$e2,$28,$c9,$31,$36,$33,$33
                                    +      $36,$29,$c9,$e2,$28,$c9,$31,$36,$33,$33,$36,$29,$00,$15,$11,$b2
                                    +      $16,$82,$4a,$00,$1c,$11,$bc,$16,$82,$49,$00,$22,$11,$c6,$16,$b1
                                    +      $00,$39,$11,$d0,$16,$ba,$3a,$84,$22,$4d,$4f,$52,$45,$20,$50,$4f
                                    +      $4e,$47,$3f,$22,$3b,$41,$24,$00,$3f,$11,$d5,$16,$97,$00,$4d,$11
                                    +      $da,$16,$ba,$3a,$ba,$3a,$8c,$37,$30,$36,$32,$00,$63,$11,$e4,$16
                                    +      $ad,$e8,$28,$41,$24,$2c,$31,$29,$d0,$22,$59,$22,$c4,$35,$30,$32
                                    +      $30,$00,$7b,$11,$ee,$16,$b9,$c9,$31,$36,$33,$30,$33,$2c,$30,$3a
                                    +      $b9,$c9,$31,$36,$32,$39,$38,$2c,$30,$00,$8d,$11,$f8,$16,$8c,$c9
                                    +      $39,$33,$36,$3a,$ba,$22,$42,$59,$45,$21,$22,$00,$93,$11,$02,$17
                                    +      $80,$00,$99,$11,$0c,$17,$b2,$00,$bb,$11,$84,$17,$b9,$c9,$31,$36
                                    +      $32,$39,$37,$2c,$30,$3a,$b9,$c9,$31,$36,$33,$30,$31,$2c,$30,$3a
                                    +      $b9,$c9,$31,$36,$33,$30,$34,$2c,$30,$00,$c1,$11,$8e,$17,$b1,$00
                                    +      $00,$00
                   ; 
                   ; Unused space.  This leaves some room for the BASIC program to expand before it
                   ; runs into the area used for variables.
                   ; 
11c3: 08 d3 a8 68+                 .junk   349
                   ; 
                   ; Applesoft variable storage starts here.
                   ; 
                   ; Without garbage collection, strings will eventually fill the space and
                   ; overwrite the code.
                   ; 
1320: 41 80 01 fd+                 .junk   752

                   ; 
                   ; Computes the address of a line on the hi-res screen.
                   ; 
                   ; On entry:
                   ;   A-reg: line number (0-191)
                   ; 
                   ; On exit:
                   ;   $00/01: pointer to start of line
                   ; 
1610: 48           GetLineAddr     pha                       ;put two copies of the line number on the stack
1611: 48                           pha
1612: 29 3f                        and     #%00111111        ;get the low 5 bits (0-63)
1614: a8                           tay
1615: b9 35 16                     lda     hires_line_hi,y   ;get the base value from the table
1618: 85 01                        sta     line_ptr+1        ;set the high byte
161a: 68                           pla                       ;get full number
161b: 29 c0                        and     #%11000000        ;look at the two high bits; should be 00/01/10
161d: f0 08                        beq     @SetLow           ;it's 00, branch
161f: 10 04                        bpl     @SetLow28         ;high is clear, branch (low byte is $00 or $80)
1621: a9 50                        lda     #$50              ;line range 128-191, low byte is $50 or $d0
1623: d0 02                        bne     @SetLow

1625: a9 28        @SetLow28       lda     #$28              ;line range 64-127, low byte is $28 or $a8
1627: 85 00        @SetLow         sta     line_ptr          ;set the low byte
1629: 68                           pla                       ;check the line number again
162a: 29 08                        and     #%00001000        ;is it 0-7, 16-23, etc?
162c: f0 06                        beq     @Return           ;yes, bail
162e: a5 00                        lda     line_ptr          ;no, it's 8-15, 24-31, etc.
1630: 09 80                        ora     #$80              ;add $80 to the low byte
1632: 85 00                        sta     line_ptr
1634: 60           @Return         rts

1635: 20 24 28 2c+ hires_line_hi   .bulk   $20,$24,$28,$2c,$30,$34,$38,$3c,$20,$24,$28,$2c,$30,$34,$38,$3c
                                    +      $21,$25,$29,$2d,$31,$35,$39,$3d,$21,$25,$29,$2d,$31,$35,$39,$3d
                                    +      $22,$26,$2a,$2e,$32,$36,$3a,$3e,$22,$26,$2a,$2e,$32,$36,$3a,$3e
                                    +      $23,$27,$2b,$2f,$33,$37,$3b,$3f,$23,$27,$2b,$2f,$33,$37,$3b,$3f

                   ; 
                   ; Calculates the line offset and bit mask for the pixel at the specified
                   ; coordinate.
                   ; 
                   ; On entry:
                   ;   A-reg: X coordinate (0-255)
                   ; 
                   ; On exit:
                   ;   $02: byte offset (0-39)
                   ;   $03: bit mask
                   ; 
1675: a8           CalcOffAndMask  tay
1676: be 90 16                     ldx     div7,y            ;divide X coordinate by 7 -> floor(XC/7)
1679: 86 02                        stx     byte_offset       ;use that as hi-res byte offset
167b: 86 03                        stx     pixel_mask        ;store it temporarily so we can shift it
167d: 06 03                        asl     pixel_mask        ;multiply -> floor(XC/7) * 8
167f: 06 03                        asl     pixel_mask
1681: 06 03                        asl     pixel_mask
1683: 18                           clc
1684: 65 02                        adc     byte_offset       ;add X coord to byte offset -> XC + floor(XC/7)
1686: 38                           sec
1687: e5 03                        sbc     pixel_mask        ;subtract -> (XC + floor(XC/7)) - (floor(XC/7) * 8)
1689: a8                           tay                       ; which would be zero without the floor() op
168a: b9 90 17                     lda     pixel_bits,y      ; but instead gives us the remainder (0-6)
168d: 85 03                        sta     pixel_mask        ;set the bit mask for the pixel
168f: 60                           rts

                   ; 
                   ; Table lookup to compute N/7, for N=[0,255].
                   ; 
1690: 00 00 00 00+ div7            .bulk   $00,$00,$00,$00,$00,$00,$00
1697: 01 01 01 01+                 .bulk   $01,$01,$01,$01,$01,$01,$01
169e: 02 02 02 02+                 .bulk   $02,$02,$02,$02,$02,$02,$02
16a5: 03 03 03 03+                 .bulk   $03,$03,$03,$03,$03,$03,$03
16ac: 04 04 04 04+                 .bulk   $04,$04,$04,$04,$04,$04,$04
16b3: 05 05 05 05+                 .bulk   $05,$05,$05,$05,$05,$05,$05
16ba: 06 06 06 06+                 .bulk   $06,$06,$06,$06,$06,$06,$06
16c1: 07 07 07 07+                 .bulk   $07,$07,$07,$07,$07,$07,$07
16c8: 08 08 08 08+                 .bulk   $08,$08,$08,$08,$08,$08,$08
16cf: 09 09 09 09+                 .bulk   $09,$09,$09,$09,$09,$09,$09
16d6: 0a 0a 0a 0a+                 .bulk   $0a,$0a,$0a,$0a,$0a,$0a,$0a
16dd: 0b 0b 0b 0b+                 .bulk   $0b,$0b,$0b,$0b,$0b,$0b,$0b
16e4: 0c 0c 0c 0c+                 .bulk   $0c,$0c,$0c,$0c,$0c,$0c,$0c
16eb: 0d 0d 0d 0d+                 .bulk   $0d,$0d,$0d,$0d,$0d,$0d,$0d
16f2: 0e 0e 0e 0e+                 .bulk   $0e,$0e,$0e,$0e,$0e,$0e,$0e
16f9: 0f 0f 0f 0f+                 .bulk   $0f,$0f,$0f,$0f,$0f,$0f,$0f
1700: 10 10 10 10+                 .bulk   $10,$10,$10,$10,$10,$10,$10
1707: 11 11 11 11+                 .bulk   $11,$11,$11,$11,$11,$11,$11
170e: 12 12 12 12+                 .bulk   $12,$12,$12,$12,$12,$12,$12
1715: 13 13 13 13+                 .bulk   $13,$13,$13,$13,$13,$13,$13
171c: 14 14 14 14+                 .bulk   $14,$14,$14,$14,$14,$14,$14
1723: 15 15 15 15+                 .bulk   $15,$15,$15,$15,$15,$15,$15
172a: 16 16 16 16+                 .bulk   $16,$16,$16,$16,$16,$16,$16
1731: 17 17 17 17+                 .bulk   $17,$17,$17,$17,$17,$17,$17
1738: 18 18 18 18+                 .bulk   $18,$18,$18,$18,$18,$18,$18
173f: 19 19 19 19+                 .bulk   $19,$19,$19,$19,$19,$19,$19
1746: 1a 1a 1a 1a+                 .bulk   $1a,$1a,$1a,$1a,$1a,$1a,$1a
174d: 1b 1b 1b 1b+                 .bulk   $1b,$1b,$1b,$1b,$1b,$1b,$1b
1754: 1c 1c 1c 1c+                 .bulk   $1c,$1c,$1c,$1c,$1c,$1c,$1c
175b: 1d 1d 1d 1d+                 .bulk   $1d,$1d,$1d,$1d,$1d,$1d,$1d
1762: 1e 1e 1e 1e+                 .bulk   $1e,$1e,$1e,$1e,$1e,$1e,$1e
1769: 1f 1f 1f 1f+                 .bulk   $1f,$1f,$1f,$1f,$1f,$1f,$1f
1770: 20 20 20 20+                 .bulk   $20,$20,$20,$20,$20,$20,$20
1777: 21 21 21 21+                 .bulk   $21,$21,$21,$21,$21,$21,$21
177e: 22 22 22 22+                 .bulk   $22,$22,$22,$22,$22,$22,$22
1785: 23 23 23 23+                 .bulk   $23,$23,$23,$23,$23,$23,$23
178c: 24 24 24 24                  .bulk   $24,$24,$24,$24
                   ; 
                   ; Hi-res single-pixel masks.
                   ; 
1790: 01 02 04 08+ pixel_bits      .bulk   $01,$02,$04,$08,$10,$20,$40

                   ; 
                   ; Draws or erases one column of the ball (3 pixels).  This takes a horizontal
                   ; offset as an argument, so we can just the position by one column.
                   ; 
                   ; On entry:
                   ;   $e0: X coordinate
                   ;   $e1: center Y coordinate
                   ;   A-reg: X coordinate delta (usually 1 or -1)
                   ; 
                   DrawEraseBallCol
1797: 18                           clc
1798: 65 e0                        adc     ball_xc           ;add offset to X coordinate
179a: 20 75 16                     jsr     CalcOffAndMask    ;calculate the horizontal offset and pixel mask
179d: a5 e1                        lda     ball_yc           ;get Y coordinate
179f: 20 10 16                     jsr     GetLineAddr       ;get row address
17a2: 20 f0 17                     jsr     DrawErasePixel    ;draw/erase that pixel
17a5: a5 e1                        lda     ball_yc
17a7: 18                           clc
17a8: 69 01                        adc     #$01              ;repeat for pixel below
17aa: 20 10 16                     jsr     GetLineAddr
17ad: 20 f0 17                     jsr     DrawErasePixel
17b0: a5 e1                        lda     ball_yc
17b2: 38                           sec
17b3: e9 01                        sbc     #$01              ;repeat for pixel above
17b5: 20 10 16                     jsr     GetLineAddr
17b8: 20 f0 17                     jsr     DrawErasePixel
17bb: 60                           rts

                   ; 
                   ; Draws or erases one row of the ball (3 pixels).  This takes an offset as an
                   ; argument, so we can adjust the position by one row.
                   ; 
                   ; On entry:
                   ;   $e0: center X coordinate
                   ;   $e1: Y coordinate
                   ;   A-reg: Y coordinate delta (usually 1 or -1)
                   ; 
                   DrawEraseBallRow
17bc: 18                           clc
17bd: 65 e1                        adc     ball_yc           ;add offset to Y coordinate
17bf: 20 10 16                     jsr     GetLineAddr       ;calculate the row address
17c2: a5 e0                        lda     ball_xc           ;get X coordinate
17c4: 20 75 16                     jsr     CalcOffAndMask    ;calculate byte offset and pixel mask
17c7: 20 f0 17                     jsr     DrawErasePixel    ;draw/erase that pixel
17ca: a5 e0                        lda     ball_xc
17cc: 18                           clc
17cd: 69 01                        adc     #$01              ;repeat for pixel to the right
17cf: 20 75 16                     jsr     CalcOffAndMask
17d2: 20 f0 17                     jsr     DrawErasePixel
17d5: a5 e0                        lda     ball_xc
17d7: 38                           sec
17d8: e9 01                        sbc     #$01              ;repeat for pixel to the left
17da: 20 75 16                     jsr     CalcOffAndMask
17dd: 20 f0 17                     jsr     DrawErasePixel
17e0: 60                           rts

                   ; 
                   ; Draws or erases the ball.
                   ; 
                   ; Instead of drawing the entire 3x3 ball, we only draw the rows or columns that
                   ; change.  The movement delta is applied to the ball's position.
                   ; 
17e1: a5 3e        DrawEraseBall   lda     delta_x           ;did the X position change?
17e3: f0 03                        beq     @NotCol           ;no, branch
17e5: 20 97 17                     jsr     DrawEraseBallCol  ;yes, draw or erase one column
17e8: a5 3f        @NotCol         lda     delta_y           ;did the Y position change?
17ea: f0 03                        beq     @Return           ;no, branch
17ec: 20 bc 17                     jsr     DrawEraseBallRow  ;yes, draw or erase one row
17ef: 60           @Return         rts

                   ; 
                   ; Draws or erases one pixel.
                   ; 
                   ; On entry:
                   ;   $00-01: hi-res line offset
                   ;   $02: byte offset in line
                   ;   $03: pixel bit mask
                   ;   $04: draw flag (0=erase)
                   ; 
17f0: a4 02        DrawErasePixel  ldy     byte_offset       ;get offset into hi-res line (0-39)
17f2: a5 03                        lda     pixel_mask        ;get pixel bits
17f4: a6 04                        ldx     draw_flag         ;are we drawing or erasing?
17f6: d0 07                        bne     @DoDraw           ;drawing, branch
17f8: 49 ff                        eor     #$ff              ;invert pixel mask
17fa: 31 00                        and     (line_ptr),y      ;clear bits
17fc: 91 00                        sta     (line_ptr),y      ;update screen
17fe: 60                           rts

17ff: 11 00        @DoDraw         ora     (line_ptr),y      ;merge bits
1801: 91 00                        sta     (line_ptr),y      ;update screen
1803: 60                           rts

                   ; 
                   ; Erases part of the ball from its current position, then draws it in its new
                   ; position.  Because the ball moves at most one pixel per frame, we only need to
                   ; redraw one row and/or one column.
                   ; 
                   ; Replaces the "current" coordinates with "new" values.
                   ; 
                   ; This is also used to draw the paddles, which can be treated as very tall
                   ; balls.
                   ; 
                   ; On entry:
                   ;   $e0: ball X position (current)
                   ;   $e1: ball Y position (current)
                   ;   $e2: ball X position (new)
                   ;   $e3: ball Y position (new)
                   ; 
                   ; On exit:
                   ;   $3e: X delta
                   ;   $3f: Y delta
                   ; 
1804: a5 e0        RedrawBall      lda     ball_xc           ;compute inverse change in X position
1806: 38                           sec
1807: e5 e2                        sbc     new_ball_xc
1809: 85 3e                        sta     delta_x
180b: a5 e1                        lda     ball_yc           ;compute inverse change in Y position
180d: 38                           sec
180e: e5 e3                        sbc     new_ball_yc
1810: 85 3f                        sta     delta_y
                   ; 
1812: a9 00                        lda     #$00
1814: 85 04                        sta     draw_flag         ;configure to erase
1816: 20 e1 17                     jsr     DrawEraseBall     ;erase row and/or column, using backward delta
                   ; Invert delta_x/delta_y, so it now represents the delta from the old position
                   ; to the new.
1819: a5 3e                        lda     delta_x           ;set delta_x = -delta_x
181b: 49 ff                        eor     #$ff
181d: 85 3e                        sta     delta_x
181f: e6 3e                        inc     delta_x
1821: a5 3f                        lda     delta_y           ;set delta_y = -delta_y
1823: 49 ff                        eor     #$ff
1825: 85 3f                        sta     delta_y
1827: e6 3f                        inc     delta_y
                   ; 
1829: a5 e2                        lda     new_ball_xc       ;copy "new" X/Y to "current" X/Y
182b: 85 e0                        sta     ball_xc
182d: a5 e3                        lda     new_ball_yc
182f: 85 e1                        sta     ball_yc
1831: a9 ff                        lda     #$ff
1833: 85 04                        sta     draw_flag         ;configure to draw
1835: 20 e1 17                     jsr     DrawEraseBall     ;draw row and/or column, using forward delta
1838: 60                           rts

                   ; 
                   ; Tests to see if a screen pixel is set.
                   ; 
                   ; On entry:
                   ;   $00: hi-res line address
                   ;   $02: byte offset in line
                   ;   $03: pixel mask
                   ; 
                   ; On exit:
                   ;   $07: incremented if pixel is set
                   ; 
1839: a4 02        TestPixel       ldy     byte_offset
183b: a5 03                        lda     pixel_mask        ;get the pixel bit mask
183d: 31 00                        and     (line_ptr),y      ;merge it with the screen contents
183f: f0 02                        beq     @Return           ;if zero, no collision; branch
1841: e6 07                        inc     coll_ctr          ;increment collision counter
1843: 60           @Return         rts

                   ; 
                   ; Tests for a collision between the ball and another object due to horizontal
                   ; movement.
                   ; 
                   ; On entry:
                   ;   A-reg: movement delta (-2 or +2)
                   ; 
                   ; On exit:
                   ;   $07: incremented 0-3 times
                   ; 
1844: 18           CheckCollX      clc
1845: 65 e0                        adc     ball_xc           ;add offset to X coord
1847: 20 75 16                     jsr     CalcOffAndMask    ;calculate byte offset and pixel mask
184a: a5 e1                        lda     ball_yc           ;get ball Y coordinate
184c: 20 10 16                     jsr     GetLineAddr       ;calculate line address
184f: 20 39 18                     jsr     TestPixel         ;test if pixel is set
1852: a5 e1                        lda     ball_yc
1854: 18                           clc
1855: 69 01                        adc     #$01              ;repeat for Y + 1
1857: 20 10 16                     jsr     GetLineAddr
185a: 20 39 18                     jsr     TestPixel
185d: a5 e1                        lda     ball_yc
185f: 38                           sec
1860: e9 01                        sbc     #$01              ;repeat for Y - 1
1862: 20 10 16                     jsr     GetLineAddr
1865: 20 39 18                     jsr     TestPixel
1868: 60                           rts

                   ; 
                   ; Tests for a collision between the ball and another object due to vertical
                   ; movement.
                   ; 
                   ; On entry:
                   ;   A-reg: movement delta (-2 or +2)
                   ; 
                   ; On exit:
                   ;   $07: incremented 0-3 times
                   ; 
1869: 18           CheckCollY      clc
186a: 65 e1                        adc     ball_yc           ;add offset to Y coord
186c: 20 10 16                     jsr     GetLineAddr       ;calculate line address
186f: a5 e0                        lda     ball_xc           ;get ball X coordinate
1871: 20 75 16                     jsr     CalcOffAndMask    ;calculate byte offset and pixel mask
1874: 20 39 18                     jsr     TestPixel         ;test if pixel is set
1877: a5 e0                        lda     ball_xc
1879: 18                           clc
187a: 69 01                        adc     #$01              ;repeat for X + 1
187c: 20 75 16                     jsr     CalcOffAndMask
187f: 20 39 18                     jsr     TestPixel
1882: a5 e0                        lda     ball_xc
1884: 38                           sec
1885: e9 01                        sbc     #$01              ;repeat for X - 1
1887: 20 75 16                     jsr     CalcOffAndMask
188a: 20 39 18                     jsr     TestPixel
188d: 60                           rts

                   ; 
                   ; Checks for a collision between the ball and an on-screen object.
                   ; 
                   ; In the event of a collision, the ball's velocity and position is updated and a
                   ; sound is played.
                   ; 
188e: a9 00        CheckCollision  lda     #$00
1890: 85 07                        sta     coll_ctr          ;clear collision counters
1892: 85 05                        sta     coll_flag
1894: a5 e5                        lda     ball_yvel         ;check Y velocity
1896: 10 04                        bpl     @YPos             ;positive or zero, branch
1898: a9 fe                        lda     #$fe              ;use an offset of -2
189a: d0 02                        bne     @YCommon          ;(always)

189c: a9 02        @YPos           lda     #$02              ;use an offset of +2
189e: 85 3f        @YCommon        sta     delta_y           ;save for later
18a0: 20 69 18                     jsr     CheckCollY        ;check for collisions from Y movement
18a3: a5 07                        lda     coll_ctr          ;did we hit anything?
18a5: f0 0d                        beq     @NoYColl          ;no, branch
18a7: e6 05                        inc     coll_flag         ;yes, set flag
18a9: a5 e5                        lda     ball_yvel         ;set yvel = -yvel
18ab: 49 ff                        eor     #$ff
18ad: 85 e5                        sta     ball_yvel
18af: e6 e5                        inc     ball_yvel
18b1: 20 19 19                     jsr     BounceY           ;back us off one pixel, play sound
                   ; 
18b4: a9 00        @NoYColl        lda     #$00
18b6: 85 07                        sta     coll_ctr          ;reset counter
18b8: a5 e4                        lda     ball_xvel         ;check X velocity
18ba: 10 04                        bpl     @XPos             ;positive or zero, branch
18bc: a9 fe                        lda     #$fe              ;use an offset of -2
18be: d0 02                        bne     @XCommon          ;(always)

18c0: a9 02        @XPos           lda     #$02
18c2: 85 3e        @XCommon        sta     delta_x           ;save for later
18c4: 20 44 18                     jsr     CheckCollX        ;check for collisions from X movement
18c7: a5 07                        lda     coll_ctr          ;did we hit anything?
18c9: f0 10                        beq     @NoXColl          ;no, branch
18cb: e6 05                        inc     coll_flag         ;yes, set flag
18cd: a5 e4                        lda     ball_xvel         ;set xvel = -xvel
18cf: 49 ff                        eor     #$ff
18d1: 85 e4                        sta     ball_xvel
18d3: e6 e4                        inc     ball_xvel
18d5: 20 15 1a                     jsr     TestPdlColl       ;modify Y velocity if we hit a paddle
18d8: 20 06 19                     jsr     BounceX           ;back us off one pixel, play sound
                   ; 
18db: a5 05        @NoXColl        lda     coll_flag         ;did we hit anything at all?
18dd: d0 26                        bne     @Return           ;yes, bail
                   ; The previous tests were for the leading edge.  We now test the future position
                   ; of the center pixel.  (Not sure what this is for... maybe an edge case where
                   ; the paddle moves on top of the ball?)
18df: a9 00                        lda     #$00
18e1: 85 07                        sta     coll_ctr          ;reset collision counter
18e3: a5 3e                        lda     delta_x           ;get X movement (+2/-2)
18e5: 18                           clc
18e6: 65 e0                        adc     ball_xc           ;add current position
18e8: 20 75 16                     jsr     CalcOffAndMask    ;calculate byte offset and pixel mask
18eb: a5 3f                        lda     delta_y           ;get Y movement (+2/-2)
18ed: 18                           clc
18ee: 65 e1                        adc     ball_yc           ;add current position
18f0: 20 10 16                     jsr     GetLineAddr       ;calculate line address
18f3: 20 39 18                     jsr     TestPixel         ;see if the center pixel is set
18f6: a5 07                        lda     coll_ctr
18f8: f0 0b                        beq     @Return           ;it isn't, return
18fa: a5 e4                        lda     ball_xvel         ;must be a paddle hit, invert the X coordinate
18fc: 49 ff                        eor     #$ff
18fe: 85 e4                        sta     ball_xvel
1900: e6 e4                        inc     ball_xvel
1902: 20 06 19                     jsr     BounceX           ;do the bounce
1905: 60           @Return         rts

                   ; 
                   ; Adjusts the ball's X position and plays a sound.
                   ; 
1906: a5 e4        BounceX         lda     ball_xvel         ;check new velocity
1908: 30 04                        bmi     @MovingLf
190a: a9 01                        lda     #$01              ;moving right
190c: 10 02                        bpl     @Common

190e: a9 ff        @MovingLf       lda     #$ff
1910: 18           @Common         clc
1911: 65 e0                        adc     ball_xc           ;add +1 or -1 to current position
1913: 85 e2                        sta     new_ball_xc       ; so we're no longer colliding
1915: 20 3f 19                     jsr     BounceSoundX      ;play sound
1918: 60                           rts

                   ; 
                   ; Adjusts the ball's Y position and plays a sound.
                   ; 
1919: a5 e5        BounceY         lda     ball_yvel         ;check new velocity
191b: 30 04                        bmi     @MovingUp
191d: a9 01                        lda     #$01              ;moving down
191f: 10 02                        bpl     @Common

1921: a9 ff        @MovingUp       lda     #$ff
1923: 18           @Common         clc
1924: 65 e1                        adc     ball_yc           ;add +1 or -1 to current position
1926: 85 e3                        sta     new_ball_yc       ; so we're no longer colliding
1928: 20 4d 19                     jsr     BounceSoundY      ;play sound
192b: 60                           rts

                   ; 
                   ; Plays a sound.
                   ; 
                   ; On entry:
                   ;   $e8: pitch
                   ;   $e9: duration
                   ; 
192c: ad 30 c0     BounceSound     lda     SPKR              ;click
192f: 88           @NoClick        dey
1930: d0 04                        bne     @NoDec
1932: c6 e9                        dec     snd_dur
1934: f0 08                        beq     @Return
1936: ca           @NoDec          dex
1937: d0 f6                        bne     @NoClick
1939: a6 e8                        ldx     snd_pitch
193b: 4c 2c 19                     jmp     BounceSound

193e: 60           @Return         rts

                   ; 
                   ; Sets up and plays the sound for bouncing off of a vertical surface.
                   ; 
                   ; A-reg is preserved.
                   ; 
193f: 48           BounceSoundX    pha
1940: a9 d0                        lda     #$d0
1942: 85 e8                        sta     snd_pitch
1944: a9 06                        lda     #$06
1946: 85 e9                        sta     snd_dur
1948: 20 2c 19                     jsr     BounceSound
194b: 68                           pla
194c: 60                           rts

                   ; 
                   ; Sets up and plays the sound for bouncing off of a horizontal surface.
                   ; 
                   ; A-reg is preserved.
                   ; 
194d: 48           BounceSoundY    pha
194e: a9 f0                        lda     #$f0
1950: 85 e8                        sta     snd_pitch
1952: a9 06                        lda     #$06
1954: 85 e9                        sta     snd_dur
1956: 20 2c 19                     jsr     BounceSound
1959: 68                           pla
195a: 60                           rts

                   ; 
                   ; Updates the ball's X/Y coordinates.
                   ; 
                   ; If we're, say, moving to the right, then X velocity will be positive.  If the
                   ; fractional portion is negative, the ADC won't overflow, and we do nothing.  If
                   ; the fractional portion is positive, the ADC might overflow; if it does, the
                   ; carry will be clear.  Thus we can use the overflow flag as a movement trigger,
                   ; and use the carry flag to see which way we were moving.
                   ; 
195b: a5 e6        MoveBall        lda     ball_x_frac       ;get fractional part of X position
195d: 18                           clc
195e: 65 e4                        adc     ball_xvel         ;add velocity
1960: 50 08                        bvc     @NoXOv            ;if no overflow, branch
1962: 90 04                        bcc     @PosX             ;if went pos to neg, branch
1964: c6 e2                        dec     new_ball_xc       ;move left
1966: b0 02                        bcs     @NoXOv            ;(always)

1968: e6 e2        @PosX           inc     new_ball_xc       ;move right
196a: 85 e6        @NoXOv          sta     ball_x_frac
                   ; 
196c: a5 e7                        lda     ball_y_frac       ;get fractional part of Y position
196e: 38                           sec
196f: e5 e5                        sbc     ball_yvel         ;subtract velocity
1971: 50 08                        bvc     @NoYOv            ;if no overflow, branch
1973: 90 04                        bcc     @NegY             ;if went pos to neg, branch
1975: e6 e3                        inc     new_ball_yc       ;move down
1977: b0 02                        bcs     @NoYOv

1979: c6 e3        @NegY           dec     new_ball_yc       ;move up
197b: 85 e7        @NoYOv          sta     ball_y_frac
197d: 60                           rts

                   ; 
                   ; CALL 6526 - redraws the paddles on screen, based on the current paddle
                   ; position.
                   ; 
                   ; Paddles are 24 pixels high and 3 pixels wide.  The position is set between 3
                   ; and 130, but they're drawn one line below that.
                   ; 
                   ; Paddles don't move instantaneously.  A call here moves each paddle 8x, one
                   ; pixel at a time.
                   ; 
                   ; On entry:
                   ;   $43: current left paddle position
                   ;   $44: current right paddle position
                   ; 
197e: a9 08        UpdatePaddles   lda     #8                ;move paddle 8 pixels per frame
1980: 85 40                        sta     pdl_drw_ctr
1982: a5 e0                        lda     ball_xc           ;preserve $e0-e3 (ball current/new position)
1984: 48                           pha                       ; so we can use the ball-drawing code for the
1985: a5 e1                        lda     ball_yc           ; paddles too
1987: 48                           pha
1988: a5 e2                        lda     new_ball_xc
198a: 48                           pha
198b: a5 e3                        lda     new_ball_yc
198d: 48                           pha
                   ; Handle left paddle (player #1).
198e: a2 00                        ldx     #$00
1990: 20 1e fb                     jsr     MON_PREAD         ;read paddle 0 into Y-reg (0-255)
1993: 98                           tya
1994: 4a                           lsr     A                 ;halve it (0-127)
1995: 18                           clc
1996: 69 03                        adc     #$03              ;add 3 (3-130)
1998: 85 41                        sta     left_pdl_new_y    ;save it
                   ; Set up coordinates.
                   ; 
                   ; We set the "current" Y coordinate to position+8, and "new" to position+16 (or
                   ; vice-versa), yielding a deltaY of 8.  The ball drawing routine will erase the
                   ; row at (current - deltaY), and draw the row at (new + deltaY).  Since
                   ; "current" and "new" are 8 pixels apart, this updates rows 24 pixels apart.
199a: a5 41        @Loop0          lda     left_pdl_new_y    ;get desired position
199c: 38                           sec
199d: e5 43                        sbc     left_pdl_y        ;subtract old position
199f: 18                           clc
19a0: 30 0e                        bmi     @LeftUp
19a2: a5 43                        lda     left_pdl_y        ;moving paddle down; get old position
19a4: 69 08                        adc     #8
19a6: 85 e1                        sta     ball_yc           ;set old paddle + 8 as current position
19a8: 69 08                        adc     #8
19aa: 85 e3                        sta     new_ball_yc       ;set old paddle + 16 as new position
19ac: e6 43                        inc     left_pdl_y        ;move paddle down one pixel
19ae: d0 0c                        bne     @Common0          ;(always)

19b0: a5 43        @LeftUp         lda     left_pdl_y        ;moving paddle up; get old position
19b2: 69 08                        adc     #8
19b4: 85 e3                        sta     new_ball_yc       ;set old paddle + 8 as new position
19b6: 69 08                        adc     #8
19b8: 85 e1                        sta     ball_yc           ;set old paddle + 16 as old position
19ba: c6 43                        dec     left_pdl_y
                   ; Draw a row.  The row will be erased from the current position and drawn at the
                   ; new position.  If we're not actually moving, the draw operation will do
                   ; nothing (but we still do it 8x).  The delay may be unavoidable because
                   ; paddle0's capacitor might still be charging.
19bc: a9 07        @Common0        lda     #$07              ;POKE 6589,LE
19be: 85 e0                        sta     ball_xc           ;set X position for left paddle
19c0: 85 e2                        sta     new_ball_xc       ;set "new" position so it draws rows
19c2: 20 04 18                     jsr     RedrawBall        ;erase one row, draw one row
19c5: c6 40                        dec     pdl_drw_ctr       ;have we done this 8x?
19c7: d0 d1                        bne     @Loop0            ;no, loop
                   ; Repeat for right paddle (player #2).
19c9: a9 08                        lda     #8
19cb: 85 40                        sta     pdl_drw_ctr       ;reset draw counter
19cd: a2 01                        ldx     #$01
19cf: 20 1e fb                     jsr     MON_PREAD         ;read paddle 1 into Y-reg (0-255)
19d2: 98                           tya
19d3: 4a                           lsr     A                 ;halve it (0-127)
19d4: 18                           clc
19d5: 69 03                        adc     #$03              ;add 3 (3-130)
19d7: 85 42                        sta     right_pdl_new_y   ;save it
                   ; 
19d9: a5 42        @Loop1          lda     right_pdl_new_y
19db: 38                           sec
19dc: e5 44                        sbc     right_pdl_y
19de: 18                           clc
19df: 30 0e                        bmi     @RightUp
19e1: a5 44                        lda     right_pdl_y
19e3: 69 08                        adc     #8
19e5: 85 e1                        sta     ball_yc
19e7: 69 08                        adc     #8
19e9: 85 e3                        sta     new_ball_yc
19eb: e6 44                        inc     right_pdl_y
19ed: d0 0c                        bne     @Common1          ;(always)

19ef: a5 44        @RightUp        lda     right_pdl_y
19f1: 69 08                        adc     #8
19f3: 85 e3                        sta     new_ball_yc
19f5: 69 08                        adc     #8
19f7: 85 e1                        sta     ball_yc
19f9: c6 44                        dec     right_pdl_y
19fb: a9 f7        @Common1        lda     #$f7              ;POKE 6652,RE
19fd: 85 e0                        sta     ball_xc           ;set X position for right paddle
19ff: 85 e2                        sta     new_ball_xc       ;set "new" position so it draws rows
1a01: 20 04 18                     jsr     RedrawBall
1a04: c6 40                        dec     pdl_drw_ctr
1a06: d0 d1                        bne     @Loop1
                   ; 
1a08: 68                           pla                       ;restore $e0-e3
1a09: 85 e3                        sta     new_ball_yc
1a0b: 68                           pla
1a0c: 85 e2                        sta     new_ball_xc
1a0e: 68                           pla
1a0f: 85 e1                        sta     ball_yc
1a11: 68                           pla
1a12: 85 e0                        sta     ball_xc
1a14: 60                           rts

                   ; 
                   ; Tests for a collision between the ball and a paddle.  Updates the ball's Y
                   ; velocity based on where on the paddle the ball hit.
                   ; 
                   ; This is only called after we detected a collision as a result of horizontal
                   ; movement.  There are no horizontal field lines in the columns where the
                   ; paddles are, so if the X coordinate matches we assume it's a paddle hit.
                   ; 
                   ; It's possible to hit the top or bottom of a paddle, but that just reacts like
                   ; striking any other horizontal surface.
                   ; 
1a15: a5 e0        TestPdlColl     lda     ball_xc           ;get ball X coordinate
1a17: c9 04                        cmp     #$04              ;POKE 6680,LE - 3
1a19: f0 0d                        beq     @HitLeft
1a1b: c9 0a                        cmp     #$0a              ;POKE 6684,LE + 3
1a1d: f0 09                        beq     @HitLeft
1a1f: c9 f4                        cmp     #$f4              ;POKE 6688,RE - 3
1a21: f0 31                        beq     @HitRight
1a23: c9 fa                        cmp     #$fa              ;POKE 6692,RE + 3
1a25: f0 2d                        beq     @HitRight
1a27: 60                           rts

1a28: a5 e1        @HitLeft        lda     ball_yc           ;get ball Y coordinate (0-159)
1a2a: 38                           sec
1a2b: e5 41                        sbc     left_pdl_new_y    ;subtract left paddle Y position (3-130)
1a2d: 38           @HitCommon      sec
1a2e: e9 0c                        sbc     #12               ;subtract 12 to get signed delta from center
1a30: 0a                           asl     A                 ; (should be roughly [-12,+12] now)
1a31: 0a                           asl     A                 ;multiply by 4 (roughly [-48,+48])
1a32: 65 e5                        adc     ball_yvel         ;add to ball Y velocity (carry matches sign)
1a34: 50 08                        bvc     @GoodVel          ;sign didn't overflow, branch
1a36: b0 04                        bcs     @ClampToNeg       ;sign changed; if went from neg to pos, branch
1a38: a9 70                        lda     #$70              ;clamp to +112
1a3a: d0 02                        bne     @GoodVel

1a3c: a9 8f        @ClampToNeg     lda     #$8f              ;clamp to -113
1a3e: 85 e5        @GoodVel        sta     ball_yvel
1a40: 30 09                        bmi     @MovingUp         ;if moving upward, branch
1a42: c9 78                        cmp     #$78              ;is velocity > 120?
1a44: 30 0d                        bmi     @Return           ;no, bail
1a46: a9 78                        lda     #$78              ;yes, clamp to 120
1a48: 85 e5                        sta     ball_yvel
1a4a: 60                           rts

1a4b: c9 88        @MovingUp       cmp     #$88              ;is velocity < -120?
1a4d: 10 04                        bpl     @Return           ;no, bail
1a4f: a9 88                        lda     #$88              ;yes, clamp to -120
1a51: 85 e5                        sta     ball_yvel
1a53: 60           @Return         rts

1a54: a5 e1        @HitRight       lda     ball_yc           ;get ball Y coordinate (0-159)
1a56: 38                           sec
1a57: e5 42                        sbc     right_pdl_new_y   ;subtract right paddle Y position (3-130)
1a59: 4c 2d 1a                     jmp     @HitCommon

                   ; 
                   ; CALLL 6748 - plays game, without gravity.
                   ; 
                   ; Continues until a point is scored or ESC is hit.
                   ; 
1a5c: 20 04 18     PlayGameNG      jsr     RedrawBall        ;erase and redraw the ball
1a5f: 20 5b 19                     jsr     MoveBall          ;update the ball's position
1a62: 20 8e 18                     jsr     CheckCollision    ;check for and handle collisions
1a65: a5 ea                        lda     pdl_mv_ctr        ;time to update the paddles?
1a67: d0 07                        bne     @SkipUpdate       ;not yet, branch
1a69: a9 0f        @_diff1         lda     #$0f              ;POKE 6762,DFF
1a6b: 85 ea                        sta     pdl_mv_ctr        ;reset counter
1a6d: 20 7e 19                     jsr     UpdatePaddles     ;update player paddle positions
1a70: c6 ea        @SkipUpdate     dec     pdl_mv_ctr
                   ; Check to see if a point has been scored.
1a72: 20 bd 1a     @_call1         jsr     TestVictoryNH     ;POKE 6771,189 or 203 ($1abd or $1acb)
1a75: ad 00 c0                     lda     KBD               ;was a key hit?
1a78: 10 e2                        bpl     PlayGameNG        ;no, keep going
1a7a: 2c 10 c0                     bit     KBDSTRB           ;clear it
1a7d: c9 9b                        cmp     #$9b              ;was it ESC?
1a7f: d0 db                        bne     PlayGameNG        ;no, keep going
1a81: 60                           rts

                   ; 
                   ; CALL 6786 - plays game, with gravity.
                   ; 
                   ; Continues until a point is scored or ESC is hit.
                   ; 
1a82: 20 04 18     PlayGameG       jsr     RedrawBall        ;erase and redraw the ball
1a85: 20 5b 19                     jsr     MoveBall          ;update the ball's position
1a88: 20 8e 18                     jsr     CheckCollision    ;check for and handle collisions
1a8b: a5 ea                        lda     pdl_mv_ctr        ;time to update the paddles?
1a8d: d0 07                        bne     @SkipUpdate       ;not yet, branch
1a8f: a9 0f        @_diff2         lda     #$0f              ;POKE 6800,DFF
1a91: 85 ea                        sta     pdl_mv_ctr        ;reset counter
1a93: 20 7e 19                     jsr     UpdatePaddles     ;update player paddle positions
1a96: c6 ea        @SkipUpdate     dec     pdl_mv_ctr        ;update counter
                   ; Apply gravity.
1a98: a5 d0                        lda     gravity_ctr       ;time to apply gravity?
1a9a: d0 0f                        bne     @NotYet           ;no, branch
1a9c: a9 05                        lda     #$05
1a9e: 85 d0                        sta     gravity_ctr       ;reset counter; we adjust Y vel every 5 frames
1aa0: a5 e5                        lda     ball_yvel
1aa2: 18                           clc
1aa3: 69 01                        adc     #$01              ;increment Y velocity
1aa5: 85 e5                        sta     ball_yvel
1aa7: 50 02                        bvc     @NotYet           ;math didn't overflow, branch
1aa9: c6 e5                        dec     ball_yvel         ;decrement back to max vel
1aab: c6 d0        @NotYet         dec     gravity_ctr       ;update counter
                   ; Check to see if a point has been scored.
1aad: 20 bd 1a     @_call2         jsr     TestVictoryNH     ;POKE 6830,189 or 203 ($1abd or $1acb)
1ab0: ad 00 c0                     lda     KBD               ;was a key hit?
1ab3: 10 cd                        bpl     PlayGameG         ;no, keep going
1ab5: 2c 10 c0                     bit     KBDSTRB           ;clear it
1ab8: c9 9b                        cmp     #$9b              ;was it ESC?
1aba: d0 c6                        bne     PlayGameG         ;no, keep going
1abc: 60                           rts

                   ; 
                   ; Called from self-modifying code.
                   ; 
                   ; Used for non-HOCKEY fields.  Score a point if the ball reaches the edge of the
                   ; screen.
                   ; 
1abd: a5 e0        TestVictoryNH   lda     ball_xc           ;get X coord
1abf: c9 01                        cmp     #1                ;reached left edge of screen?
1ac1: d0 03                        bne     @NotLeft          ;no, branch
1ac3: 68           @Scored         pla                       ;yes, pop so we return to BASIC
1ac4: 68                           pla
1ac5: 60                           rts

1ac6: c9 fe        @NotLeft        cmp     #254              ;reached right edge of screen?
1ac8: f0 f9                        beq     @Scored           ;yes, branch
1aca: 60                           rts

                   ; 
                   ; Called from self-modifying code.
                   ; 
                   ; Used for HOCKEY field.  Score a point if the ball reaches the back of the goal
                   ; area.
                   ; 
1acb: a5 e0        TestVictoryH    lda     ball_xc           ;get X coord
1acd: c9 23                        cmp     #35               ;reached leftmost goal?
1acf: f0 05                        beq     @CheckY           ;yes, check Y
1ad1: c9 dd                        cmp     #221              ;reached rightmost goal?
1ad3: f0 01                        beq     @CheckY           ;yes, check Y
1ad5: 60                           rts

1ad6: a5 e1        @CheckY         lda     ball_yc           ;get Y coord
1ad8: c9 36                        cmp     #54               ;below top of goal area?
1ada: 10 01                        bpl     @CheckBot         ;yes, branch
1adc: 60                           rts

1add: c9 68        @CheckBot       cmp     #104              ;above bottom of goal area?
1adf: 30 e2                        bmi     @Scored           ;yes, branch
1ae1: 60                           rts

                   ; 
                   ; CALL 6882 - erases the ball.  Called after point scored.
                   ; 
1ae2: c6 e1        EraseBall       dec     ball_yc           ;erase at Y-1
1ae4: a9 00                        lda     #$00              ;set flag to erase mode
1ae6: 85 04                        sta     draw_flag
1ae8: 20 bc 17                     jsr     DrawEraseBallRow  ;erase row
1aeb: e6 e1                        inc     ball_yc           ;erase at Y
1aed: a9 00                        lda     #$00              ;no additional Y offset
1aef: 20 bc 17                     jsr     DrawEraseBallRow
1af2: e6 e1                        inc     ball_yc           ;erase at Y+1
1af4: a9 00                        lda     #$00              ;no additional Y offset
1af6: 20 bc 17                     jsr     DrawEraseBallRow
1af9: 60                           rts

                   ; 
                   ; Draws a single dot.  Used by the line-drawing code.
                   ; 
                   ; On entry:
                   ;   $00-01: hi-res line pointer
                   ;   $02: hi-res byte offset (0-39)
                   ;   $04: high-bit set flag ($00/$80)
                   ;   $05: color index (0-3)
                   ; 
                   ]hi_color_flag  .var    $04    {addr/1}
                   ]color          .var    $05    {addr/1}

1afa: a5 02        DrawLineDot     lda     byte_offset       ;get offset into hi-res line
1afc: 29 01                        and     #$01              ;odd or even?
1afe: 18                           clc
1aff: 06 05                        asl     ]color            ;shift the color value left to make room
1b01: 65 05                        adc     ]color            ;merge in the odd/even bit
1b03: 46 05                        lsr     ]color            ;undo the change to ZP value
1b05: a8                           tay                       ;use combined value as index (0-7)
1b06: b9 14 1b                     lda     color_bytes,y     ;get color pattern
1b09: 25 03                        and     pixel_mask        ;mask to get just the bits we want
1b0b: 05 04                        ora     ]hi_color_flag    ;set the high bit if requested
1b0d: a4 02                        ldy     byte_offset       ;get offset into hi-res line
1b0f: 11 00                        ora     (line_ptr),y      ;merge the pixels
1b11: 91 00                        sta     (line_ptr),y
1b13: 60                           rts

                   ; 
                   ; Hi-res color patterns.  Take a color value 0-3, double it, and add one if
                   ; we're drawing in an odd column.  Black, purple, green, white (high bit clear)
                   ; or black, blue, orange, white (high bit set).
                   ; 
1b14: 00 00 55 2a+ color_bytes     .bulk   $00,$00,$55,$2a,$2a,$55,$ff,$ff

                   ; 
                   ; Draw horizontal line.  Used by game field drawing code.
                   ; 
                   ; On entry:
                   ;   $d1: initial X coordinate
                   ;   $d2: initial Y coordinate
                   ;   $d3: line length
                   ; 
1b1c: a5 d2        DrawHorizLine   lda     line_st_y         ;get row
1b1e: 20 10 16                     jsr     GetLineAddr       ;compute address
1b21: a5 d1                        lda     line_st_x         ;get initial X coordinate
1b23: 85 d4        @Loop           sta     line_xc
1b25: 20 75 16                     jsr     CalcOffAndMask    ;calculate line offset and pixel mask
1b28: 20 fa 1a                     jsr     DrawLineDot       ;draw it
1b2b: c6 d3                        dec     line_len          ;count down
1b2d: f0 07                        beq     @Return           ;branch if done
1b2f: a5 d4                        lda     line_xc           ;advance to next pixel position
1b31: 18                           clc
1b32: 69 01                        adc     #$01
1b34: d0 ed                        bne     @Loop             ;(always... unless we hit right edge of screen)
1b36: 60           @Return         rts

                   ; 
                   ; Draw vertical line.  Used by game field drawing code.
                   ; 
                   ; On entry:
                   ;   $d1: initial X coordinate
                   ;   $d2: initial Y coordinate
                   ;   $d3: line length
                   ; 
1b37: a5 d1        DrawVertLine    lda     line_st_x         ;get column
1b39: 20 75 16                     jsr     CalcOffAndMask    ;calculate line offset and pixel mask
1b3c: a5 d2                        lda     line_st_y         ;get initial Y coordinate
1b3e: 85 d5        @Loop           sta     line_yc
1b40: 20 10 16                     jsr     GetLineAddr       ;compute address
1b43: 20 fa 1a                     jsr     DrawLineDot       ;draw a dot
1b46: c6 d3                        dec     line_len          ;count down
1b48: f0 07                        beq     @Return           ;branch if done
1b4a: a5 d5                        lda     line_yc           ;advance to next line
1b4c: 18                           clc
1b4d: 69 01                        adc     #$01
1b4f: d0 ed                        bne     @Loop             ;(always)
1b51: 60           @Return         rts

                   ; 
                   ; CALL 6994 - draw game field.
                   ; 
                   ; The BASIC program sets a pointer to field data in 224/225 ($e0/e1).
                   ; 
                   ]board_ptr      .var    $e0    {addr/2}

1b52: a0 00        DrawField       ldy     #$00
1b54: b1 e0        @Loop           lda     (]board_ptr),y    ;get initial X coord from data
1b56: 85 d1                        sta     line_st_x
1b58: c8                           iny
1b59: b1 e0                        lda     (]board_ptr),y    ;get initial Y coord
1b5b: 85 d2                        sta     line_st_y
1b5d: c8                           iny
1b5e: b1 e0                        lda     (]board_ptr),y    ;get line length
1b60: 85 d3                        sta     line_len
1b62: c8                           iny
1b63: b1 e0                        lda     (]board_ptr),y    ;get direction / color flag
1b65: f0 2e                        beq     @Return           ;zero means end of list
1b67: c8                           iny
1b68: 0a                           asl     A                 ;shift left to check hi bit (bit 7)
1b69: 90 06                        bcc     @ClearFlag        ;(the value set is not actually used)
1b6b: a2 80                        ldx     #$80
1b6d: 86 04                        stx     ]hi_color_flag
1b6f: d0 04                        bne     @Cont             ;(always)

1b71: a2 00        @ClearFlag      ldx     #$00
1b73: 86 04                        stx     ]hi_color_flag
1b75: 0a           @Cont           asl     A                 ;shift left to check bit 6
1b76: 90 0f                        bcc     @DoHoriz          ;0=horizontal, 1=vertical
1b78: 18                           clc
1b79: 4a                           lsr     A                 ;shift the bits back, leaving only the color value
1b7a: 4a                           lsr     A
1b7b: 85 05                        sta     ]color
1b7d: 98                           tya                       ;preserve array index
1b7e: 48                           pha
1b7f: 20 37 1b                     jsr     DrawVertLine      ;draw line
1b82: 68                           pla                       ;restore index
1b83: a8                           tay
1b84: 4c 54 1b                     jmp     @Loop

1b87: 4a           @DoHoriz        lsr     A                 ;shift the bits back, leaving only the color value
1b88: 4a                           lsr     A
1b89: 85 05                        sta     ]color
1b8b: 98                           tya                       ;preserve array index
1b8c: 48                           pha
1b8d: 20 1c 1b                     jsr     DrawHorizLine     ;draw line
1b90: 68                           pla                       ;restore index
1b91: a8                           tay
1b92: 4c 54 1b                     jmp     @Loop

1b95: 60           @Return         rts

                   ; 
                   ; CALL 7062 - erases the hi-res screen and displays it, in mixed mode.
                   ; 
                   • Clear variables

1b96: a9 20        ClearHiRes      lda     #$20              ;set pointer to $2000
1b98: 85 1b                        sta     hptr+1
1b9a: a0 00                        ldy     #$00
1b9c: 84 1a                        sty     hptr
1b9e: 98           @Loop1          tya
1b9f: 91 1a        @Loop           sta     (hptr),y
1ba1: c8                           iny
1ba2: d0 fb                        bne     @Loop
1ba4: e6 1b                        inc     hptr+1            ;advance to next page
1ba6: a5 1b                        lda     hptr+1
1ba8: 29 1f                        and     #$1f              ;done full screen?
1baa: d0 f2                        bne     @Loop1            ;not yet, branch
1bac: 8d 57 c0                     sta     HIRES             ;select hi-res screen
1baf: 8d 53 c0                     sta     MIXSET            ;mix 4 lines of text
1bb2: 8d 50 c0                     sta     TXTCLR            ;enable graphics
1bb5: 60                           rts

                   ; 
                   ; Game field data.  These are a series of four-byte entries that describe lines:
                   ; 
                   ;  - initial X coordinate
                   ;  - initial Y coordinate
                   ;  - length of line; $00=256
                   ;  - line color and direction: bits HD0000CC
                   ;    H: color high-bit flag; if set, pixel mask has $80 added
                   ;    D: direction flag, 0=horiz, 1=vert
                   ;    CC: color (0-3)
                   ; 
                   ; A value of zero in the fourth byte indicates the end of the list.
                   ; 

                   ; 
                   ; Field #1, "BUMPER POOL".
                   ; 
                   vis
1bb6: 00 00 00 01  field1          .bulk   $00,$00,$00,$01
1bba: 00 9f 00 01                  .bulk   $00,$9f,$00,$01
1bbe: 00 00 38 41                  .bulk   $00,$00,$38,$41
1bc2: 00 68 38 41                  .bulk   $00,$68,$38,$41
1bc6: fe 00 38 41                  .bulk   $fe,$00,$38,$41
1bca: fe 68 38 41                  .bulk   $fe,$68,$38,$41
1bce: 21 36 0b 42                  .bulk   $21,$36,$0b,$42
1bd2: 21 5e 0b 42                  .bulk   $21,$5e,$0b,$42
1bd6: 2b 36 0b 42                  .bulk   $2b,$36,$0b,$42
1bda: 2b 5e 0b 42                  .bulk   $2b,$5e,$0b,$42
1bde: 21 36 0b 02                  .bulk   $21,$36,$0b,$02
1be2: 21 5e 0b 02                  .bulk   $21,$5e,$0b,$02
1be6: 21 40 0b 02                  .bulk   $21,$40,$0b,$02
1bea: 21 68 0b 02                  .bulk   $21,$68,$0b,$02
1bee: 65 36 0b 42                  .bulk   $65,$36,$0b,$42
1bf2: 65 5e 0b 42                  .bulk   $65,$5e,$0b,$42
1bf6: 71 36 0b 42                  .bulk   $71,$36,$0b,$42
1bfa: 71 5e 0b 42                  .bulk   $71,$5e,$0b,$42
1bfe: 79 4a 0b 42                  .bulk   $79,$4a,$0b,$42
1c02: 85 4a 0b 42                  .bulk   $85,$4a,$0b,$42
1c06: 8f 36 0b 42                  .bulk   $8f,$36,$0b,$42
1c0a: 8f 5e 0b 42                  .bulk   $8f,$5e,$0b,$42
1c0e: 9b 36 0b 42                  .bulk   $9b,$36,$0b,$42
1c12: 9b 5e 0b 42                  .bulk   $9b,$5e,$0b,$42
1c16: 65 36 0c 02                  .bulk   $65,$36,$0c,$02
1c1a: 65 40 0c 02                  .bulk   $65,$40,$0c,$02
1c1e: 65 5e 0c 02                  .bulk   $65,$5e,$0c,$02
1c22: 65 68 0c 02                  .bulk   $65,$68,$0c,$02
1c26: 79 4a 0c 02                  .bulk   $79,$4a,$0c,$02
1c2a: 79 54 0c 02                  .bulk   $79,$54,$0c,$02
1c2e: 8f 36 0c 02                  .bulk   $8f,$36,$0c,$02
1c32: 8f 40 0c 02                  .bulk   $8f,$40,$0c,$02
1c36: 8f 5e 0c 02                  .bulk   $8f,$5e,$0c,$02
1c3a: 8f 68 0c 02                  .bulk   $8f,$68,$0c,$02
1c3e: d1 36 0b 42                  .bulk   $d1,$36,$0b,$42
1c42: d1 5e 0b 42                  .bulk   $d1,$5e,$0b,$42
1c46: db 36 0b 42                  .bulk   $db,$36,$0b,$42
1c4a: db 5e 0b 42                  .bulk   $db,$5e,$0b,$42
1c4e: d1 36 0b 02                  .bulk   $d1,$36,$0b,$02
1c52: d1 5e 0b 02                  .bulk   $d1,$5e,$0b,$02
1c56: d1 40 0b 02                  .bulk   $d1,$40,$0b,$02
1c5a: d1 68 0b 02                  .bulk   $d1,$68,$0b,$02
1c5e: 00 00 00 00                  .bulk   $00,$00,$00,$00

                   ; 
                   ; Field #2, "HOCKEY".  Points are scored when the ball hits the back of the net,
                   ; not the edge of the screen, so a separate victory condition routine is needed.
                   ; 
                   vis
1c62: 00 00 00 81  field2          .bulk   $00,$00,$00,$81
1c66: 00 9f 00 81                  .bulk   $00,$9f,$00,$81
1c6a: 00 00 a0 c1                  .bulk   $00,$00,$a0,$c1
1c6e: fe 00 a0 c1                  .bulk   $fe,$00,$a0,$c1
1c72: 21 36 33 42                  .bulk   $21,$36,$33,$42
1c76: df 36 33 42                  .bulk   $df,$36,$33,$42
1c7a: 21 36 19 02                  .bulk   $21,$36,$19,$02
1c7e: c7 36 19 02                  .bulk   $c7,$36,$19,$02
1c82: 21 68 19 02                  .bulk   $21,$68,$19,$02
1c86: c7 68 19 02                  .bulk   $c7,$68,$19,$02
1c8a: 40 10 19 02                  .bulk   $40,$10,$19,$02
1c8e: a7 10 19 02                  .bulk   $a7,$10,$19,$02
1c92: 40 8f 19 02                  .bulk   $40,$8f,$19,$02
1c96: a7 8f 19 02                  .bulk   $a7,$8f,$19,$02
1c9a: 00 00 00 00                  .bulk   $00,$00,$00,$00

                   ; 
                   ; Field #3, "SCRAMBLE".
                   ; 
                   vis
1c9e: 00 00 00 82  field3          .bulk   $00,$00,$00,$82
1ca2: 00 9f 00 82                  .bulk   $00,$9f,$00,$82
1ca6: 01 00 38 c2                  .bulk   $01,$00,$38,$c2
1caa: 01 68 38 c2                  .bulk   $01,$68,$38,$c2
1cae: ff 00 38 c2                  .bulk   $ff,$00,$38,$c2
1cb2: ff 68 38 c2                  .bulk   $ff,$68,$38,$c2
1cb6: 10 10 29 01                  .bulk   $10,$10,$29,$01
1cba: 10 20 29 01                  .bulk   $10,$20,$29,$01
1cbe: 10 7f 29 01                  .bulk   $10,$7f,$29,$01
1cc2: 10 8f 29 01                  .bulk   $10,$8f,$29,$01
1cc6: c8 10 29 01                  .bulk   $c8,$10,$29,$01
1cca: c8 20 29 01                  .bulk   $c8,$20,$29,$01
1cce: c8 7f 29 01                  .bulk   $c8,$7f,$29,$01
1cd2: c8 8f 29 01                  .bulk   $c8,$8f,$29,$01
1cd6: 48 40 10 02                  .bulk   $48,$40,$10,$02
1cda: a8 40 10 02                  .bulk   $a8,$40,$10,$02
1cde: 48 60 10 02                  .bulk   $48,$60,$10,$02
1ce2: a8 60 10 02                  .bulk   $a8,$60,$10,$02
1ce6: 59 40 21 42                  .bulk   $59,$40,$21,$42
1cea: 79 40 21 42                  .bulk   $79,$40,$21,$42
1cee: 89 40 21 42                  .bulk   $89,$40,$21,$42
1cf2: a9 40 21 42                  .bulk   $a9,$40,$21,$42
1cf6: 00 00 00 00                  .bulk   $00,$00,$00,$00

                   ; 
                   ; Field #4, TENNIS.
                   ; 
                   vis
1cfa: 00 00 00 01  field4          .bulk   $00,$00,$00,$01
1cfe: 00 9f 00 01                  .bulk   $00,$9f,$00,$01
1d02: 7d 50 50 42                  .bulk   $7d,$50,$50,$42
1d06: 81 50 50 42                  .bulk   $81,$50,$50,$42
1d0a: 7d 50 05 02                  .bulk   $7d,$50,$05,$02
1d0e: 00 00 00 00                  .bulk   $00,$00,$00,$00

                   ; 
                   ; Clear one pixel.  Used for title animation.
                   ; 
                   ; On entry:
                   ;   $00: address of hi-res line
                   ;   $02: byte offset in line
                   ;   $03: pixel bit mask
                   ; 
1d12: a4 02        ClearPixel      ldy     byte_offset
1d14: a5 03                        lda     pixel_mask
1d16: 49 ff                        eor     #$ff              ;invert, to make it an AND mask
1d18: 31 00                        and     (line_ptr),y
1d1a: 91 00                        sta     (line_ptr),y
1d1c: 60                           rts

                   ; 
                   ; Set one pixel.  Used for title animation.
                   ; 
                   ; On entry:
                   ;   $00: address of hi-res line
                   ;   $02: byte offset in line
                   ;   $03: pixel bit mask
                   ; 
1d1d: a4 02        SetPixel        ldy     byte_offset
1d1f: a5 03                        lda     pixel_mask
1d21: 11 00                        ora     (line_ptr),y
1d23: 91 00                        sta     (line_ptr),y
1d25: 60                           rts

                   ; 
                   ; CALL 7462 - show the hi-res animated title.
                   ; 
                   ; We animate 128 individual particles, bouncing them off of an invisible
                   ; bounding box.  The movement was designed so that the pixels will return to
                   ; their original positions all at once.
                   ; 
                   ; This has a bug that causes a few pixels to be missing from the final frame.
                   ; It walks through the list, erasing each pixel and then drawing it in its new
                   ; position.  If a new pixel overlaps with the old position of a different pixel,
                   ; the other pixel's erase can clear the new pixel.  This could have been avoided
                   ; by using XOR rendering.
                   ; 
1d26: a0 00        AnimTitle       ldy     #$00              ;init particle index
1d28: 98           @AnimLoop       tya                       ;save it on stack
1d29: 48                           pha
1d2a: b9 b4 1d                     lda     title_xy,y        ;get particle X coordinate
1d2d: 85 e0                        sta     ball_xc           ;save copy
1d2f: 20 75 16                     jsr     CalcOffAndMask    ;calculate current byte offset and bit mask
1d32: 68                           pla
1d33: a8                           tay                       ;restore particle index
1d34: a5 e0                        lda     ball_xc           ;get X coordinate
1d36: 18                           clc
1d37: 79 b4 1e                     adc     vectors,y         ;add vector
1d3a: 99 b4 1d                     sta     title_xy,y        ;update particle X position
1d3d: c9 50                        cmp     #80               ;have we reached left edge of box?
1d3f: d0 0d                        bne     @NotLeft          ;no, branch
                   ; Invert movement vector X component.
1d41: b9 b4 1e     @InvertVX       lda     vectors,y         ;get vector X
1d44: 49 ff                        eor     #$ff              ;do 2's complement negation
1d46: 18                           clc
1d47: 69 01                        adc     #$01
1d49: 99 b4 1e                     sta     vectors,y         ;update value
1d4c: d0 04                        bne     @MoveY            ;(always)

1d4e: c9 a0        @NotLeft        cmp     #160              ;have we reached right edge of box?
1d50: f0 ef                        beq     @InvertVX         ;yes, bounce
1d52: c8           @MoveY          iny                       ;advance particle index to Y component
1d53: 98                           tya                       ;save it on stack
1d54: 48                           pha
1d55: b9 b4 1d                     lda     title_xy,y        ;get particle Y component
1d58: 85 e1                        sta     ball_yc           ;save copy
1d5a: 20 10 16                     jsr     GetLineAddr       ;calculate current line address
1d5d: 20 12 1d                     jsr     ClearPixel        ;erase current position
1d60: 68                           pla                       ;restore particle index
1d61: a8                           tay
1d62: a5 e1                        lda     ball_yc           ;get Y coordinate
1d64: 18                           clc
1d65: 79 b4 1e                     adc     vectors,y         ;add vector
1d68: 99 b4 1d                     sta     title_xy,y        ;update particle Y position
1d6b: c9 30                        cmp     #48               ;have we reached top edge of box?
1d6d: d0 0d                        bne     @NotTop           ;no, branch
                   ; Invert movement vector Y component.
1d6f: b9 b4 1e     @InvertVY       lda     vectors,y         ;get vector Y
1d72: 49 ff                        eor     #$ff              ;do 2's complement negation
1d74: 18                           clc
1d75: 69 01                        adc     #$01
1d77: 99 b4 1e                     sta     vectors,y         ;update value
1d7a: d0 04                        bne     @Next             ;(always)

1d7c: c9 80        @NotTop         cmp     #128              ;have we reached bottom edge of box?
1d7e: f0 ef                        beq     @InvertVY         ;yes, bounce
1d80: 88           @Next           dey                       ;decrement particle index (back to X coord)
1d81: 98                           tya                       ;save it on stack
1d82: 48                           pha
1d83: b9 b4 1d                     lda     title_xy,y        ;get new X coordinate
1d86: 20 75 16                     jsr     CalcOffAndMask    ;calculate byte offset and bit mask
1d89: 68                           pla                       ;restore particle index
1d8a: a8                           tay
1d8b: c8                           iny                       ;advance to Y coordinate
1d8c: 98                           tya                       ;save it on stack
1d8d: 48                           pha
1d8e: b9 b4 1d                     lda     title_xy,y        ;get new Y coordinate
1d91: 20 10 16                     jsr     GetLineAddr       ;calculate line address
1d94: 20 1d 1d                     jsr     SetPixel          ;draw the pixel
1d97: 68                           pla                       ;restore particle index
1d98: a8                           tay
1d99: c8                           iny                       ;advance to next particle
1d9a: d0 8c                        bne     @AnimLoop         ;branch if we have more to do
                   ; See if we've returned to the initial state by comparing the first four pixels
                   ; to their initial values.
1d9c: a2 00                        ldx     #$00
1d9e: bd b4 1d     @CmpLoop        lda     title_xy,x
1da1: dd ac 1d                     cmp     pos_check,x
1da4: d0 82                        bne     @AnimLoop         ;found a mismatch, keep going
1da6: e8                           inx
1da7: e0 08                        cpx     #8
1da9: 30 f3                        bmi     @CmpLoop
1dab: 60                           rts                       ;done

                   ; 
                   ; Initial position of the first four pixels.  When these match, we're done.
                   ; 
1dac: 67 40 67 41+ pos_check       .bulk   $67,$40,$67,$41,$67,$42,$67,$43

                   ; 
                   ; X/Y coordinates of the individual pixels that make up the "Penny Arcade" title
                   ; text.  There are 128 individual pixels, stored with the X coordinate followed
                   ; by the Y coordinate.
                   ; 
                   ; These values are updated during the animation.  If the animation runs to
                   ; completion, the values will be returned to their initial state.
                   ; 
                   vis
1db4: 67 40 67 41+ title_xy        .bulk   $67,$40,$67,$41,$67,$42,$67,$43
1dbc: 67 44 67 45+                 .bulk   $67,$44,$67,$45,$67,$46,$68,$40
1dc4: 68 43 69 40+                 .bulk   $68,$43,$69,$40,$69,$43,$6a,$41
1dcc: 6a 42 6d 43+                 .bulk   $6a,$42,$6d,$43,$6d,$44,$6d,$45
1dd4: 6e 42 6e 44+                 .bulk   $6e,$42,$6e,$44,$6e,$46,$6f,$42
1ddc: 6f 44 6f 46+                 .bulk   $6f,$44,$6f,$46,$70,$43,$70,$44
1de4: 73 42 73 43+                 .bulk   $73,$42,$73,$43,$73,$44,$73,$45
1dec: 73 46 74 42+                 .bulk   $73,$46,$74,$42,$75,$42,$76,$43
1df4: 76 44 76 45+                 .bulk   $76,$44,$76,$45,$76,$46,$79,$42
1dfc: 79 43 79 44+                 .bulk   $79,$43,$79,$44,$79,$45,$79,$46
1e04: 7a 42 7b 42+                 .bulk   $7a,$42,$7b,$42,$7c,$43,$7c,$44
1e0c: 7c 45 7c 46+                 .bulk   $7c,$45,$7c,$46,$7f,$42,$7f,$43
1e14: 7f 44 7f 45+                 .bulk   $7f,$44,$7f,$45,$7f,$49,$80,$46
1e1c: 80 48 81 47+                 .bulk   $80,$48,$81,$47,$82,$42,$82,$43
1e24: 82 44 82 45+                 .bulk   $82,$44,$82,$45,$82,$46,$6d,$4c
1e2c: 6d 4d 6d 4e+                 .bulk   $6d,$4d,$6d,$4e,$6d,$4f,$6d,$50
1e34: 6d 51 6e 4b+                 .bulk   $6d,$51,$6e,$4b,$6e,$4e,$6f,$4b
1e3c: 6f 4e 70 4c+                 .bulk   $6f,$4e,$70,$4c,$70,$4d,$70,$4e
1e44: 70 4f 70 50+                 .bulk   $70,$4f,$70,$50,$70,$51,$73,$4d
1e4c: 73 4e 73 4f+                 .bulk   $73,$4e,$73,$4f,$73,$50,$73,$51
1e54: 74 4d 75 4d+                 .bulk   $74,$4d,$75,$4d,$76,$4e,$79,$4e
1e5c: 79 4f 79 50+                 .bulk   $79,$4f,$79,$50,$7a,$4d,$7a,$51
1e64: 7b 4d 7b 51+                 .bulk   $7b,$4d,$7b,$51,$7c,$4e,$7f,$4e
1e6c: 7f 4f 7f 50+                 .bulk   $7f,$4f,$7f,$50,$80,$4d,$80,$51
1e74: 81 4d 81 51+                 .bulk   $81,$4d,$81,$51,$82,$4d,$82,$4e
1e7c: 82 4f 82 50+                 .bulk   $82,$4f,$82,$50,$82,$51,$85,$4e
1e84: 85 4f 85 50+                 .bulk   $85,$4f,$85,$50,$86,$4d,$86,$51
1e8c: 87 4d 87 51+                 .bulk   $87,$4d,$87,$51,$88,$4b,$88,$4c
1e94: 88 4d 88 4e+                 .bulk   $88,$4d,$88,$4e,$88,$4f,$88,$50
1e9c: 88 51 8b 4e+                 .bulk   $88,$51,$8b,$4e,$8b,$4f,$8b,$50
1ea4: 8c 4d 8c 4f+                 .bulk   $8c,$4d,$8c,$4f,$8c,$51,$8d,$4d
1eac: 8d 4f 8d 51+                 .bulk   $8d,$4f,$8d,$51,$8e,$4e,$8e,$4f
                   ; 
                   ; Movement vectors.  Each entry is two bytes, one for X and one for Y.  Each
                   ; value is either +1 or -1.  These are modified during the animation, but will
                   ; have returned to their initial configuration when the animation completes.
                   ; 
                   ; The vectors repeat every 4 pixels, which is why the title appears to split
                   ; into 4 pieces.
                   ; 
1eb4: 01 01 01 ff+ vectors         .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1ebc: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1ec4: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1ecc: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1ed4: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1edc: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1ee4: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1eec: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1ef4: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1efc: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f04: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f0c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f14: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f1c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f24: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f2c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f34: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f3c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f44: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f4c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f54: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f5c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f64: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f6c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f74: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f7c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f84: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f8c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f94: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1f9c: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1fa4: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
1fac: 01 01 01 ff+                 .bulk   $01,$01,$01,$ff,$ff,$01,$ff,$ff
                   ; 
                   ; The rest of the file is junk.  The last few bytes sit on the hi-res screen.
                   ; 
1fb4: 8e fd 20 ce+                 .junk   76
2000: 55 2a 55 2a+                 .junk   17
                                   .adrend ↑ $0801

Symbol Table

LabelValue
AnimTitle$1d26
ClearHiRes$1b96
DrawField$1b52
EraseBall$1ae2
PlayGameG$1a82
PlayGameNG$1a5c
UpdatePaddles$197e