shithub: psxe

Download patch

ref: 2bd54ea370da6e37c742923ad96dd6b3b5838e00
parent: 4427eabe5ce86583c7352b5ad2f250252a57a6e3
author: allkern <lisandroaalarcon@gmail.com>
date: Sat Sep 23 18:26:50 EDT 2023

Implement `CdlStop`

Implement screenshots
Start working on memory cards

--- a/.gitignore
+++ b/.gitignore
@@ -10,6 +10,7 @@
 test/
 bios/
 roms/
+snap/
 *.bin
 *.dll
 *.exe
@@ -16,4 +17,5 @@
 *.out
 *.toml
 *.zip
-*.cue
\ No newline at end of file
+*.cue
+*.iso
\ No newline at end of file
--- a/frontend/config.c
+++ b/frontend/config.c
@@ -98,6 +98,7 @@
     int help_region = 0;
     int log_level = 0;
     int quiet = 0;
+    int console_source = 0;
     const char* settings_path = NULL;
     const char* bios = NULL;
     const char* bios_search = NULL;
@@ -108,26 +109,27 @@
     const char* cd_path = NULL;
 
     static const char *const usages[] = {
-        "psxe [options]",
+        "psxe [options] path-to-cdrom",
         NULL,
     };
 
     struct argparse_option options[] = {
-        OPT_BOOLEAN ('h', "help"         , NULL          , "Display this information", argparse_help_cb, 0, 0),
-        OPT_BOOLEAN (0  , "help-model"   , &help_model   , "Display available console models", NULL, 0, 0),
-        OPT_BOOLEAN (0  , "help-region"  , &help_region  , "Display available region options", NULL, 0, 0),
-        OPT_BOOLEAN ('v', "version"      , &version      , "Display version and build information", NULL, 0, 0),
+        OPT_BOOLEAN ('h', "help"          , NULL           , "Display this information", argparse_help_cb, 0, 0),
+        OPT_BOOLEAN (0  , "help-model"    , &help_model    , "Display available console models", NULL, 0, 0),
+        OPT_BOOLEAN (0  , "help-region"   , &help_region   , "Display available region options", NULL, 0, 0),
+        OPT_BOOLEAN ('v', "version"       , &version       , "Display version and build information", NULL, 0, 0),
         OPT_GROUP("Basic options"),
-        OPT_BOOLEAN ('a', "use-args"     , &use_args     , "Ignore settings file, use CLI args instead", NULL, 0, 0),
-        OPT_STRING  ('S', "settings-file", &settings_path, "Specify settings file path", NULL, 0, 0),
-        OPT_STRING  ('b', "bios"         , &bios         , "Use this BIOS file (ignores -B, -M)", NULL, 0, 0),
-        OPT_BOOLEAN ('B', "bios-folder"  , &bios_search  , "Specify a BIOS search folder", NULL, 0, 0),
-        OPT_STRING  ('M', "model"        , &model        , "Specify console model (SPCH-XXXX)", NULL, 0, 0),
-        OPT_STRING  ('r', "region"       , &region       , "Specify console region"),
-        OPT_STRING  ('x', "exe"          , &exe          , "Boot this PS-X EXE file (ignores CDROM image)"),
-        OPT_INTEGER ('L', "log-level"    , &log_level    , "Set log level"),
-        OPT_BOOLEAN ('q', "quiet"        , &quiet        , "Silence all logs (ignores -L)"),
-        OPT_STRING  (0  , "cdrom"        , &cd_path      , "Specify a CDROM image"),
+        OPT_BOOLEAN ('a', "use-args"      , &use_args      , "Ignore settings file, use CLI args instead", NULL, 0, 0),
+        OPT_STRING  ('b', "bios"          , &bios          , "Use this BIOS file (ignores -B, -M)", NULL, 0, 0),
+        OPT_BOOLEAN ('B', "bios-folder"   , &bios_search   , "Specify a BIOS search folder", NULL, 0, 0),
+        OPT_STRING  ('c', "console-source", &console_source, "Select console source (auto, null, kernel, atcons)"),
+        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_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           , "Boot this PS-X EXE file"),
+        OPT_STRING  (0  , "cdrom"         , &cd_path       , "Specify a CDROM image"),
         OPT_END()
     };
 
--- a/frontend/config.h
+++ b/frontend/config.h
@@ -14,6 +14,8 @@
     int help_region;
     int log_level;
     int quiet;
+    int console_source;
+    const char* snap_path;
     const char* settings_path;
     const char* bios;
     const char* bios_search;
--- a/frontend/screen.c
+++ b/frontend/screen.c
@@ -133,6 +133,27 @@
 
                         return;
                     } break;
+
+                    case SDLK_F2: {
+                        SDL_Surface* surface = SDL_CreateRGBSurfaceWithFormat(
+                            0,
+                            screen->width * screen->scale,
+                            screen->height * screen->scale,
+                            16,
+                            SDL_PIXELFORMAT_BGR555
+                        );
+
+                        SDL_RenderReadPixels(
+                            screen->renderer,
+                            NULL,
+                            SDL_PIXELFORMAT_RGBA8888,
+                            surface->pixels, surface->pitch
+                        );
+
+                        SDL_SaveBMP(surface, "snap/screenshot.bmp");
+
+                        SDL_FreeSurface(surface);
+                    } break;
                 }
 
                 uint16_t mask = screen_get_button(event.key.keysym.sym);
--- a/psx/dev/cdrom.c
+++ b/psx/dev/cdrom.c
@@ -343,7 +343,45 @@
         } break;
     }
 }
-void cdrom_cmd_stop(psx_cdrom_t* cdrom) { log_fatal("stop: Unimplemented"); exit(1); }
+void cdrom_cmd_stop(psx_cdrom_t* cdrom) {
+    cdrom->delayed_command = CDL_NONE;
+
+    switch (cdrom->state) {
+        case CD_STATE_RECV_CMD: {
+            cdrom->read_ongoing = 0;
+            cdrom->cdda_playing = 0;
+
+            cdrom->irq_delay = DELAY_1MS;
+            cdrom->state = CD_STATE_SEND_RESP1;
+            cdrom->delayed_command = CDL_STOP;
+            cdrom->seek_ff = 0;
+            cdrom->seek_ss = 0;
+            cdrom->seek_mm = 0;
+            cdrom->cdda_msf.m = 0;
+            cdrom->cdda_msf.s = 0;
+            cdrom->cdda_msf.f = 0;
+        } break;
+
+        case CD_STATE_SEND_RESP1: {
+            SET_BITS(ifr, IFR_INT, 3);
+            RESP_PUSH(GETSTAT_MOTOR | GETSTAT_READ);
+
+            int double_speed = cdrom->mode & MODE_SPEED;
+
+            cdrom->irq_delay = DELAY_1MS * (double_speed ? 70 : 65);
+            cdrom->state = CD_STATE_SEND_RESP2;
+            cdrom->delayed_command = CDL_STOP;
+        } break;
+
+        case CD_STATE_SEND_RESP2: {
+            SET_BITS(ifr, IFR_INT, 2);
+            RESP_PUSH(GETSTAT_MOTOR);
+
+            cdrom->state = CD_STATE_RECV_CMD;
+            cdrom->delayed_command = CDL_NONE;
+        } break;
+    }
+}
 void cdrom_cmd_pause(psx_cdrom_t* cdrom) {
     cdrom->delayed_command = CDL_NONE;
 
@@ -758,18 +796,46 @@
         } break;
 
         case CD_STATE_SEND_RESP2: {
-            SET_BITS(ifr, IFR_INT, 2);
+            /*
+                Drive Status           1st Response   2nd Response
+                Door Open              INT5(11h,80h)  N/A
+                Spin-up                INT5(01h,80h)  N/A
+                Detect busy            INT5(03h,80h)  N/A
+                No Disk                INT3(stat)     INT5(08h,40h, 00h,00h, 00h,00h,00h,00h)
+                Audio Disk             INT3(stat)     INT5(0Ah,90h, 00h,00h, 00h,00h,00h,00h)
+                Unlicensed:Mode1       INT3(stat)     INT5(0Ah,80h, 00h,00h, 00h,00h,00h,00h)
+                Unlicensed:Mode2       INT3(stat)     INT5(0Ah,80h, 20h,00h, 00h,00h,00h,00h)
+                Unlicensed:Mode2+Audio INT3(stat)     INT5(0Ah,90h, 20h,00h, 00h,00h,00h,00h)
+                Debug/Yaroze:Mode2     INT3(stat)     INT2(02h,00h, 20h,00h, 20h,20h,20h,20h)
+                Licensed:Mode2         INT3(stat)     INT2(02h,00h, 20h,00h, 53h,43h,45h,4xh)
+                Modchip:Audio/Mode1    INT3(stat)     INT2(02h,00h, 00h,00h, 53h,43h,45h,4xh)
+            */
 
             if (cdrom->disc) {
-                RESP_PUSH(0x41);
-                RESP_PUSH(0x45);
-                RESP_PUSH(0x43);
-                RESP_PUSH(0x53);
+                SET_BITS(ifr, IFR_INT, 2);
+
+                // Unlicensed:Mode1
                 RESP_PUSH(0x00);
-                RESP_PUSH(0x20);
                 RESP_PUSH(0x00);
-                RESP_PUSH(0x02);
+                RESP_PUSH(0x00);
+                RESP_PUSH(0x00);
+                RESP_PUSH(0x00);
+                RESP_PUSH(0x00);
+                RESP_PUSH(0x80);
+                RESP_PUSH(0x0a);
+
+                // Licensed:Mode2
+                // RESP_PUSH(0x41);
+                // RESP_PUSH(0x45);
+                // RESP_PUSH(0x43);
+                // RESP_PUSH(0x53);
+                // RESP_PUSH(0x00);
+                // RESP_PUSH(0x20);
+                // RESP_PUSH(0x00);
+                // RESP_PUSH(0x02);
             } else {
+                SET_BITS(ifr, IFR_INT, 5);
+
                 RESP_PUSH(0x00);
                 RESP_PUSH(0x00);
                 RESP_PUSH(0x00);
--- a/psx/dev/dma.c
+++ b/psx/dev/dma.c
@@ -360,7 +360,7 @@
 }
 
 void psx_dma_do_pio(psx_dma_t* dma) {
-    log_fatal("PIO DMA channel unimplemented"); exit(1);
+    log_fatal("PIO DMA channel unimplemented");
 }
 
 void psx_dma_do_otc(psx_dma_t* dma) {
--- a/psx/dev/pad.c
+++ b/psx/dev/pad.c
@@ -11,32 +11,20 @@
     if (!current_slot)
         return 0xffffffff;
 
-    if (!(pad->ctrl & CTRL_JOUT)) {
-        if (pad->ctrl & CTRL_RXEN) {
-            uint32_t data = current_slot->read_func(current_slot);
+    if ((pad->ctrl & CTRL_JOUT) || (pad->ctrl & CTRL_RXEN))
+        return current_slot->read_func(current_slot->udata);
 
-            pad->ctrl &= ~CTRL_RXEN;
-
-            return data;
-        }
-
-        return 0xffffffff;
-    }
-
-    return current_slot->read_func(current_slot->udata);
+    return 0xffffffff;
 }
 
 void pad_write_tx(psx_pad_t* pad, uint16_t data) {
     psx_input_t* current_slot = pad->slot[(pad->ctrl >> 13) & 1];
 
-    if (!current_slot)
+    if (!current_slot || !(pad->ctrl & CTRL_TXEN))
         return;
-
-    if (!(pad->ctrl & CTRL_TXEN))
-        return;
     
     pad->cycles_until_irq = 512;
-    
+
     current_slot->write_func(current_slot->udata, data);
 }
 
--- a/psx/dev/pad.h
+++ b/psx/dev/pad.h
@@ -88,6 +88,11 @@
 #define CTRL_ACIE 0x0800
 #define CTRL_SLOT 0x1000
 
+enum {
+    DEST_JOY = 0x01,
+    DEST_MCD = 0x81
+};
+
 /*
     To-do: Design API to interface any type of controller.
 
@@ -115,6 +120,7 @@
     int enable_once;
     int cycles_until_irq;
     int cycle_counter;
+    int dest;
 
     uint16_t mode, ctrl, baud, stat;
 } psx_pad_t;
--- a/psx/disc/bin.c
+++ b/psx/disc/bin.c
@@ -80,7 +80,7 @@
 }
 
 int psxd_bin_get_track_addr(void* udata, msf_t* msf, int track) {
-    if (track > 0)
+    if (track > 1)
         return DISC_ERR_TRACK_OUT_OF_BOUNDS;
 
     msf->m = 0;
--