Graphics Seven Plus
First came the TRS-80, Model I. It provided character-oriented graphics.
Next came the Apple. It provided both character and line graphics (one or the other).
Now we have the Atari. It provides 14 graphics modes, some character-oriented, some line-oriented.
"Fourteen modes?" you say. "The Basic manual lists nine." Well, that's because Basic only allows you to access nine directly. However, there are others lurking within the machine waiting for a programmer to find them. All are variations on the available modes, some quite useful. One is so useful that this article will be devoted to discussing its use.
All character-line graphics on the Atari ("playfield graphics") are generated by the close cooperation of two chips, Antic and CTIA. Antic fetches data for 3.7 million points per second (320 per line x 192 lines x 60 per second) and feeds it to CTIA which generates the TV picture from that data. To determine what sort of image should be generated (character, line, pixel size, etc.), Antic looks to his program, the display list. This program coexists in memory with all the usual Basic and 6502 programs. Anyway, his program, composed of individual instruction codes, tells him what sort of image to generate.
There are 14 image-generating codes in Antic's program. Now when Basic was designed, for some reason it was decided to allow access to only nine of these codes, rather than the full 14. And in particular, the highest resolution four-color mode was left out. This is "graphics 7+" (also known as "graphics seven-and-a-half.")
We got a great deal of mail from people asking how to use this graphics mode when we documented its existence back in the July 1981 Creative. (If you wish to see a tutorial on the Atari for the Basic programmer, go back to the June issue and read the "Outpost" columns to date. Sadly, we can't explain how Antic and such work in each article because the explanation is so long, but we can refer you to previous issues to get a background.)
It takes a bit of work and a fair grasp of what goes on inside the Atari, but the results are well worth it: in the highest four-color mode, we can get double the resolution of graphics 7 using graphics 7+.
Graphics 7, you will recall, gives us 96 vertical x 160 horizontal pixels in four colors. Graphics 8 gives us 192 vertical x 320 horizontal, but only in one color. Graphics 7+ gives us 192 vertical x 160 horizontal in four colors.
This is an extremely useful mode. Graphics 8 has several disadvantages; single dots sometimes become red or blue when white was intended because of "artifacting," and candystripes tend to appear on all near-vertical lines. Graphics 7 has pixels the size of 2 x 2 graphics 8 dots, and is too "chunky" for really accurate graphics. Graphics 7+, with double the vertical resolution, brings us close to the limits of most monitors in terms of color resolution, with 2 x 1 graphics 8 dots. No artifacting, no funny stripes, just nice colors in truly high resolution.
I should also mention that the graphics 7+ resolution is equal to the resolution of a player or missile at size x 1.
Here at Houston Instruments, where I work, we have a project going to interface a plotter, capable of eight colors, to a digitizer. The image to be plotted must be displayed on the TV. Graphics 7 resolution is unacceptable; the individual pixel is too large for a quality display. But graphics 7+ provides twice the resolution while retaining the four colors of data. (Now, you'd like to know how I plan to get eight colors, right? I must confess to having a few sneaky ideas how to do so, and I promise to document the method should I succeed.) However, for now, four colors at 160 x 192 will do nicely.
A Look at Graphics 7 and 8
Graphics 7+ is midway between 7 and 8, so let's look at 7 and 8 to help understand how to generate 7+.
Graphics 7 is a "four color" mode. This means that for every point on screen, two bits of information are saved in memory. Depending on which of the four numbers possible is saved in those two bits, one of four color registers is selected to display color. (Actual color information is not saved in the display memory; rather, a color register number is saved, with the actual color being stored in the register.) Hence, one byte (eight bits) in graphics 7 display memory, looks like this:
ww xx yy zz
where w, x, y, and z are the information for a given point on screen.
10 REM PROGRAM 1 -- DAVE SMALL 20 REM PROGRAM TO GENERATE GR.7 30 REM SAMPLE DISPLAY 40 REM 50 REM 8K BASIC VERSION 60 REM 70 GRAPHICS 7 80 COLOR 1 90 PLOT 1,1 100 DRAWTO 159,1 110 COLOR 2 120 DRAWTO 159,80 130 COLOR 3 140 DRAWTO 1,1 141 FOR Z=1 TO 20 142 COLOR (INT(RND(0)*3)+1) 143 PLOT (INT(RND(0)*159)),(INT(RND(0)*80)) 144 NEXT Z 150 PRINT "NOTE EACH GRAPHICS 7 PIXEL" 160 PRINT "USES TWO SCAN LINES." 170 GOTO 170
10 REM PROGRAM 2 -- DAVE SMALL 20 REM PROGRAM TO GENERATE GR.8 30 REM SAMPLE DISPLAY 40 REM 50 REM 8K BASIC VERSION 60 REM 70 GRAPHICS 8 75 SETCOLOR 2,0,0 80 COLOR 1 90 PLOT 1,1 100 DRAWTO 159,1 120 DRAWTO 159,80 140 DRAWTO 1,1 141 FOR Z=1 TO 20 142 COLOR (INT(RND(0)*3)+1) 143 PLOT (INT(RND(0)*159)),(INT(RND(0)*80)) 144 NEXT Z 150 PRINT "NOTE EACH GRAPHICS 8 PIXEL" 160 PRINT "USES ONE SCAN LINE." 170 GOTO 170
10 REM PROGRAM 3 20 REM 30 REM CONVERT GR.7 TO GR.7+ 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 60 REM 70 REM CREATE IMAGE 530 REM *********************** 540 REM ** FROM CREATIVE COMPUTING.. 545 REM **GENERATES MULTICOLOR SPIRAL 550 GRAPHICS 7:DEG :DIM C(3) 555 PRINT "CREATING IMAGE." 590 R=20:COLOR 1:C=1 600 X0=79:Y0=47 610 FOR K=0 TO 3:C(K)=K+1*2:NEXT K 620 FOR K=1 TO 3 630 X=X0+R*COS(360):Y=Y0:PLOT X,Y 640 FOR I=0 TO 5*360 STEP 75 650 X=X0+R*COS(I):Y=Y0+R*SIN(I) 660 DRAWTO X,Y 665 C=C+1:IF C>3 THEN C=1 667 COLOR C 670 NEXT I:R=R+12 680 NEXT K 690 Z8=1 700 PRINT "MODIFYING DL." 1000 REM GR.7 TO GR.7+ 1010 START=PEEK(560)+256*PEEK(561) 1020 POKE START+3,14+64:REM LMS 1030 FOR Z=START+6 TO START+6+96 1040 IF PEEK(Z)=13 THEN POKE Z,14 1050 NEXT Z 1059 REM REMOVE THIS STOP FOR LOOP.. 1060 STOP 1100 REM GR.7+ TO GR.7 1110 FOR Z=START+6+96 TO START+6 STEP -1 1140 IF PEEK(Z)=14 THEN POKE Z,13 1150 NEXT Z 1155 POKE START+3,13+64:REM LMS 1160 GOTO 1020
The memory is mapped starting from the upper lefthand corner of the screen, from the beginning of display memory, across the screen, down one line, and so on. Hence, since we have 96 x 160, or 15,360 points, and four points stored per byte, we use 3840 bytes of data.
When Antic generates graphics 7 he does two scan lines of the same data. Hence, each Antic instruction generates two scan lines, and 96 of these instructions generate 192 lines--the height of the screen.
In graphics 8, we only save one bit of information per point. That bit is used to determine at what intensity a point is plotted, and where the background color and intensity and foreground intensity are stored in color registers. Since only one bit is saved per point, a graphics 8 display memory byte looks like this:
a b c d e f g h
where each letter represents one point. There are 320 x 192 points, 8 to a byte, which comes out to 7680 bytes of data.
Each graphics 8 Antic instruction generates one scan line, so there are 192 of them to a full screen.
Now graphics 7+ has the same vertical resolution as graphics 8--one line per Antic instruction. It also has the same horizontal resolution as graphics 7(160), and the four colors. Do you begin to see why it is such a useful mode?
Note that different information must be written into display memory to draw a line in a different mode. In particular, in graphics 7 or 7+ two bits must be written for each pixel, whereas in graphics 8 one bit must be written. This will be very important shortly. An operating system routine, stored in the ROM plug-in cartridge, handles all of the bit-shifting and masking to write the required bits into memory, based on what graphics mode it thinks it is in.
Time for some sample programs: The first generates a simple graphics 7 display. The next generates a simple graphics 8 display. This is to allow you to compare the resolutions. See Programs 1 and 2.
Next, we will take a graphics 7 display and convert it to graphics 7+.
What will happen? Well, first, since we have 96 instructions in graphics 7, each generating two scan lines, we get a total of 192 scan lines. If each of those 96 instructions generates only one scan line, as in graphics 7+, the screen will only be half filled (only the top 96 scan lines). The same display that graphics 7 had in it will be retained, it will just shrink vertically.
So for our third program, let's take a graphics 7 display, and convert it to graphics 7+. You'll see the effect of doubling your vertical resolution, and won't believe how fine a line can be drawn in four colors. All we'll do is take the 96 bytes of Antic's program, when he's in graphics 7, and convert them from an Antic code 13 (graphics 7) to a 14 (graphics 7+). See Program 3.
Pretty neat, right? Nice resolution. Now if we could only get the whole screen in that resolution.
Well, we can. We could go the tough way, where we allocate memory, build 192 graphics 7 (14) instructions, set memory pointers to display memory, ad infinitum. Were we working in assembly language, we would have to do it that way. But there's an easier way: take an existing display list and convert it. That way Basic has already allocated memory space and so forth, and we don't need to worry about fooling it into leaving memory alone.
We can take a graphics 8 display list, already 192 instructions long, and convert the 15's (Antic code for graphics 8) to 14's. That part is easy, just a FOR-NEXT loop to convert every 15 to a 14. The only slightly tricky part is catching the LMS instructions (64 + 15 or 79), changing them to 78, and leaving the display memory data bytes alone. (See August 1981 for a discussion of LMS). This way, the right amount of screen memory is already reserved for us, the display list is set up, pointers and all, and we've saved a great deal of work.
Next, since graphics 8 uses a different bit pattern to display material, we'll have to fool the operating system into thinking we're really in graphics 7 so it uses the graphics 7 bit/shift routines. This is a matter of one POKE to the low memory location where the operating system looks each time it does a line draw to determine what graphics mode it is in. The location contains the graphics number currently in effect. We will, thus, POKE a 7 in there; it should currently contain an 8 from when graphics 8 was set up.
Well, here we go. (See Program 4.) We set up graphics 8, change the display list to graphics 7+, and do a three-color draw at the top of the screen. No problem, works fine. But when we try to draw anywhere in the lower half of the screen, we get an ERROR 141 -cursor out of range.
Many, many people have tried the above routine to get into graphics 7+. All of them have run into this problem. You see, the operating system, while drawing a line, constantly checks to see if the line is going off of the visible area. Should it do so, an ERROR 144 is returned and the line drawing process stops. The OS thinks we're in graphics 7 (96 x 160), so when we try to draw below line 96, it thinks it is at the bottom of the screen and terminates the draw. In computerese this is known as "bounds checking"--and anyone who has watched football knows what "out of bounds" means. (See, these computer snob words really do have humble beginnings).
10 REM PROGRAM 4 20 REM 30 REM CONVERT GR.8 TO GR.7+ 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 60 REM 65 DIM C(3) 70 REM DISPLAY LIST MODS 80 GRAPHICS 8 90 PRINT "CONVERTING DL FROM 8 TO 7+." 100 START=PEEK(560)+256*PEEK(561) 110 POKE START+3,14+64 120 FOR Z=START+6 TO START+6+192+6 130 IF PEEK(Z)=15 THEN POKE Z,14 140 IF PEEK(Z)=15+64 THEN POKE Z,14+64:Z=Z+2:REM (SKIP LMS DATA BYTES) 150 NEXT Z 200 REM 210 REM LET OS THINK WERE IN GR.7.. 220 POKE 87,7 390 PRINT "CREATING UPPER HALF IMAGE" 400 YADD=1 410 GOSUB 500 420 PRINT "CREATING LOWER HALF IMAGE" 425 YADD=30 430 GOSUB 500 440 STOP 500 REM 530 REM ********************* 540 REM ** FROM CREATIVE COMPUTING.. 545 REM ** GENERATES MULTICOLOR SPIRAL 550 DEG 590 R=10:COLOR 1:C=1 600 X0=79:Y0=47 610 FOR K=0 TO 3:C(K)=K+1*2:NEXT K 620 FOR K=1 TO 3 630 X=X0+R*COS(360):Y=Y0:PLOT X,Y+YADD 640 FOR I=0 TO 5*360 STEP 75 650 X=X0+R*COS(I):Y=Y0+R*SIN(I) 660 DRAWTO X,Y+YADD 665 C=C+1:IF C>3 THEN C=1 667 COLOR C 670 NEXT I:R=R+12 680 NEXT K 690 Z8=1 700 RETURN
What Do We Do?
We can't POKE an 8 into the OS location, because then the draw routine will use the wrong bit shifting routine and we'll get all sorts of crazy bit patterns and colors. (Feel free to try it--there are many interesting effects obtainable this way. Just delete the POKE 87,7 in Program 3.) And we can't get by with a POKE 7...because then the OS thinks we're going out of Bounds. Because both bounds checks and draw routine selection are based on the same location, we're stuck. (The memory location is called DINDEX and is located at 57 hex or 87 decimal).
The problem resides in the extreme care taken to avoid out-of-bounds conditions. If we could draw out of bounds, and have the Atari blindly do the draw instead of telling us we were wrong, then graphics 7+ would work. Even though the operating system might conclude that we were out of our minds and drawing off the bottom edge of the screen, it would continue to draw in the right places for our graphics 7+ to work. (Screen memory, by the way, is 3780 bytes in graphics 7 and 7680 in graphics 7+. Graphics 7+ and graphics 8 use the same memory size.)
Well, the OS routine is in ROM and cannot be modified, short of pulling the chips out and putting new ones in. As I am no hardware expert this solution isn't acceptable. Besides, if I did, my programs would run only on my machine. However, it did bring to mind an analogy which solved the problem. Character sets are stored in ROM, also, and are unmodifiable, unless they are copied into RAM first. So why not copy the OS draw routine into RAM, zap the bounds check, and use it for graphics 7+?
To make a long story even longer, that's what I did. The rest of the article describes this process. The first time through, I did it all in Basic, but that was too slow, so I recoded the slow parts in 6502 assembler. Those routines I used in the graphics 7+ driver. (They should be usable in any graphics mode; they just ignore all bounds checks. However, the Atari caution extends beyond overprotecting the user; a line drawn out of bounds could go sailing straight through memory reserved for other things, and crash the Atari. Just be careful; don't try to draw from 1,1 to 3000,6700.)
The final result is three assembly routines. They are fast and efficient and both fit into page 6 in memory (600-700 hex), 256 bytes set off by Atari for a user's own purposes and left untouched by Atari routines. The first modifies the graphics 8 display list to a graphics 7+. The second copies the OS draw routine into free RAM for modification. I use Basic for the small amount of POKEing that must be done in the OS routine to make it work properly in its new memory location (it involves relocating a few addresses) and to DRAW a line using the OS routine (it just takes arguments from the Basic USR call and feeds them to the draw routine).
To use graphics 7+, one does a graphics 8 call, calls the first USR routine to set up the 7+ display list, calls the second routine to fetch the draw routine in RAM and modify it, and then all is ready. Line draws are made in one of two forms:
X=USR(third routine,X coordinate,Y coordinate,color#) or X=USR=(third,X1,Y1,X2,Y2,COLOR)
0 0250 *= $0680 02FB 1390 ATACHR = $2FB: COLOR DATA 05A 1340 OLDROW = $SA FROM Y 06FD 4CFC7C 1790 JMP $7CFC O.S...MUST MOD 10 ; 20 ; PROGRAM 5 LISTING.. 22 1400 ICCOMZ = $22 CIO DRAW FLAG 30 ; 40 ; THREE ASSEMBLY ROUTINES FOR 50 ; PAGE 6 54 1370 ROWCRS = $54 TO Y 55 1360 COLCRSL= $55 TO X LO 56 1350 COLCRSH= $56 TO X HI 57 1380 DINDEX = $57 CURR GR. MODE 60 855C 1500 STA OLDCOLH 68D 8D9706 0330 STA FETCHH (FETCH STMT) 69E D00S 0520 BNE NOT15 70 ; 1.CONVERTS DL FROM GR.8 GR7.5. 80 ; 2.COPIER FROM OS ROM TO RAM. 90 ; 3.GR7.+ DRAWTO. FULL SCREEN 0100 ; GR.7+ DRAW ROUTINE. 0110 ; 0120 ; COPYRIGHT 1981 BY DAVID M. SMALL 0130 ; 0140 ; 0150 ; ROUTINE 1: 0160 ; ASSEMBLY ROUTINE TO CONVERT 0170 ; A GR.8 DISPRLAY LIST TO A GR 7.+ 0180 ; DISPLAY LIST. 0190 ; CONVERTS ALL 15'S TO 14'S 0200 ; CONVERTS ALL (64+15) TO (64+14) 0210 ; (BUT WILL SKIP LMS DATA BYTES) 0220 ; 0230 ; PLACED IN PAGE 6. 0240 ; 0270 ; 0310 ; 0350 ; 0370 ; 0380 ; LOOP 202 TIMES. CHANGE 15 TO 0390 ; 14, 79 TO 78, SKIP LMS DATA. 0400 ; 0440 ; 0450 ; IF GR.2 ENCOUNTERED, QUIT -- 0460 ; HAS A TEXT WINDOW. 0470 ; 0500 ; 0550 ; 0590 ; 0660 ; 0680 68 0260 PLA SATISFY BASIC 0681 AD3002 0280 LDA 560 0684 8D9606 0290 STA FETCHL (FETCH STMT) 0687 8DAC06 0300 STA STOREL (STORE STMT) 0690 ; 0693 A200 0360 LDX #0 INIT X 0695 BD3412 0430 LOOP LOA $1234,X GET DL BYTE 0696 0410 FETCHL = *+1 0697 0420 FETCHH = *+2 0698 C942 0480 CMP #66 0720 ; 0740 ; 0758 ; ---------------------------- 0760 ; 0760 ; ROUTINE 2 0770 ; 0780 ; COPIES O.S. ROM TO RAM (DRAW 0790 ; ROUTINES) TO ALLOW BOUNDS 0800 ; CHECK REMOVAL. 0810 ; 0820 ; COPIES $FCFC TO $FE44 0830 ; TO $7CFC TO $7E44 0840 ; 0850 ; (THIS IS QUITE EASY TO CHANGE 0860 ; TO CUSTOMIZE FOR YOUR ATARI 0070 ; ON A 40K-48K MACHINE THIS 0880 ; IS RIGHT BELOW THE DL/DM.) 0090 ; 0900 ; (65092-64764= 328 0910 ; 328 - 256 = 72 0920 ; 0930 ; -- $FCFC TO $FDFB ($FF BYTES) 1010 ; 1020 ; -- $FDFC TO $FE44 1100 ; 1110 ; ------------------------------ 1120 ; ROUTINE 3 1130 ; 1140 ; THIS ROUTINE IS CALLED FROM 1150 ; BASIC TO PERFORM A DRAWTO 1160 ; FUNCTION IN GR 7.5, THERE ARE 1170 ; TWO POSSIBLE CALLS: 1180 ; 1190 ; D=USR(X1,Y1,X2,Y2,COLOR) 1200 ; D=USR(X2,Y2,COLOR) 1210 ; 1220 ; FIRST WILL DRAW A LINE BETWEEN 1230 ; THE SPECIFIED COORDINATES IN 1240 ; SPECIFIED COLOR. SECOND WILL 1250 ; DRAWTO FROM OLD LOCATION TO 1260 ; SPECIFIED COORDINATES. 1270 ; 1280 ; THIS ROUTINE REQUIRES THE O.S. 1290 ; DRAW ROUTINE BE COPIED INTO 1300 ; RAM AND MODIFIED. SEE ARTICLE. 1310 ; 1410 ; PULL OFF AND STORE ARGS 1480 ; 1560 ; 1610 ; 1650 ; 1690 ; 1700 ; SETUP IS DONE, OTHER MISC: 1710 ; 1760 ; 1770 ; CALL DRAW RAM ROUTINE 1780 ; 1800 END 6000 68 1510 PLA GET FROM X LO 060000 8558 1520 STA OLDCOLL
The first performs a DRAWTO from the old cursor location to the specified X and Y coordinates. The second performs a line draw between the specified points (equivalent to PLOT X1,Y1, DRAWTO X2,Y2). Both routines perform the draw in the specified color, not the color of the current COLOR statement.
Alas, the OS draw routine is too long to fit into the small page 6. So it must be stored elsewhere in RAM. Finding a free space in RAM isn't too hard. However, finding a space that is free on everyone's Atari is pretty hard. Memory sizes range from 8K to 48K (40K with Basic cartridge). I decided to tailor the routine for my 40K system and let users do relocation as necessary for their own systems. Nowadays there is so much player-missile memory being reserved, charset arrays, and so forth that a general solution is very difficult.
For Advanced Programmers
The following is a bit technical but is intended for assembly programmers. The OS routines start at $FCFC and end at $FE44 (inclusive). They are copied to $7CFC through $7E44. Several JMPs inside are relocated back to the RAM routine, making this a non-relocatable routine. (The fact that I am copying it down an even $8000 makes it quite easy to relocate.) It should be simple to do this for other size memories; the calculations are self-documenting in the OS and assembly listings. Just make sure the JMPs are changed to JMP to the point in RAM where the corresponding statement to the ROM statement is. Note that $7E44 is just below the DL/DM in a 40K or 48K (same thing with a Basic cartridge) machine. Hence it is in a relatively "safe" area.
9000 REM LOADER 9010 Z=6*256+8*16 9020 READ Z1 9030 IF Z1=-1 THEN RETURN 9040 POKE Z,Z1 9050 Z=Z+1 9060 GOTO 9020 10000 DATA 104,173,48,2,141,150,6,141,172,6,173,49,2,141,151 10010 DATA 6,141,173,6,162,0,189,52,18,201,66,240,29,201,15 10020 DATA 208,5,169,14,76,171,6,201,79,208,2,169,78,157,52 10030 DATA 18,232,201,79,208,2,232,232,224,203,144,220,96,162,0 10040 DATA 104,189,252,252,157,252,124,232,224,0,208,245,162,0,189 10050 DATA 252,253,157,252,125,232,224,75,208,245,96,104,201,3,240 10060 DATA 15,201,5,240,1,96,104,133,92,104,133,91,104,104,133 10070 DATA 90,104,133,86,104,133,85,104,104,133,84,104,104,141,251 10080 DATA 2,169,17,133,34,76,252,124 11000 DATA -1
10 REM PROGRAM -- ASSEMBLY VERSION 15 REM REQUIRES AUTORUN.SYS OR LOAD 20 REM 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 55 REM 56 IF PEEK(1536+128)<>104 THEN PRINT "ASSEMBLY NOT LOADED..":STOP 60 REM DEFINES 61 CONVERT=6*256+8*16:REM $0680 62 COPY=6*256+11*16+10:REM $06BA 63 DRAW=6*256+13*16+6:REM $06D6 65 DIM C(3) 67 REM 70 REM DISPLAY LIST MOOS 80 GRAPHICS 8 90 X=USR(CONVERT) 97 REM 200 REM 210 REM LET OS THINK WE'RE IN GR.7.. 220 POKE 87,7 230 REM 300 PRINT "PERFORMING OS COPY." 310 X=USR(COPY) 320 REM RELOCATION 321 POKE (7*4096+13*256+9*16+8),(7*16+14):REM FD98, FE TO 7E 322 POKE (7*4096+14*256+2*16+6),(7*16+14):REM FE26, FE TO 7E 323 POKE (7*4096+14*256+4*16+1),(7*16+13):REM FE41, FD TO 7D 324 REM NOP OUT BOUNDS CHECKS 325 L=7*4096+13*256+15*16+6 326 FOR Z=L TO L+2 327 POKE Z,234:REM NOP 328 NEXT Z 350 REM 390 PRINT "CREATING FULLSCREEN IMAGE" 500 REM 530 REM ************************* 540 REM ** FROM CREATIVE COMPUTING.. 545 REM ** GENERATES MULTICOLOR SPIRAL 550 DEG 590 R=20:COLOR 1:C=1 600 X0=79:Y0=85 610 FOR K=0 TO 3:C(K)=K+1*2:NEXT K 620 FOR K=1 TO 3 630 X=X0+R*COS(360):Y=Y0+R*SIN(360) 636 Z=USR(DRAW,X,Y,X,Y,0):REM (PLOT) 640 FOR I=0 TO 5*360 STEP 75 650 X=X0+R*COS(I):Y=Y0+R*SIN(I) 662 Z=USR(DRAW,X,Y,C):REM (DRAWTO) 665 C=C+1:IF C>3 THEN C=1 670 NEXT I:R=R+20 680 NEXT K 690 Z8=1 700 STOP
The bounds check is a simple JSR. This is changed to NOP (no-operation) with three NOP codes.
Programs 5, 6, 7, and 8 are listings of four assembly/Basic routines. (The Atari OS listing is copyrighted and doesn't appear here, but you can easily look up the addresses specified to find where I am copying from yourself.)
Program 5 is the page 6 assembly listing. Program 6 is the assembly program converted to DATA statements. This program is appended to your code to load the assembly routine. Program 7 is the "Sunset" multiple color spiral run in graphics 7+, using an already loaded assembly routine, and provides an example of using graphics 7+ when the routines are loaded. Finally, Program 8 is an example of using the DATA statements of Program 6 to load and draw a pretty figure using graphics 7+.
Feel free to delete the REM statements; I document the code heavily in order to make it easy to understand, but the documentation isn't needed in the final copy. (I also break up all hex opcodes for clarity; these could be calculated to save the machine the work each runthrough.)
On using AUTORUN.SYS: This is a handy way for disk users to load these routines. Boot up DOS (2.OS), and run Program 6. Next, go to DOS. Do the binary save (K), from $600 to $6FF:
and thereafter when you boot up with that disk, the graphics 7+, routines will be loaded automatically.
Generally DOS and Basic will leave these routines alone once loaded unless you reboot the system or have a particularly nasty crash. Hence, even users without disks may not have to reload the data each program run.
Well, there you have it, graphics 7+. I hope to see more and more use of it! These routines can easily be copied into a AUTORUN.SYS file and automatically loaded along with Basic, or POKEd into memory when needed. Enjoy the world of double resolution graphics 7.
10 REM PROGRAM 8 --- DEMOS LOAD THRU 15 REM DATA STATEMENTS. 20 REM 40 REM DAVE SMALL 50 REM 8K BASIC VERSION 54 GOSUB 9000 55 REM 56 IF PEEK(1536+128)<>104 THEN PRINT "ASSEMBLY NOT LOADED..":STOP 60 REM DEFINES 61 CONVERT=6*256+8*16:REM $0680 62 COPY=6*256+11*16+10:REM $06BA 63 DRAW=6*256+13*16+6:REM $06D6 65 DIM C(3) 67 REM 70 REM DISPLAY LIST MOOS 80 GRAPHICS 8+16 95 X=USR(CONVERT) 96 GOTO 200 97 REM 200 REM 210 REM LET OS THINK WE'RE IN GR.7., 220 POKE 87,7 230 REM 300 REM 310 X=USR(COPY) 320 REM RELOCATION 321 POKE (7*4096+13*256+9*16+8),(7*16+14):REM FD98, FE TO 7E 322 POKE (7*4096+14*256+2*16+6),(7*16+14):REM FE26, FE TO 7E 323 POKE (7*4096+14*256+4*16+1),(7*16+13):REM FE41, FD TO 7D 324 REM NOP OUT BOUNDS CHECKS 325 L=7*4096+13*256+15*16+6 326 FOR Z=L TO L+2 327 POKE Z,234:REM NOP 328 NEXT Z 350 REM 390 REM 400 SETCOLOR 0,2,4:REM RED 410 SETCOLOR 1,7,4:REM BLUE 420 SETCOLOR 2,13,4:REM GREEN 500 DEG 505 X2=SIN(0)*70+70:Y2=COS(0)*80+80 507 Z=USR(DRAW,X2,Y2,X2,Y2,0):REM PLOT 508 C=1 510 FOR X=0 TO 360 STEP 4 520 X1=SIN(X*1.5)*70+70 530 Y1=COS(X*2)*80+80 531 X2=SIN(X+120)*40+60 532 Y2=COS(X-40)*50+60 540 Z=USR(DRAW,X1,Y1,X2,Y2,C) 545 C=C+1:IF C=4 THEN C=1 550 NEXT X 560 GOTO 560 9000 REM LOADER 9010 Z=6*256+8*16 9020 READ Z1 9030 IF Z1=-1 THEN RETURN 9040 POKE Z,Z1 9050 Z=Z+1 9060 GOTO 9020 9999 REM DATA FOR GR 7+ DRIVER 10000 DATA 104,173,48,2,141,150,6,141,172,6,173,49,2,141,151 10010 DATA 6,141,173,6,162,0,189,52,18,201,66,240,29,201,15 10020 DATA 208,5,169,14,76,171,6,201,79,208,2,169,78,157,52 10030 DATA 18,232,201,79,208,2,232,232,224,203,144,220,96,162,0 10040 DATA 104,189,252,252,157,252,124,232,224,0,208,245,162,0,189 10050 DATA 252,253,157,252,125,232,224,75,208,245,96,104,201,3,240 10060 DATA 15,201,5,240,1,96,104,133,92,104,133,91,104,104,133 10070 DATA 90,104,133,86,104,133,85,104,104,133,84,104,104,141,251 10080 DATA 2,169,17,133,34,76,252,124 11000 DATA -1