quicknes: fire emblem
This commit is contained in:
parent
80695269f5
commit
5415f51de0
Binary file not shown.
|
@ -284,5 +284,7 @@ EXPORT const char *qn_get_mapper(Nes_Emu *e, int *number)
|
|||
case 66: return "gnrom";
|
||||
case 87: return "mapper_87";
|
||||
case 232: return "quattro";
|
||||
case 9: return "mmc2";
|
||||
case 10: return "mmc4";
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
<ClCompile Include="..\nes_emu\Mapper_Namco106.cpp" />
|
||||
<ClCompile Include="..\nes_emu\Mapper_Vrc6.cpp" />
|
||||
<ClCompile Include="..\nes_emu\misc_mappers.cpp" />
|
||||
<ClCompile Include="..\nes_emu\Mmc24.cpp" />
|
||||
<ClCompile Include="..\nes_emu\Multi_Buffer.cpp" />
|
||||
<ClCompile Include="..\nes_emu\Nes_Apu.cpp" />
|
||||
<ClCompile Include="..\nes_emu\Nes_Buffer.cpp" />
|
||||
|
@ -64,6 +65,7 @@
|
|||
<ClInclude Include="..\nes_emu\Blip_Buffer.h" />
|
||||
<ClInclude Include="..\nes_emu\Blip_Synth.h" />
|
||||
<ClInclude Include="..\nes_emu\Effects_Buffer.h" />
|
||||
<ClInclude Include="..\nes_emu\Mmc24.h" />
|
||||
<ClInclude Include="..\nes_emu\Multi_Buffer.h" />
|
||||
<ClInclude Include="..\nes_emu\Nes_Apu.h" />
|
||||
<ClInclude Include="..\nes_emu\Nes_Buffer.h" />
|
||||
|
|
|
@ -135,6 +135,9 @@
|
|||
<ClCompile Include="..\bizinterface.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="..\nes_emu\Mmc24.cpp">
|
||||
<Filter>Source Files\nes_emu</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="..\nes_emu\abstract_file.h">
|
||||
|
@ -257,5 +260,8 @@
|
|||
<ClInclude Include="..\fex\Data_Reader.h">
|
||||
<Filter>Header Files\fex</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="..\nes_emu\Mmc24.h">
|
||||
<Filter>Header Files\nes_emu</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -38,6 +38,7 @@ SRCS = \
|
|||
../nes_emu/Nes_State.cpp \
|
||||
../nes_emu/nes_util.cpp \
|
||||
../nes_emu/Nes_Vrc6_Apu.cpp \
|
||||
../nes_emu/Mmc24.cpp \
|
||||
../bizinterface.cpp \
|
||||
../fex/Data_Reader.cpp \
|
||||
../fex/blargg_errors.cpp \
|
||||
|
|
|
@ -209,5 +209,8 @@ void register_optional_mappers()
|
|||
|
||||
extern void register_namco106_mapper();
|
||||
register_namco106_mapper();
|
||||
|
||||
extern void register_mmc24();
|
||||
register_mmc24();
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,117 @@
|
|||
#include <cstring>
|
||||
|
||||
#include "Nes_Mapper.h"
|
||||
#include "blargg_source.h"
|
||||
|
||||
#include "Mmc24.h"
|
||||
|
||||
|
||||
class MMC2: public Nes_Mapper
|
||||
{
|
||||
byte regs[6]; // A,B,C,D,E,F
|
||||
|
||||
void mirror(byte val)
|
||||
{
|
||||
if (val & 1)
|
||||
mirror_horiz();
|
||||
else
|
||||
mirror_vert();
|
||||
}
|
||||
|
||||
public:
|
||||
MMC2()
|
||||
{
|
||||
register_state(regs, sizeof(regs));
|
||||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{
|
||||
std::memset(regs, 0, sizeof(regs));
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
mirror(regs[5]);
|
||||
set_prg_bank(0x8000, bank_8k, regs[0]);
|
||||
set_prg_bank(0xa000, bank_8k, 13);
|
||||
set_prg_bank(0xc000, bank_8k, 14);
|
||||
set_prg_bank(0xe000, bank_8k, 15);
|
||||
|
||||
set_chr_bank(0x0000, bank_4k, regs[1]);
|
||||
set_chr_bank(0x1000, bank_4k, regs[3]);
|
||||
|
||||
set_chr_bank_ex(0x0000, bank_4k, regs[2]);
|
||||
set_chr_bank_ex(0x1000, bank_4k, regs[4]);
|
||||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data)
|
||||
{
|
||||
switch (addr >> 12)
|
||||
{
|
||||
case 0xa: regs[0] = data; set_prg_bank(0x8000, bank_8k, data); break;
|
||||
case 0xb: regs[1] = data; set_chr_bank(0x0000, bank_4k, data); break;
|
||||
case 0xc: regs[2] = data; set_chr_bank_ex(0x0000, bank_4k, data); break;
|
||||
case 0xd: regs[3] = data; set_chr_bank(0x1000, bank_4k, data); break;
|
||||
case 0xe: regs[4] = data; set_chr_bank_ex(0x1000, bank_4k, data); break;
|
||||
case 0xf: regs[5] = data; mirror(data); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
class MMC4: public Nes_Mapper
|
||||
{
|
||||
byte regs[6]; // A,B,C,D,E,F
|
||||
|
||||
void mirror(byte val)
|
||||
{
|
||||
if (val & 1)
|
||||
mirror_horiz();
|
||||
else
|
||||
mirror_vert();
|
||||
}
|
||||
|
||||
public:
|
||||
MMC4()
|
||||
{
|
||||
register_state(regs, sizeof(regs));
|
||||
}
|
||||
|
||||
virtual void reset_state()
|
||||
{
|
||||
std::memset(regs, 0, sizeof(regs));
|
||||
}
|
||||
|
||||
virtual void apply_mapping()
|
||||
{
|
||||
enable_sram();
|
||||
|
||||
mirror(regs[5]);
|
||||
set_prg_bank(0x8000, bank_16k, regs[0]);
|
||||
|
||||
set_chr_bank(0x0000, bank_4k, regs[1]);
|
||||
set_chr_bank(0x1000, bank_4k, regs[3]);
|
||||
|
||||
set_chr_bank_ex(0x0000, bank_4k, regs[2]);
|
||||
set_chr_bank_ex(0x1000, bank_4k, regs[4]);
|
||||
}
|
||||
|
||||
virtual void write(nes_time_t, nes_addr_t addr, int data)
|
||||
{
|
||||
switch (addr >> 12)
|
||||
{
|
||||
case 0xa: regs[0] = data; set_prg_bank(0x8000, bank_16k, data); break;
|
||||
case 0xb: regs[1] = data; set_chr_bank(0x0000, bank_4k, data); break;
|
||||
case 0xc: regs[2] = data; set_chr_bank_ex(0x0000, bank_4k, data); break;
|
||||
case 0xd: regs[3] = data; set_chr_bank(0x1000, bank_4k, data); break;
|
||||
case 0xe: regs[4] = data; set_chr_bank_ex(0x1000, bank_4k, data); break;
|
||||
case 0xf: regs[5] = data; mirror(data); break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
void register_mmc24()
|
||||
{
|
||||
register_mapper<MMC2>(9);
|
||||
register_mapper<MMC4>(10);
|
||||
}
|
|
@ -0,0 +1,7 @@
|
|||
#ifndef MMC24_H
|
||||
#define MMC24_H
|
||||
|
||||
|
||||
void register_mmc24();
|
||||
|
||||
#endif
|
|
@ -148,6 +148,12 @@ void Nes_Mapper::set_chr_bank( nes_addr_t addr, bank_size_t bs, int bank )
|
|||
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() );
|
||||
|
|
|
@ -121,6 +121,7 @@ protected:
|
|||
|
||||
// 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 );
|
||||
|
||||
// Set PPU mirroring. All mappings implemented using mirror_manual().
|
||||
void mirror_manual( int page0, int page1, int page2, int page3 );
|
||||
|
|
|
@ -226,7 +226,7 @@ inline void Nes_Ppu::invalidate_sprite_max( nes_time_t t )
|
|||
|
||||
// Sprite 0 hit
|
||||
|
||||
inline int Nes_Ppu_Impl::first_opaque_sprite_line() const
|
||||
inline int Nes_Ppu_Impl::first_opaque_sprite_line() /*const*/
|
||||
{
|
||||
// advance earliest time if sprite has blank lines at beginning
|
||||
byte const* p = map_chr( sprite_tile_index( spr_ram ) * 16 );
|
||||
|
|
|
@ -66,4 +66,3 @@ while ( true )
|
|||
if ( !count )
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@ Nes_Ppu_Impl::Nes_Ppu_Impl()
|
|||
max_palette_size = 0;
|
||||
tile_cache_mem = NULL;
|
||||
ppu_state_t::unused = 0;
|
||||
|
||||
mmc24_enabled = false;
|
||||
mmc24_latched[0] = 0;
|
||||
mmc24_latched[1] = 0;
|
||||
|
||||
#ifndef NDEBUG
|
||||
// verify that unaligned accesses work
|
||||
|
@ -126,6 +130,29 @@ void Nes_Ppu_Impl::set_chr_bank( int addr, int size, long data )
|
|||
}
|
||||
}
|
||||
|
||||
void Nes_Ppu_Impl::set_chr_bank_ex( int addr, int size, long data )
|
||||
{
|
||||
mmc24_enabled = true;
|
||||
|
||||
check( !chr_is_writable || addr == data ); // to do: is CHR RAM ever bank-switched?
|
||||
//dprintf( "Tried to set CHR RAM bank at %04X to CHR+%04X\n", addr, data );
|
||||
|
||||
if ( data + size > chr_size )
|
||||
data %= chr_size;
|
||||
|
||||
int count = (unsigned) size / chr_page_size;
|
||||
assert( chr_page_size * count == size );
|
||||
assert( addr + size <= chr_addr_size );
|
||||
|
||||
int page = (unsigned) addr / chr_page_size;
|
||||
while ( count-- )
|
||||
{
|
||||
chr_pages_ex [page] = data - page * chr_page_size;
|
||||
page++;
|
||||
data += chr_page_size;
|
||||
}
|
||||
}
|
||||
|
||||
void Nes_Ppu_Impl::save_state( Nes_State_* out ) const
|
||||
{
|
||||
*out->ppu = *this;
|
||||
|
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
// NES PPU misc functions and setup
|
||||
|
||||
// Nes_Emu 0.7.0
|
||||
|
@ -45,6 +44,7 @@ public:
|
|||
enum { vaddr_clock_mask = 0x1000 };
|
||||
void set_nt_banks( int bank0, int bank1, int bank2, int bank3 );
|
||||
void set_chr_bank( int addr, int size, long data );
|
||||
void set_chr_bank_ex( int addr, int size, long data );
|
||||
|
||||
// Nametable and CHR RAM
|
||||
enum { nt_ram_size = 0x1000 };
|
||||
|
@ -77,7 +77,7 @@ protected: //friend class Nes_Ppu; private:
|
|||
|
||||
enum { last_sprite_max_scanline = 240 };
|
||||
long recalc_sprite_max( int scanline );
|
||||
int first_opaque_sprite_line() const;
|
||||
int first_opaque_sprite_line() /*const*/;
|
||||
|
||||
protected: //friend class Nes_Ppu_Rendering; private:
|
||||
|
||||
|
@ -91,8 +91,8 @@ protected: //friend class Nes_Ppu_Rendering; private:
|
|||
|
||||
typedef uint32_t cache_t;
|
||||
typedef cache_t cached_tile_t [4];
|
||||
cached_tile_t const& get_bg_tile( int index ) const;
|
||||
cached_tile_t const& get_sprite_tile( byte const* sprite ) const;
|
||||
cached_tile_t const& get_bg_tile( int index ) /*const*/;
|
||||
cached_tile_t const& get_sprite_tile( byte const* sprite ) /*const*/;
|
||||
byte* get_nametable( int addr ) { return nt_banks [addr >> 10 & 3]; };
|
||||
|
||||
private:
|
||||
|
@ -103,14 +103,37 @@ private:
|
|||
// Mapping
|
||||
enum { chr_page_size = 0x400 };
|
||||
long chr_pages [chr_addr_size / chr_page_size];
|
||||
long map_chr_addr( unsigned a ) const { return chr_pages [a / chr_page_size] + a; }
|
||||
long chr_pages_ex [chr_addr_size / chr_page_size];
|
||||
long map_chr_addr( unsigned a ) /*const*/
|
||||
{
|
||||
if (!mmc24_enabled)
|
||||
return chr_pages [a / chr_page_size] + a;
|
||||
|
||||
int page = a >> 12 & 1;
|
||||
int newval0 = (a & 0xff0) != 0xfd0;
|
||||
int newval1 = (a & 0xff0) == 0xfe0;
|
||||
|
||||
long ret;
|
||||
if (mmc24_latched[page])
|
||||
ret = chr_pages_ex [a / chr_page_size] + a;
|
||||
else
|
||||
ret = chr_pages [a / chr_page_size] + a;
|
||||
|
||||
mmc24_latched[page] &= newval0;
|
||||
mmc24_latched[page] |= newval1;
|
||||
|
||||
return ret;
|
||||
}
|
||||
byte* nt_banks [4];
|
||||
|
||||
bool mmc24_enabled;
|
||||
byte mmc24_latched [2];
|
||||
|
||||
// CHR data
|
||||
byte const* chr_data; // points to chr ram when there is no read-only data
|
||||
byte* chr_ram; // always points to impl->chr_ram; makes write_2007() faster
|
||||
long chr_size;
|
||||
byte const* map_chr( int addr ) const { return &chr_data [map_chr_addr( addr )]; }
|
||||
byte const* map_chr( int addr ) /*const*/ { return &chr_data [map_chr_addr( addr )]; }
|
||||
|
||||
// CHR cache
|
||||
cached_tile_t* tile_cache;
|
||||
|
|
|
@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
|
|||
// Nes_Ppu_Impl
|
||||
|
||||
inline Nes_Ppu_Impl::cached_tile_t const&
|
||||
Nes_Ppu_Impl::get_sprite_tile( byte const* sprite ) const
|
||||
Nes_Ppu_Impl::get_sprite_tile( byte const* sprite ) /*const*/
|
||||
{
|
||||
cached_tile_t* tiles = tile_cache;
|
||||
if ( sprite [2] & 0x40 )
|
||||
|
@ -45,7 +45,7 @@ inline Nes_Ppu_Impl::cached_tile_t const&
|
|||
((byte*) tiles + map_chr_addr( index * bytes_per_tile ));
|
||||
}
|
||||
|
||||
inline Nes_Ppu_Impl::cached_tile_t const& Nes_Ppu_Impl::get_bg_tile( int index ) const
|
||||
inline Nes_Ppu_Impl::cached_tile_t const& Nes_Ppu_Impl::get_bg_tile( int index ) /*const*/
|
||||
{
|
||||
// use index directly, since cached tile is same size as native tile
|
||||
BOOST_STATIC_ASSERT( sizeof (cached_tile_t) == bytes_per_tile );
|
||||
|
|
Loading…
Reference in New Issue