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