Merge pull request #636 from alyosha-tas/master

More Bug Fixes
This commit is contained in:
hegyak 2016-05-28 06:17:21 -07:00
commit 3ef327e748
4 changed files with 163 additions and 112 deletions

View File

@ -36,10 +36,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if ((addr & 0x1080) == 0x0080) if ((addr & 0x1080) == 0x0080)
{ {
return M6532.ReadMemory(addr, false); _tia.bus_state = M6532.ReadMemory(addr, false);
return M6532.ReadMemory(addr, false);
} }
return Rom[addr & 0x0FFF]; _tia.bus_state = Rom[addr & 0x0FFF];
return Rom[addr & 0x0FFF];
} }
internal byte BasePeekMemory(ushort addr) internal byte BasePeekMemory(ushort addr)
@ -52,15 +54,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if ((addr & 0x1080) == 0x0080) if ((addr & 0x1080) == 0x0080)
{ {
return M6532.ReadMemory(addr, true); return M6532.ReadMemory(addr, true);
} }
return Rom[addr & 0x0FFF];
return Rom[addr & 0x0FFF];
} }
internal void BaseWriteMemory(ushort addr, byte value) internal void BaseWriteMemory(ushort addr, byte value)
{ {
if (addr != LastAddress) _tia.bus_state = value;
if (addr != LastAddress)
{ {
DistinctAccessCount++; DistinctAccessCount++;
LastAddress = addr; LastAddress = addr;
@ -69,7 +71,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
addr = (ushort)(addr & 0x1FFF); addr = (ushort)(addr & 0x1FFF);
if ((addr & 0x1080) == 0) if ((addr & 0x1080) == 0)
{ {
_tia.WriteMemory(addr, value); _tia.WriteMemory(addr, value, false);
} }
else if ((addr & 0x1080) == 0x0080) else if ((addr & 0x1080) == 0x0080)
{ {
@ -83,10 +85,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal void BasePokeMemory(ushort addr, byte value) internal void BasePokeMemory(ushort addr, byte value)
{ {
addr = (ushort)(addr & 0x1FFF); addr = (ushort)(addr & 0x1FFF);
if ((addr & 0x1080) == 0) if ((addr & 0x1080) == 0)
{ {
_tia.WriteMemory(addr, value); _tia.WriteMemory(addr, value, true);
} }
else if ((addr & 0x1080) == 0x0080) else if ((addr & 0x1080) == 0x0080)
{ {
@ -108,6 +110,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_mapper.Bit13 = addr.Bit(13); _mapper.Bit13 = addr.Bit(13);
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF)); var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF));
_tia.bus_state = temp;
MemoryCallbacks.CallReads(addr); MemoryCallbacks.CallReads(addr);
return temp; return temp;
@ -115,8 +118,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
internal byte PeekMemory(ushort addr) internal byte PeekMemory(ushort addr)
{ {
var temp = _mapper.ReadMemory((ushort)(addr & 0x1FFF)); var temp = _mapper.PeekMemory((ushort)(addr & 0x1FFF));
return temp; return temp;
} }

View File

@ -20,7 +20,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
16, 16,
MemoryDomain.Endian.Little, MemoryDomain.Endian.Little,
addr => _tia.ReadMemory((ushort)addr, true), addr => _tia.ReadMemory((ushort)addr, true),
(addr, value) => this._tia.WriteMemory((ushort)addr, value), 1), (addr, value) => this._tia.WriteMemory((ushort)addr, value, true), 1),
new MemoryDomainDelegate( new MemoryDomainDelegate(
"PIA", "PIA",
1024, 1024,

View File

@ -170,15 +170,17 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{ {
val = RomImage[(addr & 0xff) + (RomImage.Length - 256)]; val = RomImage[(addr & 0xff) + (RomImage.Length - 256)];
if (((_lastData & 0xe0) == 0x60) && ((_lastAddress >= 0x1000) || if (((_lastData & 0xe0) == 0x60) && ((_lastAddress >= 0x1000) ||
(_lastAddress < 0x200))) (_lastAddress < 0x200)) && !peek)
{ {
_sliceHigh = (_sliceHigh & 0xf0ff) | ((addr & 0x8) << 8) | _sliceHigh = (_sliceHigh & 0xf0ff) | ((addr & 0x8) << 8) |
((addr & 0x70) << 4); ((addr & 0x70) << 4);
} }
} }
if (!peek)
_lastData = val; {
_lastAddress = (ushort)(addr & 0x1fff); _lastData = val;
_lastAddress = (ushort)(addr & 0x1fff);
}
return val; return val;
} }
@ -226,7 +228,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else if (addr < 0x2000 && !poke) // 256B region at 0x1f00 - 0x1fff else if (addr < 0x2000 && !poke) // 256B region at 0x1f00 - 0x1fff
{ {
if (((_lastData & 0xe0) == 0x60) && if (((_lastData & 0xe0) == 0x60) &&
((_lastAddress >= 0x1000) || (_lastAddress < 0x200))) ((_lastAddress >= 0x1000) || (_lastAddress < 0x200)) && !poke)
{ {
_sliceHigh = (_sliceHigh & 0xf0ff) | ((addr & 0x8) << 8) | _sliceHigh = (_sliceHigh & 0xf0ff) | ((addr & 0x8) << 8) |
((addr & 0x70) << 4); ((addr & 0x70) << 4);
@ -252,96 +254,95 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private void CheckBankSwitch(ushort address, byte value) private void CheckBankSwitch(ushort address, byte value)
{ {
if (((_lastData & 0xe0) == 0x60) && // Switch lower/middle/upper bank if (((_lastData & 0xe0) == 0x60) && // Switch lower/middle/upper bank
((_lastAddress >= 0x1000) || (_lastAddress < 0x200))) ((_lastAddress >= 0x1000) || (_lastAddress < 0x200)))
{
if ((address & 0x0f00) == 0x0c00) // Enable 256B of ROM at 0x1e00 - 0x1eff
{
_isRomHigh = true;
_sliceHigh = (address & 0xff) << 8;
}
else if ((address & 0x0f00) == 0x0d00) // Enable 256B of RAM at 0x1e00 - 0x1eff
{
_isRomHigh = false;
_sliceHigh = (address & 0x7f) << 8;
}
else if ((address & 0x0f40) == 0x0e00) // Enable 2K of ROM at 0x1000 - 0x17ff
{
_isRomLow = true;
_sliceLow = (address & 0x1f) << 11;
}
else if ((address & 0x0f40) == 0x0e40) // Enable 2K of RAM at 0x1000 - 0x17ff
{
_isRomLow = false;
_sliceLow = (address & 0xf) << 11;
}
else if ((address & 0x0f40) == 0x0f00) // Enable 1.5K of ROM at 0x1800 - 0x1dff
{
_isRomMiddle = true;
_sliceMiddle = (address & 0x1f) << 11;
}
else if ((address & 0x0f50) == 0x0f40) // Enable 1.5K of RAM at 0x1800 - 0x1dff
{
_isRomMiddle = false;
_sliceMiddle = (address & 0xf) << 11;
}
else if ((address & 0x0f00) == 0x0400) // Toggle bit A11 of lower block address
{
_sliceLow = _sliceLow ^ 0x800;
}
else if ((address & 0x0f00) == 0x0500) // Toggle bit A12 of lower block address
{
_sliceLow = _sliceLow ^ 0x1000;
}
else if ((address & 0x0f00) == 0x0800) // Toggle bit A11 of middle block address
{
_sliceMiddle = _sliceMiddle ^ 0x800;
}
else if ((address & 0x0f00) == 0x0900) // Toggle bit A12 of middle block address
{
_sliceMiddle = _sliceMiddle ^ 0x1000;
}
}
// Zero-page hotspots for upper page
// 0xf4, 0xf6, 0xfc, 0xfe for ROM
// 0xf5, 0xf7, 0xfd, 0xff for RAM
// 0x74 - 0x7f (0x80 bytes lower)
if ((address & 0xf75) == 0x74) // Enable 256B of ROM at 0x1e00 - 0x1eff
{ {
if ((address & 0x0f00) == 0x0c00) // Enable 256B of ROM at 0x1e00 - 0x1eff _isRomHigh = true;
{ _sliceHigh = value << 8;
_isRomHigh = true; }
_sliceHigh = (address & 0xff) << 8; else if ((address & 0xf75) == 0x75) // Enable 256B of RAM at 0x1e00 - 0x1eff
} {
else if ((address & 0x0f00) == 0x0d00) // Enable 256B of RAM at 0x1e00 - 0x1eff _isRomHigh = false;
{ _sliceHigh = (value & 0x7f) << 8;
_isRomHigh = false; }
_sliceHigh = (address & 0x7f) << 8;
} // Zero-page hotspots for lower and middle blocks
else if ((address & 0x0f40) == 0x0e00) // Enable 2K of ROM at 0x1000 - 0x17ff // 0xf8, 0xf9, 0xfa, 0xfb
// 0x78, 0x79, 0x7a, 0x7b (0x80 bytes lower)
else if ((address & 0xf7c) == 0x78)
{
if ((value & 0xf0) == 0) // Enable 2K of ROM at 0x1000 - 0x17ff
{ {
_isRomLow = true; _isRomLow = true;
_sliceLow = (address & 0x1f) << 11; _sliceLow = (value & 0xf) << 11;
} }
else if ((address & 0x0f40) == 0x0e40) // Enable 2K of RAM at 0x1000 - 0x17ff else if ((value & 0xf0) == 0x40) // Enable 2K of RAM at 0x1000 - 0x17ff
{ {
_isRomLow = false; _isRomLow = false;
_sliceLow = (address & 0xf) << 11; _sliceLow = (value & 0xf) << 11;
} }
else if ((address & 0x0f40) == 0x0f00) // Enable 1.5K of ROM at 0x1800 - 0x1dff else if ((value & 0xf0) == 0x90) // Enable 1.5K of ROM at 0x1800 - 0x1dff
{ {
_isRomMiddle = true; _isRomMiddle = true;
_sliceMiddle = (address & 0x1f) << 11; _sliceMiddle = ((value & 0xf) | 0x10) << 11;
} }
else if ((address & 0x0f50) == 0x0f40) // Enable 1.5K of RAM at 0x1800 - 0x1dff else if ((value & 0xf0) == 0xc0) // Enable 1.5K of RAM at 0x1800 - 0x1dff
{ {
_isRomMiddle = false; _isRomMiddle = false;
_sliceMiddle = (address & 0xf) << 11; _sliceMiddle = (value & 0xf) << 11;
}
else if ((address & 0x0f00) == 0x0400) // Toggle bit A11 of lower block address
{
_sliceLow = _sliceLow ^ 0x800;
}
else if ((address & 0x0f00) == 0x0500) // Toggle bit A12 of lower block address
{
_sliceLow = _sliceLow ^ 0x1000;
}
else if ((address & 0x0f00) == 0x0800) // Toggle bit A11 of middle block address
{
_sliceMiddle = _sliceMiddle ^ 0x800;
}
else if ((address & 0x0f00) == 0x0900) // Toggle bit A12 of middle block address
{
_sliceMiddle = _sliceMiddle ^ 0x1000;
}
// Zero-page hotspots for upper page
// 0xf4, 0xf6, 0xfc, 0xfe for ROM
// 0xf5, 0xf7, 0xfd, 0xff for RAM
// 0x74 - 0x7f (0x80 bytes lower)
if ((address & 0xf75) == 0x74) // Enable 256B of ROM at 0x1e00 - 0x1eff
{
_isRomHigh = true;
_sliceHigh = value << 8;
}
else if ((address & 0xf75) == 0x75) // Enable 256B of RAM at 0x1e00 - 0x1eff
{
_isRomHigh = false;
_sliceHigh = (value & 0x7f) << 8;
}
// Zero-page hotspots for lower and middle blocks
// 0xf8, 0xf9, 0xfa, 0xfb
// 0x78, 0x79, 0x7a, 0x7b (0x80 bytes lower)
else if ((address & 0xf7c) == 0x78)
{
if ((value & 0xf0) == 0) // Enable 2K of ROM at 0x1000 - 0x17ff
{
_isRomLow = true;
_sliceLow = (value & 0xf) << 11;
}
else if ((value & 0xf0) == 0x40) // Enable 2K of RAM at 0x1000 - 0x17ff
{
_isRomLow = false;
_sliceLow = (value & 0xf) << 11;
}
else if ((value & 0xf0) == 0x90) // Enable 1.5K of ROM at 0x1800 - 0x1dff
{
_isRomMiddle = true;
_sliceMiddle = ((value & 0xf) | 0x10) << 11;
}
else if ((value & 0xf0) == 0xc0) // Enable 1.5K of RAM at 0x1800 - 0x1dff
{
_isRomMiddle = false;
_sliceMiddle = (value & 0xf) << 11;
}
} }
} }
} }

View File

@ -269,6 +269,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private int[] _palette; private int[] _palette;
public int bus_state;
private byte pf0_update; private byte pf0_update;
private byte pf1_update; private byte pf1_update;
private byte pf2_update; private byte pf2_update;
@ -289,6 +291,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private bool enam1_val; private bool enam1_val;
private bool enamb_val; private bool enamb_val;
private int vblank_delay;
private byte vblank_value;
private bool p0_stuff; private bool p0_stuff;
private bool p1_stuff; private bool p1_stuff;
private bool m0_stuff; private bool m0_stuff;
@ -415,10 +420,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_capChargeStart = 0; _capChargeStart = 0;
_capCharging = false; _capCharging = false;
_vblankEnabled = false; _vblankEnabled = false;
vblank_delay = 0;
vblank_value = 0;
_vsyncEnabled = false; _vsyncEnabled = false;
_CurrentScanLine = 0; _CurrentScanLine = 0;
_audioClocks = 0; _audioClocks = 0;
bus_state = 0;
pf0_update = 0; pf0_update = 0;
pf1_update = 0; pf1_update = 0;
pf2_update = 0; pf2_update = 0;
@ -472,6 +481,20 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{ {
// Still ignoring cycles... // Still ignoring cycles...
// delay vblank latch
if (vblank_delay > 0)
{
vblank_delay++;
if (vblank_delay==3)
{
_vblankEnabled = (vblank_value & 0x02) != 0;
vblank_delay = 0;
}
}
//delay latch to new playfield register //delay latch to new playfield register
if (pf0_updater == true) if (pf0_updater == true)
{ {
@ -716,7 +739,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
} }
} }
if (_playField.Score && !_playField.Priority && (collisions & CXPF) != 0 && _core.Settings.ShowPlayfield) if (_playField.Score && !_playField.Priority && ((collisions & CXPF) != 0) && _core.Settings.ShowPlayfield)
{ {
pixelColor = !rightSide ? _palette[_player0.Color] : _palette[_player1.Color]; pixelColor = !rightSide ? _palette[_player0.Color] : _palette[_player1.Color];
} }
@ -1047,44 +1070,55 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public byte ReadMemory(ushort addr, bool peek) public byte ReadMemory(ushort addr, bool peek)
{ {
var maskedAddr = (ushort)(addr & 0x000F); var maskedAddr = (ushort)(addr & 0x000F);
byte coll = 0;
int mask = 0;
if (maskedAddr == 0x00) // CXM0P if (maskedAddr == 0x00) // CXM0P
{ {
return (byte)((((_player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00)); coll=(byte)((((_player0.Missile.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXP0) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x01) // CXM1P if (maskedAddr == 0x01) // CXM1P
{ {
return (byte)((((_player1.Missile.Collisions & CXP0) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXP1) != 0) ? 0x40 : 0x00)); coll = (byte)((((_player1.Missile.Collisions & CXP0) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXP1) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x02) // CXP0FB if (maskedAddr == 0x02) // CXP0FB
{ {
return (byte)((((_player0.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Collisions & CXBL) != 0) ? 0x40 : 0x00)); coll = (byte)((((_player0.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Collisions & CXBL) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x03) // CXP1FB if (maskedAddr == 0x03) // CXP1FB
{ {
return (byte)((((_player1.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Collisions & CXBL) != 0) ? 0x40 : 0x00)); coll = (byte)((((_player1.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Collisions & CXBL) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x04) // CXM0FB if (maskedAddr == 0x04) // CXM0FB
{ {
return (byte)((((_player0.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00)); coll = (byte)((((_player0.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x05) // CXM1FB if (maskedAddr == 0x05) // CXM1FB
{ {
return (byte)((((_player1.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00)); coll = (byte)((((_player1.Missile.Collisions & CXPF) != 0) ? 0x80 : 0x00) | (((_player1.Missile.Collisions & CXBL) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x06) // CXBLPF if (maskedAddr == 0x06) // CXBLPF
{ {
return (byte)(((_ball.Collisions & CXPF) != 0) ? 0x80 : 0x00); coll = (byte)(((_ball.Collisions & CXPF) != 0) ? 0x80 : 0x00);
mask = 0x7f;
} }
if (maskedAddr == 0x07) // CXPPMM if (maskedAddr == 0x07) // CXPPMM
{ {
return (byte)((((_player0.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXM1) != 0) ? 0x40 : 0x00)); coll = (byte)((((_player0.Collisions & CXP1) != 0) ? 0x80 : 0x00) | (((_player0.Missile.Collisions & CXM1) != 0) ? 0x40 : 0x00));
mask = 0x3f;
} }
if (maskedAddr == 0x08) // INPT0 if (maskedAddr == 0x08) // INPT0
@ -1093,28 +1127,38 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// 6105 roughly centers the paddle in Breakout // 6105 roughly centers the paddle in Breakout
if (_capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= 6105) if (_capCharging && _core.Cpu.TotalExecutedCycles - _capChargeStart >= 6105)
{ {
return 0x80; coll=0x80;
} }
return 0x00; coll=0x00;
mask = 0x7f;
} }
if (maskedAddr == 0x0C) // INPT4 if (maskedAddr == 0x0C) // INPT4
{ {
return (byte)((_core.ReadControls1(peek) & 0x08) != 0 ? 0x80 : 0x00); coll = (byte)((_core.ReadControls1(peek) & 0x08) != 0 ? 0x80 : 0x00);
mask = 0x7f;
} }
if (maskedAddr == 0x0D) // INPT5 if (maskedAddr == 0x0D) // INPT5
{ {
return (byte)((_core.ReadControls2(peek) & 0x08) != 0 ? 0x80 : 0x00); coll = (byte)((_core.ReadControls2(peek) & 0x08) != 0 ? 0x80 : 0x00);
mask = 0x7f;
} }
return 0x00; //some bits of the databus will be undriven when a read call is made. Our goal here is to sort out what
// happens to the undriven pins. Most of the time, they will be in whatever state they were when previously
//assigned in some other bus access, so let's go with that.
coll+=(byte)(mask & bus_state);
if (!peek) bus_state = (int)coll;
return coll;
} }
public void WriteMemory(ushort addr, byte value) public void WriteMemory(ushort addr, byte value, bool poke)
{ {
var maskedAddr = (ushort)(addr & 0x3f); var maskedAddr = (ushort)(addr & 0x3f);
if (!poke) bus_state = value;
if (maskedAddr == 0x00) // VSYNC if (maskedAddr == 0x00) // VSYNC
{ {
@ -1145,7 +1189,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
} }
else if (maskedAddr == 0x01) // VBLANK else if (maskedAddr == 0x01) // VBLANK
{ {
_vblankEnabled = (value & 0x02) != 0; vblank_delay = 1;
vblank_value = value;
_capCharging = (value & 0x80) == 0; _capCharging = (value & 0x80) == 0;
if ((value & 0x80) == 0) if ((value & 0x80) == 0)
{ {
@ -1575,6 +1620,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("hsyncCnt", ref _hsyncCnt); ser.Sync("hsyncCnt", ref _hsyncCnt);
// add everything to the state // add everything to the state
ser.Sync("Bus_State", ref bus_state);
ser.Sync("PF0_up",ref pf0_update); ser.Sync("PF0_up",ref pf0_update);
ser.Sync("PF1_up", ref pf1_update); ser.Sync("PF1_up", ref pf1_update);
ser.Sync("PF2_up", ref pf2_update); ser.Sync("PF2_up", ref pf2_update);
@ -1613,7 +1660,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("Ticks", ref do_ticks); ser.Sync("Ticks", ref do_ticks);
ser.Sync("VBlankDelay", ref vblank_delay);
ser.Sync("VBlankValue", ref vblank_value);
// some of these things weren't in the state because they weren't needed if // some of these things weren't in the state because they weren't needed if
// states were always taken at frame boundaries // states were always taken at frame boundaries