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/NstBoardTxcTw.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/NstBoardUnlCc21.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/NstBoardUnlKingOfFighters97.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/NstBoardUnlRetX7Gbl.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/NstBoardUnlWorldHero.cpp
|
||||
|
@ -22,7 +22,7 @@
|
||||
|
||||
#include "nstdatabase.hpp"
|
||||
|
||||
#define NST_VERSION "1.51.1"
|
||||
#define NST_VERSION "1.52.0"
|
||||
|
||||
#define MIN(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);
|
||||
|
||||
Api::Sound isound(emulator);
|
||||
isound.SetSampleBits(16);
|
||||
isound.SetSampleRate(SAMPLERATE);
|
||||
isound.SetSpeaker(Api::Sound::SPEAKER_MONO);
|
||||
|
||||
|
@ -238,7 +238,7 @@ namespace Nes
|
||||
|
||||
stream = NULL;
|
||||
|
||||
buffer.Reset( settings.bits );
|
||||
buffer.Reset();
|
||||
|
||||
if (on)
|
||||
{
|
||||
@ -297,7 +297,7 @@ namespace Nes
|
||||
if (!rate)
|
||||
return RESULT_ERR_INVALID_PARAM;
|
||||
|
||||
if (rate < 11025 || rate > 96000)
|
||||
if (rate < 44100 || rate > 96000)
|
||||
return RESULT_ERR_UNSUPPORTED;
|
||||
|
||||
settings.rate = rate;
|
||||
@ -306,23 +306,6 @@ namespace Nes
|
||||
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)
|
||||
{
|
||||
if (volume > 100)
|
||||
@ -421,7 +404,7 @@ namespace Nes
|
||||
cycles.Update( settings.rate, settings.speed, cpu );
|
||||
synchronizer.Reset( settings.speed, settings.rate, cpu );
|
||||
dcBlocker.Reset();
|
||||
buffer.Reset( settings.bits );
|
||||
buffer.Reset();
|
||||
|
||||
Cycle rate; uint fixed;
|
||||
CalculateOscillatorClock( rate, fixed );
|
||||
@ -863,20 +846,10 @@ namespace Nes
|
||||
{
|
||||
streamed = stream->length[0] + stream->length[1];
|
||||
|
||||
if (settings.bits == 16)
|
||||
{
|
||||
if (!settings.stereo)
|
||||
FlushSound<iword,false>();
|
||||
else
|
||||
FlushSound<iword,true>();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!settings.stereo)
|
||||
FlushSound<byte,false>();
|
||||
else
|
||||
FlushSound<byte,true>();
|
||||
}
|
||||
|
||||
Sound::Output::unlockCallback( *stream );
|
||||
}
|
||||
@ -921,7 +894,7 @@ namespace Nes
|
||||
#endif
|
||||
|
||||
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)
|
||||
volumes[i] = Channel::DEFAULT_VOLUME;
|
||||
@ -2474,7 +2447,7 @@ namespace Nes
|
||||
|
||||
dcBlocker.Reset();
|
||||
|
||||
buffer.Reset( settings.bits, false );
|
||||
buffer.Reset( false );
|
||||
}
|
||||
|
||||
#ifdef NST_MSVC_OPTIMIZE
|
||||
|
@ -60,7 +60,6 @@ namespace Nes
|
||||
void ClockDMA(uint=0);
|
||||
|
||||
Result SetSampleRate(dword);
|
||||
Result SetSampleBits(uint);
|
||||
Result SetSpeed(uint);
|
||||
Result SetVolume(uint,uint);
|
||||
uint GetVolume(uint) const;
|
||||
@ -601,7 +600,6 @@ namespace Nes
|
||||
Settings();
|
||||
|
||||
dword rate;
|
||||
uint bits;
|
||||
byte speed;
|
||||
bool muted;
|
||||
bool transpose;
|
||||
@ -643,11 +641,6 @@ namespace Nes
|
||||
return settings.rate;
|
||||
}
|
||||
|
||||
uint GetSampleBits() const
|
||||
{
|
||||
return settings.bits;
|
||||
}
|
||||
|
||||
uint GetSpeed() const
|
||||
{
|
||||
return settings.speed;
|
||||
|
@ -147,7 +147,7 @@ namespace Nes
|
||||
Log::Flush( "Ines: PRG-ROM was patched" NST_LINEBREAK );
|
||||
|
||||
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:
|
||||
|
@ -124,7 +124,7 @@ namespace Nes
|
||||
0x00, 0x20, 0x00, 0x20, 0x04, 0x04, 0x04, 0x04,
|
||||
0x00, 0x00, 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,
|
||||
@ -2128,11 +2128,12 @@ namespace Nes
|
||||
}
|
||||
|
||||
// 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_() \
|
||||
{ \
|
||||
const uint dst = addr_##_W(); \
|
||||
const uint dst = FetchPc16(); \
|
||||
cycles.count += cycles.clock[3]; \
|
||||
instr_(dst); \
|
||||
}
|
||||
|
||||
@ -2393,8 +2394,8 @@ namespace Nes
|
||||
NES_I_W_A( Sha, AbsY, 0x9F )
|
||||
NES_I_W_A( Sha, IndY, 0x93 )
|
||||
NES_I_W_A( Shs, AbsY, 0x9B )
|
||||
NES_I_W_U( Shx, Abs, 0x9E ) // Edge case: AbsY done internally
|
||||
NES_I_W_U( Shy, Abs, 0x9C ) // Edge case: AbsX done internally
|
||||
NES_I_W_U( Shx, 0x9E ) // Edge case: AbsY done internally
|
||||
NES_I_W_U( Shy, 0x9C ) // Edge case: AbsX done internally
|
||||
NES_IRW__( Slo, Zpg, 0x07 )
|
||||
NES_IRW__( Slo, ZpgX, 0x17 )
|
||||
NES_IRW__( Slo, Abs, 0x0F )
|
||||
|
@ -221,17 +221,36 @@ namespace Nes
|
||||
{
|
||||
NST_ASSERT( it->length );
|
||||
|
||||
bool underflow = false;
|
||||
dword uflow_length = 0;
|
||||
|
||||
if (it->offset < offset)
|
||||
{
|
||||
if (it->offset + it->length > offset)
|
||||
{
|
||||
underflow = true;
|
||||
uflow_length = offset - it->offset;
|
||||
}
|
||||
else
|
||||
{
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (it->offset >= offset + length)
|
||||
break;
|
||||
|
||||
const dword pos = it->offset - offset;
|
||||
const dword part = NST_MIN(it->length,length-pos);
|
||||
dword pos = it->offset - offset;
|
||||
dword part = NST_MIN(it->length,length-pos);
|
||||
|
||||
if (underflow)
|
||||
{
|
||||
part -= uflow_length;
|
||||
pos += uflow_length;
|
||||
}
|
||||
|
||||
if (it->fill == NO_FILL)
|
||||
std::memcpy( dst + pos, it->data, part );
|
||||
std::memcpy( dst + pos, it->data + uflow_length, part );
|
||||
else
|
||||
std::memset( dst + pos, it->fill, part );
|
||||
|
||||
|
@ -401,6 +401,8 @@ namespace Nes
|
||||
state.End();
|
||||
}
|
||||
|
||||
output.bgColor = palette.ram[0] & uint(Palette::COLOR);
|
||||
|
||||
UpdateStates();
|
||||
}
|
||||
|
||||
@ -774,6 +776,17 @@ namespace Nes
|
||||
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)
|
||||
{
|
||||
Update( cycles.one );
|
||||
@ -786,6 +799,8 @@ namespace Nes
|
||||
oam.height = (data >> 2 & 8) + 8;
|
||||
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
data = regs.ctrl[0] ;
|
||||
regs.ctrl[0] = io.latch;
|
||||
|
||||
@ -825,6 +840,8 @@ namespace Nes
|
||||
}
|
||||
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
data = (regs.ctrl[1] ^ data) & (Regs::CTRL1_EMPHASIS|Regs::CTRL1_MONOCHROME);
|
||||
regs.ctrl[1] = io.latch;
|
||||
|
||||
@ -852,13 +869,22 @@ namespace Nes
|
||||
{
|
||||
Update( cycles.one, address );
|
||||
|
||||
byte mask = 0xE0;
|
||||
uint status = regs.status & 0xFF;
|
||||
|
||||
regs.status &= (Regs::STATUS_VBLANK^0xFFU);
|
||||
scroll.toggle = 0;
|
||||
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)
|
||||
@ -882,6 +908,7 @@ namespace Nes
|
||||
|
||||
regs.oam = data;
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
}
|
||||
|
||||
NES_POKE_D(Ppu,2004)
|
||||
@ -891,6 +918,9 @@ namespace Nes
|
||||
NST_ASSERT( regs.oam < Oam::SIZE );
|
||||
NST_VERIFY( IsDead() );
|
||||
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
if (IsDead())
|
||||
{
|
||||
if ((regs.oam & 0x03) == 0x02)
|
||||
@ -903,7 +933,6 @@ namespace Nes
|
||||
|
||||
byte* const NST_RESTRICT value = oam.ram + regs.oam;
|
||||
regs.oam = (regs.oam + 1) & 0xFF;
|
||||
io.latch = 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)
|
||||
{
|
||||
io.latch = oam.ram[regs.oam];
|
||||
UpdateDecay(0xFF);
|
||||
}
|
||||
else
|
||||
{
|
||||
Update( cycles.one );
|
||||
|
||||
io.latch = oam.latch;
|
||||
UpdateDecay(0xFF);
|
||||
}
|
||||
|
||||
return io.latch;
|
||||
@ -934,6 +965,7 @@ namespace Nes
|
||||
if (cpu.GetCycles() >= cycles.reset)
|
||||
{
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
if (scroll.toggle ^= 1)
|
||||
{
|
||||
@ -956,6 +988,7 @@ namespace Nes
|
||||
if (cpu.GetCycles() >= cycles.reset)
|
||||
{
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
if (scroll.toggle ^= 1)
|
||||
{
|
||||
@ -984,6 +1017,7 @@ namespace Nes
|
||||
return;
|
||||
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
if ((address & 0x3F00) == 0x3F00)
|
||||
{
|
||||
@ -1015,27 +1049,54 @@ namespace Nes
|
||||
|
||||
NES_PEEK_A(Ppu,2007)
|
||||
{
|
||||
byte mask = 0xFF;
|
||||
byte cache = io.latch;
|
||||
|
||||
Update( cycles.one, address );
|
||||
|
||||
Cycle curCyc = cpu.GetCycles();
|
||||
Cycle delta = curCyc - decay.rd2007;
|
||||
decay.rd2007 = curCyc;
|
||||
|
||||
bool fastread = (delta <= 12);
|
||||
|
||||
address = scroll.address & 0x3FFF;
|
||||
UpdateVramAddress();
|
||||
|
||||
if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) || (scanline == SCANLINE_VBLANK))
|
||||
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 ));
|
||||
|
||||
if (fastread)
|
||||
io.latch = cache;
|
||||
|
||||
return io.latch;
|
||||
}
|
||||
|
||||
NES_POKE_D(Ppu,2xxx)
|
||||
{
|
||||
io.latch = data;
|
||||
UpdateDecay(0xFF);
|
||||
}
|
||||
|
||||
NES_PEEK(Ppu,2xxx)
|
||||
{
|
||||
if ((cpu.GetCycles() - decay.timestamp[0]) > 24576)
|
||||
return 0;
|
||||
|
||||
return io.latch;
|
||||
}
|
||||
|
||||
@ -1074,10 +1135,13 @@ namespace Nes
|
||||
}
|
||||
|
||||
io.latch = oamRam[0xFF];
|
||||
UpdateDecay(0xFF);
|
||||
}
|
||||
else do
|
||||
{
|
||||
io.latch = cpu.Peek( data++ );
|
||||
UpdateDecay(0xFF);
|
||||
|
||||
cpu.StealCycles( cpu.GetClock() );
|
||||
|
||||
Update( cycles.one );
|
||||
|
@ -186,6 +186,7 @@ namespace Nes
|
||||
NST_FORCE_INLINE uint FetchSpPattern() const;
|
||||
NST_FORCE_INLINE void FetchBgPattern0();
|
||||
NST_FORCE_INLINE void FetchBgPattern1();
|
||||
NST_FORCE_INLINE void UpdateDecay(byte);
|
||||
|
||||
NST_FORCE_INLINE void EvaluateSpritesEven();
|
||||
NST_FORCE_INLINE void EvaluateSpritesOdd();
|
||||
@ -407,6 +408,12 @@ namespace Nes
|
||||
Cycle reset;
|
||||
} cycles;
|
||||
|
||||
struct
|
||||
{
|
||||
Cycle timestamp[8];
|
||||
Cycle rd2007;
|
||||
} decay;
|
||||
|
||||
Io io;
|
||||
Regs regs;
|
||||
Scroll scroll;
|
||||
@ -419,7 +426,6 @@ namespace Nes
|
||||
|
||||
public:
|
||||
Output output;
|
||||
|
||||
private:
|
||||
PpuModel model;
|
||||
Hook hActiveHook;
|
||||
|
@ -39,7 +39,7 @@ namespace Nes
|
||||
Buffer::Buffer(uint bits)
|
||||
: output(new iword [SIZE])
|
||||
{
|
||||
Reset( bits, true );
|
||||
Reset( true );
|
||||
}
|
||||
|
||||
Buffer::~Buffer()
|
||||
@ -47,12 +47,12 @@ namespace Nes
|
||||
delete [] output;
|
||||
}
|
||||
|
||||
void Buffer::Reset(uint bits,bool clear)
|
||||
void Buffer::Reset(bool clear)
|
||||
{
|
||||
pos = start = 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)
|
||||
std::fill( output, output+SIZE, iword(0) );
|
||||
|
@ -59,7 +59,7 @@ namespace Nes
|
||||
uint length;
|
||||
};
|
||||
|
||||
void Reset(uint,bool=true);
|
||||
void Reset(bool=true);
|
||||
void operator >> (Block&);
|
||||
|
||||
template<typename,uint>
|
||||
|
@ -136,7 +136,6 @@ namespace Nes
|
||||
enabled (e),
|
||||
good (false),
|
||||
stereo (false),
|
||||
bits (0),
|
||||
rate (0),
|
||||
index (0),
|
||||
buffer (NULL),
|
||||
@ -268,14 +267,13 @@ namespace Nes
|
||||
|
||||
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();
|
||||
stereo = apu.InStereo();
|
||||
size = rate << (stereo+1);
|
||||
|
||||
const dword total = (bits == 16 ? size * sizeof(iword) : size * sizeof(byte));
|
||||
const dword total = size * sizeof(iword);
|
||||
NST_ASSERT( total );
|
||||
|
||||
if (!buffer || total != old)
|
||||
@ -296,10 +294,7 @@ namespace Nes
|
||||
good = true;
|
||||
index = 0;
|
||||
|
||||
if (bits == 16)
|
||||
std::fill( static_cast<iword*>(buffer), static_cast<iword*>(buffer) + size, iword(0) );
|
||||
else
|
||||
std::memset( buffer, 0x80, size );
|
||||
|
||||
return true;
|
||||
}
|
||||
@ -587,13 +582,13 @@ namespace Nes
|
||||
{
|
||||
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)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return bits == 16 ? StoreType<iword>() : StoreType<byte>();
|
||||
return StoreType<iword>();
|
||||
}
|
||||
|
||||
template<typename T,int SILENCE>
|
||||
@ -632,14 +627,11 @@ namespace Nes
|
||||
{
|
||||
if (enabled & good)
|
||||
{
|
||||
input = (bits == 16) ? ReverseCopy<iword>( *target ) : ReverseCopy<byte>( *target );
|
||||
input = ReverseCopy<iword>( *target );
|
||||
}
|
||||
else
|
||||
{
|
||||
if (bits == 16)
|
||||
ReverseSilence<iword,0>( *target );
|
||||
else
|
||||
ReverseSilence<byte,0x80>( *target );
|
||||
}
|
||||
|
||||
mutex.Unlock( *target );
|
||||
|
@ -181,7 +181,6 @@ namespace Nes
|
||||
bool enabled;
|
||||
bool good;
|
||||
byte stereo;
|
||||
byte bits;
|
||||
dword rate;
|
||||
uint index;
|
||||
void* buffer;
|
||||
|
@ -67,7 +67,7 @@ namespace Nes
|
||||
HEIGHT = Input::HEIGHT,
|
||||
PIXELS = Input::PIXELS,
|
||||
PALETTE = Input::PALETTE,
|
||||
DEFAULT_PALETTE = PALETTE_YUV
|
||||
NST_DEFAULT_PALETTE = PALETTE_YUV
|
||||
};
|
||||
|
||||
Result SetState(const RenderState&);
|
||||
|
@ -62,11 +62,6 @@ namespace Nes
|
||||
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()
|
||||
{
|
||||
return emulator.cpu.GetApu().SetVolume( channels, volume );
|
||||
@ -97,11 +92,6 @@ namespace Nes
|
||||
return emulator.cpu.GetApu().GetSampleRate();
|
||||
}
|
||||
|
||||
uint Sound::GetSampleBits() const throw()
|
||||
{
|
||||
return emulator.cpu.GetApu().GetSampleBits();
|
||||
}
|
||||
|
||||
uint Sound::GetVolume(uint channel) const throw()
|
||||
{
|
||||
return emulator.cpu.GetApu().GetVolume( channel );
|
||||
|
@ -262,7 +262,7 @@ namespace Nes
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
Result SetSampleRate(ulong rate) throw();
|
||||
@ -274,21 +274,6 @@ namespace Nes
|
||||
*/
|
||||
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.
|
||||
*
|
||||
|
@ -334,7 +334,7 @@ namespace Nes
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -97,13 +97,16 @@
|
||||
#include "NstBoardWaixing.hpp"
|
||||
#include "NstBoardWhirlwind.hpp"
|
||||
#include "NstBoardBenshengBs5.hpp"
|
||||
#include "NstBoardUnl158b.hpp"
|
||||
#include "NstBoardUnlA9746.hpp"
|
||||
#include "NstBoardUnlCc21.hpp"
|
||||
#include "NstBoardUnlEdu2000.hpp"
|
||||
#include "NstBoardUnlKingOfFighters96.hpp"
|
||||
#include "NstBoardUnlKingOfFighters97.hpp"
|
||||
#include "NstBoardUnlMmc3BigPrgRom.hpp"
|
||||
#include "NstBoardUnlMortalKombat2.hpp"
|
||||
#include "NstBoardUnlN625092.hpp"
|
||||
#include "NstBoardUnlRetX7Gbl.hpp"
|
||||
#include "NstBoardUnlSuperFighter3.hpp"
|
||||
#include "NstBoardUnlTf1201.hpp"
|
||||
#include "NstBoardUnlWorldHero.hpp"
|
||||
@ -1096,6 +1099,7 @@ namespace Nes
|
||||
{ "TENGEN-800032", Type::TENGEN_800032 },
|
||||
{ "TENGEN-800037", Type::TENGEN_800037 },
|
||||
{ "TENGEN-800042", Type::TENGEN_800042 },
|
||||
{ "UNL-158B", Type::UNL_158B },
|
||||
{ "UNL-22211", Type::TXC_22211A },
|
||||
{ "UNL-603-5052", Type::BTL_6035052 },
|
||||
{ "UNL-8237", Type::SUPERGAME_POCAHONTAS2 },
|
||||
@ -1472,6 +1476,13 @@ namespace Nes
|
||||
break;
|
||||
}
|
||||
|
||||
if (prg > SIZE_512K)
|
||||
{
|
||||
name = "UNL-MMC3BIGPRGROM";
|
||||
id = Type::UNL_MMC3BIGPRGROM;
|
||||
break;
|
||||
}
|
||||
|
||||
if (nmt == Type::NMT_FOURSCREEN)
|
||||
{
|
||||
if (prg == SIZE_64K && (chr == SIZE_32K || chr == SIZE_64K) && !wram && !useWramAuto)
|
||||
@ -1804,34 +1815,53 @@ namespace Nes
|
||||
|
||||
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");
|
||||
|
||||
chip.Pin(3) = L"PRG A2";
|
||||
chip.Pin(4) = L"PRG A1";
|
||||
|
||||
name = "KONAMI VRC4";
|
||||
id = Type::KONAMI_VRC4_0;
|
||||
}
|
||||
|
||||
name = "KONAMI VRC4";
|
||||
|
||||
break;
|
||||
|
||||
case 25:
|
||||
|
||||
if (submapper == 2)
|
||||
{ // The correct board is VRC2 but the functionality is implemented in the VRC4 code currently
|
||||
if (submapper == 3 || wram >= SIZE_8K) // VRC2c, but emulated as VRC4
|
||||
{
|
||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||
chip.Pin(3) = L"PRG A0";
|
||||
chip.Pin(4) = L"PRG A1";
|
||||
|
||||
name = "KONAMI VRC2";
|
||||
id = Type::KONAMI_VRC4_2;
|
||||
name = "KONAMI VRC2";
|
||||
break;
|
||||
}
|
||||
|
||||
if (!this->chips.Has(L"Konami VRC IV"))
|
||||
return false;
|
||||
else if (submapper == 2 || prg >= SIZE_256K) // VRC4d
|
||||
{
|
||||
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";
|
||||
id = Type::KONAMI_VRC4_2;
|
||||
break;
|
||||
|
||||
case 22:
|
||||
@ -1858,50 +1888,49 @@ namespace Nes
|
||||
|
||||
case 23:
|
||||
|
||||
if (submapper == 2)
|
||||
if (submapper == 1) // VRC4f - Unknown, but plausibly World Hero?
|
||||
{
|
||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||
|
||||
chip.Pin(3) = L"PRG A3";
|
||||
chip.Pin(4) = L"PRG A2";
|
||||
|
||||
chip.Pin(3) = L"PRG A1";
|
||||
chip.Pin(4) = L"PRG A0";
|
||||
name = "KONAMI VRC4";
|
||||
id = Type::KONAMI_VRC4_0;
|
||||
}
|
||||
else if (submapper == 3)
|
||||
{
|
||||
name = "KONAMI VRC2";
|
||||
id = Type::KONAMI_VRC2;
|
||||
break;
|
||||
}
|
||||
|
||||
if (prg >= SIZE_512K)
|
||||
{
|
||||
if (!this->chips.Has(L"Konami VRC IV"))
|
||||
else if (submapper == 2) // VRC4e
|
||||
{
|
||||
Chips::Type& chip = chips.Add(L"Konami VRC IV");
|
||||
|
||||
chip.Pin(3) = L"PRG A3";
|
||||
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";
|
||||
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";
|
||||
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;
|
||||
|
||||
case 24:
|
||||
@ -2344,13 +2373,6 @@ namespace Nes
|
||||
|
||||
case 78:
|
||||
|
||||
if (submapper == 1)
|
||||
{
|
||||
name = "JALECO JF-16";
|
||||
id = Type::JALECO_JF16;
|
||||
break;
|
||||
}
|
||||
|
||||
if (submapper == 3)
|
||||
{
|
||||
name = "IREM-HOLYDIVER";
|
||||
@ -2358,6 +2380,7 @@ namespace Nes
|
||||
break;
|
||||
}
|
||||
|
||||
// Default to submapper 1
|
||||
name = "JALECO JF-16";
|
||||
id = Type::JALECO_JF16;
|
||||
break;
|
||||
@ -3385,6 +3408,12 @@ namespace Nes
|
||||
id = Type::BMC_110IN1;
|
||||
break;
|
||||
|
||||
case 258:
|
||||
|
||||
name = "UNL-158B";
|
||||
id = Type::UNL_158B;
|
||||
break;
|
||||
|
||||
case 262:
|
||||
|
||||
name = "UNL-SHERO";
|
||||
@ -3494,6 +3523,12 @@ namespace Nes
|
||||
id = Type::BMC_SUPER_40IN1;
|
||||
break;
|
||||
|
||||
case 400:
|
||||
|
||||
name = "UNL-RET-X7-GBL";
|
||||
id = Type::UNL_RETX7GBL;
|
||||
break;
|
||||
|
||||
case 521:
|
||||
|
||||
name = "DREAMTECH01";
|
||||
@ -3887,14 +3922,17 @@ namespace Nes
|
||||
case Type::TXC_MXMDHTWO : return new Txc::Mxmdhtwo(c);
|
||||
case Type::TXC_POLICEMAN : return new Txc::Policeman(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_CC21 : return new Unlicensed::Cc21(c);
|
||||
case Type::UNL_EDU2000 : return new Unlicensed::Edu2000(c);
|
||||
case Type::UNL_FS304 : return new Waixing::Fs304(c);
|
||||
case Type::UNL_KINGOFFIGHTERS96 : return new Unlicensed::KingOfFighters96(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_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_SHERO : return new Sachen::StreetHeroes(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_TW = MakeId< 189, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
|
||||
// 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_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,
|
||||
@ -548,6 +549,7 @@ namespace Nes
|
||||
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_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_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,
|
||||
@ -562,6 +564,7 @@ namespace Nes
|
||||
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_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_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,
|
||||
|
@ -162,8 +162,6 @@ namespace Nes
|
||||
byte chr[8];
|
||||
} banks;
|
||||
|
||||
private:
|
||||
|
||||
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