shithub: psxe

Download patch

ref: 54de596c313e459573724c1b580c763b52c5f6d7
parent: 61f58168b98ed956dc1adde1272fae68e9c63aa3
author: allkern <lisandroaalarcon@gmail.com>
date: Sun Apr 28 21:26:19 EDT 2024

Overall improvements

--- a/frontend/screen.c
+++ b/frontend/screen.c
@@ -133,29 +133,24 @@
 // int frame = 0;
 
 void psxe_screen_update(psxe_screen_t* screen) {
-    // void* vram = psx_get_vram(screen->psx);
-
-    // if (screen->field & 2) {
-    //     for (int y = screen->field & 1; y < 512; y += 2) {
-    //         memcpy(
-    //             ((uint8_t*)screen->buf) + (y * PSX_GPU_FB_STRIDE),
-    //             ((uint8_t*)vram) + (y * PSX_GPU_FB_STRIDE),
-    //             PSX_GPU_FB_STRIDE
-    //         );
-    //     }
-    // }
-
-    // screen->field += 1;
-    // screen->field &= 3;
-
     void* display_buf = screen->debug_mode ?
         psx_get_vram(screen->psx) : psx_get_display_buffer(screen->psx);
 
-    // if (screen->texture_height == 240) {
-    //     display_buf = screen->psx->gpu->vram + (screen->psx->gpu->disp_x + ((frame * 256) * 1024));
-
-    //     frame ^= 1;
-    // }
+    // printf("res=(%u,%u) off=(%u,%u) disp=(%u,%u-%u,%u) draw=(%u,%u-%u,%u) vres=%u\n",
+    //     screen->texture_width,
+    //     screen->texture_height,
+    //     screen->psx->gpu->disp_x,
+    //     screen->psx->gpu->disp_y,
+    //     screen->psx->gpu->disp_x1,
+    //     screen->psx->gpu->disp_y1,
+    //     screen->psx->gpu->disp_x2,
+    //     screen->psx->gpu->disp_y2,
+    //     screen->psx->gpu->draw_x1,
+    //     screen->psx->gpu->draw_y1,
+    //     screen->psx->gpu->draw_x2,
+    //     screen->psx->gpu->draw_y2,
+    //     screen->psx->gpu->disp_y2 - screen->psx->gpu->disp_y1
+    // );
 
     SDL_UpdateTexture(screen->texture, NULL, display_buf, PSX_GPU_FB_STRIDE);
     SDL_RenderClear(screen->renderer);
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -633,7 +633,7 @@
     uint32_t s = cpu->r[S];
     uint32_t t = cpu->r[rt];
 
-    DO_PENDING_LOAD;
+    uint32_t tp = t;
 
     uint32_t addr = s + IMM16S;
     uint32_t load = psx_bus_read32(cpu->bus, addr & 0xfffffffc);
@@ -641,6 +641,8 @@
     if (rt == cpu->load_d)
         t = cpu->load_v;
 
+    DO_PENDING_LOAD;
+
     int shift = (int)((addr & 0x3) << 3);
     uint32_t mask = (uint32_t)0x00FFFFFF >> shift;
     uint32_t value = (t & mask) | (load << (24 - shift)); 
@@ -647,6 +649,10 @@
 
     cpu->load_d = rt;
     cpu->load_v = value;
+
+    // printf("lwl rt=%u s=%08x t=%08x addr=%08x load=%08x (%08x) tp=%08x shift=%u mask=%08x value=%08x\n",
+    //     rt, s, t, addr, load, addr & 0xfffffffc, tp, shift, mask, value
+    // );
 }
 
 void psx_cpu_i_lw(psx_cpu_t* cpu) {
@@ -699,8 +705,6 @@
     uint32_t s = cpu->r[S];
     uint32_t t = cpu->r[rt];
 
-    DO_PENDING_LOAD;
-
     uint32_t addr = s + IMM16S;
     uint32_t load = psx_bus_read32(cpu->bus, addr & 0xfffffffc);
 
@@ -707,6 +711,8 @@
     if (rt == cpu->load_d)
         t = cpu->load_v;
 
+    DO_PENDING_LOAD;
+
     int shift = (int)((addr & 0x3) << 3);
     uint32_t mask = 0xFFFFFF00 << (24 - shift);
     uint32_t value = (t & mask) | (load >> shift); 
@@ -713,6 +719,10 @@
 
     cpu->load_d = rt;
     cpu->load_v = value;
+
+    // printf("lwl rt=%u s=%08x t=%08x addr=%08x load=%08x (%08x) tp=%08x shift=%u mask=%08x value=%08x\n",
+    //     rt, s, t, addr, load, addr & 0xfffffffc, tp, shift, mask, value
+    // );
 }
 
 void psx_cpu_i_sb(psx_cpu_t* cpu) {
@@ -1855,6 +1865,24 @@
     R_GC2 = gte_clamp_rgb(cpu, 2, R_MAC2 >> 4); \
     R_BC2 = gte_clamp_rgb(cpu, 3, R_MAC3 >> 4); }
 
+void gte_interpolate_color(psx_cpu_t* cpu, uint64_t mac1, uint64_t mac2, uint64_t mac3) {
+    R_MAC1 = (int)(gte_clamp_mac(cpu, 1, ((long)R_RFC << 12) - mac1));
+    R_MAC2 = (int)(gte_clamp_mac(cpu, 2, ((long)R_GFC << 12) - mac2));
+    R_MAC3 = (int)(gte_clamp_mac(cpu, 3, ((long)R_BFC << 12) - mac3));
+
+    R_IR1 = gte_clamp_ir(cpu, 1, R_MAC1, cpu->gte_lm);
+    R_IR2 = gte_clamp_ir(cpu, 2, R_MAC2, cpu->gte_lm);
+    R_IR3 = gte_clamp_ir_z(cpu, cpu->s_mac3, cpu->gte_sf, cpu->gte_lm);
+
+    R_MAC1 = (int)(gte_clamp_mac(cpu, 1, ((long)R_IR1 * R_IR0) + mac1));
+    R_MAC2 = (int)(gte_clamp_mac(cpu, 2, ((long)R_IR2 * R_IR0) + mac2));
+    R_MAC3 = (int)(gte_clamp_mac(cpu, 3, ((long)R_IR3 * R_IR0) + mac3));
+
+    R_IR1 = gte_clamp_ir(cpu, 1, R_MAC1, cpu->gte_lm);
+    R_IR2 = gte_clamp_ir(cpu, 2, R_MAC2, cpu->gte_lm);
+    R_IR3 = gte_clamp_ir_z(cpu, cpu->s_mac3, cpu->gte_sf, cpu->gte_lm);
+}
+
 void psx_gte_i_rtps(psx_cpu_t* cpu) {
     GTE_RTP_DQ(0);
 }
@@ -2088,7 +2116,18 @@
 }
 
 void psx_gte_i_dcpl(psx_cpu_t* cpu) {
-    printf("dpcl: Unimplemented GTE instruction\n");
+    R_MAC1 = (int)(gte_clamp_mac(cpu, 1, R_RC * R_IR1) << 4);
+    R_MAC2 = (int)(gte_clamp_mac(cpu, 2, R_GC * R_IR2) << 4);
+    R_MAC3 = (int)(gte_clamp_mac(cpu, 3, R_BC * R_IR3) << 4);
+
+    gte_interpolate_color(cpu, R_MAC1, R_MAC2, R_MAC3);
+
+    R_RGB0 = R_RGB1;
+    R_RGB1 = R_RGB2;
+    R_CD2 = R_CODE;
+    R_RC2 = gte_clamp_rgb(cpu, 1, R_MAC1 >> 4);
+    R_GC2 = gte_clamp_rgb(cpu, 2, R_MAC2 >> 4);
+    R_BC2 = gte_clamp_rgb(cpu, 3, R_MAC3 >> 4);
 }
 
 void psx_gte_i_dpct(psx_cpu_t* cpu) {
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -263,7 +263,7 @@
             RESP_PUSH(
                 GETSTAT_MOTOR |
                 (cdrom->cdda_playing ? GETSTAT_PLAY : 0) |
-                // (cdrom->ongoing_read_command ? GETSTAT_READ : 0) |
+                (cdrom->ongoing_read_command ? GETSTAT_READ : 0) |
                 (cdrom->disc ? 0 : GETSTAT_TRAYOPEN)
             );
 
@@ -685,6 +685,43 @@
         } break;
     }
 }
+void cdrom_cmd_mute(psx_cdrom_t* cdrom) {
+    cdrom->delayed_command = CDL_NONE;
+
+    switch (cdrom->state) {
+        case CD_STATE_RECV_CMD: {
+            if (cdrom->pfifo_index) {
+                log_fatal("CdlMute: Expected exactly 0 parameters");
+
+                cdrom->irq_delay = DELAY_1MS;
+                cdrom->delayed_command = CDL_ERROR;
+                cdrom->state = CD_STATE_ERROR;
+                cdrom->error = ERR_PCOUNT;
+                cdrom->error_flags = GETSTAT_ERROR;
+
+                return;
+            }
+
+            cdrom->irq_delay = DELAY_1MS;
+            cdrom->delayed_command = CDL_MUTE;
+            cdrom->state = CD_STATE_SEND_RESP1;
+        } break;
+
+        case CD_STATE_SEND_RESP1: {
+            SET_BITS(ifr, IFR_INT, IFR_INT3);
+            RESP_PUSH(cdrom->stat);
+
+            if (cdrom->ongoing_read_command) {
+                cdrom->state = CD_STATE_SEND_RESP2;
+                cdrom->delayed_command = cdrom->ongoing_read_command;
+                cdrom->irq_delay = DELAY_1MS;
+            } else {
+                cdrom->delayed_command = CDL_NONE;
+                cdrom->state = CD_STATE_RECV_CMD;
+            }
+        } break;
+    } 
+}
 void cdrom_cmd_unmute(psx_cdrom_t* cdrom) {
     cdrom->delayed_command = CDL_NONE;
 
@@ -1455,7 +1492,7 @@
     "CdlStop",
     "CdlPause",
     "CdlInit",
-    "CdlUnimplemented",
+    "CdlMute",
     "CdlUnmute",
     "CdlSetfilter",
     "CdlSetmode",
@@ -1490,7 +1527,7 @@
     cdrom_cmd_stop,
     cdrom_cmd_pause,
     cdrom_cmd_init,
-    cdrom_cmd_unmute,
+    cdrom_cmd_mute,
     cdrom_cmd_unmute,
     cdrom_cmd_setfilter,
     cdrom_cmd_setmode,
--- a/psx/dev/cdrom.h
+++ b/psx/dev/cdrom.h
@@ -307,6 +307,7 @@
 void cdrom_cmd_stop(psx_cdrom_t*);
 void cdrom_cmd_pause(psx_cdrom_t*);
 void cdrom_cmd_init(psx_cdrom_t*);
+void cdrom_cmd_mute(psx_cdrom_t*);
 void cdrom_cmd_unmute(psx_cdrom_t*);
 void cdrom_cmd_setfilter(psx_cdrom_t*);
 void cdrom_cmd_setmode(psx_cdrom_t*);
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -221,6 +221,12 @@
 
     for (int y = ymin; y < ymax; y++) {
         for (int x = xmin; x < xmax; x++) {
+            int bc = (x >= gpu->draw_x1) && (x <= gpu->draw_x2) &&
+                     (y >= gpu->draw_y1) && (y <= gpu->draw_y2);
+
+            if (!bc)
+                continue;
+
             p.x = x;
             p.y = y;
 
@@ -501,7 +507,10 @@
     int y = y0;
 
     for (int x = x0; x < x1; x++) {
-        if ((x < 1024) && (y < 512) && (x >= 0) && (y >= 0))
+        int bc = (x >= gpu->draw_x1) && (x <= gpu->draw_x2) &&
+                 (y >= gpu->draw_y1) && (y <= gpu->draw_y2);
+
+        if ((x < 1024) && (y < 512) && (x >= 0) && (y >= 0) && bc)
             gpu->vram[x + (y * 1024)] = color;
 
         if (d > 0) {
@@ -525,8 +534,12 @@
     int x = x0;
 
     for (int y = y0; y < y1; y++) {
-        if ((x < 1024) && (y < 512) && (x >= 0) && (y >= 0))
+        int bc = (x >= gpu->draw_x1) && (x <= gpu->draw_x2) &&
+                 (y >= gpu->draw_y1) && (y <= gpu->draw_y2);
+
+        if ((x < 1024) && (y < 512) && (x >= 0) && (y >= 0) && bc)
             gpu->vram[x + (y * 1024)] = color;
+
         if (d > 0) {
             x = x + xi;
             d += (2 * (dx - dy));
@@ -574,6 +587,12 @@
 
     for (uint32_t y = ymin; y < ymax; y++) {
         for (uint32_t x = xmin; x < xmax; x++) {
+            int bc = (x >= gpu->draw_x1) && (x <= gpu->draw_x2) &&
+                     (y >= gpu->draw_y1) && (y <= gpu->draw_y2);
+
+            if (!bc)
+                continue;
+
             gpu->vram[x + (y * 1024)] = color;
         }
     }
@@ -1466,6 +1485,12 @@
 
                 for (uint32_t y = gpu->v0.y; y < (gpu->v0.y + gpu->ysiz); y++) {
                     for (uint32_t x = gpu->v0.x; x < (gpu->v0.x + gpu->xsiz); x++) {
+                        int bc = (x >= gpu->draw_x1) && (x <= gpu->draw_x2) &&
+                                 (y >= gpu->draw_y1) && (y <= gpu->draw_y2);
+
+                        if (!bc)
+                            continue;
+
                         if ((x < 1024) && (y < 512) && (x >= 0) && (y >= 0))
                             gpu->vram[x + (y * 1024)] = color;
                     }
@@ -1645,6 +1670,10 @@
                 case 0x06: {
                     gpu->disp_x1 = value & 0xfff;
                     gpu->disp_x2 = (value >> 12) & 0xfff;
+                } break;
+                case 0x07: {
+                    gpu->disp_y1 = value & 0x1ff;
+                    gpu->disp_y2 = (value >> 10) & 0x1ff;
                 } break;
                 case 0x08:
                     gpu->display_mode = value & 0xffffff;
--- a/psx/dev/gpu.h
+++ b/psx/dev/gpu.h
@@ -17,6 +17,7 @@
 // Use this when updating your texture
 #define PSX_GPU_FB_STRIDE 2048
 
+// 0x100000 * 2
 #define PSX_GPU_VRAM_SIZE (0x100000)
 
 #define PSX_GPU_CLOCK_NTSC 53693175 // 53.693175 MHz
--- a/psx/psx.c
+++ b/psx/psx.c
@@ -90,7 +90,15 @@
 }
 
 uint32_t psx_get_dmode_height(psx_t* psx) {
-    return (psx->gpu->display_mode & 0x4) ? 480 : 240;
+    if (psx->gpu->display_mode & 0x4)
+        return 480;
+
+    int disp = psx->gpu->disp_y2 - psx->gpu->disp_y1;
+
+    if (disp < (255-16))
+        return disp;
+
+    return 240;
 }
 
 double psx_get_display_aspect(psx_t* psx) {
--