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