mirror of
https://github.com/AppleWin/AppleWin.git
synced 2025-02-25 14:29:02 +00:00
Fix for A2osX low-level format for 48-trackl, 192K floppy image
This commit is contained in:
parent
b3e617f1e5
commit
de173b2729
@ -549,6 +549,10 @@ bool ProcessCmdLine(LPSTR lpCmdLine)
|
||||
lpNextArg = GetNextArg(lpNextArg);
|
||||
g_cmdLine.wavFileMockingboard = lpCmdLine;
|
||||
}
|
||||
else if (strcmp(lpCmdLine, "-no-disk2-stepper-defer") == 0) // a debug switch (likely to be removed in a future version)
|
||||
{
|
||||
g_cmdLine.noDisk2StepperDefer = true;
|
||||
}
|
||||
else // unsupported
|
||||
{
|
||||
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
|
||||
|
@ -22,6 +22,7 @@ struct CmdLine
|
||||
snesMaxAltControllerType[1] = false;
|
||||
supportDCD = false;
|
||||
enableDumpToRealPrinter = false;
|
||||
noDisk2StepperDefer = false;
|
||||
szImageName_harddisk[HARDDISK_1] = NULL;
|
||||
szImageName_harddisk[HARDDISK_2] = NULL;
|
||||
szSnapshotName = NULL;
|
||||
@ -63,6 +64,7 @@ struct CmdLine
|
||||
bool snesMaxAltControllerType[2];
|
||||
bool supportDCD;
|
||||
bool enableDumpToRealPrinter;
|
||||
bool noDisk2StepperDefer; // debug
|
||||
SS_CARDTYPE slotInsert[NUM_SLOTS];
|
||||
LPCSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES];
|
||||
bool driveConnected[NUM_SLOTS][NUM_DRIVES];
|
||||
|
116
source/Disk.cpp
116
source/Disk.cpp
@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
#include "Interface.h"
|
||||
#include "Core.h"
|
||||
#include "CardManager.h"
|
||||
#include "CPU.h"
|
||||
#include "DiskImage.h"
|
||||
#include "Log.h"
|
||||
@ -58,7 +59,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
const BYTE Disk2InterfaceCard::m_T00S00Pattern[] = {0xD5,0xAA,0x96,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xAA,0xDE};
|
||||
|
||||
Disk2InterfaceCard::Disk2InterfaceCard(UINT slot) :
|
||||
Card(CT_Disk2, slot)
|
||||
Card(CT_Disk2, slot),
|
||||
m_syncEvent(slot, 0, SyncEventCallback) // use slot# as "unique" id for Disk2InterfaceCards
|
||||
{
|
||||
if (m_slot != 5 && m_slot != 6) // fixme
|
||||
ThrowErrorInvalidSlot();
|
||||
@ -71,6 +73,9 @@ Disk2InterfaceCard::Disk2InterfaceCard(UINT slot) :
|
||||
m_diskLastReadLatchCycle = 0;
|
||||
m_enhanceDisk = true;
|
||||
m_is13SectorFirmware = false;
|
||||
m_deferredStepperEvent = false;
|
||||
m_deferredStepperAddress = 0;
|
||||
m_deferredStepperCumulativeCycles = 0;
|
||||
|
||||
ResetLogicStateSequencer();
|
||||
|
||||
@ -88,6 +93,9 @@ Disk2InterfaceCard::~Disk2InterfaceCard(void)
|
||||
{
|
||||
EjectDiskInternal(DRIVE_1);
|
||||
EjectDiskInternal(DRIVE_2);
|
||||
|
||||
if (m_syncEvent.m_active)
|
||||
g_SynchronousEventMgr.Remove(m_syncEvent.m_id);
|
||||
}
|
||||
|
||||
bool Disk2InterfaceCard::GetEnhanceDisk(void) { return m_enhanceDisk; }
|
||||
@ -455,7 +463,6 @@ void __stdcall Disk2InterfaceCard::ControlMotor(WORD, WORD address, BYTE, BYTE,
|
||||
void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
|
||||
{
|
||||
FloppyDrive* pDrive = &m_floppyDrive[m_currDrive];
|
||||
FloppyDisk* pFloppy = &pDrive->m_disk;
|
||||
|
||||
if (!m_floppyMotorOn) // GH#525
|
||||
{
|
||||
@ -484,16 +491,76 @@ void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE
|
||||
m_magnetStates &= ~phase_bit; // phase off
|
||||
}
|
||||
|
||||
#if LOG_DISK_PHASES
|
||||
const ULONG cycleDelta = (ULONG)(g_nCumulativeCycles - pDrive->m_lastStepperCycle);
|
||||
#endif
|
||||
pDrive->m_lastStepperCycle = g_nCumulativeCycles;
|
||||
if (!GetCardMgr().GetDisk2CardMgr().IsStepperDeferred())
|
||||
{
|
||||
m_deferredStepperAddress = address;
|
||||
m_deferredStepperCumulativeCycles = g_nCumulativeCycles;
|
||||
ControlStepperDeferred();
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_syncEvent.m_active)
|
||||
{
|
||||
// Check for adjacent magnets being turned off/on in a very short interval (10 cycles is purely based on A2osX). (GH#1110)
|
||||
// . also ProDOS rapidly turning off all 4 magnets.
|
||||
g_SynchronousEventMgr.Remove(m_syncEvent.m_id);
|
||||
m_deferredStepperEvent = false;
|
||||
|
||||
int addrDelta = (m_deferredStepperAddress & 7) - (address & 7);
|
||||
if (addrDelta < 0) addrDelta = -addrDelta;
|
||||
if (addrDelta == 2 || addrDelta == 6) // adjacent magnets: both turned off or both turned on
|
||||
{
|
||||
if ((address & 1) == 0) // adjacent magnets off
|
||||
{
|
||||
// 2 adjacent magnets off in quick succession don't move the cog (GH#1110)
|
||||
ControlStepperLogging(m_deferredStepperAddress, m_deferredStepperCumulativeCycles);
|
||||
ControlStepperLogging(address, g_nCumulativeCycles);
|
||||
return;
|
||||
}
|
||||
else // adjacent magnets on
|
||||
{
|
||||
// do nothing for now (TODO: check this)
|
||||
}
|
||||
}
|
||||
|
||||
// complete the deferred stepper event
|
||||
ControlStepperDeferred();
|
||||
}
|
||||
|
||||
// defer the effect of changing the phase
|
||||
m_deferredStepperAddress = address;
|
||||
m_deferredStepperCumulativeCycles = g_nCumulativeCycles;
|
||||
InsertSyncEvent();
|
||||
m_deferredStepperEvent = true;
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::InsertSyncEvent(void)
|
||||
{
|
||||
m_syncEvent.m_cyclesRemaining = 10; // NB. same cycle delay for magnet off and on - but perhaps they take different times?
|
||||
g_SynchronousEventMgr.Insert(&m_syncEvent);
|
||||
}
|
||||
|
||||
int Disk2InterfaceCard::SyncEventCallback(int id, int cycles, ULONG uExecutedCycles)
|
||||
{
|
||||
Disk2InterfaceCard& disk2Card = dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(id));
|
||||
disk2Card.ControlStepperDeferred();
|
||||
return 0; // Don't repeat event
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::ControlStepperDeferred(void)
|
||||
{
|
||||
m_deferredStepperEvent = false;
|
||||
const WORD address = m_deferredStepperAddress;
|
||||
|
||||
FloppyDrive* pDrive = &m_floppyDrive[m_currDrive];
|
||||
FloppyDisk* pFloppy = &pDrive->m_disk;
|
||||
|
||||
// check for any stepping effect from a magnet
|
||||
// - move only when the magnet opposite the cog is off
|
||||
// - move in the direction of an adjacent magnet if one is on
|
||||
// - do not move if both adjacent magnets are on (ie. quarter track)
|
||||
// momentum and timing are not accounted for ... maybe one day!
|
||||
// - timing is accounted for in the case when "two phases [are] turned off in rapid sequence" (UTAIIe page 9-13) (GH#1110)
|
||||
// momentum is not accounted for ... maybe one day!
|
||||
int direction = 0;
|
||||
if (m_magnetStates & (1 << ((pDrive->m_phase + 1) & 3)))
|
||||
direction += 1;
|
||||
@ -529,9 +596,21 @@ void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE
|
||||
GetFrame().FrameDrawDiskStatus(); // Show track status (GH#201)
|
||||
}
|
||||
|
||||
ControlStepperLogging(address, m_deferredStepperCumulativeCycles);
|
||||
}
|
||||
|
||||
void Disk2InterfaceCard::ControlStepperLogging(WORD address, unsigned __int64 cumulativeCycles)
|
||||
{
|
||||
FloppyDrive* pDrive = &m_floppyDrive[m_currDrive];
|
||||
|
||||
#if LOG_DISK_PHASES
|
||||
const ULONG cycleDelta = (ULONG)(cumulativeCycles - pDrive->m_lastStepperCycle);
|
||||
#endif
|
||||
pDrive->m_lastStepperCycle = cumulativeCycles; // NB. Persisted to save-state
|
||||
|
||||
#if LOG_DISK_PHASES
|
||||
LOG_DISK("%08X: track $%s magnet-states %d%d%d%d phase %d %s address $%4X last-stepper %.3fms\r\n",
|
||||
(UINT32)g_nCumulativeCycles,
|
||||
(UINT32)cumulativeCycles,
|
||||
GetCurrentTrackString().c_str(),
|
||||
(m_magnetStates >> 3) & 1,
|
||||
(m_magnetStates >> 2) & 1,
|
||||
@ -540,7 +619,7 @@ void __stdcall Disk2InterfaceCard::ControlStepper(WORD, WORD address, BYTE, BYTE
|
||||
(address >> 1) & 3, // phase
|
||||
(address & 1) ? "on " : "off",
|
||||
address,
|
||||
((float)cycleDelta)/(CLK_6502_NTSC/1000.0));
|
||||
((float)cycleDelta) / (CLK_6502_NTSC / 1000.0));
|
||||
#endif
|
||||
}
|
||||
|
||||
@ -1908,7 +1987,8 @@ BYTE __stdcall Disk2InterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE
|
||||
// 5: Added: Sequencer Function
|
||||
// 6: Added: Drive Connected & Motor On Cycle
|
||||
// 7: Deprecated SS_YAML_KEY_LSS_RESET_SEQUENCER, SS_YAML_KEY_DISK_ACCESSED
|
||||
static const UINT kUNIT_VERSION = 7;
|
||||
// 8: Added: deferred stepper: event, address & cycle
|
||||
static const UINT kUNIT_VERSION = 8;
|
||||
|
||||
#define SS_YAML_VALUE_CARD_DISK2 "Disk]["
|
||||
|
||||
@ -1925,6 +2005,9 @@ static const UINT kUNIT_VERSION = 7;
|
||||
#define SS_YAML_KEY_LSS_LATCH_DELAY "LSS Latch Delay"
|
||||
#define SS_YAML_KEY_LSS_RESET_SEQUENCER "LSS Reset Sequencer" // deprecated at v7
|
||||
#define SS_YAML_KEY_LSS_SEQUENCER_FUNCTION "LSS Sequencer Function"
|
||||
#define SS_YAML_KEY_DEFERRED_STEPPER_EVENT "Deferred Stepper Event"
|
||||
#define SS_YAML_KEY_DEFERRED_STEPPER_ADDRESS "Deferred Stepper Address"
|
||||
#define SS_YAML_KEY_DEFERRED_STEPPER_CYCLE "Deferred Stepper Cycle"
|
||||
|
||||
#define SS_YAML_KEY_DISK2UNIT "Unit"
|
||||
#define SS_YAML_KEY_DRIVE_CONNECTED "Drive Connected"
|
||||
@ -2005,6 +2088,9 @@ void Disk2InterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
|
||||
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LSS_SHIFT_REG, m_shiftReg); // v4
|
||||
yamlSaveHelper.SaveInt(SS_YAML_KEY_LSS_LATCH_DELAY, m_latchDelay); // v4
|
||||
yamlSaveHelper.SaveInt(SS_YAML_KEY_LSS_SEQUENCER_FUNCTION, m_seqFunc.function); // v5
|
||||
yamlSaveHelper.SaveBool(SS_YAML_KEY_DEFERRED_STEPPER_EVENT, m_deferredStepperEvent); // v8
|
||||
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_DEFERRED_STEPPER_ADDRESS, m_deferredStepperAddress); // v8
|
||||
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_DEFERRED_STEPPER_CYCLE, m_deferredStepperCumulativeCycles); // v8
|
||||
m_formatTrack.SaveSnapshot(yamlSaveHelper); // v2
|
||||
|
||||
SaveSnapshotDriveUnit(yamlSaveHelper, DRIVE_1);
|
||||
@ -2202,6 +2288,13 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi
|
||||
(void) yamlLoadHelper.LoadBool(SS_YAML_KEY_DISK_ACCESSED); // deprecated - but retrieve the value to avoid the "State: Unknown key (Disk Accessed)" warning
|
||||
}
|
||||
|
||||
if (version >= 8)
|
||||
{
|
||||
m_deferredStepperEvent = yamlLoadHelper.LoadBool(SS_YAML_KEY_DEFERRED_STEPPER_EVENT);
|
||||
m_deferredStepperAddress = yamlLoadHelper.LoadUint(SS_YAML_KEY_DEFERRED_STEPPER_ADDRESS);
|
||||
m_deferredStepperCumulativeCycles = yamlLoadHelper.LoadUint64(SS_YAML_KEY_DEFERRED_STEPPER_CYCLE);
|
||||
}
|
||||
|
||||
// Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1
|
||||
for (UINT i=0; i<NUM_DRIVES; i++)
|
||||
{
|
||||
@ -2214,5 +2307,8 @@ bool Disk2InterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT versi
|
||||
|
||||
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES | DRAW_DISK_STATUS);
|
||||
|
||||
if (m_deferredStepperEvent)
|
||||
InsertSyncEvent();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -27,6 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
#include "DiskLog.h"
|
||||
#include "DiskFormatTrack.h"
|
||||
#include "DiskImage.h"
|
||||
#include "SynchronousEventManager.h"
|
||||
|
||||
enum Drive_e
|
||||
{
|
||||
@ -206,6 +207,10 @@ private:
|
||||
bool GetFirmware(WORD lpNameId, BYTE* pDst);
|
||||
void InitFirmware(LPBYTE pCxRomPeripheral);
|
||||
void UpdateLatchForEmptyDrive(FloppyDrive* pDrive);
|
||||
void InsertSyncEvent(void);
|
||||
static int SyncEventCallback(int id, int cycles, ULONG uExecutedCycles);
|
||||
void ControlStepperDeferred(void);
|
||||
void ControlStepperLogging(WORD address, unsigned __int64 cumulativeCycles);
|
||||
|
||||
void PreJitterCheck(int phase, BYTE latch);
|
||||
void AddJitter(int phase, FloppyDisk& floppy);
|
||||
@ -275,6 +280,11 @@ private:
|
||||
SEQUENCER_FUNCTION m_seqFunc;
|
||||
UINT m_dbgLatchDelayedCnt;
|
||||
|
||||
bool m_deferredStepperEvent;
|
||||
WORD m_deferredStepperAddress;
|
||||
unsigned __int64 m_deferredStepperCumulativeCycles;
|
||||
SyncEvent m_syncEvent;
|
||||
|
||||
// Jitter (GH#930)
|
||||
static const BYTE m_T00S00Pattern[];
|
||||
UINT m_T00S00PatternIdx;
|
||||
|
@ -143,3 +143,8 @@ void Disk2CardManager::GetFilenameAndPathForSaveState(std::string& filename, std
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Disk2CardManager::SetStepperDefer(bool defer)
|
||||
{
|
||||
m_stepperDeferred = defer;
|
||||
}
|
||||
|
@ -3,7 +3,7 @@
|
||||
class Disk2CardManager
|
||||
{
|
||||
public:
|
||||
Disk2CardManager(void) {}
|
||||
Disk2CardManager(void) : m_stepperDeferred(true) {}
|
||||
~Disk2CardManager(void) {}
|
||||
|
||||
bool IsConditionForFullSpeed(void);
|
||||
@ -15,4 +15,9 @@ public:
|
||||
void Destroy(void);
|
||||
bool IsAnyFirmware13Sector(void);
|
||||
void GetFilenameAndPathForSaveState(std::string& filename, std::string& path);
|
||||
void SetStepperDefer(bool defer);
|
||||
bool IsStepperDeferred(void) { return m_stepperDeferred; }
|
||||
|
||||
private:
|
||||
bool m_stepperDeferred; // debug: can disable via cmd-line
|
||||
};
|
||||
|
@ -833,6 +833,9 @@ static void RepeatInitialization(void)
|
||||
if (g_cmdLine.bRemoveNoSlotClock)
|
||||
MemRemoveNoSlotClock();
|
||||
|
||||
if (g_cmdLine.noDisk2StepperDefer)
|
||||
GetCardMgr().GetDisk2CardMgr().SetStepperDefer(false);
|
||||
|
||||
// Call DebugInitialize() after SetCurrentImageDir()
|
||||
DebugInitialize();
|
||||
LogFileOutput("Main: DebugInitialize()\n");
|
||||
|
Loading…
x
Reference in New Issue
Block a user