+
+void *set_video_mode(int xsz, int ysz, int bpp)
+{
+ int i;
+ static uint16_t *modes;
+ uint16_t best = 0;
+
+ /* check for VBE2 support and output some info */
+ if(!vbe_info) {
+ if(!(vbe_info = vbe_get_info())) {
+ printf("VESA BIOS Extensions not available\n");
+ return 0;
+ }
+
+ printf("VBE Version: %x.%x\n", vbe_info->version >> 8, vbe_info->version & 0xff);
+ if(vbe_info->version < 0x200) {
+ printf("VBE >=2.0 not available. VBE 1.x support not implemented yet.");
+ return 0;
+ }
+
+ printf("Graphics adapter: %s, %s (%s)\n", (char*)VBEPTR(vbe_info->oem_vendor_name_ptr),
+ (char*)VBEPTR(vbe_info->oem_product_name_ptr), (char*)VBEPTR(vbe_info->oem_product_rev_ptr));
+ printf("Video memory: %dkb\n", vbe_info->total_mem << 6);
+
+ modes = VBEPTR(vbe_info->vid_mode_ptr);
+ }
+
+ for(i=0; i<1024; i++) { /* impose an upper limit to avoid inf-loops */
+ if(modes[i] == 0xffff) {
+ break; /* reached the end */
+ }
+
+ mode_info = vbe_get_mode_info(modes[i] | VBE_MODE_LFB);
+ if(!mode_info || mode_info->xres != xsz || mode_info->yres != ysz) {
+ continue;
+ }
+ if(SAME_BPP(mode_info->bpp, bpp)) {
+ best = modes[i];
+ }
+ }
+
+ if(best) {
+ mode_info = vbe_get_mode_info(best);
+ } else {
+ printf("Requested video mode (%dx%d %dbpp) is unavailable\n", xsz, ysz, bpp);
+ return 0;
+ }
+
+ if(vbe_set_mode(best | VBE_MODE_LFB) == -1) {
+ printf("Failed to set video mode %dx%d %dbpp\n", mode_info->xres, mode_info->yres, mode_info->bpp);
+ return 0;
+ }
+
+ return (void*)mode_info->fb_addr;
+}
+
+int get_color_bits(int *rbits, int *gbits, int *bbits)
+{
+ if(!mode_info) {
+ return -1;
+ }
+ *rbits = mode_info->rmask_size;
+ *gbits = mode_info->gmask_size;
+ *bbits = mode_info->bmask_size;
+ return 0;
+}
+
+int get_color_mask(unsigned int *rmask, unsigned int *gmask, unsigned int *bmask)
+{
+ static unsigned int maskbits[] = {0, 1, 3, 7, 0xf, 0x1f, 0x3f, 0x7f, 0xff};
+ if(!mode_info) {
+ return -1;
+ }
+ *rmask = maskbits[mode_info->rmask_size] << mode_info->rpos;
+ *gmask = maskbits[mode_info->gmask_size] << mode_info->gpos;
+ *bmask = maskbits[mode_info->bmask_size] << mode_info->bpos;
+ return 0;
+}
+
+int get_color_shift(int *rshift, int *gshift, int *bshift)
+{
+ if(!mode_info) {
+ return -1;
+ }
+ *rshift = mode_info->rpos;
+ *gshift = mode_info->gpos;
+ *bshift = mode_info->bpos;
+ return 0;
+}
+