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