shithub: psxe

Download patch

ref: 61f58168b98ed956dc1adde1272fae68e9c63aa3
parent: feef8a15f6a77f611d0dfd88bbfdbb3447232b54
author: allkern <lisandroaalarcon@gmail.com>
date: Thu Apr 25 20:13:23 EDT 2024

Compatibility improvements

--- a/frontend/config.c
+++ b/frontend/config.c
@@ -83,6 +83,7 @@
     cfg->help_model = 0;
     cfg->help_region = 0;
     cfg->model = "scph1001";
+    cfg->scale = 3;
     cfg->psxe_version = STR(REP_VERSION);
     cfg->region = "ntsc";
     cfg->settings_path = NULL;
@@ -104,6 +105,7 @@
     int log_level = 0;
     int quiet = 0;
     int console_source = 0;
+    int scale = 0;
     const char* settings_path = NULL;
     const char* bios = NULL;
     const char* bios_search = NULL;
@@ -133,6 +135,7 @@
         OPT_INTEGER ('L', "log-level"     , &log_level     , "Set log level"),
         OPT_STRING  ('M', "model"         , &model         , "Specify console model (SPCH-XXXX)", NULL, 0, 0),
         OPT_STRING  ('r', "region"        , &region        , "Specify console region"),
+        OPT_INTEGER ('s', "scale"         , &scale         , "Display scaling factor", NULL, 0, 0),
         OPT_STRING  ('S', "settings-file" , &settings_path , "Specify settings file path", NULL, 0, 0),
         OPT_BOOLEAN ('q', "quiet"         , &quiet         , "Silence all logs (ignores -L)"),
         OPT_STRING  ('x', "exe"           , &exe           , "Launch a PS-X EXE file"),
@@ -280,6 +283,9 @@
 
     if (exp_path)
         cfg->exp_path = exp_path;
+
+    if (scale)
+        cfg->scale = scale;
 }
 
 // To-do: Implement BIOS searching
--- a/frontend/config.h
+++ b/frontend/config.h
@@ -15,6 +15,7 @@
     int log_level;
     int quiet;
     int console_source;
+    int scale;
     const char* snap_path;
     const char* settings_path;
     const char* bios;
--- a/frontend/main.c
+++ b/frontend/main.c
@@ -43,7 +43,7 @@
 
     psxe_screen_t* screen = psxe_screen_create();
     psxe_screen_init(screen, psx);
-    psxe_screen_set_scale(screen, 3);
+    psxe_screen_set_scale(screen, cfg->scale);
     psxe_screen_reload(screen);
 
     SDL_Init(SDL_INIT_AUDIO);
--- a/psx/cpu.c
+++ b/psx/cpu.c
@@ -1795,6 +1795,66 @@
     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); }
 
+#define NCS(i) { \
+    R_FLAG = 0; \
+    int64_t vx = (int64_t)((int16_t)cpu->cop2_dr.v[i].p[0]); \
+    int64_t vy = (int64_t)((int16_t)cpu->cop2_dr.v[i].p[1]); \
+    int64_t vz = (int64_t)cpu->cop2_dr.v[i].z; \
+    R_MAC1 = (int)(gte_clamp_mac(cpu, 1, (int64_t)R_L11 * vx + R_L12 * vy + R_L13 * vz)); \
+    R_MAC2 = (int)(gte_clamp_mac(cpu, 2, (int64_t)R_L21 * vx + R_L22 * vy + R_L23 * vz)); \
+    R_MAC3 = (int)(gte_clamp_mac(cpu, 3, (int64_t)R_L31 * vx + R_L32 * vy + R_L33 * vz)); \
+    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, gte_clamp_mac(cpu, 1, gte_clamp_mac(cpu, 1, (long)R_RBK * 0x1000 + R_LR1 * R_IR1) + (long)R_LG1 * R_IR2) + (long)R_LB1 * R_IR3)); \
+    R_MAC2 = (int)(gte_clamp_mac(cpu, 2, gte_clamp_mac(cpu, 2, gte_clamp_mac(cpu, 2, (long)R_GBK * 0x1000 + R_LR2 * R_IR1) + (long)R_LG2 * R_IR2) + (long)R_LB2 * R_IR3)); \
+    R_MAC3 = (int)(gte_clamp_mac(cpu, 3, gte_clamp_mac(cpu, 3, gte_clamp_mac(cpu, 3, (long)R_BBK * 0x1000 + R_LR3 * R_IR1) + (long)R_LG3 * R_IR2) + (long)R_LB3 * R_IR3)); \
+    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_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); \
+    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); }
+
+#define NCDS(i) { \
+    R_FLAG = 0; \
+    int64_t vx = (int64_t)((int16_t)cpu->cop2_dr.v[i].p[0]); \
+    int64_t vy = (int64_t)((int16_t)cpu->cop2_dr.v[i].p[1]); \
+    int64_t vz = (int64_t)cpu->cop2_dr.v[i].z; \
+    R_MAC1 = gte_clamp_mac(cpu, 1, (I64(R_L11) * vx) + (I64(R_L12) * vy) + (I64(R_L13) * vz)); \
+    R_MAC2 = gte_clamp_mac(cpu, 2, (I64(R_L21) * vx) + (I64(R_L22) * vy) + (I64(R_L23) * vz)); \
+    R_MAC3 = gte_clamp_mac(cpu, 3, (I64(R_L31) * vx) + (I64(R_L32) * vy) + (I64(R_L33) * vz)); \
+    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(cpu, 3, R_MAC3, cpu->gte_lm); \
+    R_MAC1 = gte_clamp_mac(cpu, 1, (I64(R_RBK) << 12) + (I64(R_LR1) * I64(R_IR1)) + (I64(R_LR2) * I64(R_IR2)) + (I64(R_LR3) * I64(R_IR3))); \
+    R_MAC2 = gte_clamp_mac(cpu, 2, (I64(R_GBK) << 12) + (I64(R_LG1) * I64(R_IR1)) + (I64(R_LG2) * I64(R_IR2)) + (I64(R_LG3) * I64(R_IR3))); \
+    R_MAC3 = gte_clamp_mac(cpu, 3, (I64(R_BBK) << 12) + (I64(R_LB1) * I64(R_IR1)) + (I64(R_LB2) * I64(R_IR2)) + (I64(R_LB3) * I64(R_IR3))); \
+    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(cpu, 3, R_MAC3, cpu->gte_lm); \
+    int64_t ir1 = gte_clamp_ir(cpu, 1, gte_clamp_mac(cpu, 1, ((I64(R_RFC) << 12) - ((I64(R_RC << 4)) * I64(R_IR1)))), 0); \
+    int64_t ir2 = gte_clamp_ir(cpu, 2, gte_clamp_mac(cpu, 2, ((I64(R_GFC) << 12) - ((I64(R_GC << 4)) * I64(R_IR2)))), 0); \
+    int64_t ir3 = gte_clamp_ir(cpu, 3, gte_clamp_mac(cpu, 3, ((I64(R_BFC) << 12) - ((I64(R_BC << 4)) * I64(R_IR3)))), 0); \
+    R_MAC1 = gte_clamp_mac(cpu, 1, ((I64(R_RC << 4)) * I64(R_IR1)) + (I64(R_IR0) * ir1)); \
+    R_MAC2 = gte_clamp_mac(cpu, 2, ((I64(R_GC << 4)) * I64(R_IR2)) + (I64(R_IR0) * ir2)); \
+    R_MAC3 = gte_clamp_mac(cpu, 3, ((I64(R_BC << 4)) * I64(R_IR3)) + (I64(R_IR0) * ir3)); \
+    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(cpu, 3, R_MAC3, cpu->gte_lm); \
+    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_rtps(psx_cpu_t* cpu) {
     GTE_RTP_DQ(0);
 }
@@ -1984,47 +2044,7 @@
 
 // To-do: Fix flags
 void psx_gte_i_ncds(psx_cpu_t* cpu) {
-    R_FLAG = 0;
-
-    int64_t vx = (int64_t)((int16_t)cpu->cop2_dr.v[0].p[0]);
-    int64_t vy = (int64_t)((int16_t)cpu->cop2_dr.v[0].p[1]);
-    int64_t vz = (int64_t)cpu->cop2_dr.v[0].z;
-
-    R_MAC1 = gte_clamp_mac(cpu, 1, (I64(R_L11) * vx) + (I64(R_L12) * vy) + (I64(R_L13) * vz));
-    R_MAC2 = gte_clamp_mac(cpu, 2, (I64(R_L21) * vx) + (I64(R_L22) * vy) + (I64(R_L23) * vz));
-    R_MAC3 = gte_clamp_mac(cpu, 3, (I64(R_L31) * vx) + (I64(R_L32) * vy) + (I64(R_L33) * vz));
-
-    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(cpu, 3, R_MAC3, cpu->gte_lm);
-
-    R_MAC1 = gte_clamp_mac(cpu, 1, (I64(R_RBK) << 12) + (I64(R_LR1) * I64(R_IR1)) + (I64(R_LR2) * I64(R_IR2)) + (I64(R_LR3) * I64(R_IR3)));
-    R_MAC2 = gte_clamp_mac(cpu, 2, (I64(R_GBK) << 12) + (I64(R_LG1) * I64(R_IR1)) + (I64(R_LG2) * I64(R_IR2)) + (I64(R_LG3) * I64(R_IR3)));
-    R_MAC3 = gte_clamp_mac(cpu, 3, (I64(R_BBK) << 12) + (I64(R_LB1) * I64(R_IR1)) + (I64(R_LB2) * I64(R_IR2)) + (I64(R_LB3) * I64(R_IR3)));
-
-    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(cpu, 3, R_MAC3, cpu->gte_lm);
-
-    int64_t ir1 = gte_clamp_ir(cpu, 1, gte_clamp_mac(cpu, 1, ((I64(R_RFC) << 12) - ((I64(R_RC << 4)) * I64(R_IR1)))), 0);
-    int64_t ir2 = gte_clamp_ir(cpu, 2, gte_clamp_mac(cpu, 2, ((I64(R_GFC) << 12) - ((I64(R_GC << 4)) * I64(R_IR2)))), 0);
-    int64_t ir3 = gte_clamp_ir(cpu, 3, gte_clamp_mac(cpu, 3, ((I64(R_BFC) << 12) - ((I64(R_BC << 4)) * I64(R_IR3)))), 0);
-
-    R_MAC1 = gte_clamp_mac(cpu, 1, ((I64(R_RC << 4)) * I64(R_IR1)) + (I64(R_IR0) * ir1));
-    R_MAC2 = gte_clamp_mac(cpu, 2, ((I64(R_GC << 4)) * I64(R_IR2)) + (I64(R_IR0) * ir2));
-    R_MAC3 = gte_clamp_mac(cpu, 3, ((I64(R_BC << 4)) * I64(R_IR3)) + (I64(R_IR0) * ir3));
-
-    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(cpu, 3, R_MAC3, cpu->gte_lm);
-
-    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);
+    NCDS(0);
 }
 
 void psx_gte_i_cdp(psx_cpu_t* cpu) {
@@ -2032,7 +2052,9 @@
 }
 
 void psx_gte_i_ncdt(psx_cpu_t* cpu) {
-    printf("ncdt: Unimplemented GTE instruction\n");
+    NCDS(0);
+    NCDS(1);
+    NCDS(2);
 }
 
 void psx_gte_i_nccs(psx_cpu_t* cpu) {
@@ -2040,15 +2062,17 @@
 }
 
 void psx_gte_i_cc(psx_cpu_t* cpu) {
-    printf("cc: Unimplemented GTE instruction\n");
+    NCS(0); // Hack
 }
 
 void psx_gte_i_ncs(psx_cpu_t* cpu) {
-    printf("ncs: Unimplemented GTE instruction\n");
+    NCS(0);
 }
 
 void psx_gte_i_nct(psx_cpu_t* cpu) {
-    printf("nct: Unimplemented GTE instruction\n");
+    NCS(0);
+    NCS(1);
+    NCS(2);
 }
 
 void psx_gte_i_sqr(psx_cpu_t* cpu) {
@@ -2174,4 +2198,4 @@
 #undef DEBUG_ALL
 
 #undef SE8
-#undef SE16
+#undef SE16
\ No newline at end of file
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -231,15 +231,15 @@
 void cdrom_cmd_getstat(psx_cdrom_t* cdrom) {
     switch (cdrom->state) {
         case CD_STATE_RECV_CMD: {
-            if (cdrom->ongoing_read_command) {
-                cdrom->status |= STAT_BUSYSTS_MASK;
-                // printf("command=%02x\n", cdrom->ongoing_read_command);
-                cdrom->state = CD_STATE_SEND_RESP2;
-                cdrom->delayed_command = cdrom->ongoing_read_command;
-                cdrom->irq_delay = DELAY_1MS;
+            // if (cdrom->ongoing_read_command) {
+            //     cdrom->status |= STAT_BUSYSTS_MASK;
+            //     // printf("command=%02x\n", cdrom->ongoing_read_command);
+            //     cdrom->state = CD_STATE_SEND_RESP2;
+            //     cdrom->delayed_command = cdrom->ongoing_read_command;
+            //     cdrom->irq_delay = DELAY_1MS;
 
-                return;
-            }
+            //     return;
+            // }
 
             if (cdrom->pfifo_index) {
                 log_fatal("CdlGetStat: Expected exactly 0 parameters");
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -349,10 +349,15 @@
     }
 }
 
+#define CLAMP(v, d, u) ((v) < (d)) ? (d) : (((v) >= (u)) ? (u) : (v))
+
 void gpu_render_rect(psx_gpu_t* gpu, rect_data_t data) {
     if ((data.v0.x >= 1024) || (data.v0.y >= 512))
         return;
 
+    if ((data.v0.x <= -1024) || (data.v0.y <= -512))
+        return;
+
     uint16_t width, height;
 
     switch ((data.attrib >> 3) & 3) {
@@ -376,6 +381,11 @@
     /* Calculate bounding box */
     int xmax = data.v0.x + width;
     int ymax = data.v0.y + height;
+
+    xmax = CLAMP(xmax, -1024, 1024);
+    ymax = CLAMP(ymax, -1024, 1024);
+    data.v0.x = CLAMP(data.v0.x, -1024, 1024);
+    data.v0.y = CLAMP(data.v0.y, -1024, 1024);
 
     int32_t xc = 0, yc = 0;
 
--