shithub: psxe

Download patch

ref: 059c3e335e16f9d52c4223ea3a620136c0551e6c
parent: cb6938d54b06d08d5750b45ac70f25c2d9e213e0
author: allkern <lisandroaalarcon@gmail.com>
date: Wed Sep 20 17:22:30 EDT 2023

Improve semi-transparency emulation

--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -172,8 +172,15 @@
     int clutx = (data.clut & 0x3f) << 4;
     int cluty = (data.clut >> 6) & 0x1ff;
     int depth = (data.texp >> 7) & 3;
-    //int transp = (data.texp >> 5) & 3;
+    int transp = (data.attrib & PA_TRANSP) != 0;
+    int transp_mode;
 
+    if (data.attrib & PA_TEXTURED) {
+        transp_mode = (data.texp >> 5) & 3;
+    } else {
+        transp_mode = (gpu->gpustat >> 5) & 3;
+    }
+
     a = v0;
 
     /* Ensure the winding order is correct */
@@ -211,7 +218,6 @@
             if ((z0 < 0) || (z1 < 0) || (z2 < 0))
                 continue;
 
-            uint16_t texel = 0;
             uint16_t color = 0;
             uint32_t mod   = 0;
 
@@ -245,11 +251,15 @@
                 uint32_t tx = ((z0 * a.tx) + (z1 * b.tx) + (z2 * c.tx)) / area;
                 uint32_t ty = ((z0 * a.ty) + (z1 * b.ty) + (z2 * c.ty)) / area;
 
-                texel = gpu_fetch_texel(gpu, tx, ty, tpx, tpy, clutx, cluty, depth);
+                uint16_t texel = gpu_fetch_texel(gpu, tx, ty, tpx, tpy, clutx, cluty, depth);
 
                 if (!texel)
                     continue;
 
+                if (transp) {
+                    transp = (texel & 0x8000) != 0;
+                }
+
                 if (data.attrib & PA_RAW) {
                     color = texel;
                 } else {
@@ -281,7 +291,7 @@
             int cg = ((color >> 5 ) & 0x1f) << 3;
             int cb = ((color >> 10) & 0x1f) << 3;
 
-            if (data.attrib & RA_TRANSP) {
+            if (transp) {
                 uint16_t back = gpu->vram[x + (y * 1024)];
 
                 int br = ((back >> 0 ) & 0x1f) << 3;
@@ -289,11 +299,11 @@
                 int bb = ((back >> 10) & 0x1f) << 3;
 
                 // Do we use transp or gpustat here?
-                switch ((gpu->gpustat >> 5) & 3) {
+                switch (transp_mode) {
                     case 0: {
-                        cr = (br / 2) + (cr / 2);
-                        cg = (bg / 2) + (cg / 2);
-                        cb = (bb / 2) + (cb / 2);
+                        cr = (0.5f * br) + (0.5f * cr);
+                        cg = (0.5f * bg) + (0.5f * cg);
+                        cb = (0.5f * bb) + (0.5f * cb);
                     } break;
                     case 1: {
                         cr = br + cr;
@@ -304,11 +314,11 @@
                         cr = br - cr;
                         cg = bg - cg;
                         cb = bb - cb;
-                    }
+                    } break;
                     case 3: {
-                        cr = br + (cr / 4);
-                        cg = bg + (cg / 4);
-                        cb = bb + (cb / 4);
+                        cr = br + (0.25 * cr);
+                        cg = bg + (0.25 * cg);
+                        cb = bb + (0.25 * cb);
                     } break;
                 }
 
@@ -336,6 +346,10 @@
         case RS_16X16   : { width = 16        ; height = 16         ; } break;
     }
 
+    int textured = (data.attrib & RA_TEXTURED) != 0;
+    int transp = (data.attrib & RA_TRANSP) != 0;
+    int transp_mode = (gpu->gpustat >> 5) & 3;
+
     int clutx = (data.clut & 0x3f) << 4;
     int cluty = (data.clut >> 6) & 0x1ff;
 
@@ -359,7 +373,7 @@
 
             uint16_t color;
 
-            if (data.attrib & RA_TEXTURED) {
+            if (textured) {
                 uint16_t texel = gpu_fetch_texel(
                     gpu,
                     data.v0.tx + xc, data.v0.ty + yc,
@@ -371,6 +385,10 @@
                 if (!texel)
                     goto skip;
 
+                if (transp) {
+                    transp = (texel & 0x8000) != 0;
+                }
+
                 int tr = ((texel >> 0 ) & 0x1f) << 3;
                 int tg = ((texel >> 5 ) & 0x1f) << 3;
                 int tb = ((texel >> 10) & 0x1f) << 3;
@@ -394,7 +412,7 @@
             int cg = ((color >> 5 ) & 0x1f) << 3;
             int cb = ((color >> 10) & 0x1f) << 3;
 
-            if (data.attrib & RA_TRANSP) {
+            if (transp) {
                 uint16_t back = gpu->vram[x + (y * 1024)];
 
                 int br = ((back >> 0 ) & 0x1f) << 3;
@@ -401,11 +419,11 @@
                 int bg = ((back >> 5 ) & 0x1f) << 3;
                 int bb = ((back >> 10) & 0x1f) << 3;
 
-                switch ((gpu->gpustat >> 5) & 3) {
+                switch (transp_mode) {
                     case 0: {
-                        cr = (br / 2) + (cr / 2);
-                        cg = (bg / 2) + (cg / 2);
-                        cb = (bb / 2) + (cb / 2);
+                        cr = (0.5f * br) + (0.5f * cr);
+                        cg = (0.5f * bg) + (0.5f * cg);
+                        cb = (0.5f * bb) + (0.5f * cb);
                     } break;
                     case 1: {
                         cr = br + cr;
@@ -416,14 +434,18 @@
                         cr = br - cr;
                         cg = bg - cg;
                         cb = bb - cb;
-                    }
+                    } break;
                     case 3: {
-                        cr = br + (cr / 4);
-                        cg = bg + (cg / 4);
-                        cb = bb + (cb / 4);
+                        cr = br + (0.25f * cr);
+                        cg = bg + (0.25f * cg);
+                        cb = bb + (0.25f * cb);
                     } break;
                 }
 
+                cr = (cr >= 0xff) ? 0xff : ((cr <= 0) ? 0 : cr);
+                cg = (cg >= 0xff) ? 0xff : ((cg <= 0) ? 0 : cg);
+                cb = (cb >= 0xff) ? 0xff : ((cb <= 0) ? 0 : cb);
+
                 uint32_t rgb = cr | (cg << 8) | (cb << 16);
 
                 color = BGR555(rgb);
@@ -840,15 +862,6 @@
                 poly.v[3].ty = (gpu->buf[2+3*texc_offset] >> 8) & 0xff;
 
                 if (poly.attrib & PA_QUAD) {
-                    // log_set_quiet(0);
-                    // log_fatal("v0=(%u, %u, %06x) v1=(%u, %u, %06x) v2=(%u, %u, %06x) co=%u vo=%u tco=%u tpo=%u",
-                    //     poly.v[0].x, poly.v[0].y, poly.v[0].c,
-                    //     poly.v[1].x, poly.v[1].y, poly.v[1].c,
-                    //     poly.v[2].x, poly.v[2].y, poly.v[2].c,
-                    //     color_offset, vert_offset,
-                    //     texc_offset, texp_offset
-                    // );
-                    // log_set_quiet(1);
                     gpu_render_triangle(gpu, poly.v[0], poly.v[1], poly.v[2], poly);
                     gpu_render_triangle(gpu, poly.v[1], poly.v[2], poly.v[3], poly);
                 } else {
@@ -1658,6 +1671,8 @@
 #define GPU_CYCLES_PER_SCANL_NTSC 3413.0f
 #define GPU_SCANS_PER_VDRAW_NTSC 240
 #define GPU_SCANS_PER_FRAME_NTSC 263
+#define GPU_CYCLES_PER_SCANL_PAL 3406.0f
+#define GPU_SCANS_PER_FRAME_PAL  314
 
 void gpu_hblank_event(psx_gpu_t* gpu) {
     gpu->line++;
--