+ if(num_vmodes >= max_modes) {
+ int newmax = max_modes ? (max_modes << 1) : 16;
+ if(!(vmptr = realloc(vmodes, newmax * sizeof *vmodes))) {
+ fprintf(stderr, "failed to grow video mode list (%d)\n", newmax);
+ free(vmodes);
+ return -1;
+ }
+ vmodes = vmptr;
+ max_modes = newmax;
+ }
+
+ vmptr = vmodes + num_vmodes++;
+ memset(vmptr, 0, sizeof *vmptr);
+ vmptr->mode = vbe.modes[i];
+ vmptr->xsz = minf.xres;
+ vmptr->ysz = minf.yres;
+ vmptr->bpp = minf.bpp;
+ vmptr->pitch = minf.scanline_bytes;
+ if(minf.mem_model == VBE_TYPE_DIRECT) {
+ vmptr->rbits = minf.rsize;
+ vmptr->gbits = minf.gsize;
+ vmptr->bbits = minf.bsize;
+ vmptr->rshift = minf.rpos;
+ vmptr->gshift = minf.gpos;
+ vmptr->bshift = minf.bpos;
+ vmptr->rmask = calc_mask(minf.rsize, minf.rpos);
+ vmptr->gmask = calc_mask(minf.gsize, minf.gpos);
+ vmptr->bmask = calc_mask(minf.bsize, minf.bpos);
+ /*vmptr->bpp = vmptr->rbits + vmptr->gbits + vmptr->bbits;*/
+ }
+ if(minf.attr & VBE_ATTR_LFB) {
+ vmptr->fb_addr = minf.fb_addr;
+ }
+ vmptr->max_pages = minf.num_img_pages;
+ vmptr->win_gran = minf.win_gran;
+
+ printf("%04x: ", vbe.modes[i]);
+ vbe_print_mode_info(stdout, &minf);
+ }
+ fflush(stdout);
+
+ vbe_init_ver = VBE_VER_MAJOR(vbe.ver);
+ return 0;
+}
+
+void cleanup_video(void)
+{
+ free(vmodes);
+}
+
+struct video_mode *video_modes(void)
+{
+ return vmodes;
+}
+
+int num_video_modes(void)
+{
+ return num_vmodes;
+}
+
+struct video_mode *get_video_mode(int idx)
+{
+ if(idx == VMODE_CURRENT) {
+ return curmode;
+ }
+ return vmodes + idx;
+}
+
+int match_video_mode(int xsz, int ysz, int bpp)
+{
+ int i, best = -1;
+ struct video_mode *vm;
+
+ for(i=0; i<num_vmodes; i++) {
+ vm = vmodes + i;
+ if(vm->xsz != xsz || vm->ysz != ysz) continue;
+ if(SAME_BPP(vm->bpp, bpp)) {
+ best = i;
+ }
+ if(vm->bpp == bpp) break;
+ }
+
+ if(best == -1) {
+ fprintf(stderr, "failed to find video mode %dx%d %d bpp)\n", xsz, ysz, bpp);
+ return -1;
+ }
+ return best;
+}
+
+int find_video_mode(int mode)
+{
+ int i;
+ struct video_mode *vm;
+
+ vm = vmodes;
+ for(i=0; i<num_vmodes; i++) {
+ if(vm->mode == mode) return i;
+ }
+ return -1;
+}
+
+void *set_video_mode(int idx, int nbuf)
+{
+ unsigned int mode;
+ struct video_mode *vm = vmodes + idx;
+
+ if(curmode == vm) return vpgaddr[0];
+
+ printf("setting video mode %x (%dx%d %d bpp)\n", (unsigned int)vm->mode,
+ vm->xsz, vm->ysz, vm->bpp);
+ fflush(stdout);
+
+ mode = vm->mode | VBE_MODE_LFB;
+ if(vbe_setmode(mode) == -1) {
+ mode = vm->mode;
+ if(vbe_setmode(mode) == -1) {
+ fprintf(stderr, "failed to set video mode %x\n", (unsigned int)vm->mode);