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