Make sure hardware registers are manipulated as little-endian
[pcsx_rearmed.git] / plugins / gpulib / gpu.c
index 17386b4..f89e52d 100644 (file)
@@ -40,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;
@@ -52,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));
@@ -89,6 +90,8 @@ static noinline void update_height(void)
 
 static noinline void decide_frameskip(void)
 {
+  *gpu.frameskip.dirty = 1;
+
   if (gpu.frameskip.active)
     gpu.frameskip.cnt++;
   else {
@@ -96,7 +99,9 @@ static noinline void decide_frameskip(void)
     gpu.frameskip.frame_ready = 1;
   }
 
-  if (!gpu.frameskip.active && *gpu.frameskip.advice)
+  if (*gpu.frameskip.force)
+    gpu.frameskip.active = 1;
+  else if (!gpu.frameskip.active && *gpu.frameskip.advice)
     gpu.frameskip.active = 1;
   else if (gpu.frameskip.set > 0 && gpu.frameskip.cnt < gpu.frameskip.set)
     gpu.frameskip.active = 1;
@@ -370,6 +375,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)
@@ -528,6 +535,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;
@@ -708,12 +721,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));
@@ -746,6 +762,8 @@ void GPUupdateLace(void)
     return;
   }
 
+  renderer_notify_update_lace(0);
+
   if (!gpu.state.fb_dirty)
     return;
 
@@ -761,6 +779,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)
@@ -790,6 +809,8 @@ void GPUrearmedCallbacks(const struct rearmed_cbs *cbs)
 {
   gpu.frameskip.set = cbs->frameskip;
   gpu.frameskip.advice = &cbs->fskip_advice;
+  gpu.frameskip.force = &cbs->fskip_force;
+  gpu.frameskip.dirty = &cbs->fskip_dirty;
   gpu.frameskip.active = 0;
   gpu.frameskip.frame_ready = 1;
   gpu.state.hcnt = cbs->gpu_hcnt;