3 * Graphics functions for DOS.
27 #include <sys/nearptr.h>
31 static int last_r=0, last_g=0, last_b=0;
34 unsigned char * gr_video_memory = (unsigned char *)0xa0000;
36 char gr_pal_default[768];
38 int vid_installed = 0;
40 volatile ubyte * pVideoMode = (volatile ubyte *)0x449;
41 volatile ushort * pNumColumns = (volatile ushort *)0x44a;
42 volatile ubyte * pNumRows = (volatile ubyte *)0x484;
43 volatile ushort * pCharHeight = (volatile ushort *)0x485;
44 volatile ushort * pCursorPos = (volatile ushort *)0x450;
45 volatile ushort * pCursorType = (volatile ushort *)0x460;
46 volatile ushort * pTextMemory = (volatile ushort *)0xb8000;
48 typedef struct screen_save {
54 ubyte cursor_x, cursor_y;
55 ubyte cursor_sline, cursor_eline;
56 ushort * video_memory;
59 screen_save gr_saved_screen;
61 int gr_show_screen_info = 0;
62 uint32_t Vid_current_mode;
65 void gr_set_cellheight( ubyte height )
78 outpw( 0x3c4, 0xE04 ); // enable chain4 mode
79 outpw( 0x3d4, 0x4014 ); // turn on dword mode
80 outpw( 0x3d4, 0xa317 ); // turn off byte mode
85 outpw( 0x3ce, 0x4005 ); // set Shift reg to 1
87 inp( 0x3da ); // dummy input
90 outp( 0x3c0, 0x61 ); // turns on PCS & PCC
92 inp( 0x3da ); // dummy input
98 void gr_turn_screen_off()
105 void gr_turn_screen_on()
112 void gr_set_misc_mode( uint mode )
116 memset( ®s, 0, sizeof(regs) );
118 int386( 0x10, ®s, ®s );
122 void gr_set_3dbios_mode( uint mode )
125 memset( ®s, 0, sizeof(regs) );
127 regs.w.bx = 0x3d00 | (mode & 0xff);
128 int386( 0x10, ®s, ®s );
133 void gr_set_text_25()
138 int386( 0x10, ®s, ®s );
142 void gr_set_text_43()
148 int386( 0x10, ®s, ®s );
151 int386( 0x10, ®s, ®s );
155 int386( 0x10, ®s, ®s );
158 void gr_set_text_50()
164 int386( 0x10, ®s, ®s );
167 int386( 0x10, ®s, ®s );
171 int386( 0x10, ®s, ®s );
174 ubyte is_graphics_mode()
177 tmp = inp( 0x3DA ); // Reset flip-flip
178 outp( 0x3C0, 0x30 ); // Select attr register 10
179 tmp = inp( 0x3C1 ); // Get graphics/text bit
183 void gr_setcursor(ubyte x, ubyte y, ubyte sline, ubyte eline)
187 memset( ®s, 0, sizeof(regs) );
192 int386( 0x10, ®s, ®s );
194 memset( ®s, 0, sizeof(regs) );
196 regs.h.ch = sline & 0xf;
197 regs.h.cl = eline & 0xf;
198 int386( 0x10, ®s, ®s );
201 void gr_getcursor(ubyte *x, ubyte *y, ubyte * sline, ubyte * eline)
205 memset( ®s, 0, sizeof(regs) );
208 int386( 0x10, ®s, ®s );
220 gr_saved_screen.is_graphics = is_graphics_mode();
221 gr_saved_screen.video_mode = *pVideoMode;
223 if (!gr_saved_screen.is_graphics) {
224 gr_saved_screen.width = *pNumColumns;
225 gr_saved_screen.height = *pNumRows+1;
226 gr_saved_screen.char_height = *pCharHeight;
227 gr_getcursor(&gr_saved_screen.cursor_x, &gr_saved_screen.cursor_y, &gr_saved_screen.cursor_sline, &gr_saved_screen.cursor_eline );
228 MALLOC(gr_saved_screen.video_memory,ushort, gr_saved_screen.width*gr_saved_screen.height );
229 for (i=0; i < gr_saved_screen.width*gr_saved_screen.height; i++ )
230 gr_saved_screen.video_memory[i] = pTextMemory[i];
233 if (gr_show_screen_info ) {
234 printf( "Current video mode 0x%x:\n", gr_saved_screen.video_mode );
235 if (gr_saved_screen.is_graphics)
236 printf( "Graphics mode\n" );
238 printf( "Text mode\n" );
239 printf( "( %d columns by %d rows)\n", gr_saved_screen.width, gr_saved_screen.height );
240 printf( "Char height is %d pixel rows\n", gr_saved_screen.char_height );
241 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 );
252 memset( ®s, 0, sizeof(regs) );
254 int386( 0x10, ®s, ®s );
256 if ( regs.h.al == 0x1a )
262 void gr_restore_mode()
269 gr_palette_fade_out( gr_palette, 32, 0 );
270 gr_palette_set_gamma(0);
271 if ( gr_saved_screen.video_mode == 3 ) {
272 switch( gr_saved_screen.height ) {
273 case 43: gr_set_text_43(); break;
274 case 50: gr_set_text_50(); break;
275 default: gr_set_text_25(); break;
278 gr_set_misc_mode(gr_saved_screen.video_mode);
280 if (gr_saved_screen.is_graphics==0) {
283 gr_palette_read( gr_pal_default );
285 for (i=0; i < gr_saved_screen.width*gr_saved_screen.height; i++ )
286 pTextMemory[i]=gr_saved_screen.video_memory[i];
287 gr_setcursor( gr_saved_screen.cursor_x, gr_saved_screen.cursor_y, gr_saved_screen.cursor_sline, gr_saved_screen.cursor_eline );
288 gr_palette_faded_out = 1;
289 gr_palette_fade_in( gr_pal_default, 32, 0 );
298 if (vid_installed == 1) {
302 if( gr_saved_screen.video_memory ) {
303 free(gr_saved_screen.video_memory);
304 gr_saved_screen.video_memory = NULL;
310 int gr_vesa_setmode( int mode )
314 retcode=gr_vesa_checkmode( mode );
315 if ( retcode ) return retcode;
317 return gr_vesa_setmodea( mode );
322 int vid_set_mode(uint32_t mode)
325 unsigned int w,h,t,data, r;
327 //JOHNgr_disable_default_palette_loading();
335 case SM(320,200)://0:
336 if (!isvga()) return 1;
337 gr_set_misc_mode(0x13);
338 w = 320; r = 320; h = 200; t=BM_LINEAR; data = (int)gr_video_memory;
340 case SM(640,400)://SM_640x400V:
341 retcode = gr_vesa_setmode( 0x100 );
342 if (retcode !=0 ) return retcode;
343 w = 640; r = 640; h = 400; t=BM_SVGA; data = 0;
345 case SM(640,480)://SM_640x480V:
346 retcode = gr_vesa_setmode( 0x101 );
347 if (retcode !=0 ) return retcode;
348 w = 640; r = 640; h = 480; t=BM_SVGA; data = 0;
350 case SM(800,600)://SM_800x600V:
351 retcode = gr_vesa_setmode( 0x103 );
352 if (retcode !=0 ) return retcode;
353 w = 800; r = 800; h = 600; t=BM_SVGA; data = 0;
355 case SM(1024,768)://SM_1024x768V:
356 retcode = gr_vesa_setmode( 0x105 );
357 if (retcode !=0 ) return retcode;
358 w = 1024; r = 1024; h = 768; t=BM_SVGA; data = 0;
360 /* case SM_640x480V15:
361 retcode = gr_vesa_setmode( 0x110 );
362 if (retcode !=0 ) return retcode;
363 w = 640; r = 640*2; h=480; t=BM_SVGA15; data = 0;
366 retcode = gr_vesa_setmode( 0x113 );
367 if (retcode !=0 ) return retcode;
368 w = 800; r = 800*2; h=600; t=BM_SVGA15; data = 0;
372 if (!isvga()) return 1;
373 gr_set_misc_mode(0x13);
380 gr_set_cellheight( 3 );
382 w = 320; r = 320; h = 100; t=BM_LINEAR; data = (int)gr_video_memory;
385 retcode = gr_vesa_setmode( 0x102 );
386 //gr_enable_default_palette_loading();
387 if (retcode !=0 ) return retcode;
390 //gr_set_cellheight( 1 );
391 gr_vesa_setlogical( 400 );
392 w = 400; r = 400; h = 600; t=BM_SVGA; data = 0;
395 if (!isvga()) return 1;
396 gr_set_misc_mode(0xd);
399 gr_set_cellheight( 3 );
400 w = 160; r = 160; h = 100; t=BM_LINEAR; data = (int)gr_video_memory;
402 case //22: // 3dmax 320x400
403 if (!isvga()) return 1;
404 gr_set_3dbios_mode(0x31);
405 //w = 320; r = 320/4; h = 400; t=BM_MODEX; data = 0;
406 w = 320; r = 320; h = 400; t=BM_SVGA; data = 0;
409 if (!isvga()) return 1;
410 if (mode==SM(320,240))
411 w = gr_modex_setmode( 2 );
412 else if (mode==SM(320,400))
413 w = gr_modex_setmode( 6 );
415 Error("unhandled vid mode\n");
416 //gr_enable_default_palette_loading();
417 h = w & 0xffff; w = w >> 16; r = w / 4;t = BM_MODEX; data = 0;
422 Vid_current_mode = mode;
424 return gr_init_screen(BM_LINEAR, w, h, 0, 0, r, (unsigned char *)data);
432 int mode = SM(320,200);
434 // Only do this function once!
435 if (vid_installed == 1)
439 if (!__djgpp_nearptr_enable()) {
440 printf("nearptr enable=%x\n", __dpmi_error);
444 gr_video_memory = (unsigned char *)(__djgpp_conventional_base + 0xa0000);
446 gr_video_memory=(unsigned char *)-1;
448 pVideoMode = (volatile ubyte *)(__djgpp_conventional_base+0x449);
449 pNumColumns = (volatile ushort *)(__djgpp_conventional_base+0x44a);
450 pNumRows = (volatile ubyte *)(__djgpp_conventional_base+0x484);
451 pCharHeight = (volatile ushort *)(__djgpp_conventional_base+0x485);
452 pCursorPos = (volatile ushort *)(__djgpp_conventional_base+0x450);
453 pCursorType = (volatile ushort *)(__djgpp_conventional_base+0x460);
454 pTextMemory = (volatile ushort *)(__djgpp_conventional_base+0xb8000);
461 // Save the current text screen mode
462 if (gr_save_mode()==1)
466 // Save the current palette, and fade it out to black.
467 gr_palette_read( gr_pal_default );
468 gr_palette_faded_out = 0;
469 org_gamma = gr_palette_get_gamma();
470 gr_palette_set_gamma( 0 );
471 gr_palette_fade_out( gr_pal_default, 32, 0 );
473 gr_palette_set_gamma( org_gamma );
480 __djgpp_nearptr_disable();
484 MALLOC( grd_curscreen,grs_screen,1 );
485 memset( grd_curscreen, 0, sizeof(grs_screen));
488 if ((retcode = vid_set_mode(mode))) {
492 //JOHNgr_disable_default_palette_loading();
494 // Set all the screen, canvas, and bitmap variables that
495 // aren't set by the vid_set_mode call:
496 grd_curscreen->sc_canvas.cv_color = 0;
497 grd_curscreen->sc_canvas.cv_drawmode = 0;
498 grd_curscreen->sc_canvas.cv_font = NULL;
499 grd_curscreen->sc_canvas.cv_font_fg_color = 0;
500 grd_curscreen->sc_canvas.cv_font_bg_color = 0;
501 gr_set_current_canvas( &grd_curscreen->sc_canvas );
504 if (!dpmi_allocate_selector( &gr_fade_table, 256*GR_FADE_LEVELS, &gr_fade_table_selector ))
505 Error( "Error allocating fade table selector!" );
507 if (!dpmi_allocate_selector( &gr_palette, 256*3, &gr_palette_selector ))
508 Error( "Error allocating palette selector!" );
511 // if (!dpmi_allocate_selector( &gr_inverse_table, 32*32*32, &gr_inverse_table_selector ))
512 // Error( "Error allocating inverse table selector!" );
515 // Set flags indicating that this is installed.
519 atexit((void (*)) vid_close);
526 int gr_mode13_checkmode()
535 // 1=No VGA adapter installed
536 // 2=Program doesn't support this VESA granularity
537 // 3=Monitor doesn't support that VESA mode.:
538 // 4=Video card doesn't support that VESA mode.
539 // 5=No VESA driver found.
540 // 6=Bad Status after VESA call/
541 // 7=Not enough DOS memory to call VESA functions.
542 // 8=Error using DPMI.
543 // 9=Error setting logical line width.
544 // 10=Error allocating selector for A0000h
545 // 11=Not a valid mode support by gr.lib
547 int vid_check_mode(uint32_t mode)
551 case SM(320,100)://19:
563 case SM(376,564): return gr_mode13_checkmode();
564 case SM(640,400): return gr_vesa_checkmode( 0x100 );
565 case SM(640,480): return gr_vesa_checkmode( 0x101 );
566 case SM(800,600): return gr_vesa_checkmode( 0x103 );
567 case SM(1024,768): return gr_vesa_setmode( 0x105 );
568 // case SM_640x480V15: return gr_vesa_setmode( 0x110 );
569 // case SM_800x600V15: return gr_vesa_setmode( 0x113 );
574 /* Palette Stuff Starts Here... */
576 void gr_palette_step_up( int r, int g, int b )
582 if (gr_palette_faded_out) return;
584 if ( (r==last_r) && (g==last_g) && (b==last_b) ) return;
586 last_r = r; last_g = g; last_b = b;
592 for (i=0; i<256; i++ ) {
593 temp = (int)(*p++) + r + gr_palette_gamma.intval;
595 else if (temp>63) temp=63;
597 temp = (int)(*p++) + g + gr_palette_gamma.intval;
599 else if (temp>63) temp=63;
601 temp = (int)(*p++) + b + gr_palette_gamma.intval;
603 else if (temp>63) temp=63;
609 void gr_palette_clear()
614 for (i=0; i<768; i++ ) {
617 gr_palette_faded_out = 1;
620 void gr_palette_load( ubyte * pal )
626 for (i=0; i<768; i++ ) {
627 c = pal[i] + gr_palette_gamma.intval;
628 if ( c > 63 ) c = 63;
630 gr_current_pal[i] = pal[i];
632 gr_palette_faded_out = 0;
634 init_computed_colors();
638 int gr_palette_fade_out(ubyte *pal, int nsteps, int allow_keys )
642 fix fade_palette[768];
643 fix fade_palette_delta[768];
645 if (gr_palette_faded_out) return 0;
648 pal = gr_current_pal;
650 for (i=0; i<768; i++ ) {
651 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
652 fade_palette_delta[i] = fade_palette[i] / nsteps;
655 for (j=0; j<nsteps; j++ ) {
659 for (i=0; i<768; i++ ) {
660 fade_palette[i] -= fade_palette_delta[i];
661 if (fade_palette[i] < 0 )
663 c = f2i(fade_palette[i]);
664 if ( c > 63 ) c = 63;
668 gr_palette_faded_out = 1;
672 int gr_palette_fade_in(ubyte *pal, int nsteps, int allow_keys)
676 fix fade_palette[768];
677 fix fade_palette_delta[768];
680 if (!gr_palette_faded_out) return 0;
682 for (i=0; i<768; i++ ) {
683 gr_current_pal[i] = pal[i];
685 fade_palette_delta[i] = i2f(pal[i] + gr_palette_gamma.intval) / nsteps;
688 for (j=0; j<nsteps; j++ ) {
692 for (i=0; i<768; i++ ) {
693 fade_palette[i] += fade_palette_delta[i];
694 if (fade_palette[i] > i2f(pal[i] + gr_palette_gamma.intval))
695 fade_palette[i] = i2f(pal[i] + gr_palette_gamma.intval);
696 c = f2i(fade_palette[i]);
697 if ( c > 63 ) c = 63;
701 gr_palette_faded_out = 0;
705 void gr_palette_read(ubyte * palette)
710 for (i=0; i<768; i++ ) {
711 *palette++ = inp( 0x3c9 );
716 void vid_update(void)