Sixteen colors and beyond; extended hi-res graphics on the Apple. David Lubar.
Until now, anyone doing high-resolution graphics on the Apple has faced some frustrating limitations. While six colors are available, certain colors cannot appear next to one another within the same byte. As a result of this, we have all dealt with the choice of limiting object movement and location, limiting background colors, or ignoring the changes and hoping no one will notice.
Well, such problems are now history. If you own an Apple IIc or IIe with extended 80-column card, you have at your fingertips the ability to produce extended hi-res graphics with 16 independent colors.
The following article shows how this extended mode works and how to use it from Basic or assembly language. The concepts covered assume some familiarity with binary and hex numbers and a passing aquaintance with standard hi-res on the Apple. Sample programs are included for those who want to get the results but don't care about the details. so, if you couldn't care less about bits, pixels, and other hacker delights, just skip the dulk of this article and go to the section on using the sample programs. For the rest of us, if's on to the gory details. But first, a word of inspiration. Why Bother
Extended hi-res follows in the graphic tradition established by the Apple II, requiring a fairly complex amount of bit fidding to get results. While the Apple has built-in routines for normal hi-res, to work with the new mode you must start from scratch. Is it worth the effort?
As mentioned above, this mode has no color conflicts. Also, color can be thought of as a form of resolution. Given two systems with the same number of pixels, the one with more colors is capable of displaying greater detail. Objects can have shadings and highlights, and features can be market with contrasting colors. The background possibilities produced by dithering (blending patterns of colors to produce a new shade) increase as the color palette expands.
Beyond all this, there is one compelling reason to use extended hi-res. As the mountain climbers say, "It's there." Part of the fun of owning a computer is pushing the machine to its limit, making it do as much as possible. Who knows what neat things will result.
Standard hi-res graphics on the Apple uses 40 bytes per line, with seven bits out of each byte controlling pixels. This gives a potential resolution of 280 pixels.
However, the color of a pixel is determined in part by whether a bit is at an odd or an even coordinate. This cuts the actual resolution for color graphics down to 140 pixels per line.
Extended hi-res uses 80 bytes per line, thus offering a potential of 560 plotting locations. As in the standard mode, this resolution comes without any color control. to get 16 colors, you need four bits per pixel (a pattern of four bits has 16 possible values from 0000 to 1111). Normally, mode using four bits would be ideal since that would work out as two pixels per byte.
The problem here is that extended hi-res maintains the beastly tradition of ignoring the hi bit. Only seven bits out of each byte are used for graphics data. We pause here for a collective sigh. Shifty Little Devils
As a result of losing the hi bit, the data for some pxiels are spread between two bytes. So, the first problem with which we must deal is setting the right bits in the proper bytes to light the desired pixel. For example, a blue pixel has a pattern of 0001 and a white pixel is 1111. The hex value used to store these colors in the first pixel of a line would be $01 for blue and $0F for white. (Note that, as in standard hi-res, the lowest bit plots the leftmost position.)
When you move to the next pixel, the bit pattern is shifted four positions. Since the hi bit of the byte is unused, one bit must move to the next byte. thus, blue in the second position would be $10, $00, and white would be $70, $01. See Figure 1 for an example of this.
With four bits per pixel and seven bits available from each byte, it take four bytes to plot the first seven pixels. Then the pattern repeats. So, each color can be represented by seven different values, depending on the coordinate of the pixel being plotted, and some of these values are spread between two bytes.
While this seems quite bizarre, it is not really that much different from standard hi-res, where each has seven different byte values for each pair of pixels.
The next problem is knowing which byte to change. The 80 bytes of each diplay line are taken alternately from main memory and the auxiliary memory on the 80-column card. The first byte of each line comes from auxiliary memory. So, to plot a pixel we need to know which bit pattern to use, which byte or bytes to change, and whether each byte is in main or auxiliary memory. This is a time-consuming task. Fortunately, there are few tricks that simplify the work.
In my first grapplings with this mode, I tried to figure out what was happening by putting the problem on paper. This produced some fearful symmetry, or at least a clue to what was going on. Take a look at Figure 2. It shows the first four bytes of the extended hi-res screen, breaking the data into groups of four bits and showing the memory bank that produced each byte.
there are three features of interest. First, each pixel is either part of one byte or spread between two bytes. Second, the starting byte of each pixel comes either from main or auxiliary memory. Finally, each pixel starts in either an odd or even byte. All this has to be determined before plotting a pixel.
Some bit diddling produces a few useful patterns. Taking just the first seven pixels for now, note that all pixels that require just one byte occur at even coordinates (0,2,4,6).
Next, look at the pixels that start in auxiliary memory. these occur at coordinates 0, 1, 4, and 5. There is a common thread here. Each of these values, in binary, has a zero in the second bit. So, by checking the first two bits of a coordinate, we can tell whether to start in main or auxiliary memory, and whether one or two bytes must be accessed. If the lo bit of the coordinate is on, the number is odd and we start in main memory. If the next bit is on, we need to deal with two bytes.
One last glance at the illustration shows that if the coordinate is greater than three, the plotting starts on an odd byte. all of this works for the first seven pixel coordinates. the the pattern repeats. Before plotting, we need to know the remainder when the coordinate is divided by seven. Math types call this MOD7. I call it a nuisance.
The final bit of information needed is the starting byte of the desired horizontal screen line. The Apple screen is not mapped in linear order (time for another large collective sigh). The standard way to get the location is with a look-up table.
The address can also be calculated, but this is time-consuming. If you are not familiar with screen look-up tables, check your back issues, or look at the way Listing 1 finds the screen address. Once you have the start of the line, you can find the address of the block of four bytes using the formula BYTE = START + INT (XLOC/7)*2, where XLOC is the horizontal coordinate.
OK, we have all the information required to plot a pixel. To get something on the screen, two separate actions are required. first, we must deal with all the stuff discussed above. As if that weren't enough, we also have to handle the bank switching needed to store in main or auxiliary memory. Before getting into the actual plotting, let's look at the various switches used in extended hi-res. Switch Hitters
If you have a IIe with extended 80-column card, you must have the jumper installed. First, check the serial number on your Apple main board. If it begins with an A, you are out of luck. Extended hi-res works only on Appels of revision B or later.
Next, annunciator number 3 must be strobed at location $CO5E. Hi-res itself is set up in the normal fashion by turning on graphics at $C050 and enabling hi-res at $CO57. The choice of full screen ($CO52) or mixed graphics and text ($CO53) is still available, though you should do a PR#3 when using mixed mode. Otherwise, the Apple will be in 80-column mode while tryin gto display text in 40-column mode. this is fine if you like a space between each pair of letters, but it doesn't produce a very nice display.
Now that the graphics switches have been set, there are just two more switches needed to set things up. Writing to $COOD enables the 80-column mode. Writing into $COO1 sets up the Apple so bytes can be stored into either main or auxiliary memory. the two switches normally used for controlling the page display are now used to select memory banks. the page 1 switch ($CO54) enables main memory. The page 2 switch ($CO55) enables auxiliary memory. Only memory in the hi-res screen ($2000-$3FFF or 8192 to 16383 decimal) is controlled by these switches.
If you haven't encountered soft switches before, don't let the above barrage of numbers get you down. Switches are just memory locations that turn things on and off. Some are activated with any type of access (either a PEEK or a POKE from Basic or any operation referencing memory from assembly language). Some must be written to (POKE or any assembly language store command) while others must be read (PEEK or any load command).
The extended 80-column card manual covers these switches in great detail. The values given here are in hex. To access the switches from Basic, you must convert these values to decimal. See Listing 4 for an example of this.
Once you have enabled extended hires, you can place values into screen memory and see exactly how the mode works. Try putting values from 1 to 16 into location $2000 (if your monitor doesn't display the top line, drop down a bit to $2100). You'll find that pixels of different colors occupy slightly different positions (this is the 560 resolution), but no colors repeat within any position.
Actually, four of the colors are made up of a single set big (values 1, 2, 4, and 8). These are the purest colors. Pixel patterns using more bits get brighter, tending toward the pastel. Also, when setting up a pattern, you must be careful not to change other bits in the byte, or you will hcange the neighboring pixel. This is not a color conflict as in standard hi-res, since any two colors can be next to each other. It's just another messy detail. The best way to get the hang of all of this is to experiment, which brings us to the sample programs. Using the Programs
Listing 1 is an assembly language program that does all the dirty work. It has two entry points. The first, at $8000, goes to a routine that initializes extended hi-res and clears the screen. It can be accessed with a JSR $8000 from assembly language or a CALL 32768 from Basic. The second routine, accessed with JSR $8003 or CALL 32771, is the plotting (or plodding) code. It requires three parameters: the X coordinate (from 0-139), the Y coordinate (from 0-191 for full screen graphics or 0-159 for mixed mode), and the desired color (from 0-15).
If the color value is greater than 15, the hi nibble is ignored. If the X or Y coordinate is out of range, bad things will happen. From Basic, POKE the X value at 252, the Y value at 253, and the color at 254. In assembly language, use $FC, $FD, and $FE.
For those interested in the exact workings of the plotting program, the comments in the listing give all the details. True bit hackers will probably notice that the routine can be sped up in various ways. Instead of using the divide-by-seven loop, a MOD7 table can be added. Also, instead of shifting the color nibble, a set of seven tables can be added, giving the actual bit pattern for each location.
Listings 2 and 3 are Basic programs that use the plotting routine. The first draws nested squares using all the hi-res colors. While not very useful in itself, it does show what the Apple is capable of and offers an example of how to access the plotting routine. Listing 3 is a simple drawing program. Finally, Listing 4 shows how to enable extended hi-res and clear the screen entirely from Basic. It can be used as a set-up routine for experimentation.
If you plan to do any disk access, make sure to turn on the 80-column card with PRINT ctrl-D;"PR#3" rather than just PR#3, or DOS will become unhooked.
Well, that about covers it. Have fun with the programs.