Manual merge from master @ c798157

This commit is contained in:
tomcw 2016-03-21 23:48:02 +00:00
parent 0cc6a4841f
commit e98de27039
82 changed files with 6133 additions and 2908 deletions

View File

@ -76,16 +76,19 @@
<ClInclude Include="source\NoSlotClock.h" />
<ClInclude Include="source\NTSC.h" />
<ClInclude Include="source\ParallelPrinter.h" />
<ClInclude Include="source\Pravets.h" />
<ClInclude Include="source\Registry.h" />
<ClInclude Include="source\Riff.h" />
<ClInclude Include="source\SAM.h" />
<ClInclude Include="source\SaveState.h" />
<ClInclude Include="source\SaveState_Structs_common.h" />
<ClInclude Include="source\SaveState_Structs_v1.h" />
<ClInclude Include="source\SerialComms.h" />
<ClInclude Include="source\SoundCore.h" />
<ClInclude Include="source\Speaker.h" />
<ClInclude Include="source\Speech.h" />
<ClInclude Include="source\SSI263Phonemes.h" />
<ClInclude Include="source\StdAfx.h" />
<ClInclude Include="source\Structs.h" />
<ClInclude Include="source\Tape.h" />
<ClInclude Include="source\Tfe\Bittypes.h" />
<ClInclude Include="source\Tfe\Bpf.h" />
@ -97,6 +100,7 @@
<ClInclude Include="source\Tfe\Tfesupp.h" />
<ClInclude Include="source\Tfe\Uilib.h" />
<ClInclude Include="source\Video.h" />
<ClInclude Include="source\YamlHelper.h" />
<ClInclude Include="source\z80emu.h" />
<ClInclude Include="source\Z80VICE\daa.h" />
<ClInclude Include="source\Z80VICE\z80.h" />
@ -107,7 +111,7 @@
<Text Include="docs\CodingConventions.txt" />
<Text Include="docs\Debugger_Changelog.txt" />
<Text Include="docs\FAQ.txt" />
<Text Include="docs\History.txt" />
<Text Include="bin\History.txt" />
<Text Include="docs\ToDo.txt" />
<Text Include="docs\Video_Cleanup.txt" />
<Text Include="docs\Wishlist.txt" />
@ -126,6 +130,7 @@
<ClCompile Include="source\Configuration\PropertySheet.cpp" />
<ClCompile Include="source\Configuration\PropertySheetHelper.cpp" />
<ClCompile Include="source\CPU.cpp" />
<ClCompile Include="source\SAM.cpp" />
<ClCompile Include="source\Debugger\Debug.cpp" />
<ClCompile Include="source\Debugger\Debugger_Assembler.cpp" />
<ClCompile Include="source\Debugger\Debugger_Color.cpp" />
@ -152,6 +157,7 @@
<ClCompile Include="source\NoSlotClock.cpp" />
<ClCompile Include="source\NTSC.cpp" />
<ClCompile Include="source\ParallelPrinter.cpp" />
<ClCompile Include="source\Pravets.cpp" />
<ClCompile Include="source\Registry.cpp" />
<ClCompile Include="source\Riff.cpp" />
<ClCompile Include="source\SaveState.cpp" />
@ -191,6 +197,7 @@
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release NoDX|Win32'">NotUsing</PrecompiledHeader>
</ClCompile>
<ClCompile Include="source\Video.cpp" />
<ClCompile Include="source\YamlHelper.cpp" />
<ClCompile Include="source\z80emu.cpp" />
<ClCompile Include="source\Z80VICE\daa.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">NotUsing</PrecompiledHeader>
@ -237,6 +244,9 @@
<ProjectReference Include="zlib\zlib-Express2013.vcxproj">
<Project>{9b32a6e7-1237-4f36-8903-a3fd51df9c4e}</Project>
</ProjectReference>
<ProjectReference Include="libyaml\win32\yaml2013.vcxproj">
<Project>{0212e0df-06da-4080-bd1d-f3b01599f70f}</Project>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Image Include="resource\Applewin.bmp" />
@ -343,9 +353,9 @@
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
@ -354,15 +364,22 @@
<AdditionalDependencies>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)</AdditionalDependencies>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
</Link>
<PreBuildEvent>
<Command>echo Performing unit-test: TestCPU6502
.\Debug\TestCPU6502.exe</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Performing unit-test: TestCPU6502</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug NoDX|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
@ -371,6 +388,13 @@
<AdditionalDependencies>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)</AdditionalDependencies>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
</Link>
<PreBuildEvent>
<Command>echo Performing unit-test: TestCPU6502
.\Debug\TestCPU6502.exe</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Performing unit-test: TestCPU6502</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
@ -379,9 +403,9 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
@ -394,6 +418,13 @@
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
</Link>
<PreBuildEvent>
<Command>echo Performing unit-test: TestCPU6502
.\Release\TestCPU6502.exe</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Performing unit-test: TestCPU6502</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release NoDX|Win32'">
<ClCompile>
@ -402,9 +433,9 @@
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<PreprocessorDefinitions>WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;NO_DIRECT_X;YAML_DECLARE_STATIC;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<SDLCheck>true</SDLCheck>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<AdditionalIncludeDirectories>source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
</ClCompile>
@ -417,6 +448,13 @@
<LinkTimeCodeGeneration>UseLinkTimeCodeGeneration</LinkTimeCodeGeneration>
<AdditionalManifestDependencies>"type='Win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='X86' publicKeyToken='6595b64144ccf1df' language='*'"</AdditionalManifestDependencies>
</Link>
<PreBuildEvent>
<Command>echo Performing unit-test: TestCPU6502
.\Release\TestCPU6502.exe</Command>
</PreBuildEvent>
<PreBuildEvent>
<Message>Performing unit-test: TestCPU6502</Message>
</PreBuildEvent>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">

View File

@ -172,6 +172,15 @@
<ClCompile Include="source\NTSC.cpp">
<Filter>Source Files\Video</Filter>
</ClCompile>
<ClCompile Include="source\Pravets.cpp">
<Filter>Source Files\Model</Filter>
</ClCompile>
<ClCompile Include="source\SAM.cpp">
<Filter>Source Files\Emulator</Filter>
</ClCompile>
<ClCompile Include="source\YamlHelper.cpp">
<Filter>Source Files\Emulator</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="source\Applewin.h">
@ -372,9 +381,6 @@
<ClInclude Include="source\StdAfx.h">
<Filter>Source Files</Filter>
</ClInclude>
<ClInclude Include="source\Structs.h">
<Filter>Source Files\_Headers</Filter>
</ClInclude>
<ClInclude Include="source\Tape.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>
@ -423,6 +429,21 @@
<ClInclude Include="source\NTSC.h">
<Filter>Source Files\Video</Filter>
</ClInclude>
<ClInclude Include="source\Pravets.h">
<Filter>Source Files\Model</Filter>
</ClInclude>
<ClInclude Include="source\SAM.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>
<ClInclude Include="source\YamlHelper.h">
<Filter>Source Files\Emulator</Filter>
</ClInclude>
<ClInclude Include="source\SaveState_Structs_common.h">
<Filter>Source Files\_Headers</Filter>
</ClInclude>
<ClInclude Include="source\SaveState_Structs_v1.h">
<Filter>Source Files\_Headers</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Image Include="resource\Applewin.bmp">
@ -591,9 +612,6 @@
<Text Include="docs\FAQ.txt">
<Filter>Docs</Filter>
</Text>
<Text Include="docs\History.txt">
<Filter>Docs</Filter>
</Text>
<Text Include="docs\ToDo.txt">
<Filter>Docs</Filter>
</Text>
@ -603,6 +621,7 @@
<Text Include="docs\Wishlist.txt">
<Filter>Docs</Filter>
</Text>
<Text Include="bin\History.txt" />
</ItemGroup>
<ItemGroup>
<Filter Include="Docs">
@ -644,6 +663,9 @@
<Filter Include="Resource Files">
<UniqueIdentifier>{b5c6889e-727d-4339-96c8-e4284e1d6e0f}</UniqueIdentifier>
</Filter>
<Filter Include="Source Files\Model">
<UniqueIdentifier>{15b450e4-f89f-4d80-9c44-48b32f33f3e3}</UniqueIdentifier>
</Filter>
</ItemGroup>
<ItemGroup>
<ResourceCompile Include="resource\Applewin.rc">

View File

@ -26,6 +26,8 @@
>
<Tool
Name="VCPreBuildEventTool"
Description="Performing unit-test: TestCPU6502"
CommandLine=".\Release\TestCPU6502.exe"
/>
<Tool
Name="VCCustomBuildTool"
@ -54,8 +56,8 @@
FavorSizeOrSpeed="1"
OmitFramePointers="true"
WholeProgramOptimization="true"
AdditionalIncludeDirectories="source\cpu;source\emulator;source\debugger;zlib;zip_lib"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE"
AdditionalIncludeDirectories="source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include"
PreprocessorDefinitions="WIN32;NDEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC"
StringPooling="true"
RuntimeLibrary="0"
EnableFunctionLevelLinking="true"
@ -130,6 +132,8 @@
>
<Tool
Name="VCPreBuildEventTool"
Description="Performing unit-test: TestCPU6502"
CommandLine=".\Debug\TestCPU6502.exe"
/>
<Tool
Name="VCCustomBuildTool"
@ -153,8 +157,8 @@
Name="VCCLCompilerTool"
AdditionalOptions="/Zm200 "
Optimization="0"
AdditionalIncludeDirectories="source\cpu;source\emulator;source\debugger;zlib;zip_lib"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE"
AdditionalIncludeDirectories="source\cpu;source\emulator;source\debugger;zlib;zip_lib;libyaml\include"
PreprocessorDefinitions="WIN32;_DEBUG;_WINDOWS;_CRT_SECURE_NO_DEPRECATE;NO_DSHOW_STRSAFE;YAML_DECLARE_STATIC"
MinimalRebuild="true"
RuntimeLibrary="1"
UsePrecompiledHeader="2"
@ -686,6 +690,14 @@
RelativePath=".\source\Riff.h"
>
</File>
<File
RelativePath=".\source\SAM.cpp"
>
</File>
<File
RelativePath=".\source\SAM.h"
>
</File>
<File
RelativePath=".\source\SaveState.cpp"
>
@ -734,6 +746,14 @@
RelativePath=".\source\Tape.h"
>
</File>
<File
RelativePath=".\source\YamlHelper.cpp"
>
</File>
<File
RelativePath=".\source\YamlHelper.h"
>
</File>
<File
RelativePath=".\source\z80emu.cpp"
>
@ -755,11 +775,15 @@
>
</File>
<File
RelativePath=".\source\SSI263Phonemes.h"
RelativePath=".\source\SaveState_Structs_common.h"
>
</File>
<File
RelativePath=".\source\Structs.h"
RelativePath=".\source\SaveState_Structs_v1.h"
>
</File>
<File
RelativePath=".\source\SSI263Phonemes.h"
>
</File>
</Filter>
@ -959,6 +983,18 @@
>
</File>
</Filter>
<Filter
Name="Model"
>
<File
RelativePath=".\source\Pravets.cpp"
>
</File>
<File
RelativePath=".\source\Pravets.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="Docs"

BIN
Disks/SAM Slot 5.dsk Normal file

Binary file not shown.

View File

@ -9,6 +9,12 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
1.25.0.4 - 23 Apr 2015
----------------------
Fixes:
. [Bug #276] -d1 command line argument caused AppleWin to quickly exit.
1.25.0.3 - 8 Sep 2014
---------------------
Note: This is the last planned version to support Win98/ME.

View File

@ -154,10 +154,11 @@ BEGIN
CONTROL "Slider1",IDC_SPKR_VOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_VERT | TBS_BOTH | WS_TABSTOP,13,47,28,60
LTEXT "&Mockingboard:",IDC_STATIC,49,39,51,8
CONTROL "Slider1",IDC_MB_VOLUME,"msctls_trackbar32",TBS_AUTOTICKS | TBS_VERT | TBS_BOTH | WS_TABSTOP,59,47,25,60
GROUPBOX "Sound Cards",IDC_STATIC,6,122,197,61
GROUPBOX "Sound Cards",IDC_STATIC,6,122,197,64
CONTROL "Mockingboards (in slots 4 && 5)",IDC_MB_ENABLE,"Button",BS_AUTORADIOBUTTON,10,136,142,8
CONTROL "Phasor (in slot 4)",IDC_PHASOR_ENABLE,"Button",BS_AUTORADIOBUTTON,10,149,92,10
CONTROL "No sound cards",IDC_SOUNDCARD_DISABLE,"Button",BS_AUTORADIOBUTTON,10,163,78,10
CONTROL "SAM/DAC (in slot 5)",IDC_SAM_ENABLE,"Button",BS_AUTORADIOBUTTON,10,162,95,10
CONTROL "No sound cards",IDC_SOUNDCARD_DISABLE,"Button",BS_AUTORADIOBUTTON,10,175,78,10
END
IDD_PROPPAGE_DISK DIALOGEX 0, 0, 211, 188
@ -270,7 +271,7 @@ BEGIN
VALUE "FileDescription", "Apple //e Emulator for Windows"
VALUE "FileVersion", "1.26.0.0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2014 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "LegalCopyright", " 1994-2015 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
VALUE "ProductVersion", "1.26.0.0 Alpha"

View File

@ -67,36 +67,39 @@
#define IDC_SPIN_XTRIM 1026
#define IDC_SPIN_YTRIM 1027
#define IDC_PHASOR_ENABLE 1029
#define IDC_SOUNDCARD_DISABLE 1030
#define IDC_TFE_SETTINGS_ENABLE_T 1031
#define IDC_TFE_SETTINGS_ENABLE 1032
#define IDC_TFE_SETTINGS_INTERFACE_T 1033
#define IDC_TFE_SETTINGS_INTERFACE 1034
#define IDC_TFE_SETTINGS_INTERFACE_NAME 1035
#define IDC_TFE_SETTINGS_INTERFACE_DESC 1036
#define IDS_TFE_CAPTION 1037
#define IDS_TFE_ETHERNET 1038
#define IDS_TFE_INTERFACE 1039
#define IDS_OK 1040
#define IDS_CANCEL 1041
#define IDC_ETHERNET 1042
#define IDC_SCROLLLOCK_TOGGLE 1043
#define IDC_MOUSE_IN_SLOT4 1044
#define IDC_THE_FREEZES_F8_ROM_FW 1045
#define IDC_MOUSE_CROSSHAIR 1046
#define IDC_CLONETYPE 1047
#define IDC_MOUSE_RESTRICT_TO_WINDOW 1048
#define IDC_CIDERPRESS_BROWSE 1049
#define IDC_CIDERPRESS_FILENAME 1050
#define IDC_CPM_CONFIG 1051
#define IDC_DUMPTOPRINTER 1052
#define IDC_PRINTER_DUMP_FILENAME 1053
#define IDC_PRINTER_DUMP_FILENAME_BROWSE 1054
#define IDC_PRINTER_CONVERT_ENCODING 1055
#define IDC_PRINTER_FILTER_UNPRINTABLE 1056
#define IDC_PRINTER_APPEND 1057
#define IDC_SPIN_PRINTER_IDLE 1058
#define IDC_CHECK_HALF_SCAN_LINES 1059
#define IDC_SAM_ENABLE 1030
#define IDC_SOUNDCARD_DISABLE 1031
#define IDC_TFE_SETTINGS_ENABLE_T 1032
#define IDC_TFE_SETTINGS_ENABLE 1033
#define IDC_TFE_SETTINGS_INTERFACE_T 1034
#define IDC_TFE_SETTINGS_INTERFACE 1035
#define IDC_TFE_SETTINGS_INTERFACE_NAME 1036
#define IDC_TFE_SETTINGS_INTERFACE_DESC 1037
#define IDS_TFE_CAPTION 1038
#define IDS_TFE_ETHERNET 1039
#define IDS_TFE_INTERFACE 1040
#define IDS_OK 1041
#define IDS_CANCEL 1042
#define IDC_ETHERNET 1043
#define IDC_SCROLLLOCK_TOGGLE 1044
#define IDC_MOUSE_IN_SLOT4 1045
#define IDC_THE_FREEZES_F8_ROM_FW 1046
#define IDC_MOUSE_CROSSHAIR 1047
#define IDC_CLONETYPE 1048
#define IDC_MOUSE_RESTRICT_TO_WINDOW 1049
#define IDC_CIDERPRESS_BROWSE 1050
#define IDC_CIDERPRESS_FILENAME 1051
#define IDC_CPM_CONFIG 1052
#define IDC_DUMPTOPRINTER 1053
#define IDC_PRINTER_DUMP_FILENAME 1054
#define IDC_PRINTER_DUMP_FILENAME_BROWSE 1055
#define IDC_PRINTER_CONVERT_ENCODING 1056
#define IDC_PRINTER_FILTER_UNPRINTABLE 1057
#define IDC_PRINTER_APPEND 1058
#define IDC_SPIN_PRINTER_IDLE 1059
#define IDC_CHECK_HALF_SCAN_LINES 1060
#define IDC_GPL_TEXT 1061
#define IDC_GPL_BORDER 1063
#define IDC_APPLEWIN_VERSION 1064

View File

@ -32,6 +32,21 @@ typedef struct
mem_write_handler func;
} STWriteHandler;
struct mc6821_s {
/* MC6821 register. */
BYTE pra;
BYTE ddra;
BYTE cra;
BYTE prb;
BYTE ddrb;
BYTE crb;
/* Drive structure */
// struct drive_s *drive;
};
typedef struct mc6821_s mc6821_t;
class C6821
{
public:
@ -64,6 +79,18 @@ public:
m_stOutB.objTo = objTo;
m_stOutB.func = func;
}
void Get6821(mc6821_t& r6821, BYTE& byIA, BYTE& byIB)
{
r6821 = mc6821[0];
byIA = m_byIA;
byIB = m_byIB;
}
void Set6821(const mc6821_t& r6821, const BYTE byIA, const BYTE byIB)
{
mc6821[0] = r6821;
m_byIA = byIA;
m_byIB = byIB;
}
// AppleWin:TC END
private:
@ -75,20 +102,6 @@ private:
//struct drive_s;
struct mc6821_s {
/* MC6821 register. */
BYTE pra;
BYTE ddra;
BYTE cra;
BYTE prb;
BYTE ddrb;
BYTE crb;
/* Drive structure */
// struct drive_s *drive;
};
typedef struct mc6821_s mc6821_t;
//struct drive_context_s;
void mc6821_init(/*struct drive_context_s *drv*/);
void mc6821_reset(/*struct drive_context_s *drv*/);

View File

@ -33,6 +33,7 @@
#include "Applewin.h" // For g_fh
#include "Mockingboard.h" // For g_uTimer1IrqCount
#include "YamlHelper.h"
/* The AY white noise RNG algorithm is based on info from MAME's ay8910.c -
* MAME's licence explicitly permits free use of info (even encourages it).
@ -114,12 +115,17 @@ static int rstereopos, rchan1pos, rchan2pos, rchan3pos;
double CAY8910::m_fCurrentCLK_AY8910 = 0.0;
CAY8910::CAY8910() :
// Init the statics that were in sound_ay_overlay()
rng(1),
noise_toggle(0),
env_first(1), env_rev(0), env_counter(15)
void CAY8910::init(void)
{
// Init the statics that were in sound_ay_overlay()
rng = 1;
noise_toggle = 0;
env_first = 1; env_rev = 0; env_counter = 15;
}
CAY8910::CAY8910(void)
{
init();
m_fCurrentCLK_AY8910 = g_fCurrentCLK6502;
};
@ -731,6 +737,8 @@ void CAY8910::sound_ay_reset( void )
{
int f;
init(); // AppleWin:TC
/* recalculate timings based on new machines ay clock */
sound_ay_init();
@ -940,6 +948,192 @@ sound_beeper( int is_tape, int on )
}
#endif
//
#define SS_YAML_KEY_AY8910 "AY8910"
#define SS_YAML_KEY_TONE0_TICK "Tone0 Tick"
#define SS_YAML_KEY_TONE1_TICK "Tone1 Tick"
#define SS_YAML_KEY_TONE2_TICK "Tone2 Tick"
#define SS_YAML_KEY_TONE0_HIGH "Tone0 High"
#define SS_YAML_KEY_TONE1_HIGH "Tone1 High"
#define SS_YAML_KEY_TONE2_HIGH "Tone2 High"
#define SS_YAML_KEY_NOISE_TICK "Noise Tick"
#define SS_YAML_KEY_TONE_SUBCYCLES "Tone Subcycles"
#define SS_YAML_KEY_ENV_SUBCYCLES "Env Subcycles"
#define SS_YAML_KEY_ENV_INTERNAL_TICK "Env Internal Tick"
#define SS_YAML_KEY_ENV_TICK "Env Tick"
#define SS_YAML_KEY_TICK_INCR "Tick Incr"
#define SS_YAML_KEY_TONE0_PERIOD "Tone0 Period"
#define SS_YAML_KEY_TONE1_PERIOD "Tone1 Period"
#define SS_YAML_KEY_TONE2_PERIOD "Tone2 Period"
#define SS_YAML_KEY_NOISE_PERIOD "Noise Period"
#define SS_YAML_KEY_ENV_PERIOD "Env Period"
#define SS_YAML_KEY_RNG "RNG"
#define SS_YAML_KEY_NOISE_TOGGLE "Noise Toggle"
#define SS_YAML_KEY_ENV_FIRST "Env First"
#define SS_YAML_KEY_ENV_REV "Env Rev"
#define SS_YAML_KEY_ENV_COUNTER "Env Counter"
#define SS_YAML_KEY_REGISTERS "Registers"
#define SS_YAML_KEY_REG_TONE0_PERIOD "Tone0 Period"
#define SS_YAML_KEY_REG_TONE1_PERIOD "Tone1 Period"
#define SS_YAML_KEY_REG_TONE2_PERIOD "Tone2 Period"
#define SS_YAML_KEY_REG_NOISE_PERIOD "Noise Period"
#define SS_YAML_KEY_REG_MIXER "Mixer"
#define SS_YAML_KEY_REG_VOL0 "Vol0"
#define SS_YAML_KEY_REG_VOL1 "Vol1"
#define SS_YAML_KEY_REG_VOL2 "Vol2"
#define SS_YAML_KEY_REG_ENV_PERIOD "Env Period"
#define SS_YAML_KEY_REG_ENV_SHAPE "Env Shape"
#define SS_YAML_KEY_REG_PORTA "PortA"
#define SS_YAML_KEY_REG_PORTB "PortB"
#define SS_YAML_KEY_CHANGE "Change"
#define SS_YAML_VALUE_CHANGE_FORMAT "%d, %d, 0x%1X, 0x%02X"
void CAY8910::SaveSnapshot(YamlSaveHelper& yamlSaveHelper, std::string& suffix)
{
std::string unit = std::string(SS_YAML_KEY_AY8910) + suffix;
YamlSaveHelper::Label label(yamlSaveHelper, "%s:\n", unit.c_str());
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE0_TICK, ay_tone_tick[0]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE1_TICK, ay_tone_tick[1]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE2_TICK, ay_tone_tick[2]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE0_HIGH, ay_tone_high[0]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE1_HIGH, ay_tone_high[1]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE2_HIGH, ay_tone_high[2]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_TICK, ay_noise_tick);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE_SUBCYCLES, ay_tone_subcycles);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_SUBCYCLES, ay_env_subcycles);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_INTERNAL_TICK, ay_env_internal_tick);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_TICK, ay_env_tick);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TICK_INCR, ay_tick_incr);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE0_PERIOD, ay_tone_period[0]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE1_PERIOD, ay_tone_period[1]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TONE2_PERIOD, ay_tone_period[2]);
yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_PERIOD, ay_noise_period);
yamlSaveHelper.SaveUint(SS_YAML_KEY_RNG, rng);
yamlSaveHelper.SaveUint(SS_YAML_KEY_NOISE_TOGGLE, noise_toggle);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_FIRST, env_first);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_REV, env_rev);
yamlSaveHelper.SaveUint(SS_YAML_KEY_ENV_COUNTER, env_counter);
// New label
{
YamlSaveHelper::Label registers(yamlSaveHelper, "%s:\n", SS_YAML_KEY_REGISTERS);
yamlSaveHelper.SaveHexUint12(SS_YAML_KEY_REG_TONE0_PERIOD, (UINT)(sound_ay_registers[1]<<8) | sound_ay_registers[0]);
yamlSaveHelper.SaveHexUint12(SS_YAML_KEY_REG_TONE1_PERIOD, (UINT)(sound_ay_registers[3]<<8) | sound_ay_registers[2]);
yamlSaveHelper.SaveHexUint12(SS_YAML_KEY_REG_TONE2_PERIOD, (UINT)(sound_ay_registers[5]<<8) | sound_ay_registers[4]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_NOISE_PERIOD, sound_ay_registers[6]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_MIXER, sound_ay_registers[7]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_VOL0, sound_ay_registers[8]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_VOL1, sound_ay_registers[9]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_VOL2, sound_ay_registers[10]);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REG_ENV_PERIOD, (UINT)(sound_ay_registers[12]<<8) | sound_ay_registers[11]);
yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_REG_ENV_SHAPE, sound_ay_registers[13]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_PORTA, sound_ay_registers[14]);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REG_PORTB, sound_ay_registers[15]);
}
// New label
if (ay_change_count)
{
YamlSaveHelper::Label change(yamlSaveHelper, "%s:\n", SS_YAML_KEY_CHANGE);
for (int i=0; i<ay_change_count; i++)
yamlSaveHelper.Save("0x%04X: " SS_YAML_VALUE_CHANGE_FORMAT "\n", i, ay_change[i].tstates, ay_change[i].ofs, ay_change[i].reg, ay_change[i].val);
}
}
bool CAY8910::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, std::string& suffix)
{
std::string unit = std::string(SS_YAML_KEY_AY8910) + suffix;
if (!yamlLoadHelper.GetSubMap(unit))
throw std::string("Card: Expected key: ") + unit;
ay_tone_tick[0] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE0_TICK);
ay_tone_tick[1] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE1_TICK);
ay_tone_tick[2] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE2_TICK);
ay_tone_high[0] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE0_HIGH);
ay_tone_high[1] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE1_HIGH);
ay_tone_high[2] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE2_HIGH);
ay_noise_tick = yamlLoadHelper.LoadUint(SS_YAML_KEY_NOISE_TICK);
ay_tone_subcycles = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE_SUBCYCLES);
ay_env_subcycles = yamlLoadHelper.LoadUint(SS_YAML_KEY_ENV_SUBCYCLES);
ay_env_internal_tick = yamlLoadHelper.LoadUint(SS_YAML_KEY_ENV_INTERNAL_TICK);
ay_env_tick = yamlLoadHelper.LoadUint(SS_YAML_KEY_ENV_TICK);
ay_tick_incr = yamlLoadHelper.LoadUint(SS_YAML_KEY_TICK_INCR);
ay_tone_period[0] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE0_PERIOD);
ay_tone_period[1] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE1_PERIOD);
ay_tone_period[2] = yamlLoadHelper.LoadUint(SS_YAML_KEY_TONE2_PERIOD);
ay_noise_period = yamlLoadHelper.LoadUint(SS_YAML_KEY_NOISE_PERIOD);
rng = yamlLoadHelper.LoadUint(SS_YAML_KEY_RNG);
noise_toggle = yamlLoadHelper.LoadUint(SS_YAML_KEY_NOISE_TOGGLE);
env_first = yamlLoadHelper.LoadUint(SS_YAML_KEY_ENV_FIRST);
env_rev = yamlLoadHelper.LoadUint(SS_YAML_KEY_ENV_REV);
env_counter = yamlLoadHelper.LoadUint(SS_YAML_KEY_ENV_COUNTER);
if (!yamlLoadHelper.GetSubMap(SS_YAML_KEY_REGISTERS))
throw std::string("Card: Expected key: ") + SS_YAML_KEY_REGISTERS;
USHORT period = (USHORT) yamlLoadHelper.LoadUint(SS_YAML_KEY_REG_TONE0_PERIOD);
sound_ay_registers[0] = period & 0xff;
sound_ay_registers[1] = (period >> 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;
}

View File

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

View File

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

View File

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

View File

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

View File

@ -1,6 +1,7 @@
#pragma once
typedef struct _regsrec {
struct regsrec
{
BYTE a; // accumulator
BYTE x; // index X
BYTE y; // index Y
@ -8,7 +9,7 @@ typedef struct _regsrec {
WORD pc; // program counter
WORD sp; // stack pointer
BYTE bJammed; // CPU has crashed (NMOS 6502 only)
} regsrec, *regsptr;
};
extern regsrec regs;
extern unsigned __int64 g_nCumulativeCycles;
@ -26,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);

View File

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

View File

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

View File

@ -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 <stdint.h> uint8_t
typedef unsigned short u16; // TODO: change to <stdint.h> 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 <stdint.h> 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 $

View File

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

View File

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

View File

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

View File

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

View File

@ -1,10 +1,13 @@
#pragma once
class CConfigNeedingRestart;
__interface IPropertySheet
{
void Init(void);
DWORD GetVolumeMax(void); // TODO:TC: Move out of here
bool SaveStateSelectImage(HWND hWindow, bool bSave); // TODO:TC: Move out of here
void ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld);
UINT GetScrollLockToggle(void);
void SetScrollLockToggle(UINT uValue);

View File

@ -22,7 +22,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
#include "..\Structs.h"
#include "..\Common.h"
#include "..\ParallelPrinter.h"

View File

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

View File

@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
#include "..\Structs.h"
#include "..\SaveState_Structs_common.h"
#include "..\Common.h"
#include "..\Keyboard.h"
@ -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<nJC_MAX; i++)
{
if( ( (i == nJC_KEYBD_CURSORS) || (i == nJC_KEYBD_NUMPAD) ) &&
( (joytype[nOtherJoyNum] == nJC_KEYBD_CURSORS) || (joytype[nOtherJoyNum] == nJC_KEYBD_NUMPAD) )
( (JoyGetJoyType(nOtherJoyNum) == nJC_KEYBD_CURSORS) || (JoyGetJoyType(nOtherJoyNum) == nJC_KEYBD_NUMPAD) )
)
{
continue;
@ -314,7 +314,7 @@ void CPageInput::InitJoystickChoices(HWND hWnd, int nJoyNum, int nIdcValue)
if (i == nJC_MOUSE && bIsSlot4Mouse)
continue;
if(joytype[nOtherJoyNum] != i)
if (JoyGetJoyType(nOtherJoyNum) != i)
{
memcpy(pszMem, ppszJoyChoices[i], strlen(ppszJoyChoices[i])+1);
pszMem += strlen(ppszJoyChoices[i])+1;
@ -324,7 +324,7 @@ void CPageInput::InitJoystickChoices(HWND hWnd, int nJoyNum, int nIdcValue)
*pszMem = 0x00; // Doubly null terminated
m_PropertySheetHelper.FillComboBox(hWnd, nIdcValue, pnzJoystickChoices, joytype[nJoyNum]);
m_PropertySheetHelper.FillComboBox(hWnd, nIdcValue, pnzJoystickChoices, JoyGetJoyType(nJoyNum));
}
void CPageInput::InitSlotOptions(HWND hWnd)

View File

@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
#include "..\Structs.h"
#include "..\SaveState_Structs_common.h"
#include "..\Common.h"
#include "..\Mockingboard.h"
@ -93,6 +93,10 @@ BOOL CPageSound::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
if (NewSoundcardConfigured(hWnd, wparam, CT_Phasor))
InitOptions(hWnd); // re-init
break;
case IDC_SAM_ENABLE:
if (NewSoundcardConfigured(hWnd, wparam, CT_SAM))
InitOptions(hWnd); // re-init
break;
case IDC_SOUNDCARD_DISABLE:
if (NewSoundcardConfigured(hWnd, wparam, CT_Empty))
InitOptions(hWnd); // re-init
@ -114,7 +118,11 @@ BOOL CPageSound::DlgProcInternal(HWND hWnd, UINT message, WPARAM wparam, LPARAM
SendDlgItemMessage(hWnd,IDC_MB_VOLUME,TBM_SETTICFREQ,10,0);
SendDlgItemMessage(hWnd,IDC_MB_VOLUME,TBM_SETPOS,1,MB_GetVolume());
m_NewCardType = MB_GetSoundcardType(); // Reinit 1st time page is activated (fires before PSN_SETACTIVE)
if (g_Slot5 == CT_SAM)
m_NewCardType = CT_SAM;
else
m_NewCardType = MB_GetSoundcardType(); // Reinit 1st time page is activated (fires before PSN_SETACTIVE)
InitOptions(hWnd);
break;
@ -153,6 +161,8 @@ void CPageSound::InitOptions(HWND hWnd)
m_nCurrentIDCheckButton = IDC_MB_ENABLE;
else if(m_NewCardType == CT_Phasor)
m_nCurrentIDCheckButton = IDC_PHASOR_ENABLE;
else if(m_NewCardType == CT_SAM)
m_nCurrentIDCheckButton = IDC_SAM_ENABLE;
else
m_nCurrentIDCheckButton = IDC_SOUNDCARD_DISABLE;
@ -168,16 +178,23 @@ void CPageSound::InitOptions(HWND hWnd)
// Phasor button
{
const BOOL bEnable = bIsSlot4Empty || Slot4 == CT_MockingboardC;
const BOOL bEnable = bIsSlot4Empty || Slot4 == CT_MockingboardC || Slot4 == CT_Phasor;
EnableWindow(GetDlgItem(hWnd, IDC_PHASOR_ENABLE), bEnable); // Disable Phasor (slot 4)
}
// Mockingboard button
{
const BOOL bEnable = (bIsSlot4Empty || Slot4 == CT_Phasor) && bIsSlot5Empty;
const BOOL bEnable = (bIsSlot4Empty || Slot4 == CT_Phasor || Slot4 == CT_MockingboardC) &&
(bIsSlot5Empty || Slot5 == CT_SAM || Slot5 == CT_MockingboardC);
EnableWindow(GetDlgItem(hWnd, IDC_MB_ENABLE), bEnable); // Disable Mockingboard (slot 4 & 5)
}
// SAM button
{
const BOOL bEnable = bIsSlot5Empty || Slot5 == CT_MockingboardC || Slot5 == CT_SAM;
EnableWindow(GetDlgItem(hWnd, IDC_SAM_ENABLE), bEnable); // Disable SAM (slot 5)
}
EnableWindow(GetDlgItem(hWnd, IDC_MB_VOLUME), (m_nCurrentIDCheckButton != IDC_SOUNDCARD_DISABLE) ? TRUE : FALSE);
}
@ -191,6 +208,7 @@ bool CPageSound::NewSoundcardConfigured(HWND hWnd, WPARAM wparam, SS_CARDTYPE Ne
m_NewCardType = NewCardType;
const SS_CARDTYPE Slot4 = m_PropertySheetHelper.GetConfigNew().m_Slot[4];
const SS_CARDTYPE Slot5 = m_PropertySheetHelper.GetConfigNew().m_Slot[5];
if (NewCardType == CT_MockingboardC)
@ -201,13 +219,20 @@ bool CPageSound::NewSoundcardConfigured(HWND hWnd, WPARAM wparam, SS_CARDTYPE Ne
else if (NewCardType == CT_Phasor)
{
m_PropertySheetHelper.GetConfigNew().m_Slot[4] = CT_Phasor;
if (Slot5 == CT_MockingboardC)
if ((Slot5 == CT_MockingboardC) || (Slot5 == CT_SAM))
m_PropertySheetHelper.GetConfigNew().m_Slot[5] = CT_Empty;
}
else if (NewCardType == CT_SAM)
{
if ((Slot4 == CT_MockingboardC) || (Slot4 == CT_Phasor))
m_PropertySheetHelper.GetConfigNew().m_Slot[4] = CT_Empty;
m_PropertySheetHelper.GetConfigNew().m_Slot[5] = CT_SAM;
}
else
{
m_PropertySheetHelper.GetConfigNew().m_Slot[4] = CT_Empty;
if (Slot5 == CT_MockingboardC)
if ((Slot4 == CT_MockingboardC) || (Slot4 == CT_Phasor))
m_PropertySheetHelper.GetConfigNew().m_Slot[4] = CT_Empty;
if ((Slot5 == CT_MockingboardC) || (Slot5 == CT_SAM))
m_PropertySheetHelper.GetConfigNew().m_Slot[5] = CT_Empty;
}

View File

@ -24,6 +24,10 @@ public:
virtual void Init(void);
virtual DWORD GetVolumeMax(void); // TODO:TC: Move out of here
virtual bool SaveStateSelectImage(HWND hWindow, bool bSave); // TODO:TC: Move out of here
void ApplyNewConfig(const CConfigNeedingRestart& ConfigNew, const CConfigNeedingRestart& ConfigOld)
{
m_PropertySheetHelper.ApplyNewConfig(ConfigNew, ConfigOld);
}
virtual UINT GetScrollLockToggle(void){ return m_PageInput.GetScrollLockToggle(); }
virtual void SetScrollLockToggle(UINT uValue){ m_PageInput.SetScrollLockToggle(uValue); }

View File

@ -44,7 +44,7 @@ Input
. Mouse WM_USER_RESTART
. CP/M WM_USER_RESTART
Sound
. MB/Phasor/None WM_USER_RESTART
. MB/Phasor/SAM/None WM_USER_RESTART
Disk
. Enhanced disk speed WM_USER_RESTART Why? (used to patch Disk][ f/w - but not anymore)
. HDD enable WM_USER_RESTART
@ -102,6 +102,11 @@ void CPropertySheetHelper::SaveComputerType(eApple2Type NewApple2Type)
REGSAVE(TEXT(REGVALUE_APPLE2_TYPE), NewApple2Type);
}
void CPropertySheetHelper::SaveCpuType(eCpuType NewCpuType)
{
REGSAVE(TEXT(REGVALUE_CPU_TYPE), NewCpuType);
}
void CPropertySheetHelper::SetSlot4(SS_CARDTYPE NewCardType)
{
g_Slot4 = NewCardType;
@ -186,7 +191,7 @@ void CPropertySheetHelper::GetDiskBaseNameWithAWS(TCHAR* pszFilename)
if (pDiskName && pDiskName[0])
{
strcpy(pszFilename, pDiskName);
strcpy(&pszFilename[strlen(pDiskName)], ".aws");
strcpy(&pszFilename[strlen(pDiskName)], ".aws.yaml");
}
}
@ -230,9 +235,17 @@ int CPropertySheetHelper::SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bo
ofn.lStructSize = sizeof(OPENFILENAME);
ofn.hwndOwner = hWindow;
ofn.hInstance = g_hInstance;
ofn.lpstrFilter = TEXT("Save State files (*.aws)\0*.aws\0")
TEXT("All Files\0*.*\0");
ofn.lpstrFile = szFilename;
if (bSave)
{
ofn.lpstrFilter = TEXT("Save State files (*.aws.yaml)\0*.aws.yaml\0");
TEXT("All Files\0*.*\0");
}
else
{
ofn.lpstrFilter = TEXT("Save State files (*.aws,*.aws.yaml)\0*.aws;*.aws.yaml\0");
TEXT("All Files\0*.*\0");
}
ofn.lpstrFile = szFilename; // Dialog strips the last .EXT from this string (eg. file.aws.yaml is displayed as: file.aws
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = szDirectory;
ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY;
@ -242,18 +255,39 @@ int CPropertySheetHelper::SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bo
if(nRes)
{
strcpy(m_szSSNewFilename, &szFilename[ofn.nFileOffset]);
if (bSave) // Only for saving (allow loading of any file for backwards compatibility)
{
// Append .aws if it's not there
const char szAWS_EXT[] = ".aws";
const UINT uStrLenFile = strlen(m_szSSNewFilename);
const UINT uStrLenExt = strlen(szAWS_EXT);
if ((uStrLenFile <= uStrLenExt) || (strcmp(&m_szSSNewFilename[uStrLenFile-uStrLenExt], szAWS_EXT) != 0))
strcpy(&m_szSSNewFilename[uStrLenFile], szAWS_EXT);
// Append .aws.yaml if it's not there
const char szAWS_EXT1[] = ".aws";
const char szAWS_EXT2[] = ".yaml";
const char szAWS_EXT3[] = ".aws.yaml";
const UINT uStrLenFile = strlen(&szFilename[ofn.nFileOffset]);
const UINT uStrLenExt1 = strlen(szAWS_EXT1);
const UINT uStrLenExt2 = strlen(szAWS_EXT2);
const UINT uStrLenExt3 = strlen(szAWS_EXT3);
if (uStrLenFile <= uStrLenExt1)
{
strcpy(&szFilename[ofn.nFileOffset+uStrLenFile], szAWS_EXT3); // "file" += ".aws.yaml"
}
else if (uStrLenFile <= uStrLenExt2)
{
if (strcmp(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt1], szAWS_EXT1) == 0)
strcpy(&szFilename[ofn.nFileOffset+uStrLenFile-uStrLenExt1], szAWS_EXT3); // "file.aws" -> "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);

View File

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

View File

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

View File

@ -1,6 +1,6 @@
#pragma once
#include "..\Structs.h"
#include "..\SaveState_Structs_v1.h" // For SS_CARD_MOCKINGBOARD
#include "..\Common.h"
#include "Debugger_Types.h"

View File

@ -565,7 +565,6 @@ bool _6502_GetStackReturnAddress ( WORD & nAddress_ )
if (nStack <= (_6502_STACK_END - 1))
{
nAddress_ = 0;
nAddress_ = (unsigned)*(LPBYTE)(mem + nStack);
nStack++;

View File

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

View File

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

View File

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

View File

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

View File

@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-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 ]; // <FILENAME> (ie. no extension)
TCHAR fullname [ MAX_DISK_FULL_NAME + 1 ]; // <FILENAME.EXT> or <FILENAME.zip> : This is persisted to the snapshot file
std::string strDiskPathFilename;
std::string strFilenameInZip; // 0x00 or <FILENAME.EXT>
std::string strFilenameInZip; // "" or <FILENAME.EXT>
HIMAGE imagehandle; // Init'd by DiskInsert() -> ImageOpen()
bool bWriteProtected;
//
int track;
LPBYTE trackimage;
int phase;
int byte;
bool bWriteProtected;
BOOL trackimagedata;
BOOL trackimagedirty;
DWORD spinning;
@ -86,14 +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 = <FILENAME.EXT>
if (_tcsrchr(startpos,TEXT('\\')))
startpos = _tcsrchr(startpos,TEXT('\\'))+1;
_tcsncpy(imagetitle,startpos,MAX_DISK_FULL_NAME);
imagetitle[MAX_DISK_FULL_NAME] = 0;
// if imagetitle contains a lowercase char, then found=1 (why?)
BOOL found = 0;
int loop = 0;
while (imagetitle[loop] && !found)
{
if (IsCharLower(imagetitle[loop]))
found = 1;
else
loop++;
}
if ((!found) && (loop > 2))
CharLowerBuff(imagetitle+1,_tcslen(imagetitle+1));
// fptr->fullname = <FILENAME.EXT>
_tcsncpy( fptr->fullname, imagetitle, MAX_DISK_FULL_NAME );
fptr->fullname[ MAX_DISK_FULL_NAME ] = 0;
if (imagetitle[0])
{
LPTSTR dot = imagetitle;
if (_tcsrchr(dot,TEXT('.')))
dot = _tcsrchr(dot,TEXT('.'));
if (dot > imagetitle)
*dot = 0;
}
// fptr->imagename = <FILENAME> (ie. no extension)
_tcsncpy( fptr->imagename, imagetitle, MAX_DISK_IMAGE_NAME );
fptr->imagename[ MAX_DISK_IMAGE_NAME ] = 0;
}
//===========================================================================
static bool IsDriveValid(const int iDrive)
@ -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; i<NUM_DRIVES; i++)
{
strcpy(pSS->Unit[i].szFileName, g_aFloppyDisk[i].fullname);
pSS->Unit[i].track = g_aFloppyDisk[i].track;
pSS->Unit[i].phase = g_aFloppyDisk[i].phase;
pSS->Unit[i].byte = g_aFloppyDisk[i].byte;
pSS->Unit[i].writeprotected = g_aFloppyDisk[i].bWriteProtected ? TRUE : FALSE;
pSS->Unit[i].trackimagedata = g_aFloppyDisk[i].trackimagedata;
pSS->Unit[i].trackimagedirty = g_aFloppyDisk[i].trackimagedirty;
pSS->Unit[i].spinning = g_aFloppyDisk[i].spinning;
pSS->Unit[i].writelight = g_aFloppyDisk[i].writelight;
pSS->Unit[i].nibbles = g_aFloppyDisk[i].nibbles;
if(g_aFloppyDisk[i].trackimage)
memcpy(pSS->Unit[i].nTrack, g_aFloppyDisk[i].trackimage, NIBBLES_PER_TRACK);
else
memset(pSS->Unit[i].nTrack, 0, NIBBLES_PER_TRACK);
}
return 0;
}
DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
{
if(pSS->Hdr.UnitHdr.dwVersion > MAKE_VERSION(1,0,0,2))
{
return -1;
}
phases = pSS->phases; // new in 1.0.0.2 disk snapshots
currdrive = pSS->currdrive; // this was an int in 1.0.0.1 disk snapshots
phases = pSS->phases;
currdrive = pSS->currdrive;
diskaccessed = pSS->diskaccessed;
enhancedisk = pSS->enhancedisk;
floppylatch = pSS->floppylatch;
@ -1157,7 +1100,7 @@ DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
for(UINT i=0; i<NUM_DRIVES; i++)
{
DiskEject(i); // Remove any disk & update Registry to reflect empty drive
ZeroMemory(&g_aFloppyDisk[i], sizeof(Disk_t ));
ZeroMemory(&g_aFloppyDisk[i], sizeof(Disk_t));
}
for(UINT i=0; i<NUM_DRIVES; i++)
@ -1183,7 +1126,6 @@ DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
// DiskInsert() sets up:
// . imagename
// . fullname
// . strDiskPathFilename
// . writeprotected
}
@ -1225,3 +1167,181 @@ DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD /*dwSlot*/)
return 0;
}
//===========================================================================
#define SS_YAML_VALUE_CARD_DISK2 "Disk]["
#define SS_YAML_KEY_PHASES "Phases"
#define SS_YAML_KEY_CURRENT_DRIVE "Current Drive"
#define SS_YAML_KEY_DISK_ACCESSED "Disk Accessed"
#define SS_YAML_KEY_ENHANCE_DISK "Enhance Disk"
#define SS_YAML_KEY_FLOPPY_LATCH "Floppy Latch"
#define SS_YAML_KEY_FLOPPY_MOTOR_ON "Floppy Motor On"
#define SS_YAML_KEY_FLOPPY_WRITE_MODE "Floppy Write Mode"
#define SS_YAML_KEY_DISK2UNIT "Unit"
#define SS_YAML_KEY_FILENAME "Filename"
#define SS_YAML_KEY_TRACK "Track"
#define SS_YAML_KEY_PHASE "Phase"
#define SS_YAML_KEY_BYTE "Byte"
#define SS_YAML_KEY_WRITE_PROTECTED "Write Protected"
#define SS_YAML_KEY_SPINNING "Spinning"
#define SS_YAML_KEY_WRITE_LIGHT "Write Light"
#define SS_YAML_KEY_NIBBLES "Nibbles"
#define SS_YAML_KEY_TRACK_IMAGE_DATA "Track Image Data"
#define SS_YAML_KEY_TRACK_IMAGE_DIRTY "Track Image Dirty"
#define SS_YAML_KEY_TRACK_IMAGE "Track Image"
std::string DiskGetSnapshotCardName(void)
{
static const std::string name(SS_YAML_VALUE_CARD_DISK2);
return name;
}
static void DiskSaveSnapshotDisk2Unit(YamlSaveHelper& yamlSaveHelper, UINT unit)
{
YamlSaveHelper::Label label(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_DISK2UNIT, unit);
yamlSaveHelper.SaveString(SS_YAML_KEY_FILENAME, g_aFloppyDisk[unit].fullname);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TRACK, g_aFloppyDisk[unit].track);
yamlSaveHelper.SaveUint(SS_YAML_KEY_PHASE, g_aFloppyDisk[unit].phase);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_BYTE, g_aFloppyDisk[unit].byte);
yamlSaveHelper.SaveBool(SS_YAML_KEY_WRITE_PROTECTED, g_aFloppyDisk[unit].bWriteProtected);
yamlSaveHelper.SaveUint(SS_YAML_KEY_SPINNING, g_aFloppyDisk[unit].spinning);
yamlSaveHelper.SaveUint(SS_YAML_KEY_WRITE_LIGHT, g_aFloppyDisk[unit].writelight);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_NIBBLES, g_aFloppyDisk[unit].nibbles);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TRACK_IMAGE_DATA, g_aFloppyDisk[unit].trackimagedata);
yamlSaveHelper.SaveUint(SS_YAML_KEY_TRACK_IMAGE_DIRTY, g_aFloppyDisk[unit].trackimagedirty);
if (g_aFloppyDisk[unit].trackimage)
{
YamlSaveHelper::Label image(yamlSaveHelper, "%s:\n", SS_YAML_KEY_TRACK_IMAGE);
yamlSaveHelper.SaveMemory(g_aFloppyDisk[unit].trackimage, NIBBLES_PER_TRACK);
}
}
void DiskSaveSnapshot(class YamlSaveHelper& yamlSaveHelper)
{
YamlSaveHelper::Slot slot(yamlSaveHelper, DiskGetSnapshotCardName(), g_uSlot, 1);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.SaveHexUint4(SS_YAML_KEY_PHASES, phases);
yamlSaveHelper.SaveUint(SS_YAML_KEY_CURRENT_DRIVE, currdrive);
yamlSaveHelper.SaveBool(SS_YAML_KEY_DISK_ACCESSED, diskaccessed == TRUE);
yamlSaveHelper.SaveBool(SS_YAML_KEY_ENHANCE_DISK, enhancedisk == TRUE);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_FLOPPY_LATCH, floppylatch);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_MOTOR_ON, floppymotoron == TRUE);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_WRITE_MODE, floppywritemode == TRUE);
DiskSaveSnapshotDisk2Unit(yamlSaveHelper, DRIVE_1);
DiskSaveSnapshotDisk2Unit(yamlSaveHelper, DRIVE_2);
}
static void DiskLoadSnapshotDriveUnit(YamlLoadHelper& yamlLoadHelper, UINT unit)
{
std::string disk2UnitName = std::string(SS_YAML_KEY_DISK2UNIT) + (unit == DRIVE_1 ? std::string("0") : std::string("1"));
if (!yamlLoadHelper.GetSubMap(disk2UnitName))
throw std::string("Card: Expected key: ") + disk2UnitName;
bool bImageError = false;
g_aFloppyDisk[unit].fullname[0] = 0;
g_aFloppyDisk[unit].imagename[0] = 0;
g_aFloppyDisk[unit].bWriteProtected = false; // Default to false (until image is successfully loaded below)
std::string filename = yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME);
if (!filename.empty())
{
DWORD dwAttributes = GetFileAttributes(filename.c_str());
if(dwAttributes == INVALID_FILE_ATTRIBUTES)
{
// Get user to browse for file
DiskSelectImage(unit, filename.c_str());
dwAttributes = GetFileAttributes(filename.c_str());
}
bImageError = (dwAttributes == INVALID_FILE_ATTRIBUTES);
if (!bImageError)
{
if(DiskInsert(unit, filename.c_str(), dwAttributes & FILE_ATTRIBUTE_READONLY, IMAGE_DONT_CREATE) != eIMAGE_ERROR_NONE)
bImageError = true;
// DiskInsert() zeros g_aFloppyDisk[unit], then sets up:
// . imagename
// . fullname
// . writeprotected
}
}
g_aFloppyDisk[unit].track = yamlLoadHelper.LoadUint(SS_YAML_KEY_TRACK);
g_aFloppyDisk[unit].phase = yamlLoadHelper.LoadUint(SS_YAML_KEY_PHASE);
g_aFloppyDisk[unit].byte = yamlLoadHelper.LoadUint(SS_YAML_KEY_BYTE);
yamlLoadHelper.LoadBool(SS_YAML_KEY_WRITE_PROTECTED); // Consume
g_aFloppyDisk[unit].spinning = yamlLoadHelper.LoadUint(SS_YAML_KEY_SPINNING);
g_aFloppyDisk[unit].writelight = yamlLoadHelper.LoadUint(SS_YAML_KEY_WRITE_LIGHT);
g_aFloppyDisk[unit].nibbles = yamlLoadHelper.LoadUint(SS_YAML_KEY_NIBBLES);
g_aFloppyDisk[unit].trackimagedata = yamlLoadHelper.LoadUint(SS_YAML_KEY_TRACK_IMAGE_DATA);
g_aFloppyDisk[unit].trackimagedirty = yamlLoadHelper.LoadUint(SS_YAML_KEY_TRACK_IMAGE_DIRTY);
std::auto_ptr<BYTE> 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; i<NUM_DRIVES; i++)
{
DiskEject(i); // Remove any disk & update Registry to reflect empty drive
ZeroMemory(&g_aFloppyDisk[i], sizeof(Disk_t));
}
DiskLoadSnapshotDriveUnit(yamlLoadHelper, DRIVE_1);
DiskLoadSnapshotDriveUnit(yamlLoadHelper, DRIVE_2);
FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
return true;
}

View File

@ -40,7 +40,7 @@ const bool IMAGE_DONT_CREATE = false;
const bool IMAGE_CREATE = true;
extern BOOL enhancedisk;
const std::string& DiskGetDiskPathFilename(const int iDrive);
const char* DiskGetDiskPathFilename(const int iDrive);
void DiskInitialize(void); // DiskIIManagerStartup()
void DiskDestroy(void); // no, doesn't "destroy" the disk image. DiskIIManagerShutdown()
@ -70,8 +70,11 @@ void DiskSelect(const int iDrive);
void DiskUpdatePosition(DWORD);
bool DiskDriveSwap(void);
void DiskLoadRom(LPBYTE pCxRomPeripheral, UINT uSlot);
DWORD DiskGetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot);
DWORD DiskSetSnapshot(SS_CARD_DISK2* pSS, DWORD dwSlot);
int DiskSetSnapshot_v1(const struct SS_CARD_DISK2* const pSS);
std::string DiskGetSnapshotCardName(void);
void DiskSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
bool DiskLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
void Disk_LoadLastDiskImage(const int iDrive);
void Disk_SaveLastDiskImage(const int iDrive);

View File

@ -27,7 +27,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "StdAfx.h"
#include "Structs.h"
#include "Common.h"
#include "DiskImage.h"
@ -40,32 +39,37 @@ static CDiskImageHelper sg_DiskImageHelper;
// Pre: *pWriteProtected_ already set to file's r/w status - see DiskInsert()
ImageError_e ImageOpen( LPCTSTR pszImageFilename,
HIMAGE* hDiskImage_,
bool* pWriteProtected_,
HIMAGE* hDiskImage,
bool* pWriteProtected,
const bool bCreateIfNecessary,
std::string& strFilenameInZip)
std::string& strFilenameInZip,
const bool bExpectFloppy /*=true*/)
{
if (! (pszImageFilename && hDiskImage_ && pWriteProtected_ && sg_DiskImageHelper.GetWorkBuffer()))
if (! (pszImageFilename && hDiskImage && pWriteProtected && sg_DiskImageHelper.GetWorkBuffer()))
return eIMAGE_ERROR_BAD_POINTER;
// CREATE A RECORD FOR THE FILE, AND RETURN AN IMAGE HANDLE
*hDiskImage_ = (HIMAGE) VirtualAlloc(NULL, sizeof(ImageInfo), MEM_COMMIT, PAGE_READWRITE);
if (*hDiskImage_ == NULL)
*hDiskImage = (HIMAGE) VirtualAlloc(NULL, sizeof(ImageInfo), MEM_COMMIT, PAGE_READWRITE);
if (*hDiskImage == NULL)
return eIMAGE_ERROR_BAD_POINTER;
ZeroMemory(*hDiskImage_, sizeof(ImageInfo));
ImageInfo* pImageInfo = (ImageInfo*) *hDiskImage_;
pImageInfo->bWriteProtected = *pWriteProtected_;
ZeroMemory(*hDiskImage, sizeof(ImageInfo));
ImageInfo* pImageInfo = (ImageInfo*) *hDiskImage;
pImageInfo->bWriteProtected = *pWriteProtected;
ImageError_e Err = sg_DiskImageHelper.Open(pszImageFilename, pImageInfo, bCreateIfNecessary, strFilenameInZip);
if (pImageInfo->pImageType != NULL && Err == eIMAGE_ERROR_NONE && pImageInfo->pImageType->GetType() == eImageHDV)
Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
if (Err != eIMAGE_ERROR_NONE)
{
ImageClose(*hDiskImage_, true);
*hDiskImage_ = (HIMAGE)0;
ImageClose(*hDiskImage, true);
*hDiskImage = (HIMAGE)0;
return Err;
}
if (pImageInfo->pImageType && pImageInfo->pImageType->GetType() == eImageHDV)
{
if (bExpectFloppy)
Err = eIMAGE_ERROR_UNSUPPORTED_HDV;
return Err;
}
@ -76,7 +80,7 @@ ImageError_e ImageOpen( LPCTSTR pszImageFilename,
for (UINT uTrack = 0; uTrack < pImageInfo->uNumTracks; uTrack++)
pImageInfo->ValidTrack[uTrack] = (pImageInfo->uImageSize > 0) ? 1 : 0;
*pWriteProtected_ = pImageInfo->bWriteProtected;
*pWriteProtected = pImageInfo->bWriteProtected;
return eIMAGE_ERROR_NONE;
}
@ -185,6 +189,36 @@ void ImageWriteTrack( const HIMAGE hDiskImage,
//===========================================================================
bool ImageReadBlock( const HIMAGE hDiskImage,
UINT nBlock,
LPBYTE pBlockBuffer)
{
ImageInfo* ptr = (ImageInfo*) hDiskImage;
bool bRes = false;
if (ptr->pImageType->AllowRW())
bRes = ptr->pImageType->Read(ptr, nBlock, pBlockBuffer);
return bRes;
}
//===========================================================================
bool ImageWriteBlock( const HIMAGE hDiskImage,
UINT nBlock,
LPBYTE pBlockBuffer)
{
ImageInfo* ptr = (ImageInfo*) hDiskImage;
bool bRes = false;
if (ptr->pImageType->AllowRW() && !ptr->bWriteProtected)
bRes = ptr->pImageType->Write(ptr, nBlock, pBlockBuffer);
return bRes;
}
//===========================================================================
int ImageGetNumTracks(const HIMAGE hDiskImage)
{
ImageInfo* ptr = (ImageInfo*) hDiskImage;
@ -202,3 +236,60 @@ bool ImageIsMultiFileZip(const HIMAGE hDiskImage)
ImageInfo* ptr = (ImageInfo*) hDiskImage;
return ptr ? (ptr->uNumEntriesInZip > 1) : false;
}
const char* ImageGetPathname(const HIMAGE hDiskImage)
{
static char* szEmpty = "";
ImageInfo* ptr = (ImageInfo*) hDiskImage;
return ptr ? ptr->szFilename : szEmpty;
}
UINT ImageGetImageSize(const HIMAGE hDiskImage)
{
ImageInfo* ptr = (ImageInfo*) hDiskImage;
return ptr ? ptr->uImageSize : 0;
}
void GetImageTitle(LPCTSTR pPathname, TCHAR* pImageName, TCHAR* pFullName)
{
TCHAR imagetitle[ MAX_DISK_FULL_NAME+1 ];
LPCTSTR startpos = pPathname;
// imagetitle = <FILENAME.EXT>
if (_tcsrchr(startpos, TEXT('\\')))
startpos = _tcsrchr(startpos, TEXT('\\'))+1;
_tcsncpy(imagetitle, startpos, MAX_DISK_FULL_NAME);
imagetitle[MAX_DISK_FULL_NAME] = 0;
// if imagetitle contains a lowercase char, then found=1 (why?)
BOOL found = 0;
int loop = 0;
while (imagetitle[loop] && !found)
{
if (IsCharLower(imagetitle[loop]))
found = 1;
else
loop++;
}
if ((!found) && (loop > 2))
CharLowerBuff(imagetitle+1, _tcslen(imagetitle+1));
// pFullName = <FILENAME.EXT>
_tcsncpy( pFullName, imagetitle, MAX_DISK_FULL_NAME );
pFullName[ MAX_DISK_FULL_NAME ] = 0;
if (imagetitle[0])
{
LPTSTR dot = imagetitle;
if (_tcsrchr(dot, TEXT('.')))
dot = _tcsrchr(dot, TEXT('.'));
if (dot > imagetitle)
*dot = 0;
}
// pImageName = <FILENAME> (ie. no extension)
_tcsncpy( pImageName, imagetitle, MAX_DISK_IMAGE_NAME );
pImageName[ MAX_DISK_IMAGE_NAME ] = 0;
}

View File

@ -55,9 +55,14 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
eIMAGE_ERROR_UNABLE_TO_OPEN,
eIMAGE_ERROR_UNABLE_TO_OPEN_GZ,
eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP,
eIMAGE_ERROR_FAILED_TO_GET_PATHNAME,
};
ImageError_e ImageOpen(LPCTSTR pszImageFilename, HIMAGE* hDiskImage_, bool* pWriteProtected_, const bool bCreateIfNecessary, std::string& strFilenameInZip);
const int MAX_DISK_IMAGE_NAME = 15;
const int MAX_DISK_FULL_NAME = 127;
ImageError_e ImageOpen(LPCTSTR pszImageFilename, HIMAGE* hDiskImage, bool* pWriteProtected, const bool bCreateIfNecessary, std::string& strFilenameInZip, const bool bExpectFloppy=true);
void ImageClose(const HIMAGE hDiskImage, const bool bOpenError=false);
BOOL ImageBoot(const HIMAGE hDiskImage);
void ImageDestroy(void);
@ -65,7 +70,13 @@ void ImageInitialize(void);
void ImageReadTrack(const HIMAGE hDiskImage, int nTrack, int nQuarterTrack, LPBYTE pTrackImageBuffer, int* pNibbles);
void ImageWriteTrack(const HIMAGE hDiskImage, int nTrack, int nQuarterTrack, LPBYTE pTrackImage, int nNibbles);
bool ImageReadBlock(const HIMAGE hDiskImage, UINT nBlock, LPBYTE pBlockBuffer);
bool ImageWriteBlock(const HIMAGE hDiskImage, UINT nBlock, LPBYTE pBlockBuffer);
int ImageGetNumTracks(const HIMAGE hDiskImage);
bool ImageIsWriteProtected(const HIMAGE hDiskImage);
bool ImageIsMultiFileZip(const HIMAGE hDiskImage);
const char* ImageGetPathname(const HIMAGE hDiskImage);
UINT ImageGetImageSize(const HIMAGE hDiskImage);
void GetImageTitle(LPCTSTR pPathname, TCHAR* pImageName, TCHAR* pFullName);

View File

@ -28,7 +28,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "stdafx.h"
#include "Structs.h"
#include "Common.h"
#include "zlib.h"
@ -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;
}

View File

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

View File

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

View File

@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
Copyright (C) 2006-2015, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -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 ]; // <FILENAME> (ie. no extension) [not used]
TCHAR fullname[ MAX_DISK_FULL_NAME + 1 ]; // <FILENAME.EXT> or <FILENAME.zip>
std::string strFilenameInZip; // "" or <FILENAME.EXT> [not used]
HIMAGE imagehandle; // Init'd by HD_Insert() -> ImageOpen()
bool bWriteProtected; // Needed for ImageOpen() [otherwise not used]
//
BYTE hd_error;
WORD hd_memblock;
UINT hd_diskblock;
WORD hd_buf_ptr;
BOOL hd_imageloaded;
BYTE hd_buf[HD_BLOCK_SIZE+1]; // Why +1?
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 = <FILENAME.EXT>
if (_tcsrchr(startpos,TEXT('\\')))
startpos = _tcsrchr(startpos,TEXT('\\'))+1;
_tcsncpy(imagetitle,startpos,127);
imagetitle[127] = 0;
// if imagetitle contains a lowercase char, then found=1 (why?)
BOOL found = 0;
int loop = 0;
while (imagetitle[loop] && !found)
{
if (IsCharLower(imagetitle[loop]))
found = 1;
else
loop++;
}
if ((!found) && (loop > 2))
CharLowerBuff(imagetitle+1,_tcslen(imagetitle+1));
// hdptr->fullname = <FILENAME.EXT>
_tcsncpy(pHardDrive->fullname,imagetitle,127);
pHardDrive->fullname[127] = 0;
if (imagetitle[0])
{
LPTSTR dot = imagetitle;
if (_tcsrchr(dot,TEXT('.')))
dot = _tcsrchr(dot,TEXT('.'));
if (dot > imagetitle)
*dot = 0;
}
// hdptr->imagename = <FILENAME> (ie. no extension)
_tcsncpy(pHardDrive->imagename,imagetitle,15);
pHardDrive->imagename[15] = 0;
}
static void NotifyInvalidImage(TCHAR* pszImageFilename)
{
// TC: TO DO
}
static BOOL HD_Load_Image(const int iDrive, LPCSTR pszImageFilename)
//===========================================================================
BOOL HD_Insert(const int iDrive, LPCTSTR pszImageFilename);
void HD_LoadLastDiskImage(const int iDrive)
{
const bool bCreateIfNecessary = false; // NB. Don't allow creation of HDV files
std::string strFilenameInZip; // TODO: Use this
ImageError_e Error = ImageOpen(pszImageFilename, iDrive, bCreateIfNecessary, strFilenameInZip);
_ASSERT(iDrive == HARDDISK_1 || iDrive == HARDDISK_2);
g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE);
char sFilePath[ MAX_PATH + 1];
sFilePath[0] = 0;
#if HD_LED
g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF;
g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
#endif
char *pRegKey = (iDrive == HARDDISK_1)
? REGVALUE_PREF_LAST_HARDDISK_1
: REGVALUE_PREF_LAST_HARDDISK_2;
return g_HardDisk[iDrive].hd_imageloaded;
if (RegLoadString(TEXT(REG_PREFS), pRegKey, 1, sFilePath, MAX_PATH))
{
sFilePath[ MAX_PATH ] = 0;
g_bSaveDiskImage = false;
// Pass in ptr to local copy of filepath, since RemoveDisk() sets DiskPathFilename = "" // todo: update comment for HD func
HD_Insert(iDrive, sFilePath);
g_bSaveDiskImage = true;
}
}
//===========================================================================
// everything below is global
static void HD_SaveLastDiskImage(const int iDrive)
{
_ASSERT(iDrive == HARDDISK_1 || iDrive == HARDDISK_2);
if (!g_bSaveDiskImage)
return;
const char *pFileName = g_HardDisk[iDrive].fullname;
if (iDrive == HARDDISK_1)
RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_HARDDISK_1, TRUE, pFileName);
else
RegSaveString(TEXT(REG_PREFS), REGVALUE_PREF_LAST_HARDDISK_2, TRUE, pFileName);
//
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<HARDDISK_2; i++)
{
HD_CleanupDrive(i);
}
g_bSaveDiskImage = false;
HD_CleanupDrive(HARDDISK_1);
g_bSaveDiskImage = false;
HD_CleanupDrive(HARDDISK_2);
g_bSaveDiskImage = true;
}
// pszImageFilename is qualified with path
BOOL HD_InsertDisk(const int iDrive, LPCTSTR pszImageFilename)
static BOOL HD_Insert(const int iDrive, LPCTSTR pszImageFilename)
{
if (*pszImageFilename == 0x00)
return false;
return FALSE;
if (g_HardDisk[iDrive].hd_imageloaded)
HD_CleanupDrive(iDrive);
HD_Unplug(iDrive);
// Check if image is being used by the other HDD, and unplug it in order to be swapped
if (!strcmp(HD_GetFullPathName(!iDrive), pszImageFilename)) {
HD_Unplug(!iDrive);
{
const char* pszOtherPathname = HD_GetFullPathName(!iDrive);
char szCurrentPathname[MAX_PATH];
DWORD uNameLen = GetFullPathName(pszImageFilename, MAX_PATH, szCurrentPathname, NULL);
if (uNameLen == 0 || uNameLen >= MAX_PATH)
strcpy_s(szCurrentPathname, MAX_PATH, pszImageFilename);
if (!strcmp(pszOtherPathname, szCurrentPathname))
{
HD_Unplug(!iDrive);
FrameRefreshStatus(DRAW_LEDS);
}
}
BOOL bResult = HD_Load_Image(iDrive, pszImageFilename);
const bool bCreateIfNecessary = false; // NB. Don't allow creation of HDV files
const bool bExpectFloppy = false;
ImageError_e Error = ImageOpen(pszImageFilename,
&g_HardDisk[iDrive].imagehandle,
&g_HardDisk[iDrive].bWriteProtected,
bCreateIfNecessary,
g_HardDisk[iDrive].strFilenameInZip, // TODO: Use this
bExpectFloppy);
if (bResult)
GetImageTitle(pszImageFilename, &g_HardDisk[iDrive]);
g_HardDisk[iDrive].hd_imageloaded = (Error == eIMAGE_ERROR_NONE);
return bResult;
#if HD_LED
g_HardDisk[iDrive].hd_status_next = DISK_STATUS_OFF;
g_HardDisk[iDrive].hd_status_prev = DISK_STATUS_OFF;
#endif
if (Error == eIMAGE_ERROR_NONE)
{
GetImageTitle(pszImageFilename, g_HardDisk[iDrive].imagename, g_HardDisk[iDrive].fullname);
}
HD_SaveLastDiskImage(iDrive);
return g_HardDisk[iDrive].hd_imageloaded;
}
void HD_Select(const int iDrive)
static bool HD_SelectImage(const int iDrive, LPCSTR pszFilename)
{
TCHAR directory[MAX_PATH] = TEXT("");
TCHAR filename[MAX_PATH] = TEXT("");
TCHAR title[40];
strcpy(filename, pszFilename);
RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, directory, MAX_PATH);
_tcscpy(title, TEXT("Select HDV Image For HDD "));
_tcscat(title, iDrive ? TEXT("2") : TEXT("1"));
_ASSERT(sizeof(OPENFILENAME) == sizeof(OPENFILENAME_NT4)); // Required for Win98/ME support (selected by _WIN32_WINNT=0x0400 in stdafx.h)
OPENFILENAME ofn;
ZeroMemory(&ofn,sizeof(OPENFILENAME));
ofn.lStructSize = sizeof(OPENFILENAME);
@ -389,22 +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<NUM_HARDDISKS; i++)
{
HD_Unplug(i);
ZeroMemory(&g_HardDisk[i], sizeof(HDD));
}
bool bResSelectImage1 = HD_LoadSnapshotHDDUnit(yamlLoadHelper, HARDDISK_1);
bool bResSelectImage2 = HD_LoadSnapshotHDDUnit(yamlLoadHelper, HARDDISK_2);
if (!bResSelectImage1 && !bResSelectImage2)
RegSaveString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, strSaveStatePath.c_str());
HD_SetEnabled(true);
FrameRefreshStatus(DRAW_LEDS);
return true;
}

View File

@ -30,16 +30,20 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
NUM_HARDDISKS
};
void HD_Destroy(void);
bool HD_CardIsEnabled(void);
void HD_SetEnabled(const bool bEnabled);
LPCTSTR HD_GetFullName(const int iDrive);
LPCTSTR HD_GetFullPathName(const int iDrive);
VOID HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot);
VOID HD_Cleanup(void);
BOOL HD_InsertDisk(const int iDrive, LPCTSTR pszImageFilename);
void HD_Load_Rom(const LPBYTE pCxRomPeripheral, const UINT uSlot);
void HD_Select(const int iDrive);
void HD_Unplug(const int iDrive);
bool HD_IsDriveUnplugged(const int iDrive);
void HD_LoadLastDiskImage(const int iDrive);
// 1.19.0.0 Hard Disk Status/Indicator Light
void HD_GetLightStatus (Disk_Status_e *pDisk1Status_);
std::string HD_GetSnapshotCardName(void);
void HD_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
bool HD_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version, const std::string strSaveStatePath);

View File

@ -42,6 +42,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "AppleWin.h"
#include "CPU.h"
#include "Memory.h"
#include "YamlHelper.h"
#include "Configuration\PropertySheet.h"
@ -91,7 +92,7 @@ static int joysubx[2] = {0,0};
static int joysuby[2] = {0,0};
// Value persisted to Registry for REGVALUE_JOYSTICK0_EMU_TYPE
DWORD joytype[2] = {J0C_JOYSTICK1, J1C_DISABLED}; // Emulation Type for joysticks #0 & #1
static DWORD joytype[2] = {J0C_JOYSTICK1, J1C_DISABLED}; // Emulation Type for joysticks #0 & #1
static BOOL setbutton[3] = {0,0,0}; // Used when a mouse button is pressed/released
@ -753,6 +754,30 @@ void JoyDisableUsingMouse()
//===========================================================================
void JoySetJoyType(UINT num, DWORD type)
{
_ASSERT(num <= JN_JOYSTICK1);
if (num > 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();
}

View File

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

View File

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

View File

@ -11,12 +11,12 @@ bool KeybGetShiftStatus();
bool KeybGetCapsAllowed(); //For Pravets8A/C only
void KeybUpdateCtrlShiftStatus();
BYTE KeybGetKeycode ();
DWORD KeybGetNumQueries ();
void KeybQueueKeypress (int,BOOL);
void KeybToggleCapsLock ();
void KeybToggleP8ACapsLock ();
DWORD KeybGetSnapshot(SS_IO_Keyboard* pSS);
DWORD KeybSetSnapshot(SS_IO_Keyboard* pSS);
void KeybSetSnapshot_v1(const BYTE LastKey);
void 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);

View File

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

View File

@ -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<NUM_SLOTS; i++)
{
g_SlotInfo[i].bHasCard = false;
@ -815,6 +806,16 @@ static void SetMemMode(const DWORD uNewMemMode)
//===========================================================================
static void ResetPaging(BOOL initialize);
static void UpdatePaging(BOOL initialize);
// Call by:
// . CtrlReset() Soft-reset (Ctrl+Reset)
void MemResetPaging()
{
ResetPaging(0); // Initialize=0
}
static void ResetPaging(BOOL initialize)
{
lastwriteram = 0;
@ -1028,6 +1029,7 @@ static LPBYTE MemGetPtrBANK1(const WORD offset, const LPBYTE pMemBase)
if ((offset & 0xF000) != 0xC000) // Requesting RAM at physical addr $Cxxx (ie. 4K RAM BANK1)
return NULL;
// NB. This works for memaux when set to any RWpages[] value, ie. RamWork III "just works"
const BYTE bank1page = (offset >> 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;
}

View File

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

View File

@ -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<<Phasor_SY6522A_CS)
#define Phasor_SY6522B_Offset (1<<Phasor_SY6522B_CS)
typedef struct
struct SY6522_AY8910
{
SY6522 sy6522;
BYTE nAY8910Number;
BYTE nAYCurrentRegister;
BYTE nTimerStatus;
SSI263A SpeechChip;
} SY6522_AY8910;
};
// IFR & IER:
@ -155,8 +158,8 @@ static UINT64 g_uLastCumulativeCycles = 0;
// SSI263 vars:
static USHORT g_nSSI263Device = 0; // SSI263 device# which is generating phoneme-complete IRQ
static int g_nCurrentActivePhoneme = -1;
static bool g_bStopPhoneme = false;
static volatile int g_nCurrentActivePhoneme = -1; // Modified by threads: main & SSI263Thread
static volatile bool g_bStopPhoneme = false; // Modified by threads: main & SSI263Thread
static bool g_bVotraxPhoneme = false;
static const DWORD SAMPLE_RATE = 44100; // Use a base freq so that DirectX (or sound h/w) doesn't have to up/down-sample
@ -176,6 +179,7 @@ static bool g_bMBAvailable = false;
static SS_CARDTYPE g_SoundcardType = CT_Empty; // Use CT_Empty to mean: no soundcard
static bool g_bPhasorEnable = false;
static BYTE g_nPhasorMode = 0; // 0=Mockingboard emulation, 1=Phasor native
static UINT g_PhasorClockScaleFactor = 1; // for save-state only
//-------------------------------------
@ -536,7 +540,7 @@ void SSI263_Play(unsigned int nPhoneme);
#if 0
typedef struct
{
BYTE DurationPhonome;
BYTE DurationPhoneme;
BYTE Inflection; // I10..I3
BYTE RateInflection;
BYTE CtrlArtAmp;
@ -600,7 +604,7 @@ static void SSI263_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
}
pMB->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&AMPLITUDE_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; i<MB_UNITS_PER_CARD; i++)
for(UINT i=0; i<MB_UNITS_PER_CARD_v1; i++)
{
memcpy(&pSS->Unit[i].RegsSY6522, &pMB->sy6522, sizeof(SY6522));
memcpy(&pSS->Unit[i].RegsAY8910, AY8910_GetRegsPtr(nDeviceNum), 16);
memcpy(&pSS->Unit[i].RegsSSI263, &pMB->SpeechChip, sizeof(SSI263A));
pSS->Unit[i].nAYCurrentRegister = pMB->nAYCurrentRegister;
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; i<MB_UNITS_PER_CARD; i++)
for(UINT i=0; i<MB_UNITS_PER_CARD_v1; i++)
{
memcpy(&pMB->sy6522, &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; i<NUM_MB_UNITS; i++)
{
YamlSaveHelper::Label unit(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_MB_UNIT, i);
SaveSnapshotSY6522(yamlSaveHelper, pMB->sy6522);
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; i<NUM_MB_UNITS; i++)
{
char szNum[2] = {'0'+i,0};
std::string unit = std::string(SS_YAML_KEY_MB_UNIT) + std::string(szNum);
if (!yamlLoadHelper.GetSubMap(unit))
throw std::string("Card: Expected key: ") + std::string(unit);
LoadSnapshotSY6522(yamlLoadHelper, pMB->sy6522);
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; i<NUM_PHASOR_UNITS; i++)
{
YamlSaveHelper::Label unit(yamlSaveHelper, "%s%d:\n", SS_YAML_KEY_PHASOR_UNIT, i);
SaveSnapshotSY6522(yamlSaveHelper, pMB->sy6522);
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; i<NUM_PHASOR_UNITS; i++)
{
char szNum[2] = {'0'+i,0};
std::string unit = std::string(SS_YAML_KEY_MB_UNIT) + std::string(szNum);
if (!yamlLoadHelper.GetSubMap(unit))
throw std::string("Card: Expected key: ") + std::string(unit);
LoadSnapshotSY6522(yamlLoadHelper, pMB->sy6522);
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;
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

48
source/Pravets.cpp Normal file
View File

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

7
source/Pravets.h Normal file
View File

@ -0,0 +1,7 @@
#pragma once
//Pravets 8A/C only variables
extern bool P8CAPS_ON;
extern bool P8Shift;
void PravetsReset(void);

93
source/SAM.cpp Normal file
View File

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

3
source/SAM.h Normal file
View File

@ -0,0 +1,3 @@
#pragma once
void ConfigureSAM(LPBYTE pCxRomPeripheral, UINT uSlot);

View File

@ -4,7 +4,7 @@ AppleWin : An Apple //e emulator for Windows
Copyright (C) 1994-1996, Michael O'Brien
Copyright (C) 1999-2001, Oliver Schmidt
Copyright (C) 2002-2005, Tom Charlesworth
Copyright (C) 2006-2007, Tom Charlesworth, Michael Pohoreski
Copyright (C) 2006-2015, Tom Charlesworth, Michael Pohoreski
AppleWin is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@ -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; i<NUM_SLOTS; i++)
m_ConfigNew.m_Slot[i] = CT_Empty;
m_ConfigNew.m_SlotAux = CT_Empty;
m_ConfigNew.m_bEnableHDD = false;
//m_ConfigNew.m_bEnableTheFreezesF8Rom = ?; // todo: when support saving config
//m_ConfigNew.m_bEnhanceDisk = ?; // todo: when support saving config
MemReset();
PravetsReset();
DiskReset();
KeybReset();
VideoResetState();
MB_Reset();
#ifdef USE_SPEECH_API
g_Speech.Reset();
#endif
sg_Mouse.Uninitialize();
sg_Mouse.Reset();
HD_SetEnabled(false);
std::string scalar;
while(yamlHelper.GetScalar(scalar))
{
if (scalar == SS_YAML_KEY_UNIT)
ParseUnit();
else
throw std::string("Unknown top-level scalar: " + scalar);
}
SetLoadedSaveStateFlag(true);
// NB. The following disparity should be resolved:
// . A change in h/w via the Configuration property sheets results in a the VM completely restarting (via WM_USER_RESTART)
// . A change in h/w via loading a save-state avoids this VM restart
// The latter is the desired approach (as the former needs a "power-on" / F2 to start things again)
sg_PropertySheet.ApplyNewConfig(m_ConfigNew, ConfigOld);
MemInitializeROM();
MemInitializeCustomF8ROM();
MemInitializeIO();
MemUpdatePaging(TRUE);
// g_Apple2Type may've changed: so redraw frame (title, buttons, leds, etc)
SetCharsetType();
VideoReinitialize(); // g_CharsetType changed
FrameUpdateApple2Type();
}
catch(std::string szMessage)
{
MessageBox( g_hFrameWindow,
szMessage.c_str(),
TEXT("Load State"),
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
PostMessage(g_hFrameWindow, WM_USER_RESTART, 0, 0); // Power-cycle VM (undoing all the new state just loaded)
}
_ASSERT((dwError == 0) || (dwError == ERROR_ALREADY_EXISTS));
yamlHelper.FinaliseParser();
}
delete [] pSS;
void Snapshot_LoadState()
{
const std::string ext_aws = (".aws");
const size_t pos = g_strSaveStatePathname.size() - ext_aws.size();
if (g_strSaveStatePathname.find(ext_aws, pos) != std::string::npos) // find ".aws" at end of pathname
{
Snapshot_LoadState_v1();
return;
}
Snapshot_LoadState_v2();
}
//-----------------------------------------------------------------------------
// todo:
// . Uthernet card
void Snapshot_SaveState(void)
{
try
{
YamlSaveHelper yamlSaveHelper(g_strSaveStatePathname);
yamlSaveHelper.FileHdr(SS_FILE_VER);
// Unit: Apple2
{
yamlSaveHelper.UnitHdr(GetSnapshotUnitApple2Name(), UNIT_APPLE2_VER);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
yamlSaveHelper.Save("%s: %s\n", SS_YAML_KEY_MODEL, GetApple2TypeAsString().c_str());
CpuSaveSnapshot(yamlSaveHelper);
JoySaveSnapshot(yamlSaveHelper);
KeybSaveSnapshot(yamlSaveHelper);
SpkrSaveSnapshot(yamlSaveHelper);
VideoSaveSnapshot(yamlSaveHelper);
MemSaveSnapshot(yamlSaveHelper);
}
// Unit: Aux slot
MemSaveSnapshotAux(yamlSaveHelper);
// Unit: Slots
{
yamlSaveHelper.UnitHdr(GetSnapshotUnitSlotsName(), UNIT_SLOTS_VER);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
Printer_SaveSnapshot(yamlSaveHelper);
sg_SSC.SaveSnapshot(yamlSaveHelper);
sg_Mouse.SaveSnapshot(yamlSaveHelper);
if (g_Slot4 == CT_Z80)
Z80_SaveSnapshot(yamlSaveHelper, 4);
if (g_Slot5 == CT_Z80)
Z80_SaveSnapshot(yamlSaveHelper, 5);
if (g_Slot4 == CT_MockingboardC)
MB_SaveSnapshot(yamlSaveHelper, 4);
if (g_Slot5 == CT_MockingboardC)
MB_SaveSnapshot(yamlSaveHelper, 5);
if (g_Slot4 == CT_Phasor)
Phasor_SaveSnapshot(yamlSaveHelper, 4);
DiskSaveSnapshot(yamlSaveHelper);
HD_SaveSnapshot(yamlSaveHelper);
}
}
catch(std::string szMessage)
{
MessageBox( g_hFrameWindow,
szMessage.c_str(),
TEXT("Save State"),
MB_ICONEXCLAMATION | MB_SETFOREGROUND);
}
}
//-----------------------------------------------------------------------------

View File

@ -0,0 +1,136 @@
#pragma once
// Structs used by save-state file
// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT ***
/////////////////////////////////////////////////////////////////////////////////
#define MAKE_VERSION(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | (d))
#define AW_SS_TAG 'SSWA' // 'AWSS' = AppleWin SnapShot
struct SS_FILE_HDR
{
DWORD dwTag; // "AWSS"
DWORD dwVersion;
DWORD dwChecksum;
};
struct SS_UNIT_HDR
{
union
{
struct
{
DWORD dwLength; // Byte length of this unit struct
DWORD dwVersion;
} v1;
struct
{
DWORD Length; // Byte length of this unit struct
WORD Type; // SS_UNIT_TYPE
WORD Version; // Incrementing value from 1
} v2;
} hdr;
};
enum SS_UNIT_TYPE
{
UT_Reserved = 0,
UT_Apple2,
UT_Card,
UT_Config,
};
const UINT nMemMainSize = 64*1024;
const UINT nMemAuxSize = 64*1024;
const UINT kSLOT_LANG = 0;
const UINT kSLOT_AUX = 8;
struct SS_CARD_HDR
{
SS_UNIT_HDR UnitHdr;
DWORD Type; // SS_CARDTYPE
DWORD Slot; // [1..7], 0=Language card, 8=Aux
};
enum SS_CARDTYPE
{
CT_Empty = 0,
CT_Disk2, // Apple Disk][
CT_SSC, // Apple Super Serial Card
CT_MockingboardC, // Soundcard
CT_GenericPrinter,
CT_GenericHDD, // Hard disk
CT_GenericClock,
CT_MouseInterface,
CT_Z80,
CT_Phasor, // Soundcard
CT_Echo, // Soundcard
CT_SAM, // Soundcard: Software Automated Mouth
CT_80Col, // 80 column card (no memory)
CT_Extended80Col, // Extended 80-col card (64K)
CT_RamWorksIII, // RamWorksIII (up to 8MB)
CT_Uthernet,
};
/////////////////////////////////////////////////////////////////////////////////
struct SS_CARD_EMPTY
{
SS_CARD_HDR Hdr;
};
/////////////////////////////////////////////////////////////////////////////////
struct IWORD
{
union
{
struct
{
BYTE l;
BYTE h;
};
USHORT w;
};
};
struct SY6522
{
BYTE ORB; // $00 - Port B
BYTE ORA; // $01 - Port A (with handshaking)
BYTE DDRB; // $02 - Data Direction Register B
BYTE DDRA; // $03 - Data Direction Register A
//
// $04 - Read counter (L) / Write latch (L)
// $05 - Read / Write & initiate count (H)
// $06 - Read / Write & latch (L)
// $07 - Read / Write & latch (H)
// $08 - Read counter (L) / Write latch (L)
// $09 - Read counter (H) / Write latch (H)
IWORD TIMER1_COUNTER;
IWORD TIMER1_LATCH;
IWORD TIMER2_COUNTER;
IWORD TIMER2_LATCH;
//
BYTE SERIAL_SHIFT; // $0A
BYTE ACR; // $0B - Auxiliary Control Register
BYTE PCR; // $0C - Peripheral Control Register
BYTE IFR; // $0D - Interrupt Flag Register
BYTE IER; // $0E - Interrupt Enable Register
BYTE ORA_NO_HS; // $0F - Port A (without handshaking)
};
struct SSI263A
{
BYTE DurationPhoneme;
BYTE Inflection; // I10..I3
BYTE RateInflection;
BYTE CtrlArtAmp;
BYTE FilterFreq;
//
BYTE CurrentMode; // b7:6=Mode; b0=D7 pin (for IRQ)
};

View File

@ -0,0 +1,147 @@
#pragma once
#include "DiskDefs.h"
#include "SaveState_Structs_common.h"
// Structs used by save-state file v1
// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT ***
/////////////////////////////////////////////////////////////////////////////////
struct SS_CPU6502
{
BYTE A;
BYTE X;
BYTE Y;
BYTE P;
BYTE S;
USHORT PC;
unsigned __int64 nCumulativeCycles;
// IRQ = OR-sum of all interrupt sources
};
const UINT uRecvBufferSize = 9;
struct SS_IO_Comms
{
DWORD baudrate;
BYTE bytesize;
BYTE commandbyte;
DWORD comminactivity; // If non-zero then COM port open
BYTE controlbyte;
BYTE parity;
BYTE recvbuffer[uRecvBufferSize];
DWORD recvbytes;
BYTE stopbits;
};
struct SS_IO_Joystick
{
unsigned __int64 nJoyCntrResetCycle;
};
struct SS_IO_Keyboard
{
DWORD keyboardqueries;
BYTE nLastKey;
};
struct SS_IO_Speaker
{
unsigned __int64 nSpkrLastCycle;
};
struct SS_IO_Video
{
bool bAltCharSet; // charoffs
DWORD dwVidMode;
};
struct SS_BaseMemory
{
DWORD dwMemMode;
BOOL bLastWriteRam;
BYTE nMemMain[nMemMainSize];
BYTE nMemAux[nMemAuxSize];
};
struct SS_APPLE2_Unit
{
SS_UNIT_HDR UnitHdr;
SS_CPU6502 CPU6502;
SS_IO_Comms Comms;
SS_IO_Joystick Joystick;
SS_IO_Keyboard Keyboard;
SS_IO_Speaker Speaker;
SS_IO_Video Video;
SS_BaseMemory Memory;
};
/////////////////////////////////////////////////////////////////////////////////
struct DISK2_Unit
{
char szFileName[MAX_PATH];
int track;
int phase;
int byte;
BOOL writeprotected;
BOOL trackimagedata;
BOOL trackimagedirty;
DWORD spinning;
DWORD writelight;
int nibbles;
BYTE nTrack[NIBBLES_PER_TRACK];
};
struct SS_CARD_DISK2
{
SS_CARD_HDR Hdr;
DISK2_Unit Unit[2];
WORD phases;
WORD currdrive;
BOOL diskaccessed;
BOOL enhancedisk;
BYTE floppylatch;
BOOL floppymotoron;
BOOL floppywritemode;
};
/////////////////////////////////////////////////////////////////////////////////
struct MB_Unit_v1
{
SY6522 RegsSY6522;
BYTE RegsAY8910[16];
SSI263A RegsSSI263;
BYTE nAYCurrentRegister;
bool bTimer1IrqPending;
bool bTimer2IrqPending;
bool bSpeechIrqPending;
};
const UINT MB_UNITS_PER_CARD_v1 = 2;
struct SS_CARD_MOCKINGBOARD_v1
{
SS_CARD_HDR Hdr;
MB_Unit_v1 Unit[MB_UNITS_PER_CARD_v1];
};
/////////////////////////////////////////////////////////////////////////////////
struct APPLEWIN_SNAPSHOT_v1
{
SS_FILE_HDR Hdr;
SS_APPLE2_Unit Apple2Unit;
SS_CARD_EMPTY Empty1; // Slot1
SS_CARD_EMPTY Empty2; // Slot2
SS_CARD_EMPTY Empty3; // Slot3
SS_CARD_MOCKINGBOARD_v1 Mockingboard1; // Slot4
SS_CARD_MOCKINGBOARD_v1 Mockingboard2; // Slot5
SS_CARD_DISK2 Disk2; // Slot6
SS_CARD_EMPTY Empty7; // Slot7
};
const UINT kSnapshotSize_v1 = 145400; // Const size for v1

View File

@ -46,6 +46,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Frame.h"
#include "Memory.h"
#include "SerialComms.h"
#include "YamlHelper.h"
#include "..\resource\resource.h"
@ -72,7 +73,8 @@ SSC_DIPSW CSuperSerialCard::m_DIPSWDefault =
CSuperSerialCard::CSuperSerialCard() :
m_aySerialPortChoices(NULL),
m_uTCPChoiceItemIdx(0)
m_uTCPChoiceItemIdx(0),
m_uSlot(0)
{
memset(m_ayCurrentSerialPortName, 0, sizeof(m_ayCurrentSerialPortName));
m_dwSerialPortItem = 0;
@ -831,6 +833,8 @@ void CSuperSerialCard::CommInitialize(LPBYTE pCxRomPeripheral, UINT uSlot)
memcpy(pCxRomPeripheral + uSlot*256, pData+SSC_SLOT_FW_OFFSET, SSC_SLOT_FW_SIZE);
m_uSlot = uSlot;
// Expansion ROM
if (m_pExpansionRom == NULL)
{
@ -1045,7 +1049,7 @@ DWORD WINAPI CSuperSerialCard::CommThread(LPVOID lpParameter)
sprintf(szDbg, "CommThread: Err=Other (0x%08X): InQueue=0x%08X, OutQueue=0x%08X\n", dwErrors, Stat.cbInQue, Stat.cbOutQue);
OutputDebugString(szDbg);
if (g_fh)
fprintf(g_fh, szDbg);
fprintf(g_fh, "%s", szDbg);
}
return -1;
}
@ -1293,30 +1297,131 @@ void CSuperSerialCard::SetSerialPortName(const char* pSerialPortName)
//===========================================================================
DWORD CSuperSerialCard::CommGetSnapshot(SS_IO_Comms* pSS)
void CSuperSerialCard::SetSnapshot_v1( const DWORD baudrate,
const BYTE bytesize,
const BYTE commandbyte,
const DWORD comminactivity,
const BYTE controlbyte,
const BYTE parity,
const BYTE stopbits)
{
pSS->baudrate = m_uBaudRate;
pSS->bytesize = m_uByteSize;
pSS->commandbyte = m_uCommandByte;
pSS->comminactivity = m_dwCommInactivity;
pSS->controlbyte = m_uControlByte;
pSS->parity = m_uParity;
// memcpy(pSS->recvbuffer, m_RecvBuffer, uRecvBufferSize);
pSS->recvbytes = 0;
pSS->stopbits = m_uStopBits;
return 0;
m_uBaudRate = baudrate;
m_uByteSize = bytesize;
m_uCommandByte = commandbyte;
m_dwCommInactivity = comminactivity;
m_uControlByte = controlbyte;
m_uParity = parity;
// memcpy(m_RecvBuffer, pSS->recvbuffer, uRecvBufferSize);
// m_vRecvBytes = recvbytes;
m_uStopBits = stopbits;
}
DWORD CSuperSerialCard::CommSetSnapshot(SS_IO_Comms* pSS)
//===========================================================================
#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;
}

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@
#endif
// Not needed in VC7.1, but needed in VC Express
#include <tchar.h>
#include <tchar.h>
#include <crtdbg.h>
#include <dsound.h>
@ -23,7 +23,6 @@
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#if _MSC_VER >= 1600 // <stdint.h> supported from VS2010 (cl.exe v16.00)
#include <stdint.h> // cleanup WORD DWORD -> uint16_t uint32_t
@ -43,6 +42,8 @@ typedef UINT32 uint32_t;
#include <algorithm>
#include <map>
#include <queue>
#include <stack>
#include <string>
#include <vector>
// SM_CXPADDEDBORDER is not supported on 2000 & XP:

View File

@ -1,285 +0,0 @@
#pragma once
#include "DiskDefs.h"
// Structs used by save-state file
// *** DON'T CHANGE ANY STRUCT WITHOUT CONSIDERING BACKWARDS COMPATIBILITY WITH .AWS FORMAT ***
#define MAKE_VERSION(a,b,c,d) ((a<<24) | (b<<16) | (c<<8) | (d))
#define AW_SS_TAG 'SSWA' // 'AWSS' = AppleWin SnapShot
typedef struct
{
DWORD dwTag; // "AWSS"
DWORD dwVersion;
DWORD dwChecksum;
} SS_FILE_HDR;
typedef struct
{
DWORD dwLength; // Byte length of this unit struct
DWORD dwVersion;
} SS_UNIT_HDR;
/////////////////////////////////////////////////////////////////////////////////
const UINT nMemMainSize = 64*1024;
const UINT nMemAuxSize = 64*1024;
typedef struct
{
BYTE A;
BYTE X;
BYTE Y;
BYTE P;
BYTE S;
USHORT PC;
unsigned __int64 g_nCumulativeCycles;
// IRQ = OR-sum of all interrupt sources
} SS_CPU6502;
const UINT uRecvBufferSize = 9;
typedef struct
{
DWORD baudrate;
BYTE bytesize;
BYTE commandbyte;
DWORD comminactivity; // If non-zero then COM port open
BYTE controlbyte;
BYTE parity;
BYTE recvbuffer[uRecvBufferSize];
DWORD recvbytes;
BYTE stopbits;
} SS_IO_Comms;
typedef struct
{
unsigned __int64 g_nJoyCntrResetCycle;
} SS_IO_Joystick;
typedef struct
{
DWORD keyboardqueries;
BYTE nLastKey;
} SS_IO_Keyboard;
//typedef struct
//{
//} SS_IO_Memory;
typedef struct
{
unsigned __int64 g_nSpkrLastCycle;
} SS_IO_Speaker;
typedef struct
{
bool bAltCharSet; // charoffs
DWORD dwVidMode;
} SS_IO_Video;
typedef struct
{
DWORD dwMemMode;
BOOL bLastWriteRam;
BYTE nMemMain[nMemMainSize];
BYTE nMemAux[nMemAuxSize];
} SS_BaseMemory;
typedef struct
{
SS_UNIT_HDR UnitHdr;
SS_CPU6502 CPU6502;
SS_IO_Comms Comms;
SS_IO_Joystick Joystick;
SS_IO_Keyboard Keyboard;
// SS_IO_Memory Memory;
SS_IO_Speaker Speaker;
SS_IO_Video Video;
SS_BaseMemory Memory;
} SS_APPLE2_Unit;
/////////////////////////////////////////////////////////////////////////////////
typedef struct
{
DWORD dwComputerEmulation;
bool bCustomSpeed;
DWORD dwEmulationSpeed;
bool bEnhancedDiskSpeed;
DWORD dwJoystickType[2];
bool bMockingboardEnabled;
DWORD dwMonochromeColor;
DWORD dwSerialPort;
DWORD dwSoundType; // Sound Emulation
DWORD dwVideoType; // Video Emulation
} SS_AW_CFG;
typedef struct
{
char StartingDir[MAX_PATH];
DWORD dwWindowXpos;
DWORD dwWindowYpos;
} SS_AW_PREFS;
typedef struct
{
SS_UNIT_HDR UnitHdr;
DWORD dwAppleWinVersion;
SS_AW_PREFS Prefs;
SS_AW_CFG Cfg;
} SS_APPLEWIN_CONFIG;
/////////////////////////////////////////////////////////////////////////////////
typedef struct
{
SS_UNIT_HDR UnitHdr;
DWORD dwType; // SS_CARDTYPE
DWORD dwSlot; // [1..7]
} SS_CARD_HDR;
enum SS_CARDTYPE
{
CT_Empty = 0,
CT_Disk2, // Apple Disk][
CT_SSC, // Apple Super Serial Card
CT_MockingboardC, // Soundcard
CT_GenericPrinter,
CT_GenericHDD, // Hard disk
CT_GenericClock,
CT_MouseInterface,
CT_Z80,
CT_Phasor, // Soundcard
CT_Echo, // Soundcard
CT_SAM, // Soundcard: Software Automated Mouth
};
/////////////////////////////////////////////////////////////////////////////////
typedef struct
{
SS_CARD_HDR Hdr;
} SS_CARD_EMPTY;
/////////////////////////////////////////////////////////////////////////////////
typedef struct
{
char szFileName[MAX_PATH];
int track;
int phase;
int byte;
BOOL writeprotected;
BOOL trackimagedata;
BOOL trackimagedirty;
DWORD spinning;
DWORD writelight;
int nibbles;
BYTE nTrack[NIBBLES_PER_TRACK];
} DISK2_Unit;
typedef struct
{
SS_CARD_HDR Hdr;
DISK2_Unit Unit[2];
WORD phases;
WORD currdrive;
BOOL diskaccessed;
BOOL enhancedisk;
BYTE floppylatch;
BOOL floppymotoron;
BOOL floppywritemode;
} SS_CARD_DISK2;
/////////////////////////////////////////////////////////////////////////////////
typedef struct
{
union
{
struct
{
BYTE l;
BYTE h;
};
USHORT w;
};
} IWORD;
typedef struct
{
BYTE ORB; // $00 - Port B
BYTE ORA; // $01 - Port A (with handshaking)
BYTE DDRB; // $02 - Data Direction Register B
BYTE DDRA; // $03 - Data Direction Register A
//
// $04 - Read counter (L) / Write latch (L)
// $05 - Read / Write & initiate count (H)
// $06 - Read / Write & latch (L)
// $07 - Read / Write & latch (H)
// $08 - Read counter (L) / Write latch (L)
// $09 - Read counter (H) / Write latch (H)
IWORD TIMER1_COUNTER;
IWORD TIMER1_LATCH;
IWORD TIMER2_COUNTER;
IWORD TIMER2_LATCH;
//
BYTE SERIAL_SHIFT; // $0A
BYTE ACR; // $0B - Auxiliary Control Register
BYTE PCR; // $0C - Peripheral Control Register
BYTE IFR; // $0D - Interrupt Flag Register
BYTE IER; // $0E - Interrupt Enable Register
BYTE ORA_NO_HS; // $0F - Port A (without handshaking)
} SY6522;
typedef struct
{
BYTE DurationPhonome;
BYTE Inflection; // I10..I3
BYTE RateInflection;
BYTE CtrlArtAmp;
BYTE FilterFreq;
//
BYTE CurrentMode; // b7:6=Mode; b0=D7 pin (for IRQ)
} SSI263A;
typedef struct
{
SY6522 RegsSY6522;
BYTE RegsAY8910[16];
SSI263A RegsSSI263;
BYTE nAYCurrentRegister;
bool bTimer1IrqPending;
bool bTimer2IrqPending;
bool bSpeechIrqPending;
} MB_Unit;
const UINT MB_UNITS_PER_CARD = 2;
typedef struct
{
SS_CARD_HDR Hdr;
MB_Unit Unit[MB_UNITS_PER_CARD];
} SS_CARD_MOCKINGBOARD;
/////////////////////////////////////////////////////////////////////////////////
typedef struct
{
SS_FILE_HDR Hdr;
SS_APPLE2_Unit Apple2Unit;
// SS_APPLEWIN_CONFIG AppleWinCfg;
SS_CARD_EMPTY Empty1; // Slot1
SS_CARD_EMPTY Empty2; // Slot2
SS_CARD_EMPTY Empty3; // Slot3
SS_CARD_MOCKINGBOARD Mockingboard1; // Slot4
SS_CARD_MOCKINGBOARD Mockingboard2; // Slot5
SS_CARD_DISK2 Disk2; // Slot6
SS_CARD_EMPTY Empty7; // Slot7
} APPLEWIN_SNAPSHOT;
/////////////////////////////////////////////////////////////////////////////////

View File

@ -24,8 +24,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
/* Description: This module is created for emulation of the 8bit character mode (mode 1) switch,
* which is located in $c060, and so far does not intend to emulate a tape device.
*
*
* Author: Various
*
* In comments, UTA2E is an abbreviation for a reference to "Understanding the Apple //e" by James Sather
*/
#include "StdAfx.h"
@ -33,6 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "AppleWin.h"
#include "Keyboard.h"
#include "Memory.h"
#include "Pravets.h"
static bool g_CapsLockAllowed = false;
@ -76,7 +78,7 @@ BYTE __stdcall TapeRead(WORD, WORD address, BYTE, BYTE, ULONG nCyclesLeft)
return C060;
}
return (1<<7) | (MemReadFloatingBus(nCyclesLeft) & 0x7F); // Keep high-bit fixed (since TAPEIN isn't supported)
return MemReadFloatingBus(1, nCyclesLeft); // TAPEIN has high bit 1 when input is low or not connected (UTA2E page 7-5, 7-6)
}
/*

View File

@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "..\resource\resource.h"
#include "Configuration\PropertySheet.h"
#include "Debugger\Debugger_Color.h" // For NUM_DEBUG_COLORS
#include "YamlHelper.h"
#define HALF_PIXEL_SOLID 1
#define HALF_PIXEL_BLEED 0
@ -590,7 +591,6 @@ static inline int GetOriginal2EOffset(BYTE ch)
}
//===========================================================================
#define ROL_NIB(x) ( (((x)<<1)&0xF) | (((x)>>3)&1) )
//
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
@ -1195,11 +1195,10 @@ void VideoRefreshScreen ( int bVideoModeFlags )
//===========================================================================
void VideoReinitialize ()
{
NTSC_VideoInitAppleType();
NTSC_VideoInitAppleType(g_dwCyclesThisFrame);
NTSC_SetVideoStyle();
}
//===========================================================================
void VideoResetState ()
{
@ -1220,8 +1219,8 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
switch (address)
{
case 0x00: g_uVideoMode &= ~VF_80STORE; ; break;
case 0x01: g_uVideoMode |= VF_80STORE; ; break;
case 0x00: g_uVideoMode &= ~VF_80STORE; break;
case 0x01: g_uVideoMode |= VF_80STORE; break;
case 0x0C: if (!IS_APPLE2){g_uVideoMode &= ~VF_80COL; NTSC_SetVideoTextMode(40);}; break;
case 0x0D: if (!IS_APPLE2){g_uVideoMode |= VF_80COL; NTSC_SetVideoTextMode(80);}; break;
case 0x0E: if (!IS_APPLE2) g_nAltCharSetOffset = 0; break; // Alternate char set off
@ -1238,7 +1237,7 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
case 0x5F: if (!IS_APPLE2) g_uVideoMode &= ~VF_DHIRES; break;
}
// Apple IIe, Techical Nodtes, #3: Double High-Resolution Graphics
// Apple IIe, Techical Notes, #3: Double High-Resolution Graphics
// 80STORE must be OFF to display page 2
if (SW_80STORE)
g_uVideoMode &= ~VF_PAGE2;
@ -1260,7 +1259,7 @@ BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
// NB. Deferring the update by just setting /g_VideoForceFullRedraw/ is not an option, since this doesn't provide "flip-immediate"
//
// Ultimately this isn't the correct solution, and proper cycle-accurate video rendering should be done, but this is a much bigger job!
// TODO: Is MemReadFloatingBus() still accurate now that we have proper per cycle video rendering??
// TODO-Michael: Is MemReadFloatingBus() still accurate now that we have proper per cycle video rendering??
if (!g_bVideoUpdatedThisFrame)
{
@ -1323,20 +1322,42 @@ void VideoSetForceFullRedraw(void)
//===========================================================================
DWORD VideoGetSnapshot(SS_IO_Video* pSS)
void VideoSetSnapshot_v1(const UINT AltCharSet, const UINT VideoMode)
{
pSS->bAltCharSet = !(g_nAltCharSetOffset == 0);
pSS->dwVidMode = g_uVideoMode;
return 0;
g_nAltCharSetOffset = !AltCharSet ? 0 : 256;
g_uVideoMode = VideoMode;
}
//===========================================================================
//
DWORD VideoSetSnapshot(SS_IO_Video* pSS)
#define SS_YAML_KEY_ALTCHARSET "Alt Char Set"
#define SS_YAML_KEY_VIDEOMODE "Video Mode"
#define SS_YAML_KEY_CYCLESTHISFRAME "Cycles This Frame"
static std::string VideoGetSnapshotStructName(void)
{
g_nAltCharSetOffset = !pSS->bAltCharSet ? 0 : 256;
g_uVideoMode = pSS->dwVidMode;
return 0;
static const std::string name("Video");
return name;
}
void VideoSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", VideoGetSnapshotStructName().c_str());
yamlSaveHelper.SaveBool(SS_YAML_KEY_ALTCHARSET, g_nAltCharSetOffset ? true : false);
yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_VIDEOMODE, g_uVideoMode);
yamlSaveHelper.SaveUint(SS_YAML_KEY_CYCLESTHISFRAME, g_dwCyclesThisFrame);
}
void VideoLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
{
if (!yamlLoadHelper.GetSubMap(VideoGetSnapshotStructName()))
return;
g_nAltCharSetOffset = yamlLoadHelper.LoadBool(SS_YAML_KEY_ALTCHARSET) ? 256 : 0;
g_uVideoMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_VIDEOMODE);
g_dwCyclesThisFrame = yamlLoadHelper.LoadUint(SS_YAML_KEY_CYCLESTHISFRAME);
yamlLoadHelper.PopMap();
}
//===========================================================================

View File

@ -152,12 +152,11 @@ struct WinBmpHeader4_t
extern HBITMAP g_hLogoBitmap;
extern COLORREF g_nMonochromeRGB; // saved
extern uint32_t g_uVideoMode ;
extern DWORD g_eVideoType ; // saved
extern DWORD g_uHalfScanLines; // saved
extern COLORREF g_nMonochromeRGB; // saved to Registry
extern uint32_t g_uVideoMode;
extern DWORD g_eVideoType; // saved to Registry
extern DWORD g_uHalfScanLines; // saved to Registry
extern uint8_t *g_pFramebufferbits;
extern int g_nAltCharSetOffset; // alternate character set
typedef bool (*VideoUpdateFuncPtr_t)(int,int,int,int,int);
@ -177,7 +176,6 @@ void VideoReinitialize ();
void VideoResetState ();
WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles);
bool VideoGetVbl(DWORD uExecutedCycles);
void VideoEndOfVideoFrame(void);
bool VideoGetSW80COL(void);
bool VideoGetSWDHIRES(void);
@ -190,6 +188,10 @@ bool VideoGetSWAltCharSet(void);
void VideoSetForceFullRedraw(void);
void VideoSetSnapshot_v1(const UINT AltCharSet, const UINT VideoMode);
void VideoSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void VideoLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
int _Video_SetupBanks( bool bBank2 );
bool Update40ColCell (int x, int y, int xpixel, int ypixel, int offset);
bool Update80ColCell (int x, int y, int xpixel, int ypixel, int offset);

482
source/YamlHelper.cpp Normal file
View File

@ -0,0 +1,482 @@
/*
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
*/
#include "StdAfx.h"
#include "Log.h"
#include "YamlHelper.h"
int YamlHelper::InitParser(const char* pPathname)
{
m_hFile = fopen(pPathname, "r");
if (m_hFile == NULL)
{
return 0;
}
if (!yaml_parser_initialize(&m_parser))
{
return 0;
}
yaml_parser_set_input_file(&m_parser, m_hFile);
return 1;
}
void YamlHelper::FinaliseParser(void)
{
if (m_hFile)
fclose(m_hFile);
m_hFile = NULL;
}
void YamlHelper::GetNextEvent(bool bInMap /*= false*/)
{
if (!yaml_parser_parse(&m_parser, &m_newEvent))
{
//printf("Parser error %d\n", m_parser.error);
throw std::string("Parser error");
}
}
int YamlHelper::GetScalar(std::string& scalar)
{
int res = 1;
bool bDone = false;
while (!bDone)
{
GetNextEvent();
switch(m_newEvent.type)
{
case YAML_SCALAR_EVENT:
scalar = m_scalarName = (const char*)m_newEvent.data.scalar.value;
res = 1;
bDone = true;
break;
case YAML_SEQUENCE_END_EVENT:
res = 0;
bDone = true;
break;
case YAML_MAPPING_END_EVENT:
res = 0;
bDone = true;
break;
case YAML_STREAM_END_EVENT:
res = 0;
bDone = true;
break;
}
}
return res;
}
void YamlHelper::GetMapStartEvent(void)
{
GetNextEvent();
if (m_newEvent.type != YAML_MAPPING_START_EVENT)
{
//printf("Unexpected yaml event (%d)\n", m_newEvent.type);
throw std::string("Unexpected yaml event");
}
}
int YamlHelper::ParseMap(MapYaml& mapYaml)
{
mapYaml.clear();
const char*& pValue = (const char*&) m_newEvent.data.scalar.value;
bool bKey = true;
char* pKey = NULL;
int res = 1;
bool bDone = false;
while (!bDone)
{
GetNextEvent(true);
switch(m_newEvent.type)
{
case YAML_STREAM_END_EVENT:
res = 0;
bDone = true;
break;
case YAML_MAPPING_START_EVENT:
{
MapValue mapValue;
mapValue.value = "";
mapValue.subMap = new MapYaml;
mapYaml[std::string(pKey)] = mapValue;
res = ParseMap(*mapValue.subMap);
if (!res)
throw std::string("ParseMap: premature end of file during map parsing");
bKey = true; // possibly more key,value pairs in this map
}
break;
case YAML_MAPPING_END_EVENT:
bDone = true;
break;
case YAML_SCALAR_EVENT:
if (bKey)
{
pKey = _strdup(pValue);
}
else
{
MapValue mapValue;
mapValue.value = pValue;
mapValue.subMap = NULL;
mapYaml[std::string(pKey)] = mapValue;
delete [] pKey; pKey = NULL;
}
bKey = bKey ? false : true;
break;
case YAML_SEQUENCE_START_EVENT:
case YAML_SEQUENCE_END_EVENT:
throw std::string("ParseMap: Sequence event unsupported");
}
}
if (pKey)
delete [] pKey;
return res;
}
std::string YamlHelper::GetMapValue(MapYaml& mapYaml, const std::string key, bool& bFound)
{
MapYaml::const_iterator iter = mapYaml.find(key);
if (iter == mapYaml.end() || iter->second.subMap != NULL)
{
bFound = false; // not found
return "";
}
std::string value = iter->second.value;
mapYaml.erase(iter);
bFound = true;
return value;
}
bool YamlHelper::GetSubMap(MapYaml** mapYaml, const std::string key)
{
MapYaml::const_iterator iter = (*mapYaml)->find(key);
if (iter == (*mapYaml)->end() || iter->second.subMap == NULL)
{
return false; // not found
}
*mapYaml = iter->second.subMap;
return true;
}
void YamlHelper::GetMapRemainder(std::string& mapName, MapYaml& mapYaml)
{
for (MapYaml::iterator iter = mapYaml.begin(); iter != mapYaml.end(); ++iter)
{
if (iter->second.subMap)
{
std::string subMapName(iter->first);
GetMapRemainder(subMapName, *iter->second.subMap);
delete iter->second.subMap;
}
else
{
const char* pKey = iter->first.c_str();
LogOutput("%s: Unknown key (%s)\n", mapName.c_str(), pKey);
LogFileOutput("%s: Unknown key (%s)\n", mapName.c_str(), pKey);
}
}
mapYaml.clear();
}
//
void YamlHelper::MakeAsciiToHexTable(void)
{
memset(m_AsciiToHex, -1, sizeof(m_AsciiToHex));
for (int i = '0'; i<= '9'; i++)
m_AsciiToHex[i] = i - '0';
for (int i = 'A'; i<= 'F'; i++)
m_AsciiToHex[i] = i - 'A' + 0xA;
for (int i = 'a'; i<= 'f'; i++)
m_AsciiToHex[i] = i - 'a' + 0xA;
}
void YamlHelper::LoadMemory(MapYaml& mapYaml, const LPBYTE pMemBase, const size_t kAddrSpaceSize)
{
for (MapYaml::iterator it = mapYaml.begin(); it != mapYaml.end(); ++it)
{
const char* pKey = it->first.c_str();
UINT addr = strtoul(pKey, NULL, 16);
if (addr >= kAddrSpaceSize)
throw std::string("Memory: line address too big: " + it->first);
LPBYTE pDst = (LPBYTE) (pMemBase + addr);
const LPBYTE pDstEnd = (LPBYTE) (pMemBase + kAddrSpaceSize);
if (it->second.subMap)
throw std::string("Memory: unexpected sub-map");
const char* pValue = it->second.value.c_str();
size_t len = strlen(pValue);
if (len & 1)
throw std::string("Memory: hex data must be an even number of nibbles on line address: " + it->first);
for (UINT i = 0; i<len; i+=2)
{
if (pDst >= pDstEnd)
throw std::string("Memory: hex data overflowed address space on line address: " + it->first);
BYTE ah = m_AsciiToHex[ (BYTE)(*pValue++) ];
BYTE al = m_AsciiToHex[ (BYTE)(*pValue++) ];
if ((ah | al) & 0x80)
throw std::string("Memory: hex data contains illegal character on line address: " + it->first);
*pDst++ = (ah<<4) | al;
}
}
mapYaml.clear();
}
//-------------------------------------
INT YamlLoadHelper::LoadInt(const std::string key)
{
bool bFound;
std::string value = m_yamlHelper.GetMapValue(*m_pMapYaml, key, bFound);
if (value == "")
{
m_bDoGetMapRemainder = false;
throw std::string(m_currentMapName + ": Missing: " + key);
}
return strtol(value.c_str(), NULL, 0);
}
UINT YamlLoadHelper::LoadUint(const std::string key)
{
bool bFound;
std::string value = m_yamlHelper.GetMapValue(*m_pMapYaml, key, bFound);
if (value == "")
{
m_bDoGetMapRemainder = false;
throw std::string(m_currentMapName + ": Missing: " + key);
}
return strtoul(value.c_str(), NULL, 0);
}
UINT64 YamlLoadHelper::LoadUint64(const std::string key)
{
bool bFound;
std::string value = m_yamlHelper.GetMapValue(*m_pMapYaml, key, bFound);
if (value == "")
{
m_bDoGetMapRemainder = false;
throw std::string(m_currentMapName + ": Missing: " + key);
}
return _strtoui64(value.c_str(), NULL, 0);
}
bool YamlLoadHelper::LoadBool(const std::string key)
{
bool bFound;
std::string value = m_yamlHelper.GetMapValue(*m_pMapYaml, key, bFound);
if (value == "true")
return true;
else if (value == "false")
return false;
m_bDoGetMapRemainder = false;
throw std::string(m_currentMapName + ": Missing: " + key);
}
std::string YamlLoadHelper::LoadString_NoThrow(const std::string& key, bool& bFound)
{
std::string value = m_yamlHelper.GetMapValue(*m_pMapYaml, key, bFound);
return value;
}
std::string YamlLoadHelper::LoadString(const std::string& key)
{
bool bFound;
std::string value = LoadString_NoThrow(key, bFound);
if (!bFound)
{
m_bDoGetMapRemainder = false;
throw std::string(m_currentMapName + ": Missing: " + key);
}
return value;
}
void YamlLoadHelper::LoadMemory(const LPBYTE pMemBase, const size_t size)
{
m_yamlHelper.LoadMemory(*m_pMapYaml, pMemBase, size);
}
//-------------------------------------
void YamlSaveHelper::Save(const char* format, ...)
{
fwrite(m_szIndent, 1, m_indent, m_hFile);
va_list vl;
va_start(vl, format);
vfprintf(m_hFile, format, vl);
va_end(vl);
}
void YamlSaveHelper::SaveInt(const char* key, int value)
{
Save("%s: %d\n", key, value);
}
void YamlSaveHelper::SaveUint(const char* key, UINT value)
{
Save("%s: %u\n", key, value);
}
void YamlSaveHelper::SaveHexUint4(const char* key, UINT value)
{
Save("%s: 0x%01X\n", key, value);
}
void YamlSaveHelper::SaveHexUint8(const char* key, UINT value)
{
Save("%s: 0x%02X\n", key, value);
}
void YamlSaveHelper::SaveHexUint12(const char* key, UINT value)
{
Save("%s: 0x%03X\n", key, value);
}
void YamlSaveHelper::SaveHexUint16(const char* key, UINT value)
{
Save("%s: 0x%04X\n", key, value);
}
void YamlSaveHelper::SaveHexUint32(const char* key, UINT value)
{
Save("%s: 0x%08X\n", key, value);
}
void YamlSaveHelper::SaveHexUint64(const char* key, UINT64 value)
{
Save("%s: 0x%016llX\n", key, value);
}
void YamlSaveHelper::SaveBool(const char* key, bool value)
{
Save("%s: %s\n", key, value ? "true" : "false");
}
void YamlSaveHelper::SaveString(const char* key, const char* value)
{
Save("%s: %s\n", key, (value[0] != 0) ? value : "\"\"");
}
// Pre: uMemSize must be multiple of 8
void YamlSaveHelper::SaveMemory(const LPBYTE pMemBase, const UINT uMemSize)
{
if (uMemSize & 7)
throw std::string("Memory: size must be multiple of 8");
const UINT kIndent = m_indent;
const UINT kStride = 64;
const char szHex[] = "0123456789ABCDEF";
size_t lineSize = kIndent+6+2*kStride+2; // "AAAA: 00010203...3F\n\00" = 6+ 2*64 +2
char* const pLine = new char [lineSize];
for(DWORD dwOffset = 0x0000; dwOffset < uMemSize; dwOffset+=kStride)
{
char* pDst = pLine;
for (UINT i=0; i<kIndent; i++)
*pDst++ = ' ';
*pDst++ = szHex[ (dwOffset>>12)&0xf ];
*pDst++ = szHex[ (dwOffset>>8)&0xf ];
*pDst++ = szHex[ (dwOffset>>4)&0xf ];
*pDst++ = szHex[ dwOffset&0xf ];
*pDst++ = ':';
*pDst++ = ' ';
LPBYTE pMem = pMemBase + dwOffset;
for (UINT i=0; i<kStride; i+=8)
{
if (dwOffset + i >= uMemSize) // Support short final line (still multiple of 8 bytes)
{
lineSize = lineSize - 2*kStride + 2*i;
break;
}
BYTE d;
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
d = *pMem++; *pDst++ = szHex[d>>4]; *pDst++ = szHex[d&0xf];
}
*pDst++ = '\n';
*pDst = 0; // For debugger
fwrite(pLine, 1, lineSize-1, m_hFile); // -1 so don't write null terminator
}
delete [] pLine;
}
void YamlSaveHelper::FileHdr(UINT version)
{
fprintf(m_hFile, "%s:\n", SS_YAML_KEY_FILEHDR);
m_indent = 2;
SaveString(SS_YAML_KEY_TAG, SS_YAML_VALUE_AWSS);
SaveInt(SS_YAML_KEY_VERSION, version);
}
void YamlSaveHelper::UnitHdr(std::string type, UINT version)
{
fprintf(m_hFile, "\n%s:\n", SS_YAML_KEY_UNIT);
m_indent = 2;
SaveString(SS_YAML_KEY_TYPE, type.c_str());
SaveInt(SS_YAML_KEY_VERSION, version);
}

266
source/YamlHelper.h Normal file
View File

@ -0,0 +1,266 @@
#pragma once
#include "yaml.h"
#define SS_YAML_KEY_FILEHDR "File_hdr"
#define SS_YAML_KEY_TAG "Tag"
#define SS_YAML_KEY_VERSION "Version"
#define SS_YAML_KEY_UNIT "Unit"
#define SS_YAML_KEY_TYPE "Type"
#define SS_YAML_KEY_CARD "Card"
#define SS_YAML_KEY_STATE "State"
#define SS_YAML_VALUE_AWSS "AppleWin Save State"
struct MapValue;
typedef std::map<std::string, MapValue> MapYaml;
struct MapValue
{
std::string value;
MapYaml* subMap;
};
class YamlHelper
{
friend class YamlLoadHelper; // YamlLoadHelper can access YamlHelper's private members
public:
YamlHelper(void) :
m_hFile(NULL)
{
MakeAsciiToHexTable();
}
~YamlHelper(void)
{
if (m_hFile)
fclose(m_hFile);
}
int InitParser(const char* pPathname);
void FinaliseParser(void);
int GetScalar(std::string& scalar);
void GetMapStartEvent(void);
private:
void GetNextEvent(bool bInMap = false);
int ParseMap(MapYaml& mapYaml);
std::string GetMapValue(MapYaml& mapYaml, const std::string key, bool& bFound);
void LoadMemory(MapYaml& mapYaml, const LPBYTE pMemBase, const size_t kAddrSpaceSize);
bool GetSubMap(MapYaml** mapYaml, const std::string key);
void GetMapRemainder(std::string& mapName, MapYaml& mapYaml);
void MakeAsciiToHexTable(void);
yaml_parser_t m_parser;
yaml_event_t m_newEvent;
std::string m_scalarName;
FILE* m_hFile;
char m_AsciiToHex[256];
MapYaml m_mapYaml;
};
// -----
class YamlLoadHelper
{
public:
YamlLoadHelper(YamlHelper& yamlHelper)
: m_yamlHelper(yamlHelper),
m_pMapYaml(&yamlHelper.m_mapYaml),
m_bIteratingOverMap(false),
m_bDoGetMapRemainder(true),
m_topLevelMapName(yamlHelper.m_scalarName),
m_currentMapName(m_topLevelMapName)
{
if (!m_yamlHelper.ParseMap(yamlHelper.m_mapYaml))
{
m_bDoGetMapRemainder = false;
throw std::string(m_currentMapName + ": Failed to parse map");
}
}
~YamlLoadHelper(void)
{
if (m_bDoGetMapRemainder)
m_yamlHelper.GetMapRemainder(m_topLevelMapName, m_yamlHelper.m_mapYaml);
}
INT LoadInt(const std::string key);
UINT LoadUint(const std::string key);
UINT64 LoadUint64(const std::string key);
bool LoadBool(const std::string key);
std::string LoadString_NoThrow(const std::string& key, bool& bFound);
std::string LoadString(const std::string& key);
void LoadMemory(const LPBYTE pMemBase, const size_t size);
bool GetSubMap(const std::string key)
{
YamlStackItem item = {m_pMapYaml, m_currentMapName};
m_stackMap.push(item);
bool res = m_yamlHelper.GetSubMap(&m_pMapYaml, key);
if (!res)
m_stackMap.pop();
else
m_currentMapName = key;
return res;
}
void PopMap(void)
{
if (m_stackMap.empty())
return;
YamlStackItem item = m_stackMap.top();
m_stackMap.pop();
m_pMapYaml = item.pMapYaml;
m_currentMapName = item.mapName;
}
std::string GetMapNextSlotNumber(void)
{
if (!m_bIteratingOverMap)
{
m_iter = m_pMapYaml->begin();
m_bIteratingOverMap = true;
}
if (m_iter == m_pMapYaml->end())
{
m_bIteratingOverMap = false;
return "";
}
std::string scalar = m_iter->first;
++m_iter;
return scalar;
}
private:
YamlHelper& m_yamlHelper;
MapYaml* m_pMapYaml;
bool m_bDoGetMapRemainder;
struct YamlStackItem
{
MapYaml* pMapYaml;
std::string mapName;
};
std::stack<YamlStackItem> m_stackMap;
std::string m_topLevelMapName;
std::string m_currentMapName;
bool m_bIteratingOverMap;
MapYaml::iterator m_iter;
};
// -----
class YamlSaveHelper
{
public:
YamlSaveHelper(std::string pathname) :
m_hFile(NULL),
m_indent(0)
{
m_hFile = fopen(pathname.c_str(), "wt");
// todo: handle ERROR_ALREADY_EXISTS - ask if user wants to replace existing file
// - at this point any old file will have been truncated to zero
if(m_hFile == NULL)
throw std::string("Save error");
_tzset();
time_t ltime;
time(&ltime);
char timebuf[26];
errno_t err = ctime_s(timebuf, sizeof(timebuf), &ltime); // includes newline at end of string
fprintf(m_hFile, "# Date-stamp: %s\n", err == 0 ? timebuf : "Error: Datestamp\n\n");
fprintf(m_hFile, "---\n");
//
memset(m_szIndent, ' ', kMaxIndent);
}
~YamlSaveHelper()
{
if (m_hFile)
{
fprintf(m_hFile, "...\n");
fclose(m_hFile);
}
}
void Save(const char* format, ...);
void SaveInt(const char* key, int value);
void SaveUint(const char* key, UINT value);
void SaveHexUint4(const char* key, UINT value);
void SaveHexUint8(const char* key, UINT value);
void SaveHexUint12(const char* key, UINT value);
void SaveHexUint16(const char* key, UINT value);
void SaveHexUint32(const char* key, UINT value);
void SaveHexUint64(const char* key, UINT64 value);
void SaveBool(const char* key, bool value);
void SaveString(const char* key, const char* value);
void SaveMemory(const LPBYTE pMemBase, const UINT uMemSize);
class Label
{
public:
Label(YamlSaveHelper& rYamlSaveHelper, const char* format, ...) :
yamlSaveHelper(rYamlSaveHelper)
{
fwrite(yamlSaveHelper.m_szIndent, 1, yamlSaveHelper.m_indent, yamlSaveHelper.m_hFile);
va_list vl;
va_start(vl, format);
vfprintf(yamlSaveHelper.m_hFile, format, vl);
va_end(vl);
yamlSaveHelper.m_indent += 2;
_ASSERT(yamlSaveHelper.m_indent < yamlSaveHelper.kMaxIndent);
}
~Label(void)
{
yamlSaveHelper.m_indent -= 2;
_ASSERT(yamlSaveHelper.m_indent >= 0);
}
YamlSaveHelper& yamlSaveHelper;
};
class Slot : public Label
{
public:
Slot(YamlSaveHelper& rYamlSaveHelper, std::string type, UINT slot, UINT version) :
Label(rYamlSaveHelper, "%d:\n", slot)
{
rYamlSaveHelper.Save("%s: %s\n", SS_YAML_KEY_CARD, type.c_str());
rYamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_VERSION, version);
}
~Slot(void) {}
};
void FileHdr(UINT version);
void UnitHdr(std::string type, UINT version);
private:
FILE* m_hFile;
int m_indent;
static const UINT kMaxIndent = 50*2;
char m_szIndent[kMaxIndent];
};

View File

@ -29,6 +29,7 @@
#include "..\AppleWin.h"
#include "..\CPU.h"
#include "..\Memory.h"
#include "..\YamlHelper.h"
#undef IN // Defined in windef.h
@ -86,16 +87,20 @@ static BYTE reg_f2 = 0;
static BYTE reg_h2 = 0;
static BYTE reg_l2 = 0;
#if 0 // [AppleWin-TC] Not used
static int dma_request = 0;
#endif
static BYTE *z80_bank_base;
static int z80_bank_limit;
#if 0 // [AppleWin-TC] Not used
void z80_trigger_dma(void)
{
dma_request = 1;
}
#endif
void z80_reset(void)
{
@ -162,11 +167,11 @@ void z80_reset(void)
/* ------------------------------------------------------------------------- */
#if 0 // [AppleWin-TC]
static unsigned int z80_last_opcode_info;
#define LAST_OPCODE_INFO z80_last_opcode_info
#if 0 // [AppleWin-TC]
/* Remember the number of the last opcode. By default, the opcode does not
delay interrupt and does not change the I flag. */
#define SET_LAST_OPCODE(x) \
@ -463,6 +468,9 @@ static void export_registers(void)
/* ------------------------------------------------------------------------- */
// [AppleWin-TC] Z80 IRQs not supported
#if 0
/* Interrupt handling. */
#define DO_INTERRUPT(int_kind) \
@ -533,6 +541,7 @@ static void export_registers(void)
} \
} \
} while (0)
#endif
/* ------------------------------------------------------------------------- */
@ -6330,7 +6339,7 @@ DWORD z80_mainloop(ULONG uTotalCycles, ULONG uExecutedCycles)
//cpu_int_status->num_dma_per_opcode = 0; // [AppleWin-TC] Not used
if (g_ActiveCPU != CPU_Z80) // [AppleWin-TC]
if (GetActiveCpu() != CPU_Z80) // [AppleWin-TC]
break;
//} while (!dma_request);
@ -6422,3 +6431,139 @@ void z80_WRMEM(WORD Addr, BYTE Value)
}
CpuWrite( addr, Value, ConvertZ80TStatesTo6502Cycles(maincpu_clk) );
}
//===========================================================================
#define SS_YAML_VALUE_CARD_Z80 "Z80"
#define SS_YAML_KEY_REGA "A"
#define SS_YAML_KEY_REGB "B"
#define SS_YAML_KEY_REGC "C"
#define SS_YAML_KEY_REGD "D"
#define SS_YAML_KEY_REGE "E"
#define SS_YAML_KEY_REGF "F"
#define SS_YAML_KEY_REGH "H"
#define SS_YAML_KEY_REGL "L"
#define SS_YAML_KEY_REGIX "IX"
#define SS_YAML_KEY_REGIY "IY"
#define SS_YAML_KEY_REGSP "SP"
#define SS_YAML_KEY_REGPC "PC"
#define SS_YAML_KEY_REGI "I"
#define SS_YAML_KEY_REGR "R"
#define SS_YAML_KEY_IFF1 "IFF1"
#define SS_YAML_KEY_IFF2 "IFF2"
#define SS_YAML_KEY_IM_MODE "IM Mode"
#define SS_YAML_KEY_REGA2 "A'"
#define SS_YAML_KEY_REGB2 "B'"
#define SS_YAML_KEY_REGC2 "C'"
#define SS_YAML_KEY_REGD2 "D'"
#define SS_YAML_KEY_REGE2 "E'"
#define SS_YAML_KEY_REGF2 "F'"
#define SS_YAML_KEY_REGH2 "H'"
#define SS_YAML_KEY_REGL2 "L'"
#define SS_YAML_KEY_ACTIVE "Active"
std::string Z80_GetSnapshotCardName(void)
{
static const std::string name(SS_YAML_VALUE_CARD_Z80);
return name;
}
void Z80_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot)
{
YamlSaveHelper::Slot slot(yamlSaveHelper, Z80_GetSnapshotCardName(), uSlot, 1); // fixme: object should know its slot
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
// SoftCard SW & HW details: http://apple2info.net/images/f/f0/SC-SWHW.pdf
// . SoftCard uses the Apple II's DMA circuit to pause the 6502 (no CLK to 6502)
// . But: "In Apple II DMA, the 6502 CPU will die after approximately 15 clocks because it depends on the clock to refresh its internal registers."
// ref: Apple Tech Note: https://archive.org/stream/IIe_2523004_RDY_Line/IIe_2523004_RDY_Line_djvu.txt
// NB. Not for 65C02 which is a static processor.
// . SoftCard controls the 6502's RDY line to periodically allow only 1 memory fetch by 6502 (ie. the opcode fetch)
//
// So save ActiveCPU to SS_CARD_Z80 (so RDY is like IRQ & NMI signals, ie. saved struct of the producer's card)
//
// NB. Save-state only occurs when message pump runs:
// . ie. at end of 1ms emulation burst
// Either 6502 or Z80 could be active.
//
yamlSaveHelper.Save("%s: %d\n", SS_YAML_KEY_ACTIVE, GetActiveCpu() == CPU_Z80 ? 1 : 0);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGA, reg_a);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGB, reg_b);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGC, reg_c);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGD, reg_d);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGE, reg_e);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGF, reg_f);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGH, reg_h);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGL, reg_l);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REGIX, ((USHORT)reg_ixh<<8)|(USHORT)reg_ixl);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REGIY, ((USHORT)reg_iyh<<8)|(USHORT)reg_iyl);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REGSP, reg_sp);
yamlSaveHelper.SaveHexUint16(SS_YAML_KEY_REGPC, (USHORT)z80_reg_pc);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGI, reg_i);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGR, reg_r);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IFF1, iff1);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IFF2, iff2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IM_MODE, im_mode);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGA2, reg_a2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGB2, reg_b2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGC2, reg_c2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGD2, reg_d2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGE2, reg_e2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGF2, reg_f2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGH2, reg_h2);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_REGL2, reg_l2);
}
bool Z80_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uSlot, UINT version)
{
if (uSlot != 4 && uSlot != 5) // fixme
throw std::string("Card: wrong slot");
if (version != 1)
throw std::string("Card: wrong version");
reg_a = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGA);
reg_b = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGB);
reg_c = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGC);
reg_d = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGD);
reg_e = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGE);
reg_f = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGF);
reg_h = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGH);
reg_l = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGL);
USHORT IX = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGIX);
reg_ixh = IX >> 8;
reg_ixl = IX & 0xFF;
USHORT IY = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGIY);
reg_iyh = IY >> 8;
reg_iyl = IY & 0xFF;
reg_sp = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGSP);
z80_reg_pc = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGPC);
reg_i = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGI);
reg_r = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGR);
iff1 = yamlLoadHelper.LoadUint(SS_YAML_KEY_IFF1);
iff2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_IFF2);
im_mode = yamlLoadHelper.LoadUint(SS_YAML_KEY_IM_MODE);
reg_a2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGA2);
reg_b2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGB2);
reg_c2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGC2);
reg_d2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGD2);
reg_e2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGE2);
reg_f2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGF2);
reg_h2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGH2);
reg_l2 = yamlLoadHelper.LoadUint(SS_YAML_KEY_REGL2);
export_registers();
if ( yamlLoadHelper.LoadUint(SS_YAML_KEY_ACTIVE) )
SetActiveCpu(CPU_Z80); // Support MS SoftCard in multiple slots (only one Z80 can be active at any one time)
return true;
}

View File

@ -46,6 +46,7 @@ typedef struct z80_regs_s {
WORD reg_hl2;
} z80_regs_t;
#if 0 // [AppleWin-TC]: unused, so comment out
#define Z80_REGS_GET_AF(reg_ptr) ((reg_ptr)->reg_af)
#define Z80_REGS_GET_BC(reg_ptr) ((reg_ptr)->reg_bc)
#define Z80_REGS_GET_DE(reg_ptr) ((reg_ptr)->reg_de)
@ -75,6 +76,7 @@ typedef struct z80_regs_s {
#define Z80_REGS_SET_BC2(reg_ptr, val) ((reg_ptr)->reg_bc2 = (val))
#define Z80_REGS_SET_DE2(reg_ptr, val) ((reg_ptr)->reg_de2 = (val))
#define Z80_REGS_SET_HL2(reg_ptr, val) ((reg_ptr)->reg_hl2 = (val))
#endif
#endif

View File

@ -16,6 +16,7 @@
#include "StdAfx.h"
#include "AppleWin.h"
#include "CPU.h"
#include "Memory.h"
#include "z80emu.h"
@ -30,7 +31,7 @@ BYTE __stdcall CPMZ80_IONull(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULON
BYTE __stdcall CPMZ80_IOWrite(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft)
{
if ((uAddr & 0xFF00) == (0xC000 + (g_uCPMZ80Slot << 8)))
g_ActiveCPU = (g_ActiveCPU == CPU_6502) ? CPU_Z80 : CPU_6502;
SetActiveCpu( GetActiveCpu() == CPU_Z80 ? GetMainCpu() : CPU_Z80 );
return IO_Null(PC, uAddr, bWrite, uValue, nCyclesLeft);
}

View File

@ -14,3 +14,8 @@
// Protótipos
void ConfigureSoftcard(LPBYTE pCxRomPeripheral, UINT uSlot);
// NB. These are in z80.cpp:
std::string Z80_GetSnapshotCardName(void);
void Z80_SaveSnapshot(class YamlSaveHelper& yamlSaveHelper, const UINT uSlot);
bool Z80_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT uSlot, UINT version);