mirror of
https://github.com/libretro/nestopia.git
synced 2024-11-23 08:29:47 +00:00
Update core to 1.52.0
This commit is contained in:
parent
170b3bebbe
commit
63a4a991d3
@ -248,13 +248,16 @@ SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxcMxmdhtwo.cpp
|
|||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxcPoliceman.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxcPoliceman.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxcTw.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxcTw.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxRom.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardTxRom.cpp
|
||||||
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnl158b.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlA9746.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlA9746.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlCc21.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlCc21.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlEdu2000.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlEdu2000.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlKingOfFighters96.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlKingOfFighters96.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlKingOfFighters97.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlKingOfFighters97.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlMortalKombat2.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlMortalKombat2.cpp
|
||||||
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlMmc3BigPrgRom.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlN625092.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlN625092.cpp
|
||||||
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlRetX7Gbl.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlSuperFighter3.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlSuperFighter3.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlTf1201.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlTf1201.cpp
|
||||||
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlWorldHero.cpp
|
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardUnlWorldHero.cpp
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
#include "nstdatabase.hpp"
|
#include "nstdatabase.hpp"
|
||||||
|
|
||||||
#define NST_VERSION "1.51.1"
|
#define NST_VERSION "1.52.0"
|
||||||
|
|
||||||
#define MIN(a,b) ((a)<(b)?(a):(b))
|
#define MIN(a,b) ((a)<(b)?(a):(b))
|
||||||
#define MAX(a,b) ((a)>(b)?(a):(b))
|
#define MAX(a,b) ((a)>(b)?(a):(b))
|
||||||
@ -1557,7 +1557,6 @@ bool retro_load_game(const struct retro_game_info *info)
|
|||||||
ivideo.SetRenderState(state);
|
ivideo.SetRenderState(state);
|
||||||
|
|
||||||
Api::Sound isound(emulator);
|
Api::Sound isound(emulator);
|
||||||
isound.SetSampleBits(16);
|
|
||||||
isound.SetSampleRate(SAMPLERATE);
|
isound.SetSampleRate(SAMPLERATE);
|
||||||
isound.SetSpeaker(Api::Sound::SPEAKER_MONO);
|
isound.SetSpeaker(Api::Sound::SPEAKER_MONO);
|
||||||
|
|
||||||
|
@ -238,7 +238,7 @@ namespace Nes
|
|||||||
|
|
||||||
stream = NULL;
|
stream = NULL;
|
||||||
|
|
||||||
buffer.Reset( settings.bits );
|
buffer.Reset();
|
||||||
|
|
||||||
if (on)
|
if (on)
|
||||||
{
|
{
|
||||||
@ -297,7 +297,7 @@ namespace Nes
|
|||||||
if (!rate)
|
if (!rate)
|
||||||
return RESULT_ERR_INVALID_PARAM;
|
return RESULT_ERR_INVALID_PARAM;
|
||||||
|
|
||||||
if (rate < 11025 || rate > 96000)
|
if (rate < 44100 || rate > 96000)
|
||||||
return RESULT_ERR_UNSUPPORTED;
|
return RESULT_ERR_UNSUPPORTED;
|
||||||
|
|
||||||
settings.rate = rate;
|
settings.rate = rate;
|
||||||
@ -306,23 +306,6 @@ namespace Nes
|
|||||||
return RESULT_OK;
|
return RESULT_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Apu::SetSampleBits(const uint bits)
|
|
||||||
{
|
|
||||||
if (settings.bits == bits)
|
|
||||||
return RESULT_NOP;
|
|
||||||
|
|
||||||
if (!bits)
|
|
||||||
return RESULT_ERR_INVALID_PARAM;
|
|
||||||
|
|
||||||
if (bits != 8 && bits != 16)
|
|
||||||
return RESULT_ERR_UNSUPPORTED;
|
|
||||||
|
|
||||||
settings.bits = bits;
|
|
||||||
UpdateSettings();
|
|
||||||
|
|
||||||
return RESULT_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Apu::SetVolume(const uint channels,const uint volume)
|
Result Apu::SetVolume(const uint channels,const uint volume)
|
||||||
{
|
{
|
||||||
if (volume > 100)
|
if (volume > 100)
|
||||||
@ -421,7 +404,7 @@ namespace Nes
|
|||||||
cycles.Update( settings.rate, settings.speed, cpu );
|
cycles.Update( settings.rate, settings.speed, cpu );
|
||||||
synchronizer.Reset( settings.speed, settings.rate, cpu );
|
synchronizer.Reset( settings.speed, settings.rate, cpu );
|
||||||
dcBlocker.Reset();
|
dcBlocker.Reset();
|
||||||
buffer.Reset( settings.bits );
|
buffer.Reset();
|
||||||
|
|
||||||
Cycle rate; uint fixed;
|
Cycle rate; uint fixed;
|
||||||
CalculateOscillatorClock( rate, fixed );
|
CalculateOscillatorClock( rate, fixed );
|
||||||
@ -863,20 +846,10 @@ namespace Nes
|
|||||||
{
|
{
|
||||||
streamed = stream->length[0] + stream->length[1];
|
streamed = stream->length[0] + stream->length[1];
|
||||||
|
|
||||||
if (settings.bits == 16)
|
|
||||||
{
|
|
||||||
if (!settings.stereo)
|
if (!settings.stereo)
|
||||||
FlushSound<iword,false>();
|
FlushSound<iword,false>();
|
||||||
else
|
else
|
||||||
FlushSound<iword,true>();
|
FlushSound<iword,true>();
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (!settings.stereo)
|
|
||||||
FlushSound<byte,false>();
|
|
||||||
else
|
|
||||||
FlushSound<byte,true>();
|
|
||||||
}
|
|
||||||
|
|
||||||
Sound::Output::unlockCallback( *stream );
|
Sound::Output::unlockCallback( *stream );
|
||||||
}
|
}
|
||||||
@ -921,7 +894,7 @@ namespace Nes
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
Apu::Settings::Settings()
|
Apu::Settings::Settings()
|
||||||
: rate(44100), bits(16), speed(0), muted(false), transpose(false), stereo(false), audible(true)
|
: rate(44100), speed(0), muted(false), transpose(false), stereo(false), audible(true)
|
||||||
{
|
{
|
||||||
for (uint i=0; i < MAX_CHANNELS; ++i)
|
for (uint i=0; i < MAX_CHANNELS; ++i)
|
||||||
volumes[i] = Channel::DEFAULT_VOLUME;
|
volumes[i] = Channel::DEFAULT_VOLUME;
|
||||||
@ -2474,7 +2447,7 @@ namespace Nes
|
|||||||
|
|
||||||
dcBlocker.Reset();
|
dcBlocker.Reset();
|
||||||
|
|
||||||
buffer.Reset( settings.bits, false );
|
buffer.Reset( false );
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef NST_MSVC_OPTIMIZE
|
#ifdef NST_MSVC_OPTIMIZE
|
||||||
|
@ -60,7 +60,6 @@ namespace Nes
|
|||||||
void ClockDMA(uint=0);
|
void ClockDMA(uint=0);
|
||||||
|
|
||||||
Result SetSampleRate(dword);
|
Result SetSampleRate(dword);
|
||||||
Result SetSampleBits(uint);
|
|
||||||
Result SetSpeed(uint);
|
Result SetSpeed(uint);
|
||||||
Result SetVolume(uint,uint);
|
Result SetVolume(uint,uint);
|
||||||
uint GetVolume(uint) const;
|
uint GetVolume(uint) const;
|
||||||
@ -601,7 +600,6 @@ namespace Nes
|
|||||||
Settings();
|
Settings();
|
||||||
|
|
||||||
dword rate;
|
dword rate;
|
||||||
uint bits;
|
|
||||||
byte speed;
|
byte speed;
|
||||||
bool muted;
|
bool muted;
|
||||||
bool transpose;
|
bool transpose;
|
||||||
@ -643,11 +641,6 @@ namespace Nes
|
|||||||
return settings.rate;
|
return settings.rate;
|
||||||
}
|
}
|
||||||
|
|
||||||
uint GetSampleBits() const
|
|
||||||
{
|
|
||||||
return settings.bits;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint GetSpeed() const
|
uint GetSpeed() const
|
||||||
{
|
{
|
||||||
return settings.speed;
|
return settings.speed;
|
||||||
|
@ -147,7 +147,7 @@ namespace Nes
|
|||||||
Log::Flush( "Ines: PRG-ROM was patched" NST_LINEBREAK );
|
Log::Flush( "Ines: PRG-ROM was patched" NST_LINEBREAK );
|
||||||
|
|
||||||
if (Load( chr, 16 + prg.Size() ))
|
if (Load( chr, 16 + prg.Size() ))
|
||||||
Log::Flush( "Ines: PRG-ROM was patched" NST_LINEBREAK );
|
Log::Flush( "Ines: CHR-ROM was patched" NST_LINEBREAK );
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -124,7 +124,7 @@ namespace Nes
|
|||||||
0x00, 0x20, 0x00, 0x20, 0x04, 0x04, 0x04, 0x04,
|
0x00, 0x20, 0x00, 0x20, 0x04, 0x04, 0x04, 0x04,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
|
0x00, 0x00, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
|
||||||
0x00, 0x20, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
|
0x00, 0x20, 0x00, 0x00, 0x08, 0x08, 0x08, 0x08,
|
||||||
0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x00, 0x00,
|
0x00, 0x10, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
@ -2128,11 +2128,12 @@ namespace Nes
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Unofficial Opcodes SHX/SHY are edge cases
|
// Unofficial Opcodes SHX/SHY are edge cases
|
||||||
#define NES_I_W_U(instr_,addr_,hex_) \
|
#define NES_I_W_U(instr_,hex_) \
|
||||||
\
|
\
|
||||||
void Cpu::op##hex_() \
|
void Cpu::op##hex_() \
|
||||||
{ \
|
{ \
|
||||||
const uint dst = addr_##_W(); \
|
const uint dst = FetchPc16(); \
|
||||||
|
cycles.count += cycles.clock[3]; \
|
||||||
instr_(dst); \
|
instr_(dst); \
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2393,8 +2394,8 @@ namespace Nes
|
|||||||
NES_I_W_A( Sha, AbsY, 0x9F )
|
NES_I_W_A( Sha, AbsY, 0x9F )
|
||||||
NES_I_W_A( Sha, IndY, 0x93 )
|
NES_I_W_A( Sha, IndY, 0x93 )
|
||||||
NES_I_W_A( Shs, AbsY, 0x9B )
|
NES_I_W_A( Shs, AbsY, 0x9B )
|
||||||
NES_I_W_U( Shx, Abs, 0x9E ) // Edge case: AbsY done internally
|
NES_I_W_U( Shx, 0x9E ) // Edge case: AbsY done internally
|
||||||
NES_I_W_U( Shy, Abs, 0x9C ) // Edge case: AbsX done internally
|
NES_I_W_U( Shy, 0x9C ) // Edge case: AbsX done internally
|
||||||
NES_IRW__( Slo, Zpg, 0x07 )
|
NES_IRW__( Slo, Zpg, 0x07 )
|
||||||
NES_IRW__( Slo, ZpgX, 0x17 )
|
NES_IRW__( Slo, ZpgX, 0x17 )
|
||||||
NES_IRW__( Slo, Abs, 0x0F )
|
NES_IRW__( Slo, Abs, 0x0F )
|
||||||
|
@ -221,17 +221,36 @@ namespace Nes
|
|||||||
{
|
{
|
||||||
NST_ASSERT( it->length );
|
NST_ASSERT( it->length );
|
||||||
|
|
||||||
|
bool underflow = false;
|
||||||
|
dword uflow_length = 0;
|
||||||
|
|
||||||
if (it->offset < offset)
|
if (it->offset < offset)
|
||||||
|
{
|
||||||
|
if (it->offset + it->length > offset)
|
||||||
|
{
|
||||||
|
underflow = true;
|
||||||
|
uflow_length = offset - it->offset;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (it->offset >= offset + length)
|
if (it->offset >= offset + length)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
const dword pos = it->offset - offset;
|
dword pos = it->offset - offset;
|
||||||
const dword part = NST_MIN(it->length,length-pos);
|
dword part = NST_MIN(it->length,length-pos);
|
||||||
|
|
||||||
|
if (underflow)
|
||||||
|
{
|
||||||
|
part -= uflow_length;
|
||||||
|
pos += uflow_length;
|
||||||
|
}
|
||||||
|
|
||||||
if (it->fill == NO_FILL)
|
if (it->fill == NO_FILL)
|
||||||
std::memcpy( dst + pos, it->data, part );
|
std::memcpy( dst + pos, it->data + uflow_length, part );
|
||||||
else
|
else
|
||||||
std::memset( dst + pos, it->fill, part );
|
std::memset( dst + pos, it->fill, part );
|
||||||
|
|
||||||
|
@ -401,6 +401,8 @@ namespace Nes
|
|||||||
state.End();
|
state.End();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
output.bgColor = palette.ram[0] & uint(Palette::COLOR);
|
||||||
|
|
||||||
UpdateStates();
|
UpdateStates();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -774,6 +776,17 @@ namespace Nes
|
|||||||
return (regs.ctrl[1] & Regs::CTRL1_EMPHASIS) << 1;
|
return (regs.ctrl[1] & Regs::CTRL1_EMPHASIS) << 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NST_FORCE_INLINE void Ppu::UpdateDecay(byte mask)
|
||||||
|
{
|
||||||
|
Cycle curCyc = cpu.GetCycles();
|
||||||
|
|
||||||
|
for (uint i = 0; i < 8; ++i)
|
||||||
|
{
|
||||||
|
if (mask & (1 << i))
|
||||||
|
decay.timestamp[i] = curCyc;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
NES_POKE_D(Ppu,2000)
|
NES_POKE_D(Ppu,2000)
|
||||||
{
|
{
|
||||||
Update( cycles.one );
|
Update( cycles.one );
|
||||||
@ -786,6 +799,8 @@ namespace Nes
|
|||||||
oam.height = (data >> 2 & 8) + 8;
|
oam.height = (data >> 2 & 8) + 8;
|
||||||
|
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
data = regs.ctrl[0] ;
|
data = regs.ctrl[0] ;
|
||||||
regs.ctrl[0] = io.latch;
|
regs.ctrl[0] = io.latch;
|
||||||
|
|
||||||
@ -825,6 +840,8 @@ namespace Nes
|
|||||||
}
|
}
|
||||||
|
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
data = (regs.ctrl[1] ^ data) & (Regs::CTRL1_EMPHASIS|Regs::CTRL1_MONOCHROME);
|
data = (regs.ctrl[1] ^ data) & (Regs::CTRL1_EMPHASIS|Regs::CTRL1_MONOCHROME);
|
||||||
regs.ctrl[1] = io.latch;
|
regs.ctrl[1] = io.latch;
|
||||||
|
|
||||||
@ -852,13 +869,22 @@ namespace Nes
|
|||||||
{
|
{
|
||||||
Update( cycles.one, address );
|
Update( cycles.one, address );
|
||||||
|
|
||||||
|
byte mask = 0xE0;
|
||||||
uint status = regs.status & 0xFF;
|
uint status = regs.status & 0xFF;
|
||||||
|
|
||||||
regs.status &= (Regs::STATUS_VBLANK^0xFFU);
|
regs.status &= (Regs::STATUS_VBLANK^0xFFU);
|
||||||
scroll.toggle = 0;
|
scroll.toggle = 0;
|
||||||
io.latch = (io.latch & Regs::STATUS_LATCH) | status;
|
io.latch = (io.latch & Regs::STATUS_LATCH) | status;
|
||||||
|
UpdateDecay(mask);
|
||||||
|
|
||||||
return io.latch;
|
Cycle curCyc = cpu.GetCycles();
|
||||||
|
for (uint i = 0; i < 5; ++i)
|
||||||
|
{
|
||||||
|
if ((curCyc - decay.timestamp[i]) < 24576)
|
||||||
|
mask |= (1 << i);
|
||||||
|
}
|
||||||
|
|
||||||
|
return io.latch & mask;
|
||||||
}
|
}
|
||||||
|
|
||||||
NES_PEEK_A(Ppu,2002_RC2C05_01_04)
|
NES_PEEK_A(Ppu,2002_RC2C05_01_04)
|
||||||
@ -882,6 +908,7 @@ namespace Nes
|
|||||||
|
|
||||||
regs.oam = data;
|
regs.oam = data;
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
NES_POKE_D(Ppu,2004)
|
NES_POKE_D(Ppu,2004)
|
||||||
@ -891,6 +918,9 @@ namespace Nes
|
|||||||
NST_ASSERT( regs.oam < Oam::SIZE );
|
NST_ASSERT( regs.oam < Oam::SIZE );
|
||||||
NST_VERIFY( IsDead() );
|
NST_VERIFY( IsDead() );
|
||||||
|
|
||||||
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
if (IsDead())
|
if (IsDead())
|
||||||
{
|
{
|
||||||
if ((regs.oam & 0x03) == 0x02)
|
if ((regs.oam & 0x03) == 0x02)
|
||||||
@ -903,7 +933,6 @@ namespace Nes
|
|||||||
|
|
||||||
byte* const NST_RESTRICT value = oam.ram + regs.oam;
|
byte* const NST_RESTRICT value = oam.ram + regs.oam;
|
||||||
regs.oam = (regs.oam + 1) & 0xFF;
|
regs.oam = (regs.oam + 1) & 0xFF;
|
||||||
io.latch = data;
|
|
||||||
*value = data;
|
*value = data;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -914,12 +943,14 @@ namespace Nes
|
|||||||
if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || cpu.GetCycles() - (cpu.GetFrameCycles() - (341 * 241) * cycles.one) >= (341 * 240) * cycles.one)
|
if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || cpu.GetCycles() - (cpu.GetFrameCycles() - (341 * 241) * cycles.one) >= (341 * 240) * cycles.one)
|
||||||
{
|
{
|
||||||
io.latch = oam.ram[regs.oam];
|
io.latch = oam.ram[regs.oam];
|
||||||
|
UpdateDecay(0xFF);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Update( cycles.one );
|
Update( cycles.one );
|
||||||
|
|
||||||
io.latch = oam.latch;
|
io.latch = oam.latch;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
return io.latch;
|
return io.latch;
|
||||||
@ -934,6 +965,7 @@ namespace Nes
|
|||||||
if (cpu.GetCycles() >= cycles.reset)
|
if (cpu.GetCycles() >= cycles.reset)
|
||||||
{
|
{
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
if (scroll.toggle ^= 1)
|
if (scroll.toggle ^= 1)
|
||||||
{
|
{
|
||||||
@ -956,6 +988,7 @@ namespace Nes
|
|||||||
if (cpu.GetCycles() >= cycles.reset)
|
if (cpu.GetCycles() >= cycles.reset)
|
||||||
{
|
{
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
if (scroll.toggle ^= 1)
|
if (scroll.toggle ^= 1)
|
||||||
{
|
{
|
||||||
@ -984,6 +1017,7 @@ namespace Nes
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
if ((address & 0x3F00) == 0x3F00)
|
if ((address & 0x3F00) == 0x3F00)
|
||||||
{
|
{
|
||||||
@ -1015,27 +1049,54 @@ namespace Nes
|
|||||||
|
|
||||||
NES_PEEK_A(Ppu,2007)
|
NES_PEEK_A(Ppu,2007)
|
||||||
{
|
{
|
||||||
|
byte mask = 0xFF;
|
||||||
|
byte cache = io.latch;
|
||||||
|
|
||||||
Update( cycles.one, address );
|
Update( cycles.one, address );
|
||||||
|
|
||||||
|
Cycle curCyc = cpu.GetCycles();
|
||||||
|
Cycle delta = curCyc - decay.rd2007;
|
||||||
|
decay.rd2007 = curCyc;
|
||||||
|
|
||||||
|
bool fastread = (delta <= 12);
|
||||||
|
|
||||||
address = scroll.address & 0x3FFF;
|
address = scroll.address & 0x3FFF;
|
||||||
UpdateVramAddress();
|
UpdateVramAddress();
|
||||||
|
|
||||||
if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || (scanline == SCANLINE_VBLANK))
|
if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || (scanline == SCANLINE_VBLANK))
|
||||||
UpdateAddressLine(scroll.address & 0x3fff);
|
UpdateAddressLine(scroll.address & 0x3fff);
|
||||||
|
|
||||||
io.latch = (address & 0x3F00) != 0x3F00 ? io.buffer : palette.ram[address & 0x1F] & Coloring();
|
if ((address & 0x3F00) == 0x3F00) // Palette
|
||||||
|
{
|
||||||
|
io.latch = (io.latch & 0xC0) | palette.ram[address & 0x1F] & Coloring();
|
||||||
|
mask = 0x3F;
|
||||||
|
}
|
||||||
|
else // Non-Palette
|
||||||
|
{
|
||||||
|
io.latch = io.buffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateDecay(mask);
|
||||||
|
|
||||||
io.buffer = (address >= 0x2000 ? nmt.FetchName( address ) : chr.FetchPattern( address ));
|
io.buffer = (address >= 0x2000 ? nmt.FetchName( address ) : chr.FetchPattern( address ));
|
||||||
|
|
||||||
|
if (fastread)
|
||||||
|
io.latch = cache;
|
||||||
|
|
||||||
return io.latch;
|
return io.latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
NES_POKE_D(Ppu,2xxx)
|
NES_POKE_D(Ppu,2xxx)
|
||||||
{
|
{
|
||||||
io.latch = data;
|
io.latch = data;
|
||||||
|
UpdateDecay(0xFF);
|
||||||
}
|
}
|
||||||
|
|
||||||
NES_PEEK(Ppu,2xxx)
|
NES_PEEK(Ppu,2xxx)
|
||||||
{
|
{
|
||||||
|
if ((cpu.GetCycles() - decay.timestamp[0]) > 24576)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return io.latch;
|
return io.latch;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1074,10 +1135,13 @@ namespace Nes
|
|||||||
}
|
}
|
||||||
|
|
||||||
io.latch = oamRam[0xFF];
|
io.latch = oamRam[0xFF];
|
||||||
|
UpdateDecay(0xFF);
|
||||||
}
|
}
|
||||||
else do
|
else do
|
||||||
{
|
{
|
||||||
io.latch = cpu.Peek( data++ );
|
io.latch = cpu.Peek( data++ );
|
||||||
|
UpdateDecay(0xFF);
|
||||||
|
|
||||||
cpu.StealCycles( cpu.GetClock() );
|
cpu.StealCycles( cpu.GetClock() );
|
||||||
|
|
||||||
Update( cycles.one );
|
Update( cycles.one );
|
||||||
|
@ -186,6 +186,7 @@ namespace Nes
|
|||||||
NST_FORCE_INLINE uint FetchSpPattern() const;
|
NST_FORCE_INLINE uint FetchSpPattern() const;
|
||||||
NST_FORCE_INLINE void FetchBgPattern0();
|
NST_FORCE_INLINE void FetchBgPattern0();
|
||||||
NST_FORCE_INLINE void FetchBgPattern1();
|
NST_FORCE_INLINE void FetchBgPattern1();
|
||||||
|
NST_FORCE_INLINE void UpdateDecay(byte);
|
||||||
|
|
||||||
NST_FORCE_INLINE void EvaluateSpritesEven();
|
NST_FORCE_INLINE void EvaluateSpritesEven();
|
||||||
NST_FORCE_INLINE void EvaluateSpritesOdd();
|
NST_FORCE_INLINE void EvaluateSpritesOdd();
|
||||||
@ -407,6 +408,12 @@ namespace Nes
|
|||||||
Cycle reset;
|
Cycle reset;
|
||||||
} cycles;
|
} cycles;
|
||||||
|
|
||||||
|
struct
|
||||||
|
{
|
||||||
|
Cycle timestamp[8];
|
||||||
|
Cycle rd2007;
|
||||||
|
} decay;
|
||||||
|
|
||||||
Io io;
|
Io io;
|
||||||
Regs regs;
|
Regs regs;
|
||||||
Scroll scroll;
|
Scroll scroll;
|
||||||
@ -419,7 +426,6 @@ namespace Nes
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
Output output;
|
Output output;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
PpuModel model;
|
PpuModel model;
|
||||||
Hook hActiveHook;
|
Hook hActiveHook;
|
||||||
|
@ -39,7 +39,7 @@ namespace Nes
|
|||||||
Buffer::Buffer(uint bits)
|
Buffer::Buffer(uint bits)
|
||||||
: output(new iword [SIZE])
|
: output(new iword [SIZE])
|
||||||
{
|
{
|
||||||
Reset( bits, true );
|
Reset( true );
|
||||||
}
|
}
|
||||||
|
|
||||||
Buffer::~Buffer()
|
Buffer::~Buffer()
|
||||||
@ -47,12 +47,12 @@ namespace Nes
|
|||||||
delete [] output;
|
delete [] output;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Buffer::Reset(uint bits,bool clear)
|
void Buffer::Reset(bool clear)
|
||||||
{
|
{
|
||||||
pos = start = 0;
|
pos = start = 0;
|
||||||
history.pos = 0;
|
history.pos = 0;
|
||||||
|
|
||||||
std::fill( history.buffer, history.buffer+History::SIZE, iword(bits == 16 ? 0 : 0x80) );
|
std::fill( history.buffer, history.buffer+History::SIZE, iword(0) );
|
||||||
|
|
||||||
if (clear)
|
if (clear)
|
||||||
std::fill( output, output+SIZE, iword(0) );
|
std::fill( output, output+SIZE, iword(0) );
|
||||||
|
@ -59,7 +59,7 @@ namespace Nes
|
|||||||
uint length;
|
uint length;
|
||||||
};
|
};
|
||||||
|
|
||||||
void Reset(uint,bool=true);
|
void Reset(bool=true);
|
||||||
void operator >> (Block&);
|
void operator >> (Block&);
|
||||||
|
|
||||||
template<typename,uint>
|
template<typename,uint>
|
||||||
|
@ -136,7 +136,6 @@ namespace Nes
|
|||||||
enabled (e),
|
enabled (e),
|
||||||
good (false),
|
good (false),
|
||||||
stereo (false),
|
stereo (false),
|
||||||
bits (0),
|
|
||||||
rate (0),
|
rate (0),
|
||||||
index (0),
|
index (0),
|
||||||
buffer (NULL),
|
buffer (NULL),
|
||||||
@ -268,14 +267,13 @@ namespace Nes
|
|||||||
|
|
||||||
bool Tracker::Rewinder::ReverseSound::Update()
|
bool Tracker::Rewinder::ReverseSound::Update()
|
||||||
{
|
{
|
||||||
const dword old = (bits == 16 ? size * sizeof(iword) : size * sizeof(byte));
|
const dword old = size * sizeof(iword);
|
||||||
|
|
||||||
bits = apu.GetSampleBits();
|
|
||||||
rate = apu.GetSampleRate();
|
rate = apu.GetSampleRate();
|
||||||
stereo = apu.InStereo();
|
stereo = apu.InStereo();
|
||||||
size = rate << (stereo+1);
|
size = rate << (stereo+1);
|
||||||
|
|
||||||
const dword total = (bits == 16 ? size * sizeof(iword) : size * sizeof(byte));
|
const dword total = size * sizeof(iword);
|
||||||
NST_ASSERT( total );
|
NST_ASSERT( total );
|
||||||
|
|
||||||
if (!buffer || total != old)
|
if (!buffer || total != old)
|
||||||
@ -296,10 +294,7 @@ namespace Nes
|
|||||||
good = true;
|
good = true;
|
||||||
index = 0;
|
index = 0;
|
||||||
|
|
||||||
if (bits == 16)
|
|
||||||
std::fill( static_cast<iword*>(buffer), static_cast<iword*>(buffer) + size, iword(0) );
|
std::fill( static_cast<iword*>(buffer), static_cast<iword*>(buffer) + size, iword(0) );
|
||||||
else
|
|
||||||
std::memset( buffer, 0x80, size );
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -587,13 +582,13 @@ namespace Nes
|
|||||||
{
|
{
|
||||||
NST_COMPILE_ASSERT( NUM_FRAMES % 2 == 0 );
|
NST_COMPILE_ASSERT( NUM_FRAMES % 2 == 0 );
|
||||||
|
|
||||||
if (!buffer || (bits ^ apu.GetSampleBits()) | (rate ^ apu.GetSampleRate()) | (stereo ^ uint(bool(apu.InStereo()))))
|
if (!buffer || (rate ^ apu.GetSampleRate()) | (stereo ^ uint(bool(apu.InStereo()))))
|
||||||
{
|
{
|
||||||
if (!good || !Update() || !enabled)
|
if (!good || !Update() || !enabled)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
return bits == 16 ? StoreType<iword>() : StoreType<byte>();
|
return StoreType<iword>();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T,int SILENCE>
|
template<typename T,int SILENCE>
|
||||||
@ -632,14 +627,11 @@ namespace Nes
|
|||||||
{
|
{
|
||||||
if (enabled & good)
|
if (enabled & good)
|
||||||
{
|
{
|
||||||
input = (bits == 16) ? ReverseCopy<iword>( *target ) : ReverseCopy<byte>( *target );
|
input = ReverseCopy<iword>( *target );
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
if (bits == 16)
|
|
||||||
ReverseSilence<iword,0>( *target );
|
ReverseSilence<iword,0>( *target );
|
||||||
else
|
|
||||||
ReverseSilence<byte,0x80>( *target );
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mutex.Unlock( *target );
|
mutex.Unlock( *target );
|
||||||
|
@ -181,7 +181,6 @@ namespace Nes
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
bool good;
|
bool good;
|
||||||
byte stereo;
|
byte stereo;
|
||||||
byte bits;
|
|
||||||
dword rate;
|
dword rate;
|
||||||
uint index;
|
uint index;
|
||||||
void* buffer;
|
void* buffer;
|
||||||
|
@ -67,7 +67,7 @@ namespace Nes
|
|||||||
HEIGHT = Input::HEIGHT,
|
HEIGHT = Input::HEIGHT,
|
||||||
PIXELS = Input::PIXELS,
|
PIXELS = Input::PIXELS,
|
||||||
PALETTE = Input::PALETTE,
|
PALETTE = Input::PALETTE,
|
||||||
DEFAULT_PALETTE = PALETTE_YUV
|
NST_DEFAULT_PALETTE = PALETTE_YUV
|
||||||
};
|
};
|
||||||
|
|
||||||
Result SetState(const RenderState&);
|
Result SetState(const RenderState&);
|
||||||
|
@ -62,11 +62,6 @@ namespace Nes
|
|||||||
return emulator.cpu.GetApu().SetSampleRate( rate );
|
return emulator.cpu.GetApu().SetSampleRate( rate );
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Sound::SetSampleBits(uint bits) throw()
|
|
||||||
{
|
|
||||||
return emulator.cpu.GetApu().SetSampleBits( bits );
|
|
||||||
}
|
|
||||||
|
|
||||||
Result Sound::SetVolume(uint channels,uint volume) throw()
|
Result Sound::SetVolume(uint channels,uint volume) throw()
|
||||||
{
|
{
|
||||||
return emulator.cpu.GetApu().SetVolume( channels, volume );
|
return emulator.cpu.GetApu().SetVolume( channels, volume );
|
||||||
@ -97,11 +92,6 @@ namespace Nes
|
|||||||
return emulator.cpu.GetApu().GetSampleRate();
|
return emulator.cpu.GetApu().GetSampleRate();
|
||||||
}
|
}
|
||||||
|
|
||||||
uint Sound::GetSampleBits() const throw()
|
|
||||||
{
|
|
||||||
return emulator.cpu.GetApu().GetSampleBits();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint Sound::GetVolume(uint channel) const throw()
|
uint Sound::GetVolume(uint channel) const throw()
|
||||||
{
|
{
|
||||||
return emulator.cpu.GetApu().GetVolume( channel );
|
return emulator.cpu.GetApu().GetVolume( channel );
|
||||||
|
@ -262,7 +262,7 @@ namespace Nes
|
|||||||
/**
|
/**
|
||||||
* Sets the sample rate.
|
* Sets the sample rate.
|
||||||
*
|
*
|
||||||
* @param rate value in the range 11025 to 96000, default is 44100
|
* @param rate value in the range 44100 to 96000, default is 44100
|
||||||
* @return result code
|
* @return result code
|
||||||
*/
|
*/
|
||||||
Result SetSampleRate(ulong rate) throw();
|
Result SetSampleRate(ulong rate) throw();
|
||||||
@ -274,21 +274,6 @@ namespace Nes
|
|||||||
*/
|
*/
|
||||||
ulong GetSampleRate() const throw();
|
ulong GetSampleRate() const throw();
|
||||||
|
|
||||||
/**
|
|
||||||
* Sets the sample bits.
|
|
||||||
*
|
|
||||||
* @param bits value of 8 or 16, default is 16
|
|
||||||
* @return result code
|
|
||||||
*/
|
|
||||||
Result SetSampleBits(uint bits) throw();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Returns the sample bits.
|
|
||||||
*
|
|
||||||
* @return number
|
|
||||||
*/
|
|
||||||
uint GetSampleBits() const throw();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the speaker type.
|
* Sets the speaker type.
|
||||||
*
|
*
|
||||||
|
@ -334,7 +334,7 @@ namespace Nes
|
|||||||
|
|
||||||
Video::Palette::Mode Video::Palette::GetDefaultMode() const throw()
|
Video::Palette::Mode Video::Palette::GetDefaultMode() const throw()
|
||||||
{
|
{
|
||||||
NST_COMPILE_ASSERT( Core::Video::Renderer::DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 );
|
NST_COMPILE_ASSERT( Core::Video::Renderer::NST_DEFAULT_PALETTE - Core::Video::Renderer::PALETTE_YUV == 0 );
|
||||||
|
|
||||||
return MODE_YUV;
|
return MODE_YUV;
|
||||||
}
|
}
|
||||||
|
@ -97,13 +97,16 @@
|
|||||||
#include "NstBoardWaixing.hpp"
|
#include "NstBoardWaixing.hpp"
|
||||||
#include "NstBoardWhirlwind.hpp"
|
#include "NstBoardWhirlwind.hpp"
|
||||||
#include "NstBoardBenshengBs5.hpp"
|
#include "NstBoardBenshengBs5.hpp"
|
||||||
|
#include "NstBoardUnl158b.hpp"
|
||||||
#include "NstBoardUnlA9746.hpp"
|
#include "NstBoardUnlA9746.hpp"
|
||||||
#include "NstBoardUnlCc21.hpp"
|
#include "NstBoardUnlCc21.hpp"
|
||||||
#include "NstBoardUnlEdu2000.hpp"
|
#include "NstBoardUnlEdu2000.hpp"
|
||||||
#include "NstBoardUnlKingOfFighters96.hpp"
|
#include "NstBoardUnlKingOfFighters96.hpp"
|
||||||
#include "NstBoardUnlKingOfFighters97.hpp"
|
#include "NstBoardUnlKingOfFighters97.hpp"
|
||||||
|
#include "NstBoardUnlMmc3BigPrgRom.hpp"
|
||||||
#include "NstBoardUnlMortalKombat2.hpp"
|
#include "NstBoardUnlMortalKombat2.hpp"
|
||||||
#include "NstBoardUnlN625092.hpp"
|
#include "NstBoardUnlN625092.hpp"
|
||||||
|
#include "NstBoardUnlRetX7Gbl.hpp"
|
||||||
#include "NstBoardUnlSuperFighter3.hpp"
|
#include "NstBoardUnlSuperFighter3.hpp"
|
||||||
#include "NstBoardUnlTf1201.hpp"
|
#include "NstBoardUnlTf1201.hpp"
|
||||||
#include "NstBoardUnlWorldHero.hpp"
|
#include "NstBoardUnlWorldHero.hpp"
|
||||||
@ -1096,6 +1099,7 @@ namespace Nes
|
|||||||
{ "TENGEN-800032", Type::TENGEN_800032 },
|
{ "TENGEN-800032", Type::TENGEN_800032 },
|
||||||
{ "TENGEN-800037", Type::TENGEN_800037 },
|
{ "TENGEN-800037", Type::TENGEN_800037 },
|
||||||
{ "TENGEN-800042", Type::TENGEN_800042 },
|
{ "TENGEN-800042", Type::TENGEN_800042 },
|
||||||
|
{ "UNL-158B", Type::UNL_158B },
|
||||||
{ "UNL-22211", Type::TXC_22211A },
|
{ "UNL-22211", Type::TXC_22211A },
|
||||||
{ "UNL-603-5052", Type::BTL_6035052 },
|
{ "UNL-603-5052", Type::BTL_6035052 },
|
||||||
{ "UNL-8237", Type::SUPERGAME_POCAHONTAS2 },
|
{ "UNL-8237", Type::SUPERGAME_POCAHONTAS2 },
|
||||||
@ -1472,6 +1476,13 @@ namespace Nes
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (prg > SIZE_512K)
|
||||||
|
{
|
||||||
|
name = "UNL-MMC3BIGPRGROM";
|
||||||
|
id = Type::UNL_MMC3BIGPRGROM;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (nmt == Type::NMT_FOURSCREEN)
|
if (nmt == Type::NMT_FOURSCREEN)
|
||||||
{
|
{
|
||||||
if (prg == SIZE_64K && (chr == SIZE_32K || chr == SIZE_64K) && !wram && !useWramAuto)
|
if (prg == SIZE_64K && (chr == SIZE_32K || chr == SIZE_64K) && !wram && !useWramAuto)
|
||||||
@ -1804,34 +1815,53 @@ namespace Nes
|
|||||||
|
|
||||||
case 21:
|
case 21:
|
||||||
|
|
||||||
if (submapper == 1)
|
if (submapper == 2 || wram >= SIZE_8K) // VRC4c
|
||||||
|
{
|
||||||
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
chip.Pin(3) = L"PRG A7";
|
||||||
|
chip.Pin(4) = L"PRG A6";
|
||||||
|
name = "KONAMI VRC4";
|
||||||
|
id = Type::KONAMI_VRC4_2;
|
||||||
|
}
|
||||||
|
else // VRC4a - submapper 1
|
||||||
{
|
{
|
||||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
|
||||||
chip.Pin(3) = L"PRG A2";
|
chip.Pin(3) = L"PRG A2";
|
||||||
chip.Pin(4) = L"PRG A1";
|
chip.Pin(4) = L"PRG A1";
|
||||||
|
|
||||||
name = "KONAMI VRC4";
|
|
||||||
id = Type::KONAMI_VRC4_0;
|
id = Type::KONAMI_VRC4_0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
name = "KONAMI VRC4";
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
case 25:
|
case 25:
|
||||||
|
|
||||||
if (submapper == 2)
|
if (submapper == 3 || wram >= SIZE_8K) // VRC2c, but emulated as VRC4
|
||||||
{ // The correct board is VRC2 but the functionality is implemented in the VRC4 code currently
|
{
|
||||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
chip.Pin(3) = L"PRG A0";
|
chip.Pin(3) = L"PRG A0";
|
||||||
chip.Pin(4) = L"PRG A1";
|
chip.Pin(4) = L"PRG A1";
|
||||||
|
|
||||||
name = "KONAMI VRC2";
|
|
||||||
id = Type::KONAMI_VRC4_2;
|
id = Type::KONAMI_VRC4_2;
|
||||||
|
name = "KONAMI VRC2";
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
else if (submapper == 2 || prg >= SIZE_256K) // VRC4d
|
||||||
if (!this->chips.Has(L"Konami VRC IV"))
|
{
|
||||||
return false;
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
chip.Pin(3) = L"PRG A2";
|
||||||
|
chip.Pin(4) = L"PRG A3";
|
||||||
|
id = Type::KONAMI_VRC4_0;
|
||||||
|
}
|
||||||
|
else // VRC4b - submapper 1
|
||||||
|
{
|
||||||
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
chip.Pin(3) = L"PRG A0";
|
||||||
|
chip.Pin(4) = L"PRG A1";
|
||||||
|
id = Type::KONAMI_VRC4_1;
|
||||||
|
}
|
||||||
|
|
||||||
name = "KONAMI VRC4";
|
name = "KONAMI VRC4";
|
||||||
id = Type::KONAMI_VRC4_2;
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 22:
|
case 22:
|
||||||
@ -1858,50 +1888,49 @@ namespace Nes
|
|||||||
|
|
||||||
case 23:
|
case 23:
|
||||||
|
|
||||||
if (submapper == 2)
|
if (submapper == 1) // VRC4f - Unknown, but plausibly World Hero?
|
||||||
{
|
{
|
||||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
chip.Pin(3) = L"PRG A1";
|
||||||
chip.Pin(3) = L"PRG A3";
|
chip.Pin(4) = L"PRG A0";
|
||||||
chip.Pin(4) = L"PRG A2";
|
|
||||||
|
|
||||||
name = "KONAMI VRC4";
|
name = "KONAMI VRC4";
|
||||||
id = Type::KONAMI_VRC4_0;
|
id = Type::KONAMI_VRC4_0;
|
||||||
}
|
}
|
||||||
else if (submapper == 3)
|
else if (submapper == 2) // VRC4e
|
||||||
{
|
|
||||||
name = "KONAMI VRC2";
|
|
||||||
id = Type::KONAMI_VRC2;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (prg >= SIZE_512K)
|
|
||||||
{
|
|
||||||
if (!this->chips.Has(L"Konami VRC IV"))
|
|
||||||
{
|
{
|
||||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
|
||||||
chip.Pin(3) = L"PRG A3";
|
chip.Pin(3) = L"PRG A3";
|
||||||
chip.Pin(4) = L"PRG A2";
|
chip.Pin(4) = L"PRG A2";
|
||||||
|
name = "KONAMI VRC4";
|
||||||
|
id = Type::KONAMI_VRC4_1;
|
||||||
}
|
}
|
||||||
|
else if (prg >= SIZE_512K)
|
||||||
|
{
|
||||||
|
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||||
|
chip.Pin(3) = L"PRG A3";
|
||||||
|
chip.Pin(4) = L"PRG A2";
|
||||||
name = "BMC VRC4";
|
name = "BMC VRC4";
|
||||||
id = Type::BMC_VRC4;
|
id = Type::BMC_VRC4;
|
||||||
}
|
}
|
||||||
else if (this->chips.Has(L"Konami VRC II"))
|
else // VRC2b - submapper 3
|
||||||
{
|
{
|
||||||
|
Chips::Type& chip = chips.Add(L"Konami VRC II");
|
||||||
|
|
||||||
|
chip.Pin(3) = L"PRG A1";
|
||||||
|
chip.Pin(4) = L"PRG A0";
|
||||||
|
chip.Pin(21) = L"CHR A10";
|
||||||
|
chip.Pin(22) = L"CHR A16";
|
||||||
|
chip.Pin(23) = L"CHR A11";
|
||||||
|
chip.Pin(24) = L"CHR A13";
|
||||||
|
chip.Pin(25) = L"CHR A14";
|
||||||
|
chip.Pin(26) = L"CHR A12";
|
||||||
|
chip.Pin(27) = L"CHR A15";
|
||||||
|
chip.Pin(28) = (chr >= SIZE_256K ? L"CHR A17" : L"NC");
|
||||||
|
|
||||||
name = "KONAMI VRC2";
|
name = "KONAMI VRC2";
|
||||||
id = Type::KONAMI_VRC2;
|
id = Type::KONAMI_VRC2;
|
||||||
}
|
}
|
||||||
else if (this->chips.Has(L"Konami VRC IV"))
|
|
||||||
{
|
|
||||||
name = "KONAMI VRC4";
|
|
||||||
id = Type::KONAMI_VRC4_2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 24:
|
case 24:
|
||||||
@ -2344,13 +2373,6 @@ namespace Nes
|
|||||||
|
|
||||||
case 78:
|
case 78:
|
||||||
|
|
||||||
if (submapper == 1)
|
|
||||||
{
|
|
||||||
name = "JALECO JF-16";
|
|
||||||
id = Type::JALECO_JF16;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (submapper == 3)
|
if (submapper == 3)
|
||||||
{
|
{
|
||||||
name = "IREM-HOLYDIVER";
|
name = "IREM-HOLYDIVER";
|
||||||
@ -2358,6 +2380,7 @@ namespace Nes
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Default to submapper 1
|
||||||
name = "JALECO JF-16";
|
name = "JALECO JF-16";
|
||||||
id = Type::JALECO_JF16;
|
id = Type::JALECO_JF16;
|
||||||
break;
|
break;
|
||||||
@ -3385,6 +3408,12 @@ namespace Nes
|
|||||||
id = Type::BMC_110IN1;
|
id = Type::BMC_110IN1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 258:
|
||||||
|
|
||||||
|
name = "UNL-158B";
|
||||||
|
id = Type::UNL_158B;
|
||||||
|
break;
|
||||||
|
|
||||||
case 262:
|
case 262:
|
||||||
|
|
||||||
name = "UNL-SHERO";
|
name = "UNL-SHERO";
|
||||||
@ -3494,6 +3523,12 @@ namespace Nes
|
|||||||
id = Type::BMC_SUPER_40IN1;
|
id = Type::BMC_SUPER_40IN1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 400:
|
||||||
|
|
||||||
|
name = "UNL-RET-X7-GBL";
|
||||||
|
id = Type::UNL_RETX7GBL;
|
||||||
|
break;
|
||||||
|
|
||||||
case 521:
|
case 521:
|
||||||
|
|
||||||
name = "DREAMTECH01";
|
name = "DREAMTECH01";
|
||||||
@ -3887,14 +3922,17 @@ namespace Nes
|
|||||||
case Type::TXC_MXMDHTWO : return new Txc::Mxmdhtwo(c);
|
case Type::TXC_MXMDHTWO : return new Txc::Mxmdhtwo(c);
|
||||||
case Type::TXC_POLICEMAN : return new Txc::Policeman(c);
|
case Type::TXC_POLICEMAN : return new Txc::Policeman(c);
|
||||||
case Type::TXC_TW : return new Txc::Tw(c);
|
case Type::TXC_TW : return new Txc::Tw(c);
|
||||||
|
case Type::UNL_158B : return new Unlicensed::Gd98158b(c);
|
||||||
case Type::UNL_A9746 : return new Unlicensed::A9746(c);
|
case Type::UNL_A9746 : return new Unlicensed::A9746(c);
|
||||||
case Type::UNL_CC21 : return new Unlicensed::Cc21(c);
|
case Type::UNL_CC21 : return new Unlicensed::Cc21(c);
|
||||||
case Type::UNL_EDU2000 : return new Unlicensed::Edu2000(c);
|
case Type::UNL_EDU2000 : return new Unlicensed::Edu2000(c);
|
||||||
case Type::UNL_FS304 : return new Waixing::Fs304(c);
|
case Type::UNL_FS304 : return new Waixing::Fs304(c);
|
||||||
case Type::UNL_KINGOFFIGHTERS96 : return new Unlicensed::KingOfFighters96(c);
|
case Type::UNL_KINGOFFIGHTERS96 : return new Unlicensed::KingOfFighters96(c);
|
||||||
case Type::UNL_KINGOFFIGHTERS97 : return new Unlicensed::KingOfFighters97(c);
|
case Type::UNL_KINGOFFIGHTERS97 : return new Unlicensed::KingOfFighters97(c);
|
||||||
|
case Type::UNL_MMC3BIGPRGROM : return new Unlicensed::Mmc3BigPrgRom(c);
|
||||||
case Type::UNL_MORTALKOMBAT2 : return new Unlicensed::MortalKombat2(c);
|
case Type::UNL_MORTALKOMBAT2 : return new Unlicensed::MortalKombat2(c);
|
||||||
case Type::UNL_N625092 : return new Unlicensed::N625092(c);
|
case Type::UNL_N625092 : return new Unlicensed::N625092(c);
|
||||||
|
case Type::UNL_RETX7GBL : return new Unlicensed::RetX7Gbl(c);
|
||||||
case Type::UNL_SUPERFIGHTER3 : return new Unlicensed::SuperFighter3(c);
|
case Type::UNL_SUPERFIGHTER3 : return new Unlicensed::SuperFighter3(c);
|
||||||
case Type::UNL_SHERO : return new Sachen::StreetHeroes(c);
|
case Type::UNL_SHERO : return new Sachen::StreetHeroes(c);
|
||||||
case Type::UNL_TF1201 : return new Unlicensed::Tf1201(c);
|
case Type::UNL_TF1201 : return new Unlicensed::Tf1201(c);
|
||||||
|
@ -540,6 +540,7 @@ namespace Nes
|
|||||||
TXC_POLICEMAN = MakeId< 36, 512, 128, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
TXC_POLICEMAN = MakeId< 36, 512, 128, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
TXC_TW = MakeId< 189, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
TXC_TW = MakeId< 189, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
// Unlicensed
|
// Unlicensed
|
||||||
|
UNL_158B = MakeId< 258, 128, 128, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
UNL_A9746 = MakeId< 219, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
UNL_A9746 = MakeId< 219, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
UNL_CC21 = MakeId< 27, 32, 8, 0, 0, CRM_0, NMT_Z, 0 >::ID,
|
UNL_CC21 = MakeId< 27, 32, 8, 0, 0, CRM_0, NMT_Z, 0 >::ID,
|
||||||
UNL_EDU2000 = MakeId< 329, 1024, 0, 0, 32, CRM_8, NMT_Z, 0 >::ID,
|
UNL_EDU2000 = MakeId< 329, 1024, 0, 0, 32, CRM_8, NMT_Z, 0 >::ID,
|
||||||
@ -548,6 +549,7 @@ namespace Nes
|
|||||||
UNL_KINGOFFIGHTERS97 = MakeId< 263, 256, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
UNL_KINGOFFIGHTERS97 = MakeId< 263, 256, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
UNL_MORTALKOMBAT2 = MakeId< 91, 256, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
UNL_MORTALKOMBAT2 = MakeId< 91, 256, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
UNL_N625092 = MakeId< 221, 1024, 8, 0, 0, CRM_0, NMT_V, 0 >::ID,
|
UNL_N625092 = MakeId< 221, 1024, 8, 0, 0, CRM_0, NMT_V, 0 >::ID,
|
||||||
|
UNL_RETX7GBL = MakeId< 400, 2048, 0, 0, 0, CRM_32, NMT_X, 0 >::ID,
|
||||||
UNL_SUPERFIGHTER3 = MakeId< 197, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
UNL_SUPERFIGHTER3 = MakeId< 197, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
UNL_SHERO = MakeId< 262, 512, 512, 0, 0, CRM_8, NMT_4, 0 >::ID,
|
UNL_SHERO = MakeId< 262, 512, 512, 0, 0, CRM_8, NMT_4, 0 >::ID,
|
||||||
UNL_TF1201 = MakeId< 298, 128, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
|
UNL_TF1201 = MakeId< 298, 128, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
|
||||||
@ -562,6 +564,7 @@ namespace Nes
|
|||||||
UNL_TRXROM = MakeId< 4, 512, 256, 8, 0, CRM_0, NMT_4, 0 >::ID,
|
UNL_TRXROM = MakeId< 4, 512, 256, 8, 0, CRM_0, NMT_4, 0 >::ID,
|
||||||
UNL_XZY = MakeId< 176, 1024, 256, 8, 0, CRM_0, NMT_X, 0 >::ID,
|
UNL_XZY = MakeId< 176, 1024, 256, 8, 0, CRM_0, NMT_X, 0 >::ID,
|
||||||
UNL_MMC3BIGCHRRAM = MakeId< 4, 512, 0, 0, 0, CRM_32, NMT_X, 0 >::ID,
|
UNL_MMC3BIGCHRRAM = MakeId< 4, 512, 0, 0, 0, CRM_32, NMT_X, 0 >::ID,
|
||||||
|
UNL_MMC3BIGPRGROM = MakeId< 4, 1024, 0, 8, 0, CRM_8, NMT_X, 0 >::ID,
|
||||||
// Waixing
|
// Waixing
|
||||||
WAIXING_PS2_0 = MakeId< 15, 1024, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
|
WAIXING_PS2_0 = MakeId< 15, 1024, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
|
||||||
WAIXING_PS2_1 = MakeId< 15, 1024, 0, 8, 0, CRM_8, NMT_V, 0 >::ID,
|
WAIXING_PS2_1 = MakeId< 15, 1024, 0, 8, 0, CRM_8, NMT_V, 0 >::ID,
|
||||||
|
@ -162,8 +162,6 @@ namespace Nes
|
|||||||
byte chr[8];
|
byte chr[8];
|
||||||
} banks;
|
} banks;
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Irq<> irq;
|
Irq<> irq;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
129
source/core/board/NstBoardUnl158b.cpp
Normal file
129
source/core/board/NstBoardUnl158b.cpp
Normal file
@ -0,0 +1,129 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Nestopia - NES/Famicom emulator written in C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Rupert Carmichael
|
||||||
|
//
|
||||||
|
// This file is part of Nestopia.
|
||||||
|
//
|
||||||
|
// Nestopia is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Nestopia 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Nestopia; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#include "NstBoard.hpp"
|
||||||
|
#include "NstBoardUnl158b.hpp"
|
||||||
|
|
||||||
|
/* References:
|
||||||
|
https://github.com/SourMesen/Mesen/blob/master/Core/Unl158B.h
|
||||||
|
https://github.com/TASVideos/fceux/blob/master/src/boards/158B.cpp
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Nes
|
||||||
|
{
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
namespace Boards
|
||||||
|
{
|
||||||
|
namespace Unlicensed
|
||||||
|
{
|
||||||
|
Gd98158b::Gd98158b(const Context& c)
|
||||||
|
: Mmc3(c) {}
|
||||||
|
|
||||||
|
void Gd98158b::SubReset(const bool hard)
|
||||||
|
{
|
||||||
|
lut[0] = lut[1] = lut[2] = lut[7] = 0x00;
|
||||||
|
lut[3] = 0x01;
|
||||||
|
lut[4] = 0x02;
|
||||||
|
lut[5] = 0x04;
|
||||||
|
lut[6] = 0x0F;
|
||||||
|
|
||||||
|
if (hard)
|
||||||
|
reg = 0;
|
||||||
|
|
||||||
|
banks.prg[0] = 0x00;
|
||||||
|
banks.prg[1] = 0x01;
|
||||||
|
banks.prg[2] = 0x3E;
|
||||||
|
banks.prg[3] = 0x3F;
|
||||||
|
|
||||||
|
Mmc3::SubReset( hard );
|
||||||
|
|
||||||
|
Map( 0x5000U, 0x5FFFU, &Gd98158b::Peek_5000 );
|
||||||
|
Map( 0x5000U, 0x5FFFU, &Gd98158b::Poke_5000 );
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gd98158b::SubLoad(State::Loader& state,const dword baseChunk)
|
||||||
|
{
|
||||||
|
if (baseChunk == AsciiId<'1','5','8'>::V)
|
||||||
|
{
|
||||||
|
while (const dword chunk = state.Begin())
|
||||||
|
{
|
||||||
|
if (chunk == AsciiId<'R','E','G'>::V)
|
||||||
|
reg = state.Read8();
|
||||||
|
|
||||||
|
state.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Mmc3::SubLoad( state, baseChunk );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Gd98158b::SubSave(State::Saver& state) const
|
||||||
|
{
|
||||||
|
Mmc3::SubSave( state );
|
||||||
|
state.Begin( AsciiId<'1','5','8'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write8( reg ).End().End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void NST_FASTCALL Gd98158b::UpdatePrg(uint address, uint data)
|
||||||
|
{
|
||||||
|
if (reg & 0x80)
|
||||||
|
{
|
||||||
|
const uint bank = reg & 0x7;
|
||||||
|
|
||||||
|
if (reg & 0x20)
|
||||||
|
{
|
||||||
|
prg.SwapBank<SIZE_32K>( 0x0000, bank >> 1 );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prg.SwapBank<SIZE_16K>( 0x0000, bank );
|
||||||
|
prg.SwapBank<SIZE_16K>( 0x4000, bank );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
prg.SwapBank<SIZE_8K>( (address & 0x6000), data & 0xF );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NES_PEEK_A(Gd98158b,5000)
|
||||||
|
{
|
||||||
|
// Fake Open Bus read by always using 0x50
|
||||||
|
return 0x50 | lut[address & 0x7];
|
||||||
|
}
|
||||||
|
|
||||||
|
NES_POKE_AD(Gd98158b,5000)
|
||||||
|
{
|
||||||
|
if ((address & 0x7) == 0)
|
||||||
|
{
|
||||||
|
reg = data;
|
||||||
|
Mmc3::UpdatePrg();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
source/core/board/NstBoardUnl158b.hpp
Normal file
67
source/core/board/NstBoardUnl158b.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Nestopia - NES/Famicom emulator written in C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Rupert Carmichael
|
||||||
|
//
|
||||||
|
// This file is part of Nestopia.
|
||||||
|
//
|
||||||
|
// Nestopia is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Nestopia 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Nestopia; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef NST_BOARD_UNL_158B_H
|
||||||
|
#define NST_BOARD_UNL_158B_H
|
||||||
|
|
||||||
|
#ifdef NST_PRAGMA_ONCE
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "NstBoardMmc3.hpp"
|
||||||
|
|
||||||
|
namespace Nes
|
||||||
|
{
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
namespace Boards
|
||||||
|
{
|
||||||
|
namespace Unlicensed
|
||||||
|
{
|
||||||
|
class Gd98158b : public Mmc3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Gd98158b(const Context&);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void SubReset(bool);
|
||||||
|
void SubLoad(State::Loader&,dword);
|
||||||
|
void SubSave(State::Saver&) const;
|
||||||
|
|
||||||
|
void NST_FASTCALL UpdatePrg(uint, uint);
|
||||||
|
|
||||||
|
NES_DECL_PEEK( 5000 );
|
||||||
|
NES_DECL_POKE( 5000 );
|
||||||
|
|
||||||
|
byte lut[8];
|
||||||
|
uint reg;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
159
source/core/board/NstBoardUnlMmc3BigPrgRom.cpp
Normal file
159
source/core/board/NstBoardUnlMmc3BigPrgRom.cpp
Normal file
@ -0,0 +1,159 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Nestopia - NES/Famicom emulator written in C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2003-2008 Martin Freij
|
||||||
|
// Copyright (C) 2020-2022 Rupert Carmichael
|
||||||
|
//
|
||||||
|
// This file is part of Nestopia.
|
||||||
|
//
|
||||||
|
// Nestopia is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Nestopia 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Nestopia; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* Note: At the time this was written, MMC3 boards with larger than 512K PRG
|
||||||
|
are fantasy hardware. This may change in the future if it is implemented in
|
||||||
|
a product along the lines of the PowerPak or Everdrive.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "NstBoard.hpp"
|
||||||
|
#include "NstBoardMmc3.hpp"
|
||||||
|
#include "NstBoardUnlMmc3BigPrgRom.hpp"
|
||||||
|
#include "../NstFile.hpp"
|
||||||
|
|
||||||
|
namespace Nes
|
||||||
|
{
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
namespace Boards
|
||||||
|
{
|
||||||
|
namespace Unlicensed
|
||||||
|
{
|
||||||
|
#ifdef NST_MSVC_OPTIMIZE
|
||||||
|
#pragma optimize("s", on)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void Mmc3BigPrgRom::SubReset(const bool hard)
|
||||||
|
{
|
||||||
|
Mmc3::SubReset( hard );
|
||||||
|
|
||||||
|
for (uint i=0x0000; i < 0x2000; i += 0x2)
|
||||||
|
{
|
||||||
|
Map( 0x8001 + i, &Mmc3BigPrgRom::Poke_8001 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mmc3BigPrgRom::SubLoad(State::Loader& state,const dword baseChunk)
|
||||||
|
{
|
||||||
|
NST_VERIFY( baseChunk == (AsciiId<'M','M','3'>::V) );
|
||||||
|
|
||||||
|
if (baseChunk == AsciiId<'M','M','3'>::V)
|
||||||
|
{
|
||||||
|
while (const dword chunk = state.Begin())
|
||||||
|
{
|
||||||
|
switch (chunk)
|
||||||
|
{
|
||||||
|
case AsciiId<'R','E','G'>::V:
|
||||||
|
{
|
||||||
|
State::Loader::Data<12> data( state );
|
||||||
|
|
||||||
|
regs.ctrl0 = data[0];
|
||||||
|
regs.ctrl1 = data[1];
|
||||||
|
banks.prg[0] = data[2] & 0x7FU;
|
||||||
|
banks.prg[1] = data[3] & 0x7FU;
|
||||||
|
banks.chr[0] = (data[6] & 0x7FU) << 1;
|
||||||
|
banks.chr[1] = banks.chr[0] | 0x01U;
|
||||||
|
banks.chr[2] = (data[7] & 0x7FU) << 1;
|
||||||
|
banks.chr[3] = banks.chr[2] | 0x01U;
|
||||||
|
banks.chr[4] = data[8];
|
||||||
|
banks.chr[5] = data[9];
|
||||||
|
banks.chr[6] = data[10];
|
||||||
|
banks.chr[7] = data[11];
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case AsciiId<'I','R','Q'>::V:
|
||||||
|
|
||||||
|
irq.unit.LoadState( state );
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
state.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Mmc3BigPrgRom::SubSave(State::Saver& state) const
|
||||||
|
{
|
||||||
|
state.Begin( AsciiId<'M','M','3'>::V );
|
||||||
|
|
||||||
|
const byte data[12] =
|
||||||
|
{
|
||||||
|
regs.ctrl0,
|
||||||
|
regs.ctrl1,
|
||||||
|
banks.prg[0],
|
||||||
|
banks.prg[1],
|
||||||
|
0x7E,
|
||||||
|
0x7F,
|
||||||
|
banks.chr[0] >> 1,
|
||||||
|
banks.chr[2] >> 1,
|
||||||
|
banks.chr[4],
|
||||||
|
banks.chr[5],
|
||||||
|
banks.chr[6],
|
||||||
|
banks.chr[7]
|
||||||
|
};
|
||||||
|
|
||||||
|
state.Begin( AsciiId<'R','E','G'>::V ).Write( data ).End();
|
||||||
|
|
||||||
|
irq.unit.SaveState( state, AsciiId<'I','R','Q'>::V );
|
||||||
|
|
||||||
|
state.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef NST_MSVC_OPTIMIZE
|
||||||
|
#pragma optimize("", on)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
NES_POKE_D(Mmc3BigPrgRom,8001)
|
||||||
|
{
|
||||||
|
uint address = regs.ctrl0 & 0x7;
|
||||||
|
|
||||||
|
if (address < 6)
|
||||||
|
{
|
||||||
|
ppu.Update();
|
||||||
|
|
||||||
|
uint base = regs.ctrl0 << 5 & 0x1000;
|
||||||
|
|
||||||
|
if (address < 2)
|
||||||
|
{
|
||||||
|
address <<= 1;
|
||||||
|
base |= address << 10;
|
||||||
|
UpdateChr( base | 0x0000, (banks.chr[address+0] = data & 0xFE) );
|
||||||
|
UpdateChr( base | 0x0400, (banks.chr[address+1] = data | 0x01) );
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdateChr( (base ^ 0x1000) | (address-2) << 10, (banks.chr[address+2] = data) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
UpdatePrg( (address == 6) ? (regs.ctrl0 << 8 & 0x4000) : 0x2000, (banks.prg[address-6] = data & 0x7F) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
60
source/core/board/NstBoardUnlMmc3BigPrgRom.hpp
Normal file
60
source/core/board/NstBoardUnlMmc3BigPrgRom.hpp
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Nestopia - NES/Famicom emulator written in C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2003-2008 Martin Freij
|
||||||
|
// Copyright (C) 2020-2022 Rupert Carmichael
|
||||||
|
//
|
||||||
|
// This file is part of Nestopia.
|
||||||
|
//
|
||||||
|
// Nestopia is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Nestopia 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Nestopia; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef NST_BOARD_UNL_MMC3BIGPRGROM_H
|
||||||
|
#define NST_BOARD_UNL_MMC3BIGPRGROM_H
|
||||||
|
|
||||||
|
#ifdef NST_PRAGMA_ONCE
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Nes
|
||||||
|
{
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
namespace Boards
|
||||||
|
{
|
||||||
|
namespace Unlicensed
|
||||||
|
{
|
||||||
|
class NST_NO_VTABLE Mmc3BigPrgRom : public Mmc3
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit Mmc3BigPrgRom(const Context& c)
|
||||||
|
: Mmc3(c) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
void SubReset(bool);
|
||||||
|
void SubSave(State::Saver&) const;
|
||||||
|
void SubLoad(State::Loader&,dword);
|
||||||
|
|
||||||
|
NES_DECL_POKE( 8001 );
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
119
source/core/board/NstBoardUnlRetX7Gbl.cpp
Normal file
119
source/core/board/NstBoardUnlRetX7Gbl.cpp
Normal file
@ -0,0 +1,119 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Nestopia - NES/Famicom emulator written in C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Rupert Carmichael
|
||||||
|
//
|
||||||
|
// This file is part of Nestopia.
|
||||||
|
//
|
||||||
|
// Nestopia is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Nestopia 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Nestopia; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
/* References:
|
||||||
|
https://github.com/NovaSquirrel/Mesen-X/blob/master/Core/Mapper400.h
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "NstBoard.hpp"
|
||||||
|
#include "NstBoardUnlRetX7Gbl.hpp"
|
||||||
|
|
||||||
|
namespace Nes
|
||||||
|
{
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
namespace Boards
|
||||||
|
{
|
||||||
|
namespace Unlicensed
|
||||||
|
{
|
||||||
|
void RetX7Gbl::SubReset(bool)
|
||||||
|
{
|
||||||
|
Map( 0x7800U, 0x7FFFU, &RetX7Gbl::Poke_7800 );
|
||||||
|
Map( 0x8000U, 0xBFFFU, &RetX7Gbl::Poke_8000 );
|
||||||
|
Map( 0xC000U, 0xFFFFU, &RetX7Gbl::Poke_C000 );
|
||||||
|
|
||||||
|
regs[0] = 0x80;
|
||||||
|
regs[1] = 0x00;
|
||||||
|
|
||||||
|
UpdatePrg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetX7Gbl::SubLoad(State::Loader& state,const dword baseChunk)
|
||||||
|
{
|
||||||
|
if (baseChunk == AsciiId<'R','X','G'>::V)
|
||||||
|
{
|
||||||
|
while (const dword chunk = state.Begin())
|
||||||
|
{
|
||||||
|
if (chunk == AsciiId<'R','E','G'>::V)
|
||||||
|
{
|
||||||
|
State::Loader::Data<3> data( state );
|
||||||
|
|
||||||
|
regs[0] = data[0];
|
||||||
|
regs[1] = data[1];
|
||||||
|
led = data[2];
|
||||||
|
}
|
||||||
|
|
||||||
|
state.End();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdatePrg();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetX7Gbl::SubSave(State::Saver& state) const
|
||||||
|
{
|
||||||
|
state.Begin( AsciiId<'R','X','G'>::V );
|
||||||
|
|
||||||
|
const byte data[3] =
|
||||||
|
{
|
||||||
|
regs[0], regs[1], led
|
||||||
|
};
|
||||||
|
|
||||||
|
state.Begin( AsciiId<'R','E','G'>::V ).Write( data ).End();
|
||||||
|
state.End();
|
||||||
|
}
|
||||||
|
|
||||||
|
void RetX7Gbl::UpdatePrg()
|
||||||
|
{
|
||||||
|
prg.SwapBank<SIZE_16K,0x0000>( (regs[0] & 0x78) | (regs[1] & 0x7) );
|
||||||
|
prg.SwapBank<SIZE_16K,0x4000>( (regs[0] & 0x78) | 0x7 );
|
||||||
|
|
||||||
|
if (regs[0] != 0x80)
|
||||||
|
{
|
||||||
|
ppu.SetMirroring( regs[0] & 0x20 ? Ppu::NMT_H : Ppu::NMT_V );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
NES_POKE_D(RetX7Gbl,7800)
|
||||||
|
{
|
||||||
|
regs[0] = data;
|
||||||
|
UpdatePrg();
|
||||||
|
}
|
||||||
|
|
||||||
|
NES_POKE_D(RetX7Gbl,8000)
|
||||||
|
{
|
||||||
|
led = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
NES_POKE_D(RetX7Gbl,C000)
|
||||||
|
{
|
||||||
|
regs[1] = data;
|
||||||
|
UpdatePrg();
|
||||||
|
|
||||||
|
chr.SwapBank<SIZE_8K,0x0000>( (data >> 5) & 0x3 );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
67
source/core/board/NstBoardUnlRetX7Gbl.hpp
Normal file
67
source/core/board/NstBoardUnlRetX7Gbl.hpp
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// Nestopia - NES/Famicom emulator written in C++
|
||||||
|
//
|
||||||
|
// Copyright (C) 2022 Rupert Carmichael
|
||||||
|
//
|
||||||
|
// This file is part of Nestopia.
|
||||||
|
//
|
||||||
|
// Nestopia is free software; you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation; either version 2 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// Nestopia 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 General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with Nestopia; if not, write to the Free Software
|
||||||
|
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||||
|
//
|
||||||
|
////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
|
#ifndef NST_BOARD_UNL_RETX7GBL_H
|
||||||
|
#define NST_BOARD_UNL_RETX7GBL_H
|
||||||
|
|
||||||
|
#ifdef NST_PRAGMA_ONCE
|
||||||
|
#pragma once
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace Nes
|
||||||
|
{
|
||||||
|
namespace Core
|
||||||
|
{
|
||||||
|
namespace Boards
|
||||||
|
{
|
||||||
|
namespace Unlicensed
|
||||||
|
{
|
||||||
|
class RetX7Gbl : public Board
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
explicit RetX7Gbl(const Context& c)
|
||||||
|
: Board(c) {}
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
void SubReset(bool);
|
||||||
|
void SubLoad(State::Loader&,dword);
|
||||||
|
void SubSave(State::Saver&) const;
|
||||||
|
|
||||||
|
void UpdatePrg();
|
||||||
|
|
||||||
|
NES_DECL_POKE( 7800 );
|
||||||
|
NES_DECL_POKE( 8000 );
|
||||||
|
NES_DECL_POKE( C000 );
|
||||||
|
|
||||||
|
uint regs[2];
|
||||||
|
uint led;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue
Block a user