diff --git a/source/core/Nes_Core.h b/source/core/Nes_Core.h index 9409a49..e8ef183 100644 --- a/source/core/Nes_Core.h +++ b/source/core/Nes_Core.h @@ -1,16 +1,15 @@ +#pragma once // Internal NES emulator // Nes_Emu 0.7.0 -#ifndef NES_CORE_H -#define NES_CORE_H #include "blargg_common.h" #include "Nes_Apu.h" #include "Nes_Cpu.h" #include "Nes_Ppu.h" -class Nes_Mapper; +#include "Nes_Mapper.h" class Nes_Cart; class Nes_State; @@ -32,8 +31,8 @@ public: void irq_changed(); void event_changed(); - -public: private: friend class Nes_Emu; + +public: private: friend class Nes_Emu; struct impl_t { @@ -113,4 +112,133 @@ private: int mem_differs( void const* p, int cmp, unsigned long s ); -#endif +inline int Nes_Core::cpu_read( nes_addr_t addr, nes_time_t time ) +{ + //LOG_FREQ( "cpu_read", 16, addr >> 12 ); + + { + int result = cpu::low_mem [addr & 0x7FF]; + if ( !(addr & 0xE000) ) + return result; + } + + { + int result = *cpu::get_code( addr ); + if ( addr > 0x7FFF ) + return result; + } + + time += cpu_time_offset; + if ( addr < 0x4000 ) + return ppu.read( addr, time ); + + clock_ = time; + if ( data_reader_mapped [addr >> page_bits] ) + { + int result = mapper->read( time, addr ); + if ( result >= 0 ) + return result; + } + + if ( addr < 0x6000 ) + return read_io( addr ); + + if ( addr < sram_readable ) + return impl->sram [addr & (impl_t::sram_size - 1)]; + + if ( addr < lrom_readable ) + return *cpu::get_code( addr ); + + return addr >> 8; // simulate open bus +} + +inline int Nes_Core::cpu_read_ppu( nes_addr_t addr, nes_time_t time ) +{ + //LOG_FREQ( "cpu_read_ppu", 16, addr >> 12 ); + + // Read of status register (0x2002) is heavily optimized since many games + // poll it hundreds of times per frame. + nes_time_t next = ppu_2002_time; + int result = ppu.r2002; + if ( addr == 0x2002 ) + { + ppu.second_write = false; + if ( time >= next ) + result = ppu.read_2002( time + cpu_time_offset ); + } + else + { + result = cpu::low_mem [addr & 0x7FF]; + if ( addr >= 0x2000 ) + result = cpu_read( addr, time ); + } + + return result; +} + +inline void Nes_Core::cpu_write_2007( int data ) +{ + // ppu.write_2007() is inlined + if ( ppu.write_2007( data ) & Nes_Ppu::vaddr_clock_mask ) + mapper->a12_clocked(); +} + +inline void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) +{ + //LOG_FREQ( "cpu_write", 16, addr >> 12 ); + + if ( !(addr & 0xE000) ) + { + cpu::low_mem [addr & 0x7FF] = data; + return; + } + + time += cpu_time_offset; + if ( addr < 0x4000 ) + { + if ( (addr & 7) == 7 ) + cpu_write_2007( data ); + else + ppu.write( time, addr, data ); + return; + } + + clock_ = time; + if ( data_writer_mapped [addr >> page_bits] && mapper->write_intercepted( time, addr, data ) ) + return; + + if ( addr < 0x6000 ) + { + write_io( addr, data ); + return; + } + + if ( addr < sram_writable ) + { + impl->sram [addr & (impl_t::sram_size - 1)] = data; + return; + } + + if ( addr > 0x7FFF ) + { + mapper->write( clock_, addr, data ); + return; + } +} + +#define NES_CPU_READ_PPU( cpu, addr, time ) \ + STATIC_CAST(Nes_Core&,*cpu).cpu_read_ppu( addr, time ) + +#define NES_CPU_READ( cpu, addr, time ) \ + STATIC_CAST(Nes_Core&,*cpu).cpu_read( addr, time ) + +#define NES_CPU_WRITEX( cpu, addr, data, time ){\ + STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\ +} + +#define NES_CPU_WRITE( cpu, addr, data, time ){\ + if ( addr < 0x800 ) cpu->low_mem [addr] = data;\ + else if ( addr == 0x2007 ) STATIC_CAST(Nes_Core&,*cpu).cpu_write_2007( data );\ + else STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\ +} + diff --git a/source/core/Nes_Cpu.cpp b/source/core/Nes_Cpu.cpp index 4149d37..185b2d9 100644 --- a/source/core/Nes_Cpu.cpp +++ b/source/core/Nes_Cpu.cpp @@ -2,13 +2,11 @@ // Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/ #include "Nes_Cpu.h" - #include #include #include "blargg_endian.h" #include - -#include "nes_cpu_io.h" +#include /* Copyright (C) 2003-2006 Shay Green. This module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser