2005-12-17: Updated to version 1.40

Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
Gwenhael Le Moine 2024-03-19 23:35:29 +01:00
parent 0c2f128039
commit 2cc9402f4d
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
25 changed files with 1382 additions and 407 deletions

Binary file not shown.

Before

Width:  |  Height:  |  Size: 74 KiB

After

Width:  |  Height:  |  Size: 74 KiB

BIN
EMU48.EXE

Binary file not shown.

View file

@ -1,4 +1,4 @@
Known bugs and restrictions of Emu48 V1.38
Known bugs and restrictions of Emu48 V1.40
------------------------------------------
- the following I/O bits aren't emulated (incomplete)
@ -42,8 +42,7 @@ Known bugs and restrictions of Emu48 V1.38
- no MP interrupt on card control circuit or timer restart
- no beeper support with OUT command -> all programs that aren't
use the "=makebeep" subroutine, like alarm wake up, have no sound
- beeper emulation, ATTN key doesn't work,
Windows 9x: plays only default sound event or standard system beep
- beeper emulation, ATTN key doesn't work
- no infrared printer support
- Shell OS: clock isn't synchronized with real time
- HP49G: the flash memory is emulated now with some restrictions
@ -55,4 +54,4 @@ Known bugs and restrictions of Emu48 V1.38
- quitting the emulator while programming the flash isn't allowed,
because the content of flash state machine isn't saved so far
08/30/05 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
12/13/05 (c) by Christoph Gießelink, c dot giesselink at gmx dot de

View file

@ -1,3 +1,133 @@
Service Pack 40 for Emu48 Version 1.0
DISPLAY.C
- bugfix in function UpdateContrast(), used background Color 0 in
calculator off state even if Color 32 was defined
- bugfix in function CreateLcdBitmap(), DIB section shouldn't
created from the memory DC
EMU48.C
- added function IsPort2Writeable() to check if read only file
attribute is not set on port2 file
- major changes in function SettingsProc(), added "Port 2 is
Writeable" handling and make port2 changeable without closing the
current emulation session
- changed function SaveChanges(), default button for confirming the
"Do you want to save changes ?" message depends now on the
"SaveDefaultConfirm" INI-File setting (1=yes / 0=no button)
EMU48.H
- extern declaration of global variable and functions
EMU48.RC
- added item "Port 2 is Writeable" in settings dialog
- changed version
ENGINE.C
- bugfix in function WorkerThread(), when changing into SM_RUN state
display constrast must also be restored
FILES.C
- changed function CrcPort2(), made it global accessible
KML.C
- added keywords "Topbar" and "Vga" to pLexToken[] table -> scripts
using these keywords now are parsed with warnings and not quit
with a fatal error any more
- bugfix in function SkipWhite(), skipping remark text hadn't stop
at string end
- bugfix in function ParseBlocks(), stopped script parsing without
error at unknown block token
- bugfix in function SkipLines(), TOK_END was handeled wrong ->
this caused a RunKey end if condition of TOK_IFPRESSED or
TOK_IFFLAG was false and there was no TOK_ELSE inside this level
- bugfix in function KillKML(), ROM type wasn't reset to the preset
value at the end
KML.H
- added TOK_TOPBAR and TOK_VGA definition
RESOURCE.H
- added definition
RPL.C
- added function RPL_GetSystemFlag() returning the state of the
given system flag
SETTINGS.C
- changed function ReadSettings() and WriteSettings(), added item
"SaveDefaultConfirm" in section [File] in the INI-File
STACK.C
- added helper functions RPL_GetZInt() and RPL_SetZInt() to handle
HP49G Precision Integer objects
- added function DoInt() to handle a HP49G Precision Integer object
- changed function OnStackCopy() and OnStackPaste(), added HP49G
Precision Integer support (limited to 127/128 digits incl. sign)
TIMER.C
- changed function CheckT1() and CheckT2(), minor optimization in
checking if INT or WAKE bit is set
Service Pack 39 for Emu48 Version 1.0
DISPLAY.C
- bugfix in function CreateMainBitmap(), in error case hMainDC
variable wasn't cleared
EMU48.C
- changed function SettingsProc(), added sound handling
- moved function OnStackCopy() and OnStackPaste() to STACK.C
- changed function WinMain(), added accelerator key access for menus
EMU48.DSP
- added stack.c sources
EMU48.H
- extern declaration of global variables and functions
EMU48.RC
- added "Sound" group in Settings dialog
- changed menu text "Copy String" to "Copy Stack" and menu text
"Paste String" to "Paste Stack"
- added accelerator resource
- changed version
EXTERNAL.C
- added function BeepWave(), beeper function using sound card
- added function BeepWin9x(), PC speaker function for working on
Win9x
- changed function External(), removed range checking of duration;
call function BeepWin9x() on Win9x instead of Beep() or in the
case of wave sound the function BeepWave()
KML.C
- bugfix in function InitKML(), changed log message for no "Model"
definition found and a missing "Bitmap" definition wasn't detected
PCH.H
- added include conio.h
RESOURCE.H
- added several definitions
SETTINGS.C
- changed function ReadSettings() and WriteSettings(), added item
"WaveBeep" and "WaveVolume" in section [Emulator] in the INI-File
STACK.C
- new modul with the message handler functions OnStackCopy() and
OnStackPaste() prior located in EMU48.C
- changed function OnStackCopy() and OnStackPaste(), they can now
also copy real numbers from and to the clipboard
TIMER.C
- bugfix in function SetT1(), fixed unsynchronized access to timer1
value, stop timer1 only if running and restart timer1 only when
timer2 is running
Service Pack 38 for Emu48 Version 1.0
DISPLAY.C

View file

@ -124,15 +124,20 @@ static __inline VOID BuildPattern(VOID)
VOID UpdateContrast(BYTE byContrast)
{
RGBQUAD c,b;
INT i,nColors;
// table for max. 8 colors
const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 };
RGBQUAD c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
RGBQUAD b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == *(DWORD*)&b)
b = *(RGBQUAD*)&dwKMLColor[0];
// when display is off use contrast 0
if ((Chipset.IORam[BITOFFSET] & DON) == 0) byContrast = 0;
c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color
b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color
// if background color is undefined, use color 0 for compatibility
if (I == *(DWORD*)&b) b = *(RGBQUAD*)&dwKMLColor[0];
nColors = bGrayscale ? (NOCOLORSGRAY-1) : (NOCOLORSBW-1);
@ -189,7 +194,7 @@ VOID CreateLcdBitmap(VOID)
bmiLcd.Lcd_bmih.biHeight = -64 * nLcdZoom;
_ASSERT(hLcdDC == NULL);
VERIFY(hLcdDC = CreateCompatibleDC(hWindowDC));
VERIFY(hLcdBitmap = CreateDIBSection(hLcdDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0));
VERIFY(hLcdBitmap = CreateDIBSection(hWindowDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0));
hLcdBitmap = SelectObject(hLcdDC,hLcdBitmap);
_ASSERT(hPalette != NULL);
SelectPalette(hLcdDC,hPalette,FALSE); // set palette for LCD DC
@ -230,6 +235,7 @@ BOOL CreateMainBitmap(LPCTSTR szFilename)
if (hMainBitmap == NULL)
{
DeleteDC(hMainDC);
hMainDC = NULL;
return FALSE;
}
hMainBitmap = SelectObject(hMainDC,hMainBitmap);

View file

@ -13,7 +13,7 @@
#include "kml.h"
#include "debugger.h"
#define VERSION "1.38"
#define VERSION "1.40"
#define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE
#define MAXPORTS 256 // number of COM ports
@ -80,6 +80,7 @@ HCURSOR hCursorHand = NULL;
BOOL bClassicCursor = FALSE; // use hand instead of arrow cursor
BOOL bAutoSave = FALSE;
BOOL bAutoSaveOnExit = TRUE;
BOOL bSaveDefConfirm = TRUE; // yes
BOOL bAlwaysDisplayLog = TRUE;
BOOL bLoadObjectWarning = TRUE;
@ -221,6 +222,21 @@ VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboar
//#
//################
// get R/W state of port2 file
static BOOL IsPort2Writeable(VOID)
{
DWORD dwFileAtt;
BOOL bWriteable = FALSE;
SetCurrentDirectory(szEmuDirectory);
dwFileAtt = GetFileAttributes(szPort2Filename);
if (dwFileAtt != 0xFFFFFFFF)
bWriteable = ((dwFileAtt & FILE_ATTRIBUTE_READONLY) == 0);
SetCurrentDirectory(szCurrentDirectory);
return bWriteable;
}
// set listfield for serial combobox
static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting)
{
@ -257,6 +273,9 @@ static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting)
static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lParam)
{
BOOL bPort2CfgChange = FALSE;
BOOL bPort2AttChange = FALSE;
switch (message)
{
case WM_INITDIALOG:
@ -271,6 +290,15 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
// set disassebler mode
CheckDlgButton(hDlg,(disassembler_mode == HP_MNEMONICS) ? IDC_DISASM_HP : IDC_DISASM_CLASS,BST_CHECKED);
// set sound slider
SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETRANGE,FALSE,MAKELONG(0,255));
SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETTICFREQ,256/8,0);
SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETPOS,TRUE,dwWaveVol);
// set sound radio button
CheckDlgButton(hDlg,bWaveBeep ? IDC_SOUND_WAVE : IDC_SOUND_SPEAKER,BST_CHECKED);
EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),bWaveBeep);
// set combobox parameter
SetCommList(hDlg,IDC_WIRE,szSerialWire);
SetCommList(hDlg,IDC_IR,szSerialIr);
@ -281,13 +309,14 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
}
// HP48SX/GX
if (cCurrentRomType=='S' || cCurrentRomType=='G')
if (cCurrentRomType=='S' || cCurrentRomType=='G' || cCurrentRomType==0)
{
// init port1 enable checkbox
CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0);
CheckDlgButton(hDlg,IDC_PORT1WR,(Chipset.cards_status & PORT1_WRITE) != 0);
// init port2 shared checkbox and set port2 filename
// init port2 shared and writeable checkbox and set port2 filename
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
CheckDlgButton(hDlg,IDC_PORT2WR,IsPort2Writeable());
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
if (nState == SM_INVALID) // Invalid State
{
@ -299,29 +328,26 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
{
EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE);
if (nState == SM_INVALID) // Invalid State
{
// init port2 shared checkbox and set port2 filename
CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared);
SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename);
}
EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2WR),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2LOAD),FALSE);
if (cCurrentRomType=='X') // HP49G
{
SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0);
EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE);
}
}
if (nState != SM_INVALID) // not in Invalid State
{
// hide port2 settings
EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE);
EnableWindow(GetDlgItem(hDlg,IDC_PORT2LOAD),FALSE);
}
return TRUE;
case WM_COMMAND:
switch (LOWORD(wParam))
{
case IDC_SOUND_SPEAKER:
EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),FALSE);
return TRUE;
case IDC_SOUND_WAVE:
EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),TRUE);
return TRUE;
case IDC_PORT2LOAD:
if (GetLoadObjectFilename())
{
@ -366,9 +392,37 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
Chipset.SoftInt = TRUE; // set interrupt
bInterrupt = TRUE;
}
Map(0x00,0xFF);
SwitchToState(nOldState);
}
// HP48SX/GX port2 change settings detection
if(cCurrentRomType=='S' || cCurrentRomType=='G' || cCurrentRomType==0)
{
TCHAR szFilename[MAX_PATH];
BOOL bPortShared;
// shared port
bPortShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
if (bPort2IsShared != bPortShared)
{
bPort2IsShared = bPortShared;
bPort2CfgChange = TRUE; // slot2 configuration changed
}
// get current filename and notify difference
GetDlgItemText(hDlg,IDC_PORT2,szFilename,ARRAYSIZEOF(szFilename));
if (lstrcmp(szPort2Filename,szFilename) != 0)
{
lstrcpyn(szPort2Filename,szFilename,ARRAYSIZEOF(szPort2Filename));
bPort2CfgChange = TRUE; // slot2 configuration changed
}
// R/W port
if (IsDlgButtonChecked(hDlg,IDC_PORT2WR) != (UINT) IsPort2Writeable())
{
bPort2AttChange = TRUE; // slot2 file R/W attribute changed
bPort2CfgChange = TRUE; // slot2 configuration changed
}
}
// get speed checkbox value
bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED);
bAutoSave = IsDlgButtonChecked(hDlg, IDC_AUTOSAVE);
@ -383,13 +437,54 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP
SetLcdMode(!bGrayscale); // set new display mode
SwitchToState(nOldState);
}
if (nState == SM_INVALID)
if (bPort2CfgChange) // slot2 configuration changed
{
bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED);
GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,ARRAYSIZEOF(szPort2Filename));
UINT nOldState = SwitchToState(SM_INVALID);
UnmapPort2(); // unmap port2
if (bPort2AttChange) // slot2 R/W mode changed
{
DWORD dwFileAtt;
SetCurrentDirectory(szEmuDirectory);
dwFileAtt = GetFileAttributes(szPort2Filename);
if (dwFileAtt != 0xFFFFFFFF)
{
if (IsDlgButtonChecked(hDlg,IDC_PORT2WR))
dwFileAtt &= ~FILE_ATTRIBUTE_READONLY;
else
dwFileAtt |= FILE_ATTRIBUTE_READONLY;
SetFileAttributes(szPort2Filename,dwFileAtt);
}
SetCurrentDirectory(szCurrentDirectory);
}
if (cCurrentRomType) // ROM defined
{
// use 2nd command line argument if defined
MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]);
// port2 changed and card detection enabled
if ( (bPort2AttChange || Chipset.wPort2Crc != CrcPort2())
&& (Chipset.IORam[CARDCTL] & ECDT) != 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0
)
{
Chipset.HST |= MP; // set Module Pulled
IOBit(SRQ2,NINT,FALSE); // set NINT to low
Chipset.SoftInt = TRUE; // set interrupt
bInterrupt = TRUE;
}
// save fingerprint of port2
Chipset.wPort2Crc = CrcPort2();
}
SwitchToState(nOldState);
}
// set disassebler mode
// set disassembler mode
disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS;
// set sound data
dwWaveVol = SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_GETPOS,0,0);
bWaveBeep = IsDlgButtonChecked(hDlg,IDC_SOUND_WAVE);
// set combobox parameter
GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,ARRAYSIZEOF(szSerialWire));
if (cCurrentRomType!='X') // HP49G Ir port is not connected
@ -427,7 +522,11 @@ static UINT SaveChanges(BOOL bAuto)
if (bAuto)
uReply = IDYES;
else
uReply = YesNoCancelMessage(_T("Do you want to save changes ?"));
{
UINT uStyle = bSaveDefConfirm ? 0 : MB_DEFBUTTON2;
uReply = YesNoCancelMessage(_T("Do you want to save changes ?"),uStyle);
}
if (uReply != IDYES) return uReply;
@ -739,148 +838,6 @@ static LRESULT OnFileExit(VOID)
return 0;
}
//
// ID_STACK_COPY
//
static LRESULT OnStackCopy(VOID) // copy data from stack
{
HANDLE hClipObj;
LPBYTE lpData;
DWORD dwAddress,dwSize;
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
InfoMessage(_T("The emulator is busy."));
return 0;
}
_ASSERT(nState == SM_SLEEP);
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(SM_RUN);
return 0;
}
//
// ID_STACK_PASTE
//
static LRESULT OnStackPaste(VOID) // paste data to stack
{
HANDLE hClipObj;
LPBYTE lpClipdata,lpData;
BOOL bSuccess = FALSE;
// check if clipboard format is available
if (!IsClipboardFormatAvailable(CF_TEXT))
{
MessageBeep(MB_OK); // error beep
return 0;
}
SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
{
KeyboardEvent(TRUE,0,0x8000);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
}
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
InfoMessage(_T("The emulator is busy."));
goto cancel;
}
_ASSERT(nState == SM_SLEEP);
if (OpenClipboard(hWnd))
{
if ((hClipObj = GetClipboardData(CF_TEXT)))
{
if ((lpClipdata = GlobalLock(hClipObj)))
{
DWORD dwSize = strlen(lpClipdata);
if ((lpData = HeapAlloc(hHeap,0,dwSize * 2)))
{
memcpy(lpData+dwSize,lpClipdata,dwSize); // copy data
bSuccess = (WriteStack(lpData,dwSize) == S_ERR_NO);
HeapFree(hHeap,0,lpData);
}
GlobalUnlock(hClipObj);
}
}
CloseClipboard();
}
SwitchToState(SM_RUN); // run state
while (nState!=nNextState) Sleep(0);
_ASSERT(nState == SM_RUN);
if (bSuccess == FALSE) // data not copied
goto cancel;
KeyboardEvent(TRUE,0,0x8000);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
return 0;
}
//
// ID_VIEW_COPY
//
@ -1127,7 +1084,7 @@ static LRESULT OnObjectLoad(VOID)
_T("Warning: Trying to load an object while the emulator is busy\n")
_T("will certainly result in a memory lost. Before loading an object\n")
_T("you should be sure that the calculator is not doing anything.\n")
_T("Do you want to see this warning next time you try to load an object ?"));
_T("Do you want to see this warning next time you try to load an object ?"),0);
switch (uReply)
{
case IDYES:
@ -1452,6 +1409,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
MSG msg;
WNDCLASS wc;
RECT rectWindow;
HACCEL hAccel;
HSZ hszService, hszTopic; // variables for DDE server
DWORD dwAffMask;
@ -1514,6 +1472,8 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC
return FALSE;
}
VERIFY(hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_MENU)));
// initialization
QueryPerformanceFrequency(&lFreq); // init high resolution counter
QueryPerformanceCounter(&lAppStart);
@ -1607,7 +1567,8 @@ start:
while (GetMessage(&msg, NULL, 0, 0))
{
if( (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg))
if( !TranslateAccelerator(hWnd, hAccel, &msg)
&& (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg))
&& (hDlgFind == NULL || !IsDialogMessage(hDlgFind, &msg))
&& (hDlgProfile == NULL || !IsDialogMessage(hDlgProfile, &msg)))
{

View file

@ -7,21 +7,21 @@
CFG=Emu48 - Win32 Release
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
!MESSAGE
!MESSAGE NMAKE /f "Emu48.mak".
!MESSAGE
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
!MESSAGE
!MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Release"
!MESSAGE
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
!MESSAGE
!MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Release Unicode" (based on "Win32 (x86) Application")
!MESSAGE "Emu48 - Win32 Debug Unicode" (based on "Win32 (x86) Application")
!MESSAGE
!MESSAGE
# Begin Project
# PROP AllowPerConfigDependencies 0
@ -137,7 +137,7 @@ LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386
# ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386
!ENDIF
!ENDIF
# Begin Target
@ -235,6 +235,10 @@ SOURCE=.\settings.c
# End Source File
# Begin Source File
SOURCE=.\stack.c
# End Source File
# Begin Source File
SOURCE=.\timer.c
# End Source File
# End Group

View file

@ -93,6 +93,7 @@ extern HCURSOR hCursorHand;
extern BOOL bClassicCursor;
extern BOOL bAutoSave;
extern BOOL bAutoSaveOnExit;
extern BOOL bSaveDefConfirm;
extern BOOL bAlwaysDisplayLog;
extern BOOL bLoadObjectWarning;
extern HANDLE hThread;
@ -203,6 +204,7 @@ extern VOID UpdatePatches(BOOL bPatch);
extern BOOL PatchRom(LPCTSTR szFilename);
extern BOOL MapRom(LPCTSTR szFilename);
extern VOID UnmapRom(VOID);
extern WORD CrcPort2(VOID);
extern BOOL MapPort2(LPCTSTR szFilename);
extern VOID UnmapPort2(VOID);
extern VOID ResetDocument(VOID);
@ -268,7 +270,12 @@ extern LRESULT OnToolMacroPlay(VOID);
extern LRESULT OnToolMacroStop(VOID);
extern LRESULT OnToolMacroSettings(VOID);
// Stack.c
extern LRESULT OnStackCopy(VOID);
extern LRESULT OnStackPaste(VOID);
// RPL.c
extern BOOL RPL_GetSystemFlag(INT nFlag);
extern DWORD RPL_SkipOb(DWORD d);
extern DWORD RPL_ObjectSize(BYTE *o);
extern DWORD RPL_CreateTemp(DWORD l);
@ -277,7 +284,9 @@ extern VOID RPL_Replace(DWORD n);
extern VOID RPL_Push(DWORD n);
// External.c
extern VOID External(CHIPSET* w);
extern BOOL bWaveBeep;
extern DWORD dwWaveVol;
extern VOID External(CHIPSET* w);
// DDEserv.c
extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD);
@ -310,7 +319,7 @@ extern BOOL DLLDestroyWnd(VOID);
static __inline int InfoMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND);}
static __inline int AbortMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);}
static __inline int YesNoMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNO|MB_ICONEXCLAMATION|MB_SETFOREGROUND);}
static __inline int YesNoCancelMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND);}
static __inline int YesNoCancelMessage(LPCTSTR szMessage,UINT uStyle) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND|uStyle);}
// Missing Win32 API calls
static __inline LPTSTR DuplicateString(LPCTSTR szString)

View file

@ -74,7 +74,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 160
TOPMARGIN, 4
BOTTOMMARGIN, 222
BOTTOMMARGIN, 256
END
IDD_CHOOSEKML, DIALOG
@ -232,15 +232,15 @@ BEGIN
ES_READONLY
END
IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 229
IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 263
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Settings"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,13,100,10
CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10
CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10
CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,37,89,10
CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT,
@ -255,25 +255,35 @@ BEGIN
CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button",
BS_AUTORADIOBUTTON,84,101,70,11
GROUPBOX "Disassembler",IDC_STATIC,7,90,153,28
LTEXT "Volume",IDC_STATIC,13,134,24,8
CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32",
TBS_AUTOTICKS | WS_TABSTOP,39,129,68,18
CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON |
WS_GROUP | WS_TABSTOP,111,128,43,10
CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,111,
139,43,10
GROUPBOX "Sound",IDC_STATIC,7,120,153,34
CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,13,131,67,10
WS_TABSTOP,13,165,67,10
CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,84,131,69,10
BS_AUTOCHECKBOX | WS_TABSTOP,84,165,69,10
CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,143,65,10
LTEXT "Port 2 File :",IDC_STATIC,13,159,37,8
EDITTEXT IDC_PORT2,51,156,94,12,ES_AUTOHSCROLL
PUSHBUTTON "...",IDC_PORT2LOAD,145,156,10,12
GROUPBOX "Memory Cards",IDC_STATIC,7,122,153,51
LTEXT "Wire:",IDC_STATIC,13,188,17,8
COMBOBOX IDC_WIRE,31,186,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
BS_AUTOCHECKBOX | WS_TABSTOP,13,177,65,10
CONTROL "Port 2 is Writeable",IDC_PORT2WR,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,84,177,69,10
LTEXT "Port 2 File :",IDC_STATIC,13,192,37,8
EDITTEXT IDC_PORT2,51,190,94,12,ES_AUTOHSCROLL
PUSHBUTTON "...",IDC_PORT2LOAD,145,190,10,12
GROUPBOX "Memory Cards",IDC_STATIC,7,156,153,51
LTEXT "Wire:",IDC_STATIC,13,221,17,8
COMBOBOX IDC_WIRE,31,219,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
LTEXT "IR:",IDC_STATIC,89,188,9,8
COMBOBOX IDC_IR,107,186,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
LTEXT "IR:",IDC_STATIC,89,221,9,8
COMBOBOX IDC_IR,107,219,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
GROUPBOX "Serial Ports",IDC_STATIC,7,176,153,27
DEFPUSHBUTTON "&Ok",IDOK,9,208,50,14
PUSHBUTTON "&Cancel",IDCANCEL,107,208,50,14
GROUPBOX "Serial Ports",IDC_STATIC,7,209,153,27
DEFPUSHBUTTON "&Ok",IDOK,9,242,50,14
PUSHBUTTON "&Cancel",IDCANCEL,107,242,50,14
END
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66
@ -492,7 +502,7 @@ BEGIN
LTEXT "Fast",IDC_MACRO_FAST,78,16,14,8,WS_DISABLED
CONTROL "Slider1",IDC_MACRO_SLIDER,"msctls_trackbar32",
TBS_AUTOTICKS | WS_DISABLED | WS_TABSTOP,12,26,82,21
CONTROL "&Real",IDC_MACRO_REAL,"Button",BS_AUTORADIOBUTTON |
CONTROL "&Real",IDC_MACRO_REAL,"Button",BS_AUTORADIOBUTTON |
WS_GROUP | WS_TABSTOP,103,18,39,10
CONTROL "&Manual",IDC_MACRO_MANUAL,"Button",BS_AUTORADIOBUTTON,
103,32,39,10
@ -538,8 +548,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,8,0
PRODUCTVERSION 1,3,8,0
FILEVERSION 1,4,0,0
PRODUCTVERSION 1,4,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -556,12 +566,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0"
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
VALUE "FileVersion", "1, 3, 8, 0\0"
VALUE "FileVersion", "1, 4, 0, 0\0"
VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 2005\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 3, 8, 0\0"
VALUE "ProductVersion", "1, 4, 0, 0\0"
END
END
BLOCK "VarFileInfo"
@ -607,8 +617,8 @@ BEGIN
MENUITEM "&Save Object...", ID_OBJECT_SAVE
MENUITEM SEPARATOR
MENUITEM "C&opy Screen", ID_VIEW_COPY
MENUITEM "&Copy String", ID_STACK_COPY
MENUITEM "&Paste String", ID_STACK_PASTE
MENUITEM "&Copy Stack", ID_STACK_COPY
MENUITEM "&Paste Stack", ID_STACK_PASTE
MENUITEM SEPARATOR
MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED
POPUP "&Backup"
@ -755,6 +765,25 @@ END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// 24
//
CREATEPROCESS_MANIFEST_RESOURCE_ID 24 MOVEABLE PURE "Emu48.xml"
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_MENU ACCELERATORS DISCARDABLE
BEGIN
"C", ID_STACK_COPY, VIRTKEY, CONTROL, NOINVERT
"V", ID_STACK_PASTE, VIRTKEY, CONTROL, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table
@ -773,14 +802,6 @@ BEGIN
ID_BREAKPOINTS_CODEEDIT "Breakpoint List"
END
/////////////////////////////////////////////////////////////////////////////
//
// Manifest
//
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "Emu48.xml"
#endif // English (U.S.) resources
/////////////////////////////////////////////////////////////////////////////

View file

@ -549,6 +549,7 @@ loop:
IOBit(SRQ2,NINT,bNINT);
}
RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping
UpdateContrast(Chipset.contrast);
UpdateDisplayPointers();
UpdateMainDisplay();
UpdateMenuDisplay();

View file

@ -4,12 +4,15 @@
* This file is part of Emu48
*
* Copyright (C) 1995 Sebastien Carlier
* Copyright (C) 2005 Christoph Gießelink
*
*/
#include "pch.h"
#include "Emu48.h"
#include "ops.h"
#define MUSIC_FREQ 11025 // this can be adjusted for quality
//| 38G | 39G | 40G | 48SX | 48GX | 49G | Name
//#F0E4F #80F0F #80F0F #706D2 #80850 #80F0F =SFLAG53_56
@ -28,6 +31,102 @@
) \
)
BOOL bWaveBeep = FALSE; // PC speaker
DWORD dwWaveVol = 64; // wave sound volume
static __inline VOID BeepWave(DWORD dwFrequency,DWORD dwDuration)
{
HWAVEOUT hSoundDevice;
WAVEFORMATEX wf;
WAVEHDR wh;
HANDLE hEventSound;
DWORD i;
if (dwFrequency == 0) // this is just a delay
{
Sleep(dwDuration);
return;
}
hEventSound = CreateEvent(NULL,FALSE,FALSE,NULL);
wf.wFormatTag = WAVE_FORMAT_PCM;
wf.nChannels = 1;
wf.nSamplesPerSec = MUSIC_FREQ;
wf.nAvgBytesPerSec = MUSIC_FREQ;
wf.nBlockAlign = 1;
wf.wBitsPerSample = 8;
wf.cbSize = 0;
if (waveOutOpen(&hSoundDevice,WAVE_MAPPER,&wf,(DWORD)hEventSound,0,CALLBACK_EVENT) != 0)
{
CloseHandle(hEventSound); // no sound available
return;
}
// (samp/sec) * msecs * (secs/msec) = samps
wh.dwBufferLength = (DWORD) ((QWORD) MUSIC_FREQ * dwDuration / 1000);
VERIFY(wh.lpData = HeapAlloc(hHeap,0,wh.dwBufferLength));
wh.dwBytesRecorded = 0;
wh.dwUser = 0;
wh.dwFlags = 0;
wh.dwLoops = 0;
for (i = 0; i < wh.dwBufferLength; ++i) // generate square wave
{
wh.lpData[i] = (BYTE) ((((QWORD) 2 * dwFrequency * i / MUSIC_FREQ) & 1) * dwWaveVol);
}
VERIFY(waveOutPrepareHeader(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR);
ResetEvent(hEventSound); // prepare event for finishing
VERIFY(waveOutWrite(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR);
WaitForSingleObject(hEventSound,INFINITE); // wait for finishing
VERIFY(waveOutUnprepareHeader(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR);
VERIFY(waveOutClose(hSoundDevice) == MMSYSERR_NOERROR);
HeapFree(hHeap,0,wh.lpData);
CloseHandle(hEventSound);
return;
}
static __inline VOID BeepWin9x(DWORD dwFrequency,DWORD dwDuration)
{
#define PIT8254_CNT2 0x42
#define PIT8254_MCR 0x43
#define PPI8255_PBO 0x61
BYTE bySpk = _inp(PPI8255_PBO); // get current status
if (dwFrequency != 0)
{
WORD wCount;
// limit low frequency
if (lFreq.QuadPart / 65535 >= dwFrequency)
dwFrequency = (DWORD) (lFreq.QuadPart / 65535) + 1;
// determine the timer frequency
wCount = (WORD) (lFreq.QuadPart / dwFrequency);
_outp(PIT8254_MCR,0xB6); // set up the timer
_outp(PIT8254_CNT2,wCount&0xff);
_outp(PIT8254_CNT2,wCount>>8);
_outp(PPI8255_PBO,bySpk | 0x03); // turn on the speaker
}
Sleep(dwDuration);
_outp(PPI8255_PBO,bySpk & 0xFC); // turn off the speaker
return;
#undef PIT8254_CNT2
#undef PIT8254_MCR
#undef PPI8255_PBO
}
static __inline VOID Return(CHIPSET* w)
{
w->rstkp=(w->rstkp-1)&7;
@ -48,13 +147,30 @@ VOID External(CHIPSET* w) // Beep patch
w->carry = TRUE; // setting of no beep
if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz
{
if (freq < 37) freq = 37; // low limit of freqency (NT)
if (freq > 4400) freq = 4400; // high limit of HP (SX)
if (dur > 1048575) // high limit of HP (SX)
dur = 1048575;
if (bWaveBeep)
{
BeepWave(freq,dur); // wave output over sound card
}
else
{
OSVERSIONINFO version;
version.dwOSVersionInfoSize = sizeof(version);
GetVersionEx(&version);
Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep
if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS)
{
BeepWin9x(freq,dur); // do it the hard way on '9x / Me
}
else // VER_PLATFORM_WIN32_NT
{
if (freq < 37) freq = 37; // low limit of freqency (NT)
_ASSERT(freq >= 0x25 && freq <= 0x7FFF);
Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep
}
}
// estimate cpu cycles for beeping time (2MHz / 4MHz)
w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000);

View file

@ -422,7 +422,7 @@ VOID UnmapRom(VOID)
//#
//################
static WORD CrcPort2(VOID) // calculate fingerprint of port2
WORD CrcPort2(VOID) // calculate fingerprint of port2
{
DWORD dwCount;
DWORD dwFileSize;

View file

@ -83,6 +83,7 @@ static KmlToken pLexToken[] =
{TOK_IFFLAG, 000001, 6,_T("IfFlag")},
{TOK_ONDOWN, 000000, 6,_T("OnDown")},
{TOK_NOHOLD, 000000, 6,_T("NoHold")},
{TOK_TOPBAR, 000001, 6,_T("Topbar")}, // for PPC compatibility reasons
{TOK_TITLE, 000002, 5,_T("Title")},
{TOK_OUTIN, 000011, 5,_T("OutIn")},
{TOK_PATCH, 000002, 5,_T("Patch")},
@ -100,6 +101,7 @@ static KmlToken pLexToken[] =
{TOK_ONUP, 000000, 4,_T("OnUp")},
{TOK_MAP, 000011, 3,_T("Map")},
{TOK_ROM, 000002, 3,_T("Rom")},
{TOK_VGA, 000001, 3,_T("Vga")}, // for PPC compatibility reasons
{TOK_LCD, 000000, 3,_T("Lcd")},
{TOK_END, 000000, 3,_T("End")},
{0, 000000, 0,_T("")},
@ -574,7 +576,7 @@ loop:
}
if (*szText==_T('#'))
{
do szText++; while (*szText != _T('\n'));
do szText++; while (*szText != _T('\n') && *szText != 0);
if (nMode != LEX_PARAM) goto loop;
}
return;
@ -1024,6 +1026,11 @@ static KmlBlock* ParseBlocks(VOID)
}
}
if (pFirst) pBlock->pNext = NULL;
if (*szText != 0) // still KML text left
{
FatalError(); // error unknown block token
goto abort;
}
return pFirst;
abort:
if (pFirst) FreeBlocks(pFirst);
@ -1288,8 +1295,9 @@ static KmlLine* SkipLines(KmlLine* pLine, TokenId eCommand)
while (pLine)
{
if (IsBlock(pLine->eCommand)) nLevel++;
if (pLine->eCommand==eCommand)
if (pLine->eCommand == eCommand)
{
// found token, return command behind token
if (nLevel == 0) return pLine->pNext;
}
if (pLine->eCommand == TOK_END)
@ -1297,7 +1305,7 @@ static KmlLine* SkipLines(KmlLine* pLine, TokenId eCommand)
if (nLevel)
nLevel--;
else
return NULL;
break;
}
pLine = pLine->pNext;
}
@ -1467,6 +1475,7 @@ VOID KillKML(VOID)
nBackgroundW = 256;
nBackgroundH = 0;
nLcdZoom = 1;
cCurrentRomType = 0;
UpdateWindowStatus();
ResizeWindow();
return;
@ -2156,7 +2165,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
if (cCurrentRomType == 0)
{
AddToLog(_T("This KML Script doesn't specify the ROM Type."));
AddToLog(_T("This KML Script doesn't specify the model."));
goto quit;
}
if (pbyRom == NULL)
@ -2164,6 +2173,12 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
AddToLog(_T("This KML Script doesn't specify the ROM to use, or the ROM could not be loaded."));
goto quit;
}
if (hMainDC == NULL)
{
AddToLog(_T("This KML Script doesn't specify the background bitmap, or bitmap could not be loaded."));
goto quit;
}
CreateLcdBitmap();
PrintfToLog(_T("%i Buttons Defined"), nButtons);

View file

@ -35,27 +35,29 @@ typedef enum eTokenId
TOK_IFFLAG, //19
TOK_ONDOWN, //20
TOK_NOHOLD, //21
TOK_TITLE, //22
TOK_OUTIN, //23
TOK_PATCH, //24
TOK_PRINT, //25
TOK_DEBUG, //26
TOK_COLOR, //27
TOK_MODEL, //28
TOK_CLASS, //29
TOK_PRESS, //30
TOK_TYPE, //31
TOK_SIZE, //32
TOK_DOWN, //33
TOK_ZOOM, //34
TOK_ELSE, //35
TOK_ONUP, //36
TOK_EOL, //37
TOK_MAP, //38
TOK_ROM, //39
TOK_LCD, //40
TOK_NOTFLAG, //41
TOK_END //42
TOK_TOPBAR, //22
TOK_TITLE, //23
TOK_OUTIN, //24
TOK_PATCH, //25
TOK_PRINT, //26
TOK_DEBUG, //27
TOK_COLOR, //28
TOK_MODEL, //29
TOK_CLASS, //30
TOK_PRESS, //31
TOK_TYPE, //32
TOK_SIZE, //33
TOK_DOWN, //34
TOK_ZOOM, //35
TOK_ELSE, //36
TOK_ONUP, //37
TOK_EOL, //38
TOK_MAP, //39
TOK_ROM, //40
TOK_VGA, //41
TOK_LCD, //42
TOK_NOTFLAG, //43
TOK_END //44
} TokenId;
#define TYPE_NONE 00

View file

@ -13,6 +13,7 @@
#include <ctype.h>
#include <stdio.h>
#include <direct.h>
#include <conio.h>
#include <crtdbg.h>
#if !defined VERIFY

View file

@ -36,116 +36,120 @@
#define IDC_PORT1EN 1006
#define IDC_PORT1WR 1007
#define IDC_PORT2ISSHARED 1008
#define IDC_PORT2 1009
#define IDC_PORT2LOAD 1010
#define IDC_WIRE 1011
#define IDC_IR 1012
#define IDC_EMUDIR 1013
#define IDC_EMUDIRSEL 1014
#define IDC_UPDATE 1015
#define IDC_KMLSCRIPT 1016
#define IDC_AUTHOR 1017
#define IDC_TITLE 1018
#define IDC_KMLLOG 1019
#define IDC_VERSION 1020
#define IDC_LICENSE 1021
#define IDC_DISASM_WIN 1022
#define IDC_DISASM_MAP 1023
#define IDC_DISASM_ROM 1024
#define IDC_DISASM_RAM 1025
#define IDC_DISASM_PORT1 1026
#define IDC_DISASM_PORT2 1027
#define IDC_DISASM_MODULE 1028
#define IDC_DISASM_HP 1029
#define IDC_DISASM_CLASS 1030
#define IDC_ADDRESS 1031
#define IDC_DISASM_ADR 1032
#define IDC_DISASM_NEXT 1033
#define IDC_DISASM_COPY 1034
#define IDC_DEBUG_CODE 1035
#define IDC_STATIC_CODE 1036
#define IDC_STATIC_REGISTERS 1037
#define IDC_STATIC_MEMORY 1038
#define IDC_STATIC_STACK 1039
#define IDC_REG_A 1040
#define IDC_REG_B 1041
#define IDC_REG_C 1042
#define IDC_REG_D 1043
#define IDC_REG_R0 1044
#define IDC_REG_R1 1045
#define IDC_REG_R2 1046
#define IDC_REG_R3 1047
#define IDC_REG_R4 1048
#define IDC_REG_D0 1049
#define IDC_REG_D1 1050
#define IDC_REG_P 1051
#define IDC_REG_PC 1052
#define IDC_REG_OUT 1053
#define IDC_REG_IN 1054
#define IDC_REG_ST 1055
#define IDC_REG_CY 1056
#define IDC_REG_MODE 1057
#define IDC_REG_MP 1058
#define IDC_REG_SR 1059
#define IDC_REG_SB 1060
#define IDC_REG_XM 1061
#define IDC_MISC_INT 1062
#define IDC_MISC_KEY 1063
#define IDC_MISC_BS 1064
#define IDC_NEWVALUE 1065
#define IDC_ENTERADR 1066
#define IDC_DEBUG_MEM 1067
#define IDC_DEBUG_MEM_ADDR 1068
#define IDC_DEBUG_MEM_COL0 1069
#define IDC_DEBUG_MEM_COL1 1070
#define IDC_DEBUG_MEM_COL2 1071
#define IDC_DEBUG_MEM_COL3 1072
#define IDC_DEBUG_MEM_COL4 1073
#define IDC_DEBUG_MEM_COL5 1074
#define IDC_DEBUG_MEM_COL6 1075
#define IDC_DEBUG_MEM_COL7 1076
#define IDC_DEBUG_MEM_TEXT 1077
#define IDC_DEBUG_STACK 1078
#define IDC_STATIC_BREAKPOINT 1079
#define IDC_BREAKEDIT_ADD 1080
#define IDC_BREAKEDIT_DELETE 1081
#define IDC_BREAKEDIT_WND 1082
#define IDC_STATIC_MMU 1083
#define IDC_MMU_IO_A 1084
#define IDC_MMU_NCE2_A 1085
#define IDC_MMU_CE1_A 1086
#define IDC_MMU_CE2_A 1087
#define IDC_MMU_NCE3_A 1088
#define IDC_MMU_IO_S 1089
#define IDC_MMU_CE1_S 1090
#define IDC_MMU_CE2_S 1091
#define IDC_MMU_NCE2_S 1092
#define IDC_MMU_NCE3_S 1093
#define IDC_STATIC_MISC 1094
#define IDC_MISC_BS_TXT 1095
#define IDC_INSTR_TEXT 1096
#define IDC_INSTR_CODE 1097
#define IDC_INSTR_COPY 1098
#define IDC_INSTR_CLEAR 1099
#define IDC_PROFILE_LASTCYCLES 1100
#define IDC_PROFILE_LASTTIME 1101
#define IDC_BPCODE 1102
#define IDC_BPRPL 1103
#define IDC_BPACCESS 1104
#define IDC_BPREAD 1105
#define IDC_BPWRITE 1106
#define IDC_FIND_DATA 1107
#define IDC_FIND_ASCII 1108
#define IDC_FIND_CASE 1109
#define IDC_ADDR20_24 1110
#define IDC_ADDR25_27 1111
#define IDC_ADDR28_29 1112
#define IDC_ADDR30_34 1113
#define IDC_MACRO_SLOW 1114
#define IDC_MACRO_FAST 1115
#define IDC_MACRO_SLIDER 1116
#define IDC_MACRO_REAL 1117
#define IDC_MACRO_MANUAL 1118
#define IDC_PORT2WR 1009
#define IDC_PORT2 1010
#define IDC_PORT2LOAD 1011
#define IDC_WIRE 1012
#define IDC_IR 1013
#define IDC_EMUDIR 1014
#define IDC_EMUDIRSEL 1015
#define IDC_UPDATE 1016
#define IDC_KMLSCRIPT 1017
#define IDC_AUTHOR 1018
#define IDC_TITLE 1019
#define IDC_KMLLOG 1020
#define IDC_VERSION 1021
#define IDC_LICENSE 1022
#define IDC_DISASM_WIN 1023
#define IDC_DISASM_MAP 1024
#define IDC_DISASM_ROM 1025
#define IDC_DISASM_RAM 1026
#define IDC_DISASM_PORT1 1027
#define IDC_DISASM_PORT2 1028
#define IDC_DISASM_MODULE 1029
#define IDC_DISASM_HP 1030
#define IDC_DISASM_CLASS 1031
#define IDC_ADDRESS 1032
#define IDC_DISASM_ADR 1033
#define IDC_DISASM_NEXT 1034
#define IDC_DISASM_COPY 1035
#define IDC_DEBUG_CODE 1036
#define IDC_STATIC_CODE 1037
#define IDC_STATIC_REGISTERS 1038
#define IDC_STATIC_MEMORY 1039
#define IDC_STATIC_STACK 1040
#define IDC_REG_A 1041
#define IDC_REG_B 1042
#define IDC_REG_C 1043
#define IDC_REG_D 1044
#define IDC_REG_R0 1045
#define IDC_REG_R1 1046
#define IDC_REG_R2 1047
#define IDC_REG_R3 1048
#define IDC_REG_R4 1049
#define IDC_REG_D0 1050
#define IDC_REG_D1 1051
#define IDC_REG_P 1052
#define IDC_REG_PC 1053
#define IDC_REG_OUT 1054
#define IDC_REG_IN 1055
#define IDC_REG_ST 1056
#define IDC_REG_CY 1057
#define IDC_REG_MODE 1058
#define IDC_REG_MP 1059
#define IDC_REG_SR 1060
#define IDC_REG_SB 1061
#define IDC_REG_XM 1062
#define IDC_MISC_INT 1063
#define IDC_MISC_KEY 1064
#define IDC_MISC_BS 1065
#define IDC_NEWVALUE 1066
#define IDC_ENTERADR 1067
#define IDC_DEBUG_MEM 1068
#define IDC_DEBUG_MEM_ADDR 1069
#define IDC_DEBUG_MEM_COL0 1070
#define IDC_DEBUG_MEM_COL1 1071
#define IDC_DEBUG_MEM_COL2 1072
#define IDC_DEBUG_MEM_COL3 1073
#define IDC_DEBUG_MEM_COL4 1074
#define IDC_DEBUG_MEM_COL5 1075
#define IDC_DEBUG_MEM_COL6 1076
#define IDC_DEBUG_MEM_COL7 1077
#define IDC_DEBUG_MEM_TEXT 1078
#define IDC_DEBUG_STACK 1079
#define IDC_STATIC_BREAKPOINT 1080
#define IDC_BREAKEDIT_ADD 1081
#define IDC_BREAKEDIT_DELETE 1082
#define IDC_BREAKEDIT_WND 1083
#define IDC_STATIC_MMU 1084
#define IDC_MMU_IO_A 1085
#define IDC_MMU_NCE2_A 1086
#define IDC_MMU_CE1_A 1087
#define IDC_MMU_CE2_A 1088
#define IDC_MMU_NCE3_A 1089
#define IDC_MMU_IO_S 1090
#define IDC_MMU_CE1_S 1091
#define IDC_MMU_CE2_S 1092
#define IDC_MMU_NCE2_S 1093
#define IDC_MMU_NCE3_S 1094
#define IDC_STATIC_MISC 1095
#define IDC_MISC_BS_TXT 1096
#define IDC_INSTR_TEXT 1097
#define IDC_INSTR_CODE 1098
#define IDC_INSTR_COPY 1099
#define IDC_INSTR_CLEAR 1100
#define IDC_PROFILE_LASTCYCLES 1101
#define IDC_PROFILE_LASTTIME 1102
#define IDC_BPCODE 1103
#define IDC_BPRPL 1104
#define IDC_BPACCESS 1105
#define IDC_BPREAD 1106
#define IDC_BPWRITE 1107
#define IDC_FIND_DATA 1108
#define IDC_FIND_ASCII 1109
#define IDC_FIND_CASE 1110
#define IDC_ADDR20_24 1111
#define IDC_ADDR25_27 1112
#define IDC_ADDR28_29 1113
#define IDC_ADDR30_34 1114
#define IDC_MACRO_SLOW 1115
#define IDC_MACRO_FAST 1116
#define IDC_MACRO_SLIDER 1117
#define IDC_MACRO_REAL 1118
#define IDC_MACRO_MANUAL 1119
#define IDC_SOUND_SLIDER 1120
#define IDC_SOUND_SPEAKER 1121
#define IDC_SOUND_WAVE 1122
#define ID_FILE_NEW 40001
#define ID_FILE_OPEN 40002
#define ID_FILE_SAVE 40003
@ -212,7 +216,7 @@
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 123
#define _APS_NEXT_COMMAND_VALUE 40062
#define _APS_NEXT_CONTROL_VALUE 1119
#define _APS_NEXT_CONTROL_VALUE 1122
#define _APS_NEXT_SYMED_VALUE 108
#endif
#endif

View file

@ -18,13 +18,15 @@
//#F0697 #806F8 #806F8 #70579 #806F8 #806F8 =DSKTOP (D1)
//#F0DEA #80E9B #80E9B #7066E #807ED #80E9B =AVMEM (D)
//#F0705 #8076B #8076B #705B0 #8072F #8076B =INTRPPTR (D0)
// #80F02 #80F02 #706C5 #80843 #80F02 =SystemFlags
#define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9)
#define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE)
#define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3)
#define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8)
#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B)
#define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9)
#define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE)
#define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3)
#define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8)
#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B)
#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B)
#define SYSTEMFLAGS ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x706C5:0x80843):0x80F02)
#define DOINT 0x02614 // Precision Integer (HP49G)
#define DOLNGREAL 0x0263A // Precision Real (HP49G)
@ -93,6 +95,21 @@ static BOOL Metakernel(VOID)
return bMkDetect;
}
BOOL RPL_GetSystemFlag(INT nFlag)
{
DWORD dwAddr;
BYTE byMask,byFlag;
_ASSERT(nFlag > 0); // first flag is 1
// calculate memory address and bit mask
dwAddr = SYSTEMFLAGS + (nFlag - 1) / 4;
byMask = 1 << ((nFlag - 1) & 0x3);
Npeek(&byFlag,dwAddr,sizeof(byFlag));
return (byFlag & byMask) != 0;
}
DWORD RPL_SkipOb(DWORD d)
{
BYTE X[8];

View file

@ -141,6 +141,7 @@ VOID ReadSettings(VOID)
ReadString(_T("Files"),_T("Emu48Directory"),szCurrentDirectory,szEmuDirectory,ARRAYSIZEOF(szEmuDirectory));
bAutoSave = ReadInt(_T("Files"),_T("AutoSave"),bAutoSave);
bAutoSaveOnExit = ReadInt(_T("Files"),_T("AutoSaveOnExit"),bAutoSaveOnExit);
bSaveDefConfirm = ReadInt(_T("Files"),_T("SaveDefaultConfirm"),bSaveDefConfirm);
bLoadObjectWarning = ReadInt(_T("Files"),_T("LoadObjectWarning"),bLoadObjectWarning);
// Port2
bPort2IsShared = ReadInt(_T("Port2"),_T("IsShared"),bPort2IsShared);
@ -152,9 +153,11 @@ VOID ReadSettings(VOID)
disassembler_mode = ReadInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode);
// Emulator
bRealSpeed = ReadInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed);
bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
dwSXCycles = ReadInt(_T("Emulator"),_T("SXCycles"),dwSXCycles);
dwGXCycles = ReadInt(_T("Emulator"),_T("GXCycles"),dwGXCycles);
bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
bWaveBeep = ReadInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep);
dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
SetSpeed(bRealSpeed); // set speed
// Macro
bMacroRealSpeed = ReadInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed);
@ -174,6 +177,7 @@ VOID WriteSettings(VOID)
WriteString(_T("Files"),_T("Emu48Directory"),szEmuDirectory);
WriteInt(_T("Files"),_T("AutoSave"),bAutoSave);
WriteInt(_T("Files"),_T("AutoSaveOnExit"),bAutoSaveOnExit);
WriteInt(_T("Files"),_T("SaveDefaultConfirm"),bSaveDefConfirm);
WriteInt(_T("Files"),_T("LoadObjectWarning"),bLoadObjectWarning);
// Port2
WriteInt(_T("Port2"),_T("IsShared"),bPort2IsShared);
@ -185,9 +189,11 @@ VOID WriteSettings(VOID)
WriteInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode);
// Emulator
WriteInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed);
WriteInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
WriteInt(_T("Emulator"),_T("SXCycles"),dwSXCycles);
WriteInt(_T("Emulator"),_T("GXCycles"),dwGXCycles);
WriteInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
WriteInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep);
WriteInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
// Macro
WriteInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed);
WriteInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout);

646
Sources/Emu48/STACK.C Normal file
View file

@ -0,0 +1,646 @@
/*
* stack.c
*
* This file is part of Emu48
*
* Copyright (C) 2005 Christoph Gießelink
*
*/
#include "pch.h"
#include "resource.h"
#include "Emu48.h"
#include "io.h"
#define fnRadix 51 // fraction mark
#define fnApprox 105 // exact / approx. mode (HP49G)
#define DOINT 0x02614 // Precision Integer (HP49G)
#define DOREAL 0x02933 // Real
#define DOCSTR 0x02A2C // String
//################
//#
//# Low level subroutines
//#
//################
static INT RPL_GetZInt(BYTE CONST *pbyNum,INT nIntLen,LPTSTR cp,INT nSize)
{
INT i = 0; // character counter
_ASSERT(nSize > 0); // target buffer size
if (nIntLen > 1) // has sign nibble
{
--nIntLen; // remove sign from digit length
// check for valid sign
_ASSERT(pbyNum[nIntLen] == 0 || pbyNum[nIntLen] == 9);
if (pbyNum[nIntLen] == 9) // negative number
{
*cp++ = _T('-'); // add sign
--nSize; // dec dest buffer size
++i; // wrote one character
}
}
if (nIntLen >= nSize) return 0; // dest buffer overflow
i += nIntLen; // adjust character counter
while (nIntLen-- > 0) // write all digits
{
// check for valid digit
_ASSERT(pbyNum[nIntLen] >= 0 && pbyNum[nIntLen] <= 9);
*cp++ = _T('0') + pbyNum[nIntLen]; // and write
}
*cp = 0; // set EOS
return i;
}
static INT RPL_SetZInt(LPCTSTR cp,LPBYTE pbyNum,INT nSize)
{
BYTE bySign;
INT nStrLen,nNumSize;
_ASSERT(nSize > 0); // target buffer size
nStrLen = lstrlen(cp); // source string length
if ( nStrLen == 0 // empty string
// precisition integer contain only these numbers
|| _tcsspn(cp,_T("0123456789+-")) != (SIZE_T) nStrLen)
return 0;
bySign = (*cp != _T('-')) ? 0 : 9; // set sign nibble
if (*cp == _T('-') || *cp == _T('+')) // skip sign character
{
++cp;
--nStrLen;
}
if (nStrLen == 1 && *cp == _T('0')) // special code for zero
{
*pbyNum = 0; // zero data
return 1; // finish
}
// nStrLen = no. of digits without sign
if (nStrLen >= nSize) // destination buffer too small
return 0;
nNumSize = nStrLen + 1; // no. of written data
while (--nStrLen >= 0) // eval all digits
{
TCHAR c = cp[nStrLen];
// only '0' .. '9' are valid here
if (!((c >= _T('0')) || (c <= _T('9'))))
return 0;
c -= _T('0');
*pbyNum++ = (BYTE) c;
}
*pbyNum = bySign; // add sign
return nNumSize;
}
static INT RPL_GetBcd(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPTSTR cp,INT nSize)
{
BYTE byNib;
LONG v,lExp;
BOOL bPflag,bExpflag;
INT i;
lExp = 0;
for (v = 1; nExpLen--; v *= 10) // fetch exponent
{
lExp += (LONG) *pbyNum++ * v; // calc. exponent
}
if (lExp > v / 2) lExp -= v; // negative exponent
lExp -= nMantLen - 1; // set decimal point to end of mantissa
i = 0; // first character
bPflag = FALSE; // show no decimal point
// scan mantissa
for (v = (LONG) nMantLen - 1; v >= 0 || bPflag; v--)
{
if (v >= 0L) // still mantissa digits left
byNib = *pbyNum++;
else
byNib = 0; // zero for negativ exponent
if (!i) // still delete zeros at end
{
if (byNib == 0 && lExp && v > 0) // delete zeros
{
lExp++; // adjust exponent
continue;
}
// TRUE at x.E
bExpflag = v + lExp > 14 || v + lExp < -nMantLen;
bPflag = !bExpflag && v < -lExp; // decimal point flag at neg. exponent
}
// set decimal point
if ((bExpflag && v == 0) || (!lExp && i))
{
if (i >= nSize) return 0; // dest buffer overflow
cp[i++] = cDec; // write decimal point
if (v < 0) // no mantissa digits any more
{
if (i >= nSize) return 0; // dest buffer overflow
cp[i++] = _T('0'); // write heading zero
}
bPflag = FALSE; // finished with negativ exponents
}
if (v >= 0 || bPflag)
{
if (i >= nSize) return 0; // dest buffer overflow
cp[i++] = (TCHAR) byNib + _T('0'); // write character
}
lExp++; // next position
}
if (*pbyNum == 9) // negative number
{
if (i >= nSize) return 0; // dest buffer overflow
cp[i++] = _T('-'); // write sign
}
if (i >= nSize) return 0; // dest buffer overflow
cp[i] = 0; // set EOS
for (v = 0; v < (i / 2); v++) // reverse string
{
TCHAR cNib = cp[v]; // swap chars
cp[v] = cp[i-v-1];
cp[i-v-1] = cNib;
}
// write number with exponent
if (bExpflag)
{
if (i + 5 >= nSize) return 0; // dest buffer overflow
i += wsprintf(&cp[i],_T("E%d"),lExp-1);
}
return i;
}
static INT RPL_SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize)
{
TCHAR cVc[] = _T(".0123456789eE+-");
BYTE byNum[80];
INT i,nIp,nDp,nMaxExp;
LONG lExp;
cVc[0] = cDec; // replace decimal char
if ( nMantLen + nExpLen >= nSize // destination buffer too small
|| !*cp // empty string
|| _tcsspn(cp,cVc) != (SIZE_T) lstrlen(cp) // real contain only these numbers
|| lstrlen(cp) >= ARRAYSIZEOF(byNum)) // ignore too long reals
return 0;
byNum[0] = (*cp != _T('-')) ? 0 : 9; // set sign nibble
if (*cp == _T('-') || *cp == _T('+')) // skip sign character
cp++;
// only '.', '0' .. '9' are valid here
if (!((*cp == cDec) || (*cp >= _T('0')) || (*cp <= _T('9'))))
return 0;
nIp = 0; // length of integer part
if (*cp != cDec) // no decimal point
{
// count integer part
while (*cp >= _T('0') && *cp <= _T('9'))
byNum[++nIp] = *cp++ - _T('0');
if (!nIp) return 0;
}
// only '.', 'E', 'e' or end are valid here
if (!(!*cp || (*cp == cDec) || (*cp == _T('E')) || (*cp == _T('e'))))
return 0;
nDp = 0; // length of decimal part
if (*cp == cDec) // decimal point
{
cp++; // skip '.'
// count decimal part
while (*cp >= _T('0') && *cp <= _T('9'))
byNum[nIp + ++nDp] = *cp++ - _T('0');
}
// count number of heading zeros in mantissa
for (i = 0; byNum[i+1] == 0 && i + 1 < nIp + nDp; ++i) { }
if (i > 0) // have to normalize
{
INT j;
nIp -= i; // for later ajust of exponent
for (j = 1; j <= nIp + nDp; ++j) // normalize mantissa
byNum[j] = byNum[j + i];
}
if(byNum[1] == 0) // number is 0
{
ZeroMemory(pbyNum,nMantLen + nExpLen + 1);
return nMantLen + nExpLen + 1;
}
for (i = nIp + nDp; i < nMantLen;) // fill rest of mantissa with 0
byNum[++i] = 0;
// must be 'E', 'e' or end
if (!(!*cp || (*cp == _T('E')) || (*cp == _T('e'))))
return 0;
lExp = 0;
if (*cp == _T('E') || *cp == _T('e'))
{
cp++; // skip 'E'
i = FALSE; // positive exponent
if (*cp == _T('-') || *cp == _T('+'))
{
i = (*cp++ == _T('-')); // adjust exponent sign
}
// exponent symbol must be followed by number
if (*cp < _T('0') || *cp > _T('9')) return 0;
while (*cp >= _T('0') && *cp <= _T('9'))
lExp = lExp * 10 + *cp++ - _T('0');
if(i) lExp = -lExp;
}
if (*cp != 0) return 0;
// adjust exponent value with exponent from normalized mantissa
lExp += nIp - 1;
// calculate max. posive exponent
for (nMaxExp = 5, i = 1; i < nExpLen; ++i)
nMaxExp *= 10;
// check range of exponent
if ((lExp < 0 && -lExp >= nMaxExp) || (lExp >= nMaxExp))
return 0;
if (lExp < 0) lExp += 2 * nMaxExp; // adjust negative offset
for (i = nExpLen; i > 0; --i) // convert number into digits
{
byNum[nMantLen + i] = lExp % 10;
lExp /= 10;
}
// copy to target in reversed order
for (i = nMantLen + nExpLen; i >= 0; --i)
*pbyNum++ = byNum[i];
return nMantLen + nExpLen + 1;
}
//################
//#
//# Object subroutines
//#
//################
#if 0
static INT IsRealNumber(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize)
{
LPTSTR lpszNumber;
INT nLength = 0;
if ((lpszNumber = DuplicateString(cp)) != NULL)
{
LPTSTR p = lpszNumber;
INT i;
// cut heading whitespaces
for (; *p == _T(' ') || *p == _T('\t'); ++p) { }
// cut tailing whitespaces
for (i = lstrlen(p); --i >= 0;)
{
if (p[i] != _T(' ') && p[i] != _T('\t'))
break;
}
p[++i] = 0; // new EOS
nLength = RPL_SetBcd(p,nMantLen,nExpLen,cDec,pbyNum,nSize);
HeapFree(hHeap,0,lpszNumber);
}
return nLength;
}
#endif
static TCHAR GetRadix(VOID)
{
// get locale decimal point
// GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,&cDecimal,1);
return RPL_GetSystemFlag(fnRadix) ? _T(',') : _T('.');
}
static INT DoInt(DWORD dwAddress,LPTSTR cp,INT nSize)
{
LPBYTE lpbyData;
INT nLength,nIntLen;
nIntLen = Read5(dwAddress) - 5; // no. of digits
if (nIntLen <= 0) return 0; // error in calculator object
nLength = 0;
if ((lpbyData = HeapAlloc(hHeap,0,nIntLen)))
{
// get precisition integer object content and decode it
Npeek(lpbyData,dwAddress+5,nIntLen);
nLength = RPL_GetZInt(lpbyData,nIntLen,cp,nSize);
HeapFree(hHeap,0,lpbyData);
}
return nLength;
}
static INT DoReal(DWORD dwAddress,LPTSTR cp,INT nSize)
{
BYTE byNumber[16];
// get real object content and decode it
Npeek(byNumber,dwAddress,ARRAYSIZEOF(byNumber));
return RPL_GetBcd(byNumber,12,3,GetRadix(),cp,nSize);
}
//################
//#
//# Stack routines
//#
//################
//
// ID_STACK_COPY
//
LRESULT OnStackCopy(VOID) // copy data from stack
{
TCHAR cBuffer[128];
HANDLE hClipObj;
LPBYTE lpbyData;
DWORD dwAddress,dwObject,dwSize;
UINT uClipboardFormat;
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
InfoMessage(_T("The emulator is busy."));
return 0;
}
_ASSERT(nState == SM_SLEEP);
if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object
{
MessageBeep(MB_OK); // error beep
goto error;
}
switch (dwObject = Read5(dwAddress)) // select object
{
case DOINT: // Precision Integer (HP49G)
case DOREAL: // real object
dwAddress += 5; // object content
switch (dwObject)
{
case DOINT: // Precision Integer (HP49G)
// get precision integer object content and decode it
dwSize = DoInt(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
break;
case DOREAL: // real object
// get real object content and decode it
dwSize = DoReal(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
break;
}
// calculate buffer size
dwSize = (dwSize + 1) * sizeof(*cBuffer);
// memory allocation for clipboard data
if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize)) == NULL)
goto error;
if ((lpbyData = GlobalLock(hClipObj)))
{
// copy data to memory
CopyMemory(lpbyData,cBuffer,dwSize);
GlobalUnlock(hClipObj); // unlock memory
}
#if defined _UNICODE
uClipboardFormat = CF_UNICODETEXT;
#else
uClipboardFormat = CF_TEXT;
#endif
break;
case DOCSTR: // string
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 ((lpbyData = GlobalLock(hClipObj))) // lock memory
{
// copy data into clipboard buffer
for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpbyData)
*lpbyData = Read2(dwAddress);
*lpbyData = 0; // set EOS
GlobalUnlock(hClipObj); // unlock memory
uClipboardFormat = CF_TEXT; // always text
}
break;
default:
MessageBeep(MB_OK); // error beep
goto error;
}
if (OpenClipboard(hWnd))
{
if (EmptyClipboard())
SetClipboardData(uClipboardFormat,hClipObj);
else
GlobalFree(hClipObj);
CloseClipboard();
}
else // clipboard open failed
{
GlobalFree(hClipObj);
}
error:
SwitchToState(SM_RUN);
return 0;
}
//
// ID_STACK_PASTE
//
LRESULT OnStackPaste(VOID) // paste data to stack
{
#if defined _UNICODE
#define CF_TEXTFORMAT CF_UNICODETEXT
#else
#define CF_TEXTFORMAT CF_TEXT
#endif
HANDLE hClipObj;
BOOL bSuccess = FALSE;
// check if clipboard format is available
if (!IsClipboardFormatAvailable(CF_TEXTFORMAT))
{
MessageBeep(MB_OK); // error beep
return 0;
}
SuspendDebugger(); // suspend debugger
bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control
// calculator off, turn on
if (!(Chipset.IORam[BITOFFSET]&DON))
{
KeyboardEvent(TRUE,0,0x8000);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
}
_ASSERT(nState == SM_RUN); // emulator must be in RUN state
if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state
{
InfoMessage(_T("The emulator is busy."));
goto cancel;
}
_ASSERT(nState == SM_SLEEP);
if (OpenClipboard(hWnd))
{
if ((hClipObj = GetClipboardData(CF_TEXTFORMAT)))
{
LPCTSTR lpstrClipdata;
LPBYTE lpbyData;
if ((lpstrClipdata = GlobalLock(hClipObj)))
{
BYTE byNumber[128];
DWORD dwAddress;
INT s;
do
{
// HP49G in exact mode
if (cCurrentRomType == 'X' && !RPL_GetSystemFlag(fnApprox))
{
// try to convert string to HP49 precision integer
s = RPL_SetZInt(lpstrClipdata,byNumber,sizeof(byNumber));
if (s > 0) // is a real number for exact mode
{
// get TEMPOB memory for HP49 precision integer object
dwAddress = RPL_CreateTemp(s+5+5);
if ((bSuccess = (dwAddress > 0)))
{
Write5(dwAddress,DOINT); // prolog
Write5(dwAddress+5,s+5); // size
Nwrite(byNumber,dwAddress+10,s); // data
// push object to stack
RPL_Push(dwAddress);
}
break;
}
}
// try to convert string to real format
s = RPL_SetBcd(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber));
if (s > 0) // is a real number
{
// get TEMPOB memory for real object
dwAddress = RPL_CreateTemp(16+5);
if ((bSuccess = (dwAddress > 0)))
{
Write5(dwAddress,DOREAL); // prolog
Nwrite(byNumber,dwAddress+5,s); // data
// push object to stack
RPL_Push(dwAddress);
}
break;
}
// any other format
{
DWORD dwSize = lstrlen(lpstrClipdata);
if ((lpbyData = HeapAlloc(hHeap,0,dwSize * 2)))
{
#if defined _UNICODE
// copy data UNICODE -> ASCII
WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK,
lpstrClipdata, dwSize,
lpbyData+dwSize, dwSize, NULL, NULL);
#else
// copy data
memcpy(lpbyData+dwSize,lpstrClipdata,dwSize);
#endif
bSuccess = (WriteStack(lpbyData,dwSize) == S_ERR_NO);
HeapFree(hHeap,0,lpbyData);
}
}
}
while(FALSE);
GlobalUnlock(hClipObj);
}
}
CloseClipboard();
}
SwitchToState(SM_RUN); // run state
while (nState!=nNextState) Sleep(0);
_ASSERT(nState == SM_RUN);
if (bSuccess == FALSE) // data not copied
goto cancel;
KeyboardEvent(TRUE,0,0x8000);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
cancel:
bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control
ResumeDebugger();
return 0;
#undef CF_TEXTFORMAT
}

View file

@ -108,9 +108,8 @@ static VOID CheckT1(BYTE nT1)
_ASSERT((nT1&8) != 0); // timer1 MSB set
// timer MSB is one and either INT or WAKE is set
if ( (Chipset.IORam[TIMER1_CTRL]&WKE)
|| (Chipset.IORam[TIMER1_CTRL]&INTR))
// timer MSB and INT or WAKE bit is set
if ((Chipset.IORam[TIMER1_CTRL]&(WKE|INTR)) != 0)
Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ
// cpu not sleeping and T1 -> Interrupt
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE))
@ -143,9 +142,8 @@ static VOID CheckT2(DWORD dwT2)
_ASSERT((dwT2&0x80000000) != 0); // timer2 MSB set
// timer MSB is one and either INT or WAKE is set
if ( (Chipset.IORam[TIMER2_CTRL]&WKE)
|| (Chipset.IORam[TIMER2_CTRL]&INTR))
// timer MSB and INT or WAKE bit is set
if ((Chipset.IORam[TIMER2_CTRL]&(WKE|INTR)) != 0)
Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ
// cpu not sleeping and T2 -> Interrupt
if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE))
@ -185,7 +183,7 @@ static VOID RescheduleT2(BOOL bRefPoint)
uDelay = __max(tc.wPeriodMin,uDelay); // wait minimum delay of timer
_ASSERT(uDelay <= tc.wPeriodMax); // inside maximum event delay
// start timer2; schedule event, when Chipset.t2 will be zero
VERIFY(uT2TimerId = timeSetEvent(uDelay,0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT));
VERIFY(uT2TimerId = timeSetEvent(uDelay,0,&TimeProc,2,TIME_ONESHOT));
return;
}
@ -323,7 +321,7 @@ VOID StartTimers(VOID)
// set timer resolution to greatest possible one
bAccurateTimer = (timeBeginPeriod(tc.wPeriodMin) == TIMERR_NOERROR);
// set timer1 with given period
VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC));
VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,&TimeProc,1,TIME_PERIODIC));
RescheduleT2(TRUE); // start timer2
}
return;
@ -398,20 +396,32 @@ BYTE ReadT1(VOID)
VOID SetT1(BYTE byValue)
{
BOOL bEqual;
_ASSERT(byValue < 0x10); // timer1 is only a 4bit counter
if (Chipset.t1 == byValue) // same value doesn't restart timer period
return;
EnterCriticalSection(&csT1Lock);
{
bEqual = (Chipset.t1 == byValue); // check for same value
}
LeaveCriticalSection(&csT1Lock);
if (bEqual) return; // same value doesn't restart timer period
timeKillEvent(uT1TimerId); // stop timer1
uT1TimerId = 0; // set flag timer1 stopped
if (uT1TimerId != 0) // timer1 running
{
timeKillEvent(uT1TimerId); // stop timer1
uT1TimerId = 0; // set flag timer1 stopped
}
EnterCriticalSection(&csT1Lock);
{
Chipset.t1 = byValue; // set new timer1 value
CheckT1(Chipset.t1); // test timer1 control bits
}
LeaveCriticalSection(&csT1Lock);
// restart timer1 to get full period of frequency
VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC));
if (bStarted) // timer running
{
// restart timer1 to get full period of frequency
VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,&TimeProc,1,TIME_PERIODIC));
}
return;
}

View file

@ -74,7 +74,7 @@ BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 160
TOPMARGIN, 4
BOTTOMMARGIN, 210
BOTTOMMARGIN, 256
END
IDD_CHOOSEKML, DIALOG
@ -232,15 +232,15 @@ BEGIN
ES_READONLY
END
IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 229
IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 263
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Settings"
FONT 8, "MS Sans Serif"
BEGIN
CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,13,100,10
CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,
"Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10
CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10
CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,37,89,10
CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT,
@ -255,25 +255,35 @@ BEGIN
CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button",
BS_AUTORADIOBUTTON,84,101,70,11
GROUPBOX "Disassembler",IDC_STATIC,7,90,153,28
LTEXT "Volume",IDC_STATIC,13,134,24,8
CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32",
TBS_AUTOTICKS | WS_TABSTOP,39,129,68,18
CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON |
WS_GROUP | WS_TABSTOP,111,128,43,10
CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,111,
139,43,10
GROUPBOX "Sound",IDC_STATIC,7,120,153,34
CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX |
WS_TABSTOP,13,131,67,10
WS_TABSTOP,13,165,67,10
CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,84,131,69,10
BS_AUTOCHECKBOX | WS_TABSTOP,84,165,69,10
CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,13,143,65,10
LTEXT "Port 2 File :",IDC_STATIC,13,159,37,8
EDITTEXT IDC_PORT2,51,156,94,12,ES_AUTOHSCROLL
PUSHBUTTON "...",IDC_PORT2LOAD,145,156,10,12
GROUPBOX "Memory Cards",IDC_STATIC,7,122,153,51
LTEXT "Wire:",IDC_STATIC,13,188,17,8
COMBOBOX IDC_WIRE,31,186,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
BS_AUTOCHECKBOX | WS_TABSTOP,13,177,65,10
CONTROL "Port 2 is Writeable",IDC_PORT2WR,"Button",
BS_AUTOCHECKBOX | WS_TABSTOP,84,177,69,10
LTEXT "Port 2 File :",IDC_STATIC,13,192,37,8
EDITTEXT IDC_PORT2,51,190,94,12,ES_AUTOHSCROLL
PUSHBUTTON "...",IDC_PORT2LOAD,145,190,10,12
GROUPBOX "Memory Cards",IDC_STATIC,7,156,153,51
LTEXT "Wire:",IDC_STATIC,13,221,17,8
COMBOBOX IDC_WIRE,31,219,48,42,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
LTEXT "IR:",IDC_STATIC,89,188,9,8
COMBOBOX IDC_IR,107,186,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
LTEXT "IR:",IDC_STATIC,89,221,9,8
COMBOBOX IDC_IR,107,219,48,43,CBS_DROPDOWNLIST | WS_VSCROLL |
WS_TABSTOP
GROUPBOX "Serial Ports",IDC_STATIC,7,176,153,27
DEFPUSHBUTTON "&Ok",IDOK,9,208,50,14
PUSHBUTTON "&Cancel",IDCANCEL,107,208,50,14
GROUPBOX "Serial Ports",IDC_STATIC,7,209,153,27
DEFPUSHBUTTON "&Ok",IDOK,9,242,50,14
PUSHBUTTON "&Cancel",IDCANCEL,107,242,50,14
END
IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66
@ -566,8 +576,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,3,7,0
PRODUCTVERSION 1,3,7,0
FILEVERSION 1,4,0,0
PRODUCTVERSION 1,4,0,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -584,12 +594,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0"
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
VALUE "FileVersion", "1, 3, 7, 0\0"
VALUE "FileVersion", "1, 4, 0, 0\0"
VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 2005\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 3, 7, 0\0"
VALUE "ProductVersion", "1, 4, 0, 0\0"
END
END
BLOCK "VarFileInfo"
@ -634,9 +644,9 @@ BEGIN
MENUITEM "&Load Object...", ID_OBJECT_LOAD
MENUITEM "&Save Object...", ID_OBJECT_SAVE
MENUITEM SEPARATOR
MENUITEM "&Copy String", ID_STACK_COPY
MENUITEM "C&opy Screen", ID_VIEW_COPY
MENUITEM "&Paste String", ID_STACK_PASTE
MENUITEM "&Copy Stack", ID_STACK_COPY
MENUITEM "&Paste Stack", ID_STACK_PASTE
MENUITEM SEPARATOR
MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED
POPUP "&Backup"
@ -783,6 +793,18 @@ END
#endif // APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//
IDR_MENU ACCELERATORS DISCARDABLE
BEGIN
"C", ID_STACK_COPY, VIRTKEY, CONTROL, NOINVERT
"V", ID_STACK_PASTE, VIRTKEY, CONTROL, NOINVERT
END
/////////////////////////////////////////////////////////////////////////////
//
// String Table

View file

@ -24,7 +24,8 @@ RSRCOBJ=$(PRJ).o
OBJS=cursor.o disasm.o display.o debugger.o ddeserv.o \
emu48.o engine.o external.o fetch.o files.o i28f160.o keyboard.o \
keymacro.o kml.o mops.o opcodes.o rpl.o serial.o settings.o timer.o \
keymacro.o kml.o mops.o opcodes.o rpl.o serial.o settings.o stack.o \
timer.o \
$(RSRCOBJ)
LIBS=-lwinmm -lcomctl32
@ -111,6 +112,9 @@ serial.o: serial.c pch.h emu48.h types.h io.h
settings.o: settings.c pch.h emu48.h types.h i28f160.h
$(CC) $(CFLAGS) $(DEFINES) -c -o settings.o settings.c
stack.o: stack.c pch.h resource.h Emu48.h io.h
$(CC) $(CFLAGS) $(DEFINES) -c -o stack.o stack.c
timer.o: timer.c pch.h emu48.h types.h io.h
$(CC) $(CFLAGS) $(DEFINES) -c -o timer.o timer.c

View file

@ -13,6 +13,7 @@
#include <ctype.h>
#include <stdio.h>
#include <direct.h>
#include <conio.h>
// #include <crtdbg.h> // missing file
#if !defined VERIFY

View file

@ -29,7 +29,7 @@ or
MinGW-3.1.0-1.exe
w32api-3.3.tar.gz
mingw-runtime-3.8.tar.gz
binutils-2.15.94-20050118-1.tar.gz
binutils-2.16.91-20050827-1.tar.gz
gcc-core-3.4.4-20050522-1.tar.gz
Older versions of the MinGW package might not work, because there are several
@ -43,4 +43,4 @@ Many thanks to Pedro A. Arranda Guti
compatible.
08/22/05 (c) by Christoph Gießelink
12/05/05 (c) by Christoph Gießelink

Binary file not shown.