X-Git-Url: http://git.mutantstargoat.com/user/nuclear/?a=blobdiff_plain;f=src%2Fdos%2Fgfx.c;h=7e5db988c2088a07e5b444c7434879d5d34fee14;hb=4f2895e5c5c43241877cf2d183020d680d35d7c9;hp=c686e3540483555b5f859ead590100f3b7772e51;hpb=041f405d669f940976cd8485821f0de5194cbe88;p=retrobench diff --git a/src/dos/gfx.c b/src/dos/gfx.c index c686e35..7e5db98 100644 --- a/src/dos/gfx.c +++ b/src/dos/gfx.c @@ -1,12 +1,18 @@ -#include #include #include +#include #include "cdpmi.h" #include "gfx.h" #include "vbe.h" #include "vga.h" #include "util.h" +#ifdef __DJGPP__ +#define VMEM_PTR ((void*)(0xa0000 + __djgpp_conventional_base)) +#else +#define VMEM_PTR ((void*)0xa0000) +#endif + #define SAME_BPP(a, b) \ ((a) == (b) || ((a) == 16 && (b) == 15) || ((a) == 15 && (b) == 16) || \ ((a) == 32 && (b) == 24) || ((a) == 24 && (b) == 32)) @@ -19,6 +25,9 @@ static void blit_frame_lfb(void *pixels, int vsync); static void blit_frame_banked(void *pixels, int vsync); static uint32_t calc_mask(int sz, int pos); +static void enable_wrcomb(uint32_t addr, int len); +static void print_mtrr(void); + static struct video_mode *vmodes; static int num_vmodes; @@ -90,13 +99,9 @@ int init_video(void) } 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; + vmptr->win_gran = minf.win_gran; printf("%04x: ", vbe.modes[i]); vbe_print_mode_info(stdout, &minf); @@ -167,6 +172,7 @@ void *set_video_mode(int idx, int nbuf) { unsigned int mode; struct video_mode *vm = vmodes + idx; + struct cpuid_info cpu; if(curmode == vm) return vpgaddr[0]; @@ -185,7 +191,7 @@ void *set_video_mode(int idx, int nbuf) } /* unmap previous video memory mapping, if there was one (switching modes) */ - if(vpgaddr[0] && vpgaddr[0] != (void*)0xa0000) { + if(vpgaddr[0] && vpgaddr[0] != VMEM_PTR) { dpmi_munmap(vpgaddr[0]); vpgaddr[0] = vpgaddr[1] = 0; } @@ -193,12 +199,19 @@ void *set_video_mode(int idx, int nbuf) curmode = vm; if(nbuf < 1) nbuf = 1; if(nbuf > 2) nbuf = 2; - pgcount = nbuf > vm->max_pages ? vm->max_pages : nbuf; + pgcount = nbuf > vm->max_pages + 1 ? vm->max_pages + 1 : nbuf; pgsize = vm->ysz * vm->pitch; fbsize = pgcount * pgsize; + if(vm->bpp > 8) { + printf("rgb mask: %x %x %x\n", (unsigned int)vm->rmask, + (unsigned int)vm->gmask, (unsigned int)vm->bmask); + printf("rgb shift: %d %d %d\n", vm->rshift, vm->gshift, vm->bshift); + } printf("pgcount: %d, pgsize: %d, fbsize: %d\n", pgcount, pgsize, fbsize); - printf("phys addr: %p\n", (void*)vm->fb_addr); + if(vm->fb_addr) { + printf("phys addr: %p\n", (void*)vm->fb_addr); + } fflush(stdout); if(vm->fb_addr) { @@ -222,11 +235,30 @@ void *set_video_mode(int idx, int nbuf) blit_frame = blit_frame_lfb; + if(read_cpuid(&cpu) != -1 && cpu.feat & CPUID_FEAT_MTRR) { + print_mtrr(); + enable_wrcomb(vm->fb_addr, fbsize); + } + } else { - vpgaddr[0] = (void*)0xa0000; + vpgaddr[0] = VMEM_PTR; vpgaddr[1] = 0; blit_frame = blit_frame_banked; + + /* calculate window granularity shift */ + vm->win_gran_shift = 0; + vm->win_64k_step = 1; + if(vm->win_gran > 0 && vm->win_gran < 64) { + int gran = vm->win_gran; + while(gran < 64) { + vm->win_gran_shift++; + gran <<= 1; + } + vm->win_64k_step = 1 << vm->win_gran_shift; + } + + printf("granularity: %dk (step: %d)\n", vm->win_gran, vm->win_64k_step); } /* allocate main memory framebuffer */ @@ -237,13 +269,14 @@ void *set_video_mode(int idx, int nbuf) return 0; } + fflush(stdout); return vpgaddr[0]; } int set_text_mode(void) { /* unmap previous video memory mapping, if there was one (switching modes) */ - if(vpgaddr[0] && vpgaddr[0] != (void*)0xa0000) { + if(vpgaddr[0] && vpgaddr[0] != VMEM_PTR) { dpmi_munmap(vpgaddr[0]); vpgaddr[0] = vpgaddr[1] = 0; } @@ -276,8 +309,7 @@ static void blit_frame_lfb(void *pixels, int vsync) static void blit_frame_banked(void *pixels, int vsync) { - int sz, offs; - unsigned int pending; + int sz, offs, pending; unsigned char *pptr = pixels; if(vsync) wait_vsync(); @@ -286,14 +318,14 @@ static void blit_frame_banked(void *pixels, int vsync) offs = 0; pending = pgsize; while(pending > 0) { - sz = pending > curmode->bank_size ? curmode->bank_size : pending; - //memcpy64((void*)0xa0000, pptr, sz >> 3); - memcpy((void*)0xa0000, pptr, sz); + sz = pending > 65536 ? 65536 : pending; + /*memcpy64(VMEM_PTR, pptr, sz >> 3);*/ + memcpy(VMEM_PTR, pptr, sz); pptr += sz; pending -= sz; - vbe_setwin(0, ++offs); + offs += curmode->win_64k_step; + vbe_setwin(0, offs); } - vbe_setwin(0, 0); } @@ -305,3 +337,160 @@ static uint32_t calc_mask(int sz, int pos) } return mask << pos; } + +#define get_msr(msr, low, high) \ + asm volatile( \ + "\r\trdmsr" \ + : "=a"(low), "=d"(high) \ + : "c"(msr)) + +#define set_msr(msr, low, high) \ + asm volatile( \ + "\r\twrmsr" \ + :: "c"(msr), "a"(low), "d"(high)) + +#define MSR_MTRRCAP 0xfe +#define MSR_MTRRDEFTYPE 0x2ff +#define MSR_MTRRBASE(x) (0x200 | ((x) << 1)) +#define MSR_MTRRMASK(x) (0x201 | ((x) << 1)) +#define MTRRDEF_EN 0x800 +#define MTRRCAP_HAVE_WC 0x400 +#define MTRRMASK_VALID 0x800 + +#define MTRR_WC 1 + +static int get_page_memtype(uint32_t addr, int num_ranges) +{ + int i; + uint32_t rlow, rhigh; + uint32_t base, mask; + + for(i=0; i 0) { + if(get_page_memtype(addr, num_ranges) != MTRR_WC) { + return 0; + } + addr += 4096; + len -= 4096; + } + return 1; +} + +static int alloc_mtrr(int num_ranges) +{ + int i; + uint32_t rlow, rhigh; + + for(i=0; i> 1; + mask |= mask >> 2; + mask |= mask >> 4; + mask |= mask >> 8; + mask |= mask >> 16; + mask = ~mask & 0xfffff000; + + printf(" ... mask: %08x\n", (unsigned int)mask); + + disable(); + get_msr(MSR_MTRRDEFTYPE, def, rhigh); + set_msr(MSR_MTRRDEFTYPE, def & ~MTRRDEF_EN, rhigh); + + set_msr(MSR_MTRRBASE(mtrr), addr | MTRR_WC, 0); + set_msr(MSR_MTRRMASK(mtrr), mask | MTRRMASK_VALID, 0); + + set_msr(MSR_MTRRDEFTYPE, def | MTRRDEF_EN, 0); + enable(); +} + +static const char *mtrr_names[] = { "N/A", "W C", "N/A", "N/A", "W T", "W P", "W B" }; + +static const char *mtrr_type_name(int type) +{ + if(type < 0 || type >= sizeof mtrr_names / sizeof *mtrr_names) { + return mtrr_names[0]; + } + return mtrr_names[type]; +} + +static void print_mtrr(void) +{ + int i, num_ranges; + uint32_t rlow, rhigh, base, mask; + + get_msr(MSR_MTRRCAP, rlow, rhigh); + num_ranges = rlow & 0xff; + + for(i=0; i