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