From 8c2b99b53742ae0b4d7e4a654f6e450b428e04de Mon Sep 17 00:00:00 2001
From: rdanbrook <1869094+rdanbrook@users.noreply.github.com>
Date: Wed, 17 Mar 2021 16:21:51 -0400
Subject: [PATCH] Update core to 1.51.0
---
NstDatabase.xml | 95 ++++++
libretro/Makefile.common | 1 +
libretro/libretro.cpp | 4 +-
{extras => palettes}/BMFFINR2.pal | Bin
{extras => palettes}/BMFFINR3.pal | Bin
{extras => palettes}/CXA2025AS-1536.pal | Bin
.../Composite Direct (FBX).pal | Bin
{extras => palettes}/NES Classic (FBX-FS).pal | Bin
{extras => palettes}/NES_Classic-FBX.pal | Bin
{extras => palettes}/Nostalgia-FBX.pal | Bin
.../Original Hardware (FBX).pal | Bin
{extras => palettes}/PVM Style (FBX).pal | Bin
{extras => palettes}/PVM Style D93 (FBX).pal | Bin
{extras => palettes}/SONY_CXA2025AS_US.pal | Bin
{extras => palettes}/Smooth (FBX).pal | Bin
{extras => palettes}/Unsaturated-Final.pal | Bin
{extras => palettes}/Unsaturated-V5.pal | Bin
{extras => palettes}/Unsaturated-V6.pal | Bin
{extras => palettes}/Wavebeam.pal | Bin
{extras => palettes}/YUV-V3.pal | Bin
{extras => palettes}/hybrid.pal | Bin
{extras => palettes}/nescap.pal | Bin
{extras => palettes}/ntsc.pal | Bin
source/core/NstApu.cpp | 24 +-
source/core/NstApu.hpp | 16 +-
source/core/NstCartridgeInes.cpp | 2 +-
source/core/NstCpu.cpp | 70 ++--
source/core/NstCpu.hpp | 12 +-
source/core/NstFds.cpp | 67 ++--
source/core/NstFds.hpp | 4 +-
source/core/NstPpu.cpp | 183 ++++------
source/core/NstPpu.hpp | 25 +-
source/core/NstVideoRenderer.cpp | 2 -
source/core/api/NstApiVideo.cpp | 14 -
source/core/api/NstApiVideo.hpp | 5 -
source/core/board/NstBoard.cpp | 195 ++++++++++-
source/core/board/NstBoard.hpp | 55 +--
source/core/board/NstBoardCamerica.cpp | 6 +
source/core/board/NstBoardCamerica.hpp | 4 +
source/core/board/NstBoardKaiser.cpp | 315 +++++++++++++++---
source/core/board/NstBoardKaiser.hpp | 100 ++++--
source/core/board/NstBoardKonamiVrc2.cpp | 7 +-
source/core/board/NstBoardMmc1.cpp | 15 +
source/core/board/NstBoardMmc1.hpp | 3 +
source/core/board/NstBoardMmc5.cpp | 3 +-
source/core/board/NstBoardNamcot.hpp | 1 +
source/core/board/NstBoardNamcot175.cpp | 155 +--------
source/core/board/NstBoardNamcot175.hpp | 31 +-
source/core/board/NstBoardNamcot340.cpp | 89 +++++
source/core/board/NstBoardNamcot340.hpp | 58 ++++
source/core/board/NstBoardOpenCorp.cpp | 140 +++++++-
source/core/board/NstBoardOpenCorp.hpp | 11 +
source/core/board/NstBoardSunsoft5b.cpp | 2 +-
source/core/board/NstBoardTengenRambo1.cpp | 75 ++---
source/core/board/NstBoardTengenRambo1.hpp | 2 +
source/core/board/NstBoardUnlCc21.cpp | 3 +-
.../board/NstBoardUnlKingOfFighters97.cpp | 13 +-
.../board/NstBoardUnlKingOfFighters97.hpp | 2 +
58 files changed, 1230 insertions(+), 579 deletions(-)
rename {extras => palettes}/BMFFINR2.pal (100%)
rename {extras => palettes}/BMFFINR3.pal (100%)
rename {extras => palettes}/CXA2025AS-1536.pal (100%)
rename {extras => palettes}/Composite Direct (FBX).pal (100%)
rename {extras => palettes}/NES Classic (FBX-FS).pal (100%)
rename {extras => palettes}/NES_Classic-FBX.pal (100%)
rename {extras => palettes}/Nostalgia-FBX.pal (100%)
rename {extras => palettes}/Original Hardware (FBX).pal (100%)
rename {extras => palettes}/PVM Style (FBX).pal (100%)
rename {extras => palettes}/PVM Style D93 (FBX).pal (100%)
rename {extras => palettes}/SONY_CXA2025AS_US.pal (100%)
rename {extras => palettes}/Smooth (FBX).pal (100%)
rename {extras => palettes}/Unsaturated-Final.pal (100%)
rename {extras => palettes}/Unsaturated-V5.pal (100%)
rename {extras => palettes}/Unsaturated-V6.pal (100%)
rename {extras => palettes}/Wavebeam.pal (100%)
rename {extras => palettes}/YUV-V3.pal (100%)
rename {extras => palettes}/hybrid.pal (100%)
rename {extras => palettes}/nescap.pal (100%)
rename {extras => palettes}/ntsc.pal (100%)
create mode 100644 source/core/board/NstBoardNamcot340.cpp
create mode 100644 source/core/board/NstBoardNamcot340.hpp
diff --git a/NstDatabase.xml b/NstDatabase.xml
index d724eee..cee76b8 100644
--- a/NstDatabase.xml
+++ b/NstDatabase.xml
@@ -26916,4 +26916,99 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/libretro/Makefile.common b/libretro/Makefile.common
index 07f6678..56b1578 100644
--- a/libretro/Makefile.common
+++ b/libretro/Makefile.common
@@ -204,6 +204,7 @@ SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardMmc5.cpp
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardMmc6.cpp
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardNamcot163.cpp
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardNamcot175.cpp
+SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardNamcot340.cpp
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardNamcot34xx.cpp
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardNanjing.cpp
SOURCES_CXX += $(CORE_DIR)/source/core/board/NstBoardNihon.cpp
diff --git a/libretro/libretro.cpp b/libretro/libretro.cpp
index fcdbeae..55f3362 100644
--- a/libretro/libretro.cpp
+++ b/libretro/libretro.cpp
@@ -863,7 +863,7 @@ static void check_variables(void)
video.EnableUnlimSprites(true);
}
- var.key = "nestopia_overclock";
+/* var.key = "nestopia_overclock";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var))
{
@@ -872,7 +872,7 @@ static void check_variables(void)
else if (strcmp(var.value, "2x") == 0)
video.EnableOverclocking(true);
}
-
+*/
var.key = "nestopia_fds_auto_insert";
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var))
diff --git a/extras/BMFFINR2.pal b/palettes/BMFFINR2.pal
similarity index 100%
rename from extras/BMFFINR2.pal
rename to palettes/BMFFINR2.pal
diff --git a/extras/BMFFINR3.pal b/palettes/BMFFINR3.pal
similarity index 100%
rename from extras/BMFFINR3.pal
rename to palettes/BMFFINR3.pal
diff --git a/extras/CXA2025AS-1536.pal b/palettes/CXA2025AS-1536.pal
similarity index 100%
rename from extras/CXA2025AS-1536.pal
rename to palettes/CXA2025AS-1536.pal
diff --git a/extras/Composite Direct (FBX).pal b/palettes/Composite Direct (FBX).pal
similarity index 100%
rename from extras/Composite Direct (FBX).pal
rename to palettes/Composite Direct (FBX).pal
diff --git a/extras/NES Classic (FBX-FS).pal b/palettes/NES Classic (FBX-FS).pal
similarity index 100%
rename from extras/NES Classic (FBX-FS).pal
rename to palettes/NES Classic (FBX-FS).pal
diff --git a/extras/NES_Classic-FBX.pal b/palettes/NES_Classic-FBX.pal
similarity index 100%
rename from extras/NES_Classic-FBX.pal
rename to palettes/NES_Classic-FBX.pal
diff --git a/extras/Nostalgia-FBX.pal b/palettes/Nostalgia-FBX.pal
similarity index 100%
rename from extras/Nostalgia-FBX.pal
rename to palettes/Nostalgia-FBX.pal
diff --git a/extras/Original Hardware (FBX).pal b/palettes/Original Hardware (FBX).pal
similarity index 100%
rename from extras/Original Hardware (FBX).pal
rename to palettes/Original Hardware (FBX).pal
diff --git a/extras/PVM Style (FBX).pal b/palettes/PVM Style (FBX).pal
similarity index 100%
rename from extras/PVM Style (FBX).pal
rename to palettes/PVM Style (FBX).pal
diff --git a/extras/PVM Style D93 (FBX).pal b/palettes/PVM Style D93 (FBX).pal
similarity index 100%
rename from extras/PVM Style D93 (FBX).pal
rename to palettes/PVM Style D93 (FBX).pal
diff --git a/extras/SONY_CXA2025AS_US.pal b/palettes/SONY_CXA2025AS_US.pal
similarity index 100%
rename from extras/SONY_CXA2025AS_US.pal
rename to palettes/SONY_CXA2025AS_US.pal
diff --git a/extras/Smooth (FBX).pal b/palettes/Smooth (FBX).pal
similarity index 100%
rename from extras/Smooth (FBX).pal
rename to palettes/Smooth (FBX).pal
diff --git a/extras/Unsaturated-Final.pal b/palettes/Unsaturated-Final.pal
similarity index 100%
rename from extras/Unsaturated-Final.pal
rename to palettes/Unsaturated-Final.pal
diff --git a/extras/Unsaturated-V5.pal b/palettes/Unsaturated-V5.pal
similarity index 100%
rename from extras/Unsaturated-V5.pal
rename to palettes/Unsaturated-V5.pal
diff --git a/extras/Unsaturated-V6.pal b/palettes/Unsaturated-V6.pal
similarity index 100%
rename from extras/Unsaturated-V6.pal
rename to palettes/Unsaturated-V6.pal
diff --git a/extras/Wavebeam.pal b/palettes/Wavebeam.pal
similarity index 100%
rename from extras/Wavebeam.pal
rename to palettes/Wavebeam.pal
diff --git a/extras/YUV-V3.pal b/palettes/YUV-V3.pal
similarity index 100%
rename from extras/YUV-V3.pal
rename to palettes/YUV-V3.pal
diff --git a/extras/hybrid.pal b/palettes/hybrid.pal
similarity index 100%
rename from extras/hybrid.pal
rename to palettes/hybrid.pal
diff --git a/extras/nescap.pal b/palettes/nescap.pal
similarity index 100%
rename from extras/nescap.pal
rename to palettes/nescap.pal
diff --git a/extras/ntsc.pal b/palettes/ntsc.pal
similarity index 100%
rename from extras/ntsc.pal
rename to palettes/ntsc.pal
diff --git a/source/core/NstApu.cpp b/source/core/NstApu.cpp
index 19e4388..746096d 100644
--- a/source/core/NstApu.cpp
+++ b/source/core/NstApu.cpp
@@ -361,6 +361,11 @@ namespace Nes
return 0;
}
+ uint Apu::GetCtrl()
+ {
+ return ctrl;
+ }
+
Result Apu::SetSpeed(const uint speed)
{
if (settings.speed == speed)
@@ -1670,7 +1675,7 @@ namespace Nes
step = 0x7;
status = STATUS_COUNTING;
waveLength = 0;
- linearCtrl = 0;
+ //linearCtrl = 0;
linearCounter = 0;
lengthCounter.Reset();
@@ -1870,7 +1875,6 @@ namespace Nes
amp = (sum * outputVolume + rate/2) / rate * 3;
}
}
- // Disabling these blocks fixes scratchy audio in many games
/*else if (amp < Channel::OUTPUT_DECAY)
{
return 0;
@@ -2121,7 +2125,6 @@ namespace Nes
dma.buffered = false;
dma.address = 0xC000;
dma.buffer = 0x00;
- overclockingIsSafe = true;
}
Cycle Apu::Dmc::GetResetFrequency(CpuModel model)
@@ -2362,31 +2365,16 @@ namespace Nes
{
out.dac = data & 0x7F;
curSample = out.dac * outputVolume;
-
- if (out.dac != 0)
- {
- overclockingIsSafe = false;
- }
}
NST_SINGLE_CALL void Apu::Dmc::WriteReg2(const uint data)
{
regs.address = 0xC000 | (data << 6);
-
- if (regs.address != 0)
- {
- overclockingIsSafe = true;
- }
}
NST_SINGLE_CALL void Apu::Dmc::WriteReg3(const uint data)
{
regs.lengthCounter = (data << 4) + 1;
-
- if (regs.lengthCounter != 0)
- {
- overclockingIsSafe = true;
- }
}
NST_SINGLE_CALL bool Apu::Dmc::ClockDAC()
diff --git a/source/core/NstApu.hpp b/source/core/NstApu.hpp
index 9af2f8d..9820108 100644
--- a/source/core/NstApu.hpp
+++ b/source/core/NstApu.hpp
@@ -50,7 +50,6 @@ namespace Nes
public:
explicit Apu(Cpu&);
-
void Reset(bool);
void PowerOff();
void ClearBuffers();
@@ -65,6 +64,7 @@ namespace Nes
Result SetSpeed(uint);
Result SetVolume(uint,uint);
uint GetVolume(uint) const;
+ uint GetCtrl();
void Mute(bool);
void SetAutoTranspose(bool);
void SetGenie(bool);
@@ -461,7 +461,7 @@ namespace Nes
enum
{
MIN_FRQ = 2 + 1,
- STEP_CHECK = 0x00, // >= 0x1F is technically correct but will produce clicks/pops
+ STEP_CHECK = 0x1F,
REG0_LINEAR_COUNTER_LOAD = 0x7F,
REG0_LINEAR_COUNTER_START = 0x80,
REG2_WAVE_LENGTH_LOW = 0x00FF,
@@ -529,8 +529,6 @@ namespace Nes
Dmc();
- bool overclockingIsSafe;
-
void Reset(CpuModel);
void UpdateSettings(uint);
void LoadState(State::Loader&,const Cpu&,CpuModel,Cycle&);
@@ -628,16 +626,6 @@ namespace Nes
public:
- void SetOverclockSafety(bool safe)
- {
- dmc.overclockingIsSafe = safe;
- }
-
- bool GetOverclockSafety()
- {
- return dmc.overclockingIsSafe;
- }
-
dword GetSampleRate() const
{
return settings.rate;
diff --git a/source/core/NstCartridgeInes.cpp b/source/core/NstCartridgeInes.cpp
index 37e6789..7c72b9b 100644
--- a/source/core/NstCartridgeInes.cpp
+++ b/source/core/NstCartridgeInes.cpp
@@ -674,7 +674,7 @@ namespace Nes
if (setup.version)
{
- setup.mapper |= uint(header[8]) << 8 & 0x100;
+ setup.mapper |= uint(header[8]) << 8 & 0x300;
setup.subMapper = header[8] >> 4;
}
diff --git a/source/core/NstCpu.cpp b/source/core/NstCpu.cpp
index 820aad6..f02f53a 100644
--- a/source/core/NstCpu.cpp
+++ b/source/core/NstCpu.cpp
@@ -204,8 +204,6 @@ namespace Nes
ticks = 0;
logged = 0;
- cpuOverclocking = false;
-
pc = RESET_VECTOR;
cycles.count = 0;
@@ -247,7 +245,12 @@ namespace Nes
if (hard)
{
Poke(0x4017, 0x00);
- cycles.count = cycles.clock[RESET_CYCLES-1];
+ cycles.count = cycles.clock[RESET_CYCLES] + cycles.clock[0];
+ }
+ else
+ {
+ Poke(0x4017, apu.GetCtrl());
+ cycles.count = cycles.clock[RESET_CYCLES] + cycles.clock[0];
}
}
@@ -1723,18 +1726,42 @@ namespace Nes
return address;
}
- NST_SINGLE_CALL uint Cpu::Shx(uint address)
+ NST_SINGLE_CALL void Cpu::Shx(uint address)
{
- address = x & ((address >> 8) + 1);
+ uint newaddress = (address + y);
+ uint data = x & ((address >> 8) + 1);
+ Peek((address & 0xFF00) | (newaddress & 0x00FF)); // Dummy read
+
+ if ((address ^ newaddress) & 0x100)
+ {
+ address = (newaddress & (x << 8)) | (newaddress & 0x00FF);
+ }
+ else
+ {
+ address = newaddress;
+ }
+
NotifyOp("SHX",1UL << 15);
- return address;
+ StoreMem(address, data);
}
- NST_SINGLE_CALL uint Cpu::Shy(uint address)
+ NST_SINGLE_CALL void Cpu::Shy(uint address)
{
- address = y & ((address >> 8) + 1);
+ uint newaddress = (address + x);
+ uint data = y & ((address >> 8) + 1);
+ Peek((address & 0xFF00) | (newaddress & 0x00FF)); // Dummy read
+
+ if ((address ^ newaddress) & 0x100)
+ {
+ address = (newaddress & (y << 8)) | (newaddress & 0x00FF);
+ }
+ else
+ {
+ address = newaddress;
+ }
+
NotifyOp("SHY",1UL << 16);
- return address;
+ StoreMem(address, data);
}
NST_NO_INLINE uint Cpu::Slo(uint data)
@@ -1901,18 +1928,6 @@ namespace Nes
if (interrupt.irqClock != CYCLE_MAX)
interrupt.irqClock = (interrupt.irqClock > cycles.frame ? interrupt.irqClock - cycles.frame : 0);
-
- if (cpuOverclocking)
- {
- uint startCycle = cycles.count;
- uint lastCycle = cycles.count + extraCycles;
- do
- {
- ExecuteOp();
- }
- while (cycles.count < extraCycles);
- cycles.count = startCycle;
- }
}
void Cpu::Clock()
@@ -2095,6 +2110,15 @@ namespace Nes
Store##addr_( dst, instr_(dst) ); \
}
+ // Unofficial Opcodes SHX/SHY are edge cases
+ #define NES_I_W_U(instr_,addr_,hex_) \
+ \
+ void Cpu::op##hex_() \
+ { \
+ const uint dst = addr_##_W(); \
+ instr_(dst); \
+ }
+
#define NES_IP_C_(instr_,ops_,ticks_,hex_) \
\
void Cpu::op##hex_() \
@@ -2352,8 +2376,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_A( Shx, AbsY, 0x9E )
- NES_I_W_A( Shy, AbsX, 0x9C )
+ 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_IRW__( Slo, Zpg, 0x07 )
NES_IRW__( Slo, ZpgX, 0x17 )
NES_IRW__( Slo, Abs, 0x0F )
diff --git a/source/core/NstCpu.hpp b/source/core/NstCpu.hpp
index 6dcae70..0523b19 100644
--- a/source/core/NstCpu.hpp
+++ b/source/core/NstCpu.hpp
@@ -260,8 +260,8 @@ namespace Nes
NST_SINGLE_CALL void Lxa (uint);
NST_SINGLE_CALL void Sbx (uint);
NST_SINGLE_CALL uint Shs (uint);
- NST_SINGLE_CALL uint Shx (uint);
- NST_SINGLE_CALL uint Shy (uint);
+ NST_SINGLE_CALL void Shx (uint);
+ NST_SINGLE_CALL void Shy (uint);
NST_NO_INLINE void Anc (uint);
NST_NO_INLINE uint Dcp (uint);
@@ -487,8 +487,6 @@ namespace Nes
Ram ram;
Apu apu;
IoMap map;
- bool cpuOverclocking;
- uint extraCycles;
static dword logged;
static void (Cpu::*const opcodes[0x100])();
@@ -501,12 +499,6 @@ namespace Nes
return apu;
}
- void SetOverclocking(bool overclocking,uint newCycles)
- {
- cpuOverclocking = overclocking;
- extraCycles = newCycles;
- }
-
Cycle Update(uint readAddress=0)
{
apu.ClockDMA( readAddress );
diff --git a/source/core/NstFds.cpp b/source/core/NstFds.cpp
index c4cb00d..ccbebd3 100644
--- a/source/core/NstFds.cpp
+++ b/source/core/NstFds.cpp
@@ -373,7 +373,7 @@ namespace Nes
{
State::Loader::Data<4> data( state );
- io.ctrl = data[0];
+ io.ctrl = adapter.ctrl = data[0];
io.port = data[1];
break;
}
@@ -550,7 +550,13 @@ namespace Nes
NES_POKE_D(Fds,4023)
{
- io.ctrl = data;
+ io.ctrl = adapter.ctrl = data;
+
+ if (!(io.ctrl & Io::CTRL0_DISK_ENABLED))
+ {
+ cpu.ClearIRQ();
+ adapter.DisableIRQ();
+ }
}
NES_POKE_D(Fds,4026)
@@ -783,21 +789,25 @@ namespace Nes
#pragma optimize("", on)
#endif
- void Fds::Unit::Timer::Advance(uint& timer)
+ bool Fds::Unit::Timer::Clock()
{
- timer |= STATUS_PENDING_IRQ;
+ bool retval = false;
- if (ctrl & CTRL_REPEAT)
- count = latch;
- else
- ctrl &= ~uint(CTRL_ENABLED);
-
- latch = 0; // Fixes Kaettekita Mario Bros - FHorse/dragon2snow
- }
+ if (ctrl & CTRL_ENABLED)
+ {
+ if (count == 0)
+ {
+ retval = true;
+ count = latch;
- NST_SINGLE_CALL bool Fds::Unit::Timer::Clock()
- {
- return !(ctrl & CTRL_ENABLED) || !count || --count;
+ if (!(ctrl & CTRL_REPEAT))
+ ctrl &= ~uint(CTRL_ENABLED);
+ }
+ else
+ count--;
+ }
+
+ return retval;
}
#ifdef NST_MSVC_OPTIMIZE
@@ -1202,11 +1212,15 @@ namespace Nes
ibool Fds::Unit::Clock()
{
- return
- (
- (timer.Clock() ? 0 : (timer.Advance(status), 1)) |
- (drive.Clock() ? 0 : drive.Advance(status))
- );
+ bool retval = false;
+
+ if (timer.Clock())
+ {
+ status |= STATUS_PENDING_IRQ;
+ retval = true;
+ }
+
+ return (retval | (drive.Clock() ? 0 : drive.Advance(status)));
}
#ifdef NST_MSVC_OPTIMIZE
@@ -1216,6 +1230,12 @@ namespace Nes
Fds::Adapter::Adapter(Cpu& c,const Disks::Sides& s)
: Timer::M2(c,s) {}
+ void Fds::Adapter::DisableIRQ()
+ {
+ unit.status &= ~uint(Unit::STATUS_PENDING_IRQ);
+ unit.timer.ctrl &= ~uint(Unit::Timer::CTRL_ENABLED);
+ }
+
void Fds::Adapter::Reset(Cpu& cpu,byte* const io,bool protect)
{
Timer::M2::Reset( true, true );
@@ -1379,12 +1399,17 @@ namespace Nes
{
Update();
+ if (!(ctrl & Io::CTRL0_DISK_ENABLED))
+ return;
+
unit.timer.ctrl = data;
unit.timer.count = unit.timer.latch;
unit.status &= Unit::STATUS_TRANSFERED;
- if (!unit.status)
- ClearIRQ();
+ if (data & Unit::Timer::CTRL_ENABLED)
+ return;
+
+ ClearIRQ();
}
NES_POKE_D(Fds::Adapter,4024)
diff --git a/source/core/NstFds.hpp b/source/core/NstFds.hpp
index eb7b0b6..07d6506 100644
--- a/source/core/NstFds.hpp
+++ b/source/core/NstFds.hpp
@@ -340,7 +340,6 @@ namespace Nes
Timer();
void Reset();
- void Advance(uint&);
NST_SINGLE_CALL bool Clock();
@@ -435,6 +434,7 @@ namespace Nes
Adapter(Cpu&,const Disks::Sides&);
+ void DisableIRQ();
void Reset(Cpu&,byte*,bool=false);
void LoadState(State::Loader&,dword,Ppu&);
void SaveState(State::Saver&) const;
@@ -447,6 +447,8 @@ namespace Nes
NST_SINGLE_CALL uint Activity() const;
using Timer::M2::VSync;
+
+ byte ctrl;
};
struct Io
diff --git a/source/core/NstPpu.cpp b/source/core/NstPpu.cpp
index 5b6707b..d4d3251 100644
--- a/source/core/NstPpu.cpp
+++ b/source/core/NstPpu.cpp
@@ -108,7 +108,6 @@ namespace Nes
yuvMap (NULL)
{
cycles.one = PPU_RP2C02_CC;
- overclocked = false;
PowerOff();
}
@@ -169,7 +168,7 @@ namespace Nes
{
static const byte powerUpPalette[] =
{
- 0x3F,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,
+ 0x09,0x01,0x00,0x01,0x00,0x02,0x02,0x0D,
0x08,0x10,0x08,0x24,0x00,0x00,0x04,0x2C,
0x09,0x01,0x34,0x03,0x00,0x04,0x00,0x14,
0x08,0x3A,0x00,0x02,0x00,0x20,0x2C,0x08
@@ -240,8 +239,7 @@ namespace Nes
cycles.count = Cpu::CYCLE_MAX;
scanline = SCANLINE_VBLANK;
- scanline_sleep = -1;
- ssleep = -1;
+ scanline_sleep = 0;
io.address = 0;
io.pattern = 0;
@@ -493,8 +491,6 @@ namespace Nes
Cycle frame;
- scanline_sleep = -1;
-
switch (model)
{
case PPU_RP2C02:
@@ -503,8 +499,6 @@ namespace Nes
default:
- ssleep = PPU_RP2C02_VSLEEP - 2;
-
if (cycles.hClock == HCLOCK_DUMMY)
{
cycles.vClock = PPU_RP2C02_HVINT / PPU_RP2C02_CC - HCLOCK_DUMMY;
@@ -521,8 +515,6 @@ namespace Nes
case PPU_RP2C07:
- ssleep = PPU_RP2C07_VSLEEP - 2;
-
if (cycles.hClock == HCLOCK_DUMMY)
{
cycles.vClock = PPU_RP2C07_HVINT / PPU_RP2C07_CC - HCLOCK_DUMMY;
@@ -539,8 +531,6 @@ namespace Nes
case PPU_DENDY:
- ssleep = PPU_DENDY_VSLEEP - 2;
-
if (cycles.hClock == HCLOCK_DUMMY)
{
cycles.vClock = PPU_DENDY_HVINT / PPU_DENDY_CC - HCLOCK_DUMMY;
@@ -556,44 +546,6 @@ namespace Nes
break;
}
- if (overclocked)
- {
- Apu& audioSafeOverclock = cpu.GetApu();
- if (audioSafeOverclock.GetOverclockSafety())
- {
- switch (model)
- {
- case PPU_RP2C02:
- default:
-
- cpu.SetOverclocking(true,PPU_RP2C02_HSYNC * PPU_RP2C02_VACTIVE);
- break;
-
- case PPU_RP2C07:
-
- cpu.SetOverclocking(true,PPU_RP2C07_HSYNC * PPU_RP2C07_VACTIVE);
- break;
-
- case PPU_DENDY:
-
- cpu.SetOverclocking(true,PPU_DENDY_HSYNC * PPU_DENDY_VACTIVE);
- break;
- }
- }
- else
- {
- cpu.SetOverclocking(false,0);
- }
-
- audioSafeOverclock.SetOverclockSafety(true);//overclocking is only safe if direct pcm audio has not been written for one frame
- }
- else
- {
- cpu.SetOverclocking(false,0);
- Apu& audioSafeOverclock = cpu.GetApu();
- audioSafeOverclock.SetOverclockSafety(false);
- }
-
cpu.SetFrameCycles( frame );
}
@@ -698,6 +650,12 @@ namespace Nes
io.line.Toggle( io.address, GetCycles() );
}
+ NST_FORCE_INLINE void Ppu::UpdateScrollAddressLine()
+ {
+ if (io.line)
+ io.line.Toggle( scroll.address & 0x3FFF, cpu.GetCycles() );
+ }
+
NST_FORCE_INLINE void Ppu::UpdateVramAddress()
{
if ((scanline != SCANLINE_VBLANK ) && (regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED))
@@ -824,7 +782,7 @@ namespace Nes
oam.mask = oam.show[pos];
if ((regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) && !(data & Regs::CTRL1_BG_SP_ENABLED))
- UpdateAddressLine(scroll.address & 0x3fff);
+ UpdateScrollAddressLine();
}
io.latch = data;
@@ -968,10 +926,7 @@ namespace Nes
{
scroll.latch = (scroll.latch & 0x7F00) | data;
scroll.address = scroll.latch;
- if (!(regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED) ||
- (scanline == SCANLINE_VBLANK)) {
- UpdateAddressLine(scroll.address & 0x3fff);
- }
+ UpdateScrollAddressLine();
}
}
}
@@ -983,13 +938,11 @@ namespace Nes
uint address = scroll.address;
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);
- }
- else {
+ else
return;
- }
io.latch = data;
@@ -1027,10 +980,9 @@ namespace Nes
address = scroll.address & 0x3FFF;
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);
- }
io.latch = (address & 0x3F00) != 0x3F00 ? io.buffer : palette.ram[address & 0x1F] & Coloring();
io.buffer = (address >= 0x2000 ? nmt.FetchName( address ) : chr.FetchPattern( address ));
@@ -1458,7 +1410,7 @@ namespace Nes
{
NST_VERIFY( cycles.count != cycles.hClock );
- if (scanline_sleep >= 0)
+ if (scanline_sleep) // Extra lines between VBLANK and NMI in Dendy mode
{
switch (cycles.hClock)
{
@@ -1807,15 +1759,15 @@ namespace Nes
case 338:
- if (scanline_sleep++ != ssleep)
+ if (++scanline_sleep < PPU_DENDY_VSLEEP)
{
cycles.hClock = 0;
- cycles.vClock += 341;
+ cycles.vClock += HCLOCK_DUMMY;
- if (cycles.count <= 341)
+ if (cycles.count <= HCLOCK_DUMMY)
break;
- cycles.count -= 341;
+ cycles.count -= HCLOCK_DUMMY;
goto HActiveSleep;
}
@@ -1828,37 +1780,13 @@ namespace Nes
}
case HCLOCK_VBLANK_0:
- VBlank0:
-
- regs.status |= Regs::STATUS_VBLANKING;
- cycles.hClock = HCLOCK_VBLANK_1;
-
- if (cycles.count <= HCLOCK_VBLANK_1)
- break;
+ goto VBlank0;
case HCLOCK_VBLANK_1:
- VBlank1:
-
- regs.status = (regs.status & 0xFF) | (regs.status >> 1 & Regs::STATUS_VBLANK);
- oam.visible = oam.output;
- cycles.hClock = HCLOCK_VBLANK_2;
-
- if (cycles.count <= HCLOCK_VBLANK_2)
- break;
+ goto VBlank1;
case HCLOCK_VBLANK_2:
- VBlank2:
-
- scanline_sleep = -1;
-
- cycles.hClock = HCLOCK_DUMMY;
- cycles.count = Cpu::CYCLE_MAX;
- cycles.reset = 0;
-
- if (regs.ctrl[0] & regs.status & Regs::CTRL0_NMI)
- cpu.DoNMI( cpu.GetFrameCycles() );
-
- return;
+ goto VBlank2;
}
}
else if (regs.ctrl[1] & Regs::CTRL1_BG_SP_ENABLED)
@@ -2519,7 +2447,7 @@ namespace Nes
if (scanline++ != 239)
{
- const uint line = (scanline != 0 || model != PPU_RP2C02 || !regs.frame ? 341 : 340);
+ const uint line = (scanline != 0 || model != PPU_RP2C02 || !regs.frame ? HCLOCK_DUMMY : (HCLOCK_DUMMY - 1));
cycles.hClock = 0;
cycles.vClock += line;
@@ -2533,16 +2461,17 @@ namespace Nes
}
else
{
- if (ssleep >= 0)
+ if (model == PPU_DENDY)
{
- scanline_sleep = 0;
- cycles.hClock = 0;
- cycles.vClock += 341;
+ scanline_sleep = 1;
- if (cycles.count <= 341)
+ cycles.hClock = 0;
+ cycles.vClock += HCLOCK_DUMMY;
+
+ if (cycles.count <= HCLOCK_DUMMY)
break;
- cycles.count -= 341;
+ cycles.count -= HCLOCK_DUMMY;
goto HActiveSleep;
}
@@ -2556,13 +2485,37 @@ namespace Nes
}
case HCLOCK_VBLANK_0:
- goto VBlank0;
+ VBlank0:
+
+ regs.status |= Regs::STATUS_VBLANKING;
+ cycles.hClock = HCLOCK_VBLANK_1;
+
+ if (cycles.count <= HCLOCK_VBLANK_1)
+ break;
case HCLOCK_VBLANK_1:
- goto VBlank1;
+ VBlank1:
+
+ regs.status = (regs.status & 0xFF) | (regs.status >> 1 & Regs::STATUS_VBLANK);
+ oam.visible = oam.output;
+ cycles.hClock = HCLOCK_VBLANK_2;
+
+ if (cycles.count <= HCLOCK_VBLANK_2)
+ break;
case HCLOCK_VBLANK_2:
- goto VBlank2;
+ VBlank2:
+
+ scanline_sleep = 0;
+
+ cycles.hClock = HCLOCK_DUMMY;
+ cycles.count = Cpu::CYCLE_MAX;
+ cycles.reset = 0;
+
+ if (regs.ctrl[0] & regs.status & Regs::CTRL0_NMI)
+ cpu.DoNMI( cpu.GetFrameCycles() );
+
+ return;
case HCLOCK_BOOT:
goto Boot;
@@ -3227,29 +3180,29 @@ namespace Nes
if (scanline == 0 && model == PPU_RP2C02)
output.burstPhase = (output.burstPhase + 1) % 3;
- cycles.vClock += 341;
+ cycles.vClock += HCLOCK_DUMMY;
cycles.hClock = 0;
- if (cycles.count <= 341)
+ if (cycles.count <= HCLOCK_DUMMY)
break;
- cycles.count -= 341;
+ cycles.count -= HCLOCK_DUMMY;
goto HActiveOff;
}
- else
- {
- if (ssleep >= 0)
+ else
+ {
+ if (model == PPU_DENDY)
{
- scanline_sleep = 0;
+ scanline_sleep = 1;
- cycles.vClock += 341;
+ cycles.vClock += HCLOCK_DUMMY;
cycles.hClock = 0;
- if (cycles.count <= 341)
+ if (cycles.count <= HCLOCK_DUMMY)
break;
- cycles.count -= 341;
+ cycles.count -= HCLOCK_DUMMY;
goto HActiveSleep;
}
diff --git a/source/core/NstPpu.hpp b/source/core/NstPpu.hpp
index ee4c25e..a4c1078 100644
--- a/source/core/NstPpu.hpp
+++ b/source/core/NstPpu.hpp
@@ -139,7 +139,6 @@ namespace Nes
enum
{
- HCLOCK_POSTRENDER = 340,
HCLOCK_DUMMY = 341,
HCLOCK_VBLANK_0 = 681,
HCLOCK_VBLANK_1 = 682,
@@ -176,6 +175,7 @@ namespace Nes
NST_FORCE_INLINE uint Emphasis() const;
NST_FORCE_INLINE void UpdateAddressLine(uint);
+ NST_FORCE_INLINE void UpdateScrollAddressLine();
NST_FORCE_INLINE void UpdateVramAddress();
NST_FORCE_INLINE void OpenName();
@@ -345,9 +345,6 @@ namespace Nes
typedef void (Ppu::*Phase)();
- byte ram[0x100];
- byte buffer[MAX_LINE_SPRITES * 4];
-
const byte* limit;
Output* visible;
Phase phase;
@@ -361,6 +358,9 @@ namespace Nes
bool spriteZeroInLine;
bool spriteLimit;
+ byte ram[0x100];
+ byte buffer[MAX_LINE_SPRITES*4];
+
Output output[MAX_LINE_SPRITES];
};
@@ -415,9 +415,9 @@ namespace Nes
Nmt nmt;
int scanline;
int scanline_sleep;
- int ssleep;
- bool overclocked;
-
+ public:
+ Output output;
+ private:
PpuModel model;
Hook hActiveHook;
Hook hBlankHook;
@@ -432,7 +432,6 @@ namespace Nes
static const byte yuvMaps[4][0x40];
public:
- Output output;
void Update()
{
@@ -543,16 +542,6 @@ namespace Nes
{
return oam.spriteLimit;
}
-
- bool GetOverclockState() const
- {
- return overclocked;
- }
-
- void SetOverclockState(bool overclock2x)
- {
- overclocked = overclock2x;
- }
};
}
}
diff --git a/source/core/NstVideoRenderer.cpp b/source/core/NstVideoRenderer.cpp
index 9070b5a..83077dc 100644
--- a/source/core/NstVideoRenderer.cpp
+++ b/source/core/NstVideoRenderer.cpp
@@ -22,12 +22,10 @@
//
////////////////////////////////////////////////////////////////////////////////////////
-#ifdef __LIBRETRO__
#define NST_NO_SCALEX 1
#define NST_NO_HQ2X 1
#define NST_NO_2XSAI 1
#define NST_NO_XBR 1
-#endif
#include
#include
diff --git a/source/core/api/NstApiVideo.cpp b/source/core/api/NstApiVideo.cpp
index 92c8cb9..3668413 100644
--- a/source/core/api/NstApiVideo.cpp
+++ b/source/core/api/NstApiVideo.cpp
@@ -58,20 +58,6 @@ namespace Nes
return RESULT_NOP;
}
- Result Video::EnableOverclocking(bool state) throw()
- {
- if (emulator.tracker.IsLocked( true ))
- return RESULT_ERR_NOT_READY;
-
- if (emulator.ppu.GetOverclockState() != state)
- {
- emulator.ppu.SetOverclockState( state );
- return RESULT_OK;
- }
-
- return RESULT_NOP;
- }
-
bool Video::AreUnlimSpritesEnabled() const throw()
{
return !emulator.ppu.HasSpriteLimit();
diff --git a/source/core/api/NstApiVideo.hpp b/source/core/api/NstApiVideo.hpp
index d623947..4b137ae 100644
--- a/source/core/api/NstApiVideo.hpp
+++ b/source/core/api/NstApiVideo.hpp
@@ -223,11 +223,6 @@ namespace Nes
* @return result code
*/
Result EnableUnlimSprites(bool state) throw();
-
- /**
- * Adds extra scanlines to fix lag
- */
- Result EnableOverclocking(bool state) throw();
/**
* Checks if the PPU sprite software extension is enabled.
diff --git a/source/core/board/NstBoard.cpp b/source/core/board/NstBoard.cpp
index 86d30c4..06f949f 100644
--- a/source/core/board/NstBoard.cpp
+++ b/source/core/board/NstBoard.cpp
@@ -97,13 +97,13 @@
#include "NstBoardWaixing.hpp"
#include "NstBoardWhirlwind.hpp"
#include "NstBoardBenshengBs5.hpp"
-#include "NstBoardUnlN625092.hpp"
#include "NstBoardUnlA9746.hpp"
#include "NstBoardUnlCc21.hpp"
#include "NstBoardUnlEdu2000.hpp"
#include "NstBoardUnlKingOfFighters96.hpp"
#include "NstBoardUnlKingOfFighters97.hpp"
#include "NstBoardUnlMortalKombat2.hpp"
+#include "NstBoardUnlN625092.hpp"
#include "NstBoardUnlSuperFighter3.hpp"
#include "NstBoardUnlTf1201.hpp"
#include "NstBoardUnlWorldHero.hpp"
@@ -397,7 +397,16 @@ namespace Nes
{
wrk.Source().SetSecurity( true, board.GetWram() > 0 );
- for (uint i=board.GetSavableWram(), n=board.GetWram(); i < n; ++i)
+ uint i = board.GetSavableWram();
+ uint n = board.GetWram();
+
+ if (board.GetMapper() == 1 && board.GetWram() == SIZE_16K)
+ {
+ i = 0;
+ n = SIZE_8K;
+ }
+
+ for (; i < n; ++i)
*wrk.Source().Mem(i) = (board.IsAutoWram() && i < SIZE_8K) ? (0x6000 + i) >> 8 : 0x00;
vram.Fill( 0x00 );
@@ -815,7 +824,7 @@ namespace Nes
{ "CAMERICA-BF9097", Type::CAMERICA_BF9097 },
{ "CAMERICA-GAMEGENIE", Type::STD_NROM },
{ "COLORDREAMS-74*377", Type::DISCRETE_74_377 },
- { "DREAMTECH01", Type::DREAMTECH_01 },
+ { "DREAMTECH01", Type::DREAMTECH01 },
{ "HVC-AMROM", Type::STD_AMROM },
{ "HVC-AN1ROM", Type::STD_AN1ROM },
{ "HVC-ANROM", Type::STD_ANROM },
@@ -1096,8 +1105,11 @@ namespace Nes
{ "UNL-EDU2000", Type::UNL_EDU2000 },
{ "UNL-H2288", Type::KAY_H2288 },
{ "UNL-KOF97", Type::UNL_KINGOFFIGHTERS97 },
+ { "UNL-KS7013B", Type::KAISER_KS7013B },
+ { "UNL-KS7016", Type::KAISER_KS7016 },
{ "UNL-KS7031", Type::KAISER_KS7031 },
{ "UNL-KS7032", Type::KAISER_KS7032 },
+ { "UNL-KS7037", Type::KAISER_KS7037 },
{ "UNL-N625092", Type::UNL_N625092 },
{ "UNL-SA-0036", Type::SACHEN_SA0036 },
{ "UNL-SA-0037", Type::SACHEN_SA0037 },
@@ -1110,7 +1122,7 @@ namespace Nes
{ "UNL-SACHEN-8259B", Type::SACHEN_8259B },
{ "UNL-SACHEN-8259C", Type::SACHEN_8259C },
{ "UNL-SACHEN-8259D", Type::SACHEN_8259D },
- { "UNL-SHERO", Type::SACHEN_STREETHEROES },
+ { "UNL-SHERO", Type::UNL_SHERO },
{ "UNL-SL1632", Type::REXSOFT_SL1632 },
{ "UNL-SMB2J", Type::BTL_SMB2_C },
{ "UNL-T-230", Type::BTL_T230 },
@@ -1218,7 +1230,7 @@ namespace Nes
return true;
}
- bool Board::Context::DetectBoard(const byte mapper,const byte submapper,const dword chrRam,const dword wram,bool wramAuto)
+ bool Board::Context::DetectBoard(const word mapper,const byte submapper,const dword chrRam,const dword wram,bool wramAuto)
{
Type::Id id;
@@ -1241,7 +1253,12 @@ namespace Nes
{
case 0:
- if ((prg < SIZE_32K && prg != SIZE_16K) || !chr || wram >= SIZE_8K || (nmt != Type::NMT_HORIZONTAL && nmt != Type::NMT_VERTICAL))
+ if (prg == SIZE_8K && chr == SIZE_8K)
+ {
+ name = "NAMCOT-3301";
+ id = Type::STD_NROM;
+ }
+ else if ((prg < SIZE_32K && prg != SIZE_16K) || !chr || wram >= SIZE_8K || (nmt != Type::NMT_HORIZONTAL && nmt != Type::NMT_VERTICAL))
{
name = "NROM (non-standard)";
id = Type::UNL_NROM;
@@ -1921,8 +1938,16 @@ namespace Nes
case 27:
- name = "UNL WORLDHERO";
- id = Type::UNL_WORLDHERO;
+ if (prg >= SIZE_128K)
+ {
+ name = "UNL WORLDHERO";
+ id = Type::UNL_WORLDHERO;
+ }
+ else
+ {
+ name = "UNL-CC-21";
+ id = Type::UNL_CC21;
+ }
break;
case 28:
@@ -2833,8 +2858,21 @@ namespace Nes
case 176:
- name = "XIAO ZHUAN YUAN";
- id = Type::UNL_XZY;
+ if (prg >= SIZE_2048K)
+ {
+ name = "BMC-SUPER24IN1SC03";
+ id = Type::BMC_SUPER_24IN1;
+ }
+ else if (prg > SIZE_128K)
+ {
+ name = "BMC-FK23C";
+ id = Type::BMC_FKC23C;
+ }
+ else
+ {
+ name = "XIAO ZHUAN YUAN";
+ id = Type::UNL_XZY;
+ }
break;
case 177:
@@ -3170,11 +3208,16 @@ namespace Nes
name = "BMC SUPER 42-IN-1";
id = Type::BMC_SUPER_42IN1;
}
- else
+ else if (prg == SIZE_2048K)
{
name = "BMC 76-IN-1";
id = Type::BMC_76IN1;
}
+ else
+ {
+ name = "BMC-GHOSTBUSTERS63IN1";
+ id = Type::BMC_CTC65;
+ }
break;
case 227:
@@ -3334,6 +3377,127 @@ namespace Nes
id = Type::BMC_110IN1;
break;
+ case 262:
+
+ name = "UNL-SHERO";
+ id = Type::UNL_SHERO;
+ break;
+
+ case 263:
+
+ name = "UNL-KOF97";
+ id = Type::UNL_KINGOFFIGHTERS97;
+ break;
+
+ case 265:
+
+ name = "BMC-T-262";
+ id = Type::BMC_T262;
+ break;
+
+ case 283:
+ if (prg > SIZE_256K)
+ {
+ name = "BMC-GS-2013";
+ id = Type::RCM_GS2013;
+ }
+ else
+ {
+ name = "BMC-GS-2004";
+ id = Type::RCM_GS2004;
+ }
+ break;
+
+ case 285:
+
+ name = "BMC-A65AS";
+ id = Type::BMC_A65AS;
+ break;
+
+ case 286:
+
+ name = "BMC-BS-5";
+ id = Type::BENSHENG_BS5;
+ break;
+
+ case 298:
+
+ name = "UNL-TF1201";
+ id = Type::UNL_TF1201;
+ break;
+
+ case 300:
+
+ name = "BMC-190IN1";
+ id = Type::BMC_GOLDEN_190IN1;
+ break;
+
+ case 301:
+
+ name = "BMC-8157";
+ id = Type::BMC_8157;
+ break;
+
+ case 305:
+
+ name = "UNL-KS7031";
+ id = Type::KAISER_KS7031;
+ break;
+
+ case 306:
+
+ name = "UNL-KS7016";
+ id = Type::KAISER_KS7016;
+ break;
+
+ case 307:
+
+ name = "UNL-KS7037";
+ id = Type::KAISER_KS7037;
+ break;
+
+ case 312:
+
+ name = "UNL-KS7013B";
+ id = Type::KAISER_KS7013B;
+ break;
+
+ case 314:
+
+ name = "BMC-64IN1NOREPEAT";
+ id = Type::BMC_Y2K_64IN1;
+ break;
+
+ case 329:
+
+ name = "UNL-EDU2000";
+ id = Type::UNL_EDU2000;
+ break;
+
+ case 332:
+
+ name = "BMC-WS";
+ id = Type::BMC_SUPER_40IN1;
+ break;
+
+ case 521:
+
+ name = "DREAMTECH01";
+ id = Type::DREAMTECH01;
+ break;
+
+ case 529:
+
+ name = "UNL-T-230";
+ id = Type::BTL_T230;
+ break;
+
+ case 530:
+
+ name = "UNL-AX5705";
+ id = Type::BTL_AX5705;
+ break;
+
default:
return false;
@@ -3537,7 +3701,7 @@ namespace Nes
case Type::CNE_DECATHLON : return new Cne::Decathlon(c);
case Type::CNE_PSB : return new Cne::Psb(c);
case Type::CONY_STD : return new Cony::Standard(c);
- case Type::DREAMTECH_01 : return new DreamTech::D01(c);
+ case Type::DREAMTECH01 : return new DreamTech::D01(c);
case Type::FUTUREMEDIA_STD : return new FutureMedia::Standard(c);
case Type::FUJIYA_STD : return new Fujiya::Standard(c);
case Type::FUKUTAKE_SBX : return new Fukutake::Sbx(c);
@@ -3602,9 +3766,12 @@ namespace Nes
case Type::JYCOMPANY_TYPE_B :
case Type::JYCOMPANY_TYPE_C : return new JyCompany::Standard(c);
case Type::KAISER_KS202 : return new Kaiser::Ks202(c);
+ case Type::KAISER_KS7013B : return new Kaiser::Ks7013b(c);
+ case Type::KAISER_KS7016 : return new Kaiser::Ks7016(c);
case Type::KAISER_KS7022 : return new Kaiser::Ks7022(c);
case Type::KAISER_KS7031 : return new Kaiser::Ks7031(c);
case Type::KAISER_KS7032 : return new Kaiser::Ks7032(c);
+ case Type::KAISER_KS7037 : return new Kaiser::Ks7037(c);
case Type::KAISER_KS7058 : return new Kaiser::Ks7058(c);
case Type::KASING_STD : return new Kasing::Standard(c);
case Type::KAY_H2288 : return new Kay::H2288(c);
@@ -3631,8 +3798,8 @@ namespace Nes
case Type::NAMCOT_163_1 :
case Type::NAMCOT_163_S_0 :
case Type::NAMCOT_163_S_1 : return new Namcot::N163(c);
- case Type::NAMCOT_340 :
case Type::NAMCOT_175 : return new Namcot::N175(c);
+ case Type::NAMCOT_340 : return new Namcot::N340(c);
case Type::NANJING_STD : return new Nanjing::Standard(c);
case Type::UNL_UXROM_M5 :
case Type::NIHON_UNROM_M5 : return new Nihon::UnRomM5(c);
@@ -3662,7 +3829,6 @@ namespace Nes
case Type::SACHEN_SA72008 : return new Sachen::Sa72008(c);
case Type::SACHEN_74_374A : return new Sachen::S74x374a(c);
case Type::SACHEN_74_374B : return new Sachen::S74x374b(c);
- case Type::SACHEN_STREETHEROES : return new Sachen::StreetHeroes(c);
case Type::SOMERITEAM_SL12 : return new SomeriTeam::Sl12(c);
case Type::SUBOR_TYPE0 : return new Subor::Type0(c);
case Type::SUBOR_TYPE1 : return new Subor::Type1(c);
@@ -3707,6 +3873,7 @@ namespace Nes
case Type::UNL_MORTALKOMBAT2 : return new Unlicensed::MortalKombat2(c);
case Type::UNL_N625092 : return new Unlicensed::N625092(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);
case Type::UNL_WORLDHERO : return new Unlicensed::WorldHero(c);
case Type::UNL_XZY : return new Unlicensed::Xzy(c);
diff --git a/source/core/board/NstBoard.hpp b/source/core/board/NstBoard.hpp
index 2e7ffea..bc455ee 100644
--- a/source/core/board/NstBoard.hpp
+++ b/source/core/board/NstBoard.hpp
@@ -94,7 +94,7 @@ namespace Nes
CRM_32
};
- template
+ template
struct MakeId
{
NST_COMPILE_ASSERT
@@ -258,7 +258,7 @@ namespace Nes
BANDAI_AEROBICSSTUDIO = MakeId< 3, 32, 32, 0, 0, CRM_0, NMT_X, 2 >::ID,
BANDAI_OEKAKIDS = MakeId< 96, 128, 0, 0, 0, CRM_32, NMT_1, 0 >::ID,
// Bensheng
- BENSHENG_BS5 = MakeId< NMPR, 128, 64, 0, 0, CRM_0, NMT_V, 2 >::ID,
+ BENSHENG_BS5 = MakeId< 286, 128, 64, 0, 0, CRM_0, NMT_V, 2 >::ID,
// Bootleg multicarts
BMC_110IN1 = MakeId< 255, 2048, 1024, 0, 0, CRM_0, NMT_V, 0 >::ID,
BMC_150IN1 = MakeId< 202, 128, 64, 0, 0, CRM_0, NMT_V, 0 >::ID,
@@ -273,16 +273,16 @@ namespace Nes
BMC_64IN1 = MakeId< 204, 128, 64, 0, 0, CRM_0, NMT_V, 0 >::ID,
BMC_72IN1 = MakeId< 225, 1024, 512, 0, 0, CRM_0, NMT_V, 0 >::ID,
BMC_76IN1 = MakeId< 226, 2048, 0, 0, 0, CRM_8, NMT_H, 0 >::ID,
- BMC_8157 = MakeId< NMPR, 512, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
+ BMC_8157 = MakeId< 301, 512, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
BMC_9999999IN1 = MakeId< 213, 128, 64, 0, 0, CRM_0, NMT_X, 0 >::ID,
- BMC_A65AS = MakeId< NMPR, 512, 0, 0, 0, CRM_8, NMT_V, 1 >::ID,
+ BMC_A65AS = MakeId< 285, 512, 0, 0, 0, CRM_8, NMT_V, 1 >::ID,
BMC_BALLGAMES_11IN1 = MakeId< 51, 512, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
- BMC_CTC65 = MakeId< NMPR, 2048, 0, 0, 0, CRM_8, NMT_H, 0 >::ID,
+ BMC_CTC65 = MakeId< 226, 2048, 0, 0, 0, CRM_8, NMT_H, 1 >::ID,
BMC_DRAGONBOLLPARTY = MakeId< 83, 1024, 1024, 8, 0, CRM_0, NMT_V, 0 >::ID,
BMC_FAMILY_4646B = MakeId< 134, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
- BMC_FKC23C = MakeId< NMPR, 1024, 1024, 0, 0, CRM_0, NMT_X, 0 >::ID,
+ BMC_FKC23C = MakeId< 176, 1024, 1024, 0, 0, CRM_0, NMT_X, 0 >::ID,
BMC_GAME_800IN1 = MakeId< 236, 512, 64, 0, 0, CRM_8, NMT_V, 0 >::ID,
- BMC_GOLDEN_190IN1 = MakeId< NMPR, 128, 64, 0, 0, CRM_0, NMT_V, 0 >::ID,
+ BMC_GOLDEN_190IN1 = MakeId< 300, 128, 64, 0, 0, CRM_0, NMT_V, 0 >::ID,
BMC_GOLDENGAME_150IN1 = MakeId< 235, 2048, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
BMC_GOLDENGAME_260IN1 = MakeId< 235, 4096, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
BMC_GKA = MakeId< 57, 128, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
@@ -294,9 +294,9 @@ namespace Nes
BMC_CH001 = MakeId< 63, 4096, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
BMC_POWERJOY_84IN1 = MakeId< 126, 2048, 1024, 0, 0, CRM_0, NMT_X, 0 >::ID,
BMC_RESETBASED_4IN1 = MakeId< 60, 64, 32, 0, 0, CRM_0, NMT_X, 0 >::ID,
- BMC_SUPER_24IN1 = MakeId< NMPR, 4096, 2048, 8, 0, CRM_8, NMT_X, 0 >::ID,
+ BMC_SUPER_24IN1 = MakeId< 176, 4096, 2048, 0, 0, CRM_8, NMT_X, 0 >::ID,
BMC_SUPER_22GAMES = MakeId< 233, 1024, 0, 0, 0, CRM_8, NMT_Z, 0 >::ID,
- BMC_SUPER_40IN1 = MakeId< NMPR, 128, 64, 0, 0, CRM_0, NMT_V, 1 >::ID,
+ BMC_SUPER_40IN1 = MakeId< 332, 128, 64, 0, 0, CRM_0, NMT_V, 1 >::ID,
BMC_SUPER_42IN1 = MakeId< 226, 1024, 0, 0, 0, CRM_8, NMT_H, 0 >::ID,
BMC_SUPER_700IN1 = MakeId< 62, 2048, 1024, 0, 0, CRM_0, NMT_V, 0 >::ID,
BMC_SUPERBIG_7IN1 = MakeId< 44, 1024, 1024, 0, 0, CRM_0, NMT_X, 0 >::ID,
@@ -304,15 +304,15 @@ namespace Nes
BMC_SUPERHIK_4IN1 = MakeId< 49, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
BMC_SUPERHIK_300IN1 = MakeId< 212, 128, 64, 0, 0, CRM_0, NMT_V, 0 >::ID,
BMC_SUPERVISION_16IN1 = MakeId< 53, 4096, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
- BMC_T262 = MakeId< NMPR, 1024, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
+ BMC_T262 = MakeId< 265, 1024, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
BMC_VRC4 = MakeId< 23, 512, 0, 8, 0, CRM_8, NMT_V, 0 >::ID,
BMC_VT5201 = MakeId< 60, 128, 64, 0, 0, CRM_0, NMT_V, 0 >::ID,
- BMC_Y2K_64IN1 = MakeId< NMPR, 1024, 512, 0, 0, CRM_0, NMT_V, 0 >::ID,
+ BMC_Y2K_64IN1 = MakeId< 314, 1024, 512, 0, 0, CRM_0, NMT_V, 0 >::ID,
// Bootlegs
BTL_2708 = MakeId< 103, 128, 0, 0, 16, CRM_8, NMT_V, 0 >::ID,
BTL_6035052 = MakeId< 238, 512, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
BTL_AISENSHINICOL = MakeId< 42, 128, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
- BTL_AX5705 = MakeId< NMPR, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
+ BTL_AX5705 = MakeId< 530, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
BTL_DRAGONNINJA = MakeId< 222, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
BTL_GENIUSMERIOBROS = MakeId< 55, 64, 8, 2, 0, CRM_0, NMT_X, 0 >::ID,
BTL_MARIOBABY = MakeId< 42, 128, 128, 0, 0, CRM_0, NMT_X, 0 >::ID,
@@ -323,7 +323,7 @@ namespace Nes
BTL_SMB2_C = MakeId< 43, 128, 8, 0, 0, CRM_0, NMT_X, 0 >::ID,
BTL_SMB3 = MakeId< 106, 256, 128, 8, 0, CRM_0, NMT_H, 0 >::ID,
BTL_SUPERBROS11 = MakeId< 196, 512, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
- BTL_T230 = MakeId< NMPR, 256, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
+ BTL_T230 = MakeId< 529, 256, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
BTL_TOBIDASEDAISAKUSEN = MakeId< 120, 128, 8, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Camerica
CAMERICA_BF9093 = MakeId< 71, 256, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
@@ -342,7 +342,7 @@ namespace Nes
// Cony
CONY_STD = MakeId< 83, 256, 512, 0, 0, CRM_0, NMT_V, 0 >::ID,
// Dreamtech
- DREAMTECH_01 = MakeId< NMPR, 256, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
+ DREAMTECH01 = MakeId< 521, 256, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
// Fujiya
FUJIYA_STD = MakeId< 170, 32, 8, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Fukutake
@@ -418,9 +418,12 @@ namespace Nes
JYCOMPANY_TYPE_C = MakeId< 211, 2048, 2048, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Kaiser
KAISER_KS202 = MakeId< 56, 256, 128, 8, 0, CRM_0, NMT_V, 0 >::ID,
+ KAISER_KS7013B = MakeId< 312, 128, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
+ KAISER_KS7016 = MakeId< 306, 128, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
KAISER_KS7022 = MakeId< 175, 256, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
- KAISER_KS7031 = MakeId< NMPR, 128, 0, 0, 16, CRM_8, NMT_V, 0 >::ID,
+ KAISER_KS7031 = MakeId< 305, 128, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
KAISER_KS7032 = MakeId< 142, 128, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
+ KAISER_KS7037 = MakeId< 307, 128, 0, 0, 8, CRM_8, NMT_X, 0 >::ID,
KAISER_KS7058 = MakeId< 171, 32, 32, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Kasing
KASING_STD = MakeId< 115, 512, 512, 0, 0, CRM_0, NMT_V, 0 >::ID,
@@ -454,8 +457,7 @@ namespace Nes
NAMCOT_163_S_0 = MakeId< 19, 512, 256, 0, 0, CRM_0, NMT_X, 1 >::ID,
NAMCOT_163_S_1 = MakeId< 19, 512, 256, 8, 0, CRM_0, NMT_X, 1 >::ID,
NAMCOT_175 = MakeId< 210, 512, 128, 8, 0, CRM_0, NMT_V, 0 >::ID,
- // FIXME: Setting NMT_4 is incorrect but makes things work
- NAMCOT_340 = MakeId< 210, 256, 256, 0, 0, CRM_0, NMT_4, 0 >::ID,
+ NAMCOT_340 = MakeId< 210, 256, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Nitra
NITRA_TDA = MakeId< 250, 512, 256, 0, 0, CRM_0, NMT_V, 0 >::ID,
// NTDEC
@@ -468,10 +470,10 @@ namespace Nes
// Nihon Bussan
NIHON_UNROM_M5 = MakeId< 180, 128, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
// Open Corp
- OPENCORP_DAOU306 = MakeId< 156, 256, 256, 8, 0, CRM_0, NMT_1, 0 >::ID,
+ OPENCORP_DAOU306 = MakeId< 156, 256, 512, 8, 0, CRM_0, NMT_1, 0 >::ID,
// RCM
- RCM_GS2004 = MakeId< NMPR, 512, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
- RCM_GS2013 = MakeId< NMPR, 512, 0, 0, 0, CRM_8, NMT_X, 1 >::ID,
+ RCM_GS2004 = MakeId< 283, 256, 0, 0, 0, CRM_8, NMT_X, 0 >::ID,
+ RCM_GS2013 = MakeId< 283, 512, 0, 0, 0, CRM_8, NMT_X, 1 >::ID,
RCM_GS2015 = MakeId< 216, 64, 64, 0, 0, CRM_0, NMT_X, 0 >::ID,
RCM_TETRISFAMILY = MakeId< 61, 512, 0, 0, 0, CRM_8, NMT_V, 0 >::ID,
// Rex Soft
@@ -492,7 +494,6 @@ namespace Nes
SACHEN_SA72008 = MakeId< 133, 64, 32, 0, 0, CRM_0, NMT_X, 0 >::ID,
SACHEN_74_374A = MakeId< 243, 64, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
SACHEN_74_374B = MakeId< 150, 64, 128, 0, 0, CRM_0, NMT_X, 0 >::ID,
- SACHEN_STREETHEROES = MakeId< NMPR, 512, 512, 0, 0, CRM_8, NMT_2, 0 >::ID,
// Someri Team
SOMERITEAM_SL12 = MakeId< 116, 256, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Subor
@@ -526,7 +527,6 @@ namespace Nes
TENGEN_800004 = MakeId< 206, 128, 64, 0, 0, CRM_0, NMT_2, 1 >::ID,
TENGEN_800008 = MakeId< 3, 64, 64, 0, 0, CRM_0, NMT_X, 0 >::ID,
TENGEN_800030 = MakeId< 206, 128, 64, 0, 0, CRM_0, NMT_X, 1 >::ID,
- //TENGEN_800032 = MakeId< 64, 128, 128, 0, 0, CRM_0, NMT_V, 0 >::ID,
TENGEN_800032 = MakeId< 64, 128, 256, 0, 0, CRM_0, NMT_V, 0 >::ID,
TENGEN_800037 = MakeId< 158, 128, 128, 0, 0, CRM_0, NMT_Z, 0 >::ID,
TENGEN_800042 = MakeId< 68, 128, 256, 0, 0, CRM_0, NMT_V, 1 >::ID,
@@ -539,14 +539,15 @@ namespace Nes
TXC_TW = MakeId< 189, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
// Unlicensed
UNL_A9746 = MakeId< 219, 128, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
- UNL_CC21 = MakeId< NMPR, 32, 16, 0, 0, CRM_0, NMT_Z, 0 >::ID,
- UNL_EDU2000 = MakeId< NMPR, 1024, 0, 32, 0, CRM_8, 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_KINGOFFIGHTERS96 = MakeId< 187, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
- UNL_KINGOFFIGHTERS97 = MakeId< NMPR, 512, 256, 0, 0, CRM_0, NMT_X, 1 >::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_N625092 = MakeId< 221, 1024, 8, 0, 0, CRM_0, NMT_V, 0 >::ID,
UNL_SUPERFIGHTER3 = MakeId< 197, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
- UNL_TF1201 = MakeId< NMPR, 256, 256, 0, 0, CRM_0, NMT_V, 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_WORLDHERO = MakeId< 27, 128, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
UNL_AXROM = MakeId< 7, 512, 8, 8, 0, CRM_0, NMT_Z, 0 >::ID,
UNL_BXROM = MakeId< 34, 4096, 8, 8, 0, CRM_8, NMT_X, 0 >::ID,
@@ -653,7 +654,7 @@ namespace Nes
Context(Cpu*,Apu*,Ppu*,Ram&,Ram&,const Ram&,Type::Nmt,bool,bool,Chips&);
bool DetectBoard(wcstring,dword);
- bool DetectBoard(byte,byte,dword,dword,bool);
+ bool DetectBoard(word,byte,dword,dword,bool);
cstring name;
Type type;
diff --git a/source/core/board/NstBoardCamerica.cpp b/source/core/board/NstBoardCamerica.cpp
index 16ae352..12fc511 100644
--- a/source/core/board/NstBoardCamerica.cpp
+++ b/source/core/board/NstBoardCamerica.cpp
@@ -40,6 +40,7 @@ namespace Nes
void Bf9093::SubReset(bool)
{
Map( 0xC000U, 0xFFFFU, PRG_SWAP_16K_0 );
+ Map( 0x8000U, 0xBFFFU, &Bf9093::Poke_C000 );
}
void Bf9096::SubReset(bool)
@@ -68,6 +69,11 @@ namespace Nes
#pragma optimize("", on)
#endif
+ NES_POKE_D(Bf9093,C000)
+ {
+ prg.SwapBank( data );
+ }
+
void Bf9096::SwapBasePrg(uint base)
{
prg.SwapBanks( base | (prg.GetBank() & 0x3), base | 0x3 );
diff --git a/source/core/board/NstBoardCamerica.hpp b/source/core/board/NstBoardCamerica.hpp
index c7d0963..5354809 100644
--- a/source/core/board/NstBoardCamerica.hpp
+++ b/source/core/board/NstBoardCamerica.hpp
@@ -47,6 +47,10 @@ namespace Nes
protected:
void SubReset(bool);
+
+ private:
+
+ NES_DECL_POKE( C000 );
};
class Bf9096 : public Board
diff --git a/source/core/board/NstBoardKaiser.cpp b/source/core/board/NstBoardKaiser.cpp
index 90f150b..91e553f 100644
--- a/source/core/board/NstBoardKaiser.cpp
+++ b/source/core/board/NstBoardKaiser.cpp
@@ -3,6 +3,7 @@
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
+// Copyright (C) 2021 Rupert Carmichael
//
// This file is part of Nestopia.
//
@@ -38,27 +39,6 @@ namespace Nes
#pragma optimize("s", on)
#endif
- void Ks7058::SubReset(bool)
- {
- for (uint i=0x000; i < 0x1000; i += 0x100)
- {
- Map( 0xF000+i, 0xF07F+i, CHR_SWAP_4K_0 );
- Map( 0xF080+i, 0xF0FF+i, CHR_SWAP_4K_1 );
- }
- }
-
- void Ks7022::SubReset(const bool hard)
- {
- reg = 0;
-
- if (hard)
- prg.SwapBanks( 0, 0 );
-
- Map( 0x8000, &Ks7022::Poke_8000 );
- Map( 0xA000, &Ks7022::Poke_A000 );
- Map( 0xFFFC, &Ks7022::Peek_FFFC );
- }
-
Ks202::Ks202(const Context& c)
: Board(c), irq(*c.cpu) {}
@@ -89,6 +69,36 @@ namespace Nes
irq.Reset( hard, hard ? false : irq.Connected() );
}
+ void Ks7013b::SubReset(const bool hard)
+ {
+ prg.SwapBank( 0x4000, 0x7 );
+
+ Map( 0x6000U, 0x7FFFU, &Ks7013b::Poke_6000 );
+ Map( 0x8000U, 0xFFFFU, &Ks7013b::Poke_8000 );
+ }
+
+ void Ks7016::SubReset(const bool hard)
+ {
+ reg = 8;
+
+ prg.SwapBank( 0x0000, 0x3 );
+
+ Map( 0x6000U, 0x7FFFU, &Ks7016::Peek_6000 );
+ Map( 0x8000U, 0xFFFFU, &Ks7016::Poke_8000 );
+ }
+
+ void Ks7022::SubReset(const bool hard)
+ {
+ reg = 0;
+
+ if (hard)
+ prg.SwapBanks( 0, 0 );
+
+ Map( 0x8000, &Ks7022::Poke_8000 );
+ Map( 0xA000, &Ks7022::Poke_A000 );
+ Map( 0xFFFC, &Ks7022::Peek_FFFC );
+ }
+
void Ks7031::SubReset(const bool hard)
{
Map( 0x6000U, 0xFFFEU, &Ks7031::Peek_6000 );
@@ -106,6 +116,62 @@ namespace Nes
Map( 0x6000U, 0x7FFFU, &Ks7032::Peek_6000 );
}
+ void Ks7037::SubReset(const bool hard)
+ {
+ if (hard)
+ {
+ regNum = 0;
+
+ for (uint i = 0; i < 8; ++i)
+ regs[i] = 0;
+ }
+
+ Map( 0x6000U, 0x6FFFU, &Ks7037::Peek_6000 );
+ Map( 0x6000U, 0x6FFFU, &Ks7037::Poke_6000 );
+
+ Map( 0x7000U, 0x7FFFU, &Ks7037::Peek_7000 );
+ Map( 0x8000U, 0x9FFFU, &Ks7037::Peek_8000 );
+
+ for (uint i = 0x0000; i < 0x2000; i += 0x2)
+ {
+ Map( 0x8000 + i, &Ks7037::Poke_8000 );
+ Map( 0x8001 + i, &Ks7037::Poke_8001 );
+ }
+
+ Map( 0xA000U, 0xAFFFU, &Ks7037::Peek_A000 );
+
+ Map( 0xB000U, 0xBFFFU, &Ks7037::Peek_B000 );
+ Map( 0xB000U, 0xBFFFU, &Ks7037::Poke_B000 );
+
+ Map( 0xC000U, 0xDFFFU, &Ks7037::Peek_C000 );
+ Map( 0xE000U, 0xEFFFU, &Ks7037::Peek_E000 );
+ }
+
+ void Ks7058::SubReset(bool)
+ {
+ for (uint i=0x000; i < 0x1000; i += 0x100)
+ {
+ Map( 0xF000+i, 0xF07F+i, CHR_SWAP_4K_0 );
+ Map( 0xF080+i, 0xF0FF+i, CHR_SWAP_4K_1 );
+ }
+ }
+
+ void Ks7016::SubLoad(State::Loader& state,const dword baseChunk)
+ {
+ NST_VERIFY( (baseChunk == AsciiId<'K','7','6'>::V) );
+
+ if (baseChunk == AsciiId<'K','7','6'>::V)
+ {
+ while (const dword chunk = state.Begin())
+ {
+ if (chunk == AsciiId<'R','E','G'>::V)
+ reg = state.Read8();
+
+ state.End();
+ }
+ }
+ }
+
void Ks7022::SubLoad(State::Loader& state,const dword baseChunk)
{
NST_VERIFY( (baseChunk == AsciiId<'K','7','2'>::V) );
@@ -178,9 +244,32 @@ namespace Nes
}
}
- void Ks7022::SubSave(State::Saver& state) const
+ void Ks7037::SubLoad(State::Loader& state,const dword baseChunk)
{
- state.Begin( AsciiId<'K','7','2'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write8( reg ).End().End();
+ NST_VERIFY( (baseChunk == AsciiId<'K','7','7'>::V) );
+
+ if (baseChunk == AsciiId<'K','7','7'>::V)
+ {
+ while (const dword chunk = state.Begin())
+ {
+ if (chunk == AsciiId<'R','E','G'>::V)
+ {
+ State::Loader::Data<9> data( state );
+
+ regs[0] = data[0];
+ regs[1] = data[1];
+ regs[2] = data[2];
+ regs[3] = data[3];
+ regs[4] = data[4];
+ regs[5] = data[5];
+ regs[6] = data[6];
+ regs[7] = data[7];
+ regNum = data[8];
+ }
+
+ state.End();
+ }
+ }
}
void Ks202::SubSave(State::Saver& state) const
@@ -201,6 +290,16 @@ namespace Nes
state.End();
}
+ void Ks7016::SubSave(State::Saver& state) const
+ {
+ state.Begin( AsciiId<'K','7','6'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write8( reg ).End().End();
+ }
+
+ void Ks7022::SubSave(State::Saver& state) const
+ {
+ state.Begin( AsciiId<'K','7','2'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write8( reg ).End().End();
+ }
+
void Ks7031::SubSave(State::Saver& state) const
{
state.Begin( AsciiId<'K','7','1'>::V );
@@ -209,34 +308,25 @@ namespace Nes
state.End();
}
+ void Ks7037::SubSave(State::Saver& state) const
+ {
+ state.Begin( AsciiId<'K','7','7'>::V );
+
+ const byte data[9] =
+ {
+ regs[0], regs[1], regs[2], regs[3],
+ regs[4], regs[5], regs[6], regs[7],
+ regNum
+ };
+
+ state.Begin( AsciiId<'R','E','G'>::V ).Write( data ).End();
+ state.End();
+ }
+
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("", on)
#endif
- NES_PEEK_A(Ks7032,6000)
- {
- return wrk[0][address - 0x6000];
- }
-
- NES_POKE_D(Ks7022,8000)
- {
- ppu.SetMirroring( (data & 0x4) ? Ppu::NMT_H : Ppu::NMT_V );
- }
-
- NES_POKE_D(Ks7022,A000)
- {
- reg = data & 0xF;
- }
-
- NES_PEEK(Ks7022,FFFC)
- {
- ppu.Update();
- chr.SwapBank( reg );
- prg.SwapBanks( reg, reg );
-
- return prg.Peek(0x7FFC);
- }
-
NES_POKE_D(Ks202,8000)
{
irq.Update();
@@ -326,6 +416,68 @@ namespace Nes
}
}
+ bool Ks202::Irq::Clock()
+ {
+ return (count++ == 0xFFFF) ? (count=latch, true) : false;
+ }
+
+ void Ks202::Sync(Event event,Input::Controllers* controllers)
+ {
+ if (event == EVENT_END_FRAME)
+ irq.VSync();
+
+ Board::Sync( event, controllers );
+ }
+
+ NES_POKE_D(Ks7013b,6000)
+ {
+ prg.SwapBank( 0x0000, data & 0x7 );
+ }
+
+ NES_POKE_D(Ks7013b,8000)
+ {
+ ppu.SetMirroring( (data & 0x1) ? Ppu::NMT_H : Ppu::NMT_V );
+ }
+
+ NES_PEEK_A(Ks7016,6000)
+ {
+ return *(prg.Source().Mem(reg * SIZE_8K) + (address & 0x1FFF));
+ }
+
+ NES_POKE_A(Ks7016,8000)
+ {
+ bool mode = (address & 0x30) == 0x30;
+
+ switch(address & 0xD943) {
+ case 0xD943:
+ reg = mode ? 0xB : (address >> 2) & 0xF;
+ break;
+
+ case 0xD903:
+ reg = mode ? 0x8 | ((address >> 2) & 0x3) : reg = 0xB;
+ break;
+ }
+ }
+
+ NES_POKE_D(Ks7022,8000)
+ {
+ ppu.SetMirroring( (data & 0x4) ? Ppu::NMT_H : Ppu::NMT_V );
+ }
+
+ NES_POKE_D(Ks7022,A000)
+ {
+ reg = data & 0xF;
+ }
+
+ NES_PEEK(Ks7022,FFFC)
+ {
+ ppu.Update();
+ chr.SwapBank( reg );
+ prg.SwapBanks( reg, reg );
+
+ return prg.Peek(0x7FFC);
+ }
+
NES_POKE_AD(Ks7031,8000)
{
regs[(address >> 11) & 0x03] = data;
@@ -345,17 +497,74 @@ namespace Nes
return prg[0][new_addr];
}
- bool Ks202::Irq::Clock()
+ NES_PEEK_A(Ks7032,6000)
{
- return (count++ == 0xFFFF) ? (count=latch, true) : false;
+ return wrk[0][address - 0x6000];
}
- void Ks202::Sync(Event event,Input::Controllers* controllers)
+ NES_PEEK_A(Ks7037,6000)
{
- if (event == EVENT_END_FRAME)
- irq.VSync();
+ NST_VERIFY( wrk.Readable(0) );
+ return wrk.Readable(0) ? wrk[0][address - 0x6000] : (address >> 8);
+ }
- Board::Sync( event, controllers );
+ NES_POKE_AD(Ks7037,6000)
+ {
+ NST_VERIFY( wrk.Writable(0) );
+
+ if (wrk.Writable(0))
+ wrk[0][address- 0x6000] = data;
+ }
+
+ NES_PEEK_A(Ks7037,7000)
+ {
+ return *(prg.Source().Mem(SIZE_4K * 15) + (address & 0xFFF));
+ }
+
+ NES_PEEK_A(Ks7037,8000)
+ {
+ return *(prg.Source().Mem(regs[6] * SIZE_8K) + (address & 0x1FFF));
+ }
+
+ NES_POKE_D(Ks7037,8000)
+ {
+ regNum = data & 0x7U;
+ byte mirror[4] = { regs[2], regs[4], regs[3], regs[5] };
+ ppu.SetMirroring(mirror);
+ }
+
+ NES_POKE_D(Ks7037,8001)
+ {
+ regs[regNum] = data;
+ }
+
+ NES_PEEK_A(Ks7037,A000)
+ {
+ return *(prg.Source().Mem(SIZE_4K * 28) + (address & 0xFFF));
+ }
+
+ NES_PEEK_A(Ks7037,B000)
+ {
+ NST_VERIFY( wrk.Readable(0) );
+ return wrk.Readable(0) ? wrk[0][address - 0xA000] : (address >> 8);
+ }
+
+ NES_POKE_AD(Ks7037,B000)
+ {
+ NST_VERIFY( wrk.Writable(0) );
+
+ if (wrk.Writable(0))
+ wrk[0][address- 0xA000] = data;
+ }
+
+ NES_PEEK_A(Ks7037,C000)
+ {
+ return *(prg.Source().Mem(regs[7] * SIZE_8K) + (address & 0x1FFF));
+ }
+
+ NES_PEEK_A(Ks7037,E000)
+ {
+ return *(prg.Source().Mem(SIZE_8K * 15) + (address & 0x1FFF));
}
}
}
diff --git a/source/core/board/NstBoardKaiser.hpp b/source/core/board/NstBoardKaiser.hpp
index 0d6dce9..bf6def2 100644
--- a/source/core/board/NstBoardKaiser.hpp
+++ b/source/core/board/NstBoardKaiser.hpp
@@ -3,6 +3,7 @@
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
+// Copyright (C) 2021 Rupert Carmichael
//
// This file is part of Nestopia.
//
@@ -37,18 +38,6 @@ namespace Nes
{
namespace Kaiser
{
- class Ks7058 : public Board
- {
- public:
-
- explicit Ks7058(const Context& c)
- : Board(c) {}
-
- private:
-
- void SubReset(bool);
- };
-
class Ks202 : public Board
{
public:
@@ -88,6 +77,59 @@ namespace Nes
Timer::M2 irq;
};
+ class Ks7013b : public Board
+ {
+ public:
+
+ explicit Ks7013b(const Context& c)
+ : Board(c) {}
+
+ private:
+
+ void SubReset(bool);
+
+ NES_DECL_POKE( 6000 );
+ NES_DECL_POKE( 8000 );
+ };
+
+ class Ks7016 : public Board
+ {
+ public:
+
+ explicit Ks7016(const Context& c)
+ : Board(c) {}
+
+ private:
+
+ void SubReset(bool);
+ void SubLoad(State::Loader&,dword);
+ void SubSave(State::Saver&) const;
+
+ NES_DECL_PEEK( 6000 );
+ NES_DECL_POKE( 8000 );
+
+ uint reg;
+ };
+
+ class Ks7022 : public Board
+ {
+ public:
+
+ explicit Ks7022(const Context& c)
+ : Board(c) {}
+
+ private:
+
+ void SubReset(bool);
+ void SubLoad(State::Loader&,dword);
+ void SubSave(State::Saver&) const;
+
+ NES_DECL_POKE( 8000 );
+ NES_DECL_POKE( A000 );
+ NES_DECL_PEEK( FFFC );
+
+ uint reg;
+ };
class Ks7031 : public Board
{
@@ -121,11 +163,10 @@ namespace Nes
NES_DECL_PEEK( 6000 );
};
- class Ks7022 : public Board
+ class Ks7037 : public Board
{
public:
-
- explicit Ks7022(const Context& c)
+ explicit Ks7037(const Context& c)
: Board(c) {}
private:
@@ -134,11 +175,32 @@ namespace Nes
void SubLoad(State::Loader&,dword);
void SubSave(State::Saver&) const;
- NES_DECL_POKE( 8000 );
- NES_DECL_POKE( A000 );
- NES_DECL_PEEK( FFFC );
+ byte regNum;
+ byte regs[8];
- uint reg;
+ NES_DECL_PEEK( 6000 );
+ NES_DECL_POKE( 6000 );
+ NES_DECL_PEEK( 7000 );
+ NES_DECL_PEEK( 8000 );
+ NES_DECL_POKE( 8000 );
+ NES_DECL_POKE( 8001 );
+ NES_DECL_PEEK( A000 );
+ NES_DECL_PEEK( B000 );
+ NES_DECL_POKE( B000 );
+ NES_DECL_PEEK( C000 );
+ NES_DECL_PEEK( E000 );
+ };
+
+ class Ks7058 : public Board
+ {
+ public:
+
+ explicit Ks7058(const Context& c)
+ : Board(c) {}
+
+ private:
+
+ void SubReset(bool);
};
}
}
diff --git a/source/core/board/NstBoardKonamiVrc2.cpp b/source/core/board/NstBoardKonamiVrc2.cpp
index 5b8f9d2..b61c00f 100644
--- a/source/core/board/NstBoardKonamiVrc2.cpp
+++ b/source/core/board/NstBoardKonamiVrc2.cpp
@@ -153,7 +153,12 @@ namespace Nes
void Vrc2::SwapChr(uint address,uint subBank) const
{
ppu.Update();
- chr.SwapBank( address, (chr.GetBank(address) & 0xF0U >> OFFSET) | ((subBank >> chrShift & 0xF) << OFFSET) );
+
+ chr.SwapBank( address, chrShift ? OFFSET ?
+ (chr.GetBank(address) & 0x07U) | ((subBank & 0xFU) << 3) :
+ (chr.GetBank(address) & 0xF8U) | ((subBank >> 1) & 0x7U) :
+ (chr.GetBank(address) & 0xF0U >> OFFSET) | ((subBank & 0xFU) << OFFSET)
+ );
}
NES_POKE_D(Vrc2,B000) { SwapChr<0>( 0x0000, data ); }
diff --git a/source/core/board/NstBoardMmc1.cpp b/source/core/board/NstBoardMmc1.cpp
index 5438ac5..a4ef082 100644
--- a/source/core/board/NstBoardMmc1.cpp
+++ b/source/core/board/NstBoardMmc1.cpp
@@ -25,6 +25,7 @@
#include "../NstLog.hpp"
#include "NstBoard.hpp"
#include "NstBoardMmc1.hpp"
+#include "../NstFile.hpp"
namespace Nes
{
@@ -119,6 +120,20 @@ namespace Nes
#pragma optimize("", on)
#endif
+ void Mmc1::Save(File& file) const
+ {
+ uint offset = (board.GetWram() == SIZE_16K) ? SIZE_8K : 0; // SOROM
+ if (board.HasBattery() && board.GetSavableWram())
+ file.Save( File::BATTERY, wrk.Source().Mem(offset), board.GetSavableWram() );
+ }
+
+ void Mmc1::Load(File& file)
+ {
+ uint offset = (board.GetWram() == SIZE_16K) ? SIZE_8K : 0; // SOROM
+ if (board.HasBattery() && board.GetSavableWram())
+ file.Load( File::BATTERY, wrk.Source().Mem(offset), board.GetSavableWram() );
+ }
+
void Mmc1::UpdatePrg()
{
prg.SwapBanks
diff --git a/source/core/board/NstBoardMmc1.hpp b/source/core/board/NstBoardMmc1.hpp
index 962e966..ffa9e0c 100644
--- a/source/core/board/NstBoardMmc1.hpp
+++ b/source/core/board/NstBoardMmc1.hpp
@@ -82,6 +82,9 @@ namespace Nes
private:
+ void Save(File&) const;
+ void Load(File&);
+
void ResetRegisters();
virtual void NST_FASTCALL UpdateRegisters(uint);
diff --git a/source/core/board/NstBoardMmc5.cpp b/source/core/board/NstBoardMmc5.cpp
index 714d6af..474468c 100644
--- a/source/core/board/NstBoardMmc5.cpp
+++ b/source/core/board/NstBoardMmc5.cpp
@@ -655,10 +655,9 @@ namespace Nes
NES_HOOK(Mmc5,HActive)
{
- banks.fetchMode = Banks::FETCH_MODE_BG;
-
if (ppu.IsEnabled())
{
+ banks.fetchMode = Banks::FETCH_MODE_BG;
spliter.x = 0x1F;
if (ppu.GetPixelCycles() != ~0U)
diff --git a/source/core/board/NstBoardNamcot.hpp b/source/core/board/NstBoardNamcot.hpp
index 89bdd4e..44b6361 100644
--- a/source/core/board/NstBoardNamcot.hpp
+++ b/source/core/board/NstBoardNamcot.hpp
@@ -31,6 +31,7 @@
#include "NstBoardNamcot163.hpp"
#include "NstBoardNamcot175.hpp"
+#include "NstBoardNamcot340.hpp"
#include "NstBoardNamcot34xx.hpp"
namespace Nes
diff --git a/source/core/board/NstBoardNamcot175.cpp b/source/core/board/NstBoardNamcot175.cpp
index f8f6e40..639b14c 100644
--- a/source/core/board/NstBoardNamcot175.cpp
+++ b/source/core/board/NstBoardNamcot175.cpp
@@ -3,7 +3,7 @@
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
-// Copyright (C) 2014 R. Danbrook
+// Copyright (C) 2021 Rupert Carmichael
//
// This file is part of Nestopia.
//
@@ -23,10 +23,7 @@
//
////////////////////////////////////////////////////////////////////////////////////////
-#include
#include "NstBoard.hpp"
-#include "../NstTimer.hpp"
-#include "../NstFile.hpp"
#include "NstBoardNamcot175.hpp"
namespace Nes
@@ -43,16 +40,14 @@ namespace Nes
N175::N175(const Context& c)
:
- Board (c),
- irq (*c.cpu)
+ Board (c)
{
}
void N175::SubReset(const bool hard)
{
-
- irq.Reset( hard, hard || irq.Connected() );
-
+ Map( 0x6000U, 0x7FFFU, &N175::Peek_6000 );
+ Map( 0x6000U, 0x7FFFU, &N175::Poke_6000 );
Map( 0x8000U, 0x87FFU, CHR_SWAP_1K_0 );
Map( 0x8800U, 0x8FFFU, CHR_SWAP_1K_1 );
Map( 0x9000U, 0x97FFU, CHR_SWAP_1K_2 );
@@ -61,157 +56,35 @@ namespace Nes
Map( 0xA800U, 0xAFFFU, CHR_SWAP_1K_5 );
Map( 0xB000U, 0xB7FFU, CHR_SWAP_1K_6 );
Map( 0xB800U, 0xBFFFU, CHR_SWAP_1K_7 );
+ Map( 0xC000U, 0xC7FFU, &N175::Poke_C000 );
Map( 0xE000U, 0xE7FFU, PRG_SWAP_8K_0 );
Map( 0xE800U, 0xEFFFU, PRG_SWAP_8K_1 );
Map( 0xF000U, 0xF7FFU, PRG_SWAP_8K_2 );
}
- void N175::Irq::Reset(const bool hard)
- {
- if (hard)
- count = 0;
- }
-
- void N175::Load(File& file)
- {
- if (board.HasBattery())
- {
- const File::LoadBlock block[] =
- {
- { wrk.Source().Mem(), board.GetWram() }
- };
-
- file.Load( File::BATTERY, block );
- }
- else
- {
- Board::Load( file );
- }
- }
-
- void N175::Save(File& file) const
- {
- if (board.HasBattery())
- {
- const File::SaveBlock block[] =
- {
- { wrk.Source().Mem(), board.GetWram() }
- };
-
- file.Save( File::BATTERY, block );
- }
- else
- {
- Board::Save( file );
- }
- }
-
- void N175::SubLoad(State::Loader& state,const dword baseChunk)
- {
- NST_VERIFY( baseChunk == (AsciiId<'N','6','3'>::V) );
-
- if (baseChunk == AsciiId<'N','6','3'>::V)
- {
- while (const dword chunk = state.Begin())
- {
- switch (chunk)
- {
- case AsciiId<'I','R','Q'>::V:
- {
- State::Loader::Data<3> data( state );
- irq.unit.count = data[1] | (data[2] << 8 & 0x7F00) | (data[0] << 15 & 0x8000);
- break;
- }
- }
-
- state.End();
- }
- }
- }
-
- void N175::SubSave(State::Saver& state) const
- {
- state.Begin( AsciiId<'N','6','3'>::V );
-
- const byte data[3] =
- {
- irq.unit.count >> 15,
- irq.unit.count >> 0 & 0xFF,
- irq.unit.count >> 8 & 0x7F
- };
-
- state.Begin( AsciiId<'I','R','Q'>::V ).Write( data ).End();
-
- state.End();
- }
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("", on)
#endif
- bool N175::Irq::Clock()
+ NES_PEEK_A(N175,6000)
{
- return (count - 0x8000 < 0x7FFF) && (++count == 0xFFFF);
+ NST_VERIFY( wrk.Readable(0) );
+ return wrk.Readable(0) ? wrk[0][address & 0x7FFU] : (address >> 8);
}
- NES_PEEK(N175,5000)
+ NES_POKE_AD(N175,6000)
{
- irq.Update();
- return irq.unit.count & 0xFF;
- }
+ NST_VERIFY( wrk.Writable(0) );
- NES_POKE_D(N175,5000)
- {
- irq.Update();
- irq.unit.count = (irq.unit.count & 0xFF00) | data;
- irq.ClearIRQ();
- }
-
- NES_PEEK(N175,5800)
- {
- irq.Update();
- return irq.unit.count >> 8;
- }
-
- NES_POKE_D(N175,5800)
- {
- irq.Update();
- irq.unit.count = (irq.unit.count & 0x00FF) | (data << 8);
- irq.ClearIRQ();
- }
-
- void N175::SwapNmt(const uint address,const uint data) const
- {
- ppu.Update();
- nmt.Source( data < 0xE0 ).SwapBank( address, data );
+ if (wrk.Writable(0))
+ wrk[0][address & 0x7FFU] = data;
}
NES_POKE_D(N175,C000)
{
- SwapNmt( 0x0000, data );
- }
-
- NES_POKE_D(N175,C800)
- {
- SwapNmt( 0x0400, data );
- }
-
- NES_POKE_D(N175,D000)
- {
- SwapNmt( 0x0800, data );
- }
-
- NES_POKE_D(N175,D800)
- {
- SwapNmt( 0x0C00, data );
- }
-
- void N175::Sync(Event event,Input::Controllers* controllers)
- {
- if (event == EVENT_END_FRAME)
- irq.VSync();
-
- Board::Sync( event, controllers );
+ bool enable = data & 0x1;
+ wrk.Source().SetSecurity(enable, enable);
}
}
}
diff --git a/source/core/board/NstBoardNamcot175.hpp b/source/core/board/NstBoardNamcot175.hpp
index 41d9b0c..59052c1 100644
--- a/source/core/board/NstBoardNamcot175.hpp
+++ b/source/core/board/NstBoardNamcot175.hpp
@@ -3,7 +3,7 @@
// Nestopia - NES/Famicom emulator written in C++
//
// Copyright (C) 2003-2008 Martin Freij
-// Copyright (C) 2014 R. Danbrook
+// Copyright (C) 2021 Rupert Carmichael
//
// This file is part of Nestopia.
//
@@ -47,35 +47,10 @@ namespace Nes
private:
void SubReset(bool);
- void SubSave(State::Saver&) const;
- void SubLoad(State::Loader&,dword);
- void Load(File&);
- void Save(File&) const;
- void Sync(Event,Input::Controllers*);
- void SwapChr(uint,uint,uint) const;
- void SwapNmt(uint,uint) const;
- struct Irq
- {
- void Reset(bool);
- bool Clock();
-
- uint count;
- };
-
- NES_DECL_PEEK( 4800 );
- NES_DECL_POKE( 4800 );
- NES_DECL_PEEK( 5000 );
- NES_DECL_POKE( 5000 );
- NES_DECL_PEEK( 5800 );
- NES_DECL_POKE( 5800 );
+ NES_DECL_PEEK( 6000 );
+ NES_DECL_POKE( 6000 );
NES_DECL_POKE( C000 );
- NES_DECL_POKE( C800 );
- NES_DECL_POKE( D000 );
- NES_DECL_POKE( D800 );
- NES_DECL_POKE( F800 );
-
- Timer::M2 irq;
};
}
}
diff --git a/source/core/board/NstBoardNamcot340.cpp b/source/core/board/NstBoardNamcot340.cpp
new file mode 100644
index 0000000..073266b
--- /dev/null
+++ b/source/core/board/NstBoardNamcot340.cpp
@@ -0,0 +1,89 @@
+////////////////////////////////////////////////////////////////////////////////////////
+//
+// Nestopia - NES/Famicom emulator written in C++
+//
+// Copyright (C) 2003-2008 Martin Freij
+// Copyright (C) 2021 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 "NstBoardNamcot340.hpp"
+
+namespace Nes
+{
+ namespace Core
+ {
+ namespace Boards
+ {
+ namespace Namcot
+ {
+ #ifdef NST_MSVC_OPTIMIZE
+ #pragma optimize("s", on)
+ #endif
+
+ N340::N340(const Context& c)
+ :
+ Board (c)
+ {
+ }
+
+ void N340::SubReset(const bool hard)
+ {
+ Map( 0x8000U, 0x87FFU, CHR_SWAP_1K_0 );
+ Map( 0x8800U, 0x8FFFU, CHR_SWAP_1K_1 );
+ Map( 0x9000U, 0x97FFU, CHR_SWAP_1K_2 );
+ Map( 0x9800U, 0x9FFFU, CHR_SWAP_1K_3 );
+ Map( 0xA000U, 0xA7FFU, CHR_SWAP_1K_4 );
+ Map( 0xA800U, 0xAFFFU, CHR_SWAP_1K_5 );
+ Map( 0xB000U, 0xB7FFU, CHR_SWAP_1K_6 );
+ Map( 0xB800U, 0xBFFFU, CHR_SWAP_1K_7 );
+ Map( 0xE000U, 0xE7FFU, &N340::Poke_E000 );
+ Map( 0xE800U, 0xEFFFU, PRG_SWAP_8K_1 );
+ Map( 0xF000U, 0xF7FFU, PRG_SWAP_8K_2 );
+ }
+
+ #ifdef NST_MSVC_OPTIMIZE
+ #pragma optimize("", on)
+ #endif
+
+ NES_POKE_D(N340,E000)
+ {
+ prg.SwapBank( 0, data & 0x3FU );
+
+ switch ((data >> 6) & 0x3U)
+ {
+ case 0x0U: // One-screen A
+ ppu.SetMirroring( Ppu::NMT_0 );
+ break;
+ case 0x1U: // Vertical
+ ppu.SetMirroring( Ppu::NMT_V );
+ break;
+ case 0x2U: // One-screen B
+ ppu.SetMirroring( Ppu::NMT_1 );
+ break;
+ case 0x3U: // Horizontal
+ ppu.SetMirroring( Ppu::NMT_H );
+ break;
+ }
+ }
+ }
+ }
+ }
+}
diff --git a/source/core/board/NstBoardNamcot340.hpp b/source/core/board/NstBoardNamcot340.hpp
new file mode 100644
index 0000000..e079a13
--- /dev/null
+++ b/source/core/board/NstBoardNamcot340.hpp
@@ -0,0 +1,58 @@
+////////////////////////////////////////////////////////////////////////////////////////
+//
+// Nestopia - NES/Famicom emulator written in C++
+//
+// Copyright (C) 2003-2008 Martin Freij
+// Copyright (C) 2021 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_NAMCOT_340_H
+#define NST_BOARD_NAMCOT_340_H
+
+#ifdef NST_PRAGMA_ONCE
+#pragma once
+#endif
+
+namespace Nes
+{
+ namespace Core
+ {
+ namespace Boards
+ {
+ namespace Namcot
+ {
+ class N340 : public Board
+ {
+ public:
+
+ explicit N340(const Context&);
+
+ private:
+
+ void SubReset(bool);
+
+ NES_DECL_POKE( E000 );
+ };
+ }
+ }
+ }
+}
+
+#endif
diff --git a/source/core/board/NstBoardOpenCorp.cpp b/source/core/board/NstBoardOpenCorp.cpp
index 1f38c24..2416878 100644
--- a/source/core/board/NstBoardOpenCorp.cpp
+++ b/source/core/board/NstBoardOpenCorp.cpp
@@ -22,6 +22,8 @@
//
////////////////////////////////////////////////////////////////////////////////////////
+// Reference: https://github.com/TASVideos/fceux/blob/master/src/boards/156.cpp
+
#include "NstBoard.hpp"
#include "NstBoardOpenCorp.hpp"
@@ -37,17 +39,139 @@ namespace Nes
#pragma optimize("s", on)
#endif
+ void Daou306::RemapChr()
+ {
+ chr.SwapBank( 0x0000, (chrHigh[0] << 8) | chrLow[0] );
+ chr.SwapBank( 0x0400, (chrHigh[1] << 8) | chrLow[1] );
+ chr.SwapBank( 0x0800, (chrHigh[2] << 8) | chrLow[2] );
+ chr.SwapBank( 0x0C00, (chrHigh[3] << 8) | chrLow[3] );
+ chr.SwapBank( 0x1000, (chrHigh[4] << 8) | chrLow[4] );
+ chr.SwapBank( 0x1400, (chrHigh[5] << 8) | chrLow[5] );
+ chr.SwapBank( 0x1800, (chrHigh[6] << 8) | chrLow[6] );
+ chr.SwapBank( 0x1C00, (chrHigh[7] << 8) | chrLow[7] );
+
+ if (mirrorUsed) {
+ ppu.SetMirroring( mirror ^ 0x1 ? Ppu::NMT_V : Ppu::NMT_H );
+ }
+ else
+ {
+ ppu.SetMirroring( Ppu::NMT_0 );
+ }
+ }
+
void Daou306::SubReset(bool)
{
- Map( 0xC000U, CHR_SWAP_1K_0 );
- Map( 0xC001U, CHR_SWAP_1K_1 );
- Map( 0xC002U, CHR_SWAP_1K_2 );
- Map( 0xC003U, CHR_SWAP_1K_3 );
- Map( 0xC008U, CHR_SWAP_1K_4 );
- Map( 0xC009U, CHR_SWAP_1K_5 );
- Map( 0xC00AU, CHR_SWAP_1K_6 );
- Map( 0xC00BU, CHR_SWAP_1K_7 );
+ for (uint i = 0; i < 8; i++)
+ {
+ chrLow[i] = chrHigh[i] = 0;
+ }
+
+ Map( 0xC000U, 0xC00FU, &Daou306::Poke_C000 );
Map( 0xC010U, PRG_SWAP_16K_0 );
+ Map( 0xC014U, &Daou306::Poke_C014 );
+ }
+
+ NES_POKE_AD(Daou306,C000)
+ {
+ switch (address)
+ {
+ case 0xC000:
+ case 0xC001:
+ case 0xC002:
+ case 0xC003:
+ chrLow[address & 0x03] = data;
+ break;
+ case 0xC004:
+ case 0xC005:
+ case 0xC006:
+ case 0xC007:
+ chrHigh[address & 0x03] = data;
+ break;
+ case 0xC008:
+ case 0xC009:
+ case 0xC00A:
+ case 0xC00B:
+ chrLow[4 + (address & 0x03)] = data;
+ break;
+ case 0xC00C:
+ case 0xC00D:
+ case 0xC00E:
+ case 0xC00F:
+ chrHigh[4 + (address & 0x03)] = data;
+ break;
+ }
+ RemapChr();
+ }
+
+ NES_POKE_D(Daou306,C014)
+ {
+ mirror = data;
+ mirrorUsed = 1;
+ }
+
+ void Daou306::SubLoad(State::Loader& state,const dword baseChunk)
+ {
+ NST_VERIFY( baseChunk == (AsciiId<'O','P','C'>::V) );
+
+ if (baseChunk == AsciiId<'O','P','C'>::V)
+ {
+ state.Begin();
+
+ State::Loader::Data<18> data( state );
+ chrLow[0] = data[0];
+ chrLow[1] = data[1];
+ chrLow[2] = data[2];
+ chrLow[3] = data[3];
+ chrLow[4] = data[4];
+ chrLow[5] = data[5];
+ chrLow[6] = data[6];
+ chrLow[7] = data[7];
+ chrHigh[0] = data[8];
+ chrHigh[1] = data[9];
+ chrHigh[2] = data[10];
+ chrHigh[3] = data[11];
+ chrHigh[4] = data[12];
+ chrHigh[5] = data[13];
+ chrHigh[6] = data[14];
+ chrHigh[7] = data[15];
+ mirror = data[16];
+ mirrorUsed = data[17];
+
+ state.End();
+
+ RemapChr();
+ }
+ }
+
+ void Daou306::SubSave(State::Saver& state) const
+ {
+ state.Begin( AsciiId<'O','P','C'>::V );
+
+ const byte data[18] =
+ {
+ chrLow[0],
+ chrLow[1],
+ chrLow[2],
+ chrLow[3],
+ chrLow[4],
+ chrLow[5],
+ chrLow[6],
+ chrLow[7],
+ chrHigh[0],
+ chrHigh[1],
+ chrHigh[2],
+ chrHigh[3],
+ chrHigh[4],
+ chrHigh[5],
+ chrHigh[6],
+ chrHigh[7],
+ mirror,
+ mirrorUsed,
+ };
+
+ state.Begin( AsciiId<'C','H','R'>::V ).Write( data ).End();
+
+ state.End();
}
#ifdef NST_MSVC_OPTIMIZE
diff --git a/source/core/board/NstBoardOpenCorp.hpp b/source/core/board/NstBoardOpenCorp.hpp
index 5c276fa..03e128c 100644
--- a/source/core/board/NstBoardOpenCorp.hpp
+++ b/source/core/board/NstBoardOpenCorp.hpp
@@ -46,7 +46,18 @@ namespace Nes
private:
+ byte chrLow[8];
+ byte chrHigh[8];
+ byte mirror;
+ byte mirrorUsed;
+
+ void RemapChr();
void SubReset(bool);
+ void SubSave(State::Saver&) const;
+ void SubLoad(State::Loader&,dword);
+
+ NES_DECL_POKE( C000 );
+ NES_DECL_POKE( C014 );
};
}
}
diff --git a/source/core/board/NstBoardSunsoft5b.cpp b/source/core/board/NstBoardSunsoft5b.cpp
index a91d840..94fa732 100644
--- a/source/core/board/NstBoardSunsoft5b.cpp
+++ b/source/core/board/NstBoardSunsoft5b.cpp
@@ -322,7 +322,7 @@ namespace Nes
ctrl = data[0] >> 1 & 0x1F;
length = data[1] | (data[2] << 8 & 0xF00);
volume = levels[(ctrl & 0xF) ? (ctrl & 0xF) * 2 + 1 : 0];
- dc = (status & 0x1) ? ~0UL : 0UL;
+ dc = (status & 0x1) ? ~dword(0) : dword(0);
UpdateSettings( fixed );
}
diff --git a/source/core/board/NstBoardTengenRambo1.cpp b/source/core/board/NstBoardTengenRambo1.cpp
index 12c8453..7ee4708 100644
--- a/source/core/board/NstBoardTengenRambo1.cpp
+++ b/source/core/board/NstBoardTengenRambo1.cpp
@@ -54,6 +54,7 @@ namespace Nes
if (hard)
{
count = 0;
+ cycles = 0;
reload = false;
latch = 0;
enabled = false;
@@ -121,14 +122,16 @@ namespace Nes
case AsciiId<'I','R','Q'>::V:
{
- State::Loader::Data<3> data( state );
+ State::Loader::Data<4> data( state );
irq.unit.enabled = data[0] & 0x1;
+ irq.unit.mode = data[0] & 0x2 ? 1 : 0;
irq.a12.Connect( data[0] & 0x2 );
irq.m2.Connect( data[0] & 0x2 );
irq.unit.reload = data[0] & 0x4;
irq.unit.latch = data[1];
irq.unit.count = data[2];
+ irq.unit.cycles = data[3];
break;
}
@@ -164,13 +167,14 @@ namespace Nes
}
{
- const byte data[3] =
+ const byte data[4] =
{
(irq.unit.enabled ? 0x1U : 0x0U) |
(irq.m2.Connected() ? 0x2U : 0x0U) |
(irq.unit.reload ? 0x4U : 0x0U),
irq.unit.latch,
- irq.unit.count & 0xFF
+ irq.unit.count & 0xFF,
+ irq.unit.cycles,
};
state.Begin( AsciiId<'I','R','Q'>::V ).Write( data ).End();
@@ -185,47 +189,39 @@ namespace Nes
bool Rambo1::Irq::Unit::Clock()
{
- /*if (!reload)
+ cycles++;
+
+ if (latch == 1)
{
- if (count)
- {
- return !--count && enabled;
- }
- else
- {
- count = latch;
- return false;
- }
+ count = 0;
+ }
+ else if (reload)
+ {
+ reload = false;
+ count = latch | (latch ? 1 : 0);
+
+ if (mode)
+ count |= 2;
+
+ if (!latch && cycles > A12_FILTER)
+ count = 1;
+ else if (latch && (cycles > (A12_FILTER * 3)))
+ count++;
+
+ cycles = 0;
+ }
+ else if (!count)
+ {
+ count = latch;
+ if (cycles > A12_FILTER)
+ cycles = 0;
}
else
{
- reload = false;
- count = latch + 1;
- return false;
- }*/
-
- // From dragon2snow
- if (reload) {
- if (latch < 1) {
- count = latch + 1;
- }
- else {
- count = latch + 2;
- }
- reload = false;
+ count--;
}
- else if (!count) {
- count = latch + 1;
- }
-
- count--;
-
- if (!count && enabled) {
- /* wait one M2 cycle, then trigger IRQ */
- return true;
- }
-
- return false;
+
+ return (!count && enabled);
}
void Rambo1::Irq::Update()
@@ -320,6 +316,7 @@ namespace Nes
{
irq.Update();
irq.unit.latch = data;
+ irq.unit.mode = irq.m2.Connected();
}
NES_POKE_D(Rambo1,C001)
diff --git a/source/core/board/NstBoardTengenRambo1.hpp b/source/core/board/NstBoardTengenRambo1.hpp
index 1f8593f..9bd64a2 100644
--- a/source/core/board/NstBoardTengenRambo1.hpp
+++ b/source/core/board/NstBoardTengenRambo1.hpp
@@ -95,9 +95,11 @@ namespace Nes
bool Clock();
uint count;
+ uint cycles;
uint latch;
ibool reload;
ibool enabled;
+ ibool mode;
};
typedef Timer::A12 A12;
diff --git a/source/core/board/NstBoardUnlCc21.cpp b/source/core/board/NstBoardUnlCc21.cpp
index 0421c7c..98b268e 100644
--- a/source/core/board/NstBoardUnlCc21.cpp
+++ b/source/core/board/NstBoardUnlCc21.cpp
@@ -49,7 +49,8 @@ namespace Nes
NES_POKE_A(Cc21,8000)
{
ppu.SetMirroring( (address & 0x2) ? Ppu::NMT_1 : Ppu::NMT_0 );
- chr.SwapBank( address );
+ chr.SwapBank( address );
+ chr.SwapBank( address );
}
}
}
diff --git a/source/core/board/NstBoardUnlKingOfFighters97.cpp b/source/core/board/NstBoardUnlKingOfFighters97.cpp
index 9c117b0..b84048c 100644
--- a/source/core/board/NstBoardUnlKingOfFighters97.cpp
+++ b/source/core/board/NstBoardUnlKingOfFighters97.cpp
@@ -51,7 +51,8 @@ namespace Nes
}
Map( 0x9000U, &KingOfFighters97::Poke_8001 );
- Map( 0xA000U, &KingOfFighters97::Poke_8000 );
+ Map( 0xA000U, &KingOfFighters97::Poke_A000 );
+ Map( 0xB000U, &KingOfFighters97::Poke_A001 );
Map( 0xD000U, &KingOfFighters97::Poke_C001 );
for (uint i=0x0000; i < 0x1000; i += 0x2)
@@ -89,6 +90,16 @@ namespace Nes
Mmc3::NES_DO_POKE(8001,0x8001,Unscramble(data));
}
+ NES_POKE_D(KingOfFighters97,A000)
+ {
+ ppu.SetMirroring( (data & 0x02) ? Ppu::NMT_H : Ppu::NMT_V );
+ }
+
+ NES_POKE_D(KingOfFighters97,A001)
+ {
+ Mmc3::NES_DO_POKE(A001,0xA001,Unscramble(data));
+ }
+
NES_POKE_D(KingOfFighters97,C000)
{
Mmc3::NES_DO_POKE(C000,0xC000,Unscramble(data));
diff --git a/source/core/board/NstBoardUnlKingOfFighters97.hpp b/source/core/board/NstBoardUnlKingOfFighters97.hpp
index 339d070..78e58f9 100644
--- a/source/core/board/NstBoardUnlKingOfFighters97.hpp
+++ b/source/core/board/NstBoardUnlKingOfFighters97.hpp
@@ -52,6 +52,8 @@ namespace Nes
NES_DECL_POKE( 8000 );
NES_DECL_POKE( 8001 );
+ NES_DECL_POKE( A000 );
+ NES_DECL_POKE( A001 );
NES_DECL_POKE( C000 );
NES_DECL_POKE( C001 );
NES_DECL_POKE( E000 );