c2e4f8decd2f974b92cf0ddbbcfdb3ae1a3d2221
[dosrtxon] / src / dos / gfx.c
1 #ifndef GFX_H_
2 #define GFX_H_
3
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <limits.h>
8 #include "vbe.h"
9 #include "cdpmi.h"
10
11 #ifdef __DJGPP__
12 #include <sys/nearptr.h>
13
14 #define REALPTR(s, o)   (void*)(((uint32_t)(s) << 4) - __djgpp_base_address + (uint32_t)(o))
15 #else
16 #define REALPTR(s, o)   (void*)(((uint32_t)(s) << 4) + (uint32_t)(o))
17 #endif
18
19 #define VBEPTR(x)               REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff)
20 #define VBEPTR_SEG(x)   (((x) & 0xffff0000) >> 16)
21 #define VBEPTR_OFF(x)   ((x) & 0xffff)
22
23 #define SAME_BPP(a, b)  \
24         ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
25          ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32))
26
27 static unsigned int make_mask(int sz, int pos);
28
29 static struct vbe_info *vbe_info;
30 static struct vbe_mode_info *mode_info;
31 static int pal_bits = 6;
32
33 void *set_video_mode(int xsz, int ysz, int bpp)
34 {
35         int i;
36         static uint16_t *modes;
37         uint16_t best = 0;
38         unsigned int fbsize;
39
40 #ifdef __DJGPP__
41         __djgpp_nearptr_enable();
42 #endif
43
44         /* check for VBE2 support and output some info */
45         if(!vbe_info) {
46                 if(!(vbe_info = vbe_get_info())) {
47                         fprintf(stderr, "VESA BIOS Extensions not available\n");
48                         return 0;
49                 }
50
51                 printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff);
52                 if(vbe_info->version < 0x200) {
53                         fprintf(stderr, "This program requires VBE 2.0 or greater. Try running UniVBE\n");
54                         return 0;
55                 }
56
57                 printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr),
58                                 (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr));
59                 printf("Video memory: %dkb\n", vbe_info->total_mem << 6);
60
61                 modes = VBEPTR(vbe_info->vid_mode_ptr);
62         }
63
64         for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */
65                 if(modes[i] == 0xffff) {
66                         break;  /* reached the end */
67                 }
68
69                 mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB);
70                 if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) {
71                         continue;
72                 }
73                 if(SAME_BPP(mode_info->bpp, bpp)) {
74                         best = modes[i];
75                 }
76         }
77
78         if(best) {
79                 mode_info = vbe_get_mode_info(best);
80         } else {
81                 fprintf(stderr, "Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp);
82                 return 0;
83         }
84
85         if(vbe_set_mode(best | VBE_MODE_LFB) == -1) {
86                 fprintf(stderr, "Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp);
87                 return 0;
88         }
89
90         /* attempt to set 8 bits of color per component in palettized modes */
91         /*if(bpp <= 8) {
92                 pal_bits = vbe_set_palette_bits(8);
93                 printf("palette bits per color primary: %d\n", pal_bits);
94         }
95         */
96
97         fbsize = xsz * ysz * mode_info->num_img_pages * (bpp / CHAR_BIT);
98         return (void*)dpmi_mmap(mode_info->fb_addr, fbsize);
99 }
100
101 int set_text_mode(void)
102 {
103         vbe_set_mode(0x3);
104         return 0;
105 }
106
107 int get_color_depth(void)
108 {
109         if(!mode_info) {
110                 return -1;
111         }
112         return mode_info->bpp;
113 }
114
115 int get_color_bits(int *rbits, int *gbits, int *bbits)
116 {
117         if(!mode_info) {
118                 return -1;
119         }
120         *rbits = mode_info->rmask_size;
121         *gbits = mode_info->gmask_size;
122         *bbits = mode_info->bmask_size;
123         return 0;
124 }
125
126 int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask)
127 {
128         if(!mode_info) {
129                 return -1;
130         }
131         *rmask = make_mask(mode_info->rmask_size, mode_info->rpos);
132         *gmask = make_mask(mode_info->gmask_size, mode_info->gpos);
133         *bmask = make_mask(mode_info->bmask_size, mode_info->bpos);
134         return 0;
135 }
136
137 int get_color_shift(int *rshift, int *gshift, int *bshift)
138 {
139         if(!mode_info) {
140                 return -1;
141         }
142         *rshift = mode_info->rpos;
143         *gshift = mode_info->gpos;
144         *bshift = mode_info->bpos;
145         return 0;
146 }
147
148 void set_palette(int idx, int r, int g, int b)
149 {
150         int col[3];
151         col[0] = r;
152         col[1] = g;
153         col[2] = b;
154         vbe_set_palette(idx, col, 1, pal_bits);
155 }
156
157 static unsigned int make_mask(int sz, int pos)
158 {
159         unsigned int i, mask = 0;
160
161         for(i=0; i<sz; i++) {
162                 mask |= 1 << i;
163         }
164         return mask << pos;
165 }
166
167
168 #endif  /* GFX_H_ */