diff --git a/AppleWinExpress2008.vcproj b/AppleWinExpress2008.vcproj
index f4caecb5..5b84393f 100644
--- a/AppleWinExpress2008.vcproj
+++ b/AppleWinExpress2008.vcproj
@@ -227,11 +227,27 @@
Filter=".cpp"
>
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj
index c88598d7..07271ac3 100644
--- a/AppleWinExpress2019.vcxproj
+++ b/AppleWinExpress2019.vcxproj
@@ -22,10 +22,10 @@
-
+
@@ -45,6 +45,7 @@
+
@@ -107,7 +108,9 @@
+
+
@@ -129,9 +132,9 @@
-
+
@@ -141,6 +144,7 @@
+
@@ -214,7 +218,9 @@
NotUsing
NotUsing
+
+
diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters
index ec3295e5..3d7cfd4e 100644
--- a/AppleWinExpress2019.vcxproj.filters
+++ b/AppleWinExpress2019.vcxproj.filters
@@ -1,9 +1,6 @@
-
- Source Files
-
Source Files\Emulator
@@ -211,11 +208,20 @@
Source Files\Windows
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\Windows
+
+
+ Source Files
+
-
- Source Files
-
Source Files\CommonVICE
@@ -507,6 +513,18 @@
Source Files\Windows
+
+ Source Files
+
+
+ Source Files
+
+
+ Source Files\Windows
+
+
+ Source Files
+
diff --git a/source/AY8910.cpp b/source/AY8910.cpp
index 0b4e3338..3a0f0716 100644
--- a/source/AY8910.cpp
+++ b/source/AY8910.cpp
@@ -28,7 +28,7 @@
#include "AY8910.h"
-#include "AppleWin.h" // For g_fh
+#include "Core.h" // For g_fh
#include "YamlHelper.h"
/* The AY white noise RNG algorithm is based on info from MAME's ay8910.c -
diff --git a/source/AppleWin.cpp b/source/AppleWin.cpp
deleted file mode 100644
index 74099758..00000000
--- a/source/AppleWin.cpp
+++ /dev/null
@@ -1,2270 +0,0 @@
-/*
-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
-
-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: main
- *
- * Author: Various
- */
-
-#include "StdAfx.h"
-
-#include "AppleWin.h"
-#include "CardManager.h"
-#include "CPU.h"
-#include "Debug.h"
-#include "Disk.h"
-#include "DiskImage.h"
-#include "Harddisk.h"
-#include "Joystick.h"
-#include "Keyboard.h"
-#include "LanguageCard.h"
-#include "Log.h"
-#include "Memory.h"
-#include "Mockingboard.h"
-#include "MouseInterface.h"
-#include "ParallelPrinter.h"
-#include "Registry.h"
-#include "Riff.h"
-#include "SaveState.h"
-#include "SerialComms.h"
-#include "SoundCore.h"
-#include "Speaker.h"
-#ifdef USE_SPEECH_API
-#include "Speech.h"
-#endif
-#include "SynchronousEventManager.h"
-#include "Windows/WinVideo.h"
-#include "Windows/WinFrame.h"
-#include "RGBMonitor.h"
-#include "NTSC.h"
-
-#include "Configuration/About.h"
-#include "Configuration/PropertySheet.h"
-#include "Tfe/Tfe.h"
-
-static const UINT VERSIONSTRING_SIZE = 16;
-
-static UINT16 g_AppleWinVersion[4] = {0};
-static UINT16 g_OldAppleWinVersion[4] = {0};
-TCHAR VERSIONSTRING[VERSIONSTRING_SIZE] = "xx.yy.zz.ww";
-
-std::string g_pAppTitle;
-
-eApple2Type g_Apple2Type = A2TYPE_APPLE2EENHANCED;
-
-bool g_bFullSpeed = false;
-
-//=================================================
-
-// Win32
-HINSTANCE g_hInstance = (HINSTANCE)0;
-
-AppMode_e g_nAppMode = MODE_LOGO;
-static bool g_bLoadedSaveState = false;
-static bool g_bSysClkOK = false;
-
-std::string g_sStartDir; // NB. AppleWin.exe maybe relative to this! (GH#663)
-std::string g_sProgramDir; // Directory of where AppleWin executable resides
-std::string g_sDebugDir; // TODO: Not currently used
-std::string g_sScreenShotDir; // TODO: Not currently used
-std::string g_sConfigFile; // INI file to use instead of Registry
-
-bool g_bCapturePrintScreenKey = true;
-static bool g_bHookSystemKey = true;
-static bool g_bHookAltTab = false;
-static bool g_bHookAltGrControl = false;
-
-std::string g_sCurrentDir; // Also Starting Dir. Debugger uses this when load/save
-bool g_bRestart = false;
-bool g_bRestartFullScreen = false;
-
-DWORD g_dwSpeed = SPEED_NORMAL; // Affected by Config dialog's speed slider bar
-double g_fCurrentCLK6502 = CLK_6502_NTSC; // Affected by Config dialog's speed slider bar
-static double g_fMHz = 1.0; // Affected by Config dialog's speed slider bar
-
-int g_nCpuCyclesFeedback = 0;
-DWORD g_dwCyclesThisFrame = 0;
-
-bool g_bDisableDirectInput = false;
-bool g_bDisableDirectSound = false;
-bool g_bDisableDirectSoundMockingboard = false;
-int g_nMemoryClearType = MIP_FF_FF_00_00; // Note: -1 = random MIP in Memory.cpp MemReset()
-
-IPropertySheet& sg_PropertySheet = * new CPropertySheet;
-
-SynchronousEventManager g_SynchronousEventMgr;
-
-HANDLE g_hCustomRomF8 = INVALID_HANDLE_VALUE; // Cmd-line specified custom F8 ROM at $F800..$FFFF
-static bool g_bCustomRomF8Failed = false; // Set if custom F8 ROM file failed
-HANDLE g_hCustomRom = INVALID_HANDLE_VALUE; // Cmd-line specified custom ROM at $C000..$FFFF(16KiB) or $D000..$FFFF(12KiB)
-static bool g_bCustomRomFailed = false; // Set if custom ROM file failed
-
-static bool g_bEnableSpeech = false;
-#ifdef USE_SPEECH_API
-CSpeech g_Speech;
-#endif
-
-//===========================================================================
-
-#ifdef LOG_PERF_TIMINGS
-static UINT64 g_timeTotal = 0;
-UINT64 g_timeCpu = 0;
-UINT64 g_timeVideo = 0; // part of timeCpu
-UINT64 g_timeMB_Timer = 0; // part of timeCpu
-UINT64 g_timeMB_NoTimer = 0;
-UINT64 g_timeSpeaker = 0;
-static UINT64 g_timeVideoRefresh = 0;
-
-void LogPerfTimings(void)
-{
- if (g_timeTotal)
- {
- UINT64 cpu = g_timeCpu - g_timeVideo - g_timeMB_Timer;
- UINT64 video = g_timeVideo + g_timeVideoRefresh;
- UINT64 spkr = g_timeSpeaker;
- UINT64 mb = g_timeMB_Timer + g_timeMB_NoTimer;
- UINT64 audio = spkr + mb;
- UINT64 other = g_timeTotal - g_timeCpu - g_timeSpeaker - g_timeMB_NoTimer - g_timeVideoRefresh;
-
- LogOutput("Perf breakdown:\n");
- LogOutput(". CPU %% = %6.2f\n", (double)cpu / (double)g_timeTotal * 100.0);
- LogOutput(". Video %% = %6.2f\n", (double)video / (double)g_timeTotal * 100.0);
- LogOutput("... NTSC %% = %6.2f\n", (double)g_timeVideo / (double)g_timeTotal * 100.0);
- LogOutput("... refresh %% = %6.2f\n", (double)g_timeVideoRefresh / (double)g_timeTotal * 100.0);
- LogOutput(". Audio %% = %6.2f\n", (double)audio / (double)g_timeTotal * 100.0);
- LogOutput("... Speaker %% = %6.2f\n", (double)spkr / (double)g_timeTotal * 100.0);
- LogOutput("... MB %% = %6.2f\n", (double)mb / (double)g_timeTotal * 100.0);
- LogOutput(". Other %% = %6.2f\n", (double)other / (double)g_timeTotal * 100.0);
- LogOutput(". TOTAL %% = %6.2f\n", (double)(cpu+video+audio+other) / (double)g_timeTotal * 100.0);
- }
-}
-#endif
-
-//===========================================================================
-
-static DWORD dwLogKeyReadTickStart;
-static bool bLogKeyReadDone = false;
-
-void LogFileTimeUntilFirstKeyReadReset(void)
-{
-#ifdef LOG_PERF_TIMINGS
- LogPerfTimings();
-#endif
-
- if (!g_fh)
- return;
-
- dwLogKeyReadTickStart = GetTickCount();
-
- bLogKeyReadDone = false;
-}
-
-// Log the time from emulation restart/reboot until the first key read: BIT $C000
-// . AZTEC.DSK (DOS 3.3) does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message
-// . Phasor1.dsk / ProDOS 1.1.1: PC=E797: B1 50: LDA ($50),Y / "Select an Option:" message
-// . Rescue Raiders v1.3,v1.5: PC=895: LDA $C000 / boot to intro
-void LogFileTimeUntilFirstKeyRead(void)
-{
- if (!g_fh || bLogKeyReadDone)
- return;
-
- if ( (mem[regs.pc-3] != 0x2C) // AZTEC: bit $c000
- && !((regs.pc-2) == 0xE797 && mem[regs.pc-2] == 0xB1 && mem[regs.pc-1] == 0x50) // Phasor1: lda ($50),y
- && !((regs.pc-3) == 0x0895 && mem[regs.pc-3] == 0xAD) // Rescue Raiders v1.3,v1.5: lda $c000
- )
- return;
-
- DWORD dwTime = GetTickCount() - dwLogKeyReadTickStart;
-
- LogFileOutput("Time from emulation reboot until first $C000 access: %d msec\n", dwTime);
-
- bLogKeyReadDone = true;
-}
-
-//---------------------------------------------------------------------------
-
-eApple2Type GetApple2Type(void)
-{
- return g_Apple2Type;
-}
-
-void SetApple2Type(eApple2Type type)
-{
- g_Apple2Type = type;
- SetMainCpuDefault(type);
-}
-
-const UINT16* GetOldAppleWinVersion(void)
-{
- return g_OldAppleWinVersion;
-}
-
-bool GetLoadedSaveStateFlag(void)
-{
- return g_bLoadedSaveState;
-}
-
-void SetLoadedSaveStateFlag(const bool bFlag)
-{
- g_bLoadedSaveState = bFlag;
-}
-
-bool GetHookAltGrControl(void)
-{
- return g_bHookAltGrControl;
-}
-
-CardManager& GetCardMgr(void)
-{
- static CardManager g_CardMgr; // singleton
- return g_CardMgr;
-}
-
-static void ResetToLogoMode(void)
-{
- g_nAppMode = MODE_LOGO;
- SetLoadedSaveStateFlag(false);
-}
-
-//---------------------------------------------------------------------------
-
-static bool g_bPriorityNormal = true;
-
-// Make APPLEWIN process higher priority
-void SetPriorityAboveNormal(void)
-{
- if (!g_bPriorityNormal)
- return;
-
- if ( SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS) )
- {
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
- g_bPriorityNormal = false;
- }
-}
-
-// Make APPLEWIN process normal priority
-void SetPriorityNormal(void)
-{
- if (g_bPriorityNormal)
- return;
-
- if ( SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS) )
- {
- SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
- g_bPriorityNormal = true;
- }
-}
-
-//---------------------------------------------------------------------------
-
-static UINT g_uModeStepping_Cycles = 0;
-static bool g_uModeStepping_LastGetKey_ScrollLock = false;
-
-static void ContinueExecution(void)
-{
-#ifdef LOG_PERF_TIMINGS
- PerfMarker* pPerfMarkerTotal = new PerfMarker(g_timeTotal);
-#endif
-
- _ASSERT(g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING);
-
- const double fUsecPerSec = 1.e6;
-#if 1
- const UINT nExecutionPeriodUsec = 1000; // 1.0ms
-// const UINT nExecutionPeriodUsec = 100; // 0.1ms
- const double fExecutionPeriodClks = g_fCurrentCLK6502 * ((double)nExecutionPeriodUsec / fUsecPerSec);
-#else
- const double fExecutionPeriodClks = 1800.0;
- const UINT nExecutionPeriodUsec = (UINT) (fUsecPerSec * (fExecutionPeriodClks / g_fCurrentCLK6502));
-#endif
-
- //
-
- bool bScrollLock_FullSpeed = false;
- if (sg_PropertySheet.GetScrollLockToggle())
- {
- bScrollLock_FullSpeed = g_bScrollLock_FullSpeed;
- }
- else
- {
- if (g_nAppMode == MODE_RUNNING)
- {
- bScrollLock_FullSpeed = GetKeyState(VK_SCROLL) < 0;
- }
- else if (!IsDebugSteppingAtFullSpeed()) // Implicitly: MODE_STEPPING
- {
- // NB. For MODE_STEPPING: GetKeyState() is slow, so only call periodically
- // . 0x3FFF is roughly the number of cycles in a video frame, which seems a reasonable rate to call GetKeyState()
- if ((g_uModeStepping_Cycles & 0x3FFF) == 0)
- g_uModeStepping_LastGetKey_ScrollLock = GetKeyState(VK_SCROLL) < 0;
-
- bScrollLock_FullSpeed = g_uModeStepping_LastGetKey_ScrollLock;
- }
- }
-
- const bool bWasFullSpeed = g_bFullSpeed;
- g_bFullSpeed = (g_dwSpeed == SPEED_MAX) ||
- bScrollLock_FullSpeed ||
- (GetCardMgr().GetDisk2CardMgr().IsConditionForFullSpeed() && !Spkr_IsActive() && !MB_IsActive()) ||
- IsDebugSteppingAtFullSpeed();
-
- if (g_bFullSpeed)
- {
- if (!bWasFullSpeed)
- VideoRedrawScreenDuringFullSpeed(0, true); // Init for full-speed mode
-
- // Don't call Spkr_Mute() - will get speaker clicks
- MB_Mute();
- SysClk_StopTimer();
-#ifdef USE_SPEECH_API
- g_Speech.Reset(); // TODO: Put this on a timer (in emulated cycles)... otherwise CATALOG cuts out
-#endif
-
- g_nCpuCyclesFeedback = 0; // For the case when this is a big -ve number
-
- // Switch to normal priority so that APPLEWIN process doesn't hog machine!
- //. EG: No disk in Drive-1, and boot Apple: Windows will start to crawl!
- SetPriorityNormal();
- }
- else
- {
- if (bWasFullSpeed)
- VideoRedrawScreenAfterFullSpeed(g_dwCyclesThisFrame);
-
- // Don't call Spkr_Demute()
- MB_Demute();
- SysClk_StartTimerUsec(nExecutionPeriodUsec);
-
- // Switch to higher priority, eg. for audio (BUG #015394)
- SetPriorityAboveNormal();
- }
-
- //
-
- int nCyclesWithFeedback = (int) fExecutionPeriodClks + g_nCpuCyclesFeedback;
- const UINT uCyclesToExecuteWithFeedback = (nCyclesWithFeedback >= 0) ? nCyclesWithFeedback
- : 0;
-
- const DWORD uCyclesToExecute = (g_nAppMode == MODE_RUNNING) ? uCyclesToExecuteWithFeedback
- /* MODE_STEPPING */ : 0;
-
- const bool bVideoUpdate = !g_bFullSpeed;
- const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate);
- g_dwCyclesThisFrame += uActualCyclesExecuted;
-
- GetCardMgr().GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted);
- JoyUpdateButtonLatch(nExecutionPeriodUsec); // Button latch time is independent of CPU clock frequency
- PrintUpdate(uActualCyclesExecuted);
- MB_PeriodicUpdate(uActualCyclesExecuted);
-
- //
-
- DWORD uSpkrActualCyclesExecuted = uActualCyclesExecuted;
-
- bool bModeStepping_WaitTimer = false;
- if (g_nAppMode == MODE_STEPPING && !IsDebugSteppingAtFullSpeed())
- {
- g_uModeStepping_Cycles += uActualCyclesExecuted;
- if (g_uModeStepping_Cycles >= uCyclesToExecuteWithFeedback)
- {
- uSpkrActualCyclesExecuted = g_uModeStepping_Cycles;
-
- g_uModeStepping_Cycles -= uCyclesToExecuteWithFeedback;
- bModeStepping_WaitTimer = true;
- }
- }
-
- // For MODE_STEPPING: do this speaker update periodically
- // - Otherwise kills performance due to sound-buffer lock/unlock for every 6502 opcode!
- if (g_nAppMode == MODE_RUNNING || bModeStepping_WaitTimer)
- SpkrUpdate(uSpkrActualCyclesExecuted);
-
- //
-
- const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
- if (g_dwCyclesThisFrame >= dwClksPerFrame && !VideoGetVblBarEx(g_dwCyclesThisFrame))
- {
-#ifdef LOG_PERF_TIMINGS
- PerfMarker perfMarkerVideoRefresh(g_timeVideoRefresh);
-#endif
- g_dwCyclesThisFrame -= dwClksPerFrame;
-
- if (g_bFullSpeed)
- VideoRedrawScreenDuringFullSpeed(g_dwCyclesThisFrame);
- else
- VideoRefreshScreen(); // Just copy the output of our Apple framebuffer to the system Back Buffer
- }
-
-#ifdef LOG_PERF_TIMINGS
- delete pPerfMarkerTotal; // Explicitly call dtor *before* SysClk_WaitTimer()
-#endif
-
- if ((g_nAppMode == MODE_RUNNING && !g_bFullSpeed) || bModeStepping_WaitTimer)
- {
- SysClk_WaitTimer();
- }
-}
-
-void SingleStep(bool bReinit)
-{
- if (bReinit)
- {
- g_uModeStepping_Cycles = 0;
- g_uModeStepping_LastGetKey_ScrollLock = false;
- }
-
- ContinueExecution();
-}
-
-//===========================================================================
-
-double Get6502BaseClock(void)
-{
- return (GetVideoRefreshRate() == VR_50HZ) ? CLK_6502_PAL : CLK_6502_NTSC;
-}
-
-void UseClockMultiplier(double clockMultiplier)
-{
- if (clockMultiplier == 0.0)
- return;
-
- if (clockMultiplier < 1.0)
- {
- if (clockMultiplier < 0.5)
- clockMultiplier = 0.5;
- g_dwSpeed = (ULONG)((clockMultiplier - 0.5) * 20); // [0.5..0.9] -> [0..9]
- }
- else
- {
- g_dwSpeed = (ULONG)(clockMultiplier * 10);
- if (g_dwSpeed >= SPEED_MAX)
- g_dwSpeed = SPEED_MAX - 1;
- }
-
- SetCurrentCLK6502();
-}
-
-void SetCurrentCLK6502(void)
-{
- static DWORD dwPrevSpeed = (DWORD) -1;
- static VideoRefreshRate_e prevVideoRefreshRate = VR_NONE;
-
- if (dwPrevSpeed == g_dwSpeed && GetVideoRefreshRate() == prevVideoRefreshRate)
- return;
-
- dwPrevSpeed = g_dwSpeed;
- prevVideoRefreshRate = GetVideoRefreshRate();
-
- // SPEED_MIN = 0 = 0.50 MHz
- // SPEED_NORMAL = 10 = 1.00 MHz
- // 20 = 2.00 MHz
- // SPEED_MAX-1 = 39 = 3.90 MHz
- // SPEED_MAX = 40 = ???? MHz (run full-speed, /g_fCurrentCLK6502/ is ignored)
-
- if(g_dwSpeed < SPEED_NORMAL)
- g_fMHz = 0.5 + (double)g_dwSpeed * 0.05;
- else
- g_fMHz = (double)g_dwSpeed / 10.0;
-
- g_fCurrentCLK6502 = Get6502BaseClock() * g_fMHz;
-
- //
- // Now re-init modules that are dependent on /g_fCurrentCLK6502/
- //
-
- SpkrReinitialize();
- MB_Reinitialize();
-}
-
-//===========================================================================
-
-void EnterMessageLoop(void)
-{
- MSG message;
-
- PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE);
-
- while (message.message!=WM_QUIT)
- {
- if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
- {
- TranslateMessage(&message);
- DispatchMessage(&message);
-
- while ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING))
- {
- if (PeekMessage(&message,0,0,0,PM_REMOVE))
- {
- if (message.message == WM_QUIT)
- return;
-
- TranslateMessage(&message);
- DispatchMessage(&message);
- }
- else if (g_nAppMode == MODE_STEPPING)
- {
- DebugContinueStepping();
- }
- else
- {
- ContinueExecution();
- if (g_nAppMode != MODE_DEBUG)
- {
- if (g_bFullSpeed)
- ContinueExecution();
- }
- }
- }
- }
- else
- {
- if (g_nAppMode == MODE_DEBUG)
- DebuggerUpdate();
- else if (g_nAppMode == MODE_PAUSED)
- Sleep(1); // Stop process hogging CPU - 1ms, as need to fade-out speaker sound buffer
- else if (g_nAppMode == MODE_LOGO)
- Sleep(1); // Stop process hogging CPU (NB. don't delay for too long otherwise key input can be slow in other apps - GH#569)
- }
- }
-}
-
-//===========================================================================
-
-static void GetProgramDirectory(void)
-{
- TCHAR programDir[MAX_PATH];
- GetModuleFileName((HINSTANCE)0, programDir, MAX_PATH);
- programDir[MAX_PATH-1] = 0;
-
- g_sProgramDir = programDir;
-
- int loop = g_sProgramDir.size();
- while (loop--)
- {
- if ((g_sProgramDir[loop] == TEXT('\\')) || (g_sProgramDir[loop] == TEXT(':')))
- {
- g_sProgramDir.resize(loop + 1); // this reduces the size
- break;
- }
- }
-}
-
-//===========================================================================
-
-// Backwards compatibility with AppleWin <1.24.0
-static void LoadConfigOldJoystick_v1(const UINT uJoyNum)
-{
- DWORD dwOldJoyType;
- if (!REGLOAD(TEXT(uJoyNum==0 ? REGVALUE_OLD_JOYSTICK0_EMU_TYPE1 : REGVALUE_OLD_JOYSTICK1_EMU_TYPE1), &dwOldJoyType))
- return; // EG. Old AppleWin never installed
-
- UINT uNewJoyType;
- switch (dwOldJoyType)
- {
- case 0: // Disabled
- default:
- uNewJoyType = J0C_DISABLED;
- break;
- case 1: // PC Joystick
- uNewJoyType = J0C_JOYSTICK1;
- break;
- case 2: // Keyboard (standard)
- uNewJoyType = J0C_KEYBD_NUMPAD;
- sg_PropertySheet.SetJoystickCenteringControl(JOYSTICK_MODE_FLOATING);
- break;
- case 3: // Keyboard (centering)
- uNewJoyType = J0C_KEYBD_NUMPAD;
- sg_PropertySheet.SetJoystickCenteringControl(JOYSTICK_MODE_CENTERING);
- break;
- case 4: // Mouse
- uNewJoyType = J0C_MOUSE;
- break;
- }
-
- JoySetJoyType(uJoyNum, uNewJoyType);
-}
-
-//Reads configuration from the registry entries
-void LoadConfiguration(void)
-{
- DWORD dwComputerType = 0;
- eApple2Type apple2Type = A2TYPE_APPLE2EENHANCED;
-
- if (REGLOAD(TEXT(REGVALUE_APPLE2_TYPE), &dwComputerType))
- {
- const DWORD dwLoadedComputerType = dwComputerType;
-
- if ( (dwComputerType >= A2TYPE_MAX) ||
- (dwComputerType >= A2TYPE_UNDEFINED && dwComputerType < A2TYPE_CLONE) ||
- (dwComputerType >= A2TYPE_CLONE_A2_MAX && dwComputerType < A2TYPE_CLONE_A2E) )
- dwComputerType = A2TYPE_APPLE2EENHANCED;
-
- // Remap the bad Pravets models (before AppleWin v1.26)
- if (dwComputerType == A2TYPE_BAD_PRAVETS82) dwComputerType = A2TYPE_PRAVETS82;
- if (dwComputerType == A2TYPE_BAD_PRAVETS8M) dwComputerType = A2TYPE_PRAVETS8M;
-
- // Remap the bad Pravets models (at AppleWin v1.26) - GH#415
- if (dwComputerType == A2TYPE_CLONE) dwComputerType = A2TYPE_PRAVETS82;
-
- if (dwLoadedComputerType != dwComputerType)
- {
- char sText[100];
- StringCbPrintf(sText, sizeof(sText), "Unsupported Apple2Type(%d). Changing to %d", dwLoadedComputerType, dwComputerType);
-
- LogFileOutput("%s\n", sText);
-
- MessageBox(
- GetDesktopWindow(), // NB. g_hFrameWindow is not yet valid
- sText,
- "Load Configuration",
- MB_ICONSTOP | MB_SETFOREGROUND);
-
- sg_PropertySheet.ConfigSaveApple2Type((eApple2Type)dwComputerType);
- }
-
- apple2Type = (eApple2Type) dwComputerType;
- }
- else if (REGLOAD(TEXT(REGVALUE_OLD_APPLE2_TYPE), &dwComputerType)) // Support older AppleWin registry entries
- {
- switch (dwComputerType)
- {
- // NB. No A2TYPE_APPLE2E (this is correct)
- case 0: apple2Type = A2TYPE_APPLE2; break;
- case 1: apple2Type = A2TYPE_APPLE2PLUS; break;
- case 2: apple2Type = A2TYPE_APPLE2EENHANCED; break;
- default: apple2Type = A2TYPE_APPLE2EENHANCED; break;
- }
- }
-
- SetApple2Type(apple2Type);
-
- //
-
- DWORD dwMainCpuType;
- REGLOAD_DEFAULT(TEXT(REGVALUE_CPU_TYPE), &dwMainCpuType, CPU_65C02);
- if (dwMainCpuType != CPU_6502 && dwMainCpuType != CPU_65C02)
- dwMainCpuType = CPU_65C02;
- SetMainCpu((eCpuType)dwMainCpuType);
-
- //
-
- DWORD dwJoyType;
- if (REGLOAD(TEXT(REGVALUE_JOYSTICK0_EMU_TYPE), &dwJoyType))
- JoySetJoyType(JN_JOYSTICK0, dwJoyType);
- else if (REGLOAD(TEXT(REGVALUE_OLD_JOYSTICK0_EMU_TYPE2), &dwJoyType)) // GH#434
- JoySetJoyType(JN_JOYSTICK0, dwJoyType);
- else
- LoadConfigOldJoystick_v1(JN_JOYSTICK0);
-
- if (REGLOAD(TEXT(REGVALUE_JOYSTICK1_EMU_TYPE), &dwJoyType))
- JoySetJoyType(JN_JOYSTICK1, dwJoyType);
- else if (REGLOAD(TEXT(REGVALUE_OLD_JOYSTICK1_EMU_TYPE2), &dwJoyType)) // GH#434
- JoySetJoyType(JN_JOYSTICK1, dwJoyType);
- else
- LoadConfigOldJoystick_v1(JN_JOYSTICK1);
-
- DWORD dwSoundType;
- REGLOAD_DEFAULT(TEXT(REGVALUE_SOUND_EMULATION), &dwSoundType, REG_SOUNDTYPE_WAVE);
- switch (dwSoundType)
- {
- case REG_SOUNDTYPE_NONE:
- case REG_SOUNDTYPE_DIRECT: // Not supported from 1.26
- case REG_SOUNDTYPE_SMART: // Not supported from 1.26
- default:
- soundtype = SOUND_NONE;
- break;
- case REG_SOUNDTYPE_WAVE:
- soundtype = SOUND_WAVE;
- break;
- }
-
- TCHAR serialPortName[CSuperSerialCard::SIZEOF_SERIALCHOICE_ITEM];
- if (RegLoadString(
- TEXT(REG_CONFIG),
- TEXT(REGVALUE_SERIAL_PORT_NAME),
- TRUE,
- serialPortName,
- CSuperSerialCard::SIZEOF_SERIALCHOICE_ITEM))
- {
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->SetSerialPortName(serialPortName);
- }
-
- REGLOAD_DEFAULT(TEXT(REGVALUE_EMULATION_SPEED), &g_dwSpeed, SPEED_NORMAL);
- Config_Load_Video();
- SetCurrentCLK6502(); // Pre: g_dwSpeed && Config_Load_Video()->SetVideoRefreshRate()
-
- DWORD dwEnhanceDisk;
- REGLOAD_DEFAULT(TEXT(REGVALUE_ENHANCE_DISK_SPEED), &dwEnhanceDisk, 1);
- GetCardMgr().GetDisk2CardMgr().SetEnhanceDisk(dwEnhanceDisk ? true : false);
-
- //
-
- DWORD dwTmp = 0;
-
- if(REGLOAD(TEXT(REGVALUE_FS_SHOW_SUBUNIT_STATUS), &dwTmp))
- SetFullScreenShowSubunitStatus(dwTmp ? true : false);
-
- if(REGLOAD(TEXT(REGVALUE_THE_FREEZES_F8_ROM), &dwTmp))
- sg_PropertySheet.SetTheFreezesF8Rom(dwTmp);
-
- if(REGLOAD(TEXT(REGVALUE_SPKR_VOLUME), &dwTmp))
- SpkrSetVolume(dwTmp, sg_PropertySheet.GetVolumeMax());
-
- if(REGLOAD(TEXT(REGVALUE_MB_VOLUME), &dwTmp))
- MB_SetVolume(dwTmp, sg_PropertySheet.GetVolumeMax());
-
- if(REGLOAD(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), &dwTmp))
- g_bSaveStateOnExit = dwTmp ? true : false;
-
-
- if(REGLOAD(TEXT(REGVALUE_DUMP_TO_PRINTER), &dwTmp))
- g_bDumpToPrinter = dwTmp ? true : false;
-
- if(REGLOAD(TEXT(REGVALUE_CONVERT_ENCODING), &dwTmp))
- g_bConvertEncoding = dwTmp ? true : false;
-
- if(REGLOAD(TEXT(REGVALUE_FILTER_UNPRINTABLE), &dwTmp))
- g_bFilterUnprintable = dwTmp ? true : false;
-
- if(REGLOAD(TEXT(REGVALUE_PRINTER_APPEND), &dwTmp))
- g_bPrinterAppend = dwTmp ? true : false;
-
-
- if(REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp)) // TODO: Change to REGVALUE_SLOT7
- HD_SetEnabled(dwTmp ? true : false);
-
- if(REGLOAD(TEXT(REGVALUE_PDL_XTRIM), &dwTmp))
- JoySetTrim((short)dwTmp, true);
- if(REGLOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp))
- JoySetTrim((short)dwTmp, false);
-
- if(REGLOAD(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), &dwTmp))
- sg_PropertySheet.SetScrollLockToggle(dwTmp);
-
- if(REGLOAD(TEXT(REGVALUE_CURSOR_CONTROL), &dwTmp))
- sg_PropertySheet.SetJoystickCursorControl(dwTmp);
- if(REGLOAD(TEXT(REGVALUE_AUTOFIRE), &dwTmp))
- sg_PropertySheet.SetAutofire(dwTmp);
- if(REGLOAD(TEXT(REGVALUE_SWAP_BUTTONS_0_AND_1), &dwTmp))
- sg_PropertySheet.SetButtonsSwapState(dwTmp ? true : false);
- if(REGLOAD(TEXT(REGVALUE_CENTERING_CONTROL), &dwTmp))
- sg_PropertySheet.SetJoystickCenteringControl(dwTmp);
-
- if(REGLOAD(TEXT(REGVALUE_MOUSE_CROSSHAIR), &dwTmp))
- sg_PropertySheet.SetMouseShowCrosshair(dwTmp);
- if(REGLOAD(TEXT(REGVALUE_MOUSE_RESTRICT_TO_WINDOW), &dwTmp))
- sg_PropertySheet.SetMouseRestrictToWindow(dwTmp);
-
- if(REGLOAD(TEXT(REGVALUE_SLOT4), &dwTmp))
- GetCardMgr().Insert(4, (SS_CARDTYPE)dwTmp);
- if(REGLOAD(TEXT(REGVALUE_SLOT5), &dwTmp))
- GetCardMgr().Insert(5, (SS_CARDTYPE)dwTmp);
-
- //
-
- TCHAR szFilename[MAX_PATH];
-
- // Load save-state pathname *before* inserting any harddisk/disk images (for both init & reinit cases)
- // NB. inserting harddisk/disk can change snapshot pathname
- RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_SAVESTATE_FILENAME), 1, szFilename, MAX_PATH, TEXT("")); // Can be pathname or just filename
- Snapshot_SetFilename(szFilename); // If not in Registry than default will be used (ie. g_sCurrentDir + default filename)
-
- //
-
- RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, szFilename, MAX_PATH, TEXT(""));
- 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 their disk images
- RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_START_DIR), 1, szFilename, MAX_PATH, TEXT(""));
- if (szFilename[0] == '\0')
- GetCurrentDirectory(sizeof(szFilename), szFilename);
- SetCurrentImageDir(szFilename);
-
- GetCardMgr().GetDisk2CardMgr().LoadLastDiskImage();
-
- //
-
- DWORD dwTfeEnabled;
- REGLOAD_DEFAULT(TEXT(REGVALUE_UTHERNET_ACTIVE), &dwTfeEnabled, 0);
- tfe_enabled = dwTfeEnabled ? 1 : 0;
-
- RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_UTHERNET_INTERFACE), 1, szFilename, MAX_PATH, TEXT(""));
- update_tfe_interface(szFilename, NULL);
-
- //
-
- RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_PRINTER_FILENAME), 1, szFilename, MAX_PATH, TEXT(""));
- Printer_SetFilename(szFilename); // If not in Registry than default will be used
-
- REGLOAD_DEFAULT(TEXT(REGVALUE_PRINTER_IDLE_LIMIT), &dwTmp, 10);
- Printer_SetIdleLimit(dwTmp);
-
- if (REGLOAD(TEXT(REGVALUE_WINDOW_SCALE), &dwTmp))
- SetViewportScale(dwTmp);
-
- if (REGLOAD(TEXT(REGVALUE_CONFIRM_REBOOT), &dwTmp))
- g_bConfirmReboot = dwTmp;
-}
-
-//===========================================================================
-
-bool SetCurrentImageDir(const std::string & pszImageDir)
-{
- g_sCurrentDir = pszImageDir;
-
- if (!g_sCurrentDir.empty() && *g_sCurrentDir.rbegin() != '\\')
- g_sCurrentDir += '\\';
-
- if( SetCurrentDirectory(g_sCurrentDir.c_str()) )
- return true;
-
- return false;
-}
-
-//===========================================================================
-
-// TODO: Added dialog option of which file extensions to registry
-static bool g_bRegisterFileTypes = true;
-
-
-void RegisterExtensions(void)
-{
- TCHAR szCommandTmp[MAX_PATH];
- GetModuleFileName((HMODULE)0,szCommandTmp,MAX_PATH);
-
- TCHAR command[MAX_PATH];
- wsprintf(command, "\"%s\"", szCommandTmp); // Wrap path & filename in quotes & null terminate
-
- TCHAR icon[MAX_PATH];
- wsprintf(icon,TEXT("%s,1"),(LPCTSTR)command);
-
- _tcscat(command,TEXT(" \"%1\"")); // Append "%1"
-// _tcscat(command,TEXT("-d1 %1\"")); // Append "%1"
-// sprintf(command, "\"%s\" \"-d1 %%1\"", szCommandTmp); // Wrap path & filename in quotes & null terminate
-
- // NB. Registry access to HKLM typically results in ErrorCode 5(ACCESS DENIED), as UAC requires elevated permissions (Run as administrator).
- // . HKEY_CLASSES_ROOT\CLSID is a merged view of HKLM\SOFTWARE\Classes and HKCU\SOFTWARE\Classes
-
- // NB. Reflect extensions in DELREG.INF
-// RegSetValue(HKEY_CLASSES_ROOT,".bin",REG_SZ,"DiskImage",0); // Removed as .bin is too generic
-
- const char* pValueName = ".bin";
- LSTATUS res = RegDeleteValue(HKEY_CLASSES_ROOT, pValueName);
- if (res != NOERROR && res != ERROR_FILE_NOT_FOUND) LogFileOutput("RegDeleteValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = ".do";
- res = RegSetValue(HKEY_CLASSES_ROOT, pValueName ,REG_SZ,"DiskImage",0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = ".dsk";
- res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = ".nib";
- res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = ".po";
- res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = ".woz";
- res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
-// RegSetValue(HKEY_CLASSES_ROOT,".2mg",REG_SZ,"DiskImage",0); // Don't grab this, as not all .2mg images are supported (so defer to CiderPress)
-// RegSetValue(HKEY_CLASSES_ROOT,".2img",REG_SZ,"DiskImage",0); // Don't grab this, as not all .2mg images are supported (so defer to CiderPress)
-// RegSetValue(HKEY_CLASSES_ROOT,".aws.yaml",REG_SZ,"DiskImage",0); // NB. Can't grab this extension (even though it returns 0!) with embedded period (and .yaml is too generic) - GH#548
-// RegSetValue(HKEY_CLASSES_ROOT,".hdv",REG_SZ,"DiskImage",0); // TO DO
-
- pValueName = "DiskImage";
- res = RegSetValue(HKEY_CLASSES_ROOT,
- pValueName,
- REG_SZ,"Disk Image",0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = "DiskImage\\DefaultIcon";
- res = RegSetValue(HKEY_CLASSES_ROOT,
- pValueName,
- REG_SZ,icon,0);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
-// This key can interfere....
-// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExt\.dsk
-
- pValueName = "DiskImage\\shell\\open\\command";
- res = RegSetValue(HKEY_CLASSES_ROOT,
- pValueName,
- REG_SZ,command,_tcslen(command)+1);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = "DiskImage\\shell\\open\\ddeexec";
- res = RegSetValue(HKEY_CLASSES_ROOT,
- pValueName,
- REG_SZ,"%1",3);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = "DiskImage\\shell\\open\\ddeexec\\application";
- res = RegSetValue(HKEY_CLASSES_ROOT,
- pValueName,
- REG_SZ,"applewin",_tcslen("applewin")+1);
-// REG_SZ,szCommandTmp,_tcslen(szCommandTmp)+1);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-
- pValueName = "DiskImage\\shell\\open\\ddeexec\\topic";
- res = RegSetValue(HKEY_CLASSES_ROOT,
- pValueName,
- REG_SZ,"system",_tcslen("system")+1);
- if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
-}
-
-//===========================================================================
-
-// NB. On a restart, it's OK to call RegisterHotKey() again since the old g_hFrameWindow has been destroyed
-static void RegisterHotKeys(void)
-{
- BOOL bStatus[3] = {0,0,0};
-
- bStatus[0] = RegisterHotKey(
- g_hFrameWindow , // HWND hWnd
- VK_SNAPSHOT_560, // int id (user/custom id)
- 0 , // UINT fsModifiers
- VK_SNAPSHOT // UINT vk = PrintScreen
- );
-
- bStatus[1] = RegisterHotKey(
- g_hFrameWindow , // HWND hWnd
- VK_SNAPSHOT_280, // int id (user/custom id)
- MOD_SHIFT , // UINT fsModifiers
- VK_SNAPSHOT // UINT vk = PrintScreen
- );
-
- bStatus[2] = RegisterHotKey(
- g_hFrameWindow , // HWND hWnd
- VK_SNAPSHOT_TEXT, // int id (user/custom id)
- MOD_CONTROL , // UINT fsModifiers
- VK_SNAPSHOT // UINT vk = PrintScreen
- );
-
- if ((!bStatus[0] || !bStatus[1] || !bStatus[2]))
- {
- std::string msg("Unable to register for PrintScreen key(s):\n");
-
- if (!bStatus[0])
- msg += "\n. PrintScreen";
- if (!bStatus[1])
- msg += "\n. Shift+PrintScreen";
- if (!bStatus[2])
- msg += "\n. Ctrl+PrintScreen";
-
- if (g_bShowPrintScreenWarningDialog)
- MessageBox( g_hFrameWindow, msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK );
-
- msg += "\n";
- LogFileOutput(msg.c_str());
- }
-}
-
-//---------------------------------------------------------------------------
-
-static HINSTANCE g_hinstDLL = 0;
-static HHOOK g_hhook = 0;
-
-static HANDLE g_hHookThread = NULL;
-static DWORD g_HookThreadId = 0;
-
-// Pre: g_hFrameWindow must be valid
-static bool HookFilterForKeyboard()
-{
- g_hinstDLL = LoadLibrary(TEXT("HookFilter.dll"));
-
- _ASSERT(g_hFrameWindow);
-
- typedef void (*RegisterHWNDProc)(HWND, bool, bool);
- RegisterHWNDProc RegisterHWND = (RegisterHWNDProc) GetProcAddress(g_hinstDLL, "RegisterHWND");
- if (RegisterHWND)
- RegisterHWND(g_hFrameWindow, g_bHookAltTab, g_bHookAltGrControl);
-
- HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc");
-
- g_hhook = SetWindowsHookEx(
- WH_KEYBOARD_LL,
- hkprcLowLevelKeyboardProc,
- g_hinstDLL,
- 0);
-
- if (g_hhook != 0 && g_hFrameWindow != 0)
- return true;
-
- std::string msg("Failed to install hook filter for system keys");
-
- DWORD dwErr = GetLastError();
- MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
-
- msg += "\n";
- LogFileOutput(msg.c_str());
- return false;
-}
-
-static void UnhookFilterForKeyboard()
-{
- UnhookWindowsHookEx(g_hhook);
- FreeLibrary(g_hinstDLL);
-}
-
-static DWORD WINAPI HookThread(LPVOID lpParameter)
-{
- if (!HookFilterForKeyboard())
- return -1;
-
- MSG msg;
- while(GetMessage(&msg, NULL, 0, 0) > 0)
- {
- if (msg.message == WM_QUIT)
- break;
-
- TranslateMessage(&msg);
- DispatchMessage(&msg);
- }
-
- UnhookFilterForKeyboard();
- return 0;
-}
-
-static bool InitHookThread()
-{
- g_hHookThread = CreateThread(NULL, // lpThreadAttributes
- 0, // dwStackSize
- (LPTHREAD_START_ROUTINE) HookThread,
- 0, // lpParameter
- 0, // dwCreationFlags : 0 = Run immediately
- &g_HookThreadId); // lpThreadId
- if (g_hHookThread == NULL)
- return false;
-
- return true;
-}
-
-static void UninitHookThread()
-{
- if (g_hHookThread)
- {
- if (!PostThreadMessage(g_HookThreadId, WM_QUIT, 0, 0))
- {
- _ASSERT(0);
- return;
- }
-
- do
- {
- DWORD dwExitCode;
- if (GetExitCodeThread(g_hHookThread, &dwExitCode))
- {
- if(dwExitCode == STILL_ACTIVE)
- Sleep(10);
- else
- break;
- }
- }
- while(1);
-
- CloseHandle(g_hHookThread);
- g_hHookThread = NULL;
- g_HookThreadId = 0;
- }
-}
-
-//===========================================================================
-
-LPSTR GetCurrArg(LPSTR lpCmdLine)
-{
- if(*lpCmdLine == '\"')
- lpCmdLine++;
-
- return lpCmdLine;
-}
-
-LPSTR GetNextArg(LPSTR lpCmdLine)
-{
- int bInQuotes = 0;
-
- while(*lpCmdLine)
- {
- if(*lpCmdLine == '\"')
- {
- bInQuotes ^= 1;
- if(!bInQuotes)
- {
- *lpCmdLine++ = 0x00; // Assume end-quote is end of this arg
- continue;
- }
- }
-
- if((*lpCmdLine == ' ') && !bInQuotes)
- {
- *lpCmdLine++ = 0x00;
- break;
- }
-
- lpCmdLine++;
- }
-
- return lpCmdLine;
-}
-
-//---------------------------------------------------------------------------
-
-static std::string GetFullPath(LPCSTR szFileName)
-{
- std::string strPathName;
-
- if (szFileName[0] == '\\' || szFileName[1] == ':')
- {
- // Abs pathname
- strPathName = szFileName;
- }
- else
- {
- // Rel pathname (GH#663)
- strPathName = g_sStartDir;
- strPathName.append(szFileName);
- }
-
- return strPathName;
-}
-
-static void SetCurrentDir(std::string pathname)
-{
- // Due to the order HDDs/disks are inserted, then s7 insertions take priority over s6 & s5; and d2 takes priority over d1:
- // . if -s6[dN] and -hN are specified, then g_sCurrentDir will be set to the HDD image's path
- // . if -s5[dN] and -s6[dN] are specified, then g_sCurrentDir will be set to the s6 image's path
- // . if -[sN]d1 and -[sN]d2 are specified, then g_sCurrentDir will be set to the d2 image's path
- // This is purely dependent on the current order of InsertFloppyDisks() & InsertHardDisks() - ie. very brittle!
- // . better to use -current-dir to be explicit
- std::size_t found = pathname.find_last_of("\\");
- std::string path = pathname.substr(0, found);
- SetCurrentImageDir(path);
-}
-
-static bool DoDiskInsert(const UINT slot, const int nDrive, LPCSTR szFileName)
-{
- Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(slot));
-
- if (szFileName[0] == '\0')
- {
- disk2Card.EjectDisk(nDrive);
- return true;
- }
-
- std::string strPathName = GetFullPath(szFileName);
- if (strPathName.empty()) return false;
-
- ImageError_e Error = disk2Card.InsertDisk(nDrive, strPathName.c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
- bool res = (Error == eIMAGE_ERROR_NONE);
- if (res)
- SetCurrentDir(strPathName);
- return res;
-}
-
-static bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName)
-{
- if (szFileName[0] == '\0')
- {
- HD_Unplug(nDrive);
- return true;
- }
-
- std::string strPathName = GetFullPath(szFileName);
- if (strPathName.empty()) return false;
-
- BOOL bRes = HD_Insert(nDrive, strPathName.c_str());
- bool res = (bRes == TRUE);
- if (res)
- SetCurrentDir(strPathName);
- return res;
-}
-
-static void InsertFloppyDisks(const UINT slot, LPSTR szImageName_drive[NUM_DRIVES], bool& bBoot)
-{
- _ASSERT(slot == 5 || slot == 6);
-
- if (!szImageName_drive[DRIVE_1] && !szImageName_drive[DRIVE_2])
- return;
-
- bool bRes = true;
-
- if (szImageName_drive[DRIVE_1])
- {
- bRes = DoDiskInsert(slot, DRIVE_1, szImageName_drive[DRIVE_1]);
- LogFileOutput("Init: S%d, DoDiskInsert(D1), res=%d\n", slot, bRes);
- FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES); // floppy activity LEDs and floppy buttons
- bBoot = true;
- }
-
- if (szImageName_drive[DRIVE_2])
- {
- bRes |= DoDiskInsert(slot, DRIVE_2, szImageName_drive[DRIVE_2]);
- LogFileOutput("Init: S%d, DoDiskInsert(D2), res=%d\n", slot, bRes);
- }
-
- if (!bRes)
- MessageBox(g_hFrameWindow, "Failed to insert floppy disk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
-}
-
-static void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot)
-{
- if (!szImageName_harddisk[HARDDISK_1] && !szImageName_harddisk[HARDDISK_2])
- return;
-
- // Enable the Harddisk controller card
-
- HD_SetEnabled(true);
-
- DWORD dwTmp;
- BOOL res = REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp);
- if (!res || !dwTmp)
- REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 1); // Config: HDD Enabled
-
- //
-
- bool bRes = true;
-
- if (szImageName_harddisk[HARDDISK_1])
- {
- bRes = DoHardDiskInsert(HARDDISK_1, szImageName_harddisk[HARDDISK_1]);
- LogFileOutput("Init: DoHardDiskInsert(HDD1), res=%d\n", bRes);
- FrameRefreshStatus(DRAW_LEDS); // harddisk activity LED
- bBoot = true;
- }
-
- if (szImageName_harddisk[HARDDISK_2])
- {
- bRes |= DoHardDiskInsert(HARDDISK_2, szImageName_harddisk[HARDDISK_2]);
- LogFileOutput("Init: DoHardDiskInsert(HDD2), res=%d\n", bRes);
- }
-
- if (!bRes)
- MessageBox(g_hFrameWindow, "Failed to insert harddisk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
-}
-
-static void UnplugHardDiskControllerCard(void)
-{
- HD_SetEnabled(false);
-
- DWORD dwTmp;
- BOOL res = REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp);
- if (!res || dwTmp)
- REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 0); // Config: HDD Disabled
-}
-
-static bool CheckOldAppleWinVersion(void)
-{
- TCHAR szOldAppleWinVersion[VERSIONSTRING_SIZE + 1];
- RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, szOldAppleWinVersion, VERSIONSTRING_SIZE, TEXT(""));
- const bool bShowAboutDlg = strcmp(szOldAppleWinVersion, VERSIONSTRING) != 0;
-
- // version: xx.yy.zz.ww
- char* p0 = szOldAppleWinVersion;
- int len = strlen(szOldAppleWinVersion);
- szOldAppleWinVersion[len] = '.'; // append a null terminator
- szOldAppleWinVersion[len + 1] = '\0';
- for (UINT i=0; i<4; i++)
- {
- char* p1 = strstr(p0, ".");
- if (!p1)
- break;
- *p1 = 0;
- g_OldAppleWinVersion[i] = atoi(p0);
- p0 = p1+1;
- }
-
- return bShowAboutDlg;
-}
-
-//---------------------------------------------------------------------------
-
-static void ExceptionHandler(const char* pError)
-{
- MessageBox( g_hFrameWindow,
- pError,
- TEXT("Runtime Exception"),
- MB_ICONEXCLAMATION | MB_SETFOREGROUND);
-
- LogFileOutput("Runtime Exception: %s\n", pError);
-}
-
-//---------------------------------------------------------------------------
-
-static bool ProcessCmdLine(LPSTR lpCmdLine);
-static void GetAppleWinVersion(void);
-static void OneTimeInitialization(HINSTANCE passinstance);
-static void RepeatInitialization(void);
-static void Shutdown(void);
-
-struct CmdLine
-{
- CmdLine()
- {
- bShutdown = false;
- bSetFullScreen = false;
- bBoot = false;
- bChangedDisplayResolution = false;
- bSlot0LanguageCard = false;
- bSlot7EmptyOnExit = false;
- bSwapButtons0and1 = false;
- bRemoveNoSlotClock = false;
- bestWidth = 0;
- bestHeight = 0;
- szImageName_harddisk[HARDDISK_1] = NULL;
- szImageName_harddisk[HARDDISK_2] = NULL;
- szSnapshotName = NULL;
- szScreenshotFilename = NULL;
- uRamWorksExPages = 0;
- uSaturnBanks = 0;
- newVideoType = -1;
- newVideoStyleEnableMask = 0;
- newVideoStyleDisableMask = 0;
- newVideoRefreshRate = VR_NONE;
- clockMultiplier = 0.0; // 0 => not set from cmd-line
- model = A2TYPE_MAX;
- rgbCard = RGB_Videocard_e::Apple;
- rgbCardForegroundColor = 15;
- rgbCardBackgroundColor = 0;
-
- for (UINT i = 0; i < NUM_SLOTS; i++)
- {
- bSlotEmpty[i] = false;
- slotInsert[i] = CT_Empty;
- szImageName_drive[i][DRIVE_1] = NULL;
- szImageName_drive[i][DRIVE_2] = NULL;
- }
- }
-
- bool bShutdown;
- bool bSetFullScreen;
- bool bBoot;
- bool bChangedDisplayResolution;
- bool bSlot0LanguageCard;
- bool bSlotEmpty[NUM_SLOTS];
- bool bSlot7EmptyOnExit;
- bool bSwapButtons0and1;
- bool bRemoveNoSlotClock;
- SS_CARDTYPE slotInsert[NUM_SLOTS];
- UINT bestWidth;
- UINT bestHeight;
- LPSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES];
- LPSTR szImageName_harddisk[NUM_HARDDISKS];
- LPSTR szSnapshotName;
- LPSTR szScreenshotFilename;
- UINT uRamWorksExPages;
- UINT uSaturnBanks;
- int newVideoType;
- int newVideoStyleEnableMask;
- int newVideoStyleDisableMask;
- VideoRefreshRate_e newVideoRefreshRate;
- double clockMultiplier;
- eApple2Type model;
- RGB_Videocard_e rgbCard;
- int rgbCardForegroundColor;
- int rgbCardBackgroundColor;
- std::string strCurrentDir;
-};
-
-static CmdLine g_cmdLine;
-
-int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
-{
- char startDir[_MAX_PATH];
- GetCurrentDirectory(sizeof(startDir), startDir);
- g_sStartDir = startDir;
- if (*(g_sStartDir.end()-1) != '\\') g_sStartDir += '\\';
-
- if (!ProcessCmdLine(lpCmdLine))
- return 0;
-
- LogFileOutput("g_sStartDir = %s\n", g_sStartDir.c_str());
- GetAppleWinVersion();
- OneTimeInitialization(passinstance);
-
- try
- {
- do
- {
- g_bRestart = false;
-
- RepeatInitialization();
-
- // ENTER THE MAIN MESSAGE LOOP
- LogFileOutput("Main: EnterMessageLoop()\n");
- EnterMessageLoop();
- LogFileOutput("Main: LeaveMessageLoop()\n");
-
- if (g_bRestart)
- {
- g_cmdLine.bSetFullScreen = g_bRestartFullScreen;
- g_bRestartFullScreen = false;
- }
-
- MB_Reset();
- LogFileOutput("Main: MB_Reset()\n");
-
- CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard();
- if (pMouseCard)
- {
- pMouseCard->Reset(); // Deassert any pending IRQs - GH#514
- LogFileOutput("Main: CMouseInterface::Uninitialize()\n");
- }
-
- DSUninit();
- LogFileOutput("Main: DSUninit()\n");
-
- if (g_bRestart)
- g_SynchronousEventMgr.Reset();
-
- if (g_bHookSystemKey)
- {
- UninitHookThread();
- LogFileOutput("Main: UnhookFilterForKeyboard()\n");
- }
- }
- while (g_bRestart);
- }
- catch(std::runtime_error exception)
- {
- ExceptionHandler(exception.what());
- }
- catch(std::exception exception)
- {
- ExceptionHandler(exception.what());
- }
-
- Shutdown();
- return 0;
-}
-
-static bool ProcessCmdLine(LPSTR lpCmdLine)
-{
- const std::string strCmdLine(lpCmdLine); // Keep a copy for log ouput
- std::string strUnsupported;
-
- // If 1st param looks like an abs pathname then assume that an associated filetype has been double-clicked
- // NB. Handled by WM_DDE_INITIATE & WM_DDE_EXECUTE msgs
- if ((lpCmdLine[0] >= '\"' && lpCmdLine[1] >= 'A' && lpCmdLine[1] <= 'Z' && lpCmdLine[2] == ':') // always in quotes
- || strncmp("\\\\?\\", lpCmdLine, 4) == 0)
- return true;
-
- while (*lpCmdLine)
- {
- LPSTR lpNextArg = GetNextArg(lpCmdLine);
-
- if (((strcmp(lpCmdLine, "-l") == 0) || (strcmp(lpCmdLine, "-log") == 0)) && (g_fh == NULL))
- {
- LogInit();
- }
- else if (strcmp(lpCmdLine, "-noreg") == 0)
- {
- g_bRegisterFileTypes = false;
- }
- else if (strcmp(lpCmdLine, "-conf") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- char buf[MAX_PATH];
- DWORD res = GetFullPathName(lpCmdLine, MAX_PATH, buf, NULL);
- if (res == 0)
- LogFileOutput("Failed to open configuration file: %s\n", lpCmdLine);
- else
- g_sConfigFile = buf;
- }
- else if (strcmp(lpCmdLine, "-d1") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.szImageName_drive[SLOT6][DRIVE_1] = lpCmdLine;
- }
- else if (strcmp(lpCmdLine, "-d2") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.szImageName_drive[SLOT6][DRIVE_2] = lpCmdLine;
- }
- else if (strcmp(lpCmdLine, "-h1") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.szImageName_harddisk[HARDDISK_1] = lpCmdLine;
- }
- else if (strcmp(lpCmdLine, "-h2") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.szImageName_harddisk[HARDDISK_2] = lpCmdLine;
- }
- else if (lpCmdLine[0] == '-' && lpCmdLine[1] == 's' && lpCmdLine[2] >= '1' && lpCmdLine[2] <= '7')
- {
- const UINT slot = lpCmdLine[2] - '0';
-
- if (lpCmdLine[3] == 0) // -s[1..7]
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- if (strcmp(lpCmdLine, "empty") == 0)
- g_cmdLine.bSlotEmpty[slot] = true;
- if (strcmp(lpCmdLine, "diskii") == 0)
- g_cmdLine.slotInsert[slot] = CT_Disk2;
- }
- else if (lpCmdLine[3] == 'd' && (lpCmdLine[4] == '1' || lpCmdLine[4] == '2')) // -s[1..7]d[1|2]
- {
- const UINT drive = lpCmdLine[4] == '1' ? DRIVE_1 : DRIVE_2;
-
- if (slot != 5 && slot != 6)
- {
- LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
- }
- else
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.szImageName_drive[slot][drive] = lpCmdLine;
- }
- }
- else if (strcmp(lpCmdLine, "-s7-empty-on-exit") == 0)
- {
- g_cmdLine.bSlot7EmptyOnExit = true;
- }
- else
- {
- LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
- }
- }
- else if (strcmp(lpCmdLine, "-load-state") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.szSnapshotName = lpCmdLine;
- }
- else if (strcmp(lpCmdLine, "-f") == 0)
- {
- g_cmdLine.bSetFullScreen = true;
- }
-#define CMD_FS_HEIGHT "-fs-height="
- else if (strncmp(lpCmdLine, CMD_FS_HEIGHT, sizeof(CMD_FS_HEIGHT)-1) == 0)
- {
- g_cmdLine.bSetFullScreen = true; // Implied
-
- LPSTR lpTmp = lpCmdLine + sizeof(CMD_FS_HEIGHT)-1;
- bool bRes = false;
- if (strcmp(lpTmp, "best") == 0)
- {
- bRes = GetBestDisplayResolutionForFullScreen(g_cmdLine.bestWidth, g_cmdLine.bestHeight);
- }
- else
- {
- UINT userSpecifiedHeight = atoi(lpTmp);
- if (userSpecifiedHeight)
- bRes = GetBestDisplayResolutionForFullScreen(g_cmdLine.bestWidth, g_cmdLine.bestHeight, userSpecifiedHeight);
- else
- LogFileOutput("Invalid cmd-line parameter for -fs-height=x switch\n");
- }
- if (bRes)
- LogFileOutput("Best resolution for -fs-height=x switch: Width=%d, Height=%d\n", g_cmdLine.bestWidth, g_cmdLine.bestHeight);
- else
- LogFileOutput("Failed to set parameter for -fs-height=x switch\n");
- }
- else if (strcmp(lpCmdLine, "-no-di") == 0)
- {
- g_bDisableDirectInput = true;
- }
- else if (strcmp(lpCmdLine, "-m") == 0)
- {
- g_bDisableDirectSound = true;
- }
- else if (strcmp(lpCmdLine, "-no-mb") == 0)
- {
- g_bDisableDirectSoundMockingboard = true;
- }
- else if (strcmp(lpCmdLine, "-memclear") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_nMemoryClearType = atoi(lpCmdLine);
- if (g_nMemoryClearType < 0)
- g_nMemoryClearType = 0;
- else
- if (g_nMemoryClearType >= NUM_MIP)
- g_nMemoryClearType = NUM_MIP - 1;
- }
-#ifdef RAMWORKS
- else if (strcmp(lpCmdLine, "-r") == 0) // RamWorks size [1..127]
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.uRamWorksExPages = atoi(lpCmdLine);
- if (g_cmdLine.uRamWorksExPages > kMaxExMemoryBanks)
- g_cmdLine.uRamWorksExPages = kMaxExMemoryBanks;
- else
- if (g_cmdLine.uRamWorksExPages < 1)
- g_cmdLine.uRamWorksExPages = 1;
- }
-#endif
- else if (strcmp(lpCmdLine, "-s0") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
-
- if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0)
- g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks;
- else if (strcmp(lpCmdLine, "saturn64") == 0)
- g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks/2;
- else if (strcmp(lpCmdLine, "languagecard") == 0 || strcmp(lpCmdLine, "lc") == 0)
- g_cmdLine.bSlot0LanguageCard = true;
- }
- else if (strcmp(lpCmdLine, "-f8rom") == 0) // Use custom 2K ROM at [$F800..$FFFF]
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
-
- if (g_hCustomRomF8 != INVALID_HANDLE_VALUE) // Stop resource leak if -f8rom is specified twice!
- CloseHandle(g_hCustomRomF8);
-
- g_hCustomRomF8 = CreateFile(lpCmdLine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
- g_bCustomRomF8Failed = true;
- }
- else if (strcmp(lpCmdLine, "-rom") == 0) // Use custom 16K at [$C000..$FFFF] or 12K ROM at [$D000..$FFFF]
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
-
- if (g_hCustomRom != INVALID_HANDLE_VALUE) // Stop resource leak if -rom is specified twice!
- CloseHandle(g_hCustomRom);
-
- g_hCustomRom = CreateFile(lpCmdLine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
- if ((g_hCustomRom == INVALID_HANDLE_VALUE) || ((GetFileSize(g_hCustomRom, NULL) != 0x4000) && (GetFileSize(g_hCustomRom, NULL) != 0x3000)))
- g_bCustomRomFailed = true;
- }
- else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 2K (for II/II+). Use 4K,8K or 16K video ROM (for Enhanced //e)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
-
- if (!ReadVideoRomFile(lpCmdLine))
- {
- std::string msg = "Failed to load video rom (not found or not exactly 2/4/8/16KiB)\n";
- LogFileOutput("%s", msg.c_str());
- MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
- }
- else
- {
- SetVideoRomRockerSwitch(true); // Use PAL char set
- }
- }
- else if (strcmp(lpCmdLine, "-printscreen") == 0) // Turn on display of the last filename print screen was saved to
- {
- g_bDisplayPrintScreenFileName = true;
- }
- else if (strcmp(lpCmdLine, "-no-printscreen-key") == 0) // Don't try to capture PrintScreen key GH#469
- {
- g_bCapturePrintScreenKey = false;
- }
- else if (strcmp(lpCmdLine, "-no-printscreen-dlg") == 0) // Turn off the PrintScreen warning message dialog (if PrintScreen key can't be grabbed)
- {
- g_bShowPrintScreenWarningDialog = false;
- }
- else if (strcmp(lpCmdLine, "-no-hook-system-key") == 0) // Don't hook the System keys (eg. Left-ALT+ESC/SPACE/TAB) GH#556
- {
- g_bHookSystemKey = false;
- }
- else if (strcmp(lpCmdLine, "-hook-alt-tab") == 0) // GH#556
- {
- g_bHookAltTab = true;
- }
- else if (strcmp(lpCmdLine, "-hook-altgr-control") == 0) // GH#556
- {
- g_bHookAltGrControl = true;
- }
- else if (strcmp(lpCmdLine, "-altgr-sends-wmchar") == 0) // GH#625
- {
- KeybSetAltGrSendsWM_CHAR(true);
- }
- else if (strcmp(lpCmdLine, "-no-hook-alt") == 0) // GH#583
- {
- JoySetHookAltKeys(false);
- }
- else if (strcmp(lpCmdLine, "-left-alt-control-buttons") == 0) // GH#743
- {
- JoySetButtonVirtualKey(0, VK_CONTROL);
- JoySetButtonVirtualKey(1, VK_MENU);
- }
- else if (strcmp(lpCmdLine, "-right-alt-control-buttons") == 0) // GH#743
- {
- JoySetButtonVirtualKey(0, VK_MENU | KF_EXTENDED);
- JoySetButtonVirtualKey(1, VK_CONTROL | KF_EXTENDED);
- }
- else if (strcmp(lpCmdLine, "-swap-buttons") == 0)
- {
- g_cmdLine.bSwapButtons0and1 = true;
- }
- else if (strcmp(lpCmdLine, "-spkr-inc") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- const int nErrorInc = atoi(lpCmdLine);
- SoundCore_SetErrorInc( nErrorInc );
- }
- else if (strcmp(lpCmdLine, "-spkr-max") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- const int nErrorMax = atoi(lpCmdLine);
- SoundCore_SetErrorMax( nErrorMax );
- }
- else if (strcmp(lpCmdLine, "-use-real-printer") == 0) // Enable control in Advanced config to allow dumping to a real printer
- {
- g_bEnableDumpToRealPrinter = true;
- }
- else if (strcmp(lpCmdLine, "-speech") == 0)
- {
- g_bEnableSpeech = true;
- }
- else if (strcmp(lpCmdLine, "-multimon") == 0)
- {
- g_bMultiMon = true;
- }
- else if ((strcmp(lpCmdLine, "-dcd") == 0) || (strcmp(lpCmdLine, "-modem") == 0)) // GH#386
- {
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->SupportDCD(true);
- }
- else if (strcmp(lpCmdLine, "-alt-enter=toggle-full-screen") == 0) // GH#556
- {
- SetAltEnterToggleFullScreen(true);
- }
- else if (strcmp(lpCmdLine, "-alt-enter=open-apple-enter") == 0) // GH#556
- {
- SetAltEnterToggleFullScreen(false);
- }
- else if (strcmp(lpCmdLine, "-video-mode=idealized") == 0) // GH#616
- {
- g_cmdLine.newVideoType = VT_COLOR_IDEALIZED;
- }
- else if (strcmp(lpCmdLine, "-video-mode=rgb-videocard") == 0)
- {
- g_cmdLine.newVideoType = VT_COLOR_VIDEOCARD_RGB;
- }
- else if (strcmp(lpCmdLine, "-video-mode=composite-monitor") == 0) // GH#763
- {
- g_cmdLine.newVideoType = VT_COLOR_MONITOR_NTSC;
- }
- else if (strcmp(lpCmdLine, "-video-style=vertical-blend") == 0) // GH#616
- {
- g_cmdLine.newVideoStyleEnableMask = VS_COLOR_VERTICAL_BLEND;
- }
- else if (strcmp(lpCmdLine, "-video-style=no-vertical-blend") == 0) // GH#616
- {
- g_cmdLine.newVideoStyleDisableMask = VS_COLOR_VERTICAL_BLEND;
- }
- else if (strcmp(lpCmdLine, "-rgb-card-invert-bit7") == 0) // GH#633
- {
- RGB_SetInvertBit7(true);
- }
- else if (strcmp(lpCmdLine, "-screenshot-and-exit") == 0) // GH#616: For testing - Use in combination with -load-state
- {
- g_cmdLine.szScreenshotFilename = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- }
- else if (strcmp(lpCmdLine, "-clock-multiplier") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.clockMultiplier = atof(lpCmdLine);
- }
- else if (strcmp(lpCmdLine, "-model") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
-
- if (strcmp(lpCmdLine, "apple2") == 0)
- g_cmdLine.model = A2TYPE_APPLE2;
- else if (strcmp(lpCmdLine, "apple2p") == 0)
- g_cmdLine.model = A2TYPE_APPLE2PLUS;
- else if (strcmp(lpCmdLine, "apple2jp") == 0)
- g_cmdLine.model = A2TYPE_APPLE2JPLUS;
- else if (strcmp(lpCmdLine, "apple2e") == 0)
- g_cmdLine.model = A2TYPE_APPLE2E;
- else if (strcmp(lpCmdLine, "apple2ee") == 0)
- g_cmdLine.model = A2TYPE_APPLE2EENHANCED;
- else
- LogFileOutput("-model: unsupported type: %s\n", lpCmdLine);
- }
- else if (_stricmp(lpCmdLine, "-50hz") == 0) // (case-insensitive)
- {
- g_cmdLine.newVideoRefreshRate = VR_50HZ;
- }
- else if (_stricmp(lpCmdLine, "-60hz") == 0) // (case-insensitive)
- {
- g_cmdLine.newVideoRefreshRate = VR_60HZ;
- }
- else if (strcmp(lpCmdLine, "-rgb-card-type") == 0)
- {
- // RGB video card valid types are: "apple", "sl7", "eve", "feline"
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
-
- if (strcmp(lpCmdLine, "apple") == 0) // Just an alias for SL7
- g_cmdLine.rgbCard = RGB_Videocard_e::Apple;
- else if (strcmp(lpCmdLine, "sl7") == 0)
- g_cmdLine.rgbCard = RGB_Videocard_e::Video7_SL7;
- else if (strcmp(lpCmdLine, "eve") == 0)
- g_cmdLine.rgbCard = RGB_Videocard_e::LeChatMauve_EVE;
- else if (strcmp(lpCmdLine, "feline") == 0)
- g_cmdLine.rgbCard = RGB_Videocard_e::LeChatMauve_Feline;
- else
- LogFileOutput("-rgb-card-type: unsupported type: %s\n", lpCmdLine);
- }
- else if (strcmp(lpCmdLine, "-rgb-card-foreground") == 0)
- {
- // Default hardware-defined Text foreground color, for Video-7's RGB-SL7 card only
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.rgbCardForegroundColor = atoi(lpCmdLine);
- }
- else if (strcmp(lpCmdLine, "-rgb-card-background") == 0)
- {
- // Default hardware-defined Text background color, for Video-7's RGB-SL7 card only
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.rgbCardBackgroundColor = atoi(lpCmdLine);
- }
- else if (strcmp(lpCmdLine, "-power-on") == 0)
- {
- g_cmdLine.bBoot = true;
- }
- else if (strcmp(lpCmdLine, "-current-dir") == 0)
- {
- lpCmdLine = GetCurrArg(lpNextArg);
- lpNextArg = GetNextArg(lpNextArg);
- g_cmdLine.strCurrentDir = lpCmdLine;
- }
- else if (strcmp(lpCmdLine, "-no-nsc") == 0)
- {
- g_cmdLine.bRemoveNoSlotClock = true;
- }
- else // unsupported
- {
- LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
- strUnsupported += lpCmdLine;
- strUnsupported += "\n";
- }
-
- lpCmdLine = lpNextArg;
- }
-
- LogFileOutput("CmdLine: %s\n", strCmdLine.c_str());
-
- bool ok = true;
-
- if (!strUnsupported.empty())
- {
- std::string msg("Unsupported commands:\n\n");
- msg += strUnsupported;
- msg += "\n";
- msg += "Continue running AppleWin?";
- int res = MessageBox(GetDesktopWindow(), // NB. g_hFrameWindow is not yet valid
- msg.c_str(),
- "AppleWin Command Line",
- MB_ICONSTOP | MB_SETFOREGROUND | MB_YESNO);
- ok = (res != IDNO);
- }
-
- return ok;
-}
-
-static void GetAppleWinVersion(void)
-{
- char szPath[_MAX_PATH];
-
- if (0 == GetModuleFileName(NULL, szPath, sizeof(szPath)))
- strcpy_s(szPath, sizeof(szPath), __argv[0]);
-
- // Extract application version and store in a global variable
- DWORD dwHandle, dwVerInfoSize;
-
- dwVerInfoSize = GetFileVersionInfoSize(szPath, &dwHandle);
-
- if (dwVerInfoSize > 0)
- {
- char* pVerInfoBlock = new char[dwVerInfoSize];
-
- if (GetFileVersionInfo(szPath, NULL, dwVerInfoSize, pVerInfoBlock))
- {
- VS_FIXEDFILEINFO* pFixedFileInfo;
- UINT pFixedFileInfoLen;
-
- VerQueryValue(pVerInfoBlock, TEXT("\\"), (LPVOID*) &pFixedFileInfo, (PUINT) &pFixedFileInfoLen);
-
- // Construct version string from fixed file info block
-
- 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;
- StringCbPrintf(VERSIONSTRING, VERSIONSTRING_SIZE, "%d.%d.%d.%d", major, minor, fix, fix_minor);
- }
-
- delete [] pVerInfoBlock;
- }
-
- LogFileOutput("AppleWin version: %s\n", VERSIONSTRING);
-}
-
-// DO ONE-TIME INITIALIZATION
-static void OneTimeInitialization(HINSTANCE passinstance)
-{
-#if 0
-#ifdef RIFF_SPKR
- RiffInitWriteFile("Spkr.wav", SPKR_SAMPLE_RATE, 1);
-#endif
-#ifdef RIFF_MB
- RiffInitWriteFile("Mockingboard.wav", 44100, 2);
-#endif
-#endif
-
- // Initialize COM - so we can use CoCreateInstance
- // . NB. DSInit() & DIMouse::DirectInputInit are done when g_hFrameWindow is created (WM_CREATE)
- HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
- LogFileOutput("Init: CoInitializeEx(), hr=0x%08X\n", hr);
-
- g_bSysClkOK = SysClk_InitTimer();
- LogFileOutput("Init: SysClk_InitTimer(), res=%d\n", g_bSysClkOK ? 1:0);
-#ifdef USE_SPEECH_API
- if (g_bEnableSpeech)
- {
- const bool bSpeechOK = g_Speech.Init();
- LogFileOutput("Init: SysClk_InitTimer(), res=%d\n", bSpeechOK ? 1:0);
- }
-#endif
-#if 0
- DDInit(); // For WaitForVerticalBlank()
-#endif
-
- g_hInstance = passinstance;
- GdiSetBatchLimit(512);
- LogFileOutput("Init: GdiSetBatchLimit()\n");
-
- GetProgramDirectory();
- LogFileOutput("Init: GetProgramDirectory()\n");
-
- if (g_bRegisterFileTypes)
- {
- RegisterExtensions();
- LogFileOutput("Init: RegisterExtensions()\n");
- }
-
- FrameRegisterClass();
- LogFileOutput("Init: FrameRegisterClass()\n");
-
- ImageInitialize();
- LogFileOutput("Init: ImageInitialize()\n");
-}
-
-// DO INITIALIZATION THAT MUST BE REPEATED FOR A RESTART
-static void RepeatInitialization(void)
-{
- ResetToLogoMode();
-
- // NB. g_OldAppleWinVersion needed by LoadConfiguration() -> Config_Load_Video()
- const bool bShowAboutDlg = CheckOldAppleWinVersion(); // Post: g_OldAppleWinVersion
-
- LoadConfiguration();
- LogFileOutput("Main: LoadConfiguration()\n");
-
- if (g_cmdLine.model != A2TYPE_MAX)
- SetApple2Type(g_cmdLine.model);
-
- RGB_SetVideocard(g_cmdLine.rgbCard, g_cmdLine.rgbCardForegroundColor, g_cmdLine.rgbCardBackgroundColor);
-
- if (g_cmdLine.newVideoType >= 0)
- {
- SetVideoType( (VideoType_e)g_cmdLine.newVideoType );
- g_cmdLine.newVideoType = -1; // Don't reapply after a restart
- }
- SetVideoStyle( (VideoStyle_e) ((GetVideoStyle() | g_cmdLine.newVideoStyleEnableMask) & ~g_cmdLine.newVideoStyleDisableMask) );
-
- if (g_cmdLine.newVideoRefreshRate != VR_NONE)
- {
- SetVideoRefreshRate(g_cmdLine.newVideoRefreshRate);
- g_cmdLine.newVideoRefreshRate = VR_NONE; // Don't reapply after a restart
- SetCurrentCLK6502();
- }
-
- UseClockMultiplier(g_cmdLine.clockMultiplier);
- g_cmdLine.clockMultiplier = 0.0;
-
- // Apply the memory expansion switches after loading the Apple II machine type
-#ifdef RAMWORKS
- if (g_cmdLine.uRamWorksExPages)
- {
- SetRamWorksMemorySize(g_cmdLine.uRamWorksExPages);
- SetExpansionMemType(CT_RamWorksIII);
- g_cmdLine.uRamWorksExPages = 0; // Don't reapply after a restart
- }
-#endif
- if (g_cmdLine.uSaturnBanks)
- {
- SetSaturnMemorySize(g_cmdLine.uSaturnBanks); // Set number of banks before constructing Saturn card
- SetExpansionMemType(CT_Saturn128K);
- g_cmdLine.uSaturnBanks = 0; // Don't reapply after a restart
- }
-
- if (g_cmdLine.bSlot0LanguageCard)
- {
- SetExpansionMemType(CT_LanguageCard);
- g_cmdLine.bSlot0LanguageCard = false; // Don't reapply after a restart
- }
-
- if (g_cmdLine.bSwapButtons0and1)
- {
- sg_PropertySheet.SetButtonsSwapState(true);
- // Reapply after a restart - TODO: grey-out the Config UI for "Swap 0/1" when this cmd line is passed in
- }
-
- DebugInitialize();
- LogFileOutput("Main: DebugInitialize()\n");
-
- JoyInitialize();
- LogFileOutput("Main: JoyInitialize()\n");
-
- WinVideoInitialize(); // g_pFramebufferinfo been created now
- LogFileOutput("Main: VideoInitialize()\n");
-
- LogFileOutput("Main: FrameCreateWindow() - pre\n");
- FrameCreateWindow(); // g_hFrameWindow is now valid
- LogFileOutput("Main: FrameCreateWindow() - post\n");
-
- // Init palette color
- VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideoType());
-
- // Allow the 4 hardcoded slots to be configurated as empty
- // NB. this state is not persisted to the Registry/conf.ini (just as '-s7 empty' isn't)
- // TODO: support bSlotEmpty[] for slots: 0,4,5
- if (g_cmdLine.bSlotEmpty[SLOT1])
- GetCardMgr().Remove(SLOT1);
- if (g_cmdLine.bSlotEmpty[SLOT2])
- GetCardMgr().Remove(SLOT2);
- if (g_cmdLine.bSlotEmpty[SLOT3])
- GetCardMgr().Remove(SLOT3);
- if (g_cmdLine.bSlotEmpty[SLOT6])
- GetCardMgr().Remove(SLOT6);
-
- if (g_cmdLine.slotInsert[SLOT5] != CT_Empty)
- {
- if (GetCardMgr().QuerySlot(SLOT4) == CT_MockingboardC && g_cmdLine.slotInsert[SLOT5] != CT_MockingboardC) // Currently MB occupies slot4+5 when enabled
- {
- GetCardMgr().Remove(SLOT4);
- GetCardMgr().Remove(SLOT5);
- }
-
- GetCardMgr().Insert(SLOT5, g_cmdLine.slotInsert[SLOT5]);
- }
-
- // Pre: may need g_hFrameWindow for MessageBox errors
- // Post: may enable HDD, required for MemInitialize()->MemInitializeIO()
- {
- bool temp = false;
- InsertFloppyDisks(SLOT5, g_cmdLine.szImageName_drive[SLOT5], temp);
- //g_cmdLine.szImageName_drive[SLOT5][DRIVE_1] = g_cmdLine.szImageName_drive[SLOT5][DRIVE_2] = NULL; // *Do* insert on a restart (since no way they could have changed)
-
- InsertFloppyDisks(SLOT6, g_cmdLine.szImageName_drive[SLOT6], g_cmdLine.bBoot);
- g_cmdLine.szImageName_drive[SLOT6][DRIVE_1] = g_cmdLine.szImageName_drive[SLOT6][DRIVE_2] = NULL; // Don't insert on a restart
-
- InsertHardDisks(g_cmdLine.szImageName_harddisk, g_cmdLine.bBoot);
- g_cmdLine.szImageName_harddisk[HARDDISK_1] = g_cmdLine.szImageName_harddisk[HARDDISK_2] = NULL; // Don't insert on a restart
-
- if (g_cmdLine.bSlotEmpty[7])
- {
- HD_SetEnabled(false); // Disable HDD controller, but don't persist this to Registry/conf.ini (consistent with other '-sn empty' cmds)
- Snapshot_UpdatePath(); // If save-state's filename is a harddisk, and the floppy is in the same path, then the filename won't be updated
- }
- }
-
- // Set *after* InsertFloppyDisks() & InsertHardDisks(), which both update g_sCurrentDir
- if (!g_cmdLine.strCurrentDir.empty())
- SetCurrentImageDir(g_cmdLine.strCurrentDir);
-
- if (g_cmdLine.bRemoveNoSlotClock)
- MemRemoveNoSlotClock();
-
- MemInitialize();
- LogFileOutput("Main: MemInitialize()\n");
-
- // Show About dialog after creating main window (need g_hFrameWindow)
- if (bShowAboutDlg)
- {
- if (!AboutDlg())
- g_cmdLine.bShutdown = true; // Close everything down
- else
- RegSaveString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, VERSIONSTRING); // Only save version after user accepts license
- }
-
- if (g_bCapturePrintScreenKey)
- {
- RegisterHotKeys(); // needs valid g_hFrameWindow
- LogFileOutput("Main: RegisterHotKeys()\n");
- }
-
- if (g_bHookSystemKey)
- {
- if (InitHookThread()) // needs valid g_hFrameWindow (for message pump)
- LogFileOutput("Main: HookFilterForKeyboard()\n");
- }
-
- // Need to test if it's safe to call ResetMachineState(). In the meantime, just call Disk2Card's Reset():
- GetCardMgr().GetDisk2CardMgr().Reset(true); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor
- LogFileOutput("Main: DiskReset()\n");
- HD_Reset(); // GH#515
- LogFileOutput("Main: HDDReset()\n");
-
- if (!g_bSysClkOK)
- {
- MessageBox(g_hFrameWindow, "DirectX failed to create SystemClock instance", TEXT("AppleWin Error"), MB_OK);
- g_cmdLine.bShutdown = true;
- }
-
- if (g_bCustomRomF8Failed || g_bCustomRomFailed || (g_hCustomRomF8 != INVALID_HANDLE_VALUE && g_hCustomRom != INVALID_HANDLE_VALUE))
- {
- std::string msg = g_bCustomRomF8Failed ? "Failed to load custom F8 rom (not found or not exactly 2KiB)\n"
- : g_bCustomRomFailed ? "Failed to load custom rom (not found or not exactly 12KiB or 16KiB)\n"
- : "Unsupported -rom and -f8rom being used at the same time\n";
-
- LogFileOutput("%s", msg.c_str());
- MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
- g_cmdLine.bShutdown = true;
- }
-
- tfe_init();
- LogFileOutput("Main: tfe_init()\n");
-
- if (g_cmdLine.szSnapshotName)
- {
- std::string strPathname(g_cmdLine.szSnapshotName);
- int nIdx = strPathname.find_last_of('\\');
- if (nIdx >= 0 && nIdx+1 < (int)strPathname.length()) // path exists?
- {
- const std::string strPath = strPathname.substr(0, nIdx+1);
- SetCurrentImageDir(strPath);
- }
-
- // Override value just loaded from Registry by LoadConfiguration()
- // . NB. Registry value is not updated with this cmd-line value
- Snapshot_SetFilename(g_cmdLine.szSnapshotName);
- Snapshot_LoadState();
- g_cmdLine.bBoot = true;
- g_cmdLine.szSnapshotName = NULL;
- }
- else
- {
- Snapshot_Startup(); // Do this after everything has been init'ed
- LogFileOutput("Main: Snapshot_Startup()\n");
- }
-
- if (g_cmdLine.szScreenshotFilename)
- {
- Video_RedrawAndTakeScreenShot(g_cmdLine.szScreenshotFilename);
- g_cmdLine.bShutdown = true;
- }
-
- if (g_cmdLine.bShutdown)
- {
- 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 (g_cmdLine.bSetFullScreen)
- {
- if (g_cmdLine.bestWidth && g_cmdLine.bestHeight)
- {
- DEVMODE devMode;
- memset(&devMode, 0, sizeof(devMode));
- devMode.dmSize = sizeof(devMode);
- devMode.dmPelsWidth = g_cmdLine.bestWidth;
- devMode.dmPelsHeight = g_cmdLine.bestHeight;
- devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
-
- DWORD dwFlags = 0;
- LONG res = ChangeDisplaySettings(&devMode, dwFlags);
- if (res == 0)
- g_cmdLine.bChangedDisplayResolution = true;
- }
-
- PostMessage(g_hFrameWindow, WM_USER_FULLSCREEN, 0, 0);
- g_cmdLine.bSetFullScreen = false;
- }
-
- if (g_cmdLine.bBoot)
- {
- PostMessage(g_hFrameWindow, WM_USER_BOOT, 0, 0);
- g_cmdLine.bBoot = false;
- }
- }
-}
-
-static void Shutdown(void)
-{
- if (g_cmdLine.bChangedDisplayResolution)
- ChangeDisplaySettings(NULL, 0); // restore default
-
- // Release COM
- DDUninit();
- SysClk_UninitTimer();
- LogFileOutput("Exit: SysClk_UninitTimer()\n");
-
- CoUninitialize();
- LogFileOutput("Exit: CoUninitialize()\n");
-
- tfe_shutdown();
- LogFileOutput("Exit: tfe_shutdown()\n");
-
- LogDone();
-
- RiffFinishWriteFile();
-
- if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
- CloseHandle(g_hCustomRomF8);
-
- if (g_hCustomRom != INVALID_HANDLE_VALUE)
- CloseHandle(g_hCustomRom);
-
- if (g_cmdLine.bSlot7EmptyOnExit)
- UnplugHardDiskControllerCard();
-}
diff --git a/source/CPU.cpp b/source/CPU.cpp
index 9a3e3368..a6b4f6e1 100644
--- a/source/CPU.cpp
+++ b/source/CPU.cpp
@@ -87,7 +87,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "CPU.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CardManager.h"
#include "Memory.h"
#include "Mockingboard.h"
diff --git a/source/CardManager.cpp b/source/CardManager.cpp
index 86e142ef..d71e31b1 100644
--- a/source/CardManager.cpp
+++ b/source/CardManager.cpp
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "CardManager.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "Disk.h"
#include "MouseInterface.h"
diff --git a/source/CmdLine.cpp b/source/CmdLine.cpp
new file mode 100644
index 00000000..f6ffe967
--- /dev/null
+++ b/source/CmdLine.cpp
@@ -0,0 +1,527 @@
+/*
+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
+
+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: main
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "CmdLine.h"
+#include "Log.h"
+#include "Core.h"
+#include "Memory.h"
+#include "LanguageCard.h"
+#include "Keyboard.h"
+#include "Joystick.h"
+#include "SoundCore.h"
+#include "ParallelPrinter.h"
+#include "CardManager.h"
+#include "SerialComms.h"
+#include "Windows/WinFrame.h"
+
+CmdLine g_cmdLine;
+std::string g_sConfigFile; // INI file to use instead of Registry
+
+bool g_bCapturePrintScreenKey = true;
+bool g_bRegisterFileTypes = true;
+bool g_bHookSystemKey = true;
+bool g_bHookAltTab = false;
+bool g_bHookAltGrControl = false;
+
+static LPSTR GetCurrArg(LPSTR lpCmdLine)
+{
+ if(*lpCmdLine == '\"')
+ lpCmdLine++;
+
+ return lpCmdLine;
+}
+
+static LPSTR GetNextArg(LPSTR lpCmdLine)
+{
+ int bInQuotes = 0;
+
+ while(*lpCmdLine)
+ {
+ if(*lpCmdLine == '\"')
+ {
+ bInQuotes ^= 1;
+ if(!bInQuotes)
+ {
+ *lpCmdLine++ = 0x00; // Assume end-quote is end of this arg
+ continue;
+ }
+ }
+
+ if((*lpCmdLine == ' ') && !bInQuotes)
+ {
+ *lpCmdLine++ = 0x00;
+ break;
+ }
+
+ lpCmdLine++;
+ }
+
+ return lpCmdLine;
+}
+
+//---------------------------------------------------------------------------
+
+bool ProcessCmdLine(LPSTR lpCmdLine)
+{
+ const std::string strCmdLine(lpCmdLine); // Keep a copy for log ouput
+ std::string strUnsupported;
+
+ // If 1st param looks like an abs pathname then assume that an associated filetype has been double-clicked
+ // NB. Handled by WM_DDE_INITIATE & WM_DDE_EXECUTE msgs
+ if ((lpCmdLine[0] >= '\"' && lpCmdLine[1] >= 'A' && lpCmdLine[1] <= 'Z' && lpCmdLine[2] == ':') // always in quotes
+ || strncmp("\\\\?\\", lpCmdLine, 4) == 0)
+ return true;
+
+ while (*lpCmdLine)
+ {
+ LPSTR lpNextArg = GetNextArg(lpCmdLine);
+
+ if (((strcmp(lpCmdLine, "-l") == 0) || (strcmp(lpCmdLine, "-log") == 0)) && (g_fh == NULL))
+ {
+ LogInit();
+ }
+ else if (strcmp(lpCmdLine, "-noreg") == 0)
+ {
+ g_bRegisterFileTypes = false;
+ }
+ else if (strcmp(lpCmdLine, "-conf") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ char buf[MAX_PATH];
+ DWORD res = GetFullPathName(lpCmdLine, MAX_PATH, buf, NULL);
+ if (res == 0)
+ LogFileOutput("Failed to open configuration file: %s\n", lpCmdLine);
+ else
+ g_sConfigFile = buf;
+ }
+ else if (strcmp(lpCmdLine, "-d1") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.szImageName_drive[SLOT6][DRIVE_1] = lpCmdLine;
+ }
+ else if (strcmp(lpCmdLine, "-d2") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.szImageName_drive[SLOT6][DRIVE_2] = lpCmdLine;
+ }
+ else if (strcmp(lpCmdLine, "-h1") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.szImageName_harddisk[HARDDISK_1] = lpCmdLine;
+ }
+ else if (strcmp(lpCmdLine, "-h2") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.szImageName_harddisk[HARDDISK_2] = lpCmdLine;
+ }
+ else if (lpCmdLine[0] == '-' && lpCmdLine[1] == 's' && lpCmdLine[2] >= '1' && lpCmdLine[2] <= '7')
+ {
+ const UINT slot = lpCmdLine[2] - '0';
+
+ if (lpCmdLine[3] == 0) // -s[1..7]
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ if (strcmp(lpCmdLine, "empty") == 0)
+ g_cmdLine.bSlotEmpty[slot] = true;
+ if (strcmp(lpCmdLine, "diskii") == 0)
+ g_cmdLine.slotInsert[slot] = CT_Disk2;
+ }
+ else if (lpCmdLine[3] == 'd' && (lpCmdLine[4] == '1' || lpCmdLine[4] == '2')) // -s[1..7]d[1|2]
+ {
+ const UINT drive = lpCmdLine[4] == '1' ? DRIVE_1 : DRIVE_2;
+
+ if (slot != 5 && slot != 6)
+ {
+ LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
+ }
+ else
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.szImageName_drive[slot][drive] = lpCmdLine;
+ }
+ }
+ else if (strcmp(lpCmdLine, "-s7-empty-on-exit") == 0)
+ {
+ g_cmdLine.bSlot7EmptyOnExit = true;
+ }
+ else
+ {
+ LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
+ }
+ }
+ else if (strcmp(lpCmdLine, "-load-state") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.szSnapshotName = lpCmdLine;
+ }
+ else if (strcmp(lpCmdLine, "-f") == 0)
+ {
+ g_cmdLine.bSetFullScreen = true;
+ }
+#define CMD_FS_HEIGHT "-fs-height="
+ else if (strncmp(lpCmdLine, CMD_FS_HEIGHT, sizeof(CMD_FS_HEIGHT)-1) == 0)
+ {
+ g_cmdLine.bSetFullScreen = true; // Implied
+
+ LPSTR lpTmp = lpCmdLine + sizeof(CMD_FS_HEIGHT)-1;
+ bool bRes = false;
+ if (strcmp(lpTmp, "best") == 0)
+ {
+ bRes = GetBestDisplayResolutionForFullScreen(g_cmdLine.bestWidth, g_cmdLine.bestHeight);
+ }
+ else
+ {
+ UINT userSpecifiedHeight = atoi(lpTmp);
+ if (userSpecifiedHeight)
+ bRes = GetBestDisplayResolutionForFullScreen(g_cmdLine.bestWidth, g_cmdLine.bestHeight, userSpecifiedHeight);
+ else
+ LogFileOutput("Invalid cmd-line parameter for -fs-height=x switch\n");
+ }
+ if (bRes)
+ LogFileOutput("Best resolution for -fs-height=x switch: Width=%d, Height=%d\n", g_cmdLine.bestWidth, g_cmdLine.bestHeight);
+ else
+ LogFileOutput("Failed to set parameter for -fs-height=x switch\n");
+ }
+ else if (strcmp(lpCmdLine, "-no-di") == 0)
+ {
+ g_bDisableDirectInput = true;
+ }
+ else if (strcmp(lpCmdLine, "-m") == 0)
+ {
+ g_bDisableDirectSound = true;
+ }
+ else if (strcmp(lpCmdLine, "-no-mb") == 0)
+ {
+ g_bDisableDirectSoundMockingboard = true;
+ }
+ else if (strcmp(lpCmdLine, "-memclear") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_nMemoryClearType = atoi(lpCmdLine);
+ if (g_nMemoryClearType < 0)
+ g_nMemoryClearType = 0;
+ else
+ if (g_nMemoryClearType >= NUM_MIP)
+ g_nMemoryClearType = NUM_MIP - 1;
+ }
+#ifdef RAMWORKS
+ else if (strcmp(lpCmdLine, "-r") == 0) // RamWorks size [1..127]
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.uRamWorksExPages = atoi(lpCmdLine);
+ if (g_cmdLine.uRamWorksExPages > kMaxExMemoryBanks)
+ g_cmdLine.uRamWorksExPages = kMaxExMemoryBanks;
+ else
+ if (g_cmdLine.uRamWorksExPages < 1)
+ g_cmdLine.uRamWorksExPages = 1;
+ }
+#endif
+ else if (strcmp(lpCmdLine, "-s0") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0)
+ g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks;
+ else if (strcmp(lpCmdLine, "saturn64") == 0)
+ g_cmdLine.uSaturnBanks = Saturn128K::kMaxSaturnBanks/2;
+ else if (strcmp(lpCmdLine, "languagecard") == 0 || strcmp(lpCmdLine, "lc") == 0)
+ g_cmdLine.bSlot0LanguageCard = true;
+ }
+ else if (strcmp(lpCmdLine, "-f8rom") == 0) // Use custom 2K ROM at [$F800..$FFFF]
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (g_hCustomRomF8 != INVALID_HANDLE_VALUE) // Stop resource leak if -f8rom is specified twice!
+ CloseHandle(g_hCustomRomF8);
+
+ g_hCustomRomF8 = CreateFile(lpCmdLine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+ if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
+ g_bCustomRomF8Failed = true;
+ }
+ else if (strcmp(lpCmdLine, "-rom") == 0) // Use custom 16K at [$C000..$FFFF] or 12K ROM at [$D000..$FFFF]
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (g_hCustomRom != INVALID_HANDLE_VALUE) // Stop resource leak if -rom is specified twice!
+ CloseHandle(g_hCustomRom);
+
+ g_hCustomRom = CreateFile(lpCmdLine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+ if ((g_hCustomRom == INVALID_HANDLE_VALUE) || ((GetFileSize(g_hCustomRom, NULL) != 0x4000) && (GetFileSize(g_hCustomRom, NULL) != 0x3000)))
+ g_bCustomRomFailed = true;
+ }
+ else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 2K (for II/II+). Use 4K,8K or 16K video ROM (for Enhanced //e)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (!ReadVideoRomFile(lpCmdLine))
+ {
+ std::string msg = "Failed to load video rom (not found or not exactly 2/4/8/16KiB)\n";
+ LogFileOutput("%s", msg.c_str());
+ MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
+ }
+ else
+ {
+ SetVideoRomRockerSwitch(true); // Use PAL char set
+ }
+ }
+ else if (strcmp(lpCmdLine, "-printscreen") == 0) // Turn on display of the last filename print screen was saved to
+ {
+ g_bDisplayPrintScreenFileName = true;
+ }
+ else if (strcmp(lpCmdLine, "-no-printscreen-key") == 0) // Don't try to capture PrintScreen key GH#469
+ {
+ g_bCapturePrintScreenKey = false;
+ }
+ else if (strcmp(lpCmdLine, "-no-printscreen-dlg") == 0) // Turn off the PrintScreen warning message dialog (if PrintScreen key can't be grabbed)
+ {
+ g_bShowPrintScreenWarningDialog = false;
+ }
+ else if (strcmp(lpCmdLine, "-no-hook-system-key") == 0) // Don't hook the System keys (eg. Left-ALT+ESC/SPACE/TAB) GH#556
+ {
+ g_bHookSystemKey = false;
+ }
+ else if (strcmp(lpCmdLine, "-hook-alt-tab") == 0) // GH#556
+ {
+ g_bHookAltTab = true;
+ }
+ else if (strcmp(lpCmdLine, "-hook-altgr-control") == 0) // GH#556
+ {
+ g_bHookAltGrControl = true;
+ }
+ else if (strcmp(lpCmdLine, "-altgr-sends-wmchar") == 0) // GH#625
+ {
+ KeybSetAltGrSendsWM_CHAR(true);
+ }
+ else if (strcmp(lpCmdLine, "-no-hook-alt") == 0) // GH#583
+ {
+ JoySetHookAltKeys(false);
+ }
+ else if (strcmp(lpCmdLine, "-left-alt-control-buttons") == 0) // GH#743
+ {
+ JoySetButtonVirtualKey(0, VK_CONTROL);
+ JoySetButtonVirtualKey(1, VK_MENU);
+ }
+ else if (strcmp(lpCmdLine, "-right-alt-control-buttons") == 0) // GH#743
+ {
+ JoySetButtonVirtualKey(0, VK_MENU | KF_EXTENDED);
+ JoySetButtonVirtualKey(1, VK_CONTROL | KF_EXTENDED);
+ }
+ else if (strcmp(lpCmdLine, "-swap-buttons") == 0)
+ {
+ g_cmdLine.bSwapButtons0and1 = true;
+ }
+ else if (strcmp(lpCmdLine, "-spkr-inc") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ const int nErrorInc = atoi(lpCmdLine);
+ SoundCore_SetErrorInc( nErrorInc );
+ }
+ else if (strcmp(lpCmdLine, "-spkr-max") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ const int nErrorMax = atoi(lpCmdLine);
+ SoundCore_SetErrorMax( nErrorMax );
+ }
+ else if (strcmp(lpCmdLine, "-use-real-printer") == 0) // Enable control in Advanced config to allow dumping to a real printer
+ {
+ g_bEnableDumpToRealPrinter = true;
+ }
+ else if (strcmp(lpCmdLine, "-speech") == 0)
+ {
+ g_bEnableSpeech = true;
+ }
+ else if (strcmp(lpCmdLine, "-multimon") == 0)
+ {
+ g_bMultiMon = true;
+ }
+ else if ((strcmp(lpCmdLine, "-dcd") == 0) || (strcmp(lpCmdLine, "-modem") == 0)) // GH#386
+ {
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->SupportDCD(true);
+ }
+ else if (strcmp(lpCmdLine, "-alt-enter=toggle-full-screen") == 0) // GH#556
+ {
+ SetAltEnterToggleFullScreen(true);
+ }
+ else if (strcmp(lpCmdLine, "-alt-enter=open-apple-enter") == 0) // GH#556
+ {
+ SetAltEnterToggleFullScreen(false);
+ }
+ else if (strcmp(lpCmdLine, "-video-mode=idealized") == 0) // GH#616
+ {
+ g_cmdLine.newVideoType = VT_COLOR_IDEALIZED;
+ }
+ else if (strcmp(lpCmdLine, "-video-mode=rgb-videocard") == 0)
+ {
+ g_cmdLine.newVideoType = VT_COLOR_VIDEOCARD_RGB;
+ }
+ else if (strcmp(lpCmdLine, "-video-mode=composite-monitor") == 0) // GH#763
+ {
+ g_cmdLine.newVideoType = VT_COLOR_MONITOR_NTSC;
+ }
+ else if (strcmp(lpCmdLine, "-video-style=vertical-blend") == 0) // GH#616
+ {
+ g_cmdLine.newVideoStyleEnableMask = VS_COLOR_VERTICAL_BLEND;
+ }
+ else if (strcmp(lpCmdLine, "-video-style=no-vertical-blend") == 0) // GH#616
+ {
+ g_cmdLine.newVideoStyleDisableMask = VS_COLOR_VERTICAL_BLEND;
+ }
+ else if (strcmp(lpCmdLine, "-rgb-card-invert-bit7") == 0) // GH#633
+ {
+ RGB_SetInvertBit7(true);
+ }
+ else if (strcmp(lpCmdLine, "-screenshot-and-exit") == 0) // GH#616: For testing - Use in combination with -load-state
+ {
+ g_cmdLine.szScreenshotFilename = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ }
+ else if (strcmp(lpCmdLine, "-clock-multiplier") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.clockMultiplier = atof(lpCmdLine);
+ }
+ else if (strcmp(lpCmdLine, "-model") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (strcmp(lpCmdLine, "apple2") == 0)
+ g_cmdLine.model = A2TYPE_APPLE2;
+ else if (strcmp(lpCmdLine, "apple2p") == 0)
+ g_cmdLine.model = A2TYPE_APPLE2PLUS;
+ else if (strcmp(lpCmdLine, "apple2jp") == 0)
+ g_cmdLine.model = A2TYPE_APPLE2JPLUS;
+ else if (strcmp(lpCmdLine, "apple2e") == 0)
+ g_cmdLine.model = A2TYPE_APPLE2E;
+ else if (strcmp(lpCmdLine, "apple2ee") == 0)
+ g_cmdLine.model = A2TYPE_APPLE2EENHANCED;
+ else
+ LogFileOutput("-model: unsupported type: %s\n", lpCmdLine);
+ }
+ else if (_stricmp(lpCmdLine, "-50hz") == 0) // (case-insensitive)
+ {
+ g_cmdLine.newVideoRefreshRate = VR_50HZ;
+ }
+ else if (_stricmp(lpCmdLine, "-60hz") == 0) // (case-insensitive)
+ {
+ g_cmdLine.newVideoRefreshRate = VR_60HZ;
+ }
+ else if (strcmp(lpCmdLine, "-rgb-card-type") == 0)
+ {
+ // RGB video card valid types are: "apple", "sl7", "eve", "feline"
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (strcmp(lpCmdLine, "apple") == 0) // Just an alias for SL7
+ g_cmdLine.rgbCard = RGB_Videocard_e::Apple;
+ else if (strcmp(lpCmdLine, "sl7") == 0)
+ g_cmdLine.rgbCard = RGB_Videocard_e::Video7_SL7;
+ else if (strcmp(lpCmdLine, "eve") == 0)
+ g_cmdLine.rgbCard = RGB_Videocard_e::LeChatMauve_EVE;
+ else if (strcmp(lpCmdLine, "feline") == 0)
+ g_cmdLine.rgbCard = RGB_Videocard_e::LeChatMauve_Feline;
+ else
+ LogFileOutput("-rgb-card-type: unsupported type: %s\n", lpCmdLine);
+ }
+ else if (strcmp(lpCmdLine, "-rgb-card-foreground") == 0)
+ {
+ // Default hardware-defined Text foreground color, for Video-7's RGB-SL7 card only
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.rgbCardForegroundColor = atoi(lpCmdLine);
+ }
+ else if (strcmp(lpCmdLine, "-rgb-card-background") == 0)
+ {
+ // Default hardware-defined Text background color, for Video-7's RGB-SL7 card only
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.rgbCardBackgroundColor = atoi(lpCmdLine);
+ }
+ else if (strcmp(lpCmdLine, "-power-on") == 0)
+ {
+ g_cmdLine.bBoot = true;
+ }
+ else if (strcmp(lpCmdLine, "-current-dir") == 0)
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+ g_cmdLine.strCurrentDir = lpCmdLine;
+ }
+ else if (strcmp(lpCmdLine, "-no-nsc") == 0)
+ {
+ g_cmdLine.bRemoveNoSlotClock = true;
+ }
+ else // unsupported
+ {
+ LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
+ strUnsupported += lpCmdLine;
+ strUnsupported += "\n";
+ }
+
+ lpCmdLine = lpNextArg;
+ }
+
+ LogFileOutput("CmdLine: %s\n", strCmdLine.c_str());
+
+ bool ok = true;
+
+ if (!strUnsupported.empty())
+ {
+ std::string msg("Unsupported commands:\n\n");
+ msg += strUnsupported;
+ msg += "\n";
+ msg += "Continue running AppleWin?";
+ int res = MessageBox(GetDesktopWindow(), // NB. g_hFrameWindow is not yet valid
+ msg.c_str(),
+ "AppleWin Command Line",
+ MB_ICONSTOP | MB_SETFOREGROUND | MB_YESNO);
+ ok = (res != IDNO);
+ }
+
+ return ok;
+}
diff --git a/source/CmdLine.h b/source/CmdLine.h
new file mode 100644
index 00000000..bdbd64de
--- /dev/null
+++ b/source/CmdLine.h
@@ -0,0 +1,88 @@
+#pragma once
+
+#include "RgbMonitor.h"
+#include "Harddisk.h"
+#include "Disk.h"
+#include "Video.h"
+#include "Common.h"
+#include "Card.h"
+
+
+struct CmdLine
+{
+ CmdLine()
+ {
+ bShutdown = false;
+ bSetFullScreen = false;
+ bBoot = false;
+ bChangedDisplayResolution = false;
+ bSlot0LanguageCard = false;
+ bSlot7EmptyOnExit = false;
+ bSwapButtons0and1 = false;
+ bRemoveNoSlotClock = false;
+ bestWidth = 0;
+ bestHeight = 0;
+ szImageName_harddisk[HARDDISK_1] = NULL;
+ szImageName_harddisk[HARDDISK_2] = NULL;
+ szSnapshotName = NULL;
+ szScreenshotFilename = NULL;
+ uRamWorksExPages = 0;
+ uSaturnBanks = 0;
+ newVideoType = -1;
+ newVideoStyleEnableMask = 0;
+ newVideoStyleDisableMask = 0;
+ newVideoRefreshRate = VR_NONE;
+ clockMultiplier = 0.0; // 0 => not set from cmd-line
+ model = A2TYPE_MAX;
+ rgbCard = RGB_Videocard_e::Apple;
+ rgbCardForegroundColor = 15;
+ rgbCardBackgroundColor = 0;
+
+ for (UINT i = 0; i < NUM_SLOTS; i++)
+ {
+ bSlotEmpty[i] = false;
+ slotInsert[i] = CT_Empty;
+ szImageName_drive[i][DRIVE_1] = NULL;
+ szImageName_drive[i][DRIVE_2] = NULL;
+ }
+ }
+
+ bool bShutdown;
+ bool bSetFullScreen;
+ bool bBoot;
+ bool bChangedDisplayResolution;
+ bool bSlot0LanguageCard;
+ bool bSlotEmpty[NUM_SLOTS];
+ bool bSlot7EmptyOnExit;
+ bool bSwapButtons0and1;
+ bool bRemoveNoSlotClock;
+ SS_CARDTYPE slotInsert[NUM_SLOTS];
+ UINT bestWidth;
+ UINT bestHeight;
+ LPSTR szImageName_drive[NUM_SLOTS][NUM_DRIVES];
+ LPSTR szImageName_harddisk[NUM_HARDDISKS];
+ LPSTR szSnapshotName;
+ LPSTR szScreenshotFilename;
+ UINT uRamWorksExPages;
+ UINT uSaturnBanks;
+ int newVideoType;
+ int newVideoStyleEnableMask;
+ int newVideoStyleDisableMask;
+ VideoRefreshRate_e newVideoRefreshRate;
+ double clockMultiplier;
+ eApple2Type model;
+ RGB_Videocard_e rgbCard;
+ int rgbCardForegroundColor;
+ int rgbCardBackgroundColor;
+ std::string strCurrentDir;
+};
+
+bool ProcessCmdLine(LPSTR lpCmdLine);
+
+extern std::string g_sConfigFile; // INI file to use instead of Registry
+extern bool g_bCapturePrintScreenKey;
+extern bool g_bRegisterFileTypes;
+extern bool g_bHookSystemKey;
+extern bool g_bHookAltTab;
+extern bool g_bHookAltGrControl;
+extern CmdLine g_cmdLine;
diff --git a/source/Configuration/About.cpp b/source/Configuration/About.cpp
index 54456946..5bb57219 100644
--- a/source/Configuration/About.cpp
+++ b/source/Configuration/About.cpp
@@ -24,7 +24,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "About.h"
-#include "../AppleWin.h"
+#include "../Core.h"
+#include "../Windows/AppleWin.h"
#include "../Windows/WinFrame.h"
#include "../resource/resource.h"
diff --git a/source/Configuration/Config.h b/source/Configuration/Config.h
index cf7dd085..0369ed48 100644
--- a/source/Configuration/Config.h
+++ b/source/Configuration/Config.h
@@ -1,6 +1,6 @@
#pragma once
-#include "../AppleWin.h"
+#include "../Core.h"
#include "../CardManager.h"
#include "../CPU.h"
#include "../DiskImage.h" // Disk_Status_e
diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp
index dabc68ff..37c27cd8 100644
--- a/source/Configuration/PageConfig.cpp
+++ b/source/Configuration/PageConfig.cpp
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PageConfig.h"
#include "PropertySheetHelper.h"
-#include "../AppleWin.h"
+#include "../Windows/AppleWin.h"
#include "../Windows/WinFrame.h"
#include "../Registry.h"
#include "../SerialComms.h"
diff --git a/source/Configuration/PageDisk.cpp b/source/Configuration/PageDisk.cpp
index ac504d63..98ce4370 100644
--- a/source/Configuration/PageDisk.cpp
+++ b/source/Configuration/PageDisk.cpp
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PageDisk.h"
#include "PropertySheetHelper.h"
-#include "../AppleWin.h"
+#include "../Windows/AppleWin.h"
#include "../CardManager.h"
#include "../Disk.h" // Drive_e, Disk_Status_e
#include "../Windows/WinFrame.h"
diff --git a/source/Configuration/PropertySheet.cpp b/source/Configuration/PropertySheet.cpp
index f7cb3605..e9278206 100644
--- a/source/Configuration/PropertySheet.cpp
+++ b/source/Configuration/PropertySheet.cpp
@@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PropertySheet.h"
-#include "../AppleWin.h"
+#include "../Windows/AppleWin.h"
#include "../Windows/WinFrame.h"
#include "../resource/resource.h"
diff --git a/source/Configuration/PropertySheetHelper.cpp b/source/Configuration/PropertySheetHelper.cpp
index 77111765..97bb0fa7 100644
--- a/source/Configuration/PropertySheetHelper.cpp
+++ b/source/Configuration/PropertySheetHelper.cpp
@@ -26,7 +26,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PropertySheetHelper.h"
#include "IPropertySheet.h"
-#include "../AppleWin.h" // g_nAppMode, g_uScrollLockToggle, sg_PropertySheet
+#include "../Windows/AppleWin.h" // g_nAppMode, g_uScrollLockToggle, sg_PropertySheet
#include "../CardManager.h"
#include "../Disk.h"
#include "../Windows/WinFrame.h"
diff --git a/source/Core.cpp b/source/Core.cpp
new file mode 100644
index 00000000..ea2ef7da
--- /dev/null
+++ b/source/Core.cpp
@@ -0,0 +1,300 @@
+/*
+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
+
+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: main
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "Core.h"
+#include "CardManager.h"
+#include "CPU.h"
+#include "Video.h"
+#include "Log.h"
+#include "Memory.h"
+#include "Mockingboard.h"
+#include "Speaker.h"
+#include "Registry.h"
+#include "SynchronousEventManager.h"
+#include "Configuration/PropertySheet.h"
+
+#ifdef USE_SPEECH_API
+#include "Speech.h"
+#endif
+
+static const UINT VERSIONSTRING_SIZE = 16;
+static UINT16 g_OldAppleWinVersion[4] = {0};
+UINT16 g_AppleWinVersion[4] = { 0 };
+TCHAR VERSIONSTRING[VERSIONSTRING_SIZE] = "xx.yy.zz.ww";
+
+std::string g_pAppTitle;
+
+eApple2Type g_Apple2Type = A2TYPE_APPLE2EENHANCED;
+
+bool g_bFullSpeed = false;
+
+//=================================================
+
+AppMode_e g_nAppMode = MODE_LOGO;
+
+std::string g_sStartDir; // NB. AppleWin.exe maybe relative to this! (GH#663)
+std::string g_sProgramDir; // Directory of where AppleWin executable resides
+std::string g_sCurrentDir; // Also Starting Dir. Debugger uses this when load/save
+
+bool g_bRestart = false;
+
+bool g_bDisableDirectInput = false;
+bool g_bDisableDirectSound = false;
+bool g_bDisableDirectSoundMockingboard = false;
+
+DWORD g_dwSpeed = SPEED_NORMAL; // Affected by Config dialog's speed slider bar
+double g_fCurrentCLK6502 = CLK_6502_NTSC; // Affected by Config dialog's speed slider bar
+static double g_fMHz = 1.0; // Affected by Config dialog's speed slider bar
+
+int g_nCpuCyclesFeedback = 0;
+DWORD g_dwCyclesThisFrame = 0;
+
+int g_nMemoryClearType = MIP_FF_FF_00_00; // Note: -1 = random MIP in Memory.cpp MemReset()
+
+SynchronousEventManager g_SynchronousEventMgr;
+
+IPropertySheet& sg_PropertySheet = *new CPropertySheet;
+
+HANDLE g_hCustomRomF8 = INVALID_HANDLE_VALUE; // Cmd-line specified custom F8 ROM at $F800..$FFFF
+bool g_bCustomRomF8Failed = false; // Set if custom F8 ROM file failed
+HANDLE g_hCustomRom = INVALID_HANDLE_VALUE; // Cmd-line specified custom ROM at $C000..$FFFF(16KiB) or $D000..$FFFF(12KiB)
+bool g_bCustomRomFailed = false; // Set if custom ROM file failed
+
+bool g_bEnableSpeech = false;
+#ifdef USE_SPEECH_API
+CSpeech g_Speech;
+#endif
+
+//===========================================================================
+
+#ifdef LOG_PERF_TIMINGS
+static UINT64 g_timeTotal = 0;
+UINT64 g_timeCpu = 0;
+UINT64 g_timeVideo = 0; // part of timeCpu
+UINT64 g_timeMB_Timer = 0; // part of timeCpu
+UINT64 g_timeMB_NoTimer = 0;
+UINT64 g_timeSpeaker = 0;
+static UINT64 g_timeVideoRefresh = 0;
+
+void LogPerfTimings(void)
+{
+ if (g_timeTotal)
+ {
+ UINT64 cpu = g_timeCpu - g_timeVideo - g_timeMB_Timer;
+ UINT64 video = g_timeVideo + g_timeVideoRefresh;
+ UINT64 spkr = g_timeSpeaker;
+ UINT64 mb = g_timeMB_Timer + g_timeMB_NoTimer;
+ UINT64 audio = spkr + mb;
+ UINT64 other = g_timeTotal - g_timeCpu - g_timeSpeaker - g_timeMB_NoTimer - g_timeVideoRefresh;
+
+ LogOutput("Perf breakdown:\n");
+ LogOutput(". CPU %% = %6.2f\n", (double)cpu / (double)g_timeTotal * 100.0);
+ LogOutput(". Video %% = %6.2f\n", (double)video / (double)g_timeTotal * 100.0);
+ LogOutput("... NTSC %% = %6.2f\n", (double)g_timeVideo / (double)g_timeTotal * 100.0);
+ LogOutput("... refresh %% = %6.2f\n", (double)g_timeVideoRefresh / (double)g_timeTotal * 100.0);
+ LogOutput(". Audio %% = %6.2f\n", (double)audio / (double)g_timeTotal * 100.0);
+ LogOutput("... Speaker %% = %6.2f\n", (double)spkr / (double)g_timeTotal * 100.0);
+ LogOutput("... MB %% = %6.2f\n", (double)mb / (double)g_timeTotal * 100.0);
+ LogOutput(". Other %% = %6.2f\n", (double)other / (double)g_timeTotal * 100.0);
+ LogOutput(". TOTAL %% = %6.2f\n", (double)(cpu+video+audio+other) / (double)g_timeTotal * 100.0);
+ }
+}
+#endif
+
+//===========================================================================
+
+static DWORD dwLogKeyReadTickStart;
+static bool bLogKeyReadDone = false;
+
+void LogFileTimeUntilFirstKeyReadReset(void)
+{
+#ifdef LOG_PERF_TIMINGS
+ LogPerfTimings();
+#endif
+
+ if (!g_fh)
+ return;
+
+ dwLogKeyReadTickStart = GetTickCount();
+
+ bLogKeyReadDone = false;
+}
+
+// Log the time from emulation restart/reboot until the first key read: BIT $C000
+// . AZTEC.DSK (DOS 3.3) does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message
+// . Phasor1.dsk / ProDOS 1.1.1: PC=E797: B1 50: LDA ($50),Y / "Select an Option:" message
+// . Rescue Raiders v1.3,v1.5: PC=895: LDA $C000 / boot to intro
+void LogFileTimeUntilFirstKeyRead(void)
+{
+ if (!g_fh || bLogKeyReadDone)
+ return;
+
+ if ( (mem[regs.pc-3] != 0x2C) // AZTEC: bit $c000
+ && !((regs.pc-2) == 0xE797 && mem[regs.pc-2] == 0xB1 && mem[regs.pc-1] == 0x50) // Phasor1: lda ($50),y
+ && !((regs.pc-3) == 0x0895 && mem[regs.pc-3] == 0xAD) // Rescue Raiders v1.3,v1.5: lda $c000
+ )
+ return;
+
+ DWORD dwTime = GetTickCount() - dwLogKeyReadTickStart;
+
+ LogFileOutput("Time from emulation reboot until first $C000 access: %d msec\n", dwTime);
+
+ bLogKeyReadDone = true;
+}
+
+//---------------------------------------------------------------------------
+
+eApple2Type GetApple2Type(void)
+{
+ return g_Apple2Type;
+}
+
+void SetApple2Type(eApple2Type type)
+{
+ g_Apple2Type = type;
+ SetMainCpuDefault(type);
+}
+
+const UINT16* GetOldAppleWinVersion(void)
+{
+ return g_OldAppleWinVersion;
+}
+
+CardManager& GetCardMgr(void)
+{
+ static CardManager g_CardMgr; // singleton
+ return g_CardMgr;
+}
+
+//===========================================================================
+
+double Get6502BaseClock(void)
+{
+ return (GetVideoRefreshRate() == VR_50HZ) ? CLK_6502_PAL : CLK_6502_NTSC;
+}
+
+void SetCurrentCLK6502(void)
+{
+ static DWORD dwPrevSpeed = (DWORD) -1;
+ static VideoRefreshRate_e prevVideoRefreshRate = VR_NONE;
+
+ if (dwPrevSpeed == g_dwSpeed && GetVideoRefreshRate() == prevVideoRefreshRate)
+ return;
+
+ dwPrevSpeed = g_dwSpeed;
+ prevVideoRefreshRate = GetVideoRefreshRate();
+
+ // SPEED_MIN = 0 = 0.50 MHz
+ // SPEED_NORMAL = 10 = 1.00 MHz
+ // 20 = 2.00 MHz
+ // SPEED_MAX-1 = 39 = 3.90 MHz
+ // SPEED_MAX = 40 = ???? MHz (run full-speed, /g_fCurrentCLK6502/ is ignored)
+
+ if(g_dwSpeed < SPEED_NORMAL)
+ g_fMHz = 0.5 + (double)g_dwSpeed * 0.05;
+ else
+ g_fMHz = (double)g_dwSpeed / 10.0;
+
+ g_fCurrentCLK6502 = Get6502BaseClock() * g_fMHz;
+
+ //
+ // Now re-init modules that are dependent on /g_fCurrentCLK6502/
+ //
+
+ SpkrReinitialize();
+ MB_Reinitialize();
+}
+
+void UseClockMultiplier(double clockMultiplier)
+{
+ if (clockMultiplier == 0.0)
+ return;
+
+ if (clockMultiplier < 1.0)
+ {
+ if (clockMultiplier < 0.5)
+ clockMultiplier = 0.5;
+ g_dwSpeed = (ULONG)((clockMultiplier - 0.5) * 20); // [0.5..0.9] -> [0..9]
+ }
+ else
+ {
+ g_dwSpeed = (ULONG)(clockMultiplier * 10);
+ if (g_dwSpeed >= SPEED_MAX)
+ g_dwSpeed = SPEED_MAX - 1;
+ }
+
+ SetCurrentCLK6502();
+}
+
+void SetAppleWinVersion(UINT16 major, UINT16 minor, UINT16 fix, UINT16 fix_minor)
+{
+ g_AppleWinVersion[0] = major;
+ g_AppleWinVersion[1] = minor;
+ g_AppleWinVersion[2] = fix;
+ g_AppleWinVersion[3] = fix_minor;
+ StringCbPrintf(VERSIONSTRING, VERSIONSTRING_SIZE, "%d.%d.%d.%d", major, minor, fix, fix_minor);
+}
+
+bool CheckOldAppleWinVersion(void)
+{
+ TCHAR szOldAppleWinVersion[VERSIONSTRING_SIZE + 1];
+ RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, szOldAppleWinVersion, VERSIONSTRING_SIZE, TEXT(""));
+ const bool bShowAboutDlg = strcmp(szOldAppleWinVersion, VERSIONSTRING) != 0;
+
+ // version: xx.yy.zz.ww
+ char* p0 = szOldAppleWinVersion;
+ int len = strlen(szOldAppleWinVersion);
+ szOldAppleWinVersion[len] = '.'; // append a null terminator
+ szOldAppleWinVersion[len + 1] = '\0';
+ for (UINT i = 0; i < 4; i++)
+ {
+ char* p1 = strstr(p0, ".");
+ if (!p1)
+ break;
+ *p1 = 0;
+ g_OldAppleWinVersion[i] = atoi(p0);
+ p0 = p1 + 1;
+ }
+
+ return bShowAboutDlg;
+}
+
+bool SetCurrentImageDir(const std::string& pszImageDir)
+{
+ g_sCurrentDir = pszImageDir;
+
+ if (!g_sCurrentDir.empty() && *g_sCurrentDir.rbegin() != '\\')
+ g_sCurrentDir += '\\';
+
+ if (SetCurrentDirectory(g_sCurrentDir.c_str()))
+ return true;
+
+ return false;
+}
diff --git a/source/AppleWin.h b/source/Core.h
similarity index 70%
rename from source/AppleWin.h
rename to source/Core.h
index 18f12e8a..7eb8d34d 100644
--- a/source/AppleWin.h
+++ b/source/Core.h
@@ -1,17 +1,17 @@
#pragma once
#include "Card.h"
-#include "SaveState_Structs_common.h"
#include "Common.h"
void LogFileTimeUntilFirstKeyReadReset(void);
void LogFileTimeUntilFirstKeyRead(void);
-bool SetCurrentImageDir(const std::string & pszImageDir);
-
extern const UINT16* GetOldAppleWinVersion(void);
extern TCHAR VERSIONSTRING[]; // Constructed in WinMain()
+void SetAppleWinVersion(UINT16 major, UINT16 minor, UINT16 fix, UINT16 fix_minor);
+bool CheckOldAppleWinVersion(void);
+
extern std::string g_pAppTitle;
extern eApple2Type g_Apple2Type;
@@ -21,25 +21,25 @@ void SetApple2Type(eApple2Type type);
double Get6502BaseClock(void);
void SetCurrentCLK6502(void);
-void SingleStep(bool bReinit);
+// set g_dwSpeed =
+// | clockMultiplier == 0 => unchanged
+// | clockMultiplier < 1 => (max(0.5, clockMultiplier) - 0.5) * 20
+// | else => min(SPEED_MAX - 1, clockMultiplier * 10)
+void UseClockMultiplier(double clockMultiplier);
extern bool g_bFullSpeed;
//===========================================
-// Win32
-extern HINSTANCE g_hInstance;
-
extern AppMode_e g_nAppMode;
-bool GetLoadedSaveStateFlag(void);
-void SetLoadedSaveStateFlag(const bool bFlag);
-bool GetHookAltGrControl(void);
+extern std::string g_sStartDir;
extern std::string g_sProgramDir;
extern std::string g_sCurrentDir;
+bool SetCurrentImageDir(const std::string& pszImageDir);
+
extern bool g_bRestart;
-extern bool g_bRestartFullScreen;
extern DWORD g_dwSpeed;
extern double g_fCurrentCLK6502;
@@ -47,25 +47,27 @@ extern double g_fCurrentCLK6502;
extern int g_nCpuCyclesFeedback;
extern DWORD g_dwCyclesThisFrame;
-extern bool g_bDisableDirectInput; // Cmd line switch: don't init DI (so no DIMouse support)
-extern bool g_bDisableDirectSound; // Cmd line switch: don't init DS (so no MB/Speaker support)
-extern bool g_bDisableDirectSoundMockingboard; // Cmd line switch: don't init MB support
extern int g_nMemoryClearType; // Cmd line switch: use specific MIP (Memory Initialization Pattern)
extern class CardManager& GetCardMgr(void);
extern class SynchronousEventManager g_SynchronousEventMgr;
-extern HANDLE g_hCustomRomF8; // INVALID_HANDLE_VALUE if no custom F8 rom
-extern HANDLE g_hCustomRom; // INVALID_HANDLE_VALUE if no custom rom
+extern HANDLE g_hCustomRomF8; // INVALID_HANDLE_VALUE if no custom F8 rom
+extern bool g_bCustomRomF8Failed; // Set if custom F8 ROM file failed
+extern HANDLE g_hCustomRom; // INVALID_HANDLE_VALUE if no custom rom
+extern bool g_bCustomRomFailed; // Set if custom ROM file failed
+extern bool g_bEnableSpeech;
#ifdef USE_SPEECH_API
class CSpeech;
extern CSpeech g_Speech;
#endif
-extern __interface IPropertySheet& sg_PropertySheet;
+extern bool g_bDisableDirectInput; // Cmd line switch: don't init DI (so no DIMouse support)
+extern bool g_bDisableDirectSound; // Cmd line switch: don't init DS (so no MB/Speaker support)
+extern bool g_bDisableDirectSoundMockingboard; // Cmd line switch: don't init MB support
-//
+extern __interface IPropertySheet& sg_PropertySheet;
//#define LOG_PERF_TIMINGS
#ifdef LOG_PERF_TIMINGS
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index 7a5566fd..4819a5a3 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -34,7 +34,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
#include "DebugDefs.h"
-#include "../AppleWin.h"
+#include "../Windows/AppleWin.h"
+#include "../Core.h"
#include "../CardManager.h"
#include "../CPU.h"
#include "../Disk.h"
diff --git a/source/Debugger/Debugger_Assembler.cpp b/source/Debugger/Debugger_Assembler.cpp
index 653a0c26..34ce1db2 100644
--- a/source/Debugger/Debugger_Assembler.cpp
+++ b/source/Debugger/Debugger_Assembler.cpp
@@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../CPU.h"
#include "../Memory.h"
+#include "../Windows/WinFrame.h"
#define DEBUG_ASSEMBLER 0
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index cdc391ec..f2ac73f4 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -32,7 +32,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
#include "Debugger_Display.h"
-#include "../AppleWin.h"
+#include "../Windows/AppleWin.h"
+#include "../Core.h"
#include "../CPU.h"
#include "../Frame.h"
#include "../Windows/WinFrame.h"
diff --git a/source/Debugger/Debugger_Help.cpp b/source/Debugger/Debugger_Help.cpp
index c81bd20f..97e097bb 100644
--- a/source/Debugger/Debugger_Help.cpp
+++ b/source/Debugger/Debugger_Help.cpp
@@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
-#include "../AppleWin.h"
+#include "../Core.h"
#define DEBUG_COLOR_CONSOLE 0
diff --git a/source/Debugger/Debugger_Symbols.cpp b/source/Debugger/Debugger_Symbols.cpp
index 5f5e0160..a168d6cd 100644
--- a/source/Debugger/Debugger_Symbols.cpp
+++ b/source/Debugger/Debugger_Symbols.cpp
@@ -30,7 +30,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
-#include "../AppleWin.h"
+#include "../Windows/AppleWin.h"
+#include "../Core.h"
// 2.6.2.13 Added: Can now enable/disable selected symbol table(s) !
// Allow the user to disable/enable symbol tables
diff --git a/source/Disk.cpp b/source/Disk.cpp
index 7090a0d2..329848d8 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -34,7 +34,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SaveState_Structs_v1.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
+#include "Core.h"
#include "CPU.h"
#include "DiskImage.h"
#include "Log.h"
diff --git a/source/Disk2CardManager.cpp b/source/Disk2CardManager.cpp
index 11122242..0139bbbe 100644
--- a/source/Disk2CardManager.cpp
+++ b/source/Disk2CardManager.cpp
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Disk2CardManager.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CardManager.h"
#include "Disk.h"
diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp
index 5dbe3b2a..202725d7 100644
--- a/source/DiskImageHelper.cpp
+++ b/source/DiskImageHelper.cpp
@@ -28,6 +28,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
+#include "Core.h"
#include "DiskImageHelper.h"
#include "Common.h"
@@ -2199,8 +2200,6 @@ UINT CHardDiskImageHelper::GetMinDetectSize(const UINT uImageSize, bool* pTempDe
#define ASSERT_OFFSET(x, offset) _ASSERT( ((BYTE*)&pWOZ->x - (BYTE*)pWOZ) == offset )
-extern TCHAR VERSIONSTRING[]; // AppleWin.h
-
BYTE* CWOZHelper::CreateEmptyDisk(DWORD& size)
{
WOZEmptyImage525* pWOZ = new WOZEmptyImage525;
diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp
index 1c6bb4a2..0631ba01 100644
--- a/source/Harddisk.cpp
+++ b/source/Harddisk.cpp
@@ -29,7 +29,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Harddisk.h"
-#include "AppleWin.h"
+#include "Core.h"
+#include "Windows/AppleWin.h"
#include "CardManager.h"
#include "CPU.h"
#include "DiskImage.h" // ImageError_e, Disk_Status_e
diff --git a/source/Joystick.cpp b/source/Joystick.cpp
index 7441c288..ee65b5d5 100644
--- a/source/Joystick.cpp
+++ b/source/Joystick.cpp
@@ -40,7 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Joystick.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
#include "CPU.h"
#include "Memory.h"
#include "YamlHelper.h"
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index dd81c9b6..bb814f52 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -29,7 +29,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Keyboard.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
+#include "Core.h"
#include "Windows/WinFrame.h"
#include "Pravets.h"
#include "Tape.h"
diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp
index 15efb773..a362e8df 100644
--- a/source/LanguageCard.cpp
+++ b/source/LanguageCard.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "LanguageCard.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CPU.h" // GH#700
#include "Log.h"
#include "Memory.h"
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 88df89da..cbfe9918 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Memory.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CardManager.h"
#include "CPU.h"
#include "Disk.h"
diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp
index 8a152905..0f6daa0a 100644
--- a/source/Mockingboard.cpp
+++ b/source/Mockingboard.cpp
@@ -80,7 +80,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Mockingboard.h"
#include "SaveState_Structs_v1.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CardManager.h"
#include "CPU.h"
#include "Log.h"
diff --git a/source/MouseInterface.cpp b/source/MouseInterface.cpp
index b1725b22..95ef2956 100644
--- a/source/MouseInterface.cpp
+++ b/source/MouseInterface.cpp
@@ -46,7 +46,7 @@ Etc.
#include "SaveState_Structs_common.h"
#include "Common.h"
-#include "AppleWin.h" // g_SynchronousEventMgr
+#include "Core.h" // g_SynchronousEventMgr
#include "CardManager.h"
#include "CPU.h"
#include "Windows/WinFrame.h" // FrameSetCursorPosByMousePos()
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index c96aa418..f54d3537 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Includes
#include "StdAfx.h"
#include "NTSC.h"
- #include "AppleWin.h"
+ #include "Core.h"
#include "CPU.h" // CpuGetCyclesThisVideoFrame()
#include "Frame.h"
#include "Memory.h" // MemGetMainPtr(), MemGetAuxPtr(), MemGetAnnunciator()
diff --git a/source/NTSC_CharSet.cpp b/source/NTSC_CharSet.cpp
index 745c1032..70be74c1 100644
--- a/source/NTSC_CharSet.cpp
+++ b/source/NTSC_CharSet.cpp
@@ -21,7 +21,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "NTSC_CharSet.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
+#include "Core.h"
#include "../resource/resource.h"
#include "Video.h"
diff --git a/source/ParallelPrinter.cpp b/source/ParallelPrinter.cpp
index 6c1b90bd..49ab174e 100644
--- a/source/ParallelPrinter.cpp
+++ b/source/ParallelPrinter.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "ParallelPrinter.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "Memory.h"
#include "Registry.h"
#include "YamlHelper.h"
diff --git a/source/Pravets.cpp b/source/Pravets.cpp
index 0e65f2c8..70f97f1d 100644
--- a/source/Pravets.cpp
+++ b/source/Pravets.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Pravets.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "Windows/WinFrame.h"
#include "Keyboard.h"
#include "Tape.h"
diff --git a/source/Registry.cpp b/source/Registry.cpp
index 59ea7483..f543bea0 100644
--- a/source/Registry.cpp
+++ b/source/Registry.cpp
@@ -29,8 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Registry.h"
-
-extern std::string g_sConfigFile;
+#include "CmdLine.h"
namespace _ini {
//===========================================================================
diff --git a/source/SAM.cpp b/source/SAM.cpp
index 19b684a8..8394d3b5 100644
--- a/source/SAM.cpp
+++ b/source/SAM.cpp
@@ -33,7 +33,6 @@
#include "StdAfx.h"
#include "SAM.h"
-#include "AppleWin.h"
#include "Memory.h"
#include "Speaker.h"
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index d339d870..311565cb 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SaveState.h"
#include "YamlHelper.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
#include "CardManager.h"
#include "CPU.h"
#include "Debug.h"
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index 6ded02ad..0f00c546 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -36,7 +36,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "SerialComms.h"
-#include "AppleWin.h"
#include "CPU.h"
#include "Windows/WinFrame.h"
#include "Log.h"
diff --git a/source/SoundCore.cpp b/source/SoundCore.cpp
index 5209ee4c..2f224e82 100644
--- a/source/SoundCore.cpp
+++ b/source/SoundCore.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "SoundCore.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "Windows/WinFrame.h"
#include "Log.h"
#include "Speaker.h"
diff --git a/source/Speaker.cpp b/source/Speaker.cpp
index 8f0ec69f..2d8740ef 100644
--- a/source/Speaker.cpp
+++ b/source/Speaker.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Speaker.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CPU.h"
#include "Windows/WinFrame.h"
#include "Log.h"
diff --git a/source/SynchronousEventManager.cpp b/source/SynchronousEventManager.cpp
index ceba4a9b..3ad1dfeb 100644
--- a/source/SynchronousEventManager.cpp
+++ b/source/SynchronousEventManager.cpp
@@ -42,7 +42,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "SynchronousEventManager.h"
-#include "AppleWin.h"
void SynchronousEventManager::Insert(SyncEvent* pNewEvent)
{
diff --git a/source/Tape.cpp b/source/Tape.cpp
index f597ef7c..930f2b5b 100644
--- a/source/Tape.cpp
+++ b/source/Tape.cpp
@@ -32,7 +32,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Tape.h"
-#include "AppleWin.h"
#include "Keyboard.h"
#include "Memory.h"
#include "Pravets.h"
diff --git a/source/Utilities.cpp b/source/Utilities.cpp
new file mode 100644
index 00000000..b9ece845
--- /dev/null
+++ b/source/Utilities.cpp
@@ -0,0 +1,455 @@
+/*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
+
+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: main
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "Utilities.h"
+#include "Core.h"
+#include "CardManager.h"
+#include "CPU.h"
+#include "Video.h"
+#include "Joystick.h"
+#include "Log.h"
+#include "Mockingboard.h"
+#include "MouseInterface.h"
+#include "ParallelPrinter.h"
+#include "Registry.h"
+#include "Riff.h"
+#include "SaveState.h"
+#include "SerialComms.h"
+#include "Speaker.h"
+#include "Mockingboard.h"
+#include "Windows/WinFrame.h"
+
+#include "Configuration/PropertySheet.h"
+#include "Tfe/Tfe.h"
+
+// Backwards compatibility with AppleWin <1.24.0
+static void LoadConfigOldJoystick_v1(const UINT uJoyNum)
+{
+ DWORD dwOldJoyType;
+ if (!REGLOAD(TEXT(uJoyNum==0 ? REGVALUE_OLD_JOYSTICK0_EMU_TYPE1 : REGVALUE_OLD_JOYSTICK1_EMU_TYPE1), &dwOldJoyType))
+ return; // EG. Old AppleWin never installed
+
+ UINT uNewJoyType;
+ switch (dwOldJoyType)
+ {
+ case 0: // Disabled
+ default:
+ uNewJoyType = J0C_DISABLED;
+ break;
+ case 1: // PC Joystick
+ uNewJoyType = J0C_JOYSTICK1;
+ break;
+ case 2: // Keyboard (standard)
+ uNewJoyType = J0C_KEYBD_NUMPAD;
+ sg_PropertySheet.SetJoystickCenteringControl(JOYSTICK_MODE_FLOATING);
+ break;
+ case 3: // Keyboard (centering)
+ uNewJoyType = J0C_KEYBD_NUMPAD;
+ sg_PropertySheet.SetJoystickCenteringControl(JOYSTICK_MODE_CENTERING);
+ break;
+ case 4: // Mouse
+ uNewJoyType = J0C_MOUSE;
+ break;
+ }
+
+ JoySetJoyType(uJoyNum, uNewJoyType);
+}
+
+//Reads configuration from the registry entries
+void LoadConfiguration(void)
+{
+ DWORD dwComputerType = 0;
+ eApple2Type apple2Type = A2TYPE_APPLE2EENHANCED;
+
+ if (REGLOAD(TEXT(REGVALUE_APPLE2_TYPE), &dwComputerType))
+ {
+ const DWORD dwLoadedComputerType = dwComputerType;
+
+ if ( (dwComputerType >= A2TYPE_MAX) ||
+ (dwComputerType >= A2TYPE_UNDEFINED && dwComputerType < A2TYPE_CLONE) ||
+ (dwComputerType >= A2TYPE_CLONE_A2_MAX && dwComputerType < A2TYPE_CLONE_A2E) )
+ dwComputerType = A2TYPE_APPLE2EENHANCED;
+
+ // Remap the bad Pravets models (before AppleWin v1.26)
+ if (dwComputerType == A2TYPE_BAD_PRAVETS82) dwComputerType = A2TYPE_PRAVETS82;
+ if (dwComputerType == A2TYPE_BAD_PRAVETS8M) dwComputerType = A2TYPE_PRAVETS8M;
+
+ // Remap the bad Pravets models (at AppleWin v1.26) - GH#415
+ if (dwComputerType == A2TYPE_CLONE) dwComputerType = A2TYPE_PRAVETS82;
+
+ if (dwLoadedComputerType != dwComputerType)
+ {
+ char sText[100];
+ StringCbPrintf(sText, sizeof(sText), "Unsupported Apple2Type(%d). Changing to %d", dwLoadedComputerType, dwComputerType);
+
+ LogFileOutput("%s\n", sText);
+
+ MessageBox(
+ GetDesktopWindow(), // NB. g_hFrameWindow is not yet valid
+ sText,
+ "Load Configuration",
+ MB_ICONSTOP | MB_SETFOREGROUND);
+
+ sg_PropertySheet.ConfigSaveApple2Type((eApple2Type)dwComputerType);
+ }
+
+ apple2Type = (eApple2Type) dwComputerType;
+ }
+ else if (REGLOAD(TEXT(REGVALUE_OLD_APPLE2_TYPE), &dwComputerType)) // Support older AppleWin registry entries
+ {
+ switch (dwComputerType)
+ {
+ // NB. No A2TYPE_APPLE2E (this is correct)
+ case 0: apple2Type = A2TYPE_APPLE2; break;
+ case 1: apple2Type = A2TYPE_APPLE2PLUS; break;
+ case 2: apple2Type = A2TYPE_APPLE2EENHANCED; break;
+ default: apple2Type = A2TYPE_APPLE2EENHANCED; break;
+ }
+ }
+
+ SetApple2Type(apple2Type);
+
+ //
+
+ DWORD dwMainCpuType;
+ REGLOAD_DEFAULT(TEXT(REGVALUE_CPU_TYPE), &dwMainCpuType, CPU_65C02);
+ if (dwMainCpuType != CPU_6502 && dwMainCpuType != CPU_65C02)
+ dwMainCpuType = CPU_65C02;
+ SetMainCpu((eCpuType)dwMainCpuType);
+
+ //
+
+ DWORD dwJoyType;
+ if (REGLOAD(TEXT(REGVALUE_JOYSTICK0_EMU_TYPE), &dwJoyType))
+ JoySetJoyType(JN_JOYSTICK0, dwJoyType);
+ else if (REGLOAD(TEXT(REGVALUE_OLD_JOYSTICK0_EMU_TYPE2), &dwJoyType)) // GH#434
+ JoySetJoyType(JN_JOYSTICK0, dwJoyType);
+ else
+ LoadConfigOldJoystick_v1(JN_JOYSTICK0);
+
+ if (REGLOAD(TEXT(REGVALUE_JOYSTICK1_EMU_TYPE), &dwJoyType))
+ JoySetJoyType(JN_JOYSTICK1, dwJoyType);
+ else if (REGLOAD(TEXT(REGVALUE_OLD_JOYSTICK1_EMU_TYPE2), &dwJoyType)) // GH#434
+ JoySetJoyType(JN_JOYSTICK1, dwJoyType);
+ else
+ LoadConfigOldJoystick_v1(JN_JOYSTICK1);
+
+ DWORD dwSoundType;
+ REGLOAD_DEFAULT(TEXT(REGVALUE_SOUND_EMULATION), &dwSoundType, REG_SOUNDTYPE_WAVE);
+ switch (dwSoundType)
+ {
+ case REG_SOUNDTYPE_NONE:
+ case REG_SOUNDTYPE_DIRECT: // Not supported from 1.26
+ case REG_SOUNDTYPE_SMART: // Not supported from 1.26
+ default:
+ soundtype = SOUND_NONE;
+ break;
+ case REG_SOUNDTYPE_WAVE:
+ soundtype = SOUND_WAVE;
+ break;
+ }
+
+ TCHAR serialPortName[CSuperSerialCard::SIZEOF_SERIALCHOICE_ITEM];
+ if (RegLoadString(
+ TEXT(REG_CONFIG),
+ TEXT(REGVALUE_SERIAL_PORT_NAME),
+ TRUE,
+ serialPortName,
+ CSuperSerialCard::SIZEOF_SERIALCHOICE_ITEM))
+ {
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->SetSerialPortName(serialPortName);
+ }
+
+ REGLOAD_DEFAULT(TEXT(REGVALUE_EMULATION_SPEED), &g_dwSpeed, SPEED_NORMAL);
+ Config_Load_Video();
+ SetCurrentCLK6502(); // Pre: g_dwSpeed && Config_Load_Video()->SetVideoRefreshRate()
+
+ DWORD dwEnhanceDisk;
+ REGLOAD_DEFAULT(TEXT(REGVALUE_ENHANCE_DISK_SPEED), &dwEnhanceDisk, 1);
+ GetCardMgr().GetDisk2CardMgr().SetEnhanceDisk(dwEnhanceDisk ? true : false);
+
+ //
+
+ DWORD dwTmp = 0;
+
+ if(REGLOAD(TEXT(REGVALUE_FS_SHOW_SUBUNIT_STATUS), &dwTmp))
+ SetFullScreenShowSubunitStatus(dwTmp ? true : false);
+
+ if(REGLOAD(TEXT(REGVALUE_THE_FREEZES_F8_ROM), &dwTmp))
+ sg_PropertySheet.SetTheFreezesF8Rom(dwTmp);
+
+ if(REGLOAD(TEXT(REGVALUE_SPKR_VOLUME), &dwTmp))
+ SpkrSetVolume(dwTmp, sg_PropertySheet.GetVolumeMax());
+
+ if(REGLOAD(TEXT(REGVALUE_MB_VOLUME), &dwTmp))
+ MB_SetVolume(dwTmp, sg_PropertySheet.GetVolumeMax());
+
+ if(REGLOAD(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), &dwTmp))
+ g_bSaveStateOnExit = dwTmp ? true : false;
+
+
+ if(REGLOAD(TEXT(REGVALUE_DUMP_TO_PRINTER), &dwTmp))
+ g_bDumpToPrinter = dwTmp ? true : false;
+
+ if(REGLOAD(TEXT(REGVALUE_CONVERT_ENCODING), &dwTmp))
+ g_bConvertEncoding = dwTmp ? true : false;
+
+ if(REGLOAD(TEXT(REGVALUE_FILTER_UNPRINTABLE), &dwTmp))
+ g_bFilterUnprintable = dwTmp ? true : false;
+
+ if(REGLOAD(TEXT(REGVALUE_PRINTER_APPEND), &dwTmp))
+ g_bPrinterAppend = dwTmp ? true : false;
+
+
+ if(REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp)) // TODO: Change to REGVALUE_SLOT7
+ HD_SetEnabled(dwTmp ? true : false);
+
+ if(REGLOAD(TEXT(REGVALUE_PDL_XTRIM), &dwTmp))
+ JoySetTrim((short)dwTmp, true);
+ if(REGLOAD(TEXT(REGVALUE_PDL_YTRIM), &dwTmp))
+ JoySetTrim((short)dwTmp, false);
+
+ if(REGLOAD(TEXT(REGVALUE_SCROLLLOCK_TOGGLE), &dwTmp))
+ sg_PropertySheet.SetScrollLockToggle(dwTmp);
+
+ if(REGLOAD(TEXT(REGVALUE_CURSOR_CONTROL), &dwTmp))
+ sg_PropertySheet.SetJoystickCursorControl(dwTmp);
+ if(REGLOAD(TEXT(REGVALUE_AUTOFIRE), &dwTmp))
+ sg_PropertySheet.SetAutofire(dwTmp);
+ if(REGLOAD(TEXT(REGVALUE_SWAP_BUTTONS_0_AND_1), &dwTmp))
+ sg_PropertySheet.SetButtonsSwapState(dwTmp ? true : false);
+ if(REGLOAD(TEXT(REGVALUE_CENTERING_CONTROL), &dwTmp))
+ sg_PropertySheet.SetJoystickCenteringControl(dwTmp);
+
+ if(REGLOAD(TEXT(REGVALUE_MOUSE_CROSSHAIR), &dwTmp))
+ sg_PropertySheet.SetMouseShowCrosshair(dwTmp);
+ if(REGLOAD(TEXT(REGVALUE_MOUSE_RESTRICT_TO_WINDOW), &dwTmp))
+ sg_PropertySheet.SetMouseRestrictToWindow(dwTmp);
+
+ if(REGLOAD(TEXT(REGVALUE_SLOT4), &dwTmp))
+ GetCardMgr().Insert(4, (SS_CARDTYPE)dwTmp);
+ if(REGLOAD(TEXT(REGVALUE_SLOT5), &dwTmp))
+ GetCardMgr().Insert(5, (SS_CARDTYPE)dwTmp);
+
+ //
+
+ TCHAR szFilename[MAX_PATH];
+
+ // Load save-state pathname *before* inserting any harddisk/disk images (for both init & reinit cases)
+ // NB. inserting harddisk/disk can change snapshot pathname
+ RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_SAVESTATE_FILENAME), 1, szFilename, MAX_PATH, TEXT("")); // Can be pathname or just filename
+ Snapshot_SetFilename(szFilename); // If not in Registry than default will be used (ie. g_sCurrentDir + default filename)
+
+ //
+
+ RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_HDV_START_DIR), 1, szFilename, MAX_PATH, TEXT(""));
+ 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 their disk images
+ RegLoadString(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_START_DIR), 1, szFilename, MAX_PATH, TEXT(""));
+ if (szFilename[0] == '\0')
+ GetCurrentDirectory(sizeof(szFilename), szFilename);
+ SetCurrentImageDir(szFilename);
+
+ GetCardMgr().GetDisk2CardMgr().LoadLastDiskImage();
+
+ //
+
+ DWORD dwTfeEnabled;
+ REGLOAD_DEFAULT(TEXT(REGVALUE_UTHERNET_ACTIVE), &dwTfeEnabled, 0);
+ tfe_enabled = dwTfeEnabled ? 1 : 0;
+
+ RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_UTHERNET_INTERFACE), 1, szFilename, MAX_PATH, TEXT(""));
+ update_tfe_interface(szFilename, NULL);
+
+ //
+
+ RegLoadString(TEXT(REG_CONFIG), TEXT(REGVALUE_PRINTER_FILENAME), 1, szFilename, MAX_PATH, TEXT(""));
+ Printer_SetFilename(szFilename); // If not in Registry than default will be used
+
+ REGLOAD_DEFAULT(TEXT(REGVALUE_PRINTER_IDLE_LIMIT), &dwTmp, 10);
+ Printer_SetIdleLimit(dwTmp);
+
+ if (REGLOAD(TEXT(REGVALUE_WINDOW_SCALE), &dwTmp))
+ SetViewportScale(dwTmp);
+
+ if (REGLOAD(TEXT(REGVALUE_CONFIRM_REBOOT), &dwTmp))
+ g_bConfirmReboot = dwTmp;
+}
+
+static std::string GetFullPath(LPCSTR szFileName)
+{
+ std::string strPathName;
+
+ if (szFileName[0] == '\\' || szFileName[1] == ':')
+ {
+ // Abs pathname
+ strPathName = szFileName;
+ }
+ else
+ {
+ // Rel pathname (GH#663)
+ strPathName = g_sStartDir;
+ strPathName.append(szFileName);
+ }
+
+ return strPathName;
+}
+
+static void SetCurrentDir(std::string pathname)
+{
+ // Due to the order HDDs/disks are inserted, then s7 insertions take priority over s6 & s5; and d2 takes priority over d1:
+ // . if -s6[dN] and -hN are specified, then g_sCurrentDir will be set to the HDD image's path
+ // . if -s5[dN] and -s6[dN] are specified, then g_sCurrentDir will be set to the s6 image's path
+ // . if -[sN]d1 and -[sN]d2 are specified, then g_sCurrentDir will be set to the d2 image's path
+ // This is purely dependent on the current order of InsertFloppyDisks() & InsertHardDisks() - ie. very brittle!
+ // . better to use -current-dir to be explicit
+ std::size_t found = pathname.find_last_of("\\");
+ std::string path = pathname.substr(0, found);
+ SetCurrentImageDir(path);
+}
+
+bool DoDiskInsert(const UINT slot, const int nDrive, LPCSTR szFileName)
+{
+ Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(slot));
+
+ if (szFileName[0] == '\0')
+ {
+ disk2Card.EjectDisk(nDrive);
+ return true;
+ }
+
+ std::string strPathName = GetFullPath(szFileName);
+ if (strPathName.empty()) return false;
+
+ ImageError_e Error = disk2Card.InsertDisk(nDrive, strPathName.c_str(), IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
+ bool res = (Error == eIMAGE_ERROR_NONE);
+ if (res)
+ SetCurrentDir(strPathName);
+ return res;
+}
+
+bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName)
+{
+ if (szFileName[0] == '\0')
+ {
+ HD_Unplug(nDrive);
+ return true;
+ }
+
+ std::string strPathName = GetFullPath(szFileName);
+ if (strPathName.empty()) return false;
+
+ BOOL bRes = HD_Insert(nDrive, strPathName.c_str());
+ bool res = (bRes == TRUE);
+ if (res)
+ SetCurrentDir(strPathName);
+ return res;
+}
+
+void InsertFloppyDisks(const UINT slot, LPSTR szImageName_drive[NUM_DRIVES], bool& bBoot)
+{
+ _ASSERT(slot == 5 || slot == 6);
+
+ if (!szImageName_drive[DRIVE_1] && !szImageName_drive[DRIVE_2])
+ return;
+
+ bool bRes = true;
+
+ if (szImageName_drive[DRIVE_1])
+ {
+ bRes = DoDiskInsert(slot, DRIVE_1, szImageName_drive[DRIVE_1]);
+ LogFileOutput("Init: S%d, DoDiskInsert(D1), res=%d\n", slot, bRes);
+ FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES); // floppy activity LEDs and floppy buttons
+ bBoot = true;
+ }
+
+ if (szImageName_drive[DRIVE_2])
+ {
+ bRes |= DoDiskInsert(slot, DRIVE_2, szImageName_drive[DRIVE_2]);
+ LogFileOutput("Init: S%d, DoDiskInsert(D2), res=%d\n", slot, bRes);
+ }
+
+ if (!bRes)
+ MessageBox(g_hFrameWindow, "Failed to insert floppy disk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
+}
+
+void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot)
+{
+ if (!szImageName_harddisk[HARDDISK_1] && !szImageName_harddisk[HARDDISK_2])
+ return;
+
+ // Enable the Harddisk controller card
+
+ HD_SetEnabled(true);
+
+ DWORD dwTmp;
+ BOOL res = REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp);
+ if (!res || !dwTmp)
+ REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 1); // Config: HDD Enabled
+
+ //
+
+ bool bRes = true;
+
+ if (szImageName_harddisk[HARDDISK_1])
+ {
+ bRes = DoHardDiskInsert(HARDDISK_1, szImageName_harddisk[HARDDISK_1]);
+ LogFileOutput("Init: DoHardDiskInsert(HDD1), res=%d\n", bRes);
+ FrameRefreshStatus(DRAW_LEDS); // harddisk activity LED
+ bBoot = true;
+ }
+
+ if (szImageName_harddisk[HARDDISK_2])
+ {
+ bRes |= DoHardDiskInsert(HARDDISK_2, szImageName_harddisk[HARDDISK_2]);
+ LogFileOutput("Init: DoHardDiskInsert(HDD2), res=%d\n", bRes);
+ }
+
+ if (!bRes)
+ MessageBox(g_hFrameWindow, "Failed to insert harddisk(s) - see log file", "Warning", MB_ICONASTERISK | MB_OK);
+}
+
+void UnplugHardDiskControllerCard(void)
+{
+ HD_SetEnabled(false);
+
+ DWORD dwTmp;
+ BOOL res = REGLOAD(TEXT(REGVALUE_HDD_ENABLED), &dwTmp);
+ if (!res || dwTmp)
+ REGSAVE(TEXT(REGVALUE_HDD_ENABLED), 0); // Config: HDD Disabled
+}
diff --git a/source/Utilities.h b/source/Utilities.h
new file mode 100644
index 00000000..afeb6559
--- /dev/null
+++ b/source/Utilities.h
@@ -0,0 +1,12 @@
+#pragma once
+
+#include "Disk.h"
+#include "Harddisk.h"
+
+
+void LoadConfiguration();
+bool DoDiskInsert(const UINT slot, const int nDrive, LPCSTR szFileName);
+bool DoHardDiskInsert(const int nDrive, LPCSTR szFileName);
+void InsertFloppyDisks(const UINT slot, LPSTR szImageName_drive[NUM_DRIVES], bool& bBoot);
+void InsertHardDisks(LPSTR szImageName_harddisk[NUM_HARDDISKS], bool& bBoot);
+void UnplugHardDiskControllerCard(void);
diff --git a/source/Video.cpp b/source/Video.cpp
index 5dbe76d4..06f5024f 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Video.h"
-#include "AppleWin.h"
+#include "Core.h"
#include "CPU.h"
#include "Frame.h"
#include "Windows/WinFrame.h"
diff --git a/source/Windows/AppleWin.cpp b/source/Windows/AppleWin.cpp
new file mode 100644
index 00000000..91a66d7d
--- /dev/null
+++ b/source/Windows/AppleWin.cpp
@@ -0,0 +1,1048 @@
+/*
+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
+
+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: main
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "Windows/AppleWin.h"
+#include "Utilities.h"
+#include "CmdLine.h"
+#include "Debug.h"
+#include "Log.h"
+#include "Memory.h"
+#include "Mockingboard.h"
+#include "MouseInterface.h"
+#include "ParallelPrinter.h"
+#include "Registry.h"
+#include "Riff.h"
+#include "SaveState.h"
+#include "SoundCore.h"
+#include "Speaker.h"
+#ifdef USE_SPEECH_API
+#include "Speech.h"
+#endif
+#include "Windows/WinVideo.h"
+#include "Windows/WinFrame.h"
+#include "RGBMonitor.h"
+#include "NTSC.h"
+
+#include "Configuration/About.h"
+#include "Configuration/PropertySheet.h"
+#include "Tfe/Tfe.h"
+
+//=================================================
+
+// Win32
+HINSTANCE g_hInstance = (HINSTANCE)0;
+
+static bool g_bLoadedSaveState = false;
+static bool g_bSysClkOK = false;
+
+bool g_bRestartFullScreen = false;
+
+//===========================================================================
+
+bool GetLoadedSaveStateFlag(void)
+{
+ return g_bLoadedSaveState;
+}
+
+void SetLoadedSaveStateFlag(const bool bFlag)
+{
+ g_bLoadedSaveState = bFlag;
+}
+
+bool GetHookAltGrControl(void)
+{
+ return g_bHookAltGrControl;
+}
+
+static void ResetToLogoMode(void)
+{
+ g_nAppMode = MODE_LOGO;
+ SetLoadedSaveStateFlag(false);
+}
+
+//---------------------------------------------------------------------------
+
+static bool g_bPriorityNormal = true;
+
+// Make APPLEWIN process higher priority
+void SetPriorityAboveNormal(void)
+{
+ if (!g_bPriorityNormal)
+ return;
+
+ if ( SetPriorityClass(GetCurrentProcess(), ABOVE_NORMAL_PRIORITY_CLASS) )
+ {
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
+ g_bPriorityNormal = false;
+ }
+}
+
+// Make APPLEWIN process normal priority
+void SetPriorityNormal(void)
+{
+ if (g_bPriorityNormal)
+ return;
+
+ if ( SetPriorityClass(GetCurrentProcess(), NORMAL_PRIORITY_CLASS) )
+ {
+ SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
+ g_bPriorityNormal = true;
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static UINT g_uModeStepping_Cycles = 0;
+static bool g_uModeStepping_LastGetKey_ScrollLock = false;
+
+static void ContinueExecution(void)
+{
+#ifdef LOG_PERF_TIMINGS
+ PerfMarker* pPerfMarkerTotal = new PerfMarker(g_timeTotal);
+#endif
+
+ _ASSERT(g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING);
+
+ const double fUsecPerSec = 1.e6;
+#if 1
+ const UINT nExecutionPeriodUsec = 1000; // 1.0ms
+// const UINT nExecutionPeriodUsec = 100; // 0.1ms
+ const double fExecutionPeriodClks = g_fCurrentCLK6502 * ((double)nExecutionPeriodUsec / fUsecPerSec);
+#else
+ const double fExecutionPeriodClks = 1800.0;
+ const UINT nExecutionPeriodUsec = (UINT) (fUsecPerSec * (fExecutionPeriodClks / g_fCurrentCLK6502));
+#endif
+
+ //
+
+ bool bScrollLock_FullSpeed = false;
+ if (sg_PropertySheet.GetScrollLockToggle())
+ {
+ bScrollLock_FullSpeed = g_bScrollLock_FullSpeed;
+ }
+ else
+ {
+ if (g_nAppMode == MODE_RUNNING)
+ {
+ bScrollLock_FullSpeed = GetKeyState(VK_SCROLL) < 0;
+ }
+ else if (!IsDebugSteppingAtFullSpeed()) // Implicitly: MODE_STEPPING
+ {
+ // NB. For MODE_STEPPING: GetKeyState() is slow, so only call periodically
+ // . 0x3FFF is roughly the number of cycles in a video frame, which seems a reasonable rate to call GetKeyState()
+ if ((g_uModeStepping_Cycles & 0x3FFF) == 0)
+ g_uModeStepping_LastGetKey_ScrollLock = GetKeyState(VK_SCROLL) < 0;
+
+ bScrollLock_FullSpeed = g_uModeStepping_LastGetKey_ScrollLock;
+ }
+ }
+
+ const bool bWasFullSpeed = g_bFullSpeed;
+ g_bFullSpeed = (g_dwSpeed == SPEED_MAX) ||
+ bScrollLock_FullSpeed ||
+ (GetCardMgr().GetDisk2CardMgr().IsConditionForFullSpeed() && !Spkr_IsActive() && !MB_IsActive()) ||
+ IsDebugSteppingAtFullSpeed();
+
+ if (g_bFullSpeed)
+ {
+ if (!bWasFullSpeed)
+ VideoRedrawScreenDuringFullSpeed(0, true); // Init for full-speed mode
+
+ // Don't call Spkr_Mute() - will get speaker clicks
+ MB_Mute();
+ SysClk_StopTimer();
+#ifdef USE_SPEECH_API
+ g_Speech.Reset(); // TODO: Put this on a timer (in emulated cycles)... otherwise CATALOG cuts out
+#endif
+
+ g_nCpuCyclesFeedback = 0; // For the case when this is a big -ve number
+
+ // Switch to normal priority so that APPLEWIN process doesn't hog machine!
+ //. EG: No disk in Drive-1, and boot Apple: Windows will start to crawl!
+ SetPriorityNormal();
+ }
+ else
+ {
+ if (bWasFullSpeed)
+ VideoRedrawScreenAfterFullSpeed(g_dwCyclesThisFrame);
+
+ // Don't call Spkr_Demute()
+ MB_Demute();
+ SysClk_StartTimerUsec(nExecutionPeriodUsec);
+
+ // Switch to higher priority, eg. for audio (BUG #015394)
+ SetPriorityAboveNormal();
+ }
+
+ //
+
+ int nCyclesWithFeedback = (int) fExecutionPeriodClks + g_nCpuCyclesFeedback;
+ const UINT uCyclesToExecuteWithFeedback = (nCyclesWithFeedback >= 0) ? nCyclesWithFeedback
+ : 0;
+
+ const DWORD uCyclesToExecute = (g_nAppMode == MODE_RUNNING) ? uCyclesToExecuteWithFeedback
+ /* MODE_STEPPING */ : 0;
+
+ const bool bVideoUpdate = !g_bFullSpeed;
+ const DWORD uActualCyclesExecuted = CpuExecute(uCyclesToExecute, bVideoUpdate);
+ g_dwCyclesThisFrame += uActualCyclesExecuted;
+
+ GetCardMgr().GetDisk2CardMgr().UpdateDriveState(uActualCyclesExecuted);
+ JoyUpdateButtonLatch(nExecutionPeriodUsec); // Button latch time is independent of CPU clock frequency
+ PrintUpdate(uActualCyclesExecuted);
+ MB_PeriodicUpdate(uActualCyclesExecuted);
+
+ //
+
+ DWORD uSpkrActualCyclesExecuted = uActualCyclesExecuted;
+
+ bool bModeStepping_WaitTimer = false;
+ if (g_nAppMode == MODE_STEPPING && !IsDebugSteppingAtFullSpeed())
+ {
+ g_uModeStepping_Cycles += uActualCyclesExecuted;
+ if (g_uModeStepping_Cycles >= uCyclesToExecuteWithFeedback)
+ {
+ uSpkrActualCyclesExecuted = g_uModeStepping_Cycles;
+
+ g_uModeStepping_Cycles -= uCyclesToExecuteWithFeedback;
+ bModeStepping_WaitTimer = true;
+ }
+ }
+
+ // For MODE_STEPPING: do this speaker update periodically
+ // - Otherwise kills performance due to sound-buffer lock/unlock for every 6502 opcode!
+ if (g_nAppMode == MODE_RUNNING || bModeStepping_WaitTimer)
+ SpkrUpdate(uSpkrActualCyclesExecuted);
+
+ //
+
+ const UINT dwClksPerFrame = NTSC_GetCyclesPerFrame();
+ if (g_dwCyclesThisFrame >= dwClksPerFrame && !VideoGetVblBarEx(g_dwCyclesThisFrame))
+ {
+#ifdef LOG_PERF_TIMINGS
+ PerfMarker perfMarkerVideoRefresh(g_timeVideoRefresh);
+#endif
+ g_dwCyclesThisFrame -= dwClksPerFrame;
+
+ if (g_bFullSpeed)
+ VideoRedrawScreenDuringFullSpeed(g_dwCyclesThisFrame);
+ else
+ VideoRefreshScreen(); // Just copy the output of our Apple framebuffer to the system Back Buffer
+ }
+
+#ifdef LOG_PERF_TIMINGS
+ delete pPerfMarkerTotal; // Explicitly call dtor *before* SysClk_WaitTimer()
+#endif
+
+ if ((g_nAppMode == MODE_RUNNING && !g_bFullSpeed) || bModeStepping_WaitTimer)
+ {
+ SysClk_WaitTimer();
+ }
+}
+
+void SingleStep(bool bReinit)
+{
+ if (bReinit)
+ {
+ g_uModeStepping_Cycles = 0;
+ g_uModeStepping_LastGetKey_ScrollLock = false;
+ }
+
+ ContinueExecution();
+}
+
+//===========================================================================
+
+void EnterMessageLoop(void)
+{
+ MSG message;
+
+ PeekMessage(&message, NULL, 0, 0, PM_NOREMOVE);
+
+ while (message.message!=WM_QUIT)
+ {
+ if (PeekMessage(&message, NULL, 0, 0, PM_REMOVE))
+ {
+ TranslateMessage(&message);
+ DispatchMessage(&message);
+
+ while ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING))
+ {
+ if (PeekMessage(&message,0,0,0,PM_REMOVE))
+ {
+ if (message.message == WM_QUIT)
+ return;
+
+ TranslateMessage(&message);
+ DispatchMessage(&message);
+ }
+ else if (g_nAppMode == MODE_STEPPING)
+ {
+ DebugContinueStepping();
+ }
+ else
+ {
+ ContinueExecution();
+ if (g_nAppMode != MODE_DEBUG)
+ {
+ if (g_bFullSpeed)
+ ContinueExecution();
+ }
+ }
+ }
+ }
+ else
+ {
+ if (g_nAppMode == MODE_DEBUG)
+ DebuggerUpdate();
+ else if (g_nAppMode == MODE_PAUSED)
+ Sleep(1); // Stop process hogging CPU - 1ms, as need to fade-out speaker sound buffer
+ else if (g_nAppMode == MODE_LOGO)
+ Sleep(1); // Stop process hogging CPU (NB. don't delay for too long otherwise key input can be slow in other apps - GH#569)
+ }
+ }
+}
+
+//===========================================================================
+
+static void GetProgramDirectory(void)
+{
+ TCHAR programDir[MAX_PATH];
+ GetModuleFileName((HINSTANCE)0, programDir, MAX_PATH);
+ programDir[MAX_PATH-1] = 0;
+
+ g_sProgramDir = programDir;
+
+ int loop = g_sProgramDir.size();
+ while (loop--)
+ {
+ if ((g_sProgramDir[loop] == TEXT('\\')) || (g_sProgramDir[loop] == TEXT(':')))
+ {
+ g_sProgramDir.resize(loop + 1); // this reduces the size
+ break;
+ }
+ }
+}
+
+//===========================================================================
+
+void RegisterExtensions(void)
+{
+ TCHAR szCommandTmp[MAX_PATH];
+ GetModuleFileName((HMODULE)0,szCommandTmp,MAX_PATH);
+
+ TCHAR command[MAX_PATH];
+ wsprintf(command, "\"%s\"", szCommandTmp); // Wrap path & filename in quotes & null terminate
+
+ TCHAR icon[MAX_PATH];
+ wsprintf(icon,TEXT("%s,1"),(LPCTSTR)command);
+
+ _tcscat(command,TEXT(" \"%1\"")); // Append "%1"
+// _tcscat(command,TEXT("-d1 %1\"")); // Append "%1"
+// sprintf(command, "\"%s\" \"-d1 %%1\"", szCommandTmp); // Wrap path & filename in quotes & null terminate
+
+ // NB. Registry access to HKLM typically results in ErrorCode 5(ACCESS DENIED), as UAC requires elevated permissions (Run as administrator).
+ // . HKEY_CLASSES_ROOT\CLSID is a merged view of HKLM\SOFTWARE\Classes and HKCU\SOFTWARE\Classes
+
+ // NB. Reflect extensions in DELREG.INF
+// RegSetValue(HKEY_CLASSES_ROOT,".bin",REG_SZ,"DiskImage",0); // Removed as .bin is too generic
+
+ const char* pValueName = ".bin";
+ LSTATUS res = RegDeleteValue(HKEY_CLASSES_ROOT, pValueName);
+ if (res != NOERROR && res != ERROR_FILE_NOT_FOUND) LogFileOutput("RegDeleteValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = ".do";
+ res = RegSetValue(HKEY_CLASSES_ROOT, pValueName ,REG_SZ,"DiskImage",0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = ".dsk";
+ res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = ".nib";
+ res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = ".po";
+ res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = ".woz";
+ res = RegSetValue(HKEY_CLASSES_ROOT, pValueName, REG_SZ,"DiskImage",0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+// RegSetValue(HKEY_CLASSES_ROOT,".2mg",REG_SZ,"DiskImage",0); // Don't grab this, as not all .2mg images are supported (so defer to CiderPress)
+// RegSetValue(HKEY_CLASSES_ROOT,".2img",REG_SZ,"DiskImage",0); // Don't grab this, as not all .2mg images are supported (so defer to CiderPress)
+// RegSetValue(HKEY_CLASSES_ROOT,".aws.yaml",REG_SZ,"DiskImage",0); // NB. Can't grab this extension (even though it returns 0!) with embedded period (and .yaml is too generic) - GH#548
+// RegSetValue(HKEY_CLASSES_ROOT,".hdv",REG_SZ,"DiskImage",0); // TO DO
+
+ pValueName = "DiskImage";
+ res = RegSetValue(HKEY_CLASSES_ROOT,
+ pValueName,
+ REG_SZ,"Disk Image",0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = "DiskImage\\DefaultIcon";
+ res = RegSetValue(HKEY_CLASSES_ROOT,
+ pValueName,
+ REG_SZ,icon,0);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+// This key can interfere....
+// HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\FileExt\.dsk
+
+ pValueName = "DiskImage\\shell\\open\\command";
+ res = RegSetValue(HKEY_CLASSES_ROOT,
+ pValueName,
+ REG_SZ,command,_tcslen(command)+1);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = "DiskImage\\shell\\open\\ddeexec";
+ res = RegSetValue(HKEY_CLASSES_ROOT,
+ pValueName,
+ REG_SZ,"%1",3);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = "DiskImage\\shell\\open\\ddeexec\\application";
+ res = RegSetValue(HKEY_CLASSES_ROOT,
+ pValueName,
+ REG_SZ,"applewin",_tcslen("applewin")+1);
+// REG_SZ,szCommandTmp,_tcslen(szCommandTmp)+1);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+
+ pValueName = "DiskImage\\shell\\open\\ddeexec\\topic";
+ res = RegSetValue(HKEY_CLASSES_ROOT,
+ pValueName,
+ REG_SZ,"system",_tcslen("system")+1);
+ if (res != NOERROR) LogFileOutput("RegSetValue(%s) failed (0x%08X)\n", pValueName, res);
+}
+
+//===========================================================================
+
+// NB. On a restart, it's OK to call RegisterHotKey() again since the old g_hFrameWindow has been destroyed
+static void RegisterHotKeys(void)
+{
+ BOOL bStatus[3] = {0,0,0};
+
+ bStatus[0] = RegisterHotKey(
+ g_hFrameWindow , // HWND hWnd
+ VK_SNAPSHOT_560, // int id (user/custom id)
+ 0 , // UINT fsModifiers
+ VK_SNAPSHOT // UINT vk = PrintScreen
+ );
+
+ bStatus[1] = RegisterHotKey(
+ g_hFrameWindow , // HWND hWnd
+ VK_SNAPSHOT_280, // int id (user/custom id)
+ MOD_SHIFT , // UINT fsModifiers
+ VK_SNAPSHOT // UINT vk = PrintScreen
+ );
+
+ bStatus[2] = RegisterHotKey(
+ g_hFrameWindow , // HWND hWnd
+ VK_SNAPSHOT_TEXT, // int id (user/custom id)
+ MOD_CONTROL , // UINT fsModifiers
+ VK_SNAPSHOT // UINT vk = PrintScreen
+ );
+
+ if ((!bStatus[0] || !bStatus[1] || !bStatus[2]))
+ {
+ std::string msg("Unable to register for PrintScreen key(s):\n");
+
+ if (!bStatus[0])
+ msg += "\n. PrintScreen";
+ if (!bStatus[1])
+ msg += "\n. Shift+PrintScreen";
+ if (!bStatus[2])
+ msg += "\n. Ctrl+PrintScreen";
+
+ if (g_bShowPrintScreenWarningDialog)
+ MessageBox( g_hFrameWindow, msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK );
+
+ msg += "\n";
+ LogFileOutput(msg.c_str());
+ }
+}
+
+//---------------------------------------------------------------------------
+
+static HINSTANCE g_hinstDLL = 0;
+static HHOOK g_hhook = 0;
+
+static HANDLE g_hHookThread = NULL;
+static DWORD g_HookThreadId = 0;
+
+// Pre: g_hFrameWindow must be valid
+static bool HookFilterForKeyboard()
+{
+ g_hinstDLL = LoadLibrary(TEXT("HookFilter.dll"));
+
+ _ASSERT(g_hFrameWindow);
+
+ typedef void (*RegisterHWNDProc)(HWND, bool, bool);
+ RegisterHWNDProc RegisterHWND = (RegisterHWNDProc) GetProcAddress(g_hinstDLL, "RegisterHWND");
+ if (RegisterHWND)
+ RegisterHWND(g_hFrameWindow, g_bHookAltTab, g_bHookAltGrControl);
+
+ HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc");
+
+ g_hhook = SetWindowsHookEx(
+ WH_KEYBOARD_LL,
+ hkprcLowLevelKeyboardProc,
+ g_hinstDLL,
+ 0);
+
+ if (g_hhook != 0 && g_hFrameWindow != 0)
+ return true;
+
+ std::string msg("Failed to install hook filter for system keys");
+
+ DWORD dwErr = GetLastError();
+ MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
+
+ msg += "\n";
+ LogFileOutput(msg.c_str());
+ return false;
+}
+
+static void UnhookFilterForKeyboard()
+{
+ UnhookWindowsHookEx(g_hhook);
+ FreeLibrary(g_hinstDLL);
+}
+
+static DWORD WINAPI HookThread(LPVOID lpParameter)
+{
+ if (!HookFilterForKeyboard())
+ return -1;
+
+ MSG msg;
+ while(GetMessage(&msg, NULL, 0, 0) > 0)
+ {
+ if (msg.message == WM_QUIT)
+ break;
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ UnhookFilterForKeyboard();
+ return 0;
+}
+
+static bool InitHookThread()
+{
+ g_hHookThread = CreateThread(NULL, // lpThreadAttributes
+ 0, // dwStackSize
+ (LPTHREAD_START_ROUTINE) HookThread,
+ 0, // lpParameter
+ 0, // dwCreationFlags : 0 = Run immediately
+ &g_HookThreadId); // lpThreadId
+ if (g_hHookThread == NULL)
+ return false;
+
+ return true;
+}
+
+static void UninitHookThread()
+{
+ if (g_hHookThread)
+ {
+ if (!PostThreadMessage(g_HookThreadId, WM_QUIT, 0, 0))
+ {
+ _ASSERT(0);
+ return;
+ }
+
+ do
+ {
+ DWORD dwExitCode;
+ if (GetExitCodeThread(g_hHookThread, &dwExitCode))
+ {
+ if(dwExitCode == STILL_ACTIVE)
+ Sleep(10);
+ else
+ break;
+ }
+ }
+ while(1);
+
+ CloseHandle(g_hHookThread);
+ g_hHookThread = NULL;
+ g_HookThreadId = 0;
+ }
+}
+
+static void ExceptionHandler(const char* pError)
+{
+ MessageBox( g_hFrameWindow,
+ pError,
+ TEXT("Runtime Exception"),
+ MB_ICONEXCLAMATION | MB_SETFOREGROUND);
+
+ LogFileOutput("Runtime Exception: %s\n", pError);
+}
+
+//---------------------------------------------------------------------------
+
+static void GetAppleWinVersion(void);
+static void OneTimeInitialization(HINSTANCE passinstance);
+static void RepeatInitialization(void);
+static void Shutdown(void);
+
+int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
+{
+ char startDir[_MAX_PATH];
+ GetCurrentDirectory(sizeof(startDir), startDir);
+ g_sStartDir = startDir;
+ if (*(g_sStartDir.end()-1) != '\\') g_sStartDir += '\\';
+
+ if (!ProcessCmdLine(lpCmdLine))
+ return 0;
+
+ LogFileOutput("g_sStartDir = %s\n", g_sStartDir.c_str());
+ GetAppleWinVersion();
+ OneTimeInitialization(passinstance);
+
+ try
+ {
+ do
+ {
+ g_bRestart = false;
+
+ RepeatInitialization();
+
+ // ENTER THE MAIN MESSAGE LOOP
+ LogFileOutput("Main: EnterMessageLoop()\n");
+ EnterMessageLoop();
+ LogFileOutput("Main: LeaveMessageLoop()\n");
+
+ if (g_bRestart)
+ {
+ g_cmdLine.bSetFullScreen = g_bRestartFullScreen;
+ g_bRestartFullScreen = false;
+ }
+
+ MB_Reset();
+ LogFileOutput("Main: MB_Reset()\n");
+
+ CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard();
+ if (pMouseCard)
+ {
+ pMouseCard->Reset(); // Deassert any pending IRQs - GH#514
+ LogFileOutput("Main: CMouseInterface::Uninitialize()\n");
+ }
+
+ DSUninit();
+ LogFileOutput("Main: DSUninit()\n");
+
+ if (g_bRestart)
+ g_SynchronousEventMgr.Reset();
+
+ if (g_bHookSystemKey)
+ {
+ UninitHookThread();
+ LogFileOutput("Main: UnhookFilterForKeyboard()\n");
+ }
+ }
+ while (g_bRestart);
+ }
+ catch(std::runtime_error exception)
+ {
+ ExceptionHandler(exception.what());
+ }
+ catch(std::exception exception)
+ {
+ ExceptionHandler(exception.what());
+ }
+
+ Shutdown();
+ return 0;
+}
+
+static void GetAppleWinVersion(void)
+{
+ char szPath[_MAX_PATH];
+
+ if (0 == GetModuleFileName(NULL, szPath, sizeof(szPath)))
+ strcpy_s(szPath, sizeof(szPath), __argv[0]);
+
+ // Extract application version and store in a global variable
+ DWORD dwHandle, dwVerInfoSize;
+
+ dwVerInfoSize = GetFileVersionInfoSize(szPath, &dwHandle);
+
+ if (dwVerInfoSize > 0)
+ {
+ char* pVerInfoBlock = new char[dwVerInfoSize];
+
+ if (GetFileVersionInfo(szPath, NULL, dwVerInfoSize, pVerInfoBlock))
+ {
+ VS_FIXEDFILEINFO* pFixedFileInfo;
+ UINT pFixedFileInfoLen;
+
+ VerQueryValue(pVerInfoBlock, TEXT("\\"), (LPVOID*) &pFixedFileInfo, (PUINT) &pFixedFileInfoLen);
+
+ // Construct version string from fixed file info block
+
+ UINT16 major = pFixedFileInfo->dwFileVersionMS >> 16;
+ UINT16 minor = pFixedFileInfo->dwFileVersionMS & 0xffff;
+ UINT16 fix = pFixedFileInfo->dwFileVersionLS >> 16;
+ UINT16 fix_minor = pFixedFileInfo->dwFileVersionLS & 0xffff;
+ SetAppleWinVersion(major, minor, fix, fix_minor);
+ }
+
+ delete [] pVerInfoBlock;
+ }
+
+ LogFileOutput("AppleWin version: %s\n", VERSIONSTRING);
+}
+
+// DO ONE-TIME INITIALIZATION
+static void OneTimeInitialization(HINSTANCE passinstance)
+{
+#if 0
+#ifdef RIFF_SPKR
+ RiffInitWriteFile("Spkr.wav", SPKR_SAMPLE_RATE, 1);
+#endif
+#ifdef RIFF_MB
+ RiffInitWriteFile("Mockingboard.wav", 44100, 2);
+#endif
+#endif
+
+ // Initialize COM - so we can use CoCreateInstance
+ // . NB. DSInit() & DIMouse::DirectInputInit are done when g_hFrameWindow is created (WM_CREATE)
+ HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
+ LogFileOutput("Init: CoInitializeEx(), hr=0x%08X\n", hr);
+
+ g_bSysClkOK = SysClk_InitTimer();
+ LogFileOutput("Init: SysClk_InitTimer(), res=%d\n", g_bSysClkOK ? 1:0);
+#ifdef USE_SPEECH_API
+ if (g_bEnableSpeech)
+ {
+ const bool bSpeechOK = g_Speech.Init();
+ LogFileOutput("Init: SysClk_InitTimer(), res=%d\n", bSpeechOK ? 1:0);
+ }
+#endif
+#if 0
+ DDInit(); // For WaitForVerticalBlank()
+#endif
+
+ g_hInstance = passinstance;
+ GdiSetBatchLimit(512);
+ LogFileOutput("Init: GdiSetBatchLimit()\n");
+
+ GetProgramDirectory();
+ LogFileOutput("Init: GetProgramDirectory()\n");
+
+ if (g_bRegisterFileTypes)
+ {
+ RegisterExtensions();
+ LogFileOutput("Init: RegisterExtensions()\n");
+ }
+
+ FrameRegisterClass();
+ LogFileOutput("Init: FrameRegisterClass()\n");
+
+ ImageInitialize();
+ LogFileOutput("Init: ImageInitialize()\n");
+}
+
+// DO INITIALIZATION THAT MUST BE REPEATED FOR A RESTART
+static void RepeatInitialization(void)
+{
+ ResetToLogoMode();
+
+ // NB. g_OldAppleWinVersion needed by LoadConfiguration() -> Config_Load_Video()
+ const bool bShowAboutDlg = CheckOldAppleWinVersion(); // Post: g_OldAppleWinVersion
+
+ LoadConfiguration();
+ LogFileOutput("Main: LoadConfiguration()\n");
+
+ if (g_cmdLine.model != A2TYPE_MAX)
+ SetApple2Type(g_cmdLine.model);
+
+ RGB_SetVideocard(g_cmdLine.rgbCard, g_cmdLine.rgbCardForegroundColor, g_cmdLine.rgbCardBackgroundColor);
+
+ if (g_cmdLine.newVideoType >= 0)
+ {
+ SetVideoType( (VideoType_e)g_cmdLine.newVideoType );
+ g_cmdLine.newVideoType = -1; // Don't reapply after a restart
+ }
+ SetVideoStyle( (VideoStyle_e) ((GetVideoStyle() | g_cmdLine.newVideoStyleEnableMask) & ~g_cmdLine.newVideoStyleDisableMask) );
+
+ if (g_cmdLine.newVideoRefreshRate != VR_NONE)
+ {
+ SetVideoRefreshRate(g_cmdLine.newVideoRefreshRate);
+ g_cmdLine.newVideoRefreshRate = VR_NONE; // Don't reapply after a restart
+ SetCurrentCLK6502();
+ }
+
+ UseClockMultiplier(g_cmdLine.clockMultiplier);
+ g_cmdLine.clockMultiplier = 0.0;
+
+ // Apply the memory expansion switches after loading the Apple II machine type
+#ifdef RAMWORKS
+ if (g_cmdLine.uRamWorksExPages)
+ {
+ SetRamWorksMemorySize(g_cmdLine.uRamWorksExPages);
+ SetExpansionMemType(CT_RamWorksIII);
+ g_cmdLine.uRamWorksExPages = 0; // Don't reapply after a restart
+ }
+#endif
+ if (g_cmdLine.uSaturnBanks)
+ {
+ SetSaturnMemorySize(g_cmdLine.uSaturnBanks); // Set number of banks before constructing Saturn card
+ SetExpansionMemType(CT_Saturn128K);
+ g_cmdLine.uSaturnBanks = 0; // Don't reapply after a restart
+ }
+
+ if (g_cmdLine.bSlot0LanguageCard)
+ {
+ SetExpansionMemType(CT_LanguageCard);
+ g_cmdLine.bSlot0LanguageCard = false; // Don't reapply after a restart
+ }
+
+ if (g_cmdLine.bSwapButtons0and1)
+ {
+ sg_PropertySheet.SetButtonsSwapState(true);
+ // Reapply after a restart - TODO: grey-out the Config UI for "Swap 0/1" when this cmd line is passed in
+ }
+
+ DebugInitialize();
+ LogFileOutput("Main: DebugInitialize()\n");
+
+ JoyInitialize();
+ LogFileOutput("Main: JoyInitialize()\n");
+
+ WinVideoInitialize(); // g_pFramebufferinfo been created now
+ LogFileOutput("Main: VideoInitialize()\n");
+
+ LogFileOutput("Main: FrameCreateWindow() - pre\n");
+ FrameCreateWindow(); // g_hFrameWindow is now valid
+ LogFileOutput("Main: FrameCreateWindow() - post\n");
+
+ // Init palette color
+ VideoSwitchVideocardPalette(RGB_GetVideocard(), GetVideoType());
+
+ // Allow the 4 hardcoded slots to be configurated as empty
+ // NB. this state is not persisted to the Registry/conf.ini (just as '-s7 empty' isn't)
+ // TODO: support bSlotEmpty[] for slots: 0,4,5
+ if (g_cmdLine.bSlotEmpty[SLOT1])
+ GetCardMgr().Remove(SLOT1);
+ if (g_cmdLine.bSlotEmpty[SLOT2])
+ GetCardMgr().Remove(SLOT2);
+ if (g_cmdLine.bSlotEmpty[SLOT3])
+ GetCardMgr().Remove(SLOT3);
+ if (g_cmdLine.bSlotEmpty[SLOT6])
+ GetCardMgr().Remove(SLOT6);
+
+ if (g_cmdLine.slotInsert[SLOT5] != CT_Empty)
+ {
+ if (GetCardMgr().QuerySlot(SLOT4) == CT_MockingboardC && g_cmdLine.slotInsert[SLOT5] != CT_MockingboardC) // Currently MB occupies slot4+5 when enabled
+ {
+ GetCardMgr().Remove(SLOT4);
+ GetCardMgr().Remove(SLOT5);
+ }
+
+ GetCardMgr().Insert(SLOT5, g_cmdLine.slotInsert[SLOT5]);
+ }
+
+ // Pre: may need g_hFrameWindow for MessageBox errors
+ // Post: may enable HDD, required for MemInitialize()->MemInitializeIO()
+ {
+ bool temp = false;
+ InsertFloppyDisks(SLOT5, g_cmdLine.szImageName_drive[SLOT5], temp);
+ //g_cmdLine.szImageName_drive[SLOT5][DRIVE_1] = g_cmdLine.szImageName_drive[SLOT5][DRIVE_2] = NULL; // *Do* insert on a restart (since no way they could have changed)
+
+ InsertFloppyDisks(SLOT6, g_cmdLine.szImageName_drive[SLOT6], g_cmdLine.bBoot);
+ g_cmdLine.szImageName_drive[SLOT6][DRIVE_1] = g_cmdLine.szImageName_drive[SLOT6][DRIVE_2] = NULL; // Don't insert on a restart
+
+ InsertHardDisks(g_cmdLine.szImageName_harddisk, g_cmdLine.bBoot);
+ g_cmdLine.szImageName_harddisk[HARDDISK_1] = g_cmdLine.szImageName_harddisk[HARDDISK_2] = NULL; // Don't insert on a restart
+
+ if (g_cmdLine.bSlotEmpty[7])
+ {
+ HD_SetEnabled(false); // Disable HDD controller, but don't persist this to Registry/conf.ini (consistent with other '-sn empty' cmds)
+ Snapshot_UpdatePath(); // If save-state's filename is a harddisk, and the floppy is in the same path, then the filename won't be updated
+ }
+ }
+
+ // Set *after* InsertFloppyDisks() & InsertHardDisks(), which both update g_sCurrentDir
+ if (!g_cmdLine.strCurrentDir.empty())
+ SetCurrentImageDir(g_cmdLine.strCurrentDir);
+
+ if (g_cmdLine.bRemoveNoSlotClock)
+ MemRemoveNoSlotClock();
+
+ MemInitialize();
+ LogFileOutput("Main: MemInitialize()\n");
+
+ // Show About dialog after creating main window (need g_hFrameWindow)
+ if (bShowAboutDlg)
+ {
+ if (!AboutDlg())
+ g_cmdLine.bShutdown = true; // Close everything down
+ else
+ RegSaveString(TEXT(REG_CONFIG), TEXT(REGVALUE_VERSION), 1, VERSIONSTRING); // Only save version after user accepts license
+ }
+
+ if (g_bCapturePrintScreenKey)
+ {
+ RegisterHotKeys(); // needs valid g_hFrameWindow
+ LogFileOutput("Main: RegisterHotKeys()\n");
+ }
+
+ if (g_bHookSystemKey)
+ {
+ if (InitHookThread()) // needs valid g_hFrameWindow (for message pump)
+ LogFileOutput("Main: HookFilterForKeyboard()\n");
+ }
+
+ // Need to test if it's safe to call ResetMachineState(). In the meantime, just call Disk2Card's Reset():
+ GetCardMgr().GetDisk2CardMgr().Reset(true); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor
+ LogFileOutput("Main: DiskReset()\n");
+ HD_Reset(); // GH#515
+ LogFileOutput("Main: HDDReset()\n");
+
+ if (!g_bSysClkOK)
+ {
+ MessageBox(g_hFrameWindow, "DirectX failed to create SystemClock instance", TEXT("AppleWin Error"), MB_OK);
+ g_cmdLine.bShutdown = true;
+ }
+
+ if (g_bCustomRomF8Failed || g_bCustomRomFailed || (g_hCustomRomF8 != INVALID_HANDLE_VALUE && g_hCustomRom != INVALID_HANDLE_VALUE))
+ {
+ std::string msg = g_bCustomRomF8Failed ? "Failed to load custom F8 rom (not found or not exactly 2KiB)\n"
+ : g_bCustomRomFailed ? "Failed to load custom rom (not found or not exactly 12KiB or 16KiB)\n"
+ : "Unsupported -rom and -f8rom being used at the same time\n";
+
+ LogFileOutput("%s", msg.c_str());
+ MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
+ g_cmdLine.bShutdown = true;
+ }
+
+ tfe_init();
+ LogFileOutput("Main: tfe_init()\n");
+
+ if (g_cmdLine.szSnapshotName)
+ {
+ std::string strPathname(g_cmdLine.szSnapshotName);
+ int nIdx = strPathname.find_last_of('\\');
+ if (nIdx >= 0 && nIdx+1 < (int)strPathname.length()) // path exists?
+ {
+ const std::string strPath = strPathname.substr(0, nIdx+1);
+ SetCurrentImageDir(strPath);
+ }
+
+ // Override value just loaded from Registry by LoadConfiguration()
+ // . NB. Registry value is not updated with this cmd-line value
+ Snapshot_SetFilename(g_cmdLine.szSnapshotName);
+ Snapshot_LoadState();
+ g_cmdLine.bBoot = true;
+ g_cmdLine.szSnapshotName = NULL;
+ }
+ else
+ {
+ Snapshot_Startup(); // Do this after everything has been init'ed
+ LogFileOutput("Main: Snapshot_Startup()\n");
+ }
+
+ if (g_cmdLine.szScreenshotFilename)
+ {
+ Video_RedrawAndTakeScreenShot(g_cmdLine.szScreenshotFilename);
+ g_cmdLine.bShutdown = true;
+ }
+
+ if (g_cmdLine.bShutdown)
+ {
+ 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 (g_cmdLine.bSetFullScreen)
+ {
+ if (g_cmdLine.bestWidth && g_cmdLine.bestHeight)
+ {
+ DEVMODE devMode;
+ memset(&devMode, 0, sizeof(devMode));
+ devMode.dmSize = sizeof(devMode);
+ devMode.dmPelsWidth = g_cmdLine.bestWidth;
+ devMode.dmPelsHeight = g_cmdLine.bestHeight;
+ devMode.dmFields = DM_PELSWIDTH | DM_PELSHEIGHT;
+
+ DWORD dwFlags = 0;
+ LONG res = ChangeDisplaySettings(&devMode, dwFlags);
+ if (res == 0)
+ g_cmdLine.bChangedDisplayResolution = true;
+ }
+
+ PostMessage(g_hFrameWindow, WM_USER_FULLSCREEN, 0, 0);
+ g_cmdLine.bSetFullScreen = false;
+ }
+
+ if (g_cmdLine.bBoot)
+ {
+ PostMessage(g_hFrameWindow, WM_USER_BOOT, 0, 0);
+ g_cmdLine.bBoot = false;
+ }
+ }
+}
+
+static void Shutdown(void)
+{
+ if (g_cmdLine.bChangedDisplayResolution)
+ ChangeDisplaySettings(NULL, 0); // restore default
+
+ // Release COM
+ DDUninit();
+ SysClk_UninitTimer();
+ LogFileOutput("Exit: SysClk_UninitTimer()\n");
+
+ CoUninitialize();
+ LogFileOutput("Exit: CoUninitialize()\n");
+
+ tfe_shutdown();
+ LogFileOutput("Exit: tfe_shutdown()\n");
+
+ LogDone();
+
+ RiffFinishWriteFile();
+
+ if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
+ CloseHandle(g_hCustomRomF8);
+
+ if (g_hCustomRom != INVALID_HANDLE_VALUE)
+ CloseHandle(g_hCustomRom);
+
+ if (g_cmdLine.bSlot7EmptyOnExit)
+ UnplugHardDiskControllerCard();
+}
diff --git a/source/Windows/AppleWin.h b/source/Windows/AppleWin.h
new file mode 100644
index 00000000..cc05e0e9
--- /dev/null
+++ b/source/Windows/AppleWin.h
@@ -0,0 +1,14 @@
+#pragma once
+
+void SingleStep(bool bReinit);
+
+//===========================================
+
+// Win32
+extern HINSTANCE g_hInstance;
+
+bool GetLoadedSaveStateFlag(void);
+void SetLoadedSaveStateFlag(const bool bFlag);
+bool GetHookAltGrControl(void);
+
+extern bool g_bRestartFullScreen;
diff --git a/source/Windows/WinFrame.cpp b/source/Windows/WinFrame.cpp
index 5911eb59..de26836d 100644
--- a/source/Windows/WinFrame.cpp
+++ b/source/Windows/WinFrame.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Windows/WinFrame.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
#include "CardManager.h"
#include "CPU.h"
#include "Disk.h"
diff --git a/source/Windows/WinVideo.cpp b/source/Windows/WinVideo.cpp
index 13b01114..9fbffa91 100644
--- a/source/Windows/WinVideo.cpp
+++ b/source/Windows/WinVideo.cpp
@@ -30,8 +30,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Windows/WinVideo.h"
#include "Windows/WinFrame.h"
-#include "AppleWin.h"
+#include "Windows/AppleWin.h"
#include "Video.h"
+#include "Core.h"
#include "CPU.h"
#include "Joystick.h"
#include "Frame.h"
diff --git a/source/Z80VICE/z80.cpp b/source/Z80VICE/z80.cpp
index 75989b92..f3a6fd06 100644
--- a/source/Z80VICE/z80.cpp
+++ b/source/Z80VICE/z80.cpp
@@ -26,7 +26,6 @@
#include "../StdAfx.h"
-#include "../AppleWin.h"
#include "../CPU.h"
#include "../Memory.h"
#include "../YamlHelper.h"
diff --git a/source/z80emu.cpp b/source/z80emu.cpp
index d177bf19..c3f77486 100644
--- a/source/z80emu.cpp
+++ b/source/z80emu.cpp
@@ -16,7 +16,6 @@
#include "StdAfx.h"
#include "z80emu.h"
-#include "AppleWin.h"
#include "CPU.h"
#include "Memory.h"
diff --git a/test/TestCPU6502/TestCPU6502.cpp b/test/TestCPU6502/TestCPU6502.cpp
index acc3c55b..05289c27 100644
--- a/test/TestCPU6502/TestCPU6502.cpp
+++ b/test/TestCPU6502/TestCPU6502.cpp
@@ -1,6 +1,6 @@
#include "stdafx.h"
-#include "../../source/AppleWin.h"
+#include "../../source/Windows/AppleWin.h"
#include "../../source/CPU.h"
#include "../../source/Memory.h"
#include "../../source/SynchronousEventManager.h"