diff --git a/firmware/HDD/HDDRVR.BIN b/firmware/HDD/HDDRVR.BIN index 6dba7143..21f68edb 100644 Binary files a/firmware/HDD/HDDRVR.BIN and b/firmware/HDD/HDDRVR.BIN differ diff --git a/firmware/HDD/hddrvr.a65 b/firmware/HDD/hddrvr.a65 index a55320e7..07613a67 100644 --- a/firmware/HDD/hddrvr.a65 +++ b/firmware/HDD/hddrvr.a65 @@ -55,6 +55,8 @@ hd_unitnum = $c083 hd_memblock = $c084 hd_diskblock = $c086 ;hd_nextbyte = $c088 ; legacy read-only port (still supported by AppleWin) +hd_imgsizelo = $c089 +hd_imgsizehi = $c08a ; Notes on accesses to I/O registers: ; . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: @@ -280,7 +282,12 @@ GetSlotInX ; Post: ; C = hd_status.b0 ; A = result of hd_execute +; Read or write command ; X = Slot# << 4 +; Y = command +; Status command +; X = low byte of disk size +; Y = high byte of disk size cmdproc php @@ -309,11 +316,21 @@ cmdproc done ror hd_status,x ; Post: C=0 or 1 + ldy command ; Was it status + beq size ; yes, fill in the values + rts ; no, go home + +size + pha ; Save result + ldy hd_imgsizehi,x ; Get high byte of size + lda hd_imgsizelo,x ; Get low byte of size + tax ; Transfer into X + pla ; Get back status call result rts ;====================================== -; 33 unused bytes +; 18 unused bytes !zone data @@ -330,12 +347,12 @@ done ; $D7 = Removable, Interruptable, #Volumes=2, Supports write/read/status ; $BF = Removable, Interruptable, #Volumes=4, Supports format/write/read/status (KEGS / IIGS) -; datablock. This starts near the end of the firmware (at offset $FC) +; datablock. This starts near the end of the firmware (at offset $FB) ;; data -@checkCsFC -*= $00FC ; org $00FC -!warn "CsFC padding = ", * - @checkCsFC - - !word $7fff ; how many blocks are on the device. +@checkCsFB +*= $00FB ; org $00FB +!warn "CsFB padding = ", * - @checkCsFB + !byte $00 ; Smart port ID Type byte + !word $0000 ; how many blocks are on the device. Zero means use status call !byte $D7 ; specifics about the device (number of drives, read/write/format capability, etc) !byte
-d1-disconnected, -d2-disconnected
Disconnect drive-1 and/or drive-2 from the Disk II controller card in slot 6.

+ -harddisknumblocks <number of ProDOS blocks>
+ Set the number of blocks returned by a ProDOS status call. Use -harddisknumblocks 32767 to have the same autoexpanding behavior as older AppleWin versions.

-no-nsc
Remove the No-Slot clock (NSC).

-r <number of pages>
diff --git a/resource/Hddrvr.bin b/resource/Hddrvr.bin index 6dba7143..21f68edb 100644 Binary files a/resource/Hddrvr.bin and b/resource/Hddrvr.bin differ diff --git a/source/CmdLine.cpp b/source/CmdLine.cpp index 073ef21d..628614b0 100644 --- a/source/CmdLine.cpp +++ b/source/CmdLine.cpp @@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "SoundCore.h" #include "SNESMAX.h" #include "Interface.h" +#include "Harddisk.h" CmdLine g_cmdLine; std::string g_sConfigFile; // INI file to use instead of Registry @@ -246,6 +247,17 @@ bool ProcessCmdLine(LPSTR lpCmdLine) LogFileOutput("Unsupported arg: %s\n", lpCmdLine); } } + else if (strcmp(lpCmdLine, "-harddisknumblocks") == 0) // number of blocks to report for ProDOS + { + lpCmdLine = GetCurrArg(lpNextArg); + lpNextArg = GetNextArg(lpNextArg); + g_cmdLine.uHarddiskNumBlocks = atoi(lpCmdLine); + if (g_cmdLine.uHarddiskNumBlocks > 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);