cdrom: change pause timing again
[pcsx_rearmed.git] / plugins / dfxvideo / gpulib_if.c
index 82bc38d..af35f3c 100644 (file)
 #include <stdlib.h>
 #include <string.h>
 #include "../gpulib/gpu.h"
+#include "../../include/arm_features.h"
+
+#if defined(__GNUC__) && (__GNUC__ >= 6 || (defined(__clang_major__) && __clang_major__ >= 10))
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+#endif
 
 #define u32 uint32_t
 
 
 // byteswappings
 
-#define SWAP16(x) ({ uint16_t y=(x); (((y)>>8 & 0xff) | ((y)<<8 & 0xff00)); })
-#define SWAP32(x) ({ uint32_t y=(x); (((y)>>24 & 0xfful) | ((y)>>8 & 0xff00ul) | ((y)<<8 & 0xff0000ul) | ((y)<<24 & 0xff000000ul)); })
+#define SWAP16(x) __builtin_bswap16(x)
+#define SWAP32(x) __builtin_bswap32(x)
 
-#ifdef __BIG_ENDIAN__
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
 
 // big endian config
 #define HOST2LE32(x) SWAP32(x)
 
 #endif
 
-#define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)X))
-#define GETLEs32(X) ((int16_t)GETLE32((uint16_t *)X))
+#define GETLEs16(X) ((int16_t)GETLE16((uint16_t *)(X)))
 
-#define GETLE16(X) LE2HOST16(*(uint16_t *)X)
-#define GETLE32_(X) LE2HOST32(*(uint32_t *)X)
-#define GETLE16D(X) ({uint32_t val = GETLE32(X); (val<<16 | val >> 16);})
-#define PUTLE16(X, Y) do{*((uint16_t *)X)=HOST2LE16((uint16_t)Y);}while(0)
-#define PUTLE32_(X, Y) do{*((uint32_t *)X)=HOST2LE16((uint32_t)Y);}while(0)
-#ifdef __arm__
-#define GETLE32(X) (*(uint16_t *)(X)|(((uint16_t *)(X))[1]<<16))
+#define GETLE16(X) LE2HOST16(*(uint16_t *)(X))
+#define GETLE32_(X) LE2HOST32(*(uint32_t *)(X))
+#define PUTLE16(X, Y) do{*((uint16_t *)(X))=HOST2LE16((uint16_t)(Y));}while(0)
+#define PUTLE32_(X, Y) do{*((uint32_t *)(X))=HOST2LE32((uint32_t)(Y));}while(0)
+#if defined(__arm__) && !defined(HAVE_ARMV6)
+// for (very) old ARMs with no unaligned loads?
+#define GETLE32(X) (*(uint16_t *)(X)|((uint32_t)((uint16_t *)(X))[1]<<16))
 #define PUTLE32(X, Y) do{uint16_t *p_=(uint16_t *)(X);uint32_t y_=Y;p_[0]=y_;p_[1]=y_>>16;}while(0)
 #else
 #define GETLE32 GETLE32_
@@ -219,18 +223,12 @@ extern int32_t           drawH;
 #define KEY_BADTEXTURES   128
 #define KEY_CHECKTHISOUT  256
 
-#if !defined(__BIG_ENDIAN__) || defined(__x86_64__) || defined(__i386__)
-#ifndef __LITTLE_ENDIAN__
-#define __LITTLE_ENDIAN__
-#endif
-#endif
-
-#ifdef __LITTLE_ENDIAN__
+#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
 #define RED(x) (x & 0xff)
 #define BLUE(x) ((x>>16) & 0xff)
 #define GREEN(x) ((x>>8) & 0xff)
 #define COLOR(x) (x & 0xffffff)
-#elif defined __BIG_ENDIAN__
+#else
 #define RED(x) ((x>>24) & 0xff)
 #define BLUE(x) ((x>>8) & 0xff)
 #define GREEN(x) ((x>>16) & 0xff)
@@ -239,12 +237,8 @@ extern int32_t           drawH;
 
 PSXDisplay_t      PSXDisplay;
 unsigned char  *psxVub;
-signed   char  *psxVsb;
 unsigned short *psxVuw;
 unsigned short *psxVuw_eom;
-signed   short *psxVsw;
-uint32_t *psxVul;
-int32_t  *psxVsl;
 
 long              lGPUstatusRet;
 uint32_t          lGPUInfoVals[16];
@@ -260,22 +254,25 @@ unsigned short sSetMask = 0;
 unsigned long  lSetMask = 0;
 long           lLowerpart;
 
+#if defined(__GNUC__) && __GNUC__ >= 6
+#pragma GCC diagnostic ignored "-Wmisleading-indentation"
+#endif
+
 #include "soft.c"
 #include "prim.c"
 
 /////////////////////////////////////////////////////////////////////////////
 
-int renderer_init(void)
+static void set_vram(void *vram)
 {
- psxVub=(void *)gpu.vram;
-
- psxVsb=(signed char *)psxVub;                         // different ways of accessing PSX VRAM
- psxVsw=(signed short *)psxVub;
- psxVsl=(int32_t *)psxVub;
+ psxVub=vram;
  psxVuw=(unsigned short *)psxVub;
- psxVul=(uint32_t *)psxVub;
-
  psxVuw_eom=psxVuw+1024*512;                           // pre-calc of end of vram
+}
+
+int renderer_init(void)
+{
+ set_vram(gpu.vram);
 
  PSXDisplay.RGB24        = FALSE;                      // init some stuff
  PSXDisplay.Interlaced   = FALSE;
@@ -294,18 +291,45 @@ int renderer_init(void)
  return 0;
 }
 
-extern const unsigned char cmd_lengths[256];
+void renderer_finish(void)
+{
+}
 
-void do_cmd_list(unsigned int *list, int list_len)
+void renderer_notify_res_change(void)
 {
-  unsigned int cmd, len;
+}
 
-  unsigned int *list_end = list + list_len;
+void renderer_notify_scanout_change(int x, int y)
+{
+}
+
+#include "../gpulib/gpu_timing.h"
+extern const unsigned char cmd_lengths[256];
+
+int do_cmd_list(uint32_t *list, int list_len,
+ int *cycles_sum_out, int *cycles_last, int *last_cmd)
+{
+  int cpu_cycles_sum = 0, cpu_cycles = *cycles_last;
+  unsigned int cmd = 0, len;
+  uint32_t *list_start = list;
+  uint32_t *list_end = list + list_len;
 
   for (; list < list_end; list += 1 + len)
   {
-    cmd = *list >> 24;
+    short *slist = (void *)list;
+    cmd = GETLE32(list) >> 24;
     len = cmd_lengths[cmd];
+    if (list + 1 + len > list_end) {
+      cmd = -1;
+      break;
+    }
+
+#ifndef TEST
+    if (0x80 <= cmd && cmd < 0xe0)
+      break; // image i/o, forward to upper layer
+    else if ((cmd & 0xf8) == 0xe0)
+      gpu.ex_regs[cmd & 7] = GETLE32(list);
+#endif
 
     primTableJ[cmd]((void *)list);
 
@@ -313,62 +337,117 @@ void do_cmd_list(unsigned int *list, int list_len)
     {
       case 0x48 ... 0x4F:
       {
-        u32 num_vertexes = 1;
-        u32 *list_position = &(list[2]);
+        u32 num_vertexes = 2;
+        u32 *list_position = &(list[3]);
 
         while(1)
         {
-          if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
+          gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));
+
+          if(list_position >= list_end) {
+            cmd = -1;
+            goto breakloop;
+          }
+
+          if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
             break;
 
           list_position++;
           num_vertexes++;
         }
 
-        if(num_vertexes > 2)
-          len += (num_vertexes - 2);
-
+        len += (num_vertexes - 2);
         break;
       }
 
       case 0x58 ... 0x5F:
       {
-        u32 num_vertexes = 1;
-        u32 *list_position = &(list[2]);
+        u32 num_vertexes = 2;
+        u32 *list_position = &(list[4]);
 
         while(1)
         {
-          if((*list_position & 0xf000f000) == 0x50005000 || list_position >= list_end)
+          gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));
+
+          if(list_position >= list_end) {
+            cmd = -1;
+            goto breakloop;
+          }
+
+          if((*list_position & HOST2LE32(0xf000f000)) == HOST2LE32(0x50005000))
             break;
 
           list_position += 2;
           num_vertexes++;
         }
 
-        if(num_vertexes > 2)
-          len += (num_vertexes - 2) * 2;
-
+        len += (num_vertexes - 2) * 2;
         break;
       }
 
 #ifdef TEST
       case 0xA0:          //  sys -> vid
       {
-        short *slist = (void *)list;
-        u32 load_width = slist[4];
-        u32 load_height = slist[5];
+        u32 load_width = LE2HOST16(slist[4]);
+        u32 load_height = LE2HOST16(slist[5]);
         u32 load_size = load_width * load_height;
 
         len += load_size / 2;
         break;
       }
 #endif
+
+      // timing
+      case 0x02:
+        gput_sum(cpu_cycles_sum, cpu_cycles,
+            gput_fill(LE2HOST16(slist[4]) & 0x3ff, LE2HOST16(slist[5]) & 0x1ff));
+        break;
+      case 0x20 ... 0x23: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base());    break;
+      case 0x24 ... 0x27: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_t());  break;
+      case 0x28 ... 0x2B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base());    break;
+      case 0x2C ... 0x2F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_t());  break;
+      case 0x30 ... 0x33: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_g());  break;
+      case 0x34 ... 0x37: gput_sum(cpu_cycles_sum, cpu_cycles, gput_poly_base_gt()); break;
+      case 0x38 ... 0x3B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_g());  break;
+      case 0x3C ... 0x3F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_quad_base_gt()); break;
+      case 0x40 ... 0x47: gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));        break;
+      case 0x50 ... 0x57: gput_sum(cpu_cycles_sum, cpu_cycles, gput_line(0));        break;
+      case 0x60 ... 0x63:
+        gput_sum(cpu_cycles_sum, cpu_cycles,
+            gput_sprite(LE2HOST16(slist[4]) & 0x3ff, LE2HOST16(slist[5]) & 0x1ff));
+        break;
+      case 0x64 ... 0x67:
+        gput_sum(cpu_cycles_sum, cpu_cycles,
+            gput_sprite(LE2HOST16(slist[6]) & 0x3ff, LE2HOST16(slist[7]) & 0x1ff));
+        break;
+      case 0x68 ... 0x6B: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(1, 1));   break;
+      case 0x70 ... 0x73:
+      case 0x74 ... 0x77: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(8, 8));   break;
+      case 0x78 ... 0x7B:
+      case 0x7C ... 0x7F: gput_sum(cpu_cycles_sum, cpu_cycles, gput_sprite(16, 16)); break;
     }
   }
+
+breakloop:
+  gpu.ex_regs[1] &= ~0x1ff;
+  gpu.ex_regs[1] |= lGPUstatusRet & 0x1ff;
+
+  *cycles_sum_out += cpu_cycles_sum;
+  *cycles_last = cpu_cycles;
+  *last_cmd = cmd;
+  return list - list_start;
 }
 
-void renderer_sync_ecmds(uint32_t *ecmds)
+void renderer_sync_ecmds(uint32_t *ecmds_)
 {
+#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
+  // the funcs below expect LE
+  uint32_t i, ecmds[8];
+  for (i = 1; i <= 6; i++)
+    ecmds[i] = HTOLE32(ecmds_[i]);
+#else
+  uint32_t *ecmds = ecmds_;
+#endif
   cmdTexturePage((unsigned char *)&ecmds[1]);
   cmdTextureWindow((unsigned char *)&ecmds[2]);
   cmdDrawAreaStart((unsigned char *)&ecmds[3]);
@@ -377,7 +456,7 @@ void renderer_sync_ecmds(uint32_t *ecmds)
   cmdSTP((unsigned char *)&ecmds[6]);
 }
 
-void renderer_update_caches(int x, int y, int w, int h)
+void renderer_update_caches(int x, int y, int w, int h, int state_changed)
 {
 }
 
@@ -395,4 +474,9 @@ void renderer_set_config(const struct rearmed_cbs *cbs)
 {
  iUseDither = cbs->gpu_peops.iUseDither;
  dwActFixes = cbs->gpu_peops.dwActFixes;
+ if (cbs->pl_set_gpu_caps)
+  cbs->pl_set_gpu_caps(0);
+ set_vram(gpu.vram);
 }
+
+// vim:ts=2:shiftwidth=2:expandtab