X-Git-Url: https://notaz.gp2x.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=plugins%2Fgpulib%2Fgpu.c;h=ed37b7131978fc7dbf5b705b4037ee8a33a2a302;hb=f770faad8e05014d16e9c1f3c46bfd76274695c6;hp=0e6fe63d6e30d76a1a9dea6302e0f44c300f5987;hpb=09159d99cd07a084d8643f87c6c23e86c79060ff;p=pcsx_rearmed.git diff --git a/plugins/gpulib/gpu.c b/plugins/gpulib/gpu.c index 0e6fe63d..ed37b713 100644 --- a/plugins/gpulib/gpu.c +++ b/plugins/gpulib/gpu.c @@ -10,6 +10,8 @@ #include #include +#include /* for calloc */ + #include "gpu.h" #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0])) @@ -21,7 +23,6 @@ #define unlikely(x) #define preload(...) #define noinline -#error huh #endif #define gpu_log(fmt, ...) \ @@ -39,6 +40,8 @@ static void finish_vram_transfer(int is_read); static noinline void do_cmd_reset(void) { + renderer_sync(); + if (unlikely(gpu.cmd_len > 0)) do_cmd_buffer(gpu.cmd_buffer, gpu.cmd_len); gpu.cmd_len = 0; @@ -51,7 +54,6 @@ static noinline void do_cmd_reset(void) static noinline void do_reset(void) { unsigned int i; - do_cmd_reset(); memset(gpu.regs, 0, sizeof(gpu.regs)); @@ -127,11 +129,11 @@ static noinline void get_gpu_info(uint32_t data) case 0x02: case 0x03: case 0x04: - case 0x05: gpu.gp0 = gpu.ex_regs[data & 7] & 0xfffff; break; + case 0x05: case 0x06: - gpu.gp0 = gpu.ex_regs[5] & 0xfffff; + gpu.gp0 = gpu.ex_regs[5] & 0x3fffff; break; case 0x07: gpu.gp0 = 2; @@ -143,13 +145,30 @@ static noinline void get_gpu_info(uint32_t data) } // double, for overdraw guard -#define VRAM_SIZE (1024 * 512 * 2 * 2) +#define VRAM_SIZE ((1024 * 512 * 2 * 2) + 4096) + +// Minimum 16-byte VRAM alignment needed by gpu_unai's pixel-skipping +// renderer/downscaler it uses in high res modes: +#ifdef GCW_ZERO + // On GCW platform (MIPS), align to 8192 bytes (1 TLB entry) to reduce # of + // fills. (Will change this value if it ever gets large page support) + #define VRAM_ALIGN 8192 +#else + #define VRAM_ALIGN 16 +#endif + +// vram ptr received from mmap/malloc/alloc (will deallocate using this) +static uint16_t *vram_ptr_orig = NULL; +#ifdef GPULIB_USE_MMAP static int map_vram(void) { - gpu.vram = gpu.mmap(VRAM_SIZE); + gpu.vram = vram_ptr_orig = gpu.mmap(VRAM_SIZE + (VRAM_ALIGN-1)); if (gpu.vram != NULL) { - gpu.vram += 4096 / 2; + // 4kb guard in front + gpu.vram += (4096 / 2); + // Align + gpu.vram = (uint16_t*)(((uintptr_t)gpu.vram + (VRAM_ALIGN-1)) & ~(VRAM_ALIGN-1)); return 0; } else { @@ -157,9 +176,54 @@ static int map_vram(void) return -1; } } +#else +static int map_vram(void) +{ + gpu.vram = vram_ptr_orig = (uint16_t*)calloc(VRAM_SIZE + (VRAM_ALIGN-1), 1); + if (gpu.vram != NULL) { + // 4kb guard in front + gpu.vram += (4096 / 2); + // Align + gpu.vram = (uint16_t*)(((uintptr_t)gpu.vram + (VRAM_ALIGN-1)) & ~(VRAM_ALIGN-1)); + return 0; + } else { + fprintf(stderr, "could not allocate vram, expect crashes\n"); + return -1; + } +} + +static int allocate_vram(void) +{ + gpu.vram = vram_ptr_orig = (uint16_t*)calloc(VRAM_SIZE + (VRAM_ALIGN-1), 1); + if (gpu.vram != NULL) { + // 4kb guard in front + gpu.vram += (4096 / 2); + // Align + gpu.vram = (uint16_t*)(((uintptr_t)gpu.vram + (VRAM_ALIGN-1)) & ~(VRAM_ALIGN-1)); + return 0; + } else { + fprintf(stderr, "could not allocate vram, expect crashes\n"); + return -1; + } +} +#endif long GPUinit(void) { +#ifndef GPULIB_USE_MMAP + if (gpu.vram == NULL) { + if (allocate_vram() != 0) { + printf("ERROR: could not allocate VRAM, exiting..\n"); + exit(1); + } + } +#endif + + //extern uint32_t hSyncCount; // in psxcounters.cpp + //extern uint32_t frame_counter; // in psxcounters.cpp + //gpu.state.hcnt = &hSyncCount; + //gpu.state.frame_count = &frame_counter; + int ret; ret = vout_init(); ret |= renderer_init(); @@ -170,10 +234,10 @@ long GPUinit(void) gpu.cmd_len = 0; do_reset(); - if (gpu.mmap != NULL) { + /*if (gpu.mmap != NULL) { if (map_vram() != 0) ret = -1; - } + }*/ return ret; } @@ -183,17 +247,24 @@ long GPUshutdown(void) renderer_finish(); ret = vout_finish(); - if (gpu.vram != NULL) { - gpu.vram -= 4096 / 2; - gpu.munmap(gpu.vram, VRAM_SIZE); + + if (vram_ptr_orig != NULL) { +#ifdef GPULIB_USE_MMAP + gpu.munmap(vram_ptr_orig, VRAM_SIZE); +#else + free(vram_ptr_orig); +#endif } - gpu.vram = NULL; + vram_ptr_orig = gpu.vram = NULL; return ret; } void GPUwriteStatus(uint32_t data) { + //senquack TODO: Would it be wise to add cmd buffer flush here, since + // status settings can affect commands already in buffer? + static const short hres[8] = { 256, 368, 320, 384, 512, 512, 640, 640 }; static const short vres[4] = { 240, 480, 256, 480 }; uint32_t cmd = data >> 24; @@ -300,6 +371,8 @@ static int do_vram_io(uint32_t *data, int count, int is_read) int l; count *= 2; // operate in 16bpp pixels + renderer_sync(); + if (gpu.dma.offset) { l = w - gpu.dma.offset; if (count < l) @@ -388,7 +461,7 @@ static noinline int do_cmd_list_skip(uint32_t *data, int count, int *last_cmd) switch (cmd) { case 0x02: - if ((list[2] & 0x3ff) > gpu.screen.w || ((list[2] >> 16) & 0x1ff) > gpu.screen.h) + if ((int)(list[2] & 0x3ff) > gpu.screen.w || (int)((list[2] >> 16) & 0x1ff) > gpu.screen.h) // clearing something large, don't skip do_cmd_list(list, 3, &dummy); else @@ -458,6 +531,12 @@ static noinline int do_cmd_buffer(uint32_t *data, int count) cmd = data[pos] >> 24; if (0xa0 <= cmd && cmd <= 0xdf) { + if (unlikely((pos+2) >= count)) { + // incomplete vram write/read cmd, can't consume yet + cmd = -1; + break; + } + // consume vram write/read cmd start_vram_transfer(data[pos + 1], data[pos + 2], (cmd & 0xe0) == 0xc0); pos += 3; @@ -522,7 +601,6 @@ void GPUwriteData(uint32_t data) long GPUdmaChain(uint32_t *rambase, uint32_t start_addr) { uint32_t addr, *list, ld_addr = 0; - uint32_t *llist_entry = NULL; int len, left, count; long cpu_cycles = 0; @@ -531,15 +609,6 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr) if (unlikely(gpu.cmd_len > 0)) flush_cmd_buffer(); - // ff7 sends it's main list twice, detect this - if (*gpu.state.frame_count == gpu.state.last_list.frame && - *gpu.state.hcnt - gpu.state.last_list.hcnt <= 1 && - gpu.state.last_list.cycles > 2048) - { - llist_entry = rambase + (gpu.state.last_list.addr & 0x1fffff) / 4; - *llist_entry |= 0x800000; - } - log_io("gpu_dma_chain\n"); addr = start_addr & 0xffffff; for (count = 0; (addr & 0x800000) == 0; count++) @@ -586,9 +655,6 @@ long GPUdmaChain(uint32_t *rambase, uint32_t start_addr) } } - if (llist_entry) - *llist_entry &= ~0x800000; - gpu.state.last_list.frame = *gpu.state.frame_count; gpu.state.last_list.hcnt = *gpu.state.hcnt; gpu.state.last_list.cycles = cpu_cycles; @@ -651,12 +717,15 @@ long GPUfreeze(uint32_t type, struct GPUFreeze *freeze) case 1: // save if (gpu.cmd_len > 0) flush_cmd_buffer(); + + renderer_sync(); memcpy(freeze->psxVRam, gpu.vram, 1024 * 512 * 2); memcpy(freeze->ulControl, gpu.regs, sizeof(gpu.regs)); memcpy(freeze->ulControl + 0xe0, gpu.ex_regs, sizeof(gpu.ex_regs)); freeze->ulStatus = gpu.status.reg; break; case 0: // load + renderer_sync(); memcpy(gpu.vram, freeze->psxVRam, 1024 * 512 * 2); memcpy(gpu.regs, freeze->ulControl, sizeof(gpu.regs)); memcpy(gpu.ex_regs, freeze->ulControl + 0xe0, sizeof(gpu.ex_regs)); @@ -689,6 +758,8 @@ void GPUupdateLace(void) return; } + renderer_notify_update_lace(0); + if (!gpu.state.fb_dirty) return; @@ -704,6 +775,7 @@ void GPUupdateLace(void) vout_update(); gpu.state.fb_dirty = 0; gpu.state.blanked = 0; + renderer_notify_update_lace(1); } void GPUvBlank(int is_vblank, int lcf) @@ -740,6 +812,7 @@ void GPUrearmedCallbacks(const struct rearmed_cbs *cbs) gpu.state.allow_interlace = cbs->gpu_neon.allow_interlace; gpu.state.enhancement_enable = cbs->gpu_neon.enhancement_enable; + gpu.useDithering = cbs->gpu_neon.allow_dithering; gpu.mmap = cbs->mmap; gpu.munmap = cbs->munmap;