62f0a1cec081448398a639f8b3498f0479534c93
[btb/d2x.git] / 2d / 2dsline.c
1 /* $Id: 2dsline.c,v 1.10 2003-04-29 08:05:41 btb Exp $ */
2 /*
3 THE COMPUTER CODE CONTAINED HEREIN IS THE SOLE PROPERTY OF PARALLAX
4 SOFTWARE CORPORATION ("PARALLAX").  PARALLAX, IN DISTRIBUTING THE CODE TO
5 END-USERS, AND SUBJECT TO ALL OF THE TERMS AND CONDITIONS HEREIN, GRANTS A
6 ROYALTY-FREE, PERPETUAL LICENSE TO SUCH END-USERS FOR USE BY SUCH END-USERS
7 IN USING, DISPLAYING,  AND CREATING DERIVATIVE WORKS THEREOF, SO LONG AS
8 SUCH USE, DISPLAY OR CREATION IS FOR NON-COMMERCIAL, ROYALTY OR REVENUE
9 FREE PURPOSES.  IN NO EVENT SHALL THE END-USER USE THE COMPUTER CODE
10 CONTAINED HEREIN FOR REVENUE-BEARING PURPOSES.  THE END-USER UNDERSTANDS
11 AND AGREES TO THE TERMS HEREIN AND ACCEPTS THE SAME BY USE OF THIS FILE.
12 COPYRIGHT 1993-1998 PARALLAX SOFTWARE CORPORATION.  ALL RIGHTS RESERVED.
13 */
14
15 /*
16  *
17  * Graphical routines for drawing solid scanlines.
18  *
19  * Old Log:
20  * Revision 1.6  1995/09/14  14:24:03  allender
21  * fixed MW compile error
22  *
23  * Revision 1.5  1995/09/14  13:45:17  allender
24  * quick optimization for scanline
25  *
26  * Revision 1.4  1995/04/27  07:36:05  allender
27  * remove some memsets since all old is here now
28  *
29  * Revision 1.3  1995/04/19  14:35:33  allender
30  * *** empty log message ***
31  *
32  * Revision 1.2  1995/04/18  12:03:40  allender
33  * *** empty log message ***
34  *
35  * Revision 1.1  1995/03/09  09:24:06  allender
36  * Initial revision
37  *
38  *
39  * --- PC RCS information ---
40  * Revision 1.7  1994/11/18  22:50:48  john
41  * Changed a bunch of shorts to ints in calls.
42  *
43  * Revision 1.6  1994/09/02  11:40:32  john
44  * fixed bug with urect scanline drakening still
45  * only using 16 levels of fade.
46  *
47  * Revision 1.5  1994/04/08  16:59:12  john
48  * Add fading poly's; Made palette fade 32 instead of 16.
49  *
50  * Revision 1.4  1994/03/22  18:36:27  john
51  * Added darkening scanlines
52  *
53  * Revision 1.3  1993/10/15  16:22:52  john
54  * y
55  *
56  * Revision 1.2  1993/09/08  11:56:29  john
57  * neatened
58  *
59  * Revision 1.1  1993/09/08  11:44:27  john
60  * Initial revision
61  *
62  */
63
64 #ifdef HAVE_CONFIG_H
65 #include <conf.h>
66 #endif
67
68 #include <string.h>
69
70 #include "u_mem.h"
71
72 #include "gr.h"
73 #include "grdef.h"
74 #include "error.h"
75
76 #ifdef __MSDOS__
77 #include "modex.h"
78 #include "vesa.h"
79 #endif
80
81 #if defined(POLY_ACC)
82 #include "poly_acc.h"
83 #endif
84
85 int Gr_scanline_darkening_level = GR_FADE_LEVELS;
86
87 #if !defined(NO_ASM) && defined(__WATCOMC__)
88
89 void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table );
90 #pragma aux gr_linear_darken parm [edi] [eax] [ecx] [edx] modify exact [eax ebx ecx edx edi] = \
91 "               xor ebx, ebx                "   \
92 "               mov bh, al                  "   \
93 "gld_loop:      mov bl, [edi]               "   \
94 "               mov al, [ebx+edx]           "   \
95 "               mov [edi], al               "   \
96 "               inc edi                     "   \
97 "               dec ecx                     "   \
98 "               jnz gld_loop                "
99
100 #elif !defined(NO_ASM) && defined(__GNUC__)
101
102 static inline void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table ) {
103    int dummy[4];
104    __asm__ __volatile__ (
105 "               xorl %%ebx, %%ebx;"
106 "               movb %%al, %%bh;"
107 "0:             movb (%%edi), %%bl;"
108 "               movb (%%ebx, %%edx), %%al;"
109 "               movb %%al, (%%edi);"
110 "               incl %%edi;"
111 "               decl %%ecx;"
112 "               jnz 0b"
113    : "=D" (dummy[0]), "=a" (dummy[1]), "=c" (dummy[2]), "=d" (dummy[3])
114    : "0" (dest), "1" (darkening_level), "2" (count), "3" (fade_table)
115    : "%ebx");
116 }
117
118 #elif !defined(NO_ASM) && defined(_MSC_VER)
119
120 __inline void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table )
121 {
122         __asm {
123     mov edi,[dest]
124     mov eax,[darkening_level]
125     mov ecx,[count]
126     mov edx,[fade_table]
127     xor ebx, ebx
128     mov bh, al
129 gld_loop:
130     mov bl,[edi]
131     mov al,[ebx+edx]
132     mov [edi],al
133     inc edi
134     dec ecx
135     jnz gld_loop
136         }
137 }
138
139 #else // Unknown compiler, or no assembler. So we use C.
140
141 void gr_linear_darken(ubyte * dest, int darkening_level, int count, ubyte * fade_table) {
142         register int i;
143
144         for (i=0;i<count;i++)
145         {
146                 *dest = fade_table[(*dest)+(darkening_level*256)];
147                 dest++;
148         }
149 }
150
151 #endif
152
153 #ifdef NO_ASM // No Assembler. So we use C.
154 #if 0
155 void gr_linear_stosd( ubyte * dest, ubyte color, unsigned short count )
156 {
157         int i, x;
158
159         if (count > 3) {
160                 while ((int)(dest) & 0x3) { *dest++ = color; count--; };
161                 if (count >= 4) {
162                         x = (color << 24) | (color << 16) | (color << 8) | color;
163                         while (count > 4) { *(int *)dest = x; dest += 4; count -= 4; };
164                 }
165                 while (count > 0) { *dest++ = color; count--; };
166         } else {
167                 for (i=0; i<count; i++ )
168                         *dest++ = color;
169         }
170 }
171 #else
172 void gr_linear_stosd( ubyte * dest, unsigned char color, unsigned int nbytes) {
173         memset(dest,color,nbytes);
174 }
175 #endif
176 #endif
177
178 #if defined(POLY_ACC)
179 //$$ Note that this code WAS a virtual clone of the mac code and any changes to mac should be reflected here.
180 void gr_linear15_darken( short * dest, int darkening_level, int count, ubyte * fade_table )
181 {
182     //$$ this routine is a prime candidate for using the alpha blender.
183     int i;
184     unsigned short rt[32], gt[32], bt[32];
185     unsigned long level, int_level, dlevel;
186
187     dlevel = (darkening_level << 16) / GR_FADE_LEVELS;
188     level = int_level = 0;
189     for(i = 0; i != 32; ++i)
190     {
191         rt[i] = int_level << 10;
192         gt[i] = int_level << 5;
193         bt[i] = int_level;
194
195         level += dlevel;
196         int_level = level >> 16;
197     }
198
199     pa_flush();
200     for (i=0; i<count; i++ )    {
201         if(*dest & 0x8000)
202                 *dest =
203                  rt[((*dest >> 10) & 0x1f)] |
204               gt[((*dest >> 5) & 0x1f)] |
205                    bt[((*dest >> 0) & 0x1f)] |
206                 0x8000;
207                 dest++;
208         }
209 }
210
211 void gr_linear15_stosd( short * dest, ubyte color, unsigned short count )
212 {
213     //$$ this routine is a prime candidate for using the alpha blender.
214     short c = pa_clut[color];
215     pa_flush();
216     while(count--)
217         *dest++ = c;
218 }
219 #endif
220
221 void gr_uscanline( int x1, int x2, int y )
222 {
223         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) {
224                 switch(TYPE)
225                 {
226                 case BM_LINEAR:
227 #ifdef OGL
228                 case BM_OGL:
229 #endif
230                         gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1);
231                         break;
232 #ifdef __MSDOS__
233                 case BM_MODEX:
234                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
235                         break;
236                 case BM_SVGA:
237                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
238                         break;
239 #endif
240 #if defined(POLY_ACC)
241                 case BM_LINEAR15:
242                         gr_linear15_stosd( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), COLOR, x2-x1+1);
243                         break;
244 #endif
245                 }
246         } else {
247                 switch(TYPE)
248                 {
249                 case BM_LINEAR:
250 #ifdef OGL
251                 case BM_OGL:
252 #endif
253                         gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
254                         break;
255 #ifdef __MSDOS__
256                 case BM_MODEX:
257                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
258                         break;
259                 case BM_SVGA:
260 #if 1
261                         {
262                                 ubyte * vram = (ubyte *)0xA0000;
263                                 int VideoLocation,page,offset1, offset2;
264
265                                 VideoLocation = (ROWSIZE * y) + x1;
266                                 page    = VideoLocation >> 16;
267                                 offset1  = VideoLocation & 0xFFFF;
268                                 offset2   = offset1 + (x2-x1+1);
269
270                                 gr_vesa_setpage( page );
271                                 if ( offset2 <= 0xFFFF ) {
272                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
273                                 } else {
274                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, 0xFFFF-offset1+1, gr_fade_table);
275                                         page++;
276                                         gr_vesa_setpage(page);
277                                         gr_linear_darken( vram, Gr_scanline_darkening_level, offset2 - 0xFFFF, gr_fade_table);
278                                 }
279                         }
280 #else
281                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
282 #endif
283                         break;
284 #endif
285 #if defined(POLY_ACC)
286                 case BM_LINEAR15:
287                         gr_linear15_darken( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
288                         break;
289 #endif
290                 }
291         }
292 }
293
294 void gr_scanline( int x1, int x2, int y )
295 {
296         if ((y<0)||(y>MAXY)) return;
297
298         if (x2 < x1 ) x2 ^= x1 ^= x2;
299
300         if (x1 > MAXX) return;
301         if (x2 < MINX) return;
302
303         if (x1 < MINX) x1 = MINX;
304         if (x2 > MAXX) x2 = MAXX;
305
306         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) {
307                 switch(TYPE)
308                 {
309                 case BM_LINEAR:
310 #ifdef OGL
311                 case BM_OGL:
312 #endif
313                         gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1);
314                         break;
315 #ifdef __MSDOS__
316                 case BM_MODEX:
317                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
318                         break;
319                 case BM_SVGA:
320                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
321                         break;
322 #endif
323 #if defined(POLY_ACC)
324                 case BM_LINEAR15:
325                         gr_linear15_stosd( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), COLOR, x2-x1+1);
326                         break;
327 #endif
328                 }
329         } else {
330                 switch(TYPE)
331                 {
332                 case BM_LINEAR:
333 #ifdef OGL
334                 case BM_OGL:
335 #endif
336                         gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
337                         break;
338 #ifdef __MSDOS__
339                 case BM_MODEX:
340                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
341                         break;
342                 case BM_SVGA:
343 #if 1
344                         {
345                                 ubyte * vram = (ubyte *)0xA0000;
346                                 int VideoLocation,page,offset1, offset2;
347
348                                 VideoLocation = (ROWSIZE * y) + x1;
349                                 page    = VideoLocation >> 16;
350                                 offset1  = VideoLocation & 0xFFFF;
351                                 offset2   = offset1 + (x2-x1+1);
352
353                                 gr_vesa_setpage( page );
354                                 if ( offset2 <= 0xFFFF )        {
355                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
356                                 } else {
357                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, 0xFFFF-offset1+1, gr_fade_table);
358                                         page++;
359                                         gr_vesa_setpage(page);
360                                         gr_linear_darken( vram, Gr_scanline_darkening_level, offset2 - 0xFFFF, gr_fade_table);
361                                 }
362                         }
363 #else
364                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
365 #endif
366                         break;
367 #endif
368 #if defined(POLY_ACC)
369                 case BM_LINEAR15:
370                         gr_linear15_darken( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
371                         break;
372 #endif
373                 }
374         }
375 }