Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
edc1c366fe
19 changed files with 510 additions and 275 deletions
|
@ -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}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
#include <windows.h>
|
||||
|
||||
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 _<symbol>@bytes
|
||||
|
@ -20,8 +22,20 @@ 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 (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;
|
||||
|
@ -42,9 +56,12 @@ extern "C" __declspec(dllexport) LRESULT CALLBACK LowLevelKeyboardProc(
|
|||
}
|
||||
|
||||
// Suppress ctrl-escape
|
||||
bool ControlDown = (GetKeyState(VK_CONTROL) & 0x8000) != 0;
|
||||
if (pKbdLlHookStruct->vkCode == VK_ESCAPE && ControlDown)
|
||||
if (pKbdLlHookStruct->vkCode == VK_ESCAPE)
|
||||
{
|
||||
// But don't suppress CTRL+SHIFT+ESC
|
||||
if (GetKeyState(VK_CONTROL) < 0 && GetKeyState(VK_SHIFT) >= 0)
|
||||
suppress = true;
|
||||
}
|
||||
|
||||
// Suppress keys by returning 1
|
||||
if (suppress)
|
||||
|
@ -54,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;
|
||||
}
|
||||
|
|
|
@ -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 + <key> not working (when using right ALT key).
|
||||
|
||||
|
||||
1.27.5.0 - 24 Jun 2018
|
||||
----------------------
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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;
|
||||
|
@ -435,7 +442,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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -872,17 +879,20 @@ 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"));
|
||||
|
||||
_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");
|
||||
|
||||
|
@ -905,12 +915,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)
|
||||
|
@ -1077,12 +1149,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)
|
||||
{
|
||||
|
@ -1234,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);
|
||||
|
@ -1428,7 +1503,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");
|
||||
}
|
||||
|
||||
|
@ -1540,7 +1615,7 @@ int APIENTRY WinMain(HINSTANCE passinstance, HINSTANCE, LPSTR lpCmdLine, int)
|
|||
|
||||
if (g_bHookSystemKey)
|
||||
{
|
||||
UnhookFilterForKeyboard();
|
||||
UninitHookThread();
|
||||
LogFileOutput("Main: UnhookFilterForKeyboard()\n");
|
||||
}
|
||||
}
|
||||
|
@ -1559,12 +1634,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();
|
||||
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -9680,7 +9680,7 @@ void DebuggerCursorUpdate()
|
|||
}
|
||||
else
|
||||
{
|
||||
Sleep(10); // Stop process hogging CPU
|
||||
Sleep(1); // Stop process hogging CPU
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
|
120
source/Frame.cpp
120
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
|
||||
|
@ -1091,24 +1092,31 @@ 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:
|
||||
if ((g_nAppMode == MODE_RUNNING) || (g_nAppMode == MODE_STEPPING) || (g_nAppMode == MODE_LOGO))
|
||||
{
|
||||
if( !g_bDebuggerEatKey )
|
||||
{
|
||||
KeybQueueKeypress((int)wparam, ASCII);
|
||||
}
|
||||
else
|
||||
{
|
||||
g_bDebuggerEatKey = false;
|
||||
}
|
||||
}
|
||||
else if (g_nAppMode == MODE_DEBUG)
|
||||
{
|
||||
DebuggerInputConsoleChar((TCHAR)wparam);
|
||||
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:
|
||||
|
@ -1169,29 +1177,6 @@ LRESULT CALLBACK FrameWndProc (
|
|||
break;
|
||||
}
|
||||
|
||||
case WM_DESTROY:
|
||||
LogFileOutput("WM_DESTROY\n");
|
||||
DragAcceptFiles(window,0);
|
||||
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;
|
||||
|
@ -1289,19 +1274,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;
|
||||
}
|
||||
|
@ -1330,7 +1315,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
|
||||
}
|
||||
|
@ -1339,7 +1324,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))
|
||||
|
@ -1391,17 +1376,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 (!IsJoyKey && (g_nAppMode != MODE_LOGO))
|
||||
#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);
|
||||
|
@ -1413,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))
|
||||
|
@ -1431,6 +1439,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);
|
||||
}
|
||||
|
@ -1747,7 +1758,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);
|
||||
|
@ -1761,7 +1772,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);
|
||||
|
@ -1784,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;
|
||||
|
@ -1944,7 +1952,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
|
|||
|
||||
case BTN_RUN:
|
||||
KeybUpdateCtrlShiftStatus();
|
||||
if( g_bCtrlKey )
|
||||
if( KeybGetCtrlStatus() )
|
||||
{
|
||||
CtrlReset();
|
||||
if (g_nAppMode == MODE_DEBUG)
|
||||
|
@ -1988,7 +1996,7 @@ static void ProcessButtonClick(int button, bool bFromButtonUI /*=false*/)
|
|||
|
||||
case BTN_FULLSCR:
|
||||
KeybUpdateCtrlShiftStatus();
|
||||
ScreenWindowResize(g_bCtrlKey);
|
||||
ScreenWindowResize( KeybGetCtrlStatus() );
|
||||
break;
|
||||
|
||||
case BTN_DEBUG:
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -35,10 +35,12 @@ 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] = {
|
||||
{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 +51,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;
|
||||
|
||||
|
@ -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,19 +98,22 @@ bool KeybGetShiftStatus ()
|
|||
//===========================================================================
|
||||
void KeybUpdateCtrlShiftStatus()
|
||||
{
|
||||
g_bShiftKey = (GetKeyState( VK_SHIFT ) & KF_UP) ? true : false; // 0x8000 KF_UP
|
||||
g_bCtrlKey = (GetKeyState( VK_CONTROL) & KF_UP) ? true : false;
|
||||
g_bAltKey = (GetKeyState( VK_MENU ) & KF_UP) ? true : false;
|
||||
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
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
BYTE KeybGetKeycode () // Used by MemCheckPaging() & VideoCheckMode()
|
||||
BYTE KeybGetKeycode () // Used by IORead_C01x() and TapeRead() for Pravets8A
|
||||
{
|
||||
return keycode;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
void KeybQueueKeypress (int key, BOOL bASCII)
|
||||
|
||||
bool IsVirtualKeyAnAppleIIKey(WPARAM wparam);
|
||||
|
||||
void KeybQueueKeypress (WPARAM key, Keystroke_e bASCII)
|
||||
{
|
||||
if (bASCII == ASCII) // WM_CHAR
|
||||
{
|
||||
|
@ -271,8 +270,6 @@ void KeybQueueKeypress (int key, BOOL bASCII)
|
|||
keycode = key;
|
||||
}
|
||||
}
|
||||
|
||||
lastvirtkey = LOBYTE(VkKeyScan(key));
|
||||
}
|
||||
else //(bASCII != ASCII) // WM_KEYDOWN
|
||||
{
|
||||
|
@ -299,13 +296,42 @@ 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) < 0)) // Right Alt (aka Alt Gr) - GH#558
|
||||
{
|
||||
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;
|
||||
|
||||
keycode = asciicode[IS_APPLE2 ? 0 : 1][key - VK_LEFT]; // Convert to Apple arrow keycode
|
||||
lastvirtkey = 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 (GetHookAltGrControl() && GetKeyState(VK_CONTROL) < 0)
|
||||
newKey -= 'A' - 1; // convert to control-key
|
||||
}
|
||||
|
||||
PostMessage(g_hFrameWindow, WM_CHAR, newKey, 0);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
keywaiting = 1;
|
||||
|
@ -391,16 +417,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 ||
|
||||
|
@ -415,6 +433,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;
|
||||
|
@ -440,7 +476,7 @@ static bool IsAKD(void)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
|
||||
BYTE KeybReadData (void)
|
||||
{
|
||||
LogFileTimeUntilFirstKeyRead();
|
||||
|
||||
|
@ -462,7 +498,7 @@ BYTE __stdcall KeybReadData (WORD, WORD, BYTE, BYTE, ULONG)
|
|||
|
||||
//===========================================================================
|
||||
|
||||
BYTE __stdcall KeybReadFlag (WORD, WORD, BYTE, BYTE, ULONG)
|
||||
BYTE KeybReadFlag (void)
|
||||
{
|
||||
if (g_bPasteFromClipboard)
|
||||
ClipboardInit();
|
||||
|
|
|
@ -1,28 +1,23 @@
|
|||
#pragma once
|
||||
|
||||
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 (int,BOOL);
|
||||
void KeybQueueKeypress(WPARAM key, Keystroke_e bASCII);
|
||||
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;
|
||||
|
|
|
@ -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];
|
||||
|
|
|
@ -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, ...);
|
||||
|
|
|
@ -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);
|
||||
|
@ -1639,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)
|
||||
}
|
||||
|
||||
|
@ -1648,7 +1626,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);
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
@ -1852,6 +1830,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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
170
source/NTSC.cpp
170
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
|
||||
|
||||
|
@ -136,7 +133,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 +196,14 @@ 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 ] =
|
||||
// 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,
|
||||
0x0100,0x0500,0x0900,0x0D00,0x1100,0x1500,0x1900,0x1D00,0x0180,0x0580,0x0980,0x0D80,0x1180,0x1580,0x1980,0x1D80,
|
||||
|
@ -224,7 +228,7 @@ 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_kClockVertOffsetsTXT[33] =
|
||||
{
|
||||
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
|
||||
0x0000,0x0080,0x0100,0x0180,0x0200,0x0280,0x0300,0x0380,
|
||||
|
@ -234,7 +238,7 @@ 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 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 +286,7 @@ 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 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,
|
||||
|
@ -329,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
|
||||
|
@ -389,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 );
|
||||
|
@ -411,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);
|
||||
|
@ -767,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()
|
||||
{
|
||||
// BUG? g_pHorzClockOffset
|
||||
// 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));
|
||||
}
|
||||
|
@ -1134,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)
|
||||
{
|
||||
|
@ -1165,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)
|
||||
{
|
||||
|
@ -1202,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)
|
||||
{
|
||||
|
@ -1234,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)
|
||||
{
|
||||
|
@ -1275,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)
|
||||
{
|
||||
|
@ -1316,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)
|
||||
{
|
||||
|
@ -1342,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))
|
||||
{
|
||||
|
@ -1374,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))
|
||||
{
|
||||
|
@ -1469,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;
|
||||
|
@ -1629,9 +1629,12 @@ _mono:
|
|||
}
|
||||
|
||||
//===========================================================================
|
||||
void GenerateVideoTables( void );
|
||||
|
||||
void NTSC_VideoInit( uint8_t* pFramebuffer ) // wsVideoInit
|
||||
{
|
||||
make_csbits();
|
||||
GenerateVideoTables();
|
||||
initPixelDoubleMasks();
|
||||
initChromaPhaseTables();
|
||||
updateMonochromeTables( 0xFF, 0xFF, 0xFF );
|
||||
|
@ -1826,3 +1829,112 @@ bool NTSC_GetColorBurst( void )
|
|||
{
|
||||
return (g_nColorBurstPixels < 2) ? false : true;
|
||||
}
|
||||
|
||||
//===========================================================================
|
||||
|
||||
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<VIDEO_SCANNER_MAX_VERT*VIDEO_SCANNER_MAX_HORZ; cycles++)
|
||||
{
|
||||
WORD addr1 = VideoGetScannerAddress(cycles);
|
||||
WORD addr2 = g_uVideoMode & VF_TEXT ? getVideoScannerAddressTXT()
|
||||
: getVideoScannerAddressHGR();
|
||||
_ASSERT(addr1 == addr2);
|
||||
if (addr1 != addr2)
|
||||
{
|
||||
char str[80];
|
||||
sprintf(str, "vpos=%04X, hpos=%02X, Video_adr=$%04X, NTSC_adr=$%04X\n", g_nVideoClockVert, g_nVideoClockHorz, addr1, addr2);
|
||||
OutputDebugString(str);
|
||||
return false;
|
||||
}
|
||||
|
||||
g_nVideoClockHorz++;
|
||||
if (g_nVideoClockHorz == VIDEO_SCANNER_MAX_HORZ)
|
||||
{
|
||||
g_nVideoClockHorz = 0;
|
||||
g_nVideoClockVert++;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void CheckVideoTables( void )
|
||||
{
|
||||
CheckVideoTables2(A2TYPE_APPLE2PLUS, VF_HIRES);
|
||||
CheckVideoTables2(A2TYPE_APPLE2PLUS, VF_TEXT);
|
||||
CheckVideoTables2(A2TYPE_APPLE2E, VF_HIRES);
|
||||
CheckVideoTables2(A2TYPE_APPLE2E, VF_TEXT);
|
||||
}
|
||||
|
||||
static void GenerateVideoTables( void )
|
||||
{
|
||||
eApple2Type currentApple2Type = GetApple2Type();
|
||||
|
||||
//
|
||||
// g_aClockVertOffsetsHGR[]
|
||||
//
|
||||
|
||||
g_uVideoMode = VF_HIRES;
|
||||
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<VIDEO_SCANNER_MAX_VERT; i++, cycle+=VIDEO_SCANNER_MAX_HORZ)
|
||||
{
|
||||
g_aClockVertOffsetsHGR[i] = VideoGetScannerAddressPartialV(cycle);
|
||||
_ASSERT(g_aClockVertOffsetsHGR[i] == g_kClockVertOffsetsHGR[i]);
|
||||
}
|
||||
|
||||
//
|
||||
// g_aClockVertOffsetsTXT[]
|
||||
//
|
||||
|
||||
g_uVideoMode = VF_TEXT;
|
||||
for (UINT i=0, cycle=VIDEO_SCANNER_HORZ_START; i<(256+8)/8; i++, cycle+=VIDEO_SCANNER_MAX_HORZ*8)
|
||||
{
|
||||
g_aClockVertOffsetsTXT[i] = VideoGetScannerAddressPartialV(cycle);
|
||||
_ASSERT(g_aClockVertOffsetsTXT[i] == g_kClockVertOffsetsTXT[i]);
|
||||
}
|
||||
|
||||
//
|
||||
// APPLE_IIP_HORZ_CLOCK_OFFSET[]
|
||||
//
|
||||
|
||||
g_uVideoMode = VF_TEXT;
|
||||
SetApple2Type(A2TYPE_APPLE2PLUS);
|
||||
for (UINT j=0; j<5; j++)
|
||||
{
|
||||
for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++)
|
||||
{
|
||||
APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddressPartialH(cycle);
|
||||
_ASSERT(APPLE_IIP_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIP_HORZ_CLOCK_OFFSET[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// APPLE_IIE_HORZ_CLOCK_OFFSET[]
|
||||
//
|
||||
|
||||
g_uVideoMode = VF_TEXT;
|
||||
SetApple2Type(A2TYPE_APPLE2E);
|
||||
for (UINT j=0; j<5; j++)
|
||||
{
|
||||
for (UINT i=0, cycle=j*64*VIDEO_SCANNER_MAX_HORZ; i<VIDEO_SCANNER_MAX_HORZ; i++, cycle++)
|
||||
{
|
||||
APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] = VideoGetScannerAddressPartialH(cycle);
|
||||
_ASSERT(APPLE_IIE_HORZ_CLOCK_OFFSET[j][i] == kAPPLE_IIE_HORZ_CLOCK_OFFSET[j][i]);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
CheckVideoTables();
|
||||
|
||||
VideoResetState();
|
||||
SetApple2Type(currentApple2Type);
|
||||
}
|
||||
|
|
|
@ -639,17 +639,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: this func should only be called once, and never on a g_bRestart
|
||||
}
|
||||
|
|
|
@ -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 ()
|
||||
|
@ -798,12 +770,23 @@ void VideoLoadSnapshot(YamlLoadHelper& yamlLoadHelper)
|
|||
// References to Jim Sather's books are given as eg:
|
||||
// UTAIIe:5-7,P3 (Understanding the Apple IIe, chapter 5, page 7, Paragraph 3)
|
||||
//
|
||||
WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
||||
{
|
||||
// get video scanner position
|
||||
//
|
||||
int nCycles = CpuGetCyclesThisVideoFrame(uExecutedCycles);
|
||||
|
||||
static WORD g_PartialV=0, g_PartialH=0;
|
||||
|
||||
WORD VideoGetScannerAddressPartialV(DWORD nCycles)
|
||||
{
|
||||
VideoGetScannerAddress(nCycles);
|
||||
return g_PartialV;
|
||||
}
|
||||
|
||||
WORD VideoGetScannerAddressPartialH(DWORD nCycles)
|
||||
{
|
||||
VideoGetScannerAddress(nCycles);
|
||||
return g_PartialH;
|
||||
}
|
||||
|
||||
WORD VideoGetScannerAddress(DWORD nCycles)
|
||||
{
|
||||
// machine state switches
|
||||
//
|
||||
int nHires = (SW_HIRES && !SW_TEXT) ? 1 : 0;
|
||||
|
@ -836,7 +819,7 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
|||
//
|
||||
int nVLine = nCycles / kHClocks; // which vertical scanning line
|
||||
int nVState = kVLine0State + nVLine; // V state bits
|
||||
if ((nVLine >= kVPresetLine)) // check for previous vertical state preset
|
||||
if (nVLine >= kVPresetLine) // check for previous vertical state preset
|
||||
{
|
||||
nVState -= nScanLines; // compensate for preset
|
||||
}
|
||||
|
@ -867,6 +850,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
|||
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
|
||||
|
@ -881,6 +866,8 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
|||
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
|
||||
}
|
||||
|
@ -888,8 +875,7 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
|||
{
|
||||
// N: insert text-only address bits
|
||||
//
|
||||
nAddress |= p2a << 10; // a10
|
||||
nAddress |= p2b << 11; // a11
|
||||
g_PartialV = nAddress - g_PartialH;
|
||||
|
||||
// Apple ][ (not //e) and HBL?
|
||||
//
|
||||
|
@ -897,15 +883,15 @@ WORD VideoGetScannerAddress(bool* pbVblBar_OUT, const DWORD uExecutedCycles)
|
|||
!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;
|
||||
}
|
||||
|
||||
// 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<WORD>(nAddress);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
@ -197,10 +199,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);
|
||||
|
|
Loading…
Add table
Reference in a new issue