/** ** ram4.c ---- the 16 color RAM frame driver ** ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221 ** [e-mail: csaba@vuse.vanderbilt.edu]. ** ** This file is part of the GRX graphics library. ** ** The GRX graphics library is free software; you can redistribute it ** and/or modify it under some conditions; see the "copying.grx" file ** for details. ** ** This library 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. ** **/ #include "libgrx.h" #include "grdriver.h" #include "arith.h" #include "memcopy.h" #include "memfill.h" #include "fdrivers/rblit_14.h" /* frame offset address calculation */ #define FOFS(x,y,lo) ( umul32((y),(int)(lo)) + ((x)>>3) ) static INLINE GrColor readpixel(GrFrame *c,int x,int y) { GR_int32u offs; unsigned mask; GrColor pix; GRX_ENTER(); offs = FOFS(x,y,c->gf_lineoffset); mask = 0x80 >> (x &= 7); pix = (GrColor)( (((c->gf_baseaddr[0][offs] & mask) ) | ((c->gf_baseaddr[1][offs] & mask) << 1) | ((c->gf_baseaddr[2][offs] & mask) << 2) | ((c->gf_baseaddr[3][offs] & mask) << 3) ) >> (7 - x) ); GRX_RETURN(pix); } static INLINE void drawpixel(int x,int y,GrColor color) { GR_int32u offs; unsigned int mask; unsigned int cval; int op; GRX_ENTER(); offs = FOFS(x,y,CURC->gc_lineoffset); mask = 0x80 >> (x &= 7); cval = (unsigned int)color << (7 - x); switch(op = C_OPER(color) & 3) { case C_WRITE: case C_AND: CURC->gc_baseaddr[0][offs] &= ((cval ) | ~mask); CURC->gc_baseaddr[1][offs] &= ((cval >> 1) | ~mask); CURC->gc_baseaddr[2][offs] &= ((cval >> 2) | ~mask); CURC->gc_baseaddr[3][offs] &= ((cval >> 3) | ~mask); if(op != C_WRITE) break; case C_OR: CURC->gc_baseaddr[0][offs] |= ((cval ) & mask); CURC->gc_baseaddr[1][offs] |= ((cval >> 1) & mask); CURC->gc_baseaddr[2][offs] |= ((cval >> 2) & mask); CURC->gc_baseaddr[3][offs] |= ((cval >> 3) & mask); break; default: CURC->gc_baseaddr[0][offs] ^= ((cval ) & mask); CURC->gc_baseaddr[1][offs] ^= ((cval >> 1) & mask); CURC->gc_baseaddr[2][offs] ^= ((cval >> 2) & mask); CURC->gc_baseaddr[3][offs] ^= ((cval >> 3) & mask); break; } GRX_LEAVE(); } #define maskoper(d,op,s,msk) do { \ unsigned char _c_ = peek_b(d); \ poke_b((d),(_c_ & ~(msk)) | ((_c_ op (s)) & (msk)) ); \ } while (0) #define maskset(d,c,msk) \ poke_b((d),(peek_b(d) & ~(msk)) | ((c) & (msk))) static void drawhline(int x,int y,int w,GrColor color) { int oper, cval, wd, pl; GR_int32u DO; GR_int8u lm, rm; GRX_ENTER(); oper = C_OPER(color); cval = (int)color; DO = FOFS(x,y,CURC->gc_lineoffset); lm = 0xff >> (x & 7); rm = 0xff << ((-(w + x)) & 7); wd = ((x+w+7) >> 3) - (x >> 3); if (wd == 1) lm &= rm; for (pl = 0; pl < 4; ++pl) { GR_int32u cv = cval & 1 ? ~0L : 0L; cval >>= 1; if (!( !cv && (oper==C_OR||oper==C_XOR)) && !(cv && oper==C_AND) ) { GR_int8u *dptr = (GR_int8u *)&CURC->gc_baseaddr[pl][DO]; int ww = wd; if ( ((GR_int8u)(~lm)) ) { switch(oper) { case C_XOR: maskoper(dptr,^,(GR_int8u)cv,lm); break; case C_OR: maskoper(dptr,|,(GR_int8u)cv,lm); break; case C_AND: maskoper(dptr,&,(GR_int8u)cv,lm); break; default: maskset(dptr,(GR_int8u)cv,lm); break; } if (!(--ww)) continue; ++dptr; } if ( ((GR_int8u)(~rm)) ) --ww; if (ww) { switch(oper) { case C_XOR: repfill_b_xor(dptr,cv,ww); break; case C_OR: repfill_b_or( dptr,cv,ww); break; case C_AND: repfill_b_and(dptr,cv,ww); break; default: repfill_b( dptr,cv,ww); break; } } if ( ((GR_int8u)(~rm)) ) { switch(oper) { case C_XOR: maskoper(dptr,^,(GR_int8u)cv,rm); break; case C_OR: maskoper(dptr,|,(GR_int8u)cv,rm); break; case C_AND: maskoper(dptr,&,(GR_int8u)cv,rm); break; default: maskset(dptr,(GR_int8u)cv,rm); break; } } } } GRX_LEAVE(); } #undef maskoper static void drawvline(int x,int y,int h,GrColor color) { unsigned int lwdt, mask, oper, hh; char *p; GR_int32u offs; GRX_ENTER(); oper = C_OPER(color); lwdt = CURC->gc_lineoffset; offs = FOFS(x,y,lwdt); mask = 0x80 >> (x & 7); switch (oper) { case C_XOR: /* no need to xor anything with 0 */ if (color&1) { p = &CURC->gc_baseaddr[0][offs]; hh = h; colfill_b_xor(p,lwdt,mask,hh); } if (color&2) { p = &CURC->gc_baseaddr[1][offs]; hh = h; colfill_b_xor(p,lwdt,mask,hh); } if (color&4) { p = &CURC->gc_baseaddr[2][offs]; hh = h; colfill_b_xor(p,lwdt,mask,hh); } if (color&8) { p = &CURC->gc_baseaddr[3][offs]; colfill_b_xor(p,lwdt,mask,h); } break; case C_OR: /* no need to or anything with 0 */ if (color&1) { p = &CURC->gc_baseaddr[0][offs]; hh = h; colfill_b_or(p,lwdt,mask,hh); } if (color&2) { p = &CURC->gc_baseaddr[1][offs]; hh = h; colfill_b_or(p,lwdt,mask,hh); } if (color&4) { p = &CURC->gc_baseaddr[2][offs]; hh = h; colfill_b_or(p,lwdt,mask,hh); } if (color&8) { p = &CURC->gc_baseaddr[3][offs]; colfill_b_or(p,lwdt,mask,h); } break; case C_AND: /* no need to and anything with 1 */ mask = ~mask; /* set up reset mask */ if (!(color&1)) { p = &CURC->gc_baseaddr[0][offs]; hh = h; colfill_b_and(p,lwdt,mask,hh); } if (!(color&2)) { p = &CURC->gc_baseaddr[1][offs]; hh = h; colfill_b_and(p,lwdt,mask,hh); } if (!(color&4)) { p = &CURC->gc_baseaddr[2][offs]; hh = h; colfill_b_and(p,lwdt,mask,hh); } if (!(color&8)) { p = &CURC->gc_baseaddr[3][offs]; colfill_b_and(p,lwdt,mask,h); } break; default: { p = &CURC->gc_baseaddr[0][offs]; hh = h; if (color&1) colfill_b_or(p,lwdt,mask,hh); else colfill_b_and(p,lwdt,~mask,hh); p = &CURC->gc_baseaddr[1][offs]; hh = h; if (color&2) colfill_b_or(p,lwdt,mask,hh); else colfill_b_and(p,lwdt,~mask,hh); p = &CURC->gc_baseaddr[2][offs]; hh = h; if (color&4) colfill_b_or(p,lwdt,mask,hh); else colfill_b_and(p,lwdt,~mask,hh); p = &CURC->gc_baseaddr[3][offs]; if (color&8) colfill_b_or(p,lwdt,mask,h); else colfill_b_and(p,lwdt,~mask,h); break; } } GRX_LEAVE(); } static #include "fdrivers/generic/block.c" static #include "fdrivers/generic/line.c" static #include "fdrivers/generic/bitmap.c" static #include "fdrivers/generic/pattern.c" static #include "fdrivers/generic/bitblt.c" static void bltr2r(GrFrame *dst,int dx,int dy, GrFrame *src,int x,int y,int w,int h, GrColor op) { GRX_ENTER(); _GR_rblit_14(dst,dx,dy,src,x,y,w,h,op,4,bitblt); GRX_LEAVE(); } GrFrameDriver _GrFrameDriverRAM4 = { GR_frameRAM4, /* frame mode */ GR_frameUndef, /* compatible RAM frame mode */ FALSE, /* onscreen */ 4, /* scan line width alignment */ 4, /* number of planes */ 4, /* bits per pixel */ 16*1024L*1024L, /* max plane size the code can handle */ NULL, readpixel, drawpixel, drawline, drawhline, drawvline, drawblock, drawbitmap, drawpattern, bltr2r, NULL, NULL, _GrFrDrvGenericGetIndexedScanline, _GrFrDrvGenericPutScanline };