-=[ MAXCOLOR Copyright 1988 Jason Harper CompuServe 76703,4222 ]=- PURPOSE: To display the absolute maximum number of simultaneous onscreen colors that the Apple IIgs SuperHiRes graphics modes can handle: 3200. SYSTEM REQUIREMENTS: Apple IIgs, 256K memory, must be running at fast speed. Will not work properly if a desk accessory or other program is currently using an interrupt-driven background task (such as Alternate Display Mode). USAGE: Run from the Launcher or Finder or anything else that is capable of running ProDOS 16 programs. This program is slightly dangerous, so use it at your own risk if you have any important files on a RAMdisk that haven't been backed up. You should get a screen with 3200 colors used (count 'em): if there is any flicker, there is interference from another program or desk accessory. At this point you can press the Escape key to exit the program, or the space bar to toggle to/from another screen with a different set of 3200 colors. Between the two screens, all of the IIgs's 4096 displayable colors are used. WHAT'S GOING ON HERE: Colors on the IIgs are specified in terms of their red, green, and blue components. Each component has 16 possible values ranging from 0 (0% of this component) to 15 (100% of this component), for a total of 16 x 16 x 16 = 4096 distinct colors. Any one horizontal line of pixels can use at most 16 colors (the entire palette for the line is read during horizontal retrace, so it's impossible to change palettes in mid-line), so on the 200-pixel high screen at most 16 x 200 = 3200 colors can be displayed. However, only 16 separate palettes of 16 colors each (= 256 colors total) are available, so the program has to contantly modify the 16 palettes. Just changing the red component in all 16 colors of each palette every 16 scanlines takes about 90% of the processor time, so this technique doesn't have much practical use. WHAT YOU'RE SEEING: The display generated by this program is divided horizontally into 16 bands, 20 pixels wide each. All pixels in each band have the same blue component, ranging from 0 in the leftmost band to 15 in the rightmost. Vertically, each group of 16 scanlines ranges from 0 to 15 in the green component. Thus a rectangular area as wide as the screen and 16 pixels high contains all 256 permutations of green and blue components. Twelve and a half such regions completely fill the screen, each one having a distinct red component. On the initial screen, the red component ranges from 0 in the top region to 12 in the bottom (half-size) region. The alternate screen, accessed by pressing the space bar, has red components ranging from 15 down to 3. The total number of distinct colors is 16 (blues) x 16 (greens) x 12.5 (reds) = 3200. HOW IT'S DONE: With scanline interrupts, 26 of them per frame (1/60 second), set for every 8th scanline plus the very last scanline. Only one scanline at a time has the interrupt bit set in its SCB (Scanline Control Byte): the interrupt handler clears the bit in the SCB of the current line, and sets it in the next line that an interrupt is scheduled for. Each interrupt causes the red component of half of the color entries (16 colors in 8 palettes) to be changed. The even-numbered interrupts (occurring on line 0 out of each group of 16) change the colors for the bottom 8, and the odd interrupts (occurring on line 8 out of each 16) change the top 8: thus there is no chance of a palette being modified before it is needed, unless something delays the handling of the interrupt long enough that it overlaps the following interrupt. Modifying 128 color palette entries within the half millisecond it takes to display 8 scanlines of video was rather challenging. I chose red as the color component to vary with interrupts because it is represented in memory in a separate byte from the green and blue components: I can therefore accomplish the change by storing a single value (0-15) in every other byte of the appropriate part of the color palette area ($E1/9E00-9FFF). There simply isn't enough time to do this with any sort of loop or indexing: I have to use 128 'STA absolute' instructions, with the data bank register set to $E1. There are two sets of 128 such instructions, one for the top and one for the bottom half of the color palettes. Even then, the IIgs's interrupt handling mechanism takes too long to recognize that a scanline interrupt has occurred and to dispatch to my routine, causing the screen to flicker wildly (although I should point out that the interrupt dispatcher has to handle numerous IRQ sources: some of them are simply going to have more latency than others). So instead of hooking into the scanline IRQ vector, my routine hooks into the system IRQ handler vector (therefore getting control within a dozen cycles of the interrupt), and passes any non-scanline interrupts to the original handler: not quite by-the-book, but there wasn't much choice.