amd64 fixes
[btb/d2x.git] / 2d / 2dsline.c
1 /* $Id: 2dsline.c,v 1.12 2005-07-30 01:51:42 chris 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  */
20
21 #ifdef HAVE_CONFIG_H
22 #include <conf.h>
23 #endif
24
25 #include <string.h>
26
27 #include "u_mem.h"
28
29 #include "gr.h"
30 #include "grdef.h"
31 #include "error.h"
32
33 #ifdef __MSDOS__
34 #include "modex.h"
35 #include "vesa.h"
36 #endif
37
38 int Gr_scanline_darkening_level = GR_FADE_LEVELS;
39
40 #if !defined(NO_ASM) && defined(__WATCOMC__)
41
42 void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table );
43 #pragma aux gr_linear_darken parm [edi] [eax] [ecx] [edx] modify exact [eax ebx ecx edx edi] = \
44 "               xor ebx, ebx                "   \
45 "               mov bh, al                  "   \
46 "gld_loop:      mov bl, [edi]               "   \
47 "               mov al, [ebx+edx]           "   \
48 "               mov [edi], al               "   \
49 "               inc edi                     "   \
50 "               dec ecx                     "   \
51 "               jnz gld_loop                "
52
53 #elif !defined(NO_ASM) && defined(__GNUC__)
54
55 static inline void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table ) {
56    int dummy[4];
57    __asm__ __volatile__ (
58 "               xorl %%ebx, %%ebx;"
59 "               movb %%al, %%bh;"
60 "0:             movb (%%edi), %%bl;"
61 "               movb (%%ebx, %%edx), %%al;"
62 "               movb %%al, (%%edi);"
63 "               incl %%edi;"
64 "               decl %%ecx;"
65 "               jnz 0b"
66    : "=D" (dummy[0]), "=a" (dummy[1]), "=c" (dummy[2]), "=d" (dummy[3])
67    : "0" (dest), "1" (darkening_level), "2" (count), "3" (fade_table)
68    : "%ebx");
69 }
70
71 #elif !defined(NO_ASM) && defined(_MSC_VER)
72
73 __inline void gr_linear_darken( ubyte * dest, int darkening_level, int count, ubyte * fade_table )
74 {
75         __asm {
76     mov edi,[dest]
77     mov eax,[darkening_level]
78     mov ecx,[count]
79     mov edx,[fade_table]
80     xor ebx, ebx
81     mov bh, al
82 gld_loop:
83     mov bl,[edi]
84     mov al,[ebx+edx]
85     mov [edi],al
86     inc edi
87     dec ecx
88     jnz gld_loop
89         }
90 }
91
92 #else // Unknown compiler, or no assembler. So we use C.
93
94 void gr_linear_darken(ubyte * dest, int darkening_level, int count, ubyte * fade_table) {
95         register int i;
96
97         for (i=0;i<count;i++)
98         {
99                 *dest = fade_table[(*dest)+(darkening_level*256)];
100                 dest++;
101         }
102 }
103
104 #endif
105
106 #ifdef NO_ASM // No Assembler. So we use C.
107 #if 0
108 void gr_linear_stosd( ubyte * dest, ubyte color, unsigned short count )
109 {
110         int i, x;
111
112         if (count > 3) {
113                 while ((int)(dest) & 0x3) { *dest++ = color; count--; };
114                 if (count >= 4) {
115                         x = (color << 24) | (color << 16) | (color << 8) | color;
116                         while (count > 4) { *(int *)dest = x; dest += 4; count -= 4; };
117                 }
118                 while (count > 0) { *dest++ = color; count--; };
119         } else {
120                 for (i=0; i<count; i++ )
121                         *dest++ = color;
122         }
123 }
124 #else
125 void gr_linear_stosd( ubyte * dest, unsigned char color, unsigned int nbytes) {
126         memset(dest,color,nbytes);
127 }
128 #endif
129 #endif
130
131 void gr_uscanline( int x1, int x2, int y )
132 {
133         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) {
134                 switch(TYPE)
135                 {
136                 case BM_LINEAR:
137 #ifdef OGL
138                 case BM_OGL:
139 #endif
140                         gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1);
141                         break;
142 #ifdef __MSDOS__
143                 case BM_MODEX:
144                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
145                         break;
146                 case BM_SVGA:
147                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
148                         break;
149 #endif
150                 }
151         } else {
152                 switch(TYPE)
153                 {
154                 case BM_LINEAR:
155 #ifdef OGL
156                 case BM_OGL:
157 #endif
158                         gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
159                         break;
160 #ifdef __MSDOS__
161                 case BM_MODEX:
162                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
163                         break;
164                 case BM_SVGA:
165 #if 1
166                         {
167                                 ubyte * vram = (ubyte *)0xA0000;
168                                 int VideoLocation,page,offset1, offset2;
169
170                                 VideoLocation = (ROWSIZE * y) + x1;
171                                 page    = VideoLocation >> 16;
172                                 offset1  = VideoLocation & 0xFFFF;
173                                 offset2   = offset1 + (x2-x1+1);
174
175                                 gr_vesa_setpage( page );
176                                 if ( offset2 <= 0xFFFF ) {
177                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
178                                 } else {
179                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, 0xFFFF-offset1+1, gr_fade_table);
180                                         page++;
181                                         gr_vesa_setpage(page);
182                                         gr_linear_darken( vram, Gr_scanline_darkening_level, offset2 - 0xFFFF, gr_fade_table);
183                                 }
184                         }
185 #else
186                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
187 #endif
188                         break;
189 #endif
190                 }
191         }
192 }
193
194 void gr_scanline( int x1, int x2, int y )
195 {
196         if ((y<0)||(y>MAXY)) return;
197
198         if (x2 < x1 ) x2 ^= x1 ^= x2;
199
200         if (x1 > MAXX) return;
201         if (x2 < MINX) return;
202
203         if (x1 < MINX) x1 = MINX;
204         if (x2 > MAXX) x2 = MAXX;
205
206         if (Gr_scanline_darkening_level >= GR_FADE_LEVELS ) {
207                 switch(TYPE)
208                 {
209                 case BM_LINEAR:
210 #ifdef OGL
211                 case BM_OGL:
212 #endif
213                         gr_linear_stosd( DATA + ROWSIZE*y + x1, (unsigned char)COLOR, x2-x1+1);
214                         break;
215 #ifdef __MSDOS__
216                 case BM_MODEX:
217                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
218                         break;
219                 case BM_SVGA:
220                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
221                         break;
222 #endif
223                 }
224         } else {
225                 switch(TYPE)
226                 {
227                 case BM_LINEAR:
228 #ifdef OGL
229                 case BM_OGL:
230 #endif
231                         gr_linear_darken( DATA + ROWSIZE*y + x1, Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
232                         break;
233 #ifdef __MSDOS__
234                 case BM_MODEX:
235                         gr_modex_uscanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
236                         break;
237                 case BM_SVGA:
238 #if 1
239                         {
240                                 ubyte * vram = (ubyte *)0xA0000;
241                                 int VideoLocation,page,offset1, offset2;
242
243                                 VideoLocation = (ROWSIZE * y) + x1;
244                                 page    = VideoLocation >> 16;
245                                 offset1  = VideoLocation & 0xFFFF;
246                                 offset2   = offset1 + (x2-x1+1);
247
248                                 gr_vesa_setpage( page );
249                                 if ( offset2 <= 0xFFFF )        {
250                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, x2-x1+1, gr_fade_table);
251                                 } else {
252                                         gr_linear_darken( &vram[offset1], Gr_scanline_darkening_level, 0xFFFF-offset1+1, gr_fade_table);
253                                         page++;
254                                         gr_vesa_setpage(page);
255                                         gr_linear_darken( vram, Gr_scanline_darkening_level, offset2 - 0xFFFF, gr_fade_table);
256                                 }
257                         }
258 #else
259                         gr_vesa_scanline( x1+XOFFSET, x2+XOFFSET, y+YOFFSET, COLOR );
260 #endif
261                         break;
262 #endif
263                 }
264         }
265 }