////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// private void CreateTilesData(ref sTile[] t, ushort startAdr) { //create 1st tile data t = new sTile[256]; for (int i = 0; i < 256; i++) //a tile is 16 bytes { ushort adr = (ushort)(startAdr + (i * 0x10)); //a tile is 16 bytes t[i].startAdr = adr; } }
////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// private unsafe void DrawTile(sTile t, int posX, int posY, int w, int h, bool hFlip, bool vFlip, ref BitmapData b, ref Color[] palette, bool isAboveBg, int tileLine) { int y = posY; int x = posX; int stride = b.Stride; byte * ptr = (byte *)b.Scan0; int l = tileLine;// % 8; int maxBitmapIndex = 160 * 3 + 144 * stride; ushort adr1 = (ushort)(t.startAdr + l * 2); ushort adr2 = (ushort)(t.startAdr + 1 + l * 2); if (hFlip) { adr2 = (ushort)(t.startAdr + 15 - l * 2); adr1 = (ushort)(t.startAdr + 15 - 1 - l * 2); } byte b1 = GameBoy.Ram.ReadByteAt(adr1); // a line of 8 px is 2 bytes. byte b2 = GameBoy.Ram.ReadByteAt(adr2); // a line of 8 px is 2 bytes. Read8PixelsFrom2Byte(b1, b2, ref m_halfLine, ref palette); for (int m = 0; m < 8; m++) { int px = x + m; if (y >= 0 && y <= h && px <= w && px >= 0) { Color c = m_halfLine[m]; if (vFlip) { c = m_halfLine[7 - m]; } if (c != m_bitmapTransparency) { if (!isAboveBg) { Color bc = Color.FromArgb(255, ptr[(px * 3) + y * stride + 2], ptr[(px * 3) + y * stride + 1], ptr[(px * 3) + y * stride]); if (bc == m_bgPalette[0]) { ptr[(px * 3) + y * stride] = c.B; ptr[(px * 3) + y * stride + 1] = c.G; ptr[(px * 3) + y * stride + 2] = c.R; } } else { ptr[(px * 3) + y * stride] = c.B; ptr[(px * 3) + y * stride + 1] = c.G; ptr[(px * 3) + y * stride + 2] = c.R; } } } } }
////////////////////////////////////////////////////////////////////// // ////////////////////////////////////////////////////////////////////// private void DisplaySprites(ref BitmapData b, int line) { byte[] oam = new byte[0xA0]; GameBoy.Ram.ReadAt(0xFE00, 0xA0, ref oam); bool spriteSize8x16 = m_LCLD_flag_SpriteSize != 0; for (int i = (0xA0 - 4); i >= 0; i -= 4) //for (int i = 0; i < 0xA0-4; i++ ) { int posY = oam[i]; int posX = oam[i + 1]; int idx = oam[i + 2]; int flags = oam[i + 3]; bool isAboveBg = (flags & 0x80) == 0; bool HFlip = (flags & 0x40) != 0; bool VFlip = (flags & 0x20) != 0; bool useOBJ1 = (flags & 0x10) != 0; Color[] p = m_spPaletteOBJ0; if (useOBJ1) { p = m_spPaletteOBJ1; } int l = line % 8; posX = posX - 8; posY = posY - 16 + l; int curSpriteLineMin = posY; int curSpriteLineMax = posY + 8; if (spriteSize8x16) { curSpriteLineMax += 8; } if (curSpriteLineMax >= line && curSpriteLineMin <= line) { if (posX != 0 && posY != 0) { if (!spriteSize8x16) { sTile t = m_tiles_8000_8FFF[idx]; DrawTile(t, posX, posY, 160, 144, HFlip, VFlip, ref b, ref p, isAboveBg, l); } else { int k0 = idx & 0xFE; int k1 = idx | 0x01; if (!HFlip) { sTile t = m_tiles_8000_8FFF[k0]; DrawTile(t, posX, posY, 160, 144, HFlip, VFlip, ref b, ref p, isAboveBg, l); t = m_tiles_8000_8FFF[k1]; DrawTile(t, posX, posY + 8, 160, 144, HFlip, VFlip, ref b, ref p, isAboveBg, l); } else { sTile t = m_tiles_8000_8FFF[k0]; DrawTile(t, posX, posY + 8, 160, 144, HFlip, VFlip, ref b, ref p, isAboveBg, l); t = m_tiles_8000_8FFF[k1]; DrawTile(t, posX, posY, 160, 144, HFlip, VFlip, ref b, ref p, isAboveBg, l); } } } } } }