view src/gb/gbSGB.cpp @ 34:6bde5b67a2b8

saving progress
author Robert McIntyre <rlm@mit.edu>
date Mon, 05 Mar 2012 01:58:52 -0600
parents f9f4f1b99eed
children
line wrap: on
line source
1 #include <cstdlib>
2 #include <cstring>
4 #include "../common/System.h"
5 #include "../common/Util.h"
6 #include "GB.h"
7 #include "gbGlobals.h"
8 #include "../common/movie.h"
10 extern u8 * pix;
12 #define GBSGB_NONE 0
13 #define GBSGB_RESET 1
14 #define GBSGB_PACKET_TRANSMIT 2
16 u8 gbSgbBorderChar [32 * 256];
17 u8 gbSgbBorder [2048];
19 int32 gbSgbCGBSupport = 0;
20 int32 gbSgbMask = 0;
21 int32 gbSgbMode = 0;
22 int32 gbSgbPacketState = GBSGB_NONE;
23 int32 gbSgbBit = 0;
24 int32 gbSgbPacketTimeout = 0;
25 int32 GBSGB_PACKET_TIMEOUT = 66666;
26 u8 gbSgbPacket[16 * 7];
27 int32 gbSgbPacketNBits = 0;
28 int32 gbSgbPacketByte = 0;
29 int32 gbSgbPacketNumber = 0;
30 int32 gbSgbMultiplayer = 0;
31 int32 gbSgbFourPlayers = 0;
32 u8 gbSgbNextController = 0x0f;
33 u8 gbSgbReadingController = 0;
34 u16 gbSgbSCPPalette[4 * 512];
35 u8 gbSgbATF[20 * 18];
36 u8 gbSgbATFList[45 * 20 * 18];
37 u8 gbSgbScreenBuffer[4160];
39 inline void gbSgbDraw24Bit(u8 *p, u16 v)
40 {
41 *((u32 *) p) = systemColorMap32[v];
42 }
44 inline void gbSgbDraw32Bit(u32 *p, u16 v)
45 {
46 *p = systemColorMap32[v];
47 }
49 inline void gbSgbDraw16Bit(u16 *p, u16 v)
50 {
51 *p = systemColorMap16[v];
52 }
54 void gbSgbReset()
55 {
56 gbSgbPacketTimeout = 0;
57 gbSgbCGBSupport = 0;
58 gbSgbMask = 0;
59 gbSgbPacketState = GBSGB_NONE;
60 gbSgbBit = 0;
61 gbSgbPacketNBits = 0;
62 gbSgbPacketNumber = 0;
63 gbSgbMultiplayer = 0;
64 gbSgbFourPlayers = 0;
65 gbSgbNextController = 0x0f;
66 gbSgbReadingController = 0;
68 memset(gbSgbSCPPalette, 0, 512 * 4);
69 memset(gbSgbATF, 0, 20 * 18);
70 memset(gbSgbATFList, 0, 45 * 20 * 18);
71 memset(gbSgbPacket, 0, 16 * 7);
72 memset(gbSgbBorderChar, 0, 32 * 256);
73 memset(gbSgbBorder, 0, 2048);
75 int i;
76 for (i = 1; i < 2048; i += 2)
77 {
78 gbSgbBorder[i] = 1 << 2;
79 }
81 for (i = 0; i < 4; i++)
82 {
83 gbPalette[i * 4] = (0x1f) | (0x1f << 5) | (0x1f << 10);
84 gbPalette[i * 4 + 1] = (0x15) | (0x15 << 5) | (0x15 << 10);
85 gbPalette[i * 4 + 2] = (0x0c) | (0x0c << 5) | (0x0c << 10);
86 gbPalette[i * 4 + 3] = 0;
87 }
88 }
90 void gbSgbInit()
91 {
92 gbSgbReset();
93 }
95 void gbSgbShutdown()
96 {
97 memset(gbSgbBorderChar, 0, 32 * 256);
98 memset(gbSgbBorder, 0, 2048);
99 }
101 void gbSgbFillScreen(u16 color)
102 {
103 switch (systemColorDepth)
104 {
105 case 16:
106 {
107 for (int y = 0; y < 144; y++)
108 {
109 int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 2) +
110 gbBorderColumnSkip;
111 u16 *dest = (u16 *)pix + yLine;
112 for (register int x = 0; x < 160; x++)
113 gbSgbDraw16Bit(dest++, color);
114 }
115 }
116 break;
117 case 24:
118 {
119 for (int y = 0; y < 144; y++)
120 {
121 int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip + gbBorderColumnSkip;
122 u8 *dest = (u8 *)pix + yLine * 3;
123 for (register int x = 0; x < 160; x++)
124 {
125 gbSgbDraw24Bit(dest, color);
126 dest += 3;
127 }
128 }
129 }
130 break;
131 case 32:
132 {
133 for (int y = 0; y < 144; y++)
134 {
135 int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 1) + gbBorderColumnSkip;
136 u32 *dest = (u32 *)pix + yLine;
137 for (register int x = 0; x < 160; x++)
138 {
139 gbSgbDraw32Bit(dest++, color);
140 }
141 }
142 }
143 break;
144 }
145 }
147 void gbSgbRenderScreenToBuffer()
148 {
149 u16 mapAddress = 0x9800;
151 if (register_LCDC & 0x08)
152 mapAddress = 0x9c00;
154 u16 patternAddress = 0x8800;
156 int flag = 1;
158 if (register_LCDC & 0x10)
159 {
160 patternAddress = 0x8000;
161 flag = 0;
162 }
164 u8 *toAddress = gbSgbScreenBuffer;
166 for (int i = 0; i < 13; i++)
167 {
168 for (int j = 0; j < 20; j++)
169 {
170 int tile = gbReadMemoryQuick(mapAddress);
171 mapAddress++;
173 if (flag)
174 {
175 if (tile > 127)
176 tile -= 128;
177 else
178 tile += 128;
179 }
180 for (int k = 0; k < 16; k++)
181 *toAddress++ = gbReadMemoryQuick(patternAddress + tile * 16 + k);
182 }
183 mapAddress += 12;
184 }
185 }
187 void gbSgbDrawBorderTile(int x, int y, int tile, int attr)
188 {
189 u16 *dest = (u16 *)pix + ((y + 1) * (256 + 2)) + x;
190 u8 * dest8 = (u8 *)pix + ((y * 256) + x) * 3;
191 u32 *dest32 = (u32 *)pix + ((y + 1) * 257) + x;
193 u8 *tileAddress = &gbSgbBorderChar[tile * 32];
194 u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16];
196 u8 l = 8;
198 u8 palette = ((attr >> 2) & 7);
200 if (palette < 4)
201 palette += 4;
203 palette *= 16;
205 u8 xx = 0;
206 u8 yy = 0;
208 int flipX = attr & 0x40;
209 int flipY = attr & 0x80;
211 while (l > 0)
212 {
213 u8 mask = 0x80;
214 u8 a = *tileAddress++;
215 u8 b = *tileAddress++;
216 u8 c = *tileAddress2++;
217 u8 d = *tileAddress2++;
219 while (mask > 0)
220 {
221 u8 color = 0;
222 if (a & mask)
223 color++;
224 if (b & mask)
225 color += 2;
226 if (c & mask)
227 color += 4;
228 if (d & mask)
229 color += 8;
231 u8 xxx = xx;
232 u8 yyy = yy;
234 if (flipX)
235 xxx = 7 - xx;
236 if (flipY)
237 yyy = 7 - yy;
239 u8 realx = x + xxx;
240 u8 realy = y + yyy;
242 u16 c = gbPalette[palette + color];
243 if (!color)
244 c = gbPalette[0];
245 if ((realy < 40 || realy >= 184) || (realx < 48 || realx >= 208))
246 {
247 switch (systemColorDepth)
248 {
249 case 16:
250 gbSgbDraw16Bit(dest + yyy * (256 + 2) + xxx, c);
251 break;
252 case 24:
253 gbSgbDraw24Bit(dest8 + (yyy * 256 + xxx) * 3, c);
254 break;
255 case 32:
256 gbSgbDraw32Bit(dest32 + yyy * (256 + 1) + xxx, c);
257 break;
258 }
259 }
261 mask >>= 1;
263 xx++;
264 }
265 yy++;
266 xx = 0;
267 l--;
268 mask = 0x80;
269 }
270 }
272 void gbSgbRenderBorder()
273 {
274 if (gbBorderOn)
275 {
276 u8 *fromAddress = gbSgbBorder;
278 for (u8 y = 0; y < 28; y++)
279 {
280 for (u8 x = 0; x < 32; x++)
281 {
282 u8 tile = *fromAddress++;
283 u8 attr = *fromAddress++;
285 gbSgbDrawBorderTile(x * 8, y * 8, tile, attr);
286 }
287 }
288 }
289 }
291 void gbSgbPicture()
292 {
293 gbSgbRenderScreenToBuffer();
295 memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048);
297 u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048];
299 for (int i = 64; i < 128; i++)
300 {
301 gbPalette[i] = READ16LE(paletteAddr++);
302 }
304 gbSgbCGBSupport |= 4;
306 if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4)
307 {
308 gbBorderOn = 1;
309 systemGbBorderOn();
310 }
312 if (gbBorderOn && !gbSgbMask)
313 gbSgbRenderBorder();
315 if (gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4)
316 {
317 gbSgbCGBSupport = 0;
318 gbSgbMode = 2;
319 gbSgbMask = 0;
320 gbSgbRenderBorder();
321 gbReset();
322 }
324 if (gbSgbCGBSupport > 4)
325 gbSgbCGBSupport = 0;
326 }
328 void gbSgbSetPalette(int a, int b, u16 *p)
329 {
330 u16 bit00 = READ16LE(p++);
331 int i;
333 for (i = 1; i < 4; i++)
334 {
335 gbPalette[a * 4 + i] = READ16LE(p++);
336 }
338 for (i = 1; i < 4; i++)
339 {
340 gbPalette[b * 4 + i] = READ16LE(p++);
341 }
343 gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00;
344 if (gbBorderOn && !gbSgbMask)
345 gbSgbRenderBorder();
346 }
348 void gbSgbScpPalette()
349 {
350 gbSgbRenderScreenToBuffer();
352 u16 *fromAddress = (u16 *)gbSgbScreenBuffer;
354 for (int i = 0; i < 512 * 4; i++)
355 {
356 gbSgbSCPPalette[i] = READ16LE(fromAddress++);
357 }
358 }
360 void gbSgbSetATF(int n)
361 {
362 if (n < 0)
363 n = 0;
364 if (n > 44)
365 n = 44;
366 memcpy(gbSgbATF, &gbSgbATFList[n * 20 * 18], 20 * 18);
368 if (gbSgbPacket[1] & 0x40)
369 {
370 gbSgbMask = 0;
371 if (gbBorderOn)
372 gbSgbRenderBorder();
373 }
374 }
376 void gbSgbSetPalette()
377 {
378 u16 pal = READ16LE((((u16 *)&gbSgbPacket[1]))) & 511;
379 memcpy(&gbPalette[0], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
381 pal = READ16LE((((u16 *)&gbSgbPacket[3]))) & 511;
382 memcpy(&gbPalette[4], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
384 pal = READ16LE((((u16 *)&gbSgbPacket[5]))) & 511;
385 memcpy(&gbPalette[8], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
387 pal = READ16LE((((u16 *)&gbSgbPacket[7]))) & 511;
388 memcpy(&gbPalette[12], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16));
390 u8 atf = gbSgbPacket[9];
392 if (atf & 0x80)
393 {
394 gbSgbSetATF(atf & 0x3f);
395 }
397 if (atf & 0x40)
398 {
399 gbSgbMask = 0;
400 if (gbBorderOn)
401 gbSgbRenderBorder();
402 }
403 }
405 void gbSgbAttributeBlock()
406 {
407 u8 *fromAddress = &gbSgbPacket[1];
409 u8 nDataSet = *fromAddress++;
410 if (nDataSet > 12)
411 nDataSet = 12;
412 if (nDataSet == 0)
413 nDataSet = 1;
415 while (nDataSet)
416 {
417 u8 controlCode = (*fromAddress++) & 7;
418 u8 paletteDesignation = (*fromAddress++) & 0x3f;
419 u8 startH = (*fromAddress++) & 0x1f;
420 u8 startV = (*fromAddress++) & 0x1f;
421 u8 endH = (*fromAddress++) & 0x1f;
422 u8 endV = (*fromAddress++) & 0x1f;
424 u8 *toAddress = gbSgbATF;
426 for (u8 y = 0; y < 18; y++)
427 {
428 for (u8 x = 0; x < 20; x++)
429 {
430 if (x < startH || y < startV ||
431 x > endH || y > endV)
432 {
433 // outside
434 if (controlCode & 0x04)
435 *toAddress = (paletteDesignation >> 4) & 0x03;
436 }
437 else if (x > startH && x < endH &&
438 y > startV && y < endV)
439 {
440 // inside
441 if (controlCode & 0x01)
442 *toAddress = paletteDesignation & 0x03;
443 }
444 else
445 {
446 // surrounding line
447 if (controlCode & 0x02)
448 *toAddress = (paletteDesignation >> 2) & 0x03;
449 else if (controlCode == 0x01)
450 *toAddress = paletteDesignation & 0x03;
451 }
452 toAddress++;
453 }
454 }
455 nDataSet--;
456 }
457 }
459 void gbSgbSetColumnPalette(u8 col, u8 p)
460 {
461 // if(col < 0)
462 // col = 0;
463 if (col > 19)
464 col = 19;
466 p &= 3;
468 u8 *toAddress = &gbSgbATF[col];
470 for (u8 y = 0; y < 18; y++)
471 {
472 *toAddress = p;
473 toAddress += 20;
474 }
475 }
477 void gbSgbSetRowPalette(u8 row, u8 p)
478 {
479 // if(row < 0)
480 // row = 0;
481 if (row > 17)
482 row = 17;
484 p &= 3;
486 u8 *toAddress = &gbSgbATF[row * 20];
488 for (u8 x = 0; x < 20; x++)
489 {
490 *toAddress++ = p;
491 }
492 }
494 void gbSgbAttributeDivide()
495 {
496 u8 control = gbSgbPacket[1];
497 u8 coord = gbSgbPacket[2];
498 u8 colorBR = control & 3;
499 u8 colorAL = (control >> 2) & 3;
500 u8 colorOL = (control >> 4) & 3;
502 if (control & 0x40)
503 {
504 if (coord > 17)
505 coord = 17;
507 for (u8 i = 0; i < 18; i++)
508 {
509 if (i < coord)
510 gbSgbSetRowPalette(i, colorAL);
511 else if (i > coord)
512 gbSgbSetRowPalette(i, colorBR);
513 else
514 gbSgbSetRowPalette(i, colorOL);
515 }
516 }
517 else
518 {
519 if (coord > 19)
520 coord = 19;
522 for (u8 i = 0; i < 20; i++)
523 {
524 if (i < coord)
525 gbSgbSetColumnPalette(i, colorAL);
526 else if (i > coord)
527 gbSgbSetColumnPalette(i, colorBR);
528 else
529 gbSgbSetColumnPalette(i, colorOL);
530 }
531 }
532 }
534 void gbSgbAttributeLine()
535 {
536 u8 *fromAddress = &gbSgbPacket[1];
538 u8 nDataSet = *fromAddress++;
540 if (nDataSet > 0x6e)
541 nDataSet = 0x6e;
543 while (nDataSet)
544 {
545 u8 line = *fromAddress++;
546 u8 num = line & 0x1f;
547 u8 pal = (line >> 5) & 0x03;
548 if (line & 0x80)
549 {
550 if (num > 17)
551 num = 17;
552 gbSgbSetRowPalette(num, pal);
553 }
554 else
555 {
556 if (num > 19)
557 num = 19;
558 gbSgbSetColumnPalette(num, pal);
559 }
560 nDataSet--;
561 }
562 }
564 void gbSgbAttributeCharacter()
565 {
566 u8 startH = gbSgbPacket[1] & 0x1f;
567 u8 startV = gbSgbPacket[2] & 0x1f;
568 int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3]));
569 int style = gbSgbPacket[5] & 1;
570 if (startH > 19)
571 startH = 19;
572 if (startV > 17)
573 startV = 17;
575 u8 s = 6;
576 u8 *fromAddress = &gbSgbPacket[6];
577 u8 v = *fromAddress++;
579 if (style)
580 {
581 while (nDataSet)
582 {
583 u8 p = (v >> s) & 3;
584 gbSgbATF[startV * 20 + startH] = p;
585 startV++;
586 if (startV == 18)
587 {
588 startV = 0;
589 startH++;
590 if (startH == 20)
591 break;
592 }
594 if (s)
595 s -= 2;
596 else
597 {
598 s = 6;
599 v = *fromAddress++;
600 nDataSet--;
601 }
602 }
603 }
604 else
605 {
606 while (nDataSet)
607 {
608 u8 p = (v >> s) & 3;
609 gbSgbATF[startV * 20 + startH] = p;
610 startH++;
611 if (startH == 20)
612 {
613 startH = 0;
614 startV++;
615 if (startV == 18)
616 break;
617 }
619 if (s)
620 s -= 2;
621 else
622 {
623 s = 6;
624 v = *fromAddress++;
625 nDataSet--;
626 }
627 }
628 }
629 }
631 void gbSgbSetATFList()
632 {
633 gbSgbRenderScreenToBuffer();
635 u8 *fromAddress = gbSgbScreenBuffer;
636 u8 *toAddress = gbSgbATFList;
638 for (int i = 0; i < 45; i++)
639 {
640 for (int j = 0; j < 90; j++)
641 {
642 u8 v = *fromAddress++;
643 u8 s = 6;
644 if (i == 2)
645 s = 6;
646 for (int k = 0; k < 4; k++)
647 {
648 *toAddress++ = (v >> s) & 0x03;
649 s -= 2;
650 }
651 }
652 }
653 }
655 void gbSgbMaskEnable()
656 {
657 int gbSgbMaskFlag = gbSgbPacket[1] & 3;
659 gbSgbMask = gbSgbMaskFlag;
661 switch (gbSgbMaskFlag)
662 {
663 case 1:
664 break;
665 case 2:
666 gbSgbFillScreen(0x0000);
667 // memset(&gbPalette[0], 0, 128*sizeof(u16));
668 break;
669 case 3:
670 gbSgbFillScreen(gbPalette[0]);
671 break;
672 }
673 if (!gbSgbMask)
674 {
675 if (gbBorderOn)
676 gbSgbRenderBorder();
677 }
678 }
680 void gbSgbChrTransfer()
681 {
682 gbSgbRenderScreenToBuffer();
684 int address = (gbSgbPacket[1] & 1) * (128 * 32);
686 if (gbSgbPacket[1] & 1)
687 gbSgbCGBSupport |= 2;
688 else
689 gbSgbCGBSupport |= 1;
691 memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32);
693 if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4)
694 {
695 gbBorderOn = 1;
696 systemGbBorderOn();
697 }
699 if (gbBorderOn && !gbSgbMask)
700 gbSgbRenderBorder();
702 if (gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7)
703 {
704 gbSgbCGBSupport = 0;
705 gbSgbMode = 2;
706 gbSgbMask = 0;
707 gbSgbRenderBorder();
708 gbReset();
709 }
711 if (gbSgbCGBSupport > 4)
712 gbSgbCGBSupport = 0;
713 }
715 void gbSgbMultiRequest()
716 {
717 if (gbSgbPacket[1] & 1)
718 {
719 gbSgbMultiplayer = 1;
720 if (gbSgbPacket[1] & 2)
721 gbSgbFourPlayers = 1;
722 else
723 gbSgbFourPlayers = 0;
724 gbSgbNextController = 0x0e;
725 }
726 else
727 {
728 gbSgbFourPlayers = 0;
729 gbSgbMultiplayer = 0;
730 gbSgbNextController = 0x0f;
731 }
732 }
734 void gbSgbCommand()
735 {
736 int command = gbSgbPacket[0] >> 3;
737 // int nPacket = gbSgbPacket[0] & 7;
739 switch (command)
740 {
741 case 0x00:
742 gbSgbSetPalette(0, 1, (u16 *)&gbSgbPacket[1]);
743 break;
744 case 0x01:
745 gbSgbSetPalette(2, 3, (u16 *)&gbSgbPacket[1]);
746 break;
747 case 0x02:
748 gbSgbSetPalette(0, 3, (u16 *)&gbSgbPacket[1]);
749 break;
750 case 0x03:
751 gbSgbSetPalette(1, 2, (u16 *)&gbSgbPacket[1]);
752 break;
753 case 0x04:
754 gbSgbAttributeBlock();
755 break;
756 case 0x05:
757 gbSgbAttributeLine();
758 break;
759 case 0x06:
760 gbSgbAttributeDivide();
761 break;
762 case 0x07:
763 gbSgbAttributeCharacter();
764 break;
765 case 0x0a:
766 gbSgbSetPalette();
767 break;
768 case 0x0b:
769 gbSgbScpPalette();
770 break;
771 case 0x11:
772 gbSgbMultiRequest();
773 break;
774 case 0x13:
775 gbSgbChrTransfer();
776 break;
777 case 0x14:
778 gbSgbPicture();
779 break;
780 case 0x15:
781 gbSgbSetATFList();
782 break;
783 case 0x16:
784 gbSgbSetATF(gbSgbPacket[1] & 0x3f);
785 break;
786 case 0x17:
787 gbSgbMaskEnable();
788 break;
789 }
790 }
792 void gbSgbResetPacketState()
793 {
794 gbSgbPacketState = GBSGB_NONE;
795 gbSgbPacketTimeout = 0;
796 }
798 void gbSgbDoBitTransfer(u8 value)
799 {
800 value = value & 0x30;
801 switch (gbSgbPacketState)
802 {
803 case GBSGB_NONE:
804 if (value == 0)
805 {
806 gbSgbPacketState = GBSGB_RESET;
807 gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
808 }
809 else if (value == 0x30)
810 {
811 if (gbSgbMultiplayer)
812 {
813 if ((gbSgbReadingController & 7) == 7)
814 {
815 gbSgbReadingController = 0;
816 if (gbSgbMultiplayer)
817 {
818 gbSgbNextController--;
819 if (gbSgbFourPlayers)
820 {
821 if (gbSgbNextController == 0x0b)
822 gbSgbNextController = 0x0f;
823 }
824 else
825 {
826 if (gbSgbNextController == 0x0d)
827 gbSgbNextController = 0x0f;
828 }
829 }
830 }
831 else
832 {
833 gbSgbReadingController &= 3;
834 }
835 }
836 gbSgbPacketTimeout = 0;
837 }
838 else
839 {
840 if (value == 0x10)
841 gbSgbReadingController |= 0x2;
842 else if (value == 0x20)
843 gbSgbReadingController |= 0x01;
844 gbSgbPacketTimeout = 0;
845 }
846 gbSgbPacketTimeout = 0;
847 break;
848 case GBSGB_RESET:
849 if (value == 0x30)
850 {
851 gbSgbPacketState = GBSGB_PACKET_TRANSMIT;
852 gbSgbPacketByte = 0;
853 gbSgbPacketNBits = 0;
854 gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
855 }
856 else if (value == 0x00)
857 {
858 gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
859 gbSgbPacketState = GBSGB_RESET;
860 }
861 else
862 {
863 gbSgbPacketState = GBSGB_NONE;
864 gbSgbPacketTimeout = 0;
865 }
866 break;
867 case GBSGB_PACKET_TRANSMIT:
868 if (value == 0)
869 {
870 gbSgbPacketState = GBSGB_RESET;
871 gbSgbPacketTimeout = 0;
872 }
873 else if (value == 0x30)
874 {
875 if (gbSgbPacketNBits == 128)
876 {
877 gbSgbPacketNBits = 0;
878 gbSgbPacketByte = 0;
879 gbSgbPacketNumber++;
880 gbSgbPacketTimeout = 0;
881 if (gbSgbPacketNumber == (gbSgbPacket[0] & 7))
882 {
883 gbSgbCommand();
884 gbSgbPacketNumber = 0;
885 gbSgbPacketState = GBSGB_NONE;
886 gbSgbPacketTimeout = 0;
887 }
888 }
889 else
890 {
891 if (gbSgbPacketNBits < 128)
892 {
893 gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1;
894 gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit;
895 gbSgbPacketNBits++;
896 if (!(gbSgbPacketNBits & 7))
897 {
898 gbSgbPacketByte++;
899 }
900 gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
901 }
902 }
903 }
904 else
905 {
906 if (value == 0x20)
907 gbSgbBit = 0x00;
908 else
909 gbSgbBit = 0x80;
910 gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT;
911 }
912 gbSgbReadingController = 0;
913 break;
914 default:
915 gbSgbPacketState = GBSGB_NONE;
916 gbSgbPacketTimeout = 0;
917 break;
918 }
919 }
921 variable_desc gbSgbSaveStruct[] = {
922 { &gbSgbMask, sizeof(int32) },
923 { &gbSgbPacketState, sizeof(int32) },
924 { &gbSgbBit, sizeof(int32) },
925 { &gbSgbPacketNBits, sizeof(int32) },
926 { &gbSgbPacketByte, sizeof(int32) },
927 { &gbSgbPacketNumber, sizeof(int32) },
928 { &gbSgbMultiplayer, sizeof(int32) },
929 { &gbSgbNextController, sizeof(u8) },
930 { &gbSgbReadingController, sizeof(u8) },
931 { NULL, 0 }
932 };
934 variable_desc gbSgbSaveStructV3[] = {
935 { &gbSgbMask, sizeof(int32) },
936 { &gbSgbPacketState, sizeof(int32) },
937 { &gbSgbBit, sizeof(int32) },
938 { &gbSgbPacketNBits, sizeof(int32) },
939 { &gbSgbPacketByte, sizeof(int32) },
940 { &gbSgbPacketNumber, sizeof(int32) },
941 { &gbSgbMultiplayer, sizeof(int32) },
942 { &gbSgbNextController, sizeof(u8) },
943 { &gbSgbReadingController, sizeof(u8) },
944 { &gbSgbFourPlayers, sizeof(int32) },
945 { NULL, 0 }
946 };
948 void gbSgbSaveGame(gzFile gzFile)
949 {
950 utilWriteData(gzFile, gbSgbSaveStructV3);
952 utilGzWrite(gzFile, gbSgbBorder, 2048);
953 utilGzWrite(gzFile, gbSgbBorderChar, 32 * 256);
955 utilGzWrite(gzFile, gbSgbPacket, 16 * 7);
957 utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
958 utilGzWrite(gzFile, gbSgbATF, 20 * 18);
959 utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18);
961 utilGzWrite(gzFile, gbSgbScreenBuffer, 4160);
962 utilGzWrite(gzFile, &gbSgbMode, sizeof(gbSgbMode));
963 utilGzWrite(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport));
964 utilGzWrite(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout));
965 }
967 void gbSgbReadGame(gzFile gzFile, int version)
968 {
969 if (version >= 3)
970 utilReadData(gzFile, gbSgbSaveStructV3);
971 else
972 {
973 utilReadData(gzFile, gbSgbSaveStruct);
974 gbSgbFourPlayers = 0;
975 }
977 if (version >= 8)
978 {
979 utilGzRead(gzFile, gbSgbBorder, 2048);
980 utilGzRead(gzFile, gbSgbBorderChar, 32 * 256);
981 }
983 utilGzRead(gzFile, gbSgbPacket, 16 * 7);
985 utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16));
986 utilGzRead(gzFile, gbSgbATF, 20 * 18);
987 utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18);
989 if (version >= 11)
990 {
991 utilGzRead(gzFile, gbSgbScreenBuffer, 4160);
992 utilGzRead(gzFile, &gbSgbMode, sizeof(gbSgbMode));
993 utilGzRead(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport));
994 utilGzRead(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout));
995 }
996 }