emu48-mirror/sources/Emu48/EMU48.C
2024-03-19 22:24:30 +01:00

1611 lines
45 KiB
C

/*
* 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"
#define VERSION "1.10" // 05.02.99 cg, version changed
#define EMU48_INI "Emu48.ini"
#define CF_HPOBJ "CF_HPOBJ" // 13.05.98 cg, clipboard format for DDE
#define MAXPORTS 16 // 20.05.98 cg, number of COM ports
// 30.05.98 cg, new, cards status
#define PORT1_PRESENT ((cCurrentRomType=='S')?0x1:0x2)
#define PORT1_WRITE ((cCurrentRomType=='S')?0x4:0x8)
#define PORT2_PRESENT ((cCurrentRomType=='S')?0x2:0x1)
#define PORT2_WRITE ((cCurrentRomType=='S')?0x8:0x4)
// #define MONOCHROME // 27.01.99 cg, CF_BITMAP clipboard format
#ifdef _DEBUG
LPSTR szNoTitle = "Emu48 "VERSION" Debug";
#else
LPSTR szNoTitle = "Emu48 "VERSION; // 20.01.98 cg, changed
#endif
LPSTR szAppName = "Emu48"; // 13.05.98 cg, new, application name for DDE server
LPSTR szTopic = "Stack"; // 13.05.98 cg, new, topic for DDE server
LPSTR szTitle = NULL;
static const char szLicence[] =
"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"
"along with this program; if not, write to the Free Software\r\n"
"Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.";
CRITICAL_SECTION csGDILock; // 22.01.98 cg, critical section for hWindowDC
CRITICAL_SECTION csKeyLock; // 02.09.98 cg, critical section for key scan
CRITICAL_SECTION csIOLock; // 24.02.99 cg, new, critical section for I/O access
CRITICAL_SECTION csT1Lock; // 21.04.98 cg, new, critical section for timer1 access
CRITICAL_SECTION csT2Lock; // 21.04.98 cg, new, critical section for timer2 access
LARGE_INTEGER lFreq; // 24.08.98 cg, new, counter frequency
DWORD idDdeInst; // 13.05.98 cg, DDE server id
UINT uCF_HpObj; // 13.05.98 cg, DDE clipboard format
HINSTANCE hApp = NULL;
HWND hWnd = NULL;
HDC hWindowDC = NULL;
HPALETTE hPalette = NULL;
HPALETTE hOldPalette = NULL; // 11.09.98 cg, new, old palette of hWindowDC
HANDLE hThread;
DWORD lThreadId;
BOOL bAutoSave = FALSE;
BOOL bAutoSaveOnExit = TRUE;
BOOL bAlwaysDisplayLog = TRUE;
static BOOL bRealSpeed = FALSE;
//################
//#
//# Window Status
//#
//################
VOID SetWindowTitle(LPSTR szString)
{
if (szTitle)
{
LocalFree(szTitle);
}
if (szString)
{
szTitle = DuplicateString(szString);
}
else
{
szTitle = NULL;
}
if (szTitle)
{
SetWindowText(hWnd, szTitle);
}
else
{
SetWindowText(hWnd, szNoTitle);
}
return;
}
VOID UpdateWindowStatus()
{
HMENU hMenu;
if (hWnd == NULL) return; // 30.01.98 cg, bugfix, return if window closed
hMenu = GetMenu(hWnd);
if ((nState == 0)||(nState == 3))
{
if (szCurrentFilename[0])
EnableMenuItem(hMenu,ID_FILE_SAVE,MF_ENABLED);
else
EnableMenuItem(hMenu,ID_FILE_SAVE,MF_GRAYED);
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);
EnableMenuItem(hMenu,ID_OBJECT_LOAD,MF_ENABLED);
EnableMenuItem(hMenu,ID_OBJECT_SAVE,MF_ENABLED);
// 17.06.98 cg, new, enable menu entries
EnableMenuItem(hMenu,ID_STACK_COPY,MF_ENABLED);
EnableMenuItem(hMenu,ID_STACK_PASTE,MF_ENABLED);
// 10.11.98 cg, new, enable menu entries
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);
// 17.06.98 cg, new, disable menu entries
EnableMenuItem(hMenu,ID_STACK_COPY,MF_GRAYED);
EnableMenuItem(hMenu,ID_STACK_PASTE,MF_GRAYED);
// 10.11.98 cg, new, enable menu entries
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
//#
//################
static BOOL WritePrivateProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue, LPCTSTR lpszFilename)
{
char s[16];
wsprintf(s,"%i",nValue);
return WritePrivateProfileString(lpszSection, lpszEntry, s, lpszFilename);
}
// 20.05.98 cg, new, set listfield for serial combobox
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 VOID ReadSettings()
{
// Files
// 01.02.98 cg, calculate size of buffer
GetPrivateProfileString("Files","Emu48Directory",szCurrentDirectory,szEmu48Directory,
sizeof(szEmu48Directory),EMU48_INI);
bAutoSave = GetPrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI);
bAutoSaveOnExit = GetPrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI);
// Port2
bPort2IsShared = GetPrivateProfileInt("Port2","IsShared",0,EMU48_INI);
// 01.02.98 cg, calculate size of buffer
GetPrivateProfileString("Port2","Filename","SHARED.BIN",szPort2Filename,sizeof(szPort2Filename),EMU48_INI);
// Timers
// 13.06.98 cg, changed default value from unset to set
// 10.11.98 cg, removed, not adjustable any more
// bAccurateTimer = GetPrivateProfileInt("Timers","AccurateTimer",1,EMU48_INI);
// uT1Period = GetPrivateProfileInt("Timers","T1Period",62,EMU48_INI);
// KML
bAlwaysDisplayLog = GetPrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
// 23.04.98 cg, new, Emulator
bRealSpeed = GetPrivateProfileInt("Emulator","RealSpeed",0,EMU48_INI);
dwSXCycles = GetPrivateProfileInt("Emulator","SXCycles",82,EMU48_INI);
dwGXCycles = GetPrivateProfileInt("Emulator","GXCycles",123,EMU48_INI);
SetSpeed(bRealSpeed); // 23.04.98 cg, set speed
// 20.05.98 cg, new, Serial
GetPrivateProfileString("Serial","Wire",NO_SERIAL,szSerialWire,sizeof(szSerialWire),EMU48_INI);
GetPrivateProfileString("Serial","Ir",NO_SERIAL,szSerialIr,sizeof(szSerialIr),EMU48_INI);
return;
}
static VOID WriteSettings()
{
// Files
WritePrivateProfileString("Files","Emu48Directory",szEmu48Directory,EMU48_INI);
WritePrivateProfileInt("Files","AutoSave",bAutoSave,EMU48_INI);
WritePrivateProfileInt("Files","AutoSaveOnExit",bAutoSaveOnExit,EMU48_INI);
// Port2
WritePrivateProfileInt("Port2","IsShared",bPort2IsShared,EMU48_INI);
WritePrivateProfileString("Port2","Filename",szPort2Filename,EMU48_INI);
// Timers
// 10.11.98 cg, removed, not adjustable any more
// WritePrivateProfileInt("Timers","AccurateTimer",bAccurateTimer,EMU48_INI);
// WritePrivateProfileInt("Timers","T1Period",uT1Period,EMU48_INI);
// KML
WritePrivateProfileInt("KML","AlwaysDisplayLog",bAlwaysDisplayLog,EMU48_INI);
// 23.04.98 cg, new, Emulator
WritePrivateProfileInt("Emulator","RealSpeed",bRealSpeed,EMU48_INI);
WritePrivateProfileInt("Emulator","SXCycles",dwSXCycles,EMU48_INI);
WritePrivateProfileInt("Emulator","GXCycles",dwGXCycles,EMU48_INI);
// 20.05.98 cg, new, Serial
WritePrivateProfileString("Serial","Wire",szSerialWire,EMU48_INI);
WritePrivateProfileString("Serial","Ir",szSerialIr,EMU48_INI);
return;
}
static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{
switch (message)
{
case WM_INITDIALOG:
// 30.05.98 cg, new, init port1 enable checkbox
CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0);
CheckDlgButton(hDlg,IDC_PORT1WR,Chipset.Port1_Writeable);
// 23.04.98 cg, new, init speed checkbox
CheckDlgButton(hDlg,IDC_REALSPEED,bRealSpeed);
CheckDlgButton(hDlg,IDC_AUTOSAVE,bAutoSave);
CheckDlgButton(hDlg,IDC_AUTOSAVEONEXIT,bAutoSaveOnExit);
CheckDlgButton(hDlg,IDC_ALWAYSDISPLOG,bAlwaysDisplayLog);
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
// 10.11.98 cg, removed, not adjustable any more
// SetDlgItemInt(hDlg,IDC_T1PERIOD,uT1Period,FALSE);
// 20.05.98 cg, new, set combobox parameter
SetCommList(hDlg,IDC_WIRE,szSerialWire);
SetCommList(hDlg,IDC_IR,szSerialIr);
// 10.11.98 cg, removed, not adjustable any more
// CheckDlgButton(hDlg,IDC_USEMMTIMER,bAccurateTimer);
if (nState == 1)
{
// 30.05.98 cg, new, disable port1 enable box
EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
}
else
{
EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE);
}
if (CommConnect() != PORT_CLOSE) // 20.05.98 cg, new, disable when port open
{
EnableWindow(GetDlgItem(hDlg,IDC_WIRE),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
}
return TRUE;
case WM_COMMAND:
if (wParam == IDOK)
{
// BOOL bTranslated;
// UINT uNewT1Period;
if (Chipset.Port1Size)
{
UINT nOldState = SwitchToState(3);
Chipset.Port1_Writeable = IsDlgButtonChecked(hDlg, IDC_PORT1WR);
// 30.05.98 cg, changed, added code for port1 disable
Chipset.cards_status = 0;
if (IsDlgButtonChecked(hDlg, IDC_PORT1EN))
{
Chipset.cards_status |= PORT1_PRESENT;
if (Chipset.Port1_Writeable)
Chipset.cards_status |= PORT1_WRITE;
}
if (Chipset.inte)
{
Chipset.Shutdn = FALSE;
Chipset.SoftInt = TRUE;
bInterrupt = TRUE;
}
Map(0x00,0xFF);
SwitchToState(nOldState);
}
// 23.04.98 cg, new, get speed checkbox value
bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED);
bAutoSave = IsDlgButtonChecked(hDlg, IDC_AUTOSAVE);
bAutoSaveOnExit = IsDlgButtonChecked(hDlg, IDC_AUTOSAVEONEXIT);
bAlwaysDisplayLog = IsDlgButtonChecked(hDlg, IDC_ALWAYSDISPLOG);
SetSpeed(bRealSpeed); // 23.04.98 cg, set speed
if (nState == 1)
{
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
// 01.02.98 cg, calculate size of buffer
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,sizeof(szPort2Filename));
}
// 10.11.98 cg, removed, not adjustable any more
// bAccurateTimer = IsDlgButtonChecked(hDlg,IDC_USEMMTIMER);
// uNewT1Period = GetDlgItemInt(hDlg, IDC_T1PERIOD, &bTranslated, FALSE);
// if (bTranslated)
// uT1Period = uNewT1Period;
// else
// uT1Period = 62;
// 20.05.98 cg, new, set combobox parameter
// 26.08.98 cg, changed implementation
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,sizeof(szSerialWire));
GetDlgItemText(hDlg,IDC_IR ,szSerialIr ,sizeof(szSerialIr));
EndDialog(hDlg, wParam);
}
if (wParam == IDCANCEL)
{
EndDialog(hDlg, wParam);
}
// 10.11.98 cg, removed, not adjustable any more
// if (wParam == IDC_T1DEFAULT)
// {
// SetDlgItemInt(hDlg,IDC_T1PERIOD,62,FALSE);
// }
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(hDlg);
}
//################
//#
//# 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;
WritePrivateProfileString("Files","LastDocument",szCurrentFilename,EMU48_INI);
return IDYES;
}
SaveDocument();
return IDYES;
}
//################
//#
//# Message Handlers
//#
//################
//
// WM_CREATE
//
static LRESULT OnCreate(HWND hWindow)
{
hWnd = hWindow;
hWindowDC = GetDC(hWnd);
DragAcceptFiles(hWnd,TRUE); // 05.02.99 cg & Will Laughlin, moved, support dropped files
return 0;
}
//
// WM_DESTROY
//
static LRESULT OnDestroy(HWND hWindow)
{
DragAcceptFiles(hWnd,FALSE); // 05.02.99 cg & Will Laughlin, no WM_DROPFILES message any more
SwitchToState(2);
WriteSettings();
ReleaseDC(hWnd, hWindowDC);
SetWindowTitle(NULL); // 27.01.98 cg, bugfix, free memory of title
hWindowDC = NULL; // 11.09.98 cg, hWindowDC isn't valid any more
hWnd = NULL;
PostQuitMessage(0);
return 0;
UNREFERENCED_PARAMETER(hWindow);
}
//
// WM_PAINT
//
static LRESULT OnPaint(HWND hWindow)
{
PAINTSTRUCT Paint;
HDC hPaintDC;
hPaintDC = BeginPaint(hWindow, &Paint);
if (hMainDC != NULL) // 30.01.98 cg, bugfix, EndPaint() was not called
{
BitBlt(hPaintDC, 0, 0, nBackgroundW, nBackgroundH, hMainDC, nBackgroundX, nBackgroundY, SRCCOPY);
if ((nState==0)||(nState==3))
{
UpdateMainDisplay();
UpdateMenuDisplay();
UpdateAnnunciators(); // 21.07.98 cg, bugfix, redraw annunciators
RefreshButtons();
}
}
EndPaint(hWindow, &Paint);
return 0;
}
//
// WM_DROPFILES
//
// 01.11.98 cg & Will Laughlin, new, support dropped files
static LRESULT OnDropFiles(HANDLE hFilesInfo)
{
char szFileName[MAX_PATH];
WORD wNumFiles,wIndex;
BOOL bSuccess;
// 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;
}
WritePrivateProfileString("Files","LastDocument",szCurrentFilename,EMU48_INI);
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
//
static LRESULT OnFileExit()
{
SwitchToState(2); // 21.02.99 cg, bugfix, hold emulation thread first
if (SaveChanges(bAutoSaveOnExit) == IDCANCEL)
{
return 0;
}
DestroyWindow(hWnd);
return 0;
}
//
// WM_SYS_CLOSE
//
static LRESULT OnSysClose()
{
SwitchToState(2); // 21.02.99 cg, bugfix, hold emulation thread first
if (SaveChanges(bAutoSaveOnExit) == IDCANCEL)
{
return 0;
}
DestroyWindow(hWnd);
return 0;
}
//
// ID_STACK_COPY
//
static LRESULT OnStackCopy() // 17.06.98 cg, new, copy data from stack
{
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
//
static LRESULT OnStackPaste() // 17.06.98 cg, new, paste data to stack
{
HANDLE hClipObj;
LPBYTE lpClipdata,lpData;
BOOL bSuccess = FALSE;
// 10.11.98 cg, bugfix, moved from bottom of function
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()
{
// 22.09.98 cg, bugfix, always close clipboard
if (OpenClipboard(hWnd))
{
if (EmptyClipboard())
{
#if !defined MONOCHROME
// 27.01.99 cg, changed implementation for DIB bitmap
#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
// 27.01.99 cg, end of changed implementation
#else
HBITMAP hOldBmp, hBmp;
HDC hBmpDC;
// 24.08.98 cg, changed implementation
_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);
// 24.08.98 cg, end of changed implementation
SetClipboardData(CF_BITMAP,hBmp);
SelectObject(hBmpDC,hOldBmp);
DeleteDC(hBmpDC);
#endif
}
CloseClipboard();
}
// 22.09.98 cg, end of bugfix
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);
Chipset.pc = 0;
Chipset.inte = TRUE;
Chipset.Shutdn = FALSE;
Chipset.SoftInt = TRUE;
Reset(); // 21.01.98 cg, bugfix, must unconfig MMU too
bInterrupt = TRUE;
SwitchToState(0);
}
return 0;
}
//
// ID_VIEW_SETTINGS
//
static LRESULT OnViewSettings()
{
ReadSettings();
if (nState == 1) UnmapPort2();
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_SETTINGS), hWnd, (DLGPROC)SettingsProc) == -1)
AbortMessage("Settings Dialog Creation Error !");
if (nState == 1) MapPort2(szPort2Filename);
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;
if (!Chipset.dispon) // 10.11.98 cg, new, calculator off, turn on
{
// 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;
}
if (WaitForSleepState()) // 10.11.98 cg, changed, wait for cpu SHUTDN then sleep state
{
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);
// 10.11.98 cg, changed, wait for sleep mode
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;
}
if (WaitForSleepState()) // 10.11.98 cg, wait for cpu SHUTDN then sleep state
return 0;
while (nState!=nNextState) Sleep(0);
_ASSERT(nState==3);
if (!GetSaveObjectFilename())
{
SwitchToState(0);
return 0;
}
SaveObject(szBufferFilename);
SwitchToState(0);
return 0;
}
//
// ID_DISASM
//
// 15.07.98 cg, new, dialogbox for disassembly
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:
// 10.11.98 cg, new, set fonts & cursor
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);
// 10.11.98 cg, end of new part
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));
// 12.02.98 cg, new, set font of new button
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);
disassembler_map = MEM_MAP; // 10.11.98 cg, new disassemble with mapped modules
disassembler_mode = HP_MNEMONICS; // 10.11.98 cg, new use HP mnemonics for disassembling
dwAddress = strtoul(szAddress,&cpStop,16);
dwAddressMax = 0x100000; // 10.11.98 cg, new, greatest address (mapped mode)
return TRUE;
case WM_COMMAND:
switch(wParam)
{
// 10.11.98 cg, new, decode radio buttons
case IDC_DISASM_MAP:
disassembler_map = MEM_MAP;
dwAddressMax = 0x100000;
break;
case IDC_DISASM_ROM:
disassembler_map = MEM_ROM;
dwAddressMax = dwRomSize;
break;
case IDC_DISASM_RAM:
disassembler_map = MEM_RAM;
dwAddressMax = Chipset.Port0Size * 2048;
break;
case IDC_DISASM_PORT1:
disassembler_map = MEM_PORT1;
dwAddressMax = ((Chipset.cards_status & PORT1_PRESENT) != 0) ? (Chipset.Port1Size * 2048) : 0;
break;
case IDC_DISASM_PORT2:
disassembler_map = MEM_PORT2;
dwAddressMax = (dwPort2Mask != 0) ? ((dwPort2Mask + 1) << 17) : 0;
break;
case IDC_DISASM_HP:
disassembler_mode = HP_MNEMONICS;
break;
case IDC_DISASM_CLASS:
disassembler_mode = CLASS_MNEMONICS;
break;
// 10.11.98 cg, end of new part
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:
if (dwAddress >= dwAddressMax) // 10.11.98 cg, bugfix, moved check from IDOK
return FALSE;
i = wsprintf(szAddress,"%05lX ",dwAddress);
dwAddress = disassemble(dwAddress,&szAddress[i]);
// 12.02.99 cg, changed, implementation for multi selectable items
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);
break;
// 12.02.99 cg, new, copy selected items to clipoard
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
}
break;
// 12.02.99 cg, end of new part
case IDCANCEL:
EndDialog(hDlg, wParam);
break;
}
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(hDlg);
}
//
// 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);
break;
}
break;
}
return FALSE;
UNREFERENCED_PARAMETER(lParam);
UNREFERENCED_PARAMETER(hDlg);
}
static LRESULT OnToolDisasm() // 15.07.98 cg, new, disasm dialogbox call
{
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 (pbyRom) SwitchToState(3); // 25.01.99 cg, removed, don't stop emulation
if (DialogBox(hApp, MAKEINTRESOURCE(IDD_ABOUT), hWnd, (DLGPROC)About) == -1)
AbortMessage("About Dialog Box Creation Error !");
// if (pbyRom) SwitchToState(0); // 25.01.99 cg, removed
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)
{
// 03.09.98 cg, bugfix, call RunKey() only once (suppress autorepeat feature)
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);
}
static LRESULT CALLBACK MainWndProc(HWND hWindow, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_CREATE: return OnCreate(hWindow);
case WM_DESTROY: return OnDestroy(hWindow);
case WM_PAINT: return OnPaint(hWindow);
// 01.11.98 cg & Will Laughlin, new, support dropped files
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();
case ID_STACK_COPY: return OnStackCopy(); // 17.06.98 cg, new, copy data from stack
case ID_STACK_PASTE: return OnStackPaste(); // 17.06.98 cg, new, paste data to stack
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();
case ID_TOOL_DISASM: return OnToolDisasm(); // 15.07.98 cg, new, disassembler dialog box
case ID_ABOUT: return OnAbout();
}
break;
case WM_SYSCOMMAND:
switch (LOWORD(wParam))
{
case SC_CLOSE: return OnSysClose();
}
break;
case WM_RBUTTONDOWN: // 01.10.97 cg, for holding key pressed
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);
}
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;
}
// 01.11.98 cg, bugfix, changed varible type of first two arguments
int PASCAL WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nCmdShow)
{
MSG msg;
WNDCLASS wc;
RECT rectWindow;
HSZ hszService, hszTopic; // 13.05.98 cg, new, varibles for DDE server
hApp = hInst;
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);
if (FlushMessages(&msg)) return msg.wParam;
// initialization
QueryPerformanceFrequency(&lFreq); // 24.08.98 cg, init high resolution counter
// 01.02.98 cg, calculate size of buffer
GetCurrentDirectory(sizeof(szCurrentDirectory), szCurrentDirectory);
ReadSettings();
// szNoTitle = "Emu48 "VERSION; // 20.01.98 cg, removed
UpdateWindowStatus();
nState = 1; // thread starts in an invalid state
nNextState = 1;
hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&WorkerThread, NULL, 0, &lThreadId);
if (hThread == NULL)
{
AbortMessage("Thread creation failed.");
return FALSE;
}
// 20.02.99 cg, changed, use 2nd command line argument if defined
MapPort2((__argc < 3) ? szPort2Filename : __argv[2]);
// 13.05.98 cg, new, initialize DDE server
if (DdeInitialize(&idDdeInst,(PFNCALLBACK) &DdeCallback,
APPCLASS_STANDARD |
CBF_FAIL_EXECUTES | CBF_FAIL_ADVISES |
CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS,0))
{
AbortMessage("Could not initialize server!");
return FALSE;
}
if (__argc >= 2) // 20.02.99 cg, changed, use decoded parameter line
{
CHAR szTemp[256] = "Loading ";
strcat(szTemp, __argv[1]); // 20.02.99 cg, changed, use decoded parameter line
SetWindowTitle(szTemp);
if (FlushMessages(&msg)) return msg.wParam;
if (OpenDocument(__argv[1])) // 20.02.99 cg, changed, use decoded parameter line
goto start;
}
// 09.12.97 cg, bugfix, function parameter
GetPrivateProfileString("Files","LastDocument","",szBufferFilename,sizeof(szBufferFilename),EMU48_INI);
if (szBufferFilename[0])
{
CHAR szTemp[256] = "Loading ";
strcat(szTemp, szBufferFilename);
SetWindowTitle(szTemp);
if (FlushMessages(&msg)) return msg.wParam;
if (OpenDocument(szBufferFilename))
goto start;
}
SetWindowTitle("New Document");
if (FlushMessages(&msg)) return msg.wParam;
if (NewDocument())
{
SetWindowTitle("Untitled");
goto start;
}
ResetDocument();
// SetWindowTitle(NULL); // 27.01.98 cg, removed, see WM_DESTROY
start:
InitializeCriticalSection(&csGDILock); // 03.01.99 cg, bugfix, initialize critical section
InitializeCriticalSection(&csKeyLock); // 03.01.99 cg, bugfix, initialize critical section
InitializeCriticalSection(&csIOLock); // 24.02.99 cg, new, initialize critical section
InitializeCriticalSection(&csT1Lock); // 03.01.99 cg, bugfix, initialize critical section
InitializeCriticalSection(&csT2Lock); // 03.01.99 cg, bugfix, initialize critical section
// 13.05.98 cg, new, init clipboard format and name service
uCF_HpObj = RegisterClipboardFormat(CF_HPOBJ);
hszService = DdeCreateStringHandle(idDdeInst,szAppName,0);
hszTopic = DdeCreateStringHandle(idDdeInst,szTopic,0);
DdeNameService(idDdeInst,hszService,NULL,DNS_REGISTER);
// 13.05.98 cg, new, end of init
if (pbyRom) SwitchToState(0);
while (GetMessage(&msg, NULL, 0, 0))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
// 13.05.98 cg, new, clean up DDE server
DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER);
DdeFreeStringHandle(idDdeInst, hszService);
DdeFreeStringHandle(idDdeInst, hszTopic);
DdeUninitialize(idDdeInst);
// 13.05.98 cg, new, end of clean up
DeleteCriticalSection(&csGDILock); // 03.01.99 cg, bugfix, release critical section
DeleteCriticalSection(&csKeyLock); // 03.01.99 cg, bugfix, release critical section
DeleteCriticalSection(&csIOLock); // 24.02.99 cg, new, release critical section
DeleteCriticalSection(&csT1Lock); // 03.01.99 cg, bugfix, release critical section
DeleteCriticalSection(&csT2Lock); // 03.01.99 cg, bugfix, release critical section
// SwitchToState(2); // 27.01.98 cg, removed, done in WM_DESTROY
_ASSERT(nState == 2); // 30.01.98 cg, set by WM_DESTROY
ResetDocument();
ResetBackup();
cCurrentRomType = 0;
// KillKML(); // 27.01.98 cg, removed, done in ResetDocument() or OnFileClose()
_ASSERT(pKml == NULL); // 27.01.98 cg, KML script not closed
UnmapPort2();
_ASSERT(szTitle == NULL); // 11.09.98 cg, freed allocated memory
_ASSERT(hPalette == NULL); // 11.09.98 cg, freed resource memory
return msg.wParam;
UNREFERENCED_PARAMETER(lpCmdLine);
UNREFERENCED_PARAMETER(hPrevInst);
}