From 66e6632eea557ea75c2ad2d2f140f0c84f59018d Mon Sep 17 00:00:00 2001 From: Sergio Martin Date: Sat, 13 Jan 2024 18:42:59 +0100 Subject: [PATCH] Reverting changes back to 0c8318e26e8d8e3d1f9bec295890fb70de2ef5b5 since some of those commits did something that affected performance --- meson.build | 3 +- source/core/Data_Reader.cpp | 40 ++++- source/core/Data_Reader.h | 31 +--- source/core/Nes_Buffer.cpp | 2 +- source/core/Nes_Buffer.h | 4 +- source/core/Nes_Core.cpp | 179 ++++-------------- source/core/Nes_Core.h | 1 - source/core/Nes_Cpu.cpp | 73 +++++++- source/core/Nes_Cpu.h | 65 +------ source/core/Nes_Emu.h | 12 +- source/core/Nes_Fme7_Apu.h | 2 +- source/core/Nes_Mapper.cpp | 289 ++++++++++++++++++++++++++++++ source/core/Nes_Mapper.h | 208 ++++++++------------- source/core/Nes_Namco_Apu.h | 2 +- source/core/Nes_Ppu.cpp | 6 +- source/core/Nes_Ppu_Bg.h | 68 +++++++ source/core/Nes_Ppu_Impl.cpp | 8 + source/core/Nes_Ppu_Rendering.cpp | 112 ++++-------- source/core/Nes_Ppu_Sprites.h | 10 +- source/core/Nes_Vrc7.h | 2 +- source/core/abstract_file.cpp | 2 + source/core/apu_state.h | 15 +- source/core/blargg_common.h | 3 + source/core/blargg_config.h | 17 ++ source/core/blargg_endian.h | 3 - source/core/blargg_source.h | 5 + source/core/nes_cpu_io.h | 26 ++- source/core/nes_data.cpp | 66 +++++++ source/core/nes_data.h | 52 +----- source/core/nes_ntsc.h | 38 ++-- source/core/nes_ntsc_impl.h | 10 +- tests/games/benchmark0.txt | 76 ++++---- 32 files changed, 833 insertions(+), 597 deletions(-) create mode 100644 source/core/Nes_Ppu_Bg.h create mode 100644 source/core/blargg_config.h create mode 100644 source/core/nes_data.cpp diff --git a/meson.build b/meson.build index 99bafa8..85bd2d3 100644 --- a/meson.build +++ b/meson.build @@ -26,6 +26,7 @@ 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', @@ -40,7 +41,7 @@ quickerNESCoreSrc = [ # quickerNES Core Configuration quickerNESCoreDependency = declare_dependency( - compile_args : [ '-Wfatal-errors', '-Wall', '-Werror', '-Wno-multichar', '-DBLARGG_NONPORTABLE'], + compile_args : [ '-Wfatal-errors', '-Wall', '-Wno-multichar' ], include_directories : include_directories(['source', 'source/core', 'extern']), sources : [ quickerNESCoreSrc, 'extern/metrohash128/metrohash128.cpp' ] ) diff --git a/source/core/Data_Reader.cpp b/source/core/Data_Reader.cpp index b90be5d..cb366a3 100644 --- a/source/core/Data_Reader.cpp +++ b/source/core/Data_Reader.cpp @@ -1,7 +1,7 @@ // File_Extractor 1.0.0. http://www.slack.net/~ant/ -#include #include "Data_Reader.h" + #include "blargg_endian.h" #include @@ -20,7 +20,7 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ // Data_Reader -const char * Data_Reader::read( void* p, size_t n ) +const char * Data_Reader::read( void* p, int n ) { if ( n < 0 ) return "Internal usage bug"; @@ -38,20 +38,52 @@ const char * Data_Reader::read( void* p, size_t n ) return err; } +const char * Data_Reader::read_avail( void* p, int* n_ ) +{ + int n = min( (uint64_t)(*n_), remain() ); + *n_ = 0; + + if ( n < 0 ) + return "Internal usage bug"; + + if ( n <= 0 ) + return 0; + + const char * err = read_v( p, n ); + if ( !err ) + { + remain_ -= n; + *n_ = n; + } + + return err; +} + +const char * Data_Reader::read_avail( void* p, long* n ) +{ + int i = STATIC_CAST(int, *n); + const char * err = read_avail( p, &i ); + *n = i; + return err; +} + const char * Data_Reader::skip_v( int count ) { char buf [512]; while ( count ) { - int n = std::min( count, (int) sizeof buf ); + int n = min( count, (int) sizeof buf ); count -= n; RETURN_ERR( read_v( buf, n ) ); } return 0; } -const char * Data_Reader::skip( size_t n ) +const char * Data_Reader::skip( int n ) { + if ( n < 0 ) + return "Internal usage bug"; + if ( n <= 0 ) return 0; diff --git a/source/core/Data_Reader.h b/source/core/Data_Reader.h index 6c5b3c9..110108c 100644 --- a/source/core/Data_Reader.h +++ b/source/core/Data_Reader.h @@ -4,10 +4,8 @@ #ifndef DATA_READER_H #define DATA_READER_H -#include -#include +#include #include "blargg_common.h" -#include "blargg_source.h" /* Some functions accept a long instead of int for convenience where caller has a long due to some other interface, and would otherwise have to get a warning, @@ -24,33 +22,18 @@ public: // Reads min(*n,remain()) bytes and sets *n to this number, thus trying to read more // tham remain() bytes doesn't result in error, just *n being set to remain(). - const char * read_avail( void* p, size_t* count ) - { - int n = std::min(*count, remain()); - *count = 0; - - if ( n <= 0 ) - return 0; - - const char * err = read_v( p, n ); - if ( !err ) - { - remain_ -= n; - *count = n; - } - - return err; - } + const char * read_avail( void* p, int* n ); + const char * read_avail( void* p, long* n ); // Reads exactly n bytes, or returns error if they couldn't ALL be read. // Reading past end of file results in blargg_err_file_eof. - const char * read( void* p, size_t n ); + const char * read( void* p, int n ); // Number of bytes remaining until end of file - size_t remain() const { return remain_; } + uint64_t remain() const { return remain_; } // Reads and discards n bytes. Skipping past end of file results in blargg_err_file_eof. - const char * skip( size_t n ); + const char * skip( int n ); virtual ~Data_Reader() { } @@ -64,7 +47,7 @@ protected: Data_Reader() : remain_( 0 ) { } // Sets remain - void set_remain( size_t n ) { remain_ = n; } + void set_remain( uint64_t n ) { remain_ = n; } // Do same as read(). Guaranteed that 0 < n <= remain(). Value of remain() is updated // AFTER this call succeeds, not before. set_remain() should NOT be called from this. diff --git a/source/core/Nes_Buffer.cpp b/source/core/Nes_Buffer.cpp index c0979df..731e05a 100644 --- a/source/core/Nes_Buffer.cpp +++ b/source/core/Nes_Buffer.cpp @@ -163,7 +163,7 @@ Nes_Nonlinearizer::Nes_Nonlinearizer() float const gain = 0x7fff * 1.3f; // don't use entire range, so any overflow will stay within table int const range = (int) (table_size * Nes_Apu::nonlinear_tnd_gain()); - for (uint32_t i = 0; i < table_size; i++ ) + for ( int i = 0; i < table_size; i++ ) { int const offset = table_size - range; int j = i - offset; diff --git a/source/core/Nes_Buffer.h b/source/core/Nes_Buffer.h index f7a64f4..6d70fe4 100644 --- a/source/core/Nes_Buffer.h +++ b/source/core/Nes_Buffer.h @@ -11,8 +11,8 @@ class Nes_Apu; class Nes_Nonlinearizer { private: - static const uint8_t table_bits = 11; - static const uint32_t table_size = 1 << table_bits; + enum { table_bits = 11 }; + enum { table_size = 1 << table_bits }; int16_t table [table_size]; Nes_Apu* apu; long accum; diff --git a/source/core/Nes_Core.cpp b/source/core/Nes_Core.cpp index d9452ec..cf62b8a 100644 --- a/source/core/Nes_Core.cpp +++ b/source/core/Nes_Core.cpp @@ -1,4 +1,12 @@ +// Nes_Emu 0.7.0. http://www.slack.net/~ant/ + +#include "Nes_Core.h" + +#include +#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 @@ -9,76 +17,9 @@ 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; @@ -129,79 +70,9 @@ const char * Nes_Core::open( Nes_Cart const* new_cart ) RETURN_ERR( init() ); - // 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); + mapper = Nes_Mapper::create( new_cart, this ); + if ( !mapper ) + return unsupported_mapper; RETURN_ERR( ppu.open_chr( new_cart->chr(), new_cart->chr_size() ) ); @@ -296,7 +167,7 @@ void Nes_Core::load_state( Nes_State_ const& in ) if ( in.sram_size ) { sram_present = true; - memcpy( impl->sram, in.sram, std::min( (int) in.sram_size, (int) sizeof impl->sram ) ); + memcpy( impl->sram, in.sram, min( (int) in.sram_size, (int) sizeof impl->sram ) ); enable_sram( true ); // mapper can override (read-only, unmapped, etc.) } @@ -334,6 +205,16 @@ void Nes_Core::enable_sram( bool b, bool read_only ) } } +// Unmapped memory + +#ifndef NDEBUG +static nes_addr_t last_unmapped_addr; +#endif + +void Nes_Core::log_unmapped( nes_addr_t addr, int data ) +{ +} + inline void Nes_Core::cpu_adjust_time( int n ) { ppu_2002_time -= n; @@ -395,6 +276,10 @@ 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 ) @@ -413,6 +298,10 @@ 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 } @@ -484,7 +373,7 @@ void Nes_Core::vector_interrupt( nes_addr_t vector ) inline nes_time_t Nes_Core::earliest_irq( nes_time_t present ) { - return std::min( impl->apu.earliest_irq( present ), mapper->next_irq( present ) ); + return min( impl->apu.earliest_irq( present ), mapper->next_irq( present ) ); } void Nes_Core::irq_changed() @@ -509,13 +398,13 @@ inline nes_time_t Nes_Core::earliest_event( nes_time_t present ) // DMC if ( wait_states_enabled ) - t = std::min( t, impl->apu.next_dmc_read_time() + 1 ); + t = min( t, impl->apu.next_dmc_read_time() + 1 ); // NMI - t = std::min( t, ppu.nmi_time() ); + t = min( t, ppu.nmi_time() ); if ( single_instruction_mode ) - t = std::min( t, present + 1 ); + t = min( t, present + 1 ); return t; } diff --git a/source/core/Nes_Core.h b/source/core/Nes_Core.h index 6189e0f..522b4f2 100644 --- a/source/core/Nes_Core.h +++ b/source/core/Nes_Core.h @@ -104,7 +104,6 @@ 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 79b1f59..6be300e 100644 --- a/source/core/Nes_Cpu.cpp +++ b/source/core/Nes_Cpu.cpp @@ -1,4 +1,15 @@ +// Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/ + +// TODO: remove +#if !defined (NDEBUG) && 0 + #pragma peephole on + #pragma global_optimizer on + #pragma optimization_level 4 + #pragma scheduling 604 + #undef BLARGG_ENABLE_OPTIMIZER +#endif + #include "Nes_Cpu.h" #include @@ -8,17 +19,59 @@ #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 */ -#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 );\ +#include "blargg_source.h" + +#ifdef BLARGG_ENABLE_OPTIMIZER + #include BLARGG_ENABLE_OPTIMIZER +#endif + +inline void Nes_Cpu::set_code_page( int i, uint8_t const* p ) +{ + code_map [i] = p - (unsigned) i * page_size; } +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. @@ -39,6 +92,10 @@ #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 071c482..1284d84 100644 --- a/source/core/Nes_Cpu.h +++ b/source/core/Nes_Cpu.h @@ -1,19 +1,6 @@ // 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 @@ -27,50 +14,15 @@ 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 ) - { - 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 reset( void const* unmapped_page = 0 ); // 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 ) - { - 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 ); - } + enum { page_bits = 11 }; + enum { page_count = 0x10000 >> page_bits }; + enum { page_size = 1L << page_bits }; + void map_code( nes_addr_t start, unsigned size, void const* code ); // Access memory as the emulated CPU does. int read( nes_addr_t ); @@ -108,10 +60,10 @@ public: unsigned long error_count() const { return error_count_; } // If PC exceeds 0xFFFF and encounters page_wrap_opcode, it will be silently wrapped. - static const uint8_t page_wrap_opcode = 0xF2; + enum { page_wrap_opcode = 0xF2 }; // One of the many opcodes that are undefined and stop CPU emulation. - static const uint8_t bad_opcode = 0xD2; + enum { bad_opcode = 0xD2 }; uint8_t const* code_map [page_count + 1]; nes_time_t clock_limit; @@ -120,7 +72,8 @@ public: nes_time_t end_time_; unsigned long error_count_; - static const uint8_t irq_inhibit = 0x04; + enum { irq_inhibit = 0x04 }; + void set_code_page( int, uint8_t const* ); void update_clock_limit(); registers_t r; diff --git a/source/core/Nes_Emu.h b/source/core/Nes_Emu.h index 948b179..f4fb5d1 100644 --- a/source/core/Nes_Emu.h +++ b/source/core/Nes_Emu.h @@ -62,7 +62,7 @@ public: struct frame_t { static const uint8_t left = 8; - + int joypad_read_count; // number of times joypads were strobed (read) int burst_phase; // NTSC burst phase for frame (0, 1, or 2) @@ -162,10 +162,10 @@ public: // Graphics // Number of frames generated per second - static const uint16_t frame_rate = 60; + enum { frame_rate = 60 }; // Size of fixed NES color table (including the 8 color emphasis modes) - static const uint16_t color_table_size = 8 * 64; + enum { color_table_size = 8 * 64 }; // NES color lookup table based on standard NTSC TV decoder. Use nes_ntsc.h to // generate a palette with custom parameters. @@ -183,7 +183,7 @@ public: // Set range of host palette entries to use in graphics buffer; default uses // all of them. Begin will be rounded up to next multiple of palette_alignment. // Use frame().palette_begin to find the adjusted beginning entry used. - static const uint8_t palette_alignment = 64; + enum { palette_alignment = 64 }; void set_palette_range( int begin, int end = 256 ); // Access to emulated memory, for viewer/cheater/debugger @@ -198,11 +198,11 @@ public: long nametable_size() const { return 0x1000; } // Built-in 2K memory - static const uint16_t low_mem_size = 0x800; + enum { low_mem_size = 0x800 }; uint8_t* low_mem() { return emu.low_mem; } // Optional 8K memory - static const uint16_t high_mem_size = 0x2000; + enum { high_mem_size = 0x2000 }; uint8_t* high_mem() { return emu.impl->sram; } // End of public interface diff --git a/source/core/Nes_Fme7_Apu.h b/source/core/Nes_Fme7_Apu.h index 507d98b..79d714b 100644 --- a/source/core/Nes_Fme7_Apu.h +++ b/source/core/Nes_Fme7_Apu.h @@ -60,7 +60,7 @@ private: } oscs [osc_count]; blip_time_t last_time; - static const uint8_t amp_range = 192; // can be any value; this gives best error/quality tradeoff + enum { amp_range = 192 }; // can be any value; this gives best error/quality tradeoff Blip_Synth synth; void run_until( blip_time_t ); diff --git a/source/core/Nes_Mapper.cpp b/source/core/Nes_Mapper.cpp index d1b2a72..051535a 100644 --- a/source/core/Nes_Mapper.cpp +++ b/source/core/Nes_Mapper.cpp @@ -6,8 +6,297 @@ #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 022cb2b..45e949c 100644 --- a/source/core/Nes_Mapper.h +++ b/source/core/Nes_Mapper.h @@ -1,27 +1,15 @@ -#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; @@ -35,43 +23,30 @@ public: // Register optional mappers included with Nes_Emu void register_optional_mappers(); - virtual ~Nes_Mapper() = default; + // Create mapper appropriate for cartridge. Returns NULL if it uses unsupported mapper. + static Nes_Mapper* create( Nes_Cart const*, Nes_Core* ); + + virtual ~Nes_Mapper(); // Reset mapper to power-up state. - virtual inline void reset() - { - default_reset_state(); - reset_state(); - apply_mapping(); - } + virtual void reset(); // Save snapshot of mapper state. Default saves registered state. - virtual inline void save_state( mapper_state_t& out ) - { - out.write( state, state_size ); - } + virtual void save_state( mapper_state_t& ); // Resets mapper, loads state, then applies it - 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; } + virtual void load_state( mapper_state_t const& ); // I/O // Read from memory - virtual inline int read( nes_time_t, nes_addr_t ) { return -1; } ; + virtual int read( nes_time_t, nes_addr_t ); // 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 inline bool write_intercepted( nes_time_t, nes_addr_t, int data ) { return false; } + virtual bool write_intercepted( nes_time_t, nes_addr_t, int data ); // Timing @@ -79,66 +54,53 @@ public: enum { no_irq = LONG_MAX / 2 }; // Time next IRQ will occur at - virtual inline nes_time_t next_irq( nes_time_t present ) { return no_irq; }; + virtual nes_time_t next_irq( nes_time_t present ); // Run mapper until given time - virtual inline void run_until( nes_time_t ) { }; + virtual void run_until( nes_time_t ); // End video frame of given length - virtual inline void end_frame( nes_time_t length ) { }; - + virtual void end_frame( nes_time_t length ); + // Sound // Number of sound channels - virtual inline int channel_count() const { return 0; }; + virtual int channel_count() const; // Set sound buffer for channel to output to, or NULL to silence channel. - virtual inline void set_channel_buf( int index, Blip_Buffer* ) { }; + virtual void set_channel_buf( int index, Blip_Buffer* ); // Set treble equalization - virtual inline void set_treble( blip_eq_t const& ) { }; - + virtual 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 inline void a12_clocked() {}; + virtual void a12_clocked(); protected: // Services provided for derived mapper classes - Nes_Mapper() - { - emu_ = NULL; - static char c; - state = &c; // TODO: state must not be null? - state_size = 0; - } + Nes_Mapper(); // 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(). - inline void register_state(void* p, unsigned s) - { - state = p; - state_size = s; - } + void register_state( void*, unsigned ); // Enable 8K of RAM at 0x6000-0x7FFF, optionally read-only. - inline void enable_sram( bool enabled = true, bool read_only = false ) { emu_->enable_sram( enabled, read_only ); } + void enable_sram( bool enabled = true, bool read_only = false ); // 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. - inline void intercept_writes( nes_addr_t addr, unsigned size ) { emu().add_mapper_intercept( addr, size, false, true ); } + void intercept_writes( nes_addr_t addr, unsigned size ); // 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. - inline void intercept_reads( nes_addr_t addr, unsigned size ) - { - emu().add_mapper_intercept( addr, size, true, false ); - } + void intercept_reads( nes_addr_t addr, unsigned size ); // Bank sizes for mapping enum bank_size_t { // 1 << bank_Xk = X * 1024 @@ -155,51 +117,22 @@ 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 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 set_prg_bank( nes_addr_t addr, bank_size_t size, int bank ); + // Map 'size' bytes from 'CHR + bank * size' to PPU address space starting at 'addr' - 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 ); - } + 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 ); // Set PPU mirroring. All mappings implemented using mirror_manual(). - 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 ); } + 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(); // 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. - inline bool ppu_enabled() const { return emu().ppu.w2001 & 0x08; } + bool ppu_enabled() const; // Cartridge being emulated Nes_Cart const& cart() const { return *cart_; } @@ -207,13 +140,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). - inline void irq_changed() { emu_->irq_changed(); } + void 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 ) { return data; } + int handle_bus_conflict( nes_addr_t addr, int data ); // Reference to emulator that uses this mapper. Nes_Core& emu() const { return *emu_; } @@ -223,12 +156,7 @@ protected: // Read state from snapshot. Default reads data into registered state, then calls // apply_mapping(). - inline void read_state( mapper_state_t const& in ) - { - memset( state, 0, state_size ); - in.read( state, state_size ); - apply_mapping(); - } + virtual void read_state( mapper_state_t const& ); // Apply current mapping state to hardware. Called after reading mapper state // from a snapshot. @@ -244,26 +172,42 @@ private: unsigned state_size; Nes_Cart const* cart_; - // 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 ); - } + void default_reset_state(); }; + +#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_Namco_Apu.h b/source/core/Nes_Namco_Apu.h index 6e76784..6f793f0 100644 --- a/source/core/Nes_Namco_Apu.h +++ b/source/core/Nes_Namco_Apu.h @@ -20,7 +20,7 @@ public: void volume( double ); void treble_eq( const blip_eq_t& ); void output( Blip_Buffer* ); - static const uint8_t osc_count = 8; + enum { osc_count = 8 }; void osc_output( int index, Blip_Buffer* ); void reset(); void end_frame( nes_time_t ); diff --git a/source/core/Nes_Ppu.cpp b/source/core/Nes_Ppu.cpp index 4380bf1..d2fcf8e 100644 --- a/source/core/Nes_Ppu.cpp +++ b/source/core/Nes_Ppu.cpp @@ -3,9 +3,9 @@ // Nes_Emu 0.7.0. http://www.slack.net/~ant/ -#include -#include #include "Nes_Ppu.h" + +#include #include "Nes_State.h" #include "Nes_Mapper.h" #include "Nes_Core.h" @@ -272,7 +272,7 @@ void Nes_Ppu::update_sprite_hit( nes_time_t cpu_time ) if ( count_needed > 240 ) count_needed = 240; while ( scanline_count < count_needed ) - render_bg_until( std::max( cpu_time, next_bg_time + 1 ) ); + render_bg_until( max( cpu_time, next_bg_time + 1 ) ); if ( sprite_hit_found < 0 ) return; // sprite won't hit diff --git a/source/core/Nes_Ppu_Bg.h b/source/core/Nes_Ppu_Bg.h new file mode 100644 index 0000000..81e1eb3 --- /dev/null +++ b/source/core/Nes_Ppu_Bg.h @@ -0,0 +1,68 @@ +while ( true ) +{ + while ( count-- ) + { + int attrib = attr_table [addr >> 2 & 0x07]; + attrib >>= (addr >> 4 & 4) | (addr & 2); + unsigned long offset = (attrib & 3) * attrib_factor + this->palette_offset; + + // draw one tile + cache_t const* lines = this->get_bg_tile( nametable [addr] + bg_bank ); + uint8_t* p = pixels; + addr++; + pixels += 8; // next tile + + if ( !clipped ) + { + // optimal case: no clipping + for ( int n = 4; n--; ) + { + unsigned long line = *lines++; + ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; + ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; + p += row_bytes; + ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; + ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; + p += row_bytes; + } + } + else + { + lines += fine_y >> 1; + + if ( fine_y & 1 ) + { + unsigned long line = *lines++; + ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; + ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; + p += row_bytes; + } + + for ( int n = height >> 1; n--; ) + { + unsigned long line = *lines++; + ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; + ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; + p += row_bytes; + ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; + ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; + p += row_bytes; + } + + if ( height & 1 ) + { + unsigned long line = *lines; + ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; + ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; + } + } + } + + count = count2; + count2 = 0; + addr -= 32; + attr_table = attr_table - nametable + nametable2; + nametable = nametable2; + if ( !count ) + break; +} diff --git a/source/core/Nes_Ppu_Impl.cpp b/source/core/Nes_Ppu_Impl.cpp index 3a34505..90dd383 100644 --- a/source/core/Nes_Ppu_Impl.cpp +++ b/source/core/Nes_Ppu_Impl.cpp @@ -37,6 +37,14 @@ 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 46dd340..2abef34 100644 --- a/source/core/Nes_Ppu_Rendering.cpp +++ b/source/core/Nes_Ppu_Rendering.cpp @@ -3,9 +3,8 @@ #include "Nes_Ppu_Rendering.h" -#include -#include -#include +#include +#include /* 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 @@ -20,6 +19,16 @@ 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& @@ -178,83 +187,26 @@ void Nes_Ppu_Rendering::draw_background_( int remain ) uint8_t* pixels = row_pixels; row_pixels += height * row_bytes; - unsigned long const mask = 0x03030303; - unsigned long const attrib_factor = 0x04040404; + unsigned long const mask = 0x03030303 + zero; + unsigned long const attrib_factor = 0x04040404 + zero; - const int fine_y = (height == 8) ? 0 : addr >> 12; - const int clipped = (height == 8) ? false : true; - addr &= 0x03ff; - if (height == 8) height -= fine_y & 1; - - while ( true ) + if ( height == 8 ) { - while ( count-- ) - { - int attrib = attr_table [addr >> 2 & 0x07]; - attrib >>= (addr >> 4 & 4) | (addr & 2); - unsigned long offset = (attrib & 3) * attrib_factor + this->palette_offset; - - // draw one tile - cache_t const* lines = this->get_bg_tile( nametable [addr] + bg_bank ); - uint8_t* p = pixels; - addr++; - pixels += 8; // next tile - - if ( !clipped ) - { - // optimal case: no clipping - for ( int n = 4; n--; ) - { - unsigned long line = *lines++; - ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; - ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; - p += row_bytes; - ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; - ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; - p += row_bytes; - } - } - else - { - lines += fine_y >> 1; - - if ( fine_y & 1 ) - { - unsigned long line = *lines++; - ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; - ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; - p += row_bytes; - } - - for ( int n = height >> 1; n--; ) - { - unsigned long line = *lines++; - ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; - ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; - p += row_bytes; - ((unaligned_uint32_t*) p) [0].val = (line >> 6 & mask) + offset; - ((unaligned_uint32_t*) p) [1].val = (line >> 2 & mask) + offset; - p += row_bytes; - } - - if ( height & 1 ) - { - unsigned long line = *lines; - ((unaligned_uint32_t*) p) [0].val = (line >> 4 & mask) + offset; - ((unaligned_uint32_t*) p) [1].val = (line & mask) + offset; - } - } - } - - count = count2; - count2 = 0; - addr -= 32; - attr_table = attr_table - nametable + nametable2; - nametable = nametable2; - if ( !count ) - break; + // unclipped + addr &= 0x03ff; + int const fine_y = 0; + int const clipped = false; + #include "Nes_Ppu_Bg.h" + } + else + { + // clipped + int const fine_y = addr >> 12; + addr &= 0x03ff; + height -= fine_y & 1; + int const clipped = true; + #include "Nes_Ppu_Bg.h" } - } while ( remain ); } @@ -363,7 +315,7 @@ void Nes_Ppu_Rendering::check_sprite_hit( int begin, int end ) } // check each line - unsigned long const mask = 0x01010101; + unsigned long const mask = 0x01010101 + zero; do { // get pixels for line @@ -500,8 +452,8 @@ void Nes_Ppu_Rendering::draw_background( int start, int count ) { // not rendering, but still handle sprite hit using mini graphics buffer int y = spr_ram [0] + 1; - int skip = std::min( count, std::max( y - start, 0 ) ); - int visible = std::min( count - skip, sprite_height() ); + int skip = min( count, max( y - start, 0 ) ); + int visible = min( count - skip, sprite_height() ); if ( visible > 0 ) { diff --git a/source/core/Nes_Ppu_Sprites.h b/source/core/Nes_Ppu_Sprites.h index f5d438c..8d936f3 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; -unsigned long const maskgen = 0x80808080; +unsigned long const mask = 0x03030303 + zero; +unsigned long const maskgen = 0x80808080 + zero; #define DRAW_PAIR( shift ) { \ int sprite_count = *scanlines; \ @@ -48,7 +48,7 @@ unsigned long const maskgen = 0x80808080; if ( !(sprite_2 & 0x20) ) { // front - unsigned long const maskgen2 = 0x7f7f7f7f; + unsigned long const maskgen2 = 0x7f7f7f7f + zero; #define CALC_FOUR( in, line, out ) \ unsigned long out; \ @@ -88,8 +88,8 @@ if ( !(sprite_2 & 0x20) ) else { // behind - unsigned long const omask = 0x20202020; - unsigned long const bg_or = 0xc3c3c3c3; + unsigned long const omask = 0x20202020 + zero; + unsigned long const bg_or = 0xc3c3c3c3 + zero; #define CALC_FOUR( in, line, out ) \ unsigned long out; \ diff --git a/source/core/Nes_Vrc7.h b/source/core/Nes_Vrc7.h index 018d229..ee10c06 100644 --- a/source/core/Nes_Vrc7.h +++ b/source/core/Nes_Vrc7.h @@ -20,7 +20,7 @@ public: void volume( double ); void treble_eq( blip_eq_t const& ); void output( Blip_Buffer* ); - static const uint8_t osc_count = 6; + enum { osc_count = 6 }; void osc_output( int index, Blip_Buffer* ); void end_frame( nes_time_t ); void save_snapshot(vrc7_snapshot_t*); diff --git a/source/core/abstract_file.cpp b/source/core/abstract_file.cpp index 0280032..417cf8f 100644 --- a/source/core/abstract_file.cpp +++ b/source/core/abstract_file.cpp @@ -1,6 +1,8 @@ #include "abstract_file.h" +#include "blargg_config.h" + #include #include diff --git a/source/core/apu_state.h b/source/core/apu_state.h index 56fd3a9..5cfed75 100644 --- a/source/core/apu_state.h +++ b/source/core/apu_state.h @@ -8,7 +8,6 @@ #include #include "blargg_common.h" -#include "blargg_endian.h" struct apu_state_t { @@ -71,19 +70,7 @@ struct apu_state_t //uint8_t length_counters [4]; enum { tag = 0x41505552 }; // 'APUR' - 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 ); - } - + void swap(); }; BOOST_STATIC_ASSERT( sizeof (apu_state_t) == 72 ); diff --git a/source/core/blargg_common.h b/source/core/blargg_common.h index 60dcf3e..413fd6b 100644 --- a/source/core/blargg_common.h +++ b/source/core/blargg_common.h @@ -34,6 +34,9 @@ arithmetic on smaller types. */ // In case compiler doesn't support these properly. Used rarely. #define STATIC_CAST(T,expr) static_cast (expr) +// User configuration can override the above macros if necessary +#include "blargg_config.h" + // BOOST_STATIC_ASSERT( expr ): Generates compile error if expr is 0. #ifndef BOOST_STATIC_ASSERT #ifdef _MSC_VER diff --git a/source/core/blargg_config.h b/source/core/blargg_config.h new file mode 100644 index 0000000..3ef8c2d --- /dev/null +++ b/source/core/blargg_config.h @@ -0,0 +1,17 @@ +// Library configuration. Modify this file as necessary. + +// File_Extractor 1.0.0 +#ifndef BLARGG_CONFIG_H +#define BLARGG_CONFIG_H + +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H +#endif + +// Use standard config.h if present +#ifdef HAVE_CONFIG_H + #include "config.h" +#endif + + +#endif diff --git a/source/core/blargg_endian.h b/source/core/blargg_endian.h index 2d221c0..f5f1567 100644 --- a/source/core/blargg_endian.h +++ b/source/core/blargg_endian.h @@ -105,7 +105,4 @@ 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/blargg_source.h b/source/core/blargg_source.h index d7d80b2..68942c4 100644 --- a/source/core/blargg_source.h +++ b/source/core/blargg_source.h @@ -32,4 +32,9 @@ otherwise continues normally. */ return "Out of memory";\ } while ( 0 ) +/* The usual min/max functions for built-in types. */ + +template T min( T x, T y ) { return x < y ? x : y; } +template T max( T x, T y ) { return x > y ? x : y; } + #endif diff --git a/source/core/nes_cpu_io.h b/source/core/nes_cpu_io.h index de14094..bf02c9e 100644 --- a/source/core/nes_cpu_io.h +++ b/source/core/nes_cpu_io.h @@ -41,6 +41,10 @@ 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 } @@ -75,7 +79,7 @@ void Nes_Core::cpu_write_2007( int data ) mapper->a12_clocked(); } -inline void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) +void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time ) { //LOG_FREQ( "cpu_write", 16, addr >> 12 ); @@ -116,4 +120,24 @@ inline 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.cpp b/source/core/nes_data.cpp new file mode 100644 index 0000000..041b0b5 --- /dev/null +++ b/source/core/nes_data.cpp @@ -0,0 +1,66 @@ + +// Nes_Emu 0.7.0. http://www.slack.net/~ant/ + +#include "nes_data.h" + +#include "blargg_endian.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" + +#define SWAP_BE( n ) (void) (set_be( &(n), (n) )) +#define SWAP_LE( n ) (void) (set_le( &(n), (n) )) + +void nes_block_t::swap() +{ + SWAP_BE( tag ); + SWAP_LE( size ); +} + +void nes_state_t::swap() +{ + SWAP_LE( timestamp ); + SWAP_LE( frame_count ); +} + +void cpu_state_t::swap() +{ + SWAP_LE( pc ); +} + +void ppu_state_t::swap() +{ + SWAP_LE( vram_addr ); + SWAP_LE( vram_temp ); + SWAP_LE( decay_low ); + SWAP_LE( decay_high ); +} + +void apu_state_t::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 ); +} + +void joypad_state_t::swap() +{ + SWAP_LE( joypad_latches [0] ); + SWAP_LE( joypad_latches [1] ); +} diff --git a/source/core/nes_data.h b/source/core/nes_data.h index 655f143..97059ba 100644 --- a/source/core/nes_data.h +++ b/source/core/nes_data.h @@ -6,10 +6,8 @@ #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; @@ -50,13 +48,8 @@ struct nes_block_t uint32_t tag; // ** stored in big-endian uint32_t size; - inline void swap() - { - SWAP_BE( tag ); - SWAP_LE( size ); - } + void swap(); }; - BOOST_STATIC_ASSERT( sizeof (nes_block_t) == 8 ); unsigned long const group_begin_size = 0xffffffff; // group block has this size @@ -70,13 +63,8 @@ struct nes_state_t uint32_t frame_count; // number of frames emulated since power-up enum { tag = FOUR_CHAR('TIME') }; - inline void swap() - { - SWAP_LE( timestamp ); - SWAP_LE( frame_count ); - } + void swap(); }; - BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 ); struct joypad_state_t @@ -86,12 +74,7 @@ struct joypad_state_t uint8_t unused [3]; enum { tag = FOUR_CHAR('CTRL') }; - inline void swap() - { - SWAP_LE( joypad_latches [0] ); - SWAP_LE( joypad_latches [1] ); - } - + void swap(); }; BOOST_STATIC_ASSERT( sizeof (joypad_state_t) == 12 ); @@ -106,18 +89,8 @@ struct mapper_state_t uint8_t data [max_mapper_state_size]; }; - 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; - } + void write( const void* p, unsigned long s ); + int read( void* p, unsigned long s ) const; }; struct cpu_state_t @@ -131,12 +104,8 @@ struct cpu_state_t uint8_t unused [1]; enum { tag = FOUR_CHAR('CPUR') }; - inline void swap() - { - SWAP_LE( pc ); - } + void swap(); }; - BOOST_STATIC_ASSERT( sizeof (cpu_state_t) == 8 ); struct ppu_state_t @@ -158,15 +127,8 @@ struct ppu_state_t uint8_t unused2[3]; enum { tag = FOUR_CHAR('PPUR') }; - void swap() - { - SWAP_LE( vram_addr ); - SWAP_LE( vram_temp ); - SWAP_LE( decay_low ); - SWAP_LE( decay_high ); - } + void swap(); }; - BOOST_STATIC_ASSERT( sizeof (ppu_state_t) == 20 + 0x20 ); struct mmc1_state_t diff --git a/source/core/nes_ntsc.h b/source/core/nes_ntsc.h index 59f797a..1f53187 100644 --- a/source/core/nes_ntsc.h +++ b/source/core/nes_ntsc.h @@ -5,7 +5,6 @@ #define NES_NTSC_H #include "nes_ntsc_config.h" -#include #ifdef __cplusplus extern "C" { @@ -47,9 +46,9 @@ extern nes_ntsc_setup_t const nes_ntsc_rgb; /* crisp image */ extern nes_ntsc_setup_t const nes_ntsc_monochrome;/* desaturated + artifacts */ #ifdef NES_NTSC_EMPHASIS - static const uint16_t nes_ntsc_palette_size = 64 * 8; + enum { nes_ntsc_palette_size = 64 * 8 }; #else - static const uint16_t { nes_ntsc_palette_size = 64 }; + enum { nes_ntsc_palette_size = 64 }; #endif /* Initializes and adjusts parameters. Can be called multiple times on the same @@ -80,10 +79,10 @@ value. */ /* Interface for user-defined custom blitters */ -const static uint8_t nes_ntsc_in_chunk = 3; /* number of input pixels read per chunk */ -const static uint8_t nes_ntsc_out_chunk = 7 ; /* number of output pixels generated per chunk */ -const static uint8_t nes_ntsc_black = 15; /* palette index for black */ -const static uint8_t nes_ntsc_burst_count = 3 ; /* burst phase cycles through 0, 1, and 2 */ +enum { nes_ntsc_in_chunk = 3 }; /* number of input pixels read per chunk */ +enum { nes_ntsc_out_chunk = 7 }; /* number of output pixels generated per chunk */ +enum { nes_ntsc_black = 15 }; /* palette index for black */ +enum { nes_ntsc_burst_count = 3 }; /* burst phase cycles through 0, 1, and 2 */ /* Begins outputting row and starts three pixels. First pixel will be cut off a bit. Use nes_ntsc_black for unused pixels. Declares variables, so must be before first @@ -107,13 +106,12 @@ statement in a block (unless you're using C++). */ /* private */ -const static uint8_t nes_ntsc_entry_size = 128; +enum { nes_ntsc_entry_size = 128 }; typedef unsigned long nes_ntsc_rgb_t; struct nes_ntsc_t { nes_ntsc_rgb_t table [nes_ntsc_palette_size] [nes_ntsc_entry_size]; }; - -const static uint8_t nes_ntsc_burst_size = nes_ntsc_entry_size / nes_ntsc_burst_count; +enum { nes_ntsc_burst_size = nes_ntsc_entry_size / nes_ntsc_burst_count }; #define NES_NTSC_ENTRY_( ktable, n ) \ (nes_ntsc_rgb_t const*) (ktable + (n) * (nes_ntsc_entry_size * sizeof (nes_ntsc_rgb_t))) @@ -124,18 +122,18 @@ const static uint8_t nes_ntsc_burst_size = nes_ntsc_entry_size / nes_ntsc_burst_ #define NES_NTSC_RGB15_OUT( x, out ) NES_NTSC_RGB_OUT( x, out, 15 ) #define NES_NTSC_RAW_OUT( x, out ) NES_NTSC_RGB_OUT( x, out, 0 ) -const static uint16_t nes_ntsc_min_in_width = 256; -const static uint16_t nes_ntsc_min_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_min_in_width ); +enum { nes_ntsc_min_in_width = 256 }; +enum { nes_ntsc_min_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_min_in_width ) }; -const static uint16_t nes_ntsc_640_in_width = 271; -const static uint16_t nes_ntsc_640_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_640_in_width ); -const static uint16_t nes_ntsc_640_overscan_left = 8; -const static uint16_t nes_ntsc_640_overscan_right = nes_ntsc_640_in_width - 256 - nes_ntsc_640_overscan_left; +enum { nes_ntsc_640_in_width = 271 }; +enum { nes_ntsc_640_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_640_in_width ) }; +enum { nes_ntsc_640_overscan_left = 8 }; +enum { nes_ntsc_640_overscan_right = nes_ntsc_640_in_width - 256 - nes_ntsc_640_overscan_left }; -const static uint16_t nes_ntsc_full_in_width = 283; -const static uint16_t nes_ntsc_full_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_full_in_width ); -const static uint16_t nes_ntsc_full_overscan_left = 16; -const static uint16_t nes_ntsc_full_overscan_right = nes_ntsc_full_in_width - 256 - nes_ntsc_full_overscan_left; +enum { nes_ntsc_full_in_width = 283 }; +enum { nes_ntsc_full_out_width = NES_NTSC_OUT_WIDTH( nes_ntsc_full_in_width ) }; +enum { nes_ntsc_full_overscan_left = 16 }; +enum { nes_ntsc_full_overscan_right = nes_ntsc_full_in_width - 256 - nes_ntsc_full_overscan_left }; /* common 3->7 ntsc macros */ #define NES_NTSC_BEGIN_ROW_6_( pixel0, pixel1, pixel2, ENTRY, table ) \ diff --git a/source/core/nes_ntsc_impl.h b/source/core/nes_ntsc_impl.h index 9772fd2..de3672b 100644 --- a/source/core/nes_ntsc_impl.h +++ b/source/core/nes_ntsc_impl.h @@ -44,9 +44,9 @@ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ #define rgb_unit (1 << rgb_bits) #define rgb_offset (rgb_unit * 2 + 0.5f) -const static uint16_t burst_size = nes_ntsc_entry_size / burst_count; -const static uint8_t kernel_half = 16; -const static uint8_t kernel_size = kernel_half * 2 + 1; +enum { burst_size = nes_ntsc_entry_size / burst_count }; +enum { kernel_half = 16 }; +enum { kernel_size = kernel_half * 2 + 1 }; typedef struct init_t { @@ -284,8 +284,8 @@ static void init( init_t* impl, nes_ntsc_setup_t const* setup ) #define PACK_RGB( r, g, b ) ((r) << 21 | (g) << 11 | (b) << 1) -const static uint16_t rgb_kernel_size = burst_size / alignment_count; -const static uint32_t rgb_bias = rgb_unit * 2 * nes_ntsc_rgb_builder; +enum { rgb_kernel_size = burst_size / alignment_count }; +enum { rgb_bias = rgb_unit * 2 * nes_ntsc_rgb_builder }; typedef struct pixel_info_t { diff --git a/tests/games/benchmark0.txt b/tests/games/benchmark0.txt index aa33e31..325ec92 100644 --- a/tests/games/benchmark0.txt +++ b/tests/games/benchmark0.txt @@ -1,4 +1,4 @@ -Git revision: main:d023e639c3ac3ad84cffba52d5645b81a501c4d4 +Git revision: main:95a95df8e17630200c2f9741786b1abd9159c7a3 Getting system information Architecture: x86_64 CPU op-mode(s): 32-bit, 64-bit @@ -52,8 +52,8 @@ Running Tests sequentially... [] Initial State Hash: 0xB1413A628D2B1D1B79B4F07B3E70AE83 [] State Size: 12793 bytes [] ********** Running Test ********** -[] Elapsed time: 0.413s -[] Performance: 38227.178 steps / s +[] Elapsed time: 0.371s +[] Performance: 42603.262 steps / s [] Final State Hash: 0x1FA0AE49927B0C7485B8A8931F14A57A [] Verification Hash: 0x1FA0AE49927B0C7485B8A8931F14A57A (Passed) [] ----------------------------------------- @@ -66,8 +66,8 @@ Running Tests sequentially... [] Initial State Hash: 0xB1413A628D2B1D1B79B4F07B3E70AE83 [] State Size: 12793 bytes [] ********** Running Test ********** -[] Elapsed time: 1.162s -[] Performance: 33942.159 steps / s +[] Elapsed time: 1.055s +[] Performance: 37366.389 steps / s [] Final State Hash: 0xCDD173D996245BF7133375B2217A01C [] Verification Hash: 0xCDD173D996245BF7133375B2217A01C (Passed) ~/quickerNES/tests/games @@ -82,8 +82,8 @@ Running Tests sequentially... [] Initial State Hash: 0x3CA9F26CF6511A0694C15C1FF876FCC [] State Size: 12807 bytes [] ********** Running Test ********** -[] Elapsed time: 1.334s -[] Performance: 27443.872 steps / s +[] Elapsed time: 1.305s +[] Performance: 28064.077 steps / s [] Final State Hash: 0xB6A66050EB4D7445D6A84A76D7B2BB65 [] Verification Hash: 0xB6A66050EB4D7445D6A84A76D7B2BB65 (Passed) [] ----------------------------------------- @@ -97,7 +97,7 @@ Running Tests sequentially... [] State Size: 12807 bytes [] ********** Running Test ********** [] Elapsed time: 1.242s -[] Performance: 27916.811 steps / s +[] Performance: 27902.635 steps / s [] Final State Hash: 0xDF97F201F54959948D4C4B89C4D220FC [] Verification Hash: 0xDF97F201F54959948D4C4B89C4D220FC (Passed) ~/quickerNES/tests/games @@ -112,8 +112,8 @@ Running Tests sequentially... [] Initial State Hash: 0x6FE586095495B63F2EFD6B69C5560FC9 [] State Size: 20993 bytes [] ********** Running Test ********** -[] Elapsed time: 7.240s -[] Performance: 25162.227 steps / s +[] Elapsed time: 7.480s +[] Performance: 24355.534 steps / s [] Final State Hash: 0xF0F317E40A902D175E6902B49500DF4B [] Verification Hash: 0xF0F317E40A902D175E6902B49500DF4B (Passed) ~/quickerNES/tests/games @@ -128,8 +128,8 @@ Running Tests sequentially... [] Initial State Hash: 0xB6C7EB1C577108C7C0E045D00EC73DDC [] State Size: 12798 bytes [] ********** Running Test ********** -[] Elapsed time: 10.556s -[] Performance: 28096.433 steps / s +[] Elapsed time: 10.656s +[] Performance: 27832.552 steps / s [] Final State Hash: 0x407AA16502BE4D678916D218B1310132 [] Verification Hash: 0x407AA16502BE4D678916D218B1310132 (Passed) ~/quickerNES/tests/games @@ -144,8 +144,8 @@ Running Tests sequentially... [] Initial State Hash: 0x6FE586095495B63F2EFD6B69C5560FC9 [] State Size: 20993 bytes [] ********** Running Test ********** -[] Elapsed time: 1.601s -[] Performance: 24709.686 steps / s +[] Elapsed time: 1.318s +[] Performance: 30011.572 steps / s [] Final State Hash: 0x65214803DC4559ABBED8C449F04D4C91 [] Verification Hash: 0x65214803DC4559ABBED8C449F04D4C91 (Passed) [] ----------------------------------------- @@ -158,8 +158,8 @@ Running Tests sequentially... [] Initial State Hash: 0x6FE586095495B63F2EFD6B69C5560FC9 [] State Size: 20993 bytes [] ********** Running Test ********** -[] Elapsed time: 1.527s -[] Performance: 24456.475 steps / s +[] Elapsed time: 1.198s +[] Performance: 31170.751 steps / s [] Final State Hash: 0x9042C9EFA138F36E505AA33BF50436 [] Verification Hash: 0x9042C9EFA138F36E505AA33BF50436 (Passed) ~/quickerNES/tests/games @@ -174,8 +174,8 @@ Running Tests sequentially... [] Initial State Hash: 0x7BE2D5D63A0545DF3D44A5881CA69E9D [] State Size: 12798 bytes [] ********** Running Test ********** -[] Elapsed time: 2.353s -[] Performance: 36618.048 steps / s +[] Elapsed time: 2.292s +[] Performance: 37588.356 steps / s [] Final State Hash: 0xFFB8ABEE93CDEA838DB6B69470AC819A [] Verification Hash: 0xFFB8ABEE93CDEA838DB6B69470AC819A (Passed) ~/quickerNES/tests/games @@ -190,8 +190,8 @@ Running Tests sequentially... [] Initial State Hash: 0x43443FDD057BBE517B4CDA12736CAD67 [] State Size: 12792 bytes [] ********** Running Test ********** -[] Elapsed time: 1.075s -[] Performance: 37795.958 steps / s +[] Elapsed time: 1.008s +[] Performance: 40292.895 steps / s [] Final State Hash: 0x926C1D6B031E5BD739B13B5734C3D500 [] Verification Hash: 0x926C1D6B031E5BD739B13B5734C3D500 (Passed) ~/quickerNES/tests/games @@ -206,8 +206,8 @@ Running Tests sequentially... [] Initial State Hash: 0x1F405ED3A13732A3DBEDC4C54A50AC79 [] State Size: 12792 bytes [] ********** Running Test ********** -[] Elapsed time: 0.713s -[] Performance: 25064.892 steps / s +[] Elapsed time: 0.737s +[] Performance: 24225.342 steps / s [] Final State Hash: 0xFBB1BE4D99BB17041747DF056C079D57 [] Verification Hash: 0xFBB1BE4D99BB17041747DF056C079D57 (Passed) [] ----------------------------------------- @@ -220,8 +220,8 @@ Running Tests sequentially... [] Initial State Hash: 0x1F405ED3A13732A3DBEDC4C54A50AC79 [] State Size: 12792 bytes [] ********** Running Test ********** -[] Elapsed time: 2.690s -[] Performance: 24953.019 steps / s +[] Elapsed time: 2.803s +[] Performance: 23939.753 steps / s [] Final State Hash: 0xDC3A45216E64D193849B0B248D18E0C3 [] Verification Hash: 0xDC3A45216E64D193849B0B248D18E0C3 (Passed) ~/quickerNES/tests/games @@ -236,8 +236,8 @@ Running Tests sequentially... [] Initial State Hash: 0x7CC865ED649238B850937BAE9DCADC5 [] State Size: 12798 bytes [] ********** Running Test ********** -[] Elapsed time: 1.406s -[] Performance: 28927.321 steps / s +[] Elapsed time: 1.381s +[] Performance: 29450.401 steps / s [] Final State Hash: 0x358165AE6BC7A3EAE0E08D24F9A19BC6 [] Verification Hash: 0x358165AE6BC7A3EAE0E08D24F9A19BC6 (Passed) [] ----------------------------------------- @@ -250,8 +250,8 @@ Running Tests sequentially... [] Initial State Hash: 0x7CC865ED649238B850937BAE9DCADC5 [] State Size: 12798 bytes [] ********** Running Test ********** -[] Elapsed time: 1.327s -[] Performance: 29464.084 steps / s +[] Elapsed time: 1.287s +[] Performance: 30400.721 steps / s [] Final State Hash: 0x5527602EE5679B55EC45BA654B704477 [] Verification Hash: 0x5527602EE5679B55EC45BA654B704477 (Passed) ~/quickerNES/tests/games @@ -266,8 +266,8 @@ Running Tests sequentially... [] Initial State Hash: 0x6FE586095495B63F2EFD6B69C5560FC9 [] State Size: 20993 bytes [] ********** Running Test ********** -[] Elapsed time: 0.901s -[] Performance: 28617.890 steps / s +[] Elapsed time: 0.895s +[] Performance: 28805.919 steps / s [] Final State Hash: 0xCCB65DF6BED258071A720C5FA2FE4FB9 [] Verification Hash: 0xCCB65DF6BED258071A720C5FA2FE4FB9 (Passed) ~/quickerNES/tests/games @@ -282,8 +282,8 @@ Running Tests sequentially... [] Initial State Hash: 0xA1482537F260939E3E0059719CD723AD [] State Size: 12793 bytes [] ********** Running Test ********** -[] Elapsed time: 2.328s -[] Performance: 32959.393 steps / s +[] Elapsed time: 2.365s +[] Performance: 32439.480 steps / s [] Final State Hash: 0xC988A4BDCB3B44DA54AD97D2F2E0F4AF [] Verification Hash: 0xC988A4BDCB3B44DA54AD97D2F2E0F4AF (Passed) ~/quickerNES/tests/games @@ -298,8 +298,8 @@ Running Tests sequentially... [] Initial State Hash: 0x6FE586095495B63F2EFD6B69C5560FC9 [] State Size: 20993 bytes [] ********** Running Test ********** -[] Elapsed time: 0.736s -[] Performance: 35346.699 steps / s +[] Elapsed time: 0.684s +[] Performance: 38036.181 steps / s [] Final State Hash: 0x3D0ACE9B9D592AE6922354DDC3682BAB [] Verification Hash: 0x3D0ACE9B9D592AE6922354DDC3682BAB (Passed) ~/quickerNES/tests/games @@ -314,8 +314,8 @@ Running Tests sequentially... [] Initial State Hash: 0x6FE586095495B63F2EFD6B69C5560FC9 [] State Size: 20993 bytes [] ********** Running Test ********** -[] Elapsed time: 1.768s -[] Performance: 26014.717 steps / s +[] Elapsed time: 1.780s +[] Performance: 25838.636 steps / s [] Final State Hash: 0x1E08CEBDE3EC56B659D54328D3D9E344 [] Verification Hash: 0x1E08CEBDE3EC56B659D54328D3D9E344 (Passed) ~/quickerNES/tests/games @@ -330,8 +330,8 @@ Running Tests sequentially... [] Initial State Hash: 0x4BB3E8B61F496038D8A01894B8B824F [] State Size: 12792 bytes [] ********** Running Test ********** -[] Elapsed time: 0.890s -[] Performance: 33617.789 steps / s +[] Elapsed time: 0.888s +[] Performance: 33704.677 steps / s [] Final State Hash: 0x4E40A40820C188009A061C5C7FC7DB29 [] Verification Hash: 0x4E40A40820C188009A061C5C7FC7DB29 (Passed) ~/quickerNES/tests/games