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