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