New save-state (.aws) v2:

. Format now extensible for supporting new hardware types in the future
. Include missing items like Apple2Type, CyclesThisVideoFrame (#255)
Continue to support loading of old v1 format.

Added card save/load for:
. Mouse (#260)
. HDD (#260)
. Printer

Extended card support for:
. SSC

Other:
. Added save-state v1 struct size checks
. Create SaveState_Structs_v2.h and split out common into SaveState_Structs_common.h
. Refactor HardDisk.cpp to use imagehandle; and consolidate with Disk.cpp
. Fix Disk/HD_GetFullPathName() which wasn't always returning full pathname
. Consolidate common GetImageTitle() and move into DiskImage.cpp
This commit is contained in:
tomcw 2015-02-13 22:40:53 +00:00
parent 0fc6d18139
commit 717c5cba84
48 changed files with 2195 additions and 756 deletions

View File

@ -755,11 +755,19 @@
>
</File>
<File
RelativePath=".\source\SSI263Phonemes.h"
RelativePath=".\source\SaveState_Structs_common.h"
>
</File>
<File
RelativePath=".\source\Structs.h"
RelativePath=".\source\SaveState_Structs_v1.h"
>
</File>
<File
RelativePath=".\source\SaveState_Structs_v2.h"
>
</File>
<File
RelativePath=".\source\SSI263Phonemes.h"
>
</File>
</Filter>

View File

@ -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*/);

View File

@ -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)

View File

@ -1,6 +1,6 @@
#pragma once
#include "Structs.h"
#include "SaveState_Structs_common.h"
#include "Common.h"
void SetCurrentCLK6502();

View File

@ -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;
}

View File

@ -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);

View File

@ -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,

View File

@ -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);

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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); }

View File

@ -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");

View File

@ -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);

View File

@ -4285,7 +4285,7 @@ Update_t CmdMemoryLoad (int nArgs)
if (bBankSpecified)
{
MemUpdatePaging(1);
MemUpdatePaging(TRUE);
}
else
{

View File

@ -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"

View File

@ -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;

View File

@ -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 ]; // <FILENAME> (ie. no extension)
TCHAR fullname [ MAX_DISK_FULL_NAME + 1 ]; // <FILENAME.EXT> or <FILENAME.zip> : This is persisted to the snapshot file
std::string strDiskPathFilename;
std::string strFilenameInZip; // 0x00 or <FILENAME.EXT>
std::string strFilenameInZip; // "" or <FILENAME.EXT>
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 = <FILENAME.EXT>
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 = <FILENAME.EXT>
_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 = <FILENAME> (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; i<NUM_DRIVES; i++)
{
strcpy(pSS->Unit[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; i<NUM_DRIVES; i++)
{
strcpy(pSS->Unit[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; i<NUM_DRIVES; i++)
{
DiskEject(i); // Remove any disk & update Registry to reflect empty drive
ZeroMemory(&g_aFloppyDisk[i], sizeof(Disk_t ));
}
bool bResSelectImage = false;
for(UINT i=0; i<NUM_DRIVES; i++)
{
if(pSS->Unit[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);
}

View File

@ -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);

View File

@ -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 = <FILENAME.EXT>
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 = <FILENAME.EXT>
_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 = <FILENAME> (ie. no extension)
_tcsncpy( pImageName, imagetitle, MAX_DISK_IMAGE_NAME );
pImageName[ MAX_DISK_IMAGE_NAME ] = 0;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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();

View File

@ -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 ]; // <FILENAME> (ie. no extension) [not used]
TCHAR fullname[ MAX_DISK_FULL_NAME + 1 ]; // <FILENAME.EXT> or <FILENAME.zip>
std::string strFilenameInZip; // "" or <FILENAME.EXT> [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 = <FILENAME.EXT>
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 = <FILENAME.EXT>
_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 = <FILENAME> (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<HARDDISK_2; i++)
{
HD_CleanupDrive(i);
}
g_bSaveDiskImage = false;
HD_CleanupDrive(HARDDISK_1);
g_bSaveDiskImage = false;
HD_CleanupDrive(HARDDISK_2);
g_bSaveDiskImage = true;
}
// pszImageFilename is qualified with path
BOOL HD_InsertDisk(const int iDrive, LPCTSTR pszImageFilename)
static BOOL HD_Insert(const int iDrive, LPCTSTR pszImageFilename)
{
if (*pszImageFilename == 0x00)
return false;
return FALSE;
if (g_HardDisk[iDrive].hd_imageloaded)
HD_CleanupDrive(iDrive);
HD_Unplug(iDrive);
// Check if image is being used by the other HDD, and unplug it in order to be swapped
if (!strcmp(HD_GetFullPathName(!iDrive), pszImageFilename)) {
HD_Unplug(!iDrive);
{
const char* pszOtherPathname = HD_GetFullPathName(!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))
{
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<NUM_HARDDISKS; i++)
{
strcpy(CardHDD.Unit[i].szFilename, g_HardDisk[i].fullname);
CardHDD.Unit[i].error = g_HardDisk[i].hd_error;
CardHDD.Unit[i].memblock = g_HardDisk[i].hd_memblock;
CardHDD.Unit[i].diskblock = g_HardDisk[i].hd_diskblock;
CardHDD.Unit[i].buf_ptr = g_HardDisk[i].hd_buf_ptr;
CardHDD.Unit[i].imageloaded = g_HardDisk[i].hd_imageloaded;
memcpy(CardHDD.Unit[i].buf, g_HardDisk[i].hd_buf, sizeof(CardHDD.Unit[i].buf));
CardHDD.Unit[i].status_next = g_HardDisk[i].hd_status_next;
CardHDD.Unit[i].status_prev = g_HardDisk[i].hd_status_prev;
}
//
DWORD dwBytesWritten;
BOOL bRes = WriteFile( hFile,
&CardHDD,
CardHDD.Hdr.UnitHdr.hdr.v2.Length,
&dwBytesWritten,
NULL);
if(!bRes || (dwBytesWritten != CardHDD.Hdr.UnitHdr.hdr.v2.Length))
{
//dwError = GetLastError();
throw std::string("Save error: HDD");
}
}
void HD_SetSnapshot(const HANDLE hFile, const std::string strSaveStatePath)
{
SS_CARD_HDD CardHDD;
DWORD dwBytesRead;
BOOL bRes = ReadFile( hFile,
&CardHDD,
sizeof(CardHDD),
&dwBytesRead,
NULL);
if (dwBytesRead != sizeof(CardHDD))
throw std::string("Card: file corrupt");
if (CardHDD.Hdr.Slot != 7) // fixme
throw std::string("Card: wrong slot");
if (CardHDD.Hdr.UnitHdr.hdr.v2.Version > 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; i<NUM_HARDDISKS; i++)
{
HD_Unplug(i);
ZeroMemory(&g_HardDisk[i], sizeof(HDD));
}
bool bResSelectImage = false;
for (UINT i=0; i<NUM_HARDDISKS; i++)
{
if (CardHDD.Unit[i].szFilename[0] == 0x00)
continue;
DWORD dwAttributes = GetFileAttributes(CardHDD.Unit[i].szFilename);
if (dwAttributes == INVALID_FILE_ATTRIBUTES)
{
// Get user to browse for file
bResSelectImage = HD_SelectImage(i, CardHDD.Unit[i].szFilename);
dwAttributes = GetFileAttributes(CardHDD.Unit[i].szFilename);
}
bool bImageError = (dwAttributes == INVALID_FILE_ATTRIBUTES);
if (!bImageError)
{
if (!HD_Insert(i, CardHDD.Unit[i].szFilename))
bImageError = true;
// HD_Insert() sets up:
// . imagename
// . fullname
// . hd_imageloaded
}
//
// strcpy(g_HardDisk[i].fullname, CardHDD.Unit[i].szFilename);
g_HardDisk[i].hd_error = CardHDD.Unit[i].error;
g_HardDisk[i].hd_memblock = CardHDD.Unit[i].memblock;
g_HardDisk[i].hd_diskblock = CardHDD.Unit[i].diskblock;
g_HardDisk[i].hd_buf_ptr = CardHDD.Unit[i].buf_ptr;
// g_HardDisk[i].hd_imageloaded = CardHDD.Unit[i].imageloaded;
memcpy(g_HardDisk[i].hd_buf, CardHDD.Unit[i].buf, sizeof(CardHDD.Unit[i].buf));
g_HardDisk[i].hd_status_next = (Disk_Status_e) CardHDD.Unit[i].status_next;
g_HardDisk[i].hd_status_prev = (Disk_Status_e) CardHDD.Unit[i].status_prev;
if (bImageError)
{
g_HardDisk[i].hd_imageloaded = FALSE;
}
}
if (!bResSelectImage)
RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, strSaveStatePath.c_str());
HD_SetEnabled(true);
FrameRefreshStatus(DRAW_LEDS);
}

View File

@ -30,16 +30,19 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
NUM_HARDDISKS
};
void HD_Destroy(void);
bool HD_CardIsEnabled(void);
void HD_SetEnabled(const bool bEnabled);
LPCTSTR HD_GetFullName(const int iDrive);
LPCTSTR HD_GetFullPathName(const int iDrive);
VOID HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot);
VOID HD_Cleanup(void);
BOOL HD_InsertDisk(const int iDrive, LPCTSTR pszImageFilename);
void HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot);
void HD_Select(const int iDrive);
void HD_Unplug(const int iDrive);
bool HD_IsDriveUnplugged(const int iDrive);
void HD_LoadLastDiskImage(const int iDrive);
// 1.19.0.0 Hard Disk Status/Indicator Light
void HD_GetLightStatus (Disk_Status_e *pDisk1Status_);
void HD_GetSnapshot(const HANDLE hFile);
void HD_SetSnapshot(const HANDLE hFile, const std::string strSaveStatePath);

View File

@ -824,14 +824,19 @@ void JoyportControl(const UINT uControl)
//===========================================================================
DWORD JoyGetSnapshot(SS_IO_Joystick* pSS)
void JoySetSnapshot_v1(const unsigned __int64 JoyCntrResetCycle)
{
pSS->g_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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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;
}

View File

@ -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);

View File

@ -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; i<MB_UNITS_PER_CARD; i++)
{
memcpy(&pSS->Unit[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; i<MB_UNITS_PER_CARD; i++)
{
memcpy(&pMB->sy6522, &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++;
}
}

View File

@ -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);

View File

@ -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
}; // namespace DIMouse

View File

@ -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();

View File

@ -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;
}

View File

@ -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

View File

@ -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; i<NUM_SLOTS; i++)
m_ConfigNew.m_Slot[i] = CT_Empty;
MemReset();
if (!IS_APPLE2)
MemResetPaging();
DiskReset();
KeybReset();
VideoResetState();
MB_Reset();
sg_Mouse.Uninitialize();
sg_Mouse.Reset();
HD_SetEnabled(false);
while(1)
{
SS_UNIT_HDR UnitHdr;
DWORD dwBytesRead;
BOOL bRes = ReadFile( m_hFile,
&UnitHdr,
sizeof(UnitHdr),
&dwBytesRead,
NULL);
if (dwBytesRead == 0)
break; // EOF (OK)
if(!bRes || (dwBytesRead != sizeof(UnitHdr)))
throw std::string("File size mismatch");
switch (UnitHdr.hdr.v2.Type)
{
case UT_Apple2:
LoadUnitApple2(UnitHdr.hdr.v2.Length, UnitHdr.hdr.v2.Version);
break;
case UT_Card:
LoadUnitCard(UnitHdr.hdr.v2.Length, UnitHdr.hdr.v2.Version);
break;
case UT_Config:
LoadUnitConfig(UnitHdr.hdr.v2.Length, UnitHdr.hdr.v2.Version);
break;
default:
// Log then skip unsupported unit type
break;
}
}
SetLoadedSaveStateFlag(true);
// NB. The following disparity should be resolved:
// . A change in h/w via the Configuration property sheets results in a the VM completely restarting (via WM_USER_RESTART)
// . A change in h/w via loading a save-state avoids this VM restart
// The latter is the desired approach (as the former needs a "power-on" / F2 to start things again)
sg_PropertySheet.ApplyNewConfig(m_ConfigNew, ConfigOld);
MemInitializeROM();
MemInitializeCustomF8ROM();
MemInitializeIO();
MemUpdatePaging(TRUE);
//PostMessage(g_hFrameWindow, WM_USER_RESTART, 0, 0); // No, as this power-cycles VM (undoing all the new state just loaded)
}
catch(std::string szMessage)
{
MessageBox( g_hFrameWindow,
szMessage.c_str(),
TEXT("Load State"),
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
}
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
}
void Snapshot_LoadState()
{
SS_FILE_HDR Hdr;
Snapshot_LoadState_FileHdr(Hdr);
if (m_hFile == INVALID_HANDLE_VALUE)
return;
if(Hdr.dwVersion <= MAKE_VERSION(1,0,0,1))
{
CloseHandle(m_hFile);
m_hFile = INVALID_HANDLE_VALUE;
Snapshot_LoadState_v1();
return;
}
memset(pSS, 0, sizeof(APPLEWIN_SNAPSHOT));
Snapshot_LoadState_v2(Hdr.dwVersion);
}
pSS->Hdr.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;
}
//-----------------------------------------------------------------------------

View File

@ -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;
};

View File

@ -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

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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;
}

View File

@ -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);

View File

@ -23,7 +23,6 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <windows.h>
@ -36,6 +35,7 @@
#include <algorithm>
#include <map>
#include <queue>
#include <string>
#include <vector>
// SM_CXPADDEDBORDER is not supported on 2000 & XP:

View File

@ -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;
}
//===========================================================================

View File

@ -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 );