From 2ce1b12090b2571b05d9ea451986212e590b876a Mon Sep 17 00:00:00 2001 From: John Tsiombikas Date: Tue, 3 Mar 2020 16:04:19 +0200 Subject: [PATCH] fallback to banked modes if LFB is not available --- src/dos/gfx.c | 52 +++++++++++++++++++++++++++++----------------------- src/dos/gfx.h | 1 + src/dos/main.c | 52 +++++++++++++++++++++++++++++++++++++++++++++++----- src/dos/vbe.c | 2 ++ src/game.c | 3 +++ src/game.h | 2 ++ 6 files changed, 84 insertions(+), 28 deletions(-) diff --git a/src/dos/gfx.c b/src/dos/gfx.c index b610f18..61ac7db 100644 --- a/src/dos/gfx.c +++ b/src/dos/gfx.c @@ -1,5 +1,7 @@ #include #include +#include +#include "cdpmi.h" #include "gfx.h" #include "vbe.h" #include "vga.h" @@ -77,7 +79,14 @@ int init_video(void) vmptr->gmask = calc_mask(minf.gsize, minf.gpos); vmptr->bmask = calc_mask(minf.bsize, minf.bpos); } - vmptr->fb_addr = minf.fb_addr; + if(minf.attr & VBE_ATTR_LFB) { + vmptr->fb_addr = minf.fb_addr; + } else { + vmptr->bank_size = (uint32_t)minf.bank_size * 1024; + if(!vmptr->bank_size) { + vmptr->bank_size = 65536; + } + } vmptr->max_pages = minf.num_img_pages; printf("%04x: ", vbe.modes[i]); @@ -86,12 +95,6 @@ int init_video(void) fflush(stdout); vbe_init_ver = VBE_VER_MAJOR(vbe.ver); - if(vbe_init_ver < 2) { - fprintf(stderr, "VBE 2.0 required. Upgrade your video card or run univbe.\n"); - free(vmodes); - vmodes = 0; - return -1; - } return 0; } @@ -171,25 +174,28 @@ void *set_video_mode(int idx, int nbuf) printf("pgcount: %d, pgsize: %d, fbsize: %d\n", pgcount, pgsize, fbsize); printf("phys addr: %p\n", (void*)vm->fb_addr); - - vpgaddr[0] = (void*)dpmi_mmap(vm->fb_addr, fbsize); - if(!vpgaddr[0]) { - fprintf(stderr, "failed to map framebuffer (phys: %lx, size: %d)\n", - (unsigned long)vm->fb_addr, fbsize); - set_text_mode(); - return 0; - } - //memset(vpgaddr[0], 0xaa, fbsize); - - printf("vaddr: %p\n", vpgaddr[0]); fflush(stdout); - if(pgcount > 1) { - vpgaddr[1] = (char*)vpgaddr[0] + pgsize; - fbidx = 1; - page_flip(FLIP_NOW); /* start with the second page visible */ + if(vm->fb_addr) { + vpgaddr[0] = (void*)dpmi_mmap(vm->fb_addr, fbsize); + if(!vpgaddr[0]) { + fprintf(stderr, "failed to map framebuffer (phys: %lx, size: %d)\n", + (unsigned long)vm->fb_addr, fbsize); + set_text_mode(); + return 0; + } + memset(vpgaddr[0], 0xaa, fbsize); + + if(pgcount > 1) { + vpgaddr[1] = (char*)vpgaddr[0] + pgsize; + fbidx = 1; + page_flip(FLIP_NOW); /* start with the second page visible */ + } else { + fbidx = 0; + vpgaddr[1] = 0; + } } else { - fbidx = 0; + vpgaddr[0] = (void*)0xa0000; vpgaddr[1] = 0; } return vpgaddr[0]; diff --git a/src/dos/gfx.h b/src/dos/gfx.h index 731ab14..9556af1 100644 --- a/src/dos/gfx.h +++ b/src/dos/gfx.h @@ -11,6 +11,7 @@ struct video_mode { uint32_t rmask, gmask, bmask; uint32_t fb_addr; short max_pages; + uint32_t bank_size; }; #ifdef __cplusplus diff --git a/src/dos/main.c b/src/dos/main.c index ca57152..c344df1 100644 --- a/src/dos/main.c +++ b/src/dos/main.c @@ -12,11 +12,15 @@ static void draw(void); static struct video_mode *vmode; +static void swap_lfb(void *pixels); +static void swap_banked(void *pixels); + int main(int argc, char **argv) { + void *fb_buf; struct video_mode *vmodes; - int vmidx; + int vmidx, status = 0; init_logger("game.log"); @@ -36,9 +40,22 @@ int main(int argc, char **argv) } vmode = vmodes + vmidx; + if(vmode->fb_addr) { + swap_buffers = swap_lfb; + } else { + swap_buffers = swap_banked; + } + fb_width = vmode->xsz; fb_height = vmode->ysz; - fb_size = (vmode->xsz * vmode->bpp / 8) * vmode->ysz; + fb_size = vmode->pitch * vmode->ysz; + + if(!(fb_buf = malloc(fb_size + vmode->pitch * 2))) { + fprintf(stderr, "failed to allocate framebuffer\n"); + status = -1; + goto break_evloop; + } + fb_pixels = (char*)fb_buf + vmode->pitch; reset_timer(); @@ -53,16 +70,17 @@ int main(int argc, char **argv) } break_evloop: + free(fb_buf); set_text_mode(); cleanup_video(); kb_shutdown(); - return 0; + return status; } static void draw(void) { int i, j; - uint16_t *pptr = vmem; + uint16_t *pptr = fb_pixels; for(i=0; i 0) { + sz = pending > vmode->bank_size ? vmode->bank_size : pending; + memcpy(vmem, pptr, sz); + pptr += sz; + pending -= sz; + vbe_setwin(0, ++offs); + } + + vbe_setwin(0, 0); +} diff --git a/src/dos/vbe.c b/src/dos/vbe.c index 3ada182..713b792 100644 --- a/src/dos/vbe.c +++ b/src/dos/vbe.c @@ -191,6 +191,8 @@ void vbe_print_mode_info(FILE *fp, struct vbe_mode_info *minf) if(minf->attr & VBE_ATTR_LFB) { fprintf(fp, " lfb@%lx", (unsigned long)minf->fb_addr); + } else { + fprintf(fp, " %xkb/bank", (unsigned int)minf->bank_size); } fprintf(fp, " ["); diff --git a/src/game.c b/src/game.c index 91ddb23..0fc762d 100644 --- a/src/game.c +++ b/src/game.c @@ -6,6 +6,9 @@ void *fb_pixels, *vmem; long time_msec; +void (*swap_buffers)(void*); + + int game_init(int argc, char **argv) { return 0; diff --git a/src/game.h b/src/game.h index 12e051b..542aba2 100644 --- a/src/game.h +++ b/src/game.h @@ -10,6 +10,8 @@ extern void *fb_pixels, *vmem; extern long time_msec; +extern void (*swap_buffers)(void*); + /* special keys */ enum { KB_ESC = 27, -- 1.7.10.4