Пример #1
0
        static void Main(string[] args)
        {
            var memory = Cpu6502Compiler.Compile("main.s");

            var memManager = new MemoryManager(memory);
            var obs        = new OutputObserver();

            memManager.RegisterObserver(obs);

            var cpu = new Cpu6502(memManager);

            cpu.Reset();

            Console.WriteLine();
        }
Пример #2
0
        public NesBus()
        {
            Devices = new List<IResetableDevice>();

            // Connect devices
            Cpu6502 = new Cpu6502();
            Cpu6502.ConnectBus(this);
            Devices.Add(Cpu6502);

            Ppu2C02 = new Ppu2C02();
            Ppu2C02.ConnectBus(this);
            Devices.Add(Ppu2C02);

            Apu2A03 = new Apu2A03();
            Apu2A03.ConnectBus(this);
            Devices.Add(Apu2A03);

            // init 2k RAM
            Ram = Enumerable.Repeat((byte)0, 2 * 1024).ToList();

            // Controlers
            Controller = new byte[] { 0x00, 0x00 };
            ControllerState = new byte[] { 0x00, 0x00 };
        }
Пример #3
0
        public bool Clock()
        {
            // Clocking. The heart and soul of an emulator. The running
            // frequency is controlled by whatever calls this function.
            // So here we "divide" the clock as necessary and call
            // the peripheral devices clock() function at the correct
            // times.

            // The fastest clock frequency the digital system cares
            // about is equivalent to the PPU clock. So the PPU is clocked
            // each time this function is called...
            Ppu2C02.Clock();

            // ...also clock the APU
            Apu2A03.Clock();

            // The CPU runs 3 times slower than the PPU so we only call its
            // clock() function every 3 times this function is called. We
            // have a global counter to keep track of this.
            if (SystemClockCounter % 3 == 0)
            {
                // Is the system performing a DMA transfer form CPU memory to 
                // OAM memory on PPU?...
                if (dma_transfer)
                {
                    // ...Yes! We need to wait until the next even CPU clock cycle
                    // before it starts...
                    if (dma_dummy)
                    {
                        // ...So hang around in here each clock until 1 or 2 cycles
                        // have elapsed...
                        if (SystemClockCounter % 2 == 1)
                        {
                            // ...and finally allow DMA to start
                            dma_dummy = false;
                        }
                    }
                    else
                    {
                        // DMA can take place!
                        if (SystemClockCounter % 2 == 0)
                        {
                            // On even clock cycles, read from CPU bus
                            dma_data = CpuRead((ushort)(dma_page << 8 | dma_addr), false);
                        }
                        else
                        {
                            // On odd clock cycles, write to PPU OAM
                            Ppu2C02.OAM[dma_addr] = dma_data;
                            // Increment the lo byte of the address
                            dma_addr++;
                            // If this wraps around, we know that 256
                            // bytes have been written, so end the DMA
                            // transfer, and proceed as normal
                            if (dma_addr == 0x00)
                            {
                                dma_transfer = false;
                                dma_dummy = true;
                            }
                        }
                    }
                }
                else
                {
                    // No DMA happening, the CPU is in control of its
                    // own destiny. Go forth my friend and calculate
                    // awesomeness for many generations to come...
                    Cpu6502.Clock();
                }
            }

            // Synchronising with Audio
            bool bAudioSampleReady = false;
            dAudioTime += dAudioTimePerNESClock;
            if (dAudioTime >= dAudioTimePerSystemSample)
            {
                dAudioTime -= dAudioTimePerSystemSample;
                dAudioSample = Apu2A03.GetOutputSample();
                bAudioSampleReady = true;
            }


            // The PPU is capable of emitting an interrupt to indicate the
            // vertical blanking period has been entered. If it has, we need
            // to send that irq to the CPU.
            if (Ppu2C02.Nmi)
            {
                Ppu2C02.Nmi = false;
                Cpu6502.NMI();
            }

            // Check if cartridge is requesting IRQ
            if (Cartridge.GetMapper().IrqState)
            {
                Cartridge.GetMapper().IrqClear();
                Cpu6502.IRQ();
            }

            SystemClockCounter++;

            return bAudioSampleReady;
        }
Пример #4
0
 public Register(Cpu6502 cpu)
 {
     _cpu  = new(cpu);
     Value = 0;
 }