Reverting changes back to 0c8318e26e since some of those commits did something that affected performance

This commit is contained in:
Sergio Martin 2024-01-13 18:42:59 +01:00
parent 95a95df8e1
commit 66e6632eea
32 changed files with 833 additions and 597 deletions

View File

@ -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' ]
)

View File

@ -1,7 +1,7 @@
// File_Extractor 1.0.0. http://www.slack.net/~ant/
#include <algorithm>
#include "Data_Reader.h"
#include "blargg_endian.h"
#include <errno.h>
@ -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;

View File

@ -4,10 +4,8 @@
#ifndef DATA_READER_H
#define DATA_READER_H
#include <algorithm>
#include <cstdint>
#include <stdint.h>
#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.

View File

@ -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;

View File

@ -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;

View File

@ -1,4 +1,12 @@
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
#include "Nes_Core.h"
#include <string.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
@ -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 <algorithm>
#include <cstring>
#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;
}

View File

@ -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 );

View File

@ -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 <string.h>
@ -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 );

View File

@ -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;

View File

@ -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

View File

@ -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<blip_good_quality,1> synth;
void run_until( blip_time_t );

View File

@ -6,8 +6,297 @@
#include <cstdio>
#include <string.h>
#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;
}

View File

@ -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 <cstdio>
#include <string.h>
#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

View File

@ -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 );

View File

@ -3,9 +3,9 @@
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
#include <algorithm>
#include <cstring>
#include "Nes_Ppu.h"
#include <string.h>
#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

68
source/core/Nes_Ppu_Bg.h Normal file
View File

@ -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;
}

View File

@ -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()

View File

@ -3,9 +3,8 @@
#include "Nes_Ppu_Rendering.h"
#include <algorithm>
#include <cstring>
#include <cstddef>
#include <string.h>
#include <stddef.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
@ -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 )
{

View File

@ -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; \

View File

@ -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*);

View File

@ -1,6 +1,8 @@
#include "abstract_file.h"
#include "blargg_config.h"
#include <string.h>
#include <stdlib.h>

View File

@ -8,7 +8,6 @@
#include <stdint.h>
#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 );

View File

@ -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<T> (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

View File

@ -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

View File

@ -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

View File

@ -32,4 +32,9 @@ otherwise continues normally. */
return "Out of memory";\
} while ( 0 )
/* The usual min/max functions for built-in types. */
template<typename T> T min( T x, T y ) { return x < y ? x : y; }
template<typename T> T max( T x, T y ) { return x > y ? x : y; }
#endif

View File

@ -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 );\
}

66
source/core/nes_data.cpp Normal file
View File

@ -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] );
}

View File

@ -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 <cstring>
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

View File

@ -5,7 +5,6 @@
#define NES_NTSC_H
#include "nes_ntsc_config.h"
#include <cstdint>
#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 ) \

View File

@ -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
{

View File

@ -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