rev |
line source |
nuclear@7
|
1 #include <stdio.h>
|
nuclear@7
|
2 #include <string.h>
|
nuclear@7
|
3 #include "vbe.h"
|
nuclear@7
|
4 #include "dpmi.h"
|
nuclear@7
|
5
|
nuclear@7
|
6 /* VGA DAC registers used for palette setting in 8bpp modes */
|
nuclear@7
|
7 #define VGA_DAC_STATE 0x3c7
|
nuclear@7
|
8 #define VGA_DAC_ADDR_RD 0x3c7
|
nuclear@7
|
9 #define VGA_DAC_ADDR_WR 0x3c8
|
nuclear@7
|
10 #define VGA_DAC_DATA 0x3c9
|
nuclear@7
|
11
|
nuclear@7
|
12 #define MODE_LFB (1 << 14)
|
nuclear@7
|
13
|
nuclear@7
|
14
|
nuclear@7
|
15 struct vbe_info *vbe_get_info(void)
|
nuclear@7
|
16 {
|
nuclear@7
|
17 static unsigned short info_block_seg;
|
nuclear@7
|
18 static struct vbe_info *info;
|
nuclear@7
|
19 struct dpmi_real_regs regs;
|
nuclear@7
|
20
|
nuclear@7
|
21 if(!info) {
|
nuclear@7
|
22 /* allocate 32 paragraphs (512 bytes) */
|
nuclear@7
|
23 info_block_seg = dpmi_alloc(32);
|
nuclear@7
|
24 info = (struct vbe_info*)(info_block_seg << 4);
|
nuclear@7
|
25 }
|
nuclear@7
|
26
|
nuclear@7
|
27 memcpy(info->sig, "VBE2", 4);
|
nuclear@7
|
28
|
nuclear@7
|
29 memset(®s, 0, sizeof regs);
|
nuclear@7
|
30 regs.es = info_block_seg;
|
nuclear@7
|
31 regs.eax = 0x4f00;
|
nuclear@7
|
32
|
nuclear@7
|
33 dpmi_real_int(0x10, ®s);
|
nuclear@7
|
34
|
nuclear@7
|
35 return info;
|
nuclear@7
|
36 }
|
nuclear@7
|
37
|
nuclear@7
|
38 struct vbe_mode_info *vbe_get_mode_info(int mode)
|
nuclear@7
|
39 {
|
nuclear@7
|
40 static unsigned short mode_info_seg;
|
nuclear@7
|
41 static struct vbe_mode_info *mi;
|
nuclear@7
|
42 struct dpmi_real_regs regs;
|
nuclear@7
|
43
|
nuclear@7
|
44 if(!mi) {
|
nuclear@7
|
45 /* allocate 16 paragraphs (256 bytes) */
|
nuclear@7
|
46 mode_info_seg = dpmi_alloc(16);
|
nuclear@7
|
47 mi = (struct vbe_mode_info*)(mode_info_seg << 4);
|
nuclear@7
|
48 }
|
nuclear@7
|
49
|
nuclear@7
|
50 memset(®s, 0, sizeof regs);
|
nuclear@7
|
51 regs.es = mode_info_seg;
|
nuclear@7
|
52 regs.eax = 0x4f01;
|
nuclear@7
|
53 regs.ecx = mode;
|
nuclear@7
|
54 regs.es = mode_info_seg;
|
nuclear@7
|
55
|
nuclear@7
|
56 dpmi_real_int(0x10, ®s);
|
nuclear@7
|
57 if(regs.eax & 0xff00) {
|
nuclear@7
|
58 return 0;
|
nuclear@7
|
59 }
|
nuclear@7
|
60
|
nuclear@7
|
61 return mi;
|
nuclear@7
|
62 }
|
nuclear@7
|
63
|
nuclear@7
|
64 int vbe_set_mode(int mode)
|
nuclear@7
|
65 {
|
nuclear@7
|
66 struct dpmi_real_regs regs;
|
nuclear@7
|
67
|
nuclear@7
|
68 memset(®s, 0, sizeof regs);
|
nuclear@7
|
69 regs.eax = 0x4f02;
|
nuclear@7
|
70 regs.ebx = mode;
|
nuclear@7
|
71 dpmi_real_int(0x10, ®s);
|
nuclear@7
|
72
|
nuclear@7
|
73 if(regs.eax == 0x100) {
|
nuclear@7
|
74 return -1;
|
nuclear@7
|
75 }
|
nuclear@7
|
76 return 0;
|
nuclear@7
|
77 }
|
nuclear@7
|
78
|
nuclear@7
|
79 int vbe_set_palette_bits(int bits)
|
nuclear@7
|
80 {
|
nuclear@7
|
81 struct dpmi_real_regs regs;
|
nuclear@7
|
82
|
nuclear@7
|
83 memset(®s, 0, sizeof regs);
|
nuclear@7
|
84 regs.eax = 0x4f08;
|
nuclear@7
|
85 regs.ebx = bits << 8; /* bits in bh */
|
nuclear@7
|
86 dpmi_real_int(0x10, ®s);
|
nuclear@7
|
87
|
nuclear@7
|
88 if((regs.eax >> 8) & 0xff == 3) {
|
nuclear@7
|
89 return -1;
|
nuclear@7
|
90 }
|
nuclear@7
|
91 return regs.ebx >> 8 & 0xff; /* new color bits in bh */
|
nuclear@7
|
92 }
|
nuclear@7
|
93
|
nuclear@7
|
94 /* TODO: implement palette setting through the VBE2 interface for
|
nuclear@7
|
95 * non-VGA displays (actually don't).
|
nuclear@7
|
96 */
|
nuclear@7
|
97 void vbe_set_palette(int idx, int *col, int count, int bits)
|
nuclear@7
|
98 {
|
nuclear@7
|
99 int i, shift = 8 - bits;
|
nuclear@7
|
100
|
nuclear@7
|
101 __asm {
|
nuclear@7
|
102 mov dx, VGA_DAC_ADDR_WR
|
nuclear@7
|
103 mov eax, idx
|
nuclear@7
|
104 out dx, al
|
nuclear@7
|
105 }
|
nuclear@7
|
106
|
nuclear@7
|
107 for(i=0; i<count; i++) {
|
nuclear@7
|
108 unsigned char r = *col++;
|
nuclear@7
|
109 unsigned char g = *col++;
|
nuclear@7
|
110 unsigned char b = *col++;
|
nuclear@7
|
111
|
nuclear@7
|
112 if(shift) {
|
nuclear@7
|
113 r >>= shift;
|
nuclear@7
|
114 g >>= shift;
|
nuclear@7
|
115 b >>= shift;
|
nuclear@7
|
116 }
|
nuclear@7
|
117
|
nuclear@7
|
118 __asm {
|
nuclear@7
|
119 mov dx, VGA_DAC_DATA
|
nuclear@7
|
120 mov al, r
|
nuclear@7
|
121 out dx, al
|
nuclear@7
|
122 mov al, g
|
nuclear@7
|
123 out dx, al
|
nuclear@7
|
124 mov al, b
|
nuclear@7
|
125 out dx, al
|
nuclear@7
|
126 }
|
nuclear@7
|
127 }
|
nuclear@7
|
128 }
|
nuclear@7
|
129
|
nuclear@7
|
130 static unsigned int get_mask(int sz, int pos)
|
nuclear@7
|
131 {
|
nuclear@7
|
132 unsigned int i, mask = 0;
|
nuclear@7
|
133
|
nuclear@7
|
134 for(i=0; i<sz; i++) {
|
nuclear@7
|
135 mask |= 1 << i;
|
nuclear@7
|
136 }
|
nuclear@7
|
137 return mask << pos;
|
nuclear@7
|
138 }
|
nuclear@7
|
139
|
nuclear@7
|
140 void print_mode_info(FILE *fp, struct vbe_mode_info *mi)
|
nuclear@7
|
141 {
|
nuclear@7
|
142 fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres);
|
nuclear@7
|
143 fprintf(fp, "color depth: %d\n", mi->bpp);
|
nuclear@7
|
144 fprintf(fp, "mode attributes: %x\n", mi->mode_attr);
|
nuclear@7
|
145 fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes);
|
nuclear@7
|
146 fprintf(fp, "number of planes: %d\n", (int)mi->num_planes);
|
nuclear@7
|
147 fprintf(fp, "number of banks: %d\n", (int)mi->num_banks);
|
nuclear@7
|
148 fprintf(fp, "mem model: %d\n", (int)mi->mem_model);
|
nuclear@7
|
149 fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos));
|
nuclear@7
|
150 fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos));
|
nuclear@7
|
151 fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos));
|
nuclear@7
|
152 fprintf(fp, "framebuffer address: %x\n", mi->fb_addr);
|
nuclear@7
|
153 }
|