annotate src/gb/gbSGB.cpp @ 486:3f0156038802

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