shithub: psxe

Download patch

ref: 23948daf66d70fd666f2b0da138f3dfec25a92e4
parent: 6c85f2833023e575b3a4678c687f650be2d8bbeb
author: allkern <lisandroaalarcon@gmail.com>
date: Thu May 9 17:46:43 EDT 2024

Improved T2 IRQ emulation

Implemented CDROM volume registers

--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -1678,23 +1678,30 @@
 }
 
 void cdrom_write_lcdlspuv(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("Volume registers unimplemented");
+    cdrom->vapp[0] = value;
 }
 
 void cdrom_write_rcdrspuv(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("Volume registers unimplemented");
+    cdrom->vapp[3] = value;
 }
 
 void cdrom_write_rcdlspuv(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("Volume registers unimplemented");
+    cdrom->vapp[2] = value;
 }
 
 void cdrom_write_lcdrspuv(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("Volume registers unimplemented");
+    cdrom->vapp[1] = value;
 }
 
 void cdrom_write_volume(psx_cdrom_t* cdrom, uint8_t value) {
-    log_fatal("Volume registers unimplemented");
+    cdrom->xa_mute = value & 1;
+
+    if (value & 0x20) {
+        cdrom->vol[0] = cdrom->vapp[0];
+        cdrom->vol[1] = cdrom->vapp[1];
+        cdrom->vol[2] = cdrom->vapp[2];
+        cdrom->vol[3] = cdrom->vapp[3];
+    }
 }
 
 psx_cdrom_read_function_t g_psx_cdrom_read_table[] = {
@@ -2120,6 +2127,20 @@
     }
 }
 
+void cdrom_apply_volume_settings(psx_cdrom_t* cdrom) {
+    int16_t* ptr = cdrom->cdda_buf;
+
+    float ll_vol = (((float)cdrom->vol[0]) / 255.0f);
+    float lr_vol = (((float)cdrom->vol[1]) / 255.0f);
+    float rl_vol = (((float)cdrom->vol[2]) / 255.0f);
+    float rr_vol = (((float)cdrom->vol[3]) / 255.0f);
+
+    for (int i = 0; i < CD_SECTOR_SIZE >> 1; i += 2) {
+        ptr[i  ] = ptr[i  ] * ll_vol + ptr[i+1] * rl_vol;
+        ptr[i+1] = ptr[i+1] * rr_vol + ptr[i  ] * lr_vol;
+    }
+}
+
 void psx_cdrom_get_cdda_samples(psx_cdrom_t* cdrom, void* buf, int size, psx_spu_t* spu) {
     memset(buf, 0, size);
 
@@ -2162,18 +2183,31 @@
                 cdrom->xa_sample_idx = 0;
             }
 
+            if (cdrom->xa_mute) {
+                *ptr++ = 0;
+                *ptr++ = 0;
+
+                return;
+            }
+
+            float ll_vol = (((float)cdrom->vol[0]) / 255.0f);
+            float rr_vol = (((float)cdrom->vol[3]) / 255.0f);
+
             if (stereo) {
                 cdrom->xa_last_left_sample = cdrom->xa_left_resample_buf[cdrom->xa_sample_idx];
                 cdrom->xa_last_right_sample = cdrom->xa_right_resample_buf[cdrom->xa_sample_idx++];
 
-                *ptr++ = cdrom->xa_last_left_sample;
-                *ptr++ = cdrom->xa_last_right_sample;
+                float lr_vol = (((float)cdrom->vol[1]) / 255.0f);
+                float rl_vol = (((float)cdrom->vol[2]) / 255.0f);
 
+                *ptr++ = (cdrom->xa_last_left_sample * ll_vol) + (cdrom->xa_last_right_sample * rl_vol);
+                *ptr++ = (cdrom->xa_last_left_sample * lr_vol) + (cdrom->xa_last_right_sample * rr_vol);
+
             } else {
                 cdrom->xa_last_mono_sample = cdrom->xa_mono_resample_buf[cdrom->xa_sample_idx++];
 
-                *ptr++ = cdrom->xa_last_mono_sample;
-                *ptr++ = cdrom->xa_last_mono_sample;
+                *ptr++ = cdrom->xa_last_mono_sample * ll_vol;
+                *ptr++ = cdrom->xa_last_mono_sample * rr_vol;
             }
 
             --cdrom->xa_remaining_samples;
@@ -2198,6 +2232,8 @@
 
     // Increment sector
     msf_add_f(&cdrom->cdda_msf, 1);
+
+    cdrom_apply_volume_settings(cdrom);
 
     memcpy(buf, cdrom->cdda_buf, size);
 
--- a/psx/dev/cdrom.h
+++ b/psx/dev/cdrom.h
@@ -211,6 +211,7 @@
     uint8_t* xa_sector_buf;
     msf_t xa_msf;
     int xa_playing;
+    int xa_mute;
     uint8_t xa_file;
     uint8_t xa_channel;
     uint8_t xa_coding;
@@ -231,6 +232,8 @@
     int16_t xa_last_left_sample;
     int16_t xa_last_right_sample;
     int16_t xa_last_mono_sample;
+    uint8_t vol[4];
+    uint8_t vapp[4];
 
     const char* path;
     psx_disc_t* disc;
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -1752,6 +1752,23 @@
             gpu->gpustat &= ~(1 << 31);
         }
 
+        // HACK!! More games are fine with this
+        // but others, like Dead or Alive, will refuse
+        // to boot because this frequency is not fast
+        // enough. Sending T2 IRQs every line fixes DoA
+        // but breaks a bunch of games, so I'll keep this
+        // like this until I actually fix the timers
+        // Games that cared about T2:
+        // - Dead or Alive
+        // - NBA Jam
+        // - Doom
+        // - Devil Dice
+        // - Zanac x Zanac
+        // - Soukyugurentai
+        // - Mortal Kombat
+        // - PaRappa the Rapper
+        // - In The Hunt
+        // - etc.
         if (!(gpu->line & 7))
             psx_ic_irq(gpu->ic, IC_TIMER2);
     } else {
--