Esempio n. 1
0
        public PPU(CPU cpu)
        {
            this.cpu   = cpu;
            latch      = 0;
            frameCount = 0;
            tReg       = new LoopyRegister();
            vReg       = new LoopyRegister();

            // Two adjacent 16 * 16 2D arrays of 8 * 8 tiles. Used only for testing
            PatternMemory = new Color[2, (16 * 8), (16 * 8)];

#if LOGGING
            //CSV log - file creation
            csvLogs     = new DirectoryInfo(@"/Users/alexwright/Documents/MSc Files/Project/csv_logs");
            dateTime    = DateTime.UtcNow;
            cultInfo    = CultureInfo.CreateSpecificCulture("en-UK");
            csvFileName = $"project_nes_ppu_log_{dateTime.ToString("o", cultInfo)}.csv";
            filePath    = $"{csvLogs.FullName}/{csvFileName}";
            using (File.Create(filePath)) { }

            using (StreamWriter file = new StreamWriter(filePath, true))
                file.WriteLine(
                    $"frameCount," +
                    $"scanLine," +
                    $"cycle," +
                    $"vReg.Address," +
                    $"read(address)," +
                    $"ppuData," +
                    $"patternShifterHi," +
                    $"patternShifterLo," +
                    $"attribShifterHi," +
                    $"attribShifterLo," +
                    $"tileID," +
                    $"tileAttrib," +
                    $"tileMSB," +
                    $"tileLSB"
                    );
#endif
        }
Esempio n. 2
0
        public void WriteDataFromBus(uint address, byte data)
        {
            switch (address)
            {
            case 0x2000:     // Control
                registerControl      = data;
                registerT.NameTableX = HasControlFlag(Control.NameTableX) ? (byte)1 : (byte)0;
                registerT.NameTableY = HasControlFlag(Control.NameTableY) ? (byte)1 : (byte)0;
                spriteSize           = HasControlFlag(Control.SpriteSize) ? (byte)16 : (byte)8;
                return;

            case 0x2001:     // Mask
                registerMask = data;
                return;

            case 0x2002:     // Status (read-only)
                return;

            case 0x2003:     // OAM Address
                oamAddress = data;
                return;

            case 0x2004:     // OAM Data
                mainOAM[oamAddress++] = data;
                return;

            case 0x2005:     // Scroll
                if (!byteLatch)
                {
                    fineX             = (byte)(data & 0x07);
                    registerT.CoarseX = (byte)(data >> 3);
                }
                else
                {
                    registerT.FineY   = (byte)(data & 0x07);
                    registerT.CoarseY = (byte)(data >> 3);
                }
                byteLatch = !byteLatch;
                return;

            case 0x2006:     // PPU Address
                if (!byteLatch)
                {
                    registerT.Reg = (ushort)((registerT.Reg & 0x00FF) | (data << 8));
                }
                else
                {
                    registerT.Reg = (ushort)((registerT.Reg & 0xFF00) | data);
                    registerV     = registerT;
                }

                byteLatch = !byteLatch;
                return;

            case 0x2007:     // PPU Data
                WritePPUData(registerV.Reg, data);
                if (registerV.Reg >= 0x3F00 && registerV.Reg <= 0x3F03)
                {
                    patternTableDisplay[0].DataChanged();
                    patternTableDisplay[1].DataChanged();
                }
                registerV.Reg += (ushort)(HasControlFlag(Control.IncrementMode) ? 32 : 1);
                return;
            }
        }
Esempio n. 3
0
        public void CpuWrite(ushort address, byte data)
        {
            switch (address)
            {
            case 0x0000:     // Control
                _control.reg = data;
                _tRamAddress.SetFlag(LoopyRegister.Flags.NameTableX, _control.GetFlag(Control.Flags.NameTableX));
                _tRamAddress.SetFlag(LoopyRegister.Flags.NameTableY, _control.GetFlag(Control.Flags.NameTableY));
                break;

            case 0x0001:     // Mask
                _mask.reg = data;
                break;

            case 0x0002:     // Status
                break;

            case 0x0003:     // OAM Address
                break;

            case 0x0004:     // OAM Data
                break;

            case 0x0005:     // Scroll
                if (_addressLatch == 0)
                {
                    _fineX = (byte)(data & 0x07);
                    _tRamAddress.SetCoarseX((byte)(data >> 3));
                    _ppuAddress   = (ushort)((_ppuAddress & 0xFF00) | data << 8);
                    _addressLatch = 1;
                }
                else
                {
                    _tRamAddress.SetFineY((byte)(data & 0x07));
                    _tRamAddress.SetCoarseY((byte)(data >> 3));
                    _addressLatch = 0;
                }
                break;

            case 0x0006:     // PPU Address
                if (_addressLatch == 0)
                {
                    _tRamAddress.reg = (ushort)((data & 0x3F) << 8 | _tRamAddress.reg & 0x00FF);
                    _addressLatch    = 1;
                }
                else
                {
                    _tRamAddress.reg = (ushort)(_tRamAddress.reg & 0xFF00 | data);
                    _vRamAddress     = _tRamAddress;
                    _addressLatch    = 0;
                }
                break;

            case 0x0007:     // PPU Data
                PpuWrite(_vRamAddress.reg, data);
                var inclementModeFlagValue = _control.GetFlag(Control.Flags.IncrementMode);
                if (inclementModeFlagValue)
                {
                    _vRamAddress.reg += 1;
                }
                else
                {
                    _vRamAddress.reg += 32;
                }
                break;
            }
        }