home *** CD-ROM | disk | FTP | other *** search
- /**
- ** COLORS.C
- **
- ** Copyright (C) 1992, Csaba Biegl
- ** 820 Stirrup Dr, Nashville, TN, 37221
- ** csaba@vuse.vanderbilt.edu
- **
- ** This file is distributed under the terms listed in the document
- ** "copying.cb", available from the author at the address above.
- ** A copy of "copying.cb" should accompany this file; if not, a copy
- ** should be available from where this file was obtained. This file
- ** may not be distributed without a verbatim copy of "copying.cb".
- ** You should also have received a copy of the GNU General Public
- ** License along with this program (it is in the file "copying");
- ** if not, write to the Free Software Foundation, Inc., 675 Mass Ave,
- ** Cambridge, MA 02139, USA.
- **
- ** This program is distributed in the hope that it will be useful,
- ** but WITHOUT ANY WARRANTY; without even the implied warranty of
- ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- ** GNU General Public License for more details.
- **/
-
- #include "grx.h"
- #include "libgrx.h"
- #include "interrup.h"
- #include "gmalloc.h"
- #include "reg8514a.h"
-
- #include <string.h>
- #include <stdlib.h>
-
-
- typedef struct {
- unsigned int n:6;
- unsigned int state:2; /* 0=free, 1=shared, 2=writable */
- unsigned char r;
- unsigned char g;
- unsigned char b;
- } color;
-
- #define C_FREE 0 /* free color */
- #define C_SHARED 1 /* shared (by GrAllocColor) */
- #define C_WRITABLE 2 /* writable (by GrAllocCell) */
-
- #define KEEPBITS(v,n) \
- v = ((v += (0x80 >> n)) > 0xff) ? \
- (0xff ^ (0xff >> n)) : \
- (v & (0xff ^ (0xff >> n)))
-
-
- static color *colortable = NULL; /* color info table */
- static int maxused; /* max used index in table */
- static int freecolors; /* number of free colors */
- static int whitecolor; /* index of white color */
- static int RGBmode; /* set when in RGB mode */
- static int lastcolors = -1; /* # of colors last initted to */
-
- #define init_done() (lastcolors == _GrNumColors)
-
- static void setcolor(int c,int r,int g,int b)
- {
- REGISTERS regs;
-
- switch(_GrAdapterType) {
- case GR_EGA:
- regs.r_ax = 0x1000;
- regs.r_bx = c & 0x0f;
- regs.r_bx |= ((r & 0x40) << 7) | ((r & 0x80) << 3);
- regs.r_bx |= ((g & 0x40) << 6) | ((g & 0x80) << 2);
- regs.r_bx |= ((b & 0x40) << 5) | ((b & 0x80) << 1);
- int10(®s);
- break;
- case GR_VGA:
- case GR_S3:
- if(_GrNumColors == 16) {
- regs.r_ax = 0x1000;
- regs.r_bx = (c & 0x0f) | ((c & 0x0f) << 8);
- int10(®s);
- }
- #ifdef __GNUC__
- asm volatile(
- "cli \n"
- "movl %0,%%eax \n"
- "movl $0x3c8,%%edx \n"
- "outb %%al,%%dx \n"
- "inb $0x80,%%al \n"
- "incl %%edx \n"
- "movl %1,%%eax \n"
- "shrb $2,%%al \n"
- "outb %%al,%%dx \n"
- "inb $0x80,%%al \n"
- "movl %2,%%eax \n"
- "shrb $2,%%al \n"
- "outb %%al,%%dx \n"
- "inb $0x80,%%al \n"
- "movl %3,%%eax \n"
- "shrb $2,%%al \n"
- "outb %%al,%%dx \n"
- "sti \n"
- : /* NOTHING */
- : "g" (c), "g" (r), "g" (g), "g" (b)
- : "ax", "dx"
- );
- #elif defined(__TURBOC__)
- disable();
- outportb(0x3c8,c);
- inportb(0x80);
- outportb(0x3c9,(r >> 2));
- inportb(0x80);
- outportb(0x3c9,(g >> 2));
- inportb(0x80);
- outportb(0x3c9,(b >> 2));
- enable();
- #else
- regs.r_ax = 0x1010;
- regs.r_bx = c & 0xff;
- regs.r_dx = ((r & 0xfc) << 6);
- regs.r_cx = ((g & 0xfc) << 6) | ((b & 0xfc) >> 2);
- int10(®s);
- #endif
- break;
- case GR_8514A:
- WaitQueue(4);
- outp(DAC_W_INDEX,c);
- outp(DAC_DATA,(r >> 2));
- outp(DAC_DATA,(g >> 2));
- outp(DAC_DATA,(b >> 2));
- break;
- }
- colortable[c].r = r;
- colortable[c].g = g;
- colortable[c].b = b;
- }
-
- static int initcolors(void)
- {
- int whitevalue;
-
- if((_GrCurrentMode >= GR_320_200_graphics) && !init_done()) {
- switch(_GrNumColors) {
- #if (GRXPLANES & 16)
- case 32768:
- #endif
- case 2:
- whitecolor = _GrNumColors - 1;
- freecolors = 0;
- RGBmode = TRUE;
- maxused = 0;
- break;
- case 256:
- case 16:
- whitecolor = 15;
- whitevalue = (_GrAdapterType == GR_EGA) ? 0xc0 : 0xfc;
- if((_GrNumColors > lastcolors) && (colortable != NULL)) {
- _GrFree(colortable);
- colortable = NULL;
- }
- if(colortable == NULL) {
- colortable = _GrMalloc(sizeof(color) * _GrNumColors);
- if(colortable == NULL) return(FALSE);
- }
- memset(colortable,0,(sizeof(color) * _GrNumColors));
- colortable[0].state = C_SHARED;
- setcolor(0,0,0,0);
- colortable[whitecolor].state = C_SHARED;
- setcolor(whitecolor,whitevalue,whitevalue,whitevalue);
- freecolors = _GrNumColors - 2;
- maxused = whitecolor + 1;
- RGBmode = FALSE;
- break;
- }
- lastcolors = _GrNumColors;
- }
- return(init_done() ? TRUE : FALSE);
- }
-
- void GrResetColors(void)
- {
- lastcolors = (lastcolors >= _GrNumColors) ? (_GrNumColors + 1) : (-1);
- initcolors();
- }
-
- void GrRefreshColors(void)
- {
- color *c;
- int n;
-
- if(lastcolors != _GrNumColors)
- initcolors();
- else for(n = 0,c = colortable; n < maxused; n++,c++)
- if(c->state != C_FREE) setcolor(n,c->r,c->g,c->b);
- }
-
- void GrSetRGBcolorMode(void)
- {
- color *c;
- int n;
-
- if((init_done() || initcolors()) && !RGBmode &&
- ((_GrAdapterType == GR_VGA) ||
- (_GrAdapterType == GR_8514A) ||
- (_GrAdapterType == GR_S3)) &&
- (_GrNumColors == 256)) {
- for(n = 0,c = colortable; n < 256; n++,c++) {
- c->state = C_SHARED;
- c->n = 1;
- setcolor(n,(n & 0xe0),((n << 3) & 0xe0),((n << 6) & 0xc0));
- }
- freecolors = 0;
- whitecolor = 255;
- RGBmode = TRUE;
- maxused = 256;
- }
- }
-
- int GrNumColors(void)
- {
- return(_GrNumColors);
- }
-
- int GrNumFreeColors(void)
- {
- if(!init_done()) initcolors();
- return(freecolors);
- }
-
- int GrWhite(void)
- {
- return((init_done() || initcolors()) ? whitecolor : GrNOCOLOR);
- }
-
- int GrBlack(void)
- {
- return((init_done() || initcolors()) ? 0 : GrNOCOLOR);
- }
-
- int GrAllocColor(int r,int g,int b)
- {
- color *c;
- int err,minerr;
- int n,free = (-1);
-
- if(!init_done() && !initcolors()) return(GrNOCOLOR);
- if(RGBmode) switch(_GrNumColors) {
- #if (GRXPLANES & 16)
- case 32768:
- KEEPBITS(r,5);
- KEEPBITS(g,5);
- KEEPBITS(b,5);
- return((r << 7) | (g << 2) | (b >> 3));
- #endif
- case 256:
- KEEPBITS(r,3);
- KEEPBITS(g,3);
- KEEPBITS(b,2);
- return(r | (g >> 3) | (b >> 6));
- case 2:
- return(((r*30 + g*59 + b*11) >= 128*100) ? 1 : 0);
- default:
- return(GrNOCOLOR);
- }
- switch(_GrAdapterType) {
- case GR_EGA:
- KEEPBITS(r,2);
- KEEPBITS(g,2);
- KEEPBITS(b,2);
- break;
- case GR_VGA:
- case GR_8514A:
- case GR_S3:
- KEEPBITS(r,6);
- KEEPBITS(g,6);
- KEEPBITS(b,6);
- break;
- default:
- return(GrNOCOLOR);
- }
- for(n = 0,c = colortable; n < maxused; n++,c++) {
- switch(c->state) {
- case C_SHARED:
- if((c->r != r) || (c->g != g) || (c->b != b)) break;
- c->n++;
- return(n);
- case C_FREE:
- free = n;
- break;
- }
- }
- if((free < 0) && (maxused < _GrNumColors))
- free = maxused++;
- if(free >= 0) {
- colortable[free].state = C_SHARED;
- colortable[free].n = 1;
- setcolor(free,r,g,b);
- freecolors--;
- return(free);
- }
- minerr = 3*32*32;
- for(n = 0,c = colortable; n < _GrNumColors; n++,c++) {
- if(c->state == C_SHARED) {
- err = ((c->r - r) >> 2) * (c->r - r) +
- ((c->g - g) >> 2) * (c->g - g) +
- ((c->b - b) >> 2) * (c->b - b);
- if(err <= minerr) {
- minerr = err;
- free = n;
- }
- }
- }
- if(free >= 0) {
- colortable[free].n++;
- return(free);
- }
- return(GrNOCOLOR);
- }
-
- int GrAllocCell(void)
- {
- int n,free = (-1);
-
- if((init_done() || initcolors()) && !RGBmode && (freecolors > 0)) {
- for(n = 0; n < maxused; n++) {
- if(colortable[n].state == C_FREE) {
- free = n;
- break;
- }
- }
- if(free < 0) free = maxused++;
- colortable[free].state = C_WRITABLE;
- colortable[free].n = 1;
- freecolors--;
- return(free);
- }
- return(GrNOCOLOR);
- }
-
- void GrFreeColor(int n)
- {
- color *c;
-
- if(init_done() && !RGBmode &&
- ((unsigned)n < (unsigned)_GrNumColors) &&
- ((c = &colortable[n])->state != C_FREE)) {
- if(c->n > 0) c->n--;
- if(c->n == 0) c->state = C_FREE;
- }
- }
-
- void GrSetColor(int n,int r,int g,int b)
- {
- color *c;
-
- if((init_done() || initcolors()) && !RGBmode &&
- ((unsigned)n < (unsigned)_GrNumColors)) {
- c = &colortable[n];
- switch(c->state) {
- case C_SHARED:
- if(c->n > 0) return;
- break;
- case C_FREE:
- if(n >= maxused) maxused = n + 1;
- freecolors--;
- break;
- }
- c->state = C_WRITABLE;
- c->n = 1;
- switch(_GrAdapterType) {
- case GR_EGA:
- KEEPBITS(r,2);
- KEEPBITS(g,2);
- KEEPBITS(b,2);
- break;
- case GR_VGA:
- KEEPBITS(r,6);
- KEEPBITS(g,6);
- KEEPBITS(b,6);
- break;
- }
- setcolor(n,r,g,b);
- }
- }
-
- void GrQueryColor(int n,int *r,int *g,int *b)
- {
- color *c;
-
- if(init_done() && ((unsigned)n < (unsigned)_GrNumColors)) {
- if(colortable == NULL) switch(_GrNumColors) {
- #if (GRXPLANES & 16)
- case 32768:
- *r = (n >> 7) & 0xf8;
- *g = (n >> 2) & 0xf8;
- *b = (n << 3) & 0xf8;
- return;
- #endif
- case 2:
- *r = *g = *b = (n ? 255 : 0);
- return;
- default:
- *r = *g = *b = 0;
- return;
- }
- c = &colortable[n];
- *r = c->r;
- *g = c->g;
- *b = c->b;
- }
- }
-