2 pcboot - bootable PC demo/game kernel
3 Copyright (C) 2018 John Tsiombikas <nuclear@member.fsf.org>
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY, without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <https://www.gnu.org/licenses/>.
24 #define REALPTR(s, o) (void*)(((uint32_t)(s) << 4) + (uint32_t)(o))
25 #define VBEPTR(x) REALPTR(((x) & 0xffff0000) >> 16, (x) & 0xffff)
26 #define VBEPTR_SEG(x) (((x) & 0xffff0000) >> 16)
27 #define VBEPTR_OFF(x) ((x) & 0xffff)
30 #define SAME_BPP(a, b) \
31 ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \
32 ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32))
35 unsigned int color_mask(int nbits, int pos);
37 static struct vbe_info *vbe_info;
38 static uint16_t *modes;
39 static int mode_count;
40 static struct vbe_mode_info *mode_info;
42 void set_vga_mode(int mode)
44 struct int86regs regs;
46 memset(®s, 0, sizeof regs);
51 static int init_once(void)
57 return vbe_info && modes ? 0 : -1;
61 /* check for VBE2 support and output some info */
62 if(!(vbe_info = vbe_get_info())) {
63 printf("VESA BIOS Extensions not available\n");
67 printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff);
68 if(vbe_info->version < 0x200) {
69 printf("VBE >=2.0 not available. VBE 1.x support not implemented yet.");
73 printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr),
74 (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr));
75 printf("Video memory: %dkb\n", vbe_info->total_mem << 6);
77 modes = VBEPTR(vbe_info->vid_mode_ptr);
80 for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */
81 if(modes[i] == 0xffff) {
82 break; /* reached the end */
89 void *set_video_mode(int mode)
91 if(init_once() == -1) return 0;
92 if(mode < 0) return 0;
94 if(!(mode_info = vbe_get_mode_info(mode))) {
98 if(vbe_set_mode(mode | VBE_MODE_LFB) == -1) {
99 printf("Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp);
103 return (void*)mode_info->fb_addr;
106 int find_video_mode_idx(int xsz, int ysz, int bpp)
108 int i, best = -1, best_bpp = 0;
109 struct vbe_mode_info *inf;
111 if(init_once() == -1) return -1;
113 for(i=0; i<mode_count; i++) {
114 inf = vbe_get_mode_info(modes[i] | VBE_MODE_LFB);
115 if(!inf || inf->xres != xsz || inf->yres != ysz) {
118 if((bpp <= 0 && inf->bpp > best_bpp) || SAME_BPP(inf->bpp, bpp)) {
125 printf("Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp);
131 int video_mode_count(void)
133 if(init_once() == -1) return 0;
137 int video_mode_info(int n, struct video_mode *vid)
139 struct vbe_mode_info *inf;
141 if(init_once() == -1) return -1;
143 if(!(inf = vbe_get_mode_info(modes[n] | VBE_MODE_LFB))) {
146 vid->mode = modes[n];
147 vid->width = inf->xres;
148 vid->height = inf->yres;
150 vid->rbits = inf->rmask_size;
151 vid->gbits = inf->gmask_size;
152 vid->bbits = inf->bmask_size;
153 vid->rshift = inf->rpos;
154 vid->gshift = inf->gpos;
155 vid->bshift = inf->bpos;
156 vid->rmask = color_mask(inf->rmask_size, inf->rpos);
157 vid->gmask = color_mask(inf->gmask_size, inf->gpos);
158 vid->bmask = color_mask(inf->bmask_size, inf->bpos);
162 int get_color_bits(int *rbits, int *gbits, int *bbits)
167 *rbits = mode_info->rmask_size;
168 *gbits = mode_info->gmask_size;
169 *bbits = mode_info->bmask_size;
173 int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask)
178 *rmask = color_mask(mode_info->rmask_size, mode_info->rpos);
179 *gmask = color_mask(mode_info->gmask_size, mode_info->gpos);
180 *bmask = color_mask(mode_info->bmask_size, mode_info->bpos);
184 int get_color_shift(int *rshift, int *gshift, int *bshift)
189 *rshift = mode_info->rpos;
190 *gshift = mode_info->gpos;
191 *bshift = mode_info->bpos;
195 unsigned int color_mask(int nbits, int pos)
197 static unsigned int maskbits[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
198 return maskbits[nbits] << pos;
201 const char *get_video_vendor(void)
203 if(init_once() == -1) return 0;
204 return (char*)VBEPTR(vbe_info->oem_vendor_name_ptr);
207 int get_video_mem_size(void)
209 if(init_once() == -1) return 0;
210 return vbe_info->total_mem << 6;