set memcard paths, rm dead code
[pcsx_rearmed.git] / libpcsxcore / sio.c
CommitLineData
ef79bbde
P
1/***************************************************************************
2 * Copyright (C) 2007 Ryan Schultz, PCSX-df Team, PCSX team *
3 * *
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. *
8 * *
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. *
13 * *
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 ***************************************************************************/
19
20/*
21* SIO functions.
22*/
23
24#include "sio.h"
25#include <sys/stat.h>
26
27// Status Flags
28#define TX_RDY 0x0001
29#define RX_RDY 0x0002
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
35#define DSR 0x0080
36#define CTS 0x0100
37#define IRQ 0x0200
38
39// Control Flags
40#define TX_PERM 0x0001
41#define DTR 0x0002
42#define RX_PERM 0x0004
43#define BREAK 0x0008
44#define RESET_ERR 0x0010
45#define RTS 0x0020
46#define SIO_RESET 0x0040
47
48// *** FOR WORKS ON PADS AND MEMORY CARDS *****
49
50static unsigned char buf[256];
51unsigned char cardh[4] = { 0x00, 0x00, 0x5a, 0x5d };
52
53// Transfer Ready and the Buffer is Empty
54// static unsigned short StatReg = 0x002b;
55static unsigned short StatReg = TX_RDY | TX_EMPTY;
56static unsigned short ModeReg;
57static unsigned short CtrlReg;
58static unsigned short BaudReg;
59
60static unsigned int bufcount;
61static unsigned int parp;
62static unsigned int mcdst, rdwr;
63static unsigned char adrH, adrL;
64static unsigned int padst;
65
66char Mcd1Data[MCD_SIZE], Mcd2Data[MCD_SIZE];
67
d28b54b1 68#define SIO_INT(eCycle) { \
69 if (!Config.Sio) { \
70 psxRegs.interrupt |= (1 << PSXINT_SIO); \
71 psxRegs.intCycle[PSXINT_SIO].cycle = eCycle; \
72 psxRegs.intCycle[PSXINT_SIO].sCycle = psxRegs.cycle; \
73 new_dyna_set_event(PSXINT_SIO, eCycle); \
74 } \
75}
76
ef79bbde
P
77// clk cycle byte
78// 4us * 8bits = (PSXCLK / 1000000) * 32; (linuzappz)
79// TODO: add SioModePrescaler and BaudReg
d28b54b1 80#define SIO_CYCLES 535
ef79bbde
P
81
82void sioWrite8(unsigned char value) {
83#ifdef PAD_LOG
84 PAD_LOG("sio write8 %x\n", value);
85#endif
86 switch (padst) {
d28b54b1 87 case 1: SIO_INT(SIO_CYCLES);
ef79bbde
P
88 if ((value & 0x40) == 0x40) {
89 padst = 2; parp = 1;
90 if (!Config.UseNet) {
91 switch (CtrlReg & 0x2002) {
92 case 0x0002:
93 buf[parp] = PAD1_poll(value);
94 break;
95 case 0x2002:
96 buf[parp] = PAD2_poll(value);
97 break;
98 }
99 }/* else {
100// SysPrintf("%x: %x, %x, %x, %x\n", CtrlReg&0x2002, buf[2], buf[3], buf[4], buf[5]);
101 }*/
102
103 if (!(buf[parp] & 0x0f)) {
104 bufcount = 2 + 32;
105 } else {
106 bufcount = 2 + (buf[parp] & 0x0f) * 2;
107 }
108 if (buf[parp] == 0x41) {
109 switch (value) {
110 case 0x43:
111 buf[1] = 0x43;
112 break;
113 case 0x45:
114 buf[1] = 0xf3;
115 break;
116 }
117 }
118 }
119 else padst = 0;
120 return;
121 case 2:
122 parp++;
123/* if (buf[1] == 0x45) {
124 buf[parp] = 0;
d28b54b1 125 SIO_INT(SIO_CYCLES);
ef79bbde
P
126 return;
127 }*/
128 if (!Config.UseNet) {
129 switch (CtrlReg & 0x2002) {
130 case 0x0002: buf[parp] = PAD1_poll(value); break;
131 case 0x2002: buf[parp] = PAD2_poll(value); break;
132 }
133 }
134
135 if (parp == bufcount) { padst = 0; return; }
d28b54b1 136 SIO_INT(SIO_CYCLES);
ef79bbde
P
137 return;
138 }
139
140 switch (mcdst) {
141 case 1:
d28b54b1 142 SIO_INT(SIO_CYCLES);
ef79bbde
P
143 if (rdwr) { parp++; return; }
144 parp = 1;
145 switch (value) {
146 case 0x52: rdwr = 1; break;
147 case 0x57: rdwr = 2; break;
148 default: mcdst = 0;
149 }
150 return;
151 case 2: // address H
d28b54b1 152 SIO_INT(SIO_CYCLES);
ef79bbde
P
153 adrH = value;
154 *buf = 0;
155 parp = 0;
156 bufcount = 1;
157 mcdst = 3;
158 return;
159 case 3: // address L
d28b54b1 160 SIO_INT(SIO_CYCLES);
ef79bbde
P
161 adrL = value;
162 *buf = adrH;
163 parp = 0;
164 bufcount = 1;
165 mcdst = 4;
166 return;
167 case 4:
d28b54b1 168 SIO_INT(SIO_CYCLES);
ef79bbde
P
169 parp = 0;
170 switch (rdwr) {
171 case 1: // read
172 buf[0] = 0x5c;
173 buf[1] = 0x5d;
174 buf[2] = adrH;
175 buf[3] = adrL;
176 switch (CtrlReg & 0x2002) {
177 case 0x0002:
178 memcpy(&buf[4], Mcd1Data + (adrL | (adrH << 8)) * 128, 128);
179 break;
180 case 0x2002:
181 memcpy(&buf[4], Mcd2Data + (adrL | (adrH << 8)) * 128, 128);
182 break;
183 }
184 {
185 char xor = 0;
186 int i;
187 for (i = 2; i < 128 + 4; i++)
188 xor ^= buf[i];
189 buf[132] = xor;
190 }
191 buf[133] = 0x47;
192 bufcount = 133;
193 break;
194 case 2: // write
195 buf[0] = adrL;
196 buf[1] = value;
197 buf[129] = 0x5c;
198 buf[130] = 0x5d;
199 buf[131] = 0x47;
200 bufcount = 131;
201 break;
202 }
203 mcdst = 5;
204 return;
205 case 5:
206 parp++;
207 if (rdwr == 2) {
208 if (parp < 128) buf[parp + 1] = value;
209 }
d28b54b1 210 SIO_INT(SIO_CYCLES);
ef79bbde
P
211 return;
212 }
213
214 switch (value) {
215 case 0x01: // start pad
216 StatReg |= RX_RDY; // Transfer is Ready
217
218 if (!Config.UseNet) {
219 switch (CtrlReg & 0x2002) {
220 case 0x0002: buf[0] = PAD1_startPoll(1); break;
221 case 0x2002: buf[0] = PAD2_startPoll(2); break;
222 }
223 } else {
224 if ((CtrlReg & 0x2002) == 0x0002) {
225 int i, j;
226
227 PAD1_startPoll(1);
228 buf[0] = 0;
229 buf[1] = PAD1_poll(0x42);
230 if (!(buf[1] & 0x0f)) {
231 bufcount = 32;
232 } else {
233 bufcount = (buf[1] & 0x0f) * 2;
234 }
235 buf[2] = PAD1_poll(0);
236 i = 3;
237 j = bufcount;
238 while (j--) {
239 buf[i++] = PAD1_poll(0);
240 }
241 bufcount+= 3;
242
243 if (NET_sendPadData(buf, bufcount) == -1)
244 netError();
245
246 if (NET_recvPadData(buf, 1) == -1)
247 netError();
248 if (NET_recvPadData(buf + 128, 2) == -1)
249 netError();
250 } else {
251 memcpy(buf, buf + 128, 32);
252 }
253 }
254
255 bufcount = 2;
256 parp = 0;
257 padst = 1;
d28b54b1 258 SIO_INT(SIO_CYCLES);
ef79bbde
P
259 return;
260 case 0x81: // start memcard
261 StatReg |= RX_RDY;
262 memcpy(buf, cardh, 4);
263 parp = 0;
264 bufcount = 3;
265 mcdst = 1;
266 rdwr = 0;
d28b54b1 267 SIO_INT(SIO_CYCLES);
ef79bbde
P
268 return;
269 }
270}
271
272void sioWriteStat16(unsigned short value) {
273}
274
275void sioWriteMode16(unsigned short value) {
276 ModeReg = value;
277}
278
279void sioWriteCtrl16(unsigned short value) {
280 CtrlReg = value & ~RESET_ERR;
281 if (value & RESET_ERR) StatReg &= ~IRQ;
282 if ((CtrlReg & SIO_RESET) || (!CtrlReg)) {
283 padst = 0; mcdst = 0; parp = 0;
284 StatReg = TX_RDY | TX_EMPTY;
d28b54b1 285 psxRegs.interrupt &= ~(1 << PSXINT_SIO);
ef79bbde
P
286 }
287}
288
289void sioWriteBaud16(unsigned short value) {
290 BaudReg = value;
291}
292
293unsigned char sioRead8() {
294 unsigned char ret = 0;
295
296 if ((StatReg & RX_RDY)/* && (CtrlReg & RX_PERM)*/) {
297// StatReg &= ~RX_OVERRUN;
298 ret = buf[parp];
299 if (parp == bufcount) {
300 StatReg &= ~RX_RDY; // Receive is not Ready now
301 if (mcdst == 5) {
302 mcdst = 0;
303 if (rdwr == 2) {
304 switch (CtrlReg & 0x2002) {
305 case 0x0002:
306 memcpy(Mcd1Data + (adrL | (adrH << 8)) * 128, &buf[1], 128);
307 SaveMcd(Config.Mcd1, Mcd1Data, (adrL | (adrH << 8)) * 128, 128);
308 break;
309 case 0x2002:
310 memcpy(Mcd2Data + (adrL | (adrH << 8)) * 128, &buf[1], 128);
311 SaveMcd(Config.Mcd2, Mcd2Data, (adrL | (adrH << 8)) * 128, 128);
312 break;
313 }
314 }
315 }
316 if (padst == 2) padst = 0;
317 if (mcdst == 1) {
318 mcdst = 2;
319 StatReg|= RX_RDY;
320 }
321 }
322 }
323
324#ifdef PAD_LOG
325 PAD_LOG("sio read8 ;ret = %x\n", ret);
326#endif
327 return ret;
328}
329
330unsigned short sioReadStat16() {
331 return StatReg;
332}
333
334unsigned short sioReadMode16() {
335 return ModeReg;
336}
337
338unsigned short sioReadCtrl16() {
339 return CtrlReg;
340}
341
342unsigned short sioReadBaud16() {
343 return BaudReg;
344}
345
346void netError() {
347 ClosePlugins();
348 SysMessage(_("Connection closed!\n"));
349
350 CdromId[0] = '\0';
351 CdromLabel[0] = '\0';
352
353 SysRunGui();
354}
355
356void sioInterrupt() {
357#ifdef PAD_LOG
358 PAD_LOG("Sio Interrupt (CP0.Status = %x)\n", psxRegs.CP0.n.Status);
359#endif
360// SysPrintf("Sio Interrupt\n");
361 StatReg |= IRQ;
362 psxHu32ref(0x1070) |= SWAPu32(0x80);
363}
364
365void LoadMcd(int mcd, char *str) {
366 FILE *f;
367 char *data = NULL;
368
369 if (mcd == 1) data = Mcd1Data;
370 if (mcd == 2) data = Mcd2Data;
371
372 if (*str == 0) {
373 sprintf(str, "memcards/card%d.mcd", mcd);
374 SysPrintf(_("No memory card value was specified - creating a default card %s\n"), str);
375 }
376 f = fopen(str, "rb");
377 if (f == NULL) {
378 SysPrintf(_("The memory card %s doesn't exist - creating it\n"), str);
379 CreateMcd(str);
380 f = fopen(str, "rb");
381 if (f != NULL) {
382 struct stat buf;
383
384 if (stat(str, &buf) != -1) {
385 if (buf.st_size == MCD_SIZE + 64)
386 fseek(f, 64, SEEK_SET);
387 else if(buf.st_size == MCD_SIZE + 3904)
388 fseek(f, 3904, SEEK_SET);
389 }
390 fread(data, 1, MCD_SIZE, f);
391 fclose(f);
392 }
393 else
394 SysMessage(_("Memory card %s failed to load!\n"), str);
395 }
396 else {
397 struct stat buf;
398 SysPrintf(_("Loading memory card %s\n"), str);
399 if (stat(str, &buf) != -1) {
400 if (buf.st_size == MCD_SIZE + 64)
401 fseek(f, 64, SEEK_SET);
402 else if(buf.st_size == MCD_SIZE + 3904)
403 fseek(f, 3904, SEEK_SET);
404 }
405 fread(data, 1, MCD_SIZE, f);
406 fclose(f);
407 }
408}
409
410void LoadMcds(char *mcd1, char *mcd2) {
411 LoadMcd(1, mcd1);
412 LoadMcd(2, mcd2);
413}
414
415void SaveMcd(char *mcd, char *data, uint32_t adr, int size) {
416 FILE *f;
417
418 f = fopen(mcd, "r+b");
419 if (f != NULL) {
420 struct stat buf;
421
422 if (stat(mcd, &buf) != -1) {
423 if (buf.st_size == MCD_SIZE + 64)
424 fseek(f, adr + 64, SEEK_SET);
425 else if (buf.st_size == MCD_SIZE + 3904)
426 fseek(f, adr + 3904, SEEK_SET);
427 else
428 fseek(f, adr, SEEK_SET);
429 } else
430 fseek(f, adr, SEEK_SET);
431
432 fwrite(data + adr, 1, size, f);
433 fclose(f);
434 return;
435 }
436
437#if 0
438 // try to create it again if we can't open it
439 f = fopen(mcd, "wb");
440 if (f != NULL) {
441 fwrite(data, 1, MCD_SIZE, f);
442 fclose(f);
443 }
444#endif
445
446 ConvertMcd(mcd, data);
447}
448
449void CreateMcd(char *mcd) {
450 FILE *f;
451 struct stat buf;
452 int s = MCD_SIZE;
453 int i = 0, j;
454
455 f = fopen(mcd, "wb");
456 if (f == NULL)
457 return;
458
459 if (stat(mcd, &buf) != -1) {
460 if ((buf.st_size == MCD_SIZE + 3904) || strstr(mcd, ".gme")) {
461 s = s + 3904;
462 fputc('1', f);
463 s--;
464 fputc('2', f);
465 s--;
466 fputc('3', f);
467 s--;
468 fputc('-', f);
469 s--;
470 fputc('4', f);
471 s--;
472 fputc('5', f);
473 s--;
474 fputc('6', f);
475 s--;
476 fputc('-', f);
477 s--;
478 fputc('S', f);
479 s--;
480 fputc('T', f);
481 s--;
482 fputc('D', f);
483 s--;
484 for (i = 0; i < 7; i++) {
485 fputc(0, f);
486 s--;
487 }
488 fputc(1, f);
489 s--;
490 fputc(0, f);
491 s--;
492 fputc(1, f);
493 s--;
494 fputc('M', f);
495 s--;
496 fputc('Q', f);
497 s--;
498 for (i = 0; i < 14; i++) {
499 fputc(0xa0, f);
500 s--;
501 }
502 fputc(0, f);
503 s--;
504 fputc(0xff, f);
505 while (s-- > (MCD_SIZE + 1))
506 fputc(0, f);
507 } else if ((buf.st_size == MCD_SIZE + 64) || strstr(mcd, ".mem") || strstr(mcd, ".vgs")) {
508 s = s + 64;
509 fputc('V', f);
510 s--;
511 fputc('g', f);
512 s--;
513 fputc('s', f);
514 s--;
515 fputc('M', f);
516 s--;
517 for (i = 0; i < 3; i++) {
518 fputc(1, f);
519 s--;
520 fputc(0, f);
521 s--;
522 fputc(0, f);
523 s--;
524 fputc(0, f);
525 s--;
526 }
527 fputc(0, f);
528 s--;
529 fputc(2, f);
530 while (s-- > (MCD_SIZE + 1))
531 fputc(0, f);
532 }
533 }
534 fputc('M', f);
535 s--;
536 fputc('C', f);
537 s--;
538 while (s-- > (MCD_SIZE - 127))
539 fputc(0, f);
540 fputc(0xe, f);
541 s--;
542
543 for (i = 0; i < 15; i++) { // 15 blocks
544 fputc(0xa0, f);
545 s--;
546 fputc(0x00, f);
547 s--;
548 fputc(0x00, f);
549 s--;
550 fputc(0x00, f);
551 s--;
552 fputc(0x00, f);
553 s--;
554 fputc(0x00, f);
555 s--;
556 fputc(0x00, f);
557 s--;
558 fputc(0x00, f);
559 s--;
560 fputc(0xff, f);
561 s--;
562 fputc(0xff, f);
563 s--;
564 for (j = 0; j < 117; j++) {
565 fputc(0x00, f);
566 s--;
567 }
568 fputc(0xa0, f);
569 s--;
570 }
571
572 for (i = 0; i < 20; i++) {
573 fputc(0xff, f);
574 s--;
575 fputc(0xff, f);
576 s--;
577 fputc(0xff, f);
578 s--;
579 fputc(0xff, f);
580 s--;
581 fputc(0x00, f);
582 s--;
583 fputc(0x00, f);
584 s--;
585 fputc(0x00, f);
586 s--;
587 fputc(0x00, f);
588 s--;
589 fputc(0xff, f);
590 s--;
591 fputc(0xff, f);
592 s--;
593 for (j = 0; j < 118; j++) {
594 fputc(0x00, f);
595 s--;
596 }
597 }
598
599 while ((s--) >= 0)
600 fputc(0, f);
601
602 fclose(f);
603}
604
605void ConvertMcd(char *mcd, char *data) {
606 FILE *f;
607 int i = 0;
608 int s = MCD_SIZE;
609
610 if (strstr(mcd, ".gme")) {
611 f = fopen(mcd, "wb");
612 if (f != NULL) {
613 fwrite(data - 3904, 1, MCD_SIZE + 3904, f);
614 fclose(f);
615 }
616 f = fopen(mcd, "r+");
617 s = s + 3904;
618 fputc('1', f); s--;
619 fputc('2', f); s--;
620 fputc('3', f); s--;
621 fputc('-', f); s--;
622 fputc('4', f); s--;
623 fputc('5', f); s--;
624 fputc('6', f); s--;
625 fputc('-', f); s--;
626 fputc('S', f); s--;
627 fputc('T', f); s--;
628 fputc('D', f); s--;
629 for (i = 0; i < 7; i++) {
630 fputc(0, f); s--;
631 }
632 fputc(1, f); s--;
633 fputc(0, f); s--;
634 fputc(1, f); s--;
635 fputc('M', f); s--;
636 fputc('Q', f); s--;
637 for(i=0;i<14;i++) {
638 fputc(0xa0, f); s--;
639 }
640 fputc(0, f); s--;
641 fputc(0xff, f);
642 while (s-- > (MCD_SIZE+1)) fputc(0, f);
643 fclose(f);
644 } else if(strstr(mcd, ".mem") || strstr(mcd,".vgs")) {
645 f = fopen(mcd, "wb");
646 if (f != NULL) {
647 fwrite(data-64, 1, MCD_SIZE+64, f);
648 fclose(f);
649 }
650 f = fopen(mcd, "r+");
651 s = s + 64;
652 fputc('V', f); s--;
653 fputc('g', f); s--;
654 fputc('s', f); s--;
655 fputc('M', f); s--;
656 for(i=0;i<3;i++) {
657 fputc(1, f); s--;
658 fputc(0, f); s--;
659 fputc(0, f); s--;
660 fputc(0, f); s--;
661 }
662 fputc(0, f); s--;
663 fputc(2, f);
664 while (s-- > (MCD_SIZE+1)) fputc(0, f);
665 fclose(f);
666 } else {
667 f = fopen(mcd, "wb");
668 if (f != NULL) {
669 fwrite(data, 1, MCD_SIZE, f);
670 fclose(f);
671 }
672 }
673}
674
675void GetMcdBlockInfo(int mcd, int block, McdBlock *Info) {
676 unsigned char *data = NULL, *ptr, *str, *sstr;
677 unsigned short clut[16];
678 unsigned short c;
679 int i, x;
680
681 memset(Info, 0, sizeof(McdBlock));
682
683 if (mcd == 1) data = Mcd1Data;
684 if (mcd == 2) data = Mcd2Data;
685
686 ptr = data + block * 8192 + 2;
687
688 Info->IconCount = *ptr & 0x3;
689
690 ptr += 2;
691
692 x = 0;
693
694 str = Info->Title;
695 sstr = Info->sTitle;
696
697 for (i = 0; i < 48; i++) {
698 c = *(ptr) << 8;
699 c |= *(ptr + 1);
700 if (!c) break;
701
702 // Convert ASCII characters to half-width
703 if (c >= 0x8281 && c <= 0x829A)
704 c = (c - 0x8281) + 'a';
705 else if (c >= 0x824F && c <= 0x827A)
706 c = (c - 0x824F) + '0';
707 else if (c == 0x8140) c = ' ';
708 else if (c == 0x8143) c = ',';
709 else if (c == 0x8144) c = '.';
710 else if (c == 0x8146) c = ':';
711 else if (c == 0x8147) c = ';';
712 else if (c == 0x8148) c = '?';
713 else if (c == 0x8149) c = '!';
714 else if (c == 0x815E) c = '/';
715 else if (c == 0x8168) c = '"';
716 else if (c == 0x8169) c = '(';
717 else if (c == 0x816A) c = ')';
718 else if (c == 0x816D) c = '[';
719 else if (c == 0x816E) c = ']';
720 else if (c == 0x817C) c = '-';
721 else {
722 str[i] = ' ';
723 sstr[x++] = *ptr++; sstr[x++] = *ptr++;
724 continue;
725 }
726
727 str[i] = sstr[x++] = c;
728 ptr += 2;
729 }
730
731 trim(str);
732 trim(sstr);
733
734 ptr = data + block * 8192 + 0x60; // icon palette data
735
736 for (i = 0; i < 16; i++) {
737 clut[i] = *((unsigned short *)ptr);
738 ptr += 2;
739 }
740
741 for (i = 0; i < Info->IconCount; i++) {
742 short *icon = &Info->Icon[i * 16 * 16];
743
744 ptr = data + block * 8192 + 128 + 128 * i; // icon data
745
746 for (x = 0; x < 16 * 16; x++) {
747 icon[x++] = clut[*ptr & 0xf];
748 icon[x] = clut[*ptr >> 4];
749 ptr++;
750 }
751 }
752
753 ptr = data + block * 128;
754
755 Info->Flags = *ptr;
756
757 ptr += 0xa;
758 strncpy(Info->ID, ptr, 12);
759 ptr += 12;
760 strncpy(Info->Name, ptr, 16);
761}
762
763int sioFreeze(gzFile f, int Mode) {
764 gzfreeze(buf, sizeof(buf));
765 gzfreeze(&StatReg, sizeof(StatReg));
766 gzfreeze(&ModeReg, sizeof(ModeReg));
767 gzfreeze(&CtrlReg, sizeof(CtrlReg));
768 gzfreeze(&BaudReg, sizeof(BaudReg));
769 gzfreeze(&bufcount, sizeof(bufcount));
770 gzfreeze(&parp, sizeof(parp));
771 gzfreeze(&mcdst, sizeof(mcdst));
772 gzfreeze(&rdwr, sizeof(rdwr));
773 gzfreeze(&adrH, sizeof(adrH));
774 gzfreeze(&adrL, sizeof(adrL));
775 gzfreeze(&padst, sizeof(padst));
776
777 return 0;
778}