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 #include +#include #include // SM_CXPADDEDBORDER is not supported on 2000 & XP: diff --git a/source/Video.cpp b/source/Video.cpp index 8f9cbd95..7030f290 100644 --- a/source/Video.cpp +++ b/source/Video.cpp @@ -39,6 +39,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #include "..\resource\resource.h" #include "Configuration\PropertySheet.h" #include "Debugger\Debugger_Color.h" // For NUM_DEBUG_COLORS +#include "SaveState_Structs_v2.h" #define HALF_PIXEL_SOLID 1 #define HALF_PIXEL_BLEED 0 @@ -2941,20 +2942,26 @@ void VideoSetForceFullRedraw(void) //=========================================================================== -DWORD VideoGetSnapshot(SS_IO_Video* pSS) +void VideoSetSnapshot_v1(const UINT AltCharSet, const UINT VideoMode) { - pSS->bAltCharSet = !(g_nAltCharSetOffset == 0); - pSS->dwVidMode = g_uVideoMode; - return 0; + g_nAltCharSetOffset = !AltCharSet ? 0 : 256; + g_uVideoMode = VideoMode; } -//=========================================================================== +// -DWORD VideoSetSnapshot(SS_IO_Video* pSS) +void VideoGetSnapshot(SS_IO_Video_v2& Video) { - g_nAltCharSetOffset = !pSS->bAltCharSet ? 0 : 256; - g_uVideoMode = pSS->dwVidMode; - return 0; + Video.AltCharSet = !(g_nAltCharSetOffset == 0); + Video.VideoMode = g_uVideoMode; + Video.CyclesThisVideoFrame = g_dwCyclesThisFrame; +} + +void VideoSetSnapshot(const SS_IO_Video_v2& Video) +{ + g_nAltCharSetOffset = !Video.AltCharSet ? 0 : 256; + g_uVideoMode = Video.VideoMode; + g_dwCyclesThisFrame = Video.CyclesThisVideoFrame; } //=========================================================================== diff --git a/source/Video.h b/source/Video.h index 9aa270b9..93f179f5 100644 --- a/source/Video.h +++ b/source/Video.h @@ -85,8 +85,9 @@ bool VideoGetSWAltCharSet(void); void VideoSetForceFullRedraw(void); -DWORD VideoGetSnapshot(SS_IO_Video* pSS); -DWORD VideoSetSnapshot(SS_IO_Video* pSS); +void VideoSetSnapshot_v1(const UINT AltCharSet, const UINT VideoMode); +void VideoGetSnapshot(struct SS_IO_Video_v2& Video); +void VideoSetSnapshot(const struct SS_IO_Video_v2& Video); void _Video_Dirty(); void _Video_RedrawScreen( VideoUpdateFuncPtr_t update, bool bMixed = false );