From b0dc4fd4073d142b6ae641a2ac4bf2024165f84b Mon Sep 17 00:00:00 2001 From: Peter Ibbotson Date: Sun, 14 Jan 2024 16:03:14 +0000 Subject: [PATCH] ProDOS HDD Driver modified to support returning the volume size in the X/Y registers. New command line option to force a size for autoexpanding use. --- firmware/HDD/HDDRVR.BIN | Bin 256 -> 256 bytes firmware/HDD/hddrvr.a65 | 31 ++++++++++++++++++++++++------- help/CommandLine.html | 2 ++ resource/Hddrvr.bin | Bin 256 -> 256 bytes source/CmdLine.cpp | 12 ++++++++++++ source/CmdLine.h | 2 ++ source/Harddisk.cpp | 35 ++++++++++++++++++++++++++++++++--- source/Harddisk.h | 4 +++- 8 files changed, 75 insertions(+), 11 deletions(-) diff --git a/firmware/HDD/HDDRVR.BIN b/firmware/HDD/HDDRVR.BIN index 6dba71433602115a07d5f3229a0dc2247a90f942..21f68edb0d673c9cbf78c66566fb5a9318d25d87 100644 GIT binary patch delta 28 kcmZo*YG9ghi+_pJ2gU@CJzWR(b{<%jkudS0DARQ=0JVq= kHarddiskMaxNumBlocks) + g_cmdLine.uHarddiskNumBlocks = kHarddiskMaxNumBlocks; + else + if (g_cmdLine.uHarddiskNumBlocks < 0) + g_cmdLine.uHarddiskNumBlocks = 0; + } else if (strcmp(lpCmdLine, "-load-state") == 0) { lpCmdLine = GetCurrArg(lpNextArg); diff --git a/source/CmdLine.h b/source/CmdLine.h index 98b4b2d0..a5f45651 100644 --- a/source/CmdLine.h +++ b/source/CmdLine.h @@ -36,6 +36,7 @@ struct CmdLine noDisk2StepperDefer = false; szSnapshotName = NULL; szScreenshotFilename = NULL; + uHarddiskNumBlocks = 0; uRamWorksExPages = 0; uSaturnBanks = 0; newVideoType = -1; @@ -82,6 +83,7 @@ struct CmdLine LPCSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES]; bool driveConnected[NUM_SLOTS][NUM_DRIVES]; LPCSTR szImageName_harddisk[NUM_SLOTS][NUM_HARDDISKS]; + UINT uHarddiskNumBlocks; LPSTR szSnapshotName; LPSTR szScreenshotFilename; UINT uRamWorksExPages; diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp index a076ade3..1add0014 100644 --- a/source/Harddisk.cpp +++ b/source/Harddisk.cpp @@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "Registry.h" #include "SaveState.h" #include "YamlHelper.h" +#include "CmdLine.h" #include "Debugger/Debug.h" #include "../resource/resource.h" @@ -53,6 +54,8 @@ Memory map (for slot 7): C0F6 (r/w) LOW BYTE OF BLOCK NUMBER C0F7 (r/w) HIGH BYTE OF BLOCK NUMBER C0F8 (r) NEXT BYTE (legacy read-only port - still supported) + C0F9 (r) LOW BYTE OF DISK IMAGE SIZE IN BLOCKS + C0FA (r) HIGHT BYTE OF DISK IMAGE SIZE IN BLOCKS Firmware notes: . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: @@ -75,6 +78,8 @@ Overview bytes, in a linear fashion. The internal formatting and meaning of each block to be decided by the Apple's operating system (ProDOS). To create an empty .HDV file, just create a 0 byte file. + Use the -harddisknumblocks n command line option to set the disk size + returned by ProDOS status calls. 2. Emulation code There are 4 commands ProDOS will send to a block device. @@ -657,19 +662,31 @@ BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BY r = (BYTE)(pHDD->m_memblock & 0x00FF); break; case 0x5: - r = (BYTE)(pHDD->m_memblock & 0xFF00 >> 8); + r = (BYTE)((pHDD->m_memblock & 0xFF00) >> 8); break; case 0x6: r = (BYTE)(pHDD->m_diskblock & 0x00FF); break; case 0x7: - r = (BYTE)(pHDD->m_diskblock & 0xFF00 >> 8); + r = (BYTE)((pHDD->m_diskblock & 0xFF00) >> 8); break; case 0x8: // Legacy: continue to support this I/O port for old HDD firmware r = pHDD->m_buf[pHDD->m_buf_ptr]; if (pHDD->m_buf_ptr < sizeof(pHDD->m_buf)-1) pHDD->m_buf_ptr++; break; + case 0x9: + if (pHDD->m_imageloaded) + r = (BYTE)(GetImageSizeInBlocks(pHDD->m_imagehandle) & 0x00ff); + else + r = 0; + break; + case 0xa: + if (pHDD->m_imageloaded) + r = (BYTE)((GetImageSizeInBlocks(pHDD->m_imagehandle) & 0xff00) >> 8); + else + r = 0; + break; default: pHDD->m_status_next = DISK_STATUS_OFF; r = IO_Null(pc, addr, bWrite, d, nExecutedCycles); @@ -694,7 +711,9 @@ BYTE __stdcall HarddiskInterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, B case 0x0: // r/o: status case 0x1: // r/o: execute case 0x8: // r/o: legacy next-data port - // Writing to these 3 read-only registers is a no-op. + case 0x9: // r/o: low byte of image size + case 0xa: // r/o: high byte of image size + // Writing to these 5 read-only registers is a no-op. // NB. Don't change m_status_next, as UpdateLightStatus() has a huge performance cost! // Firmware has a busy-wait loop doing "rol hd_status,x" // - this RMW opcode does an IORead() then an IOWrite(), and the loop iterates ~100 times! @@ -729,6 +748,16 @@ BYTE __stdcall HarddiskInterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, B return r; } +UINT HarddiskInterfaceCard::GetImageSizeInBlocks(ImageInfo* const pImageInfo) +{ + if (g_cmdLine.uHarddiskNumBlocks != 0) + return g_cmdLine.uHarddiskNumBlocks; + UINT numberOfBlocks = (pImageInfo ? pImageInfo->uImageSize : 0) / HD_BLOCK_SIZE; + if (numberOfBlocks > kHarddiskMaxNumBlocks) + numberOfBlocks = kHarddiskMaxNumBlocks; + return numberOfBlocks; +} + //=========================================================================== void HarddiskInterfaceCard::UpdateLightStatus(HardDiskDrive* pHDD) diff --git a/source/Harddisk.h b/source/Harddisk.h index cca84e2e..fc71d93d 100644 --- a/source/Harddisk.h +++ b/source/Harddisk.h @@ -34,6 +34,8 @@ enum HardDrive_e NUM_HARDDISKS }; +const UINT kHarddiskMaxNumBlocks = 0xffff; // Maximum number of blocks we can report. + class HardDiskDrive { public: @@ -117,7 +119,7 @@ private: const std::string& DiskGetBaseName(const int iDrive); bool SelectImage(const int drive, LPCSTR pszFilename); void UpdateLightStatus(HardDiskDrive* pHDD); - + static UINT GetImageSizeInBlocks(ImageInfo* const pImageInfo); void SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit); bool LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit);