cdrom: change pause timing again
[pcsx_rearmed.git] / libpcsxcore / sio.c
index b63f56b..0bc763c 100644 (file)
 * SIO functions.
 */
 
+#include "misc.h"
+#include "psxcounters.h"
+#include "psxevents.h"
 #include "sio.h"
 #include <sys/stat.h>
 
+#ifdef USE_LIBRETRO_VFS
+#include <streams/file_stream_transforms.h>
+#endif
+
 // Status Flags
 #define TX_RDY         0x0001
 #define RX_RDY         0x0002
@@ -48,7 +55,8 @@
 // *** FOR WORKS ON PADS AND MEMORY CARDS *****
 
 static unsigned char buf[256];
-unsigned char cardh[4] = { 0x00, 0x00, 0x5a, 0x5d };
+static unsigned char cardh1[4] = { 0xff, 0x08, 0x5a, 0x5d };
+static unsigned char cardh2[4] = { 0xff, 0x08, 0x5a, 0x5d };
 
 // Transfer Ready and the Buffer is Empty
 // static unsigned short StatReg = 0x002b;
@@ -64,80 +72,57 @@ static unsigned char adrH, adrL;
 static unsigned int padst;
 
 char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE];
+char McdDisable[2];
 
 // clk cycle byte
 // 4us * 8bits = (PSXCLK / 1000000) * 32; (linuzappz)
 // TODO: add SioModePrescaler and BaudReg
-static inline void SIO_INT() {
-       if (!Config.Sio) {
-               psxRegs.interrupt |= 0x80;
-               psxRegs.intCycle[7 + 1] = 400;
-               psxRegs.intCycle[7] = psxRegs.cycle;
-               new_dyna_set_event(1, 400);
-       }
-}
+#define SIO_CYCLES             535
 
 void sioWrite8(unsigned char value) {
-#ifdef PAD_LOG
-       PAD_LOG("sio write8 %x\n", value);
+       int more_data = 0;
+#if 0
+       s32 framec = psxRegs.cycle - rcnts[3].cycleStart;
+       printf("%d:%03d sio write8 %04x %02x\n", frame_counter,
+               (s32)(framec / (PSXCLK / 60 / 263.0f)), CtrlReg, value);
 #endif
        switch (padst) {
-               case 1: SIO_INT();
+               case 1:
                        if ((value & 0x40) == 0x40) {
                                padst = 2; parp = 1;
-                               if (!Config.UseNet) {
-                                       switch (CtrlReg & 0x2002) {
-                                               case 0x0002:
-                                                       buf[parp] = PAD1_poll(value);
-                                                       break;
-                                               case 0x2002:
-                                                       buf[parp] = PAD2_poll(value);
-                                                       break;
-                                       }
-                               }/* else {
-//                                     SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]);
-                               }*/
-
-                               if (!(buf[parp] & 0x0f)) {
-                                       bufcount = 2 + 32;
-                               } else {
-                                       bufcount = 2 + (buf[parp] & 0x0f) * 2;
+                               switch (CtrlReg & 0x2002) {
+                                       case 0x0002:
+                                               buf[parp] = PAD1_poll(value, &more_data);
+                                               break;
+                                       case 0x2002:
+                                               buf[parp] = PAD2_poll(value, &more_data);
+                                               break;
                                }
-                               if (buf[parp] == 0x41) {
-                                       switch (value) {
-                                               case 0x43:
-                                                       buf[1] = 0x43;
-                                                       break;
-                                               case 0x45:
-                                                       buf[1] = 0xf3;
-                                                       break;
-                                       }
+
+                               if (more_data) {
+                                       bufcount = parp + 1;
+                                       set_event(PSXINT_SIO, SIO_CYCLES);
                                }
                        }
                        else padst = 0;
                        return;
                case 2:
                        parp++;
-/*                     if (buf[1] == 0x45) {
-                               buf[parp] = 0;
-                               SIO_INT();
-                               return;
-                       }*/
-                       if (!Config.UseNet) {
-                               switch (CtrlReg & 0x2002) {
-                                       case 0x0002: buf[parp] = PAD1_poll(value); break;
-                                       case 0x2002: buf[parp] = PAD2_poll(value); break;
-                               }
+                       switch (CtrlReg & 0x2002) {
+                               case 0x0002: buf[parp] = PAD1_poll(value, &more_data); break;
+                               case 0x2002: buf[parp] = PAD2_poll(value, &more_data); break;
                        }
 
-                       if (parp == bufcount) { padst = 0; return; }
-                       SIO_INT();
+                       if (more_data) {
+                               bufcount = parp + 1;
+                               set_event(PSXINT_SIO, SIO_CYCLES);
+                       }
                        return;
        }
 
        switch (mcdst) {
                case 1:
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
                        if (rdwr) { parp++; return; }
                        parp = 1;
                        switch (value) {
@@ -147,7 +132,7 @@ void sioWrite8(unsigned char value) {
                        }
                        return;
                case 2: // address H
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
                        adrH = value;
                        *buf = 0;
                        parp = 0;
@@ -155,7 +140,7 @@ void sioWrite8(unsigned char value) {
                        mcdst = 3;
                        return;
                case 3: // address L
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
                        adrL = value;
                        *buf = adrH;
                        parp = 0;
@@ -163,7 +148,7 @@ void sioWrite8(unsigned char value) {
                        mcdst = 4;
                        return;
                case 4:
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
                        parp = 0;
                        switch (rdwr) {
                                case 1: // read
@@ -202,10 +187,18 @@ void sioWrite8(unsigned char value) {
                        return;
                case 5:
                        parp++;
+                       if ((rdwr == 1 && parp == 132) ||
+                           (rdwr == 2 && parp == 129)) {
+                               // clear "new card" flags
+                               if (CtrlReg & 0x2000)
+                                       cardh2[1] &= ~8;
+                               else
+                                       cardh1[1] &= ~8;
+                       }
                        if (rdwr == 2) {
                                if (parp < 128) buf[parp + 1] = value;
                        }
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
                        return;
        }
 
@@ -213,56 +206,41 @@ void sioWrite8(unsigned char value) {
                case 0x01: // start pad
                        StatReg |= RX_RDY;              // Transfer is Ready
 
-                       if (!Config.UseNet) {
-                               switch (CtrlReg & 0x2002) {
-                                       case 0x0002: buf[0] = PAD1_startPoll(1); break;
-                                       case 0x2002: buf[0] = PAD2_startPoll(2); break;
-                               }
-                       } else {
-                               if ((CtrlReg & 0x2002) == 0x0002) {
-                                       int i, j;
-
-                                       PAD1_startPoll(1);
-                                       buf[0] = 0;
-                                       buf[1] = PAD1_poll(0x42);
-                                       if (!(buf[1] & 0x0f)) {
-                                               bufcount = 32;
-                                       } else {
-                                               bufcount = (buf[1] & 0x0f) * 2;
-                                       }
-                                       buf[2] = PAD1_poll(0);
-                                       i = 3;
-                                       j = bufcount;
-                                       while (j--) {
-                                               buf[i++] = PAD1_poll(0);
-                                       }
-                                       bufcount+= 3;
-
-                                       if (NET_sendPadData(buf, bufcount) == -1)
-                                               netError();
-
-                                       if (NET_recvPadData(buf, 1) == -1)
-                                               netError();
-                                       if (NET_recvPadData(buf + 128, 2) == -1)
-                                               netError();
-                               } else {
-                                       memcpy(buf, buf + 128, 32);
-                               }
+                       switch (CtrlReg & 0x2002) {
+                               case 0x0002: buf[0] = PAD1_startPoll(1); break;
+                               case 0x2002: buf[0] = PAD2_startPoll(2); break;
                        }
-
-                       bufcount = 2;
+                       bufcount = 1;
                        parp = 0;
                        padst = 1;
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
                        return;
                case 0x81: // start memcard
+                       if (CtrlReg & 0x2000)
+                       {
+                               if (McdDisable[1])
+                                       goto no_device;
+                               memcpy(buf, cardh2, 4);
+                       }
+                       else
+                       {
+                               if (McdDisable[0])
+                                       goto no_device;
+                               memcpy(buf, cardh1, 4);
+                       }
                        StatReg |= RX_RDY;
-                       memcpy(buf, cardh, 4);
                        parp = 0;
                        bufcount = 3;
                        mcdst = 1;
                        rdwr = 0;
-                       SIO_INT();
+                       set_event(PSXINT_SIO, SIO_CYCLES);
+                       return;
+               default:
+               no_device:
+                       StatReg |= RX_RDY;
+                       buf[0] = 0xff;
+                       parp = 0;
+                       bufcount = 0;
                        return;
        }
 }
@@ -277,10 +255,10 @@ void sioWriteMode16(unsigned short value) {
 void sioWriteCtrl16(unsigned short value) {
        CtrlReg = value & ~RESET_ERR;
        if (value & RESET_ERR) StatReg &= ~IRQ;
-       if ((CtrlReg & SIO_RESET) || (!CtrlReg)) {
+       if ((CtrlReg & SIO_RESET) || !(CtrlReg & DTR)) {
                padst = 0; mcdst = 0; parp = 0;
                StatReg = TX_RDY | TX_EMPTY;
-               psxRegs.interrupt &= ~0x80;
+               psxRegs.interrupt &= ~(1 << PSXINT_SIO);
        }
 }
 
@@ -319,8 +297,10 @@ unsigned char sioRead8() {
                }
        }
 
-#ifdef PAD_LOG
-       PAD_LOG("sio read8 ;ret = %x\n", ret);
+#if 0
+       s32 framec = psxRegs.cycle - rcnts[3].cycleStart;
+       printf("%d:%03d sio read8  %04x %02x\n", frame_counter,
+               (s32)((float)framec / (PSXCLK / 60 / 263.0f)), CtrlReg, ret);
 #endif
        return ret;
 }
@@ -341,36 +321,47 @@ unsigned short sioReadBaud16() {
        return BaudReg;
 }
 
-void netError() {
-       ClosePlugins();
-       SysMessage(_("Connection closed!\n"));
-
-       CdromId[0] = '\0';
-       CdromLabel[0] = '\0';
-
-       SysRunGui();
-}
-
 void sioInterrupt() {
 #ifdef PAD_LOG
        PAD_LOG("Sio Interrupt (CP0.Status = %x)\n", psxRegs.CP0.n.Status);
 #endif
 //     SysPrintf("Sio Interrupt\n");
-       StatReg |= IRQ;
-       psxHu32ref(0x1070) |= SWAPu32(0x80);
+       if (!(StatReg & IRQ)) {
+               StatReg |= IRQ;
+               psxHu32ref(0x1070) |= SWAPu32(0x80);
+       }
 }
 
 void LoadMcd(int mcd, char *str) {
        FILE *f;
        char *data = NULL;
 
-       if (mcd == 1) data = Mcd1Data;
-       if (mcd == 2) data = Mcd2Data;
+       if (mcd != 1 && mcd != 2)
+               return;
 
-       if (*str == 0) {
-               sprintf(str, "memcards/card%d.mcd", mcd);
-               SysPrintf(_("No memory card value was specified - creating a default card %s\n"), str);
+       if (mcd == 1) {
+               data = Mcd1Data;
+               cardh1[1] |= 8; // mark as new
+       }
+       if (mcd == 2) {
+               data = Mcd2Data;
+               cardh2[1] |= 8;
        }
+
+       McdDisable[mcd - 1] = 0;
+#ifdef HAVE_LIBRETRO
+       // memcard1 is handled by libretro
+       if (mcd == 1)
+               return;
+#endif
+
+       if (str == NULL || strcmp(str, "none") == 0) {
+               McdDisable[mcd - 1] = 1;
+               return;
+       }
+       if (*str == 0)
+               return;
+
        f = fopen(str, "rb");
        if (f == NULL) {
                SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str);
@@ -385,7 +376,12 @@ void LoadMcd(int mcd, char *str) {
                                else if(buf.st_size == MCD_SIZE + 3904)
                                        fseek(f, 3904, SEEK_SET);
                        }
-                       fread(data, 1, MCD_SIZE, f);
+                       if (fread(data, 1, MCD_SIZE, f) != MCD_SIZE) {
+#ifndef NDEBUG
+                               SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+                               memset(data, 0x00, MCD_SIZE);
+                       }
                        fclose(f);
                }
                else
@@ -400,7 +396,12 @@ void LoadMcd(int mcd, char *str) {
                        else if(buf.st_size == MCD_SIZE + 3904)
                                fseek(f, 3904, SEEK_SET);
                }
-               fread(data, 1, MCD_SIZE, f);
+               if (fread(data, 1, MCD_SIZE, f) != MCD_SIZE) {
+#ifndef NDEBUG
+                       SysPrintf(_("File IO error in <%s:%s>.\n"), __FILE__, __func__);
+#endif
+                       memset(data, 0x00, MCD_SIZE);
+               }
                fclose(f);
        }
 }
@@ -413,6 +414,9 @@ void LoadMcds(char *mcd1, char *mcd2) {
 void SaveMcd(char *mcd, char *data, uint32_t adr, int size) {
        FILE *f;
 
+       if (mcd == NULL || *mcd == 0 || strcmp(mcd, "none") == 0)
+               return;
+
        f = fopen(mcd, "r+b");
        if (f != NULL) {
                struct stat buf;
@@ -612,6 +616,7 @@ void ConvertMcd(char *mcd, char *data) {
                        fclose(f);
                }
                f = fopen(mcd, "r+");
+               if (f == NULL) return;
                s = s + 3904;
                fputc('1', f); s--;
                fputc('2', f); s--;
@@ -646,6 +651,7 @@ void ConvertMcd(char *mcd, char *data) {
                        fclose(f);
                }
                f = fopen(mcd, "r+");
+               if (f == NULL) return;
                s = s + 64;
                fputc('V', f); s--;
                fputc('g', f); s--;
@@ -671,13 +677,19 @@ void ConvertMcd(char *mcd, char *data) {
 }
 
 void GetMcdBlockInfo(int mcd, int block, McdBlock *Info) {
-       unsigned char *data = NULL, *ptr, *str, *sstr;
+       char *data = NULL, *ptr, *str, *sstr;
        unsigned short clut[16];
        unsigned short c;
        int i, x;
 
        memset(Info, 0, sizeof(McdBlock));
 
+       if (mcd != 1 && mcd != 2)
+               return;
+
+       if (McdDisable[mcd - 1])
+               return;
+
        if (mcd == 1) data = Mcd1Data;
        if (mcd == 2) data = Mcd2Data;
 
@@ -758,7 +770,7 @@ void GetMcdBlockInfo(int mcd, int block, McdBlock *Info) {
        strncpy(Info->Name, ptr, 16);
 }
 
-int sioFreeze(gzFile f, int Mode) {
+int sioFreeze(void *f, int Mode) {
        gzfreeze(buf, sizeof(buf));
        gzfreeze(&StatReg, sizeof(StatReg));
        gzfreeze(&ModeReg, sizeof(ModeReg));