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