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.
This commit is contained in:
Peter Ibbotson 2024-01-14 16:03:14 +00:00
parent 7497aa9923
commit b0dc4fd407
8 changed files with 75 additions and 11 deletions

Binary file not shown.

View File

@ -55,6 +55,8 @@ hd_unitnum = $c083
hd_memblock = $c084 hd_memblock = $c084
hd_diskblock = $c086 hd_diskblock = $c086
;hd_nextbyte = $c088 ; legacy read-only port (still supported by AppleWin) ;hd_nextbyte = $c088 ; legacy read-only port (still supported by AppleWin)
hd_imgsizelo = $c089
hd_imgsizehi = $c08a
; Notes on accesses to I/O registers: ; Notes on accesses to I/O registers:
; . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: ; . ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register:
@ -280,7 +282,12 @@ GetSlotInX
; Post: ; Post:
; C = hd_status.b0 ; C = hd_status.b0
; A = result of hd_execute ; A = result of hd_execute
; Read or write command
; X = Slot# << 4 ; X = Slot# << 4
; Y = command
; Status command
; X = low byte of disk size
; Y = high byte of disk size
cmdproc cmdproc
php php
@ -309,11 +316,21 @@ cmdproc
done done
ror hd_status,x ; Post: C=0 or 1 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 rts
;====================================== ;======================================
; 33 unused bytes ; 18 unused bytes
!zone data !zone data
@ -330,12 +347,12 @@ done
; $D7 = Removable, Interruptable, #Volumes=2, Supports write/read/status ; $D7 = Removable, Interruptable, #Volumes=2, Supports write/read/status
; $BF = Removable, Interruptable, #Volumes=4, Supports format/write/read/status (KEGS / IIGS) ; $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 ;; data
@checkCsFC @checkCsFB
*= $00FC ; org $00FC *= $00FB ; org $00FB
!warn "CsFC padding = ", * - @checkCsFC !warn "CsFB padding = ", * - @checkCsFB
!byte $00 ; Smart port ID Type byte
!word $7fff ; how many blocks are on the device. !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 $D7 ; specifics about the device (number of drives, read/write/format capability, etc)
!byte <Entrypoint_ProDOS ; entry point offset for ProDOS (must be $0a) !byte <Entrypoint_ProDOS ; entry point offset for ProDOS (must be $0a)

View File

@ -68,6 +68,8 @@
Insert a hard disk controller card into slot 5 or 7.<br><br> Insert a hard disk controller card into slot 5 or 7.<br><br>
-d1-disconnected, -d2-disconnected<br> -d1-disconnected, -d2-disconnected<br>
Disconnect drive-1 and/or drive-2 from the Disk II controller card in slot 6.<br><br> Disconnect drive-1 and/or drive-2 from the Disk II controller card in slot 6.<br><br>
-harddisknumblocks &lt;number of ProDOS blocks&gt;<br>
Set the number of blocks returned by a ProDOS status call. Use -harddisknumblocks 32767 to have the same autoexpanding behavior as older AppleWin versions.<br><br>
-no-nsc<br> -no-nsc<br>
Remove the No-Slot clock (NSC).<br><br> Remove the No-Slot clock (NSC).<br><br>
-r &lt;number of pages&gt;<br> -r &lt;number of pages&gt;<br>

Binary file not shown.

View File

@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SoundCore.h" #include "SoundCore.h"
#include "SNESMAX.h" #include "SNESMAX.h"
#include "Interface.h" #include "Interface.h"
#include "Harddisk.h"
CmdLine g_cmdLine; CmdLine g_cmdLine;
std::string g_sConfigFile; // INI file to use instead of Registry 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); 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) else if (strcmp(lpCmdLine, "-load-state") == 0)
{ {
lpCmdLine = GetCurrArg(lpNextArg); lpCmdLine = GetCurrArg(lpNextArg);

View File

@ -36,6 +36,7 @@ struct CmdLine
noDisk2StepperDefer = false; noDisk2StepperDefer = false;
szSnapshotName = NULL; szSnapshotName = NULL;
szScreenshotFilename = NULL; szScreenshotFilename = NULL;
uHarddiskNumBlocks = 0;
uRamWorksExPages = 0; uRamWorksExPages = 0;
uSaturnBanks = 0; uSaturnBanks = 0;
newVideoType = -1; newVideoType = -1;
@ -82,6 +83,7 @@ struct CmdLine
LPCSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES]; LPCSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES];
bool driveConnected[NUM_SLOTS][NUM_DRIVES]; bool driveConnected[NUM_SLOTS][NUM_DRIVES];
LPCSTR szImageName_harddisk[NUM_SLOTS][NUM_HARDDISKS]; LPCSTR szImageName_harddisk[NUM_SLOTS][NUM_HARDDISKS];
UINT uHarddiskNumBlocks;
LPSTR szSnapshotName; LPSTR szSnapshotName;
LPSTR szScreenshotFilename; LPSTR szScreenshotFilename;
UINT uRamWorksExPages; UINT uRamWorksExPages;

View File

@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Registry.h" #include "Registry.h"
#include "SaveState.h" #include "SaveState.h"
#include "YamlHelper.h" #include "YamlHelper.h"
#include "CmdLine.h"
#include "Debugger/Debug.h" #include "Debugger/Debug.h"
#include "../resource/resource.h" #include "../resource/resource.h"
@ -53,6 +54,8 @@ Memory map (for slot 7):
C0F6 (r/w) LOW BYTE OF BLOCK NUMBER C0F6 (r/w) LOW BYTE OF BLOCK NUMBER
C0F7 (r/w) HIGH BYTE OF BLOCK NUMBER C0F7 (r/w) HIGH BYTE OF BLOCK NUMBER
C0F8 (r) NEXT BYTE (legacy read-only port - still supported) 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: Firmware notes:
. ROR ABS16,X and ROL ABS16,X - only used for $C081+s*$10 STATUS register: . 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 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 block to be decided by the Apple's operating system (ProDOS). To create
an empty .HDV file, just create a 0 byte file. 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 2. Emulation code
There are 4 commands ProDOS will send to a block device. 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); r = (BYTE)(pHDD->m_memblock & 0x00FF);
break; break;
case 0x5: case 0x5:
r = (BYTE)(pHDD->m_memblock & 0xFF00 >> 8); r = (BYTE)((pHDD->m_memblock & 0xFF00) >> 8);
break; break;
case 0x6: case 0x6:
r = (BYTE)(pHDD->m_diskblock & 0x00FF); r = (BYTE)(pHDD->m_diskblock & 0x00FF);
break; break;
case 0x7: case 0x7:
r = (BYTE)(pHDD->m_diskblock & 0xFF00 >> 8); r = (BYTE)((pHDD->m_diskblock & 0xFF00) >> 8);
break; break;
case 0x8: // Legacy: continue to support this I/O port for old HDD firmware case 0x8: // Legacy: continue to support this I/O port for old HDD firmware
r = pHDD->m_buf[pHDD->m_buf_ptr]; r = pHDD->m_buf[pHDD->m_buf_ptr];
if (pHDD->m_buf_ptr < sizeof(pHDD->m_buf)-1) if (pHDD->m_buf_ptr < sizeof(pHDD->m_buf)-1)
pHDD->m_buf_ptr++; pHDD->m_buf_ptr++;
break; 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: default:
pHDD->m_status_next = DISK_STATUS_OFF; pHDD->m_status_next = DISK_STATUS_OFF;
r = IO_Null(pc, addr, bWrite, d, nExecutedCycles); 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 0x0: // r/o: status
case 0x1: // r/o: execute case 0x1: // r/o: execute
case 0x8: // r/o: legacy next-data port 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! // 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" // 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! // - 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; 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) void HarddiskInterfaceCard::UpdateLightStatus(HardDiskDrive* pHDD)

View File

@ -34,6 +34,8 @@ enum HardDrive_e
NUM_HARDDISKS NUM_HARDDISKS
}; };
const UINT kHarddiskMaxNumBlocks = 0xffff; // Maximum number of blocks we can report.
class HardDiskDrive class HardDiskDrive
{ {
public: public:
@ -117,7 +119,7 @@ private:
const std::string& DiskGetBaseName(const int iDrive); const std::string& DiskGetBaseName(const int iDrive);
bool SelectImage(const int drive, LPCSTR pszFilename); bool SelectImage(const int drive, LPCSTR pszFilename);
void UpdateLightStatus(HardDiskDrive* pHDD); void UpdateLightStatus(HardDiskDrive* pHDD);
static UINT GetImageSizeInBlocks(ImageInfo* const pImageInfo);
void SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit); void SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit);
bool LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit); bool LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit);