示例#1
0
        private UInt16 StackPopWord()
        {
            byte low  = StackPop();
            byte high = StackPop();

            return(BitMagic.Combine(high, low));
        }
示例#2
0
        public bool IND()
        {
            byte low  = CpuRead(PC++);
            byte high = CpuRead(PC++);

            UInt16 ptr = BitMagic.Combine(high, low);

            byte addrLow, addrHigh;

            // hardware bug
            if (low == 0x00FF)
            {
                addrLow  = CpuRead((ptr));
                addrHigh = CpuRead((UInt16)(ptr & 0xFF00));
            }
            else
            {
                addrLow  = CpuRead(ptr);
                addrHigh = CpuRead((UInt16)(ptr + 1));
            }

            address = BitMagic.Combine(addrHigh, addrLow);

            return(false);
        }
示例#3
0
        private UInt16 ReadWord(UInt16 address)
        {
            byte low  = CpuRead(address);
            byte high = CpuRead((UInt16)(address + 1));

            return(BitMagic.Combine(high, low));
        }
示例#4
0
        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);
        }
示例#5
0
        public bool ABS()
        {
            byte low  = CpuRead(PC++);
            byte high = CpuRead(PC++);

            address = BitMagic.Combine(high, low);

            return(false);
        }
示例#6
0
        public bool IZX()
        {
            byte t = CpuRead(PC++);

            // address is in zero page
            byte addrLow  = CpuRead((UInt16)((t + X) & 0x00FF));
            byte addrHigh = CpuRead((UInt16)((t + X + 1) & 0x00FF));

            address = BitMagic.Combine(addrHigh, addrLow);

            return(false);
        }
示例#7
0
        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);
        }
示例#8
0
        // global system clock
        public void Clock()
        {
            ppu.Clock();

            if (clockCounter % 3 == 0)
            {
                if (dmaStarted)
                {
                    if (dmaDummy)
                    {
                        if (clockCounter % 2 == 1)
                        {
                            dmaDummy = false;
                        }
                    }
                    else
                    {
                        if (clockCounter % 2 == 0)
                        {
                            UInt16 address = BitMagic.Combine(dmaPage, dmaAddress);
                            dmaData = CpuRead(address);
                        }
                        else
                        {
                            ppu.Oam[dmaAddress++] = dmaData;

                            // after 256 writes dmaAddress loops back to zero
                            if (dmaAddress == 0)
                            {
                                dmaStarted = false;
                                dmaDummy   = true;
                            }
                        }
                    }
                }
                else
                {
                    cpu.Clock();
                }
            }

            if (ppu.EmitNmi)
            {
                cpu.NMI();
            }

            clockCounter++;
        }
示例#9
0
        // 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);
            }
        }
示例#10
0
        public bool IZY()
        {
            byte t = CpuRead(PC++);

            // address is in zero page
            byte addrLow  = CpuRead((UInt16)(t & 0x00FF));
            byte addrHigh = CpuRead((UInt16)((t + 1) & 0x00FF));

            address  = BitMagic.Combine(addrHigh, addrLow);
            address += Y;

            // if page is crossed
            if (Page(address) != Page((UInt16)(addrHigh << 8)))
            {
                return(true);
            }

            return(false);
        }
示例#11
0
        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);
        }
示例#12
0
        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);
        }
示例#13
0
 private void UpdateNegativeFlag(byte target)
 {
     Status.NegativeFlag = BitMagic.IsBitSet(target, 7);
 }
示例#14
0
        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;
            }
        }
示例#15
0
        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;
            }
        }