fix bug: when opening d1 level 1 with oem data files, both d1 and d2 oem briefing...
[btb/d2x.git] / 2d / 2dsline.c
1 /* $Id: 2dsline.c,v 1.9 2002-10-12 03:09:23 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                 *dest=fade_table[(*dest++)+(darkening_level*256)];
146 }
147
148 #endif
149
150 #ifdef NO_ASM // No Assembler. So we use C.
151 #if 0
152 void gr_linear_stosd( ubyte * dest, ubyte color, unsigned short count )
153 {
154         int i, x;
155
156         if (count > 3) {
157                 while ((int)(dest) & 0x3) { *dest++ = color; count--; };
158                 if (count >= 4) {
159                         x = (color << 24) | (color << 16) | (color << 8) | color;
160                         while (count > 4) { *(int *)dest = x; dest += 4; count -= 4; };
161                 }
162                 while (count > 0) { *dest++ = color; count--; };
163         } else {
164                 for (i=0; i<count; i++ )
165                         *dest++ = color;
166         }
167 }
168 #else
169 void gr_linear_stosd( ubyte * dest, unsigned char color, unsigned int nbytes) {
170         memset(dest,color,nbytes);
171 }
172 #endif
173 #endif
174
175 #if defined(POLY_ACC)
176 //$$ Note that this code WAS a virtual clone of the mac code and any changes to mac should be reflected here.
177 void gr_linear15_darken( short * dest, int darkening_level, int count, ubyte * fade_table )
178 {
179     //$$ this routine is a prime candidate for using the alpha blender.
180     int i;
181     unsigned short rt[32], gt[32], bt[32];
182     unsigned long level, int_level, dlevel;
183
184     dlevel = (darkening_level << 16) / GR_FADE_LEVELS;
185     level = int_level = 0;
186     for(i = 0; i != 32; ++i)
187     {
188         rt[i] = int_level << 10;
189         gt[i] = int_level << 5;
190         bt[i] = int_level;
191
192         level += dlevel;
193         int_level = level >> 16;
194     }
195
196     pa_flush();
197     for (i=0; i<count; i++ )    {
198         if(*dest & 0x8000)
199                 *dest =
200                  rt[((*dest >> 10) & 0x1f)] |
201               gt[((*dest >> 5) & 0x1f)] |
202                    bt[((*dest >> 0) & 0x1f)] |
203                 0x8000;
204                 dest++;
205         }
206 }
207
208 void gr_linear15_stosd( short * dest, ubyte color, unsigned short count )
209 {
210     //$$ this routine is a prime candidate for using the alpha blender.
211     short c = pa_clut[color];
212     pa_flush();
213     while(count--)
214         *dest++ = c;
215 }
216 #endif
217
218 void gr_uscanline( int x1, int x2, int y )
219 {
220         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) {
221                 switch(TYPE)
222                 {
223                 case BM_LINEAR:
224 #ifdef OGL
225                 case BM_OGL:
226 #endif
227                         gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1);
228                         break;
229 #ifdef __MSDOS__
230                 case BM_MODEX:
231                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
232                         break;
233                 case BM_SVGA:
234                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
235                         break;
236 #endif
237 #if defined(POLY_ACC)
238                 case BM_LINEAR15:
239                         gr_linear15_stosd( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), COLOR, x2-x1+1);
240                         break;
241 #endif
242                 }
243         } else {
244                 switch(TYPE)
245                 {
246                 case BM_LINEAR:
247 #ifdef OGL
248                 case BM_OGL:
249 #endif
250                         gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
251                         break;
252 #ifdef __MSDOS__
253                 case BM_MODEX:
254                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
255                         break;
256                 case BM_SVGA:
257 #if 1
258                         {
259                                 ubyte * vram = (ubyte *)0xA0000;
260                                 int VideoLocation,page,offset1, offset2;
261
262                                 VideoLocation = (ROWSIZE * y) + x1;
263                                 page    = VideoLocation >> 16;
264                                 offset1  = VideoLocation & 0xFFFF;
265                                 offset2   = offset1 + (x2-x1+1);
266
267                                 gr_vesa_setpage( page );
268                                 if ( offset2 <= 0xFFFF ) {
269                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
270                                 } else {
271                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, 0xFFFF-offset1+1, gr_fade_table);
272                                         page++;
273                                         gr_vesa_setpage(page);
274                                         gr_linear_darken( vram, Gr_scanline_darkening_level, offset2 - 0xFFFF, gr_fade_table);
275                                 }
276                         }
277 #else
278                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
279 #endif
280                         break;
281 #endif
282 #if defined(POLY_ACC)
283                 case BM_LINEAR15:
284                         gr_linear15_darken( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
285                         break;
286 #endif
287                 }
288         }
289 }
290
291 void gr_scanline( int x1, int x2, int y )
292 {
293         if ((y<0)||(y>MAXY)) return;
294
295         if (x2 < x1 ) x2 ^= x1 ^= x2;
296
297         if (x1 > MAXX) return;
298         if (x2 < MINX) return;
299
300         if (x1 < MINX) x1 = MINX;
301         if (x2 > MAXX) x2 = MAXX;
302
303         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) {
304                 switch(TYPE)
305                 {
306                 case BM_LINEAR:
307 #ifdef OGL
308                 case BM_OGL:
309 #endif
310                         gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1);
311                         break;
312 #ifdef __MSDOS__
313                 case BM_MODEX:
314                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
315                         break;
316                 case BM_SVGA:
317                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
318                         break;
319 #endif
320 #if defined(POLY_ACC)
321                 case BM_LINEAR15:
322                         gr_linear15_stosd( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), COLOR, x2-x1+1);
323                         break;
324 #endif
325                 }
326         } else {
327                 switch(TYPE)
328                 {
329                 case BM_LINEAR:
330 #ifdef OGL
331                 case BM_OGL:
332 #endif
333                         gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
334                         break;
335 #ifdef __MSDOS__
336                 case BM_MODEX:
337                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
338                         break;
339                 case BM_SVGA:
340 #if 1
341                         {
342                                 ubyte * vram = (ubyte *)0xA0000;
343                                 int VideoLocation,page,offset1, offset2;
344
345                                 VideoLocation = (ROWSIZE * y) + x1;
346                                 page    = VideoLocation >> 16;
347                                 offset1  = VideoLocation & 0xFFFF;
348                                 offset2   = offset1 + (x2-x1+1);
349
350                                 gr_vesa_setpage( page );
351                                 if ( offset2 <= 0xFFFF )        {
352                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
353                                 } else {
354                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, 0xFFFF-offset1+1, gr_fade_table);
355                                         page++;
356                                         gr_vesa_setpage(page);
357                                         gr_linear_darken( vram, Gr_scanline_darkening_level, offset2 - 0xFFFF, gr_fade_table);
358                                 }
359                         }
360 #else
361                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
362 #endif
363                         break;
364 #endif
365 #if defined(POLY_ACC)
366                 case BM_LINEAR15:
367                         gr_linear15_darken( (short *)(DATA + ROWSIZE*y + x1 * PA_BPP), Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
368                         break;
369 #endif
370                 }
371         }
372 }