shithub: psxe

Download patch

ref: 6d3047e01b59cc63a1f51db845d9bb091a95fd1e
parent: 716b378886c95a13f065faf063528d62046fb609
author: allkern <lisandroaalarcon@gmail.com>
date: Thu Dec 21 07:28:20 EST 2023

Implement mono XA-ADPCM

--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -1203,8 +1203,16 @@
                     cdrom->xa_channel
                 );
 
-                cdrom->state = CD_STATE_RECV_CMD;
-                cdrom->delayed_command = CDL_NONE;
+                int double_speed = cdrom->mode & MODE_SPEED;
+
+                cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY;
+                cdrom->state = CD_STATE_SEND_RESP2;
+                cdrom->delayed_command = CDL_READS;
+
+                if (cdrom->spin_delay) {
+                    cdrom->irq_delay += cdrom->spin_delay;
+                    cdrom->spin_delay = 0;
+                }
             }
 
             int err = psx_disc_seek(cdrom->disc, msf);
@@ -1220,7 +1228,7 @@
 
                 return;
             }
-            
+
             int double_speed = cdrom->mode & MODE_SPEED;
 
             cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY;
@@ -1262,6 +1270,20 @@
             cdrom->delayed_command = CDL_READS;
             cdrom->dfifo_index = 0;
 
+            if (cdrom->mode & MODE_XA_ADPCM) {
+                int double_speed = cdrom->mode & MODE_SPEED;
+
+                if (cdrom->dfifo[0x12] & 4) {
+                    cdrom->irq_delay = 10;
+                    cdrom->irq_delay = double_speed ? READ_DOUBLE_DELAY : READ_SINGLE_DELAY;
+                    cdrom->state = CD_STATE_SEND_RESP2;
+                    cdrom->delayed_command = CDL_READS;
+                    // cdrom->irq_disable = 1;
+
+                    return;
+                }
+            }
+
             SET_BITS(ifr, IFR_INT, IFR_INT1);
             RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ);
         } break;
@@ -1538,9 +1560,10 @@
     cdrom->xa_left_buf = malloc(XA_STEREO_SAMPLES * sizeof(int16_t));
     cdrom->xa_right_buf = malloc(XA_STEREO_SAMPLES * sizeof(int16_t));
     cdrom->xa_mono_buf = malloc(XA_MONO_SAMPLES * sizeof(int16_t));
-    cdrom->xa_upsample_buf = malloc((14112 + 6) * sizeof(int16_t));
+    cdrom->xa_upsample_buf = malloc(((14112 * 2) + 6) * sizeof(int16_t));
     cdrom->xa_left_resample_buf = malloc(2352 * sizeof(int16_t));
     cdrom->xa_right_resample_buf = malloc(2352 * sizeof(int16_t));
+    cdrom->xa_mono_resample_buf = malloc(XA_MONO_RESAMPLE_SIZE * sizeof(int16_t));
     cdrom->xa_step = 6;
 
     // We will use this whenever we implement proper
@@ -1550,9 +1573,10 @@
     memset(cdrom->xa_left_buf, 0, XA_STEREO_SAMPLES * sizeof(int16_t));
     memset(cdrom->xa_right_buf, 0, XA_STEREO_SAMPLES * sizeof(int16_t));
     memset(cdrom->xa_mono_buf, 0, XA_MONO_SAMPLES * sizeof(int16_t));
-    memset(cdrom->xa_upsample_buf, 0, (14112 + 6) * sizeof(int16_t));
+    memset(cdrom->xa_upsample_buf, 0, ((14112 * 2) + 6) * sizeof(int16_t));
     memset(cdrom->xa_left_resample_buf, 0, 2352 * sizeof(int16_t));
     memset(cdrom->xa_right_resample_buf, 0, 2352 * sizeof(int16_t));
+    memset(cdrom->xa_mono_resample_buf, 0, XA_MONO_RESAMPLE_SIZE * sizeof(int16_t));
 }
 
 uint32_t psx_cdrom_read32(psx_cdrom_t* cdrom, uint32_t offset) {
@@ -1613,7 +1637,11 @@
         cdrom->irq_delay -= cyc;
 
         if (cdrom->irq_delay <= 0) {
-            psx_ic_irq(cdrom->ic, IC_CDROM);
+            if (!cdrom->irq_disable) {
+                psx_ic_irq(cdrom->ic, IC_CDROM);
+            } else {
+                cdrom->irq_disable = 0;
+            }
 
             cdrom->irq_delay = 0;
 
@@ -1755,11 +1783,30 @@
     0,   0,  -52, -55,  -60
 };
 
-void cdrom_resample_xa_buf(psx_cdrom_t* cdrom, int16_t* dst, int16_t* src) {
-    // To-do: Account for 18KHz samples and mono
+void cdrom_resample_xa_buf(psx_cdrom_t* cdrom, int16_t* dst, int16_t* src, int stereo) {
+    // To-do: Account for 18KHz samples
     // int f18khz = ((cdrom->xa_sector_buf[0x13] >> 2) & 1) == 1;
 
-    for (int i = 0; i < XA_STEREO_SAMPLES; i++) {
+    if (stereo) {
+        for (int i = 0; i < XA_STEREO_SAMPLES; i++) {
+            int j = i * 7;
+
+            cdrom->xa_upsample_buf[j] = src[i];
+
+            // Nearest neighbor
+            for (int k = 0; k < 7; k++)
+                cdrom->xa_upsample_buf[j+k] = src[i];
+        }
+
+        for (int i = 0; i < XA_STEREO_RESAMPLE_SIZE; i++)
+            dst[i] = cdrom->xa_upsample_buf[i*6];
+
+        cdrom->xa_remaining_samples = XA_STEREO_RESAMPLE_SIZE;
+
+        return;
+    }
+
+    for (int i = 0; i < XA_MONO_SAMPLES; i++) {
         int j = i * 7;
 
         cdrom->xa_upsample_buf[j] = src[i];
@@ -1769,10 +1816,10 @@
             cdrom->xa_upsample_buf[j+k] = src[i];
     }
 
-    for (int i = 0; i < 2352; i++)
+    for (int i = 0; i < XA_MONO_RESAMPLE_SIZE; i++)
         dst[i] = cdrom->xa_upsample_buf[i*6];
 
-    cdrom->xa_remaining_samples = 2352;
+    cdrom->xa_remaining_samples = XA_MONO_RESAMPLE_SIZE;
 }
 
 void cdrom_decode_xa_block(psx_cdrom_t* cdrom, int idx, int blk, int nib, int16_t* buf, int16_t* h) {
@@ -1878,17 +1925,41 @@
         int16_t* ptr = (int16_t*)buf;
 
         for (int i = 0; i < (size >> 2); i++) {
+            int stereo = (cdrom->xa_sector_buf[0x13] & 1) == 1;
+
             if (!cdrom->xa_remaining_samples) {
                 cdrom_fetch_xa_sector(cdrom);
+
+                if (cdrom->xa_sector_buf[0x12] & 0x80) {
+                    SET_BITS(status, STAT_ADPBUSY_MASK, 0);
+
+                    cdrom->xa_playing = 0;
+                    cdrom->xa_remaining_samples = 0;
+
+                    return;
+                }
+
+                stereo = (cdrom->xa_sector_buf[0x13] & 1) == 1;
+
                 cdrom_decode_xa_sector(cdrom, buf);
-                cdrom_resample_xa_buf(cdrom, cdrom->xa_left_resample_buf, cdrom->xa_left_buf);
-                cdrom_resample_xa_buf(cdrom, cdrom->xa_right_resample_buf, cdrom->xa_right_buf);
 
+                if (stereo) {
+                    cdrom_resample_xa_buf(cdrom, cdrom->xa_left_resample_buf, cdrom->xa_left_buf, stereo);
+                    cdrom_resample_xa_buf(cdrom, cdrom->xa_right_resample_buf, cdrom->xa_right_buf, stereo);
+                } else {
+                    cdrom_resample_xa_buf(cdrom, cdrom->xa_mono_resample_buf, cdrom->xa_mono_buf, stereo);
+                }
+
                 cdrom->xa_sample_idx = 0;
             }
 
-            *ptr++ = cdrom->xa_left_resample_buf[(cdrom->xa_sample_idx) % 2352];
-            *ptr++ = cdrom->xa_right_resample_buf[(cdrom->xa_sample_idx++) % 2352];
+            if (stereo) {
+                *ptr++ = cdrom->xa_left_resample_buf[(cdrom->xa_sample_idx) % XA_STEREO_RESAMPLE_SIZE];
+                *ptr++ = cdrom->xa_right_resample_buf[(cdrom->xa_sample_idx++) % XA_STEREO_RESAMPLE_SIZE];
+            } else {
+                *ptr++ = cdrom->xa_mono_resample_buf[(cdrom->xa_sample_idx) % XA_MONO_RESAMPLE_SIZE];
+                *ptr++ = cdrom->xa_mono_resample_buf[(cdrom->xa_sample_idx++) % XA_MONO_RESAMPLE_SIZE];
+            }
 
             --cdrom->xa_remaining_samples;
         }
--- a/psx/dev/cdrom.h
+++ b/psx/dev/cdrom.h
@@ -186,6 +186,7 @@
     uint8_t mode;
 
     int irq_delay;
+    int irq_disable;
     uint8_t command;
     uint8_t delayed_command;
     uint8_t int_number;
@@ -218,8 +219,6 @@
     int16_t* xa_decoded_buf;
     int16_t* xa_left_ring_buf;
     int16_t* xa_right_ring_buf;
-    int16_t* xa_stereo_resample_buf;
-    int16_t* xa_mono_resample_buf;
     uint32_t xa_sample_idx;
     int xa_remaining_samples;
     uint32_t xa_step;
@@ -226,6 +225,7 @@
     uint32_t xa_ringbuf_pos;
     int16_t* xa_left_resample_buf;
     int16_t* xa_right_resample_buf;
+    int16_t* xa_mono_resample_buf;
     int16_t* xa_upsample_buf;
 
     const char* path;
--- a/psx/dev/gpu.c
+++ b/psx/dev/gpu.c
@@ -116,13 +116,17 @@
 uint16_t psx_gpu_read16(psx_gpu_t* gpu, uint32_t offset) {
     log_fatal("Unhandled 16-bit GPU read at offset %08x", offset);
 
-    exit(1);
+    return 0;
+
+    // exit(1);
 }
 
 uint8_t psx_gpu_read8(psx_gpu_t* gpu, uint32_t offset) {
     log_fatal("Unhandled 8-bit GPU read at offset %08x", offset);
 
-    exit(1);
+    return 0;
+
+    // exit(1);
 }
 
 int min(int x0, int x1) {
@@ -1728,7 +1732,7 @@
 }
 
 void* psx_gpu_get_display_buffer(psx_gpu_t* gpu) {
-    return gpu->vram + (gpu->draw_x1 + (gpu->draw_y1 * 1024));
+    return gpu->vram + (gpu->disp_x + (gpu->disp_y * 1024));
 }
 
 void psx_gpu_destroy(psx_gpu_t* gpu) {
--