mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-01-17 00:30:04 +00:00
Write support for WOZ1/WOZ2 images (#756)
Also: - Allow creation of a blank (WOZ2) image - multi-zip support extended to scan for the first valid image (useful for most woz-a-day zips which have at least 2 entries and were previously failing)
This commit is contained in:
parent
d07558b610
commit
4956957ca1
185
source/Disk.cpp
185
source/Disk.cpp
@ -282,6 +282,12 @@ void Disk2InterfaceCard::ReadTrack(const int drive, ULONG uExecutedCycles)
|
|||||||
if (ImagePhaseToTrack(pFloppy->m_imagehandle, pDrive->m_phasePrecise, false) >= ImageGetNumTracks(pFloppy->m_imagehandle))
|
if (ImagePhaseToTrack(pFloppy->m_imagehandle, pDrive->m_phasePrecise, false) >= ImageGetNumTracks(pFloppy->m_imagehandle))
|
||||||
{
|
{
|
||||||
_ASSERT(0); // What can cause this? Add a comment to replace this assert.
|
_ASSERT(0); // What can cause this? Add a comment to replace this assert.
|
||||||
|
// Boot with DOS 3.3 Master in D1
|
||||||
|
// Create a blank disk in D2
|
||||||
|
// INIT HELLO,D2
|
||||||
|
// RUN HELLO
|
||||||
|
// F2 to reboot DOS 3.3 Master
|
||||||
|
// RUN HELLO,D2
|
||||||
pFloppy->m_trackimagedata = false;
|
pFloppy->m_trackimagedata = false;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -729,17 +735,6 @@ void Disk2InterfaceCard::NotifyInvalidImage(const int drive, LPCTSTR pszImageFil
|
|||||||
pszImageFilename);
|
pszImageFilename);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case eIMAGE_ERROR_UNSUPPORTED_MULTI_ZIP:
|
|
||||||
StringCbPrintf(
|
|
||||||
szBuffer,
|
|
||||||
MAX_PATH + 128,
|
|
||||||
TEXT("Unable to use the file %s\nbecause the ")
|
|
||||||
TEXT("first file (%s) in this multi-zip archive is not recognized.\n")
|
|
||||||
TEXT("Try unzipping and using the disk images directly.\n"),
|
|
||||||
pszImageFilename,
|
|
||||||
m_floppyDrive[drive].m_disk.m_strFilenameInZip.c_str());
|
|
||||||
break;
|
|
||||||
|
|
||||||
case eIMAGE_ERROR_GZ:
|
case eIMAGE_ERROR_GZ:
|
||||||
case eIMAGE_ERROR_ZIP:
|
case eIMAGE_ERROR_ZIP:
|
||||||
StringCbPrintf(
|
StringCbPrintf(
|
||||||
@ -984,24 +979,18 @@ void Disk2InterfaceCard::ResetLogicStateSequencer(void)
|
|||||||
m_shiftReg = 0;
|
m_shiftReg = 0;
|
||||||
m_latchDelay = 0;
|
m_latchDelay = 0;
|
||||||
m_resetSequencer = true;
|
m_resetSequencer = true;
|
||||||
|
m_writeStarted = false;
|
||||||
m_dbgLatchDelayedCnt = 0;
|
m_dbgLatchDelayedCnt = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk2InterfaceCard::UpdateBitStreamPositionAndDiskCycle(const ULONG uExecutedCycles)
|
UINT Disk2InterfaceCard::GetBitCellDelta(const ULONG uExecutedCycles)
|
||||||
{
|
{
|
||||||
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
|
||||||
|
|
||||||
CpuCalcCycles(uExecutedCycles);
|
CpuCalcCycles(uExecutedCycles);
|
||||||
const UINT bitCellDelta = GetBitCellDelta(ImageGetOptimalBitTiming(floppy.m_imagehandle));
|
|
||||||
UpdateBitStreamPosition(floppy, bitCellDelta);
|
|
||||||
|
|
||||||
m_diskLastCycle = g_nCumulativeCycles;
|
|
||||||
}
|
|
||||||
|
|
||||||
UINT Disk2InterfaceCard::GetBitCellDelta(const BYTE optimalBitTiming)
|
|
||||||
{
|
|
||||||
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
||||||
|
|
||||||
|
const BYTE optimalBitTiming = ImageGetOptimalBitTiming(floppy.m_imagehandle);
|
||||||
|
|
||||||
// NB. m_extraCycles is needed to retain accuracy:
|
// NB. m_extraCycles is needed to retain accuracy:
|
||||||
// . Read latch #1: 0-> 9: cycleDelta= 9, bitCellDelta=2, extraCycles=1
|
// . Read latch #1: 0-> 9: cycleDelta= 9, bitCellDelta=2, extraCycles=1
|
||||||
// . Read latch #2: 9->20: cycleDelta=11, bitCellDelta=2, extraCycles=3
|
// . Read latch #2: 9->20: cycleDelta=11, bitCellDelta=2, extraCycles=3
|
||||||
@ -1010,9 +999,9 @@ UINT Disk2InterfaceCard::GetBitCellDelta(const BYTE optimalBitTiming)
|
|||||||
#if 0
|
#if 0
|
||||||
if (optimalBitTiming == 32)
|
if (optimalBitTiming == 32)
|
||||||
{
|
{
|
||||||
const ULONG cycleDelta = (ULONG)(g_nCumulativeCycles - m_diskLastCycle) + (BYTE) m_extraCycles;
|
const ULONG cycleDelta = (ULONG)(g_nCumulativeCycles - m_diskLastCycle) + (BYTE) floppy.m_extraCycles;
|
||||||
bitCellDelta = cycleDelta / 4; // DIV 4 for 4us per bit-cell
|
bitCellDelta = cycleDelta / 4; // DIV 4 for 4us per bit-cell
|
||||||
m_extraCycles = cycleDelta & 3; // MOD 4 : remainder carried forward for next time
|
floppy.m_extraCycles = cycleDelta & 3; // MOD 4 : remainder carried forward for next time
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -1022,6 +1011,11 @@ UINT Disk2InterfaceCard::GetBitCellDelta(const BYTE optimalBitTiming)
|
|||||||
bitCellDelta = (UINT) floor( cycleDelta / bitTime );
|
bitCellDelta = (UINT) floor( cycleDelta / bitTime );
|
||||||
floppy.m_extraCycles = (double)cycleDelta - ((double)bitCellDelta * bitTime);
|
floppy.m_extraCycles = (double)cycleDelta - ((double)bitCellDelta * bitTime);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NB. actual m_diskLastCycle for the last bitCell is minus floppy.m_extraCycles
|
||||||
|
// - but don't need this value; and it's correctly accounted for in this function.
|
||||||
|
m_diskLastCycle = g_nCumulativeCycles;
|
||||||
|
|
||||||
return bitCellDelta;
|
return bitCellDelta;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1036,6 +1030,8 @@ void Disk2InterfaceCard::UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG
|
|||||||
floppy.m_bitOffset %= floppy.m_bitCount;
|
floppy.m_bitOffset %= floppy.m_bitCount;
|
||||||
|
|
||||||
UpdateBitStreamOffsets(floppy);
|
UpdateBitStreamOffsets(floppy);
|
||||||
|
|
||||||
|
m_resetSequencer = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy)
|
void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy)
|
||||||
@ -1045,8 +1041,28 @@ void Disk2InterfaceCard::UpdateBitStreamOffsets(FloppyDisk& floppy)
|
|||||||
floppy.m_bitMask = 1 << remainder;
|
floppy.m_bitMask = 1 << remainder;
|
||||||
}
|
}
|
||||||
|
|
||||||
void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles)
|
__forceinline void Disk2InterfaceCard::IncBitStream(FloppyDisk& floppy)
|
||||||
{
|
{
|
||||||
|
floppy.m_bitMask >>= 1;
|
||||||
|
if (!floppy.m_bitMask)
|
||||||
|
{
|
||||||
|
floppy.m_bitMask = 1 << 7;
|
||||||
|
floppy.m_byte++;
|
||||||
|
}
|
||||||
|
|
||||||
|
floppy.m_bitOffset++;
|
||||||
|
if (floppy.m_bitOffset == floppy.m_bitCount)
|
||||||
|
{
|
||||||
|
floppy.m_bitMask = 1 << 7;
|
||||||
|
floppy.m_bitOffset = 0;
|
||||||
|
floppy.m_byte = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, ULONG uExecutedCycles)
|
||||||
|
{
|
||||||
|
_ASSERT(m_seqFunc.function != dataShiftWrite);
|
||||||
|
|
||||||
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
||||||
FloppyDisk& floppy = drive.m_disk;
|
FloppyDisk& floppy = drive.m_disk;
|
||||||
|
|
||||||
@ -1067,14 +1083,11 @@ void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYT
|
|||||||
if (!drive.m_spinning) // GH#599
|
if (!drive.m_spinning) // GH#599
|
||||||
return;
|
return;
|
||||||
|
|
||||||
CpuCalcCycles(uExecutedCycles);
|
|
||||||
|
|
||||||
// Skipping forward a large amount of bitcells means the bitstream will very likely be out-of-sync.
|
// Skipping forward a large amount of bitcells means the bitstream will very likely be out-of-sync.
|
||||||
// The first 1-bit will produce a latch nibble, and this 1-bit is unlikely to be the nibble's high bit.
|
// The first 1-bit will produce a latch nibble, and this 1-bit is unlikely to be the nibble's high bit.
|
||||||
// So we need to ensure we run enough bits through the sequencer to re-sync.
|
// So we need to ensure we run enough bits through the sequencer to re-sync.
|
||||||
// NB. For Planetfall 13 bitcells(NG) / 14 bitcells(OK)
|
|
||||||
const UINT significantBitCells = 50; // 5x 10-bit sync FF nibbles
|
const UINT significantBitCells = 50; // 5x 10-bit sync FF nibbles
|
||||||
UINT bitCellDelta = GetBitCellDelta(ImageGetOptimalBitTiming(floppy.m_imagehandle));
|
UINT bitCellDelta = GetBitCellDelta(uExecutedCycles);
|
||||||
|
|
||||||
UINT bitCellRemainder;
|
UINT bitCellRemainder;
|
||||||
if (bitCellDelta <= significantBitCells)
|
if (bitCellDelta <= significantBitCells)
|
||||||
@ -1092,20 +1105,21 @@ void __stdcall Disk2InterfaceCard::DataLatchReadWriteWOZ(WORD pc, WORD addr, BYT
|
|||||||
drive.m_headWindow = 0;
|
drive.m_headWindow = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// NB. actual m_diskLastCycle for the last bitCell is minus floppy.m_extraCycles
|
|
||||||
// - but don't need this value; and it's correctly accounted for in GetBitCellDelta()
|
|
||||||
m_diskLastCycle = g_nCumulativeCycles;
|
|
||||||
|
|
||||||
if (!bWrite)
|
if (!bWrite)
|
||||||
{
|
{
|
||||||
if (m_seqFunc.function != readSequencing)
|
if (m_seqFunc.function != readSequencing)
|
||||||
|
{
|
||||||
|
_ASSERT(m_seqFunc.function == checkWriteProtAndInitWrite);
|
||||||
|
UpdateBitStreamPosition(floppy, bitCellRemainder);
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
DataLatchReadWOZ(pc, addr, bitCellRemainder);
|
DataLatchReadWOZ(pc, addr, bitCellRemainder);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
DataLatchWriteWOZ(pc, addr, d, bitCellRemainder);
|
_ASSERT(m_seqFunc.function == dataLoadWrite);
|
||||||
|
DataLoadWriteWOZ(pc, addr, bitCellRemainder);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Show track status (GH#201) - NB. Prevent flooding of forcing UI to redraw!!!
|
// Show track status (GH#201) - NB. Prevent flooding of forcing UI to redraw!!!
|
||||||
@ -1147,20 +1161,7 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain
|
|||||||
BYTE outputBit = (drive.m_headWindow & 0xf) ? (drive.m_headWindow >> 1) & 1
|
BYTE outputBit = (drive.m_headWindow & 0xf) ? (drive.m_headWindow >> 1) & 1
|
||||||
: (rand() < ((RAND_MAX * 3) / 10)) ? 1 : 0; // ~30% chance of a 1 bit (Ref: WOZ-2.0)
|
: (rand() < ((RAND_MAX * 3) / 10)) ? 1 : 0; // ~30% chance of a 1 bit (Ref: WOZ-2.0)
|
||||||
|
|
||||||
floppy.m_bitMask >>= 1;
|
IncBitStream(floppy);
|
||||||
if (!floppy.m_bitMask)
|
|
||||||
{
|
|
||||||
floppy.m_bitMask = 1 << 7;
|
|
||||||
floppy.m_byte++;
|
|
||||||
}
|
|
||||||
|
|
||||||
floppy.m_bitOffset++;
|
|
||||||
if (floppy.m_bitOffset == floppy.m_bitCount)
|
|
||||||
{
|
|
||||||
floppy.m_bitMask = 1 << 7;
|
|
||||||
floppy.m_bitOffset = 0;
|
|
||||||
floppy.m_byte = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_resetSequencer)
|
if (m_resetSequencer)
|
||||||
{
|
{
|
||||||
@ -1238,17 +1239,64 @@ void Disk2InterfaceCard::DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemain
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
void Disk2InterfaceCard::DataLatchWriteWOZ(WORD pc, WORD addr, BYTE d, UINT bitCellRemainder)
|
void Disk2InterfaceCard::DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemainder)
|
||||||
{
|
{
|
||||||
_ASSERT(m_seqFunc.writeMode);
|
_ASSERT(m_seqFunc.function == dataLoadWrite);
|
||||||
|
|
||||||
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
||||||
FloppyDisk& floppy = drive.m_disk;
|
FloppyDisk& floppy = drive.m_disk;
|
||||||
|
|
||||||
if (!floppy.m_bWriteProtected)
|
if (floppy.m_bWriteProtected)
|
||||||
{
|
{
|
||||||
//TODO
|
_ASSERT(0); // Must be a bug in the 6502 code for this to occur!
|
||||||
|
UpdateBitStreamPosition(floppy, bitCellRemainder);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_writeStarted)
|
||||||
|
UpdateBitStreamPosition(floppy, bitCellRemainder); // skip over bitCells before switching to write mode
|
||||||
|
|
||||||
|
m_writeStarted = true;
|
||||||
|
#if LOG_DISK_WOZ_LOADWRITE
|
||||||
|
LOG_DISK("load shiftReg with %02X (was: %02X)\n", m_floppyLatch, m_shiftReg);
|
||||||
|
#endif
|
||||||
|
m_shiftReg = m_floppyLatch;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Disk2InterfaceCard::DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles)
|
||||||
|
{
|
||||||
|
_ASSERT(m_seqFunc.function == dataShiftWrite);
|
||||||
|
|
||||||
|
FloppyDrive& drive = m_floppyDrive[m_currDrive];
|
||||||
|
FloppyDisk& floppy = drive.m_disk;
|
||||||
|
|
||||||
|
const UINT bitCellRemainder = GetBitCellDelta(uExecutedCycles);
|
||||||
|
|
||||||
|
if (floppy.m_bWriteProtected)
|
||||||
|
{
|
||||||
|
_ASSERT(0); // Must be a bug in the 6502 code for this to occur!
|
||||||
|
UpdateBitStreamPosition(floppy, bitCellRemainder);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LOG_DISK_WOZ_SHIFTWRITE
|
||||||
|
LOG_DISK("T$%02X, bitOffset=%04X: %02X (%d bits)\n", drive.m_phase/2, floppy.m_bitOffset, m_shiftReg, bitCellRemainder);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
for (UINT i = 0; i < bitCellRemainder; i++)
|
||||||
|
{
|
||||||
|
BYTE outputBit = m_shiftReg & 0x80;
|
||||||
|
m_shiftReg <<= 1;
|
||||||
|
|
||||||
|
BYTE n = floppy.m_trackimage[floppy.m_byte];
|
||||||
|
n &= ~floppy.m_bitMask;
|
||||||
|
if (outputBit) n |= floppy.m_bitMask;
|
||||||
|
floppy.m_trackimage[floppy.m_byte] = n;
|
||||||
|
|
||||||
|
IncBitStream(floppy);
|
||||||
|
}
|
||||||
|
|
||||||
|
floppy.m_trackimagedirty = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
@ -1485,7 +1533,9 @@ bool Disk2InterfaceCard::UserSelectNewDiskImage(const int drive, LPCSTR pszFilen
|
|||||||
|
|
||||||
void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG uExecutedCycles)
|
void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG uExecutedCycles)
|
||||||
{
|
{
|
||||||
// NB. m_seqFunc.function == checkWriteProtAndInitWrite or shiftWrite (both OK)
|
// NB. Only reads in LOAD mode can issue the SR (shift write-protect) operation - UTAIIe page 9-20, fig 9.11
|
||||||
|
// But STA $C08D,X (no PX) does a read from $C08D+X, followed by the write to $C08D+X
|
||||||
|
// So just want to ignore: STA $C0ED or eg. STA $BFFF,X (PX, X=$EE)
|
||||||
|
|
||||||
// Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13)
|
// Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13)
|
||||||
// "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12)
|
// "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12)
|
||||||
@ -1500,20 +1550,27 @@ void __stdcall Disk2InterfaceCard::LoadWriteProtect(WORD, WORD, BYTE write, BYTE
|
|||||||
// the write protect switch would still be read correctly" (UTAIIe page 9-21)
|
// the write protect switch would still be read correctly" (UTAIIe page 9-21)
|
||||||
// . Sequencer "SR" (Shift Right) command only loads QA (bit7) of data register (UTAIIe page 9-21)
|
// . Sequencer "SR" (Shift Right) command only loads QA (bit7) of data register (UTAIIe page 9-21)
|
||||||
// . A read or write will shift 'write protect' in QA.
|
// . A read or write will shift 'write protect' in QA.
|
||||||
if (m_floppyDrive[m_currDrive].m_disk.m_bWriteProtected)
|
FloppyDisk& floppy = m_floppyDrive[m_currDrive].m_disk;
|
||||||
|
if (floppy.m_bWriteProtected)
|
||||||
m_floppyLatch |= 0x80;
|
m_floppyLatch |= 0x80;
|
||||||
else
|
else
|
||||||
m_floppyLatch &= 0x7F;
|
m_floppyLatch &= 0x7F;
|
||||||
|
|
||||||
if (ImageIsWOZ(m_floppyDrive[m_currDrive].m_disk.m_imagehandle))
|
if (m_writeStarted) // Prevent ResetLogicStateSequencer() from resetting m_writeStarted
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (ImageIsWOZ(floppy.m_imagehandle))
|
||||||
{
|
{
|
||||||
#if LOG_DISK_NIBBLES_READ
|
#if LOG_DISK_NIBBLES_READ
|
||||||
CpuCalcCycles(uExecutedCycles);
|
CpuCalcCycles(uExecutedCycles);
|
||||||
LOG_DISK("%08X: reset LSS: ~PC=%04X\r\n", (UINT32)g_nCumulativeCycles, regs.pc);
|
LOG_DISK("%08X: reset LSS: ~PC=%04X\r\n", (UINT32)g_nCumulativeCycles, regs.pc);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
const UINT bitCellDelta = GetBitCellDelta(uExecutedCycles);
|
||||||
|
UpdateBitStreamPosition(floppy, bitCellDelta); // Fix E7-copy protection
|
||||||
|
|
||||||
|
// UpdateBitStreamPosition() must be done below ResetLSS, as the former clears m_resetSequencer. (Commando.woz is sensitive to this)
|
||||||
ResetLogicStateSequencer(); // reset sequencer (UTAIIe page 9-21)
|
ResetLogicStateSequencer(); // reset sequencer (UTAIIe page 9-21)
|
||||||
// m_latchDelay = 7; // TODO: Treat like a regular $C0EC latch load?
|
|
||||||
UpdateBitStreamPositionAndDiskCycle(uExecutedCycles); // Fix E7-copy protection
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1688,6 +1745,9 @@ void Disk2InterfaceCard::SetSequencerFunction(WORD addr)
|
|||||||
case 2: m_seqFunc.loadMode = 0; break; // $C08C,X (sequence addr A3 input)
|
case 2: m_seqFunc.loadMode = 0; break; // $C08C,X (sequence addr A3 input)
|
||||||
case 3: m_seqFunc.loadMode = 1; break; // $C08D,X (sequence addr A3 input)
|
case 3: m_seqFunc.loadMode = 1; break; // $C08D,X (sequence addr A3 input)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!m_seqFunc.writeMode)
|
||||||
|
m_writeStarted = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
|
BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
|
||||||
@ -1698,6 +1758,9 @@ BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||||||
ImageInfo* pImage = pCard->m_floppyDrive[pCard->m_currDrive].m_disk.m_imagehandle;
|
ImageInfo* pImage = pCard->m_floppyDrive[pCard->m_currDrive].m_disk.m_imagehandle;
|
||||||
bool isWOZ = ImageIsWOZ(pImage);
|
bool isWOZ = ImageIsWOZ(pImage);
|
||||||
|
|
||||||
|
if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite) // Occurs at end of sector write ($C0EE)
|
||||||
|
pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write
|
||||||
|
|
||||||
pCard->SetSequencerFunction(addr);
|
pCard->SetSequencerFunction(addr);
|
||||||
|
|
||||||
switch (addr & 0xF)
|
switch (addr & 0xF)
|
||||||
@ -1723,8 +1786,8 @@ BYTE __stdcall Disk2InterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||||||
// only even addresses return the latch (UTAIIe Table 9.1)
|
// only even addresses return the latch (UTAIIe Table 9.1)
|
||||||
if (!(addr & 1))
|
if (!(addr & 1))
|
||||||
{
|
{
|
||||||
if (isWOZ)
|
if (isWOZ && pCard->m_seqFunc.function != dataShiftWrite)
|
||||||
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, d, nExecutedCycles);
|
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, nExecutedCycles);
|
||||||
|
|
||||||
return pCard->m_floppyLatch;
|
return pCard->m_floppyLatch;
|
||||||
}
|
}
|
||||||
@ -1740,6 +1803,9 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||||||
ImageInfo* pImage = pCard->m_floppyDrive[pCard->m_currDrive].m_disk.m_imagehandle;
|
ImageInfo* pImage = pCard->m_floppyDrive[pCard->m_currDrive].m_disk.m_imagehandle;
|
||||||
bool isWOZ = ImageIsWOZ(pImage);
|
bool isWOZ = ImageIsWOZ(pImage);
|
||||||
|
|
||||||
|
if (isWOZ && pCard->m_seqFunc.function == dataShiftWrite)
|
||||||
|
pCard->DataShiftWriteWOZ(pc, addr, nExecutedCycles); // Finish any previous write
|
||||||
|
|
||||||
pCard->SetSequencerFunction(addr);
|
pCard->SetSequencerFunction(addr);
|
||||||
|
|
||||||
switch (addr & 0xF)
|
switch (addr & 0xF)
|
||||||
@ -1763,13 +1829,12 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
|
|||||||
}
|
}
|
||||||
|
|
||||||
// any address writes the latch via sequencer LD command (74LS323 datasheet)
|
// any address writes the latch via sequencer LD command (74LS323 datasheet)
|
||||||
// if (pCard->m_seqFunc.writeMode /* && m_seqFunc.loadMode */)
|
|
||||||
if (pCard->m_seqFunc.function == dataLoadWrite)
|
if (pCard->m_seqFunc.function == dataLoadWrite)
|
||||||
{
|
{
|
||||||
pCard->m_floppyLatch = d;
|
pCard->m_floppyLatch = d;
|
||||||
|
|
||||||
if (isWOZ)
|
if (isWOZ)
|
||||||
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, d, nExecutedCycles);
|
pCard->DataLatchReadWriteWOZ(pc, addr, bWrite, nExecutedCycles);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -185,12 +185,13 @@ private:
|
|||||||
void WriteTrack(const int drive);
|
void WriteTrack(const int drive);
|
||||||
const std::string & DiskGetFullPathName(const int drive);
|
const std::string & DiskGetFullPathName(const int drive);
|
||||||
void ResetLogicStateSequencer(void);
|
void ResetLogicStateSequencer(void);
|
||||||
void UpdateBitStreamPositionAndDiskCycle(const ULONG uExecutedCycles);
|
UINT GetBitCellDelta(const ULONG uExecutedCycles);
|
||||||
UINT GetBitCellDelta(const BYTE optimalBitTiming);
|
|
||||||
void UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG bitCellDelta);
|
void UpdateBitStreamPosition(FloppyDisk& floppy, const ULONG bitCellDelta);
|
||||||
void UpdateBitStreamOffsets(FloppyDisk& floppy);
|
void UpdateBitStreamOffsets(FloppyDisk& floppy);
|
||||||
|
__forceinline void IncBitStream(FloppyDisk& floppy);
|
||||||
void DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
|
void DataLatchReadWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
|
||||||
void DataLatchWriteWOZ(WORD pc, WORD addr, BYTE d, UINT bitCellRemainder);
|
void DataLoadWriteWOZ(WORD pc, WORD addr, UINT bitCellRemainder);
|
||||||
|
void DataShiftWriteWOZ(WORD pc, WORD addr, ULONG uExecutedCycles);
|
||||||
void SetSequencerFunction(WORD addr);
|
void SetSequencerFunction(WORD addr);
|
||||||
void DumpSectorWOZ(FloppyDisk floppy);
|
void DumpSectorWOZ(FloppyDisk floppy);
|
||||||
void DumpTrackWOZ(FloppyDisk floppy);
|
void DumpTrackWOZ(FloppyDisk floppy);
|
||||||
@ -206,7 +207,7 @@ private:
|
|||||||
void __stdcall ControlMotor(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles);
|
void __stdcall ControlMotor(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles);
|
||||||
void __stdcall Enable(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles);
|
void __stdcall Enable(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles);
|
||||||
void __stdcall ReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
void __stdcall ReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
||||||
void __stdcall DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
|
void __stdcall DataLatchReadWriteWOZ(WORD pc, WORD addr, BYTE bWrite, ULONG uExecutedCycles);
|
||||||
void __stdcall LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG);
|
void __stdcall LoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG);
|
||||||
void __stdcall SetReadMode(WORD, WORD, BYTE, BYTE, ULONG);
|
void __stdcall SetReadMode(WORD, WORD, BYTE, BYTE, ULONG);
|
||||||
void __stdcall SetWriteMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCycles);
|
void __stdcall SetWriteMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCycles);
|
||||||
@ -240,8 +241,9 @@ private:
|
|||||||
BYTE m_shiftReg;
|
BYTE m_shiftReg;
|
||||||
int m_latchDelay;
|
int m_latchDelay;
|
||||||
bool m_resetSequencer;
|
bool m_resetSequencer;
|
||||||
|
bool m_writeStarted;
|
||||||
|
|
||||||
enum SEQFUNC {readSequencing=0, checkWriteProtAndInitWrite, dataShiftWrite, dataLoadWrite}; // UTAIIe 9-14
|
enum SEQFUNC {readSequencing=0, dataShiftWrite, checkWriteProtAndInitWrite, dataLoadWrite}; // UTAIIe 9-14
|
||||||
union SEQUENCER_FUNCTION
|
union SEQUENCER_FUNCTION
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
|
@ -63,7 +63,7 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
|||||||
ImageError_e Err = pImageInfo->pImageHelper->Open(pszImageFilename.c_str(), pImageInfo, bCreateIfNecessary, strFilenameInZip);
|
ImageError_e Err = pImageInfo->pImageHelper->Open(pszImageFilename.c_str(), pImageInfo, bCreateIfNecessary, strFilenameInZip);
|
||||||
if (Err != eIMAGE_ERROR_NONE)
|
if (Err != eIMAGE_ERROR_NONE)
|
||||||
{
|
{
|
||||||
ImageClose(*ppImageInfo, true);
|
ImageClose(*ppImageInfo);
|
||||||
*ppImageInfo = NULL;
|
*ppImageInfo = NULL;
|
||||||
return Err;
|
return Err;
|
||||||
}
|
}
|
||||||
@ -83,9 +83,6 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
|||||||
|
|
||||||
pImageInfo->uNumTracks = sg_DiskImageHelper.GetNumTracksInImage(pImageInfo->pImageType);
|
pImageInfo->uNumTracks = sg_DiskImageHelper.GetNumTracksInImage(pImageInfo->pImageType);
|
||||||
|
|
||||||
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
|
|
||||||
pImageInfo->ValidTrack[uTrack] = (pImageInfo->uImageSize > 0) ? 1 : 0;
|
|
||||||
|
|
||||||
*pWriteProtected = pImageInfo->bWriteProtected;
|
*pWriteProtected = pImageInfo->bWriteProtected;
|
||||||
|
|
||||||
return eIMAGE_ERROR_NONE;
|
return eIMAGE_ERROR_NONE;
|
||||||
@ -93,25 +90,9 @@ ImageError_e ImageOpen( const std::string & pszImageFilename,
|
|||||||
|
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
void ImageClose(ImageInfo* const pImageInfo, const bool bOpenError /*=false*/)
|
void ImageClose(ImageInfo* const pImageInfo)
|
||||||
{
|
{
|
||||||
bool bDeleteFile = false;
|
pImageInfo->pImageHelper->Close(pImageInfo);
|
||||||
|
|
||||||
if (!bOpenError)
|
|
||||||
{
|
|
||||||
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
|
|
||||||
{
|
|
||||||
if (!pImageInfo->ValidTrack[uTrack])
|
|
||||||
{
|
|
||||||
// TODO: Comment using info from this URL:
|
|
||||||
// http://groups.google.de/group/comp.emulators.apple2/msg/7a1b9317e7905152
|
|
||||||
bDeleteFile = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pImageInfo->pImageHelper->Close(pImageInfo, bDeleteFile);
|
|
||||||
|
|
||||||
delete pImageInfo;
|
delete pImageInfo;
|
||||||
}
|
}
|
||||||
@ -162,7 +143,7 @@ void ImageReadTrack( ImageInfo* const pImageInfo,
|
|||||||
|
|
||||||
const UINT track = pImageInfo->pImageType->PhaseToTrack(phase);
|
const UINT track = pImageInfo->pImageType->PhaseToTrack(phase);
|
||||||
|
|
||||||
if (pImageInfo->pImageType->AllowRW() && pImageInfo->ValidTrack[track])
|
if (pImageInfo->pImageType->AllowRW())
|
||||||
{
|
{
|
||||||
pImageInfo->pImageType->Read(pImageInfo, phase, pTrackImageBuffer, pNibbles, pBitCount, enhanceDisk);
|
pImageInfo->pImageType->Read(pImageInfo, phase, pTrackImageBuffer, pNibbles, pBitCount, enhanceDisk);
|
||||||
}
|
}
|
||||||
@ -190,7 +171,14 @@ void ImageWriteTrack( ImageInfo* const pImageInfo,
|
|||||||
if (pImageInfo->pImageType->AllowRW() && !pImageInfo->bWriteProtected)
|
if (pImageInfo->pImageType->AllowRW() && !pImageInfo->bWriteProtected)
|
||||||
{
|
{
|
||||||
pImageInfo->pImageType->Write(pImageInfo, phase, pTrackImageBuffer, nNibbles);
|
pImageInfo->pImageType->Write(pImageInfo, phase, pTrackImageBuffer, nNibbles);
|
||||||
pImageInfo->ValidTrack[track] = 1;
|
|
||||||
|
eImageType imageType = pImageInfo->pImageType->GetType();
|
||||||
|
if (imageType == eImageWOZ1 || imageType == eImageWOZ2)
|
||||||
|
{
|
||||||
|
DWORD dummy;
|
||||||
|
bool res = sg_DiskImageHelper.WOZUpdateInfo(pImageInfo, dummy);
|
||||||
|
_ASSERT(res);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -234,7 +222,7 @@ bool ImageIsWriteProtected(ImageInfo* const pImageInfo)
|
|||||||
|
|
||||||
bool ImageIsMultiFileZip(ImageInfo* const pImageInfo)
|
bool ImageIsMultiFileZip(ImageInfo* const pImageInfo)
|
||||||
{
|
{
|
||||||
return pImageInfo ? (pImageInfo->uNumEntriesInZip > 1) : false;
|
return pImageInfo ? (pImageInfo->uNumValidImagesInZip > 1) : false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string & ImageGetPathname(ImageInfo* const pImageInfo)
|
const std::string & ImageGetPathname(ImageInfo* const pImageInfo)
|
||||||
|
@ -51,7 +51,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
eIMAGE_ERROR_GZ,
|
eIMAGE_ERROR_GZ,
|
||||||
eIMAGE_ERROR_ZIP,
|
eIMAGE_ERROR_ZIP,
|
||||||
eIMAGE_ERROR_REJECTED_MULTI_ZIP,
|
eIMAGE_ERROR_REJECTED_MULTI_ZIP,
|
||||||
eIMAGE_ERROR_UNSUPPORTED_MULTI_ZIP,
|
|
||||||
eIMAGE_ERROR_UNABLE_TO_OPEN,
|
eIMAGE_ERROR_UNABLE_TO_OPEN,
|
||||||
eIMAGE_ERROR_UNABLE_TO_OPEN_GZ,
|
eIMAGE_ERROR_UNABLE_TO_OPEN_GZ,
|
||||||
eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP,
|
eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP,
|
||||||
@ -66,7 +65,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|||||||
struct ImageInfo;
|
struct ImageInfo;
|
||||||
|
|
||||||
ImageError_e ImageOpen(const std::string & pszImageFilename, ImageInfo** ppImageInfo, bool* pWriteProtected, const bool bCreateIfNecessary, std::string& strFilenameInZip, const bool bExpectFloppy=true);
|
ImageError_e ImageOpen(const std::string & pszImageFilename, ImageInfo** ppImageInfo, bool* pWriteProtected, const bool bCreateIfNecessary, std::string& strFilenameInZip, const bool bExpectFloppy=true);
|
||||||
void ImageClose(ImageInfo* const pImageInfo, const bool bOpenError=false);
|
void ImageClose(ImageInfo* const pImageInfo);
|
||||||
BOOL ImageBoot(ImageInfo* const pImageInfo);
|
BOOL ImageBoot(ImageInfo* const pImageInfo);
|
||||||
void ImageDestroy(void);
|
void ImageDestroy(void);
|
||||||
void ImageInitialize(void);
|
void ImageInitialize(void);
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -31,11 +31,11 @@ struct ImageInfo
|
|||||||
std::string szFilenameInZip;
|
std::string szFilenameInZip;
|
||||||
zip_fileinfo zipFileInfo;
|
zip_fileinfo zipFileInfo;
|
||||||
UINT uNumEntriesInZip;
|
UINT uNumEntriesInZip;
|
||||||
|
UINT uNumValidImagesInZip;
|
||||||
// Floppy only
|
// Floppy only
|
||||||
BYTE ValidTrack[TRACKS_MAX];
|
|
||||||
UINT uNumTracks;
|
UINT uNumTracks;
|
||||||
BYTE* pImageBuffer;
|
BYTE* pImageBuffer;
|
||||||
BYTE* pTrackMap; // WOZ only
|
BYTE* pWOZTrackMap; // WOZ only (points into pImageBuffer)
|
||||||
BYTE optimalBitTiming; // WOZ only
|
BYTE optimalBitTiming; // WOZ only
|
||||||
UINT maxNibblesPerTrack;
|
UINT maxNibblesPerTrack;
|
||||||
|
|
||||||
@ -73,6 +73,7 @@ public:
|
|||||||
virtual const char* GetCreateExtensions(void) = 0;
|
virtual const char* GetCreateExtensions(void) = 0;
|
||||||
virtual const char* GetRejectExtensions(void) = 0;
|
virtual const char* GetRejectExtensions(void) = 0;
|
||||||
|
|
||||||
|
bool WriteImageHeader(ImageInfo* pImageInfo, LPBYTE pHdr, const UINT hdrSize);
|
||||||
void SetVolumeNumber(const BYTE uVolumeNumber) { m_uVolumeNumber = uVolumeNumber; }
|
void SetVolumeNumber(const BYTE uVolumeNumber) { m_uVolumeNumber = uVolumeNumber; }
|
||||||
bool IsValidImageSize(const DWORD uImageSize);
|
bool IsValidImageSize(const DWORD uImageSize);
|
||||||
|
|
||||||
@ -88,6 +89,7 @@ protected:
|
|||||||
bool WriteTrack(ImageInfo* pImageInfo, const int nTrack, LPBYTE pTrackBuffer, const UINT uTrackSize);
|
bool WriteTrack(ImageInfo* pImageInfo, const int nTrack, LPBYTE pTrackBuffer, const UINT uTrackSize);
|
||||||
bool ReadBlock(ImageInfo* pImageInfo, const int nBlock, LPBYTE pBlockBuffer);
|
bool ReadBlock(ImageInfo* pImageInfo, const int nBlock, LPBYTE pBlockBuffer);
|
||||||
bool WriteBlock(ImageInfo* pImageInfo, const int nBlock, LPBYTE pBlockBuffer);
|
bool WriteBlock(ImageInfo* pImageInfo, const int nBlock, LPBYTE pBlockBuffer);
|
||||||
|
bool WriteImageData(ImageInfo* pImageInfo, LPBYTE pSrcBuffer, const UINT uSrcSize, const long offset);
|
||||||
|
|
||||||
LPBYTE Code62(int sector);
|
LPBYTE Code62(int sector);
|
||||||
void Decode62(LPBYTE imageptr);
|
void Decode62(LPBYTE imageptr);
|
||||||
@ -134,6 +136,10 @@ private:
|
|||||||
#pragma pack(push)
|
#pragma pack(push)
|
||||||
#pragma pack(1) // Ensure Header2IMG & WOZ structs are packed
|
#pragma pack(1) // Ensure Header2IMG & WOZ structs are packed
|
||||||
|
|
||||||
|
#pragma warning(push)
|
||||||
|
#pragma warning(disable: 4200) // Allow zero-sized array in struct
|
||||||
|
|
||||||
|
|
||||||
class C2IMGHelper : public CHdrHelper
|
class C2IMGHelper : public CHdrHelper
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -200,10 +206,15 @@ public:
|
|||||||
virtual ~CWOZHelper(void) {}
|
virtual ~CWOZHelper(void) {}
|
||||||
virtual eDetectResult DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DWORD& dwOffset) { _ASSERT(0); return eMismatch; }
|
virtual eDetectResult DetectHdr(LPBYTE& pImage, DWORD& dwImageSize, DWORD& dwOffset) { _ASSERT(0); return eMismatch; }
|
||||||
virtual UINT GetMaxHdrSize(void) { return sizeof(WOZHeader); }
|
virtual UINT GetMaxHdrSize(void) { return sizeof(WOZHeader); }
|
||||||
eDetectResult ProcessChunks(const LPBYTE pImage, const DWORD dwImageSize, DWORD& dwOffset, BYTE*& pTrackMap);
|
eDetectResult ProcessChunks(ImageInfo* pImageInfo, DWORD& dwOffset);
|
||||||
bool IsWriteProtected(void) { return m_pInfo->v1.writeProtected == 1; }
|
bool IsWriteProtected(void) { return m_pInfo->v1.writeProtected == 1; }
|
||||||
BYTE GetOptimalBitTiming(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->optimalBitTiming : CWOZHelper::InfoChunkv2::optimalBitTiming5_25; }
|
BYTE GetOptimalBitTiming(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->optimalBitTiming : InfoChunkv2::optimalBitTiming5_25; }
|
||||||
UINT GetMaxNibblesPerTrack(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->largestTrack*CWOZHelper::BLOCK_SIZE : CWOZHelper::WOZ1_TRACK_SIZE; }
|
UINT GetMaxNibblesPerTrack(void) { return (m_pInfo->v1.version >= 2) ? m_pInfo->largestTrack*CWOZHelper::BLOCK_SIZE : WOZ1_TRACK_SIZE; }
|
||||||
|
void InvalidateInfo(void) { m_pInfo = NULL; }
|
||||||
|
BYTE* CreateEmptyDisk(DWORD& size);
|
||||||
|
#if _DEBUG
|
||||||
|
BYTE* CreateEmptyDiskv1(DWORD& size);
|
||||||
|
#endif
|
||||||
|
|
||||||
static const UINT32 ID1_WOZ1 = '1ZOW'; // 'WOZ1'
|
static const UINT32 ID1_WOZ1 = '1ZOW'; // 'WOZ1'
|
||||||
static const UINT32 ID1_WOZ2 = '2ZOW'; // 'WOZ2'
|
static const UINT32 ID1_WOZ2 = '2ZOW'; // 'WOZ2'
|
||||||
@ -217,10 +228,24 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
static const UINT32 MAX_TRACKS_5_25 = 40;
|
static const UINT32 MAX_TRACKS_5_25 = 40;
|
||||||
|
static const UINT32 MAX_QUARTER_TRACKS_5_25 = MAX_TRACKS_5_25 * 4;
|
||||||
static const UINT32 WOZ1_TRACK_SIZE = 6656; // 0x1A00
|
static const UINT32 WOZ1_TRACK_SIZE = 6656; // 0x1A00
|
||||||
static const UINT32 WOZ1_TRK_OFFSET = 6646;
|
static const UINT32 WOZ1_TRK_OFFSET = 6646;
|
||||||
static const UINT32 EMPTY_TRACK_SIZE = 6400;
|
static const UINT32 EMPTY_TRACK_SIZE = 6400; // $C.5 blocks
|
||||||
static const UINT32 BLOCK_SIZE = 512;
|
static const UINT32 BLOCK_SIZE = 512;
|
||||||
|
static const BYTE TMAP_TRACK_EMPTY = 0xFF;
|
||||||
|
static const UINT16 TRK_DEFAULT_BLOCK_COUNT_5_25 = 13; // $D is default for TRKv2.blockCount
|
||||||
|
|
||||||
|
struct WOZChunkHdr
|
||||||
|
{
|
||||||
|
UINT32 id;
|
||||||
|
UINT32 size;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Tmap
|
||||||
|
{
|
||||||
|
BYTE tmap[MAX_QUARTER_TRACKS_5_25];
|
||||||
|
};
|
||||||
|
|
||||||
struct TRKv1
|
struct TRKv1
|
||||||
{
|
{
|
||||||
@ -239,17 +264,22 @@ public:
|
|||||||
UINT32 bitCount;
|
UINT32 bitCount;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct Trks
|
||||||
|
{
|
||||||
|
TRKv2 trks[MAX_QUARTER_TRACKS_5_25];
|
||||||
|
BYTE bits[0]; // bits[] starts at offset 3 x BLOCK_SIZE = 1536
|
||||||
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static const UINT32 INFO_CHUNK_ID = 'OFNI'; // 'INFO'
|
static const UINT32 INFO_CHUNK_ID = 'OFNI'; // 'INFO'
|
||||||
static const UINT32 TMAP_CHUNK_ID = 'PAMT'; // 'TMAP'
|
static const UINT32 TMAP_CHUNK_ID = 'PAMT'; // 'TMAP'
|
||||||
static const UINT32 TRKS_CHUNK_ID = 'SKRT'; // 'TRKS'
|
static const UINT32 TRKS_CHUNK_ID = 'SKRT'; // 'TRKS'
|
||||||
static const UINT32 WRIT_CHUNK_ID = 'TIRW'; // 'WRIT' - WOZv2
|
static const UINT32 WRIT_CHUNK_ID = 'TIRW'; // 'WRIT' - WOZv2
|
||||||
static const UINT32 META_CHUNK_ID = 'ATEM'; // 'META'
|
static const UINT32 META_CHUNK_ID = 'ATEM'; // 'META'
|
||||||
|
static const UINT32 INFO_CHUNK_SIZE = 60; // Fixed size for both WOZv1 & WOZv2
|
||||||
|
|
||||||
struct InfoChunk
|
struct InfoChunk
|
||||||
{
|
{
|
||||||
UINT32 id;
|
|
||||||
UINT32 size;
|
|
||||||
BYTE version;
|
BYTE version;
|
||||||
BYTE diskType;
|
BYTE diskType;
|
||||||
BYTE writeProtected; // 1 = Floppy is write protected
|
BYTE writeProtected; // 1 = Floppy is write protected
|
||||||
@ -281,9 +311,41 @@ private:
|
|||||||
static const BYTE optimalBitTiming5_25 = 32;
|
static const BYTE optimalBitTiming5_25 = 32;
|
||||||
};
|
};
|
||||||
|
|
||||||
InfoChunkv2* m_pInfo;
|
InfoChunkv2* m_pInfo; // NB. image-specific - only valid during Detect(), which calls InvalidateInfo() when done
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
|
struct WOZEmptyImage525 // 5.25"
|
||||||
|
{
|
||||||
|
WOZHeader hdr;
|
||||||
|
|
||||||
|
WOZChunkHdr infoHdr;
|
||||||
|
InfoChunkv2 info;
|
||||||
|
BYTE infoPadding[INFO_CHUNK_SIZE-sizeof(InfoChunkv2)];
|
||||||
|
|
||||||
|
WOZChunkHdr tmapHdr;
|
||||||
|
Tmap tmap;
|
||||||
|
|
||||||
|
WOZChunkHdr trksHdr;
|
||||||
|
Trks trks;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct WOZv1EmptyImage525 // 5.25"
|
||||||
|
{
|
||||||
|
WOZHeader hdr;
|
||||||
|
|
||||||
|
WOZChunkHdr infoHdr;
|
||||||
|
InfoChunk info;
|
||||||
|
BYTE infoPadding[INFO_CHUNK_SIZE-sizeof(InfoChunk)];
|
||||||
|
|
||||||
|
WOZChunkHdr tmapHdr;
|
||||||
|
Tmap tmap;
|
||||||
|
|
||||||
|
WOZChunkHdr trksHdr;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
#pragma warning(pop)
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
//-------------------------------------
|
//-------------------------------------
|
||||||
@ -304,7 +366,8 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
ImageError_e Open(LPCTSTR pszImageFilename, ImageInfo* pImageInfo, const bool bCreateIfNecessary, std::string& strFilenameInZip);
|
ImageError_e Open(LPCTSTR pszImageFilename, ImageInfo* pImageInfo, const bool bCreateIfNecessary, std::string& strFilenameInZip);
|
||||||
void Close(ImageInfo* pImageInfo, const bool bDeleteFile);
|
void Close(ImageInfo* pImageInfo);
|
||||||
|
bool WOZUpdateInfo(ImageInfo* pImageInfo, DWORD& dwOffset);
|
||||||
|
|
||||||
virtual CImageBase* Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, ImageInfo* pImageInfo) = 0;
|
virtual CImageBase* Detect(LPBYTE pImage, DWORD dwSize, const TCHAR* pszExt, DWORD& dwOffset, ImageInfo* pImageInfo) = 0;
|
||||||
virtual CImageBase* GetImageForCreation(const TCHAR* pszExt, DWORD* pCreateImageSize) = 0;
|
virtual CImageBase* GetImageForCreation(const TCHAR* pszExt, DWORD* pCreateImageSize) = 0;
|
||||||
@ -317,7 +380,7 @@ protected:
|
|||||||
ImageError_e CheckNormalFile(LPCTSTR pszImageFilename, ImageInfo* pImageInfo, const bool bCreateIfNecessary);
|
ImageError_e CheckNormalFile(LPCTSTR pszImageFilename, ImageInfo* pImageInfo, const bool bCreateIfNecessary);
|
||||||
void GetCharLowerExt(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize);
|
void GetCharLowerExt(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize);
|
||||||
void GetCharLowerExt2(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize);
|
void GetCharLowerExt2(TCHAR* pszExt, LPCTSTR pszImageFilename, const UINT uExtSize);
|
||||||
void SetImageInfo(ImageInfo* pImageInfo, FileType_e eFileGZip, DWORD dwOffset, CImageBase* pImageType, DWORD dwSize);
|
void SetImageInfo(ImageInfo* pImageInfo, FileType_e fileType, DWORD dwOffset, CImageBase* pImageType, DWORD dwSize);
|
||||||
|
|
||||||
UINT GetNumImages(void) { return m_vecImageTypes.size(); };
|
UINT GetNumImages(void) { return m_vecImageTypes.size(); };
|
||||||
CImageBase* GetImage(UINT uIndex) { _ASSERT(uIndex<GetNumImages()); return m_vecImageTypes[uIndex]; }
|
CImageBase* GetImage(UINT uIndex) { _ASSERT(uIndex<GetNumImages()); return m_vecImageTypes[uIndex]; }
|
||||||
|
@ -10,6 +10,8 @@
|
|||||||
#define LOG_DISK_NIBBLES_WRITE 1
|
#define LOG_DISK_NIBBLES_WRITE 1
|
||||||
#define LOG_DISK_NIBBLES_WRITE_TRACK_GAPS 1 // Gap1, Gap2 & Gap3 info when writing a track
|
#define LOG_DISK_NIBBLES_WRITE_TRACK_GAPS 1 // Gap1, Gap2 & Gap3 info when writing a track
|
||||||
#define LOG_DISK_NIBBLES_USE_RUNTIME_VAR 1
|
#define LOG_DISK_NIBBLES_USE_RUNTIME_VAR 1
|
||||||
|
#define LOG_DISK_WOZ_LOADWRITE 1
|
||||||
|
#define LOG_DISK_WOZ_SHIFTWRITE 1
|
||||||
|
|
||||||
// __VA_ARGS__ not supported on MSVC++ .NET 7.x
|
// __VA_ARGS__ not supported on MSVC++ .NET 7.x
|
||||||
#if (LOG_DISK_ENABLED)
|
#if (LOG_DISK_ENABLED)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user