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