Merge upstream core at tag 1.51.1

This commit is contained in:
rdanbrook 2021-08-25 22:20:30 -04:00
parent 1f407e3d0b
commit fecad6d8a5
15 changed files with 477 additions and 50 deletions

View file

@ -662,6 +662,8 @@ nestopia_SOURCES = \
source/core/board/NstBoardInlNsf.hpp \
source/core/board/NstBoardAction53.cpp \
source/core/board/NstBoardAction53.hpp \
source/core/board/NstBoardWaixingFs304.cpp \
source/core/board/NstBoardWaixingFs304.hpp \
source/core/NstPins.hpp \
source/core/NstNsf.hpp \
source/core/NstTrackerRewinder.hpp \

View file

@ -27023,4 +27023,41 @@
</board>
</cartridge>
</game>
<game>
<cartridge system="Famicom" dump="ok" crc="8589652D" sha1="0CC7ED7F5D7EE0959EE3724C3AF06EF8DF397C59">
<board type="NANJING" mapper="163">
<prg size="2048k" />
<wram size="8k" battery="1" />
<pad h="0" v="1" />
</board>
</cartridge>
</game>
<game>
<cartridge system="NES-NTSC" dump="ok" crc="F312D1DE" sha1="35C157A921156E47FD3F6573D150F54108D0EDFC">
<board type="NES-TXROM" mapper="4">
<prg size="16k" />
<chip type="MMC3A" />
</board>
</cartridge>
</game>
<game>
<cartridge system="NES-NTSC" dump="ok" crc="A512BDF6" sha1="F794FDA12D34E611D58E652319ED583AE61B81E0">
<board type="NES-HKROM" mapper="4">
<prg size="32k" />
<chr size="8k" />
<pad h="0" v="1" />
<chip type="MMC6B" battery="0" />
</board>
</cartridge>
</game>
<game>
<cartridge system="NES-NTSC" dump="ok" crc="633AFE6F" sha1="2F29F3DC724027FAD926BC9D4470A481884E42A5">
<board type="NES-HKROM" mapper="4">
<prg size="32k" />
<chr size="8k" />
<pad h="0" v="1" />
<chip type="MMC6B" battery="0" />
</board>
</cartridge>
</game>
</database>

View file

@ -1667,6 +1667,13 @@
<File
RelativePath="..\source\core\board\NstBoardWaixingFfv.hpp"
>
<File
RelativePath="..\source\core\board\NstBoardWaixingFs304.cpp"
>
</File>
<File
RelativePath="..\source\core\board\NstBoardWaixingFs304.hpp"
>
</File>
<File
RelativePath="..\source\core\board\NstBoardWaixingPs2.cpp"

View file

@ -317,6 +317,7 @@
<ClInclude Include="..\source\core\board\NstBoardTxcTw.hpp" />
<ClInclude Include="..\source\core\board\NstBoardWaixing.hpp" />
<ClInclude Include="..\source\core\board\NstBoardWaixingFfv.hpp" />
<ClInclude Include="..\source\core\board\NstBoardWaixingFs304.hpp" />
<ClInclude Include="..\source\core\board\NstBoardWaixingPs2.hpp" />
<ClInclude Include="..\source\core\board\NstBoardWaixingSecurity.hpp" />
<ClInclude Include="..\source\core\board\NstBoardWaixingSgz.hpp" />
@ -620,6 +621,7 @@
<ClCompile Include="..\source\core\board\NstBoardTxcTw.cpp" />
<ClCompile Include="..\source\core\board\NstBoardWaixing.cpp" />
<ClCompile Include="..\source\core\board\NstBoardWaixingFfv.cpp" />
<ClCompile Include="..\source\core\board\NstBoardWaixingFs304.cpp" />
<ClCompile Include="..\source\core\board\NstBoardWaixingPs2.cpp" />
<ClCompile Include="..\source\core\board\NstBoardWaixingSecurity.cpp" />
<ClCompile Include="..\source\core\board\NstBoardWaixingSgz.cpp" />

View file

@ -2324,9 +2324,15 @@ namespace Nes
cpu.StealCycles( cpu.GetClock(1) );
// This is disabled until a real solution is discovered
//if ((readAddress & 0xF000) != 0x4000)
// cpu.Peek( readAddress );
/* According to dmc_dma_during_read4/dma_2007_read, DMC DMA during read causes
* 2-3 extra $2007 reads before the real read. The nesdev wiki states that this
* also happens when polling $2002 for vblank.
*/
if ((readAddress & 0xF000) != 0x4000)
{
cpu.Peek( readAddress );
cpu.Peek( readAddress );
}
cpu.StealCycles( cpu.GetClock(1) );
cpu.Peek( readAddress );

View file

@ -1280,6 +1280,7 @@ namespace Nes
NST_SINGLE_CALL void Cpu::Rts()
{
opcode = map.Peek8( pc );
pc = Pull16() + 1;
cycles.count += cycles.clock[RTS_CYCLES-1];
}
@ -1290,6 +1291,7 @@ namespace Nes
{
const uint packed = Pull8();
opcode = map.Peek8( pc );
pc = Pull16();
flags.Unpack( packed );
}
@ -1802,6 +1804,7 @@ namespace Nes
{
NST_DEBUG_MSG("6502 BRK");
opcode = map.Peek8( pc );
Push16( pc + 1 );
Push8( flags.Pack() | Flags::B );
flags.i = Flags::I;

View file

@ -1103,6 +1103,7 @@ namespace Nes
{ "UNL-AX5705", Type::BTL_AX5705 },
{ "UNL-CC-21", Type::UNL_CC21 },
{ "UNL-EDU2000", Type::UNL_EDU2000 },
{ "UNL-FS304", Type::UNL_FS304 },
{ "UNL-H2288", Type::KAY_H2288 },
{ "UNL-KOF97", Type::UNL_KINGOFFIGHTERS97 },
{ "UNL-KS7013B", Type::KAISER_KS7013B },
@ -1110,6 +1111,7 @@ namespace Nes
{ "UNL-KS7031", Type::KAISER_KS7031 },
{ "UNL-KS7032", Type::KAISER_KS7032 },
{ "UNL-KS7037", Type::KAISER_KS7037 },
{ "UNL-KS7057", Type::KAISER_KS7057 },
{ "UNL-N625092", Type::UNL_N625092 },
{ "UNL-SA-0036", Type::SACHEN_SA0036 },
{ "UNL-SA-0037", Type::SACHEN_SA0037 },
@ -1449,7 +1451,7 @@ namespace Nes
case 4:
if (submapper == 1)
{ // StarTropics/Zoda's Revenge - might not be correct
{ // StarTropics/Zoda's Revenge
chips.Add(L"MMC6B");
name = "NES-HKROM";
id = Type::STD_HKROM;
@ -2778,6 +2780,12 @@ namespace Nes
id = Type::BANDAI_LZ93D50_24C01;
break;
case 162:
name = "UNL-FS304";
id = Type::UNL_FS304;
break;
case 163:
name = "NANJING";
@ -3438,6 +3446,12 @@ namespace Nes
id = Type::BMC_8157;
break;
case 302:
name = "UNL-KS7057";
id = Type::KAISER_KS7057;
break;
case 305:
name = "UNL-KS7031";
@ -3498,6 +3512,12 @@ namespace Nes
id = Type::BTL_AX5705;
break;
case 554:
name = "UNL-KS7010";
id = Type::KAISER_KS7010;
break;
default:
return false;
@ -3766,12 +3786,14 @@ 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_KS7010 : return new Kaiser::Ks7010(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_KS7057 : return new Kaiser::Ks7057(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);
@ -3868,6 +3890,7 @@ namespace Nes
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_MORTALKOMBAT2 : return new Unlicensed::MortalKombat2(c);

View file

@ -418,12 +418,14 @@ 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_KS7010 = MakeId< 554, 128, 128, 0, 0, CRM_0, NMT_V, 1 >::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< 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_KS7057 = MakeId< 302, 128, 0, 0, 0, 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,
@ -541,6 +543,7 @@ namespace Nes
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,
UNL_FS304 = MakeId< 162, 2048, 0, 8, 0, CRM_8, NMT_X, 0 >::ID,
UNL_KINGOFFIGHTERS96 = MakeId< 187, 512, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,
UNL_KINGOFFIGHTERS97 = MakeId< 263, 256, 256, 0, 0, CRM_0, NMT_X, 0 >::ID,
UNL_MORTALKOMBAT2 = MakeId< 91, 256, 512, 0, 0, CRM_0, NMT_X, 0 >::ID,

View file

@ -69,6 +69,21 @@ namespace Nes
irq.Reset( hard, hard ? false : irq.Connected() );
}
void Ks7010::SubReset(const bool hard)
{
prg.SwapBank<SIZE_16K>( 0x0000, 0x5 );
prg.SwapBank<SIZE_16K>( 0x4000, 0x3 );
// At the time of writing, the true mask for bankswitching is unknown
Map( 0x6000U, 0x7FFFU, &Ks7010::Peek_6000 );
Map( 0xCAB6U, 0xCAD6U, &Ks7010::Peek_FFFC );
Map( 0xEBE2U, 0xEBE3U, &Ks7010::Peek_FFFC );
Map( 0xEE32U, &Ks7010::Peek_FFFC );
Map( 0xFFFCU, &Ks7010::Peek_FFFC );
reg = 0;
}
void Ks7013b::SubReset(const bool hard)
{
prg.SwapBank<SIZE_16K>( 0x4000, 0x7 );
@ -147,6 +162,22 @@ namespace Nes
Map( 0xE000U, 0xEFFFU, &Ks7037::Peek_E000 );
}
void Ks7057::SubReset(const bool hard)
{
prg.SwapBank<SIZE_8K>( 0x2000, 0xD );
prg.SwapBank<SIZE_16K>( 0x4000, 0x7 );
Map( 0x6000U, 0x9FFFU, &Ks7057::Peek_6000 );
Map( 0x8000U, 0x9FFFU, &Ks7057::Poke_8000 );
Map( 0xB000U, 0xE003U, &Ks7057::Poke_B000 );
if (hard)
{
for (uint i = 0; i < 8; ++i)
regs[i] = 0;
}
}
void Ks7058::SubReset(bool)
{
for (uint i=0x000; i < 0x1000; i += 0x100)
@ -156,38 +187,6 @@ namespace Nes
}
}
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) );
if (baseChunk == AsciiId<'K','7','2'>::V)
{
while (const dword chunk = state.Begin())
{
if (chunk == AsciiId<'R','E','G'>::V)
reg = state.Read8();
state.End();
}
}
}
void Ks202::SubLoad(State::Loader& state,const dword baseChunk)
{
NST_VERIFY( (baseChunk == AsciiId<'K','0','2'>::V) );
@ -221,6 +220,54 @@ namespace Nes
}
}
void Ks7010::SubLoad(State::Loader& state,const dword baseChunk)
{
NST_VERIFY( (baseChunk == AsciiId<'K','7','0'>::V) );
if (baseChunk == AsciiId<'K','7','0'>::V)
{
while (const dword chunk = state.Begin())
{
if (chunk == AsciiId<'R','E','G'>::V)
reg = state.Read8();
state.End();
}
}
}
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) );
if (baseChunk == AsciiId<'K','7','2'>::V)
{
while (const dword chunk = state.Begin())
{
if (chunk == AsciiId<'R','E','G'>::V)
reg = state.Read8();
state.End();
}
}
}
void Ks7031::SubLoad(State::Loader& state,const dword baseChunk)
{
NST_VERIFY( (baseChunk == AsciiId<'K','7','1'>::V) );
@ -272,6 +319,33 @@ namespace Nes
}
}
void Ks7057::SubLoad(State::Loader& state,const dword baseChunk)
{
NST_VERIFY( (baseChunk == AsciiId<'K','5','7'>::V) );
if (baseChunk == AsciiId<'K','5','7'>::V)
{
while (const dword chunk = state.Begin())
{
if (chunk == AsciiId<'R','E','G'>::V)
{
State::Loader::Data<8> 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];
}
state.End();
}
}
}
void Ks202::SubSave(State::Saver& state) const
{
state.Begin( AsciiId<'K','0','2'>::V );
@ -290,6 +364,11 @@ namespace Nes
state.End();
}
void Ks7010::SubSave(State::Saver& state) const
{
state.Begin( AsciiId<'K','7','0'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write8( reg ).End().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();
@ -323,6 +402,20 @@ namespace Nes
state.End();
}
void Ks7057::SubSave(State::Saver& state) const
{
state.Begin( AsciiId<'K','5','7'>::V );
const byte data[8] =
{
regs[0], regs[1], regs[2], regs[3],
regs[4], regs[5], regs[6], regs[7]
};
state.Begin( AsciiId<'R','E','G'>::V ).Write( data ).End();
state.End();
}
#ifdef NST_MSVC_OPTIMIZE
#pragma optimize("", on)
#endif
@ -429,6 +522,20 @@ namespace Nes
Board::Sync( event, controllers );
}
NES_PEEK_A(Ks7010,6000)
{
return *(prg.Source().Mem(reg * SIZE_8K) + (address & 0x1FFF));
}
NES_PEEK_A(Ks7010,FFFC)
{
reg = (address >> 2) & 0xF;
chr.SwapBank<SIZE_8K,0x0000>( reg );
ppu.Update();
return prg.Peek(address & 0x7FFF);
}
NES_POKE_D(Ks7013b,6000)
{
prg.SwapBank<SIZE_16K>( 0x0000, data & 0x7 );
@ -566,6 +673,39 @@ namespace Nes
{
return *(prg.Source().Mem(SIZE_8K * 15) + (address & 0x1FFF));
}
NES_PEEK_A(Ks7057,6000)
{
return *(prg.Source().Mem(regs[(address >> 11) - 0xC] * SIZE_2K) + (address & 0x7FF));
}
NES_POKE_D(Ks7057,8000)
{
ppu.SetMirroring( (data & 0x1) ? Ppu::NMT_V : Ppu::NMT_H );
}
NES_POKE_AD(Ks7057,B000)
{
switch(address & 0xF003)
{
case 0xB000: regs[4] = (regs[4] & 0xF0) | (data & 0xF); break;
case 0xB001: regs[4] = (regs[4] & 0xF) | (data << 4); break;
case 0xB002: regs[5] = (regs[5] & 0xF0) | (data & 0xF); break;
case 0xB003: regs[5] = (regs[5] & 0xF) | (data << 4); break;
case 0xC000: regs[6] = (regs[6] & 0xF0) | (data & 0xF); break;
case 0xC001: regs[6] = (regs[6] & 0xF) | (data << 4); break;
case 0xC002: regs[7] = (regs[7] & 0xF0) | (data & 0xF); break;
case 0xC003: regs[7] = (regs[7] & 0xF) | (data << 4); break;
case 0xD000: regs[0] = (regs[0] & 0xF0) | (data & 0xF); break;
case 0xD001: regs[0] = (regs[0] & 0xF) | (data << 4); break;
case 0xD002: regs[1] = (regs[1] & 0xF0) | (data & 0xF); break;
case 0xD003: regs[1] = (regs[1] & 0xF) | (data << 4); break;
case 0xE000: regs[2] = (regs[2] & 0xF0) | (data & 0xF); break;
case 0xE001: regs[2] = (regs[2] & 0xF) | (data << 4); break;
case 0xE002: regs[3] = (regs[3] & 0xF0) | (data & 0xF); break;
case 0xE003: regs[3] = (regs[3] & 0xF) | (data << 4); break;
}
}
}
}
}

View file

@ -77,6 +77,25 @@ namespace Nes
Timer::M2<Irq> irq;
};
class Ks7010 : public Board
{
public:
explicit Ks7010(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_PEEK( FFFC );
uint reg;
};
class Ks7013b : public Board
{
public:
@ -191,6 +210,25 @@ namespace Nes
NES_DECL_PEEK( E000 );
};
class Ks7057 : public Board
{
public:
explicit Ks7057(const Context& c)
: Board(c) {}
private:
void SubReset(bool);
void SubLoad(State::Loader&,dword);
void SubSave(State::Saver&) const;
byte regs[8];
NES_DECL_PEEK( 6000 );
NES_DECL_POKE( 8000 );
NES_DECL_POKE( B000 );
};
class Ks7058 : public Board
{
public:

View file

@ -58,32 +58,28 @@ namespace Nes
uint latch;
ibool reload;
ibool enabled;
const ibool persistant;
const ibool persistent;
public:
explicit BaseIrq(bool p)
: persistant(p) {}
: persistent(p) {}
NST_FORCE_INLINE bool Clock()
{
const uint tmp = count;
const bool tmp = count || reload;
if (reload)
{
reload = false;
count = latch;
}
else if (!count)
if (!count || reload)
{
count = latch;
}
else
{
count--;
--count;
}
return (tmp | persistant) && !count && enabled;
reload = false;
return (tmp | persistent) && !count && enabled;
}
void SetLatch(uint data)
@ -120,8 +116,8 @@ namespace Nes
template<uint Delay=0, uint ClockFilter=BaseIrq::CLOCK_FILTER>
struct Irq : Timer::A12<BaseIrq,ClockFilter,Delay>
{
Irq(Cpu& c,Ppu& p,bool persistant)
: Timer::A12<BaseIrq,ClockFilter,Delay>(c,p,persistant) {}
Irq(Cpu& c,Ppu& p,bool persistent)
: Timer::A12<BaseIrq,ClockFilter,Delay>(c,p,persistent) {}
};
protected:

View file

@ -37,7 +37,7 @@ namespace Nes
#endif
Mmc6::Mmc6(const Context& c)
: Mmc3(c,REV_B) {}
: Mmc3(c,REV_A) {}
void Mmc6::SubReset(const bool hard)
{

View file

@ -32,6 +32,7 @@
#include "NstBoardMmc3.hpp"
#include "NstBoardWaixingPs2.hpp"
#include "NstBoardWaixingFfv.hpp"
#include "NstBoardWaixingFs304.hpp"
#include "NstBoardWaixingSh2.hpp"
#include "NstBoardWaixingZs.hpp"
#include "NstBoardWaixingSecurity.hpp"

View file

@ -0,0 +1,106 @@
////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// 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 "NstBoardWaixing.hpp"
// Reference: https://github.com/TASVideos/fceux/blob/master/src/boards/164.cpp
namespace Nes
{
namespace Core
{
namespace Boards
{
namespace Waixing
{
void Fs304::SubReset(bool)
{
Map( 0x5000U, 0x5FFFU, &Fs304::Poke_5000 );
regs[0] = 0x3;
regs[1] = 0x0;
regs[2] = 0x0;
regs[3] = 0x7;
UpdatePrg();
}
void Fs304::SubSave(State::Saver& state) const
{
const byte data[4] = { regs[0], regs[1], regs[2], regs[3] };
state.Begin( AsciiId<'3','0','4'>::V ).Begin( AsciiId<'R','E','G'>::V ).Write( data ).End().End();
}
void Fs304::SubLoad(State::Loader& state,const dword baseChunk)
{
NST_VERIFY( baseChunk == (AsciiId<'3','0','4'>::V) );
if (baseChunk == AsciiId<'3','0','4'>::V)
{
while (const dword chunk = state.Begin())
{
if (chunk == AsciiId<'R','E','G'>::V)
{
State::Loader::Data<4> data( state );
regs[0] = data[0];
regs[1] = data[1];
regs[2] = data[2];
regs[3] = data[3];
}
state.End();
}
}
}
void Fs304::UpdatePrg()
{
switch (regs[3] & 0x5) {
case 0:
prg.SwapBank<SIZE_32K>( 0x0000, ((regs[0] & 0xC) | (regs[1] & 0x2) | ((regs[2] & 0xF) << 4)) );
break;
case 1:
prg.SwapBank<SIZE_32K>( 0x0000, ((regs[0] & 0xC) | (regs[2] & 0xF) << 4) );
break;
case 4:
prg.SwapBank<SIZE_32K>( 0x0000, ((regs[0] & 0xE) | ((regs[1] >> 1) & 0x1) | ((regs[2] & 0xF) << 4)) );
break;
case 5:
prg.SwapBank<SIZE_32K>( 0x0000, ((regs[0] & 0xF) | ((regs[2] & 0xF) << 4)) );
break;
}
}
NES_POKE_AD(Fs304,5000)
{
regs[(address >> 8) & 0x3] = data;
UpdatePrg();
}
}
}
}
}

View file

@ -0,0 +1,63 @@
////////////////////////////////////////////////////////////////////////////////////////
//
// Nestopia - NES/Famicom emulator written in C++
//
// 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_WAIXING_FS304_H
#define NST_BOARD_WAIXING_FS304_H
#ifdef NST_PRAGMA_ONCE
#pragma once
#endif
namespace Nes
{
namespace Core
{
namespace Boards
{
namespace Waixing
{
class Fs304 : public Board
{
public:
explicit Fs304(const Context& c)
: Board(c) {}
private:
void SubReset(bool);
void SubSave(State::Saver&) const;
void SubLoad(State::Loader&,dword);
void UpdatePrg();
NES_DECL_POKE( 5000 );
uint regs[4];
};
}
}
}
}
#endif