mirror of
https://github.com/0ldsk00l/nestopia.git
synced 2025-04-02 10:31:51 -04:00
This commit is a culmination of many commits made in the upstream repository at https://gitlab.com/jgemu/nestopia and fixes a number of warnings, making the codebase far more robust: -Wimplicit-fallthrough -Wunused-local-typedefs -Wunused-private-field -Wmaybe-uninitialized -Wunused-variable -Warray-bounds -Wdelete-non-virtual-dtor -Wsequence-point -Wparentheses
1503 lines
65 KiB
C++
1503 lines
65 KiB
C++
////////////////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Nestopia - NES/Famicom emulator written in C++
|
|
//
|
|
// Copyright (C) 2003-2008 Martin Freij
|
|
//
|
|
// 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 "../NstLog.hpp"
|
|
#include "../NstCpu.hpp"
|
|
#include "../NstPpu.hpp"
|
|
#include "../NstState.hpp"
|
|
#include "NstVsSystem.hpp"
|
|
#include "NstVsRbiBaseball.hpp"
|
|
#include "NstVsTkoBoxing.hpp"
|
|
#include "NstVsSuperXevious.hpp"
|
|
|
|
namespace Nes
|
|
{
|
|
namespace Core
|
|
{
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("s", on)
|
|
#endif
|
|
|
|
class Cartridge::VsSystem::Dip
|
|
{
|
|
class Proxy;
|
|
|
|
struct Setting
|
|
{
|
|
uint data;
|
|
cstring name;
|
|
};
|
|
|
|
Setting* settings;
|
|
uint size;
|
|
uint selection;
|
|
cstring name;
|
|
|
|
public:
|
|
|
|
struct Value
|
|
{
|
|
cstring const name;
|
|
const uint data;
|
|
const uint selection;
|
|
|
|
Value(cstring n,uint d,uint s=0)
|
|
: name(n), data(d), selection(s) {}
|
|
};
|
|
|
|
void operator = (const Value&);
|
|
|
|
private:
|
|
|
|
class Proxy
|
|
{
|
|
Dip& dip;
|
|
const uint index;
|
|
|
|
public:
|
|
|
|
Proxy(Dip& d,uint i)
|
|
: dip(d), index(i) {}
|
|
|
|
void operator = (const Value& value)
|
|
{
|
|
dip.settings[index].data = value.data;
|
|
dip.settings[index].name = value.name;
|
|
}
|
|
|
|
operator uint() const
|
|
{
|
|
return dip.settings[index].data;
|
|
}
|
|
|
|
cstring Name() const
|
|
{
|
|
return dip.settings[index].name;
|
|
}
|
|
};
|
|
|
|
public:
|
|
|
|
Dip()
|
|
: settings(NULL) {}
|
|
|
|
~Dip()
|
|
{
|
|
delete [] settings;
|
|
}
|
|
|
|
uint Size() const
|
|
{
|
|
return size;
|
|
}
|
|
|
|
void Select(uint i)
|
|
{
|
|
NST_ASSERT( i < size );
|
|
selection = i;
|
|
}
|
|
|
|
uint Selection() const
|
|
{
|
|
return selection;
|
|
}
|
|
|
|
Proxy operator [] (uint i)
|
|
{
|
|
NST_ASSERT( i < size );
|
|
return Proxy(*this,i);
|
|
}
|
|
|
|
cstring Name() const
|
|
{
|
|
return name;
|
|
}
|
|
};
|
|
|
|
void Cartridge::VsSystem::Dip::operator = (const Value& value)
|
|
{
|
|
NST_ASSERT( settings == NULL && value.data && value.selection < value.data );
|
|
|
|
name = value.name;
|
|
size = value.data;
|
|
selection = value.selection;
|
|
settings = new Setting [size];
|
|
}
|
|
|
|
Cartridge::VsSystem::VsDipSwitches::VsDipSwitches(Dip*& old,uint n)
|
|
: table(old), size(n)
|
|
{
|
|
old = NULL;
|
|
|
|
regs[0] = 0;
|
|
regs[1] = 0;
|
|
|
|
for (uint i=0; i < n; ++i)
|
|
{
|
|
regs[0] |= (table[i][table[i].Selection()] & DIPSWITCH_4016_MASK) << DIPSWITCH_4016_SHIFT;
|
|
regs[1] |= (table[i][table[i].Selection()] & DIPSWITCH_4017_MASK) << DIPSWITCH_4017_SHIFT;
|
|
}
|
|
}
|
|
|
|
Cartridge::VsSystem::VsDipSwitches::~VsDipSwitches()
|
|
{
|
|
delete [] table;
|
|
}
|
|
|
|
inline void Cartridge::VsSystem::VsDipSwitches::Reset()
|
|
{
|
|
coinTimer = 0;
|
|
regs[0] &= ~uint(COIN);
|
|
}
|
|
|
|
inline uint Cartridge::VsSystem::VsDipSwitches::Reg(uint i) const
|
|
{
|
|
return regs[i];
|
|
}
|
|
|
|
uint Cartridge::VsSystem::VsDipSwitches::NumDips() const
|
|
{
|
|
return size;
|
|
}
|
|
|
|
uint Cartridge::VsSystem::VsDipSwitches::NumValues(uint dip) const
|
|
{
|
|
NST_ASSERT( dip < size );
|
|
return table[dip].Size();
|
|
}
|
|
|
|
cstring Cartridge::VsSystem::VsDipSwitches::GetDipName(uint dip) const
|
|
{
|
|
NST_ASSERT( dip < size );
|
|
return table[dip].Name();
|
|
}
|
|
|
|
cstring Cartridge::VsSystem::VsDipSwitches::GetValueName(uint dip,uint value) const
|
|
{
|
|
NST_ASSERT( dip < size && value < table[dip].Size() );
|
|
return table[dip][value].Name();
|
|
}
|
|
|
|
uint Cartridge::VsSystem::VsDipSwitches::GetValue(uint dip) const
|
|
{
|
|
NST_ASSERT( dip < size );
|
|
return table[dip].Selection();
|
|
}
|
|
|
|
void Cartridge::VsSystem::VsDipSwitches::SetValue(uint dip,uint value)
|
|
{
|
|
NST_ASSERT( dip < size && value < table[dip].Size() );
|
|
|
|
const uint old = table[dip].Selection();
|
|
|
|
regs[0] &= ~((table[dip][old] & DIPSWITCH_4016_MASK) << DIPSWITCH_4016_SHIFT);
|
|
regs[1] &= ~((table[dip][old] & DIPSWITCH_4017_MASK) << DIPSWITCH_4017_SHIFT);
|
|
|
|
table[dip].Select( value );
|
|
|
|
regs[0] |= (table[dip][value] & DIPSWITCH_4016_MASK) << DIPSWITCH_4016_SHIFT;
|
|
regs[1] |= (table[dip][value] & DIPSWITCH_4017_MASK) << DIPSWITCH_4017_SHIFT;
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
void Cartridge::VsSystem::VsDipSwitches::BeginFrame(Input::Controllers* const input)
|
|
{
|
|
if (!coinTimer)
|
|
{
|
|
if (input)
|
|
{
|
|
Input::Controllers::VsSystem::callback( input->vsSystem );
|
|
|
|
if (input->vsSystem.insertCoin & COIN)
|
|
{
|
|
regs[0] |= input->vsSystem.insertCoin & COIN;
|
|
coinTimer = 20;
|
|
}
|
|
}
|
|
}
|
|
else if (--coinTimer == 15)
|
|
{
|
|
regs[0] &= ~uint(COIN);
|
|
}
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("s", on)
|
|
#endif
|
|
|
|
struct Cartridge::VsSystem::Context
|
|
{
|
|
Dip* dips;
|
|
uint numDips;
|
|
Cpu& cpu;
|
|
Ppu& ppu;
|
|
PpuModel ppuModel;
|
|
Mode mode;
|
|
InputMapper::Type inputMapper;
|
|
|
|
Context(Cpu& c,Ppu& p)
|
|
:
|
|
dips (NULL),
|
|
numDips (0),
|
|
cpu (c),
|
|
ppu (p),
|
|
ppuModel (PPU_RP2C03B),
|
|
mode (MODE_STD),
|
|
inputMapper (InputMapper::TYPE_NONE)
|
|
{
|
|
}
|
|
|
|
void SetDips(uint n)
|
|
{
|
|
numDips = n;
|
|
dips = new Dip [n];
|
|
}
|
|
};
|
|
|
|
Cartridge::VsSystem* Cartridge::VsSystem::Create
|
|
(
|
|
Cpu& cpu,
|
|
Ppu& ppu,
|
|
const PpuModel ppuModel,
|
|
const dword prgCrc
|
|
)
|
|
{
|
|
switch (prgCrc)
|
|
{
|
|
// VS. Dual-System Games are unsupported
|
|
|
|
case 0xB90497AA: // Tennis
|
|
case 0x2A909613: // Tennis (alt)
|
|
case 0xBC202DB6: // Tennis P2
|
|
case 0x008A9C16: // Wrecking Crew P1
|
|
case 0x30C42B1E: // Wrecking Crew P2
|
|
case 0xAD407F52: // Balloon Fight P1
|
|
case 0x6AD67502: // Balloon Fight P2
|
|
case 0x18A93B7B: // Mahjong (J)
|
|
case 0xA2AD7D61: // Mahjong (J) (alt)
|
|
case 0xA9A4A6C5: // Mahjong (J) P1
|
|
case 0x78D1D213: // Mahjong (J) P2
|
|
case 0x13A91937: // Baseball P1
|
|
case 0xC4DD2523: // Baseball P1 (alt 1)
|
|
case 0xB5853830: // Baseball P1 (alt 2)
|
|
case 0x968A6E9D: // Baseball P2
|
|
case 0xF64D7252: // Baseball P2 (alt 1)
|
|
case 0xF5DEBF88: // Baseball P2 (alt 2)
|
|
case 0xF42DAB14: // Ice Climber P1
|
|
case 0x7D6B764F: // Ice Climber P2
|
|
|
|
throw RESULT_ERR_UNSUPPORTED_VSSYSTEM;
|
|
}
|
|
|
|
Context context( cpu, ppu );
|
|
|
|
try
|
|
{
|
|
// Credit to the MAME devs for much of the DIP switch info.
|
|
|
|
switch (prgCrc)
|
|
{
|
|
case 0xEB2DBA63: // TKO Boxing
|
|
|
|
context.SetDips(7);
|
|
context.dips[0] = Dip::Value( "Coinage", 4, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x01 );
|
|
context.dips[0][2] = Dip::Value( "2 Coins / 1 Credit", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "3 Coins / 1 Credit", 0x03 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x04 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[4] = Dip::Value( "Palette Color", 2, 1 );
|
|
context.dips[4][0] = Dip::Value( "Black", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "White", 0x20 );
|
|
context.dips[5] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[6] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[6][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[6][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
context.mode = MODE_TKO;
|
|
break;
|
|
|
|
case 0x135ADF7C: // RBI Baseball
|
|
|
|
context.SetDips(4);
|
|
context.dips[0] = Dip::Value( "Coinage", 4, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x01 );
|
|
context.dips[0][2] = Dip::Value( "2 Coins / 1 Credit", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "3 Coins / 1 Credit", 0x03 );
|
|
context.dips[1] = Dip::Value( "Max. 1p/in, 2p/in, Min", 4, 1 );
|
|
context.dips[1][0] = Dip::Value( "2, 1, 3", 0x04 );
|
|
context.dips[1][1] = Dip::Value( "2, 2, 4", 0x0C );
|
|
context.dips[1][2] = Dip::Value( "3, 2, 6", 0x00 );
|
|
context.dips[1][3] = Dip::Value( "4, 3, 7", 0x08 );
|
|
context.dips[2] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[3] = Dip::Value( "PPU", 5, 0 );
|
|
context.dips[3][0] = Dip::Value( "RP2C03", 0x20 );
|
|
context.dips[3][1] = Dip::Value( "RP2C04-0001", 0x00 );
|
|
context.dips[3][2] = Dip::Value( "RP2C04-0002", 0x40 );
|
|
context.dips[3][3] = Dip::Value( "RP2C04-0003", 0x80 );
|
|
context.dips[3][4] = Dip::Value( "RP2C04-0004", 0xC0 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
context.mode = MODE_RBI;
|
|
break;
|
|
|
|
case 0xED588F00: // Duck Hunt
|
|
|
|
context.SetDips(4);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Difficulty", 4, 1 );
|
|
context.dips[1][0] = Dip::Value( "Easy", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "Normal", 0x08 );
|
|
context.dips[1][2] = Dip::Value( "Hard", 0x10 );
|
|
context.dips[1][3] = Dip::Value( "Very Hard", 0x18 );
|
|
context.dips[2] = Dip::Value( "Misses per Game", 2, 1 );
|
|
context.dips[2][0] = Dip::Value( "3", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "5", 0x20 );
|
|
context.dips[3] = Dip::Value( "Bonus Life", 4, 0 );
|
|
context.dips[3][0] = Dip::Value( "30000", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "50000", 0x40 );
|
|
context.dips[3][2] = Dip::Value( "80000", 0x80 );
|
|
context.dips[3][3] = Dip::Value( "100000", 0xC0 );
|
|
|
|
break;
|
|
|
|
case 0x16D3F469: // Ninja Jajamaru Kun (J)
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 3, 0 );
|
|
context.dips[1][0] = Dip::Value( "3", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "4", 0x10 );
|
|
context.dips[1][2] = Dip::Value( "5", 0x08 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[4] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RC2C05_01;
|
|
context.inputMapper = InputMapper::TYPE_3;
|
|
break;
|
|
|
|
case 0x8850924B: // Tetris
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Coinage", 4, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x02 );
|
|
context.dips[0][2] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][3] = Dip::Value( "3 Coins / 1 Credit", 0x03 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x04 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[4] = Dip::Value( "Palette Color", 3, 2 );
|
|
context.dips[4][0] = Dip::Value( "Black", 0x40 );
|
|
context.dips[4][1] = Dip::Value( "Green", 0x20 );
|
|
context.dips[4][2] = Dip::Value( "Grey", 0x60 );
|
|
context.dips[5] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0x8C0C2DF5: // Top Gun
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives per Coin", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "3 - 12 Max", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "2 - 9 Max", 0x08 );
|
|
context.dips[2] = Dip::Value( "Bonus", 4, 0 );
|
|
context.dips[2][0] = Dip::Value( "30k and every 50k", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "50k and every 100k", 0x20 );
|
|
context.dips[2][2] = Dip::Value( "100k and every 150k", 0x10 );
|
|
context.dips[2][3] = Dip::Value( "200k and every 200k", 0x30 );
|
|
context.dips[3] = Dip::Value( "Difficulty", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "Hard", 0x40 );
|
|
context.dips[4] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RC2C05_04;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0x70901B25: // Slalom
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Freestyle Points", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Left / Right", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "Hold Time", 0x08 );
|
|
context.dips[2] = Dip::Value( "Difficulty", 4, 1 );
|
|
context.dips[2][0] = Dip::Value( "Easy", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "Normal", 0x10 );
|
|
context.dips[2][2] = Dip::Value( "Hard", 0x20 );
|
|
context.dips[2][3] = Dip::Value( "Hardest", 0x30 );
|
|
context.dips[3] = Dip::Value( "Allow Continue", 2, 1 );
|
|
context.dips[3][0] = Dip::Value( "No", 0x40 );
|
|
context.dips[3][1] = Dip::Value( "Yes", 0x00 );
|
|
context.dips[4] = Dip::Value( "Inverted input", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0002;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xCF36261E: // Super Sky Kid
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[0][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "On", 0x01 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x02 );
|
|
context.dips[2] = Dip::Value( "Lives", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "2", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "3", 0x04 );
|
|
context.dips[3] = Dip::Value( "Coinage", 4, 0 );
|
|
context.dips[3][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "1 Coin / 2 Credits", 0x08 );
|
|
context.dips[3][2] = Dip::Value( "2 Coins / 1 Credit", 0x10 );
|
|
context.dips[3][3] = Dip::Value( "3 Coins / 1 Credit", 0x18 );
|
|
context.dips[4] = Dip::Value( "PPU", 5, 0 );
|
|
context.dips[4][0] = Dip::Value( "RP2C03", 0x20 );
|
|
context.dips[4][1] = Dip::Value( "RP2C04-0001", 0x00 );
|
|
context.dips[4][2] = Dip::Value( "RP2C04-0002", 0x40 );
|
|
context.dips[4][3] = Dip::Value( "RP2C04-0003", 0x80 );
|
|
context.dips[4][4] = Dip::Value( "RP2C04-0004", 0xC0 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_3;
|
|
break;
|
|
|
|
case 0xE1AA8214: // Star Luster
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Coinage", 4, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x02 );
|
|
context.dips[0][2] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][3] = Dip::Value( "3 Coins / 1 Credit", 0x03 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x04 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[4] = Dip::Value( "Palette Color", 3, 0 );
|
|
context.dips[4][0] = Dip::Value( "Black", 0x40 );
|
|
context.dips[4][1] = Dip::Value( "Green", 0x20 );
|
|
context.dips[4][2] = Dip::Value( "Grey", 0x60 );
|
|
context.dips[5] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xD5D7EAC4: // Dr. Mario
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Drop Rate Increases After", 4, 0 );
|
|
context.dips[0][0] = Dip::Value( "7 Pills", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "8 Pills", 0x01 );
|
|
context.dips[0][2] = Dip::Value( "9 Pills", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "10 Pills", 0x03 );
|
|
context.dips[1] = Dip::Value( "Virus Level", 4, 0 );
|
|
context.dips[1][0] = Dip::Value( "1", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "3", 0x04 );
|
|
context.dips[1][2] = Dip::Value( "5", 0x08 );
|
|
context.dips[1][3] = Dip::Value( "7", 0x0C );
|
|
context.dips[2] = Dip::Value( "Drop Speed Up", 4, 0 );
|
|
context.dips[2][0] = Dip::Value( "Slow", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "Medium", 0x10 );
|
|
context.dips[2][2] = Dip::Value( "Fast", 0x20 );
|
|
context.dips[2][3] = Dip::Value( "Fastest", 0x30 );
|
|
context.dips[3] = Dip::Value( "Free Play", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[4] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0003;
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0xFFBEF374: // Castlevania
|
|
|
|
context.SetDips(4);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 2, 1 );
|
|
context.dips[1][0] = Dip::Value( "2", 0x08 );
|
|
context.dips[1][1] = Dip::Value( "3", 0x00 );
|
|
context.dips[2] = Dip::Value( "Bonus", 4, 0 );
|
|
context.dips[2][0] = Dip::Value( "100k", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "200k", 0x20 );
|
|
context.dips[2][2] = Dip::Value( "300k", 0x10 );
|
|
context.dips[2][3] = Dip::Value( "400k", 0x30 );
|
|
context.dips[3] = Dip::Value( "Difficulty", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "Hard", 0x40 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0002;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xE2C0A2BE: // Platoon
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[0][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "On", 0x01 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x02 );
|
|
context.dips[2] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x04 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[5] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[5][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "1 Coin / 2 Credits", 0x20 );
|
|
context.dips[5][2] = Dip::Value( "1 Coin / 3 Credits", 0x40 );
|
|
context.dips[5][3] = Dip::Value( "2 Coins / 1 Credit", 0x60 );
|
|
context.dips[5][4] = Dip::Value( "3 Coins / 1 Credit", 0x80 );
|
|
context.dips[5][5] = Dip::Value( "4 Coins / 1 Credit", 0xA0 );
|
|
context.dips[5][6] = Dip::Value( "5 Coins / 1 Credit", 0xC0 );
|
|
context.dips[5][7] = Dip::Value( "Free Play", 0xE0 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xCBE85490: // Excitebike
|
|
case 0x29155E0C: // Excitebike (alt)
|
|
|
|
context.SetDips(4);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Bonus", 4, 0 );
|
|
context.dips[1][0] = Dip::Value( "100k and Every 50k", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "Every 100k", 0x10 );
|
|
context.dips[1][2] = Dip::Value( "100k Only", 0x08 );
|
|
context.dips[1][3] = Dip::Value( "None", 0x18 );
|
|
context.dips[2] = Dip::Value( "1st Half Qualifying Time", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "Hard", 0x20 );
|
|
context.dips[3] = Dip::Value( "2nd Half Qualifying Time", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "Hard", 0x40 );
|
|
|
|
if (prgCrc == 0x29155E0C)
|
|
context.ppuModel = PPU_RP2C04_0004;
|
|
else
|
|
context.ppuModel = PPU_RP2C04_0003;
|
|
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0x07138C06: // Clu Clu Land
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[3] = Dip::Value( "Lives", 4, 1 );
|
|
context.dips[3][0] = Dip::Value( "2", 0x60 );
|
|
context.dips[3][1] = Dip::Value( "3", 0x00 );
|
|
context.dips[3][2] = Dip::Value( "4", 0x40 );
|
|
context.dips[3][3] = Dip::Value( "5", 0x20 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0004;
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0x43A357EF: // Ice Climber
|
|
case 0xD4EB5923: // -||-
|
|
|
|
context.SetDips(4);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 4, 0 );
|
|
context.dips[1][0] = Dip::Value( "3", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "4", 0x10 );
|
|
context.dips[1][2] = Dip::Value( "5", 0x08 );
|
|
context.dips[1][3] = Dip::Value( "7", 0x18 );
|
|
context.dips[2] = Dip::Value( "Difficulty", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "Hard", 0x20 );
|
|
context.dips[3] = Dip::Value( "Time before the bear", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Long", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "Short", 0x40 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0004;
|
|
|
|
if (prgCrc == 0x43A357EF)
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
else
|
|
context.inputMapper = InputMapper::TYPE_4;
|
|
|
|
break;
|
|
|
|
case 0x737DD1BF: // Super Mario Bros
|
|
case 0x4BF3972D: // -||-
|
|
case 0x8B60CC58: // -||-
|
|
case 0x8192C804: // -||-
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x06 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x01 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x05 );
|
|
context.dips[0][4] = Dip::Value( "1 Coin / 5 Credits", 0x03 );
|
|
context.dips[0][5] = Dip::Value( "2 Coins / 1 Credit", 0x04 );
|
|
context.dips[0][6] = Dip::Value( "3 Coins / 1 Credit", 0x02 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 2, 1 );
|
|
context.dips[1][0] = Dip::Value( "2", 0x08 );
|
|
context.dips[1][1] = Dip::Value( "3", 0x00 );
|
|
context.dips[2] = Dip::Value( "Bonus Life", 4, 0 );
|
|
context.dips[2][0] = Dip::Value( "100", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "150", 0x20 );
|
|
context.dips[2][2] = Dip::Value( "200", 0x10 );
|
|
context.dips[2][3] = Dip::Value( "250", 0x30 );
|
|
context.dips[3] = Dip::Value( "Timer", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "Fast", 0x40 );
|
|
context.dips[4] = Dip::Value( "Continue Lives", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "3", 0x80 );
|
|
context.dips[4][1] = Dip::Value( "4", 0x00 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0004;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xEC461DB9: // Pinball
|
|
case 0xE528F651: // -||- (alt)
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x01 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x06 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x04 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x07 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x00 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[3] = Dip::Value( "Balls", 4, 1 );
|
|
context.dips[3][0] = Dip::Value( "2", 0x60 );
|
|
context.dips[3][1] = Dip::Value( "3", 0x00 );
|
|
context.dips[3][2] = Dip::Value( "4", 0x40 );
|
|
context.dips[3][3] = Dip::Value( "5", 0x20 );
|
|
context.dips[4] = Dip::Value( "Ball Speed", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "Fast", 0x80 );
|
|
|
|
if (prgCrc == 0xEC461DB9)
|
|
{
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
}
|
|
else
|
|
{
|
|
context.inputMapper = InputMapper::TYPE_5;
|
|
}
|
|
break;
|
|
|
|
case 0xAE8063EF: // Mach Rider - Fighting Course
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Km 1st Race", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "12", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "15", 0x10 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0x0B65A917: // Mach Rider
|
|
case 0x8A6A9848: // -||-
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Time", 4, 0 );
|
|
context.dips[1][0] = Dip::Value( "280", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "250", 0x10 );
|
|
context.dips[1][2] = Dip::Value( "220", 0x08 );
|
|
context.dips[1][3] = Dip::Value( "200", 0x18 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0002;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0x46914E3E: // Soccer
|
|
|
|
context.SetDips(3);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Points Timer", 4, 2 );
|
|
context.dips[1][0] = Dip::Value( "600 Pts", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "800 Pts", 0x10 );
|
|
context.dips[1][2] = Dip::Value( "1000 Pts", 0x08 );
|
|
context.dips[1][3] = Dip::Value( "1200 Pts", 0x18 );
|
|
context.dips[2] = Dip::Value( "Difficulty", 4, 1 );
|
|
context.dips[2][0] = Dip::Value( "Easy", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "Normal", 0x40 );
|
|
context.dips[2][2] = Dip::Value( "Hard", 0x20 );
|
|
context.dips[2][3] = Dip::Value( "Very Hard", 0x60 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0003;
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0x70433F2C: // Battle City
|
|
|
|
context.SetDips(7);
|
|
context.dips[0] = Dip::Value( "Credits for 2 Players", 2, 1 );
|
|
context.dips[0][0] = Dip::Value( "1", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "2", 0x01 );
|
|
context.dips[1] = Dip::Value( "Lives", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "3", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "5", 0x02 );
|
|
context.dips[2] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x04 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[5] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[6] = Dip::Value( "PPU", 4, 0 );
|
|
context.dips[6][0] = Dip::Value( "RP2C04-0001", 0x00 );
|
|
context.dips[6][1] = Dip::Value( "RP2C04-0002", 0x40 );
|
|
context.dips[6][2] = Dip::Value( "RP2C04-0003", 0x80 );
|
|
context.dips[6][3] = Dip::Value( "RP2C04-0004", 0xC0 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0xD99A2087: // Gradius
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "3", 0x08 );
|
|
context.dips[1][1] = Dip::Value( "4", 0x00 );
|
|
context.dips[2] = Dip::Value( "Bonus", 4, 0 );
|
|
context.dips[2][0] = Dip::Value( "100k", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "200k", 0x20 );
|
|
context.dips[2][2] = Dip::Value( "300k", 0x10 );
|
|
context.dips[2][3] = Dip::Value( "400k", 0x30 );
|
|
context.dips[3] = Dip::Value( "Difficulty", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "Hard", 0x40 );
|
|
context.dips[4] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0x1E438D52: // Goonies
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "3", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "2", 0x08 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[4] = Dip::Value( "Timer", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Normal", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "Fast", 0x40 );
|
|
context.dips[5] = Dip::Value( "Demo Sounds", 2, 1 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0003;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xFF5135A3: // Hogan's Alley
|
|
|
|
context.SetDips(4);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Difficulty", 4, 1 );
|
|
context.dips[1][0] = Dip::Value( "Easy", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "Normal", 0x08 );
|
|
context.dips[1][2] = Dip::Value( "Hard", 0x10 );
|
|
context.dips[1][3] = Dip::Value( "Very Hard", 0x18 );
|
|
context.dips[2] = Dip::Value( "Misses per Game", 2, 1 );
|
|
context.dips[2][0] = Dip::Value( "3", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "5", 0x20 );
|
|
context.dips[3] = Dip::Value( "Bonus Life", 4, 0 );
|
|
context.dips[3][0] = Dip::Value( "30000", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "50000", 0x40 );
|
|
context.dips[3][2] = Dip::Value( "80000", 0x80 );
|
|
context.dips[3][3] = Dip::Value( "100000", 0xC0 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
break;
|
|
|
|
case 0x17AE56BE: // Freedom Force
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[5] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
break;
|
|
|
|
case 0xC99EC059: // Raid on Bungeling Bay
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "2", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "3", 0x08 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x10 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[5] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[5][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RP2C04_0002;
|
|
context.inputMapper = InputMapper::TYPE_4;
|
|
break;
|
|
|
|
case 0xF9D3B0A3: // Super Xevious
|
|
case 0x66BB838F: // -||-
|
|
case 0x9924980A: // -||-
|
|
|
|
context.SetDips(6);
|
|
context.dips[0] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[0][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "On", 0x01 );
|
|
context.dips[1] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "On", 0x02 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x04 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x08 );
|
|
context.dips[4] = Dip::Value( "Coinage", 4, 0 );
|
|
context.dips[4][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "1 Coin / 2 Credits", 0x10 );
|
|
context.dips[4][2] = Dip::Value( "2 Coins / 1 Credit", 0x20 );
|
|
context.dips[4][3] = Dip::Value( "3 Coins / 1 Credit", 0x30 );
|
|
context.dips[5] = Dip::Value( "PPU", 4, 0 );
|
|
context.dips[5][0] = Dip::Value( "RP2C04-0001", 0x00 );
|
|
context.dips[5][1] = Dip::Value( "RP2C04-0002", 0x40 );
|
|
context.dips[5][2] = Dip::Value( "RP2C04-0003", 0x80 );
|
|
context.dips[5][3] = Dip::Value( "RP2C04-0004", 0xC0 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
context.ppuModel = PPU_RP2C04_0001;
|
|
context.mode = MODE_XEV;
|
|
break;
|
|
|
|
case 0xCC2C4B5D: // Golf (J)
|
|
case 0x86167220: // Lady Golf
|
|
|
|
context.ppuModel = PPU_RP2C04_0002;
|
|
// fallthrough
|
|
|
|
case 0xA93A5AEE: // Golf
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x01 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x06 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x04 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x07 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x00 );
|
|
context.dips[1] = Dip::Value( "Hole Size", 2, 0 );
|
|
context.dips[1][0] = Dip::Value( "Large", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "Small", 0x08 );
|
|
context.dips[2] = Dip::Value( "Points per Stroke", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Easier", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "Harder", 0x10 );
|
|
context.dips[3] = Dip::Value( "Starting Points", 4, 0 );
|
|
context.dips[3][0] = Dip::Value( "10", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "13", 0x40 );
|
|
context.dips[3][2] = Dip::Value( "16", 0x20 );
|
|
context.dips[3][3] = Dip::Value( "20", 0x60 );
|
|
context.dips[4] = Dip::Value( "Difficulty Vs. Computer", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Easy", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "Hard", 0x80 );
|
|
|
|
context.inputMapper = InputMapper::TYPE_2;
|
|
break;
|
|
|
|
case 0xCA85E56D: // Mighty Bomb Jack
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "1 Coin / 4 Credits", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "2 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "3 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "4 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "5 Coins / 1 Credit", 0x07 );
|
|
context.dips[1] = Dip::Value( "Lives", 4, 0 );
|
|
context.dips[1][0] = Dip::Value( "2", 0x10 );
|
|
context.dips[1][1] = Dip::Value( "3", 0x00 );
|
|
context.dips[1][2] = Dip::Value( "4", 0x08 );
|
|
context.dips[1][3] = Dip::Value( "5", 0x18 );
|
|
context.dips[2] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[2][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[2][1] = Dip::Value( "On", 0x20 );
|
|
context.dips[3] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[3][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[3][1] = Dip::Value( "On", 0x40 );
|
|
context.dips[4] = Dip::Value( "Unknown/Unused", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "On", 0x80 );
|
|
|
|
context.ppuModel = PPU_RC2C05_02;
|
|
context.inputMapper = InputMapper::TYPE_1;
|
|
break;
|
|
|
|
case 0xFE446787: // Gumshoe
|
|
|
|
context.SetDips(5);
|
|
context.dips[0] = Dip::Value( "Coinage", 8, 0 );
|
|
context.dips[0][0] = Dip::Value( "1 Coin / 1 Credit", 0x00 );
|
|
context.dips[0][1] = Dip::Value( "1 Coin / 2 Credits", 0x04 );
|
|
context.dips[0][2] = Dip::Value( "1 Coin / 3 Credits", 0x02 );
|
|
context.dips[0][3] = Dip::Value( "2 Coins / 1 Credit", 0x06 );
|
|
context.dips[0][4] = Dip::Value( "3 Coins / 1 Credit", 0x01 );
|
|
context.dips[0][5] = Dip::Value( "4 Coins / 1 Credit", 0x05 );
|
|
context.dips[0][6] = Dip::Value( "5 Coins / 1 Credit", 0x03 );
|
|
context.dips[0][7] = Dip::Value( "Free Play", 0x07 );
|
|
context.dips[1] = Dip::Value( "Difficulty", 4, 1 );
|
|
context.dips[1][0] = Dip::Value( "Easy", 0x00 );
|
|
context.dips[1][1] = Dip::Value( "Normal", 0x08 );
|
|
context.dips[1][2] = Dip::Value( "Hard", 0x10 );
|
|
context.dips[1][3] = Dip::Value( "Very Hard", 0x18 );
|
|
context.dips[2] = Dip::Value( "Lives", 2, 1 );
|
|
context.dips[2][0] = Dip::Value( "3", 0x10 );
|
|
context.dips[2][1] = Dip::Value( "5", 0x00 );
|
|
context.dips[3] = Dip::Value( "Bullets per Balloon", 2, 1 );
|
|
context.dips[3][0] = Dip::Value( "2", 0x40 );
|
|
context.dips[3][1] = Dip::Value( "3", 0x00 );
|
|
context.dips[4] = Dip::Value( "Bonus Life", 2, 0 );
|
|
context.dips[4][0] = Dip::Value( "80000", 0x00 );
|
|
context.dips[4][1] = Dip::Value( "100000", 0x80 );
|
|
|
|
context.ppuModel = PPU_RC2C05_03;
|
|
break;
|
|
|
|
default:
|
|
|
|
context.SetDips(8);
|
|
|
|
for (uint i=0; i < 8; ++i)
|
|
{
|
|
context.dips[i] = Dip::Value( "Unknown", 2, 0 );
|
|
context.dips[i][0] = Dip::Value( "Off", 0x00 );
|
|
context.dips[i][1] = Dip::Value( "On", 1U << i );
|
|
}
|
|
|
|
if (ppuModel != PPU_RP2C02)
|
|
context.ppuModel = ppuModel;
|
|
|
|
break;
|
|
}
|
|
|
|
switch (context.mode)
|
|
{
|
|
case MODE_RBI: return new RbiBaseball ( context );
|
|
case MODE_TKO: return new TkoBoxing ( context );
|
|
case MODE_XEV: return new SuperXevious ( context );
|
|
default: return new VsSystem ( context );
|
|
}
|
|
}
|
|
catch (...)
|
|
{
|
|
delete [] context.dips;
|
|
throw;
|
|
}
|
|
}
|
|
|
|
void Cartridge::VsSystem::Destroy(Cartridge::VsSystem* vsSystem)
|
|
{
|
|
delete vsSystem;
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
struct Cartridge::VsSystem::InputMapper::Type1 : InputMapper
|
|
{
|
|
void Fix(Pad (&pads)[4],const uint (&ports)[2]) const
|
|
{
|
|
const uint p[2] = { ports[0] < 4 ? pads[ports[0]].buttons : 0, ports[1] < 4 ? pads[ports[1]].buttons : 0 };
|
|
|
|
for (uint i=2; i--; )
|
|
{
|
|
if (ports[i] < 4)
|
|
pads[ports[i]].buttons = (p[i] & ~uint(Pad::SELECT|Pad::START)) | ((p[i] & Pad::SELECT) << 1) | ((p[i] & Pad::START) >> 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct Cartridge::VsSystem::InputMapper::Type2 : InputMapper
|
|
{
|
|
void Fix(Pad (&pads)[4],const uint (&ports)[2]) const
|
|
{
|
|
const uint p[2] = { ports[0] < 4 ? pads[ports[0]].buttons : 0, ports[1] < 4 ? pads[ports[1]].buttons : 0 };
|
|
|
|
for (uint i=2; i--; )
|
|
{
|
|
if (ports[i] < 4)
|
|
pads[ports[i]].buttons = (p[i^1] & ~uint(Pad::SELECT|Pad::START)) | ((p[i^0] & Pad::SELECT) << 1) | ((p[i^0] & Pad::START) >> 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct Cartridge::VsSystem::InputMapper::Type3 : InputMapper
|
|
{
|
|
void Fix(Pad (&pads)[4],const uint (&ports)[2]) const
|
|
{
|
|
const uint p[2] = { ports[0] < 4 ? pads[ports[0]].buttons : 0, ports[1] < 4 ? pads[ports[1]].buttons : 0 };
|
|
|
|
if (ports[1] < 4)
|
|
pads[ports[1]].buttons = p[0] & ~uint(Pad::SELECT|Pad::START);
|
|
|
|
if (ports[0] < 4)
|
|
pads[ports[0]].buttons = (p[1] & ~uint(Pad::SELECT|Pad::START)) | ((p[0] & Pad::START) >> 1) | (p[1] & Pad::START);
|
|
}
|
|
};
|
|
|
|
struct Cartridge::VsSystem::InputMapper::Type4 : InputMapper
|
|
{
|
|
void Fix(Pad (&pads)[4],const uint (&ports)[2]) const
|
|
{
|
|
const uint p[2] = { ports[0] < 4 ? pads[ports[0]].buttons : 0, ports[1] < 4 ? pads[ports[1]].buttons : 0 };
|
|
|
|
for (uint i=2; i--; )
|
|
{
|
|
if (ports[i] < 4)
|
|
pads[ports[i]].buttons = (p[i^1] & ~uint(Pad::SELECT|Pad::START)) | (((p[i^0] & Pad::SELECT) ^ Pad::SELECT) << 1) | ((p[i^0] & Pad::START) >> 1);
|
|
}
|
|
}
|
|
};
|
|
|
|
struct Cartridge::VsSystem::InputMapper::Type5 : InputMapper
|
|
{
|
|
void Fix(Pad (&pads)[4],const uint (&ports)[2]) const
|
|
{
|
|
const uint p[2] = { ports[0] < 4 ? pads[ports[0]].buttons : 0, ports[1] < 4 ? pads[ports[1]].buttons : 0 };
|
|
|
|
if (ports[1] < 4)
|
|
pads[ports[1]].buttons = (p[1] & ~uint(Pad::A|Pad::SELECT|Pad::START)) | ((p[0] & Pad::B) >> 1) | ((p[1] & Pad::SELECT) << 1) | ((p[1] & Pad::START) >> 1);
|
|
|
|
if (ports[0] < 4)
|
|
pads[ports[0]].buttons = (p[0] & ~uint(Pad::B|Pad::SELECT|Pad::START)) | ((p[1] & Pad::A) << 1) | ((p[0] & Pad::SELECT) << 1) | ((p[0] & Pad::START) >> 1);
|
|
}
|
|
};
|
|
|
|
void Cartridge::VsSystem::InputMapper::Begin(const Api::Input input,Input::Controllers* const controllers)
|
|
{
|
|
Input::Controllers::Pad::callback.Get( userCallback, userData );
|
|
|
|
if (controllers)
|
|
{
|
|
uint ports[2];
|
|
|
|
for (uint i=0; i < 2; ++i)
|
|
{
|
|
ports[i] = input.GetConnectedController(i) - Api::Input::PAD1;
|
|
|
|
if (ports[i] < 4)
|
|
Input::Controllers::Pad::callback( controllers->pad[ports[i]], ports[i] );
|
|
}
|
|
|
|
Input::Controllers::Pad::callback.Set( NULL, NULL );
|
|
|
|
Fix( controllers->pad, ports );
|
|
}
|
|
}
|
|
|
|
void Cartridge::VsSystem::InputMapper::End() const
|
|
{
|
|
Input::Controllers::Pad::callback.Set( userCallback, userData );
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("s", on)
|
|
#endif
|
|
|
|
Cartridge::VsSystem::InputMapper* Cartridge::VsSystem::InputMapper::Create(Type type)
|
|
{
|
|
switch (type)
|
|
{
|
|
case TYPE_1: return new Type1;
|
|
case TYPE_2: return new Type2;
|
|
case TYPE_3: return new Type3;
|
|
case TYPE_4: return new Type4;
|
|
case TYPE_5: return new Type5;
|
|
case TYPE_NONE: default: break;
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
Cartridge::VsSystem::VsSystem(Context& context)
|
|
:
|
|
cpu (context.cpu),
|
|
ppu (context.ppu),
|
|
inputMapper (InputMapper::Create( context.inputMapper )),
|
|
dips (context.dips,context.numDips),
|
|
ppuModel (context.ppuModel)
|
|
{
|
|
}
|
|
|
|
Cartridge::VsSystem::~VsSystem()
|
|
{
|
|
delete inputMapper;
|
|
}
|
|
|
|
void Cartridge::VsSystem::Reset(bool)
|
|
{
|
|
dips.Reset();
|
|
|
|
coin = 0;
|
|
|
|
p4016 = cpu.Map( 0x4016 );
|
|
p4017 = cpu.Map( 0x4017 );
|
|
|
|
cpu.Map( 0x4016 ).Set( this, &VsSystem::Peek_4016, &VsSystem::Poke_4016 );
|
|
cpu.Map( 0x4017 ).Set( this, &VsSystem::Peek_4017, &VsSystem::Poke_4017 );
|
|
cpu.Map( 0x4020 ).Set( this, &VsSystem::Peek_4020, &VsSystem::Poke_4020 );
|
|
|
|
cpu.Map( 0x5000, 0x5FFF ).Set( this, &VsSystem::Peek_Nop, &VsSystem::Poke_Nop );
|
|
|
|
Reset();
|
|
}
|
|
|
|
void Cartridge::VsSystem::SaveState(State::Saver& state,const dword baseChunk) const
|
|
{
|
|
state.Begin( baseChunk );
|
|
|
|
state.Write8( coin );
|
|
SubSave( state );
|
|
|
|
state.End();
|
|
}
|
|
|
|
void Cartridge::VsSystem::LoadState(State::Loader& state)
|
|
{
|
|
coin = state.Read8();
|
|
|
|
while (const dword chunk = state.Begin())
|
|
{
|
|
SubLoad( state, chunk );
|
|
state.End();
|
|
}
|
|
}
|
|
|
|
#ifdef NST_MSVC_OPTIMIZE
|
|
#pragma optimize("", on)
|
|
#endif
|
|
|
|
NES_PEEK_A(Cartridge::VsSystem,Nop)
|
|
{
|
|
return address >> 8;
|
|
}
|
|
|
|
NES_POKE(Cartridge::VsSystem,Nop)
|
|
{
|
|
}
|
|
|
|
NES_PEEK_A(Cartridge::VsSystem,4016)
|
|
{
|
|
return dips.Reg(0) | (p4016.Peek( address ) & (STATUS_4016_MASK^0xFFU));
|
|
}
|
|
|
|
NES_POKE_AD(Cartridge::VsSystem,4016)
|
|
{
|
|
p4016.Poke( address, data );
|
|
}
|
|
|
|
NES_PEEK_A(Cartridge::VsSystem,4017)
|
|
{
|
|
return dips.Reg(1) | (p4017.Peek( address ) & (STATUS_4017_MASK^0xFFU));
|
|
}
|
|
|
|
NES_POKE_AD(Cartridge::VsSystem,4017)
|
|
{
|
|
p4017.Poke( address, data );
|
|
}
|
|
|
|
NES_PEEK(Cartridge::VsSystem,4020)
|
|
{
|
|
return coin;
|
|
}
|
|
|
|
NES_POKE_D(Cartridge::VsSystem,4020)
|
|
{
|
|
coin = data;
|
|
}
|
|
}
|
|
}
|