rlm@1: #include rlm@1: #include rlm@1: rlm@1: #include "../common/System.h" rlm@1: #include "../common/Util.h" rlm@1: #include "GB.h" rlm@1: #include "gbGlobals.h" rlm@1: #include "../common/movie.h" rlm@1: rlm@1: extern u8 * pix; rlm@1: rlm@1: #define GBSGB_NONE 0 rlm@1: #define GBSGB_RESET 1 rlm@1: #define GBSGB_PACKET_TRANSMIT 2 rlm@1: rlm@1: u8 gbSgbBorderChar [32 * 256]; rlm@1: u8 gbSgbBorder [2048]; rlm@1: rlm@1: int32 gbSgbCGBSupport = 0; rlm@1: int32 gbSgbMask = 0; rlm@1: int32 gbSgbMode = 0; rlm@1: int32 gbSgbPacketState = GBSGB_NONE; rlm@1: int32 gbSgbBit = 0; rlm@1: int32 gbSgbPacketTimeout = 0; rlm@1: int32 GBSGB_PACKET_TIMEOUT = 66666; rlm@1: u8 gbSgbPacket[16 * 7]; rlm@1: int32 gbSgbPacketNBits = 0; rlm@1: int32 gbSgbPacketByte = 0; rlm@1: int32 gbSgbPacketNumber = 0; rlm@1: int32 gbSgbMultiplayer = 0; rlm@1: int32 gbSgbFourPlayers = 0; rlm@1: u8 gbSgbNextController = 0x0f; rlm@1: u8 gbSgbReadingController = 0; rlm@1: u16 gbSgbSCPPalette[4 * 512]; rlm@1: u8 gbSgbATF[20 * 18]; rlm@1: u8 gbSgbATFList[45 * 20 * 18]; rlm@1: u8 gbSgbScreenBuffer[4160]; rlm@1: rlm@1: inline void gbSgbDraw24Bit(u8 *p, u16 v) rlm@1: { rlm@1: *((u32 *) p) = systemColorMap32[v]; rlm@1: } rlm@1: rlm@1: inline void gbSgbDraw32Bit(u32 *p, u16 v) rlm@1: { rlm@1: *p = systemColorMap32[v]; rlm@1: } rlm@1: rlm@1: inline void gbSgbDraw16Bit(u16 *p, u16 v) rlm@1: { rlm@1: *p = systemColorMap16[v]; rlm@1: } rlm@1: rlm@1: void gbSgbReset() rlm@1: { rlm@1: gbSgbPacketTimeout = 0; rlm@1: gbSgbCGBSupport = 0; rlm@1: gbSgbMask = 0; rlm@1: gbSgbPacketState = GBSGB_NONE; rlm@1: gbSgbBit = 0; rlm@1: gbSgbPacketNBits = 0; rlm@1: gbSgbPacketNumber = 0; rlm@1: gbSgbMultiplayer = 0; rlm@1: gbSgbFourPlayers = 0; rlm@1: gbSgbNextController = 0x0f; rlm@1: gbSgbReadingController = 0; rlm@1: rlm@1: memset(gbSgbSCPPalette, 0, 512 * 4); rlm@1: memset(gbSgbATF, 0, 20 * 18); rlm@1: memset(gbSgbATFList, 0, 45 * 20 * 18); rlm@1: memset(gbSgbPacket, 0, 16 * 7); rlm@1: memset(gbSgbBorderChar, 0, 32 * 256); rlm@1: memset(gbSgbBorder, 0, 2048); rlm@1: rlm@1: int i; rlm@1: for (i = 1; i < 2048; i += 2) rlm@1: { rlm@1: gbSgbBorder[i] = 1 << 2; rlm@1: } rlm@1: rlm@1: for (i = 0; i < 4; i++) rlm@1: { rlm@1: gbPalette[i * 4] = (0x1f) | (0x1f << 5) | (0x1f << 10); rlm@1: gbPalette[i * 4 + 1] = (0x15) | (0x15 << 5) | (0x15 << 10); rlm@1: gbPalette[i * 4 + 2] = (0x0c) | (0x0c << 5) | (0x0c << 10); rlm@1: gbPalette[i * 4 + 3] = 0; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbInit() rlm@1: { rlm@1: gbSgbReset(); rlm@1: } rlm@1: rlm@1: void gbSgbShutdown() rlm@1: { rlm@1: memset(gbSgbBorderChar, 0, 32 * 256); rlm@1: memset(gbSgbBorder, 0, 2048); rlm@1: } rlm@1: rlm@1: void gbSgbFillScreen(u16 color) rlm@1: { rlm@1: switch (systemColorDepth) rlm@1: { rlm@1: case 16: rlm@1: { rlm@1: for (int y = 0; y < 144; y++) rlm@1: { rlm@1: int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 2) + rlm@1: gbBorderColumnSkip; rlm@1: u16 *dest = (u16 *)pix + yLine; rlm@1: for (register int x = 0; x < 160; x++) rlm@1: gbSgbDraw16Bit(dest++, color); rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 24: rlm@1: { rlm@1: for (int y = 0; y < 144; y++) rlm@1: { rlm@1: int yLine = (y + gbBorderRowSkip) * gbBorderLineSkip + gbBorderColumnSkip; rlm@1: u8 *dest = (u8 *)pix + yLine * 3; rlm@1: for (register int x = 0; x < 160; x++) rlm@1: { rlm@1: gbSgbDraw24Bit(dest, color); rlm@1: dest += 3; rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: case 32: rlm@1: { rlm@1: for (int y = 0; y < 144; y++) rlm@1: { rlm@1: int yLine = (y + gbBorderRowSkip + 1) * (gbBorderLineSkip + 1) + gbBorderColumnSkip; rlm@1: u32 *dest = (u32 *)pix + yLine; rlm@1: for (register int x = 0; x < 160; x++) rlm@1: { rlm@1: gbSgbDraw32Bit(dest++, color); rlm@1: } rlm@1: } rlm@1: } rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbRenderScreenToBuffer() rlm@1: { rlm@1: u16 mapAddress = 0x9800; rlm@1: rlm@1: if (register_LCDC & 0x08) rlm@1: mapAddress = 0x9c00; rlm@1: rlm@1: u16 patternAddress = 0x8800; rlm@1: rlm@1: int flag = 1; rlm@1: rlm@1: if (register_LCDC & 0x10) rlm@1: { rlm@1: patternAddress = 0x8000; rlm@1: flag = 0; rlm@1: } rlm@1: rlm@1: u8 *toAddress = gbSgbScreenBuffer; rlm@1: rlm@1: for (int i = 0; i < 13; i++) rlm@1: { rlm@1: for (int j = 0; j < 20; j++) rlm@1: { rlm@1: int tile = gbReadMemoryQuick(mapAddress); rlm@1: mapAddress++; rlm@1: rlm@1: if (flag) rlm@1: { rlm@1: if (tile > 127) rlm@1: tile -= 128; rlm@1: else rlm@1: tile += 128; rlm@1: } rlm@1: for (int k = 0; k < 16; k++) rlm@1: *toAddress++ = gbReadMemoryQuick(patternAddress + tile * 16 + k); rlm@1: } rlm@1: mapAddress += 12; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbDrawBorderTile(int x, int y, int tile, int attr) rlm@1: { rlm@1: u16 *dest = (u16 *)pix + ((y + 1) * (256 + 2)) + x; rlm@1: u8 * dest8 = (u8 *)pix + ((y * 256) + x) * 3; rlm@1: u32 *dest32 = (u32 *)pix + ((y + 1) * 257) + x; rlm@1: rlm@1: u8 *tileAddress = &gbSgbBorderChar[tile * 32]; rlm@1: u8 *tileAddress2 = &gbSgbBorderChar[tile * 32 + 16]; rlm@1: rlm@1: u8 l = 8; rlm@1: rlm@1: u8 palette = ((attr >> 2) & 7); rlm@1: rlm@1: if (palette < 4) rlm@1: palette += 4; rlm@1: rlm@1: palette *= 16; rlm@1: rlm@1: u8 xx = 0; rlm@1: u8 yy = 0; rlm@1: rlm@1: int flipX = attr & 0x40; rlm@1: int flipY = attr & 0x80; rlm@1: rlm@1: while (l > 0) rlm@1: { rlm@1: u8 mask = 0x80; rlm@1: u8 a = *tileAddress++; rlm@1: u8 b = *tileAddress++; rlm@1: u8 c = *tileAddress2++; rlm@1: u8 d = *tileAddress2++; rlm@1: rlm@1: while (mask > 0) rlm@1: { rlm@1: u8 color = 0; rlm@1: if (a & mask) rlm@1: color++; rlm@1: if (b & mask) rlm@1: color += 2; rlm@1: if (c & mask) rlm@1: color += 4; rlm@1: if (d & mask) rlm@1: color += 8; rlm@1: rlm@1: u8 xxx = xx; rlm@1: u8 yyy = yy; rlm@1: rlm@1: if (flipX) rlm@1: xxx = 7 - xx; rlm@1: if (flipY) rlm@1: yyy = 7 - yy; rlm@1: rlm@1: u8 realx = x + xxx; rlm@1: u8 realy = y + yyy; rlm@1: rlm@1: u16 c = gbPalette[palette + color]; rlm@1: if (!color) rlm@1: c = gbPalette[0]; rlm@1: if ((realy < 40 || realy >= 184) || (realx < 48 || realx >= 208)) rlm@1: { rlm@1: switch (systemColorDepth) rlm@1: { rlm@1: case 16: rlm@1: gbSgbDraw16Bit(dest + yyy * (256 + 2) + xxx, c); rlm@1: break; rlm@1: case 24: rlm@1: gbSgbDraw24Bit(dest8 + (yyy * 256 + xxx) * 3, c); rlm@1: break; rlm@1: case 32: rlm@1: gbSgbDraw32Bit(dest32 + yyy * (256 + 1) + xxx, c); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: mask >>= 1; rlm@1: rlm@1: xx++; rlm@1: } rlm@1: yy++; rlm@1: xx = 0; rlm@1: l--; rlm@1: mask = 0x80; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbRenderBorder() rlm@1: { rlm@1: if (gbBorderOn) rlm@1: { rlm@1: u8 *fromAddress = gbSgbBorder; rlm@1: rlm@1: for (u8 y = 0; y < 28; y++) rlm@1: { rlm@1: for (u8 x = 0; x < 32; x++) rlm@1: { rlm@1: u8 tile = *fromAddress++; rlm@1: u8 attr = *fromAddress++; rlm@1: rlm@1: gbSgbDrawBorderTile(x * 8, y * 8, tile, attr); rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbPicture() rlm@1: { rlm@1: gbSgbRenderScreenToBuffer(); rlm@1: rlm@1: memcpy(gbSgbBorder, gbSgbScreenBuffer, 2048); rlm@1: rlm@1: u16 *paletteAddr = (u16 *)&gbSgbScreenBuffer[2048]; rlm@1: rlm@1: for (int i = 64; i < 128; i++) rlm@1: { rlm@1: gbPalette[i] = READ16LE(paletteAddr++); rlm@1: } rlm@1: rlm@1: gbSgbCGBSupport |= 4; rlm@1: rlm@1: if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) rlm@1: { rlm@1: gbBorderOn = 1; rlm@1: systemGbBorderOn(); rlm@1: } rlm@1: rlm@1: if (gbBorderOn && !gbSgbMask) rlm@1: gbSgbRenderBorder(); rlm@1: rlm@1: if (gbSgbMode && gbCgbMode && gbSgbCGBSupport > 4) rlm@1: { rlm@1: gbSgbCGBSupport = 0; rlm@1: gbSgbMode = 2; rlm@1: gbSgbMask = 0; rlm@1: gbSgbRenderBorder(); rlm@1: gbReset(); rlm@1: } rlm@1: rlm@1: if (gbSgbCGBSupport > 4) rlm@1: gbSgbCGBSupport = 0; rlm@1: } rlm@1: rlm@1: void gbSgbSetPalette(int a, int b, u16 *p) rlm@1: { rlm@1: u16 bit00 = READ16LE(p++); rlm@1: int i; rlm@1: rlm@1: for (i = 1; i < 4; i++) rlm@1: { rlm@1: gbPalette[a * 4 + i] = READ16LE(p++); rlm@1: } rlm@1: rlm@1: for (i = 1; i < 4; i++) rlm@1: { rlm@1: gbPalette[b * 4 + i] = READ16LE(p++); rlm@1: } rlm@1: rlm@1: gbPalette[0] = gbPalette[4] = gbPalette[8] = gbPalette[12] = bit00; rlm@1: if (gbBorderOn && !gbSgbMask) rlm@1: gbSgbRenderBorder(); rlm@1: } rlm@1: rlm@1: void gbSgbScpPalette() rlm@1: { rlm@1: gbSgbRenderScreenToBuffer(); rlm@1: rlm@1: u16 *fromAddress = (u16 *)gbSgbScreenBuffer; rlm@1: rlm@1: for (int i = 0; i < 512 * 4; i++) rlm@1: { rlm@1: gbSgbSCPPalette[i] = READ16LE(fromAddress++); rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbSetATF(int n) rlm@1: { rlm@1: if (n < 0) rlm@1: n = 0; rlm@1: if (n > 44) rlm@1: n = 44; rlm@1: memcpy(gbSgbATF, &gbSgbATFList[n * 20 * 18], 20 * 18); rlm@1: rlm@1: if (gbSgbPacket[1] & 0x40) rlm@1: { rlm@1: gbSgbMask = 0; rlm@1: if (gbBorderOn) rlm@1: gbSgbRenderBorder(); rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbSetPalette() rlm@1: { rlm@1: u16 pal = READ16LE((((u16 *)&gbSgbPacket[1]))) & 511; rlm@1: memcpy(&gbPalette[0], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); rlm@1: rlm@1: pal = READ16LE((((u16 *)&gbSgbPacket[3]))) & 511; rlm@1: memcpy(&gbPalette[4], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); rlm@1: rlm@1: pal = READ16LE((((u16 *)&gbSgbPacket[5]))) & 511; rlm@1: memcpy(&gbPalette[8], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); rlm@1: rlm@1: pal = READ16LE((((u16 *)&gbSgbPacket[7]))) & 511; rlm@1: memcpy(&gbPalette[12], &gbSgbSCPPalette[pal * 4], 4 * sizeof(u16)); rlm@1: rlm@1: u8 atf = gbSgbPacket[9]; rlm@1: rlm@1: if (atf & 0x80) rlm@1: { rlm@1: gbSgbSetATF(atf & 0x3f); rlm@1: } rlm@1: rlm@1: if (atf & 0x40) rlm@1: { rlm@1: gbSgbMask = 0; rlm@1: if (gbBorderOn) rlm@1: gbSgbRenderBorder(); rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbAttributeBlock() rlm@1: { rlm@1: u8 *fromAddress = &gbSgbPacket[1]; rlm@1: rlm@1: u8 nDataSet = *fromAddress++; rlm@1: if (nDataSet > 12) rlm@1: nDataSet = 12; rlm@1: if (nDataSet == 0) rlm@1: nDataSet = 1; rlm@1: rlm@1: while (nDataSet) rlm@1: { rlm@1: u8 controlCode = (*fromAddress++) & 7; rlm@1: u8 paletteDesignation = (*fromAddress++) & 0x3f; rlm@1: u8 startH = (*fromAddress++) & 0x1f; rlm@1: u8 startV = (*fromAddress++) & 0x1f; rlm@1: u8 endH = (*fromAddress++) & 0x1f; rlm@1: u8 endV = (*fromAddress++) & 0x1f; rlm@1: rlm@1: u8 *toAddress = gbSgbATF; rlm@1: rlm@1: for (u8 y = 0; y < 18; y++) rlm@1: { rlm@1: for (u8 x = 0; x < 20; x++) rlm@1: { rlm@1: if (x < startH || y < startV || rlm@1: x > endH || y > endV) rlm@1: { rlm@1: // outside rlm@1: if (controlCode & 0x04) rlm@1: *toAddress = (paletteDesignation >> 4) & 0x03; rlm@1: } rlm@1: else if (x > startH && x < endH && rlm@1: y > startV && y < endV) rlm@1: { rlm@1: // inside rlm@1: if (controlCode & 0x01) rlm@1: *toAddress = paletteDesignation & 0x03; rlm@1: } rlm@1: else rlm@1: { rlm@1: // surrounding line rlm@1: if (controlCode & 0x02) rlm@1: *toAddress = (paletteDesignation >> 2) & 0x03; rlm@1: else if (controlCode == 0x01) rlm@1: *toAddress = paletteDesignation & 0x03; rlm@1: } rlm@1: toAddress++; rlm@1: } rlm@1: } rlm@1: nDataSet--; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbSetColumnPalette(u8 col, u8 p) rlm@1: { rlm@1: // if(col < 0) rlm@1: // col = 0; rlm@1: if (col > 19) rlm@1: col = 19; rlm@1: rlm@1: p &= 3; rlm@1: rlm@1: u8 *toAddress = &gbSgbATF[col]; rlm@1: rlm@1: for (u8 y = 0; y < 18; y++) rlm@1: { rlm@1: *toAddress = p; rlm@1: toAddress += 20; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbSetRowPalette(u8 row, u8 p) rlm@1: { rlm@1: // if(row < 0) rlm@1: // row = 0; rlm@1: if (row > 17) rlm@1: row = 17; rlm@1: rlm@1: p &= 3; rlm@1: rlm@1: u8 *toAddress = &gbSgbATF[row * 20]; rlm@1: rlm@1: for (u8 x = 0; x < 20; x++) rlm@1: { rlm@1: *toAddress++ = p; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbAttributeDivide() rlm@1: { rlm@1: u8 control = gbSgbPacket[1]; rlm@1: u8 coord = gbSgbPacket[2]; rlm@1: u8 colorBR = control & 3; rlm@1: u8 colorAL = (control >> 2) & 3; rlm@1: u8 colorOL = (control >> 4) & 3; rlm@1: rlm@1: if (control & 0x40) rlm@1: { rlm@1: if (coord > 17) rlm@1: coord = 17; rlm@1: rlm@1: for (u8 i = 0; i < 18; i++) rlm@1: { rlm@1: if (i < coord) rlm@1: gbSgbSetRowPalette(i, colorAL); rlm@1: else if (i > coord) rlm@1: gbSgbSetRowPalette(i, colorBR); rlm@1: else rlm@1: gbSgbSetRowPalette(i, colorOL); rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: if (coord > 19) rlm@1: coord = 19; rlm@1: rlm@1: for (u8 i = 0; i < 20; i++) rlm@1: { rlm@1: if (i < coord) rlm@1: gbSgbSetColumnPalette(i, colorAL); rlm@1: else if (i > coord) rlm@1: gbSgbSetColumnPalette(i, colorBR); rlm@1: else rlm@1: gbSgbSetColumnPalette(i, colorOL); rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbAttributeLine() rlm@1: { rlm@1: u8 *fromAddress = &gbSgbPacket[1]; rlm@1: rlm@1: u8 nDataSet = *fromAddress++; rlm@1: rlm@1: if (nDataSet > 0x6e) rlm@1: nDataSet = 0x6e; rlm@1: rlm@1: while (nDataSet) rlm@1: { rlm@1: u8 line = *fromAddress++; rlm@1: u8 num = line & 0x1f; rlm@1: u8 pal = (line >> 5) & 0x03; rlm@1: if (line & 0x80) rlm@1: { rlm@1: if (num > 17) rlm@1: num = 17; rlm@1: gbSgbSetRowPalette(num, pal); rlm@1: } rlm@1: else rlm@1: { rlm@1: if (num > 19) rlm@1: num = 19; rlm@1: gbSgbSetColumnPalette(num, pal); rlm@1: } rlm@1: nDataSet--; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbAttributeCharacter() rlm@1: { rlm@1: u8 startH = gbSgbPacket[1] & 0x1f; rlm@1: u8 startV = gbSgbPacket[2] & 0x1f; rlm@1: int nDataSet = READ16LE(((u16 *)&gbSgbPacket[3])); rlm@1: int style = gbSgbPacket[5] & 1; rlm@1: if (startH > 19) rlm@1: startH = 19; rlm@1: if (startV > 17) rlm@1: startV = 17; rlm@1: rlm@1: u8 s = 6; rlm@1: u8 *fromAddress = &gbSgbPacket[6]; rlm@1: u8 v = *fromAddress++; rlm@1: rlm@1: if (style) rlm@1: { rlm@1: while (nDataSet) rlm@1: { rlm@1: u8 p = (v >> s) & 3; rlm@1: gbSgbATF[startV * 20 + startH] = p; rlm@1: startV++; rlm@1: if (startV == 18) rlm@1: { rlm@1: startV = 0; rlm@1: startH++; rlm@1: if (startH == 20) rlm@1: break; rlm@1: } rlm@1: rlm@1: if (s) rlm@1: s -= 2; rlm@1: else rlm@1: { rlm@1: s = 6; rlm@1: v = *fromAddress++; rlm@1: nDataSet--; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: while (nDataSet) rlm@1: { rlm@1: u8 p = (v >> s) & 3; rlm@1: gbSgbATF[startV * 20 + startH] = p; rlm@1: startH++; rlm@1: if (startH == 20) rlm@1: { rlm@1: startH = 0; rlm@1: startV++; rlm@1: if (startV == 18) rlm@1: break; rlm@1: } rlm@1: rlm@1: if (s) rlm@1: s -= 2; rlm@1: else rlm@1: { rlm@1: s = 6; rlm@1: v = *fromAddress++; rlm@1: nDataSet--; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbSetATFList() rlm@1: { rlm@1: gbSgbRenderScreenToBuffer(); rlm@1: rlm@1: u8 *fromAddress = gbSgbScreenBuffer; rlm@1: u8 *toAddress = gbSgbATFList; rlm@1: rlm@1: for (int i = 0; i < 45; i++) rlm@1: { rlm@1: for (int j = 0; j < 90; j++) rlm@1: { rlm@1: u8 v = *fromAddress++; rlm@1: u8 s = 6; rlm@1: if (i == 2) rlm@1: s = 6; rlm@1: for (int k = 0; k < 4; k++) rlm@1: { rlm@1: *toAddress++ = (v >> s) & 0x03; rlm@1: s -= 2; rlm@1: } rlm@1: } rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbMaskEnable() rlm@1: { rlm@1: int gbSgbMaskFlag = gbSgbPacket[1] & 3; rlm@1: rlm@1: gbSgbMask = gbSgbMaskFlag; rlm@1: rlm@1: switch (gbSgbMaskFlag) rlm@1: { rlm@1: case 1: rlm@1: break; rlm@1: case 2: rlm@1: gbSgbFillScreen(0x0000); rlm@1: // memset(&gbPalette[0], 0, 128*sizeof(u16)); rlm@1: break; rlm@1: case 3: rlm@1: gbSgbFillScreen(gbPalette[0]); rlm@1: break; rlm@1: } rlm@1: if (!gbSgbMask) rlm@1: { rlm@1: if (gbBorderOn) rlm@1: gbSgbRenderBorder(); rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbChrTransfer() rlm@1: { rlm@1: gbSgbRenderScreenToBuffer(); rlm@1: rlm@1: int address = (gbSgbPacket[1] & 1) * (128 * 32); rlm@1: rlm@1: if (gbSgbPacket[1] & 1) rlm@1: gbSgbCGBSupport |= 2; rlm@1: else rlm@1: gbSgbCGBSupport |= 1; rlm@1: rlm@1: memcpy(&gbSgbBorderChar[address], gbSgbScreenBuffer, 128 * 32); rlm@1: rlm@1: if (gbBorderAutomatic && !gbBorderOn && gbSgbCGBSupport > 4) rlm@1: { rlm@1: gbBorderOn = 1; rlm@1: systemGbBorderOn(); rlm@1: } rlm@1: rlm@1: if (gbBorderOn && !gbSgbMask) rlm@1: gbSgbRenderBorder(); rlm@1: rlm@1: if (gbSgbMode && gbCgbMode && gbSgbCGBSupport == 7) rlm@1: { rlm@1: gbSgbCGBSupport = 0; rlm@1: gbSgbMode = 2; rlm@1: gbSgbMask = 0; rlm@1: gbSgbRenderBorder(); rlm@1: gbReset(); rlm@1: } rlm@1: rlm@1: if (gbSgbCGBSupport > 4) rlm@1: gbSgbCGBSupport = 0; rlm@1: } rlm@1: rlm@1: void gbSgbMultiRequest() rlm@1: { rlm@1: if (gbSgbPacket[1] & 1) rlm@1: { rlm@1: gbSgbMultiplayer = 1; rlm@1: if (gbSgbPacket[1] & 2) rlm@1: gbSgbFourPlayers = 1; rlm@1: else rlm@1: gbSgbFourPlayers = 0; rlm@1: gbSgbNextController = 0x0e; rlm@1: } rlm@1: else rlm@1: { rlm@1: gbSgbFourPlayers = 0; rlm@1: gbSgbMultiplayer = 0; rlm@1: gbSgbNextController = 0x0f; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbCommand() rlm@1: { rlm@1: int command = gbSgbPacket[0] >> 3; rlm@1: // int nPacket = gbSgbPacket[0] & 7; rlm@1: rlm@1: switch (command) rlm@1: { rlm@1: case 0x00: rlm@1: gbSgbSetPalette(0, 1, (u16 *)&gbSgbPacket[1]); rlm@1: break; rlm@1: case 0x01: rlm@1: gbSgbSetPalette(2, 3, (u16 *)&gbSgbPacket[1]); rlm@1: break; rlm@1: case 0x02: rlm@1: gbSgbSetPalette(0, 3, (u16 *)&gbSgbPacket[1]); rlm@1: break; rlm@1: case 0x03: rlm@1: gbSgbSetPalette(1, 2, (u16 *)&gbSgbPacket[1]); rlm@1: break; rlm@1: case 0x04: rlm@1: gbSgbAttributeBlock(); rlm@1: break; rlm@1: case 0x05: rlm@1: gbSgbAttributeLine(); rlm@1: break; rlm@1: case 0x06: rlm@1: gbSgbAttributeDivide(); rlm@1: break; rlm@1: case 0x07: rlm@1: gbSgbAttributeCharacter(); rlm@1: break; rlm@1: case 0x0a: rlm@1: gbSgbSetPalette(); rlm@1: break; rlm@1: case 0x0b: rlm@1: gbSgbScpPalette(); rlm@1: break; rlm@1: case 0x11: rlm@1: gbSgbMultiRequest(); rlm@1: break; rlm@1: case 0x13: rlm@1: gbSgbChrTransfer(); rlm@1: break; rlm@1: case 0x14: rlm@1: gbSgbPicture(); rlm@1: break; rlm@1: case 0x15: rlm@1: gbSgbSetATFList(); rlm@1: break; rlm@1: case 0x16: rlm@1: gbSgbSetATF(gbSgbPacket[1] & 0x3f); rlm@1: break; rlm@1: case 0x17: rlm@1: gbSgbMaskEnable(); rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: void gbSgbResetPacketState() rlm@1: { rlm@1: gbSgbPacketState = GBSGB_NONE; rlm@1: gbSgbPacketTimeout = 0; rlm@1: } rlm@1: rlm@1: void gbSgbDoBitTransfer(u8 value) rlm@1: { rlm@1: value = value & 0x30; rlm@1: switch (gbSgbPacketState) rlm@1: { rlm@1: case GBSGB_NONE: rlm@1: if (value == 0) rlm@1: { rlm@1: gbSgbPacketState = GBSGB_RESET; rlm@1: gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; rlm@1: } rlm@1: else if (value == 0x30) rlm@1: { rlm@1: if (gbSgbMultiplayer) rlm@1: { rlm@1: if ((gbSgbReadingController & 7) == 7) rlm@1: { rlm@1: gbSgbReadingController = 0; rlm@1: if (gbSgbMultiplayer) rlm@1: { rlm@1: gbSgbNextController--; rlm@1: if (gbSgbFourPlayers) rlm@1: { rlm@1: if (gbSgbNextController == 0x0b) rlm@1: gbSgbNextController = 0x0f; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (gbSgbNextController == 0x0d) rlm@1: gbSgbNextController = 0x0f; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: gbSgbReadingController &= 3; rlm@1: } rlm@1: } rlm@1: gbSgbPacketTimeout = 0; rlm@1: } rlm@1: else rlm@1: { rlm@1: if (value == 0x10) rlm@1: gbSgbReadingController |= 0x2; rlm@1: else if (value == 0x20) rlm@1: gbSgbReadingController |= 0x01; rlm@1: gbSgbPacketTimeout = 0; rlm@1: } rlm@1: gbSgbPacketTimeout = 0; rlm@1: break; rlm@1: case GBSGB_RESET: rlm@1: if (value == 0x30) rlm@1: { rlm@1: gbSgbPacketState = GBSGB_PACKET_TRANSMIT; rlm@1: gbSgbPacketByte = 0; rlm@1: gbSgbPacketNBits = 0; rlm@1: gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; rlm@1: } rlm@1: else if (value == 0x00) rlm@1: { rlm@1: gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; rlm@1: gbSgbPacketState = GBSGB_RESET; rlm@1: } rlm@1: else rlm@1: { rlm@1: gbSgbPacketState = GBSGB_NONE; rlm@1: gbSgbPacketTimeout = 0; rlm@1: } rlm@1: break; rlm@1: case GBSGB_PACKET_TRANSMIT: rlm@1: if (value == 0) rlm@1: { rlm@1: gbSgbPacketState = GBSGB_RESET; rlm@1: gbSgbPacketTimeout = 0; rlm@1: } rlm@1: else if (value == 0x30) rlm@1: { rlm@1: if (gbSgbPacketNBits == 128) rlm@1: { rlm@1: gbSgbPacketNBits = 0; rlm@1: gbSgbPacketByte = 0; rlm@1: gbSgbPacketNumber++; rlm@1: gbSgbPacketTimeout = 0; rlm@1: if (gbSgbPacketNumber == (gbSgbPacket[0] & 7)) rlm@1: { rlm@1: gbSgbCommand(); rlm@1: gbSgbPacketNumber = 0; rlm@1: gbSgbPacketState = GBSGB_NONE; rlm@1: gbSgbPacketTimeout = 0; rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: if (gbSgbPacketNBits < 128) rlm@1: { rlm@1: gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] >>= 1; rlm@1: gbSgbPacket[gbSgbPacketNumber * 16 + gbSgbPacketByte] |= gbSgbBit; rlm@1: gbSgbPacketNBits++; rlm@1: if (!(gbSgbPacketNBits & 7)) rlm@1: { rlm@1: gbSgbPacketByte++; rlm@1: } rlm@1: gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; rlm@1: } rlm@1: } rlm@1: } rlm@1: else rlm@1: { rlm@1: if (value == 0x20) rlm@1: gbSgbBit = 0x00; rlm@1: else rlm@1: gbSgbBit = 0x80; rlm@1: gbSgbPacketTimeout = GBSGB_PACKET_TIMEOUT; rlm@1: } rlm@1: gbSgbReadingController = 0; rlm@1: break; rlm@1: default: rlm@1: gbSgbPacketState = GBSGB_NONE; rlm@1: gbSgbPacketTimeout = 0; rlm@1: break; rlm@1: } rlm@1: } rlm@1: rlm@1: variable_desc gbSgbSaveStruct[] = { rlm@1: { &gbSgbMask, sizeof(int32) }, rlm@1: { &gbSgbPacketState, sizeof(int32) }, rlm@1: { &gbSgbBit, sizeof(int32) }, rlm@1: { &gbSgbPacketNBits, sizeof(int32) }, rlm@1: { &gbSgbPacketByte, sizeof(int32) }, rlm@1: { &gbSgbPacketNumber, sizeof(int32) }, rlm@1: { &gbSgbMultiplayer, sizeof(int32) }, rlm@1: { &gbSgbNextController, sizeof(u8) }, rlm@1: { &gbSgbReadingController, sizeof(u8) }, rlm@1: { NULL, 0 } rlm@1: }; rlm@1: rlm@1: variable_desc gbSgbSaveStructV3[] = { rlm@1: { &gbSgbMask, sizeof(int32) }, rlm@1: { &gbSgbPacketState, sizeof(int32) }, rlm@1: { &gbSgbBit, sizeof(int32) }, rlm@1: { &gbSgbPacketNBits, sizeof(int32) }, rlm@1: { &gbSgbPacketByte, sizeof(int32) }, rlm@1: { &gbSgbPacketNumber, sizeof(int32) }, rlm@1: { &gbSgbMultiplayer, sizeof(int32) }, rlm@1: { &gbSgbNextController, sizeof(u8) }, rlm@1: { &gbSgbReadingController, sizeof(u8) }, rlm@1: { &gbSgbFourPlayers, sizeof(int32) }, rlm@1: { NULL, 0 } rlm@1: }; rlm@1: rlm@1: void gbSgbSaveGame(gzFile gzFile) rlm@1: { rlm@1: utilWriteData(gzFile, gbSgbSaveStructV3); rlm@1: rlm@1: utilGzWrite(gzFile, gbSgbBorder, 2048); rlm@1: utilGzWrite(gzFile, gbSgbBorderChar, 32 * 256); rlm@1: rlm@1: utilGzWrite(gzFile, gbSgbPacket, 16 * 7); rlm@1: rlm@1: utilGzWrite(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); rlm@1: utilGzWrite(gzFile, gbSgbATF, 20 * 18); rlm@1: utilGzWrite(gzFile, gbSgbATFList, 45 * 20 * 18); rlm@1: rlm@1: utilGzWrite(gzFile, gbSgbScreenBuffer, 4160); rlm@1: utilGzWrite(gzFile, &gbSgbMode, sizeof(gbSgbMode)); rlm@1: utilGzWrite(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport)); rlm@1: utilGzWrite(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout)); rlm@1: } rlm@1: rlm@1: void gbSgbReadGame(gzFile gzFile, int version) rlm@1: { rlm@1: if (version >= 3) rlm@1: utilReadData(gzFile, gbSgbSaveStructV3); rlm@1: else rlm@1: { rlm@1: utilReadData(gzFile, gbSgbSaveStruct); rlm@1: gbSgbFourPlayers = 0; rlm@1: } rlm@1: rlm@1: if (version >= 8) rlm@1: { rlm@1: utilGzRead(gzFile, gbSgbBorder, 2048); rlm@1: utilGzRead(gzFile, gbSgbBorderChar, 32 * 256); rlm@1: } rlm@1: rlm@1: utilGzRead(gzFile, gbSgbPacket, 16 * 7); rlm@1: rlm@1: utilGzRead(gzFile, gbSgbSCPPalette, 4 * 512 * sizeof(u16)); rlm@1: utilGzRead(gzFile, gbSgbATF, 20 * 18); rlm@1: utilGzRead(gzFile, gbSgbATFList, 45 * 20 * 18); rlm@1: rlm@1: if (version >= 11) rlm@1: { rlm@1: utilGzRead(gzFile, gbSgbScreenBuffer, 4160); rlm@1: utilGzRead(gzFile, &gbSgbMode, sizeof(gbSgbMode)); rlm@1: utilGzRead(gzFile, &gbSgbCGBSupport, sizeof(gbSgbCGBSupport)); rlm@1: utilGzRead(gzFile, &gbSgbPacketTimeout, sizeof(gbSgbPacketTimeout)); rlm@1: } rlm@1: } rlm@1: