diff --git a/AppleWinExpress2013.vcxproj b/AppleWinExpress2013.vcxproj
index 95b86697..6d0c6dba 100644
--- a/AppleWinExpress2013.vcxproj
+++ b/AppleWinExpress2013.vcxproj
@@ -76,16 +76,19 @@
+
+
+
+
-
@@ -97,6 +100,7 @@
+
@@ -107,7 +111,7 @@
-
+
@@ -126,6 +130,7 @@
+
@@ -152,6 +157,7 @@
+
@@ -191,6 +197,7 @@
NotUsing
+
NotUsing
@@ -237,6 +244,9 @@
{9b32a6e7-1237-4f36-8903-a3fd51df9c4e}
+
+ {0212e0df-06da-4080-bd1d-f3b01599f70f}
+
@@ -343,9 +353,9 @@
Use
Level3
Disabled
- WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)
true
- source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)
+ source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)
MultiThreadedDebug
@@ -354,15 +364,22 @@
htmlhelp.lib;comctl32.lib;ddraw.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;Advapi32.lib;shell32.lib;Comdlg32.lib;ole32.lib;wsock32.lib;%(AdditionalDependencies)
"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"
+
+ echo Performing unit-test: TestCPU6502
+.\Debug\TestCPU6502.exe
+
+
+ Performing unit-test: TestCPU6502
+
Use
Level3
Disabled
- WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;%(PreprocessorDefinitions)
+ WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)
true
- source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)
+ source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)
MultiThreadedDebug
@@ -371,6 +388,13 @@
htmlhelp.lib;comctl32.lib;ddraw.lib;winmm.lib;dsound.lib;dxguid.lib;version.lib;strmiids.lib;dinput8.lib;user32.lib;gdi32.lib;Advapi32.lib;shell32.lib;Comdlg32.lib;ole32.lib;wsock32.lib;%(AdditionalDependencies)
"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"
+
+ echo Performing unit-test: TestCPU6502
+.\Debug\TestCPU6502.exe
+
+
+ Performing unit-test: TestCPU6502
+
@@ -379,9 +403,9 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)
true
- source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)
+ source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)
MultiThreaded
Speed
@@ -394,6 +418,13 @@
UseLinkTimeCodeGeneration
"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"
+
+ echo Performing unit-test: TestCPU6502
+.\Release\TestCPU6502.exe
+
+
+ Performing unit-test: TestCPU6502
+
@@ -402,9 +433,9 @@
MaxSpeed
true
true
- WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;%(PreprocessorDefinitions)
+ WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)
true
- source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)
+ source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)
MultiThreaded
Speed
@@ -417,6 +448,13 @@
UseLinkTimeCodeGeneration
"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"
+
+ echo Performing unit-test: TestCPU6502
+.\Release\TestCPU6502.exe
+
+
+ Performing unit-test: TestCPU6502
+
diff --git a/AppleWinExpress2013.vcxproj.filters b/AppleWinExpress2013.vcxproj.filters
index 6b8315a3..c9b778eb 100644
--- a/AppleWinExpress2013.vcxproj.filters
+++ b/AppleWinExpress2013.vcxproj.filters
@@ -172,6 +172,15 @@
Source Files\Video
+
+ Source Files\Model
+
+
+ Source Files\Emulator
+
+
+ Source Files\Emulator
+
@@ -372,9 +381,6 @@
Source Files
-
- Source Files\_Headers
-
Source Files\Emulator
@@ -423,6 +429,21 @@
Source Files\Video
+
+ Source Files\Model
+
+
+ Source Files\Emulator
+
+
+ Source Files\Emulator
+
+
+ Source Files\_Headers
+
+
+ Source Files\_Headers
+
@@ -591,9 +612,6 @@
Docs
-
- Docs
-
Docs
@@ -603,6 +621,7 @@
Docs
+
@@ -644,6 +663,9 @@
{b5c6889e-727d-4339-96c8-e4284e1d6e0f}
+
+ {15b450e4-f89f-4d80-9c44-48b32f33f3e3}
+
diff --git a/ApplewinExpress9.00.vcproj b/ApplewinExpress9.00.vcproj
index 27e7e9f1..5542a063 100644
--- a/ApplewinExpress9.00.vcproj
+++ b/ApplewinExpress9.00.vcproj
@@ -26,6 +26,8 @@
>
+
+
+
+
@@ -734,6 +746,14 @@
RelativePath=".\source\Tape.h"
>
+
+
+
+
@@ -755,11 +775,15 @@
>
+
+
@@ -959,6 +983,18 @@
>
+
+
+
+
+
+
> 8) & 0xf;
+ period = (USHORT) yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_TONE1_PERIOD);
+ sound_ay_registers[2] = period & 0xff;
+ sound_ay_registers[3] = (period >> 8) & 0xf;
+ period = (USHORT) yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_TONE2_PERIOD);
+ sound_ay_registers[4] = period & 0xff;
+ sound_ay_registers[5] = (period >> 8) & 0xf;
+ sound_ay_registers[6] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_NOISE_PERIOD);
+ sound_ay_registers[7] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_MIXER);
+ sound_ay_registers[8] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_VOL0);
+ sound_ay_registers[9] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_VOL1);
+ sound_ay_registers[10] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_VOL2);
+ period = (USHORT) yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_ENV_PERIOD);
+ sound_ay_registers[11] = period & 0xff;
+ sound_ay_registers[12] = period >> 8;
+ sound_ay_registers[13] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_ENV_SHAPE);
+ sound_ay_registers[14] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_PORTA);
+ sound_ay_registers[15] = yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_PORTB);
+
+ yamlLoadHelper.PopMap();
+
+ ay_change_count = 0;
+ if (yamlLoadHelper.GetSubMap(SS_YAML_KEY_CHANGE))
+ {
+ while(1)
+ {
+ char szIndex[7];
+ sprintf_s(szIndex, sizeof(szIndex), "0x%04X", ay_change_count);
+
+ bool bFound;
+ std::string value = yamlLoadHelper.LoadString_NoThrow(szIndex, bFound);
+ if (!bFound)
+ break; // done
+
+ if(4 != sscanf_s(value.c_str(), SS_YAML_VALUE_CHANGE_FORMAT,
+ &ay_change[ay_change_count].tstates,
+ &ay_change[ay_change_count].ofs,
+ &ay_change[ay_change_count].reg,
+ &ay_change[ay_change_count].val))
+ throw std::string("Card: AY8910: Failed to scanf change list");
+
+ ay_change_count++;
+ if (ay_change_count > AY_CHANGE_MAX)
+ throw std::string("Card: AY8910: Too many changes");
+ }
+
+ yamlLoadHelper.PopMap();
+ }
+
+ yamlLoadHelper.PopMap();
+
+ return true;
+}
+
///////////////////////////////////////////////////////////////////////////////
// AY8910 interface
@@ -996,8 +1190,25 @@ void AY8910_InitClock(int nClock)
BYTE* AY8910_GetRegsPtr(UINT uChip)
{
- if(uChip >= MAX_8910)
+ if (uChip >= MAX_8910)
return NULL;
return g_AY8910[uChip].GetAYRegsPtr();
}
+
+UINT AY8910_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix)
+{
+ if (uChip >= MAX_8910)
+ return 0;
+
+ g_AY8910[uChip].SaveSnapshot(yamlSaveHelper, suffix);
+ return 1;
+}
+
+UINT AY8910_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix)
+{
+ if (uChip >= MAX_8910)
+ return 0;
+
+ return g_AY8910[uChip].LoadSnapshot(yamlLoadHelper, suffix) ? 1 : 0;
+}
diff --git a/source/AY8910.h b/source/AY8910.h
index 59a53359..31ad9a15 100644
--- a/source/AY8910.h
+++ b/source/AY8910.h
@@ -17,6 +17,9 @@ BYTE* AY8910_GetRegsPtr(UINT uChip);
void AY8910UpdateSetCycles();
+UINT AY8910_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, UINT uChip, std::string& suffix);
+UINT AY8910_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uChip, std::string& suffix);
+
//-------------------------------------
// FUSE stuff
@@ -43,8 +46,11 @@ public:
void sound_frame( void );
BYTE* GetAYRegsPtr( void ) { return &sound_ay_registers[0]; }
static void SetCLK( double CLK ) { m_fCurrentCLK_AY8910 = CLK; }
+ void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, std::string& suffix);
+ bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, std::string& suffix);
private:
+ void init( void );
void sound_end( void );
void sound_ay_overlay( void );
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 76a0b3e6..c49a6e0a 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Configuration\PropertySheet.h"
#include "Tfe\Tfe.h"
+static UINT16 g_AppleWinVersion[4] = {0};
char VERSIONSTRING[16] = "xx.yy.zz.ww";
TCHAR *g_pAppTitle = TITLE_APPLE_2E_ENHANCED;
@@ -65,9 +66,6 @@ eApple2Type g_Apple2Type = A2TYPE_APPLE2EENHANCED;
bool g_bFullSpeed = false;
-//Pravets 8A/C variables
-bool P8CAPS_ON = false;
-bool P8Shift = false;
//=================================================
// Win32
@@ -102,8 +100,6 @@ CMouseInterface sg_Mouse;
SS_CARDTYPE g_Slot4 = CT_Empty;
SS_CARDTYPE g_Slot5 = CT_Empty;
-eCPU g_ActiveCPU = CPU_6502;
-
HANDLE g_hCustomRomF8 = INVALID_HANDLE_VALUE; // Cmd-line specified custom ROM at $F800..$FFFF
static bool g_bCustomRomF8Failed = false; // Set if custom ROM file failed
@@ -114,6 +110,22 @@ CSpeech g_Speech;
//===========================================================================
+eApple2Type GetApple2Type(void)
+{
+ return g_Apple2Type;
+}
+
+void SetApple2Type(eApple2Type type)
+{
+ g_Apple2Type = type;
+ SetMainCpuDefault(type);
+}
+
+const UINT16* GetAppleWinVersion(void)
+{
+ return &g_AppleWinVersion[0];
+}
+
bool GetLoadedSaveStateFlag(void)
{
return g_bLoadedSaveState;
@@ -371,20 +383,39 @@ static void LoadConfigOldJoystick(const UINT uJoyNum)
break;
}
- joytype[uJoyNum] = uNewJoyType;
+ JoySetJoyType(uJoyNum, uNewJoyType);
+}
+
+//Sets the character set for the Apple model/clone
+void SetCharsetType(void)
+{
+ switch ( GetApple2Type() )
+ {
+ case A2TYPE_APPLE2: g_nCharsetType = 0; break;
+ case A2TYPE_APPLE2PLUS: g_nCharsetType = 0; break;
+ case A2TYPE_APPLE2E: g_nCharsetType = 0; break;
+ case A2TYPE_APPLE2EENHANCED:g_nCharsetType = 0; break;
+ case A2TYPE_PRAVETS82: g_nCharsetType = 1; break;
+ case A2TYPE_PRAVETS8A: g_nCharsetType = 2; break;
+ case A2TYPE_PRAVETS8M: g_nCharsetType = 3; break; //This charset has a very small difference with the PRAVETS82 one an probably has some misplaced characters. Still the Pravets82 charset is used, because setting charset to 3 results in some problems.
+ default:
+ _ASSERT(0);
+ g_nCharsetType = 0;
+ }
}
//Reads configuration from the registry entries
void LoadConfiguration(void)
{
DWORD dwComputerType;
+ eApple2Type apple2Type = A2TYPE_APPLE2EENHANCED;
if (REGLOAD(TEXT(REGVALUE_APPLE2_TYPE), &dwComputerType))
{
if ((dwComputerType >= A2TYPE_MAX) || (dwComputerType >= A2TYPE_UNDEFINED && dwComputerType < A2TYPE_CLONE))
dwComputerType = A2TYPE_APPLE2EENHANCED;
- g_Apple2Type = (eApple2Type) dwComputerType;
+ apple2Type = (eApple2Type) dwComputerType;
}
else // Support older AppleWin registry entries
{
@@ -392,27 +423,42 @@ void LoadConfiguration(void)
switch (dwComputerType)
{
// NB. No A2TYPE_APPLE2E (this is correct)
- case 0: g_Apple2Type = A2TYPE_APPLE2;
- case 1: g_Apple2Type = A2TYPE_APPLE2PLUS;
- case 2: g_Apple2Type = A2TYPE_APPLE2EENHANCED;
- default: g_Apple2Type = A2TYPE_APPLE2EENHANCED;
+ case 0: apple2Type = A2TYPE_APPLE2; break;
+ case 1: apple2Type = A2TYPE_APPLE2PLUS; break;
+ case 2: apple2Type = A2TYPE_APPLE2EENHANCED; break;
+ default: apple2Type = A2TYPE_APPLE2EENHANCED;
}
}
- switch (g_Apple2Type) //Sets the character set for the Apple model/clone
+ SetApple2Type(apple2Type);
+ SetCharsetType();
+
+ //
+
+ DWORD dwCpuType;
+ eCpuType cpu = CPU_65C02;
+
+ if (REGLOAD(TEXT(REGVALUE_CPU_TYPE), &dwCpuType))
{
- case A2TYPE_APPLE2: g_nCharsetType = 0; break;
- case A2TYPE_APPLE2PLUS: g_nCharsetType = 0; break;
- case A2TYPE_APPLE2E: g_nCharsetType = 0; break;
- case A2TYPE_APPLE2EENHANCED:g_nCharsetType = 0; break;
- case A2TYPE_PRAVETS82: g_nCharsetType = 1; break;
- case A2TYPE_PRAVETS8A: g_nCharsetType = 2; break;
- case A2TYPE_PRAVETS8M: g_nCharsetType = 3; break; //This charset has a very small difference with the PRAVETS82 one an probably has some misplaced characters. Still the Pravets82 charset is used, because setting charset to 3 results in some problems.
+ if (dwCpuType != CPU_6502 && dwCpuType != CPU_65C02)
+ dwCpuType = CPU_65C02;
+
+ cpu = (eCpuType) dwCpuType;
}
- if (!REGLOAD(TEXT(REGVALUE_JOYSTICK0_EMU_TYPE), &joytype[JN_JOYSTICK0]))
+ SetMainCpu(cpu);
+
+ //
+
+ DWORD dwJoyType;
+ if (REGLOAD(TEXT(REGVALUE_JOYSTICK0_EMU_TYPE), &dwJoyType))
+ JoySetJoyType(JN_JOYSTICK0, dwJoyType);
+ else
LoadConfigOldJoystick(JN_JOYSTICK0);
- if (!REGLOAD(TEXT(REGVALUE_JOYSTICK1_EMU_TYPE), &joytype[JN_JOYSTICK1]))
+
+ if (REGLOAD(TEXT(REGVALUE_JOYSTICK1_EMU_TYPE), &dwJoyType))
+ JoySetJoyType(JN_JOYSTICK1, dwJoyType);
+ else
LoadConfigOldJoystick(JN_JOYSTICK1);
REGLOAD(TEXT("Sound Emulation") ,&soundtype);
@@ -469,12 +515,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))
@@ -500,15 +540,20 @@ void LoadConfiguration(void)
if(REGLOAD(TEXT(REGVALUE_SLOT5), &dwTmp))
g_Slot5 = (SS_CARDTYPE) dwTmp;
- if (g_Slot4 == CT_MockingboardC || g_Slot4 == CT_Phasor)
- MB_SetSoundcardType(g_Slot4);
- else
- MB_SetSoundcardType(CT_Empty);
-
//
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)
@@ -550,7 +595,7 @@ bool SetCurrentImageDir(const char* pszImageDir)
strcpy(g_sCurrentDir, pszImageDir);
int nLen = strlen( g_sCurrentDir );
- if( g_sCurrentDir[ nLen - 1 ] != '\\' )
+ if ((nLen > 0) && (g_sCurrentDir[ nLen - 1 ] != '\\'))
{
g_sCurrentDir[ nLen + 0 ] = '\\';
g_sCurrentDir[ nLen + 1 ] = 0;
@@ -739,10 +784,12 @@ static int DoDiskInsert(const int nDrive, LPCSTR szFileName)
int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
+ bool bShutdown = false;
bool bSetFullScreen = false;
bool bBoot = false;
LPSTR szImageName_drive1 = NULL;
LPSTR szImageName_drive2 = NULL;
+ LPSTR szSnapshotName = NULL;
const std::string strCmdLine(lpCmdLine); // Keep a copy for log ouput
while (*lpCmdLine)
@@ -774,6 +821,12 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
lpNextArg = GetNextArg(lpNextArg);
szImageName_drive2 = lpCmdLine;
}
+ else if (strcmp(lpCmdLine, "-load-state") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ szSnapshotName = lpCmdLine;
+ }
else if (strcmp(lpCmdLine, "-f") == 0)
{
bSetFullScreen = true;
@@ -811,8 +864,8 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
g_uMaxExPages = atoi(lpCmdLine);
- if (g_uMaxExPages > 127)
- g_uMaxExPages = 128;
+ if (g_uMaxExPages > kMaxExMemoryBanks)
+ g_uMaxExPages = kMaxExMemoryBanks;
else if (g_uMaxExPages < 1)
g_uMaxExPages = 1;
}
@@ -905,11 +958,11 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
// Construct version string from fixed file info block
- unsigned long major = pFixedFileInfo->dwFileVersionMS >> 16;
- unsigned long minor = pFixedFileInfo->dwFileVersionMS & 0xffff;
- unsigned long fix = pFixedFileInfo->dwFileVersionLS >> 16;
- unsigned long fix_minor = pFixedFileInfo->dwFileVersionLS & 0xffff;
- sprintf(VERSIONSTRING, "%d.%d.%d.%d", major, minor, fix, fix_minor); // potential buffer overflow
+ unsigned long major = g_AppleWinVersion[0] = pFixedFileInfo->dwFileVersionMS >> 16;
+ unsigned long minor = g_AppleWinVersion[1] = pFixedFileInfo->dwFileVersionMS & 0xffff;
+ unsigned long fix = g_AppleWinVersion[2] = pFixedFileInfo->dwFileVersionLS >> 16;
+ unsigned long fix_minor = g_AppleWinVersion[3] = pFixedFileInfo->dwFileVersionLS & 0xffff;
+ sprintf(VERSIONSTRING, "%d.%d.%d.%d", major, minor, fix, fix_minor); // potential buffer overflow
}
}
@@ -955,7 +1008,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
DiskInitialize();
LogFileOutput("Init: DiskInitialize()\n");
- int nError = 0; // TODO: Show error MsgBox if we get a DiskInsert error
+ int nError = 0; // TODO: Show error MsgBox if we get a DiskInsert error
if (szImageName_drive1)
{
nError = DoDiskInsert(DRIVE_1, szImageName_drive1);
@@ -1003,7 +1056,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (bShowAboutDlg)
{
if (!AboutDlg())
- PostMessage(g_hFrameWindow, WM_DESTROY, 0, 0); // Close everything down
+ bShutdown = true; // Close everything down
else
RegSaveString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, VERSIONSTRING); // Only save version after user accepts license
}
@@ -1019,31 +1072,57 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (!bSysClkOK)
{
MessageBox(g_hFrameWindow, "DirectX failed to create SystemClock instance", TEXT("AppleWin Error"), MB_OK);
- PostMessage(g_hFrameWindow, WM_DESTROY, 0, 0); // Close everything down
+ bShutdown = true;
}
if (g_bCustomRomF8Failed)
{
MessageBox(g_hFrameWindow, "Failed to load custom F8 rom (not found or not exactly 2KB)", TEXT("AppleWin Error"), MB_OK);
- PostMessage(g_hFrameWindow, WM_DESTROY, 0, 0); // Close everything down
+ bShutdown = true;
}
tfe_init();
LogFileOutput("Main: tfe_init()\n");
- Snapshot_Startup(); // Do this after everything has been init'ed
- LogFileOutput("Main: Snapshot_Startup()\n");
-
- if (bSetFullScreen)
+ if (szSnapshotName)
{
- PostMessage(g_hFrameWindow, WM_USER_FULLSCREEN, 0, 0);
- bSetFullScreen = false;
+ // Override value just loaded from Registry by LoadConfiguration()
+ // . NB. Registry value is not updated with this cmd-line value
+ Snapshot_SetFilename(szSnapshotName);
+ Snapshot_LoadState();
+ bBoot = true;
+#if _DEBUG && 0 // Debug/test: Save a duplicate of the save-state file in tmp folder
+ std::string saveName = std::string("tmp\\") + std::string(szSnapshotName);
+ Snapshot_SetFilename(saveName);
+ g_bSaveStateOnExit = true;
+ bShutdown = true;
+#endif
+ szSnapshotName = NULL;
+ }
+ else
+ {
+ Snapshot_Startup(); // Do this after everything has been init'ed
+ LogFileOutput("Main: Snapshot_Startup()\n");
}
- if (bBoot)
+ if (bShutdown)
{
- PostMessage(g_hFrameWindow, WM_USER_BOOT, 0, 0);
- bBoot = false;
+ PostMessage(g_hFrameWindow, WM_DESTROY, 0, 0); // Close everything down
+ // NB. If shutting down, then don't post any other messages (GH#286)
+ }
+ else
+ {
+ if (bSetFullScreen)
+ {
+ PostMessage(g_hFrameWindow, WM_USER_FULLSCREEN, 0, 0);
+ bSetFullScreen = false;
+ }
+
+ if (bBoot)
+ {
+ PostMessage(g_hFrameWindow, WM_USER_BOOT, 0, 0);
+ bBoot = false;
+ }
}
// ENTER THE MAIN MESSAGE LOOP
diff --git a/source/Applewin.h b/source/Applewin.h
index 24f19fd2..b57efcde 100644
--- a/source/Applewin.h
+++ b/source/Applewin.h
@@ -1,23 +1,23 @@
#pragma once
-#include "Structs.h"
+#include "SaveState_Structs_common.h"
#include "Common.h"
void SetCurrentCLK6502();
bool SetCurrentImageDir(const char* pszImageDir);
+void SetCharsetType(void);
-
+extern const UINT16* GetAppleWinVersion(void);
extern char VERSIONSTRING[]; // Constructed in WinMain()
extern TCHAR *g_pAppTitle;
extern eApple2Type g_Apple2Type;
+eApple2Type GetApple2Type(void);
+void SetApple2Type(eApple2Type type);
extern bool g_bFullSpeed;
-//Pravets 8A/C only variables
-extern bool P8CAPS_ON;
-extern bool P8Shift;
//===========================================
// Win32
@@ -49,9 +49,6 @@ extern SS_CARDTYPE g_Slot5; // Mockingboard, Z80, in slot5
extern HANDLE g_hCustomRomF8; // NULL if no custom rom
-enum eCPU {CPU_6502=1, CPU_Z80};
-extern eCPU g_ActiveCPU;
-
#ifdef USE_SPEECH_API
class CSpeech;
extern CSpeech g_Speech;
diff --git a/source/CPU.cpp b/source/CPU.cpp
index faf45fbf..daacf9fc 100644
--- a/source/CPU.cpp
+++ b/source/CPU.cpp
@@ -63,7 +63,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
// What about these:
// . 65C02: STZ?, TRB?, TSB?
-// . Answer: TRB & TSB don't have affected adressing modes
+// . Answer: TRB & TSB don't have affected addressing modes
// . STZ probably doesn't add a cycle since otherwise it would be slower than STA which doesn't make sense.
//
// NB. 'Zero-page indexed' opcodes wrap back to zero-page.
@@ -103,6 +103,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Z80VICE\z80mem.h"
#include "Debugger\Debug.h"
+#include "YamlHelper.h"
// 6502 Accumulator Bit Flags
#define AF_SIGN 0x80
@@ -148,6 +149,53 @@ static volatile UINT32 g_bmIRQ = 0;
static volatile UINT32 g_bmNMI = 0;
static volatile BOOL g_bNmiFlank = FALSE; // Positive going flank on NMI line
+//
+
+static eCpuType g_MainCPU = CPU_65C02;
+static eCpuType g_ActiveCPU = CPU_65C02;
+
+eCpuType GetMainCpu(void)
+{
+ return g_MainCPU;
+}
+
+void SetMainCpu(eCpuType cpu)
+{
+ _ASSERT(cpu != CPU_Z80);
+ if (cpu == CPU_Z80)
+ return;
+
+ g_MainCPU = cpu;
+}
+
+static bool IsCpu65C02(eApple2Type apple2Type)
+{
+ // NB. All Pravets clones are 6502 (GH#307)
+ return (apple2Type == A2TYPE_APPLE2EENHANCED) || (apple2Type & A2TYPE_APPLE2C);
+}
+
+eCpuType ProbeMainCpuDefault(eApple2Type apple2Type)
+{
+ return IsCpu65C02(apple2Type) ? CPU_65C02 : CPU_6502;
+}
+
+void SetMainCpuDefault(eApple2Type apple2Type)
+{
+ SetMainCpu( ProbeMainCpuDefault(apple2Type) );
+}
+
+eCpuType GetActiveCpu(void)
+{
+ return g_ActiveCPU;
+}
+
+void SetActiveCpu(eCpuType cpu)
+{
+ g_ActiveCPU = cpu;
+}
+
+//
+
#include "cpu/cpu_general.inl"
#include "cpu/cpu_instructions.inl"
@@ -409,8 +457,8 @@ static __forceinline void CheckInterruptSources(ULONG uExecutedCycles)
static DWORD InternalCpuExecute (DWORD uTotalCycles)
{
- if (IS_APPLE2 || (g_Apple2Type == A2TYPE_APPLE2E))
- return Cpu6502(uTotalCycles); // Apple ][, ][+, //e
+ if (GetMainCpu() == CPU_6502)
+ return Cpu6502(uTotalCycles); // Apple ][, ][+, //e, Clones
else
return Cpu65C02(uTotalCycles); // Enhanced Apple //e
}
@@ -639,36 +687,83 @@ void CpuReset()
regs.bJammed = 0;
- g_ActiveCPU = CPU_6502;
+ SetActiveCpu( GetMainCpu() );
z80_reset();
}
//===========================================================================
-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;
+}
+
+//
+
+#define SS_YAML_KEY_CPU_TYPE "Type"
+#define SS_YAML_KEY_REGA "A"
+#define SS_YAML_KEY_REGX "X"
+#define SS_YAML_KEY_REGY "Y"
+#define SS_YAML_KEY_REGP "P"
+#define SS_YAML_KEY_REGS "S"
+#define SS_YAML_KEY_REGPC "PC"
+#define SS_YAML_KEY_CUMULATIVECYCLES "Cumulative Cycles"
+
+#define SS_YAML_VALUE_6502 "6502"
+#define SS_YAML_VALUE_65C02 "65C02"
+
+static std::string CpuGetSnapshotStructName(void)
+{
+ static const std::string name("CPU");
+ return name;
+}
+
+void CpuSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ regs.ps |= (AF_RESERVED | AF_BREAK);
+
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", CpuGetSnapshotStructName().c_str());
+ yamlSaveHelper.SaveString(SS_YAML_KEY_CPU_TYPE, GetMainCpu() == CPU_6502 ? SS_YAML_VALUE_6502 : SS_YAML_VALUE_65C02);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGA, regs.a);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGX, regs.x);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGY, regs.y);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGP, regs.ps);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGS, (BYTE) regs.sp);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REGPC, regs.pc);
+ yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_CUMULATIVECYCLES, g_nCumulativeCycles);
+}
+
+void CpuLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+{
+ if (!yamlLoadHelper.GetSubMap(CpuGetSnapshotStructName()))
+ return;
+
+ std::string cpuType = yamlLoadHelper.LoadString(SS_YAML_KEY_CPU_TYPE);
+ eCpuType cpu;
+ if (cpuType == SS_YAML_VALUE_6502) cpu = CPU_6502;
+ else if (cpuType == SS_YAML_VALUE_65C02) cpu = CPU_65C02;
+ else throw std::string("Load: Unknown main CPU type");
+ SetMainCpu(cpu);
+
+ regs.a = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_REGA);
+ regs.x = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_REGX);
+ regs.y = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_REGY);
+ regs.ps = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_REGP) | (AF_RESERVED | AF_BREAK);
+ regs.sp = (USHORT) ((yamlLoadHelper.LoadUint(SS_YAML_KEY_REGS) & 0xff) | 0x100);
+ regs.pc = (USHORT) yamlLoadHelper.LoadUint(SS_YAML_KEY_REGPC);
+
+ CpuIrqReset();
+ CpuNmiReset();
+ g_nCumulativeCycles = yamlLoadHelper.LoadUint64(SS_YAML_KEY_CUMULATIVECYCLES);
+
+ yamlLoadHelper.PopMap();
}
diff --git a/source/CPU.h b/source/CPU.h
index 58c5d886..5086e9e1 100644
--- a/source/CPU.h
+++ b/source/CPU.h
@@ -1,6 +1,7 @@
#pragma once
-typedef struct _regsrec {
+struct regsrec
+{
BYTE a; // accumulator
BYTE x; // index X
BYTE y; // index Y
@@ -8,7 +9,7 @@ typedef struct _regsrec {
WORD pc; // program counter
WORD sp; // stack pointer
BYTE bJammed; // CPU has crashed (NMOS 6502 only)
-} regsrec, *regsptr;
+};
extern regsrec regs;
extern unsigned __int64 g_nCumulativeCycles;
@@ -26,10 +27,20 @@ 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 CpuSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+void CpuLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
BYTE CpuRead(USHORT addr, ULONG uExecutedCycles);
void CpuWrite(USHORT addr, BYTE a, ULONG uExecutedCycles);
DWORD CpuGetEmulationTime_ms(void);
+
+enum eCpuType {CPU_6502=1, CPU_65C02, CPU_Z80}; // Don't change! Persisted to Registry
+
+eCpuType GetMainCpu(void);
+void SetMainCpu(eCpuType cpu);
+eCpuType ProbeMainCpuDefault(eApple2Type apple2Type);
+void SetMainCpuDefault(eApple2Type apple2Type);
+eCpuType GetActiveCpu(void);
+void SetActiveCpu(eCpuType cpu);
diff --git a/source/CPU/cpu6502.h b/source/CPU/cpu6502.h
index 3645242e..b2a25e67 100644
--- a/source/CPU/cpu6502.h
+++ b/source/CPU/cpu6502.h
@@ -35,7 +35,6 @@ static DWORD Cpu6502 (DWORD uTotalCycles)
WORD val;
AF_TO_EF
ULONG uExecutedCycles = 0;
- BOOL bSlowerOnPagecross = 0; // Set if opcode writes to memory (eg. ASL, STA)
WORD base;
g_bDebugBreakpointHit = 0;
@@ -49,275 +48,276 @@ static DWORD Cpu6502 (DWORD uTotalCycles)
ULONG uPreviousCycles = uExecutedCycles;
// NTSC_END
- if (g_ActiveCPU == CPU_Z80)
+ if (GetActiveCpu() == CPU_Z80)
{
const UINT uZ80Cycles = z80_mainloop(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles)
}
else
{
- if (!Fetch(iOpcode, uExecutedCycles))
- break;
+ if (!Fetch(iOpcode, uExecutedCycles))
+ break;
#define $ INV // INV = Invalid -> Debugger Break
- switch (iOpcode)
- {
- case 0x00: BRK CYC(7) break;
- case 0x01: idx ORA CYC(6) break;
- case 0x02: $ HLT CYC(2) break;
- case 0x03: $ idx ASO CYC(8) break;
- case 0x04: $ ZPG NOP CYC(3) break;
- case 0x05: ZPG ORA CYC(3) break;
- case 0x06: ZPG ASLn CYC(5) break;
- case 0x07: $ ZPG ASO CYC(5) break; // invalid
- case 0x08: PHP CYC(3) break;
- case 0x09: IMM ORA CYC(2) break;
- case 0x0A: asl CYC(2) break;
- case 0x0B: $ IMM ANC CYC(2) break; // invald
- case 0x0C: $ abx NOP CYC(4) break;
- case 0x0D: ABS ORA CYC(4) break;
- case 0x0E: ABS ASLn CYC(6) break;
- case 0x0F: $ ABS ASO CYC(6) break; // invalid
- case 0x10: REL BPL CYC(2) break;
- case 0x11: idy ORA CYC(5) break;
- case 0x12: $ HLT CYC(2) break;
- case 0x13: $ idy ASO CYC(8) break; // invalid
- case 0x14: $ zpx NOP CYC(4) break;
- case 0x15: zpx ORA CYC(4) break;
- case 0x16: zpx ASLn CYC(6) break;
- case 0x17: $ zpx ASO CYC(6) break; // invalid
- case 0x18: CLC CYC(2) break;
- case 0x19: aby ORA CYC(4) break;
- case 0x1A: $ NOP CYC(2) break;
- case 0x1B: $ aby ASO CYC(7) break; // invalid
- case 0x1C: $ abx NOP CYC(4) break;
- case 0x1D: abx ORA CYC(4) break;
- case 0x1E: abx ASLn CYC(6) break;
- case 0x1F: $ abx ASO CYC(7) break; // invalid
- case 0x20: ABS JSR CYC(6) break;
- case 0x21: idx AND CYC(6) break;
- case 0x22: $ HLT CYC(2) break;
- case 0x23: $ idx RLA CYC(8) break;
- case 0x24: ZPG BIT CYC(3) break;
- case 0x25: ZPG AND CYC(3) break;
- case 0x26: ZPG ROLn CYC(5) break;
- case 0x27: $ ZPG RLA CYC(5) break;
- case 0x28: PLP CYC(4) break;
- case 0x29: IMM AND CYC(2) break;
- case 0x2A: rol CYC(2) break;
- case 0x2B: $ IMM ANC CYC(2) break; // invalid
- case 0x2C: ABS BIT CYC(4) break;
- case 0x2D: ABS AND CYC(2) break;
- case 0x2E: ABS ROLn CYC(6) break;
- case 0x2F: $ ABS RLA CYC(6) break;
- case 0x30: REL BMI CYC(2) break;
- case 0x31: idy AND CYC(5) break;
- case 0x32: $ HLT CYC(2) break;
- case 0x33: $ idy RLA CYC(8) break; // invalid
- case 0x34: $ zpx NOP CYC(4) break;
- case 0x35: zpx AND CYC(4) break;
- case 0x36: zpx ROLn CYC(6) break;
- case 0x37: $ zpx RLA CYC(6) break;
- case 0x38: SEC CYC(2) break;
- case 0x39: aby AND CYC(4) break;
- case 0x3A: $ NOP CYC(2) break;
- case 0x3B: $ aby RLA CYC(7) break; // invalid
- case 0x3C: $ abx NOP CYC(4) break;
- case 0x3D: abx AND CYC(4) break;
- case 0x3E: abx ROLn CYC(6) break;
- case 0x3F: $ abx RLA CYC(7) break; // invalid
- case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
- case 0x41: idx EOR CYC(6) break;
- case 0x42: $ HLT CYC(2) break;
- case 0x43: $ idx LSE CYC(8) break; // invalid
- case 0x44: $ ZPG NOP CYC(3) break;
- case 0x45: ZPG EOR CYC(3) break;
- case 0x46: ZPG LSRn CYC(5) break;
- case 0x47: $ ZPG LSE CYC(5) break; // invalid
- case 0x48: PHA CYC(3) break;
- case 0x49: IMM EOR CYC(2) break;
- case 0x4A: lsr CYC(2) break;
- case 0x4B: $ IMM ALR CYC(2) break; // invalid
- case 0x4C: ABS JMP CYC(3) break;
- case 0x4D: ABS EOR CYC(4) break;
- case 0x4E: ABS LSRn CYC(6) break;
- case 0x4F: $ ABS LSE CYC(6) break;
- case 0x50: REL BVC CYC(2) break;
- case 0x51: idy EOR CYC(5) break;
- case 0x52: $ HLT CYC(2) break;
- case 0x53: $ idy LSE CYC(8) break;
- case 0x54: $ zpx NOP CYC(4) break;
- case 0x55: zpx EOR CYC(4) break;
- case 0x56: zpx LSRn CYC(6) break;
- case 0x57: $ zpx LSE CYC(6) break; // invalid
- case 0x58: CLI CYC(2) break;
- case 0x59: aby EOR CYC(4) break;
- case 0x5A: $ NOP CYC(2) break;
- case 0x5B: $ aby LSE CYC(7) break; // invalid
- case 0x5C: $ abx NOP CYC(4) break;
- case 0x5D: abx EOR CYC(4) break;
- case 0x5E: abx LSRn CYC(6) break;
- case 0x5F: $ abx LSE CYC(7) break;
- case 0x60: RTS CYC(6) break;
- case 0x61: idx ADCn CYC(6) break;
- case 0x62: $ HLT CYC(2) break;
- case 0x63: $ idx RRA CYC(8) break; // invalid
- case 0x64: $ ZPG NOP CYC(3) break;
- case 0x65: ZPG ADCn CYC(3) break;
- case 0x66: ZPG RORn CYC(5) break;
- case 0x67: $ ZPG RRA CYC(5) break;
- case 0x68: PLA CYC(4) break;
- case 0x69: IMM ADCn CYC(2) break;
- case 0x6A: ror CYC(2) break;
- case 0x6B: $ IMM ARR CYC(2) break; // invalid
- case 0x6C: IABSNMOS JMP CYC(6) break;
- case 0x6D: ABS ADCn CYC(4) break;
- case 0x6E: ABS RORn CYC(6) break;
- case 0x6F: $ ABS RRA CYC(6) break; // invalid
- case 0x70: REL BVS CYC(2) break;
- case 0x71: idy ADCn CYC(5) break;
- case 0x72: $ HLT CYC(2) break;
- case 0x73: $ idy RRA CYC(8) break; // invalid
- case 0x74: $ zpx NOP CYC(4) break;
- case 0x75: zpx ADCn CYC(4) break;
- case 0x76: zpx RORn CYC(6) break;
- case 0x77: $ zpx RRA CYC(6) break; // invalid
- case 0x78: SEI CYC(2) break;
- case 0x79: aby ADCn CYC(4) break;
- case 0x7A: $ NOP CYC(2) break;
- case 0x7B: $ aby RRA CYC(7) break; // invalid
- case 0x7C: $ abx NOP CYC(4) break;
- case 0x7D: abx ADCn CYC(4) break;
- case 0x7E: abx RORn CYC(6) break;
- case 0x7F: $ abx RRA CYC(7) break; // invalid
- case 0x80: $ IMM NOP CYC(2) break;
- case 0x81: idx STA CYC(6) break;
- case 0x82: $ IMM NOP CYC(2) break;
- case 0x83: $ idx AXS CYC(6) break; // invalid
- case 0x84: ZPG STY CYC(3) break;
- case 0x85: ZPG STA CYC(3) break;
- case 0x86: ZPG STX CYC(3) break;
- case 0x87: $ ZPG AXS CYC(3) break; // invalid
- case 0x88: DEY CYC(2) break;
- case 0x89: $ IMM NOP CYC(2) break;
- case 0x8A: TXA CYC(2) break;
- case 0x8B: $ IMM XAA CYC(2) break; // invalid
- case 0x8C: ABS STY CYC(4) break;
- case 0x8D: ABS STA CYC(4) break;
- case 0x8E: ABS STX CYC(4) break;
- case 0x8F: $ ABS AXS CYC(4) break; // invalid
- case 0x90: REL BCC CYC(2) break;
- case 0x91: idy STA CYC(6) break;
- case 0x92: $ HLT CYC(2) break;
- case 0x93: $ idy AXA CYC(6) break; // invalid
- case 0x94: zpx STY CYC(4) break;
- case 0x95: zpx STA CYC(4) break;
- case 0x96: zpy STX CYC(4) break;
- case 0x97: $ zpy AXS CYC(4) break; // invalid
- case 0x98: TYA CYC(2) break;
- case 0x99: aby STA CYC(5) break;
- case 0x9A: TXS CYC(2) break;
- case 0x9B: $ aby TAS CYC(5) break; // invalid
- case 0x9C: $ abx SAY CYC(5) break; // invalid
- case 0x9D: abx STA CYC(5) break;
- case 0x9E: $ aby XAS CYC(5) break;
- case 0x9F: $ aby AXA CYC(5) break;
- case 0xA0: IMM LDY CYC(2) break;
- case 0xA1: idx LDA CYC(6) break;
- case 0xA2: IMM LDX CYC(2) break;
- case 0xA3: $ idx LAX CYC(6) break; // invalid
- case 0xA4: ZPG LDY CYC(3) break;
- case 0xA5: ZPG LDA CYC(3) break;
- case 0xA6: ZPG LDX CYC(3) break;
- case 0xA7: $ ZPG LAX CYC(3) break; // invalid
- case 0xA8: TAY CYC(2) break;
- case 0xA9: IMM LDA CYC(2) break;
- case 0xAA: TAX CYC(2) break;
- case 0xAB: $ IMM OAL CYC(2) break; // invalid
- case 0xAC: ABS LDY CYC(4) break;
- case 0xAD: ABS LDA CYC(4) break;
- case 0xAE: ABS LDX CYC(4) break;
- case 0xAF: $ ABS LAX CYC(4) break; // invalid
- case 0xB0: REL BCS CYC(2) break;
- case 0xB1: idy LDA CYC(5) break;
- case 0xB2: $ HLT CYC(2) break;
- case 0xB3: $ idy LAX CYC(5) break;
- case 0xB4: zpx LDY CYC(4) break;
- case 0xB5: zpx LDA CYC(4) break;
- case 0xB6: zpy LDX CYC(4) break;
- case 0xB7: $ zpy LAX CYC(4) break; // invalid
- case 0xB8: CLV CYC(2) break;
- case 0xB9: aby LDA CYC(4) break;
- case 0xBA: TSX CYC(2) break;
- case 0xBB: $ aby LAS CYC(4) break; // invalid
- case 0xBC: abx LDY CYC(4) break;
- case 0xBD: abx LDA CYC(4) break;
- case 0xBE: aby LDX CYC(4) break;
- case 0xBF: $ aby LAX CYC(4) break; // invalid
- case 0xC0: IMM CPY CYC(2) break;
- case 0xC1: idx CMP CYC(6) break;
- case 0xC2: $ IMM NOP CYC(2) break;
- case 0xC3: $ idx DCM CYC(8) break; // invalid
- case 0xC4: ZPG CPY CYC(3) break;
- case 0xC5: ZPG CMP CYC(3) break;
- case 0xC6: ZPG DECn CYC(5) break;
- case 0xC7: $ ZPG DCM CYC(5) break; // invalid
- case 0xC8: INY CYC(2) break;
- case 0xC9: IMM CMP CYC(2) break;
- case 0xCA: DEX CYC(2) break;
- case 0xCB: $ IMM SAX CYC(2) break; // invalid
- case 0xCC: ABS CPY CYC(4) break;
- case 0xCD: ABS CMP CYC(4) break;
- case 0xCE: ABS DECn CYC(5) break;
- case 0xCF: $ ABS DCM CYC(6) break; // invalid
- case 0xD0: REL BNE CYC(2) break;
- case 0xD1: idy CMP CYC(5) break;
- case 0xD2: $ HLT CYC(2) break;
- case 0xD3: $ idy DCM CYC(8) break; // invalid
- case 0xD4: $ zpx NOP CYC(4) break;
- case 0xD5: zpx CMP CYC(4) break;
- case 0xD6: zpx DECn CYC(6) break;
- case 0xD7: $ zpx DCM CYC(6) break; // invalid
- case 0xD8: CLD CYC(2) break;
- case 0xD9: aby CMP CYC(4) break;
- case 0xDA: $ NOP CYC(2) break;
- case 0xDB: $ aby DCM CYC(7) break; // invalid
- case 0xDC: $ abx NOP CYC(4) break;
- case 0xDD: abx CMP CYC(4) break;
- case 0xDE: abx DECn CYC(6) break;
- case 0xDF: $ abx DCM CYC(7) break; // invalid
- case 0xE0: IMM CPX CYC(2) break;
- case 0xE1: idx SBCn CYC(6) break;
- case 0xE2: $ IMM NOP CYC(2) break;
- case 0xE3: $ idx INS CYC(8) break; // invalid
- case 0xE4: ZPG CPX CYC(3) break;
- case 0xE5: ZPG SBCn CYC(3) break;
- case 0xE6: ZPG INCn CYC(5) break;
- case 0xE7: $ ZPG INS CYC(5) break; // invalid
- case 0xE8: INX CYC(2) break;
- case 0xE9: IMM SBCn CYC(2) break;
- case 0xEA: NOP CYC(2) break;
- case 0xEB: $ IMM SBCn CYC(2) break;
- case 0xEC: ABS CPX CYC(4) break;
- case 0xED: ABS SBCn CYC(4) break;
- case 0xEE: ABS INCn CYC(6) break;
- case 0xEF: $ ABS INS CYC(6) break; // invalid
- case 0xF0: REL BEQ CYC(2) break;
- case 0xF1: idy SBCn CYC(5) break;
- case 0xF2: $ HLT CYC(2) break;
- case 0xF3: $ idy INS CYC(8) break; // invalid
- case 0xF4: $ zpx NOP CYC(4) break;
- case 0xF5: zpx SBCn CYC(4) break;
- case 0xF6: zpx INCn CYC(6) break;
- case 0xF7: $ zpx INS CYC(6) break; // invalid
- case 0xF8: SED CYC(2) break;
- case 0xF9: aby SBCn CYC(4) break;
- case 0xFA: $ NOP CYC(2) break;
- case 0xFB: $ aby INS CYC(7) break;
- case 0xFC: $ abx NOP CYC(4) break;
- case 0xFD: abx SBCn CYC(4) break;
- case 0xFE: abx INCn CYC(6) break;
- case 0xFF: $ abx INS CYC(7) break;
- }
+ switch (iOpcode)
+ {
+ case 0x00: BRK CYC(7) break;
+ case 0x01: idx ORA CYC(6) break;
+ case 0x02: $ HLT CYC(2) break;
+ case 0x03: $ idx ASO CYC(8) break;
+ case 0x04: $ ZPG NOP CYC(3) break;
+ case 0x05: ZPG ORA CYC(3) break;
+ case 0x06: ZPG ASLn CYC(5) break;
+ case 0x07: $ ZPG ASO CYC(5) break;
+ case 0x08: PHP CYC(3) break;
+ case 0x09: IMM ORA CYC(2) break;
+ case 0x0A: asl CYC(2) break;
+ case 0x0B: $ IMM ANC CYC(2) break;
+ case 0x0C: $ ABSX_OPT NOP CYC(4) break;
+ case 0x0D: ABS ORA CYC(4) break;
+ case 0x0E: ABS ASLn CYC(6) break;
+ case 0x0F: $ ABS ASO CYC(6) break;
+ case 0x10: REL BPL CYC(2) break;
+ case 0x11: INDY_OPT ORA CYC(5) break;
+ case 0x12: $ HLT CYC(2) break;
+ case 0x13: $ INDY_CONST ASO CYC(8) break;
+ case 0x14: $ zpx NOP CYC(4) break;
+ case 0x15: zpx ORA CYC(4) break;
+ case 0x16: zpx ASLn CYC(6) break;
+ case 0x17: $ zpx ASO CYC(6) break;
+ case 0x18: CLC CYC(2) break;
+ case 0x19: ABSY_OPT ORA CYC(4) break;
+ case 0x1A: $ NOP CYC(2) break;
+ case 0x1B: $ ABSY_CONST ASO CYC(7) break;
+ case 0x1C: $ ABSX_OPT NOP CYC(4) break;
+ case 0x1D: ABSX_OPT ORA CYC(4) break;
+ case 0x1E: ABSX_CONST ASLn CYC(7) break;
+ case 0x1F: $ ABSX_CONST ASO CYC(7) break;
+ case 0x20: ABS JSR CYC(6) break;
+ case 0x21: idx AND CYC(6) break;
+ case 0x22: $ HLT CYC(2) break;
+ case 0x23: $ idx RLA CYC(8) break;
+ case 0x24: ZPG BIT CYC(3) break;
+ case 0x25: ZPG AND CYC(3) break;
+ case 0x26: ZPG ROLn CYC(5) break;
+ case 0x27: $ ZPG RLA CYC(5) break;
+ case 0x28: PLP CYC(4) break;
+ case 0x29: IMM AND CYC(2) break;
+ case 0x2A: rol CYC(2) break;
+ case 0x2B: $ IMM ANC CYC(2) break;
+ case 0x2C: ABS BIT CYC(4) break;
+ case 0x2D: ABS AND CYC(4) break;
+ case 0x2E: ABS ROLn CYC(6) break;
+ case 0x2F: $ ABS RLA CYC(6) break;
+ case 0x30: REL BMI CYC(2) break;
+ case 0x31: INDY_OPT AND CYC(5) break;
+ case 0x32: $ HLT CYC(2) break;
+ case 0x33: $ INDY_CONST RLA CYC(8) break;
+ case 0x34: $ zpx NOP CYC(4) break;
+ case 0x35: zpx AND CYC(4) break;
+ case 0x36: zpx ROLn CYC(6) break;
+ case 0x37: $ zpx RLA CYC(6) break;
+ case 0x38: SEC CYC(2) break;
+ case 0x39: ABSY_OPT AND CYC(4) break;
+ case 0x3A: $ NOP CYC(2) break;
+ case 0x3B: $ ABSY_CONST RLA CYC(7) break;
+ case 0x3C: $ ABSX_OPT NOP CYC(4) break;
+ case 0x3D: ABSX_OPT AND CYC(4) break;
+ case 0x3E: ABSX_CONST ROLn CYC(6) break;
+ case 0x3F: $ ABSX_CONST RLA CYC(7) break;
+ case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
+ case 0x41: idx EOR CYC(6) break;
+ case 0x42: $ HLT CYC(2) break;
+ case 0x43: $ idx LSE CYC(8) break;
+ case 0x44: $ ZPG NOP CYC(3) break;
+ case 0x45: ZPG EOR CYC(3) break;
+ case 0x46: ZPG LSRn CYC(5) break;
+ case 0x47: $ ZPG LSE CYC(5) break;
+ case 0x48: PHA CYC(3) break;
+ case 0x49: IMM EOR CYC(2) break;
+ case 0x4A: lsr CYC(2) break;
+ case 0x4B: $ IMM ALR CYC(2) break;
+ case 0x4C: ABS JMP CYC(3) break;
+ case 0x4D: ABS EOR CYC(4) break;
+ case 0x4E: ABS LSRn CYC(6) break;
+ case 0x4F: $ ABS LSE CYC(6) break;
+ case 0x50: REL BVC CYC(2) break;
+ case 0x51: INDY_OPT EOR CYC(5) break;
+ case 0x52: $ HLT CYC(2) break;
+ case 0x53: $ INDY_CONST LSE CYC(8) break;
+ case 0x54: $ zpx NOP CYC(4) break;
+ case 0x55: zpx EOR CYC(4) break;
+ case 0x56: zpx LSRn CYC(6) break;
+ case 0x57: $ zpx LSE CYC(6) break;
+ case 0x58: CLI CYC(2) break;
+ case 0x59: ABSY_OPT EOR CYC(4) break;
+ case 0x5A: $ NOP CYC(2) break;
+ case 0x5B: $ ABSY_CONST LSE CYC(7) break;
+ case 0x5C: $ ABSX_OPT NOP CYC(4) break;
+ case 0x5D: ABSX_OPT EOR CYC(4) break;
+ case 0x5E: ABSX_CONST LSRn CYC(6) break;
+ case 0x5F: $ ABSX_CONST LSE CYC(7) break;
+ case 0x60: RTS CYC(6) break;
+ case 0x61: idx ADCn CYC(6) break;
+ case 0x62: $ HLT CYC(2) break;
+ case 0x63: $ idx RRA CYC(8) break;
+ case 0x64: $ ZPG NOP CYC(3) break;
+ case 0x65: ZPG ADCn CYC(3) break;
+ case 0x66: ZPG RORn CYC(5) break;
+ case 0x67: $ ZPG RRA CYC(5) break;
+ case 0x68: PLA CYC(4) break;
+ case 0x69: IMM ADCn CYC(2) break;
+ case 0x6A: ror CYC(2) break;
+ case 0x6B: $ IMM ARR CYC(2) break;
+ case 0x6C: IABS_NMOS JMP CYC(5) break; // GH#264
+ case 0x6D: ABS ADCn CYC(4) break;
+ case 0x6E: ABS RORn CYC(6) break;
+ case 0x6F: $ ABS RRA CYC(6) break;
+ case 0x70: REL BVS CYC(2) break;
+ case 0x71: INDY_OPT ADCn CYC(5) break;
+ case 0x72: $ HLT CYC(2) break;
+ case 0x73: $ INDY_CONST RRA CYC(8) break;
+ case 0x74: $ zpx NOP CYC(4) break;
+ case 0x75: zpx ADCn CYC(4) break;
+ case 0x76: zpx RORn CYC(6) break;
+ case 0x77: $ zpx RRA CYC(6) break;
+ case 0x78: SEI CYC(2) break;
+ case 0x79: ABSY_OPT ADCn CYC(4) break;
+ case 0x7A: $ NOP CYC(2) break;
+ case 0x7B: $ ABSY_CONST RRA CYC(7) break;
+ case 0x7C: $ ABSX_OPT NOP CYC(4) break;
+ case 0x7D: ABSX_OPT ADCn CYC(4) break;
+ case 0x7E: ABSX_CONST RORn CYC(6) break;
+ case 0x7F: $ ABSX_CONST RRA CYC(7) break;
+ case 0x80: $ IMM NOP CYC(2) break;
+ case 0x81: idx STA CYC(6) break;
+ case 0x82: $ IMM NOP CYC(2) break;
+ case 0x83: $ idx AXS CYC(6) break;
+ case 0x84: ZPG STY CYC(3) break;
+ case 0x85: ZPG STA CYC(3) break;
+ case 0x86: ZPG STX CYC(3) break;
+ case 0x87: $ ZPG AXS CYC(3) break;
+ case 0x88: DEY CYC(2) break;
+ case 0x89: $ IMM NOP CYC(2) break;
+ case 0x8A: TXA CYC(2) break;
+ case 0x8B: $ IMM XAA CYC(2) break;
+ case 0x8C: ABS STY CYC(4) break;
+ case 0x8D: ABS STA CYC(4) break;
+ case 0x8E: ABS STX CYC(4) break;
+ case 0x8F: $ ABS AXS CYC(4) break;
+ case 0x90: REL BCC CYC(2) break;
+ case 0x91: INDY_CONST STA CYC(6) break;
+ case 0x92: $ HLT CYC(2) break;
+ case 0x93: $ INDY_CONST AXA CYC(6) break;
+ case 0x94: zpx STY CYC(4) break;
+ case 0x95: zpx STA CYC(4) break;
+ case 0x96: zpy STX CYC(4) break;
+ case 0x97: $ zpy AXS CYC(4) break;
+ case 0x98: TYA CYC(2) break;
+ case 0x99: ABSY_CONST STA CYC(5) break;
+ case 0x9A: TXS CYC(2) break;
+ case 0x9B: $ ABSY_CONST TAS CYC(5) break;
+ case 0x9C: $ ABSX_CONST SAY CYC(5) break;
+ case 0x9D: ABSX_CONST STA CYC(5) break;
+ case 0x9E: $ ABSY_CONST XAS CYC(5) break;
+ case 0x9F: $ ABSY_CONST AXA CYC(5) break;
+ case 0xA0: IMM LDY CYC(2) break;
+ case 0xA1: idx LDA CYC(6) break;
+ case 0xA2: IMM LDX CYC(2) break;
+ case 0xA3: $ idx LAX CYC(6) break;
+ case 0xA4: ZPG LDY CYC(3) break;
+ case 0xA5: ZPG LDA CYC(3) break;
+ case 0xA6: ZPG LDX CYC(3) break;
+ case 0xA7: $ ZPG LAX CYC(3) break;
+ case 0xA8: TAY CYC(2) break;
+ case 0xA9: IMM LDA CYC(2) break;
+ case 0xAA: TAX CYC(2) break;
+ case 0xAB: $ IMM OAL CYC(2) break;
+ case 0xAC: ABS LDY CYC(4) break;
+ case 0xAD: ABS LDA CYC(4) break;
+ case 0xAE: ABS LDX CYC(4) break;
+ case 0xAF: $ ABS LAX CYC(4) break;
+ case 0xB0: REL BCS CYC(2) break;
+ case 0xB1: INDY_OPT LDA CYC(5) break;
+ case 0xB2: $ HLT CYC(2) break;
+ case 0xB3: $ INDY_OPT LAX CYC(5) break;
+ case 0xB4: zpx LDY CYC(4) break;
+ case 0xB5: zpx LDA CYC(4) break;
+ case 0xB6: zpy LDX CYC(4) break;
+ case 0xB7: $ zpy LAX CYC(4) break;
+ case 0xB8: CLV CYC(2) break;
+ case 0xB9: ABSY_OPT LDA CYC(4) break;
+ case 0xBA: TSX CYC(2) break;
+ case 0xBB: $ ABSY_OPT LAS CYC(4) break;
+ case 0xBC: ABSX_OPT LDY CYC(4) break;
+ case 0xBD: ABSX_OPT LDA CYC(4) break;
+ case 0xBE: ABSY_OPT LDX CYC(4) break;
+ case 0xBF: $ ABSY_OPT LAX CYC(4) break;
+ case 0xC0: IMM CPY CYC(2) break;
+ case 0xC1: idx CMP CYC(6) break;
+ case 0xC2: $ IMM NOP CYC(2) break;
+ case 0xC3: $ idx DCM CYC(8) break;
+ case 0xC4: ZPG CPY CYC(3) break;
+ case 0xC5: ZPG CMP CYC(3) break;
+ case 0xC6: ZPG DEC CYC(5) break;
+ case 0xC7: $ ZPG DCM CYC(5) break;
+ case 0xC8: INY CYC(2) break;
+ case 0xC9: IMM CMP CYC(2) break;
+ case 0xCA: DEX CYC(2) break;
+ case 0xCB: $ IMM SAX CYC(2) break;
+ case 0xCC: ABS CPY CYC(4) break;
+ case 0xCD: ABS CMP CYC(4) break;
+ case 0xCE: ABS DEC CYC(6) break;
+ case 0xCF: $ ABS DCM CYC(6) break;
+ case 0xD0: REL BNE CYC(2) break;
+ case 0xD1: INDY_OPT CMP CYC(5) break;
+ case 0xD2: $ HLT CYC(2) break;
+ case 0xD3: $ INDY_CONST DCM CYC(8) break;
+ case 0xD4: $ zpx NOP CYC(4) break;
+ case 0xD5: zpx CMP CYC(4) break;
+ case 0xD6: zpx DEC CYC(6) break;
+ case 0xD7: $ zpx DCM CYC(6) break;
+ case 0xD8: CLD CYC(2) break;
+ case 0xD9: ABSY_OPT CMP CYC(4) break;
+ case 0xDA: $ NOP CYC(2) break;
+ case 0xDB: $ ABSY_CONST DCM CYC(7) break;
+ case 0xDC: $ ABSX_OPT NOP CYC(4) break;
+ case 0xDD: ABSX_OPT CMP CYC(4) break;
+ case 0xDE: ABSX_CONST DEC CYC(7) break;
+ case 0xDF: $ ABSX_CONST DCM CYC(7) break;
+ case 0xE0: IMM CPX CYC(2) break;
+ case 0xE1: idx SBCn CYC(6) break;
+ case 0xE2: $ IMM NOP CYC(2) break;
+ case 0xE3: $ idx INS CYC(8) break;
+ case 0xE4: ZPG CPX CYC(3) break;
+ case 0xE5: ZPG SBCn CYC(3) break;
+ case 0xE6: ZPG INC CYC(5) break;
+ case 0xE7: $ ZPG INS CYC(5) break;
+ case 0xE8: INX CYC(2) break;
+ case 0xE9: IMM SBCn CYC(2) break;
+ case 0xEA: NOP CYC(2) break;
+ case 0xEB: $ IMM SBCn CYC(2) break;
+ case 0xEC: ABS CPX CYC(4) break;
+ case 0xED: ABS SBCn CYC(4) break;
+ case 0xEE: ABS INC CYC(6) break;
+ case 0xEF: $ ABS INS CYC(6) break;
+ case 0xF0: REL BEQ CYC(2) break;
+ case 0xF1: INDY_OPT SBCn CYC(5) break;
+ case 0xF2: $ HLT CYC(2) break;
+ case 0xF3: $ INDY_CONST INS CYC(8) break;
+ case 0xF4: $ zpx NOP CYC(4) break;
+ case 0xF5: zpx SBCn CYC(4) break;
+ case 0xF6: zpx INC CYC(6) break;
+ case 0xF7: $ zpx INS CYC(6) break;
+ case 0xF8: SED CYC(2) break;
+ case 0xF9: ABSY_OPT SBCn CYC(4) break;
+ case 0xFA: $ NOP CYC(2) break;
+ case 0xFB: $ ABSY_CONST INS CYC(7) break;
+ case 0xFC: $ ABSX_OPT NOP CYC(4) break;
+ case 0xFD: ABSX_OPT SBCn CYC(4) break;
+ case 0xFE: ABSX_CONST INC CYC(7) break;
+ case 0xFF: $ ABSX_CONST INS CYC(7) break;
+ }
+#undef $
}
// NTSC_BEGIN
diff --git a/source/CPU/cpu65C02.h b/source/CPU/cpu65C02.h
index a85e3c04..d9ad28c5 100644
--- a/source/CPU/cpu65C02.h
+++ b/source/CPU/cpu65C02.h
@@ -38,7 +38,6 @@ static DWORD Cpu65C02 (DWORD uTotalCycles)
WORD val;
AF_TO_EF
ULONG uExecutedCycles = 0;
- BOOL bSlowerOnPagecross = 0; // Set if opcode writes to memory (eg. ASL, STA)
WORD base;
g_bDebugBreakpointHit = 0;
@@ -52,7 +51,7 @@ static DWORD Cpu65C02 (DWORD uTotalCycles)
ULONG uPreviousCycles = uExecutedCycles;
// NTSC_END
- if (g_ActiveCPU == CPU_Z80)
+ if (GetActiveCpu() == CPU_Z80)
{
const UINT uZ80Cycles = z80_mainloop(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles)
}
@@ -61,265 +60,265 @@ static DWORD Cpu65C02 (DWORD uTotalCycles)
if (!Fetch(iOpcode, uExecutedCycles))
break;
+#define $ INV // INV = Invalid -> Debugger Break
switch (iOpcode)
{
-#define $ INV // INV = Invalid -> Debugger Break
- case 0x00: BRK CYC(7) break;
- case 0x01: idx ORA CYC(6) break;
- case 0x02: $ IMM NOP CYC(2) break;
- case 0x03: $ NOP CYC(2) break;
- case 0x04: ZPG TSB CYC(5) break;
- case 0x05: ZPG ORA CYC(3) break;
- case 0x06: ZPG ASLc CYC(5) break;
- case 0x07: $ NOP CYC(2) break;
- case 0x08: PHP CYC(3) break;
- case 0x09: IMM ORA CYC(2) break;
- case 0x0A: asl CYC(2) break;
- case 0x0B: $ NOP CYC(2) break;
- case 0x0C: ABS TSB CYC(6) break;
- case 0x0D: ABS ORA CYC(4) break;
- case 0x0E: ABS ASLc CYC(6) break;
- case 0x0F: $ NOP CYC(2) break;
- case 0x10: REL BPL CYC(2) break;
- case 0x11: idy ORA CYC(5) break;
- case 0x12: izp ORA CYC(5) break;
- case 0x13: $ NOP CYC(2) break;
- case 0x14: ZPG TRB CYC(5) break;
- case 0x15: zpx ORA CYC(4) break;
- case 0x16: zpx ASLc CYC(6) break;
- case 0x17: $ NOP CYC(2) break;
- case 0x18: CLC CYC(2) break;
- case 0x19: aby ORA CYC(4) break;
- case 0x1A: INA CYC(2) break;
- case 0x1B: $ NOP CYC(2) break;
- case 0x1C: ABS TRB CYC(6) break;
- case 0x1D: abx ORA CYC(4) break;
- case 0x1E: abx ASLc CYC(6) break;
- case 0x1F: $ NOP CYC(2) break;
- case 0x20: ABS JSR CYC(6) break;
- case 0x21: idx AND CYC(6) break;
- case 0x22: $ IMM NOP CYC(2) break;
- case 0x23: $ NOP CYC(2) break;
- case 0x24: ZPG BIT CYC(3) break;
- case 0x25: ZPG AND CYC(3) break;
- case 0x26: ZPG ROLc CYC(5) break;
- case 0x27: $ NOP CYC(2) break;
- case 0x28: PLP CYC(4) break;
- case 0x29: IMM AND CYC(2) break;
- case 0x2A: rol CYC(2) break;
- case 0x2B: $ NOP CYC(2) break;
- case 0x2C: ABS BIT CYC(4) break;
- case 0x2D: ABS AND CYC(2) break;
- case 0x2E: ABS ROLc CYC(6) break;
- case 0x2F: $ NOP CYC(2) break;
- case 0x30: REL BMI CYC(2) break;
- case 0x31: idy AND CYC(5) break;
- case 0x32: izp AND CYC(5) break;
- case 0x33: $ NOP CYC(2) break;
- case 0x34: zpx BIT CYC(4) break;
- case 0x35: zpx AND CYC(4) break;
- case 0x36: zpx ROLc CYC(6) break;
- case 0x37: $ NOP CYC(2) break;
- case 0x38: SEC CYC(2) break;
- case 0x39: aby AND CYC(4) break;
- case 0x3A: DEA CYC(2) break;
- case 0x3B: $ NOP CYC(2) break;
- case 0x3C: abx BIT CYC(4) break;
- case 0x3D: abx AND CYC(4) break;
- case 0x3E: abx ROLc CYC(6) break;
- case 0x3F: $ NOP CYC(2) break;
- case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
- case 0x41: idx EOR CYC(6) break;
- case 0x42: $ IMM NOP CYC(2) break;
- case 0x43: $ NOP CYC(2) break;
- case 0x44: $ ZPG NOP CYC(3) break;
- case 0x45: ZPG EOR CYC(3) break;
- case 0x46: ZPG LSRc CYC(5) break;
- case 0x47: $ NOP CYC(2) break;
- case 0x48: PHA CYC(3) break;
- case 0x49: IMM EOR CYC(2) break;
- case 0x4A: lsr CYC(2) break;
- case 0x4B: $ NOP CYC(2) break;
- case 0x4C: ABS JMP CYC(3) break;
- case 0x4D: ABS EOR CYC(4) break;
- case 0x4E: ABS LSRc CYC(6) break;
- case 0x4F: $ NOP CYC(2) break;
- case 0x50: REL BVC CYC(2) break;
- case 0x51: idy EOR CYC(5) break;
- case 0x52: izp EOR CYC(5) break;
- case 0x53: $ NOP CYC(2) break;
- case 0x54: $ zpx NOP CYC(4) break;
- case 0x55: zpx EOR CYC(4) break;
- case 0x56: zpx LSRc CYC(6) break;
- case 0x57: $ NOP CYC(2) break;
- case 0x58: CLI CYC(2) break;
- case 0x59: aby EOR CYC(4) break;
- case 0x5A: PHY CYC(3) break;
- case 0x5B: $ NOP CYC(2) break;
- case 0x5C: $ abx NOP CYC(8) break;
- case 0x5D: abx EOR CYC(4) break;
- case 0x5E: abx LSRc CYC(6) break;
- case 0x5F: $ NOP CYC(2) break;
- case 0x60: RTS CYC(6) break;
- case 0x61: idx ADCc CYC(6) break;
- case 0x62: $ IMM NOP CYC(2) break;
- case 0x63: $ NOP CYC(2) break;
- case 0x64: ZPG STZ CYC(3) break;
- case 0x65: ZPG ADCc CYC(3) break;
- case 0x66: ZPG RORc CYC(5) break;
- case 0x67: $ NOP CYC(2) break;
- case 0x68: PLA CYC(4) break;
- case 0x69: IMM ADCc CYC(2) break;
- case 0x6A: ror CYC(2) break;
- case 0x6B: $ NOP CYC(2) break;
- case 0x6C: IABSCMOS JMP CYC(6) break;
- case 0x6D: ABS ADCc CYC(4) break;
- case 0x6E: ABS RORc CYC(6) break;
- case 0x6F: $ NOP CYC(2) break;
- case 0x70: REL BVS CYC(2) break;
- case 0x71: idy ADCc CYC(5) break;
- case 0x72: izp ADCc CYC(5) break;
- case 0x73: $ NOP CYC(2) break;
- case 0x74: zpx STZ CYC(4) break;
- case 0x75: zpx ADCc CYC(4) break;
- case 0x76: zpx RORc CYC(6) break;
- case 0x77: $ NOP CYC(2) break;
- case 0x78: SEI CYC(2) break;
- case 0x79: aby ADCc CYC(4) break;
- case 0x7A: PLY CYC(4) break;
- case 0x7B: $ NOP CYC(2) break;
- case 0x7C: IABSX JMP CYC(6) break; //
- case 0x7D: abx ADCc CYC(4) break;
- case 0x7E: abx RORc CYC(6) break;
- case 0x7F: $ NOP CYC(2) break;
- case 0x80: REL BRA CYC(2) break;
- case 0x81: idx STA CYC(6) break;
- case 0x82: $ IMM NOP CYC(2) break;
- case 0x83: $ NOP CYC(2) break;
- case 0x84: ZPG STY CYC(3) break;
- case 0x85: ZPG STA CYC(3) break;
- case 0x86: ZPG STX CYC(3) break;
- case 0x87: $ NOP CYC(2) break;
- case 0x88: DEY CYC(2) break;
- case 0x89: IMM BITI CYC(2) break;
- case 0x8A: TXA CYC(2) break;
- case 0x8B: $ NOP CYC(2) break;
- case 0x8C: ABS STY CYC(4) break;
- case 0x8D: ABS STA CYC(4) break;
- case 0x8E: ABS STX CYC(4) break;
- case 0x8F: $ NOP CYC(2) break;
- case 0x90: REL BCC CYC(2) break;
- case 0x91: idy STA CYC(6) break;
- case 0x92: izp STA CYC(5) break;
- case 0x93: $ NOP CYC(2) break;
- case 0x94: zpx STY CYC(4) break;
- case 0x95: zpx STA CYC(4) break;
- case 0x96: zpy STX CYC(4) break;
- case 0x97: $ NOP CYC(2) break;
- case 0x98: TYA CYC(2) break;
- case 0x99: aby STA CYC(5) break;
- case 0x9A: TXS CYC(2) break;
- case 0x9B: $ NOP CYC(2) break;
- case 0x9C: ABS STZ CYC(4) break;
- case 0x9D: abx STA CYC(5) break;
- case 0x9E: abx STZ CYC(5) break;
- case 0x9F: $ NOP CYC(2) break;
- case 0xA0: IMM LDY CYC(2) break;
- case 0xA1: idx LDA CYC(6) break;
- case 0xA2: IMM LDX CYC(2) break;
- case 0xA3: $ NOP CYC(2) break;
- case 0xA4: ZPG LDY CYC(3) break;
- case 0xA5: ZPG LDA CYC(3) break;
- case 0xA6: ZPG LDX CYC(3) break;
- case 0xA7: $ NOP CYC(2) break;
- case 0xA8: TAY CYC(2) break;
- case 0xA9: IMM LDA CYC(2) break;
- case 0xAA: TAX CYC(2) break;
- case 0xAB: $ NOP CYC(2) break;
- case 0xAC: ABS LDY CYC(4) break;
- case 0xAD: ABS LDA CYC(4) break;
- case 0xAE: ABS LDX CYC(4) break;
- case 0xAF: $ NOP CYC(2) break;
- case 0xB0: REL BCS CYC(2) break;
- case 0xB1: idy LDA CYC(5) break;
- case 0xB2: izp LDA CYC(5) break;
- case 0xB3: $ NOP CYC(2) break;
- case 0xB4: zpx LDY CYC(4) break;
- case 0xB5: zpx LDA CYC(4) break;
- case 0xB6: zpy LDX CYC(4) break;
- case 0xB7: $ NOP CYC(2) break;
- case 0xB8: CLV CYC(2) break;
- case 0xB9: aby LDA CYC(4) break;
- case 0xBA: TSX CYC(2) break;
- case 0xBB: $ NOP CYC(2) break;
- case 0xBC: abx LDY CYC(4) break;
- case 0xBD: abx LDA CYC(4) break;
- case 0xBE: aby LDX CYC(4) break;
- case 0xBF: $ NOP CYC(2) break;
- case 0xC0: IMM CPY CYC(2) break;
- case 0xC1: idx CMP CYC(6) break;
- case 0xC2: $ IMM NOP CYC(2) break;
- case 0xC3: $ NOP CYC(2) break;
- case 0xC4: ZPG CPY CYC(3) break;
- case 0xC5: ZPG CMP CYC(3) break;
- case 0xC6: ZPG DECc CYC(5) break;
- case 0xC7: $ NOP CYC(2) break;
- case 0xC8: INY CYC(2) break;
- case 0xC9: IMM CMP CYC(2) break;
- case 0xCA: DEX CYC(2) break;
- case 0xCB: $ NOP CYC(2) break;
- case 0xCC: ABS CPY CYC(4) break;
- case 0xCD: ABS CMP CYC(4) break;
- case 0xCE: ABS DECc CYC(5) break;
- case 0xCF: $ NOP CYC(2) break;
- case 0xD0: REL BNE CYC(2) break;
- case 0xD1: idy CMP CYC(5) break;
- case 0xD2: izp CMP CYC(5) break;
- case 0xD3: $ NOP CYC(2) break;
- case 0xD4: $ zpx NOP CYC(4) break;
- case 0xD5: zpx CMP CYC(4) break;
- case 0xD6: zpx DECc CYC(6) break;
- case 0xD7: $ NOP CYC(2) break;
- case 0xD8: CLD CYC(2) break;
- case 0xD9: aby CMP CYC(4) break;
- case 0xDA: PHX CYC(3) break;
- case 0xDB: $ NOP CYC(2) break;
- case 0xDC: $ abx NOP CYC(4) break;
- case 0xDD: abx CMP CYC(4) break;
- case 0xDE: abx DECc CYC(6) break;
- case 0xDF: $ NOP CYC(2) break;
- case 0xE0: IMM CPX CYC(2) break;
- case 0xE1: idx SBCc CYC(6) break;
- case 0xE2: $ IMM NOP CYC(2) break;
- case 0xE3: $ NOP CYC(2) break;
- case 0xE4: ZPG CPX CYC(3) break;
- case 0xE5: ZPG SBCc CYC(3) break;
- case 0xE6: ZPG INCc CYC(5) break;
- case 0xE7: $ NOP CYC(2) break;
- case 0xE8: INX CYC(2) break;
- case 0xE9: IMM SBCc CYC(2) break;
- case 0xEA: NOP CYC(2) break;
- case 0xEB: $ NOP CYC(2) break;
- case 0xEC: ABS CPX CYC(4) break;
- case 0xED: ABS SBCc CYC(4) break;
- case 0xEE: ABS INCc CYC(6) break;
- case 0xEF: $ NOP CYC(2) break;
- case 0xF0: REL BEQ CYC(2) break;
- case 0xF1: idy SBCc CYC(5) break;
- case 0xF2: izp SBCc CYC(5) break;
- case 0xF3: $ NOP CYC(2) break;
- case 0xF4: $ zpx NOP CYC(4) break;
- case 0xF5: zpx SBCc CYC(4) break;
- case 0xF6: zpx INCc CYC(6) break;
- case 0xF7: $ NOP CYC(2) break;
- case 0xF8: SED CYC(2) break;
- case 0xF9: aby SBCc CYC(4) break;
- case 0xFA: PLX CYC(4) break;
- case 0xFB: $ NOP CYC(2) break;
- case 0xFC: $ abx NOP CYC(4) break;
- case 0xFD: abx SBCc CYC(4) break;
- case 0xFE: abx INCc CYC(6) break;
- case 0xFF: $ NOP CYC(2) break;
+ case 0x00: BRK CYC(7) break;
+ case 0x01: idx ORA CYC(6) break;
+ case 0x02: $ IMM NOP CYC(2) break;
+ case 0x03: $ NOP CYC(1) break;
+ case 0x04: ZPG TSB CYC(5) break;
+ case 0x05: ZPG ORA CYC(3) break;
+ case 0x06: ZPG ASLc CYC(5) break;
+ case 0x07: $ NOP CYC(1) break;
+ case 0x08: PHP CYC(3) break;
+ case 0x09: IMM ORA CYC(2) break;
+ case 0x0A: asl CYC(2) break;
+ case 0x0B: $ NOP CYC(1) break;
+ case 0x0C: ABS TSB CYC(6) break;
+ case 0x0D: ABS ORA CYC(4) break;
+ case 0x0E: ABS ASLc CYC(6) break;
+ case 0x0F: $ NOP CYC(1) break;
+ case 0x10: REL BPL CYC(2) break;
+ case 0x11: INDY_OPT ORA CYC(5) break;
+ case 0x12: izp ORA CYC(5) break;
+ case 0x13: $ NOP CYC(1) break;
+ case 0x14: ZPG TRB CYC(5) break;
+ case 0x15: zpx ORA CYC(4) break;
+ case 0x16: zpx ASLc CYC(6) break;
+ case 0x17: $ NOP CYC(1) break;
+ case 0x18: CLC CYC(2) break;
+ case 0x19: ABSY_OPT ORA CYC(4) break;
+ case 0x1A: INA CYC(2) break;
+ case 0x1B: $ NOP CYC(1) break;
+ case 0x1C: ABS TRB CYC(6) break;
+ case 0x1D: ABSX_OPT ORA CYC(4) break;
+ case 0x1E: ABSX_OPT ASLc CYC(6) break;
+ case 0x1F: $ NOP CYC(1) break;
+ case 0x20: ABS JSR CYC(6) break;
+ case 0x21: idx AND CYC(6) break;
+ case 0x22: $ IMM NOP CYC(2) break;
+ case 0x23: $ NOP CYC(1) break;
+ case 0x24: ZPG BIT CYC(3) break;
+ case 0x25: ZPG AND CYC(3) break;
+ case 0x26: ZPG ROLc CYC(5) break;
+ case 0x27: $ NOP CYC(1) break;
+ case 0x28: PLP CYC(4) break;
+ case 0x29: IMM AND CYC(2) break;
+ case 0x2A: rol CYC(2) break;
+ case 0x2B: $ NOP CYC(1) break;
+ case 0x2C: ABS BIT CYC(4) break;
+ case 0x2D: ABS AND CYC(4) break;
+ case 0x2E: ABS ROLc CYC(6) break;
+ case 0x2F: $ NOP CYC(1) break;
+ case 0x30: REL BMI CYC(2) break;
+ case 0x31: INDY_OPT AND CYC(5) break;
+ case 0x32: izp AND CYC(5) break;
+ case 0x33: $ NOP CYC(1) break;
+ case 0x34: zpx BIT CYC(4) break;
+ case 0x35: zpx AND CYC(4) break;
+ case 0x36: zpx ROLc CYC(6) break;
+ case 0x37: $ NOP CYC(1) break;
+ case 0x38: SEC CYC(2) break;
+ case 0x39: ABSY_OPT AND CYC(4) break;
+ case 0x3A: DEA CYC(2) break;
+ case 0x3B: $ NOP CYC(1) break;
+ case 0x3C: ABSX_OPT BIT CYC(4) break;
+ case 0x3D: ABSX_OPT AND CYC(4) break;
+ case 0x3E: ABSX_OPT ROLc CYC(6) break;
+ case 0x3F: $ NOP CYC(1) break;
+ case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
+ case 0x41: idx EOR CYC(6) break;
+ case 0x42: $ IMM NOP CYC(2) break;
+ case 0x43: $ NOP CYC(1) break;
+ case 0x44: $ ZPG NOP CYC(3) break;
+ case 0x45: ZPG EOR CYC(3) break;
+ case 0x46: ZPG LSRc CYC(5) break;
+ case 0x47: $ NOP CYC(1) break;
+ case 0x48: PHA CYC(3) break;
+ case 0x49: IMM EOR CYC(2) break;
+ case 0x4A: lsr CYC(2) break;
+ case 0x4B: $ NOP CYC(1) break;
+ case 0x4C: ABS JMP CYC(3) break;
+ case 0x4D: ABS EOR CYC(4) break;
+ case 0x4E: ABS LSRc CYC(6) break;
+ case 0x4F: $ NOP CYC(1) break;
+ case 0x50: REL BVC CYC(2) break;
+ case 0x51: INDY_OPT EOR CYC(5) break;
+ case 0x52: izp EOR CYC(5) break;
+ case 0x53: $ NOP CYC(1) break;
+ case 0x54: $ zpx NOP CYC(4) break;
+ case 0x55: zpx EOR CYC(4) break;
+ case 0x56: zpx LSRc CYC(6) break;
+ case 0x57: $ NOP CYC(1) break;
+ case 0x58: CLI CYC(2) break;
+ case 0x59: ABSY_OPT EOR CYC(4) break;
+ case 0x5A: PHY CYC(3) break;
+ case 0x5B: $ NOP CYC(1) break;
+ case 0x5C: $ ABS NOP CYC(8) break;
+ case 0x5D: ABSX_OPT EOR CYC(4) break;
+ case 0x5E: ABSX_OPT LSRc CYC(6) break;
+ case 0x5F: $ NOP CYC(1) break;
+ case 0x60: RTS CYC(6) break;
+ case 0x61: idx ADCc CYC(6) break;
+ case 0x62: $ IMM NOP CYC(2) break;
+ case 0x63: $ NOP CYC(1) break;
+ case 0x64: ZPG STZ CYC(3) break;
+ case 0x65: ZPG ADCc CYC(3) break;
+ case 0x66: ZPG RORc CYC(5) break;
+ case 0x67: $ NOP CYC(1) break;
+ case 0x68: PLA CYC(4) break;
+ case 0x69: IMM ADCc CYC(2) break;
+ case 0x6A: ror CYC(2) break;
+ case 0x6B: $ NOP CYC(1) break;
+ case 0x6C: IABS_CMOS JMP CYC(6) break;
+ case 0x6D: ABS ADCc CYC(4) break;
+ case 0x6E: ABS RORc CYC(6) break;
+ case 0x6F: $ NOP CYC(1) break;
+ case 0x70: REL BVS CYC(2) break;
+ case 0x71: INDY_OPT ADCc CYC(5) break;
+ case 0x72: izp ADCc CYC(5) break;
+ case 0x73: $ NOP CYC(1) break;
+ case 0x74: zpx STZ CYC(4) break;
+ case 0x75: zpx ADCc CYC(4) break;
+ case 0x76: zpx RORc CYC(6) break;
+ case 0x77: $ NOP CYC(1) break;
+ case 0x78: SEI CYC(2) break;
+ case 0x79: ABSY_OPT ADCc CYC(4) break;
+ case 0x7A: PLY CYC(4) break;
+ case 0x7B: $ NOP CYC(1) break;
+ case 0x7C: IABSX JMP CYC(6) break;
+ case 0x7D: ABSX_OPT ADCc CYC(4) break;
+ case 0x7E: ABSX_OPT RORc CYC(6) break;
+ case 0x7F: $ NOP CYC(1) break;
+ case 0x80: REL BRA CYC(2) break;
+ case 0x81: idx STA CYC(6) break;
+ case 0x82: $ IMM NOP CYC(2) break;
+ case 0x83: $ NOP CYC(1) break;
+ case 0x84: ZPG STY CYC(3) break;
+ case 0x85: ZPG STA CYC(3) break;
+ case 0x86: ZPG STX CYC(3) break;
+ case 0x87: $ NOP CYC(1) break;
+ case 0x88: DEY CYC(2) break;
+ case 0x89: IMM BITI CYC(2) break;
+ case 0x8A: TXA CYC(2) break;
+ case 0x8B: $ NOP CYC(1) break;
+ case 0x8C: ABS STY CYC(4) break;
+ case 0x8D: ABS STA CYC(4) break;
+ case 0x8E: ABS STX CYC(4) break;
+ case 0x8F: $ NOP CYC(1) break;
+ case 0x90: REL BCC CYC(2) break;
+ case 0x91: INDY_CONST STA CYC(6) break;
+ case 0x92: izp STA CYC(5) break;
+ case 0x93: $ NOP CYC(1) break;
+ case 0x94: zpx STY CYC(4) break;
+ case 0x95: zpx STA CYC(4) break;
+ case 0x96: zpy STX CYC(4) break;
+ case 0x97: $ NOP CYC(1) break;
+ case 0x98: TYA CYC(2) break;
+ case 0x99: ABSY_CONST STA CYC(5) break;
+ case 0x9A: TXS CYC(2) break;
+ case 0x9B: $ NOP CYC(1) break;
+ case 0x9C: ABS STZ CYC(4) break;
+ case 0x9D: ABSX_CONST STA CYC(5) break;
+ case 0x9E: ABSX_CONST STZ CYC(5) break;
+ case 0x9F: $ NOP CYC(1) break;
+ case 0xA0: IMM LDY CYC(2) break;
+ case 0xA1: idx LDA CYC(6) break;
+ case 0xA2: IMM LDX CYC(2) break;
+ case 0xA3: $ NOP CYC(1) break;
+ case 0xA4: ZPG LDY CYC(3) break;
+ case 0xA5: ZPG LDA CYC(3) break;
+ case 0xA6: ZPG LDX CYC(3) break;
+ case 0xA7: $ NOP CYC(1) break;
+ case 0xA8: TAY CYC(2) break;
+ case 0xA9: IMM LDA CYC(2) break;
+ case 0xAA: TAX CYC(2) break;
+ case 0xAB: $ NOP CYC(1) break;
+ case 0xAC: ABS LDY CYC(4) break;
+ case 0xAD: ABS LDA CYC(4) break;
+ case 0xAE: ABS LDX CYC(4) break;
+ case 0xAF: $ NOP CYC(1) break;
+ case 0xB0: REL BCS CYC(2) break;
+ case 0xB1: INDY_OPT LDA CYC(5) break;
+ case 0xB2: izp LDA CYC(5) break;
+ case 0xB3: $ NOP CYC(1) break;
+ case 0xB4: zpx LDY CYC(4) break;
+ case 0xB5: zpx LDA CYC(4) break;
+ case 0xB6: zpy LDX CYC(4) break;
+ case 0xB7: $ NOP CYC(1) break;
+ case 0xB8: CLV CYC(2) break;
+ case 0xB9: ABSY_OPT LDA CYC(4) break;
+ case 0xBA: TSX CYC(2) break;
+ case 0xBB: $ NOP CYC(1) break;
+ case 0xBC: ABSX_OPT LDY CYC(4) break;
+ case 0xBD: ABSX_OPT LDA CYC(4) break;
+ case 0xBE: ABSY_OPT LDX CYC(4) break;
+ case 0xBF: $ NOP CYC(1) break;
+ case 0xC0: IMM CPY CYC(2) break;
+ case 0xC1: idx CMP CYC(6) break;
+ case 0xC2: $ IMM NOP CYC(2) break;
+ case 0xC3: $ NOP CYC(1) break;
+ case 0xC4: ZPG CPY CYC(3) break;
+ case 0xC5: ZPG CMP CYC(3) break;
+ case 0xC6: ZPG DEC CYC(5) break;
+ case 0xC7: $ NOP CYC(1) break;
+ case 0xC8: INY CYC(2) break;
+ case 0xC9: IMM CMP CYC(2) break;
+ case 0xCA: DEX CYC(2) break;
+ case 0xCB: $ NOP CYC(1) break;
+ case 0xCC: ABS CPY CYC(4) break;
+ case 0xCD: ABS CMP CYC(4) break;
+ case 0xCE: ABS DEC CYC(6) break;
+ case 0xCF: $ NOP CYC(1) break;
+ case 0xD0: REL BNE CYC(2) break;
+ case 0xD1: INDY_OPT CMP CYC(5) break;
+ case 0xD2: izp CMP CYC(5) break;
+ case 0xD3: $ NOP CYC(1) break;
+ case 0xD4: $ zpx NOP CYC(4) break;
+ case 0xD5: zpx CMP CYC(4) break;
+ case 0xD6: zpx DEC CYC(6) break;
+ case 0xD7: $ NOP CYC(1) break;
+ case 0xD8: CLD CYC(2) break;
+ case 0xD9: ABSY_OPT CMP CYC(4) break;
+ case 0xDA: PHX CYC(3) break;
+ case 0xDB: $ NOP CYC(1) break;
+ case 0xDC: $ ABS LDD CYC(4) break;
+ case 0xDD: ABSX_OPT CMP CYC(4) break;
+ case 0xDE: ABSX_CONST DEC CYC(7) break;
+ case 0xDF: $ NOP CYC(1) break;
+ case 0xE0: IMM CPX CYC(2) break;
+ case 0xE1: idx SBCc CYC(6) break;
+ case 0xE2: $ IMM NOP CYC(2) break;
+ case 0xE3: $ NOP CYC(1) break;
+ case 0xE4: ZPG CPX CYC(3) break;
+ case 0xE5: ZPG SBCc CYC(3) break;
+ case 0xE6: ZPG INC CYC(5) break;
+ case 0xE7: $ NOP CYC(1) break;
+ case 0xE8: INX CYC(2) break;
+ case 0xE9: IMM SBCc CYC(2) break;
+ case 0xEA: NOP CYC(2) break;
+ case 0xEB: $ NOP CYC(1) break;
+ case 0xEC: ABS CPX CYC(4) break;
+ case 0xED: ABS SBCc CYC(4) break;
+ case 0xEE: ABS INC CYC(6) break;
+ case 0xEF: $ NOP CYC(1) break;
+ case 0xF0: REL BEQ CYC(2) break;
+ case 0xF1: INDY_OPT SBCc CYC(5) break;
+ case 0xF2: izp SBCc CYC(5) break;
+ case 0xF3: $ NOP CYC(1) break;
+ case 0xF4: $ zpx NOP CYC(4) break;
+ case 0xF5: zpx SBCc CYC(4) break;
+ case 0xF6: zpx INC CYC(6) break;
+ case 0xF7: $ NOP CYC(1) break;
+ case 0xF8: SED CYC(2) break;
+ case 0xF9: ABSY_OPT SBCc CYC(4) break;
+ case 0xFA: PLX CYC(4) break;
+ case 0xFB: $ NOP CYC(1) break;
+ case 0xFC: $ ABS LDD CYC(4) break;
+ case 0xFD: ABSX_OPT SBCc CYC(4) break;
+ case 0xFE: ABSX_CONST INC CYC(7) break;
+ case 0xFF: $ NOP CYC(1) break;
}
#undef $
}
diff --git a/source/CPU/cpu65d02.h b/source/CPU/cpu65d02.h
index bd55a933..7c3d34ed 100644
--- a/source/CPU/cpu65d02.h
+++ b/source/CPU/cpu65d02.h
@@ -18,8 +18,8 @@ along with AppleWin; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-typedef unsigned char u8;
-typedef unsigned short u16;
+typedef unsigned char u8; // TODO: change to uint8_t
+typedef unsigned short u16; // TODO: change to uint16_t
// return (x < 255) ? (x+1) : 255;
inline u8 IncClamp8( u8 x )
@@ -37,43 +37,58 @@ inline u8 DecClamp8( u8 x )
return r;
}
+// TODO: Verify: RGBA or BGRA (.bmp format)
// 0 A n/a
// 1 B Exec
// 2 G Read
// 3 R Write
-// RGBA r= write, g = read, b = pc
-int g_aMemoryAccess[ 65536 ];
-u8 *g_pRead = 0;
-u8 *g_pWrite = 0;
-u8 *g_pExeec = 0;
+//
+// 0xAARRGGBB
+// [0] B Exec
+// [1] G Load
+// [2] R Store
+// [3] A n/a
+// RGBA r = write, g = read, b = Program Counter
+const int HEATMAP_W_MASK = 0x00FF0000; // Red Store
+const int HEATMAP_R_MASK = 0x0000FF00; // Green Load
+const int HEATMAP_X_MASK = 0x000000FF; // Blue Exec
+
+
+// This is a memory heatmap
+// FF = accessed on this clock cycle
+// FE = accessed 1 clock cycles ago
+// FD = accessed 2 clock cycles ago
+// etc.
+// Displayed as 256x256 64K memory access
+int g_aMemoryHeatmap[ 65536 ]; // TODO: Change to int32_t
+
+#define HEATMAP_W(addr) g_aMemoryHeatmap[ addr ] |= HEATMAP_W_MASK
+#define HEATMAP_R(addr) g_aMemoryHeatmap[ addr ] |= HEATMAP_R_MASK
+#define HEATMAP_X(addr) g_aMemoryHeatmap[ addr ] |= HEATMAP_X_MASK
#undef READ
#define READ ReadByte( addr, uExecutedCycles )
inline u8 ReadByte( u16 addr, int uExecutedCycles )
{
- (u8*) g_pRead = ((u8*)g_aMemoryAccess) + (addr * 4) + 3;
- *g_pRead = IncClamp8( *g_pRead );
+ // TODO: We should have a single g_bDebuggerActive so we can have a single implementation across ][+ //e
+ HEATMAP_R(addr);
- return
- ( \
- ((addr & 0xF000) == 0xC000) \
- ? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles) \
- : *(mem+addr) \
- );
+ return ((addr & 0xF000) == 0xC000)
+ ? IORead[(addr>>4) & 0xFF](regs.pc,addr,0,0,uExecutedCycles)
+ : *(mem+addr);
}
-#undef WRITE
-#define WRITE(a) \
- (u8*) g_pWrite = ((u8*)g_aMemoryAccess) + (addr * 4) + 0; \
- *g_pWrite = DecClamp8( *g_pWrite ); \
- { \
- memdirty[addr >> 8] = 0xFF; \
- LPBYTE page = memwrite[addr >> 8]; \
- if (page) \
- *(page+(addr & 0xFF)) = (BYTE)(a); \
- else if ((addr & 0xF000) == 0xC000) \
- IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles); \
+#undef WRITE
+#define WRITE(a) \
+ HEATMAP_W(addr); \
+ { \
+ memdirty[addr >> 8] = 0xFF; \
+ LPBYTE page = memwrite[addr >> 8]; \
+ if (page) \
+ *(page+(addr & 0xFF)) = (BYTE)(a); \
+ else if ((addr & 0xF000) == 0xC000) \
+ IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles); \
}
#include "cpu/cpu_instructions.inl"
@@ -97,7 +112,6 @@ static DWORD Cpu65D02 (DWORD uTotalCycles)
WORD val;
AF_TO_EF
ULONG uExecutedCycles = 0;
- BOOL bSlowerOnPagecross = 0; // Set if opcode writes to memory (eg. ASL, STA)
WORD base;
g_bDebugBreakpointHit = 0;
@@ -111,12 +125,14 @@ static DWORD Cpu65D02 (DWORD uTotalCycles)
ULONG uPreviousCycles = uExecutedCycles;
// NTSC_END
- if (g_ActiveCPU == CPU_Z80)
+ if (GetActiveCpu() == CPU_Z80)
{
const UINT uZ80Cycles = z80_mainloop(uTotalCycles, uExecutedCycles); CYC(uZ80Cycles)
}
else
+ HEATMAP_X( regs.pc );
+
if (!Fetch(iOpcode, uExecutedCycles))
break;
@@ -131,525 +147,264 @@ static DWORD Cpu65D02 (DWORD uTotalCycles)
{
// TODO Optimization Note: ?? Move CYC(#) to array ??
-// Version 1 opcode: INV AM Instruction // Form1: INV=DebugBreak AM=AddressingMode
-// INV Instruction // Form2:
-//! ! ! ! ! ! // Tab-Stops
-/*
- case 0x00: BRK CYC(7) break;
- case 0x01: idx ORA CYC(6) break;
- case 0x02: INV IMM NOP CYC(2) break;
- case 0x03: INV NOP CYC(2) break;
- case 0x04: ZPG TSB CYC(5) break;
- case 0x05: ZPG ORA CYC(3) break;
- case 0x06: ZPG ASL_CMOS CYC(5) break;
- case 0x07: INV NOP CYC(2) break;
- case 0x08: PHP CYC(3) break;
- case 0x09: IMM ORA CYC(2) break;
- case 0x0A: asl CYC(2) break;
- case 0x0B: INV NOP CYC(2) break;
- case 0x0C: ABS TSB CYC(6) break;
- case 0x0D: ABS ORA CYC(4) break;
- case 0x0E: ABS ASL_CMOS CYC(6) break;
- case 0x0F: INV NOP CYC(2) break;
- case 0x10: REL BPL CYC(2) break;
- case 0x11: idy ORA CYC(5) break;
- case 0x12: izp ORA CYC(5) break;
- case 0x13: INV NOP CYC(2) break;
- case 0x14: ZPG TRB CYC(5) break;
- case 0x15: zpx ORA CYC(4) break;
- case 0x16: zpx ASL_CMOS CYC(6) break;
- case 0x17: INV NOP CYC(2) break;
- case 0x18: CLC CYC(2) break;
- case 0x19: aby ORA CYC(4) break;
- case 0x1A: INA CYC(2) break;
- case 0x1B: INV NOP CYC(2) break;
- case 0x1C: ABS TRB CYC(6) break;
- case 0x1D: abx ORA CYC(4) break;
- case 0x1E: abx ASL_CMOS CYC(6) break;
- case 0x1F: INV NOP CYC(2) break;
- case 0x20: ABS JSR CYC(6) break;
- case 0x21: idx AND CYC(6) break;
- case 0x22: INV IMM NOP CYC(2) break;
- case 0x23: INV NOP CYC(2) break;
- case 0x24: ZPG BIT CYC(3) break;
- case 0x25: ZPG AND CYC(3) break;
- case 0x26: ZPG ROL_CMOS CYC(5) break;
- case 0x27: INV NOP CYC(2) break;
- case 0x28: PLP CYC(4) break;
- case 0x29: IMM AND CYC(2) break;
- case 0x2A: rol CYC(2) break;
- case 0x2B: INV NOP CYC(2) break;
- case 0x2C: ABS BIT CYC(4) break;
- case 0x2D: ABS AND CYC(2) break;
- case 0x2E: ABS ROL_CMOS CYC(6) break;
- case 0x2F: INV NOP CYC(2) break;
- case 0x30: REL BMI CYC(2) break;
- case 0x31: idy AND CYC(5) break;
- case 0x32: izp AND CYC(5) break;
- case 0x33: INV NOP CYC(2) break;
- case 0x34: zpx BIT CYC(4) break;
- case 0x35: zpx AND CYC(4) break;
- case 0x36: zpx ROL_CMOS CYC(6) break;
- case 0x37: INV NOP CYC(2) break;
- case 0x38: SEC CYC(2) break;
- case 0x39: aby AND CYC(4) break;
- case 0x3A: DEA CYC(2) break;
- case 0x3B: INV NOP CYC(2) break;
- case 0x3C: abx BIT CYC(4) break;
- case 0x3D: abx AND CYC(4) break;
- case 0x3E: abx ROL_CMOS CYC(6) break;
- case 0x3F: INV NOP CYC(2) break;
- case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
- case 0x41: idx EOR CYC(6) break;
- case 0x42: INV IMM NOP CYC(2) break;
- case 0x43: INV NOP CYC(2) break;
- case 0x44: INV ZPG NOP CYC(3) break;
- case 0x45: ZPG EOR CYC(3) break;
- case 0x46: ZPG LSR_CMOS CYC(5) break;
- case 0x47: INV NOP CYC(2) break;
- case 0x48: PHA CYC(3) break;
- case 0x49: IMM EOR CYC(2) break;
- case 0x4A: lsr CYC(2) break;
- case 0x4B: INV NOP CYC(2) break;
- case 0x4C: ABS JMP CYC(3) break;
- case 0x4D: ABS EOR CYC(4) break;
- case 0x4E: ABS LSR_CMOS CYC(6) break;
- case 0x4F: INV NOP CYC(2) break;
- case 0x50: REL BVC CYC(2) break;
- case 0x51: idy EOR CYC(5) break;
- case 0x52: izp EOR CYC(5) break;
- case 0x53: INV NOP CYC(2) break;
- case 0x54: INV zpx NOP CYC(4) break;
- case 0x55: zpx EOR CYC(4) break;
- case 0x56: zpx LSR_CMOS CYC(6) break;
- case 0x57: INV NOP CYC(2) break;
- case 0x58: CLI CYC(2) break;
- case 0x59: aby EOR CYC(4) break;
- case 0x5A: PHY CYC(3) break;
- case 0x5B: INV NOP CYC(2) break;
- case 0x5C: INV abx NOP CYC(8) break;
- case 0x5D: abx EOR CYC(4) break;
- case 0x5E: abx LSR_CMOS CYC(6) break;
- case 0x5F: INV NOP CYC(2) break;
- case 0x60: RTS CYC(6) break;
- case 0x61: idx ADC_CMOS CYC(6) break;
- case 0x62: INV IMM NOP CYC(2) break;
- case 0x63: INV NOP CYC(2) break;
- case 0x64: ZPG STZ CYC(3) break;
- case 0x65: ZPG ADC_CMOS CYC(3) break;
- case 0x66: ZPG ROR_CMOS CYC(5) break;
- case 0x67: INV NOP CYC(2) break;
- case 0x68: PLA CYC(4) break;
- case 0x69: IMM ADC_CMOS CYC(2) break;
- case 0x6A: ror CYC(2) break;
- case 0x6B: INV NOP CYC(2) break;
- case 0x6C: IABSCMOS JMP CYC(6) break; // 0x6C // 65c02 IABSCMOS JMP // 6502 IABSNMOS JMP
- case 0x6D: ABS ADC_CMOS CYC(4) break;
- case 0x6E: ABS ROR_CMOS CYC(6) break;
- case 0x6F: INV NOP CYC(2) break;
- case 0x70: REL BVS CYC(2) break;
- case 0x71: idy ADC_CMOS CYC(5) break;
- case 0x72: izp ADC_CMOS CYC(5) break;
- case 0x73: INV NOP CYC(2) break;
- case 0x74: zpx STZ CYC(4) break;
- case 0x75: zpx ADC_CMOS CYC(4) break;
- case 0x76: zpx ROR_CMOS CYC(6) break;
- case 0x77: INV NOP CYC(2) break;
- case 0x78: SEI CYC(2) break;
- case 0x79: aby ADC_CMOS CYC(4) break;
- case 0x7A: PLY CYC(4) break;
- case 0x7B: INV NOP CYC(2) break;
- case 0x7C: IABSX JMP CYC(6) break; // 0x7C // 65c02 IABSX JMP // 6502 ABSX NOP
- case 0x7D: abx ADC_CMOS CYC(4) break;
- case 0x7E: abx ROR_CMOS CYC(6) break;
- case 0x7F: INV NOP CYC(2) break;
- case 0x80: REL BRA CYC(2) break;
- case 0x81: idx STA CYC(6) break;
- case 0x82: INV IMM NOP CYC(2) break;
- case 0x83: INV NOP CYC(2) break;
- case 0x84: ZPG STY CYC(3) break;
- case 0x85: ZPG STA CYC(3) break;
- case 0x86: ZPG STX CYC(3) break;
- case 0x87: INV NOP CYC(2) break;
- case 0x88: DEY CYC(2) break;
- case 0x89: IMM BITI CYC(2) break;
- case 0x8A: TXA CYC(2) break;
- case 0x8B: INV NOP CYC(2) break;
- case 0x8C: ABS STY CYC(4) break;
- case 0x8D: ABS STA CYC(4) break;
- case 0x8E: ABS STX CYC(4) break;
- case 0x8F: INV NOP CYC(2) break;
- case 0x90: REL BCC CYC(2) break;
- case 0x91: idy STA CYC(6) break;
- case 0x92: izp STA CYC(5) break;
- case 0x93: INV NOP CYC(2) break;
- case 0x94: zpx STY CYC(4) break;
- case 0x95: zpx STA CYC(4) break;
- case 0x96: zpy STX CYC(4) break;
- case 0x97: INV NOP CYC(2) break;
- case 0x98: TYA CYC(2) break;
- case 0x99: aby STA CYC(5) break;
- case 0x9A: TXS CYC(2) break;
- case 0x9B: INV NOP CYC(2) break;
- case 0x9C: ABS STZ CYC(4) break;
- case 0x9D: abx STA CYC(5) break;
- case 0x9E: abx STZ CYC(5) break;
- case 0x9F: INV NOP CYC(2) break;
- case 0xA0: IMM LDY CYC(2) break;
- case 0xA1: idx LDA CYC(6) break;
- case 0xA2: IMM LDX CYC(2) break;
- case 0xA3: INV NOP CYC(2) break;
- case 0xA4: ZPG LDY CYC(3) break;
- case 0xA5: ZPG LDA CYC(3) break;
- case 0xA6: ZPG LDX CYC(3) break;
- case 0xA7: INV NOP CYC(2) break;
- case 0xA8: TAY CYC(2) break;
- case 0xA9: IMM LDA CYC(2) break;
- case 0xAA: TAX CYC(2) break;
- case 0xAB: INV NOP CYC(2) break;
- case 0xAC: ABS LDY CYC(4) break;
- case 0xAD: ABS LDA CYC(4) break;
- case 0xAE: ABS LDX CYC(4) break;
- case 0xAF: INV NOP CYC(2) break;
- case 0xB0: REL BCS CYC(2) break;
- case 0xB1: idy LDA CYC(5) break;
- case 0xB2: izp LDA CYC(5) break;
- case 0xB3: INV NOP CYC(2) break;
- case 0xB4: zpx LDY CYC(4) break;
- case 0xB5: zpx LDA CYC(4) break;
- case 0xB6: zpy LDX CYC(4) break;
- case 0xB7: INV NOP CYC(2) break;
- case 0xB8: CLV CYC(2) break;
- case 0xB9: aby LDA CYC(4) break;
- case 0xBA: TSX CYC(2) break;
- case 0xBB: INV NOP CYC(2) break;
- case 0xBC: abx LDY CYC(4) break;
- case 0xBD: abx LDA CYC(4) break;
- case 0xBE: aby LDX CYC(4) break;
- case 0xBF: INV NOP CYC(2) break;
- case 0xC0: IMM CPY CYC(2) break;
- case 0xC1: idx CMP CYC(6) break;
- case 0xC2: INV IMM NOP CYC(2) break;
- case 0xC3: INV NOP CYC(2) break;
- case 0xC4: ZPG CPY CYC(3) break;
- case 0xC5: ZPG CMP CYC(3) break;
- case 0xC6: ZPG DEC_CMOS CYC(5) break;
- case 0xC7: INV NOP CYC(2) break;
- case 0xC8: INY CYC(2) break;
- case 0xC9: IMM CMP CYC(2) break;
- case 0xCA: DEX CYC(2) break;
- case 0xCB: INV NOP CYC(2) break;
- case 0xCC: ABS CPY CYC(4) break;
- case 0xCD: ABS CMP CYC(4) break;
- case 0xCE: ABS DEC_CMOS CYC(5) break;
- case 0xCF: INV NOP CYC(2) break;
- case 0xD0: REL BNE CYC(2) break;
- case 0xD1: idy CMP CYC(5) break;
- case 0xD2: izp CMP CYC(5) break;
- case 0xD3: INV NOP CYC(2) break;
- case 0xD4: INV zpx NOP CYC(4) break;
- case 0xD5: zpx CMP CYC(4) break;
- case 0xD6: zpx DEC_CMOS CYC(6) break;
- case 0xD7: INV NOP CYC(2) break;
- case 0xD8: CLD CYC(2) break;
- case 0xD9: aby CMP CYC(4) break;
- case 0xDA: PHX CYC(3) break;
- case 0xDB: INV NOP CYC(2) break;
- case 0xDC: INV abx NOP CYC(4) break;
- case 0xDD: abx CMP CYC(4) break;
- case 0xDE: abx DEC_CMOS CYC(6) break;
- case 0xDF: INV NOP CYC(2) break;
- case 0xE0: IMM CPX CYC(2) break;
- case 0xE1: idx SBC_CMOS CYC(6) break;
- case 0xE2: INV IMM NOP CYC(2) break;
- case 0xE3: INV NOP CYC(2) break;
- case 0xE4: ZPG CPX CYC(3) break;
- case 0xE5: ZPG SBC_CMOS CYC(3) break;
- case 0xE6: ZPG INC_CMOS CYC(5) break;
- case 0xE7: INV NOP CYC(2) break;
- case 0xE8: INX CYC(2) break;
- case 0xE9: IMM SBC_CMOS CYC(2) break;
- case 0xEA: NOP CYC(2) break;
- case 0xEB: INV NOP CYC(2) break;
- case 0xEC: ABS CPX CYC(4) break;
- case 0xED: ABS SBC_CMOS CYC(4) break;
- case 0xEE: ABS INC_CMOS CYC(6) break;
- case 0xEF: INV NOP CYC(2) break;
- case 0xF0: REL BEQ CYC(2) break;
- case 0xF1: idy SBC_CMOS CYC(5) break;
- case 0xF2: izp SBC_CMOS CYC(5) break;
- case 0xF3: INV NOP CYC(2) break;
- case 0xF4: INV zpx NOP CYC(4) break;
- case 0xF5: zpx SBC_CMOS CYC(4) break;
- case 0xF6: zpx INC_CMOS CYC(6) break;
- case 0xF7: INV NOP CYC(2) break;
- case 0xF8: SED CYC(2) break;
- case 0xF9: aby SBC_CMOS CYC(4) break;
- case 0xFA: PLX CYC(4) break;
- case 0xFB: INV NOP CYC(2) break;
- case 0xFC: INV abx NOP CYC(4) break;
- case 0xFD: abx SBC_CMOS CYC(4) break;
- case 0xFE: abx INC_CMOS CYC(6) break;
- case 0xFF: INV NOP CYC(2) break;
-*/
-// Version 2 opcode: $ AM Instruction // $=DebugBreak AM=AddressingMode
-//! ! ! ! ! ! // Tab-Stops
- case 0x00: BRK CYC(7) break;
- case 0x01: idx ORA CYC(6) break;
- case 0x02: $ IMM NOP CYC(2) break;
- case 0x03: $ NOP CYC(2) break;
- case 0x04: ZPG TSB CYC(5) break;
- case 0x05: ZPG ORA CYC(3) break;
- case 0x06: ZPG ASLc CYC(5) break;
- case 0x07: $ NOP CYC(2) break;
- case 0x08: PHP CYC(3) break;
- case 0x09: IMM ORA CYC(2) break;
- case 0x0A: asl CYC(2) break;
- case 0x0B: $ NOP CYC(2) break;
- case 0x0C: ABS TSB CYC(6) break;
- case 0x0D: ABS ORA CYC(4) break;
- case 0x0E: ABS ASLc CYC(6) break;
- case 0x0F: $ NOP CYC(2) break;
- case 0x10: REL BPL CYC(2) break;
- case 0x11: idy ORA CYC(5) break;
- case 0x12: izp ORA CYC(5) break;
- case 0x13: $ NOP CYC(2) break;
- case 0x14: ZPG TRB CYC(5) break;
- case 0x15: zpx ORA CYC(4) break;
- case 0x16: zpx ASLc CYC(6) break;
- case 0x17: $ NOP CYC(2) break;
- case 0x18: CLC CYC(2) break;
- case 0x19: aby ORA CYC(4) break;
- case 0x1A: INA CYC(2) break;
- case 0x1B: $ NOP CYC(2) break;
- case 0x1C: ABS TRB CYC(6) break;
- case 0x1D: abx ORA CYC(4) break;
- case 0x1E: abx ASLc CYC(6) break;
- case 0x1F: $ NOP CYC(2) break;
- case 0x20: ABS JSR CYC(6) break;
- case 0x21: idx AND CYC(6) break;
- case 0x22: $ IMM NOP CYC(2) break;
- case 0x23: $ NOP CYC(2) break;
- case 0x24: ZPG BIT CYC(3) break;
- case 0x25: ZPG AND CYC(3) break;
- case 0x26: ZPG ROLc CYC(5) break;
- case 0x27: $ NOP CYC(2) break;
- case 0x28: PLP CYC(4) break;
- case 0x29: IMM AND CYC(2) break;
- case 0x2A: rol CYC(2) break;
- case 0x2B: $ NOP CYC(2) break;
- case 0x2C: ABS BIT CYC(4) break;
- case 0x2D: ABS AND CYC(2) break;
- case 0x2E: ABS ROLc CYC(6) break;
- case 0x2F: $ NOP CYC(2) break;
- case 0x30: REL BMI CYC(2) break;
- case 0x31: idy AND CYC(5) break;
- case 0x32: izp AND CYC(5) break;
- case 0x33: $ NOP CYC(2) break;
- case 0x34: zpx BIT CYC(4) break;
- case 0x35: zpx AND CYC(4) break;
- case 0x36: zpx ROLc CYC(6) break;
- case 0x37: $ NOP CYC(2) break;
- case 0x38: SEC CYC(2) break;
- case 0x39: aby AND CYC(4) break;
- case 0x3A: DEA CYC(2) break;
- case 0x3B: $ NOP CYC(2) break;
- case 0x3C: abx BIT CYC(4) break;
- case 0x3D: abx AND CYC(4) break;
- case 0x3E: abx ROLc CYC(6) break;
- case 0x3F: $ NOP CYC(2) break;
- case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
- case 0x41: idx EOR CYC(6) break;
- case 0x42: $ IMM NOP CYC(2) break;
- case 0x43: $ NOP CYC(2) break;
- case 0x44: $ ZPG NOP CYC(3) break;
- case 0x45: ZPG EOR CYC(3) break;
- case 0x46: ZPG LSRc CYC(5) break;
- case 0x47: $ NOP CYC(2) break;
- case 0x48: PHA CYC(3) break;
- case 0x49: IMM EOR CYC(2) break;
- case 0x4A: lsr CYC(2) break;
- case 0x4B: $ NOP CYC(2) break;
- case 0x4C: ABS JMP CYC(3) break;
- case 0x4D: ABS EOR CYC(4) break;
- case 0x4E: ABS LSRc CYC(6) break;
- case 0x4F: $ NOP CYC(2) break;
- case 0x50: REL BVC CYC(2) break;
- case 0x51: idy EOR CYC(5) break;
- case 0x52: izp EOR CYC(5) break;
- case 0x53: $ NOP CYC(2) break;
- case 0x54: $ zpx NOP CYC(4) break;
- case 0x55: zpx EOR CYC(4) break;
- case 0x56: zpx LSRc CYC(6) break;
- case 0x57: $ NOP CYC(2) break;
- case 0x58: CLI CYC(2) break;
- case 0x59: aby EOR CYC(4) break;
- case 0x5A: PHY CYC(3) break;
- case 0x5B: $ NOP CYC(2) break;
- case 0x5C: $ abx NOP CYC(8) break;
- case 0x5D: abx EOR CYC(4) break;
- case 0x5E: abx LSRc CYC(6) break;
- case 0x5F: $ NOP CYC(2) break;
- case 0x60: RTS CYC(6) break;
- case 0x61: idx ADCc CYC(6) break;
- case 0x62: $ IMM NOP CYC(2) break;
- case 0x63: $ NOP CYC(2) break;
- case 0x64: ZPG STZ CYC(3) break;
- case 0x65: ZPG ADCc CYC(3) break;
- case 0x66: ZPG RORc CYC(5) break;
- case 0x67: $ NOP CYC(2) break;
- case 0x68: PLA CYC(4) break;
- case 0x69: IMM ADCc CYC(2) break;
- case 0x6A: ror CYC(2) break;
- case 0x6B: $ NOP CYC(2) break;
- case 0x6C: IABSCMOS JMP CYC(6) break; // 0x6C // 65c02 IABSCMOS JMP // 6502 IABSNMOS JMP
- case 0x6D: ABS ADCc CYC(4) break;
- case 0x6E: ABS RORc CYC(6) break;
- case 0x6F: $ NOP CYC(2) break;
- case 0x70: REL BVS CYC(2) break;
- case 0x71: idy ADCc CYC(5) break;
- case 0x72: izp ADCc CYC(5) break;
- case 0x73: $ NOP CYC(2) break;
- case 0x74: zpx STZ CYC(4) break;
- case 0x75: zpx ADCc CYC(4) break;
- case 0x76: zpx RORc CYC(6) break;
- case 0x77: $ NOP CYC(2) break;
- case 0x78: SEI CYC(2) break;
- case 0x79: aby ADCc CYC(4) break;
- case 0x7A: PLY CYC(4) break;
- case 0x7B: $ NOP CYC(2) break;
- case 0x7C: IABSX JMP CYC(6) break; // 0x7C // 65c02 IABSX JMP // 6502 ABSX NOP
- case 0x7D: abx ADCc CYC(4) break;
- case 0x7E: abx RORc CYC(6) break;
- case 0x7F: $ NOP CYC(2) break;
- case 0x80: REL BRA CYC(2) break;
- case 0x81: idx STA CYC(6) break;
- case 0x82: $ IMM NOP CYC(2) break;
- case 0x83: $ NOP CYC(2) break;
- case 0x84: ZPG STY CYC(3) break;
- case 0x85: ZPG STA CYC(3) break;
- case 0x86: ZPG STX CYC(3) break;
- case 0x87: $ NOP CYC(2) break;
- case 0x88: DEY CYC(2) break;
- case 0x89: IMM BITI CYC(2) break;
- case 0x8A: TXA CYC(2) break;
- case 0x8B: $ NOP CYC(2) break;
- case 0x8C: ABS STY CYC(4) break;
- case 0x8D: ABS STA CYC(4) break;
- case 0x8E: ABS STX CYC(4) break;
- case 0x8F: $ NOP CYC(2) break;
- case 0x90: REL BCC CYC(2) break;
- case 0x91: idy STA CYC(6) break;
- case 0x92: izp STA CYC(5) break;
- case 0x93: $ NOP CYC(2) break;
- case 0x94: zpx STY CYC(4) break;
- case 0x95: zpx STA CYC(4) break;
- case 0x96: zpy STX CYC(4) break;
- case 0x97: $ NOP CYC(2) break;
- case 0x98: TYA CYC(2) break;
- case 0x99: aby STA CYC(5) break;
- case 0x9A: TXS CYC(2) break;
- case 0x9B: $ NOP CYC(2) break;
- case 0x9C: ABS STZ CYC(4) break;
- case 0x9D: abx STA CYC(5) break;
- case 0x9E: abx STZ CYC(5) break;
- case 0x9F: $ NOP CYC(2) break;
- case 0xA0: IMM LDY CYC(2) break;
- case 0xA1: idx LDA CYC(6) break;
- case 0xA2: IMM LDX CYC(2) break;
- case 0xA3: $ NOP CYC(2) break;
- case 0xA4: ZPG LDY CYC(3) break;
- case 0xA5: ZPG LDA CYC(3) break;
- case 0xA6: ZPG LDX CYC(3) break;
- case 0xA7: $ NOP CYC(2) break;
- case 0xA8: TAY CYC(2) break;
- case 0xA9: IMM LDA CYC(2) break;
- case 0xAA: TAX CYC(2) break;
- case 0xAB: $ NOP CYC(2) break;
- case 0xAC: ABS LDY CYC(4) break;
- case 0xAD: ABS LDA CYC(4) break;
- case 0xAE: ABS LDX CYC(4) break;
- case 0xAF: $ NOP CYC(2) break;
- case 0xB0: REL BCS CYC(2) break;
- case 0xB1: idy LDA CYC(5) break;
- case 0xB2: izp LDA CYC(5) break;
- case 0xB3: $ NOP CYC(2) break;
- case 0xB4: zpx LDY CYC(4) break;
- case 0xB5: zpx LDA CYC(4) break;
- case 0xB6: zpy LDX CYC(4) break;
- case 0xB7: $ NOP CYC(2) break;
- case 0xB8: CLV CYC(2) break;
- case 0xB9: aby LDA CYC(4) break;
- case 0xBA: TSX CYC(2) break;
- case 0xBB: $ NOP CYC(2) break;
- case 0xBC: abx LDY CYC(4) break;
- case 0xBD: abx LDA CYC(4) break;
- case 0xBE: aby LDX CYC(4) break;
- case 0xBF: $ NOP CYC(2) break;
- case 0xC0: IMM CPY CYC(2) break;
- case 0xC1: idx CMP CYC(6) break;
- case 0xC2: $ IMM NOP CYC(2) break;
- case 0xC3: $ NOP CYC(2) break;
- case 0xC4: ZPG CPY CYC(3) break;
- case 0xC5: ZPG CMP CYC(3) break;
- case 0xC6: ZPG DECc CYC(5) break;
- case 0xC7: $ NOP CYC(2) break;
- case 0xC8: INY CYC(2) break;
- case 0xC9: IMM CMP CYC(2) break;
- case 0xCA: DEX CYC(2) break;
- case 0xCB: $ NOP CYC(2) break;
- case 0xCC: ABS CPY CYC(4) break;
- case 0xCD: ABS CMP CYC(4) break;
- case 0xCE: ABS DECc CYC(5) break;
- case 0xCF: $ NOP CYC(2) break;
- case 0xD0: REL BNE CYC(2) break;
- case 0xD1: idy CMP CYC(5) break;
- case 0xD2: izp CMP CYC(5) break;
- case 0xD3: $ NOP CYC(2) break;
- case 0xD4: $ zpx NOP CYC(4) break;
- case 0xD5: zpx CMP CYC(4) break;
- case 0xD6: zpx DECc CYC(6) break;
- case 0xD7: $ NOP CYC(2) break;
- case 0xD8: CLD CYC(2) break;
- case 0xD9: aby CMP CYC(4) break;
- case 0xDA: PHX CYC(3) break;
- case 0xDB: $ NOP CYC(2) break;
- case 0xDC: $ abx NOP CYC(4) break;
- case 0xDD: abx CMP CYC(4) break;
- case 0xDE: abx DECc CYC(6) break;
- case 0xDF: $ NOP CYC(2) break;
- case 0xE0: IMM CPX CYC(2) break;
- case 0xE1: idx SBCc CYC(6) break;
- case 0xE2: $ IMM NOP CYC(2) break;
- case 0xE3: $ NOP CYC(2) break;
- case 0xE4: ZPG CPX CYC(3) break;
- case 0xE5: ZPG SBCc CYC(3) break;
- case 0xE6: ZPG INCc CYC(5) break;
- case 0xE7: $ NOP CYC(2) break;
- case 0xE8: INX CYC(2) break;
- case 0xE9: IMM SBCc CYC(2) break;
- case 0xEA: NOP CYC(2) break;
- case 0xEB: $ NOP CYC(2) break;
- case 0xEC: ABS CPX CYC(4) break;
- case 0xED: ABS SBCc CYC(4) break;
- case 0xEE: ABS INCc CYC(6) break;
- case 0xEF: $ NOP CYC(2) break;
- case 0xF0: REL BEQ CYC(2) break;
- case 0xF1: idy SBCc CYC(5) break;
- case 0xF2: izp SBCc CYC(5) break;
- case 0xF3: $ NOP CYC(2) break;
- case 0xF4: $ zpx NOP CYC(4) break;
- case 0xF5: zpx SBCc CYC(4) break;
- case 0xF6: zpx INCc CYC(6) break;
- case 0xF7: $ NOP CYC(2) break;
- case 0xF8: SED CYC(2) break;
- case 0xF9: aby SBCc CYC(4) break;
- case 0xFA: PLX CYC(4) break;
- case 0xFB: $ NOP CYC(2) break;
- case 0xFC: $ abx NOP CYC(4) break;
- case 0xFD: abx SBCc CYC(4) break;
- case 0xFE: abx INCc CYC(6) break;
- case 0xFF: $ NOP CYC(2) break;
+// Version 2 opcode: $ AM Instruction // $=DebugBreak AM=AddressingMode
+//! ! ! ! ! ! // Tab-Stops
+ case 0x00: BRK CYC(7) break;
+ case 0x01: idx ORA CYC(6) break;
+ case 0x02: $ IMM NOP CYC(2) break;
+ case 0x03: $ NOP CYC(2) break;
+ case 0x04: ZPG TSB CYC(5) break;
+ case 0x05: ZPG ORA CYC(3) break;
+ case 0x06: ZPG ASLc CYC(5) break;
+ case 0x07: $ NOP CYC(2) break;
+ case 0x08: PHP CYC(3) break;
+ case 0x09: IMM ORA CYC(2) break;
+ case 0x0A: asl CYC(2) break;
+ case 0x0B: $ NOP CYC(2) break;
+ case 0x0C: ABS TSB CYC(6) break;
+ case 0x0D: ABS ORA CYC(4) break;
+ case 0x0E: ABS ASLc CYC(6) break;
+ case 0x0F: $ NOP CYC(2) break;
+ case 0x10: REL BPL CYC(2) break;
+ case 0x11: INDY_OPT ORA CYC(5) break;
+ case 0x12: izp ORA CYC(5) break;
+ case 0x13: $ NOP CYC(2) break;
+ case 0x14: ZPG TRB CYC(5) break;
+ case 0x15: zpx ORA CYC(4) break;
+ case 0x16: zpx ASLc CYC(6) break;
+ case 0x17: $ NOP CYC(2) break;
+ case 0x18: CLC CYC(2) break;
+ case 0x19: ABSY_OPT ORA CYC(4) break;
+ case 0x1A: INA CYC(2) break;
+ case 0x1B: $ NOP CYC(2) break;
+ case 0x1C: ABS TRB CYC(6) break;
+ case 0x1D: ABSX_OPT ORA CYC(4) break;
+ case 0x1E: ABSX_OPT ASLc CYC(6) break;
+ case 0x1F: $ NOP CYC(2) break;
+ case 0x20: ABS JSR CYC(6) break;
+ case 0x21: idx AND CYC(6) break;
+ case 0x22: $ IMM NOP CYC(2) break;
+ case 0x23: $ NOP CYC(2) break;
+ case 0x24: ZPG BIT CYC(3) break;
+ case 0x25: ZPG AND CYC(3) break;
+ case 0x26: ZPG ROLc CYC(5) break;
+ case 0x27: $ NOP CYC(2) break;
+ case 0x28: PLP CYC(4) break;
+ case 0x29: IMM AND CYC(2) break;
+ case 0x2A: rol CYC(2) break;
+ case 0x2B: $ NOP CYC(2) break;
+ case 0x2C: ABS BIT CYC(4) break;
+ case 0x2D: ABS AND CYC(2) break;
+ case 0x2E: ABS ROLc CYC(6) break;
+ case 0x2F: $ NOP CYC(2) break;
+ case 0x30: REL BMI CYC(2) break;
+ case 0x31: INDY_OPT AND CYC(5) break;
+ case 0x32: izp AND CYC(5) break;
+ case 0x33: $ NOP CYC(2) break;
+ case 0x34: zpx BIT CYC(4) break;
+ case 0x35: zpx AND CYC(4) break;
+ case 0x36: zpx ROLc CYC(6) break;
+ case 0x37: $ NOP CYC(2) break;
+ case 0x38: SEC CYC(2) break;
+ case 0x39: ABSY_OPT AND CYC(4) break;
+ case 0x3A: DEA CYC(2) break;
+ case 0x3B: $ NOP CYC(2) break;
+ case 0x3C: ABSX_OPT BIT CYC(4) break;
+ case 0x3D: ABSX_OPT AND CYC(4) break;
+ case 0x3E: ABSX_OPT ROLc CYC(6) break;
+ case 0x3F: $ NOP CYC(2) break;
+ case 0x40: RTI CYC(6) DoIrqProfiling(uExecutedCycles); break;
+ case 0x41: idx EOR CYC(6) break;
+ case 0x42: $ IMM NOP CYC(2) break;
+ case 0x43: $ NOP CYC(2) break;
+ case 0x44: $ ZPG NOP CYC(3) break;
+ case 0x45: ZPG EOR CYC(3) break;
+ case 0x46: ZPG LSRc CYC(5) break;
+ case 0x47: $ NOP CYC(2) break;
+ case 0x48: PHA CYC(3) break;
+ case 0x49: IMM EOR CYC(2) break;
+ case 0x4A: lsr CYC(2) break;
+ case 0x4B: $ NOP CYC(2) break;
+ case 0x4C: ABS JMP CYC(3) break;
+ case 0x4D: ABS EOR CYC(4) break;
+ case 0x4E: ABS LSRc CYC(6) break;
+ case 0x4F: $ NOP CYC(2) break;
+ case 0x50: REL BVC CYC(2) break;
+ case 0x51: INDY_OPT EOR CYC(5) break;
+ case 0x52: izp EOR CYC(5) break;
+ case 0x53: $ NOP CYC(2) break;
+ case 0x54: $ zpx NOP CYC(4) break;
+ case 0x55: zpx EOR CYC(4) break;
+ case 0x56: zpx LSRc CYC(6) break;
+ case 0x57: $ NOP CYC(2) break;
+ case 0x58: CLI CYC(2) break;
+ case 0x59: ABSY_OPT EOR CYC(4) break;
+ case 0x5A: PHY CYC(3) break;
+ case 0x5B: $ NOP CYC(2) break;
+ case 0x5C: $ ABSX_OPT NOP CYC(8) break;
+ case 0x5D: ABSX_OPT EOR CYC(4) break;
+ case 0x5E: ABSX_OPT LSRc CYC(6) break;
+ case 0x5F: $ NOP CYC(2) break;
+ case 0x60: RTS CYC(6) break;
+ case 0x61: idx ADCc CYC(6) break;
+ case 0x62: $ IMM NOP CYC(2) break;
+ case 0x63: $ NOP CYC(2) break;
+ case 0x64: ZPG STZ CYC(3) break;
+ case 0x65: ZPG ADCc CYC(3) break;
+ case 0x66: ZPG RORc CYC(5) break;
+ case 0x67: $ NOP CYC(2) break;
+ case 0x68: PLA CYC(4) break;
+ case 0x69: IMM ADCc CYC(2) break;
+ case 0x6A: ror CYC(2) break;
+ case 0x6B: $ NOP CYC(2) break;
+ case 0x6C: IABS_CMOS JMP CYC(6) break;
+ case 0x6D: ABS ADCc CYC(4) break;
+ case 0x6E: ABS RORc CYC(6) break;
+ case 0x6F: $ NOP CYC(2) break;
+ case 0x70: REL BVS CYC(2) break;
+ case 0x71: INDY_OPT ADCc CYC(5) break;
+ case 0x72: izp ADCc CYC(5) break;
+ case 0x73: $ NOP CYC(2) break;
+ case 0x74: zpx STZ CYC(4) break;
+ case 0x75: zpx ADCc CYC(4) break;
+ case 0x76: zpx RORc CYC(6) break;
+ case 0x77: $ NOP CYC(2) break;
+ case 0x78: SEI CYC(2) break;
+ case 0x79: ABSY_OPT ADCc CYC(4) break;
+ case 0x7A: PLY CYC(4) break;
+ case 0x7B: $ NOP CYC(2) break;
+ case 0x7C: IABSX JMP CYC(6) break;
+ case 0x7D: ABSX_OPT ADCc CYC(4) break;
+ case 0x7E: ABSX_OPT RORc CYC(6) break;
+ case 0x7F: $ NOP CYC(2) break;
+ case 0x80: REL BRA CYC(2) break;
+ case 0x81: idx STA CYC(6) break;
+ case 0x82: $ IMM NOP CYC(2) break;
+ case 0x83: $ NOP CYC(2) break;
+ case 0x84: ZPG STY CYC(3) break;
+ case 0x85: ZPG STA CYC(3) break;
+ case 0x86: ZPG STX CYC(3) break;
+ case 0x87: $ NOP CYC(2) break;
+ case 0x88: DEY CYC(2) break;
+ case 0x89: IMM BITI CYC(2) break;
+ case 0x8A: TXA CYC(2) break;
+ case 0x8B: $ NOP CYC(2) break;
+ case 0x8C: ABS STY CYC(4) break;
+ case 0x8D: ABS STA CYC(4) break;
+ case 0x8E: ABS STX CYC(4) break;
+ case 0x8F: $ NOP CYC(2) break;
+ case 0x90: REL BCC CYC(2) break;
+ case 0x91: INDY_CONST STA CYC(6) break;
+ case 0x92: izp STA CYC(5) break;
+ case 0x93: $ NOP CYC(2) break;
+ case 0x94: zpx STY CYC(4) break;
+ case 0x95: zpx STA CYC(4) break;
+ case 0x96: zpy STX CYC(4) break;
+ case 0x97: $ NOP CYC(2) break;
+ case 0x98: TYA CYC(2) break;
+ case 0x99: ABSY_CONST STA CYC(5) break;
+ case 0x9A: TXS CYC(2) break;
+ case 0x9B: $ NOP CYC(2) break;
+ case 0x9C: ABS STZ CYC(4) break;
+ case 0x9D: ABSX_CONST STA CYC(5) break;
+ case 0x9E: ABSX_CONST STZ CYC(5) break;
+ case 0x9F: $ NOP CYC(2) break;
+ case 0xA0: IMM LDY CYC(2) break;
+ case 0xA1: idx LDA CYC(6) break;
+ case 0xA2: IMM LDX CYC(2) break;
+ case 0xA3: $ NOP CYC(2) break;
+ case 0xA4: ZPG LDY CYC(3) break;
+ case 0xA5: ZPG LDA CYC(3) break;
+ case 0xA6: ZPG LDX CYC(3) break;
+ case 0xA7: $ NOP CYC(2) break;
+ case 0xA8: TAY CYC(2) break;
+ case 0xA9: IMM LDA CYC(2) break;
+ case 0xAA: TAX CYC(2) break;
+ case 0xAB: $ NOP CYC(2) break;
+ case 0xAC: ABS LDY CYC(4) break;
+ case 0xAD: ABS LDA CYC(4) break;
+ case 0xAE: ABS LDX CYC(4) break;
+ case 0xAF: $ NOP CYC(2) break;
+ case 0xB0: REL BCS CYC(2) break;
+ case 0xB1: INDY_OPT LDA CYC(5) break;
+ case 0xB2: izp LDA CYC(5) break;
+ case 0xB3: $ NOP CYC(2) break;
+ case 0xB4: zpx LDY CYC(4) break;
+ case 0xB5: zpx LDA CYC(4) break;
+ case 0xB6: zpy LDX CYC(4) break;
+ case 0xB7: $ NOP CYC(2) break;
+ case 0xB8: CLV CYC(2) break;
+ case 0xB9: ABSY_OPT LDA CYC(4) break;
+ case 0xBA: TSX CYC(2) break;
+ case 0xBB: $ NOP CYC(2) break;
+ case 0xBC: ABSX_OPT LDY CYC(4) break;
+ case 0xBD: ABSX_OPT LDA CYC(4) break;
+ case 0xBE: ABSY_OPT LDX CYC(4) break;
+ case 0xBF: $ NOP CYC(2) break;
+ case 0xC0: IMM CPY CYC(2) break;
+ case 0xC1: idx CMP CYC(6) break;
+ case 0xC2: $ IMM NOP CYC(2) break;
+ case 0xC3: $ NOP CYC(2) break;
+ case 0xC4: ZPG CPY CYC(3) break;
+ case 0xC5: ZPG CMP CYC(3) break;
+ case 0xC6: ZPG DEC CYC(5) break;
+ case 0xC7: $ NOP CYC(2) break;
+ case 0xC8: INY CYC(2) break;
+ case 0xC9: IMM CMP CYC(2) break;
+ case 0xCA: DEX CYC(2) break;
+ case 0xCB: $ NOP CYC(2) break;
+ case 0xCC: ABS CPY CYC(4) break;
+ case 0xCD: ABS CMP CYC(4) break;
+ case 0xCE: ABS DEC CYC(6) break;
+ case 0xCF: $ NOP CYC(2) break;
+ case 0xD0: REL BNE CYC(2) break;
+ case 0xD1: INDY_OPT CMP CYC(5) break;
+ case 0xD2: izp CMP CYC(5) break;
+ case 0xD3: $ NOP CYC(2) break;
+ case 0xD4: $ zpx NOP CYC(4) break;
+ case 0xD5: zpx CMP CYC(4) break;
+ case 0xD6: zpx DEC CYC(6) break;
+ case 0xD7: $ NOP CYC(2) break;
+ case 0xD8: CLD CYC(2) break;
+ case 0xD9: ABSY_OPT CMP CYC(4) break;
+ case 0xDA: PHX CYC(3) break;
+ case 0xDB: $ NOP CYC(2) break;
+ case 0xDC: $ ABSX_OPT NOP CYC(4) break;
+ case 0xDD: ABSX_OPT CMP CYC(4) break;
+ case 0xDE: ABSX_CONST DEC CYC(7) break;
+ case 0xDF: $ NOP CYC(2) break;
+ case 0xE0: IMM CPX CYC(2) break;
+ case 0xE1: idx SBCc CYC(6) break;
+ case 0xE2: $ IMM NOP CYC(2) break;
+ case 0xE3: $ NOP CYC(2) break;
+ case 0xE4: ZPG CPX CYC(3) break;
+ case 0xE5: ZPG SBCc CYC(3) break;
+ case 0xE6: ZPG INC CYC(5) break;
+ case 0xE7: $ NOP CYC(2) break;
+ case 0xE8: INX CYC(2) break;
+ case 0xE9: IMM SBCc CYC(2) break;
+ case 0xEA: NOP CYC(2) break;
+ case 0xEB: $ NOP CYC(2) break;
+ case 0xEC: ABS CPX CYC(4) break;
+ case 0xED: ABS SBCc CYC(4) break;
+ case 0xEE: ABS INC CYC(6) break;
+ case 0xEF: $ NOP CYC(2) break;
+ case 0xF0: REL BEQ CYC(2) break;
+ case 0xF1: INDY_OPT SBCc CYC(5) break;
+ case 0xF2: izp SBCc CYC(5) break;
+ case 0xF3: $ NOP CYC(2) break;
+ case 0xF4: $ zpx NOP CYC(4) break;
+ case 0xF5: zpx SBCc CYC(4) break;
+ case 0xF6: zpx INC CYC(6) break;
+ case 0xF7: $ NOP CYC(2) break;
+ case 0xF8: SED CYC(2) break;
+ case 0xF9: ABSY_OPT SBCc CYC(4) break;
+ case 0xFA: PLX CYC(4) break;
+ case 0xFB: $ NOP CYC(2) break;
+ case 0xFC: $ ABSX_OPT NOP CYC(4) break;
+ case 0xFD: ABSX_OPT SBCc CYC(4) break;
+ case 0xFE: ABSX_CONST INC CYC(7) break;
+ case 0xFF: $ NOP CYC(2) break;
}
#undef $
diff --git a/source/CPU/cpu_general.inl b/source/CPU/cpu_general.inl
index 25f7086e..4d565efb 100644
--- a/source/CPU/cpu_general.inl
+++ b/source/CPU/cpu_general.inl
@@ -73,6 +73,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
IOWrite[(addr>>4) & 0xFF](regs.pc,addr,1,(BYTE)(a),uExecutedCycles); \
}
+#define ON_PAGECROSS_REPLACE_HI_ADDR if ((base ^ addr) >> 8) {addr = (val<<8) | (addr&0xff);} /* GH#282 */
+
//
// ExtraCycles:
@@ -89,10 +91,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
-#define CHECK_PAGE_CHANGE if (bSlowerOnPagecross) { \
- if ((base ^ addr) & 0xFF00) \
- uExtraCycles=1; \
- }
+// TODO Optimization Note: uExtraCycles = ((base ^ addr) >> 8) & 1;
+#define CHECK_PAGE_CHANGE if ((base ^ addr) & 0xFF00) \
+ uExtraCycles=1;
/****************************************************************************
*
@@ -102,53 +103,71 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define ABS addr = *(LPWORD)(mem+regs.pc); regs.pc += 2;
#define IABSX addr = *(LPWORD)(mem+(*(LPWORD)(mem+regs.pc))+(WORD)regs.x); regs.pc += 2;
-#define ABSX base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.x; regs.pc += 2; CHECK_PAGE_CHANGE;
-#define ABSY base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.y; regs.pc += 2; CHECK_PAGE_CHANGE;
-// TODO Optimization Note: uExtraCycles = ((base & 0xFF) + 1) >> 8;
-#define IABSCMOS base = *(LPWORD)(mem+regs.pc); \
+
+// Optimised for page-cross
+#define ABSX_OPT base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.x; regs.pc += 2; CHECK_PAGE_CHANGE;
+// Not optimised for page-cross
+#define ABSX_CONST base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.x; regs.pc += 2;
+
+// Optimised for page-cross
+#define ABSY_OPT base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.y; regs.pc += 2; CHECK_PAGE_CHANGE;
+// Not optimised for page-cross
+#define ABSY_CONST base = *(LPWORD)(mem+regs.pc); addr = base+(WORD)regs.y; regs.pc += 2;
+
+// TODO Optimization Note (just for IABSCMOS): uExtraCycles = ((base & 0xFF) + 1) >> 8;
+#define IABS_CMOS base = *(LPWORD)(mem+regs.pc); \
addr = *(LPWORD)(mem+base); \
if ((base & 0xFF) == 0xFF) uExtraCycles=1; \
regs.pc += 2;
-#define IABSNMOS base = *(LPWORD)(mem+regs.pc); \
+#define IABS_NMOS base = *(LPWORD)(mem+regs.pc); \
if ((base & 0xFF) == 0xFF) \
addr = *(mem+base)+((WORD)*(mem+(base&0xFF00))<<8);\
- else \
+ else \
addr = *(LPWORD)(mem+base); \
regs.pc += 2;
+
#define IMM addr = regs.pc++;
+
#define INDX base = ((*(mem+regs.pc++))+regs.x) & 0xFF; \
if (base == 0xFF) \
addr = *(mem+0xFF)+(((WORD)*mem)<<8); \
else \
addr = *(LPWORD)(mem+base);
-#define INDY if (*(mem+regs.pc) == 0xFF) \
+
+// Optimised for page-cross
+#define INDY_OPT if (*(mem+regs.pc) == 0xFF) /*incurs an extra cycle for page-crossing*/ \
base = *(mem+0xFF)+(((WORD)*mem)<<8); \
else \
base = *(LPWORD)(mem+*(mem+regs.pc)); \
regs.pc++; \
addr = base+(WORD)regs.y; \
CHECK_PAGE_CHANGE;
+// Not optimised for page-cross
+#define INDY_CONST if (*(mem+regs.pc) == 0xFF) /*no extra cycle for page-crossing*/ \
+ base = *(mem+0xFF)+(((WORD)*mem)<<8); \
+ else \
+ base = *(LPWORD)(mem+*(mem+regs.pc)); \
+ regs.pc++; \
+ addr = base+(WORD)regs.y;
+
#define IZPG base = *(mem+regs.pc++); \
if (base == 0xFF) \
addr = *(mem+0xFF)+(((WORD)*mem)<<8); \
else \
addr = *(LPWORD)(mem+base);
+
#define REL addr = (signed char)*(mem+regs.pc++);
// TODO Optimization Note:
// . Opcodes that generate zero-page addresses can't be accessing $C000..$CFFF
// so they could be paired with special READZP/WRITEZP macros (instead of READ/WRITE)
-#define ZPG addr = *(mem+regs.pc++);
+#define ZPG addr = *(mem+regs.pc++);
#define ZPGX addr = ((*(mem+regs.pc++))+regs.x) & 0xFF;
#define ZPGY addr = ((*(mem+regs.pc++))+regs.y) & 0xFF;
// Tidy 3 char addressing modes to keep the opcode table visually aligned, clean, and readable.
-#undef abx
-#undef abx
-#undef aby
#undef asl
#undef idx
-#undef idy
#undef imm
#undef izp
#undef lsr
@@ -158,11 +177,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef zpx
#undef zpy
-#define abx ABSX
-#define aby ABSY
#define asl ASLA // Arithmetic Shift Left
#define idx INDX
-#define idy INDY
#define imm IMM
#define izp IZPG
#define lsr LSRA // Logical Shift Right
@@ -171,6 +187,3 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define ror RORA // Rotate Right
#define zpx ZPGX
#define zpy ZPGY
-// 0x6C // 65c02 IABSCMOS JMP // 6502 IABSNMOS JMP
-// 0x7C IABSX
-
diff --git a/source/CPU/cpu_instructions.inl b/source/CPU/cpu_instructions.inl
index 84e68bae..8daa6178 100644
--- a/source/CPU/cpu_instructions.inl
+++ b/source/CPU/cpu_instructions.inl
@@ -68,15 +68,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef CPY
#undef DCM
#undef DEA
-#undef DEC_NMOS
-#undef DEC_CMOS
+#undef DEC
#undef DEX
#undef DEY
#undef EOR
#undef HLT
#undef INA
-#undef INC_NMOS
-#undef INC_CMOS
+#undef INC
#undef INS
#undef INX
#undef INY
@@ -139,8 +137,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef ADCn
#undef ASLn
-#undef DECn
-#undef INCn
#undef LSRn
#undef ROLn
#undef RORn
@@ -148,8 +144,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define ADCn ADC_NMOS
#define ASLn ASL_NMOS
-#define DECn DEC_NMOS
-#define INCn INC_NMOS
#define LSRn LSR_NMOS
#define ROLn ROL_NMOS
#define RORn ROR_NMOS
@@ -159,8 +153,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#undef ADCc
#undef ASLc
-#undef DECc
-#undef INCc
#undef LSRc
#undef ROLc
#undef RORc
@@ -168,8 +160,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define ADCc ADC_CMOS
#define ASLc ASL_CMOS
-#define DECc DEC_CMOS
-#define INCc INC_CMOS
#define LSRc LSR_CMOS
#define ROLc ROL_CMOS
#define RORc ROR_CMOS
@@ -177,7 +167,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// ==========
-#define ADC_NMOS bSlowerOnPagecross = 1; \
+#define ADC_NMOS /*bSlowerOnPagecross = 1;*/ \
temp = READ; \
if (regs.ps & AF_DECIMAL) { \
val = (regs.a & 0x0F) + (temp & 0x0F) + flagc; \
@@ -203,7 +193,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
regs.a = val & 0xFF; \
SETNZ(regs.a); \
}
-#define ADC_CMOS bSlowerOnPagecross = 1; \
+#define ADC_CMOS /*bSlowerOnPagecross = 1*/; \
temp = READ; \
flagv = !((regs.a ^ temp) & 0x80); \
if (regs.ps & AF_DECIMAL) { \
@@ -242,7 +232,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagn = 0; \
regs.a >>= 1; \
SETZ(regs.a)
-#define AND bSlowerOnPagecross = 1; \
+#define AND /*bSlowerOnPagecross = 1;*/ \
regs.a &= READ; \
SETNZ(regs.a)
#define ANC regs.a &= READ; \
@@ -274,12 +264,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagv = ((val & 0x40) ^ ((val & 0x20) << 1)); \
regs.a = (val & 0xFF); \
}
-#define ASL_NMOS bSlowerOnPagecross = 0; \
+#define ASL_NMOS /*bSlowerOnPagecross = 0;*/ \
val = READ << 1; \
flagc = (val > 0xFF); \
SETNZ(val) \
WRITE(val)
-#define ASL_CMOS bSlowerOnPagecross = 1; \
+#define ASL_CMOS /*bSlowerOnPagecross = 1*/; \
val = READ << 1; \
flagc = (val > 0xFF); \
SETNZ(val) \
@@ -288,21 +278,22 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagc = (val > 0xFF); \
SETNZ(val) \
regs.a = (BYTE)val;
-#define ASO bSlowerOnPagecross = 0; \
+#define ASO /*bSlowerOnPagecross = 0;*/ \
val = READ << 1; \
flagc = (val > 0xFF); \
WRITE(val) \
regs.a |= val; \
SETNZ(regs.a)
-#define AXA bSlowerOnPagecross = 0;/*FIXME: $93 case is still unclear*/ \
+#define AXA /*bSlowerOnPagecross = 0;*/ \
val = regs.a & regs.x & (((base >> 8) + 1) & 0xFF); \
+ ON_PAGECROSS_REPLACE_HI_ADDR \
WRITE(val)
-#define AXS bSlowerOnPagecross = 0; \
+#define AXS /*bSlowerOnPagecross = 0;*/ \
WRITE(regs.a & regs.x)
#define BCC if (!flagc) BRANCH_TAKEN;
#define BCS if ( flagc) BRANCH_TAKEN;
#define BEQ if ( flagz) BRANCH_TAKEN;
-#define BIT bSlowerOnPagecross = 1; \
+#define BIT /*bSlowerOnPagecross = 1;*/ \
val = READ; \
flagz = !(regs.a & val); \
flagn = val & 0x80; \
@@ -325,7 +316,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define CLD regs.ps &= ~AF_DECIMAL;
#define CLI regs.ps &= ~AF_INTERRUPT;
#define CLV flagv = 0;
-#define CMP bSlowerOnPagecross = 1; \
+#define CMP /*bSlowerOnPagecross = 1;*/ \
val = READ; \
flagc = (regs.a >= val); \
val = regs.a-val; \
@@ -338,7 +329,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagc = (regs.y >= val); \
val = regs.y-val; \
SETNZ(val)
-#define DCM bSlowerOnPagecross = 0; \
+#define DCM /*bSlowerOnPagecross = 0;*/ \
val = READ-1; \
WRITE(val) \
flagc = (regs.a >= val); \
@@ -346,11 +337,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
SETNZ(val)
#define DEA --regs.a; \
SETNZ(regs.a)
-#define DEC_NMOS bSlowerOnPagecross = 0; \
- val = READ-1; \
- SETNZ(val) \
- WRITE(val)
-#define DEC_CMOS bSlowerOnPagecross = 1; \
+#define DEC /*bSlowerOnPagecross = 0;*/ \
val = READ-1; \
SETNZ(val) \
WRITE(val)
@@ -358,22 +345,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
SETNZ(regs.x)
#define DEY --regs.y; \
SETNZ(regs.y)
-#define EOR bSlowerOnPagecross = 1; \
+#define EOR /*bSlowerOnPagecross = 1;*/ \
regs.a ^= READ; \
SETNZ(regs.a)
#define HLT regs.bJammed = 1; \
--regs.pc;
#define INA ++regs.a; \
SETNZ(regs.a)
-#define INC_NMOS bSlowerOnPagecross = 0; \
+#define INC /*bSlowerOnPagecross = 0;*/ \
val = READ+1; \
SETNZ(val) \
WRITE(val)
-#define INC_CMOS bSlowerOnPagecross = 1; \
- val = READ+1; \
- SETNZ(val) \
- WRITE(val)
-#define INS bSlowerOnPagecross = 0; \
+#define INS /*bSlowerOnPagecross = 0;*/ \
val = READ+1; \
WRITE(val) \
temp = val; \
@@ -408,38 +391,40 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
PUSH(regs.pc >> 8) \
PUSH(regs.pc & 0xFF) \
regs.pc = addr;
-#define LAS bSlowerOnPagecross = 1; \
+#define LAS /*bSlowerOnPagecross = 1*/; \
val = (BYTE)(READ & regs.sp); \
regs.a = regs.x = (BYTE) val; \
regs.sp = val | 0x100; \
SETNZ(val)
-#define LAX bSlowerOnPagecross = 1; \
+#define LAX /*bSlowerOnPagecross = 1;*/ \
regs.a = regs.x = READ; \
SETNZ(regs.a)
-#define LDA bSlowerOnPagecross = 1; \
+#define LDA /*bSlowerOnPagecross = 1;*/ \
regs.a = READ; \
SETNZ(regs.a)
-#define LDX bSlowerOnPagecross = 1; \
+#define LDD /*Undocumented 65C02: LoaD and Discard*/ \
+ READ;
+#define LDX /*bSlowerOnPagecross = 1;*/ \
regs.x = READ; \
SETNZ(regs.x)
-#define LDY bSlowerOnPagecross = 1; \
+#define LDY /*bSlowerOnPagecross = 1;*/ \
regs.y = READ; \
SETNZ(regs.y)
-#define LSE bSlowerOnPagecross = 0; \
+#define LSE /*bSlowerOnPagecross = 0;*/ \
val = READ; \
flagc = (val & 1); \
val >>= 1; \
WRITE(val) \
regs.a ^= val; \
SETNZ(regs.a)
-#define LSR_NMOS bSlowerOnPagecross = 0; \
+#define LSR_NMOS /*bSlowerOnPagecross = 0;*/ \
val = READ; \
flagc = (val & 1); \
flagn = 0; \
val >>= 1; \
SETZ(val) \
WRITE(val)
-#define LSR_CMOS bSlowerOnPagecross = 1; \
+#define LSR_CMOS /*bSlowerOnPagecross = 1;*/ \
val = READ; \
flagc = (val & 1); \
flagn = 0; \
@@ -450,12 +435,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagn = 0; \
regs.a >>= 1; \
SETZ(regs.a)
-#define NOP bSlowerOnPagecross = 1;
+#define NOP /*bSlowerOnPagecross = 1;*/
#define OAL regs.a |= 0xEE; \
regs.a &= READ; \
regs.x = regs.a; \
SETNZ(regs.a)
-#define ORA bSlowerOnPagecross = 1; \
+#define ORA /*bSlowerOnPagecross = 1;*/ \
regs.a |= READ; \
SETNZ(regs.a)
#define PHA PUSH(regs.a)
@@ -471,18 +456,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
SETNZ(regs.x)
#define PLY regs.y = POP; \
SETNZ(regs.y)
-#define RLA bSlowerOnPagecross = 0; \
+#define RLA /*bSlowerOnPagecross = 0;*/ \
val = (READ << 1) | flagc; \
flagc = (val > 0xFF); \
WRITE(val) \
regs.a &= val; \
SETNZ(regs.a)
-#define ROL_NMOS bSlowerOnPagecross = 0; \
+#define ROL_NMOS /*bSlowerOnPagecross = 0;*/ \
val = (READ << 1) | flagc; \
flagc = (val > 0xFF); \
SETNZ(val) \
WRITE(val)
-#define ROL_CMOS bSlowerOnPagecross = 1; \
+#define ROL_CMOS /*bSlowerOnPagecross = 1;*/ \
val = (READ << 1) | flagc; \
flagc = (val > 0xFF); \
SETNZ(val) \
@@ -491,13 +476,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagc = (val > 0xFF); \
regs.a = val & 0xFF; \
SETNZ(regs.a);
-#define ROR_NMOS bSlowerOnPagecross = 0; \
+#define ROR_NMOS /*bSlowerOnPagecross = 0;*/ \
temp = READ; \
val = (temp >> 1) | (flagc ? 0x80 : 0); \
flagc = (temp & 1); \
SETNZ(val) \
WRITE(val)
-#define ROR_CMOS bSlowerOnPagecross = 1; \
+#define ROR_CMOS /*bSlowerOnPagecross = 1;*/ \
temp = READ; \
val = (temp >> 1) | (flagc ? 0x80 : 0); \
flagc = (temp & 1); \
@@ -507,7 +492,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagc = (regs.a & 1); \
regs.a = val & 0xFF; \
SETNZ(regs.a)
-#define RRA bSlowerOnPagecross = 0; \
+#define RRA /*bSlowerOnPagecross = 0;*/ \
temp = READ; \
val = (temp >> 1) | (flagc ? 0x80 : 0); \
flagc = (temp & 1); \
@@ -549,10 +534,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
flagc = (temp >= val); \
regs.x = temp-val; \
SETNZ(regs.x)
-#define SAY bSlowerOnPagecross = 0; \
+#define SAY /*bSlowerOnPagecross = 0;*/ \
val = regs.y & (((base >> 8) + 1) & 0xFF); \
+ ON_PAGECROSS_REPLACE_HI_ADDR \
WRITE(val)
-#define SBC_NMOS bSlowerOnPagecross = 1; \
+#define SBC_NMOS /*bSlowerOnPagecross = 1;*/ \
temp = READ; \
temp2 = regs.a - temp - !flagc; \
if (regs.ps & AF_DECIMAL) { \
@@ -576,7 +562,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
regs.a = val & 0xFF; \
SETNZ(regs.a); \
}
-#define SBC_CMOS bSlowerOnPagecross = 1; \
+#define SBC_CMOS /*bSlowerOnPagecross = 1;*/ \
temp = READ; \
flagv = ((regs.a ^ temp) & 0x80); \
if (regs.ps & AF_DECIMAL) { \
@@ -622,29 +608,30 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define SEC flagc = 1;
#define SED regs.ps |= AF_DECIMAL;
#define SEI regs.ps |= AF_INTERRUPT;
-#define STA bSlowerOnPagecross = 0; \
+#define STA /*bSlowerOnPagecross = 0;*/ \
WRITE(regs.a)
-#define STX bSlowerOnPagecross = 0; \
+#define STX /*bSlowerOnPagecross = 0;*/ \
WRITE(regs.x)
-#define STY bSlowerOnPagecross = 0; \
+#define STY /*bSlowerOnPagecross = 0;*/ \
WRITE(regs.y)
-#define STZ bSlowerOnPagecross = 0; \
+#define STZ /*bSlowerOnPagecross = 0;*/ \
WRITE(0)
-#define TAS bSlowerOnPagecross = 0; \
+#define TAS /*bSlowerOnPagecross = 0;*/ \
val = regs.a & regs.x; \
regs.sp = 0x100 | val; \
val &= (((base >> 8) + 1) & 0xFF); \
+ ON_PAGECROSS_REPLACE_HI_ADDR \
WRITE(val)
#define TAX regs.x = regs.a; \
SETNZ(regs.x)
#define TAY regs.y = regs.a; \
SETNZ(regs.y)
-#define TRB bSlowerOnPagecross = 0; \
+#define TRB /*bSlowerOnPagecross = 0;*/ \
val = READ; \
flagz = !(regs.a & val); \
val &= ~regs.a; \
WRITE(val)
-#define TSB bSlowerOnPagecross = 0; \
+#define TSB /*bSlowerOnPagecross = 0;*/ \
val = READ; \
flagz = !(regs.a & val); \
val |= regs.a; \
@@ -659,7 +646,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define XAA regs.a = regs.x; \
regs.a &= READ; \
SETNZ(regs.a)
-#define XAS bSlowerOnPagecross = 0; \
+#define XAS /*bSlowerOnPagecross = 0;*/ \
val = regs.x & (((base >> 8) + 1) & 0xFF); \
+ ON_PAGECROSS_REPLACE_HI_ADDR \
WRITE(val)
-
diff --git a/source/Common.h b/source/Common.h
index f89db922..2bc2a071 100644
--- a/source/Common.h
+++ b/source/Common.h
@@ -70,6 +70,7 @@ enum AppMode_e
// Configuration
#define REG_CONFIG "Configuration"
#define REGVALUE_APPLE2_TYPE "Apple2 Type"
+#define REGVALUE_CPU_TYPE "CPU Type"
#define REGVALUE_OLD_APPLE2_TYPE "Computer Emulation" // Deprecated
#define REGVALUE_CONFIRM_REBOOT "Confirm Reboot" // Added at 1.24.1 PageConfig
#define REGVALUE_SPKR_VOLUME "Speaker Volume"
@@ -165,7 +166,7 @@ enum eIRQSRC {IS_6522=0, IS_SPEECH, IS_SSC, IS_MOUSE};
#define IS_APPLE2C (g_Apple2Type & APPLE2C_MASK)
#define IS_CLONE() (g_Apple2Type & APPLECLONE_MASK)
-// NB. These get persisted to the Registry, so don't change the values for these enums!
+// NB. These get persisted to the Registry & save-state file, so don't change the values for these enums!
enum eApple2Type {
A2TYPE_APPLE2=0,
A2TYPE_APPLE2PLUS,
diff --git a/source/Configuration/Config.h b/source/Configuration/Config.h
index 2915d6cb..36be83af 100644
--- a/source/Configuration/Config.h
+++ b/source/Configuration/Config.h
@@ -1,6 +1,7 @@
#pragma once
#include "..\AppleWin.h"
+#include "..\CPU.h"
#include "..\Disk.h" // BOOL enhancedisk
#include "..\HardDisk.h" // HD_CardIsEnabled()
@@ -8,13 +9,15 @@ class CConfigNeedingRestart
{
public:
CConfigNeedingRestart(UINT bEnableTheFreezesF8Rom = false) :
- m_Apple2Type(g_Apple2Type),
+ m_Apple2Type( GetApple2Type() ),
+ m_CpuType( GetMainCpu() ),
m_bEnhanceDisk(enhancedisk),
m_uSaveLoadStateMsg(0)
{
m_bEnableHDD = HD_CardIsEnabled();
m_bEnableTheFreezesF8Rom = bEnableTheFreezesF8Rom;
memset(&m_Slot, 0, sizeof(m_Slot));
+ m_SlotAux = CT_Empty;
m_Slot[4] = g_Slot4;
m_Slot[5] = g_Slot5;
}
@@ -22,6 +25,7 @@ public:
const CConfigNeedingRestart& operator= (const CConfigNeedingRestart& other)
{
m_Apple2Type = other.m_Apple2Type;
+ m_CpuType = other.m_CpuType;
memcpy(m_Slot, other.m_Slot, sizeof(m_Slot));
m_bEnhanceDisk = other.m_bEnhanceDisk;
m_bEnableHDD = other.m_bEnableHDD;
@@ -33,6 +37,7 @@ public:
bool operator== (const CConfigNeedingRestart& other) const
{
return m_Apple2Type == other.m_Apple2Type &&
+ m_CpuType == other.m_CpuType &&
memcmp(m_Slot, other.m_Slot, sizeof(m_Slot)) == 0 &&
m_bEnhanceDisk == other.m_bEnhanceDisk &&
m_bEnableHDD == other.m_bEnableHDD &&
@@ -46,7 +51,9 @@ public:
}
eApple2Type m_Apple2Type;
+ eCpuType m_CpuType;
SS_CARDTYPE m_Slot[NUM_SLOTS]; // 0..7
+ SS_CARDTYPE m_SlotAux;
BOOL m_bEnhanceDisk;
bool m_bEnableHDD;
UINT m_bEnableTheFreezesF8Rom;
diff --git a/source/Configuration/IPropertySheet.h b/source/Configuration/IPropertySheet.h
index c25b2ce8..b0312009 100644
--- a/source/Configuration/IPropertySheet.h
+++ b/source/Configuration/IPropertySheet.h
@@ -1,10 +1,13 @@
#pragma once
+class CConfigNeedingRestart;
+
__interface IPropertySheet
{
void Init(void);
DWORD GetVolumeMax(void); // TODO:TC: Move out of here
bool SaveStateSelectImage(HWND hWindow, bool bSave); // TODO:TC: Move out of here
+ void ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld);
UINT GetScrollLockToggle(void);
void SetScrollLockToggle(UINT uValue);
diff --git a/source/Configuration/PageAdvanced.cpp b/source/Configuration/PageAdvanced.cpp
index de469041..c50cf5c7 100644
--- a/source/Configuration/PageAdvanced.cpp
+++ b/source/Configuration/PageAdvanced.cpp
@@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
-#include "..\Structs.h"
#include "..\Common.h"
#include "..\ParallelPrinter.h"
diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp
index a5c47884..f525fc8c 100644
--- a/source/Configuration/PageConfig.cpp
+++ b/source/Configuration/PageConfig.cpp
@@ -129,6 +129,7 @@ BOOL CPageConfig::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
const DWORD NewComputerMenuItem = (DWORD) SendDlgItemMessage(hWnd, IDC_COMPUTER, CB_GETCURSEL, 0, 0);
const eApple2Type NewApple2Type = GetApple2Type(NewComputerMenuItem);
m_PropertySheetHelper.GetConfigNew().m_Apple2Type = NewApple2Type;
+ m_PropertySheetHelper.GetConfigNew().m_CpuType = ProbeMainCpuDefault(NewApple2Type);
}
break;
diff --git a/source/Configuration/PageInput.cpp b/source/Configuration/PageInput.cpp
index 9326afee..7bd0a20b 100644
--- a/source/Configuration/PageInput.cpp
+++ b/source/Configuration/PageInput.cpp
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
-#include "..\Structs.h"
+#include "..\SaveState_Structs_common.h"
#include "..\Common.h"
#include "..\Keyboard.h"
@@ -214,12 +214,12 @@ void CPageInput::DlgOK(HWND hWnd)
if (JoySetEmulationType(hWnd, m_nJoy0ChoiceTranlationTbl[uNewJoyType0], JN_JOYSTICK0, bIsSlot4Mouse))
{
- REGSAVE(TEXT(REGVALUE_JOYSTICK0_EMU_TYPE), joytype[0]);
+ REGSAVE(TEXT(REGVALUE_JOYSTICK0_EMU_TYPE), JoyGetJoyType(0));
}
if (JoySetEmulationType(hWnd, m_nJoy1ChoiceTranlationTbl[uNewJoyType1], JN_JOYSTICK1, bIsSlot4Mouse))
{
- REGSAVE(TEXT(REGVALUE_JOYSTICK1_EMU_TYPE), joytype[1]);
+ REGSAVE(TEXT(REGVALUE_JOYSTICK1_EMU_TYPE), JoyGetJoyType(1));
}
JoySetTrim((short)SendDlgItemMessage(hWnd, IDC_SPIN_XTRIM, UDM_GETPOS, 0, 0), true);
@@ -305,7 +305,7 @@ void CPageInput::InitJoystickChoices(HWND hWnd, int nJoyNum, int nIdcValue)
for(UINT i=nJC_KEYBD_CURSORS; i "file" + ".aws.yaml"
+ else
+ strcpy(&szFilename[ofn.nFileOffset+uStrLenFile], szAWS_EXT3); // "file" += ".aws.yaml"
+ }
+ else if ((uStrLenFile <= uStrLenExt3) || (strcmp(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt3], szAWS_EXT3) != 0))
+ {
+ if (strcmp(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt1], szAWS_EXT1) == 0)
+ strcpy(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt1], szAWS_EXT3); // "file.aws" -> "file" + ".aws.yaml"
+ else if (strcmp(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt2], szAWS_EXT2) == 0)
+ strcpy(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt2], szAWS_EXT3); // "file.yaml" -> "file" + ".aws.yaml"
+ else
+ strcpy(&szFilename[ofn.nFileOffset+uStrLenFile], szAWS_EXT3); // "file" += ".aws.yaml"
+ }
}
+ strcpy(m_szSSNewFilename, &szFilename[ofn.nFileOffset]);
strcpy(m_szSSNewPathname, szFilename);
szFilename[ofn.nFileOffset] = 0;
@@ -319,41 +353,52 @@ 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_CpuType))
+ {
+ SaveCpuType(ConfigNew.m_CpuType);
+ }
+
+ 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)
{
// NB. clone-type is encoded in g_Apple2Type
- m_ConfigOld.m_Apple2Type = g_Apple2Type;
+ m_ConfigOld.m_Apple2Type = GetApple2Type();
+ m_ConfigOld.m_CpuType = GetMainCpu();
m_ConfigOld.m_Slot[4] = g_Slot4;
m_ConfigOld.m_Slot[5] = g_Slot5;
m_ConfigOld.m_bEnhanceDisk = enhancedisk;
@@ -371,7 +416,8 @@ void CPropertySheetHelper::SaveCurrentConfig(void)
void CPropertySheetHelper::RestoreCurrentConfig(void)
{
// NB. clone-type is encoded in g_Apple2Type
- g_Apple2Type = m_ConfigOld.m_Apple2Type;
+ SetApple2Type(m_ConfigOld.m_Apple2Type);
+ SetMainCpu(m_ConfigOld.m_CpuType);
g_Slot4 = m_ConfigOld.m_Slot[4];
g_Slot5 = m_ConfigOld.m_Slot[5];
enhancedisk = m_ConfigOld.m_bEnhanceDisk;
@@ -411,6 +457,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");
@@ -421,6 +470,9 @@ bool CPropertySheetHelper::HardwareConfigChanged(HWND hWnd)
if (CONFIG_CHANGED(m_Apple2Type))
strMsgMain += ". Emulated computer has changed\n";
+ if (CONFIG_CHANGED(m_CpuType))
+ strMsgMain += ". Emulated main CPU has changed\n";
+
if (CONFIG_CHANGED(m_Slot[4]))
strMsgMain += GetSlot(4);
diff --git a/source/Configuration/PropertySheetHelper.h b/source/Configuration/PropertySheetHelper.h
index 74896cdb..5fd83fd4 100644
--- a/source/Configuration/PropertySheetHelper.h
+++ b/source/Configuration/PropertySheetHelper.h
@@ -18,7 +18,6 @@ public:
void SetSlot5(SS_CARDTYPE NewCardType);
std::string BrowseToFile(HWND hWindow, TCHAR* pszTitle, TCHAR* REGVALUE,TCHAR* FILEMASKS);
void SaveStateUpdate();
- void GetDiskBaseNameWithAWS(TCHAR* pszFilename);
int SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bool bSave);
void PostMsgAfterClose(HWND hWnd, PAGETYPE page);
@@ -37,17 +36,20 @@ 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);
bool IsOkToRestart(HWND hWnd);
void SaveComputerType(eApple2Type NewApple2Type);
+ void SaveCpuType(eCpuType NewCpuType);
bool HardwareConfigChanged(HWND hWnd);
bool CheckChangesForRestart(HWND hWnd);
void ApplyNewConfig(void);
void RestoreCurrentConfig(void);
std::string GetSlot(const UINT uSlot);
std::string GetCardName(const SS_CARDTYPE CardType);
+ void GetDiskBaseNameWithAWS(TCHAR* pszFilename);
PAGETYPE m_LastPage;
UINT32 m_bmPages;
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index 1441ad97..a985c577 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -1955,7 +1955,7 @@ Update_t CmdTraceFile (int nArgs)
fclose( g_hTraceFile );
g_hTraceFile = NULL;
- sprintf( sText, "Trace stopped." );
+ _snprintf( sText, sizeof(sText), "Trace stopped." );
}
else
{
@@ -1975,16 +1975,17 @@ Update_t CmdTraceFile (int nArgs)
if (g_hTraceFile)
{
- sprintf( sText, "Trace started: %s", sFilePath );
+ _snprintf( sText, sizeof(sText), "Trace started: %s", sFilePath );
g_bTraceHeader = true;
}
else
{
- sprintf( sText, "Trace ERROR: %s", sFilePath );
+ _snprintf( sText, sizeof(sText), "Trace ERROR: %s", sFilePath );
}
}
-
+
+ sText[sizeof(sText)-1] = 0; // _snprintf needs null if string was longer than buffer
ConsoleBufferPush( sText );
ConsoleBufferToDisplay();
@@ -2313,7 +2314,7 @@ void ConfigSave_PrepareHeader ( const Parameters_e eCategory, const Commands_e e
sprintf( sText, "%s %s = %s\n"
, g_aTokens[ TOKEN_COMMENT_EOL ].sToken
, g_aParameters[ PARAM_CATEGORY ].m_sName
- , g_aParameters[ eCategory ]
+ , g_aParameters[ eCategory ].m_sName
);
g_ConfigState.PushLine( sText );
@@ -4297,10 +4298,10 @@ Update_t CmdMemoryLoad (int nArgs)
TCHAR sLoadSaveFilePath[ MAX_PATH ];
_tcscpy( sLoadSaveFilePath, g_sCurrentDir ); // TODO: g_sDebugDir
- WORD nAddressStart;
- WORD nAddress2 = 0;
- WORD nAddressEnd = 0;
- int nAddressLen = 0;
+ WORD nAddressStart = 0;
+ WORD nAddress2 = 0;
+ WORD nAddressEnd = 0;
+ int nAddressLen = 0;
if( pFileType )
{
@@ -4370,7 +4371,7 @@ Update_t CmdMemoryLoad (int nArgs)
if (bBankSpecified)
{
- MemUpdatePaging(1);
+ MemUpdatePaging(TRUE);
}
else
{
@@ -5975,6 +5976,7 @@ Update_t CmdOutputPrintf (int nArgs)
{
case '\\':
eThis = PS_ESCAPE;
+ break;
case '%':
eThis = PS_TYPE;
break;
@@ -7027,7 +7029,6 @@ Update_t CmdWindowViewCode (int nArgs)
Update_t CmdWindowViewConsole (int nArgs)
{
return _CmdWindowViewFull( WINDOW_CONSOLE );
- return UPDATE_ALL;
}
//===========================================================================
@@ -7049,14 +7050,12 @@ Update_t CmdWindowViewOutput (int nArgs)
Update_t CmdWindowViewSource (int nArgs)
{
return _CmdWindowViewFull( WINDOW_CONSOLE );
- return UPDATE_ALL;
}
//===========================================================================
Update_t CmdWindowViewSymbols (int nArgs)
{
return _CmdWindowViewFull( WINDOW_CONSOLE );
- return UPDATE_ALL;
}
//===========================================================================
@@ -7771,7 +7770,7 @@ void OutputTraceLine ()
(unsigned)regs.sp,
(char*) sFlags
, sDisassembly
- , sTarget
+ //, sTarget // TODO: Show target?
);
}
}
diff --git a/source/Debugger/Debug.h b/source/Debugger/Debug.h
index 8c1fdc79..add6cca5 100644
--- a/source/Debugger/Debug.h
+++ b/source/Debugger/Debug.h
@@ -1,6 +1,6 @@
#pragma once
-#include "..\Structs.h"
+#include "..\SaveState_Structs_v1.h" // For SS_CARD_MOCKINGBOARD
#include "..\Common.h"
#include "Debugger_Types.h"
diff --git a/source/Debugger/Debugger_Assembler.cpp b/source/Debugger/Debugger_Assembler.cpp
index 63a46f81..4c2730cd 100644
--- a/source/Debugger/Debugger_Assembler.cpp
+++ b/source/Debugger/Debugger_Assembler.cpp
@@ -565,7 +565,6 @@ bool _6502_GetStackReturnAddress ( WORD & nAddress_ )
if (nStack <= (_6502_STACK_END - 1))
{
- nAddress_ = 0;
nAddress_ = (unsigned)*(LPBYTE)(mem + nStack);
nStack++;
diff --git a/source/Debugger/Debugger_Commands.cpp b/source/Debugger/Debugger_Commands.cpp
index 105561d2..970ec3d1 100644
--- a/source/Debugger/Debugger_Commands.cpp
+++ b/source/Debugger/Debugger_Commands.cpp
@@ -40,345 +40,345 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Command_t g_aCommands[] =
{
// Assembler
-// {"!" , CmdAssemberMini , CMD_ASSEMBLER_MINI , "Mini assembler" }
- {"A" , CmdAssemble , CMD_ASSEMBLE , "Assemble instructions" }
+// {TEXT("!") , CmdAssemberMini , CMD_ASSEMBLER_MINI , "Mini assembler" },
+ {TEXT("A") , CmdAssemble , CMD_ASSEMBLE , "Assemble instructions" },
// CPU (Main)
- ,{"." , CmdCursorJumpPC , CMD_CURSOR_JUMP_PC , "Locate the cursor in the disasm window" } // centered
- ,{"=" , CmdCursorSetPC , CMD_CURSOR_SET_PC , "Sets the PC to the current instruction" }
-// ,{"g" , CmdGoNormalSpeed , CMD_GO_NORMAL , "Run @ normal speed [until PC == address]" }
-// ,{"G" , CmdGoFullSpeed , CMD_GO_FULL , "Run @ full speed [until PC == address]" }
- ,{"G" , CmdGo , CMD_GO , "Run @ full speed [until PC == address]" }
- ,{"IN" , CmdIn , CMD_IN , "Input byte from IO $C0xx" }
- ,{"KEY" , CmdKey , CMD_INPUT_KEY , "Feed key into emulator" }
- ,{"JSR" , CmdJSR , CMD_JSR , "Call sub-routine" }
- ,{"NOP" , CmdNOP , CMD_NOP , "Zap the current instruction with a NOP" }
- ,{"OUT" , CmdOut , CMD_OUT , "Output byte to IO $C0xx" }
+ {TEXT(".") , CmdCursorJumpPC , CMD_CURSOR_JUMP_PC , "Locate the cursor in the disasm window" }, // centered
+ {TEXT("=") , CmdCursorSetPC , CMD_CURSOR_SET_PC , "Sets the PC to the current instruction" },
+// {TEXT("g") , CmdGoNormalSpeed , CMD_GO_NORMAL , "Run @ normal speed [until PC == address]" },
+// {TEXT("G") , CmdGoFullSpeed , CMD_GO_FULL , "Run @ full speed [until PC == address]" },
+ {TEXT("G") , CmdGo , CMD_GO , "Run @ full speed [until PC == address]" },
+ {TEXT("IN") , CmdIn , CMD_IN , "Input byte from IO $C0xx" },
+ {TEXT("KEY") , CmdKey , CMD_INPUT_KEY , "Feed key into emulator" },
+ {TEXT("JSR") , CmdJSR , CMD_JSR , "Call sub-routine" },
+ {TEXT("NOP") , CmdNOP , CMD_NOP , "Zap the current instruction with a NOP" },
+ {TEXT("OUT") , CmdOut , CMD_OUT , "Output byte to IO $C0xx" },
// CPU - Meta Info
- ,{"PROFILE" , CmdProfile , CMD_PROFILE , "List/Save 6502 profiling" }
- ,{"R" , CmdRegisterSet , CMD_REGISTER_SET , "Set register" }
+ {TEXT("PROFILE") , CmdProfile , CMD_PROFILE , "List/Save 6502 profiling" },
+ {TEXT("R") , CmdRegisterSet , CMD_REGISTER_SET , "Set register" },
// CPU - Stack
- ,{"POP" , CmdStackPop , CMD_STACK_POP }
- ,{"PPOP" , CmdStackPopPseudo , CMD_STACK_POP_PSEUDO }
- ,{"PUSH" , CmdStackPop , CMD_STACK_PUSH }
-// ,{"RTS" , CmdStackReturn , CMD_STACK_RETURN }
- ,{"P" , CmdStepOver , CMD_STEP_OVER , "Step current instruction" }
- ,{"RTS" , CmdStepOut , CMD_STEP_OUT , "Step out of subroutine" }
+ {TEXT("POP") , CmdStackPop , CMD_STACK_POP },
+ {TEXT("PPOP") , CmdStackPopPseudo , CMD_STACK_POP_PSEUDO },
+ {TEXT("PUSH") , CmdStackPop , CMD_STACK_PUSH },
+// {TEXT("RTS") , CmdStackReturn , CMD_STACK_RETURN },
+ {TEXT("P") , CmdStepOver , CMD_STEP_OVER , "Step current instruction" },
+ {TEXT("RTS") , CmdStepOut , CMD_STEP_OUT , "Step out of subroutine" },
// CPU - Meta Info
- ,{"T" , CmdTrace , CMD_TRACE , "Trace current instruction" }
- ,{"TF" , CmdTraceFile , CMD_TRACE_FILE , "Save trace to filename" }
- ,{"TL" , CmdTraceLine , CMD_TRACE_LINE , "Trace (with cycle counting)" }
- ,{"U" , CmdUnassemble , CMD_UNASSEMBLE , "Disassemble instructions" }
-// ,{"WAIT" , CmdWait , CMD_WAIT , "Run until"
+ {TEXT("T") , CmdTrace , CMD_TRACE , "Trace current instruction" },
+ {TEXT("TF") , CmdTraceFile , CMD_TRACE_FILE , "Save trace to filename" },
+ {TEXT("TL") , CmdTraceLine , CMD_TRACE_LINE , "Trace (with cycle counting)" },
+ {TEXT("U") , CmdUnassemble , CMD_UNASSEMBLE , "Disassemble instructions" },
+// {TEXT("WAIT") , CmdWait , CMD_WAIT , "Run until
// Bookmarks
- ,{"BM" , CmdBookmark , CMD_BOOKMARK , "Alias for BMA (Bookmark Add)" }
- ,{"BMA" , CmdBookmarkAdd , CMD_BOOKMARK_ADD , "Add/Update addess to bookmark" }
- ,{"BMC" , CmdBookmarkClear , CMD_BOOKMARK_CLEAR , "Clear (remove) bookmark" }
- ,{"BML" , CmdBookmarkList , CMD_BOOKMARK_LIST , "List all bookmarks" }
- ,{"BMG" , CmdBookmarkGoto , CMD_BOOKMARK_GOTO , "Move cursor to bookmark" }
-// ,{"BMLOAD" , CmdBookmarkLoad , CMD_BOOKMARK_LOAD , "Load bookmarks" }
- ,{"BMSAVE" , CmdBookmarkSave , CMD_BOOKMARK_SAVE , "Save bookmarks" }
+ {TEXT("BM") , CmdBookmark , CMD_BOOKMARK , "Alias for BMA (Bookmark Add)" },
+ {TEXT("BMA") , CmdBookmarkAdd , CMD_BOOKMARK_ADD , "Add/Update addess to bookmark" },
+ {TEXT("BMC") , CmdBookmarkClear , CMD_BOOKMARK_CLEAR , "Clear (remove) bookmark" },
+ {TEXT("BML") , CmdBookmarkList , CMD_BOOKMARK_LIST , "List all bookmarks" },
+ {TEXT("BMG") , CmdBookmarkGoto , CMD_BOOKMARK_GOTO , "Move cursor to bookmark" },
+// {TEXT("BMLOAD") , CmdBookmarkLoad , CMD_BOOKMARK_LOAD , "Load bookmarks" },
+ {TEXT("BMSAVE") , CmdBookmarkSave , CMD_BOOKMARK_SAVE , "Save bookmarks" },
// Breakpoints
- ,{"BRK" , CmdBreakInvalid , CMD_BREAK_INVALID , "Enter debugger on BRK or INVALID" }
- ,{"BRKOP" , CmdBreakOpcode , CMD_BREAK_OPCODE , "Enter debugger on opcode" }
- ,{"BP" , CmdBreakpoint , CMD_BREAKPOINT , "Alias for BPR (Breakpoint Register Add)" }
- ,{"BPA" , CmdBreakpointAddSmart , CMD_BREAKPOINT_ADD_SMART , "Add (smart) breakpoint" }
-// ,{"BPP" , CmdBreakpointAddFlag , CMD_BREAKPOINT_ADD_FLAG , "Add breakpoint on flags" }
- ,{"BPR" , CmdBreakpointAddReg , CMD_BREAKPOINT_ADD_REG , "Add breakpoint on register value" } // NOTE! Different from SoftICE !!!!
- ,{"BPX" , CmdBreakpointAddPC , CMD_BREAKPOINT_ADD_PC , "Add breakpoint at current instruction" }
- ,{"BPIO" , CmdBreakpointAddIO , CMD_BREAKPOINT_ADD_IO , "Add breakpoint for IO address $C0xx" }
- ,{"BPM" , CmdBreakpointAddMem , CMD_BREAKPOINT_ADD_MEM , "Add breakpoint on memory access" } // SoftICE
+ {TEXT("BRK") , CmdBreakInvalid , CMD_BREAK_INVALID , "Enter debugger on BRK or INVALID" },
+ {TEXT("BRKOP") , CmdBreakOpcode , CMD_BREAK_OPCODE , "Enter debugger on opcode" },
+ {TEXT("BP") , CmdBreakpoint , CMD_BREAKPOINT , "Alias for BPR (Breakpoint Register Add)" },
+ {TEXT("BPA") , CmdBreakpointAddSmart, CMD_BREAKPOINT_ADD_SMART , "Add (smart) breakpoint" },
+// {TEXT("BPP") , CmdBreakpointAddFlag , CMD_BREAKPOINT_ADD_FLAG , "Add breakpoint on flags" },
+ {TEXT("BPR") , CmdBreakpointAddReg , CMD_BREAKPOINT_ADD_REG , "Add breakpoint on register value" }, // NOTE! Different from SoftICE !!!!
+ {TEXT("BPX") , CmdBreakpointAddPC , CMD_BREAKPOINT_ADD_PC , "Add breakpoint at current instruction" },
+ {TEXT("BPIO") , CmdBreakpointAddIO , CMD_BREAKPOINT_ADD_IO , "Add breakpoint for IO address $C0xx" },
+ {TEXT("BPM") , CmdBreakpointAddMem , CMD_BREAKPOINT_ADD_MEM , "Add breakpoint on memory access" }, // SoftICE
- ,{"BPC" , CmdBreakpointClear , CMD_BREAKPOINT_CLEAR , "Clear (remove) breakpoint" } // SoftICE
- ,{"BPD" , CmdBreakpointDisable , CMD_BREAKPOINT_DISABLE , "Disable breakpoint- it is still in the list, just not active" } // SoftICE
- ,{"BPEDIT" , CmdBreakpointEdit , CMD_BREAKPOINT_EDIT , "Edit breakpoint" } // SoftICE
- ,{"BPE" , CmdBreakpointEnable , CMD_BREAKPOINT_ENABLE , "(Re)Enable disabled breakpoint" } // SoftICE
- ,{"BPL" , CmdBreakpointList , CMD_BREAKPOINT_LIST , "List all breakpoints" } // SoftICE
-// ,{"BPLOAD" , CmdBreakpointLoad , CMD_BREAKPOINT_LOAD , "Loads breakpoints" }
- ,{"BPSAVE" , CmdBreakpointSave , CMD_BREAKPOINT_SAVE , "Saves breakpoints" }
+ {TEXT("BPC") , CmdBreakpointClear , CMD_BREAKPOINT_CLEAR , "Clear (remove) breakpoint" }, // SoftICE
+ {TEXT("BPD") , CmdBreakpointDisable , CMD_BREAKPOINT_DISABLE , "Disable breakpoint- it is still in the list, just not active" }, // SoftICE
+ {TEXT("BPEDIT") , CmdBreakpointEdit , CMD_BREAKPOINT_EDIT , "Edit breakpoint" }, // SoftICE
+ {TEXT("BPE") , CmdBreakpointEnable , CMD_BREAKPOINT_ENABLE , "(Re)Enable disabled breakpoint" }, // SoftICE
+ {TEXT("BPL") , CmdBreakpointList , CMD_BREAKPOINT_LIST , "List all breakpoints" }, // SoftICE
+// {TEXT("BPLOAD") , CmdBreakpointLoad , CMD_BREAKPOINT_LOAD , "Loads breakpoints" },
+ {TEXT("BPSAVE") , CmdBreakpointSave , CMD_BREAKPOINT_SAVE , "Saves breakpoints" },
// Config
- ,{"BENCHMARK" , CmdBenchmark , CMD_BENCHMARK , "Benchmark the emulator" }
- ,{"BW" , CmdConfigColorMono , CMD_CONFIG_BW , "Sets/Shows RGB for Black & White scheme" }
- ,{"COLOR" , CmdConfigColorMono , CMD_CONFIG_COLOR , "Sets/Shows RGB for color scheme" }
-// ,{"OPTION" , CmdConfigMenu , CMD_CONFIG_MENU , "Access config options" }
- ,{"DISASM" , CmdConfigDisasm , CMD_CONFIG_DISASM , "Sets/Shows disassembly view options." }
- ,{"FONT" , CmdConfigFont , CMD_CONFIG_FONT , "Shows current font or sets new one" }
- ,{"HCOLOR" , CmdConfigHColor , CMD_CONFIG_HCOLOR , "Sets/Shows colors mapped to Apple HGR" }
- ,{"LOAD" , CmdConfigLoad , CMD_CONFIG_LOAD , "Load debugger configuration" }
- ,{"MONO" , CmdConfigColorMono , CMD_CONFIG_MONOCHROME , "Sets/Shows RGB for monochrome scheme" }
- ,{"SAVE" , CmdConfigSave , CMD_CONFIG_SAVE , "Save debugger configuration" }
- ,{"PWD" , CmdConfigGetDebugDir , CMD_CONFIG_GET_DEBUG_DIR , "Display current debugger directory for scripts & mem load/save." }
- ,{"CD" , CmdConfigSetDebugDir , CMD_CONFIG_SET_DEBUG_DIR , "Update current debugger directory." }
+ {TEXT("BENCHMARK") , CmdBenchmark , CMD_BENCHMARK , "Benchmark the emulator" },
+ {TEXT("BW") , CmdConfigColorMono , CMD_CONFIG_BW , "Sets/Shows RGB for Black & White scheme" },
+ {TEXT("COLOR") , CmdConfigColorMono , CMD_CONFIG_COLOR , "Sets/Shows RGB for color scheme" },
+// {TEXT("OPTION") , CmdConfigMenu , CMD_CONFIG_MENU , "Access config options" },
+ {TEXT("DISASM") , CmdConfigDisasm , CMD_CONFIG_DISASM , "Sets/Shows disassembly view options." },
+ {TEXT("FONT") , CmdConfigFont , CMD_CONFIG_FONT , "Shows current font or sets new one" },
+ {TEXT("HCOLOR") , CmdConfigHColor , CMD_CONFIG_HCOLOR , "Sets/Shows colors mapped to Apple HGR" },
+ {TEXT("LOAD") , CmdConfigLoad , CMD_CONFIG_LOAD , "Load debugger configuration" },
+ {TEXT("MONO") , CmdConfigColorMono , CMD_CONFIG_MONOCHROME , "Sets/Shows RGB for monochrome scheme" },
+ {TEXT("SAVE") , CmdConfigSave , CMD_CONFIG_SAVE , "Save debugger configuration" },
+ {TEXT("PWD") , CmdConfigGetDebugDir , CMD_CONFIG_GET_DEBUG_DIR , "Displays the current debugger directory. Used for scripts & mem load/save." },
+ {TEXT("CD") , CmdConfigSetDebugDir , CMD_CONFIG_SET_DEBUG_DIR , "Updates the current debugger directory." },
// Cursor
- ,{"RET" , CmdCursorJumpRetAddr , CMD_CURSOR_JUMP_RET_ADDR , "Sets the cursor to the subroutine caller" }
- ,{ "^" , NULL , CMD_CURSOR_LINE_UP } // \x2191 = Up Arrow (Unicode)
- ,{"Shift ^" , NULL , CMD_CURSOR_LINE_UP_1 }
- ,{ "v" , NULL , CMD_CURSOR_LINE_DOWN } // \x2193 = Dn Arrow (Unicode)
- ,{"Shift v" , NULL , CMD_CURSOR_LINE_DOWN_1 }
- ,{"PAGEUP" , CmdCursorPageUp , CMD_CURSOR_PAGE_UP , "Scroll up one screen" }
- ,{"PAGEUP256" , CmdCursorPageUp256 , CMD_CURSOR_PAGE_UP_256 , "Scroll up 256 bytes" } // Shift
- ,{"PAGEUP4K" , CmdCursorPageUp4K , CMD_CURSOR_PAGE_UP_4K , "Scroll up 4096 bytes" } // Ctrl
- ,{"PAGEDN" , CmdCursorPageDown , CMD_CURSOR_PAGE_DOWN , "Scroll down one scren" }
- ,{"PAGEDOWN256" , CmdCursorPageDown256 , CMD_CURSOR_PAGE_DOWN_256 , "Scroll down 256 bytes" } // Shift
- ,{"PAGEDOWN4K" , CmdCursorPageDown4K , CMD_CURSOR_PAGE_DOWN_4K , "Scroll down 4096 bytes" } // Ctrl
+ {TEXT("RET") , CmdCursorJumpRetAddr , CMD_CURSOR_JUMP_RET_ADDR , "Sets the cursor to the sub-routine caller" },
+ {TEXT( "^") , NULL , CMD_CURSOR_LINE_UP }, // \x2191 = Up Arrow (Unicode)
+ {TEXT("Shift ^") , NULL , CMD_CURSOR_LINE_UP_1 },
+ {TEXT( "v") , NULL , CMD_CURSOR_LINE_DOWN }, // \x2193 = Dn Arrow (Unicode)
+ {TEXT("Shift v") , NULL , CMD_CURSOR_LINE_DOWN_1 },
+ {TEXT("PAGEUP" ) , CmdCursorPageUp , CMD_CURSOR_PAGE_UP , "Scroll up one screen" },
+ {TEXT("PAGEUP256") , CmdCursorPageUp256 , CMD_CURSOR_PAGE_UP_256 , "Scroll up 256 bytes" }, // Shift
+ {TEXT("PAGEUP4K" ) , CmdCursorPageUp4K , CMD_CURSOR_PAGE_UP_4K , "Scroll up 4096 bytes" }, // Ctrl
+ {TEXT("PAGEDN" ) , CmdCursorPageDown , CMD_CURSOR_PAGE_DOWN , "Scroll down one scren" },
+ {TEXT("PAGEDOWN256") , CmdCursorPageDown256 , CMD_CURSOR_PAGE_DOWN_256 , "Scroll down 256 bytes" }, // Shift
+ {TEXT("PAGEDOWN4K" ) , CmdCursorPageDown4K , CMD_CURSOR_PAGE_DOWN_4K , "Scroll down 4096 bytes" }, // Ctrl
// Disassembler Data
- ,{"Z" , CmdDisasmDataDefByte1 , CMD_DISASM_DATA , "Treat byte [range] as data" }
- ,{"X" , CmdDisasmDataDefCode , CMD_DISASM_CODE , "Treat byte [range] as code" }
+ {TEXT("Z") , CmdDisasmDataDefByte1 , CMD_DISASM_DATA , "Treat byte [range] as data" },
+ {TEXT("X") , CmdDisasmDataDefCode , CMD_DISASM_CODE , "Treat byte [range] as code" },
// TODO: Conflicts with monitor command #L -> 000DL
- ,{"B" , CmdDisasmDataList , CMD_DISASM_LIST , "List all byte ranges treated as data" }
+ {TEXT("B") , CmdDisasmDataList , CMD_DISASM_LIST , "List all byte ranges treated as data" },
// without symbol lookup
- ,{"DB" , CmdDisasmDataDefByte1 , CMD_DEFINE_DATA_BYTE1 , "Define byte(s)" }
- ,{"DB2" , CmdDisasmDataDefByte2 , CMD_DEFINE_DATA_BYTE2 , "Define byte array, display 2 bytes/line" }
- ,{"DB4" , CmdDisasmDataDefByte4 , CMD_DEFINE_DATA_BYTE4 , "Define byte array, display 4 bytes/line" }
- ,{"DB8" , CmdDisasmDataDefByte8 , CMD_DEFINE_DATA_BYTE8 , "Define byte array, display 8 bytes/line" }
- ,{"DW" , CmdDisasmDataDefWord1 , CMD_DEFINE_DATA_WORD1 , "Define address array" }
- ,{"DW2" , CmdDisasmDataDefWord2 , CMD_DEFINE_DATA_WORD2 , "Define address array, display 2 words/line" }
- ,{"DW4" , CmdDisasmDataDefWord4 , CMD_DEFINE_DATA_WORD4 , "Define address array, display 4 words/line" }
- ,{"ASC" , CmdDisasmDataDefString , CMD_DEFINE_DATA_STR , "Define text string" } // 2.7.0.26 Changed: DS to ASC because DS is used as "Define Space" assembler directive
-// .{"DF" , CmdDisasmDataDefFloat , CMD_DEFINE_DATA_FLOAT , "Define AppleSoft (packed) Float" }
-// .{"DFX" , CmdDisasmDataDefFloatUnpack , CMD_DEFINE_DATA_FLOAT2 , "Define AppleSoft (unpacked) Float" }
+ {TEXT("DB") , CmdDisasmDataDefByte1 , CMD_DEFINE_DATA_BYTE1, "Define byte(s)" },
+ {TEXT("DB2") , CmdDisasmDataDefByte2 , CMD_DEFINE_DATA_BYTE2, "Define byte array, display 2 bytes/line" },
+ {TEXT("DB4") , CmdDisasmDataDefByte4 , CMD_DEFINE_DATA_BYTE4, "Define byte array, display 4 bytes/line" },
+ {TEXT("DB8") , CmdDisasmDataDefByte8 , CMD_DEFINE_DATA_BYTE8, "Define byte array, display 8 bytes/line" },
+ {TEXT("DW") , CmdDisasmDataDefWord1 , CMD_DEFINE_DATA_WORD1, "Define address array" },
+ {TEXT("DW2") , CmdDisasmDataDefWord2 , CMD_DEFINE_DATA_WORD2, "Define address array, display 2 words/line" },
+ {TEXT("DW4") , CmdDisasmDataDefWord4 , CMD_DEFINE_DATA_WORD4, "Define address array, display 4 words/line" },
+ {TEXT("ASC") , CmdDisasmDataDefString , CMD_DEFINE_DATA_STR , "Define text string" }, // 2.7.0.26 Changed: DS to ASC because DS is used as "Define Space" assembler directive
+// {TEXT("DF") , CmdDisasmDataDefFloat , CMD_DEFINE_DATA_FLOAT, "Define AppleSoft (packed) Float" },
+// {TEXT("DFX") , CmdDisasmDataDefFloatUnpack , CMD_DEFINE_DATA_FLOAT2,"Define AppleSoft (unpacked) Float" },
// with symbol lookup
-// .{"DA<>" , CmdDisasmDataDefAddress8HL , CMD_DEFINE_ADDR_8_HL , "Define split array of addresses, high byte section followed by low byte section" }
-// .{"DA><" , CmdDisasmDataDefAddress8LH , CMD_DEFINE_ADDR_8_LH , "Define split array of addresses, low byte section followed by high byte section" }
-// .{"DA<" , CmdDisasmDataDefAddress8H , CMD_DEFINE_ADDR_BYTE_H , "Define array of high byte addresses" }
-// .{"DB>" , CmdDisasmDataDefAddress8L , CMD_DEFINE_ADDR_BYTE_L , "Define array of low byte addresses" }
- ,{"DA" , CmdDisasmDataDefAddress16 , CMD_DEFINE_ADDR_WORD , "Define array of word addresses" }
+// {TEXT("DA<>") , CmdDisasmDataDefAddress8HL , CMD_DEFINE_ADDR_8_HL , "Define split array of addresses, high byte section followed by low byte section" },
+// {TEXT("DA><") , CmdDisasmDataDefAddress8LH , CMD_DEFINE_ADDR_8_LH , "Define split array of addresses, low byte section followed by high byte section" },
+// {TEXT("DA<") , CmdDisasmDataDefAddress8H , CMD_DEFINE_ADDR_BYTE_H , "Define array of high byte addresses" },
+// {TEXT("DB>") , CmdDisasmDataDefAddress8L , CMD_DEFINE_ADDR_BYTE_L , "Define array of low byte addresses" }
+ {TEXT("DA") , CmdDisasmDataDefAddress16 , CMD_DEFINE_ADDR_WORD , "Define array of word addresses" },
// TODO: Rename config cmd: DISASM
-// {"UA" , CmdDisasmDataSmart , CMD_SMART_DISASSEMBLE , "Analyze opcodes to determine if code or data" }
+// {TEXT("UA") , CmdDisasmDataSmart , CMD_SMART_DISASSEMBLE, "Analyze opcodes to determine if code or data" },
// Disk
- ,{"DISK" , CmdDisk , CMD_DISK , "Access Disk Drive Functions" }
+ {TEXT("DISK") , CmdDisk , CMD_DISK , "Access Disk Drive Functions" },
// Flags
-// {"FC" , CmdFlag , CMD_FLAG_CLEAR , "Clear specified Flag" } // NVRBDIZC see AW_CPU.cpp AF_*
+// {TEXT("FC") , CmdFlag , CMD_FLAG_CLEAR , "Clear specified Flag" }, // NVRBDIZC see AW_CPU.cpp AF_*
// TODO: Conflicts with monitor command #L -> 000CL
- ,{"CL" , CmdFlag , CMD_FLAG_CLEAR , "Clear specified Flag" } // NVRBDIZC see AW_CPU.cpp AF_*
+ {TEXT("CL") , CmdFlag , CMD_FLAG_CLEAR , "Clear specified Flag" }, // NVRBDIZC see AW_CPU.cpp AF_*
- ,{"CLC" , CmdFlagClear , CMD_FLAG_CLR_C , "Clear Flag Carry" } // 0 // Legacy
- ,{"CLZ" , CmdFlagClear , CMD_FLAG_CLR_Z , "Clear Flag Zero" } // 1
- ,{"CLI" , CmdFlagClear , CMD_FLAG_CLR_I , "Clear Flag Interrupts Disabled" } // 2
- ,{"CLD" , CmdFlagClear , CMD_FLAG_CLR_D , "Clear Flag Decimal (BCD)" } // 3
- ,{"CLB" , CmdFlagClear , CMD_FLAG_CLR_B , "CLear Flag Break" } // 4 // Legacy
- ,{"CLR" , CmdFlagClear , CMD_FLAG_CLR_R , "Clear Flag Reserved" } // 5
- ,{"CLV" , CmdFlagClear , CMD_FLAG_CLR_V , "Clear Flag Overflow" } // 6
- ,{"CLN" , CmdFlagClear , CMD_FLAG_CLR_N , "Clear Flag Negative (Sign)" } // 7
+ {TEXT("CLC") , CmdFlagClear , CMD_FLAG_CLR_C , "Clear Flag Carry" }, // 0 // Legacy
+ {TEXT("CLZ") , CmdFlagClear , CMD_FLAG_CLR_Z , "Clear Flag Zero" }, // 1
+ {TEXT("CLI") , CmdFlagClear , CMD_FLAG_CLR_I , "Clear Flag Interrupts Disabled" }, // 2
+ {TEXT("CLD") , CmdFlagClear , CMD_FLAG_CLR_D , "Clear Flag Decimal (BCD)" }, // 3
+ {TEXT("CLB") , CmdFlagClear , CMD_FLAG_CLR_B , "CLear Flag Break" }, // 4 // Legacy
+ {TEXT("CLR") , CmdFlagClear , CMD_FLAG_CLR_R , "Clear Flag Reserved" }, // 5
+ {TEXT("CLV") , CmdFlagClear , CMD_FLAG_CLR_V , "Clear Flag Overflow" }, // 6
+ {TEXT("CLN") , CmdFlagClear , CMD_FLAG_CLR_N , "Clear Flag Negative (Sign)" }, // 7
-// ,{"FS" , CmdFlag , CMD_FLAG_SET , "Set specified Flag" }
- ,{"SE" , CmdFlag , CMD_FLAG_SET , "Set specified Flag" }
+// {TEXT("FS") , CmdFlag , CMD_FLAG_SET , "Set specified Flag" },
+ {TEXT("SE") , CmdFlag , CMD_FLAG_SET , "Set specified Flag" },
- ,{"SEC" , CmdFlagSet , CMD_FLAG_SET_C , "Set Flag Carry" } // 0
- ,{"SEZ" , CmdFlagSet , CMD_FLAG_SET_Z , "Set Flag Zero" } // 1
- ,{"SEI" , CmdFlagSet , CMD_FLAG_SET_I , "Set Flag Interrupts Disabled" } // 2
- ,{"SED" , CmdFlagSet , CMD_FLAG_SET_D , "Set Flag Decimal (BCD)" } // 3
- ,{"SEB" , CmdFlagSet , CMD_FLAG_SET_B , "Set Flag Break" } // 4 // Legacy
- ,{"SER" , CmdFlagSet , CMD_FLAG_SET_R , "Set Flag Reserved" } // 5
- ,{"SEV" , CmdFlagSet , CMD_FLAG_SET_V , "Set Flag Overflow" } // 6
- ,{"SEN" , CmdFlagSet , CMD_FLAG_SET_N , "Set Flag Negative" } // 7
+ {TEXT("SEC") , CmdFlagSet , CMD_FLAG_SET_C , "Set Flag Carry" }, // 0
+ {TEXT("SEZ") , CmdFlagSet , CMD_FLAG_SET_Z , "Set Flag Zero" }, // 1
+ {TEXT("SEI") , CmdFlagSet , CMD_FLAG_SET_I , "Set Flag Interrupts Disabled" }, // 2
+ {TEXT("SED") , CmdFlagSet , CMD_FLAG_SET_D , "Set Flag Decimal (BCD)" }, // 3
+ {TEXT("SEB") , CmdFlagSet , CMD_FLAG_SET_B , "Set Flag Break" }, // 4 // Legacy
+ {TEXT("SER") , CmdFlagSet , CMD_FLAG_SET_R , "Set Flag Reserved" }, // 5
+ {TEXT("SEV") , CmdFlagSet , CMD_FLAG_SET_V , "Set Flag Overflow" }, // 6
+ {TEXT("SEN") , CmdFlagSet , CMD_FLAG_SET_N , "Set Flag Negative" }, // 7
// Help
- ,{"?" , CmdHelpList , CMD_HELP_LIST , "List all available commands" }
- ,{"HELP" , CmdHelpSpecific , CMD_HELP_SPECIFIC , "Help on specific command" }
- ,{"VERSION" , CmdVersion , CMD_VERSION , "Displays version of emulator/debugger" }
- ,{"MOTD" , CmdMOTD , CMD_MOTD } // MOTD: Message Of The Day
+ {TEXT("?") , CmdHelpList , CMD_HELP_LIST , "List all available commands" },
+ {TEXT("HELP") , CmdHelpSpecific , CMD_HELP_SPECIFIC , "Help on specific command" },
+ {TEXT("VERSION") , CmdVersion , CMD_VERSION , "Displays version of emulator/debugger" },
+ {TEXT("MOTD") , CmdMOTD , CMD_MOTD }, // MOTD: Message Of The Day
// Memory
- ,{"MC" , CmdMemoryCompare , CMD_MEMORY_COMPARE }
+ {TEXT("MC") , CmdMemoryCompare , CMD_MEMORY_COMPARE },
- ,{"MD1" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 , "Hex dump in the mini memory area 1" }
- ,{"MD2" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_2 , "Hex dump in the mini memory area 2" }
+ {TEXT("MD1") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 , "Hex dump in the mini memory area 1" },
+ {TEXT("MD2") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_2 , "Hex dump in the mini memory area 2" },
- ,{"MA1" , CmdMemoryMiniDumpAscii , CMD_MEM_MINI_DUMP_ASCII_1 , "ASCII text in mini memory area 1" }
- ,{"MA2" , CmdMemoryMiniDumpAscii , CMD_MEM_MINI_DUMP_ASCII_2 , "ASCII text in mini memory area 2" }
- ,{"MT1" , CmdMemoryMiniDumpApple , CMD_MEM_MINI_DUMP_APPLE_1 , "Apple Text in mini memory area 1" }
- ,{"MT2" , CmdMemoryMiniDumpApple , CMD_MEM_MINI_DUMP_APPLE_2 , "Apple Text in mini memory area 2" }
-// {"ML1" , CmdMemoryMiniDumpLow , CMD_MEM_MINI_DUMP_TXT_LO_1 , "Text (Ctrl) in mini memory dump area 1" }
-// {"ML2" , CmdMemoryMiniDumpLow , CMD_MEM_MINI_DUMP_TXT_LO_2 , "Text (Ctrl) in mini memory dump area 2" }
-// {"MH1" , CmdMemoryMiniDumpHigh , CMD_MEM_MINI_DUMP_TXT_HI_1 , "Text (High) in mini memory dump area 1" }
-// {"MH2" , CmdMemoryMiniDumpHigh , CMD_MEM_MINI_DUMP_TXT_HI_2 , "Text (High) in mini memory dump area 2" }
+ {TEXT("MA1") , CmdMemoryMiniDumpAscii,CMD_MEM_MINI_DUMP_ASCII_1, "ASCII text in mini memory area 1" },
+ {TEXT("MA2") , CmdMemoryMiniDumpAscii,CMD_MEM_MINI_DUMP_ASCII_2, "ASCII text in mini memory area 2" },
+ {TEXT("MT1") , CmdMemoryMiniDumpApple,CMD_MEM_MINI_DUMP_APPLE_1, "Apple Text in mini memory area 1" },
+ {TEXT("MT2") , CmdMemoryMiniDumpApple,CMD_MEM_MINI_DUMP_APPLE_2, "Apple Text in mini memory area 2" },
+// {TEXT("ML1") , CmdMemoryMiniDumpLow , CMD_MEM_MINI_DUMP_TXT_LO_1, "Text (Ctrl) in mini memory dump area 1" },
+// {TEXT("ML2") , CmdMemoryMiniDumpLow , CMD_MEM_MINI_DUMP_TXT_LO_2, "Text (Ctrl) in mini memory dump area 2" },
+// {TEXT("MH1") , CmdMemoryMiniDumpHigh, CMD_MEM_MINI_DUMP_TXT_HI_1, "Text (High) in mini memory dump area 1" },
+// {TEXT("MH2") , CmdMemoryMiniDumpHigh, CMD_MEM_MINI_DUMP_TXT_HI_2, "Text (High) in mini memory dump area 2" },
- ,{"ME" , CmdMemoryEdit , CMD_MEMORY_EDIT , "Memory Editor - Not Implemented!" } // TODO: like Copy ][+ Sector Edit
- ,{"MEB" , CmdMemoryEnterByte , CMD_MEMORY_ENTER_BYTE , "Enter byte" }
- ,{"MEW" , CmdMemoryEnterWord , CMD_MEMORY_ENTER_WORD , "Enter word" }
- ,{"BLOAD" , CmdMemoryLoad , CMD_MEMORY_LOAD , "Load a region of memory" }
- ,{"M" , CmdMemoryMove , CMD_MEMORY_MOVE , "Memory move" }
- ,{"BSAVE" , CmdMemorySave , CMD_MEMORY_SAVE , "Save a region of memory" }
- ,{"S" , CmdMemorySearch , CMD_MEMORY_SEARCH , "Search memory for text / hex values" }
- ,{"@" ,_SearchMemoryDisplay , CMD_MEMORY_FIND_RESULTS , "Display search memory results" }
-// ,{"SA" , CmdMemorySearchAscii , CMD_MEMORY_SEARCH_ASCII , "Search ASCII text" }
-// ,{"ST" , CmdMemorySearchApple , CMD_MEMORY_SEARCH_APPLE , "Search Apple text (hi-bit)" }
- ,{"SH" , CmdMemorySearchHex , CMD_MEMORY_SEARCH_HEX , "Search memory for hex values" }
- ,{"F" , CmdMemoryFill , CMD_MEMORY_FILL , "Memory fill" }
+ {TEXT("ME") , CmdMemoryEdit , CMD_MEMORY_EDIT , "Memory Editor - Not Implemented!" }, // TODO: like Copy ][+ Sector Edit
+ {TEXT("MEB") , CmdMemoryEnterByte , CMD_MEMORY_ENTER_BYTE , "Enter byte" },
+ {TEXT("MEW") , CmdMemoryEnterWord , CMD_MEMORY_ENTER_WORD , "Enter word" },
+ {TEXT("BLOAD") , CmdMemoryLoad , CMD_MEMORY_LOAD , "Load a region of memory" },
+ {TEXT("M") , CmdMemoryMove , CMD_MEMORY_MOVE , "Memory move" },
+ {TEXT("BSAVE") , CmdMemorySave , CMD_MEMORY_SAVE , "Save a region of memory" },
+ {TEXT("S") , CmdMemorySearch , CMD_MEMORY_SEARCH , "Search memory for text / hex values" },
+ {TEXT("@") ,_SearchMemoryDisplay , CMD_MEMORY_FIND_RESULTS , "Display search memory results" },
+// {TEXT("SA") , CmdMemorySearchAscii, CMD_MEMORY_SEARCH_ASCII , "Search ASCII text" },
+// {TEXT("ST") , CmdMemorySearchApple , CMD_MEMORY_SEARCH_APPLE , "Search Apple text (hi-bit)" },
+ {TEXT("SH") , CmdMemorySearchHex , CMD_MEMORY_SEARCH_HEX , "Search memory for hex values" },
+ {TEXT("F") , CmdMemoryFill , CMD_MEMORY_FILL , "Memory fill" },
- ,{"NTSC" , CmdNTSC , CMD_NTSC , "Save/Load the NTSC palette" }
- ,{"TSAVE" , CmdTextSave , CMD_TEXT_SAVE , "Save text screen" }
+ {TEXT("NTSC") , CmdNTSC , CMD_NTSC , "Save/Load the NTSC palette" },
+ {TEXT("TSAVE") , CmdTextSave , CMD_TEXT_SAVE , "Save text screen" },
// Output / Scripts
- ,{"CALC" , CmdOutputCalc , CMD_OUTPUT_CALC , "Display mini calc result" }
- ,{"ECHO" , CmdOutputEcho , CMD_OUTPUT_ECHO , "Echo string to console" } // or toggle command echoing"
- ,{"PRINT" , CmdOutputPrint , CMD_OUTPUT_PRINT , "Display string and/or hex values" }
- ,{"PRINTF" , CmdOutputPrintf , CMD_OUTPUT_PRINTF , "Display formatted string" }
- ,{"RUN" , CmdOutputRun , CMD_OUTPUT_RUN , "Run script file of debugger commands" }
+ {TEXT("CALC") , CmdOutputCalc , CMD_OUTPUT_CALC , "Display mini calc result" },
+ {TEXT("ECHO") , CmdOutputEcho , CMD_OUTPUT_ECHO , "Echo string to console" }, // or toggle command echoing"
+ {TEXT("PRINT") , CmdOutputPrint , CMD_OUTPUT_PRINT , "Display string and/or hex values" },
+ {TEXT("PRINTF") , CmdOutputPrintf , CMD_OUTPUT_PRINTF , "Display formatted string" },
+ {TEXT("RUN") , CmdOutputRun , CMD_OUTPUT_RUN , "Run script file of debugger commands" },
// Source Level Debugging
- ,{"SOURCE" , CmdSource , CMD_SOURCE , "Starts/Stops source level debugging" }
- ,{"SYNC" , CmdSync , CMD_SYNC , "Syncs the cursor to the source file" }
+ {TEXT("SOURCE") , CmdSource , CMD_SOURCE , "Starts/Stops source level debugging" },
+ {TEXT("SYNC") , CmdSync , CMD_SYNC , "Syncs the cursor to the source file" },
// Symbols
- ,{"SYM" , CmdSymbols , CMD_SYMBOLS_LOOKUP , "Lookup symbol or address, or define symbol" }
+ {TEXT("SYM") , CmdSymbols , CMD_SYMBOLS_LOOKUP , "Lookup symbol or address, or define symbol" },
- ,{"SYMMAIN" , CmdSymbolsCommand , CMD_SYMBOLS_ROM , "Main/ROM symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMBASIC" , CmdSymbolsCommand , CMD_SYMBOLS_APPLESOFT , "Applesoft symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMASM" , CmdSymbolsCommand , CMD_SYMBOLS_ASSEMBLY , "Assembly symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMUSER" , CmdSymbolsCommand , CMD_SYMBOLS_USER_1 , "First user symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMUSER2" , CmdSymbolsCommand , CMD_SYMBOLS_USER_2 , "Second User symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMSRC" , CmdSymbolsCommand , CMD_SYMBOLS_SRC_1 , "First Source symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMSRC2" , CmdSymbolsCommand , CMD_SYMBOLS_SRC_2 , "Second Source symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMDOS33" , CmdSymbolsCommand , CMD_SYMBOLS_DOS33 , "DOS 3.3 symbol table lookup/menu" } // CLEAR,LOAD,SAVE
- ,{"SYMPRODOS" , CmdSymbolsCommand , CMD_SYMBOLS_PRODOS , "ProDOS symbol table lookup/menu" } // CLEAR,LOAD,SAVE
+ {"SYMMAIN" , CmdSymbolsCommand , CMD_SYMBOLS_ROM , "Main/ROM symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMBASIC" , CmdSymbolsCommand , CMD_SYMBOLS_APPLESOFT , "Applesoft symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMASM" , CmdSymbolsCommand , CMD_SYMBOLS_ASSEMBLY , "Assembly symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMUSER" , CmdSymbolsCommand , CMD_SYMBOLS_USER_1 , "First user symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMUSER2" , CmdSymbolsCommand , CMD_SYMBOLS_USER_2 , "Second User symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMSRC" , CmdSymbolsCommand , CMD_SYMBOLS_SRC_1 , "First Source symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMSRC2" , CmdSymbolsCommand , CMD_SYMBOLS_SRC_2 , "Second Source symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMDOS33" , CmdSymbolsCommand , CMD_SYMBOLS_DOS33 , "DOS 3.3 symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
+ {"SYMPRODOS" , CmdSymbolsCommand , CMD_SYMBOLS_PRODOS , "ProDOS symbol table lookup/menu" }, // CLEAR,LOAD,SAVE
-// ,{"SYMCLEAR" , CmdSymbolsClear , CMD_SYMBOLS_CLEAR } // can't use SC = SetCarry
- ,{"SYMINFO" , CmdSymbolsInfo , CMD_SYMBOLS_INFO , "Display summary of symbols" }
- ,{"SYMLIST" , CmdSymbolsList , CMD_SYMBOLS_LIST , "Lookup symbol in main/user/src tables" } // 'symbolname', can't use param '*'
+// {TEXT("SYMCLEAR") , CmdSymbolsClear , CMD_SYMBOLS_CLEAR }, // can't use SC = SetCarry
+ {TEXT("SYMINFO") , CmdSymbolsInfo , CMD_SYMBOLS_INFO , "Display summary of symbols" },
+ {TEXT("SYMLIST") , CmdSymbolsList , CMD_SYMBOLS_LIST , "Lookup symbol in main/user/src tables" }, // 'symbolname', can't use param '*'
// Variables
-// ,{"CLEAR" , CmdVarsClear , CMD_VARIABLES_CLEAR }
-// ,{"VAR" , CmdVarsDefine , CMD_VARIABLES_DEFINE }
-// ,{"INT8" , CmdVarsDefineInt8 , CMD_VARIABLES_DEFINE_INT8 }
-// ,{"INT16" , CmdVarsDefineInt16 , CMD_VARIABLES_DEFINE_INT16 }
-// ,{"VARS" , CmdVarsList , CMD_VARIABLES_LIST }
-// ,{"VARSLOAD" , CmdVarsLoad , CMD_VARIABLES_LOAD }
-// ,{"VARSSAVE" , CmdVarsSave , CMD_VARIABLES_SAVE }
-// ,{"SET" , CmdVarsSet , CMD_VARIABLES_SET }
+// {TEXT("CLEAR") , CmdVarsClear , CMD_VARIABLES_CLEAR },
+// {TEXT("VAR") , CmdVarsDefine , CMD_VARIABLES_DEFINE },
+// {TEXT("INT8") , CmdVarsDefineInt8 , CMD_VARIABLES_DEFINE_INT8},
+// {TEXT("INT16") , CmdVarsDefineInt16 , CMD_VARIABLES_DEFINE_INT16},
+// {TEXT("VARS") , CmdVarsList , CMD_VARIABLES_LIST },
+// {TEXT("VARSLOAD") , CmdVarsLoad , CMD_VARIABLES_LOAD },
+// {TEXT("VARSSAVE") , CmdVarsSave , CMD_VARIABLES_SAVE },
+// {TEXT("SET") , CmdVarsSet , CMD_VARIABLES_SET },
// View
- ,{"TEXT" , CmdViewOutput_Text4X , CMD_VIEW_TEXT4X , "View Text screen (current page)" }
- ,{"TEXT1" , CmdViewOutput_Text41 , CMD_VIEW_TEXT41 , "View Text screen Page 1" }
- ,{"TEXT2" , CmdViewOutput_Text42 , CMD_VIEW_TEXT42 , "View Text screen Page 2" }
- ,{"TEXT80" , CmdViewOutput_Text8X , CMD_VIEW_TEXT8X , "View 80-col Text screen (current page)" }
- ,{"TEXT81" , CmdViewOutput_Text81 , CMD_VIEW_TEXT81 , "View 80-col Text screen Page 1" }
- ,{"TEXT82" , CmdViewOutput_Text82 , CMD_VIEW_TEXT82 , "View 80-col Text screen Page 2" }
- ,{"GR" , CmdViewOutput_GRX , CMD_VIEW_GRX , "View Lo-Res screen (current page)" }
- ,{"GR1" , CmdViewOutput_GR1 , CMD_VIEW_GR1 , "View Lo-Res screen Page 1" }
- ,{"GR2" , CmdViewOutput_GR2 , CMD_VIEW_GR2 , "View Lo-Res screen Page 2" }
- ,{"DGR" , CmdViewOutput_DGRX , CMD_VIEW_DGRX , "View Double lo-res (current page)" }
- ,{"DGR1" , CmdViewOutput_DGR1 , CMD_VIEW_DGR1 , "View Double lo-res Page 1" }
- ,{"DGR2" , CmdViewOutput_DGR2 , CMD_VIEW_DGR2 , "View Double lo-res Page 2" }
- ,{"HGR" , CmdViewOutput_HGRX , CMD_VIEW_HGRX , "View Hi-res (current page)" }
- ,{"HGR1" , CmdViewOutput_HGR1 , CMD_VIEW_HGR1 , "View Hi-res Page 1" }
- ,{"HGR2" , CmdViewOutput_HGR2 , CMD_VIEW_HGR2 , "View Hi-res Page 2" }
- ,{"DHGR" , CmdViewOutput_DHGRX , CMD_VIEW_DHGRX , "View Double Hi-res (current page)" }
- ,{"DHGR1" , CmdViewOutput_DHGR1 , CMD_VIEW_DHGR1 , "View Double Hi-res Page 1" }
- ,{"DHGR2" , CmdViewOutput_DHGR2 , CMD_VIEW_DHGR2 , "View Double Hi-res Page 2" }
+ {TEXT("TEXT") , CmdViewOutput_Text4X , CMD_VIEW_TEXT4X, "View Text screen (current page)" },
+ {TEXT("TEXT1") , CmdViewOutput_Text41 , CMD_VIEW_TEXT41, "View Text screen Page 1" },
+ {TEXT("TEXT2") , CmdViewOutput_Text42 , CMD_VIEW_TEXT42, "View Text screen Page 2" },
+ {TEXT("TEXT80") , CmdViewOutput_Text8X , CMD_VIEW_TEXT8X, "View 80-col Text screen (current page)" },
+ {TEXT("TEXT81") , CmdViewOutput_Text81 , CMD_VIEW_TEXT81, "View 80-col Text screen Page 1" },
+ {TEXT("TEXT82") , CmdViewOutput_Text82 , CMD_VIEW_TEXT82, "View 80-col Text screen Page 2" },
+ {TEXT("GR") , CmdViewOutput_GRX , CMD_VIEW_GRX , "View Lo-Res screen (current page)" },
+ {TEXT("GR1") , CmdViewOutput_GR1 , CMD_VIEW_GR1 , "View Lo-Res screen Page 1" },
+ {TEXT("GR2") , CmdViewOutput_GR2 , CMD_VIEW_GR2 , "View Lo-Res screen Page 2" },
+ {TEXT("DGR") , CmdViewOutput_DGRX , CMD_VIEW_DGRX , "View Double lo-res (current page)" },
+ {TEXT("DGR1") , CmdViewOutput_DGR1 , CMD_VIEW_DGR1 , "View Double lo-res Page 1" },
+ {TEXT("DGR2") , CmdViewOutput_DGR2 , CMD_VIEW_DGR2 , "View Double lo-res Page 2" },
+ {TEXT("HGR") , CmdViewOutput_HGRX , CMD_VIEW_HGRX , "View Hi-res (current page)" },
+ {TEXT("HGR1") , CmdViewOutput_HGR1 , CMD_VIEW_HGR1 , "View Hi-res Page 1" },
+ {TEXT("HGR2") , CmdViewOutput_HGR2 , CMD_VIEW_HGR2 , "View Hi-res Page 2" },
+ {TEXT("DHGR") , CmdViewOutput_DHGRX , CMD_VIEW_DHGRX , "View Double Hi-res (current page)" },
+ {TEXT("DHGR1") , CmdViewOutput_DHGR1 , CMD_VIEW_DHGR1 , "View Double Hi-res Page 1" },
+ {TEXT("DHGR2") , CmdViewOutput_DHGR2 , CMD_VIEW_DHGR2 , "View Double Hi-res Page 2" },
// Watch
- ,{"W" , CmdWatch , CMD_WATCH , "Alias for WA (Watch Add)" }
- ,{"WA" , CmdWatchAdd , CMD_WATCH_ADD , "Add/Update address or symbol to watch" }
- ,{"WC" , CmdWatchClear , CMD_WATCH_CLEAR , "Clear (remove) watch" }
- ,{"WD" , CmdWatchDisable , CMD_WATCH_DISABLE , "Disable specific watch - listed not active" }
- ,{"WE" , CmdWatchEnable , CMD_WATCH_ENABLE , "(Re)Enable disabled watch" }
- ,{"WL" , CmdWatchList , CMD_WATCH_LIST , "List all watches" }
-// ,{"WLOAD" , CmdWatchLoad , CMD_WATCH_LOAD , "Load Watches" } // Cant use as param to W
- ,{"WSAVE" , CmdWatchSave , CMD_WATCH_SAVE , "Save Watches" } // due to symbol look-up
+ {TEXT("W") , CmdWatch , CMD_WATCH , "Alias for WA (Watch Add)" },
+ {TEXT("WA") , CmdWatchAdd , CMD_WATCH_ADD , "Add/Update address or symbol to watch" },
+ {TEXT("WC") , CmdWatchClear , CMD_WATCH_CLEAR , "Clear (remove) watch" },
+ {TEXT("WD") , CmdWatchDisable , CMD_WATCH_DISABLE , "Disable specific watch - it is still in the list, just not active" },
+ {TEXT("WE") , CmdWatchEnable , CMD_WATCH_ENABLE , "(Re)Enable disabled watch" },
+ {TEXT("WL") , CmdWatchList , CMD_WATCH_LIST , "List all watches" },
+// {TEXT("WLOAD") , CmdWatchLoad , CMD_WATCH_LOAD , "Load Watches" }, // Cant use as param to W
+ {TEXT("WSAVE") , CmdWatchSave , CMD_WATCH_SAVE , "Save Watches" }, // due to symbol look-up
// Window
- ,{"WIN" , CmdWindow , CMD_WINDOW , "Show specified debugger window" }
+ {TEXT("WIN") , CmdWindow , CMD_WINDOW , "Show specified debugger window" },
// CODE 0, CODE 1, CODE 2 ... ???
- ,{"CODE" , CmdWindowViewCode , CMD_WINDOW_CODE , "Switch to full code window" } // Can't use WC = WatchClear
- ,{"CODE1" , CmdWindowShowCode1 , CMD_WINDOW_CODE_1 , "Show code on top split window" }
- ,{"CODE2" , CmdWindowShowCode2 , CMD_WINDOW_CODE_2 , "Show code on bottom split window" }
- ,{"CONSOLE" , CmdWindowViewConsole , CMD_WINDOW_CONSOLE , "Switch to full console window" }
- ,{"DATA" , CmdWindowViewData , CMD_WINDOW_DATA , "Switch to full data window" }
- ,{"DATA1" , CmdWindowShowData1 , CMD_WINDOW_DATA_1 , "Show data on top split window" }
- ,{"DATA2" , CmdWindowShowData2 , CMD_WINDOW_DATA_2 , "Show data on bottom split window" }
- ,{"SOURCE1" , CmdWindowShowSource1 , CMD_WINDOW_SOURCE_1 , "Show source on top split screen" }
- ,{"SOURCE2" , CmdWindowShowSource2 , CMD_WINDOW_SOURCE_2 , "Show source on bottom split screen" }
+ {TEXT("CODE") , CmdWindowViewCode , CMD_WINDOW_CODE , "Switch to full code window" }, // Can't use WC = WatchClear
+ {TEXT("CODE1") , CmdWindowShowCode1 , CMD_WINDOW_CODE_1 , "Show code on top split window" },
+ {TEXT("CODE2") , CmdWindowShowCode2 , CMD_WINDOW_CODE_2 , "Show code on bottom split window" },
+ {TEXT("CONSOLE") , CmdWindowViewConsole , CMD_WINDOW_CONSOLE , "Switch to full console window" },
+ {TEXT("DATA") , CmdWindowViewData , CMD_WINDOW_DATA , "Switch to full data window" },
+ {TEXT("DATA1") , CmdWindowShowData1 , CMD_WINDOW_DATA_1 , "Show data on top split window" },
+ {TEXT("DATA2") , CmdWindowShowData2 , CMD_WINDOW_DATA_2 , "Show data on bottom split window" },
+ {TEXT("SOURCE1") , CmdWindowShowSource1 , CMD_WINDOW_SOURCE_1, "Show source on top split screen" },
+ {TEXT("SOURCE2") , CmdWindowShowSource2 , CMD_WINDOW_SOURCE_2, "Show source on bottom split screen" },
- ,{"\\" , CmdWindowViewOutput , CMD_WINDOW_OUTPUT , "Display Apple output until key pressed" }
-// ,{"INFO" , CmdToggleInfoPanel , CMD_WINDOW_TOGGLE }
-// ,{"WINSOURCE" , CmdWindowShowSource , CMD_WINDOW_SOURCE }
-// ,{"ZEROPAGE" , CmdWindowShowZeropage , CMD_WINDOW_ZEROPAGE }
+ {TEXT("\\") , CmdWindowViewOutput , CMD_WINDOW_OUTPUT , "Display Apple output until key pressed" },
+// {TEXT("INFO") , CmdToggleInfoPanel , CMD_WINDOW_TOGGLE },
+// {TEXT("WINSOURCE") , CmdWindowShowSource , CMD_WINDOW_SOURCE },
+// {TEXT("ZEROPAGE") , CmdWindowShowZeropage, CMD_WINDOW_ZEROPAGE },
// Zero Page
- ,{"ZP" , CmdZeroPage , CMD_ZEROPAGE_POINTER , "Alias for ZPA (Zero Page Add)" }
- ,{"ZP0" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_0 , "Set/Update/Remove ZP watch 0 " }
- ,{"ZP1" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_1 , "Set/Update/Remove ZP watch 1" }
- ,{"ZP2" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_2 , "Set/Update/Remove ZP watch 2" }
- ,{"ZP3" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_3 , "Set/Update/Remove ZP watch 3" }
- ,{"ZP4" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_4 , "Set/Update/Remove ZP watch 4" }
- ,{"ZP5" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_5 , "Set/Update/Remove ZP watch 5 " }
- ,{"ZP6" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_6 , "Set/Update/Remove ZP watch 6" }
- ,{"ZP7" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_7 , "Set/Update/Remove ZP watch 7" }
- ,{"ZPA" , CmdZeroPageAdd , CMD_ZEROPAGE_POINTER_ADD , "Add/Update address to zero page pointer" }
- ,{"ZPC" , CmdZeroPageClear , CMD_ZEROPAGE_POINTER_CLEAR , "Clear (remove) zero page pointer" }
- ,{"ZPD" , CmdZeroPageDisable , CMD_ZEROPAGE_POINTER_DISABLE, "Disable zero page pointer" }
- ,{"ZPE" , CmdZeroPageEnable , CMD_ZEROPAGE_POINTER_ENABLE , "(Re)Enable disabled zero page pointer" }
- ,{"ZPL" , CmdZeroPageList , CMD_ZEROPAGE_POINTER_LIST , "List all zero page pointers" }
-// ,{"ZPLOAD" , CmdZeroPageLoad , CMD_ZEROPAGE_POINTER_LOAD , "Load zero page pointers" } // Cant use as param to ZP
- ,{"ZPSAVE" , CmdZeroPageSave , CMD_ZEROPAGE_POINTER_SAVE , "Save zero page pointers" } // due to symbol look-up
+ {TEXT("ZP") , CmdZeroPage , CMD_ZEROPAGE_POINTER , "Alias for ZPA (Zero Page Add)" },
+ {TEXT("ZP0") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_0 , "Set/Update/Remove ZP watch 0 " },
+ {TEXT("ZP1") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_1 , "Set/Update/Remove ZP watch 1" },
+ {TEXT("ZP2") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_2 , "Set/Update/Remove ZP watch 2" },
+ {TEXT("ZP3") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_3 , "Set/Update/Remove ZP watch 3" },
+ {TEXT("ZP4") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_4 , "Set/Update/Remove ZP watch 4" },
+ {TEXT("ZP5") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_5 , "Set/Update/Remove ZP watch 5 " },
+ {TEXT("ZP6") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_6 , "Set/Update/Remove ZP watch 6" },
+ {TEXT("ZP7") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_7 , "Set/Update/Remove ZP watch 7" },
+ {TEXT("ZPA") , CmdZeroPageAdd , CMD_ZEROPAGE_POINTER_ADD , "Add/Update address to zero page pointer"},
+ {TEXT("ZPC") , CmdZeroPageClear , CMD_ZEROPAGE_POINTER_CLEAR , "Clear (remove) zero page pointer" },
+ {TEXT("ZPD") , CmdZeroPageDisable , CMD_ZEROPAGE_POINTER_DISABLE,"Disable zero page pointer - it is still in the list, just not active" },
+ {TEXT("ZPE") , CmdZeroPageEnable , CMD_ZEROPAGE_POINTER_ENABLE, "(Re)Enable disabled zero page pointer" },
+ {TEXT("ZPL") , CmdZeroPageList , CMD_ZEROPAGE_POINTER_LIST , "List all zero page pointers" },
+// {TEXT("ZPLOAD") , CmdZeroPageLoad , CMD_ZEROPAGE_POINTER_LOAD , "Load zero page pointers" }, // Cant use as param to ZP
+ {TEXT("ZPSAVE") , CmdZeroPageSave , CMD_ZEROPAGE_POINTER_SAVE , "Save zero page pointers" }, // due to symbol look-up
-// {"TIMEDEMO"),CmdTimeDemo, CMD_TIMEDEMO }, // CmdBenchmarkStart(), CmdBenchmarkStop()
-// {"WC"),CmdShowCodeWindow}, // Can't use since WatchClear
-// {"WD"),CmdShowDataWindow}, //
+// {TEXT("TIMEDEMO"),CmdTimeDemo, CMD_TIMEDEMO }, // CmdBenchmarkStart(), CmdBenchmarkStop()
+// {TEXT("WC"),CmdShowCodeWindow}, // Can't use since WatchClear
+// {TEXT("WD"),CmdShowDataWindow}, //
// Internal Consistency Check
- ,{ DEBUGGER__COMMANDS_VERIFY_TXT__, NULL, NUM_COMMANDS }
+ { DEBUGGER__COMMANDS_VERIFY_TXT__, NULL, NUM_COMMANDS },
// Aliasies - Can be in any order
- ,{"->" , NULL , CMD_CURSOR_JUMP_PC }
- ,{"Ctrl ->" , NULL , CMD_CURSOR_SET_PC }
- ,{"Shift ->" , NULL , CMD_CURSOR_JUMP_PC } // at top
- ,{"INPUT" , CmdIn , CMD_IN }
+ {TEXT("->") , NULL , CMD_CURSOR_JUMP_PC },
+ {TEXT("Ctrl ->" ) , NULL , CMD_CURSOR_SET_PC },
+ {TEXT("Shift ->") , NULL , CMD_CURSOR_JUMP_PC }, // at top
+ {TEXT("INPUT") , CmdIn , CMD_IN },
// Data
// Flags - Clear
- ,{"RC" , CmdFlagClear , CMD_FLAG_CLR_C , "Clear Flag Carry" } // 0 // Legacy
- ,{"RZ" , CmdFlagClear , CMD_FLAG_CLR_Z , "Clear Flag Zero" } // 1
- ,{"RI" , CmdFlagClear , CMD_FLAG_CLR_I , "Clear Flag Interrupts Disabled" } // 2
- ,{"RD" , CmdFlagClear , CMD_FLAG_CLR_D , "Clear Flag Decimal (BCD)" } // 3
- ,{"RB" , CmdFlagClear , CMD_FLAG_CLR_B , "CLear Flag Break" } // 4 // Legacy
- ,{"RR" , CmdFlagClear , CMD_FLAG_CLR_R , "Clear Flag Reserved" } // 5
- ,{"RV" , CmdFlagClear , CMD_FLAG_CLR_V , "Clear Flag Overflow" } // 6
- ,{"RN" , CmdFlagClear , CMD_FLAG_CLR_N , "Clear Flag Negative (Sign)" } // 7
+ {TEXT("RC") , CmdFlagClear , CMD_FLAG_CLR_C , "Clear Flag Carry" }, // 0 // Legacy
+ {TEXT("RZ") , CmdFlagClear , CMD_FLAG_CLR_Z , "Clear Flag Zero" }, // 1
+ {TEXT("RI") , CmdFlagClear , CMD_FLAG_CLR_I , "Clear Flag Interrupts Disabled" }, // 2
+ {TEXT("RD") , CmdFlagClear , CMD_FLAG_CLR_D , "Clear Flag Decimal (BCD)" }, // 3
+ {TEXT("RB") , CmdFlagClear , CMD_FLAG_CLR_B , "CLear Flag Break" }, // 4 // Legacy
+ {TEXT("RR") , CmdFlagClear , CMD_FLAG_CLR_R , "Clear Flag Reserved" }, // 5
+ {TEXT("RV") , CmdFlagClear , CMD_FLAG_CLR_V , "Clear Flag Overflow" }, // 6
+ {TEXT("RN") , CmdFlagClear , CMD_FLAG_CLR_N , "Clear Flag Negative (Sign)" }, // 7
// Flags - Set
- ,{"SC" , CmdFlagSet , CMD_FLAG_SET_C , "Set Flag Carry" } // 0
- ,{"SZ" , CmdFlagSet , CMD_FLAG_SET_Z , "Set Flag Zero" } // 1
- ,{"SI" , CmdFlagSet , CMD_FLAG_SET_I , "Set Flag Interrupts Disabled" } // 2
- ,{"SD" , CmdFlagSet , CMD_FLAG_SET_D , "Set Flag Decimal (BCD)" } // 3
- ,{"SB" , CmdFlagSet , CMD_FLAG_SET_B , "CLear Flag Break" } // 4 // Legacy
- ,{"SR" , CmdFlagSet , CMD_FLAG_SET_R , "Clear Flag Reserved" } // 5
- ,{"SV" , CmdFlagSet , CMD_FLAG_SET_V , "Clear Flag Overflow" } // 6
- ,{"SN" , CmdFlagSet , CMD_FLAG_SET_N , "Clear Flag Negative" } // 7
+ {TEXT("SC") , CmdFlagSet , CMD_FLAG_SET_C , "Set Flag Carry" }, // 0
+ {TEXT("SZ") , CmdFlagSet , CMD_FLAG_SET_Z , "Set Flag Zero" }, // 1
+ {TEXT("SI") , CmdFlagSet , CMD_FLAG_SET_I , "Set Flag Interrupts Disabled" }, // 2
+ {TEXT("SD") , CmdFlagSet , CMD_FLAG_SET_D , "Set Flag Decimal (BCD)" }, // 3
+ {TEXT("SB") , CmdFlagSet , CMD_FLAG_SET_B , "CLear Flag Break" }, // 4 // Legacy
+ {TEXT("SR") , CmdFlagSet , CMD_FLAG_SET_R , "Clear Flag Reserved" }, // 5
+ {TEXT("SV") , CmdFlagSet , CMD_FLAG_SET_V , "Clear Flag Overflow" }, // 6
+ {TEXT("SN") , CmdFlagSet , CMD_FLAG_SET_N , "Clear Flag Negative" }, // 7
// Memory
- ,{"D" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 , "Hex dump in the mini memory area 1" } // FIXME: Must also work in DATA screen
- ,{"M1" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 } // alias
- ,{"M2" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_2 } // alias
+ {TEXT("D") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 , "Hex dump in the mini memory area 1" }, // FIXME: Must also work in DATA screen
+ {TEXT("M1") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 }, // alias
+ {TEXT("M2") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_2 }, // alias
- ,{"ME8" , CmdMemoryEnterByte , CMD_MEMORY_ENTER_BYTE } // changed from EB -- bugfix: EB:## ##
- ,{"ME16" , CmdMemoryEnterWord , CMD_MEMORY_ENTER_WORD }
- ,{"MM" , CmdMemoryMove , CMD_MEMORY_MOVE }
- ,{"MS" , CmdMemorySearch , CMD_MEMORY_SEARCH } // CmdMemorySearch
- ,{"P0" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_0 }
- ,{"P1" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_1 }
- ,{"P2" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_2 }
- ,{"P3" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_3 }
- ,{"P4" , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_4 }
- ,{"REGISTER" , CmdRegisterSet , CMD_REGISTER_SET }
-// ,{"RET" , CmdStackReturn , CMD_STACK_RETURN }
- ,{"TRACE" , CmdTrace , CMD_TRACE }
+ {TEXT("ME8") , CmdMemoryEnterByte , CMD_MEMORY_ENTER_BYTE }, // changed from EB -- bugfix: EB:## ##
+ {TEXT("ME16") , CmdMemoryEnterWord , CMD_MEMORY_ENTER_WORD },
+ {TEXT("MM") , CmdMemoryMove , CMD_MEMORY_MOVE },
+ {TEXT("MS") , CmdMemorySearch , CMD_MEMORY_SEARCH }, // CmdMemorySearch
+ {TEXT("P0") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_0 },
+ {TEXT("P1") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_1 },
+ {TEXT("P2") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_2 },
+ {TEXT("P3") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_3 },
+ {TEXT("P4") , CmdZeroPagePointer , CMD_ZEROPAGE_POINTER_4 },
+ {TEXT("REGISTER") , CmdRegisterSet , CMD_REGISTER_SET },
+// {TEXT("RET") , CmdStackReturn , CMD_STACK_RETURN },
+ {TEXT("TRACE") , CmdTrace , CMD_TRACE },
-// ,{"SYMBOLS" , CmdSymbols , CMD_SYMBOLS_LOOKUP , "Return " }
-// ,{"SYMBOLS1" , CmdSymbolsInfo , CMD_SYMBOLS_1 }
-// ,{"SYMBOLS2" , CmdSymbolsInfo , CMD_SYMBOLS_2 }
-// ,{"SYM0" , CmdSymbolsInfo , CMD_SYMBOLS_ROM }
-// ,{"SYM1" , CmdSymbolsInfo , CMD_SYMBOLS_APPLESOFT }
-// ,{"SYM2" , CmdSymbolsInfo , CMD_SYMBOLS_ASSEMBLY }
-// ,{"SYM3" , CmdSymbolsInfo , CMD_SYMBOLS_USER_1 }
-// ,{"SYM4" , CmdSymbolsInfo , CMD_SYMBOLS_USER_2 }
-// ,{"SYM5" , CmdSymbolsInfo , CMD_SYMBOLS_SRC_1 }
-// ,{"SYM6" , CmdSymbolsInfo , CMD_SYMBOLS_SRC_2 }
- ,{"SYMDOS" , CmdSymbolsCommand , CMD_SYMBOLS_DOS33 }
- ,{"SYMPRO" , CmdSymbolsCommand , CMD_SYMBOLS_PRODOS }
+// {TEXT("SYMBOLS") , CmdSymbols , CMD_SYMBOLS_LOOKUP , "Return " },
+// {TEXT("SYMBOLS1") , CmdSymbolsInfo , CMD_SYMBOLS_1 },
+// {TEXT("SYMBOLS2") , CmdSymbolsInfo , CMD_SYMBOLS_2 },
+// {"SYM0" , CmdSymbolsInfo , CMD_SYMBOLS_ROM },
+// {"SYM1" , CmdSymbolsInfo , CMD_SYMBOLS_APPLESOFT },
+// {"SYM2" , CmdSymbolsInfo , CMD_SYMBOLS_ASSEMBLY },
+// {"SYM3" , CmdSymbolsInfo , CMD_SYMBOLS_USER_1 },
+// {"SYM4" , CmdSymbolsInfo , CMD_SYMBOLS_USER_2 },
+// {"SYM5" , CmdSymbolsInfo , CMD_SYMBOLS_SRC_1 },
+// {"SYM6" , CmdSymbolsInfo , CMD_SYMBOLS_SRC_2 },
+ {"SYMDOS" , CmdSymbolsCommand , CMD_SYMBOLS_DOS33 },
+ {"SYMPRO" , CmdSymbolsCommand , CMD_SYMBOLS_PRODOS },
- ,{"TEXT40" , CmdViewOutput_Text4X , CMD_VIEW_TEXT4X }
- ,{"TEXT41" , CmdViewOutput_Text41 , CMD_VIEW_TEXT41 }
- ,{"TEXT42" , CmdViewOutput_Text42 , CMD_VIEW_TEXT42 }
+ {TEXT("TEXT40") , CmdViewOutput_Text4X , CMD_VIEW_TEXT4X },
+ {TEXT("TEXT41") , CmdViewOutput_Text41 , CMD_VIEW_TEXT41 },
+ {TEXT("TEXT42") , CmdViewOutput_Text42 , CMD_VIEW_TEXT42 },
-// ,{"WATCH" , CmdWatchAdd , CMD_WATCH_ADD }
- ,{"WINDOW" , CmdWindow , CMD_WINDOW }
-// ,{"W?" , CmdWatchAdd , CMD_WATCH_ADD }
- ,{"ZAP" , CmdNOP , CMD_NOP }
+// {TEXT("WATCH") , CmdWatchAdd , CMD_WATCH_ADD },
+ {TEXT("WINDOW") , CmdWindow , CMD_WINDOW },
+// {TEXT("W?") , CmdWatchAdd , CMD_WATCH_ADD },
+ {TEXT("ZAP") , CmdNOP , CMD_NOP },
// DEPRECATED -- Probably should be removed in a future version
- ,{"BENCH" , CmdBenchmarkStart , CMD_BENCHMARK } // already hae BENCHMARK
- ,{"EXITBENCH" , NULL , CMD_BENCHMARK } // 2.8.03 was incorrectly alias with 'E' Bug #246. // CmdBenchmarkStop
- ,{"MDB" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 } // MemoryDumpByte // Did anyone actually use this??
-// ,{"MEMORY" , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 } // MemoryDumpByte // Did anyone actually use this??
+ {TEXT("BENCH") , CmdBenchmarkStart , CMD_BENCHMARK },
+ {TEXT("EXITBENCH") , NULL , CMD_BENCHMARK }, // 2.8.03 was incorrectly alias with 'E' Bug #246. // CmdBenchmarkStop
+ {TEXT("MDB") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 }, // MemoryDumpByte // Did anyone actually use this??
+// {TEXT("MEMORY") , CmdMemoryMiniDumpHex , CMD_MEM_MINI_DUMP_HEX_1 }, // MemoryDumpByte // Did anyone actually use this??
};
const int NUM_COMMANDS_WITH_ALIASES = sizeof(g_aCommands) / sizeof (Command_t); // Determined at compile-time ;-)
@@ -391,114 +391,113 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
Command_t g_aParameters[] =
{
// Breakpoint
- {"<=" , NULL, PARAM_BP_LESS_EQUAL }
- ,{"<" , NULL, PARAM_BP_LESS_THAN }
- ,{"=" , NULL, PARAM_BP_EQUAL }
- ,{"!=" , NULL, PARAM_BP_NOT_EQUAL }
- ,{"!" , NULL, PARAM_BP_NOT_EQUAL_1 }
- ,{">" , NULL, PARAM_BP_GREATER_THAN }
- ,{">=" , NULL, PARAM_BP_GREATER_EQUAL }
- ,{"R" , NULL, PARAM_BP_READ }
- ,{"?" , NULL, PARAM_BP_READ }
- ,{"W" , NULL, PARAM_BP_WRITE }
- ,{"@" , NULL, PARAM_BP_WRITE }
- ,{"*" , NULL, PARAM_BP_READ_WRITE }
+ {TEXT("<=") , NULL, PARAM_BP_LESS_EQUAL },
+ {TEXT("<" ) , NULL, PARAM_BP_LESS_THAN },
+ {TEXT("=" ) , NULL, PARAM_BP_EQUAL },
+ {TEXT("!=") , NULL, PARAM_BP_NOT_EQUAL },
+ {TEXT("!" ) , NULL, PARAM_BP_NOT_EQUAL_1 },
+ {TEXT(">" ) , NULL, PARAM_BP_GREATER_THAN },
+ {TEXT(">=") , NULL, PARAM_BP_GREATER_EQUAL },
+ {TEXT("R") , NULL, PARAM_BP_READ },
+ {TEXT("?") , NULL, PARAM_BP_READ },
+ {TEXT("W") , NULL, PARAM_BP_WRITE },
+ {TEXT("@") , NULL, PARAM_BP_WRITE },
+ {TEXT("*") , NULL, PARAM_BP_READ_WRITE },
// Regs (for PUSH / POP)
- ,{"A" , NULL, PARAM_REG_A }
- ,{"X" , NULL, PARAM_REG_X }
- ,{"Y" , NULL, PARAM_REG_Y }
- ,{"PC" , NULL, PARAM_REG_PC }
- ,{"S" , NULL, PARAM_REG_SP }
-// ,{"G" , NULL, PARAM_REG_PC }
+ {TEXT("A") , NULL, PARAM_REG_A },
+ {TEXT("X") , NULL, PARAM_REG_X },
+ {TEXT("Y") , NULL, PARAM_REG_Y },
+ {TEXT("PC") , NULL, PARAM_REG_PC },
+ {TEXT("S") , NULL, PARAM_REG_SP },
// Flags
- ,{"P" , NULL, PARAM_FLAGS }
- ,{"C" , NULL, PARAM_FLAG_C } // ---- ---1 Carry
- ,{"Z" , NULL, PARAM_FLAG_Z } // ---- --1- Zero
- ,{"I" , NULL, PARAM_FLAG_I } // ---- -1-- Interrupt
- ,{"D" , NULL, PARAM_FLAG_D } // ---- 1--- Decimal
- ,{"B" , NULL, PARAM_FLAG_B } // ---1 ---- Break
- ,{"R" , NULL, PARAM_FLAG_R } // --1- ---- Reserved
- ,{"V" , NULL, PARAM_FLAG_V } // -1-- ---- Overflow
- ,{"N" , NULL, PARAM_FLAG_N } // 1--- ---- Sign
+ {TEXT("P") , NULL, PARAM_FLAGS },
+ {TEXT("C") , NULL, PARAM_FLAG_C }, // ---- ---1 Carry
+ {TEXT("Z") , NULL, PARAM_FLAG_Z }, // ---- --1- Zero
+ {TEXT("I") , NULL, PARAM_FLAG_I }, // ---- -1-- Interrupt
+ {TEXT("D") , NULL, PARAM_FLAG_D }, // ---- 1--- Decimal
+ {TEXT("B") , NULL, PARAM_FLAG_B }, // ---1 ---- Break
+ {TEXT("R") , NULL, PARAM_FLAG_R }, // --1- ---- Reserved
+ {TEXT("V") , NULL, PARAM_FLAG_V }, // -1-- ---- Overflow
+ {TEXT("N") , NULL, PARAM_FLAG_N }, // 1--- ---- Sign
// Disasm
- ,{"BRANCH" , NULL, PARAM_CONFIG_BRANCH }
- ,{"COLON" , NULL, PARAM_CONFIG_COLON }
- ,{"OPCODE" , NULL, PARAM_CONFIG_OPCODE }
- ,{"POINTER" , NULL, PARAM_CONFIG_POINTER }
- ,{"SPACES" , NULL, PARAM_CONFIG_SPACES }
- ,{"TARGET" , NULL, PARAM_CONFIG_TARGET }
+ {TEXT("BRANCH") , NULL, PARAM_CONFIG_BRANCH },
+ {TEXT("COLON") , NULL, PARAM_CONFIG_COLON },
+ {TEXT("OPCODE") , NULL, PARAM_CONFIG_OPCODE },
+ {TEXT("POINTER") , NULL, PARAM_CONFIG_POINTER },
+ {TEXT("SPACES") , NULL, PARAM_CONFIG_SPACES },
+ {TEXT("TARGET") , NULL, PARAM_CONFIG_TARGET },
// Disk
- ,{"EJECT" , NULL, PARAM_DISK_EJECT }
- ,{"INFO" , NULL, PARAM_DISK_INFO }
- ,{"PROTECT" , NULL, PARAM_DISK_PROTECT }
- ,{"READ" , NULL, PARAM_DISK_READ }
+ {TEXT("EJECT") , NULL, PARAM_DISK_EJECT },
+ {TEXT("INFO") , NULL, PARAM_DISK_INFO },
+ {TEXT("PROTECT") , NULL, PARAM_DISK_PROTECT },
+ {TEXT("READ") , NULL, PARAM_DISK_READ },
// Font (Config)
- ,{"MODE" , NULL, PARAM_FONT_MODE } // also INFO, CONSOLE, DISASM (from Window)
+ {TEXT("MODE") , NULL, PARAM_FONT_MODE }, // also INFO, CONSOLE, DISASM (from Window)
// General
- ,{"FIND" , NULL, PARAM_FIND }
- ,{"BRANCH" , NULL, PARAM_BRANCH }
- ,{"CATEGORY" , NULL, PARAM_CATEGORY }
- ,{"CLEAR" , NULL, PARAM_CLEAR }
- ,{"LOAD" , NULL, PARAM_LOAD }
- ,{"LIST" , NULL, PARAM_LIST }
- ,{"OFF" , NULL, PARAM_OFF }
- ,{"ON" , NULL, PARAM_ON }
- ,{"RESET" , NULL, PARAM_RESET }
- ,{"SAVE" , NULL, PARAM_SAVE }
- ,{"START" , NULL, PARAM_START } // benchmark
- ,{"STOP" , NULL, PARAM_STOP } // benchmark
+ {TEXT("FIND") , NULL, PARAM_FIND },
+ {TEXT("BRANCH") , NULL, PARAM_BRANCH },
+ {"CATEGORY" , NULL, PARAM_CATEGORY },
+ {TEXT("CLEAR") , NULL, PARAM_CLEAR },
+ {TEXT("LOAD") , NULL, PARAM_LOAD },
+ {TEXT("LIST") , NULL, PARAM_LIST },
+ {TEXT("OFF") , NULL, PARAM_OFF },
+ {TEXT("ON") , NULL, PARAM_ON },
+ {TEXT("RESET") , NULL, PARAM_RESET },
+ {TEXT("SAVE") , NULL, PARAM_SAVE },
+ {TEXT("START") , NULL, PARAM_START }, // benchmark
+ {TEXT("STOP") , NULL, PARAM_STOP }, // benchmark
// Help Categories
- ,{"*" , NULL, PARAM_WILDSTAR }
- ,{"BOOKMARKS" , NULL, PARAM_CAT_BOOKMARKS }
- ,{"BREAKPOINTS", NULL, PARAM_CAT_BREAKPOINTS }
- ,{"CONFIG" , NULL, PARAM_CAT_CONFIG }
- ,{"CPU" , NULL, PARAM_CAT_CPU }
-// ,{"EXPRESSION" ,
- ,{"FLAGS" , NULL, PARAM_CAT_FLAGS }
- ,{"HELP" , NULL, PARAM_CAT_HELP }
- ,{"KEYBOARD" , NULL, PARAM_CAT_KEYBOARD }
- ,{"MEMORY" , NULL, PARAM_CAT_MEMORY } // alias // SOURCE [SYMBOLS] [MEMORY] filename
- ,{"OUTPUT" , NULL, PARAM_CAT_OUTPUT }
- ,{"OPERATORS" , NULL, PARAM_CAT_OPERATORS }
- ,{"RANGE" , NULL, PARAM_CAT_RANGE }
-// ,{"REGISTERS" NULL, PARAM_CAT_REGISTERS }
- ,{"SYMBOLS" , NULL, PARAM_CAT_SYMBOLS }
- ,{"VIEW" , NULL, PARAM_CAT_VIEW }
- ,{"WATCHES" , NULL, PARAM_CAT_WATCHES }
- ,{"WINDOW" , NULL, PARAM_CAT_WINDOW }
- ,{"ZEROPAGE" , NULL, PARAM_CAT_ZEROPAGE }
+ {"*" , NULL, PARAM_WILDSTAR },
+ {"BOOKMARKS" , NULL, PARAM_CAT_BOOKMARKS },
+ {"BREAKPOINTS" , NULL, PARAM_CAT_BREAKPOINTS },
+ {"CONFIG" , NULL, PARAM_CAT_CONFIG },
+ {"CPU" , NULL, PARAM_CAT_CPU },
+// {TEXT("EXPRESSION") ,
+ {"FLAGS" , NULL, PARAM_CAT_FLAGS },
+ {"HELP" , NULL, PARAM_CAT_HELP },
+ {"KEYBOARD" , NULL, PARAM_CAT_KEYBOARD },
+ {"MEMORY" , NULL, PARAM_CAT_MEMORY }, // alias // SOURCE [SYMBOLS] [MEMORY] filename
+ {"OUTPUT" , NULL, PARAM_CAT_OUTPUT },
+ {"OPERATORS" , NULL, PARAM_CAT_OPERATORS },
+ {"RANGE" , NULL, PARAM_CAT_RANGE },
+// {TEXT("REGISTERS") , NULL, PARAM_CAT_REGISTERS },
+ {"SYMBOLS" , NULL, PARAM_CAT_SYMBOLS },
+ {"VIEW" , NULL, PARAM_CAT_VIEW },
+ {"WATCHES" , NULL, PARAM_CAT_WATCHES },
+ {"WINDOW" , NULL, PARAM_CAT_WINDOW },
+ {"ZEROPAGE" , NULL, PARAM_CAT_ZEROPAGE },
// Memory
- ,{"?" , NULL, PARAM_MEM_SEARCH_WILD }
-// ,{"*" , NULL, PARAM_MEM_SEARCH_BYTE }
+ {TEXT("?") , NULL, PARAM_MEM_SEARCH_WILD },
+// {TEXT("*") , NULL, PARAM_MEM_SEARCH_BYTE },
// Source level debugging
- ,{"MEM" , NULL, PARAM_SRC_MEMORY }
- ,{"MEMORY" , NULL, PARAM_SRC_MEMORY }
- ,{"SYM" , NULL, PARAM_SRC_SYMBOLS }
- ,{"SYMBOLS" , NULL, PARAM_SRC_SYMBOLS }
- ,{"MERLIN" , NULL, PARAM_SRC_MERLIN }
- ,{"ORCA" , NULL, PARAM_SRC_ORCA }
+ {TEXT("MEM") , NULL, PARAM_SRC_MEMORY },
+ {TEXT("MEMORY") , NULL, PARAM_SRC_MEMORY },
+ {TEXT("SYM") , NULL, PARAM_SRC_SYMBOLS },
+ {TEXT("SYMBOLS") , NULL, PARAM_SRC_SYMBOLS },
+ {TEXT("MERLIN") , NULL, PARAM_SRC_MERLIN },
+ {TEXT("ORCA") , NULL, PARAM_SRC_ORCA },
// View
-// ,{"VIEW") , NULL, PARAM_SRC_??? },
+// {TEXT("VIEW") , NULL, PARAM_SRC_??? },
// Window Win Cmd WinEffects CmdEffects
- ,{"CODE" , NULL, PARAM_CODE } // x x code win only switch to code window
-// ,{"CODE1" , NULL, PARAM_CODE_1 } // - x code/data win
- ,{"CODE2" , NULL, PARAM_CODE_2 } // - x code/data win
- ,{"CONSOLE" , NULL, PARAM_CONSOLE } // x - switch to console window
- ,{"DATA" , NULL, PARAM_DATA } // x x data win only switch to data window
-// ,{"DATA1" , NULL, PARAM_DATA_1 } // - x code/data win
- ,{"DATA2" , NULL, PARAM_DATA_2 } // - x code/data win
- ,{"DISASM" , NULL, PARAM_DISASM } //
- ,{"INFO" , NULL, PARAM_INFO } // - x code/data Toggles showing/hiding Regs/Stack/BP/Watches/ZP
- ,{"SOURCE" , NULL, PARAM_SOURCE } // x x switch to source window
- ,{"SRC" , NULL, PARAM_SOURCE } // alias
-// ,{"SOURCE_1" , NULL, PARAM_SOURCE_1 } // - x code/data
- ,{"SOURCE2 " , NULL, PARAM_SOURCE_2 } // - x
- ,{"SYMBOLS" , NULL, PARAM_SYMBOLS } // x x code/data win switch to symbols window
- ,{"SYM" , NULL, PARAM_SYMBOLS } // alias x SOURCE [SYM] [MEM] filename
-// ,{"SYMBOL1" , NULL, PARAM_SYMBOL_1 } // - x code/data win
- ,{"SYMBOL2" , NULL, PARAM_SYMBOL_2 } // - x code/data win
+ {TEXT("CODE") , NULL, PARAM_CODE }, // x x code win only switch to code window
+// {TEXT("CODE1") , NULL, PARAM_CODE_1 }, // - x code/data win
+ {TEXT("CODE2") , NULL, PARAM_CODE_2 }, // - x code/data win
+ {TEXT("CONSOLE") , NULL, PARAM_CONSOLE }, // x - switch to console window
+ {TEXT("DATA") , NULL, PARAM_DATA }, // x x data win only switch to data window
+// {TEXT("DATA1") , NULL, PARAM_DATA_1 }, // - x code/data win
+ {TEXT("DATA2") , NULL, PARAM_DATA_2 }, // - x code/data win
+ {TEXT("DISASM") , NULL, PARAM_DISASM }, //
+ {TEXT("INFO") , NULL, PARAM_INFO }, // - x code/data Toggles showing/hiding Regs/Stack/BP/Watches/ZP
+ {TEXT("SOURCE") , NULL, PARAM_SOURCE }, // x x switch to source window
+ {TEXT("SRC") , NULL, PARAM_SOURCE }, // alias
+// {TEXT("SOURCE_1") , NULL, PARAM_SOURCE_1 }, // - x code/data
+ {TEXT("SOURCE2 ") , NULL, PARAM_SOURCE_2 }, // - x
+ {TEXT("SYMBOLS") , NULL, PARAM_SYMBOLS }, // x x code/data win switch to symbols window
+ {TEXT("SYM") , NULL, PARAM_SYMBOLS }, // alias x SOURCE [SYM] [MEM] filename
+// {TEXT("SYMBOL1") , NULL, PARAM_SYMBOL_1 }, // - x code/data win
+ {TEXT("SYMBOL2") , NULL, PARAM_SYMBOL_2 }, // - x code/data win
// Internal Consistency Check
- ,{DEBUGGER__PARAMS_VERIFY_TXT__,NULL,NUM_PARAMS}
+ { DEBUGGER__PARAMS_VERIFY_TXT__, NULL, NUM_PARAMS },
};
//===========================================================================
@@ -512,7 +511,7 @@ void VerifyDebuggerCommandTable()
if ( g_aCommands[ iCmd ].iCommand != iCmd)
{
sprintf( sText, "*** ERROR *** Enumerated Commands mis-matched at #%d!", iCmd );
- MessageBoxA( g_hFrameWindow, sText, "ERROR", MB_OK );
+ MessageBoxA( g_hFrameWindow, sText, TEXT("ERROR"), MB_OK );
PostQuitMessage( 1 );
}
}
@@ -521,14 +520,14 @@ void VerifyDebuggerCommandTable()
if (strcmp( g_aCommands[ NUM_COMMANDS ].m_sName, DEBUGGER__COMMANDS_VERIFY_TXT__))
{
sprintf( sText, "*** ERROR *** Total Commands mis-matched!" );
- MessageBoxA( g_hFrameWindow, sText, "ERROR", MB_OK );
+ MessageBoxA( g_hFrameWindow, sText, TEXT("ERROR"), MB_OK );
PostQuitMessage( 1 );
}
if (strcmp( g_aParameters[ NUM_PARAMS ].m_sName, DEBUGGER__PARAMS_VERIFY_TXT__))
{
sprintf( sText, "*** ERROR *** Total Parameters mis-matched!" );
- MessageBoxA( g_hFrameWindow, sText, "ERROR", MB_OK );
+ MessageBoxA( g_hFrameWindow, sText, TEXT("ERROR"), MB_OK );
PostQuitMessage( 2 );
}
}
diff --git a/source/Debugger/Debugger_Console.cpp b/source/Debugger/Debugger_Console.cpp
index 4b907f72..901e9248 100644
--- a/source/Debugger/Debugger_Console.cpp
+++ b/source/Debugger/Debugger_Console.cpp
@@ -279,8 +279,9 @@ bool ConsoleBufferPush ( const char * pText )
const char *pSrc = pText;
conchar_t *pDst = & g_aConsoleBuffer[ g_nConsoleBuffer ][ 0 ];
- while ((x < CONSOLE_WIDTH) && (c = *pSrc))
+ while ((x < CONSOLE_WIDTH) && *pSrc)
{
+ c = *pSrc;
if ((c == '\n') || (x == (CONSOLE_WIDTH - 1)))
{
*pDst = 0;
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 6e4c98dd..9b854941 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -1223,7 +1223,7 @@ void DrawBreakpoints ( int line )
//===========================================================================
int GetConsoleLineHeightPixels()
{
- int nHeight = nHeight = g_aFontConfig[ FONT_CONSOLE ]._nFontHeight; // _nLineHeight; // _nFontHeight;
+ int nHeight = g_aFontConfig[ FONT_CONSOLE ]._nFontHeight; // _nLineHeight; // _nFontHeight;
/*
if (g_iFontSpacing == FONT_SPACING_CLASSIC)
{
@@ -2434,10 +2434,10 @@ void DrawMemory ( int line, int iMemDump )
DEVICE_e eDevice = pMD->eDevice;
MemoryView_e iView = pMD->eView;
- SS_CARD_MOCKINGBOARD SS_MB;
+ SS_CARD_MOCKINGBOARD_v1 SS_MB;
if ((eDevice == DEV_SY6522) || (eDevice == DEV_AY8910))
- MB_GetSnapshot(&SS_MB, 4+(nAddr>>1)); // Slot4 or Slot5
+ MB_GetSnapshot_v1(&SS_MB, 4+(nAddr>>1)); // Slot4 or Slot5
int nFontWidth = g_aFontConfig[ FONT_INFO ]._nFontWidthAvg;
diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp
index b92223ba..84ed29ea 100644
--- a/source/Debugger/Debugger_Help.cpp
+++ b/source/Debugger/Debugger_Help.cpp
@@ -126,7 +126,7 @@ Update_t Help_Arg_1( int iCommandHelp )
{
_Arg_1( iCommandHelp );
- wsprintf( g_aArgs[ 1 ].sArg, g_aCommands[ iCommandHelp ].m_sName ); // .3 Fixed: Help_Arg_1() now copies command name into arg.name
+ wsprintf( g_aArgs[ 1 ].sArg, "%s", g_aCommands[ iCommandHelp ].m_sName ); // .3 Fixed: Help_Arg_1() now copies command name into arg.name
return CmdHelpSpecific( 1 );
}
@@ -669,49 +669,49 @@ Update_t CmdHelpSpecific (int nArgs)
// HACK: Major kludge to display category!!!
if (iCmd <= CMD_UNASSEMBLE)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_CPU ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_CPU ].m_sName );
else
if (iCmd <= CMD_BOOKMARK_SAVE)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_BOOKMARKS ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_BOOKMARKS ].m_sName );
else
if (iCmd <= CMD_BREAKPOINT_SAVE)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_BREAKPOINTS ].m_sName );
else
if (iCmd <= CMD_CONFIG_SAVE)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_CONFIG ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_CONFIG ].m_sName );
else
if (iCmd <= CMD_CURSOR_PAGE_DOWN_4K)
wsprintf( sCategory, "Scrolling" );
else
if (iCmd <= CMD_FLAG_SET_N)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_FLAGS ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_FLAGS ].m_sName );
else
if (iCmd <= CMD_MOTD)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_HELP ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_HELP ].m_sName );
else
if (iCmd <= CMD_MEMORY_FILL)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_MEMORY ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_MEMORY ].m_sName );
else
if (iCmd <= CMD_OUTPUT_RUN)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_OUTPUT ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_OUTPUT ].m_sName );
else
if (iCmd <= CMD_SYNC)
wsprintf( sCategory, "Source" );
else
if (iCmd <= CMD_SYMBOLS_LIST)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_SYMBOLS ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_SYMBOLS ].m_sName );
else
if (iCmd <= CMD_VIEW_DHGR2)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_VIEW ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_VIEW ].m_sName );
else
if (iCmd <= CMD_WATCH_SAVE)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_WATCHES ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_WATCHES ].m_sName );
else
if (iCmd <= CMD_WINDOW_OUTPUT)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_WINDOW ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_WINDOW ].m_sName );
else
if (iCmd <= CMD_ZEROPAGE_POINTER_SAVE)
- wsprintf( sCategory, g_aParameters[ PARAM_CAT_ZEROPAGE ].m_sName );
+ wsprintf( sCategory, "%s", g_aParameters[ PARAM_CAT_ZEROPAGE ].m_sName );
else
wsprintf( sCategory, "Unknown!" );
diff --git a/source/Disk.cpp b/source/Disk.cpp
index 211ca632..a239e1c8 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
-Copyright (C) 2006-2014, Tom Charlesworth, Michael Pohoreski
+Copyright (C) 2006-2015, Tom Charlesworth, Michael Pohoreski, Nick Westgate
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -24,21 +24,31 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/* Description: Disk
*
* Author: Various
+ *
+ * In comments, UTA2E is an abbreviation for a reference to "Understanding the Apple //e" by James Sather
*/
#include "StdAfx.h"
+#include "SaveState_Structs_v1.h"
+
#include "AppleWin.h"
#include "Disk.h"
#include "DiskImage.h"
#include "Frame.h"
+#include "Log.h"
#include "Memory.h"
#include "Registry.h"
#include "Video.h"
+#include "YamlHelper.h"
#include "..\resource\resource.h"
#define LOG_DISK_ENABLED 0
+#define LOG_DISK_TRACKS 1
+#define LOG_DISK_MOTOR 0
+#define LOG_DISK_PHASES 0
+#define LOG_DISK_NIBBLES 0
// __VA_ARGS__ not supported on MSVC++ .NET 7.x
#if (LOG_DISK_ENABLED)
@@ -61,21 +71,18 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Private ________________________________________________________________________________________
- const int MAX_DISK_IMAGE_NAME = 15;
- const int MAX_DISK_FULL_NAME = 127;
-
struct Disk_t
{
TCHAR imagename[ MAX_DISK_IMAGE_NAME + 1 ]; // (ie. no extension)
TCHAR fullname [ MAX_DISK_FULL_NAME + 1 ]; // or : This is persisted to the snapshot file
- std::string strDiskPathFilename;
- std::string strFilenameInZip; // 0x00 or
+ std::string strFilenameInZip; // "" or
HIMAGE imagehandle; // Init'd by DiskInsert() -> ImageOpen()
+ bool bWriteProtected;
+ //
int track;
LPBYTE trackimage;
int phase;
int byte;
- bool bWriteProtected;
BOOL trackimagedata;
BOOL trackimagedirty;
DWORD spinning;
@@ -86,14 +93,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;
@@ -108,9 +114,11 @@ static BOOL diskaccessed = 0;
static Disk_t g_aFloppyDisk[NUM_DRIVES];
static BYTE floppylatch = 0;
static BOOL floppymotoron = 0;
+static BOOL floppyloadmode = 0; // for efficiency this is not used; it's extremely unlikely to affect emulation (nickw)
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 );
@@ -118,6 +126,7 @@ static bool IsDriveValid( const int iDrive );
static void ReadTrack (int drive);
static void RemoveDisk (int drive);
static void WriteTrack (int drive);
+static LPCTSTR DiskGetFullPathName(const int iDrive);
//===========================================================================
@@ -127,14 +136,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)
@@ -152,19 +156,27 @@ char* DiskGetCurrentState(void)
else if (floppywritemode)
{
if (g_aFloppyDisk[currdrive].bWriteProtected)
- return "Writing";
- else
return "Writing (write protected)";
+ else
+ return "Writing";
}
else
{
- return "Reading";
+ /*if (floppyloadmode)
+ {
+ if (g_aFloppyDisk[currdrive].bWriteProtected)
+ return "Reading write protect state (write protected)";
+ else
+ return "Reading write protect state (not write protected)";
+ }
+ else*/
+ return "Reading";
}
}
//===========================================================================
- void Disk_LoadLastDiskImage(const int iDrive)
+void Disk_LoadLastDiskImage(const int iDrive)
{
_ASSERT(iDrive == DRIVE_1 || iDrive == DRIVE_2);
@@ -175,22 +187,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,12 +207,23 @@ 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);
else
RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_DISK_2, TRUE, pFileName);
+
+ //
+
+ char szPathName[MAX_PATH];
+ strcpy(szPathName, DiskGetFullPathName(iDrive));
+ if (_tcsrchr(szPathName, TEXT('\\')))
+ {
+ char* pPathEnd = _tcsrchr(szPathName, TEXT('\\'))+1;
+ *pPathEnd = 0;
+ RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_START_DIR), 1, szPathName);
+ }
}
//===========================================================================
@@ -249,53 +265,6 @@ static Disk_Status_e GetDriveLightStatus(const int iDrive)
return DISK_STATUS_OFF;
}
-//===========================================================================
-
-static void GetImageTitle(LPCTSTR imagefilename, Disk_t* fptr)
-{
- TCHAR imagetitle[ MAX_DISK_FULL_NAME+1 ];
- LPCTSTR startpos = imagefilename;
-
- // imagetitle =
- if (_tcsrchr(startpos,TEXT('\\')))
- startpos = _tcsrchr(startpos,TEXT('\\'))+1;
-
- _tcsncpy(imagetitle,startpos,MAX_DISK_FULL_NAME);
- imagetitle[MAX_DISK_FULL_NAME] = 0;
-
- // if imagetitle contains a lowercase char, then found=1 (why?)
- BOOL found = 0;
- int loop = 0;
- while (imagetitle[loop] && !found)
- {
- if (IsCharLower(imagetitle[loop]))
- found = 1;
- else
- loop++;
- }
-
- if ((!found) && (loop > 2))
- CharLowerBuff(imagetitle+1,_tcslen(imagetitle+1));
-
- // fptr->fullname =
- _tcsncpy( fptr->fullname, imagetitle, MAX_DISK_FULL_NAME );
- fptr->fullname[ MAX_DISK_FULL_NAME ] = 0;
-
- if (imagetitle[0])
- {
- LPTSTR dot = imagetitle;
- if (_tcsrchr(dot,TEXT('.')))
- dot = _tcsrchr(dot,TEXT('.'));
- if (dot > imagetitle)
- *dot = 0;
- }
-
- // fptr->imagename = (ie. no extension)
- _tcsncpy( fptr->imagename, imagetitle, MAX_DISK_IMAGE_NAME );
- fptr->imagename[ MAX_DISK_IMAGE_NAME ] = 0;
-}
-
-
//===========================================================================
static bool IsDriveValid(const int iDrive)
@@ -331,8 +300,9 @@ static void ReadTrack(const int iDrive)
if (pFloppy->trackimage && pFloppy->imagehandle)
{
- LOG_DISK("read track %2X%s\r", pFloppy->track, (pFloppy->phase & 1) ? ".5" : "");
-
+#if LOG_DISK_TRACKS
+ LOG_DISK("track $%02X%s read\r\n", pFloppy->track, (pFloppy->phase & 1) ? ".5" : " ");
+#endif
ImageReadTrack(
pFloppy->imagehandle,
pFloppy->track,
@@ -370,7 +340,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 );
@@ -389,12 +358,17 @@ static void WriteTrack(const int iDrive)
return;
if (pFloppy->trackimage && pFloppy->imagehandle)
+ {
+#if LOG_DISK_TRACKS
+ LOG_DISK("track $%02X%s write\r\n", pFloppy->track, (pFloppy->phase & 0) ? ".5" : " "); // TODO: hard-coded to whole tracks - see below (nickw)
+#endif
ImageWriteTrack(
pFloppy->imagehandle,
pFloppy->track,
- pFloppy->phase,
+ pFloppy->phase, // TODO: this should never be used; it's the current phase (half-track), not that of the track to be written (nickw)
pFloppy->trackimage,
- pFloppy->nibbles );
+ pFloppy->nibbles);
+ }
pFloppy->trackimagedirty = 0;
}
@@ -415,34 +389,34 @@ void DiskBoot(void)
//===========================================================================
-static BYTE __stdcall DiskControlMotor(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
+static void __stdcall DiskControlMotor(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
{
floppymotoron = address & 1;
+#if LOG_DISK_MOTOR
+ LOG_DISK("motor %s\r\n", (floppymotoron) ? "on" : "off");
+#endif
CheckSpinning();
- return MemReadFloatingBus(1, uExecutedCycles); // TC-TODO: Check b7 always set
}
//===========================================================================
-static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
+static void __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
{
Disk_t * fptr = &g_aFloppyDisk[currdrive];
-#if 1
- int phase = (address >> 1) & 3;
+ int phase = (address >> 1) & 3;
int phase_bit = (1 << phase);
+#if 1
// update the magnet states
if (address & 1)
{
// phase on
phases |= phase_bit;
- LOG_DISK("track %02X phases %X phase %d on address $C0E%X\r", fptr->phase, phases, phase, address & 0xF);
}
else
{
// phase off
phases &= ~phase_bit;
- LOG_DISK("track %02X phases %X phase %d off address $C0E%X\r", fptr->phase, phases, phase, address & 0xF);
}
// check for any stepping effect from a magnet
@@ -463,7 +437,6 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG u
const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
const int newtrack = (nNumTracksInImage == 0) ? 0
: MIN(nNumTracksInImage-1, fptr->phase >> 1); // (round half tracks down)
- LOG_DISK("newtrack %2X%s\r", newtrack, (fptr->phase & 1) ? ".5" : "");
if (newtrack != fptr->track)
{
if (fptr->trackimage && fptr->trackimagedirty)
@@ -478,31 +451,21 @@ static BYTE __stdcall DiskControlStepper(WORD, WORD address, BYTE, BYTE, ULONG u
// https://github.com/AppleWin/AppleWin/issues/201
FrameDrawDiskStatus( (HDC)0 );
}
-#else // Old 1.13.1 code for Chessmaster 2000 to work! (see bug#18109)
- const int nNumTracksInImage = ImageGetNumTracks(fptr->imagehandle);
- if (address & 1) {
- int phase = (address >> 1) & 3;
- int direction = 0;
- if (phase == ((fptr->phase+1) & 3))
- direction = 1;
- if (phase == ((fptr->phase+3) & 3))
- direction = -1;
- if (direction) {
- fptr->phase = MAX(0,MIN(79,fptr->phase+direction));
- if (!(fptr->phase & 1)) {
- int newtrack = MIN(nNumTracksInImage-1,fptr->phase >> 1);
- if (newtrack != fptr->track) {
- if (fptr->trackimage && fptr->trackimagedirty)
- WriteTrack(currdrive);
- fptr->track = newtrack;
- fptr->trackimagedata = 0;
- }
- }
- }
- }
+#else
+ // substitute alternate stepping code here to test
+#endif
+#if LOG_DISK_PHASES
+ LOG_DISK("track $%02X%s phases %d%d%d%d phase %d %s address $%4X\r\n",
+ fptr->phase >> 1,
+ (fptr->phase & 1) ? ".5" : " ",
+ (phases >> 3) & 1,
+ (phases >> 2) & 1,
+ (phases >> 1) & 1,
+ (phases >> 0) & 1,
+ phase,
+ (address & 1) ? "on " : "off",
+ address);
#endif
- return ((address & 0xF) == 0) ? 0xFF // TC-TODO: Check why $C0E0 only returns 0xFF
- : MemReadFloatingBus(1, uExecutedCycles); // TC-TODO: Check b7 always set
}
//===========================================================================
@@ -520,13 +483,12 @@ void DiskDestroy(void)
//===========================================================================
-static BYTE __stdcall DiskEnable(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
+static void __stdcall DiskEnable(WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
{
currdrive = address & 1;
g_aFloppyDisk[!currdrive].spinning = 0;
g_aFloppyDisk[!currdrive].writelight = 0;
CheckSpinning();
- return MemReadFloatingBus(uExecutedCycles);
}
//===========================================================================
@@ -558,6 +520,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)
@@ -581,7 +548,7 @@ void DiskInitialize(void)
{
int loop = NUM_DRIVES;
while (loop--)
- ZeroMemory(&g_aFloppyDisk[loop],sizeof(Disk_t ));
+ ZeroMemory(&g_aFloppyDisk[loop], sizeof(Disk_t));
TCHAR imagefilename[MAX_PATH];
_tcscpy(imagefilename,g_sProgramDir);
@@ -611,10 +578,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 +614,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 +703,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;
@@ -793,8 +773,9 @@ bool Disk_IsDriveEmpty(const int iDrive)
//===========================================================================
-static BYTE __stdcall DiskReadWrite (WORD programcounter, WORD, BYTE, BYTE, ULONG)
+static void __stdcall DiskReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft)
{
+ /* floppyloadmode = 0; */
Disk_t * fptr = &g_aFloppyDisk[currdrive];
diskaccessed = 1;
@@ -803,32 +784,23 @@ static BYTE __stdcall DiskReadWrite (WORD programcounter, WORD, BYTE, BYTE, ULON
ReadTrack(currdrive);
if (!fptr->trackimagedata)
- return 0xFF;
-
- BYTE result = 0;
-
- if (!floppywritemode || !fptr->bWriteProtected)
{
- if (floppywritemode)
- {
- if (floppylatch & 0x80)
- {
- *(fptr->trackimage+fptr->byte) = floppylatch;
- fptr->trackimagedirty = 1;
- }
- else
- {
- return 0;
- }
- }
- else
- {
- result = *(fptr->trackimage+fptr->byte);
- }
+ floppylatch = 0xFF;
+ return;
}
- if (0)
- { LOG_DISK("nib %4X = %2X\r", fptr->byte, result); }
+ if (!floppywritemode)
+ {
+ floppylatch = *(fptr->trackimage + fptr->byte);
+#if LOG_DISK_NIBBLES
+ LOG_DISK("read %4X = %2X\r\n", fptr->byte, floppylatch);
+#endif
+ }
+ else if ((floppylatch & 0x80) && !fptr->bWriteProtected) // && floppywritemode
+ {
+ *(fptr->trackimage + fptr->byte) = floppylatch;
+ fptr->trackimagedirty = 1;
+ }
if (++fptr->byte >= fptr->nibbles)
fptr->byte = 0;
@@ -838,8 +810,6 @@ static BYTE __stdcall DiskReadWrite (WORD programcounter, WORD, BYTE, BYTE, ULON
// NB. Prevent flooding of forcing UI to redraw!!!
if( ((fptr->byte) & 0xFF) == 0 )
FrameDrawDiskStatus( (HDC)0 );
-
- return result;
}
//===========================================================================
@@ -852,7 +822,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 +850,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 +860,15 @@ 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;
}
//===========================================================================
@@ -909,24 +880,31 @@ void DiskSelect(const int iDrive)
//===========================================================================
-static BYTE __stdcall DiskSetLatchValue(WORD, WORD, BYTE write, BYTE value, ULONG)
-{
- if (write)
- floppylatch = value;
- return floppylatch;
+static void __stdcall DiskLoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG) {
+ /* floppyloadmode = 1; */
+ if (!write)
+ {
+ if (floppymotoron && !floppywritemode)
+ {
+ // phase 1 on also forces write protect in the Disk II drive (UTA2E page 9-7) but we don't implement that
+ if (g_aFloppyDisk[currdrive].bWriteProtected)
+ floppylatch |= 0x80;
+ else
+ floppylatch &= 0x7F;
+ }
+ }
}
//===========================================================================
-static BYTE __stdcall DiskSetReadMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCycles)
+static void __stdcall DiskSetReadMode(WORD, WORD, BYTE, BYTE, ULONG)
{
floppywritemode = 0;
- return MemReadFloatingBus(g_aFloppyDisk[currdrive].bWriteProtected, uExecutedCycles);
}
//===========================================================================
-static BYTE __stdcall DiskSetWriteMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCycles)
+static void __stdcall DiskSetWriteMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCycles)
{
floppywritemode = 1;
BOOL modechange = !g_aFloppyDisk[currdrive].writelight;
@@ -936,8 +914,6 @@ static BYTE __stdcall DiskSetWriteMode(WORD, WORD, BYTE, BYTE, ULONG uExecutedCy
//FrameRefreshStatus(DRAW_LEDS);
FrameDrawDiskLEDS( (HDC)0 );
}
-
- return MemReadFloatingBus(1, uExecutedCycles); // TC-TODO: Check b7 always set
}
//===========================================================================
@@ -1032,121 +1008,88 @@ void DiskLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot)
memcpy(pCxRomPeripheral + uSlot*APPLE_SLOT_SIZE, pData, DISK2_FW_SIZE);
- // NB. We used to disable the track stepping delay in the Disk II controller firmware by
+ // Note: We used to disable the track stepping delay in the Disk II controller firmware by
// patching $C64C with $A9,$00,$EA. Now not doing this since:
// . Authentic Speed should be authentic
// . Enhanced Speed runs emulation unthrottled, so removing the delay has negligible effect
// . Patching the firmware breaks the ADC checksum used by "The CIA Files" (Tricky Dick)
- // . In this case we can patch to compensate for an ADC or EOR checksum but not both
+ // . In this case we can patch to compensate for an ADC or EOR checksum but not both (nickw)
RegisterIoHandler(uSlot, Disk_IORead, Disk_IOWrite, NULL, NULL, NULL, NULL);
+
+ g_uSlot = uSlot;
}
//===========================================================================
static BYTE __stdcall Disk_IORead(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft)
{
- addr &= 0xFF;
-
- switch (addr & 0xf)
+ switch (addr & 0xF)
{
- case 0x0: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x1: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x2: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x3: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x4: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x5: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x6: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x7: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x8: return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
- case 0x9: return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
- case 0xA: return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
- case 0xB: return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
- case 0xC: return DiskReadWrite(pc, addr, bWrite, d, nCyclesLeft);
- case 0xD: return DiskSetLatchValue(pc, addr, bWrite, d, nCyclesLeft);
- case 0xE: return DiskSetReadMode(pc, addr, bWrite, d, nCyclesLeft);
- case 0xF: return DiskSetWriteMode(pc, addr, bWrite, d, nCyclesLeft);
+ case 0x0: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x1: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x2: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x3: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x4: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x5: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x6: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x7: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x8: DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x9: DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xA: DiskEnable(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xB: DiskEnable(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xC: DiskReadWrite(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xD: DiskLoadWriteProtect(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xE: DiskSetReadMode(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xF: DiskSetWriteMode(pc, addr, bWrite, d, nCyclesLeft); break;
}
- return 0;
+ // only even addresses return the latch (UTA2E Table 9.1)
+ if (!(addr & 1))
+ return floppylatch;
+ else
+ return MemReadFloatingBus(nCyclesLeft);
}
static BYTE __stdcall Disk_IOWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft)
{
- addr &= 0xFF;
-
- switch (addr & 0xf)
+ switch (addr & 0xF)
{
- case 0x0: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x1: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x2: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x3: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x4: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x5: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x6: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x7: return DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft);
- case 0x8: return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
- case 0x9: return DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft);
- case 0xA: return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
- case 0xB: return DiskEnable(pc, addr, bWrite, d, nCyclesLeft);
- case 0xC: return DiskReadWrite(pc, addr, bWrite, d, nCyclesLeft);
- case 0xD: return DiskSetLatchValue(pc, addr, bWrite, d, nCyclesLeft);
- case 0xE: return DiskSetReadMode(pc, addr, bWrite, d, nCyclesLeft);
- case 0xF: return DiskSetWriteMode(pc, addr, bWrite, d, nCyclesLeft);
+ case 0x0: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x1: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x2: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x3: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x4: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x5: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x6: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x7: DiskControlStepper(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x8: DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0x9: DiskControlMotor(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xA: DiskEnable(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xB: DiskEnable(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xC: DiskReadWrite(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xD: DiskLoadWriteProtect(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xE: DiskSetReadMode(pc, addr, bWrite, d, nCyclesLeft); break;
+ case 0xF: DiskSetWriteMode(pc, addr, bWrite, d, nCyclesLeft); break;
}
+ // any address writes the latch via sequencer LD command (74LS323 datasheet)
+ if (floppywritemode /* && floppyloadmode */)
+ {
+ floppylatch = d;
+ }
return 0;
}
//===========================================================================
-DWORD DiskGetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot)
+int DiskSetSnapshot_v1(const SS_CARD_DISK2* const pSS)
{
- pSS->Hdr.UnitHdr.dwLength = sizeof(SS_CARD_DISK2);
- pSS->Hdr.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,2);
+ if(pSS->Hdr.UnitHdr.hdr.v1.dwVersion > MAKE_VERSION(1,0,0,2))
+ return -1;
- pSS->Hdr.dwSlot = dwSlot;
- pSS->Hdr.dwType = CT_Disk2;
-
- pSS->phases = phases; // new in 1.0.0.2 disk snapshots
- pSS->currdrive = currdrive; // this was an int in 1.0.0.1 disk snapshots
- pSS->diskaccessed = diskaccessed;
- pSS->enhancedisk = enhancedisk;
- pSS->floppylatch = floppylatch;
- pSS->floppymotoron = floppymotoron;
- pSS->floppywritemode = floppywritemode;
-
- for(UINT i=0; iUnit[i].szFileName, g_aFloppyDisk[i].fullname);
- pSS->Unit[i].track = g_aFloppyDisk[i].track;
- pSS->Unit[i].phase = g_aFloppyDisk[i].phase;
- pSS->Unit[i].byte = g_aFloppyDisk[i].byte;
- pSS->Unit[i].writeprotected = g_aFloppyDisk[i].bWriteProtected ? TRUE : FALSE;
- pSS->Unit[i].trackimagedata = g_aFloppyDisk[i].trackimagedata;
- pSS->Unit[i].trackimagedirty = g_aFloppyDisk[i].trackimagedirty;
- pSS->Unit[i].spinning = g_aFloppyDisk[i].spinning;
- pSS->Unit[i].writelight = g_aFloppyDisk[i].writelight;
- pSS->Unit[i].nibbles = g_aFloppyDisk[i].nibbles;
-
- if(g_aFloppyDisk[i].trackimage)
- memcpy(pSS->Unit[i].nTrack, g_aFloppyDisk[i].trackimage, NIBBLES_PER_TRACK);
- else
- memset(pSS->Unit[i].nTrack, 0, NIBBLES_PER_TRACK);
- }
-
- return 0;
-}
-
-DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
-{
- if(pSS->Hdr.UnitHdr.dwVersion > MAKE_VERSION(1,0,0,2))
- {
- return -1;
- }
-
- phases = pSS->phases; // new in 1.0.0.2 disk snapshots
- currdrive = pSS->currdrive; // this was an int in 1.0.0.1 disk snapshots
+ phases = pSS->phases;
+ currdrive = pSS->currdrive;
diskaccessed = pSS->diskaccessed;
enhancedisk = pSS->enhancedisk;
floppylatch = pSS->floppylatch;
@@ -1157,7 +1100,7 @@ DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
for(UINT i=0; i pTrack( new BYTE [NIBBLES_PER_TRACK] );
+ memset(pTrack.get(), 0, NIBBLES_PER_TRACK);
+ if (yamlLoadHelper.GetSubMap(SS_YAML_KEY_TRACK_IMAGE))
+ {
+ yamlLoadHelper.LoadMemory(pTrack.get(), NIBBLES_PER_TRACK);
+ yamlLoadHelper.PopMap();
+ }
+
+ yamlLoadHelper.PopMap();
+
+ //
+
+ if (!filename.empty() && !bImageError)
+ {
+ if ((g_aFloppyDisk[unit].trackimage == NULL) && g_aFloppyDisk[unit].nibbles)
+ AllocTrack(unit);
+
+ if (g_aFloppyDisk[unit].trackimage == NULL)
+ bImageError = true;
+ else
+ memcpy(g_aFloppyDisk[unit].trackimage, pTrack.get(), NIBBLES_PER_TRACK);
+ }
+
+ if (bImageError)
+ {
+ g_aFloppyDisk[unit].trackimagedata = 0;
+ g_aFloppyDisk[unit].trackimagedirty = 0;
+ g_aFloppyDisk[unit].nibbles = 0;
+ }
+}
+
+bool DiskLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != 6) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ phases = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASES);
+ currdrive = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_DRIVE);
+ diskaccessed = yamlLoadHelper.LoadBool(SS_YAML_KEY_DISK_ACCESSED);
+ enhancedisk = yamlLoadHelper.LoadBool(SS_YAML_KEY_ENHANCE_DISK);
+ floppylatch = yamlLoadHelper.LoadUint(SS_YAML_KEY_FLOPPY_LATCH);
+ floppymotoron = yamlLoadHelper.LoadBool(SS_YAML_KEY_FLOPPY_MOTOR_ON);
+ floppywritemode = yamlLoadHelper.LoadBool(SS_YAML_KEY_FLOPPY_WRITE_MODE);
+
+ // Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1
+ for(UINT i=0; ibWriteProtected = *pWriteProtected_;
+ ZeroMemory(*hDiskImage, sizeof(ImageInfo));
+ ImageInfo* pImageInfo = (ImageInfo*) *hDiskImage;
+ pImageInfo->bWriteProtected = *pWriteProtected;
ImageError_e Err = sg_DiskImageHelper.Open(pszImageFilename, pImageInfo, bCreateIfNecessary, strFilenameInZip);
- if (pImageInfo->pImageType != NULL && Err == eIMAGE_ERROR_NONE && pImageInfo->pImageType->GetType() == eImageHDV)
- Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
-
if (Err != eIMAGE_ERROR_NONE)
{
- ImageClose(*hDiskImage_, true);
- *hDiskImage_ = (HIMAGE)0;
+ ImageClose(*hDiskImage, true);
+ *hDiskImage = (HIMAGE)0;
+ return Err;
+ }
+
+ if (pImageInfo->pImageType && pImageInfo->pImageType->GetType() == eImageHDV)
+ {
+ if (bExpectFloppy)
+ Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
return Err;
}
@@ -76,7 +80,7 @@ ImageError_e ImageOpen( LPCTSTR pszImageFilename,
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
pImageInfo->ValidTrack[uTrack] = (pImageInfo->uImageSize > 0) ? 1 : 0;
- *pWriteProtected_ = pImageInfo->bWriteProtected;
+ *pWriteProtected = pImageInfo->bWriteProtected;
return eIMAGE_ERROR_NONE;
}
@@ -185,6 +189,36 @@ void ImageWriteTrack( const HIMAGE hDiskImage,
//===========================================================================
+bool ImageReadBlock( const HIMAGE hDiskImage,
+ UINT nBlock,
+ LPBYTE pBlockBuffer)
+{
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+
+ bool bRes = false;
+ if (ptr->pImageType->AllowRW())
+ bRes = ptr->pImageType->Read(ptr, nBlock, pBlockBuffer);
+
+ return bRes;
+}
+
+//===========================================================================
+
+bool ImageWriteBlock( const HIMAGE hDiskImage,
+ UINT nBlock,
+ LPBYTE pBlockBuffer)
+{
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+
+ bool bRes = false;
+ if (ptr->pImageType->AllowRW() && !ptr->bWriteProtected)
+ bRes = ptr->pImageType->Write(ptr, nBlock, pBlockBuffer);
+
+ return bRes;
+}
+
+//===========================================================================
+
int ImageGetNumTracks(const HIMAGE hDiskImage)
{
ImageInfo* ptr = (ImageInfo*) hDiskImage;
@@ -202,3 +236,60 @@ bool ImageIsMultiFileZip(const HIMAGE hDiskImage)
ImageInfo* ptr = (ImageInfo*) hDiskImage;
return ptr ? (ptr->uNumEntriesInZip > 1) : false;
}
+
+const char* ImageGetPathname(const HIMAGE hDiskImage)
+{
+ static char* szEmpty = "";
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+ return ptr ? ptr->szFilename : szEmpty;
+}
+
+UINT ImageGetImageSize(const HIMAGE hDiskImage)
+{
+ ImageInfo* ptr = (ImageInfo*) hDiskImage;
+ return ptr ? ptr->uImageSize : 0;
+}
+
+void GetImageTitle(LPCTSTR pPathname, TCHAR* pImageName, TCHAR* pFullName)
+{
+ TCHAR imagetitle[ MAX_DISK_FULL_NAME+1 ];
+ LPCTSTR startpos = pPathname;
+
+ // imagetitle =
+ if (_tcsrchr(startpos, TEXT('\\')))
+ startpos = _tcsrchr(startpos, TEXT('\\'))+1;
+
+ _tcsncpy(imagetitle, startpos, MAX_DISK_FULL_NAME);
+ imagetitle[MAX_DISK_FULL_NAME] = 0;
+
+ // if imagetitle contains a lowercase char, then found=1 (why?)
+ BOOL found = 0;
+ int loop = 0;
+ while (imagetitle[loop] && !found)
+ {
+ if (IsCharLower(imagetitle[loop]))
+ found = 1;
+ else
+ loop++;
+ }
+
+ if ((!found) && (loop > 2))
+ CharLowerBuff(imagetitle+1, _tcslen(imagetitle+1));
+
+ // pFullName =
+ _tcsncpy( pFullName, imagetitle, MAX_DISK_FULL_NAME );
+ pFullName[ MAX_DISK_FULL_NAME ] = 0;
+
+ if (imagetitle[0])
+ {
+ LPTSTR dot = imagetitle;
+ if (_tcsrchr(dot, TEXT('.')))
+ dot = _tcsrchr(dot, TEXT('.'));
+ if (dot > imagetitle)
+ *dot = 0;
+ }
+
+ // pImageName = (ie. no extension)
+ _tcsncpy( pImageName, imagetitle, MAX_DISK_IMAGE_NAME );
+ pImageName[ MAX_DISK_IMAGE_NAME ] = 0;
+}
diff --git a/source/DiskImage.h b/source/DiskImage.h
index b712399f..73b5bd4d 100644
--- a/source/DiskImage.h
+++ b/source/DiskImage.h
@@ -55,9 +55,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
eIMAGE_ERROR_UNABLE_TO_OPEN,
eIMAGE_ERROR_UNABLE_TO_OPEN_GZ,
eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP,
+ eIMAGE_ERROR_FAILED_TO_GET_PATHNAME,
};
-ImageError_e ImageOpen(LPCTSTR pszImageFilename, HIMAGE* hDiskImage_, bool* pWriteProtected_, const bool bCreateIfNecessary, std::string& strFilenameInZip);
+ const int MAX_DISK_IMAGE_NAME = 15;
+ const int MAX_DISK_FULL_NAME = 127;
+
+
+ImageError_e ImageOpen(LPCTSTR pszImageFilename, HIMAGE* hDiskImage, bool* pWriteProtected, const bool bCreateIfNecessary, std::string& strFilenameInZip, const bool bExpectFloppy=true);
void ImageClose(const HIMAGE hDiskImage, const bool bOpenError=false);
BOOL ImageBoot(const HIMAGE hDiskImage);
void ImageDestroy(void);
@@ -65,7 +70,13 @@ void ImageInitialize(void);
void ImageReadTrack(const HIMAGE hDiskImage, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles);
void ImageWriteTrack(const HIMAGE hDiskImage, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles);
+bool ImageReadBlock(const HIMAGE hDiskImage, UINT nBlock, LPBYTE pBlockBuffer);
+bool ImageWriteBlock(const HIMAGE hDiskImage, UINT nBlock, LPBYTE pBlockBuffer);
int ImageGetNumTracks(const HIMAGE hDiskImage);
bool ImageIsWriteProtected(const HIMAGE hDiskImage);
bool ImageIsMultiFileZip(const HIMAGE hDiskImage);
+const char* ImageGetPathname(const HIMAGE hDiskImage);
+UINT ImageGetImageSize(const HIMAGE hDiskImage);
+
+void GetImageTitle(LPCTSTR pPathname, TCHAR* pImageName, TCHAR* pFullName);
diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp
index 4eeef4a8..c4e8cb26 100644
--- a/source/DiskImageHelper.cpp
+++ b/source/DiskImageHelper.cpp
@@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "stdafx.h"
-#include "Structs.h"
#include "Common.h"
#include "zlib.h"
@@ -436,7 +435,7 @@ void CImageBase::DenibblizeTrack(LPBYTE trackimage, SectorOrder_e SectorOrder, i
offset = 0;
}
- if ((bytenum == 3) && (byteval[1] = 0xAA))
+ if ((bytenum == 3) && (byteval[1] == 0xAA))
{
int loop = 0;
int tempoffset = offset;
@@ -1435,7 +1434,9 @@ ImageError_e CImageHelperBase::Open( LPCTSTR pszImageFilename,
if (Err != eIMAGE_ERROR_NONE)
return Err;
- _tcsncpy(pImageInfo->szFilename, pszImageFilename, MAX_PATH);
+ DWORD uNameLen = GetFullPathName(pszImageFilename, MAX_PATH, pImageInfo->szFilename, NULL);
+ if (uNameLen == 0 || uNameLen >= MAX_PATH)
+ Err = eIMAGE_ERROR_FAILED_TO_GET_PATHNAME;
return eIMAGE_ERROR_NONE;
}
@@ -1453,9 +1454,10 @@ void CImageHelperBase::Close(ImageInfo* pImageInfo, const bool bDeleteFile)
if (bDeleteFile)
{
DeleteFile(pImageInfo->szFilename);
- pImageInfo->szFilename[0] = 0;
}
+ pImageInfo->szFilename[0] = 0;
+
delete [] pImageInfo->pImageBuffer;
pImageInfo->pImageBuffer = NULL;
}
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 8bbd0783..e590b92c 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -41,6 +41,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Mockingboard.h"
#include "MouseInterface.h"
#include "ParallelPrinter.h"
+#include "Pravets.h"
#include "Registry.h"
#include "SaveState.h"
#include "SerialComms.h"
@@ -183,7 +184,7 @@ static bool g_bFullScreen32Bit = true;
// Updates g_pAppTitle
// ====================================================================
-void GetAppleWindowTitle()
+static void GetAppleWindowTitle()
{
g_pAppTitle = g_pAppleWindowTitle;
@@ -568,6 +569,7 @@ static void DrawFrameWindow ()
DebugDisplay(1);
else
// Win7: In fullscreen mode with 1 redraw the screen doesn't get redrawn.
+ // 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)
//VideoRefreshScreen(0);
VideoRedrawScreen();
@@ -622,6 +624,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
@@ -764,6 +769,14 @@ void FrameDrawDiskStatus( HDC passdc )
//===========================================================================
static void DrawStatusArea (HDC passdc, int drawflags)
{
+ if (g_hFrameWindow == NULL)
+ {
+ // TC: Fix drawing of drive buttons before frame created:
+ // . Main init loop: LoadConfiguration() called before FrameCreateWindow(), eg:
+ // LoadConfiguration() -> Disk_LoadLastDiskImage() -> DiskInsert() -> FrameRefreshStatus()
+ return;
+ }
+
FrameReleaseDC();
HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
int x = buttonx;
@@ -1025,7 +1038,7 @@ LRESULT CALLBACK FrameWndProc (
if (!restart) {
DiskDestroy();
ImageDestroy();
- HD_Cleanup();
+ HD_Destroy();
}
PrintDestroy();
sg_SSC.CommDestroy();
@@ -1314,7 +1327,7 @@ LRESULT CALLBACK FrameWndProc (
{
RevealCursor();
}
- else if (g_nAppMode == MODE_RUNNING)
+ else if (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING)
{
if (!sg_Mouse.IsEnabled())
{
@@ -1391,7 +1404,7 @@ LRESULT CALLBACK FrameWndProc (
DrawCrosshairs(x,y);
JoySetPosition(x-viewportx-2, g_nViewportCX-4, y-viewporty-2, g_nViewportCY-4);
}
- else if (sg_Mouse.IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING))
+ else if (sg_Mouse.IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING))
{
if (g_bLastCursorInAppleViewport)
break;
@@ -1422,7 +1435,7 @@ LRESULT CALLBACK FrameWndProc (
if (wparam == IDEVENT_TIMER_MOUSE)
{
// NB. Need to check /g_bAppActive/ since WM_TIMER events still occur after AppleWin app has lost focus
- if (g_bAppActive && sg_Mouse.IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING))
+ if (g_bAppActive && sg_Mouse.IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING))
{
if (!g_bLastCursorInAppleViewport)
break;
@@ -1973,12 +1986,15 @@ void RelayEvent (UINT message, WPARAM wparam, LPARAM lparam) {
}
//===========================================================================
+
+// todo: consolidate CtrlReset() and ResetMachineState()
void ResetMachineState ()
{
DiskReset(); // Set floppymotoron=0
g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
MemReset();
+ PravetsReset();
DiskBoot();
VideoResetState();
sg_SSC.CommReset();
@@ -1987,7 +2003,7 @@ void ResetMachineState ()
MB_Reset();
SpkrReset();
sg_Mouse.Reset();
- g_ActiveCPU = CPU_6502;
+ SetActiveCpu( GetMainCpu() );
#ifdef USE_SPEECH_API
g_Speech.Reset();
#endif
@@ -1997,12 +2013,15 @@ void ResetMachineState ()
//===========================================================================
+
+// todo: consolidate CtrlReset() and ResetMachineState()
void CtrlReset()
{
// Ctrl+Reset - TODO: This is a terrible place for this code!
if (!IS_APPLE2)
MemResetPaging();
+ PravetsReset();
DiskReset();
KeybReset();
if (!IS_APPLE2)
@@ -2468,7 +2487,6 @@ void FrameSetCursorPosByMousePos()
int iY, iMinY, iMaxY;
sg_Mouse.GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
- _ASSERT(iMinX == 0 && iMinY == 0);
float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
@@ -2504,7 +2522,6 @@ static void FrameSetCursorPosByMousePos(int x, int y, int dx, int dy, bool bLeav
int iX, iMinX, iMaxX;
int iY, iMinY, iMaxY;
sg_Mouse.GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
- _ASSERT(iMinX == 0 && iMinY == 0);
if (bLeavingAppleScreen)
{
@@ -2624,3 +2641,17 @@ void GetViewportCXCY(int& nViewportCX, int& nViewportCY)
nViewportCX = g_nViewportCX;
nViewportCY = g_nViewportCY;
}
+
+// Call all funcs with dependency on g_Apple2Type
+void FrameUpdateApple2Type(void)
+{
+ DeleteGdiObjects();
+ CreateGdiObjects();
+
+ // DRAW_TITLE : calls GetAppleWindowTitle()
+ // DRAW_LEDS : update LEDs (eg. CapsLock varies on Apple2 type)
+ DrawStatusArea( (HDC)0, DRAW_TITLE|DRAW_LEDS );
+
+ // Draw buttons & call DrawStatusArea(DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS)
+ DrawFrameWindow();
+}
diff --git a/source/Frame.h b/source/Frame.h
index 81f87278..e54f4187 100644
--- a/source/Frame.h
+++ b/source/Frame.h
@@ -59,6 +59,7 @@
void GetViewportCXCY(int& nViewportCX, int& nViewportCY);
bool GetFullScreen32Bit(void);
void SetFullScreen32Bit(bool b32Bit);
+ void FrameUpdateApple2Type(void);
void FrameDrawDiskLEDS( HDC hdc );
void FrameDrawDiskStatus( HDC hdc );
diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp
index 3406140e..90b3a0bc 100644
--- a/source/Harddisk.cpp
+++ b/source/Harddisk.cpp
@@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
-Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
+Copyright (C) 2006-2015, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "HardDisk.h"
#include "Memory.h"
#include "Registry.h"
+#include "YamlHelper.h"
#include "..\resource\resource.h"
@@ -114,28 +115,29 @@ Overview
struct HDD
{
// From Disk_t
- TCHAR imagename[16]; // Not used
- TCHAR fullname[128];
+ TCHAR imagename[ MAX_DISK_IMAGE_NAME + 1 ]; // (ie. no extension) [not used]
+ TCHAR fullname[ MAX_DISK_FULL_NAME + 1 ]; // or
+ std::string strFilenameInZip; // "" or [not used]
+ HIMAGE imagehandle; // Init'd by HD_Insert() -> ImageOpen()
+ bool bWriteProtected; // Needed for ImageOpen() [otherwise not used]
//
BYTE hd_error;
WORD hd_memblock;
UINT hd_diskblock;
WORD hd_buf_ptr;
- BOOL hd_imageloaded;
- BYTE hd_buf[HD_BLOCK_SIZE+1]; // Why +1?
+ bool hd_imageloaded;
+ BYTE hd_buf[HD_BLOCK_SIZE+1]; // Why +1? Probably for erroreous reads beyond the block size (ie. reads from I/O addr 0xC0F8)
#if HD_LED
Disk_Status_e hd_status_next;
Disk_Status_e hd_status_prev;
#endif
-
- ImageInfo Info;
};
static bool g_bHD_RomLoaded = false;
static bool g_bHD_Enabled = false;
-static BYTE g_nHD_UnitNum = HARDDISK_1;
+static BYTE g_nHD_UnitNum = HARDDISK_1<<7; // b7=unit
// The HDD interface has a single Command register for both drives:
// . ProDOS will write to Command before switching drives
@@ -143,114 +145,96 @@ static BYTE g_nHD_Command;
static HDD g_HardDisk[NUM_HARDDISKS] = {0};
+static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
static UINT g_uSlot = 7;
static CHardDiskImageHelper sg_HardDiskImageHelper;
//===========================================================================
+static void HD_SaveLastDiskImage(const int iDrive);
+
static void HD_CleanupDrive(const int iDrive)
{
- sg_HardDiskImageHelper.Close(&g_HardDisk[iDrive].Info, false);
-
- g_HardDisk[iDrive].hd_imageloaded = false;
- g_HardDisk[iDrive].imagename[0] = 0;
- g_HardDisk[iDrive].fullname[0] = 0;
- g_HardDisk[iDrive].Info.szFilename[0] = 0;
-}
-
-static ImageError_e ImageOpen( LPCTSTR pszImageFilename,
- const int iDrive,
- const bool bCreateIfNecessary,
- std::string& strFilenameInZip)
-{
- if (!pszImageFilename)
- return eIMAGE_ERROR_BAD_POINTER;
-
- HDD* pHDD = &g_HardDisk[iDrive];
- ImageInfo* pImageInfo = &pHDD->Info;
- pImageInfo->bWriteProtected = false;
-
- ImageError_e Err = sg_HardDiskImageHelper.Open(pszImageFilename, pImageInfo, bCreateIfNecessary, strFilenameInZip);
-
- if (Err != eIMAGE_ERROR_NONE)
+ if (g_HardDisk[iDrive].imagehandle)
{
- HD_CleanupDrive(iDrive);
- return Err;
+ ImageClose(g_HardDisk[iDrive].imagehandle);
+ g_HardDisk[iDrive].imagehandle = (HIMAGE)0;
}
- return eIMAGE_ERROR_NONE;
+ g_HardDisk[iDrive].hd_imageloaded = false;
+
+ g_HardDisk[iDrive].imagename[0] = 0;
+ g_HardDisk[iDrive].fullname[0] = 0;
+ g_HardDisk[iDrive].strFilenameInZip = "";
+
+ HD_SaveLastDiskImage(iDrive);
}
//-----------------------------------------------------------------------------
-static void GetImageTitle(LPCTSTR pszImageFilename, HDD* pHardDrive)
-{
- TCHAR imagetitle[128];
- LPCTSTR startpos = pszImageFilename;
-
- // imagetitle =
- if (_tcsrchr(startpos,TEXT('\\')))
- startpos = _tcsrchr(startpos,TEXT('\\'))+1;
- _tcsncpy(imagetitle,startpos,127);
- imagetitle[127] = 0;
-
- // if imagetitle contains a lowercase char, then found=1 (why?)
- BOOL found = 0;
- int loop = 0;
- while (imagetitle[loop] && !found)
- {
- if (IsCharLower(imagetitle[loop]))
- found = 1;
- else
- loop++;
- }
-
- if ((!found) && (loop > 2))
- CharLowerBuff(imagetitle+1,_tcslen(imagetitle+1));
-
- // hdptr->fullname =
- _tcsncpy(pHardDrive->fullname,imagetitle,127);
- pHardDrive->fullname[127] = 0;
-
- if (imagetitle[0])
- {
- LPTSTR dot = imagetitle;
- if (_tcsrchr(dot,TEXT('.')))
- dot = _tcsrchr(dot,TEXT('.'));
- if (dot > imagetitle)
- *dot = 0;
- }
-
- // hdptr->imagename = (ie. no extension)
- _tcsncpy(pHardDrive->imagename,imagetitle,15);
- pHardDrive->imagename[15] = 0;
-}
-
static void NotifyInvalidImage(TCHAR* pszImageFilename)
{
// TC: TO DO
}
-static BOOL HD_Load_Image(const int iDrive, LPCSTR pszImageFilename)
+//===========================================================================
+
+BOOL HD_Insert(const int iDrive, LPCTSTR pszImageFilename);
+
+void HD_LoadLastDiskImage(const int iDrive)
{
- const bool bCreateIfNecessary = false; // NB. Don't allow creation of HDV files
- std::string strFilenameInZip; // TODO: Use this
- ImageError_e Error = ImageOpen(pszImageFilename, iDrive, bCreateIfNecessary, strFilenameInZip);
+ _ASSERT(iDrive == HARDDISK_1 || iDrive == HARDDISK_2);
- g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE);
+ char sFilePath[ MAX_PATH + 1];
+ sFilePath[0] = 0;
-#if HD_LED
- g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF;
- g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
-#endif
+ char *pRegKey = (iDrive == HARDDISK_1)
+ ? REGVALUE_PREF_LAST_HARDDISK_1
+ : REGVALUE_PREF_LAST_HARDDISK_2;
- return g_HardDisk[iDrive].hd_imageloaded;
+ if (RegLoadString(TEXT(REG_PREFS), pRegKey, 1, sFilePath, MAX_PATH))
+ {
+ sFilePath[ MAX_PATH ] = 0;
+
+ g_bSaveDiskImage = false;
+ // Pass in ptr to local copy of filepath, since RemoveDisk() sets DiskPathFilename = "" // todo: update comment for HD func
+ HD_Insert(iDrive, sFilePath);
+ g_bSaveDiskImage = true;
+ }
}
//===========================================================================
-// everything below is global
+static void HD_SaveLastDiskImage(const int iDrive)
+{
+ _ASSERT(iDrive == HARDDISK_1 || iDrive == HARDDISK_2);
+
+ if (!g_bSaveDiskImage)
+ return;
+
+ const char *pFileName = g_HardDisk[iDrive].fullname;
+
+ if (iDrive == HARDDISK_1)
+ RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_HARDDISK_1, TRUE, pFileName);
+ else
+ RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_HARDDISK_2, TRUE, pFileName);
+
+ //
+
+ char szPathName[MAX_PATH];
+ strcpy(szPathName, HD_GetFullPathName(iDrive));
+ if (_tcsrchr(szPathName, TEXT('\\')))
+ {
+ char* pPathEnd = _tcsrchr(szPathName, TEXT('\\'))+1;
+ *pPathEnd = 0;
+ RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, szPathName);
+ }
+}
+
+//===========================================================================
+
+// (Nearly) everything below is global
static BYTE __stdcall HD_IO_EMUL(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
@@ -263,7 +247,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 +283,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 +321,82 @@ VOID HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot)
RegisterIoHandler(g_uSlot, HD_IO_EMUL, HD_IO_EMUL, NULL, NULL, NULL, NULL);
}
-VOID HD_Cleanup(void)
+void HD_Destroy(void)
{
- for(int i=HARDDISK_1; i= MAX_PATH)
+ strcpy_s(szCurrentPathname, MAX_PATH, pszImageFilename);
+
+ if (!strcmp(pszOtherPathname, szCurrentPathname))
+ {
+ HD_Unplug(!iDrive);
+ FrameRefreshStatus(DRAW_LEDS);
+ }
}
- BOOL bResult = HD_Load_Image(iDrive, pszImageFilename);
+ const bool bCreateIfNecessary = false; // NB. Don't allow creation of HDV files
+ const bool bExpectFloppy = false;
+ ImageError_e Error = ImageOpen(pszImageFilename,
+ &g_HardDisk[iDrive].imagehandle,
+ &g_HardDisk[iDrive].bWriteProtected,
+ bCreateIfNecessary,
+ g_HardDisk[iDrive].strFilenameInZip, // TODO: Use this
+ bExpectFloppy);
- if (bResult)
- GetImageTitle(pszImageFilename, &g_HardDisk[iDrive]);
+ g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE);
- return bResult;
+#if HD_LED
+ g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF;
+ g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
+#endif
+
+ if (Error == eIMAGE_ERROR_NONE)
+ {
+ GetImageTitle(pszImageFilename, g_HardDisk[iDrive].imagename, g_HardDisk[iDrive].fullname);
+ }
+
+ HD_SaveLastDiskImage(iDrive);
+
+ return g_HardDisk[iDrive].hd_imageloaded;
}
-void HD_Select(const int iDrive)
+static bool HD_SelectImage(const int iDrive, LPCSTR pszFilename)
{
TCHAR directory[MAX_PATH] = TEXT("");
TCHAR filename[MAX_PATH] = TEXT("");
TCHAR title[40];
+ strcpy(filename, pszFilename);
+
RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, directory, MAX_PATH);
_tcscpy(title, TEXT("Select HDV Image For HDD "));
_tcscat(title, iDrive ? TEXT("2") : TEXT("1"));
+ _ASSERT(sizeof(OPENFILENAME) == sizeof(OPENFILENAME_NT4)); // Required for Win98/ME support (selected by _WIN32_WINNT=0x0400 in stdafx.h)
+
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
@@ -389,22 +410,29 @@ 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)
@@ -415,7 +443,7 @@ void HD_Unplug(const int iDrive)
bool HD_IsDriveUnplugged(const int iDrive)
{
- return g_HardDisk[iDrive].hd_imageloaded == FALSE;
+ return g_HardDisk[iDrive].hd_imageloaded == false;
}
//-----------------------------------------------------------------------------
@@ -450,33 +478,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 +512,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 +532,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 +588,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 +660,156 @@ void HD_GetLightStatus (Disk_Status_e *pDisk1Status_)
*pDisk1Status_ = DISK_STATUS_OFF;
}
}
+
+//===========================================================================
+
+#define SS_YAML_VALUE_CARD_HDD "Generic HDD"
+
+#define SS_YAML_KEY_CURRENT_UNIT "Current Unit"
+#define SS_YAML_KEY_COMMAND "Command"
+
+#define SS_YAML_KEY_HDDUNIT "Unit"
+#define SS_YAML_KEY_FILENAME "Filename"
+#define SS_YAML_KEY_ERROR "Error"
+#define SS_YAML_KEY_MEMBLOCK "MemBlock"
+#define SS_YAML_KEY_DISKBLOCK "DiskBlock"
+#define SS_YAML_KEY_IMAGELOADED "ImageLoaded"
+#define SS_YAML_KEY_STATUS_NEXT "Status Next"
+#define SS_YAML_KEY_STATUS_PREV "Status Prev"
+#define SS_YAML_KEY_BUF_PTR "Buffer Offset"
+#define SS_YAML_KEY_BUF "Buffer"
+
+std::string HD_GetSnapshotCardName(void)
+{
+ static const std::string name(SS_YAML_VALUE_CARD_HDD);
+ return name;
+}
+
+static void HD_SaveSnapshotHDDUnit(YamlSaveHelper& yamlSaveHelper, UINT unit)
+{
+ YamlSaveHelper::Label label(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_HDDUNIT, unit);
+ yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, g_HardDisk[unit].fullname);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_ERROR, g_HardDisk[unit].hd_error);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_MEMBLOCK, g_HardDisk[unit].hd_memblock);
+ yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_DISKBLOCK, g_HardDisk[unit].hd_diskblock);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_IMAGELOADED, g_HardDisk[unit].hd_imageloaded);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_STATUS_NEXT, g_HardDisk[unit].hd_status_next);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_STATUS_PREV, g_HardDisk[unit].hd_status_prev);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_BUF_PTR, g_HardDisk[unit].hd_buf_ptr);
+
+ // New label
+ {
+ YamlSaveHelper::Label buffer(yamlSaveHelper, "%s:\n", SS_YAML_KEY_BUF);
+ yamlSaveHelper.SaveMemory(g_HardDisk[unit].hd_buf, HD_BLOCK_SIZE);
+ }
+}
+
+void HD_SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ if (!HD_CardIsEnabled())
+ return;
+
+ YamlSaveHelper::Slot slot(yamlSaveHelper, HD_GetSnapshotCardName(), g_uSlot, 1);
+
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+ yamlSaveHelper.Save("%s: %d # b7=unit\n", SS_YAML_KEY_CURRENT_UNIT, g_nHD_UnitNum);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_COMMAND, g_nHD_Command);
+
+ HD_SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_1);
+ HD_SaveSnapshotHDDUnit(yamlSaveHelper, HARDDISK_2);
+}
+
+static bool HD_LoadSnapshotHDDUnit(YamlLoadHelper& yamlLoadHelper, UINT unit)
+{
+ std::string hddUnitName = std::string(SS_YAML_KEY_HDDUNIT) + (unit == HARDDISK_1 ? std::string("0") : std::string("1"));
+ if (!yamlLoadHelper.GetSubMap(hddUnitName))
+ throw std::string("Card: Expected key: ") + hddUnitName;
+
+ g_HardDisk[unit].fullname[0] = 0;
+ g_HardDisk[unit].imagename[0] = 0;
+ g_HardDisk[unit].hd_imageloaded = false; // Default to false (until image is successfully loaded below)
+ g_HardDisk[unit].hd_status_next = DISK_STATUS_OFF;
+ g_HardDisk[unit].hd_status_prev = DISK_STATUS_OFF;
+
+ std::string filename = yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME);
+ g_HardDisk[unit].hd_error = yamlLoadHelper.LoadUint(SS_YAML_KEY_ERROR);
+ g_HardDisk[unit].hd_memblock = yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMBLOCK);
+ g_HardDisk[unit].hd_diskblock = yamlLoadHelper.LoadUint(SS_YAML_KEY_DISKBLOCK);
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_IMAGELOADED); // Consume
+ Disk_Status_e diskStatusNext = (Disk_Status_e) yamlLoadHelper.LoadUint(SS_YAML_KEY_STATUS_NEXT);
+ Disk_Status_e diskStatusPrev = (Disk_Status_e) yamlLoadHelper.LoadUint(SS_YAML_KEY_STATUS_PREV);
+ g_HardDisk[unit].hd_buf_ptr = yamlLoadHelper.LoadUint(SS_YAML_KEY_BUF_PTR);
+
+ if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_BUF))
+ throw hddUnitName + std::string(": Missing: ") + std::string(SS_YAML_KEY_BUF);
+ yamlLoadHelper.LoadMemory(g_HardDisk[unit].hd_buf, HD_BLOCK_SIZE);
+
+ yamlLoadHelper.PopMap();
+ yamlLoadHelper.PopMap();
+
+ //
+
+ bool bResSelectImage = false;
+
+ if (!filename.empty())
+ {
+ DWORD dwAttributes = GetFileAttributes(filename.c_str());
+ if (dwAttributes == INVALID_FILE_ATTRIBUTES)
+ {
+ // Get user to browse for file
+ bResSelectImage = HD_SelectImage(unit, filename.c_str());
+
+ dwAttributes = GetFileAttributes(filename.c_str());
+ }
+
+ bool bImageError = (dwAttributes == INVALID_FILE_ATTRIBUTES);
+ if (!bImageError)
+ {
+ if (!HD_Insert(unit, filename.c_str()))
+ bImageError = true;
+
+ // HD_Insert() sets up:
+ // . imagename
+ // . fullname
+ // . hd_imageloaded
+ // . hd_status_next = DISK_STATUS_OFF
+ // . hd_status_prev = DISK_STATUS_OFF
+
+ g_HardDisk[unit].hd_status_next = diskStatusNext;
+ g_HardDisk[unit].hd_status_prev = diskStatusPrev;
+ }
+ }
+
+ return bResSelectImage;
+}
+
+bool HD_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, const std::string strSaveStatePath)
+{
+ if (slot != 7) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ g_nHD_UnitNum = yamlLoadHelper.LoadUint(SS_YAML_KEY_CURRENT_UNIT); // b7=unit
+ g_nHD_Command = yamlLoadHelper.LoadUint(SS_YAML_KEY_COMMAND);
+
+ // Unplug all HDDs first in case HDD-2 is to be plugged in as HDD-1
+ for (UINT i=0; i JN_JOYSTICK1)
+ return;
+
+ joytype[num] = type;
+
+ // Refresh centre positions whenever 'joytype' changes
+ JoySetTrim(JoyGetTrim(true) , true);
+ JoySetTrim(JoyGetTrim(false), false);
+}
+
+DWORD JoyGetJoyType(UINT num)
+{
+ _ASSERT(num <= JN_JOYSTICK1);
+ if (num > JN_JOYSTICK1)
+ return J0C_DISABLED;
+
+ return joytype[num];
+}
+
+//===========================================================================
+
void JoySetTrim(short nValue, bool bAxisX)
{
if(bAxisX)
@@ -824,14 +849,45 @@ 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)
+//
+
+#define SS_YAML_KEY_COUNTERRESETCYCLE "Counter Reset Cycle"
+#define SS_YAML_KEY_JOY0TRIMX "Joystick0 TrimX"
+#define SS_YAML_KEY_JOY0TRIMY "Joystick0 TrimY"
+#define SS_YAML_KEY_JOY1TRIMX "Joystick1 TrimX"
+#define SS_YAML_KEY_JOY1TRIMY "Joystick1 TrimY"
+
+static std::string JoyGetSnapshotStructName(void)
{
- g_nJoyCntrResetCycle = pSS->g_nJoyCntrResetCycle;
- return 0;
+ static const std::string name("Joystick");
+ return name;
+}
+
+void JoySaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", JoyGetSnapshotStructName().c_str());
+ yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_COUNTERRESETCYCLE, g_nJoyCntrResetCycle);
+ yamlSaveHelper.SaveInt(SS_YAML_KEY_JOY0TRIMX, JoyGetTrim(true));
+ yamlSaveHelper.SaveInt(SS_YAML_KEY_JOY0TRIMY, JoyGetTrim(false));
+ yamlSaveHelper.Save("%s: %d # not implemented yet\n", SS_YAML_KEY_JOY1TRIMX, 0); // not implemented yet
+ yamlSaveHelper.Save("%s: %d # not implemented yet\n", SS_YAML_KEY_JOY1TRIMY, 0); // not implemented yet
+}
+
+void JoyLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+{
+ if (!yamlLoadHelper.GetSubMap(JoyGetSnapshotStructName()))
+ return;
+
+ g_nJoyCntrResetCycle = yamlLoadHelper.LoadUint64(SS_YAML_KEY_COUNTERRESETCYCLE);
+ JoySetTrim(yamlLoadHelper.LoadInt(SS_YAML_KEY_JOY0TRIMX), true);
+ JoySetTrim(yamlLoadHelper.LoadInt(SS_YAML_KEY_JOY0TRIMY), false);
+ yamlLoadHelper.LoadInt(SS_YAML_KEY_JOY1TRIMX); // dump value
+ yamlLoadHelper.LoadInt(SS_YAML_KEY_JOY1TRIMY); // dump value
+
+ yamlLoadHelper.PopMap();
}
diff --git a/source/Joystick.h b/source/Joystick.h
index 9889c2c9..517b9fcd 100644
--- a/source/Joystick.h
+++ b/source/Joystick.h
@@ -5,8 +5,6 @@ enum JOYNUM {JN_JOYSTICK0=0, JN_JOYSTICK1};
enum JOY0CHOICE {J0C_DISABLED=0, J0C_JOYSTICK1, J0C_KEYBD_CURSORS, J0C_KEYBD_NUMPAD, J0C_MOUSE, J0C_MAX};
enum JOY1CHOICE {J1C_DISABLED=0, J1C_JOYSTICK2, J1C_KEYBD_CURSORS, J1C_KEYBD_NUMPAD, J1C_MOUSE, J1C_MAX};
-extern DWORD joytype[2];
-
enum {JOYSTICK_MODE_FLOATING=0, JOYSTICK_MODE_CENTERING}; // Joystick centering control
void JoyInitialize();
@@ -21,11 +19,14 @@ BOOL JoyUsingKeyboard();
BOOL JoyUsingKeyboardCursors();
BOOL JoyUsingKeyboardNumpad();
void JoyDisableUsingMouse();
+void JoySetJoyType(UINT num, DWORD type);
+DWORD JoyGetJoyType(UINT num);
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 JoySaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+void JoyLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
BYTE __stdcall JoyReadButton(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
BYTE __stdcall JoyReadPosition(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index 2b1e1727..936eb63b 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -31,7 +31,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "AppleWin.h"
#include "Frame.h"
#include "Keyboard.h"
+#include "Pravets.h"
#include "Tape.h"
+#include "YamlHelper.h"
static bool g_bKeybBufferEnable = false;
@@ -50,7 +52,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 +161,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 +418,6 @@ static char ClipboardCurrChar(bool bIncPtr)
BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
{
- keyboardqueries++;
-
- //
-
if(g_bPasteFromClipboard)
ClipboardInit();
@@ -463,10 +452,6 @@ BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG)
{
- keyboardqueries++;
-
- //
-
if(g_bPasteFromClipboard)
ClipboardInit();
@@ -516,16 +501,33 @@ 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)
+//
+
+#define SS_YAML_KEY_LASTKEY "Last Key"
+
+static std::string KeybGetSnapshotStructName(void)
{
- keyboardqueries = pSS->keyboardqueries;
- g_nLastKey = pSS->nLastKey;
- return 0;
+ static const std::string name("Keyboard");
+ return name;
+}
+
+void KeybSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", KeybGetSnapshotStructName().c_str());
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LASTKEY, g_nLastKey);
+}
+
+void KeybLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+{
+ if (!yamlLoadHelper.GetSubMap(KeybGetSnapshotStructName()))
+ return;
+
+ g_nLastKey = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTKEY);
+
+ yamlLoadHelper.PopMap();
}
diff --git a/source/Keyboard.h b/source/Keyboard.h
index 0010b677..f79cb203 100644
--- a/source/Keyboard.h
+++ b/source/Keyboard.h
@@ -11,12 +11,12 @@ bool KeybGetShiftStatus();
bool KeybGetCapsAllowed(); //For Pravets8A/C only
void KeybUpdateCtrlShiftStatus();
BYTE KeybGetKeycode ();
-DWORD KeybGetNumQueries ();
void KeybQueueKeypress (int,BOOL);
void KeybToggleCapsLock ();
void KeybToggleP8ACapsLock ();
-DWORD KeybGetSnapshot(SS_IO_Keyboard* pSS);
-DWORD KeybSetSnapshot(SS_IO_Keyboard* pSS);
+void KeybSetSnapshot_v1(const BYTE LastKey);
+void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
BYTE __stdcall KeybReadData (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
BYTE __stdcall KeybReadFlag (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
diff --git a/source/Log.cpp b/source/Log.cpp
index e277a56c..fb419b05 100644
--- a/source/Log.cpp
+++ b/source/Log.cpp
@@ -33,13 +33,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
void LogOutput(LPCTSTR format, ...)
{
- TCHAR output[256];
+ TCHAR output[256];
- va_list args;
- va_start(args, format);
+ va_list args;
+ va_start(args, format);
- _vsntprintf(output, sizeof(output) - 1, format, args);
- OutputDebugString(output);
+ _vsntprintf(output, sizeof(output) - 1, format, args);
+ OutputDebugString(output);
}
//---------------------------------------------------------------------------
@@ -51,11 +51,11 @@ void LogFileOutput(LPCTSTR format, ...)
if (!g_fh)
return;
- TCHAR output[256];
+ TCHAR output[256];
- va_list args;
- va_start(args, format);
+ va_list args;
+ va_start(args, format);
- _vsntprintf(output, sizeof(output) - 1, format, args);
- fprintf(g_fh, output);
+ _vsntprintf(output, sizeof(output) - 1, format, args);
+ fprintf(g_fh, "%s", output);
}
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 56c36b00..5d2bcd18 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -24,6 +24,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/* Description: Memory emulation
*
* Author: Various
+ *
+ * In comments, UTA2E is an abbreviation for a reference to "Understanding the Apple //e" by James Sather
*/
#include "StdAfx.h"
@@ -42,6 +44,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "NoSlotClock.h"
#include "ParallelPrinter.h"
#include "Registry.h"
+#include "SAM.h"
#include "SerialComms.h"
#include "Speaker.h"
#include "Tape.h"
@@ -52,6 +55,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 "YamlHelper.h"
// Memory Flag
#define MF_80STORE 0x00000001
@@ -170,7 +174,7 @@ iofunction IORead[256];
iofunction IOWrite[256];
static LPVOID SlotParameters[NUM_SLOTS];
-static BOOL lastwriteram = 0;
+static BOOL lastwriteram = 0; // NB. redundant - only used in MemSetPaging(), where it's forced to 1
LPBYTE mem = NULL;
@@ -194,12 +198,12 @@ static BOOL Pravets8charmode = 0;
static CNoSlotClock g_NoSlotClock;
#ifdef RAMWORKS
-UINT g_uMaxExPages = 1; // user requested ram pages
-static LPBYTE RWpages[128]; // pointers to RW memory banks
+UINT g_uMaxExPages = 1; // user requested ram pages (default to 1 aux bank: so total = 128KB)
+UINT g_uActiveBank = 0; // 0 = aux 64K for: //e extended 80 Col card, or //c
+static LPBYTE RWpages[kMaxExMemoryBanks]; // pointers to RW memory banks
#endif
BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
-void UpdatePaging(BOOL initialize);
//=============================================================================
@@ -231,7 +235,7 @@ static BYTE __stdcall IORead_C01x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
case 0x6: return MemCheckPaging(pc, addr, bWrite, d, nCyclesLeft);
case 0x7: return MemCheckPaging(pc, addr, bWrite, d, nCyclesLeft);
case 0x8: return MemCheckPaging(pc, addr, bWrite, d, nCyclesLeft);
- case 0x9: return VideoCheckVbl( nCyclesLeft ); // NTSC cleanup
+ case 0x9: return VideoCheckVbl(nCyclesLeft);
case 0xA: return VideoCheckMode(pc, addr, bWrite, d, nCyclesLeft);
case 0xB: return VideoCheckMode(pc, addr, bWrite, d, nCyclesLeft);
case 0xC: return MemCheckPaging(pc, addr, bWrite, d, nCyclesLeft);
@@ -342,7 +346,7 @@ static BYTE __stdcall IORead_C06x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
{
static byte CurrentKestroke = 0;
CurrentKestroke = KeybGetKeycode();
- switch (addr & 0xf)
+ switch (addr & 0x7) // address bit 4 is ignored (UTA2E page 7-5)
{
//In Pravets8A/C if SETMODE (8bit character encoding) is enabled, bit6 in $C060 is 0; Else it is 1
//If (CAPS lOCK of Pravets8A/C is on or Shift is pressed) and (MODE is enabled), bit7 in $C000 is 1; Else it is 0
@@ -356,14 +360,6 @@ static BYTE __stdcall IORead_C06x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
case 0x5: return JoyReadPosition(pc, addr, bWrite, d, nCyclesLeft); //$C065 Analog input 1
case 0x6: return JoyReadPosition(pc, addr, bWrite, d, nCyclesLeft); //$C066 Analog input 2
case 0x7: return JoyReadPosition(pc, addr, bWrite, d, nCyclesLeft); //$C067 Analog input 3
- case 0x8: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0x9: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0xA: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0xB: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0xC: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0xD: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0xE: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
- case 0xF: return IO_Null(pc, addr, bWrite, d, nCyclesLeft);
}
return 0;
@@ -694,11 +690,6 @@ static void InitIoHandlers()
//
- IO_SELECT = 0;
- IO_SELECT_InternalROM = 0;
- g_eExpansionRomType = eExpRomNull;
- g_uPeripheralRomSlot = 0;
-
for (i=0; i> 8) & 0xF;
return (memshadow[0xD0+bank1page] == pMemBase+(0xC0+bank1page)*256)
? mem+offset+0x1000 // Return ptr to $Dxxx address - 'mem' has (a potentially dirty) 4K RAM BANK1 mapped in at $D000
@@ -1104,17 +1106,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);
@@ -1149,12 +1148,22 @@ void MemInitialize()
#ifdef RAMWORKS
// allocate memory for RAMWorks III - up to 8MB
- RWpages[0] = memaux;
+ g_uActiveBank = 0;
+ RWpages[g_uActiveBank] = memaux;
+
UINT i = 1;
while ((i < g_uMaxExPages) && (RWpages[i] = (LPBYTE) VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE)))
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;
@@ -1211,8 +1220,6 @@ void MemInitialize()
if (pData == NULL)
return;
- //
-
memset(pCxRomInternal,0,CxRomSize);
memset(pCxRomPeripheral,0,CxRomSize);
@@ -1224,17 +1231,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;
}
@@ -1249,15 +1262,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);
@@ -1295,11 +1320,12 @@ void MemInitialize()
{
ConfigureSoftcard(pCxRomPeripheral, 5); // $C500 : Z80 card
}
+ else
+ if (g_Slot5 == CT_SAM)
+ ConfigureSAM(pCxRomPeripheral, 5); // $C500 : Z80 card
DiskLoadRom(pCxRomPeripheral, 6); // $C600 : Disk][ f/w
HD_Load_Rom(pCxRomPeripheral, 7); // $C700 : HDD f/w
-
- MemReset();
}
inline DWORD getRandomTime()
@@ -1312,7 +1338,8 @@ inline DWORD getRandomTime()
// Called by:
// . MemInitialize()
// . ResetMachineState() eg. Power-cycle ('Apple-Go' button)
-// . Snapshot_LoadState()
+// . Snapshot_LoadState_v1()
+// . Snapshot_LoadState_v2()
void MemReset()
{
// INITIALIZE THE PAGING TABLES
@@ -1321,9 +1348,16 @@ void MemReset()
// INITIALIZE THE RAM IMAGES
ZeroMemory(memaux ,0x10000);
-
ZeroMemory(memmain,0x10000);
+ // Init the I/O ROM vars
+ IO_SELECT = 0;
+ IO_SELECT_InternalROM = 0;
+ g_eExpansionRomType = eExpRomNull;
+ g_uPeripheralRomSlot = 0;
+
+ //
+
int iByte;
// Memory is pseudo-initialized across various models of Apple ][ //e //c
@@ -1394,14 +1428,14 @@ void MemReset()
break;
case MIP_RANDOM:
- unsigned char random[ 256 + 4 ];
+ unsigned char random[ 256 ];
for( iByte = 0x0000; iByte < 0xC000; iByte += 256 )
{
for( int i = 0; i < 256; i++ )
{
clock = getRandomTime();
- random[ i+0 ] ^= (clock >> 0) & 0xFF;
- random[ i+1 ] ^= (clock >> 11) & 0xFF;
+ random[ (i+0) & 0xFF ] ^= (clock >> 0) & 0xFF;
+ random[ (i+1) & 0xFF ] ^= (clock >> 11) & 0xFF;
}
memcpy( &memmain[ iByte ], random, 256 );
@@ -1434,7 +1468,7 @@ void MemReset()
// - "BeachParty-PoacherWars-DaytonDinger-BombsAway.dsk"
// - "Dung Beetles, Ms. PacMan, Pooyan, Star Cruiser, Star Thief, Invas. Force.dsk"
memmain[ 0x620B ] = 0x0;
-
+
// https://github.com/AppleWin/AppleWin/issues/222
// MIP_PAGE_ADDRESS_LOW
// "Copy II+ v5.0.dsk"
@@ -1455,23 +1489,7 @@ void MemReset()
CpuInitialize();
//Sets Caps Lock = false (Pravets 8A/C only)
- z80_reset();
-}
-
-//===========================================================================
-
-// Call by:
-// . Soft-reset (Ctrl+Reset)
-// . Snapshot_LoadState()
-void MemResetPaging()
-{
- ResetPaging(0); // Initialize=0
- if (g_Apple2Type == A2TYPE_PRAVETS8A)
- {
- P8CAPS_ON = false;
- TapeWrite (0, 0, 0, 0 ,0);
- FrameRefreshStatus(DRAW_LEDS);
- }
+ z80_reset(); // NB. Also called above in CpuInitialize()
}
//===========================================================================
@@ -1592,7 +1610,8 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
case 0x73: // Ramworks III set aux page number
if ((value < g_uMaxExPages) && RWpages[value])
{
- memaux = RWpages[value];
+ g_uActiveBank = value;
+ memaux = RWpages[g_uActiveBank];
UpdatePaging(0); // Initialize=0
}
break;
@@ -1670,34 +1689,218 @@ 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;
-
+ // NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v1()
UpdatePaging(1); // Initialize=1
-
- return 0;
+}
+
+//
+
+#define UNIT_AUXSLOT_VER 1
+
+#define SS_YAML_KEY_MEMORYMODE "Memory Mode"
+#define SS_YAML_KEY_LASTRAMWRITE "Last RAM Write"
+#define SS_YAML_KEY_IOSELECT "IO_SELECT"
+#define SS_YAML_KEY_IOSELECT_INT "IO_SELECT_InternalROM"
+#define SS_YAML_KEY_EXPANSIONROMTYPE "Expansion ROM Type"
+#define SS_YAML_KEY_PERIPHERALROMSLOT "Peripheral ROM Slot"
+
+#define SS_YAML_VALUE_CARD_80COL "80 Column"
+#define SS_YAML_VALUE_CARD_EXTENDED80COL "Extended 80 Column"
+#define SS_YAML_VALUE_CARD_RAMWORKSIII "RamWorksIII"
+
+#define SS_YAML_KEY_NUMAUXBANKS "Num Aux Banks"
+#define SS_YAML_KEY_ACTIVEAUXBANK "Active Aux Bank"
+
+static std::string MemGetSnapshotStructName(void)
+{
+ static const std::string name("Memory");
+ return name;
+}
+
+std::string MemGetSnapshotUnitAuxSlotName(void)
+{
+ static const std::string name("Auxiliary Slot");
+ return name;
+}
+
+static std::string MemGetSnapshotMainMemStructName(void)
+{
+ static const std::string name("Main Memory");
+ return name;
+}
+
+static std::string MemGetSnapshotAuxMemStructName(void)
+{
+ static const std::string name("Auxiliary Memory Bank");
+ return name;
+}
+
+static void MemSaveSnapshotMemory(YamlSaveHelper& yamlSaveHelper, bool bIsMainMem, UINT bank=0)
+{
+ LPBYTE pMemBase = MemGetBankPtr(bank);
+
+ if (bIsMainMem)
+ {
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", MemGetSnapshotMainMemStructName().c_str());
+ yamlSaveHelper.SaveMemory(pMemBase, 64*1024);
+ }
+ else
+ {
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s%02X:\n", MemGetSnapshotAuxMemStructName().c_str(), bank-1);
+ yamlSaveHelper.SaveMemory(pMemBase, 64*1024);
+ }
+}
+
+void MemSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ // Scope so that "Memory" & "Main Memory" are at same indent level
+ {
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", MemGetSnapshotStructName().c_str());
+ yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_MEMORYMODE, memmode);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_LASTRAMWRITE, lastwriteram ? 1 : 0);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IOSELECT, IO_SELECT);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IOSELECT_INT, IO_SELECT_InternalROM);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_EXPANSIONROMTYPE, (UINT) g_eExpansionRomType);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PERIPHERALROMSLOT, g_uPeripheralRomSlot);
+ }
+
+ MemSaveSnapshotMemory(yamlSaveHelper, true);
+}
+
+bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+{
+ if (!yamlLoadHelper.GetSubMap(MemGetSnapshotStructName()))
+ return false;
+
+ SetMemMode( yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMORYMODE) );
+ lastwriteram = yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE;
+ IO_SELECT = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_IOSELECT);
+ IO_SELECT_InternalROM = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_IOSELECT_INT);
+ g_eExpansionRomType = (eExpansionRomType) yamlLoadHelper.LoadUint(SS_YAML_KEY_EXPANSIONROMTYPE);
+ g_uPeripheralRomSlot = yamlLoadHelper.LoadUint(SS_YAML_KEY_PERIPHERALROMSLOT);
+
+ yamlLoadHelper.PopMap();
+
+ //
+
+ if (!yamlLoadHelper.GetSubMap( MemGetSnapshotMainMemStructName() ))
+ throw std::string("Card: Expected key: ") + MemGetSnapshotMainMemStructName();
+
+ yamlLoadHelper.LoadMemory(memmain, _6502_MEM_END+1);
+ memset(memdirty, 0, 0x100);
+
+ yamlLoadHelper.PopMap();
+
+ //
+
+ modechanging = 0;
+ // NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
+ UpdatePaging(1); // Initialize=1 (Still needed, even with call to MemUpdatePaging() - why?)
+
+ return true;
+}
+
+void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
+{
+ if (IS_APPLE2)
+ {
+ return; // No Aux slot for AppleII
+ }
+
+ if (IS_APPLE2C)
+ {
+ _ASSERT(g_uMaxExPages == 1);
+ }
+
+ yamlSaveHelper.UnitHdr(MemGetSnapshotUnitAuxSlotName(), UNIT_AUXSLOT_VER);
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+
+ std::string card = g_uMaxExPages == 0 ? SS_YAML_VALUE_CARD_80COL : // todo: support empty slot
+ g_uMaxExPages == 1 ? SS_YAML_VALUE_CARD_EXTENDED80COL :
+ SS_YAML_VALUE_CARD_RAMWORKSIII;
+ yamlSaveHelper.SaveString(SS_YAML_KEY_CARD, card.c_str());
+ yamlSaveHelper.Save("%s: %02X # [0,1..7F] 0=no aux mem, 1=128K system, etc\n", SS_YAML_KEY_NUMAUXBANKS, g_uMaxExPages);
+ yamlSaveHelper.Save("%s: %02X # [ 0..7E] 0=memaux\n", SS_YAML_KEY_ACTIVEAUXBANK, g_uActiveBank);
+
+ for(UINT uBank = 1; uBank <= g_uMaxExPages; uBank++)
+ {
+ MemSaveSnapshotMemory(yamlSaveHelper, false, uBank);
+ }
+}
+
+bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT version)
+{
+ if (version != UNIT_AUXSLOT_VER)
+ throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Version mismatch");
+
+ // "State"
+ UINT numAuxBanks = yamlLoadHelper.LoadUint(SS_YAML_KEY_NUMAUXBANKS);
+ UINT activeAuxBank = yamlLoadHelper.LoadUint(SS_YAML_KEY_ACTIVEAUXBANK);
+
+ std::string card = yamlLoadHelper.LoadString(SS_YAML_KEY_CARD);
+ if (card == SS_YAML_VALUE_CARD_80COL)
+ {
+ if (numAuxBanks != 0 || activeAuxBank != 0)
+ throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
+ }
+ else if (card == SS_YAML_VALUE_CARD_EXTENDED80COL)
+ {
+ if (numAuxBanks != 1 || activeAuxBank != 0)
+ throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
+ }
+ else if (card == SS_YAML_VALUE_CARD_RAMWORKSIII)
+ {
+ if (numAuxBanks < 2 || numAuxBanks > 0x7F || (activeAuxBank+1) > numAuxBanks)
+ throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
+ }
+ else
+ {
+ // todo: support empty slot
+ throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Unknown card: " + card);
+ }
+
+ g_uMaxExPages = numAuxBanks;
+ g_uActiveBank = activeAuxBank;
+
+ //
+
+ for(UINT uBank = 1; uBank <= g_uMaxExPages; uBank++)
+ {
+ LPBYTE pBank = MemGetBankPtr(uBank);
+ if (!pBank)
+ {
+ pBank = RWpages[uBank-1] = (LPBYTE) VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE);
+ if (!pBank)
+ throw std::string("Card: mem alloc failed");
+ }
+
+ // "Auxiliary Memory Bankxx"
+ char szBank[3];
+ sprintf(szBank, "%02X", uBank-1);
+ std::string auxMemName = MemGetSnapshotAuxMemStructName() + szBank;
+
+ if (!yamlLoadHelper.GetSubMap(auxMemName))
+ throw std::string("Memory: Missing map name: " + auxMemName);
+
+ yamlLoadHelper.LoadMemory(pBank, _6502_MEM_END+1);
+
+ yamlLoadHelper.PopMap();
+ }
+
+ memaux = RWpages[g_uActiveBank];
+ // NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
+
+ return true;
}
diff --git a/source/Memory.h b/source/Memory.h
index 207cd1b1..3a104755 100644
--- a/source/Memory.h
+++ b/source/Memory.h
@@ -32,6 +32,7 @@ extern LPBYTE mem;
extern LPBYTE memdirty;
#ifdef RAMWORKS
+const UINT kMaxExMemoryBanks = 127; // 127 * aux mem(64K) + main mem(64K) = 8MB
extern UINT g_uMaxExPages; // user requested ram pages (from cmd line)
#endif
@@ -44,14 +45,21 @@ 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);
+std::string MemGetSnapshotUnitAuxSlotName(void);
+void MemSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
+void MemSaveSnapshotAux(class YamlSaveHelper& yamlSaveHelper);
+bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT version);
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp
index 590c7870..0143f8e9 100644
--- a/source/Mockingboard.cpp
+++ b/source/Mockingboard.cpp
@@ -77,12 +77,15 @@ 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"
#include "Memory.h"
#include "Mockingboard.h"
#include "SoundCore.h"
+#include "YamlHelper.h"
#include "AY8910.h"
#include "SSI263Phonemes.h"
@@ -114,14 +117,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define Phasor_SY6522A_Offset (1<SpeechChip.CurrentMode &= ~1; // Clear SSI263's D7 pin
- pMB->SpeechChip.DurationPhonome = nValue;
+ pMB->SpeechChip.DurationPhoneme = nValue;
g_nSSI263Device = nDevice;
@@ -632,7 +636,7 @@ static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
if(g_fh) fprintf(g_fh, "CTRL = %d, ART = 0x%02X, AMP=0x%02X\n", nValue>>7, (nValue&ARTICULATION_MASK)>>4, nValue&LITUDE_MASK);
#endif
if((pMB->SpeechChip.CtrlArtAmp & CONTROL_MASK) && !(nValue & CONTROL_MASK)) // H->L
- pMB->SpeechChip.CurrentMode = pMB->SpeechChip.DurationPhonome & DURATION_MODE_MASK;
+ pMB->SpeechChip.CurrentMode = pMB->SpeechChip.DurationPhoneme & DURATION_MODE_MASK;
pMB->SpeechChip.CtrlArtAmp = nValue;
break;
case SSI_FILFREQ:
@@ -826,7 +830,7 @@ static void MB_Update()
double fTicksSecs = (double)GetTickCount() / 1000.0;
sprintf(szDbg, "%010.3f: [MBUpdt] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X xxx\n", fTicksSecs, dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples);
OutputDebugString(szDbg);
- if (g_fh) fprintf(g_fh, szDbg);
+ if (g_fh) fprintf(g_fh, "%s", szDbg);
dwByteOffset = dwCurrentWriteCursor;
}
@@ -839,7 +843,7 @@ static void MB_Update()
double fTicksSecs = (double)GetTickCount() / 1000.0;
sprintf(szDbg, "%010.3f: [MBUpdt] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X XXX\n", fTicksSecs, dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples);
OutputDebugString(szDbg);
- if (g_fh) fprintf(g_fh, szDbg);
+ if (g_fh) fprintf(g_fh, "%s", szDbg);
dwByteOffset = dwCurrentWriteCursor;
}
@@ -1002,11 +1006,22 @@ static void SSI263_Play(unsigned int nPhoneme)
#if 1
HRESULT hr;
- if(g_nCurrentActivePhoneme >= 0)
{
- // A write to DURPHON before previous phoneme has completed
- g_bStopPhoneme = true;
- hr = SSI263Voice[g_nCurrentActivePhoneme].lpDSBvoice->Stop();
+ int nCurrPhoneme = g_nCurrentActivePhoneme; // local copy in case SSI263Thread sets it to -1
+ if (nCurrPhoneme >= 0)
+ {
+ // A write to DURPHON before previous phoneme has completed
+ g_bStopPhoneme = true;
+ hr = SSI263Voice[nCurrPhoneme].lpDSBvoice->Stop();
+
+ // Busy-wait until ACK from SSI263Thread
+ // . required to avoid data-race
+ while ( g_bStopPhoneme && // wait for SSI263Thread to ACK the lpDSBVoice->Stop()
+ g_nCurrentActivePhoneme >= 0) // wait for SSI263Thread to get end of sample event
+ ;
+
+ g_bStopPhoneme = false;
+ }
}
g_nCurrentActivePhoneme = nPhoneme;
@@ -1371,7 +1386,8 @@ void MB_Initialize()
// NB. Called when /g_fCurrentCLK6502/ changes
void MB_Reinitialize()
{
- AY8910_InitClock((int)g_fCurrentCLK6502);
+ AY8910_InitClock((int)g_fCurrentCLK6502); // todo: account for g_PhasorClockScaleFactor?
+ // NB. Other calls to AY8910_InitClock() use the constant CLK_6502
}
//-----------------------------------------------------------------------------
@@ -1403,9 +1419,10 @@ static void ResetState()
//g_bMBAvailable = false;
- //g_SoundcardType = CT_Empty;
- //g_bPhasorEnable = false;
+// g_SoundcardType = CT_Empty; // Don't uncomment, else _ASSERT will fire in MB_Read() after an F2->MB_Reset()
+// g_bPhasorEnable = false;
g_nPhasorMode = 0;
+ g_PhasorClockScaleFactor = 1;
}
void MB_Reset()
@@ -1553,9 +1570,9 @@ static BYTE __stdcall PhasorIO(WORD PC, WORD nAddr, BYTE bWrite, BYTE nValue, UL
if(g_nPhasorMode < 2)
g_nPhasorMode = nAddr & 1;
- double fCLK = (nAddr & 4) ? CLK_6502*2 : CLK_6502;
+ g_PhasorClockScaleFactor = (nAddr & 4) ? 2 : 1;
- AY8910_InitClock((int)fCLK);
+ AY8910_InitClock((int)(CLK_6502 * g_PhasorClockScaleFactor));
return MemReadFloatingBus(nCyclesLeft);
}
@@ -1761,45 +1778,48 @@ 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_v1* 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_v1);
+ 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;
SY6522_AY8910* pMB = &g_MB[nDeviceNum];
- for(UINT i=0; iUnit[i].RegsSY6522, &pMB->sy6522, sizeof(SY6522));
memcpy(&pSS->Unit[i].RegsAY8910, AY8910_GetRegsPtr(nDeviceNum), 16);
memcpy(&pSS->Unit[i].RegsSSI263, &pMB->SpeechChip, sizeof(SSI263A));
pSS->Unit[i].nAYCurrentRegister = pMB->nAYCurrentRegister;
+ pSS->Unit[i].bTimer1IrqPending = false;
+ pSS->Unit[i].bTimer2IrqPending = false;
+ pSS->Unit[i].bSpeechIrqPending = false;
nDeviceNum++;
pMB++;
}
-
- return 0;
}
-DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD /*dwSlot*/)
+int MB_SetSnapshot_v1(const SS_CARD_MOCKINGBOARD_v1* 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];
g_nSSI263Device = 0;
g_nCurrentActivePhoneme = -1;
- for(UINT i=0; isy6522, &pSS->Unit[i].RegsSY6522, sizeof(SY6522));
memcpy(AY8910_GetRegsPtr(nDeviceNum), &pSS->Unit[i].RegsAY8910, 16);
@@ -1814,7 +1834,7 @@ DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD /*dwSlot*/)
// FIX THIS:
// . Speech chip could be Votrax instead
// . Is this IRQ compatible with Phasor?
- if(pMB->SpeechChip.DurationPhonome)
+ if(pMB->SpeechChip.DurationPhoneme)
{
g_nSSI263Device = nDeviceNum;
@@ -1832,3 +1852,357 @@ DWORD MB_SetSnapshot(SS_CARD_MOCKINGBOARD* pSS, DWORD /*dwSlot*/)
return 0;
}
+
+//===========================================================================
+
+static UINT DoWriteFile(const HANDLE hFile, const void* const pData, const UINT Length)
+{
+ DWORD dwBytesWritten;
+ BOOL bRes = WriteFile( hFile,
+ pData,
+ Length,
+ &dwBytesWritten,
+ NULL);
+
+ if(!bRes || (dwBytesWritten != Length))
+ {
+ //dwError = GetLastError();
+ throw std::string("Card: save error");
+ }
+
+ return dwBytesWritten;
+}
+
+static UINT DoReadFile(const HANDLE hFile, void* const pData, const UINT Length)
+{
+ DWORD dwBytesRead;
+ BOOL bRes = ReadFile( hFile,
+ pData,
+ Length,
+ &dwBytesRead,
+ NULL);
+
+ if (dwBytesRead != Length)
+ throw std::string("Card: file corrupt");
+
+ return dwBytesRead;
+}
+
+//===========================================================================
+
+const UINT NUM_MB_UNITS = 2;
+const UINT NUM_PHASOR_UNITS = 2;
+
+#define SS_YAML_KEY_MB_UNIT "Unit"
+#define SS_YAML_KEY_SY6522 "SY6522"
+#define SS_YAML_KEY_SY6522_REG_ORB "ORB"
+#define SS_YAML_KEY_SY6522_REG_ORA "ORA"
+#define SS_YAML_KEY_SY6522_REG_DDRB "DDRB"
+#define SS_YAML_KEY_SY6522_REG_DDRA "DDRA"
+#define SS_YAML_KEY_SY6522_REG_T1_COUNTER "Timer1 Counter"
+#define SS_YAML_KEY_SY6522_REG_T1_LATCH "Timer1 Latch"
+#define SS_YAML_KEY_SY6522_REG_T2_COUNTER "Timer2 Counter"
+#define SS_YAML_KEY_SY6522_REG_T2_LATCH "Timer2 Latch"
+#define SS_YAML_KEY_SY6522_REG_SERIAL_SHIFT "Serial Shift"
+#define SS_YAML_KEY_SY6522_REG_ACR "ACR"
+#define SS_YAML_KEY_SY6522_REG_PCR "PCR"
+#define SS_YAML_KEY_SY6522_REG_IFR "IFR"
+#define SS_YAML_KEY_SY6522_REG_IER "IER"
+#define SS_YAML_KEY_SSI263 "SSI263"
+#define SS_YAML_KEY_SSI263_REG_DUR_PHON "Duration / Phoneme"
+#define SS_YAML_KEY_SSI263_REG_INF "Inflection"
+#define SS_YAML_KEY_SSI263_REG_RATE_INF "Rate / Inflection"
+#define SS_YAML_KEY_SSI263_REG_CTRL_ART_AMP "Control / Articulation / Amplitude"
+#define SS_YAML_KEY_SSI263_REG_FILTER_FREQ "Filter Frequency"
+#define SS_YAML_KEY_SSI263_REG_CURRENT_MODE "Current Mode"
+#define SS_YAML_KEY_AY_CURR_REG "AY Current Register"
+#define SS_YAML_KEY_TIMER1_IRQ "Timer1 IRQ Pending"
+#define SS_YAML_KEY_TIMER2_IRQ "Timer2 IRQ Pending"
+#define SS_YAML_KEY_SPEECH_IRQ "Speech IRQ Pending"
+
+#define SS_YAML_KEY_PHASOR_UNIT "Unit"
+#define SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR "Clock Scale Factor"
+#define SS_YAML_KEY_PHASOR_MODE "Mode"
+
+std::string MB_GetSnapshotCardName(void)
+{
+ static const std::string name("Mockingboard C");
+ return name;
+}
+
+std::string Phasor_GetSnapshotCardName(void)
+{
+ static const std::string name("Phasor");
+ return name;
+}
+
+static void SaveSnapshotSY6522(YamlSaveHelper& yamlSaveHelper, SY6522& sy6522)
+{
+ YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", SS_YAML_KEY_SY6522);
+
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_ORB, sy6522.ORB);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_ORA, sy6522.ORA);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_DDRB, sy6522.DDRB);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_DDRA, sy6522.DDRA);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_SY6522_REG_T1_COUNTER, sy6522.TIMER1_COUNTER.w);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_SY6522_REG_T1_LATCH, sy6522.TIMER1_LATCH.w);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_SY6522_REG_T2_COUNTER, sy6522.TIMER2_COUNTER.w);
+ yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_SY6522_REG_T2_LATCH, sy6522.TIMER2_LATCH.w);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_SERIAL_SHIFT, sy6522.SERIAL_SHIFT);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_ACR, sy6522.ACR);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_PCR, sy6522.PCR);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_IFR, sy6522.IFR);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SY6522_REG_IER, sy6522.IER);
+ // NB. No need to write ORA_NO_HS, since same data as ORA, just without handshake
+}
+
+static void SaveSnapshotSSI263(YamlSaveHelper& yamlSaveHelper, SSI263A& ssi263)
+{
+ YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", SS_YAML_KEY_SSI263);
+
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_DUR_PHON, ssi263.DurationPhoneme);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_INF, ssi263.Inflection);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_RATE_INF, ssi263.RateInflection);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_CTRL_ART_AMP, ssi263.CtrlArtAmp);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_FILTER_FREQ, ssi263.FilterFreq);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_SSI263_REG_CURRENT_MODE, ssi263.CurrentMode);
+}
+
+void MB_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
+{
+ const UINT nMbCardNum = uSlot - SLOT4;
+ UINT nDeviceNum = nMbCardNum*2;
+ SY6522_AY8910* pMB = &g_MB[nDeviceNum];
+
+ YamlSaveHelper::Slot slot(yamlSaveHelper, MB_GetSnapshotCardName(), uSlot, 1); // fixme: object should be just 1 Mockingboard card & it will know its slot
+
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+
+ for(UINT i=0; isy6522);
+ AY8910_SaveSnapshot(yamlSaveHelper, nDeviceNum, std::string(""));
+ SaveSnapshotSSI263(yamlSaveHelper, pMB->SpeechChip);
+
+ yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_AY_CURR_REG, pMB->nAYCurrentRegister);
+ yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER1_IRQ, "false");
+ yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER2_IRQ, "false");
+ yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_SPEECH_IRQ, "false");
+
+ nDeviceNum++;
+ pMB++;
+ }
+}
+
+static void LoadSnapshotSY6522(YamlLoadHelper& yamlLoadHelper, SY6522& sy6522)
+{
+ if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_SY6522))
+ throw std::string("Card: Expected key: ") + std::string(SS_YAML_KEY_SY6522);
+
+ sy6522.ORB = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_ORB);
+ sy6522.ORA = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_ORA);
+ sy6522.DDRB = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_DDRB);
+ sy6522.DDRA = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_DDRA);
+ sy6522.TIMER1_COUNTER.w = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_T1_COUNTER);
+ sy6522.TIMER1_LATCH.w = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_T1_LATCH);
+ sy6522.TIMER2_COUNTER.w = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_T2_COUNTER);
+ sy6522.TIMER2_LATCH.w = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_T2_LATCH);
+ sy6522.SERIAL_SHIFT = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_SERIAL_SHIFT);
+ sy6522.ACR = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_ACR);
+ sy6522.PCR = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_PCR);
+ sy6522.IFR = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_IFR);
+ sy6522.IER = yamlLoadHelper.LoadUint(SS_YAML_KEY_SY6522_REG_IER);
+ sy6522.ORA_NO_HS = 0; // Not saved
+
+ yamlLoadHelper.PopMap();
+}
+
+static void LoadSnapshotSSI263(YamlLoadHelper& yamlLoadHelper, SSI263A& ssi263)
+{
+ if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_SSI263))
+ throw std::string("Card: Expected key: ") + std::string(SS_YAML_KEY_SSI263);
+
+ ssi263.DurationPhoneme = yamlLoadHelper.LoadUint(SS_YAML_KEY_SSI263_REG_DUR_PHON);
+ ssi263.Inflection = yamlLoadHelper.LoadUint(SS_YAML_KEY_SSI263_REG_INF);
+ ssi263.RateInflection = yamlLoadHelper.LoadUint(SS_YAML_KEY_SSI263_REG_RATE_INF);
+ ssi263.CtrlArtAmp = yamlLoadHelper.LoadUint(SS_YAML_KEY_SSI263_REG_CTRL_ART_AMP);
+ ssi263.FilterFreq = yamlLoadHelper.LoadUint(SS_YAML_KEY_SSI263_REG_FILTER_FREQ);
+ ssi263.CurrentMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_SSI263_REG_CURRENT_MODE);
+
+ yamlLoadHelper.PopMap();
+}
+
+bool MB_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != 4 && slot != 5) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ AY8910UpdateSetCycles();
+
+ const UINT nMbCardNum = slot - SLOT4;
+ UINT nDeviceNum = nMbCardNum*2;
+ SY6522_AY8910* pMB = &g_MB[nDeviceNum];
+
+ g_nSSI263Device = 0;
+ g_nCurrentActivePhoneme = -1;
+
+ for(UINT i=0; isy6522);
+ AY8910_LoadSnapshot(yamlLoadHelper, nDeviceNum, std::string(""));
+ LoadSnapshotSSI263(yamlLoadHelper, pMB->SpeechChip);
+
+ pMB->nAYCurrentRegister = yamlLoadHelper.LoadUint(SS_YAML_KEY_AY_CURR_REG);
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER1_IRQ); // Consume
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_IRQ); // Consume
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_SPEECH_IRQ); // Consume
+
+ yamlLoadHelper.PopMap();
+
+ //
+
+ 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.DurationPhoneme)
+ {
+ 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++;
+ }
+
+ AY8910_InitClock((int)CLK_6502);
+
+ // Setup in MB_InitializeIO() -> MB_SetSoundcardType()
+ g_SoundcardType = CT_Empty;
+ g_bPhasorEnable = false;
+
+ return true;
+}
+
+void Phasor_SaveSnapshot(YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
+{
+ if (uSlot != 4)
+ throw std::string("Card: Phasor only supported in slot-4");
+
+ UINT nDeviceNum = 0;
+ SY6522_AY8910* pMB = &g_MB[0]; // fixme: Phasor uses MB's slot4(2x6522), slot4(2xSSI263), but slot4+5(4xAY8910)
+
+ YamlSaveHelper::Slot slot(yamlSaveHelper, Phasor_GetSnapshotCardName(), uSlot, 1); // fixme: object should be just 1 Mockingboard card & it will know its slot
+
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR, g_PhasorClockScaleFactor);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASOR_MODE, g_nPhasorMode);
+
+ for(UINT i=0; isy6522);
+ AY8910_SaveSnapshot(yamlSaveHelper, nDeviceNum+0, std::string("-A"));
+ AY8910_SaveSnapshot(yamlSaveHelper, nDeviceNum+1, std::string("-B"));
+ SaveSnapshotSSI263(yamlSaveHelper, pMB->SpeechChip);
+
+ yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_AY_CURR_REG, pMB->nAYCurrentRegister);
+ yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER1_IRQ, "false");
+ yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_TIMER2_IRQ, "false");
+ yamlSaveHelper.Save("%s: %s # Not supported\n", SS_YAML_KEY_SPEECH_IRQ, "false");
+
+ nDeviceNum += 2;
+ pMB++;
+ }
+}
+
+bool Phasor_LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != 4) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ g_PhasorClockScaleFactor = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_CLOCK_SCALE_FACTOR);
+ g_nPhasorMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASOR_MODE);
+
+ AY8910UpdateSetCycles();
+
+ UINT nDeviceNum = 0;
+ SY6522_AY8910* pMB = &g_MB[0];
+
+ g_nSSI263Device = 0;
+ g_nCurrentActivePhoneme = -1;
+
+ for(UINT i=0; isy6522);
+ AY8910_LoadSnapshot(yamlLoadHelper, nDeviceNum+0, std::string("-A"));
+ AY8910_LoadSnapshot(yamlLoadHelper, nDeviceNum+1, std::string("-B"));
+ LoadSnapshotSSI263(yamlLoadHelper, pMB->SpeechChip);
+
+ pMB->nAYCurrentRegister = yamlLoadHelper.LoadUint(SS_YAML_KEY_AY_CURR_REG);
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER1_IRQ); // Consume
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_TIMER2_IRQ); // Consume
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_SPEECH_IRQ); // Consume
+
+ yamlLoadHelper.PopMap();
+
+ //
+
+ 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.DurationPhoneme)
+ {
+ 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 += 2;
+ pMB++;
+ }
+
+ AY8910_InitClock((int)(CLK_6502 * g_PhasorClockScaleFactor));
+
+ // Setup in MB_InitializeIO() -> MB_SetSoundcardType()
+ g_SoundcardType = CT_Empty;
+ g_bPhasorEnable = false;
+
+ return true;
+}
diff --git a/source/Mockingboard.h b/source/Mockingboard.h
index edd337b8..901a9e41 100644
--- a/source/Mockingboard.h
+++ b/source/Mockingboard.h
@@ -22,5 +22,13 @@ 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_v1* const pSS, const DWORD dwSlot); // For debugger
+int MB_SetSnapshot_v1(const struct SS_CARD_MOCKINGBOARD_v1* const pSS, const DWORD dwSlot);
+std::string MB_GetSnapshotCardName(void);
+void MB_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
+bool MB_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+
+std::string Phasor_GetSnapshotCardName(void);
+void Phasor_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
+bool Phasor_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
diff --git a/source/MouseInterface.cpp b/source/MouseInterface.cpp
index 0805e3ff..34b25788 100644
--- a/source/MouseInterface.cpp
+++ b/source/MouseInterface.cpp
@@ -41,7 +41,7 @@ Etc.
#include "stdafx.h"
-#include "Structs.h"
+#include "SaveState_Structs_common.h"
#include "Common.h"
#include "CPU.h"
@@ -50,6 +50,7 @@ Etc.
#include "Memory.h"
#include "MouseInterface.h"
#include "SoundCore.h" // SAFE_RELEASE()
+#include "YamlHelper.h"
#include "..\resource\resource.h"
@@ -210,7 +211,7 @@ void CMouseInterface::Reset()
m_iMinY = 0;
m_iMaxY = 1023;
- m_bButtons[0] = m_bButtons[1] = FALSE;
+ m_bButtons[0] = m_bButtons[1] = false;
//
@@ -447,15 +448,13 @@ void CMouseInterface::OnMouseEvent(bool bEventVBL)
if ( !( m_byMode & MODE_MOUSE_ON ) ) // Mouse Off
return;
- BOOL bBtn0 = m_bButtons[0];
- BOOL bBtn1 = m_bButtons[1];
if ( m_nX != m_iX || m_nY != m_iY )
{
byState |= STAT_INT_MOVEMENT|STAT_MOVEMENT_SINCE_READMOUSE; // X/Y moved since last READMOUSE | Movement interrupt
m_byState |= STAT_MOVEMENT_SINCE_READMOUSE; // [TC] Used by CopyII+9.1 and ProTERM3.1
}
- if ( m_bBtn0 != bBtn0 || m_bBtn1 != bBtn1 )
+ if ( m_bBtn0 != m_bButtons[0] || m_bBtn1 != m_bButtons[1] )
byState |= STAT_INT_BUTTON; // Button 0/1 interrupt
if ( bEventVBL )
byState |= STAT_INT_VBL;
@@ -495,8 +494,8 @@ void CMouseInterface::Clear()
m_byState = 0;
m_nX = 0;
m_nY = 0;
- m_bBtn0 = 0;
- m_bBtn1 = 0;
+ m_bBtn0 = false;
+ m_bBtn1 = false;
SetPositionAbs( 0, 0 );
// CpuIrqDeassert(IS_MOUSE);
@@ -594,10 +593,168 @@ void CMouseInterface::SetPositionRel(long dX, long dY, int* pOutOfBoundsX, int*
void CMouseInterface::SetButton(eBUTTON Button, eBUTTONSTATE State)
{
- m_bButtons[Button]= (State == BUTTON_DOWN) ? TRUE : FALSE;
+ m_bButtons[Button] = (State == BUTTON_DOWN);
OnMouseEvent();
}
+#define SS_YAML_VALUE_CARD_MOUSE "Mouse Card"
+
+#define SS_YAML_KEY_MC6821 "MC6821"
+#define SS_YAML_KEY_PRA "PRA"
+#define SS_YAML_KEY_DDRA "DDRA"
+#define SS_YAML_KEY_CRA "CRA"
+#define SS_YAML_KEY_PRB "PRB"
+#define SS_YAML_KEY_DDRB "DDRB"
+#define SS_YAML_KEY_CRB "CRB"
+#define SS_YAML_KEY_IA "IA"
+#define SS_YAML_KEY_IB "IB"
+
+#define SS_YAML_KEY_DATALEN "DataLen"
+#define SS_YAML_KEY_MODE "Mode"
+#define SS_YAML_KEY_6821B "6821B"
+#define SS_YAML_KEY_6821A "6821A"
+#define SS_YAML_KEY_BUFF "Buffer"
+#define SS_YAML_KEY_BUFFPOS "Buffer Position"
+#define SS_YAML_KEY_MOUSESTATE "State"
+#define SS_YAML_KEY_X "X"
+#define SS_YAML_KEY_Y "Y"
+#define SS_YAML_KEY_BTN0 "Btn0"
+#define SS_YAML_KEY_BTN1 "Btn1"
+#define SS_YAML_KEY_VBL "VBL"
+#define SS_YAML_KEY_IX "iX"
+#define SS_YAML_KEY_IMINX "iMinX"
+#define SS_YAML_KEY_IMAXX "iMaxX"
+#define SS_YAML_KEY_IY "iY"
+#define SS_YAML_KEY_IMINY "iMinY"
+#define SS_YAML_KEY_IMAXY "iMaxY"
+#define SS_YAML_KEY_BUTTON0 "Button0"
+#define SS_YAML_KEY_BUTTON1 "Button1"
+#define SS_YAML_KEY_ENABLED "Enabled"
+
+std::string CMouseInterface::GetSnapshotCardName(void)
+{
+ static const std::string name(SS_YAML_VALUE_CARD_MOUSE);
+ return name;
+}
+
+void CMouseInterface::SaveSnapshotMC6821(YamlSaveHelper& yamlSaveHelper, std::string key)
+{
+ mc6821_t mc6821;
+ BYTE byIA;
+ BYTE byIB;
+
+ m_6821.Get6821(mc6821, byIA, byIB);
+
+ YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", key.c_str());
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PRA, mc6821.pra);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_DDRA, mc6821.ddra);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_CRA, mc6821.cra);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PRB, mc6821.prb);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_DDRB, mc6821.ddrb);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_CRB, mc6821.crb);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IA, byIA);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IB, byIB);
+}
+
+void CMouseInterface::SaveSnapshot(class YamlSaveHelper& yamlSaveHelper)
+{
+ if (!m_bActive)
+ return;
+
+ YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), m_uSlot, 1);
+
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+ SaveSnapshotMC6821(yamlSaveHelper, SS_YAML_KEY_MC6821);
+ yamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_DATALEN, m_nDataLen);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_MODE, m_byMode);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_6821B, m_by6821B);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_6821A, m_by6821A);
+
+ // New label
+ {
+ YamlSaveHelper::Label buffer(yamlSaveHelper, "%s:\n", SS_YAML_KEY_BUFF);
+ yamlSaveHelper.SaveMemory(m_byBuff, sizeof(m_byBuff));
+ }
+
+ yamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_BUFFPOS, m_nBuffPos);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_MOUSESTATE, m_byState);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_X, m_nX);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_Y, m_nY);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_BTN0, m_bBtn0);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_BTN1, m_bBtn1);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_VBL, m_bVBL);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IX, m_iX);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IMINX, m_iMinX);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IMAXX, m_iMaxX);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IY, m_iY);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IMINY, m_iMinY);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IMAXY, m_iMaxY);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_BUTTON0, m_bButtons[0]);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_BUTTON1, m_bButtons[1]);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_ENABLED, m_bEnabled);
+}
+
+void CMouseInterface::LoadSnapshotMC6821(YamlLoadHelper& yamlLoadHelper, std::string key)
+{
+ if (!yamlLoadHelper.GetSubMap(key))
+ throw std::string("Card: Expected key: ") + key;
+
+ mc6821_t mc6821;
+ mc6821.pra = yamlLoadHelper.LoadUint(SS_YAML_KEY_PRA);
+ mc6821.ddra = yamlLoadHelper.LoadUint(SS_YAML_KEY_DDRA);
+ mc6821.cra = yamlLoadHelper.LoadUint(SS_YAML_KEY_CRA);
+ mc6821.prb = yamlLoadHelper.LoadUint(SS_YAML_KEY_PRB);
+ mc6821.ddrb = yamlLoadHelper.LoadUint(SS_YAML_KEY_DDRB);
+ mc6821.crb = yamlLoadHelper.LoadUint(SS_YAML_KEY_CRB);
+
+ BYTE byIA = yamlLoadHelper.LoadUint(SS_YAML_KEY_IA);
+ BYTE byIB = yamlLoadHelper.LoadUint(SS_YAML_KEY_IB);
+
+ m_6821.Set6821(mc6821, byIA, byIB);
+
+ yamlLoadHelper.PopMap();
+}
+
+bool CMouseInterface::LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != 4) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ LoadSnapshotMC6821(yamlLoadHelper, SS_YAML_KEY_MC6821);
+
+ m_nDataLen = yamlLoadHelper.LoadUint(SS_YAML_KEY_DATALEN);
+ m_byMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_MODE);
+ m_by6821B = yamlLoadHelper.LoadUint(SS_YAML_KEY_6821B);
+ m_by6821A = yamlLoadHelper.LoadUint(SS_YAML_KEY_6821A);
+
+ if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_BUFF))
+ throw std::string("Card: Expected key: "SS_YAML_KEY_BUFF);
+ yamlLoadHelper.LoadMemory(m_byBuff, sizeof(m_byBuff));
+ yamlLoadHelper.PopMap();
+
+ m_nBuffPos = yamlLoadHelper.LoadUint(SS_YAML_KEY_BUFFPOS);
+ m_byState = yamlLoadHelper.LoadUint(SS_YAML_KEY_MOUSESTATE);
+ m_nX = yamlLoadHelper.LoadInt(SS_YAML_KEY_X);
+ m_nY = yamlLoadHelper.LoadInt(SS_YAML_KEY_Y);
+ m_bBtn0 = yamlLoadHelper.LoadBool(SS_YAML_KEY_BTN0);
+ m_bBtn1 = yamlLoadHelper.LoadBool(SS_YAML_KEY_BTN1);
+ m_bVBL = yamlLoadHelper.LoadBool(SS_YAML_KEY_VBL);
+ m_iX = yamlLoadHelper.LoadInt(SS_YAML_KEY_IX);
+ m_iMinX = yamlLoadHelper.LoadInt(SS_YAML_KEY_IMINX);
+ m_iMaxX = yamlLoadHelper.LoadInt(SS_YAML_KEY_IMAXX);
+ m_iY = yamlLoadHelper.LoadInt(SS_YAML_KEY_IY);
+ m_iMinY = yamlLoadHelper.LoadInt(SS_YAML_KEY_IMINY);
+ m_iMaxY = yamlLoadHelper.LoadInt(SS_YAML_KEY_IMAXY);
+ m_bButtons[0] = yamlLoadHelper.LoadBool(SS_YAML_KEY_BUTTON0);
+ m_bButtons[1] = yamlLoadHelper.LoadBool(SS_YAML_KEY_BUTTON1);
+ m_bEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_ENABLED); // MemInitializeIO() calls Initialize() which sets true
+
+ return true;
+}
+
//=============================================================================
// DirectInput interface
//=============================================================================
@@ -819,4 +976,4 @@ namespace DIMouse
return S_OK;
}
-}; // namespace DIMouse
\ No newline at end of file
+}; // namespace DIMouse
diff --git a/source/MouseInterface.h b/source/MouseInterface.h
index 6c13a4f2..2b48f0f0 100644
--- a/source/MouseInterface.h
+++ b/source/MouseInterface.h
@@ -12,15 +12,14 @@ 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);
void SetPositionRel(long dx, long dy, int* pOutOfBoundsX, int* pOutOfBoundsY);
void SetButton(eBUTTON Button, eBUTTONSTATE State);
bool IsActive() { return m_bActive; }
- bool IsEnabled() { return m_bEnabled; }
- bool IsActiveAndEnabled() { return IsActive() && IsEnabled(); }
+ bool IsEnabled() { return m_bEnabled; } // NB. m_bEnabled == true implies that m_bActive == true
+ bool IsActiveAndEnabled() { return IsActive() && IsEnabled(); } // todo: just use IsEnabled()
void SetEnabled(bool bEnabled) { m_bEnabled = bEnabled; }
void SetVBlank(bool bVBL);
void GetXY(int& iX, int& iMinX, int& iMaxX, int& iY, int& iMinY, int& iMaxY)
@@ -38,7 +37,12 @@ public:
m_iY = iY;
}
+ std::string GetSnapshotCardName(void);
+ void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+ bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+
protected:
+ void SetSlotRom();
void On6821_A(BYTE byData);
void On6821_B(BYTE byData);
void OnCommand();
@@ -55,6 +59,8 @@ protected:
void SetClampX(int iMinX, int iMaxX);
void SetClampY(int iMinY, int iMaxY);
+ void SaveSnapshotMC6821(class YamlSaveHelper& yamlSaveHelper, std::string key);
+ void LoadSnapshotMC6821(class YamlLoadHelper& yamlLoadHelper, std::string key);
C6821 m_6821;
@@ -69,8 +75,8 @@ protected:
BYTE m_byState;
int m_nX;
int m_nY;
- BOOL m_bBtn0;
- BOOL m_bBtn1;
+ bool m_bBtn0;
+ bool m_bBtn1;
bool m_bVBL;
@@ -83,12 +89,14 @@ protected:
int m_iMinY;
int m_iMaxY;
- BOOL m_bButtons[2];
+ bool m_bButtons[2];
//
+ // todo: remove m_bActive:
+ // - instantiate CMouseInterface object when active (and delete when inactive)
bool m_bActive; // Mouse h/w is active within the Apple][ VM
- bool m_bEnabled; // Windows' mouse events get passed to Apple]['s mouse h/w
+ bool m_bEnabled; // Windows' mouse events get passed to Apple]['s mouse h/w (m_bEnabled == true implies that m_bActive == true)
LPBYTE m_pSlotRom;
UINT m_uSlot;
};
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index 5894c4e2..44bcc42c 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -99,7 +99,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Globals (Public) ___________________________________________________
uint16_t g_nVideoClockVert = 0; // 9-bit: VC VB VA V5 V4 V3 V2 V1 V0 = 0 .. 262
- uint16_t g_nVideoClockHorz = 0; // 6-bit: H5 H4 H3 H2 H1 H0 = 0 .. 64, 25 >= visible
+ uint16_t g_nVideoClockHorz = 0; // 6-bit: H5 H4 H3 H2 H1 H0 = 0 .. 64, 25 >= visible (NB. final hpos is 2 cycles long, so a line is 65 cycles)
// Globals (Private) __________________________________________________
static int g_nVideoCharSet = 0;
@@ -1449,7 +1449,7 @@ void NTSC_SetVideoMode( int bVideoModeFlags )
g_aHorzClockVideoMode[ h ] = bVideoModeFlags;
g_nVideoMixed = bVideoModeFlags & VF_MIXED;
- g_nVideoCharSet = g_nAltCharSetOffset != 0;
+ g_nVideoCharSet = VideoGetSWAltCharSet() ? 1 : 0;
g_nTextPage = 1;
g_nHiresPage = 1;
@@ -1654,19 +1654,21 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
}
//===========================================================================
-void NTSC_VideoInitAppleType ()
+void NTSC_VideoInitAppleType ( DWORD cyclesThisFrame )
{
int model = g_Apple2Type;
- // anything other than low bit set means not II/II+
+ // anything other than low bit set means not II/II+ (TC: include Pravets machines too?)
if (model & 0xFFFE)
g_pHorzClockOffset = APPLE_IIE_HORZ_CLOCK_OFFSET;
else
g_pHorzClockOffset = APPLE_IIP_HORZ_CLOCK_OFFSET;
- g_nVideoClockVert = 0;
- g_nVideoClockHorz = 0;
-
+ // TC: Move these to a better place (as init'ing these 2 vars is nothing to do with g_Apple2Type)
+ _ASSERT(cyclesThisFrame < VIDEO_SCANNER_6502_CYCLES);
+ if (cyclesThisFrame >= VIDEO_SCANNER_6502_CYCLES) cyclesThisFrame = 0; // error
+ g_nVideoClockVert = (uint16_t) (cyclesThisFrame / VIDEO_SCANNER_MAX_HORZ);
+ g_nVideoClockHorz = cyclesThisFrame % VIDEO_SCANNER_MAX_HORZ;
}
//===========================================================================
diff --git a/source/NTSC.h b/source/NTSC.h
index 3c53caf4..a6f3adec 100644
--- a/source/NTSC.h
+++ b/source/NTSC.h
@@ -13,7 +13,7 @@
extern uint32_t*NTSC_VideoGetChromaTable( bool bHueTypeMonochrome, bool bMonitorTypeColorTV );
extern uint16_t NTSC_VideoGetScannerAddress( unsigned long cycles6502 );
extern void NTSC_VideoInit( uint8_t *pFramebuffer );
- extern void NTSC_VideoInitAppleType ();
+ extern void NTSC_VideoInitAppleType ( DWORD cyclesThisFrame );
extern void NTSC_VideoInitChroma();
extern bool NTSC_VideoIsVbl();
extern void NTSC_VideoUpdateCycles( long cycles6502 );
diff --git a/source/ParallelPrinter.cpp b/source/ParallelPrinter.cpp
index 2ef531a6..f17609db 100644
--- a/source/ParallelPrinter.cpp
+++ b/source/ParallelPrinter.cpp
@@ -32,22 +32,24 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Memory.h"
#include "ParallelPrinter.h"
#include "Registry.h"
+#include "YamlHelper.h"
#include "..\resource\resource.h"
static DWORD inactivity = 0;
+static unsigned int g_PrinterIdleLimit = 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 +81,8 @@ VOID PrintLoadRom(LPBYTE pCxRomPeripheral, const UINT uSlot)
//
RegisterIoHandler(uSlot, PrintStatus, PrintTransmit, NULL, NULL, NULL, NULL);
+
+ g_uSlot = uSlot;
}
//===========================================================================
@@ -242,11 +246,79 @@ void Printer_SetFilename(char* prtFilename)
unsigned int Printer_GetIdleLimit()
{
- return g_iPrinterIdleLimit;
+ return g_PrinterIdleLimit;
}
-//unsigned int
void Printer_SetIdleLimit(unsigned int Duration)
{
- g_iPrinterIdleLimit = Duration;
+ g_PrinterIdleLimit = Duration;
+}
+
+//===========================================================================
+
+#define SS_YAML_VALUE_CARD_PRINTER "Generic Printer"
+
+#define SS_YAML_KEY_INACTIVITY "Inactivity"
+#define SS_YAML_KEY_IDLELIMIT "Printer Idle Limit"
+#define SS_YAML_KEY_FILENAME "Print Filename"
+#define SS_YAML_KEY_FILEOPEN "Is File Open"
+#define SS_YAML_KEY_DUMPTOPRINTER "Dump To Printer"
+#define SS_YAML_KEY_CONVERTENCODING "Convert Encoding"
+#define SS_YAML_KEY_FILTERUNPRINTABLE "Filter Unprintable"
+#define SS_YAML_KEY_APPEND "Printer Append"
+#define SS_YAML_KEY_DUMPTOREALPRINTER "Enable Dump To Real Printer"
+
+std::string Printer_GetSnapshotCardName(void)
+{
+ static const std::string name(SS_YAML_VALUE_CARD_PRINTER);
+ return name;
+}
+
+void Printer_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper)
+{
+ YamlSaveHelper::Slot slot(yamlSaveHelper, Printer_GetSnapshotCardName(), g_uSlot, 1);
+
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_INACTIVITY, inactivity);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_IDLELIMIT, g_PrinterIdleLimit);
+ yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, g_szPrintFilename);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_FILEOPEN, (file != NULL) ? true : false);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_DUMPTOPRINTER, g_bDumpToPrinter);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_CONVERTENCODING, g_bConvertEncoding);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_FILTERUNPRINTABLE, g_bFilterUnprintable);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_APPEND, g_bPrinterAppend);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_DUMPTOREALPRINTER, g_bEnableDumpToRealPrinter);
+}
+
+bool Printer_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != 1) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ inactivity = yamlLoadHelper.LoadUint(SS_YAML_KEY_INACTIVITY);
+ g_PrinterIdleLimit = yamlLoadHelper.LoadUint(SS_YAML_KEY_IDLELIMIT);
+ strncpy(g_szPrintFilename, yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME).c_str(), sizeof(g_szPrintFilename));
+
+ if (yamlLoadHelper.LoadBool(SS_YAML_KEY_FILEOPEN))
+ {
+ yamlLoadHelper.LoadBool(SS_YAML_KEY_APPEND); // Consume
+ 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");
+ }
+ else
+ {
+ g_bPrinterAppend = yamlLoadHelper.LoadBool(SS_YAML_KEY_APPEND);
+ }
+
+ g_bDumpToPrinter = yamlLoadHelper.LoadBool(SS_YAML_KEY_DUMPTOPRINTER);
+ g_bConvertEncoding = yamlLoadHelper.LoadBool(SS_YAML_KEY_CONVERTENCODING);
+ g_bFilterUnprintable = yamlLoadHelper.LoadBool(SS_YAML_KEY_FILTERUNPRINTABLE);
+ g_bEnableDumpToRealPrinter = yamlLoadHelper.LoadBool(SS_YAML_KEY_DUMPTOREALPRINTER);
+
+ return true;
}
diff --git a/source/ParallelPrinter.h b/source/ParallelPrinter.h
index d2936a13..d2b96bdb 100644
--- a/source/ParallelPrinter.h
+++ b/source/ParallelPrinter.h
@@ -9,11 +9,12 @@ char* Printer_GetFilename();
void Printer_SetIdleLimit(unsigned int Duration);
unsigned int Printer_GetIdleLimit();
+std::string Printer_GetSnapshotCardName(void);
+void Printer_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+bool Printer_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+
extern bool g_bDumpToPrinter;
extern bool g_bConvertEncoding;
extern bool g_bFilterUnprintable;
extern bool g_bPrinterAppend;
-extern int g_iPrinterIdleLimit;
-extern bool g_bFilterUnprintable;
-extern bool g_bPrinterAppend;
extern bool g_bEnableDumpToRealPrinter; // Set by cmd-line: -printer-real
diff --git a/source/Pravets.cpp b/source/Pravets.cpp
new file mode 100644
index 00000000..296cf4f7
--- /dev/null
+++ b/source/Pravets.cpp
@@ -0,0 +1,48 @@
+/*
+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-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
+the Free Software Foundation; either version 2 of the License, or
+(at your option) any later version.
+
+AppleWin is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with AppleWin; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+/* Description: Pravets - Apple II clone
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "AppleWin.h"
+#include "Frame.h"
+#include "Keyboard.h"
+#include "Tape.h"
+
+//Pravets 8A/C variables
+bool P8CAPS_ON = false;
+bool P8Shift = false;
+
+void PravetsReset(void)
+{
+ if (g_Apple2Type == A2TYPE_PRAVETS8A)
+ {
+ P8CAPS_ON = false;
+ TapeWrite(0, 0, 0, 0 ,0);
+ FrameRefreshStatus(DRAW_LEDS);
+ }
+}
diff --git a/source/Pravets.h b/source/Pravets.h
new file mode 100644
index 00000000..801d1804
--- /dev/null
+++ b/source/Pravets.h
@@ -0,0 +1,7 @@
+#pragma once
+
+//Pravets 8A/C only variables
+extern bool P8CAPS_ON;
+extern bool P8Shift;
+
+void PravetsReset(void);
diff --git a/source/SAM.cpp b/source/SAM.cpp
new file mode 100644
index 00000000..2fa4c420
--- /dev/null
+++ b/source/SAM.cpp
@@ -0,0 +1,93 @@
+/*
+ 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
+
+ AppleWin is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ AppleWin is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with AppleWin; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+/*
+ SAM.CPP
+
+ Emulate an 8 bit DAC (eg: SAM card) which writes unsigned byte
+ data written to its IO area to the audio buffer (as used by the speaker).
+ This merges the data with the speaker stream, reducing the volume
+ of the Apple speaker when active.
+
+ Riccardo Macri Mar 2015
+*/
+#include "StdAfx.h"
+
+#include "AppleWin.h"
+#include "Memory.h"
+#include "SAM.h"
+#include "Speaker.h"
+
+//
+// Write 8 bit data to speaker. Emulates a "SAM" speech card DAC
+//
+
+
+static BYTE __stdcall IOWrite_SAM(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft)
+{
+ // Emulate audio from a SAM / 8 bit DAC card
+ // Only supportable if AppleWin is using WAVE output
+ //
+ // This works by using the existing speaker handling but then
+ // replacing the speaker audio with the 8 bit samples from the DAC
+ // before they get sent out to the soundcard buffer, whilst
+ // audio samples are being written to the SAM.
+ //
+ // Whilst very unusual, it is possible to intermingle use of SAM and the apple
+ // speaker. This is crudely supported with g_bQuieterSpeaker making the Apple
+ // speaker produce quieter clicks which will be crudely intermingled
+ // with the SAM data. The mute gets reset after the speaker code detects
+ // silence.
+
+ if (soundtype != SOUND_WAVE)
+ return MemReadFloatingBus(nCyclesLeft);
+
+ // use existing speaker code to bring timing up to date
+ BYTE res = SpkrToggle(pc, addr, bWrite, d, nCyclesLeft);
+
+ // The DAC in the SAM uses unsigned 8 bit samples
+ // The WAV data that g_nSpeakerData is loaded into is a signed short
+ //
+ // We convert unsigned 8 bit to signed by toggling the most significant bit
+ //
+ // SAM card WAV driver SAM WAV
+ // 0xFF 255 0x7f 127 _ FF 7F
+ // 0x81 129 0x01 1 / \
+ // 0x80 128 0x00 0 / \ /80 00
+ // 0x7f 127 0xFF -1 \_/
+ // 0x00 0 0x80 -128 00 80
+ //
+ // SAM is 8 bit, PC WAV is 16 so shift audio to the MSB (<< 8)
+
+ g_nSpeakerData = (d ^ 0x80) << 8;
+
+ // make speaker quieter so eg: a metronome click through the
+ // Apple speaker is softer vs. the analogue SAM output.
+ g_bQuieterSpeaker = true;
+
+ return res;
+}
+
+void ConfigureSAM(LPBYTE pCxRomPeripheral, UINT uSlot)
+{
+ RegisterIoHandler(uSlot, IO_Null, IOWrite_SAM, IO_Null, IO_Null, NULL, NULL);
+}
diff --git a/source/SAM.h b/source/SAM.h
new file mode 100644
index 00000000..291ac5c0
--- /dev/null
+++ b/source/SAM.h
@@ -0,0 +1,3 @@
+#pragma once
+
+void ConfigureSAM(LPBYTE pCxRomPeripheral, UINT uSlot);
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index 6587e458..3a771cd8 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
-Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
+Copyright (C) 2006-2015, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -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 "YamlHelper.h"
+
#include "AppleWin.h"
#include "CPU.h"
#include "Disk.h"
@@ -36,17 +39,20 @@ 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 "Pravets.h"
#include "SerialComms.h"
#include "Speaker.h"
+#include "Speech.h"
#include "Video.h"
+#include "z80emu.h"
-// Prototypes (Public)
- // Note: This is here and not in Video.h to prevent header include bloat.
- // i.e. so we don't need to incude "Structs.h" for NTSC.cpp
- DWORD VideoGetSnapshot(SS_IO_Video* pSS);
- DWORD VideoSetSnapshot(SS_IO_Video* pSS);
+#include "Configuration\Config.h"
+#include "Configuration\IPropertySheet.h"
-#define DEFAULT_SNAPSHOT_NAME "SaveState.aws"
+
+#define DEFAULT_SNAPSHOT_NAME "SaveState.aws.yaml"
bool g_bSaveStateOnExit = false;
@@ -54,6 +60,13 @@ static std::string g_strSaveStateFilename;
static std::string g_strSaveStatePathname;
static std::string g_strSaveStatePath;
+static YamlHelper yamlHelper;
+
+#define SS_FILE_VER 2
+
+#define UNIT_APPLE2_VER 1
+#define UNIT_SLOTS_VER 1
+
//-----------------------------------------------------------------------------
void Snapshot_SetFilename(std::string strPathname)
@@ -98,22 +111,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));
//
@@ -126,49 +144,32 @@ 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
//
// Reset all sub-systems
MemReset();
-
- if (!IS_APPLE2)
- MemResetPaging();
-
DiskReset();
KeybReset();
VideoResetState();
@@ -178,38 +179,46 @@ 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);
SetCurrentImageDir(strOldImageDir.c_str());
+
+ PostMessage(g_hFrameWindow, WM_USER_RESTART, 0, 0); // Power-cycle VM (undoing all the new state just loaded)
}
delete [] pSS;
@@ -217,104 +226,393 @@ void Snapshot_LoadState()
//-----------------------------------------------------------------------------
-void Snapshot_SaveState()
+static HANDLE m_hFile = INVALID_HANDLE_VALUE;
+static CConfigNeedingRestart m_ConfigNew;
+
+static std::string GetSnapshotUnitApple2Name(void)
{
- APPLEWIN_SNAPSHOT* pSS = (APPLEWIN_SNAPSHOT*) new char[sizeof(APPLEWIN_SNAPSHOT)];
- if(pSS == NULL)
+ static const std::string name("Apple2");
+ return name;
+}
+
+static std::string GetSnapshotUnitSlotsName(void)
+{
+ static const std::string name("Slots");
+ return name;
+}
+
+#define SS_YAML_KEY_MODEL "Model"
+
+#define SS_YAML_VALUE_APPLE2 "Apple]["
+#define SS_YAML_VALUE_APPLE2PLUS "Apple][+"
+#define SS_YAML_VALUE_APPLE2E "Apple//e"
+#define SS_YAML_VALUE_APPLE2EENHANCED "Enhanced Apple//e"
+#define SS_YAML_VALUE_APPLE2C "Apple2c"
+#define SS_YAML_VALUE_PRAVETS82 "Pravets82"
+#define SS_YAML_VALUE_PRAVETS8M "Pravets8M"
+#define SS_YAML_VALUE_PRAVETS8A "Pravets8A"
+
+static eApple2Type ParseApple2Type(std::string type)
+{
+ if (type == SS_YAML_VALUE_APPLE2) return A2TYPE_APPLE2;
+ else if (type == SS_YAML_VALUE_APPLE2PLUS) return A2TYPE_APPLE2PLUS;
+ else if (type == SS_YAML_VALUE_APPLE2E) return A2TYPE_APPLE2E;
+ else if (type == SS_YAML_VALUE_APPLE2EENHANCED) return A2TYPE_APPLE2EENHANCED;
+ else if (type == SS_YAML_VALUE_APPLE2C) return A2TYPE_APPLE2C;
+ else if (type == SS_YAML_VALUE_PRAVETS82) return A2TYPE_PRAVETS82;
+ else if (type == SS_YAML_VALUE_PRAVETS8M) return A2TYPE_PRAVETS8M;
+ else if (type == SS_YAML_VALUE_PRAVETS8A) return A2TYPE_PRAVETS8A;
+
+ throw std::string("Load: Unknown Apple2 type");
+}
+
+static std::string GetApple2TypeAsString(void)
+{
+ switch ( GetApple2Type() )
{
- // To do
- return;
+ case A2TYPE_APPLE2: return SS_YAML_VALUE_APPLE2;
+ case A2TYPE_APPLE2PLUS: return SS_YAML_VALUE_APPLE2PLUS;
+ case A2TYPE_APPLE2E: return SS_YAML_VALUE_APPLE2E;
+ case A2TYPE_APPLE2EENHANCED:return SS_YAML_VALUE_APPLE2EENHANCED;
+ case A2TYPE_APPLE2C: return SS_YAML_VALUE_APPLE2C;
+ case A2TYPE_PRAVETS82: return SS_YAML_VALUE_PRAVETS82;
+ case A2TYPE_PRAVETS8M: return SS_YAML_VALUE_PRAVETS8M;
+ case A2TYPE_PRAVETS8A: return SS_YAML_VALUE_PRAVETS8A;
+ default:
+ throw std::string("Save: Unknown Apple2 type");
+ }
+}
+
+//---
+
+static UINT ParseFileHdr(void)
+{
+ std::string scalar;
+ if (!yamlHelper.GetScalar(scalar))
+ throw std::string(SS_YAML_KEY_FILEHDR ": Failed to find scalar");
+
+ if (scalar != SS_YAML_KEY_FILEHDR)
+ throw std::string("Failed to find file header");
+
+ yamlHelper.GetMapStartEvent();
+
+ YamlLoadHelper yamlLoadHelper(yamlHelper);
+
+ //
+
+ std::string value = yamlLoadHelper.LoadString(SS_YAML_KEY_TAG);
+ if (value != SS_YAML_VALUE_AWSS)
+ {
+ //printf("%s: Bad tag (%s) - expected %s\n", SS_YAML_KEY_FILEHDR, value.c_str(), SS_YAML_VALUE_AWSS);
+ throw std::string(SS_YAML_KEY_FILEHDR ": Bad tag");
}
- memset(pSS, 0, sizeof(APPLEWIN_SNAPSHOT));
+ return yamlLoadHelper.LoadUint(SS_YAML_KEY_VERSION);
+}
- pSS->Hdr.dwTag = AW_SS_TAG;
- pSS->Hdr.dwVersion = MAKE_VERSION(1,0,0,1);
- pSS->Hdr.dwChecksum = 0; // TO DO
+//---
- //
- // Apple2 unit
- //
+static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version)
+{
+ if (version != UNIT_APPLE2_VER)
+ throw std::string(SS_YAML_KEY_UNIT ": Apple2: Version mismatch");
- pSS->Apple2Unit.UnitHdr.dwLength = sizeof(SS_APPLE2_Unit);
- pSS->Apple2Unit.UnitHdr.dwVersion = MAKE_VERSION(1,0,0,0);
+ std::string model = yamlLoadHelper.LoadString(SS_YAML_KEY_MODEL);
+ SetApple2Type( ParseApple2Type(model) ); // NB. Sets default main CPU type
+ m_ConfigNew.m_Apple2Type = GetApple2Type();
- 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);
+ CpuLoadSnapshot(yamlLoadHelper); // NB. Overrides default main CPU type
+ m_ConfigNew.m_CpuType = GetMainCpu();
- //
- // 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;
+ JoyLoadSnapshot(yamlLoadHelper);
+ KeybLoadSnapshot(yamlLoadHelper);
+ SpkrLoadSnapshot(yamlLoadHelper);
+ VideoLoadSnapshot(yamlLoadHelper);
+ MemLoadSnapshot(yamlLoadHelper);
+}
- //
- // 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;
+static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT version)
+{
+ if (version != UNIT_SLOTS_VER)
+ throw std::string(SS_YAML_KEY_UNIT ": Slots: Version mismatch");
- //
- // 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)
+ while (1)
{
- DWORD dwBytesWritten;
- BOOL bRes = WriteFile( hFile,
- pSS,
- sizeof(APPLEWIN_SNAPSHOT),
- &dwBytesWritten,
- NULL);
+ std::string scalar = yamlLoadHelper.GetMapNextSlotNumber();
+ if (scalar.empty())
+ break; // done all slots
- if(!bRes || (dwBytesWritten != sizeof(APPLEWIN_SNAPSHOT)))
- dwError = GetLastError();
+ const int slot = strtoul(scalar.c_str(), NULL, 10); // NB. aux slot supported as a different "unit"
+ if (slot < 1 || slot > 7)
+ throw std::string("Slots: Invalid slot #: ") + scalar;
- CloseHandle(hFile);
+ yamlLoadHelper.GetSubMap(scalar);
+
+ std::string card = yamlLoadHelper.LoadString(SS_YAML_KEY_CARD);
+ UINT version = yamlLoadHelper.LoadUint(SS_YAML_KEY_VERSION);
+
+ if (!yamlLoadHelper.GetSubMap(std::string(SS_YAML_KEY_STATE)))
+ throw std::string(SS_YAML_KEY_UNIT ": Expected sub-map name: " SS_YAML_KEY_STATE);
+
+ bool bIsCardSupported = true;
+ SS_CARDTYPE type = CT_Empty;
+ bool bRes = false;
+
+ if (card == Printer_GetSnapshotCardName())
+ {
+ bRes = Printer_LoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_GenericPrinter;
+ }
+ else if (card == sg_SSC.GetSnapshotCardName())
+ {
+ bRes = sg_SSC.LoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_SSC;
+ }
+ else if (card == sg_Mouse.GetSnapshotCardName())
+ {
+ bRes = sg_Mouse.LoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_MouseInterface;
+ }
+ else if (card == Z80_GetSnapshotCardName())
+ {
+ bRes = Z80_LoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_Z80;
+ }
+ else if (card == MB_GetSnapshotCardName())
+ {
+ bRes = MB_LoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_MockingboardC;
+ }
+ else if (card == Phasor_GetSnapshotCardName())
+ {
+ bRes = Phasor_LoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_Phasor;
+ }
+ else if (card == DiskGetSnapshotCardName())
+ {
+ bRes = DiskLoadSnapshot(yamlLoadHelper, slot, version);
+ type = CT_Disk2;
+ }
+ else if (card == HD_GetSnapshotCardName())
+ {
+ bRes = HD_LoadSnapshot(yamlLoadHelper, slot, version, g_strSaveStatePath);
+ m_ConfigNew.m_bEnableHDD = true;
+ type = CT_GenericHDD;
+ }
+ else
+ {
+ bIsCardSupported = false;
+ throw std::string("Slots: Unknown card: " + card); // todo: don't throw - just ignore & continue
+ }
+
+ if (bRes && bIsCardSupported)
+ {
+ m_ConfigNew.m_Slot[slot] = type;
+ }
+
+ yamlLoadHelper.PopMap();
+ yamlLoadHelper.PopMap();
+ }
+}
+
+//---
+
+static void ParseUnit(void)
+{
+ yamlHelper.GetMapStartEvent();
+
+ YamlLoadHelper yamlLoadHelper(yamlHelper);
+
+ std::string unit = yamlLoadHelper.LoadString(SS_YAML_KEY_TYPE);
+ UINT version = yamlLoadHelper.LoadUint(SS_YAML_KEY_VERSION);
+
+ if (!yamlLoadHelper.GetSubMap(std::string(SS_YAML_KEY_STATE)))
+ throw std::string(SS_YAML_KEY_UNIT ": Expected sub-map name: " SS_YAML_KEY_STATE);
+
+ if (unit == GetSnapshotUnitApple2Name())
+ {
+ ParseUnitApple2(yamlLoadHelper, version);
+ }
+ else if (unit == MemGetSnapshotUnitAuxSlotName())
+ {
+ MemLoadSnapshotAux(yamlLoadHelper, version);
+ }
+ else if (unit == GetSnapshotUnitSlotsName())
+ {
+ ParseSlots(yamlLoadHelper, version);
}
else
{
- dwError = GetLastError();
+ throw std::string(SS_YAML_KEY_UNIT ": Unknown type: " ) + unit;
+ }
+}
+
+static void Snapshot_LoadState_v2(void)
+{
+ try
+ {
+ int res = yamlHelper.InitParser( g_strSaveStatePathname.c_str() );
+ if (!res)
+ throw std::string("Failed to initialize parser or open file"); // TODO: disambiguate
+
+ UINT version = ParseFileHdr();
+ if (version != SS_FILE_VER)
+ throw std::string("Version mismatch");
+
+ //
+
+ CConfigNeedingRestart ConfigOld;
+ ConfigOld.m_Slot[1] = CT_GenericPrinter; // fixme
+ ConfigOld.m_Slot[2] = CT_SSC; // fixme
+ //ConfigOld.m_Slot[3] = CT_Uthernet; // todo
+ ConfigOld.m_Slot[6] = CT_Disk2; // fixme
+ ConfigOld.m_Slot[7] = ConfigOld.m_bEnableHDD ? CT_GenericHDD : CT_Empty; // fixme
+ //ConfigOld.m_SlotAux = ?; // fixme
+
+ for (UINT i=0; ibaudrate = 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)
+//===========================================================================
+
+#define SS_YAML_VALUE_CARD_SSC "Super Serial Card"
+
+#define SS_YAML_KEY_DIPSWDEFAULT "DIPSW Default"
+#define SS_YAML_KEY_DIPSWCURRENT "DIPSW Current"
+
+#define SS_YAML_KEY_BAUDRATE "Baud Rate"
+#define SS_YAML_KEY_FWMODE "Firmware mode"
+#define SS_YAML_KEY_STOPBITS "Stop Bits"
+#define SS_YAML_KEY_BYTESIZE "Byte Size"
+#define SS_YAML_KEY_PARITY "Parity"
+#define SS_YAML_KEY_LINEFEED "Linefeed"
+#define SS_YAML_KEY_INTERRUPTS "Interrupts"
+#define SS_YAML_KEY_CONTROL "Control Byte"
+#define SS_YAML_KEY_COMMAND "Command Byte"
+#define SS_YAML_KEY_INACTIVITY "Comm Inactivity"
+#define SS_YAML_KEY_TXIRQENABLED "TX IRQ Enabled"
+#define SS_YAML_KEY_RXIRQENABLED "RX IRQ Enabled"
+#define SS_YAML_KEY_TXIRQPENDING "TX IRQ Pending"
+#define SS_YAML_KEY_RXIRQPENDING "RX IRQ Pending"
+#define SS_YAML_KEY_WRITTENTX "Written TX"
+#define SS_YAML_KEY_SERIALPORTNAME "Serial Port Name"
+
+std::string CSuperSerialCard::GetSnapshotCardName(void)
{
- 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;
- return 0;
+ static const std::string name(SS_YAML_VALUE_CARD_SSC);
+ return name;
+}
+
+void CSuperSerialCard::SaveSnapshotDIPSW(YamlSaveHelper& yamlSaveHelper, std::string key, SSC_DIPSW& dipsw)
+{
+ YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", key.c_str());
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_BAUDRATE, dipsw.uBaudRate);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_FWMODE, dipsw.eFirmwareMode);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_STOPBITS, dipsw.uStopBits);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_BYTESIZE, dipsw.uByteSize);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PARITY, dipsw.uParity);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_LINEFEED, dipsw.bLinefeed);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_INTERRUPTS, dipsw.bInterrupts);
+}
+
+void CSuperSerialCard::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), m_uSlot, 1);
+
+ YamlSaveHelper::Label unit(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+ SaveSnapshotDIPSW(yamlSaveHelper, SS_YAML_KEY_DIPSWDEFAULT, m_DIPSWDefault);
+ SaveSnapshotDIPSW(yamlSaveHelper, SS_YAML_KEY_DIPSWCURRENT, m_DIPSWCurrent);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_BAUDRATE, m_uBaudRate);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_STOPBITS, m_uStopBits);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_BYTESIZE, m_uByteSize);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_PARITY, m_uParity);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_CONTROL, m_uControlByte);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_COMMAND, m_uCommandByte);
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_INACTIVITY, m_dwCommInactivity);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_TXIRQENABLED, m_bTxIrqEnabled);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_RXIRQENABLED, m_bRxIrqEnabled);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_TXIRQPENDING, m_vbTxIrqPending);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_RXIRQPENDING, m_vbRxIrqPending);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_WRITTENTX, m_bWrittenTx);
+ yamlSaveHelper.SaveString(SS_YAML_KEY_SERIALPORTNAME, GetSerialPortName());
+}
+
+void CSuperSerialCard::LoadSnapshotDIPSW(YamlLoadHelper& yamlLoadHelper, std::string key, SSC_DIPSW& dipsw)
+{
+ if (!yamlLoadHelper.GetSubMap(key))
+ throw std::string("Card: Expected key: " + key);
+
+ dipsw.uBaudRate = yamlLoadHelper.LoadUint(SS_YAML_KEY_BAUDRATE);
+ dipsw.eFirmwareMode = (eFWMODE) yamlLoadHelper.LoadUint(SS_YAML_KEY_FWMODE);
+ dipsw.uStopBits = yamlLoadHelper.LoadUint(SS_YAML_KEY_STOPBITS);
+ dipsw.uByteSize = yamlLoadHelper.LoadUint(SS_YAML_KEY_BYTESIZE);
+ dipsw.uParity = yamlLoadHelper.LoadUint(SS_YAML_KEY_PARITY);
+ dipsw.bLinefeed = yamlLoadHelper.LoadBool(SS_YAML_KEY_LINEFEED);
+ dipsw.bInterrupts = yamlLoadHelper.LoadBool(SS_YAML_KEY_INTERRUPTS);
+
+ yamlLoadHelper.PopMap();
+}
+
+bool CSuperSerialCard::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != 2) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != 1)
+ throw std::string("Card: wrong version");
+
+ LoadSnapshotDIPSW(yamlLoadHelper, SS_YAML_KEY_DIPSWDEFAULT, m_DIPSWDefault);
+ LoadSnapshotDIPSW(yamlLoadHelper, SS_YAML_KEY_DIPSWCURRENT, m_DIPSWCurrent);
+
+ m_uBaudRate = yamlLoadHelper.LoadUint(SS_YAML_KEY_BAUDRATE);
+ m_uStopBits = yamlLoadHelper.LoadUint(SS_YAML_KEY_STOPBITS);
+ m_uByteSize = yamlLoadHelper.LoadUint(SS_YAML_KEY_BYTESIZE);
+ m_uParity = yamlLoadHelper.LoadUint(SS_YAML_KEY_PARITY);
+ m_uControlByte = yamlLoadHelper.LoadUint(SS_YAML_KEY_CONTROL);
+ m_uCommandByte = yamlLoadHelper.LoadUint(SS_YAML_KEY_COMMAND);
+ m_dwCommInactivity = yamlLoadHelper.LoadUint(SS_YAML_KEY_INACTIVITY);
+ m_bTxIrqEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_TXIRQENABLED);
+ m_bRxIrqEnabled = yamlLoadHelper.LoadBool(SS_YAML_KEY_RXIRQENABLED);
+ m_vbTxIrqPending = yamlLoadHelper.LoadBool(SS_YAML_KEY_TXIRQPENDING);
+ m_vbRxIrqPending = yamlLoadHelper.LoadBool(SS_YAML_KEY_RXIRQPENDING);
+ m_bWrittenTx = yamlLoadHelper.LoadBool(SS_YAML_KEY_WRITTENTX);
+
+ std::string serialPortName = yamlLoadHelper.LoadString(SS_YAML_KEY_SERIALPORTNAME);
+ SetSerialPortName(serialPortName.c_str());
+
+ return true;
}
diff --git a/source/SerialComms.h b/source/SerialComms.h
index d75d2ea9..c86678d2 100644
--- a/source/SerialComms.h
+++ b/source/SerialComms.h
@@ -33,8 +33,10 @@ 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);
+ std::string GetSnapshotCardName(void);
+ void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+ bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
char* GetSerialPortChoices();
DWORD GetSerialPort() { return m_dwSerialPortItem; } // Drop-down list item
@@ -72,6 +74,8 @@ private:
void CommThUninit();
UINT GetNumSerialPortChoices() { return m_vecSerialPortsItems.size(); }
void ScanCOMPorts();
+ void SaveSnapshotDIPSW(class YamlSaveHelper& yamlSaveHelper, std::string key, SSC_DIPSW& dipsw);
+ void LoadSnapshotDIPSW(class YamlLoadHelper& yamlLoadHelper, std::string key, SSC_DIPSW& dipsw);
//
@@ -134,4 +138,5 @@ private:
OVERLAPPED m_o;
BYTE* m_pExpansionRom;
+ UINT m_uSlot;
};
diff --git a/source/Speaker.cpp b/source/Speaker.cpp
index 3608ecd6..fcf1dd9f 100644
--- a/source/Speaker.cpp
+++ b/source/Speaker.cpp
@@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SoundCore.h"
#include "Speaker.h"
#include "Video.h" // VideoRedrawScreen()
+#include "YamlHelper.h"
#include "Debugger\Debug.h" // For DWORD extbench
@@ -51,11 +52,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// their buffers are running low.
//
-#define SOUND_NONE 0
-#define SOUND_DIRECT 1
-#define SOUND_SMART 2
-#define SOUND_WAVE 3
-
static const unsigned short g_nSPKR_NumChannels = 1;
static const DWORD g_dwDSSpkrBufferSize = MAX_SAMPLES * sizeof(short) * g_nSPKR_NumChannels;
@@ -66,18 +62,20 @@ static short* g_pSpeakerBuffer = NULL;
// Globals (SOUND_WAVE)
const short SPKR_DATA_INIT = (short)0x8000;
-static short g_nSpeakerData = SPKR_DATA_INIT;
+short g_nSpeakerData = SPKR_DATA_INIT;
static UINT g_nBufferIdx = 0;
static short* g_pRemainderBuffer = NULL;
static UINT g_nRemainderBufferSize; // Setup in SpkrInitialize()
static UINT g_nRemainderBufferIdx; // Setup in SpkrInitialize()
-
// Application-wide globals:
DWORD soundtype = SOUND_WAVE;
double g_fClksPerSpkrSample; // Setup in SetClksPerSpkrSample()
+// Allow temporary quietening of speaker (8 bit DAC)
+bool g_bQuieterSpeaker = false;
+
// Globals
static DWORD lastcyclenum = 0;
static DWORD toggles = 0;
@@ -226,7 +224,7 @@ void SpkrDestroy ()
g_pSpeakerBuffer = NULL;
g_pRemainderBuffer = NULL;
}
- else
+ else if (soundtype == SOUND_DIRECT || soundtype == SOUND_SMART)
{
InternalBeep(0,0);
}
@@ -328,8 +326,8 @@ void SpkrReset()
BOOL SpkrSetEmulationType (HWND window, DWORD newtype)
{
- if (soundtype != SOUND_NONE)
- SpkrDestroy();
+ SpkrDestroy(); // GH#295: Destroy for all types (even SOUND_NONE)
+
soundtype = newtype;
if (soundtype != SOUND_NONE)
SpkrInitialize();
@@ -447,7 +445,21 @@ BYTE __stdcall SpkrToggle (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft)
UpdateSpkr();
- g_nSpeakerData = ~g_nSpeakerData;
+ if (g_bQuieterSpeaker)
+ {
+ // quieten the speaker if 8 bit DAC in use
+ if (g_nSpeakerData == (SPKR_DATA_INIT >> 2))
+ g_nSpeakerData = ~g_nSpeakerData;
+ else
+ g_nSpeakerData = SPKR_DATA_INIT>>2;
+ }
+ else
+ {
+ if (g_nSpeakerData == SPKR_DATA_INIT)
+ g_nSpeakerData = ~g_nSpeakerData;
+ else
+ g_nSpeakerData = SPKR_DATA_INIT;
+ }
}
else if (soundtype != SOUND_NONE)
{
@@ -875,7 +887,7 @@ static ULONG Spkr_SubmitWaveBuffer(short* pSpeakerBuffer, ULONG nNumSamples)
double fTicksSecs = (double)GetTickCount() / 1000.0;
sprintf(szDbg, "%010.3f: [Submit] PC=%08X, WC=%08X, Diff=%08X, Off=%08X, NS=%08X XXX\n", fTicksSecs, dwCurrentPlayCursor, dwCurrentWriteCursor, dwCurrentWriteCursor-dwCurrentPlayCursor, dwByteOffset, nNumSamples);
OutputDebugString(szDbg);
- if (g_fh) fprintf(g_fh, szDbg);
+ if (g_fh) fprintf(g_fh, "%s", szDbg);
dwByteOffset = dwCurrentWriteCursor;
nNumSamplesError = 0;
@@ -993,6 +1005,7 @@ static void Spkr_SetActive(bool bActive)
// Called by SpkrUpdate() after 0.2s of speaker inactivity
g_bSpkrRecentlyActive = false;
SpeakerVoice.bRecentlyActive = false;
+ g_bQuieterSpeaker = 0; // undo any muting (for 8 bit DAC)
}
}
@@ -1080,14 +1093,33 @@ 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)
+//
+
+#define SS_YAML_KEY_LASTCYCLE "Last Cycle"
+
+static std::string SpkrGetSnapshotStructName(void)
{
- g_nSpkrLastCycle = pSS->g_nSpkrLastCycle;
- return 0;
+ static const std::string name("Speaker");
+ return name;
+}
+
+void SpkrSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SpkrGetSnapshotStructName().c_str());
+ yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LASTCYCLE, g_nSpkrLastCycle);
+}
+
+void SpkrLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+{
+ if (!yamlLoadHelper.GetSubMap(SpkrGetSnapshotStructName()))
+ return;
+
+ g_nSpkrLastCycle = yamlLoadHelper.LoadUint64(SS_YAML_KEY_LASTCYCLE);
+
+ yamlLoadHelper.PopMap();
}
diff --git a/source/Speaker.h b/source/Speaker.h
index 8e93fbbe..2e6312bd 100644
--- a/source/Speaker.h
+++ b/source/Speaker.h
@@ -1,7 +1,14 @@
#pragma once
+#define SOUND_NONE 0
+#define SOUND_DIRECT 1
+#define SOUND_SMART 2
+#define SOUND_WAVE 3
+
extern DWORD soundtype;
extern double g_fClksPerSpkrSample;
+extern bool g_bQuieterSpeaker;
+extern short g_nSpeakerData;
void SpkrDestroy ();
void SpkrInitialize ();
@@ -19,7 +26,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 SpkrSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+void SpkrLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
BYTE __stdcall SpkrToggle (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft);
diff --git a/source/StdAfx.h b/source/StdAfx.h
index 989c60da..6befb99a 100644
--- a/source/StdAfx.h
+++ b/source/StdAfx.h
@@ -14,7 +14,7 @@
#endif
// Not needed in VC7.1, but needed in VC Express
-#include
+#include
#include
#include
@@ -23,7 +23,6 @@
#include
#include
#include
-#include
#include
#if _MSC_VER >= 1600 // supported from VS2010 (cl.exe v16.00)
#include // cleanup WORD DWORD -> uint16_t uint32_t
@@ -43,6 +42,8 @@ typedef UINT32 uint32_t;
#include
#include