public byte CpuRead(UInt16 address, bool debugMode = false) { if (InCpuRamRange(address)) { return(cpuRam[MaskCpuRam(address)]); } else if (InPpuRange(address)) { return(ppu.CpuRead(MaskPpu(address), debugMode)); } else if (InControllerRange(address)) { int index = address & 0x0001; byte data = (byte)(BitMagic.IsBitSet(capturedController[index], 7) ? 0x01 : 0x00); capturedController[index] <<= 1; return(data); } else if (InCartridgeRange(address)) { return(cartridge.CpuRead(address)); } return(0x00); }
private void LoadShifters() { bgPatternLow.Load(bgNextTileLsb); bgPatternHigh.Load(bgNextTileMsb); byte nextAttributeLowVal = (byte)(BitMagic.IsBitSet(bgNextTileAttribute, 0) ? 0xFF : 0x00); bgAttributeLow.Load(nextAttributeLowVal); byte nextAttributeHighVal = (byte)(BitMagic.IsBitSet(bgNextTileAttribute, 1) ? 0xFF : 0x00); bgAttributeHigh.Load(nextAttributeHighVal); }
// TODO: // - handle different file formats private void ReadHeader(FileStream fs) { // discard name fs.Seek(4, SeekOrigin.Begin); int prgRomSize = fs.ReadByte(); // num of 16kb units prgMemory = new byte[prgRomSize * 16 * 1024]; int chrRomSize = fs.ReadByte(); // num of 8kb units if (chrRomSize == 0) { usingChrRam = true; chrMemory = new byte[8 * 1024]; } else { chrMemory = new byte[chrRomSize * 8 * 1024]; } int flags6 = (byte)fs.ReadByte(); int flags7 = (byte)fs.ReadByte(); int flags8 = (byte)fs.ReadByte(); int flags9 = (byte)fs.ReadByte(); int flags10 = (byte)fs.ReadByte(); // padding fs.Seek(5, SeekOrigin.Current); int mapperId = (flags7 & 0xF0) | ((flags6 & 0xF0) >> 4); AddMapperFromId(mapperId); Mode = BitMagic.IsBitSet((byte)flags6, 0) ? MirrorMode.VERTICAL : MirrorMode.HORIZONTAL; bool hasTrainer = BitMagic.IsBitSet((byte)flags6, 2); if (hasTrainer) { fs.Seek(512, SeekOrigin.Current); } }
public bool ASL() { byte data = Fetch(); Status.CarryFlag = BitMagic.IsBitSet(data, 7); data <<= 1; UpdateZeroFlag(data); UpdateNegativeFlag(data); if (operations[currentOpcode].Mode == AddressingMode.ACC) { A = data; } else { CpuWrite(address, data); } return(false); }
public bool ROR() { byte data = Fetch(); bool bit0Set = BitMagic.IsBitSet(data, 0); data >>= 1; BitMagic.SetBit(ref data, 7, Status.CarryFlag); Status.CarryFlag = bit0Set; UpdateZeroFlag(data); UpdateNegativeFlag(data); if (operations[currentOpcode].Mode == AddressingMode.ACC) { A = data; } else { CpuWrite(address, data); } return(false); }
private void UpdateNegativeFlag(byte target) { Status.NegativeFlag = BitMagic.IsBitSet(target, 7); }
private void PopulateSpriteShifters() { for (int i = 0; i < 8; ++i) { spriteShiftLow[i] = 0; spriteShiftHigh[i] = 0; } for (int i = 0; i < spritesNumber; ++i) { var sprite = currentScanlineSprites[i]; UInt16 addrLow = 0x0000, addrHigh = 0x0000; byte patternTable = 0x00, spriteRow = 0x00; UInt16 tilePosition = 0x0000; if (!controlRegister.SpriteSize) { // 8x8 patternTable = (byte)((controlRegister.PatternSprite ? 0x01 : 0x00) << 12); tilePosition = (UInt16)(sprite.Id << 4); if (!sprite.Attributes.FlipVertically) { spriteRow = (byte)(scanLine - sprite.Y); } else { spriteRow = (byte)(7 - (scanLine - sprite.Y)); } } else { // 8x16 patternTable = (byte)((BitMagic.IsBitSet(sprite.Id, 0) ? 0x01 : 0x00) << 12); if (!sprite.Attributes.FlipVertically) { if (scanLine - sprite.Y < 8) { // top half tilePosition = (UInt16)((sprite.Id & 0xFE) << 4); } else { // bottom half tilePosition = (UInt16)(((sprite.Id & 0xFE) + 1) << 4); } spriteRow = (byte)((scanLine - sprite.Y) & 0x07); } else { if (scanLine - sprite.Y < 8) { // top half tilePosition = (UInt16)(((sprite.Id & 0xFE) + 1) << 4); } else { // bottom half tilePosition = (UInt16)((sprite.Id & 0xFE) << 4); } spriteRow = (byte)((7 - (scanLine - sprite.Y)) & 0x07); } } addrLow = (UInt16)(patternTable | tilePosition | spriteRow); addrHigh = (UInt16)(addrLow + 8); byte spriteLow = PpuRead(addrLow); byte spriteHigh = PpuRead(addrHigh); if (sprite.Attributes.FlipHorizontally) { spriteLow = BitMagic.Flip(spriteLow); spriteHigh = BitMagic.Flip(spriteHigh); } spriteShiftLow[i] = spriteLow; spriteShiftHigh[i] = spriteHigh; } }
private void DrawPixel() { Pixel bgPixel = new Pixel(); if (maskRegister.ShowBackground) { UInt16 bitmask = (UInt16)(0x8000 >> fineX); bgPixel.Value = (byte) ( (((bgPatternHigh.Register & bitmask) != 0 ? 1 : 0) << 1) | ((bgPatternLow.Register & bitmask) != 0 ? 1 : 0) ); bgPixel.Palette = (byte) ( (((bgAttributeHigh.Register & bitmask) != 0 ? 1 : 0) << 1) | ((bgAttributeLow.Register & bitmask) != 0 ? 1 : 0) ); } Pixel fgPixel = new Pixel(); bool fgPriority = false; if (maskRegister.ShowSprites) { spriteZeroRendered = false; for (int i = 0; i < spritesNumber; ++i) { var sprite = currentScanlineSprites[i]; if (sprite.X == 0) { // we've hit the sprite byte fgPixelLow = (byte)(BitMagic.IsBitSet(spriteShiftLow[i], 7) ? 0x01 : 0x00); byte fgPixelHigh = (byte)(BitMagic.IsBitSet(spriteShiftHigh[i], 7) ? 0x01 : 0x00); fgPixel.Value = (byte)((fgPixelHigh << 1) | fgPixelLow); fgPixel.Palette = sprite.Attributes.Palette; fgPriority = sprite.Attributes.Priority; if (fgPixel.Value != 0) { if (i == 0) { spriteZeroRendered = true; } break; } } } } Pixel pixel = Pixel.Pick(bgPixel, fgPixel, fgPriority); if (spriteZeroSelected && spriteZeroRendered && bgPixel.Value > 0 && fgPixel.Value > 0) { if (maskRegister.ShowBackground && maskRegister.ShowSprites) { if (!(maskRegister.ShowBackgroundLeft || maskRegister.ShowSpritesLeft)) { if (cycle >= 9 && cycle <= 256) { statusRegister.SpriteZeroHit = true; } } else { if (cycle >= 1 && cycle <= 256) { statusRegister.SpriteZeroHit = true; } } } } if (cycle >= 1 && cycle <= 256 && scanLine >= 0 && scanLine < 240) { var color = paletteRam.PixelColor(pixel); int index = 256 * scanLine + cycle - 1; int finalColor = 0; finalColor |= (color.R << 16); finalColor |= (color.G << 8); finalColor |= (color.B << 0); PixelBuffer[index] = finalColor; } }