Use FindTrackSeamWOZ() to find longest run of sync FF/10 nibbles. Jitter added: . only for tracks 33.0 and above . only for tracks with long runs of sync FF/10 of more than 110 Changes: . DumpTrackWOZ() outputs nibble then zeros (instead of zeros first) . Debugger: 'disk info' outputs bitOffset (instead of byteOffset+mask)
This commit is contained in:
parent
f300edb5de
commit
4c83186545
|
@ -3436,13 +3436,12 @@ Update_t CmdDisk ( int nArgs)
|
|||
if (nArgs > 2)
|
||||
return HelpLastCommand();
|
||||
|
||||
ConsoleBufferPushFormat("FW%2d: D%d at T$%s, phase $%s, offset $%X, mask $%02X, extraCycles %.2f, %s",
|
||||
ConsoleBufferPushFormat("FW%2d: D%d at T$%s, phase $%s, bitOffset $%04X, extraCycles %.2f, %s",
|
||||
diskCard.GetCurrentFirmware(),
|
||||
diskCard.GetCurrentDrive() + 1,
|
||||
diskCard.GetCurrentTrackString().c_str(),
|
||||
diskCard.GetCurrentPhaseString().c_str(),
|
||||
diskCard.GetCurrentOffset(),
|
||||
diskCard.GetCurrentLSSBitMask(),
|
||||
diskCard.GetCurrentBitOffset(),
|
||||
diskCard.GetCurrentExtraCycles(),
|
||||
diskCard.GetCurrentState()
|
||||
);
|
||||
|
|
243
source/Disk.cpp
243
source/Disk.cpp
|
@ -104,8 +104,7 @@ void Disk2InterfaceCard::SetEnhanceDisk(bool bEnhanceDisk) { m_enhanceDisk = bEn
|
|||
int Disk2InterfaceCard::GetCurrentDrive(void) { return m_currDrive; }
|
||||
int Disk2InterfaceCard::GetCurrentTrack(void) { return ImagePhaseToTrack(m_floppyDrive[m_currDrive].m_disk.m_imagehandle, m_floppyDrive[m_currDrive].m_phasePrecise, false); }
|
||||
float Disk2InterfaceCard::GetCurrentPhase(void) { return m_floppyDrive[m_currDrive].m_phasePrecise; }
|
||||
int Disk2InterfaceCard::GetCurrentOffset(void) { return m_floppyDrive[m_currDrive].m_disk.m_byte; }
|
||||
BYTE Disk2InterfaceCard::GetCurrentLSSBitMask(void) { return m_floppyDrive[m_currDrive].m_disk.m_bitMask; }
|
||||
UINT Disk2InterfaceCard::GetCurrentBitOffset(void) { return m_floppyDrive[m_currDrive].m_disk.m_bitOffset; }
|
||||
double Disk2InterfaceCard::GetCurrentExtraCycles(void) { return m_floppyDrive[m_currDrive].m_disk.m_extraCycles; }
|
||||
int Disk2InterfaceCard::GetTrack(const int drive) { return ImagePhaseToTrack(m_floppyDrive[drive].m_disk.m_imagehandle, m_floppyDrive[drive].m_phasePrecise, false); }
|
||||
|
||||
|
@ -325,6 +324,12 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
|
|||
}
|
||||
else
|
||||
{
|
||||
// NB. This function is only called for a new track when there's a latch read, ie. only for *even* DEVICE SELECT I/O accesses.
|
||||
// . So when seeking across tracks (ie. sequencing through the magnet phases), then not all (quarter) tracks will need reading.
|
||||
// . eg. for 'Balance of Power'(GH#1022), for seek T00->T35: this only reads: 00.00, 00.25, 00.75, 01.25, 01.75, ... 34.25, 34.75, 35.00 (skipping the NN.00, NN.50 tracks).
|
||||
// . And so the bitOffset "round-up" below isn't called for every track.
|
||||
// TODO: consider forcing this function be be called for every track (and appropriately adjust the "round-up" amount - ie. halve it)
|
||||
|
||||
_ASSERT(pFloppy->m_nibbles && pFloppy->m_bitCount);
|
||||
if (pFloppy->m_nibbles == 0 || pFloppy->m_bitCount == 0)
|
||||
{
|
||||
|
@ -337,15 +342,23 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
|
|||
|
||||
if (pFloppy->m_bitOffset >= pFloppy->m_bitCount)
|
||||
pFloppy->m_bitOffset = 0;
|
||||
#if LOG_DISK_WOZ_READTRACK
|
||||
LOG_DISK("T%05.2f: %04X->%04X, Len=%04X\n", pDrive->m_phasePrecise / 2, currentBitPosition, pFloppy->m_bitOffset, pFloppy->m_bitCount);
|
||||
#endif
|
||||
|
||||
pFloppy->m_byte = pFloppy->m_bitOffset / 8;
|
||||
pFloppy->m_bitMask = 1 << (7 - (pFloppy->m_bitOffset % 8));
|
||||
|
||||
pFloppy->m_extraCycles = 0.0;
|
||||
pDrive->m_headWindow = 0;
|
||||
|
||||
FindTrackSeamWOZ(*pFloppy, pDrive->m_phasePrecise/2);
|
||||
}
|
||||
|
||||
pFloppy->m_trackimagedata = (pFloppy->m_nibbles != 0);
|
||||
|
||||
pFloppy->m_initialBitOffset = pFloppy->m_bitOffset;
|
||||
pFloppy->m_revs = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1196,6 +1209,9 @@ __forceinline void Disk2InterfaceCard::IncBitStream(FloppyDisk& floppy)
|
|||
floppy.m_bitOffset = 0;
|
||||
floppy.m_byte = 0;
|
||||
}
|
||||
|
||||
if (floppy.m_bitOffset == floppy.m_initialBitOffset)
|
||||
floppy.m_revs++;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::PreJitterCheck(int phase, BYTE latch)
|
||||
|
@ -1240,6 +1256,29 @@ void Disk2InterfaceCard::AddJitter(int phase, FloppyDisk& floppy)
|
|||
m_foundT00S00Pattern = false;
|
||||
}
|
||||
|
||||
// GH#1125: For T$21 (track 33.0) or above (and sufficiently long sync FF/10 run-length), then randomly skip 1 bit-cell at the start of the FF/2 track seam.
|
||||
// Example of high sync FF/10 run-lengths for tracks 33.0+:
|
||||
// . Accolade Comics:114, Silent Service:117, Wings of Fury:140, Wizardry I:127, Wizardry III:283
|
||||
// NB. Restrict to higher FF/10 run-lengths to limit the titles affected by this jitter.
|
||||
void Disk2InterfaceCard::AddTrackSeamJitter(float phasePrecise, FloppyDisk& floppy)
|
||||
{
|
||||
if (phasePrecise >= (33.0 * 2) && floppy.m_longestSyncFFRunLength > 110)
|
||||
{
|
||||
if (floppy.m_bitOffset == floppy.m_longestSyncFFBitOffsetStart)
|
||||
{
|
||||
if (rand() < RAND_THRESHOLD(5, 10))
|
||||
{
|
||||
LogOutput("Disk: T%05.2f jitter - slip 1 bitcell (revs=%d) (PC=%04X)\n", phasePrecise / 2, floppy.m_revs, regs.pc);
|
||||
IncBitStream(floppy);
|
||||
}
|
||||
else
|
||||
{
|
||||
LogOutput("Disk: T%05.2f jitter - *** SKIP *** (revs=%d) (PC=%04X)\n", phasePrecise / 2, floppy.m_revs, regs.pc);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, ULONG uExecutedCycles)
|
||||
{
|
||||
_ASSERT(m_seqFunc.function != dataShiftWrite);
|
||||
|
@ -1346,6 +1385,8 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain
|
|||
|
||||
IncBitStream(floppy);
|
||||
|
||||
AddTrackSeamJitter(drive.m_phasePrecise, floppy);
|
||||
|
||||
m_shiftReg <<= 1;
|
||||
m_shiftReg |= outputBit;
|
||||
|
||||
|
@ -1432,6 +1473,8 @@ void Disk2InterfaceCard::DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemain
|
|||
LOG_DISK("load shiftReg with %02X (was: %02X)\n", m_floppyLatch, m_shiftReg);
|
||||
#endif
|
||||
m_shiftReg = m_floppyLatch;
|
||||
|
||||
floppy.m_longestSyncFFBitOffsetStart = -1; // invalidate the track seam location after a write
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles)
|
||||
|
@ -1478,6 +1521,107 @@ void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCy
|
|||
|
||||
//===========================================================================
|
||||
|
||||
// For now all that's needed is this basic case:
|
||||
// . find [start,end] of longest run of FF/10 sync nibbles
|
||||
void Disk2InterfaceCard::FindTrackSeamWOZ(FloppyDisk& floppy, float track)
|
||||
{
|
||||
const UINT oldBitOffset = floppy.m_bitOffset; // Save current state
|
||||
|
||||
BYTE shiftReg = 0;
|
||||
UINT zeroCount = 0;
|
||||
|
||||
int startBitOffset = -1; // NB. change this to start of first FF/10
|
||||
floppy.m_bitOffset = 0;
|
||||
UpdateBitStreamOffsets(floppy);
|
||||
|
||||
int nibbleStartBitOffset = -1;
|
||||
int syncFFStartBitOffset = -1;
|
||||
int syncFFRunLength = 0;
|
||||
int longestSyncFFStartBitOffset = -1;
|
||||
int longestSyncFFRunLength = 0;
|
||||
|
||||
floppy.m_longestSyncFFBitOffsetStart = -1;
|
||||
|
||||
while (1)
|
||||
{
|
||||
BYTE n = floppy.m_trackimage[floppy.m_byte];
|
||||
BYTE outputBit = (n & floppy.m_bitMask) ? 1 : 0;
|
||||
|
||||
IncBitStream(floppy);
|
||||
|
||||
if ((startBitOffset < 0 && floppy.m_bitOffset == 0) || (startBitOffset == floppy.m_bitOffset)) // done complete track?
|
||||
break;
|
||||
|
||||
if (shiftReg & 0x80)
|
||||
{
|
||||
if (outputBit == 0) // zero, so LSS holds nibble in latch
|
||||
{
|
||||
zeroCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// else: start of next nibble
|
||||
|
||||
if (shiftReg == 0xff && zeroCount == 2)
|
||||
{
|
||||
if (syncFFStartBitOffset < 0)
|
||||
syncFFStartBitOffset = nibbleStartBitOffset;
|
||||
syncFFRunLength++;
|
||||
}
|
||||
|
||||
if ((shiftReg != 0xff || zeroCount != 2) && syncFFStartBitOffset >= 0)
|
||||
{
|
||||
// Longest FF/2 run could straddle end/start of track's bit buffer
|
||||
if (startBitOffset < 0)
|
||||
startBitOffset = nibbleStartBitOffset;
|
||||
|
||||
if (longestSyncFFRunLength < syncFFRunLength)
|
||||
{
|
||||
longestSyncFFStartBitOffset = syncFFStartBitOffset;
|
||||
longestSyncFFRunLength = syncFFRunLength;
|
||||
}
|
||||
syncFFStartBitOffset = -1;
|
||||
syncFFRunLength = 0;
|
||||
}
|
||||
|
||||
shiftReg = 0;
|
||||
zeroCount = 0;
|
||||
}
|
||||
|
||||
shiftReg <<= 1;
|
||||
shiftReg |= outputBit;
|
||||
|
||||
if (shiftReg == 0x01)
|
||||
{
|
||||
nibbleStartBitOffset = floppy.m_bitOffset - 1;
|
||||
if (nibbleStartBitOffset < 0) nibbleStartBitOffset += floppy.m_bitCount;
|
||||
}
|
||||
}
|
||||
|
||||
if (longestSyncFFRunLength)
|
||||
{
|
||||
const int longestSyncFFBitOffsetEnd = (longestSyncFFStartBitOffset + longestSyncFFRunLength * 10 - 1) % floppy.m_bitCount;
|
||||
#if LOG_DISK_WOZ_TRACK_SEAM
|
||||
LOG_DISK("Track seam: T%05.2f: FF/10 (run=%d), start=%04X, end=%04X\n", track, longestSyncFFRunLength, longestSyncFFStartBitOffset, longestSyncFFBitOffsetEnd);
|
||||
#endif
|
||||
floppy.m_longestSyncFFBitOffsetStart = longestSyncFFStartBitOffset;
|
||||
floppy.m_longestSyncFFRunLength = longestSyncFFRunLength;
|
||||
}
|
||||
else
|
||||
{
|
||||
#if LOG_DISK_WOZ_TRACK_SEAM
|
||||
LOG_DISK("Track seam: T%05.2f: FF/10 (none)\n", track);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Restore state
|
||||
|
||||
floppy.m_bitOffset = oldBitOffset;
|
||||
UpdateBitStreamOffsets(floppy);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
#ifdef _DEBUG
|
||||
// Dump nibbles from current position bitstream wraps to same position
|
||||
// NB. Need to define LOG_DISK_NIBBLES_READ so that GetReadD5AAxxDetectedString() works.
|
||||
|
@ -1489,21 +1633,22 @@ void Disk2InterfaceCard::DumpTrackWOZ(FloppyDisk floppy) // pass a copy of m_flo
|
|||
UINT zeroCount = 0;
|
||||
UINT nibbleCount = 0;
|
||||
|
||||
const UINT startBitOffset = 0; // NB. may need to tweak this offset, since the bistream is a circular buffer
|
||||
const UINT startBitOffset = 0; // NB. may need to tweak this offset, since the bitstream is a circular buffer
|
||||
floppy.m_bitOffset = startBitOffset;
|
||||
UpdateBitStreamOffsets(floppy);
|
||||
|
||||
floppy.m_byte = floppy.m_bitOffset / 8;
|
||||
const UINT remainder = 7 - (floppy.m_bitOffset & 7);
|
||||
floppy.m_bitMask = 1 << remainder;
|
||||
int nibbleStartBitOffset = -1;
|
||||
|
||||
bool newLine = true;
|
||||
bool doneLastBit = false;
|
||||
|
||||
while (1)
|
||||
{
|
||||
if (newLine)
|
||||
if (newLine && nibbleStartBitOffset >= 0)
|
||||
{
|
||||
newLine = false;
|
||||
LogOutput("%04X:", floppy.m_bitOffset & 0xffff);
|
||||
LogOutput("%04X:", nibbleStartBitOffset);
|
||||
nibbleStartBitOffset = -1;
|
||||
}
|
||||
|
||||
BYTE n = floppy.m_trackimage[floppy.m_byte];
|
||||
|
@ -1512,53 +1657,67 @@ void Disk2InterfaceCard::DumpTrackWOZ(FloppyDisk floppy) // pass a copy of m_flo
|
|||
IncBitStream(floppy);
|
||||
|
||||
if (startBitOffset == floppy.m_bitOffset) // done complete track?
|
||||
doneLastBit = true;
|
||||
else if (doneLastBit)
|
||||
break;
|
||||
|
||||
if (shiftReg == 0 && outputBit == 0)
|
||||
if (shiftReg & 0x80)
|
||||
{
|
||||
zeroCount++;
|
||||
continue;
|
||||
if (outputBit == 0) // zero, so LSS holds nibble in latch
|
||||
{
|
||||
zeroCount++;
|
||||
continue;
|
||||
}
|
||||
|
||||
// else: start of next nibble
|
||||
|
||||
nibbleCount++;
|
||||
|
||||
char syncBits = zeroCount <= 9 ? '0' + zeroCount : '+';
|
||||
if (zeroCount == 0) LogOutput("%02X ", shiftReg);
|
||||
else LogOutput("%02X(%c)", shiftReg, syncBits);
|
||||
|
||||
formatTrack.DecodeLatchNibbleRead(shiftReg);
|
||||
|
||||
if ((nibbleCount % 32) == 0)
|
||||
{
|
||||
std::string strReadDetected = formatTrack.GetReadD5AAxxDetectedString();
|
||||
if (!strReadDetected.empty())
|
||||
{
|
||||
OutputDebugString("\t; ");
|
||||
OutputDebugString(strReadDetected.c_str());
|
||||
}
|
||||
OutputDebugString("\n");
|
||||
newLine = true;
|
||||
}
|
||||
|
||||
shiftReg = 0;
|
||||
zeroCount = 0;
|
||||
}
|
||||
|
||||
shiftReg <<= 1;
|
||||
shiftReg |= outputBit;
|
||||
|
||||
if ((shiftReg & 0x80) == 0)
|
||||
continue;
|
||||
|
||||
nibbleCount++;
|
||||
|
||||
char syncBits = zeroCount <= 9 ? '0'+zeroCount : '+';
|
||||
if (zeroCount == 0) LogOutput(" %02X", shiftReg);
|
||||
else LogOutput("(%c)%02X", syncBits, shiftReg);
|
||||
|
||||
formatTrack.DecodeLatchNibbleRead(shiftReg);
|
||||
|
||||
if ((nibbleCount % 32) == 0)
|
||||
if (shiftReg == 0x01)
|
||||
{
|
||||
std::string strReadDetected = formatTrack.GetReadD5AAxxDetectedString();
|
||||
if (!strReadDetected.empty())
|
||||
{
|
||||
OutputDebugString("\t; ");
|
||||
OutputDebugString(strReadDetected.c_str());
|
||||
}
|
||||
OutputDebugString("\n");
|
||||
newLine = true;
|
||||
nibbleStartBitOffset = floppy.m_bitOffset - 1;
|
||||
if (nibbleStartBitOffset < 0) nibbleStartBitOffset += floppy.m_bitCount;
|
||||
}
|
||||
|
||||
shiftReg = 0;
|
||||
zeroCount = 0;
|
||||
}
|
||||
|
||||
// Output any remaining zeroCount
|
||||
if (zeroCount)
|
||||
{
|
||||
char syncBits = zeroCount <= 9 ? '0'+zeroCount : '+';
|
||||
LogOutput("(%c)", syncBits);
|
||||
}
|
||||
|
||||
// Output any partial nibble
|
||||
if (shiftReg)
|
||||
if (shiftReg & 0x80)
|
||||
{
|
||||
LogOutput("%02X", shiftReg);
|
||||
|
||||
// Output any remaining zeroCount
|
||||
if (zeroCount)
|
||||
{
|
||||
char syncBits = zeroCount <= 9 ? '0' + zeroCount : '+';
|
||||
LogOutput("(%c)", syncBits);
|
||||
}
|
||||
}
|
||||
else if (shiftReg)
|
||||
{
|
||||
LogOutput("%02X/Partial Nibble", shiftReg);
|
||||
}
|
||||
|
|
|
@ -68,6 +68,10 @@ public:
|
|||
m_trackimage = NULL;
|
||||
m_trackimagedata = false;
|
||||
m_trackimagedirty = false;
|
||||
m_longestSyncFFRunLength = 0;
|
||||
m_longestSyncFFBitOffsetStart = -1;
|
||||
m_initialBitOffset = 0;
|
||||
m_revs = 0;
|
||||
}
|
||||
|
||||
public:
|
||||
|
@ -85,6 +89,10 @@ public:
|
|||
LPBYTE m_trackimage;
|
||||
bool m_trackimagedata;
|
||||
bool m_trackimagedirty;
|
||||
UINT m_longestSyncFFRunLength;
|
||||
int m_longestSyncFFBitOffsetStart;
|
||||
UINT m_initialBitOffset; // debug
|
||||
UINT m_revs; // debug
|
||||
};
|
||||
|
||||
class FloppyDrive
|
||||
|
@ -155,8 +163,7 @@ public:
|
|||
int GetCurrentDrive(void);
|
||||
int GetCurrentTrack(void);
|
||||
float GetCurrentPhase(void);
|
||||
int GetCurrentOffset(void);
|
||||
BYTE GetCurrentLSSBitMask(void);
|
||||
UINT GetCurrentBitOffset(void);
|
||||
double GetCurrentExtraCycles(void);
|
||||
int GetTrack(const int drive);
|
||||
static std::string FormatPhaseString(float phase);
|
||||
|
@ -203,6 +210,7 @@ private:
|
|||
void DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
|
||||
void DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles);
|
||||
void SetSequencerFunction(WORD addr, ULONG executedCycles);
|
||||
void FindTrackSeamWOZ(FloppyDisk& floppy, float track);
|
||||
void DumpTrackWOZ(FloppyDisk floppy);
|
||||
bool GetFirmware(WORD lpNameId, BYTE* pDst);
|
||||
void InitFirmware(LPBYTE pCxRomPeripheral);
|
||||
|
@ -214,6 +222,7 @@ private:
|
|||
|
||||
void PreJitterCheck(int phase, BYTE latch);
|
||||
void AddJitter(int phase, FloppyDisk& floppy);
|
||||
void AddTrackSeamJitter(float phasePrecise, FloppyDisk& floppy);
|
||||
|
||||
void SaveSnapshotFloppy(YamlSaveHelper& yamlSaveHelper, UINT unit);
|
||||
void SaveSnapshotDriveUnit(YamlSaveHelper& yamlSaveHelper, UINT unit);
|
||||
|
|
|
@ -14,6 +14,8 @@
|
|||
#define LOG_DISK_NIBBLES_USE_RUNTIME_VAR 1
|
||||
#define LOG_DISK_WOZ_LOADWRITE 1
|
||||
#define LOG_DISK_WOZ_SHIFTWRITE 1
|
||||
#define LOG_DISK_WOZ_READTRACK 1
|
||||
#define LOG_DISK_WOZ_TRACK_SEAM 1
|
||||
|
||||
// __VA_ARGS__ not supported on MSVC++ .NET 7.x
|
||||
#if (LOG_DISK_ENABLED)
|
||||
|
|
Loading…
Reference in New Issue