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