From: qballlives AT aol DOT com (QBallLives) Newsgroups: comp.os.msdos.djgpp Subject: Re: Multi palettes in Alegro Date: 10 Mar 1998 07:45:20 GMT Lines: 261 Message-ID: <19980310074501.CAA24171@ladder02.news.aol.com> NNTP-Posting-Host: ladder02.news.aol.com Organization: AOL http://www.aol.com References: <199803092349 DOT PAA11509 AT adit DOT ap DOT net> To: djgpp AT delorie DOT com DJ-Gateway: from newsgroup comp.os.msdos.djgpp Precedence: bulk >At 08:30 3/8/1998 GMT, John & Sue Kissell wrote: >> Using a 256 color palette, is it possible to simultaneously use >>different palettes in different parts of the screen in Allegro without >>the flicker produced by set_palette()? I tried a hack using memcpy with >>a temporary palette, but I'm beginning to think that the way a vidieo >>monitor works makes this unlikely, if not impossible, without some sort >>of interrupt routine. Any comments? > >I'm fairly sure you can only have one palette at a time with standard VGA >hardware. To eliminate the flicker, aren't you supposed to use `vsync'? > > vsync will definitely help with the snow that comes from with modifying the palette - but I just learned something that might help Sue out a bit... A friend of mine showed me how to make a "Clut" palette, which I use to "simulate" more colors than are actually available to use... It's opened alot of doors for me, so I hope it opens doors for you as well.. I'll describe it and give code. There are probably several algorithms that come up with a better choice of colors than this. What you do is, you've got your 256 color palette - let's say you want 16 "shades" of those 256 colors int color_table[256][16]; // <= the declaration Make an outer loop where you'll extract the RED, GREEN, and BLUE values from your current palette. I'd suggest extracting those values into floating point variables... but you can get weird sorts of effects using ints too (experiment) Double those values (or triple them, whatever) Calculate the change in intensity of each color by dividing the new values by the # of steps you want to take ex: ri = red/16.0; gi = blue/16.0; bi = blue/16.0; The way this is setup... the lowest intensitys of all colors will be black (or close to black) Now, for an inner loop (yes, there's ANOTHER inner loop too - you should save your clut palette to disk - especially when you want to simulate ALOT of shades!) In this inner loop, you'll loop from 15 to 0 (start with the highest intensity) - extract your floating point RED, GREEN, and BLUE values into ints - and check they're range (between 0 and 63 each) ... You're ready for the innermost loop now: Loop through all 256 colors in the palette, and, using a calculation a friend gave to me, select the "best fit" color to the color you'd like to have. Here's the code: // Here is where we make our enhanced palette... // The limitation in mode13h is having 256 simultaneous colors, and what // making a "clut" palette (which is what the following routine does), is // to try to simulate more colors void Make_Bigger_Palette(void) { rgb_palette a_palette; int index1, index2; float red, green, blue; int send_red, send_green, send_blue; float ri, gi, bi; // increments for colors // first, since I don't have a full palette struct floating around // in memory, I'll load this one with the current palette for (index1=0; index1<256; index1++) Get_Palette_Register(index1, (rgb_color_ptr)&a_palette.colors[index1]); Print_String_Mode_Y(10,10,170,"examining current palette",0); // loop through all colors for (index1=0; index1<256; index1++) { // extract red, green, and blue factors... red=(float)a_palette.colors[index1].red; green=(float)a_palette.colors[index1].green; blue=(float)a_palette.colors[index1].blue; // double the intensities red*=2; green*=2; blue*=2; // get the change in red, green, and blue // making the 16.0 into 32.0 should make the lowest // intensity color the color you started with... ri=red/16.0; gi=green/16.0; bi=blue/16.0; // loop through shades we'd like to have // we'll start with the 16th position of the table being // the highest intensity for(index2=15;index2>=0;index2--) { send_red = red; send_green = green; send_blue = blue; // since 63 would be the maximum if we were // talking the actual color palette... we're just testing // boundaries here if (send_red>63) send_red = 63; if (send_green>63) send_green = 63; if (send_blue>63) send_blue = 63; // call another function to get the color that best fits // a shade we would like color_table[index1][index2]=Get_Best_Fit_Color(send_red,send_ green,send_blue,(rgb_palette_ptr)&a_palette); // decrement red, green, and blue factors red-=ri; green-=gi; blue-=bi; } } // Save the Bigger Palette to the disk so we don't have to wait // for the table to be created next time Save_Bigger_Palette(); } // end Make_Bigger_Palette int Get_Best_Fit_Color(int redy, int greeny, int bluey, rgb_palette_ptr pal) { int i; int red_dist, green_dist, blue_dist; int dist_new, dist_best,color_best; int r, g, b; char ch_buffer[80]; dist_best = 63; // loop through all colors... ::sigh:: again... for(i=0;i<256;i++) { // get the current rgbs for a color r = pal->colors[i].red; g = pal->colors[i].green; b = pal->colors[i].blue; // these "distances" will be used to determine what color // would be the best match, in lieu of the color we'd really // like to have red_dist=redy-r; green_dist=greeny-g; blue_dist=bluey-b; // squaring and adding it all together countermands any // negative signs we might have run into... hopefully // the current palette contains a color that's pretty close... dist_new=red_dist*red_dist+green_dist*green_dist+blue_dist*blue_dist; // is it close? if(dist_new<=dist_best) { sprintf(ch_buffer,"making progress..."); Print_String_Mode_Y(10,20,rand()%255,ch_buffer,0); color_best=i; dist_best=dist_new; } } // send the closest color back to the calling procedure return(color_best); } // end Get_Best_Fit_Color Never mind the Print_String_Mode_Y, that's just a routine I made... It's good to know the thing is working (not locked up), so that's why I use it ; ) Here's a routine to show that new bigger palette: void Show_Bigger_Palette(void) { // this routine shows the real palette on a single line, // and then shows our enhanced palette int index1,index2,offset; Print_String_Mode_Y(10,50,170,"Special thanks to Dhonn Lushine",0); Print_String_Mode_Y(10,60,170,"(dhonn AT usa DOT net) for his help...",0); Print_String_Mode_Y(10,80,170,"original palette",0); for (index1=0; index1<256; index1++) { outportb(SEQUENCER, SEQ_PLANE_ENABLE); outportb(SEQUENCER+1, (0x01<<(index1 & 0x03) ) ); video_buffer[(100<<6) + (100<<4) + (index1>>2)] = (unsigned char)index1; } Print_String_Mode_Y(10,110,170,"bigger palette",0); for (index1=0; index1<256; index1++) { outportb(SEQUENCER, SEQ_PLANE_ENABLE); outportb(SEQUENCER+1, (0x01<<(index1 & 0x03) ) ); video_buffer[(100<<6) + (100<<4) + (index1>>2)] = (unsigned char)index1; for (index2=0; index2<16; index2++) { offset = index2 + 130; video_buffer[(offset<<6) + (offset<<4) + (index1>>2)] = (unsigned char)color_table[index1][index2]; } } } // end Show_Bigger_Palette I hope this helps you... It opens the door to textured polys (w/ flat shading!), more "colors" for fake phong effects, gouraud... this is good! Have a good one! Jim the loiterer aloiterer AT juno DOT com http://www.fortunecity.com/skyscraper/gigahertz/179/index.html