cleanup Atari2600 mapper code

This commit is contained in:
adelikat 2020-03-18 15:46:17 -05:00
parent a61230e4ab
commit 8f860adf51
31 changed files with 740 additions and 960 deletions

View File

@ -2,9 +2,6 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
Mapper used for multi-cart 2K games
*/
internal class Multicart2K : MapperBase
{
private int _gameTotal;
@ -28,15 +25,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
IncrementGame();
}
private void IncrementGame()
{
_currentGame++;
if (_currentGame >= _gameTotal)
{
_currentGame = 0;
}
}
public override byte ReadMemory(ushort addr)
{
@ -49,5 +37,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
public override byte PeekMemory(ushort addr) => ReadMemory(addr);
private void IncrementGame()
{
_currentGame++;
if (_currentGame >= _gameTotal)
{
_currentGame = 0;
}
}
}
}

View File

@ -2,9 +2,6 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
Mapper used for multi-cart 4K games
*/
internal class Multicart4K : MapperBase
{
private int _gameTotal;
@ -28,15 +25,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
IncrementGame();
}
private void IncrementGame()
{
_currentGame++;
if (_currentGame >= _gameTotal)
{
_currentGame = 0;
}
}
public override byte ReadMemory(ushort addr)
{
@ -49,5 +37,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
public override byte PeekMemory(ushort addr) => ReadMemory(addr);
private void IncrementGame()
{
_currentGame++;
if (_currentGame >= _gameTotal)
{
_currentGame = 0;
}
}
}
}

View File

@ -2,9 +2,6 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
Mapper used for multi-cart 8K games
*/
internal class Multicart8K : MapperBase
{
private int _bank4K;
@ -33,6 +30,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
IncrementGame();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void IncrementGame()
{
_currentGame++;
@ -57,16 +64,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF) + (_currentGame * 8192)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -80,16 +77,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8)

View File

@ -15,20 +15,20 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
0 1xxx xBxx xxxx
Each bit corresponds to one of the 13 address lines. a 0 or 1 means that bit must be
0 or 1 to trigger the bankswitch. x is a bit that is not concidered (it can be either
0 or 1 to trigger the bankswitch. x is a bit that is not considered (it can be either
0 or 1 and is thus a "don't care" bit).
B is the bank we will select. sooo, accessing 0800 will select bank 0, and 0840
B is the bank we will select. So, accessing 0800 will select bank 0, and 0840
will select bank 1.
*/
internal class m0840 : MapperBase
internal class m0840 : MapperBase
{
private int _bank4K;
public m0840(Atari2600 core) : base(core)
{
}
private int _bank4K;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
@ -41,6 +41,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -56,16 +66,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -79,27 +79,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
switch (addr & 0x1840)
_bank4K = (addr & 0x1840) switch
{
case 0x0800:
_bank4K = 0;
break;
case 0x0840:
_bank4K = 1;
break;
}
0x0800 => 0,
0x0840 => 1,
_ => _bank4K
};
}
}
}

View File

@ -6,7 +6,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
3E (Boulderdash
-----
This works similar to 3F (Tigervision) above, except RAM has been added. The range of
This works similar to 3F (TigerVision) above, except RAM has been added. The range of
addresses has been restricted, too. Only 3E and 3F can be written to now.
1000-17FF - this bank is selectable
@ -16,7 +16,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
8 bits, there's enough for 256 2K banks, or a maximum of 512K of ROM.
Writing to 3E, however, is what's new. Writing here selects a 1K RAM bank into
1000-17FF. The example (Boulderdash) uses 16K of RAM, however there's theoretically
1000-17FF. The example (BoulderDash) uses 16K of RAM, however there's theoretically
enough space for 256K of RAM. When RAM is selected, 1000-13FF is the read port while
1400-17FF is the write port.
*/
@ -26,8 +26,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
}
private int _lowbank2K;
private int _rambank1K;
private int _lowBank2K;
private int _ramBank1K;
private bool _hasRam;
private byte[] _ram = new byte[256 * 1024]; // Up to 256k
@ -36,16 +36,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("lowbank_2k", ref _lowbank2K);
ser.Sync("rambank_1k", ref _rambank1K);
ser.Sync("lowbank_2k", ref _lowBank2K);
ser.Sync("rambank_1k", ref _ramBank1K);
ser.Sync("cart_ram", ref _ram, false);
ser.Sync("hasRam", ref _hasRam);
}
public override void HardReset()
{
_lowbank2K = 0;
_rambank1K = 0;
_lowBank2K = 0;
_ramBank1K = 0;
_hasRam = false;
_ram = new byte[256 * 1024];
base.HardReset();
@ -64,27 +64,30 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
if (addr < 0x1400)
{
return _ram[(addr & 0x03FF) + (_rambank1K << 10)];
return _ram[(addr & 0x03FF) + (_ramBank1K << 10)];
}
return _ram[(addr & 0x03FF) + (_rambank1K << 10)] = 0xFF; // Reading from the write port triggers an unwanted write
return _ram[(addr & 0x03FF) + (_ramBank1K << 10)] = 0xFF; // Reading from the write port triggers an unwanted write
}
return Core.Rom[(_lowbank2K << 11) + (addr & 0x07FF)];
return Core.Rom[(_lowBank2K << 11) + (addr & 0x07FF)];
}
if (addr < 0x2000) // High bank fixed to last 2k of ROM
{
return Core.Rom[(Core.Rom.Length - 0x800) + (addr & 0x07FF)];
return Core.Rom[Core.Rom.Length - 0x800 + (addr & 0x07FF)];
}
return base.ReadMemory(addr);
}
public override byte PeekMemory(ushort addr)
{
return ReadMemory(addr);
}
public override byte PeekMemory(ushort addr) => ReadMemory(addr);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void WriteMem(ushort addr, byte value, bool poke)
{
@ -93,18 +96,18 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (addr == 0x003E)
{
_hasRam = true;
_rambank1K = value;
_ramBank1K = value;
}
else if (addr == 0x003F)
{
_hasRam = false;
if (value << 11 < Core.Rom.Length)
{
_lowbank2K = value;
_lowBank2K = value;
}
else
{
_lowbank2K = value & (Core.Rom.Length >> 11);
_lowBank2K = value & (Core.Rom.Length >> 11);
}
}
}
@ -119,18 +122,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (addr < 0x1800) // Write port
{
_ram[(_rambank1K << 10) + (addr & 0x3FF)] = value;
_ram[(_ramBank1K << 10) + (addr & 0x3FF)] = value;
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
}
}

View File

@ -3,11 +3,11 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
3F (Tigervision)
3F (TigerVision)
-----
Traditionally, this method was used on the Tigervision games. The ROMs were all 8K, and
there's two 2K pages in the 4K of address space. The upper bank is fixed to the last 2K
Traditionally, this method was used on the TigerVision games. The ROMs were all 8K, and
there's two 2K pages in the 4K of address space. The upper bank is fixed to the last 2K
of the ROM.
The first 2K is selectable by writing to any location between 0000 and 003F. Yes, this
@ -17,27 +17,26 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
The homebrew community has decided that if 8K is good, more ROM is better! This mapper
can support up to 512K bytes of ROM just by implementing all 8 bits on the mapper
register, and this has been done... however I do not think 512K ROMs have been made just
register, and this has been done... however do not think 512K ROMs have been made just
yet.
*/
internal class m3F : MapperBase
{
private int _lowBank2K;
public m3F(Atari2600 core) : base(core)
{
}
private int _lowbank2K;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("lowbank_2k", ref _lowbank2K);
ser.Sync("lowbank_2k", ref _lowBank2K);
}
public override void HardReset()
{
_lowbank2K = 0;
_lowBank2K = 0;
base.HardReset();
}
@ -50,21 +49,24 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (addr < 0x1800) // Low 2k Bank
{
return Core.Rom[(_lowbank2K << 11) + (addr & 0x07FF)];
return Core.Rom[(_lowBank2K << 11) + (addr & 0x07FF)];
}
if (addr < 0x2000) // High bank fixed to last 2k of ROM
{
return Core.Rom[(Core.Rom.Length - 2048) + (addr & 0x07FF)];
return Core.Rom[Core.Rom.Length - 2048 + (addr & 0x07FF)];
}
return base.ReadMemory(addr);
}
public override byte PeekMemory(ushort addr)
{
return ReadMemory(addr);
}
public override byte PeekMemory(ushort addr) => ReadMemory(addr);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void WriteMem(ushort addr, byte value, bool poke)
{
@ -74,26 +76,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
if ((value << 11) < Core.Rom.Length)
{
_lowbank2K = value;
_lowBank2K = value;
}
else
{
_lowbank2K = value & (Core.Rom.Length >> 11);
_lowBank2K = value & (Core.Rom.Length >> 11);
}
}
}
base.WriteMemory(addr, value);
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
}
}

View File

@ -3,7 +3,7 @@ using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/* From Kebtris docs
/* From Kevtris docs
4A50 (no name)
-----
@ -15,7 +15,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
One major problem is that it specifies that memory can be read and written
to at the same address, but this is nearly impossible to detect on a 2600
cartridge. You'd almost have to try and figure out what opcodes are being
cartridge. You'd almost have to try and figure out what OpCodes are being
run, and what cycle it's on somehow, all just by watching address and
data bus state. Not very practical.
@ -23,13 +23,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
There's just tons and tons of unnecessary things like attempting to detect
BIT instructions, handling page wraps and other silly things.
This all supposidly fit into a Xilinx XC9536XL but I am not sure how the
This all supposedly fit into a Xilinx XC9536XL but I am not sure how the
chip could handle the RAM issue above at all. It almost needs to see R/W
and M2 (clock) to be able to properly do most of the things it's doing.
*/
/* From Stella docs
Bankswitching method as defined/created by John Payson (aka Supercat),
Bankswitching method as defined/created by John Payson (aka SuperCat),
documented at http://www.casperkitty.com/stella/cartfmt.htm.
In this bankswitching scheme the 2600's 4K cartridge address space
@ -43,10 +43,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal class m4A50 : MapperBase
{
public m4A50(Atari2600 core) : base(core)
{
}
private byte[] _ram = new byte[32768];
private byte _lastData = 0xFF;
@ -61,6 +57,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private int _sliceMiddle;
private byte[] _romImage;
public m4A50(Atari2600 core) : base(core)
{
}
private byte[] RomImage
{
get
@ -129,6 +130,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, poke: false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, poke: true);
private byte ReadMem(ushort addr, bool peek)
{
byte val = 0;
@ -142,27 +153,31 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (addr < 0x1800) // 2K region from 0x1000 - 0x17ff
{
val = _isRomLow ? RomImage[(addr & 0x7ff) + _sliceLow]
: _ram[(addr & 0x7ff) + _sliceLow];
val = _isRomLow
? RomImage[(addr & 0x7ff) + _sliceLow]
: _ram[(addr & 0x7ff) + _sliceLow];
}
else if (addr < 0x1E00) // 1.5K region from 0x1800 - 0x1dff
{
val = _isRomMiddle ? RomImage[(addr & 0x7ff) + _sliceMiddle + 0x10000]
: _ram[(addr & 0x7ff) + _sliceMiddle];
val = _isRomMiddle
? RomImage[(addr & 0x7ff) + _sliceMiddle + 0x10000]
: _ram[(addr & 0x7ff) + _sliceMiddle];
}
else if (addr < 0x1F00) // 256B region from 0x1e00 - 0x1eff
{
val = _isRomHigh ? RomImage[(addr & 0xff) + _sliceHigh + 0x10000]
: _ram[(addr & 0xff) + _sliceHigh];
val = _isRomHigh
? RomImage[(addr & 0xff) + _sliceHigh + 0x10000]
: _ram[(addr & 0xff) + _sliceHigh];
}
else if (addr < 0x2000) // 256B region from 0x1f00 - 0x1fff
{
val = RomImage[(addr & 0xff) + (RomImage.Length - 256)];
if ((_lastData & 0xe0) == 0x60 && (_lastAddress >= 0x1000 ||
_lastAddress < 0x200) && !peek)
if ((_lastData & 0xe0) == 0x60 && (_lastAddress >= 0x1000
|| _lastAddress < 0x200) && !peek)
{
_sliceHigh = (_sliceHigh & 0xf0ff) | ((addr & 0x8) << 8) |
((addr & 0x70) << 4);
_sliceHigh = (_sliceHigh & 0xf0ff)
| ((addr & 0x8) << 8)
| ((addr & 0x70) << 4);
}
}
@ -175,16 +190,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return val;
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (addr < 0x1000) // Hotspots below 0x1000
@ -218,11 +223,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (addr < 0x2000 && !poke) // 256B region at 0x1f00 - 0x1fff
{
if (((_lastData & 0xe0) == 0x60) &&
(_lastAddress >= 0x1000 || (_lastAddress < 0x200)) && !poke)
if ((_lastData & 0xe0) == 0x60
&& (_lastAddress >= 0x1000 || _lastAddress < 0x200))
{
_sliceHigh = (_sliceHigh & 0xf0ff) | ((addr & 0x8) << 8) |
((addr & 0x70) << 4);
_sliceHigh = (_sliceHigh & 0xf0ff)
| ((addr & 0x8) << 8)
| ((addr & 0x70) << 4);
}
}
@ -233,20 +239,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void CheckBankSwitch(ushort address, byte value)
{
if (((_lastData & 0xe0) == 0x60) && // Switch lower/middle/upper bank
((_lastAddress >= 0x1000) || (_lastAddress < 0x200)))
if ((_lastData & 0xe0) == 0x60 // Switch lower/middle/upper bank
&& (_lastAddress >= 0x1000 || _lastAddress < 0x200))
{
if ((address & 0x0f00) == 0x0c00) // Enable 256B of ROM at 0x1e00 - 0x1eff
{
@ -280,19 +276,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if ((address & 0x0f00) == 0x0400) // Toggle bit A11 of lower block address
{
_sliceLow = _sliceLow ^ 0x800;
_sliceLow ^= 0x800;
}
else if ((address & 0x0f00) == 0x0500) // Toggle bit A12 of lower block address
{
_sliceLow = _sliceLow ^ 0x1000;
_sliceLow ^= 0x1000;
}
else if ((address & 0x0f00) == 0x0800) // Toggle bit A11 of middle block address
{
_sliceMiddle = _sliceMiddle ^ 0x800;
_sliceMiddle ^= 0x800;
}
else if ((address & 0x0f00) == 0x0900) // Toggle bit A12 of middle block address
{
_sliceMiddle = _sliceMiddle ^ 0x1000;
_sliceMiddle ^= 0x1000;
}
}

View File

@ -1,87 +1,38 @@
using System;
using System.Linq;
using BizHawk.Common;
/*
This is the cartridge class for Arcadia (aka Starpath) Supercharger
games. Christopher Salomon provided most of the technical details
used in creating this class. A good description of the Supercharger
is provided in the Cuttle Cart's manual.
The Supercharger has four 2K banks. There are three banks of RAM
and one bank of ROM. All 6K of the RAM can be read and written.
D7-D5 of this byte: Write Pulse Delay (n/a for emulator)
D4-D0: RAM/ROM configuration:
$F000-F7FF $F800-FFFF Address range that banks map into
000wp 2 ROM
001wp 0 ROM
010wp 2 0 as used in Commie Mutants and many others
011wp 0 2 as used in Suicide Mission
100wp 2 ROM
101wp 1 ROM
110wp 2 1 as used in Killer Satellites
111wp 1 2 as we use for 2k/4k ROM cloning
w = Write Enable (1 = enabled; accesses to $F000-$F0FF cause writes
to happen. 0 = disabled, and the cart acts like ROM.)
p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
wanting to access the ROM for multiloads. Otherwise set to 1.
*/
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
This is the cartridge class for Arcadia (aka StarPath) Supercharger
games. Christopher Salomon provided most of the technical details
used in creating this class. A good description of the Supercharger
is provided in the Cuttle Cart's manual.
The Supercharger has four 2K banks. There are three banks of RAM
and one bank of ROM. All 6K of the RAM can be read and written.
D7-D5 of this byte: Write Pulse Delay (n/a for emulator)
D4-D0: RAM/ROM configuration:
$F000-F7FF $F800-FFFF Address range that banks map into
000wp 2 ROM
001wp 0 ROM
010wp 2 0 as used in Commie Mutants and many others
011wp 0 2 as used in Suicide Mission
100wp 2 ROM
101wp 1 ROM
110wp 2 1 as used in Killer Satellites
111wp 1 2 as we use for 2k/4k ROM cloning
w = Write Enable (1 = enabled; accesses to $F000-$F0FF cause writes
to happen. 0 = disabled, and the cart acts like ROM.)
p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
wanting to access the ROM for multi-loads. Otherwise set to 1.
*/
internal class mAR : MapperBase
{
public mAR(Atari2600 core) : base(core)
{
InitializeSettings();
}
private byte[] _superChargerImage = new byte[8192];
private int[] _imageOffsets = new int[2];
private bool _writePending;
private int _distinctAccesses;
private bool _writeEnabled;
private byte _dataHoldRegister;
private byte _numberOfLoadImages;
private byte[] _loadedImages;
private byte[] _header = new byte[256];
private bool _powerIndicator; // Indicates if the ROM's power is on or off
private int _powerRomCycle; // Indicates when the power was last turned on
private int _size;
private ulong _elapsedCycles;
private void InitializeSettings()
{
// TODO: clean this stuff up
/*****************************************/
int size = Core.Rom.Length;
_size = Core.Rom.Length < 8448 ? 8448 : Core.Rom.Length; // 8448 or Rom size, whichever is bigger
_numberOfLoadImages = (byte)(_size / 8448);
// TODO: why are we making a redundant copy?
_loadedImages = new byte[_size];
for (int i = 0; i < size; i++)
{
_loadedImages[i] = Core.Rom[i];
}
if (size < 8448)
{
for (int i = size; i < _size; i++)
{
_loadedImages[i] = _defaultHeader[i];
}
}
/*****************************************/
InitializeRom();
BankConfiguration(0);
}
#region SuperCharger Data
private readonly byte[] _dummyRomCode =
@ -163,6 +114,25 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
#endregion
private byte[] _superChargerImage = new byte[8192];
private int[] _imageOffsets = new int[2];
private bool _writePending;
private int _distinctAccesses;
private bool _writeEnabled;
private byte _dataHoldRegister;
private byte _numberOfLoadImages;
private byte[] _loadedImages;
private byte[] _header = new byte[256];
private bool _powerIndicator; // Indicates if the ROM's power is on or off
private int _powerRomCycle; // Indicates when the power was last turned on
private int _size;
private ulong _elapsedCycles;
public mAR(Atari2600 core) : base(core)
{
InitializeSettings();
}
public override byte[] CartRam => _superChargerImage;
public override void HardReset()
@ -215,6 +185,46 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_elapsedCycles++;
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void InitializeSettings()
{
// TODO: clean this stuff up
/*****************************************/
int size = Core.Rom.Length;
_size = Core.Rom.Length < 8448 ? 8448 : Core.Rom.Length; // 8448 or Rom size, whichever is bigger
_numberOfLoadImages = (byte)(_size / 8448);
// TODO: why are we making a redundant copy?
_loadedImages = new byte[_size];
for (int i = 0; i < size; i++)
{
_loadedImages[i] = Core.Rom[i];
}
if (size < 8448)
{
for (int i = size; i < _size; i++)
{
_loadedImages[i] = _defaultHeader[i];
}
}
/*****************************************/
InitializeRom();
BankConfiguration(0);
}
private byte ReadMem(ushort addr, bool peek)
{
if (addr < 0x1000)
@ -274,16 +284,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return _superChargerImage[(addr & 0x07FF) + _imageOffsets[((addr & 0x800) > 0) ? 1 : 0]];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (addr < 0x1000)
@ -330,16 +330,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void InitializeRom()
{
/* scrom.asm data borrowed from Stella:
@ -394,7 +384,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// w = Write Enable (1 = enabled; accesses to $F000-$F0FF cause writes
// to happen. 0 = disabled, and the cart acts like ROM.)
// p = ROM Power (0 = enabled, 1 = off.) Only power the ROM if you're
// wanting to access the ROM for multiloads. Otherwise set to 1.
// wanting to access the ROM for multi-loads. Otherwise set to 1.
//_bank2k = configuration & 0x1F; // remember for the bank() method
_powerIndicator = !((configuration & 0x01) > 0);
@ -468,7 +458,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
int bank = _header[16 + j] & 0x03;
int page = (_header[16 + j] >> 2) & 0x07;
var src = _loadedImages.Skip((image * 8448) + (j * 256)).Take(256).ToArray();
var src = _loadedImages
.Skip((image * 8448) + (j * 256))
.Take(256)
.ToArray();
byte sum = (byte)(Checksum(src) + _header[16 + j] + _header[64 + j]);
if (!invalidPageChecksumSeen && (sum != 0x55))
@ -498,7 +492,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
byte sum = 0;
for (int i = 0; i < s.Count(); i++)
for (int i = 0; i < s.Length; i++)
{
sum += s[i];
}

View File

@ -6,7 +6,7 @@ using BizHawk.Common.NumberExtensions;
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
* Spectravideo Compumate Add-on Kevtris Documentation
Spectra-video Compumate Add-on Kevtris Documentation
This is more than just a cartridge mapper- it's also a "computer" add-on.
There's two 8K EPROMs soldered on top of each other. There's two short
@ -47,7 +47,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
1000-1FFF : selectable 4K ROM bank (selected by D0, D1 on portA)
On powerup, the port is all 1's, so the last bank of ROM is enabled, RAM is
On power up, the port is all 1's, so the last bank of ROM is enabled, RAM is
disabled.
when RAM is enabled:
@ -70,7 +70,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Bit 6 of portA clocks the 4017. Each rising edge advances the column one
count.
There's 10 columns labelled 0-9, and 4 rows, labelled 0-3.
There's 10 columns labeled 0-9, and 4 rows, labeled 0-3.
Column
@ -104,8 +104,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
/*
* Spectravideo Compumate Add-on Stella Documentation
Cartridge class used for SpectraVideo CompuMate bankswitched games.
* SpectraVideo Compumate Add-on Stella Documentation
Cartridge class used for SpectraVideo Compumate bankswitched games.
This is more than just a cartridge mapper - it's also a "computer" add-on.
There's two 8K EPROMs soldered on top of each other. There's two short
@ -129,12 +129,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
D1 = bank select high bit
D0 = bank select low bit
INPT0: D7 = FUNC key input (0 on startup / 1 = key pressed)
INPT1: D7 = always HIGH input (pulled high thru 20K resistor)
INPT2: D7 = always HIGH input (pulled high thru 20K resistor)
INPT3: D7 = SHIFT key input (0 on startup / 1 = key pressed)
INPT4: D7 = keyboard row 0 input (0 = key pressed)
INPT5: D7 = keyboard row 2 input (0 = key pressed)
INPUT0: D7 = FUNC key input (0 on startup / 1 = key pressed)
INPUT1: D7 = always HIGH input (pulled high thru 20K resistor)
INPUT2: D7 = always HIGH input (pulled high thru 20K resistor)
INPUT3: D7 = SHIFT key input (0 on startup / 1 = key pressed)
INPUT4: D7 = keyboard row 0 input (0 = key pressed)
INPUT5: D7 = keyboard row 2 input (0 = key pressed)
The keyboard's composed of a 4017 1 of 10 counter, driving the 10 columns of
the keyboard. It has 4 rows. The 4 row outputs are buffered by inverters.
@ -145,7 +145,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Bit 6 of portA clocks the 4017. Each rising edge advances the column one
count.
There's 10 columns labelled 0-9, and 4 rows, labelled 0-3.
There's 10 columns labeled 0-9, and 4 rows, labeled 0-3.
Column
@ -218,11 +218,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.SyncState(ser);
}
private byte ReadMem(ushort addr, bool peek)
{
public override byte ReadMemory(ushort addr)
{
// A unique feature of the keyboard is that it changes the operation of inputs 0-3
// by holding them high in the no-button-pressed state.
// However exposing this behaviour to the rest of the system would be overly cunmbersome
// However exposing this behaviour to the rest of the system would be overly cumbersome
// so instead we bypass these cases here
if ((addr & 0x000F) == 8 && (addr & 0x1080) == 0 && addr < 1000)
{
@ -278,19 +278,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
throw new Exception("this hasn't been tested");
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr) => ReadMemory(addr);
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr,true);
}
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void WriteMem(ushort addr, byte value, bool poke)
{
// Mimicking the 6532 logic for accessing port A, for testing
////var isPortA = false; // adelikat: Commented out this variable to remove a warning. Should this be deleted or is this supposed to be actually used?
if ((addr & 0x0200) == 0) // If the RS bit is not set, this is a ram write
@ -321,7 +318,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
if (addr == 0x280 && !poke) // Stella uses only 280
////if (isPortA && !poke)
////if (isPortA && !poke)
{
var bit5 = value.Bit(5);
var bit4 = value.Bit(4);
@ -361,15 +358,5 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.WriteMemory(addr, value);
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, true);
}
}
}

View File

@ -17,12 +17,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mCV : MapperBase
{
private byte[] _ram = new byte[1024];
public mCV(Atari2600 core) : base(core)
{
}
private byte[] _ram = new byte[1024];
public override byte[] CartRam => _ram;
public override void SyncState(Serializer ser)
@ -51,16 +51,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (addr >= 0x1800 && addr < 0x2000)
{
return Core.Rom[(addr & 0x7FF)];
return Core.Rom[addr & 0x7FF];
}
return base.ReadMemory(addr);
}
public override byte PeekMemory(ushort addr)
{
return ReadMemory(addr);
}
public override byte PeekMemory(ushort addr) => ReadMemory(addr);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void WriteMem(ushort addr, byte value, bool poke)
{
@ -70,18 +73,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (addr >= 0x1400 && addr < 0x1800)
{
_ram[(addr & 0x3FF)] = value;
_ram[addr & 0x3FF] = value;
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
}
}

View File

@ -12,12 +12,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
lots of the internal workings of the chip (number 4644495, "video memory system").
Interestingly, the patent shows the DPC as a *separate* device. You plug a
passthrough cartridge into your 2600, then plug the game cartridge into the
passthrough. Apparently, Activision thought that people wouldn't like this, or
pass-through cartridge into your 2600, then plug the game cartridge into the
pass-through. Apparently, Activision thought that people wouldn't like this, or
there was some other reasoning behind it and they ditched that idea and went with
the DPC inside the cartridge.
Unfortunately for Activision, it was filed in January of 1984, during the height of
Unfortunately for ActiVision, it was filed in January of 1984, during the height of
the crash. The inventor is listed as David Crane.
OK, enough background. Now onto the meat:
@ -139,7 +139,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Masking the data:
-----------------
1038-103F is the readback for the mask value
1038-103F is the read back for the mask value
1040-1047 is the start count
1048-104F is the end count
@ -221,14 +221,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Pitfall 2 just reads this location and stuffs it into the audio register every scanline or
so. The value read at 1004-1007 is the instantanious value generated by the fetchers and
mixing hardware.
*/
internal class mDPC : MapperBase
{
public mDPC(Atari2600 core) : base(core)
{
}
// Table for computing the input bit of the random number generator's
// shift register (it's the NOT of the EOR of four bits)
private readonly byte[] _randomInputBits = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 };
@ -245,6 +240,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private float _fractionalClocks; // Fractional DPC music OSC clocks unused during the last update
private byte[] _dspData;
public mDPC(Atari2600 core) : base(core)
{
}
public byte[] DspData => _dspData ??= Core.Rom.Skip(8192).Take(2048).ToArray();
public override void SyncState(Serializer ser)
@ -285,6 +285,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_elapsedCycles++;
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (addr < 0x1000)
@ -385,16 +395,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (addr < 0x1000)
@ -470,16 +470,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8)
@ -496,8 +486,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
// Using bits 7, 5, 4, & 3 of the shift register compute the input
// bit for the shift register
var bit = _randomInputBits[((_currentRandomVal >> 3) & 0x07) |
((_currentRandomVal & 0x80) > 0 ? 0x08 : 0x00)];
var bit = _randomInputBits[((_currentRandomVal >> 3) & 0x07)
| ((_currentRandomVal & 0x80) > 0 ? 0x08 : 0x00)];
// Update the shift register
_currentRandomVal = (byte)((_currentRandomVal << 1) | bit);

View File

@ -11,11 +11,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mDPCPlus : MapperBase
{
// TODO: PokeMem, and everything else
public mDPCPlus(Atari2600 core) : base(core)
{
throw new NotImplementedException();
}
// Table for computing the input bit of the random number generator's
// shift register (it's the NOT of the EOR of four bits)
private readonly byte[] _randomInputBits = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 };
private int[] _counters = new int[8];
private byte[] _tops = new byte[8];
@ -29,11 +27,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private float _fractionalClocks; // Fractional DPC music OSC clocks unused during the last update
private byte[] _dspData;
public byte[] DspData => _dspData ??= Core.Rom.Skip(8192).Take(2048).ToArray();
// Table for computing the input bit of the random number generator's
// shift register (it's the NOT of the EOR of four bits)
private readonly byte[] _randomInputBits = { 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1 };
// TODO: PokeMem, and everything else
public mDPCPlus(Atari2600 core) : base(core)
{
throw new NotImplementedException();
}
public byte[] DspData => _dspData ??= Core.Rom.Skip(8192).Take(2048).ToArray();
public override void SyncState(Serializer ser)
{
@ -73,6 +74,83 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_elapsedCycles++;
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
{
if (addr < 0x1000)
{
base.WriteMemory(addr, value);
return;
}
Address(addr);
ClockRandomNumberGenerator();
if (addr >= 0x1040 && addr < 0x1080)
{
var index = addr & 0x07;
var function = (addr >> 3) & 0x07;
switch (function)
{
// DFx top count
case 0x00:
_tops[index] = value;
_flags[index] = 0x00;
break;
// DFx bottom count
case 0x01:
_bottoms[index] = value;
break;
// DFx counter low
case 0x02:
if (index >= 5 && _musicModes[index - 5])
{
// Data fetcher is in music mode so its low counter value
// should be loaded from the top register not the poked value
_counters[index] = (_counters[index] & 0x0700) |
_tops[index];
}
else
{
// Data fetcher is either not a music mode data fetcher or it
// isn't in music mode so it's low counter value should be loaded
// with the poked value
_counters[index] = (_counters[index] & 0x0700) | value;
}
break;
// DFx counter high
case 0x03:
_counters[index] = (ushort)(((value & 0x07) << 8)
| (_counters[index] & 0x00ff));
// Execute special code for music mode data fetchers
if (index >= 5)
{
_musicModes[index - 5] = (value & 0x10) > 0;
// NOTE: We are not handling the clock source input for
// the music mode data fetchers. We're going to assume
// they always use the OSC input.
}
break;
// Random Number Generator Reset
case 0x06:
_currentRandomVal = 1;
break;
}
}
}
private byte ReadMem(ushort addr, bool peek)
{
if (addr < 0x1000)
@ -173,89 +251,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
public override void WriteMemory(ushort addr, byte value)
{
if (addr < 0x1000)
{
base.WriteMemory(addr, value);
return;
}
Address(addr);
ClockRandomNumberGenerator();
if (addr >= 0x1040 && addr < 0x1080)
{
var index = addr & 0x07;
var function = (addr >> 3) & 0x07;
switch (function)
{
// DFx top count
case 0x00:
_tops[index] = value;
_flags[index] = 0x00;
break;
// DFx bottom count
case 0x01:
_bottoms[index] = value;
break;
// DFx counter low
case 0x02:
if ((index >= 5) && _musicModes[index - 5])
{
// Data fetcher is in music mode so its low counter value
// should be loaded from the top register not the poked value
_counters[index] = (_counters[index] & 0x0700) |
_tops[index];
}
else
{
// Data fetcher is either not a music mode data fetcher or it
// isn't in music mode so it's low counter value should be loaded
// with the poked value
_counters[index] = (_counters[index] & 0x0700) | value;
}
break;
// DFx counter high
case 0x03:
_counters[index] = (ushort)(((value & 0x07) << 8) |
(_counters[index] & 0x00ff));
// Execute special code for music mode data fetchers
if (index >= 5)
{
_musicModes[index - 5] = (value & 0x10) > 0;
// NOTE: We are not handling the clock source input for
// the music mode data fetchers. We're going to assume
// they always use the OSC input.
}
break;
// Random Number Generator Reset
case 0x06:
_currentRandomVal = 1;
break;
}
}
}
private void Address(ushort addr)
{
if (addr == 0x1FF6)

View File

@ -22,17 +22,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Example Games:
Frogger II - Threedeep! (1983) (Parker Bros)
*/
internal class mE0 : MapperBase
{
public mE0(Atari2600 core) : base(core)
{
}
private int _toggle1;
private int _toggle2;
private int _toggle3;
public mE0(Atari2600 core) : base(core)
{
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
@ -49,6 +48,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, poke: false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, poke: true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -79,16 +88,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(7 * 1024) + (addr & 0x3FF)]; // 7 because final bank is always set to last
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -102,16 +101,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
switch (addr)

View File

@ -21,17 +21,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
is the read port.
1800-19FF also holds RAM. 1800-18FF is the write port, 1900-19FF is the read port.
Only 256 bytes of RAM is accessable at time, but there are four different 256 byte
banks making a total of 1K accessable here.
Only 256 bytes of RAM is accessible at time, but there are four different 256 byte
banks making a total of 1K accessible here.
Accessing 1FE8 through 1FEB select which 256 byte bank shows up.
*/
internal class mE7 : MapperBase
{
private const int RamBank1Offset = 1024;
private int _rombank1K;
private int _rambank1Toggle;
private int _romBank1K;
private int _ramBank1Toggle;
private byte[] _ram = new byte[2048];
private bool _enableRam0;
@ -43,16 +42,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("toggle", ref _rombank1K);
ser.Sync("toggle", ref _romBank1K);
ser.Sync("ram", ref _ram, false);
ser.Sync("EnableRam0", ref _enableRam0);
ser.Sync("rambank1_toggle", ref _rambank1Toggle);
ser.Sync("rambank1_toggle", ref _ramBank1Toggle);
}
public override void HardReset()
{
_rombank1K = 0;
_rambank1Toggle = 0;
_romBank1K = 0;
_ramBank1Toggle = 0;
_ram = new byte[2048];
_enableRam0 = false;
base.HardReset();
@ -60,6 +59,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public override byte[] CartRam => _ram;
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
private byte ReadMem(ushort addr, bool peek)
{
if (addr < 0x1000)
@ -84,17 +87,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return _ram[addr & 0x3FF];
}
return Core.Rom[(_rombank1K * 0x800) + (addr & 0x7FF)];
return Core.Rom[(_romBank1K * 0x800) + (addr & 0x7FF)];
}
if (addr < 0x1900) // Ram 1 Write port
{
return _ram[RamBank1Offset + (_rambank1Toggle * 0x100) + (addr & 0xFF)] = 0xFF; // Reading from the 256b write port @1800 riggers an unwanted write
return _ram[RamBank1Offset + (_ramBank1Toggle * 0x100) + (addr & 0xFF)] = 0xFF; // Reading from the 256b write port @1800 riggers an unwanted write
}
if (addr < 0x1A00) // Ram 1 Read port
{
return _ram[RamBank1Offset + (_rambank1Toggle * 0x100) + (addr & 0xFF)];
return _ram[RamBank1Offset + (_ramBank1Toggle * 0x100) + (addr & 0xFF)];
}
if (addr < 0x2000)
@ -108,15 +111,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return base.ReadMemory(addr);
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private void WriteMem(ushort addr, byte value, bool poke)
{
@ -135,61 +134,51 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (addr >= 0x1800 && addr < 0x1900)
{
_ram[RamBank1Offset + (addr & 0xFF) + (_rambank1Toggle * 0x100)] = value;
_ram[RamBank1Offset + (addr & 0xFF) + (_ramBank1Toggle * 0x100)] = value;
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
_enableRam0 = false;
switch (addr)
{
case 0x1FE0:
_rombank1K = 0;
_romBank1K = 0;
break;
case 0x1FE1:
_rombank1K = 1;
_romBank1K = 1;
break;
case 0x1FE2:
_rombank1K = 2;
_romBank1K = 2;
break;
case 0x1FE3:
_rombank1K = 3;
_romBank1K = 3;
break;
case 0x1FE4:
_rombank1K = 4;
_romBank1K = 4;
break;
case 0x1FE5:
_rombank1K = 5;
_romBank1K = 5;
break;
case 0x1FE6:
_rombank1K = 6;
_romBank1K = 6;
break;
case 0x1FE7:
_rombank1K = 7;
_romBank1K = 7;
_enableRam0 = true;
break;
case 0x1FE8:
_rambank1Toggle = 0;
_ramBank1Toggle = 0;
break;
case 0x1FE9:
_rambank1Toggle = 1;
_ramBank1Toggle = 1;
break;
case 0x1FEA:
_rambank1Toggle = 2;
_ramBank1Toggle = 2;
break;
case 0x1FEB:
_rambank1Toggle = 3;
_ramBank1Toggle = 3;
break;
}
}

View File

@ -11,7 +11,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
1FE0-1FEF. Accessing one of these will select the desired bank. 1FE0 = bank 0,
1FE1 = bank 1, etc.
*/
internal class mEF : MapperBase
{
private int _toggle;
@ -32,6 +31,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -47,16 +56,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -70,34 +69,28 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FE0) _toggle = 0;
if (addr == 0x1FE1) _toggle = 1;
if (addr == 0x1FE2) _toggle = 2;
if (addr == 0x1FE3) _toggle = 3;
if (addr == 0x1FE4) _toggle = 4;
if (addr == 0x1FE5) _toggle = 5;
if (addr == 0x1FE6) _toggle = 6;
if (addr == 0x1FE7) _toggle = 7;
if (addr == 0x1FE8) _toggle = 8;
if (addr == 0x1FE9) _toggle = 9;
if (addr == 0x1FEA) _toggle = 10;
if (addr == 0x1FEB) _toggle = 11;
if (addr == 0x1FEC) _toggle = 12;
if (addr == 0x1FED) _toggle = 13;
if (addr == 0x1FEE) _toggle = 14;
if (addr == 0x1FEF) _toggle = 15;
_toggle = addr switch
{
0x1FE0 => 0,
0x1FE1 => 1,
0x1FE2 => 2,
0x1FE3 => 3,
0x1FE4 => 4,
0x1FE5 => 5,
0x1FE6 => 6,
0x1FE7 => 7,
0x1FE8 => 8,
0x1FE9 => 9,
0x1FEA => 10,
0x1FEB => 11,
0x1FEC => 12,
0x1FED => 13,
0x1FEE => 14,
0x1FEF => 15,
_ => _toggle
};
}
}
}

View File

@ -9,29 +9,39 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mEFSC : MapperBase
{
private int _bank4K;
private byte[] _ram = new byte[128];
public mEFSC(Atari2600 core) : base(core)
{
}
private int _bank4k;
private byte[] _ram = new byte[128];
public override byte[] CartRam => _ram;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("bank4k", ref _bank4k);
ser.Sync("bank4k", ref _bank4K);
ser.Sync("auxRam", ref _ram, false);
}
public override void HardReset()
{
_bank4k = 0;
_bank4K = 0;
_ram = new byte[128];
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -52,20 +62,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (addr < 0x1100)
{
return _ram[(addr & 0x7F)];
return _ram[addr & 0x7F];
}
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
private void WriteMem(ushort addr, byte value, bool poke)
@ -85,34 +85,28 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FE0) _bank4k = 0;
if (addr == 0x1FE1) _bank4k = 1;
if (addr == 0x1FE2) _bank4k = 2;
if (addr == 0x1FE3) _bank4k = 3;
if (addr == 0x1FE4) _bank4k = 4;
if (addr == 0x1FE5) _bank4k = 5;
if (addr == 0x1FE6) _bank4k = 6;
if (addr == 0x1FE7) _bank4k = 7;
if (addr == 0x1FE8) _bank4k = 8;
if (addr == 0x1FE9) _bank4k = 9;
if (addr == 0x1FEA) _bank4k = 10;
if (addr == 0x1FEB) _bank4k = 11;
if (addr == 0x1FEC) _bank4k = 12;
if (addr == 0x1FED) _bank4k = 13;
if (addr == 0x1FEE) _bank4k = 14;
if (addr == 0x1FEF) _bank4k = 15;
_bank4K = addr switch
{
0x1FE0 => 0,
0x1FE1 => 1,
0x1FE2 => 2,
0x1FE3 => 3,
0x1FE4 => 4,
0x1FE5 => 5,
0x1FE6 => 6,
0x1FE7 => 7,
0x1FE8 => 8,
0x1FE9 => 9,
0x1FEA => 10,
0x1FEB => 11,
0x1FEC => 12,
0x1FED => 13,
0x1FEE => 14,
0x1FEF => 15,
_ => _bank4K
};
}
}
}

View File

@ -3,10 +3,10 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
F0 (Megaboy)
F0 (MegaBoy)
-----
This was used on one game, "megaboy".. Some kind of educational cartridge. It supports
This was used on one game, "MegaBoy".. Some kind of educational cartridge. It supports
64K of ROM making it the biggest single production game made during the original run
of the 2600.
@ -17,7 +17,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
bank is numbered by means of one of the ROM locations, and the code simply keeps accessing
1FF0 until the bank it is looking for comes up.
*/
internal class mF0 : MapperBase
{
private int _bank;
@ -38,6 +37,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -56,16 +65,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (addr < 0x1000)
@ -78,16 +77,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Increment()
{
_bank++;

View File

@ -9,7 +9,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Again, this works like F8 and F6 except now there's 8 4K banks. Selection is performed
by accessing 1FF4 through 1FFB.
*/
internal class mF4 :MapperBase
{
private int _toggle;
@ -30,6 +29,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -45,16 +54,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -68,27 +67,20 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF4) _toggle = 0;
if (addr == 0x1FF5) _toggle = 1;
if (addr == 0x1FF6) _toggle = 2;
if (addr == 0x1FF7) _toggle = 3;
if (addr == 0x1FF8) _toggle = 4;
if (addr == 0x1FF9) _toggle = 5;
if (addr == 0x1FF9) _toggle = 5;
if (addr == 0x1FFA) _toggle = 6;
if (addr == 0x1FFB) _toggle = 7;
_toggle = addr switch
{
0x1FF4 => 0,
0x1FF5 => 1,
0x1FF6 => 2,
0x1FF7 => 3,
0x1FF8 => 4,
0x1FF9 => 5,
0x1FFA => 6,
0x1FFB => 7,
_ => _toggle
};
}
}
}

View File

@ -8,7 +8,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mF4SC : MapperBase
{
private int _bank4k;
private int _bank4K;
private byte[] _ram = new byte[128];
public mF4SC(Atari2600 core) : base(core)
@ -20,17 +20,27 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("toggle", ref _bank4k);
ser.Sync("toggle", ref _bank4K);
ser.Sync("auxRam", ref _ram, false);
}
public override void HardReset()
{
_bank4k = 0;
_bank4K = 0;
_ram = new byte[128];
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -45,26 +55,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (addr < 0x1080)
{
_ram[(addr & 0x7F)] = 0xFF; // Reading from the write port triggers an unwanted write of open bus
_ram[addr & 0x7F] = 0xFF; // Reading from the write port triggers an unwanted write of open bus
return 0xFF; // 0xFF is used for deterministic emulation, in reality it would be a random value based on pins being high or low
}
if (addr < 0x1100)
{
return _ram[(addr & 0x7F)];
return _ram[addr & 0x7F];
}
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
private void WriteMem(ushort addr, byte value, bool poke)
@ -84,27 +84,20 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF4) _bank4k = 0;
if (addr == 0x1FF5) _bank4k = 1;
if (addr == 0x1FF6) _bank4k = 2;
if (addr == 0x1FF7) _bank4k = 3;
if (addr == 0x1FF8) _bank4k = 4;
if (addr == 0x1FF9) _bank4k = 5;
if (addr == 0x1FF9) _bank4k = 5;
if (addr == 0x1FFA) _bank4k = 6;
if (addr == 0x1FFB) _bank4k = 7;
_bank4K = addr switch
{
0x1FF4 => 0,
0x1FF5 => 1,
0x1FF6 => 2,
0x1FF7 => 3,
0x1FF8 => 4,
0x1FF9 => 5,
0x1FFA => 6,
0x1FFB => 7,
_ => _bank4K
};
}
}
}

View File

@ -13,12 +13,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal class mF6 : MapperBase
{
private int _toggle;
public mF6(Atari2600 core) : base(core)
{
}
private int _toggle;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
@ -46,15 +46,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
private void WriteMem(ushort addr, byte value, bool poke)
{
@ -70,21 +64,21 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
=> WriteMem(addr, value, true);
private void Address(ushort addr)
{
if (addr == 0x1FF6) _toggle = 0;
if (addr == 0x1FF7) _toggle = 1;
if (addr == 0x1FF8) _toggle = 2;
if (addr == 0x1FF9) _toggle = 3;
_toggle = addr switch
{
0x1FF6 => 0,
0x1FF7 => 1,
0x1FF8 => 2,
0x1FF9 => 3,
_ => _toggle
};
}
}
}

View File

@ -8,29 +8,39 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mF6SC : MapperBase
{
private int _bank4K;
private byte[] _ram = new byte[128];
public mF6SC(Atari2600 core) : base(core)
{
}
private int _bank4k;
private byte[] _ram = new byte[128];
public override byte[] CartRam => _ram;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("bank_4k", ref _bank4k);
ser.Sync("bank_4k", ref _bank4K);
ser.Sync("auxRam", ref _ram, false);
}
public override void HardReset()
{
_bank4k = 0;
_bank4K = 0;
_ram = new byte[128];
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -54,17 +64,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return _ram[(addr & 0x7F)];
}
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
private void WriteMem(ushort addr, byte value, bool poke)
@ -84,22 +84,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF6) _bank4k = 0;
if (addr == 0x1FF7) _bank4k = 1;
if (addr == 0x1FF8) _bank4k = 2;
if (addr == 0x1FF9) _bank4k = 3;
_bank4K = addr switch
{
0x1FF6 => 0,
0x1FF7 => 1,
0x1FF8 => 2,
0x1FF9 => 3,
_ => _bank4K
};
}
}
}

View File

@ -39,6 +39,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -54,16 +64,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -77,16 +77,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8)

View File

@ -8,22 +8,39 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mF8SC : MapperBase
{
private int _bank4K;
private byte[] _ram = new byte[128];
public mF8SC(Atari2600 core) : base(core)
{
}
private int _bank_4K;
private byte[] _ram = new byte[128];
public override byte[] CartRam => _ram;
public override void HardReset()
{
_bank_4K = 0;
_bank4K = 0;
_ram = new byte[128];
base.HardReset();
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("bank_4k", ref _bank4K);
ser.Sync("auxRam", ref _ram, false);
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -44,20 +61,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (addr < 0x1100)
{
return _ram[(addr & 0x7F)];
return _ram[addr & 0x7F];
}
return Core.Rom[(_bank_4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
private void WriteMem(ushort addr, byte value, bool poke)
@ -77,32 +84,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("bank_4k", ref _bank_4K);
ser.Sync("auxRam", ref _ram, false);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8)
{
_bank_4K = 0;
_bank4K = 0;
}
else if (addr == 0x1FF9)
{
_bank_4K = 1;
_bank4K = 1;
}
}
}

View File

@ -8,7 +8,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Apparently some of Sega's games have banks that are physically flipped, so even though this game uses a common mapper, the initial bank that gets pointed to is incorrect.
*/
internal class mF8_sega : MapperBase
{
private int _bank4K = 1;
@ -29,6 +28,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -44,16 +53,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -67,16 +66,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8)

View File

@ -13,7 +13,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
accessing 1FF8, 1FF9, and 1FFA. There's also 256 bytes of RAM mapped into 1000-11FF.
The write port is at 1000-10FF, and the read port is 1100-11FF.
*/
internal class mFA : MapperBase
{
private int _toggle;
@ -37,6 +36,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -62,16 +71,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -89,21 +88,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8) _toggle = 0;
if (addr == 0x1FF9) _toggle = 1;
if (addr == 0x1FFA) _toggle = 2;
_toggle = addr switch
{
0x1FF8 => 0,
0x1FF9 => 1,
0x1FFA => 2,
_ => _toggle
};
}
}
}

View File

@ -2,7 +2,7 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/**
/*
This is an extended version of the CBS RAM Plus bankswitching scheme
supported by the Harmony cartridge.
@ -10,29 +10,39 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
*/
internal class mFA2 : MapperBase
{
private int _bank4K;
private byte[] _ram = new byte[256];
public mFA2(Atari2600 core) : base(core)
{
}
private int _bank4k;
private byte[] _ram = new byte[256];
public override byte[] CartRam => _ram;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("bank4k", ref _bank4k);
ser.Sync("bank4k", ref _bank4K);
ser.Sync("auxRam", ref _ram, false);
}
public override void HardReset()
{
_bank4k = 0;
_bank4K = 0;
_ram = new byte[256];
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -55,17 +65,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return _ram[addr & 0xFF];
}
return Core.Rom[(_bank4k << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
private void WriteMem(ushort addr, byte value, bool poke)
@ -85,28 +85,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x1FF5) _bank4k = 0;
if (addr == 0x1FF6) _bank4k = 1;
if (addr == 0x1FF7) _bank4k = 2;
if (addr == 0x1FF8) _bank4k = 3;
if (addr == 0x1FF9) _bank4k = 4;
if (addr == 0x1FFA) _bank4k = 5;
if (addr == 0x1FFB && Core.Rom.Length == 28 * 1024) // Only available on 28k Roms
_bank4K = addr switch
{
_bank4k = 6;
}
0x1FF5 => 0,
0x1FF6 => 1,
0x1FF7 => 2,
0x1FF8 => 3,
0x1FF9 => 4,
0x1FFA => 5,
0x1FFB when Core.Rom.Length == 28 * 1024 => 6,
_ => _bank4K
};
}
}
}

View File

@ -3,10 +3,10 @@
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
MC (Megacart)
MC (MegaCart)
-----
This is the mapper for the "Chris Wilkson's Megacart".
This is the mapper for the "Chris Wilkson's MegaCart".
Only four addresses are used to bankswitch on this one.
@ -33,11 +33,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
says:
"
Megacart Specification, Rev1.1
MegaCart Specification, Rev1.1
(c) 1997 Chris Wilkson
cwilkson@mit.edu
Because the console's memory is randomized at powerup, there is no way to
Because the console's memory is randomized at power up, there is no way to
predict the data initially contained in the "hot addresses". Therefore,
hardware will force slot 3 to always point to ROM block $FF immediately
after any read or write to the RESET vector at $FFFC-$FFFD. Block $FF
@ -58,7 +58,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
address bus. An actual system doesn't have that luxury, unfortunately, so it must
disregard accesses to 3C-3F instead.
*/
internal class mMC : MapperBase
{
public mMC(Atari2600 core) : base(core)

View File

@ -9,12 +9,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal class mSB : MapperBase
{
private int _bank4K;
private int myStartBank => (Core.Rom.Length >> 12) - 1;
public mSB(Atari2600 core) : base(core)
{
}
private int MyStartBank => (Core.Rom.Length >> 12) - 1;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
@ -27,6 +28,18 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr)
=> ReadMem(addr, false);
public override byte PeekMemory(ushort addr)
=> ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -42,16 +55,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_bank4K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -65,22 +68,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
var temp = addr & (0x17FF + (Core.Rom.Length >> 12));
if ((temp & 0x1800) == 0x800)
{
_bank4K = temp & myStartBank;
_bank4K = temp & MyStartBank;
}
}
}

View File

@ -11,15 +11,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
Accessing 0220 will select the first bank, and accessing 0240 will select the second.
*/
internal class mUA : MapperBase
{
private int _toggle;
public mUA(Atari2600 core) : base(core)
{
}
private int _toggle;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
@ -32,6 +31,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -47,16 +56,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Core.Rom[(_toggle << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
}
private void WriteMem(ushort addr, byte value, bool poke)
{
if (!poke)
@ -70,16 +69,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if (addr == 0x0220)

View File

@ -35,24 +35,34 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal class mX07 : MapperBase
{
private int _romBank2K;
public mX07(Atari2600 core) : base(core)
{
}
private int _rombank2K;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("rombank_2k", ref _rombank2K);
ser.Sync("rombank_2k", ref _romBank2K);
}
public override void HardReset()
{
_rombank2K = 0;
_romBank2K = 0;
base.HardReset();
}
public override byte ReadMemory(ushort addr) => ReadMem(addr, false);
public override byte PeekMemory(ushort addr) => ReadMem(addr, true);
public override void WriteMemory(ushort addr, byte value)
=> WriteMem(addr, value, false);
public override void PokeMemory(ushort addr, byte value)
=> WriteMem(addr, value, true);
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
@ -65,17 +75,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return base.ReadMemory(addr);
}
return Core.Rom[(_rombank2K << 12) + (addr & 0xFFF)];
}
public override byte ReadMemory(ushort addr)
{
return ReadMem(addr, false);
}
public override byte PeekMemory(ushort addr)
{
return ReadMem(addr, true);
return Core.Rom[(_romBank2K << 12) + (addr & 0xFFF)];
}
private void WriteMem(ushort addr, byte value, bool poke)
@ -91,16 +91,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
public override void WriteMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: false);
}
public override void PokeMemory(ushort addr, byte value)
{
WriteMem(addr, value, poke: true);
}
private void Address(ushort addr)
{
if ((addr & 0x180F) == 0x080D)
@ -109,16 +99,16 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if ((addr & 0x1880) == 0)
{
if ((_rombank2K & 0xE) == 0xE)
if ((_romBank2K & 0xE) == 0xE)
{
Bank(((addr & 0x40) >> 6) | (_rombank2K & 0xE));
Bank(((addr & 0x40) >> 6) | (_romBank2K & 0xE));
}
}
}
private void Bank(int bank)
{
_rombank2K = bank & 0x0F;
_romBank2K = bank & 0x0F;
}
}
}

View File

@ -188,7 +188,9 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=aaaaaaa/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=aaaaaaaa/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=AARRGGBB/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ABCDEFGH/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=accum/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Activision/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=addr/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=adelikat/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ADPCM/@EntryIndexedValue">True</s:Boolean>
@ -198,6 +200,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Arkanoid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=assy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=assys/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Atariage/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=atten/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Attrib/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Attribs/@EntryIndexedValue">True</s:Boolean>
@ -214,6 +217,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=backbuffer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=backcolor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bandai/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bankswitch/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bankswitched/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=bankswitching/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Bezier/@EntryIndexedValue">True</s:Boolean>
@ -252,7 +256,9 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Coleco/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Colecovision/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=colesced/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Commavid/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Compositing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Compumate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Conout/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Coroutine/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Cpus/@EntryIndexedValue">True</s:Boolean>
@ -289,14 +295,18 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dontfire/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Dupped/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Ejin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=emucore/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Endian/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=endianess/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=endrift/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=EPRO/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Faaaaaaa/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Fairchild/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Famicom/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Famtasia/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FCEU/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFC/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFFFE/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=FFFFFFFF/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ffmpeg/@EntryIndexedValue">True</s:Boolean>
@ -317,6 +327,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Frameskip/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Frameskipping/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=framestart/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Frogger/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Frugalizer/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Frugalizers/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=gambatte/@EntryIndexedValue">True</s:Boolean>
@ -351,10 +362,12 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Justifier/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=keepalives/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kernings/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kevtris/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=KEYMENU/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Kopi/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=leadout/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Letterboxing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=LFSR/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Libretro/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Libsnes/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=libspeexdsp/@EntryIndexedValue">True</s:Boolean>
@ -373,6 +386,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=luaf/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=luases/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Lua_0027s/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Magicard/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Mainform/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mainmemory/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=mame/@EntryIndexedValue">True</s:Boolean>
@ -421,6 +435,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Palletize/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=passthru/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=pathing/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Payson/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCFX/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=PCSX/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=performant/@EntryIndexedValue">True</s:Boolean>
@ -459,6 +474,8 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=riffmaster/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=RLCA/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Roms/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=ROM_0027s/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Salomon/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=samp/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=samplerate/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Saturnus/@EntryIndexedValue">True</s:Boolean>
@ -470,6 +487,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=scanlines/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Screenshot/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Screensize/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=scrom/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=shaders/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=speccy/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Speedruns/@EntryIndexedValue">True</s:Boolean>
@ -500,6 +518,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Tastudio/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tasvideos/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tempfile/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Threedeep/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=tkey/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=toolform/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Trollers/@EntryIndexedValue">True</s:Boolean>
@ -549,6 +568,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=WRAM/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=WSWAN/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=XBOX/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xilinx/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xinput/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xjin/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Xploder/@EntryIndexedValue">True</s:Boolean>