OSDN Git Service

EXEMM BROKEN
[proj16/16.git] / src / lib / 16_vl_1.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or  modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without    even the implied warranty of\r
13  * MERCHANTABILITY or   FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for       more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin     Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 #include <conio.h>\r
24 #include <stdio.h>\r
25 #include <stdlib.h>\r
26 #include "src/lib/16_vl.h"\r
27 \r
28 static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */\r
29 \r
30 //===========================================================================\r
31 \r
32 //==============\r
33 //\r
34 // VL_SetScreen\r
35 //\r
36 //==============\r
37 \r
38 void    VL_SetScreen (unsigned int crtc, int pelpan)\r
39 {\r
40 // PROC VL_SetScreen  crtc:WORD, pel:WORD\r
41 // PUBLIC       VL_SetScreen\r
42         word TimeCount = *clockw;\r
43         __asm {\r
44                 mov     cx,[TimeCount]          // if TimeCount goes up by two, the retrace\r
45                 add     cx,2                            // period was missed (an interrupt covered it)\r
46 \r
47                 mov     dx,STATUS_REGISTER_1\r
48 \r
49         // wait for     a display signal to make sure the raster isn't in       the middle\r
50         // of a sync\r
51 \r
52 #ifdef __BORLANDC__\r
53         }\r
54 #endif\r
55 SetScreen_waitdisplay:\r
56 #ifdef __BORLANDC__\r
57         __asm {\r
58 #endif\r
59                 in      al,dx\r
60                 test    al,1    //1 = display is disabled (HBL / VBL)\r
61                 jnz     SetScreen_waitdisplay\r
62 \r
63 #ifdef __BORLANDC__\r
64         }\r
65 #endif\r
66 SetScreen_loop:\r
67 #ifdef __BORLANDC__\r
68         __asm {\r
69 #endif\r
70                 sti\r
71                 jmp     SetScreen_skip1\r
72                 cli\r
73 #ifdef __BORLANDC__\r
74         }\r
75 #endif\r
76 SetScreen_skip1:\r
77 #ifdef __BORLANDC__\r
78         __asm {\r
79 #endif\r
80                 cmp     [TimeCount],cx          // will only happen if an interrupt is\r
81                 jae     SetScreen_setcrtc                       // straddling the entire retrace period\r
82 \r
83         // when several succesive display not enableds occur,\r
84         // the bottom of the screen has been hit\r
85 \r
86                 in      al,dx\r
87                 test    al,8\r
88                 jnz     SetScreen_waitdisplay\r
89                 test    al,1\r
90                 jz      SetScreen_loop\r
91 \r
92                 in      al,dx\r
93                 test    al,8\r
94                 jnz     SetScreen_waitdisplay\r
95                 test    al,1\r
96                 jz      SetScreen_loop\r
97 \r
98                 in      al,dx\r
99                 test    al,8\r
100                 jnz     SetScreen_waitdisplay\r
101                 test    al,1\r
102                 jz      SetScreen_loop\r
103 \r
104                 in      al,dx\r
105                 test    al,8\r
106                 jnz     SetScreen_waitdisplay\r
107                 test    al,1\r
108                 jz      SetScreen_loop\r
109 \r
110                 in      al,dx\r
111                 test    al,8\r
112                 jnz     SetScreen_waitdisplay\r
113                 test    al,1\r
114                 jz      SetScreen_loop\r
115 \r
116 #ifdef __BORLANDC__\r
117         }\r
118 #endif\r
119 SetScreen_setcrtc:\r
120 #ifdef __BORLANDC__\r
121         __asm {\r
122 #endif\r
123         // set CRTC start\r
124         // for  some reason, my XT's EGA card doesn't like word outs to the CRTC index...\r
125 \r
126                 mov     cx,[crtc]\r
127                 mov     dx,CRTC_INDEX\r
128                 mov     al,0ch          //start address high register\r
129                 out     dx,al\r
130                 inc     dx\r
131                 mov     al,ch\r
132                 out     dx,al\r
133                 dec     dx\r
134                 mov     al,0dh          //start address low register\r
135                 out     dx,al\r
136                 mov     al,cl\r
137                 inc     dx\r
138                 out     dx,al\r
139 \r
140 \r
141         // set horizontal panning\r
142 \r
143                 mov     dx,ATR_INDEX\r
144 //              mov     al,ATR_PELPAN or        20h\r
145                 out     dx,al\r
146                 jmp     SetScreen_done\r
147                 mov     al,[BYTE PTR pelpan]            //pel pan value\r
148                 out     dx,al\r
149 #ifdef __BORLANDC__\r
150         }\r
151 #endif\r
152 SetScreen_done:\r
153 #ifdef __BORLANDC__\r
154         __asm {\r
155 #endif\r
156 //              sti\r
157 \r
158 //              ret\r
159         }\r
160 }\r
161 \r
162 /*\r
163 ====================\r
164 =\r
165 = VL_SetLineWidth\r
166 =\r
167 = Line witdh is in      WORDS, 40 words is normal width for     vgaplanegr\r
168 =\r
169 ====================\r
170 */\r
171 #if 0\r
172 void VL_SetLineWidth (unsigned width, global_game_variables_t *gvar)\r
173 {\r
174         int i,offset;\r
175 \r
176 //\r
177 // set wide virtual screen\r
178 //\r
179         outport (CRTC_INDEX,CRTC_OFFSET+width*256);\r
180 \r
181 //\r
182 // set up lookup tables\r
183 //\r
184         gvar->video.ofs.linewidth = width*2;\r
185 \r
186         offset = 0;\r
187 \r
188         for     (i=0;i<MAXSCANLINES;i++)\r
189         {\r
190                 gvar->video.ofs.ylookup[i]=offset;\r
191                 offset += gvar->video.ofs.linewidth;\r
192         }\r
193 }\r
194 #endif\r
195 /*\r
196 =============================================================================\r
197 \r
198                                                 PALETTE OPS\r
199 \r
200                 To avoid snow, do a WaitVBL BEFORE calling these\r
201 \r
202 =============================================================================\r
203 */\r
204 \r
205 \r
206 /*\r
207 =================\r
208 =\r
209 = VL_FillPalette\r
210 =\r
211 =================\r
212 */\r
213 \r
214 void VL_FillPalette (int red, int green, int blue)\r
215 {\r
216         int     i;\r
217 \r
218         outportb (PAL_WRITE_REG,0);\r
219         for     (i=0;i<256;i++)\r
220         {\r
221                 outportb (PAL_DATA_REG,red);\r
222                 outportb (PAL_DATA_REG,green);\r
223                 outportb (PAL_DATA_REG,blue);\r
224         }\r
225 }\r
226 \r
227 //===========================================================================\r
228 \r
229 /*\r
230 =================\r
231 =\r
232 = VL_SetColor\r
233 =\r
234 =================\r
235 */\r
236 \r
237 void VL_SetColor        (int color, int red, int green, int blue)\r
238 {\r
239         outportb (PAL_WRITE_REG,color);\r
240         outportb (PAL_DATA_REG,red);\r
241         outportb (PAL_DATA_REG,green);\r
242         outportb (PAL_DATA_REG,blue);\r
243 }\r
244 \r
245 //===========================================================================\r
246 \r
247 /*\r
248 =================\r
249 =\r
250 = VL_GetColor\r
251 =\r
252 =================\r
253 */\r
254 \r
255 void VL_GetColor        (int color, int *red, int *green, int *blue)\r
256 {\r
257         outportb (PAL_READ_REG,color);\r
258         *red = inportb (PAL_DATA_REG);\r
259         *green = inportb (PAL_DATA_REG);\r
260         *blue = inportb (PAL_DATA_REG);\r
261 }\r
262 \r
263 //===========================================================================\r
264 \r
265 /*\r
266 =================\r
267 =\r
268 = VL_SetPalette\r
269 =\r
270 = If fast palette setting has been tested for, it is used\r
271 = (some cards don't like outsb palette setting)\r
272 =\r
273 =================\r
274 */\r
275 \r
276 void VL_SetPalette (byte far *palette, video_t *v)\r
277 {\r
278 //      int     i;\r
279         boolean fastpalette;\r
280         fastpalette=v->fastpalette;\r
281 \r
282 //      outportb (PAL_WRITE_REG,0);\r
283 //      for     (i=0;i<768;i++)\r
284 //              outportb(PAL_DATA_REG,*palette++);\r
285 \r
286         __asm {\r
287                 mov     dx,PAL_WRITE_REG\r
288                 mov     al,0\r
289                 out     dx,al\r
290                 mov     dx,PAL_DATA_REG\r
291                 lds     si,[palette]\r
292 \r
293                 test    [ss:fastpalette],1\r
294                 jz      slowset\r
295 //\r
296 // set palette fast for cards that can take it\r
297 //\r
298                 //mov   cx,768\r
299                 //rep outsb\r
300                 //jmp   done\r
301 \r
302 //\r
303 // set palette slowly for       some video cards\r
304 //\r
305 #ifdef __BORLANDC__\r
306         }\r
307 #endif\r
308 slowset:\r
309 #ifdef __BORLANDC__\r
310         __asm {\r
311 #endif\r
312                 mov     cx,256\r
313 #ifdef __BORLANDC__\r
314         }\r
315 #endif\r
316 setloop:\r
317 #ifdef __BORLANDC__\r
318         __asm {\r
319 #endif\r
320                 lodsb\r
321                 out     dx,al\r
322                 lodsb\r
323                 out     dx,al\r
324                 lodsb\r
325                 out     dx,al\r
326                 loop    setloop\r
327 #ifdef __BORLANDC__\r
328         }\r
329 #endif\r
330 done:\r
331 #ifdef __BORLANDC__\r
332         __asm {\r
333 #endif\r
334                 mov     ax,ss\r
335                         mov     ds,ax\r
336         }\r
337         v->fastpalette=fastpalette;\r
338 }\r
339 \r
340 \r
341 //===========================================================================\r
342 \r
343 /*\r
344 =================\r
345 =\r
346 = VL_GetPalette\r
347 =\r
348 = This does not use the port string instructions,\r
349 = due to some incompatabilities\r
350 =\r
351 =================\r
352 */\r
353 \r
354 void VL_GetPalette (byte far *palette)\r
355 {\r
356         int     i;\r
357 \r
358         outportb (PAL_READ_REG,0);\r
359         for     (i=0;i<768;i++)\r
360                 *palette++ = inportb(PAL_DATA_REG);\r
361 }\r
362 \r
363 \r
364 //===========================================================================\r
365 \r
366 /*\r
367 =================\r
368 =\r
369 = VL_FadeOut\r
370 =\r
371 = Fades the current palette to the given color  in      the given number of steps\r
372 =\r
373 =================\r
374 */\r
375 \r
376 void VL_FadeOut (int start, int end, int red, int green, int blue, int steps, video_t *v)\r
377 {\r
378         int             i,j,orig,delta;\r
379         byte    far *origptr, far *newptr;\r
380 \r
381         VL_WaitVBL(1);\r
382         VL_GetPalette (&v->palette1[0][0]);\r
383         _fmemcpy (v->palette2,v->palette1,PALSIZE);\r
384 \r
385 //\r
386 // fade through intermediate frames\r
387 //\r
388         for     (i=0;i<steps;i++)\r
389         {\r
390                 origptr = &v->palette1[start][0];\r
391                 newptr = &v->palette2[start][0];\r
392                 for     (j=start;j<=end;j++)\r
393                 {\r
394                         orig = *origptr++;\r
395                         delta = red-orig;\r
396                         *newptr++ = orig + delta * i / steps;\r
397                         orig = *origptr++;\r
398                         delta = green-orig;\r
399                         *newptr++ = orig + delta * i / steps;\r
400                         orig = *origptr++;\r
401                         delta = blue-orig;\r
402                         *newptr++ = orig + delta * i / steps;\r
403                 }\r
404 \r
405                 VL_WaitVBL(1);\r
406                 VL_SetPalette (&v->palette2[0][0], v);\r
407         }\r
408 \r
409 //\r
410 // final color\r
411 //\r
412         VL_FillPalette (red,green,blue);\r
413 \r
414         v->screenfaded = true;\r
415 }\r
416 \r
417 \r
418 /*\r
419 =================\r
420 =\r
421 = VL_FadeIn\r
422 =\r
423 =================\r
424 */\r
425 \r
426 void VL_FadeIn (int start, int end, byte far *palette, int steps, video_t *v)\r
427 {\r
428         int             i,j,delta;\r
429 \r
430         VL_WaitVBL(1);\r
431         VL_GetPalette (&v->palette1[0][0]);\r
432         _fmemcpy (&v->palette2[0][0],&v->palette1[0][0],sizeof(v->palette1));\r
433 \r
434         start *= 3;\r
435         end = end*3+2;\r
436 \r
437 //\r
438 // fade through intermediate frames\r
439 //\r
440         for     (i=0;i<steps;i++)\r
441         {\r
442                 for     (j=start;j<=end;j++)\r
443                 {\r
444                         delta = palette[j]-v->palette1[0][j];\r
445                         v->palette2[0][j] = v->palette1[0][j] + delta * i / steps;\r
446                 }\r
447 \r
448                 VL_WaitVBL(1);\r
449                 VL_SetPalette (&v->palette2[0][0], v);\r
450         }\r
451 \r
452 //\r
453 // final color\r
454 //\r
455         VL_SetPalette (palette, v);\r
456         v->screenfaded = false;\r
457 }\r
458 \r
459 \r
460 \r
461 /*\r
462 =================\r
463 =\r
464 = VL_TestPaletteSet\r
465 =\r
466 = Sets the palette with outsb, then reads it in and     compares\r
467 = If it compares ok, fastpalette is set to true.\r
468 =\r
469 =================\r
470 */\r
471 \r
472 void VL_TestPaletteSet (video_t *v)\r
473 {\r
474         int     i;\r
475 \r
476         for     (i=0;i<768;i++)\r
477                 v->palette1[0][i] = i;\r
478 \r
479         v->fastpalette = true;\r
480         VL_SetPalette (&v->palette1[0][0], v);\r
481         VL_GetPalette (&v->palette2[0][0]);\r
482         if (_fmemcmp (&v->palette1[0][0],&v->palette2[0][0],768))\r
483                 v->fastpalette = false;\r
484 }\r
485 \r
486 \r
487 /*\r
488 =============================================================================\r
489 \r
490                                                         PIXEL OPS\r
491 \r
492 =============================================================================\r
493 */\r
494 \r
495 //byte  rightmasks[4] = {1,3,7,15};\r
496 \r
497 /*\r
498 =================\r
499 =\r
500 = VL_Plot\r
501 =\r
502 =================\r
503 */\r
504 \r
505 void VL_Plot (int x, int y, int color, global_game_variables_t *gvar)\r
506 {\r
507         byte mask;\r
508         VCLIPDEF\r
509 \r
510         mask = pclip[x&3];\r
511         VGAMAPMASK(mask);\r
512         //*(byte far *)MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+(gvar->video.ofs.ylookup[y]+(x>>2))) = color;\r
513         *(byte far *)MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+((y*gvar->video.page[0].stridew)+(x>>2))) = color;\r
514         VGAMAPMASK(15);\r
515 }\r
516 \r
517 \r
518 /*\r
519 =================\r
520 =\r
521 = VL_Hlin\r
522 =\r
523 =================\r
524 */\r
525 \r
526 void VL_Hlin    (unsigned x, unsigned y, unsigned width, unsigned color, global_game_variables_t *gvar)\r
527 {\r
528         unsigned                xbyte;\r
529         byte                    far *dest;\r
530         byte                    leftmask,rightmask;\r
531         int                             midbytes;\r
532 \r
533         LRCLIPDEF\r
534 \r
535         xbyte = x>>2;\r
536         leftmask = lclip[x&3];\r
537         rightmask = rclip[(x+width-1)&3];\r
538         midbytes = ((x+width+3)>>2) - xbyte - 2;\r
539 \r
540         //dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+gvar->video.ofs.ylookup[y]+xbyte);\r
541         dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+(y*gvar->video.page[0].stridew)+xbyte);\r
542 \r
543         if (midbytes<0)\r
544         {\r
545         // all in       one byte\r
546                 VGAMAPMASK(leftmask&rightmask);\r
547                 *dest = color;\r
548                 VGAMAPMASK(15);\r
549                 return;\r
550         }\r
551 \r
552         VGAMAPMASK(leftmask);\r
553         *dest++ = color;\r
554 \r
555         VGAMAPMASK(15);\r
556         _fmemset (dest,color,midbytes);\r
557         dest+=midbytes;\r
558 \r
559         VGAMAPMASK(rightmask);\r
560         *dest = color;\r
561 \r
562         VGAMAPMASK(15);\r
563 }\r
564 \r
565 \r
566 /*\r
567 =================\r
568 =\r
569 = VL_Vlin\r
570 =\r
571 =================\r
572 */\r
573 \r
574 void VL_Vlin    (int x, int y, int height, int color, global_game_variables_t *gvar)\r
575 {\r
576         byte    far *dest,mask;\r
577         VCLIPDEF\r
578 \r
579         mask = pclip[x&3];\r
580         VGAMAPMASK(mask);\r
581 \r
582         //dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+gvar->video.ofs.ylookup[y]+(x>>2));\r
583         dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+(y*gvar->video.page[0].stridew)+(x>>2));\r
584 \r
585         while (height--)\r
586         {\r
587                 *dest = color;\r
588                 dest += gvar->video.ofs.linewidth;\r
589         }\r
590 \r
591         VGAMAPMASK(15);\r
592 }\r
593 \r
594 \r
595 /*\r
596 =================\r
597 =\r
598 = VL_Bar\r
599 =\r
600 =================\r
601 */\r
602 \r
603 void VL_Bar (int x, int y, int width, int height, int color, global_game_variables_t *gvar)\r
604 {\r
605         byte    far *dest;\r
606         byte    leftmask,rightmask;\r
607         int             midbytes,linedelta;\r
608 \r
609         LRCLIPDEF\r
610 \r
611         leftmask = lclip[x&3];\r
612         rightmask = rclip[(x+width-1)&3];\r
613         midbytes = ((x+width+3)>>2) - (x>>2) - 2;\r
614         linedelta = gvar->video.ofs.linewidth-(midbytes+1);\r
615 \r
616         //dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+gvar->video.ofs.ylookup[y]+(x>>2));\r
617         dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+(y*gvar->video.page[0].stridew)+(x>>2));\r
618 \r
619         if (midbytes<0)\r
620         {\r
621         // all in       one byte\r
622                 VGAMAPMASK(leftmask&rightmask);\r
623                 while (height--)\r
624                 {\r
625                         *dest = color;\r
626                         dest += gvar->video.ofs.linewidth;\r
627                 }\r
628                 VGAMAPMASK(15);\r
629                 return;\r
630         }\r
631 \r
632         while (height--)\r
633         {\r
634                 VGAMAPMASK(leftmask);\r
635                 *dest++ = color;\r
636 \r
637                 VGAMAPMASK(15);\r
638                 _fmemset (dest,color,midbytes);\r
639                 dest+=midbytes;\r
640 \r
641                 VGAMAPMASK(rightmask);\r
642                 *dest = color;\r
643 \r
644                 dest+=linedelta;\r
645         }\r
646 \r
647         VGAMAPMASK(15);\r
648 }\r
649 \r
650 //==========================================================================\r
651 \r
652 /*\r
653 =================\r
654 =\r
655 = VL_MemToScreen\r
656 =\r
657 = Draws a block of data to the screen.\r
658 =\r
659 =================\r
660 */\r
661 \r
662 void VL_MemToScreen (byte far *source, int width, int height, int x, int y, global_game_variables_t *gvar)\r
663 {\r
664         byte    far *screen,far *dest,mask;\r
665         int             plane;\r
666 \r
667         width>>=2;\r
668         //dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+gvar->video.ofs.ylookup[y]+(x>>2));\r
669         dest = MK_FP(SCREENSEG,gvar->video.ofs.bufferofs+(y*gvar->video.page[0].stridew)+(x>>2));\r
670         mask = 1 << (x&3);\r
671 \r
672         for     (plane = 0; plane<4; plane++)\r
673         {\r
674                 VGAMAPMASK(mask);\r
675                 mask <<= 1;\r
676                 if (mask == 16)\r
677                         mask = 1;\r
678 \r
679                 screen = dest;\r
680                 for     (y=0;y<height;y++,screen+=gvar->video.ofs.linewidth,source+=width)\r
681                         _fmemcpy (screen,source,width);\r
682         }\r
683 }\r
684 \r
685 //==========================================================================\r
686 \r
687 /*\r
688 ==============\r
689 \r
690  VL_WaitVBL                     ******** NEW *********\r
691 \r
692  Wait for       the vertical retrace (returns before the actual vertical sync)\r
693 \r
694 ==============\r
695 */\r
696 \r
697 void VL_WaitVBL(word num)\r
698 {\r
699 //PROC  VL_WaitVBL  num:WORD\r
700 //PUBLIC        VL_WaitVBL\r
701 #ifdef __WATCOMC__\r
702         __asm {\r
703 #endif\r
704         wait:\r
705 #ifdef __BORLANDC__\r
706         __asm {\r
707 #endif\r
708 \r
709                 mov     dx,STATUS_REGISTER_1\r
710 \r
711                 mov     cx,[num]\r
712         //\r
713         // wait for     a display signal to make sure the raster isn't in       the middle\r
714         // of a sync\r
715         //\r
716 #ifdef __BORLANDC__\r
717         }\r
718 #endif\r
719         waitnosync:\r
720 #ifdef __BORLANDC__\r
721         __asm {\r
722 #endif\r
723                 in      al,dx\r
724                 test    al,8\r
725                 jnz     waitnosync\r
726 \r
727 \r
728 #ifdef __BORLANDC__\r
729         }\r
730 #endif\r
731         waitsync:\r
732 #ifdef __BORLANDC__\r
733         __asm {\r
734 #endif\r
735                 in      al,dx\r
736                 test    al,8\r
737                 jz      waitsync\r
738 \r
739                 loop    waitnosync\r
740 \r
741                 ret\r
742         }\r
743 }\r
744 \r
745 //===========================================================================\r
746 #if 0\r
747 #define VGAWRITEMODE(x) asm{\r
748                 cli\r
749                 mov     dx,GC_INDEX\r
750                 mov     al,GC_MODE\r
751                 out     dx,al\r
752                 inc     dx\r
753                 in      al,dx\r
754                 and     al,252\r
755                 or      al,x\r
756                 out     dx,al\r
757                 sti\r
758 }\r
759 \r
760 #define VGAMAPMASK(x) asm{\r
761                 cli\r
762                 mov     dx,SC_INDEX\r
763                 mov     al,SC_MAPMASK\r
764                 mov     ah,x\r
765                 out     dx,ax\r
766                 sti\r
767 }\r
768 \r
769 #define VGAREADMAP(x) asm{\r
770                 cli\r
771                 mov     dx,GC_INDEX\r
772                 mov     al,GC_READMAP\r
773                 mov     ah,x\r
774                 out     dx,ax\r
775                 sti\r
776 }\r
777 \r
778 #define EGABITMASK(x) asm{\r
779                 mov     dx,GC_INDEX\r
780                 mov     ax,GC_BITMASK+256*x\r
781                 out     dx,ax\r
782                 sti\r
783 }\r
784 #endif\r
785 void VGAWRITEMODE(byte x)\r
786 {\r
787         __asm {\r
788                 cli\r
789                 mov     dx,GC_INDEX\r
790                 mov     al,GC_MODE\r
791                 out     dx,al\r
792                 inc     dx\r
793                 in      al,dx\r
794                 and     al,252\r
795                 or      al,x\r
796                 out     dx,al\r
797                 sti\r
798         }\r
799 }\r
800 \r
801 void VGAMAPMASK(byte x)\r
802 {\r
803         __asm {\r
804                 cli\r
805                 mov     dx,SC_INDEX\r
806                 mov     al,SC_MAPMASK\r
807                 mov     ah,x\r
808                 out     dx,ax\r
809                 sti\r
810         }\r
811 }\r
812 \r
813 void VGAREADMAP(byte x)\r
814 {\r
815         __asm {\r
816                 cli\r
817                 mov     dx,GC_INDEX\r
818                 mov     al,GC_READMAP\r
819                 mov     ah,x\r
820                 out     dx,ax\r
821                 sti\r
822         }\r
823 }\r
824 \r
825 void VGABITMASK(byte x)\r
826 {\r
827         word q = 256*x;\r
828         __asm {\r
829                 mov     dx,GC_INDEX\r
830                 mov     ax,GC_BITMASK+q\r
831                 out     dx,ax\r
832                 sti\r
833         }\r
834 }\r
835 \r
836 //===========================================================================\r