private void UpdateModel(bool updateBitmap) { if (updateBitmap) { uint[,] backgroundBuffer = x80.backgroundBuffer; uint[,] windowBuffer = x80.windowBuffer; byte[] oam = x80.oam; for (int y = 0, pixelIndex = 0; y < HEIGHT; ++y) { x80.ly = y; x80.lcdcMode = LcdcModeType.SearchingOamRam; if (x80.lcdcInterruptEnabled && (x80.lcdcOamInterruptEnabled || (x80.lcdcLycLyCoincidenceInterruptEnabled && x80.lyCompare == y))) { x80.lcdcInterruptRequested = true; } ExecuteProcessor(800); x80.lcdcMode = LcdcModeType.TransferingData; ExecuteProcessor(1720); x80.UpdateWindow(); x80.UpdateBackground(); x80.UpdateSpriteTiles(); bool backgroundDisplayed = x80.backgroundDisplayed; int scrollX = x80.scrollX; int scrollY = x80.scrollY; bool windowDisplayed = x80.windowDisplayed; int windowX = x80.windowX - 7; int windowY = x80.windowY; for (int x = 0; x < WIDTH; ++x, ++pixelIndex) { uint intensity = 0; if (backgroundDisplayed) { intensity = backgroundBuffer [0xFF & (scrollY + y), 0xFF & (scrollX + x)]; } if (windowDisplayed && y >= windowY && y < windowY + HEIGHT && x >= windowX && x < windowX + WIDTH && windowX >= -7 && windowX < WIDTH && windowY >= 0 && windowY < HEIGHT) { intensity = windowBuffer [y - windowY, x - windowX]; } pixels [pixelIndex] = intensity; } if (x80.spritesDisplayed) { uint[, , ,] spriteTile = x80.spriteTile; if (x80.largeSprites) { for (int address = 0; address < WIDTH; address += 4) { int spriteY = oam [address]; int spriteX = oam [address + 1]; if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168) { continue; } spriteY -= 16; if (spriteY > y || spriteY + 15 < y) { continue; } spriteX -= 8; int spriteTileIndex0 = 0xFE & oam [address + 2]; int spriteTileIndex1 = spriteTileIndex0 | 0x01; int spriteFlags = oam [address + 3]; bool spritePriority = (0x80 & spriteFlags) == 0x80; bool spriteYFlipped = (0x40 & spriteFlags) == 0x40; bool spriteXFlipped = (0x20 & spriteFlags) == 0x20; int spritePalette = (0x10 & spriteFlags) == 0x10 ? 1 : 0; if (spriteYFlipped) { int temp = spriteTileIndex0; spriteTileIndex0 = spriteTileIndex1; spriteTileIndex1 = temp; } int spriteRow = y - spriteY; if (spriteRow >= 0 && spriteRow < 8) { int screenAddress = (y << 7) + (y << 5) + spriteX; for (int x = 0; x < 8; ++x, ++screenAddress) { int screenX = spriteX + x; if (screenX >= 0 && screenX < WIDTH) { uint color = spriteTile [spriteTileIndex0, spriteYFlipped ? 7 - spriteRow : spriteRow, spriteXFlipped ? 7 - x : x, spritePalette]; if (color > 0) { if (spritePriority) { if (pixels [screenAddress] == 0xFFFFFFFF) { pixels [screenAddress] = color; } } else { pixels [screenAddress] = color; } } } } continue; } spriteY += 8; spriteRow = y - spriteY; if (spriteRow >= 0 && spriteRow < 8) { int screenAddress = (y << 7) + (y << 5) + spriteX; for (int x = 0; x < 8; ++x, ++screenAddress) { int screenX = spriteX + x; if (screenX >= 0 && screenX < WIDTH) { uint color = spriteTile [spriteTileIndex1, spriteYFlipped ? 7 - spriteRow : spriteRow, spriteXFlipped ? 7 - x : x, spritePalette]; if (color > 0) { if (spritePriority) { if (pixels [screenAddress] == 0xFFFFFFFF) { pixels [screenAddress] = color; } } else { pixels [screenAddress] = color; } } } } } } } else { for (int address = 0; address < WIDTH; address += 4) { int spriteY = oam [address]; int spriteX = oam [address + 1]; if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168) { continue; } spriteY -= 16; if (spriteY > y || spriteY + 7 < y) { continue; } spriteX -= 8; int spriteTileIndex = oam [address + 2]; int spriteFlags = oam [address + 3]; bool spritePriority = (0x80 & spriteFlags) == 0x80; bool spriteYFlipped = (0x40 & spriteFlags) == 0x40; bool spriteXFlipped = (0x20 & spriteFlags) == 0x20; int spritePalette = (0x10 & spriteFlags) == 0x10 ? 1 : 0; int spriteRow = y - spriteY; int screenAddress = (y << 7) + (y << 5) + spriteX; for (int x = 0; x < 8; ++x, ++screenAddress) { int screenX = spriteX + x; if (screenX >= 0 && screenX < WIDTH) { uint color = spriteTile [spriteTileIndex, spriteYFlipped ? 7 - spriteRow : spriteRow, spriteXFlipped ? 7 - x : x, spritePalette]; if (color > 0) { if (spritePriority) { if (pixels [screenAddress] == 0xFFFFFFFF) { pixels [screenAddress] = color; } } else { pixels [screenAddress] = color; } } } } } } } x80.lcdcMode = LcdcModeType.HBlank; if (x80.lcdcInterruptEnabled && x80.lcdcHBlankInterruptEnabled) { x80.lcdcInterruptRequested = true; } ExecuteProcessor(2040); AddTicksPerScanLine(); } } else { for (int y = 0; y < HEIGHT; ++y) { x80.ly = y; x80.lcdcMode = LcdcModeType.SearchingOamRam; if (x80.lcdcInterruptEnabled && (x80.lcdcOamInterruptEnabled || (x80.lcdcLycLyCoincidenceInterruptEnabled && x80.lyCompare == y))) { x80.lcdcInterruptRequested = true; } ExecuteProcessor(800); x80.lcdcMode = LcdcModeType.TransferingData; ExecuteProcessor(1720); x80.lcdcMode = LcdcModeType.HBlank; if (x80.lcdcInterruptEnabled && x80.lcdcHBlankInterruptEnabled) { x80.lcdcInterruptRequested = true; } ExecuteProcessor(2040); AddTicksPerScanLine(); } } x80.lcdcMode = LcdcModeType.VBlank; if (x80.vBlankInterruptEnabled) { x80.vBlankInterruptRequested = true; } if (x80.lcdcInterruptEnabled && x80.lcdcVBlankInterruptEnabled) { x80.lcdcInterruptRequested = true; } for (int y = 144; y <= 153; ++y) { x80.ly = y; if (x80.lcdcInterruptEnabled && x80.lcdcLycLyCoincidenceInterruptEnabled && x80.lyCompare == y) { x80.lcdcInterruptRequested = true; } ExecuteProcessor(4560); AddTicksPerScanLine(); } if (Audio != null) { x80.SoundChip.OutputSound(Audio); } }
private void UpdateModel(bool updateBitmap) { if (updateBitmap) { uint[] backgroundPalette = _x80.BackgroundPalette; uint[] objectPalette0 = _x80.ObjectPalette0; uint[] objectPalette1 = _x80.ObjectPalette1; uint[,] backgroundBuffer = _x80.BackgroundBuffer; uint[,] windowBuffer = _x80.WindowBuffer; byte[] oam = _x80.Oam; for (int y = 0, pixelIndex = 0; y < 144; y++) { _x80.Ly = y; _x80.LcdcMode = LcdcModeType.SearchingOamRam; if (_x80.LcdcInterruptEnabled && (_x80.LcdcOamInterruptEnabled || (_x80.LcdcLycLyCoincidenceInterruptEnabled && _x80.LyCompare == y))) { _x80.LcdcInterruptRequested = true; } ExecuteProcessor(800); _x80.LcdcMode = LcdcModeType.TransferingData; ExecuteProcessor(1720); _x80.UpdateWindow(); _x80.UpdateBackground(); _x80.UpdateSpriteTiles(); bool backgroundDisplayed = _x80.BackgroundDisplayed; bool backgroundAndWindowTileDataSelect = _x80.BackgroundAndWindowTileDataSelect; bool backgroundTileMapDisplaySelect = _x80.BackgroundTileMapDisplaySelect; int scrollX = _x80.ScrollX; int scrollY = _x80.ScrollY; bool windowDisplayed = _x80.WindowDisplayed; bool windowTileMapDisplaySelect = _x80.WindowTileMapDisplaySelect; int windowX = _x80.WindowX - 7; int windowY = _x80.WindowY; int windowPointY = windowY + y; for (int x = 0; x < 160; x++, pixelIndex++) { uint intensity = 0; if (backgroundDisplayed) { intensity = backgroundBuffer[0xFF & (scrollY + y), 0xFF & (scrollX + x)]; } if (windowDisplayed && y >= windowY && y < windowY + 144 && x >= windowX && x < windowX + 160 && windowX >= -7 && windowX <= 159 && windowY >= 0 && windowY <= 143) { intensity = windowBuffer[y - windowY, x - windowX]; } _pixels[pixelIndex] = intensity; } if (_x80.SpritesDisplayed) { uint[,,,] spriteTile = _x80.SpriteTile; if (_x80.LargeSprites) { for (int address = 0; address < 160; address += 4) { int spriteY = oam[address]; int spriteX = oam[address + 1]; if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168) { continue; } spriteY -= 16; if (spriteY > y || spriteY + 15 < y) { continue; } spriteX -= 8; int spriteTileIndex0 = 0xFE & oam[address + 2]; int spriteTileIndex1 = spriteTileIndex0 | 0x01; int spriteFlags = oam[address + 3]; bool spritePriority = (0x80 & spriteFlags) == 0x80; bool spriteYFlipped = (0x40 & spriteFlags) == 0x40; bool spriteXFlipped = (0x20 & spriteFlags) == 0x20; int spritePalette = (0x10 & spriteFlags) == 0x10 ? 1 : 0; if (spriteYFlipped) { int temp = spriteTileIndex0; spriteTileIndex0 = spriteTileIndex1; spriteTileIndex1 = temp; } int spriteRow = y - spriteY; if (spriteRow >= 0 && spriteRow < 8) { int screenAddress = (y << 7) + (y << 5) + spriteX; for (int x = 0; x < 8; x++, screenAddress++) { int screenX = spriteX + x; if (screenX >= 0 && screenX < 160) { uint color = spriteTile[spriteTileIndex0, spriteYFlipped ? 7 - spriteRow : spriteRow, spriteXFlipped ? 7 - x : x, spritePalette]; if (color > 0) { if (spritePriority) { if (_pixels[screenAddress] == 0xFFFFFFFF) { _pixels[screenAddress] = color; } } else { _pixels[screenAddress] = color; } } } } continue; } spriteY += 8; spriteRow = y - spriteY; if (spriteRow >= 0 && spriteRow < 8) { int screenAddress = (y << 7) + (y << 5) + spriteX; for (int x = 0; x < 8; x++, screenAddress++) { int screenX = spriteX + x; if (screenX >= 0 && screenX < 160) { uint color = spriteTile[spriteTileIndex1, spriteYFlipped ? 7 - spriteRow : spriteRow, spriteXFlipped ? 7 - x : x, spritePalette]; if (color > 0) { if (spritePriority) { if (_pixels[screenAddress] == 0xFFFFFFFF) { _pixels[screenAddress] = color; } } else { _pixels[screenAddress] = color; } } } } } } } else { for (int address = 0; address < 160; address += 4) { int spriteY = oam[address]; int spriteX = oam[address + 1]; if (spriteY == 0 || spriteX == 0 || spriteY >= 160 || spriteX >= 168) { continue; } spriteY -= 16; if (spriteY > y || spriteY + 7 < y) { continue; } spriteX -= 8; int spriteTileIndex = oam[address + 2]; int spriteFlags = oam[address + 3]; bool spritePriority = (0x80 & spriteFlags) == 0x80; bool spriteYFlipped = (0x40 & spriteFlags) == 0x40; bool spriteXFlipped = (0x20 & spriteFlags) == 0x20; int spritePalette = (0x10 & spriteFlags) == 0x10 ? 1 : 0; int spriteRow = y - spriteY; int screenAddress = (y << 7) + (y << 5) + spriteX; for (int x = 0; x < 8; x++, screenAddress++) { int screenX = spriteX + x; if (screenX >= 0 && screenX < 160) { uint color = spriteTile[spriteTileIndex, spriteYFlipped ? 7 - spriteRow : spriteRow, spriteXFlipped ? 7 - x : x, spritePalette]; if (color > 0) { if (spritePriority) { if (_pixels[screenAddress] == 0xFFFFFFFF) { _pixels[screenAddress] = color; } } else { _pixels[screenAddress] = color; } } } } } } } _x80.LcdcMode = LcdcModeType.HBlank; if (_x80.LcdcInterruptEnabled && _x80.LcdcHBlankInterruptEnabled) { _x80.LcdcInterruptRequested = true; } ExecuteProcessor(2040); AddTicksPerScanLine(); } } else { for (int y = 0; y < 144; y++) { _x80.Ly = y; _x80.LcdcMode = LcdcModeType.SearchingOamRam; if (_x80.LcdcInterruptEnabled && (_x80.LcdcOamInterruptEnabled || (_x80.LcdcLycLyCoincidenceInterruptEnabled && _x80.LyCompare == y))) { _x80.LcdcInterruptRequested = true; } ExecuteProcessor(800); _x80.LcdcMode = LcdcModeType.TransferingData; ExecuteProcessor(1720); _x80.LcdcMode = LcdcModeType.HBlank; if (_x80.LcdcInterruptEnabled && _x80.LcdcHBlankInterruptEnabled) { _x80.LcdcInterruptRequested = true; } ExecuteProcessor(2040); AddTicksPerScanLine(); } } _x80.LcdcMode = LcdcModeType.VBlank; if (_x80.VBlankInterruptEnabled) { _x80.VBlankInterruptRequested = true; } if (_x80.LcdcInterruptEnabled && _x80.LcdcVBlankInterruptEnabled) { _x80.LcdcInterruptRequested = true; } for (int y = 144; y <= 153; y++) { _x80.Ly = y; if (_x80.LcdcInterruptEnabled && _x80.LcdcLycLyCoincidenceInterruptEnabled && _x80.LyCompare == y) { _x80.LcdcInterruptRequested = true; } ExecuteProcessor(4560); AddTicksPerScanLine(); } }