FreeBASIC  0.91.0
gfx_driver_modex.c
Go to the documentation of this file.
1 /* Mode X gfx driver
2  * Mode X setting code derived from original Michael Abrash article in
3  * Dr. Dobb's Journal/Graphics Programming Black Book
4  */
5 
6 #include "../fb_gfx.h"
7 #include "fb_gfx_dos.h"
8 #include "vga.h"
9 #include <pc.h>
10 #include <go32.h>
11 #include <sys/farptr.h>
12 
13 static int driver_init(char *title, int w, int h, int depth, int refresh_rate, int flags);
14 static void driver_update(void);
15 static void end_of_driver_update(void);
16 static int *driver_fetch_modes(int depth, int *size);
17 
19 {
20  "ModeX", /* char *name; */
21  driver_init, /* int (*init)(char *title, int w, int h, int depth, int refresh_rate, int flags); */
22  fb_dos_exit, /* void (*exit)(void); */
23  fb_dos_lock, /* void (*lock)(void); */
24  fb_dos_unlock, /* void (*unlock)(void); */
25  fb_dos_set_palette, /* void (*set_palette)(int index, int r, int g, int b); */
26  fb_dos_vga_wait_vsync, /* void (*wait_vsync)(void); */
27  fb_dos_get_mouse, /* int (*get_mouse)(int *x, int *y, int *z, int *buttons, int *clip); */
28  fb_dos_set_mouse, /* void (*set_mouse)(int x, int y, int cursor, int clip); */
29  fb_dos_set_window_title, /* void (*set_window_title)(char *title); */
30  NULL, /* int (*set_window_pos)(int x, int y); */
31  driver_fetch_modes, /* int *(*fetch_modes)(int depth, int *size); */
32  NULL, /* void (*flip)(void); */
33  NULL /* void (*poll_events)(void); */
34 };
35 
36 static int modes[] = {
37  SCREENLIST(320, 240),
38  };
39 
40 static unsigned short CRTParams[] = {
41  0x0D06, /* vertical total */
42  0x3E07, /* overflow (bit 8 of vertical counts) */
43  0x4109, /* cell height (2 to double scan) */
44  0xEA10, /* v sync start */
45  0xAC11, /* v sync end and protect cr0-cr7 */
46  0xDF12, /* vertical displayed */
47  0x0014, /* turn off dword mode */
48  0xE715, /* v blank start */
49  0x0616, /* v blank end */
50  0xE317 /* turn on byte mode */
51  };
52 
53 #define CRT_PARM_LENGTH 10
54 
55 static int driver_init(char *title, int w, int h, int depth_arg, int refresh_rate, int flags)
56 {
57  int depth = MAX(8, depth_arg);
58  int i;
59 
60  fb_dos_detect();
61 
62  if (flags & DRIVER_OPENGL)
63  return -1;
64 
65  if ((w != 320) || (h != 240) || (depth != 8)) {
66  return -1;
67  }
68 
69  /* set base video mode */
70  fb_dos.regs.x.ax = 0x13;
71  __dpmi_int(0x10, &fb_dos.regs);
72 
73  /* tweak to Mode X */
74  outportw(SC_INDEX, 0x0604); /* disable chain4 */
75 
76  outportw(SC_INDEX, 0x0100); /* synchronous reset */
77  outportb(MISC_OUTPUT, 0xE3); /* select 25 MHz dot clock & 60 Hz scanning rate */
78  outportw(SC_INDEX, 0x0300); /* undo reset (restart sequencer) */
79 
80  outportb(CRTC_INDEX, 0x11); /* VSync End reg contains register write protect bit */
81  outportb(CRTC_INDEX+1, inportb(CRTC_INDEX+1) & 0x7F); /* remove write protect on various CRTC registers */
82 
83  for (i = 0; i < CRT_PARM_LENGTH; i++) {
84  outportw(CRTC_INDEX, CRTParams[i]);
85  }
86 
87  refresh_rate = 60;
88 
90  fb_dos.update_len = (unsigned int)end_of_driver_update - (unsigned int)driver_update;
92 
93  return fb_dos_init(title, w, h, depth, refresh_rate, flags);
94 }
95 
96 static void driver_update(void)
97 {
98  int plane;
99  unsigned long screen;
100  unsigned char *buffer;
101  int x, y;
102 
103  _farsetsel(_dos_ds);
104  for (plane = 0; plane < 4; plane++) {
105  buffer = (unsigned char *)__fb_gfx->framebuffer + plane;
106  outportw(SC_INDEX, (0x100 << plane) | 0x02); /* set write plane */
107  screen = 0xA0000;
108  for (y = 0; y < fb_dos.h; y++) {
109  if (__fb_gfx->dirty[y]) {
110  for (x = 0; x < fb_dos.w; x += 4, screen++) {
111  _farnspokeb(screen, buffer[x]);
112  }
113  } else {
114  screen += fb_dos.w / 4;
115  }
116  buffer += fb_dos.w;
117  }
118  }
119 }
120 static void end_of_driver_update(void) { /* do not remove */ }
121 
122 static int *driver_fetch_modes(int depth, int *size)
123 {
124  if (depth != 8) return NULL;
125 
126  *size = sizeof(modes) / sizeof(int);
127  return memcpy((void*)malloc(sizeof(modes)), modes, sizeof(modes));
128 }