emu48-mirror/sources/Emu48/EMU48.C

1542 lines
41 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"
#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:25:45 +01:00
#define VERSION "1.15" // 23.10.99 cg, changed version
#define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE
2024-03-19 22:24:30 +01:00
2024-03-19 22:25:45 +01:00
#define MAXPORTS 16 // 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
LPSTR szNoTitle = "Emu48 "VERSION" Debug";
#else
2024-03-19 22:25:45 +01:00
LPSTR szNoTitle = "Emu48 "VERSION;
2024-03-19 22:24:30 +01:00
#endif
2024-03-19 22:25:45 +01:00
LPSTR szAppName = "Emu48"; // application name for DDE server
LPSTR szTopic = "Stack"; // topic for DDE server
2024-03-19 22:24:30 +01:00
LPSTR szTitle = NULL;
2024-03-19 22:25:45 +01:00
static const char szLicence[] = // 30.11.99 cg, changed, update of address
2024-03-19 22:24:30 +01:00
"This program is free software; you can redistribute it and/or modify\r\n"
"it under the terms of the GNU General Public License as published by\r\n"
"the Free Software Foundation; either version 2 of the License, or\r\n"
"(at your option) any later version.\r\n"
"\r\n"
"This program is distributed in the hope that it will be useful,\r\n"
"but WITHOUT ANY WARRANTY; without even the implied warranty of\r\n"
"MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\r\n"
"See the GNU General Public License for more details.\r\n"
"\r\n"
"You should have received a copy of the GNU General Public License\r\n"
2024-03-19 22:25:45 +01:00
"along with this program; if not, write to the Free Software Foundation,\r\n"
"Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA";
CRITICAL_SECTION csGDILock; // critical section for hWindowDC
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
CRITICAL_SECTION csRecvLock; // 24.10.99 cg, moved, critical section for receive byte
INT nArgc; // 08.11.99 cg, new, no. of command line arguments
LPCTSTR *ppArgv; // 08.11.99 cg, new, command line arguments
LARGE_INTEGER lFreq; // counter frequency
DWORD idDdeInst; // DDE server id
UINT uCF_HpObj; // DDE clipboard format
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: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:24:30 +01:00
BOOL bAutoSave = FALSE;
BOOL bAutoSaveOnExit = TRUE;
BOOL bAlwaysDisplayLog = TRUE;
//################
//#
//# Window Status
//#
//################
VOID SetWindowTitle(LPSTR szString)
{
if (szTitle)
{
LocalFree(szTitle);
}
if (szString)
{
szTitle = DuplicateString(szString);
}
else
{
szTitle = NULL;
}
2024-03-19 22:25:45 +01:00
_ASSERT(hWnd != NULL);
2024-03-19 22:24:30 +01:00
if (szTitle)
{
SetWindowText(hWnd, szTitle);
}
else
{
SetWindowText(hWnd, szNoTitle);
}
return;
}
VOID UpdateWindowStatus()
{
HMENU hMenu;
2024-03-19 22:25:45 +01:00
if (hWnd == NULL) return; // return if window closed
2024-03-19 22:24:30 +01:00
hMenu = GetMenu(hWnd);
if ((nState == 0)||(nState == 3))
{
2024-03-19 22:25:45 +01:00
// 02.12.99 cg, new, disable stack loading items on HP38G
UINT uStackEnable = (cCurrentRomType!='A') ? MF_ENABLED : MF_GRAYED;
// 02.12.99 cg, changed implementation
EnableMenuItem(hMenu,ID_FILE_SAVE,(szCurrentFilename[0]) ? MF_ENABLED : MF_GRAYED);
2024-03-19 22:24:30 +01:00
EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_ENABLED);
EnableMenuItem(hMenu,ID_FILE_CLOSE,MF_ENABLED);
EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_GRAYED);
EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_ENABLED);
EnableMenuItem(hMenu,ID_VIEW_COPY,MF_ENABLED);
EnableMenuItem(hMenu,ID_VIEW_RESET,MF_ENABLED);
2024-03-19 22:25:45 +01:00
// 02.12.99 cg, new, added HP38G part
EnableMenuItem(hMenu,ID_OBJECT_LOAD,uStackEnable);
EnableMenuItem(hMenu,ID_OBJECT_SAVE,uStackEnable);
EnableMenuItem(hMenu,ID_STACK_COPY,uStackEnable);
EnableMenuItem(hMenu,ID_STACK_PASTE,uStackEnable);
// 02.12.99 cg, end of added part
2024-03-19 22:24:30 +01:00
EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_ENABLED);
}
else
{
EnableMenuItem(hMenu,ID_FILE_SAVE,MF_GRAYED);
EnableMenuItem(hMenu,ID_FILE_SAVEAS,MF_GRAYED);
EnableMenuItem(hMenu,ID_FILE_CLOSE,MF_ENABLED);
EnableMenuItem(hMenu,ID_BACKUP_SAVE,MF_GRAYED);
EnableMenuItem(hMenu,ID_VIEW_COPY,MF_GRAYED);
EnableMenuItem(hMenu,ID_VIEW_RESET,MF_GRAYED);
EnableMenuItem(hMenu,ID_OBJECT_LOAD,MF_GRAYED);
EnableMenuItem(hMenu,ID_OBJECT_SAVE,MF_GRAYED);
EnableMenuItem(hMenu,ID_STACK_COPY,MF_GRAYED);
EnableMenuItem(hMenu,ID_STACK_PASTE,MF_GRAYED);
EnableMenuItem(hMenu,ID_TOOL_DISASM,MF_GRAYED);
}
if (bBackup)
{
EnableMenuItem(hMenu,ID_BACKUP_RESTORE,MF_ENABLED);
EnableMenuItem(hMenu,ID_BACKUP_DELETE,MF_ENABLED);
}
else
{
EnableMenuItem(hMenu,ID_BACKUP_RESTORE,MF_GRAYED);
EnableMenuItem(hMenu,ID_BACKUP_DELETE,MF_GRAYED);
}
return;
}
//################
//#
//# Settings
//#
//################
2024-03-19 22:25:45 +01:00
// set listfield for serial combobox
2024-03-19 22:24:30 +01:00
static VOID SetCommList(HWND hDlg,int nIDDlgItem,char *szSetting)
{
HANDLE hComm;
BOOL bAdd;
WORD wCount, wIndex = 1;
char szBuffer[16];
WPARAM wSelect = 0; // set select to disabled
SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) NO_SERIAL);
for (wCount = 1;wCount <= MAXPORTS;++wCount)
{
wsprintf(szBuffer,"COM%u",wCount);
if (bAdd = (strcmp(szBuffer,szSetting) == 0))
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
{
SendDlgItemMessage(hDlg,nIDDlgItem,CB_ADDSTRING,0,(LPARAM) szBuffer);
++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);
CheckDlgButton(hDlg,IDC_ALWAYSDISPLOG,bAlwaysDisplayLog);
2024-03-19 22:25:45 +01:00
// set combobox parameter
2024-03-19 22:24:30 +01:00
SetCommList(hDlg,IDC_WIRE,szSerialWire);
SetCommList(hDlg,IDC_IR,szSerialIr);
2024-03-19 22:25:45 +01:00
if (CommConnect() != PORT_CLOSE) // disable when port open
{
EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
}
// 01.12.99 cg, HP48SX/GX
if (cCurrentRomType!='A' && cCurrentRomType!='X')
{
// init port1 enable checkbox
CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0);
// 19.11.99 cg, changed, use cards_status variable now
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);
if (nState == 1) // Invalid State
{
EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
}
}
else // HP38G/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:25:45 +01:00
if (nState == 1) // Invalid State
{
// init port2 shared checkbox and set port2 filename
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
}
if (cCurrentRomType=='X') // 01.12.99 cg, HP48SX/GX
{
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:25:45 +01:00
if (nState != 1) // 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:
if (wParam == IDOK)
{
2024-03-19 22:25:45 +01:00
if (Chipset.Port1Size && cCurrentRomType!='X')
2024-03-19 22:24:30 +01:00
{
UINT nOldState = SwitchToState(3);
2024-03-19 22:25:45 +01:00
// port1 disabled ?;
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
// 19.11.99 cg, changed, use dialog variable now
if (IsDlgButtonChecked(hDlg, IDC_PORT1WR))
2024-03-19 22:24:30 +01:00
Chipset.cards_status |= PORT1_WRITE;
}
if (Chipset.inte)
{
Chipset.Shutdn = FALSE;
Chipset.SoftInt = TRUE;
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);
bAlwaysDisplayLog = IsDlgButtonChecked(hDlg, IDC_ALWAYSDISPLOG);
2024-03-19 22:25:45 +01:00
SetSpeed(bRealSpeed); // set speed
2024-03-19 22:24:30 +01:00
if (nState == 1)
{
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,sizeof(szPort2Filename));
}
2024-03-19 22:25:45 +01:00
// set combobox parameter
2024-03-19 22:24:30 +01:00
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,sizeof(szSerialWire));
GetDlgItemText(hDlg,IDC_IR ,szSerialIr ,sizeof(szSerialIr));
EndDialog(hDlg, wParam);
}
if (wParam == IDCANCEL)
{
EndDialog(hDlg, wParam);
}
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;
if (pbyRom == NULL) return IDNO;
if (bAuto)
uReply = IDYES;
else
uReply = YesNoCancelMessage("Do you want to save changes ?");
if (uReply != IDYES) return uReply;
if (szCurrentFilename[0]==0)
{ // Save As...
uReply = GetSaveAsFilename();
if (uReply != IDOK) return uReply;
if (!SaveDocumentAs(szBufferFilename)) return IDCANCEL;
2024-03-19 22:25:45 +01:00
WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function
2024-03-19 22:24:30 +01:00
return IDYES;
}
SaveDocument();
return IDYES;
}
//################
//#
//# Message Handlers
//#
//################
//
// WM_CREATE
//
static LRESULT OnCreate(HWND hWindow)
{
hWnd = hWindow;
hWindowDC = GetDC(hWnd);
2024-03-19 22:25:45 +01:00
DragAcceptFiles(hWnd,TRUE); // support dropped files
2024-03-19 22:24:30 +01:00
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
// SwitchToState(2); // 01.12.99 cg, removed, doing in main program now
// WriteSettings(); // 01.12.99 cg, removed, doing in main program now
2024-03-19 22:24:30 +01:00
ReleaseDC(hWnd, hWindowDC);
2024-03-19 22:25:45 +01:00
SetWindowTitle(NULL); // free memory of title
hWindowDC = NULL; // hWindowDC isn't valid any more
2024-03-19 22:24:30 +01:00
hWnd = NULL;
PostQuitMessage(0);
return 0;
UNREFERENCED_PARAMETER(hWindow);
}
//
// WM_PAINT
//
static LRESULT OnPaint(HWND hWindow)
{
PAINTSTRUCT Paint;
HDC hPaintDC;
hPaintDC = BeginPaint(hWindow, &Paint);
2024-03-19 22:25:45 +01:00
if (hMainDC != NULL)
2024-03-19 22:24:30 +01:00
{
BitBlt(hPaintDC, 0, 0, nBackgroundW, nBackgroundH, hMainDC, nBackgroundX, nBackgroundY, SRCCOPY);
if ((nState==0)||(nState==3))
{
UpdateMainDisplay();
UpdateMenuDisplay();
2024-03-19 22:25:45 +01:00
UpdateAnnunciators();
2024-03-19 22:24:30 +01:00
RefreshButtons();
}
}
EndPaint(hWindow, &Paint);
return 0;
}
//
// WM_DROPFILES
//
static LRESULT OnDropFiles(HANDLE hFilesInfo)
{
char szFileName[MAX_PATH];
WORD wNumFiles,wIndex;
BOOL bSuccess;
2024-03-19 22:25:45 +01:00
if (cCurrentRomType=='A') return 0; // 06.12.99 cg, new, HP38 has no stack, ignore
2024-03-19 22:24:30 +01:00
// get number of files dropped
wNumFiles = DragQueryFile (hFilesInfo,(UINT)-1,NULL,0);
if (!Chipset.dispon) // calculator off, turn on
{
// turn on HP
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
}
_ASSERT(nState == 0); // Emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
DragFinish (hFilesInfo);
InfoMessage("The emulator is busy.");
return 0;
}
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==3);
// get each name and load it into the emulator
for (wIndex = 0;wIndex < wNumFiles;++wIndex)
{
DragQueryFile (hFilesInfo,wIndex,(LPSTR) szFileName,sizeof(szFileName));
// szFileName has file name, now try loading it
if ((bSuccess = LoadObject(szFileName)) == FALSE)
break;
}
DragFinish (hFilesInfo);
SwitchToState(0); // run state
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==0);
if (bSuccess == FALSE) // data not copied
return 0;
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
return 0;
}
//
// ID_FILE_NEW
//
static LRESULT OnFileNew()
{
UINT uReply;
SaveBackup();
if (pbyRom)
{
SwitchToState(1);
uReply = SaveChanges(bAutoSave);
if (uReply==IDCANCEL) goto cancel;
}
NewDocument();
SetWindowTitle("Untitled");
UpdateWindowStatus();
cancel:
if (pbyRom) SwitchToState(0);
return 0;
}
//
// ID_FILE_OPEN
//
static LRESULT OnFileOpen()
{
UINT uReply;
if (pbyRom)
{
SwitchToState(1);
uReply = SaveChanges(bAutoSave);
if (uReply==IDCANCEL) goto cancel;
}
if (GetOpenFilename())
{
OpenDocument(szBufferFilename);
}
cancel:
if (pbyRom)
{
SwitchToState(0);
}
return 0;
}
//
// ID_FILE_SAVE
//
static LRESULT OnFileSave()
{
if (pbyRom == NULL) return 0;
SwitchToState(1);
SaveChanges(TRUE);
SwitchToState(0);
return 0;
}
//
// ID_FILE_SAVEAS
//
static LRESULT OnFileSaveAs()
{
UINT uReply;
if (pbyRom == NULL) return 0;
SwitchToState(1);
uReply = GetSaveAsFilename();
if (uReply != IDOK)
{
SwitchToState(0);
return 0;
}
if (!SaveDocumentAs(szBufferFilename))
{
SwitchToState(0);
return 0;
}
2024-03-19 22:25:45 +01:00
WriteLastDocument(szCurrentFilename); // 11.12.99 cg, changed, call function
2024-03-19 22:24:30 +01:00
SwitchToState(0);
return 0;
}
//
// ID_FILE_CLOSE
//
static LRESULT OnFileClose()
{
if (pbyRom == NULL) return 0;
SwitchToState(1);
if (SaveChanges(bAutoSave)!=IDCANCEL)
{
KillKML();
ResetDocument();
SetWindowTitle(NULL);
}
else
{
SwitchToState(0);
}
return 0;
}
//
// ID_FILE_EXIT
//
// WM_SYS_CLOSE
//
2024-03-19 22:25:45 +01:00
static LRESULT OnFileExit()
2024-03-19 22:24:30 +01:00
{
2024-03-19 22:25:45 +01:00
SwitchToState(1); // hold emulation thread
2024-03-19 22:24:30 +01:00
if (SaveChanges(bAutoSaveOnExit) == IDCANCEL)
{
2024-03-19 22:25:45 +01:00
SwitchToState(0); // 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:25:45 +01:00
static LRESULT OnStackCopy() // copy data from stack
2024-03-19 22:24:30 +01:00
{
HANDLE hClipObj;
LPBYTE lpData;
DWORD dwAddress,dwSize;
_ASSERT(nState == 0); // Emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
InfoMessage("The emulator is busy.");
return 0;
}
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==3);
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;
if (lpData = GlobalLock(hClipObj)) // lock memory
{
// 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:
SwitchToState(0);
return 0;
}
//
// ID_STACK_PASTE
//
2024-03-19 22:25:45 +01:00
static LRESULT OnStackPaste() // paste data to stack
2024-03-19 22:24:30 +01:00
{
HANDLE hClipObj;
LPBYTE lpClipdata,lpData;
BOOL bSuccess = FALSE;
if (!Chipset.dispon) // calculator off, turn on
{
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
}
_ASSERT(nState == 0); // Emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
InfoMessage("The emulator is busy.");
return 0;
}
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==3);
if (OpenClipboard(hWnd))
{
if ( IsClipboardFormatAvailable(CF_TEXT)
|| IsClipboardFormatAvailable(CF_OEMTEXT))
{
if (hClipObj = GetClipboardData(CF_TEXT))
{
if (lpClipdata = GlobalLock(hClipObj))
{
DWORD dwSize = strlen(lpClipdata);
if (lpData = (LPBYTE) LocalAlloc(LMEM_FIXED,dwSize * 2))
{
memcpy(lpData+dwSize,lpClipdata,dwSize); // copy data
bSuccess = (WriteStack(lpData,dwSize) == S_ERR_NO);
LocalFree(lpData);
}
GlobalUnlock(hClipObj);
}
}
}
else // unknown clipboard format
{
MessageBeep(MB_OK); // error beep
}
CloseClipboard();
}
SwitchToState(0); // run state
while (nState!=nNextState) Sleep(0);
_ASSERT(nState == 0);
if (bSuccess == FALSE) // data not copied
return 0;
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
return 0;
}
//
// ID_VIEW_COPY
//
static LRESULT OnViewCopy()
{
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;
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
hBmp = CreateCompatibleBitmap(hLcdDC,131*nLcdDoubled,64*nLcdDoubled);
hBmpDC = CreateCompatibleDC(hLcdDC);
hBmp = SelectObject(hBmpDC,hBmp);
BitBlt(hBmpDC, 0, 0, 131*nLcdDoubled, 64*nLcdDoubled, hLcdDC, 0, 0, SRCCOPY);
hBmp = SelectObject(hBmpDC,hBmp);
// fill BITMAP structure for size information
GetObject(hBmp, sizeof(bm), &bm);
wBits = bm.bmPlanes * bm.bmBitsPixel;
// make sure bits per pixel is valid
if (wBits <= 1)
wBits = 1;
else if (wBits <= 4)
wBits = 4;
else if (wBits <= 8)
wBits = 8;
else // if greater than 8-bit, force to 24-bit
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);
SetClipboardData(CF_DIB, hClipObj);
// get number of entries in the logical palette
GetObject(hPalette,sizeof(WORD),&wBits);
// memory allocation for temporary palette data
if ((ppal = LocalAlloc(LPTR, sizeof(LOGPALETTE) + wBits * sizeof(PALETTEENTRY))) != NULL)
{
ppal->palVersion = PALVERSION;
ppal->palNumEntries = wBits;
GetPaletteEntries(hPalette, 0, wBits, ppal->palPalEntry);
SetClipboardData(CF_PALETTE, CreatePalette(ppal));
LocalFree(ppal);
}
}
DeleteDC(hBmpDC);
DeleteObject(hBmp);
#undef WIDTHBYTES
#undef PALVERSION
#else
HBITMAP hOldBmp, hBmp;
HDC hBmpDC;
_ASSERT(nLcdDoubled == 1 || nLcdDoubled == 2 || nLcdDoubled == 4);
hBmp = CreateBitmap(131*nLcdDoubled,64*nLcdDoubled,1,1,NULL);
hBmpDC = CreateCompatibleDC(NULL);
hOldBmp = (HBITMAP)SelectObject(hBmpDC,hBmp);
BitBlt(hBmpDC, 0, 0, 131*nLcdDoubled, 64*nLcdDoubled, hLcdDC, 0, 0, SRCCOPY);
SetClipboardData(CF_BITMAP,hBmp);
SelectObject(hBmpDC,hOldBmp);
DeleteDC(hBmpDC);
#endif
}
CloseClipboard();
}
return 0;
}
//
// ID_VIEW_RESET
//
static LRESULT OnViewReset()
{
if (nState!=0) return 0;
if (YesNoMessage("Are you sure you want to press the Reset Button ?")==IDYES)
{
SwitchToState(3);
2024-03-19 22:25:45 +01:00
CpuReset(); // 19.03.99 cg, changed, register setting after Cpu Reset
2024-03-19 22:24:30 +01:00
SwitchToState(0);
}
return 0;
}
//
// ID_VIEW_SETTINGS
//
static LRESULT OnViewSettings()
{
ReadSettings();
2024-03-19 22:25:45 +01:00
// in nState = 1 port2 file must be closed from document
_ASSERT(nState != 1 || pbyPort2 == NULL);
2024-03-19 22:24:30 +01:00
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc) == -1)
AbortMessage("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
//
static LRESULT OnViewScript()
{
CHAR cType = cCurrentRomType;
if (nState!=0)
{
InfoMessage("You cannot change the KML script when Emu48 is not running.\n"
"Use the File,New menu item to create a new calculator.");
return 0;
}
SwitchToState(1);
retry:
if (!DisplayChooseKml(cType)) goto ok;
if (!InitKML(szCurrentKml,FALSE))
{
if (AbortMessage("This KML Script has errors.\nPress Ok to try to find a correct script.")==IDCANCEL)
{
if (szCurrentFilename[0])
OnFileSave();
else
OnFileSaveAs();
goto ok;
}
goto retry;
}
ok:
if (pbyRom) SwitchToState(0);
return 0;
}
//
// ID_BACKUP_SAVE
//
static LRESULT OnBackupSave()
{
UINT nOldState;
if (pbyRom == NULL) return 0;
nOldState = SwitchToState(1);
SaveBackup();
SwitchToState(nOldState);
return 0;
}
//
// ID_BACKUP_RESTORE
//
static LRESULT OnBackupRestore()
{
SwitchToState(1);
RestoreBackup();
if (pbyRom) SwitchToState(0);
return 0;
}
//
// ID_BACKUP_DELETE
//
static LRESULT OnBackupDelete()
{
ResetBackup();
return 0;
}
//
// ID_OBJECT_LOAD
//
static LRESULT OnObjectLoad()
{
static BOOL bWarning = TRUE;
2024-03-19 22:25:45 +01:00
if (!Chipset.dispon) // calculator off, turn on
2024-03-19 22:24:30 +01:00
{
// turn on HP
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
}
if (nState!=0)
{
InfoMessage("The emulator must be running to load an object.");
return 0;
}
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
{
InfoMessage("The emulator is busy.");
return 0;
}
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==3);
if (bWarning)
{
UINT uReply = YesNoCancelMessage(
"Warning: Trying to load an object while the emulator is busy \n"
"will certainly result in a memory lost. Before loading an object \n"
"you should be sure that the HP48 is not doing anything. \n"
"Do you want to see this warning next time you try to load an object ?");
switch (uReply)
{
case IDYES:
break;
case IDNO:
bWarning = FALSE;
break;
case IDCANCEL:
SwitchToState(0);
return 0;
}
}
if (!GetLoadObjectFilename())
{
SwitchToState(0);
return 0;
}
if (!LoadObject(szBufferFilename))
{
SwitchToState(0);
return 0;
}
SwitchToState(0); // run state
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==0);
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
KeyboardEvent(FALSE,0,0x8000);
while(Chipset.Shutdn == FALSE) Sleep(0);
return 0;
}
//
// ID_OBJECT_SAVE
//
static LRESULT OnObjectSave()
{
if (nState!=0)
{
InfoMessage("The emulator must be running to save an object.");
return 0;
}
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
return 0;
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==3);
if (!GetSaveObjectFilename())
{
SwitchToState(0);
return 0;
}
SaveObject(szBufferFilename);
SwitchToState(0);
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;
LPINT lpnCount;
char *cpStop,szAddress[256] = "0";
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_MNEMONICS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_HP,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_CLASS,WM_SETFONT,(WPARAM)GetStockObject(DEFAULT_GUI_FONT),MAKELPARAM(FALSE,0));
SendDlgItemMessage(hDlg,IDC_DISASM_MAP,BM_SETCHECK,1,0);
SendDlgItemMessage(hDlg,IDC_DISASM_HP,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
disassembler_mode = HP_MNEMONICS; // use HP mnemonics for disassembling
2024-03-19 22:24:30 +01:00
dwAddress = strtoul(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:
switch(wParam)
{
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:25:45 +01:00
dwAddressMax = (cCurrentRomType=='X')
? (Chipset.Port2Size * 2048)
: ((dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 18) : (dwPort2Size * 2048));
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_HP:
disassembler_mode = HP_MNEMONICS;
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case IDC_DISASM_CLASS:
disassembler_mode = CLASS_MNEMONICS;
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);
GetDlgItemText(hDlg,IDC_DISASM_ADR,szAddress,sizeof(szAddress));
// test if valid hex address
for (i = 0; i < (LONG) strlen(szAddress); ++i)
{
if (isxdigit(szAddress[i]) == FALSE)
return FALSE;
}
dwAddress = strtoul(szAddress,&cpStop,16);
// 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:25:45 +01:00
i = wsprintf(szAddress,(dwAddress <= 99999) ? "%05lX " : "%06lX ",dwAddress);
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:
// get number of selections
if ((i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELCOUNT,0,0)) == 0)
break; // no items selected
if ((lpnCount = (LPINT) LocalAlloc(LMEM_FIXED,i * sizeof(INT))) != NULL)
{
HANDLE hClipObj;
LONG j,lMem = 0;
// get indexes of selected items
i = SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETSELITEMS,i,(LPARAM) lpnCount);
for (j = 0;j < i;++j) // scan all selected items
{
// calculate total amount of needed memory
lMem += SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETTEXTLEN,lpnCount[j],0) + 2;
}
// allocate clipboard data
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,lMem + 1)) != NULL)
{
LPBYTE lpData;
if (lpData = GlobalLock(hClipObj))
{
for (j = 0;j < i;++j) // scan all selected items
{
lpData += SendDlgItemMessage(hDlg,IDC_DISASM_WIN,LB_GETTEXT,lpnCount[j],(LPARAM) lpData);
*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);
}
}
LocalFree(lpnCount); // free item table
}
2024-03-19 22:25:45 +01:00
return TRUE;
2024-03-19 22:24:30 +01:00
case 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);
}
//
// 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:
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:25:45 +01:00
static LRESULT OnToolDisasm() // disasm dialogbox call
2024-03-19 22:24:30 +01:00
{
if (pbyRom) SwitchToState(3);
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_DISASM), hWnd, (DLGPROC)Disasm) == -1)
AbortMessage("Disassembler Dialog Box Creation Error !");
if (pbyRom) SwitchToState(0);
return 0;
}
static LRESULT OnAbout()
{
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1)
AbortMessage("About Dialog Box Creation Error !");
return 0;
}
static LRESULT OnLButtonDown(UINT nFlags, WORD x, WORD y)
{
if (nState==0) MouseButtonDownAt(nFlags, x,y);
return 0;
}
static LRESULT OnLButtonUp(UINT nFlags, WORD x, WORD y)
{
if (nState==0) MouseButtonUpAt(nFlags, x,y);
return 0;
}
static LRESULT OnMouseMove(UINT nFlags, WORD x, WORD y)
{
if (nState==0) MouseMovesTo(nFlags, x,y);
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:24:30 +01:00
if (nState==0 && (lKeyData & 0x40000000)==0)
RunKey((BYTE)nVirtKey, TRUE);
return 0;
}
static LRESULT OnKeyUp(int nVirtKey, DWORD lKeyData)
{
if (nState==0) RunKey((BYTE)nVirtKey, FALSE);
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:
switch (LOWORD(wParam))
{
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
#if 0 // 01.12.99 cg, removed
2024-03-19 22:24:30 +01:00
static BOOL FlushMessages(LPMSG msg)
{
while (PeekMessage(msg, NULL, 0, 0, PM_REMOVE))
{
if (msg->message == WM_QUIT) return TRUE;
TranslateMessage(msg);
DispatchMessage(msg);
}
return FALSE;
}
2024-03-19 22:25:45 +01:00
#endif // 01.12.99 cg
2024-03-19 22:24:30 +01:00
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:24:30 +01:00
hApp = hInst;
2024-03-19 22:25:45 +01:00
nArgc = __argc; // 08.11.99 cg, new, no. of command line arguments
ppArgv = (LPCTSTR*) __argv; // 08.11.99 cg, new, command line arguments
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));
wc.hCursor = LoadCursor(NULL, IDC_ARROW);
wc.hbrBackground = NULL;
wc.lpszMenuName = MAKEINTRESOURCE(IDR_MENU);
wc.lpszClassName = "CEmu48";
if (!RegisterClass(&wc))
{
AbortMessage(
"CEmu48 class registration failed.\n"
"This application will now terminate.");
return FALSE;
}
// 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);
hWnd = CreateWindow("CEmu48", "Emu48",
WS_CAPTION|WS_SYSMENU|WS_MINIMIZEBOX|WS_OVERLAPPED,
CW_USEDEFAULT, CW_USEDEFAULT,
rectWindow.right - rectWindow.left,
rectWindow.bottom - rectWindow.top,
NULL,NULL,hApp,NULL
);
if (hWnd == NULL)
{
AbortMessage("Window creation failed.\n");
return FALSE;
}
ShowWindow(hWnd, nCmdShow);
2024-03-19 22:25:45 +01:00
// 01.12.99 cg, removed, useless and quit with resources open
// if (FlushMessages(&msg)) return msg.wParam;
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:24:30 +01:00
GetCurrentDirectory(sizeof(szCurrentDirectory), szCurrentDirectory);
ReadSettings();
UpdateWindowStatus();
2024-03-19 22:25:45 +01:00
// create auto event handle
hEventShutdn = CreateEvent(NULL,FALSE,FALSE,NULL);
if (hEventShutdn == NULL)
{
AbortMessage("Event creation failed.");
DestroyWindow(hWnd); // 02.12.99 cg, bugfix, close DC
return FALSE;
}
2024-03-19 22:24:30 +01:00
nState = 1; // thread starts in an invalid state
nNextState = 1;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId);
if (hThread == NULL)
{
2024-03-19 22:25:45 +01:00
CloseHandle(hEventShutdn); // close event handle
2024-03-19 22:24:30 +01:00
AbortMessage("Thread creation failed.");
2024-03-19 22:25:45 +01:00
DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:25:45 +01:00
// 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:25:45 +01:00
TerminateThread(hThread, 0); // 01.12.99 cg, bugfix, kill emulation thread
CloseHandle(hEventShutdn); // 01.12.99 cg, bugfix, close event handle
2024-03-19 22:24:30 +01:00
AbortMessage("Could not initialize server!");
2024-03-19 22:25:45 +01:00
DestroyWindow(hWnd); // 01.12.99 cg, bugfix, close DC
2024-03-19 22:24:30 +01:00
return FALSE;
}
2024-03-19 22:25:45 +01:00
// 08.11.99 cg, changed, replaced __argc and __argv variable
if (nArgc >= 2) // use decoded parameter line
2024-03-19 22:24:30 +01:00
{
CHAR szTemp[256] = "Loading ";
2024-03-19 22:25:45 +01:00
strcat(szTemp, ppArgv[1]);
2024-03-19 22:24:30 +01:00
SetWindowTitle(szTemp);
2024-03-19 22:25:45 +01:00
// 01.12.99 cg, removed, useless and quit with resources open
// if (FlushMessages(&msg)) return msg.wParam;
if (OpenDocument(ppArgv[1]))
2024-03-19 22:24:30 +01:00
goto start;
}
2024-03-19 22:25:45 +01:00
// 08.11.99 cg, end of replacement
2024-03-19 22:24:30 +01:00
2024-03-19 22:25:45 +01:00
// 11.12.99 cg, changed, call function
ReadLastDocument(szBufferFilename, sizeof(szBufferFilename));
2024-03-19 22:24:30 +01:00
if (szBufferFilename[0])
{
CHAR szTemp[256] = "Loading ";
strcat(szTemp, szBufferFilename);
SetWindowTitle(szTemp);
2024-03-19 22:25:45 +01:00
// 01.12.99 cg, removed, useless and quit with resources open
// if (FlushMessages(&msg)) return msg.wParam;
2024-03-19 22:24:30 +01:00
if (OpenDocument(szBufferFilename))
goto start;
}
2024-03-19 22:25:45 +01:00
2024-03-19 22:24:30 +01:00
SetWindowTitle("New Document");
2024-03-19 22:25:45 +01:00
// 01.12.99 cg, removed, useless and quit with resources open
// if (FlushMessages(&msg)) return msg.wParam;
2024-03-19 22:24:30 +01:00
if (NewDocument())
{
SetWindowTitle("Untitled");
goto start;
}
ResetDocument();
start:
2024-03-19 22:25:45 +01:00
InitializeCriticalSection(&csGDILock);
InitializeCriticalSection(&csKeyLock);
InitializeCriticalSection(&csIOLock);
InitializeCriticalSection(&csT1Lock);
InitializeCriticalSection(&csT2Lock);
InitializeCriticalSection(&csRecvLock); // 24.10.99 cg, moved, init critical section for receive byte
// init clipboard format and name service
2024-03-19 22:24:30 +01:00
uCF_HpObj = RegisterClipboardFormat(CF_HPOBJ);
hszService = DdeCreateStringHandle(idDdeInst,szAppName,0);
hszTopic = DdeCreateStringHandle(idDdeInst,szTopic,0);
DdeNameService(idDdeInst,hszService,NULL,DNS_REGISTER);
if (pbyRom) SwitchToState(0);
while (GetMessage(&msg, NULL, 0, 0))
{
2024-03-19 22:25:45 +01:00
if(hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
2024-03-19 22:24:30 +01:00
}
2024-03-19 22:25:45 +01:00
SwitchToState(2); // 01.12.99 cg, moved from OnDestroy(), exit emulation thread
// 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:25:45 +01:00
DeleteCriticalSection(&csGDILock);
DeleteCriticalSection(&csKeyLock);
DeleteCriticalSection(&csIOLock);
DeleteCriticalSection(&csT1Lock);
DeleteCriticalSection(&csT2Lock);
DeleteCriticalSection(&csRecvLock); // 24.10.99 cg, moved, end of critical section for receive byte
WriteSettings(); // 01.12.99 cg, moved from OnDestroy()
2024-03-19 22:24:30 +01:00
2024-03-19 22:25:45 +01:00
CloseHandle(hEventShutdn); // close event handle
_ASSERT(nState == 2); // 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:24:30 +01:00
return msg.wParam;
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(hPrevInst);
}