More simplifications

This commit is contained in:
Sergio Martin 2024-01-13 17:15:24 +01:00
parent 13561dc134
commit 95a95df8e1
15 changed files with 402 additions and 507 deletions

View File

@ -26,7 +26,6 @@ quickerNESCoreSrc = [
'source/core/Nes_Cpu.cpp',
'source/core/Nes_State.cpp',
'source/core/emu2413.cpp',
'source/core/nes_data.cpp',
'source/core/nes_util.cpp',
'source/core/emu2413_state.cpp',
'source/core/Nes_Effects_Buffer.cpp',

View File

@ -1,12 +1,4 @@
// 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"
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
@ -17,9 +9,76 @@ FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
// Nes_Emu 0.7.0. http://www.slack.net/~ant/
#include <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;
@ -70,9 +129,79 @@ const char * Nes_Core::open( Nes_Cart const* new_cart )
RETURN_ERR( init() );
mapper = Nes_Mapper::create( new_cart, this );
if ( !mapper )
return unsupported_mapper;
// Getting cartdrige mapper code
auto mapperCode = new_cart->mapper_code();
// Storage for the mapper, NULL by default
mapper = NULL;
// Now checking if the detected mapper code is supported
if (mapperCode == 0) mapper = new Mapper000();
if (mapperCode == 1) mapper = new Mapper001();
if (mapperCode == 2) mapper = new Mapper002();
if (mapperCode == 3) mapper = new Mapper003();
if (mapperCode == 4) mapper = new Mapper004();
if (mapperCode == 5) mapper = new Mapper005();
if (mapperCode == 7) mapper = new Mapper007();
if (mapperCode == 9) mapper = new Mapper009();
if (mapperCode == 10) mapper = new Mapper010();
if (mapperCode == 11) mapper = new Mapper011();
if (mapperCode == 15) mapper = new Mapper015();
if (mapperCode == 19) mapper = new Mapper019();
if (mapperCode == 21) mapper = new Mapper021();
if (mapperCode == 22) mapper = new Mapper022();
if (mapperCode == 23) mapper = new Mapper023();
if (mapperCode == 24) mapper = new Mapper024();
if (mapperCode == 25) mapper = new Mapper025();
if (mapperCode == 26) mapper = new Mapper026();
if (mapperCode == 30) mapper = new Mapper030();
if (mapperCode == 32) mapper = new Mapper032();
if (mapperCode == 33) mapper = new Mapper033();
if (mapperCode == 34) mapper = new Mapper034();
if (mapperCode == 60) mapper = new Mapper060();
if (mapperCode == 66) mapper = new Mapper066();
if (mapperCode == 69) mapper = new Mapper069();
if (mapperCode == 70) mapper = new Mapper070();
if (mapperCode == 71) mapper = new Mapper071();
if (mapperCode == 73) mapper = new Mapper073();
if (mapperCode == 75) mapper = new Mapper075();
if (mapperCode == 78) mapper = new Mapper078();
if (mapperCode == 79) mapper = new Mapper079();
if (mapperCode == 85) mapper = new Mapper085();
if (mapperCode == 86) mapper = new Mapper086();
if (mapperCode == 87) mapper = new Mapper087();
if (mapperCode == 88) mapper = new Mapper088();
if (mapperCode == 89) mapper = new Mapper089();
if (mapperCode == 93) mapper = new Mapper093();
if (mapperCode == 94) mapper = new Mapper094();
if (mapperCode == 97) mapper = new Mapper097();
if (mapperCode == 113) mapper = new Mapper113();
if (mapperCode == 140) mapper = new Mapper140();
if (mapperCode == 152) mapper = new Mapper152();
if (mapperCode == 154) mapper = new Mapper154();
if (mapperCode == 156) mapper = new Mapper156();
if (mapperCode == 180) mapper = new Mapper180();
if (mapperCode == 184) mapper = new Mapper184();
if (mapperCode == 190) mapper = new Mapper190();
if (mapperCode == 193) mapper = new Mapper193();
if (mapperCode == 206) mapper = new Mapper206();
if (mapperCode == 207) mapper = new Mapper207();
if (mapperCode == 232) mapper = new Mapper232();
if (mapperCode == 240) mapper = new Mapper240();
if (mapperCode == 241) mapper = new Mapper241();
if (mapperCode == 244) mapper = new Mapper244();
if (mapperCode == 246) mapper = new Mapper246();
// If no mapper was found, return null (error) now
if (mapper == NULL)
{
fprintf(stderr, "Could not find mapper for code: %u\n", mapperCode);
return NULL;
}
// Assigning backwards pointers to cartdrige and emulator now
mapper->setCartridge(new_cart);
mapper->setCore(this);
RETURN_ERR( ppu.open_chr( new_cart->chr(), new_cart->chr_size() ) );
@ -205,13 +334,6 @@ void Nes_Core::enable_sram( bool b, bool read_only )
}
}
// Unmapped memory
void Nes_Core::log_unmapped( nes_addr_t addr, int data )
{
}
inline void Nes_Core::cpu_adjust_time( int n )
{
ppu_2002_time -= n;
@ -273,10 +395,6 @@ void Nes_Core::write_io( nes_addr_t addr, int data )
}
return;
}
#ifndef NDEBUG
log_unmapped( addr, data );
#endif
}
int Nes_Core::read_io( nes_addr_t addr )
@ -295,10 +413,6 @@ int Nes_Core::read_io( nes_addr_t addr )
if ( addr == Nes_Apu::status_addr )
return impl->apu.read_status( clock() );
#ifndef NDEBUG
log_unmapped( addr );
#endif
return addr >> 8; // simulate open bus
}

View File

@ -104,6 +104,7 @@ public: private: friend class Nes_Mapper;
void add_mapper_intercept( nes_addr_t start, unsigned size, bool read, bool write );
public: private: friend class Nes_Cpu;
int cpu_read_ppu( nes_addr_t, nes_time_t );
int cpu_read( nes_addr_t, nes_time_t );
void cpu_write( nes_addr_t, int data, nes_time_t );

View File

@ -1,7 +1,4 @@
// Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/
#include "Nes_Cpu.h"
#include <string.h>
@ -11,55 +8,17 @@
#include "nes_cpu_io.h"
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "blargg_source.h"
inline void Nes_Cpu::set_code_page( int i, uint8_t const* p )
{
code_map [i] = p - (unsigned) i * page_size;
#define NES_CPU_READ_PPU( cpu, addr, time ) STATIC_CAST(Nes_Core&,*cpu).cpu_read_ppu( addr, time )
#define NES_CPU_READ( cpu, addr, time ) STATIC_CAST(Nes_Core&,*cpu).cpu_read( addr, time )
#define NES_CPU_WRITEX( cpu, addr, data, time ) {STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );}
#define NES_CPU_WRITE( cpu, addr, data, time ) \
{\
if ( addr < 0x800 ) cpu->low_mem [addr] = data;\
else if ( addr == 0x2007 ) STATIC_CAST(Nes_Core&,*cpu).cpu_write_2007( data );\
else STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\
}
void Nes_Cpu::reset( void const* unmapped_page )
{
r.status = 0;
r.sp = 0;
r.pc = 0;
r.a = 0;
r.x = 0;
r.y = 0;
error_count_ = 0;
clock_count = 0;
clock_limit = 0;
irq_time_ = LONG_MAX / 2 + 1;
end_time_ = LONG_MAX / 2 + 1;
set_code_page( 0, low_mem );
set_code_page( 1, low_mem );
set_code_page( 2, low_mem );
set_code_page( 3, low_mem );
for ( int i = 4; i < page_count + 1; i++ )
set_code_page( i, (uint8_t*) unmapped_page );
isCorrectExecution = true;
}
void Nes_Cpu::map_code( nes_addr_t start, unsigned size, const void* data )
{
unsigned first_page = start / page_size;
for ( unsigned i = size / page_size; i--; )
set_code_page( first_page + i, (uint8_t*) data + i * page_size );
}
// Note: 'addr' is evaulated more than once in the following macros, so it
// must not contain side-effects.
@ -80,10 +39,6 @@ void Nes_Cpu::map_code( nes_addr_t start, unsigned size, const void* data )
#define GET_SP() ((sp - 1) & 0xFF)
#define PUSH( v ) ((sp = (sp - 1) | 0x100), WRITE_LOW( sp, v ))
#ifdef BLARGG_ENABLE_OPTIMIZER
#include BLARGG_ENABLE_OPTIMIZER
#endif
int Nes_Cpu::read( nes_addr_t addr )
{
return READ( addr );

View File

@ -1,6 +1,19 @@
// NES 6502 CPU emulator
// Nes_Emu 0.7.0. http://www.slack.net/~ant/nes-emu/
/* Copyright (C) 2003-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
// Nes_Emu 0.7.0
#ifndef NES_CPU_H
@ -14,15 +27,50 @@ typedef unsigned nes_addr_t; // 16-bit address
class Nes_Cpu {
public:
inline void set_code_page( int i, uint8_t const* p )
{
code_map [i] = p - (unsigned) i * page_size;
}
// Clear registers, unmap memory, and map code pages to unmapped_page.
void reset( void const* unmapped_page = 0 );
void reset( void const* unmapped_page = 0 )
{
r.status = 0;
r.sp = 0;
r.pc = 0;
r.a = 0;
r.x = 0;
r.y = 0;
error_count_ = 0;
clock_count = 0;
clock_limit = 0;
irq_time_ = LONG_MAX / 2 + 1;
end_time_ = LONG_MAX / 2 + 1;
set_code_page( 0, low_mem );
set_code_page( 1, low_mem );
set_code_page( 2, low_mem );
set_code_page( 3, low_mem );
for ( int i = 4; i < page_count + 1; i++ )
set_code_page( i, (uint8_t*) unmapped_page );
isCorrectExecution = true;
}
// Map code memory (memory accessed via the program counter). Start and size
// must be multiple of page_size.
static const uint8_t page_bits = 11;
static const uint16_t page_count = 0x10000 >> page_bits;
static const uint16_t page_size = 1L << page_bits;
void map_code( nes_addr_t start, unsigned size, void const* code );
void map_code( nes_addr_t start, unsigned size, void const* code )
{
unsigned first_page = start / page_size;
for ( unsigned i = size / page_size; i--; )
set_code_page( first_page + i, (uint8_t*) code + i * page_size );
}
// Access memory as the emulated CPU does.
int read( nes_addr_t );
@ -73,7 +121,6 @@ public:
unsigned long error_count_;
static const uint8_t irq_inhibit = 0x04;
void set_code_page( int, uint8_t const* );
void update_clock_limit();
registers_t r;

View File

@ -6,297 +6,8 @@
#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,15 +1,27 @@
#pragma once
// NES mapper interface
/* Copyright (C) 2004-2006 Shay Green. This module is free software; you
can redistribute it and/or modify it under the terms of the GNU Lesser
General Public License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version. This
module is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for
more details. You should have received a copy of the GNU Lesser General
Public License along with this module; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
// Nes_Emu 0.7.0
#ifndef NES_MAPPER
#define NES_MAPPER
#include "Nes_Cart.h"
#include "Nes_Cpu.h"
#include "nes_data.h"
#include "Nes_Core.h"
#include <cstdio>
#include <string.h>
#include "blargg_source.h"
class Blip_Buffer;
class blip_eq_t;
class Nes_Core;
@ -23,30 +35,43 @@ public:
// Register optional mappers included with Nes_Emu
void register_optional_mappers();
// Create mapper appropriate for cartridge. Returns NULL if it uses unsupported mapper.
static Nes_Mapper* create( Nes_Cart const*, Nes_Core* );
virtual ~Nes_Mapper();
virtual ~Nes_Mapper() = default;
// Reset mapper to power-up state.
virtual void reset();
virtual inline void reset()
{
default_reset_state();
reset_state();
apply_mapping();
}
// Save snapshot of mapper state. Default saves registered state.
virtual void save_state( mapper_state_t& );
virtual inline void save_state( mapper_state_t& out )
{
out.write( state, state_size );
}
// Resets mapper, loads state, then applies it
virtual void load_state( mapper_state_t const& );
virtual inline void load_state( mapper_state_t const& in )
{
default_reset_state();
read_state( in );
apply_mapping();
}
void setCartridge(const Nes_Cart* cart) { cart_ = cart; }
void setCore(Nes_Core* core) { emu_ = core; }
// I/O
// Read from memory
virtual int read( nes_time_t, nes_addr_t );
virtual inline int read( nes_time_t, nes_addr_t ) { return -1; } ;
// Write to memory
virtual void write( nes_time_t, nes_addr_t, int data ) = 0;
// Write to memory below 0x8000 (returns false if mapper didn't handle write)
virtual bool write_intercepted( nes_time_t, nes_addr_t, int data );
virtual inline bool write_intercepted( nes_time_t, nes_addr_t, int data ) { return false; }
// Timing
@ -54,53 +79,66 @@ public:
enum { no_irq = LONG_MAX / 2 };
// Time next IRQ will occur at
virtual nes_time_t next_irq( nes_time_t present );
virtual inline nes_time_t next_irq( nes_time_t present ) { return no_irq; };
// Run mapper until given time
virtual void run_until( nes_time_t );
virtual inline void run_until( nes_time_t ) { };
// End video frame of given length
virtual void end_frame( nes_time_t length );
virtual inline void end_frame( nes_time_t length ) { };
// Sound
// Number of sound channels
virtual int channel_count() const;
virtual inline int channel_count() const { return 0; };
// Set sound buffer for channel to output to, or NULL to silence channel.
virtual void set_channel_buf( int index, Blip_Buffer* );
virtual inline void set_channel_buf( int index, Blip_Buffer* ) { };
// Set treble equalization
virtual void set_treble( blip_eq_t const& );
virtual inline void set_treble( blip_eq_t const& ) { };
// Misc
// Called when bit 12 of PPU's VRAM address changes from 0 to 1 due to
// $2006 and $2007 accesses (but not due to PPU scanline rendering).
virtual void a12_clocked();
virtual inline void a12_clocked() {};
protected:
// Services provided for derived mapper classes
Nes_Mapper();
Nes_Mapper()
{
emu_ = NULL;
static char c;
state = &c; // TODO: state must not be null?
state_size = 0;
}
// Register state data to automatically save and load. Be sure the binary
// layout is suitable for use in a file, including any byte-order issues.
// Automatically cleared to zero by default reset().
void register_state( void*, unsigned );
inline void register_state(void* p, unsigned s)
{
state = p;
state_size = s;
}
// Enable 8K of RAM at 0x6000-0x7FFF, optionally read-only.
void enable_sram( bool enabled = true, bool read_only = false );
inline void enable_sram( bool enabled = true, bool read_only = false ) { emu_->enable_sram( enabled, read_only ); }
// Cause CPU writes within given address range to call mapper's write() function.
// Might map a larger address range, which the mapper can ignore and pass to
// Nes_Mapper::write(). The range 0x8000-0xffff is always intercepted by the mapper.
void intercept_writes( nes_addr_t addr, unsigned size );
inline void intercept_writes( nes_addr_t addr, unsigned size ) { emu().add_mapper_intercept( addr, size, false, true ); }
// Cause CPU reads within given address range to call mapper's read() function.
// Might map a larger address range, which the mapper can ignore and pass to
// Nes_Mapper::read(). CPU opcode/operand reads and low-memory reads always
// go directly to memory and cannot be intercepted.
void intercept_reads( nes_addr_t addr, unsigned size );
inline void intercept_reads( nes_addr_t addr, unsigned size )
{
emu().add_mapper_intercept( addr, size, true, false );
}
// Bank sizes for mapping
enum bank_size_t { // 1 << bank_Xk = X * 1024
@ -117,22 +155,51 @@ protected:
enum { last_bank = -1 };
// Map 'size' bytes from 'PRG + bank * size' to CPU address space starting at 'addr'
void set_prg_bank( nes_addr_t addr, bank_size_t size, int bank );
void set_prg_bank( nes_addr_t addr, bank_size_t bs, int bank )
{
int bank_size = 1 << bs;
int bank_count = cart_->prg_size() >> bs;
if ( bank < 0 )
bank += bank_count;
if ( bank >= bank_count )
bank %= bank_count;
emu().map_code( addr, bank_size, cart_->prg() + (bank << bs) );
if ( unsigned (addr - 0x6000) < 0x2000 )
emu().enable_prg_6000();
}
// Map 'size' bytes from 'CHR + bank * size' to PPU address space starting at 'addr'
void set_chr_bank( nes_addr_t addr, bank_size_t size, int bank );
void set_chr_bank_ex( nes_addr_t addr, bank_size_t size, int bank );
inline void set_chr_bank( nes_addr_t addr, bank_size_t bs, int bank )
{
emu().ppu.render_until( emu().clock() );
emu().ppu.set_chr_bank( addr, 1 << bs, bank << bs );
}
inline void set_chr_bank_ex( nes_addr_t addr, bank_size_t bs, int bank )
{
emu().ppu.render_until( emu().clock() );
emu().ppu.set_chr_bank_ex( addr, 1 << bs, bank << bs );
}
// Set PPU mirroring. All mappings implemented using mirror_manual().
void mirror_manual( int page0, int page1, int page2, int page3 );
void mirror_single( int page );
void mirror_horiz( int page = 0 );
void mirror_vert( int page = 0 );
void mirror_full();
inline void mirror_manual( int page0, int page1, int page2, int page3 )
{
emu().ppu.render_bg_until( emu().clock() );
emu().ppu.set_nt_banks( page0, page1, page2, page3 );
}
inline void mirror_horiz( int p = 0) { mirror_manual( p, p, p ^ 1, p ^ 1 ); }
inline void mirror_vert( int p = 0 ) { mirror_manual( p, p ^ 1, p, p ^ 1 ); }
inline void mirror_single( int p ) { mirror_manual( p, p, p, p ); }
inline void mirror_full() { mirror_manual( 0, 1, 2, 3 ); }
// True if PPU rendering is enabled. Some mappers watch PPU memory accesses to determine
// when scanlines occur, and can only do this when rendering is enabled.
bool ppu_enabled() const;
inline bool ppu_enabled() const { return emu().ppu.w2001 & 0x08; }
// Cartridge being emulated
Nes_Cart const& cart() const { return *cart_; }
@ -140,13 +207,13 @@ protected:
// Must be called when next_irq()'s return value is earlier than previous,
// current CPU run can be stopped earlier. Best to call whenever time may
// have changed (no performance impact if called even when time didn't change).
void irq_changed();
inline void irq_changed() { emu_->irq_changed(); }
// Handle data written to mapper that doesn't handle bus conflict arising due to
// PRG also reading data. Returns data that mapper should act as if were
// written. Currently always returns 'data' and just checks that data written is
// the same as byte in PRG at same address and writes debug message if it doesn't.
int handle_bus_conflict( nes_addr_t addr, int data );
int handle_bus_conflict( nes_addr_t addr, int data ) { return data; }
// Reference to emulator that uses this mapper.
Nes_Core& emu() const { return *emu_; }
@ -156,7 +223,12 @@ protected:
// Read state from snapshot. Default reads data into registered state, then calls
// apply_mapping().
virtual void read_state( mapper_state_t const& );
inline void read_state( mapper_state_t const& in )
{
memset( state, 0, state_size );
in.read( state, state_size );
apply_mapping();
}
// Apply current mapping state to hardware. Called after reading mapper state
// from a snapshot.
@ -172,42 +244,26 @@ private:
unsigned state_size;
Nes_Cart const* cart_;
void default_reset_state();
// Sets mirroring, maps first 8K CHR in, first and last 16K of PRG,
// intercepts writes to upper half of memory, and clears registered state.
inline void default_reset_state()
{
int mirroring = cart_->mirroring();
if ( mirroring & 8 )
mirror_full();
else if ( mirroring & 1 )
mirror_vert();
else
mirror_horiz();
set_chr_bank( 0, bank_8k, 0 );
set_prg_bank( 0x8000, bank_16k, 0 );
set_prg_bank( 0xC000, bank_16k, last_bank );
intercept_writes( 0x8000, 0x8000 );
memset( state, 0, state_size );
}
};
#ifdef NDEBUG
inline int Nes_Mapper::handle_bus_conflict( nes_addr_t addr, int data ) { return data; }
#endif
inline void Nes_Mapper::mirror_horiz( int p ) { mirror_manual( p, p, p ^ 1, p ^ 1 ); }
inline void Nes_Mapper::mirror_vert( int p ) { mirror_manual( p, p ^ 1, p, p ^ 1 ); }
inline void Nes_Mapper::mirror_single( int p ) { mirror_manual( p, p, p, p ); }
inline void Nes_Mapper::mirror_full() { mirror_manual( 0, 1, 2, 3 ); }
inline void Nes_Mapper::register_state( void* p, unsigned s )
{
state = p;
state_size = s;
}
inline bool Nes_Mapper::write_intercepted( nes_time_t, nes_addr_t, int ) { return false; }
inline int Nes_Mapper::read( nes_time_t, nes_addr_t ) { return -1; } // signal to caller
inline void Nes_Mapper::intercept_reads( nes_addr_t addr, unsigned size )
{
emu().add_mapper_intercept( addr, size, true, false );
}
inline void Nes_Mapper::intercept_writes( nes_addr_t addr, unsigned size )
{
emu().add_mapper_intercept( addr, size, false, true );
}
inline void Nes_Mapper::enable_sram( bool enabled, bool read_only )
{
emu_->enable_sram( enabled, read_only );
}
#endif

View File

@ -37,14 +37,6 @@ Nes_Ppu_Impl::Nes_Ppu_Impl()
mmc24_enabled = false;
mmc24_latched[0] = 0;
mmc24_latched[1] = 0;
#if !defined(NDEBUG) && !defined(PSP) && !defined(PS2)
// verify that unaligned accesses work
static unsigned char b [19] = { 0 };
static unsigned char b2 [19] = { 1,2,3,4,0,5,6,7,8,0,9,0,1,2,0,3,4,5,6 };
for ( int i = 0; i < 19; i += 5 )
*(volatile uint32_t*) &b [i] = *(volatile uint32_t*) &b2 [i];
#endif
}
Nes_Ppu_Impl::~Nes_Ppu_Impl()

View File

@ -20,16 +20,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "blargg_source.h"
#ifdef BLARGG_ENABLE_OPTIMIZER
#include BLARGG_ENABLE_OPTIMIZER
#endif
#ifdef __MWERKS__
static unsigned zero = 0; // helps CodeWarrior optimizer when added to constants
#else
const unsigned zero = 0; // compile-time constant on other compilers
#endif
// Nes_Ppu_Impl
inline Nes_Ppu_Impl::cached_tile_t const&
@ -188,8 +178,8 @@ void Nes_Ppu_Rendering::draw_background_( int remain )
uint8_t* pixels = row_pixels;
row_pixels += height * row_bytes;
unsigned long const mask = 0x03030303 + zero;
unsigned long const attrib_factor = 0x04040404 + zero;
unsigned long const mask = 0x03030303;
unsigned long const attrib_factor = 0x04040404;
const int fine_y = (height == 8) ? 0 : addr >> 12;
const int clipped = (height == 8) ? false : true;
@ -373,7 +363,7 @@ void Nes_Ppu_Rendering::check_sprite_hit( int begin, int end )
}
// check each line
unsigned long const mask = 0x01010101 + zero;
unsigned long const mask = 0x01010101;
do
{
// get pixels for line

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 + zero;
unsigned long const maskgen = 0x80808080 + zero;
unsigned long const mask = 0x03030303;
unsigned long const maskgen = 0x80808080;
#define DRAW_PAIR( shift ) { \
int sprite_count = *scanlines; \
@ -48,7 +48,7 @@ unsigned long const maskgen = 0x80808080 + zero;
if ( !(sprite_2 & 0x20) )
{
// front
unsigned long const maskgen2 = 0x7f7f7f7f + zero;
unsigned long const maskgen2 = 0x7f7f7f7f;
#define CALC_FOUR( in, line, out ) \
unsigned long out; \
@ -88,8 +88,8 @@ if ( !(sprite_2 & 0x20) )
else
{
// behind
unsigned long const omask = 0x20202020 + zero;
unsigned long const bg_or = 0xc3c3c3c3 + zero;
unsigned long const omask = 0x20202020;
unsigned long const bg_or = 0xc3c3c3c3;
#define CALC_FOUR( in, line, out ) \
unsigned long out; \

View File

@ -8,6 +8,7 @@
#include <stdint.h>
#include "blargg_common.h"
#include "blargg_endian.h"
struct apu_state_t
{
@ -70,7 +71,19 @@ struct apu_state_t
//uint8_t length_counters [4];
enum { tag = 0x41505552 }; // 'APUR'
void swap();
void swap()
{
SWAP_LE( apu.frame_delay );
SWAP_LE( square1.delay );
SWAP_LE( square2.delay );
SWAP_LE( triangle.delay );
SWAP_LE( noise.delay );
SWAP_LE( noise.shift_reg );
SWAP_LE( dmc.delay );
SWAP_LE( dmc.remain );
SWAP_LE( dmc.addr );
}
};
BOOST_STATIC_ASSERT( sizeof (apu_state_t) == 72 );

View File

@ -105,4 +105,7 @@ inline void set_be( uint32_t* p, unsigned long n ) { SET_BE32( p, n ); }
inline unsigned get_be( uint16_t* p ) { return GET_BE16( p ); }
inline unsigned long get_be( uint32_t* p ) { return GET_BE32( p ); }
#define SWAP_BE( n ) (void) (set_be( &(n), (n) ))
#define SWAP_LE( n ) (void) (set_le( &(n), (n) ))
#endif

View File

@ -41,10 +41,6 @@ int Nes_Core::cpu_read( nes_addr_t addr, nes_time_t time )
if ( addr < lrom_readable )
return *cpu::get_code( addr );
#ifndef NDEBUG
log_unmapped( addr );
#endif
return addr >> 8; // simulate open bus
}
@ -79,7 +75,7 @@ void Nes_Core::cpu_write_2007( int data )
mapper->a12_clocked();
}
void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time )
inline void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time )
{
//LOG_FREQ( "cpu_write", 16, addr >> 12 );
@ -120,24 +116,4 @@ void Nes_Core::cpu_write( nes_addr_t addr, int data, nes_time_t time )
mapper->write( clock_, addr, data );
return;
}
#ifndef NDEBUG
log_unmapped( addr, data );
#endif
}
#define NES_CPU_READ_PPU( cpu, addr, time ) \
STATIC_CAST(Nes_Core&,*cpu).cpu_read_ppu( addr, time )
#define NES_CPU_READ( cpu, addr, time ) \
STATIC_CAST(Nes_Core&,*cpu).cpu_read( addr, time )
#define NES_CPU_WRITEX( cpu, addr, data, time ){\
STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\
}
#define NES_CPU_WRITE( cpu, addr, data, time ){\
if ( addr < 0x800 ) cpu->low_mem [addr] = data;\
else if ( addr == 0x2007 ) STATIC_CAST(Nes_Core&,*cpu).cpu_write_2007( data );\
else STATIC_CAST(Nes_Core&,*cpu).cpu_write( addr, data, time );\
}

View File

@ -6,8 +6,10 @@
#ifndef NES_DATA_H
#define NES_DATA_H
#include "blargg_endian.h"
#include "blargg_common.h"
#include "apu_state.h"
#include <cstring>
typedef long nes_tag_t;
@ -48,8 +50,13 @@ struct nes_block_t
uint32_t tag; // ** stored in big-endian
uint32_t size;
void swap();
inline void swap()
{
SWAP_BE( tag );
SWAP_LE( size );
}
};
BOOST_STATIC_ASSERT( sizeof (nes_block_t) == 8 );
unsigned long const group_begin_size = 0xffffffff; // group block has this size
@ -63,8 +70,13 @@ struct nes_state_t
uint32_t frame_count; // number of frames emulated since power-up
enum { tag = FOUR_CHAR('TIME') };
void swap();
inline void swap()
{
SWAP_LE( timestamp );
SWAP_LE( frame_count );
}
};
BOOST_STATIC_ASSERT( sizeof (nes_state_t) == 8 );
struct joypad_state_t
@ -74,7 +86,12 @@ struct joypad_state_t
uint8_t unused [3];
enum { tag = FOUR_CHAR('CTRL') };
void swap();
inline void swap()
{
SWAP_LE( joypad_latches [0] );
SWAP_LE( joypad_latches [1] );
}
};
BOOST_STATIC_ASSERT( sizeof (joypad_state_t) == 12 );
@ -89,8 +106,18 @@ struct mapper_state_t
uint8_t data [max_mapper_state_size];
};
void write( const void* p, unsigned long s );
int read( void* p, unsigned long s ) const;
inline void write( const void* p, unsigned long s )
{
size = s;
memcpy( data, p, s );
}
inline int read( void* p, unsigned long s ) const
{
if ( (long) s > size )s = size;
memcpy( p, data, s );
return s;
}
};
struct cpu_state_t
@ -104,8 +131,12 @@ struct cpu_state_t
uint8_t unused [1];
enum { tag = FOUR_CHAR('CPUR') };
void swap();
inline void swap()
{
SWAP_LE( pc );
}
};
BOOST_STATIC_ASSERT( sizeof (cpu_state_t) == 8 );
struct ppu_state_t
@ -127,8 +158,15 @@ struct ppu_state_t
uint8_t unused2[3];
enum { tag = FOUR_CHAR('PPUR') };
void swap();
void swap()
{
SWAP_LE( vram_addr );
SWAP_LE( vram_temp );
SWAP_LE( decay_low );
SWAP_LE( decay_high );
}
};
BOOST_STATIC_ASSERT( sizeof (ppu_state_t) == 20 + 0x20 );
struct mmc1_state_t