rev |
line source |
nuclear@0
|
1 #include <stdio.h>
|
nuclear@0
|
2 #include <string.h>
|
nuclear@3
|
3 #include <conio.h>
|
nuclear@0
|
4 #include "vbe.h"
|
nuclear@0
|
5 #include "dpmi.h"
|
nuclear@3
|
6 #include "inttypes.h"
|
nuclear@3
|
7
|
nuclear@3
|
8 #ifdef __DJGPP__
|
nuclear@3
|
9 #include <pc.h>
|
nuclear@3
|
10 #include <sys/nearptr.h>
|
nuclear@3
|
11
|
nuclear@3
|
12 #define SEG_ADDR(s) (((uint32_t)(s) << 4) - __djgpp_base_address)
|
nuclear@3
|
13
|
nuclear@3
|
14 #define outp(p, v) outportb(p, v)
|
nuclear@3
|
15 #else
|
nuclear@3
|
16 #define SEG_ADDR(s) ((uint32_t)(s) << 4)
|
nuclear@3
|
17 #endif
|
nuclear@0
|
18
|
nuclear@0
|
19 /* VGA DAC registers used for palette setting in 8bpp modes */
|
nuclear@0
|
20 #define VGA_DAC_STATE 0x3c7
|
nuclear@0
|
21 #define VGA_DAC_ADDR_RD 0x3c7
|
nuclear@0
|
22 #define VGA_DAC_ADDR_WR 0x3c8
|
nuclear@0
|
23 #define VGA_DAC_DATA 0x3c9
|
nuclear@0
|
24
|
nuclear@0
|
25 #define MODE_LFB (1 << 14)
|
nuclear@0
|
26
|
nuclear@0
|
27
|
nuclear@0
|
28 struct vbe_info *vbe_get_info(void)
|
nuclear@0
|
29 {
|
nuclear@3
|
30 static uint16_t info_block_seg, info_block_selector;
|
nuclear@0
|
31 static struct vbe_info *info;
|
nuclear@0
|
32 struct dpmi_real_regs regs;
|
nuclear@0
|
33
|
nuclear@0
|
34 if(!info) {
|
nuclear@0
|
35 /* allocate 32 paragraphs (512 bytes) */
|
nuclear@3
|
36 info_block_seg = dpmi_alloc(32, &info_block_selector);
|
nuclear@3
|
37 info = (struct vbe_info*)SEG_ADDR(info_block_seg);
|
nuclear@0
|
38 }
|
nuclear@0
|
39
|
nuclear@0
|
40 memcpy(info->sig, "VBE2", 4);
|
nuclear@0
|
41
|
nuclear@0
|
42 memset(®s, 0, sizeof regs);
|
nuclear@0
|
43 regs.es = info_block_seg;
|
nuclear@0
|
44 regs.eax = 0x4f00;
|
nuclear@0
|
45
|
nuclear@0
|
46 dpmi_real_int(0x10, ®s);
|
nuclear@0
|
47
|
nuclear@0
|
48 return info;
|
nuclear@0
|
49 }
|
nuclear@0
|
50
|
nuclear@0
|
51 struct vbe_mode_info *vbe_get_mode_info(int mode)
|
nuclear@0
|
52 {
|
nuclear@3
|
53 static uint16_t mode_info_seg, mode_info_selector;
|
nuclear@0
|
54 static struct vbe_mode_info *mi;
|
nuclear@0
|
55 struct dpmi_real_regs regs;
|
nuclear@0
|
56
|
nuclear@0
|
57 if(!mi) {
|
nuclear@0
|
58 /* allocate 16 paragraphs (256 bytes) */
|
nuclear@3
|
59 mode_info_seg = dpmi_alloc(16, &mode_info_selector);
|
nuclear@3
|
60 mi = (struct vbe_mode_info*)SEG_ADDR(mode_info_seg);
|
nuclear@0
|
61 }
|
nuclear@0
|
62
|
nuclear@0
|
63 memset(®s, 0, sizeof regs);
|
nuclear@0
|
64 regs.es = mode_info_seg;
|
nuclear@0
|
65 regs.eax = 0x4f01;
|
nuclear@0
|
66 regs.ecx = mode;
|
nuclear@0
|
67 regs.es = mode_info_seg;
|
nuclear@0
|
68
|
nuclear@0
|
69 dpmi_real_int(0x10, ®s);
|
nuclear@0
|
70 if(regs.eax & 0xff00) {
|
nuclear@0
|
71 return 0;
|
nuclear@0
|
72 }
|
nuclear@0
|
73
|
nuclear@0
|
74 return mi;
|
nuclear@0
|
75 }
|
nuclear@0
|
76
|
nuclear@0
|
77 int vbe_set_mode(int mode)
|
nuclear@0
|
78 {
|
nuclear@0
|
79 struct dpmi_real_regs regs;
|
nuclear@0
|
80
|
nuclear@0
|
81 memset(®s, 0, sizeof regs);
|
nuclear@0
|
82 regs.eax = 0x4f02;
|
nuclear@0
|
83 regs.ebx = mode;
|
nuclear@0
|
84 dpmi_real_int(0x10, ®s);
|
nuclear@0
|
85
|
nuclear@0
|
86 if(regs.eax == 0x100) {
|
nuclear@0
|
87 return -1;
|
nuclear@0
|
88 }
|
nuclear@0
|
89 return 0;
|
nuclear@0
|
90 }
|
nuclear@0
|
91
|
nuclear@0
|
92 int vbe_set_palette_bits(int bits)
|
nuclear@0
|
93 {
|
nuclear@0
|
94 struct dpmi_real_regs regs;
|
nuclear@0
|
95
|
nuclear@0
|
96 memset(®s, 0, sizeof regs);
|
nuclear@0
|
97 regs.eax = 0x4f08;
|
nuclear@0
|
98 regs.ebx = bits << 8; /* bits in bh */
|
nuclear@0
|
99 dpmi_real_int(0x10, ®s);
|
nuclear@0
|
100
|
nuclear@3
|
101 if(((regs.eax >> 8) & 0xff) == 3) {
|
nuclear@0
|
102 return -1;
|
nuclear@0
|
103 }
|
nuclear@0
|
104 return regs.ebx >> 8 & 0xff; /* new color bits in bh */
|
nuclear@0
|
105 }
|
nuclear@0
|
106
|
nuclear@0
|
107 /* TODO: implement palette setting through the VBE2 interface for
|
nuclear@0
|
108 * non-VGA displays (actually don't).
|
nuclear@0
|
109 */
|
nuclear@0
|
110 void vbe_set_palette(int idx, int *col, int count, int bits)
|
nuclear@0
|
111 {
|
nuclear@0
|
112 int i, shift = 8 - bits;
|
nuclear@0
|
113
|
nuclear@3
|
114 outp(VGA_DAC_ADDR_WR, idx);
|
nuclear@0
|
115
|
nuclear@0
|
116 for(i=0; i<count; i++) {
|
nuclear@0
|
117 unsigned char r = *col++;
|
nuclear@0
|
118 unsigned char g = *col++;
|
nuclear@0
|
119 unsigned char b = *col++;
|
nuclear@0
|
120
|
nuclear@0
|
121 if(shift) {
|
nuclear@0
|
122 r >>= shift;
|
nuclear@0
|
123 g >>= shift;
|
nuclear@0
|
124 b >>= shift;
|
nuclear@0
|
125 }
|
nuclear@0
|
126
|
nuclear@3
|
127 outp(VGA_DAC_DATA, r);
|
nuclear@3
|
128 outp(VGA_DAC_DATA, g);
|
nuclear@3
|
129 outp(VGA_DAC_DATA, b);
|
nuclear@0
|
130 }
|
nuclear@0
|
131 }
|
nuclear@0
|
132
|
nuclear@3
|
133 int vbe_set_disp_start(int x, int y, int when)
|
nuclear@3
|
134 {
|
nuclear@3
|
135 struct dpmi_real_regs regs;
|
nuclear@3
|
136
|
nuclear@3
|
137 memset(®s, 0, sizeof regs);
|
nuclear@3
|
138 regs.eax = 0x4f07;
|
nuclear@3
|
139 regs.ebx = when & 0xffff;
|
nuclear@3
|
140 regs.ecx = x & 0xffff;
|
nuclear@3
|
141 regs.edx = y & 0xffff;
|
nuclear@3
|
142 dpmi_real_int(0x10, ®s);
|
nuclear@3
|
143
|
nuclear@3
|
144 if(regs.eax == 0x100) {
|
nuclear@3
|
145 return -1;
|
nuclear@3
|
146 }
|
nuclear@3
|
147 return 0;
|
nuclear@3
|
148 }
|
nuclear@3
|
149
|
nuclear@3
|
150 int vbe_set_scanlen(int len, int mode)
|
nuclear@3
|
151 {
|
nuclear@3
|
152 struct dpmi_real_regs regs;
|
nuclear@3
|
153
|
nuclear@3
|
154 memset(®s, 0, sizeof regs);
|
nuclear@3
|
155 regs.eax = 0x4f06;
|
nuclear@3
|
156 regs.ebx = mode;
|
nuclear@3
|
157 regs.ecx = len & 0xffff;
|
nuclear@3
|
158 dpmi_real_int(0x10, ®s);
|
nuclear@3
|
159
|
nuclear@3
|
160 if(regs.eax == 0x100) {
|
nuclear@3
|
161 return -1;
|
nuclear@3
|
162 }
|
nuclear@3
|
163 return regs.ecx & 0xffff;
|
nuclear@3
|
164 }
|
nuclear@3
|
165
|
nuclear@3
|
166 int vbe_get_scanlen(int mode)
|
nuclear@3
|
167 {
|
nuclear@3
|
168 int res;
|
nuclear@3
|
169 struct dpmi_real_regs regs;
|
nuclear@3
|
170
|
nuclear@3
|
171 memset(®s, 0, sizeof regs);
|
nuclear@3
|
172 regs.eax = 0x4f06;
|
nuclear@3
|
173 regs.ebx = 1;
|
nuclear@3
|
174 dpmi_real_int(0x10, ®s);
|
nuclear@3
|
175
|
nuclear@3
|
176 if(regs.eax == 0x100) {
|
nuclear@3
|
177 return -1;
|
nuclear@3
|
178 }
|
nuclear@3
|
179
|
nuclear@3
|
180 if(mode == VBE_SCANLEN_PIXELS) {
|
nuclear@3
|
181 res = regs.ecx & 0xffff;
|
nuclear@3
|
182 } else {
|
nuclear@3
|
183 res = regs.ebx & 0xffff;
|
nuclear@3
|
184 }
|
nuclear@3
|
185 return res;
|
nuclear@3
|
186 }
|
nuclear@3
|
187
|
nuclear@3
|
188
|
nuclear@0
|
189 static unsigned int get_mask(int sz, int pos)
|
nuclear@0
|
190 {
|
nuclear@0
|
191 unsigned int i, mask = 0;
|
nuclear@0
|
192
|
nuclear@0
|
193 for(i=0; i<sz; i++) {
|
nuclear@0
|
194 mask |= 1 << i;
|
nuclear@0
|
195 }
|
nuclear@0
|
196 return mask << pos;
|
nuclear@0
|
197 }
|
nuclear@0
|
198
|
nuclear@0
|
199 void print_mode_info(FILE *fp, struct vbe_mode_info *mi)
|
nuclear@0
|
200 {
|
nuclear@0
|
201 fprintf(fp, "resolution: %dx%d\n", mi->xres, mi->yres);
|
nuclear@0
|
202 fprintf(fp, "color depth: %d\n", mi->bpp);
|
nuclear@0
|
203 fprintf(fp, "mode attributes: %x\n", mi->mode_attr);
|
nuclear@0
|
204 fprintf(fp, "bytes per scanline: %d\n", mi->scanline_bytes);
|
nuclear@0
|
205 fprintf(fp, "number of planes: %d\n", (int)mi->num_planes);
|
nuclear@0
|
206 fprintf(fp, "number of banks: %d\n", (int)mi->num_banks);
|
nuclear@0
|
207 fprintf(fp, "mem model: %d\n", (int)mi->mem_model);
|
nuclear@0
|
208 fprintf(fp, "red bits: %d (mask: %x)\n", (int)mi->rmask_size, get_mask(mi->rmask_size, mi->rpos));
|
nuclear@0
|
209 fprintf(fp, "green bits: %d (mask: %x)\n", (int)mi->gmask_size, get_mask(mi->gmask_size, mi->gpos));
|
nuclear@0
|
210 fprintf(fp, "blue bits: %d (mask: %x)\n", (int)mi->bmask_size, get_mask(mi->bmask_size, mi->bpos));
|
nuclear@3
|
211 fprintf(fp, "framebuffer address: %x\n", (unsigned int)mi->fb_addr);
|
nuclear@0
|
212 }
|