1 /***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
4 * This program is free software; you can redistribute it and/or modify *
5 * it under the terms of the GNU General Public License as published by *
6 * the Free Software Foundation; either version 2 of the License, or *
7 * (at your option) any later version. *
9 * This program is distributed in the hope that it will be useful, *
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
12 * GNU General Public License for more details. *
14 * You should have received a copy of the GNU General Public License *
15 * along with this program; if not, write to the *
16 * Free Software Foundation, Inc., *
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA. *
18 ***************************************************************************/
30 #define TX_EMPTY 0x0004
31 #define PARITY_ERR 0x0008
32 #define RX_OVERRUN 0x0010
33 #define FRAMING_ERR 0x0020
34 #define SYNC_DETECT 0x0040
40 #define TX_PERM 0x0001
42 #define RX_PERM 0x0004
44 #define RESET_ERR 0x0010
46 #define SIO_RESET 0x0040
48 // *** FOR WORKS ON PADS AND MEMORY CARDS *****
50 static unsigned char buf[256];
51 static unsigned char cardh1[4] = { 0xff, 0x08, 0x5a, 0x5d };
52 static unsigned char cardh2[4] = { 0xff, 0x08, 0x5a, 0x5d };
54 // Transfer Ready and the Buffer is Empty
55 // static unsigned short StatReg = 0x002b;
56 static unsigned short StatReg = TX_RDY | TX_EMPTY;
57 static unsigned short ModeReg;
58 static unsigned short CtrlReg;
59 static unsigned short BaudReg;
61 static unsigned int bufcount;
62 static unsigned int parp;
63 static unsigned int mcdst, rdwr;
64 static unsigned char adrH, adrL;
65 static unsigned int padst;
67 char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE];
70 #define SIO_INT(eCycle) { \
72 psxRegs.interrupt |= (1 << PSXINT_SIO); \
73 psxRegs.intCycle[PSXINT_SIO].cycle = eCycle; \
74 psxRegs.intCycle[PSXINT_SIO].sCycle = psxRegs.cycle; \
75 new_dyna_set_event(PSXINT_SIO, eCycle); \
80 // 4us * 8bits = (PSXCLK / 1000000) * 32; (linuzappz)
81 // TODO: add SioModePrescaler and BaudReg
82 #define SIO_CYCLES 535
84 void sioWrite8(unsigned char value) {
86 PAD_LOG("sio write8 %x\n", value);
89 case 1: SIO_INT(SIO_CYCLES);
90 if ((value & 0x40) == 0x40) {
93 switch (CtrlReg & 0x2002) {
95 buf[parp] = PAD1_poll(value);
98 buf[parp] = PAD2_poll(value);
102 // SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]);
105 if (!(buf[parp] & 0x0f)) {
108 bufcount = 2 + (buf[parp] & 0x0f) * 2;
110 if (buf[parp] == 0x41) {
125 /* if (buf[1] == 0x45) {
130 if (!Config.UseNet) {
131 switch (CtrlReg & 0x2002) {
132 case 0x0002: buf[parp] = PAD1_poll(value); break;
133 case 0x2002: buf[parp] = PAD2_poll(value); break;
137 if (parp == bufcount) { padst = 0; return; }
145 if (rdwr) { parp++; return; }
148 case 0x52: rdwr = 1; break;
149 case 0x57: rdwr = 2; break;
178 switch (CtrlReg & 0x2002) {
180 memcpy(&buf[4], Mcd1Data + (adrL | (adrH << 8)) * 128, 128);
183 memcpy(&buf[4], Mcd2Data + (adrL | (adrH << 8)) * 128, 128);
189 for (i = 2; i < 128 + 4; i++)
209 if ((rdwr == 1 && parp == 132) ||
210 (rdwr == 2 && parp == 129)) {
211 // clear "new card" flags
212 if (CtrlReg & 0x2000)
218 if (parp < 128) buf[parp + 1] = value;
225 case 0x01: // start pad
226 StatReg |= RX_RDY; // Transfer is Ready
228 if (!Config.UseNet) {
229 switch (CtrlReg & 0x2002) {
230 case 0x0002: buf[0] = PAD1_startPoll(1); break;
231 case 0x2002: buf[0] = PAD2_startPoll(2); break;
234 if ((CtrlReg & 0x2002) == 0x0002) {
239 buf[1] = PAD1_poll(0x42);
240 if (!(buf[1] & 0x0f)) {
243 bufcount = (buf[1] & 0x0f) * 2;
245 buf[2] = PAD1_poll(0);
249 buf[i++] = PAD1_poll(0);
253 if (NET_sendPadData(buf, bufcount) == -1)
256 if (NET_recvPadData(buf, 1) == -1)
258 if (NET_recvPadData(buf + 128, 2) == -1)
261 memcpy(buf, buf + 128, 32);
270 case 0x81: // start memcard
271 if (CtrlReg & 0x2000)
275 memcpy(buf, cardh2, 4);
281 memcpy(buf, cardh1, 4);
300 void sioWriteStat16(unsigned short value) {
303 void sioWriteMode16(unsigned short value) {
307 void sioWriteCtrl16(unsigned short value) {
308 CtrlReg = value & ~RESET_ERR;
309 if (value & RESET_ERR) StatReg &= ~IRQ;
310 if ((CtrlReg & SIO_RESET) || !(CtrlReg & DTR)) {
311 padst = 0; mcdst = 0; parp = 0;
312 StatReg = TX_RDY | TX_EMPTY;
313 psxRegs.interrupt &= ~(1 << PSXINT_SIO);
317 void sioWriteBaud16(unsigned short value) {
321 unsigned char sioRead8() {
322 unsigned char ret = 0;
324 if ((StatReg & RX_RDY)/* && (CtrlReg & RX_PERM)*/) {
325 // StatReg &= ~RX_OVERRUN;
327 if (parp == bufcount) {
328 StatReg &= ~RX_RDY; // Receive is not Ready now
332 switch (CtrlReg & 0x2002) {
334 memcpy(Mcd1Data + (adrL | (adrH << 8)) * 128, &buf[1], 128);
335 SaveMcd(Config.Mcd1, Mcd1Data, (adrL | (adrH << 8)) * 128, 128);
338 memcpy(Mcd2Data + (adrL | (adrH << 8)) * 128, &buf[1], 128);
339 SaveMcd(Config.Mcd2, Mcd2Data, (adrL | (adrH << 8)) * 128, 128);
344 if (padst == 2) padst = 0;
353 PAD_LOG("sio read8 ;ret = %x\n", ret);
358 unsigned short sioReadStat16() {
362 unsigned short sioReadMode16() {
366 unsigned short sioReadCtrl16() {
370 unsigned short sioReadBaud16() {
376 SysMessage(_("Connection closed!\n"));
379 CdromLabel[0] = '\0';
384 void sioInterrupt() {
386 PAD_LOG("Sio Interrupt (CP0.Status = %x)\n", psxRegs.CP0.n.Status);
388 // SysPrintf("Sio Interrupt\n");
390 psxHu32ref(0x1070) |= SWAPu32(0x80);
393 void LoadMcd(int mcd, char *str) {
397 if (mcd != 1 && mcd != 2)
402 cardh1[1] |= 8; // mark as new
409 McdDisable[mcd - 1] = 0;
410 if (str == NULL || *str == 0) {
411 McdDisable[mcd - 1] = 1;
414 f = fopen(str, "rb");
416 SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str);
418 f = fopen(str, "rb");
422 if (stat(str, &buf) != -1) {
423 if (buf.st_size == MCD_SIZE + 64)
424 fseek(f, 64, SEEK_SET);
425 else if(buf.st_size == MCD_SIZE + 3904)
426 fseek(f, 3904, SEEK_SET);
428 fread(data, 1, MCD_SIZE, f);
432 SysMessage(_("Memory card %s failed to load!\n"), str);
436 SysPrintf(_("Loading memory card %s\n"), str);
437 if (stat(str, &buf) != -1) {
438 if (buf.st_size == MCD_SIZE + 64)
439 fseek(f, 64, SEEK_SET);
440 else if(buf.st_size == MCD_SIZE + 3904)
441 fseek(f, 3904, SEEK_SET);
443 fread(data, 1, MCD_SIZE, f);
448 void LoadMcds(char *mcd1, char *mcd2) {
453 void SaveMcd(char *mcd, char *data, uint32_t adr, int size) {
456 f = fopen(mcd, "r+b");
460 if (stat(mcd, &buf) != -1) {
461 if (buf.st_size == MCD_SIZE + 64)
462 fseek(f, adr + 64, SEEK_SET);
463 else if (buf.st_size == MCD_SIZE + 3904)
464 fseek(f, adr + 3904, SEEK_SET);
466 fseek(f, adr, SEEK_SET);
468 fseek(f, adr, SEEK_SET);
470 fwrite(data + adr, 1, size, f);
476 // try to create it again if we can't open it
477 f = fopen(mcd, "wb");
479 fwrite(data, 1, MCD_SIZE, f);
484 ConvertMcd(mcd, data);
487 void CreateMcd(char *mcd) {
493 f = fopen(mcd, "wb");
497 if (stat(mcd, &buf) != -1) {
498 if ((buf.st_size == MCD_SIZE + 3904) || strstr(mcd, ".gme")) {
522 for (i = 0; i < 7; i++) {
536 for (i = 0; i < 14; i++) {
543 while (s-- > (MCD_SIZE + 1))
545 } else if ((buf.st_size == MCD_SIZE + 64) || strstr(mcd, ".mem") || strstr(mcd, ".vgs")) {
555 for (i = 0; i < 3; i++) {
568 while (s-- > (MCD_SIZE + 1))
576 while (s-- > (MCD_SIZE - 127))
581 for (i = 0; i < 15; i++) { // 15 blocks
602 for (j = 0; j < 117; j++) {
610 for (i = 0; i < 20; i++) {
631 for (j = 0; j < 118; j++) {
643 void ConvertMcd(char *mcd, char *data) {
648 if (strstr(mcd, ".gme")) {
649 f = fopen(mcd, "wb");
651 fwrite(data - 3904, 1, MCD_SIZE + 3904, f);
654 f = fopen(mcd, "r+");
667 for (i = 0; i < 7; i++) {
680 while (s-- > (MCD_SIZE+1)) fputc(0, f);
682 } else if(strstr(mcd, ".mem") || strstr(mcd,".vgs")) {
683 f = fopen(mcd, "wb");
685 fwrite(data-64, 1, MCD_SIZE+64, f);
688 f = fopen(mcd, "r+");
702 while (s-- > (MCD_SIZE+1)) fputc(0, f);
705 f = fopen(mcd, "wb");
707 fwrite(data, 1, MCD_SIZE, f);
713 void GetMcdBlockInfo(int mcd, int block, McdBlock *Info) {
714 char *data = NULL, *ptr, *str, *sstr;
715 unsigned short clut[16];
719 memset(Info, 0, sizeof(McdBlock));
721 if (mcd != 1 && mcd != 2)
724 if (McdDisable[mcd - 1])
727 if (mcd == 1) data = Mcd1Data;
728 if (mcd == 2) data = Mcd2Data;
730 ptr = data + block * 8192 + 2;
732 Info->IconCount = *ptr & 0x3;
741 for (i = 0; i < 48; i++) {
746 // Convert ASCII characters to half-width
747 if (c >= 0x8281 && c <= 0x829A)
748 c = (c - 0x8281) + 'a';
749 else if (c >= 0x824F && c <= 0x827A)
750 c = (c - 0x824F) + '0';
751 else if (c == 0x8140) c = ' ';
752 else if (c == 0x8143) c = ',';
753 else if (c == 0x8144) c = '.';
754 else if (c == 0x8146) c = ':';
755 else if (c == 0x8147) c = ';';
756 else if (c == 0x8148) c = '?';
757 else if (c == 0x8149) c = '!';
758 else if (c == 0x815E) c = '/';
759 else if (c == 0x8168) c = '"';
760 else if (c == 0x8169) c = '(';
761 else if (c == 0x816A) c = ')';
762 else if (c == 0x816D) c = '[';
763 else if (c == 0x816E) c = ']';
764 else if (c == 0x817C) c = '-';
767 sstr[x++] = *ptr++; sstr[x++] = *ptr++;
771 str[i] = sstr[x++] = c;
778 ptr = data + block * 8192 + 0x60; // icon palette data
780 for (i = 0; i < 16; i++) {
781 clut[i] = *((unsigned short *)ptr);
785 for (i = 0; i < Info->IconCount; i++) {
786 short *icon = &Info->Icon[i * 16 * 16];
788 ptr = data + block * 8192 + 128 + 128 * i; // icon data
790 for (x = 0; x < 16 * 16; x++) {
791 icon[x++] = clut[*ptr & 0xf];
792 icon[x] = clut[*ptr >> 4];
797 ptr = data + block * 128;
802 strncpy(Info->ID, ptr, 12);
804 strncpy(Info->Name, ptr, 16);
807 int sioFreeze(gzFile f, int Mode) {
808 gzfreeze(buf, sizeof(buf));
809 gzfreeze(&StatReg, sizeof(StatReg));
810 gzfreeze(&ModeReg, sizeof(ModeReg));
811 gzfreeze(&CtrlReg, sizeof(CtrlReg));
812 gzfreeze(&BaudReg, sizeof(BaudReg));
813 gzfreeze(&bufcount, sizeof(bufcount));
814 gzfreeze(&parp, sizeof(parp));
815 gzfreeze(&mcdst, sizeof(mcdst));
816 gzfreeze(&rdwr, sizeof(rdwr));
817 gzfreeze(&adrH, sizeof(adrH));
818 gzfreeze(&adrL, sizeof(adrL));
819 gzfreeze(&padst, sizeof(padst));