______________________________________________________________________________ | SECTION 1 PART A SUBPART 3 | Palette Coding | ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ***Palettes in Qbasic*** Introduction: This is a new series from Joe Lawrence. Part A is in this issue of the fanzine. Part B is for next issue. Take it away Joe! Table of Contents ----------------------------------------------------------------------------- Part A - Documentation 1.) Introduction, Screen Modes 2.) The PALETTE Function 3.) Using Ports to optimize palette functions Part B - Building Palette routines 1.) Introduction to Palette routines 2.) PalRGBSet() 3.) PalGradient() 4.) PalSave() 5.) PalLoad() 6.) PalRestore() 7.) PalBrighten() 8.) PalDarken() 9.) PalRGBPower() 10.) PalRotate() 11.) PalMorph() 12.) PalFade() ----------------------------------------------------------------------------- * Part A, Subject One Introduction, Screen Modes ----------------------------------------------------------------------------- Now for a little introduction. Hi I'm Joe Lawrence, webfreak residing at http://www.geocities.com/SiliconValley/Park/2323/, and of course, Qbasic programmer. My homepage features QBasic programming content, so stop by sometime. All e-mail can be slung towards lawrencej@ufrsd.k12.nj.us Enough about me, let's get going... As you most likely know, there are numerous screen modes which to work with in Qbasic. Most popular are: screen 7 & 9, both boasting multiple video pages, screen 12, featuring 640x480 sharp resolution, and my favorite, screen 13 with 256 colors. Although 307200 pixels sound tempting, we'll be using screen 13, since we're focusing on colors, not resolution. ----------------------------------------------------------------------------- * Part A, Subject Two The PALETTE Function ----------------------------------------------------------------------------- Okay, now we get into the coding bit. I assume you have decent knowledge of graphic functions, like line, circle, etc. You'll also have to be capable of VGA graphics, which most people know have. (If you're not sure, try anyway.) Okay, here's an example of the PALETTE function... SCREEN 13 PALETTE 15, 63 PRINT "The text is now red!" SLEEP SCREEN 0: SYSTEM Let's break the program down. First we change to screen 13, 320x200x256. Then we change color 15's value to 63. See the palette is an array of colors. Color 1 has a value, blue, Color 2 has another, etc. (Don't worry about where I got 63 from, I'll explain it in a minute...) After we changed the color, we printed something out, waited for a key- press, then reset the video mode and quit. Now let's breakdown the palette statement... PALETTE color, value The first argument, color, is which color to change. In the example I changed color 15, which is normally white. Value, the second argument, is the new color we'd like to see in place of argument one (color). The formula, is this: value = 65536 * Blue + 256 * Green + Red The blue, green, and red variables are the measure of blue, green, and red hue in the new color. Possible values for the hues range from 0 to 63, where 0 is none and 63 is full. For example, if I wanted to change color 15 from white to purple, here's what I would do... SCREEN 13 Blue = 63: Red = 63: Green = 0 value = 65536 * Blue + 256 * Green + Red PALETTE 15, value PRINT "Color 15 is now purple!" SLEEP SCREEN 0: SYSTEM Neat tricks can be done with the PALETTE function, try this example on for size... (Note, you may have to change the delay. For reference, 1000 works good on a Pentium 100.) SCREEN 13 PRINT "Color 15 is in flux!" DO FOR Blue = 63 to 0 step -1 value = 65536 * Blue + 256 * Green + Red PALETTE 15, value For Delay = 1 to 1000: NEXT NEXT FOR Red = 63 to 0 step -1 value = 65536 * Blue + 256 * Green + Red PALETTE 15, value For Delay = 1 to 1000: NEXT NEXT FOR Green = 63 to 0 step -1 value = 65536 * Blue + 256 * Green + Red PALETTE 15, value For Delay = 1 to 1000: NEXT NEXT LOOP UNTIL INKEY$ <> "" SLEEP SCREEN 0: SYSTEM By simply decreasing each hue by one, then changing the color, we get a nice, smooth fading effect. In conclusion, although I've only changed text, and color 15, you can certainly play around with changing graphics and other colors. (Remember though, that the PALETTE statement changes a colors RGB value even if it is already plotted.) ----------------------------------------------------------------------------- * Part A, Subject 3 Three Using Ports to optimize palette functions ----------------------------------------------------------------------------- The PALETTE function is sufficient enough to handle a color here, a color there, etc. If you plan to do any significant color manipulation, however, PALETTE is simply not going to cut it. So we do instead of letting Qbasic do the work for us, we'll do it ourselves by accessing the VGA card directly, creating much needed speed. Although using the ports take an extra step or two, the results out weigh your time. For a taste, try this program on for size. SCREEN 13 StartTime = TIMER LOCATE 1, 1: PRINT "PALETTE Time: " FOR N = 1 TO 10000 value = 65536 * INT(RND * 63) + 256 * INT(RND * 63) + INT(RND * 63) PALETTE 15, value LOCATE 1, 15: PRINT USING "##.##"; TIMER - StartTime NEXT StartTime = TIMER LOCATE 2, 1: PRINT "Port Time: " FOR N = 1 TO 10000 OUT &H3C8, 15 OUT &H3C9, INT(RND * 63) OUT &H3C9, INT(RND * 63) OUT &H3C9, INT(RND * 63) LOCATE 2, 15: PRINT USING "##.##"; TIMER - StartTime NEXT This program changes the values of 10000 colors, first with PALETTE, then with the ports. Although the time difference may seem insignificant, when using fading effects, time racks up. Okay, now how do these port things work, you ask? Simple. The syntax for porting is simply OUT port, data. In this case, we use hexadecimal &H3C8 to tell the VGA card to prepare this color for RGB data. Then we use &H3C9 to change that color's RGB values. Remember, though to always change them in this order: Red, Green, then Blue. Now what if you'd like to get a color's RGB values? Simply use var = INP (&H3C9) . Here's an example... SCREEN 13 ' Change color zero to purple OUT &H3C8, 0 ' Point to color OUT &H3C9, 63 ' Send RGB values OUT &H3C9, 0 OUT &H3C9, 63 ' Read color zero's Red, Green, and Blue values OUT &H3C8, 0 ' Point to color red = INP (&H3C9) ' Get RGB values green = INP (&H3C9) blue = INP (&H3C9) ' Print out the values PRINT "Red: "; red; " Green: "; green; " Blue: "; blue END All this short program does is change color 0, the background, to bright purple. Then it goes and "asks" the VGA card what color 0's RGB values are. In this case, bright purple consists of 63 red and 63 blue. (Remember their are only 63 hues, so 63 would equal 100%.) Here's a little VGA quirk discovered by the authors of Tricks of the Game Programming Gurus... "I found a little problem with the VGA card in reading a palette register. It seems that the register you request is not the one you get all the time. This bug is hardware-specific and manifests itself on some VGA cards. For no, my solution is to read each color register twice. That seems to fix it..." -------------------------------------------------------- * EDITOR'S NOTE: * This article was originally printed in Peter Cooper's BASIX Fanzine, * Issue #6 from August 1996.