shithub: psxe

Download patch

ref: bd3e55548dafd97ce02401010f0308d437889dae
parent: 4787a909b713b7f655172177fc8ea509cc1b2f17
author: allkern <lisandroaalarcon@gmail.com>
date: Thu Jul 6 19:56:38 EDT 2023

Fix GPU commands

--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -40,16 +40,26 @@
         case 0x00: {
             uint32_t data = 0x0;
 
-            if (gpu->c0_ysiz) {
-                data = *((uint32_t*)(&gpu->vram[gpu->c0_xpos + (gpu->c0_ypos * 1024)]));
+            if (gpu->c0_tsiz) {
+                data |= gpu->vram[gpu->c0_addr + (gpu->c0_xcnt + (gpu->c0_ycnt * 1024))];
 
-                gpu->c0_xsiz -= 2;
-                gpu->c0_xpos += 2;
+                gpu->c0_xcnt += 1;
 
-                if (gpu->c0_xsiz <= 0) {
-                    gpu->c0_ypos += 1;
-                    gpu->c0_ysiz -= 1;
+                if (gpu->c0_xcnt == gpu->c0_xsiz) {
+                    gpu->c0_ycnt += 1;
+                    gpu->c0_xcnt = 0;
                 }
+
+                data |= gpu->vram[gpu->c0_addr + (gpu->c0_xcnt + (gpu->c0_ycnt * 1024))] << 16;
+
+                gpu->c0_xcnt += 1;
+
+                if (gpu->c0_xcnt == gpu->c0_xsiz) {
+                    gpu->c0_ycnt += 1;
+                    gpu->c0_xcnt = 0;
+                }
+
+                gpu->c0_tsiz -= 2;
             }
 
             return data;
@@ -94,11 +104,11 @@
 
 #define EDGE(a, b, c) ((b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x))
 
-uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx, uint32_t tpy) {
+uint16_t gpu_fetch_texel(psx_gpu_t* gpu, uint16_t tx, uint16_t ty, uint32_t tpx, uint32_t tpy, int depth) {
     tx = (tx & ~gpu->texw_mx) | (gpu->texw_ox & gpu->texw_mx);
     ty = (ty & ~gpu->texw_my) | (gpu->texw_oy & gpu->texw_my);
 
-    switch (gpu->texp_d) {
+    switch (depth) {
         // 4-bit
         case 0: {
             uint16_t texel = gpu->vram[(tpx + (tx >> 2)) + ((tpy + ty) * 1024)];
@@ -124,20 +134,82 @@
     }
 }
 
-void gpu_render_flat_line(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, uint32_t color) {
-    double l = 640.0;
+void plotLineLow(psx_gpu_t* gpu, int x0, int y0, int x1, int y1, uint16_t color) {
+    int dx = x1 - x0;
+    int dy = y1 - y0;
+    int yi = 1;
+    if (dy < 0) {
+        yi = -1;
+        dy = -dy;
+    }
+    int d = (2 * dy) - dx;
+    int y = y0;
 
-    for (double p = 0.0; p < 1.0; p += 1.0 / l) {
-        unsigned int ax = (v0.x * p) + (v1.x * (1.0f - p));
-        unsigned int ay = (v0.y * p) + (v1.y * (1.0f - p));
+    for (int x = x0; x < x1; x++) {
+        gpu->vram[x + (y * 1024)] = color;
 
-        if ((ax > 1024) || (ay > 512))
-            continue;
+        if (d > 0) {
+            y += yi;
+            d += (2 * (dy - dx));
+        } else {
+            d += 2*dy;
+        }
+    }
+}
 
-        gpu->vram[ax + (ay * 1024)] = color;
+void plotLineHigh(psx_gpu_t* gpu, int x0, int y0, int x1, int y1, uint16_t color) {
+    int dx = x1 - x0;
+    int dy = y1 - y0;
+    int xi = 1;
+    if (dx < 0) {
+        xi = -1;
+        dx = -dx;
     }
+    int d = (2 * dx) - dy;
+    int x = x0;
+
+    for (int y = y0; y < y1; y++) {
+        gpu->vram[x + (y * 1024)] = color;
+        if (d > 0) {
+            x = x + xi;
+            d += (2 * (dx - dy));
+        } else {
+            d += 2*dx;
+        }
+    }
 }
 
+void plotLine(psx_gpu_t* gpu, int x0, int y0, int x1, int y1, uint16_t color) {
+    if (abs(y1 - y0) < abs(x1 - x0)) {
+        if (x0 > x1) {
+            plotLineLow(gpu, x1, y1, x0, y0, color);
+        } else {
+            plotLineLow(gpu, x0, y0, x1, y1, color);
+        }
+    } else {
+        if (y0 > y1) {
+            plotLineHigh(gpu, x1, y1, x0, y0, color);
+        } else {
+            plotLineHigh(gpu, x0, y0, x1, y1, color);
+        }
+    }
+}
+
+void gpu_render_flat_line(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, uint32_t color) {
+    plotLine(gpu, v0.x, v0.y, v1.x, v1.y, color);
+    // double l = 640.0;
+
+    // for (double p = 0.0; p < 1.0; p += 1.0 / l) {
+    //     unsigned int ax = (v0.x * p) + (v1.x * (1.0f - p));
+    //     unsigned int ay = (v0.y * p) + (v1.y * (1.0f - p));
+
+    //     if ((ax > 1024) || (ay > 512))
+    //         continue;
+
+    //     gpu->vram[ax + (ay * 1024)] = color;
+    // }
+}
+
 void gpu_render_flat_rectangle(psx_gpu_t* gpu, vertex_t v, uint32_t w, uint32_t h, uint32_t color) {
     /* Offset coordinates */
     v.x += gpu->off_x;
@@ -171,7 +243,7 @@
 
     for (int y = ymin; y < ymax; y++) {
         for (int x = xmin; x < xmax; x++) {
-            uint16_t color = gpu_fetch_texel(gpu, a.tx + xc, a.ty + yc, tpx, tpy);
+            uint16_t color = gpu_fetch_texel(gpu, a.tx + xc, a.ty + yc, tpx, tpy, gpu->texp_d);
 
             ++xc;
 
@@ -298,7 +370,7 @@
     }
 }
 
-void gpu_render_textured_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, uint32_t tpx, uint32_t tpy) {
+void gpu_render_textured_triangle(psx_gpu_t* gpu, vertex_t v0, vertex_t v1, vertex_t v2, uint32_t tpx, uint32_t tpy, int depth) {
     vertex_t a, b, c;
 
     a = v0;
@@ -341,7 +413,7 @@
                 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;
 
-                uint16_t color = gpu_fetch_texel(gpu, tx, ty, tpx, tpy);
+                uint16_t color = gpu_fetch_texel(gpu, tx, ty, tpx, tpy, depth);
 
                 if (!color) continue;
 
@@ -511,9 +583,9 @@
             if (!gpu->cmd_args_remaining) {
                 gpu->state = GPU_STATE_RECV_DATA;
 
+                uint32_t texp = gpu->buf[4] >> 16;
                 gpu->color = gpu->buf[0] & 0xffffff;
                 gpu->pal   = gpu->buf[2] >> 16;
-                gpu->texp  = gpu->buf[4] >> 16;
                 gpu->v0.tx = gpu->buf[2] & 0xff;
                 gpu->v0.ty = (gpu->buf[2] >> 8) & 0xff;
                 gpu->v1.tx = gpu->buf[4] & 0xff;
@@ -534,11 +606,12 @@
                 gpu->clut_x = (gpu->pal & 0x3f) << 4;
                 gpu->clut_y = (gpu->pal >> 6) & 0x1ff;
 
-                uint32_t tpx = (gpu->texp & 0xf) << 6;
-                uint32_t tpy = (gpu->texp & 0x10) << 4;
+                uint32_t tpx = (texp & 0xf) << 6;
+                uint32_t tpy = (texp & 0x10) << 4;
+                uint32_t depth = (texp >> 7) & 0x3;
 
-                gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy);
-                gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy);
+                gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy, depth);
+                gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy, depth);
 
                 gpu->state = GPU_STATE_RECV_CMD;
             }
@@ -558,9 +631,9 @@
             if (!gpu->cmd_args_remaining) {
                 gpu->state = GPU_STATE_RECV_DATA;
 
+                uint32_t texp = gpu->buf[4] >> 16;
                 gpu->color = gpu->buf[0] & 0xffffff;
                 gpu->pal   = gpu->buf[2] >> 16;
-                gpu->texp  = gpu->buf[4] >> 16;
                 gpu->v0.tx = gpu->buf[2] & 0xff;
                 gpu->v0.ty = (gpu->buf[2] >> 8) & 0xff;
                 gpu->v1.tx = gpu->buf[4] & 0xff;
@@ -581,11 +654,12 @@
                 gpu->clut_x = (gpu->pal & 0x3f) << 4;
                 gpu->clut_y = (gpu->pal >> 6) & 0x1ff;
 
-                uint32_t tpx = (gpu->texp & 0xf) << 6;
-                uint32_t tpy = (gpu->texp & 0x10) << 4;
+                uint32_t tpx = (texp & 0xf) << 6;
+                uint32_t tpy = (texp & 0x10) << 4;
+                int depth = (texp >> 7) & 0x3;
 
-                gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy);
-                gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy);
+                gpu_render_textured_triangle(gpu, gpu->v0, gpu->v1, gpu->v2, tpx, tpy, depth);
+                gpu_render_textured_triangle(gpu, gpu->v1, gpu->v2, gpu->v3, tpx, tpy, depth);
 
                 gpu->state = GPU_STATE_RECV_CMD;
             }
@@ -687,10 +761,18 @@
 
         case GPU_STATE_RECV_ARGS: {
             if (!gpu->cmd_args_remaining) {
-                gpu->c0_xpos = gpu->buf[1] & 0xffff;
-                gpu->c0_ypos = gpu->buf[1] >> 16;
+                gpu->c0_xcnt = 0;
+                gpu->c0_ycnt = 0;
+                uint32_t c0_xpos = gpu->buf[1] & 0xffff;
+                uint32_t c0_ypos = gpu->buf[1] >> 16;
                 gpu->c0_xsiz = gpu->buf[2] & 0xffff;
                 gpu->c0_ysiz = gpu->buf[2] >> 16;
+                c0_xpos = c0_xpos & 0x3ff;
+                c0_ypos = c0_ypos & 0x1ff;
+                gpu->c0_xsiz = ((gpu->c0_xsiz - 1) & 0x3ff) + 1;
+                gpu->c0_ysiz = ((gpu->c0_ysiz - 1) & 0x1ff) + 1;
+                gpu->c0_tsiz = ((gpu->c0_xsiz * gpu->c0_ysiz) + 1) & 0xfffffffe;
+                gpu->c0_addr = c0_xpos + (c0_ypos * 1024);
 
                 gpu->state = GPU_STATE_RECV_CMD;
             }
@@ -720,12 +802,6 @@
                 gpu->xsiz = (((gpu->xsiz & 0x3ff) + 0x0f) & 0xfffffff0);
                 gpu->ysiz = gpu->ysiz & 0x1ff;
 
-                log_fatal("Render flat rectangle pos=(%u, %u) siz=(%u, %u), color=%02x",
-                    gpu->v0.x, gpu->v0.y,
-                    gpu->xsiz, gpu->ysiz,
-                    gpu->color
-                );
-
                 gpu->v0.x += gpu->off_x;
                 gpu->v0.y += gpu->off_y;
 
@@ -743,9 +819,12 @@
         case 0x01: /* Cache clear */ break;
         case 0x02: gpu_cmd_02(gpu); break;
         case 0x28: gpu_cmd_28(gpu); break;
-        case 0x2c: gpu_cmd_2c(gpu); break;
+        case 0x2c: gpu_cmd_2d(gpu); break;
         case 0x2d: gpu_cmd_2d(gpu); break;
+        case 0x2e: gpu_cmd_2d(gpu); break;
+        case 0x2f: gpu_cmd_2d(gpu); break;
         case 0x30: gpu_cmd_30(gpu); break;
+        case 0x32: gpu_cmd_30(gpu); break;
         case 0x38: gpu_cmd_38(gpu); break;
         case 0x40: gpu_cmd_40(gpu); break;
         case 0x64: gpu_cmd_64(gpu); break;
--- a/psx/dev/gpu.h
+++ b/psx/dev/gpu.h
@@ -70,8 +70,10 @@
     uint32_t xcnt, ycnt;
     vertex_t v0, v1, v2, v3;
     uint32_t pal, texp;
-    uint32_t c0_xpos, c0_ypos;
+    uint32_t c0_xcnt, c0_ycnt;
+    uint32_t c0_addr;
     int c0_xsiz, c0_ysiz;
+    int c0_tsiz;
 
     // GPU state
     uint32_t state;
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -69,11 +69,11 @@
 
 uint32_t psx_pad_read32(psx_pad_t* pad, uint32_t offset) {
     switch (offset) {
-        case 0: log_fatal("RX read 32"); return pad_read_rx(pad);
-        case 4: log_fatal("ST read 32"); return pad_handle_stat_read(pad);
-        case 8: log_fatal("MD read 32"); return pad->mode;
-        case 10: log_fatal("CT read 32"); return pad->ctrl;
-        case 14: log_fatal("BD read 32"); return pad->baud;
+        case 0: return pad_read_rx(pad);
+        case 4: return pad_handle_stat_read(pad);
+        case 8: return pad->mode;
+        case 10: return pad->ctrl;
+        case 14: return pad->baud;
     }
 
     log_fatal("Unhandled 32-bit PAD read at offset %08x", offset);
@@ -83,11 +83,11 @@
 
 uint16_t psx_pad_read16(psx_pad_t* pad, uint32_t offset) {
     switch (offset) {
-        case 0: log_fatal("RX read 16"); return pad_read_rx(pad) & 0xffff;
-        case 4: log_fatal("ST read 16 %04x", pad_handle_stat_read(pad) & 0xffff); return pad_handle_stat_read(pad) & 0xffff;
-        case 8: log_fatal("MD read 16"); return pad->mode;
-        case 10: log_fatal("CT read 16 %04x", pad->ctrl & 0xffff); return pad->ctrl & 0xffff;
-        case 14: log_fatal("BD read 16"); return pad->baud;
+        case 0: return pad_read_rx(pad) & 0xffff;
+        case 4: return pad_handle_stat_read(pad) & 0xffff;
+        case 8: return pad->mode;
+        case 10: return pad->ctrl & 0xffff;
+        case 14: return pad->baud;
     }
 
     log_fatal("Unhandled 16-bit PAD read at offset %08x", offset);
@@ -97,11 +97,11 @@
 
 uint8_t psx_pad_read8(psx_pad_t* pad, uint32_t offset) {
     switch (offset) {
-        case 0: log_fatal("RX read 8 %02x", pad_read_rx(pad) & 0xff); return pad_read_rx(pad) & 0xff;
-        case 4: log_fatal("ST read 8"); return pad_handle_stat_read(pad) & 0xff;
-        case 8: log_fatal("MD read 8"); return pad->mode & 0xff;
-        case 10: log_fatal("CT read 8"); return pad->ctrl & 0xff;
-        case 14: log_fatal("BD read 8"); return pad->baud & 0xff;
+        case 0: return pad_read_rx(pad) & 0xff;
+        case 4: return pad_handle_stat_read(pad) & 0xff;
+        case 8: return pad->mode & 0xff;
+        case 10: return pad->ctrl & 0xff;
+        case 14: return pad->baud & 0xff;
     }
 
     log_fatal("Unhandled 8-bit PAD read at offset %08x", offset);
@@ -111,10 +111,10 @@
 
 void psx_pad_write32(psx_pad_t* pad, uint32_t offset, uint32_t value) {
     switch (offset) {
-        case 0: log_fatal("TX write 32 %08x", value); pad_write_tx(pad, value); return;
-        case 8: log_fatal("MD write 32 %08x", value); pad->mode = value & 0xffff; return;
-        case 10: log_fatal("CT write 32 %08x", value); pad_handle_ctrl_write(pad, value); return;
-        case 14: log_fatal("BD write 32 %08x", value); pad->baud = value & 0xffff; return;
+        case 0: pad_write_tx(pad, value); return;
+        case 8: pad->mode = value & 0xffff; return;
+        case 10: pad_handle_ctrl_write(pad, value); return;
+        case 14: pad->baud = value & 0xffff; return;
     }
 
     log_fatal("Unhandled 32-bit PAD write at offset %08x (%08x)", offset, value);
@@ -122,10 +122,10 @@
 
 void psx_pad_write16(psx_pad_t* pad, uint32_t offset, uint16_t value) {
     switch (offset) {
-        case 0: log_fatal("TX write 16 %04x", value); pad_write_tx(pad, value); return;
-        case 8: log_fatal("MD write 16 %04x", value); pad->mode = value; return;
-        case 10: log_fatal("CT write 16 %04x", value); pad_handle_ctrl_write(pad, value); return;
-        case 14: log_fatal("BD write 16 %04x", value); pad->baud = value; return;
+        case 0: pad_write_tx(pad, value); return;
+        case 8: pad->mode = value; return;
+        case 10: pad_handle_ctrl_write(pad, value); return;
+        case 14: pad->baud = value; return;
     }
 
     log_fatal("Unhandled 16-bit PAD write at offset %08x (%04x)", offset, value);
@@ -133,10 +133,10 @@
 
 void psx_pad_write8(psx_pad_t* pad, uint32_t offset, uint8_t value) {
     switch (offset) {
-        case 0: log_fatal("TX write 8 %02x", value); pad_write_tx(pad, value); return;
-        case 8: log_fatal("MD write 8 %02x", value); pad->mode = value; return;
-        case 10: log_fatal("CT write 8 %02x", value); pad_handle_ctrl_write(pad, value); return;
-        case 14: log_fatal("BD write 8 %02x", value); pad->baud = value; return;
+        case 0: pad_write_tx(pad, value); return;
+        case 8: pad->mode = value; return;
+        case 10: pad_handle_ctrl_write(pad, value); return;
+        case 14: pad->baud = value; return;
     }
 
     log_fatal("Unhandled 8-bit PAD write at offset %08x (%02x)", offset, value);
@@ -166,8 +166,6 @@
 
         if (pad->cycles_until_irq <= 0) {
             psx_ic_irq(pad->ic, IC_JOY);
-
-            log_fatal("PAD IRQ");
 
             pad->cycles_until_irq = 0;
         }
--