psx_gpu: rework enhancement buffer selection
[pcsx_rearmed.git] / plugins / gpu_neon / psx_gpu / psx_gpu_parse.c
index f920c73..67da86e 100644 (file)
@@ -688,11 +688,21 @@ u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
         }
         SET_Ex(2, list[0]);
         break;
-               }
+      }
+
+      case 0xE3:
+      {
+        s16 viewport_start_x = list[0] & 0x3FF;
+        s16 viewport_start_y = (list[0] >> 10) & 0x1FF;
+
+        if(viewport_start_x == psx_gpu->viewport_start_x &&
+         viewport_start_y == psx_gpu->viewport_start_y)
+        {
+          break;
+        }
   
-               case 0xE3:
-        psx_gpu->viewport_start_x = list[0] & 0x3FF;
-        psx_gpu->viewport_start_y = (list[0] >> 10) & 0x1FF;
+        psx_gpu->viewport_start_x = viewport_start_x;
+        psx_gpu->viewport_start_y = viewport_start_y;
 
 #ifdef TEXTURE_CACHE_4BPP
         psx_gpu->viewport_mask =
@@ -700,12 +710,23 @@ u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
          psx_gpu->viewport_end_y);
 #endif
-                       SET_Ex(3, list[0]);
-                       break;
-  
-               case 0xE4:
-        psx_gpu->viewport_end_x = list[0] & 0x3FF;
-        psx_gpu->viewport_end_y = (list[0] >> 10) & 0x1FF;
+        SET_Ex(3, list[0]);
+        break;
+      }
+
+      case 0xE4:
+      {
+        s16 viewport_end_x = list[0] & 0x3FF;
+        s16 viewport_end_y = (list[0] >> 10) & 0x1FF;
+
+        if(viewport_end_x == psx_gpu->viewport_end_x &&
+         viewport_end_y == psx_gpu->viewport_end_y)
+        {
+          break;
+        }
+
+        psx_gpu->viewport_end_x = viewport_end_x;
+        psx_gpu->viewport_end_y = viewport_end_y;
 
 #ifdef TEXTURE_CACHE_4BPP
         psx_gpu->viewport_mask =
@@ -713,10 +734,11 @@ u32 gpu_parse(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
          psx_gpu->viewport_start_y, psx_gpu->viewport_end_x,
          psx_gpu->viewport_end_y);
 #endif
-                       SET_Ex(4, list[0]);
-                       break;
+        SET_Ex(4, list[0]);
+        break;
+      }
   
-               case 0xE5:
+      case 0xE5:
       {
         s32 offset_x = list[0] << 21;
         s32 offset_y = list[0] << 10;
@@ -760,17 +782,44 @@ breakloop:
   return list - list_start;
 }
 
-static void *select_enhancement_buf_ptr(psx_gpu_struct *psx_gpu, u32 x)
+#ifdef PCSX
+
+#define ENH_BUF_TABLE_STEP (1024 / sizeof(psx_gpu->enhancement_buf_by_x16))
+
+static void update_enhancement_buf_table_from_hres(psx_gpu_struct *psx_gpu)
+{
+  u32 b, x, s;
+
+  b = 0;
+  s = psx_gpu->enhancement_x_threshold;
+  for (x = 0; x < sizeof(psx_gpu->enhancement_buf_by_x16); x++)
+  {
+    if (b < 3 && x * ENH_BUF_TABLE_STEP >= s - ENH_BUF_TABLE_STEP - 1)
+    {
+      s += psx_gpu->enhancement_x_threshold;
+      b++;
+    }
+    psx_gpu->enhancement_buf_by_x16[x] = b;
+  }
+}
+
+static void update_enhancement_buf_table_from_x(psx_gpu_struct *psx_gpu,
+ u32 x0, u32 len)
 {
-  u32 b;
-  for (b = 0; x >= psx_gpu->enhancement_x_threshold; b++)
-    x -= psx_gpu->enhancement_x_threshold;
-  return psx_gpu->enhancement_buf_ptr + b * 1024 * 1024;
+  u32 x, b;
+
+  for (x = x0, b = 0; x >= len; b++)
+    x -= len;
+  if (b > 3)
+    b = 3;
+
+  memset(psx_gpu->enhancement_buf_by_x16 + x0 / ENH_BUF_TABLE_STEP,
+   b, (len + ENH_BUF_TABLE_STEP - 1) / ENH_BUF_TABLE_STEP);
 }
 
 #define select_enhancement_buf(psx_gpu) \
   psx_gpu->enhancement_current_buf_ptr = \
-    select_enhancement_buf_ptr(psx_gpu, psx_gpu->saved_viewport_start_x + 8)
+    select_enhancement_buf_ptr(psx_gpu, psx_gpu->saved_viewport_start_x)
 
 #define enhancement_disable() { \
   psx_gpu->vram_out_ptr = psx_gpu->vram_ptr; \
@@ -864,6 +913,8 @@ static void do_quad_enhanced(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
   }
 }
 
+#if 0
+
 #define fill_vertex(i, x_, y_, u_, v_, rgb_) \
   vertexes[i].x = x_; \
   vertexes[i].y = y_; \
@@ -873,7 +924,7 @@ static void do_quad_enhanced(psx_gpu_struct *psx_gpu, vertex_struct *vertexes,
   vertexes[i].g = (rgb_) >> 8; \
   vertexes[i].b = (rgb_) >> 16
 
-static void do_esprite_in_triangles(psx_gpu_struct *psx_gpu, int x, int y,
+static void do_sprite_enhanced(psx_gpu_struct *psx_gpu, int x, int y,
  u32 u, u32 v, u32 w, u32 h, u32 cmd_rgb)
 {
   vertex_struct *vertex_ptrs[3];
@@ -928,8 +979,19 @@ static void do_esprite_in_triangles(psx_gpu_struct *psx_gpu, int x, int y,
 
   psx_gpu->render_state_base = render_state_base_saved;
 }
+#else
+static void do_sprite_enhanced(psx_gpu_struct *psx_gpu, int x, int y,
+ u32 u, u32 v, u32 w, u32 h, u32 cmd_rgb)
+{
+  u32 flags = (cmd_rgb >> 24);
+  u32 color = cmd_rgb & 0xffffff;
 
-u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_command)
+  render_sprite_4x(psx_gpu, x, y, u, v, w, h, flags, color);
+}
+#endif
+
+u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size,
+ u32 *last_command)
 {
   u32 current_command = 0, command_length;
 
@@ -972,7 +1034,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
 
         do_fill(psx_gpu, x, y, width, height, color);
 
-        psx_gpu->vram_out_ptr = psx_gpu->enhancement_current_buf_ptr;
+        psx_gpu->vram_out_ptr = select_enhancement_buf_ptr(psx_gpu, x);
         x *= 2;
         y *= 2;
         width *= 2;
@@ -1216,7 +1278,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
         u32 height = list_s16[5] & 0x1FF;
 
         render_sprite(psx_gpu, x, y, 0, 0, width, height, current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, 0, 0, width, height, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, 0, 0, width, height, list[0]);
         break;
       }
   
@@ -1233,7 +1295,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
 
         render_sprite(psx_gpu, x, y, u, v, width, height,
          current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, u, v, width, height, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, u, v, width, height, list[0]);
         break;
       }
   
@@ -1246,7 +1308,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
 
         render_sprite(psx_gpu, x, y, 0, 0, 1, 1, current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, 0, 0, 1, 1, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, 0, 0, 1, 1, list[0]);
         break;
       }
   
@@ -1259,7 +1321,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
 
         render_sprite(psx_gpu, x, y, 0, 0, 8, 8, current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, 0, 0, 8, 8, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, 0, 0, 8, 8, list[0]);
         break;
       }
   
@@ -1277,7 +1339,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
 
         render_sprite(psx_gpu, x, y, u, v, 8, 8,
          current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, u, v, 8, 8, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, u, v, 8, 8, list[0]);
         break;
       }
   
@@ -1290,7 +1352,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
         s32 y = sign_extend_11bit(list_s16[3] + psx_gpu->offset_y);
 
         render_sprite(psx_gpu, x, y, 0, 0, 16, 16, current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, 0, 0, 16, 16, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, 0, 0, 16, 16, list[0]);
         break;
       }
   
@@ -1307,7 +1369,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
         set_clut(psx_gpu, list_s16[5]);
 
         render_sprite(psx_gpu, x, y, u, v, 16, 16, current_command, list[0]);
-        do_esprite_in_triangles(psx_gpu, x, y, u, v, 16, 16, list[0]);
+        do_sprite_enhanced(psx_gpu, x, y, u, v, 16, 16, list[0]);
         break;
       }
   
@@ -1388,10 +1450,27 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
       }
   
       case 0xE3:
-        psx_gpu->viewport_start_x = list[0] & 0x3FF;
-        psx_gpu->viewport_start_y = (list[0] >> 10) & 0x1FF;
-        psx_gpu->saved_viewport_start_x = psx_gpu->viewport_start_x;
-        psx_gpu->saved_viewport_start_y = psx_gpu->viewport_start_y;
+      {
+        s16 viewport_start_x = list[0] & 0x3FF;
+        s16 viewport_start_y = (list[0] >> 10) & 0x1FF;
+        u32 d;
+
+        if(viewport_start_x == psx_gpu->viewport_start_x &&
+         viewport_start_y == psx_gpu->viewport_start_y)
+        {
+          break;
+        }
+        psx_gpu->viewport_start_x = viewport_start_x;
+        psx_gpu->viewport_start_y = viewport_start_y;
+        psx_gpu->saved_viewport_start_x = viewport_start_x;
+        psx_gpu->saved_viewport_start_y = viewport_start_y;
+
+        d = (u32)psx_gpu->viewport_end_x - (u32)viewport_start_x + 1;
+        if((u32)psx_gpu->enhancement_x_threshold - d <= 16)
+        {
+          update_enhancement_buf_table_from_x(psx_gpu,
+           viewport_start_x, d);
+        }
         select_enhancement_buf(psx_gpu);
 
 #ifdef TEXTURE_CACHE_4BPP
@@ -1402,12 +1481,32 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
 #endif
         SET_Ex(3, list[0]);
         break;
-  
+      }
+
       case 0xE4:
-        psx_gpu->viewport_end_x = list[0] & 0x3FF;
-        psx_gpu->viewport_end_y = (list[0] >> 10) & 0x1FF;
-        psx_gpu->saved_viewport_end_x = psx_gpu->viewport_end_x;
-        psx_gpu->saved_viewport_end_y = psx_gpu->viewport_end_y;
+      {
+        s16 viewport_end_x = list[0] & 0x3FF;
+        s16 viewport_end_y = (list[0] >> 10) & 0x1FF;
+        u32 d;
+
+        if(viewport_end_x == psx_gpu->viewport_end_x &&
+         viewport_end_y == psx_gpu->viewport_end_y)
+        {
+          break;
+        }
+
+        psx_gpu->viewport_end_x = viewport_end_x;
+        psx_gpu->viewport_end_y = viewport_end_y;
+        psx_gpu->saved_viewport_end_x = viewport_end_x;
+        psx_gpu->saved_viewport_end_y = viewport_end_y;
+
+        d = (u32)viewport_end_x - (u32)psx_gpu->viewport_start_x + 1;
+        if((u32)psx_gpu->enhancement_x_threshold - d <= 16)
+        {
+          update_enhancement_buf_table_from_x(psx_gpu,
+           psx_gpu->viewport_start_x, d);
+        }
+        select_enhancement_buf(psx_gpu);
 
 #ifdef TEXTURE_CACHE_4BPP
         psx_gpu->viewport_mask =
@@ -1417,6 +1516,7 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
 #endif
         SET_Ex(4, list[0]);
         break;
+      }
   
       case 0xE5:
       {
@@ -1454,13 +1554,14 @@ u32 gpu_parse_enhanced(psx_gpu_struct *psx_gpu, u32 *list, u32 size, u32 *last_c
     }
   }
 
-#ifdef PCSX
+  enhancement_disable();
+
 breakloop:
-#endif
-enhancement_disable();
   if (last_command != NULL)
     *last_command = current_command;
   return list - list_start;
 }
 
+#endif /* PCSX */
+
 // vim:shiftwidth=2:expandtab