******************************************************************************** * 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.