A.N.A.L.O.G. ISSUE 9 / JANUARY 1983 / PAGE 80
In this version of the now famous “Non-Tutorial” series, I thought it would be a good time for a small machine language game. Something simple, yet fun. Something with action, sound effects, player missile graphics, and absolutely FREE. After banging my head against a wall for ten minutes and coming up with some obvious rip-off’s like “PacMan Meets Godzilla” and “Communist Preppies From Space”, I thought of having a rabbit (you must remember Harvey, the invisible rabbit, from the movie by the same name?) in a room with walls moving in on him. Sound good?
Here is a very quick description of the game so far: Harvey Wallbanger is situated in the middle of a closed-in room. He may move freely within the room (that part of the screen within the four walls) but the room is constantly getting smaller (the walls are moving in on our rabbit friend.) Harvey is allowed to touch the left and right hand walls, but he will be killed if flattened by these two walls. He is under no circumstances allowed to touch the top and bottom walls, for they are highly electrified.
All is not lost for Harvey, however. He does have his patented “Wallbanger Gun” ™ to shoot at the walls and make them move away. His only problem is that the speed of the moving walls constantly increases with time. Numbers will appear on the screen that Harvey may collect. These numbers will be added to his score. The faster you collect the numbers, the bigger the final score. The numbers may not be within the confines of the now-receding wall and this will necessitate that Harvey shoot back a wall to access the numbers. Also, Harvey cannot shoot the numbers as this will kill off that particular number and generate a new one someplace else. By the way, I happen to be thinking up this game as I am writing this description. (Shows you how organized he is. Ed.)
As you read the Assembler listing for the game you will notice that there are no line numbers in the source code. This is due to the fact that I am using the ATARI Macro Assembler package exclusively now.
There are two BASIC programs following the machine language listing of Harvey Wallbanger. The first is a disk file maker program to get the game up and running faster than typing in the Assembler source listing. The second BASIC listing will contain modifications to the first to make a cassette bootable machine language tape for the cassette-bound crowd.
; ====================================== ; HARVEY WALLBANGER by Charles Bachand ; ====================================== ; ====================================== ; Copyright (C) 1982 ANALOG Magazine ; ====================================== ; ------------------------ ; Operating System Equates ; ------------------------ HPOSP0 = $D000 ;player 0 horizontal position M0PF = $D000 ;missile 0/playfield collision HPOSP2 = $D002 ;player 2 horizontal position HPOSP3 = $D003 ;player 3 horizontal position HPOSM0 = $D004 ;missile 0 horizontal position P0PF = $D004 ;player 0/playfield collisions P0PL = $D00C ;player 0 to player collisions GRP2 = $D00F ;player 2 graphics register COLBK = $D01A ;background color GRACTL = $D01D ;graphics control register HITCLR = $D01E ;collision 'HIT' clear CONSOL = $D01F ;console switch port AUDF1 = $D200 ;audio frequency 1 AUDC1 = $D201 ;audio volume 1 AUDF2 = $D202 ;audio frequency 2 AUDC2 = $D203 ;audio volume 2 AUDF3 = $D204 ;audio frequency 3 AUDC3 = $D205 ;audio volume 3 AUDF4 = $D206 ;audio frequency 4 AUDC4 = $D207 ;audio volume 4 RANDOM = $D20A ;random number generator IRQEN = $D20E ;IRQ interrupt enable PMBASE = $D407 ;P/M base address WSYNC = $D40A ;wait for horizontal sync VCOUNT = $D40B ;scan line counter SETVBV = $E45C ;set vertical blank vector XITVBV = $E462 ;vertical blank exit vector SIOINT = $E465 ;serial I/O initialization ATRACT = $004D ;atract mode counter ; ----------------------- ; System Shadow Registers ; ----------------------- RTCLOK = $0012 ;system clock CDTMV1 = $0218 ;system timer 1 CDTMV2 = $021A ;system timer 2 CDTMA1 = $0226 ;system timer 1 vector CDTMA2 = $0228 ;system timer 2 vector SDMCTL = $022F ;DMA control SDLSTL = $0230 ;display list pointer GPRIOR = $026F ;graphics priority STICK0 = $0278 ;joystick 1 STRIG0 = $0284 ;trigger 1 PCOLR0 = $02C0 ;player 0 color PCOLR1 = $02C1 ;player 1 color PCOLR2 = $02C2 ;player 2 color PCOLR3 = $02C3 ;player 3 color COLOR2 = $02C6 ;playfield 2 color COLOR3 = $02C7 ;playfield 3 color COLOR4 = $02C8 ;background color ; ------------------- ; Page Zero Variables ; ------------------- ORG $0080 ;area not used by system PIC DS 2 ;rabbit image pointer ; -------------------------- ; Player / Missile RAM Space ; -------------------------- ORG $3000 ;out of everyones way PM DS $180 ;first area not used MISL DS $80 ;Missile graphics area PLR0 DS $80 ;player 0 graphics area PLR1 DS $80 ;player 1 graphics area PLR2 DS $80 ;player 2 graphics area PLR3 DS $80 ;player 3 graphics area ; ------------------- ; Program entry point ; ------------------- JMP HARVEY ; ----------------- ; Game display list ; ----------------- DL DB $70,$70 ;32 blank scan lines DB $70,$70 DB $47 ;mode 2 line w/LMS bit DW DISP ;address of game display DB $07,$07 ;9 more mode 2 lines DB $07,$07 DB $07,$07 DB $07,$07 DB $07 DB $70,$70 ;skip 16 lines DB $46 ;mode 1 line w/LMS bit DW SLINE ;address of score line DB $41 ;jump on vertical blank DW DL ;to start of display list ; --------------- ; Score line data ; --------------- SLINE DB 'R'+$A0 DB 'A'+$A0 DB 'B'+$A0 DB 'B'+$A0 DB 'I'+$A0 DB 'T'+$A0 DB 'S'+$A0 DB ':'+$A0 RNUM DB '3'+$A0 ;number of rabbits DB ' '+$A0 DB 'S'+$A0 DB 'C'+$A0 DB 'O'+$A0 DB 'R'+$A0 DB 'E'+$A0 DB ':'+$A0 SNUM DB '0'+$A0 ;score display DB '0'+$A0 DB '0'+$A0 DB '0'+$A0 ; ----------------- ; Game over message ; ----------------- GOMSG DB 'game' DB 0,0,'ov' DB 'er',$80 PSMSG DB 'pres' DB 's',0,0,'s' DB 'tart',$80 ; ------------------- ; Initialization Code ; ------------------- HARVEY CLD ;clear decimal flag JSR SIOINT ;stop cassette LDA #'3'+$A0;display for '3' STA RNUM ;3 lives (display) LDA #3 ;get 3 lives STA LIVES ;initialize counter LDA #'0'+$A0;display for '0' STA SNUM ;store in the four STA SNUM+1 ;bytes used for the STA SNUM+2 ;score display STA SNUM+3 ;area. MORE LDA #60 ;get 1 second count STA TIM2ST ;set reset value STA CDTMV2 ;set system timer #2 JSR CLSCRN ;clear game playfield LDY #2 ;display 3 numbers (0-2) INUMS JSR PUTNUM ;put the number on screen DEY ;decrement number counter BPL INUMS ;done yet? No. LDA #DL&$FF ;Yes. low byte DL address STA SDLSTL ;DL pointer (low) LDA #DL/256 ;high byte DL address STA SDLSTL+1;DL pointer (high) LDA #$04 ;set PF over PLAYER STA GPRIOR ;graphics priority LDA #40 ;high wall STA BYLOC ;starting location LDA #196 ;low wall STA BYLOC+1 ;starting location LDA #60 ;left wall STA BXLOC ;starting location STA HPOSP2 ;hardware register LDA #184 ;right wall STA BXLOC+1 ;starting location STA HPOSP3 ;hardware register LDA #122 ;center screen-4 color clocks STA HARX ;Harvey's initial X position LDA #55 ;center P/M-8 bytes STA HARY ;Harvey's initial Y position LDA #$2E ;set P/M DMA on bits STA SDMCTL ;store in DMA control LDA #3 ;set P/M enable bits on STA GRACTL ;store in graphics control LDA #PM/256 ;get high byte of P/M addr STA PMBASE ;point hardware to it LDA #$96 ;light blue color STA COLOR2 ;default color too dark LDA #$48 ;pink color STA COLOR3 ;same here LDA #$18 ;gold color STA PCOLR0 ;set rabbit color LDA #$98 ;blue color STA PCOLR1 ;set missile 1 color LDA #$34 ;red-orange color STA PCOLR2 ;left wall color LDA #$C4 ;green color STA PCOLR3 ;right wall color LDA #1 ;initialize trigger flag- STA STRIGF ;to no shot fired LDX #VB/256 ;address of VB (MSB) LDY #VB&$FF ;address of VB (LSB) LDA #7 ;deferred vertical blank opt JSR SETVBV ;set deferred Vblank vector LDA #T1&$FF ;addr of timer 1 routine LSB STA CDTMA1 ;set timer 1 vector LSB LDA #T1/256 ;addr of timer 1 routine MSB STA CDTMA1+1;set timer 1 vector MSB LDA #T2&$FF ;addr of timer 2 routine LSB STA CDTMA2 ;set timer 2 vector LSB LDA #T2/256 ;addr of timer 2 routine MSB STA CDTMA2+1;set timer 2 vector MSB LDA #1 ;get 4.25 second count STA CDTMV1+1;set system timer #1 LDA #0 ;get a zero STA HITCLR ;reset collision registers STA DIESW ;rabbit is alive STA TICTOC ;reset tictoc counter STA VOL1 ;start with no tictoc sound STA VOL2 ;start with no shuffle noise STA IRQEN ;disable all IRQ interrupts LDX #3 ;set index value to 3 WINCZ STA WINC,X ;zero wall mover counter STA SHOTX,X ;zero X missile location STA SHOTY,X ;zero Y missile location STA SINCX,X ;zero X missile increment STA SINCY,X ;zero Y missile increment DEX ;next wall mover counter BPL WINCZ ;more walls/missiles? Yes. TAX ;set index to zero IM01 STA MISL,X ;clear Missile area STA PLR0,X ;clear Player 0, 1 area INX ;do next byte BNE IM01 ;done yet? No. LDA #$FF ;turn on pixels IM23 STA PLR2,X ;set Player 2, 3 area INX ;do next byte BNE IM23 ;done yet? No. ; ------------------------------------------ ; Main program used to generate the display. ; Actual game done entirely during display's ; vertical blank processing routine. ; ------------------------------------------ HBARS INX ;increment wall pointer TXA ;transfer pointer to Acc AND #1 ;mask off lowest bit TAX ;put back in X register LDA BYLOC,X ;get wall vertical position LSR A ;divide by 2, odd=carry set PHP ;save carry flag VCHECK CMP VCOUNT ;compare with line counter BNE VCHECK ;not yet! STA WSYNC ;start at new line PLP ;get carry flag back BCC ONELIN ;branch on even line number STA WSYNC ;wait for next line ONELIN LDA RANDOM ;random background color AND #$F6 ;max lum of 6 STA COLBK ;for horizontal walls LDY #10 ;let's have 10 lines of this LINES LDA #0 ;get a zero for overlap STA GRP2,X ;background overlaps player STA WSYNC ;wait for next line LDA RANDOM ;random background color AND #$F6 ;max lum of 6 STA COLBK ;for horizontal walls DEY ;decrement line counter BNE LINES ;10 lines done yet? No! LDA COLOR4 ;get original background STA COLBK ;store in background LDA LIVES ;more lives BEQ HB1 ;No. skip code LDA DIESW ;a new life? BPL HB1 ;No. JMP MORE ;Yes. more lives HB1 LDA CONSOL ;check for start switch AND #$01 ;mask off bit BNE HBARS ;start? No. JMP HARVEY ;restart game ; ----------------------------------------- ; System timer #1 interrupt handler. ; Used to speed up walls every 4.25 seconds. ; ----------------------------------------- T1 LDA TIM2ST ;get wall speed CMP #2 ;must stop at two BEQ TIM1 ;is it two? Yes. DEC TIM2ST ;No, then decrement TIM1 LDA #1 ;get 4.25 second cycle time STA CDTMV1+1;reset timer #1 RTS ;return ; ------------------------------------------- ; System timer #2 interrupt handler. ; Used to move walls and initiate wall noise. ; ------------------------------------------- T2 LDA TIM2ST ;get timer #2 value STA CDTMV2 ;reset timer #2 INC BYLOC ;move top wall down DEC BYLOC+1 ;move bottom wall up INC BXLOC ;change left wall location LDA BXLOC ;get new location STA HPOSP2 ;change player 2 position DEC BXLOC+1 ;change right wall location LDA BXLOC+1 ;get new location STA HPOSP3 ;change player 3 position INC TICTOC ;increment TIC-TOC counter LDA TICTOC ;get counter value AND #1 ;just need 0 or 1 value TAX ;use for index LDA METRO,X ;get sound frequency STA AUDF1 ;change frequency LDA #$08 ;get volume value STA VOL1 ;save in volume counter RTS ;return ; ------------------------------------------- ; Deferred vertical blank processing routine. ; Here is where all the actual game playing ; takes place. This could be quite long. ; ------------------------------------------- VB LDA DIESW ;rabbit dying? BNE VB0 ;He sure is. LDA LIVES ;any lives left? BNE VB0 ;There sure are. JSR CLSCRN ;clear screen of numbers LDX #0 ;initialize X with zero STX AUDC1 ;stop tictoc sound STX AUDC2 ;stop dying sound STX AUDC3 ;stop gun noise STX AUDC4 ;stop number sound STX CDTMV1 ;shut off the two timers STX CDTMV1+1;ditto. STX CDTMV2 ;same here. GOPRT LDA GOMSG,X ;get a character BMI PSINIT ;end of scring? Yes. STA DISP+85,X;put on screen INX ;increment index JMP GOPRT ;continue PSINIT LDX #0 ;zero the index PSPRT LDA PSMSG,X ;get another character BMI VBXIT ;end of string? Yes. STA DISP+144,X;put on screen INX ;increment index JMP PSPRT ;continue VBXIT JMP VBX ;exit vertical blank VB0 LDA P0PL ;player/player collisions STA P0PLT ;store in temp variable LDA P0PF ;player to PF collisions STA P0PFT ;store in temp variable LDA NSOUND ;treasure sound counter BMI NOSND ;end of sound? Yes. DEC NSOUND ;decrement volume LSR A ;divide volume by 2 ORA #$A0 ;add pure tone STA AUDC4 ;change volume NOSND LDA VOL1 ;get tictoc volume value BMI SND2 ;if <0 we produce no sound DEC VOL1 ;decrement volume value ORA #$C0 ;mask on the distortion STA AUDC1 ;generate the tictoc sound SND2 LDA VOL2 ;get shuffle volume BMI SND3 ;if <0 we produce no sound DEC VOL2 ;decrement volume value ORA #$80 ;mask on the distortion STA AUDC2 ;generate the shuffle noise SND3 LDA FREQ3 ;get shot frequency INC FREQ3 ;increment shot frequency INC FREQ3 ;do it again INC FREQ3 ;and one last time STA AUDF3 ;change frequency (lower) LDA DIESW ;is rabbit dying BEQ TMOV1 ;No. continue INC DIESW ;Yes. 2 second die period INC PCOLR0 ;change rabbit colors INC PCOLR0 ;again LDA PCOLR0 ;get number ASL A ;*2 ASL A ;*4 ASL A ;*8 STA AUDF2 ;use as frequency LDA #$88 ;get distortion STA AUDC2 ;make sound JMP VBX ;exit vertical blank TMOV1 LDA WINC ;check push wall up BEQ TMOV2 ;push up? No. DEC WINC ;decrement push up counter LDA BYLOC ;get top wall location CMP #28 ;compare with top of screen BEQ TMOV2 ;at top? Yes. DEC BYLOC ;move wall up TMOV2 LDA WINC+1 ;check push wall down BEQ TMOV3 ;push down? No. DEC WINC+1 ;decrement push down counter LDA BYLOC+1 ;get bottom wall location CMP #204 ;compare bottom of screen BEQ TMOV3 ;at bottom? Yes. INC BYLOC+1 ;move wall down TMOV3 LDA WINC+2 ;check push wall left BEQ TMOV4 ;push left? No. DEC WINC+2 ;decrement push left counter LDA BXLOC ;get left wall position STA HPOSP2 ;move left wall player CMP #39 ;check for left wall limit BEQ TMOV4 ;at limit? Yes. DEC BXLOC ;move wall left TMOV4 LDA WINC+3 ;check push wall right BEQ TMOVX ;push right? No. DEC WINC+3 ;decrement push right counter LDA BXLOC+1 ;get right wall position STA HPOSP3 ;move right wall player CMP #208 ;check for right wall limit BEQ TMOVX ;at limit? Yes. INC BXLOC+1 ;move wall right TMOVX LDA #0 ;get a zero STA ATRACT ;poke out atract mode STA XTEMP ;zero rabbit X increment STA YTEMP ;zero rabbit Y increment LDA STICK0 ;get joystick value CMP #$0F ;at center position? BEQ CENTER ;Yes. skip code LDA RTCLOK+2;get real time clock LSB AND #$07 ;at 1/7.5 second mark? BNE CENTER ;No. skip code LDA #$10 ;get shuffle frequency STA AUDF2 ;set frequency register LDA #$04 ;get volume value STA VOL2 ;set shuffle volume CENTER LDA STICK0 ;get joystick value SEC ;set carry for subtract SBC #5 ;values 5-15 only ASL A ;5-15 now 0,2,4,... TAX ;use for index LDA RTCLOK+2;get real time clock LSB ROR A ;divide by 2 ROR A ;divide by 4 ROR A ;divide by 8 ROR A ;carry set/reset at .13 sec LDA PK1,X ;get rabbit picture LSB BCC PICMVL ;other pic at .13 sec? No. LDA PK2,X ;get alternate picture LSB PICMVL STA PIC ;store LSB of pic address LDA PK1+1,X ;get rabbit picture MSB BCC PICMVH ;other pic at .13 sec? No. LDA PK2+1,X ;get alternate picture MSB PICMVH STA PIC+1 ;store MSB of pic address LDX #3 ;count 3 downto 0 CHKSTK LSR STICK0 ;shift bit into carry BCS CHKNXT ;correct direction? No. LDA STBLX,X ;check X movement direction BEQ CHK0 ;movement allowed? No. STA XTEMP ;store X movement value CHK0 LDA STBLY,X ;check Y movement direction BEQ CHKNXT ;movement allowed? No. STA YTEMP ;store Y movement value CHKNXT DEX ;do next stick position BPL CHKSTK ;done yet? No. LDA P0PLT ;get player 0 collision CMP #$0C ;left/right squeze? BNE NOSQUE ;No. Check indvdual walls DEC RNUM ;decrement lives display DEC LIVES ;decrement lines counter INC DIESW ;the rabbit has died switch NOSQUE AND #$04 ;check left wall collision BEQ BMPRT ;hit left wall? No. INC HARX ;Yes. Move rabbit to right LDA #0 ;get zero value STA XTEMP ;stop rabbit X movement BMPRT LDA P0PLT ;get player 0 collision AND #$08 ;check right wall collision BEQ BMPUP ;hit right wall? No. DEC HARX ;Yes. Move rabbit to left LDA #0 ;get zero value STA XTEMP ;stop rabbit X movement BMPUP CLC ;clear carry for add LDA BYLOC ;top wall Y location ADC #4 ;offset by 4 LSR A ;divide by 2 CMP HARY ;compare rabbit Y location BCC BMPDN ;hit top wall? No. DEC RNUM ;decrement lives display DEC LIVES ;decrement lines counter INC DIESW ;the rabbit has died switch BMPDN LDA HARY ;get rabbit Y location ADC #10 ;offset by 10 ASL A ;multiply by 2 CMP BYLOC+1 ;compare bottom wall Y BCC NOBMP ;hit bottom wall? No. DEC RNUM ;decrement lives display DEC LIVES ;decrement lines counter INC DIESW ;the rabbit has died switch NOBMP CLC ;clear carry for add LDA HARX ;get rabbit X position ADC XTEMP ;add X increment STA HARX ;save new rabbit X position STA HPOSP0 ;position rabbit player 0 CLC ;clear carry for add LDA HARY ;get rabbit Y position ADC YTEMP ;add Y increment STA HARY ;save new rabbit Y position TAX ;use position as index LDY #0 ;initialize picture counter MOVHAR LDA (PIC),Y ;get rabbit picture byte STA PLR0,X ;store in player 0 area INX ;increment player pointer INY ;increment picture pointer CPY #14 ;check for end of picture BNE MOVHAR ;at end? No. LDA STRIG0 ;get trigger value CMP STRIGF ;compare with trigger flag STA STRIGF ;save new trigger flag BCS NOFIRE ;shot fired? No. LDA XTEMP ;rabbit X increment ORA YTEMP ;OR rabbit Y increment BNE FIREGN ;rabbit stationary? No. INC STRIGF ;set trigger flag to 1 BNE NOFIRE ;skip fire routine FIREGN LDA #$40 ;initialize frequency STA FREQ3 ;zero audio freq 3 LDA #$04 ;shot volume + distortion STA AUDC3 ;enable volume 3 INC SHOTS ;increment shot pointer LDA SHOTS ;get shot pointer AND #3 ;make it 0-3 only TAX ;use pointer for index LDA XTEMP ;get rabbit X increment ASL A ;make shot twice as fast STA SINCX,X ;set missile X increment LDA YTEMP ;get rabbit Y increment ASL A ;make shot twice as fast STA SINCY,X ;set missile Y increment CLC ;clear carry for add LDA HARX ;get rabbit X position ADC #3 ;move to center X of rabbit STA SHOTX,X ;shot initial X position LDA HARY ;get rabbit Y position ADC #8 ;its move to center Y of rabbit STA SHOTY,X ;shot initial Y position NOFIRE LDA #0 ;zero accumulator TAX ;zero X index ERASES STA MISL,X ;zero all missiles INX ;next missile byte BPL ERASES ;done? No. LDX #3 ;count 3 downto 0 PLOTS LDA SINCX,X ;get missile X increment ORA SINCY,X ;OR missile Y increment BEQ NOPLOT ;any movement? No. LDA SHOTY,X ;missile Y position CLC ;clear carry for add ADC SINCY,X ;add Y increment STA SHOTY,X ;store new Y position TAY ;Y position now index ASL A ;multiply by 2 ADC #2 ;offset for compare CMP BYLOC+1 ;compare with bottom wall BCC HITTP ;hit bottom wall? No. JSR ZINCXY ;zero missile increments ADC WINC+1 ;add 8 to wall increment STA WINC+1 ;new bottom wall increment JMP PLOTNH ;continue HITTP SBC #12 ;offset for bottom side CMP BYLOC ;compare with top wall BCS PLOTNH ;hit top wall? No. JSR ZINCXY ;zero missile increments ADC WINC ;add 8 to wall increment STA WINC ;new top wall increment PLOTNH LDA MISL,Y ;get missile byte ORA MISMSK,X;OR missile mask STA MISL,Y ;store new byte LDA MISL+1,Y;get next missile byte ORA MISMSK,X;OR missile mask STA MISL+1,Y;store new next byte LDA M0PF,X ;missile/playfield collision LDY #0 ;init Y register MHPF ROR A ;collision? BCC MHPF0 ;No. No. No. JMP MHIT ;Yes. Yes. Yes. MHPF0 INY ;try next bit CPY #4 ;any more bits? BNE MHPF ;Certainly! Yuk. Yuk. CLC ;clear carry for add LDA SHOTX,X ;get missile X position ADC SINCX,X ;add X increment STA SHOTX,X ;store new X position STA HPOSM0,X;position missile CMP BXLOC+1 ;compare missile with wall BCC HITLF ;hit right wall? No. JSR ZINCXY ;zero missile increments ADC WINC+3 ;add 8 to wall increment STA WINC+3 ;new wall increment JMP NOPLOT ;continue HITLF SBC #6 ;offset for right side CMP BXLOC ;compare with left wall BCS NOPLOT ;hit left wall? No. JSR ZINCXY ;zero missile increments ADC WINC+2 ;add 8 to wall increment STA WINC+2 ;new wall increment NOPLOT DEX ;next missile BMI NOPL1 ;missiles done? Yes. JMP PLOTS ;continue loop NOPL1 LDX #3 ;set up pointer LDA #0 ;zero accumulator CHKMIS ORA SINCX,X ;OR in X increments ORA SINCY,X ;OR in Y increments DEX ;decrement pointer BPL CHKMIS ;at end? No. CMP #0 ;check shot increments BNE NOSSND ;any increments? Yes. STA AUDC3 ;end shot sound NOSSND LDY #0 ;initialize Y index MISHIT LSR P0PFT ;shift collision to carry BCC MH1 ;collision w/number? No. JSR ERANUM ;erase the number LDA VTBL,Y ;get value of number PHA ;save on stack JSR PUTNUM ;put out a new number PLA ;get old number TAY ;use as counter value BEQ SCX ;was it zero? Yes. SCORER LDX #3 ;point to score low digit SC1 INC SNUM,X ;increment digit LDA SNUM,X ;get digit CMP #'9'+$A1;past ATASCII '9'+color? BNE SCY ;No. continue LDA #'0'+$A0;reset digit STA SNUM,X ;change score display DEX ;point to next digit BPL SC1 ;score rolled over? No. SCY DEY ;decrement value BNE SCORER ;scoring done? No. SCX JMP VBX ;exit routine MH1 INY ;check next color digit CPY #3 ;done 0-2 yet? BNE MISHIT ;No. continue VBX STA HITCLR ;clear collision registers JMP XITVBV ;exit deferred vertical blank MHIT TXA ;save X register PHA ;on stack JSR ERANUM ;erase number hit and JSR PUTNUM ;put a new one on screen PLA ;pull X register TAX ;from stack JMP NOPLOT ;continue on ; ------------------------- ; Commonly used subroutines ; ------------------------- ; Clear missile display area ZINCXY LDA #0 ;get zero value STA SINCX,X ;zero missile X increment STA SINCY,X ;zero missile Y increment CLC ;clear carry for add LDA #8 ;get value for add RTS ;we return to the program ; Clear the game playfield CLSCRN LDX #200 ;set 0-199 bytes LDA #0 ;to zero CL0 STA DISP-1,X;store in display DEX ;count down BNE CL0 ;past zero yet? No. RTS ;return to program ; Put random number from 0-9 on screen at ; a random location 0-199 PUTNUM LDX RANDOM ;get random number CPX #200 ;is number < 200? BCS PUTNUM ;No. try another LDA DISP,X ;see if space is occupied BNE PUTNUM ;Yes. try again PN0 LDA RANDOM ;get another random number AND #$0F ;limit it to 0-15 CMP #10 ;is number < 10? BCS PN0 ;No. try another STA VTBL,Y ;save number ORA CTBL,Y ;OR with color STA DISP,X ;put number on screen TXA ;move screen offset to A STA ATBL,Y ;save screen offset RTS ;end of routine ; Erase number from screen ERANUM LDA #0 ;get zero for blank LDX ATBL,Y ;get # position on screen STA DISP,X ;blank number on screen LDA RANDOM ;get random number AND #$1F ;mask off high bits ORA #$10 ;make it $10-$1F STA AUDF4 ;use as sound frequency LDA #30 ;initialize- STA NSOUND ;volume counter RTS ;end of routine ; ---------------------------- ; Program tables and constants ; ---------------------------- MISMSK DB $03 ;missile 0 mask DB $0C ;missile 1 mask DB $30 ;missile 2 mask DB $C0 ;missile 3 mask HARLF1 DB 0,0 ;left view #1 DB $12,$0A DB $3C,$74 DB $3C,$1C DB $1E,$3E DB $3F,$7E HARLF2 DB 0,0 ;left view #2 DB $0B,$0A DB $3C,$74 DB $3C,$1C DB $1E,$3E DB $3E,$F7 HARRT1 DB 0,0 ;right view #1 DB $48,$50 DB $3C,$2E DB $3C,$38 DB $78,$7C DB $FC,$7E HARRT2 DB 0,0 ;right view #2 DB $D0,$50 DB $3C,$2E DB $3C,$38 DB $78,$7C DB $7C,$EF HARFR1 DB 0,0 ;front view #1 DB $42,$24 DB $3C,$14 DB $3C,$18 DB $3C,$7E DB $7E,$E7 HARFR2 DB 0,0 ;front view #2 DB $42,$24 DB $3C,$28 DB $3C,$18 DB $3C,$7E DB $7E,$E7 HARDN1 DB 0,0 ;down view #1 DB $44,$24 DB $3C,$14 DB $3C,$18 DB $3C,$7E DB $FE,$07 HARDN2 DB 0,0 ;down view #2 DB $22,$24 DB $3C,$28 DB $3C,$18 DB $3C,$7E DB $7F,$E0 HARUP1 DB 0,0 ;up view #1 DB $44,$24 DB $3C,$3C DB $3C,$18 DB $3C,$66 DB $FE,$07 HARUP2 DB 0,0 ;up view #2 DB $22,$24 DB $3C,$3C DB $3C,$18 DB $3C,$66 DB $7F,$E0 DB 0,0 PK1 DW HARRT1 ;rabbit pictures set 1 DW HARRT1 DW HARRT1 DW 0 DW HARLF1 DW HARLF1 DW HARLF1 DW 0 DW HARDN1 DW HARUP1 DW HARFR1 PK2 DW HARRT2 ;rabbit pictures set 2 DW HARRT2 DW HARRT2 DW 0 DW HARLF2 DW HARLF2 DW HARLF2 DW 0 DW HARDN2 DW HARUP2 DW HARFR2 CTBL DB $10,$50 ;color offset table DB $90 METRO DB 38,41 ;tictoc tones STBLX DB $01,$FF ;joystick X increments DB $00,$00 STBLY DB $00,$00 ;joystick Y increments DB $01,$FF ; --------------------- ; Variable Storage Area ; --------------------- HARX DS 1 ;Harvey's X locatin HARY DS 1 ;Harvey's Y location BYLOC DS 2 ;horizontal wall Y locations BXLOC DS 2 ;vertical wall X locations VOL1 DS 1 ;tictoc volume VOL2 DS 1 ;shuffle volume FREQ3 DS 1 ;shot frequency NSOUND DS 1 ;pick number up sound TICTOC DS 1 ;tictoc sound counter TIM2ST DS 1 ;wall speed timer WINC DS 4 ;wall mover counters STRIGF DS 1 ;trigger compare register XTEMP DS 1 ;temporary variable YTEMP DS 1 ;temporary variable P0PLT DS 1 ;player 0 collision shadow P0PFT DS 1 ;PL to PF collision shadow VTBL DS 3 ;value of #'s on screen ATBL DS 3 ;screen offset to #'s SHOTS DS 1 ;shot enable counter LIVES DS 1 ;number of lives left DIESW DS 1 ;rabbit dying switch SHOTX DS 4 ;missile X location SHOTY DS 4 ;missile Y location SINCX DS 4 ;missile X increment SINCY DS 4 ;missile Y increment DISP DS 200 ;screen display area END HARVEY
100 REM HARVEY WALLBANGER 110 REM CASSETTE MAKER PROGRAM 120 REM 130 DIM PROG$(1600):PNTR=1 140 LINE=990:TRAP 220 150 LINE=LINE+10:FOR COUNT=1 TO 15 160 READ BYTE:PROG$(PNTR)=CHR$(BYTE) 170 PNTR=PNTR+1:TOTAL=TOTAL+BYTE 180 NEXT COUNT:? "LINE:";LINE 190 READ CHECKSUM 200 IF CHECKSUM=TOTAL THEN 150 210 ? "BAD CHECKSUM: LINE ";LINE:STOP220 IF PEEK(195)=6 THEN 240 230 ? "BAD DATA: LINE ";LINE:STOP 240 OPEN #1,8,128,"C:" 241 PROG$(1,1)=CHR$(0) 242 PROG$(2,2)=CHR$(12) 243 PROG$(3,3)=CHR$(250) 244 PROG$(4,4)=CHR$(51) 250 PRINT #1;PROG$;:END 999 REM 1000 DATA 255,255,0,52,216,57,76,71,52 ,112,112,112,112,71,7,1560 1010 DATA 58,7,7,7,7,7,7,7,7,7,112,112 ,70,27,52,2054 1020 DATA 65,3,52,242,225,226,226,233, 244,243,218,211,192,243,227,4904 1030 DATA 239,242,229,218,208,208,208, 208,103,97,109,101,0,0,111,7185 1040 DATA 118,101,114,128,112,114,101, 115,115,0,0,115,116,97,114,8645 1050 DATA 116,128,216,32,101,228,169,2 11,141,35,52,169,3,141,245,10632 1060 DATA 57,169,208,141,43,52,141,44, 52,141,45,52,141,46,52,12016 1070 DATA 169,60,141,228,57,141,26,2,3 2,220,56,160,2,32,231,13573 1080 DATA 56,136,16,250,169,3,141,48,2 ,169,52,141,49,2,169,14976 1090 DATA 4,141,111,2,169,40,141,219,5 7,169,196,141,220,57,169,16812 1100 DATA 60,141,221,57,141,2,208,169, 184,141,222,57,141,3,208,18767 1110 DATA 169,122,141,217,57,169,55,14 1,218,57,169,46,141,47,2,20518 1120 DATA 169,3,141,29,208,169,48,141, 7,212,169,150,141,198,2,22305 1130 DATA 169,72,141,199,2,169,24,141, 192,2,169,152,141,193,2,24073 1140 DATA 169,52,141,194,2,169,196,141 ,195,2,169,1,141,233,57,25935 1150 DATA 162,53,160,204,169,7,32,92,2 28,169,137,141,38,2,169,27698 1160 DATA 53,141,39,2,169,153,141,40,2 ,169,53,141,41,2,169,29013 1170 DATA 1,141,25,2,169,0,141,30,208, 141,246,57,141,227,57,30599 1180 DATA 141,223,57,141,224,57,141,14 ,210,162,3,157,229,57,157,32572 1190 DATA 247,57,157,251,57,157,255,57 ,157,3,58,202,16,238,170,34654 1200 DATA 157,128,49,157,0,50,232,208, 247,169,255,157,0,51,232,36746 1210 DATA 208,250,232,138,41,1,170,189 ,219,57,74,8,205,11,212,38761 1220 DATA 208,251,141,10,212,40,144,3, 141,10,212,173,10,210,41,40567 1230 DATA 246,141,26,208,160,10,169,0, 157,15,208,141,10,212,173,42443 1240 DATA 10,210,41,246,141,26,208,136 ,208,237,173,200,2,141,26,44448 1250 DATA 208,173,245,57,240,8,173,246 ,57,16,3,76,99,52,173,46274 1260 DATA 31,208,41,1,208,177,76,71,52 ,173,228,57,201,2,240,48040 1270 DATA 3,206,228,57,169,1,141,25,2, 96,173,228,57,141,26,49593 1280 DATA 2,238,219,57,206,220,57,238, 221,57,173,221,57,141,2,51702 1290 DATA 208,206,222,57,173,222,57,14 1,3,208,238,227,57,173,227,54121 1300 DATA 57,41,1,170,189,207,57,141,0 ,210,169,8,141,223,57,55792 1310 DATA 96,173,246,57,208,60,173,245 ,57,208,55,32,220,56,162,57840 1320 DATA 0,142,1,210,142,3,210,142,5, 210,142,7,210,142,24,59430 1330 DATA 2,142,25,2,142,26,2,189,47,5 2,48,7,157,92,58,60421 1340 DATA 232,76,240,53,162,0,189,58,5 2,48,7,157,151,58,232,62136 1350 DATA 76,254,53,76,189,56,173,12,2 08,141,236,57,173,4,208,64052 1360 DATA 141,237,57,173,226,57,48,9,2 06,226,57,74,9,160,141,65873 1370 DATA 7,210,173,223,57,48,8,206,22 3,57,9,192,141,1,210,67638 1380 DATA 173,224,57,48,8,206,224,57,9 ,128,141,3,210,173,225,69524 1390 DATA 57,238,225,57,238,225,57,238 ,225,57,141,4,210,173,246,71915 1400 DATA 57,240,26,238,246,57,238,192 ,2,238,192,2,173,192,2,74010 1410 DATA 10,10,10,141,2,210,169,136,1 41,3,210,76,189,56,173,75546 1420 DATA 229,57,240,13,206,229,57,173 ,219,57,201,28,240,3,206,77704 1430 DATA 219,57,173,230,57,240,13,206 ,230,57,173,220,57,201,204,80041 1440 DATA 240,3,238,220,57,173,231,57, 240,16,206,231,57,173,221,82404 1450 DATA 57,141,2,208,201,39,240,3,20 6,221,57,173,232,57,240,84481 1460 DATA 16,206,232,57,173,222,57,141 ,3,208,201,208,240,3,238,86686 1470 DATA 222,57,169,0,133,77,141,234, 57,141,235,57,173,120,2,88504 1480 DATA 201,15,240,16,165,20,41,7,20 8,10,169,16,141,2,210,89965 1490 DATA 169,4,141,224,57,173,120,2,5 6,233,5,10,170,165,20,91514 1500 DATA 106,106,106,106,189,160,57,1 44,3,189,182,57,133,128,189,93369 1510 DATA 161,57,144,3,189,183,57,133, 129,162,3,78,120,2,176,94966 1520 DATA 16,189,209,57,240,3,141,234, 57,189,213,57,240,3,141,96955 1530 DATA 235,57,202,16,232,173,236,57 ,201,12,208,9,206,35,52,98886 1540 DATA 206,245,57,238,246,57,41,4,2 40,8,238,217,57,169,0,100909 1550 DATA 141,234,57,173,236,57,41,8,2 40,8,206,217,57,169,0,102753 1560 DATA 141,234,57,24,173,219,57,105 ,4,74,205,218,57,144,9,104474 1570 DATA 206,35,52,206,245,57,238,246 ,57,173,218,57,105,10,10,106389 1580 DATA 205,220,57,144,9,206,35,52,2 06,245,57,238,246,57,24,108390 1590 DATA 173,217,57,109,234,57,141,21 7,57,141,0,208,24,173,218,110416 1600 DATA 57,109,235,57,141,218,57,170 ,160,0,177,128,157,0,50,112132 1610 DATA 232,200,192,14,208,245,173,1 32,2,205,233,57,141,233,57,114456 1620 DATA 176,63,173,234,57,13,235,57, 208,5,238,233,57,208,50,116463 1630 DATA 169,64,141,225,57,169,4,141, 5,210,238,244,57,173,244,118604 1640 DATA 57,41,3,170,173,234,57,10,15 7,255,57,173,235,57,10,120293 1650 DATA 157,3,58,24,173,217,57,105,3 ,157,247,57,173,218,57,121999 1660 DATA 105,8,157,251,57,169,0,170,1 57,128,49,232,16,250,162,123910 1670 DATA 3,189,255,57,29,3,58,240,127 ,189,251,57,24,125,3,125520 1680 DATA 58,157,251,57,168,10,105,2,2 05,220,57,144,12,32,208,127206 1690 DATA 56,109,230,57,141,230,57,76, 31,56,233,12,205,219,57,128975 1700 DATA 176,9,32,208,56,109,229,57,1 41,229,57,185,128,49,29,130669 1710 DATA 34,57,153,128,49,185,129,49, 29,34,57,153,129,49,189,132093 1720 DATA 0,208,160,0,106,144,3,76,195 ,56,200,192,4,208,245,133890 1730 DATA 24,189,247,57,125,255,57,157 ,247,57,157,4,208,205,222,136101 1740 DATA 57,144,12,32,208,56,109,232, 57,141,232,57,76,111,56,137681 1750 DATA 233,6,205,221,57,176,9,32,20 8,56,109,231,57,141,231,139653 1760 DATA 57,202,48,3,76,232,55,162,3, 169,0,29,255,57,29,141030 1770 DATA 3,58,202,16,247,201,0,208,3, 141,5,210,160,0,78,142562 1780 DATA 237,57,144,40,32,10,57,185,2 38,57,72,32,231,56,104,144114 1790 DATA 168,240,23,162,3,254,43,52,1 89,43,52,201,218,208,8,145978 1800 DATA 169,208,157,43,52,202,16,238 ,136,208,233,76,189,56,200,148161 1810 DATA 192,3,208,206,141,30,208,76, 98,228,138,72,32,10,57,149860 1820 DATA 32,231,56,104,170,76,111,56, 169,0,157,255,57,157,3,151494 1830 DATA 58,24,169,8,96,162,200,169,0 ,157,6,58,202,208,250,153261 1840 DATA 96,174,10,210,224,200,176,24 9,189,7,58,208,244,173,10,155489 1850 DATA 210,41,15,201,10,176,247,153 ,238,57,25,204,57,157,7,157287 1860 DATA 58,138,153,241,57,96,169,0,1 90,241,57,157,7,58,173,159082 1870 DATA 10,210,41,31,9,16,141,6,210, 169,30,141,226,57,96,160475 1880 DATA 3,12,48,192,0,0,18,10,60,116 ,60,28,30,62,63,161177 1890 DATA 126,0,0,11,10,60,116,60,28,3 0,62,62,247,0,0,161989 1900 DATA 72,80,60,46,60,56,120,124,25 2,126,0,0,208,80,60,163333 1910 DATA 46,60,56,120,124,124,239,0,0 ,66,36,60,20,60,24,164368 1920 DATA 60,126,126,231,0,0,66,36,60, 40,60,24,60,126,126,165509 1930 DATA 231,0,0,68,36,60,20,60,24,60 ,126,254,7,0,0,166455 1940 DATA 34,36,60,40,60,24,60,126,127 ,224,0,0,68,36,60,167410 1950 DATA 60,60,24,60,102,254,7,0,0,34 ,36,60,60,60,24,168251 1960 DATA 60,102,127,224,0,0,62,57,62, 57,62,57,0,0,38,169159 1970 DATA 57,38,57,38,57,0,0,110,57,13 4,57,86,57,74,57,170038 1980 DATA 74,57,74,57,0,0,50,57,50,57, 50,57,0,0,122,170743 1990 DATA 57,146,57,98,57,16,80,144,38 ,41,1,255,0,0,0,171733 2000 DATA 0,1,255,226,2,227,2,0,52,0,0 ,0,0,0,0,172498
109 REM HARVEY WALLBANGER MODS 119 REM CASSETTE MAKER PROGRAM 120 REM 240 OPEN #1,8,128,"C:" 241 PROG$(1,1)=CHR$(0) 242 PROG$(2,2)=CHR$(12) 243 PROG$(3,3)=CHR$(250) 244 PROG$(4,4)=CHRS(51)
100 DATA 817,932,302,586,656,712,870,669,51,479,193,91,319,452,924,8053 250 DATA 285,231,567,689,303,362,67,46 9,843,631,894,319,256,274,52,6242 1130 DATA 953,210,109,618,739,238,199, 149,911,918,186,323,41,918,771,7283 1280 DATA 935,511,995,351,627,385,48,1 05,175,753,90,209,952,23,281,6440 1430 DATA 311,380,58,163,971,712,689,4 07,32,950,188,870,940,957,259,7887 1580 DATA 158,247,25,309,36,207,896,23 6,138,727,30,33,86,84,918,4130 1730 DATA 267,19,72,666,735,10,970,383 ,295,90,71,422,156,969,659,5704 1880 DATA 368,413,755,735,716,200,469, 421,256,643,209,559,680,6424