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