BizHawk/BizHawk.Emulation.Cores/Computers/Commodore64/Serial/Drive1541.FluxTransitions.cs

167 lines
6.3 KiB
C#
Raw Normal View History

2017-04-15 19:53:02 +00:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using BizHawk.Emulation.Cores.Computers.Commodore64.Media;
namespace BizHawk.Emulation.Cores.Computers.Commodore64.Serial
{
public sealed partial class Drive1541
{
[SaveState.DoNotSave]
private const long LEHMER_RNG_PRIME = 48271;
[SaveState.SaveWithName("DiskDensityCounter")]
private int _diskDensityCounter; // density .. 16
[SaveState.SaveWithName("DiskSupplementaryCounter")]
private int _diskSupplementaryCounter; // 0 .. 16
[SaveState.SaveWithName("DiskFluxReversalDetected")]
private bool _diskFluxReversalDetected;
[SaveState.SaveWithName("DiskBitsRemainingInDataEntry")]
private int _diskBitsLeft;
[SaveState.SaveWithName("DiskDataEntryIndex")]
private int _diskByteOffset;
[SaveState.SaveWithName("DiskDataEntry")]
private int _diskBits;
[SaveState.SaveWithName("DiskCurrentCycle")]
private int _diskCycle;
[SaveState.SaveWithName("DiskDensityConfig")]
2016-02-22 23:50:11 +00:00
private int _diskDensity;
2017-04-15 19:53:02 +00:00
[SaveState.SaveWithName("PreviousCA1")]
private bool _previousCa1;
[SaveState.SaveWithName("CountsBeforeRandomTransition")]
private int _countsBeforeRandomTransition;
[SaveState.SaveWithName("CurrentRNG")]
private int _rngCurrent;
[SaveState.SaveWithName("Clocks")]
private int _clocks;
[SaveState.SaveWithName("CpuClocks")]
private int _cpuClocks;
// Lehmer RNG
private void AdvanceRng()
{
if (_rngCurrent == 0)
_rngCurrent = 1;
_rngCurrent = (int)(_rngCurrent * LEHMER_RNG_PRIME % int.MaxValue);
}
private void ExecuteFlux()
2016-02-22 23:50:11 +00:00
{
// This actually executes the main 16mhz clock
2017-04-15 19:53:02 +00:00
while (_clocks > 0)
{
_clocks--;
// rotate disk
2016-02-22 23:50:11 +00:00
if (_motorEnabled)
2017-04-15 19:53:02 +00:00
{
if (_disk == null)
{
_diskBitsLeft = 1;
_diskBits = 0;
}
else
{
if (_diskBitsLeft <= 0)
{
_diskByteOffset++;
if (_diskByteOffset == Disk.FluxEntriesPerTrack)
{
_diskByteOffset = 0;
}
_diskBits = _trackImageData[_diskByteOffset];
_diskBitsLeft = Disk.FluxBitsPerEntry;
}
}
if ((_diskBits & 1) != 0)
{
2016-02-22 23:50:11 +00:00
_countsBeforeRandomTransition = 0;
2017-04-15 19:53:02 +00:00
_diskFluxReversalDetected = true;
}
2016-02-22 23:50:11 +00:00
_diskBits >>= 1;
2017-04-15 19:53:02 +00:00
_diskBitsLeft--;
}
// random flux transition readings for unformatted data
if (_countsBeforeRandomTransition > 0)
{
_countsBeforeRandomTransition--;
if (_countsBeforeRandomTransition == 0)
{
_diskFluxReversalDetected = true;
AdvanceRng();
// This constant is what VICE uses. TODO: Determine accuracy.
_countsBeforeRandomTransition = (_rngCurrent % 367) + 33;
}
}
// flux transition circuitry
if (_diskFluxReversalDetected)
{
_diskDensityCounter = _diskDensity;
_diskSupplementaryCounter = 0;
_diskFluxReversalDetected = false;
if (_countsBeforeRandomTransition == 0)
2016-02-22 23:50:11 +00:00
{
2017-04-15 19:53:02 +00:00
AdvanceRng();
// This constant is what VICE uses. TODO: Determine accuracy.
_countsBeforeRandomTransition = (_rngCurrent & 0x1F) + 289;
}
}
// counter circuitry
if (_diskDensityCounter >= 16)
{
_diskDensityCounter = _diskDensity;
2016-02-22 23:50:11 +00:00
_diskSupplementaryCounter++;
2017-04-15 19:53:02 +00:00
if ((_diskSupplementaryCounter & 0x3) == 0x2)
2016-02-22 23:50:11 +00:00
{
_bitsRemainingInLatchedByte--;
_byteReady = false;
2016-02-22 23:50:11 +00:00
_bitHistory = (_bitHistory << 1) | ((_diskSupplementaryCounter & 0xC) == 0x0 ? 1 : 0);
_sync = false;
if (Via1.Cb2 && (_bitHistory & 0x3FF) == 0x3FF)
{
_sync = true;
_bitsRemainingInLatchedByte = 8;
_byteReady = false;
}
if (_bitsRemainingInLatchedByte <= 0)
{
_bitsRemainingInLatchedByte = 8;
// SOE (sync output enabled)
_byteReady = Via1.Ca2;
}
2016-02-22 23:50:11 +00:00
// negative transition activates SO pin on CPU
_previousCa1 = Via1.Ca1;
Via1.Ca1 = !_byteReady;
if (_previousCa1 && !Via1.Ca1)
{
// cycle 6 is roughly 400ns
_overflowFlagDelaySr |= _diskCycle > 6 ? 4 : 2;
}
}
2017-04-15 19:53:02 +00:00
}
if (_diskSupplementaryCounter >= 16)
{
_diskSupplementaryCounter = 0;
}
_cpuClocks--;
if (_cpuClocks <= 0)
{
ExecuteSystem();
_cpuClocks = 16;
}
2016-02-22 23:50:11 +00:00
_diskDensityCounter++;
2017-04-15 19:53:02 +00:00
_diskCycle = (_diskCycle + 1) & 0xF;
}
}
}
}