Make harddisk a class (#995)

. Add user-protection when unchecking HDD controller (as images aren't restored on a 'cancel')
. Fix possible crash when removing (via Config->Disk) either Disk2 card(s5) or HDD card(s7), then cancelling during emulation
. Fix m_buf[] size
This commit is contained in:
TomCh 2021-11-01 20:12:42 +00:00 committed by GitHub
parent 830030ee05
commit ff7c9dc185
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
15 changed files with 523 additions and 526 deletions

View file

@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Disk.h" #include "Disk.h"
#include "FourPlay.h" #include "FourPlay.h"
#include "Harddisk.h"
#include "MouseInterface.h" #include "MouseInterface.h"
#include "SAM.h" #include "SAM.h"
#include "SerialComms.h" #include "SerialComms.h"
@ -64,7 +65,7 @@ void CardManager::InsertInternal(UINT slot, SS_CARDTYPE type)
m_slot[slot] = new DummyCard(type); m_slot[slot] = new DummyCard(type);
break; break;
case CT_GenericHDD: case CT_GenericHDD:
m_slot[slot] = new DummyCard(type); m_slot[slot] = new HarddiskInterfaceCard(slot);
break; break;
case CT_GenericClock: case CT_GenericClock:
m_slot[slot] = new DummyCard(type); m_slot[slot] = new DummyCard(type);

View file

@ -34,13 +34,13 @@ public:
Card& GetRef(UINT slot) Card& GetRef(UINT slot)
{ {
SS_CARDTYPE t=QuerySlot(slot); SS_CARDTYPE t=QuerySlot(slot);
_ASSERT((t==CT_SSC || t==CT_MouseInterface || t==CT_Disk2 || t == CT_FourPlay || t == CT_SNESMAX || t == CT_SAM) && m_slot[slot]); _ASSERT((t==CT_GenericHDD || t==CT_SSC || t==CT_MouseInterface || t==CT_Disk2 || t == CT_FourPlay || t == CT_SNESMAX || t == CT_SAM) && m_slot[slot]);
return *m_slot[slot]; return *m_slot[slot];
} }
Card* GetObj(UINT slot) Card* GetObj(UINT slot)
{ {
SS_CARDTYPE t=QuerySlot(slot); SS_CARDTYPE t=QuerySlot(slot);
_ASSERT(t==CT_SSC || t==CT_MouseInterface || t==CT_Disk2 || t == CT_FourPlay || t == CT_SNESMAX || t == CT_SAM); _ASSERT(t == CT_GenericHDD || t==CT_SSC || t==CT_MouseInterface || t==CT_Disk2 || t == CT_FourPlay || t == CT_SNESMAX || t == CT_SAM);
return m_slot[slot]; return m_slot[slot];
} }

View file

@ -84,7 +84,7 @@ INT_PTR CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARA
if (m_PropertySheetHelper.GetConfigOld().m_Slot[SLOT7] != m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7]) if (m_PropertySheetHelper.GetConfigOld().m_Slot[SLOT7] != m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7])
{ {
if (m_PropertySheetHelper.GetConfigOld().m_Slot[SLOT7] == CT_GenericHDD || m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7] == CT_GenericHDD) if (m_PropertySheetHelper.GetConfigOld().m_Slot[SLOT7] == CT_GenericHDD || m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7] == CT_GenericHDD)
HD_SetEnabled(m_PropertySheetHelper.GetConfigOld().m_Slot[SLOT7] == CT_GenericHDD); m_PropertySheetHelper.SetSlot(SLOT7, m_PropertySheetHelper.GetConfigOld().m_Slot[SLOT7]);
} }
DlgCANCEL(hWnd); DlgCANCEL(hWnd);
break; break;
@ -149,12 +149,21 @@ INT_PTR CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARA
case IDC_HDD_ENABLE: case IDC_HDD_ENABLE:
{ {
const BOOL checked = IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE) ? TRUE : FALSE; const BOOL checked = IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE) ? TRUE : FALSE;
// Add some user-protection, as (currently) removing the HDD images can't be undone!
if (checked || !checked && GetFrame().FrameMessageBox("This will unplug the HDD image(s)! Proceed?", "Eject/Unplug Warning", MB_ICONWARNING | MB_YESNO | MB_SETFOREGROUND) != IDNO)
{
m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7] = checked ? CT_GenericHDD : CT_Empty; m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7] = checked ? CT_GenericHDD : CT_Empty;
// NB. Unusual as it creates slot object when checkbox is toggled (instead of after OK) // NB. Unusual as it creates slot object when checkbox is toggled (instead of after OK)
// Needed as we need a HarddiskInterfaceCard object so that images can be inserted/ejected [*2] // Needed as we need a HarddiskInterfaceCard object so that images can be inserted/ejected [*2]
HD_SetEnabled(m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7] == CT_GenericHDD); m_PropertySheetHelper.SetSlot(SLOT7, m_PropertySheetHelper.GetConfigNew().m_Slot[SLOT7]);
InitComboHDD(hWnd, SLOT7); // disabling will remove the HDD images - so update drop-down to reflect this
EnableHDD(hWnd, checked); EnableHDD(hWnd, checked);
} }
else
{
CheckDlgButton(hWnd, IDC_HDD_ENABLE, BST_CHECKED);
}
}
break; break;
case IDC_HDD_SWAP: case IDC_HDD_SWAP:
HandleHDDSwap(hWnd); HandleHDDSwap(hWnd);
@ -184,7 +193,7 @@ INT_PTR CPageDisk::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARA
RegLoadString(TEXT(REG_CONFIG), REGVALUE_CIDERPRESSLOC, 1, PathToCiderPress, MAX_PATH, TEXT("")); RegLoadString(TEXT(REG_CONFIG), REGVALUE_CIDERPRESSLOC, 1, PathToCiderPress, MAX_PATH, TEXT(""));
SendDlgItemMessage(hWnd, IDC_CIDERPRESS_FILENAME ,WM_SETTEXT, 0, (LPARAM)PathToCiderPress); SendDlgItemMessage(hWnd, IDC_CIDERPRESS_FILENAME ,WM_SETTEXT, 0, (LPARAM)PathToCiderPress);
CheckDlgButton(hWnd, IDC_HDD_ENABLE, HD_CardIsEnabled() ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hWnd, IDC_HDD_ENABLE, (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD) ? BST_CHECKED : BST_UNCHECKED);
EnableHDD(hWnd, IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE)); EnableHDD(hWnd, IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE));
@ -226,15 +235,19 @@ void CPageDisk::InitComboHDD(HWND hWnd, UINT /*slot*/)
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD1, m_defaultHDDOptions, -1); m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD1, m_defaultHDDOptions, -1);
m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD2, m_defaultHDDOptions, -1); m_PropertySheetHelper.FillComboBox(hWnd, IDC_COMBO_HDD2, m_defaultHDDOptions, -1);
if (!HD_GetFullName(HARDDISK_1).empty()) if (GetCardMgr().QuerySlot(SLOT7) != CT_GenericHDD)
return;
HarddiskInterfaceCard& card = dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7));
if (!card.GetFullName(HARDDISK_1).empty())
{ {
SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(HARDDISK_1).c_str()); SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_INSERTSTRING, 0, (LPARAM)card.GetFullName(HARDDISK_1).c_str());
SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_SETCURSEL, 0, 0); SendDlgItemMessage(hWnd, IDC_COMBO_HDD1, CB_SETCURSEL, 0, 0);
} }
if (!HD_GetFullName(HARDDISK_2).empty()) if (!card.GetFullName(HARDDISK_2).empty())
{ {
SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(HARDDISK_2).c_str()); SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_INSERTSTRING, 0, (LPARAM)card.GetFullName(HARDDISK_2).c_str());
SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_SETCURSEL, 0, 0); SendDlgItemMessage(hWnd, IDC_COMBO_HDD2, CB_SETCURSEL, 0, 0);
} }
} }
@ -315,6 +328,11 @@ void CPageDisk::HandleHDDCombo(HWND hWnd, UINT driveSelected, UINT comboSelected
if (!IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE)) if (!IsDlgButtonChecked(hWnd, IDC_HDD_ENABLE))
return; return;
_ASSERT(GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD);
if (GetCardMgr().QuerySlot(SLOT7) != CT_GenericHDD)
return;
HarddiskInterfaceCard& card = dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7));
// Search from "select hard drive" // Search from "select hard drive"
DWORD dwOpenDialogIndex = (DWORD)SendDlgItemMessage(hWnd, comboSelected, CB_FINDSTRINGEXACT, -1, (LPARAM)&m_defaultHDDOptions[0]); DWORD dwOpenDialogIndex = (DWORD)SendDlgItemMessage(hWnd, comboSelected, CB_FINDSTRINGEXACT, -1, (LPARAM)&m_defaultHDDOptions[0]);
DWORD dwComboSelection = (DWORD)SendDlgItemMessage(hWnd, comboSelected, CB_GETCURSEL, 0, 0); DWORD dwComboSelection = (DWORD)SendDlgItemMessage(hWnd, comboSelected, CB_GETCURSEL, 0, 0);
@ -324,7 +342,7 @@ void CPageDisk::HandleHDDCombo(HWND hWnd, UINT driveSelected, UINT comboSelected
if (dwComboSelection == dwOpenDialogIndex) if (dwComboSelection == dwOpenDialogIndex)
{ {
EnableHDD(hWnd, FALSE); // Prevent multiple Selection dialogs to be triggered EnableHDD(hWnd, FALSE); // Prevent multiple Selection dialogs to be triggered
bool bRes = HD_Select(driveSelected); bool bRes = card.Select(driveSelected);
EnableHDD(hWnd, TRUE); EnableHDD(hWnd, TRUE);
if (!bRes) if (!bRes)
@ -341,13 +359,13 @@ void CPageDisk::HandleHDDCombo(HWND hWnd, UINT driveSelected, UINT comboSelected
SendDlgItemMessage(hWnd, comboSelected, CB_DELETESTRING, 0, 0); SendDlgItemMessage(hWnd, comboSelected, CB_DELETESTRING, 0, 0);
} }
SendDlgItemMessage(hWnd, comboSelected, CB_INSERTSTRING, 0, (LPARAM)HD_GetFullName(driveSelected).c_str()); SendDlgItemMessage(hWnd, comboSelected, CB_INSERTSTRING, 0, (LPARAM)card.GetFullName(driveSelected).c_str());
SendDlgItemMessage(hWnd, comboSelected, CB_SETCURSEL, 0, 0); SendDlgItemMessage(hWnd, comboSelected, CB_SETCURSEL, 0, 0);
// If the HD was in the other combo, remove now // If the HD was in the other combo, remove now
DWORD comboOther = (comboSelected == IDC_COMBO_HDD1) ? IDC_COMBO_HDD2 : IDC_COMBO_HDD1; DWORD comboOther = (comboSelected == IDC_COMBO_HDD1) ? IDC_COMBO_HDD2 : IDC_COMBO_HDD1;
DWORD duplicated = (DWORD)SendDlgItemMessage(hWnd, comboOther, CB_FINDSTRINGEXACT, -1, (LPARAM)HD_GetFullName(driveSelected).c_str()); DWORD duplicated = (DWORD)SendDlgItemMessage(hWnd, comboOther, CB_FINDSTRINGEXACT, -1, (LPARAM)card.GetFullName(driveSelected).c_str());
if (duplicated != CB_ERR) if (duplicated != CB_ERR)
{ {
SendDlgItemMessage(hWnd, comboOther, CB_DELETESTRING, duplicated, 0); SendDlgItemMessage(hWnd, comboOther, CB_DELETESTRING, duplicated, 0);
@ -361,7 +379,7 @@ void CPageDisk::HandleHDDCombo(HWND hWnd, UINT driveSelected, UINT comboSelected
if (RemovalConfirmation(comboSelected)) if (RemovalConfirmation(comboSelected))
{ {
// Unplug selected disk // Unplug selected disk
HD_Unplug(driveSelected); card.Unplug(driveSelected);
// Remove drive from list // Remove drive from list
SendDlgItemMessage(hWnd, comboSelected, CB_DELETESTRING, 0, 0); SendDlgItemMessage(hWnd, comboSelected, CB_DELETESTRING, 0, 0);
} }
@ -447,7 +465,10 @@ void CPageDisk::HandleHDDSwap(HWND hWnd)
if (!RemovalConfirmation(IDC_HDD_SWAP)) if (!RemovalConfirmation(IDC_HDD_SWAP))
return; return;
if (!HD_ImageSwap()) if (GetCardMgr().QuerySlot(SLOT7) != CT_GenericHDD)
return;
if (!dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).ImageSwap())
return; return;
InitComboHDD(hWnd, SLOT7); InitComboHDD(hWnd, SLOT7);
@ -482,7 +503,7 @@ UINT CPageDisk::RemovalConfirmation(UINT uCommand)
if (bMsgBox) if (bMsgBox)
{ {
int nRes = GetFrame().FrameMessageBox(szText, TEXT("Eject/Unplug Warning"), MB_ICONWARNING | MB_YESNO | MB_SETFOREGROUND); int nRes = GetFrame().FrameMessageBox(szText, "Eject/Unplug Warning", MB_ICONWARNING | MB_YESNO | MB_SETFOREGROUND);
if (nRes == IDNO) if (nRes == IDNO)
uCommand = 0; uCommand = 0;
} }

View file

@ -393,7 +393,7 @@ void CPropertySheetHelper::RestoreCurrentConfig(void)
SetSlot(SLOT3, m_ConfigOld.m_Slot[SLOT3]); SetSlot(SLOT3, m_ConfigOld.m_Slot[SLOT3]);
SetSlot(SLOT4, m_ConfigOld.m_Slot[SLOT4]); SetSlot(SLOT4, m_ConfigOld.m_Slot[SLOT4]);
SetSlot(SLOT5, m_ConfigOld.m_Slot[SLOT5]); SetSlot(SLOT5, m_ConfigOld.m_Slot[SLOT5]);
HD_SetEnabled(m_ConfigOld.m_Slot[SLOT7] == CT_GenericHDD); SetSlot(SLOT7, m_ConfigOld.m_Slot[SLOT7]);
GetPropertySheet().SetTheFreezesF8Rom(m_ConfigOld.m_bEnableTheFreezesF8Rom); GetPropertySheet().SetTheFreezesF8Rom(m_ConfigOld.m_bEnableTheFreezesF8Rom);
} }

View file

@ -72,6 +72,10 @@ Disk2InterfaceCard::Disk2InterfaceCard(UINT slot) :
ResetLogicStateSequencer(); ResetLogicStateSequencer();
// if created by user in Config->Disk, then MemInitializeIO() won't be called
if (GetCxRomPeripheral())
Initialize(GetCxRomPeripheral()); // During regular start-up, Initialize() will be called later by MemInitializeIO()
// Debug: // Debug:
#if LOG_DISK_NIBBLES_USE_RUNTIME_VAR #if LOG_DISK_NIBBLES_USE_RUNTIME_VAR
m_bLogDisk_NibblesRW = false; m_bLogDisk_NibblesRW = false;
@ -86,6 +90,9 @@ Disk2InterfaceCard::~Disk2InterfaceCard(void)
{ {
EjectDiskInternal(DRIVE_1); EjectDiskInternal(DRIVE_1);
EjectDiskInternal(DRIVE_2); EjectDiskInternal(DRIVE_2);
// if destroyed by user in Config->Disk, then ensure that old object's reference is removed
UnregisterIoHandler(m_slot);
} }
bool Disk2InterfaceCard::GetEnhanceDisk(void) { return m_enhanceDisk; } bool Disk2InterfaceCard::GetEnhanceDisk(void) { return m_enhanceDisk; }
@ -1791,8 +1798,7 @@ void Disk2InterfaceCard::InitFirmware(LPBYTE pCxRomPeripheral)
memcpy(pCxRomPeripheral + m_slot*APPLE_SLOT_SIZE, m_16SectorFirmware, DISK2_FW_SIZE); memcpy(pCxRomPeripheral + m_slot*APPLE_SLOT_SIZE, m_16SectorFirmware, DISK2_FW_SIZE);
} }
// TODO: LoadRom_Disk_Floppy() void Disk2InterfaceCard::Initialize(LPBYTE pCxRomPeripheral)
void Disk2InterfaceCard::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
{ {
bool res = GetFirmware(IDR_DISK2_13SECTOR_FW, m_13SectorFirmware); bool res = GetFirmware(IDR_DISK2_13SECTOR_FW, m_13SectorFirmware);
_ASSERT(res); _ASSERT(res);
@ -1807,10 +1813,7 @@ void Disk2InterfaceCard::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot)
// . Patching the firmware breaks the ADC checksum used by "The CIA Files" (Tricky Dick) // . Patching the firmware breaks the ADC checksum used by "The CIA Files" (Tricky Dick)
// . In this case we can patch to compensate for an ADC or EOR checksum but not both (nickw) // . In this case we can patch to compensate for an ADC or EOR checksum but not both (nickw)
_ASSERT(m_slot == uSlot); RegisterIoHandler(m_slot, &Disk2InterfaceCard::IORead, &Disk2InterfaceCard::IOWrite, NULL, NULL, this, NULL);
RegisterIoHandler(uSlot, &Disk2InterfaceCard::IORead, &Disk2InterfaceCard::IOWrite, NULL, NULL, this, NULL);
m_slot = uSlot;
InitFirmware(pCxRomPeripheral); InitFirmware(pCxRomPeripheral);
} }

View file

@ -130,7 +130,7 @@ public:
virtual void Init(void) {}; virtual void Init(void) {};
virtual void Reset(const bool powerCycle); virtual void Reset(const bool powerCycle);
void Initialize(LPBYTE pCxRomPeripheral, UINT uSlot); void Initialize(LPBYTE pCxRomPeripheral);
void Destroy(void); // no, doesn't "destroy" the disk image. DiskIIManagerShutdown() void Destroy(void); // no, doesn't "destroy" the disk image. DiskIIManagerShutdown()
void Boot(void); void Boot(void);

View file

@ -34,7 +34,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "CardManager.h" #include "CardManager.h"
#include "CPU.h" #include "CPU.h"
#include "DiskImage.h" // ImageError_e, Disk_Status_e #include "DiskImage.h" // ImageError_e, Disk_Status_e
#include "DiskImageHelper.h"
#include "Memory.h" #include "Memory.h"
#include "Registry.h" #include "Registry.h"
#include "SaveState.h" #include "SaveState.h"
@ -115,101 +114,74 @@ Overview
sound card in slot 7 is a generally bad idea) will cause problems. sound card in slot 7 is a generally bad idea) will cause problems.
*/ */
struct HDD
HarddiskInterfaceCard::HarddiskInterfaceCard(UINT slot) :
Card(CT_GenericHDD),
m_slot(slot)
{ {
HDD() m_unitNum = HARDDISK_1 << 7; // b7=unit
{
clear();
}
void clear()
{
// This is not a POD (there is a std::string)
// memset(0) does not work
imagename.clear();
fullname.clear();
strFilenameInZip.clear();
imagehandle = NULL;
bWriteProtected = false;
hd_error = 0;
hd_memblock = 0;
hd_diskblock = 0;
hd_buf_ptr = 0;
hd_imageloaded = false;
memset(hd_buf, 0, sizeof(hd_buf));
#if HD_LED
hd_status_next = DISK_STATUS_OFF;
hd_status_prev = DISK_STATUS_OFF;
#endif
}
// From FloppyDisk
std::string imagename; // <FILENAME> (ie. no extension)
std::string fullname; // <FILENAME.EXT> or <FILENAME.zip>
std::string strFilenameInZip; // "" or <FILENAME.EXT> [not used]
ImageInfo* imagehandle; // Init'd by HD_Insert() -> ImageOpen()
bool bWriteProtected; // Needed for ImageOpen() [otherwise not used]
//
BYTE hd_error; // NB. Firmware requires that b0=0 (OK) or b0=1 (Error)
WORD hd_memblock;
UINT hd_diskblock;
WORD hd_buf_ptr;
bool hd_imageloaded;
BYTE hd_buf[HD_BLOCK_SIZE+1]; // Why +1? Probably for erroreous reads beyond the block size (ie. reads from I/O addr 0xC0F8)
#if HD_LED
Disk_Status_e hd_status_next;
Disk_Status_e hd_status_prev;
#endif
};
static bool g_bHD_RomLoaded = false;
static bool g_bHD_Enabled = false;
static BYTE g_nHD_UnitNum = HARDDISK_1<<7; // b7=unit
// The HDD interface has a single Command register for both drives: // The HDD interface has a single Command register for both drives:
// . ProDOS will write to Command before switching drives // . ProDOS will write to Command before switching drives
static BYTE g_nHD_Command; m_command = 0;
static HDD g_HardDisk[NUM_HARDDISKS]; m_saveDiskImage = true; // Save the DiskImage name to Registry
static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry // if created by user in Config->Disk, then MemInitializeIO() won't be called
static UINT g_uSlot = SLOT7; if (GetCxRomPeripheral())
Initialize(GetCxRomPeripheral()); // During regular start-up, Initialize() will be called later by MemInitializeIO()
}
HarddiskInterfaceCard::~HarddiskInterfaceCard(void)
{
CleanupDriveInternal(HARDDISK_1);
CleanupDriveInternal(HARDDISK_2);
// if destroyed by user in Config->Disk, then ensure that old object's reference is removed
UnregisterIoHandler(m_slot);
}
void HarddiskInterfaceCard::Reset(const bool powerCycle)
{
m_hardDiskDrive[HARDDISK_1].m_error = 0;
m_hardDiskDrive[HARDDISK_2].m_error = 0;
}
//=========================================================================== //===========================================================================
static void HD_SaveLastDiskImage(const int iDrive); void HarddiskInterfaceCard::CleanupDriveInternal(const int iDrive)
static void HD_CleanupDrive(const int iDrive)
{ {
if (g_HardDisk[iDrive].imagehandle) if (m_hardDiskDrive[iDrive].m_imagehandle)
{ {
ImageClose(g_HardDisk[iDrive].imagehandle); ImageClose(m_hardDiskDrive[iDrive].m_imagehandle);
g_HardDisk[iDrive].imagehandle = NULL; m_hardDiskDrive[iDrive].m_imagehandle = NULL;
} }
g_HardDisk[iDrive].hd_imageloaded = false; m_hardDiskDrive[iDrive].m_imageloaded = false;
g_HardDisk[iDrive].imagename.clear(); m_hardDiskDrive[iDrive].m_imagename.clear();
g_HardDisk[iDrive].fullname.clear(); m_hardDiskDrive[iDrive].m_fullname.clear();
g_HardDisk[iDrive].strFilenameInZip.clear(); m_hardDiskDrive[iDrive].m_strFilenameInZip.clear();
HD_SaveLastDiskImage(iDrive);
} }
//----------------------------------------------------------------------------- void HarddiskInterfaceCard::CleanupDrive(const int iDrive)
{
CleanupDriveInternal(iDrive);
static void NotifyInvalidImage(TCHAR* pszImageFilename) SaveLastDiskImage(iDrive);
}
//===========================================================================
void HarddiskInterfaceCard::NotifyInvalidImage(TCHAR* pszImageFilename)
{ {
// TC: TO DO // TC: TO DO
} }
//=========================================================================== //===========================================================================
BOOL HD_Insert(const int iDrive, const std::string& pathname); void HarddiskInterfaceCard::LoadLastDiskImage(const int drive)
void HD_LoadLastDiskImage(const int drive)
{ {
_ASSERT(drive == HARDDISK_1 || drive == HARDDISK_2); _ASSERT(drive == HARDDISK_1 || drive == HARDDISK_2);
@ -219,32 +191,32 @@ void HD_LoadLastDiskImage(const int drive)
char pathname[MAX_PATH]; char pathname[MAX_PATH];
std::string& regSection = RegGetConfigSlotSection(g_uSlot); std::string& regSection = RegGetConfigSlotSection(m_slot);
if (RegLoadString(regSection.c_str(), regKey.c_str(), TRUE, pathname, MAX_PATH, TEXT(""))) if (RegLoadString(regSection.c_str(), regKey.c_str(), TRUE, pathname, MAX_PATH, TEXT("")))
{ {
g_bSaveDiskImage = false; m_saveDiskImage = false;
HD_Insert(drive, pathname); Insert(drive, pathname);
g_bSaveDiskImage = true; m_saveDiskImage = true;
} }
} }
//=========================================================================== //===========================================================================
static void HD_SaveLastDiskImage(const int drive) void HarddiskInterfaceCard::SaveLastDiskImage(const int drive)
{ {
_ASSERT(drive == HARDDISK_1 || drive == HARDDISK_2); _ASSERT(drive == HARDDISK_1 || drive == HARDDISK_2);
if (!g_bSaveDiskImage) if (!m_saveDiskImage)
return; return;
std::string& regSection = RegGetConfigSlotSection(g_uSlot); std::string& regSection = RegGetConfigSlotSection(m_slot);
RegSaveValue(regSection.c_str(), REGVALUE_CARD_TYPE, TRUE, CT_GenericHDD); RegSaveValue(regSection.c_str(), REGVALUE_CARD_TYPE, TRUE, CT_GenericHDD);
const std::string regKey = (drive == HARDDISK_1) const std::string regKey = (drive == HARDDISK_1)
? REGVALUE_LAST_HARDDISK_1 ? REGVALUE_LAST_HARDDISK_1
: REGVALUE_LAST_HARDDISK_2; : REGVALUE_LAST_HARDDISK_2;
const std::string& pathName = HD_GetFullPathName(drive); const std::string& pathName = HarddiskGetFullPathName(drive);
RegSaveString(regSection.c_str(), regKey.c_str(), TRUE, pathName); RegSaveString(regSection.c_str(), regKey.c_str(), TRUE, pathName);
@ -252,7 +224,7 @@ static void HD_SaveLastDiskImage(const int drive)
// For now, only update 'HDV Starting Directory' for slot7 & drive1 // For now, only update 'HDV Starting Directory' for slot7 & drive1
// . otherwise you'll get inconsistent results if you set drive1, then drive2 (and the images were in different folders) // . otherwise you'll get inconsistent results if you set drive1, then drive2 (and the images were in different folders)
if (g_uSlot != SLOT7 || drive != HARDDISK_1) if (m_slot != SLOT7 || drive != HARDDISK_1)
return; return;
TCHAR szPathName[MAX_PATH]; TCHAR szPathName[MAX_PATH];
@ -267,83 +239,33 @@ static void HD_SaveLastDiskImage(const int drive)
//=========================================================================== //===========================================================================
// (Nearly) everything below is global const std::string& HarddiskInterfaceCard::GetFullName(const int iDrive)
static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
static const DWORD HDDRVR_SIZE = APPLE_SLOT_SIZE;
bool HD_CardIsEnabled(void)
{ {
return g_bHD_RomLoaded && g_bHD_Enabled; return m_hardDiskDrive[iDrive].m_fullname;
} }
// Called by: const std::string& HarddiskInterfaceCard::HarddiskGetFullPathName(const int iDrive)
// . LoadConfiguration() - Done at each restart
// . RestoreCurrentConfig() - Done when Config dialog is cancelled
// . Snapshot_LoadState_v2() - Done to default to disabled state
void HD_SetEnabled(const bool bEnabled, bool updateRegistry/*=true*/)
{ {
if(g_bHD_Enabled == bEnabled) return ImageGetPathname(m_hardDiskDrive[iDrive].m_imagehandle);
return;
g_bHD_Enabled = bEnabled;
if (bEnabled)
GetCardMgr().Insert(SLOT7, CT_GenericHDD, updateRegistry);
else
GetCardMgr().Remove(SLOT7);
#if 0
// FIXME: For LoadConfiguration(), g_uSlot=7 (see definition at start of file)
// . g_uSlot is only really setup by HD_Load_Rom(), later on
RegisterIoHandler(g_uSlot, HD_IO_EMUL, HD_IO_EMUL, NULL, NULL, NULL, NULL);
LPBYTE pCxRomPeripheral = MemGetCxRomPeripheral();
if(pCxRomPeripheral == NULL) // This will be NULL when called after loading value from Registry
return;
//
if(g_bHD_Enabled)
HD_Load_Rom(pCxRomPeripheral, g_uSlot);
else
memset(pCxRomPeripheral + g_uSlot*256, 0, HDDRVR_SIZE);
#endif
} }
//------------------------------------- const std::string& HarddiskInterfaceCard::DiskGetBaseName(const int iDrive)
const std::string & HD_GetFullName(const int iDrive)
{ {
return g_HardDisk[iDrive].fullname; return m_hardDiskDrive[iDrive].m_imagename;
} }
const std::string & HD_GetFullPathName(const int iDrive) void HarddiskInterfaceCard::GetFilenameAndPathForSaveState(std::string& filename, std::string& path)
{
return ImageGetPathname(g_HardDisk[iDrive].imagehandle);
}
static const std::string & HD_DiskGetBaseName(const int iDrive)
{
return g_HardDisk[iDrive].imagename;
}
void HD_GetFilenameAndPathForSaveState(std::string& filename, std::string& path)
{ {
filename = ""; filename = "";
path = ""; path = "";
if (!g_bHD_Enabled)
return;
for (UINT i=HARDDISK_1; i<=HARDDISK_2; i++) for (UINT i=HARDDISK_1; i<=HARDDISK_2; i++)
{ {
if (!g_HardDisk[i].hd_imageloaded) if (!m_hardDiskDrive[i].m_imageloaded)
continue; continue;
filename = HD_DiskGetBaseName(i); filename = DiskGetBaseName(i);
std::string pathname = HD_GetFullPathName(i); std::string pathname = HarddiskGetFullPathName(i);
int idx = pathname.find_last_of(PATH_SEPARATOR); int idx = pathname.find_last_of(PATH_SEPARATOR);
if (idx >= 0 && idx+1 < (int)pathname.length()) // path exists? if (idx >= 0 && idx+1 < (int)pathname.length()) // path exists?
@ -357,55 +279,48 @@ void HD_GetFilenameAndPathForSaveState(std::string& filename, std::string& path)
} }
} }
//------------------------------------- //===========================================================================
void HD_Reset(void) void HarddiskInterfaceCard::Initialize(const LPBYTE pCxRomPeripheral)
{ {
g_HardDisk[HARDDISK_1].hd_error = 0; const DWORD HARDDISK_FW_SIZE = APPLE_SLOT_SIZE;
g_HardDisk[HARDDISK_2].hd_error = 0;
}
//------------------------------------- BYTE* pData = GetFrame().GetResource(IDR_HDDRVR_FW, "FIRMWARE", HARDDISK_FW_SIZE);
void HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot)
{
if(!g_bHD_Enabled)
return;
BYTE* pData = GetFrame().GetResource(IDR_HDDRVR_FW, "FIRMWARE", HDDRVR_SIZE);
if (pData == NULL) if (pData == NULL)
return; return;
g_uSlot = uSlot; memcpy(pCxRomPeripheral + m_slot * APPLE_SLOT_SIZE, pData, HARDDISK_FW_SIZE);
memcpy(pCxRomPeripheral + uSlot*256, pData, HDDRVR_SIZE);
g_bHD_RomLoaded = true;
RegisterIoHandler(g_uSlot, HD_IO_EMUL, HD_IO_EMUL, NULL, NULL, NULL, NULL); RegisterIoHandler(m_slot, IORead, IOWrite, NULL, NULL, this, NULL);
} }
void HD_Destroy(void) //===========================================================================
void HarddiskInterfaceCard::Destroy(void)
{ {
g_bSaveDiskImage = false; m_saveDiskImage = false;
HD_CleanupDrive(HARDDISK_1); CleanupDrive(HARDDISK_1);
g_bSaveDiskImage = false; m_saveDiskImage = false;
HD_CleanupDrive(HARDDISK_2); CleanupDrive(HARDDISK_2);
g_bSaveDiskImage = true; m_saveDiskImage = true;
} }
//===========================================================================
// Pre: pathname likely to include path (but can also just be filename) // Pre: pathname likely to include path (but can also just be filename)
BOOL HD_Insert(const int iDrive, const std::string& pathname) BOOL HarddiskInterfaceCard::Insert(const int iDrive, const std::string& pathname)
{ {
if (pathname.empty()) if (pathname.empty())
return FALSE; return FALSE;
if (g_HardDisk[iDrive].hd_imageloaded) if (m_hardDiskDrive[iDrive].m_imageloaded)
HD_Unplug(iDrive); Unplug(iDrive);
// Check if image is being used by the other HDD, and unplug it in order to be swapped // Check if image is being used by the other HDD, and unplug it in order to be swapped
{ {
const std::string & pszOtherPathname = HD_GetFullPathName(!iDrive); const std::string & pszOtherPathname = HarddiskGetFullPathName(!iDrive);
char szCurrentPathname[MAX_PATH]; char szCurrentPathname[MAX_PATH];
DWORD uNameLen = GetFullPathName(pathname.c_str(), MAX_PATH, szCurrentPathname, NULL); DWORD uNameLen = GetFullPathName(pathname.c_str(), MAX_PATH, szCurrentPathname, NULL);
@ -414,7 +329,7 @@ BOOL HD_Insert(const int iDrive, const std::string& pathname)
if (!strcmp(pszOtherPathname.c_str(), szCurrentPathname)) if (!strcmp(pszOtherPathname.c_str(), szCurrentPathname))
{ {
HD_Unplug(!iDrive); Unplug(!iDrive);
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS); GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS);
} }
} }
@ -423,31 +338,31 @@ BOOL HD_Insert(const int iDrive, const std::string& pathname)
const bool bExpectFloppy = false; const bool bExpectFloppy = false;
const bool bIsHarddisk = true; const bool bIsHarddisk = true;
ImageError_e Error = ImageOpen(pathname, ImageError_e Error = ImageOpen(pathname,
&g_HardDisk[iDrive].imagehandle, &m_hardDiskDrive[iDrive].m_imagehandle,
&g_HardDisk[iDrive].bWriteProtected, &m_hardDiskDrive[iDrive].m_bWriteProtected,
bCreateIfNecessary, bCreateIfNecessary,
g_HardDisk[iDrive].strFilenameInZip, // TODO: Use this m_hardDiskDrive[iDrive].m_strFilenameInZip, // TODO: Use this
bExpectFloppy); bExpectFloppy);
g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE); m_hardDiskDrive[iDrive].m_imageloaded = (Error == eIMAGE_ERROR_NONE);
#if HD_LED m_hardDiskDrive[iDrive].m_status_next = DISK_STATUS_OFF;
g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF; m_hardDiskDrive[iDrive].m_status_prev = DISK_STATUS_OFF;
g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
#endif
if (Error == eIMAGE_ERROR_NONE) if (Error == eIMAGE_ERROR_NONE)
{ {
GetImageTitle(pathname.c_str(), g_HardDisk[iDrive].imagename, g_HardDisk[iDrive].fullname); GetImageTitle(pathname.c_str(), m_hardDiskDrive[iDrive].m_imagename, m_hardDiskDrive[iDrive].m_fullname);
Snapshot_UpdatePath(); Snapshot_UpdatePath();
} }
HD_SaveLastDiskImage(iDrive); SaveLastDiskImage(iDrive);
return g_HardDisk[iDrive].hd_imageloaded; return m_hardDiskDrive[iDrive].m_imageloaded;
} }
static bool HD_SelectImage(const int drive, LPCSTR pszFilename) //-----------------------------------------------------------------------------
bool HarddiskInterfaceCard::SelectImage(const int drive, LPCSTR pszFilename)
{ {
TCHAR directory[MAX_PATH]; TCHAR directory[MAX_PATH];
TCHAR filename[MAX_PATH]; TCHAR filename[MAX_PATH];
@ -478,7 +393,7 @@ static bool HD_SelectImage(const int drive, LPCSTR pszFilename)
if ((!ofn.nFileExtension) || !filename[ofn.nFileExtension]) if ((!ofn.nFileExtension) || !filename[ofn.nFileExtension])
StringCbCat(filename, MAX_PATH, TEXT(".hdv")); StringCbCat(filename, MAX_PATH, TEXT(".hdv"));
if (HD_Insert(drive, filename)) if (Insert(drive, filename))
{ {
bRes = true; bRes = true;
} }
@ -491,252 +406,241 @@ static bool HD_SelectImage(const int drive, LPCSTR pszFilename)
return bRes; return bRes;
} }
bool HD_Select(const int iDrive) bool HarddiskInterfaceCard::Select(const int iDrive)
{ {
return HD_SelectImage(iDrive, TEXT("")); return SelectImage(iDrive, TEXT(""));
} }
void HD_Unplug(const int iDrive) //===========================================================================
void HarddiskInterfaceCard::Unplug(const int iDrive)
{ {
if (g_HardDisk[iDrive].hd_imageloaded) if (m_hardDiskDrive[iDrive].m_imageloaded)
{ {
HD_CleanupDrive(iDrive); CleanupDrive(iDrive);
Snapshot_UpdatePath(); Snapshot_UpdatePath();
} }
} }
bool HD_IsDriveUnplugged(const int iDrive) bool HarddiskInterfaceCard::IsDriveUnplugged(const int iDrive)
{ {
return g_HardDisk[iDrive].hd_imageloaded == false; return m_hardDiskDrive[iDrive].m_imageloaded == false;
} }
//----------------------------------------------------------------------------- //===========================================================================
#define DEVICE_OK 0x00 #define DEVICE_OK 0x00
#define DEVICE_UNKNOWN_ERROR 0x28 #define DEVICE_UNKNOWN_ERROR 0x28
#define DEVICE_IO_ERROR 0x27 #define DEVICE_IO_ERROR 0x27
static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles) BYTE __stdcall HarddiskInterfaceCard::IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{ {
const UINT slot = ((addr & 0xff) >> 4) - 8;
HarddiskInterfaceCard* pCard = (HarddiskInterfaceCard*)MemGetSlotParameters(slot);
HardDiskDrive* pHDD = &(pCard->m_hardDiskDrive[pCard->m_unitNum >> 7]); // bit7 = drive select
BYTE r = DEVICE_OK; BYTE r = DEVICE_OK;
addr &= 0xFF; pHDD->m_status_next = DISK_STATUS_READ;
if (!HD_CardIsEnabled()) switch (addr & 0xF)
return r;
HDD* pHDD = &g_HardDisk[g_nHD_UnitNum >> 7]; // bit7 = drive select
if (bWrite == 0) // read
{ {
#if HD_LED case 0x0:
pHDD->hd_status_next = DISK_STATUS_READ; if (pHDD->m_imageloaded)
#endif
switch (addr)
{
case 0xF0:
if (pHDD->hd_imageloaded)
{ {
// based on loaded data block request, load block into memory // based on loaded data block request, load block into memory
// returns status // returns status
switch (g_nHD_Command) switch (pCard->m_command)
{ {
default: default:
case 0x00: //status case 0x00: //status
if (ImageGetImageSize(pHDD->imagehandle) == 0) if (ImageGetImageSize(pHDD->m_imagehandle) == 0)
{ {
pHDD->hd_error = 1; pHDD->m_error = 1;
r = DEVICE_IO_ERROR; r = DEVICE_IO_ERROR;
} }
break; break;
case 0x01: //read case 0x01: //read
if ((pHDD->hd_diskblock * HD_BLOCK_SIZE) < ImageGetImageSize(pHDD->imagehandle)) if ((pHDD->m_diskblock * HD_BLOCK_SIZE) < ImageGetImageSize(pHDD->m_imagehandle))
{ {
bool bRes = ImageReadBlock(pHDD->imagehandle, pHDD->hd_diskblock, pHDD->hd_buf); bool bRes = ImageReadBlock(pHDD->m_imagehandle, pHDD->m_diskblock, pHDD->m_buf);
if (bRes) if (bRes)
{ {
pHDD->hd_error = 0; pHDD->m_error = 0;
r = 0; r = 0;
pHDD->hd_buf_ptr = 0; pHDD->m_buf_ptr = 0;
} }
else else
{ {
pHDD->hd_error = 1; pHDD->m_error = 1;
r = DEVICE_IO_ERROR; r = DEVICE_IO_ERROR;
} }
} }
else else
{ {
pHDD->hd_error = 1; pHDD->m_error = 1;
r = DEVICE_IO_ERROR; r = DEVICE_IO_ERROR;
} }
break; break;
case 0x02: //write case 0x02: //write
{ {
#if HD_LED pHDD->m_status_next = DISK_STATUS_WRITE;
pHDD->hd_status_next = DISK_STATUS_WRITE;
#endif
bool bRes = true; bool bRes = true;
const bool bAppendBlocks = (pHDD->hd_diskblock * HD_BLOCK_SIZE) >= ImageGetImageSize(pHDD->imagehandle); const bool bAppendBlocks = (pHDD->m_diskblock * HD_BLOCK_SIZE) >= ImageGetImageSize(pHDD->m_imagehandle);
if (bAppendBlocks) if (bAppendBlocks)
{ {
memset(pHDD->hd_buf, 0, HD_BLOCK_SIZE); memset(pHDD->m_buf, 0, HD_BLOCK_SIZE);
// Inefficient (especially for gzip/zip files!) // Inefficient (especially for gzip/zip files!)
UINT uBlock = ImageGetImageSize(pHDD->imagehandle) / HD_BLOCK_SIZE; UINT uBlock = ImageGetImageSize(pHDD->m_imagehandle) / HD_BLOCK_SIZE;
while (uBlock < pHDD->hd_diskblock) while (uBlock < pHDD->m_diskblock)
{ {
bRes = ImageWriteBlock(pHDD->imagehandle, uBlock++, pHDD->hd_buf); bRes = ImageWriteBlock(pHDD->m_imagehandle, uBlock++, pHDD->m_buf);
_ASSERT(bRes); _ASSERT(bRes);
if (!bRes) if (!bRes)
break; break;
} }
} }
memmove(pHDD->hd_buf, mem+pHDD->hd_memblock, HD_BLOCK_SIZE); memmove(pHDD->m_buf, mem+pHDD->m_memblock, HD_BLOCK_SIZE);
if (bRes) if (bRes)
bRes = ImageWriteBlock(pHDD->imagehandle, pHDD->hd_diskblock, pHDD->hd_buf); bRes = ImageWriteBlock(pHDD->m_imagehandle, pHDD->m_diskblock, pHDD->m_buf);
if (bRes) if (bRes)
{ {
pHDD->hd_error = 0; pHDD->m_error = 0;
r = 0; r = 0;
} }
else else
{ {
pHDD->hd_error = 1; pHDD->m_error = 1;
r = DEVICE_IO_ERROR; r = DEVICE_IO_ERROR;
} }
} }
break; break;
case 0x03: //format case 0x03: //format
#if HD_LED pHDD->m_status_next = DISK_STATUS_WRITE;
pHDD->hd_status_next = DISK_STATUS_WRITE;
#endif
break; break;
} }
} }
else else
{ {
#if HD_LED pHDD->m_status_next = DISK_STATUS_OFF;
pHDD->hd_status_next = DISK_STATUS_OFF; pHDD->m_error = 1;
#endif
pHDD->hd_error = 1;
r = DEVICE_UNKNOWN_ERROR; r = DEVICE_UNKNOWN_ERROR;
} }
break; break;
case 0xF1: // hd_error case 0x1: // m_error
#if HD_LED pHDD->m_status_next = DISK_STATUS_OFF; // TODO: FIXME: ??? YELLOW ??? WARNING
pHDD->hd_status_next = DISK_STATUS_OFF; // TODO: FIXME: ??? YELLOW ??? WARNING if (pHDD->m_error)
#endif
if (pHDD->hd_error)
{ {
_ASSERT(pHDD->hd_error & 1); _ASSERT(pHDD->m_error & 1);
pHDD->hd_error |= 1; // Firmware requires that b0=1 for an error pHDD->m_error |= 1; // Firmware requires that b0=1 for an error
} }
r = pHDD->hd_error; r = pHDD->m_error;
break; break;
case 0xF2: case 0x2:
r = g_nHD_Command; r = pCard->m_command;
break; break;
case 0xF3: case 0x3:
r = g_nHD_UnitNum; r = pCard->m_unitNum;
break; break;
case 0xF4: case 0x4:
r = (BYTE)(pHDD->hd_memblock & 0x00FF); r = (BYTE)(pHDD->m_memblock & 0x00FF);
break; break;
case 0xF5: case 0x5:
r = (BYTE)(pHDD->hd_memblock & 0xFF00 >> 8); r = (BYTE)(pHDD->m_memblock & 0xFF00 >> 8);
break; break;
case 0xF6: case 0x6:
r = (BYTE)(pHDD->hd_diskblock & 0x00FF); r = (BYTE)(pHDD->m_diskblock & 0x00FF);
break; break;
case 0xF7: case 0x7:
r = (BYTE)(pHDD->hd_diskblock & 0xFF00 >> 8); r = (BYTE)(pHDD->m_diskblock & 0xFF00 >> 8);
break; break;
case 0xF8: case 0x8:
r = pHDD->hd_buf[pHDD->hd_buf_ptr]; r = pHDD->m_buf[pHDD->m_buf_ptr];
if (pHDD->hd_buf_ptr < sizeof(pHDD->hd_buf)-1) if (pHDD->m_buf_ptr < sizeof(pHDD->m_buf)-1)
pHDD->hd_buf_ptr++; pHDD->m_buf_ptr++;
break; break;
default: default:
#if HD_LED pHDD->m_status_next = DISK_STATUS_OFF;
pHDD->hd_status_next = DISK_STATUS_OFF; r = IO_Null(pc, addr, bWrite, d, nExecutedCycles);
#endif
return IO_Null(pc, addr, bWrite, d, nExecutedCycles);
}
}
else // write to registers
{
#if HD_LED
pHDD->hd_status_next = DISK_STATUS_PROT; // TODO: FIXME: If we ever enable write-protect on HD then need to change to something else ...
#endif
switch (addr)
{
case 0xF2:
g_nHD_Command = d;
break;
case 0xF3:
// b7 = drive#
// b6..4 = slot#
// b3..0 = ?
g_nHD_UnitNum = d;
break;
case 0xF4:
pHDD->hd_memblock = (pHDD->hd_memblock & 0xFF00) | d;
break;
case 0xF5:
pHDD->hd_memblock = (pHDD->hd_memblock & 0x00FF) | (d << 8);
break;
case 0xF6:
pHDD->hd_diskblock = (pHDD->hd_diskblock & 0xFF00) | d;
break;
case 0xF7:
pHDD->hd_diskblock = (pHDD->hd_diskblock & 0x00FF) | (d << 8);
break;
default:
#if HD_LED
pHDD->hd_status_next = DISK_STATUS_OFF;
#endif
return IO_Null(pc, addr, bWrite, d, nExecutedCycles);
}
} }
#if HD_LED pCard->UpdateLightStatus(pHDD);
// 1.19.0.0 Hard Disk Status/Indicator Light
if( pHDD->hd_status_prev != pHDD->hd_status_next ) // Update LEDs if state changes
{
pHDD->hd_status_prev = pHDD->hd_status_next;
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS);
}
#endif
return r; return r;
} }
// 1.19.0.0 Hard Disk Status/Indicator Light //-----------------------------------------------------------------------------
void HD_GetLightStatus (Disk_Status_e *pDisk1Status_)
BYTE __stdcall HarddiskInterfaceCard::IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{ {
#if HD_LED const UINT slot = ((addr & 0xff) >> 4) - 8;
if ( HD_CardIsEnabled() ) HarddiskInterfaceCard* pCard = (HarddiskInterfaceCard*)MemGetSlotParameters(slot);
HardDiskDrive* pHDD = &(pCard->m_hardDiskDrive[pCard->m_unitNum >> 7]); // bit7 = drive select
BYTE r = DEVICE_OK;
pHDD->m_status_next = DISK_STATUS_PROT; // TODO: FIXME: If we ever enable write-protect on HD then need to change to something else ...
switch (addr & 0xF)
{ {
HDD* pHDD = &g_HardDisk[g_nHD_UnitNum >> 7]; // bit7 = drive select case 0x2:
*pDisk1Status_ = pHDD->hd_status_prev; pCard->m_command = d;
} else break;
#endif case 0x3:
// b7 = drive#
// b6..4 = slot#
// b3..0 = ?
pCard->m_unitNum = d;
break;
case 0x4:
pHDD->m_memblock = (pHDD->m_memblock & 0xFF00) | d;
break;
case 0x5:
pHDD->m_memblock = (pHDD->m_memblock & 0x00FF) | (d << 8);
break;
case 0x6:
pHDD->m_diskblock = (pHDD->m_diskblock & 0xFF00) | d;
break;
case 0x7:
pHDD->m_diskblock = (pHDD->m_diskblock & 0x00FF) | (d << 8);
break;
default:
pHDD->m_status_next = DISK_STATUS_OFF;
r = IO_Null(pc, addr, bWrite, d, nExecutedCycles);
}
pCard->UpdateLightStatus(pHDD);
return r;
}
//===========================================================================
void HarddiskInterfaceCard::UpdateLightStatus(HardDiskDrive* pHDD)
{ {
*pDisk1Status_ = DISK_STATUS_OFF; if (pHDD->m_status_prev != pHDD->m_status_next) // Update LEDs if state changes
{
pHDD->m_status_prev = pHDD->m_status_next;
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS);
} }
} }
bool HD_ImageSwap(void) void HarddiskInterfaceCard::GetLightStatus(Disk_Status_e *pDisk1Status)
{ {
std::swap(g_HardDisk[HARDDISK_1], g_HardDisk[HARDDISK_2]); HardDiskDrive* pHDD = &m_hardDiskDrive[m_unitNum >> 7]; // bit7 = drive select
*pDisk1Status = pHDD->m_status_prev;
}
HD_SaveLastDiskImage(HARDDISK_1); //===========================================================================
HD_SaveLastDiskImage(HARDDISK_2);
bool HarddiskInterfaceCard::ImageSwap(void)
{
std::swap(m_hardDiskDrive[HARDDISK_1], m_hardDiskDrive[HARDDISK_2]);
SaveLastDiskImage(HARDDISK_1);
SaveLastDiskImage(HARDDISK_2);
GetFrame().FrameRefreshStatus(DRAW_LEDS); GetFrame().FrameRefreshStatus(DRAW_LEDS);
@ -765,70 +669,67 @@ static const UINT kUNIT_VERSION = 2;
#define SS_YAML_KEY_BUF_PTR "Buffer Offset" #define SS_YAML_KEY_BUF_PTR "Buffer Offset"
#define SS_YAML_KEY_BUF "Buffer" #define SS_YAML_KEY_BUF "Buffer"
std::string HD_GetSnapshotCardName(void) std::string HarddiskInterfaceCard::GetSnapshotCardName(void)
{ {
static const std::string name(SS_YAML_VALUE_CARD_HDD); static const std::string name(SS_YAML_VALUE_CARD_HDD);
return name; return name;
} }
static void HD_SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit) void HarddiskInterfaceCard::SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit)
{ {
YamlSaveHelper::Label label(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_HDDUNIT, unit); YamlSaveHelper::Label label(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_HDDUNIT, unit);
yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, g_HardDisk[unit].fullname); yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, m_hardDiskDrive[unit].m_fullname);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_ERROR, g_HardDisk[unit].hd_error); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_ERROR, m_hardDiskDrive[unit].m_error);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_MEMBLOCK, g_HardDisk[unit].hd_memblock); yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_MEMBLOCK, m_hardDiskDrive[unit].m_memblock);
yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_DISKBLOCK, g_HardDisk[unit].hd_diskblock); yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_DISKBLOCK, m_hardDiskDrive[unit].m_diskblock);
yamlSaveHelper.SaveBool(SS_YAML_KEY_IMAGELOADED, g_HardDisk[unit].hd_imageloaded); yamlSaveHelper.SaveBool(SS_YAML_KEY_IMAGELOADED, m_hardDiskDrive[unit].m_imageloaded);
yamlSaveHelper.SaveUint(SS_YAML_KEY_STATUS_NEXT, g_HardDisk[unit].hd_status_next); yamlSaveHelper.SaveUint(SS_YAML_KEY_STATUS_NEXT, m_hardDiskDrive[unit].m_status_next);
yamlSaveHelper.SaveUint(SS_YAML_KEY_STATUS_PREV, g_HardDisk[unit].hd_status_prev); yamlSaveHelper.SaveUint(SS_YAML_KEY_STATUS_PREV, m_hardDiskDrive[unit].m_status_prev);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_BUF_PTR, g_HardDisk[unit].hd_buf_ptr); yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_BUF_PTR, m_hardDiskDrive[unit].m_buf_ptr);
// New label // New label
{ {
YamlSaveHelper::Label buffer(yamlSaveHelper, "%s:\n", SS_YAML_KEY_BUF); YamlSaveHelper::Label buffer(yamlSaveHelper, "%s:\n", SS_YAML_KEY_BUF);
yamlSaveHelper.SaveMemory(g_HardDisk[unit].hd_buf, HD_BLOCK_SIZE); yamlSaveHelper.SaveMemory(m_hardDiskDrive[unit].m_buf, HD_BLOCK_SIZE);
} }
} }
void HD_SaveSnapshot(YamlSaveHelper& yamlSaveHelper) void HarddiskInterfaceCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{ {
if (!HD_CardIsEnabled()) YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), m_slot, kUNIT_VERSION);
return;
YamlSaveHelper::Slot slot(yamlSaveHelper, HD_GetSnapshotCardName(), g_uSlot, kUNIT_VERSION);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE); YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.Save("%s: %d # b7=unit\n", SS_YAML_KEY_CURRENT_UNIT, g_nHD_UnitNum); yamlSaveHelper.Save("%s: %d # b7=unit\n", SS_YAML_KEY_CURRENT_UNIT, m_unitNum);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_COMMAND, g_nHD_Command); yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_COMMAND, m_command);
HD_SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_1); SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_1);
HD_SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_2); SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_2);
} }
static bool HD_LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit) bool HarddiskInterfaceCard::LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit)
{ {
std::string hddUnitName = std::string(SS_YAML_KEY_HDDUNIT) + (unit == HARDDISK_1 ? std::string("0") : std::string("1")); std::string hddUnitName = std::string(SS_YAML_KEY_HDDUNIT) + (unit == HARDDISK_1 ? std::string("0") : std::string("1"));
if (!yamlLoadHelper.GetSubMap(hddUnitName)) if (!yamlLoadHelper.GetSubMap(hddUnitName))
throw std::string("Card: Expected key: ") + hddUnitName; throw std::string("Card: Expected key: ") + hddUnitName;
g_HardDisk[unit].fullname.clear(); m_hardDiskDrive[unit].m_fullname.clear();
g_HardDisk[unit].imagename.clear(); m_hardDiskDrive[unit].m_imagename.clear();
g_HardDisk[unit].hd_imageloaded = false; // Default to false (until image is successfully loaded below) m_hardDiskDrive[unit].m_imageloaded = false; // Default to false (until image is successfully loaded below)
g_HardDisk[unit].hd_status_next = DISK_STATUS_OFF; m_hardDiskDrive[unit].m_status_next = DISK_STATUS_OFF;
g_HardDisk[unit].hd_status_prev = DISK_STATUS_OFF; m_hardDiskDrive[unit].m_status_prev = DISK_STATUS_OFF;
std::string filename = yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME); std::string filename = yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME);
g_HardDisk[unit].hd_error = yamlLoadHelper.LoadUint(SS_YAML_KEY_ERROR); m_hardDiskDrive[unit].m_error = yamlLoadHelper.LoadUint(SS_YAML_KEY_ERROR);
g_HardDisk[unit].hd_memblock = yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMBLOCK); m_hardDiskDrive[unit].m_memblock = yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMBLOCK);
g_HardDisk[unit].hd_diskblock = yamlLoadHelper.LoadUint(SS_YAML_KEY_DISKBLOCK); m_hardDiskDrive[unit].m_diskblock = yamlLoadHelper.LoadUint(SS_YAML_KEY_DISKBLOCK);
yamlLoadHelper.LoadBool(SS_YAML_KEY_IMAGELOADED); // Consume yamlLoadHelper.LoadBool(SS_YAML_KEY_IMAGELOADED); // Consume
Disk_Status_e diskStatusNext = (Disk_Status_e) yamlLoadHelper.LoadUint(SS_YAML_KEY_STATUS_NEXT); Disk_Status_e diskStatusNext = (Disk_Status_e) yamlLoadHelper.LoadUint(SS_YAML_KEY_STATUS_NEXT);
Disk_Status_e diskStatusPrev = (Disk_Status_e) yamlLoadHelper.LoadUint(SS_YAML_KEY_STATUS_PREV); Disk_Status_e diskStatusPrev = (Disk_Status_e) yamlLoadHelper.LoadUint(SS_YAML_KEY_STATUS_PREV);
g_HardDisk[unit].hd_buf_ptr = yamlLoadHelper.LoadUint(SS_YAML_KEY_BUF_PTR); m_hardDiskDrive[unit].m_buf_ptr = yamlLoadHelper.LoadUint(SS_YAML_KEY_BUF_PTR);
if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_BUF)) if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_BUF))
throw hddUnitName + std::string(": Missing: ") + std::string(SS_YAML_KEY_BUF); throw hddUnitName + std::string(": Missing: ") + std::string(SS_YAML_KEY_BUF);
yamlLoadHelper.LoadMemory(g_HardDisk[unit].hd_buf, HD_BLOCK_SIZE); yamlLoadHelper.LoadMemory(m_hardDiskDrive[unit].m_buf, HD_BLOCK_SIZE);
yamlLoadHelper.PopMap(); yamlLoadHelper.PopMap();
yamlLoadHelper.PopMap(); yamlLoadHelper.PopMap();
@ -843,7 +744,7 @@ static bool HD_LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit)
if (dwAttributes == INVALID_FILE_ATTRIBUTES) if (dwAttributes == INVALID_FILE_ATTRIBUTES)
{ {
// Get user to browse for file // Get user to browse for file
bResSelectImage = HD_SelectImage(unit, filename.c_str()); bResSelectImage = SelectImage(unit, filename.c_str());
dwAttributes = GetFileAttributes(filename.c_str()); dwAttributes = GetFileAttributes(filename.c_str());
} }
@ -851,27 +752,27 @@ static bool HD_LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit)
bool bImageError = (dwAttributes == INVALID_FILE_ATTRIBUTES); bool bImageError = (dwAttributes == INVALID_FILE_ATTRIBUTES);
if (!bImageError) if (!bImageError)
{ {
if (!HD_Insert(unit, filename.c_str())) if (!Insert(unit, filename.c_str()))
bImageError = true; bImageError = true;
// HD_Insert() sets up: // HD_Insert() sets up:
// . imagename // . m_imagename
// . fullname // . m_fullname
// . hd_imageloaded // . m_imageloaded
// . hd_status_next = DISK_STATUS_OFF // . hd_status_next = DISK_STATUS_OFF
// . hd_status_prev = DISK_STATUS_OFF // . hd_status_prev = DISK_STATUS_OFF
g_HardDisk[unit].hd_status_next = diskStatusNext; m_hardDiskDrive[unit].m_status_next = diskStatusNext;
g_HardDisk[unit].hd_status_prev = diskStatusPrev; m_hardDiskDrive[unit].m_status_prev = diskStatusPrev;
} }
} }
return bResSelectImage; return bResSelectImage;
} }
bool HD_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, const std::string & strSaveStatePath) bool HarddiskInterfaceCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, const std::string& strSaveStatePath)
{ {
if (slot != 7) // fixme if (slot != SLOT7) // fixme
throw std::string("Card: wrong slot"); throw std::string("Card: wrong slot");
if (version < 1 || version > kUNIT_VERSION) if (version < 1 || version > kUNIT_VERSION)
@ -880,24 +781,22 @@ bool HD_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, co
if (version == 1 && (regs.pc >> 8) == (0xC0|slot)) if (version == 1 && (regs.pc >> 8) == (0xC0|slot))
throw std::string("HDD card: 6502 is running old HDD firmware"); throw std::string("HDD card: 6502 is running old HDD firmware");
g_nHD_UnitNum = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_UNIT); // b7=unit m_unitNum = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_UNIT); // b7=unit
g_nHD_Command = yamlLoadHelper.LoadUint(SS_YAML_KEY_COMMAND); m_command = yamlLoadHelper.LoadUint(SS_YAML_KEY_COMMAND);
// Unplug all HDDs first in case HDD-2 is to be plugged in as HDD-1 // Unplug all HDDs first in case HDD-2 is to be plugged in as HDD-1
for (UINT i=0; i<NUM_HARDDISKS; i++) for (UINT i=0; i<NUM_HARDDISKS; i++)
{ {
HD_Unplug(i); Unplug(i);
g_HardDisk[i].clear(); m_hardDiskDrive[i].clear();
} }
bool bResSelectImage1 = HD_LoadSnapshotHDDUnit(yamlLoadHelper, HARDDISK_1); bool bResSelectImage1 = LoadSnapshotHDDUnit(yamlLoadHelper, HARDDISK_1);
bool bResSelectImage2 = HD_LoadSnapshotHDDUnit(yamlLoadHelper, HARDDISK_2); bool bResSelectImage2 = LoadSnapshotHDDUnit(yamlLoadHelper, HARDDISK_2);
if (!bResSelectImage1 && !bResSelectImage2) if (!bResSelectImage1 && !bResSelectImage2)
RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, strSaveStatePath); RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, strSaveStatePath);
HD_SetEnabled(true, false);
GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS); GetFrame().FrameRefreshStatus(DRAW_LEDS | DRAW_DISK_STATUS);
return true; return true;

View file

@ -23,10 +23,9 @@ along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ */
#include "Card.h"
#include "DiskImage.h" #include "DiskImage.h"
#include "DiskImageHelper.h"
// 1.19.0.0 Hard Disk Status/Indicator Light
#define HD_LED 1
enum HardDrive_e enum HardDrive_e
{ {
@ -35,24 +34,100 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
NUM_HARDDISKS NUM_HARDDISKS
}; };
void HD_Destroy(void); class HardDiskDrive
bool HD_CardIsEnabled(void); {
void HD_SetEnabled(const bool bEnabled, bool updateRegistry = true); public:
const std::string & HD_GetFullName(const int iDrive); HardDiskDrive(void)
const std::string & HD_GetFullPathName(const int iDrive); {
void HD_GetFilenameAndPathForSaveState(std::string& filename, std::string& path); clear();
void HD_Reset(void); }
void HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot); ~HardDiskDrive(void) {}
bool HD_Select(const int iDrive);
BOOL HD_Insert(const int iDrive, const std::string& pathname);
void HD_Unplug(const int iDrive);
bool HD_IsDriveUnplugged(const int iDrive);
void HD_LoadLastDiskImage(const int iDrive);
// 1.19.0.0 Hard Disk Status/Indicator Light void clear()
void HD_GetLightStatus (Disk_Status_e *pDisk1Status_); {
bool HD_ImageSwap(void); m_imagename.clear();
m_fullname.clear();
m_strFilenameInZip.clear();
m_imagehandle = NULL;
m_bWriteProtected = false;
//
m_error = 0;
m_memblock = 0;
m_diskblock = 0;
m_buf_ptr = 0;
m_imageloaded = false;
memset(m_buf, 0, sizeof(m_buf));
m_status_next = DISK_STATUS_OFF;
m_status_prev = DISK_STATUS_OFF;
}
std::string HD_GetSnapshotCardName(void); // From FloppyDisk
void HD_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper); std::string m_imagename; // <FILENAME> (ie. no extension)
bool HD_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, const std::string & strSaveStatePath); std::string m_fullname; // <FILENAME.EXT> or <FILENAME.zip>
std::string m_strFilenameInZip; // "" or <FILENAME.EXT> [not used]
ImageInfo* m_imagehandle; // Init'd by HD_Insert() -> ImageOpen()
bool m_bWriteProtected; // Needed for ImageOpen() [otherwise not used]
//
BYTE m_error; // NB. Firmware requires that b0=0 (OK) or b0=1 (Error)
WORD m_memblock;
UINT m_diskblock;
WORD m_buf_ptr;
bool m_imageloaded;
BYTE m_buf[HD_BLOCK_SIZE];
Disk_Status_e m_status_next;
Disk_Status_e m_status_prev;
};
class HarddiskInterfaceCard : public Card
{
public:
HarddiskInterfaceCard(UINT slot);
virtual ~HarddiskInterfaceCard(void);
virtual void Init(void) {}
virtual void Reset(const bool powerCycle);
void Initialize(const LPBYTE pCxRomPeripheral);
void Destroy(void);
const std::string& GetFullName(const int iDrive);
const std::string& HarddiskGetFullPathName(const int iDrive);
void GetFilenameAndPathForSaveState(std::string& filename, std::string& path);
bool Select(const int iDrive);
BOOL Insert(const int iDrive, const std::string& pathname);
void Unplug(const int iDrive);
bool IsDriveUnplugged(const int iDrive);
void LoadLastDiskImage(const int iDrive);
void GetLightStatus(Disk_Status_e* pDisk1Status);
bool ImageSwap(void);
static std::string GetSnapshotCardName(void);
void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, const std::string& strSaveStatePath);
static BYTE __stdcall IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
static BYTE __stdcall IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
private:
void CleanupDriveInternal(const int iDrive);
void CleanupDrive(const int iDrive);
void NotifyInvalidImage(TCHAR* pszImageFilename);
void SaveLastDiskImage(const int drive);
const std::string& DiskGetBaseName(const int iDrive);
bool SelectImage(const int drive, LPCSTR pszFilename);
void UpdateLightStatus(HardDiskDrive* pHDD);
void SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit);
bool LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit);
//
BYTE m_unitNum; // b7=unit
BYTE m_command;
bool m_saveDiskImage; // Save the DiskImage name to Registry
UINT m_slot;
HardDiskDrive m_hardDiskDrive[NUM_HARDDISKS];
};

View file

@ -1012,6 +1012,12 @@ void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, io
ExpansionRom[uSlot] = pExpansionRom; ExpansionRom[uSlot] = pExpansionRom;
} }
void UnregisterIoHandler(UINT uSlot)
{
RegisterIoHandler(uSlot, NULL, NULL, NULL, NULL, NULL, NULL);
g_SlotInfo[uSlot].bHasCard = false;
}
// From UTAIIe:5-28: Since INTCXROM==1 then state of SLOTC3ROM is not important // From UTAIIe:5-28: Since INTCXROM==1 then state of SLOTC3ROM is not important
static void IoHandlerCardsOut(void) static void IoHandlerCardsOut(void)
{ {
@ -1784,14 +1790,14 @@ void MemInitializeIO(void)
} }
else if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2) else if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2)
{ {
dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(SLOT5)).Initialize(pCxRomPeripheral, SLOT5); // $C500 : Disk][ card dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(SLOT5)).Initialize(pCxRomPeripheral); // $C500 : Disk][ card
} }
if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2) if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(SLOT6)).Initialize(pCxRomPeripheral, SLOT6); // $C600 : Disk][ card dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(SLOT6)).Initialize(pCxRomPeripheral); // $C600 : Disk][ card
if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD) if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
HD_Load_Rom(pCxRomPeripheral, SLOT7); // $C700 : HDD f/w dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Initialize(pCxRomPeripheral);
} }
// Called by: // Called by:

View file

@ -60,6 +60,7 @@ const UINT kMaxExMemoryBanks = 127; // 127 * aux mem(64K) + main mem(64K) = 8MB
#endif #endif
void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, iofunction IOReadCx, iofunction IOWriteCx, LPVOID lpSlotParameter, BYTE* pExpansionRom); void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, iofunction IOReadCx, iofunction IOWriteCx, LPVOID lpSlotParameter, BYTE* pExpansionRom);
void UnregisterIoHandler(UINT uSlot);
void MemDestroy (); void MemDestroy ();
bool MemCheckSLOTC3ROM(); bool MemCheckSLOTC3ROM();

View file

@ -147,7 +147,10 @@ void Snapshot_GetDefaultFilenameAndPath(std::string& defaultFilename, std::strin
{ {
// Attempt to get a default filename/path based on harddisk plugged-in or floppy disk inserted // Attempt to get a default filename/path based on harddisk plugged-in or floppy disk inserted
// . Priority given to harddisk over floppy images // . Priority given to harddisk over floppy images
HD_GetFilenameAndPathForSaveState(defaultFilename, defaultPath);
if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).GetFilenameAndPathForSaveState(defaultFilename, defaultPath);
if (defaultFilename.empty()) if (defaultFilename.empty())
GetCardMgr().GetDisk2CardMgr().GetFilenameAndPathForSaveState(defaultFilename, defaultPath); GetCardMgr().GetDisk2CardMgr().GetFilenameAndPathForSaveState(defaultFilename, defaultPath);
} }
@ -370,11 +373,11 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT unitVersion)
GetCardMgr().Insert(slot, type); GetCardMgr().Insert(slot, type);
bRes = dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(slot)).LoadSnapshot(yamlLoadHelper, slot, cardVersion); bRes = dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(slot)).LoadSnapshot(yamlLoadHelper, slot, cardVersion);
} }
else if (card == HD_GetSnapshotCardName()) else if (card == HarddiskInterfaceCard::GetSnapshotCardName())
{ {
type = CT_GenericHDD; type = CT_GenericHDD;
GetCardMgr().Insert(slot, type); GetCardMgr().Insert(slot, type);
bRes = HD_LoadSnapshot(yamlLoadHelper, slot, cardVersion, g_strSaveStatePath); bRes = dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(slot)).LoadSnapshot(yamlLoadHelper, slot, cardVersion, g_strSaveStatePath);
} }
else if (card == tfe_GetSnapshotCardName()) else if (card == tfe_GetSnapshotCardName())
{ {
@ -496,9 +499,6 @@ static void Snapshot_LoadState_v2(void)
MemReset(); // Also calls CpuInitialize() MemReset(); // Also calls CpuInitialize()
GetPravets().Reset(); GetPravets().Reset();
HD_Reset();
HD_SetEnabled(false); // Set disabled & also removes card from slot 7
KeybReset(); KeybReset();
GetVideo().VideoResetState(); GetVideo().VideoResetState();
GetVideo().SetVideoRefreshRate(VR_60HZ); // Default to 60Hz as older save-states won't contain refresh rate GetVideo().SetVideoRefreshRate(VR_60HZ); // Default to 60Hz as older save-states won't contain refresh rate
@ -574,9 +574,6 @@ void Snapshot_LoadState()
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
// todo:
// . Uthernet card
void Snapshot_SaveState(void) void Snapshot_SaveState(void)
{ {
try try
@ -646,7 +643,7 @@ void Snapshot_SaveState(void)
dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(SLOT6)).SaveSnapshot(yamlSaveHelper); dynamic_cast<Disk2InterfaceCard&>(GetCardMgr().GetRef(SLOT6)).SaveSnapshot(yamlSaveHelper);
if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD) if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
HD_SaveSnapshot(yamlSaveHelper); dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).SaveSnapshot(yamlSaveHelper);
for (UINT slot = SLOT3; slot <= SLOT5; slot++) for (UINT slot = SLOT3; slot <= SLOT5; slot++)
{ {

View file

@ -267,11 +267,6 @@ void LoadConfiguration(void)
tfe_init(true); tfe_init(true);
} }
} }
else if (slot == SLOT7)
{
if ((SS_CARDTYPE)dwTmp == CT_GenericHDD) // TODO: move this to when HarddiskInterfaceCard object is instantiated
HD_SetEnabled(true, false);
}
} }
else // legacy (AppleWin 1.30.3 or earlier) else // legacy (AppleWin 1.30.3 or earlier)
{ {
@ -296,7 +291,7 @@ void LoadConfiguration(void)
else if (slot == SLOT5 && REGLOAD(TEXT(REGVALUE_SLOT5), &dwTmp)) else if (slot == SLOT5 && REGLOAD(TEXT(REGVALUE_SLOT5), &dwTmp))
GetCardMgr().Insert(SLOT5, (SS_CARDTYPE)dwTmp); GetCardMgr().Insert(SLOT5, (SS_CARDTYPE)dwTmp);
else if (slot == SLOT7 && REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp)) else if (slot == SLOT7 && REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp))
HD_SetEnabled(dwTmp ? true : false); GetCardMgr().Insert(SLOT7, (SS_CARDTYPE)dwTmp);
} }
} }
@ -314,8 +309,11 @@ void LoadConfiguration(void)
GetCurrentDirectory(sizeof(szFilename), szFilename); GetCurrentDirectory(sizeof(szFilename), szFilename);
SetCurrentImageDir(szFilename); SetCurrentImageDir(szFilename);
HD_LoadLastDiskImage(HARDDISK_1); if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
HD_LoadLastDiskImage(HARDDISK_2); {
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).LoadLastDiskImage(HARDDISK_1);
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).LoadLastDiskImage(HARDDISK_2);
}
// //
@ -401,16 +399,20 @@ static bool DoDiskInsert(const UINT slot, const int nDrive, LPCSTR szFileName)
static bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName) static bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName)
{ {
_ASSERT(GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD);
if (GetCardMgr().QuerySlot(SLOT7) != CT_GenericHDD)
return false;
if (szFileName[0] == '\0') if (szFileName[0] == '\0')
{ {
HD_Unplug(nDrive); dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Unplug(nDrive);
return true; return true;
} }
std::string strPathName = GetFullPath(szFileName); std::string strPathName = GetFullPath(szFileName);
if (strPathName.empty()) return false; if (strPathName.empty()) return false;
BOOL bRes = HD_Insert(nDrive, strPathName); BOOL bRes = dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Insert(nDrive, strPathName);
bool res = (bRes == TRUE); bool res = (bRes == TRUE);
if (res) if (res)
SetCurrentDir(strPathName); SetCurrentDir(strPathName);
@ -454,7 +456,8 @@ void InsertHardDisks(LPCSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot)
if (!szImageName_harddisk[HARDDISK_1] && !szImageName_harddisk[HARDDISK_2]) if (!szImageName_harddisk[HARDDISK_1] && !szImageName_harddisk[HARDDISK_2])
return; return;
HD_SetEnabled(true); // Enable the Harddisk controller card if (GetCardMgr().QuerySlot(SLOT7) != CT_GenericHDD)
GetCardMgr().Insert(SLOT7, CT_GenericHDD); // Enable the Harddisk controller card
bool bRes = true; bool bRes = true;
@ -476,11 +479,6 @@ void InsertHardDisks(LPCSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot)
GetFrame().FrameMessageBox("Failed to insert harddisk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK); GetFrame().FrameMessageBox("Failed to insert harddisk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
} }
void UnplugHardDiskControllerCard(void)
{
HD_SetEnabled(false);
}
void GetAppleWindowTitle() void GetAppleWindowTitle()
{ {
switch (g_Apple2Type) switch (g_Apple2Type)
@ -541,7 +539,8 @@ void GetAppleWindowTitle()
void ResetMachineState() void ResetMachineState()
{ {
GetCardMgr().GetDisk2CardMgr().Reset(true); GetCardMgr().GetDisk2CardMgr().Reset(true);
HD_Reset(); if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Reset(true);
g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset() MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset()
@ -595,7 +594,8 @@ void CtrlReset()
GetPravets().Reset(); GetPravets().Reset();
GetCardMgr().GetDisk2CardMgr().Reset(); GetCardMgr().GetDisk2CardMgr().Reset();
HD_Reset(); if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Reset(true);
KeybReset(); KeybReset();
if (GetCardMgr().IsSSCInstalled()) if (GetCardMgr().IsSSCInstalled())
GetCardMgr().GetSSC()->CommReset(); GetCardMgr().GetSSC()->CommReset();

View file

@ -7,7 +7,6 @@
void LoadConfiguration(); void LoadConfiguration();
void InsertFloppyDisks(const UINT slot, LPCSTR szImageName_drive[NUM_DRIVES], bool driveConnected[NUM_DRIVES], bool& bBoot); void InsertFloppyDisks(const UINT slot, LPCSTR szImageName_drive[NUM_DRIVES], bool driveConnected[NUM_DRIVES], bool& bBoot);
void InsertHardDisks(LPCSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot); void InsertHardDisks(LPCSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot);
void UnplugHardDiskControllerCard(void);
void GetAppleWindowTitle(); void GetAppleWindowTitle();
void CtrlReset(); void CtrlReset();

View file

@ -782,7 +782,7 @@ static void RepeatInitialization(void)
if (g_cmdLine.bSlotEmpty[SLOT7]) if (g_cmdLine.bSlotEmpty[SLOT7])
{ {
HD_SetEnabled(false); // Disable HDD controller, and persist this to Registry/conf.ini (consistent with other '-sn empty' cmds) GetCardMgr().Remove(SLOT7); // Disable HDD controller, and persist this to Registry/conf.ini (consistent with other '-sn empty' cmds)
Snapshot_UpdatePath(); // If save-state's filename is a harddisk, and the floppy is in the same path, then the filename won't be updated Snapshot_UpdatePath(); // If save-state's filename is a harddisk, and the floppy is in the same path, then the filename won't be updated
} }
} }
@ -821,7 +821,8 @@ static void RepeatInitialization(void)
// Need to test if it's safe to call ResetMachineState(). In the meantime, just call Disk2Card's Reset(): // Need to test if it's safe to call ResetMachineState(). In the meantime, just call Disk2Card's Reset():
GetCardMgr().GetDisk2CardMgr().Reset(true); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor GetCardMgr().GetDisk2CardMgr().Reset(true); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor
LogFileOutput("Main: DiskReset()\n"); LogFileOutput("Main: DiskReset()\n");
HD_Reset(); // GH#515 if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Reset(true); // GH#515
LogFileOutput("Main: HDDReset()\n"); LogFileOutput("Main: HDDReset()\n");
if (!g_bSysClkOK) if (!g_bSysClkOK)
@ -916,7 +917,7 @@ static void Shutdown(void)
CloseHandle(g_hCustomRom); CloseHandle(g_hCustomRom);
if (g_cmdLine.bSlot7EmptyOnExit) if (g_cmdLine.bSlot7EmptyOnExit)
UnplugHardDiskControllerCard(); GetCardMgr().Remove(SLOT7);
} }
IPropertySheet& GetPropertySheet(void) IPropertySheet& GetPropertySheet(void)

View file

@ -741,11 +741,9 @@ void Win32Frame::DrawStatusArea (HDC passdc, int drawflags)
int y = buttony+BUTTONS*BUTTONCY+1; int y = buttony+BUTTONS*BUTTONCY+1;
const bool bCaps = KeybGetCapsStatus(); const bool bCaps = KeybGetCapsStatus();
#if HD_LED
// 1.19.0.0 Hard Disk Status/Indicator Light
Disk_Status_e eHardDriveStatus = DISK_STATUS_OFF; Disk_Status_e eHardDriveStatus = DISK_STATUS_OFF;
HD_GetLightStatus(&eHardDriveStatus); if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
#endif dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).GetLightStatus(&eHardDriveStatus);
if (g_bIsFullScreen) if (g_bIsFullScreen)
{ {
@ -764,11 +762,9 @@ void Win32Frame::DrawStatusArea (HDC passdc, int drawflags)
FrameDrawDiskStatus(dc); FrameDrawDiskStatus(dc);
} }
#if HD_LED
SetTextAlign(dc, TA_RIGHT | TA_TOP); SetTextAlign(dc, TA_RIGHT | TA_TOP);
SetTextColor(dc, g_aDiskFullScreenColorsLED[ eHardDriveStatus ] ); SetTextColor(dc, g_aDiskFullScreenColorsLED[ eHardDriveStatus ] );
TextOut(dc,x+23,y+2,TEXT("H"),1); TextOut(dc,x+23,y+2,TEXT("H"),1);
#endif
if (!IS_APPLE2) if (!IS_APPLE2)
{ {
@ -849,11 +845,8 @@ void Win32Frame::DrawStatusArea (HDC passdc, int drawflags)
case A2TYPE_PRAVETS8A : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsBitmapP8 [bCaps != 0]); break; case A2TYPE_PRAVETS8A : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsBitmapP8 [bCaps != 0]); break;
} }
#if HD_LED
// 1.19.0.0 Hard Disk Status/Indicator Light
RECT rDiskLed = {0,0,8,8}; RECT rDiskLed = {0,0,8,8};
DrawBitmapRect(dc,x+12,y+18,&rDiskLed,g_hDiskWindowedLED[eHardDriveStatus]); DrawBitmapRect(dc,x+12,y+18,&rDiskLed,g_hDiskWindowedLED[eHardDriveStatus]);
#endif
} }
} }
@ -968,7 +961,8 @@ LRESULT Win32Frame::WndProc(
DebugDestroy(); DebugDestroy();
if (!g_bRestart) { if (!g_bRestart) {
GetCardMgr().GetDisk2CardMgr().Destroy(); GetCardMgr().GetDisk2CardMgr().Destroy();
HD_Destroy(); if (GetCardMgr().QuerySlot(SLOT7) == CT_GenericHDD)
dynamic_cast<HarddiskInterfaceCard&>(GetCardMgr().GetRef(SLOT7)).Destroy();
} }
PrintDestroy(); PrintDestroy();
if (GetCardMgr().IsSSCInstalled()) if (GetCardMgr().IsSSCInstalled())