From 52e7d61c7efaff92f8ba27b67cbec4978974dcf3 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 22 Apr 2018 14:37:59 +0100
Subject: [PATCH 001/128] SSC: . DCD state is now a mirror of DSR unless -dcd
switch is used. (Fixes #553) . Removed -dsr,-dtr switches, so -modem is now
an alias for -dcd. (Also for #553) . Wait for events (RLSD,DSR,CTS) in
CommThread and call GetCommModemStatus() in CommThread.
---
source/Applewin.cpp | 16 +--------
source/SerialComms.cpp | 80 ++++++++++++++++--------------------------
source/SerialComms.h | 9 ++---
3 files changed, 34 insertions(+), 71 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 37909826..7505d533 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1210,24 +1210,10 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
g_bMultiMon = true;
}
- else if (strcmp(lpCmdLine, "-dcd") == 0) // GH#386
+ else if ((strcmp(lpCmdLine, "-dcd") == 0) || (strcmp(lpCmdLine, "-modem") == 0)) // GH#386
{
sg_SSC.SupportDCD(true);
}
- else if (strcmp(lpCmdLine, "-dsr") == 0) // GH#386
- {
- sg_SSC.SupportDSR(true);
- }
- else if (strcmp(lpCmdLine, "-dtr") == 0) // GH#386
- {
- sg_SSC.SupportDTR(true);
- }
- else if (strcmp(lpCmdLine, "-modem") == 0) // GH#386
- {
- sg_SSC.SupportDCD(true);
- sg_SSC.SupportDSR(true);
- sg_SSC.SupportDTR(true);
- }
else // unsupported
{
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index 0964ba9a..7cde6fca 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -68,9 +68,7 @@ CSuperSerialCard::CSuperSerialCard() :
m_aySerialPortChoices(NULL),
m_uTCPChoiceItemIdx(0),
m_uSlot(0),
- m_bCfgSupportDCD(false),
- m_bCfgSupportDSR(false),
- m_bCfgSupportDTR(false)
+ m_bCfgSupportDCD(false)
{
memset(m_ayCurrentSerialPortName, 0, sizeof(m_ayCurrentSerialPortName));
m_dwSerialPortItem = 0;
@@ -119,6 +117,7 @@ void CSuperSerialCard::InternalReset()
m_uDTR = DTR_CONTROL_DISABLE;
m_uRTS = RTS_CONTROL_DISABLE;
+ m_dwModemStatus = m_kDefaultModemStatus;
}
CSuperSerialCard::~CSuperSerialCard()
@@ -524,11 +523,8 @@ void CSuperSerialCard::UpdateCommandReg(BYTE command)
m_bRxIrqEnabled = false;
}
- if (m_bCfgSupportDTR) // GH#386
- {
- // Data Terminal Ready (DTR) setting (0=set DTR high (indicates 'not ready'))
- m_uDTR = (m_uCommandByte & CMD_DTR) ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
- }
+ // Data Terminal Ready (DTR) setting (0=set DTR high (indicates 'not ready')) (GH#386)
+ m_uDTR = (m_uCommandByte & CMD_DTR) ? DTR_CONTROL_ENABLE : DTR_CONTROL_DISABLE;
}
BYTE __stdcall CSuperSerialCard::CommCommand(WORD, WORD, BYTE write, BYTE value, ULONG)
@@ -754,29 +750,21 @@ BYTE __stdcall CSuperSerialCard::CommStatus(WORD, WORD, BYTE, BYTE, ULONG)
if (!CheckComm())
return ST_DSR | ST_DCD | ST_TX_EMPTY;
- static DWORD modemStatus = 0;
- if (m_bCfgSupportDCD || m_bCfgSupportDSR)
+ DWORD modemStatus = m_kDefaultModemStatus;
+ if (m_hCommHandle != INVALID_HANDLE_VALUE)
{
- if (m_hCommHandle != INVALID_HANDLE_VALUE)
+ modemStatus = m_dwModemStatus; // Take a copy of this volatile variable
+ if (!m_bCfgSupportDCD) // Default: DSR state is mirrored to DCD (GH#553)
{
- // Call GetCommModemStatus() outside of the critical section. For Win7-64: takes 1-2msecs!
- static DWORD dwLastTimeGettingModemStatus = 0;
- DWORD dwCurrTime = GetTickCount();
- if (dwCurrTime - dwLastTimeGettingModemStatus > 8) // Limit reading status to twice a 16.6ms video frame (arbitrary throttle limit)
- {
- // Only permit periodic reading, otherwise a tight 6502 polling loop can kill emulator performance!
- GetCommModemStatus(m_hCommHandle, &modemStatus); // Returns 0x30 = MS_DSR_ON|MS_CTS_ON
- dwLastTimeGettingModemStatus = dwCurrTime;
- }
- }
- else if (m_hCommListenSocket != INVALID_SOCKET)
- {
- if (m_hCommAcceptSocket != INVALID_SOCKET)
- modemStatus = MS_RLSD_ON | MS_DSR_ON | MS_CTS_ON;
- else
- modemStatus = 0;
+ modemStatus &= ~MS_RLSD_ON;
+ if (modemStatus & MS_DSR_ON)
+ modemStatus |= MS_RLSD_ON;
}
}
+ else if (m_hCommListenSocket != INVALID_SOCKET && m_hCommAcceptSocket != INVALID_SOCKET)
+ {
+ modemStatus = MS_RLSD_ON | MS_DSR_ON | MS_CTS_ON;
+ }
//
@@ -803,17 +791,8 @@ BYTE __stdcall CSuperSerialCard::CommStatus(WORD, WORD, BYTE, BYTE, ULONG)
//
- BYTE DSR = 0;
- BYTE DCD = 0;
-
- if ((m_hCommHandle != INVALID_HANDLE_VALUE) && (m_bCfgSupportDCD || m_bCfgSupportDSR)) // GH#386
- {
- if (m_bCfgSupportDSR)
- DSR = (modemStatus & MS_DSR_ON) ? 0x00 : ST_DSR;
-
- if (m_bCfgSupportDCD)
- DCD = (modemStatus & MS_RLSD_ON) ? 0x00 : ST_DCD;
- }
+ BYTE DSR = (modemStatus & MS_DSR_ON) ? 0x00 : ST_DSR; // DSR is active low (see SY6551 datasheet) (GH#386)
+ BYTE DCD = (modemStatus & MS_RLSD_ON) ? 0x00 : ST_DCD; // DCD is active low (see SY6551 datasheet) (GH#386)
//
@@ -825,7 +804,7 @@ BYTE __stdcall CSuperSerialCard::CommStatus(WORD, WORD, BYTE, BYTE, ULONG)
BYTE uStatus =
IRQ
| DSR
- | DCD // Need 0x00 (ie. DCD is active) to allow ZLink to start up
+ | DCD
| TX_EMPTY
| RX_FULL;
@@ -882,17 +861,11 @@ BYTE __stdcall CSuperSerialCard::CommDipSw(WORD, WORD addr, BYTE, BYTE, ULONG)
BYTE SW2_5 = m_DIPSWCurrent.bLinefeed ? 0 : 1; // SW2-5 (LF: yes-ON(0); no-OFF(1))
- BYTE CTS = 0; // GH#311
+ BYTE CTS = 1; // Default to CTS being false. (Support CTS in DIPSW: GH#311)
if (CheckComm() && m_hCommHandle != INVALID_HANDLE_VALUE)
- {
- DWORD modemStatus = 0;
- if (GetCommModemStatus(m_hCommHandle, &modemStatus))
- CTS = (modemStatus & MS_CTS_ON) ? 0 : 1; // CTS is true when 0
- }
+ CTS = (m_dwModemStatus & MS_CTS_ON) ? 0 : 1; // CTS active low (see SY6551 datasheet)
else if (m_hCommListenSocket != INVALID_SOCKET)
- {
CTS = (m_hCommAcceptSocket != INVALID_SOCKET) ? 0 : 1;
- }
// SSC-54:
sw = SW2_1<<7 | // b7 : SW2-1
@@ -1070,10 +1043,18 @@ void CSuperSerialCard::CheckCommEvent(DWORD dwEvtMask)
LeaveCriticalSection(&m_CriticalSection);
}
}
- else if (dwEvtMask & EV_TXEMPTY)
+
+ if (dwEvtMask & EV_TXEMPTY)
{
TransmitDone();
}
+
+ if (dwEvtMask & (EV_RLSD|EV_DSR|EV_CTS))
+ {
+ // For Win7-64: takes 1-2msecs!
+ // Don't read from main emulation thread, otherwise a tight 6502 polling loop can kill emulator performance!
+ GetCommModemStatus(m_hCommHandle, const_cast(&m_dwModemStatus));
+ }
}
DWORD WINAPI CSuperSerialCard::CommThread(LPVOID lpParameter)
@@ -1081,8 +1062,7 @@ DWORD WINAPI CSuperSerialCard::CommThread(LPVOID lpParameter)
CSuperSerialCard* pSSC = (CSuperSerialCard*) lpParameter;
char szDbg[100];
- BOOL bRes = SetCommMask(pSSC->m_hCommHandle, EV_TXEMPTY | EV_RXCHAR);
-// BOOL bRes = SetCommMask(pSSC->m_hCommHandle, EV_RXCHAR); // Just RX
+ BOOL bRes = SetCommMask(pSSC->m_hCommHandle, EV_RLSD | EV_DSR | EV_CTS | EV_TXEMPTY | EV_RXCHAR);
if (!bRes)
{
sprintf(szDbg, "SSC: CommThread(): SetCommMask() failed\n");
diff --git a/source/SerialComms.h b/source/SerialComms.h
index cfc393ca..89231dfa 100644
--- a/source/SerialComms.h
+++ b/source/SerialComms.h
@@ -43,8 +43,6 @@ public:
void SetSerialPortName(const char* pSerialPortName);
bool IsActive() { return (m_hCommHandle != INVALID_HANDLE_VALUE) || (m_hCommListenSocket != INVALID_SOCKET); }
void SupportDCD(bool bEnable) { m_bCfgSupportDCD = bEnable; } // Status
- void SupportDSR(bool bEnable) { m_bCfgSupportDSR = bEnable; } // Status
- void SupportDTR(bool bEnable) { m_bCfgSupportDTR = bEnable; } // Control
void CommTcpSerialAccept();
void CommTcpSerialReceive();
@@ -139,12 +137,11 @@ private:
BYTE* m_pExpansionRom;
UINT m_uSlot;
- // Modem
bool m_bCfgSupportDCD;
- bool m_bCfgSupportDSR;
- bool m_bCfgSupportDTR;
UINT m_uDTR;
- // Modem (end)
+
+ static const DWORD m_kDefaultModemStatus = 0; // MS_RLSD_OFF(=DCD_OFF), MS_DSR_OFF, MS_CTS_OFF
+ volatile DWORD m_dwModemStatus; // Updated by CommThread when any of RLSD|DSR|CTS changes / Read by main thread - CommStatus()& CommDipSw()
UINT m_uRTS;
};
From a7a4ee28ccab46c0d1e9e4bc058aed0972740f0a Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 22 Apr 2018 15:16:51 +0100
Subject: [PATCH 002/128] Help: Added a new help page about AppleWin's SSC
emulation. (Fixes #554)
---
help/Table of Contents.hhc | 6 ++-
help/card-ssc.html | 81 ++++++++++++++++++++++++++++++++++++++
help/cfg-config.html | 10 +----
help/toc.html | 1 +
4 files changed, 89 insertions(+), 9 deletions(-)
create mode 100644 help/card-ssc.html
diff --git a/help/Table of Contents.hhc b/help/Table of Contents.hhc
index 00c06e4e..552359e1 100644
--- a/help/Table of Contents.hhc
+++ b/help/Table of Contents.hhc
@@ -84,7 +84,11 @@
+
Function Keys F1-F8:
These PC function keys correspond to buttons on the toolbar.
Function Key F2 + Ctrl:
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 512cc541..188ab1b7 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1257,6 +1257,14 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
sg_SSC.SupportDCD(true);
}
+ else if (strcmp(lpCmdLine, "-alt-enter=toggle-full-screen") == 0) // GH#556
+ {
+ SetAltEnterToggleFullScreen(true);
+ }
+ else if (strcmp(lpCmdLine, "-alt-enter=open-apple-enter") == 0) // GH#556
+ {
+ SetAltEnterToggleFullScreen(false);
+ }
else // unsupported
{
LogFileOutput("Unsupported arg: %s\n", lpCmdLine);
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 6a6f0c98..ee031b02 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -175,6 +175,15 @@ 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:
@@ -1733,15 +1742,15 @@ LRESULT CALLBACK FrameWndProc (
}
break;
- case WM_SYSKEYDOWN:
+ case WM_SYSKEYDOWN: // ALT + any key; or F10
KeybUpdateCtrlShiftStatus();
// http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
- if (g_bAltKey && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
+ if (g_bAltEnter_ToggleFullScreen && g_bAltKey && (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
- else
- PostMessage(window,WM_KEYDOWN,wparam,lparam);
+
+ PostMessage(window,WM_KEYDOWN,wparam,lparam);
if ((wparam == VK_F10) || (wparam == VK_MENU)) // VK_MENU == ALT Key
return 0;
@@ -1752,10 +1761,11 @@ LRESULT CALLBACK FrameWndProc (
KeybUpdateCtrlShiftStatus();
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
- if (g_bAltKey && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
+ if (g_bAltEnter_ToggleFullScreen && g_bAltKey && (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
diff --git a/source/Frame.h b/source/Frame.h
index 0528bfe5..672b95e9 100644
--- a/source/Frame.h
+++ b/source/Frame.h
@@ -61,3 +61,5 @@
UINT GetFrameBufferHeight(void);
UINT Get3DBorderWidth(void);
UINT Get3DBorderHeight(void);
+
+ void SetAltEnterToggleFullScreen(bool mode);
From 734bc4cee2b8610fd539d12dcca79a725985b118 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Tue, 12 Jun 2018 21:50:27 +0100
Subject: [PATCH 023/128] AKD: Support both Return and Enter (and other
extended keys). (#330)
---
source/Frame.cpp | 10 +++++-----
source/Keyboard.cpp | 19 ++++++++++++++-----
source/Keyboard.h | 2 +-
3 files changed, 20 insertions(+), 11 deletions(-)
diff --git a/source/Frame.cpp b/source/Frame.cpp
index ee031b02..245245bf 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -1394,7 +1394,7 @@ LRESULT CALLBACK FrameWndProc (
// Note about Alt Gr (Right-Alt):
// . WM_KEYDOWN[Left-Control], then:
// . WM_KEYDOWN[Right-Alt]
- BOOL extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
+ bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
BOOL down = 1;
BOOL autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
BOOL IsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
@@ -1403,8 +1403,8 @@ LRESULT CALLBACK FrameWndProc (
{
KeybQueueKeypress((int)wparam, NOT_ASCII);
- if ((HIWORD(lparam) & KF_REPEAT) == 0)
- KeybAnyKeyDown(WM_KEYDOWN, wparam);
+ if (!autorep)
+ KeybAnyKeyDown(WM_KEYDOWN, wparam, extended);
}
}
else if (g_nAppMode == MODE_DEBUG)
@@ -1426,13 +1426,13 @@ LRESULT CALLBACK FrameWndProc (
}
else
{
- BOOL extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
+ bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
BOOL down = 0;
BOOL autorep = 0;
BOOL bIsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
if (!bIsJoyKey)
- KeybAnyKeyDown(WM_KEYUP, wparam);
+ KeybAnyKeyDown(WM_KEYUP, wparam, extended);
}
break;
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index ce02585b..70146809 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -390,11 +390,13 @@ static char ClipboardCurrChar(bool bIncPtr)
//===========================================================================
-static uint64_t g_AKDFlags[4] = {0,0,0,0};
+const UINT kAKDNumElements = 256/64;
+static uint64_t g_AKDFlags[2][kAKDNumElements] = { {0,0,0,0}, // normal
+ {0,0,0,0}}; // extended
// NB. Don't need to be concerned about if numpad/cursors are used for joystick,
// since parent calls JoyProcessKey() just before this.
-void KeybAnyKeyDown(UINT message, WPARAM wparam)
+void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
{
if (wparam > 255)
{
@@ -419,17 +421,24 @@ void KeybAnyKeyDown(UINT message, WPARAM wparam)
{
UINT offset = wparam >> 6;
UINT bit = wparam & 0x3f;
+ UINT idx = !bIsExtended ? 0 : 1;
if (message == WM_KEYDOWN)
- g_AKDFlags[offset] |= (1LL<
Date: Sat, 16 Jun 2018 10:24:05 +0100
Subject: [PATCH 024/128] Hook system keys: (#556) . added -no-hook-system-key
to prevent hooking system keys . updated help . HookFilter.dll: changed to
directly send virtual key code
---
HookFilter/HookFilter.cpp | 10 +++-------
help/CommandLine.html | 2 ++
source/Applewin.cpp | 37 ++++++++++++++++++++++++++-----------
3 files changed, 31 insertions(+), 18 deletions(-)
diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp
index 0ec04004..fcf3bf33 100644
--- a/HookFilter/HookFilter.cpp
+++ b/HookFilter/HookFilter.cpp
@@ -20,28 +20,24 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
UINT newMsg = pKbdLlHookStruct->flags & LLKHF_UP ? WM_KEYUP : WM_KEYDOWN;
LPARAM newlParam = newMsg == WM_KEYUP ? 3<<30 : 0; // b31:transition state, b30:previous key state
- // Note about PostMessage() and use of VkKeyScan():
- // . Convert the ascii code to virtual key code, so that the message pump can do TranslateMessage()
- // . NB. From MSDN for "WM_KEYDOWN" && "WM_KEYUP" : "Applications must pass wParam to TranslateMessage without altering it at all."
-
// Suppress alt-tab
if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
{
- PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x09)), newlParam);
+ PostMessage(g_hFrameWindow, newMsg, VK_TAB, newlParam);
suppress = true;
}
// Suppress alt-escape
if (pKbdLlHookStruct->vkCode == VK_ESCAPE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
{
- PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x1B)), newlParam);
+ PostMessage(g_hFrameWindow, newMsg, VK_ESCAPE, newlParam);
suppress = true;
}
// Suppress alt-space
if (pKbdLlHookStruct->vkCode == VK_SPACE && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
{
- PostMessage(g_hFrameWindow, newMsg, LOBYTE(VkKeyScan(0x20)), newlParam);
+ PostMessage(g_hFrameWindow, newMsg, VK_SPACE, newlParam);
suppress = true;
}
diff --git a/help/CommandLine.html b/help/CommandLine.html
index 0d48ca57..f8c17778 100644
--- a/help/CommandLine.html
+++ b/help/CommandLine.html
@@ -42,6 +42,8 @@
Enable the dialog box to display the last file saved to
-no-printscreen-key
Prevent the PrintScreen key from being registered
+ -no-hook-system-key
+ Prevent certain system key combinations from being hooked (to prevent the emulator from trapping ALT+ESC, ALT+SPACE, ALT+TAB and CTRL+ESC). This means that the equivalent Open Apple+<key> combinations won't work within the emulator.
-use-real-printer
Enables Advanced configuration control to allow dumping to a real printer
-noreg
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 188ab1b7..de24d066 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -78,6 +78,8 @@ TCHAR g_sProgramDir[MAX_PATH] = TEXT(""); // Directory of where AppleWin exe
TCHAR g_sDebugDir [MAX_PATH] = TEXT(""); // TODO: Not currently used
TCHAR g_sScreenShotDir[MAX_PATH] = TEXT(""); // TODO: Not currently used
bool g_bCapturePrintScreenKey = true;
+static bool g_bHookSystemKey = true;
+
TCHAR g_sCurrentDir[MAX_PATH] = TEXT(""); // Also Starting Dir. Debugger uses this when load/save
bool g_bRestart = false;
bool g_bRestartFullScreen = false;
@@ -871,7 +873,7 @@ static HINSTANCE g_hinstDLL = 0;
static HHOOK g_hhook = 0;
// Pre: g_hFrameWindow must be valid
-void HookFilterForKeyboard()
+bool HookFilterForKeyboard()
{
g_hinstDLL = LoadLibrary(TEXT("HookFilter.dll"));
@@ -890,16 +892,17 @@ void HookFilterForKeyboard()
g_hinstDLL,
0);
- if (g_hhook == 0 || g_hFrameWindow == 0)
- {
- std::string msg("Failed to install hook filter for system keys");
+ if (g_hhook != 0 && g_hFrameWindow != 0)
+ return true;
- DWORD dwErr = GetLastError();
- MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
+ std::string msg("Failed to install hook filter for system keys");
- msg += "\n";
- LogFileOutput(msg.c_str());
- }
+ DWORD dwErr = GetLastError();
+ MessageBox(GetDesktopWindow(), msg.c_str(), "Warning", MB_ICONASTERISK | MB_OK);
+
+ msg += "\n";
+ LogFileOutput(msg.c_str());
+ return false;
}
void UnhookFilterForKeyboard()
@@ -1227,6 +1230,10 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
g_bShowPrintScreenWarningDialog = false;
}
+ else if (strcmp(lpCmdLine, "-no-hook-system-key") == 0) // Don't hook the System keys (eg. Left-ALT+ESC/SPACE/TAB) GH#556
+ {
+ g_bHookSystemKey = false;
+ }
else if (strcmp(lpCmdLine, "-spkr-inc") == 0)
{
lpCmdLine = GetCurrArg(lpNextArg);
@@ -1419,7 +1426,11 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
LogFileOutput("Main: RegisterHotKeys()\n");
}
- HookFilterForKeyboard(); // needs valid g_hFrameWindow (for message pump)
+ if (g_bHookSystemKey)
+ {
+ if (HookFilterForKeyboard()) // needs valid g_hFrameWindow (for message pump)
+ LogFileOutput("Main: HookFilterForKeyboard()\n");
+ }
// Need to test if it's safe to call ResetMachineState(). In the meantime, just call DiskReset():
DiskReset(); // Switch from a booting A][+ to a non-autostart A][, so need to turn off floppy motor
@@ -1527,7 +1538,11 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
DSUninit();
LogFileOutput("Main: DSUninit()\n");
- UnhookFilterForKeyboard();
+ if (g_bHookSystemKey)
+ {
+ UnhookFilterForKeyboard();
+ LogFileOutput("Main: UnhookFilterForKeyboard()\n");
+ }
}
while (g_bRestart);
From 6ad262128273c111df3def1acdbfea326e0a5cf5 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 16 Jun 2018 11:36:43 +0100
Subject: [PATCH 025/128] Fixed save-state not saving last key & update
history.txt
---
bin/History.txt | 9 +++++++++
source/Keyboard.cpp | 9 +++------
2 files changed, 12 insertions(+), 6 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index f121102d..ccf66a23 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -9,6 +9,15 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.5.0 - dd mmm 2018
+----------------------
+. [Bug #556] Allow system key combinations to be read: Open Apple (left ALT) + ESC/SPACE/TAB.
+ - Also fixes #145, #198, #448.
+ - Support new command line switches: -no-hook-system-key, -alt-enter=
+ - Fix for save-state which wasn't correctly saving last key.
+. [Bug #330] Any Key Down (AKD) wasn't working for the multi-key case.
+
+
1.27.4.0 - 26 May 2018
----------------------
. [Bug #555] Fix for showing 559th DHGR vertical column.
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index 70146809..14341ec4 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -51,11 +51,8 @@ static bool g_bCapsLock = true; //Caps lock key for Apple2 and Lat/Cyr lock for
static bool g_bP8CapsLock = true; //Caps lock key of Pravets 8A/C
static int lastvirtkey = 0; // Current PC keycode
static BYTE keycode = 0; // Current Apple keycode
-
static BOOL keywaiting = 0;
-static BYTE g_nLastKey = 0x00;
-
//
// ----- ALL GLOBALLY ACCESSIBLE FUNCTIONS ARE BELOW THIS LINE -----
//
@@ -513,7 +510,7 @@ void KeybToggleP8ACapsLock ()
void KeybSetSnapshot_v1(const BYTE LastKey)
{
- g_nLastKey = LastKey;
+ keycode = LastKey;
}
//
@@ -529,7 +526,7 @@ static std::string KeybGetSnapshotStructName(void)
void KeybSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", KeybGetSnapshotStructName().c_str());
- yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LASTKEY, g_nLastKey);
+ yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LASTKEY, keycode);
}
void KeybLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
@@ -537,7 +534,7 @@ void KeybLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
if (!yamlLoadHelper.GetSubMap(KeybGetSnapshotStructName()))
return;
- g_nLastKey = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTKEY);
+ keycode = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTKEY);
yamlLoadHelper.PopMap();
}
From 7f478fa36cc32b5abf93e343d4fbc5138d5af883 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 17 Jun 2018 18:47:57 +0100
Subject: [PATCH 026/128] Mockingboard: Reading 6522's IER now returns
0x80|IER. (Fixes #567)
---
source/Mockingboard.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp
index 6af5d49d..96cc0ee5 100644
--- a/source/Mockingboard.cpp
+++ b/source/Mockingboard.cpp
@@ -549,7 +549,7 @@ static BYTE SY6522_Read(BYTE nDevice, BYTE nReg)
nValue = pMB->sy6522.IFR;
break;
case 0x0e: // IER
- nValue = 0x80; // Datasheet says this is 0x80|IER
+ nValue = 0x80 | pMB->sy6522.IER; // GH#567
break;
case 0x0f: // ORA_NO_HS
nValue = pMB->sy6522.ORA;
From 9bc7feb37e34635c980195c02877435f807a9cb9 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Wed, 20 Jun 2018 22:12:19 +0100
Subject: [PATCH 027/128] Mockingboard: Better support for stop/starting 6522's
IER.TIMERx (#567)
---
source/Mockingboard.cpp | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/source/Mockingboard.cpp b/source/Mockingboard.cpp
index 96cc0ee5..49e8bd23 100644
--- a/source/Mockingboard.cpp
+++ b/source/Mockingboard.cpp
@@ -480,11 +480,11 @@ static void SY6522_Write(BYTE nDevice, BYTE nReg, BYTE nValue)
pMB->sy6522.IER |= nValue;
UpdateIFR(pMB, 0);
- // Check if active timer changed from non-interrupt (polling IFR) to interrupt:
- if ((pMB->sy6522.IER & IxR_TIMER1) && pMB->bTimer1Active)
+ // Check if a timer interrupt has been enabled (regardless of if there's an active timer or not): GH#567
+ if (pMB->sy6522.IER & IxR_TIMER1)
StartTimer1(pMB);
- if ((pMB->sy6522.IER & IxR_TIMER2) && pMB->bTimer2Active)
+ if (pMB->sy6522.IER & IxR_TIMER2)
StartTimer2(pMB);
}
break;
From 47ec7f435542d26d5802c79d165784af25b362b7 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 23 Jun 2018 17:50:23 +0100
Subject: [PATCH 028/128] Reverted ad12a8e: video rendering from screen
position -1: so now DHGR vertical column 559 is hidden again (see #555).
Changed HGR rendering, such that that last video byte (at hpos=64) clears
g_nLastColumnPixelNTSC so that the end-of-line off-screen pixel is zero (see
#555).
---
source/NTSC.cpp | 10 +++++++++-
1 file changed, 9 insertions(+), 1 deletion(-)
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index a167b811..ec480f67 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -1291,6 +1291,14 @@ void updateScreenSingleHires40 (long cycles6502)
if (m & 0x80)
bits = (bits << 1) | g_nLastColumnPixelNTSC;
updatePixels( bits );
+
+ // For last hpos && bit6=1: (GH#555)
+ // * if bit7=0 (no shift) then clear g_nLastColumnPixelNTSC to prevent a 3rd 14M (aka DHGR) pixel being drawn
+ // . even though this is off-screen, it still has an on-screen affect (making the green dot more white on the screen edge).
+ // * if bit7=1 (half-dot shift) then also clear g_nLastColumnPixelNTSC
+ // . not sure if this is correct though
+ if (g_nVideoClockHorz == (VIDEO_SCANNER_MAX_HORZ-1))
+ g_nLastColumnPixelNTSC = 0;
}
}
updateVideoScannerHorzEOL();
@@ -1631,7 +1639,7 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
for (int y = 0; y < (VIDEO_SCANNER_Y_DISPLAY*2); y++)
{
uint32_t offset = sizeof(bgra_t) * GetFrameBufferWidth() * ((GetFrameBufferHeight() - 1) - y - GetFrameBufferBorderHeight()) + (sizeof(bgra_t) * GetFrameBufferBorderWidth());
-// offset -= sizeof(bgra_t); // GH#555: Start 1 RGBA pixel before frame to account for g_nLastColumnPixelNTSC
+// offset -= sizeof(bgra_t); // GH#555: Start 1 RGBA pixel before frame to account for g_nLastColumnPixelNTSC // TC: revert as lose half an HGR pixel on left-edge
g_pScanLines[y] = (bgra_t*) (g_pFramebufferbits + offset);
}
From 5f87cc0f7cfe72c794b8bada6361e7de12685d64 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 24 Jun 2018 10:19:27 +0100
Subject: [PATCH 029/128] 1.27.5: Bump version & update History.txt
---
bin/History.txt | 5 ++++-
resource/Applewin.rc | 8 ++++----
2 files changed, 8 insertions(+), 5 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index ccf66a23..4c2ec95e 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -9,12 +9,15 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
-1.27.5.0 - dd mmm 2018
+1.27.5.0 - 24 Jun 2018
----------------------
+. [Bug #567] Fixed Mockingboard/6522: Reading the 6522's IER now returns 0x80|IER.
. [Bug #556] Allow system key combinations to be read: Open Apple (left ALT) + ESC/SPACE/TAB.
- Also fixes #145, #198, #448.
- Support new command line switches: -no-hook-system-key, -alt-enter=
- Fix for save-state which wasn't correctly saving last key.
+. [Bug #555] Reverted 1.27.4's "Fix for showing 559th DHGR vertical column".
+ - So 559th DHGR vertical column remains hidden (this is still a bug).
. [Bug #330] Any Key Down (AKD) wasn't working for the multi-key case.
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index cdd1c6b2..c207be7c 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,4,0
- PRODUCTVERSION 1,27,4,0
+ FILEVERSION 1,27,5,0
+ PRODUCTVERSION 1,27,5,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 4, 0"
+ VALUE "FileVersion", "1, 27, 5, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 4, 0"
+ VALUE "ProductVersion", "1, 27, 5, 0"
END
END
BLOCK "VarFileInfo"
From 9cacf8d90df019c73d76446349f5fa4372918b47 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 30 Jun 2018 14:30:30 +0100
Subject: [PATCH 030/128] Small refactor for reading $C01x soft switch status
flags Prevent Apple II from reading $C01x/$C07F soft switch status flags
---
source/Keyboard.cpp | 6 ++--
source/Keyboard.h | 6 ++--
source/Memory.cpp | 71 ++++++++++++++++-----------------------------
source/Memory.h | 1 -
source/Video.cpp | 28 ------------------
source/Video.h | 4 ---
6 files changed, 30 insertions(+), 86 deletions(-)
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index 14341ec4..b9734da3 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -108,7 +108,7 @@ void KeybUpdateCtrlShiftStatus()
}
//===========================================================================
-BYTE KeybGetKeycode () // Used by MemCheckPaging() & VideoCheckMode()
+BYTE KeybGetKeycode () // Used by IORead_C01x() and TapeRead() for Pravets8A
{
return keycode;
}
@@ -440,7 +440,7 @@ static bool IsAKD(void)
//===========================================================================
-BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
+BYTE KeybReadData (void)
{
LogFileTimeUntilFirstKeyRead();
@@ -462,7 +462,7 @@ BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
//===========================================================================
-BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG)
+BYTE KeybReadFlag (void)
{
if (g_bPasteFromClipboard)
ClipboardInit();
diff --git a/source/Keyboard.h b/source/Keyboard.h
index d6236b56..c5518620 100644
--- a/source/Keyboard.h
+++ b/source/Keyboard.h
@@ -15,14 +15,12 @@ void KeybQueueKeypress (int,BOOL);
void KeybToggleCapsLock ();
void KeybToggleP8ACapsLock ();
void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended);
+BYTE KeybReadData (void);
+BYTE KeybReadFlag (void);
void KeybSetSnapshot_v1(const BYTE LastKey);
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
-BYTE __stdcall KeybReadData (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
-BYTE __stdcall KeybReadFlag (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
-BYTE __stdcall KbdAllow8Bit (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles); //For Pravets A/C only
-
extern bool g_bShiftKey;
extern bool g_bCtrlKey;
extern bool g_bAltKey;
diff --git a/source/Memory.cpp b/source/Memory.cpp
index a0bb58da..d7537bc3 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -209,7 +209,7 @@ BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYT
static BYTE __stdcall IORead_C00x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
- return KeybReadData(pc, addr, bWrite, d, nExecutedCycles);
+ return KeybReadData();
}
static BYTE __stdcall IOWrite_C00x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
@@ -224,32 +224,36 @@ static BYTE __stdcall IOWrite_C00x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON
static BYTE __stdcall IORead_C01x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
+ if (IS_APPLE2) // Include Pravets machines too?
+ return KeybReadFlag();
+
+ bool res = false;
switch (addr & 0xf)
{
- case 0x0: return KeybReadFlag(pc, addr, bWrite, d, nExecutedCycles);
- case 0x1: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x2: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x3: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x4: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x5: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x6: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x7: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x8: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0x9: return VideoCheckVbl(nExecutedCycles);
- case 0xA: return VideoCheckMode(pc, addr, bWrite, d, nExecutedCycles);
- case 0xB: return VideoCheckMode(pc, addr, bWrite, d, nExecutedCycles);
- case 0xC: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0xD: return MemCheckPaging(pc, addr, bWrite, d, nExecutedCycles);
- case 0xE: return VideoCheckMode(pc, addr, bWrite, d, nExecutedCycles);
- case 0xF: return VideoCheckMode(pc, addr, bWrite, d, nExecutedCycles);
+ case 0x0: return KeybReadFlag();
+ case 0x1: res = SW_BANK2 ? true : false; break;
+ case 0x2: res = SW_HIGHRAM ? true : false; break;
+ case 0x3: res = SW_AUXREAD ? true : false; break;
+ case 0x4: res = SW_AUXWRITE ? true : false; break;
+ case 0x5: res = SW_INTCXROM ? true : false; break;
+ case 0x6: res = SW_ALTZP ? true : false; break;
+ case 0x7: res = SW_SLOTC3ROM ? true : false; break;
+ case 0x8: res = SW_80STORE ? true : false; break;
+ case 0x9: res = VideoGetVblBar(nExecutedCycles); break;
+ case 0xA: res = VideoGetSWTEXT(); break;
+ case 0xB: res = VideoGetSWMIXED(); break;
+ case 0xC: res = SW_PAGE2 ? true : false; break;
+ case 0xD: res = VideoGetSWHIRES(); break;
+ case 0xE: res = VideoGetSWAltCharSet(); break;
+ case 0xF: res = VideoGetSW80COL(); break;
}
- return 0;
+ return KeybGetKeycode() | (res ? 0x80 : 0);
}
static BYTE __stdcall IOWrite_C01x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
- return KeybReadFlag(pc, addr, bWrite, d, nExecutedCycles);
+ return KeybReadFlag();
}
//-------------------------------------
@@ -344,8 +348,6 @@ static BYTE __stdcall IOWrite_C05x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULON
static BYTE __stdcall IORead_C06x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
- static byte CurrentKestroke = 0;
- CurrentKestroke = KeybGetKeycode();
switch (addr & 0x7) // address bit 4 is ignored (UTAIIe:7-5)
{
//In Pravets8A/C if SETMODE (8bit character encoding) is enabled, bit6 in $C060 is 0; Else it is 1
@@ -399,7 +401,7 @@ static BYTE __stdcall IORead_C07x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG
case 0xC: return IO_Null(pc, addr, bWrite, d, nExecutedCycles);
case 0xD: return IO_Null(pc, addr, bWrite, d, nExecutedCycles);
case 0xE: return IO_Null(pc, addr, bWrite, d, nExecutedCycles);
- case 0xF: return VideoCheckMode(pc, addr, bWrite, d, nExecutedCycles);
+ case 0xF: return MemReadFloatingBus(VideoGetSWDHIRES(), nExecutedCycles);
}
return 0;
@@ -1016,29 +1018,6 @@ static void UpdatePaging(BOOL initialize)
//===========================================================================
-// TODO: >= Apple2e only?
-BYTE __stdcall MemCheckPaging(WORD, WORD address, BYTE, BYTE, ULONG)
-{
- address &= 0xFF;
- BOOL result = 0;
- switch (address)
- {
- case 0x11: result = SW_BANK2; break;
- case 0x12: result = SW_HIGHRAM; break;
- case 0x13: result = SW_AUXREAD; break;
- case 0x14: result = SW_AUXWRITE; break;
- case 0x15: result = SW_INTCXROM; break;
- case 0x16: result = SW_ALTZP; break;
- case 0x17: result = SW_SLOTC3ROM; break;
- case 0x18: result = SW_80STORE; break;
- case 0x1C: result = SW_PAGE2; break;
- case 0x1D: result = SW_HIRES; break;
- }
- return KeybGetKeycode() | (result ? 0x80 : 0);
-}
-
-//===========================================================================
-
void MemDestroy()
{
VirtualFree(memaux ,0,MEM_RELEASE);
@@ -1648,7 +1627,7 @@ BYTE MemReadFloatingBus(const ULONG uExecutedCycles)
BYTE MemReadFloatingBus(const BYTE highbit, const ULONG uExecutedCycles)
{
BYTE r = MemReadFloatingBus(uExecutedCycles);
- return (r & ~0x80) | ((highbit) ? 0x80 : 0);
+ return (r & ~0x80) | (highbit ? 0x80 : 0);
}
//===========================================================================
diff --git a/source/Memory.h b/source/Memory.h
index 9b75730b..191a5b26 100644
--- a/source/Memory.h
+++ b/source/Memory.h
@@ -99,5 +99,4 @@ bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT version);
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
-BYTE __stdcall MemCheckPaging (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
BYTE __stdcall MemSetPaging(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
diff --git a/source/Video.cpp b/source/Video.cpp
index da2dd2a8..4ce1b145 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -338,34 +338,6 @@ void VideoBenchmark () {
MB_ICONINFORMATION | MB_SETFOREGROUND);
}
-//===========================================================================
-BYTE VideoCheckMode (WORD, WORD address, BYTE, BYTE, ULONG uExecutedCycles)
-{
- address &= 0xFF;
- if (address == 0x7F)
- return MemReadFloatingBus(SW_DHIRES != 0, uExecutedCycles);
- else {
- BOOL result = 0;
- switch (address) {
- case 0x1A: result = SW_TEXT; break;
- case 0x1B: result = SW_MIXED; break;
- case 0x1D: result = SW_HIRES; break;
- case 0x1E: result = g_nAltCharSetOffset; break;
- case 0x1F: result = SW_80COL; break;
- case 0x7F: result = SW_DHIRES; break;
- }
- return KeybGetKeycode() | (result ? 0x80 : 0);
- }
-}
-
-//===========================================================================
-BYTE VideoCheckVbl ( ULONG uExecutedCycles )
-{
- bool bVblBar = VideoGetVblBar(uExecutedCycles);
- BYTE r = KeybGetKeycode();
- return (r & ~0x80) | (bVblBar ? 0x80 : 0);
- }
-
// This is called from PageConfig
//===========================================================================
void VideoChooseMonochromeColor ()
diff --git a/source/Video.h b/source/Video.h
index dbae4172..1e133a11 100644
--- a/source/Video.h
+++ b/source/Video.h
@@ -197,10 +197,6 @@ enum VideoScreenShot_e
void Video_TakeScreenShot( VideoScreenShot_e iScreenShotType );
void Video_SetBitmapHeader( WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel );
-
-// Win32/MSVC: __stdcall
-BYTE VideoCheckMode (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
-BYTE VideoCheckVbl ( ULONG uExecutedCycles );
BYTE VideoSetMode (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
void Config_Load_Video(void);
From 881e51874b9723f0280792c78f2217e4ed37f2bf Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 30 Jun 2018 18:21:28 +0100
Subject: [PATCH 031/128] Fix for other apps having sluggish key response -
fixes #569
---
source/Applewin.cpp | 2 +-
source/Memory.cpp | 1 +
2 files changed, 2 insertions(+), 1 deletion(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index de24d066..356a869c 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -435,7 +435,7 @@ void EnterMessageLoop(void)
else if (g_nAppMode == MODE_PAUSED)
Sleep(1); // Stop process hogging CPU - 1ms, as need to fade-out speaker sound buffer
else if (g_nAppMode == MODE_LOGO)
- Sleep(100); // Stop process hogging CPU
+ Sleep(1); // Stop process hogging CPU (NB. don't delay for too long otherwise key input can be slow in other apps - GH#569)
}
}
}
diff --git a/source/Memory.cpp b/source/Memory.cpp
index d7537bc3..79357f8d 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -1831,6 +1831,7 @@ _done_saturn:
UpdatePaging(0); // Initialize=0
}
+ // Replicate 80STORE, PAGE2 and HIRES to video sub-system
if ((address <= 1) || ((address >= 0x54) && (address <= 0x57)))
return VideoSetMode(programcounter,address,write,value,nExecutedCycles);
From c457241229c8249f5582a6cff76fae23f99bfa81 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 15 Jul 2018 15:38:37 +0100
Subject: [PATCH 032/128] Keyboard: . When in MODE_LOGO, don't pass WM_CHAR to
Apple II keyboard (now consistent with WM_KEYDOWN) . Small refactor for Apple
II keyboard's WM_KEYDOWN handler Move code for log init & done to Log.cpp
---
source/Applewin.cpp | 14 ++------------
source/Frame.cpp | 6 ++++--
source/Keyboard.cpp | 29 +++++++++++++++++++----------
source/Log.cpp | 25 +++++++++++++++++++++++++
source/Log.h | 6 ++++--
5 files changed, 54 insertions(+), 26 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 356a869c..dc1c9315 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1077,12 +1077,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (((strcmp(lpCmdLine, "-l") == 0) || (strcmp(lpCmdLine, "-log") == 0)) && (g_fh == NULL))
{
- g_fh = fopen("AppleWin.log", "a+t"); // Open log file (append & text mode)
- setvbuf(g_fh, NULL, _IONBF, 0); // No buffering (so implicit fflush after every fprintf)
- CHAR aDateStr[80], aTimeStr[80];
- GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, (LPTSTR)aDateStr, sizeof(aDateStr));
- GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, (LPTSTR)aTimeStr, sizeof(aTimeStr));
- fprintf(g_fh, "*** Logging started: %s %s\n", aDateStr, aTimeStr);
+ LogInit();
}
else if (strcmp(lpCmdLine, "-noreg") == 0)
{
@@ -1559,12 +1554,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
tfe_shutdown();
LogFileOutput("Exit: tfe_shutdown()\n");
- if (g_fh)
- {
- fprintf(g_fh,"*** Logging ended\n\n");
- fclose(g_fh);
- g_fh = NULL;
- }
+ LogDone();
RiffFinishWriteFile();
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 245245bf..3b4803b5 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -1098,7 +1098,8 @@ LRESULT CALLBACK FrameWndProc (
{
if( !g_bDebuggerEatKey )
{
- KeybQueueKeypress((int)wparam, ASCII);
+ if (g_nAppMode != MODE_LOGO) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
+ KeybQueueKeypress((int)wparam, ASCII);
}
else
{
@@ -1399,7 +1400,8 @@ LRESULT CALLBACK FrameWndProc (
BOOL autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
BOOL IsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
- if (!IsJoyKey && (g_nAppMode != MODE_LOGO))
+ if (!IsJoyKey &&
+ (g_nAppMode != MODE_LOGO)) // !MODE_LOGO - not emulating so don't pass to the VM's keyboard
{
KeybQueueKeypress((int)wparam, NOT_ASCII);
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index b9734da3..bd1bb24a 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -37,8 +37,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Video.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change
static BYTE asciicode[2][10] = {
- {0x08,0x0D,0x15,0x2F,0x00,0x00,0x00,0x00,0x00,0x00},
- {0x08,0x0B,0x15,0x0A,0x00,0x00,0x00,0x00,0x00,0x7F}
+ // VK_LEFT/UP/RIGHT/DOWN/SELECT, VK_PRINT/EXECUTE/SNAPSHOT/INSERT/DELETE
+ {0x08,0x0D,0x15,0x2F,0x00, 0x00,0x00,0x00,0x00,0x00}, // Apple II
+ {0x08,0x0B,0x15,0x0A,0x00, 0x00,0x00,0x00,0x00,0x7F} // Apple //e
}; // Convert PC arrow keys to Apple keycodes
bool g_bShiftKey = false;
@@ -49,7 +50,6 @@ static bool g_bTK3KModeKey = false; //TK3000 //e |Mode| key
static bool g_bCapsLock = true; //Caps lock key for Apple2 and Lat/Cyr lock for Pravets8
static bool g_bP8CapsLock = true; //Caps lock key of Pravets 8A/C
-static int lastvirtkey = 0; // Current PC keycode
static BYTE keycode = 0; // Current Apple keycode
static BOOL keywaiting = 0;
@@ -102,7 +102,7 @@ bool KeybGetShiftStatus ()
//===========================================================================
void KeybUpdateCtrlShiftStatus()
{
- g_bShiftKey = (GetKeyState( VK_SHIFT ) & KF_UP) ? true : false; // 0x8000 KF_UP
+ g_bShiftKey = (GetKeyState( VK_SHIFT ) & KF_UP) ? true : false;
g_bCtrlKey = (GetKeyState( VK_CONTROL) & KF_UP) ? true : false;
g_bAltKey = (GetKeyState( VK_MENU ) & KF_UP) ? true : false;
}
@@ -271,8 +271,6 @@ void KeybQueueKeypress (int key, BOOL bASCII)
keycode = key;
}
}
-
- lastvirtkey = LOBYTE(VkKeyScan(key));
}
else //(bASCII != ASCII) // WM_KEYDOWN
{
@@ -299,13 +297,24 @@ void KeybQueueKeypress (int key, BOOL bASCII)
FrameRefreshStatus(DRAW_LEDS); // TODO: Implement |Mode| LED in the UI; make it appear only when in TK3000 mode
VideoRedrawScreen(); // TODO: Still need to implement page mode switching and 'whatnot'
}
+ return;
}
- if (!((key >= VK_LEFT) && (key <= VK_DELETE) && asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]))
+ if (key >= VK_LEFT && key <= VK_DELETE)
+ {
+ BYTE n = asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]; // Convert to Apple arrow keycode
+ if (!n)
+ return;
+ keycode = n;
+ }
+ else if ((GetKeyState( VK_RMENU ) & KF_UP)) // Right ALT
+ {
+ //
+ }
+ else
+ {
return;
-
- keycode = asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]; // Convert to Apple arrow keycode
- lastvirtkey = key;
+ }
}
keywaiting = 1;
diff --git a/source/Log.cpp b/source/Log.cpp
index 3c8753be..15f9dade 100644
--- a/source/Log.cpp
+++ b/source/Log.cpp
@@ -32,6 +32,31 @@ FILE* g_fh = NULL;
//---------------------------------------------------------------------------
+void LogInit(void)
+{
+ if (g_fh)
+ return;
+
+ g_fh = fopen("AppleWin.log", "a+t"); // Open log file (append & text mode)
+ setvbuf(g_fh, NULL, _IONBF, 0); // No buffering (so implicit fflush after every fprintf)
+ CHAR aDateStr[80], aTimeStr[80];
+ GetDateFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, (LPTSTR)aDateStr, sizeof(aDateStr));
+ GetTimeFormat(LOCALE_SYSTEM_DEFAULT, 0, NULL, NULL, (LPTSTR)aTimeStr, sizeof(aTimeStr));
+ fprintf(g_fh, "*** Logging started: %s %s\n", aDateStr, aTimeStr);
+}
+
+void LogDone(void)
+{
+ if (!g_fh)
+ return;
+
+ fprintf(g_fh,"*** Logging ended\n\n");
+ fclose(g_fh);
+ g_fh = NULL;
+}
+
+//---------------------------------------------------------------------------
+
void LogOutput(LPCTSTR format, ...)
{
TCHAR output[256];
diff --git a/source/Log.h b/source/Log.h
index d97224de..d952e69a 100644
--- a/source/Log.h
+++ b/source/Log.h
@@ -10,5 +10,7 @@
extern FILE* g_fh; // Filehandle for log file
-extern void LogOutput(LPCTSTR format, ...);
-extern void LogFileOutput(LPCTSTR format, ...);
+void LogInit(void);
+void LogDone(void);
+void LogOutput(LPCTSTR format, ...);
+void LogFileOutput(LPCTSTR format, ...);
From 97b07eaee40ba9c774ae12a4e5e7af82f79259ef Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 15 Jul 2018 21:00:01 +0100
Subject: [PATCH 033/128] Keyboard hook filter: . Created a dedicated thread
with message loop (#570) HookFilter dll: Only call GetKeyState() if keycode
is ESC (instead of every time) DebuggerCursorUpdate(): reduce sleep from 10ms
to 1ms
---
HookFilter/HookFilter.cpp | 9 +++--
source/Applewin.cpp | 73 ++++++++++++++++++++++++++++++++++++---
source/Debugger/Debug.cpp | 2 +-
3 files changed, 76 insertions(+), 8 deletions(-)
diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp
index fcf3bf33..d7e9602d 100644
--- a/HookFilter/HookFilter.cpp
+++ b/HookFilter/HookFilter.cpp
@@ -42,9 +42,12 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
}
// Suppress ctrl-escape
- bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
- if (pKbdLlHookStruct->vkCode == VK_ESCAPE && ControlDown)
- suppress = true;
+ if (pKbdLlHookStruct->vkCode == VK_ESCAPE)
+ {
+ bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
+ if (ControlDown)
+ suppress = true;
+ }
// Suppress keys by returning 1
if (suppress)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index dc1c9315..9c64d904 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -872,8 +872,11 @@ static void RegisterHotKeys(void)
static HINSTANCE g_hinstDLL = 0;
static HHOOK g_hhook = 0;
+static HANDLE g_hHookThread = NULL;
+static DWORD g_HookThreadId = 0;
+
// Pre: g_hFrameWindow must be valid
-bool HookFilterForKeyboard()
+static bool HookFilterForKeyboard()
{
g_hinstDLL = LoadLibrary(TEXT("HookFilter.dll"));
@@ -905,12 +908,74 @@ bool HookFilterForKeyboard()
return false;
}
-void UnhookFilterForKeyboard()
+static void UnhookFilterForKeyboard()
{
UnhookWindowsHookEx(g_hhook);
FreeLibrary(g_hinstDLL);
}
+static DWORD WINAPI HookThread(LPVOID lpParameter)
+{
+ if (!HookFilterForKeyboard())
+ return -1;
+
+ MSG msg;
+ while(GetMessage(&msg, NULL, 0, 0) > 0)
+ {
+ if (msg.message == WM_QUIT)
+ break;
+
+ TranslateMessage(&msg);
+ DispatchMessage(&msg);
+ }
+
+ UnhookFilterForKeyboard();
+ return 0;
+}
+
+static bool InitHookThread()
+{
+ g_hHookThread = CreateThread(NULL, // lpThreadAttributes
+ 0, // dwStackSize
+ (LPTHREAD_START_ROUTINE) HookThread,
+ 0, // lpParameter
+ 0, // dwCreationFlags : 0 = Run immediately
+ &g_HookThreadId); // lpThreadId
+ if (g_hHookThread == NULL)
+ return false;
+
+ return true;
+}
+
+static void UninitHookThread()
+{
+ if (g_hHookThread)
+ {
+ if (!PostThreadMessage(g_HookThreadId, WM_QUIT, 0, 0))
+ {
+ _ASSERT(0);
+ return;
+ }
+
+ do
+ {
+ DWORD dwExitCode;
+ if (GetExitCodeThread(g_hHookThread, &dwExitCode))
+ {
+ if(dwExitCode == STILL_ACTIVE)
+ Sleep(10);
+ else
+ break;
+ }
+ }
+ while(1);
+
+ CloseHandle(g_hHookThread);
+ g_hHookThread = NULL;
+ g_HookThreadId = 0;
+ }
+}
+
//===========================================================================
LPSTR GetCurrArg(LPSTR lpCmdLine)
@@ -1423,7 +1488,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (g_bHookSystemKey)
{
- if (HookFilterForKeyboard()) // needs valid g_hFrameWindow (for message pump)
+ if (InitHookThread()) // needs valid g_hFrameWindow (for message pump)
LogFileOutput("Main: HookFilterForKeyboard()\n");
}
@@ -1535,7 +1600,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (g_bHookSystemKey)
{
- UnhookFilterForKeyboard();
+ UninitHookThread();
LogFileOutput("Main: UnhookFilterForKeyboard()\n");
}
}
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index c57f55ae..404b570a 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -9680,7 +9680,7 @@ void DebuggerCursorUpdate()
}
else
{
- Sleep(10); // Stop process hogging CPU
+ Sleep(1); // Stop process hogging CPU
}
}
From 5e13bef808d62b5186fd8aad2df54e949df9f126 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 23 Jul 2018 22:14:54 +0100
Subject: [PATCH 034/128] VS2015: Add missing Hook Filter dependency
---
AppleWinExpress2015.sln | 1 +
1 file changed, 1 insertion(+)
diff --git a/AppleWinExpress2015.sln b/AppleWinExpress2015.sln
index 803daee0..19114355 100644
--- a/AppleWinExpress2015.sln
+++ b/AppleWinExpress2015.sln
@@ -5,6 +5,7 @@ VisualStudioVersion = 14.0.25420.1
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AppleWin", "AppleWinExpress2015.vcxproj", "{0A960136-A00A-4D4B-805F-664D9950D2CA}"
ProjectSection(ProjectDependencies) = postProject
+ {AA5854AD-2BC7-4EFD-9790-349ADB35E35A} = {AA5854AD-2BC7-4EFD-9790-349ADB35E35A}
{CF5A49BF-62A5-41BB-B10C-F34D556A7A45} = {CF5A49BF-62A5-41BB-B10C-F34D556A7A45}
{0212E0DF-06DA-4080-BD1D-F3B01599F70F} = {0212E0DF-06DA-4080-BD1D-F3B01599F70F}
{509739E7-0AF3-4C09-A1A9-F0B1BC31B39D} = {509739E7-0AF3-4C09-A1A9-F0B1BC31B39D}
From 1afa2490c54ba69015162ce690f84f09b8538146 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 23 Jul 2018 22:27:33 +0100
Subject: [PATCH 035/128] Keyboard: Refactor for GetKeyState()
---
source/Debugger/Debug.cpp | 4 ++--
source/Frame.h | 3 ---
source/Keyboard.cpp | 11 ++++++-----
source/Keyboard.h | 4 +++-
4 files changed, 11 insertions(+), 11 deletions(-)
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index 404b570a..b38f40d8 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -780,7 +780,7 @@ Update_t CmdBenchmarkStop (int nArgs)
DWORD currtime = GetTickCount();
while ((extbench = GetTickCount()) != currtime)
; // intentional busy-waiting
- KeybQueueKeypress(TEXT(' '),1);
+ KeybQueueKeypress(TEXT(' ') ,ASCII);
return UPDATE_ALL; // 0;
}
@@ -2096,7 +2096,7 @@ Update_t CmdUnassemble (int nArgs)
Update_t CmdKey (int nArgs)
{
KeybQueueKeypress(
- nArgs ? g_aArgs[1].nValue ? g_aArgs[1].nValue : g_aArgs[1].sArg[0] : TEXT(' '), 1); // FIXME!!!
+ nArgs ? g_aArgs[1].nValue ? g_aArgs[1].nValue : g_aArgs[1].sArg[0] : TEXT(' '), ASCII); // FIXME!!!
return UPDATE_CONSOLE_DISPLAY;
}
diff --git a/source/Frame.h b/source/Frame.h
index 672b95e9..f5cace2d 100644
--- a/source/Frame.h
+++ b/source/Frame.h
@@ -3,9 +3,6 @@
// 1.19.0.0 Hard Disk Status/Indicator Light
#define HD_LED 1
- // Keyboard -- keystroke type
- enum {NOT_ASCII=0, ASCII};
-
// Win32
extern HWND g_hFrameWindow;
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index bd1bb24a..c890c4e2 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -102,9 +102,9 @@ bool KeybGetShiftStatus ()
//===========================================================================
void KeybUpdateCtrlShiftStatus()
{
- g_bShiftKey = (GetKeyState( VK_SHIFT ) & KF_UP) ? true : false;
- g_bCtrlKey = (GetKeyState( VK_CONTROL) & KF_UP) ? true : false;
- g_bAltKey = (GetKeyState( VK_MENU ) & KF_UP) ? true : false;
+ g_bShiftKey = (GetKeyState( VK_SHIFT ) < 0) ? true : false; // L or R shift
+ g_bCtrlKey = (GetKeyState( VK_CONTROL) < 0) ? true : false; // L or R ctrl
+ g_bAltKey = (GetKeyState( VK_MENU ) < 0) ? true : false; // L or R alt
}
//===========================================================================
@@ -114,7 +114,7 @@ BYTE KeybGetKeycode () // Used by IORead_C01x() and TapeRead() for Pravets8A
}
//===========================================================================
-void KeybQueueKeypress (int key, BOOL bASCII)
+void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
{
if (bASCII == ASCII) // WM_CHAR
{
@@ -307,9 +307,10 @@ void KeybQueueKeypress (int key, BOOL bASCII)
return;
keycode = n;
}
- else if ((GetKeyState( VK_RMENU ) & KF_UP)) // Right ALT
+ else if ((GetKeyState(VK_RMENU) < 0)) // Right Alt (aka Alt Gr)
{
//
+ return;
}
else
{
diff --git a/source/Keyboard.h b/source/Keyboard.h
index c5518620..802903fc 100644
--- a/source/Keyboard.h
+++ b/source/Keyboard.h
@@ -1,5 +1,7 @@
#pragma once
+enum Keystroke_e {NOT_ASCII=0, ASCII};
+
void ClipboardInitiatePaste();
void KeybReset();
@@ -11,7 +13,7 @@ bool KeybGetShiftStatus();
bool KeybGetCapsAllowed(); //For Pravets8A/C only
void KeybUpdateCtrlShiftStatus();
BYTE KeybGetKeycode ();
-void KeybQueueKeypress (int,BOOL);
+void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII);
void KeybToggleCapsLock ();
void KeybToggleP8ACapsLock ();
void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended);
From 6ed354714e2ecdc1f3beb7e3b00794925c1ded85 Mon Sep 17 00:00:00 2001
From: TomCh
Date: Fri, 27 Jul 2018 21:55:53 +0100
Subject: [PATCH 036/128] Support ClosedApple+key with Alt Gr when combined
with a regular keyboard key:
. When Alt Gr is pressed, then manually post WM_CHAR message on receiving a WM_KEYDOWN (manually translate and account for shift/control/caps-lock)
. Hook filter: suppress Alt Gr's (ie. RMENU's) fake LCONTROL messages
Also:
. Hook filter: allow Ctrl+Shift+Esc (for Task Manager)
. Keyboard: refactor only use accessor functions to get the Alt/Control/Shift state
---
HookFilter/HookFilter.cpp | 16 +++++++-
source/Debugger/Debug.cpp | 8 ++--
source/Frame.cpp | 45 ++++++++++++---------
source/Keyboard.cpp | 83 ++++++++++++++++++++++++++-------------
source/Keyboard.h | 7 +---
5 files changed, 101 insertions(+), 58 deletions(-)
diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp
index d7e9602d..e21ee760 100644
--- a/HookFilter/HookFilter.cpp
+++ b/HookFilter/HookFilter.cpp
@@ -20,6 +20,18 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
UINT newMsg = pKbdLlHookStruct->flags & LLKHF_UP ? WM_KEYUP : WM_KEYDOWN;
LPARAM newlParam = newMsg == WM_KEYUP ? 3<<30 : 0; // b31:transition state, b30:previous key state
+ //
+
+ // NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
+ // Keyboard scanCodes: LCONTROL=0x1D, LCONTROL_from_RMENU=0x21D
+ // . For: Microsoft PS/2/Win7-64, VAIO laptop/Win7-64, Microsoft USB/Win10-64
+ // NB. WM_KEYDOWN also includes a 9/10-bit? scanCode: LCONTROL=0x1D, RCONTROL=0x11D, RMENU=0x1D(not 0x21D)
+ // . Can't suppress in app, since scanCode is not >= 0x200
+ if (pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200)
+ {
+ suppress = true;
+ }
+
// Suppress alt-tab
if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
{
@@ -44,8 +56,8 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
// Suppress ctrl-escape
if (pKbdLlHookStruct->vkCode == VK_ESCAPE)
{
- bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
- if (ControlDown)
+ // But don't suppress CTRL+SHIFT+ESC
+ if (GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) >= 0)
suppress = true;
}
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index b38f40d8..8f2b6a64 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -9709,11 +9709,11 @@ void DebuggerMouseClick( int x, int y )
if (g_nAppMode != MODE_DEBUG)
return;
- // NOTE: KeybUpdateCtrlShiftStatus() should be called before
+ KeybUpdateCtrlShiftStatus();
int iAltCtrlShift = 0;
- iAltCtrlShift |= (g_bAltKey & 1) << 0;
- iAltCtrlShift |= (g_bCtrlKey & 1) << 1;
- iAltCtrlShift |= (g_bShiftKey & 1) << 2;
+ iAltCtrlShift |= KeybGetAltStatus() ? 1<<0 : 0;
+ iAltCtrlShift |= KeybGetCtrlStatus() ? 1<<1 : 0;
+ iAltCtrlShift |= KeybGetShiftStatus() ? 1<<2 : 0;
// GH#462 disasm click #
if (iAltCtrlShift != g_bConfigDisasmClick)
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 3b4803b5..7a6a255d 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -57,6 +57,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Debugger/Debug.h"
//#define ENABLE_MENU 0
+#define DEBUG_KEY_MESSAGES 0
// 3D border around the 560x384 Apple II display
#define VIEWPORTX 5
@@ -1096,15 +1097,16 @@ LRESULT CALLBACK FrameWndProc (
case WM_CHAR:
if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_LOGO))
{
- if( !g_bDebuggerEatKey )
+ 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((int)wparam, ASCII);
- }
- else
- {
- g_bDebuggerEatKey = false;
+ KeybQueueKeypress(wparam, ASCII);
}
+
+ g_bDebuggerEatKey = false;
}
else if (g_nAppMode == MODE_DEBUG)
{
@@ -1290,19 +1292,19 @@ LRESULT CALLBACK FrameWndProc (
// CTRL+SHIFT+F9 Toggle 50% Scan Lines
// ALT+F9 Can't use Alt-F9 as Alt is Open-Apple = Joystick Button #1
- if ( !g_bCtrlKey && !g_bShiftKey ) // F9
+ if ( !KeybGetCtrlStatus() && !KeybGetShiftStatus() ) // F9
{
g_eVideoType++;
if (g_eVideoType >= NUM_VIDEO_MODES)
g_eVideoType = 0;
}
- else if ( !g_bCtrlKey && g_bShiftKey ) // SHIFT+F9
+ else if ( !KeybGetCtrlStatus() && KeybGetShiftStatus() ) // SHIFT+F9
{
if (g_eVideoType <= 0)
g_eVideoType = NUM_VIDEO_MODES;
g_eVideoType--;
}
- else if ( g_bCtrlKey && g_bShiftKey ) // CTRL+SHIFT+F9
+ else if ( KeybGetCtrlStatus() && KeybGetShiftStatus() ) // CTRL+SHIFT+F9
{
g_uHalfScanLines = !g_uHalfScanLines;
}
@@ -1331,7 +1333,7 @@ LRESULT CALLBACK FrameWndProc (
}
else if (wparam == VK_F10)
{
- if (g_Apple2Type == A2TYPE_PRAVETS8A && !g_bCtrlKey)
+ if (g_Apple2Type == A2TYPE_PRAVETS8A && !KeybGetCtrlStatus())
{
KeybToggleP8ACapsLock (); // F10: Toggles P8 Capslock
}
@@ -1340,7 +1342,7 @@ LRESULT CALLBACK FrameWndProc (
SetUsingCursor(FALSE); // Ctrl+F10
}
}
- else if (wparam == VK_F11 && !g_bCtrlKey) // Save state (F11)
+ else if (wparam == VK_F11 && !KeybGetCtrlStatus()) // Save state (F11)
{
SoundCore_SetFade(FADE_OUT);
if(sg_PropertySheet.SaveStateSelectImage(window, true))
@@ -1392,18 +1394,20 @@ LRESULT CALLBACK FrameWndProc (
}
else if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_LOGO) || (g_nAppMode == MODE_STEPPING))
{
- // Note about Alt Gr (Right-Alt):
- // . WM_KEYDOWN[Left-Control], then:
- // . WM_KEYDOWN[Right-Alt]
+ // NB. Alt Gr (Right-Alt): this normally send 2 WM_KEYDOWN messages for: VK_LCONTROL, then VK_RMENU
+ // . NB. The keyboard hook filter now suppresses VK_LCONTROL
bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
BOOL down = 1;
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
{
- KeybQueueKeypress((int)wparam, NOT_ASCII);
+ KeybQueueKeypress(wparam, NOT_ASCII);
if (!autorep)
KeybAnyKeyDown(WM_KEYDOWN, wparam, extended);
@@ -1433,6 +1437,9 @@ LRESULT CALLBACK FrameWndProc (
BOOL autorep = 0;
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);
}
@@ -1749,7 +1756,7 @@ LRESULT CALLBACK FrameWndProc (
// http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
- if (g_bAltEnter_ToggleFullScreen && g_bAltKey && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
+ 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);
@@ -1763,7 +1770,7 @@ LRESULT CALLBACK FrameWndProc (
KeybUpdateCtrlShiftStatus();
// v1.25.0: Alt-Return Alt-Enter toggle fullscreen
- if (g_bAltEnter_ToggleFullScreen && g_bAltKey && (wparam == VK_RETURN)) // NB. VK_RETURN = 0x0D; Normally WM_CHAR will be 0x0A but ALT key triggers as WM_SYSKEYDOWN and VK_MENU
+ 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);
@@ -1946,7 +1953,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
case BTN_RUN:
KeybUpdateCtrlShiftStatus();
- if( g_bCtrlKey )
+ if( KeybGetCtrlStatus() )
{
CtrlReset();
if (g_nAppMode == MODE_DEBUG)
@@ -1990,7 +1997,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
case BTN_FULLSCR:
KeybUpdateCtrlShiftStatus();
- ScreenWindowResize(g_bCtrlKey);
+ ScreenWindowResize( KeybGetCtrlStatus() );
break;
case BTN_DEBUG:
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index c890c4e2..c23190e6 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -35,6 +35,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Tape.h"
#include "YamlHelper.h"
#include "Video.h" // Needed by TK3000 //e, to refresh the frame at each |Mode| change
+#include "Log.h"
static BYTE asciicode[2][10] = {
// VK_LEFT/UP/RIGHT/DOWN/SELECT, VK_PRINT/EXECUTE/SNAPSHOT/INSERT/DELETE
@@ -65,36 +66,31 @@ void KeybReset()
}
//===========================================================================
-bool KeybGetAltStatus ()
-{
- return g_bAltKey;
-}
-
-//===========================================================================
-bool KeybGetCapsStatus ()
+bool KeybGetCapsStatus()
{
return g_bCapsLock;
}
+
//===========================================================================
bool KeybGetP8CapsStatus()
{
return g_bP8CapsLock;
}
+
//===========================================================================
-/*
-bool KeybGetCapsAllowed() //For Pravets 8A/C only
+bool KeybGetAltStatus()
{
- return g_CapsLockAllowed;
+ return g_bAltKey;
}
-*/
+
//===========================================================================
-bool KeybGetCtrlStatus ()
+bool KeybGetCtrlStatus()
{
return g_bCtrlKey;
}
//===========================================================================
-bool KeybGetShiftStatus ()
+bool KeybGetShiftStatus()
{
return g_bShiftKey;
}
@@ -102,9 +98,9 @@ bool KeybGetShiftStatus ()
//===========================================================================
void KeybUpdateCtrlShiftStatus()
{
- g_bShiftKey = (GetKeyState( VK_SHIFT ) < 0) ? true : false; // L or R shift
- g_bCtrlKey = (GetKeyState( VK_CONTROL) < 0) ? true : false; // L or R ctrl
g_bAltKey = (GetKeyState( VK_MENU ) < 0) ? true : false; // L or R alt
+ g_bCtrlKey = (GetKeyState( VK_CONTROL) < 0) ? true : false; // L or R ctrl
+ g_bShiftKey = (GetKeyState( VK_SHIFT ) < 0) ? true : false; // L or R shift
}
//===========================================================================
@@ -114,7 +110,10 @@ BYTE KeybGetKeycode () // Used by IORead_C01x() and TapeRead() for Pravets8A
}
//===========================================================================
-void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
+
+bool IsVirtualKeyAnAppleIIKey(WPARAM wparam);
+
+void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII)
{
if (bASCII == ASCII) // WM_CHAR
{
@@ -205,7 +204,7 @@ void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
}
else //i.e. latin letters
{
- if (GetCapsLockAllowed() == false)
+ if (GetCapsLockAllowed() == false)
{
if (key == '{') keycode = '[';
if (key == '}') keycode = ']';
@@ -309,7 +308,27 @@ void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII)
}
else if ((GetKeyState(VK_RMENU) < 0)) // Right Alt (aka Alt Gr)
{
- //
+ if (IsVirtualKeyAnAppleIIKey(key))
+ {
+ // When Alt Gr is down, then WM_CHAR is not posted - so fix this.
+ // NB. Still get WM_KEYDOWN/WM_KEYUP for the virtual key, so AKD works.
+ WPARAM newKey = key;
+
+ // Translate if shift or ctrl is down
+ if (key >= 'A' && key <= 'Z')
+ {
+ if ( (GetKeyState(VK_SHIFT) >= 0) && !g_bCapsLock )
+ newKey += 'a' - 'A'; // convert to lowercase key
+ else if (GetKeyState(VK_CONTROL) < 0)
+ {
+ LogOutput("L-Control=%d, R-Control=%d\n", GetKeyState(VK_LCONTROL), GetKeyState(VK_RCONTROL));
+ newKey -= 'A' - 1; // convert to control-key
+ }
+ }
+
+ PostMessage(g_hFrameWindow, WM_CHAR, newKey, 0);
+ }
+
return;
}
else
@@ -401,16 +420,8 @@ const UINT kAKDNumElements = 256/64;
static uint64_t g_AKDFlags[2][kAKDNumElements] = { {0,0,0,0}, // normal
{0,0,0,0}}; // extended
-// NB. Don't need to be concerned about if numpad/cursors are used for joystick,
-// since parent calls JoyProcessKey() just before this.
-void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
+static bool IsVirtualKeyAnAppleIIKey(WPARAM wparam)
{
- if (wparam > 255)
- {
- _ASSERT(0);
- return;
- }
-
if (wparam == VK_BACK ||
wparam == VK_TAB ||
wparam == VK_RETURN ||
@@ -425,6 +436,24 @@ void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
(wparam >= VK_OEM_1 && wparam <= VK_OEM_3) || // 7 in total
(wparam >= VK_OEM_4 && wparam <= VK_OEM_8) || // 5 in total
(wparam == VK_OEM_102))
+ {
+ return true;
+ }
+
+ return false;
+}
+
+// NB. Don't need to be concerned about if numpad/cursors are used for joystick,
+// since parent calls JoyProcessKey() just before this.
+void KeybAnyKeyDown(UINT message, WPARAM wparam, bool bIsExtended)
+{
+ if (wparam > 255)
+ {
+ _ASSERT(0);
+ return;
+ }
+
+ if (IsVirtualKeyAnAppleIIKey(wparam))
{
UINT offset = wparam >> 6;
UINT bit = wparam & 0x3f;
diff --git a/source/Keyboard.h b/source/Keyboard.h
index 802903fc..65920f39 100644
--- a/source/Keyboard.h
+++ b/source/Keyboard.h
@@ -5,12 +5,11 @@ enum Keystroke_e {NOT_ASCII=0, ASCII};
void ClipboardInitiatePaste();
void KeybReset();
-bool KeybGetAltStatus();
bool KeybGetCapsStatus();
bool KeybGetP8CapsStatus();
+bool KeybGetAltStatus();
bool KeybGetCtrlStatus();
bool KeybGetShiftStatus();
-bool KeybGetCapsAllowed(); //For Pravets8A/C only
void KeybUpdateCtrlShiftStatus();
BYTE KeybGetKeycode ();
void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII);
@@ -22,7 +21,3 @@ BYTE KeybReadFlag (void);
void KeybSetSnapshot_v1(const BYTE LastKey);
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
-
-extern bool g_bShiftKey;
-extern bool g_bCtrlKey;
-extern bool g_bAltKey;
From a4f225555fa68fd7ac619b215998c18f43d37ef3 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Fri, 27 Jul 2018 22:05:59 +0100
Subject: [PATCH 037/128] Keyboard: added comment for GH558 and removed some
debug logging
---
HookFilter/HookFilter.cpp | 2 +-
source/Keyboard.cpp | 5 +----
2 files changed, 2 insertions(+), 5 deletions(-)
diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp
index e21ee760..6a4525d9 100644
--- a/HookFilter/HookFilter.cpp
+++ b/HookFilter/HookFilter.cpp
@@ -27,7 +27,7 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
// . For: Microsoft PS/2/Win7-64, VAIO laptop/Win7-64, Microsoft USB/Win10-64
// NB. WM_KEYDOWN also includes a 9/10-bit? scanCode: LCONTROL=0x1D, RCONTROL=0x11D, RMENU=0x1D(not 0x21D)
// . Can't suppress in app, since scanCode is not >= 0x200
- if (pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200)
+ if (pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200) // GH#558
{
suppress = true;
}
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index c23190e6..7ad5af59 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -306,7 +306,7 @@ void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII)
return;
keycode = n;
}
- else if ((GetKeyState(VK_RMENU) < 0)) // Right Alt (aka Alt Gr)
+ else if ((GetKeyState(VK_RMENU) < 0)) // Right Alt (aka Alt Gr) - GH#558
{
if (IsVirtualKeyAnAppleIIKey(key))
{
@@ -320,10 +320,7 @@ void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII)
if ( (GetKeyState(VK_SHIFT) >= 0) && !g_bCapsLock )
newKey += 'a' - 'A'; // convert to lowercase key
else if (GetKeyState(VK_CONTROL) < 0)
- {
- LogOutput("L-Control=%d, R-Control=%d\n", GetKeyState(VK_LCONTROL), GetKeyState(VK_RCONTROL));
newKey -= 'A' - 1; // convert to control-key
- }
}
PostMessage(g_hFrameWindow, WM_CHAR, newKey, 0);
From b069614a2569d7e92e87627c03943fffd05ce3b4 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 28 Jul 2018 10:44:12 +0100
Subject: [PATCH 038/128] 1.27.6: Bump version & update History.txt
---
bin/History.txt | 5 +++++
resource/Applewin.rc | 8 ++++----
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index 4c2ec95e..9bbe234a 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -8,6 +8,11 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.6.0 - 28 Jul 2018
+----------------------
+. [Bug #570] Fixed lag when repeat-stepping in debugger.
+. [Bug #558] Fixed ClosedApple + not working (when using right ALT key).
+
1.27.5.0 - 24 Jun 2018
----------------------
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index c207be7c..a71c4458 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,5,0
- PRODUCTVERSION 1,27,5,0
+ FILEVERSION 1,27,6,0
+ PRODUCTVERSION 1,27,6,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 5, 0"
+ VALUE "FileVersion", "1, 27, 6, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 5, 0"
+ VALUE "ProductVersion", "1, 27, 6, 0"
END
END
BLOCK "VarFileInfo"
From 140d505fe96ff36223cd24afaab53b8cf9a6041d Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 29 Jul 2018 22:34:09 +0100
Subject: [PATCH 039/128] Keyboard: . reverted default so that ALT+TAB is not
hooked (#556) . reverted default so that ALT GR's fake LCONTROL is not hooked
(#558) . added new switches: -hook-alt-tab and -hook-altgr-control to support
hooking these key combo's (#556)
---
HookFilter/HookFilter.cpp | 10 +++++++---
source/Applewin.cpp | 19 +++++++++++++++++--
source/Applewin.h | 1 +
source/Keyboard.cpp | 2 +-
4 files changed, 26 insertions(+), 6 deletions(-)
diff --git a/HookFilter/HookFilter.cpp b/HookFilter/HookFilter.cpp
index 6a4525d9..fe3a045d 100644
--- a/HookFilter/HookFilter.cpp
+++ b/HookFilter/HookFilter.cpp
@@ -1,6 +1,8 @@
#include
static HWND g_hFrameWindow = (HWND)0;
+static bool g_bHookAltTab = false;
+static bool g_bHookAltGrControl = false;
// NB. __stdcall (or WINAPI) and extern "C":
// . symbol is decorated as _@bytes
@@ -27,13 +29,13 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
// . For: Microsoft PS/2/Win7-64, VAIO laptop/Win7-64, Microsoft USB/Win10-64
// NB. WM_KEYDOWN also includes a 9/10-bit? scanCode: LCONTROL=0x1D, RCONTROL=0x11D, RMENU=0x1D(not 0x21D)
// . Can't suppress in app, since scanCode is not >= 0x200
- if (pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200) // GH#558
+ if (g_bHookAltGrControl && pKbdLlHookStruct->vkCode == VK_LCONTROL && pKbdLlHookStruct->scanCode >= 0x200) // GH#558
{
suppress = true;
}
// Suppress alt-tab
- if (pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
+ if (g_bHookAltTab && pKbdLlHookStruct->vkCode == VK_TAB && (pKbdLlHookStruct->flags & LLKHF_ALTDOWN))
{
PostMessage(g_hFrameWindow, newMsg, VK_TAB, newlParam);
suppress = true;
@@ -69,7 +71,9 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
return CallNextHookEx(0/*parameter is ignored*/, nCode, wParam, lParam);
}
-extern "C" __declspec(dllexport) void __cdecl RegisterHWND(HWND hWnd)
+extern "C" __declspec(dllexport) void __cdecl RegisterHWND(HWND hWnd, bool bHookAltTab, bool bHookAltGrControl)
{
g_hFrameWindow = hWnd;
+ g_bHookAltTab = bHookAltTab;
+ g_bHookAltGrControl = bHookAltGrControl;
}
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 9c64d904..46cfbda8 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -79,6 +79,8 @@ TCHAR g_sDebugDir [MAX_PATH] = TEXT(""); // TODO: Not currently used
TCHAR g_sScreenShotDir[MAX_PATH] = TEXT(""); // TODO: Not currently used
bool g_bCapturePrintScreenKey = true;
static bool g_bHookSystemKey = true;
+static bool g_bHookAltTab = false;
+static bool g_bHookAltGrControl = false;
TCHAR g_sCurrentDir[MAX_PATH] = TEXT(""); // Also Starting Dir. Debugger uses this when load/save
bool g_bRestart = false;
@@ -171,6 +173,11 @@ void SetLoadedSaveStateFlag(const bool bFlag)
g_bLoadedSaveState = bFlag;
}
+bool GetHookAltGrControl(void)
+{
+ return g_bHookAltGrControl;
+}
+
static void ResetToLogoMode(void)
{
g_nAppMode = MODE_LOGO;
@@ -882,10 +889,10 @@ static bool HookFilterForKeyboard()
_ASSERT(g_hFrameWindow);
- typedef void (*RegisterHWNDProc)(HWND);
+ typedef void (*RegisterHWNDProc)(HWND, bool, bool);
RegisterHWNDProc RegisterHWND = (RegisterHWNDProc) GetProcAddress(g_hinstDLL, "RegisterHWND");
if (RegisterHWND)
- RegisterHWND(g_hFrameWindow);
+ RegisterHWND(g_hFrameWindow, g_bHookAltTab, g_bHookAltGrControl);
HOOKPROC hkprcLowLevelKeyboardProc = (HOOKPROC) GetProcAddress(g_hinstDLL, "LowLevelKeyboardProc");
@@ -1294,6 +1301,14 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
g_bHookSystemKey = false;
}
+ else if (strcmp(lpCmdLine, "-hook-alt-tab") == 0) // GH#556
+ {
+ g_bHookAltTab = true;
+ }
+ else if (strcmp(lpCmdLine, "-hook-altgr-control") == 0) // GH#556
+ {
+ g_bHookAltGrControl = true;
+ }
else if (strcmp(lpCmdLine, "-spkr-inc") == 0)
{
lpCmdLine = GetCurrArg(lpNextArg);
diff --git a/source/Applewin.h b/source/Applewin.h
index 43a6937b..a3732ecc 100644
--- a/source/Applewin.h
+++ b/source/Applewin.h
@@ -30,6 +30,7 @@ extern HINSTANCE g_hInstance;
extern AppMode_e g_nAppMode;
bool GetLoadedSaveStateFlag(void);
void SetLoadedSaveStateFlag(const bool bFlag);
+bool GetHookAltGrControl(void);
extern TCHAR g_sProgramDir[MAX_PATH];
extern TCHAR g_sCurrentDir[MAX_PATH];
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index 7ad5af59..c28afd46 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -319,7 +319,7 @@ void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII)
{
if ( (GetKeyState(VK_SHIFT) >= 0) && !g_bCapsLock )
newKey += 'a' - 'A'; // convert to lowercase key
- else if (GetKeyState(VK_CONTROL) < 0)
+ else if (GetHookAltGrControl() && GetKeyState(VK_CONTROL) < 0)
newKey -= 'A' - 1; // convert to control-key
}
From 898f30f08a8710abaa29529c9ce937a1f515d88f Mon Sep 17 00:00:00 2001
From: tomcw
Date: Tue, 31 Jul 2018 18:06:53 +0100
Subject: [PATCH 040/128] Fixed save-state on exit not working if there was a
VM restart (eg. config h/w change). Fixes #564
---
source/Frame.cpp | 4 +++-
source/SaveState.cpp | 6 ++++--
2 files changed, 7 insertions(+), 3 deletions(-)
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 7a6a255d..4afb1e82 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -1092,6 +1092,7 @@ LRESULT CALLBACK FrameWndProc (
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_CHAR:
@@ -1175,7 +1176,8 @@ LRESULT CALLBACK FrameWndProc (
case WM_DESTROY:
LogFileOutput("WM_DESTROY\n");
DragAcceptFiles(window,0);
- Snapshot_Shutdown();
+ if (!g_bRestart) // GH#564: Only save-state on shutdown (not on a restart)
+ Snapshot_Shutdown();
DebugDestroy();
if (!g_bRestart) {
DiskDestroy();
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index d067a381..ff2c7a96 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -637,17 +637,19 @@ void Snapshot_Startup()
Snapshot_LoadState();
- bDone = true;
+ bDone = true; // Prevents a g_bRestart from loading an old save-state
}
void Snapshot_Shutdown()
{
static bool bDone = false;
+ _ASSERT(!bDone);
+ _ASSERT(!g_bRestart);
if(!g_bSaveStateOnExit || bDone)
return;
Snapshot_SaveState();
- bDone = true;
+ bDone = true; // Debug flag: should only be called once, and never on a g_bRestart
}
From e4bd6162c50760239f74148bd90fb3c066247b87 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Tue, 31 Jul 2018 18:17:42 +0100
Subject: [PATCH 041/128] Refactor: move code for WM_CLOSE next to WM_DESTROY,
and WM_KEYDOWN next to WM_CHAR
---
source/Frame.cpp | 91 +++++++++++++++++++++-----------------------
source/SaveState.cpp | 2 +-
2 files changed, 45 insertions(+), 48 deletions(-)
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 4afb1e82..b58379c0 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -1095,25 +1095,29 @@ LRESULT CALLBACK FrameWndProc (
// Exit via DefWindowProc(), which does the default action for WM_CLOSE, which is to call DestroyWindow(), posting WM_DESTROY
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_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) {
+ DiskDestroy();
+ ImageDestroy();
+ HD_Destroy();
+ }
+ PrintDestroy();
+ sg_SSC.CommDestroy();
+ CpuDestroy();
+ MemDestroy();
+ SpkrDestroy();
+ VideoDestroy();
+ 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");
@@ -1173,30 +1177,6 @@ LRESULT CALLBACK FrameWndProc (
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) {
- DiskDestroy();
- ImageDestroy();
- HD_Destroy();
- }
- PrintDestroy();
- sg_SSC.CommDestroy();
- CpuDestroy();
- MemDestroy();
- SpkrDestroy();
- VideoDestroy();
- 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_DISPLAYCHANGE:
VideoReinitialize();
break;
@@ -1421,6 +1401,26 @@ LRESULT CALLBACK FrameWndProc (
}
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:
// Process is done in WM_KEYUP: VK_F1 VK_F2 VK_F3 VK_F4 VK_F5 VK_F6 VK_F7 VK_F8
if ((wparam >= VK_F1) && (wparam <= VK_F8) && (buttondown == (int)wparam-VK_F1))
@@ -1795,10 +1795,7 @@ LRESULT CALLBACK FrameWndProc (
}
case WM_USER_RESTART:
- // . Changed Apple computer type (][+ or //e)
- // . Changed slot configuration
- // . Changed disk speed (normal or enhanced)
- // . Changed Freeze F8 rom setting
+ // Changed h/w config, eg. Apple computer type (][+ or //e), slot configuration, etc.
g_bRestart = true;
PostMessage(window,WM_CLOSE,0,0);
break;
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index ff2c7a96..4870e9d6 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -651,5 +651,5 @@ void Snapshot_Shutdown()
Snapshot_SaveState();
- bDone = true; // Debug flag: should only be called once, and never on a g_bRestart
+ bDone = true; // Debug flag: this func should only be called once, and never on a g_bRestart
}
From 5e02eaee531032cfd9ff5c1f77a269303d26de14 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Thu, 2 Aug 2018 22:37:20 +0100
Subject: [PATCH 042/128] Use VideoGetScannerAddress() to generate the NTSC
video lookup tables
---
source/Memory.cpp | 1 -
source/NTSC.cpp | 93 ++++++++++++++++++++++++++++++++++++++++++++---
source/Video.cpp | 6 +--
3 files changed, 88 insertions(+), 12 deletions(-)
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 79357f8d..70e308ea 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -1618,7 +1618,6 @@ void MemReset()
BYTE MemReadFloatingBus(const ULONG uExecutedCycles)
{
-// return mem[ VideoGetScannerAddress(NULL, uExecutedCycles) ]; // NG: ANSI STORY (End Credits) - repro by running from "Turn the disk over"
return mem[ NTSC_VideoGetScannerAddress(uExecutedCycles) ]; // OK: This does the 2-cycle adjust for ANSI STORY (End Credits)
}
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index ec480f67..72f045a4 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -136,7 +136,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
static const UINT g_kFrameBufferWidth = GetFrameBufferWidth();
- static unsigned (*g_pHorzClockOffset)[VIDEO_SCANNER_MAX_HORZ] = 0;
+ static unsigned short (*g_pHorzClockOffset)[VIDEO_SCANNER_MAX_HORZ] = 0;
typedef void (*UpdateScreenFunc_t)(long);
static UpdateScreenFunc_t g_apFuncVideoUpdateScanline[VIDEO_SCANNER_Y_DISPLAY];
@@ -199,7 +199,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define SIGNAL_1 0.7465656072f
// Tables
- static unsigned g_aClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ] =
+ static unsigned short g_aClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ];
+
+ static unsigned short g_kClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ] =
{
0x0000,0x0400,0x0800,0x0C00,0x1000,0x1400,0x1800,0x1C00,0x0080,0x0480,0x0880,0x0C80,0x1080,0x1480,0x1880,0x1C80,
0x0100,0x0500,0x0900,0x0D00,0x1100,0x1500,0x1900,0x1D00,0x0180,0x0580,0x0980,0x0D80,0x1180,0x1580,0x1980,0x1D80,
@@ -224,7 +226,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0B80,0x0F80,0x1380,0x1780,0x1B80,0x1F80
};
- static unsigned g_aClockVertOffsetsTXT[33] =
+ static unsigned short g_aClockVertOffsetsTXT[33];
+
+ static unsigned short g_kClockVertOffsetsTXT[33] =
{
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
@@ -234,7 +238,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x380
};
- static unsigned APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
+ static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
+
+ static unsigned short kAPPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
{
{0x1068,0x1068,0x1069,0x106A,0x106B,0x106C,0x106D,0x106E,0x106F,
0x1070,0x1071,0x1072,0x1073,0x1074,0x1075,0x1076,0x1077,
@@ -282,7 +288,9 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F}
};
- static unsigned APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
+ static unsigned short APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
+
+ static unsigned short kAPPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
{
{0x0068,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,
@@ -776,7 +784,7 @@ INLINE uint16_t updateVideoScannerAddressTXT()
//===========================================================================
INLINE uint16_t updateVideoScannerAddressHGR()
{
- // BUG? g_pHorzClockOffset
+ // NB. Not a bug: For both A2 and //e then use APPLE_IIE_HORZ_CLOCK_OFFSET - see VideoGetScannerAddress() where only TEXT mode adds $1000
return (g_aClockVertOffsetsHGR[g_nVideoClockVert ] +
APPLE_IIE_HORZ_CLOCK_OFFSET[g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nHiresPage * 0x2000));
}
@@ -1629,9 +1637,12 @@ _mono:
}
//===========================================================================
+void GenerateVideoTables( void );
+
void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
{
make_csbits();
+ GenerateVideoTables();
initPixelDoubleMasks();
initChromaPhaseTables();
updateMonochromeTables( 0xFF, 0xFF, 0xFF );
@@ -1826,3 +1837,73 @@ bool NTSC_GetColorBurst( void )
{
return (g_nColorBurstPixels < 2) ? false : true;
}
+
+//===========================================================================
+void GenerateVideoTables( void )
+{
+ eApple2Type currentApple2Type = GetApple2Type();
+
+ g_uVideoMode = VF_HIRES;
+ for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<256; i++, cycle+=VIDEO_SCANNER_MAX_HORZ)
+ {
+ if (i % 64 == 0) cycle=VIDEO_SCANNER_HORZ_START; // repeat every 64th scanline
+ g_aClockVertOffsetsHGR[i] = VideoGetScannerAddress(NULL, cycle) - 0x2000;
+ _ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]);
+ }
+
+ // Repeat last 6 entries for scanlines [256...261]
+ const UINT kLine256 = 64 - (VIDEO_SCANNER_MAX_VERT - 256);
+ for (UINT i=256, cycle=kLine256*VIDEO_SCANNER_MAX_HORZ+VIDEO_SCANNER_HORZ_START; i
Date: Sun, 5 Aug 2018 22:19:51 +0100
Subject: [PATCH 043/128] Improve VideoGetScannerAddress() to generate NTSC
tables; and check tables with all video cycles
---
source/NTSC.cpp | 147 ++++++++++++++++++++++++++++-------------------
source/Video.cpp | 40 +++++++++----
source/Video.h | 4 +-
3 files changed, 121 insertions(+), 70 deletions(-)
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index 72f045a4..b97b5b6b 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -22,7 +22,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// Includes
#include "StdAfx.h"
#include "Applewin.h"
- #include "CPU.h"
+ #include "CPU.h" // CpuGetCyclesThisVideoFrame()
#include "Frame.h" // FRAMEBUFFER_W FRAMEBUFFER_H
#include "Memory.h" // MemGetMainPtr() MemGetBankPtr()
#include "Video.h" // g_pFramebufferbits
@@ -41,9 +41,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "ntsc_rgb.h"
#endif
- //LPBYTE MemGetMainPtr(const WORD);
- //LPBYTE MemGetBankPtr(const UINT nBank);
-
// Defines
#define HGR_TEST_PATTERN 0
@@ -199,8 +196,13 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#define SIGNAL_1 0.7465656072f
// Tables
- static unsigned short g_aClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ];
+ // Video scanner tables are now runtime-generated using UTAIIe logic
+ static unsigned short g_aClockVertOffsetsHGR[VIDEO_SCANNER_MAX_VERT];
+ static unsigned short g_aClockVertOffsetsTXT[33];
+ static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
+ static unsigned short APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
+#ifdef _DEBUG
static unsigned short g_kClockVertOffsetsHGR[ VIDEO_SCANNER_MAX_VERT ] =
{
0x0000,0x0400,0x0800,0x0C00,0x1000,0x1400,0x1800,0x1C00,0x0080,0x0480,0x0880,0x0C80,0x1080,0x1480,0x1880,0x1C80,
@@ -226,8 +228,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0B80,0x0F80,0x1380,0x1780,0x1B80,0x1F80
};
- static unsigned short g_aClockVertOffsetsTXT[33];
-
static unsigned short g_kClockVertOffsetsTXT[33] =
{
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
@@ -238,8 +238,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x380
};
- static unsigned short APPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
-
static unsigned short kAPPLE_IIP_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
{
{0x1068,0x1068,0x1069,0x106A,0x106B,0x106C,0x106D,0x106E,0x106F,
@@ -288,8 +286,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F}
};
- static unsigned short APPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ];
-
static unsigned short kAPPLE_IIE_HORZ_CLOCK_OFFSET[5][VIDEO_SCANNER_MAX_HORZ] =
{
{0x0068,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,
@@ -337,6 +333,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,
0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,0x001F}
};
+#endif
/*
http://www.kreativekorp.com/miscpages/a2info/munafo.shtml
@@ -397,11 +394,6 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
static csbits_t csbits; // charset, optionally followed by alt charset
// Prototypes
- // prototype from CPU.h
- //unsigned char CpuRead(unsigned short addr, unsigned long uExecutedCycles);
- // prototypes from Memory.h
- //unsigned char * MemGetAuxPtr (unsigned short);
- //unsigned char * MemGetMainPtr (unsigned short);
INLINE float clampZeroOne( const float & x );
INLINE uint8_t getCharSetBits( const int iChar );
INLINE uint16_t getLoResBits( uint8_t iByte );
@@ -419,8 +411,8 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
INLINE void updatePixels( uint16_t bits );
INLINE void updateVideoScannerHorzEOL();
INLINE void updateVideoScannerAddress();
- INLINE uint16_t updateVideoScannerAddressTXT();
- INLINE uint16_t updateVideoScannerAddressHGR();
+ INLINE uint16_t getVideoScannerAddressTXT();
+ INLINE uint16_t getVideoScannerAddressHGR();
static void initChromaPhaseTables();
static real initFilterChroma (real z);
@@ -775,16 +767,16 @@ inline void updateVideoScannerAddress()
}
//===========================================================================
-INLINE uint16_t updateVideoScannerAddressTXT()
+INLINE uint16_t getVideoScannerAddressTXT()
{
return (g_aClockVertOffsetsTXT[g_nVideoClockVert/8] +
g_pHorzClockOffset [g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nTextPage * 0x400));
}
//===========================================================================
-INLINE uint16_t updateVideoScannerAddressHGR()
+INLINE uint16_t getVideoScannerAddressHGR()
{
- // NB. Not a bug: For both A2 and //e then use APPLE_IIE_HORZ_CLOCK_OFFSET - see VideoGetScannerAddress() where only TEXT mode adds $1000
+ // NB. For both A2 and //e use APPLE_IIE_HORZ_CLOCK_OFFSET - see VideoGetScannerAddress() where only TEXT mode adds $1000
return (g_aClockVertOffsetsHGR[g_nVideoClockVert ] +
APPLE_IIE_HORZ_CLOCK_OFFSET[g_nVideoClockVert/64][g_nVideoClockHorz] + (g_nHiresPage * 0x2000));
}
@@ -1142,7 +1134,7 @@ void updateScreenDoubleHires40 (long cycles6502) // wsUpdateVideoHires0
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressHGR();
+ uint16_t addr = getVideoScannerAddressHGR();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
@@ -1173,7 +1165,7 @@ void updateScreenDoubleHires80 (long cycles6502 ) // wsUpdateVideoDblHires
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressHGR();
+ uint16_t addr = getVideoScannerAddressHGR();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
@@ -1210,7 +1202,7 @@ void updateScreenDoubleLores40 (long cycles6502) // wsUpdateVideo7MLores
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressTXT();
+ uint16_t addr = getVideoScannerAddressTXT();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
@@ -1242,7 +1234,7 @@ void updateScreenDoubleLores80 (long cycles6502) // wsUpdateVideoDblLores
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressTXT();
+ uint16_t addr = getVideoScannerAddressTXT();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
@@ -1283,7 +1275,7 @@ void updateScreenSingleHires40 (long cycles6502)
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressHGR();
+ uint16_t addr = getVideoScannerAddressHGR();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
@@ -1324,7 +1316,7 @@ void updateScreenSingleLores40 (long cycles6502)
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressTXT();
+ uint16_t addr = getVideoScannerAddressTXT();
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
@@ -1350,7 +1342,7 @@ void updateScreenText40 (long cycles6502)
{
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressTXT();
+ uint16_t addr = getVideoScannerAddressTXT();
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
{
@@ -1382,7 +1374,7 @@ void updateScreenText80 (long cycles6502)
{
for (; cycles6502 > 0; --cycles6502)
{
- uint16_t addr = updateVideoScannerAddressTXT();
+ uint16_t addr = getVideoScannerAddressTXT();
if ((g_nVideoClockHorz < VIDEO_SCANNER_HORZ_COLORBURST_END) && (g_nVideoClockHorz >= VIDEO_SCANNER_HORZ_COLORBURST_BEG))
{
@@ -1477,9 +1469,9 @@ uint16_t NTSC_VideoGetScannerAddress ( const ULONG uExecutedCycles )
uint16_t addr;
bool bHires = (g_uVideoMode & VF_HIRES) && !(g_uVideoMode & VF_TEXT); // SW_HIRES && !SW_TEXT
if( bHires )
- addr = updateVideoScannerAddressHGR();
+ addr = getVideoScannerAddressHGR();
else
- addr = updateVideoScannerAddressTXT();
+ addr = getVideoScannerAddressTXT();
g_nVideoClockVert = currVideoClockVert;
g_nVideoClockHorz = currVideoClockHorz;
@@ -1839,55 +1831,93 @@ bool NTSC_GetColorBurst( void )
}
//===========================================================================
-void GenerateVideoTables( void )
+
+static bool CheckVideoTables2( eApple2Type type, uint32_t mode )
+{
+ SetApple2Type(type);
+ NTSC_VideoInitAppleType();
+
+ g_uVideoMode = mode;
+
+ g_dwCyclesThisFrame = 0;
+ g_nVideoClockHorz = g_nVideoClockVert = 0;
+
+ for (DWORD cycles=0; cycles= kVPresetLine)) // check for previous vertical state preset
+ if (nVLine >= kVPresetLine) // check for previous vertical state preset
{
nVState -= nScanLines; // compensate for preset
}
@@ -835,6 +850,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
nAddress |= h_1 << 1; // a1
nAddress |= h_2 << 2; // a2
nAddress |= nSum << 3; // a3 - a6
+ g_PartialH = nAddress;
+
nAddress |= v_0 << 7; // a7
nAddress |= v_1 << 8; // a8
nAddress |= v_2 << 9; // a9
@@ -849,6 +866,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
nAddress |= v_A << 10; // a10
nAddress |= v_B << 11; // a11
nAddress |= v_C << 12; // a12
+ g_PartialV = nAddress - g_PartialH;
+
nAddress |= p2a << 13; // a13
nAddress |= p2b << 14; // a14
}
@@ -856,24 +875,23 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, DWORD nCycles)
{
// N: insert text-only address bits
//
- nAddress |= p2a << 10; // a10
- nAddress |= p2b << 11; // a11
+ g_PartialV = nAddress - g_PartialH;
// Apple ][ (not //e) and HBL?
//
if (IS_APPLE2 && // Apple II only (UTAIIe:I-4,#5)
!h_5 && (!h_4 || !h_3)) // HBL (UTAIIe:8-10,F8.5)
{
- nAddress |= 1 << 12; // Y: a12 (add $1000 to address!)
+ nAddress |= 1 << 12; // Y: a12 (add $1000 to address!)
+ g_PartialH |= 1 << 12;
}
- }
- // update VBL' state
- //
- if (pbVblBar_OUT != NULL)
- {
- *pbVblBar_OUT = !v_4 || !v_3; // VBL' = (v_4 & v_3)' (UTAIIe:5-10,#3)
+ nAddress |= p2a << 10; // a10
+ nAddress |= p2b << 11; // a11
}
+
+ // VBL' = v_4' | v_3' = (v_4 & v_3)' (UTAIIe:5-10,#3)
+
return static_cast(nAddress);
}
diff --git a/source/Video.h b/source/Video.h
index 1e133a11..3bacb655 100644
--- a/source/Video.h
+++ b/source/Video.h
@@ -169,7 +169,9 @@ void VideoRedrawScreen (void);
void VideoRefreshScreen (uint32_t uRedrawWholeScreenVideoMode = 0, bool bRedrawWholeScreen = false);
void VideoReinitialize ();
void VideoResetState ();
-WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles);
+WORD VideoGetScannerAddressPartialV(DWORD nCycles);
+WORD VideoGetScannerAddressPartialH(DWORD nCycles);
+WORD VideoGetScannerAddress(DWORD nCycles);
bool VideoGetVblBar(DWORD uExecutedCycles);
bool VideoGetSW80COL(void);
From bd7a96ce6e25877a2f30015b231520700f693df5 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 6 Aug 2018 19:06:28 +0100
Subject: [PATCH 044/128] Small refactor of VideoGetScannerAddress()
---
source/NTSC.cpp | 8 ++--
source/Video.cpp | 113 +++++++++++++++++++++--------------------------
source/Video.h | 5 +--
3 files changed, 57 insertions(+), 69 deletions(-)
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index b97b5b6b..29dd332c 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -1886,7 +1886,7 @@ static void GenerateVideoTables( void )
g_uVideoMode = VF_HIRES;
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i= kVPresetLine) // check for previous vertical state preset
{
- nVState -= nScanLines; // compensate for preset
+ nVState -= kScanLines; // compensate for preset
}
int v_A = (nVState >> 0) & 1; // get vertical state bits
int v_B = (nVState >> 1) & 1;
@@ -835,9 +820,9 @@ WORD VideoGetScannerAddress(DWORD nCycles)
// calculate scanning memory address
//
- if (nHires && SW_MIXED && v_4 && v_2) // HIRES TIME signal (UTAIIe:5-7,P3)
+ if (bHires && SW_MIXED && v_4 && v_2) // HIRES TIME signal (UTAIIe:5-7,P3)
{
- nHires = 0; // address is in text memory for mixed hires
+ bHires = false; // address is in text memory for mixed hires
}
int nAddend0 = 0x0D; // 1 1 0 1
@@ -845,54 +830,58 @@ WORD VideoGetScannerAddress(DWORD nCycles)
int nAddend2 = (v_4 << 3) | (v_3 << 2) | (v_4 << 1) | (v_3 << 0);
int nSum = (nAddend0 + nAddend1 + nAddend2) & 0x0F; // SUM (UTAIIe:5-9)
- int nAddress = 0; // build address from video scanner equations (UTAIIe:5-8,T5.1)
- nAddress |= h_0 << 0; // a0
- nAddress |= h_1 << 1; // a1
- nAddress |= h_2 << 2; // a2
- nAddress |= nSum << 3; // a3 - a6
- g_PartialH = nAddress;
+ WORD nAddressH = 0; // build address from video scanner equations (UTAIIe:5-8,T5.1)
+ nAddressH |= h_0 << 0; // a0
+ nAddressH |= h_1 << 1; // a1
+ nAddressH |= h_2 << 2; // a2
+ nAddressH |= nSum << 3; // a3 - a6
+ if (!bHires)
+ {
+ // Apple ][ (not //e) and HBL?
+ //
+ if (IS_APPLE2 && // Apple II only (UTAIIe:I-4,#5)
+ !h_5 && (!h_4 || !h_3)) // HBL (UTAIIe:8-10,F8.5)
+ {
+ nAddressH |= 1 << 12; // Y: a12 (add $1000 to address!)
+ }
+ }
- nAddress |= v_0 << 7; // a7
- nAddress |= v_1 << 8; // a8
- nAddress |= v_2 << 9; // a9
+ WORD nAddressV = 0;
+ nAddressV |= v_0 << 7; // a7
+ nAddressV |= v_1 << 8; // a8
+ nAddressV |= v_2 << 9; // a9
- int p2a = !(nPage2 && !n80Store);
- int p2b = nPage2 && !n80Store;
+ int p2a = !(bPage2 && !b80Store) ? 1 : 0;
+ int p2b = (bPage2 && !b80Store) ? 1 : 0;
- if (nHires) // hires?
+ WORD nAddressP = 0; // Page bits
+ if (bHires) // hires?
{
// Y: insert hires-only address bits
//
- nAddress |= v_A << 10; // a10
- nAddress |= v_B << 11; // a11
- nAddress |= v_C << 12; // a12
- g_PartialV = nAddress - g_PartialH;
-
- nAddress |= p2a << 13; // a13
- nAddress |= p2b << 14; // a14
+ nAddressV |= v_A << 10; // a10
+ nAddressV |= v_B << 11; // a11
+ nAddressV |= v_C << 12; // a12
+ nAddressP |= p2a << 13; // a13
+ nAddressP |= p2b << 14; // a14
}
else
{
// N: insert text-only address bits
//
- g_PartialV = nAddress - g_PartialH;
-
- // Apple ][ (not //e) and HBL?
- //
- if (IS_APPLE2 && // Apple II only (UTAIIe:I-4,#5)
- !h_5 && (!h_4 || !h_3)) // HBL (UTAIIe:8-10,F8.5)
- {
- nAddress |= 1 << 12; // Y: a12 (add $1000 to address!)
- g_PartialH |= 1 << 12;
- }
-
- nAddress |= p2a << 10; // a10
- nAddress |= p2b << 11; // a11
+ nAddressP |= p2a << 10; // a10
+ nAddressP |= p2b << 11; // a11
}
// VBL' = v_4' | v_3' = (v_4 & v_3)' (UTAIIe:5-10,#3)
- return static_cast(nAddress);
+ if (videoScannerAddr == VS_PartialAddrH)
+ return nAddressH;
+
+ if (videoScannerAddr == VS_PartialAddrV)
+ return nAddressV;
+
+ return nAddressP | nAddressV | nAddressH;
}
//===========================================================================
@@ -903,7 +892,7 @@ bool VideoGetVblBar(const DWORD uExecutedCycles)
int nCycles = CpuGetCyclesThisVideoFrame(uExecutedCycles);
// calculate video parameters according to display standard
- const int kScanLines = bVideoScannerNTSC ? kNTSCScanLines : kPALScanLines;
+ const int kScanLines = g_bVideoScannerNTSC ? kNTSCScanLines : kPALScanLines;
const int kScanCycles = kScanLines * kHClocks;
nCycles %= kScanCycles;
diff --git a/source/Video.h b/source/Video.h
index 3bacb655..bd064502 100644
--- a/source/Video.h
+++ b/source/Video.h
@@ -169,9 +169,8 @@ void VideoRedrawScreen (void);
void VideoRefreshScreen (uint32_t uRedrawWholeScreenVideoMode = 0, bool bRedrawWholeScreen = false);
void VideoReinitialize ();
void VideoResetState ();
-WORD VideoGetScannerAddressPartialV(DWORD nCycles);
-WORD VideoGetScannerAddressPartialH(DWORD nCycles);
-WORD VideoGetScannerAddress(DWORD nCycles);
+enum VideoScanner_e {VS_FullAddr, VS_PartialAddrV, VS_PartialAddrH};
+WORD VideoGetScannerAddress(DWORD nCycles, VideoScanner_e videoScannerAddr = VS_FullAddr);
bool VideoGetVblBar(DWORD uExecutedCycles);
bool VideoGetSW80COL(void);
From 74c0ca2cdec41f04d08a0be59eeb82a138bb4a59 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 6 Aug 2018 21:40:20 +0100
Subject: [PATCH 045/128] 1.27.7: Bump version & update History.txt & update
docs for new switches
---
bin/History.txt | 9 +++++++++
help/CommandLine.html | 9 ++++++++-
help/keyboard.html | 2 +-
help/savestate.html | 4 +++-
resource/Applewin.rc | 8 ++++----
5 files changed, 25 insertions(+), 7 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index 9bbe234a..5ae99a94 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -8,6 +8,15 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.7.0 - 6 Aug 2018
+---------------------
+. [Bug #564] Fixed 'Save State on Exit' not working correctly when there's a Configuration change to the hardware.
+. [Bug #556] Reverted default so that ALT+TAB is not hooked (#556)
+ - Support new command line switch: -hook-alt-tab to support hooking ALT+TAB.
+. [Bug #558] Reverted default so that ALT GR's fake LEFT CONTROL is not hooked (#558)
+ - Support new command line switch: -hook-altgr-control to suppess ALR GR's fake LEFT CONTROL.
+
+
1.27.6.0 - 28 Jul 2018
----------------------
. [Bug #570] Fixed lag when repeat-stepping in debugger.
diff --git a/help/CommandLine.html b/help/CommandLine.html
index f8c17778..73b56862 100644
--- a/help/CommandLine.html
+++ b/help/CommandLine.html
@@ -43,7 +43,14 @@
-no-printscreen-key
Prevent the PrintScreen key from being registered
-no-hook-system-key
- Prevent certain system key combinations from being hooked (to prevent the emulator from trapping ALT+ESC, ALT+SPACE, ALT+TAB and CTRL+ESC). This means that the equivalent Open Apple+<key> combinations won't work within the emulator.
+ Prevent certain system key combinations from being hooked (to prevent the emulator from trapping ALT+ESC, ALT+SPACE, ALT+TAB and CTRL+ESC). This means that the equivalent Open Apple+<key> combinations won't work within the emulator.
+ NB. This switch takes precedence over -hook-alt-tab and -hook-altgr-control.
+ -hook-alt-tab
+ By default the emulator doesn't hook ALT+TAB. Use this to allow Open Apple+TAB to be readable by the emulated machine.
+ -hook-altgr-control
+ By default the emulator doesn't suppress ALT GR's (Right Alt's) fake LEFT CONTROL. Use this to suppress this fake LEFT CONTROL to allow Closed Apple+CTRL+<key> to be readable by the emulated machine.
+ NB. Suppressing this fake LEFT CONTROL seems to prevent international keyboards from being able to type certain keys.
+
-use-real-printer
Enables Advanced configuration control to allow dumping to a real printer
-noreg
diff --git a/help/keyboard.html b/help/keyboard.html
index 5e6de04d..a228e2f1 100644
--- a/help/keyboard.html
+++ b/help/keyboard.html
@@ -29,7 +29,7 @@
The Solid Apple key was introduced on the Apple //e and later renamed to the
Option key. This key is emulated with the PC's
Right Alt
- key, which is in the same position as the Solid Apple key on the original //e.
+ key (or Alt Gr key), which is in the same position as the Solid Apple key on the original //e.
Numeric Keypad:
The numeric keypad, introduced on the Extended Keyboard //e, is emulated
diff --git a/help/savestate.html b/help/savestate.html
index 87847144..ff5595f5 100644
--- a/help/savestate.html
+++ b/help/savestate.html
@@ -13,7 +13,8 @@
The complete1 Apple //e state can be saved
to a PC file at any time. This can be useful for continuity across AppleWin
sessions or to help with games that don't have a save option.
-
This is controlled by the AppleWin Configuration tab labelled Advanced.
+
The state can optionally be automatically saved on AppleWin exit, and (automatically) restored on AppleWin restart.
+
This is all controlled by the AppleWin Configuration tab labeled Advanced.
Details:
The entire Apple //e state is saved to a human-readable (.yaml) file.
1
@@ -28,6 +29,7 @@
Mouse card
CP/M SoftCard
Parallel Printer card
+
Super Serial card
The following are not yet persisted to the file:
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index a71c4458..d93fa74e 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,6,0
- PRODUCTVERSION 1,27,6,0
+ FILEVERSION 1,27,7,0
+ PRODUCTVERSION 1,27,7,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 6, 0"
+ VALUE "FileVersion", "1, 27, 7, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 6, 0"
+ VALUE "ProductVersion", "1, 27, 7, 0"
END
END
BLOCK "VarFileInfo"
From 396c55d8a3ac36d85a4f8c8d9e10504f1375ea27 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 12 Aug 2018 12:48:08 +0100
Subject: [PATCH 046/128] Coverity: tackled a few CIDs (#470)
---
source/Applewin.cpp | 2 ++
source/DiskImageHelper.cpp | 70 ++++++++++++++++++++++----------------
source/ParallelPrinter.cpp | 19 +++++++++--
source/SerialComms.cpp | 1 +
4 files changed, 60 insertions(+), 32 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 46cfbda8..5fa5dce3 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1399,6 +1399,8 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
unsigned long fix_minor = g_AppleWinVersion[3] = pFixedFileInfo->dwFileVersionLS & 0xffff;
sprintf(VERSIONSTRING, "%d.%d.%d.%d", major, minor, fix, fix_minor); // potential buffer overflow
}
+
+ delete [] pVerInfoBlock;
}
LogFileOutput("AppleWin version: %s\n", VERSIONSTRING);
diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp
index 5aa50d5d..f1c1a4e1 100644
--- a/source/DiskImageHelper.cpp
+++ b/source/DiskImageHelper.cpp
@@ -1214,41 +1214,53 @@ ImageError_e CImageHelperBase::CheckZipFile(LPCTSTR pszImageFilename, ImageInfo*
return eIMAGE_ERROR_UNABLE_TO_OPEN_ZIP;
unz_global_info global_info;
- int nRes = unzGetGlobalInfo(hZipFile, &global_info);
- if (nRes != UNZ_OK)
- return eIMAGE_ERROR_ZIP;
-
- nRes = unzGoToFirstFile(hZipFile); // Only support 1st file in zip archive for now
- if (nRes != UNZ_OK)
- return eIMAGE_ERROR_ZIP;
-
unz_file_info file_info;
char szFilename[MAX_PATH];
memset(szFilename, 0, sizeof(szFilename));
- nRes = unzGetCurrentFileInfo(hZipFile, &file_info, szFilename, MAX_PATH, NULL, 0, NULL, 0);
- if (nRes != UNZ_OK)
- return eIMAGE_ERROR_ZIP;
+ int nRes = 0, nLen = 0;
- const UINT uFileSize = file_info.uncompressed_size;
- if (uFileSize > GetMaxImageSize())
- return eIMAGE_ERROR_BAD_SIZE;
-
- pImageInfo->pImageBuffer = new BYTE[uFileSize];
-
- nRes = unzOpenCurrentFile(hZipFile);
- if (nRes != UNZ_OK)
- return eIMAGE_ERROR_ZIP;
-
- int nLen = unzReadCurrentFile(hZipFile, pImageInfo->pImageBuffer, uFileSize);
- if (nLen < 0)
+ try
{
- unzCloseCurrentFile(hZipFile); // Must CloseCurrentFile before Close
- return eIMAGE_ERROR_UNSUPPORTED;
- }
+ nRes = unzGetGlobalInfo(hZipFile, &global_info);
+ if (nRes != UNZ_OK)
+ throw eIMAGE_ERROR_ZIP;
- nRes = unzCloseCurrentFile(hZipFile);
- if (nRes != UNZ_OK)
- return eIMAGE_ERROR_ZIP;
+ nRes = unzGoToFirstFile(hZipFile); // Only support 1st file in zip archive for now
+ if (nRes != UNZ_OK)
+ throw eIMAGE_ERROR_ZIP;
+
+ nRes = unzGetCurrentFileInfo(hZipFile, &file_info, szFilename, MAX_PATH, NULL, 0, NULL, 0);
+ if (nRes != UNZ_OK)
+ throw eIMAGE_ERROR_ZIP;
+
+ const UINT uFileSize = file_info.uncompressed_size;
+ if (uFileSize > GetMaxImageSize())
+ throw eIMAGE_ERROR_BAD_SIZE;
+
+ pImageInfo->pImageBuffer = new BYTE[uFileSize];
+
+ nRes = unzOpenCurrentFile(hZipFile);
+ if (nRes != UNZ_OK)
+ throw eIMAGE_ERROR_ZIP;
+
+ nLen = unzReadCurrentFile(hZipFile, pImageInfo->pImageBuffer, uFileSize);
+ if (nLen < 0)
+ {
+ unzCloseCurrentFile(hZipFile); // Must CloseCurrentFile before Close
+ throw eIMAGE_ERROR_UNSUPPORTED;
+ }
+
+ nRes = unzCloseCurrentFile(hZipFile);
+ if (nRes != UNZ_OK)
+ throw eIMAGE_ERROR_ZIP;
+ }
+ catch (ImageError_e error)
+ {
+ if (hZipFile)
+ unzClose(hZipFile);
+
+ return error;
+ }
nRes = unzClose(hZipFile);
hZipFile = NULL;
diff --git a/source/ParallelPrinter.cpp b/source/ParallelPrinter.cpp
index 1c6db6bd..0916b083 100644
--- a/source/ParallelPrinter.cpp
+++ b/source/ParallelPrinter.cpp
@@ -29,6 +29,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Applewin.h"
+#include "Frame.h" // g_hFrameWindow
#include "Memory.h"
#include "ParallelPrinter.h"
#include "Registry.h"
@@ -234,14 +235,26 @@ char* Printer_GetFilename()
void Printer_SetFilename(char* prtFilename)
{
- if(*prtFilename)
+ if (*prtFilename)
+ {
strcpy(g_szPrintFilename, (const char *) prtFilename);
+ }
else //No registry entry is available
{
_tcsncpy(g_szPrintFilename, g_sProgramDir, MAX_PATH);
g_szPrintFilename[MAX_PATH - 1] = 0;
- _tcsncat(g_szPrintFilename, _T(DEFAULT_PRINT_FILENAME), MAX_PATH);
- RegSaveString(TEXT("Configuration"),REGVALUE_PRINTER_FILENAME,1,g_szPrintFilename);
+
+ // NB. _tcsncat_s() terminates program if buffer is too small! So continue to use manual buffer check & _tcsncat()
+
+ int nLen = sizeof(g_szPrintFilename) - strlen(g_szPrintFilename) - (sizeof(DEFAULT_PRINT_FILENAME)-1) - 1;
+ if (nLen < 0)
+ {
+ MessageBox(g_hFrameWindow, "Printer - SetFilename(): folder too deep", "Warning", MB_ICONWARNING | MB_OK);
+ return;
+ }
+
+ _tcsncat(g_szPrintFilename, DEFAULT_PRINT_FILENAME, sizeof(DEFAULT_PRINT_FILENAME)-1);
+ RegSaveString(REG_CONFIG, REGVALUE_PRINTER_FILENAME, 1, g_szPrintFilename);
}
}
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index 77302924..ac410d19 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -216,6 +216,7 @@ bool CSuperSerialCard::CheckComm()
// have socket so attempt to bind it
SOCKADDR_IN saAddress;
+ memset(&saAddress, 0, sizeof(SOCKADDR_IN));
saAddress.sin_family = AF_INET;
saAddress.sin_port = htons(TCP_SERIAL_PORT); // TODO: get from registry / GUI
saAddress.sin_addr.s_addr = htonl(INADDR_ANY);
From 7d100a349bfcb4627cecad7660c5b977f96f5a56 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 9 Sep 2018 13:56:55 +0100
Subject: [PATCH 047/128] NTSC: Merge-squash from 'GH555-1-pixel' branch for
the 1 pixel shift for 14M video modes (#555)
---
source/Frame.cpp | 3 +-
source/Frame.h | 1 -
source/NTSC.cpp | 199 +++++++++++++++++++++++++++++++++++++++++++----
source/NTSC.h | 5 +-
source/Video.cpp | 8 +-
5 files changed, 189 insertions(+), 27 deletions(-)
diff --git a/source/Frame.cpp b/source/Frame.cpp
index b58379c0..eb4d5470 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Memory.h"
#include "Mockingboard.h"
#include "MouseInterface.h"
+#include "NTSC.h"
#include "ParallelPrinter.h"
#include "Pravets.h"
#include "Registry.h"
@@ -199,7 +200,7 @@ void SetAltEnterToggleFullScreen(bool mode)
UINT GetFrameBufferBorderlessWidth(void)
{
- static const UINT uFrameBufferBorderlessW = 560; // 560 = Double Hi-Res
+ static const UINT uFrameBufferBorderlessW = NTSC_GetFrameBufferBorderlessWidth(); // 560 = Double Hi-Res, +1 for GH#555
return uFrameBufferBorderlessW;
}
diff --git a/source/Frame.h b/source/Frame.h
index f5cace2d..c072520b 100644
--- a/source/Frame.h
+++ b/source/Frame.h
@@ -3,7 +3,6 @@
// 1.19.0.0 Hard Disk Status/Indicator Light
#define HD_LED 1
-
// Win32
extern HWND g_hFrameWindow;
extern int g_nViewportCX;
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index 29dd332c..f47bd337 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -23,13 +23,23 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Applewin.h"
#include "CPU.h" // CpuGetCyclesThisVideoFrame()
- #include "Frame.h" // FRAMEBUFFER_W FRAMEBUFFER_H
+ #include "Frame.h"
#include "Memory.h" // MemGetMainPtr() MemGetBankPtr()
#include "Video.h" // g_pFramebufferbits
#include "NTSC.h"
#include "NTSC_CharSet.h"
+
+// GH#555: Extend the 14M video modes by 1 pixel
+// . 14M (DHGR,DGR,80COL) are shifted right by 1 pixel, so zero out the left-most visible pixel.
+// . 7M (all other modes) are not shift right by 1 pixel, so zero out the right-most visible pixel.
+// NB. This 1 pixel shift is a workaround for the 14M video modes that actually start 7x 14M pixels to the left on *real h/w*.
+// . 7x 14M pixels early + 1x 14M pixel shifted right = 2 complete color phase rotations.
+// . ie. the 14M colors are correct, but being 1 pixel out is the closest we can get the 7M and 14M video modes to overlap.
+// . The alternative is to render the 14M correctly 7 pixels early, but have 7-pixel borders left (for 7M modes) or right (for 14M modes).
+#define EXTEND_14M_VIDEO_BY_1_PIXEL 1
+
#define NTSC_REMOVE_WHITE_RINGING 1 // 0 = theoritical dimmed white has chroma, 1 = pure white without chroma tinting
#define NTSC_REMOVE_BLACK_GHOSTING 1 // 1 = remove black smear/smudges carrying over
#define NTSC_REMOVE_GRAY_CHROMA 1 // 1 = remove all chroma in gray1 and gray2
@@ -120,6 +130,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// "There are exactly 17030 (65 x 262) 6502 cycles in every television scan of an American Apple."
#define VIDEO_SCANNER_MAX_HORZ 65 // TODO: use Video.cpp: kHClocks
#define VIDEO_SCANNER_MAX_VERT 262 // TODO: use Video.cpp: kNTSCScanLines
+ static const int VIDEO_SCANNER_6502_CYCLES = VIDEO_SCANNER_MAX_HORZ * VIDEO_SCANNER_MAX_VERT;
#define VIDEO_SCANNER_HORZ_COLORBURST_BEG 12
#define VIDEO_SCANNER_HORZ_COLORBURST_END 16
@@ -440,6 +451,17 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
static void updateScreenText40 ( long cycles6502 );
static void updateScreenText80 ( long cycles6502 );
+//===========================================================================
+// NB. This func only exists so that EXTEND_14M_VIDEO_BY_1_PIXEL only needs to exist in this cpp file!
+UINT NTSC_GetFrameBufferBorderlessWidth(void)
+{
+#if !EXTEND_14M_VIDEO_BY_1_PIXEL
+ return 560; // 560 = Double Hi-Res
+#else
+ return 561; // 560 = Double Hi-Res, +1 for GH#555
+#endif
+}
+
//===========================================================================
static void set_csbits()
{
@@ -657,13 +679,19 @@ inline void updateFramebufferMonitorDoubleScanline( uint16_t signal, bgra_t *pTa
}
#endif
+//===========================================================================
+inline bool GetColorBurst( void )
+{
+ return g_nColorBurstPixels >= 2;
+}
+
//===========================================================================
// NB. g_nLastColumnPixelNTSC = bits.b13 will be superseded by these parent funcs which use bits.b14:
// . updateScreenDoubleHires80(), updateScreenDoubleLores80(), updateScreenText80()
inline void updatePixels( uint16_t bits )
{
- if (g_nColorBurstPixels < 2)
+ if (!GetColorBurst())
{
/* #1 of 7 */
g_pFuncUpdateBnWPixel(bits & 1); bits >>= 1;
@@ -716,27 +744,70 @@ inline void updatePixels( uint16_t bits )
}
//===========================================================================
+
+#if !EXTEND_14M_VIDEO_BY_1_PIXEL
+// NOTE: This writes out-of-bounds for a 560x384 framebuffer
inline void updateVideoScannerHorzEOL()
{
if (VIDEO_SCANNER_MAX_HORZ == ++g_nVideoClockHorz)
{
if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
{
- //VIDEO_DRAW_ENDLINE();
- if (g_nColorBurstPixels < 2)
+ if (!GetColorBurst())
{
- // NOTE: This writes out-of-bounds for a 560x384 framebuffer
+ // Only for: VF_TEXT && !VF_MIXED (ie. full 24-row TEXT40 or TEXT80)
g_pFuncUpdateBnWPixel(g_nLastColumnPixelNTSC);
g_pFuncUpdateBnWPixel(0);
g_pFuncUpdateBnWPixel(0);
- g_pFuncUpdateBnWPixel(0);
}
else
{
- // NOTE: This writes out-of-bounds for a 560x384 framebuffer
g_pFuncUpdateHuePixel(g_nLastColumnPixelNTSC);
g_pFuncUpdateHuePixel(0);
g_pFuncUpdateHuePixel(0);
+ }
+ }
+
+ g_nVideoClockHorz = 0;
+
+ if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
+ {
+ g_nVideoClockVert = 0;
+
+ updateFlashRate();
+ }
+
+ if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
+ {
+ updateVideoScannerAddress();
+ }
+ }
+}
+#endif
+
+//-------------------------------------
+
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+// NB. Only needed for video modes that are 14M and shift the color phase, ie:
+// . updateScreenDoubleHires80(), updateScreenDoubleLores80(), updateScreenText80()
+// NOTE: This writes out-of-bounds for a 560x384 framebuffer
+inline void updateVideoScannerHorzEOL_14M()
+{
+ if (VIDEO_SCANNER_MAX_HORZ == ++g_nVideoClockHorz)
+ {
+ if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
+ {
+ if (!GetColorBurst())
+ {
+ // Only for: VF_TEXT && !VF_MIXED (ie. full 24-row TEXT40 or TEXT80)
+ g_pFuncUpdateBnWPixel(g_nLastColumnPixelNTSC); // 14M: Output a 561st dot
+ g_pFuncUpdateBnWPixel(0);
+ g_pFuncUpdateBnWPixel(0);
+ }
+ else
+ {
+ g_pFuncUpdateHuePixel(g_nLastColumnPixelNTSC); // 14M: Output a 561st dot
+ g_pFuncUpdateHuePixel(0);
g_pFuncUpdateHuePixel(0);
}
}
@@ -757,10 +828,63 @@ inline void updateVideoScannerHorzEOL()
}
}
+//-----------------
+
+// NOTE: This writes out-of-bounds for a 560x384 framebuffer
+inline void updateVideoScannerHorzEOL()
+{
+ if (VIDEO_SCANNER_MAX_HORZ == ++g_nVideoClockHorz)
+ {
+ if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
+ {
+ if ( !GetColorBurst() || // Only for: VF_TEXT && !VF_MIXED (ie. full 24-row TEXT40 or TEXT80)
+ (g_eVideoType == VT_MONO_CUSTOM) || (g_eVideoType == VT_MONO_AMBER) || (g_eVideoType == VT_MONO_GREEN) || (g_eVideoType == VT_MONO_WHITE) )
+ {
+ g_pFuncUpdateBnWPixel(0);
+ g_pFuncUpdateBnWPixel(0);
+
+ // 7M: Stop outputting video after 560 dots
+ *(UINT32*)&g_pVideoAddress[0] = 0;
+ *(UINT32*)&g_pVideoAddress[g_kFrameBufferWidth] = 0;
+ }
+ else
+ {
+ g_pFuncUpdateHuePixel(g_nLastColumnPixelNTSC);
+ g_pFuncUpdateHuePixel(0);
+
+ // 7M: Stop outputting video after 560 dots
+ *(UINT32*)&g_pVideoAddress[0] = 0;
+ *(UINT32*)&g_pVideoAddress[g_kFrameBufferWidth] = 0;
+ }
+ }
+
+ g_nVideoClockHorz = 0;
+
+ if (++g_nVideoClockVert == VIDEO_SCANNER_MAX_VERT)
+ {
+ g_nVideoClockVert = 0;
+
+ updateFlashRate();
+ }
+
+ if (g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY)
+ {
+ updateVideoScannerAddress();
+ }
+ }
+}
+#endif
+
//===========================================================================
inline void updateVideoScannerAddress()
{
- g_pVideoAddress = g_nVideoClockVert> 14) & 1;
+
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+ zeroPixel0_14M();
+#endif
}
}
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+ updateVideoScannerHorzEOL_14M();
+#else
updateVideoScannerHorzEOL();
+#endif
}
}
@@ -1217,6 +1375,7 @@ void updateScreenDoubleLores40 (long cycles6502) // wsUpdateVideo7MLores
uint16_t lo = getLoResBits( m );
uint16_t bits = g_aPixelDoubleMaskHGR[(0xFF & lo >> ((1 - (g_nVideoClockHorz & 1)) * 2)) & 0x7F]; // Optimization: hgrbits
updatePixels( bits );
+ // NB. No zeroPixel0_14M(), since no color phase shift (or use of g_nLastColumnPixelNTSC)
}
}
updateVideoScannerHorzEOL();
@@ -1258,9 +1417,18 @@ void updateScreenDoubleLores80 (long cycles6502) // wsUpdateVideoDblLores
uint16_t bits = (main << 7) | (aux & 0x7f);
updatePixels( bits );
g_nLastColumnPixelNTSC = (bits >> 14) & 1;
+
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+ zeroPixel0_14M();
+#endif
}
}
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+ updateVideoScannerHorzEOL_14M();
+#else
updateVideoScannerHorzEOL();
+#endif
+
}
}
@@ -1404,9 +1572,18 @@ void updateScreenText80 (long cycles6502)
bits = (bits << 1) | g_nLastColumnPixelNTSC; // GH#555: Align TEXT80 chars with DHGR
updatePixels( bits );
g_nLastColumnPixelNTSC = (bits >> 14) & 1;
+
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+ zeroPixel0_14M();
+#endif
}
}
+#if EXTEND_14M_VIDEO_BY_1_PIXEL
+ updateVideoScannerHorzEOL_14M();
+#else
updateVideoScannerHorzEOL();
+#endif
+
}
}
@@ -1824,12 +2001,6 @@ void NTSC_VideoRedrawWholeScreen( void )
#endif
}
-//===========================================================================
-bool NTSC_GetColorBurst( void )
-{
- return (g_nColorBurstPixels < 2) ? false : true;
-}
-
//===========================================================================
static bool CheckVideoTables2( eApple2Type type, uint32_t mode )
diff --git a/source/NTSC.h b/source/NTSC.h
index 50ea29d1..d81f283b 100644
--- a/source/NTSC.h
+++ b/source/NTSC.h
@@ -1,6 +1,3 @@
-// Constants
- const int VIDEO_SCANNER_6502_CYCLES = 17030;
-
// Globals (Public)
extern uint16_t g_nVideoClockVert;
extern uint16_t g_nVideoClockHorz;
@@ -19,4 +16,4 @@
extern void NTSC_VideoInitChroma();
extern void NTSC_VideoUpdateCycles( long cycles6502 );
extern void NTSC_VideoRedrawWholeScreen( void );
- extern bool NTSC_GetColorBurst( void );
+ extern UINT NTSC_GetFrameBufferBorderlessWidth( void );
diff --git a/source/Video.cpp b/source/Video.cpp
index c5808efa..d5663f3b 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -567,6 +567,7 @@ void VideoRedrawScreen (void)
//===========================================================================
// TC: Hacky-fix for GH#341 - better to draw to the correct position in the framebuffer to start with! (in NTSC.cpp)
+// . NB. Now the dx is corrected in NTSC.cpp, updateVideoScannerAddress()
static void VideoFrameBufferAdjust(int& xSrc, int& ySrc, bool bInvertY=false)
{
int dx=0, dy=0;
@@ -574,15 +575,8 @@ static void VideoFrameBufferAdjust(int& xSrc, int& ySrc, bool bInvertY=false)
if (g_eVideoType == VT_MONO_TV || g_eVideoType == VT_COLOR_TV)
{
// Adjust the src locations for the NTSC video modes
- dx = 2;
dy = -1;
}
- else if (g_eVideoType == VT_COLOR_MONITOR)
- {
- //if ((g_uVideoMode & VF_TEXT) == 0) // NB. Not sufficient, eg. ANSI STORY...
- if ( NTSC_GetColorBurst() == true ) // ANSI STORY (end credits): split DGR/TEXT80/DGR on scanline
- dx = 2;
- }
if (bInvertY)
dy =- dy;
From 39f91c552c1848a893ec2fd1b204ead7993927eb Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 9 Sep 2018 15:41:04 +0100
Subject: [PATCH 048/128] NTSC (#555) . For the 14M video modes
(DHGR,DGR,80COL), start rendering 1x 14M pixel early to account for these
video modes being shifted right by 1 pixel . Revert the display width back to
560 by disabling EXTEND_14M_VIDEO_BY_1_PIXEL
---
source/NTSC.cpp | 20 ++++++++++++++++----
1 file changed, 16 insertions(+), 4 deletions(-)
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index f47bd337..007ea275 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -38,7 +38,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
// . 7x 14M pixels early + 1x 14M pixel shifted right = 2 complete color phase rotations.
// . ie. the 14M colors are correct, but being 1 pixel out is the closest we can get the 7M and 14M video modes to overlap.
// . The alternative is to render the 14M correctly 7 pixels early, but have 7-pixel borders left (for 7M modes) or right (for 14M modes).
-#define EXTEND_14M_VIDEO_BY_1_PIXEL 1
+#define EXTEND_14M_VIDEO_BY_1_PIXEL 0
#define NTSC_REMOVE_WHITE_RINGING 1 // 0 = theoritical dimmed white has chroma, 1 = pure white without chroma tinting
#define NTSC_REMOVE_BLACK_GHOSTING 1 // 1 = remove black smear/smudges carrying over
@@ -878,12 +878,25 @@ inline void updateVideoScannerHorzEOL()
//===========================================================================
inline void updateVideoScannerAddress()
{
- g_pVideoAddress = g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY ? g_pScanLines[2*g_nVideoClockVert] : g_pScanLines[0];
+ g_pVideoAddress = g_nVideoClockVert < VIDEO_SCANNER_Y_DISPLAY ? g_pScanLines[2*g_nVideoClockVert] : g_pScanLines[0];
// Adjust, as these video styles have 2x 14M pixels of pre-render
// NB. For VT_COLOR_MONITOR, also check color-burst so that TEXT and MIXED(HGR+TEXT) render the TEXT at the same offset (GH#341)
if (g_eVideoType == VT_MONO_TV || g_eVideoType == VT_COLOR_TV || (g_eVideoType == VT_COLOR_MONITOR && GetColorBurst()))
- g_pVideoAddress = (bgra_t*) ((UINT32*)g_pVideoAddress - 2);
+ g_pVideoAddress -= 2;
+
+ // GH#555: For the 14M video modes (DHGR,DGR,80COL), start rendering 1x 14M pixel early to account for these video modes being shifted right by 1 pixel
+ // NB. This 1 pixel shift right is a workaround for the 14M video modes that actually start 7x 14M pixels to the left on *real h/w*.
+ // . 7x 14M pixels early + 1x 14M pixel shifted right = 2 complete color phase rotations.
+ // . ie. the 14M colors are correct, but being 1 pixel out is the closest we can get the 7M and 14M video modes to overlap.
+ // . The alternative is to render the 14M correctly 7 pixels early, but have 7-pixel borders left (for 7M modes) or right (for 14M modes).
+ if ((g_pFuncUpdateGraphicsScreen == updateScreenDoubleHires80) ||
+ (g_pFuncUpdateGraphicsScreen == updateScreenDoubleLores80) ||
+ (g_pFuncUpdateGraphicsScreen == updateScreenText80) ||
+ (g_nVideoMixed && g_nVideoClockVert >= VIDEO_SCANNER_Y_MIXED && g_pFuncUpdateTextScreen == updateScreenText80))
+ {
+ g_pVideoAddress -= 1;
+ }
g_nColorPhaseNTSC = INITIAL_COLOR_PHASE;
g_nLastColumnPixelNTSC = 0;
@@ -1819,7 +1832,6 @@ void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
for (int y = 0; y < (VIDEO_SCANNER_Y_DISPLAY*2); y++)
{
uint32_t offset = sizeof(bgra_t) * GetFrameBufferWidth() * ((GetFrameBufferHeight() - 1) - y - GetFrameBufferBorderHeight()) + (sizeof(bgra_t) * GetFrameBufferBorderWidth());
-// offset -= sizeof(bgra_t); // GH#555: Start 1 RGBA pixel before frame to account for g_nLastColumnPixelNTSC // TC: revert as lose half an HGR pixel on left-edge
g_pScanLines[y] = (bgra_t*) (g_pFramebufferbits + offset);
}
From 18622cb11357014886842e30c26f38d6588ee6d7 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 9 Sep 2018 15:50:55 +0100
Subject: [PATCH 049/128] 1.27.8: Bump version & update History.txt
---
bin/History.txt | 5 +++++
resource/Applewin.rc | 8 ++++----
2 files changed, 9 insertions(+), 4 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index 5ae99a94..7eaeeef0 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -8,6 +8,11 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.8.0 - 9 Sep 2018
+---------------------
+. [Bug #555] Fix for showing 559th DHGR/DGR/TEXT80 vertical column (retaining 560-pixel display width).
+
+
1.27.7.0 - 6 Aug 2018
---------------------
. [Bug #564] Fixed 'Save State on Exit' not working correctly when there's a Configuration change to the hardware.
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index d93fa74e..88b11363 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,7,0
- PRODUCTVERSION 1,27,7,0
+ FILEVERSION 1,27,8,0
+ PRODUCTVERSION 1,27,8,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 7, 0"
+ VALUE "FileVersion", "1, 27, 8, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 7, 0"
+ VALUE "ProductVersion", "1, 27, 8, 0"
END
END
BLOCK "VarFileInfo"
From a15e5a47f60c988c9ef0c60e35fb59235cccdc6f Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 10 Sep 2018 21:28:08 +0100
Subject: [PATCH 050/128] MemGetAuxPtr(): Refactor & added comment about video
scanner fetching aux from the 1st 64K aux bank (#520)
---
source/Memory.cpp | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 70e308ea..f53719aa 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -1095,11 +1095,14 @@ LPBYTE MemGetAuxPtr(const WORD offset)
: memaux+offset;
#ifdef RAMWORKS
- if ( ((SW_PAGE2 && SW_80STORE) || VideoGetSW80COL()) &&
- ( ( ((offset & 0xFF00)>=0x0400) &&
- ((offset & 0xFF00)<=0x0700) ) ||
- ( SW_HIRES && ((offset & 0xFF00)>=0x2000) &&
- ((offset & 0xFF00)<=0x3F00) ) ) ) {
+ // Video scanner (for 14M video modes) always fetches from 1st 64K aux bank (UTAIIe ref?)
+ if (((SW_PAGE2 && SW_80STORE) || VideoGetSW80COL()) &&
+ (
+ ( ((offset & 0xFF00)>=0x0400) && ((offset & 0xFF00)<=0x0700) ) ||
+ ( SW_HIRES && ((offset & 0xFF00)>=0x2000) && ((offset & 0xFF00)<=0x3F00) )
+ )
+ )
+ {
lpMem = (memshadow[(offset >> 8)] == (RWpages[0]+(offset & 0xFF00)))
? mem+offset
: RWpages[0]+offset;
From a2d05ca3861eccfa7c4cadbfc0bc51291b7cc754 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 16 Sep 2018 22:02:35 +0100
Subject: [PATCH 051/128] mem(cache): provide more details about how the
mem(cache) and associated variables work, eg. when reading/writing to the
same or different memory banks
---
source/Memory.cpp | 94 +++++++++++++++++++++++++++++++++++------------
source/NTSC.cpp | 2 +-
2 files changed, 71 insertions(+), 25 deletions(-)
diff --git a/source/Memory.cpp b/source/Memory.cpp
index f53719aa..4313cae6 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -79,7 +79,7 @@ MEMORY MANAGEMENT SOFT SWITCHES
$C000 W 80STOREOFF Allow page2 to switch video page1 page2
$C001 W 80STOREON Allow page2 to switch main & aux video memory
$C002 W RAMRDOFF Read enable main memory from $0200-$BFFF
- $C003 W RAMDRON Read enable aux memory from $0200-$BFFF
+ $C003 W RAMRDON Read enable aux memory from $0200-$BFFF
$C004 W RAMWRTOFF Write enable main memory from $0200-$BFFF
$C005 W RAMWRTON Write enable aux memory from $0200-$BFFF
$C006 W INTCXROMOFF Enable slot ROM from $C100-$C7FF (but $C800-$CFFF depends on INTC8ROM)
@@ -129,29 +129,44 @@ SOFT SWITCH STATUS FLAGS
// Notes
// -----
//
-// mem
-// - a copy of the memimage ptr
-//
// memimage
// - 64KB
+//
+// mem
+// (a pointer to memimage 64KB)
+// - a 64KB r/w memory cache
// - reflects the current readable memory in the 6502's 64K address space
// . excludes $Cxxx I/O memory
// . could be a mix of RAM/ROM, main/aux, etc
+// - may also reflect the current writeable memory (on a 256-page granularity) if the write page addr == read page addr
+// . for this case, the memdirty flag(s) are valid
+// . when writes instead occur to backing-store, then memdirty flag(s) can be ignored
//
// memmain, memaux
-// - physical contiguous 64KB RAM for main & aux respectively
+// - physical contiguous 64KB "backing-store" for main & aux respectively
+// - NB. 4K bank1 BSR is at $C000-$CFFF
//
// memwrite
-// - 1 ptr entry per 256-byte page
+// - 1 pointer entry per 256-byte page
// - used to write to a page
+// - if RD & WR point to the same 256-byte RAM page, then memwrite will point to the page in 'mem'
+// . ie. when SW_AUXREAD==SW_AUXWRITE, or 4K-BSR is r/w, or 8K BSR is r/w, or SW_80STORE=1
+// . So 'mem' remains correct for both r&w operations, but the physical 64K mem block becomes stale
+// - if RD & WR point to different 256-byte pages, then memwrite will point to the page in the physical 64K mem block
+// . writes will still set the dirty flag (but can be ignored)
+// . UpdatePaging() ignores this, as it only copies back to the physical 64K mem block when memshadow changes (for that 256-byte page)
//
// memdirty
// - 1 byte entry per 256-byte page
// - set when a write occurs to a 256-byte page
+// - indicates that 'mem' (ie. the cache) is out-of-sync with the "physical" 64K backing-store memory
+// - NB. a page's dirty flag is only useful(valid) when 'mem' is used for both read & write for the corresponding page
+// When they differ, then writes go directly to the backing-store.
+// . In this case, the dirty flag will just force a memcpy() to the same address in backing-store.
//
// memshadow
-// - 1 ptr entry per 256-byte page
-// - reflects how 'mem' is setup
+// - 1 pointer entry per 256-byte page
+// - reflects how 'mem' is setup for read operations (at a 256-byte granularity)
// . EG: if ALTZP=1, then:
// . mem will have copies of memaux's ZP & stack
// . memshadow[0] = &memaux[0x0000]
@@ -817,19 +832,6 @@ static bool IsCardInSlot(const UINT uSlot)
//===========================================================================
-static void BackMainImage(void)
-{
- for (UINT loop = 0; loop < 256; loop++)
- {
- if (memshadow[loop] && ((*(memdirty+loop) & 1) || (loop <= 1)))
- CopyMemory(memshadow[loop], memimage+(loop << 8), 256);
-
- *(memdirty+loop) &= ~1;
- }
-}
-
-//===========================================================================
-
DWORD GetMemMode(void)
{
return memmode;
@@ -925,7 +927,7 @@ static void UpdatePaging(BOOL initialize)
for (loop = 0xC0; loop < 0xC8; loop++)
{
- memdirty[loop] = 0; // ROM can't be dirty
+ memdirty[loop] = 0; // mem(cache) can't be dirty for ROM (but STA $Csnn will set the dirty flag)
const UINT uSlotOffset = (loop & 0x0f) * 0x100;
if (loop == 0xC3)
memshadow[loop] = (SW_SLOTC3ROM && !SW_INTCXROM) ? pCxRomPeripheral+uSlotOffset // C300..C3FF - Slot 3 ROM (all 0x00's)
@@ -937,7 +939,7 @@ static void UpdatePaging(BOOL initialize)
for (loop = 0xC8; loop < 0xD0; loop++)
{
- memdirty[loop] = 0; // ROM can't be dirty (but STA $CFFF will set the dirty flag)
+ memdirty[loop] = 0; // mem(cache) can't be dirty for ROM (but STA $Cnnn will set the dirty flag)
const UINT uRomOffset = (loop & 0x0f) * 0x100;
memshadow[loop] = (!SW_INTCXROM && !INTC8ROM) ? pCxRomPeripheral+uRomOffset // C800..CFFF - Peripheral ROM (GH#486)
: pCxRomInternal+uRomOffset; // C800..CFFF - Internal ROM
@@ -1070,6 +1072,19 @@ bool MemCheckINTCXROM()
//===========================================================================
+static void BackMainImage(void)
+{
+ for (UINT loop = 0; loop < 256; loop++)
+ {
+ if (memshadow[loop] && ((*(memdirty+loop) & 1) || (loop <= 1)))
+ CopyMemory(memshadow[loop], mem+(loop << 8), 256);
+
+ *(memdirty+loop) &= ~1;
+ }
+}
+
+//===========================================================================
+
static LPBYTE MemGetPtrBANK1(const WORD offset, const LPBYTE pMemBase)
{
if ((offset & 0xF000) != 0xC000) // Requesting RAM at physical addr $Cxxx (ie. 4K RAM BANK1)
@@ -1114,6 +1129,34 @@ LPBYTE MemGetAuxPtr(const WORD offset)
//-------------------------------------
+// if memshadow == memmain
+// so RD memmain
+// case: RD == WR
+// so RD(mem),WR(mem)
+// so 64K memmain could be incorrect
+// *therefore mem is correct
+// case: RD != WR
+// so RD(mem),WR(memaux)
+// doesn't matter since RD != WR, then it's guaranteed that memaux is correct
+// *therefore either mem or memmain is correct
+// else ; memshadow != memmain
+// so RD memaux (or ROM)
+// case: RD == WR
+// so RD(mem),WR(mem)
+// so 64K memaux could be incorrect
+// *therefore memmain is correct
+// case: RD != WR
+// so RD(mem),WR(memmain)
+// doesn't matter since RD != WR, then it's guaranteed that memmain is correct
+// *therefore memmain is correct
+//
+// *OR*
+//
+// Is the mem(cache) setup to read (via memshadow) from memmain?
+// . if yes, then return the mem(cache) address as writes (via memwrite) may've made the mem(cache) dirty.
+// . if no, then return memmain, as the mem(cache) isn't involved in memmain (any writes will go directly to this backing-store).
+//
+
LPBYTE MemGetMainPtr(const WORD offset)
{
LPBYTE lpMem = MemGetPtrBANK1(offset, memmain);
@@ -1127,6 +1170,9 @@ LPBYTE MemGetMainPtr(const WORD offset)
//===========================================================================
+// Used by:
+// . Savestate: MemSaveSnapshotMemory(), MemLoadSnapshotAux()
+// . Debugger : CmdMemorySave(), CmdMemoryLoad()
LPBYTE MemGetBankPtr(const UINT nBank)
{
BackMainImage(); // Flush any dirty pages to back-buffer
@@ -1784,7 +1830,7 @@ _done_saturn:
// IT DOES SO.
//
// NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
- // - although any date-race is probably a bug in the 6502 code too.
+ // - although any data-race is probably a bug in the 6502 code too.
if ((address >= 4) && (address <= 5) &&
((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
modechanging = 1;
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index 007ea275..ae0b1503 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -24,7 +24,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Applewin.h"
#include "CPU.h" // CpuGetCyclesThisVideoFrame()
#include "Frame.h"
- #include "Memory.h" // MemGetMainPtr() MemGetBankPtr()
+ #include "Memory.h" // MemGetMainPtr() MemGetAuxPtr()
#include "Video.h" // g_pFramebufferbits
#include "NTSC.h"
From 53d1d04988530b4a634b54acd84cfc93ec74ae53 Mon Sep 17 00:00:00 2001
From: TomCh
Date: Tue, 2 Oct 2018 22:08:54 +0100
Subject: [PATCH 052/128] DiskII: Support partial nibble reads for very close
disk latch reads (#586)
Support partial reads for sequential accesses of 6 or less cycles.
- And 31 or less cycles when in "Disk Access Speed" = "Authentic Speed"
Save-state support for partial read cycle (Disk][ unit v3)
Added boot-time logging for Phasor1.dsk (ProDOS 1.1.1)
---
source/Applewin.cpp | 7 +++++--
source/Disk.cpp | 31 ++++++++++++++++++++++++++++++-
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 5fa5dce3..6ec6a619 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -129,13 +129,16 @@ void LogFileTimeUntilFirstKeyReadReset(void)
}
// Log the time from emulation restart/reboot until the first key read: BIT $C000
-// . NB. AZTEC.DSK does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message
+// . AZTEC.DSK (DOS 3.3) does prior LDY $C000 reads, but the BIT $C000 is at the "Press any key" message
+// . Phasor1.dsk / ProDOS 1.1.1: PC=E797: B1 50: LDA ($50),Y / "Select an Option:" message
void LogFileTimeUntilFirstKeyRead(void)
{
if (!g_fh || bLogKeyReadDone)
return;
- if (mem[regs.pc-3] != 0x2C) // bit $c000
+ if ( (mem[regs.pc-3] != 0x2C) // AZTEC: bit $c000
+ && !((regs.pc-2) == 0xE797 && mem[regs.pc-2] == 0xB1 && mem[regs.pc-1] == 0x50) // Phasor1: lda ($50),y
+ )
return;
DWORD dwTime = GetTickCount() - dwLogKeyReadTickStart;
diff --git a/source/Disk.cpp b/source/Disk.cpp
index f81002a9..d3998ae7 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -86,6 +86,7 @@ static WORD phases = 0; // state bits for stepper magnet phases 0 - 3
static bool g_bSaveDiskImage = true; // Save the DiskImage name to Registry
static UINT g_uSlot = 0;
static unsigned __int64 g_uDiskLastCycle = 0;
+static unsigned __int64 g_uDiskLastReadLatchCycle = 0;
static FormatTrack g_formatTrack;
static bool IsDriveValid( const int iDrive );
@@ -895,7 +896,23 @@ static void __stdcall DiskReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULO
// but Sherwood Forest sets shift mode and reads with the drive off, so don't check for now
if (!floppywritemode)
{
+ const ULONG nReadCycleDiff = (ULONG) (g_nCumulativeCycles - g_uDiskLastReadLatchCycle);
+
+ // Support partial nibble read if disk reads are very close: (GH#582)
+ // . 6 cycles (1st->2nd read) for DOS 3.3 / $BD34: "read with delays to see if disk is spinning." (Beneath Apple DOS)
+ // . 6 cycles (1st->2nd read) for Curse of the Azure Bonds (loop to see if disk is spinning)
+ // . 31 cycles is the max for a partial 8-bit nibble
+ const ULONG kReadAccessThreshold = enhancedisk ? 6 : 31;
+
+ if (nReadCycleDiff <= kReadAccessThreshold)
+ {
+ UINT invalidBits = 8 - (nReadCycleDiff / 4); // 4 cycles per bit-cell
+ floppylatch = *(pFloppy->trackimage + pFloppy->byte) >> invalidBits;
+ return; // Early return so don't update: g_uDiskLastReadLatchCycle & pFloppy->byte
+ }
+
floppylatch = *(pFloppy->trackimage + pFloppy->byte);
+ g_uDiskLastReadLatchCycle = g_nCumulativeCycles;
#if LOG_DISK_NIBBLES_READ
#if LOG_DISK_NIBBLES_USE_RUNTIME_VAR
@@ -959,6 +976,10 @@ void DiskReset(const bool bIsPowerCycle/*=false*/)
if (bIsPowerCycle) // GH#460
{
+ // NB. This doesn't affect the drive head (ie. drive's track position)
+ // . The initial machine start-up state is track=0, but after a power-cycle the track could be any value.
+ // . (For DiskII firmware, this results in a subtle extra latch read in this latter case, for the track!=0 case)
+
g_aFloppyDrive[DRIVE_1].spinning = 0;
g_aFloppyDrive[DRIVE_1].writelight = 0;
g_aFloppyDrive[DRIVE_2].spinning = 0;
@@ -1363,7 +1384,8 @@ int DiskSetSnapshot_v1(const SS_CARD_DISK2* const pSS)
// Unit version history:
// 2: Added: Format Track state & DiskLastCycle
-static const UINT kUNIT_VERSION = 2;
+// 3: Added: DiskLastReadLatchCycle
+static const UINT kUNIT_VERSION = 3;
#define SS_YAML_VALUE_CARD_DISK2 "Disk]["
@@ -1375,6 +1397,7 @@ static const UINT kUNIT_VERSION = 2;
#define SS_YAML_KEY_FLOPPY_MOTOR_ON "Floppy Motor On"
#define SS_YAML_KEY_FLOPPY_WRITE_MODE "Floppy Write Mode"
#define SS_YAML_KEY_LAST_CYCLE "Last Cycle"
+#define SS_YAML_KEY_LAST_READ_LATCH_CYCLE "Last Read Latch Cycle"
#define SS_YAML_KEY_DISK2UNIT "Unit"
#define SS_YAML_KEY_FILENAME "Filename"
@@ -1429,6 +1452,7 @@ void DiskSaveSnapshot(class YamlSaveHelper& yamlSaveHelper)
yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_MOTOR_ON, floppymotoron == TRUE);
yamlSaveHelper.SaveBool(SS_YAML_KEY_FLOPPY_WRITE_MODE, floppywritemode == TRUE);
yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LAST_CYCLE, g_uDiskLastCycle); // v2
+ yamlSaveHelper.SaveHexUint64(SS_YAML_KEY_LAST_READ_LATCH_CYCLE, g_uDiskLastReadLatchCycle); // v3
g_formatTrack.SaveSnapshot(yamlSaveHelper); // v2
DiskSaveSnapshotDisk2Unit(yamlSaveHelper, DRIVE_1);
@@ -1534,6 +1558,11 @@ bool DiskLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT vers
g_formatTrack.LoadSnapshot(yamlLoadHelper);
}
+ if (version >= 3)
+ {
+ g_uDiskLastReadLatchCycle = yamlLoadHelper.LoadUint64(SS_YAML_KEY_LAST_READ_LATCH_CYCLE);
+ }
+
// Eject all disks first in case Drive-2 contains disk to be inserted into Drive-1
for(UINT i=0; i
Date: Tue, 2 Oct 2018 22:21:11 +0100
Subject: [PATCH 053/128] 1.27.9: Bump version & update History.txt
---
bin/History.txt | 6 ++++++
resource/Applewin.rc | 8 ++++----
2 files changed, 10 insertions(+), 4 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index 7eaeeef0..152f821a 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -8,6 +8,12 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.9.0 - 2 Oct 2018
+---------------------
+. [Bug #582] Support for partial disk II latch reads when accesses are very close.
+ - Fixes Curse of the Azure Bonds & Pool of Radiance (saving characters and creating disks).
+
+
1.27.8.0 - 9 Sep 2018
---------------------
. [Bug #555] Fix for showing 559th DHGR/DGR/TEXT80 vertical column (retaining 560-pixel display width).
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index 88b11363..8d985736 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,8,0
- PRODUCTVERSION 1,27,8,0
+ FILEVERSION 1,27,9,0
+ PRODUCTVERSION 1,27,9,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 8, 0"
+ VALUE "FileVersion", "1, 27, 9, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 8, 0"
+ VALUE "ProductVersion", "1, 27, 9, 0"
END
END
BLOCK "VarFileInfo"
From 91a6227da1625bedc0fbb021e14cbacc293c23a9 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 13 Oct 2018 22:35:55 +0100
Subject: [PATCH 054/128] Debugger: Fixed disasm of branch targets <000 missing
leading zeros. (Fixes #587)
---
source/Debugger/Debugger_Display.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index eaf033dc..63a34037 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -1493,7 +1493,7 @@ int GetDisassemblyLine ( WORD nBaseAddress, DisasmLine_t & line_ )
if (! (bDisasmFormatFlags & DISASM_FORMAT_SYMBOL))
{
- pTarget = FormatAddress( nTarget, nOpbyte );
+ pTarget = FormatAddress( nTarget, (iOpmode != AM_R) ? nOpbyte : 3 ); // GH#587: For Bcc opcodes, pretend it's a 3-byte opcode to print a 16-bit target addr
}
// sprintf( sTarget, g_aOpmodes[ iOpmode ]._sFormat, pTarget );
From 46274d4d1c45fc28ac7701ddb61e9515c5f9dcfd Mon Sep 17 00:00:00 2001
From: TomCh
Date: Fri, 26 Oct 2018 11:23:30 -0700
Subject: [PATCH 055/128] Apple II: Language Card and Saturn support for slot-0
(PR #589)
Support for #408:
* added slot-0 LC and Saturn 128K for Apple II and II+
* added save-state support
- for slot-0 LC/Saturn, save the LC state in the slot-0 card, not the //e MMU; and switch to a new Apple2 unit ver2
* added g_Slot0, g_SlotAux
* added new LanguageCard.cpp/h to project and moved Saturn code into these new files.
* updated VS2013,2015,2017 projects
---
AppleWinExpress2008.vcproj | 8 +
AppleWinExpress2013.vcxproj | 2 +
AppleWinExpress2013.vcxproj.filters | 6 +
AppleWinExpress2015.vcxproj | 2 +
AppleWinExpress2015.vcxproj.filters | 6 +
AppleWinExpress2017.vcxproj | 2 +
AppleWinExpress2017.vcxproj.filters | 6 +
source/Applewin.cpp | 56 ++--
source/Applewin.h | 2 +
source/Common.h | 10 +-
source/Configuration/PageAdvanced.cpp | 4 +-
source/Debugger/Debugger_Display.cpp | 7 +-
source/LanguageCard.cpp | 376 ++++++++++++++++++++++++++
source/LanguageCard.h | 83 ++++++
source/Memory.cpp | 376 +++++++++++++++++---------
source/Memory.h | 30 +-
source/SaveState.cpp | 27 +-
source/SaveState_Structs_common.h | 8 +-
18 files changed, 824 insertions(+), 187 deletions(-)
create mode 100644 source/LanguageCard.cpp
create mode 100644 source/LanguageCard.h
diff --git a/AppleWinExpress2008.vcproj b/AppleWinExpress2008.vcproj
index 92fe61ea..1b926246 100644
--- a/AppleWinExpress2008.vcproj
+++ b/AppleWinExpress2008.vcproj
@@ -625,6 +625,14 @@
RelativePath=".\source\Keyboard.h"
>
+
+
+
+
diff --git a/AppleWinExpress2013.vcxproj b/AppleWinExpress2013.vcxproj
index 63aa1764..9b32be34 100644
--- a/AppleWinExpress2013.vcxproj
+++ b/AppleWinExpress2013.vcxproj
@@ -71,6 +71,7 @@
+
@@ -154,6 +155,7 @@
+
diff --git a/AppleWinExpress2013.vcxproj.filters b/AppleWinExpress2013.vcxproj.filters
index d1376eee..80023974 100644
--- a/AppleWinExpress2013.vcxproj.filters
+++ b/AppleWinExpress2013.vcxproj.filters
@@ -76,6 +76,9 @@
Source Files\Emulator
+
+ Source Files\Emulator
+ Source Files\Emulator
@@ -312,6 +315,9 @@
Source Files\Emulator
+
+ Source Files\Emulator
+ Source Files\Emulator
diff --git a/AppleWinExpress2015.vcxproj b/AppleWinExpress2015.vcxproj
index 4467abb4..329910e4 100644
--- a/AppleWinExpress2015.vcxproj
+++ b/AppleWinExpress2015.vcxproj
@@ -71,6 +71,7 @@
+
@@ -154,6 +155,7 @@
+
diff --git a/AppleWinExpress2015.vcxproj.filters b/AppleWinExpress2015.vcxproj.filters
index d1376eee..80023974 100644
--- a/AppleWinExpress2015.vcxproj.filters
+++ b/AppleWinExpress2015.vcxproj.filters
@@ -76,6 +76,9 @@
Source Files\Emulator
+
+ Source Files\Emulator
+ Source Files\Emulator
@@ -312,6 +315,9 @@
Source Files\Emulator
+
+ Source Files\Emulator
+ Source Files\Emulator
diff --git a/AppleWinExpress2017.vcxproj b/AppleWinExpress2017.vcxproj
index c1e10c1e..ce3cf6b1 100644
--- a/AppleWinExpress2017.vcxproj
+++ b/AppleWinExpress2017.vcxproj
@@ -71,6 +71,7 @@
+
@@ -154,6 +155,7 @@
+
diff --git a/AppleWinExpress2017.vcxproj.filters b/AppleWinExpress2017.vcxproj.filters
index baba23fc..d9a1afb6 100644
--- a/AppleWinExpress2017.vcxproj.filters
+++ b/AppleWinExpress2017.vcxproj.filters
@@ -76,6 +76,9 @@
Source Files\Emulator
+
+ Source Files\Emulator
+ Source Files\Emulator
@@ -312,6 +315,9 @@
Source Files\Emulator
+
+ Source Files\Emulator
+ Source Files\Emulator
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 6ec6a619..cb785c33 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -36,6 +36,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Frame.h"
#include "Harddisk.h"
#include "Joystick.h"
+#include "LanguageCard.h"
#include "Log.h"
#include "Memory.h"
#include "Mockingboard.h"
@@ -102,8 +103,10 @@ IPropertySheet& sg_PropertySheet = * new CPropertySheet;
CSuperSerialCard sg_SSC;
CMouseInterface sg_Mouse;
-SS_CARDTYPE g_Slot4 = CT_Empty;
-SS_CARDTYPE g_Slot5 = CT_Empty;
+SS_CARDTYPE g_Slot0 = CT_LanguageCard; // Just for Apple II or II+ or similar clones
+SS_CARDTYPE g_Slot4 = CT_Empty;
+SS_CARDTYPE g_Slot5 = CT_Empty;
+SS_CARDTYPE g_SlotAux = CT_Extended80Col; // For Apple //e and above
HANDLE g_hCustomRomF8 = INVALID_HANDLE_VALUE; // Cmd-line specified custom ROM at $F800..$FFFF
static bool g_bCustomRomF8Failed = false; // Set if custom ROM file failed
@@ -1145,6 +1148,8 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
LPSTR szImageName_harddisk[NUM_HARDDISKS] = {NULL,NULL};
LPSTR szSnapshotName = NULL;
const std::string strCmdLine(lpCmdLine); // Keep a copy for log ouput
+ UINT uRamWorksExPages = 0;
+ UINT uSaturnBanks = 0;
while (*lpCmdLine)
{
@@ -1249,37 +1254,30 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
#ifdef RAMWORKS
else if (strcmp(lpCmdLine, "-r") == 0) // RamWorks size [1..127]
{
- g_eMemType = MEM_TYPE_RAMWORKS;
-
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
- g_uMaxExPages = atoi(lpCmdLine);
- if (g_uMaxExPages > kMaxExMemoryBanks)
- g_uMaxExPages = kMaxExMemoryBanks;
+ uRamWorksExPages = atoi(lpCmdLine);
+ if (uRamWorksExPages > kMaxExMemoryBanks)
+ uRamWorksExPages = kMaxExMemoryBanks;
else
- if (g_uMaxExPages < 1)
- g_uMaxExPages = 1;
+ if (uRamWorksExPages < 1)
+ uRamWorksExPages = 1;
}
#endif
-#ifdef SATURN
else if (strcmp(lpCmdLine, "-saturn") == 0) // 64 = Saturn 64K (4 banks), 128 = Saturn 128K (8 banks)
{
- g_eMemType = MEM_TYPE_SATURN;
-
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
- // " The boards consist of 16K banks of memory
- // (4 banks for the 64K board,
- // 8 banks for the 128K), accessed one at a time"
- g_uSaturnTotalBanks = atoi(lpCmdLine) / 16; // number of 16K Banks [1..8]
- if (g_uSaturnTotalBanks > 8)
- g_uSaturnTotalBanks = 8;
+ // "The boards consist of 16K banks of memory (4 banks for the 64K board, 8 banks for the 128K), accessed one at a time" - Ref: "64K/128K RAM BOARD", Saturn Systems, Ch.1 Introduction(pg-5)
+ uSaturnBanks = atoi(lpCmdLine) / 16; // number of 16K Banks [1..8]
+ if (uSaturnBanks > Saturn128K::kMaxSaturnBanks)
+ uSaturnBanks = Saturn128K::kMaxSaturnBanks;
else
- if (g_uSaturnTotalBanks < 1)
- g_uSaturnTotalBanks = 1;
+ if (uSaturnBanks < 1)
+ uSaturnBanks = 1;
+
}
-#endif
else if (strcmp(lpCmdLine, "-f8rom") == 0) // Use custom 2K ROM at [$F800..$FFFF]
{
lpCmdLine = GetCurrArg(lpNextArg);
@@ -1459,6 +1457,22 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
LoadConfiguration();
LogFileOutput("Main: LoadConfiguration()\n");
+ // Apply the memory expansion switches after loading the Apple II machine type
+#ifdef RAMWORKS
+ if (uRamWorksExPages)
+ {
+ SetRamWorksMemorySize(uRamWorksExPages);
+ SetExpansionMemType(CT_RamWorksIII);
+ uRamWorksExPages = 0; // Don't reapply after a restart
+ }
+#endif
+ if (uSaturnBanks)
+ {
+ SetSaturnMemorySize(uSaturnBanks); // Set number of banks before constructing Saturn card
+ SetExpansionMemType(CT_Saturn128K);
+ uSaturnBanks = 0; // Don't reapply after a restart
+ }
+
DebugInitialize();
LogFileOutput("Main: DebugInitialize()\n");
diff --git a/source/Applewin.h b/source/Applewin.h
index a3732ecc..894cae02 100644
--- a/source/Applewin.h
+++ b/source/Applewin.h
@@ -49,8 +49,10 @@ extern bool g_bDisableDirectSound; // Cmd line switch: don't init DS (s
extern bool g_bDisableDirectSoundMockingboard; // Cmd line switch: don't init MB support
extern int g_nMemoryClearType; // Cmd line switch: use specific MIP (Memory Initialization Pattern)
+extern SS_CARDTYPE g_Slot0; // LC or Saturn in slot0
extern SS_CARDTYPE g_Slot4; // Mockingboard, Z80, Mouse in slot4
extern SS_CARDTYPE g_Slot5; // Mockingboard, Z80, in slot5
+extern SS_CARDTYPE g_SlotAux;
extern HANDLE g_hCustomRomF8; // NULL if no custom rom
diff --git a/source/Common.h b/source/Common.h
index c78af713..0bdfa9e4 100644
--- a/source/Common.h
+++ b/source/Common.h
@@ -20,7 +20,6 @@ const DWORD dwClksPerFrame = uCyclesPerLine * uLinesPerFrame; // 17030
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#define RAMWORKS // 8MB RamWorks III support
-//#define SATURN // SATURN 128K
// Use a base freq so that DirectX (or sound h/w) doesn't have to up/down-sample
// Assume base freqs are 44.1KHz & 48KHz
@@ -112,6 +111,7 @@ enum AppMode_e
#define REGVALUE_CUSTOM_SPEED "Custom Speed"
#define REGVALUE_EMULATION_SPEED "Emulation Speed"
#define REGVALUE_WINDOW_SCALE "Window Scale"
+#define REGVALUE_SLOT0 "Slot 0"
#define REGVALUE_SLOT1 "Slot 1"
#define REGVALUE_SLOT2 "Slot 2"
#define REGVALUE_SLOT3 "Slot 3"
@@ -193,7 +193,7 @@ enum eApple2Type {
A2TYPE_MAX
};
-inline bool IsApple2(eApple2Type type)
+inline bool IsApple2Plus(eApple2Type type) // Apple ][,][+
{
return (type & (APPLE2E_MASK|APPLE2C_MASK)) == 0;
}
@@ -203,6 +203,12 @@ inline bool IsClone(eApple2Type type)
return (type & APPLECLONE_MASK) != 0;
}
+inline bool IsApple2PlusOrClone(eApple2Type type) // Apple ][,][+ or clone ][,][+
+{
+ return ((type & (APPLE2E_MASK|APPLE2C_MASK)) == 0)
+ || (type & APPLECLONE_MASK) && !(type & A2TYPE_CLONE_A2E);
+}
+
extern eApple2Type g_Apple2Type;
inline bool IsOriginal2E(void)
{
diff --git a/source/Configuration/PageAdvanced.cpp b/source/Configuration/PageAdvanced.cpp
index d7ed2d7a..5d63b6bd 100644
--- a/source/Configuration/PageAdvanced.cpp
+++ b/source/Configuration/PageAdvanced.cpp
@@ -259,8 +259,8 @@ int CPageAdvanced::GetCloneMenuItem(void)
void CPageAdvanced::InitFreezeDlgButton(HWND hWnd)
{
- const bool bIsApple2 = IsApple2( m_PropertySheetHelper.GetConfigNew().m_Apple2Type );
- EnableWindow(GetDlgItem(hWnd, IDC_THE_FREEZES_F8_ROM_FW), bIsApple2 ? TRUE : FALSE);
+ const bool bIsApple2Plus = IsApple2Plus( m_PropertySheetHelper.GetConfigNew().m_Apple2Type );
+ EnableWindow(GetDlgItem(hWnd, IDC_THE_FREEZES_F8_ROM_FW), bIsApple2Plus ? TRUE : FALSE);
const UINT CheckTheFreezesRom = m_PropertySheetHelper.GetConfigNew().m_bEnableTheFreezesF8Rom ? BST_CHECKED : BST_UNCHECKED;
CheckDlgButton(hWnd, IDC_THE_FREEZES_F8_ROM_FW, CheckTheFreezesRom);
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 63a34037..937eccf3 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -34,6 +34,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "../Applewin.h"
#include "../CPU.h"
#include "../Frame.h"
+#include "../LanguageCard.h"
#include "../Memory.h"
#include "../Mockingboard.h"
#include "../Video.h"
@@ -2891,11 +2892,9 @@ void _DrawSoftSwitchLanguageCardBank( RECT & rect, int iBankDisplay, int bg_defa
int iActiveBank = -1;
char sText[ 4 ] = "?"; // Default to RAMWORKS
#ifdef RAMWORKS
- if (g_eMemType == MEM_TYPE_RAMWORKS) { sText[0] = 'r'; iActiveBank = g_uActiveBank; } // RAMWORKS
+ if (GetCurrentExpansionMemType() == CT_RamWorksIII) { sText[0] = 'r'; iActiveBank = GetRamWorksActiveBank(); } // RAMWORKS
#endif
-#ifdef SATURN
- if (g_eMemType == MEM_TYPE_SATURN ) { sText[0] = 's'; iActiveBank = g_uSaturnActiveBank; } // SATURN 64K 128K
-#endif // SATURN
+ if (GetCurrentExpansionMemType() == CT_Saturn128K) { sText[0] = 's'; iActiveBank = GetLanguageCard()->GetActiveBank(); } // SATURN 64K 128K
if (iActiveBank >= 0)
{
diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp
new file mode 100644
index 00000000..44c6413f
--- /dev/null
+++ b/source/LanguageCard.cpp
@@ -0,0 +1,376 @@
+/*
+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-2018, Tom Charlesworth, Michael Pohoreski, Nick Westgate
+
+AppleWin is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+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: Language Card and Saturn 128K emulation
+ *
+ * Author: various
+ */
+
+#include "StdAfx.h"
+
+#include "Applewin.h"
+#include "LanguageCard.h"
+#include "Log.h"
+#include "Memory.h"
+#include "YamlHelper.h"
+
+
+const UINT LanguageCardUnit::kMemModeInitialState = MF_BANK2 | MF_WRITERAM; // !INTCXROM
+
+LanguageCardUnit::LanguageCardUnit(void) :
+ m_uLastRamWrite(0),
+ m_type(CT_LanguageCardIIe)
+{
+ SetMemMainLanguageCard(NULL, true);
+}
+
+DWORD LanguageCardUnit::SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write)
+{
+ memmode &= ~(MF_BANK2 | MF_HIGHRAM);
+
+ if (!(address & 8))
+ memmode |= MF_BANK2;
+
+ if (((address & 2) >> 1) == (address & 1))
+ memmode |= MF_HIGHRAM;
+
+ if (address & 1) // GH#392
+ {
+ if (!write && GetLastRamWrite())
+ {
+ memmode |= MF_WRITERAM; // UTAIIe:5-23
+ }
+ }
+ else
+ {
+ memmode &= ~MF_WRITERAM; // UTAIIe:5-23
+ }
+
+ SetLastRamWrite( ((address & 1) && !write) ); // UTAIIe:5-23
+
+ return memmode;
+}
+
+//-------------------------------------
+
+LanguageCardSlot0::LanguageCardSlot0(void)
+{
+ m_type = CT_LanguageCard;
+ m_pMemory = (LPBYTE) VirtualAlloc(NULL, kMemBankSize, MEM_COMMIT, PAGE_READWRITE);
+ SetMemMainLanguageCard(m_pMemory);
+}
+
+LanguageCardSlot0::~LanguageCardSlot0(void)
+{
+ VirtualFree(m_pMemory, 0, MEM_RELEASE);
+ m_pMemory = NULL;
+}
+
+//
+
+static const UINT kUNIT_LANGUAGECARD_VER = 1;
+static const UINT kSLOT_LANGUAGECARD = 0;
+
+#define SS_YAML_VALUE_CARD_LANGUAGECARD "Language Card"
+
+#define SS_YAML_KEY_MEMORYMODE "Memory Mode"
+#define SS_YAML_KEY_LASTRAMWRITE "Last RAM Write"
+
+std::string LanguageCardSlot0::GetSnapshotMemStructName(void)
+{
+ static const std::string name("Memory Bank");
+ return name;
+}
+
+std::string LanguageCardSlot0::GetSnapshotCardName(void)
+{
+ static const std::string name(SS_YAML_VALUE_CARD_LANGUAGECARD);
+ return name;
+}
+
+void LanguageCardSlot0::SaveLCState(YamlSaveHelper& yamlSaveHelper)
+{
+ yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_MEMORYMODE, GetMemMode() & (MF_WRITERAM|MF_HIGHRAM|MF_BANK2));
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_LASTRAMWRITE, GetLastRamWrite() ? 1 : 0);
+}
+
+void LanguageCardSlot0::LoadLCState(YamlLoadHelper& yamlLoadHelper)
+{
+ DWORD memMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMORYMODE) & MF_LANGCARD_MASK;
+ BOOL lastRamWrite = yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE;
+ SetMemMode( (GetMemMode() & ~MF_LANGCARD_MASK) | memMode );
+ SetLastRamWrite(lastRamWrite);
+}
+
+void LanguageCardSlot0::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ if (!IsApple2PlusOrClone(GetApple2Type()))
+ {
+ _ASSERT(0);
+ LogFileOutput("Warning: Save-state attempted to save %s for //e or above\n", GetSnapshotCardName().c_str());
+ return; // No Language Card support for //e and above
+ }
+
+ YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), kSLOT_LANGUAGECARD, kUNIT_LANGUAGECARD_VER);
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+
+ SaveLCState(yamlSaveHelper);
+
+ {
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", GetSnapshotMemStructName().c_str());
+ yamlSaveHelper.SaveMemory(m_pMemory, kMemBankSize);
+ }
+}
+
+bool LanguageCardSlot0::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != kSLOT_LANGUAGECARD)
+ throw std::string("Card: wrong slot");
+
+ if (version != kUNIT_LANGUAGECARD_VER)
+ throw std::string("Card: wrong version");
+
+ // "State"
+ LoadLCState(yamlLoadHelper);
+
+ if (!m_pMemory)
+ {
+ m_pMemory = (LPBYTE) VirtualAlloc(NULL, kMemBankSize, MEM_COMMIT, PAGE_READWRITE);
+ if (!m_pMemory)
+ throw std::string("Card: mem alloc failed");
+ }
+
+ if (!yamlLoadHelper.GetSubMap(GetSnapshotMemStructName()))
+ throw std::string("Memory: Missing map name: " + GetSnapshotMemStructName());
+
+ yamlLoadHelper.LoadMemory(m_pMemory, kMemBankSize);
+
+ yamlLoadHelper.PopMap();
+
+ // NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
+
+ return true;
+}
+
+//-------------------------------------
+
+Saturn128K::Saturn128K(UINT banks)
+{
+ m_type = CT_Saturn128K;
+ m_uSaturnTotalBanks = (banks == 0) ? kMaxSaturnBanks : banks;
+ m_uSaturnActiveBank = 0;
+
+ for (UINT i=0; i> 1) & 4
+ | (address >> 0) & 3;
+
+ if (m_uSaturnActiveBank >= m_uSaturnTotalBanks)
+ {
+ // EG. Run RAMTEST128K tests on a Saturn 64K card
+ // TODO: Saturn::UpdatePaging() should deal with this case:
+ // . Technically read floating-bus, write to nothing
+ // . But the mem cache doesn't support floating-bus reads from non-I/O space
+ m_uSaturnActiveBank = m_uSaturnTotalBanks-1; // FIXME: just prevent crash for now!
+ }
+
+ SetMemMainLanguageCard( m_aSaturnBanks[ m_uSaturnActiveBank ] );
+
+ modechanging = 1;
+ }
+ else
+ {
+ memmode &= ~(MF_BANK2 | MF_HIGHRAM);
+
+ if (!(address & 8))
+ memmode |= MF_BANK2;
+
+ if (((address & 2) >> 1) == (address & 1))
+ memmode |= MF_HIGHRAM;
+
+ if (address & 1 && GetLastRamWrite()) // Saturn differs from Apple's 16K LC: any access (LC is read-only)
+ memmode |= MF_WRITERAM;
+ else
+ memmode &= ~MF_WRITERAM;
+
+ SetLastRamWrite(address & 1); // Saturn differs from Apple's 16K LC: any access (LC is read-only)
+ }
+
+ return memmode;
+}
+
+//
+
+static const UINT kUNIT_SATURN_VER = 1;
+static const UINT kSLOT_SATURN = 0;
+
+#define SS_YAML_VALUE_CARD_SATURN128 "Saturn 128"
+
+#define SS_YAML_KEY_NUM_SATURN_BANKS "Num Saturn Banks"
+#define SS_YAML_KEY_ACTIVE_SATURN_BANK "Active Saturn Bank"
+
+std::string Saturn128K::GetSnapshotMemStructName(void)
+{
+ static const std::string name("Memory Bank");
+ return name;
+}
+
+std::string Saturn128K::GetSnapshotCardName(void)
+{
+ static const std::string name(SS_YAML_VALUE_CARD_SATURN128);
+ return name;
+}
+
+void Saturn128K::SaveSnapshot(YamlSaveHelper& yamlSaveHelper)
+{
+ if (!IsApple2PlusOrClone(GetApple2Type()))
+ {
+ _ASSERT(0);
+ LogFileOutput("Warning: Save-state attempted to save %s for //e or above\n", GetSnapshotCardName().c_str());
+ return; // No Saturn support for //e and above
+ }
+
+ YamlSaveHelper::Slot slot(yamlSaveHelper, GetSnapshotCardName(), kSLOT_SATURN, kUNIT_SATURN_VER);
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+
+ SaveLCState(yamlSaveHelper);
+
+ yamlSaveHelper.Save("%s: 0x%02X # [1..8] 4=64K, 8=128K card\n", SS_YAML_KEY_NUM_SATURN_BANKS, m_uSaturnTotalBanks);
+ yamlSaveHelper.Save("%s: 0x%02X # [0..7]\n", SS_YAML_KEY_ACTIVE_SATURN_BANK, m_uSaturnActiveBank);
+
+ for(UINT uBank = 0; uBank < m_uSaturnTotalBanks; uBank++)
+ {
+ LPBYTE pMemBase = m_aSaturnBanks[uBank];
+ YamlSaveHelper::Label state(yamlSaveHelper, "%s%02X:\n", GetSnapshotMemStructName().c_str(), uBank);
+ yamlSaveHelper.SaveMemory(pMemBase, kMemBankSize);
+ }
+}
+
+bool Saturn128K::LoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version)
+{
+ if (slot != kSLOT_SATURN) // fixme
+ throw std::string("Card: wrong slot");
+
+ if (version != kUNIT_SATURN_VER)
+ throw std::string("Card: wrong version");
+
+ // "State"
+ LoadLCState(yamlLoadHelper);
+
+ UINT numBanks = yamlLoadHelper.LoadUint(SS_YAML_KEY_NUM_SATURN_BANKS);
+ UINT activeBank = yamlLoadHelper.LoadUint(SS_YAML_KEY_ACTIVE_SATURN_BANK);
+
+ if (numBanks < 1 || numBanks > kMaxSaturnBanks || activeBank >= numBanks)
+ throw std::string(SS_YAML_KEY_UNIT ": Bad Saturn card state");
+
+ m_uSaturnTotalBanks = numBanks;
+ m_uSaturnActiveBank = activeBank;
+
+ //
+
+ for(UINT uBank = 0; uBank < m_uSaturnTotalBanks; uBank++)
+ {
+ LPBYTE pBank = m_aSaturnBanks[uBank];
+ if (!pBank)
+ {
+ pBank = m_aSaturnBanks[uBank] = (LPBYTE) VirtualAlloc(NULL, kMemBankSize, MEM_COMMIT, PAGE_READWRITE);
+ if (!pBank)
+ throw std::string("Card: mem alloc failed");
+ }
+
+ // "Memory Bankxx"
+ char szBank[3];
+ sprintf(szBank, "%02X", uBank);
+ std::string memName = GetSnapshotMemStructName() + szBank;
+
+ if (!yamlLoadHelper.GetSubMap(memName))
+ throw std::string("Memory: Missing map name: " + memName);
+
+ yamlLoadHelper.LoadMemory(pBank, kMemBankSize);
+
+ yamlLoadHelper.PopMap();
+ }
+
+ SetMemMainLanguageCard( m_aSaturnBanks[ m_uSaturnActiveBank ] );
+
+ // NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
+
+ return true;
+}
diff --git a/source/LanguageCard.h b/source/LanguageCard.h
new file mode 100644
index 00000000..c3654dfe
--- /dev/null
+++ b/source/LanguageCard.h
@@ -0,0 +1,83 @@
+#pragma once
+
+//
+// Language Card (base unit) for Apple //e and above
+//
+
+class LanguageCardUnit
+{
+public:
+ LanguageCardUnit(void);
+ virtual ~LanguageCardUnit(void) {}
+
+ virtual DWORD SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write);
+ virtual void SetMemorySize(UINT banks) {} // No-op for //e and slot-0 16K LC
+ virtual UINT GetActiveBank(void) { return 0; } // Always 0 as only 1x 16K bank
+ virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper) { _ASSERT(0); } // Not used for //e
+ virtual bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version) { _ASSERT(0); return false; } // Not used for //e
+
+ BOOL GetLastRamWrite(void) { return m_uLastRamWrite; }
+ void SetLastRamWrite(BOOL count) { m_uLastRamWrite = count; }
+ SS_CARDTYPE GetMemoryType(void) { return m_type; }
+
+ static const UINT kMemModeInitialState;
+
+protected:
+ SS_CARDTYPE m_type;
+
+private:
+ UINT m_uLastRamWrite;
+};
+
+//
+// Language Card (slot-0) for Apple II or II+
+//
+
+class LanguageCardSlot0 : public LanguageCardUnit
+{
+public:
+ LanguageCardSlot0(void);
+ virtual ~LanguageCardSlot0(void);
+
+ virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+ virtual bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+
+ static const UINT kMemBankSize = 16*1024;
+ static std::string GetSnapshotCardName(void);
+
+protected:
+ void SaveLCState(class YamlSaveHelper& yamlSaveHelper);
+ void LoadLCState(class YamlLoadHelper& yamlLoadHelper);
+
+private:
+ std::string GetSnapshotMemStructName(void);
+
+ LPBYTE m_pMemory;
+};
+
+//
+// Saturn 128K
+//
+
+class Saturn128K : public LanguageCardSlot0
+{
+public:
+ Saturn128K(UINT banks);
+ virtual ~Saturn128K(void);
+
+ virtual DWORD SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write);
+ virtual void SetMemorySize(UINT banks);
+ virtual UINT GetActiveBank(void);
+ virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
+ virtual bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+
+ static const UINT kMaxSaturnBanks = 8; // 8 * 16K = 128K
+ static std::string GetSnapshotCardName(void);
+
+private:
+ std::string GetSnapshotMemStructName(void);
+
+ UINT m_uSaturnTotalBanks; // Will be > 0 if Saturn card is installed
+ UINT m_uSaturnActiveBank; // Saturn 128K Language Card Bank 0 .. 7
+ LPBYTE m_aSaturnBanks[kMaxSaturnBanks];
+};
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 4313cae6..a154114b 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Harddisk.h"
#include "Joystick.h"
#include "Keyboard.h"
+#include "LanguageCard.h"
#include "Log.h"
#include "Memory.h"
#include "Mockingboard.h"
@@ -180,8 +181,6 @@ iofunction IORead[256];
iofunction IOWrite[256];
static LPVOID SlotParameters[NUM_SLOTS];
-static BOOL g_bLastWriteRam = 0;
-
LPBYTE mem = NULL;
//
@@ -197,31 +196,153 @@ static LPBYTE memimage = NULL;
static LPBYTE pCxRomInternal = NULL;
static LPBYTE pCxRomPeripheral = NULL;
-static const DWORD kMemModeInitialState = MF_BANK2 | MF_WRITERAM; // !INTCXROM
-static DWORD memmode = kMemModeInitialState;
+static LPBYTE g_pMemMainLanguageCard = NULL;
+
+static DWORD memmode = LanguageCardUnit::kMemModeInitialState;
static BOOL modechanging = 0; // An Optimisation: means delay calling UpdatePaging() for 1 instruction
-static BOOL Pravets8charmode = 0;
static CNoSlotClock g_NoSlotClock;
+static LanguageCardUnit* g_pLanguageCard = NULL; // For all Apple II, //e and above
#ifdef RAMWORKS
-UINT g_uMaxExPages = 1; // user requested ram pages (default to 1 aux bank: so total = 128KB)
-UINT g_uActiveBank = 0; // 0 = aux 64K for: //e extended 80 Col card, or //c -- ALSO RAMWORKS
+static UINT g_uMaxExPages = 1; // user requested ram pages (default to 1 aux bank: so total = 128KB)
+static UINT g_uActiveBank = 0; // 0 = aux 64K for: //e extended 80 Col card, or //c -- ALSO RAMWORKS
static LPBYTE RWpages[kMaxExMemoryBanks]; // pointers to RW memory banks
#endif
-#ifdef SATURN
-UINT g_uSaturnTotalBanks = 0; // Will be > 0 if Saturn card is "installed"
-UINT g_uSaturnActiveBank = 0; // Saturn 128K Language Card Bank 0 .. 7
-static LPBYTE g_aSaturnPages[8];
-#endif // SATURN
-
-MemoryType_e g_eMemType = MEM_TYPE_NATIVE; // 0 = Native memory, 1=RAMWORKS, 2 = SATURN
-
BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
//=============================================================================
+static SS_CARDTYPE g_MemTypeAppleIIPlus = CT_LanguageCard; // Keep a copy so it's not lost if machine type changes, eg: A][ -> A//e -> A][
+static SS_CARDTYPE g_MemTypeAppleIIe = CT_Extended80Col; // Keep a copy so it's not lost if machine type changes, eg: A//e -> A][ -> A//e
+static UINT g_uSaturnBanksFromCmdLine = 0;
+
+// Called from MemLoadSnapshot()
+static void ResetDefaultMachineMemTypes(void)
+{
+ g_MemTypeAppleIIPlus = CT_LanguageCard;
+ g_MemTypeAppleIIe = CT_Extended80Col;
+}
+
+// Called from MemInitialize(), MemLoadSnapshot()
+void SetExpansionMemTypeDefault(void)
+{
+ SS_CARDTYPE defaultType = IsApple2PlusOrClone(GetApple2Type()) ? g_MemTypeAppleIIPlus : g_MemTypeAppleIIe;
+ SetExpansionMemType(defaultType);
+}
+
+// Called from SetExpansionMemTypeDefault(), MemLoadSnapshotAux(), SaveState.cpp_ParseSlots(), cmd-line switch
+void SetExpansionMemType(const SS_CARDTYPE type)
+{
+ SS_CARDTYPE newSlot0Card;
+ SS_CARDTYPE newSlotAuxCard;
+
+ // Set defaults:
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ {
+ newSlot0Card = CT_LanguageCard;
+ newSlotAuxCard = CT_Empty;
+ }
+ else // Apple //e or above
+ {
+ newSlot0Card = CT_Empty; // NB. No slot0 for //e
+ newSlotAuxCard = CT_Extended80Col;
+ }
+
+ if (type == CT_Saturn128K)
+ {
+ g_MemTypeAppleIIPlus = type;
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ newSlot0Card = CT_Saturn128K;
+ else
+ newSlot0Card = CT_Empty; // NB. No slot0 for //e
+ }
+ else if (type == CT_RamWorksIII)
+ {
+ g_MemTypeAppleIIe = type;
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ newSlotAuxCard = CT_Empty; // NB. No aux slot for ][ or ][+
+ else
+ newSlotAuxCard = CT_RamWorksIII;
+ }
+
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ {
+ delete g_pLanguageCard;
+ g_pLanguageCard = NULL;
+
+ if (newSlot0Card == CT_Saturn128K)
+ g_pLanguageCard = new Saturn128K(g_uSaturnBanksFromCmdLine);
+ else // newSlot0Card == CT_LanguageCard
+ g_pLanguageCard = new LanguageCardSlot0;
+ }
+ else
+ {
+ delete g_pLanguageCard;
+ g_pLanguageCard = new LanguageCardUnit;
+ }
+
+ _ASSERT(g_pMemMainLanguageCard);
+
+ g_Slot0 = newSlot0Card;
+ g_SlotAux = newSlotAuxCard;
+}
+
+SS_CARDTYPE GetCurrentExpansionMemType(void)
+{
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ return g_Slot0;
+ else
+ return g_SlotAux;
+}
+
+//
+
+void SetRamWorksMemorySize(UINT pages)
+{
+ g_uMaxExPages = pages;
+}
+
+UINT GetRamWorksActiveBank(void)
+{
+ return g_uActiveBank;
+}
+
+void SetSaturnMemorySize(UINT banks)
+{
+ g_uSaturnBanksFromCmdLine = banks;
+}
+
+//
+
+static BOOL GetLastRamWrite(void)
+{
+ return g_pLanguageCard->GetLastRamWrite();
+}
+
+static void SetLastRamWrite(BOOL count)
+{
+ g_pLanguageCard->SetLastRamWrite(count);
+}
+
+//
+
+void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain /*=false*/)
+{
+ if (bMemMain)
+ g_pMemMainLanguageCard = memmain+0xC000;
+ else
+ g_pMemMainLanguageCard = ptr;
+}
+
+LanguageCardUnit* GetLanguageCard(void)
+{
+ return g_pLanguageCard;
+}
+
+//=============================================================================
+
static BYTE __stdcall IORead_C00x(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles)
{
return KeybReadData();
@@ -837,7 +958,7 @@ DWORD GetMemMode(void)
return memmode;
}
-static void SetMemMode(const DWORD uNewMemMode)
+void SetMemMode(DWORD uNewMemMode)
{
#if defined(_DEBUG) && 0
static DWORD dwOldDiff = 0;
@@ -881,8 +1002,8 @@ void MemResetPaging()
static void ResetPaging(BOOL initialize)
{
- g_bLastWriteRam = 0;
- SetMemMode(kMemModeInitialState);
+ SetLastRamWrite(0);
+ SetMemMode(LanguageCardUnit::kMemModeInitialState);
UpdatePaging(initialize);
}
@@ -949,24 +1070,24 @@ static void UpdatePaging(BOOL initialize)
{
int bankoffset = (SW_BANK2 ? 0 : 0x1000);
memshadow[loop] = SW_HIGHRAM ? SW_ALTZP ? memaux+(loop << 8)-bankoffset
- : memmain+(loop << 8)-bankoffset
- : memrom+((loop-0xD0) * 0x100);
+ : g_pMemMainLanguageCard+((loop-0xC0)<<8)-bankoffset
+ : memrom+((loop-0xD0) * 0x100);
memwrite[loop] = SW_WRITERAM ? SW_HIGHRAM ? mem+(loop << 8)
: SW_ALTZP ? memaux+(loop << 8)-bankoffset
- : memmain+(loop << 8)-bankoffset
+ : g_pMemMainLanguageCard+((loop-0xC0)<<8)-bankoffset
: NULL;
}
for (loop = 0xE0; loop < 0x100; loop++)
{
memshadow[loop] = SW_HIGHRAM ? SW_ALTZP ? memaux+(loop << 8)
- : memmain+(loop << 8)
+ : g_pMemMainLanguageCard+((loop-0xC0)<<8)
: memrom+((loop-0xD0) * 0x100);
memwrite[loop] = SW_WRITERAM ? SW_HIGHRAM ? mem+(loop << 8)
: SW_ALTZP ? memaux+(loop << 8)
- : memmain+(loop << 8)
+ : g_pMemMainLanguageCard+((loop-0xC0)<<8)
: NULL;
}
@@ -1043,6 +1164,9 @@ void MemDestroy()
RWpages[0]=NULL;
#endif
+ delete g_pLanguageCard;
+ g_pLanguageCard = NULL;
+
memaux = NULL;
memmain = NULL;
memdirty = NULL;
@@ -1054,6 +1178,8 @@ void MemDestroy()
mem = NULL;
+ g_pMemMainLanguageCard = NULL;
+
ZeroMemory(memwrite, sizeof(memwrite));
ZeroMemory(memshadow,sizeof(memshadow));
}
@@ -1285,20 +1411,27 @@ void MemInitialize()
// this happens when running under valgrind
memimage = (LPBYTE)newloc;
-#ifdef RAMWORKS
- // allocate memory for RAMWorks III - up to 8MB
- g_uActiveBank = 0;
- RWpages[g_uActiveBank] = memaux;
+ //
- UINT i = 1;
- while ((i < g_uMaxExPages) && (RWpages[i] = (LPBYTE) VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE)))
- i++;
+ RWpages[0] = memaux;
+
+ SetExpansionMemTypeDefault();
+
+#ifdef RAMWORKS
+ if (GetCurrentExpansionMemType() == CT_RamWorksIII)
+ {
+ // allocate memory for RAMWorks III - up to 8MB
+ g_uActiveBank = 0;
+
+ UINT i = 1;
+ while ((i < g_uMaxExPages) && (RWpages[i] = (LPBYTE) VirtualAlloc(NULL, _6502_MEM_END+1, MEM_COMMIT, PAGE_READWRITE)))
+ i++;
+ while (i < kMaxExMemoryBanks)
+ RWpages[i++] = NULL;
+ }
#endif
-#ifdef SATURN
- for( UINT iPage = 0; iPage < g_uSaturnTotalBanks; iPage++ )
- g_aSaturnPages[ iPage ] = (LPBYTE) VirtualAlloc( NULL, 1024 * 16,MEM_COMMIT,PAGE_READWRITE); // Saturn Pages are 16K / bank, Max 8 Banks/Card
-#endif // SATURN
+ //
MemInitializeROM();
MemInitializeCustomF8ROM();
@@ -1723,69 +1856,7 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
// DETERMINE THE NEW MEMORY PAGING MODE.
if ((address >= 0x80) && (address <= 0x8F))
{
- SetMemMode(memmode & ~(MF_BANK2 | MF_HIGHRAM));
-
-#ifdef SATURN
-/*
- Bin Addr.
- $C0N0 4K Bank A, RAM read, Write protect
- $C0N1 4K Bank A, ROM read, Write enabled
- $C0N2 4K Bank A, ROM read, Write protect
- $C0N3 4K Bank A, RAM read, Write enabled
- 0100 $C0N4 select 16K Bank 1
- 0101 $C0N5 select 16K Bank 2
- 0110 $C0N6 select 16K Bank 3
- 0111 $C0N7 select 16K Bank 4
- $C0N8 4K Bank B, RAM read, Write protect
- $C0N9 4K Bank B, ROM read, Write enabled
- $C0NA 4K Bank B, ROM read, Write protect
- $C0NB 4K Bank B, RAM read, Write enabled
- 1100 $C0NC select 16K Bank 5
- 1101 $C0ND select 16K Bank 6
- 1110 $C0NE select 16K Bank 7
- 1111 $C0NF select 16K Bank 8
-*/
- if (g_uSaturnTotalBanks)
- {
- if ((address & 7) > 3)
- {
- g_uSaturnActiveBank = 0 // Saturn 128K Language Card Bank 0 .. 7
- | (address >> 1) & 4
- | (address >> 0) & 3
- ;
-
- // TODO: Update paging()
-
- goto _done_saturn;
- }
-
- // Fall into 16K IO switches
- }
-
-#endif // SATURN
- {
- // Apple 16K Language Card
- if (!(address & 8))
- SetMemMode(memmode | MF_BANK2);
-
- // C081 C089 Read ROM, Write enable
- // C082 C08A Read ROM, Write protect
- if (((address & 2) >> 1) == (address & 1))
- SetMemMode(memmode | MF_HIGHRAM);
-
- if (address & 1) // GH#392
- {
- if (!write && g_bLastWriteRam)
- {
- SetMemMode(memmode | MF_WRITERAM); // UTAIIe:5-23
- }
- }
- else
- {
- SetMemMode(memmode & ~(MF_WRITERAM)); // UTAIIe:5-23
- }
- }
- g_bLastWriteRam = (address & 1) && (!write); // UTAIIe:5-23
+ SetMemMode( g_pLanguageCard->SetPaging(address, memmode, modechanging, write ? true : false) );
}
else if (!IS_APPLE2)
{
@@ -1814,33 +1885,32 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
{
g_uActiveBank = value;
memaux = RWpages[g_uActiveBank];
- UpdatePaging(0); // Initialize=0
+ UpdatePaging(FALSE); // Initialize=FALSE
}
break;
#endif
}
}
-#ifdef SATURN
-_done_saturn:
-#endif // SATURN
-
- // IF THE EMULATED PROGRAM HAS JUST UPDATE THE MEMORY WRITE MODE AND IS
- // ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
- // IT DOES SO.
- //
- // NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
- // - although any data-race is probably a bug in the 6502 code too.
- if ((address >= 4) && (address <= 5) &&
- ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
- modechanging = 1;
- return write ? 0 : MemReadFloatingBus(1, nExecutedCycles);
- }
- if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) &&
- (((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) ||
- ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) {
- modechanging = 1;
- return write ? 0 : MemReadFloatingBus(1, nExecutedCycles);
+ if (GetCurrentExpansionMemType() != CT_Saturn128K) // TODO: Not sure this optimisation is valid for Saturn, so skip it for now
+ {
+ // IF THE EMULATED PROGRAM HAS JUST UPDATE THE MEMORY WRITE MODE AND IS
+ // ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
+ // IT DOES SO.
+ //
+ // NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
+ // - although any data-race is probably a bug in the 6502 code too.
+ if ((address >= 4) && (address <= 5) &&
+ ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
+ modechanging = 1;
+ return write ? 0 : MemReadFloatingBus(1, nExecutedCycles);
+ }
+ if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) &&
+ (((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) ||
+ ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) {
+ modechanging = 1;
+ return write ? 0 : MemReadFloatingBus(1, nExecutedCycles);
+ }
}
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
@@ -1903,7 +1973,7 @@ LPVOID MemGetSlotParameters(UINT uSlot)
void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux)
{
SetMemMode(MemMode ^ MF_INTCXROM); // Convert from SLOTCXROM to INTCXROM
- g_bLastWriteRam = LastWriteRam;
+ SetLastRamWrite(LastWriteRam);
memcpy(memmain, pMemMain, nMemMainSize);
memcpy(memaux, pMemAux, nMemAuxSize);
@@ -1918,8 +1988,6 @@ void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE*
//
-#define UNIT_AUXSLOT_VER 1
-
#define SS_YAML_KEY_MEMORYMODE "Memory Mode"
#define SS_YAML_KEY_LASTRAMWRITE "Last RAM Write"
#define SS_YAML_KEY_IOSELECT "IO_SELECT"
@@ -1927,6 +1995,10 @@ void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE*
#define SS_YAML_KEY_EXPANSIONROMTYPE "Expansion ROM Type"
#define SS_YAML_KEY_PERIPHERALROMSLOT "Peripheral ROM Slot"
+//
+
+static const UINT kUNIT_AUXSLOT_VER = 1;
+
#define SS_YAML_VALUE_CARD_80COL "80 Column"
#define SS_YAML_VALUE_CARD_EXTENDED80COL "Extended 80 Column"
#define SS_YAML_VALUE_CARD_RAMWORKSIII "RamWorksIII"
@@ -1958,19 +2030,19 @@ static std::string MemGetSnapshotAuxMemStructName(void)
return name;
}
-static void MemSaveSnapshotMemory(YamlSaveHelper& yamlSaveHelper, bool bIsMainMem, UINT bank=0)
+static void MemSaveSnapshotMemory(YamlSaveHelper& yamlSaveHelper, bool bIsMainMem, UINT bank=0, UINT size=64*1024)
{
LPBYTE pMemBase = MemGetBankPtr(bank);
if (bIsMainMem)
{
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", MemGetSnapshotMainMemStructName().c_str());
- yamlSaveHelper.SaveMemory(pMemBase, 64*1024);
+ yamlSaveHelper.SaveMemory(pMemBase, size);
}
else
{
YamlSaveHelper::Label state(yamlSaveHelper, "%s%02X:\n", MemGetSnapshotAuxMemStructName().c_str(), bank-1);
- yamlSaveHelper.SaveMemory(pMemBase, 64*1024);
+ yamlSaveHelper.SaveMemory(pMemBase, size);
}
}
@@ -1979,29 +2051,56 @@ void MemSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
// Scope so that "Memory" & "Main Memory" are at same indent level
{
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", MemGetSnapshotStructName().c_str());
- yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_MEMORYMODE, memmode ^ MF_INTCXROM); // Convert from INTCXROM to SLOTCXROM
- yamlSaveHelper.SaveUint(SS_YAML_KEY_LASTRAMWRITE, g_bLastWriteRam ? 1 : 0);
+ DWORD saveMemMode = memmode;
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ saveMemMode &= ~MF_LANGCARD_MASK; // For II,II+: clear LC bits - set later by slot-0 LC or Saturn
+ yamlSaveHelper.SaveHexUint32(SS_YAML_KEY_MEMORYMODE, saveMemMode);
+ if (!IsApple2PlusOrClone(GetApple2Type())) // NB. This is set later for II,II+ by slot-0 LC or Saturn
+ yamlSaveHelper.SaveUint(SS_YAML_KEY_LASTRAMWRITE, GetLastRamWrite() ? 1 : 0);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IOSELECT, IO_SELECT);
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_IOSELECT_INT, INTC8ROM ? 1 : 0);
yamlSaveHelper.SaveUint(SS_YAML_KEY_EXPANSIONROMTYPE, (UINT) g_eExpansionRomType);
yamlSaveHelper.SaveUint(SS_YAML_KEY_PERIPHERALROMSLOT, g_uPeripheralRomSlot);
}
- MemSaveSnapshotMemory(yamlSaveHelper, true);
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ MemSaveSnapshotMemory(yamlSaveHelper, true, 0, 48*1024); // NB. Language Card/Saturn provides the remaining 16K (or multiple) bank(s)
+ else
+ MemSaveSnapshotMemory(yamlSaveHelper, true);
}
-bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
{
if (!yamlLoadHelper.GetSubMap(MemGetSnapshotStructName()))
return false;
- SetMemMode( yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMORYMODE) ^ MF_INTCXROM ); // Convert from SLOTCXROM to INTCXROM
- g_bLastWriteRam = yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE;
+ // Create default LC type for AppleII machine (do prior to loading saved LC state)
+ ResetDefaultMachineMemTypes();
+ SetExpansionMemTypeDefault();
+
+ //
+
IO_SELECT = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_IOSELECT);
INTC8ROM = yamlLoadHelper.LoadUint(SS_YAML_KEY_IOSELECT_INT) ? true : false;
g_eExpansionRomType = (eExpansionRomType) yamlLoadHelper.LoadUint(SS_YAML_KEY_EXPANSIONROMTYPE);
g_uPeripheralRomSlot = yamlLoadHelper.LoadUint(SS_YAML_KEY_PERIPHERALROMSLOT);
+ if (version == 1)
+ {
+ SetMemMode( yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMORYMODE) ^ MF_INTCXROM ); // Convert from SLOTCXROM to INTCXROM
+ SetLastRamWrite( yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE );
+ }
+ else
+ {
+ UINT uMemMode = yamlLoadHelper.LoadUint(SS_YAML_KEY_MEMORYMODE);
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ uMemMode &= ~MF_LANGCARD_MASK; // For II,II+: clear LC bits - set later by slot-0 LC or Saturn
+ SetMemMode(uMemMode);
+
+ if (!IsApple2PlusOrClone(GetApple2Type()))
+ SetLastRamWrite( yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTRAMWRITE) ? TRUE : FALSE ); // NB. This is set later for II,II+ by slot-0 LC or Saturn
+ }
+
yamlLoadHelper.PopMap();
//
@@ -2009,7 +2108,9 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
if (!yamlLoadHelper.GetSubMap( MemGetSnapshotMainMemStructName() ))
throw std::string("Card: Expected key: ") + MemGetSnapshotMainMemStructName();
+ memset(memmain, 0, _6502_MEM_END+1); // Clear it, as high 16K may not be in the save-state (eg. the case of Saturn replacing LC)
yamlLoadHelper.LoadMemory(memmain, _6502_MEM_END+1);
+ memcpy(g_pMemMainLanguageCard, memmain+0xC000, LanguageCardSlot0::kMemBankSize);
memset(memdirty, 0, 0x100);
yamlLoadHelper.PopMap();
@@ -2024,6 +2125,7 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
return true;
}
+// TODO: Switch from checking 'g_uMaxExPages == n' to using g_SlotAux
void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
{
if (IS_APPLE2)
@@ -2036,7 +2138,7 @@ void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
_ASSERT(g_uMaxExPages == 1);
}
- yamlSaveHelper.UnitHdr(MemGetSnapshotUnitAuxSlotName(), UNIT_AUXSLOT_VER);
+ yamlSaveHelper.UnitHdr(MemGetSnapshotUnitAuxSlotName(), kUNIT_AUXSLOT_VER);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
std::string card = g_uMaxExPages == 0 ? SS_YAML_VALUE_CARD_80COL : // todo: support empty slot
@@ -2054,32 +2156,37 @@ void MemSaveSnapshotAux(YamlSaveHelper& yamlSaveHelper)
bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT version)
{
- if (version != UNIT_AUXSLOT_VER)
+ if (version != kUNIT_AUXSLOT_VER)
throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Version mismatch");
// "State"
UINT numAuxBanks = yamlLoadHelper.LoadUint(SS_YAML_KEY_NUMAUXBANKS);
UINT activeAuxBank = yamlLoadHelper.LoadUint(SS_YAML_KEY_ACTIVEAUXBANK);
+ SS_CARDTYPE type = CT_Empty;
std::string card = yamlLoadHelper.LoadString(SS_YAML_KEY_CARD);
if (card == SS_YAML_VALUE_CARD_80COL)
{
+ type = CT_80Col;
if (numAuxBanks != 0 || activeAuxBank != 0)
throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
}
else if (card == SS_YAML_VALUE_CARD_EXTENDED80COL)
{
+ type = CT_Extended80Col;
if (numAuxBanks != 1 || activeAuxBank != 0)
throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
}
else if (card == SS_YAML_VALUE_CARD_RAMWORKSIII)
{
+ type = CT_RamWorksIII;
if (numAuxBanks < 2 || numAuxBanks > 0x7F || (activeAuxBank+1) > numAuxBanks)
throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Bad aux slot card state");
}
else
{
// todo: support empty slot
+ type = CT_Empty;
throw std::string(SS_YAML_KEY_UNIT ": AuxSlot: Unknown card: " + card);
}
@@ -2093,7 +2200,7 @@ bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT version)
LPBYTE pBank = MemGetBankPtr(uBank);
if (!pBank)
{
- pBank = RWpages[uBank-1] = (LPBYTE) VirtualAlloc(NULL,_6502_MEM_END+1,MEM_COMMIT,PAGE_READWRITE);
+ pBank = RWpages[uBank-1] = (LPBYTE) VirtualAlloc(NULL, _6502_MEM_END+1, MEM_COMMIT, PAGE_READWRITE);
if (!pBank)
throw std::string("Card: mem alloc failed");
}
@@ -2111,6 +2218,9 @@ bool MemLoadSnapshotAux(YamlLoadHelper& yamlLoadHelper, UINT version)
yamlLoadHelper.PopMap();
}
+ g_Slot0 = CT_Empty;
+ g_SlotAux = type;
+
memaux = RWpages[g_uActiveBank];
// NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
diff --git a/source/Memory.h b/source/Memory.h
index 191a5b26..ff81ddab 100644
--- a/source/Memory.h
+++ b/source/Memory.h
@@ -13,6 +13,8 @@
#define MF_INTCXROM 0x00000200
#define MF_WRITERAM 0x00000400 // Language Card RAM is Write Enabled
#define MF_IMAGEMASK 0x000003F7
+#define MF_LANGCARD_MASK (MF_WRITERAM|MF_HIGHRAM|MF_BANK2)
+
enum
{
@@ -39,18 +41,8 @@ enum MemoryInitPattern_e
, NUM_MIP
};
-enum MemoryType_e
-{
- MEM_TYPE_NATIVE = 0,
- MEM_TYPE_RAMWORKS = 1,
- MEM_TYPE_SATURN = 2,
- NUM_MEM_TYPE = 3
-};
-
typedef BYTE (__stdcall *iofunction)(WORD nPC, WORD nAddr, BYTE nWriteFlag, BYTE nWriteValue, ULONG nExecutedCycles);
-extern MemoryType_e g_eMemType;
-
extern iofunction IORead[256];
extern iofunction IOWrite[256];
extern LPBYTE memwrite[0x100];
@@ -63,11 +55,6 @@ extern UINT g_uMaxExPages; // user requested ram pages (from cmd line)
extern UINT g_uActiveBank;
#endif
-#ifdef SATURN
-extern UINT g_uSaturnTotalBanks;
-extern UINT g_uSaturnActiveBank; // Saturn 128K Language Card Bank 0 .. 7
-#endif // SATURN
-
void RegisterIoHandler(UINT uSlot, iofunction IOReadC0, iofunction IOWriteC0, iofunction IOReadCx, iofunction IOWriteCx, LPVOID lpSlotParameter, BYTE* pExpansionRom);
void MemDestroy ();
@@ -78,6 +65,7 @@ LPBYTE MemGetMainPtr(const WORD);
LPBYTE MemGetBankPtr(const UINT nBank);
LPBYTE MemGetCxRomPeripheral();
DWORD GetMemMode(void);
+void SetMemMode(DWORD memmode);
bool MemIsAddrCodeMemory(const USHORT addr);
void MemInitialize ();
void MemInitializeROM(void);
@@ -93,10 +81,20 @@ LPVOID MemGetSlotParameters (UINT uSlot);
void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux);
std::string MemGetSnapshotUnitAuxSlotName(void);
void MemSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
-bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
+bool MemLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
void MemSaveSnapshotAux(class YamlSaveHelper& yamlSaveHelper);
bool MemLoadSnapshotAux(class YamlLoadHelper& yamlLoadHelper, UINT version);
BYTE __stdcall IO_Null(WORD programcounter, WORD address, BYTE write, BYTE value, ULONG nCycles);
BYTE __stdcall MemSetPaging(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExecutedCycles);
+
+enum SS_CARDTYPE;
+void SetExpansionMemType(const SS_CARDTYPE type);
+SS_CARDTYPE GetCurrentExpansionMemType(void);
+
+void SetRamWorksMemorySize(UINT pages);
+UINT GetRamWorksActiveBank(void);
+void SetSaturnMemorySize(UINT banks);
+void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain=false);
+class LanguageCardUnit* GetLanguageCard(void);
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index 4870e9d6..c248b81b 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -37,6 +37,7 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "Frame.h"
#include "Joystick.h"
#include "Keyboard.h"
+#include "LanguageCard.h"
#include "Memory.h"
#include "Mockingboard.h"
#include "MouseInterface.h"
@@ -64,7 +65,7 @@ static YamlHelper yamlHelper;
#define SS_FILE_VER 2
-#define UNIT_APPLE2_VER 1
+#define UNIT_APPLE2_VER 2
#define UNIT_SLOTS_VER 1
//-----------------------------------------------------------------------------
@@ -323,7 +324,7 @@ static UINT ParseFileHdr(void)
static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version)
{
- if (version != UNIT_APPLE2_VER)
+ if (version == 0 || version > UNIT_APPLE2_VER)
throw std::string(SS_YAML_KEY_UNIT ": Apple2: Version mismatch");
std::string model = yamlLoadHelper.LoadString(SS_YAML_KEY_MODEL);
@@ -337,7 +338,7 @@ static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version)
KeybLoadSnapshot(yamlLoadHelper);
SpkrLoadSnapshot(yamlLoadHelper);
VideoLoadSnapshot(yamlLoadHelper);
- MemLoadSnapshot(yamlLoadHelper);
+ MemLoadSnapshot(yamlLoadHelper, version);
// g_Apple2Type may've changed: so redraw frame (title, buttons, leds, etc)
VideoReinitialize(); // g_CharsetType changed
@@ -358,7 +359,8 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT version)
break; // done all slots
const int slot = strtoul(scalar.c_str(), NULL, 10); // NB. aux slot supported as a different "unit"
- if (slot < 1 || slot > 7)
+ // NB. slot-0 only supported for Apple II or II+ (or similar clones)
+ if (slot < 0 || slot > 7)
throw std::string("Slots: Invalid slot #: ") + scalar;
yamlLoadHelper.GetSubMap(scalar);
@@ -414,6 +416,18 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT version)
m_ConfigNew.m_bEnableHDD = true;
type = CT_GenericHDD;
}
+ else if (card == LanguageCardSlot0::GetSnapshotCardName())
+ {
+ type = CT_LanguageCard;
+ SetExpansionMemType(type);
+ bRes = GetLanguageCard()->LoadSnapshot(yamlLoadHelper, slot, version);
+ }
+ else if (card == Saturn128K::GetSnapshotCardName())
+ {
+ type = CT_Saturn128K;
+ SetExpansionMemType(type);
+ bRes = GetLanguageCard()->LoadSnapshot(yamlLoadHelper, slot, version);
+ }
else
{
bIsCardSupported = false;
@@ -477,6 +491,7 @@ static void Snapshot_LoadState_v2(void)
//
CConfigNeedingRestart ConfigOld;
+ //ConfigOld.m_Slot[0] = CT_LanguageCard; // fixme: II/II+=LC, //e=empty
ConfigOld.m_Slot[1] = CT_GenericPrinter; // fixme
ConfigOld.m_Slot[2] = CT_SSC; // fixme
//ConfigOld.m_Slot[3] = CT_Uthernet; // todo
@@ -489,7 +504,6 @@ static void Snapshot_LoadState_v2(void)
m_ConfigNew.m_SlotAux = CT_Empty;
m_ConfigNew.m_bEnableHDD = false;
//m_ConfigNew.m_bEnableTheFreezesF8Rom = ?; // todo: when support saving config
- //m_ConfigNew.m_bEnhanceDisk = ?; // todo: when support saving config
MemReset();
PravetsReset();
@@ -591,6 +605,9 @@ void Snapshot_SaveState(void)
yamlSaveHelper.UnitHdr(GetSnapshotUnitSlotsName(), UNIT_SLOTS_VER);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
+ if (IsApple2PlusOrClone(GetApple2Type()))
+ GetLanguageCard()->SaveSnapshot(yamlSaveHelper); // Language Card or Saturn 128K
+
Printer_SaveSnapshot(yamlSaveHelper);
sg_SSC.SaveSnapshot(yamlSaveHelper);
diff --git a/source/SaveState_Structs_common.h b/source/SaveState_Structs_common.h
index 2ba29f81..8a44ce8f 100644
--- a/source/SaveState_Structs_common.h
+++ b/source/SaveState_Structs_common.h
@@ -46,9 +46,6 @@ enum SS_UNIT_TYPE
const UINT nMemMainSize = 64*1024;
const UINT nMemAuxSize = 64*1024;
-const UINT kSLOT_LANG = 0;
-const UINT kSLOT_AUX = 8;
-
struct SS_CARD_HDR
{
SS_UNIT_HDR UnitHdr;
@@ -70,10 +67,13 @@ enum SS_CARDTYPE
CT_Phasor, // Soundcard
CT_Echo, // Soundcard
CT_SAM, // Soundcard: Software Automated Mouth
- CT_80Col, // 80 column card (no memory)
+ CT_80Col, // 80 column card (1K)
CT_Extended80Col, // Extended 80-col card (64K)
CT_RamWorksIII, // RamWorksIII (up to 8MB)
CT_Uthernet,
+ CT_LanguageCard, // Apple][ or ][+ in slot-0
+ CT_LanguageCardIIe, // Apple//e LC instance (not a card)
+ CT_Saturn128K, // Saturn 128K (but may be populated with less RAM, in multiples of 16K)
};
/////////////////////////////////////////////////////////////////////////////////
From 9e1170ca9eb54785c386bdf27c8131dd8e007567 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 27 Oct 2018 18:16:32 +0100
Subject: [PATCH 056/128] LC: Added more comments when loading save-state
memory v1 for II or II+
---
source/Memory.cpp | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)
diff --git a/source/Memory.cpp b/source/Memory.cpp
index a154114b..3996bee5 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -2108,9 +2108,15 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
if (!yamlLoadHelper.GetSubMap( MemGetSnapshotMainMemStructName() ))
throw std::string("Card: Expected key: ") + MemGetSnapshotMainMemStructName();
- memset(memmain, 0, _6502_MEM_END+1); // Clear it, as high 16K may not be in the save-state (eg. the case of Saturn replacing LC)
+ memset(memmain+0xC000, 0, LanguageCardSlot0::kMemBankSize); // Clear it, as high 16K may not be in the save-state's "Main Memory" (eg. the case of II+ Saturn replacing //e LC)
+
yamlLoadHelper.LoadMemory(memmain, _6502_MEM_END+1);
- memcpy(g_pMemMainLanguageCard, memmain+0xC000, LanguageCardSlot0::kMemBankSize);
+ if (version == 1 && IsApple2PlusOrClone(GetApple2Type()))
+ {
+ // v1 for II/II+ doesn't have a dedicated slot-0 LC, instead the 16K is stored as the top 16K of memmain
+ memcpy(g_pMemMainLanguageCard, memmain+0xC000, LanguageCardSlot0::kMemBankSize);
+ memset(memmain+0xC000, 0, LanguageCardSlot0::kMemBankSize);
+ }
memset(memdirty, 0, 0x100);
yamlLoadHelper.PopMap();
From 034337cb2857ce79469ee770d334e089602c1f2e Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 27 Oct 2018 18:48:47 +0100
Subject: [PATCH 057/128] Saturn: Change cmd-line to -s0
---
source/Applewin.cpp | 11 ++++-------
1 file changed, 4 insertions(+), 7 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index cb785c33..5dddcdf8 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1264,19 +1264,16 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
uRamWorksExPages = 1;
}
#endif
- else if (strcmp(lpCmdLine, "-saturn") == 0) // 64 = Saturn 64K (4 banks), 128 = Saturn 128K (8 banks)
+ else if (strcmp(lpCmdLine, "-s0") == 0)
{
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
// "The boards consist of 16K banks of memory (4 banks for the 64K board, 8 banks for the 128K), accessed one at a time" - Ref: "64K/128K RAM BOARD", Saturn Systems, Ch.1 Introduction(pg-5)
- uSaturnBanks = atoi(lpCmdLine) / 16; // number of 16K Banks [1..8]
- if (uSaturnBanks > Saturn128K::kMaxSaturnBanks)
+ if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0)
uSaturnBanks = Saturn128K::kMaxSaturnBanks;
- else
- if (uSaturnBanks < 1)
- uSaturnBanks = 1;
-
+ else if (strcmp(lpCmdLine, "saturn64") == 0)
+ uSaturnBanks = Saturn128K::kMaxSaturnBanks/2;
}
else if (strcmp(lpCmdLine, "-f8rom") == 0) // Use custom 2K ROM at [$F800..$FFFF]
{
From c90eb07f179808e34e8edc970ac25eb81345d3fa Mon Sep 17 00:00:00 2001
From: tomcw
Date: Wed, 31 Oct 2018 22:04:42 +0000
Subject: [PATCH 058/128] Saturn: Updated help docs
---
help/CommandLine.html | 7 +++++--
help/dbg-screen-layout.html | 1 +
help/savestate.html | 1 +
3 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/help/CommandLine.html b/help/CommandLine.html
index 73b56862..650318d3 100644
--- a/help/CommandLine.html
+++ b/help/CommandLine.html
@@ -19,14 +19,17 @@
Start with hard disk 1 plugged-in (and auto power-on the Apple II). NB. Hard disk controller card gets enabled.
-h2 <pathname>
Start with hard disk 2 plugged-in. NB. Hard disk controller card gets enabled.
+ -s0 <saturn|saturn64|saturn128>
+ Insert a Saturn 64K or Saturn 128K card into slot 0 in Apple II or Apple II+ machines (or similar clone).
+ Where -s0 saturn is an alias for -s0 saturn128.
-s7 empty
Remove the hard disk controller card from slot 7.
Useful to allow a floppy disk to boot from slot 6, drive 1. Use in combination with -d1.
-r <number of pages>
- Emulate a RAMworks III card with 1 to 127 pages (each page is 64K, giving a max of 8MB)
+ Emulate a RAMworks III card with 1 to 127 pages (each page is 64K, giving a max of 8MB) in the auxiliary slot in an Apple //e machine.
-load-state <savestate>
Load a save-state file
- NB. This takes precedent over the -d1,d2,h1,h2,s7 and -r switches.
+ NB. This takes precedent over the -d1,d2,h1,h2,s0,s7 and -r switches.
'rNN' will appear if a RAMworks 64K bank is active.
+
'sNN' will appear if a Saturn 16K bank is active.
diff --git a/help/savestate.html b/help/savestate.html
index ff5595f5..c98e7a32 100644
--- a/help/savestate.html
+++ b/help/savestate.html
@@ -21,6 +21,7 @@
The following are persisted to the file:
Apple model: ][, ][+, //e, Enhanced //e or clone (eg. Pravets)
+
Apple ]['s slot-0 language card: 16K Language Card, Saturn 64K or Saturn 128K
Apple //e's auxiliary card: 80 Column, Extended 80 Column or RamWorks III
Disk][ (even during r/w operation)
Hard disk (even during r/w operation)
From 09ab12d0b6f291a41845b3ab57df074d9ca67b6d Mon Sep 17 00:00:00 2001
From: tomcw
Date: Thu, 1 Nov 2018 21:14:16 +0000
Subject: [PATCH 059/128] Save-state: Keyboard - save 'Key Waiting' flag.
(Fixes #591)
---
source/Keyboard.cpp | 7 ++++++-
source/Keyboard.h | 2 +-
source/SaveState.cpp | 2 +-
3 files changed, 8 insertions(+), 3 deletions(-)
diff --git a/source/Keyboard.cpp b/source/Keyboard.cpp
index c28afd46..9fa5bdfe 100644
--- a/source/Keyboard.cpp
+++ b/source/Keyboard.cpp
@@ -552,6 +552,7 @@ void KeybSetSnapshot_v1(const BYTE LastKey)
//
#define SS_YAML_KEY_LASTKEY "Last Key"
+#define SS_YAML_KEY_KEYWAITING "Key Waiting"
static std::string KeybGetSnapshotStructName(void)
{
@@ -563,14 +564,18 @@ void KeybSaveSnapshot(YamlSaveHelper& yamlSaveHelper)
{
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", KeybGetSnapshotStructName().c_str());
yamlSaveHelper.SaveHexUint8(SS_YAML_KEY_LASTKEY, keycode);
+ yamlSaveHelper.SaveBool(SS_YAML_KEY_KEYWAITING, keywaiting ? true : false);
}
-void KeybLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
+void KeybLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
{
if (!yamlLoadHelper.GetSubMap(KeybGetSnapshotStructName()))
return;
keycode = (BYTE) yamlLoadHelper.LoadUint(SS_YAML_KEY_LASTKEY);
+ if (version == 2)
+ keywaiting = (BOOL) yamlLoadHelper.LoadBool(SS_YAML_KEY_KEYWAITING);
+
yamlLoadHelper.PopMap();
}
diff --git a/source/Keyboard.h b/source/Keyboard.h
index 65920f39..28b520b9 100644
--- a/source/Keyboard.h
+++ b/source/Keyboard.h
@@ -20,4 +20,4 @@ BYTE KeybReadData (void);
BYTE KeybReadFlag (void);
void KeybSetSnapshot_v1(const BYTE LastKey);
void KeybSaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
-void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
+void KeybLoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT version);
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index c248b81b..e7c36fad 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -335,7 +335,7 @@ static void ParseUnitApple2(YamlLoadHelper& yamlLoadHelper, UINT version)
m_ConfigNew.m_CpuType = GetMainCpu();
JoyLoadSnapshot(yamlLoadHelper);
- KeybLoadSnapshot(yamlLoadHelper);
+ KeybLoadSnapshot(yamlLoadHelper, version);
SpkrLoadSnapshot(yamlLoadHelper);
VideoLoadSnapshot(yamlLoadHelper);
MemLoadSnapshot(yamlLoadHelper, version);
From 13c393624bd83280836d30babbbfe2549ab0b5f9 Mon Sep 17 00:00:00 2001
From: TomCh
Date: Sun, 4 Nov 2018 15:07:46 +0000
Subject: [PATCH 060/128] Apple II original: default to 48K (ie. no Language
Card) (PR #592)
Added support for #590:
* Changed Apple II original to default to no LC
* Added new cmd-line switch: -s0
* Changed so when LC is in slot-0, it now use Apple II+'s F8 (auto-start) ROM
---
source/Applewin.cpp | 10 ++++-
source/Common.h | 5 +++
source/LanguageCard.cpp | 5 +++
source/LanguageCard.h | 3 +-
source/Memory.cpp | 83 ++++++++++++++++++++++++++++++++---------
source/SaveState.cpp | 2 +-
6 files changed, 88 insertions(+), 20 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 5dddcdf8..cb01a4b1 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1142,6 +1142,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
bool bSetFullScreen = false;
bool bBoot = false;
bool bChangedDisplayResolution = false;
+ bool bSlot0LanguageCard = false;
bool bSlot7Empty = false;
UINT bestWidth = 0, bestHeight = 0;
LPSTR szImageName_drive[NUM_DRIVES] = {NULL,NULL};
@@ -1269,11 +1270,12 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
- // "The boards consist of 16K banks of memory (4 banks for the 64K board, 8 banks for the 128K), accessed one at a time" - Ref: "64K/128K RAM BOARD", Saturn Systems, Ch.1 Introduction(pg-5)
if (strcmp(lpCmdLine, "saturn") == 0 || strcmp(lpCmdLine, "saturn128") == 0)
uSaturnBanks = Saturn128K::kMaxSaturnBanks;
else if (strcmp(lpCmdLine, "saturn64") == 0)
uSaturnBanks = Saturn128K::kMaxSaturnBanks/2;
+ else if (strcmp(lpCmdLine, "languagecard") == 0 || strcmp(lpCmdLine, "lc") == 0)
+ bSlot0LanguageCard = true;
}
else if (strcmp(lpCmdLine, "-f8rom") == 0) // Use custom 2K ROM at [$F800..$FFFF]
{
@@ -1470,6 +1472,12 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
uSaturnBanks = 0; // Don't reapply after a restart
}
+ if (bSlot0LanguageCard)
+ {
+ SetExpansionMemType(CT_LanguageCard);
+ bSlot0LanguageCard = false; // Don't reapply after a restart
+ }
+
DebugInitialize();
LogFileOutput("Main: DebugInitialize()\n");
diff --git a/source/Common.h b/source/Common.h
index 0bdfa9e4..c8572e96 100644
--- a/source/Common.h
+++ b/source/Common.h
@@ -193,6 +193,11 @@ enum eApple2Type {
A2TYPE_MAX
};
+inline bool IsApple2Original(eApple2Type type) // Apple ][
+{
+ return type == A2TYPE_APPLE2;
+}
+
inline bool IsApple2Plus(eApple2Type type) // Apple ][,][+
{
return (type & (APPLE2E_MASK|APPLE2C_MASK)) == 0;
diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp
index 44c6413f..2c61139c 100644
--- a/source/LanguageCard.cpp
+++ b/source/LanguageCard.cpp
@@ -44,6 +44,11 @@ LanguageCardUnit::LanguageCardUnit(void) :
SetMemMainLanguageCard(NULL, true);
}
+LanguageCardUnit::~LanguageCardUnit(void)
+{
+ SetMemMainLanguageCard(NULL);
+}
+
DWORD LanguageCardUnit::SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write)
{
memmode &= ~(MF_BANK2 | MF_HIGHRAM);
diff --git a/source/LanguageCard.h b/source/LanguageCard.h
index c3654dfe..7134b1d5 100644
--- a/source/LanguageCard.h
+++ b/source/LanguageCard.h
@@ -8,7 +8,7 @@ class LanguageCardUnit
{
public:
LanguageCardUnit(void);
- virtual ~LanguageCardUnit(void) {}
+ virtual ~LanguageCardUnit(void);
virtual DWORD SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write);
virtual void SetMemorySize(UINT banks) {} // No-op for //e and slot-0 16K LC
@@ -71,6 +71,7 @@ public:
virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
virtual bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+ // "The boards consist of 16K banks of memory (4 banks for the 64K board, 8 banks for the 128K), accessed one at a time" - Ref: "64K/128K RAM BOARD", Saturn Systems, Ch.1 Introduction(pg-5)
static const UINT kMaxSaturnBanks = 8; // 8 * 16K = 128K
static std::string GetSnapshotCardName(void);
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 3996bee5..52efdbe1 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -214,6 +214,9 @@ BYTE __stdcall IO_Annunciator(WORD programcounter, WORD address, BYTE write, BYT
//=============================================================================
+// Default memory types on a VM restart
+// - can be overwritten by cmd-line or loading a save-state
+static SS_CARDTYPE g_MemTypeAppleII = CT_Empty;
static SS_CARDTYPE g_MemTypeAppleIIPlus = CT_LanguageCard; // Keep a copy so it's not lost if machine type changes, eg: A][ -> A//e -> A][
static SS_CARDTYPE g_MemTypeAppleIIe = CT_Extended80Col; // Keep a copy so it's not lost if machine type changes, eg: A//e -> A][ -> A//e
static UINT g_uSaturnBanksFromCmdLine = 0;
@@ -221,14 +224,18 @@ static UINT g_uSaturnBanksFromCmdLine = 0;
// Called from MemLoadSnapshot()
static void ResetDefaultMachineMemTypes(void)
{
+ g_MemTypeAppleII = CT_Empty;
g_MemTypeAppleIIPlus = CT_LanguageCard;
g_MemTypeAppleIIe = CT_Extended80Col;
}
// Called from MemInitialize(), MemLoadSnapshot()
-void SetExpansionMemTypeDefault(void)
+static void SetExpansionMemTypeDefault(void)
{
- SS_CARDTYPE defaultType = IsApple2PlusOrClone(GetApple2Type()) ? g_MemTypeAppleIIPlus : g_MemTypeAppleIIe;
+ SS_CARDTYPE defaultType = IsApple2Original(GetApple2Type()) ? g_MemTypeAppleII
+ : IsApple2PlusOrClone(GetApple2Type()) ? g_MemTypeAppleIIPlus
+ : g_MemTypeAppleIIe;
+
SetExpansionMemType(defaultType);
}
@@ -239,7 +246,12 @@ void SetExpansionMemType(const SS_CARDTYPE type)
SS_CARDTYPE newSlotAuxCard;
// Set defaults:
- if (IsApple2PlusOrClone(GetApple2Type()))
+ if (IsApple2Original(GetApple2Type()))
+ {
+ newSlot0Card = CT_Empty;
+ newSlotAuxCard = CT_Empty;
+ }
+ else if (IsApple2PlusOrClone(GetApple2Type()))
{
newSlot0Card = CT_LanguageCard;
newSlotAuxCard = CT_Empty;
@@ -250,11 +262,12 @@ void SetExpansionMemType(const SS_CARDTYPE type)
newSlotAuxCard = CT_Extended80Col;
}
- if (type == CT_Saturn128K)
+ if (type == CT_LanguageCard || type == CT_Saturn128K)
{
+ g_MemTypeAppleII = type;
g_MemTypeAppleIIPlus = type;
if (IsApple2PlusOrClone(GetApple2Type()))
- newSlot0Card = CT_Saturn128K;
+ newSlot0Card = type;
else
newSlot0Card = CT_Empty; // NB. No slot0 for //e
}
@@ -264,18 +277,19 @@ void SetExpansionMemType(const SS_CARDTYPE type)
if (IsApple2PlusOrClone(GetApple2Type()))
newSlotAuxCard = CT_Empty; // NB. No aux slot for ][ or ][+
else
- newSlotAuxCard = CT_RamWorksIII;
+ newSlotAuxCard = type;
}
if (IsApple2PlusOrClone(GetApple2Type()))
{
delete g_pLanguageCard;
- g_pLanguageCard = NULL;
if (newSlot0Card == CT_Saturn128K)
g_pLanguageCard = new Saturn128K(g_uSaturnBanksFromCmdLine);
- else // newSlot0Card == CT_LanguageCard
+ else if (newSlot0Card == CT_LanguageCard)
g_pLanguageCard = new LanguageCardSlot0;
+ else
+ g_pLanguageCard = NULL;
}
else
{
@@ -283,8 +297,6 @@ void SetExpansionMemType(const SS_CARDTYPE type)
g_pLanguageCard = new LanguageCardUnit;
}
- _ASSERT(g_pMemMainLanguageCard);
-
g_Slot0 = newSlot0Card;
g_SlotAux = newSlotAuxCard;
}
@@ -318,12 +330,15 @@ void SetSaturnMemorySize(UINT banks)
static BOOL GetLastRamWrite(void)
{
- return g_pLanguageCard->GetLastRamWrite();
+ if (g_pLanguageCard)
+ return g_pLanguageCard->GetLastRamWrite();
+ return 0;
}
static void SetLastRamWrite(BOOL count)
{
- g_pLanguageCard->SetLastRamWrite(count);
+ if (g_pLanguageCard)
+ g_pLanguageCard->SetLastRamWrite(count);
}
//
@@ -338,6 +353,7 @@ void SetMemMainLanguageCard(LPBYTE ptr, bool bMemMain /*=false*/)
LanguageCardUnit* GetLanguageCard(void)
{
+ _ASSERT(g_pLanguageCard);
return g_pLanguageCard;
}
@@ -1003,7 +1019,12 @@ void MemResetPaging()
static void ResetPaging(BOOL initialize)
{
SetLastRamWrite(0);
- SetMemMode(LanguageCardUnit::kMemModeInitialState);
+
+ if (IsApple2PlusOrClone(GetApple2Type()) && g_Slot0 == CT_Empty)
+ SetMemMode(0);
+ else
+ SetMemMode(LanguageCardUnit::kMemModeInitialState);
+
UpdatePaging(initialize);
}
@@ -1178,8 +1199,6 @@ void MemDestroy()
mem = NULL;
- g_pMemMainLanguageCard = NULL;
-
ZeroMemory(memwrite, sizeof(memwrite));
ZeroMemory(memshadow,sizeof(memshadow));
}
@@ -1519,6 +1538,36 @@ void MemInitializeROM(void)
void MemInitializeCustomF8ROM(void)
{
const UINT F8RomSize = 0x800;
+ const UINT F8RomOffset = Apple2RomSize-F8RomSize;
+
+ if (IsApple2Original(GetApple2Type()) && g_Slot0 == CT_LanguageCard)
+ {
+ try
+ {
+ HRSRC hResInfo = FindResource(NULL, MAKEINTRESOURCE(IDR_APPLE2_PLUS_ROM), "ROM");
+ if (hResInfo == NULL)
+ throw false;
+
+ DWORD dwResSize = SizeofResource(NULL, hResInfo);
+ if(dwResSize != Apple2RomSize)
+ throw false;
+
+ HGLOBAL hResData = LoadResource(NULL, hResInfo);
+ if(hResData == NULL)
+ throw false;
+
+ BYTE* pData = (BYTE*) LockResource(hResData); // NB. Don't need to unlock resource
+ if (pData == NULL)
+ throw false;
+
+ memcpy(memrom+F8RomOffset, pData+F8RomOffset, F8RomSize);
+ }
+ catch (bool)
+ {
+ MessageBox( g_hFrameWindow, "Failed to read F8 (auto-start) ROM for language card in original Apple][", TEXT("AppleWin Error"), MB_OK );
+ }
+ }
+
if (g_hCustomRomF8 != INVALID_HANDLE_VALUE)
{
BYTE OldRom[Apple2RomSize]; // NB. 12KB on stack
@@ -1526,7 +1575,7 @@ void MemInitializeCustomF8ROM(void)
SetFilePointer(g_hCustomRomF8, 0, NULL, FILE_BEGIN);
DWORD uNumBytesRead;
- BOOL bRes = ReadFile(g_hCustomRomF8, memrom+Apple2RomSize-F8RomSize, F8RomSize, &uNumBytesRead, NULL);
+ BOOL bRes = ReadFile(g_hCustomRomF8, memrom+F8RomOffset, F8RomSize, &uNumBytesRead, NULL);
if (uNumBytesRead != F8RomSize)
{
memcpy(memrom, OldRom, Apple2RomSize); // ROM at $D000...$FFFF
@@ -1854,7 +1903,7 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
#endif
// DETERMINE THE NEW MEMORY PAGING MODE.
- if ((address >= 0x80) && (address <= 0x8F))
+ if (g_Slot0 != CT_Empty && (address >= 0x80 && address <= 0x8F))
{
SetMemMode( g_pLanguageCard->SetPaging(address, memmode, modechanging, write ? true : false) );
}
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index e7c36fad..c61cabf5 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -605,7 +605,7 @@ void Snapshot_SaveState(void)
yamlSaveHelper.UnitHdr(GetSnapshotUnitSlotsName(), UNIT_SLOTS_VER);
YamlSaveHelper::Label state(yamlSaveHelper, "%s:\n", SS_YAML_KEY_STATE);
- if (IsApple2PlusOrClone(GetApple2Type()))
+ if (g_Slot0 != CT_Empty && IsApple2PlusOrClone(GetApple2Type()))
GetLanguageCard()->SaveSnapshot(yamlSaveHelper); // Language Card or Saturn 128K
Printer_SaveSnapshot(yamlSaveHelper);
From f4ccc6929b5039a7068ad63d9f3d101d89fe7b50 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 4 Nov 2018 15:39:14 +0000
Subject: [PATCH 061/128] Help docs: updated for 48K Apple II and LC cmd-line
switch
---
help/CommandLine.html | 3 +++
help/cfg-config.html | 4 ++--
2 files changed, 5 insertions(+), 2 deletions(-)
diff --git a/help/CommandLine.html b/help/CommandLine.html
index 650318d3..9b3ff70f 100644
--- a/help/CommandLine.html
+++ b/help/CommandLine.html
@@ -22,6 +22,9 @@
-s0 <saturn|saturn64|saturn128>
Insert a Saturn 64K or Saturn 128K card into slot 0 in Apple II or Apple II+ machines (or similar clone).
Where -s0 saturn is an alias for -s0 saturn128.
+ -s0 <languagecard|lc>
+ Insert an Apple 16K Language Card into slot 0 in Apple II and use the F8 auto-start ROM.
+ NB. The Apple II+ already defaults to having a Language Card, so this switch is not required.
-s7 empty
Remove the hard disk controller card from slot 7.
Useful to allow a floppy disk to boot from slot 6, drive 1. Use in combination with -d1.
diff --git a/help/cfg-config.html b/help/cfg-config.html
index e8e027cf..5a6a036d 100644
--- a/help/cfg-config.html
+++ b/help/cfg-config.html
@@ -16,8 +16,8 @@
the predecessors of the Apple //e: the Apple ][ and Apple ][+. Besides running
with a different Apple system ROM, some differences are discussed below.
-
Apple ][ : Non-autobooting, 64K machine, no lower-case, no 80-column, 6502 CPU
-
Apple ][+ : Autobooting version of the Apple ][
+
Apple ][ : 48K non-autostarting, Integer BASIC, no lower-case, no 80-column, 6502 CPU
+
Apple ][+ : 64K autostarting, Applesoft BASIC version of the Apple ][
Apple //e : 128K machine, lower-case, 80-column, 6502 CPU
Enhanced Apple //e : 128K machine, lower-case, 80-column, 65C02 CPU
Clone (specific model selectable from Advanced page)
From 155547f847c9215c855099cf9935cc4f63515de2 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 4 Nov 2018 16:35:25 +0000
Subject: [PATCH 062/128] 1.27.10: Bump version & update History.txt
---
bin/History.txt | 14 ++++++++++++++
resource/Applewin.rc | 8 ++++----
source/Memory.cpp | 5 +++++
3 files changed, 23 insertions(+), 4 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index 152f821a..37886844 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -8,6 +8,20 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+
+1.27.10.0 - 4 Nov 2018
+----------------------
+. [Change #590] Apple II original: default to 48K (so no LC installed in slot-0).
+ - Added new command line switch: -s0
+ ('lc' is an alias for 'languagecard')
+ - When LC is in slot-0, it now use the Apple II+'s F8 (auto-start) ROM
+. [Change #408] Support Saturn 64K and 128K cards in slot-0.
+ - Added new command line switch: -s0
+ ('saturn' is an alias for 'saturn128')
+. [Bug #591] Save-state wasn't preserving the 'key-waiting' flag.
+. [Bug #587] Debugger: disassembly for branch targets < $1000 were missing the leading '0'.
+
+
1.27.9.0 - 2 Oct 2018
---------------------
. [Bug #582] Support for partial disk II latch reads when accesses are very close.
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index 8d985736..3a4d3378 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,9,0
- PRODUCTVERSION 1,27,9,0
+ FILEVERSION 1,27,10,0
+ PRODUCTVERSION 1,27,10,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 9, 0"
+ VALUE "FileVersion", "1, 27, 10, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 9, 0"
+ VALUE "ProductVersion", "1, 27, 10, 0"
END
END
BLOCK "VarFileInfo"
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 52efdbe1..42dcc991 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -2021,6 +2021,11 @@ LPVOID MemGetSlotParameters(UINT uSlot)
void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE* const pMemMain, const BYTE* const pMemAux)
{
+ // Create default LC type for AppleII machine (do prior to loading saved LC state)
+ ResetDefaultMachineMemTypes();
+ g_MemTypeAppleII = CT_LanguageCard; // SSv1 doesn't save machine type - so if current machine is Apple II then give it 64K + LC
+ SetExpansionMemTypeDefault();
+
SetMemMode(MemMode ^ MF_INTCXROM); // Convert from SLOTCXROM to INTCXROM
SetLastRamWrite(LastWriteRam);
From 325bc23d08395c2846fb5b4b98e3a6cf6d15c828 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 4 Nov 2018 17:29:22 +0000
Subject: [PATCH 063/128] Fix for LC when //e (broken 13c3936)
---
source/Common.h | 5 ++---
source/Memory.cpp | 5 +++--
2 files changed, 5 insertions(+), 5 deletions(-)
diff --git a/source/Common.h b/source/Common.h
index c8572e96..6dcf7756 100644
--- a/source/Common.h
+++ b/source/Common.h
@@ -200,7 +200,7 @@ inline bool IsApple2Original(eApple2Type type) // Apple ][
inline bool IsApple2Plus(eApple2Type type) // Apple ][,][+
{
- return (type & (APPLE2E_MASK|APPLE2C_MASK)) == 0;
+ return ((type & (APPLE2E_MASK|APPLE2C_MASK)) == 0) && !(type & APPLECLONE_MASK);
}
inline bool IsClone(eApple2Type type)
@@ -210,8 +210,7 @@ inline bool IsClone(eApple2Type type)
inline bool IsApple2PlusOrClone(eApple2Type type) // Apple ][,][+ or clone ][,][+
{
- return ((type & (APPLE2E_MASK|APPLE2C_MASK)) == 0)
- || (type & APPLECLONE_MASK) && !(type & A2TYPE_CLONE_A2E);
+ return (type & (APPLE2E_MASK|APPLE2C_MASK)) == 0;
}
extern eApple2Type g_Apple2Type;
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 42dcc991..cc43c55e 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -1903,9 +1903,10 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
#endif
// DETERMINE THE NEW MEMORY PAGING MODE.
- if (g_Slot0 != CT_Empty && (address >= 0x80 && address <= 0x8F))
+ if (address >= 0x80 && address <= 0x8F)
{
- SetMemMode( g_pLanguageCard->SetPaging(address, memmode, modechanging, write ? true : false) );
+ if (!IS_APPLE2 || (IsApple2PlusOrClone(GetApple2Type()) && g_Slot0 != CT_Empty))
+ SetMemMode( g_pLanguageCard->SetPaging(address, memmode, modechanging, write ? true : false) );
}
else if (!IS_APPLE2)
{
From 3bf94eca9ddf48813f7cd9809c7d6e7f6283d33d Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 4 Nov 2018 20:04:38 +0000
Subject: [PATCH 064/128] Fix for save-state v1: original Apple II needs a LC
---
source/Memory.cpp | 2 ++
1 file changed, 2 insertions(+)
diff --git a/source/Memory.cpp b/source/Memory.cpp
index cc43c55e..958a805a 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -2131,6 +2131,8 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
// Create default LC type for AppleII machine (do prior to loading saved LC state)
ResetDefaultMachineMemTypes();
+ if (version == 1)
+ g_MemTypeAppleII = CT_LanguageCard; // version=1: original Apple II always had a LC
SetExpansionMemTypeDefault();
//
From f9b7d9326ec5f448f3858c9820bc258822cb2297 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Tue, 6 Nov 2018 19:12:10 +0000
Subject: [PATCH 065/128] Fixed Coverity 'High Impact Outstanding' issues:
CIDs in main code:
1446691
1446688 (false positive)
1446672 (false positive)
1446643
1446642
1446641
1446635 (false positive)
CIDs in debugger:
1472410
1446728 (false positive)
1446684
1446673
1472409
1446693
1446692
1446726
1446687
1446685
1446683
---
source/Applewin.cpp | 4 +++
source/Debugger/Debug.cpp | 25 ++++++++++++-------
source/Debugger/Debugger_DisassemblerData.cpp | 7 +++++-
source/Debugger/Debugger_Display.cpp | 5 ++--
source/Debugger/Debugger_Parser.cpp | 6 ++---
source/DiskImageHelper.cpp | 1 +
source/Memory.cpp | 1 +
source/ParallelPrinter.cpp | 1 +
source/SerialComms.cpp | 1 +
9 files changed, 36 insertions(+), 15 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index cb01a4b1..46ea2718 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1281,6 +1281,10 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
+
+ if (g_hCustomRomF8 != INVALID_HANDLE_VALUE) // Stop resource leak if -f8rom is specified twice!
+ CloseHandle(g_hCustomRomF8);
+
g_hCustomRomF8 = CreateFile(lpCmdLine, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
g_bCustomRomF8Failed = true;
diff --git a/source/Debugger/Debug.cpp b/source/Debugger/Debug.cpp
index 8f2b6a64..233ec4fa 100644
--- a/source/Debugger/Debug.cpp
+++ b/source/Debugger/Debug.cpp
@@ -3639,7 +3639,7 @@ Update_t CmdFlagClear (int nArgs)
{
int iFlag = (g_iCommand - CMD_FLAG_CLR_C);
- if (g_iCommand == CMD_FLAG_CLEAR)
+ if (g_iCommand == CMD_FLAG_CLEAR) // Undocumented: "cl f f ... f", eg: "se n v c" (TODO: Conflicts with monitor command #L -> 000CL)
{
int iArg = nArgs;
while (iArg)
@@ -3648,9 +3648,10 @@ Update_t CmdFlagClear (int nArgs)
while (iFlag < _6502_NUM_FLAGS)
{
// if (g_aFlagNames[iFlag] == g_aArgs[iArg].sArg[0])
- if (g_aBreakpointSource[ BP_SRC_FLAG_N + iFlag ][0] == g_aArgs[iArg].sArg[0])
+ if (g_aBreakpointSource[ BP_SRC_FLAG_N - iFlag ][0] == toupper(g_aArgs[iArg].sArg[0]))
{
- regs.ps &= ~(1 << iFlag);
+ regs.ps &= ~(1 << (7-iFlag));
+ break;
}
iFlag++;
}
@@ -3670,7 +3671,7 @@ Update_t CmdFlagSet (int nArgs)
{
int iFlag = (g_iCommand - CMD_FLAG_SET_C);
- if (g_iCommand == CMD_FLAG_SET)
+ if (g_iCommand == CMD_FLAG_SET) // Undocumented: "se f f ... f", eg: "se n v c"
{
int iArg = nArgs;
while (iArg)
@@ -3679,9 +3680,10 @@ Update_t CmdFlagSet (int nArgs)
while (iFlag < _6502_NUM_FLAGS)
{
// if (g_aFlagNames[iFlag] == g_aArgs[iArg].sArg[0])
- if (g_aBreakpointSource[ BP_SRC_FLAG_N + iFlag ][0] == g_aArgs[iArg].sArg[0])
+ if (g_aBreakpointSource[ BP_SRC_FLAG_N - iFlag ][0] == toupper(g_aArgs[iArg].sArg[0]))
{
- regs.ps |= (1 << iFlag);
+ regs.ps |= (1 << (7-iFlag));
+ break;
}
iFlag++;
}
@@ -4151,8 +4153,12 @@ Update_t CmdConfigSetDebugDir (int nArgs)
{
_tcsncpy( sPath, g_sCurrentDir, 2 ); // Prefix with drive letter & colon
sPath[2] = 0;
+ _tcscat( sPath, g_aArgs[1].sArg );
+ }
+ else
+ {
+ _tcscpy( sPath, g_aArgs[1].sArg );
}
- _tcscat( sPath, g_aArgs[1].sArg );
}
else // Relative
{
@@ -6454,7 +6460,8 @@ Update_t CmdOutputRun (int nArgs)
// if (g_aArgs[1].bType & TYPE_QUOTED_2)
- _tcscpy( sMiniFileName, pFileName );
+ _tcsncpy( sMiniFileName, pFileName, sizeof(sMiniFileName) );
+ sMiniFileName[sizeof(sMiniFileName)-1] = 0;
// _tcscat( sMiniFileName, ".aws" ); // HACK: MAGIC STRING
if (pFileName[0] == '\\' || pFileName[1] == ':') // NB. Any prefix quote has already been stripped
@@ -7616,7 +7623,7 @@ Update_t CmdZeroPagePointer (int nArgs)
// int nPtrNum = g_aArgs[0].sArg[1] - '0'; // HACK: hard-coded to command length
int iZP = g_iCommand - CMD_ZEROPAGE_POINTER_0;
- if( (iZP < 0) || (iZP > MAX_ZEROPAGE_POINTERS) )
+ if( (iZP < 0) || (iZP >= MAX_ZEROPAGE_POINTERS) )
return Help_Arg_1( g_iCommand );
if (nArgs == 0)
diff --git a/source/Debugger/Debugger_DisassemblerData.cpp b/source/Debugger/Debugger_DisassemblerData.cpp
index c36a5618..0eded8e1 100644
--- a/source/Debugger/Debugger_DisassemblerData.cpp
+++ b/source/Debugger/Debugger_DisassemblerData.cpp
@@ -81,16 +81,21 @@ WORD _CmdDefineByteRange(int nArgs,int iArg,DisasmData_t & tData_)
// tData_.nArraySize = 0;
char *pSymbolName = "";
- char aSymbolName[ 32 ];
+ char aSymbolName[ MAX_SYMBOLS_LEN+1 ];
SymbolTable_Index_e eSymbolTable = SYMBOLS_ASSEMBLY;
bool bAutoDefineName = false; // 2.7.0.34
if( nArgs > 1 )
{
if( g_aArgs[ 2 ].eToken == TOKEN_COLON ) // 2.7.0.31 Bug fix: DB range, i.e. DB 174E:174F
+ {
bAutoDefineName = true;
+ }
else
+ {
pSymbolName = g_aArgs[ 1 ].sArg;
+ pSymbolName[MAX_SYMBOLS_LEN] = 0; // truncate to max symbol length
+ }
}
else
{
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 937eccf3..3a171829 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -1792,7 +1792,8 @@ void FormatDisassemblyLine( const DisasmLine_t & line, char * sDisassembly, cons
if (line.bTargetImmediate)
{
strcat( sDisassembly, "#" );
- strcpy( sTarget, line.sTarget ); // sTarget
+ strncpy( sTarget, line.sTarget, sizeof(sTarget) );
+ sTarget[sizeof(sTarget)-1] = 0;
}
else
sprintf( sTarget, g_aOpmodes[ line.iOpmode ].m_sFormat, line.nTarget );
@@ -2460,7 +2461,7 @@ void DrawMemory ( int line, int iMemDump )
char sText[ MAX_MEM_VIEW_TXT * 2 ];
char sData[ MAX_MEM_VIEW_TXT * 2 ];
- char sType [ 4 ] = "Mem";
+ char sType [ 6 ] = "Mem";
char sAddress[ 8 ] = "";
int iForeground = FG_INFO_OPCODE;
diff --git a/source/Debugger/Debugger_Parser.cpp b/source/Debugger/Debugger_Parser.cpp
index f28a4b8d..dbbfb664 100644
--- a/source/Debugger/Debugger_Parser.cpp
+++ b/source/Debugger/Debugger_Parser.cpp
@@ -127,7 +127,7 @@ int _Arg_Shift( int iSrc, int iEnd, int iDst )
{
if (iDst < 0)
return ARG_SYNTAX_ERROR;
- if (iDst > MAX_ARGS)
+ if (iDst >= MAX_ARGS)
return ARG_SYNTAX_ERROR;
int nArgs = (iEnd - iSrc);
@@ -151,10 +151,10 @@ int _Args_Insert( int iSrc, int iEnd, int nLen )
iSrc += nLen;
int iDst = iEnd + nLen;
- if (iDst > MAX_ARGS)
+ if (iDst >= MAX_ARGS)
return ARG_SYNTAX_ERROR;
- if (iSrc > MAX_ARGS)
+ if (iSrc >= MAX_ARGS)
return ARG_SYNTAX_ERROR;
while (nLen--)
diff --git a/source/DiskImageHelper.cpp b/source/DiskImageHelper.cpp
index f1c1a4e1..48ba633d 100644
--- a/source/DiskImageHelper.cpp
+++ b/source/DiskImageHelper.cpp
@@ -1268,6 +1268,7 @@ ImageError_e CImageHelperBase::CheckZipFile(LPCTSTR pszImageFilename, ImageInfo*
return eIMAGE_ERROR_ZIP;
strncpy(pImageInfo->szFilenameInZip, szFilename, MAX_PATH);
+ pImageInfo->szFilenameInZip[MAX_PATH-1] = 0;
memcpy(&pImageInfo->zipFileInfo.tmz_date, &file_info.tmu_date, sizeof(file_info.tmu_date));
pImageInfo->zipFileInfo.dosDate = file_info.dosDate;
pImageInfo->zipFileInfo.internal_fa = file_info.internal_fa;
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 958a805a..4c164140 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -1580,6 +1580,7 @@ void MemInitializeCustomF8ROM(void)
{
memcpy(memrom, OldRom, Apple2RomSize); // ROM at $D000...$FFFF
bRes = FALSE;
+ // NB. Keep g_hCustomRomF8 handle open - so that any next restart can load it again
}
if (!bRes)
diff --git a/source/ParallelPrinter.cpp b/source/ParallelPrinter.cpp
index 0916b083..a12c0171 100644
--- a/source/ParallelPrinter.cpp
+++ b/source/ParallelPrinter.cpp
@@ -315,6 +315,7 @@ bool Printer_LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT
inactivity = yamlLoadHelper.LoadUint(SS_YAML_KEY_INACTIVITY);
g_PrinterIdleLimit = yamlLoadHelper.LoadUint(SS_YAML_KEY_IDLELIMIT);
strncpy(g_szPrintFilename, yamlLoadHelper.LoadString(SS_YAML_KEY_FILENAME).c_str(), sizeof(g_szPrintFilename));
+ g_szPrintFilename[sizeof(g_szPrintFilename)-1] = 0;
if (yamlLoadHelper.LoadBool(SS_YAML_KEY_FILEOPEN))
{
diff --git a/source/SerialComms.cpp b/source/SerialComms.cpp
index ac410d19..f512d942 100644
--- a/source/SerialComms.cpp
+++ b/source/SerialComms.cpp
@@ -1316,6 +1316,7 @@ char* CSuperSerialCard::GetSerialPortChoices()
void CSuperSerialCard::SetSerialPortName(const char* pSerialPortName)
{
strncpy(m_ayCurrentSerialPortName, pSerialPortName, SIZEOF_SERIALCHOICE_ITEM);
+ m_ayCurrentSerialPortName[SIZEOF_SERIALCHOICE_ITEM-1] = 0;
// Init m_aySerialPortChoices, so that we have choices to show if serial is active when we 1st open Config dialog
GetSerialPortChoices();
From 42c58f54e74e5729eed03de638006b267ef3979f Mon Sep 17 00:00:00 2001
From: TomCh
Date: Fri, 9 Nov 2018 20:51:51 +0000
Subject: [PATCH 066/128] Refactor Language Card (#593)
* Refactor Language Card:
. MemSetPaging() now not used for $C080-C08F accesses.
- Instead LC registers its own I/O handler like all other slot 1-7 cards.
. Saturn uses base LC's 16K for bank0
* Move all 'modechanging = 0' to UpdatePaging()
---
source/LanguageCard.cpp | 119 ++++++++++++++++++++++++++++++----------
source/LanguageCard.h | 13 +++--
source/Memory.cpp | 74 +++++++++++++------------
source/Memory.h | 2 +
source/SaveState.cpp | 6 +-
5 files changed, 144 insertions(+), 70 deletions(-)
diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp
index 2c61139c..2ae13fc3 100644
--- a/source/LanguageCard.cpp
+++ b/source/LanguageCard.cpp
@@ -49,19 +49,28 @@ LanguageCardUnit::~LanguageCardUnit(void)
SetMemMainLanguageCard(NULL);
}
-DWORD LanguageCardUnit::SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write)
+void LanguageCardUnit::InitializeIO(void)
{
+ RegisterIoHandler(kSlot0, &LanguageCardUnit::IO, &LanguageCardUnit::IO, NULL, NULL, this, NULL);
+}
+
+BYTE __stdcall LanguageCardUnit::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nExecutedCycles)
+{
+ LanguageCardUnit* pLC = (LanguageCardUnit*) MemGetSlotParameters(kSlot0);
+
+ DWORD memmode = GetMemMode();
+ DWORD lastmemmode = memmode;
memmode &= ~(MF_BANK2 | MF_HIGHRAM);
- if (!(address & 8))
+ if (!(uAddr & 8))
memmode |= MF_BANK2;
- if (((address & 2) >> 1) == (address & 1))
+ if (((uAddr & 2) >> 1) == (uAddr & 1))
memmode |= MF_HIGHRAM;
- if (address & 1) // GH#392
+ if (uAddr & 1) // GH#392
{
- if (!write && GetLastRamWrite())
+ if (!bWrite && pLC->GetLastRamWrite())
{
memmode |= MF_WRITERAM; // UTAIIe:5-23
}
@@ -71,9 +80,36 @@ DWORD LanguageCardUnit::SetPaging(WORD address, DWORD memmode, BOOL& modechangin
memmode &= ~MF_WRITERAM; // UTAIIe:5-23
}
- SetLastRamWrite( ((address & 1) && !write) ); // UTAIIe:5-23
+ pLC->SetLastRamWrite( ((uAddr & 1) && !bWrite) ); // UTAIIe:5-23
+ SetMemMode(memmode);
- return memmode;
+ //
+
+ if (IS_APPLE2E)
+ {
+ // IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
+ // ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
+ // IT DOES SO.
+ //
+ // NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
+ // - although any data-race is probably a bug in the 6502 code too.
+ if ((PC < 0xC000) &&
+ (((*(LPDWORD)(mem+PC) & 0x00FFFEFF) == 0x00C0048D) || // Next: STA $C004 or STA $C005
+ ((*(LPDWORD)(mem+PC) & 0x00FFFEFF) == 0x00C0028D))) // Next: STA $C002 or STA $C003
+ {
+ SetModeChanging(1);
+ return bWrite ? 0 : MemReadFloatingBus(nExecutedCycles);
+ }
+ }
+
+ // IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
+ // WRITE TABLES.
+ if (lastmemmode != memmode)
+ {
+ MemUpdatePaging(0); // Initialize=0
+ }
+
+ return bWrite ? 0 : MemReadFloatingBus(nExecutedCycles);
}
//-------------------------------------
@@ -94,7 +130,7 @@ LanguageCardSlot0::~LanguageCardSlot0(void)
//
static const UINT kUNIT_LANGUAGECARD_VER = 1;
-static const UINT kSLOT_LANGUAGECARD = 0;
+static const UINT kSLOT_LANGUAGECARD = LanguageCardUnit::kSlot0;
#define SS_YAML_VALUE_CARD_LANGUAGECARD "Language Card"
@@ -188,7 +224,9 @@ Saturn128K::Saturn128K(UINT banks)
for (UINT i=0; im_uSaturnTotalBanks);
+ if (!pLC->m_uSaturnTotalBanks)
+ return bWrite ? 0 : MemReadFloatingBus(nExecutedCycles);
+
+ bool bBankChanged = false;
+ DWORD memmode=0, lastmemmode=0;
+
+ if (uAddr & (1<<2))
{
- m_uSaturnActiveBank = 0 // Saturn 128K Language Card Bank 0 .. 7
- | (address >> 1) & 4
- | (address >> 0) & 3;
+ pLC->m_uSaturnActiveBank = 0 // Saturn 128K Language Card Bank 0 .. 7
+ | (uAddr >> 1) & 4
+ | (uAddr >> 0) & 3;
- if (m_uSaturnActiveBank >= m_uSaturnTotalBanks)
+ if (pLC->m_uSaturnActiveBank >= pLC->m_uSaturnTotalBanks)
{
// EG. Run RAMTEST128K tests on a Saturn 64K card
// TODO: Saturn::UpdatePaging() should deal with this case:
// . Technically read floating-bus, write to nothing
// . But the mem cache doesn't support floating-bus reads from non-I/O space
- m_uSaturnActiveBank = m_uSaturnTotalBanks-1; // FIXME: just prevent crash for now!
+ pLC->m_uSaturnActiveBank = pLC->m_uSaturnTotalBanks-1; // FIXME: just prevent crash for now!
}
- SetMemMainLanguageCard( m_aSaturnBanks[ m_uSaturnActiveBank ] );
-
- modechanging = 1;
+ SetMemMainLanguageCard( pLC->m_aSaturnBanks[ pLC->m_uSaturnActiveBank ] );
+ bBankChanged = true;
}
else
{
+ memmode = GetMemMode();
+ lastmemmode = memmode;
memmode &= ~(MF_BANK2 | MF_HIGHRAM);
- if (!(address & 8))
+ if (!(uAddr & 8))
memmode |= MF_BANK2;
- if (((address & 2) >> 1) == (address & 1))
+ if (((uAddr & 2) >> 1) == (uAddr & 1))
memmode |= MF_HIGHRAM;
- if (address & 1 && GetLastRamWrite()) // Saturn differs from Apple's 16K LC: any access (LC is read-only)
+ if (uAddr & 1 && pLC->GetLastRamWrite())// Saturn differs from Apple's 16K LC: any access (LC is read-only)
memmode |= MF_WRITERAM;
else
memmode &= ~MF_WRITERAM;
- SetLastRamWrite(address & 1); // Saturn differs from Apple's 16K LC: any access (LC is read-only)
+ pLC->SetLastRamWrite(uAddr & 1); // Saturn differs from Apple's 16K LC: any access (LC is read-only)
+ SetMemMode(memmode);
}
- return memmode;
+ // NB. Unlike LC, no need to check if next opcode is STA $C002-5, as Saturn is not for //e
+
+ // IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
+ // WRITE TABLES.
+ if ((lastmemmode != memmode) || bBankChanged)
+ {
+ MemUpdatePaging(0); // Initialize=0
+ }
+
+ return bWrite ? 0 : MemReadFloatingBus(nExecutedCycles);
}
//
static const UINT kUNIT_SATURN_VER = 1;
-static const UINT kSLOT_SATURN = 0;
+static const UINT kSLOT_SATURN = LanguageCardUnit::kSlot0;
#define SS_YAML_VALUE_CARD_SATURN128 "Saturn 128"
diff --git a/source/LanguageCard.h b/source/LanguageCard.h
index 7134b1d5..f7cfaaa5 100644
--- a/source/LanguageCard.h
+++ b/source/LanguageCard.h
@@ -10,7 +10,7 @@ public:
LanguageCardUnit(void);
virtual ~LanguageCardUnit(void);
- virtual DWORD SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write);
+ virtual void InitializeIO(void);
virtual void SetMemorySize(UINT banks) {} // No-op for //e and slot-0 16K LC
virtual UINT GetActiveBank(void) { return 0; } // Always 0 as only 1x 16K bank
virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper) { _ASSERT(0); } // Not used for //e
@@ -20,7 +20,10 @@ public:
void SetLastRamWrite(BOOL count) { m_uLastRamWrite = count; }
SS_CARDTYPE GetMemoryType(void) { return m_type; }
+ static BYTE __stdcall IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nExecutedCycles);
+
static const UINT kMemModeInitialState;
+ static const UINT kSlot0 = 0;
protected:
SS_CARDTYPE m_type;
@@ -49,10 +52,10 @@ protected:
void SaveLCState(class YamlSaveHelper& yamlSaveHelper);
void LoadLCState(class YamlLoadHelper& yamlLoadHelper);
+ LPBYTE m_pMemory;
+
private:
std::string GetSnapshotMemStructName(void);
-
- LPBYTE m_pMemory;
};
//
@@ -65,12 +68,14 @@ public:
Saturn128K(UINT banks);
virtual ~Saturn128K(void);
- virtual DWORD SetPaging(WORD address, DWORD memmode, BOOL& modechanging, bool write);
+ virtual void InitializeIO(void);
virtual void SetMemorySize(UINT banks);
virtual UINT GetActiveBank(void);
virtual void SaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
virtual bool LoadSnapshot(class YamlLoadHelper& yamlLoadHelper, UINT slot, UINT version);
+ static BYTE __stdcall IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValue, ULONG nExecutedCycles);
+
// "The boards consist of 16K banks of memory (4 banks for the 64K board, 8 banks for the 128K), accessed one at a time" - Ref: "64K/128K RAM BOARD", Saturn Systems, Ch.1 Introduction(pg-5)
static const UINT kMaxSaturnBanks = 8; // 8 * 16K = 128K
static std::string GetSnapshotCardName(void);
diff --git a/source/Memory.cpp b/source/Memory.cpp
index 4c164140..da8caa25 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -229,7 +229,7 @@ static void ResetDefaultMachineMemTypes(void)
g_MemTypeAppleIIe = CT_Extended80Col;
}
-// Called from MemInitialize(), MemLoadSnapshot()
+// Called from MemInitialize(), MemLoadSnapshot(), MemSetSnapshot_v1()
static void SetExpansionMemTypeDefault(void)
{
SS_CARDTYPE defaultType = IsApple2Original(GetApple2Type()) ? g_MemTypeAppleII
@@ -280,25 +280,28 @@ void SetExpansionMemType(const SS_CARDTYPE type)
newSlotAuxCard = type;
}
+ g_Slot0 = newSlot0Card;
+ g_SlotAux = newSlotAuxCard;
+}
+
+void CreateLanguageCard(void)
+{
+ delete g_pLanguageCard;
+ g_pLanguageCard = NULL;
+
if (IsApple2PlusOrClone(GetApple2Type()))
{
- delete g_pLanguageCard;
-
- if (newSlot0Card == CT_Saturn128K)
+ if (g_Slot0 == CT_Saturn128K)
g_pLanguageCard = new Saturn128K(g_uSaturnBanksFromCmdLine);
- else if (newSlot0Card == CT_LanguageCard)
+ else if (g_Slot0 == CT_LanguageCard)
g_pLanguageCard = new LanguageCardSlot0;
else
g_pLanguageCard = NULL;
}
else
{
- delete g_pLanguageCard;
g_pLanguageCard = new LanguageCardUnit;
}
-
- g_Slot0 = newSlot0Card;
- g_SlotAux = newSlotAuxCard;
}
SS_CARDTYPE GetCurrentExpansionMemType(void)
@@ -969,6 +972,11 @@ static bool IsCardInSlot(const UINT uSlot)
//===========================================================================
+void SetModeChanging(BOOL value)
+{
+ modechanging = value;
+}
+
DWORD GetMemMode(void)
{
return memmode;
@@ -1037,6 +1045,8 @@ void MemUpdatePaging(BOOL initialize)
static void UpdatePaging(BOOL initialize)
{
+ modechanging = 0;
+
// SAVE THE CURRENT PAGING SHADOW TABLE
LPBYTE oldshadow[256];
if (!initialize)
@@ -1437,7 +1447,7 @@ void MemInitialize()
SetExpansionMemTypeDefault();
#ifdef RAMWORKS
- if (GetCurrentExpansionMemType() == CT_RamWorksIII)
+ if (g_SlotAux == CT_RamWorksIII)
{
// allocate memory for RAMWorks III - up to 8MB
g_uActiveBank = 0;
@@ -1452,6 +1462,8 @@ void MemInitialize()
//
+ CreateLanguageCard();
+
MemInitializeROM();
MemInitializeCustomF8ROM();
MemInitializeIO();
@@ -1580,9 +1592,10 @@ void MemInitializeCustomF8ROM(void)
{
memcpy(memrom, OldRom, Apple2RomSize); // ROM at $D000...$FFFF
bRes = FALSE;
- // NB. Keep g_hCustomRomF8 handle open - so that any next restart can load it again
}
+ // NB. If succeeded, then keep g_hCustomRomF8 handle open - so that any next restart can load it again
+
if (!bRes)
{
MessageBox( g_hFrameWindow, "Failed to read custom F8 rom", TEXT("AppleWin Error"), MB_OK );
@@ -1616,8 +1629,10 @@ void MemInitializeIO(void)
{
InitIoHandlers();
- const UINT uSlot = 0;
- RegisterIoHandler(uSlot, MemSetPaging, MemSetPaging, NULL, NULL, NULL, NULL);
+ if (g_pLanguageCard)
+ g_pLanguageCard->InitializeIO();
+ else
+ RegisterIoHandler(LanguageCardUnit::kSlot0, IO_Null, IO_Null, NULL, NULL, NULL, NULL);
// TODO: Cleanup peripheral setup!!!
PrintLoadRom(pCxRomPeripheral, 1); // $C100 : Parallel printer f/w
@@ -1904,12 +1919,7 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
#endif
// DETERMINE THE NEW MEMORY PAGING MODE.
- if (address >= 0x80 && address <= 0x8F)
- {
- if (!IS_APPLE2 || (IsApple2PlusOrClone(GetApple2Type()) && g_Slot0 != CT_Empty))
- SetMemMode( g_pLanguageCard->SetPaging(address, memmode, modechanging, write ? true : false) );
- }
- else if (!IS_APPLE2)
+ if (!IS_APPLE2)
{
switch (address)
{
@@ -1943,24 +1953,19 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
}
}
- if (GetCurrentExpansionMemType() != CT_Saturn128K) // TODO: Not sure this optimisation is valid for Saturn, so skip it for now
+ if (IS_APPLE2E)
{
- // IF THE EMULATED PROGRAM HAS JUST UPDATE THE MEMORY WRITE MODE AND IS
+ // IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
// ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
// IT DOES SO.
//
// NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
// - although any data-race is probably a bug in the 6502 code too.
if ((address >= 4) && (address <= 5) &&
- ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) {
+ ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) // Next: STA $C002 or STA $C003
+ {
modechanging = 1;
- return write ? 0 : MemReadFloatingBus(1, nExecutedCycles);
- }
- if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) &&
- (((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) ||
- ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) {
- modechanging = 1;
- return write ? 0 : MemReadFloatingBus(1, nExecutedCycles);
+ return 0; // For $C004 & $C005: entry to this func is always via a write to $C004 or $C005
}
}
@@ -1968,8 +1973,6 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
// WRITE TABLES.
if ((lastmemmode != memmode) || modechanging)
{
- modechanging = 0;
-
// NB. Must check MF_SLOTC3ROM too, as IoHandlerCardsIn() depends on both MF_INTCXROM|MF_SLOTC3ROM
if ((lastmemmode & (MF_INTCXROM|MF_SLOTC3ROM)) != (memmode & (MF_INTCXROM|MF_SLOTC3ROM)))
{
@@ -2027,6 +2030,7 @@ void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE*
ResetDefaultMachineMemTypes();
g_MemTypeAppleII = CT_LanguageCard; // SSv1 doesn't save machine type - so if current machine is Apple II then give it 64K + LC
SetExpansionMemTypeDefault();
+ CreateLanguageCard(); // Create LC here, as for SSv1 there is no slot-0 state
SetMemMode(MemMode ^ MF_INTCXROM); // Convert from SLOTCXROM to INTCXROM
SetLastRamWrite(LastWriteRam);
@@ -2037,7 +2041,6 @@ void MemSetSnapshot_v1(const DWORD MemMode, const BOOL LastWriteRam, const BYTE*
//
- modechanging = 0;
// NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v1()
UpdatePaging(1); // Initialize=1
}
@@ -2133,8 +2136,12 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
// Create default LC type for AppleII machine (do prior to loading saved LC state)
ResetDefaultMachineMemTypes();
if (version == 1)
- g_MemTypeAppleII = CT_LanguageCard; // version=1: original Apple II always had a LC
+ g_MemTypeAppleII = CT_LanguageCard; // version=1: original Apple II always has a LC
+ else
+ g_MemTypeAppleIIPlus = CT_Empty; // version=2+: Apple II/II+ initially start with slot-0 empty
SetExpansionMemTypeDefault();
+ CreateLanguageCard(); // Create default LC now for: (a) //e which has no slot-0 LC (so this is final)
+ // (b) II/II+ which get re-created later if slot-0 has a card
//
@@ -2181,7 +2188,6 @@ bool MemLoadSnapshot(YamlLoadHelper& yamlLoadHelper, UINT version)
//
- modechanging = 0;
// NB. MemUpdatePaging(TRUE) called at end of Snapshot_LoadState_v2()
UpdatePaging(1); // Initialize=1 (Still needed, even with call to MemUpdatePaging() - why?)
// TC-TODO: At this point, the cards haven't been loaded, so the card's expansion ROM is unknown - so pointless(?) calling this now
diff --git a/source/Memory.h b/source/Memory.h
index ff81ddab..6538ae01 100644
--- a/source/Memory.h
+++ b/source/Memory.h
@@ -66,6 +66,7 @@ LPBYTE MemGetBankPtr(const UINT nBank);
LPBYTE MemGetCxRomPeripheral();
DWORD GetMemMode(void);
void SetMemMode(DWORD memmode);
+void SetModeChanging(BOOL value);
bool MemIsAddrCodeMemory(const USHORT addr);
void MemInitialize ();
void MemInitializeROM(void);
@@ -92,6 +93,7 @@ BYTE __stdcall MemSetPaging(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG nExec
enum SS_CARDTYPE;
void SetExpansionMemType(const SS_CARDTYPE type);
SS_CARDTYPE GetCurrentExpansionMemType(void);
+void CreateLanguageCard(void);
void SetRamWorksMemorySize(UINT pages);
UINT GetRamWorksActiveBank(void);
diff --git a/source/SaveState.cpp b/source/SaveState.cpp
index c61cabf5..ca2fed79 100644
--- a/source/SaveState.cpp
+++ b/source/SaveState.cpp
@@ -371,7 +371,6 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT version)
if (!yamlLoadHelper.GetSubMap(std::string(SS_YAML_KEY_STATE)))
throw std::string(SS_YAML_KEY_UNIT ": Expected sub-map name: " SS_YAML_KEY_STATE);
- bool bIsCardSupported = true;
SS_CARDTYPE type = CT_Empty;
bool bRes = false;
@@ -420,21 +419,22 @@ static void ParseSlots(YamlLoadHelper& yamlLoadHelper, UINT version)
{
type = CT_LanguageCard;
SetExpansionMemType(type);
+ CreateLanguageCard();
bRes = GetLanguageCard()->LoadSnapshot(yamlLoadHelper, slot, version);
}
else if (card == Saturn128K::GetSnapshotCardName())
{
type = CT_Saturn128K;
SetExpansionMemType(type);
+ CreateLanguageCard();
bRes = GetLanguageCard()->LoadSnapshot(yamlLoadHelper, slot, version);
}
else
{
- bIsCardSupported = false;
throw std::string("Slots: Unknown card: " + card); // todo: don't throw - just ignore & continue
}
- if (bRes && bIsCardSupported)
+ if (bRes)
{
m_ConfigNew.m_Slot[slot] = type;
}
From 6fb5b3b0e8c511251d4a18b6cb4141b2f0764e16 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 10 Nov 2018 10:30:19 +0000
Subject: [PATCH 067/128] Refactor: consolidate 'modechanging' optimisations
into a single function
---
source/LanguageCard.cpp | 18 ++------------
source/Memory.cpp | 53 +++++++++++++++++++++++++----------------
source/Memory.h | 2 +-
3 files changed, 36 insertions(+), 37 deletions(-)
diff --git a/source/LanguageCard.cpp b/source/LanguageCard.cpp
index 2ae13fc3..24d3c64e 100644
--- a/source/LanguageCard.cpp
+++ b/source/LanguageCard.cpp
@@ -85,22 +85,8 @@ BYTE __stdcall LanguageCardUnit::IO(WORD PC, WORD uAddr, BYTE bWrite, BYTE uValu
//
- if (IS_APPLE2E)
- {
- // IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
- // ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
- // IT DOES SO.
- //
- // NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
- // - although any data-race is probably a bug in the 6502 code too.
- if ((PC < 0xC000) &&
- (((*(LPDWORD)(mem+PC) & 0x00FFFEFF) == 0x00C0048D) || // Next: STA $C004 or STA $C005
- ((*(LPDWORD)(mem+PC) & 0x00FFFEFF) == 0x00C0028D))) // Next: STA $C002 or STA $C003
- {
- SetModeChanging(1);
- return bWrite ? 0 : MemReadFloatingBus(nExecutedCycles);
- }
- }
+ if (MemOptimizeForModeChanging(PC, uAddr))
+ return bWrite ? 0 : MemReadFloatingBus(nExecutedCycles);
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
// WRITE TABLES.
diff --git a/source/Memory.cpp b/source/Memory.cpp
index da8caa25..0799589e 100644
--- a/source/Memory.cpp
+++ b/source/Memory.cpp
@@ -972,11 +972,6 @@ static bool IsCardInSlot(const UINT uSlot)
//===========================================================================
-void SetModeChanging(BOOL value)
-{
- modechanging = value;
-}
-
DWORD GetMemMode(void)
{
return memmode;
@@ -1953,21 +1948,8 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
}
}
- if (IS_APPLE2E)
- {
- // IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
- // ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
- // IT DOES SO.
- //
- // NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
- // - although any data-race is probably a bug in the 6502 code too.
- if ((address >= 4) && (address <= 5) &&
- ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) // Next: STA $C002 or STA $C003
- {
- modechanging = 1;
- return 0; // For $C004 & $C005: entry to this func is always via a write to $C004 or $C005
- }
- }
+ if (MemOptimizeForModeChanging(programcounter, address))
+ return write ? 0 : MemReadFloatingBus(nExecutedCycles);
// IF THE MEMORY PAGING MODE HAS CHANGED, UPDATE OUR MEMORY IMAGES AND
// WRITE TABLES.
@@ -2012,6 +1994,37 @@ BYTE __stdcall MemSetPaging(WORD programcounter, WORD address, BYTE write, BYTE
//===========================================================================
+bool MemOptimizeForModeChanging(WORD programcounter, WORD address)
+{
+ if (IS_APPLE2E)
+ {
+ // IF THE EMULATED PROGRAM HAS JUST UPDATED THE MEMORY WRITE MODE AND IS
+ // ABOUT TO UPDATE THE MEMORY READ MODE, HOLD OFF ON ANY PROCESSING UNTIL
+ // IT DOES SO.
+ //
+ // NB. A 6502 interrupt occurring between these memory write & read updates could lead to incorrect behaviour.
+ // - although any data-race is probably a bug in the 6502 code too.
+ if ((address >= 4) && (address <= 5) && // Now: RAMWRTOFF or RAMWRTON
+ ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D)) // Next: STA $C002(RAMRDOFF) or STA $C003(RAMRDON)
+ {
+ modechanging = 1;
+ return true;
+ }
+
+ if ((address >= 0x80) && (address <= 0x8F) && (programcounter < 0xC000) && // Now: LC
+ (((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0048D) || // Next: STA $C004(RAMWRTOFF) or STA $C005(RAMWRTON)
+ ((*(LPDWORD)(mem+programcounter) & 0x00FFFEFF) == 0x00C0028D))) // or STA $C002(RAMRDOFF) or STA $C003(RAMRDON)
+ {
+ modechanging = 1;
+ return true;
+ }
+ }
+
+ return false;
+}
+
+//===========================================================================
+
LPVOID MemGetSlotParameters(UINT uSlot)
{
_ASSERT(uSlot < NUM_SLOTS);
diff --git a/source/Memory.h b/source/Memory.h
index 6538ae01..7ae9c469 100644
--- a/source/Memory.h
+++ b/source/Memory.h
@@ -66,7 +66,7 @@ LPBYTE MemGetBankPtr(const UINT nBank);
LPBYTE MemGetCxRomPeripheral();
DWORD GetMemMode(void);
void SetMemMode(DWORD memmode);
-void SetModeChanging(BOOL value);
+bool MemOptimizeForModeChanging(WORD programcounter, WORD address);
bool MemIsAddrCodeMemory(const USHORT addr);
void MemInitialize ();
void MemInitializeROM(void);
From 14e0bb7b71080ad8945d0cfa5490f22afce102cb Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 10 Nov 2018 15:55:20 +0000
Subject: [PATCH 068/128] Added new switch: '-no-hook-alt' - used to prevent
left/right ALT from emulating open/closed apple keys (#583)
---
source/Applewin.cpp | 4 ++++
source/Frame.cpp | 10 +++++-----
source/Joystick.cpp | 14 +++++++++++++-
source/Joystick.h | 3 ++-
4 files changed, 24 insertions(+), 7 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 46ea2718..f0e787b8 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1313,6 +1313,10 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
{
g_bHookAltGrControl = true;
}
+ else if (strcmp(lpCmdLine, "-no-hook-alt") == 0) // GH#583
+ {
+ JoySetHookAltKeys(false);
+ }
else if (strcmp(lpCmdLine, "-spkr-inc") == 0)
{
lpCmdLine = GetCurrArg(lpNextArg);
diff --git a/source/Frame.cpp b/source/Frame.cpp
index eb4d5470..26841a44 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -1378,10 +1378,10 @@ LRESULT CALLBACK FrameWndProc (
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 now suppresses VK_LCONTROL
+ // . 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 = 1;
- BOOL autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
+ bool down = true;
+ bool autorep = (HIWORD(lparam) & KF_REPEAT) != 0;
BOOL IsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
#if DEBUG_KEY_MESSAGES
@@ -1436,8 +1436,8 @@ LRESULT CALLBACK FrameWndProc (
else
{
bool extended = (HIWORD(lparam) & KF_EXTENDED) != 0;
- BOOL down = 0;
- BOOL autorep = 0;
+ bool down = false;
+ bool autorep = false;
BOOL bIsJoyKey = JoyProcessKey((int)wparam, extended, down, autorep);
#if DEBUG_KEY_MESSAGES
diff --git a/source/Joystick.cpp b/source/Joystick.cpp
index bdcecfc7..01e61733 100644
--- a/source/Joystick.cpp
+++ b/source/Joystick.cpp
@@ -111,6 +111,15 @@ static UINT g_bJoyportEnabled = 0; // Set to use Joyport to drive the 3 button i
static UINT g_uJoyportActiveStick = 0;
static UINT g_uJoyportReadMode = JOYPORT_LEFTRIGHT;
+static bool g_bHookAltKeys = true;
+
+//===========================================================================
+
+void JoySetHookAltKeys(bool hook)
+{
+ g_bHookAltKeys = hook;
+}
+
//===========================================================================
void CheckJoystick0()
{
@@ -296,7 +305,7 @@ void JoyInitialize()
#define SUPPORT_CURSOR_KEYS
-BOOL JoyProcessKey(int virtkey, BOOL extended, BOOL down, BOOL autorep)
+BOOL JoyProcessKey(int virtkey, bool extended, bool down, bool autorep)
{
static struct
{
@@ -314,6 +323,9 @@ BOOL JoyProcessKey(int virtkey, BOOL extended, BOOL down, BOOL autorep)
return 0;
}
+ if (!g_bHookAltKeys && virtkey == VK_MENU) // GH#583
+ return 0;
+
//
BOOL keychange = 0;
diff --git a/source/Joystick.h b/source/Joystick.h
index 8d22876f..2e69d1ce 100644
--- a/source/Joystick.h
+++ b/source/Joystick.h
@@ -8,7 +8,7 @@ enum JOY1CHOICE {J1C_DISABLED=0, J1C_JOYSTICK2, J1C_KEYBD_CURSORS, J1C_KEYBD_NUM
enum {JOYSTICK_MODE_FLOATING=0, JOYSTICK_MODE_CENTERING}; // Joystick centering control
void JoyInitialize();
-BOOL JoyProcessKey(int,BOOL,BOOL,BOOL);
+BOOL JoyProcessKey(int,bool,bool,bool);
void JoyReset();
void JoySetButton(eBUTTON,eBUTTONSTATE);
BOOL JoySetEmulationType(HWND,DWORD,int, const bool bMousecardActive);
@@ -24,6 +24,7 @@ DWORD JoyGetJoyType(UINT num);
void JoySetTrim(short nValue, bool bAxisX);
short JoyGetTrim(bool bAxisX);
void JoyportControl(const UINT uControl);
+void JoySetHookAltKeys(bool hook);
void JoySetSnapshot_v1(const unsigned __int64 JoyCntrResetCycle);
void JoySaveSnapshot(class YamlSaveHelper& yamlSaveHelper);
void JoyLoadSnapshot(class YamlLoadHelper& yamlLoadHelper);
From aa59c718470d84287da8cf854de663287fc624ea Mon Sep 17 00:00:00 2001
From: TomCh
Date: Sat, 17 Nov 2018 16:29:17 +0000
Subject: [PATCH 069/128] Add support for PAL/European or custom 8K video ROMs
(#596)
Added new cmd-line switch: -videorom to replace the video ROM for the Enhanced //e.
- Support video ROM sizes of 4K, 8K and 16K (top 8K only).
- NB. The rocker switch is set to European video ROM.
F10 (for //e or Enhanced //e models) emulates the PAL //e's rocker switch (under the keyboard) to toggle between European or US video ROM.
Other:
- Fixed debugger's view of the AltCharSet soft-switch (it was showing the opposite state).
---
resource/Applewin.rc | 8 +--
source/Applewin.cpp | 20 +++++-
source/Debugger/Debugger_Display.cpp | 2 +-
source/Frame.cpp | 21 ++++--
source/NTSC.cpp | 2 +-
source/NTSC_CharSet.cpp | 100 ++++++++++++++++++++++++++-
source/NTSC_CharSet.h | 3 +-
source/Video.cpp | 63 ++++++++++++++++-
source/Video.h | 9 ++-
9 files changed, 208 insertions(+), 20 deletions(-)
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index 3a4d3378..3262496d 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,10,0
- PRODUCTVERSION 1,27,10,0
+ FILEVERSION 1,27,11,0
+ PRODUCTVERSION 1,27,11,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 10, 0"
+ VALUE "FileVersion", "1, 27, 11, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 10, 0"
+ VALUE "ProductVersion", "1, 27, 11, 0"
END
END
BLOCK "VarFileInfo"
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index f0e787b8..9d2fb161 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1289,6 +1289,22 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
g_bCustomRomF8Failed = true;
}
+ else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 4K,8K or 16K video ROM for Enhanced //e
+ {
+ lpCmdLine = GetCurrArg(lpNextArg);
+ lpNextArg = GetNextArg(lpNextArg);
+
+ if (!ReadVideoRomFile(lpCmdLine))
+ {
+ std::string msg = "Failed to load video rom (not found or not exactly 4/8/16KiB)";
+ LogFileOutput("%s", msg.c_str());
+ MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
+ }
+ else
+ {
+ SetVideoRomRockerSwitch(true); // Use PAL char set
+ }
+ }
else if (strcmp(lpCmdLine, "-printscreen") == 0) // Turn on display of the last filename print screen was saved to
{
g_bDisplayPrintScreenFileName = true;
@@ -1553,7 +1569,9 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (g_bCustomRomF8Failed)
{
- MessageBox(g_hFrameWindow, "Failed to load custom F8 rom (not found or not exactly 2KB)", TEXT("AppleWin Error"), MB_OK);
+ std::string msg = "Failed to load custom F8 rom (not found or not exactly 2KiB)";
+ LogFileOutput("%s", msg.c_str());
+ MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
bShutdown = true;
}
diff --git a/source/Debugger/Debugger_Display.cpp b/source/Debugger/Debugger_Display.cpp
index 3a171829..b9a8a62a 100644
--- a/source/Debugger/Debugger_Display.cpp
+++ b/source/Debugger/Debugger_Display.cpp
@@ -3089,7 +3089,7 @@ void DrawSoftSwitches( int iSoftSwitch )
_DrawSoftSwitch( rect, 0xC00C, bSet, "Col", "40", "80", NULL, bgMemory );
// C00E = off, C00F = on
- bSet = VideoGetSWAltCharSet();
+ bSet = !VideoGetSWAltCharSet();
_DrawSoftSwitch( rect, 0xC00E, bSet, NULL, "ASC", "MOUS", NULL, bgMemory ); // ASCII/MouseText
#if SOFTSWITCH_LANGCARD
diff --git a/source/Frame.cpp b/source/Frame.cpp
index 26841a44..de139893 100644
--- a/source/Frame.cpp
+++ b/source/Frame.cpp
@@ -1316,14 +1316,19 @@ LRESULT CALLBACK FrameWndProc (
}
else if (wparam == VK_F10)
{
- if (g_Apple2Type == A2TYPE_PRAVETS8A && !KeybGetCtrlStatus())
- {
- KeybToggleP8ACapsLock (); // F10: Toggles P8 Capslock
- }
- else
+ if (KeybGetCtrlStatus())
{
SetUsingCursor(FALSE); // Ctrl+F10
}
+ else if (g_Apple2Type == A2TYPE_APPLE2E || g_Apple2Type == A2TYPE_APPLE2EENHANCED)
+ {
+ 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)
{
@@ -1758,7 +1763,6 @@ LRESULT CALLBACK FrameWndProc (
KeybUpdateCtrlShiftStatus();
// http://msdn.microsoft.com/en-us/library/windows/desktop/gg153546(v=vs.85).aspx
- // v1.25.0: Alt-Return Alt-Enter toggle fullscreen
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
@@ -1772,7 +1776,10 @@ LRESULT CALLBACK FrameWndProc (
case WM_SYSKEYUP:
KeybUpdateCtrlShiftStatus();
- // v1.25.0: Alt-Return Alt-Enter toggle fullscreen
+ // 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
diff --git a/source/NTSC.cpp b/source/NTSC.cpp
index ae0b1503..088626dc 100644
--- a/source/NTSC.cpp
+++ b/source/NTSC.cpp
@@ -471,7 +471,7 @@ static void set_csbits()
case A2TYPE_APPLE2: csbits = &csbits_a2[0]; g_nVideoCharSet = 0; break;
case A2TYPE_APPLE2PLUS: csbits = &csbits_a2[0]; g_nVideoCharSet = 0; break;
case A2TYPE_APPLE2E: csbits = &csbits_2e[0]; break;
- case A2TYPE_APPLE2EENHANCED:csbits = &csbits_enhanced2e[0]; break;
+ case A2TYPE_APPLE2EENHANCED:csbits = GetEnhanced2e_csbits(); break;
case A2TYPE_PRAVETS82: csbits = &csbits_pravets82[0]; g_nVideoCharSet = 0; break; // Apple ][ clone
case A2TYPE_PRAVETS8M: csbits = &csbits_pravets8M[0]; g_nVideoCharSet = 0; break; // Apple ][ clone
case A2TYPE_PRAVETS8A: csbits = &csbits_pravets8C[0]; break; // Apple //e clone
diff --git a/source/NTSC_CharSet.cpp b/source/NTSC_CharSet.cpp
index 4fa37822..88d1250f 100644
--- a/source/NTSC_CharSet.cpp
+++ b/source/NTSC_CharSet.cpp
@@ -21,10 +21,12 @@ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#include "StdAfx.h"
#include "Applewin.h"
+#include "Video.h"
#include "NTSC_CharSet.h"
-unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e
+unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
+static unsigned char csbits_enhanced2e_pal[2][256][8]; // PAL Enhanced //e (2764 8K video ROM - top 4K) via rocker switch under keyboard
unsigned char csbits_2e[2][256][8]; // Original //e (no mousetext)
unsigned char csbits_a2[1][256][8]; // ][ and ][+
unsigned char csbits_pravets82[1][256][8]; // Pravets 82
@@ -86,6 +88,91 @@ static void get_csbits(csbits_t csbits, const char* resourceName, const UINT cy0
delete [] pBuffer;
}
+//-------------------------------------
+
+// ROM address (RA):
+// -----------------
+// . RA10,..,RA3;SEGC,SEGB,SEGA => [2^8][2^3] => 256 chars of 8 lines (total = 2KiB)
+// . VID7,..,VID0 is the 8-bit video character (eg. from TEXT/$400 memory)
+//
+// UTAIIe:8-13, Table 8.2:
+//
+// ALTCHRSET | RA10 | RA9
+//------------------------------------------
+// 0 | VID7 + VID6.FLASH | VID6.VID7
+// 1 | VID7 | VID6
+//
+// FLASH toggles every 16 VBLs, so alternates between selecting NORMAL control/special and INVERSE control/special
+//
+
+void userVideoRom4K(csbits_t csbits, const BYTE* pVideoRom)
+{
+ int RA = 0; // rom address
+ int i = 0;
+
+ // regular char set
+
+ for (; i<64; i++, RA+=8) // [00..3F] INVERSE / [40..7F] FLASH
+ {
+ for (int y=0; y<8; y++)
+ {
+ csbits[0][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
+ csbits[0][i+64][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-14 (Table 8.3) we use FLASH=0, so RA=00ccccccsss
+ }
+ }
+
+ RA = (1<<10 | 0<<9); // UTAIIe:8-14 (Table 8.3)
+
+ for (i=128; i<256; i++, RA+=8) // [80..BF] NORMAL
+ {
+ for (int y=0; y<8; y++)
+ {
+ csbits[0][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
+ }
+ }
+
+ RA = (1<<10 | 1<<9); // UTAIIe:8-14 (Table 8.3)
+
+ for (i=192; i<256; i++, RA+=8) // [C0..FF] NORMAL
+ {
+ for (int y=0; y<8; y++)
+ {
+ csbits[0][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
+ }
+ }
+
+ // alt char set
+
+ RA = 0;
+
+ for (i=0; i<256; i++, RA+=8) // [00..7F] INVERSE / [80..FF] NORMAL
+ {
+ for (int y=0; y<8; y++)
+ {
+ csbits[1][i][y] = pVideoRom[RA+y] ^ 0xff; // UTAIIe:8-11 "dot patterns in the video ROM are inverted..."
+ }
+ }
+}
+
+void userVideoRom(void)
+{
+ const BYTE* pVideoRom;
+ UINT size = GetVideoRom(pVideoRom); // 4K or 8K
+ if (!size)
+ return;
+
+ if (size == kVideoRomSize4K)
+ {
+ userVideoRom4K(&csbits_enhanced2e[0], pVideoRom);
+ return;
+ }
+
+ userVideoRom4K(&csbits_enhanced2e_pal[0], pVideoRom);
+ userVideoRom4K(&csbits_enhanced2e[0], &pVideoRom[4*1024]);
+}
+
+//-------------------------------------
+
void make_csbits(void)
{
get_csbits(&csbits_enhanced2e[0], TEXT("CHARSET40"), 0); // Enhanced //e: Alt char set off
@@ -99,4 +186,15 @@ void make_csbits(void)
// Original //e is just Enhanced //e with the 32 mousetext chars [0x40..0x5F] replaced by the non-alt charset chars [0x40..0x5F]
memcpy(csbits_2e, csbits_enhanced2e, sizeof(csbits_enhanced2e));
memcpy(&csbits_2e[1][64], &csbits_2e[0][64], 32*8);
+
+ // Try to use any user-provided video ROM for Enhanced //e
+ userVideoRom();
+}
+
+csbits_t GetEnhanced2e_csbits(void)
+{
+ if (IsVideoRom4K())
+ return csbits_enhanced2e;
+
+ return GetVideoRomRockerSwitch() == false ? csbits_enhanced2e : csbits_enhanced2e_pal;
}
diff --git a/source/NTSC_CharSet.h b/source/NTSC_CharSet.h
index 3f549059..465a2b51 100644
--- a/source/NTSC_CharSet.h
+++ b/source/NTSC_CharSet.h
@@ -2,7 +2,7 @@
typedef unsigned char (*csbits_t)[256][8];
-extern unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e
+extern unsigned char csbits_enhanced2e[2][256][8]; // Enhanced //e (2732 4K video ROM)
extern unsigned char csbits_2e[2][256][8]; // Original //e (no mousetext)
extern unsigned char csbits_a2[1][256][8]; // ][ and ][+
extern unsigned char csbits_pravets82[1][256][8]; // Pravets 82
@@ -10,3 +10,4 @@ extern unsigned char csbits_pravets8M[1][256][8]; // Pravets 8M
extern unsigned char csbits_pravets8C[2][256][8]; // Pravets 8A & 8C
void make_csbits(void);
+csbits_t GetEnhanced2e_csbits(void);
diff --git a/source/Video.cpp b/source/Video.cpp
index d5663f3b..3d593218 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -647,7 +647,7 @@ void VideoResetState ()
//===========================================================================
-BYTE VideoSetMode (WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
+BYTE VideoSetMode(WORD, WORD address, BYTE write, BYTE, ULONG uExecutedCycles)
{
address &= 0xFF;
@@ -1141,6 +1141,65 @@ static void Video_SaveScreenShot( const char *pScreenShotFileName, const VideoSc
}
}
+
+//===========================================================================
+
+static const UINT kVideoRomSize8K = kVideoRomSize4K*2;
+static const UINT kVideoRomSize16K = kVideoRomSize8K*2;
+static const UINT kVideoRomSizeMax = kVideoRomSize16K;
+static BYTE g_videoRom[kVideoRomSizeMax];
+static UINT g_videoRomSize = 0;
+static bool g_videoRomRockerSwitch = false;
+
+bool ReadVideoRomFile(const char* pRomFile)
+{
+ g_videoRomSize = 0;
+
+ HANDLE h = CreateFile(pRomFile, GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL);
+ if (h == INVALID_HANDLE_VALUE)
+ return false;
+
+ const ULONG size = GetFileSize(h, NULL);
+ if (size == kVideoRomSize4K || size == kVideoRomSize8K || size == kVideoRomSize16K)
+ {
+ DWORD bytesRead;
+ if (ReadFile(h, g_videoRom, size, &bytesRead, NULL) && bytesRead == size)
+ g_videoRomSize = size;
+ }
+
+ if (g_videoRomSize == kVideoRomSize16K)
+ {
+ // Use top 8K (assume bottom 8K is all 0xFF's)
+ memcpy(&g_videoRom[0], &g_videoRom[kVideoRomSize8K], kVideoRomSize8K);
+ g_videoRomSize = kVideoRomSize8K;
+ }
+
+ CloseHandle(h);
+
+ return g_videoRomSize != 0;
+}
+
+UINT GetVideoRom(const BYTE*& pVideoRom)
+{
+ pVideoRom = &g_videoRom[0];
+ return g_videoRomSize;
+}
+
+bool GetVideoRomRockerSwitch(void)
+{
+ return g_videoRomRockerSwitch;
+}
+
+void SetVideoRomRockerSwitch(bool state)
+{
+ g_videoRomRockerSwitch = state;
+}
+
+bool IsVideoRom4K(void)
+{
+ return g_videoRomSize == 0 || g_videoRomSize == kVideoRomSize4K;
+}
+
//===========================================================================
void Config_Load_Video()
@@ -1160,8 +1219,6 @@ void Config_Save_Video()
REGSAVE(TEXT(REGVALUE_VIDEO_MONO_COLOR ),g_nMonochromeRGB);
}
-// ____________________________________________________________________
-
//===========================================================================
static void videoCreateDIBSection()
{
diff --git a/source/Video.h b/source/Video.h
index bd064502..301b503b 100644
--- a/source/Video.h
+++ b/source/Video.h
@@ -198,7 +198,14 @@ enum VideoScreenShot_e
void Video_TakeScreenShot( VideoScreenShot_e iScreenShotType );
void Video_SetBitmapHeader( WinBmpHeader_t *pBmp, int nWidth, int nHeight, int nBitsPerPixel );
-BYTE VideoSetMode (WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
+BYTE VideoSetMode(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
+
+const UINT kVideoRomSize4K = 4*1024;
+bool ReadVideoRomFile(const char* pRomFile);
+UINT GetVideoRom(const BYTE*& pVideoRom);
+bool GetVideoRomRockerSwitch(void);
+void SetVideoRomRockerSwitch(bool state);
+bool IsVideoRom4K(void);
void Config_Load_Video(void);
void Config_Save_Video(void);
From 6bf729922572ac4e4a19cb7b43ec7cf660f422df Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 17 Nov 2018 17:02:09 +0000
Subject: [PATCH 070/128] 1.27.12: Bump version & update History.txt + help
---
bin/History.txt | 14 ++++++++++++++
help/CommandLine.html | 4 ++++
help/keyboard.html | 9 +++++----
resource/Applewin.rc | 8 ++++----
4 files changed, 27 insertions(+), 8 deletions(-)
diff --git a/bin/History.txt b/bin/History.txt
index 37886844..7dd8b0c0 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -9,6 +9,20 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.12.0 - 17 Nov 2018
+-----------------------
+. [Change #574] Add support for PAL/European or custom 8K video ROMs:
+ - Added new command line switch: -videorom
+ - Replaces the video ROM for the Enhanced //e.
+ - Support video ROM sizes of 4K, 8K and 16K (top 8K only).
+ - NB. The rocker switch is set to the European video ROM position.
+ - F10 (for //e or Enhanced //e models) emulates the PAL //e's rocker switch (under the keyboard).
+ - Use to toggle between European or US video ROM.
+. [Change #583] Added new switch: '-no-hook-alt':
+ - Used to prevent left/right ALT from emulating Open/Solid Apple keys.
+ - For European keyboards where AltGr is needed to type keys like '[',']'.
+
+
1.27.10.0 - 4 Nov 2018
----------------------
. [Change #590] Apple II original: default to 48K (so no LC installed in slot-0).
diff --git a/help/CommandLine.html b/help/CommandLine.html
index 9b3ff70f..0eb15a2d 100644
--- a/help/CommandLine.html
+++ b/help/CommandLine.html
@@ -44,6 +44,8 @@
NB. This changes the display resolution (and restores on exit).
-f8rom <rom-file>
Use custom 2K ROM at [$F800..$FFFF]. <rom-file> must be 2048 bytes long
+ -videorom <file>
+ Use an alternate European or custom 4K, 8K or 16K video ROM.
-printscreen
Enable the dialog box to display the last file saved to
-no-printscreen-key
@@ -51,6 +53,8 @@
-no-hook-system-key
Prevent certain system key combinations from being hooked (to prevent the emulator from trapping ALT+ESC, ALT+SPACE, ALT+TAB and CTRL+ESC). This means that the equivalent Open Apple+<key> combinations won't work within the emulator.
NB. This switch takes precedence over -hook-alt-tab and -hook-altgr-control.
+ -no-hook-alt
+ Prevent the left and right ALT keys from being hooked (eg. to prevent emulation of Open/Solid Apple keys via the ALT keys).
-hook-alt-tab
By default the emulator doesn't hook ALT+TAB. Use this to allow Open Apple+TAB to be readable by the emulated machine.
-hook-altgr-control
diff --git a/help/keyboard.html b/help/keyboard.html
index a228e2f1..10314837 100644
--- a/help/keyboard.html
+++ b/help/keyboard.html
@@ -86,10 +86,11 @@
through the configuration dialog. NB. Use Shift+F9 to reverse-cycle the display modes.
Function Key F9 + Ctrl + Shift:
This PC function key combo will toggle 50% scanline mode
-
Function Key F10 (or Ctrl+left mouse button):
- This PC function key will stop emulating an Apple joystick with the PC's mouse.
- In Pravets 8A emulation mode it servers as Caps Lock and Ctrl+F10 shall
- be used to stop emulating an Apple joystick with the PC's mouse.
+
Function Key F10:
+ In //e or Enhanced //e emulation mode it will emulate the rocker switch for European video ROM selection. Use the Command Line switch to use an alternate European video ROM file.
+ In Pravets 8A emulation mode it servers as Caps Lock.
+
Function Key F10 + Ctrl (or Ctrl+left mouse button):
+ This PC function key combo will stop emulating an Apple joystick with the PC's mouse.
Function Keys F11-F12:
These PC function keys correspond to saving/loading a save-state
file.
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index 3262496d..9c20dd50 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -252,8 +252,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,11,0
- PRODUCTVERSION 1,27,11,0
+ FILEVERSION 1,27,12,0
+ PRODUCTVERSION 1,27,12,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +271,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 11, 0"
+ VALUE "FileVersion", "1, 27, 12, 0"
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 11, 0"
+ VALUE "ProductVersion", "1, 27, 12, 0"
END
END
BLOCK "VarFileInfo"
From af899fa90acfd3ec2fde24146f9e7f2946c8c967 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 19 Nov 2018 22:15:04 +0000
Subject: [PATCH 071/128] Added support for Apple II/II+ 2K video ROMs (fixes
#205)
---
source/Applewin.cpp | 4 +--
source/NTSC_CharSet.cpp | 55 ++++++++++++++++++++++++++++++++++++++---
source/Video.cpp | 4 +--
source/Video.h | 3 ++-
4 files changed, 57 insertions(+), 9 deletions(-)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 9d2fb161..411a0ec8 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1289,14 +1289,14 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if ((g_hCustomRomF8 == INVALID_HANDLE_VALUE) || (GetFileSize(g_hCustomRomF8, NULL) != 0x800))
g_bCustomRomF8Failed = true;
}
- else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 4K,8K or 16K video ROM for Enhanced //e
+ else if (strcmp(lpCmdLine, "-videorom") == 0) // Use 2K (for II/II+). Use 4K,8K or 16K video ROM (for Enhanced //e)
{
lpCmdLine = GetCurrArg(lpNextArg);
lpNextArg = GetNextArg(lpNextArg);
if (!ReadVideoRomFile(lpCmdLine))
{
- std::string msg = "Failed to load video rom (not found or not exactly 4/8/16KiB)";
+ std::string msg = "Failed to load video rom (not found or not exactly 2/4/8/16KiB)";
LogFileOutput("%s", msg.c_str());
MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
}
diff --git a/source/NTSC_CharSet.cpp b/source/NTSC_CharSet.cpp
index 88d1250f..a150f26b 100644
--- a/source/NTSC_CharSet.cpp
+++ b/source/NTSC_CharSet.cpp
@@ -154,11 +154,11 @@ void userVideoRom4K(csbits_t csbits, const BYTE* pVideoRom)
}
}
-void userVideoRom(void)
+void userVideoRomForIIe(void)
{
const BYTE* pVideoRom;
- UINT size = GetVideoRom(pVideoRom); // 4K or 8K
- if (!size)
+ UINT size = GetVideoRom(pVideoRom); // 2K or 4K or 8K
+ if (size < kVideoRomSize4K)
return;
if (size == kVideoRomSize4K)
@@ -173,6 +173,50 @@ void userVideoRom(void)
//-------------------------------------
+void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom)
+{
+ int RA = 0; // rom address
+
+ for (int i=0; i<256; i++, RA+=8)
+ {
+ for (int y=0; y<8; y++)
+ {
+ BYTE d=0;
+ BYTE n = pVideoRom[RA+y];
+
+ // UTAII:8-30 "Bit 7 of your EPROM fonts will control flashing in the lower 1024 bytes of the EPROM"
+ // UTAII:8-31 "If you leave O7 (EPROM Output7) reset in these patterns, the resulting characters will be inversions..."
+ if (!(n & 0x80) && RA < 1024)
+ n = n ^ 0x7f;
+ n &= 0x7f;
+
+ // UTAII:8-30 "TEXT ROM pattern is ... reversed"
+ for (BYTE j=0; j<7; j++)
+ {
+ if (n & 1)
+ d |= 1;
+ d <<= 1;
+ n >>= 1;
+ }
+
+ d >>= 1; // Undo the last left shift
+ csbits[0][i][y] = d;
+ }
+ }
+}
+
+void userVideoRomForIIPlus(void)
+{
+ const BYTE* pVideoRom;
+ UINT size = GetVideoRom(pVideoRom); // 2K or 4K or 8K
+ if (size != kVideoRomSize2K)
+ return;
+
+ userVideoRom2K(&csbits_a2[0], pVideoRom);
+}
+
+//-------------------------------------
+
void make_csbits(void)
{
get_csbits(&csbits_enhanced2e[0], TEXT("CHARSET40"), 0); // Enhanced //e: Alt char set off
@@ -188,7 +232,10 @@ void make_csbits(void)
memcpy(&csbits_2e[1][64], &csbits_2e[0][64], 32*8);
// Try to use any user-provided video ROM for Enhanced //e
- userVideoRom();
+ userVideoRomForIIe();
+
+ // Try to use any user-provided video ROM for II/II+
+ userVideoRomForIIPlus();
}
csbits_t GetEnhanced2e_csbits(void)
diff --git a/source/Video.cpp b/source/Video.cpp
index 3d593218..c26b56e6 100644
--- a/source/Video.cpp
+++ b/source/Video.cpp
@@ -1160,7 +1160,7 @@ bool ReadVideoRomFile(const char* pRomFile)
return false;
const ULONG size = GetFileSize(h, NULL);
- if (size == kVideoRomSize4K || size == kVideoRomSize8K || size == kVideoRomSize16K)
+ if (size == kVideoRomSize2K || size == kVideoRomSize4K || size == kVideoRomSize8K || size == kVideoRomSize16K)
{
DWORD bytesRead;
if (ReadFile(h, g_videoRom, size, &bytesRead, NULL) && bytesRead == size)
@@ -1197,7 +1197,7 @@ void SetVideoRomRockerSwitch(bool state)
bool IsVideoRom4K(void)
{
- return g_videoRomSize == 0 || g_videoRomSize == kVideoRomSize4K;
+ return g_videoRomSize <= kVideoRomSize4K;
}
//===========================================================================
diff --git a/source/Video.h b/source/Video.h
index 301b503b..2ab5d360 100644
--- a/source/Video.h
+++ b/source/Video.h
@@ -200,7 +200,8 @@ void Video_SetBitmapHeader( WinBmpHeader_t *pBmp, int nWidth, int nHeight, int n
BYTE VideoSetMode(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULONG uExecutedCycles);
-const UINT kVideoRomSize4K = 4*1024;
+const UINT kVideoRomSize2K = 1024*2;
+const UINT kVideoRomSize4K = kVideoRomSize2K*2;
bool ReadVideoRomFile(const char* pRomFile);
UINT GetVideoRom(const BYTE*& pVideoRom);
bool GetVideoRomRockerSwitch(void);
From cbd41333c944bc427745feacc3c0563fcd0b29f4 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Wed, 21 Nov 2018 21:21:54 +0000
Subject: [PATCH 072/128] 2K ROM: refactor
---
source/NTSC_CharSet.cpp | 13 +++----------
1 file changed, 3 insertions(+), 10 deletions(-)
diff --git a/source/NTSC_CharSet.cpp b/source/NTSC_CharSet.cpp
index a150f26b..a5d6c906 100644
--- a/source/NTSC_CharSet.cpp
+++ b/source/NTSC_CharSet.cpp
@@ -181,25 +181,18 @@ void userVideoRom2K(csbits_t csbits, const BYTE* pVideoRom)
{
for (int y=0; y<8; y++)
{
- BYTE d=0;
BYTE n = pVideoRom[RA+y];
// UTAII:8-30 "Bit 7 of your EPROM fonts will control flashing in the lower 1024 bytes of the EPROM"
// UTAII:8-31 "If you leave O7 (EPROM Output7) reset in these patterns, the resulting characters will be inversions..."
if (!(n & 0x80) && RA < 1024)
n = n ^ 0x7f;
- n &= 0x7f;
// UTAII:8-30 "TEXT ROM pattern is ... reversed"
- for (BYTE j=0; j<7; j++)
- {
- if (n & 1)
- d |= 1;
- d <<= 1;
- n >>= 1;
- }
+ BYTE d = 0;
+ for (BYTE j=0; j<7; j++, n >>= 1) // Just bits [0..6]
+ d = (d << 1) | (n & 1);
- d >>= 1; // Undo the last left shift
csbits[0][i][y] = d;
}
}
From 5504d280c7d1606c1cf64d26f6f06a200b5ca40c Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 3 Dec 2018 17:38:52 +0000
Subject: [PATCH 073/128] When drive is off then data register holds its
present state. (Fixes #599) NB. Drive off = motor off && stopped spinning
after 1 sec delay.
---
source/Disk.cpp | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git a/source/Disk.cpp b/source/Disk.cpp
index d3998ae7..06cb34dc 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -892,10 +892,14 @@ static void __stdcall DiskReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULO
}
}
- // Should really test for drive off - after 1 second drive off delay (UTAIIe page 9-13)
- // but Sherwood Forest sets shift mode and reads with the drive off, so don't check for now
if (!floppywritemode)
{
+ // Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13)
+ // "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12)
+ // Note: Sherwood Forest sets shift mode and reads with the drive off.
+ if (!pDrive->spinning) // GH#599
+ return;
+
const ULONG nReadCycleDiff = (ULONG) (g_nCumulativeCycles - g_uDiskLastReadLatchCycle);
// Support partial nibble read if disk reads are very close: (GH#582)
@@ -954,10 +958,8 @@ static void __stdcall DiskReadWrite(WORD pc, WORD addr, BYTE bWrite, BYTE d, ULO
if (++pFloppy->byte >= pFloppy->nibbles)
pFloppy->byte = 0;
- // Feature Request #201 Show track status
- // https://github.com/AppleWin/AppleWin/issues/201
- // NB. Prevent flooding of forcing UI to redraw!!!
- if( ((pFloppy->byte) & 0xFF) == 0 )
+ // Show track status (GH#201) - NB. Prevent flooding of forcing UI to redraw!!!
+ if ((pFloppy->byte & 0xFF) == 0)
FrameDrawDiskStatus( (HDC)0 );
}
@@ -1052,11 +1054,16 @@ bool DiskSelect(const int iDrive)
static void __stdcall DiskLoadWriteProtect(WORD, WORD, BYTE write, BYTE value, ULONG)
{
/* floppyloadmode = 1; */
+
+ // Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13)
+ // "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12)
+ // Note: Gemstone Warrior sets load mode with the drive off.
+ if (g_aFloppyDrive[currdrive].spinning) // GH#599
+ return;
+
if (!write)
{
// Notes:
- // . Should really test for drive off - after 1 second drive off delay (UTAIIe page 9-13)
- // but Gemstone Warrior sets load mode with the drive off, so don't check for now
// . Phase 1 on also forces write protect in the Disk II drive (UTAIIe page 9-7) but we don't implement that
// . write mode doesn't prevent reading write protect (GH#537):
// "If for some reason the above write protect check were entered with the READ/WRITE switch in WRITE,
From 5ddff0d688e29e5d32b5ea025ca62dc1e158fe4c Mon Sep 17 00:00:00 2001
From: tomcw
Date: Mon, 3 Dec 2018 21:36:54 +0000
Subject: [PATCH 074/128] DiskII: read write protect - fix spinning test
---
source/Disk.cpp | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/source/Disk.cpp b/source/Disk.cpp
index 06cb34dc..b07f16ab 100644
--- a/source/Disk.cpp
+++ b/source/Disk.cpp
@@ -1058,7 +1058,7 @@ static void __stdcall DiskLoadWriteProtect(WORD, WORD, BYTE write, BYTE value, U
// Don't change latch if drive off after 1 second drive-off delay (UTAIIe page 9-13)
// "DRIVES OFF forces the data register to hold its present state." (UTAIIe page 9-12)
// Note: Gemstone Warrior sets load mode with the drive off.
- if (g_aFloppyDrive[currdrive].spinning) // GH#599
+ if (!g_aFloppyDrive[currdrive].spinning) // GH#599
return;
if (!write)
From 54fffdf25a978c33faf4e62557b0d67d125bc912 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 8 Dec 2018 13:29:48 +0000
Subject: [PATCH 075/128] 1.27.13: Bump version & update History.txt + help
---
AppleWinExpress2008.vcproj | 4 ++++
bin/History.txt | 9 ++++++++-
help/CommandLine.html | 14 ++++++++------
help/dbg-screen-layout.html | 4 ++--
help/savestate.html | 3 +++
resource/Applewin.rc | 9 +++++----
resource/version.h | 5 +++++
source/Applewin.cpp | 4 ++--
8 files changed, 37 insertions(+), 15 deletions(-)
create mode 100644 resource/version.h
diff --git a/AppleWinExpress2008.vcproj b/AppleWinExpress2008.vcproj
index 1b926246..ccc80c1f 100644
--- a/AppleWinExpress2008.vcproj
+++ b/AppleWinExpress2008.vcproj
@@ -1285,6 +1285,10 @@
RelativePath=".\resource\TKClock.rom"
>
+
+
diff --git a/bin/History.txt b/bin/History.txt
index 7dd8b0c0..f4a9a2a7 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -8,10 +8,17 @@ https://github.com/AppleWin/AppleWin/issues/new
Tom Charlesworth
+1.27.13.0 - 8 Dec 2018
+----------------------
+. [Bug #599] Fix for Ultima V not loading in Authentic Speed mode (regression introduced at 1.27.9.0).
+. [Change #205] Added support for Apple II/II+ custom 2K video ROMs.
+ - Extended command line switch: -videorom
+ - If the ROM sizs is 2K, then it replaces the video ROM for the Apple II/II+.
+
1.27.12.0 - 17 Nov 2018
-----------------------
-. [Change #574] Add support for PAL/European or custom 8K video ROMs:
+. [Change #574] Added support for PAL/European or custom 8K video ROMs:
- Added new command line switch: -videorom
- Replaces the video ROM for the Enhanced //e.
- Support video ROM sizes of 4K, 8K and 16K (top 8K only).
diff --git a/help/CommandLine.html b/help/CommandLine.html
index 0eb15a2d..1d265e69 100644
--- a/help/CommandLine.html
+++ b/help/CommandLine.html
@@ -20,16 +20,16 @@
-h2 <pathname>
Start with hard disk 2 plugged-in. NB. Hard disk controller card gets enabled.
-s0 <saturn|saturn64|saturn128>
- Insert a Saturn 64K or Saturn 128K card into slot 0 in Apple II or Apple II+ machines (or similar clone).
+ Insert a Saturn 64K or Saturn 128K card into slot 0 in the Apple II or II+ machines (or similar clone).
Where -s0 saturn is an alias for -s0 saturn128.
-s0 <languagecard|lc>
- Insert an Apple 16K Language Card into slot 0 in Apple II and use the F8 auto-start ROM.
+ Insert an Apple 16K Language Card into slot 0 in the original Apple II and use the F8 auto-start ROM.
NB. The Apple II+ already defaults to having a Language Card, so this switch is not required.
-s7 empty
Remove the hard disk controller card from slot 7.
Useful to allow a floppy disk to boot from slot 6, drive 1. Use in combination with -d1.
-r <number of pages>
- Emulate a RAMworks III card with 1 to 127 pages (each page is 64K, giving a max of 8MB) in the auxiliary slot in an Apple //e machine.
+ Emulate a RamWorks III card with 1 to 127 pages (each page is 64K, giving a max of 8MB) in the auxiliary slot in an Apple //e machine.
-load-state <savestate>
Load a save-state file
NB. This takes precedent over the -d1,d2,h1,h2,s0,s7 and -r switches.
@@ -42,10 +42,12 @@
nnnn: select a specific resolution with height=nnnn pixels
NB. This changes the display resolution (and restores on exit).
- -f8rom <rom-file>
- Use custom 2K ROM at [$F800..$FFFF]. <rom-file> must be 2048 bytes long
+ -f8rom <file>
+ Use custom 2K ROM for any Apple II machine at [$F800..$FFFF]. <file> must be 2048 bytes long
-videorom <file>
- Use an alternate European or custom 4K, 8K or 16K video ROM.
+ Use an alternate custom 2K video ROM for Apple II or II+ machines (but not clones).
+ Use an alternate European or custom 4K, 8K or 16K (top 8K only) video ROM for the Enhanced //e.
+ NB. There's currently no support for using an alternate video ROM for the original Apple //e or clones.
-printscreen
Enable the dialog box to display the last file saved to
Note: Only the file names of the disk images are stored in the .yaml file (not the
full path). This allows you to move your disk image around or distribute them.
diff --git a/resource/Applewin.rc b/resource/Applewin.rc
index 9c20dd50..ffcc230e 100644
--- a/resource/Applewin.rc
+++ b/resource/Applewin.rc
@@ -1,6 +1,7 @@
// Microsoft Visual C++ generated resource script.
//
#include "resource.h"
+#include "version.h"
#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
@@ -252,8 +253,8 @@ DISK_ICON ICON "DISK.ICO"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 1,27,12,0
- PRODUCTVERSION 1,27,12,0
+ FILEVERSION APPLEWIN_VERSION
+ PRODUCTVERSION APPLEWIN_VERSION
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -271,12 +272,12 @@ BEGIN
VALUE "Comments", "https://github.com/AppleWin"
VALUE "CompanyName", "AppleWin"
VALUE "FileDescription", "Apple //e Emulator for Windows"
- VALUE "FileVersion", "1, 27, 12, 0"
+ VALUE "FileVersion", APPLEWIN_VERSION_STR
VALUE "InternalName", "APPLEWIN"
VALUE "LegalCopyright", " 1994-2018 Michael O'Brien, Oliver Schmidt, Tom Charlesworth, Michael Pohoreski, Nick Westgate, Linards Ticmanis"
VALUE "OriginalFilename", "APPLEWIN.EXE"
VALUE "ProductName", "Apple //e Emulator"
- VALUE "ProductVersion", "1, 27, 12, 0"
+ VALUE "ProductVersion", APPLEWIN_VERSION_STR
END
END
BLOCK "VarFileInfo"
diff --git a/resource/version.h b/resource/version.h
new file mode 100644
index 00000000..ba6ac1b3
--- /dev/null
+++ b/resource/version.h
@@ -0,0 +1,5 @@
+#define APPLEWIN_VERSION 1,27,13,0
+
+#define xstr(a) str(a)
+#define str(a) #a
+#define APPLEWIN_VERSION_STR xstr(APPLEWIN_VERSION)
diff --git a/source/Applewin.cpp b/source/Applewin.cpp
index 411a0ec8..a63fbb39 100644
--- a/source/Applewin.cpp
+++ b/source/Applewin.cpp
@@ -1296,7 +1296,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (!ReadVideoRomFile(lpCmdLine))
{
- std::string msg = "Failed to load video rom (not found or not exactly 2/4/8/16KiB)";
+ std::string msg = "Failed to load video rom (not found or not exactly 2/4/8/16KiB)\n";
LogFileOutput("%s", msg.c_str());
MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
}
@@ -1569,7 +1569,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
if (g_bCustomRomF8Failed)
{
- std::string msg = "Failed to load custom F8 rom (not found or not exactly 2KiB)";
+ std::string msg = "Failed to load custom F8 rom (not found or not exactly 2KiB)\n";
LogFileOutput("%s", msg.c_str());
MessageBox(g_hFrameWindow, msg.c_str(), TEXT("AppleWin Error"), MB_OK);
bShutdown = true;
From 7e2f53b62cde2e4e8af2cc592dbd3545e4fa39a6 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sat, 8 Dec 2018 13:36:52 +0000
Subject: [PATCH 076/128] History.txt: fixed typo
---
bin/History.txt | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/bin/History.txt b/bin/History.txt
index f4a9a2a7..58c2d73d 100644
--- a/bin/History.txt
+++ b/bin/History.txt
@@ -13,7 +13,7 @@ Tom Charlesworth
. [Bug #599] Fix for Ultima V not loading in Authentic Speed mode (regression introduced at 1.27.9.0).
. [Change #205] Added support for Apple II/II+ custom 2K video ROMs.
- Extended command line switch: -videorom
- - If the ROM sizs is 2K, then it replaces the video ROM for the Apple II/II+.
+ - If the ROM size is 2K, then it replaces the video ROM for the Apple II/II+.
1.27.12.0 - 17 Nov 2018
From d0f03fc90c71dfa5ed498bc1fa2aec567afa0297 Mon Sep 17 00:00:00 2001
From: tomcw
Date: Sun, 9 Dec 2018 10:05:46 +0000
Subject: [PATCH 077/128] Removed CTRL+F10 functionality to reveal mouse cursor
(fixes #597)
---
help/keyboard.html | 9 ++++-----
source/Frame.cpp | 6 +-----
2 files changed, 5 insertions(+), 10 deletions(-)
diff --git a/help/keyboard.html b/help/keyboard.html
index 10314837..26d75449 100644
--- a/help/keyboard.html
+++ b/help/keyboard.html
@@ -74,6 +74,8 @@
Copy the text screen (auto detect 40/80 columns) to the clipboard.
Alt+Enter:
Default: Toggle between windowed and full screen video modes. (NB. Will conflict with emulation and prevent Open Apple + Enter from being readable. Use the Command Line switch to allow Open Apple + Enter to be readable.)
+
Ctrl+Left Mouse Button:
+ This will show the Windows mouse cursor when emulating an Apple joystick with the PC's mouse or using a Mouse card.
Function Keys F1-F8:
These PC function keys correspond to buttons on the toolbar.
Function Key F2 + Ctrl:
@@ -89,9 +91,6 @@
Function Key F10:
In //e or Enhanced //e emulation mode it will emulate the rocker switch for European video ROM selection. Use the Command Line switch to use an alternate European video ROM file.
In Pravets 8A emulation mode it servers as Caps Lock.
-
Function Key F10 + Ctrl (or Ctrl+left mouse button):
- This PC function key combo will stop emulating an Apple joystick with the PC's mouse.
-
Function Keys F11-F12:
- These PC function keys correspond to saving/loading a save-state
- file.
+
Function Keys F11-F12:
+ These PC function keys correspond to saving/loading a save-state file.