1611 lines
45 KiB
C
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);
|
|
}
|