emu48-mirror/sources/Emu48/EMU48.C

1627 lines
44 KiB
C
Raw Normal View History

2024-03-19 22:24:30 +01:00
/*
* Emu48.c
*
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
*
*/
#include "pch.h"
#include "resource.h"
#include "Emu48.h"
2024-03-19 22:36:03 +01:00
#include "io.h"
2024-03-19 22:24:30 +01:00
#include "kml.h"
2024-03-19 22:25:45 +01:00
#include "debugger.h"
2024-03-19 22:24:30 +01:00
2024-03-19 22:38:33 +01:00
#define VERSION "1.35"
2024-03-19 22:25:45 +01:00
#define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE
2024-03-19 22:24:30 +01:00
2024-03-19 22:38:33 +01:00
#define MAXPORTS 256 // number of COM ports
2024-03-19 22:24:30 +01:00
2024-03-19 22:25:45 +01:00
// #define MONOCHROME // CF_BITMAP clipboard format
2024-03-19 22:24:30 +01:00
#ifdef _DEBUG
2024-03-19 22:37:03 +01:00
LPTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug");
2024-03-19 22:24:30 +01:00
#else
2024-03-19 22:37:03 +01:00
LPTSTR szNoTitle = _T("Emu48 ")_T(VERSION);
2024-03-19 22:24:30 +01:00
#endif
2024-03-19 22:37:03 +01:00
LPTSTR szAppName = _T("Emu48"); // application name for DDE server
LPTSTR szTopic = _T("Stack"); // topic for DDE server
LPTSTR szTitle = NULL;
2024-03-19 22:38:33 +01:00
static BOOL bOwnCursor = FALSE;
static const LPCTSTR szLicence =
2024-03-19 22:37:03 +01:00
_T("This program is free software; you can redistribute it and/or modify\r\n")
_T("it under the terms of the GNU General Public License as published by\r\n")
_T("the Free Software Foundation; either version 2 of the License, or\r\n")
_T("(at your option) any later version.\r\n")
_T("\r\n")
_T("This program is distributed in the hope that it will be useful,\r\n")
_T("but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n")
_T("MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n")
_T("See the GNU General Public License for more details.\r\n")
_T("\r\n")
_T("You should have received a copy of the GNU General Public License\r\n")
_T("along with this program; if not, write to the Free Software Foundation,\r\n")
_T("Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA");
2024-03-19 22:25:45 +01:00
CRITICAL_SECTION csGDILock; // critical section for hWindowDC
2024-03-19 22:37:54 +01:00
GRAYON(CRITICAL_SECTION csLcdLock); // critical section for display update
2024-03-19 22:25:45 +01:00
CRITICAL_SECTION csKeyLock; // critical section for key scan
CRITICAL_SECTION csIOLock; // critical section for I/O access
CRITICAL_SECTION csT1Lock; // critical section for timer1 access
CRITICAL_SECTION csT2Lock; // critical section for timer2 access
2024-03-19 22:37:54 +01:00
CRITICAL_SECTION csTxdLock; // critical section for transmit byte
2024-03-19 22:36:03 +01:00
CRITICAL_SECTION csRecvLock; // critical section for receive byte
2024-03-19 22:38:33 +01:00
CRITICAL_SECTION csSlowLock; // critical section for speed slow down
2024-03-19 22:36:03 +01:00
INT nArgc; // no. of command line arguments
LPCTSTR *ppArgv; // command line arguments
LARGE_INTEGER lFreq; // high performance counter frequency
LARGE_INTEGER lAppStart; // high performance counter value at Appl. start
2024-03-19 22:25:45 +01:00
DWORD idDdeInst; // DDE server id
UINT uCF_HpObj; // DDE clipboard format
2024-03-19 22:38:33 +01:00
HANDLE hHeap;
2024-03-19 22:25:45 +01:00
HANDLE hThread;
DWORD lThreadId;
HANDLE hEventShutdn; // event handle to stop cpu thread
2024-03-19 22:24:30 +01:00
HINSTANCE hApp = NULL;
HWND hWnd = NULL;
2024-03-19 22:37:03 +01:00
HWND hDlgDebug = NULL; // handle for debugger dialog
HWND hDlgFind = NULL; // handle for debugger find dialog
2024-03-19 22:38:33 +01:00
HWND hDlgProfile = NULL; // handle for debugger profile dialog
2024-03-19 22:25:45 +01:00
HDC hWindowDC = NULL;
2024-03-19 22:24:30 +01:00
HPALETTE hPalette = NULL;
2024-03-19 22:25:45 +01:00
HPALETTE hOldPalette = NULL; // old palette of hWindowDC
2024-03-19 22:38:33 +01:00
HCURSOR hCursorArrow = NULL;
HCURSOR hCursorHand = NULL;
BOOL bClassicCursor = FALSE; // use hand instead of arrow cursor
2024-03-19 22:24:30 +01:00
BOOL bAutoSave = FALSE;
BOOL bAutoSaveOnExit = TRUE;
BOOL bAlwaysDisplayLog = TRUE;
2024-03-19 22:38:33 +01:00
BOOL bLoadObjectWarning = TRUE;
2024-03-19 22:24:30 +01:00
2024-03-19 22:37:03 +01:00
2024-03-19 22:24:30 +01:00
//################
//#
//# Window Status
//#
//################
2024-03-19 22:38:33 +01:00
VOID SetWindowTitle(LPCTSTR szString)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:38:33 +01:00
if (szTitle) HeapFree(hHeap,0,szTitle);
2024-03-19 22:37:03 +01:00
_ASSERT(hWnd != NULL);
2024-03-19 22:24:30 +01:00
if (szString)
{
szTitle = DuplicateString(szString);
SetWindowText(hWnd, szTitle);
}
else
{
2024-03-19 22:37:03 +01:00
szTitle = NULL;
2024-03-19 22:24:30 +01:00
SetWindowText(hWnd, szNoTitle);
}
return;
}
2024-03-19 22:37:54 +01:00
VOID UpdateWindowStatus(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if (hWnd) // window open
{
// disable stack loading items on HP38G, HP39/40G
BOOL bStackEnable = cCurrentRomType!='6' && cCurrentRomType!='A' && cCurrentRomType!='E';
BOOL bRun = nState == SM_RUN || nState == SM_SLEEP;
2024-03-19 22:24:30 +01:00
2024-03-19 22:37:03 +01:00
UINT uStackEnable = (bRun && bStackEnable) ? MF_ENABLED : MF_GRAYED;
UINT uRun = bRun ? MF_ENABLED : MF_GRAYED;
UINT uBackup = bBackup ? MF_ENABLED : MF_GRAYED;
2024-03-19 22:24:30 +01:00
2024-03-19 22:37:03 +01:00
HMENU hMenu = GetMenu(hWnd); // get menu handle
EnableMenuItem(hMenu,ID_FILE_NEW,MF_ENABLED);
EnableMenuItem(hMenu,ID_FILE_OPEN,MF_ENABLED);
EnableMenuItem(hMenu,ID_FILE_SAVE,(bRun && szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED);
EnableMenuItem(hMenu,ID_FILE_SAVEAS,uRun);
EnableMenuItem(hMenu,ID_FILE_CLOSE,uRun);
2024-03-19 22:25:45 +01:00
EnableMenuItem(hMenu,ID_OBJECT_LOAD,uStackEnable);
EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable);
2024-03-19 22:37:03 +01:00
EnableMenuItem(hMenu,ID_VIEW_COPY,uRun);
2024-03-19 22:25:45 +01:00
EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable);
EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable);
2024-03-19 22:37:03 +01:00
EnableMenuItem(hMenu,ID_VIEW_RESET,uRun);
EnableMenuItem(hMenu,ID_BACKUP_SAVE,uRun);
EnableMenuItem(hMenu,ID_BACKUP_RESTORE,uBackup);
EnableMenuItem(hMenu,ID_BACKUP_DELETE,uBackup);
EnableMenuItem(hMenu,ID_VIEW_SCRIPT,uRun);
EnableMenuItem(hMenu,ID_TOOL_DISASM,uRun);
2024-03-19 22:37:54 +01:00
EnableMenuItem(hMenu,ID_TOOL_DEBUG,(bRun && nDbgState == DBG_OFF) ? MF_ENABLED : MF_GRAYED);
2024-03-19 22:24:30 +01:00
}
return;
}
2024-03-19 22:36:03 +01:00
//################
//#
//# Clipboard Tool
//#
//################
VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboard
{
LONG i;
LPINT lpnCount;
2024-03-19 22:37:54 +01:00
2024-03-19 22:36:03 +01:00
// get number of selections
if ((i = SendMessage(hWnd,LB_GETSELCOUNT,0,0)) == 0)
return; // no items selected
2024-03-19 22:38:33 +01:00
if ((lpnCount = HeapAlloc(hHeap,0,i * sizeof(INT))) != NULL)
2024-03-19 22:36:03 +01:00
{
HANDLE hClipObj;
LONG j,lMem = 0;
// get indexes of selected items
i = SendMessage(hWnd,LB_GETSELITEMS,i,(LPARAM) lpnCount);
for (j = 0;j < i;++j) // scan all selected items
{
// calculate total amount of needed memory
lMem += SendMessage(hWnd,LB_GETTEXTLEN,lpnCount[j],0) + 2;
}
// allocate clipboard data
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,lMem + 1)) != NULL)
{
LPBYTE lpData;
2024-03-19 22:37:03 +01:00
if ((lpData = GlobalLock(hClipObj)))
2024-03-19 22:36:03 +01:00
{
for (j = 0;j < i;++j) // scan all selected items
{
2024-03-19 22:38:33 +01:00
#if defined _UNICODE
{
INT nLength = SendMessage(hWnd,LB_GETTEXTLEN,lpnCount[j],0) + 1;
LPTSTR szTmp = HeapAlloc(hHeap,0,nLength * sizeof(szTmp[0]));
if (szTmp != NULL)
{
SendMessage(hWnd,LB_GETTEXT,lpnCount[j],(LPARAM) szTmp);
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
szTmp, nLength,
lpData, nLength, NULL, NULL);
HeapFree(hHeap,0,szTmp);
lpData += nLength - 1;
}
}
#else
{
lpData += SendMessage(hWnd,LB_GETTEXT,lpnCount[j],(LPARAM) lpData);
}
#endif
2024-03-19 22:36:03 +01:00
*lpData++ = '\r';
*lpData++ = '\n';
}
*lpData = 0; // set end of string
GlobalUnlock(hClipObj); // unlock memory
}
if (OpenClipboard(hWnd))
{
if (EmptyClipboard())
SetClipboardData(CF_TEXT,hClipObj);
else
GlobalFree(hClipObj);
CloseClipboard();
}
else // clipboard open failed
{
GlobalFree(hClipObj);
}
}
2024-03-19 22:38:33 +01:00
HeapFree(hHeap,0,lpnCount); // free item table
2024-03-19 22:36:03 +01:00
}
return;
}
2024-03-19 22:24:30 +01:00
//################
//#
//# Settings
//#
//################
2024-03-19 22:25:45 +01:00
// set listfield for serial combobox
2024-03-19 22:37:03 +01:00
static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting)
2024-03-19 22:24:30 +01:00
{
HANDLE hComm;
BOOL bAdd;
WORD wCount, wIndex = 1;
2024-03-19 22:37:03 +01:00
TCHAR szBuffer[16];
2024-03-19 22:24:30 +01:00
WPARAM wSelect = 0; // set select to disabled
2024-03-19 22:37:54 +01:00
SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) _T(NO_SERIAL));
2024-03-19 22:24:30 +01:00
for (wCount = 1;wCount <= MAXPORTS;++wCount)
{
2024-03-19 22:37:54 +01:00
wsprintf(szBuffer,_T("\\\\.\\COM%u"),wCount);
if ((bAdd = (lstrcmp(&szBuffer[4],szSetting) == 0)))
2024-03-19 22:24:30 +01:00
wSelect = wIndex;
// test if COM port is valid
hComm = CreateFile(szBuffer,GENERIC_READ | GENERIC_WRITE,0,NULL,OPEN_EXISTING,0,NULL);
if(hComm != INVALID_HANDLE_VALUE)
{
BOOL bError = CloseHandle(hComm);
_ASSERT(bError);
bAdd = TRUE;
}
if (bAdd) // add item to combobox
{
2024-03-19 22:37:54 +01:00
SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) &szBuffer[4]);
2024-03-19 22:24:30 +01:00
++wIndex;
}
}
SendDlgItemMessage(hDlg,nIDDlgItem,CB_SETCURSEL,wSelect,0L);
}
static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
2024-03-19 22:25:45 +01:00
// init speed checkbox
2024-03-19 22:24:30 +01:00
CheckDlgButton(hDlg,IDC_REALSPEED,bRealSpeed);
CheckDlgButton(hDlg,IDC_AUTOSAVE,bAutoSave);
CheckDlgButton(hDlg,IDC_AUTOSAVEONEXIT,bAutoSaveOnExit);
2024-03-19 22:38:33 +01:00
CheckDlgButton(hDlg,IDC_OBJECTLOADWARNING,bLoadObjectWarning);
2024-03-19 22:24:30 +01:00
CheckDlgButton(hDlg,IDC_ALWAYSDISPLOG,bAlwaysDisplayLog);
2024-03-19 22:25:45 +01:00
2024-03-19 22:36:03 +01:00
// set disassebler mode
CheckDlgButton(hDlg,(disassembler_mode == HP_MNEMONICS) ? IDC_DISASM_HP : IDC_DISASM_CLASS,BST_CHECKED);
2024-03-19 22:25:45 +01:00
// set combobox parameter
2024-03-19 22:37:54 +01:00
SetCommList(hDlg,IDC_WIRE,szSerialWire);
2024-03-19 22:24:30 +01:00
SetCommList(hDlg,IDC_IR,szSerialIr);
2024-03-19 22:37:03 +01:00
if (bCommInit) // disable when port open
2024-03-19 22:25:45 +01:00
{
EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
}
2024-03-19 22:36:03 +01:00
// HP48SX/GX
2024-03-19 22:37:03 +01:00
if (cCurrentRomType=='S' || cCurrentRomType=='G')
2024-03-19 22:25:45 +01:00
{
// init port1 enable checkbox
CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0);
CheckDlgButton(hDlg,IDC_PORT1WR,(Chipset.cards_status & PORT1_WRITE) != 0);
// init port2 shared checkbox and set port2 filename
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
2024-03-19 22:37:03 +01:00
if (nState == SM_INVALID) // Invalid State
2024-03-19 22:25:45 +01:00
{
EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
}
}
2024-03-19 22:37:03 +01:00
else // HP38G/HP39G/HP40G/HP49G
2024-03-19 22:24:30 +01:00
{
EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
2024-03-19 22:37:03 +01:00
if (nState == SM_INVALID) // Invalid State
2024-03-19 22:25:45 +01:00
{
// init port2 shared checkbox and set port2 filename
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
}
2024-03-19 22:36:03 +01:00
if (cCurrentRomType=='X') // HP49G
2024-03-19 22:25:45 +01:00
{
SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0);
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
}
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
if (nState != SM_INVALID) // not in Invalid State
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:25:45 +01:00
// hide port2 settings
2024-03-19 22:24:30 +01:00
EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE);
}
return TRUE;
case WM_COMMAND:
2024-03-19 22:38:33 +01:00
switch (LOWORD(wParam))
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:38:33 +01:00
case IDOK:
2024-03-19 22:25:45 +01:00
if (Chipset.Port1Size && cCurrentRomType!='X')
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
UINT nOldState = SwitchToState(SM_SLEEP);
2024-03-19 22:36:03 +01:00
// save old card status
BYTE bCardsStatus = Chipset.cards_status;
// port1 disabled?
2024-03-19 22:25:45 +01:00
Chipset.cards_status &= ~(PORT1_PRESENT | PORT1_WRITE);
2024-03-19 22:24:30 +01:00
if (IsDlgButtonChecked(hDlg, IDC_PORT1EN))
{
Chipset.cards_status |= PORT1_PRESENT;
2024-03-19 22:25:45 +01:00
if (IsDlgButtonChecked(hDlg, IDC_PORT1WR))
2024-03-19 22:24:30 +01:00
Chipset.cards_status |= PORT1_WRITE;
}
2024-03-19 22:36:03 +01:00
// changed card status in slot1?
if ( ((bCardsStatus ^ Chipset.cards_status) & (PORT1_PRESENT | PORT1_WRITE)) != 0
&& (Chipset.IORam[CARDCTL] & ECDT) != 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0
)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:36:03 +01:00
Chipset.HST |= MP; // set Module Pulled
IOBit(SRQ2,NINT,FALSE); // set NINT to low
Chipset.SoftInt = TRUE; // set interrupt
2024-03-19 22:24:30 +01:00
bInterrupt = TRUE;
}
Map(0x00,0xFF);
SwitchToState(nOldState);
}
2024-03-19 22:25:45 +01:00
// get speed checkbox value
2024-03-19 22:24:30 +01:00
bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED);
bAutoSave = IsDlgButtonChecked(hDlg, IDC_AUTOSAVE);
bAutoSaveOnExit = IsDlgButtonChecked(hDlg, IDC_AUTOSAVEONEXIT);
2024-03-19 22:38:33 +01:00
bLoadObjectWarning = IsDlgButtonChecked(hDlg, IDC_OBJECTLOADWARNING);
2024-03-19 22:24:30 +01:00
bAlwaysDisplayLog = IsDlgButtonChecked(hDlg, IDC_ALWAYSDISPLOG);
2024-03-19 22:25:45 +01:00
SetSpeed(bRealSpeed); // set speed
2024-03-19 22:37:03 +01:00
if (nState == SM_INVALID)
2024-03-19 22:24:30 +01:00
{
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
2024-03-19 22:37:03 +01:00
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,ARRAYSIZEOF(szPort2Filename));
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:36:03 +01:00
// set disassebler mode
disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS;
2024-03-19 22:25:45 +01:00
// set combobox parameter
2024-03-19 22:37:03 +01:00
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,ARRAYSIZEOF(szSerialWire));
2024-03-19 22:36:03 +01:00
if (cCurrentRomType!='X') // HP49G Ir port is not connected
2024-03-19 22:37:03 +01:00
GetDlgItemText(hDlg,IDC_IR,szSerialIr,ARRAYSIZEOF(szSerialIr));
2024-03-19 22:38:33 +01:00
// no break
case IDCANCEL:
EndDialog(hDlg, LOWORD(wParam));
2024-03-19 22:24:30 +01:00
}
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
}
//################
//#
//# Save Helper
//#
//################
//
// UINT SaveChanges(BOOL bAuto);
// Return code :
// IDYES File successfuly saved
// IDNO File not saved
// IDCANCEL Cancel command
//
static UINT SaveChanges(BOOL bAuto)
{
UINT uReply;
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (pbyRom == NULL) return IDNO;
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (bAuto)
uReply = IDYES;
else
2024-03-19 22:37:03 +01:00
uReply = YesNoCancelMessage(_T("Do you want to save changes ?"));
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (uReply != IDYES) return uReply;
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (szCurrentFilename[0]==0)
{ // Save As...
uReply = GetSaveAsFilename();
if (uReply != IDOK) return uReply;
if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL;
2024-03-19 22:36:03 +01:00
WriteLastDocument(szCurrentFilename);
2024-03-19 22:24:30 +01:00
return IDYES;
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
SaveDocument();
return IDYES;
}
//################
//#
//# Message Handlers
//#
//################
//
// WM_CREATE
//
static LRESULT OnCreate(HWND hWindow)
{
2024-03-19 22:36:03 +01:00
InitializeCriticalSection(&csGDILock);
2024-03-19 22:37:54 +01:00
GRAYON(InitializeCriticalSection(&csLcdLock));
2024-03-19 22:36:03 +01:00
InitializeCriticalSection(&csKeyLock);
InitializeCriticalSection(&csIOLock);
InitializeCriticalSection(&csT1Lock);
InitializeCriticalSection(&csT2Lock);
2024-03-19 22:37:54 +01:00
InitializeCriticalSection(&csTxdLock);
2024-03-19 22:36:03 +01:00
InitializeCriticalSection(&csRecvLock);
2024-03-19 22:38:33 +01:00
InitializeCriticalSection(&csSlowLock);
// load cursors
hCursorArrow = LoadCursor(NULL,IDC_ARROW);
hCursorHand = LoadCursor(NULL,IDC_HAND);
if (hCursorHand == NULL)
{
// for Win95, NT4.0
bOwnCursor = ((hCursorHand = CreateHandCursor()) != NULL);
}
2024-03-19 22:36:03 +01:00
2024-03-19 22:24:30 +01:00
hWnd = hWindow;
hWindowDC = GetDC(hWnd);
return 0;
}
//
// WM_DESTROY
//
static LRESULT OnDestroy(HWND hWindow)
{
2024-03-19 22:25:45 +01:00
DragAcceptFiles(hWnd,FALSE); // no WM_DROPFILES message any more
2024-03-19 22:37:54 +01:00
if (hThread) SwitchToState(SM_RETURN); // exit emulation thread
2024-03-19 22:25:45 +01:00
SetWindowTitle(NULL); // free memory of title
2024-03-19 22:37:54 +01:00
ReleaseDC(hWnd, hWindowDC);
2024-03-19 22:25:45 +01:00
hWindowDC = NULL; // hWindowDC isn't valid any more
2024-03-19 22:24:30 +01:00
hWnd = NULL;
2024-03-19 22:36:03 +01:00
2024-03-19 22:38:33 +01:00
if (bOwnCursor) // destroy hand cursor
{
DestroyCursor(hCursorHand);
bOwnCursor = FALSE;
}
2024-03-19 22:36:03 +01:00
DeleteCriticalSection(&csGDILock);
2024-03-19 22:37:54 +01:00
GRAYON(DeleteCriticalSection(&csLcdLock));
2024-03-19 22:36:03 +01:00
DeleteCriticalSection(&csKeyLock);
DeleteCriticalSection(&csIOLock);
DeleteCriticalSection(&csT1Lock);
DeleteCriticalSection(&csT2Lock);
2024-03-19 22:37:54 +01:00
DeleteCriticalSection(&csTxdLock);
2024-03-19 22:36:03 +01:00
DeleteCriticalSection(&csRecvLock);
2024-03-19 22:38:33 +01:00
DeleteCriticalSection(&csSlowLock);
2024-03-19 22:36:03 +01:00
2024-03-19 22:37:03 +01:00
#if defined _USRDLL // DLL version
DLLDestroyWnd(); // cleanup system
#else // EXE version
PostQuitMessage(0); // exit message loop
#endif
2024-03-19 22:24:30 +01:00
return 0;
UNREFERENCED_PARAMETER(hWindow);
}
//
// WM_PAINT
//
static LRESULT OnPaint(HWND hWindow)
{
PAINTSTRUCT Paint;
HDC hPaintDC;
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
hPaintDC = BeginPaint(hWindow, &Paint);
2024-03-19 22:25:45 +01:00
if (hMainDC != NULL)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:54 +01:00
RECT rcMainPaint = Paint.rcPaint;
rcMainPaint.left += nBackgroundX; // coordinates in source bitmap
rcMainPaint.top += nBackgroundY;
rcMainPaint.right += nBackgroundX;
rcMainPaint.bottom += nBackgroundY;
2024-03-19 22:36:03 +01:00
EnterCriticalSection(&csGDILock); // solving NT GDI problems
{
2024-03-19 22:37:03 +01:00
UINT nLines = (Chipset.lcounter == 0) ? 64 : (Chipset.lcounter + 1);
// redraw background bitmap
BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top,
Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top,
2024-03-19 22:37:54 +01:00
hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY);
2024-03-19 22:37:03 +01:00
// redraw main display area
BitBlt(hWindowDC, nLcdX, nLcdY,
2024-03-19 22:38:33 +01:00
131*nLcdZoom, nLines*nLcdZoom,
hLcdDC, Chipset.boffset*nLcdZoom, 0, SRCCOPY);
2024-03-19 22:37:03 +01:00
// redraw menu display area
2024-03-19 22:38:33 +01:00
BitBlt(hWindowDC, nLcdX, nLcdY+nLines*nLcdZoom,
131*nLcdZoom, (64-nLines)*nLcdZoom,
hLcdDC, 0, nLines*nLcdZoom, SRCCOPY);
2024-03-19 22:36:03 +01:00
GdiFlush();
}
LeaveCriticalSection(&csGDILock);
2024-03-19 22:37:03 +01:00
UpdateAnnunciators();
2024-03-19 22:37:54 +01:00
RefreshButtons(&rcMainPaint);
2024-03-19 22:24:30 +01:00
}
EndPaint(hWindow, &Paint);
return 0;
}
//
// WM_DROPFILES
//
static LRESULT OnDropFiles(HANDLE hFilesInfo)
{
2024-03-19 22:37:03 +01:00
TCHAR szFileName[MAX_PATH];
WORD wNumFiles,wIndex;
BOOL bSuccess;
2024-03-19 22:24:30 +01:00
// get number of files dropped
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
2024-03-19 22:37:54 +01:00
SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
2024-03-19 22:24:30 +01:00
{
// turn on HP
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
2024-03-19 22:37:54 +01:00
Sleep(200);
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
2024-03-19 22:24:30 +01:00
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
DragFinish (hFilesInfo);
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator is busy."));
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_SLEEP);
2024-03-19 22:24:30 +01:00
// get each name and load it into the emulator
for (wIndex = 0;wIndex < wNumFiles;++wIndex)
{
2024-03-19 22:37:03 +01:00
DragQueryFile (hFilesInfo,wIndex,szFileName,ARRAYSIZEOF(szFileName));
2024-03-19 22:24:30 +01:00
// szFileName has file name, now try loading it
if ((bSuccess = LoadObject(szFileName)) == FALSE)
break;
}
DragFinish (hFilesInfo);
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN); // run state
2024-03-19 22:24:30 +01:00
while (nState!=nNextState) Sleep(0);
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RUN);
2024-03-19 22:24:30 +01:00
if (bSuccess == FALSE) // data not copied
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
2024-03-19 22:37:54 +01:00
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_FILE_NEW
//
2024-03-19 22:37:54 +01:00
static LRESULT OnFileNew(VOID)
2024-03-19 22:24:30 +01:00
{
SaveBackup();
if (pbyRom)
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
if (IDCANCEL == SaveChanges(bAutoSave))
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
if (NewDocument()) SetWindowTitle(_T("Untitled"));
2024-03-19 22:24:30 +01:00
UpdateWindowStatus();
cancel:
2024-03-19 22:37:03 +01:00
if (pbyRom) SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_FILE_OPEN
//
2024-03-19 22:37:54 +01:00
static LRESULT OnFileOpen(VOID)
2024-03-19 22:24:30 +01:00
{
if (pbyRom)
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
if (IDCANCEL == SaveChanges(bAutoSave))
goto cancel;
2024-03-19 22:24:30 +01:00
}
if (GetOpenFilename())
{
OpenDocument(szBufferFilename);
}
cancel:
2024-03-19 22:37:03 +01:00
if (pbyRom) SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_FILE_SAVE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnFileSave(VOID)
2024-03-19 22:24:30 +01:00
{
if (pbyRom == NULL) return 0;
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
2024-03-19 22:24:30 +01:00
SaveChanges(TRUE);
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_FILE_SAVEAS
//
2024-03-19 22:37:54 +01:00
static LRESULT OnFileSaveAs(VOID)
2024-03-19 22:24:30 +01:00
{
UINT uReply;
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (pbyRom == NULL) return 0;
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
uReply = GetSaveAsFilename();
if (uReply != IDOK)
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
if (!SaveDocumentAs(szBufferFilename))
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:36:03 +01:00
WriteLastDocument(szCurrentFilename);
2024-03-19 22:37:54 +01:00
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_FILE_CLOSE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnFileClose(VOID)
2024-03-19 22:24:30 +01:00
{
if (pbyRom == NULL) return 0;
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
2024-03-19 22:24:30 +01:00
if (SaveChanges(bAutoSave)!=IDCANCEL)
{
2024-03-19 22:37:54 +01:00
DisableDebugger();
2024-03-19 22:24:30 +01:00
KillKML();
ResetDocument();
SetWindowTitle(NULL);
}
else
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
}
return 0;
}
//
// ID_FILE_EXIT
//
// WM_SYS_CLOSE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnFileExit(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID); // hold emulation thread
2024-03-19 22:24:30 +01:00
if (SaveChanges(bAutoSaveOnExit) == IDCANCEL)
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN); // on cancel restart emulation thread
2024-03-19 22:24:30 +01:00
return 0;
}
DestroyWindow(hWnd);
return 0;
}
//
// ID_STACK_COPY
//
2024-03-19 22:37:54 +01:00
static LRESULT OnStackCopy(VOID) // copy data from stack
2024-03-19 22:24:30 +01:00
{
HANDLE hClipObj;
LPBYTE lpData;
DWORD dwAddress,dwSize;
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
2024-03-19 22:24:30 +01:00
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator is busy."));
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_SLEEP);
2024-03-19 22:24:30 +01:00
if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object
{
MessageBeep(MB_OK); // error beep
goto error;
}
if (Read5(dwAddress) != 0x02A2C) // string object
{
MessageBeep(MB_OK); // error beep
goto error;
}
dwAddress += 5; // address of string length
dwSize = (Read5(dwAddress) - 5) / 2; // length of string
// memory allocation for clipboard data
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize + 1)) == NULL)
goto error;
2024-03-19 22:37:03 +01:00
if ((lpData = GlobalLock(hClipObj))) // lock memory
2024-03-19 22:24:30 +01:00
{
// copy data into clipboard buffer
for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpData)
*lpData = Read2(dwAddress);
*lpData = 0; // set end of string
GlobalUnlock(hClipObj); // unlock memory
if (OpenClipboard(hWnd))
{
if (EmptyClipboard())
SetClipboardData(CF_TEXT,hClipObj);
else
GlobalFree(hClipObj);
CloseClipboard();
}
}
else // lock memory failed
{
GlobalFree(hClipObj);
}
error:
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_STACK_PASTE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnStackPaste(VOID) // paste data to stack
2024-03-19 22:24:30 +01:00
{
HANDLE hClipObj;
LPBYTE lpClipdata,lpData;
BOOL bSuccess = FALSE;
2024-03-19 22:37:54 +01:00
SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
2024-03-19 22:24:30 +01:00
{
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
2024-03-19 22:37:54 +01:00
Sleep(200);
2024-03-19 22:24:30 +01:00
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
}
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
2024-03-19 22:24:30 +01:00
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator is busy."));
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_SLEEP);
2024-03-19 22:24:30 +01:00
if (OpenClipboard(hWnd))
{
if ( IsClipboardFormatAvailable(CF_TEXT)
|| IsClipboardFormatAvailable(CF_OEMTEXT))
{
2024-03-19 22:37:03 +01:00
if ((hClipObj = GetClipboardData(CF_TEXT)))
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if ((lpClipdata = GlobalLock(hClipObj)))
2024-03-19 22:24:30 +01:00
{
DWORD dwSize = strlen(lpClipdata);
2024-03-19 22:38:33 +01:00
if ((lpData = HeapAlloc(hHeap,0,dwSize * 2)))
2024-03-19 22:24:30 +01:00
{
memcpy(lpData+dwSize,lpClipdata,dwSize); // copy data
bSuccess = (WriteStack(lpData,dwSize) == S_ERR_NO);
2024-03-19 22:38:33 +01:00
HeapFree(hHeap,0,lpData);
2024-03-19 22:24:30 +01:00
}
GlobalUnlock(hClipObj);
}
}
}
else // unknown clipboard format
{
MessageBeep(MB_OK); // error beep
}
CloseClipboard();
}
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN); // run state
2024-03-19 22:24:30 +01:00
while (nState!=nNextState) Sleep(0);
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RUN);
2024-03-19 22:24:30 +01:00
if (bSuccess == FALSE) // data not copied
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
2024-03-19 22:37:54 +01:00
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_VIEW_COPY
//
2024-03-19 22:37:54 +01:00
static LRESULT OnViewCopy(VOID)
2024-03-19 22:24:30 +01:00
{
if (OpenClipboard(hWnd))
{
if (EmptyClipboard())
{
#if !defined MONOCHROME
2024-03-19 22:25:45 +01:00
// DIB bitmap
2024-03-19 22:24:30 +01:00
#define WIDTHBYTES(bits) (((bits) + 31) / 32 * 4)
#define PALVERSION 0x300
BITMAP bm;
LPBITMAPINFOHEADER lpbi;
PLOGPALETTE ppal;
HBITMAP hBmp;
HDC hBmpDC;
HANDLE hClipObj;
WORD wBits;
DWORD dwLen, dwSizeImage;
2024-03-19 22:38:33 +01:00
_ASSERT(nLcdZoom == 1 || nLcdZoom == 2 || nLcdZoom == 4);
hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdZoom,64*nLcdZoom);
2024-03-19 22:24:30 +01:00
hBmpDC = CreateCompatibleDC(hLcdDC);
hBmp = SelectObject(hBmpDC,hBmp);
2024-03-19 22:38:33 +01:00
BitBlt(hBmpDC,0,0,131*nLcdZoom,64*nLcdZoom,hLcdDC,Chipset.boffset*nLcdZoom,0,SRCCOPY);
2024-03-19 22:24:30 +01:00
hBmp = SelectObject(hBmpDC,hBmp);
// fill BITMAP structure for size information
GetObject(hBmp, sizeof(bm), &bm);
wBits = bm.bmPlanes * bm.bmBitsPixel;
2024-03-19 22:37:54 +01:00
// make sure bits per pixel is valid
2024-03-19 22:24:30 +01:00
if (wBits <= 1)
wBits = 1;
else if (wBits <= 4)
wBits = 4;
else if (wBits <= 8)
wBits = 8;
2024-03-19 22:37:54 +01:00
else // if greater than 8-bit, force to 24-bit
2024-03-19 22:24:30 +01:00
wBits = 24;
dwSizeImage = WIDTHBYTES((DWORD)bm.bmWidth * wBits) * bm.bmHeight;
// calculate memory size to store CF_DIB data
dwLen = sizeof(BITMAPINFOHEADER) + dwSizeImage;
if (wBits != 24) // a 24 bitcount DIB has no color table
{
// add size for color table
dwLen += (1 << wBits) * sizeof(RGBQUAD);
}
// memory allocation for clipboard data
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE, dwLen)) != NULL)
{
lpbi = GlobalLock(hClipObj);
// initialize BITMAPINFOHEADER
lpbi->biSize = sizeof(BITMAPINFOHEADER);
lpbi->biWidth = bm.bmWidth;
lpbi->biHeight = bm.bmHeight;
lpbi->biPlanes = 1;
lpbi->biBitCount = wBits;
lpbi->biCompression = BI_RGB;
lpbi->biSizeImage = dwSizeImage;
lpbi->biXPelsPerMeter = 0;
lpbi->biYPelsPerMeter = 0;
lpbi->biClrUsed = 0;
lpbi->biClrImportant = 0;
// get bitmap color table and bitmap data
GetDIBits(hBmpDC, hBmp, 0, lpbi->biHeight, (LPBYTE)lpbi + dwLen - dwSizeImage,
(LPBITMAPINFO)lpbi, DIB_RGB_COLORS);
GlobalUnlock(hClipObj);
2024-03-19 22:37:54 +01:00
SetClipboardData(CF_DIB, hClipObj);
2024-03-19 22:24:30 +01:00
2024-03-19 22:37:54 +01:00
// get number of entries in the logical palette
2024-03-19 22:24:30 +01:00
GetObject(hPalette,sizeof(WORD),&wBits);
// memory allocation for temporary palette data
2024-03-19 22:38:33 +01:00
if ((ppal = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,sizeof(LOGPALETTE) + wBits * sizeof(PALETTEENTRY))) != NULL)
2024-03-19 22:24:30 +01:00
{
ppal->palVersion = PALVERSION;
ppal->palNumEntries = wBits;
GetPaletteEntries(hPalette, 0, wBits, ppal->palPalEntry);
2024-03-19 22:37:54 +01:00
SetClipboardData(CF_PALETTE, CreatePalette(ppal));
2024-03-19 22:38:33 +01:00
HeapFree(hHeap,0,ppal);
2024-03-19 22:24:30 +01:00
}
}
DeleteDC(hBmpDC);
DeleteObject(hBmp);
#undef WIDTHBYTES
#undef PALVERSION
#else
HBITMAP hOldBmp, hBmp;
HDC hBmpDC;
2024-03-19 22:37:54 +01:00
// don't work with background index <> 0
2024-03-19 22:38:33 +01:00
_ASSERT(nLcdZoom == 1 || nLcdZoom == 2 || nLcdZoom == 4);
hBmp = CreateBitmap(131*nLcdZoom,64*nLcdZoom,1,1,NULL);
2024-03-19 22:24:30 +01:00
hBmpDC = CreateCompatibleDC(NULL);
hOldBmp = (HBITMAP)SelectObject(hBmpDC,hBmp);
2024-03-19 22:38:33 +01:00
BitBlt(hBmpDC,0,0,131*nLcdZoom,64*nLcdZoom,hLcdDC,Chipset.boffset*nLcdZoom,0,SRCCOPY);
2024-03-19 22:24:30 +01:00
SetClipboardData(CF_BITMAP,hBmp);
SelectObject(hBmpDC,hOldBmp);
DeleteDC(hBmpDC);
#endif
}
CloseClipboard();
}
return 0;
}
//
// ID_VIEW_RESET
//
2024-03-19 22:37:54 +01:00
static LRESULT OnViewReset(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if (nState != SM_RUN) return 0;
if (YesNoMessage(_T("Are you sure you want to press the Reset Button ?"))==IDYES)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_SLEEP);
2024-03-19 22:36:03 +01:00
CpuReset(); // register setting after Cpu Reset
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
}
return 0;
}
//
// ID_VIEW_SETTINGS
//
2024-03-19 22:37:54 +01:00
static LRESULT OnViewSettings(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
// not in nState = SM_INVALID or port2 file must be closed from document
_ASSERT(nState != SM_INVALID || pbyPort2 == NULL);
2024-03-19 22:25:45 +01:00
2024-03-19 22:24:30 +01:00
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc) == -1)
2024-03-19 22:37:03 +01:00
AbortMessage(_T("Settings Dialog Creation Error !"));
2024-03-19 22:25:45 +01:00
2024-03-19 22:24:30 +01:00
WriteSettings();
return 0;
}
//
// ID_VIEW_SCRIPT
//
2024-03-19 22:37:54 +01:00
static LRESULT OnViewScript(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
BYTE cType = cCurrentRomType;
if (nState != SM_RUN)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("You cannot change the KML script when Emu48 is not running.\n")
_T("Use the File,New menu item to create a new calculator."));
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
2024-03-19 22:24:30 +01:00
retry:
if (!DisplayChooseKml(cType)) goto ok;
if (!InitKML(szCurrentKml,FALSE))
{
2024-03-19 22:37:03 +01:00
if (AbortMessage(_T("This KML Script has errors.\nPress Ok to try to find a correct script."))==IDCANCEL)
2024-03-19 22:24:30 +01:00
{
if (szCurrentFilename[0])
OnFileSave();
else
OnFileSaveAs();
goto ok;
}
goto retry;
}
ok:
2024-03-19 22:37:03 +01:00
if (pbyRom) SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_BACKUP_SAVE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnBackupSave(VOID)
2024-03-19 22:24:30 +01:00
{
UINT nOldState;
if (pbyRom == NULL) return 0;
2024-03-19 22:37:03 +01:00
nOldState = SwitchToState(SM_INVALID);
2024-03-19 22:24:30 +01:00
SaveBackup();
SwitchToState(nOldState);
return 0;
}
//
// ID_BACKUP_RESTORE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnBackupRestore(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_INVALID);
2024-03-19 22:24:30 +01:00
RestoreBackup();
2024-03-19 22:37:03 +01:00
if (pbyRom) SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_BACKUP_DELETE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnBackupDelete(VOID)
2024-03-19 22:24:30 +01:00
{
ResetBackup();
return 0;
}
//
// ID_OBJECT_LOAD
//
2024-03-19 22:37:54 +01:00
static LRESULT OnObjectLoad(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:54 +01:00
SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
2024-03-19 22:24:30 +01:00
{
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
2024-03-19 22:37:54 +01:00
Sleep(200);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
if (nState != SM_RUN)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator must be running to load an object."));
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:25:45 +01:00
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator is busy."));
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_SLEEP);
2024-03-19 22:37:54 +01:00
2024-03-19 22:38:33 +01:00
if (bLoadObjectWarning)
2024-03-19 22:24:30 +01:00
{
UINT uReply = YesNoCancelMessage(
2024-03-19 22:37:03 +01:00
_T("Warning: Trying to load an object while the emulator is busy\n")
_T("will certainly result in a memory lost. Before loading an object\n")
_T("you should be sure that the calculator is not doing anything.\n")
_T("Do you want to see this warning next time you try to load an object ?"));
2024-03-19 22:24:30 +01:00
switch (uReply)
{
case IDYES:
break;
case IDNO:
2024-03-19 22:38:33 +01:00
bLoadObjectWarning = FALSE;
2024-03-19 22:24:30 +01:00
break;
case IDCANCEL:
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (!GetLoadObjectFilename())
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (!LoadObject(szBufferFilename))
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:37:54 +01:00
goto cancel;
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN); // run state
2024-03-19 22:24:30 +01:00
while (nState!=nNextState) Sleep(0);
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RUN);
2024-03-19 22:24:30 +01:00
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
while(Chipset.Shutdn == FALSE) Sleep(0);
2024-03-19 22:37:54 +01:00
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
2024-03-19 22:24:30 +01:00
return 0;
}
//
// ID_OBJECT_SAVE
//
2024-03-19 22:37:54 +01:00
static LRESULT OnObjectSave(VOID)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if (nState != SM_RUN)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator must be running to save an object."));
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:25:45 +01:00
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
2024-03-19 22:36:03 +01:00
{
2024-03-19 22:37:03 +01:00
InfoMessage(_T("The emulator is busy."));
2024-03-19 22:24:30 +01:00
return 0;
2024-03-19 22:36:03 +01:00
}
2024-03-19 22:24:30 +01:00
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_SLEEP);
2024-03-19 22:24:30 +01:00
if (!GetSaveObjectFilename())
{
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
SaveObject(szBufferFilename);
2024-03-19 22:37:54 +01:00
2024-03-19 22:37:03 +01:00
SwitchToState(SM_RUN);
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
return 0;
}
//
2024-03-19 22:25:45 +01:00
// ID_TOOL_DISASM
2024-03-19 22:24:30 +01:00
//
static BOOL CALLBACK Disasm(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{
static DWORD dwAddress, dwAddressMax;
LONG i;
2024-03-19 22:37:03 +01:00
TCHAR *cpStop,szAddress[256] = _T("0");
2024-03-19 22:36:03 +01:00
2024-03-19 22:24:30 +01:00
switch (message)
{
case WM_INITDIALOG:
2024-03-19 22:25:45 +01:00
// set fonts & cursor
2024-03-19 22:24:30 +01:00
SendDlgItemMessage(hDlg,IDC_DISASM_MODULE,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_MAP,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_ROM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_RAM,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_PORT1,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_PORT2,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_MAP,BM_SETCHECK,1,0);
SendDlgItemMessage(hDlg,IDC_ADDRESS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_NEXT,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_COPY,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDCANCEL,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress);
2024-03-19 22:25:45 +01:00
disassembler_map = MEM_MAP; // disassemble with mapped modules
2024-03-19 22:37:03 +01:00
dwAddress = _tcstoul(szAddress,&cpStop,16);
2024-03-19 22:25:45 +01:00
dwAddressMax = 0x100000; // greatest address (mapped mode)
2024-03-19 22:24:30 +01:00
return TRUE;
case WM_COMMAND:
2024-03-19 22:38:33 +01:00
switch(LOWORD(wParam))
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:25:45 +01:00
// decode radio buttons
2024-03-19 22:24:30 +01:00
case IDC_DISASM_MAP:
disassembler_map = MEM_MAP;
dwAddressMax = 0x100000;
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_ROM:
disassembler_map = MEM_ROM;
dwAddressMax = dwRomSize;
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_RAM:
disassembler_map = MEM_RAM;
dwAddressMax = Chipset.Port0Size * 2048;
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_PORT1:
disassembler_map = MEM_PORT1;
dwAddressMax = ((Chipset.cards_status & PORT1_PRESENT) != 0) ? (Chipset.Port1Size * 2048) : 0;
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_PORT2:
disassembler_map = MEM_PORT2;
2024-03-19 22:37:54 +01:00
dwAddressMax = ((cCurrentRomType=='E' || cCurrentRomType=='X')
? Chipset.Port2Size
: dwPort2Size)
* 2048;
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDOK:
SendDlgItemMessage(hDlg,IDC_DISASM_ADR,EM_SETSEL,0,-1);
2024-03-19 22:37:03 +01:00
GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,ARRAYSIZEOF(szAddress));
2024-03-19 22:24:30 +01:00
// test if valid hex address
2024-03-19 22:37:03 +01:00
for (i = 0; i < (LONG) lstrlen(szAddress); ++i)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if (_istxdigit(szAddress[i]) == FALSE)
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:37:03 +01:00
dwAddress = _tcstoul(szAddress,&cpStop,16);
2024-03-19 22:24:30 +01:00
// no break
case IDC_DISASM_NEXT:
2024-03-19 22:25:45 +01:00
if (dwAddress >= dwAddressMax)
2024-03-19 22:24:30 +01:00
return FALSE;
2024-03-19 22:37:03 +01:00
i = wsprintf(szAddress,(dwAddress <= 0xFFFFF) ? _T("%05lX ") : _T("%06lX "),dwAddress);
2024-03-19 22:25:45 +01:00
dwAddress = disassemble(dwAddress,&szAddress[i],VIEW_LONG);
2024-03-19 22:24:30 +01:00
i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_ADDSTRING,0,(LPARAM) szAddress);
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SELITEMRANGE,FALSE,MAKELPARAM(0,i));
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SETSEL,TRUE,i);
SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_SETTOPINDEX,i,0);
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_COPY:
2024-03-19 22:36:03 +01:00
// copy selected items to clipboard
CopyItemsToClipboard(GetDlgItem(hDlg,IDC_DISASM_WIN));
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDCANCEL:
2024-03-19 22:38:33 +01:00
EndDialog(hDlg,IDCANCEL);
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
}
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
}
//
// ID_ABOUT
//
static BOOL CALLBACK About(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
SetDlgItemText(hDlg,IDC_VERSION,szNoTitle);
SetDlgItemText(hDlg,IDC_LICENSE,szLicence);
return TRUE;
case WM_COMMAND:
2024-03-19 22:38:33 +01:00
wParam = LOWORD(wParam);
2024-03-19 22:24:30 +01:00
if ((wParam==IDOK)||(wParam==IDCANCEL))
{
EndDialog(hDlg, wParam);
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
}
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
}
2024-03-19 22:37:54 +01:00
static LRESULT OnToolDisasm(VOID) // disasm dialogbox call
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if (pbyRom) SwitchToState(SM_SLEEP);
2024-03-19 22:24:30 +01:00
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1)
2024-03-19 22:37:03 +01:00
AbortMessage(_T("Disassembler Dialog Box Creation Error !"));
if (pbyRom) SwitchToState(SM_RUN);
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:37:54 +01:00
static LRESULT OnAbout(VOID)
2024-03-19 22:24:30 +01:00
{
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1)
2024-03-19 22:37:03 +01:00
AbortMessage(_T("About Dialog Box Creation Error !"));
2024-03-19 22:24:30 +01:00
return 0;
}
static LRESULT OnLButtonDown(UINT nFlags, WORD x, WORD y)
{
2024-03-19 22:37:03 +01:00
if (nState == SM_RUN) MouseButtonDownAt(nFlags, x,y);
2024-03-19 22:24:30 +01:00
return 0;
}
2024-03-19 22:37:54 +01:00
static LRESULT OnLButtonUp(UINT nFlags, WORD x, WORD y)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:37:03 +01:00
if (nState == SM_RUN) MouseButtonUpAt(nFlags, x,y);
2024-03-19 22:24:30 +01:00
return 0;
}
static LRESULT OnMouseMove(UINT nFlags, WORD x, WORD y)
{
2024-03-19 22:37:03 +01:00
if (nState == SM_RUN) MouseMovesTo(nFlags, x,y);
2024-03-19 22:24:30 +01:00
return 0;
}
static LRESULT OnKeyDown(int nVirtKey, DWORD lKeyData)
{
2024-03-19 22:25:45 +01:00
// call RunKey() only once (suppress autorepeat feature)
2024-03-19 22:37:03 +01:00
if (nState == SM_RUN && (lKeyData & 0x40000000) == 0)
2024-03-19 22:24:30 +01:00
RunKey((BYTE)nVirtKey, TRUE);
return 0;
}
static LRESULT OnKeyUp(int nVirtKey, DWORD lKeyData)
{
2024-03-19 22:37:03 +01:00
if (nState == SM_RUN) RunKey((BYTE)nVirtKey, FALSE);
2024-03-19 22:24:30 +01:00
return 0;
UNREFERENCED_PARAMETER(lKeyData);
}
2024-03-19 22:25:45 +01:00
LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
2024-03-19 22:24:30 +01:00
{
switch (uMsg)
{
case WM_CREATE: return OnCreate(hWindow);
case WM_DESTROY: return OnDestroy(hWindow);
case WM_PAINT: return OnPaint(hWindow);
case WM_DROPFILES: return OnDropFiles((HANDLE)wParam);
case WM_ACTIVATE:
if (LOWORD(wParam)==WA_INACTIVE) break;
case WM_QUERYNEWPALETTE:
if (hPalette)
{
SelectPalette(hWindowDC, hPalette, FALSE);
if (RealizePalette(hWindowDC))
{
InvalidateRect(hWindow,NULL,TRUE);
return TRUE;
}
}
return FALSE;
case WM_PALETTECHANGED:
if ((HWND)wParam == hWindow) break;
if (hPalette)
{
SelectPalette(hWindowDC, hPalette, FALSE);
if (RealizePalette(hWindowDC))
{
// UpdateColors(hWindowDC);
InvalidateRect (hWnd, (LPRECT) (NULL), 1);
}
}
return FALSE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case ID_FILE_NEW: return OnFileNew();
case ID_FILE_OPEN: return OnFileOpen();
case ID_FILE_SAVE: return OnFileSave();
case ID_FILE_SAVEAS: return OnFileSaveAs();
case ID_FILE_CLOSE: return OnFileClose();
case ID_FILE_EXIT: return OnFileExit();
2024-03-19 22:25:45 +01:00
case ID_STACK_COPY: return OnStackCopy();
case ID_STACK_PASTE: return OnStackPaste();
2024-03-19 22:24:30 +01:00
case ID_VIEW_COPY: return OnViewCopy();
case ID_VIEW_RESET: return OnViewReset();
case ID_VIEW_SETTINGS: return OnViewSettings();
case ID_VIEW_SCRIPT: return OnViewScript();
case ID_BACKUP_SAVE: return OnBackupSave();
case ID_BACKUP_RESTORE:return OnBackupRestore();
case ID_BACKUP_DELETE: return OnBackupDelete();
case ID_OBJECT_LOAD: return OnObjectLoad();
case ID_OBJECT_SAVE: return OnObjectSave();
2024-03-19 22:25:45 +01:00
case ID_TOOL_DISASM: return OnToolDisasm();
case ID_TOOL_DEBUG: return OnToolDebug();
2024-03-19 22:24:30 +01:00
case ID_ABOUT: return OnAbout();
}
break;
case WM_SYSCOMMAND:
2024-03-19 22:38:33 +01:00
switch (wParam & 0xFFF0)
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:25:45 +01:00
case SC_CLOSE: return OnFileExit();
2024-03-19 22:24:30 +01:00
}
break;
2024-03-19 22:25:45 +01:00
case WM_RBUTTONDOWN:
2024-03-19 22:24:30 +01:00
case WM_LBUTTONDOWN: return OnLButtonDown(wParam, LOWORD(lParam), HIWORD(lParam));
case WM_LBUTTONUP: return OnLButtonUp(wParam, LOWORD(lParam), HIWORD(lParam));
case WM_MOUSEMOVE: return OnMouseMove(wParam, LOWORD(lParam), HIWORD(lParam));
case WM_KEYUP: return OnKeyUp((int)wParam, lParam);
case WM_KEYDOWN: return OnKeyDown((int)wParam, lParam);
}
return DefWindowProc(hWindow, uMsg, wParam, lParam);
}
2024-03-19 22:25:45 +01:00
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
2024-03-19 22:24:30 +01:00
{
MSG msg;
WNDCLASS wc;
RECT rectWindow;
2024-03-19 22:25:45 +01:00
HSZ hszService, hszTopic; // variables for DDE server
2024-03-19 22:36:03 +01:00
DWORD dwAffMask;
2024-03-19 22:24:30 +01:00
hApp = hInst;
2024-03-19 22:37:03 +01:00
#if defined _UNICODE
{
ppArgv = CommandLineToArgvW(GetCommandLine(),&nArgc);
}
#else
{
nArgc = __argc; // no. of command line arguments
ppArgv = (LPCTSTR*) __argv; // command line arguments
}
#endif
2024-03-19 22:38:33 +01:00
hHeap = GetProcessHeap();
if (hHeap == NULL)
{
AbortMessage(_T("Heap creation failed."));
return FALSE;
}
2024-03-19 22:24:30 +01:00
wc.style = CS_BYTEALIGNCLIENT;
wc.lpfnWndProc = (WNDPROC)MainWndProc;
wc.cbClsExtra = 0;
wc.cbWndExtra = 0;
wc.hInstance = hInst;
wc.hIcon = LoadIcon(hInst, MAKEINTRESOURCE(IDI_EMU48));
2024-03-19 22:38:33 +01:00
wc.hCursor = NULL;
2024-03-19 22:24:30 +01:00
wc.hbrBackground = NULL;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
2024-03-19 22:37:03 +01:00
wc.lpszClassName = _T("CEmu48");
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (!RegisterClass(&wc))
{
AbortMessage(
2024-03-19 22:37:03 +01:00
_T("CEmu48 class registration failed.\n")
_T("This application will now terminate."));
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
// Create window
rectWindow.left = 0;
rectWindow.top = 0;
rectWindow.right = 256;
rectWindow.bottom = 0;
AdjustWindowRect(&rectWindow, WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED, TRUE);
2024-03-19 22:37:54 +01:00
2024-03-19 22:37:03 +01:00
hWnd = CreateWindow(_T("CEmu48"), _T("Emu48"),
2024-03-19 22:24:30 +01:00
WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED,
CW_USEDEFAULT, CW_USEDEFAULT,
rectWindow.right - rectWindow.left,
rectWindow.bottom - rectWindow.top,
NULL,NULL,hApp,NULL
);
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
if (hWnd == NULL)
{
2024-03-19 22:37:03 +01:00
AbortMessage(_T("Window creation failed."));
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
// initialization
2024-03-19 22:25:45 +01:00
QueryPerformanceFrequency(&lFreq); // init high resolution counter
2024-03-19 22:36:03 +01:00
QueryPerformanceCounter(&lAppStart);
2024-03-19 22:24:30 +01:00
2024-03-19 22:37:03 +01:00
GetCurrentDirectory(ARRAYSIZEOF(szCurrentDirectory), szCurrentDirectory);
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
ReadSettings();
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
UpdateWindowStatus();
2024-03-19 22:25:45 +01:00
// create auto event handle
hEventShutdn = CreateEvent(NULL,FALSE,FALSE,NULL);
if (hEventShutdn == NULL)
{
2024-03-19 22:37:03 +01:00
AbortMessage(_T("Event creation failed."));
2024-03-19 22:36:03 +01:00
DestroyWindow(hWnd);
2024-03-19 22:25:45 +01:00
return FALSE;
}
2024-03-19 22:37:03 +01:00
nState = SM_RUN; // init state must be <> nNextState
nNextState = SM_INVALID; // go into invalid state
2024-03-19 22:36:03 +01:00
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, CREATE_SUSPENDED, &lThreadId);
2024-03-19 22:24:30 +01:00
if (hThread == NULL)
{
2024-03-19 22:25:45 +01:00
CloseHandle(hEventShutdn); // close event handle
2024-03-19 22:37:03 +01:00
AbortMessage(_T("Thread creation failed."));
2024-03-19 22:36:03 +01:00
DestroyWindow(hWnd);
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:36:03 +01:00
// on multiprocessor machines for QueryPerformanceCounter()
dwAffMask = SetThreadAffinityMask(hThread,1);
_ASSERT(dwAffMask != 0);
ResumeThread(hThread); // start thread
while (nState!=nNextState) Sleep(0); // wait for thread initialized
2024-03-19 22:37:54 +01:00
2024-03-19 22:37:03 +01:00
idDdeInst = 0; // initialize DDE server
2024-03-19 22:24:30 +01:00
if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback,
APPCLASS_STANDARD |
CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES |
CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0))
{
2024-03-19 22:36:03 +01:00
TerminateThread(hThread, 0); // kill emulation thread
CloseHandle(hEventShutdn); // close event handle
2024-03-19 22:37:03 +01:00
AbortMessage(_T("Could not initialize server!"));
2024-03-19 22:36:03 +01:00
DestroyWindow(hWnd);
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:36:03 +01:00
_ASSERT(hWnd != NULL);
_ASSERT(hWindowDC != NULL);
2024-03-19 22:25:45 +01:00
if (nArgc >= 2) // use decoded parameter line
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:38:33 +01:00
TCHAR szTemp[MAX_PATH+8] = _T("Loading ");
2024-03-19 22:37:03 +01:00
lstrcat(szTemp, ppArgv[1]);
2024-03-19 22:24:30 +01:00
SetWindowTitle(szTemp);
2024-03-19 22:25:45 +01:00
if (OpenDocument(ppArgv[1]))
2024-03-19 22:24:30 +01:00
goto start;
}
2024-03-19 22:37:03 +01:00
ReadLastDocument(szBufferFilename, ARRAYSIZEOF(szBufferFilename));
2024-03-19 22:24:30 +01:00
if (szBufferFilename[0])
{
2024-03-19 22:38:33 +01:00
TCHAR szTemp[MAX_PATH+8] = _T("Loading ");
2024-03-19 22:37:03 +01:00
lstrcat(szTemp, szBufferFilename);
2024-03-19 22:24:30 +01:00
SetWindowTitle(szTemp);
if (OpenDocument(szBufferFilename))
goto start;
}
2024-03-19 22:25:45 +01:00
2024-03-19 22:37:03 +01:00
SetWindowTitle(_T("New Document"));
2024-03-19 22:24:30 +01:00
if (NewDocument())
{
2024-03-19 22:37:03 +01:00
SetWindowTitle(_T("Untitled"));
2024-03-19 22:24:30 +01:00
goto start;
}
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
ResetDocument();
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
start:
2024-03-19 22:25:45 +01:00
// init clipboard format and name service
2024-03-19 22:37:03 +01:00
uCF_HpObj = RegisterClipboardFormat(_T(CF_HPOBJ));
2024-03-19 22:24:30 +01:00
hszService = DdeCreateStringHandle(idDdeInst,szAppName,0);
hszTopic = DdeCreateStringHandle(idDdeInst,szTopic,0);
DdeNameService(idDdeInst,hszService,NULL,DNS_REGISTER);
2024-03-19 22:37:03 +01:00
ShowWindow(hWnd, nCmdShow);
if (pbyRom) SwitchToState(SM_RUN);
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
while (GetMessage(&msg, NULL, 0, 0))
{
2024-03-19 22:38:33 +01:00
if( (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg))
&& (hDlgFind == NULL || !IsDialogMessage(hDlgFind, &msg))
&& (hDlgProfile == NULL || !IsDialogMessage(hDlgProfile, &msg)))
2024-03-19 22:25:45 +01:00
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:25:45 +01:00
// clean up DDE server
2024-03-19 22:24:30 +01:00
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
DdeFreeStringHandle(idDdeInst, hszService);
DdeFreeStringHandle(idDdeInst, hszTopic);
DdeUninitialize(idDdeInst);
2024-03-19 22:36:03 +01:00
WriteSettings(); // save emulation settings
2024-03-19 22:37:54 +01:00
2024-03-19 22:37:03 +01:00
CloseHandle(hThread); // close thread handle
2024-03-19 22:25:45 +01:00
CloseHandle(hEventShutdn); // close event handle
2024-03-19 22:37:03 +01:00
_ASSERT(nState == SM_RETURN); // emulation thread down?
2024-03-19 22:24:30 +01:00
ResetDocument();
ResetBackup();
2024-03-19 22:25:45 +01:00
_ASSERT(pbyPort2 == NULL); // port2 file unmapped
_ASSERT(pKml == NULL); // KML script not closed
_ASSERT(szTitle == NULL); // freed allocated memory
_ASSERT(hPalette == NULL); // freed resource memory
2024-03-19 22:37:54 +01:00
2024-03-19 22:24:30 +01:00
return msg.wParam;
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(hPrevInst);
}