diff --git a/AppleWinExpress2008.vcproj b/AppleWinExpress2008.vcproj
index 700a0630..f4caecb5 100644
--- a/AppleWinExpress2008.vcproj
+++ b/AppleWinExpress2008.vcproj
@@ -961,6 +961,14 @@
RelativePath=".\source\Windows\DirectInput.h"
>
+
+
+
+
diff --git a/AppleWinExpress2019.vcxproj b/AppleWinExpress2019.vcxproj
index 561d2aa1..c88598d7 100644
--- a/AppleWinExpress2019.vcxproj
+++ b/AppleWinExpress2019.vcxproj
@@ -109,6 +109,7 @@
+
@@ -215,6 +216,7 @@
+
diff --git a/AppleWinExpress2019.vcxproj.filters b/AppleWinExpress2019.vcxproj.filters
index faa855c1..ec3295e5 100644
--- a/AppleWinExpress2019.vcxproj.filters
+++ b/AppleWinExpress2019.vcxproj.filters
@@ -208,6 +208,9 @@
Source Files\Windows
+
+ Source Files\Windows
+
@@ -501,6 +504,9 @@
Source Files\Windows
+
+ Source Files\Windows
+
diff --git a/source/AppleWin.cpp b/source/AppleWin.cpp
index 4cff67e3..74099758 100644
--- a/source/AppleWin.cpp
+++ b/source/AppleWin.cpp
@@ -34,7 +34,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
#include "Disk.h"
#include "DiskImage.h"
-#include "Frame.h"
#include "Harddisk.h"
#include "Joystick.h"
#include "Keyboard.h"
@@ -55,6 +54,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#endif
#include "SynchronousEventManager.h"
#include "Windows/WinVideo.h"
+#include "Windows/WinFrame.h"
#include "RGBMonitor.h"
#include "NTSC.h"
diff --git a/source/Configuration/About.cpp b/source/Configuration/About.cpp
index c0c55f58..54456946 100644
--- a/source/Configuration/About.cpp
+++ b/source/Configuration/About.cpp
@@ -25,7 +25,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "About.h"
#include "../AppleWin.h"
-#include "../Frame.h"
+#include "../Windows/WinFrame.h"
#include "../resource/resource.h"
static const TCHAR g_szGPL[] =
diff --git a/source/Configuration/PageConfig.cpp b/source/Configuration/PageConfig.cpp
index 0d97d4a5..dabc68ff 100644
--- a/source/Configuration/PageConfig.cpp
+++ b/source/Configuration/PageConfig.cpp
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PropertySheetHelper.h"
#include "../AppleWin.h"
-#include "../Frame.h"
+#include "../Windows/WinFrame.h"
#include "../Registry.h"
#include "../SerialComms.h"
#include "../Windows/WinVideo.h"
diff --git a/source/Configuration/PageDisk.cpp b/source/Configuration/PageDisk.cpp
index 7357565c..ac504d63 100644
--- a/source/Configuration/PageDisk.cpp
+++ b/source/Configuration/PageDisk.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../AppleWin.h"
#include "../CardManager.h"
#include "../Disk.h" // Drive_e, Disk_Status_e
-#include "../Frame.h"
+#include "../Windows/WinFrame.h"
#include "../Registry.h"
#include "../resource/resource.h"
diff --git a/source/Configuration/PropertySheet.cpp b/source/Configuration/PropertySheet.cpp
index f94c9271..f7cb3605 100644
--- a/source/Configuration/PropertySheet.cpp
+++ b/source/Configuration/PropertySheet.cpp
@@ -32,7 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "PropertySheet.h"
#include "../AppleWin.h"
-#include "../Frame.h"
+#include "../Windows/WinFrame.h"
#include "../resource/resource.h"
void CPropertySheet::Init(void)
diff --git a/source/Configuration/PropertySheetHelper.cpp b/source/Configuration/PropertySheetHelper.cpp
index e49623d8..77111765 100644
--- a/source/Configuration/PropertySheetHelper.cpp
+++ b/source/Configuration/PropertySheetHelper.cpp
@@ -29,7 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../AppleWin.h" // g_nAppMode, g_uScrollLockToggle, sg_PropertySheet
#include "../CardManager.h"
#include "../Disk.h"
-#include "../Frame.h"
+#include "../Windows/WinFrame.h"
#include "../Log.h"
#include "../Registry.h"
#include "../SaveState.h"
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index 2ad4386c..7a5566fd 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -38,12 +38,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../CardManager.h"
#include "../CPU.h"
#include "../Disk.h"
-#include "../Frame.h"
#include "../Keyboard.h"
#include "../Memory.h"
#include "../NTSC.h"
#include "../SoundCore.h" // SoundCore_SetFade()
#include "../Windows/WinVideo.h"
+#include "../Windows/WinFrame.h"
#include "../Video.h"
// #define DEBUG_COMMAND_HELP 1
diff --git a/source/Debugger/Debugger_Assembler.cpp b/source/Debugger/Debugger_Assembler.cpp
index ae9b40dc..653a0c26 100644
--- a/source/Debugger/Debugger_Assembler.cpp
+++ b/source/Debugger/Debugger_Assembler.cpp
@@ -31,7 +31,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
#include "../CPU.h"
-#include "../Frame.h"
#include "../Memory.h"
#define DEBUG_ASSEMBLER 0
diff --git a/source/Debugger/Debugger_Commands.cpp b/source/Debugger/Debugger_Commands.cpp
index 42b7fc57..28abcff4 100644
--- a/source/Debugger/Debugger_Commands.cpp
+++ b/source/Debugger/Debugger_Commands.cpp
@@ -27,7 +27,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debug.h"
-#include "../Frame.h"
+#include "../Windows/WinFrame.h"
// Commands _______________________________________________________________________________________
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 207a3652..cdc391ec 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../AppleWin.h"
#include "../CPU.h"
#include "../Frame.h"
+#include "../Windows/WinFrame.h"
#include "../LanguageCard.h"
#include "../Memory.h"
#include "../Mockingboard.h"
diff --git a/source/Disk.cpp b/source/Disk.cpp
index 235c6592..7090a0d2 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -37,13 +37,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "AppleWin.h"
#include "CPU.h"
#include "DiskImage.h"
-#include "Frame.h"
#include "Log.h"
#include "Memory.h"
#include "Registry.h"
#include "SaveState.h"
#include "Video.h"
#include "Windows/WinVideo.h"
+#include "Windows/WinFrame.h"
#include "YamlHelper.h"
#include "../resource/resource.h"
diff --git a/source/Frame.cpp b/source/Frame.cpp
index c797903f..e4d94d7f 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -29,180 +29,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Frame.h"
-#include "AppleWin.h"
-#include "CardManager.h"
-#include "CPU.h"
-#include "Disk.h"
-#include "DiskImage.h"
-#include "Harddisk.h"
-#include "Keyboard.h"
-#include "Log.h"
-#include "Memory.h"
-#include "Mockingboard.h"
-#include "MouseInterface.h"
-#include "Windows/DirectInput.h"
-#include "NTSC.h"
-#include "ParallelPrinter.h"
-#include "Pravets.h"
-#include "Registry.h"
-#include "SaveState.h"
-#include "SerialComms.h"
-#include "SoundCore.h"
-#include "Speaker.h"
-#ifdef USE_SPEECH_API
-#include "Speech.h"
-#endif
-#include "Windows/WinVideo.h"
-
-#include "../resource/resource.h"
-#include "Configuration/PropertySheet.h"
-#include "Debugger/Debug.h"
-#if _MSC_VER <= 1500 // VS2008 only (cl.exe v15.00)
-#include
-#endif
-
-//#define ENABLE_MENU 0
-#define DEBUG_KEY_MESSAGES 0
-
-// 3D border around the 560x384 Apple II display
-#define VIEWPORTX 5
-#define VIEWPORTY 5
-
-static const int kDEFAULT_VIEWPORT_SCALE = 2;
- int g_nViewportCX = GetFrameBufferBorderlessWidth() * kDEFAULT_VIEWPORT_SCALE;
- int g_nViewportCY = GetFrameBufferBorderlessHeight() * kDEFAULT_VIEWPORT_SCALE;
-static int g_nViewportScale = kDEFAULT_VIEWPORT_SCALE; // saved REGSAVE
-static int g_nMaxViewportScale = kDEFAULT_VIEWPORT_SCALE; // Max scale in Windowed mode with borders, buttons etc (full-screen may be +1)
-
-#define BUTTONX (g_nViewportCX + VIEWPORTX*2)
-#define BUTTONY 0
-#define BUTTONCX 45
-#define BUTTONCY 45
-#define BUTTONS 8
-
- static HBITMAP g_hCapsLockBitmap[2];
- static HBITMAP g_hHardDiskBitmap[2];
-
- //Pravets8 only
- static HBITMAP g_hCapsBitmapP8[2];
- static HBITMAP g_hCapsBitmapLat[2];
- //static HBITMAP charsetbitmap [4]; //The idea was to add a charset indicator on the front panel, but it was given up. All charsetbitmap occurences must be REMOVED!
- //===========================
- static HBITMAP g_hDiskWindowedLED[ NUM_DISK_STATUS ];
-
-static int g_nTrackDrive1 = -1;
-static int g_nTrackDrive2 = -1;
-static int g_nSectorDrive1 = -1;
-static int g_nSectorDrive2 = -1;
-static TCHAR g_sTrackDrive1 [8] = TEXT("??");
-static TCHAR g_sTrackDrive2 [8] = TEXT("??");
-static TCHAR g_sSectorDrive1[8] = TEXT("??");
-static TCHAR g_sSectorDrive2[8] = TEXT("??");
-Disk_Status_e g_eStatusDrive1 = DISK_STATUS_OFF;
-Disk_Status_e g_eStatusDrive2 = DISK_STATUS_OFF;
-
-// Must keep in sync with Disk_Status_e g_aDiskFullScreenColors
-static DWORD g_aDiskFullScreenColorsLED[ NUM_DISK_STATUS ] =
-{
- RGB( 0, 0, 0), // DISK_STATUS_OFF BLACK
- RGB( 0,255, 0), // DISK_STATUS_READ GREEN
- RGB(255, 0, 0), // DISK_STATUS_WRITE RED
- RGB(255,128, 0) // DISK_STATUS_PROT ORANGE
-// RGB( 0, 0,255) // DISK_STATUS_PROT -blue-
-};
-
-static HBITMAP buttonbitmap[BUTTONS];
-
-static bool g_bAppActive = false;
-static HBRUSH btnfacebrush = (HBRUSH)0;
-static HPEN btnfacepen = (HPEN)0;
-static HPEN btnhighlightpen = (HPEN)0;
-static HPEN btnshadowpen = (HPEN)0;
-static int buttonactive = -1;
-static int buttondown = -1;
-static int buttonover = -1;
-static int buttonx = BUTTONX;
-static int buttony = BUTTONY;
-static HDC g_hFrameDC = (HDC)0;
-static RECT framerect = {0,0,0,0};
-
- HWND g_hFrameWindow = (HWND)0;
-static bool g_bIsFullScreen = false;
- BOOL g_bConfirmReboot = 1; // saved PageConfig REGSAVE
- BOOL g_bMultiMon = 0; // OFF = load window position & clamp initial frame to screen, ON = use window position as is
-
-static BOOL helpquit = 0;
-static HFONT smallfont = (HFONT)0;
-static HWND tooltipwindow = (HWND)0;
-static BOOL g_bUsingCursor = FALSE; // TRUE = AppleWin is using (hiding) the mouse-cursor && restricting cursor to window - see SetUsingCursor()
-static int viewportx = VIEWPORTX; // Default to Normal (non-FullScreen) mode
-static int viewporty = VIEWPORTY; // Default to Normal (non-FullScreen) mode
-
-static UINT_PTR g_TimerIDEvent_100msec = 0;
-static UINT g_uCount100msec = 0;
-
-static bool g_bShowingCursor = true;
-static bool g_bLastCursorInAppleViewport = false;
-
-void DrawStatusArea (HDC passdc, BOOL drawflags);
-static void ProcessButtonClick (int button, bool bFromButtonUI=false);
-void ProcessDiskPopupMenu(HWND hwnd, POINT pt, const int iDrive);
-void RelayEvent (UINT message, WPARAM wparam, LPARAM lparam);
-void ResetMachineState ();
-void SetFullScreenMode ();
-void SetNormalMode ();
-static void SetUsingCursor(BOOL);
-static bool FileExists(std::string strFilename);
-
-bool g_bScrollLock_FullSpeed = false;
-bool g_bFreshReset = false;
-static bool g_bFullScreen32Bit = true;
-
-#if 0 // enable non-integral full-screen scaling
-#define FULLSCREEN_SCALE_TYPE float
-#else
-#define FULLSCREEN_SCALE_TYPE int
-#endif
-
-static RECT g_main_window_saved_rect;
-static int g_main_window_saved_style;
-static int g_main_window_saved_exstyle;
-static FULLSCREEN_SCALE_TYPE g_win_fullscreen_scale = 1;
-static int g_win_fullscreen_offsetx = 0;
-static int g_win_fullscreen_offsety = 0;
-
-static bool g_bFrameActive = false;
-static bool g_windowMinimized = false;
-
-static std::string driveTooltip;
-
-// __ Prototypes __________________________________________________________________________________
-void DrawCrosshairs (int x, int y);
-void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x=0, int y=0);
-static void ScreenWindowResize(const bool bCtrlKey);
-void FrameResizeWindow(int nNewScale);
-
-
-// ==========================================================================
-
-static bool g_bAltEnter_ToggleFullScreen = true; // Default for ALT+ENTER is to toggle between windowed and full-screen modes
-
-void SetAltEnterToggleFullScreen(bool mode)
-{
- g_bAltEnter_ToggleFullScreen = mode;
-}
-
-// ==========================================================================
-
-// Display construction:
-// . Apple II video gets rendered to the framebuffer (maybe with some preliminary/final NTSC data in the border areas)
-// . The *borderless* framebuffer is stretchblt() copied to the frame DC, in VideoRefreshScreen()
-// . Draw cross-hairs (if using mouse as either a mouse or joystick) to frame DC
-// . In Windowed mode:
-// - Draw 3D border, 8x buttons, status area (disk LEDs, caps) to frame DC
-// . In Fullscreen mode:
-// - Optional: Draw status area to frame DC
-//
UINT GetFrameBufferBorderlessWidth(void)
{
@@ -238,2833 +64,3 @@ UINT GetFrameBufferHeight(void)
{
return GetFrameBufferBorderlessHeight() + 2*GetFrameBufferBorderHeight();
}
-
-//
-
-UINT Get3DBorderWidth(void)
-{
- return IsFullScreen() ? 0 : VIEWPORTX;
-}
-
-UINT Get3DBorderHeight(void)
-{
- return IsFullScreen() ? 0 : VIEWPORTY;
-}
-
-// ==========================================================================
-
-static void GetAppleWindowTitle()
-{
- switch (g_Apple2Type)
- {
- default:
- case A2TYPE_APPLE2: g_pAppTitle = TITLE_APPLE_2 ; break;
- case A2TYPE_APPLE2PLUS: g_pAppTitle = TITLE_APPLE_2_PLUS ; break;
- case A2TYPE_APPLE2JPLUS: g_pAppTitle = TITLE_APPLE_2_JPLUS ; break;
- case A2TYPE_APPLE2E: g_pAppTitle = TITLE_APPLE_2E ; break;
- case A2TYPE_APPLE2EENHANCED: g_pAppTitle = TITLE_APPLE_2E_ENHANCED; break;
- case A2TYPE_PRAVETS82: g_pAppTitle = TITLE_PRAVETS_82 ; break;
- case A2TYPE_PRAVETS8M: g_pAppTitle = TITLE_PRAVETS_8M ; break;
- case A2TYPE_PRAVETS8A: g_pAppTitle = TITLE_PRAVETS_8A ; break;
- case A2TYPE_TK30002E: g_pAppTitle = TITLE_TK3000_2E ; break;
- case A2TYPE_BASE64A: g_pAppTitle = TITLE_BASE64A ; break;
- }
-
-#if _DEBUG
- g_pAppTitle += " *DEBUG* ";
-#endif
-
- if (g_nAppMode == MODE_LOGO)
- return;
-
- g_pAppTitle += " - ";
-
- if( IsVideoStyle(VS_HALF_SCANLINES) )
- g_pAppTitle += " 50% ";
-
- g_pAppTitle += VideoGetAppWindowTitle();
-
- if (GetCardMgr().GetDisk2CardMgr().IsAnyFirmware13Sector())
- g_pAppTitle += " (S6-13) ";
-
- if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
- g_pAppTitle += TEXT(" (custom rom)");
- else if (sg_PropertySheet.GetTheFreezesF8Rom() && IS_APPLE2)
- g_pAppTitle += TEXT(" (The Freeze's non-autostart F8 rom)");
-
- switch (g_nAppMode)
- {
- case MODE_PAUSED : g_pAppTitle += std::string(TEXT(" [")) + TITLE_PAUSED + TEXT("]"); break;
- case MODE_STEPPING: g_pAppTitle += std::string(TEXT(" [")) + TITLE_STEPPING + TEXT("]"); break;
- }
-}
-
-//===========================================================================
-
-static void FrameShowCursor(BOOL bShow)
-{
- int nCount;
-
- if (bShow)
- {
- do
- {
- nCount = ShowCursor(bShow);
- }
- while(nCount < 0);
- g_bShowingCursor = true;
- }
- else
- {
- do
- {
- nCount = ShowCursor(bShow);
- }
- while(nCount >= 0);
- g_bShowingCursor = false;
- }
-}
-
-// Called when:
-// . Ctrl-Left mouse button
-// . PAUSE pressed (when MODE_RUNNING)
-// . AppleWin's main window is activated/deactivated
-static void RevealCursor()
-{
- CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard();
-
- if (!pMouseCard || !pMouseCard->IsActiveAndEnabled())
- return;
-
- pMouseCard->SetEnabled(false);
-
- FrameShowCursor(TRUE);
-
- if (sg_PropertySheet.GetMouseShowCrosshair()) // Erase crosshairs if they are being drawn
- DrawCrosshairs(0,0);
-
- if (sg_PropertySheet.GetMouseRestrictToWindow())
- SetUsingCursor(FALSE);
-
- g_bLastCursorInAppleViewport = false;
-}
-
-// Called when:
-// . WM_MOUSEMOVE event
-// . Switch from full-screen to normal (windowed) mode
-// . AppleWin's main window is activated/deactivated
-static void FullScreenRevealCursor(void)
-{
- if (!g_bIsFullScreen)
- return;
-
- if (GetCardMgr().IsMouseCardInstalled())
- return;
-
- if (!g_bUsingCursor && !g_bShowingCursor)
- {
- FrameShowCursor(TRUE);
- g_uCount100msec = 0;
- }
-}
-
-//===========================================================================
-
-#define LOADBUTTONBITMAP(bitmapname) LoadImage(g_hInstance,bitmapname, \
- IMAGE_BITMAP,0,0, \
- LR_CREATEDIBSECTION | \
- LR_LOADMAP3DCOLORS | \
- LR_LOADTRANSPARENT);
-
-static void CreateGdiObjects(void)
-{
- ZeroMemory(buttonbitmap, BUTTONS*sizeof(HBITMAP));
-
- buttonbitmap[BTN_HELP] = (HBITMAP)LOADBUTTONBITMAP(TEXT("HELP_BUTTON"));
-
- switch (g_Apple2Type)
- {
- case A2TYPE_PRAVETS82:
- case A2TYPE_PRAVETS8M:
- case A2TYPE_PRAVETS8A:
- buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUNP_BUTTON"));
- break;
- case A2TYPE_TK30002E:
- buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN3000E_BUTTON"));
- break;
- case A2TYPE_BASE64A:
- buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUNBASE64A_BUTTON"));
- break;
- default:
- buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN_BUTTON"));
- break;
- }
-
- buttonbitmap[BTN_DRIVE1 ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DRIVE1_BUTTON"));
- buttonbitmap[BTN_DRIVE2 ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DRIVE2_BUTTON"));
- buttonbitmap[BTN_DRIVESWAP] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DRIVESWAP_BUTTON"));
- buttonbitmap[BTN_FULLSCR ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("FULLSCR_BUTTON"));
- buttonbitmap[BTN_DEBUG ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DEBUG_BUTTON"));
- buttonbitmap[BTN_SETUP ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("SETUP_BUTTON"));
-
- //
-
- g_hCapsLockBitmap[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSOFF_BITMAP"));
- g_hCapsLockBitmap[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSON_BITMAP"));
- //Pravets8 only
- g_hCapsBitmapP8[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSOFF_P8_BITMAP"));
- g_hCapsBitmapP8[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSON_P8_BITMAP"));
- g_hCapsBitmapLat[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_LATOFF_BITMAP"));
- g_hCapsBitmapLat[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_LATON_BITMAP"));
-
- /*charsetbitmap[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_APPLE_BITMAP"));
- charsetbitmap[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_82_BITMAP"));
- charsetbitmap[2] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_8A_BITMAP"));
- charsetbitmap[3] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_8M_BITMAP"));
- */
- //===========================
- g_hDiskWindowedLED[ DISK_STATUS_OFF ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKOFF_BITMAP"));
- g_hDiskWindowedLED[ DISK_STATUS_READ ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKREAD_BITMAP"));
- g_hDiskWindowedLED[ DISK_STATUS_WRITE] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKWRITE_BITMAP"));
- g_hDiskWindowedLED[ DISK_STATUS_PROT ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKPROT_BITMAP"));
-
- btnfacebrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
- btnfacepen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNFACE));
- btnhighlightpen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNHIGHLIGHT));
- btnshadowpen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW));
- smallfont = CreateFont(11,6,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,
- OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
- DEFAULT_QUALITY,VARIABLE_PITCH | FF_SWISS,
- TEXT("Small Fonts"));
-}
-
-//===========================================================================
-static void DeleteGdiObjects(void)
-{
- for (int loop = 0; loop < BUTTONS; loop++)
- _ASSERT(DeleteObject(buttonbitmap[loop]));
-
- for (int loop = 0; loop < 2; loop++)
- {
- _ASSERT(DeleteObject(g_hCapsLockBitmap[loop]));
- _ASSERT(DeleteObject(g_hCapsBitmapP8[loop]));
- _ASSERT(DeleteObject(g_hCapsBitmapLat[loop]));
- }
-
- for (int loop = 0; loop < NUM_DISK_STATUS; loop++)
- {
- _ASSERT(DeleteObject(g_hDiskWindowedLED[loop]));
- }
-
- _ASSERT(DeleteObject(btnfacebrush));
- _ASSERT(DeleteObject(btnfacepen));
- _ASSERT(DeleteObject(btnhighlightpen));
- _ASSERT(DeleteObject(btnshadowpen));
- _ASSERT(DeleteObject(smallfont));
-}
-
-// Draws an 3D box around the main apple screen
-//===========================================================================
-static void Draw3dRect (HDC dc, int x1, int y1, int x2, int y2, BOOL out)
-{
- SelectObject(dc,GetStockObject(NULL_BRUSH));
- SelectObject(dc,out ? btnshadowpen : btnhighlightpen);
- POINT pt[3];
- pt[0].x = x1; pt[0].y = y2-1;
- pt[1].x = x2-1; pt[1].y = y2-1;
- pt[2].x = x2-1; pt[2].y = y1;
- Polyline(dc,(LPPOINT)&pt,3);
- SelectObject(dc,(out == 1) ? btnhighlightpen : btnshadowpen);
- pt[1].x = x1; pt[1].y = y1;
- pt[2].x = x2; pt[2].y = y1;
- Polyline(dc,(LPPOINT)&pt,3);
-}
-
-//===========================================================================
-static void DrawBitmapRect (HDC dc, int x, int y, LPRECT rect, HBITMAP bitmap) {
- HDC memdc = CreateCompatibleDC(dc);
- SelectObject(memdc,bitmap);
- BitBlt(dc,x,y,
- rect->right + 1 - rect->left,
- rect->bottom + 1 - rect->top,
- memdc,
- rect->left,
- rect->top,
- SRCCOPY);
- DeleteDC(memdc);
-}
-
-//===========================================================================
-static void DrawButton (HDC passdc, int number) {
- FrameReleaseDC();
- HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
- int x = buttonx;
- int y = buttony+number*BUTTONCY;
- if (number == buttondown) {
- int loop = 0;
- while (loop++ < 3)
- Draw3dRect(dc,x+loop,y+loop,x+BUTTONCX,y+BUTTONCY,0);
- RECT rect = {0,0,39,39};
- DrawBitmapRect(dc,x+4,y+4,&rect,buttonbitmap[number]);
- }
- else {
- Draw3dRect(dc,x+1,y+1,x+BUTTONCX,y+BUTTONCY,1);
- Draw3dRect(dc,x+2,y+2,x+BUTTONCX-1,y+BUTTONCY-1,1);
- RECT rect = {1,1,40,40};
- DrawBitmapRect(dc,x+3,y+3,&rect,buttonbitmap[number]);
- }
- if ((number == BTN_DRIVE1) || (number == BTN_DRIVE2)) {
- int offset = (number == buttondown) << 1;
- RECT rect = {x+offset+3,
- y+offset+31,
- x+offset+42,
- y+offset+42};
- SelectObject(dc,smallfont);
- SetTextColor(dc,RGB(0,0,0));
- SetTextAlign(dc,TA_CENTER | TA_TOP);
- SetBkMode(dc,TRANSPARENT);
-
- LPCTSTR pszBaseName = (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- ? dynamic_cast(GetCardMgr().GetRef(SLOT6)).GetBaseName(number-BTN_DRIVE1).c_str()
- : "";
-
- ExtTextOut(dc,x+offset+22,rect.top,ETO_CLIPPED,&rect,
- pszBaseName,
- MIN(8,_tcslen(pszBaseName)),
- NULL);
- }
- if (!passdc)
- ReleaseDC(g_hFrameWindow,dc);
-}
-
-//===========================================================================
-
-// NB. x=y=0 means erase only
-static void DrawCrosshairs (int x, int y) {
- static int lastx = 0;
- static int lasty = 0;
- FrameReleaseDC();
- HDC dc = GetDC(g_hFrameWindow);
-#define LINE(x1,y1,x2,y2) MoveToEx(dc,x1,y1,NULL); LineTo(dc,x2,y2);
-
- // ERASE THE OLD CROSSHAIRS
- if (lastx && lasty)
- if (g_bIsFullScreen)
- {
- int loop = 4;
- while (loop--) {
- RECT rect = {0,0,5,5};
- switch (loop) {
- case 0: OffsetRect(&rect, GetFullScreenOffsetX()+lastx-2, GetFullScreenOffsetY()+viewporty-5); break;
- case 1: OffsetRect(&rect, GetFullScreenOffsetX()+lastx-2, GetFullScreenOffsetY()+viewporty+g_nViewportCY); break;
- case 2: OffsetRect(&rect, GetFullScreenOffsetX()+viewportx-5, GetFullScreenOffsetY()+lasty-2); break;
- case 3: OffsetRect(&rect, GetFullScreenOffsetX()+viewportx+g_nViewportCX, GetFullScreenOffsetY()+lasty-2); break;
- }
- FillRect(dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
- }
- }
- else
- {
- int loop = 5;
- while (loop--) {
- switch (loop) {
- case 0: SelectObject(dc,GetStockObject(BLACK_PEN)); break;
- case 1: // fall through
- case 2: SelectObject(dc,btnshadowpen); break;
- case 3: // fall through
- case 4: SelectObject(dc,btnfacepen); break;
- }
- LINE(lastx-2,VIEWPORTY-loop-1,
- lastx+3,VIEWPORTY-loop-1);
- LINE(VIEWPORTX-loop-1,lasty-2,
- VIEWPORTX-loop-1,lasty+3);
- if ((loop == 1) || (loop == 2))
- SelectObject(dc,btnhighlightpen);
- LINE(lastx-2,VIEWPORTY+g_nViewportCY+loop,
- lastx+3,VIEWPORTY+g_nViewportCY+loop);
- LINE(VIEWPORTX+g_nViewportCX+loop,lasty-2,
- VIEWPORTX+g_nViewportCX+loop,lasty+3);
- }
- }
-
- // DRAW THE NEW CROSSHAIRS
- if (x && y) {
- if (g_bIsFullScreen)
- {
- int loop = 4;
- while (loop--) {
- if ((loop == 1) || (loop == 2))
- SelectObject(dc,GetStockObject(WHITE_PEN));
- else
- SelectObject(dc,GetStockObject(BLACK_PEN));
- LINE(GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty-5,
- GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty);
- LINE(GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty+g_nViewportCY+4,
- GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty+g_nViewportCY-1);
- LINE(GetFullScreenOffsetX()+viewportx-5, GetFullScreenOffsetY()+y+loop-2,
- GetFullScreenOffsetX()+viewportx, GetFullScreenOffsetY()+y+loop-2);
- LINE(GetFullScreenOffsetX()+viewportx+g_nViewportCX+4, GetFullScreenOffsetY()+y+loop-2,
- GetFullScreenOffsetX()+viewportx+g_nViewportCX-1, GetFullScreenOffsetY()+y+loop-2);
- }
- }
- else
- {
- int loop = 4;
- while (loop--) {
- if ((loop == 1) || (loop == 2))
- SelectObject(dc,GetStockObject(WHITE_PEN));
- else
- SelectObject(dc,GetStockObject(BLACK_PEN));
- LINE(x+loop-2,viewporty-5,
- x+loop-2,viewporty);
- LINE(x+loop-2,viewporty+g_nViewportCY+4,
- x+loop-2,viewporty+g_nViewportCY-1);
- LINE(viewportx-5, y+loop-2,
- viewportx, y+loop-2);
- LINE(viewportx+g_nViewportCX+4,y+loop-2,
- viewportx+g_nViewportCX-1,y+loop-2);
- }
- }
- }
-#undef LINE
- lastx = x;
- lasty = y;
- ReleaseDC(g_hFrameWindow,dc);
-}
-
-//===========================================================================
-static void DrawFrameWindow (bool bPaintingWindow = false);
-static void DrawFrameWindow (bool bPaintingWindow/*=false*/)
-{
- FrameReleaseDC();
- PAINTSTRUCT ps;
- HDC dc = bPaintingWindow
- ? BeginPaint(g_hFrameWindow,&ps)
- : GetDC(g_hFrameWindow);
-
- if (!g_bIsFullScreen)
- {
- // DRAW THE 3D BORDER AROUND THE EMULATED SCREEN
- Draw3dRect(dc,
- VIEWPORTX-2,VIEWPORTY-2,
- VIEWPORTX+g_nViewportCX+2,VIEWPORTY+g_nViewportCY+2,
- 0);
- Draw3dRect(dc,
- VIEWPORTX-3,VIEWPORTY-3,
- VIEWPORTX+g_nViewportCX+3,VIEWPORTY+g_nViewportCY+3,
- 0);
- SelectObject(dc,btnfacepen);
- Rectangle(dc,
- VIEWPORTX-4,VIEWPORTY-4,
- VIEWPORTX+g_nViewportCX+4,VIEWPORTY+g_nViewportCY+4);
- Rectangle(dc,
- VIEWPORTX-5,VIEWPORTY-5,
- VIEWPORTX+g_nViewportCX+5,VIEWPORTY+g_nViewportCY+5);
-
- // DRAW THE TOOLBAR BUTTONS
- int iButton = BUTTONS;
- while (iButton--)
- {
- DrawButton(dc,iButton);
- }
-
- if (g_nViewportScale == 2)
- {
- int x = buttonx + 1;
- int y = buttony + BUTTONS*BUTTONCY + 36; // 36 = height of StatusArea
- RECT rect = {x, y, x+45, y+BUTTONS*BUTTONCY+22};
- int res = FillRect(dc, &rect, btnfacebrush);
- }
- }
-
- // DRAW THE STATUS AREA
- DrawStatusArea(dc,DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS);
-
- // DRAW THE CONTENTS OF THE EMULATED SCREEN
- if (g_nAppMode == MODE_LOGO)
- VideoDisplayLogo();
- else if (g_nAppMode == MODE_DEBUG)
- DebugDisplay();
- else
- VideoRedrawScreen();
-
- if (bPaintingWindow)
- EndPaint(g_hFrameWindow,&ps);
- else
- ReleaseDC(g_hFrameWindow,dc);
-
-}
-
-//===========================================================================
-static bool g_bFullScreen_ShowSubunitStatus = true;
-
-bool IsFullScreen(void)
-{
- return g_bIsFullScreen;
-}
-
-bool GetFullScreenShowSubunitStatus(void)
-{
- return g_bFullScreen_ShowSubunitStatus;
-}
-
-void SetFullScreenShowSubunitStatus(bool bShow)
-{
- g_bFullScreen_ShowSubunitStatus = bShow;
-}
-
-//===========================================================================
-void FrameDrawDiskLEDS( HDC passdc )
-{
- g_eStatusDrive1 = DISK_STATUS_OFF;
- g_eStatusDrive2 = DISK_STATUS_OFF;
-
- // Slot6 drive takes priority unless it's off:
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- dynamic_cast(GetCardMgr().GetRef(SLOT6)).GetLightStatus(&g_eStatusDrive1, &g_eStatusDrive2);
-
- // Slot5:
- {
- Disk_Status_e eDrive1StatusSlot5 = DISK_STATUS_OFF;
- Disk_Status_e eDrive2StatusSlot5 = DISK_STATUS_OFF;
- if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2)
- dynamic_cast(GetCardMgr().GetRef(SLOT5)).GetLightStatus(&eDrive1StatusSlot5, &eDrive2StatusSlot5);
-
- if (g_eStatusDrive1 == DISK_STATUS_OFF) g_eStatusDrive1 = eDrive1StatusSlot5;
- if (g_eStatusDrive2 == DISK_STATUS_OFF) g_eStatusDrive2 = eDrive2StatusSlot5;
- }
-
- // Draw Track/Sector
- FrameReleaseDC();
- HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
-
- int x = buttonx;
- int y = buttony+BUTTONS*BUTTONCY+1;
-
- if (g_bIsFullScreen)
- {
- if (!g_bFullScreen_ShowSubunitStatus)
- return;
-
- SelectObject(dc,smallfont);
- SetBkMode(dc,OPAQUE);
- SetBkColor(dc,RGB(0,0,0));
- SetTextAlign(dc,TA_LEFT | TA_TOP);
-
- SetTextColor(dc, g_aDiskFullScreenColorsLED[g_eStatusDrive1] );
- TextOut(dc,x+ 3,y+2,TEXT("1"),1);
-
- SetTextColor(dc, g_aDiskFullScreenColorsLED[g_eStatusDrive2] );
- TextOut(dc,x+13,y+2,TEXT("2"),1);
- }
- else
- {
- RECT rDiskLed = {0,0,8,8};
- DrawBitmapRect(dc,x+12,y+6,&rDiskLed,g_hDiskWindowedLED[g_eStatusDrive1]);
- DrawBitmapRect(dc,x+31,y+6,&rDiskLed,g_hDiskWindowedLED[g_eStatusDrive2]);
- }
-}
-
-// Feature Request #201 Show track status
-// https://github.com/AppleWin/AppleWin/issues/201
-//===========================================================================
-void FrameDrawDiskStatus( HDC passdc )
-{
- if (mem == NULL)
- return;
-
- if (g_nAppMode == MODE_LOGO)
- return;
-
- if (g_windowMinimized) // Prevent DC leaks when app window is minimised (GH#820)
- return;
-
- // We use the actual drive since probing from memory doesn't tell us anything we don't already know.
- // DOS3.3 ProDOS
- // Drive $B7EA $BE3D
- // Track $B7EC LC1 $D356
- // Sector $B7ED LC1 $D357
- // RWTS LC1 $D300
-
- if (GetCardMgr().QuerySlot(SLOT6) != CT_Disk2)
- return;
-
- Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
- int nActiveFloppy = disk2Card.GetCurrentDrive();
- int nDisk1Track = disk2Card.GetTrack(DRIVE_1);
- int nDisk2Track = disk2Card.GetTrack(DRIVE_2);
-
- // Probe known OS's for Track/Sector
- int isProDOS = mem[ 0xBF00 ] == 0x4C;
- bool isValid = true;
-
- // Try DOS3.3 Sector
- if ( !isProDOS )
- {
- int nDOS33track = mem[ 0xB7EC ];
- int nDOS33sector = mem[ 0xB7ED ];
-
- if ((nDOS33track >= 0 && nDOS33track < 40)
- && (nDOS33sector >= 0 && nDOS33sector < 16))
- {
-#if _DEBUG && 0
- if (nDOS33track != nDisk1Track)
- {
- char text[128];
- sprintf( text, "\n\n\nWARNING: DOS33Track: %d (%02X) != nDisk1Track: %d (%02X)\n\n\n", nDOS33track, nDOS33track, nDisk1Track, nDisk1Track );
- OutputDebugString( text );
- }
-#endif // _DEBUG
-
- /**/ if (nActiveFloppy == 0) g_nSectorDrive1 = nDOS33sector;
- else if (nActiveFloppy == 1) g_nSectorDrive2 = nDOS33sector;
- }
- else
- isValid = false;
- }
- else // isProDOS
- {
- // we can't just read from mem[ 0xD357 ] since it might be bank-switched from ROM
- // and we need the Language Card RAM
- // memrom[ 0xD350 ] = " ERROR\x07\x00" Applesoft error message
- // T S
- int nProDOStrack = *MemGetMainPtr( 0xC356 ); // LC1 $D356
- int nProDOSsector = *MemGetMainPtr( 0xC357 ); // LC1 $D357
-
- if ((nProDOStrack >= 0 && nProDOStrack < 40)
- && (nProDOSsector >= 0 && nProDOSsector < 16))
- {
- /**/ if (nActiveFloppy == 0) g_nSectorDrive1 = nProDOSsector;
- else if (nActiveFloppy == 1) g_nSectorDrive2 = nProDOSsector;
- }
- else
- isValid = false;
- }
-
- g_nTrackDrive1 = nDisk1Track;
- g_nTrackDrive2 = nDisk2Track;
-
- if( !isValid )
- {
- if (nActiveFloppy == 0) g_nSectorDrive1 = -1;
- else g_nSectorDrive2 = -1;
- }
-
- sprintf_s( g_sTrackDrive1 , sizeof(g_sTrackDrive1 ), "%2d", g_nTrackDrive1 );
- if (g_nSectorDrive1 < 0) sprintf_s( g_sSectorDrive1, sizeof(g_sSectorDrive1), "??" );
- else sprintf_s( g_sSectorDrive1, sizeof(g_sSectorDrive1), "%2d", g_nSectorDrive1 );
-
- sprintf_s( g_sTrackDrive2 , sizeof(g_sTrackDrive2), "%2d", g_nTrackDrive2 );
- if (g_nSectorDrive2 < 0) sprintf_s( g_sSectorDrive2, sizeof(g_sSectorDrive2), "??" );
- else sprintf_s( g_sSectorDrive2, sizeof(g_sSectorDrive2), "%2d", g_nSectorDrive2 );
-
- // Draw Track/Sector
- FrameReleaseDC();
- HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
-
- int x = buttonx;
- int y = buttony+BUTTONS*BUTTONCY+4;
-
- SelectObject(dc,smallfont);
- SetBkMode(dc,OPAQUE);
- SetBkColor(dc,RGB(0,0,0));
- SetTextAlign(dc,TA_LEFT | TA_TOP);
-
- char text[ 16 ];
-
- if (g_bIsFullScreen)
- {
- // GH#57 - drive lights in full screen mode
-
- if (!g_bFullScreen_ShowSubunitStatus)
- return;
-
- SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive1 ] );
- TextOut(dc,x+ 3,y+2,TEXT("1"),1);
-
- SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive2 ] );
- TextOut(dc,x+13,y+2,TEXT("2"),1);
-
- int dx = 0;
- if( nActiveFloppy == 0 )
- sprintf( text, "%s/%s ", g_sTrackDrive1, g_sSectorDrive1 );
- else
- sprintf( text, "%s/%s ", g_sTrackDrive2, g_sSectorDrive2 );
-
- SetTextColor(dc, g_aDiskFullScreenColorsLED[ DISK_STATUS_READ ] );
- TextOut(dc,x+dx,y-12,text, strlen(text) ); // original: y+2; y-12 puts status in the Configuration Button Icon
- }
- else
- {
- // NB. Only draw Track/Sector if 2x windowed
- if (g_nViewportScale == 1)
- return;
-
- // Erase background
- SelectObject(dc,GetStockObject(NULL_PEN));
- SelectObject(dc,btnfacebrush);
- Rectangle(dc,x+4,y+32,x+BUTTONCX+1,y+56); // y+35 -> 44 -> 56
-
- SetTextColor(dc,RGB(0,0,0));
- SetBkMode(dc,TRANSPARENT);
-
- sprintf( text, "T%s", g_sTrackDrive1 );
- TextOut(dc,x+6, y+32, text, strlen(text) );
- sprintf( text, "S%s", g_sSectorDrive1 );
- TextOut(dc,x+6, y+42, text, strlen(text) );
-
- sprintf( text, "T%s", g_sTrackDrive2 );
- TextOut(dc,x+26,y+32, text, strlen(text) );
- sprintf( text, "S%s", g_sSectorDrive2 );
- TextOut(dc,x+26,y+42, text, strlen(text) );
- }
-}
-
-//===========================================================================
-static void DrawStatusArea (HDC passdc, int drawflags)
-{
- if (g_hFrameWindow == NULL)
- {
- // TC: Fix drawing of drive buttons before frame created:
- // . Main init loop: LoadConfiguration() called before FrameCreateWindow(), eg:
- // LoadConfiguration() -> Disk_LoadLastDiskImage() -> DiskInsert() -> FrameRefreshStatus()
- return;
- }
-
- FrameReleaseDC();
- HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
- int x = buttonx;
- int y = buttony+BUTTONS*BUTTONCY+1;
- const bool bCaps = KeybGetCapsStatus();
- //const bool bP8Caps = KeybGetP8CapsStatus(); // TODO: FIXME: Not used ?! Should show the LED status ...
-
-#if HD_LED
- // 1.19.0.0 Hard Disk Status/Indicator Light
- Disk_Status_e eHardDriveStatus = DISK_STATUS_OFF;
- HD_GetLightStatus(&eHardDriveStatus);
-#endif
-
- if (g_bIsFullScreen)
- {
- if (!g_bFullScreen_ShowSubunitStatus)
- {
- // Erase Config button icon too, as trk/sec is written here - see FrameDrawDiskStatus()
- RECT rect = {x-2,y-BUTTONCY,x+BUTTONCX+2,y+BUTTONCY}; // Extend rect's width by +/-2 as the TITLE_PAUSED text is wider than an icon button
- FillRect(dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
- }
- else
- {
- SelectObject(dc,smallfont);
-
- if (drawflags & DRAW_DISK_STATUS)
- FrameDrawDiskStatus( dc );
-
-#if HD_LED
- SetTextAlign(dc, TA_RIGHT | TA_TOP);
- SetTextColor(dc, g_aDiskFullScreenColorsLED[ eHardDriveStatus ] );
- TextOut(dc,x+23,y+2,TEXT("H"),1);
-#endif
-
- if (!IS_APPLE2)
- {
- SetTextAlign(dc,TA_RIGHT | TA_TOP);
- SetTextColor(dc,(bCaps
- ? RGB(128,128,128)
- : RGB( 0, 0, 0) ));
-
- TextOut(dc,x+BUTTONCX,y+2,TEXT("A"),1); // NB. Caps Lock indicator is already flush right!
- }
-
- //
-
- static const char* pCurrentAppModeText = NULL;
-
- const char* const pNewAppModeText = (g_nAppMode == MODE_PAUSED)
- ? TITLE_PAUSED
- : (g_nAppMode == MODE_STEPPING)
- ? TITLE_STEPPING
- : NULL;
-
- SetTextAlign(dc, TA_CENTER | TA_TOP);
-
- if (pCurrentAppModeText && pNewAppModeText != pCurrentAppModeText)
- {
- SetTextColor(dc, RGB(0,0,0));
- TextOut(dc, x+BUTTONCX/2, y+13, pCurrentAppModeText, strlen(pCurrentAppModeText));
- pCurrentAppModeText = NULL;
- }
-
- if (pNewAppModeText)
- {
- SetTextColor(dc, RGB(255,255,255));
- TextOut(dc, x+BUTTONCX/2, y+13, pNewAppModeText, strlen(pNewAppModeText));
- pCurrentAppModeText = pNewAppModeText;
- }
- }
- }
- else // !g_bIsFullScreen
- {
- if (drawflags & DRAW_BACKGROUND)
- {
- SelectObject(dc,GetStockObject(NULL_PEN));
- SelectObject(dc,btnfacebrush);
- Rectangle(dc,x,y,x+BUTTONCX+2,y+34);
- Draw3dRect(dc,x+1,y+3,x+BUTTONCX,y+30,0);
-
- SelectObject(dc,smallfont);
- SetTextAlign(dc,TA_CENTER | TA_TOP);
- SetTextColor(dc,RGB(0,0,0));
- SetBkMode(dc,TRANSPARENT);
- TextOut(dc,x+ 7,y+5,TEXT("1"),1);
- TextOut(dc,x+27,y+5,TEXT("2"),1);
-
- // 1.19.0.0 Hard Disk Status/Indicator Light
- TextOut(dc,x+ 7,y+17,TEXT("H"),1);
- }
-
- if (drawflags & DRAW_LEDS)
- {
- FrameDrawDiskLEDS( dc );
-
- if (drawflags & DRAW_DISK_STATUS)
- FrameDrawDiskStatus( dc );
-
- if (!IS_APPLE2)
- {
- RECT rCapsLed = {0,0,10,12}; // HACK: HARD-CODED bitmaps size
- switch (g_Apple2Type)
- {
- case A2TYPE_APPLE2 :
- case A2TYPE_APPLE2PLUS :
- case A2TYPE_APPLE2E :
- case A2TYPE_APPLE2EENHANCED:
- default : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsLockBitmap[bCaps != 0]); break;
- case A2TYPE_PRAVETS82 :
- case A2TYPE_PRAVETS8M : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsBitmapP8 [bCaps != 0]); break; // TODO: FIXME: Shouldn't one of these use g_hCapsBitmapLat ??
- case A2TYPE_PRAVETS8A : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsBitmapP8 [bCaps != 0]); break;
- }
-
-#if HD_LED
- // 1.19.0.0 Hard Disk Status/Indicator Light
- RECT rDiskLed = {0,0,8,8};
- DrawBitmapRect(dc,x+12,y+18,&rDiskLed,g_hDiskWindowedLED[eHardDriveStatus]);
-#endif
- }
- }
-
- if (drawflags & DRAW_TITLE)
- {
- GetAppleWindowTitle(); // SetWindowText() // WindowTitle
- SendMessage(g_hFrameWindow,WM_SETTEXT,0,(LPARAM)g_pAppTitle.c_str());
- }
-
- if (drawflags & DRAW_BUTTON_DRIVES)
- {
- DrawButton(dc, BTN_DRIVE1);
- DrawButton(dc, BTN_DRIVE2);
- }
- }
-
- if (!passdc)
- ReleaseDC(g_hFrameWindow,dc);
-}
-
-//===========================================================================
-static void EraseButton (int number) {
- RECT rect;
- rect.left = buttonx;
- rect.right = rect.left+BUTTONCX;
- rect.top = buttony+number*BUTTONCY;
- rect.bottom = rect.top+BUTTONCY;
-
- InvalidateRect(g_hFrameWindow,&rect,1);
-}
-
-//===========================================================================
-
-LRESULT CALLBACK FrameWndProc (
- HWND window,
- UINT message,
- WPARAM wparam,
- LPARAM lparam)
-{
- switch (message)
- {
- case WM_ACTIVATE: // Sent when window is activated/deactivated. wParam indicates WA_ACTIVE, WA_INACTIVE, etc
- // Eg. Deactivate when Config dialog is active, AppleWin app loses focus, etc
- JoyReset();
- SetUsingCursor(FALSE);
- RevealCursor();
- FullScreenRevealCursor();
- g_bFrameActive = (wparam != WA_INACTIVE);
- break;
-
- case WM_ACTIVATEAPP: // Sent when different app's window is activated/deactivated.
- // Eg. Deactivate when AppleWin app loses focus
- g_bAppActive = (wparam ? TRUE : FALSE);
- break;
-
- case WM_SIZE:
- switch(wparam)
- {
- case SIZE_RESTORED:
- case SIZE_MAXIMIZED:
- g_windowMinimized = false;
- break;
- case SIZE_MINIMIZED:
- g_windowMinimized = true;
- break;
- default: // SIZE_MAXSHOW, SIZE_MAXHIDE
- break;
- }
- break;
-
- case WM_CLOSE:
- LogFileOutput("WM_CLOSE\n");
- if (g_bIsFullScreen && g_bRestart)
- g_bRestartFullScreen = true;
- if (g_bIsFullScreen)
- SetNormalMode();
- if (!IsIconic(window))
- GetWindowRect(window,&framerect);
- RegSaveValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_X_POS), 1, framerect.left);
- RegSaveValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_Y_POS), 1, framerect.top);
- FrameReleaseDC();
- SetUsingCursor(FALSE);
- if (helpquit) {
- helpquit = 0;
- HtmlHelp(NULL,NULL,HH_CLOSE_ALL,0);
- }
- if (g_TimerIDEvent_100msec)
- {
- BOOL bRes = KillTimer(g_hFrameWindow, g_TimerIDEvent_100msec);
- LogFileOutput("KillTimer(g_TimerIDEvent_100msec), res=%d\n", bRes ? 1 : 0);
- g_TimerIDEvent_100msec = 0;
- }
- LogFileOutput("WM_CLOSE (done)\n");
- // Exit via DefWindowProc(), which does the default action for WM_CLOSE, which is to call DestroyWindow(), posting WM_DESTROY
- break;
-
- case WM_DESTROY:
- LogFileOutput("WM_DESTROY\n");
- DragAcceptFiles(window,0);
- if (!g_bRestart) // GH#564: Only save-state on shutdown (not on a restart)
- Snapshot_Shutdown();
- DebugDestroy();
- if (!g_bRestart) {
- GetCardMgr().GetDisk2CardMgr().Destroy();
- ImageDestroy();
- HD_Destroy();
- }
- PrintDestroy();
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommDestroy();
- CpuDestroy();
- MemDestroy();
- SpkrDestroy();
- WinVideoDestroy();
- MB_Destroy();
- DeleteGdiObjects();
- DIMouse::DirectInputUninit(window); // NB. do before window is destroyed
- PostQuitMessage(0); // Post WM_QUIT message to the thread's message queue
- LogFileOutput("WM_DESTROY (done)\n");
- break;
-
- case WM_CREATE:
- LogFileOutput("WM_CREATE\n");
- g_hFrameWindow = window; // NB. g_hFrameWindow by CreateWindow()
-
- CreateGdiObjects();
- LogFileOutput("WM_CREATE: CreateGdiObjects()\n");
-
- DSInit();
- LogFileOutput("WM_CREATE: DSInit()\n");
-
- DIMouse::DirectInputInit(window);
- LogFileOutput("WM_CREATE: DIMouse::DirectInputInit()\n");
-
- MB_Initialize();
- LogFileOutput("WM_CREATE: MB_Initialize()\n");
-
- SpkrInitialize();
- LogFileOutput("WM_CREATE: SpkrInitialize()\n");
-
- DragAcceptFiles(window,1);
- LogFileOutput("WM_CREATE: DragAcceptFiles()\n");
-
- LogFileOutput("WM_CREATE (done)\n");
- break;
-
- case WM_DDE_INITIATE: {
- LogFileOutput("WM_DDE_INITIATE\n");
- ATOM application = GlobalAddAtom(TEXT("applewin"));
- ATOM topic = GlobalAddAtom(TEXT("system"));
- if(LOWORD(lparam) == application && HIWORD(lparam) == topic)
- SendMessage((HWND)wparam,WM_DDE_ACK,(WPARAM)window,MAKELPARAM(application,topic));
- GlobalDeleteAtom(application);
- GlobalDeleteAtom(topic);
- LogFileOutput("WM_DDE_INITIATE (done)\n");
- break;
- }
-
- case WM_DDE_EXECUTE:
- {
- LogFileOutput("WM_DDE_EXECUTE\n");
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- {
- Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
- LPTSTR filename = (LPTSTR)GlobalLock((HGLOBAL)lparam);
- ImageError_e Error = disk2Card.InsertDisk(DRIVE_1, filename, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
- if (Error == eIMAGE_ERROR_NONE)
- {
- if (!g_bIsFullScreen)
- DrawButton((HDC)0,BTN_DRIVE1);
-
- PostMessage(window, WM_USER_BOOT, 0, 0);
- }
- else
- {
- disk2Card.NotifyInvalidImage(DRIVE_1, filename, Error);
- }
- }
- GlobalUnlock((HGLOBAL)lparam);
- LogFileOutput("WM_DDE_EXECUTE (done)\n");
- break;
- }
-
- case WM_DISPLAYCHANGE:
- VideoReinitialize();
- break;
-
- case WM_DROPFILES:
- {
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- {
- Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
- TCHAR filename[MAX_PATH];
- DragQueryFile((HDROP)wparam,0,filename,sizeof(filename));
- POINT point;
- DragQueryPoint((HDROP)wparam,&point);
- RECT rect;
- rect.left = buttonx;
- rect.right = rect.left+BUTTONCX+1;
- rect.top = buttony+BTN_DRIVE2*BUTTONCY+1;
- rect.bottom = rect.top+BUTTONCY;
- const int iDrive = PtInRect(&rect,point) ? DRIVE_2 : DRIVE_1;
- ImageError_e Error = disk2Card.InsertDisk(iDrive, filename, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
- if (Error == eIMAGE_ERROR_NONE)
- {
- if (!g_bIsFullScreen)
- DrawButton((HDC)0,PtInRect(&rect,point) ? BTN_DRIVE2 : BTN_DRIVE1);
- rect.top = buttony+BTN_DRIVE1*BUTTONCY+1;
- if (!PtInRect(&rect,point))
- {
- SetForegroundWindow(window);
- ProcessButtonClick(BTN_RUN);
- }
- }
- else
- {
- disk2Card.NotifyInvalidImage(iDrive, filename, Error);
- }
- }
- DragFinish((HDROP)wparam);
- break;
- }
-
- // @see: http://answers.google.com/answers/threadview?id=133059
- // Win32 doesn't pass the PrintScreen key via WM_CHAR
- // else if (wparam == VK_SNAPSHOT)
- // Solution: 2 choices:
- // 1) register hotkey, or
- // 2) Use low level Keyboard hooks
- // We use the 1st one since it is compatible with Win95
- case WM_HOTKEY:
- // wparam = user id
- // lparam = modifiers: shift, ctrl, alt, win
- if (wparam == VK_SNAPSHOT_560)
- {
-#if _DEBUG
-// MessageBox( g_hFrameWindow, "Double 580x384 size!", "PrintScreen", MB_OK );
-#endif
- Video_TakeScreenShot( SCREENSHOT_560x384 );
- }
- else
- if (wparam == VK_SNAPSHOT_280) // ( lparam & MOD_SHIFT )
- {
-#if _DEBUG
-// MessageBox( g_hFrameWindow, "Normal 280x192 size!", "PrintScreen", MB_OK );
-#endif
- Video_TakeScreenShot( SCREENSHOT_280x192 );
- }
- else
- if (wparam == VK_SNAPSHOT_TEXT) // ( lparam & MOD_CONTROL )
- {
- char *pText;
- size_t nSize = 0;
-
- // if viewing the debugger, get the last virtual debugger screen
- if ((g_nAppMode == MODE_DEBUG) && !DebugGetVideoMode(NULL))
- nSize = Util_GetDebuggerText( pText );
- else
- nSize = Util_GetTextScreen( pText );
- Util_CopyTextToClipboard( nSize, pText );
- }
- break;
-
- case WM_KEYDOWN:
- KeybUpdateCtrlShiftStatus();
-
- // Processing is done in WM_KEYUP for: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
- if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == -1))
- {
- SetUsingCursor(FALSE);
- buttondown = wparam-VK_F1;
- if (g_bIsFullScreen && (buttonover != -1)) {
- if (buttonover != buttondown)
- EraseButton(buttonover);
- buttonover = -1;
- }
- DrawButton((HDC)0,buttondown);
- }
- else if (wparam == VK_F9)
- {
- // F9 Next Video Mode
- // SHIFT+F9 Prev Video Mode
- // CTRL+SHIFT+F9 Toggle 50% Scan Lines
- // ALT+F9 Can't use Alt-F9 as Alt is Open-Apple = Joystick Button #1
-
- if ( !KeybGetCtrlStatus() && !KeybGetShiftStatus() ) // F9
- {
- g_eVideoType++;
- if (g_eVideoType >= NUM_VIDEO_MODES)
- g_eVideoType = 0;
- }
- else if ( !KeybGetCtrlStatus() && KeybGetShiftStatus() ) // SHIFT+F9
- {
- if (g_eVideoType <= 0)
- g_eVideoType = NUM_VIDEO_MODES;
- g_eVideoType--;
- }
- else if ( KeybGetCtrlStatus() && KeybGetShiftStatus() ) // CTRL+SHIFT+F9
- {
- SetVideoStyle( (VideoStyle_e) (GetVideoStyle() ^ VS_HALF_SCANLINES) );
- }
-
- // TODO: Clean up code:FrameRefreshStatus(DRAW_TITLE) DrawStatusArea((HDC)0,DRAW_TITLE)
- DrawStatusArea( (HDC)0, DRAW_TITLE );
-
- VideoReinitialize(false);
-
- if (g_nAppMode != MODE_LOGO)
- {
- if (g_nAppMode == MODE_DEBUG)
- {
- UINT debugVideoMode;
- if ( DebugGetVideoMode(&debugVideoMode) )
- VideoRefreshScreen(debugVideoMode, true);
- else
- VideoRefreshScreen();
- }
- else
- {
- VideoRefreshScreen();
- }
- }
-
- Config_Save_Video();
- }
- else if (wparam == VK_F10)
- {
- if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED || g_Apple2Type == A2TYPE_BASE64A)
- {
- SetVideoRomRockerSwitch( !GetVideoRomRockerSwitch() ); // F10: toggle rocker switch
- NTSC_VideoInitAppleType();
- }
- else if (g_Apple2Type == A2TYPE_PRAVETS8A)
- {
- KeybToggleP8ACapsLock (); // F10: Toggles Pravets8A Capslock
- }
- }
- else if (wparam == VK_F11 && !KeybGetCtrlStatus()) // Save state (F11)
- {
- SoundCore_SetFade(FADE_OUT);
- if(sg_PropertySheet.SaveStateSelectImage(window, true))
- {
- Snapshot_SaveState();
- }
- SoundCore_SetFade(FADE_IN);
- }
- else if (wparam == VK_F12) // Load state (F12 or Ctrl+F12)
- {
- SoundCore_SetFade(FADE_OUT);
- if(sg_PropertySheet.SaveStateSelectImage(window, false))
- {
- Snapshot_LoadState();
- }
- SoundCore_SetFade(FADE_IN);
- }
- else if (wparam == VK_CAPITAL)
- {
- KeybToggleCapsLock();
- }
- else if (wparam == VK_PAUSE)
- {
- SetUsingCursor(FALSE);
- switch (g_nAppMode)
- {
- case MODE_RUNNING:
- g_nAppMode = MODE_PAUSED;
- SoundCore_SetFade(FADE_OUT);
- RevealCursor();
- break;
- case MODE_PAUSED:
- g_nAppMode = MODE_RUNNING;
- SoundCore_SetFade(FADE_IN);
- // Don't call FrameShowCursor(FALSE) else ClipCursor() won't be called
- break;
- case MODE_STEPPING:
- SoundCore_SetFade(FADE_OUT);
- DebugStopStepping();
- break;
- }
- DrawStatusArea((HDC)0,DRAW_TITLE);
- if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG))
- VideoRedrawScreen();
- }
- else if ((wparam == VK_SCROLL) && sg_PropertySheet.GetScrollLockToggle())
- {
- g_bScrollLock_FullSpeed = !g_bScrollLock_FullSpeed;
- }
- else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_LOGO) || (g_nAppMode == MODE_STEPPING))
- {
- // NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
- // . NB. The keyboard hook filter will suppress VK_LCONTROL (if -hook-altgr-control is passed on the cmd-line)
- bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
- bool down = true;
- bool autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
- BOOL IsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
-
-#if DEBUG_KEY_MESSAGES
- LogOutput("WM_KEYDOWN: %08X (scanCode=%04X)\n", wparam, (lparam>>16)&0xfff);
-#endif
- if (!IsJoyKey &&
- (g_nAppMode != MODE_LOGO)) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
- {
- // GH#678 Alternate key(s) to toggle max speed
- // . Ctrl-0: Toggle speed: custom speed / Full-Speed
- // . Ctrl-1: Speed = 1 MHz
- // . Ctrl-3: Speed = Full-Speed
- bool keyHandled = false;
- if( KeybGetCtrlStatus() &&
- !KeybGetAltStatus() && // GH#749 - AltGr also fakes CTRL being pressed!
- wparam >= '0' && wparam <= '9' )
- {
- switch (wparam)
- {
- case '0': // Toggle speed: custom speed / Full-Speed
- if (g_dwSpeed == SPEED_MAX)
- REGLOAD_DEFAULT(TEXT(REGVALUE_EMULATION_SPEED), &g_dwSpeed, SPEED_NORMAL);
- else
- g_dwSpeed = SPEED_MAX;
- keyHandled = true; break;
- case '1': // Speed = 1 MHz
- g_dwSpeed = SPEED_NORMAL;
- REGSAVE(TEXT(REGVALUE_EMULATION_SPEED), g_dwSpeed);
- keyHandled = true; break;
- case '3': // Speed = Full-Speed
- g_dwSpeed = SPEED_MAX;
- keyHandled = true; break;
- default:
- break;
- }
-
- if (keyHandled)
- SetCurrentCLK6502();
- }
-
- if (!keyHandled)
- KeybQueueKeypress(wparam, NOT_ASCII);
-
- if (!autorep)
- KeybAnyKeyDown(WM_KEYDOWN, wparam, extended);
- }
- }
- else if (g_nAppMode == MODE_DEBUG)
- {
- DebuggerProcessKey(wparam); // Debugger already active, re-direct key to debugger
- }
- break;
-
- case WM_CHAR:
- if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_LOGO))
- {
- if (!g_bDebuggerEatKey)
- {
-#if DEBUG_KEY_MESSAGES
- LogOutput("WM_CHAR: %08X\n", wparam);
-#endif
- if (g_nAppMode != MODE_LOGO) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
- KeybQueueKeypress(wparam, ASCII);
- }
-
- g_bDebuggerEatKey = false;
- }
- else if (g_nAppMode == MODE_DEBUG)
- {
- DebuggerInputConsoleChar((TCHAR)wparam);
- }
- break;
-
- case WM_KEYUP:
- if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1))
- {
- buttondown = -1;
- if (g_bIsFullScreen)
- EraseButton(wparam-VK_F1);
- else
- DrawButton((HDC)0,wparam-VK_F1);
-
- const int iButton = wparam-VK_F1;
- if (KeybGetCtrlStatus() && (wparam == VK_F3 || wparam == VK_F4)) // Ctrl+F3/F4 for drive pop-up menu (GH#817)
- {
- POINT pt; // location of mouse click
- pt.x = buttonx + BUTTONCX/2;
- pt.y = buttony + BUTTONCY/2 + iButton * BUTTONCY;
- const int iDrive = wparam - VK_F3;
- ProcessDiskPopupMenu( window, pt, iDrive );
-
- FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
- DrawButton((HDC)0, iButton);
- }
- else
- {
- ProcessButtonClick(iButton, true);
- }
- }
- else
- {
- bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
- bool down = false;
- bool autorep = false;
- BOOL bIsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
-
-#if DEBUG_KEY_MESSAGES
- LogOutput("WM_KEYUP: %08X\n", wparam);
-#endif
- if (!bIsJoyKey)
- KeybAnyKeyDown(WM_KEYUP, wparam, extended);
- }
- break;
-
- case WM_LBUTTONDOWN:
- KeybUpdateCtrlShiftStatus();
-
- if (buttondown == -1)
- {
- int x = LOWORD(lparam);
- int y = HIWORD(lparam);
- if ((x >= buttonx) &&
- (y >= buttony) &&
- (y <= buttony+BUTTONS*BUTTONCY))
- {
- buttonactive = buttondown = (y-buttony-1)/BUTTONCY;
- DrawButton((HDC)0,buttonactive);
- SetCapture(window);
- }
- else if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
- {
- if (wparam & (MK_CONTROL | MK_SHIFT))
- {
- SetUsingCursor(FALSE);
- }
- else
- {
- JoySetButton(BUTTON0, BUTTON_DOWN);
- }
- }
- else if ( ((x < buttonx) && JoyUsingMouse() && ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING))) )
- {
- SetUsingCursor(TRUE);
- }
- else if (GetCardMgr().IsMouseCardInstalled())
- {
- if (wparam & (MK_CONTROL | MK_SHIFT))
- {
- RevealCursor();
- }
- else if (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING)
- {
- CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard();
-
- if (pMouseCard)
- {
- if (!pMouseCard->IsEnabled())
- {
- pMouseCard->SetEnabled(true);
-
- POINT Point;
- GetCursorPos(&Point);
- ScreenToClient(g_hFrameWindow, &Point);
- const int iOutOfBoundsX=0, iOutOfBoundsY=0;
- UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY, Point.x, Point.y);
-
- // Don't call SetButton() when 1st enabled (else get the confusing action of both enabling & an Apple mouse click)
- }
- else
- {
- pMouseCard->SetButton(BUTTON0, BUTTON_DOWN);
- }
- }
- }
- }
-
- DebuggerMouseClick( x, y );
- }
- RelayEvent(WM_LBUTTONDOWN,wparam,lparam);
- break;
-
- case WM_LBUTTONUP:
- if (buttonactive != -1) {
- ReleaseCapture();
- if (buttondown == buttonactive) {
- buttondown = -1;
- if (g_bIsFullScreen)
- EraseButton(buttonactive);
- else
- DrawButton((HDC)0,buttonactive);
- ProcessButtonClick(buttonactive, true);
- }
- buttonactive = -1;
- }
- else if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
- {
- JoySetButton(BUTTON0, BUTTON_UP);
- }
- else if (GetCardMgr().IsMouseCardInstalled())
- {
- GetCardMgr().GetMouseCard()->SetButton(BUTTON0, BUTTON_UP);
- }
- RelayEvent(WM_LBUTTONUP,wparam,lparam);
- break;
-
- case WM_MOUSEMOVE: {
- // MSDN: "WM_MOUSEMOVE message" : Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates...
- int x = GET_X_LPARAM(lparam);
- int y = GET_Y_LPARAM(lparam);
- int newover = (((x >= buttonx) &&
- (x <= buttonx+BUTTONCX) &&
- (y >= buttony) &&
- (y <= buttony+BUTTONS*BUTTONCY))
- ? (y-buttony-1)/BUTTONCY : -1);
- if (buttonactive != -1) {
- int newdown = (newover == buttonactive) ? buttonactive : -1;
- if (newdown != buttondown) {
- buttondown = newdown;
- DrawButton((HDC)0,buttonactive);
- }
- }
- else if (g_bIsFullScreen && (newover != buttonover) && (buttondown == -1)) {
- if (buttonover != -1)
- EraseButton(buttonover);
- buttonover = newover;
- if (buttonover != -1)
- DrawButton((HDC)0,buttonover);
- }
- else if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
- {
- DrawCrosshairs(x,y);
- JoySetPosition(x-viewportx-2, g_nViewportCX-4, y-viewporty-2, g_nViewportCY-4);
- }
- else if (GetCardMgr().IsMouseCardInstalled() && GetCardMgr().GetMouseCard()->IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING))
- {
- if (g_bLastCursorInAppleViewport)
- break;
-
- // Outside Apple viewport
-
- const int iAppleScreenMaxX = g_nViewportCX-1;
- const int iAppleScreenMaxY = g_nViewportCY-1;
- const int iBoundMinX = viewportx;
- const int iBoundMaxX = iAppleScreenMaxX;
- const int iBoundMinY = viewporty;
- const int iBoundMaxY = iAppleScreenMaxY;
-
- int iOutOfBoundsX=0, iOutOfBoundsY=0;
- if (x < iBoundMinX) iOutOfBoundsX=-1;
- if (x > iBoundMaxX) iOutOfBoundsX=1;
- if (y < iBoundMinY) iOutOfBoundsY=-1;
- if (y > iBoundMaxY) iOutOfBoundsY=1;
-
- UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY, x, y);
- }
-
- FullScreenRevealCursor();
-
- RelayEvent(WM_MOUSEMOVE,wparam,lparam);
- break;
- }
-
- case WM_TIMER:
- if (wparam == IDEVENT_TIMER_MOUSE)
- {
- // NB. Need to check /g_bAppActive/ since WM_TIMER events still occur after AppleWin app has lost focus
- if (g_bAppActive && GetCardMgr().IsMouseCardInstalled() && GetCardMgr().GetMouseCard()->IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING))
- {
- if (!g_bLastCursorInAppleViewport)
- break;
-
- // Inside Apple viewport
-
- int iOutOfBoundsX=0, iOutOfBoundsY=0;
-
- long dX,dY;
- if (DIMouse::ReadImmediateData(&dX, &dY) == S_OK)
- GetCardMgr().GetMouseCard()->SetPositionRel(dX, dY, &iOutOfBoundsX, &iOutOfBoundsY);
-
- UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY);
- }
- }
- else if (wparam == IDEVENT_TIMER_100MSEC) // GH#504
- {
- if (g_bIsFullScreen
- && !GetCardMgr().IsMouseCardInstalled() // Don't interfere if there's a mousecard present!
- && !g_bUsingCursor // Using mouse for joystick emulation (or mousecard restricted to window)
- && g_bShowingCursor
- && g_bFrameActive) // Frame inactive when eg. Config or 'Select Disk Image' dialogs are opened
- {
- g_uCount100msec++;
- if (g_uCount100msec > 20) // Hide every 2sec of mouse inactivity
- {
- FrameShowCursor(FALSE);
- }
- }
- }
- break;
-
-// VSCROLL
-// SB_LINEUP // Line Scrolling
-// SB_PAGEUP // Page Scrolling
- case WM_MOUSEWHEEL:
- if (g_nAppMode == MODE_DEBUG)
- {
- KeybUpdateCtrlShiftStatus();
- int zDelta = (short) HIWORD( wparam );
- if (zDelta > 0)
- {
- DebuggerProcessKey( VK_UP );
- }
- else
- {
- DebuggerProcessKey( VK_DOWN );
- }
- }
- break;
-
- case WM_NOTIFY: // Tooltips for Drive buttons
- if (((LPNMTTDISPINFO)lparam)->hdr.hwndFrom == tooltipwindow && ((LPNMTTDISPINFO)lparam)->hdr.code == TTN_GETDISPINFO)
- {
- LPNMTTDISPINFO pInfo = (LPNMTTDISPINFO)lparam;
- SendMessage(pInfo->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, 150);
-
- Disk2InterfaceCard *pDisk2Slot5 = NULL, *pDisk2Slot6 = NULL;
-
- if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2)
- pDisk2Slot5 = dynamic_cast(GetCardMgr().GetObj(SLOT5));
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- pDisk2Slot6 = dynamic_cast(GetCardMgr().GetObj(SLOT6));
-
- std::string slot5 = pDisk2Slot5 ? pDisk2Slot5->GetFullDiskFilename(((LPNMTTDISPINFO)lparam)->hdr.idFrom) : "";
- std::string slot6 = pDisk2Slot6 ? pDisk2Slot6->GetFullDiskFilename(((LPNMTTDISPINFO)lparam)->hdr.idFrom) : "";
-
- if (pDisk2Slot5)
- {
- if (slot6.empty()) slot6 = "";
- if (slot5.empty()) slot5 = "";
- slot6 = std::string("Slot6: ") + slot6;
- slot5 = std::string("Slot5: ") + slot5;
- }
-
- std::string join = (!slot6.empty() && !slot5.empty()) ? "\r\n" : "";
- driveTooltip = slot6 + join + slot5;
- ((LPNMTTDISPINFO)lparam)->lpszText = (LPTSTR)driveTooltip.c_str();
- }
- break;
-
- case WM_PAINT:
- if (GetUpdateRect(window,NULL,0)){
- DrawFrameWindow(true);
- }
- break;
-
- case WM_PALETTECHANGED:
- // To avoid creating an infinite loop, a window that receives this
- // message must not realize its palette, unless it determines that
- // wParam does not contain its own window handle.
- if ((HWND)wparam == window)
- break;
- // else fall through
-
- case WM_QUERYNEWPALETTE:
- DrawFrameWindow();
- break;
-
- case WM_RBUTTONDOWN:
- case WM_RBUTTONUP:
- if ((buttonover == -1) && (message == WM_RBUTTONUP)) // HACK: BUTTON_NONE
- {
- int x = LOWORD(lparam);
- int y = HIWORD(lparam);
-
- if ((x >= buttonx) &&
- (y >= buttony) &&
- (y <= buttony+BUTTONS*BUTTONCY))
- {
- const int iButton = (y-buttony-1)/BUTTONCY;
- const int iDrive = iButton - BTN_DRIVE1;
- if ((iButton == BTN_DRIVE1) || (iButton == BTN_DRIVE2))
- {
- {
- RECT rect; // client area
- POINT pt; // location of mouse click
-
- // Get the bounding rectangle of the client area.
- GetClientRect(window, (LPRECT) &rect);
-
- // Get the client coordinates for the mouse click.
- pt.x = GET_X_LPARAM(lparam);
- pt.y = GET_Y_LPARAM(lparam);
-
- // If the mouse click took place inside the client
- // area, execute the application-defined function
- // that displays the shortcut menu.
- if (PtInRect((LPRECT) &rect, pt))
- ProcessDiskPopupMenu( window, pt, iDrive );
- }
-
- FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
- DrawButton((HDC)0, iButton);
- }
- }
- }
-
- if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
- JoySetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP);
- else if (GetCardMgr().IsMouseCardInstalled())
- GetCardMgr().GetMouseCard()->SetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP);
-
- RelayEvent(message,wparam,lparam);
- break;
-
- case WM_SYSCOLORCHANGE:
-#if DEBUG_DD_PALETTE
- if( g_bIsFullScreen )
- OutputDebugString( "WM_SYSCOLORCHANGE: Full Screen\n" );
- else
- OutputDebugString( "WM_SYSCOLORCHANGE: Windowed\n" );
-#endif
-
- DeleteGdiObjects();
- CreateGdiObjects();
- break;
-
- case WM_SYSCOMMAND:
- switch (wparam & 0xFFF0) {
- case SC_KEYMENU:
- if (g_bIsFullScreen && g_bAppActive)
- return 0;
- break;
- case SC_MINIMIZE:
- GetWindowRect(window,&framerect);
- break;
- }
- break;
-
- case WM_SYSKEYDOWN: // ALT + any key; or F10
- KeybUpdateCtrlShiftStatus();
-
- // http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
- if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
- return 0; // NOP -- eat key
-
- PostMessage(window,WM_KEYDOWN,wparam,lparam);
-
- if ((wparam == VK_F10) || (wparam == VK_MENU)) // VK_MENU == ALT Key
- return 0;
-
- break;
-
- case WM_SYSKEYUP:
- KeybUpdateCtrlShiftStatus();
-
- // F10: no WM_KEYUP handler for VK_F10. Don't allow WM_KEYUP to pass to default handler which will show the app window's "menu" (and lose focus)
- if (wparam == VK_F10)
- return 0;
-
- if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
- ScreenWindowResize(false);
- else
- PostMessage(window,WM_KEYUP,wparam,lparam);
-
- break;
-
- case WM_MENUCHAR: // GH#556 - Suppress the Windows Default Beep (ie. Ding) whenever ALT+ is pressed
- return (MNC_CLOSE << 16) | (wparam & 0xffff);
-
- case WM_USER_BENCHMARK: {
- UpdateWindow(window);
- ResetMachineState();
- DrawStatusArea((HDC)0,DRAW_TITLE);
- HCURSOR oldcursor = SetCursor(LoadCursor(0,IDC_WAIT));
- g_nAppMode = MODE_BENCHMARK;
- VideoBenchmark();
- g_nAppMode = MODE_LOGO;
- ResetMachineState();
- SetCursor(oldcursor);
- break;
- }
-
- case WM_USER_RESTART:
- // Changed h/w config, eg. Apple computer type (][+ or //e), slot configuration, etc.
- g_bRestart = true;
- PostMessage(window,WM_CLOSE,0,0);
- break;
-
- case WM_USER_SAVESTATE: // Save state
- Snapshot_SaveState();
- break;
-
- case WM_USER_LOADSTATE: // Load state
- Snapshot_LoadState();
- break;
-
- case WM_USER_TCP_SERIAL: // TCP serial events
- {
- WORD error = WSAGETSELECTERROR(lparam);
- if (error != 0)
- {
- LogOutput("TCP Serial Winsock error 0x%X (%d)\r", error, error);
- switch (error)
- {
- case WSAENETRESET:
- case WSAECONNABORTED:
- case WSAECONNRESET:
- case WSAENOTCONN:
- case WSAETIMEDOUT:
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommTcpSerialClose();
- break;
-
- default:
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommTcpSerialCleanup();
- break;
- }
- }
- else
- {
- WORD wSelectEvent = WSAGETSELECTEVENT(lparam);
- switch(wSelectEvent)
- {
- case FD_ACCEPT:
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommTcpSerialAccept();
- break;
-
- case FD_CLOSE:
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommTcpSerialClose();
- break;
-
- case FD_READ:
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommTcpSerialReceive();
- break;
- }
- }
- break;
- }
-
- // Message posted by: WM_DDE_EXECUTE & Cmd-line boot
- case WM_USER_BOOT:
- {
- SetForegroundWindow(window);
- Sleep(500); // Wait for SetForegroundWindow() to take affect (400ms seems OK, so use 500ms to be sure)
- SoundCore_TweakVolumes();
- ProcessButtonClick(BTN_RUN);
- break;
- }
-
- // Message posted by: Cmd-line boot
- case WM_USER_FULLSCREEN:
- {
- ScreenWindowResize(false);
- break;
- }
-
- } // switch(message)
-
- return DefWindowProc(window,message,wparam,lparam);
-}
-
-
-
-//===========================================================================
-// Process: VK_F6
-static void ScreenWindowResize(const bool bCtrlKey)
-{
- static int nOldViewportScale = kDEFAULT_VIEWPORT_SCALE;
-
- if (g_bIsFullScreen) // if full screen: then switch back to normal
- {
- SetNormalMode();
- FrameResizeWindow(nOldViewportScale);
- }
- else if (bCtrlKey) // if normal screen && CTRL: then toggle scaling
- {
- FrameResizeWindow( (g_nViewportScale == 1) ? 2 : 1 ); // Toggle between 1x and 2x
- REGSAVE(TEXT(REGVALUE_WINDOW_SCALE), g_nViewportScale);
- }
- else
- {
- nOldViewportScale = g_nViewportScale;
- FrameResizeWindow(1); // reset to 1x
- SetFullScreenMode();
- }
-}
-
-static bool ConfirmReboot(bool bFromButtonUI)
-{
- if (!bFromButtonUI || !g_bConfirmReboot)
- return true;
-
- int res = MessageBox(g_hFrameWindow,
- "Are you sure you want to reboot?\n"
- "(All data will be lost!)\n"
- "\n"
- "You can skip this dialog from displaying\n"
- "in the future by unchecking:\n"
- "\n"
- " [ ] Confirm reboot\n"
- "\n"
- "in the Configuration dialog.\n"
- , "Reboot", MB_ICONWARNING|MB_YESNO);
- return res == IDYES;
-}
-
-static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
-{
- SoundCore_SetFade(FADE_OUT);
- bool bAllowFadeIn = true;
-
-#if DEBUG_DD_PALETTE
- char _text[ 80 ];
- sprintf( _text, "Button: F%d Full Screen: %d\n", button+1, g_bIsFullScreen );
- OutputDebugString( _text );
-#endif
-
- switch (button) {
-
- case BTN_HELP:
- {
- const std::string filename = g_sProgramDir + TEXT("APPLEWIN.CHM");
-
- // (GH#437) For any internet downloaded AppleWin.chm files (stored on an NTFS drive) there may be an Alt Data Stream containing a Zone Identifier
- // - try to delete it, otherwise the content won't be displayed unless it's unblock (via File Properties)
- {
- const std::string filename_with_zone_identifier = filename + TEXT(":Zone.Identifier");
- DeleteFile(filename_with_zone_identifier.c_str());
- }
-
- HtmlHelp(g_hFrameWindow,filename.c_str(),HH_DISPLAY_TOC,0);
- helpquit = 1;
- }
- break;
-
- case BTN_RUN:
- KeybUpdateCtrlShiftStatus();
- if( KeybGetCtrlStatus() )
- {
- CtrlReset();
- if (g_nAppMode == MODE_DEBUG)
- DebugDisplay(TRUE);
- return;
- }
-
- if (g_nAppMode == MODE_LOGO)
- {
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- dynamic_cast(GetCardMgr().GetRef(SLOT6)).Boot();
-
- LogFileTimeUntilFirstKeyReadReset();
- g_nAppMode = MODE_RUNNING;
- }
- else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_DEBUG) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_PAUSED))
- {
- if (ConfirmReboot(bFromButtonUI))
- {
- ResetMachineState();
-
- // NB. Don't exit debugger or stepping
-
- if (g_nAppMode == MODE_DEBUG)
- DebugDisplay(TRUE);
- }
- }
-
- DrawStatusArea((HDC)0,DRAW_TITLE);
- VideoRedrawScreen();
- break;
-
- case BTN_DRIVE1:
- case BTN_DRIVE2:
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- {
- dynamic_cast(GetCardMgr().GetRef(SLOT6)).UserSelectNewDiskImage(button-BTN_DRIVE1);
- if (!g_bIsFullScreen)
- DrawButton((HDC)0,button);
- }
- break;
-
- case BTN_DRIVESWAP:
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- {
- dynamic_cast(GetCardMgr().GetRef(SLOT6)).DriveSwap();
- }
- break;
-
- case BTN_FULLSCR:
- KeybUpdateCtrlShiftStatus();
- ScreenWindowResize( KeybGetCtrlStatus() );
- break;
-
- case BTN_DEBUG:
- if (g_nAppMode == MODE_LOGO && !GetLoadedSaveStateFlag())
- {
- // FIXME: Why is this needed? Surely when state is MODE_LOGO, then AppleII system will have been reset!
- // - Transition to MODE_LOGO when: (a) AppleWin starts, (b) there's a Config change to the AppleII h/w
- ResetMachineState();
- }
-
- if (g_nAppMode == MODE_STEPPING)
- {
- // Allow F7 to enter debugger even when not MODE_RUNNING
- DebugStopStepping();
- bAllowFadeIn = false;
- }
- else if (g_nAppMode == MODE_DEBUG)
- {
- DebugExitDebugger(); // Exit debugger, switch to MODE_RUNNING or MODE_STEPPING
- g_bDebuggerEatKey = false; // Don't "eat" the next keypress when leaving the debugger via F7 (or clicking the Debugger button)
- }
- else // MODE_RUNNING, MODE_LOGO, MODE_PAUSED
- {
- DebugBegin();
- }
- break;
-
- case BTN_SETUP:
- {
- sg_PropertySheet.Init();
- }
- break;
-
- }
-
- if((g_nAppMode != MODE_DEBUG) && (g_nAppMode != MODE_PAUSED) && bAllowFadeIn)
- {
- SoundCore_SetFade(FADE_IN);
- }
-}
-
-
-//===========================================================================
-
-// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/menus/usingmenus.asp
-// http://www.codeproject.com/menu/MenusForBeginners.asp?df=100&forumid=67645&exp=0&select=903061
-
-void ProcessDiskPopupMenu(HWND hwnd, POINT pt, const int iDrive)
-{
- if (GetCardMgr().QuerySlot(SLOT6) != CT_Disk2)
- return;
-
- Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
-
- // This is the default installation path of CiderPress.
- // It shall not be left blank, otherwise an explorer window will be open.
- TCHAR PathToCiderPress[MAX_PATH];
- RegLoadString(
- TEXT("Configuration"),
- REGVALUE_CIDERPRESSLOC,
- 1,
- PathToCiderPress,
- MAX_PATH,
- TEXT("C:\\Program Files\\faddenSoft\\CiderPress\\CiderPress.exe"));
- //TODO: A directory is open if an empty path to CiderPress is set. This has to be fixed.
-
- std::string filename1= "\"";
- filename1.append( disk2Card.GetFullName(iDrive) );
- filename1.append("\"");
- std::string sFileNameEmpty = "\"";
- sFileNameEmpty.append("\"");
-
- // Load the menu template containing the shortcut menu from the
- // application's resources.
- HMENU hmenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MENU_DISK_POPUP)); // menu template
- if (hmenu == NULL)
- return;
-
- // Get the first shortcut menu in the menu template.
- // This is the menu that TrackPopupMenu displays.
- HMENU hmenuTrackPopup = GetSubMenu(hmenu, 0); // shortcut menu
-
- // TrackPopup uses screen coordinates, so convert the
- // coordinates of the mouse click to screen coordinates.
- ClientToScreen(hwnd, (LPPOINT) &pt);
-
- // Check menu depending on current floppy protection
- {
- int iMenuItem = ID_DISKMENU_WRITEPROTECTION_OFF;
- if (disk2Card.GetProtect( iDrive ))
- iMenuItem = ID_DISKMENU_WRITEPROTECTION_ON;
-
- CheckMenuItem(hmenu, iMenuItem, MF_CHECKED);
- }
-
- if (disk2Card.IsDriveEmpty(iDrive))
- EnableMenuItem(hmenu, ID_DISKMENU_EJECT, MF_GRAYED);
-
- if (disk2Card.IsDiskImageWriteProtected(iDrive))
- {
- // If image-file is read-only (or a gzip) then disable these menu items
- EnableMenuItem(hmenu, ID_DISKMENU_WRITEPROTECTION_ON, MF_GRAYED);
- EnableMenuItem(hmenu, ID_DISKMENU_WRITEPROTECTION_OFF, MF_GRAYED);
- }
-
- // Draw and track the shortcut menu.
- int iCommand = TrackPopupMenu(
- hmenuTrackPopup
- , TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD
- , pt.x, pt.y
- , 0
- , hwnd, NULL );
-
- if (iCommand == ID_DISKMENU_EJECT)
- disk2Card.EjectDisk( iDrive );
- else
- if (iCommand == ID_DISKMENU_WRITEPROTECTION_ON)
- disk2Card.SetProtect( iDrive, true );
- else
- if (iCommand == ID_DISKMENU_WRITEPROTECTION_OFF)
- disk2Card.SetProtect( iDrive, false );
- else
- if (iCommand == ID_DISKMENU_SENDTO_CIDERPRESS)
- {
- static char szCiderpressNotFoundCaption[] = "CiderPress not found";
- static char szCiderpressNotFoundText[] = "CiderPress not found!\n"
- "Please install CiderPress.\n"
- "Otherwise set the path to CiderPress from Configuration->Disk.";
-
- disk2Card.FlushCurrentTrack(iDrive);
-
- //if(!filename1.compare("\"\"") == false) //Do not use this, for some reason it does not work!!!
- if(!filename1.compare(sFileNameEmpty) )
- {
- int MB_Result = MessageBox(g_hFrameWindow, "No disk image loaded. Do you want to run CiderPress anyway?" ,"No disk image.", MB_ICONINFORMATION|MB_YESNO);
- if (MB_Result == IDYES)
- {
- if (FileExists (PathToCiderPress ))
- {
- HINSTANCE nResult = ShellExecute(NULL, "open", PathToCiderPress, "" , NULL, SW_SHOWNORMAL);
- }
- else
- {
- MessageBox(g_hFrameWindow, szCiderpressNotFoundText, szCiderpressNotFoundCaption, MB_ICONINFORMATION|MB_OK);
- }
- }
- }
- else
- {
- if (FileExists (PathToCiderPress ))
- {
- HINSTANCE nResult = ShellExecute(NULL, "open", PathToCiderPress, filename1.c_str() , NULL, SW_SHOWNORMAL);
- }
- else
- {
- MessageBox(g_hFrameWindow, szCiderpressNotFoundText, szCiderpressNotFoundCaption, MB_ICONINFORMATION|MB_OK);
- }
- }
- }
-
- // Destroy the menu.
- BOOL bRes = DestroyMenu(hmenu);
- _ASSERT(bRes);
-}
-
-
-//===========================================================================
-void RelayEvent (UINT message, WPARAM wparam, LPARAM lparam) {
- if (g_bIsFullScreen)
- return;
- MSG msg;
- msg.hwnd = g_hFrameWindow;
- msg.message = message;
- msg.wParam = wparam;
- msg.lParam = lparam;
- SendMessage(tooltipwindow,TTM_RELAYEVENT,0,(LPARAM)&msg);
-}
-
-//===========================================================================
-
-// CtrlReset() vs ResetMachineState():
-// . CPU:
-// Ctrl+Reset : 6502.sp=-3 / CpuReset()
-// Power cycle: 6502.sp=0x1ff / CpuInitialize()
-// . Disk][:
-// Ctrl+Reset : if motor-on, then motor-off but continue to spin for 1s
-// Power cycle: motor-off & immediately stop spinning
-
-// todo: consolidate CtrlReset() and ResetMachineState()
-void ResetMachineState ()
-{
- GetCardMgr().GetDisk2CardMgr().Reset(true);
- HD_Reset();
- g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
-
- MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset()
- PravetsReset();
- if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
- dynamic_cast(GetCardMgr().GetRef(SLOT6)).Boot();
- VideoResetState();
- KeybReset();
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommReset();
- PrintReset();
- JoyReset();
- MB_Reset();
- SpkrReset();
- if (GetCardMgr().IsMouseCardInstalled())
- GetCardMgr().GetMouseCard()->Reset();
- SetActiveCpu( GetMainCpu() );
-#ifdef USE_SPEECH_API
- g_Speech.Reset();
-#endif
-
- SoundCore_SetFade(FADE_NONE);
- LogFileTimeUntilFirstKeyReadReset();
-}
-
-
-//===========================================================================
-
-/*
- * In comments, UTAII is an abbreviation for a reference to "Understanding the Apple II" by James Sather
- */
-
-// todo: consolidate CtrlReset() and ResetMachineState()
-// Ctrl+Reset - TODO: This is a terrible place for this code! Should be in AppleWin.cpp
-void CtrlReset()
-{
- if (!IS_APPLE2)
- {
- // For A][ & A][+, reset doesn't reset the LC switches (UTAII:5-29)
- MemResetPaging();
-
- // For A][ & A][+, reset doesn't reset the video mode (UTAII:4-4)
- VideoResetState(); // Switch Alternate char set off
- }
-
- if (IsAppleIIeOrAbove(GetApple2Type()) || IsCopamBase64A(GetApple2Type()))
- {
- // For A][ & A][+, reset doesn't reset the annunciators (UTAIIe:I-5)
- // Base 64A: on RESET does reset to ROM page 0 (GH#807)
- MemAnnunciatorReset();
- }
-
- PravetsReset();
- GetCardMgr().GetDisk2CardMgr().Reset();
- HD_Reset();
- KeybReset();
- if (GetCardMgr().IsSSCInstalled())
- GetCardMgr().GetSSC()->CommReset();
- MB_Reset();
- if (GetCardMgr().IsMouseCardInstalled())
- GetCardMgr().GetMouseCard()->Reset(); // Deassert any pending IRQs - GH#514
-#ifdef USE_SPEECH_API
- g_Speech.Reset();
-#endif
-
- CpuReset();
- g_bFreshReset = true;
-}
-
-
-//===========================================================================
-
-int GetFullScreenOffsetX(void)
-{
- return g_win_fullscreen_offsetx;
-}
-
-int GetFullScreenOffsetY(void)
-{
- return g_win_fullscreen_offsety;
-}
-
-void SetFullScreenMode ()
-{
-#ifdef NO_DIRECT_X
-
- return;
-
-#else // NO_DIRECT_X
-
- MONITORINFO monitor_info;
- FULLSCREEN_SCALE_TYPE width, height, scalex, scaley;
- int top, left;
-
- buttonover = -1;
-
- g_main_window_saved_style = GetWindowLong(g_hFrameWindow, GWL_STYLE);
- g_main_window_saved_exstyle = GetWindowLong(g_hFrameWindow, GWL_EXSTYLE);
- GetWindowRect(g_hFrameWindow, &g_main_window_saved_rect);
- SetWindowLong(g_hFrameWindow, GWL_STYLE , g_main_window_saved_style & ~(WS_CAPTION | WS_THICKFRAME));
- SetWindowLong(g_hFrameWindow, GWL_EXSTYLE, g_main_window_saved_exstyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
-
- monitor_info.cbSize = sizeof(monitor_info);
- GetMonitorInfo(MonitorFromWindow(g_hFrameWindow, MONITOR_DEFAULTTONEAREST), &monitor_info);
-
- left = monitor_info.rcMonitor.left;
- top = monitor_info.rcMonitor.top;
-
- width = (FULLSCREEN_SCALE_TYPE)(monitor_info.rcMonitor.right - monitor_info.rcMonitor.left);
- height = (FULLSCREEN_SCALE_TYPE)(monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top );
-
- scalex = width / GetFrameBufferBorderlessWidth();
- scaley = height / GetFrameBufferBorderlessHeight();
-
- g_win_fullscreen_scale = (scalex <= scaley) ? scalex : scaley;
- g_win_fullscreen_offsetx = ((int)width - (int)(g_win_fullscreen_scale * GetFrameBufferBorderlessWidth())) / 2;
- g_win_fullscreen_offsety = ((int)height - (int)(g_win_fullscreen_scale * GetFrameBufferBorderlessHeight())) / 2;
- SetWindowPos(g_hFrameWindow, NULL, left, top, (int)width, (int)height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
- g_bIsFullScreen = true;
-
- SetViewportScale(g_win_fullscreen_scale, true);
-
- buttonx = GetFullScreenOffsetX() + g_nViewportCX + VIEWPORTX*2;
- buttony = GetFullScreenOffsetY();
- viewportx = VIEWPORTX; // TC-TODO: Should be zero too? (Since there's no 3D border in full-screen)
- viewporty = 0; // GH#464
-
- InvalidateRect(g_hFrameWindow,NULL,1);
-
-#endif // NO_DIRECT_X
-}
-
-//===========================================================================
-void SetNormalMode ()
-{
- FullScreenRevealCursor(); // Do before clearing g_bIsFullScreen flag
-
- buttonover = -1;
- buttonx = BUTTONX;
- buttony = BUTTONY;
- viewportx = VIEWPORTX;
- viewporty = VIEWPORTY;
-
- g_win_fullscreen_offsetx = 0;
- g_win_fullscreen_offsety = 0;
- g_win_fullscreen_scale = 1;
- SetWindowLong(g_hFrameWindow, GWL_STYLE, g_main_window_saved_style);
- SetWindowLong(g_hFrameWindow, GWL_EXSTYLE, g_main_window_saved_exstyle);
- SetWindowPos(g_hFrameWindow, NULL,
- g_main_window_saved_rect.left,
- g_main_window_saved_rect.top,
- g_main_window_saved_rect.right - g_main_window_saved_rect.left,
- g_main_window_saved_rect.bottom - g_main_window_saved_rect.top,
- SWP_SHOWWINDOW);
- g_bIsFullScreen = false;
-}
-
-//===========================================================================
-static void SetUsingCursor (BOOL bNewValue)
-{
- if (bNewValue == g_bUsingCursor)
- return;
-
- g_bUsingCursor = bNewValue;
-
- if (g_bUsingCursor)
- {
- // Set TRUE when:
- // . Using mouse for joystick emulation
- // . Using mousecard and mouse is restricted to window
- SetCapture(g_hFrameWindow);
- RECT rect = { viewportx+2, // left
- viewporty+2, // top
- viewportx+g_nViewportCX-1, // right
- viewporty+g_nViewportCY-1}; // bottom
- ClientToScreen(g_hFrameWindow,(LPPOINT)&rect.left);
- ClientToScreen(g_hFrameWindow,(LPPOINT)&rect.right);
- ClipCursor(&rect);
- FrameShowCursor(FALSE);
- POINT pt;
- GetCursorPos(&pt);
- ScreenToClient(g_hFrameWindow,&pt);
- DrawCrosshairs(pt.x,pt.y);
- }
- else
- {
- DrawCrosshairs(0,0);
- FrameShowCursor(TRUE);
- ClipCursor(NULL);
- ReleaseCapture();
- }
-}
-
-int GetViewportScale(void)
-{
- return g_nViewportScale;
-}
-
-int SetViewportScale(int nNewScale, bool bForce /*=false*/)
-{
- if (!bForce && nNewScale > g_nMaxViewportScale)
- nNewScale = g_nMaxViewportScale;
-
- g_nViewportScale = nNewScale;
- g_nViewportCX = g_nViewportScale * GetFrameBufferBorderlessWidth();
- g_nViewportCY = g_nViewportScale * GetFrameBufferBorderlessHeight();
-
- return nNewScale;
-}
-
-static void SetupTooltipControls(void)
-{
- TOOLINFO toolinfo;
- toolinfo.cbSize = sizeof(toolinfo);
- toolinfo.uFlags = TTF_CENTERTIP;
- toolinfo.hwnd = g_hFrameWindow;
- toolinfo.hinst = g_hInstance;
- toolinfo.lpszText = LPSTR_TEXTCALLBACK;
- toolinfo.rect.left = BUTTONX;
- toolinfo.rect.right = toolinfo.rect.left+BUTTONCX+1;
- toolinfo.uId = 0;
- toolinfo.rect.top = BUTTONY+BTN_DRIVE1*BUTTONCY+1;
- toolinfo.rect.bottom = toolinfo.rect.top+BUTTONCY;
- SendMessage(tooltipwindow, TTM_ADDTOOL, 0, (LPARAM)&toolinfo);
- toolinfo.uId = 1;
- toolinfo.rect.top = BUTTONY+BTN_DRIVE2*BUTTONCY+1;
- toolinfo.rect.bottom = toolinfo.rect.top+BUTTONCY;
- SendMessage(tooltipwindow, TTM_ADDTOOL, 0, (LPARAM)&toolinfo);
-}
-
-// SM_CXPADDEDBORDER is not supported on 2000 & XP, but GetSystemMetrics() returns 0 for unknown values, so this use of SM_CXPADDEDBORDER works on 2000 & XP too:
-// http://msdn.microsoft.com/en-nz/library/windows/desktop/ms724385(v=vs.85).aspx
-// NB. GetSystemMetrics(SM_CXPADDEDBORDER) returns 0 for Win7, when built with VS2008 (see GH#571)
-static void GetWidthHeight(int& nWidth, int& nHeight)
-{
- nWidth = g_nViewportCX + VIEWPORTX*2
- + BUTTONCX
- + (GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
- nHeight = g_nViewportCY + VIEWPORTY*2
- + (GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2 // NB. No SM_CYPADDEDBORDER
- + GetSystemMetrics(SM_CYCAPTION);
-
-#if 0 // GH#571
- LogOutput("g_nViewportCX = %d\n", g_nViewportCX);
- LogOutput("VIEWPORTX = %d (const)\n", VIEWPORTX);
- LogOutput("BUTTONCX = %d (const)\n", BUTTONCX);
- LogOutput("GetSystemMetrics(SM_CXFRAME) = %d (unused)\n", GetSystemMetrics(SM_CXFRAME));
- LogOutput("GetSystemMetrics(SM_CXFIXEDFRAME) = %d\n", GetSystemMetrics(SM_CXFIXEDFRAME));
- LogOutput("GetSystemMetrics(SM_CXBORDER) = %d (unused)\n", GetSystemMetrics(SM_CXBORDER));
- LogOutput("GetSystemMetrics(SM_CXPADDEDBORDER) = %d\n", GetSystemMetrics(SM_CXPADDEDBORDER));
- LogOutput("nWidth = %d\n", nWidth);
- LogOutput("g_nViewportCY = %d\n", g_nViewportCY);
- LogOutput("VIEWPORTY = %d (const)\n", VIEWPORTY);
- LogOutput("GetSystemMetrics(SM_CYFRAME) = %d (unused)\n", GetSystemMetrics(SM_CYFRAME));
- LogOutput("GetSystemMetrics(SM_CYFIXEDFRAME) = %d\n", GetSystemMetrics(SM_CYFIXEDFRAME));
- LogOutput("GetSystemMetrics(SM_CYBORDER) = %d (unused)\n", GetSystemMetrics(SM_CYBORDER));
- LogOutput("GetSystemMetrics(SM_CYCAPTION) = %d\n", GetSystemMetrics(SM_CYCAPTION));
- LogOutput("nHeight = %d\n\n", nHeight);
-#endif
-}
-
-static void FrameResizeWindow(int nNewScale)
-{
- int nOldWidth, nOldHeight;
- GetWidthHeight(nOldWidth, nOldHeight);
-
- nNewScale = SetViewportScale(nNewScale);
-
- GetWindowRect(g_hFrameWindow, &framerect);
- int nXPos = framerect.left;
- int nYPos = framerect.top;
-
- //
-
- buttonx = g_nViewportCX + VIEWPORTX*2;
- buttony = 0;
-
- // Invalidate old rect region
- {
- RECT irect;
- irect.left = irect.top = 0;
- irect.right = nOldWidth;
- irect.bottom = nOldHeight;
- InvalidateRect(g_hFrameWindow, &irect, TRUE);
- }
-
- // Resize the window
- int nNewWidth, nNewHeight;
- GetWidthHeight(nNewWidth, nNewHeight);
-
- MoveWindow(g_hFrameWindow, nXPos, nYPos, nNewWidth, nNewHeight, TRUE);
- UpdateWindow(g_hFrameWindow);
-
- // Remove the tooltips for the old window size
- TOOLINFO toolinfo = {0};
- toolinfo.cbSize = sizeof(toolinfo);
- toolinfo.hwnd = g_hFrameWindow;
- toolinfo.uId = 0;
- SendMessage(tooltipwindow, TTM_DELTOOL, 0, (LPARAM)&toolinfo);
- toolinfo.uId = 1;
- SendMessage(tooltipwindow, TTM_DELTOOL, 0, (LPARAM)&toolinfo);
-
- // Setup the tooltips for the new window size
- SetupTooltipControls();
-}
-
-//
-// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
-//
-
-//===========================================================================
-
-void FrameCreateWindow(void)
-{
- int nWidth, nHeight;
-
- // Set g_nMaxViewportScale
- {
- int nOldViewportCX = g_nViewportCX;
- int nOldViewportCY = g_nViewportCY;
-
- g_nViewportCX = GetFrameBufferBorderlessWidth() * 2;
- g_nViewportCY = GetFrameBufferBorderlessHeight() * 2;
- GetWidthHeight(nWidth, nHeight); // Probe with 2x dimensions
-
- g_nViewportCX = nOldViewportCX;
- g_nViewportCY = nOldViewportCY;
-
- if (nWidth > GetSystemMetrics(SM_CXSCREEN) || nHeight > GetSystemMetrics(SM_CYSCREEN))
- g_nMaxViewportScale = 1;
- }
-
- GetWidthHeight(nWidth, nHeight);
-
- // If screen is too small for 2x, then revert to 1x
- if (g_nViewportScale == 2 && (nWidth > GetSystemMetrics(SM_CXSCREEN) || nHeight > GetSystemMetrics(SM_CYSCREEN)))
- {
- g_nMaxViewportScale = 1;
- SetViewportScale(1);
- GetWidthHeight(nWidth, nHeight);
- }
-
- // Restore Window X Position
- int nXPos = -1;
- {
- const int nXScreen = GetSystemMetrics(SM_CXSCREEN) - nWidth;
-
- if (RegLoadValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_X_POS), 1, (DWORD*)&nXPos))
- {
- if ((nXPos > nXScreen) && !g_bMultiMon)
- nXPos = -1; // Not fully visible, so default to centre position
- }
-
- if ((nXPos == -1) && !g_bMultiMon)
- nXPos = nXScreen / 2;
- }
-
- // Restore Window Y Position
- int nYPos = -1;
- {
- const int nYScreen = GetSystemMetrics(SM_CYSCREEN) - nHeight;
-
- if (RegLoadValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_Y_POS), 1, (DWORD*)&nYPos))
- {
- if ((nYPos > nYScreen) && !g_bMultiMon)
- nYPos = -1; // Not fully visible, so default to centre position
- }
-
- if ((nYPos == -1) && !g_bMultiMon)
- nYPos = nYScreen / 2;
- }
-
- //
-
- buttonx = (g_nViewportCX + VIEWPORTX*2);
- buttony = 0;
-
- GetAppleWindowTitle();
-
- // NB. g_hFrameWindow also set by WM_CREATE - NB. CreateWindow() must synchronously send WM_CREATE
- g_hFrameWindow = CreateWindow(
- TEXT("APPLE2FRAME"),
- g_pAppTitle.c_str(),
- WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
- WS_MINIMIZEBOX | WS_VISIBLE,
- nXPos, nYPos, nWidth, nHeight,
- HWND_DESKTOP,
- (HMENU)0,
- g_hInstance, NULL );
-
- InitCommonControls();
- tooltipwindow = CreateWindow(
- TOOLTIPS_CLASS,NULL,TTS_ALWAYSTIP,
- CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
- g_hFrameWindow,
- (HMENU)0,
- g_hInstance,NULL );
-
- SetupTooltipControls();
-
- _ASSERT(g_TimerIDEvent_100msec == 0);
- g_TimerIDEvent_100msec = SetTimer(g_hFrameWindow, IDEVENT_TIMER_100MSEC, 100, NULL);
- LogFileOutput("FrameCreateWindow: SetTimer(), id=0x%08X\n", g_TimerIDEvent_100msec);
-}
-
-//===========================================================================
-HDC FrameGetDC () {
- if (!g_hFrameDC) {
- g_hFrameDC = GetDC(g_hFrameWindow);
- SetViewportOrgEx(g_hFrameDC,viewportx,viewporty,NULL);
- }
- return g_hFrameDC;
-}
-
-//===========================================================================
-void FrameReleaseDC () {
- if (g_hFrameDC) {
- SetViewportOrgEx(g_hFrameDC,0,0,NULL);
- ReleaseDC(g_hFrameWindow,g_hFrameDC);
- g_hFrameDC = (HDC)0;
- }
-}
-
-//===========================================================================
-void FrameRefreshStatus (int drawflags, bool bUpdateDiskStatus) {
- // NB. 99% of the time we draw the disk status. On DiskDriveSwap() we don't.
- drawflags |= bUpdateDiskStatus ? DRAW_DISK_STATUS : 0;
- DrawStatusArea((HDC)0,drawflags);
-}
-
-//===========================================================================
-void FrameRegisterClass () {
- WNDCLASSEX wndclass;
- ZeroMemory(&wndclass,sizeof(WNDCLASSEX));
- wndclass.cbSize = sizeof(WNDCLASSEX);
- wndclass.style = CS_OWNDC | CS_BYTEALIGNCLIENT;
- wndclass.lpfnWndProc = FrameWndProc;
- wndclass.hInstance = g_hInstance;
- wndclass.hIcon = LoadIcon(g_hInstance,TEXT("APPLEWIN_ICON"));
- wndclass.hCursor = LoadCursor(0,IDC_ARROW);
- wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
-#if ENABLE_MENU
- wndclass.lpszMenuName = (LPCSTR)IDR_MENU1;
-#endif
- wndclass.lpszClassName = TEXT("APPLE2FRAME");
- wndclass.hIconSm = (HICON)LoadImage(g_hInstance,TEXT("APPLEWIN_ICON"),
- IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
- RegisterClassEx(&wndclass);
-}
-
-//===========================================================================
-// TODO: FIXME: Util_TestFileExists()
-static bool FileExists(std::string strFilename)
-{
- struct stat stFileInfo;
- int intStat = stat(strFilename.c_str(),&stFileInfo);
- return (intStat == 0) ? true : false;
-}
-
-//===========================================================================
-
-// Called when:
-// . Mouse f/w sets abs position
-// . UpdateMouseInAppleViewport() is called and inside Apple screen
-void FrameSetCursorPosByMousePos()
-{
-// _ASSERT(GetCardMgr().IsMouseCardInstalled()); // CMouseInterface::ctor calls this function, ie. before GetCardMgr()::m_pMouseCard is setup
- if (!GetCardMgr().IsMouseCardInstalled())
- return;
-
- if (!g_hFrameWindow || g_bShowingCursor)
- return;
-
- int iX, iMinX, iMaxX;
- int iY, iMinY, iMaxY;
- GetCardMgr().GetMouseCard()->GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
-
- float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
- float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
-
- int iWindowX = (int)(fScaleX * (float)g_nViewportCX);
- int iWindowY = (int)(fScaleY * (float)g_nViewportCY);
-
- POINT Point = {viewportx+2, viewporty+2}; // top-left
- ClientToScreen(g_hFrameWindow, &Point);
- SetCursorPos(Point.x+iWindowX-VIEWPORTX, Point.y+iWindowY-VIEWPORTY);
-
-#if defined(_DEBUG) && 0 // OutputDebugString() when cursor position changes since last time
- static int OldX=0, OldY=0;
- char szDbg[200];
- int X=Point.x+iWindowX-VIEWPORTX;
- int Y=Point.y+iWindowY-VIEWPORTY;
- if (X != OldX || Y != OldY)
- {
- sprintf(szDbg, "[FrameSetCursorPosByMousePos] x,y=%d,%d (MaxX,Y=%d,%d)\n", X,Y, iMaxX,iMaxY); OutputDebugString(szDbg);
- OldX=X; OldY=Y;
- }
-#endif
-}
-
-// Called when:
-// . UpdateMouseInAppleViewport() is called and mouse leaving/entering Apple screen area
-// . NB. Not called when leaving & mouse clipped to Apple screen area
-static void FrameSetCursorPosByMousePos(int x, int y, int dx, int dy, bool bLeavingAppleScreen)
-{
- _ASSERT(GetCardMgr().IsMouseCardInstalled());
- if (!GetCardMgr().IsMouseCardInstalled())
- return;
-
-// char szDbg[200];
- if (!g_hFrameWindow || (g_bShowingCursor && bLeavingAppleScreen) || (!g_bShowingCursor && !bLeavingAppleScreen))
- return;
-
- int iX, iMinX, iMaxX;
- int iY, iMinY, iMaxY;
- GetCardMgr().GetMouseCard()->GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
-
- if (bLeavingAppleScreen)
- {
- // Set mouse x/y pos to edge of mouse's window
- if (dx < 0) iX = iMinX;
- if (dx > 0) iX = iMaxX;
- if (dy < 0) iY = iMinY;
- if (dy > 0) iY = iMaxY;
-
- float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
- float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
-
- int iWindowX = (int)(fScaleX * (float)g_nViewportCX) + dx;
- int iWindowY = (int)(fScaleY * (float)g_nViewportCY) + dy;
-
- POINT Point = {viewportx+2, viewporty+2}; // top-left
- ClientToScreen(g_hFrameWindow, &Point);
- SetCursorPos(Point.x+iWindowX-VIEWPORTX, Point.y+iWindowY-VIEWPORTY);
-// sprintf(szDbg, "[MOUSE_LEAVING ] x=%d, y=%d (Scale: x,y=%f,%f; iX,iY=%d,%d)\n", iWindowX, iWindowY, fScaleX, fScaleY, iX, iY); OutputDebugString(szDbg);
- }
- else // Mouse entering Apple screen area
- {
-// sprintf(szDbg, "[MOUSE_ENTERING] x=%d, y=%d\n", x, y); OutputDebugString(szDbg);
- if (!g_bIsFullScreen) // GH#464
- {
- x -= (viewportx+2-VIEWPORTX); if (x < 0) x = 0;
- y -= (viewporty+2-VIEWPORTY); if (y < 0) y = 0;
- }
-
- _ASSERT(x <= g_nViewportCX);
- _ASSERT(y <= g_nViewportCY);
- float fScaleX = (float)x / (float)g_nViewportCX;
- float fScaleY = (float)y / (float)g_nViewportCY;
-
- int iAppleX = iMinX + (int)(fScaleX * (float)(iMaxX-iMinX));
- int iAppleY = iMinY + (int)(fScaleY * (float)(iMaxY-iMinY));
-
- GetCardMgr().GetMouseCard()->SetCursorPos(iAppleX, iAppleY); // Set new entry position
-
- // Dump initial deltas (otherwise can get big deltas since last read when entering Apple screen area)
- DIMouse::ReadImmediateData();
- }
-}
-
-static void DrawCrosshairsMouse()
-{
- _ASSERT(GetCardMgr().IsMouseCardInstalled());
- if (!GetCardMgr().IsMouseCardInstalled())
- return;
-
- if (!sg_PropertySheet.GetMouseShowCrosshair())
- return;
-
- int iX, iMinX, iMaxX;
- int iY, iMinY, iMaxY;
- GetCardMgr().GetMouseCard()->GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
- _ASSERT(iMinX == 0 && iMinY == 0);
-
- float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
- float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
-
- int iWindowX = (int)(fScaleX * (float)g_nViewportCX);
- int iWindowY = (int)(fScaleY * (float)g_nViewportCY);
-
- DrawCrosshairs(iWindowX,iWindowY);
-}
-
-#ifdef _DEBUG
-//#define _DEBUG_SHOW_CURSOR // NB. Get an ASSERT on LMB (after Ctrl+LMB)
-#endif
-
-static void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x, int y)
-{
- const bool bOutsideAppleViewport = iOutOfBoundsX || iOutOfBoundsY;
-
- if (bOutsideAppleViewport)
- {
- if (sg_PropertySheet.GetMouseRestrictToWindow())
- return;
-
- g_bLastCursorInAppleViewport = false;
-
- if (!g_bShowingCursor)
- {
- // Mouse leaving Apple screen area
- FrameSetCursorPosByMousePos(0, 0, iOutOfBoundsX, iOutOfBoundsY, true);
-#ifdef _DEBUG_SHOW_CURSOR
- g_bShowingCursor = true;
-#else
- FrameShowCursor(TRUE);
-#endif
- }
- }
- else
- {
- g_bLastCursorInAppleViewport = true;
-
- if (g_bShowingCursor)
- {
- // Mouse entering Apple screen area
- FrameSetCursorPosByMousePos(x, y, 0, 0, false);
-#ifdef _DEBUG_SHOW_CURSOR
- g_bShowingCursor = false;
-#else
- FrameShowCursor(FALSE);
-#endif
-
- //
-
- if (sg_PropertySheet.GetMouseRestrictToWindow())
- SetUsingCursor(TRUE);
- }
- else
- {
- FrameSetCursorPosByMousePos(); // Set cursor to Apple position each time
- }
-
- DrawCrosshairsMouse();
- }
-}
-
-void GetViewportCXCY(int& nViewportCX, int& nViewportCY)
-{
- nViewportCX = g_nViewportCX;
- nViewportCY = g_nViewportCY;
-}
-
-// Call all funcs with dependency on g_Apple2Type
-void FrameUpdateApple2Type(void)
-{
- DeleteGdiObjects();
- CreateGdiObjects();
-
- // DRAW_TITLE : calls GetAppleWindowTitle()
- // DRAW_LEDS : update LEDs (eg. CapsLock varies on Apple2 type)
- DrawStatusArea( (HDC)0, DRAW_TITLE|DRAW_LEDS );
-
- // Draw buttons & call DrawStatusArea(DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS)
- DrawFrameWindow();
-}
-
-bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight /*= 0*/)
-{
- typedef std::vector< std::pair > VEC_PAIR;
- VEC_PAIR vecDisplayResolutions;
-
- for (UINT iModeNum = 0; ; iModeNum++)
- {
- DEVMODE devMode;
- devMode.dmSize = sizeof(DEVMODE);
- devMode.dmDriverExtra = 0;
- BOOL bValid = EnumDisplaySettings(NULL, iModeNum, &devMode);
- if (!bValid)
- break;
- if (iModeNum == 0) // 0 is the initial "cache info about display device" operation
- continue;
-
- if (devMode.dmBitsPerPel != 32)
- continue;
-
- if (userSpecifiedHeight == 0 || userSpecifiedHeight == devMode.dmPelsHeight)
- {
- if (vecDisplayResolutions.size() == 0 || vecDisplayResolutions.back() != std::pair(devMode.dmPelsWidth, devMode.dmPelsHeight) ) // Skip duplicate resolutions
- {
- vecDisplayResolutions.push_back( std::pair(devMode.dmPelsWidth, devMode.dmPelsHeight) );
- LogFileOutput("EnumDisplaySettings(%d) - %d x %d\n", iModeNum, devMode.dmPelsWidth, devMode.dmPelsHeight);
- }
- }
- }
-
- if (userSpecifiedHeight)
- {
- if (vecDisplayResolutions.size() == 0)
- return false;
-
- // Pick least width (such that it's wide enough to scale)
- UINT width = (UINT)-1;
- for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it)
- {
- if (width > it->first)
- {
- UINT scaleFactor = it->second / GetFrameBufferBorderlessHeight();
- if (it->first >= (GetFrameBufferBorderlessWidth() * scaleFactor))
- {
- width = it->first;
- }
- }
- }
-
- if (width == (UINT)-1)
- return false;
-
- bestWidth = width;
- bestHeight = userSpecifiedHeight;
- return true;
- }
-
- // Pick max height that's an exact multiple of GetFrameBufferBorderlessHeight()
- UINT tmpBestWidth = 0;
- UINT tmpBestHeight = 0;
- for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it)
- {
- if ((it->second % GetFrameBufferBorderlessHeight()) == 0)
- {
- if (it->second > tmpBestHeight)
- {
- UINT scaleFactor = it->second / GetFrameBufferBorderlessHeight();
- if (it->first >= (GetFrameBufferBorderlessWidth() * scaleFactor))
- {
- tmpBestWidth = it->first;
- tmpBestHeight = it->second;
- }
- }
- }
- }
-
- if (tmpBestWidth == 0)
- return false;
-
- bestWidth = tmpBestWidth;
- bestHeight = tmpBestHeight;
- return true;
-}
diff --git a/source/Frame.h b/source/Frame.h
index 4b3a6b63..7ec2e247 100644
--- a/source/Frame.h
+++ b/source/Frame.h
@@ -3,58 +3,9 @@
// 1.19.0.0 Hard Disk Status/Indicator Light
#define HD_LED 1
-// Win32
- extern HWND g_hFrameWindow;
- extern int g_nViewportCX;
- extern int g_nViewportCY;
- extern BOOL g_bConfirmReboot; // saved PageConfig REGSAVE
- extern BOOL g_bMultiMon;
-
-
-// Emulator
- extern bool g_bFreshReset;
- extern std::string PathFilename[2];
- extern bool g_bScrollLock_FullSpeed;
-
-
-// Prototypes
- void CtrlReset();
-
- void FrameCreateWindow(void);
- HDC FrameGetDC ();
- void FrameReleaseDC ();
- void FrameRefreshStatus (int, bool bUpdateDiskStatus = true );
- void FrameRegisterClass ();
- void FrameSetCursorPosByMousePos();
- int GetViewportScale(void);
- int SetViewportScale(int nNewScale, bool bForce = false);
- void GetViewportCXCY(int& nViewportCX, int& nViewportCY);
- void FrameUpdateApple2Type(void);
- bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight=0);
-
- bool IsFullScreen(void);
- bool GetFullScreenShowSubunitStatus(void);
- void SetFullScreenShowSubunitStatus(bool bShow);
-
- void FrameDrawDiskLEDS( HDC hdc );
- void FrameDrawDiskStatus( HDC hdc );
-
- LRESULT CALLBACK FrameWndProc (
- HWND window,
- UINT message,
- WPARAM wparam,
- LPARAM lparam );
-
- int GetFullScreenOffsetX(void);
- int GetFullScreenOffsetY(void);
-
UINT GetFrameBufferBorderlessWidth(void);
UINT GetFrameBufferBorderlessHeight(void);
UINT GetFrameBufferBorderWidth(void);
UINT GetFrameBufferBorderHeight(void);
UINT GetFrameBufferWidth(void);
UINT GetFrameBufferHeight(void);
- UINT Get3DBorderWidth(void);
- UINT Get3DBorderHeight(void);
-
- void SetAltEnterToggleFullScreen(bool mode);
diff --git a/source/Harddisk.cpp b/source/Harddisk.cpp
index 537be4dd..1c6bb4a2 100644
--- a/source/Harddisk.cpp
+++ b/source/Harddisk.cpp
@@ -34,7 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "CPU.h"
#include "DiskImage.h" // ImageError_e, Disk_Status_e
#include "DiskImageHelper.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Memory.h"
#include "Registry.h"
#include "SaveState.h"
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index 00939557..dd81c9b6 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Keyboard.h"
#include "AppleWin.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Pravets.h"
#include "Tape.h"
#include "YamlHelper.h"
diff --git a/source/Memory.cpp b/source/Memory.cpp
index aa3d4cae..0b4f528e 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -35,7 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "CardManager.h"
#include "CPU.h"
#include "Disk.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Harddisk.h"
#include "Joystick.h"
#include "Keyboard.h"
diff --git a/source/MouseInterface.cpp b/source/MouseInterface.cpp
index 84d7f0cc..b1725b22 100644
--- a/source/MouseInterface.cpp
+++ b/source/MouseInterface.cpp
@@ -49,7 +49,7 @@ Etc.
#include "AppleWin.h" // g_SynchronousEventMgr
#include "CardManager.h"
#include "CPU.h"
-#include "Frame.h" // FrameSetCursorPosByMousePos()
+#include "Windows/WinFrame.h" // FrameSetCursorPosByMousePos()
#include "Log.h"
#include "Memory.h"
#include "Video.h"
diff --git a/source/ParallelPrinter.cpp b/source/ParallelPrinter.cpp
index 5c511394..6c1b90bd 100644
--- a/source/ParallelPrinter.cpp
+++ b/source/ParallelPrinter.cpp
@@ -30,7 +30,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "ParallelPrinter.h"
#include "AppleWin.h"
-#include "Frame.h" // g_hFrameWindow
#include "Memory.h"
#include "Registry.h"
#include "YamlHelper.h"
diff --git a/source/Pravets.cpp b/source/Pravets.cpp
index 66b90da1..0e65f2c8 100644
--- a/source/Pravets.cpp
+++ b/source/Pravets.cpp
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Pravets.h"
#include "AppleWin.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Keyboard.h"
#include "Tape.h"
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index 92991452..d339d870 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -36,7 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "CPU.h"
#include "Debug.h"
#include "Disk.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Joystick.h"
#include "Keyboard.h"
#include "LanguageCard.h"
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index b7c5bfa8..6ded02ad 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -38,7 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SerialComms.h"
#include "AppleWin.h"
#include "CPU.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Log.h"
#include "Memory.h"
#include "YamlHelper.h"
diff --git a/source/SoundCore.cpp b/source/SoundCore.cpp
index 3cffc649..5209ee4c 100644
--- a/source/SoundCore.cpp
+++ b/source/SoundCore.cpp
@@ -30,7 +30,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "SoundCore.h"
#include "AppleWin.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Log.h"
#include "Speaker.h"
diff --git a/source/Speaker.cpp b/source/Speaker.cpp
index 1b4bbe6d..8f0ec69f 100644
--- a/source/Speaker.cpp
+++ b/source/Speaker.cpp
@@ -31,7 +31,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Speaker.h"
#include "AppleWin.h"
#include "CPU.h"
-#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Log.h"
#include "Memory.h"
#include "SoundCore.h"
diff --git a/source/Video.cpp b/source/Video.cpp
index 4ab0475f..5dbe76d4 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -32,6 +32,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "AppleWin.h"
#include "CPU.h"
#include "Frame.h"
+#include "Windows/WinFrame.h"
#include "Log.h"
#include "Memory.h"
#include "Registry.h"
diff --git a/source/Windows/WinFrame.cpp b/source/Windows/WinFrame.cpp
new file mode 100644
index 00000000..5911eb59
--- /dev/null
+++ b/source/Windows/WinFrame.cpp
@@ -0,0 +1,3034 @@
+/*
+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: Frame
+ *
+ * Author: Various
+ */
+
+#include "StdAfx.h"
+
+#include "Windows/WinFrame.h"
+#include "AppleWin.h"
+#include "CardManager.h"
+#include "CPU.h"
+#include "Disk.h"
+#include "DiskImage.h"
+#include "Harddisk.h"
+#include "Keyboard.h"
+#include "Log.h"
+#include "Memory.h"
+#include "Mockingboard.h"
+#include "MouseInterface.h"
+#include "Windows/DirectInput.h"
+#include "NTSC.h"
+#include "ParallelPrinter.h"
+#include "Pravets.h"
+#include "Registry.h"
+#include "SaveState.h"
+#include "SerialComms.h"
+#include "SoundCore.h"
+#include "Speaker.h"
+#include "Frame.h"
+#ifdef USE_SPEECH_API
+#include "Speech.h"
+#endif
+#include "Windows/WinVideo.h"
+
+#include "../resource/resource.h"
+#include "Configuration/PropertySheet.h"
+#include "Debugger/Debug.h"
+#if _MSC_VER <= 1500 // VS2008 only (cl.exe v15.00)
+#include
+#endif
+
+//#define ENABLE_MENU 0
+#define DEBUG_KEY_MESSAGES 0
+
+// 3D border around the 560x384 Apple II display
+#define VIEWPORTX 5
+#define VIEWPORTY 5
+
+static const int kDEFAULT_VIEWPORT_SCALE = 2;
+ int g_nViewportCX = GetFrameBufferBorderlessWidth() * kDEFAULT_VIEWPORT_SCALE;
+ int g_nViewportCY = GetFrameBufferBorderlessHeight() * kDEFAULT_VIEWPORT_SCALE;
+static int g_nViewportScale = kDEFAULT_VIEWPORT_SCALE; // saved REGSAVE
+static int g_nMaxViewportScale = kDEFAULT_VIEWPORT_SCALE; // Max scale in Windowed mode with borders, buttons etc (full-screen may be +1)
+
+#define BUTTONX (g_nViewportCX + VIEWPORTX*2)
+#define BUTTONY 0
+#define BUTTONCX 45
+#define BUTTONCY 45
+#define BUTTONS 8
+
+ static HBITMAP g_hCapsLockBitmap[2];
+ static HBITMAP g_hHardDiskBitmap[2];
+
+ //Pravets8 only
+ static HBITMAP g_hCapsBitmapP8[2];
+ static HBITMAP g_hCapsBitmapLat[2];
+ //static HBITMAP charsetbitmap [4]; //The idea was to add a charset indicator on the front panel, but it was given up. All charsetbitmap occurences must be REMOVED!
+ //===========================
+ static HBITMAP g_hDiskWindowedLED[ NUM_DISK_STATUS ];
+
+static int g_nTrackDrive1 = -1;
+static int g_nTrackDrive2 = -1;
+static int g_nSectorDrive1 = -1;
+static int g_nSectorDrive2 = -1;
+static TCHAR g_sTrackDrive1 [8] = TEXT("??");
+static TCHAR g_sTrackDrive2 [8] = TEXT("??");
+static TCHAR g_sSectorDrive1[8] = TEXT("??");
+static TCHAR g_sSectorDrive2[8] = TEXT("??");
+Disk_Status_e g_eStatusDrive1 = DISK_STATUS_OFF;
+Disk_Status_e g_eStatusDrive2 = DISK_STATUS_OFF;
+
+// Must keep in sync with Disk_Status_e g_aDiskFullScreenColors
+static DWORD g_aDiskFullScreenColorsLED[ NUM_DISK_STATUS ] =
+{
+ RGB( 0, 0, 0), // DISK_STATUS_OFF BLACK
+ RGB( 0,255, 0), // DISK_STATUS_READ GREEN
+ RGB(255, 0, 0), // DISK_STATUS_WRITE RED
+ RGB(255,128, 0) // DISK_STATUS_PROT ORANGE
+// RGB( 0, 0,255) // DISK_STATUS_PROT -blue-
+};
+
+static HBITMAP buttonbitmap[BUTTONS];
+
+static bool g_bAppActive = false;
+static HBRUSH btnfacebrush = (HBRUSH)0;
+static HPEN btnfacepen = (HPEN)0;
+static HPEN btnhighlightpen = (HPEN)0;
+static HPEN btnshadowpen = (HPEN)0;
+static int buttonactive = -1;
+static int buttondown = -1;
+static int buttonover = -1;
+static int buttonx = BUTTONX;
+static int buttony = BUTTONY;
+static HDC g_hFrameDC = (HDC)0;
+static RECT framerect = {0,0,0,0};
+
+ HWND g_hFrameWindow = (HWND)0;
+static bool g_bIsFullScreen = false;
+ BOOL g_bConfirmReboot = 1; // saved PageConfig REGSAVE
+ BOOL g_bMultiMon = 0; // OFF = load window position & clamp initial frame to screen, ON = use window position as is
+
+static BOOL helpquit = 0;
+static HFONT smallfont = (HFONT)0;
+static HWND tooltipwindow = (HWND)0;
+static BOOL g_bUsingCursor = FALSE; // TRUE = AppleWin is using (hiding) the mouse-cursor && restricting cursor to window - see SetUsingCursor()
+static int viewportx = VIEWPORTX; // Default to Normal (non-FullScreen) mode
+static int viewporty = VIEWPORTY; // Default to Normal (non-FullScreen) mode
+
+static UINT_PTR g_TimerIDEvent_100msec = 0;
+static UINT g_uCount100msec = 0;
+
+static bool g_bShowingCursor = true;
+static bool g_bLastCursorInAppleViewport = false;
+
+void DrawStatusArea (HDC passdc, BOOL drawflags);
+static void ProcessButtonClick (int button, bool bFromButtonUI=false);
+void ProcessDiskPopupMenu(HWND hwnd, POINT pt, const int iDrive);
+void RelayEvent (UINT message, WPARAM wparam, LPARAM lparam);
+void ResetMachineState ();
+void SetFullScreenMode ();
+void SetNormalMode ();
+static void SetUsingCursor(BOOL);
+static bool FileExists(std::string strFilename);
+
+bool g_bScrollLock_FullSpeed = false;
+bool g_bFreshReset = false;
+static bool g_bFullScreen32Bit = true;
+
+#if 0 // enable non-integral full-screen scaling
+#define FULLSCREEN_SCALE_TYPE float
+#else
+#define FULLSCREEN_SCALE_TYPE int
+#endif
+
+static RECT g_main_window_saved_rect;
+static int g_main_window_saved_style;
+static int g_main_window_saved_exstyle;
+static FULLSCREEN_SCALE_TYPE g_win_fullscreen_scale = 1;
+static int g_win_fullscreen_offsetx = 0;
+static int g_win_fullscreen_offsety = 0;
+
+static bool g_bFrameActive = false;
+static bool g_windowMinimized = false;
+
+static std::string driveTooltip;
+
+// __ Prototypes __________________________________________________________________________________
+void DrawCrosshairs (int x, int y);
+void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x=0, int y=0);
+static void ScreenWindowResize(const bool bCtrlKey);
+void FrameResizeWindow(int nNewScale);
+
+
+// ==========================================================================
+
+static bool g_bAltEnter_ToggleFullScreen = true; // Default for ALT+ENTER is to toggle between windowed and full-screen modes
+
+void SetAltEnterToggleFullScreen(bool mode)
+{
+ g_bAltEnter_ToggleFullScreen = mode;
+}
+
+// ==========================================================================
+
+// Display construction:
+// . Apple II video gets rendered to the framebuffer (maybe with some preliminary/final NTSC data in the border areas)
+// . The *borderless* framebuffer is stretchblt() copied to the frame DC, in VideoRefreshScreen()
+// . Draw cross-hairs (if using mouse as either a mouse or joystick) to frame DC
+// . In Windowed mode:
+// - Draw 3D border, 8x buttons, status area (disk LEDs, caps) to frame DC
+// . In Fullscreen mode:
+// - Optional: Draw status area to frame DC
+//
+
+UINT Get3DBorderWidth(void)
+{
+ return IsFullScreen() ? 0 : VIEWPORTX;
+}
+
+UINT Get3DBorderHeight(void)
+{
+ return IsFullScreen() ? 0 : VIEWPORTY;
+}
+
+// ==========================================================================
+
+static void GetAppleWindowTitle()
+{
+ switch (g_Apple2Type)
+ {
+ default:
+ case A2TYPE_APPLE2: g_pAppTitle = TITLE_APPLE_2 ; break;
+ case A2TYPE_APPLE2PLUS: g_pAppTitle = TITLE_APPLE_2_PLUS ; break;
+ case A2TYPE_APPLE2JPLUS: g_pAppTitle = TITLE_APPLE_2_JPLUS ; break;
+ case A2TYPE_APPLE2E: g_pAppTitle = TITLE_APPLE_2E ; break;
+ case A2TYPE_APPLE2EENHANCED: g_pAppTitle = TITLE_APPLE_2E_ENHANCED; break;
+ case A2TYPE_PRAVETS82: g_pAppTitle = TITLE_PRAVETS_82 ; break;
+ case A2TYPE_PRAVETS8M: g_pAppTitle = TITLE_PRAVETS_8M ; break;
+ case A2TYPE_PRAVETS8A: g_pAppTitle = TITLE_PRAVETS_8A ; break;
+ case A2TYPE_TK30002E: g_pAppTitle = TITLE_TK3000_2E ; break;
+ case A2TYPE_BASE64A: g_pAppTitle = TITLE_BASE64A ; break;
+ }
+
+#if _DEBUG
+ g_pAppTitle += " *DEBUG* ";
+#endif
+
+ if (g_nAppMode == MODE_LOGO)
+ return;
+
+ g_pAppTitle += " - ";
+
+ if( IsVideoStyle(VS_HALF_SCANLINES) )
+ g_pAppTitle += " 50% ";
+
+ g_pAppTitle += VideoGetAppWindowTitle();
+
+ if (GetCardMgr().GetDisk2CardMgr().IsAnyFirmware13Sector())
+ g_pAppTitle += " (S6-13) ";
+
+ if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
+ g_pAppTitle += TEXT(" (custom rom)");
+ else if (sg_PropertySheet.GetTheFreezesF8Rom() && IS_APPLE2)
+ g_pAppTitle += TEXT(" (The Freeze's non-autostart F8 rom)");
+
+ switch (g_nAppMode)
+ {
+ case MODE_PAUSED : g_pAppTitle += std::string(TEXT(" [")) + TITLE_PAUSED + TEXT("]"); break;
+ case MODE_STEPPING: g_pAppTitle += std::string(TEXT(" [")) + TITLE_STEPPING + TEXT("]"); break;
+ }
+}
+
+//===========================================================================
+
+static void FrameShowCursor(BOOL bShow)
+{
+ int nCount;
+
+ if (bShow)
+ {
+ do
+ {
+ nCount = ShowCursor(bShow);
+ }
+ while(nCount < 0);
+ g_bShowingCursor = true;
+ }
+ else
+ {
+ do
+ {
+ nCount = ShowCursor(bShow);
+ }
+ while(nCount >= 0);
+ g_bShowingCursor = false;
+ }
+}
+
+// Called when:
+// . Ctrl-Left mouse button
+// . PAUSE pressed (when MODE_RUNNING)
+// . AppleWin's main window is activated/deactivated
+static void RevealCursor()
+{
+ CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard();
+
+ if (!pMouseCard || !pMouseCard->IsActiveAndEnabled())
+ return;
+
+ pMouseCard->SetEnabled(false);
+
+ FrameShowCursor(TRUE);
+
+ if (sg_PropertySheet.GetMouseShowCrosshair()) // Erase crosshairs if they are being drawn
+ DrawCrosshairs(0,0);
+
+ if (sg_PropertySheet.GetMouseRestrictToWindow())
+ SetUsingCursor(FALSE);
+
+ g_bLastCursorInAppleViewport = false;
+}
+
+// Called when:
+// . WM_MOUSEMOVE event
+// . Switch from full-screen to normal (windowed) mode
+// . AppleWin's main window is activated/deactivated
+static void FullScreenRevealCursor(void)
+{
+ if (!g_bIsFullScreen)
+ return;
+
+ if (GetCardMgr().IsMouseCardInstalled())
+ return;
+
+ if (!g_bUsingCursor && !g_bShowingCursor)
+ {
+ FrameShowCursor(TRUE);
+ g_uCount100msec = 0;
+ }
+}
+
+//===========================================================================
+
+#define LOADBUTTONBITMAP(bitmapname) LoadImage(g_hInstance,bitmapname, \
+ IMAGE_BITMAP,0,0, \
+ LR_CREATEDIBSECTION | \
+ LR_LOADMAP3DCOLORS | \
+ LR_LOADTRANSPARENT);
+
+static void CreateGdiObjects(void)
+{
+ ZeroMemory(buttonbitmap, BUTTONS*sizeof(HBITMAP));
+
+ buttonbitmap[BTN_HELP] = (HBITMAP)LOADBUTTONBITMAP(TEXT("HELP_BUTTON"));
+
+ switch (g_Apple2Type)
+ {
+ case A2TYPE_PRAVETS82:
+ case A2TYPE_PRAVETS8M:
+ case A2TYPE_PRAVETS8A:
+ buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUNP_BUTTON"));
+ break;
+ case A2TYPE_TK30002E:
+ buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN3000E_BUTTON"));
+ break;
+ case A2TYPE_BASE64A:
+ buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUNBASE64A_BUTTON"));
+ break;
+ default:
+ buttonbitmap[BTN_RUN] = (HBITMAP)LOADBUTTONBITMAP(TEXT("RUN_BUTTON"));
+ break;
+ }
+
+ buttonbitmap[BTN_DRIVE1 ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DRIVE1_BUTTON"));
+ buttonbitmap[BTN_DRIVE2 ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DRIVE2_BUTTON"));
+ buttonbitmap[BTN_DRIVESWAP] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DRIVESWAP_BUTTON"));
+ buttonbitmap[BTN_FULLSCR ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("FULLSCR_BUTTON"));
+ buttonbitmap[BTN_DEBUG ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DEBUG_BUTTON"));
+ buttonbitmap[BTN_SETUP ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("SETUP_BUTTON"));
+
+ //
+
+ g_hCapsLockBitmap[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSOFF_BITMAP"));
+ g_hCapsLockBitmap[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSON_BITMAP"));
+ //Pravets8 only
+ g_hCapsBitmapP8[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSOFF_P8_BITMAP"));
+ g_hCapsBitmapP8[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_CAPSON_P8_BITMAP"));
+ g_hCapsBitmapLat[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_LATOFF_BITMAP"));
+ g_hCapsBitmapLat[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("LED_LATON_BITMAP"));
+
+ /*charsetbitmap[0] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_APPLE_BITMAP"));
+ charsetbitmap[1] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_82_BITMAP"));
+ charsetbitmap[2] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_8A_BITMAP"));
+ charsetbitmap[3] = (HBITMAP)LOADBUTTONBITMAP(TEXT("CHARSET_8M_BITMAP"));
+ */
+ //===========================
+ g_hDiskWindowedLED[ DISK_STATUS_OFF ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKOFF_BITMAP"));
+ g_hDiskWindowedLED[ DISK_STATUS_READ ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKREAD_BITMAP"));
+ g_hDiskWindowedLED[ DISK_STATUS_WRITE] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKWRITE_BITMAP"));
+ g_hDiskWindowedLED[ DISK_STATUS_PROT ] = (HBITMAP)LOADBUTTONBITMAP(TEXT("DISKPROT_BITMAP"));
+
+ btnfacebrush = CreateSolidBrush(GetSysColor(COLOR_BTNFACE));
+ btnfacepen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNFACE));
+ btnhighlightpen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNHIGHLIGHT));
+ btnshadowpen = CreatePen(PS_SOLID,1,GetSysColor(COLOR_BTNSHADOW));
+ smallfont = CreateFont(11,6,0,0,FW_NORMAL,0,0,0,ANSI_CHARSET,
+ OUT_DEFAULT_PRECIS,CLIP_DEFAULT_PRECIS,
+ DEFAULT_QUALITY,VARIABLE_PITCH | FF_SWISS,
+ TEXT("Small Fonts"));
+}
+
+//===========================================================================
+static void DeleteGdiObjects(void)
+{
+ for (int loop = 0; loop < BUTTONS; loop++)
+ _ASSERT(DeleteObject(buttonbitmap[loop]));
+
+ for (int loop = 0; loop < 2; loop++)
+ {
+ _ASSERT(DeleteObject(g_hCapsLockBitmap[loop]));
+ _ASSERT(DeleteObject(g_hCapsBitmapP8[loop]));
+ _ASSERT(DeleteObject(g_hCapsBitmapLat[loop]));
+ }
+
+ for (int loop = 0; loop < NUM_DISK_STATUS; loop++)
+ {
+ _ASSERT(DeleteObject(g_hDiskWindowedLED[loop]));
+ }
+
+ _ASSERT(DeleteObject(btnfacebrush));
+ _ASSERT(DeleteObject(btnfacepen));
+ _ASSERT(DeleteObject(btnhighlightpen));
+ _ASSERT(DeleteObject(btnshadowpen));
+ _ASSERT(DeleteObject(smallfont));
+}
+
+// Draws an 3D box around the main apple screen
+//===========================================================================
+static void Draw3dRect (HDC dc, int x1, int y1, int x2, int y2, BOOL out)
+{
+ SelectObject(dc,GetStockObject(NULL_BRUSH));
+ SelectObject(dc,out ? btnshadowpen : btnhighlightpen);
+ POINT pt[3];
+ pt[0].x = x1; pt[0].y = y2-1;
+ pt[1].x = x2-1; pt[1].y = y2-1;
+ pt[2].x = x2-1; pt[2].y = y1;
+ Polyline(dc,(LPPOINT)&pt,3);
+ SelectObject(dc,(out == 1) ? btnhighlightpen : btnshadowpen);
+ pt[1].x = x1; pt[1].y = y1;
+ pt[2].x = x2; pt[2].y = y1;
+ Polyline(dc,(LPPOINT)&pt,3);
+}
+
+//===========================================================================
+static void DrawBitmapRect (HDC dc, int x, int y, LPRECT rect, HBITMAP bitmap) {
+ HDC memdc = CreateCompatibleDC(dc);
+ SelectObject(memdc,bitmap);
+ BitBlt(dc,x,y,
+ rect->right + 1 - rect->left,
+ rect->bottom + 1 - rect->top,
+ memdc,
+ rect->left,
+ rect->top,
+ SRCCOPY);
+ DeleteDC(memdc);
+}
+
+//===========================================================================
+static void DrawButton (HDC passdc, int number) {
+ FrameReleaseDC();
+ HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
+ int x = buttonx;
+ int y = buttony+number*BUTTONCY;
+ if (number == buttondown) {
+ int loop = 0;
+ while (loop++ < 3)
+ Draw3dRect(dc,x+loop,y+loop,x+BUTTONCX,y+BUTTONCY,0);
+ RECT rect = {0,0,39,39};
+ DrawBitmapRect(dc,x+4,y+4,&rect,buttonbitmap[number]);
+ }
+ else {
+ Draw3dRect(dc,x+1,y+1,x+BUTTONCX,y+BUTTONCY,1);
+ Draw3dRect(dc,x+2,y+2,x+BUTTONCX-1,y+BUTTONCY-1,1);
+ RECT rect = {1,1,40,40};
+ DrawBitmapRect(dc,x+3,y+3,&rect,buttonbitmap[number]);
+ }
+ if ((number == BTN_DRIVE1) || (number == BTN_DRIVE2)) {
+ int offset = (number == buttondown) << 1;
+ RECT rect = {x+offset+3,
+ y+offset+31,
+ x+offset+42,
+ y+offset+42};
+ SelectObject(dc,smallfont);
+ SetTextColor(dc,RGB(0,0,0));
+ SetTextAlign(dc,TA_CENTER | TA_TOP);
+ SetBkMode(dc,TRANSPARENT);
+
+ LPCTSTR pszBaseName = (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ ? dynamic_cast(GetCardMgr().GetRef(SLOT6)).GetBaseName(number-BTN_DRIVE1).c_str()
+ : "";
+
+ ExtTextOut(dc,x+offset+22,rect.top,ETO_CLIPPED,&rect,
+ pszBaseName,
+ MIN(8,_tcslen(pszBaseName)),
+ NULL);
+ }
+ if (!passdc)
+ ReleaseDC(g_hFrameWindow,dc);
+}
+
+//===========================================================================
+
+// NB. x=y=0 means erase only
+static void DrawCrosshairs (int x, int y) {
+ static int lastx = 0;
+ static int lasty = 0;
+ FrameReleaseDC();
+ HDC dc = GetDC(g_hFrameWindow);
+#define LINE(x1,y1,x2,y2) MoveToEx(dc,x1,y1,NULL); LineTo(dc,x2,y2);
+
+ // ERASE THE OLD CROSSHAIRS
+ if (lastx && lasty)
+ if (g_bIsFullScreen)
+ {
+ int loop = 4;
+ while (loop--) {
+ RECT rect = {0,0,5,5};
+ switch (loop) {
+ case 0: OffsetRect(&rect, GetFullScreenOffsetX()+lastx-2, GetFullScreenOffsetY()+viewporty-5); break;
+ case 1: OffsetRect(&rect, GetFullScreenOffsetX()+lastx-2, GetFullScreenOffsetY()+viewporty+g_nViewportCY); break;
+ case 2: OffsetRect(&rect, GetFullScreenOffsetX()+viewportx-5, GetFullScreenOffsetY()+lasty-2); break;
+ case 3: OffsetRect(&rect, GetFullScreenOffsetX()+viewportx+g_nViewportCX, GetFullScreenOffsetY()+lasty-2); break;
+ }
+ FillRect(dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ }
+ }
+ else
+ {
+ int loop = 5;
+ while (loop--) {
+ switch (loop) {
+ case 0: SelectObject(dc,GetStockObject(BLACK_PEN)); break;
+ case 1: // fall through
+ case 2: SelectObject(dc,btnshadowpen); break;
+ case 3: // fall through
+ case 4: SelectObject(dc,btnfacepen); break;
+ }
+ LINE(lastx-2,VIEWPORTY-loop-1,
+ lastx+3,VIEWPORTY-loop-1);
+ LINE(VIEWPORTX-loop-1,lasty-2,
+ VIEWPORTX-loop-1,lasty+3);
+ if ((loop == 1) || (loop == 2))
+ SelectObject(dc,btnhighlightpen);
+ LINE(lastx-2,VIEWPORTY+g_nViewportCY+loop,
+ lastx+3,VIEWPORTY+g_nViewportCY+loop);
+ LINE(VIEWPORTX+g_nViewportCX+loop,lasty-2,
+ VIEWPORTX+g_nViewportCX+loop,lasty+3);
+ }
+ }
+
+ // DRAW THE NEW CROSSHAIRS
+ if (x && y) {
+ if (g_bIsFullScreen)
+ {
+ int loop = 4;
+ while (loop--) {
+ if ((loop == 1) || (loop == 2))
+ SelectObject(dc,GetStockObject(WHITE_PEN));
+ else
+ SelectObject(dc,GetStockObject(BLACK_PEN));
+ LINE(GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty-5,
+ GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty);
+ LINE(GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty+g_nViewportCY+4,
+ GetFullScreenOffsetX()+x+loop-2, GetFullScreenOffsetY()+viewporty+g_nViewportCY-1);
+ LINE(GetFullScreenOffsetX()+viewportx-5, GetFullScreenOffsetY()+y+loop-2,
+ GetFullScreenOffsetX()+viewportx, GetFullScreenOffsetY()+y+loop-2);
+ LINE(GetFullScreenOffsetX()+viewportx+g_nViewportCX+4, GetFullScreenOffsetY()+y+loop-2,
+ GetFullScreenOffsetX()+viewportx+g_nViewportCX-1, GetFullScreenOffsetY()+y+loop-2);
+ }
+ }
+ else
+ {
+ int loop = 4;
+ while (loop--) {
+ if ((loop == 1) || (loop == 2))
+ SelectObject(dc,GetStockObject(WHITE_PEN));
+ else
+ SelectObject(dc,GetStockObject(BLACK_PEN));
+ LINE(x+loop-2,viewporty-5,
+ x+loop-2,viewporty);
+ LINE(x+loop-2,viewporty+g_nViewportCY+4,
+ x+loop-2,viewporty+g_nViewportCY-1);
+ LINE(viewportx-5, y+loop-2,
+ viewportx, y+loop-2);
+ LINE(viewportx+g_nViewportCX+4,y+loop-2,
+ viewportx+g_nViewportCX-1,y+loop-2);
+ }
+ }
+ }
+#undef LINE
+ lastx = x;
+ lasty = y;
+ ReleaseDC(g_hFrameWindow,dc);
+}
+
+//===========================================================================
+static void DrawFrameWindow (bool bPaintingWindow = false);
+static void DrawFrameWindow (bool bPaintingWindow/*=false*/)
+{
+ FrameReleaseDC();
+ PAINTSTRUCT ps;
+ HDC dc = bPaintingWindow
+ ? BeginPaint(g_hFrameWindow,&ps)
+ : GetDC(g_hFrameWindow);
+
+ if (!g_bIsFullScreen)
+ {
+ // DRAW THE 3D BORDER AROUND THE EMULATED SCREEN
+ Draw3dRect(dc,
+ VIEWPORTX-2,VIEWPORTY-2,
+ VIEWPORTX+g_nViewportCX+2,VIEWPORTY+g_nViewportCY+2,
+ 0);
+ Draw3dRect(dc,
+ VIEWPORTX-3,VIEWPORTY-3,
+ VIEWPORTX+g_nViewportCX+3,VIEWPORTY+g_nViewportCY+3,
+ 0);
+ SelectObject(dc,btnfacepen);
+ Rectangle(dc,
+ VIEWPORTX-4,VIEWPORTY-4,
+ VIEWPORTX+g_nViewportCX+4,VIEWPORTY+g_nViewportCY+4);
+ Rectangle(dc,
+ VIEWPORTX-5,VIEWPORTY-5,
+ VIEWPORTX+g_nViewportCX+5,VIEWPORTY+g_nViewportCY+5);
+
+ // DRAW THE TOOLBAR BUTTONS
+ int iButton = BUTTONS;
+ while (iButton--)
+ {
+ DrawButton(dc,iButton);
+ }
+
+ if (g_nViewportScale == 2)
+ {
+ int x = buttonx + 1;
+ int y = buttony + BUTTONS*BUTTONCY + 36; // 36 = height of StatusArea
+ RECT rect = {x, y, x+45, y+BUTTONS*BUTTONCY+22};
+ int res = FillRect(dc, &rect, btnfacebrush);
+ }
+ }
+
+ // DRAW THE STATUS AREA
+ DrawStatusArea(dc,DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS);
+
+ // DRAW THE CONTENTS OF THE EMULATED SCREEN
+ if (g_nAppMode == MODE_LOGO)
+ VideoDisplayLogo();
+ else if (g_nAppMode == MODE_DEBUG)
+ DebugDisplay();
+ else
+ VideoRedrawScreen();
+
+ if (bPaintingWindow)
+ EndPaint(g_hFrameWindow,&ps);
+ else
+ ReleaseDC(g_hFrameWindow,dc);
+
+}
+
+//===========================================================================
+static bool g_bFullScreen_ShowSubunitStatus = true;
+
+bool IsFullScreen(void)
+{
+ return g_bIsFullScreen;
+}
+
+bool GetFullScreenShowSubunitStatus(void)
+{
+ return g_bFullScreen_ShowSubunitStatus;
+}
+
+void SetFullScreenShowSubunitStatus(bool bShow)
+{
+ g_bFullScreen_ShowSubunitStatus = bShow;
+}
+
+//===========================================================================
+void FrameDrawDiskLEDS( HDC passdc )
+{
+ g_eStatusDrive1 = DISK_STATUS_OFF;
+ g_eStatusDrive2 = DISK_STATUS_OFF;
+
+ // Slot6 drive takes priority unless it's off:
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ dynamic_cast(GetCardMgr().GetRef(SLOT6)).GetLightStatus(&g_eStatusDrive1, &g_eStatusDrive2);
+
+ // Slot5:
+ {
+ Disk_Status_e eDrive1StatusSlot5 = DISK_STATUS_OFF;
+ Disk_Status_e eDrive2StatusSlot5 = DISK_STATUS_OFF;
+ if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2)
+ dynamic_cast(GetCardMgr().GetRef(SLOT5)).GetLightStatus(&eDrive1StatusSlot5, &eDrive2StatusSlot5);
+
+ if (g_eStatusDrive1 == DISK_STATUS_OFF) g_eStatusDrive1 = eDrive1StatusSlot5;
+ if (g_eStatusDrive2 == DISK_STATUS_OFF) g_eStatusDrive2 = eDrive2StatusSlot5;
+ }
+
+ // Draw Track/Sector
+ FrameReleaseDC();
+ HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
+
+ int x = buttonx;
+ int y = buttony+BUTTONS*BUTTONCY+1;
+
+ if (g_bIsFullScreen)
+ {
+ if (!g_bFullScreen_ShowSubunitStatus)
+ return;
+
+ SelectObject(dc,smallfont);
+ SetBkMode(dc,OPAQUE);
+ SetBkColor(dc,RGB(0,0,0));
+ SetTextAlign(dc,TA_LEFT | TA_TOP);
+
+ SetTextColor(dc, g_aDiskFullScreenColorsLED[g_eStatusDrive1] );
+ TextOut(dc,x+ 3,y+2,TEXT("1"),1);
+
+ SetTextColor(dc, g_aDiskFullScreenColorsLED[g_eStatusDrive2] );
+ TextOut(dc,x+13,y+2,TEXT("2"),1);
+ }
+ else
+ {
+ RECT rDiskLed = {0,0,8,8};
+ DrawBitmapRect(dc,x+12,y+6,&rDiskLed,g_hDiskWindowedLED[g_eStatusDrive1]);
+ DrawBitmapRect(dc,x+31,y+6,&rDiskLed,g_hDiskWindowedLED[g_eStatusDrive2]);
+ }
+}
+
+// Feature Request #201 Show track status
+// https://github.com/AppleWin/AppleWin/issues/201
+//===========================================================================
+void FrameDrawDiskStatus( HDC passdc )
+{
+ if (mem == NULL)
+ return;
+
+ if (g_nAppMode == MODE_LOGO)
+ return;
+
+ if (g_windowMinimized) // Prevent DC leaks when app window is minimised (GH#820)
+ return;
+
+ // We use the actual drive since probing from memory doesn't tell us anything we don't already know.
+ // DOS3.3 ProDOS
+ // Drive $B7EA $BE3D
+ // Track $B7EC LC1 $D356
+ // Sector $B7ED LC1 $D357
+ // RWTS LC1 $D300
+
+ if (GetCardMgr().QuerySlot(SLOT6) != CT_Disk2)
+ return;
+
+ Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
+ int nActiveFloppy = disk2Card.GetCurrentDrive();
+ int nDisk1Track = disk2Card.GetTrack(DRIVE_1);
+ int nDisk2Track = disk2Card.GetTrack(DRIVE_2);
+
+ // Probe known OS's for Track/Sector
+ int isProDOS = mem[ 0xBF00 ] == 0x4C;
+ bool isValid = true;
+
+ // Try DOS3.3 Sector
+ if ( !isProDOS )
+ {
+ int nDOS33track = mem[ 0xB7EC ];
+ int nDOS33sector = mem[ 0xB7ED ];
+
+ if ((nDOS33track >= 0 && nDOS33track < 40)
+ && (nDOS33sector >= 0 && nDOS33sector < 16))
+ {
+#if _DEBUG && 0
+ if (nDOS33track != nDisk1Track)
+ {
+ char text[128];
+ sprintf( text, "\n\n\nWARNING: DOS33Track: %d (%02X) != nDisk1Track: %d (%02X)\n\n\n", nDOS33track, nDOS33track, nDisk1Track, nDisk1Track );
+ OutputDebugString( text );
+ }
+#endif // _DEBUG
+
+ /**/ if (nActiveFloppy == 0) g_nSectorDrive1 = nDOS33sector;
+ else if (nActiveFloppy == 1) g_nSectorDrive2 = nDOS33sector;
+ }
+ else
+ isValid = false;
+ }
+ else // isProDOS
+ {
+ // we can't just read from mem[ 0xD357 ] since it might be bank-switched from ROM
+ // and we need the Language Card RAM
+ // memrom[ 0xD350 ] = " ERROR\x07\x00" Applesoft error message
+ // T S
+ int nProDOStrack = *MemGetMainPtr( 0xC356 ); // LC1 $D356
+ int nProDOSsector = *MemGetMainPtr( 0xC357 ); // LC1 $D357
+
+ if ((nProDOStrack >= 0 && nProDOStrack < 40)
+ && (nProDOSsector >= 0 && nProDOSsector < 16))
+ {
+ /**/ if (nActiveFloppy == 0) g_nSectorDrive1 = nProDOSsector;
+ else if (nActiveFloppy == 1) g_nSectorDrive2 = nProDOSsector;
+ }
+ else
+ isValid = false;
+ }
+
+ g_nTrackDrive1 = nDisk1Track;
+ g_nTrackDrive2 = nDisk2Track;
+
+ if( !isValid )
+ {
+ if (nActiveFloppy == 0) g_nSectorDrive1 = -1;
+ else g_nSectorDrive2 = -1;
+ }
+
+ sprintf_s( g_sTrackDrive1 , sizeof(g_sTrackDrive1 ), "%2d", g_nTrackDrive1 );
+ if (g_nSectorDrive1 < 0) sprintf_s( g_sSectorDrive1, sizeof(g_sSectorDrive1), "??" );
+ else sprintf_s( g_sSectorDrive1, sizeof(g_sSectorDrive1), "%2d", g_nSectorDrive1 );
+
+ sprintf_s( g_sTrackDrive2 , sizeof(g_sTrackDrive2), "%2d", g_nTrackDrive2 );
+ if (g_nSectorDrive2 < 0) sprintf_s( g_sSectorDrive2, sizeof(g_sSectorDrive2), "??" );
+ else sprintf_s( g_sSectorDrive2, sizeof(g_sSectorDrive2), "%2d", g_nSectorDrive2 );
+
+ // Draw Track/Sector
+ FrameReleaseDC();
+ HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
+
+ int x = buttonx;
+ int y = buttony+BUTTONS*BUTTONCY+4;
+
+ SelectObject(dc,smallfont);
+ SetBkMode(dc,OPAQUE);
+ SetBkColor(dc,RGB(0,0,0));
+ SetTextAlign(dc,TA_LEFT | TA_TOP);
+
+ char text[ 16 ];
+
+ if (g_bIsFullScreen)
+ {
+ // GH#57 - drive lights in full screen mode
+
+ if (!g_bFullScreen_ShowSubunitStatus)
+ return;
+
+ SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive1 ] );
+ TextOut(dc,x+ 3,y+2,TEXT("1"),1);
+
+ SetTextColor(dc, g_aDiskFullScreenColorsLED[ g_eStatusDrive2 ] );
+ TextOut(dc,x+13,y+2,TEXT("2"),1);
+
+ int dx = 0;
+ if( nActiveFloppy == 0 )
+ sprintf( text, "%s/%s ", g_sTrackDrive1, g_sSectorDrive1 );
+ else
+ sprintf( text, "%s/%s ", g_sTrackDrive2, g_sSectorDrive2 );
+
+ SetTextColor(dc, g_aDiskFullScreenColorsLED[ DISK_STATUS_READ ] );
+ TextOut(dc,x+dx,y-12,text, strlen(text) ); // original: y+2; y-12 puts status in the Configuration Button Icon
+ }
+ else
+ {
+ // NB. Only draw Track/Sector if 2x windowed
+ if (g_nViewportScale == 1)
+ return;
+
+ // Erase background
+ SelectObject(dc,GetStockObject(NULL_PEN));
+ SelectObject(dc,btnfacebrush);
+ Rectangle(dc,x+4,y+32,x+BUTTONCX+1,y+56); // y+35 -> 44 -> 56
+
+ SetTextColor(dc,RGB(0,0,0));
+ SetBkMode(dc,TRANSPARENT);
+
+ sprintf( text, "T%s", g_sTrackDrive1 );
+ TextOut(dc,x+6, y+32, text, strlen(text) );
+ sprintf( text, "S%s", g_sSectorDrive1 );
+ TextOut(dc,x+6, y+42, text, strlen(text) );
+
+ sprintf( text, "T%s", g_sTrackDrive2 );
+ TextOut(dc,x+26,y+32, text, strlen(text) );
+ sprintf( text, "S%s", g_sSectorDrive2 );
+ TextOut(dc,x+26,y+42, text, strlen(text) );
+ }
+}
+
+//===========================================================================
+static void DrawStatusArea (HDC passdc, int drawflags)
+{
+ if (g_hFrameWindow == NULL)
+ {
+ // TC: Fix drawing of drive buttons before frame created:
+ // . Main init loop: LoadConfiguration() called before FrameCreateWindow(), eg:
+ // LoadConfiguration() -> Disk_LoadLastDiskImage() -> DiskInsert() -> FrameRefreshStatus()
+ return;
+ }
+
+ FrameReleaseDC();
+ HDC dc = (passdc ? passdc : GetDC(g_hFrameWindow));
+ int x = buttonx;
+ int y = buttony+BUTTONS*BUTTONCY+1;
+ const bool bCaps = KeybGetCapsStatus();
+ //const bool bP8Caps = KeybGetP8CapsStatus(); // TODO: FIXME: Not used ?! Should show the LED status ...
+
+#if HD_LED
+ // 1.19.0.0 Hard Disk Status/Indicator Light
+ Disk_Status_e eHardDriveStatus = DISK_STATUS_OFF;
+ HD_GetLightStatus(&eHardDriveStatus);
+#endif
+
+ if (g_bIsFullScreen)
+ {
+ if (!g_bFullScreen_ShowSubunitStatus)
+ {
+ // Erase Config button icon too, as trk/sec is written here - see FrameDrawDiskStatus()
+ RECT rect = {x-2,y-BUTTONCY,x+BUTTONCX+2,y+BUTTONCY}; // Extend rect's width by +/-2 as the TITLE_PAUSED text is wider than an icon button
+ FillRect(dc, &rect, (HBRUSH)GetStockObject(BLACK_BRUSH));
+ }
+ else
+ {
+ SelectObject(dc,smallfont);
+
+ if (drawflags & DRAW_DISK_STATUS)
+ FrameDrawDiskStatus( dc );
+
+#if HD_LED
+ SetTextAlign(dc, TA_RIGHT | TA_TOP);
+ SetTextColor(dc, g_aDiskFullScreenColorsLED[ eHardDriveStatus ] );
+ TextOut(dc,x+23,y+2,TEXT("H"),1);
+#endif
+
+ if (!IS_APPLE2)
+ {
+ SetTextAlign(dc,TA_RIGHT | TA_TOP);
+ SetTextColor(dc,(bCaps
+ ? RGB(128,128,128)
+ : RGB( 0, 0, 0) ));
+
+ TextOut(dc,x+BUTTONCX,y+2,TEXT("A"),1); // NB. Caps Lock indicator is already flush right!
+ }
+
+ //
+
+ static const char* pCurrentAppModeText = NULL;
+
+ const char* const pNewAppModeText = (g_nAppMode == MODE_PAUSED)
+ ? TITLE_PAUSED
+ : (g_nAppMode == MODE_STEPPING)
+ ? TITLE_STEPPING
+ : NULL;
+
+ SetTextAlign(dc, TA_CENTER | TA_TOP);
+
+ if (pCurrentAppModeText && pNewAppModeText != pCurrentAppModeText)
+ {
+ SetTextColor(dc, RGB(0,0,0));
+ TextOut(dc, x+BUTTONCX/2, y+13, pCurrentAppModeText, strlen(pCurrentAppModeText));
+ pCurrentAppModeText = NULL;
+ }
+
+ if (pNewAppModeText)
+ {
+ SetTextColor(dc, RGB(255,255,255));
+ TextOut(dc, x+BUTTONCX/2, y+13, pNewAppModeText, strlen(pNewAppModeText));
+ pCurrentAppModeText = pNewAppModeText;
+ }
+ }
+ }
+ else // !g_bIsFullScreen
+ {
+ if (drawflags & DRAW_BACKGROUND)
+ {
+ SelectObject(dc,GetStockObject(NULL_PEN));
+ SelectObject(dc,btnfacebrush);
+ Rectangle(dc,x,y,x+BUTTONCX+2,y+34);
+ Draw3dRect(dc,x+1,y+3,x+BUTTONCX,y+30,0);
+
+ SelectObject(dc,smallfont);
+ SetTextAlign(dc,TA_CENTER | TA_TOP);
+ SetTextColor(dc,RGB(0,0,0));
+ SetBkMode(dc,TRANSPARENT);
+ TextOut(dc,x+ 7,y+5,TEXT("1"),1);
+ TextOut(dc,x+27,y+5,TEXT("2"),1);
+
+ // 1.19.0.0 Hard Disk Status/Indicator Light
+ TextOut(dc,x+ 7,y+17,TEXT("H"),1);
+ }
+
+ if (drawflags & DRAW_LEDS)
+ {
+ FrameDrawDiskLEDS( dc );
+
+ if (drawflags & DRAW_DISK_STATUS)
+ FrameDrawDiskStatus( dc );
+
+ if (!IS_APPLE2)
+ {
+ RECT rCapsLed = {0,0,10,12}; // HACK: HARD-CODED bitmaps size
+ switch (g_Apple2Type)
+ {
+ case A2TYPE_APPLE2 :
+ case A2TYPE_APPLE2PLUS :
+ case A2TYPE_APPLE2E :
+ case A2TYPE_APPLE2EENHANCED:
+ default : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsLockBitmap[bCaps != 0]); break;
+ case A2TYPE_PRAVETS82 :
+ case A2TYPE_PRAVETS8M : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsBitmapP8 [bCaps != 0]); break; // TODO: FIXME: Shouldn't one of these use g_hCapsBitmapLat ??
+ case A2TYPE_PRAVETS8A : DrawBitmapRect(dc,x+31,y+17,&rCapsLed,g_hCapsBitmapP8 [bCaps != 0]); break;
+ }
+
+#if HD_LED
+ // 1.19.0.0 Hard Disk Status/Indicator Light
+ RECT rDiskLed = {0,0,8,8};
+ DrawBitmapRect(dc,x+12,y+18,&rDiskLed,g_hDiskWindowedLED[eHardDriveStatus]);
+#endif
+ }
+ }
+
+ if (drawflags & DRAW_TITLE)
+ {
+ GetAppleWindowTitle(); // SetWindowText() // WindowTitle
+ SendMessage(g_hFrameWindow,WM_SETTEXT,0,(LPARAM)g_pAppTitle.c_str());
+ }
+
+ if (drawflags & DRAW_BUTTON_DRIVES)
+ {
+ DrawButton(dc, BTN_DRIVE1);
+ DrawButton(dc, BTN_DRIVE2);
+ }
+ }
+
+ if (!passdc)
+ ReleaseDC(g_hFrameWindow,dc);
+}
+
+//===========================================================================
+static void EraseButton (int number) {
+ RECT rect;
+ rect.left = buttonx;
+ rect.right = rect.left+BUTTONCX;
+ rect.top = buttony+number*BUTTONCY;
+ rect.bottom = rect.top+BUTTONCY;
+
+ InvalidateRect(g_hFrameWindow,&rect,1);
+}
+
+//===========================================================================
+
+LRESULT CALLBACK FrameWndProc (
+ HWND window,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam)
+{
+ switch (message)
+ {
+ case WM_ACTIVATE: // Sent when window is activated/deactivated. wParam indicates WA_ACTIVE, WA_INACTIVE, etc
+ // Eg. Deactivate when Config dialog is active, AppleWin app loses focus, etc
+ JoyReset();
+ SetUsingCursor(FALSE);
+ RevealCursor();
+ FullScreenRevealCursor();
+ g_bFrameActive = (wparam != WA_INACTIVE);
+ break;
+
+ case WM_ACTIVATEAPP: // Sent when different app's window is activated/deactivated.
+ // Eg. Deactivate when AppleWin app loses focus
+ g_bAppActive = (wparam ? TRUE : FALSE);
+ break;
+
+ case WM_SIZE:
+ switch(wparam)
+ {
+ case SIZE_RESTORED:
+ case SIZE_MAXIMIZED:
+ g_windowMinimized = false;
+ break;
+ case SIZE_MINIMIZED:
+ g_windowMinimized = true;
+ break;
+ default: // SIZE_MAXSHOW, SIZE_MAXHIDE
+ break;
+ }
+ break;
+
+ case WM_CLOSE:
+ LogFileOutput("WM_CLOSE\n");
+ if (g_bIsFullScreen && g_bRestart)
+ g_bRestartFullScreen = true;
+ if (g_bIsFullScreen)
+ SetNormalMode();
+ if (!IsIconic(window))
+ GetWindowRect(window,&framerect);
+ RegSaveValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_X_POS), 1, framerect.left);
+ RegSaveValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_Y_POS), 1, framerect.top);
+ FrameReleaseDC();
+ SetUsingCursor(FALSE);
+ if (helpquit) {
+ helpquit = 0;
+ HtmlHelp(NULL,NULL,HH_CLOSE_ALL,0);
+ }
+ if (g_TimerIDEvent_100msec)
+ {
+ BOOL bRes = KillTimer(g_hFrameWindow, g_TimerIDEvent_100msec);
+ LogFileOutput("KillTimer(g_TimerIDEvent_100msec), res=%d\n", bRes ? 1 : 0);
+ g_TimerIDEvent_100msec = 0;
+ }
+ LogFileOutput("WM_CLOSE (done)\n");
+ // Exit via DefWindowProc(), which does the default action for WM_CLOSE, which is to call DestroyWindow(), posting WM_DESTROY
+ break;
+
+ case WM_DESTROY:
+ LogFileOutput("WM_DESTROY\n");
+ DragAcceptFiles(window,0);
+ if (!g_bRestart) // GH#564: Only save-state on shutdown (not on a restart)
+ Snapshot_Shutdown();
+ DebugDestroy();
+ if (!g_bRestart) {
+ GetCardMgr().GetDisk2CardMgr().Destroy();
+ ImageDestroy();
+ HD_Destroy();
+ }
+ PrintDestroy();
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommDestroy();
+ CpuDestroy();
+ MemDestroy();
+ SpkrDestroy();
+ WinVideoDestroy();
+ MB_Destroy();
+ DeleteGdiObjects();
+ DIMouse::DirectInputUninit(window); // NB. do before window is destroyed
+ PostQuitMessage(0); // Post WM_QUIT message to the thread's message queue
+ LogFileOutput("WM_DESTROY (done)\n");
+ break;
+
+ case WM_CREATE:
+ LogFileOutput("WM_CREATE\n");
+ g_hFrameWindow = window; // NB. g_hFrameWindow by CreateWindow()
+
+ CreateGdiObjects();
+ LogFileOutput("WM_CREATE: CreateGdiObjects()\n");
+
+ DSInit();
+ LogFileOutput("WM_CREATE: DSInit()\n");
+
+ DIMouse::DirectInputInit(window);
+ LogFileOutput("WM_CREATE: DIMouse::DirectInputInit()\n");
+
+ MB_Initialize();
+ LogFileOutput("WM_CREATE: MB_Initialize()\n");
+
+ SpkrInitialize();
+ LogFileOutput("WM_CREATE: SpkrInitialize()\n");
+
+ DragAcceptFiles(window,1);
+ LogFileOutput("WM_CREATE: DragAcceptFiles()\n");
+
+ LogFileOutput("WM_CREATE (done)\n");
+ break;
+
+ case WM_DDE_INITIATE: {
+ LogFileOutput("WM_DDE_INITIATE\n");
+ ATOM application = GlobalAddAtom(TEXT("applewin"));
+ ATOM topic = GlobalAddAtom(TEXT("system"));
+ if(LOWORD(lparam) == application && HIWORD(lparam) == topic)
+ SendMessage((HWND)wparam,WM_DDE_ACK,(WPARAM)window,MAKELPARAM(application,topic));
+ GlobalDeleteAtom(application);
+ GlobalDeleteAtom(topic);
+ LogFileOutput("WM_DDE_INITIATE (done)\n");
+ break;
+ }
+
+ case WM_DDE_EXECUTE:
+ {
+ LogFileOutput("WM_DDE_EXECUTE\n");
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ {
+ Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
+ LPTSTR filename = (LPTSTR)GlobalLock((HGLOBAL)lparam);
+ ImageError_e Error = disk2Card.InsertDisk(DRIVE_1, filename, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
+ if (Error == eIMAGE_ERROR_NONE)
+ {
+ if (!g_bIsFullScreen)
+ DrawButton((HDC)0,BTN_DRIVE1);
+
+ PostMessage(window, WM_USER_BOOT, 0, 0);
+ }
+ else
+ {
+ disk2Card.NotifyInvalidImage(DRIVE_1, filename, Error);
+ }
+ }
+ GlobalUnlock((HGLOBAL)lparam);
+ LogFileOutput("WM_DDE_EXECUTE (done)\n");
+ break;
+ }
+
+ case WM_DISPLAYCHANGE:
+ VideoReinitialize();
+ break;
+
+ case WM_DROPFILES:
+ {
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ {
+ Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
+ TCHAR filename[MAX_PATH];
+ DragQueryFile((HDROP)wparam,0,filename,sizeof(filename));
+ POINT point;
+ DragQueryPoint((HDROP)wparam,&point);
+ RECT rect;
+ rect.left = buttonx;
+ rect.right = rect.left+BUTTONCX+1;
+ rect.top = buttony+BTN_DRIVE2*BUTTONCY+1;
+ rect.bottom = rect.top+BUTTONCY;
+ const int iDrive = PtInRect(&rect,point) ? DRIVE_2 : DRIVE_1;
+ ImageError_e Error = disk2Card.InsertDisk(iDrive, filename, IMAGE_USE_FILES_WRITE_PROTECT_STATUS, IMAGE_DONT_CREATE);
+ if (Error == eIMAGE_ERROR_NONE)
+ {
+ if (!g_bIsFullScreen)
+ DrawButton((HDC)0,PtInRect(&rect,point) ? BTN_DRIVE2 : BTN_DRIVE1);
+ rect.top = buttony+BTN_DRIVE1*BUTTONCY+1;
+ if (!PtInRect(&rect,point))
+ {
+ SetForegroundWindow(window);
+ ProcessButtonClick(BTN_RUN);
+ }
+ }
+ else
+ {
+ disk2Card.NotifyInvalidImage(iDrive, filename, Error);
+ }
+ }
+ DragFinish((HDROP)wparam);
+ break;
+ }
+
+ // @see: http://answers.google.com/answers/threadview?id=133059
+ // Win32 doesn't pass the PrintScreen key via WM_CHAR
+ // else if (wparam == VK_SNAPSHOT)
+ // Solution: 2 choices:
+ // 1) register hotkey, or
+ // 2) Use low level Keyboard hooks
+ // We use the 1st one since it is compatible with Win95
+ case WM_HOTKEY:
+ // wparam = user id
+ // lparam = modifiers: shift, ctrl, alt, win
+ if (wparam == VK_SNAPSHOT_560)
+ {
+#if _DEBUG
+// MessageBox( g_hFrameWindow, "Double 580x384 size!", "PrintScreen", MB_OK );
+#endif
+ Video_TakeScreenShot( SCREENSHOT_560x384 );
+ }
+ else
+ if (wparam == VK_SNAPSHOT_280) // ( lparam & MOD_SHIFT )
+ {
+#if _DEBUG
+// MessageBox( g_hFrameWindow, "Normal 280x192 size!", "PrintScreen", MB_OK );
+#endif
+ Video_TakeScreenShot( SCREENSHOT_280x192 );
+ }
+ else
+ if (wparam == VK_SNAPSHOT_TEXT) // ( lparam & MOD_CONTROL )
+ {
+ char *pText;
+ size_t nSize = 0;
+
+ // if viewing the debugger, get the last virtual debugger screen
+ if ((g_nAppMode == MODE_DEBUG) && !DebugGetVideoMode(NULL))
+ nSize = Util_GetDebuggerText( pText );
+ else
+ nSize = Util_GetTextScreen( pText );
+ Util_CopyTextToClipboard( nSize, pText );
+ }
+ break;
+
+ case WM_KEYDOWN:
+ KeybUpdateCtrlShiftStatus();
+
+ // Processing is done in WM_KEYUP for: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
+ if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == -1))
+ {
+ SetUsingCursor(FALSE);
+ buttondown = wparam-VK_F1;
+ if (g_bIsFullScreen && (buttonover != -1)) {
+ if (buttonover != buttondown)
+ EraseButton(buttonover);
+ buttonover = -1;
+ }
+ DrawButton((HDC)0,buttondown);
+ }
+ else if (wparam == VK_F9)
+ {
+ // F9 Next Video Mode
+ // SHIFT+F9 Prev Video Mode
+ // CTRL+SHIFT+F9 Toggle 50% Scan Lines
+ // ALT+F9 Can't use Alt-F9 as Alt is Open-Apple = Joystick Button #1
+
+ if ( !KeybGetCtrlStatus() && !KeybGetShiftStatus() ) // F9
+ {
+ g_eVideoType++;
+ if (g_eVideoType >= NUM_VIDEO_MODES)
+ g_eVideoType = 0;
+ }
+ else if ( !KeybGetCtrlStatus() && KeybGetShiftStatus() ) // SHIFT+F9
+ {
+ if (g_eVideoType <= 0)
+ g_eVideoType = NUM_VIDEO_MODES;
+ g_eVideoType--;
+ }
+ else if ( KeybGetCtrlStatus() && KeybGetShiftStatus() ) // CTRL+SHIFT+F9
+ {
+ SetVideoStyle( (VideoStyle_e) (GetVideoStyle() ^ VS_HALF_SCANLINES) );
+ }
+
+ // TODO: Clean up code:FrameRefreshStatus(DRAW_TITLE) DrawStatusArea((HDC)0,DRAW_TITLE)
+ DrawStatusArea( (HDC)0, DRAW_TITLE );
+
+ VideoReinitialize(false);
+
+ if (g_nAppMode != MODE_LOGO)
+ {
+ if (g_nAppMode == MODE_DEBUG)
+ {
+ UINT debugVideoMode;
+ if ( DebugGetVideoMode(&debugVideoMode) )
+ VideoRefreshScreen(debugVideoMode, true);
+ else
+ VideoRefreshScreen();
+ }
+ else
+ {
+ VideoRefreshScreen();
+ }
+ }
+
+ Config_Save_Video();
+ }
+ else if (wparam == VK_F10)
+ {
+ if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED || g_Apple2Type == A2TYPE_BASE64A)
+ {
+ SetVideoRomRockerSwitch( !GetVideoRomRockerSwitch() ); // F10: toggle rocker switch
+ NTSC_VideoInitAppleType();
+ }
+ else if (g_Apple2Type == A2TYPE_PRAVETS8A)
+ {
+ KeybToggleP8ACapsLock (); // F10: Toggles Pravets8A Capslock
+ }
+ }
+ else if (wparam == VK_F11 && !KeybGetCtrlStatus()) // Save state (F11)
+ {
+ SoundCore_SetFade(FADE_OUT);
+ if(sg_PropertySheet.SaveStateSelectImage(window, true))
+ {
+ Snapshot_SaveState();
+ }
+ SoundCore_SetFade(FADE_IN);
+ }
+ else if (wparam == VK_F12) // Load state (F12 or Ctrl+F12)
+ {
+ SoundCore_SetFade(FADE_OUT);
+ if(sg_PropertySheet.SaveStateSelectImage(window, false))
+ {
+ Snapshot_LoadState();
+ }
+ SoundCore_SetFade(FADE_IN);
+ }
+ else if (wparam == VK_CAPITAL)
+ {
+ KeybToggleCapsLock();
+ }
+ else if (wparam == VK_PAUSE)
+ {
+ SetUsingCursor(FALSE);
+ switch (g_nAppMode)
+ {
+ case MODE_RUNNING:
+ g_nAppMode = MODE_PAUSED;
+ SoundCore_SetFade(FADE_OUT);
+ RevealCursor();
+ break;
+ case MODE_PAUSED:
+ g_nAppMode = MODE_RUNNING;
+ SoundCore_SetFade(FADE_IN);
+ // Don't call FrameShowCursor(FALSE) else ClipCursor() won't be called
+ break;
+ case MODE_STEPPING:
+ SoundCore_SetFade(FADE_OUT);
+ DebugStopStepping();
+ break;
+ }
+ DrawStatusArea((HDC)0,DRAW_TITLE);
+ if ((g_nAppMode != MODE_LOGO) && (g_nAppMode != MODE_DEBUG))
+ VideoRedrawScreen();
+ }
+ else if ((wparam == VK_SCROLL) && sg_PropertySheet.GetScrollLockToggle())
+ {
+ g_bScrollLock_FullSpeed = !g_bScrollLock_FullSpeed;
+ }
+ else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_LOGO) || (g_nAppMode == MODE_STEPPING))
+ {
+ // NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
+ // . NB. The keyboard hook filter will suppress VK_LCONTROL (if -hook-altgr-control is passed on the cmd-line)
+ bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
+ bool down = true;
+ bool autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
+ BOOL IsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
+
+#if DEBUG_KEY_MESSAGES
+ LogOutput("WM_KEYDOWN: %08X (scanCode=%04X)\n", wparam, (lparam>>16)&0xfff);
+#endif
+ if (!IsJoyKey &&
+ (g_nAppMode != MODE_LOGO)) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
+ {
+ // GH#678 Alternate key(s) to toggle max speed
+ // . Ctrl-0: Toggle speed: custom speed / Full-Speed
+ // . Ctrl-1: Speed = 1 MHz
+ // . Ctrl-3: Speed = Full-Speed
+ bool keyHandled = false;
+ if( KeybGetCtrlStatus() &&
+ !KeybGetAltStatus() && // GH#749 - AltGr also fakes CTRL being pressed!
+ wparam >= '0' && wparam <= '9' )
+ {
+ switch (wparam)
+ {
+ case '0': // Toggle speed: custom speed / Full-Speed
+ if (g_dwSpeed == SPEED_MAX)
+ REGLOAD_DEFAULT(TEXT(REGVALUE_EMULATION_SPEED), &g_dwSpeed, SPEED_NORMAL);
+ else
+ g_dwSpeed = SPEED_MAX;
+ keyHandled = true; break;
+ case '1': // Speed = 1 MHz
+ g_dwSpeed = SPEED_NORMAL;
+ REGSAVE(TEXT(REGVALUE_EMULATION_SPEED), g_dwSpeed);
+ keyHandled = true; break;
+ case '3': // Speed = Full-Speed
+ g_dwSpeed = SPEED_MAX;
+ keyHandled = true; break;
+ default:
+ break;
+ }
+
+ if (keyHandled)
+ SetCurrentCLK6502();
+ }
+
+ if (!keyHandled)
+ KeybQueueKeypress(wparam, NOT_ASCII);
+
+ if (!autorep)
+ KeybAnyKeyDown(WM_KEYDOWN, wparam, extended);
+ }
+ }
+ else if (g_nAppMode == MODE_DEBUG)
+ {
+ DebuggerProcessKey(wparam); // Debugger already active, re-direct key to debugger
+ }
+ break;
+
+ case WM_CHAR:
+ if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_LOGO))
+ {
+ if (!g_bDebuggerEatKey)
+ {
+#if DEBUG_KEY_MESSAGES
+ LogOutput("WM_CHAR: %08X\n", wparam);
+#endif
+ if (g_nAppMode != MODE_LOGO) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
+ KeybQueueKeypress(wparam, ASCII);
+ }
+
+ g_bDebuggerEatKey = false;
+ }
+ else if (g_nAppMode == MODE_DEBUG)
+ {
+ DebuggerInputConsoleChar((TCHAR)wparam);
+ }
+ break;
+
+ case WM_KEYUP:
+ if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1))
+ {
+ buttondown = -1;
+ if (g_bIsFullScreen)
+ EraseButton(wparam-VK_F1);
+ else
+ DrawButton((HDC)0,wparam-VK_F1);
+
+ const int iButton = wparam-VK_F1;
+ if (KeybGetCtrlStatus() && (wparam == VK_F3 || wparam == VK_F4)) // Ctrl+F3/F4 for drive pop-up menu (GH#817)
+ {
+ POINT pt; // location of mouse click
+ pt.x = buttonx + BUTTONCX/2;
+ pt.y = buttony + BUTTONCY/2 + iButton * BUTTONCY;
+ const int iDrive = wparam - VK_F3;
+ ProcessDiskPopupMenu( window, pt, iDrive );
+
+ FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
+ DrawButton((HDC)0, iButton);
+ }
+ else
+ {
+ ProcessButtonClick(iButton, true);
+ }
+ }
+ else
+ {
+ bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
+ bool down = false;
+ bool autorep = false;
+ BOOL bIsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
+
+#if DEBUG_KEY_MESSAGES
+ LogOutput("WM_KEYUP: %08X\n", wparam);
+#endif
+ if (!bIsJoyKey)
+ KeybAnyKeyDown(WM_KEYUP, wparam, extended);
+ }
+ break;
+
+ case WM_LBUTTONDOWN:
+ KeybUpdateCtrlShiftStatus();
+
+ if (buttondown == -1)
+ {
+ int x = LOWORD(lparam);
+ int y = HIWORD(lparam);
+ if ((x >= buttonx) &&
+ (y >= buttony) &&
+ (y <= buttony+BUTTONS*BUTTONCY))
+ {
+ buttonactive = buttondown = (y-buttony-1)/BUTTONCY;
+ DrawButton((HDC)0,buttonactive);
+ SetCapture(window);
+ }
+ else if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
+ {
+ if (wparam & (MK_CONTROL | MK_SHIFT))
+ {
+ SetUsingCursor(FALSE);
+ }
+ else
+ {
+ JoySetButton(BUTTON0, BUTTON_DOWN);
+ }
+ }
+ else if ( ((x < buttonx) && JoyUsingMouse() && ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING))) )
+ {
+ SetUsingCursor(TRUE);
+ }
+ else if (GetCardMgr().IsMouseCardInstalled())
+ {
+ if (wparam & (MK_CONTROL | MK_SHIFT))
+ {
+ RevealCursor();
+ }
+ else if (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING)
+ {
+ CMouseInterface* pMouseCard = GetCardMgr().GetMouseCard();
+
+ if (pMouseCard)
+ {
+ if (!pMouseCard->IsEnabled())
+ {
+ pMouseCard->SetEnabled(true);
+
+ POINT Point;
+ GetCursorPos(&Point);
+ ScreenToClient(g_hFrameWindow, &Point);
+ const int iOutOfBoundsX=0, iOutOfBoundsY=0;
+ UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY, Point.x, Point.y);
+
+ // Don't call SetButton() when 1st enabled (else get the confusing action of both enabling & an Apple mouse click)
+ }
+ else
+ {
+ pMouseCard->SetButton(BUTTON0, BUTTON_DOWN);
+ }
+ }
+ }
+ }
+
+ DebuggerMouseClick( x, y );
+ }
+ RelayEvent(WM_LBUTTONDOWN,wparam,lparam);
+ break;
+
+ case WM_LBUTTONUP:
+ if (buttonactive != -1) {
+ ReleaseCapture();
+ if (buttondown == buttonactive) {
+ buttondown = -1;
+ if (g_bIsFullScreen)
+ EraseButton(buttonactive);
+ else
+ DrawButton((HDC)0,buttonactive);
+ ProcessButtonClick(buttonactive, true);
+ }
+ buttonactive = -1;
+ }
+ else if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
+ {
+ JoySetButton(BUTTON0, BUTTON_UP);
+ }
+ else if (GetCardMgr().IsMouseCardInstalled())
+ {
+ GetCardMgr().GetMouseCard()->SetButton(BUTTON0, BUTTON_UP);
+ }
+ RelayEvent(WM_LBUTTONUP,wparam,lparam);
+ break;
+
+ case WM_MOUSEMOVE: {
+ // MSDN: "WM_MOUSEMOVE message" : Do not use the LOWORD or HIWORD macros to extract the x- and y- coordinates...
+ int x = GET_X_LPARAM(lparam);
+ int y = GET_Y_LPARAM(lparam);
+ int newover = (((x >= buttonx) &&
+ (x <= buttonx+BUTTONCX) &&
+ (y >= buttony) &&
+ (y <= buttony+BUTTONS*BUTTONCY))
+ ? (y-buttony-1)/BUTTONCY : -1);
+ if (buttonactive != -1) {
+ int newdown = (newover == buttonactive) ? buttonactive : -1;
+ if (newdown != buttondown) {
+ buttondown = newdown;
+ DrawButton((HDC)0,buttonactive);
+ }
+ }
+ else if (g_bIsFullScreen && (newover != buttonover) && (buttondown == -1)) {
+ if (buttonover != -1)
+ EraseButton(buttonover);
+ buttonover = newover;
+ if (buttonover != -1)
+ DrawButton((HDC)0,buttonover);
+ }
+ else if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
+ {
+ DrawCrosshairs(x,y);
+ JoySetPosition(x-viewportx-2, g_nViewportCX-4, y-viewporty-2, g_nViewportCY-4);
+ }
+ else if (GetCardMgr().IsMouseCardInstalled() && GetCardMgr().GetMouseCard()->IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING))
+ {
+ if (g_bLastCursorInAppleViewport)
+ break;
+
+ // Outside Apple viewport
+
+ const int iAppleScreenMaxX = g_nViewportCX-1;
+ const int iAppleScreenMaxY = g_nViewportCY-1;
+ const int iBoundMinX = viewportx;
+ const int iBoundMaxX = iAppleScreenMaxX;
+ const int iBoundMinY = viewporty;
+ const int iBoundMaxY = iAppleScreenMaxY;
+
+ int iOutOfBoundsX=0, iOutOfBoundsY=0;
+ if (x < iBoundMinX) iOutOfBoundsX=-1;
+ if (x > iBoundMaxX) iOutOfBoundsX=1;
+ if (y < iBoundMinY) iOutOfBoundsY=-1;
+ if (y > iBoundMaxY) iOutOfBoundsY=1;
+
+ UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY, x, y);
+ }
+
+ FullScreenRevealCursor();
+
+ RelayEvent(WM_MOUSEMOVE,wparam,lparam);
+ break;
+ }
+
+ case WM_TIMER:
+ if (wparam == IDEVENT_TIMER_MOUSE)
+ {
+ // NB. Need to check /g_bAppActive/ since WM_TIMER events still occur after AppleWin app has lost focus
+ if (g_bAppActive && GetCardMgr().IsMouseCardInstalled() && GetCardMgr().GetMouseCard()->IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING || g_nAppMode == MODE_STEPPING))
+ {
+ if (!g_bLastCursorInAppleViewport)
+ break;
+
+ // Inside Apple viewport
+
+ int iOutOfBoundsX=0, iOutOfBoundsY=0;
+
+ long dX,dY;
+ if (DIMouse::ReadImmediateData(&dX, &dY) == S_OK)
+ GetCardMgr().GetMouseCard()->SetPositionRel(dX, dY, &iOutOfBoundsX, &iOutOfBoundsY);
+
+ UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY);
+ }
+ }
+ else if (wparam == IDEVENT_TIMER_100MSEC) // GH#504
+ {
+ if (g_bIsFullScreen
+ && !GetCardMgr().IsMouseCardInstalled() // Don't interfere if there's a mousecard present!
+ && !g_bUsingCursor // Using mouse for joystick emulation (or mousecard restricted to window)
+ && g_bShowingCursor
+ && g_bFrameActive) // Frame inactive when eg. Config or 'Select Disk Image' dialogs are opened
+ {
+ g_uCount100msec++;
+ if (g_uCount100msec > 20) // Hide every 2sec of mouse inactivity
+ {
+ FrameShowCursor(FALSE);
+ }
+ }
+ }
+ break;
+
+// VSCROLL
+// SB_LINEUP // Line Scrolling
+// SB_PAGEUP // Page Scrolling
+ case WM_MOUSEWHEEL:
+ if (g_nAppMode == MODE_DEBUG)
+ {
+ KeybUpdateCtrlShiftStatus();
+ int zDelta = (short) HIWORD( wparam );
+ if (zDelta > 0)
+ {
+ DebuggerProcessKey( VK_UP );
+ }
+ else
+ {
+ DebuggerProcessKey( VK_DOWN );
+ }
+ }
+ break;
+
+ case WM_NOTIFY: // Tooltips for Drive buttons
+ if (((LPNMTTDISPINFO)lparam)->hdr.hwndFrom == tooltipwindow && ((LPNMTTDISPINFO)lparam)->hdr.code == TTN_GETDISPINFO)
+ {
+ LPNMTTDISPINFO pInfo = (LPNMTTDISPINFO)lparam;
+ SendMessage(pInfo->hdr.hwndFrom, TTM_SETMAXTIPWIDTH, 0, 150);
+
+ Disk2InterfaceCard *pDisk2Slot5 = NULL, *pDisk2Slot6 = NULL;
+
+ if (GetCardMgr().QuerySlot(SLOT5) == CT_Disk2)
+ pDisk2Slot5 = dynamic_cast(GetCardMgr().GetObj(SLOT5));
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ pDisk2Slot6 = dynamic_cast(GetCardMgr().GetObj(SLOT6));
+
+ std::string slot5 = pDisk2Slot5 ? pDisk2Slot5->GetFullDiskFilename(((LPNMTTDISPINFO)lparam)->hdr.idFrom) : "";
+ std::string slot6 = pDisk2Slot6 ? pDisk2Slot6->GetFullDiskFilename(((LPNMTTDISPINFO)lparam)->hdr.idFrom) : "";
+
+ if (pDisk2Slot5)
+ {
+ if (slot6.empty()) slot6 = "";
+ if (slot5.empty()) slot5 = "";
+ slot6 = std::string("Slot6: ") + slot6;
+ slot5 = std::string("Slot5: ") + slot5;
+ }
+
+ std::string join = (!slot6.empty() && !slot5.empty()) ? "\r\n" : "";
+ driveTooltip = slot6 + join + slot5;
+ ((LPNMTTDISPINFO)lparam)->lpszText = (LPTSTR)driveTooltip.c_str();
+ }
+ break;
+
+ case WM_PAINT:
+ if (GetUpdateRect(window,NULL,0)){
+ DrawFrameWindow(true);
+ }
+ break;
+
+ case WM_PALETTECHANGED:
+ // To avoid creating an infinite loop, a window that receives this
+ // message must not realize its palette, unless it determines that
+ // wParam does not contain its own window handle.
+ if ((HWND)wparam == window)
+ break;
+ // else fall through
+
+ case WM_QUERYNEWPALETTE:
+ DrawFrameWindow();
+ break;
+
+ case WM_RBUTTONDOWN:
+ case WM_RBUTTONUP:
+ if ((buttonover == -1) && (message == WM_RBUTTONUP)) // HACK: BUTTON_NONE
+ {
+ int x = LOWORD(lparam);
+ int y = HIWORD(lparam);
+
+ if ((x >= buttonx) &&
+ (y >= buttony) &&
+ (y <= buttony+BUTTONS*BUTTONCY))
+ {
+ const int iButton = (y-buttony-1)/BUTTONCY;
+ const int iDrive = iButton - BTN_DRIVE1;
+ if ((iButton == BTN_DRIVE1) || (iButton == BTN_DRIVE2))
+ {
+ {
+ RECT rect; // client area
+ POINT pt; // location of mouse click
+
+ // Get the bounding rectangle of the client area.
+ GetClientRect(window, (LPRECT) &rect);
+
+ // Get the client coordinates for the mouse click.
+ pt.x = GET_X_LPARAM(lparam);
+ pt.y = GET_Y_LPARAM(lparam);
+
+ // If the mouse click took place inside the client
+ // area, execute the application-defined function
+ // that displays the shortcut menu.
+ if (PtInRect((LPRECT) &rect, pt))
+ ProcessDiskPopupMenu( window, pt, iDrive );
+ }
+
+ FrameRefreshStatus(DRAW_LEDS | DRAW_BUTTON_DRIVES);
+ DrawButton((HDC)0, iButton);
+ }
+ }
+ }
+
+ if (g_bUsingCursor && !GetCardMgr().IsMouseCardInstalled())
+ JoySetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP);
+ else if (GetCardMgr().IsMouseCardInstalled())
+ GetCardMgr().GetMouseCard()->SetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP);
+
+ RelayEvent(message,wparam,lparam);
+ break;
+
+ case WM_SYSCOLORCHANGE:
+#if DEBUG_DD_PALETTE
+ if( g_bIsFullScreen )
+ OutputDebugString( "WM_SYSCOLORCHANGE: Full Screen\n" );
+ else
+ OutputDebugString( "WM_SYSCOLORCHANGE: Windowed\n" );
+#endif
+
+ DeleteGdiObjects();
+ CreateGdiObjects();
+ break;
+
+ case WM_SYSCOMMAND:
+ switch (wparam & 0xFFF0) {
+ case SC_KEYMENU:
+ if (g_bIsFullScreen && g_bAppActive)
+ return 0;
+ break;
+ case SC_MINIMIZE:
+ GetWindowRect(window,&framerect);
+ break;
+ }
+ break;
+
+ case WM_SYSKEYDOWN: // ALT + any key; or F10
+ KeybUpdateCtrlShiftStatus();
+
+ // http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
+ if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
+ return 0; // NOP -- eat key
+
+ PostMessage(window,WM_KEYDOWN,wparam,lparam);
+
+ if ((wparam == VK_F10) || (wparam == VK_MENU)) // VK_MENU == ALT Key
+ return 0;
+
+ break;
+
+ case WM_SYSKEYUP:
+ KeybUpdateCtrlShiftStatus();
+
+ // F10: no WM_KEYUP handler for VK_F10. Don't allow WM_KEYUP to pass to default handler which will show the app window's "menu" (and lose focus)
+ if (wparam == VK_F10)
+ return 0;
+
+ if (g_bAltEnter_ToggleFullScreen && KeybGetAltStatus() && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
+ ScreenWindowResize(false);
+ else
+ PostMessage(window,WM_KEYUP,wparam,lparam);
+
+ break;
+
+ case WM_MENUCHAR: // GH#556 - Suppress the Windows Default Beep (ie. Ding) whenever ALT+ is pressed
+ return (MNC_CLOSE << 16) | (wparam & 0xffff);
+
+ case WM_USER_BENCHMARK: {
+ UpdateWindow(window);
+ ResetMachineState();
+ DrawStatusArea((HDC)0,DRAW_TITLE);
+ HCURSOR oldcursor = SetCursor(LoadCursor(0,IDC_WAIT));
+ g_nAppMode = MODE_BENCHMARK;
+ VideoBenchmark();
+ g_nAppMode = MODE_LOGO;
+ ResetMachineState();
+ SetCursor(oldcursor);
+ break;
+ }
+
+ case WM_USER_RESTART:
+ // Changed h/w config, eg. Apple computer type (][+ or //e), slot configuration, etc.
+ g_bRestart = true;
+ PostMessage(window,WM_CLOSE,0,0);
+ break;
+
+ case WM_USER_SAVESTATE: // Save state
+ Snapshot_SaveState();
+ break;
+
+ case WM_USER_LOADSTATE: // Load state
+ Snapshot_LoadState();
+ break;
+
+ case WM_USER_TCP_SERIAL: // TCP serial events
+ {
+ WORD error = WSAGETSELECTERROR(lparam);
+ if (error != 0)
+ {
+ LogOutput("TCP Serial Winsock error 0x%X (%d)\r", error, error);
+ switch (error)
+ {
+ case WSAENETRESET:
+ case WSAECONNABORTED:
+ case WSAECONNRESET:
+ case WSAENOTCONN:
+ case WSAETIMEDOUT:
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommTcpSerialClose();
+ break;
+
+ default:
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommTcpSerialCleanup();
+ break;
+ }
+ }
+ else
+ {
+ WORD wSelectEvent = WSAGETSELECTEVENT(lparam);
+ switch(wSelectEvent)
+ {
+ case FD_ACCEPT:
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommTcpSerialAccept();
+ break;
+
+ case FD_CLOSE:
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommTcpSerialClose();
+ break;
+
+ case FD_READ:
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommTcpSerialReceive();
+ break;
+ }
+ }
+ break;
+ }
+
+ // Message posted by: WM_DDE_EXECUTE & Cmd-line boot
+ case WM_USER_BOOT:
+ {
+ SetForegroundWindow(window);
+ Sleep(500); // Wait for SetForegroundWindow() to take affect (400ms seems OK, so use 500ms to be sure)
+ SoundCore_TweakVolumes();
+ ProcessButtonClick(BTN_RUN);
+ break;
+ }
+
+ // Message posted by: Cmd-line boot
+ case WM_USER_FULLSCREEN:
+ {
+ ScreenWindowResize(false);
+ break;
+ }
+
+ } // switch(message)
+
+ return DefWindowProc(window,message,wparam,lparam);
+}
+
+
+
+//===========================================================================
+// Process: VK_F6
+static void ScreenWindowResize(const bool bCtrlKey)
+{
+ static int nOldViewportScale = kDEFAULT_VIEWPORT_SCALE;
+
+ if (g_bIsFullScreen) // if full screen: then switch back to normal
+ {
+ SetNormalMode();
+ FrameResizeWindow(nOldViewportScale);
+ }
+ else if (bCtrlKey) // if normal screen && CTRL: then toggle scaling
+ {
+ FrameResizeWindow( (g_nViewportScale == 1) ? 2 : 1 ); // Toggle between 1x and 2x
+ REGSAVE(TEXT(REGVALUE_WINDOW_SCALE), g_nViewportScale);
+ }
+ else
+ {
+ nOldViewportScale = g_nViewportScale;
+ FrameResizeWindow(1); // reset to 1x
+ SetFullScreenMode();
+ }
+}
+
+static bool ConfirmReboot(bool bFromButtonUI)
+{
+ if (!bFromButtonUI || !g_bConfirmReboot)
+ return true;
+
+ int res = MessageBox(g_hFrameWindow,
+ "Are you sure you want to reboot?\n"
+ "(All data will be lost!)\n"
+ "\n"
+ "You can skip this dialog from displaying\n"
+ "in the future by unchecking:\n"
+ "\n"
+ " [ ] Confirm reboot\n"
+ "\n"
+ "in the Configuration dialog.\n"
+ , "Reboot", MB_ICONWARNING|MB_YESNO);
+ return res == IDYES;
+}
+
+static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
+{
+ SoundCore_SetFade(FADE_OUT);
+ bool bAllowFadeIn = true;
+
+#if DEBUG_DD_PALETTE
+ char _text[ 80 ];
+ sprintf( _text, "Button: F%d Full Screen: %d\n", button+1, g_bIsFullScreen );
+ OutputDebugString( _text );
+#endif
+
+ switch (button) {
+
+ case BTN_HELP:
+ {
+ const std::string filename = g_sProgramDir + TEXT("APPLEWIN.CHM");
+
+ // (GH#437) For any internet downloaded AppleWin.chm files (stored on an NTFS drive) there may be an Alt Data Stream containing a Zone Identifier
+ // - try to delete it, otherwise the content won't be displayed unless it's unblock (via File Properties)
+ {
+ const std::string filename_with_zone_identifier = filename + TEXT(":Zone.Identifier");
+ DeleteFile(filename_with_zone_identifier.c_str());
+ }
+
+ HtmlHelp(g_hFrameWindow,filename.c_str(),HH_DISPLAY_TOC,0);
+ helpquit = 1;
+ }
+ break;
+
+ case BTN_RUN:
+ KeybUpdateCtrlShiftStatus();
+ if( KeybGetCtrlStatus() )
+ {
+ CtrlReset();
+ if (g_nAppMode == MODE_DEBUG)
+ DebugDisplay(TRUE);
+ return;
+ }
+
+ if (g_nAppMode == MODE_LOGO)
+ {
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ dynamic_cast(GetCardMgr().GetRef(SLOT6)).Boot();
+
+ LogFileTimeUntilFirstKeyReadReset();
+ g_nAppMode = MODE_RUNNING;
+ }
+ else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_DEBUG) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_PAUSED))
+ {
+ if (ConfirmReboot(bFromButtonUI))
+ {
+ ResetMachineState();
+
+ // NB. Don't exit debugger or stepping
+
+ if (g_nAppMode == MODE_DEBUG)
+ DebugDisplay(TRUE);
+ }
+ }
+
+ DrawStatusArea((HDC)0,DRAW_TITLE);
+ VideoRedrawScreen();
+ break;
+
+ case BTN_DRIVE1:
+ case BTN_DRIVE2:
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ {
+ dynamic_cast(GetCardMgr().GetRef(SLOT6)).UserSelectNewDiskImage(button-BTN_DRIVE1);
+ if (!g_bIsFullScreen)
+ DrawButton((HDC)0,button);
+ }
+ break;
+
+ case BTN_DRIVESWAP:
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ {
+ dynamic_cast(GetCardMgr().GetRef(SLOT6)).DriveSwap();
+ }
+ break;
+
+ case BTN_FULLSCR:
+ KeybUpdateCtrlShiftStatus();
+ ScreenWindowResize( KeybGetCtrlStatus() );
+ break;
+
+ case BTN_DEBUG:
+ if (g_nAppMode == MODE_LOGO && !GetLoadedSaveStateFlag())
+ {
+ // FIXME: Why is this needed? Surely when state is MODE_LOGO, then AppleII system will have been reset!
+ // - Transition to MODE_LOGO when: (a) AppleWin starts, (b) there's a Config change to the AppleII h/w
+ ResetMachineState();
+ }
+
+ if (g_nAppMode == MODE_STEPPING)
+ {
+ // Allow F7 to enter debugger even when not MODE_RUNNING
+ DebugStopStepping();
+ bAllowFadeIn = false;
+ }
+ else if (g_nAppMode == MODE_DEBUG)
+ {
+ DebugExitDebugger(); // Exit debugger, switch to MODE_RUNNING or MODE_STEPPING
+ g_bDebuggerEatKey = false; // Don't "eat" the next keypress when leaving the debugger via F7 (or clicking the Debugger button)
+ }
+ else // MODE_RUNNING, MODE_LOGO, MODE_PAUSED
+ {
+ DebugBegin();
+ }
+ break;
+
+ case BTN_SETUP:
+ {
+ sg_PropertySheet.Init();
+ }
+ break;
+
+ }
+
+ if((g_nAppMode != MODE_DEBUG) && (g_nAppMode != MODE_PAUSED) && bAllowFadeIn)
+ {
+ SoundCore_SetFade(FADE_IN);
+ }
+}
+
+
+//===========================================================================
+
+// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/winui/winui/windowsuserinterface/resources/menus/usingmenus.asp
+// http://www.codeproject.com/menu/MenusForBeginners.asp?df=100&forumid=67645&exp=0&select=903061
+
+void ProcessDiskPopupMenu(HWND hwnd, POINT pt, const int iDrive)
+{
+ if (GetCardMgr().QuerySlot(SLOT6) != CT_Disk2)
+ return;
+
+ Disk2InterfaceCard& disk2Card = dynamic_cast(GetCardMgr().GetRef(SLOT6));
+
+ // This is the default installation path of CiderPress.
+ // It shall not be left blank, otherwise an explorer window will be open.
+ TCHAR PathToCiderPress[MAX_PATH];
+ RegLoadString(
+ TEXT("Configuration"),
+ REGVALUE_CIDERPRESSLOC,
+ 1,
+ PathToCiderPress,
+ MAX_PATH,
+ TEXT("C:\\Program Files\\faddenSoft\\CiderPress\\CiderPress.exe"));
+ //TODO: A directory is open if an empty path to CiderPress is set. This has to be fixed.
+
+ std::string filename1= "\"";
+ filename1.append( disk2Card.GetFullName(iDrive) );
+ filename1.append("\"");
+ std::string sFileNameEmpty = "\"";
+ sFileNameEmpty.append("\"");
+
+ // Load the menu template containing the shortcut menu from the
+ // application's resources.
+ HMENU hmenu = LoadMenu(g_hInstance, MAKEINTRESOURCE(IDR_MENU_DISK_POPUP)); // menu template
+ if (hmenu == NULL)
+ return;
+
+ // Get the first shortcut menu in the menu template.
+ // This is the menu that TrackPopupMenu displays.
+ HMENU hmenuTrackPopup = GetSubMenu(hmenu, 0); // shortcut menu
+
+ // TrackPopup uses screen coordinates, so convert the
+ // coordinates of the mouse click to screen coordinates.
+ ClientToScreen(hwnd, (LPPOINT) &pt);
+
+ // Check menu depending on current floppy protection
+ {
+ int iMenuItem = ID_DISKMENU_WRITEPROTECTION_OFF;
+ if (disk2Card.GetProtect( iDrive ))
+ iMenuItem = ID_DISKMENU_WRITEPROTECTION_ON;
+
+ CheckMenuItem(hmenu, iMenuItem, MF_CHECKED);
+ }
+
+ if (disk2Card.IsDriveEmpty(iDrive))
+ EnableMenuItem(hmenu, ID_DISKMENU_EJECT, MF_GRAYED);
+
+ if (disk2Card.IsDiskImageWriteProtected(iDrive))
+ {
+ // If image-file is read-only (or a gzip) then disable these menu items
+ EnableMenuItem(hmenu, ID_DISKMENU_WRITEPROTECTION_ON, MF_GRAYED);
+ EnableMenuItem(hmenu, ID_DISKMENU_WRITEPROTECTION_OFF, MF_GRAYED);
+ }
+
+ // Draw and track the shortcut menu.
+ int iCommand = TrackPopupMenu(
+ hmenuTrackPopup
+ , TPM_LEFTALIGN | TPM_LEFTBUTTON | TPM_RETURNCMD
+ , pt.x, pt.y
+ , 0
+ , hwnd, NULL );
+
+ if (iCommand == ID_DISKMENU_EJECT)
+ disk2Card.EjectDisk( iDrive );
+ else
+ if (iCommand == ID_DISKMENU_WRITEPROTECTION_ON)
+ disk2Card.SetProtect( iDrive, true );
+ else
+ if (iCommand == ID_DISKMENU_WRITEPROTECTION_OFF)
+ disk2Card.SetProtect( iDrive, false );
+ else
+ if (iCommand == ID_DISKMENU_SENDTO_CIDERPRESS)
+ {
+ static char szCiderpressNotFoundCaption[] = "CiderPress not found";
+ static char szCiderpressNotFoundText[] = "CiderPress not found!\n"
+ "Please install CiderPress.\n"
+ "Otherwise set the path to CiderPress from Configuration->Disk.";
+
+ disk2Card.FlushCurrentTrack(iDrive);
+
+ //if(!filename1.compare("\"\"") == false) //Do not use this, for some reason it does not work!!!
+ if(!filename1.compare(sFileNameEmpty) )
+ {
+ int MB_Result = MessageBox(g_hFrameWindow, "No disk image loaded. Do you want to run CiderPress anyway?" ,"No disk image.", MB_ICONINFORMATION|MB_YESNO);
+ if (MB_Result == IDYES)
+ {
+ if (FileExists (PathToCiderPress ))
+ {
+ HINSTANCE nResult = ShellExecute(NULL, "open", PathToCiderPress, "" , NULL, SW_SHOWNORMAL);
+ }
+ else
+ {
+ MessageBox(g_hFrameWindow, szCiderpressNotFoundText, szCiderpressNotFoundCaption, MB_ICONINFORMATION|MB_OK);
+ }
+ }
+ }
+ else
+ {
+ if (FileExists (PathToCiderPress ))
+ {
+ HINSTANCE nResult = ShellExecute(NULL, "open", PathToCiderPress, filename1.c_str() , NULL, SW_SHOWNORMAL);
+ }
+ else
+ {
+ MessageBox(g_hFrameWindow, szCiderpressNotFoundText, szCiderpressNotFoundCaption, MB_ICONINFORMATION|MB_OK);
+ }
+ }
+ }
+
+ // Destroy the menu.
+ BOOL bRes = DestroyMenu(hmenu);
+ _ASSERT(bRes);
+}
+
+
+//===========================================================================
+void RelayEvent (UINT message, WPARAM wparam, LPARAM lparam) {
+ if (g_bIsFullScreen)
+ return;
+ MSG msg;
+ msg.hwnd = g_hFrameWindow;
+ msg.message = message;
+ msg.wParam = wparam;
+ msg.lParam = lparam;
+ SendMessage(tooltipwindow,TTM_RELAYEVENT,0,(LPARAM)&msg);
+}
+
+//===========================================================================
+
+// CtrlReset() vs ResetMachineState():
+// . CPU:
+// Ctrl+Reset : 6502.sp=-3 / CpuReset()
+// Power cycle: 6502.sp=0x1ff / CpuInitialize()
+// . Disk][:
+// Ctrl+Reset : if motor-on, then motor-off but continue to spin for 1s
+// Power cycle: motor-off & immediately stop spinning
+
+// todo: consolidate CtrlReset() and ResetMachineState()
+void ResetMachineState ()
+{
+ GetCardMgr().GetDisk2CardMgr().Reset(true);
+ HD_Reset();
+ g_bFullSpeed = 0; // Might've hit reset in middle of InternalCpuExecute() - so beep may get (partially) muted
+
+ MemReset(); // calls CpuInitialize(), CNoSlotClock.Reset()
+ PravetsReset();
+ if (GetCardMgr().QuerySlot(SLOT6) == CT_Disk2)
+ dynamic_cast(GetCardMgr().GetRef(SLOT6)).Boot();
+ VideoResetState();
+ KeybReset();
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommReset();
+ PrintReset();
+ JoyReset();
+ MB_Reset();
+ SpkrReset();
+ if (GetCardMgr().IsMouseCardInstalled())
+ GetCardMgr().GetMouseCard()->Reset();
+ SetActiveCpu( GetMainCpu() );
+#ifdef USE_SPEECH_API
+ g_Speech.Reset();
+#endif
+
+ SoundCore_SetFade(FADE_NONE);
+ LogFileTimeUntilFirstKeyReadReset();
+}
+
+
+//===========================================================================
+
+/*
+ * In comments, UTAII is an abbreviation for a reference to "Understanding the Apple II" by James Sather
+ */
+
+// todo: consolidate CtrlReset() and ResetMachineState()
+// Ctrl+Reset - TODO: This is a terrible place for this code! Should be in AppleWin.cpp
+void CtrlReset()
+{
+ if (!IS_APPLE2)
+ {
+ // For A][ & A][+, reset doesn't reset the LC switches (UTAII:5-29)
+ MemResetPaging();
+
+ // For A][ & A][+, reset doesn't reset the video mode (UTAII:4-4)
+ VideoResetState(); // Switch Alternate char set off
+ }
+
+ if (IsAppleIIeOrAbove(GetApple2Type()) || IsCopamBase64A(GetApple2Type()))
+ {
+ // For A][ & A][+, reset doesn't reset the annunciators (UTAIIe:I-5)
+ // Base 64A: on RESET does reset to ROM page 0 (GH#807)
+ MemAnnunciatorReset();
+ }
+
+ PravetsReset();
+ GetCardMgr().GetDisk2CardMgr().Reset();
+ HD_Reset();
+ KeybReset();
+ if (GetCardMgr().IsSSCInstalled())
+ GetCardMgr().GetSSC()->CommReset();
+ MB_Reset();
+ if (GetCardMgr().IsMouseCardInstalled())
+ GetCardMgr().GetMouseCard()->Reset(); // Deassert any pending IRQs - GH#514
+#ifdef USE_SPEECH_API
+ g_Speech.Reset();
+#endif
+
+ CpuReset();
+ g_bFreshReset = true;
+}
+
+
+//===========================================================================
+
+int GetFullScreenOffsetX(void)
+{
+ return g_win_fullscreen_offsetx;
+}
+
+int GetFullScreenOffsetY(void)
+{
+ return g_win_fullscreen_offsety;
+}
+
+void SetFullScreenMode ()
+{
+#ifdef NO_DIRECT_X
+
+ return;
+
+#else // NO_DIRECT_X
+
+ MONITORINFO monitor_info;
+ FULLSCREEN_SCALE_TYPE width, height, scalex, scaley;
+ int top, left;
+
+ buttonover = -1;
+
+ g_main_window_saved_style = GetWindowLong(g_hFrameWindow, GWL_STYLE);
+ g_main_window_saved_exstyle = GetWindowLong(g_hFrameWindow, GWL_EXSTYLE);
+ GetWindowRect(g_hFrameWindow, &g_main_window_saved_rect);
+ SetWindowLong(g_hFrameWindow, GWL_STYLE , g_main_window_saved_style & ~(WS_CAPTION | WS_THICKFRAME));
+ SetWindowLong(g_hFrameWindow, GWL_EXSTYLE, g_main_window_saved_exstyle & ~(WS_EX_DLGMODALFRAME | WS_EX_WINDOWEDGE | WS_EX_CLIENTEDGE | WS_EX_STATICEDGE));
+
+ monitor_info.cbSize = sizeof(monitor_info);
+ GetMonitorInfo(MonitorFromWindow(g_hFrameWindow, MONITOR_DEFAULTTONEAREST), &monitor_info);
+
+ left = monitor_info.rcMonitor.left;
+ top = monitor_info.rcMonitor.top;
+
+ width = (FULLSCREEN_SCALE_TYPE)(monitor_info.rcMonitor.right - monitor_info.rcMonitor.left);
+ height = (FULLSCREEN_SCALE_TYPE)(monitor_info.rcMonitor.bottom - monitor_info.rcMonitor.top );
+
+ scalex = width / GetFrameBufferBorderlessWidth();
+ scaley = height / GetFrameBufferBorderlessHeight();
+
+ g_win_fullscreen_scale = (scalex <= scaley) ? scalex : scaley;
+ g_win_fullscreen_offsetx = ((int)width - (int)(g_win_fullscreen_scale * GetFrameBufferBorderlessWidth())) / 2;
+ g_win_fullscreen_offsety = ((int)height - (int)(g_win_fullscreen_scale * GetFrameBufferBorderlessHeight())) / 2;
+ SetWindowPos(g_hFrameWindow, NULL, left, top, (int)width, (int)height, SWP_NOZORDER | SWP_NOACTIVATE | SWP_FRAMECHANGED);
+ g_bIsFullScreen = true;
+
+ SetViewportScale(g_win_fullscreen_scale, true);
+
+ buttonx = GetFullScreenOffsetX() + g_nViewportCX + VIEWPORTX*2;
+ buttony = GetFullScreenOffsetY();
+ viewportx = VIEWPORTX; // TC-TODO: Should be zero too? (Since there's no 3D border in full-screen)
+ viewporty = 0; // GH#464
+
+ InvalidateRect(g_hFrameWindow,NULL,1);
+
+#endif // NO_DIRECT_X
+}
+
+//===========================================================================
+void SetNormalMode ()
+{
+ FullScreenRevealCursor(); // Do before clearing g_bIsFullScreen flag
+
+ buttonover = -1;
+ buttonx = BUTTONX;
+ buttony = BUTTONY;
+ viewportx = VIEWPORTX;
+ viewporty = VIEWPORTY;
+
+ g_win_fullscreen_offsetx = 0;
+ g_win_fullscreen_offsety = 0;
+ g_win_fullscreen_scale = 1;
+ SetWindowLong(g_hFrameWindow, GWL_STYLE, g_main_window_saved_style);
+ SetWindowLong(g_hFrameWindow, GWL_EXSTYLE, g_main_window_saved_exstyle);
+ SetWindowPos(g_hFrameWindow, NULL,
+ g_main_window_saved_rect.left,
+ g_main_window_saved_rect.top,
+ g_main_window_saved_rect.right - g_main_window_saved_rect.left,
+ g_main_window_saved_rect.bottom - g_main_window_saved_rect.top,
+ SWP_SHOWWINDOW);
+ g_bIsFullScreen = false;
+}
+
+//===========================================================================
+static void SetUsingCursor (BOOL bNewValue)
+{
+ if (bNewValue == g_bUsingCursor)
+ return;
+
+ g_bUsingCursor = bNewValue;
+
+ if (g_bUsingCursor)
+ {
+ // Set TRUE when:
+ // . Using mouse for joystick emulation
+ // . Using mousecard and mouse is restricted to window
+ SetCapture(g_hFrameWindow);
+ RECT rect = { viewportx+2, // left
+ viewporty+2, // top
+ viewportx+g_nViewportCX-1, // right
+ viewporty+g_nViewportCY-1}; // bottom
+ ClientToScreen(g_hFrameWindow,(LPPOINT)&rect.left);
+ ClientToScreen(g_hFrameWindow,(LPPOINT)&rect.right);
+ ClipCursor(&rect);
+ FrameShowCursor(FALSE);
+ POINT pt;
+ GetCursorPos(&pt);
+ ScreenToClient(g_hFrameWindow,&pt);
+ DrawCrosshairs(pt.x,pt.y);
+ }
+ else
+ {
+ DrawCrosshairs(0,0);
+ FrameShowCursor(TRUE);
+ ClipCursor(NULL);
+ ReleaseCapture();
+ }
+}
+
+int GetViewportScale(void)
+{
+ return g_nViewportScale;
+}
+
+int SetViewportScale(int nNewScale, bool bForce /*=false*/)
+{
+ if (!bForce && nNewScale > g_nMaxViewportScale)
+ nNewScale = g_nMaxViewportScale;
+
+ g_nViewportScale = nNewScale;
+ g_nViewportCX = g_nViewportScale * GetFrameBufferBorderlessWidth();
+ g_nViewportCY = g_nViewportScale * GetFrameBufferBorderlessHeight();
+
+ return nNewScale;
+}
+
+static void SetupTooltipControls(void)
+{
+ TOOLINFO toolinfo;
+ toolinfo.cbSize = sizeof(toolinfo);
+ toolinfo.uFlags = TTF_CENTERTIP;
+ toolinfo.hwnd = g_hFrameWindow;
+ toolinfo.hinst = g_hInstance;
+ toolinfo.lpszText = LPSTR_TEXTCALLBACK;
+ toolinfo.rect.left = BUTTONX;
+ toolinfo.rect.right = toolinfo.rect.left+BUTTONCX+1;
+ toolinfo.uId = 0;
+ toolinfo.rect.top = BUTTONY+BTN_DRIVE1*BUTTONCY+1;
+ toolinfo.rect.bottom = toolinfo.rect.top+BUTTONCY;
+ SendMessage(tooltipwindow, TTM_ADDTOOL, 0, (LPARAM)&toolinfo);
+ toolinfo.uId = 1;
+ toolinfo.rect.top = BUTTONY+BTN_DRIVE2*BUTTONCY+1;
+ toolinfo.rect.bottom = toolinfo.rect.top+BUTTONCY;
+ SendMessage(tooltipwindow, TTM_ADDTOOL, 0, (LPARAM)&toolinfo);
+}
+
+// SM_CXPADDEDBORDER is not supported on 2000 & XP, but GetSystemMetrics() returns 0 for unknown values, so this use of SM_CXPADDEDBORDER works on 2000 & XP too:
+// http://msdn.microsoft.com/en-nz/library/windows/desktop/ms724385(v=vs.85).aspx
+// NB. GetSystemMetrics(SM_CXPADDEDBORDER) returns 0 for Win7, when built with VS2008 (see GH#571)
+static void GetWidthHeight(int& nWidth, int& nHeight)
+{
+ nWidth = g_nViewportCX + VIEWPORTX*2
+ + BUTTONCX
+ + (GetSystemMetrics(SM_CXFIXEDFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2;
+ nHeight = g_nViewportCY + VIEWPORTY*2
+ + (GetSystemMetrics(SM_CYFIXEDFRAME) + GetSystemMetrics(SM_CXPADDEDBORDER)) * 2 // NB. No SM_CYPADDEDBORDER
+ + GetSystemMetrics(SM_CYCAPTION);
+
+#if 0 // GH#571
+ LogOutput("g_nViewportCX = %d\n", g_nViewportCX);
+ LogOutput("VIEWPORTX = %d (const)\n", VIEWPORTX);
+ LogOutput("BUTTONCX = %d (const)\n", BUTTONCX);
+ LogOutput("GetSystemMetrics(SM_CXFRAME) = %d (unused)\n", GetSystemMetrics(SM_CXFRAME));
+ LogOutput("GetSystemMetrics(SM_CXFIXEDFRAME) = %d\n", GetSystemMetrics(SM_CXFIXEDFRAME));
+ LogOutput("GetSystemMetrics(SM_CXBORDER) = %d (unused)\n", GetSystemMetrics(SM_CXBORDER));
+ LogOutput("GetSystemMetrics(SM_CXPADDEDBORDER) = %d\n", GetSystemMetrics(SM_CXPADDEDBORDER));
+ LogOutput("nWidth = %d\n", nWidth);
+ LogOutput("g_nViewportCY = %d\n", g_nViewportCY);
+ LogOutput("VIEWPORTY = %d (const)\n", VIEWPORTY);
+ LogOutput("GetSystemMetrics(SM_CYFRAME) = %d (unused)\n", GetSystemMetrics(SM_CYFRAME));
+ LogOutput("GetSystemMetrics(SM_CYFIXEDFRAME) = %d\n", GetSystemMetrics(SM_CYFIXEDFRAME));
+ LogOutput("GetSystemMetrics(SM_CYBORDER) = %d (unused)\n", GetSystemMetrics(SM_CYBORDER));
+ LogOutput("GetSystemMetrics(SM_CYCAPTION) = %d\n", GetSystemMetrics(SM_CYCAPTION));
+ LogOutput("nHeight = %d\n\n", nHeight);
+#endif
+}
+
+static void FrameResizeWindow(int nNewScale)
+{
+ int nOldWidth, nOldHeight;
+ GetWidthHeight(nOldWidth, nOldHeight);
+
+ nNewScale = SetViewportScale(nNewScale);
+
+ GetWindowRect(g_hFrameWindow, &framerect);
+ int nXPos = framerect.left;
+ int nYPos = framerect.top;
+
+ //
+
+ buttonx = g_nViewportCX + VIEWPORTX*2;
+ buttony = 0;
+
+ // Invalidate old rect region
+ {
+ RECT irect;
+ irect.left = irect.top = 0;
+ irect.right = nOldWidth;
+ irect.bottom = nOldHeight;
+ InvalidateRect(g_hFrameWindow, &irect, TRUE);
+ }
+
+ // Resize the window
+ int nNewWidth, nNewHeight;
+ GetWidthHeight(nNewWidth, nNewHeight);
+
+ MoveWindow(g_hFrameWindow, nXPos, nYPos, nNewWidth, nNewHeight, TRUE);
+ UpdateWindow(g_hFrameWindow);
+
+ // Remove the tooltips for the old window size
+ TOOLINFO toolinfo = {0};
+ toolinfo.cbSize = sizeof(toolinfo);
+ toolinfo.hwnd = g_hFrameWindow;
+ toolinfo.uId = 0;
+ SendMessage(tooltipwindow, TTM_DELTOOL, 0, (LPARAM)&toolinfo);
+ toolinfo.uId = 1;
+ SendMessage(tooltipwindow, TTM_DELTOOL, 0, (LPARAM)&toolinfo);
+
+ // Setup the tooltips for the new window size
+ SetupTooltipControls();
+}
+
+//
+// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
+//
+
+//===========================================================================
+
+void FrameCreateWindow(void)
+{
+ int nWidth, nHeight;
+
+ // Set g_nMaxViewportScale
+ {
+ int nOldViewportCX = g_nViewportCX;
+ int nOldViewportCY = g_nViewportCY;
+
+ g_nViewportCX = GetFrameBufferBorderlessWidth() * 2;
+ g_nViewportCY = GetFrameBufferBorderlessHeight() * 2;
+ GetWidthHeight(nWidth, nHeight); // Probe with 2x dimensions
+
+ g_nViewportCX = nOldViewportCX;
+ g_nViewportCY = nOldViewportCY;
+
+ if (nWidth > GetSystemMetrics(SM_CXSCREEN) || nHeight > GetSystemMetrics(SM_CYSCREEN))
+ g_nMaxViewportScale = 1;
+ }
+
+ GetWidthHeight(nWidth, nHeight);
+
+ // If screen is too small for 2x, then revert to 1x
+ if (g_nViewportScale == 2 && (nWidth > GetSystemMetrics(SM_CXSCREEN) || nHeight > GetSystemMetrics(SM_CYSCREEN)))
+ {
+ g_nMaxViewportScale = 1;
+ SetViewportScale(1);
+ GetWidthHeight(nWidth, nHeight);
+ }
+
+ // Restore Window X Position
+ int nXPos = -1;
+ {
+ const int nXScreen = GetSystemMetrics(SM_CXSCREEN) - nWidth;
+
+ if (RegLoadValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_X_POS), 1, (DWORD*)&nXPos))
+ {
+ if ((nXPos > nXScreen) && !g_bMultiMon)
+ nXPos = -1; // Not fully visible, so default to centre position
+ }
+
+ if ((nXPos == -1) && !g_bMultiMon)
+ nXPos = nXScreen / 2;
+ }
+
+ // Restore Window Y Position
+ int nYPos = -1;
+ {
+ const int nYScreen = GetSystemMetrics(SM_CYSCREEN) - nHeight;
+
+ if (RegLoadValue(TEXT(REG_PREFS), TEXT(REGVALUE_PREF_WINDOW_Y_POS), 1, (DWORD*)&nYPos))
+ {
+ if ((nYPos > nYScreen) && !g_bMultiMon)
+ nYPos = -1; // Not fully visible, so default to centre position
+ }
+
+ if ((nYPos == -1) && !g_bMultiMon)
+ nYPos = nYScreen / 2;
+ }
+
+ //
+
+ buttonx = (g_nViewportCX + VIEWPORTX*2);
+ buttony = 0;
+
+ GetAppleWindowTitle();
+
+ // NB. g_hFrameWindow also set by WM_CREATE - NB. CreateWindow() must synchronously send WM_CREATE
+ g_hFrameWindow = CreateWindow(
+ TEXT("APPLE2FRAME"),
+ g_pAppTitle.c_str(),
+ WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
+ WS_MINIMIZEBOX | WS_VISIBLE,
+ nXPos, nYPos, nWidth, nHeight,
+ HWND_DESKTOP,
+ (HMENU)0,
+ g_hInstance, NULL );
+
+ InitCommonControls();
+ tooltipwindow = CreateWindow(
+ TOOLTIPS_CLASS,NULL,TTS_ALWAYSTIP,
+ CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,CW_USEDEFAULT,
+ g_hFrameWindow,
+ (HMENU)0,
+ g_hInstance,NULL );
+
+ SetupTooltipControls();
+
+ _ASSERT(g_TimerIDEvent_100msec == 0);
+ g_TimerIDEvent_100msec = SetTimer(g_hFrameWindow, IDEVENT_TIMER_100MSEC, 100, NULL);
+ LogFileOutput("FrameCreateWindow: SetTimer(), id=0x%08X\n", g_TimerIDEvent_100msec);
+}
+
+//===========================================================================
+HDC FrameGetDC () {
+ if (!g_hFrameDC) {
+ g_hFrameDC = GetDC(g_hFrameWindow);
+ SetViewportOrgEx(g_hFrameDC,viewportx,viewporty,NULL);
+ }
+ return g_hFrameDC;
+}
+
+//===========================================================================
+void FrameReleaseDC () {
+ if (g_hFrameDC) {
+ SetViewportOrgEx(g_hFrameDC,0,0,NULL);
+ ReleaseDC(g_hFrameWindow,g_hFrameDC);
+ g_hFrameDC = (HDC)0;
+ }
+}
+
+//===========================================================================
+void FrameRefreshStatus (int drawflags, bool bUpdateDiskStatus) {
+ // NB. 99% of the time we draw the disk status. On DiskDriveSwap() we don't.
+ drawflags |= bUpdateDiskStatus ? DRAW_DISK_STATUS : 0;
+ DrawStatusArea((HDC)0,drawflags);
+}
+
+//===========================================================================
+void FrameRegisterClass () {
+ WNDCLASSEX wndclass;
+ ZeroMemory(&wndclass,sizeof(WNDCLASSEX));
+ wndclass.cbSize = sizeof(WNDCLASSEX);
+ wndclass.style = CS_OWNDC | CS_BYTEALIGNCLIENT;
+ wndclass.lpfnWndProc = FrameWndProc;
+ wndclass.hInstance = g_hInstance;
+ wndclass.hIcon = LoadIcon(g_hInstance,TEXT("APPLEWIN_ICON"));
+ wndclass.hCursor = LoadCursor(0,IDC_ARROW);
+ wndclass.hbrBackground = (HBRUSH)GetStockObject(BLACK_BRUSH);
+#if ENABLE_MENU
+ wndclass.lpszMenuName = (LPCSTR)IDR_MENU1;
+#endif
+ wndclass.lpszClassName = TEXT("APPLE2FRAME");
+ wndclass.hIconSm = (HICON)LoadImage(g_hInstance,TEXT("APPLEWIN_ICON"),
+ IMAGE_ICON,16,16,LR_DEFAULTCOLOR);
+ RegisterClassEx(&wndclass);
+}
+
+//===========================================================================
+// TODO: FIXME: Util_TestFileExists()
+static bool FileExists(std::string strFilename)
+{
+ struct stat stFileInfo;
+ int intStat = stat(strFilename.c_str(),&stFileInfo);
+ return (intStat == 0) ? true : false;
+}
+
+//===========================================================================
+
+// Called when:
+// . Mouse f/w sets abs position
+// . UpdateMouseInAppleViewport() is called and inside Apple screen
+void FrameSetCursorPosByMousePos()
+{
+// _ASSERT(GetCardMgr().IsMouseCardInstalled()); // CMouseInterface::ctor calls this function, ie. before GetCardMgr()::m_pMouseCard is setup
+ if (!GetCardMgr().IsMouseCardInstalled())
+ return;
+
+ if (!g_hFrameWindow || g_bShowingCursor)
+ return;
+
+ int iX, iMinX, iMaxX;
+ int iY, iMinY, iMaxY;
+ GetCardMgr().GetMouseCard()->GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
+
+ float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
+ float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
+
+ int iWindowX = (int)(fScaleX * (float)g_nViewportCX);
+ int iWindowY = (int)(fScaleY * (float)g_nViewportCY);
+
+ POINT Point = {viewportx+2, viewporty+2}; // top-left
+ ClientToScreen(g_hFrameWindow, &Point);
+ SetCursorPos(Point.x+iWindowX-VIEWPORTX, Point.y+iWindowY-VIEWPORTY);
+
+#if defined(_DEBUG) && 0 // OutputDebugString() when cursor position changes since last time
+ static int OldX=0, OldY=0;
+ char szDbg[200];
+ int X=Point.x+iWindowX-VIEWPORTX;
+ int Y=Point.y+iWindowY-VIEWPORTY;
+ if (X != OldX || Y != OldY)
+ {
+ sprintf(szDbg, "[FrameSetCursorPosByMousePos] x,y=%d,%d (MaxX,Y=%d,%d)\n", X,Y, iMaxX,iMaxY); OutputDebugString(szDbg);
+ OldX=X; OldY=Y;
+ }
+#endif
+}
+
+// Called when:
+// . UpdateMouseInAppleViewport() is called and mouse leaving/entering Apple screen area
+// . NB. Not called when leaving & mouse clipped to Apple screen area
+static void FrameSetCursorPosByMousePos(int x, int y, int dx, int dy, bool bLeavingAppleScreen)
+{
+ _ASSERT(GetCardMgr().IsMouseCardInstalled());
+ if (!GetCardMgr().IsMouseCardInstalled())
+ return;
+
+// char szDbg[200];
+ if (!g_hFrameWindow || (g_bShowingCursor && bLeavingAppleScreen) || (!g_bShowingCursor && !bLeavingAppleScreen))
+ return;
+
+ int iX, iMinX, iMaxX;
+ int iY, iMinY, iMaxY;
+ GetCardMgr().GetMouseCard()->GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
+
+ if (bLeavingAppleScreen)
+ {
+ // Set mouse x/y pos to edge of mouse's window
+ if (dx < 0) iX = iMinX;
+ if (dx > 0) iX = iMaxX;
+ if (dy < 0) iY = iMinY;
+ if (dy > 0) iY = iMaxY;
+
+ float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
+ float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
+
+ int iWindowX = (int)(fScaleX * (float)g_nViewportCX) + dx;
+ int iWindowY = (int)(fScaleY * (float)g_nViewportCY) + dy;
+
+ POINT Point = {viewportx+2, viewporty+2}; // top-left
+ ClientToScreen(g_hFrameWindow, &Point);
+ SetCursorPos(Point.x+iWindowX-VIEWPORTX, Point.y+iWindowY-VIEWPORTY);
+// sprintf(szDbg, "[MOUSE_LEAVING ] x=%d, y=%d (Scale: x,y=%f,%f; iX,iY=%d,%d)\n", iWindowX, iWindowY, fScaleX, fScaleY, iX, iY); OutputDebugString(szDbg);
+ }
+ else // Mouse entering Apple screen area
+ {
+// sprintf(szDbg, "[MOUSE_ENTERING] x=%d, y=%d\n", x, y); OutputDebugString(szDbg);
+ if (!g_bIsFullScreen) // GH#464
+ {
+ x -= (viewportx+2-VIEWPORTX); if (x < 0) x = 0;
+ y -= (viewporty+2-VIEWPORTY); if (y < 0) y = 0;
+ }
+
+ _ASSERT(x <= g_nViewportCX);
+ _ASSERT(y <= g_nViewportCY);
+ float fScaleX = (float)x / (float)g_nViewportCX;
+ float fScaleY = (float)y / (float)g_nViewportCY;
+
+ int iAppleX = iMinX + (int)(fScaleX * (float)(iMaxX-iMinX));
+ int iAppleY = iMinY + (int)(fScaleY * (float)(iMaxY-iMinY));
+
+ GetCardMgr().GetMouseCard()->SetCursorPos(iAppleX, iAppleY); // Set new entry position
+
+ // Dump initial deltas (otherwise can get big deltas since last read when entering Apple screen area)
+ DIMouse::ReadImmediateData();
+ }
+}
+
+static void DrawCrosshairsMouse()
+{
+ _ASSERT(GetCardMgr().IsMouseCardInstalled());
+ if (!GetCardMgr().IsMouseCardInstalled())
+ return;
+
+ if (!sg_PropertySheet.GetMouseShowCrosshair())
+ return;
+
+ int iX, iMinX, iMaxX;
+ int iY, iMinY, iMaxY;
+ GetCardMgr().GetMouseCard()->GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY);
+ _ASSERT(iMinX == 0 && iMinY == 0);
+
+ float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX));
+ float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY));
+
+ int iWindowX = (int)(fScaleX * (float)g_nViewportCX);
+ int iWindowY = (int)(fScaleY * (float)g_nViewportCY);
+
+ DrawCrosshairs(iWindowX,iWindowY);
+}
+
+#ifdef _DEBUG
+//#define _DEBUG_SHOW_CURSOR // NB. Get an ASSERT on LMB (after Ctrl+LMB)
+#endif
+
+static void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x, int y)
+{
+ const bool bOutsideAppleViewport = iOutOfBoundsX || iOutOfBoundsY;
+
+ if (bOutsideAppleViewport)
+ {
+ if (sg_PropertySheet.GetMouseRestrictToWindow())
+ return;
+
+ g_bLastCursorInAppleViewport = false;
+
+ if (!g_bShowingCursor)
+ {
+ // Mouse leaving Apple screen area
+ FrameSetCursorPosByMousePos(0, 0, iOutOfBoundsX, iOutOfBoundsY, true);
+#ifdef _DEBUG_SHOW_CURSOR
+ g_bShowingCursor = true;
+#else
+ FrameShowCursor(TRUE);
+#endif
+ }
+ }
+ else
+ {
+ g_bLastCursorInAppleViewport = true;
+
+ if (g_bShowingCursor)
+ {
+ // Mouse entering Apple screen area
+ FrameSetCursorPosByMousePos(x, y, 0, 0, false);
+#ifdef _DEBUG_SHOW_CURSOR
+ g_bShowingCursor = false;
+#else
+ FrameShowCursor(FALSE);
+#endif
+
+ //
+
+ if (sg_PropertySheet.GetMouseRestrictToWindow())
+ SetUsingCursor(TRUE);
+ }
+ else
+ {
+ FrameSetCursorPosByMousePos(); // Set cursor to Apple position each time
+ }
+
+ DrawCrosshairsMouse();
+ }
+}
+
+void GetViewportCXCY(int& nViewportCX, int& nViewportCY)
+{
+ nViewportCX = g_nViewportCX;
+ nViewportCY = g_nViewportCY;
+}
+
+// Call all funcs with dependency on g_Apple2Type
+void FrameUpdateApple2Type(void)
+{
+ DeleteGdiObjects();
+ CreateGdiObjects();
+
+ // DRAW_TITLE : calls GetAppleWindowTitle()
+ // DRAW_LEDS : update LEDs (eg. CapsLock varies on Apple2 type)
+ DrawStatusArea( (HDC)0, DRAW_TITLE|DRAW_LEDS );
+
+ // Draw buttons & call DrawStatusArea(DRAW_BACKGROUND | DRAW_LEDS | DRAW_DISK_STATUS)
+ DrawFrameWindow();
+}
+
+bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight /*= 0*/)
+{
+ typedef std::vector< std::pair > VEC_PAIR;
+ VEC_PAIR vecDisplayResolutions;
+
+ for (UINT iModeNum = 0; ; iModeNum++)
+ {
+ DEVMODE devMode;
+ devMode.dmSize = sizeof(DEVMODE);
+ devMode.dmDriverExtra = 0;
+ BOOL bValid = EnumDisplaySettings(NULL, iModeNum, &devMode);
+ if (!bValid)
+ break;
+ if (iModeNum == 0) // 0 is the initial "cache info about display device" operation
+ continue;
+
+ if (devMode.dmBitsPerPel != 32)
+ continue;
+
+ if (userSpecifiedHeight == 0 || userSpecifiedHeight == devMode.dmPelsHeight)
+ {
+ if (vecDisplayResolutions.size() == 0 || vecDisplayResolutions.back() != std::pair(devMode.dmPelsWidth, devMode.dmPelsHeight) ) // Skip duplicate resolutions
+ {
+ vecDisplayResolutions.push_back( std::pair(devMode.dmPelsWidth, devMode.dmPelsHeight) );
+ LogFileOutput("EnumDisplaySettings(%d) - %d x %d\n", iModeNum, devMode.dmPelsWidth, devMode.dmPelsHeight);
+ }
+ }
+ }
+
+ if (userSpecifiedHeight)
+ {
+ if (vecDisplayResolutions.size() == 0)
+ return false;
+
+ // Pick least width (such that it's wide enough to scale)
+ UINT width = (UINT)-1;
+ for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it)
+ {
+ if (width > it->first)
+ {
+ UINT scaleFactor = it->second / GetFrameBufferBorderlessHeight();
+ if (it->first >= (GetFrameBufferBorderlessWidth() * scaleFactor))
+ {
+ width = it->first;
+ }
+ }
+ }
+
+ if (width == (UINT)-1)
+ return false;
+
+ bestWidth = width;
+ bestHeight = userSpecifiedHeight;
+ return true;
+ }
+
+ // Pick max height that's an exact multiple of GetFrameBufferBorderlessHeight()
+ UINT tmpBestWidth = 0;
+ UINT tmpBestHeight = 0;
+ for (VEC_PAIR::iterator it = vecDisplayResolutions.begin(); it!= vecDisplayResolutions.end(); ++it)
+ {
+ if ((it->second % GetFrameBufferBorderlessHeight()) == 0)
+ {
+ if (it->second > tmpBestHeight)
+ {
+ UINT scaleFactor = it->second / GetFrameBufferBorderlessHeight();
+ if (it->first >= (GetFrameBufferBorderlessWidth() * scaleFactor))
+ {
+ tmpBestWidth = it->first;
+ tmpBestHeight = it->second;
+ }
+ }
+ }
+ }
+
+ if (tmpBestWidth == 0)
+ return false;
+
+ bestWidth = tmpBestWidth;
+ bestHeight = tmpBestHeight;
+ return true;
+}
diff --git a/source/Windows/WinFrame.h b/source/Windows/WinFrame.h
new file mode 100644
index 00000000..4c04970f
--- /dev/null
+++ b/source/Windows/WinFrame.h
@@ -0,0 +1,54 @@
+#pragma once
+
+// 1.19.0.0 Hard Disk Status/Indicator Light
+#define HD_LED 1
+
+// Win32
+ extern HWND g_hFrameWindow;
+ extern int g_nViewportCX;
+ extern int g_nViewportCY;
+ extern BOOL g_bConfirmReboot; // saved PageConfig REGSAVE
+ extern BOOL g_bMultiMon;
+
+
+// Emulator
+ extern bool g_bFreshReset;
+ extern std::string PathFilename[2];
+ extern bool g_bScrollLock_FullSpeed;
+
+
+// Prototypes
+ void CtrlReset();
+
+ void FrameCreateWindow(void);
+ HDC FrameGetDC ();
+ void FrameReleaseDC ();
+ void FrameRefreshStatus (int, bool bUpdateDiskStatus = true );
+ void FrameRegisterClass ();
+ void FrameSetCursorPosByMousePos();
+ int GetViewportScale(void);
+ int SetViewportScale(int nNewScale, bool bForce = false);
+ void GetViewportCXCY(int& nViewportCX, int& nViewportCY);
+ void FrameUpdateApple2Type(void);
+ bool GetBestDisplayResolutionForFullScreen(UINT& bestWidth, UINT& bestHeight, UINT userSpecifiedHeight=0);
+
+ bool IsFullScreen(void);
+ bool GetFullScreenShowSubunitStatus(void);
+ void SetFullScreenShowSubunitStatus(bool bShow);
+
+ void FrameDrawDiskLEDS( HDC hdc );
+ void FrameDrawDiskStatus( HDC hdc );
+
+ LRESULT CALLBACK FrameWndProc (
+ HWND window,
+ UINT message,
+ WPARAM wparam,
+ LPARAM lparam );
+
+ int GetFullScreenOffsetX(void);
+ int GetFullScreenOffsetY(void);
+
+ UINT Get3DBorderWidth(void);
+ UINT Get3DBorderHeight(void);
+
+ void SetAltEnterToggleFullScreen(bool mode);
diff --git a/source/Windows/WinVideo.cpp b/source/Windows/WinVideo.cpp
index 6c1d875f..13b01114 100644
--- a/source/Windows/WinVideo.cpp
+++ b/source/Windows/WinVideo.cpp
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Windows/WinVideo.h"
+#include "Windows/WinFrame.h"
#include "AppleWin.h"
#include "Video.h"
#include "CPU.h"