********************************************************************************
* Bomber, by Bob Bishop *
* Copyright 1978 Softape *
* *
* This is the older version, which doesn't keep score. *
********************************************************************************
* Disassembly by Andy McFadden, using 6502bench SourceGen v1.7.1. *
* Last updated 2020/08/17 *
********************************************************************************
* There are three shapes: plane, tank, bomb. These are collectively defined *
* as a single series of 128 screen coordinates (two bytes each, 256 bytes *
* total). The data at $0b00 has 55 coordinates for the plane, 2 for the bomb, *
* and 71 for the tank. *
* *
* Each of the 128 X/Y coordinates is tracked as 8.8 fixed-point values. Only *
* the integer part is used when rendering. *
* *
* Each coordinate also has a movement vector, stored as two 8.8 fixed-point *
* values (one for X, one for Y). Initially, the movement values cause the *
* plane to move left at 2 pixels/frame, and the tank to the right at 0.5 *
* pixels/frame. When a bomb is dropped, the two bomb pixels gain a vertical *
* movement value that is increased every frame until the bomb hits the tank or *
* the ground. *
* *
* When the tank is hit, the coordinate movement values for the tank pixels are *
* replaced with pre-computed values, to which a fixed gravitational *
* acceleration is applied. *
********************************************************************************
GRAVITY .eq $10 {const} ;acceleration per frame
PLANE_AND_BOMB .eq $72 {const} ;number of pixels in plane + bomb
bomb_vert_accel .eq $05 ;fractional part; $10 if falling, else 0
cur_coord_lo_ptr .eq $06 {addr/2} ;points to $1200 or $1400
cur_coord_hi_ptr .eq $08 {addr/2} ;points to $1300 or $1500
next_coord_lo_ptr .eq $0a {addr/2} ;points to $1200 or $1400
next_coord_hi_ptr .eq $0c {addr/2} ;points to $1300 or $1500
expl_counter .eq $0e ;counts down during explosion
MON_CH .eq $24 ;cursor horizontal displacement
MON_CV .eq $25 ;cursor vertical displacement
MON_INVFLAG .eq $32 ;text mask (255=normal, 127=flash, 63=inv)
coord_lo_buf0 .eq $1200 {addr/256} ;position (frac), buffer 0
coord_hi_buf0 .eq $1300 {addr/256} ;position (int), buffer 0
coord_lo_buf1 .eq $1400 {addr/256} ;position (frac), buffer 1
coord_hi_buf1 .eq $1500 {addr/256} ;position (int), buffer 1
delta_posn_lo .eq $1600 {addr/256} ;per-frame position change, low byte
delta_posn_hi .eq $1700 {addr/256} ;per-frame position change, hi byte
saved_state .eq $1800 {addr/256} ;buffer in which pre-explosion tank is saved
HIRES_PAGE1 .eq $2000 {addr/8192} ;hi-res page 1
KBD .eq $c000 ;R last key pressed + 128
KBDSTRB .eq $c010 ;RW keyboard strobe
TXTCLR .eq $c050 ;RW display graphics
MIXCLR .eq $c052 ;RW display full screen
MIXSET .eq $c053 ;RW display split screen
HIRES .eq $c057 ;RW display hi-res graphics
MON_VTAB .eq $fc22 ;tab to row specified in Acc
MON_HOME .eq $fc58 ;clear screen and reset text output to top-left
MON_COUT .eq $fded ;print Acc to output device via $36-37
.org $8ab2
;
; Integer BASIC header. Sets variable storage limits, relocates assembly-
; language portion, and updates program-start pointer to code at end.
;
; 0 POKE 74,0: POKE 75,8: POKE 204,0: POKE 205,8: POKE 60,( PEEK (202)+231)
; MOD 256: POKE 61, PEEK (203)+( PEEK (202)+231)/256
; 1 POKE 62,( PEEK (60)+255) MOD 256: POKE 63, PEEK (61)+( PEEK
; (60)+255)/256+9: POKE 66,0: POKE 67,8: CALL -468
; 2 POKE 202,( PEEK (62)+1) MOD 256: POKE 203, PEEK (63)+( PEEK (62)+1)/256:
; GOTO 0
; 2510 ^ +RUN [...]
;
; $4a-4b (74-75) is LOMEM, which is set to $800.
; $cc-cd (204-205) is HIMEM, also set to $800.
;
; The BASIC header is 231 bytes long. The code memory-moves the $a00 bytes that
; follow it to address $0800, using the monitor MOVE function ($fe2c / -468).
;
; $ca-cb (202-203) holds the address of the start of the INTBASIC program
; $3c-3d (60-61, A1 start) is set to the program start + 231
; $3e-3f (62-63, A2 end) is set to A1 + $9ff
; $43-43 (66-67, A4 count) is set to $800
;
; Finally, switch the BASIC program-start pointer to the trailing code:
;
; $ca-cb (202-203) is set to post-move A2, i.e. $9599
;
8ab2: 5a 00 00 64+ .bulk $5a,$00,$00,$64,$b7,$4a,$00,$65,$b0,$00,$00,$03,$64,$b7,$4b,$00
+ $65,$b8,$08,$00,$03,$64,$b2,$cc,$00,$65,$b0,$00,$00,$03,$64,$b2
+ $cd,$00,$65,$b8,$08,$00,$03,$64,$b6,$3c,$00,$65,$38,$2e,$3f,$b2
+ $ca,$00,$72,$12,$b2,$e7,$00,$72,$1f,$b2,$00,$01,$03,$64,$b6,$3d
+ $00,$65,$2e,$3f,$b2,$cb,$00,$72,$12,$38,$2e,$3f,$b2,$ca,$00,$72
+ $12,$b2,$e7,$00,$72,$15,$b2,$00,$01,$01,$52,$01,$00,$64,$b6,$3e
+ $00,$65,$38,$2e,$3f,$b6,$3c,$00,$72,$12,$b2,$ff,$00,$72,$1f,$b2
+ $00,$01,$03,$64,$b6,$3f,$00,$65,$2e,$3f,$b6,$3d,$00,$72,$12,$38
+ $2e,$3f,$b6,$3c,$00,$72,$12,$b2,$ff,$00,$72,$15,$b2,$00,$01,$12
+ $b9,$09,$00,$03,$64,$b6,$42,$00,$65,$b0,$00,$00,$03,$64,$b6,$43
+ $00,$65,$b8,$08,$00,$03,$4d,$36,$b4,$d4,$01,$01,$3b,$02,$00,$64
+ $b2,$ca,$00,$65,$38,$2e,$3f,$b6,$3e,$00,$72,$12,$b1,$01,$00,$72
+ $1f,$b2,$00,$01,$03,$64,$b2,$cb,$00,$65,$2e,$3f,$b6,$3f,$00,$72
+ $12,$38,$2e,$3f,$b6,$3e,$00,$72,$12,$b1,$01,$00,$72,$15,$b2,$00
+ $01,$03,$5f,$b0,$00,$00,$01
.org $0800
0800: 20 ce 09 jsr ShowTitleAndInstr ;show title, pause, print instructions at bottom
0803: 20 35 08 jsr Initialize ;init; does initial draw
0806: 20 9a 08 :GameLoop jsr XdrawShapes ;draw everything
0809: 20 a9 08 jsr CheckCollision ;see if bomb hit tank
080c: 20 7a 09 jsr UpdateCoords ;update positions
080f: 20 9a 08 jsr XdrawShapes ;erase everything
0812: 20 a5 09 jsr SwapPointers ;swap pointers
0815: 20 20 09 jsr UpdateBomb ;drop bomb, or update bomb position
0818: a5 0e lda expl_counter ;is tank exploding?
081a: f0 ea beq :GameLoop ;no, continue loop
081c: 10 0a bpl :ExplInProg ;branch if explosion already in progress
081e: 20 c9 08 jsr PreExplosion ;make a copy of shape data
0821: a9 7f lda #127 ;run animation for 127 frames
0823: 85 0e sta expl_counter ;set counter
0825: 4c 06 08 jmp :GameLoop ;loop again
0828: 20 e0 08 :ExplInProg jsr AnimateExplosion ;update coordinates
082b: c6 0e dec expl_counter ;are we done with animation?
082d: d0 d7 bne :GameLoop ;not yet, loop
082f: 20 fa 08 jsr PostExplosion ;reset state
0832: 4c 06 08 jmp :GameLoop ;keep playing
;
; Initialize game state.
;
0835: 20 c0 0c Initialize jsr ClearHiRes ;clear hi-res screen, enable graphics
0838: 8d 53 c0 sta MIXSET ;enable mixed-mode graphics
083b: a9 00 lda #$00
083d: 85 05 sta bomb_vert_accel ;init bomb acceleration
083f: 85 0e sta expl_counter ;init explosion animation counter
0841: 85 06 sta cur_coord_lo_ptr ;init pointers
0843: 85 08 sta cur_coord_hi_ptr
0845: 85 0a sta next_coord_lo_ptr
0847: 85 0c sta next_coord_hi_ptr
0849: a9 12 lda #>coord_lo_buf0
084b: 85 07 sta cur_coord_lo_ptr+1
084d: a9 13 lda #>coord_hi_buf0
084f: 85 09 sta cur_coord_hi_ptr+1
0851: a9 14 lda #>coord_lo_buf1
0853: 85 0b sta next_coord_lo_ptr+1
0855: a9 15 lda #>coord_hi_buf1
0857: 85 0d sta next_coord_hi_ptr+1
; Init $1300 to an alternating pattern of an ascending value and $9F (159), then
; draw it This is a complicated way to draw a green line across the bottom of
; the screen.
0859: a0 00 ldy #$00
085b: 18 clc
085c: 98 :Loop1 tya
085d: 69 01 adc #$01
085f: 91 08 sta (cur_coord_hi_ptr),y
0861: c8 iny
0862: a9 9f lda #$9f
0864: 91 08 sta (cur_coord_hi_ptr),y
0866: c8 iny
0867: d0 f3 bne :Loop1
0869: 20 9a 08 jsr XdrawShapes
; Set fractional positions to zero, and copy $0b00-0bff to set integer position.
086c: a0 00 ldy #$00
086e: a9 00 :Loop2 lda #$00
0870: 91 06 sta (cur_coord_lo_ptr),y
0872: b9 00 0b lda pixel_data,y
0875: 91 08 sta (cur_coord_hi_ptr),y
0877: c8 iny
0878: d0 f4 bne :Loop2
; Init movement to zero for all coordinates.
087a: a9 00 lda #$00
087c: 99 00 16 :Loop3 sta delta_posn_lo,y
087f: 99 00 17 sta delta_posn_hi,y
0882: c8 iny
0883: d0 f7 bne :Loop3
; Set plane/bomb movement to -2.0.
0885: a9 fe lda #$fe ;integer
0887: 99 00 17 :Loop4 sta delta_posn_hi,y
088a: c8 iny
088b: c8 iny
088c: c0 72 cpy #PLANE_AND_BOMB
088e: d0 f7 bne :Loop4
; Set tank movement to +0.5.
0890: a9 80 lda #$80 ;fractional part
0892: 99 00 16 :Loop5 sta delta_posn_lo,y
0895: c8 iny
0896: c8 iny
0897: d0 f9 bne :Loop5
0899: 60 rts
;
; Xdraws plane, tank, and bomb.
;
]data_ptr .var $00 {addr/2}
]count .var $02 {addr/1}
089a: a5 08 XdrawShapes lda cur_coord_hi_ptr ;draw "current" coordinates
089c: 85 00 sta ]data_ptr
089e: a5 09 lda cur_coord_hi_ptr+1
08a0: 85 01 sta ]data_ptr+1
08a2: a9 80 lda #$80 ;plane+bomb+tank have 128 total pixels
08a4: 85 02 sta ]count
08a6: 4c c0 0d jmp XdrawPixelSet
;
; Checks for a collision between the bomb and a tank.
;
08a9: a5 0e CheckCollision lda expl_counter ;already exploding?
08ab: d0 1b bne :Return ;yes, bail
08ad: a0 6f ldy #PLANE_AND_BOMB-3 ;index row of first bomb pixel
08af: b1 08 lda (cur_coord_hi_ptr),y ;get row
08b1: c9 98 cmp #152 ;reached top of tank?
08b3: 90 13 bcc :Return ;not yet, bail
08b5: 88 dey ;index col
08b6: b1 08 lda (cur_coord_hi_ptr),y ;get bomb column
08b8: a0 7c ldy #PLANE_AND_BOMB+10
08ba: f1 08 sbc (cur_coord_hi_ptr),y ;subtract column of tank pixel #5
08bc: 10 02 bpl :IsPos ; (near center)
08be: 49 ff eor #$ff ;negate (note no +1)
08c0: c9 0b :IsPos cmp #11 ;within 10 pixels?
08c2: b0 04 bcs :Return ;no, bail
08c4: a9 ff lda #$ff
08c6: 85 0e sta expl_counter ;hit!
08c8: 60 :Return rts
;
; Does initial prep for explosion animation. Saves current tank position and
; initializes pixel movement.
;
08c9: a0 72 PreExplosion ldy #PLANE_AND_BOMB ;start at first tank pixel
08cb: b1 08 :Loop lda (cur_coord_hi_ptr),y
08cd: 99 00 18 sta saved_state,y ;save current position data
08d0: b9 00 10 lda expl_move_lo,y ;copy explosion movement in
08d3: 99 00 16 sta delta_posn_lo,y
08d6: b9 00 11 lda expl_move_hi,y
08d9: 99 00 17 sta delta_posn_hi,y
08dc: c8 iny
08dd: d0 ec bne :Loop
08df: 60 rts
;
; Updates pixel coordinates during the explosion.
;
AnimateExplosion
08e0: a0 73 ldy #PLANE_AND_BOMB+1 ;first tank pixel, +1 to modify row
08e2: 18 :Loop clc
08e3: b9 00 16 lda delta_posn_lo,y ;apply gravity to vertical movement values
08e6: 69 10 adc #GRAVITY
08e8: 99 00 16 sta delta_posn_lo,y
08eb: b9 00 17 lda delta_posn_hi,y
08ee: 69 00 adc #$00
08f0: 99 00 17 sta delta_posn_hi,y
08f3: c8 iny
08f4: c8 iny ;move to next row value
08f5: c0 01 cpy #$01 ;off end of page?
08f7: d0 e9 bne :Loop ;not yet, loop
08f9: 60 rts
;
; Resets state after explosion has finished. The tank reappears where it last
; was.
;
08fa: a0 72 PostExplosion ldy #PLANE_AND_BOMB ;start at first byte of tank
08fc: b9 00 18 :Loop lda saved_state,y
08ff: 91 08 sta (cur_coord_hi_ptr),y ;restore integer part of tank position data
0901: a9 00 lda #$00
0903: 91 06 sta (cur_coord_lo_ptr),y ;clear fractional part of position data
0905: 99 00 17 sta delta_posn_hi,y ;set movement to zero
0908: 99 00 16 sta delta_posn_lo,y
090b: c8 iny
090c: d0 ee bne :Loop
; Reset tank movement and bomb.
090e: a0 72 ldy #PLANE_AND_BOMB
0910: a9 80 lda #$80
0912: 99 00 16 :Loop2 sta delta_posn_lo,y ;set to 0.5 pixels per frame
0915: c8 iny
0916: c8 iny
0917: d0 f9 bne :Loop2
0919: 20 57 09 jsr ResetBomb ;reset bomb state
091c: 8d 10 c0 sta KBDSTRB ;clear keyboard strobe
091f: 60 rts
;
; Checks for bomb drop initiation. If bomb is falling, applies acceleration,
; and checks for impact with ground.
;
0920: a5 0e UpdateBomb lda expl_counter ;exploding?
0922: d0 55 bne :Return ;yes, bail
0924: ad 00 c0 lda KBD ;check keyboard
0927: 10 0b bpl :NoKey ;branch if key not hit
0929: 8d 10 c0 sta KBDSTRB ;clear keyboard strobe
092c: a5 05 lda bomb_vert_accel ;is the bomb already falling?
092e: d0 04 bne :NoKey ;yes, continue
0930: a9 10 lda #GRAVITY
0932: 85 05 sta bomb_vert_accel ;set nonzero vertical acceleration
; Update speed at which the two bomb pixels are falling.
0934: a0 6f :NoKey ldy #PLANE_AND_BOMB-3 ;index row byte of first bomb pixel
0936: 18 clc
0937: b9 00 16 lda delta_posn_lo,y ;get speed, low byte
093a: 65 05 adc bomb_vert_accel ;update it
093c: 99 00 16 sta delta_posn_lo,y ;save it
093f: 48 pha
0940: b9 00 17 lda delta_posn_hi,y ;get speed, high byte
0943: 69 00 adc #$00
0945: 99 00 17 sta delta_posn_hi,y
0948: c8 iny
0949: c8 iny
094a: 99 00 17 sta delta_posn_hi,y ;set high value for second pixel
094d: 68 pla
094e: 99 00 16 sta delta_posn_lo,y ;set low value for second pixel
; Check if we've reached the ground.
0951: b1 08 lda (cur_coord_hi_ptr),y ;get bomb's current row
0953: c9 a0 cmp #160 ;reached bottom of screen?
0955: d0 22 bne :Return ;not yet, bail
; Reset bomb position and acceleration.
0957: a0 71 ResetBomb ldy #PLANE_AND_BOMB-1 ;index row byte of second bomb pixel
0959: a9 07 lda #$07
095b: 91 08 sta (cur_coord_hi_ptr),y ;return to row 7
095d: a9 00 lda #$00
095f: 91 06 sta (cur_coord_lo_ptr),y ;set vertical movement to zero
0961: 99 00 16 sta delta_posn_lo,y
0964: 99 00 17 sta delta_posn_hi,y
0967: 88 dey ;back up to first bomb pixel
0968: 88 dey
0969: 99 00 17 sta delta_posn_hi,y ;reset those too
096c: 99 00 16 sta delta_posn_lo,y
096f: 91 06 sta (cur_coord_lo_ptr),y
0971: a9 07 lda #$07
0973: 91 08 sta (cur_coord_hi_ptr),y
0975: a9 00 lda #$00
0977: 85 05 sta bomb_vert_accel ;set bomb acceleration to zero
0979: 60 :Return rts
;
; Updates the coordinates for plane, tank, and bomb. Values are read from the
; "current" buffer and written to the "next" buffer.
;
; If tank fragments have fallen "below" ground, we keep updating and drawing
; them off-screen.
;
097a: a0 00 UpdateCoords ldy #$00 ;start with column byte
097c: 18 :PairLoop clc
097d: b1 06 lda (cur_coord_lo_ptr),y ;get current position, fractional part
097f: 79 00 16 adc delta_posn_lo,y ;apply movement
0982: 91 0a sta (next_coord_lo_ptr),y ;store for next frame
0984: b1 08 lda (cur_coord_hi_ptr),y ;repeat for integer part
0986: 79 00 17 adc delta_posn_hi,y
0989: 91 0c sta (next_coord_hi_ptr),y
098b: c8 iny ;advance to row byte
098c: 18 clc
098d: b1 06 lda (cur_coord_lo_ptr),y
098f: 79 00 16 adc delta_posn_lo,y
0992: 91 0a sta (next_coord_lo_ptr),y
0994: b1 08 lda (cur_coord_hi_ptr),y
0996: 79 00 17 adc delta_posn_hi,y
0999: c9 a0 cmp #160 ;off bottom of screen?
099b: 90 02 bcc :InView
099d: a9 a0 lda #160 ;clamp to screen, just below mixed-mode graphics area
099f: 91 0c :InView sta (next_coord_hi_ptr),y
09a1: c8 iny
09a2: d0 d8 bne :PairLoop
09a4: 60 rts
;
; Swaps $06-07, $08-09 with $0a-0b, $0c-0d.
;
09a5: a5 06 SwapPointers lda cur_coord_lo_ptr
09a7: 48 pha
09a8: a5 0a lda next_coord_lo_ptr
09aa: 85 06 sta cur_coord_lo_ptr
09ac: 68 pla
09ad: 85 0a sta next_coord_lo_ptr
09af: a5 07 lda cur_coord_lo_ptr+1
09b1: 48 pha
09b2: a5 0b lda next_coord_lo_ptr+1
09b4: 85 07 sta cur_coord_lo_ptr+1
09b6: 68 pla
09b7: 85 0b sta next_coord_lo_ptr+1
09b9: a5 08 lda cur_coord_hi_ptr
09bb: 48 pha
09bc: a5 0c lda next_coord_hi_ptr
09be: 85 08 sta cur_coord_hi_ptr
09c0: 68 pla
09c1: 85 0c sta next_coord_hi_ptr
09c3: a5 09 lda cur_coord_hi_ptr+1
09c5: 48 pha
09c6: a5 0d lda next_coord_hi_ptr+1
09c8: 85 09 sta cur_coord_hi_ptr+1
09ca: 68 pla
09cb: 85 0d sta next_coord_hi_ptr+1
09cd: 60 rts
;
; Clears the screen and briefly shows the title text, then draws the in-game
; instructions.
;
]text_ptr .var $00 {addr/2}
]timer .var $03 {addr/2}
ShowTitleAndInstr
09ce: 20 58 fc jsr MON_HOME ;clear screen
09d1: a9 0a lda #10
09d3: 85 25 sta MON_CV ;text col 10
09d5: 20 22 fc jsr MON_VTAB
09d8: a0 00 ldy #$00 ;start at char 0
09da: a9 0d lda #13 ;text col 13
09dc: 85 24 sta MON_CH
09de: ad 34 0a lda text_addr
09e1: 85 00 sta ]text_ptr
09e3: ad 35 0a lda text_addr+1
09e6: 85 01 sta ]text_ptr+1
09e8: 20 26 0a jsr PrintString ;print null-terminated string, advancing Y-reg
09eb: a9 13 lda #19 ;text col 19
09ed: 85 24 sta MON_CH
09ef: 20 26 0a jsr PrintString ;print next string ("BY")
09f2: a9 0f lda #15 ;text col 15
09f4: 85 24 sta MON_CH
09f6: 20 26 0a jsr PrintString ;print next string (author / copyright)
; Pause briefly.
09f9: a9 00 lda #$00
09fb: 85 03 sta ]timer
09fd: 85 04 sta ]timer+1
09ff: a2 06 ldx #$06
0a01: c6 03 :WaitLoop dec ]timer
0a03: d0 fc bne :WaitLoop
0a05: c6 04 dec ]timer+1
0a07: d0 f8 bne :WaitLoop
0a09: ca dex
0a0a: d0 f5 bne :WaitLoop
; Print in-game instructions.
0a0c: a9 14 lda #20 ;top row of hgr text window
0a0e: 85 25 sta MON_CV
0a10: 20 22 fc jsr MON_VTAB
0a13: a9 02 lda #2 ;column 2
0a15: 85 24 sta MON_CH
0a17: a9 7f lda #$7f
0a19: 85 32 sta MON_INVFLAG ;inverse text
0a1b: 20 26 0a jsr PrintString
0a1e: a9 ff lda #$ff
0a20: 85 32 sta MON_INVFLAG ;normal text
0a22: 20 26 0a jsr PrintString
0a25: 60 rts
;
; Prints a null-terminated string with COUT at the current text position.
;
; On entry:
; $00-01: string pointer
; Y-reg: current position in string
;
0a26: b1 00 PrintString lda (]text_ptr),y ;get char
0a28: f0 08 beq :Done ;if '\0', bail
0a2a: 09 80 ora #$80 ;make sure high bit is set
0a2c: 20 ed fd jsr MON_COUT ;output char
0a2f: c8 iny
0a30: d0 f4 bne PrintString
0a32: c8 :Done iny ;advance past null termination
0a33: 60 rts
0a34: 36 0a text_addr .dd2 title_strings
;
; Strings printed for the title and instructions.
0a36: 2a 2a 2a 20+ title_strings .str ‘*** BOMBER ***’
0a44: 8d .dd1 $8d
0a45: 8d .dd1 $8d
0a46: 00 .dd1 $00
0a47: 42 59 .str ‘BY’
0a49: 8d .dd1 $8d
0a4a: 8d .dd1 $8d
0a4b: 00 .dd1 $00
0a4c: 42 4f 42 20+ .str ‘BOB BISHOP’
0a56: 8d 8d a0 a0+ .str $8d,$8d,“ COPYRIGHT (C) 1978 SOFTAPE”,$8d
0a7a: 00 .dd1 $00
0a7b: 20 20 20 20+ .str ‘ ’ ;37 spaces (printed in inverse)
0aa0: 8d .dd1 $8d
0aa1: 8d .dd1 $8d
0aa2: 00 .dd1 $00
0aa3: 20 20 20 20+ .str ‘ (HIT ANY KEY TO RELEASE THE BOMB)’
0ac8: 00 .dd1 $00
;
0ac9: 00 ff ff ff+ .align $0100 (55 bytes)
;
; Bomber image (27x8), defined as a series of coordinate values. Even bytes are
; column (0-255), odd bytes are row (0-191).
;
; The bomber has 55 pixels ($6e bytes), plus two more for the bomb. When the
; bomb isn't dropping, the coordinates place it under the plane, so you can
; treat plane+bomb as a single $72-byte shape.
;
; Top part of tail is row 0, placing the shape at the top of the screen.
;
0b00: f0 06 f1 06+ pixel_data .bulk $f0,$06,$f1,$06,$f2,$06,$f3,$06,$f4,$06,$f5,$06,$f6,$06,$f7,$06
+ $f8,$06,$f9,$06,$fa,$06,$fb,$05,$fc,$05,$fd,$05,$fe,$05,$fe,$04
+ $ff,$03,$ff,$02,$ff,$01,$ff,$00,$fe,$00,$fd,$01,$fc,$02,$fb,$03
+ $fa,$04,$f9,$04,$f8,$04,$f7,$04,$f6,$04,$f5,$04,$f4,$04,$f3,$04
+ $f2,$04,$f1,$04,$f0,$04,$ef,$04,$ee,$03,$ed,$03,$ec,$03,$eb,$04
+ $ea,$04,$e9,$04,$e8,$05,$e5,$05,$e6,$05,$e7,$05,$e7,$06,$e8,$06
+ $e9,$06,$ea,$06,$eb,$06,$ec,$06,$ed,$06,$ee,$06,$ef,$06,$f0,$07
+ $f1,$07
;
; Tank image (23x13). 71 pixels ($8e bytes). Note this fills out the rest of
; the page exactly.
;
; Bottom row is 158, one up from the green line drawn at the bottom of the
; mixed-mode graphics area.
;
0b72: 55 98 56 98+ .bulk $55,$98,$56,$98,$57,$98,$58,$98,$59,$98,$5a,$98,$5b,$98,$5c,$98
+ $5c,$97,$5d,$96,$5d,$95,$5c,$94,$5b,$94,$5a,$94,$59,$94,$58,$94
+ $58,$93,$57,$93,$57,$92,$56,$93,$56,$94,$55,$94,$54,$94,$53,$95
+ $53,$96,$54,$97,$54,$98,$53,$98,$52,$98,$51,$98,$50,$98,$4f,$98
+ $4e,$98,$4d,$99,$4d,$9a,$4e,$9b,$4e,$9c,$4f,$9d,$50,$9e,$51,$9e
+ $52,$9e,$53,$9e,$54,$9e,$55,$9e,$56,$9e,$57,$9e,$58,$9e,$59,$9e
+ $5a,$9e,$5b,$9e,$5c,$9e,$5d,$9e,$5e,$9e,$5f,$9e,$60,$9e,$61,$9d
+ $62,$9c,$63,$9b,$63,$9a,$62,$99,$61,$98,$60,$98,$5f,$98,$5e,$98
+ $5d,$98,$5e,$95,$5f,$95,$60,$95,$61,$95,$62,$95,$63,$95
;
; Hi-res row base address, low byte. Offset by 2. (We only use 256 of 280
; pixels, so the left side is offset 2 bytes, and the right side is short about
; 1.5 bytes.)
0c00: 02 02 02 02+ hires_addr_lo .bulk $02,$02,$02,$02,$02,$02,$02,$02,$82,$82,$82,$82,$82,$82,$82,$82
+ $02,$02,$02,$02,$02,$02,$02,$02,$82,$82,$82,$82,$82,$82,$82,$82
+ $02,$02,$02,$02,$02,$02,$02,$02,$82,$82,$82,$82,$82,$82,$82,$82
+ $02,$02,$02,$02,$02,$02,$02,$02,$82,$82,$82,$82,$82,$82,$82,$82
+ $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
+ $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
+ $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
+ $2a,$2a,$2a,$2a,$2a,$2a,$2a,$2a,$aa,$aa,$aa,$aa,$aa,$aa,$aa,$aa
+ $52,$52,$52,$52,$52,$52,$52,$52,$d2,$d2,$d2,$d2,$d2,$d2,$d2,$d2
+ $52,$52,$52,$52,$52,$52,$52,$52,$d2,$d2,$d2,$d2,$d2,$d2,$d2,$d2
+ $52,$52,$52,$52,$52,$52,$52,$52,$d2,$d2,$d2,$d2,$d2,$d2,$d2,$d2
+ $52,$52,$52,$52,$52,$52,$52,$52,$d2,$d2,$d2,$d2,$d2,$d2,$d2,$d2
;
; Clears hi-res page 1 to zeroes, and enables hi-res graphics.
;
• Clear variables
]ptr .var $03 {addr/2}
0cc0: a0 00 ClearHiRes ldy #<HIRES_PAGE1 ;init pointer to hi-res page 1
0cc2: 84 03 sty ]ptr
0cc4: a2 20 ldx #>HIRES_PAGE1 ;value $20 also used as page counter
0cc6: 86 04 stx ]ptr+1
0cc8: 98 tya
0cc9: 91 03 :ClearLoop sta (]ptr),y
0ccb: c8 iny
0ccc: d0 fb bne :ClearLoop
0cce: e6 04 inc ]ptr+1
0cd0: ca dex
0cd1: d0 f6 bne :ClearLoop
0cd3: 8d 50 c0 sta TXTCLR ;enable graphics
0cd6: 8d 52 c0 sta MIXCLR ;disable mixed-mode
0cd9: 8d 57 c0 sta HIRES ;enable hi-res
0cdc: 60 rts
0cdd: 02 04 08 10+ .align $0100 (35 bytes)
;
; Hi-res row base address, high byte.
0d00: 20 24 28 2c+ hires_addr_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
+ $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
+ $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
;
; Draws a series of pixels with exclusive-OR. Call a second time to erase.
;
; The data stream is pairs of bytes. The first byte is the column (0-255), the
; second byte is the row (0-191).
;
; On entry:
; $00-01: pointer to shape data
; $02: number of pairs of bytes of data
;
• Clear variables
]data_ptr .var $00 {addr/2}
]count .var $02 {addr/1}
]hptr .var $03 {addr/2}
0dc0: a0 00 XdrawPixelSet ldy #$00
0dc2: b1 00 lda (]data_ptr),y ;get X coordinate
0dc4: e6 00 inc ]data_ptr ;advance pointer (low byte only)
0dc6: aa tax ;hold in X-reg
0dc7: b1 00 lda (]data_ptr),y ;get Y coordinate
0dc9: e6 00 inc ]data_ptr ;advance pointer (low byte only)
0dcb: a8 tay
0dcc: b9 00 0c lda hires_addr_lo,y ;look up line address
0dcf: 85 03 sta ]hptr ;set hi-res pointer
0dd1: b9 00 0d lda hires_addr_hi,y
0dd4: 85 04 sta ]hptr+1
0dd6: bc 00 0e ldy xc_to_byte,x ;get byte offset
0dd9: bd 00 0f lda xc_to_pixel,x ;get pixel mask
0ddc: 51 03 eor (]hptr),y ;XOR with screen contents
0dde: 91 03 sta (]hptr),y ;store
0de0: c6 02 dec ]count ;more to do?
0de2: d0 dc bne XdrawPixelSet ;no, continue
0de4: 60 rts
0de5: 05 05 05 05+ .align $0100 (27 bytes)
;
; Converts an X coordinate (0-255) to a byte offset. This is in addition to the
; 2-column shift added by the address lookup table.
0e00: 00 00 00 00+ xc_to_byte .bulk $00,$00,$00,$00,$00,$00,$00,$01,$01,$01,$01,$01,$01,$01,$02,$02
+ $02,$02,$02,$02,$02,$03,$03,$03,$03,$03,$03,$03,$04,$04,$04,$04
+ $04,$04,$04,$05,$05,$05,$05,$05,$05,$05,$06,$06,$06,$06,$06,$06
+ $06,$07,$07,$07,$07,$07,$07,$07,$08,$08,$08,$08,$08,$08,$08,$09
+ $09,$09,$09,$09,$09,$09,$0a,$0a,$0a,$0a,$0a,$0a,$0a,$0b,$0b,$0b
+ $0b,$0b,$0b,$0b,$0c,$0c,$0c,$0c,$0c,$0c,$0c,$0d,$0d,$0d,$0d,$0d
+ $0d,$0d,$0e,$0e,$0e,$0e,$0e,$0e,$0e,$0f,$0f,$0f,$0f,$0f,$0f,$0f
+ $10,$10,$10,$10,$10,$10,$10,$11,$11,$11,$11,$11,$11,$11,$12,$12
+ $12,$12,$12,$12,$12,$13,$13,$13,$13,$13,$13,$13,$14,$14,$14,$14
+ $14,$14,$14,$15,$15,$15,$15,$15,$15,$15,$16,$16,$16,$16,$16,$16
+ $16,$17,$17,$17,$17,$17,$17,$17,$18,$18,$18,$18,$18,$18,$18,$19
+ $19,$19,$19,$19,$19,$19,$1a,$1a,$1a,$1a,$1a,$1a,$1a,$1b,$1b,$1b
+ $1b,$1b,$1b,$1b,$1c,$1c,$1c,$1c,$1c,$1c,$1c,$1d,$1d,$1d,$1d,$1d
+ $1d,$1d,$1e,$1e,$1e,$1e,$1e,$1e,$1e,$1f,$1f,$1f,$1f,$1f,$1f,$1f
+ $20,$20,$20,$20,$20,$20,$20,$21,$21,$21,$21,$21,$21,$21,$22,$22
+ $22,$22,$22,$22,$22,$23,$23,$23,$23,$23,$23,$23,$24,$24,$24,$24
;
; Converts an X coordinate (0-255) to a pixel value.
0f00: 01 02 04 08+ xc_to_pixel .bulk $01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02
+ $04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08
+ $10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20
+ $40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01
+ $02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04
+ $08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10
+ $20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40
+ $01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02
+ $04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08
+ $10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20
+ $40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01
+ $02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04
+ $08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10
+ $20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40
+ $01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02
+ $04,$08,$10,$20,$40,$01,$02,$04,$08,$10,$20,$40,$01,$02,$04,$08
;
; Explosion movement, fractional part. Values at +$72-ff are used for the tank.
1000: 4b 50 10 0b+ expl_move_lo .bulk $4b,$50,$10,$0b,$40,$1d,$b5,$3c,$ec,$dc,$cc,$f0,$14,$42,$ad,$a1
+ $45,$19,$f4,$5b,$73,$d0,$19,$f6,$d3,$f3,$e0,$16,$cc,$d3,$f0,$0e
+ $76,$e8,$98,$99,$ce,$74,$4a,$10,$26,$f2,$b3,$da,$13,$fd,$9c,$fc
+ $f7,$86,$c1,$5e,$7c,$f5,$3d,$b1,$64,$51,$66,$dd,$b2,$ac,$c5,$0f
+ $2d,$8c,$c4,$47,$91,$56,$cb,$70,$29,$d7,$b5,$3d,$a8,$9c,$d4,$77
+ $89,$c2,$ac,$d6,$f5,$0b,$51,$6f,$13,$d1,$48,$b2,$8c,$ed,$83,$de
+ $4d,$be,$47,$a9,$e0,$22,$86,$f8,$8e,$75,$17,$a8,$bb,$64,$7a,$2a
+ $12,$99,$d6,$c8,$8f,$19,$f5,$1f,$33,$c8,$9e,$6b,$53,$f2,$97,$a6
+ $de,$76,$c4,$6e,$77,$b9,$dc,$c6,$d0,$17,$82,$91,$4b,$45,$14,$4c
+ $d9,$e3,$fd,$bc,$f6,$db,$79,$c3,$ea,$3c,$cd,$b0,$00,$1b,$52,$a5
+ $2d,$98,$84,$40,$10,$2f,$1e,$70,$32,$a7,$b0,$1c,$f3,$d6,$d4,$67
+ $9d,$84,$55,$36,$c8,$8b,$4d,$b4,$67,$aa,$20,$1e,$6c,$f8,$83,$cd
+ $95,$38,$96,$c1,$7a,$22,$98,$ba,$2a,$38,$91,$59,$fb,$72,$89,$f5
+ $2a,$3d,$a3,$f8,$97,$af,$32,$b5,$2c,$da,$3a,$39,$d3,$e7,$82,$b1
+ $41,$69,$eb,$4e,$6d,$a3,$c5,$31,$47,$a4,$7a,$00,$1a,$16,$e5,$35
+ $1f,$19,$c0,$11,$58,$ae,$62,$97,$93,$d0,$1d,$a2,$92,$8b,$79,$fe
;
; Explosion movement, integer part. Values at +$72-ff are used for the tank.
1100: ff fe ff fd+ expl_move_hi .bulk $ff,$fe,$ff,$fd,$00,$ff,$00,$ff,$00,$fd,$00,$fe,$00,$fd,$00,$fe
+ $ff,$fe,$00,$ff,$ff,$fe,$ff,$ff,$00,$fe,$ff,$fd,$ff,$ff,$ff,$fd
+ $ff,$fd,$00,$ff,$ff,$ff,$00,$ff,$ff,$fe,$00,$ff,$ff,$fd,$ff,$ff
+ $00,$ff,$ff,$fd,$00,$fd,$ff,$ff,$ff,$fe,$ff,$fe,$ff,$ff,$00,$ff
+ $00,$fd,$00,$fe,$00,$fd,$00,$fd,$00,$fe,$00,$ff,$00,$ff,$00,$fd
+ $ff,$ff,$ff,$fe,$00,$fd,$ff,$ff,$ff,$ff,$00,$ff,$00,$fe,$00,$fd
+ $00,$ff,$00,$fe,$ff,$ff,$00,$fd,$ff,$fe,$00,$fd,$ff,$ff,$ff,$fe
+ $ff,$fd,$00,$ff,$00,$fd,$ff,$ff,$ff,$fe,$ff,$fd,$00,$fd,$ff,$fe
+ $ff,$fd,$00,$fd,$ff,$fe,$00,$fe,$ff,$fd,$00,$fd,$00,$fe,$ff,$fd
+ $00,$ff,$00,$fe,$ff,$fe,$ff,$fe,$00,$fe,$ff,$fe,$00,$ff,$00,$fe
+ $ff,$fe,$00,$fd,$00,$ff,$ff,$ff,$00,$fd,$00,$fd,$ff,$fd,$ff,$fe
+ $ff,$fd,$ff,$ff,$ff,$fe,$ff,$fd,$00,$fd,$00,$fd,$ff,$fd,$ff,$ff
+ $00,$fe,$ff,$fe,$00,$fe,$ff,$fe,$00,$fd,$ff,$ff,$00,$ff,$ff,$fe
+ $00,$fe,$ff,$ff,$00,$ff,$ff,$fe,$00,$ff,$00,$fe,$ff,$ff,$ff,$fe
+ $ff,$fe,$ff,$fd,$00,$fe,$ff,$ff,$ff,$ff,$ff,$fd,$00,$fe,$ff,$fe
+ $00,$fd,$ff,$ff,$00,$ff,$00,$fd,$ff,$fe,$00,$ff,$00,$ff,$00,$ff
.org $9599
;
; Integer BASIC footer. The initial header changes the start-of-program pointer
; to this address.
;
; 0 REM *** BOMBER BY BISHOP ***
; 1 REM
; COPYRIGHT 1978 SOFTAPE
; 2 REM
; * ALL RIGHTS RESERVED *
; 4 REM
;
; 10 CALL 2048
;
9599: 1e integer_prog .dd1 $1e
959a: 00 00 .dd2 0 ;line 0
959c: 5d .dd1 $5d ;REM
959d: a0 aa aa aa+ .str “ *** BOMBER BY BISHOP ***”
95b6: 01 .dd1 $01
95b7: 1d .dd1 $1d
95b8: 01 00 .dd2 1
95ba: 5d .dd1 $5d ;REM
95bb: a0 8a c3 cf+ .str “ ”,$8a,“COPYRIGHT 1978 SOFTAPE”
95d3: 01 .dd1 $01
95d4: 1e .dd1 $1e
95d5: 02 00 .dd2 2
95d7: 5d .dd1 $5d ;REM
95d8: a0 8a aa a0+ .str “ ”,$8a,“* ALL RIGHTS RESERVED *”
95f1: 01 .dd1 $01
95f2: 06 .dd1 $06
95f3: 04 00 .dd2 4
95f5: 5d .dd1 $5d ;REM
95f6: 8a .dd1 $8a
95f7: 01 .dd1 $01
95f8: 08 .dd1 $08
95f9: 0a 00 .dd2 10
95fb: 4d .dd1 $4d ;CALL
95fc: b2 .dd1 $b2 ;(integer constant)
95fd: 00 08 .dd2 $0800 ;2048
95ff: 01 .dd1 $01
No exported symbols found.