diff --git a/resource/Applewin.rc b/resource/Applewin.rc index 17f204e9..7e8aa5e7 100644 --- a/resource/Applewin.rc +++ b/resource/Applewin.rc @@ -121,6 +121,8 @@ BEGIN "Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,114,166,10 LTEXT "(Shift+Insert during emulation)",IDC_STATIC,89,166,94,8 CONTROL "Mouse interface in slot 4",IDC_MOUSE_IN_SLOT4,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,9,128,106,10 + CONTROL "Show crosshairs in window's frame",IDC_MOUSE_CROSSHAIR, + "Button",BS_AUTOCHECKBOX | WS_TABSTOP,21,142,159,10 END IDD_PROPPAGE_SOUND DIALOGEX 0, 0, 210, 221 @@ -142,22 +144,6 @@ BEGIN CONTROL "Disable soundcards",IDC_SOUNDCARD_DISABLE,"Button",BS_AUTORADIOBUTTON | BS_NOTIFY,10,194,78,10 END -IDD_PROPPAGE_SAVESTATE DIALOG 0, 0, 210, 221 -STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU -CAPTION "Save State" -FONT 8, "MS Sans Serif" -BEGIN - LTEXT "Save State file name:",IDC_STATIC,5,29,74,8 - GROUPBOX "Save State Control",IDC_STATIC,5,74,200,73 - CONTROL "Save State on exit",IDC_SAVESTATE_ON_EXIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,85,74,10 - PUSHBUTTON "Save State",IDC_SAVESTATE,16,102,85,15 - PUSHBUTTON "Load State",IDC_LOADSTATE,16,124,85,15 - EDITTEXT IDC_SAVESTATE_FILENAME,5,40,143,12,ES_AUTOHSCROLL - LTEXT "(F11 during emulation)",IDC_STATIC,110,105,74,8 - LTEXT "(F12 during emulation)",IDC_STATIC,110,127,90,8 - PUSHBUTTON "Browse...",IDC_SAVESTATE_BROWSE,154,39,50,14 -END - IDD_PROPPAGE_DISK DIALOGEX 0, 0, 210, 221 STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU CAPTION "Disk" @@ -198,10 +184,19 @@ STYLE DS_SETFONT | WS_CHILD | WS_VISIBLE | WS_DISABLED | WS_CAPTION | WS_SYSMENU CAPTION "Advanced" FONT 8, "MS Sans Serif", 0, 0, 0x0 BEGIN - LTEXT "&Clone:",-1,5,29,40,8 - COMBOBOX IDC_CLONETYPE,45,27,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP + LTEXT "&Clone:",IDC_STATIC,5,165,40,8 + COMBOBOX IDC_CLONETYPE,45,163,100,100,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP CONTROL "The Freeze's non-autostart F8 rom (Apple ][ or ][+ only)",IDC_THE_FREEZES_F8_ROM_FW, "Button",BS_AUTOCHECKBOX | WS_TABSTOP,15,206,182,10 + LTEXT "Save State file name:",IDC_STATIC,5,12,74,8 + GROUPBOX "Save State Control",IDC_STATIC,5,57,200,73 + CONTROL "Save State on exit",IDC_SAVESTATE_ON_EXIT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,68,74,10 + PUSHBUTTON "Save State",IDC_SAVESTATE,16,85,85,15 + PUSHBUTTON "Load State",IDC_LOADSTATE,16,107,85,15 + EDITTEXT IDC_SAVESTATE_FILENAME,5,23,143,12,ES_AUTOHSCROLL + LTEXT "(F11 during emulation)",IDC_STATIC,110,88,74,8 + LTEXT "(F12 during emulation)",IDC_STATIC,110,110,90,8 + PUSHBUTTON "Browse...",IDC_SAVESTATE_BROWSE,154,22,50,14 END diff --git a/resource/resource.h b/resource/resource.h index a078bb5c..f0907721 100644 --- a/resource/resource.h +++ b/resource/resource.h @@ -16,7 +16,6 @@ #define IDC_SLIDER_CPU_SPEED 111 #define IDD_PROPPAGE_SOUND 112 #define IDC_DISKTYPE 113 -#define IDD_PROPPAGE_SAVESTATE 114 #define IDC_JOYSTICK1 115 #define IDD_PROPPAGE_DISK 116 #define IDC_BENCHMARK 117 @@ -78,6 +77,7 @@ #define IDC_SCROLLLOCK_TOGGLE 1043 #define IDC_MOUSE_IN_SLOT4 1044 #define IDC_THE_FREEZES_F8_ROM_FW 1045 +#define IDC_MOUSE_CROSSHAIR 1045 #define IDC_CLONETYPE 1046 #define IDM_EXIT 40001 #define IDM_HELP 40002 diff --git a/source/Applewin.cpp b/source/Applewin.cpp index 160adc3c..04b9174c 100644 --- a/source/Applewin.cpp +++ b/source/Applewin.cpp @@ -438,6 +438,8 @@ void LoadConfiguration () if(LOAD(TEXT(REGVALUE_MOUSE_IN_SLOT4), &dwTmp)) g_uMouseInSlot4 = dwTmp; + if(LOAD(TEXT(REGVALUE_MOUSE_CROSSHAIR), &dwTmp)) + g_uMouseShowCrosshair = dwTmp; g_Slot4 = g_uMouseInSlot4 ? CT_MouseInterface : CT_Mockingboard; // @@ -675,7 +677,7 @@ int APIENTRY WinMain (HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int) //----- // Initialize COM - so we can use CoCreateInstance - // . NB. DSInit() & DirectInputInit are done when g_hFrameWindow is created (WM_CREATE) + // . NB. DSInit() & DIMouse::DirectInputInit are done when g_hFrameWindow is created (WM_CREATE) CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); bool bSysClkOK = SysClk_InitTimer(); diff --git a/source/Common.h b/source/Common.h index 904d1e50..e3965453 100644 --- a/source/Common.h +++ b/source/Common.h @@ -82,6 +82,7 @@ enum AppMode_e #define REGVALUE_PDL_YTRIM "PDL Y-Trim" #define REGVALUE_SCROLLLOCK_TOGGLE "ScrollLock Toggle" #define REGVALUE_MOUSE_IN_SLOT4 "Mouse in slot 4" +#define REGVALUE_MOUSE_CROSSHAIR "Mouse crosshair" #define REGVALUE_THE_FREEZES_F8_ROM "The Freeze's F8 Rom" #define REGVALUE_CLONETYPE "Clone Type" diff --git a/source/Frame.cpp b/source/Frame.cpp index d150a15e..e860cb6e 100644 --- a/source/Frame.cpp +++ b/source/Frame.cpp @@ -33,23 +33,27 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define ENABLE_MENU 0 +// Magic numbers (used by FrameCreateWindow to calc width/height): +#define MAGICX 5 // 3D border between Apple window & Emulator's RHS buttons +#define MAGICY 5 // 3D border between Apple window & Title bar + #define VIEWPORTCX 560 #if ENABLE_MENU #define VIEWPORTCY 400 #else #define VIEWPORTCY 384 #endif -#define BUTTONX (VIEWPORTCX+(VIEWPORTX<<1)) +#define BUTTONX (VIEWPORTCX + VIEWPORTX*2) #define BUTTONY 0 #define BUTTONCX 45 #define BUTTONCY 45 -#define FSVIEWPORTX (640-BUTTONCX-5-VIEWPORTCX) -#define FSVIEWPORTY ((480-VIEWPORTCY)>>1) +// NB. FSxxx = FullScreen xxx +#define FSVIEWPORTX (640-BUTTONCX-MAGICX-VIEWPORTCX) +#define FSVIEWPORTY ((480-VIEWPORTCY)/2) #define FSBUTTONX (640-BUTTONCX) -#define FSBUTTONY (((480-VIEWPORTCY)>>1)-1) +#define FSBUTTONY (((480-VIEWPORTCY)/2)-1) #define BUTTONS 8 - static HBITMAP capsbitmap[2]; static HBITMAP diskbitmap[ NUM_DISK_STATUS ]; @@ -75,16 +79,15 @@ static BOOL painting = 0; static HFONT smallfont = (HFONT)0; static HWND tooltipwindow = (HWND)0; static BOOL usingcursor = 0; -static int viewportx = VIEWPORTX; -static int viewporty = VIEWPORTY; +static int viewportx = VIEWPORTX; // Default to Normal (non-FullScreen) mode +static int viewporty = VIEWPORTY; // Default to Normal (non-FullScreen) mode static LPDIRECTDRAW directdraw = (LPDIRECTDRAW)0; static LPDIRECTDRAWSURFACE surface = (LPDIRECTDRAWSURFACE)0; -static UINT g_uPrevMouseX = 0; -static UINT g_uPrevMouseY = 0; static bool g_bShowingCursor = true; static bool g_bOldShowingCursor = true; // Used during MODE_PAUSE +static bool g_bLastCursorInAppleViewport = false; void DrawStatusArea (HDC passdc, BOOL drawflags); void ProcessButtonClick (int button); @@ -97,6 +100,11 @@ void SetUsingCursor (BOOL); bool g_bScrollLock_FullSpeed = false; +// Prototypes: +static void FrameSetCursorPosByMousePos(int x, int y, int dx, int dy, bool bLeavingAppleScreen); +static void DrawCrosshairsMouse(); +static void UpdateMouseInAppleViewport(int iOutOfBoundsX, int iOutOfBoundsY, int x=0, int y=0); + //=========================================================================== void CreateGdiObjects () { ZeroMemory(buttonbitmap,BUTTONS*sizeof(HBITMAP)); @@ -403,7 +411,7 @@ void DrawStatusArea (HDC passdc, int drawflags) if (drawflags & DRAW_TITLE) { - TCHAR title[40]; + TCHAR title[80]; switch (g_Apple2Type) { case A2TYPE_APPLE2: _tcscpy(title, TITLE_APPLE_2); break; @@ -412,6 +420,11 @@ void DrawStatusArea (HDC passdc, int drawflags) case A2TYPE_APPLE2EEHANCED: _tcscpy(title, TITLE_APPLE_2E_ENHANCED); break; } + if (g_hCustomRomF8 != INVALID_HANDLE_VALUE) + _tcscat(title,TEXT(" (custom rom)")); + else if (g_uTheFreezesF8Rom && IS_APPLE2) + _tcscat(title,TEXT(" (The Freeze's non-autostart F8 rom)")); + switch (g_nAppMode) { case MODE_PAUSED : _tcscat(title,TEXT(" [")); _tcscat(title,TITLE_PAUSED ); _tcscat(title,TEXT("]")); break; @@ -491,6 +504,7 @@ LRESULT CALLBACK FrameWndProc ( g_hFrameWindow = window; CreateGdiObjects(); DSInit(); + DIMouse::DirectInputInit(window); MB_Initialize(); SpkrInitialize(); DragAcceptFiles(window,1); @@ -538,6 +552,7 @@ LRESULT CALLBACK FrameWndProc ( VideoDestroy(); MB_Destroy(); DeleteGdiObjects(); + DIMouse::DirectInputUninit(window); PostQuitMessage(0); // Post WM_QUIT message to the thread's message queue break; @@ -586,9 +601,20 @@ LRESULT CALLBACK FrameWndProc ( } else if (wparam == VK_F9) { - videotype++; // Cycle through available video modes - if (videotype >= VT_NUM_MODES) - videotype = 0; + // Cycle through available video modes + if (GetKeyState(VK_SHIFT) >= 0) // Backwards + { + if (videotype == 0) + videotype = VT_NUM_MODES; + videotype--; + } + else // Forwards + { + videotype++; + if (videotype >= VT_NUM_MODES) + videotype = 0; + } + VideoReinitialize(); if ((g_nAppMode != MODE_LOGO) || ((g_nAppMode == MODE_DEBUG) && (g_bDebuggerViewingAppleOutput))) // +PATCH { @@ -628,17 +654,20 @@ LRESULT CALLBACK FrameWndProc ( g_nAppMode = MODE_PAUSED; SoundCore_SetFade(FADE_OUT); g_bOldShowingCursor = g_bShowingCursor; - if (sg_Mouse.Active() && !g_bShowingCursor) + if (sg_Mouse.IsActiveAndEnabled() && !g_bShowingCursor) { int nCount = ShowCursor(1); _ASSERT(nCount >= 0); g_bShowingCursor = true; + + if (g_uMouseShowCrosshair) // Erase crosshairs if they are being drawn + DrawCrosshairs(0,0); } break; case MODE_PAUSED: g_nAppMode = MODE_RUNNING; SoundCore_SetFade(FADE_IN); - if (sg_Mouse.Active() && !g_bOldShowingCursor) + if (sg_Mouse.IsActiveAndEnabled() && !g_bOldShowingCursor) { int nCount = ShowCursor(0); _ASSERT(nCount < 0); @@ -723,9 +752,35 @@ LRESULT CALLBACK FrameWndProc ( { SetUsingCursor(1); } - else if (sg_Mouse.Active()) + else if (sg_Mouse.IsActive()) { - sg_Mouse.SetButton(BUTTON0, BUTTON_DOWN); + if (wparam & (MK_CONTROL | MK_SHIFT)) + { + sg_Mouse.SetEnabled(false); + + int nCount = ShowCursor(1); + _ASSERT(nCount >= 0); + g_bShowingCursor = true; + + if (g_uMouseShowCrosshair) // Erase crosshairs if they are being drawn + DrawCrosshairs(0,0); + } + else + { + if (!sg_Mouse.IsEnabled()) + { + sg_Mouse.SetEnabled(true); + + int nCount = ShowCursor(0); + _ASSERT(nCount < 0); + g_bShowingCursor = false; + // Don't call SetButton() when enabling + } + else + { + sg_Mouse.SetButton(BUTTON0, BUTTON_DOWN); + } + } } DebuggerMouseClick( x, y ); } @@ -749,7 +804,7 @@ LRESULT CALLBACK FrameWndProc ( { JoySetButton(BUTTON0, BUTTON_UP); } - else if (sg_Mouse.Active()) + else if (sg_Mouse.IsActive()) { sg_Mouse.SetButton(BUTTON0, BUTTON_UP); } @@ -783,37 +838,50 @@ LRESULT CALLBACK FrameWndProc ( DrawCrosshairs(x,y); JoySetPosition(x-viewportx-2, VIEWPORTCX-4, y-viewporty-2, VIEWPORTCY-4); } - else if (sg_Mouse.Active() && (g_nAppMode == MODE_RUNNING)) + else if (sg_Mouse.IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING)) { - if ((x >= viewportx+2) && - (x < buttonx) && - (y >= viewporty+2) && - (y <= viewporty+VIEWPORTCY-1)) - { - if (g_bShowingCursor) - { - int nCount = ShowCursor(0); - _ASSERT(nCount < 0); - g_bShowingCursor = false; - } - sg_Mouse.SetPositionRel(x-g_uPrevMouseX, y-g_uPrevMouseY); - } - else - { - if (!g_bShowingCursor) - { - int nCount = ShowCursor(1); - _ASSERT(nCount >= 0); - g_bShowingCursor = true; - } - } + if (g_bLastCursorInAppleViewport) + break; + + const int iAppleScreenMaxX = VIEWPORTCX-1; + const int iAppleScreenMaxY = VIEWPORTCY-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); } + RelayEvent(WM_MOUSEMOVE,wparam,lparam); - g_uPrevMouseX = x; - g_uPrevMouseY = y; break; } + case WM_TIMER: + if (wparam == IDEVENT_TIMER_MOUSE) + { + if (sg_Mouse.IsActiveAndEnabled() && (g_nAppMode == MODE_RUNNING)) + { + if (g_bLastCursorInAppleViewport == false) + break; + + int iOutOfBoundsX=0, iOutOfBoundsY=0; + + long dX,dY; + if (DIMouse::ReadImmediateData(&dX, &dY) == S_OK) + sg_Mouse.SetPositionRel(dX, dY, &iOutOfBoundsX, &iOutOfBoundsY); + + UpdateMouseInAppleViewport(iOutOfBoundsX, iOutOfBoundsY); + } + } + break; + // VSCROLL // SB_LINEUP // Line Scrolling // SB_PAGEUP // Page Scrolling @@ -833,7 +901,6 @@ LRESULT CALLBACK FrameWndProc ( } break; - case WM_NOTIFY: if(((LPNMTTDISPINFO)lparam)->hdr.hwndFrom == tooltipwindow && ((LPNMTTDISPINFO)lparam)->hdr.code == TTN_GETDISPINFO) @@ -907,7 +974,7 @@ LRESULT CALLBACK FrameWndProc ( } if (usingcursor) { - if (sg_Mouse.Active()) + if (sg_Mouse.IsActive()) sg_Mouse.SetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP); else JoySetButton(BUTTON1, (message == WM_RBUTTONDOWN) ? BUTTON_DOWN : BUTTON_UP); @@ -966,6 +1033,7 @@ LRESULT CALLBACK FrameWndProc ( case WM_USER_RESTART: // . Changed Apple computer type (][+ or //e) // . Changed disk speed (normal or enhanced) + // . Changed Freeze F8 rom setting if (g_nAppMode != MODE_LOGO) if (MessageBox(g_hFrameWindow, TEXT("Restarting the emulator will reset the state ") @@ -1218,10 +1286,10 @@ void SetUsingCursor (BOOL newvalue) { usingcursor = newvalue; if (usingcursor) { SetCapture(g_hFrameWindow); - RECT rect = {viewportx+2, - viewporty+2, - viewportx+VIEWPORTCX-1, - viewporty+VIEWPORTCY-1}; + RECT rect = {viewportx+2, // left + viewporty+2, // top + viewportx+VIEWPORTCX-1, // right + viewporty+VIEWPORTCY-1}; // bottom ClientToScreen(g_hFrameWindow,(LPPOINT)&rect.left); ClientToScreen(g_hFrameWindow,(LPPOINT)&rect.right); ClipCursor(&rect); @@ -1246,14 +1314,14 @@ void SetUsingCursor (BOOL newvalue) { //=========================================================================== void FrameCreateWindow () { - int width = VIEWPORTCX + (VIEWPORTX<<1) + int width = VIEWPORTCX + VIEWPORTX*2 + BUTTONCX - + (GetSystemMetrics(SM_CXBORDER)<<1) - + 5; - int height = VIEWPORTCY + (VIEWPORTY<<1) + + GetSystemMetrics(SM_CXBORDER)*2 + + MAGICX; + int height = VIEWPORTCY + VIEWPORTY*2 + GetSystemMetrics(SM_CYBORDER) + GetSystemMetrics(SM_CYCAPTION) - + 5; + + MAGICY; int xpos; if (!RegLoadValue(TEXT("Preferences"),TEXT("Window X-Position"),1,(DWORD *)&xpos)) @@ -1393,3 +1461,159 @@ void FrameReleaseVideoDC () { surface->Unlock(NULL); } } + +//=========================================================================== + +// Called when: +// . Mouse f/w sets abs position +// . UpdateMouseInAppleViewport() is called and inside Apple screen +void FrameSetCursorPosByMousePos() +{ + if (!g_hFrameWindow || g_bShowingCursor) + return; + + int iX, iMinX, iMaxX; + int iY, iMinY, iMaxY; + sg_Mouse.GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY); + + _ASSERT(iMinX == 0 && iMinY == 0); + float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX)); + float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY)); + + int iWindowX = (int)(fScaleX * (float)VIEWPORTCX); + int iWindowY = (int)(fScaleY * (float)VIEWPORTCY); + + POINT Point = {viewportx+2, viewporty+2}; // top-left + ClientToScreen(g_hFrameWindow, &Point); + SetCursorPos(Point.x+iWindowX-MAGICX, Point.y+iWindowY-MAGICY); + +#if defined(_DEBUG) && 0 + static int OldX=0, OldY=0; + char szDbg[200]; + int X=Point.x+iWindowX-MAGICX; + int Y=Point.y+iWindowY-MAGICY; + 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 +} + +static void FrameSetCursorPosByMousePos(int x, int y, int dx, int dy, bool bLeavingAppleScreen) +{ +// char szDbg[200]; + if (!g_hFrameWindow || (g_bShowingCursor && bLeavingAppleScreen) || (!g_bShowingCursor && !bLeavingAppleScreen)) + return; + + int iX, iMinX, iMaxX; + int iY, iMinY, iMaxY; + sg_Mouse.GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY); + _ASSERT(iMinX == 0 && iMinY == 0); + + 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)VIEWPORTCX) + dx; + int iWindowY = (int)(fScaleY * (float)VIEWPORTCY) + dy; + + POINT Point = {viewportx+2, viewporty+2}; // top-left + ClientToScreen(g_hFrameWindow, &Point); + SetCursorPos(Point.x+iWindowX-MAGICX, Point.y+iWindowY-MAGICY); +// 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); + x -= (viewportx+2-MAGICX); + y -= (viewporty+2-MAGICY); + + _ASSERT(x <= VIEWPORTCX); + _ASSERT(y <= VIEWPORTCY); + float fScaleX = (float)x / (float)VIEWPORTCX; + float fScaleY = (float)y / (float)VIEWPORTCY; + + int iAppleX = iMinX + (int)(fScaleX * (float)(iMaxX-iMinX)); + int iAppleY = iMinY + (int)(fScaleY * (float)(iMaxY-iMinY)); + + sg_Mouse.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() +{ + if (!g_uMouseShowCrosshair) + return; + + int iX, iMinX, iMaxX; + int iY, iMinY, iMaxY; + sg_Mouse.GetXY(iX, iMinX, iMaxX, iY, iMinY, iMaxY); + _ASSERT(iMinX == 0 && iMinY == 0); + + float fScaleX = (float)(iX-iMinX) / ((float)(iMaxX-iMinX)); + float fScaleY = (float)(iY-iMinY) / ((float)(iMaxY-iMinY)); + + int iWindowX = (int)(fScaleX * (float)VIEWPORTCX); + int iWindowY = (int)(fScaleY * (float)VIEWPORTCY); + + 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) + { + g_bLastCursorInAppleViewport = false; + + if (!g_bShowingCursor) + { + // Mouse leaving Apple screen area + FrameSetCursorPosByMousePos(0, 0, iOutOfBoundsX, iOutOfBoundsY, true); +#ifdef _DEBUG_SHOW_CURSOR +#else + int nCount = ShowCursor(1); + _ASSERT(nCount >= 0); +#endif + g_bShowingCursor = true; + } + } + else + { + g_bLastCursorInAppleViewport = true; + + if (g_bShowingCursor) + { + // Mouse entering Apple screen area + FrameSetCursorPosByMousePos(x, y, 0, 0, false); +#ifdef _DEBUG_SHOW_CURSOR +#else + int nCount = ShowCursor(0); + _ASSERT(nCount < 0); +#endif + g_bShowingCursor = false; + } + else + { + FrameSetCursorPosByMousePos(); // Set cursor to Apple position each time + } + + DrawCrosshairsMouse(); + } +} diff --git a/source/Frame.h b/source/Frame.h index a4082b04..e5724fef 100644 --- a/source/Frame.h +++ b/source/Frame.h @@ -19,6 +19,7 @@ void FrameRefreshStatus (int); void FrameRegisterClass (); void FrameReleaseDC (); void FrameReleaseVideoDC (); +void FrameSetCursorPosByMousePos(); LRESULT CALLBACK FrameWndProc ( HWND window, diff --git a/source/Joystick.cpp b/source/Joystick.cpp index 0647e36b..4bcb08be 100644 --- a/source/Joystick.cpp +++ b/source/Joystick.cpp @@ -53,10 +53,11 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA #define MODE_CENTERING 2 #define MODE_SMOOTH 3 -typedef struct _joyinforec { +typedef struct +{ int device; int mode; -} joyinforec, *joyinfoptr; +} joyinforec; static const joyinforec joyinfo[5] = {{DEVICE_NONE,MODE_NONE}, {DEVICE_JOYSTICK,MODE_STANDARD}, @@ -111,7 +112,7 @@ static short g_nPdlTrimX = 0; static short g_nPdlTrimY = 0; //=========================================================================== -void CheckJoystick0 () +void CheckJoystick0() { static DWORD lastcheck = 0; DWORD currtime = GetTickCount(); @@ -141,7 +142,7 @@ void CheckJoystick0 () } } -void CheckJoystick1 () +void CheckJoystick1() { static DWORD lastcheck = 0; DWORD currtime = GetTickCount(); @@ -177,7 +178,7 @@ void CheckJoystick1 () // //=========================================================================== -void JoyInitialize () +void JoyInitialize() { // Emulated joystick #0 can only use JOYSTICKID1 (if no joystick, then use mouse) // Emulated joystick #1 can only use JOYSTICKID2 (if no joystick, then disable) @@ -249,7 +250,7 @@ void JoyInitialize () //=========================================================================== -BOOL JoyProcessKey (int virtkey, BOOL extended, BOOL down, BOOL autorep) +BOOL JoyProcessKey(int virtkey, BOOL extended, BOOL down, BOOL autorep) { if( (joyinfo[joytype[0]].device != DEVICE_KEYBOARD) && (joyinfo[joytype[1]].device != DEVICE_KEYBOARD) && @@ -366,7 +367,7 @@ BOOL JoyProcessKey (int virtkey, BOOL extended, BOOL down, BOOL autorep) //=========================================================================== -BYTE __stdcall JoyReadButton (WORD, WORD address, BYTE, BYTE, ULONG nCyclesLeft) +BYTE __stdcall JoyReadButton(WORD, WORD address, BYTE, BYTE, ULONG nCyclesLeft) { address &= 0xFF; @@ -420,7 +421,7 @@ BYTE __stdcall JoyReadButton (WORD, WORD address, BYTE, BYTE, ULONG nCyclesLeft) static const double PDL_CNTR_INTERVAL = 2816.0 / 255.0; // 11.04 (From KEGS) -BYTE __stdcall JoyReadPosition (WORD programcounter, WORD address, BYTE, BYTE, ULONG nCyclesLeft) +BYTE __stdcall JoyReadPosition(WORD programcounter, WORD address, BYTE, BYTE, ULONG nCyclesLeft) { int nJoyNum = (address & 2) ? 1 : 0; // $C064..$C067 @@ -438,7 +439,7 @@ BYTE __stdcall JoyReadPosition (WORD programcounter, WORD address, BYTE, BYTE, U } //=========================================================================== -void JoyReset () +void JoyReset() { int loop = 0; while (loop < JK_MAX) @@ -446,7 +447,7 @@ void JoyReset () } //=========================================================================== -BYTE __stdcall JoyResetPosition (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft) +BYTE __stdcall JoyResetPosition(WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft) { CpuCalcCycles(nCyclesLeft); g_nJoyCntrResetCycle = g_nCumulativeCycles; @@ -462,7 +463,7 @@ BYTE __stdcall JoyResetPosition (WORD, WORD, BYTE, BYTE, ULONG nCyclesLeft) //=========================================================================== // Called when mouse is being used as a joystick && mouse button changes -void JoySetButton (eBUTTON number, eBUTTONSTATE down) +void JoySetButton(eBUTTON number, eBUTTONSTATE down) { if (number > 1) // Sanity check on mouse button # return; @@ -484,7 +485,7 @@ void JoySetButton (eBUTTON number, eBUTTONSTATE down) } //=========================================================================== -BOOL JoySetEmulationType (HWND window, DWORD newtype, int nJoystickNumber) +BOOL JoySetEmulationType(HWND window, DWORD newtype, int nJoystickNumber) { if(joytype[nJoystickNumber] == newtype) return 1; // Already set to this type. Return OK. @@ -508,7 +509,7 @@ BOOL JoySetEmulationType (HWND window, DWORD newtype, int nJoystickNumber) else if ((joyinfo[newtype].device == DEVICE_MOUSE) && (joyinfo[joytype[nJoystickNumber]].device != DEVICE_MOUSE)) { - if (sg_Mouse.Active()) + if (sg_Mouse.IsActive()) { MessageBox(window, TEXT("Mouse interface card is enabled - unable to use mouse for joystick emulation."), @@ -539,7 +540,7 @@ BOOL JoySetEmulationType (HWND window, DWORD newtype, int nJoystickNumber) //=========================================================================== // Called when mouse is being used as a joystick && mouse position changes -void JoySetPosition (int xvalue, int xrange, int yvalue, int yrange) +void JoySetPosition(int xvalue, int xrange, int yvalue, int yrange) { int nJoyNum = (joyinfo[joytype[0]].device == DEVICE_MOUSE) ? 0 : 1; xpos[nJoyNum] = (xvalue*255)/xrange; @@ -547,7 +548,7 @@ void JoySetPosition (int xvalue, int xrange, int yvalue, int yrange) } //=========================================================================== -void JoyUpdatePosition () +void JoyUpdatePosition() { if (buttonlatch[0]) --buttonlatch[0]; if (buttonlatch[1]) --buttonlatch[1]; @@ -555,13 +556,24 @@ void JoyUpdatePosition () } //=========================================================================== -BOOL JoyUsingMouse () +BOOL JoyUsingMouse() { return (joyinfo[joytype[0]].device == DEVICE_MOUSE) || (joyinfo[joytype[1]].device == DEVICE_MOUSE); } //=========================================================================== +void JoyDisableUsingMouse() +{ + if (joyinfo[joytype[0]].device == DEVICE_MOUSE) + joytype[0] = DEVICE_NONE; + + if (joyinfo[joytype[1]].device == DEVICE_MOUSE) + joytype[1] = DEVICE_NONE; +} + +//=========================================================================== + void JoySetTrim(short nValue, bool bAxisX) { if(bAxisX) diff --git a/source/Joystick.h b/source/Joystick.h index 3127d07c..5fd62445 100644 --- a/source/Joystick.h +++ b/source/Joystick.h @@ -4,19 +4,20 @@ enum JOYNUM {JN_JOYSTICK0=0, JN_JOYSTICK1}; extern DWORD joytype[2]; -void JoyInitialize (); -BOOL JoyProcessKey (int,BOOL,BOOL,BOOL); -void JoyReset (); -void JoySetButton (eBUTTON,eBUTTONSTATE); -BOOL JoySetEmulationType (HWND,DWORD,int); -void JoySetPosition (int,int,int,int); -void JoyUpdatePosition (); -BOOL JoyUsingMouse (); +void JoyInitialize(); +BOOL JoyProcessKey(int,BOOL,BOOL,BOOL); +void JoyReset(); +void JoySetButton(eBUTTON,eBUTTONSTATE); +BOOL JoySetEmulationType(HWND,DWORD,int); +void JoySetPosition(int,int,int,int); +void JoyUpdatePosition(); +BOOL JoyUsingMouse(); +void JoyDisableUsingMouse(); void JoySetTrim(short nValue, bool bAxisX); short JoyGetTrim(bool bAxisX); DWORD JoyGetSnapshot(SS_IO_Joystick* pSS); DWORD JoySetSnapshot(SS_IO_Joystick* pSS); -BYTE __stdcall JoyReadButton (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft); -BYTE __stdcall JoyReadPosition (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft); -BYTE __stdcall JoyResetPosition (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft); +BYTE __stdcall JoyReadButton(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft); +BYTE __stdcall JoyReadPosition(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft); +BYTE __stdcall JoyResetPosition(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nCyclesLeft); diff --git a/source/Memory.cpp b/source/Memory.cpp index 71612622..41020bd6 100644 --- a/source/Memory.cpp +++ b/source/Memory.cpp @@ -1013,7 +1013,7 @@ void MemInitialize() } } - if (g_uTheFreezesF8Rom) + if (g_uTheFreezesF8Rom && IS_APPLE2) { hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_FREEZES_F8_ROM), "ROM"); diff --git a/source/MouseInterface.cpp b/source/MouseInterface.cpp index 164b3968..c92db667 100644 --- a/source/MouseInterface.cpp +++ b/source/MouseInterface.cpp @@ -5,6 +5,7 @@ #pragma hdrstop #include "..\resource\resource.h" #include "MouseInterface.h" +#include "Frame.h" // FrameSetCursorPosByMousePos() // Sets mouse mode #define MOUSE_SET 0x00 @@ -104,6 +105,7 @@ void CMouseInterface::Initialize(LPBYTE pCxRomPeripheral, UINT uSlot) // m_bActive = true; + SetEnabled(true); SetSlotRom(); // Pre: m_bActive == true RegisterIoHandler(uSlot, &CMouseInterface::IORead, &CMouseInterface::IOWrite, NULL, NULL, this, NULL); } @@ -319,6 +321,9 @@ void CMouseInterface::OnWrite() switch( m_byBuff[0] & 0xF0 ) { case MOUSE_CLAMP: + // Blazing Paddles: + // . MOUSE_CLAMP(Y, 0xFFEC, 0x00D3) + // . MOUSE_CLAMP(X, 0xFFEC, 0x012B) nMin = ( m_byBuff[3] << 8 ) | m_byBuff[1]; nMax = ( m_byBuff[4] << 8 ) | m_byBuff[2]; if ( m_byBuff[0] & 1 ) // Clamp Y @@ -394,26 +399,52 @@ void CMouseInterface::Clear() //=========================================================================== -void CMouseInterface::ClampX() +int CMouseInterface::ClampX() { if ( m_iX > m_iMaxX ) + { m_iX = m_iMaxX; + return 1; + } else if ( m_iX < m_iMinX ) + { m_iX = m_iMinX; + return -1; + } + + return 0; } -void CMouseInterface::ClampY() +int CMouseInterface::ClampY() { if ( m_iY > m_iMaxY ) + { m_iY = m_iMaxY; + return 1; + } else if ( m_iY < m_iMinY ) + { m_iY = m_iMinY; + return -1; + } + + return 0; } void CMouseInterface::SetClampX(int iMinX, int iMaxX) { - if ( iMinX < 0 || iMinX > iMaxX ) + if ( (UINT)iMinX > 0xFFFF || (UINT)iMaxX > 0xFFFF ) + { + _ASSERT(0); return; + } + if ( iMinX > iMaxX ) + { + // For Blazing Paddles + int iNewMaxX = (iMinX + iMaxX) & 0xFFFF; + iMinX = 0; + iMaxX = iNewMaxX; + } m_iMaxX = iMaxX; m_iMinX = iMinX; ClampX(); @@ -421,8 +452,18 @@ void CMouseInterface::SetClampX(int iMinX, int iMaxX) void CMouseInterface::SetClampY(int iMinY, int iMaxY) { - if ( iMinY < 0 || iMinY > iMaxY ) + if ( (UINT)iMinY > 0xFFFF || (UINT)iMaxY > 0xFFFF ) + { + _ASSERT(0); return; + } + if ( iMinY > iMaxY ) + { + // For Blazing Paddles + int iNewMaxY = (iMinY + iMaxY) & 0xFFFF; + iMinY = 0; + iMaxY = iNewMaxY; + } m_iMaxY = iMaxY; m_iMinY = iMinY; ClampY(); @@ -430,17 +471,21 @@ void CMouseInterface::SetClampY(int iMinY, int iMaxY) void CMouseInterface::SetPositionAbs(int x, int y) { +#if defined(_DEBUG) && 0 + char szDbg[200]; sprintf(szDbg, "[SetPositionAbs] x=%d, y=%d (m_iX=%d, m_iY=%d)\n", x,y, m_iX,m_iY); OutputDebugString(szDbg); +#endif m_iX = x; m_iY = y; + FrameSetCursorPosByMousePos(); } -void CMouseInterface::SetPositionRel(int dx, int dy) +void CMouseInterface::SetPositionRel(long dX, long dY, int* pOutOfBoundsX, int* pOutOfBoundsY) { - m_iX += dx; - ClampX(); + m_iX += dX; + *pOutOfBoundsX = ClampX(); - m_iY += dy; - ClampY(); + m_iY += dY; + *pOutOfBoundsY = ClampY(); OnMouseEvent(); } @@ -450,3 +495,189 @@ void CMouseInterface::SetButton(eBUTTON Button, eBUTTONSTATE State) m_bButtons[Button]= (State == BUTTON_DOWN) ? TRUE : FALSE; OnMouseEvent(); } + +//============================================================================= +// DirectInput interface +//============================================================================= + +//#define STRICT +#define DIRECTINPUT_VERSION 0x0800 + +#include + +namespace DIMouse +{ + + static LPDIRECTINPUT8 g_pDI = NULL; + static LPDIRECTINPUTDEVICE8 g_pMouse = NULL; + #define SAMPLE_BUFFER_SIZE 16 // arbitrary number of buffer elements + + static UINT_PTR g_TimerIDEvent = 0; + + //----------------------------------------------------------------------------- + // Name: OnCreateDevice() + // Desc: Sets up the mouse device using the flags from the dialog. + //----------------------------------------------------------------------------- + HRESULT DirectInputInit( HWND hDlg ) + { + HRESULT hr; + BOOL bExclusive; + BOOL bForeground; + BOOL bImmediate; + DWORD dwCoopFlags; + + DirectInputUninit(hDlg); + + // Determine where the buffer would like to be allocated + bExclusive = FALSE; + bForeground = FALSE; // Otherwise get DIERR_OTHERAPPHASPRIO (== E_ACCESSDENIED) on Acquire() + bImmediate = TRUE; + + if( bExclusive ) + dwCoopFlags = DISCL_EXCLUSIVE; + else + dwCoopFlags = DISCL_NONEXCLUSIVE; + + if( bForeground ) + dwCoopFlags |= DISCL_FOREGROUND; + else + dwCoopFlags |= DISCL_BACKGROUND; + + // Create a DInput object + if( FAILED( hr = DirectInput8Create( GetModuleHandle(NULL), DIRECTINPUT_VERSION, + IID_IDirectInput8, (VOID**)&g_pDI, NULL ) ) ) + return hr; + + // Obtain an interface to the system mouse device. + if( FAILED( hr = g_pDI->CreateDevice( GUID_SysMouse, &g_pMouse, NULL ) ) ) + return hr; + + // Set the data format to "mouse format" - a predefined data format + // + // A data format specifies which controls on a device we + // are interested in, and how they should be reported. + // + // This tells DirectInput that we will be passing a + // DIMOUSESTATE2 structure to IDirectInputDevice::GetDeviceState. + if( FAILED( hr = g_pMouse->SetDataFormat( &c_dfDIMouse2 ) ) ) + return hr; + + // Set the cooperativity level to let DirectInput know how + // this device should interact with the system and with other + // DirectInput applications. + hr = g_pMouse->SetCooperativeLevel( hDlg, dwCoopFlags ); + if( hr == DIERR_UNSUPPORTED && !bForeground && bExclusive ) + { + DirectInputUninit(hDlg); + //MessageBox( hDlg, _T("SetCooperativeLevel() returned DIERR_UNSUPPORTED.\n") + // _T("For security reasons, background exclusive mouse\n") + // _T("access is not allowed."), + // _T("Mouse"), MB_OK ); + return S_OK; + } + + if( FAILED(hr) ) + return hr; + + if( !bImmediate ) + { + // IMPORTANT STEP TO USE BUFFERED DEVICE DATA! + // + // DirectInput uses unbuffered I/O (buffer size = 0) by default. + // If you want to read buffered data, you need to set a nonzero + // buffer size. + // + // Set the buffer size to SAMPLE_BUFFER_SIZE (defined above) elements. + // + // The buffer size is a DWORD property associated with the device. + DIPROPDWORD dipdw; + dipdw.diph.dwSize = sizeof(DIPROPDWORD); + dipdw.diph.dwHeaderSize = sizeof(DIPROPHEADER); + dipdw.diph.dwObj = 0; + dipdw.diph.dwHow = DIPH_DEVICE; + dipdw.dwData = SAMPLE_BUFFER_SIZE; // Arbitary buffer size + + if( FAILED( hr = g_pMouse->SetProperty( DIPROP_BUFFERSIZE, &dipdw.diph ) ) ) + return hr; + } + + // Acquire the newly created device + if (FAILED(hr = g_pMouse->Acquire())) + return hr; + + // Setup timer to read mouse position + if (g_TimerIDEvent = SetTimer(hDlg, IDEVENT_TIMER_MOUSE, 8, NULL) == 0) // 120Hz timer + return -1; + + return S_OK; + } + + //----------------------------------------------------------------------------- + // Name: FreeDirectInput() + // Desc: Initialize the DirectInput variables. + //----------------------------------------------------------------------------- + void DirectInputUninit( HWND hDlg ) + { + // Unacquire the device one last time just in case + // the app tried to exit while the device is still acquired. + if( g_pMouse ) + g_pMouse->Unacquire(); + + // Release any DirectInput objects. + SAFE_RELEASE( g_pMouse ); + SAFE_RELEASE( g_pDI ); + + if (g_TimerIDEvent) + KillTimer(hDlg, g_TimerIDEvent); + } + + //----------------------------------------------------------------------------- + // Name: ReadImmediateData() + // Desc: Read the input device's state when in immediate mode and display it. + //----------------------------------------------------------------------------- + HRESULT ReadImmediateData( long* pX, long* pY ) + { + HRESULT hr; + DIMOUSESTATE2 dims2; // DirectInput mouse state structure + + if (pX) *pX = 0; + if (pY) *pY = 0; + + if( NULL == g_pMouse ) + return S_OK; + + // Get the input's device state, and put the state in dims + ZeroMemory( &dims2, sizeof(dims2) ); + hr = g_pMouse->GetDeviceState( sizeof(DIMOUSESTATE2), &dims2 ); + if( FAILED(hr) ) + { + // DirectInput may be telling us that the input stream has been + // interrupted. We aren't tracking any state between polls, so + // we don't have any special reset that needs to be done. + // We just re-acquire and try again. + + // If input is lost then acquire and keep trying + hr = g_pMouse->Acquire(); + while( hr == DIERR_INPUTLOST ) + hr = g_pMouse->Acquire(); + + // Update the dialog text + if( hr == DIERR_OTHERAPPHASPRIO || + hr == DIERR_NOTACQUIRED ) + { + //SetDlgItemText( hDlg, IDC_DATA, TEXT("Unacquired") ); + } + + // hr may be DIERR_OTHERAPPHASPRIO or other errors. This + // may occur when the app is minimized or in the process of + // switching, so just try again later + return S_OK; + } + + if (pX) *pX = dims2.lX; + if (pY) *pY = dims2.lY; + + return S_OK; + } + +}; // namespace DIMouse \ No newline at end of file diff --git a/source/MouseInterface.h b/source/MouseInterface.h index 112785bc..192d3eaf 100644 --- a/source/MouseInterface.h +++ b/source/MouseInterface.h @@ -19,10 +19,27 @@ public: static BYTE __stdcall IORead(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft); static BYTE __stdcall IOWrite(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nCyclesLeft); - void SetPositionRel(int dx, int dy); + void SetPositionRel(long dx, long dy, int* pOutOfBoundsX, int* pOutOfBoundsY); void SetButton(eBUTTON Button, eBUTTONSTATE State); - bool Active() { return m_bActive; } + bool IsActive() { return m_bActive; } + bool IsEnabled() { return m_bEnabled; } + bool IsActiveAndEnabled() { return IsActive() && IsEnabled(); } + void SetEnabled(bool bEnabled) { m_bEnabled = bEnabled; } void SetVBlank(bool bVBL); + void GetXY(int& iX, int& iMinX, int& iMaxX, int& iY, int& iMinY, int& iMaxY) + { + iX = m_iX; + iMinX = m_iMinX; + iMaxX = m_iMaxX; + iY = m_iY; + iMinY = m_iMinY; + iMaxY = m_iMaxY; + } + void SetCursorPos(int iX, int iY) + { + m_iX = iX; + m_iY = iY; + } protected: void On6821_A(BYTE byData); @@ -37,8 +54,8 @@ protected: //friend CALLBACK_HANDLER( MouseHandler ); void SetPositionAbs(int x, int y); - void ClampX(); - void ClampY(); + int ClampX(); + int ClampY(); void SetClampX(int iMinX, int iMaxX); void SetClampY(int iMinY, int iMaxY); @@ -74,7 +91,17 @@ protected: // - bool m_bActive; + bool m_bActive; // Mouse h/w is active within the Apple][ VM + bool m_bEnabled; // Windows' mouse events get passed to Apple]['s mouse h/w LPBYTE m_pSlotRom; UINT m_uSlot; }; + +#define IDEVENT_TIMER_MOUSE 1 + +namespace DIMouse +{ + HRESULT DirectInputInit( HWND hDlg ); + void DirectInputUninit( HWND hDlg ); + HRESULT ReadImmediateData( long* pX=NULL, long* pY=NULL ); +}; \ No newline at end of file diff --git a/source/PropertySheetPage.cpp b/source/PropertySheetPage.cpp index 6ccafef6..8e445fd8 100644 --- a/source/PropertySheetPage.cpp +++ b/source/PropertySheetPage.cpp @@ -96,12 +96,13 @@ TCHAR discchoices[] = TEXT("Authentic Speed\0") const UINT VOLUME_MIN = 0; const UINT VOLUME_MAX = 59; -enum {PG_CONFIG=0, PG_INPUT, PG_SOUND, PG_SAVESTATE, PG_DISK, PG_ADVANCED, PG_NUM_SHEETS}; +enum {PG_CONFIG=0, PG_INPUT, PG_SOUND, PG_DISK, PG_ADVANCED, PG_NUM_SHEETS}; UINT g_nLastPage = PG_CONFIG; UINT g_uScrollLockToggle = 0; UINT g_uMouseInSlot4 = 0; +UINT g_uMouseShowCrosshair = 0; // @@ -255,9 +256,6 @@ static void ConfigDlg_OK(HWND window, UINT afterclose) MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES) { afterclose = WM_USER_RESTART; - - if (NewApple2Type > A2TYPE_APPLE2PLUS) - g_uTheFreezesF8Rom = false; } } @@ -283,7 +281,6 @@ static void ConfigDlg_OK(HWND window, UINT afterclose) SAVE(TEXT("Custom Speed") ,IsDlgButtonChecked(window,IDC_CUSTOM_SPEED)); SAVE(TEXT("Emulation Speed") ,g_dwSpeed); SAVE(TEXT("Video Emulation") ,videotype); - SAVE(TEXT(REGVALUE_THE_FREEZES_F8_ROM),g_uTheFreezesF8Rom); // @@ -470,6 +467,8 @@ static void InputDlg_OK(HWND window, UINT afterclose) JoySetTrim((short)SendDlgItemMessage(window, IDC_SPIN_XTRIM, UDM_GETPOS, 0, 0), true); JoySetTrim((short)SendDlgItemMessage(window, IDC_SPIN_YTRIM, UDM_GETPOS, 0, 0), false); + g_uMouseShowCrosshair = IsDlgButtonChecked(window, IDC_MOUSE_CROSSHAIR) ? 1 : 0; + // KeybSetBufferMode(bNewKeybBufferEnable); SAVE(TEXT("Joystick 0 Emulation"),joytype[0]); @@ -478,6 +477,7 @@ static void InputDlg_OK(HWND window, UINT afterclose) SAVE(TEXT(REGVALUE_PDL_YTRIM),JoyGetTrim(false)); SAVE(TEXT(REGVALUE_SCROLLLOCK_TOGGLE),g_uScrollLockToggle); SAVE(TEXT(REGVALUE_MOUSE_IN_SLOT4),g_uMouseInSlot4); + SAVE(TEXT(REGVALUE_MOUSE_CROSSHAIR),g_uMouseShowCrosshair); // SAVE(TEXT(REGVALUE_KEYB_BUFFER_ENABLE),KeybGetBufferMode() ? 1 : 0); // @@ -571,12 +571,14 @@ static BOOL CALLBACK InputDlgProc (HWND window, { UINT uNewState = IsDlgButtonChecked(window, IDC_MOUSE_IN_SLOT4) ? 1 : 0; LPCSTR pMsg = uNewState ? - TEXT("The emulator needs to restart as the slot configuration has changed.\n") - TEXT("Also Mockingboard/Phasor cards won't be available in slot 4.\n\n") + TEXT("The emulator needs to restart as the slot configuration has changed.\n\n") + TEXT("Also Mockingboard/Phasor cards won't be available in slot 4\n") + TEXT("and the mouse can't be used for joystick emulation.\n\n") TEXT("Would you like to restart the emulator now?") : - TEXT("The emulator needs to restart as the slot configuration has changed.\n") - TEXT("(Mockingboard/Phasor cards will now be available in slot 4.)\n\n") + TEXT("The emulator needs to restart as the slot configuration has changed.\n\n") + TEXT("(Mockingboard/Phasor cards will now be available in slot 4\n") + TEXT("and the mouse can be used for joystick emulation)\n\n") TEXT("Would you like to restart the emulator now?"); if (MessageBox(window, pMsg, @@ -584,6 +586,14 @@ static BOOL CALLBACK InputDlgProc (HWND window, MB_ICONQUESTION | MB_YESNO | MB_SETFOREGROUND) == IDYES) { g_uMouseInSlot4 = uNewState; + + if (uNewState) + { + JoyDisableUsingMouse(); + InitJoystickChoices(window, JN_JOYSTICK0, IDC_JOYSTICK0); + InitJoystickChoices(window, JN_JOYSTICK1, IDC_JOYSTICK1); + } + afterclose = WM_USER_RESTART; PropSheet_PressButton(GetParent(window), PSBTN_OK); } @@ -618,6 +628,8 @@ static BOOL CALLBACK InputDlgProc (HWND window, CheckDlgButton(window, IDC_SCROLLLOCK_TOGGLE, g_uScrollLockToggle ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(window, IDC_MOUSE_IN_SLOT4, g_uMouseInSlot4 ? BST_CHECKED : BST_UNCHECKED); + CheckDlgButton(window, IDC_MOUSE_CROSSHAIR, g_uMouseShowCrosshair ? BST_CHECKED : BST_UNCHECKED); + EnableWindow(GetDlgItem(window, IDC_MOUSE_CROSSHAIR), g_uMouseInSlot4 ? TRUE : FALSE); // CheckDlgButton(window, IDC_KEYB_BUFFER_ENABLE, KeybGetBufferMode() ? BST_CHECKED : BST_UNCHECKED); } } @@ -759,175 +771,6 @@ static BOOL CALLBACK SoundDlgProc (HWND window, //=========================================================================== -static char g_szNewDirectory[MAX_PATH]; -static char g_szNewFilename[MAX_PATH]; - -static void SaveStateUpdate() -{ - Snapshot_SetFilename(g_szNewFilename); - - RegSaveString(TEXT("Configuration"),REGVALUE_SAVESTATE_FILENAME,1,Snapshot_GetFilename()); - - if(g_szNewDirectory[0]) - RegSaveString(TEXT("Preferences"),REGVALUE_PREF_START_DIR,1,g_szNewDirectory); -} - -static void SaveStateDlg_OK(HWND window, UINT afterclose) -{ - char szFilename[MAX_PATH]; - - memset(szFilename, 0, sizeof(szFilename)); - * ((USHORT*) szFilename) = sizeof(szFilename); - - UINT nLineLength = SendDlgItemMessage(window,IDC_SAVESTATE_FILENAME,EM_LINELENGTH,0,0); - - SendDlgItemMessage(window,IDC_SAVESTATE_FILENAME,EM_GETLINE,0,(LPARAM)szFilename); - - nLineLength = nLineLength > sizeof(szFilename)-1 ? sizeof(szFilename)-1 : nLineLength; - szFilename[nLineLength] = 0x00; - - SaveStateUpdate(); - - g_bSaveStateOnExit = IsDlgButtonChecked(window, IDC_SAVESTATE_ON_EXIT) ? true : false; - - SAVE(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), g_bSaveStateOnExit ? 1 : 0); - - // - - if (afterclose) - PostMessage(g_hFrameWindow,afterclose,0,0); -} - -static void SaveStateDlg_CANCEL(HWND window) -{ -} - -//--------------------------------------------------------------------------- - -static int SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bool bSave) -{ - TCHAR szDirectory[MAX_PATH] = TEXT(""); - TCHAR szFilename[MAX_PATH]; - - // Attempt to use drive1's image name as the name for the .aws file - LPCTSTR pDiskName0 = DiskGetName(0); - if (pDiskName0 && pDiskName0[0]) - { - strcpy(szFilename, pDiskName0); - strcpy(&szFilename[strlen(pDiskName0)], ".aws"); - // NB. OK'ing this property sheet will call Snapshot_SetFilename() with this new filename - } - else - { - strcpy(szFilename, Snapshot_GetFilename()); - } - - RegLoadString(TEXT("Preferences"),REGVALUE_PREF_START_DIR,1,szDirectory,MAX_PATH); - - - // - - OPENFILENAME ofn; - ZeroMemory(&ofn,sizeof(OPENFILENAME)); - - ofn.lStructSize = sizeof(OPENFILENAME); - ofn.hwndOwner = hWindow; - ofn.hInstance = g_hInstance; - ofn.lpstrFilter = TEXT("Save State files (*.aws)\0*.aws\0") - TEXT("All Files\0*.*\0"); - ofn.lpstrFile = szFilename; - ofn.nMaxFile = MAX_PATH; - ofn.lpstrInitialDir = szDirectory; - ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; - ofn.lpstrTitle = pszTitle; - - int nRes = bSave ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn); - - if(nRes) - { - strcpy(g_szNewFilename, &szFilename[ofn.nFileOffset]); - - szFilename[ofn.nFileOffset] = 0; - if (_tcsicmp(szDirectory, szFilename)) - strcpy(g_szNewDirectory, szFilename); - } - - return nRes; -} - -//--------------------------------------------------------------------------- - -static BOOL CALLBACK SaveStateDlgProc (HWND window, - UINT message, - WPARAM wparam, - LPARAM lparam) -{ - static UINT afterclose = 0; - - switch (message) - { - case WM_NOTIFY: - { - // Property Sheet notifications - - switch (((LPPSHNOTIFY)lparam)->hdr.code) - { - case PSN_KILLACTIVE: - SetWindowLong(window, DWL_MSGRESULT, FALSE); // Changes are valid - break; - case PSN_APPLY: - SetWindowLong(window, DWL_MSGRESULT, PSNRET_NOERROR); // Changes are valid - SaveStateDlg_OK(window, afterclose); - break; - case PSN_QUERYCANCEL: - // Can use this to ask user to confirm cancel - break; - case PSN_RESET: - SaveStateDlg_CANCEL(window); - break; - } - } - break; - - case WM_COMMAND: - switch (LOWORD(wparam)) - { - case IDC_SAVESTATE_FILENAME: - break; - case IDC_SAVESTATE_BROWSE: - if(SaveStateSelectImage(window, TEXT("Select Save State file"), true)) - SendDlgItemMessage(window, IDC_SAVESTATE_FILENAME, WM_SETTEXT, 0, (LPARAM) g_szNewFilename); - break; - case IDC_SAVESTATE_ON_EXIT: - break; - case IDC_SAVESTATE: - afterclose = WM_USER_SAVESTATE; - break; - case IDC_LOADSTATE: - afterclose = WM_USER_LOADSTATE; - break; - } - break; - - case WM_INITDIALOG: - { - g_nLastPage = PG_SAVESTATE; - - SendDlgItemMessage(window,IDC_SAVESTATE_FILENAME,WM_SETTEXT,0,(LPARAM)Snapshot_GetFilename()); - - CheckDlgButton(window, IDC_SAVESTATE_ON_EXIT, g_bSaveStateOnExit ? BST_CHECKED : BST_UNCHECKED); - - g_szNewDirectory[0] = 0x00; - - afterclose = 0; - } - } - - return 0; -} - -//=========================================================================== - static void EnableHDD(HWND window, BOOL bEnable) { EnableWindow(GetDlgItem(window, IDC_HDD1), bEnable); @@ -1064,8 +907,104 @@ static BOOL CALLBACK DiskDlgProc (HWND window, //=========================================================================== +static char g_szNewDirectory[MAX_PATH]; +static char g_szNewFilename[MAX_PATH]; + +static void SaveStateUpdate() +{ + Snapshot_SetFilename(g_szNewFilename); + + RegSaveString(TEXT("Configuration"),REGVALUE_SAVESTATE_FILENAME,1,Snapshot_GetFilename()); + + if(g_szNewDirectory[0]) + RegSaveString(TEXT("Preferences"),REGVALUE_PREF_START_DIR,1,g_szNewDirectory); +} + +static int SaveStateSelectImage(HWND hWindow, TCHAR* pszTitle, bool bSave) +{ + TCHAR szDirectory[MAX_PATH] = TEXT(""); + TCHAR szFilename[MAX_PATH]; + + // Attempt to use drive1's image name as the name for the .aws file + LPCTSTR pDiskName0 = DiskGetName(0); + if (pDiskName0 && pDiskName0[0]) + { + strcpy(szFilename, pDiskName0); + strcpy(&szFilename[strlen(pDiskName0)], ".aws"); + // NB. OK'ing this property sheet will call Snapshot_SetFilename() with this new filename + } + else + { + strcpy(szFilename, Snapshot_GetFilename()); + } + + RegLoadString(TEXT("Preferences"),REGVALUE_PREF_START_DIR,1,szDirectory,MAX_PATH); + + + // + + OPENFILENAME ofn; + ZeroMemory(&ofn,sizeof(OPENFILENAME)); + + ofn.lStructSize = sizeof(OPENFILENAME); + ofn.hwndOwner = hWindow; + ofn.hInstance = g_hInstance; + ofn.lpstrFilter = TEXT("Save State files (*.aws)\0*.aws\0") + TEXT("All Files\0*.*\0"); + ofn.lpstrFile = szFilename; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrInitialDir = szDirectory; + ofn.Flags = OFN_PATHMUSTEXIST | OFN_HIDEREADONLY; + ofn.lpstrTitle = pszTitle; + + int nRes = bSave ? GetSaveFileName(&ofn) : GetOpenFileName(&ofn); + + if(nRes) + { + strcpy(g_szNewFilename, &szFilename[ofn.nFileOffset]); + + szFilename[ofn.nFileOffset] = 0; + if (_tcsicmp(szDirectory, szFilename)) + strcpy(g_szNewDirectory, szFilename); + } + + return nRes; +} + +static void InitFreezeDlgButton(HWND window) +{ + if (g_bEnableFreezeDlgButton == UNDEFINED) + EnableWindow(GetDlgItem(window, IDC_THE_FREEZES_F8_ROM_FW), IS_APPLE2 ? TRUE : FALSE); + else + EnableWindow(GetDlgItem(window, IDC_THE_FREEZES_F8_ROM_FW), g_bEnableFreezeDlgButton ? TRUE : FALSE); + + CheckDlgButton(window, IDC_THE_FREEZES_F8_ROM_FW, g_uTheFreezesF8Rom ? BST_CHECKED : BST_UNCHECKED); +} + +//--------------------------------------------------------------------------- + static void AdvancedDlg_OK(HWND window, UINT afterclose) { + char szFilename[MAX_PATH]; + + memset(szFilename, 0, sizeof(szFilename)); + * ((USHORT*) szFilename) = sizeof(szFilename); + + UINT nLineLength = SendDlgItemMessage(window,IDC_SAVESTATE_FILENAME,EM_LINELENGTH,0,0); + + SendDlgItemMessage(window,IDC_SAVESTATE_FILENAME,EM_GETLINE,0,(LPARAM)szFilename); + + nLineLength = nLineLength > sizeof(szFilename)-1 ? sizeof(szFilename)-1 : nLineLength; + szFilename[nLineLength] = 0x00; + + SaveStateUpdate(); + + g_bSaveStateOnExit = IsDlgButtonChecked(window, IDC_SAVESTATE_ON_EXIT) ? true : false; + + SAVE(TEXT(REGVALUE_SAVE_STATE_ON_EXIT), g_bSaveStateOnExit ? 1 : 0); + + // + g_uCloneType = (DWORD)SendDlgItemMessage(window, IDC_CLONETYPE, CB_GETCURSEL, 0, 0); SAVE(TEXT(REGVALUE_CLONETYPE), g_uCloneType); @@ -1083,16 +1022,6 @@ static void AdvancedDlg_CANCEL(HWND window) //--------------------------------------------------------------------------- -static void InitFreezeDlgButton(HWND window) -{ - if (g_bEnableFreezeDlgButton == UNDEFINED) - EnableWindow(GetDlgItem(window, IDC_THE_FREEZES_F8_ROM_FW), IS_APPLE2 ? TRUE : FALSE); - else - EnableWindow(GetDlgItem(window, IDC_THE_FREEZES_F8_ROM_FW), g_bEnableFreezeDlgButton ? TRUE : FALSE); - - CheckDlgButton(window, IDC_THE_FREEZES_F8_ROM_FW, g_uTheFreezesF8Rom ? BST_CHECKED : BST_UNCHECKED); -} - static BOOL CALLBACK AdvancedDlgProc (HWND window, UINT message, WPARAM wparam, @@ -1132,6 +1061,23 @@ static BOOL CALLBACK AdvancedDlgProc (HWND window, case WM_COMMAND: switch (LOWORD(wparam)) { + case IDC_SAVESTATE_FILENAME: + break; + case IDC_SAVESTATE_BROWSE: + if(SaveStateSelectImage(window, TEXT("Select Save State file"), true)) + SendDlgItemMessage(window, IDC_SAVESTATE_FILENAME, WM_SETTEXT, 0, (LPARAM) g_szNewFilename); + break; + case IDC_SAVESTATE_ON_EXIT: + break; + case IDC_SAVESTATE: + afterclose = WM_USER_SAVESTATE; + break; + case IDC_LOADSTATE: + afterclose = WM_USER_LOADSTATE; + break; + + // + case IDC_THE_FREEZES_F8_ROM_FW: { UINT uNewState = IsDlgButtonChecked(window, IDC_THE_FREEZES_F8_ROM_FW) ? 1 : 0; @@ -1159,6 +1105,14 @@ static BOOL CALLBACK AdvancedDlgProc (HWND window, { g_nLastPage = PG_ADVANCED; + SendDlgItemMessage(window,IDC_SAVESTATE_FILENAME,WM_SETTEXT,0,(LPARAM)Snapshot_GetFilename()); + + CheckDlgButton(window, IDC_SAVESTATE_ON_EXIT, g_bSaveStateOnExit ? BST_CHECKED : BST_UNCHECKED); + + g_szNewDirectory[0] = 0x00; + + // + FillComboBox(window, IDC_CLONETYPE, g_CloneChoices, g_uCloneType); InitFreezeDlgButton(window); @@ -1433,12 +1387,6 @@ void PSP_Init() PropSheetPages[PG_SOUND].pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_SOUND); PropSheetPages[PG_SOUND].pfnDlgProc = (DLGPROC)SoundDlgProc; - PropSheetPages[PG_SAVESTATE].dwSize = sizeof(PROPSHEETPAGE); - PropSheetPages[PG_SAVESTATE].dwFlags = PSP_DEFAULT; - PropSheetPages[PG_SAVESTATE].hInstance = g_hInstance; - PropSheetPages[PG_SAVESTATE].pszTemplate = MAKEINTRESOURCE(IDD_PROPPAGE_SAVESTATE); - PropSheetPages[PG_SAVESTATE].pfnDlgProc = (DLGPROC)SaveStateDlgProc; - PropSheetPages[PG_DISK].dwSize = sizeof(PROPSHEETPAGE); PropSheetPages[PG_DISK].dwFlags = PSP_DEFAULT; PropSheetPages[PG_DISK].hInstance = g_hInstance; diff --git a/source/PropertySheetPage.h b/source/PropertySheetPage.h index 5cd1d3b8..63c8352d 100644 --- a/source/PropertySheetPage.h +++ b/source/PropertySheetPage.h @@ -9,5 +9,6 @@ void get_tfe_enabled(int *tfe_enabled); extern UINT g_uScrollLockToggle; extern UINT g_uMouseInSlot4; +extern UINT g_uMouseShowCrosshair; extern UINT g_uTheFreezesF8Rom; extern DWORD g_uCloneType;