* 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
// *** 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;
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) {
}
return;
case 2: // address H
- SIO_INT();
+ set_event(PSXINT_SIO, SIO_CYCLES);
adrH = value;
*buf = 0;
parp = 0;
mcdst = 3;
return;
case 3: // address L
- SIO_INT();
+ set_event(PSXINT_SIO, SIO_CYCLES);
adrL = value;
*buf = adrH;
parp = 0;
mcdst = 4;
return;
case 4:
- SIO_INT();
+ set_event(PSXINT_SIO, SIO_CYCLES);
parp = 0;
switch (rdwr) {
case 1: // read
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;
}
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;
}
}
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);
}
}
}
}
-#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;
}
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);
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
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);
}
}
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;
fclose(f);
}
f = fopen(mcd, "r+");
+ if (f == NULL) return;
s = s + 3904;
fputc('1', f); s--;
fputc('2', f); s--;
fclose(f);
}
f = fopen(mcd, "r+");
+ if (f == NULL) return;
s = s + 64;
fputc('V', f); s--;
fputc('g', f); s--;
}
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;
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));