A.N.A.L.O.G. ISSUE 8 / NOVEMBER 1982 / PAGE 57
When writing game programs, many programmers automatically choose assembly language over BASIC because of the obvious speed advantage. This can sometimes be a mistake, since BASIC offers some functions (such as sine, square root, etc.) not easily written in assembler. One way to take advantage of the convenience of BASIC and the speed of assembler is to combine the two languages. ATARI BASIC allows the user to “call” machine-language subroutines, which can be many times faster than the same routine in BASIC. A.N.A.L.O.G. Software’s shooting gallery game “Carnival” uses this technique. Fine screen scrolling, music generation and other functions which must be performed quickly are done in assembler, while simpler operations are handled by BASIC.
In order to assist those game programmers who would like to have dramatic explosion effects in their BASIC programs, I have developed Graphic Violence, a group of assembly-language subroutines. These routines allow BASIC to generate up to 20 simultaneous explosions in GRAPHICS 7. They can optionally generate sound effects as well as “cycle” the colors of the explosions for an interesting “radioactive glow” effect.
The first half of this article is a non-technical explanation of how to use Graphic Violence. The second half is an in-depth discussion of the actual assembly language code for those interested in the inner workings of the subroutines.
Listing 1 is the BASIC language code necessary to set up the Graphic Violence subroutine. This code should be placed in any program that is to use the explosion generator. After typing this program in, SAVE it immediately, BEFORE RUNNING IT! The routine has some safeguards against typing errors in the DATA statements, but if it is executed with bad DATA, the system may crash and it will be necessary to re-type the program.
After the program is typed and SAVEd, RUN it. If it is typed correctly, the program will run for several seconds before anything happens. The screen colors will begin cycling quickly. If not, an error was made somewhere, and you should re-boot your system, load the SAVEd program, find the mistake, SAVE it and try again.
If a message such as “COORD1 ERR” occurs, you have made a mistake typing in the DATA statements. “COORD1 ERR” indicates that an error was made in the COORD1 DATA, “INIT ERR” is an error in the INITIALIZATION CODE, etc. Find the error, fix it and re-RUN the program.
Once the computer starts cycling colors, press SYSTEM RESET before doing anything else. Whenever operating any program using the Graphic Violence subroutine, you MUST use the SYSTEM RESET key to terminate the program. The subroutine automatically disables the BREAK key since typing commands in immediate mode while the subroutine is in operation will usually cause a system crash. Pressing SYSTEM RESET will correctly terminate the subroutine and avoid any problems.
At this point, you should have a correctly operating Graphic Violence initialization subroutine SAVEd on tape or disk.
A=USR(ADR(INIT$),ADR(MAIN$),ADR(COORD1$),ADR,(COORD2$),COLOR,SOUND)
The COLOR value tells whether or not you want the color of the explosions to cycle. In the program listing, this value is set to 1, indicating that cycling is desired. If you do not want cycling, place a here.
The SOUND value tells whether or not you want the routine to generate sounds with the explosions. In the listing it is a 1, indicating that we want sound. If sound is not desired, place a here.
With listing #1 in your computer, add listing #2 to the original program and RUN it. This is a short demonstration routine which simply places an explosion at the center of the screen, then repeats.
By looking at this short routine, you will notice the USR call in line 220. This is the command which starts an explosion. Once the Graphic Violence machine-code subroutine is set up, this short operation is all you need to generate explosions.
Remember to stop the program by pressing SYSTEM RESET.
A=USR(ADR(EXPLS$),X,Y)
X and Y are the screen coordinates of the center of the explosion. In the listing, X=80 an-d Y=48, placing the explosion at the center of the screen. This statement is the heart of the Graphic Violence routine. Once this statement is executed, it starts off an explosion while BASIC continues with whatever it is doing. In addition, the explosion handler can operate up to 20 explosions simultaneously, while BASIC does its own processing!
In the previous example, we generated one explosion at the center of the screen, just to keep things simple. In this example, we will see how the Graphic Violence routine will handle up to 20 simultaneous explosions without the programmer having to worry about what’s going on inside the explosion handler! All the programmer needs to do is send the explosion coordinates to the routine via the USR command and let the computer do the rest. (What could be simpler?)
With listing #1 in your computer, add listing #3 to the original program and RUN it. The program will fill up most of the screen with graphics, then start dropping “bombs” from the top of the screen. As they hit the graphics area, they will explode violently, “eating” away the graphics. As soon as one of the bombs falls off the bottom of the screen, an end message will be displayed and subsequently destroyed by a number of explosions. The program will run continuously and MUST be stopped by pressing SYSTEM RESET.
The Graphic Violence explosion generator subroutine will operate in almost any game using graphics 7. Explosions overlapping the edges of the screen are automatically “clipped,” but the program has minimal error-trapping. The user should take care to make sure that the coordinates supplied to the routine do not exceed the graphics 7 screen limits. The routine uses sound channel 1 when the sound generation option is requested. The Explosions use COLOR 3 (SETCOLOR 2), and will cycle the color only (not brightness) if color cycling is requested. Any program using the Graphic Violence roudne must be terminated with SYSTEM RESET to avoid a system crash.
The following section contains a discussion of the assembly-language routines that make up Graphic Violence. This information is not necessary to use the subroutine, but may assist those interested in assembly language and the inner workings of the ATARI computers.
The Graphic Violence subroutine is made up of three program segments and two data tables. These five modules work together to provide a machine-language explosion generator for BASIC.
The first assembly program (listing #4) is the Graphic Violence initialization subroutine. It is stored in the BASIC string variable INIT$. Its function is to accept the locations of the main program module and the explosion plot coordinates, start up the main module, and accept the color cycling and sound generation options.
Remember that this is the routine called in the BASIC statement:
A=USR(ADR(INIT$),ADR(MAIN$),ADR(COORD1$),ADR(COORD2$),COLOR,SOUND)
The second assembly language program (Listing #5) is the explosion start routine. It is called by the BASIC statement:
A=USR(ADR(EXPL$),X,Y)
This routine simply accepts the coordinates of the explosion from BASIC. If there are 20 explosions active, it will ignore the request, otherwise it will send the coordinates to the main module, which is executing in the deferred vertical blank.
The third assembly language listing (LISTING #6) is the vertical blank interrupt routine, stored in MAIN$. It does all the color cycling, sound, and graphics for the explosions. Since it is an interrupt-driven program, it operates independently of BASIC, allowing BASIC to continue processing normally while the vertical blank does all the explosion work.
Since this program is stored in a BASIC string, any program editing or immediate mode operations in BASIC while the vertical blank routine is running will cause a system crash. This is due to the fact that BASIC moves its variables around in memory during editing of programs, and such movement of the interrupt routine will confuse the system. To help avoid such a problem, the Graphic Violence interrupt routine disables the break key, making it necessary to press SYSTEM RESET to stop program execution. This is only a partial solution, however, since if the programmer allows his program to end with the READY prompt, then enters a program line, the crash will still occur.
The interrupt routine performs several functions. First, it disables the BREAK key and cycles the color of playfield type 2 if necessary. Next it processes sound, if required, using sound channel 1. The last major function it performs is that of explosion graphics generation.
Each explosion graphic is made up of 89 separate pixels. The routine uses the specified centerpoint of each explosion and adds X and Y offset values, which are stored in the BASIC string variables COORD 1$ and COORD2$. Each of the 89 pixels are first turned on, one pixel at a time, resulting in a “growing” appearance. After all 89 pixels are on, the routine turns off one pixel at a time, causing the explosion to dissipate. Each active explosion has a pixel either turned on or off each time the interrupt is performed. Since this happens 60 times a second, each explosion takes roughly 3 seconds to expand and dissipate ((89*2)/60). Explosions are independent of each other because of three tables. The X and Y coordinates of each explosion are stored in the XPOS and YPOS tables. The third table, CNT, holds the number of the pixel which will be turned on or off next for each explosion. This value ranges from 0 to 88 for “on” pixels, and 89 to 177 for “off” pixels. If the CNT value for an explosion exceeds 177, the explosion has dissipated completely and its values are removed from the explosion tables by a “repack” operation. That is, if explosion number 2 is finished, explosion 3 will move back to 2, 4 to 3, etc.
By expanding the XPOS, YPOS and CNT tables and altering the explosion call routine (Listing #5), advanced users can enable the Graphic Violence routine to handle many more explosions than it can now. However, 20 explosions are more than enough for most applications, and the routine should serve well as is.
I hope that ATARI programmers will see by this example that it is not always necessary to write game programs completely in assembly language. Just use BASIC for complicated functions difficult to write in assembler, and use assembler for things BASIC is too slow to do.
And by the way, have fun causing graphic havoc on your computer!
10 REM ************************** 20 REM * GRAPHIC VIOLENCE DEMO * 30 REM * A.N.A.L.O.G. COMPUTING * 40 REM * BY TOM HUDSON * 50 REM ************************** 60 REM 70 REM *** INITIALIZE THE GRAPHIC VIOLENCE SUBROUTINE *** 80 GOSUB 10010 90 REM 100 REM ***************************** 110 REM ** YOUR PROGRAM GOES HERE! ** 120 REM ***************************** 130 GOTO 130 10000 REM *** INITIALIZATION SUBROUTIN E *** 10010 DIM INIT$(41),EXPL$(29),MAIN$(35 5),COORD1$(89),COORD2$(89):RESTORE 110 00 10020 TOT=0:FOR X=1 TO 89:READ A:TOT=T OT+A:COORD1$(X,X)=CHR$(A):NEXT X:IF TO T<>9984 THEN ? "COORD1 ERR":END 10030 TOT=0:FOR X=1 TO 89:READ A:TOT=T OT+A:COORD2$(X,X)=CHR$(A):NEXT X:IF TO T<>9984 THEN ? "COORD2 ERR":END 10040 TOT=0:FOR X=1 TO 41:READ A:TOT=T OT+A:INIT$(X,X)=CHR$(A):NEXT X:IF TOT< >4237 THEN ? "INIT ERR":END 10050 TOT=0:FOR X=1 TO 29:READ A:TOT=T OT+A:EXPL$(X,X)=CHR$(A):NEXT X:IF TOT< >2198 THEN ? "EXPL ERR":END 10060 TOT=0:FOR X=1 TO 355:READ A:TOT= TOT+A:MAIN$(X,X)=CHR$(A):NEXT X:IF TOT <>36691 THEN ? "MAIN ERR":END 10070 REM *** SET UP PLOT BITS *** 10080 POKE 1568,192:POKE 1569,48:POKE 1570,12:POKE 1571,3 10090 REM *** INITIALIZE GRAPHIC VIOLE NCE ROUTINE AND RETURN *** 10100 A=USR(ADR(INIT$),ADR(MAIN$),ADR( COORD1$),ADR(COORD2$),1,1) 10110 RETURN 11000 REM *** COORD1 DATA *** 11010 DATA 0,1,255,0,255,0,255,2,1,1,0 ,254,255,1,0,1,254,254,2,0,1,255,2,2,2 ,255,254,1,253,3,3,4,252,253,254 11020 DATA 255,254,2,3,3,253,0,0,0,4,4 ,252,255,2,0,3,2,1,253,254,254,252,253 ,3,253,252,251,251,252,4,3,4,255 11030 DATA 5,5,5,253,1,254,0,255,252,2 53,251,253,252,3,4,3,1,255,1,2,4 12000 REM *** COORD2 DATA *** 12010 DATA 0,255,1,2,254,255,0,1,254,0 ,1,0,255,1,253,253,2,255,255,254,2,3,2 ,0,254,2,1,3,254,1,254,255,0,1,253 12020 DATA 253,254,3,2,0,3,252,4,3,0,2 ,2,4,4,5,3,253,252,0,3,4,254,252,252,2 ,1,1,0,255,254,255,1,251 12030 DATA 0,255,1,4,4,252,251,252,253 ,253,255,255,3,253,253,4,251,5,5,252,3 13000 REM *** INITIALIZATION CODE *** 13010 DATA 104,169,0,141,0,6,141,1,6,1 04,170,104,168,169,7 13020 DATA 32,92,228,104,133,204,104,1 33,203,104,133,206,104,133,205 13030 DATA 104,104,141,11,6,104,104,14 1,12,6,96 14000 REM *** EXPLOSION CALL CODE *** 14010 DATA 104,173,1,6,201,20,48,5,104 ,104,104,104,96,104,104 14020 DATA 141,2,6,104,104,141,3,6,169 ,1,141,0,6,96 14990 REM *** MAIN INTERRUPT CODE *** 15000 DATA 216,165,16,41,127,133,16,14 1,14,210,173,11,6,240,20 15010 DATA 173,14,6,24,105,16,141,14,6 ,173,198,2,41,15,13 15020 DATA 14,6,141,198,2,173,12,6,240 ,22,173,13,6,240,17 15030 DATA 56,233,1,141,13,6,74,74,74, 141,1,210,169,40,141 15040 DATA 0,210,173,0,6,240,31,238,1, 6,174,1,6,173,2 15050 DATA 6,157,64,6,173,3,6,157,85,6 ,169,127,141,13,6 15060 DATA 169,0,157,106,6,141,0,6,141 ,5,6,238,5,6,173 15070 DATA 1,6,205,5,6,16,3,76,98,228, 174,5,6,169,0 15080 DATA 141,4,6,189,106,6,201,89,48 ,51,238,4,6,56,233 15090 DATA 89,201,89,48,41,138,168,232 ,236,1,6,240,2,16,21 15100 DATA 189,64,6,153,64,6,189,85,6, 153,85,6,189,106,6 15110 DATA 153,106,6,200,208,227,206,1 ,6,206,5,6,169,0,240 15120 DATA 176,254,106,6,168,189,64,6, 24,113,203,141,6,6,201 15130 DATA 160,176,159,189,85,6,24,113 ,205,141,7,6,201,96,176 15140 DATA 146,10,133,207,169,0,240,2, 240,137,133,208,165,207,10 15150 DATA 133,207,165,208,42,133,208, 165,207,10,133,207,141,9,6 15160 DATA 165,208,42,133,208,141,8,6, 165,207,10,133,207,165,208 15170 DATA 42,133,208,165,207,10,133,2 07,165,208,42,133,208,165,207 15180 DATA 24,109,9,6,133,207,165,208, 109,8,6,133,208,165,88 15190 DATA 24,101,207,133,207,165,89,1 01,208,133,208,173,6,6,41 15200 DATA 3,168,190,32,6,142,10,6,173 ,6,6,74,74,24,101 15210 DATA 207,133,207,165,208,105,0,1 33,208,160,0,173,4,6,208 15220 DATA 11,173,10,6,81,207,145,207, 169,0,240,132,173,10,6 15230 DATA 73,255,49,207,145,207,169,0 ,240,241
10 DATA 280,584,117,872,443,39,803,938,42,503,948,583,773,754,453,8132 10820 DATA 663,814,280,321,554,442,562 ,706,821,779,332,901,124,164,556,8019 12010 DATA 151,34,36,734,44,907,884,83 1,254,592,785,494,178,812,217,6945 15040 DATA 696,834,922,296,863,301,996 ,27,550,398,634,887,664,954,378,9392 15190 DATA 817,737,589,518,917,3498
130 REM *************************** 140 REM * GRAPHIC VIOLENCE DEMO * 150 REM * NUMBER 1 * 160 REM *************************** 170 REM 180 REM *** SET UP GRAPHIC MODE 7 *** 190 GRAPHICS 7+16 200 REM *** SET OFF AN EXPLOSION *** 210 REM *** AT SCREEN CENTER *** 220 A=USR(ADR(EXPL$),80,48) 230 REM *** WAIT A FEW SECONDS *** 240 FOR WAIT=1 TO 2000: NEXT WAIT 250 REM *** DO EXPLOSION AGAIN *** 260 GOTO 220
130 REM *************************** 140 REM * GRAPHIC VIOLENCE DEMO * 150 REM * NUMBER 2 * 160 REM *************************** 170 REM 180 REM *** SET UP GRAPHICS 7 FULL SCREEN AND EXPLOSION COLOR *** 190 GRAPHICS 7+16:SETCOLOR 2,15,15 200 REM *** DRAW THE 'GROUND' *** 210 COLOR 1:FOR Y=20 TO 95:PLOT 0,Y:DR AWTO 159,Y:NEXT Y 220 REM *** TRAP ANY ERRORS TO 'THE EN D' ROUTINE *** 230 TRAP 320 240 REM *** RANDOMIZE START POINT FOR DROPPING BOMBS *** 250 X=5+RND(0)*149:Y=RND(0)*3 260 REM *** ADVANCE THE BOMB AS IT DRO PS *** 270 COLOR 0:PLOT X,Y:Y=Y+3 280 REM *** IF THE BOMB HITS COLOR 1, SET OFF EXPLOSION *** 290 LOCATE X,Y,Z:IF Z=1 THEN A=USR(ADR (EXPL$),X,Y):GOTO 250 300 REM *** NO HIT, CONTINUE DROP *** 310 COLOR 2:PLOT X,Y:FOR DELAY=1 TO 10 :NEXT DELAY:GOTO 270 320 REM *** 'THE END' *** 330 GRAPHICS 7+16:SETCOLOR 2,15,15:COL OR 1 340 REM *** PLOT 'THE END' *** 350 RESTORE 400:FOR X=1 TO 22:READ FRX ,FRY,TUX,TUY:PLOT FRX,FRY:DRAWTO TUX,T UY:NEXT X 360 REM *** SET OFF 200 RANDOM EXPLOSI ONS *** 370 FOR EXPL=1 TO 200:A=USR(ADR(EXPL$) ,48+RND(0)*75,20+RND(0)*55):FOR DELAY= 1 TO 40:NEXT DELAY:NEXT EXPL 380 REM *** LET EXPLOSIONS DIE, THEN R E-RUN THE DEMO *** 390 FOR DELAY=1 TO 2000:NEXT DELAY:GOT O 190 400 REM *** 'THE END' DATA *** 410 DATA 50,25,67,25,59,25,59,45,72,25 ,72,45,72,35,88,35,88,25,88,45,93,25,9 3,45,93,25,109,25,93,35,109,35 420 DATA 93,45,109,45,50,50,50,70,50,5 0,67,50,50,60,67,60,50,70,67,70,72,70, 72,50,72,50,88,70,88,70,88,50 430 DATA 93,50,93,70,93,50,102,50,102, 50,109,56,109,56,109,64,109,64,102,70, 102,70,93,70
0100 ; GRAPHIC VIOLENCE 0110 ; 0120 ; A.N.A.L.O.G. COMPUTING #8 0130 ; 0140 ; INITIALIZATION CODE 0150 ; 0160 READY = $600 0170 EXPCNT = $601 0180 CYCFLG = $60B 0190 SNDFLG = $60C 0200 COORD1 = $C0 0210 COORD2 = $CD 0220 SETVBV = $E45C 0230 *= $6000 0240 INIT PLA ;DISCARD 0250 LDA #0 ;ZERO OUT: 0260 STA READY ;READY FLAG 0270 STA EXPCNT ;# OF EXPL. 0280 PLA ;INTERRUPT HI 0290 TAX ;PUT IN X 0300 PLA ;INTERRUPT LO 0310 TAY ;PUT IN Y 0320 LDA #7 ;DEFERRED VBI 0330 JSR SETVBV ;SET IT! 0340 PLA ;COORD1 HI 0350 STA COORD1+1 ;SAVE IT 0360 PLA ;PULL COORD1 LO 0370 STA COORD1 ;SAVE IT 0380 PLA ;PULL COORD2 HI 0390 STA COORD2+1 ;SAVE IT 0400 PLA ;PULL COORD2 LO 0410 STA COORD2 ;SAVE IT 0420 PLA ;DISCARD 0430 PLA ;PULL COLOR CYCLE FLAG 0440 STA CYCFLG ;SAVE IT 0450 PLA ;DISCARD 0460 PLA ;PULL SOUND FLG 0470 STA SNDFLG ;SAVE IT 0480 RTS ;FINISHED! 0490 .END
0100 ; GRAPHIC VIOLENCE 0110 ; 0120 ; A.N.A.L.O.G. COMPUTING #8 0130 ; 0140 ; EXPLOSION CALL ROUTINE 0150 ; 0160 READY = $600 0170 EXPCNT = $601 0180 NEWX = $602 0190 NEWY = $603 0200 *=$6000 0210 PLA ;DISCARD 0220 LDA EXPCNT ;# OF EXPL. 0230 CMP #20 ;20 ACTIVE? 0240 BMI EXPOK ;NO, IT'S OK! 0250 PLA ;YES, DISCARD 0260 PLA ;BOTH COORDS 0270 PLA 0280 PLA 0290 RTS ;AND EXIT 0300 EXPOK PLA ;DISCARD HIGH 0310 PLA ;GET X-COORD 0320 STA NEWX ;STORE IT 0330 PLA ;DISCARD HIGH 0340 PLA ;GET Y-COORD 0350 STA NEMY ;STORE IT 0360 LDA #1 ;TELL INTERRUPT 0370 STA READY ;WE'RE READY! 0380 RTS ;AND EXIT BACK 0390 ; TO BASIC! 0400 .END
0100 ; GRAPHIC VIOLENCE 0110 ; 0120 ; A.N.A.L.O.G. COMPUTING #8 0130 ; 0140 ; VBLANK INTERRUPT ROUTINE 0150 ; 0160 READY = $600 0170 EXPCNT = $601 0180 NEWX = $602 0190 NEWY = $603 0200 PLOTCLR = $604 0210 COUNTR = $605 0220 PLOTX = $606 0230 PLOTY = $607 0240 HIHLD = $608 0250 LOHLD = $609 0260 PLOTBVT = $60A 0270 CYCFLG = $60B 0280 SNDFLG = $60C 0290 SNDCNT = $60D 0300 COLOR = $60E 0310 PLOTBL = $620 0320 XPOS = $640 0330 YPOS = XPOS+21 0340 CNT = YPOS+21 0350 LO = $CF 0360 HI = $D0 0370 COORD1 = $CB 0380 COORD2 = $CD 0390 ; 0400 ;SYSTEM EQUATES 0410 ; 0420 XITVBV = $E462 0430 COLPF2 = $2C6 0440 AUDC1 = $D201 0450 AUDF1 = $D200 0460 SAVMSC = $58 0470 POKMSK = $10 0480 IRQEN = $D20E 0490 *=$6000 0500 CLD ;CLEAR DECIMAL 0510 LDA POKMSK ;GET IRQ INT. 0520 AND #$7F ;NO BREAK KEY 0530 STA POKMSK ;THE BREAK KEY 0540 STA IRQEN ;IS NOW OFF! 0550 LDA CYCFLG ;CYCLING COLOR? 0560 BEQ CONT ;NO, CONTINUE 0570 LDA COLOR ;GET LAST COLOR 0580 CLC ;INCREMENT IT 0590 ADC #16 ;BY 16 0600 STA COLOR ;AND SAVE IT 0610 LDA COLPF2 ;GET COLOR REG. 0620 AND #$0F ;GET BRIGHTNESS 0630 ORA COLOR ;ADD THE COLOR 0640 STA COLPF2 ;AND SAVE IT! 0650 CONT LDA SNDFLG ;SOUND ON? 0660 BEQ GO ;NO, SKIP IT! 0670 LDA SNDCNT ;MORE SOUND? 0680 BEQ GO ;NO, SKIP IT! 0690 SEC ;DECREMENT THE 0700 SBC #1 ;SOUND COUNTER 0710 STA SNDCNT ;AND STORE IT 0720 LSR A ;SHIFT DOWN TO 0730 LSR A ;DERIVE VOLUME 0740 LSR A ;FROM COUNTER 0750 STA AUDC1 ;SET UP SOUND 0760 LDA #40 ;CHANNEL 1... 0770 STA AUDF1 ;FINISHED! 0780 GO LDA READY ;NEW EXPLOSION? 0790 BEQ MAIN ;NO, CONTINUE 0800 ; 0810 ;AT THIS POINT, THERE IS A 0820 ;NEW EXPLOSION! 0830 ; 0840 INC EXPCNT ;ONE MORE EXPL 0850 LDX EXPCNT ;PUT IN INDEX 0860 LDA NEWX ;GET X-COORD, 0870 STA XPOS,X ;PUT IN TABLE 0880 LDA NEWY ;GET Y-COORD, 0890 STA YPOS,X ;PUT IN TABLE 0900 LDA #127 ;INITIALIZE THE 0910 STA SNDCNT ;SOUND COUNTER 0920 LDA #0 ;INIT COUNTER 0930 STA CNT,X ;FOR EXPL IMAGE 0940 STA READY ;AND READY FLAG 0950 MAIN STA COUNTR ;ZERO COUNTER 0960 RUNLP INC COUNTR ;NEXT EXPLOSION 0970 LDA EXPCNT ;GET # OF EXPL. 0980 CMP COUNTR ;ANY MORE EXPL? 0990 BPL INDEX ;YES, CONTINUE 1000 JMP XITVBV 1010 INDEX LDX COUNTR ;GET INDEX 1020 LDA #0 ;SET PLOTCLR 1030 STA PLOTCLR ;0=PLOT A BLOCK 1040 LDA CNT,X ;GET COUNTER 1050 ; FOR EXPLOSION 1060 CMP #89 ;ALL DRAWN? 1070 BMI DOPLOT ;NO, DO IT NOW 1080 INC PLOTCLR ;1=ERASE BLOCK 1090 SEC ;GET READY FOR 1100 SBC #89 ;ERASE CYCLE 1110 CMP #89 ;ERASE DONE? 1120 BMI DOPLOT ;NO, ERASE BLOCK 1130 TXA ;MOVE INDEX 1140 TAY ;TO Y REGISTER 1150 ; 1160 ;THE FOLLOWING ROUTINE REPACKS 1170 ;THE EXPLOSION TABLE TO GET RID 1180 ;OF EXPLOSIONS THAT ARE DONE. 1190 ; 1200 REPACK INX ;NEXT EXPLOSION 1210 CPX EXPCNT ;DONE? 1220 BEQ RPK2 ;NO, REPACK MORE 1230 BPL RPKEND ;YES, EXIT! 1240 RPK2 LDA XPOS,X ;NO, START RPK 1250 STA XPOS,Y ;MOVE BACK X 1260 LDA YPOS,X 1270 STA YPOS,Y ;MOVE BACK Y 1280 LDA CNT,X 1290 STA CNT,Y ;MOVE BACK CNT 1300 INY 1310 BNE REPACK ;NEXT REPACK 1320 RPKEND DEC EXPCNT ;DEC POINTERS 1330 DEC COUNTR ;DUE TO REPACK 1340 LDA #8 ;FORCE BRANCH 1350 BEQ RUNLP ;TO NEXT EXPL. 1360 DOPLOT INC CNT,X ;INC COUNTER 1370 TAY ;EXP PHASE IN Y 1380 LDA XPOS,X ;GET X-COORD 1390 CLC 1400 ADC (COORD1),Y ;ADD X OFFSET 1410 STA PLOTX ;STORE IT 1420 CMP #168 ;OFF SCREEN? 1430 BCS RUNLP ;YES, DON'T PLOT 1440 LDA YPOS,X ;GET Y-COORD 1450 CLC 1460 ADC (COORD2),Y ;ADD Y OFFSET 1470 STA PLOTY ;STORE IT 1480 CMP #96 ;OFF SCREEN? 1490 BCS RUNLP ;YES, DON'T PLOT 1500 ; 1510 ;THE FOLLOWING SECTION IS A 1520 ;DEDICATED MULTIPLY ROUTINE 1530 ;WHICH MULTIPLIES THE A REGISTER 1540 ;BY 40, WITH RESULT IN LO & HI 1550 ; 1560 ASL A 1570 STA LO 1580 LDA #8 1590 BEQ X2 1600 JRUNLP BEQ RUNLP 1610 X2 STA HI ;*2 1620 LDA LO 1630 ASL A 1640 STA LO 1650 LDA HI 1660 ROL A 1670 STA HI ;*4 1680 LDA LO 1690 ASL A 1700 STA LO 1710 STA LOHLD 1720 LDA HI 1730 ROL A 1748 STA HI 1750 STA HIHLD ;*8 1760 LDA LO 1770 ASL A 1780 STA LO 1790 LDA HI 1800 ROL A 1818 STA HI ;*16 1820 LDA LO 1830 ASL A 1840 STA LO 1850 LDA HI 1860 ROL A 1870 STA HI ;*32 1880 LDA LO 1890 CLC 1900 ADC LOHLD 1910 STA LO 1920 LDA HI 1930 ADC HIHLD 1940 STA HI ;+*8=*46 1950 ; 1960 ;AT THIS POINT, THE MULTIPLY BY 1970 ;40 IS FINISHED, AND WE NEED TO 1980 ;GET AN OFFSET INTO THE SCREEN 1990 ;MEMORY 2000 ; 2010 LDA SAVMSC ;ADD THE DISPLAY 2020 CLC ;ADDRESS TO GET 2030 ADC LO ;THE ACTUAL 2040 STA LO ;ADDRESS OF THE 2050 LDA SAVMSC+1 ;BYTE THAT HILL 2060 ADC HI ;BE ALTERED FOR 2070 STA HI ;THE PLOT. 2080 LDA PLOTX ;MASK PLOTX FOR 2090 AND #3 ;THE PLOT AND 2180 TAY ;PLACE IN Y REG 2110 LDX PLOTBL,Y ;GET PLOT BITS, 2120 STX PLOTBYT ;AND SAVE! 2130 LDA PLOTX ;GET PLOTX AND 2140 LSR A ;DIVIDE 2150 LSR A ;BY 4 2160 CLC ;AND ADD TO 2170 ADC LO ;PLOT ADDRESS 2180 STA LO ;FOR FINAL PLOT 2190 LDA HI ;ADDRESS. 2200 ADC #0 2210 STA HI 2220 LDY #6 ;ZERO OUT Y REG. 2230 LDA PLOTCLR ;ERASING? 2240 BNE CLEARIT ;YES,GO CLEAR IT 2250 LDA PLOTBYT ;GET PLOT BITS, 2260 EOR (LO),Y ;ALTER DISPLAY, 2270 STA CL01,Y ;AND PLOT IT! 2280 LDA #6 ;FORCE BRANCH 2290 JRUNLP2 BEQ JRUNLP ;AND EXIT! 2300 CLEARIT LDA PLOTBYT ;PLOT BITS 2310 EOR #$FF ;FLIP 'EM 2320 AND (LO),Y ;ALTER DISPLAY 2330 STA (LO),Y ;AND ERASE IT! 2340 LDA #0 ;FORCE BRANCH 2350 BEQ JRUNLP2 ;AND EXIT! 2360 .END