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