shithub: psxe

Download patch

ref: 8163706a9f348cc0a0aacaa67434b194aacd9ae1
parent: 32088d682e8b0f1005d012c3313054b852df87c9
author: allkern <lisandroaalarcon@gmail.com>
date: Fri Sep 15 17:16:53 EDT 2023

Implement CdlPlay (CDDA)

Fix resolution to multiples of 320x240

--- a/frontend/main.c
+++ b/frontend/main.c
@@ -1,5 +1,6 @@
 #include "psx/psx.h"
 #include "psx/input/sda.h"
+#include "psx/disc/cue.h"
 
 #include "screen.h"
 #include "config.h"
@@ -6,6 +7,12 @@
 
 #undef main
 
+void audio_update(void* ud, uint8_t* buf, int size) {
+    psx_cdrom_t* cdrom = ud;
+
+    psx_cdrom_get_cdda_samples(cdrom, buf, size);
+}
+
 int main(int argc, const char* argv[]) {
     psxe_config_t* cfg = psxe_cfg_create();
 
@@ -28,6 +35,24 @@
     psxe_screen_set_scale(screen, 3);
     psxe_screen_reload(screen);
 
+    SDL_Init(SDL_INIT_AUDIO);
+
+    SDL_AudioDeviceID dev;
+    SDL_AudioSpec obtained, desired;
+
+    desired.freq     = 44100;
+    desired.format   = AUDIO_S16SYS;
+    desired.channels = 2;
+    desired.samples  = CD_SECTOR_SIZE >> 2;
+    desired.callback = &audio_update;
+    desired.userdata = cdrom;
+
+    dev = SDL_OpenAudioDevice(NULL, 0, &desired, &obtained, 0);
+
+    log_fatal("obtained.samples=%u", obtained.samples);
+
+    if (dev) SDL_PauseAudioDevice(dev, 0);
+    
     psx_gpu_t* gpu = psx_get_gpu(psx);
     psx_gpu_set_event_callback(gpu, GPU_EVENT_DMODE, psxe_gpu_dmode_event_cb);
     psx_gpu_set_event_callback(gpu, GPU_EVENT_VBLANK, psxe_gpu_vblank_event_cb);
@@ -74,7 +99,7 @@
 
     if (cfg->cd_path)
         psx_cdrom_destroy(cdrom);
-    
+
     psx_input_destroy(input);
     psx_destroy(psx);
     psxi_sda_destroy(controller);
--- a/frontend/screen.c
+++ b/frontend/screen.c
@@ -54,6 +54,14 @@
     if (screen->renderer) SDL_DestroyRenderer(screen->renderer);
     if (screen->window) SDL_DestroyWindow(screen->window);
 
+    if (screen->debug_mode) {
+        screen->width = PSX_GPU_FB_WIDTH;
+        screen->height = PSX_GPU_FB_HEIGHT;
+    } else {
+        screen->width = 320;
+        screen->height = 240;
+    }
+
     screen->window = SDL_CreateWindow(
         "psxe " STR(REP_VERSION) "-" STR(REP_COMMIT_HASH),
         SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
@@ -97,6 +105,8 @@
 void psxe_screen_toggle_debug_mode(psxe_screen_t* screen) {
     screen->debug_mode = !screen->debug_mode;
 
+    psxe_screen_set_scale(screen, screen->saved_scale);
+
     psxe_gpu_dmode_event_cb(screen->psx->gpu);
 }
 
@@ -161,6 +171,9 @@
 void psxe_gpu_dmode_event_cb(psx_gpu_t* gpu) {
     psxe_screen_t* screen = gpu->udata[0];
 
+    int texture_width;
+    int texture_height;
+
     screen->format = psx_get_display_format(screen->psx) ?
         SDL_PIXELFORMAT_BGR555 : SDL_PIXELFORMAT_RGB888;
 
@@ -167,16 +180,20 @@
     if (screen->debug_mode) {
         screen->width = PSX_GPU_FB_WIDTH;
         screen->height = PSX_GPU_FB_HEIGHT;
+        texture_width = PSX_GPU_FB_WIDTH;
+        texture_height = PSX_GPU_FB_HEIGHT;
     } else {
-        screen->width = psx_get_display_width(screen->psx);
-        screen->height = psx_get_display_height(screen->psx);
+        screen->width = 320;
+        screen->height = 240;
+        texture_width = psx_get_display_width(screen->psx);
+        texture_height = psx_get_display_height(screen->psx);
     }
 
-    if (screen->width > 512) {
-        screen->scale = 1;
-    } else {
-        screen->scale = screen->saved_scale;
-    }
+    // if (screen->width > 512) {
+    //     screen->scale = 1;
+    // } else {
+    //     screen->scale = screen->saved_scale;
+    // }
 
     SDL_DestroyTexture(screen->texture);
 
@@ -184,7 +201,7 @@
         screen->renderer,
         SDL_PIXELFORMAT_BGR555,
         SDL_TEXTUREACCESS_STREAMING,
-        screen->width, screen->height
+        texture_width, texture_height
     );
 
     SDL_SetWindowSize(
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -153,6 +153,61 @@
         } break;
     }
 }
+void cdrom_cmd_play(psx_cdrom_t* cdrom) {
+    cdrom->delayed_command = CDL_NONE;
+
+    switch (cdrom->state) {
+        case CD_STATE_RECV_CMD: {
+            // if (cdrom->pfifo_index) {
+            //     log_fatal("CdlGetStat: 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->state = CD_STATE_SEND_RESP1;
+            cdrom->delayed_command = CDL_PLAY;
+
+            cdrom->cdda_msf.m = cdrom->seek_mm;
+            cdrom->cdda_msf.s = cdrom->seek_ss;
+            cdrom->cdda_msf.f = cdrom->seek_ff;
+
+            // Convert seek to I
+            msf_t msf = cdrom->cdda_msf;
+            
+            msf_from_bcd(&msf);
+
+            msf.s -= 24;
+
+            // Seek to that address and read sector
+            psx_disc_seek(cdrom->disc, msf);
+            psx_disc_read_sector(cdrom->disc, cdrom->cdda_buf);
+
+            // Increment sector
+            msf_add_f(&msf, 1);
+            msf_to_bcd(&msf);
+
+            cdrom->cdda_msf = msf;
+            
+            cdrom->cdda_sector_offset = 0;
+            cdrom->cdda_playing = 1;
+        } break;
+
+        case CD_STATE_SEND_RESP1: {
+            SET_BITS(ifr, IFR_INT, IFR_INT3);
+            RESP_PUSH(GETSTAT_MOTOR | GETSTAT_PLAY);
+
+            cdrom->delayed_command = CDL_NONE;
+            cdrom->state = CD_STATE_RECV_CMD;
+        } break;
+    }
+}
 void cdrom_cmd_readn(psx_cdrom_t* cdrom) {
     cdrom->delayed_command = CDL_NONE;
     cdrom->read_ongoing = 1;
@@ -528,7 +583,7 @@
 
             psx_disc_get_track_addr(cdrom->disc, &td, cdrom->gettd_track);
 
-            log_fatal("GetTD track=%u, addr=%02u:%02u", cdrom->gettd_track, td.m, td.s);
+            log_fatal("@@@@@@@@@@@@@@@@ GetTD track=%u, addr=%02u:%02u", cdrom->gettd_track, td.m, td.s);
 
             // To-do: Handle OOB tracks
 
@@ -860,9 +915,9 @@
     "CdlUnimplemented",
     "CdlGetstat",
     "CdlSetloc",
+    "CdlPlay",
     "CdlUnimplemented",
     "CdlUnimplemented",
-    "CdlUnimplemented",
     "CdlReadn",
     "CdlUnimplemented",
     "CdlStop",
@@ -895,9 +950,9 @@
     cdrom_cmd_unimplemented,
     cdrom_cmd_getstat,
     cdrom_cmd_setloc,
+    cdrom_cmd_play,
     cdrom_cmd_unimplemented,
     cdrom_cmd_unimplemented,
-    cdrom_cmd_unimplemented,
     cdrom_cmd_readn,
     cdrom_cmd_unimplemented,
     cdrom_cmd_stop,
@@ -1109,6 +1164,8 @@
 
     cdrom->ic = ic;
     cdrom->status = STAT_PRMEMPT_MASK | STAT_PRMWRDY_MASK;
+    cdrom->dfifo = malloc(CD_SECTOR_SIZE);
+    cdrom->cdda_buf = malloc(CD_SECTOR_SIZE);
 }
 
 uint32_t psx_cdrom_read32(psx_cdrom_t* cdrom, uint32_t offset) {
@@ -1236,6 +1293,95 @@
 
         exit(1);
     }
+}
+
+void psx_cdrom_get_cdda_samples(psx_cdrom_t* cdrom, void* buf, int size) {
+    if (!cdrom->cdda_playing) {
+        memset(buf, 0, size);
+    
+        return;
+    }
+
+    memcpy(buf, cdrom->cdda_buf, size);
+
+    // Convert seek to I
+    msf_t msf = cdrom->cdda_msf;
+    
+    msf_from_bcd(&msf);
+
+    // Seek to that address and read sector
+    psx_disc_seek(cdrom->disc, msf);
+    psx_disc_read_sector(cdrom->disc, cdrom->cdda_buf);
+
+    // Increment sector
+    msf_add_f(&msf, 1);
+    msf_to_bcd(&msf);
+
+    // Assign to CDDA MSF
+    cdrom->cdda_msf = msf;
+
+    /*
+    start = offset
+    end = offset + request
+
+    start = 0
+    end = 10
+    
+    */
+
+    // int req_start = cdrom->cdda_sector_offset;
+    // int req_end = req_start + size;
+
+    // if (req_end > CD_SECTOR_SIZE) {
+    //     int unbuffered = req_end - CD_SECTOR_SIZE;
+    //     //int buffered = 
+    // }
+
+    // // We need a new sector
+    // if (cdrom->cdda_sector_offset >= CD_SECTOR_SIZE) {
+    //     cdrom->cdda_sector_offset -= CD_SECTOR_SIZE;
+
+    //     // Convert seek to I
+    //     msf_t msf = cdrom->cdda_msf;
+        
+    //     msf_from_bcd(&msf);
+
+    //     // Seek to that address and read sector
+    //     psx_disc_seek(cdrom->disc, msf);
+    //     psx_disc_read_sector(cdrom->disc, cdrom->cdda_buf);
+
+    //     // Increment sector
+    //     msf_add_f(&msf, 1);
+    //     msf_to_bcd(&msf);
+
+    //     // Assign to CDDA MSF
+    //     cdrom->cdda_msf = msf;
+    // }
+
+    memcpy(buf, cdrom->cdda_buf, size);
+
+    // cdrom->cdda_sector_offset += size;
+
+    // // We need a new sector
+    // if (cdrom->cdda_sector_offset >= CD_SECTOR_SIZE) {
+    //     cdrom->cdda_sector_offset -= CD_SECTOR_SIZE;
+
+    //     // Convert seek to I
+    //     msf_t msf = cdrom->cdda_msf;
+        
+    //     msf_from_bcd(&msf);
+
+    //     // Seek to that address and read sector
+    //     psx_disc_seek(cdrom->disc, msf);
+    //     psx_disc_read_sector(cdrom->disc, cdrom->cdda_buf);
+
+    //     // Increment sector
+    //     msf_add_f(&msf, 1);
+    //     msf_to_bcd(&msf);
+
+    //     // Assign to CDDA MSF
+    //     cdrom->cdda_msf = msf;
+    // }
 }
 
 void psx_cdrom_destroy(psx_cdrom_t* cdrom) {
--- a/psx/dev/cdrom.h
+++ b/psx/dev/cdrom.h
@@ -155,8 +155,8 @@
     int pfifo_index;
     int rfifo_index;
 
-    uint8_t read_buf[CD_SECTOR_SIZE];
-    uint8_t dfifo[CD_SECTOR_SIZE];
+    uint8_t* read_buf;
+    uint8_t* dfifo;
     int dfifo_index;
     int dfifo_full;
 
@@ -185,6 +185,12 @@
     int read_ongoing;
     int gettd_track;
 
+    // CDDA
+    uint8_t* cdda_buf;
+    int cdda_sector_offset;
+    msf_t cdda_msf;
+    int cdda_playing;
+
     const char* path;
     psx_disc_t* disc;
 } psx_cdrom_t;
@@ -200,6 +206,7 @@
 void psx_cdrom_update(psx_cdrom_t*);
 void psx_cdrom_destroy(psx_cdrom_t*);
 void psx_cdrom_open(psx_cdrom_t*, const char*);
+void psx_cdrom_get_cdda_samples(psx_cdrom_t*, void*, int);
 
 /*
   Command          Parameters      Response(s)
@@ -251,6 +258,7 @@
 void cdrom_cmd_unimplemented(psx_cdrom_t*);
 void cdrom_cmd_getstat(psx_cdrom_t*);
 void cdrom_cmd_setloc(psx_cdrom_t*);
+void cdrom_cmd_play(psx_cdrom_t*);
 void cdrom_cmd_readn(psx_cdrom_t*);
 void cdrom_cmd_stop(psx_cdrom_t*);
 void cdrom_cmd_pause(psx_cdrom_t*);
--