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