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