1 /**
2  ** ram4.c ---- the 16 color RAM frame driver
3  **
4  ** Copyright (c) 1995 Csaba Biegl, 820 Stirrup Dr, Nashville, TN 37221
5  ** [e-mail: csaba@vuse.vanderbilt.edu].
6  **
7  ** This file is part of the GRX graphics library.
8  **
9  ** The GRX graphics library is free software; you can redistribute it
10  ** and/or modify it under some conditions; see the "copying.grx" file
11  ** for details.
12  **
13  ** This library is distributed in the hope that it will be useful,
14  ** but WITHOUT ANY WARRANTY; without even the implied warranty of
15  ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16  **
17  **/
18 
19 #include "libgrx.h"
20 #include "grdriver.h"
21 #include "arith.h"
22 #include "memcopy.h"
23 #include "memfill.h"
24 
25 #include "fdrivers/rblit_14.h"
26 
27 /* frame offset address calculation */
28 #define FOFS(x,y,lo) ( umul32((y),(int)(lo)) + ((x)>>3) )
29 
30 
31 static INLINE
readpixel(GrFrame * c,int x,int y)32 GrColor readpixel(GrFrame *c,int x,int y)
33 {
34 	GR_int32u offs;
35 	unsigned mask;
36 	GrColor pix;
37 	GRX_ENTER();
38 	offs = FOFS(x,y,c->gf_lineoffset);
39 	mask = 0x80 >> (x &= 7);
40 	pix = (GrColor)(
41 	    (((c->gf_baseaddr[0][offs] & mask)     ) |
42 	     ((c->gf_baseaddr[1][offs] & mask) << 1) |
43 	     ((c->gf_baseaddr[2][offs] & mask) << 2) |
44 	     ((c->gf_baseaddr[3][offs] & mask) << 3)
45 	    ) >> (7 - x)
46 	);
47 	GRX_RETURN(pix);
48 }
49 
50 static INLINE
drawpixel(int x,int y,GrColor color)51 void drawpixel(int x,int y,GrColor color)
52 {
53 	GR_int32u offs;
54 	unsigned int mask;
55 	unsigned int cval;
56 	int  op;
57 	GRX_ENTER();
58 	offs = FOFS(x,y,CURC->gc_lineoffset);
59 	mask = 0x80 >> (x &= 7);
60 	cval = (unsigned int)color << (7 - x);
61         switch(op = C_OPER(color) & 3) {
62 	  case C_WRITE:
63 	  case C_AND:
64 	    CURC->gc_baseaddr[0][offs] &= ((cval     ) | ~mask);
65 	    CURC->gc_baseaddr[1][offs] &= ((cval >> 1) | ~mask);
66 	    CURC->gc_baseaddr[2][offs] &= ((cval >> 2) | ~mask);
67 	    CURC->gc_baseaddr[3][offs] &= ((cval >> 3) | ~mask);
68 	    if(op != C_WRITE) break;
69 	  case C_OR:
70 	    CURC->gc_baseaddr[0][offs] |= ((cval     ) & mask);
71 	    CURC->gc_baseaddr[1][offs] |= ((cval >> 1) & mask);
72 	    CURC->gc_baseaddr[2][offs] |= ((cval >> 2) & mask);
73 	    CURC->gc_baseaddr[3][offs] |= ((cval >> 3) & mask);
74 	    break;
75 	  default:
76 	    CURC->gc_baseaddr[0][offs] ^= ((cval     ) & mask);
77 	    CURC->gc_baseaddr[1][offs] ^= ((cval >> 1) & mask);
78 	    CURC->gc_baseaddr[2][offs] ^= ((cval >> 2) & mask);
79 	    CURC->gc_baseaddr[3][offs] ^= ((cval >> 3) & mask);
80 	    break;
81 	}
82 	GRX_LEAVE();
83 }
84 
85 #define maskoper(d,op,s,msk) do {                        \
86   unsigned char _c_ = peek_b(d);                         \
87   poke_b((d),(_c_ & ~(msk)) | ((_c_ op (s)) & (msk)) );  \
88 } while (0)
89 #define maskset(d,c,msk) \
90     poke_b((d),(peek_b(d) & ~(msk)) | ((c) & (msk)))
91 
drawhline(int x,int y,int w,GrColor color)92 static void drawhline(int x,int y,int w,GrColor color) {
93   int oper, cval, wd, pl;
94   GR_int32u DO;
95   GR_int8u  lm, rm;
96   GRX_ENTER();
97   oper = C_OPER(color);
98   cval = (int)color;
99   DO   = FOFS(x,y,CURC->gc_lineoffset);
100   lm   = 0xff >> (x & 7);
101   rm   = 0xff << ((-(w + x)) & 7);
102   wd   = ((x+w+7) >> 3) - (x >> 3);
103   if (wd == 1) lm &= rm;
104   for (pl = 0; pl < 4; ++pl) {
105     GR_int32u cv = cval & 1 ? ~0L : 0L;
106     cval >>= 1;
107     if (!( !cv && (oper==C_OR||oper==C_XOR)) && !(cv && oper==C_AND) ) {
108       GR_int8u far *dptr = (GR_int8u far *)&CURC->gc_baseaddr[pl][DO];
109       int ww = wd;
110       if ( ((GR_int8u)(~lm)) ) {
111 	  switch(oper) {
112 	    case C_XOR: maskoper(dptr,^,(GR_int8u)cv,lm); break;
113 	    case C_OR:  maskoper(dptr,|,(GR_int8u)cv,lm); break;
114 	    case C_AND: maskoper(dptr,&,(GR_int8u)cv,lm); break;
115 	    default:    maskset(dptr,(GR_int8u)cv,lm);    break;
116 	  }
117 	  if (!(--ww)) continue;
118 	  ++dptr;
119       }
120       if ( ((GR_int8u)(~rm)) ) --ww;
121       if (ww) {
122 	  switch(oper) {
123 	    case C_XOR: repfill_b_xor(dptr,cv,ww); break;
124 	    case C_OR:  repfill_b_or( dptr,cv,ww); break;
125 	    case C_AND: repfill_b_and(dptr,cv,ww); break;
126 	    default:    repfill_b(    dptr,cv,ww); break;
127 	  }
128       }
129       if ( ((GR_int8u)(~rm)) ) {
130 	  switch(oper) {
131 	    case C_XOR: maskoper(dptr,^,(GR_int8u)cv,rm); break;
132 	    case C_OR:  maskoper(dptr,|,(GR_int8u)cv,rm); break;
133 	    case C_AND: maskoper(dptr,&,(GR_int8u)cv,rm); break;
134 	    default:    maskset(dptr,(GR_int8u)cv,rm);    break;
135 	  }
136       }
137     }
138   }
139   GRX_LEAVE();
140 }
141 #undef maskoper
142 
drawvline(int x,int y,int h,GrColor color)143 static void drawvline(int x,int y,int h,GrColor color)
144 {
145 	unsigned int lwdt, mask, oper, hh;
146 	char far *p;
147 	GR_int32u offs;
148 	GRX_ENTER();
149 	oper = C_OPER(color);
150 	lwdt = CURC->gc_lineoffset;
151 	offs = FOFS(x,y,lwdt);
152 	mask = 0x80 >> (x & 7);
153 	switch (oper) {
154 	  case C_XOR:
155 	      /* no need to xor anything with 0 */
156 	      if (color&1) {
157 		p = &CURC->gc_baseaddr[0][offs];
158 		hh = h;
159 		colfill_b_xor(p,lwdt,mask,hh);
160 	      }
161 	      if (color&2) {
162 		p = &CURC->gc_baseaddr[1][offs];
163 		hh = h;
164 		colfill_b_xor(p,lwdt,mask,hh);
165 	      }
166 	      if (color&4) {
167 		p = &CURC->gc_baseaddr[2][offs];
168 		hh = h;
169 		colfill_b_xor(p,lwdt,mask,hh);
170 	      }
171 	      if (color&8) {
172 		p = &CURC->gc_baseaddr[3][offs];
173 		colfill_b_xor(p,lwdt,mask,h);
174 	      }
175 	      break;
176 	  case C_OR:
177 	      /* no need to or anything with 0 */
178 	      if (color&1) {
179 		p = &CURC->gc_baseaddr[0][offs];
180 		hh = h;
181 		colfill_b_or(p,lwdt,mask,hh);
182 	      }
183 	      if (color&2) {
184 		p = &CURC->gc_baseaddr[1][offs];
185 		hh = h;
186 		colfill_b_or(p,lwdt,mask,hh);
187 	      }
188 	      if (color&4) {
189 		p = &CURC->gc_baseaddr[2][offs];
190 		hh = h;
191 		colfill_b_or(p,lwdt,mask,hh);
192 	      }
193 	      if (color&8) {
194 		p = &CURC->gc_baseaddr[3][offs];
195 		colfill_b_or(p,lwdt,mask,h);
196 	      }
197 	      break;
198 	  case C_AND:
199 	      /* no need to and anything with 1 */
200 	      mask = ~mask; /* set up reset mask */
201 	      if (!(color&1)) {
202 		p = &CURC->gc_baseaddr[0][offs];
203 		hh = h;
204 		colfill_b_and(p,lwdt,mask,hh);
205 	      }
206 	      if (!(color&2)) {
207 		p = &CURC->gc_baseaddr[1][offs];
208 		hh = h;
209 		colfill_b_and(p,lwdt,mask,hh);
210 	      }
211 	      if (!(color&4)) {
212 		p = &CURC->gc_baseaddr[2][offs];
213 		hh = h;
214 		colfill_b_and(p,lwdt,mask,hh);
215 	      }
216 	      if (!(color&8)) {
217 		p = &CURC->gc_baseaddr[3][offs];
218 		colfill_b_and(p,lwdt,mask,h);
219 	      }
220 	      break;
221 	  default: {
222 	      p = &CURC->gc_baseaddr[0][offs];
223 	      hh = h;
224 	      if (color&1) colfill_b_or(p,lwdt,mask,hh);
225 	      else         colfill_b_and(p,lwdt,~mask,hh);
226 	      p = &CURC->gc_baseaddr[1][offs];
227 	      hh = h;
228 	      if (color&2) colfill_b_or(p,lwdt,mask,hh);
229 	      else         colfill_b_and(p,lwdt,~mask,hh);
230 	      p = &CURC->gc_baseaddr[2][offs];
231 	      hh = h;
232 	      if (color&4) colfill_b_or(p,lwdt,mask,hh);
233 	      else         colfill_b_and(p,lwdt,~mask,hh);
234 	      p = &CURC->gc_baseaddr[3][offs];
235 	      if (color&8) colfill_b_or(p,lwdt,mask,h);
236 	      else         colfill_b_and(p,lwdt,~mask,h);
237 	      break;
238 	    }
239 	}
240 	GRX_LEAVE();
241 }
242 
243 static
244 #include "fdrivers/generic/block.c"
245 
246 static
247 #include "fdrivers/generic/line.c"
248 
249 static
250 #include "fdrivers/generic/bitmap.c"
251 
252 static
253 #include "fdrivers/generic/pattern.c"
254 
255 static
256 #include "fdrivers/generic/bitblt.c"
257 
bltr2r(GrFrame * dst,int dx,int dy,GrFrame * src,int x,int y,int w,int h,GrColor op)258 static void bltr2r(GrFrame *dst,int dx,int dy,
259 		   GrFrame *src,int x,int y,int w,int h,
260 		   GrColor op)
261 {
262     GRX_ENTER();
263     _GR_rblit_14(dst,dx,dy,src,x,y,w,h,op,4,bitblt);
264     GRX_LEAVE();
265 }
266 
267 GrFrameDriver _GrFrameDriverRAM4 = {
268     GR_frameRAM4,               /* frame mode */
269     GR_frameUndef,              /* compatible RAM frame mode */
270     FALSE,                      /* onscreen */
271     4,                          /* scan line width alignment */
272     4,                          /* number of planes */
273     4,                          /* bits per pixel */
274 #ifdef __TURBOC__
275     65520L,                     /* max plane size the code can handle */
276 #else
277     16*1024L*1024L,             /* max plane size the code can handle */
278 #endif
279     NULL,
280     readpixel,
281     drawpixel,
282     drawline,
283     drawhline,
284     drawvline,
285     drawblock,
286     drawbitmap,
287     drawpattern,
288     bltr2r,
289     NULL,
290     NULL,
291     _GrFrDrvGenericGetIndexedScanline,
292     _GrFrDrvGenericPutScanline
293 };
294