HMove updatealyosha-tas says:"You can merge it now, I have nothing more to add to it."

HMove update

alyosha-tas says:
"You can merge it now, I have nothing more to add to it."
This commit is contained in:
hegyak 2016-05-21 10:55:25 -07:00
commit dbc23a1f4d
10 changed files with 1363 additions and 2596 deletions

View File

@ -241,6 +241,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_mapper = new mUA();
break;
// Special Sega Mapper which has swapped banks
case "F8_sega":
_mapper = new mF8_sega();
break;
// Homebrew mappers
case "3E":
_mapper = new m3E();

View File

@ -45,7 +45,15 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
game.AddOption("m", DetectMapper(rom));
}
if (Rom.HashSHA1() == "3A77DB43B6583E8689435F0F14AA04B9E57BDDED" ||
Rom.HashSHA1() == "E986E1818E747BEB9B33CE4DFF1CDC6B55BDB620")
{
game.RemoveOption("m");
game.AddOption("m", "F8_sega");
}
Console.WriteLine("Game uses mapper " + game.GetOptionsDict()["m"]);
Console.WriteLine(Rom.HashSHA1());
RebootCore();
SetupMemoryDomains();

View File

@ -74,13 +74,14 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
return Timer.Value;
}
// TODO: fix this to match real behaviour
// This is an undocumented instruction whose behaviour is more dynamic then indicated here
if ((registerAddr & 0x5) == 0x5)
{
// Read interrupt flag
if (Timer.InterruptEnabled && Timer.InterruptFlag)
if (Timer.InterruptFlag) //Timer.InterruptEnabled && )
{
return 0x80;
return 0xC0;
}
return 0x00;
@ -112,7 +113,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Write to Timer/1
Timer.PrescalerShift = 0;
Timer.Value = value;
Timer.PrescalerCount = 0;
Timer.PrescalerCount = 0;// 1 << Timer.PrescalerShift;
Timer.InterruptFlag = false;
}
else if (registerAddr == 0x05)
@ -120,7 +121,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Write to Timer/8
Timer.PrescalerShift = 3;
Timer.Value = value;
Timer.PrescalerCount = 0;
Timer.PrescalerCount = 0;// 1 << Timer.PrescalerShift;
Timer.InterruptFlag = false;
}
else if (registerAddr == 0x06)
@ -128,7 +129,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Write to Timer/64
Timer.PrescalerShift = 6;
Timer.Value = value;
Timer.PrescalerCount = 0;
Timer.PrescalerCount = 0;// 1 << Timer.PrescalerShift;
Timer.InterruptFlag = false;
}
else if (registerAddr == 0x07)
@ -136,7 +137,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Write to Timer/1024
Timer.PrescalerShift = 10;
Timer.Value = value;
Timer.PrescalerCount = 0;
Timer.PrescalerCount = 0;// 1 << Timer.PrescalerShift;
Timer.InterruptFlag = false;
}
}

View File

@ -0,0 +1,98 @@
using BizHawk.Common;
namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
/*
F8 (Atari style 8K)
-----
This is the fairly standard way 8K of cartridge ROM was implemented. There are two
4K ROM banks, which get mapped into the 4K of cartridge space. Accessing 1FF8 or
1FF9 selects one of the two 4K banks. When one of these two addresses are accessed,
the banks switch spontaniously.
ANY kind of access will trigger the switching- reading or writing. Usually games use
LDA or BIT on 1FF8/1FF9 to perform the switch.
When the switch occurs, the entire 4K ROM bank switches, including the code that is
reading the 1FF8/1FF9 location. Usually, games put a small stub of code in BOTH banks
so when the switch occurs, the code won't crash.
*/
internal class mF8_sega : MapperBase
{
private int _bank4K=1;
public override void SyncState(Serializer ser)
{
base.SyncState(ser);
ser.Sync("bank_4k", ref _bank4K);
}
public override void HardReset()
{
_bank4K = 1;
base.HardReset();
}
private byte ReadMem(ushort addr, bool peek)
{
if (!peek)
{
Address(addr);
}
if (addr < 0x1000)
{
return base.ReadMemory(addr);
}
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)
{
Address(addr);
}
if (addr < 0x1000)
{
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);
}
private void Address(ushort addr)
{
if (addr == 0x1FF8)
{
_bank4K = 0;
}
else if (addr == 0x1FF9)
{
_bank4K = 1;
}
}
}
}

View File

@ -245,6 +245,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
// TODO when sound timing is made exact:
// NTSC refclock is actually 315 / 88 mhz
//3546895
int clockrate = _pal ? 3546895 : 3579545;
int clocksperframe = 228 * NominalNumScanlines;
@ -268,39 +269,44 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private int[] _palette;
private int test_count_p0;
private int test_count_p1;
private int test_count_m0;
private int test_count_m1;
private int test_count_b;
private byte pf0_update;
private byte pf1_update;
private byte pf2_update;
private bool pf0_updater;
private bool pf1_updater;
private bool pf2_updater;
private byte pf0_delay_clock;
private byte pf1_delay_clock;
private byte pf2_delay_clock;
private byte pf0_max_delay;
private byte pf1_max_delay;
private byte pf2_max_delay;
private byte pf0_update = 0;
private byte pf1_update = 0;
private byte pf2_update = 0;
private bool pf0_updater = false;
private bool pf1_updater = false;
private bool pf2_updater = false;
private byte pf0_delay_clock = 0;
private byte pf1_delay_clock = 0;
private byte pf2_delay_clock = 0;
private byte pf0_max_delay = 0;
private byte pf1_max_delay = 0;
private byte pf2_max_delay = 0;
private int enam0_delay;
private int enam1_delay;
private int enamb_delay;
private bool enam0_val;
private bool enam1_val;
private bool enamb_val;
private int enam0_delay = 0;
private int enam1_delay = 0;
private int enamb_delay = 0;
private bool enam0_val = false;
private bool enam1_val = false;
private bool enamb_val = false;
private bool p0_stuff;
private bool p1_stuff;
private bool m0_stuff;
private bool m1_stuff;
private bool b_stuff;
private int HMP0_delay;
private byte HMP0_val;
private int HMP1_delay;
private byte HMP1_val;
private int prg0_delay = 0;
private int prg1_delay = 0;
private byte prg0_val = 0;
private byte prg1_val = 0;
private int prg0_delay;
private int prg1_delay;
private byte prg0_val;
private byte prg1_val;
private bool do_ticks;
private bool do_ticks = false;
private byte _hsyncCnt;
private int _capChargeStart;
private bool _capCharging;
@ -413,6 +419,44 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_CurrentScanLine = 0;
_audioClocks = 0;
pf0_update = 0;
pf1_update = 0;
pf2_update = 0;
pf0_updater = false;
pf1_updater = false;
pf2_updater = false;
pf0_delay_clock = 0;
pf1_delay_clock = 0;
pf2_delay_clock = 0;
pf0_max_delay = 0;
pf1_max_delay = 0;
pf2_max_delay = 0;
enam0_delay = 0;
enam1_delay = 0;
enamb_delay = 0;
enam0_val = false;
enam1_val = false;
enamb_val = false;
p0_stuff = false;
p1_stuff = false;
m0_stuff = false;
m1_stuff = false;
b_stuff = false;
HMP0_delay = 0;
HMP0_val = 0;
HMP1_delay = 0;
HMP1_val = 0;
prg0_delay = 0;
prg1_delay = 0;
prg0_val = 0;
prg1_val = 0;
do_ticks = false;
_player0 = new PlayerData();
_player1 = new PlayerData();
_playField = new PlayfieldData();
@ -429,7 +473,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Still ignoring cycles...
//delay latch to new playfield register
if (pf0_updater==true)
if (pf0_updater == true)
{
pf0_delay_clock++;
if (pf0_delay_clock > pf0_max_delay)
@ -458,10 +502,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
//delay latch to missile enable
if (enam0_delay>0)
if (enam0_delay > 0)
{
enam0_delay++;
if (enam0_delay==3)
if (enam0_delay == 3)
{
enam0_delay = 0;
_player0.Missile.Enabled = enam0_val;
@ -520,10 +564,32 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
// HMP write delay
if (HMP0_delay > 0)
{
HMP0_delay++;
if (HMP0_delay == 4)
{
HMP0_delay = 0;
_player0.HM = HMP0_val;
}
}
if (HMP1_delay > 0)
{
HMP1_delay++;
if (HMP1_delay == 3)
{
HMP1_delay = 0;
_player1.HM = HMP1_val;
}
}
// Reset the RDY flag when we reach hblank
if (_hsyncCnt <= 0)
{
_core.Cpu.RDY = true;
}
// Assume we're on the left side of the screen for now
@ -681,7 +747,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
throw new Exception(); // TODO
_scanlinebuffer[_CurrentScanLine * ScreenWidth + x] = pixelColor;
}
} else
}
else
{
do_ticks = true;
}
@ -708,44 +775,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// ---- Things that happen every time ----
// Handle HMOVE
if (_hmove.HMoveEnabled)
{
// On the first time, set the latches and counters
if (_hmove.HMoveJustStarted)
{
_hmove.Player0Latch = true;
_hmove.Player0Cnt = 0;
test_count_p0 = 0;
test_count_p1 = 0;
test_count_m0 = 0;
test_count_m1 = 0;
test_count_b = 0;
_hmove.Missile0Latch = true;
_hmove.Missile0Cnt = 0;
_hmove.Player1Latch = true;
_hmove.Player1Cnt = 0;
_hmove.Missile1Latch = true;
_hmove.Missile1Cnt = 0;
_hmove.BallLatch = true;
_hmove.BallCnt = 0;
_hmove.HMoveCnt = 0;
_hmove.HMoveJustStarted = false;
_hmove.LateHBlankReset = true;
_hmove.DecCntEnabled = false;
}
if (_hmove.DecCntEnabled)
{
@ -760,26 +794,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// If the move counter still has a bit in common with the HM register
if (((15 - _hmove.Player0Cnt) ^ ((_player0.HM & 0x07) | ((~(_player0.HM & 0x08)) & 0x08))) != 0x0F)
{
// "Clock-Stuffing"
if (do_ticks==true)
{
_player0.Tick();
}
// Increase by 1, max of 15
test_count_p0++;
if (test_count_p0 < 16)
{
_hmove.Player0Cnt++;
}
else
{
_hmove.Player0Cnt = 0;
}
//_hmove.Player0Cnt %= 16;
p0_stuff = true;
}
else
{
@ -793,24 +808,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// If the move counter still has a bit in common with the HM register
if (((15 - _hmove.Missile0Cnt) ^ ((_player0.Missile.Hm & 0x07) | ((~(_player0.Missile.Hm & 0x08)) & 0x08))) != 0x0F)
{
// "Clock-Stuffing"
if (do_ticks == true)
{
_player0.Missile.Tick();
}
// Increase by 1, max of 15
test_count_m0++;
if (test_count_m0 < 16)
{
_hmove.Missile0Cnt++;
}
else
{
_hmove.Missile0Cnt = 0;
}
//_hmove.Missile0Cnt %= 16;
m0_stuff = true;
}
else
{
@ -824,22 +822,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// If the move counter still has a bit in common with the HM register
if (((15 - _hmove.Player1Cnt) ^ ((_player1.HM & 0x07) | ((~(_player1.HM & 0x08)) & 0x08))) != 0x0F)
{
// "Clock-Stuffing"
if (do_ticks == true)
{
_player1.Tick();
}
// Increase by 1, max of 15
test_count_p1++;
if (test_count_p1 < 16)
{
_hmove.Player1Cnt++;
}
else
{
_hmove.Player1Cnt = 0;
}
//_hmove.Player1Cnt %= 16;
p1_stuff = true;
}
else
{
@ -852,22 +835,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// If the move counter still has a bit in common with the HM register
if (((15 - _hmove.Missile1Cnt) ^ ((_player1.Missile.Hm & 0x07) | ((~(_player1.Missile.Hm & 0x08)) & 0x08))) != 0x0F)
{
// "Clock-Stuffing"
if (do_ticks == true)
{
_player1.Missile.Tick();
}
// Increase by 1, max of 15
test_count_m1++;
if (test_count_m1 < 16)
{
_hmove.Missile1Cnt++;
}
else
{
_hmove.Missile1Cnt = 0;
}
// _hmove.Missile1Cnt %= 16;
m1_stuff = true;
}
else
{
@ -880,22 +848,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// If the move counter still has a bit in common with the HM register
if (((15 - _hmove.BallCnt) ^ ((_ball.HM & 0x07) | ((~(_ball.HM & 0x08)) & 0x08))) != 0x0F)
{
// "Clock-Stuffing"
if (do_ticks == true)
{
_ball.Tick();
}
// Increase by 1, max of 15
test_count_b++;
if (test_count_b < 16)
{
_hmove.BallCnt++;
}
else
{
_hmove.BallCnt = 0;
}
//_hmove.BallCnt %= 16;
b_stuff = true;
}
else
{
@ -913,6 +866,108 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_hmove.HMoveCnt++;
_hmove.HMoveCnt %= 4;
if (p0_stuff == true && _hsyncCnt % 4 == 0)
{
p0_stuff = false;
// "Clock-Stuffing"
if (do_ticks == true)
{
_player0.Tick();
}
// Increase by 1, max of 15
_hmove.test_count_p0++;
if (_hmove.test_count_p0 < 16)
{
_hmove.Player0Cnt++;
}
else
{
_hmove.Player0Cnt = 0;
}
}
if (p1_stuff == true && _hsyncCnt % 4 == 0)
{
p1_stuff = false;
// "Clock-Stuffing"
if (do_ticks == true)
{
_player1.Tick();
}
// Increase by 1, max of 15
_hmove.test_count_p1++;
if (_hmove.test_count_p1 < 16)
{
_hmove.Player1Cnt++;
}
else
{
_hmove.Player1Cnt = 0;
}
}
if (m0_stuff == true && _hsyncCnt % 4 == 0)
{
m0_stuff = false;
// "Clock-Stuffing"
if (do_ticks == true)
{
_player0.Missile.Tick();
}
// Increase by 1, max of 15
_hmove.test_count_m0++;
if (_hmove.test_count_m0 < 16)
{
_hmove.Missile0Cnt++;
}
else
{
_hmove.Missile0Cnt = 0;
}
}
if (m1_stuff == true && _hsyncCnt % 4 == 0)
{
m1_stuff = false;
// "Clock-Stuffing"
if (do_ticks == true)
{
_player1.Missile.Tick();
}
// Increase by 1, max of 15
_hmove.test_count_m1++;
if (_hmove.test_count_m1 < 16)
{
_hmove.Missile1Cnt++;
}
else
{
_hmove.Missile1Cnt = 0;
}
}
if (b_stuff == true && _hsyncCnt % 4 == 0)
{
b_stuff = false;
// "Clock-Stuffing"
if (do_ticks == true)
{
_ball.Tick();
}
// Increase by 1, max of 15
_hmove.test_count_b++;
if (_hmove.test_count_b < 16)
{
_hmove.BallCnt++;
}
else
{
_hmove.BallCnt = 0;
}
}
}
if (_hmove.HMoveDelayCnt < 5)
@ -925,10 +980,35 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_hmove.HMoveDelayCnt++;
_hmove.HMoveCnt = 0;
_hmove.DecCntEnabled = true;
_hmove.test_count_p0 = 0;
_hmove.test_count_p1 = 0;
_hmove.test_count_m0 = 0;
_hmove.test_count_m1 = 0;
_hmove.test_count_b = 0;
_hmove.Player0Latch = true;
_hmove.Player0Cnt = 0;
_hmove.Missile0Latch = true;
_hmove.Missile0Cnt = 0;
_hmove.Player1Latch = true;
_hmove.Player1Cnt = 0;
_hmove.Missile1Latch = true;
_hmove.Missile1Cnt = 0;
_hmove.BallLatch = true;
_hmove.BallCnt = 0;
_hmove.LateHBlankReset = true;
}
}
// Increment the hsync counter
_hsyncCnt++;
_hsyncCnt %= 228;
@ -1196,29 +1276,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Resp depends on HMOVE
if (!_hmove.LateHBlankReset)
{
if (_hsyncCnt < 69)
{
_player0.HPosCnt = 0;
_player0.ResetCnt = 2;
_player0.Reset = true;
_player0.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67) _player0.HPosCnt = 160 - 3;
}
else
{
_player0.ResetCnt = 0;
}
}
else
{
if (_hsyncCnt < 76)
{
_player0.HPosCnt = 0;
_player0.ResetCnt = 1;
_player0.Reset = true;
}
else
{
_player0.ResetCnt = 0;
}
_player0.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75) _player0.HPosCnt = 160 - 3;
}
}
else if (maskedAddr == 0x11) // RESP1
@ -1226,27 +1290,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// RESP depends on HMOVE
if (!_hmove.LateHBlankReset)
{
if (_hsyncCnt < 69)
{
_player1.HPosCnt = 0;
_player1.ResetCnt = 2;
_player1.Reset = true;
} else
{
_player1.ResetCnt = 0;
}
} else
{
if (_hsyncCnt < 76)
{
_player1.HPosCnt = 0;
_player1.ResetCnt = 1;
_player1.Reset = true;
_player1.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67) _player1.HPosCnt = 160 - 3;
}
else
{
_player1.ResetCnt = 0;
}
_player1.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75) _player1.HPosCnt = 160 - 3;
}
}
@ -1255,9 +1305,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_player0.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
} else
if (_hsyncCnt == 67) _player0.Missile.HPosCnt = 160 - 3;
}
else
{
_player0.Missile.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75) _player0.Missile.HPosCnt = 160 - 3;
}
}
@ -1266,10 +1319,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_player1.Missile.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67) _player1.Missile.HPosCnt = 160 - 3;
}
else
{
_player1.Missile.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75) _player1.Missile.HPosCnt = 160 - 3;
}
}
else if (maskedAddr == 0x14) // RESBL
@ -1277,10 +1332,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
if (!_hmove.LateHBlankReset)
{
_ball.HPosCnt = (byte)(_hsyncCnt < 68 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 67) _ball.HPosCnt = 160 - 3;
}
else
{
_ball.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 3 : 160 - 4);
_ball.HPosCnt = (byte)(_hsyncCnt < 76 ? 160 - 2 : 160 - 4);
if (_hsyncCnt == 75) _ball.HPosCnt = 160 - 3;
}
}
@ -1337,11 +1394,13 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
else if (maskedAddr == 0x20) // HMP0
{
_player0.HM = (byte)((value & 0xF0) >> 4);
HMP0_val = (byte)((value & 0xF0) >> 4);
HMP0_delay = 1;
}
else if (maskedAddr == 0x21) // HMP1
{
_player1.HM = (byte)((value & 0xF0) >> 4);
HMP1_val = (byte)((value & 0xF0) >> 4);
HMP1_delay = 1;
}
else if (maskedAddr == 0x22) // HMM0
{
@ -1378,7 +1437,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
else if (maskedAddr == 0x2A) // HMOVE
{
_hmove.HMoveEnabled = true;
_hmove.HMoveJustStarted = true;
_hmove.HMoveDelayCnt = 0;
}
else if (maskedAddr == 0x2B) // HMCLR
@ -1458,6 +1516,8 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// TODO: more accurate would be to have audio.Cycle() occur at
// the explicit exact times in the scanline, instead of just approximately spaced
public void GetSamples(short[] samples)
{
if (_audioClocks > 0)
{
var samples31khz = new short[_audioClocks]; // mono
@ -1486,7 +1546,7 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
samples[i * 2] = samples31khz[(int)(((double)samples31khz.Length / (double)(samples.Length / 2)) * i)];
samples[(i * 2) + 1] = samples[i * 2];
}
}
_audioClocks = 0;
}
@ -1513,6 +1573,48 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
_ball.SyncState(ser);
_hmove.SyncState(ser);
ser.Sync("hsyncCnt", ref _hsyncCnt);
// add everything to the state
ser.Sync("PF0_up",ref pf0_update);
ser.Sync("PF1_up", ref pf1_update);
ser.Sync("PF2_up", ref pf2_update);
ser.Sync("PF0_upper", ref pf0_updater);
ser.Sync("PF1_upper", ref pf1_updater);
ser.Sync("PF2_upper", ref pf2_updater);
ser.Sync("PF0_delay", ref pf0_delay_clock);
ser.Sync("PF1_delay", ref pf1_delay_clock);
ser.Sync("PF2_delay", ref pf2_delay_clock);
ser.Sync("PF0_max", ref pf0_max_delay);
ser.Sync("PF1_max", ref pf1_max_delay);
ser.Sync("PF2_max", ref pf2_max_delay);
ser.Sync("Enam0_delay", ref enam0_delay);
ser.Sync("Enam1_delay", ref enam1_delay);
ser.Sync("Enab_delay", ref enamb_delay);
ser.Sync("Enam0_val", ref enam0_val);
ser.Sync("Enam1_val", ref enam1_val);
ser.Sync("Enab_val", ref enamb_val);
ser.Sync("P0_stuff", ref p0_stuff);
ser.Sync("P1_stuff", ref p1_stuff);
ser.Sync("M0_stuff", ref m0_stuff);
ser.Sync("M1_stuf", ref m1_stuff);
ser.Sync("b_stuff", ref b_stuff);
ser.Sync("hmp0_delay", ref HMP0_delay);
ser.Sync("hmp0_val", ref HMP0_val);
ser.Sync("hmp1_delay", ref HMP1_delay);
ser.Sync("hmp1_val", ref HMP1_val);
ser.Sync("PRG0_delay", ref prg0_delay);
ser.Sync("PRG1_delay", ref prg1_delay);
ser.Sync("PRG0_val", ref prg0_val);
ser.Sync("PRG1_val", ref prg1_val);
ser.Sync("Ticks", ref do_ticks);
// some of these things weren't in the state because they weren't needed if
// states were always taken at frame boundaries
ser.Sync("capChargeStart", ref _capChargeStart);
@ -1521,6 +1623,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("vsyncEnabled", ref _vsyncEnabled);
ser.Sync("CurrentScanLine", ref _CurrentScanLine);
ser.Sync("scanlinebuffer", ref _scanlinebuffer, false);
ser.Sync("AudioClocks", ref _audioClocks);
ser.Sync("FrameStartCycles", ref frameStartCycles);
ser.Sync("FrameEndCycles", ref frameEndCycles);
ser.BeginSection("Player0");
_player0.SyncState(ser);

View File

@ -7,7 +7,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
private struct HMoveData
{
public bool HMoveEnabled;
public bool HMoveJustStarted;
public bool LateHBlankReset;
public bool DecCntEnabled;
@ -20,6 +19,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public byte HMoveDelayCnt;
public byte HMoveCnt;
public int test_count_p0;
public int test_count_p1;
public int test_count_m0;
public int test_count_m1;
public int test_count_b;
public byte Player0Cnt;
public byte Player1Cnt;
public byte Missile0Cnt;
@ -30,7 +35,6 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
{
ser.BeginSection("HMove");
ser.Sync("hmoveEnabled", ref HMoveEnabled);
ser.Sync("hmoveJustStarted", ref HMoveJustStarted);
ser.Sync("lateHBlankReset", ref LateHBlankReset);
ser.Sync("decCntEnabled", ref DecCntEnabled);
ser.Sync("player0Latch", ref Player0Latch);
@ -44,6 +48,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("player1Cnt", ref Player1Cnt);
ser.Sync("missile0Cnt", ref Missile0Cnt);
ser.Sync("missile1Cnt", ref Missile1Cnt);
ser.Sync("Test_count_p0", ref test_count_p0);
ser.Sync("Test_count_p1", ref test_count_p1);
ser.Sync("Test_count_m0", ref test_count_m0);
ser.Sync("Test_count_m1", ref test_count_m1);
ser.Sync("Test_count_b", ref test_count_b);
ser.Sync("ballCnt", ref BallCnt);
ser.EndSection();
}

View File

@ -14,10 +14,34 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public byte Hm;
public byte Collisions;
// Resp commands do not trigger start signals for main copies. We need to model this
public int Draw_To;
public byte ScanCnt;
public bool ScanCntInit;
public int Start_Signal;
public int Signal_Reached;
public bool Tick()
{
var result = false;
if (ScanCntInit==true)
{
if (ScanCnt < (1 << Size) && Enabled && !ResetToPlayer)
{
result = true;
ScanCnt++;
} else
{
ScanCntInit = false;
}
}
/*
// At hPosCnt == 0, start drawing the missile, if enabled
if (HPosCnt < (1 << Size))
{
@ -62,6 +86,34 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
result = true;
}
}
}*/
if (Start_Signal == 160)
{
ScanCnt = 0;
Start_Signal++;
ScanCntInit = true;
}
if (Start_Signal == 16 && ((Number & 0x07) == 0x01 || ((Number & 0x07) == 0x03)))
{
ScanCnt = 0;
Start_Signal++;
ScanCntInit = true;
}
if (Start_Signal == 32 && ((Number & 0x07) == 0x02 || ((Number & 0x07) == 0x03) || ((Number & 0x07) == 0x06)))
{
ScanCnt = 0;
Start_Signal++;
ScanCntInit = true;
}
if (Start_Signal == 64 && ((Number & 0x07) == 0x04 || ((Number & 0x07) == 0x06)))
{
ScanCnt = 0;
Start_Signal++;
ScanCntInit = true;
}
// Increment the counter
@ -70,6 +122,19 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// Counter loops at 160
HPosCnt %= 160;
//our goal here is to send a start signal 4 clocks before drawing begins. The properly emulates
//drawing on a real TIA
if (HPosCnt == 156 || HPosCnt == 12 || HPosCnt == 28 || HPosCnt == 60)
{
Start_Signal = HPosCnt;
Signal_Reached = HPosCnt + 5;
}
if (Start_Signal < Signal_Reached)
{
Start_Signal++;
}
return result;
}
@ -83,6 +148,11 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("number", ref Number);
ser.Sync("HM", ref Hm);
ser.Sync("collisions", ref Collisions);
ser.Sync("start_signal", ref Start_Signal);
ser.Sync("signal_reached", ref Signal_Reached);
ser.Sync("draw_to", ref Draw_To);
ser.Sync("scanCnt", ref ScanCnt);
ser.Sync("scanCntInit", ref ScanCntInit);
ser.EndSection();
}
}

View File

@ -18,10 +18,12 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
public bool Reflect;
public bool Delay;
public byte Nusiz;
public bool Reset;
public byte ResetCnt;
public byte Collisions;
// Resp commands do not trigger start signals for main copies. We need to model this
public int Start_Signal;
public int Signal_Reached;
public bool Tick()
{
var result = false;
@ -112,9 +114,10 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
// At counter position 0 we should initalize the scan counter.
// Note that for double and quad sized players that the scan counter is not started immediately.
if (HPosCnt == 0 && !Reset)
if (Start_Signal==160)
{
ScanCnt = 0;
Start_Signal++;
if ((Nusiz & 0x07) == 0x05)
{
ScanCntInit = true;
@ -129,42 +132,42 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
}
}
if (HPosCnt == 16 && ((Nusiz & 0x07) == 0x01 || ((Nusiz & 0x07) == 0x03)))
if (Start_Signal == 16 && ((Nusiz & 0x07) == 0x01 || ((Nusiz & 0x07) == 0x03)))
{
ScanCnt = 0;
Start_Signal++;
}
if (HPosCnt == 32 && ((Nusiz & 0x07) == 0x02 || ((Nusiz & 0x07) == 0x03) || ((Nusiz & 0x07) == 0x06)))
if (Start_Signal == 32 && ((Nusiz & 0x07) == 0x02 || ((Nusiz & 0x07) == 0x03) || ((Nusiz & 0x07) == 0x06)))
{
ScanCnt = 0;
Start_Signal++;
}
if (HPosCnt == 64 && ((Nusiz & 0x07) == 0x04 || ((Nusiz & 0x07) == 0x06)))
if (Start_Signal == 64 && ((Nusiz & 0x07) == 0x04 || ((Nusiz & 0x07) == 0x06)))
{
ScanCnt = 0;
Start_Signal++;
}
// Reset is no longer in effect
Reset = false;
// Increment the counter
HPosCnt++;
// Counter loops at 160
HPosCnt %= 160;
if (ResetCnt < 4)
//our goal here is to send a start signal 4 clocks before drawing begins. This properly emulates
//drawing on a real TIA
if (HPosCnt==156 || HPosCnt==12 || HPosCnt==28 || HPosCnt==60)
{
ResetCnt++;
Start_Signal = HPosCnt-1;
Signal_Reached = HPosCnt + 5;
}
if (ResetCnt == 4)
if (Start_Signal<Signal_Reached)
{
HPosCnt = 0;
Reset = true;
ResetCnt++;
Start_Signal++;
}
return result;
}
@ -181,9 +184,9 @@ namespace BizHawk.Emulation.Cores.Atari.Atari2600
ser.Sync("reflect", ref Reflect);
ser.Sync("delay", ref Delay);
ser.Sync("nusiz", ref Nusiz);
ser.Sync("reset", ref Reset);
ser.Sync("resetCnt", ref ResetCnt);
ser.Sync("collisions", ref Collisions);
ser.Sync("start_signal", ref Start_Signal);
ser.Sync("signal_reached", ref Signal_Reached);
}
}
}

View File

@ -284,12 +284,13 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
//PAL:
//0 15 30 45 60 -> 12 27 42 57 -> 9 24 39 54 -> 6 21 36 51 -> 3 18 33 48 -> 0
//sequence of ppu clocks per cpu clock: 4,3,3,3,3
//sequence of ppu clocks per cpu clock: 3,3,3,3,4
//at least it should be, but something is off with that (start up time?) so it is 3,3,3,4,3 for now
//NTSC:
//sequence of ppu clocks per cpu clock: 3
ByteBuffer cpu_sequence;
static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[]{3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3,3});
static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[]{4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3,4,3,3,3,3});
static ByteBuffer cpu_sequence_NTSC = new ByteBuffer(new byte[]{3,3,3,3,3});
static ByteBuffer cpu_sequence_PAL = new ByteBuffer(new byte[]{3,3,3,4,3});
public int cpu_step, cpu_stepcounter, cpu_deadcounter;
#if VS2012
@ -301,7 +302,7 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
if (cpu_stepcounter == cpu_sequence[cpu_step])
{
cpu_step++;
cpu_step &= 31;
if(cpu_step == 5) cpu_step=0;
cpu_stepcounter = 0;
if (sprdma_countdown > 0)
@ -311,6 +312,8 @@ namespace BizHawk.Emulation.Cores.Nintendo.NES
{
//its weird that this is 514.. normally itd be 512 (and people would say its wrong) or 513 (and people would say its right)
//but 514 passes test 4-irq_and_dma
// according to nesdev wiki, http://wiki.nesdev.com/w/index.php/PPU_OAM this is 513 on even cycles and 514 on odd cycles
// TODO: Implement that
cpu_deadcounter += 514;
}
}

1535
TIA.cs

File diff suppressed because it is too large Load Diff