vbe
authorJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 24 Jun 2023 22:07:03 +0000 (01:07 +0300)
committerJohn Tsiombikas <nuclear@member.fsf.org>
Sat, 24 Jun 2023 22:07:03 +0000 (01:07 +0300)
drv_vbe.c
vidsys.c
vidsys.h

index e051692..59ec306 100644 (file)
--- a/drv_vbe.c
+++ b/drv_vbe.c
@@ -16,16 +16,19 @@ static int getmode(void);
 static const char *memsize_str(long sz);
 static int get_mode_info(int mode, struct vbe_mode_info *mi);
 static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi);
+static unsigned int calc_mask(int nbits, int pos);
 
-static struct vid_driver drv = {"vbe", 2};
+static struct vid_driver drv;
 static struct vid_drvops drvops = {init, cleanup, setmode, getmode};
-static struct vid_modeinfo *modes;
-static int num_modes;
 static unsigned int vbe_ver;
 
+static int cur_mode;
+
 
 void vid_register_vbe(void)
 {
+       drv.name = "vbe";
+       drv.prio = 2;
        drv.ops = &drvops;
 
        vid_drvlist[vid_numdrv++] = &drv;
@@ -42,6 +45,8 @@ static int init(void)
        int i, count;
        struct vid_modeinfo modeinf;
 
+       cur_mode = -1;
+
        vbe = dpmi_lowbuf();
        bufseg = (intptr_t)vbe >> 4;
 
@@ -57,7 +62,7 @@ static int init(void)
 
        vbe_ver = vbe->ver;
 
-       printf("Found VBE %d.%d\n", vbe_ver >> 8, vbe_ver & 0xff);
+       printf("Found VBE %d.%d\n", VBE_VER_MAJOR(vbe_ver), VBE_VER_MINOR(vbe_ver));
        printf("OEM: %s\n", (char*)farptr_to_linear(vbe->oem_name));
        if(vbe_ver >= 0x0200) {
                printf("%s - %s (%s)\n", (char*)farptr_to_linear(vbe->vendor),
@@ -81,31 +86,59 @@ static int init(void)
                modelist[i] = vbe_modelist[i];
        }
 
-       printf("found %d modes\n", count);
-       return 0;
-       num_modes = 0;
+       if(!(drv.modes = malloc(count * sizeof *drv.modes))) {
+               fprintf(stderr, "failed to allocate mode list\n");
+               free(modelist);
+               return -1;
+       }
+
+       drv.num_modes = 0;
        for(i=0; i<count; i++) {
                if(get_mode_info(modelist[i], &vbemi) == -1) {
                        continue;
                }
-               conv_vbeinfo(modelist[i], modes + num_modes++, &vbemi);
+               if(conv_vbeinfo(modelist[i], drv.modes + drv.num_modes, &vbemi) == -1) {
+                       continue;
+               }
+               drv.num_modes++;
        }
 
+       free(modelist);
        return 0;
 }
 
 static void cleanup(void)
 {
+       free(drv.modes);
+       drv.modes = 0;
+       drv.num_modes = 0;
 }
 
 static int setmode(int mode)
 {
-       return -1;
+       struct dpmi_regs regs = {0};
+
+       regs.eax = 0x4f02;
+       regs.ebx = mode | VBE_MODE_LFB;
+       dpmi_rmint(0x10, &regs);
+
+       if(regs.eax != 0x4f) {
+               regs.eax = 0x4f02;
+               regs.ebx = mode;
+               dpmi_rmint(0x10, &regs);
+               if(regs.eax != 0x4f) {
+                       return -1;
+               }
+               cur_mode = mode;
+       } else {
+               cur_mode = mode | VBE_MODE_LFB;
+       }
+       return 0;
 }
 
 static int getmode(void)
 {
-       return -1;
+       return cur_mode;
 }
 
 static const char *memsize_str(long sz)
@@ -149,17 +182,47 @@ static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info
        static const struct { int width, height, bpp; } stdmode[] = {
                {640, 400, 8},          /* 100h */
                {640, 480, 8},          /* 101h */
-               {800, 600, 4},          /* 102h */
-               {800, 600, 8},          /* 103h */
-               {1024, 768, 4},         /* 104h */
-               {1024, 768, 8},         /* 105h */
-               {1280, 1024, 4},        /* 106h */
-               {1280, 1024, 8}         /* 107h */
+               {800, 600, 4}, {800, 600, 8},           /* 102h - 103h */
+               {1024, 768, 4}, {1024, 768, 8},         /* 104h - 105h */
+               {1280, 1024, 4}, {1280, 1024, 8},       /* 106h - 107h */
+               {80, 60, 4}, {132, 25, 4}, {132, 43, 4}, {132, 50, 4}, {132, 60, 4},
+               {320, 200, 15}, {320, 200, 16}, {320, 200, 24}, /* 10dh - 10fh */
+               {640, 480, 15}, {640, 480, 16}, {640, 480, 24}, /* 110h - 112h */
+               {800, 600, 15}, {800, 600, 16}, {800, 600, 24}, /* 113h - 115h */
+               {1024, 768, 15}, {1024, 768, 16}, {1024, 768, 24}, /* 116h - 118h */
+               {1280, 1024, 15}, {1280, 1024, 16}, {1280, 1024, 24} /* 119h - 11bh */
        };
+
+       if(!(vbemi->attr & VBE_ATTR_AVAIL)) {
+               return -1;      /* ignore unsupported modes */
+       }
+       if(!(vbemi->attr & VBE_ATTR_GFX)) {
+               return -1;      /* ignore text modes */
+       }
+       if(vbemi->attr & VBE_ATTR_LFB) {
+               mi->lfb = 1;
+       }
+
+       mi->drv = &drv;
+       mi->modeno = mode;
+       mi->vmem_addr = 0xa0000;
+
        if(vbe_ver >= 0x0102) {
                mi->width = vbemi->xres;
                mi->height = vbemi->yres;
                mi->bpp = vbemi->bpp;
+               mi->rshift = vbemi->rpos;
+               mi->gshift = vbemi->gpos;
+               mi->bshift = vbemi->bpos;
+               mi->rmask = calc_mask(vbemi->rsize, vbemi->rpos);
+               mi->gmask = calc_mask(vbemi->gsize, vbemi->gpos);
+               mi->bmask = calc_mask(vbemi->bsize, vbemi->bpos);
+               mi->pages = vbemi->num_img_pages + 1;
+
+               if(vbe_ver >= 0x0200) {
+                       mi->vmem_addr = vbemi->fb_addr;
+                       mi->vmem_size = vbemi->scanline_bytes * mi->height * mi->pages;
+               }
        } else {
                if((mode & 0xff) > 7) {
                        return -1;
@@ -168,5 +231,20 @@ static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info
                mi->height = stdmode[mode & 0xff].height;
                mi->bpp = stdmode[mode & 0xff].bpp;
        }
+       mi->ncolors = 1 << mi->bpp;
+       mi->pitch = vbemi->scanline_bytes;
+       mi->win_size = vbemi->win_size;
+       mi->win_gran = vbemi->win_gran;
        return 0;
 }
+
+static unsigned int calc_mask(int nbits, int pos)
+{
+       int i;
+       unsigned int mask = 0;
+
+       for(i=0; i<nbits; i++) {
+               mask = (mask << 1) | 1;
+       }
+       return mask << pos;
+}
index 43913c8..66f6811 100644 (file)
--- a/vidsys.c
+++ b/vidsys.c
@@ -42,7 +42,7 @@ int vid_init(void)
 
                for(j=0; j<drv->num_modes; j++) {
                        if(num_modes >= max_modes) {
-                               int newsz = max_modes ? max_modes * 2 : 8;
+                               int newsz = max_modes ? max_modes * 2 : 128;
                                void *tmp = realloc(modes, newsz * sizeof *modes);
                                if(!tmp) {
                                        fprintf(stderr, "failed to allocate modes list\n");
index f2e308c..34e35ed 100644 (file)
--- a/vidsys.h
+++ b/vidsys.h
@@ -40,13 +40,15 @@ struct vid_driver {
 
 struct vid_modeinfo {
        int modeno;
-       int width, height, bpp, ncolors;
+       int width, height, bpp, pitch;
+       int ncolors;
        uint32_t rmask, gmask, bmask;
        int rshift, gshift, bshift;
        int pages;
        int win_size, win_gran;
        uint32_t vmem_addr;
        size_t vmem_size;
+       int lfb;
 
        struct vid_driver *drv;
        struct vid_gfxops ops;