]> icculus.org git repositories - btb/d2x.git/blob - arch/dos/dosgr.c
This commit was generated by cvs2svn to compensate for changes in r2,
[btb/d2x.git] / arch / dos / dosgr.c
1 // Graphics functions for DOS.
2
3 #include <stdio.h>
4 #include <string.h>
5 #include <io.h>
6 #include <dos.h>
7 #include <dpmi.h>
8 #include "gr.h"
9 #include "grdef.h"
10 #include "palette.h"
11 #include "maths.h"
12 #include "u_mem.h"
13 #include "u_dpmi.h"
14 #include "vesa.h"
15 #include "modex.h"
16 #include "error.h"
17
18 #include "gamefont.h"
19
20 #ifdef __DJGPP__
21 #include <sys/nearptr.h>
22 #endif
23
24 static int last_r=0, last_g=0, last_b=0;
25
26 /* old gr.c stuff */
27 unsigned char * gr_video_memory = (unsigned char *)0xa0000;
28
29 char gr_pal_default[768];
30
31 int gr_installed = 0;
32
33 volatile ubyte * pVideoMode =  (volatile ubyte *)0x449;
34 volatile ushort * pNumColumns = (volatile ushort *)0x44a;
35 volatile ubyte * pNumRows = (volatile ubyte *)0x484;
36 volatile ushort * pCharHeight = (volatile ushort *)0x485;
37 volatile ushort * pCursorPos = (volatile ushort *)0x450;
38 volatile ushort * pCursorType = (volatile ushort *)0x460;
39 volatile ushort * pTextMemory = (volatile ushort *)0xb8000;
40
41 typedef struct screen_save {
42         ubyte   video_mode;
43         ubyte   is_graphics;
44         ushort  char_height;
45         ubyte           width;
46         ubyte           height;
47         ubyte           cursor_x, cursor_y;
48         ubyte           cursor_sline, cursor_eline;
49         ushort * video_memory;
50 } screen_save;
51
52 screen_save gr_saved_screen;
53
54 int gr_show_screen_info = 0;
55
56 void gr_set_cellheight( ubyte height )
57 {
58         ubyte temp;
59
60    outp( 0x3d4, 9 );
61         temp = inp( 0x3d5 );
62    temp &= 0xE0;
63         temp |= height;
64         outp( 0x3d5, temp );
65 }
66
67 void gr_set_linear()
68 {
69         outpw( 0x3c4, 0xE04 );            // enable chain4 mode
70         outpw( 0x3d4, 0x4014 );           // turn on dword mode
71         outpw( 0x3d4, 0xa317 );           // turn off byte mode
72 }
73
74 void gr_16_to_256()
75 {
76         outpw( 0x3ce, 0x4005 );         // set Shift reg to 1
77
78         inp( 0x3da );                                   // dummy input
79
80         outp( 0x3c0, 0x30 );
81         outp( 0x3c0, 0x61 );               // turns on PCS & PCC
82
83         inp( 0x3da );                                   // dummy input
84
85         outp( 0x3c0, 0x33 );
86         outp( 0x3c0, 0 );
87 }
88
89 void gr_turn_screen_off()
90 {
91         ubyte temp;
92         temp = inp( 0x3da );
93         outp( 0x3c0, 0 );
94 }
95
96 void gr_turn_screen_on()
97 {
98         ubyte temp;
99         temp = inp( 0x3da );
100         outp( 0x3c0, 0x20 );
101 }
102
103 void gr_set_misc_mode( uint mode )
104 {
105         union REGS regs;
106
107         memset( &regs, 0, sizeof(regs) );
108         regs.w.ax = mode;
109         int386( 0x10, &regs, &regs );
110
111 }
112
113 void gr_set_3dbios_mode( uint mode )
114 {
115         union REGS regs;
116         memset( &regs, 0, sizeof(regs) );
117         regs.w.ax = 0x4fd0;
118         regs.w.bx = 0x3d00 | (mode & 0xff);
119         int386( 0x10, &regs, &regs );
120 }
121
122
123
124 void gr_set_text_25()
125 {
126         union REGS regs;
127
128         regs.w.ax = 3;
129         int386( 0x10, &regs, &regs );
130
131 }
132
133 void gr_set_text_43()
134 {
135         union REGS regs;
136
137         regs.w.ax = 0x1201;
138         regs.w.bx = 0x30;
139         int386( 0x10, &regs, &regs );
140
141         regs.w.ax = 3;
142         int386( 0x10, &regs, &regs );
143
144         regs.w.ax = 0x1112;
145         regs.w.bx = 0x0;
146         int386( 0x10, &regs, &regs );
147 }
148
149 void gr_set_text_50()
150 {
151         union REGS regs;
152
153         regs.w.ax = 0x1202;
154         regs.w.bx = 0x30;
155         int386( 0x10, &regs, &regs );
156
157         regs.w.ax = 3;
158         int386( 0x10, &regs, &regs );
159
160         regs.w.ax = 0x1112;
161         regs.w.bx = 0x0;
162         int386( 0x10, &regs, &regs );
163 }
164
165 ubyte is_graphics_mode()
166 {
167         byte tmp;
168         tmp = inp( 0x3DA );             // Reset flip-flip
169         outp( 0x3C0, 0x30 );            // Select attr register 10
170         tmp = inp( 0x3C1 );     // Get graphics/text bit
171         return tmp & 1;
172 }
173
174 void gr_setcursor(ubyte x, ubyte y, ubyte sline, ubyte eline)
175 {
176         union REGS regs;
177
178         memset( &regs, 0, sizeof(regs) );
179         regs.w.ax = 0x0200;
180         regs.w.bx = 0;
181         regs.h.dh = y;
182         regs.h.dl = x;
183         int386( 0x10, &regs, &regs );
184
185         memset( &regs, 0, sizeof(regs) );
186         regs.w.ax = 0x0100;
187         regs.h.ch = sline & 0xf;
188         regs.h.cl = eline & 0xf;
189         int386( 0x10, &regs, &regs );
190 }
191
192 void gr_getcursor(ubyte *x, ubyte *y, ubyte * sline, ubyte * eline)
193 {
194         union REGS regs;
195
196         memset( &regs, 0, sizeof(regs) );
197         regs.w.ax = 0x0300;
198         regs.w.bx = 0;
199         int386( 0x10, &regs, &regs );
200         *y = regs.h.dh;
201         *x = regs.h.dl;
202         *sline = regs.h.ch;
203         *eline = regs.h.cl;
204 }
205
206
207 int gr_save_mode()
208 {
209         int i;
210
211         gr_saved_screen.is_graphics = is_graphics_mode();
212         gr_saved_screen.video_mode = *pVideoMode;
213         
214         if (!gr_saved_screen.is_graphics)       {
215                 gr_saved_screen.width = *pNumColumns;
216                 gr_saved_screen.height = *pNumRows+1;
217                 gr_saved_screen.char_height = *pCharHeight;
218                 gr_getcursor(&gr_saved_screen.cursor_x, &gr_saved_screen.cursor_y, &gr_saved_screen.cursor_sline, &gr_saved_screen.cursor_eline );
219                 MALLOC(gr_saved_screen.video_memory,ushort, gr_saved_screen.width*gr_saved_screen.height );
220                 for (i=0; i < gr_saved_screen.width*gr_saved_screen.height; i++ )
221                         gr_saved_screen.video_memory[i] = pTextMemory[i];
222         }
223
224         if (gr_show_screen_info )       {
225                 printf( "Current video mode 0x%x:\n",  gr_saved_screen.video_mode );
226                 if (gr_saved_screen.is_graphics)
227                         printf( "Graphics mode\n" );
228                 else    {
229                         printf( "Text mode\n" );
230                         printf( "( %d columns by %d rows)\n", gr_saved_screen.width, gr_saved_screen.height );
231                         printf( "Char height is %d pixel rows\n", gr_saved_screen.char_height );
232                         printf( "Cursor of type 0x%x,0x%x is at (%d, %d)\n", gr_saved_screen.cursor_sline, gr_saved_screen.cursor_eline,gr_saved_screen.cursor_x, gr_saved_screen.cursor_y );
233                 }
234         }
235
236         return 0;
237 }
238
239 int isvga()
240 {
241         union REGS regs;
242
243         memset( &regs, 0, sizeof(regs) );
244         regs.w.ax = 0x1a00;
245         int386( 0x10, &regs, &regs );
246
247         if ( regs.h.al == 0x1a )
248                  return 1;
249
250         return 0;
251 }
252
253 void gr_restore_mode()
254 {
255         int i;
256
257         //gr_set_text_25(); 
258
259 #ifndef NOGRAPH
260         gr_palette_fade_out( gr_palette, 32, 0 );
261         gr_palette_set_gamma(0);
262         if ( gr_saved_screen.video_mode == 3 )  {
263                 switch( gr_saved_screen.height )          {
264                 case 43:        gr_set_text_43(); break;
265                 case 50:        gr_set_text_50(); break;
266                 default:        gr_set_text_25(); break;
267                 }
268         } else {
269                 gr_set_misc_mode(gr_saved_screen.video_mode);   
270         }
271         if (gr_saved_screen.is_graphics==0)     {
272                 gr_sync_display();
273                 gr_sync_display();
274                 gr_palette_read( gr_pal_default );
275                 gr_palette_clear();
276                 for (i=0; i < gr_saved_screen.width*gr_saved_screen.height; i++ )
277                         pTextMemory[i]=gr_saved_screen.video_memory[i];
278                 gr_setcursor( gr_saved_screen.cursor_x, gr_saved_screen.cursor_y, gr_saved_screen.cursor_sline, gr_saved_screen.cursor_eline );
279                 gr_palette_faded_out = 1;
280                 gr_palette_fade_in( gr_pal_default, 32, 0 );
281         }
282 #endif
283
284 }
285
286 void gr_close()
287 {
288         if (gr_installed==1)
289         {
290                 gr_installed = 0;
291                 gr_restore_mode();
292                 free(grd_curscreen);
293                 if( gr_saved_screen.video_memory ) {
294                         free(gr_saved_screen.video_memory);
295                         gr_saved_screen.video_memory = NULL;
296                 }
297         }
298 }
299
300 #ifndef __DJGPP__
301 int gr_vesa_setmode( int mode )
302 {
303         int retcode;
304
305         retcode=gr_vesa_checkmode( mode );
306         if ( retcode ) return retcode;
307
308         return gr_vesa_setmodea( mode );
309 }
310 #endif
311
312
313 int gr_set_mode(u_int32_t mode)
314 {
315         int retcode;
316         unsigned int w,h,t,data, r;
317
318         //JOHNgr_disable_default_palette_loading();
319 #ifdef NOGRAPH
320 return 0;
321 #endif
322         switch(mode)
323         {
324         case SM_ORIGINAL:
325                 return 0;
326         case SM(320,200)://0:
327                 if (!isvga()) return 1;
328                 gr_set_misc_mode(0x13);
329                 w = 320; r = 320; h = 200; t=BM_LINEAR; data = (int)gr_video_memory;
330                 break;
331         case SM(640,400)://SM_640x400V:
332                 retcode = gr_vesa_setmode( 0x100 ); 
333                 if (retcode !=0 ) return retcode;
334                 w = 640; r = 640; h = 400; t=BM_SVGA; data = 0;
335                 break;
336         case SM(640,480)://SM_640x480V:
337                 retcode = gr_vesa_setmode( 0x101 ); 
338                 if (retcode !=0 ) return retcode;
339                 w = 640; r = 640; h = 480; t=BM_SVGA; data = 0;
340                 break;
341         case SM(800,600)://SM_800x600V:
342                 retcode = gr_vesa_setmode( 0x103 ); 
343                 if (retcode !=0 ) return retcode;
344                 w = 800; r = 800; h = 600; t=BM_SVGA; data = 0;
345                 break;
346         case SM(1024,768)://SM_1024x768V:
347                 retcode = gr_vesa_setmode( 0x105 ); 
348                 if (retcode !=0 ) return retcode;
349                 w = 1024; r = 1024; h = 768; t=BM_SVGA; data = 0;
350                 break;
351 /*      case SM_640x480V15:
352                 retcode = gr_vesa_setmode( 0x110 ); 
353                 if (retcode !=0 ) return retcode;
354                 w = 640; r = 640*2; h=480; t=BM_SVGA15; data = 0;
355                 break;
356         case SM_800x600V15:
357                 retcode = gr_vesa_setmode( 0x113 ); 
358                 if (retcode !=0 ) return retcode;
359                 w = 800; r = 800*2; h=600; t=BM_SVGA15; data = 0;
360                 break;*/
361 //      case 19:
362         case SM(320,100):
363                 if (!isvga()) return 1;
364                 gr_set_misc_mode(0x13); 
365 //              {
366 //                      ubyte x;
367 //                      x = inp( 0x3c5 );
368 //                      x |= 8;
369 //                      outp( 0x3c5, x );
370 //              }
371                 gr_set_cellheight( 3 );
372
373                 w = 320; r = 320; h = 100; t=BM_LINEAR; data = (int)gr_video_memory;
374                 break;
375 /*      case 20:
376                 retcode = gr_vesa_setmode( 0x102 ); 
377                 //gr_enable_default_palette_loading();
378                 if (retcode !=0 ) return retcode;
379                 gr_16_to_256();
380                 gr_set_linear();
381                 //gr_set_cellheight( 1 );
382                 gr_vesa_setlogical( 400 );
383                 w = 400; r = 400; h = 600; t=BM_SVGA; data = 0;
384                 break;
385         case 21:
386                 if (!isvga()) return 1;
387                 gr_set_misc_mode(0xd);  
388                 gr_16_to_256();
389                 gr_set_linear();
390                 gr_set_cellheight( 3 );
391                 w = 160; r = 160; h = 100; t=BM_LINEAR; data = (int)gr_video_memory;
392                 break;
393         case //22:                      // 3dmax 320x400
394                 if (!isvga()) return 1;
395                 gr_set_3dbios_mode(0x31);
396                 //w = 320; r = 320/4; h = 400; t=BM_MODEX; data = 0;
397                 w = 320; r = 320; h = 400; t=BM_SVGA; data = 0;
398                 break;*/
399         default:
400                 if (!isvga()) return 1;
401                 if (mode==SM(320,240))
402                         w = gr_modex_setmode( 2 );
403                 else if (mode==SM(320,400))
404                         w = gr_modex_setmode( 6 );
405                 else
406                         Error("unhandled vid mode\n");
407                 //gr_enable_default_palette_loading();
408                 h = w & 0xffff; w = w >> 16; r = w / 4;t = BM_MODEX; data = 0;
409                 break;
410         }
411         gr_palette_clear();
412
413         memset( grd_curscreen, 0, sizeof(grs_screen));
414         grd_curscreen->sc_mode = mode;
415         grd_curscreen->sc_w = w;
416         grd_curscreen->sc_h = h;
417         grd_curscreen->sc_aspect = fixdiv(grd_curscreen->sc_w*3,grd_curscreen->sc_h*4);
418         grd_curscreen->sc_canvas.cv_bitmap.bm_x = 0;
419         grd_curscreen->sc_canvas.cv_bitmap.bm_y = 0;
420         grd_curscreen->sc_canvas.cv_bitmap.bm_w = w;
421         grd_curscreen->sc_canvas.cv_bitmap.bm_h = h;
422         grd_curscreen->sc_canvas.cv_bitmap.bm_rowsize = r;
423         grd_curscreen->sc_canvas.cv_bitmap.bm_type = t;
424         grd_curscreen->sc_canvas.cv_bitmap.bm_data = (unsigned char *)data;
425         gr_set_current_canvas(NULL);
426
427         //gr_enable_default_palette_loading();
428         gamefont_choose_game_font(w,h);
429
430         return 0;
431 }
432
433 int gr_init(int mode)
434 {
435         int org_gamma;
436         int retcode;
437
438         // Only do this function once!
439         if (gr_installed==1)
440                 return 1;
441
442 #ifdef __DJGPP__
443         if (!__djgpp_nearptr_enable()) {
444                 printf("nearptr enable=%x\n", __dpmi_error);
445                 return 10;
446         }
447 #ifndef SAVEGR
448         gr_video_memory = (unsigned char *)(__djgpp_conventional_base + 0xa0000);
449 #else
450         gr_video_memory=(unsigned char *)-1;
451 #endif
452         pVideoMode =  (volatile ubyte *)(__djgpp_conventional_base+0x449);
453         pNumColumns = (volatile ushort *)(__djgpp_conventional_base+0x44a);
454         pNumRows = (volatile ubyte *)(__djgpp_conventional_base+0x484);
455         pCharHeight = (volatile ushort *)(__djgpp_conventional_base+0x485);
456         pCursorPos = (volatile ushort *)(__djgpp_conventional_base+0x450);
457         pCursorType = (volatile ushort *)(__djgpp_conventional_base+0x460);
458         pTextMemory = (volatile ushort *)(__djgpp_conventional_base+0xb8000);
459 #endif
460 #ifndef __DJGPP__
461         if (gr_init_A0000())
462                 return 10;
463 #endif
464
465         // Save the current text screen mode
466         if (gr_save_mode()==1)
467                 return 1;
468
469 #ifndef NOGRAPH
470         // Save the current palette, and fade it out to black.
471         gr_palette_read( gr_pal_default );
472         gr_palette_faded_out = 0;
473         org_gamma = gr_palette_get_gamma();
474         gr_palette_set_gamma( 0 );
475         gr_palette_fade_out( gr_pal_default, 32, 0 );
476         gr_palette_clear();
477         gr_palette_set_gamma( org_gamma );
478         gr_sync_display();
479         gr_sync_display();
480 #endif
481
482 #ifdef __DJGPP__
483 #ifdef SAVEGR
484         __djgpp_nearptr_disable();
485 #endif
486 #endif
487
488         MALLOC( grd_curscreen,grs_screen,1 );
489         memset( grd_curscreen, 0, sizeof(grs_screen));
490
491         // Set the mode.
492         if ((retcode=gr_set_mode(mode)))
493         {
494                 gr_restore_mode();
495                 return retcode;
496         }
497         //JOHNgr_disable_default_palette_loading();
498
499         // Set all the screen, canvas, and bitmap variables that
500         // aren't set by the gr_set_mode call:
501         grd_curscreen->sc_canvas.cv_color = 0;
502         grd_curscreen->sc_canvas.cv_drawmode = 0;
503         grd_curscreen->sc_canvas.cv_font = NULL;
504         grd_curscreen->sc_canvas.cv_font_fg_color = 0;
505         grd_curscreen->sc_canvas.cv_font_bg_color = 0;
506         gr_set_current_canvas( &grd_curscreen->sc_canvas );
507
508 #if 0
509         if (!dpmi_allocate_selector( &gr_fade_table, 256*GR_FADE_LEVELS, &gr_fade_table_selector ))
510                 Error( "Error allocating fade table selector!" );
511
512         if (!dpmi_allocate_selector( &gr_palette, 256*3, &gr_palette_selector ))
513                 Error( "Error allocating palette selector!" );
514 #endif
515
516 //      if (!dpmi_allocate_selector( &gr_inverse_table, 32*32*32, &gr_inverse_table_selector ))
517 //              Error( "Error allocating inverse table selector!" );
518
519
520         // Set flags indicating that this is installed.
521         gr_installed = 1;
522 #ifdef __GNUC__
523
524         atexit((void (*)) gr_close);
525 #else
526         atexit(gr_close);
527 #endif
528         return 0;
529 }
530
531 int gr_mode13_checkmode()
532 {
533         if (isvga()) 
534                 return 0;
535         else
536                 return 1;
537 }
538
539 //  0=Mode set OK
540 //  1=No VGA adapter installed
541 //  2=Program doesn't support this VESA granularity
542 //  3=Monitor doesn't support that VESA mode.:
543 //  4=Video card doesn't support that VESA mode.
544 //  5=No VESA driver found.
545 //  6=Bad Status after VESA call/
546 //  7=Not enough DOS memory to call VESA functions.
547 //  8=Error using DPMI.
548 //  9=Error setting logical line width.
549 // 10=Error allocating selector for A0000h
550 // 11=Not a valid mode support by gr.lib
551
552 int gr_check_mode(u_int32_t mode)
553 {
554         switch(mode)
555         {
556         case SM(320,100)://19:
557         case SM(320,200):
558         case SM(320,240):
559         case SM(360,200):
560         case SM(360,240):
561         case SM(376,282):
562         case SM(320,400):
563         case SM(320,480):
564         case SM(360,400):
565         case SM(360,480):
566         case SM(360,360):
567         case SM(376,308):
568         case SM(376,564):               return gr_mode13_checkmode();
569         case SM(640,400):               return gr_vesa_checkmode( 0x100 ); 
570         case SM(640,480):       return gr_vesa_checkmode( 0x101 ); 
571         case SM(800,600):       return gr_vesa_checkmode( 0x103 ); 
572         case SM(1024,768):      return gr_vesa_setmode( 0x105 ); 
573 //      case SM_640x480V15:     return gr_vesa_setmode( 0x110 ); 
574 //      case SM_800x600V15:     return gr_vesa_setmode( 0x113 ); 
575         }
576         return 11;
577 }
578
579 /* Palette Stuff Starts Here... */
580
581 void gr_palette_step_up( int r, int g, int b )
582 {
583         int i;
584         ubyte *p;
585         int temp;
586
587         if (gr_palette_faded_out) return;
588
589         if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
590
591         last_r = r; last_g = g; last_b = b;
592
593         outp( 0x3c6, 0xff );
594         outp( 0x3c8, 0 );
595         p=gr_palette;
596
597         for (i=0; i<256; i++ )  {
598                 temp = (int)(*p++) + r + gr_palette_gamma;
599                 if (temp<0) temp=0;
600                 else if (temp>63) temp=63;
601                 outp( 0x3c9, temp );
602                 temp = (int)(*p++) + g + gr_palette_gamma;
603                 if (temp<0) temp=0;
604                 else if (temp>63) temp=63;
605                 outp( 0x3c9, temp );
606                 temp = (int)(*p++) + b + gr_palette_gamma;
607                 if (temp<0) temp=0;
608                 else if (temp>63) temp=63;
609                 outp( 0x3c9, temp );
610         }
611 }
612
613
614 void gr_palette_clear()
615 {
616         int i;
617         outp( 0x3c6, 0xff );
618         outp( 0x3c8, 0 );
619         for (i=0; i<768; i++ )  {
620                 outp( 0x3c9, 0 );
621         }
622         gr_palette_faded_out = 1;
623 }
624
625 void gr_palette_load( ubyte * pal )
626 {
627         int i;
628         ubyte c;
629         outp( 0x3c6, 0xff );
630         outp( 0x3c8, 0 );
631         for (i=0; i<768; i++ )  {
632                 c = pal[i] + gr_palette_gamma;
633                 if ( c > 63 ) c = 63;
634                 outp( 0x3c9,c);
635                 gr_current_pal[i] = pal[i];
636         }
637         gr_palette_faded_out = 0;
638
639         init_computed_colors();
640 }
641
642
643 int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys )
644 {
645         ubyte c;
646         int i,j;
647         fix fade_palette[768];
648         fix fade_palette_delta[768];
649
650         if (gr_palette_faded_out) return 0;
651
652         if (!pal)
653                 pal = gr_current_pal;
654
655         for (i=0; i<768; i++ )  {
656                 fade_palette[i] = i2f(pal[i]+gr_palette_gamma);
657                 fade_palette_delta[i] = fade_palette[i] / nsteps;
658         }
659
660         for (j=0; j<nsteps; j++ )       {
661                 gr_sync_display();
662                 outp( 0x3c6, 0xff );
663                 outp( 0x3c8, 0 );
664                 for (i=0; i<768; i++ )  {
665                         fade_palette[i] -= fade_palette_delta[i];
666                         if (fade_palette[i] < 0 )
667                                 fade_palette[i] = 0;
668                         c = f2i(fade_palette[i]);
669                         if ( c > 63 ) c = 63;
670                         outp( 0x3c9, c );
671                 }
672         }
673         gr_palette_faded_out = 1;
674         return 0;
675 }
676
677 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
678 {
679         int i,j;
680         ubyte c;
681         fix fade_palette[768];
682         fix fade_palette_delta[768];
683
684
685         if (!gr_palette_faded_out) return 0;
686
687         for (i=0; i<768; i++ )  {
688                 gr_current_pal[i] = pal[i];
689                 fade_palette[i] = 0;
690                 fade_palette_delta[i] = i2f(pal[i]+gr_palette_gamma) / nsteps;
691         }
692
693         for (j=0; j<nsteps; j++ )       {
694                 gr_sync_display();
695                 outp( 0x3c6, 0xff );
696                 outp( 0x3c8, 0 );
697                 for (i=0; i<768; i++ )  {
698                         fade_palette[i] += fade_palette_delta[i];
699                         if (fade_palette[i] > i2f(pal[i]+gr_palette_gamma) )
700                                 fade_palette[i] = i2f(pal[i]+gr_palette_gamma);
701                         c = f2i(fade_palette[i]);
702                         if ( c > 63 ) c = 63;
703                         outp( 0x3c9, c );
704                 }
705         }
706         gr_palette_faded_out = 0;
707         return 0;
708 }
709
710 void gr_palette_read(ubyte * palette)
711 {
712         int i;
713         outp( 0x3c6, 0xff );
714         outp( 0x3c7, 0 );
715         for (i=0; i<768; i++ )  {
716                 *palette++ = inp( 0x3c9 );
717         }
718 }
719
720 void gr_update(void)
721 { }