#include "vidsys.h"
#include "drv.h"
#include "vbe.h"
+#include "vga.h"
#include "cdpmi.h"
#define farptr_to_linear(rmaddr) \
static int init(void);
static void cleanup(void);
+static struct vid_modeinfo *find_mode(int mode);
static int setmode(int mode);
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 setwin(int wid, int pos);
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 void pack(uint32_t *pix, int r, int g, int b);
+static void unpack(uint32_t pix, int *r, int *g, int *b);
+static void clear(uint32_t color);
+static void blitfb_lfb(void *fb, int pitch);
+static void blitfb_banked(void *fb, int pitch);
+static void flip(int vsync);
+
static struct vid_driver drv;
static struct vid_drvops drvops = {init, cleanup, setmode, getmode};
static unsigned int vbe_ver;
static int cur_mode;
+static struct vid_modeinfo *cur_mi;
+static int cur_pgsize;
void vid_register_vbe(void)
struct vid_modeinfo modeinf;
cur_mode = -1;
+ cur_mi = 0;
vbe = dpmi_lowbuf();
bufseg = (intptr_t)vbe >> 4;
regs.eax = 0x4f00;
regs.es = bufseg;
dpmi_rmint(0x10, ®s);
- if(regs.eax != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) {
+ if((regs.eax & 0xffff) != 0x4f || memcmp(vbe->sig, "VESA", 4) != 0) {
fprintf(stderr, "failed to get VBE controller information\n");
return -1;
}
drv.num_modes = 0;
}
+static struct vid_modeinfo *find_mode(int mode)
+{
+ int i;
+ for(i=0; i<drv.num_modes; i++) {
+ if(drv.modes[i].modeno == mode) {
+ return drv.modes + i;
+ }
+ }
+ return 0;
+}
+
static int setmode(int mode)
{
+ struct vid_modeinfo *minf;
struct dpmi_regs regs = {0};
+ if((minf = find_mode(mode)) && minf->lfb) {
+ mode |= VBE_MODE_LFB;
+ }
+
+retry:
regs.eax = 0x4f02;
- regs.ebx = mode | VBE_MODE_LFB;
+ regs.ebx = mode;
dpmi_rmint(0x10, ®s);
- if(regs.eax != 0x4f) {
- regs.eax = 0x4f02;
- regs.ebx = mode;
- dpmi_rmint(0x10, ®s);
- if(regs.eax != 0x4f) {
- return -1;
+ if((regs.eax & 0xffff) != 0x4f) {
+ if(mode & VBE_MODE_LFB) {
+ mode &= ~VBE_MODE_LFB;
+ goto retry;
}
- cur_mode = mode;
+ return -1;
+ }
+ cur_mode = mode;
+
+ if(!(cur_mi = minf)) return 0;
+
+ cur_pgsize = minf->height * minf->pitch;
+
+ if(mode & VBE_MODE_LFB) {
+ minf->ops.blitfb = blitfb_lfb;
} else {
- cur_mode = mode | VBE_MODE_LFB;
+ minf->ops.blitfb = blitfb_banked;
}
return 0;
}
regs.ecx = mode;
regs.es = bufseg;
dpmi_rmint(0x10, ®s);
- if(regs.eax != 0x4f) {
+ if((regs.eax & 0xffff) != 0x4f) {
return -1;
}
return 0;
}
+static int setwin(int wid, int pos)
+{
+ struct dpmi_regs regs = {0};
+
+ regs.eax = 0x4f05;
+ regs.ebx = wid;
+ regs.edx = pos;
+ dpmi_rmint(0x10, ®s);
+ if((regs.eax & 0xffff) != 0x4f) {
+ return -1;
+ }
+ return 0;
+}
+
static int conv_vbeinfo(int mode, struct vid_modeinfo *mi, struct vbe_mode_info *vbemi)
{
+ static int gran_shift;
static const struct { int width, height, bpp; } stdmode[] = {
{640, 400, 8}, /* 100h */
{640, 480, 8}, /* 101h */
mi->pitch = vbemi->scanline_bytes;
mi->win_size = vbemi->win_size;
mi->win_gran = vbemi->win_gran;
+
+ gran_shift = 0;
+ mi->win_step = 1;
+ if(mi->win_gran > 0 && mi->win_gran < 64) {
+ int gran = mi->win_gran;
+ while(gran < 64) {
+ gran_shift++;
+ gran <<= 1;
+ }
+ mi->win_step = 1 << gran_shift;
+ }
+
+ mi->ops.pack = pack;
+ mi->ops.unpack = unpack;
+ mi->ops.setpal = vga_setpal;
+ mi->ops.getpal = vga_getpal;
+ mi->ops.vsync = vga_vsync;
+ mi->ops.clear = clear;
+ mi->ops.blitfb = 0;
+ mi->ops.flip = flip;
return 0;
}
}
return mask << pos;
}
+
+
+static void pack(uint32_t *pix, int r, int g, int b)
+{
+ *pix = (((uint32_t)r << cur_mi->rshift) & cur_mi->rmask) |
+ (((uint32_t)g << cur_mi->gshift) & cur_mi->gmask) |
+ (((uint32_t)b << cur_mi->bshift) & cur_mi->bmask);
+}
+
+static void unpack(uint32_t pix, int *r, int *g, int *b)
+{
+ *r = (pix & cur_mi->rmask) >> cur_mi->rshift;
+ *g = (pix & cur_mi->gmask) >> cur_mi->gshift;
+ *b = (pix & cur_mi->bmask) >> cur_mi->bshift;
+}
+
+static void clear(uint32_t color)
+{
+}
+
+static void blitfb_lfb(void *fb, int pitch)
+{
+ int i;
+ unsigned char *dest, *src;
+
+ dest = vid_vmem;
+ src = fb;
+
+ for(i=0; i<cur_mi->height; i++) {
+ memcpy(dest, src, cur_mi->pitch);
+ dest += cur_mi->pitch;
+ src += pitch;
+ }
+}
+
+static void blitfb_banked(void *fb, int pitch)
+{
+ int sz, offs, pending;
+ unsigned char *pptr = fb;
+
+ /* assume initial window offset at 0 */
+ offs = 0;
+ pending = cur_pgsize;
+ while(pending > 0) {
+ sz = pending > 65536 ? 65536 : pending;
+ memcpy((void*)0xa0000, pptr, sz);
+ pptr += sz;
+ pending -= sz;
+ offs += cur_mi->win_step;
+ setwin(0, offs);
+ }
+ setwin(0, 0);
+}
+
+static void flip(int vsync)
+{
+ /* TODO */
+}
struct vid_modeinfo *vm;
void *vmem;
+static const char *usage_fmt = "Usage %s: [options]\n"
+ "Options: \n"
+ " -s <XxY>: video resolution\n"
+ " -b <bpp>: color depth\n";
+
int main(int argc, char **argv)
{
+ int i;
int mode;
int xres = 320;
int yres = 200;
int bpp = 8;
+ for(i=1; i<argc; i++) {
+ if(argv[i][0] == '-') {
+ if(argv[i][2]) {
+invalopt: fprintf(stderr, "invalid option: %s\n", argv[i]);
+ return 1;
+ }
+ switch(argv[i][1]) {
+ case 's':
+ if(!argv[++i] || sscanf(argv[i], "%dx%d", &xres, &yres) != 2) {
+ fprintf(stderr, "invalid resolution: %s\n", argv[i]);
+ return 1;
+ }
+ break;
+
+ case 'b':
+ if(!argv[++i] || (bpp = atoi(argv[i])) <= 0) {
+ fprintf(stderr, "invalid color depth: %s\n", argv[i]);
+ return 1;
+ }
+
+ case 'h':
+ printf(usage_fmt, argv[0]);
+ return 0;
+
+ default:
+ goto invalopt;
+ }
+ } else {
+ fprintf(stderr, "unexpected argument: %s\n", argv[i]);
+ return 1;
+ }
+ }
+
+
if(vid_init() == -1) {
fprintf(stderr, "failed to initialize video\n");
return 1;
#include <stdlib.h>
#include <assert.h>
#include "vidsys.h"
+#include "vga.h"
#include "drv.h"
#include "cdpmi.h"
struct vid_driver *vid_drvlist[MAX_DRV];
int vid_numdrv;
+void *vid_vmem;
+int vid_vmem_size;
+
static struct vid_modeinfo **modes, *cur_mode;
static int num_modes, max_modes;
-static void *vmem;
-static int vmem_size;
int vid_init(void)
{
- int i, j;
+ int i, j, len;
+ struct vid_modeinfo *vm;
vid_numdrv = 0;
free(modes);
cur_mode = 0;
num_modes = max_modes = 0;
- vmem = 0;
- vmem_size = 0;
+ vid_vmem = 0;
+ vid_vmem_size = 0;
if(dpmi_init() == -1) {
return -1;
}
printf("found %d modes:\n", num_modes);
- for(i=0; i<num_modes; i++) {
- printf("[%6s] %04x: %dx%d %dbpp\n", modes[i]->drv->name, modes[i]->modeno,
- modes[i]->width, modes[i]->height, modes[i]->bpp);
+ for(i=0; i<num_modes; i+=2) {
+ vm = modes[i];
+ len = printf("[%4s] %04x: %dx%d %dbpp", vm->drv->name, vm->modeno,
+ vm->width, vm->height, vm->bpp);
+ if(i + 1 >= num_modes) {
+ putchar('\n');
+ break;
+ }
+ for(j=len; j<40; j++) putchar(' ');
+ vm = modes[i + 1];
+ printf("[%4s] %04x: %dx%d %dbpp\n", vm->drv->name, vm->modeno,
+ vm->width, vm->height, vm->bpp);
}
return 0;
vid_setmode(3);
}
- if(vmem >= (void*)0x100000) {
- dpmi_munmap(vmem);
+ if(vid_vmem >= (void*)0x100000) {
+ dpmi_munmap(vid_vmem);
}
for(i=0; i<vid_numdrv; i++) {
if(drv->ops->setmode(mode) == 0) {
cur_mode = modes[i];
- if(vmem >= (void*)0x100000) {
- assert(vmem_size);
- dpmi_munmap(vmem);
+ if(vid_vmem >= (void*)0x100000) {
+ assert(vid_vmem_size);
+ dpmi_munmap(vid_vmem);
}
if(modes[i]->vmem_addr < 0x100000) {
- vmem = (void*)modes[i]->vmem_addr;
- vmem_size = 0;
+ vid_vmem = (void*)modes[i]->vmem_addr;
+ vid_vmem_size = 0;
} else {
- vmem = dpmi_mmap(modes[i]->vmem_addr, modes[i]->vmem_size);
- vmem_size = modes[i]->vmem_size;
+ vid_vmem = dpmi_mmap(modes[i]->vmem_addr, modes[i]->vmem_size);
+ vid_vmem_size = modes[i]->vmem_size;
}
- return vmem;
+ return vid_vmem;
}
}
}