diff --git a/meson.build b/meson.build index b3f5d43..99bafa8 100644 --- a/meson.build +++ b/meson.build @@ -26,7 +26,6 @@ quickerNESCoreSrc = [ 'source/core/Nes_Cpu.cpp', 'source/core/Nes_State.cpp', 'source/core/emu2413.cpp', - 'source/core/nes_data.cpp', 'source/core/nes_util.cpp', 'source/core/emu2413_state.cpp', 'source/core/Nes_Effects_Buffer.cpp', diff --git a/source/core/Nes_Core.cpp b/source/core/Nes_Core.cpp index 5134de4..d9452ec 100644 --- a/source/core/Nes_Core.cpp +++ b/source/core/Nes_Core.cpp @@ -1,12 +1,4 @@ -// Nes_Emu 0.7.0. http://www.slack.net/~ant/ - -#include -#include -#include "Nes_Core.h" -#include "Nes_Mapper.h" -#include "Nes_State.h" - /* Copyright (C) 2004-2006 Shay Green. This module is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either @@ -17,9 +9,76 @@ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this module; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +// Nes_Emu 0.7.0. http://www.slack.net/~ant/ +#include +#include +#include "Nes_Core.h" +#include "Nes_Mapper.h" +#include "Nes_State.h" #include "blargg_source.h" +/* + New mapping distribution by Sergio Martin (eien86) + https://github.com/SergioMartin86/jaffarPlus +*/ +#include "mappers/mapper000.hpp" +#include "mappers/mapper001.hpp" +#include "mappers/mapper002.hpp" +#include "mappers/mapper003.hpp" +#include "mappers/mapper004.hpp" +#include "mappers/mapper005.hpp" +#include "mappers/mapper007.hpp" +#include "mappers/mapper009.hpp" +#include "mappers/mapper010.hpp" +#include "mappers/mapper011.hpp" +#include "mappers/mapper015.hpp" +#include "mappers/mapper019.hpp" +#include "mappers/mapper021.hpp" +#include "mappers/mapper022.hpp" +#include "mappers/mapper023.hpp" +#include "mappers/mapper024.hpp" +#include "mappers/mapper025.hpp" +#include "mappers/mapper026.hpp" +#include "mappers/mapper030.hpp" +#include "mappers/mapper032.hpp" +#include "mappers/mapper033.hpp" +#include "mappers/mapper034.hpp" +#include "mappers/mapper060.hpp" +#include "mappers/mapper066.hpp" +#include "mappers/mapper069.hpp" +#include "mappers/mapper070.hpp" +#include "mappers/mapper071.hpp" +#include "mappers/mapper073.hpp" +#include "mappers/mapper075.hpp" +#include "mappers/mapper078.hpp" +#include "mappers/mapper079.hpp" +#include "mappers/mapper085.hpp" +#include "mappers/mapper086.hpp" +#include "mappers/mapper087.hpp" +#include "mappers/mapper088.hpp" +#include "mappers/mapper089.hpp" +#include "mappers/mapper093.hpp" +#include "mappers/mapper094.hpp" +#include "mappers/mapper097.hpp" +#include "mappers/mapper113.hpp" +#include "mappers/mapper140.hpp" +#include "mappers/mapper152.hpp" +#include "mappers/mapper154.hpp" +#include "mappers/mapper156.hpp" +#include "mappers/mapper180.hpp" +#include "mappers/mapper184.hpp" +#include "mappers/mapper190.hpp" +#include "mappers/mapper193.hpp" +#include "mappers/mapper206.hpp" +#include "mappers/mapper207.hpp" +#include "mappers/mapper232.hpp" +#include "mappers/mapper240.hpp" +#include "mappers/mapper241.hpp" +#include "mappers/mapper244.hpp" +#include "mappers/mapper246.hpp" + + extern const char unsupported_mapper [] = "Unsupported mapper"; bool const wait_states_enabled = true; @@ -70,9 +129,79 @@ const char * Nes_Core::open( Nes_Cart const* new_cart ) RETURN_ERR( init() ); - mapper = Nes_Mapper::create( new_cart, this ); - if ( !mapper ) - return unsupported_mapper; + // Getting cartdrige mapper code + auto mapperCode = new_cart->mapper_code(); + + // Storage for the mapper, NULL by default + mapper = NULL; + + // Now checking if the detected mapper code is supported + if (mapperCode == 0) mapper = new Mapper000(); + if (mapperCode == 1) mapper = new Mapper001(); + if (mapperCode == 2) mapper = new Mapper002(); + if (mapperCode == 3) mapper = new Mapper003(); + if (mapperCode == 4) mapper = new Mapper004(); + if (mapperCode == 5) mapper = new Mapper005(); + if (mapperCode == 7) mapper = new Mapper007(); + if (mapperCode == 9) mapper = new Mapper009(); + if (mapperCode == 10) mapper = new Mapper010(); + if (mapperCode == 11) mapper = new Mapper011(); + if (mapperCode == 15) mapper = new Mapper015(); + if (mapperCode == 19) mapper = new Mapper019(); + if (mapperCode == 21) mapper = new Mapper021(); + if (mapperCode == 22) mapper = new Mapper022(); + if (mapperCode == 23) mapper = new Mapper023(); + if (mapperCode == 24) mapper = new Mapper024(); + if (mapperCode == 25) mapper = new Mapper025(); + if (mapperCode == 26) mapper = new Mapper026(); + if (mapperCode == 30) mapper = new Mapper030(); + if (mapperCode == 32) mapper = new Mapper032(); + if (mapperCode == 33) mapper = new Mapper033(); + if (mapperCode == 34) mapper = new Mapper034(); + if (mapperCode == 60) mapper = new Mapper060(); + if (mapperCode == 66) mapper = new Mapper066(); + if (mapperCode == 69) mapper = new Mapper069(); + if (mapperCode == 70) mapper = new Mapper070(); + if (mapperCode == 71) mapper = new Mapper071(); + if (mapperCode == 73) mapper = new Mapper073(); + if (mapperCode == 75) mapper = new Mapper075(); + if (mapperCode == 78) mapper = new Mapper078(); + if (mapperCode == 79) mapper = new Mapper079(); + if (mapperCode == 85) mapper = new Mapper085(); + if (mapperCode == 86) mapper = new Mapper086(); + if (mapperCode == 87) mapper = new Mapper087(); + if (mapperCode == 88) mapper = new Mapper088(); + if (mapperCode == 89) mapper = new Mapper089(); + if (mapperCode == 93) mapper = new Mapper093(); + if (mapperCode == 94) mapper = new Mapper094(); + if (mapperCode == 97) mapper = new Mapper097(); + if (mapperCode == 113) mapper = new Mapper113(); + if (mapperCode == 140) mapper = new Mapper140(); + if (mapperCode == 152) mapper = new Mapper152(); + if (mapperCode == 154) mapper = new Mapper154(); + if (mapperCode == 156) mapper = new Mapper156(); + if (mapperCode == 180) mapper = new Mapper180(); + if (mapperCode == 184) mapper = new Mapper184(); + if (mapperCode == 190) mapper = new Mapper190(); + if (mapperCode == 193) mapper = new Mapper193(); + if (mapperCode == 206) mapper = new Mapper206(); + if (mapperCode == 207) mapper = new Mapper207(); + if (mapperCode == 232) mapper = new Mapper232(); + if (mapperCode == 240) mapper = new Mapper240(); + if (mapperCode == 241) mapper = new Mapper241(); + if (mapperCode == 244) mapper = new Mapper244(); + if (mapperCode == 246) mapper = new Mapper246(); + + // If no mapper was found, return null (error) now + if (mapper == NULL) + { + fprintf(stderr, "Could not find mapper for code: %u\n", mapperCode); + return NULL; + } + + // Assigning backwards pointers to cartdrige and emulator now + mapper->setCartridge(new_cart); + mapper->setCore(this); RETURN_ERR( ppu.open_chr( new_cart->chr(), new_cart->chr_size() ) ); @@ -205,13 +334,6 @@ void Nes_Core::enable_sram( bool b, bool read_only ) } } -// Unmapped memory - - -void Nes_Core::log_unmapped( nes_addr_t addr, int data ) -{ -} - inline void Nes_Core::cpu_adjust_time( int n ) { ppu_2002_time -= n; @@ -273,10 +395,6 @@ void Nes_Core::write_io( nes_addr_t addr, int data ) } return; } - - #ifndef NDEBUG - log_unmapped( addr, data ); - #endif } int Nes_Core::read_io( nes_addr_t addr ) @@ -295,10 +413,6 @@ int Nes_Core::read_io( nes_addr_t addr ) if ( addr == Nes_Apu::status_addr ) return impl->apu.read_status( clock() ); - #ifndef NDEBUG - log_unmapped( addr ); - #endif - return addr >> 8; // simulate open bus } diff --git a/source/core/Nes_Core.h b/source/core/Nes_Core.h index 522b4f2..6189e0f 100644 --- a/source/core/Nes_Core.h +++ b/source/core/Nes_Core.h @@ -104,6 +104,7 @@ public: private: friend class Nes_Mapper; void add_mapper_intercept( nes_addr_t start, unsigned size, bool read, bool write ); public: private: friend class Nes_Cpu; + int cpu_read_ppu( nes_addr_t, nes_time_t ); int cpu_read( nes_addr_t, nes_time_t ); void cpu_write( nes_addr_t, int data, nes_time_t ); diff --git a/source/core/Nes_Cpu.cpp b/source/core/Nes_Cpu.cpp index 366f2a5..79b1f59 100644 --- a/source/core/Nes_Cpu.cpp +++ b/source/core/Nes_Cpu.cpp @@ -1,7 +1,4 @@ -// Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/ - - #include "Nes_Cpu.h" #include @@ -11,55 +8,17 @@ #include "nes_cpu_io.h" -/* 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 -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for -more details. You should have received a copy of the GNU Lesser General -Public License along with this module; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ -#include "blargg_source.h" - -inline void Nes_Cpu::set_code_page( int i, uint8_t const* p ) -{ - code_map [i] = p - (unsigned) i * page_size; +#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 );\ } -void Nes_Cpu::reset( void const* unmapped_page ) -{ - r.status = 0; - r.sp = 0; - r.pc = 0; - r.a = 0; - r.x = 0; - r.y = 0; - - error_count_ = 0; - clock_count = 0; - clock_limit = 0; - irq_time_ = LONG_MAX / 2 + 1; - end_time_ = LONG_MAX / 2 + 1; - - set_code_page( 0, low_mem ); - set_code_page( 1, low_mem ); - set_code_page( 2, low_mem ); - set_code_page( 3, low_mem ); - for ( int i = 4; i < page_count + 1; i++ ) - set_code_page( i, (uint8_t*) unmapped_page ); - - isCorrectExecution = true; -} - -void Nes_Cpu::map_code( nes_addr_t start, unsigned size, const void* data ) -{ - unsigned first_page = start / page_size; - for ( unsigned i = size / page_size; i--; ) - set_code_page( first_page + i, (uint8_t*) data + i * page_size ); -} // Note: 'addr' is evaulated more than once in the following macros, so it // must not contain side-effects. @@ -80,10 +39,6 @@ void Nes_Cpu::map_code( nes_addr_t start, unsigned size, const void* data ) #define GET_SP() ((sp - 1) & 0xFF) #define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v )) -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - int Nes_Cpu::read( nes_addr_t addr ) { return READ( addr ); diff --git a/source/core/Nes_Cpu.h b/source/core/Nes_Cpu.h index 6211913..071c482 100644 --- a/source/core/Nes_Cpu.h +++ b/source/core/Nes_Cpu.h @@ -1,6 +1,19 @@ // NES 6502 CPU emulator +// Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/ + +/* 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 +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for +more details. You should have received a copy of the GNU Lesser General +Public License along with this module; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ + // Nes_Emu 0.7.0 #ifndef NES_CPU_H @@ -14,15 +27,50 @@ typedef unsigned nes_addr_t; // 16-bit address class Nes_Cpu { public: + + inline void set_code_page( int i, uint8_t const* p ) + { + code_map [i] = p - (unsigned) i * page_size; + } + // Clear registers, unmap memory, and map code pages to unmapped_page. - void reset( void const* unmapped_page = 0 ); + void reset( void const* unmapped_page = 0 ) + { + r.status = 0; + r.sp = 0; + r.pc = 0; + r.a = 0; + r.x = 0; + r.y = 0; + + error_count_ = 0; + clock_count = 0; + clock_limit = 0; + irq_time_ = LONG_MAX / 2 + 1; + end_time_ = LONG_MAX / 2 + 1; + + set_code_page( 0, low_mem ); + set_code_page( 1, low_mem ); + set_code_page( 2, low_mem ); + set_code_page( 3, low_mem ); + for ( int i = 4; i < page_count + 1; i++ ) + set_code_page( i, (uint8_t*) unmapped_page ); + + isCorrectExecution = true; + } // Map code memory (memory accessed via the program counter). Start and size // must be multiple of page_size. static const uint8_t page_bits = 11; static const uint16_t page_count = 0x10000 >> page_bits; static const uint16_t page_size = 1L << page_bits; - void map_code( nes_addr_t start, unsigned size, void const* code ); + + void map_code( nes_addr_t start, unsigned size, void const* code ) + { + unsigned first_page = start / page_size; + for ( unsigned i = size / page_size; i--; ) + set_code_page( first_page + i, (uint8_t*) code + i * page_size ); + } // Access memory as the emulated CPU does. int read( nes_addr_t ); @@ -73,7 +121,6 @@ public: unsigned long error_count_; static const uint8_t irq_inhibit = 0x04; - void set_code_page( int, uint8_t const* ); void update_clock_limit(); registers_t r; diff --git a/source/core/Nes_Mapper.cpp b/source/core/Nes_Mapper.cpp index 051535a..d1b2a72 100644 --- a/source/core/Nes_Mapper.cpp +++ b/source/core/Nes_Mapper.cpp @@ -6,297 +6,8 @@ #include #include #include "Nes_Core.h" - -/* Copyright (C) 2004-2006 Shay Green. This module is free software; you -can redistribute it and/or modify it under the terms of the GNU Lesser -General Public License as published by the Free Software Foundation; either -version 2.1 of the License, or (at your option) any later version. This -module is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS -FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for -more details. You should have received a copy of the GNU Lesser General -Public License along with this module; if not, write to the Free Software -Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ - #include "blargg_source.h" -/* - New mapping distribution by Sergio Martin (eien86) - https://github.com/SergioMartin86/jaffarPlus -*/ -#include "mappers/mapper000.hpp" -#include "mappers/mapper001.hpp" -#include "mappers/mapper002.hpp" -#include "mappers/mapper003.hpp" -#include "mappers/mapper004.hpp" -#include "mappers/mapper005.hpp" -#include "mappers/mapper007.hpp" -#include "mappers/mapper009.hpp" -#include "mappers/mapper010.hpp" -#include "mappers/mapper011.hpp" -#include "mappers/mapper015.hpp" -#include "mappers/mapper019.hpp" -#include "mappers/mapper021.hpp" -#include "mappers/mapper022.hpp" -#include "mappers/mapper023.hpp" -#include "mappers/mapper024.hpp" -#include "mappers/mapper025.hpp" -#include "mappers/mapper026.hpp" -#include "mappers/mapper030.hpp" -#include "mappers/mapper032.hpp" -#include "mappers/mapper033.hpp" -#include "mappers/mapper034.hpp" -#include "mappers/mapper060.hpp" -#include "mappers/mapper066.hpp" -#include "mappers/mapper069.hpp" -#include "mappers/mapper070.hpp" -#include "mappers/mapper071.hpp" -#include "mappers/mapper073.hpp" -#include "mappers/mapper075.hpp" -#include "mappers/mapper078.hpp" -#include "mappers/mapper079.hpp" -#include "mappers/mapper085.hpp" -#include "mappers/mapper086.hpp" -#include "mappers/mapper087.hpp" -#include "mappers/mapper088.hpp" -#include "mappers/mapper089.hpp" -#include "mappers/mapper093.hpp" -#include "mappers/mapper094.hpp" -#include "mappers/mapper097.hpp" -#include "mappers/mapper113.hpp" -#include "mappers/mapper140.hpp" -#include "mappers/mapper152.hpp" -#include "mappers/mapper154.hpp" -#include "mappers/mapper156.hpp" -#include "mappers/mapper180.hpp" -#include "mappers/mapper184.hpp" -#include "mappers/mapper190.hpp" -#include "mappers/mapper193.hpp" -#include "mappers/mapper206.hpp" -#include "mappers/mapper207.hpp" -#include "mappers/mapper232.hpp" -#include "mappers/mapper240.hpp" -#include "mappers/mapper241.hpp" -#include "mappers/mapper244.hpp" -#include "mappers/mapper246.hpp" - -Nes_Mapper::Nes_Mapper() -{ - emu_ = NULL; - static char c; - state = &c; // TODO: state must not be null? - state_size = 0; -} - -Nes_Mapper::~Nes_Mapper() -{ -} - -// Sets mirroring, maps first 8K CHR in, first and last 16K of PRG, -// intercepts writes to upper half of memory, and clears registered state. -void Nes_Mapper::default_reset_state() -{ - int mirroring = cart_->mirroring(); - if ( mirroring & 8 ) - mirror_full(); - else if ( mirroring & 1 ) - mirror_vert(); - else - mirror_horiz(); - - set_chr_bank( 0, bank_8k, 0 ); - - set_prg_bank( 0x8000, bank_16k, 0 ); - set_prg_bank( 0xC000, bank_16k, last_bank ); - - intercept_writes( 0x8000, 0x8000 ); - - memset( state, 0, state_size ); -} - -void Nes_Mapper::reset() -{ - default_reset_state(); - reset_state(); - apply_mapping(); -} - -void mapper_state_t::write( const void* p, unsigned long s ) -{ - size = s; - memcpy( data, p, s ); -} - -int mapper_state_t::read( void* p, unsigned long s ) const -{ - if ( (long) s > size ) - s = size; - memcpy( p, data, s ); - return s; -} - -void Nes_Mapper::save_state( mapper_state_t& out ) -{ - out.write( state, state_size ); -} - -void Nes_Mapper::load_state( mapper_state_t const& in ) -{ - default_reset_state(); - read_state( in ); - apply_mapping(); -} - -void Nes_Mapper::read_state( mapper_state_t const& in ) -{ - memset( state, 0, state_size ); - in.read( state, state_size ); - apply_mapping(); -} - -// Timing - -void Nes_Mapper::irq_changed() { emu_->irq_changed(); } - -nes_time_t Nes_Mapper::next_irq( nes_time_t ) { return no_irq; } - -void Nes_Mapper::a12_clocked() { } - -void Nes_Mapper::run_until( nes_time_t ) { } - -void Nes_Mapper::end_frame( nes_time_t ) { } - -bool Nes_Mapper::ppu_enabled() const { return emu().ppu.w2001 & 0x08; } - -// Sound - -int Nes_Mapper::channel_count() const { return 0; } - -void Nes_Mapper::set_channel_buf( int, Blip_Buffer* ) { } - -void Nes_Mapper::set_treble( blip_eq_t const& ) { } // Memory mapping -void Nes_Mapper::set_prg_bank( nes_addr_t addr, bank_size_t bs, int bank ) -{ - int bank_size = 1 << bs; - - int bank_count = cart_->prg_size() >> bs; - if ( bank < 0 ) - bank += bank_count; - - if ( bank >= bank_count ) - bank %= bank_count; - - emu().map_code( addr, bank_size, cart_->prg() + (bank << bs) ); - - if ( unsigned (addr - 0x6000) < 0x2000 ) - emu().enable_prg_6000(); -} - -void Nes_Mapper::set_chr_bank( nes_addr_t addr, bank_size_t bs, int bank ) -{ - emu().ppu.render_until( emu().clock() ); - emu().ppu.set_chr_bank( addr, 1 << bs, bank << bs ); -} - -void Nes_Mapper::set_chr_bank_ex( nes_addr_t addr, bank_size_t bs, int bank ) -{ - emu().ppu.render_until( emu().clock() ); - emu().ppu.set_chr_bank_ex( addr, 1 << bs, bank << bs ); -} - -void Nes_Mapper::mirror_manual( int page0, int page1, int page2, int page3 ) -{ - emu().ppu.render_bg_until( emu().clock() ); - emu().ppu.set_nt_banks( page0, page1, page2, page3 ); -} - -#ifndef NDEBUG -int Nes_Mapper::handle_bus_conflict( nes_addr_t addr, int data ) -{ - return data; -} -#endif - - -Nes_Mapper* Nes_Mapper::create( Nes_Cart const* cart, Nes_Core* emu ) -{ - // Getting cartdrige mapper code - auto mapperCode = cart->mapper_code(); - - // Storage for the mapper, NULL by default - Nes_Mapper* mapper = NULL; - - // Now checking if the detected mapper code is supported - if (mapperCode == 0) mapper = new Mapper000(); - if (mapperCode == 1) mapper = new Mapper001(); - if (mapperCode == 2) mapper = new Mapper002(); - if (mapperCode == 3) mapper = new Mapper003(); - if (mapperCode == 4) mapper = new Mapper004(); - if (mapperCode == 5) mapper = new Mapper005(); - if (mapperCode == 7) mapper = new Mapper007(); - if (mapperCode == 9) mapper = new Mapper009(); - if (mapperCode == 10) mapper = new Mapper010(); - if (mapperCode == 11) mapper = new Mapper011(); - if (mapperCode == 15) mapper = new Mapper015(); - if (mapperCode == 19) mapper = new Mapper019(); - if (mapperCode == 21) mapper = new Mapper021(); - if (mapperCode == 22) mapper = new Mapper022(); - if (mapperCode == 23) mapper = new Mapper023(); - if (mapperCode == 24) mapper = new Mapper024(); - if (mapperCode == 25) mapper = new Mapper025(); - if (mapperCode == 26) mapper = new Mapper026(); - if (mapperCode == 30) mapper = new Mapper030(); - if (mapperCode == 32) mapper = new Mapper032(); - if (mapperCode == 33) mapper = new Mapper033(); - if (mapperCode == 34) mapper = new Mapper034(); - if (mapperCode == 60) mapper = new Mapper060(); - if (mapperCode == 66) mapper = new Mapper066(); - if (mapperCode == 69) mapper = new Mapper069(); - if (mapperCode == 70) mapper = new Mapper070(); - if (mapperCode == 71) mapper = new Mapper071(); - if (mapperCode == 73) mapper = new Mapper073(); - if (mapperCode == 75) mapper = new Mapper075(); - if (mapperCode == 78) mapper = new Mapper078(); - if (mapperCode == 79) mapper = new Mapper079(); - if (mapperCode == 85) mapper = new Mapper085(); - if (mapperCode == 86) mapper = new Mapper086(); - if (mapperCode == 87) mapper = new Mapper087(); - if (mapperCode == 88) mapper = new Mapper088(); - if (mapperCode == 89) mapper = new Mapper089(); - if (mapperCode == 93) mapper = new Mapper093(); - if (mapperCode == 94) mapper = new Mapper094(); - if (mapperCode == 97) mapper = new Mapper097(); - if (mapperCode == 113) mapper = new Mapper113(); - if (mapperCode == 140) mapper = new Mapper140(); - if (mapperCode == 152) mapper = new Mapper152(); - if (mapperCode == 154) mapper = new Mapper154(); - if (mapperCode == 156) mapper = new Mapper156(); - if (mapperCode == 180) mapper = new Mapper180(); - if (mapperCode == 184) mapper = new Mapper184(); - if (mapperCode == 190) mapper = new Mapper190(); - if (mapperCode == 193) mapper = new Mapper193(); - if (mapperCode == 206) mapper = new Mapper206(); - if (mapperCode == 207) mapper = new Mapper207(); - if (mapperCode == 232) mapper = new Mapper232(); - if (mapperCode == 240) mapper = new Mapper240(); - if (mapperCode == 241) mapper = new Mapper241(); - if (mapperCode == 244) mapper = new Mapper244(); - if (mapperCode == 246) mapper = new Mapper246(); - - // If no mapper was found, return null (error) now - if (mapper == NULL) - { - fprintf(stderr, "Could not find mapper for code: %u\n", mapperCode); - return NULL; - } - - // Assigning backwards pointers to cartdrige and emulator now - mapper->cart_ = cart; - mapper->emu_ = emu; - - // Returning successfully created mapper - return mapper; -} diff --git a/source/core/Nes_Mapper.h b/source/core/Nes_Mapper.h index 45e949c..022cb2b 100644 --- a/source/core/Nes_Mapper.h +++ b/source/core/Nes_Mapper.h @@ -1,15 +1,27 @@ +#pragma once // NES mapper interface +/* Copyright (C) 2004-2006 Shay Green. This module is free software; you +can redistribute it and/or modify it under the terms of the GNU Lesser +General Public License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. This +module is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS +FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for +more details. You should have received a copy of the GNU Lesser General +Public License along with this module; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ // Nes_Emu 0.7.0 -#ifndef NES_MAPPER -#define NES_MAPPER - #include "Nes_Cart.h" #include "Nes_Cpu.h" #include "nes_data.h" #include "Nes_Core.h" +#include +#include +#include "blargg_source.h" + class Blip_Buffer; class blip_eq_t; class Nes_Core; @@ -23,30 +35,43 @@ public: // Register optional mappers included with Nes_Emu void register_optional_mappers(); - // Create mapper appropriate for cartridge. Returns NULL if it uses unsupported mapper. - static Nes_Mapper* create( Nes_Cart const*, Nes_Core* ); - - virtual ~Nes_Mapper(); + virtual ~Nes_Mapper() = default; // Reset mapper to power-up state. - virtual void reset(); + virtual inline void reset() + { + default_reset_state(); + reset_state(); + apply_mapping(); + } // Save snapshot of mapper state. Default saves registered state. - virtual void save_state( mapper_state_t& ); + virtual inline void save_state( mapper_state_t& out ) + { + out.write( state, state_size ); + } // Resets mapper, loads state, then applies it - virtual void load_state( mapper_state_t const& ); + virtual inline void load_state( mapper_state_t const& in ) + { + default_reset_state(); + read_state( in ); + apply_mapping(); + } + + void setCartridge(const Nes_Cart* cart) { cart_ = cart; } + void setCore(Nes_Core* core) { emu_ = core; } // I/O // Read from memory - virtual int read( nes_time_t, nes_addr_t ); + virtual inline int read( nes_time_t, nes_addr_t ) { return -1; } ; // Write to memory virtual void write( nes_time_t, nes_addr_t, int data ) = 0; // Write to memory below 0x8000 (returns false if mapper didn't handle write) - virtual bool write_intercepted( nes_time_t, nes_addr_t, int data ); + virtual inline bool write_intercepted( nes_time_t, nes_addr_t, int data ) { return false; } // Timing @@ -54,53 +79,66 @@ public: enum { no_irq = LONG_MAX / 2 }; // Time next IRQ will occur at - virtual nes_time_t next_irq( nes_time_t present ); + virtual inline nes_time_t next_irq( nes_time_t present ) { return no_irq; }; // Run mapper until given time - virtual void run_until( nes_time_t ); + virtual inline void run_until( nes_time_t ) { }; // End video frame of given length - virtual void end_frame( nes_time_t length ); - + virtual inline void end_frame( nes_time_t length ) { }; + // Sound // Number of sound channels - virtual int channel_count() const; + virtual inline int channel_count() const { return 0; }; // Set sound buffer for channel to output to, or NULL to silence channel. - virtual void set_channel_buf( int index, Blip_Buffer* ); + virtual inline void set_channel_buf( int index, Blip_Buffer* ) { }; // Set treble equalization - virtual void set_treble( blip_eq_t const& ); - + virtual inline void set_treble( blip_eq_t const& ) { }; + // Misc // Called when bit 12 of PPU's VRAM address changes from 0 to 1 due to // $2006 and $2007 accesses (but not due to PPU scanline rendering). - virtual void a12_clocked(); + virtual inline void a12_clocked() {}; protected: // Services provided for derived mapper classes - Nes_Mapper(); + Nes_Mapper() + { + emu_ = NULL; + static char c; + state = &c; // TODO: state must not be null? + state_size = 0; + } // Register state data to automatically save and load. Be sure the binary // layout is suitable for use in a file, including any byte-order issues. // Automatically cleared to zero by default reset(). - void register_state( void*, unsigned ); + inline void register_state(void* p, unsigned s) + { + state = p; + state_size = s; + } // Enable 8K of RAM at 0x6000-0x7FFF, optionally read-only. - void enable_sram( bool enabled = true, bool read_only = false ); + inline void enable_sram( bool enabled = true, bool read_only = false ) { emu_->enable_sram( enabled, read_only ); } // Cause CPU writes within given address range to call mapper's write() function. // Might map a larger address range, which the mapper can ignore and pass to // Nes_Mapper::write(). The range 0x8000-0xffff is always intercepted by the mapper. - void intercept_writes( nes_addr_t addr, unsigned size ); + inline void intercept_writes( nes_addr_t addr, unsigned size ) { emu().add_mapper_intercept( addr, size, false, true ); } // Cause CPU reads within given address range to call mapper's read() function. // Might map a larger address range, which the mapper can ignore and pass to // Nes_Mapper::read(). CPU opcode/operand reads and low-memory reads always // go directly to memory and cannot be intercepted. - void intercept_reads( nes_addr_t addr, unsigned size ); + inline void intercept_reads( nes_addr_t addr, unsigned size ) + { + emu().add_mapper_intercept( addr, size, true, false ); + } // Bank sizes for mapping enum bank_size_t { // 1 << bank_Xk = X * 1024 @@ -117,22 +155,51 @@ protected: enum { last_bank = -1 }; // Map 'size' bytes from 'PRG + bank * size' to CPU address space starting at 'addr' - void set_prg_bank( nes_addr_t addr, bank_size_t size, int bank ); - + void set_prg_bank( nes_addr_t addr, bank_size_t bs, int bank ) + { + int bank_size = 1 << bs; + + int bank_count = cart_->prg_size() >> bs; + if ( bank < 0 ) + bank += bank_count; + + if ( bank >= bank_count ) + bank %= bank_count; + + emu().map_code( addr, bank_size, cart_->prg() + (bank << bs) ); + + if ( unsigned (addr - 0x6000) < 0x2000 ) + emu().enable_prg_6000(); + } + // Map 'size' bytes from 'CHR + bank * size' to PPU address space starting at 'addr' - void set_chr_bank( nes_addr_t addr, bank_size_t size, int bank ); - void set_chr_bank_ex( nes_addr_t addr, bank_size_t size, int bank ); + inline void set_chr_bank( nes_addr_t addr, bank_size_t bs, int bank ) + { + emu().ppu.render_until( emu().clock() ); + emu().ppu.set_chr_bank( addr, 1 << bs, bank << bs ); + } + + inline void set_chr_bank_ex( nes_addr_t addr, bank_size_t bs, int bank ) + { + emu().ppu.render_until( emu().clock() ); + emu().ppu.set_chr_bank_ex( addr, 1 << bs, bank << bs ); + } // Set PPU mirroring. All mappings implemented using mirror_manual(). - void mirror_manual( int page0, int page1, int page2, int page3 ); - void mirror_single( int page ); - void mirror_horiz( int page = 0 ); - void mirror_vert( int page = 0 ); - void mirror_full(); + inline void mirror_manual( int page0, int page1, int page2, int page3 ) + { + emu().ppu.render_bg_until( emu().clock() ); + emu().ppu.set_nt_banks( page0, page1, page2, page3 ); + } + + inline void mirror_horiz( int p = 0) { mirror_manual( p, p, p ^ 1, p ^ 1 ); } + inline void mirror_vert( int p = 0 ) { mirror_manual( p, p ^ 1, p, p ^ 1 ); } + inline void mirror_single( int p ) { mirror_manual( p, p, p, p ); } + inline void mirror_full() { mirror_manual( 0, 1, 2, 3 ); } // True if PPU rendering is enabled. Some mappers watch PPU memory accesses to determine // when scanlines occur, and can only do this when rendering is enabled. - bool ppu_enabled() const; + inline bool ppu_enabled() const { return emu().ppu.w2001 & 0x08; } // Cartridge being emulated Nes_Cart const& cart() const { return *cart_; } @@ -140,13 +207,13 @@ protected: // Must be called when next_irq()'s return value is earlier than previous, // current CPU run can be stopped earlier. Best to call whenever time may // have changed (no performance impact if called even when time didn't change). - void irq_changed(); + inline void irq_changed() { emu_->irq_changed(); } // Handle data written to mapper that doesn't handle bus conflict arising due to // PRG also reading data. Returns data that mapper should act as if were // written. Currently always returns 'data' and just checks that data written is // the same as byte in PRG at same address and writes debug message if it doesn't. - int handle_bus_conflict( nes_addr_t addr, int data ); + int handle_bus_conflict( nes_addr_t addr, int data ) { return data; } // Reference to emulator that uses this mapper. Nes_Core& emu() const { return *emu_; } @@ -156,7 +223,12 @@ protected: // Read state from snapshot. Default reads data into registered state, then calls // apply_mapping(). - virtual void read_state( mapper_state_t const& ); + inline void read_state( mapper_state_t const& in ) + { + memset( state, 0, state_size ); + in.read( state, state_size ); + apply_mapping(); + } // Apply current mapping state to hardware. Called after reading mapper state // from a snapshot. @@ -172,42 +244,26 @@ private: unsigned state_size; Nes_Cart const* cart_; - void default_reset_state(); + // Sets mirroring, maps first 8K CHR in, first and last 16K of PRG, + // intercepts writes to upper half of memory, and clears registered state. + inline void default_reset_state() + { + int mirroring = cart_->mirroring(); + if ( mirroring & 8 ) + mirror_full(); + else if ( mirroring & 1 ) + mirror_vert(); + else + mirror_horiz(); + + set_chr_bank( 0, bank_8k, 0 ); + + set_prg_bank( 0x8000, bank_16k, 0 ); + set_prg_bank( 0xC000, bank_16k, last_bank ); + + intercept_writes( 0x8000, 0x8000 ); + + memset( state, 0, state_size ); + } }; - -#ifdef NDEBUG -inline int Nes_Mapper::handle_bus_conflict( nes_addr_t addr, int data ) { return data; } -#endif - -inline void Nes_Mapper::mirror_horiz( int p ) { mirror_manual( p, p, p ^ 1, p ^ 1 ); } -inline void Nes_Mapper::mirror_vert( int p ) { mirror_manual( p, p ^ 1, p, p ^ 1 ); } -inline void Nes_Mapper::mirror_single( int p ) { mirror_manual( p, p, p, p ); } -inline void Nes_Mapper::mirror_full() { mirror_manual( 0, 1, 2, 3 ); } - -inline void Nes_Mapper::register_state( void* p, unsigned s ) -{ - state = p; - state_size = s; -} - -inline bool Nes_Mapper::write_intercepted( nes_time_t, nes_addr_t, int ) { return false; } - -inline int Nes_Mapper::read( nes_time_t, nes_addr_t ) { return -1; } // signal to caller - -inline void Nes_Mapper::intercept_reads( nes_addr_t addr, unsigned size ) -{ - emu().add_mapper_intercept( addr, size, true, false ); -} - -inline void Nes_Mapper::intercept_writes( nes_addr_t addr, unsigned size ) -{ - emu().add_mapper_intercept( addr, size, false, true ); -} - -inline void Nes_Mapper::enable_sram( bool enabled, bool read_only ) -{ - emu_->enable_sram( enabled, read_only ); -} - -#endif diff --git a/source/core/Nes_Ppu_Impl.cpp b/source/core/Nes_Ppu_Impl.cpp index 90dd383..3a34505 100644 --- a/source/core/Nes_Ppu_Impl.cpp +++ b/source/core/Nes_Ppu_Impl.cpp @@ -37,14 +37,6 @@ Nes_Ppu_Impl::Nes_Ppu_Impl() mmc24_enabled = false; mmc24_latched[0] = 0; mmc24_latched[1] = 0; - - #if !defined(NDEBUG) && !defined(PSP) && !defined(PS2) - // verify that unaligned accesses work - static unsigned char b [19] = { 0 }; - static unsigned char b2 [19] = { 1,2,3,4,0,5,6,7,8,0,9,0,1,2,0,3,4,5,6 }; - for ( int i = 0; i < 19; i += 5 ) - *(volatile uint32_t*) &b [i] = *(volatile uint32_t*) &b2 [i]; - #endif } Nes_Ppu_Impl::~Nes_Ppu_Impl() diff --git a/source/core/Nes_Ppu_Rendering.cpp b/source/core/Nes_Ppu_Rendering.cpp index ab7d546..46dd340 100644 --- a/source/core/Nes_Ppu_Rendering.cpp +++ b/source/core/Nes_Ppu_Rendering.cpp @@ -20,16 +20,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "blargg_source.h" -#ifdef BLARGG_ENABLE_OPTIMIZER - #include BLARGG_ENABLE_OPTIMIZER -#endif - -#ifdef __MWERKS__ - static unsigned zero = 0; // helps CodeWarrior optimizer when added to constants -#else - const unsigned zero = 0; // compile-time constant on other compilers -#endif - // Nes_Ppu_Impl inline Nes_Ppu_Impl::cached_tile_t const& @@ -188,8 +178,8 @@ void Nes_Ppu_Rendering::draw_background_( int remain ) uint8_t* pixels = row_pixels; row_pixels += height * row_bytes; - unsigned long const mask = 0x03030303 + zero; - unsigned long const attrib_factor = 0x04040404 + zero; + unsigned long const mask = 0x03030303; + unsigned long const attrib_factor = 0x04040404; const int fine_y = (height == 8) ? 0 : addr >> 12; const int clipped = (height == 8) ? false : true; @@ -373,7 +363,7 @@ void Nes_Ppu_Rendering::check_sprite_hit( int begin, int end ) } // check each line - unsigned long const mask = 0x01010101 + zero; + unsigned long const mask = 0x01010101; do { // get pixels for line diff --git a/source/core/Nes_Ppu_Sprites.h b/source/core/Nes_Ppu_Sprites.h index 8d936f3..f5d438c 100644 --- a/source/core/Nes_Ppu_Sprites.h +++ b/source/core/Nes_Ppu_Sprites.h @@ -27,8 +27,8 @@ if ( sprite_2 & 0x80 ) // attributes unsigned long offset = (sprite_2 & 3) * 0x04040404 + (this->palette_offset + 0x10101010); -unsigned long const mask = 0x03030303 + zero; -unsigned long const maskgen = 0x80808080 + zero; +unsigned long const mask = 0x03030303; +unsigned long const maskgen = 0x80808080; #define DRAW_PAIR( shift ) { \ int sprite_count = *scanlines; \ @@ -48,7 +48,7 @@ unsigned long const maskgen = 0x80808080 + zero; if ( !(sprite_2 & 0x20) ) { // front - unsigned long const maskgen2 = 0x7f7f7f7f + zero; + unsigned long const maskgen2 = 0x7f7f7f7f; #define CALC_FOUR( in, line, out ) \ unsigned long out; \ @@ -88,8 +88,8 @@ if ( !(sprite_2 & 0x20) ) else { // behind - unsigned long const omask = 0x20202020 + zero; - unsigned long const bg_or = 0xc3c3c3c3 + zero; + unsigned long const omask = 0x20202020; + unsigned long const bg_or = 0xc3c3c3c3; #define CALC_FOUR( in, line, out ) \ unsigned long out; \ diff --git a/source/core/apu_state.h b/source/core/apu_state.h index 5cfed75..56fd3a9 100644 --- a/source/core/apu_state.h +++ b/source/core/apu_state.h @@ -8,6 +8,7 @@ #include #include "blargg_common.h" +#include "blargg_endian.h" struct apu_state_t { @@ -70,7 +71,19 @@ struct apu_state_t //uint8_t length_counters [4]; enum { tag = 0x41505552 }; // 'APUR' - void swap(); + void swap() + { + SWAP_LE( apu.frame_delay ); + SWAP_LE( square1.delay ); + SWAP_LE( square2.delay ); + SWAP_LE( triangle.delay ); + SWAP_LE( noise.delay ); + SWAP_LE( noise.shift_reg ); + SWAP_LE( dmc.delay ); + SWAP_LE( dmc.remain ); + SWAP_LE( dmc.addr ); + } + }; BOOST_STATIC_ASSERT( sizeof (apu_state_t) == 72 ); diff --git a/source/core/blargg_endian.h b/source/core/blargg_endian.h index f5f1567..2d221c0 100644 --- a/source/core/blargg_endian.h +++ b/source/core/blargg_endian.h @@ -105,4 +105,7 @@ inline void set_be( uint32_t* p, unsigned long n ) { SET_BE32( p, n ); } inline unsigned get_be( uint16_t* p ) { return GET_BE16( p ); } inline unsigned long get_be( uint32_t* p ) { return GET_BE32( p ); } +#define SWAP_BE( n ) (void) (set_be( &(n), (n) )) +#define SWAP_LE( n ) (void) (set_le( &(n), (n) )) + #endif diff --git a/source/core/nes_cpu_io.h b/source/core/nes_cpu_io.h index bf02c9e..de14094 100644 --- a/source/core/nes_cpu_io.h +++ b/source/core/nes_cpu_io.h @@ -41,10 +41,6 @@ int Nes_Core::cpu_read( nes_addr_t addr, nes_time_t time ) if ( addr < lrom_readable ) return *cpu::get_code( addr ); - #ifndef NDEBUG - log_unmapped( addr ); - #endif - return addr >> 8; // simulate open bus } @@ -79,7 +75,7 @@ void Nes_Core::cpu_write_2007( int data ) mapper->a12_clocked(); } -void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) +inline void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) { //LOG_FREQ( "cpu_write", 16, addr >> 12 ); @@ -120,24 +116,4 @@ void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) mapper->write( clock_, addr, data ); return; } - - #ifndef NDEBUG - log_unmapped( addr, data ); - #endif -} - -#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_data.h b/source/core/nes_data.h index 97059ba..655f143 100644 --- a/source/core/nes_data.h +++ b/source/core/nes_data.h @@ -6,8 +6,10 @@ #ifndef NES_DATA_H #define NES_DATA_H +#include "blargg_endian.h" #include "blargg_common.h" #include "apu_state.h" +#include typedef long nes_tag_t; @@ -48,8 +50,13 @@ struct nes_block_t uint32_t tag; // ** stored in big-endian uint32_t size; - void swap(); + inline void swap() + { + SWAP_BE( tag ); + SWAP_LE( size ); + } }; + BOOST_STATIC_ASSERT( sizeof (nes_block_t) == 8 ); unsigned long const group_begin_size = 0xffffffff; // group block has this size @@ -63,8 +70,13 @@ struct nes_state_t uint32_t frame_count; // number of frames emulated since power-up enum { tag = FOUR_CHAR('TIME') }; - void swap(); + inline void swap() + { + SWAP_LE( timestamp ); + SWAP_LE( frame_count ); + } }; + BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 ); struct joypad_state_t @@ -74,7 +86,12 @@ struct joypad_state_t uint8_t unused [3]; enum { tag = FOUR_CHAR('CTRL') }; - void swap(); + inline void swap() + { + SWAP_LE( joypad_latches [0] ); + SWAP_LE( joypad_latches [1] ); + } + }; BOOST_STATIC_ASSERT( sizeof (joypad_state_t) == 12 ); @@ -89,8 +106,18 @@ struct mapper_state_t uint8_t data [max_mapper_state_size]; }; - void write( const void* p, unsigned long s ); - int read( void* p, unsigned long s ) const; + inline void write( const void* p, unsigned long s ) + { + size = s; + memcpy( data, p, s ); + } + + inline int read( void* p, unsigned long s ) const + { + if ( (long) s > size )s = size; + memcpy( p, data, s ); + return s; + } }; struct cpu_state_t @@ -104,8 +131,12 @@ struct cpu_state_t uint8_t unused [1]; enum { tag = FOUR_CHAR('CPUR') }; - void swap(); + inline void swap() + { + SWAP_LE( pc ); + } }; + BOOST_STATIC_ASSERT( sizeof (cpu_state_t) == 8 ); struct ppu_state_t @@ -127,8 +158,15 @@ struct ppu_state_t uint8_t unused2[3]; enum { tag = FOUR_CHAR('PPUR') }; - void swap(); + void swap() + { + SWAP_LE( vram_addr ); + SWAP_LE( vram_temp ); + SWAP_LE( decay_low ); + SWAP_LE( decay_high ); + } }; + BOOST_STATIC_ASSERT( sizeof (ppu_state_t) == 20 + 0x20 ); struct mmc1_state_t diff --git a/tests/games/rcProAMII/anyPercent.sol b/tests/games/rcProAMII/anyPercent.sol deleted file mode 100644 index e69de29..0000000