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