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))
36 static struct vbe_info *vbe_info;
37 static struct vbe_mode_info *mode_info;
39 void set_vga_mode(int mode)
41 struct int86regs regs;
43 memset(®s, 0, sizeof regs);
48 void *set_video_mode(int xsz, int ysz, int bpp)
51 static uint16_t *modes;
54 /* check for VBE2 support and output some info */
56 if(!(vbe_info = vbe_get_info())) {
57 printf("VESA BIOS Extensions not available\n");
61 printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff);
62 if(vbe_info->version < 0x200) {
63 printf("VBE >=2.0 not available. VBE 1.x support not implemented yet.");
67 printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr),
68 (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr));
69 printf("Video memory: %dkb\n", vbe_info->total_mem << 6);
71 modes = VBEPTR(vbe_info->vid_mode_ptr);
74 for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */
75 if(modes[i] == 0xffff) {
76 break; /* reached the end */
79 mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB);
80 if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) {
83 if(SAME_BPP(mode_info->bpp, bpp)) {
89 mode_info = vbe_get_mode_info(best);
91 printf("Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp);
95 if(vbe_set_mode(best | VBE_MODE_LFB) == -1) {
96 printf("Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp);
100 return (void*)mode_info->fb_addr;
103 int get_color_bits(int *rbits, int *gbits, int *bbits)
108 *rbits = mode_info->rmask_size;
109 *gbits = mode_info->gmask_size;
110 *bbits = mode_info->bmask_size;
114 int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask)
116 static unsigned int maskbits[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
120 *rmask = maskbits[mode_info->rmask_size] << mode_info->rpos;
121 *gmask = maskbits[mode_info->gmask_size] << mode_info->gpos;
122 *bmask = maskbits[mode_info->bmask_size] << mode_info->bpos;
126 int get_color_shift(int *rshift, int *gshift, int *bshift)
131 *rshift = mode_info->rpos;
132 *gshift = mode_info->gpos;
133 *bshift = mode_info->bpos;