Mercurial > vba-clojure
comparison src/gb/gbSGB.cpp @ 17:75e5bb1e0aa1
going to now integrate the gb src tree since it has no dependencies
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Sat, 03 Mar 2012 11:44:47 -0600 |
parents | f9f4f1b99eed |
children |
comparison
equal
deleted
inserted
replaced
16:9e598342e182 | 17:75e5bb1e0aa1 |
---|---|
1 #include <cstdlib> | |
2 #include <cstring> | |
3 | |
4 #include "../common/System.h" | |
5 #include "../common/Util.h" | |
6 #include "GB.h" | |
7 #include "gbGlobals.h" | |
8 #include "../common/movie.h" | |
9 | |
10 extern u8 * pix; | |
11 | |
12 #define GBSGB_NONE 0 | |
13 #define GBSGB_RESET 1 | |
14 #define GBSGB_PACKET_TRANSMIT 2 | |
15 | |
16 u8 gbSgbBorderChar [32 * 256]; | |
17 u8 gbSgbBorder [2048]; | |
18 | |
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]; | |
38 | |
39 inline void gbSgbDraw24Bit(u8 *p, u16 v) | |
40 { | |
41 *((u32 *) p) = systemColorMap32[v]; | |
42 } | |
43 | |
44 inline void gbSgbDraw32Bit(u32 *p, u16 v) | |
45 { | |
46 *p = systemColorMap32[v]; | |
47 } | |
48 | |
49 inline void gbSgbDraw16Bit(u16 *p, u16 v) | |
50 { | |
51 *p = systemColorMap16[v]; | |
52 } | |
53 | |
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; | |
67 | |
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); | |
74 | |
75 int i; | |
76 for (i = 1; i < 2048; i += 2) | |
77 { | |
78 gbSgbBorder[i] = 1 << 2; | |
79 } | |
80 | |
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 } | |
89 | |
90 void gbSgbInit() | |
91 { | |
92 gbSgbReset(); | |
93 } | |
94 | |
95 void gbSgbShutdown() | |
96 { | |
97 memset(gbSgbBorderChar, 0, 32 * 256); | |
98 memset(gbSgbBorder, 0, 2048); | |
99 } | |
100 | |
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 } | |
146 | |
147 void gbSgbRenderScreenToBuffer() | |
148 { | |
149 u16 mapAddress = 0x9800; | |
150 | |
151 if (register_LCDC & 0x08) | |
152 mapAddress = 0x9c00; | |
153 | |
154 u16 patternAddress = 0x8800; | |
155 | |
156 int flag = 1; | |
157 | |
158 if (register_LCDC & 0x10) | |
159 { | |
160 patternAddress = 0x8000; | |
161 flag = 0; | |
162 } | |
163 | |
164 u8 *toAddress = gbSgbScreenBuffer; | |
165 | |
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++; | |
172 | |
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 } | |
186 | |
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; | |
192 | |
193 u8 *tileAddress = &gbSgbBorderChar[tile * 32]; | |
194 u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16]; | |
195 | |
196 u8 l = 8; | |
197 | |
198 u8 palette = ((attr >> 2) & 7); | |
199 | |
200 if (palette < 4) | |
201 palette += 4; | |
202 | |
203 palette *= 16; | |
204 | |
205 u8 xx = 0; | |
206 u8 yy = 0; | |
207 | |
208 int flipX = attr & 0x40; | |
209 int flipY = attr & 0x80; | |
210 | |
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++; | |
218 | |
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; | |
230 | |
231 u8 xxx = xx; | |
232 u8 yyy = yy; | |
233 | |
234 if (flipX) | |
235 xxx = 7 - xx; | |
236 if (flipY) | |
237 yyy = 7 - yy; | |
238 | |
239 u8 realx = x + xxx; | |
240 u8 realy = y + yyy; | |
241 | |
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 } | |
260 | |
261 mask >>= 1; | |
262 | |
263 xx++; | |
264 } | |
265 yy++; | |
266 xx = 0; | |
267 l--; | |
268 mask = 0x80; | |
269 } | |
270 } | |
271 | |
272 void gbSgbRenderBorder() | |
273 { | |
274 if (gbBorderOn) | |
275 { | |
276 u8 *fromAddress = gbSgbBorder; | |
277 | |
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++; | |
284 | |
285 gbSgbDrawBorderTile(x * 8, y * 8, tile, attr); | |
286 } | |
287 } | |
288 } | |
289 } | |
290 | |
291 void gbSgbPicture() | |
292 { | |
293 gbSgbRenderScreenToBuffer(); | |
294 | |
295 memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048); | |
296 | |
297 u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048]; | |
298 | |
299 for (int i = 64; i < 128; i++) | |
300 { | |
301 gbPalette[i] = READ16LE(paletteAddr++); | |
302 } | |
303 | |
304 gbSgbCGBSupport |= 4; | |
305 | |
306 if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) | |
307 { | |
308 gbBorderOn = 1; | |
309 systemGbBorderOn(); | |
310 } | |
311 | |
312 if (gbBorderOn && !gbSgbMask) | |
313 gbSgbRenderBorder(); | |
314 | |
315 if (gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) | |
316 { | |
317 gbSgbCGBSupport = 0; | |
318 gbSgbMode = 2; | |
319 gbSgbMask = 0; | |
320 gbSgbRenderBorder(); | |
321 gbReset(); | |
322 } | |
323 | |
324 if (gbSgbCGBSupport > 4) | |
325 gbSgbCGBSupport = 0; | |
326 } | |
327 | |
328 void gbSgbSetPalette(int a, int b, u16 *p) | |
329 { | |
330 u16 bit00 = READ16LE(p++); | |
331 int i; | |
332 | |
333 for (i = 1; i < 4; i++) | |
334 { | |
335 gbPalette[a * 4 + i] = READ16LE(p++); | |
336 } | |
337 | |
338 for (i = 1; i < 4; i++) | |
339 { | |
340 gbPalette[b * 4 + i] = READ16LE(p++); | |
341 } | |
342 | |
343 gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00; | |
344 if (gbBorderOn && !gbSgbMask) | |
345 gbSgbRenderBorder(); | |
346 } | |
347 | |
348 void gbSgbScpPalette() | |
349 { | |
350 gbSgbRenderScreenToBuffer(); | |
351 | |
352 u16 *fromAddress = (u16 *)gbSgbScreenBuffer; | |
353 | |
354 for (int i = 0; i < 512 * 4; i++) | |
355 { | |
356 gbSgbSCPPalette[i] = READ16LE(fromAddress++); | |
357 } | |
358 } | |
359 | |
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); | |
367 | |
368 if (gbSgbPacket[1] & 0x40) | |
369 { | |
370 gbSgbMask = 0; | |
371 if (gbBorderOn) | |
372 gbSgbRenderBorder(); | |
373 } | |
374 } | |
375 | |
376 void gbSgbSetPalette() | |
377 { | |
378 u16 pal = READ16LE((((u16 *)&gbSgbPacket[1]))) & 511; | |
379 memcpy(&gbPalette[0], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); | |
380 | |
381 pal = READ16LE((((u16 *)&gbSgbPacket[3]))) & 511; | |
382 memcpy(&gbPalette[4], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); | |
383 | |
384 pal = READ16LE((((u16 *)&gbSgbPacket[5]))) & 511; | |
385 memcpy(&gbPalette[8], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); | |
386 | |
387 pal = READ16LE((((u16 *)&gbSgbPacket[7]))) & 511; | |
388 memcpy(&gbPalette[12], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); | |
389 | |
390 u8 atf = gbSgbPacket[9]; | |
391 | |
392 if (atf & 0x80) | |
393 { | |
394 gbSgbSetATF(atf & 0x3f); | |
395 } | |
396 | |
397 if (atf & 0x40) | |
398 { | |
399 gbSgbMask = 0; | |
400 if (gbBorderOn) | |
401 gbSgbRenderBorder(); | |
402 } | |
403 } | |
404 | |
405 void gbSgbAttributeBlock() | |
406 { | |
407 u8 *fromAddress = &gbSgbPacket[1]; | |
408 | |
409 u8 nDataSet = *fromAddress++; | |
410 if (nDataSet > 12) | |
411 nDataSet = 12; | |
412 if (nDataSet == 0) | |
413 nDataSet = 1; | |
414 | |
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; | |
423 | |
424 u8 *toAddress = gbSgbATF; | |
425 | |
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 } | |
458 | |
459 void gbSgbSetColumnPalette(u8 col, u8 p) | |
460 { | |
461 // if(col < 0) | |
462 // col = 0; | |
463 if (col > 19) | |
464 col = 19; | |
465 | |
466 p &= 3; | |
467 | |
468 u8 *toAddress = &gbSgbATF[col]; | |
469 | |
470 for (u8 y = 0; y < 18; y++) | |
471 { | |
472 *toAddress = p; | |
473 toAddress += 20; | |
474 } | |
475 } | |
476 | |
477 void gbSgbSetRowPalette(u8 row, u8 p) | |
478 { | |
479 // if(row < 0) | |
480 // row = 0; | |
481 if (row > 17) | |
482 row = 17; | |
483 | |
484 p &= 3; | |
485 | |
486 u8 *toAddress = &gbSgbATF[row * 20]; | |
487 | |
488 for (u8 x = 0; x < 20; x++) | |
489 { | |
490 *toAddress++ = p; | |
491 } | |
492 } | |
493 | |
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; | |
501 | |
502 if (control & 0x40) | |
503 { | |
504 if (coord > 17) | |
505 coord = 17; | |
506 | |
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; | |
521 | |
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 } | |
533 | |
534 void gbSgbAttributeLine() | |
535 { | |
536 u8 *fromAddress = &gbSgbPacket[1]; | |
537 | |
538 u8 nDataSet = *fromAddress++; | |
539 | |
540 if (nDataSet > 0x6e) | |
541 nDataSet = 0x6e; | |
542 | |
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 } | |
563 | |
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; | |
574 | |
575 u8 s = 6; | |
576 u8 *fromAddress = &gbSgbPacket[6]; | |
577 u8 v = *fromAddress++; | |
578 | |
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 } | |
593 | |
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 } | |
618 | |
619 if (s) | |
620 s -= 2; | |
621 else | |
622 { | |
623 s = 6; | |
624 v = *fromAddress++; | |
625 nDataSet--; | |
626 } | |
627 } | |
628 } | |
629 } | |
630 | |
631 void gbSgbSetATFList() | |
632 { | |
633 gbSgbRenderScreenToBuffer(); | |
634 | |
635 u8 *fromAddress = gbSgbScreenBuffer; | |
636 u8 *toAddress = gbSgbATFList; | |
637 | |
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 } | |
654 | |
655 void gbSgbMaskEnable() | |
656 { | |
657 int gbSgbMaskFlag = gbSgbPacket[1] & 3; | |
658 | |
659 gbSgbMask = gbSgbMaskFlag; | |
660 | |
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 } | |
679 | |
680 void gbSgbChrTransfer() | |
681 { | |
682 gbSgbRenderScreenToBuffer(); | |
683 | |
684 int address = (gbSgbPacket[1] & 1) * (128 * 32); | |
685 | |
686 if (gbSgbPacket[1] & 1) | |
687 gbSgbCGBSupport |= 2; | |
688 else | |
689 gbSgbCGBSupport |= 1; | |
690 | |
691 memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32); | |
692 | |
693 if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) | |
694 { | |
695 gbBorderOn = 1; | |
696 systemGbBorderOn(); | |
697 } | |
698 | |
699 if (gbBorderOn && !gbSgbMask) | |
700 gbSgbRenderBorder(); | |
701 | |
702 if (gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) | |
703 { | |
704 gbSgbCGBSupport = 0; | |
705 gbSgbMode = 2; | |
706 gbSgbMask = 0; | |
707 gbSgbRenderBorder(); | |
708 gbReset(); | |
709 } | |
710 | |
711 if (gbSgbCGBSupport > 4) | |
712 gbSgbCGBSupport = 0; | |
713 } | |
714 | |
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 } | |
733 | |
734 void gbSgbCommand() | |
735 { | |
736 int command = gbSgbPacket[0] >> 3; | |
737 // int nPacket = gbSgbPacket[0] & 7; | |
738 | |
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 } | |
791 | |
792 void gbSgbResetPacketState() | |
793 { | |
794 gbSgbPacketState = GBSGB_NONE; | |
795 gbSgbPacketTimeout = 0; | |
796 } | |
797 | |
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 } | |
920 | |
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 }; | |
933 | |
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 }; | |
947 | |
948 void gbSgbSaveGame(gzFile gzFile) | |
949 { | |
950 utilWriteData(gzFile, gbSgbSaveStructV3); | |
951 | |
952 utilGzWrite(gzFile, gbSgbBorder, 2048); | |
953 utilGzWrite(gzFile, gbSgbBorderChar, 32 * 256); | |
954 | |
955 utilGzWrite(gzFile, gbSgbPacket, 16 * 7); | |
956 | |
957 utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); | |
958 utilGzWrite(gzFile, gbSgbATF, 20 * 18); | |
959 utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18); | |
960 | |
961 utilGzWrite(gzFile, gbSgbScreenBuffer, 4160); | |
962 utilGzWrite(gzFile, &gbSgbMode, sizeof(gbSgbMode)); | |
963 utilGzWrite(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport)); | |
964 utilGzWrite(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout)); | |
965 } | |
966 | |
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 } | |
976 | |
977 if (version >= 8) | |
978 { | |
979 utilGzRead(gzFile, gbSgbBorder, 2048); | |
980 utilGzRead(gzFile, gbSgbBorderChar, 32 * 256); | |
981 } | |
982 | |
983 utilGzRead(gzFile, gbSgbPacket, 16 * 7); | |
984 | |
985 utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); | |
986 utilGzRead(gzFile, gbSgbATF, 20 * 18); | |
987 utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18); | |
988 | |
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 } | |
997 |