diff --git a/ApplewinExpress9.00.vcproj b/ApplewinExpress9.00.vcproj
index 55966eea..3973237d 100644
--- a/ApplewinExpress9.00.vcproj
+++ b/ApplewinExpress9.00.vcproj
@@ -755,11 +755,19 @@
>
+
+
+
+
diff --git a/source/6821.h b/source/6821.h
index fb92378a..5b269581 100644
--- a/source/6821.h
+++ b/source/6821.h
@@ -32,6 +32,21 @@ typedef struct
mem_write_handler func;
} STWriteHandler;
+struct mc6821_s {
+ /* MC6821 register. */
+ BYTE pra;
+ BYTE ddra;
+ BYTE cra;
+ BYTE prb;
+ BYTE ddrb;
+ BYTE crb;
+
+ /* Drive structure */
+// struct drive_s *drive;
+};
+typedef struct mc6821_s mc6821_t;
+
+
class C6821
{
public:
@@ -64,6 +79,18 @@ public:
m_stOutB.objTo = objTo;
m_stOutB.func = func;
}
+ void Get6821(mc6821_t& r6821, BYTE& byIA, BYTE& byIB)
+ {
+ r6821 = mc6821[0];
+ byIA = m_byIA;
+ byIB = m_byIB;
+ }
+ void Set6821(const mc6821_t& r6821, const BYTE byIA, const BYTE byIB)
+ {
+ mc6821[0] = r6821;
+ m_byIA = byIA;
+ m_byIB = byIB;
+ }
// AppleWin:TC END
private:
@@ -75,20 +102,6 @@ private:
//struct drive_s;
- struct mc6821_s {
- /* MC6821 register. */
- BYTE pra;
- BYTE ddra;
- BYTE cra;
- BYTE prb;
- BYTE ddrb;
- BYTE crb;
-
- /* Drive structure */
- // struct drive_s *drive;
- };
- typedef struct mc6821_s mc6821_t;
-
//struct drive_context_s;
void mc6821_init(/*struct drive_context_s *drv*/);
void mc6821_reset(/*struct drive_context_s *drv*/);
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index a4d5ee05..8a379095 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -469,12 +469,6 @@ void LoadConfiguration(void)
if(REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp))
HD_SetEnabled(dwTmp ? true : false);
- char szHDVPathname[MAX_PATH] = {0};
- if(RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_LAST_HARDDISK_1), 1, szHDVPathname, sizeof(szHDVPathname)))
- HD_InsertDisk(HARDDISK_1, szHDVPathname);
- if(RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_LAST_HARDDISK_2), 1, szHDVPathname, sizeof(szHDVPathname)))
- HD_InsertDisk(HARDDISK_2, szHDVPathname);
-
if(REGLOAD(TEXT(REGVALUE_PDL_XTRIM), &dwTmp))
JoySetTrim((short)dwTmp, true);
if(REGLOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp))
@@ -509,6 +503,16 @@ void LoadConfiguration(void)
char szFilename[MAX_PATH] = {0};
+ RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, szFilename, MAX_PATH);
+ if (szFilename[0] == 0)
+ GetCurrentDirectory(sizeof(szFilename), szFilename);
+ SetCurrentImageDir(szFilename);
+
+ HD_LoadLastDiskImage(HARDDISK_1);
+ HD_LoadLastDiskImage(HARDDISK_2);
+
+ //
+
// Current/Starting Dir is the "root" of where the user keeps his disk images
RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_START_DIR), 1, szFilename, MAX_PATH);
if (szFilename[0] == 0)
diff --git a/source/Applewin.h b/source/Applewin.h
index 172bd308..e55c7c2a 100644
--- a/source/Applewin.h
+++ b/source/Applewin.h
@@ -1,6 +1,6 @@
#pragma once
-#include "Structs.h"
+#include "SaveState_Structs_common.h"
#include "Common.h"
void SetCurrentCLK6502();
diff --git a/source/CPU.cpp b/source/CPU.cpp
index fadaecbb..62a98d37 100644
--- a/source/CPU.cpp
+++ b/source/CPU.cpp
@@ -102,6 +102,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Z80VICE\z80mem.h"
#include "Debugger\Debug.h"
+#include "SaveState_Structs_v2.h"
#define AF_SIGN 0x80
@@ -642,30 +643,46 @@ void CpuReset()
//===========================================================================
-DWORD CpuGetSnapshot(SS_CPU6502* pSS)
+void CpuSetSnapshot_v1(const BYTE A, const BYTE X, const BYTE Y, const BYTE P, const BYTE SP, const USHORT PC, const unsigned __int64 CumulativeCycles)
{
- pSS->A = regs.a;
- pSS->X = regs.x;
- pSS->Y = regs.y;
- pSS->P = regs.ps | AF_RESERVED | AF_BREAK;
- pSS->S = (BYTE) (regs.sp & 0xff);
- pSS->PC = regs.pc;
- pSS->g_nCumulativeCycles = g_nCumulativeCycles;
+ regs.a = A;
+ regs.x = X;
+ regs.y = Y;
+ regs.ps = P | (AF_RESERVED | AF_BREAK);
+ regs.sp = ((USHORT)SP) | 0x100;
+ regs.pc = PC;
- return 0;
-}
-
-DWORD CpuSetSnapshot(SS_CPU6502* pSS)
-{
- regs.a = pSS->A;
- regs.x = pSS->X;
- regs.y = pSS->Y;
- regs.ps = pSS->P | AF_RESERVED | AF_BREAK;
- regs.sp = (USHORT)pSS->S | 0x100;
- regs.pc = pSS->PC;
CpuIrqReset();
CpuNmiReset();
- g_nCumulativeCycles = pSS->g_nCumulativeCycles;
-
- return 0;
+ g_nCumulativeCycles = CumulativeCycles;
+}
+
+//
+
+void CpuGetSnapshot(SS_CPU6502_v2& CPU)
+{
+ regs.ps |= (AF_RESERVED | AF_BREAK);
+
+ CPU.A = regs.a;
+ CPU.X = regs.x;
+ CPU.Y = regs.y;
+ CPU.P = regs.ps;
+ CPU.S = (BYTE) regs.sp;
+ CPU.PC = regs.pc;
+
+ CPU.CumulativeCycles = g_nCumulativeCycles;
+}
+
+void CpuSetSnapshot(const SS_CPU6502_v2& CPU)
+{
+ regs.a = CPU.A;
+ regs.x = CPU.X;
+ regs.y = CPU.Y;
+ regs.ps = CPU.P | (AF_RESERVED | AF_BREAK);
+ regs.sp = ((USHORT)CPU.S) | 0x100;
+ regs.pc = CPU.PC;
+
+ CpuIrqReset();
+ CpuNmiReset();
+ g_nCumulativeCycles = CPU.CumulativeCycles;
}
diff --git a/source/CPU.h b/source/CPU.h
index 58c5d886..7b60cd7e 100644
--- a/source/CPU.h
+++ b/source/CPU.h
@@ -1,6 +1,7 @@
#pragma once
-typedef struct _regsrec {
+struct regsrec
+{
BYTE a; // accumulator
BYTE x; // index X
BYTE y; // index Y
@@ -8,7 +9,7 @@ typedef struct _regsrec {
WORD pc; // program counter
WORD sp; // stack pointer
BYTE bJammed; // CPU has crashed (NMOS 6502 only)
-} regsrec, *regsptr;
+};
extern regsrec regs;
extern unsigned __int64 g_nCumulativeCycles;
@@ -26,8 +27,9 @@ void CpuNmiReset();
void CpuNmiAssert(eIRQSRC Device);
void CpuNmiDeassert(eIRQSRC Device);
void CpuReset ();
-DWORD CpuGetSnapshot(SS_CPU6502* pSS);
-DWORD CpuSetSnapshot(SS_CPU6502* pSS);
+void CpuSetSnapshot_v1(const BYTE A, const BYTE X, const BYTE Y, const BYTE P, const BYTE SP, const USHORT PC, const unsigned __int64 CumulativeCycles);
+void CpuGetSnapshot(struct SS_CPU6502_v2& CPU);
+void CpuSetSnapshot(const struct SS_CPU6502_v2& CPU);
BYTE CpuRead(USHORT addr, ULONG uExecutedCycles);
void CpuWrite(USHORT addr, BYTE a, ULONG uExecutedCycles);
diff --git a/source/Common.h b/source/Common.h
index dc549637..b2f9ee22 100644
--- a/source/Common.h
+++ b/source/Common.h
@@ -164,7 +164,7 @@ enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC, IS_MOUSE};
#define IS_APPLE2C (g_Apple2Type & APPLE2C_MASK)
#define IS_CLONE() (g_Apple2Type & APPLECLONE_MASK)
-// NB. These get persisted to the Registry, so don't change the values for these enums!
+// NB. These get persisted to the Registry & save-state file, so don't change the values for these enums!
enum eApple2Type {
A2TYPE_APPLE2=0,
A2TYPE_APPLE2PLUS,
diff --git a/source/Configuration/IPropertySheet.h b/source/Configuration/IPropertySheet.h
index c25b2ce8..b0312009 100644
--- a/source/Configuration/IPropertySheet.h
+++ b/source/Configuration/IPropertySheet.h
@@ -1,10 +1,13 @@
#pragma once
+class CConfigNeedingRestart;
+
__interface IPropertySheet
{
void Init(void);
DWORD GetVolumeMax(void); // TODO:TC: Move out of here
bool SaveStateSelectImage(HWND hWindow, bool bSave); // TODO:TC: Move out of here
+ void ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld);
UINT GetScrollLockToggle(void);
void SetScrollLockToggle(UINT uValue);
diff --git a/source/Configuration/PageAdvanced.cpp b/source/Configuration/PageAdvanced.cpp
index de469041..c50cf5c7 100644
--- a/source/Configuration/PageAdvanced.cpp
+++ b/source/Configuration/PageAdvanced.cpp
@@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
-#include "..\Structs.h"
#include "..\Common.h"
#include "..\ParallelPrinter.h"
diff --git a/source/Configuration/PageInput.cpp b/source/Configuration/PageInput.cpp
index 9326afee..940b9978 100644
--- a/source/Configuration/PageInput.cpp
+++ b/source/Configuration/PageInput.cpp
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
-#include "..\Structs.h"
+#include "..\SaveState_Structs_common.h"
#include "..\Common.h"
#include "..\Keyboard.h"
diff --git a/source/Configuration/PageSound.cpp b/source/Configuration/PageSound.cpp
index 92e73002..6f459dd7 100644
--- a/source/Configuration/PageSound.cpp
+++ b/source/Configuration/PageSound.cpp
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
-#include "..\Structs.h"
+#include "..\SaveState_Structs_common.h"
#include "..\Common.h"
#include "..\Mockingboard.h"
diff --git a/source/Configuration/PropertySheet.h b/source/Configuration/PropertySheet.h
index ba1dc6bb..82ae0edd 100644
--- a/source/Configuration/PropertySheet.h
+++ b/source/Configuration/PropertySheet.h
@@ -24,6 +24,10 @@ public:
virtual void Init(void);
virtual DWORD GetVolumeMax(void); // TODO:TC: Move out of here
virtual bool SaveStateSelectImage(HWND hWindow, bool bSave); // TODO:TC: Move out of here
+ void ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld)
+ {
+ m_PropertySheetHelper.ApplyNewConfig(ConfigNew, ConfigOld);
+ }
virtual UINT GetScrollLockToggle(void){ return m_PageInput.GetScrollLockToggle(); }
virtual void SetScrollLockToggle(UINT uValue){ m_PageInput.SetScrollLockToggle(uValue); }
diff --git a/source/Configuration/PropertySheetHelper.cpp b/source/Configuration/PropertySheetHelper.cpp
index b135b059..c9e93e31 100644
--- a/source/Configuration/PropertySheetHelper.cpp
+++ b/source/Configuration/PropertySheetHelper.cpp
@@ -319,35 +319,40 @@ bool CPropertySheetHelper::CheckChangesForRestart(HWND hWnd)
return true; // OK
}
-#define CONFIG_CHANGED(var) \
- (m_ConfigOld.var != m_ConfigNew.var)
+#define CONFIG_CHANGED_LOCAL(var) \
+ (ConfigOld.var != ConfigNew.var)
// Apply changes to Registry
+void CPropertySheetHelper::ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld)
+{
+ if (CONFIG_CHANGED_LOCAL(m_Apple2Type))
+ {
+ SaveComputerType(ConfigNew.m_Apple2Type);
+ }
+
+ if (CONFIG_CHANGED_LOCAL(m_Slot[4]))
+ SetSlot4(ConfigNew.m_Slot[4]);
+
+ if (CONFIG_CHANGED_LOCAL(m_Slot[5]))
+ SetSlot5(ConfigNew.m_Slot[5]);
+
+ if (CONFIG_CHANGED_LOCAL(m_bEnhanceDisk))
+ REGSAVE(TEXT(REGVALUE_ENHANCE_DISK_SPEED), ConfigNew.m_bEnhanceDisk);
+
+ if (CONFIG_CHANGED_LOCAL(m_bEnableHDD))
+ {
+ REGSAVE(TEXT(REGVALUE_HDD_ENABLED), ConfigNew.m_bEnableHDD ? 1 : 0);
+ }
+
+ if (CONFIG_CHANGED_LOCAL(m_bEnableTheFreezesF8Rom))
+ {
+ REGSAVE(TEXT(REGVALUE_THE_FREEZES_F8_ROM), ConfigNew.m_bEnableTheFreezesF8Rom);
+ }
+}
+
void CPropertySheetHelper::ApplyNewConfig(void)
{
- if (CONFIG_CHANGED(m_Apple2Type))
- {
- SaveComputerType(m_ConfigNew.m_Apple2Type);
- }
-
- if (CONFIG_CHANGED(m_Slot[4]))
- SetSlot4(m_ConfigNew.m_Slot[4]);
-
- if (CONFIG_CHANGED(m_Slot[5]))
- SetSlot5(m_ConfigNew.m_Slot[5]);
-
- if (CONFIG_CHANGED(m_bEnhanceDisk))
- REGSAVE(TEXT(REGVALUE_ENHANCE_DISK_SPEED), m_ConfigNew.m_bEnhanceDisk);
-
- if (CONFIG_CHANGED(m_bEnableHDD))
- {
- REGSAVE(TEXT(REGVALUE_HDD_ENABLED), m_ConfigNew.m_bEnableHDD ? 1 : 0);
- }
-
- if (CONFIG_CHANGED(m_bEnableTheFreezesF8Rom))
- {
- REGSAVE(TEXT(REGVALUE_THE_FREEZES_F8_ROM), m_ConfigNew.m_bEnableTheFreezesF8Rom);
- }
+ ApplyNewConfig(m_ConfigNew, m_ConfigOld);
}
void CPropertySheetHelper::SaveCurrentConfig(void)
@@ -411,6 +416,9 @@ bool CPropertySheetHelper::IsOkToRestart(HWND hWnd)
return true;
}
+#define CONFIG_CHANGED(var) \
+ (m_ConfigOld.var != m_ConfigNew.var)
+
bool CPropertySheetHelper::HardwareConfigChanged(HWND hWnd)
{
std::string strMsg("The emulator needs to restart as the hardware configuration has changed:\n");
diff --git a/source/Configuration/PropertySheetHelper.h b/source/Configuration/PropertySheetHelper.h
index 74896cdb..42503688 100644
--- a/source/Configuration/PropertySheetHelper.h
+++ b/source/Configuration/PropertySheetHelper.h
@@ -37,6 +37,7 @@ public:
CConfigNeedingRestart& GetConfigNew(void) { return m_ConfigNew; }
bool IsConfigChanged(void) { return m_ConfigNew != m_ConfigOld; }
void SetDoBenchmark(void) { m_bDoBenchmark = true; }
+ void ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld);
private:
bool IsOkToSaveLoadState(HWND hWnd, const bool bConfigChanged);
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index cde48207..78a2e92d 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -4285,7 +4285,7 @@ Update_t CmdMemoryLoad (int nArgs)
if (bBankSpecified)
{
- MemUpdatePaging(1);
+ MemUpdatePaging(TRUE);
}
else
{
diff --git a/source/Debugger/Debug.h b/source/Debugger/Debug.h
index 26c3ecec..5c69c604 100644
--- a/source/Debugger/Debug.h
+++ b/source/Debugger/Debug.h
@@ -1,6 +1,6 @@
#pragma once
-#include "..\Structs.h"
+#include "..\SaveState_Structs_v1.h" // For SS_CARD_MOCKINGBOARD
#include "..\Common.h"
#include "Debugger_Types.h"
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 6e4c98dd..47270730 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -2437,7 +2437,7 @@ void DrawMemory ( int line, int iMemDump )
SS_CARD_MOCKINGBOARD SS_MB;
if ((eDevice == DEV_SY6522) || (eDevice == DEV_AY8910))
- MB_GetSnapshot(&SS_MB, 4+(nAddr>>1)); // Slot4 or Slot5
+ MB_GetSnapshot_v1(&SS_MB, 4+(nAddr>>1)); // Slot4 or Slot5
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
diff --git a/source/Disk.cpp b/source/Disk.cpp
index 211ca632..84e338e4 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -28,6 +28,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
+#include "SaveState_Structs_v1.h"
+
#include "AppleWin.h"
#include "Disk.h"
#include "DiskImage.h"
@@ -61,21 +63,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Private ________________________________________________________________________________________
- const int MAX_DISK_IMAGE_NAME = 15;
- const int MAX_DISK_FULL_NAME = 127;
-
struct Disk_t
{
TCHAR imagename[ MAX_DISK_IMAGE_NAME + 1 ]; // (ie. no extension)
TCHAR fullname [ MAX_DISK_FULL_NAME + 1 ]; // or : This is persisted to the snapshot file
- std::string strDiskPathFilename;
- std::string strFilenameInZip; // 0x00 or
+ std::string strFilenameInZip; // "" or
HIMAGE imagehandle; // Init'd by DiskInsert() -> ImageOpen()
+ bool bWriteProtected;
+ //
int track;
LPBYTE trackimage;
int phase;
int byte;
- bool bWriteProtected;
BOOL trackimagedata;
BOOL trackimagedirty;
DWORD spinning;
@@ -86,14 +85,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
{
memcpy(imagename, other.imagename, sizeof(imagename));
memcpy(fullname , other.fullname, sizeof(fullname));
- strDiskPathFilename = other.strDiskPathFilename;
strFilenameInZip = other.strFilenameInZip;
imagehandle = other.imagehandle;
+ bWriteProtected = other.bWriteProtected;
track = other.track;
trackimage = other.trackimage;
phase = other.phase;
byte = other.byte;
- bWriteProtected = other.bWriteProtected;
trackimagedata = other.trackimagedata;
trackimagedirty = other.trackimagedirty;
spinning = other.spinning;
@@ -109,8 +107,9 @@ static Disk_t g_aFloppyDisk[NUM_DRIVES];
static BYTE floppylatch = 0;
static BOOL floppymotoron = 0;
static BOOL floppywritemode = 0;
-static WORD phases; // state bits for stepper magnet phases 0 - 3
+static WORD phases = 0; // state bits for stepper magnet phases 0 - 3
static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
+static UINT g_uSlot = 0;
static void CheckSpinning();
static Disk_Status_e GetDriveLightStatus( const int iDrive );
@@ -127,14 +126,9 @@ int DiskGetCurrentPhase(void) { return g_aFloppyDisk[currdrive].phase; }
int DiskGetCurrentOffset(void) { return g_aFloppyDisk[currdrive].byte; }
int DiskGetTrack( int drive ) { return g_aFloppyDisk[ drive ].track; }
-const std::string& DiskGetDiskPathFilename(const int iDrive)
+const char* DiskGetDiskPathFilename(const int iDrive)
{
- return g_aFloppyDisk[iDrive].strDiskPathFilename;
-}
-
-static void DiskSetDiskPathFilename(const int iDrive, const std::string strPathName)
-{
- g_aFloppyDisk[iDrive].strDiskPathFilename = strPathName;
+ return g_aFloppyDisk[iDrive].fullname;
}
char* DiskGetCurrentState(void)
@@ -164,7 +158,7 @@ char* DiskGetCurrentState(void)
//===========================================================================
- void Disk_LoadLastDiskImage(const int iDrive)
+void Disk_LoadLastDiskImage(const int iDrive)
{
_ASSERT(iDrive == DRIVE_1 || iDrive == DRIVE_2);
@@ -175,22 +169,15 @@ char* DiskGetCurrentState(void)
? REGVALUE_PREF_LAST_DISK_1
: REGVALUE_PREF_LAST_DISK_2;
- if (RegLoadString(TEXT(REG_PREFS),pRegKey,1,sFilePath,MAX_PATH))
+ if (RegLoadString(TEXT(REG_PREFS), pRegKey, 1, sFilePath, MAX_PATH))
{
sFilePath[ MAX_PATH ] = 0;
- DiskSetDiskPathFilename(iDrive, sFilePath);
-#if _DEBUG
-// MessageBox(g_hFrameWindow,pFileName,pRegKey,MB_OK);
-#endif
-
- // _tcscat(imagefilename,TEXT("MASTER.DSK")); // TODO: Should remember last disk by user
g_bSaveDiskImage = false;
// Pass in ptr to local copy of filepath, since RemoveDisk() sets DiskPathFilename = ""
DiskInsert(iDrive, sFilePath, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
g_bSaveDiskImage = true;
}
- //else MessageBox(g_hFrameWindow,"Reg Key/Value not found",pRegKey,MB_OK);
}
//===========================================================================
@@ -202,7 +189,7 @@ void Disk_SaveLastDiskImage(const int iDrive)
if (!g_bSaveDiskImage)
return;
- const char *pFileName = DiskGetDiskPathFilename(iDrive).c_str();
+ const char *pFileName = g_aFloppyDisk[iDrive].fullname;
if (iDrive == DRIVE_1)
RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_DISK_1, TRUE, pFileName);
@@ -249,53 +236,6 @@ static Disk_Status_e GetDriveLightStatus(const int iDrive)
return DISK_STATUS_OFF;
}
-//===========================================================================
-
-static void GetImageTitle(LPCTSTR imagefilename, Disk_t* fptr)
-{
- TCHAR imagetitle[ MAX_DISK_FULL_NAME+1 ];
- LPCTSTR startpos = imagefilename;
-
- // imagetitle =
- if (_tcsrchr(startpos,TEXT('\\')))
- startpos = _tcsrchr(startpos,TEXT('\\'))+1;
-
- _tcsncpy(imagetitle,startpos,MAX_DISK_FULL_NAME);
- imagetitle[MAX_DISK_FULL_NAME] = 0;
-
- // if imagetitle contains a lowercase char, then found=1 (why?)
- BOOL found = 0;
- int loop = 0;
- while (imagetitle[loop] && !found)
- {
- if (IsCharLower(imagetitle[loop]))
- found = 1;
- else
- loop++;
- }
-
- if ((!found) && (loop > 2))
- CharLowerBuff(imagetitle+1,_tcslen(imagetitle+1));
-
- // fptr->fullname =
- _tcsncpy( fptr->fullname, imagetitle, MAX_DISK_FULL_NAME );
- fptr->fullname[ MAX_DISK_FULL_NAME ] = 0;
-
- if (imagetitle[0])
- {
- LPTSTR dot = imagetitle;
- if (_tcsrchr(dot,TEXT('.')))
- dot = _tcsrchr(dot,TEXT('.'));
- if (dot > imagetitle)
- *dot = 0;
- }
-
- // fptr->imagename = (ie. no extension)
- _tcsncpy( fptr->imagename, imagetitle, MAX_DISK_IMAGE_NAME );
- fptr->imagename[ MAX_DISK_IMAGE_NAME ] = 0;
-}
-
-
//===========================================================================
static bool IsDriveValid(const int iDrive)
@@ -370,7 +310,6 @@ static void RemoveDisk(const int iDrive)
memset( pFloppy->imagename, 0, MAX_DISK_IMAGE_NAME+1 );
memset( pFloppy->fullname , 0, MAX_DISK_FULL_NAME +1 );
pFloppy->strFilenameInZip = "";
- DiskSetDiskPathFilename(iDrive, "");
Disk_SaveLastDiskImage( iDrive );
Video_ResetScreenshotCounter( NULL );
@@ -558,6 +497,11 @@ LPCTSTR DiskGetFullDiskFilename(const int iDrive)
return DiskGetFullName(iDrive);
}
+static LPCTSTR DiskGetFullPathName(const int iDrive)
+{
+ return ImageGetPathname(g_aFloppyDisk[iDrive].imagehandle);
+}
+
// Return the imagename
// . Used by Drive Button's icons & Property Sheet Page (Save snapshot)
LPCTSTR DiskGetBaseName(const int iDrive)
@@ -611,10 +555,20 @@ ImageError_e DiskInsert(const int iDrive, LPCTSTR pszImageFilename, const bool b
else
fptr->bWriteProtected = bForceWriteProtected ? true : (dwAttributes & FILE_ATTRIBUTE_READONLY);
- // Check if image is being used by the other HDD, and unplug it in order to be swapped
- std::string otherDisk = DiskGetDiskPathFilename(!iDrive);
- if (!strcmp(otherDisk.c_str(), pszImageFilename)) {
- DiskEject(!iDrive);
+ // Check if image is being used by the other drive, and if so remove it in order so it can be swapped
+ {
+ const char* pszOtherPathname = DiskGetFullPathName(!iDrive);
+
+ char szCurrentPathname[MAX_PATH];
+ DWORD uNameLen = GetFullPathName(pszImageFilename, MAX_PATH, szCurrentPathname, NULL);
+ if (uNameLen == 0 || uNameLen >= MAX_PATH)
+ strcpy_s(szCurrentPathname, MAX_PATH, pszImageFilename);
+
+ if (!strcmp(pszOtherPathname, szCurrentPathname))
+ {
+ DiskEject(!iDrive);
+ FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
+ }
}
ImageError_e Error = ImageOpen(pszImageFilename,
@@ -637,19 +591,15 @@ ImageError_e DiskInsert(const int iDrive, LPCTSTR pszImageFilename, const bool b
if (Error == eIMAGE_ERROR_NONE)
{
- GetImageTitle(pszImageFilename, fptr);
-
- DiskSetDiskPathFilename(iDrive, pszImageFilename);
-
- //MessageBox( g_hFrameWindow, imagefilename, fptr->imagename, MB_OK );
- Video_ResetScreenshotCounter( fptr->imagename );
+ GetImageTitle(pszImageFilename, fptr->imagename, fptr->fullname);
+ Video_ResetScreenshotCounter(fptr->imagename);
}
else
{
- Video_ResetScreenshotCounter( NULL );
+ Video_ResetScreenshotCounter(NULL);
}
- Disk_SaveLastDiskImage( iDrive );
+ Disk_SaveLastDiskImage(iDrive);
return Error;
}
@@ -730,6 +680,13 @@ void DiskNotifyInvalidImage(const int iDrive, LPCTSTR pszImageFilename, const Im
pszImageFilename);
break;
+ case eIMAGE_ERROR_FAILED_TO_GET_PATHNAME:
+ wsprintf(
+ szBuffer,
+ TEXT("Unable to GetFullPathName() for the file: %s."),
+ pszImageFilename);
+ break;
+
default:
// IGNORE OTHER ERRORS SILENTLY
return;
@@ -852,7 +809,7 @@ void DiskReset(void)
//===========================================================================
-void DiskSelectImage(const int iDrive, LPSTR pszFilename)
+static bool DiskSelectImage(const int iDrive, LPCSTR pszFilename)
{
TCHAR directory[MAX_PATH] = TEXT("");
TCHAR filename[MAX_PATH] = TEXT("");
@@ -880,6 +837,8 @@ void DiskSelectImage(const int iDrive, LPSTR pszFilename)
ofn.Flags = OFN_PATHMUSTEXIST;
ofn.lpstrTitle = title;
+ bool bRes = false;
+
if (GetOpenFileName(&ofn))
{
if ((!ofn.nFileExtension) || !filename[ofn.nFileExtension])
@@ -888,16 +847,18 @@ void DiskSelectImage(const int iDrive, LPSTR pszFilename)
ImageError_e Error = DiskInsert(iDrive, filename, ofn.Flags & OFN_READONLY, IMAGE_CREATE);
if (Error == eIMAGE_ERROR_NONE)
{
- DiskSetDiskPathFilename(iDrive, filename);
filename[ofn.nFileOffset] = 0;
if (_tcsicmp(directory, filename))
RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_START_DIR), 1, filename);
+ bRes = true;
}
else
{
DiskNotifyInvalidImage(iDrive, filename, Error);
}
}
+
+ return bRes;
}
//===========================================================================
@@ -1040,6 +1001,8 @@ void DiskLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot)
// . In this case we can patch to compensate for an ADC or EOR checksum but not both
RegisterIoHandler(uSlot, Disk_IORead, Disk_IOWrite, NULL, NULL, NULL, NULL);
+
+ g_uSlot = uSlot;
}
//===========================================================================
@@ -1100,53 +1063,13 @@ static BYTE __stdcall Disk_IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON
//===========================================================================
-DWORD DiskGetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot)
+int DiskSetSnapshot_v1(const SS_CARD_DISK2* const pSS)
{
- pSS->Hdr.UnitHdr.dwLength = sizeof(SS_CARD_DISK2);
- pSS->Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,2);
+ if(pSS->Hdr.UnitHdr.hdr.v1.dwVersion > MAKE_VERSION(1,0,0,2))
+ return -1;
- pSS->Hdr.dwSlot = dwSlot;
- pSS->Hdr.dwType = CT_Disk2;
-
- pSS->phases = phases; // new in 1.0.0.2 disk snapshots
- pSS->currdrive = currdrive; // this was an int in 1.0.0.1 disk snapshots
- pSS->diskaccessed = diskaccessed;
- pSS->enhancedisk = enhancedisk;
- pSS->floppylatch = floppylatch;
- pSS->floppymotoron = floppymotoron;
- pSS->floppywritemode = floppywritemode;
-
- for(UINT i=0; iUnit[i].szFileName, g_aFloppyDisk[i].fullname);
- pSS->Unit[i].track = g_aFloppyDisk[i].track;
- pSS->Unit[i].phase = g_aFloppyDisk[i].phase;
- pSS->Unit[i].byte = g_aFloppyDisk[i].byte;
- pSS->Unit[i].writeprotected = g_aFloppyDisk[i].bWriteProtected ? TRUE : FALSE;
- pSS->Unit[i].trackimagedata = g_aFloppyDisk[i].trackimagedata;
- pSS->Unit[i].trackimagedirty = g_aFloppyDisk[i].trackimagedirty;
- pSS->Unit[i].spinning = g_aFloppyDisk[i].spinning;
- pSS->Unit[i].writelight = g_aFloppyDisk[i].writelight;
- pSS->Unit[i].nibbles = g_aFloppyDisk[i].nibbles;
-
- if(g_aFloppyDisk[i].trackimage)
- memcpy(pSS->Unit[i].nTrack, g_aFloppyDisk[i].trackimage, NIBBLES_PER_TRACK);
- else
- memset(pSS->Unit[i].nTrack, 0, NIBBLES_PER_TRACK);
- }
-
- return 0;
-}
-
-DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
-{
- if(pSS->Hdr.UnitHdr.dwVersion > MAKE_VERSION(1,0,0,2))
- {
- return -1;
- }
-
- phases = pSS->phases; // new in 1.0.0.2 disk snapshots
- currdrive = pSS->currdrive; // this was an int in 1.0.0.1 disk snapshots
+ phases = pSS->phases;
+ currdrive = pSS->currdrive;
diskaccessed = pSS->diskaccessed;
enhancedisk = pSS->enhancedisk;
floppylatch = pSS->floppylatch;
@@ -1183,7 +1106,6 @@ DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
// DiskInsert() sets up:
// . imagename
// . fullname
- // . strDiskPathFilename
// . writeprotected
}
@@ -1225,3 +1147,194 @@ DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
return 0;
}
+
+//===========================================================================
+
+struct DISK2_Unit_v2
+{
+ char szFileName[MAX_PATH];
+ UINT Track;
+ UINT Phase;
+ UINT Byte;
+ BOOL WriteProtected;
+ BOOL TrackImageData;
+ BOOL TrackImageDirty;
+ DWORD Spinning;
+ DWORD WriteLight;
+ UINT Nibbles;
+ BYTE TrackImage[NIBBLES_PER_TRACK];
+};
+
+struct SS_CARD_DISK2_v2
+{
+ SS_CARD_HDR Hdr;
+ DISK2_Unit_v2 Unit[2];
+ WORD Phases;
+ WORD CurrDrive;
+ BOOL DiskAccessed;
+ BOOL EnhanceDisk;
+ BYTE FloppyLatch;
+ BOOL FloppyMotorOn;
+ BOOL FloppyWriteMode;
+};
+
+void DiskGetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_DISK2_v2 CardDisk2;
+
+ SS_CARD_DISK2_v2* const pSS = &CardDisk2;
+
+ pSS->Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_DISK2);
+ pSS->Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ pSS->Hdr.UnitHdr.hdr.v2.Version = 1;
+
+ pSS->Hdr.Slot = g_uSlot;
+ pSS->Hdr.Type = CT_Disk2;
+
+ pSS->Phases = phases;
+ pSS->CurrDrive = currdrive;
+ pSS->DiskAccessed = diskaccessed;
+ pSS->EnhanceDisk = enhancedisk;
+ pSS->FloppyLatch = floppylatch;
+ pSS->FloppyMotorOn = floppymotoron;
+ pSS->FloppyWriteMode = floppywritemode;
+
+ for(UINT i=0; iUnit[i].szFileName, g_aFloppyDisk[i].fullname);
+ pSS->Unit[i].Track = g_aFloppyDisk[i].track;
+ pSS->Unit[i].Phase = g_aFloppyDisk[i].phase;
+ pSS->Unit[i].Byte = g_aFloppyDisk[i].byte;
+ pSS->Unit[i].WriteProtected = g_aFloppyDisk[i].bWriteProtected ? TRUE : FALSE;
+ pSS->Unit[i].TrackImageData = g_aFloppyDisk[i].trackimagedata;
+ pSS->Unit[i].TrackImageDirty = g_aFloppyDisk[i].trackimagedirty;
+ pSS->Unit[i].Spinning = g_aFloppyDisk[i].spinning;
+ pSS->Unit[i].WriteLight = g_aFloppyDisk[i].writelight;
+ pSS->Unit[i].Nibbles = g_aFloppyDisk[i].nibbles;
+
+ if(g_aFloppyDisk[i].trackimage)
+ memcpy(pSS->Unit[i].TrackImage, g_aFloppyDisk[i].trackimage, NIBBLES_PER_TRACK);
+ else
+ memset(pSS->Unit[i].TrackImage, 0, NIBBLES_PER_TRACK);
+ }
+
+ //
+
+ DWORD dwBytesWritten;
+ BOOL bRes = WriteFile( hFile,
+ &CardDisk2,
+ CardDisk2.Hdr.UnitHdr.hdr.v2.Length,
+ &dwBytesWritten,
+ NULL);
+
+ if(!bRes || (dwBytesWritten != CardDisk2.Hdr.UnitHdr.hdr.v2.Length))
+ {
+ //dwError = GetLastError();
+ throw std::string("Save error: Disk][");
+ }
+}
+
+void DiskSetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_DISK2_v2 CardDisk2;
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( hFile,
+ &CardDisk2,
+ sizeof(CardDisk2),
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != sizeof(CardDisk2))
+ throw std::string("Card: file corrupt");
+
+ if (CardDisk2.Hdr.Slot != 6) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (CardDisk2.Hdr.UnitHdr.hdr.v2.Version > 1)
+ throw std::string("Card: wrong version");
+
+ if (CardDisk2.Hdr.UnitHdr.hdr.v2.Length != sizeof(SS_CARD_DISK2_v2))
+ throw std::string("Card: unit size mismatch");
+
+ const SS_CARD_DISK2_v2* const pSS = &CardDisk2;
+
+ phases = pSS->Phases;
+ currdrive = pSS->CurrDrive;
+ diskaccessed = pSS->DiskAccessed;
+ enhancedisk = pSS->EnhanceDisk;
+ floppylatch = pSS->FloppyLatch;
+ floppymotoron = pSS->FloppyMotorOn;
+ floppywritemode = pSS->FloppyWriteMode;
+
+ // Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1
+ for(UINT i=0; iUnit[i].szFileName[0] == 0x00)
+ continue;
+
+ DWORD dwAttributes = GetFileAttributes(pSS->Unit[i].szFileName);
+ if(dwAttributes == INVALID_FILE_ATTRIBUTES)
+ {
+ // Get user to browse for file
+ bResSelectImage = DiskSelectImage(i, pSS->Unit[i].szFileName);
+
+ dwAttributes = GetFileAttributes(pSS->Unit[i].szFileName);
+ }
+
+ bool bImageError = (dwAttributes == INVALID_FILE_ATTRIBUTES);
+ if (!bImageError)
+ {
+ if(DiskInsert(i, pSS->Unit[i].szFileName, dwAttributes & FILE_ATTRIBUTE_READONLY, IMAGE_DONT_CREATE) != eIMAGE_ERROR_NONE)
+ bImageError = true;
+
+ // DiskInsert() sets up:
+ // . imagename
+ // . fullname
+ // . writeprotected
+ }
+
+ //
+
+// strcpy(g_aFloppyDisk[i].fullname, pSS->Unit[i].szFileName);
+ g_aFloppyDisk[i].track = pSS->Unit[i].Track;
+ g_aFloppyDisk[i].phase = pSS->Unit[i].Phase;
+ g_aFloppyDisk[i].byte = pSS->Unit[i].Byte;
+// g_aFloppyDisk[i].writeprotected = pSS->Unit[i].WriteProtected;
+ g_aFloppyDisk[i].trackimagedata = pSS->Unit[i].TrackImageData;
+ g_aFloppyDisk[i].trackimagedirty = pSS->Unit[i].TrackImageDirty;
+ g_aFloppyDisk[i].spinning = pSS->Unit[i].Spinning;
+ g_aFloppyDisk[i].writelight = pSS->Unit[i].WriteLight;
+ g_aFloppyDisk[i].nibbles = pSS->Unit[i].Nibbles;
+
+ //
+
+ if(!bImageError)
+ {
+ if((g_aFloppyDisk[i].trackimage == NULL) && g_aFloppyDisk[i].nibbles)
+ AllocTrack(i);
+
+ if(g_aFloppyDisk[i].trackimage == NULL)
+ bImageError = true;
+ else
+ memcpy(g_aFloppyDisk[i].trackimage, pSS->Unit[i].TrackImage, NIBBLES_PER_TRACK);
+ }
+
+ if(bImageError)
+ {
+ g_aFloppyDisk[i].trackimagedata = 0;
+ g_aFloppyDisk[i].trackimagedirty = 0;
+ g_aFloppyDisk[i].nibbles = 0;
+ }
+ }
+
+ FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
+}
diff --git a/source/Disk.h b/source/Disk.h
index 5c7daa02..e597ef51 100644
--- a/source/Disk.h
+++ b/source/Disk.h
@@ -40,7 +40,7 @@ const bool IMAGE_DONT_CREATE = false;
const bool IMAGE_CREATE = true;
extern BOOL enhancedisk;
-const std::string& DiskGetDiskPathFilename(const int iDrive);
+const char* DiskGetDiskPathFilename(const int iDrive);
void DiskInitialize(void); // DiskIIManagerStartup()
void DiskDestroy(void); // no, doesn't "destroy" the disk image. DiskIIManagerShutdown()
@@ -70,8 +70,10 @@ void DiskSelect(const int iDrive);
void DiskUpdatePosition(DWORD);
bool DiskDriveSwap(void);
void DiskLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot);
-DWORD DiskGetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot);
-DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot);
+
+int DiskSetSnapshot_v1(const struct SS_CARD_DISK2* const pSS);
+void DiskGetSnapshot(const HANDLE hFile);
+void DiskSetSnapshot(const HANDLE hFile);
void Disk_LoadLastDiskImage(const int iDrive);
void Disk_SaveLastDiskImage(const int iDrive);
diff --git a/source/DiskImage.cpp b/source/DiskImage.cpp
index 86992b97..001c5427 100644
--- a/source/DiskImage.cpp
+++ b/source/DiskImage.cpp
@@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
-#include "Structs.h"
#include "Common.h"
#include "DiskImage.h"
@@ -40,32 +39,37 @@ static CDiskImageHelper sg_DiskImageHelper;
// Pre: *pWriteProtected_ already set to file's r/w status - see DiskInsert()
ImageError_e ImageOpen( LPCTSTR pszImageFilename,
- HIMAGE* hDiskImage_,
- bool* pWriteProtected_,
+ HIMAGE* hDiskImage,
+ bool* pWriteProtected,
const bool bCreateIfNecessary,
- std::string& strFilenameInZip)
+ std::string& strFilenameInZip,
+ const bool bExpectFloppy /*=true*/)
{
- if (! (pszImageFilename && hDiskImage_ && pWriteProtected_ && sg_DiskImageHelper.GetWorkBuffer()))
+ if (! (pszImageFilename && hDiskImage && pWriteProtected && sg_DiskImageHelper.GetWorkBuffer()))
return eIMAGE_ERROR_BAD_POINTER;
// CREATE A RECORD FOR THE FILE, AND RETURN AN IMAGE HANDLE
- *hDiskImage_ = (HIMAGE) VirtualAlloc(NULL, sizeof(ImageInfo), MEM_COMMIT, PAGE_READWRITE);
- if (*hDiskImage_ == NULL)
+ *hDiskImage = (HIMAGE) VirtualAlloc(NULL, sizeof(ImageInfo), MEM_COMMIT, PAGE_READWRITE);
+ if (*hDiskImage == NULL)
return eIMAGE_ERROR_BAD_POINTER;
- ZeroMemory(*hDiskImage_, sizeof(ImageInfo));
- ImageInfo* pImageInfo = (ImageInfo*) *hDiskImage_;
- pImageInfo->bWriteProtected = *pWriteProtected_;
+ ZeroMemory(*hDiskImage, sizeof(ImageInfo));
+ ImageInfo* pImageInfo = (ImageInfo*) *hDiskImage;
+ pImageInfo->bWriteProtected = *pWriteProtected;
ImageError_e Err = sg_DiskImageHelper.Open(pszImageFilename, pImageInfo, bCreateIfNecessary, strFilenameInZip);
- if (pImageInfo->pImageType != NULL && Err == eIMAGE_ERROR_NONE && pImageInfo->pImageType->GetType() == eImageHDV)
- Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
-
if (Err != eIMAGE_ERROR_NONE)
{
- ImageClose(*hDiskImage_, true);
- *hDiskImage_ = (HIMAGE)0;
+ ImageClose(*hDiskImage, true);
+ *hDiskImage = (HIMAGE)0;
+ return Err;
+ }
+
+ if (pImageInfo->pImageType && pImageInfo->pImageType->GetType() == eImageHDV)
+ {
+ if (bExpectFloppy)
+ Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
return Err;
}
@@ -76,7 +80,7 @@ ImageError_e ImageOpen( LPCTSTR pszImageFilename,
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
pImageInfo->ValidTrack[uTrack] = (pImageInfo->uImageSize > 0) ? 1 : 0;
- *pWriteProtected_ = pImageInfo->bWriteProtected;
+ *pWriteProtected = pImageInfo->bWriteProtected;
return eIMAGE_ERROR_NONE;
}
@@ -185,6 +189,36 @@ void ImageWriteTrack( const HIMAGE hDiskImage,
//===========================================================================
+bool ImageReadBlock( const HIMAGE hDiskImage,
+ UINT nBlock,
+ LPBYTE pBlockBuffer)
+{
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+
+ bool bRes = false;
+ if (ptr->pImageType->AllowRW())
+ bRes = ptr->pImageType->Read(ptr, nBlock, pBlockBuffer);
+
+ return bRes;
+}
+
+//===========================================================================
+
+bool ImageWriteBlock( const HIMAGE hDiskImage,
+ UINT nBlock,
+ LPBYTE pBlockBuffer)
+{
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+
+ bool bRes = false;
+ if (ptr->pImageType->AllowRW() && !ptr->bWriteProtected)
+ bRes = ptr->pImageType->Write(ptr, nBlock, pBlockBuffer);
+
+ return bRes;
+}
+
+//===========================================================================
+
int ImageGetNumTracks(const HIMAGE hDiskImage)
{
ImageInfo* ptr = (ImageInfo*) hDiskImage;
@@ -202,3 +236,60 @@ bool ImageIsMultiFileZip(const HIMAGE hDiskImage)
ImageInfo* ptr = (ImageInfo*) hDiskImage;
return ptr ? (ptr->uNumEntriesInZip > 1) : false;
}
+
+const char* ImageGetPathname(const HIMAGE hDiskImage)
+{
+ static char* szEmpty = "";
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+ return ptr ? ptr->szFilename : szEmpty;
+}
+
+UINT ImageGetImageSize(const HIMAGE hDiskImage)
+{
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+ return ptr ? ptr->uImageSize : 0;
+}
+
+void GetImageTitle(LPCTSTR pPathname, TCHAR* pImageName, TCHAR* pFullName)
+{
+ TCHAR imagetitle[ MAX_DISK_FULL_NAME+1 ];
+ LPCTSTR startpos = pPathname;
+
+ // imagetitle =
+ if (_tcsrchr(startpos, TEXT('\\')))
+ startpos = _tcsrchr(startpos, TEXT('\\'))+1;
+
+ _tcsncpy(imagetitle, startpos, MAX_DISK_FULL_NAME);
+ imagetitle[MAX_DISK_FULL_NAME] = 0;
+
+ // if imagetitle contains a lowercase char, then found=1 (why?)
+ BOOL found = 0;
+ int loop = 0;
+ while (imagetitle[loop] && !found)
+ {
+ if (IsCharLower(imagetitle[loop]))
+ found = 1;
+ else
+ loop++;
+ }
+
+ if ((!found) && (loop > 2))
+ CharLowerBuff(imagetitle+1, _tcslen(imagetitle+1));
+
+ // pFullName =
+ _tcsncpy( pFullName, imagetitle, MAX_DISK_FULL_NAME );
+ pFullName[ MAX_DISK_FULL_NAME ] = 0;
+
+ if (imagetitle[0])
+ {
+ LPTSTR dot = imagetitle;
+ if (_tcsrchr(dot, TEXT('.')))
+ dot = _tcsrchr(dot, TEXT('.'));
+ if (dot > imagetitle)
+ *dot = 0;
+ }
+
+ // pImageName = (ie. no extension)
+ _tcsncpy( pImageName, imagetitle, MAX_DISK_IMAGE_NAME );
+ pImageName[ MAX_DISK_IMAGE_NAME ] = 0;
+}
diff --git a/source/DiskImage.h b/source/DiskImage.h
index b712399f..73b5bd4d 100644
--- a/source/DiskImage.h
+++ b/source/DiskImage.h
@@ -55,9 +55,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
eIMAGE_ERROR_UNABLE_TO_OPEN,
eIMAGE_ERROR_UNABLE_TO_OPEN_GZ,
eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP,
+ eIMAGE_ERROR_FAILED_TO_GET_PATHNAME,
};
-ImageError_e ImageOpen(LPCTSTR pszImageFilename, HIMAGE* hDiskImage_, bool* pWriteProtected_, const bool bCreateIfNecessary, std::string& strFilenameInZip);
+ const int MAX_DISK_IMAGE_NAME = 15;
+ const int MAX_DISK_FULL_NAME = 127;
+
+
+ImageError_e ImageOpen(LPCTSTR pszImageFilename, HIMAGE* hDiskImage, bool* pWriteProtected, const bool bCreateIfNecessary, std::string& strFilenameInZip, const bool bExpectFloppy=true);
void ImageClose(const HIMAGE hDiskImage, const bool bOpenError=false);
BOOL ImageBoot(const HIMAGE hDiskImage);
void ImageDestroy(void);
@@ -65,7 +70,13 @@ void ImageInitialize(void);
void ImageReadTrack(const HIMAGE hDiskImage, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles);
void ImageWriteTrack(const HIMAGE hDiskImage, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles);
+bool ImageReadBlock(const HIMAGE hDiskImage, UINT nBlock, LPBYTE pBlockBuffer);
+bool ImageWriteBlock(const HIMAGE hDiskImage, UINT nBlock, LPBYTE pBlockBuffer);
int ImageGetNumTracks(const HIMAGE hDiskImage);
bool ImageIsWriteProtected(const HIMAGE hDiskImage);
bool ImageIsMultiFileZip(const HIMAGE hDiskImage);
+const char* ImageGetPathname(const HIMAGE hDiskImage);
+UINT ImageGetImageSize(const HIMAGE hDiskImage);
+
+void GetImageTitle(LPCTSTR pPathname, TCHAR* pImageName, TCHAR* pFullName);
diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp
index 4eeef4a8..11d692bc 100644
--- a/source/DiskImageHelper.cpp
+++ b/source/DiskImageHelper.cpp
@@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "stdafx.h"
-#include "Structs.h"
#include "Common.h"
#include "zlib.h"
@@ -1435,7 +1434,9 @@ ImageError_e CImageHelperBase::Open( LPCTSTR pszImageFilename,
if (Err != eIMAGE_ERROR_NONE)
return Err;
- _tcsncpy(pImageInfo->szFilename, pszImageFilename, MAX_PATH);
+ DWORD uNameLen = GetFullPathName(pszImageFilename, MAX_PATH, pImageInfo->szFilename, NULL);
+ if (uNameLen == 0 || uNameLen >= MAX_PATH)
+ Err = eIMAGE_ERROR_FAILED_TO_GET_PATHNAME;
return eIMAGE_ERROR_NONE;
}
@@ -1453,9 +1454,10 @@ void CImageHelperBase::Close(ImageInfo* pImageInfo, const bool bDeleteFile)
if (bDeleteFile)
{
DeleteFile(pImageInfo->szFilename);
- pImageInfo->szFilename[0] = 0;
}
+ pImageInfo->szFilename[0] = 0;
+
delete [] pImageInfo->pImageBuffer;
pImageInfo->pImageBuffer = NULL;
}
diff --git a/source/Frame.cpp b/source/Frame.cpp
index e4960e9b..84cc1d45 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -563,7 +563,8 @@ static void DrawFrameWindow ()
else if (g_nAppMode == MODE_DEBUG)
DebugDisplay(1);
else
- // Win7: In fullscreen mode with 1 redraw, the the screen doesn't get redraw.
+ // Win7: In fullscreen mode with 1 redraw, the screen doesn't get redraw.
+ // TC: 07/01/2015: Tryed with MP's double-buffered DX full-screen code, but still the same.
VideoRedrawScreen(g_bIsFullScreen ? 2 : 1); // TC: 22/06/2014: Why 2 redraws in full-screen mode (32-bit only)? (8-bit doesn't need this nor does Win8, just Win7 or older OS's)
// DD Full-Screen Palette: BUGFIX: needs to come _after_ all drawing...
@@ -617,6 +618,9 @@ void FrameDrawDiskLEDS( HDC passdc )
//===========================================================================
void FrameDrawDiskStatus( HDC passdc )
{
+ if (mem == NULL)
+ return;
+
// We use the actual drive since probing from memory doesn't tell us anything we don't already know.
// DOS3.3 ProDOS
// Drive $B7EA $BE3D
@@ -1023,7 +1027,7 @@ LRESULT CALLBACK FrameWndProc (
if (!restart) {
DiskDestroy();
ImageDestroy();
- HD_Cleanup();
+ HD_Destroy();
}
PrintDestroy();
sg_SSC.CommDestroy();
diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp
index 3406140e..9934abd3 100644
--- a/source/Harddisk.cpp
+++ b/source/Harddisk.cpp
@@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
-Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
+Copyright (C) 2006-2015, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -114,22 +114,23 @@ Overview
struct HDD
{
// From Disk_t
- TCHAR imagename[16]; // Not used
- TCHAR fullname[128];
+ TCHAR imagename[ MAX_DISK_IMAGE_NAME + 1 ]; // (ie. no extension) [not used]
+ TCHAR fullname[ MAX_DISK_FULL_NAME + 1 ]; // or
+ std::string strFilenameInZip; // "" or [not used]
+ HIMAGE imagehandle; // Init'd by HD_Insert() -> ImageOpen()
+ bool bWriteProtected; // Needed for ImageOpen() [otherwise not used]
//
BYTE hd_error;
WORD hd_memblock;
UINT hd_diskblock;
WORD hd_buf_ptr;
BOOL hd_imageloaded;
- BYTE hd_buf[HD_BLOCK_SIZE+1]; // Why +1?
+ 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
-
- ImageInfo Info;
};
static bool g_bHD_RomLoaded = false;
@@ -143,114 +144,85 @@ static BYTE g_nHD_Command;
static HDD g_HardDisk[NUM_HARDDISKS] = {0};
+static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
static UINT g_uSlot = 7;
static CHardDiskImageHelper sg_HardDiskImageHelper;
//===========================================================================
+static void HD_SaveLastDiskImage(const int iDrive);
+
static void HD_CleanupDrive(const int iDrive)
{
- sg_HardDiskImageHelper.Close(&g_HardDisk[iDrive].Info, false);
-
- g_HardDisk[iDrive].hd_imageloaded = false;
- g_HardDisk[iDrive].imagename[0] = 0;
- g_HardDisk[iDrive].fullname[0] = 0;
- g_HardDisk[iDrive].Info.szFilename[0] = 0;
-}
-
-static ImageError_e ImageOpen( LPCTSTR pszImageFilename,
- const int iDrive,
- const bool bCreateIfNecessary,
- std::string& strFilenameInZip)
-{
- if (!pszImageFilename)
- return eIMAGE_ERROR_BAD_POINTER;
-
- HDD* pHDD = &g_HardDisk[iDrive];
- ImageInfo* pImageInfo = &pHDD->Info;
- pImageInfo->bWriteProtected = false;
-
- ImageError_e Err = sg_HardDiskImageHelper.Open(pszImageFilename, pImageInfo, bCreateIfNecessary, strFilenameInZip);
-
- if (Err != eIMAGE_ERROR_NONE)
+ if (g_HardDisk[iDrive].imagehandle)
{
- HD_CleanupDrive(iDrive);
- return Err;
+ ImageClose(g_HardDisk[iDrive].imagehandle);
+ g_HardDisk[iDrive].imagehandle = (HIMAGE)0;
}
- return eIMAGE_ERROR_NONE;
+ g_HardDisk[iDrive].hd_imageloaded = false;
+
+ g_HardDisk[iDrive].imagename[0] = 0;
+ g_HardDisk[iDrive].fullname[0] = 0;
+ g_HardDisk[iDrive].strFilenameInZip = "";
+
+ HD_SaveLastDiskImage(iDrive);
}
//-----------------------------------------------------------------------------
-static void GetImageTitle(LPCTSTR pszImageFilename, HDD* pHardDrive)
-{
- TCHAR imagetitle[128];
- LPCTSTR startpos = pszImageFilename;
-
- // imagetitle =
- if (_tcsrchr(startpos,TEXT('\\')))
- startpos = _tcsrchr(startpos,TEXT('\\'))+1;
- _tcsncpy(imagetitle,startpos,127);
- imagetitle[127] = 0;
-
- // if imagetitle contains a lowercase char, then found=1 (why?)
- BOOL found = 0;
- int loop = 0;
- while (imagetitle[loop] && !found)
- {
- if (IsCharLower(imagetitle[loop]))
- found = 1;
- else
- loop++;
- }
-
- if ((!found) && (loop > 2))
- CharLowerBuff(imagetitle+1,_tcslen(imagetitle+1));
-
- // hdptr->fullname =
- _tcsncpy(pHardDrive->fullname,imagetitle,127);
- pHardDrive->fullname[127] = 0;
-
- if (imagetitle[0])
- {
- LPTSTR dot = imagetitle;
- if (_tcsrchr(dot,TEXT('.')))
- dot = _tcsrchr(dot,TEXT('.'));
- if (dot > imagetitle)
- *dot = 0;
- }
-
- // hdptr->imagename = (ie. no extension)
- _tcsncpy(pHardDrive->imagename,imagetitle,15);
- pHardDrive->imagename[15] = 0;
-}
-
static void NotifyInvalidImage(TCHAR* pszImageFilename)
{
// TC: TO DO
}
-static BOOL HD_Load_Image(const int iDrive, LPCSTR pszImageFilename)
+//===========================================================================
+
+BOOL HD_Insert(const int iDrive, LPCTSTR pszImageFilename);
+
+void HD_LoadLastDiskImage(const int iDrive)
{
- const bool bCreateIfNecessary = false; // NB. Don't allow creation of HDV files
- std::string strFilenameInZip; // TODO: Use this
- ImageError_e Error = ImageOpen(pszImageFilename, iDrive, bCreateIfNecessary, strFilenameInZip);
+ _ASSERT(iDrive == HARDDISK_1 || iDrive == HARDDISK_2);
- g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE);
+ char sFilePath[ MAX_PATH + 1];
+ sFilePath[0] = 0;
-#if HD_LED
- g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF;
- g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
-#endif
+ char *pRegKey = (iDrive == HARDDISK_1)
+ ? REGVALUE_PREF_LAST_HARDDISK_1
+ : REGVALUE_PREF_LAST_HARDDISK_2;
- return g_HardDisk[iDrive].hd_imageloaded;
+ if (RegLoadString(TEXT(REG_PREFS), pRegKey, 1, sFilePath, MAX_PATH))
+ {
+ sFilePath[ MAX_PATH ] = 0;
+
+ g_bSaveDiskImage = false;
+ // Pass in ptr to local copy of filepath, since RemoveDisk() sets DiskPathFilename = "" // todo: update comment for HD func
+ HD_Insert(iDrive, sFilePath);
+ g_bSaveDiskImage = true;
+ }
}
//===========================================================================
-// everything below is global
+static void HD_SaveLastDiskImage(const int iDrive)
+{
+ _ASSERT(iDrive == HARDDISK_1 || iDrive == HARDDISK_2);
+
+ if (!g_bSaveDiskImage)
+ return;
+
+ const char *pFileName = g_HardDisk[iDrive].fullname;
+
+ if (iDrive == HARDDISK_1)
+ RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_HARDDISK_1, TRUE, pFileName);
+ else
+ RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_HARDDISK_2, TRUE, pFileName);
+}
+
+//===========================================================================
+
+// (Nearly) everything below is global
static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
@@ -263,7 +235,8 @@ bool HD_CardIsEnabled(void)
// Called by:
// . LoadConfiguration() - Done at each restart
-// . DiskDlg_OK() - When HD is enabled/disabled on UI
+// . RestoreCurrentConfig() - Done when Config dialog is cancelled
+// . Snapshot_LoadState_v2() - Done to default to disabled state
void HD_SetEnabled(const bool bEnabled)
{
if(g_bHD_Enabled == bEnabled)
@@ -298,17 +271,17 @@ LPCTSTR HD_GetFullName(const int iDrive)
LPCTSTR HD_GetFullPathName(const int iDrive)
{
- return g_HardDisk[iDrive].Info.szFilename;
+ return ImageGetPathname(g_HardDisk[iDrive].imagehandle);
}
-static LPCTSTR HD_DiskGetBaseName (const int iDrive) // Not used
+static LPCTSTR HD_DiskGetBaseName(const int iDrive) // Not used
{
return g_HardDisk[iDrive].imagename;
}
//-------------------------------------
-VOID HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot)
+void HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot)
{
if(!g_bHD_Enabled)
return;
@@ -336,46 +309,82 @@ VOID HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot)
RegisterIoHandler(g_uSlot, HD_IO_EMUL, HD_IO_EMUL, NULL, NULL, NULL, NULL);
}
-VOID HD_Cleanup(void)
+void HD_Destroy(void)
{
- for(int i=HARDDISK_1; i= MAX_PATH)
+ strcpy_s(szCurrentPathname, MAX_PATH, pszImageFilename);
+
+ if (!strcmp(pszOtherPathname, szCurrentPathname))
+ {
+ HD_Unplug(!iDrive);
+ FrameRefreshStatus(DRAW_LEDS);
+ }
}
- BOOL bResult = HD_Load_Image(iDrive, pszImageFilename);
+ const bool bCreateIfNecessary = false; // NB. Don't allow creation of HDV files
+ const bool bExpectFloppy = false;
+ ImageError_e Error = ImageOpen(pszImageFilename,
+ &g_HardDisk[iDrive].imagehandle,
+ &g_HardDisk[iDrive].bWriteProtected,
+ bCreateIfNecessary,
+ g_HardDisk[iDrive].strFilenameInZip, // TODO: Use this
+ bExpectFloppy);
- if (bResult)
- GetImageTitle(pszImageFilename, &g_HardDisk[iDrive]);
+ g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE);
- return bResult;
+#if HD_LED
+ g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF;
+ g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
+#endif
+
+ if (Error == eIMAGE_ERROR_NONE)
+ {
+ GetImageTitle(pszImageFilename, g_HardDisk[iDrive].imagename, g_HardDisk[iDrive].fullname);
+ }
+
+ HD_SaveLastDiskImage(iDrive);
+
+ return g_HardDisk[iDrive].hd_imageloaded;
}
-void HD_Select(const int iDrive)
+static bool HD_SelectImage(const int iDrive, LPCSTR pszFilename)
{
TCHAR directory[MAX_PATH] = TEXT("");
TCHAR filename[MAX_PATH] = TEXT("");
TCHAR title[40];
+ strcpy(filename, pszFilename);
+
RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, directory, MAX_PATH);
_tcscpy(title, TEXT("Select HDV Image For HDD "));
_tcscat(title, iDrive ? TEXT("2") : TEXT("1"));
+ _ASSERT(sizeof(OPENFILENAME) == sizeof(OPENFILENAME_NT4)); // Required for Win98/ME support (selected by _WIN32_WINNT=0x0400 in stdafx.h)
+
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
@@ -389,22 +398,32 @@ void HD_Select(const int iDrive)
ofn.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY; // Don't allow creation & hide the read-only checkbox
ofn.lpstrTitle = title;
+ bool bRes = false;
+
if (GetOpenFileName(&ofn))
{
if ((!ofn.nFileExtension) || !filename[ofn.nFileExtension])
_tcscat(filename,TEXT(".hdv"));
- if (HD_InsertDisk(iDrive, filename))
+ if (HD_Insert(iDrive, filename))
{
filename[ofn.nFileOffset] = 0;
if (_tcsicmp(directory, filename))
RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, filename);
+ bRes = true;
}
else
{
NotifyInvalidImage(filename);
}
}
+
+ return bRes;
+}
+
+void HD_Select(const int iDrive)
+{
+ HD_SelectImage(iDrive, TEXT(""));
}
void HD_Unplug(const int iDrive)
@@ -450,33 +469,33 @@ static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
{
default:
case 0x00: //status
- if (pHDD->Info.uImageSize == 0)
+ if (ImageGetImageSize(pHDD->imagehandle) == 0)
{
pHDD->hd_error = 1;
r = DEVICE_IO_ERROR;
}
break;
case 0x01: //read
- if ((pHDD->hd_diskblock * HD_BLOCK_SIZE) < pHDD->Info.uImageSize)
+ if ((pHDD->hd_diskblock * HD_BLOCK_SIZE) < ImageGetImageSize(pHDD->imagehandle))
+ {
+ bool bRes = ImageReadBlock(pHDD->imagehandle, pHDD->hd_diskblock, pHDD->hd_buf);
+ if (bRes)
{
- bool bRes = pHDD->Info.pImageType->Read(&pHDD->Info, pHDD->hd_diskblock, pHDD->hd_buf);
- if (bRes)
- {
- pHDD->hd_error = 0;
- r = 0;
- pHDD->hd_buf_ptr = 0;
- }
- else
- {
- pHDD->hd_error = 1;
- r = DEVICE_IO_ERROR;
- }
+ pHDD->hd_error = 0;
+ r = 0;
+ pHDD->hd_buf_ptr = 0;
}
else
{
pHDD->hd_error = 1;
r = DEVICE_IO_ERROR;
}
+ }
+ else
+ {
+ pHDD->hd_error = 1;
+ r = DEVICE_IO_ERROR;
+ }
break;
case 0x02: //write
{
@@ -484,17 +503,17 @@ static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
pHDD->hd_status_next = DISK_STATUS_WRITE;
#endif
bool bRes = true;
- const bool bAppendBlocks = (pHDD->hd_diskblock * HD_BLOCK_SIZE) >= pHDD->Info.uImageSize;
+ const bool bAppendBlocks = (pHDD->hd_diskblock * HD_BLOCK_SIZE) >= ImageGetImageSize(pHDD->imagehandle);
if (bAppendBlocks)
{
ZeroMemory(pHDD->hd_buf, HD_BLOCK_SIZE);
// Inefficient (especially for gzip/zip files!)
- UINT uBlock = pHDD->Info.uImageSize / HD_BLOCK_SIZE;
+ UINT uBlock = ImageGetImageSize(pHDD->imagehandle) / HD_BLOCK_SIZE;
while (uBlock < pHDD->hd_diskblock)
{
- bRes = pHDD->Info.pImageType->Write(&pHDD->Info, uBlock++, pHDD->hd_buf);
+ bRes = ImageWriteBlock(pHDD->imagehandle, uBlock++, pHDD->hd_buf);
_ASSERT(bRes);
if (!bRes)
break;
@@ -504,7 +523,7 @@ static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
MoveMemory(pHDD->hd_buf, mem+pHDD->hd_memblock, HD_BLOCK_SIZE);
if (bRes)
- bRes = pHDD->Info.pImageType->Write(&pHDD->Info, pHDD->hd_diskblock, pHDD->hd_buf);
+ bRes = ImageWriteBlock(pHDD->imagehandle, pHDD->hd_diskblock, pHDD->hd_buf);
if (bRes)
{
@@ -560,7 +579,8 @@ static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
break;
case 0xF8:
r = pHDD->hd_buf[pHDD->hd_buf_ptr];
- pHDD->hd_buf_ptr++;
+ if (pHDD->hd_buf_ptr < sizeof(pHDD->hd_buf)-1)
+ pHDD->hd_buf_ptr++;
break;
default:
#if HD_LED
@@ -631,3 +651,159 @@ void HD_GetLightStatus (Disk_Status_e *pDisk1Status_)
*pDisk1Status_ = DISK_STATUS_OFF;
}
}
+
+//===========================================================================
+
+struct HDD_Unit
+{
+ char szFilename[MAX_PATH];
+ BYTE error;
+ WORD memblock;
+ UINT diskblock;
+ WORD buf_ptr;
+ BOOL imageloaded;
+ BYTE buf[HD_BLOCK_SIZE];
+ UINT status_next;
+ UINT status_prev;
+};
+
+struct SS_CARD_HDD
+{
+ SS_CARD_HDR Hdr;
+ HDD_Unit Unit[NUM_HARDDISKS];
+ BYTE CurrUnit;
+ BYTE Command;
+};
+
+void HD_GetSnapshot(const HANDLE hFile)
+{
+ if (!HD_CardIsEnabled())
+ return;
+
+ SS_CARD_HDD CardHDD;
+
+ CardHDD.Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_HDD);
+ CardHDD.Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ CardHDD.Hdr.UnitHdr.hdr.v2.Version = 1;
+
+ CardHDD.Hdr.Slot = g_uSlot;
+ CardHDD.Hdr.Type = CT_GenericHDD;
+
+ CardHDD.CurrUnit = g_nHD_UnitNum;
+ CardHDD.Command = g_nHD_Command;
+
+ for (UINT i=0; i 1)
+ throw std::string("Card: wrong version");
+
+ if (CardHDD.Hdr.UnitHdr.hdr.v2.Length != sizeof(SS_CARD_HDD))
+ throw std::string("Card: unit size mismatch");
+
+ g_nHD_UnitNum = CardHDD.CurrUnit;
+ g_nHD_Command = CardHDD.Command;
+
+ // Unplug all HDDs first in case HDD-2 is to be plugged in as HDD-1
+ for (UINT i=0; ig_nJoyCntrResetCycle = g_nJoyCntrResetCycle;
- return 0;
+ g_nJoyCntrResetCycle = JoyCntrResetCycle;
}
-DWORD JoySetSnapshot(SS_IO_Joystick* pSS)
+//
+
+void JoyGetSnapshot(unsigned __int64& rJoyCntrResetCycle)
{
- g_nJoyCntrResetCycle = pSS->g_nJoyCntrResetCycle;
- return 0;
+ rJoyCntrResetCycle = g_nJoyCntrResetCycle;
+}
+
+void JoySetSnapshot(const unsigned __int64 JoyCntrResetCycle)
+{
+ g_nJoyCntrResetCycle = JoyCntrResetCycle;
}
diff --git a/source/Joystick.h b/source/Joystick.h
index 9889c2c9..f4dfba56 100644
--- a/source/Joystick.h
+++ b/source/Joystick.h
@@ -24,8 +24,9 @@ void JoyDisableUsingMouse();
void JoySetTrim(short nValue, bool bAxisX);
short JoyGetTrim(bool bAxisX);
void JoyportControl(const UINT uControl);
-DWORD JoyGetSnapshot(SS_IO_Joystick* pSS);
-DWORD JoySetSnapshot(SS_IO_Joystick* pSS);
+void JoySetSnapshot_v1(const unsigned __int64 JoyCntrResetCycle);
+void JoyGetSnapshot(unsigned __int64& rJoyCntrResetCycle);
+void JoySetSnapshot(const unsigned __int64 JoyCntrResetCycle);
BYTE __stdcall JoyReadButton(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
BYTE __stdcall JoyReadPosition(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index 2b1e1727..e3e3e2d1 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -50,7 +50,6 @@ static bool g_bCapsLock = true; //Caps lock key for Apple2 and Lat/Cyr lock for
static bool g_bP8CapsLock = true; //Caps lock key of Pravets 8A/C
static int lastvirtkey = 0; // Current PC keycode
static BYTE keycode = 0; // Current Apple keycode
-static DWORD keyboardqueries = 0;
#ifdef KEY_OLD
// Original
@@ -160,14 +159,6 @@ BYTE KeybGetKeycode () // Used by MemCheckPaging() & VideoCheckMode()
return keycode;
}
-//===========================================================================
-DWORD KeybGetNumQueries () // Used in determining 'idleness' of Apple system
-{
- DWORD result = keyboardqueries;
- keyboardqueries = 0;
- return result;
-}
-
//===========================================================================
void KeybQueueKeypress (int key, BOOL bASCII)
{
@@ -425,10 +416,6 @@ static char ClipboardCurrChar(bool bIncPtr)
BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
{
- keyboardqueries++;
-
- //
-
if(g_bPasteFromClipboard)
ClipboardInit();
@@ -463,10 +450,6 @@ BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG)
{
- keyboardqueries++;
-
- //
-
if(g_bPasteFromClipboard)
ClipboardInit();
@@ -516,16 +499,19 @@ void KeybToggleP8ACapsLock ()
//===========================================================================
-DWORD KeybGetSnapshot(SS_IO_Keyboard* pSS)
+void KeybSetSnapshot_v1(const BYTE LastKey)
{
- pSS->keyboardqueries = keyboardqueries;
- pSS->nLastKey = g_nLastKey;
- return 0;
+ g_nLastKey = LastKey;
}
-DWORD KeybSetSnapshot(SS_IO_Keyboard* pSS)
+//
+
+void KeybGetSnapshot(BYTE& rLastKey)
{
- keyboardqueries = pSS->keyboardqueries;
- g_nLastKey = pSS->nLastKey;
- return 0;
+ rLastKey = g_nLastKey;
+}
+
+void KeybSetSnapshot(const BYTE LastKey)
+{
+ g_nLastKey = LastKey;
}
diff --git a/source/Keyboard.h b/source/Keyboard.h
index 0010b677..7544d486 100644
--- a/source/Keyboard.h
+++ b/source/Keyboard.h
@@ -11,12 +11,12 @@ bool KeybGetShiftStatus();
bool KeybGetCapsAllowed(); //For Pravets8A/C only
void KeybUpdateCtrlShiftStatus();
BYTE KeybGetKeycode ();
-DWORD KeybGetNumQueries ();
void KeybQueueKeypress (int,BOOL);
void KeybToggleCapsLock ();
void KeybToggleP8ACapsLock ();
-DWORD KeybGetSnapshot(SS_IO_Keyboard* pSS);
-DWORD KeybSetSnapshot(SS_IO_Keyboard* pSS);
+void KeybSetSnapshot_v1(const BYTE LastKey);
+void KeybGetSnapshot(BYTE& rLastKey);
+void KeybSetSnapshot(const BYTE LastKey);
BYTE __stdcall KeybReadData (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
BYTE __stdcall KeybReadFlag (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 3868e0b2..9c97e0fb 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -51,6 +51,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "..\resource\resource.h"
#include "Configuration\PropertySheet.h"
#include "Debugger\DebugDefs.h"
+#include "SaveState_Structs_v2.h"
// Memory Flag
#define MF_80STORE 0x00000001
@@ -1103,17 +1104,14 @@ LPBYTE MemGetCxRomPeripheral()
//===========================================================================
+const UINT CxRomSize = 4*1024;
+const UINT Apple2RomSize = 12*1024;
+const UINT Apple2eRomSize = Apple2RomSize+CxRomSize;
+//const UINT Pravets82RomSize = 12*1024;
+//const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize;
+
void MemInitialize()
{
- // Init the I/O handlers
- InitIoHandlers();
-
- const UINT CxRomSize = 4*1024;
- const UINT Apple2RomSize = 12*1024;
- const UINT Apple2eRomSize = Apple2RomSize+CxRomSize;
- //const UINT Pravets82RomSize = 12*1024;
- //const UINT Pravets8ARomSize = Pravets82RomSize+CxRomSize;
-
// ALLOCATE MEMORY FOR THE APPLE MEMORY IMAGE AND ASSOCIATED DATA STRUCTURES
memaux = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE);
memmain = (LPBYTE)VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE);
@@ -1154,6 +1152,14 @@ void MemInitialize()
i++;
#endif
+ MemInitializeROM();
+ MemInitializeCustomF8ROM();
+ MemInitializeIO();
+ MemReset();
+}
+
+void MemInitializeROM(void)
+{
// READ THE APPLE FIRMWARE ROMS INTO THE ROM IMAGE
UINT ROM_SIZE = 0;
HRSRC hResInfo = NULL;
@@ -1210,8 +1216,6 @@ void MemInitialize()
if (pData == NULL)
return;
- //
-
memset(pCxRomInternal,0,CxRomSize);
memset(pCxRomPeripheral,0,CxRomSize);
@@ -1223,17 +1227,23 @@ void MemInitialize()
}
_ASSERT(ROM_SIZE == Apple2RomSize);
- memcpy(memrom, pData, Apple2RomSize); // ROM at $D000...$FFFF
+ memcpy(memrom, pData, Apple2RomSize); // ROM at $D000...$FFFF
+}
+void MemInitializeCustomF8ROM(void)
+{
const UINT F8RomSize = 0x800;
if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
{
+ BYTE OldRom[Apple2RomSize]; // NB. 12KB on stack
+ memcpy(OldRom, memrom, Apple2RomSize);
+
SetFilePointer(g_hCustomRomF8, 0, NULL, FILE_BEGIN);
DWORD uNumBytesRead;
BOOL bRes = ReadFile(g_hCustomRomF8, memrom+Apple2RomSize-F8RomSize, F8RomSize, &uNumBytesRead, NULL);
if (uNumBytesRead != F8RomSize)
{
- memcpy(memrom, pData, Apple2RomSize); // ROM at $D000...$FFFF
+ memcpy(memrom, OldRom, Apple2RomSize); // ROM at $D000...$FFFF
bRes = FALSE;
}
@@ -1248,15 +1258,27 @@ void MemInitialize()
if (sg_PropertySheet.GetTheFreezesF8Rom() && IS_APPLE2)
{
- hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_FREEZES_F8_ROM), "ROM");
+ HGLOBAL hResData = NULL;
+ BYTE* pData = NULL;
+
+ HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_FREEZES_F8_ROM), "ROM");
if (hResInfo && (SizeofResource(NULL, hResInfo) == 0x800) && (hResData = LoadResource(NULL, hResInfo)) && (pData = (BYTE*) LockResource(hResData)))
{
memcpy(memrom+Apple2RomSize-F8RomSize, pData, F8RomSize);
}
}
+}
- //
+// Called by:
+// . MemInitialize()
+// . Snapshot_LoadState_v2()
+//
+// Since called by LoadState(), then this must not init any cards
+// - it should only init the card I/O hooks
+void MemInitializeIO(void)
+{
+ InitIoHandlers();
const UINT uSlot = 0;
RegisterIoHandler(uSlot, MemSetPaging, MemSetPaging, NULL, NULL, NULL, NULL);
@@ -1297,8 +1319,6 @@ void MemInitialize()
DiskLoadRom(pCxRomPeripheral, 6); // $C600 : Disk][ f/w
HD_Load_Rom(pCxRomPeripheral, 7); // $C700 : HDD f/w
-
- MemReset();
}
inline DWORD getRandomTime()
@@ -1647,27 +1667,43 @@ LPVOID MemGetSlotParameters(UINT uSlot)
// . If we were to save the state when 'modechanging' is set, then on restoring the state, the 6502 code will immediately update the read memory mode.
// . This will work correctly.
-DWORD MemGetSnapshot(SS_BaseMemory* pSS)
+void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux)
{
- pSS->dwMemMode = memmode;
- pSS->bLastWriteRam = lastwriteram;
+ SetMemMode(MemMode);
+ lastwriteram = LastWriteRam;
- for(DWORD dwOffset = 0x0000; dwOffset < 0x10000; dwOffset+=0x100)
- {
- memcpy(pSS->nMemMain+dwOffset, MemGetMainPtr((WORD)dwOffset), 0x100);
- memcpy(pSS->nMemAux+dwOffset, MemGetAuxPtr((WORD)dwOffset), 0x100);
- }
-
- return 0;
-}
-
-DWORD MemSetSnapshot(SS_BaseMemory* pSS)
-{
- SetMemMode(pSS->dwMemMode);
- lastwriteram = pSS->bLastWriteRam;
-
- memcpy(memmain, pSS->nMemMain, nMemMainSize);
- memcpy(memaux, pSS->nMemAux, nMemAuxSize);
+ memcpy(memmain, pMemMain, nMemMainSize);
+ memcpy(memaux, pMemAux, nMemAuxSize);
+ memset(memdirty, 0, 0x100);
+
+ //
+
+ modechanging = 0;
+
+ UpdatePaging(1); // Initialize=1
+}
+
+//
+
+void MemGetSnapshot(SS_BaseMemory_v2& Memory)
+{
+ Memory.dwMemMode = memmode;
+ Memory.bLastWriteRam = lastwriteram;
+
+ for(DWORD dwOffset = 0x0000; dwOffset < 0x10000; dwOffset+=0x100)
+ {
+ memcpy(Memory.MemMain+dwOffset, MemGetMainPtr((WORD)dwOffset), 0x100);
+ memcpy(Memory.MemAux+dwOffset, MemGetAuxPtr((WORD)dwOffset), 0x100);
+ }
+}
+
+void MemSetSnapshot(const SS_BaseMemory_v2& Memory)
+{
+ SetMemMode(Memory.dwMemMode);
+ lastwriteram = Memory.bLastWriteRam;
+
+ memcpy(memmain, Memory.MemMain, nMemMainSize);
+ memcpy(memaux, Memory.MemAux, nMemAuxSize);
memset(memdirty, 0, 0x100);
//
@@ -1675,6 +1711,4 @@ DWORD MemSetSnapshot(SS_BaseMemory* pSS)
modechanging = 0;
UpdatePaging(1); // Initialize=1
-
- return 0;
}
diff --git a/source/Memory.h b/source/Memory.h
index 207cd1b1..bc5a0a53 100644
--- a/source/Memory.h
+++ b/source/Memory.h
@@ -44,14 +44,18 @@ LPBYTE MemGetMainPtr(const WORD);
LPBYTE MemGetBankPtr(const UINT nBank);
LPBYTE MemGetCxRomPeripheral();
void MemInitialize ();
+void MemInitializeROM(void);
+void MemInitializeCustomF8ROM(void);
+void MemInitializeIO(void);
BYTE MemReadFloatingBus(const ULONG uExecutedCycles);
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles);
void MemReset ();
void MemResetPaging ();
void MemUpdatePaging(BOOL initialize);
LPVOID MemGetSlotParameters (UINT uSlot);
-DWORD MemGetSnapshot(SS_BaseMemory* pSS);
-DWORD MemSetSnapshot(SS_BaseMemory* pSS);
+void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux);
+void MemGetSnapshot(struct SS_BaseMemory_v2& Memory);
+void MemSetSnapshot(const struct SS_BaseMemory_v2& Memory);
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp
index 590c7870..405ad239 100644
--- a/source/Mockingboard.cpp
+++ b/source/Mockingboard.cpp
@@ -77,6 +77,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
+#include "SaveState_Structs_v1.h"
+
#include "AppleWin.h"
#include "CPU.h"
#include "Log.h"
@@ -1761,13 +1763,15 @@ void MB_SetVolume(DWORD dwVolume, DWORD dwVolumeMax)
//===========================================================================
-DWORD MB_GetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD dwSlot)
+// Called by debugger - Debugger_Display.cpp
+void MB_GetSnapshot_v1(SS_CARD_MOCKINGBOARD* const pSS, const DWORD dwSlot)
{
- pSS->Hdr.UnitHdr.dwLength = sizeof(SS_CARD_DISK2);
- pSS->Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,0);
+ pSS->Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_MOCKINGBOARD);
+ pSS->Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ pSS->Hdr.UnitHdr.hdr.v2.Version = 1;
- pSS->Hdr.dwSlot = dwSlot;
- pSS->Hdr.dwType = CT_MockingboardC;
+ pSS->Hdr.Slot = dwSlot;
+ pSS->Hdr.Type = CT_MockingboardC;
UINT nMbCardNum = dwSlot - SLOT4;
UINT nDeviceNum = nMbCardNum*2;
@@ -1783,16 +1787,14 @@ DWORD MB_GetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD dwSlot)
nDeviceNum++;
pMB++;
}
-
- return 0;
}
-DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD /*dwSlot*/)
+int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD* const pSS, const DWORD /*dwSlot*/)
{
- if(pSS->Hdr.UnitHdr.dwVersion != MAKE_VERSION(1,0,0,0))
+ if(pSS->Hdr.UnitHdr.hdr.v1.dwVersion != MAKE_VERSION(1,0,0,0))
return -1;
- UINT nMbCardNum = pSS->Hdr.dwSlot - SLOT4;
+ UINT nMbCardNum = pSS->Hdr.Slot - SLOT4;
UINT nDeviceNum = nMbCardNum*2;
SY6522_AY8910* pMB = &g_MB[nDeviceNum];
@@ -1832,3 +1834,111 @@ DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD /*dwSlot*/)
return 0;
}
+
+//===========================================================================
+
+void MB_GetSnapshot(const HANDLE hFile, const UINT uSlot)
+{
+ SS_CARD_MOCKINGBOARD CardMockingboardC;
+
+ SS_CARD_MOCKINGBOARD* const pSS = &CardMockingboardC;
+
+ pSS->Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_MOCKINGBOARD);
+ pSS->Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ pSS->Hdr.UnitHdr.hdr.v2.Version = 1;
+
+ pSS->Hdr.Slot = uSlot; // fixme: object should be just 1 Mockingboard card & it will know its slot
+ pSS->Hdr.Type = CT_MockingboardC;
+
+ UINT nMbCardNum = uSlot - SLOT4;
+ UINT nDeviceNum = nMbCardNum*2;
+ SY6522_AY8910* pMB = &g_MB[nDeviceNum];
+
+ for(UINT i=0; iUnit[i].RegsSY6522, &pMB->sy6522, sizeof(SY6522));
+ memcpy(&pSS->Unit[i].RegsAY8910, AY8910_GetRegsPtr(nDeviceNum), 16);
+ memcpy(&pSS->Unit[i].RegsSSI263, &pMB->SpeechChip, sizeof(SSI263A));
+ pSS->Unit[i].nAYCurrentRegister = pMB->nAYCurrentRegister;
+
+ nDeviceNum++;
+ pMB++;
+ }
+
+ //
+
+ DWORD dwBytesWritten;
+ BOOL bRes = WriteFile( hFile,
+ &CardMockingboardC,
+ CardMockingboardC.Hdr.UnitHdr.hdr.v2.Length,
+ &dwBytesWritten,
+ NULL);
+
+ if(!bRes || (dwBytesWritten != CardMockingboardC.Hdr.UnitHdr.hdr.v2.Length))
+ {
+ //dwError = GetLastError();
+ throw std::string("Save error: Mockingboard");
+ }
+}
+
+void MB_SetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_MOCKINGBOARD CardMockingboardC;
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( hFile,
+ &CardMockingboardC,
+ sizeof(CardMockingboardC),
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != sizeof(CardMockingboardC))
+ throw std::string("Card: file corrupt");
+
+ if (CardMockingboardC.Hdr.Slot != 4 && CardMockingboardC.Hdr.Slot != 5) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (CardMockingboardC.Hdr.UnitHdr.hdr.v2.Version > 1)
+ throw std::string("Card: wrong version");
+
+ if (CardMockingboardC.Hdr.UnitHdr.hdr.v2.Length != sizeof(SS_CARD_MOCKINGBOARD))
+ throw std::string("Card: unit size mismatch");
+
+ UINT nMbCardNum = CardMockingboardC.Hdr.Slot - SLOT4;
+ UINT nDeviceNum = nMbCardNum*2;
+ SY6522_AY8910* pMB = &g_MB[nDeviceNum];
+
+ g_nSSI263Device = 0;
+ g_nCurrentActivePhoneme = -1;
+
+ for(UINT i=0; isy6522, &CardMockingboardC.Unit[i].RegsSY6522, sizeof(SY6522));
+ memcpy(AY8910_GetRegsPtr(nDeviceNum), &CardMockingboardC.Unit[i].RegsAY8910, 16);
+ memcpy(&pMB->SpeechChip, &CardMockingboardC.Unit[i].RegsSSI263, sizeof(SSI263A));
+ pMB->nAYCurrentRegister = CardMockingboardC.Unit[i].nAYCurrentRegister;
+
+ StartTimer(pMB); // Attempt to start timer
+
+ //
+
+ // Crude - currently only support a single speech chip
+ // FIX THIS:
+ // . Speech chip could be Votrax instead
+ // . Is this IRQ compatible with Phasor?
+ if(pMB->SpeechChip.DurationPhonome)
+ {
+ g_nSSI263Device = nDeviceNum;
+
+ if((pMB->SpeechChip.CurrentMode != MODE_IRQ_DISABLED) && (pMB->sy6522.PCR == 0x0C) && (pMB->sy6522.IER & IxR_PERIPHERAL))
+ {
+ pMB->sy6522.IFR |= IxR_PERIPHERAL;
+ UpdateIFR(pMB);
+ pMB->SpeechChip.CurrentMode |= 1; // Set SSI263's D7 pin
+ }
+ }
+
+ nDeviceNum++;
+ pMB++;
+ }
+}
diff --git a/source/Mockingboard.h b/source/Mockingboard.h
index edd337b8..dc9f55c5 100644
--- a/source/Mockingboard.h
+++ b/source/Mockingboard.h
@@ -22,5 +22,8 @@ double MB_GetFramePeriod();
bool MB_IsActive();
DWORD MB_GetVolume();
void MB_SetVolume(DWORD dwVolume, DWORD dwVolumeMax);
-DWORD MB_GetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD dwSlot);
-DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD dwSlot);
+
+void MB_GetSnapshot_v1(struct SS_CARD_MOCKINGBOARD* const pSS, const DWORD dwSlot); // For debugger
+int MB_SetSnapshot_v1(const struct SS_CARD_MOCKINGBOARD* const pSS, const DWORD dwSlot);
+void MB_GetSnapshot(const HANDLE hFile, const UINT uSlot);
+void MB_SetSnapshot(const HANDLE hFile);
diff --git a/source/MouseInterface.cpp b/source/MouseInterface.cpp
index 0805e3ff..442fed43 100644
--- a/source/MouseInterface.cpp
+++ b/source/MouseInterface.cpp
@@ -41,7 +41,7 @@ Etc.
#include "stdafx.h"
-#include "Structs.h"
+#include "SaveState_Structs_common.h"
#include "Common.h"
#include "CPU.h"
@@ -598,6 +598,166 @@ void CMouseInterface::SetButton(eBUTTON Button, eBUTTONSTATE State)
OnMouseEvent();
}
+struct MouseCard_Unit
+{
+ //6821
+ mc6821_t mc6821;
+ BYTE byIA;
+ BYTE byIB;
+
+ //MouseCard
+ int nDataLen;
+ BYTE byMode;
+
+ BYTE by6821B;
+ BYTE by6821A;
+ BYTE byBuff[8];
+ int nBuffPos;
+
+ BYTE byState;
+ int nX;
+ int nY;
+ BOOL bBtn0;
+ BOOL bBtn1;
+
+ bool bVBL;
+
+ //
+
+ int iX;
+ int iMinX;
+ int iMaxX;
+ int iY;
+ int iMinY;
+ int iMaxY;
+
+ BOOL bButtons[2];
+
+ //
+
+ bool bActive; // Mouse h/w is active within the Apple][ VM
+ bool bEnabled; // Windows' mouse events get passed to Apple]['s mouse h/w
+};
+
+struct SS_CARD_MOUSECARD
+{
+ SS_CARD_HDR Hdr;
+ MouseCard_Unit Unit;
+};
+
+// Post:
+// 0 = No mouse card
+// >0 = Mouse card saved OK from slot n
+// -1 = File error
+int CMouseInterface::GetSnapshot(const HANDLE hFile)
+{
+ if (!m_bActive)
+ return 0;
+
+ SS_CARD_MOUSECARD CardMouseCard;
+
+ CardMouseCard.Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_MOUSECARD);
+ CardMouseCard.Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ CardMouseCard.Hdr.UnitHdr.hdr.v2.Version = 1;
+
+ CardMouseCard.Hdr.Slot = m_uSlot;
+ CardMouseCard.Hdr.Type = CT_MouseInterface;
+
+ MouseCard_Unit& Unit = CardMouseCard.Unit;
+
+ m_6821.Get6821(Unit.mc6821, Unit.byIA, Unit.byIB);
+
+ Unit.nDataLen = m_nDataLen;
+ Unit.byMode = m_byMode;
+ Unit.by6821B = m_by6821B;
+ Unit.by6821A = m_by6821A;
+ memcpy(Unit.byBuff, m_byBuff, sizeof(Unit.byBuff));
+ Unit.nBuffPos = m_nBuffPos;
+ Unit.byState = m_byState;
+ Unit.nX = m_nX;
+ Unit.nY = m_nY;
+ Unit.bBtn0 = m_bBtn0;
+ Unit.bBtn1 = m_bBtn1;
+ Unit.bVBL = m_bVBL;
+ Unit.iX = m_iX;
+ Unit.iMinX = m_iMinX;
+ Unit.iMaxX = m_iMaxX;
+ Unit.iY = m_iY;
+ Unit.iMinY = m_iMinY;
+ Unit.iMaxY = m_iMaxY;
+ Unit.bButtons[0] = m_bButtons[0];
+ Unit.bButtons[1] = m_bButtons[1];
+ Unit.bActive = m_bActive;
+ Unit.bEnabled = m_bEnabled;
+
+ //
+
+ DWORD dwBytesWritten;
+ BOOL bRes = WriteFile( hFile,
+ &CardMouseCard,
+ CardMouseCard.Hdr.UnitHdr.hdr.v2.Length,
+ &dwBytesWritten,
+ NULL);
+
+ if(!bRes || (dwBytesWritten != CardMouseCard.Hdr.UnitHdr.hdr.v2.Length))
+ throw std::string("Save error: Mouse");
+
+ return m_uSlot;
+}
+
+void CMouseInterface::SetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_MOUSECARD CardMouseCard;
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( hFile,
+ &CardMouseCard,
+ sizeof(CardMouseCard),
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != sizeof(CardMouseCard))
+ throw std::string("Card: file corrupt");
+
+ if (CardMouseCard.Hdr.Slot != 4) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (CardMouseCard.Hdr.UnitHdr.hdr.v2.Version > 1)
+ throw std::string("Card: wrong version");
+
+ if (CardMouseCard.Hdr.UnitHdr.hdr.v2.Length != sizeof(SS_CARD_MOUSECARD))
+ throw std::string("Card: unit size mismatch");
+
+ const MouseCard_Unit& Unit = CardMouseCard.Unit;
+
+ m_6821.Set6821(Unit.mc6821, Unit.byIA, Unit.byIB);
+
+ m_nDataLen = Unit.nDataLen;
+ m_byMode = Unit.byMode;
+ m_by6821B = Unit.by6821B;
+ m_by6821A = Unit.by6821A;
+ memcpy(m_byBuff, Unit.byBuff, sizeof(Unit.byBuff));
+ m_nBuffPos = Unit.nBuffPos;
+ m_byState = Unit.byState;
+ m_nX = Unit.nX;
+ m_nY = Unit.nY;
+ m_bBtn0 = Unit.bBtn0;
+ m_bBtn1 = Unit.bBtn1;
+ m_bVBL = Unit.bVBL;
+ m_iX = Unit.iX;
+ m_iMinX = Unit.iMinX;
+ m_iMaxX = Unit.iMaxX;
+ m_iY = Unit.iY;
+ m_iMinY = Unit.iMinY;
+ m_iMaxY = Unit.iMaxY;
+ m_bButtons[0] = Unit.bButtons[0];
+ m_bButtons[1] = Unit.bButtons[1];
+
+ m_bActive = Unit.bActive;
+ //m_bEnabled = Unit.bEnabled;
+ //m_uSlot = CardMouseCard.Hdr.Slot;
+}
+
//=============================================================================
// DirectInput interface
//=============================================================================
@@ -819,4 +979,4 @@ namespace DIMouse
return S_OK;
}
-}; // namespace DIMouse
\ No newline at end of file
+}; // namespace DIMouse
diff --git a/source/MouseInterface.h b/source/MouseInterface.h
index 6c13a4f2..600b6321 100644
--- a/source/MouseInterface.h
+++ b/source/MouseInterface.h
@@ -12,7 +12,6 @@ public:
void Initialize(LPBYTE pCxRomPeripheral, UINT uSlot);
void Uninitialize();
void Reset();
- void SetSlotRom();
static BYTE __stdcall IORead(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft);
static BYTE __stdcall IOWrite(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft);
@@ -38,7 +37,11 @@ public:
m_iY = iY;
}
+ int GetSnapshot(const HANDLE hFile);
+ void SetSnapshot(const HANDLE hFile);
+
protected:
+ void SetSlotRom();
void On6821_A(BYTE byData);
void On6821_B(BYTE byData);
void OnCommand();
diff --git a/source/ParallelPrinter.cpp b/source/ParallelPrinter.cpp
index 2ef531a6..a26498f4 100644
--- a/source/ParallelPrinter.cpp
+++ b/source/ParallelPrinter.cpp
@@ -36,18 +36,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "..\resource\resource.h"
static DWORD inactivity = 0;
+static int g_iPrinterIdleLimit = 10;
static FILE* file = NULL;
DWORD const PRINTDRVR_SIZE = APPLE_SLOT_SIZE;
-TCHAR filepath[MAX_PATH * 2];
#define DEFAULT_PRINT_FILENAME "Printer.txt"
static char g_szPrintFilename[MAX_PATH] = {0};
bool g_bDumpToPrinter = false;
bool g_bConvertEncoding = true;
bool g_bFilterUnprintable = true;
bool g_bPrinterAppend = false;
-int g_iPrinterIdleLimit = 10;
bool g_bEnableDumpToRealPrinter = false;
+static UINT g_uSlot = 0;
+
//===========================================================================
static BYTE __stdcall PrintStatus(WORD, WORD, BYTE, BYTE, ULONG);
@@ -79,6 +80,8 @@ VOID PrintLoadRom(LPBYTE pCxRomPeripheral, const UINT uSlot)
//
RegisterIoHandler(uSlot, PrintStatus, PrintTransmit, NULL, NULL, NULL, NULL);
+
+ g_uSlot = uSlot;
}
//===========================================================================
@@ -245,8 +248,110 @@ unsigned int Printer_GetIdleLimit()
return g_iPrinterIdleLimit;
}
-//unsigned int
void Printer_SetIdleLimit(unsigned int Duration)
{
g_iPrinterIdleLimit = Duration;
}
+
+//===========================================================================
+
+struct PrinterCard_Unit
+{
+ DWORD Inactivity;
+ UINT PrinterIdleLimit;
+ char PrintFilename[MAX_PATH];
+ BOOL IsFileOpen;
+ BOOL DumpToPrinter;
+ BOOL ConvertEncoding;
+ BOOL FilterUnprintable;
+ BOOL PrinterAppend;
+ BOOL EnableDumpToRealPrinter;
+};
+
+struct SS_CARD_PRINTER
+{
+ SS_CARD_HDR Hdr;
+ PrinterCard_Unit Unit;
+};
+
+void Printer_GetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_PRINTER CardPrinter;
+
+ SS_CARD_PRINTER* const pSS = &CardPrinter;
+
+ pSS->Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_PRINTER);
+ pSS->Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ pSS->Hdr.UnitHdr.hdr.v2.Version = 1;
+
+ pSS->Hdr.Slot = g_uSlot;
+ pSS->Hdr.Type = CT_GenericPrinter;
+
+ CardPrinter.Unit.Inactivity = inactivity;
+ CardPrinter.Unit.PrinterIdleLimit = g_iPrinterIdleLimit;
+ memcpy(CardPrinter.Unit.PrintFilename, g_szPrintFilename, sizeof(CardPrinter.Unit.PrintFilename));
+ CardPrinter.Unit.IsFileOpen = (file != NULL);
+ CardPrinter.Unit.DumpToPrinter = g_bDumpToPrinter;
+ CardPrinter.Unit.ConvertEncoding = g_bConvertEncoding;
+ CardPrinter.Unit.FilterUnprintable = g_bFilterUnprintable;
+ CardPrinter.Unit.PrinterAppend = g_bPrinterAppend;
+ CardPrinter.Unit.EnableDumpToRealPrinter = g_bEnableDumpToRealPrinter;
+
+ //
+
+ DWORD dwBytesWritten;
+ BOOL bRes = WriteFile( hFile,
+ &CardPrinter,
+ CardPrinter.Hdr.UnitHdr.hdr.v2.Length,
+ &dwBytesWritten,
+ NULL);
+
+ if(!bRes || (dwBytesWritten != CardPrinter.Hdr.UnitHdr.hdr.v2.Length))
+ {
+ //dwError = GetLastError();
+ throw std::string("Save error: Printer Card");
+ }
+}
+
+void Printer_SetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_PRINTER CardPrinter;
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( hFile,
+ &CardPrinter,
+ sizeof(CardPrinter),
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != sizeof(CardPrinter))
+ throw std::string("Card: file corrupt");
+
+ if (CardPrinter.Hdr.Slot != 1) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (CardPrinter.Hdr.UnitHdr.hdr.v2.Version > 1)
+ throw std::string("Card: wrong version");
+
+ if (CardPrinter.Hdr.UnitHdr.hdr.v2.Length != sizeof(SS_CARD_PRINTER))
+ throw std::string("Card: unit size mismatch");
+
+ ClosePrint(); // Close current print session (and close file handle)
+
+ inactivity = CardPrinter.Unit.Inactivity;
+ g_iPrinterIdleLimit = CardPrinter.Unit.PrinterIdleLimit;
+ memcpy(g_szPrintFilename, CardPrinter.Unit.PrintFilename, sizeof(g_szPrintFilename));
+ if (CardPrinter.Unit.IsFileOpen)
+ {
+ g_bPrinterAppend = true; // Re-open print-file in append mode
+ BOOL bRes = CheckPrint();
+ if (!bRes)
+ throw std::string("Printer Card: Unable to resume printing to file");
+ }
+
+ g_bDumpToPrinter = CardPrinter.Unit.DumpToPrinter == TRUE;
+ g_bConvertEncoding = CardPrinter.Unit.ConvertEncoding == TRUE;
+ g_bFilterUnprintable = CardPrinter.Unit.FilterUnprintable == TRUE;
+ g_bPrinterAppend = CardPrinter.Unit.PrinterAppend == TRUE;
+ g_bEnableDumpToRealPrinter = CardPrinter.Unit.EnableDumpToRealPrinter == TRUE;
+}
diff --git a/source/ParallelPrinter.h b/source/ParallelPrinter.h
index d2936a13..fc227231 100644
--- a/source/ParallelPrinter.h
+++ b/source/ParallelPrinter.h
@@ -9,11 +9,11 @@ char* Printer_GetFilename();
void Printer_SetIdleLimit(unsigned int Duration);
unsigned int Printer_GetIdleLimit();
+void Printer_GetSnapshot(const HANDLE hFile);
+void Printer_SetSnapshot(const HANDLE hFile);
+
extern bool g_bDumpToPrinter;
extern bool g_bConvertEncoding;
extern bool g_bFilterUnprintable;
extern bool g_bPrinterAppend;
-extern int g_iPrinterIdleLimit;
-extern bool g_bFilterUnprintable;
-extern bool g_bPrinterAppend;
extern bool g_bEnableDumpToRealPrinter; // Set by cmd-line: -printer-real
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index 5c38beed..4229fc15 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -23,11 +23,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/* Description: Save-state (snapshot) module
*
- * Author: Copyright (c) 2004-2006 Tom Charlesworth
+ * Author: Copyright (c) 2004-2015 Tom Charlesworth
*/
#include "StdAfx.h"
+#include "SaveState_Structs_v1.h"
+#include "SaveState_Structs_v2.h"
+
#include "AppleWin.h"
#include "CPU.h"
#include "Disk.h"
@@ -36,10 +39,15 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Keyboard.h"
#include "Memory.h"
#include "Mockingboard.h"
+#include "MouseInterface.h"
+#include "ParallelPrinter.h"
#include "SerialComms.h"
#include "Speaker.h"
#include "Video.h"
+#include "Configuration\Config.h"
+#include "Configuration\IPropertySheet.h"
+
#define DEFAULT_SNAPSHOT_NAME "SaveState.aws"
@@ -93,22 +101,27 @@ const char* Snapshot_GetPath()
//-----------------------------------------------------------------------------
-void Snapshot_LoadState()
+static void Snapshot_LoadState_v1() // .aws v1.0.0.1, up to (and including) AppleWin v1.25.0
{
- char szMessage[32 + MAX_PATH];
- std::string strOldImageDir;
+ std::string strOldImageDir(g_sCurrentDir);
- APPLEWIN_SNAPSHOT* pSS = (APPLEWIN_SNAPSHOT*) new char[sizeof(APPLEWIN_SNAPSHOT)];
+ APPLEWIN_SNAPSHOT_v1* pSS = (APPLEWIN_SNAPSHOT_v1*) new char[sizeof(APPLEWIN_SNAPSHOT_v1)]; // throw's bad_alloc
try
{
- strOldImageDir = g_sCurrentDir;
+#if _MSC_VER >= 1600 // static_assert supported from VS2010 (cl.exe v16.00)
+ static_assert(kSnapshotSize_v1 == sizeof(APPLEWIN_SNAPSHOT_v1), "Save-state v1 struct size mismatch");
+#else
+ // A compile error here means sizeof(APPLEWIN_SNAPSHOT_v1) is wrong, eg. one of the constituent structs has been modified
+ typedef char VerifySizesAreEqual[kSnapshotSize_v1 == sizeof(APPLEWIN_SNAPSHOT_v1) ? 1 : -1];
+#endif
+
+ if (kSnapshotSize_v1 != sizeof(APPLEWIN_SNAPSHOT_v1))
+ throw std::string("Save-state v1 struct size mismatch");
+
SetCurrentImageDir(g_strSaveStatePath.c_str()); // Allow .dsk's load without prompting
- if(pSS == NULL)
- throw(0);
-
- memset(pSS, 0, sizeof(APPLEWIN_SNAPSHOT));
+ memset(pSS, 0, sizeof(APPLEWIN_SNAPSHOT_v1));
//
@@ -121,39 +134,26 @@ void Snapshot_LoadState()
NULL);
if(hFile == INVALID_HANDLE_VALUE)
- {
- strcpy(szMessage, "File not found: ");
- strcpy(szMessage + strlen(szMessage), g_strSaveStatePathname.c_str());
- throw(0);
- }
+ throw std::string("File not found: ") + g_strSaveStatePathname;
DWORD dwBytesRead;
BOOL bRes = ReadFile( hFile,
pSS,
- sizeof(APPLEWIN_SNAPSHOT),
+ sizeof(APPLEWIN_SNAPSHOT_v1),
&dwBytesRead,
NULL);
CloseHandle(hFile);
- if(!bRes || (dwBytesRead != sizeof(APPLEWIN_SNAPSHOT)))
- {
+ if(!bRes || (dwBytesRead != sizeof(APPLEWIN_SNAPSHOT_v1)))
// File size wrong: probably because of version mismatch or corrupt file
- strcpy(szMessage, "File size mismatch");
- throw(0);
- }
+ throw std::string("File size mismatch");
if(pSS->Hdr.dwTag != AW_SS_TAG)
- {
- strcpy(szMessage, "File corrupt");
- throw(0);
- }
+ throw std::string("File corrupt");
if(pSS->Hdr.dwVersion != MAKE_VERSION(1,0,0,1))
- {
- strcpy(szMessage, "Version mismatch");
- throw(0);
- }
+ throw std::string("Version mismatch");
// TO DO: Verify checksum
@@ -173,34 +173,40 @@ void Snapshot_LoadState()
// Apple2 unit
//
- CpuSetSnapshot(&pSS->Apple2Unit.CPU6502);
- sg_SSC.CommSetSnapshot(&pSS->Apple2Unit.Comms);
- JoySetSnapshot(&pSS->Apple2Unit.Joystick);
- KeybSetSnapshot(&pSS->Apple2Unit.Keyboard);
- SpkrSetSnapshot(&pSS->Apple2Unit.Speaker);
- VideoSetSnapshot(&pSS->Apple2Unit.Video);
- MemSetSnapshot(&pSS->Apple2Unit.Memory);
+ SS_CPU6502& CPU = pSS->Apple2Unit.CPU6502;
+ CpuSetSnapshot_v1(CPU.A, CPU.X, CPU.Y, CPU.P, CPU.S, CPU.PC, CPU.nCumulativeCycles);
+
+ SS_IO_Comms& SSC = pSS->Apple2Unit.Comms;
+ sg_SSC.SetSnapshot_v1(SSC.baudrate, SSC.bytesize, SSC.commandbyte, SSC.comminactivity, SSC.controlbyte, SSC.parity, SSC.stopbits);
+
+ JoySetSnapshot_v1(pSS->Apple2Unit.Joystick.nJoyCntrResetCycle);
+ KeybSetSnapshot_v1(pSS->Apple2Unit.Keyboard.nLastKey);
+ SpkrSetSnapshot_v1(pSS->Apple2Unit.Speaker.nSpkrLastCycle);
+ VideoSetSnapshot_v1(pSS->Apple2Unit.Video.bAltCharSet, pSS->Apple2Unit.Video.dwVidMode);
+ MemSetSnapshot_v1(pSS->Apple2Unit.Memory.dwMemMode, pSS->Apple2Unit.Memory.bLastWriteRam, pSS->Apple2Unit.Memory.nMemMain, pSS->Apple2Unit.Memory.nMemAux);
//
//
// Slot4: Mockingboard
- MB_SetSnapshot(&pSS->Mockingboard1, 4);
+ MB_SetSnapshot_v1(&pSS->Mockingboard1, 4);
//
// Slot5: Mockingboard
- MB_SetSnapshot(&pSS->Mockingboard2, 5);
+ MB_SetSnapshot_v1(&pSS->Mockingboard2, 5);
//
// Slot6: Disk][
- DiskSetSnapshot(&pSS->Disk2, 6);
+ DiskSetSnapshot_v1(&pSS->Disk2);
SetLoadedSaveStateFlag(true);
+
+ MemUpdatePaging(TRUE);
}
- catch(int)
+ catch(std::string szMessage)
{
MessageBox( g_hFrameWindow,
- szMessage,
+ szMessage.c_str(),
TEXT("Load State"),
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
@@ -212,104 +218,429 @@ void Snapshot_LoadState()
//-----------------------------------------------------------------------------
-void Snapshot_SaveState()
+HANDLE m_hFile = INVALID_HANDLE_VALUE;
+CConfigNeedingRestart m_ConfigNew;
+
+static void Snapshot_LoadState_FileHdr(SS_FILE_HDR& Hdr)
{
- APPLEWIN_SNAPSHOT* pSS = (APPLEWIN_SNAPSHOT*) new char[sizeof(APPLEWIN_SNAPSHOT)];
- if(pSS == NULL)
+ try
{
- // To do
+ m_hFile = CreateFile( g_strSaveStatePathname.c_str(),
+ GENERIC_READ,
+ 0,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ if(m_hFile == INVALID_HANDLE_VALUE)
+ throw std::string("File not found: ") + g_strSaveStatePathname;
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( m_hFile,
+ &Hdr,
+ sizeof(Hdr),
+ &dwBytesRead,
+ NULL);
+
+ if(!bRes || (dwBytesRead != sizeof(Hdr)))
+ throw std::string("File size mismatch");
+
+ if(Hdr.dwTag != AW_SS_TAG)
+ throw std::string("File corrupt");
+ }
+ catch(std::string szMessage)
+ {
+ MessageBox( g_hFrameWindow,
+ szMessage.c_str(),
+ TEXT("Load State"),
+ MB_ICONEXCLAMATION | MB_SETFOREGROUND);
+
+ if(m_hFile == INVALID_HANDLE_VALUE)
+ {
+ CloseHandle(m_hFile);
+ m_hFile = INVALID_HANDLE_VALUE;
+ }
+ }
+}
+
+#define UNIT_APPLE2_VER 1
+#define UNIT_CARD_VER 1
+#define UNIT_CONFIG_VER 1
+
+static void LoadUnitApple2(DWORD Length, DWORD Version)
+{
+ SS_APPLE2_Unit_v2 Apple2Unit;
+
+ if (Version != UNIT_APPLE2_VER)
+ throw std::string("Apple2: Version mismatch");
+
+ if (Length != sizeof(Apple2Unit))
+ throw std::string("Apple2: Length mismatch");
+
+ if (SetFilePointer(m_hFile, -(LONG)sizeof(Apple2Unit.UnitHdr), NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ throw std::string("Apple2: file corrupt");
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( m_hFile,
+ &Apple2Unit,
+ Length,
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != Length)
+ throw std::string("Apple2: file corrupt");
+
+ g_Apple2Type = (eApple2Type) Apple2Unit.Apple2Type;
+ m_ConfigNew.m_Apple2Type = g_Apple2Type;
+
+ CpuSetSnapshot(Apple2Unit.CPU6502);
+ JoySetSnapshot(Apple2Unit.Joystick.JoyCntrResetCycle);
+ KeybSetSnapshot(Apple2Unit.Keyboard.LastKey);
+ SpkrSetSnapshot(Apple2Unit.Speaker.SpkrLastCycle);
+ VideoSetSnapshot(Apple2Unit.Video);
+ MemSetSnapshot(Apple2Unit.Memory);
+}
+
+//===
+
+static void LoadCardDisk2(void)
+{
+ DiskSetSnapshot(m_hFile);
+}
+
+static void LoadCardMockingboardC(void)
+{
+ MB_SetSnapshot(m_hFile);
+}
+
+static void LoadCardMouseInterface(void)
+{
+ sg_Mouse.SetSnapshot(m_hFile);
+}
+
+static void LoadCardSSC(void)
+{
+ sg_SSC.SetSnapshot(m_hFile);
+}
+
+static void LoadCardPrinter(void)
+{
+ Printer_SetSnapshot(m_hFile);
+}
+
+static void LoadCardHDD(void)
+{
+ HD_SetSnapshot(m_hFile, g_strSaveStatePath);
+ m_ConfigNew.m_bEnableHDD = true;
+}
+
+//===
+
+static void LoadUnitCard(DWORD Length, DWORD Version)
+{
+ SS_CARD_HDR Card;
+
+ if (Version != UNIT_APPLE2_VER)
+ throw std::string("Card: Version mismatch");
+
+ if (Length < sizeof(Card))
+ throw std::string("Card: file corrupt");
+
+ if (SetFilePointer(m_hFile, -(LONG)sizeof(Card.UnitHdr), NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ throw std::string("Card: file corrupt");
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( m_hFile,
+ &Card,
+ sizeof(Card),
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != sizeof(Card))
+ throw std::string("Card: file corrupt");
+
+ //currently cards are changed by restarting machine (ie. all slot empty) then adding cards (most of which are hardcoded to specific slots)
+
+ if (SetFilePointer(m_hFile, -(LONG)sizeof(SS_CARD_HDR), NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ throw std::string("Card: file corrupt");
+
+ bool bIsCardSupported = true;
+
+ switch(Card.Type)
+ {
+ case CT_Empty:
+ throw std::string("Card: todo");
+ break;
+ case CT_Disk2:
+ LoadCardDisk2();
+ break;
+ case CT_SSC:
+ LoadCardSSC();
+ break;
+ case CT_MockingboardC:
+ LoadCardMockingboardC();
+ break;
+ case CT_GenericPrinter:
+ LoadCardPrinter();
+ break;
+ case CT_GenericHDD:
+ LoadCardHDD();
+ break;
+ case CT_MouseInterface:
+ LoadCardMouseInterface();
+ break;
+ case CT_Z80:
+ throw std::string("Card: todo");
+ break;
+ case CT_Phasor:
+ throw std::string("Card: todo");
+ break;
+ default:
+ //throw std::string("Card: unsupported");
+ bIsCardSupported = false;
+ if (SetFilePointer(m_hFile, Card.UnitHdr.hdr.v2.Length, NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ throw std::string("Card: failed to skip unsupported card");
+ }
+
+ if (bIsCardSupported)
+ m_ConfigNew.m_Slot[Card.Slot] = (SS_CARDTYPE) Card.Type;
+}
+
+static void LoadUnitConfig(DWORD Length, DWORD Version)
+{
+ SS_APPLEWIN_CONFIG Cfg;
+
+ if (Version != UNIT_CONFIG_VER)
+ throw std::string("Config: Version mismatch");
+
+ if (Length != sizeof(Cfg))
+ throw std::string("Config: Length mismatch");
+
+ if (SetFilePointer(m_hFile, -(LONG)sizeof(Cfg.UnitHdr), NULL, FILE_CURRENT) == INVALID_SET_FILE_POINTER)
+ throw std::string("Config: file corrupt");
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( m_hFile,
+ &Cfg,
+ Length,
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != Length)
+ throw std::string("Config: file corrupt");
+
+ // todo:
+ //m_ConfigNew.m_bEnhanceDisk;
+ //m_ConfigNew.m_bEnableHDD;
+}
+
+static void Snapshot_LoadState_v2(DWORD dwVersion)
+{
+ try
+ {
+ if (dwVersion != MAKE_VERSION(2,0,0,0))
+ throw std::string("Version mismatch");
+
+ CConfigNeedingRestart ConfigOld;
+ ConfigOld.m_Slot[1] = CT_GenericPrinter; // fixme
+ ConfigOld.m_Slot[2] = CT_SSC; // fixme
+ ConfigOld.m_Slot[6] = CT_Disk2; // fixme
+ ConfigOld.m_Slot[7] = ConfigOld.m_bEnableHDD ? CT_GenericHDD : CT_Empty; // fixme
+
+ for (UINT i=0; iHdr.dwTag = AW_SS_TAG;
- pSS->Hdr.dwVersion = MAKE_VERSION(1,0,0,1);
- pSS->Hdr.dwChecksum = 0; // TO DO
+//-----------------------------------------------------------------------------
- //
- // Apple2 unit
- //
-
- pSS->Apple2Unit.UnitHdr.dwLength = sizeof(SS_APPLE2_Unit);
- pSS->Apple2Unit.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,0);
-
- CpuGetSnapshot(&pSS->Apple2Unit.CPU6502);
- sg_SSC.CommGetSnapshot(&pSS->Apple2Unit.Comms);
- JoyGetSnapshot(&pSS->Apple2Unit.Joystick);
- KeybGetSnapshot(&pSS->Apple2Unit.Keyboard);
- SpkrGetSnapshot(&pSS->Apple2Unit.Speaker);
- VideoGetSnapshot(&pSS->Apple2Unit.Video);
- MemGetSnapshot(&pSS->Apple2Unit.Memory);
-
- //
- // Slot1: Empty
- pSS->Empty1.Hdr.UnitHdr.dwLength = sizeof(SS_CARD_EMPTY);
- pSS->Empty1.Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,0);
- pSS->Empty1.Hdr.dwSlot = 1;
- pSS->Empty1.Hdr.dwType = CT_Empty;
-
- //
- // Slot2: Empty
- pSS->Empty2.Hdr.UnitHdr.dwLength = sizeof(SS_CARD_EMPTY);
- pSS->Empty2.Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,0);
- pSS->Empty2.Hdr.dwSlot = 2;
- pSS->Empty2.Hdr.dwType = CT_Empty;
-
- //
- // Slot3: Empty
- pSS->Empty3.Hdr.UnitHdr.dwLength = sizeof(SS_CARD_EMPTY);
- pSS->Empty3.Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,0);
- pSS->Empty3.Hdr.dwSlot = 3;
- pSS->Empty3.Hdr.dwType = CT_Empty;
-
- //
- // Slot4: Mockingboard
- MB_GetSnapshot(&pSS->Mockingboard1, 4);
-
- //
- // Slot5: Mockingboard
- MB_GetSnapshot(&pSS->Mockingboard2, 5);
-
- //
- // Slot6: Disk][
- DiskGetSnapshot(&pSS->Disk2, 6);
-
- //
-
- HANDLE hFile = CreateFile( g_strSaveStatePathname.c_str(),
- GENERIC_WRITE,
- 0,
- NULL,
- CREATE_ALWAYS,
- FILE_ATTRIBUTE_NORMAL,
- NULL);
-
- DWORD dwError = GetLastError();
- _ASSERT((dwError == 0) || (dwError == ERROR_ALREADY_EXISTS));
-
- if(hFile != INVALID_HANDLE_VALUE)
+void Snapshot_SaveState()
+{
+ try
{
+ // todo: append '.aws' if missing
+
+ m_hFile = CreateFile( g_strSaveStatePathname.c_str(),
+ GENERIC_WRITE,
+ 0,
+ NULL,
+ CREATE_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL);
+
+ DWORD dwError = GetLastError();
+ _ASSERT((dwError == 0) || (dwError == ERROR_ALREADY_EXISTS));
+
+ // todo: handle ERROR_ALREADY_EXISTS - ask if user wants to replace existing file
+
+ if(m_hFile == INVALID_HANDLE_VALUE)
+ {
+ //dwError = GetLastError();
+ throw std::string("Save error");
+ }
+
+ //
+
+ APPLEWIN_SNAPSHOT_v2 AppleSnapshotv2;
+
+ AppleSnapshotv2.Hdr.dwTag = AW_SS_TAG;
+ AppleSnapshotv2.Hdr.dwVersion = MAKE_VERSION(2,0,0,0);
+ AppleSnapshotv2.Hdr.dwChecksum = 0; // TO DO
+
+ SS_APPLE2_Unit_v2& Apple2Unit = AppleSnapshotv2.Apple2Unit;
+
+ //
+ // Apple2 unit
+ //
+
+ Apple2Unit.UnitHdr.hdr.v2.Length = sizeof(SS_APPLE2_Unit_v2);
+ Apple2Unit.UnitHdr.hdr.v2.Type = UT_Apple2;
+ Apple2Unit.UnitHdr.hdr.v2.Version = UNIT_APPLE2_VER;
+
+ Apple2Unit.Apple2Type = g_Apple2Type;
+
+ CpuGetSnapshot(Apple2Unit.CPU6502);
+ JoyGetSnapshot(Apple2Unit.Joystick.JoyCntrResetCycle);
+ KeybGetSnapshot(Apple2Unit.Keyboard.LastKey);
+ SpkrGetSnapshot(Apple2Unit.Speaker.SpkrLastCycle);
+ VideoGetSnapshot(Apple2Unit.Video);
+ MemGetSnapshot(Apple2Unit.Memory);
+
DWORD dwBytesWritten;
- BOOL bRes = WriteFile( hFile,
- pSS,
- sizeof(APPLEWIN_SNAPSHOT),
+ BOOL bRes = WriteFile( m_hFile,
+ &AppleSnapshotv2,
+ sizeof(APPLEWIN_SNAPSHOT_v2),
&dwBytesWritten,
NULL);
- if(!bRes || (dwBytesWritten != sizeof(APPLEWIN_SNAPSHOT)))
- dwError = GetLastError();
+ if(!bRes || (dwBytesWritten != sizeof(APPLEWIN_SNAPSHOT_v2)))
+ {
+ //dwError = GetLastError();
+ throw std::string("Save error");
+ }
- CloseHandle(hFile);
+ //
+
+ Printer_GetSnapshot(m_hFile);
+
+ sg_SSC.GetSnapshot(m_hFile);
+
+ sg_Mouse.GetSnapshot(m_hFile);
+
+ if (g_Slot4 == CT_MockingboardC)
+ MB_GetSnapshot(m_hFile, 4);
+
+ if (g_Slot5 == CT_MockingboardC)
+ MB_GetSnapshot(m_hFile, 5);
+
+ DiskGetSnapshot(m_hFile);
+
+ HD_GetSnapshot(m_hFile);
}
- else
+ catch(std::string szMessage)
{
- dwError = GetLastError();
+ MessageBox( g_hFrameWindow,
+ szMessage.c_str(),
+ TEXT("Save State"),
+ MB_ICONEXCLAMATION | MB_SETFOREGROUND);
}
- _ASSERT((dwError == 0) || (dwError == ERROR_ALREADY_EXISTS));
-
- delete [] pSS;
+ CloseHandle(m_hFile);
+ m_hFile = INVALID_HANDLE_VALUE;
}
//-----------------------------------------------------------------------------
diff --git a/source/SaveState_Structs_common.h b/source/SaveState_Structs_common.h
new file mode 100644
index 00000000..3732d558
--- /dev/null
+++ b/source/SaveState_Structs_common.h
@@ -0,0 +1,77 @@
+#pragma once
+
+// Structs used by save-state file
+
+// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT ***
+
+/////////////////////////////////////////////////////////////////////////////////
+
+#define MAKE_VERSION(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | (d))
+
+#define AW_SS_TAG 'SSWA' // 'AWSS' = AppleWin SnapShot
+
+struct SS_FILE_HDR
+{
+ DWORD dwTag; // "AWSS"
+ DWORD dwVersion;
+ DWORD dwChecksum;
+};
+
+struct SS_UNIT_HDR
+{
+ union
+ {
+ struct
+ {
+ DWORD dwLength; // Byte length of this unit struct
+ DWORD dwVersion;
+ } v1;
+ struct
+ {
+ DWORD Length; // Byte length of this unit struct
+ WORD Type; // SS_UNIT_TYPE
+ WORD Version; // Incrementing value from 1
+ } v2;
+ } hdr;
+};
+
+enum SS_UNIT_TYPE
+{
+ UT_Reserved = 0,
+ UT_Apple2,
+ UT_Card,
+ UT_Config,
+};
+
+const UINT nMemMainSize = 64*1024;
+const UINT nMemAuxSize = 64*1024;
+
+struct SS_CARD_HDR
+{
+ SS_UNIT_HDR UnitHdr;
+ DWORD Type; // SS_CARDTYPE
+ DWORD Slot; // [1..7], 0=Language card, 8=Aux
+};
+
+enum SS_CARDTYPE
+{
+ CT_Empty = 0,
+ CT_Disk2, // Apple Disk][
+ CT_SSC, // Apple Super Serial Card
+ CT_MockingboardC, // Soundcard
+ CT_GenericPrinter,
+ CT_GenericHDD, // Hard disk
+ CT_GenericClock,
+ CT_MouseInterface,
+ CT_Z80,
+ CT_Phasor, // Soundcard
+ CT_Echo, // Soundcard
+ CT_SAM, // Soundcard: Software Automated Mouth
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+struct SS_CARD_EMPTY
+{
+ SS_CARD_HDR Hdr;
+};
diff --git a/source/Structs.h b/source/SaveState_Structs_v1.h
similarity index 56%
rename from source/Structs.h
rename to source/SaveState_Structs_v1.h
index f2af25ac..f4c84645 100644
--- a/source/Structs.h
+++ b/source/SaveState_Structs_v1.h
@@ -1,34 +1,15 @@
#pragma once
#include "DiskDefs.h"
+#include "SaveState_Structs_common.h"
-// Structs used by save-state file
+// Structs used by save-state file v1
// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT ***
-#define MAKE_VERSION(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | (d))
-
-#define AW_SS_TAG 'SSWA' // 'AWSS' = AppleWin SnapShot
-
-typedef struct
-{
- DWORD dwTag; // "AWSS"
- DWORD dwVersion;
- DWORD dwChecksum;
-} SS_FILE_HDR;
-
-typedef struct
-{
- DWORD dwLength; // Byte length of this unit struct
- DWORD dwVersion;
-} SS_UNIT_HDR;
-
/////////////////////////////////////////////////////////////////////////////////
-const UINT nMemMainSize = 64*1024;
-const UINT nMemAuxSize = 64*1024;
-
-typedef struct
+struct SS_CPU6502
{
BYTE A;
BYTE X;
@@ -36,13 +17,13 @@ typedef struct
BYTE P;
BYTE S;
USHORT PC;
- unsigned __int64 g_nCumulativeCycles;
+ unsigned __int64 nCumulativeCycles;
// IRQ = OR-sum of all interrupt sources
-} SS_CPU6502;
+};
const UINT uRecvBufferSize = 9;
-typedef struct
+struct SS_IO_Comms
{
DWORD baudrate;
BYTE bytesize;
@@ -53,121 +34,53 @@ typedef struct
BYTE recvbuffer[uRecvBufferSize];
DWORD recvbytes;
BYTE stopbits;
-} SS_IO_Comms;
+};
-typedef struct
+struct SS_IO_Joystick
{
- unsigned __int64 g_nJoyCntrResetCycle;
-} SS_IO_Joystick;
+ unsigned __int64 nJoyCntrResetCycle;
+};
-typedef struct
+struct SS_IO_Keyboard
{
DWORD keyboardqueries;
BYTE nLastKey;
-} SS_IO_Keyboard;
+};
-//typedef struct
-//{
-//} SS_IO_Memory;
-
-typedef struct
+struct SS_IO_Speaker
{
- unsigned __int64 g_nSpkrLastCycle;
-} SS_IO_Speaker;
+ unsigned __int64 nSpkrLastCycle;
+};
-typedef struct
+struct SS_IO_Video
{
bool bAltCharSet; // charoffs
DWORD dwVidMode;
-} SS_IO_Video;
+};
-typedef struct
+struct SS_BaseMemory
{
DWORD dwMemMode;
BOOL bLastWriteRam;
BYTE nMemMain[nMemMainSize];
BYTE nMemAux[nMemAuxSize];
-} SS_BaseMemory;
+};
-typedef struct
+struct SS_APPLE2_Unit
{
SS_UNIT_HDR UnitHdr;
SS_CPU6502 CPU6502;
SS_IO_Comms Comms;
SS_IO_Joystick Joystick;
SS_IO_Keyboard Keyboard;
-// SS_IO_Memory Memory;
SS_IO_Speaker Speaker;
SS_IO_Video Video;
SS_BaseMemory Memory;
-} SS_APPLE2_Unit;
-
-/////////////////////////////////////////////////////////////////////////////////
-
-typedef struct
-{
- DWORD dwComputerEmulation;
- bool bCustomSpeed;
- DWORD dwEmulationSpeed;
- bool bEnhancedDiskSpeed;
- DWORD dwJoystickType[2];
- bool bMockingboardEnabled;
- DWORD dwMonochromeColor;
- DWORD dwSerialPort;
- DWORD dwSoundType; // Sound Emulation
- DWORD dwVideoType; // Video Emulation
-} SS_AW_CFG;
-
-typedef struct
-{
- char StartingDir[MAX_PATH];
- DWORD dwWindowXpos;
- DWORD dwWindowYpos;
-} SS_AW_PREFS;
-
-typedef struct
-{
- SS_UNIT_HDR UnitHdr;
- DWORD dwAppleWinVersion;
- SS_AW_PREFS Prefs;
- SS_AW_CFG Cfg;
-} SS_APPLEWIN_CONFIG;
-
-/////////////////////////////////////////////////////////////////////////////////
-
-typedef struct
-{
- SS_UNIT_HDR UnitHdr;
- DWORD dwType; // SS_CARDTYPE
- DWORD dwSlot; // [1..7]
-} SS_CARD_HDR;
-
-enum SS_CARDTYPE
-{
- CT_Empty = 0,
- CT_Disk2, // Apple Disk][
- CT_SSC, // Apple Super Serial Card
- CT_MockingboardC, // Soundcard
- CT_GenericPrinter,
- CT_GenericHDD, // Hard disk
- CT_GenericClock,
- CT_MouseInterface,
- CT_Z80,
- CT_Phasor, // Soundcard
- CT_Echo, // Soundcard
- CT_SAM, // Soundcard: Software Automated Mouth
};
/////////////////////////////////////////////////////////////////////////////////
-typedef struct
-{
- SS_CARD_HDR Hdr;
-} SS_CARD_EMPTY;
-
-/////////////////////////////////////////////////////////////////////////////////
-
-typedef struct
+struct DISK2_Unit
{
char szFileName[MAX_PATH];
int track;
@@ -180,9 +93,9 @@ typedef struct
DWORD writelight;
int nibbles;
BYTE nTrack[NIBBLES_PER_TRACK];
-} DISK2_Unit;
+};
-typedef struct
+struct SS_CARD_DISK2
{
SS_CARD_HDR Hdr;
DISK2_Unit Unit[2];
@@ -193,11 +106,11 @@ typedef struct
BYTE floppylatch;
BOOL floppymotoron;
BOOL floppywritemode;
-} SS_CARD_DISK2;
+};
/////////////////////////////////////////////////////////////////////////////////
-typedef struct
+struct IWORD
{
union
{
@@ -208,9 +121,9 @@ typedef struct
};
USHORT w;
};
-} IWORD;
+};
-typedef struct
+struct SY6522
{
BYTE ORB; // $00 - Port B
BYTE ORA; // $01 - Port A (with handshaking)
@@ -234,9 +147,9 @@ typedef struct
BYTE IFR; // $0D - Interrupt Flag Register
BYTE IER; // $0E - Interrupt Enable Register
BYTE ORA_NO_HS; // $0F - Port A (without handshaking)
-} SY6522;
+};
-typedef struct
+struct SSI263A
{
BYTE DurationPhonome;
BYTE Inflection; // I10..I3
@@ -245,9 +158,9 @@ typedef struct
BYTE FilterFreq;
//
BYTE CurrentMode; // b7:6=Mode; b0=D7 pin (for IRQ)
-} SSI263A;
+};
-typedef struct
+struct MB_Unit
{
SY6522 RegsSY6522;
BYTE RegsAY8910[16];
@@ -256,23 +169,22 @@ typedef struct
bool bTimer1IrqPending;
bool bTimer2IrqPending;
bool bSpeechIrqPending;
-} MB_Unit;
+};
const UINT MB_UNITS_PER_CARD = 2;
-typedef struct
+struct SS_CARD_MOCKINGBOARD
{
SS_CARD_HDR Hdr;
MB_Unit Unit[MB_UNITS_PER_CARD];
-} SS_CARD_MOCKINGBOARD;
+};
/////////////////////////////////////////////////////////////////////////////////
-typedef struct
+struct APPLEWIN_SNAPSHOT_v1
{
SS_FILE_HDR Hdr;
SS_APPLE2_Unit Apple2Unit;
-// SS_APPLEWIN_CONFIG AppleWinCfg;
SS_CARD_EMPTY Empty1; // Slot1
SS_CARD_EMPTY Empty2; // Slot2
SS_CARD_EMPTY Empty3; // Slot3
@@ -280,6 +192,6 @@ typedef struct
SS_CARD_MOCKINGBOARD Mockingboard2; // Slot5
SS_CARD_DISK2 Disk2; // Slot6
SS_CARD_EMPTY Empty7; // Slot7
-} APPLEWIN_SNAPSHOT;
+};
-/////////////////////////////////////////////////////////////////////////////////
+const UINT kSnapshotSize_v1 = 145400; // Const size for v1
diff --git a/source/SaveState_Structs_v2.h b/source/SaveState_Structs_v2.h
new file mode 100644
index 00000000..cec392cf
--- /dev/null
+++ b/source/SaveState_Structs_v2.h
@@ -0,0 +1,114 @@
+#pragma once
+
+#include "SaveState_Structs_common.h"
+
+// Structs used by save-state file v2
+
+// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT ***
+
+/////////////////////////////////////////////////////////////////////////////////
+
+struct SS_CPU6502_v2
+{
+ BYTE A;
+ BYTE X;
+ BYTE Y;
+ BYTE P;
+ BYTE S;
+ USHORT PC;
+ unsigned __int64 CumulativeCycles;
+ // IRQ = OR-sum of all interrupt sources
+};
+
+struct SS_IO_Joystick_v2
+{
+ unsigned __int64 JoyCntrResetCycle;
+};
+
+struct SS_IO_Keyboard_v2
+{
+ BYTE LastKey;
+};
+
+struct SS_IO_Speaker_v2
+{
+ unsigned __int64 SpkrLastCycle;
+};
+
+struct SS_IO_Video_v2
+{
+ UINT32 AltCharSet;
+ UINT32 VideoMode;
+ UINT32 CyclesThisVideoFrame;
+};
+
+struct SS_BaseMemory_v2
+{
+ DWORD dwMemMode;
+ BOOL bLastWriteRam;
+ BYTE MemMain[nMemMainSize];
+ BYTE MemAux[nMemAuxSize];
+};
+
+struct SS_APPLE2_Unit_v2
+{
+ SS_UNIT_HDR UnitHdr;
+ UINT32 Apple2Type;
+ SS_CPU6502_v2 CPU6502;
+ SS_IO_Joystick_v2 Joystick;
+ SS_IO_Keyboard_v2 Keyboard;
+ SS_IO_Speaker_v2 Speaker;
+ SS_IO_Video_v2 Video;
+ SS_BaseMemory_v2 Memory;
+};
+
+/////////////////////////////////////////////////////////////////////////////////
+
+#pragma pack(push,4) // push current alignment to stack & set alignment to 4
+ // - need so that 12-byte Hdr doesn't get padded to 16 bytes
+ // - NB. take care not to affect the old v2 structs
+
+struct APPLEWIN_SNAPSHOT_v2
+{
+ SS_FILE_HDR Hdr;
+ SS_APPLE2_Unit_v2 Apple2Unit;
+// SS_CARD_EMPTY[7] Slots; // Slot 0..7 (0=language card for Apple][)
+// SS_CARD_EMPTY AuxSlot; // Apple//e auxiliary slot (including optional RAMworks memory)
+// SS_APPLEWIN_CONFIG AppleWinCfg;
+};
+
+#pragma pack(pop)
+
+/////////////////////////////////////////////////////////////////////////////////
+
+struct SS_AW_CFG
+{
+ UINT32 AppleWinVersion;
+ UINT32 VideoMode;
+ UINT32 MonochromeColor;
+ float ClockFreqMHz;
+ //
+ UINT32 JoystickType[2];
+ UINT32 JoystickTrim[2];
+ UINT32 IsAllowCursorsToBeRead;
+ UINT32 IsAutofire;
+ UINT32 IsKeyboardAutocentering;
+ UINT32 IsSwapButton0and1;
+ //
+ UINT32 SpeakerVolume;
+ UINT32 MockingboardVolume;
+ //
+ UINT32 IsEnhancedDiskSpeed;
+ //
+ UINT32 IsEncodingConversionForClones;
+ UINT32 IsFilterUnprintableChars;
+ UINT32 IsAppendToFile;
+ UINT32 TerminatePrintingAfterIdleSecs;
+ UINT32 IsUsingFreezesF8Rom;
+};
+
+struct SS_APPLEWIN_CONFIG
+{
+ SS_UNIT_HDR UnitHdr;
+ SS_AW_CFG Cfg;
+};
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index 77b55f91..ec91f4af 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -72,7 +72,8 @@ SSC_DIPSW CSuperSerialCard::m_DIPSWDefault =
CSuperSerialCard::CSuperSerialCard() :
m_aySerialPortChoices(NULL),
- m_uTCPChoiceItemIdx(0)
+ m_uTCPChoiceItemIdx(0),
+ m_uSlot(0)
{
memset(m_ayCurrentSerialPortName, 0, sizeof(m_ayCurrentSerialPortName));
m_dwSerialPortItem = 0;
@@ -831,6 +832,8 @@ void CSuperSerialCard::CommInitialize(LPBYTE pCxRomPeripheral, UINT uSlot)
memcpy(pCxRomPeripheral + uSlot*256, pData+SSC_SLOT_FW_OFFSET, SSC_SLOT_FW_SIZE);
+ m_uSlot = uSlot;
+
// Expansion ROM
if (m_pExpansionRom == NULL)
{
@@ -1293,30 +1296,144 @@ void CSuperSerialCard::SetSerialPortName(const char* pSerialPortName)
//===========================================================================
-DWORD CSuperSerialCard::CommGetSnapshot(SS_IO_Comms* pSS)
+void CSuperSerialCard::SetSnapshot_v1( const DWORD baudrate,
+ const BYTE bytesize,
+ const BYTE commandbyte,
+ const DWORD comminactivity,
+ const BYTE controlbyte,
+ const BYTE parity,
+ const BYTE stopbits)
{
- pSS->baudrate = m_uBaudRate;
- pSS->bytesize = m_uByteSize;
- pSS->commandbyte = m_uCommandByte;
- pSS->comminactivity = m_dwCommInactivity;
- pSS->controlbyte = m_uControlByte;
- pSS->parity = m_uParity;
-// memcpy(pSS->recvbuffer, m_RecvBuffer, uRecvBufferSize);
- pSS->recvbytes = 0;
- pSS->stopbits = m_uStopBits;
- return 0;
+ m_uBaudRate = baudrate;
+ m_uByteSize = bytesize;
+ m_uCommandByte = commandbyte;
+ m_dwCommInactivity = comminactivity;
+ m_uControlByte = controlbyte;
+ m_uParity = parity;
+// memcpy(m_RecvBuffer, pSS->recvbuffer, uRecvBufferSize);
+// m_vRecvBytes = recvbytes;
+ m_uStopBits = stopbits;
}
-DWORD CSuperSerialCard::CommSetSnapshot(SS_IO_Comms* pSS)
+//===========================================================================
+
+struct SSC_Unit
{
- m_uBaudRate = pSS->baudrate;
- m_uByteSize = pSS->bytesize;
- m_uCommandByte = pSS->commandbyte;
- m_dwCommInactivity = pSS->comminactivity;
- m_uControlByte = pSS->controlbyte;
- m_uParity = pSS->parity;
-// memcpy(m_RecvBuffer, pSS->recvbuffer, uRecvBufferSize);
-// m_vRecvBytes = pSS->recvbytes;
- m_uStopBits = pSS->stopbits;
+ SSC_DIPSW DIPSWDefault;
+ SSC_DIPSW DIPSWCurrent;
+
+ DWORD uBaudRate;
+
+ BYTE uStopBits;
+ BYTE uByteSize;
+ BYTE uParity;
+
+ BYTE uControlByte;
+ BYTE uCommandByte;
+
+ DWORD dwCommInactivity; // If non-zero then COM port open
+
+ bool bTxIrqEnabled;
+ bool bRxIrqEnabled;
+
+ bool vbTxIrqPending;
+ bool vbRxIrqPending;
+
+ bool bWrittenTx;
+};
+
+struct SS_CARD_SSC
+{
+ SS_CARD_HDR Hdr;
+ SSC_Unit Unit;
+};
+
+// Post:
+// 0 = No card
+// >0 = Card saved OK from slot n
+// -1 = File error
+int CSuperSerialCard::GetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_SSC CardSuperSerial;
+
+ CardSuperSerial.Hdr.UnitHdr.hdr.v2.Length = sizeof(SS_CARD_SSC);
+ CardSuperSerial.Hdr.UnitHdr.hdr.v2.Type = UT_Card;
+ CardSuperSerial.Hdr.UnitHdr.hdr.v2.Version = 1;
+
+ CardSuperSerial.Hdr.Slot = m_uSlot;
+ CardSuperSerial.Hdr.Type = CT_SSC;
+
+ SSC_Unit& Unit = CardSuperSerial.Unit;
+
+ Unit.DIPSWDefault = m_DIPSWDefault;
+ Unit.DIPSWCurrent = m_DIPSWCurrent;
+ Unit.uBaudRate = m_uBaudRate;
+ Unit.uStopBits = m_uStopBits;
+ Unit.uByteSize = m_uByteSize;
+ Unit.uParity = m_uParity;
+ Unit.uControlByte = m_uControlByte;
+ Unit.uCommandByte = m_uCommandByte;
+ Unit.dwCommInactivity = m_dwCommInactivity;
+ Unit.bTxIrqEnabled = m_bTxIrqEnabled;
+ Unit.bRxIrqEnabled = m_bRxIrqEnabled;
+ Unit.vbTxIrqPending = m_vbTxIrqPending;
+ Unit.vbRxIrqPending = m_vbRxIrqPending;
+ Unit.bWrittenTx = m_bWrittenTx;
+
+ //
+
+ DWORD dwBytesWritten;
+ BOOL bRes = WriteFile( hFile,
+ &CardSuperSerial,
+ CardSuperSerial.Hdr.UnitHdr.hdr.v2.Length,
+ &dwBytesWritten,
+ NULL);
+
+ if(!bRes || (dwBytesWritten != CardSuperSerial.Hdr.UnitHdr.hdr.v2.Length))
+ throw std::string("Save error: SSC");
+
+ return m_uSlot;
+}
+
+int CSuperSerialCard::SetSnapshot(const HANDLE hFile)
+{
+ SS_CARD_SSC CardSuperSerial;
+
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( hFile,
+ &CardSuperSerial,
+ sizeof(CardSuperSerial),
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != sizeof(CardSuperSerial))
+ throw std::string("Card: file corrupt");
+
+ if (CardSuperSerial.Hdr.Slot != 2) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (CardSuperSerial.Hdr.UnitHdr.hdr.v2.Version != 1)
+ throw std::string("Card: wrong version");
+
+ if (CardSuperSerial.Hdr.UnitHdr.hdr.v2.Length != sizeof(SS_CARD_SSC))
+ throw std::string("Card: unit size mismatch");
+
+ SSC_Unit& Unit = CardSuperSerial.Unit;
+
+ m_DIPSWDefault = Unit.DIPSWDefault;
+ m_DIPSWCurrent = Unit.DIPSWCurrent;
+ m_uBaudRate = Unit.uBaudRate;
+ m_uStopBits = Unit.uStopBits;
+ m_uByteSize = Unit.uByteSize;
+ m_uParity = Unit.uParity;
+ m_uControlByte = Unit.uControlByte;
+ m_uCommandByte = Unit.uCommandByte;
+ m_dwCommInactivity = Unit.dwCommInactivity;
+ m_bTxIrqEnabled = Unit.bTxIrqEnabled;
+ m_bRxIrqEnabled = Unit.bRxIrqEnabled;
+ m_vbTxIrqPending = Unit.vbTxIrqPending;
+ m_vbRxIrqPending = Unit.vbRxIrqPending;
+ m_bWrittenTx = Unit.bWrittenTx;
+
return 0;
}
diff --git a/source/SerialComms.h b/source/SerialComms.h
index d75d2ea9..7be33799 100644
--- a/source/SerialComms.h
+++ b/source/SerialComms.h
@@ -33,8 +33,9 @@ public:
void CommDestroy();
void CommSetSerialPort(HWND hWindow, DWORD dwNewSerialPortItem);
void CommUpdate(DWORD);
- DWORD CommGetSnapshot(SS_IO_Comms* pSS);
- DWORD CommSetSnapshot(SS_IO_Comms* pSS);
+ void SetSnapshot_v1(const DWORD baudrate, const BYTE bytesize, const BYTE commandbyte, const DWORD comminactivity, const BYTE controlbyte, const BYTE parity, const BYTE stopbits);
+ int GetSnapshot(const HANDLE hFile);
+ int SetSnapshot(const HANDLE hFile);
char* GetSerialPortChoices();
DWORD GetSerialPort() { return m_dwSerialPortItem; } // Drop-down list item
@@ -134,4 +135,5 @@ private:
OVERLAPPED m_o;
BYTE* m_pExpansionRom;
+ UINT m_uSlot;
};
diff --git a/source/Speaker.cpp b/source/Speaker.cpp
index 3608ecd6..da574207 100644
--- a/source/Speaker.cpp
+++ b/source/Speaker.cpp
@@ -1080,14 +1080,19 @@ void Spkr_DSUninit()
//=============================================================================
-DWORD SpkrGetSnapshot(SS_IO_Speaker* pSS)
+void SpkrSetSnapshot_v1(const unsigned __int64 SpkrLastCycle)
{
- pSS->g_nSpkrLastCycle = g_nSpkrLastCycle;
- return 0;
+ g_nSpkrLastCycle = SpkrLastCycle;
}
-DWORD SpkrSetSnapshot(SS_IO_Speaker* pSS)
+//
+
+void SpkrGetSnapshot(unsigned __int64& rSpkrLastCycle)
{
- g_nSpkrLastCycle = pSS->g_nSpkrLastCycle;
- return 0;
+ rSpkrLastCycle = g_nSpkrLastCycle;
+}
+
+void SpkrSetSnapshot(const unsigned __int64 SpkrLastCycle)
+{
+ g_nSpkrLastCycle = SpkrLastCycle;
}
diff --git a/source/Speaker.h b/source/Speaker.h
index 8e93fbbe..d4b960d2 100644
--- a/source/Speaker.h
+++ b/source/Speaker.h
@@ -19,7 +19,8 @@ void Spkr_Demute();
bool Spkr_IsActive();
bool Spkr_DSInit();
void Spkr_DSUninit();
-DWORD SpkrGetSnapshot(SS_IO_Speaker* pSS);
-DWORD SpkrSetSnapshot(SS_IO_Speaker* pSS);
+void SpkrSetSnapshot_v1(const unsigned __int64 SpkrLastCycle);
+void SpkrGetSnapshot(unsigned __int64& rSpkrLastCycle);
+void SpkrSetSnapshot(const unsigned __int64 SpkrLastCycle);
BYTE __stdcall SpkrToggle (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
diff --git a/source/StdAfx.h b/source/StdAfx.h
index 2e0d77a7..bcbbd3c8 100644
--- a/source/StdAfx.h
+++ b/source/StdAfx.h
@@ -23,7 +23,6 @@
#include
#include
#include
-#include
#include
#include
@@ -36,6 +35,7 @@
#include
#include