]> 4ch.mooo.com Git - 16.git/blob - src/lib/doslib/hw/vga/vga.h
added a bunch of things~ and midi stuff~
[16.git] / src / lib / doslib / hw / vga / vga.h
1
2 #ifndef __DOSLIB_HW_VGA_VGA_H
3 #define __DOSLIB_HW_VGA_VGA_H
4
5 #include <hw/cpu/cpu.h>
6 #include <stdint.h>
7
8 #if TARGET_MSDOS == 32
9 typedef unsigned char *VGA_RAM_PTR;
10 typedef uint16_t *VGA_ALPHA_PTR;
11 #else
12 typedef unsigned char far *VGA_RAM_PTR;
13 typedef uint16_t far *VGA_ALPHA_PTR;
14 #endif
15
16 /* vga_flags */
17 #define VGA_IS_TANDY                    0x02    /* Tandy/PCjr */
18 #define VGA_IS_HGC                      0x04
19 #define VGA_IS_MCGA                     0x08
20 #define VGA_IS_VGA                      0x10
21 #define VGA_IS_EGA                      0x20
22 #define VGA_IS_CGA                      0x40
23 #define VGA_IS_MDA                      0x80
24 #define VGA_IS_AMSTRAD                  0x100
25
26 /* sequencer index */
27 #define VGA_AC_ENABLE                   0x20
28
29 /* graphics controller regs */
30 #define VGA_GC_DATA_ROTATE_OP_NONE              (0 << 3)
31 #define VGA_GC_DATA_ROTATE_OP_AND               (1 << 3)
32 #define VGA_GC_DATA_ROTATE_OP_OR                (2 << 3)
33 #define VGA_GC_DATA_ROTATE_OP_XOR               (3 << 3)
34
35 /* font manipulation vars */
36 #define VGA_EGA_BYTES_PER_CHAR_BITMAP           32
37 #define VGA_EGA_BYTES_PER_CHAR_BITMAP_SHIFT     5
38
39 /* EGA/VGA memory map bits */
40 enum {
41         VGA_MEMMAP_A0000_128K=0,
42         VGA_MEMMAP_A0000_64K,
43         VGA_MEMMAP_B0000_32K,
44         VGA_MEMMAP_B8000_32K
45 };
46
47 enum {
48         VGA_CGA_MODE_40WIDE=0,
49         VGA_CGA_MODE_80WIDE=0x01,
50         VGA_CGA_MODE_GRAPHICS=0x02,
51         VGA_CGA_MODE_BW=0x04,
52         VGA_CGA_MODE_VIDEO_ENABLE=0x08,
53         VGA_CGA_MODE_VIDEO_640=0x10,
54         VGA_CGA_MODE_NO_BLINKING=0x20
55 };
56
57 /* sequencer registers */
58 enum {
59         VGA_SC_MAP_MASK=2
60 };
61
62 /* graphics controller registers */
63 enum {
64         VGA_GC_ENABLE_SET_RESET=0,
65         VGA_GC_SET_RESET=1,
66         VGA_GC_DATA_ROTATE=3,
67         VGA_GC_MODE=5,
68         VGA_GC_BIT_MASK=8
69 };
70
71 enum { /* CGA palette selection (320x200x4) */
72         VGA_CGA_PALETTE_GR_BR_RD=0,
73         VGA_CGA_PALETTE_CY_MA_WH=1
74 };
75
76 enum { /* color select (text=border color  320x200=background    640x200=foreground */
77         VGA_CGA_PALETTE_CS_BLUE=(1U << 0U),
78         VGA_CGA_PALETTE_CS_GREEN=(1U << 1U),
79         VGA_CGA_PALETTE_CS_RED=(1U << 2U),
80         VGA_CGA_PALETTE_CS_INTENSITY=(1U << 3U),
81         VGA_CGA_PALETTE_CS_ALT_INTENSITY=(1U << 4U)
82 };
83
84 extern VGA_RAM_PTR      vga_graphics_ram;
85 extern VGA_RAM_PTR      vga_graphics_ram_fence;
86 extern VGA_ALPHA_PTR    vga_alpha_ram;
87 extern VGA_ALPHA_PTR    vga_alpha_ram_fence;
88
89 extern uint32_t         vga_clock_rates[4];
90 extern unsigned char    vga_pos_x,vga_pos_y,vga_color;
91 extern unsigned char    vga_width,vga_height;
92 extern unsigned char    vga_alpha_mode;
93 extern unsigned char    vga_hgc_type;
94 extern unsigned int     vga_base_3x0;
95 extern unsigned long    vga_ram_base;
96 extern unsigned long    vga_ram_size;
97 extern unsigned char    vga_stride;
98 extern unsigned short   vga_flags;
99 extern unsigned char    vga_9wide;
100
101 unsigned char int10_getmode();
102 void vga_write(const char *msg);
103 void int10_setmode(unsigned char mode);
104 void update_state_vga_memory_map_select(unsigned char c);
105 unsigned char vga_force_read(const VGA_RAM_PTR p);
106 void vga_force_write(VGA_RAM_PTR p,const unsigned char c);
107 void vga_force_write_w(VGA_ALPHA_PTR p,const unsigned short c);
108 int check_vga_3C0();
109 void vga_sync_hw_cursor();
110 void vga_sync_bios_cursor();
111 void update_state_vga_memory_map_select(unsigned char c);
112 void vga_set_memory_map(unsigned char c);
113 void vga_bios_set_80x50_text();
114 void update_state_from_vga();
115 int probe_vga();
116 void vga_write_state_DEBUG(FILE *f);
117 void vga_relocate_crtc(unsigned char color);
118 void vga_switch_to_mono();
119 void vga_switch_to_color();
120 void vga_turn_on_hgc();
121 void vga_turn_off_hgc();
122 void vga_set_cga_palette_and_background(unsigned char pal,unsigned char color);
123 void vga_set_cga_mode(unsigned char b);
124 void vga_tandy_setpalette(unsigned char i,unsigned char c);
125 void vga_enable_256color_modex();
126 void vga_set_stride(unsigned int stride);
127 void vga_set_start_location(unsigned int offset);
128 void vga_set_ypan_sub(unsigned char c);
129 void vga_set_xpan(unsigned char c);
130 void vga_splitscreen(unsigned int v);
131 void vga_alpha_switch_to_font_plane();
132 void vga_alpha_switch_from_font_plane();
133 void vga_set_9wide(unsigned char en);
134 void vga_select_charset_a_b(unsigned short a,unsigned short b);
135 void vga_write_crtc_mode(struct vga_mode_params *p,unsigned int flags);
136 void vga_correct_crtc_mode(struct vga_mode_params *p);
137 void vga_read_crtc_mode(struct vga_mode_params *p);
138
139 #define VGA_WRITE_CRTC_MODE_NO_CLEAR_SYNC       0x0001
140
141 static inline unsigned char vga_read_CRTC(unsigned char i) {
142         outp(vga_base_3x0+4,i);
143         return inp(vga_base_3x0+5);
144 }
145
146 static inline unsigned char vga_read_GC(unsigned char i) {
147         outp(0x3CE,i);
148         return inp(0x3CF);
149 }
150
151 static inline unsigned char vga_read_sequencer(unsigned char i) {
152         outp(0x3C4,i);
153         return inp(0x3C5);
154 }
155
156 static inline void vga_write_sequencer(unsigned char i,unsigned char c) {
157         outp(0x3C4,i);
158         outp(0x3C5,c);
159 }
160
161 static inline void vga_write_GC(unsigned char i,unsigned char c) {
162         outp(0x3CE,i);
163         outp(0x3CF,c);
164 }
165
166 static inline void vga_write_CRTC(unsigned char i,unsigned char c) {
167         outp(vga_base_3x0+4,i);
168         outp(vga_base_3x0+5,c);
169 }
170
171 static inline void vga_write_color(unsigned char c) {
172         vga_color = c;
173 }
174
175 static inline void vga_read_PAL(unsigned char i,unsigned char *p,unsigned int count) {
176         count *= 3;
177         outp(0x3C7,i);
178         while (count-- > 0) *p++ = inp(0x3C9);
179 }
180
181 static inline void vga_write_PAL(unsigned char i,unsigned char *p,unsigned int count) {
182         count *= 3;
183         outp(0x3C8,i);
184         while (count-- > 0) outp(0x3C9,*p++);
185 }
186
187 /* NTS: VGA hardware treats bit 5 of the index as a "screen enable".
188  *      When the caller is done reprogramming it is expected to or the index by VGA_AC_ENABLE */
189 static inline void vga_write_AC(unsigned char i,unsigned char c) {
190         inp(vga_base_3x0+0xA); /* reset flipflop */
191         outp(0x3C0,i);
192         outp(0x3C0,c);
193         inp(vga_base_3x0+0xA);
194 }
195
196 static inline unsigned char vga_read_AC(unsigned char i) {
197         unsigned char c;
198
199         /* NTS: Reading the palette registers must occur this way because
200          *      an old S3 Virge DX card I have will misread the values
201          *      when PAS=1 otherwise. */
202
203         inp(vga_base_3x0+0xA);  /* reset latch */
204         outp(0x3C0,i&(~0x20));  /* index with PAS=0 */
205         c = inp(0x3C1);
206         inp(vga_base_3x0+0xA);  /* reset latch */
207         outp(0x3C0,i|0x20);     /* index with PAS=1 */
208         inp(vga_base_3x0+0xA);  /* reset latch */
209
210         return c;
211 }
212
213 static inline void vga_AC_reenable_screen() {
214         inp(vga_base_3x0+0xA); /* reset flipflop */
215         outp(0x3C0,0x20);
216         inp(vga_base_3x0+0xA);
217 }
218
219 static inline void vga_palette_lseek(unsigned int i) {
220         outp(0x3C8,i);
221 }
222
223 static inline void vga_palette_write(unsigned char r,unsigned char g,unsigned char b) {
224         outp(0x3C9,r);
225         outp(0x3C9,g);
226         outp(0x3C9,b);
227 }
228
229 static inline unsigned char vga_in_vsync() {
230         unsigned int p = vga_base_3x0 + 0xA;
231         return (inp(p) & 0x8);
232 }
233
234 static inline void vga_wait_for_hsync() {
235         unsigned int p = vga_base_3x0 + 0xA;
236         while ((inp(p) & 0x1) == 0);
237 }
238
239 static inline void vga_wait_for_hsync_end() {
240         unsigned int p = vga_base_3x0 + 0xA;
241         while ((inp(p) & 0x1) != 0);
242 }
243
244 static inline void vga_wait_for_vsync() {
245         unsigned int p = vga_base_3x0 + 0xA;
246         while ((inp(p) & 0x8) == 0);
247 }
248
249 static inline void vga_wait_for_vsync_end() {
250         unsigned int p = vga_base_3x0 + 0xA;
251         while ((inp(p) & 0x8) != 0);
252 }
253
254 static inline unsigned char vga_AC_RGB_to_code(unsigned char r,unsigned char g,unsigned char b) {
255         return  (((b>>1)&1)<<0)|(((g>>1)&1)<<1)|(((r>>1)&1)<<2)|
256                 (((b>>0)&1)<<3)|(((g>>0)&1)<<4)|(((r>>0)&1)<<5);
257 }
258
259 #if defined(TARGET_WINDOWS) && TARGET_MSDOS == 32
260 /* we have to call the Win16 executable buffer */
261 #else
262 # pragma aux int10_getmode = \
263         "mov    ax,0x0F00" \
264         "int    0x10" \
265         value [al] \
266         modify [ax bx];
267
268 # pragma aux int10_setmode = \
269         "xor    ah,ah" \
270         "int    0x10" \
271         parm [al] \
272         modify [ax bx];
273 #endif
274
275 /* Watcom loves to reorder memory I/O on us. So to avoid problems we just have to
276  * suck it up and write the VGA memory functions in assembly language where it can't
277  * reorder access. Keeping the I/O in order is very important if we're to make
278  * proper use of the VGA hardware latch */
279 #if TARGET_MSDOS == 32
280 #pragma aux vga_force_read = \
281         "mov    al,[ebx]" \
282         modify [al] \
283         value [al] \
284         parm [ebx];
285 #pragma aux vga_force_write = \
286         "mov    [ebx],al" \
287         parm [ebx] [al];
288 #else
289 #pragma aux vga_force_read = \
290         "mov    al,es:[di]" \
291         modify [al] \
292         value [al] \
293         parm [es di];
294 #pragma aux vga_force_write = \
295         "mov    es:[di],al" \
296         parm [es di] [al];
297 #pragma aux vga_force_write_w = \
298         "mov    es:[di],ax" \
299         parm [es di] [ax];
300 #endif
301
302 /* all video timing and mode related values.
303  * notice that other params like graphics controller settings aren't included here,
304  * since you can always set those up yourself without disturbing the video timing */
305 /* NTS: VGA standard hardware seems to be designed so that generally clock_div2=1
306  *      means you divide the master clock by 2. But it also seems that this bit is
307  *      ignored in 256-color modes and the VGA acts like it's always clear (NOT SET),
308  *      timings are programmed as if 640x400, and pixels are doubled horizontally
309  *      regardless of the bit. Despite all that, the general mode timing calculations
310  *      work out correctly anyway. This is important to know, because it may affect
311  *      your ability to correctly use this API for major mode changes between
312  *      256-color modes & other modes. */
313 struct vga_mode_params {
314         unsigned char           clock_select:2; /* 0x3C2 Misc out reg bits 2-3 */
315         unsigned char           hsync_neg:1;    /* 0x3C2 bit 6 */
316         unsigned char           vsync_neg:1;    /* 0x3C2 bit 7 */
317         unsigned char           clock9:1;       /* sequencer[1] bit 0 */
318         unsigned char           clock_div2:1;   /* sequencer[1] bit 3 [divide master clock by 2] */
319         unsigned char           word_mode:1;    /* CRTC[0x17] bit 6 = WORD MODE */
320         unsigned char           dword_mode:1;   /* CRTC[0x14] bit 6 = DWORD MODE */
321         unsigned short          horizontal_total; /* CRTC[0]             -5 */
322         unsigned short          horizontal_display_end; /* CRTC[1]       -1 */
323         unsigned short          horizontal_blank_start; /* CRTC[2] */
324         unsigned short          horizontal_blank_end;   /* CRTC[3] bit 0-4 & CRTC[5] bit 7 */
325         unsigned short          horizontal_start_retrace;/* CRTC[4] */
326         unsigned short          horizontal_end_retrace; /* CRTC[5] bit 0-4 */
327         unsigned char           horizontal_start_delay_after_total; /* CRTC[3] bit 5-6 */
328         unsigned char           horizontal_start_delay_after_retrace; /* CRTC[5] bit 5-6 */
329         unsigned short          vertical_total; /* CRTC[6] and CRTC[7] bit 0 and CRTC[7] bit 5          -2 */
330         unsigned short          vertical_start_retrace; /* CRTC[0x10] and CRTC[7] bit 2 and CRTC[7] bit 7 */
331         unsigned short          vertical_end_retrace; /* CRTC[0x11] bit 0-3 */
332         unsigned char           refresh_cycles_per_scanline; /* CRTC[0x11] bit 6 */
333         unsigned char           inc_mem_addr_only_every_4th; /* CRTC[0x14] bit 5 */
334         unsigned short          vertical_display_end;   /* CRTC[0x12] and CRTC[7] bit 1 and CRTC[7] bit 6 */
335         unsigned short          vertical_blank_start;   /* CRTC[0x15] and CRTC[7] bit 3 */
336         unsigned short          vertical_blank_end;     /* CRTC[0x16] bit 0-7 */
337         unsigned char           shift_load_rate:1;      /* sequencer[1] bit 2 */
338         unsigned char           shift4_enable:1;        /* sequencer[1] bit 4 */
339         unsigned char           address_wrap_select:1;  /* CRTC[0x17] bit 5 */
340         unsigned char           memaddr_div2:1;         /* CRTC[0x17] bit 3 */
341         unsigned char           scanline_div2:1;        /* CRTC[0x17] bit 2 */
342         unsigned char           map14:1;                /* CRTC[0x17] bit 1 */
343         unsigned char           map13:1;                /* CRTC[0x17] bit 0 */
344         unsigned char           scan_double:1;          /* CRTC[0x09] bit 7 */
345         unsigned char           max_scanline;           /* CRTC[0x09] bit 4-0 */
346         unsigned char           offset;                 /* CRTC[0x13] */
347         unsigned char           sync_enable:1;          /* CRTC[0x17] bit 7 */
348 };
349
350 #endif /* __DOSLIB_HW_VGA_VGA_H */
351