2010-09-19: Updated to version 48

Signed-off-by: Gwenhael Le Moine <gwenhael.le.moine@gmail.com>
This commit is contained in:
Gwenhael Le Moine 2024-03-20 07:46:28 +01:00
parent af664bab5f
commit 39ac10a752
No known key found for this signature in database
GPG key ID: FDFE3669426707A7
30 changed files with 859 additions and 211 deletions

View file

@ -2,7 +2,7 @@
Emu48 - A freeware HP38/39/40/48/49 Emulator
for Windows 9x, ME, NT, 2000, XP and Vista
for Windows 9x, ME, NT, 2000, XP, Vista and 7
@ -10,8 +10,7 @@
* OPERATING SYSTEM *
********************
This version of Emu48 should work with all Intel Win32 platforms. You may
recompile the sources to run Emu48 with Windows NT on a DEC Alpha.
This version of Emu48 should work with all Intel IA32 and x64 platforms.
****************
@ -19,9 +18,9 @@ recompile the sources to run Emu48 with Windows NT on a DEC Alpha.
****************
Emu48 is distributed in 1 archive:
- Emu48v14xSetup.zip All files and sources
- Emu48v15xSetup.zip All files and sources
To install Emu48, just start the executable file inside the Emu48v14xSetup.zip
To install Emu48, just start the executable file inside the Emu48v15xSetup.zip
archive. The installer will guide you through the installation. When you first
run Emu48, it will detect the directory in which you installed it, and will
write its configuration to a file named Emu48.ini in your Windows directory. If
@ -29,8 +28,8 @@ you move the Emu48 directory to another place you have to change the directory
path inside the Emu48.ini file manually or have to delete the Emu48.ini file.
You can also update your current version with the Service Packs:
- E48BP4x.ZIP New EXE-File
- E48SP4x.ZIP Sources of the Service Pack
- E48BP5x.ZIP New EXE-File
- E48SP5x.ZIP Sources of the Service Pack
Replace the original EXE file please.
@ -436,7 +435,7 @@ have discussed there in different threads for years now.
***************
Emu48 - An HP38/39/40/48/49 Emulator
Copyright (C) 2009 Sebastien Carlier & Christoph Gießelink
Copyright (C) 2010 Sebastien Carlier & Christoph Gießelink
This program is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software

View file

@ -1,4 +1,4 @@
Emu48 1.46+
Emu48 1.48+ (based on Emu48 1.50)
Emu48+ is a modified version of Emu48 to add support for the ARM-based
calculators. It does not emulate the ARM CPU, but it enhances the

BIN
Emu48.dll

Binary file not shown.

BIN
Emu48.exe

Binary file not shown.

View file

@ -1,4 +1,4 @@
Known bugs and restrictions of Emu48 V1.49
Known bugs and restrictions of Emu48 V1.50
------------------------------------------
- the following I/O bits aren't emulated (incomplete)
@ -27,7 +27,6 @@ Known bugs and restrictions of Emu48 V1.49
- display updating differs from the real machine
- screen VBL counter values may skip after large display operations
like turning on or updating the whole display
- executing an opcode over a MMU boundary will fail
- read on an unconfigured address (open data bus) will not show the
same value like a real calculator
- the Yorke hardware signals BEN and DA19 aren't fully supported,
@ -53,4 +52,4 @@ Known bugs and restrictions of Emu48 V1.49
- quitting the emulator while programming the flash isn't allowed,
because the content of flash state machine isn't saved so far
08/18/09 (c) by Christoph Gießelink, c dot giesselink at gmx dot de
07/27/10 (c) by Christoph Gießelink, c dot giesselink at gmx dot de

View file

@ -1,4 +1,154 @@
--------------------------------------------------------------------
Service Pack 48 for Emu48 Version 1.0
DEBUGGER.C
- changed table MemMap[], replaced Chipset_t memory pointer Port0,
Port1 and Port2 by new variables
DISASM.C
- changed function rn_ram(), rn_port1() and rn_port2(), replaced
Chipset_t memory pointers Port0, Port1 and Port2 by new variables
EMU48.C
- changed function Disasm(), added if opcode should be interpreted
as PCO
EMU48.H
- extern declaration of global variables
EMU48.RC
- changed IDR_DEBUG_MEM, added several accelerator keys
- changed version
ENGINE.C
- changed function WorkerThread(), replaced structure Chipset_t
element Port2 by new variable
FILES.C
- added global variables to hold the memory module pointer prior
located in the Chipset_t structure
- bugfix in function PatchRom(), if first patch address in a line
was outside the ROM area, the emulator crashed with an access
violation, removed the patch address wrap around
- changed function ResetDocument(), NewDocument(), OpenDocument(),
SaveDocument(), SaveBackup(), RestoreBackup() and ResetBackup(),
replaced Chipset_t memory pointer Port0, Port1 and Port2 by new
variables
KML.C
- changed function InitKML(), pointed out that a packed ROM image is
an error
MOPS.C
- changed function MapP0(), MapP1() and MapP2(), replaced Chipset_t
memory pointer Port0, Port1 and Port2 by new variables
OPCODES.C
- bugfix in function o807(), a pressed ON key prevented the CPU
going into shutdown mode
OPS.H
- changed function Nunpack(), new coding for speed optimization,
this solved also a bug in the code optimizer of VS2010 (the
optimizer generated wrong code, another possible workaround for
this problem was declaring the function argument "BYTE *a" as
"volatile BYTE *a")
PCH.H
- added INVALID_FILE_ATTRIBUTES definition
RPL.C
- changed function Metakernel(), replaced structure Chipset_t
element Port1 by new variable
SETTINGS.C
- changed function WriteReg() and DelReg(), changed function
protoytypes to make them compatible with the functions
WritePrivateProfileString() and WritePrivateProfileInt()
- changed function GetRegistryInt(), changed function protoytype to
make it compatible with function GetPrivateProfileInt()
TIMER.C
- changed function SetHP48Time(), replaced structure Chipset_t
element Port0 by new variable
TYPES.H
- changed structure Chipset_t, replaced Port0, Port1 and Port2 with
a DWORD placeholder each, because when compiling for x64
architecture these 3 byte pointers grow up to 8 bytes and destroy
the state file structure
Service Pack 47 for Emu48 Version 1.0
DDESERV.C
- changed function DdeCallback(), made ON key hold time variable
DEBUGGER.C
- changed function Debugger(), added Debugger Settings to the system
menu
EMU48.C
- changed function OnDropFiles() and OnObjectLoad(), made ON key
hold time variable
- changed function OnFileMruOpen(), on success move selected entry
to top of MRU table
EMU48.DSP
- changed to REGISTRY (HKCU/Software/Emu48) saving in Release,
Debug, Release Unicode and Debug Unicode configuration
- added symbfile.c sources
EMU48.H
- extern declaration of global variables and functions
EMU48.RC
- changed IDD_DEBUG_SETTINGS, replaced "Ok" with "OK" and removed
accelerator keys from "OK" and "Cancel"
- changed version and copyright
KEYBOARD.C
- changed function KeyboardEvent(), made key switch time variable
KML.C
- enabled "IfMem" KML keyword
- changed function RunLine(), removed warning when compiling for x64
architecture
MRU.C
- changed function MruAdd(), added entry moving to top when the
entry is already in the table
- added function MruMoveTop(), move MRU entry to top of table
OPS.H
- bugfix in function FASTPTR(), longest opcode is 21 nibbles long
and fixed problem executing an opcode over a MMU boundary
PCH.H
- enabled WinXP style under VS2005 and VS2008
SETTINGS.C
- changed function ReadSettings() and WriteSettings(), added items
"WakeupDelay" and "KeyMinDelay" in section [Emulator] in the
INI-File
STACK.C
- bugfix in function RPL_GetBcd(), detection for exponent writing
was wrong -> on negative exponents sometimes the result format was
wrong, on positive exponents from E12 until E14 with 12 digit
mantissa setting the result itself was wrong
- added helper functions RPL_GetComplex() and RPL_SetComplex() to
handle complex number objects
- added function DoComplex() to handle a complex number object
- changed function OnStackCopy(), added complex number support
- changed function OnStackPaste(), made ON key hold time variable,
added flag to disable automatic clipboard object detection and
added complex number support
SYMBFILE.C
- new module for loading external symbols from a Saturn3 linker file
Service Pack 46 for Emu48 Version 1.0
APPLE.C

View file

@ -60,7 +60,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
{
// turn on HP
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
}
@ -93,7 +93,7 @@ HDDEDATA CALLBACK DdeCallback(UINT iType,UINT iFmt,HCONV hConv,
}
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);

View file

@ -92,75 +92,75 @@ static CONST MODEL_MAP_T MemMap[] =
},
{
'6', // HP38G (64K)
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL // nc.
},
{
'A', // HP38G
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL, // nc.
&pbyNoMEM, NULL // nc.
},
{
'E', // HP39/40G
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM part 1
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&pbyNoMEM, NULL, // nc.
&Chipset.Port2, &Chipset.Port2Size // RAM part 2
&Port2, &Chipset.Port2Size // RAM part 2
},
{
'G', // HP48GX
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&Chipset.Port1, &Chipset.Port1Size, // Card slot 1
&Port1, &Chipset.Port1Size, // Card slot 1
&pbyPort2, &dwPort2Size // Card slot 2
},
{
'S', // HP48SX
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&Chipset.Port1, &Chipset.Port1Size, // Card slot 1
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&Port1, &Chipset.Port1Size, // Card slot 1
&pbyPort2, &dwPort2Size, // Card slot 2
&pbyNoMEM, NULL // nc.
},
{
'X', // HP49G
&pbyRom, &dwRomSize, // Flash
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyRom, &dwRomSize, // Flash
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&Chipset.Port1, &Chipset.Port1Size, // Port 1 part 1
&Chipset.Port2, &Chipset.Port2Size // Port 1 part 2
&Port1, &Chipset.Port1Size, // Port 1 part 1
&Port2, &Chipset.Port2Size // Port 1 part 2
},
{ // CdB for HP: add Q type
'Q', // HP49G+
&pbyRom, &dwRomSize, // Flash
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyRom, &dwRomSize, // Flash
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&Chipset.Port1, &Chipset.Port1Size, // Port 1 part 1
&Chipset.Port2, &Chipset.Port2Size // Port 1 part 2
&Port1, &Chipset.Port1Size, // Port 1 part 1
&Port2, &Chipset.Port2Size // Port 1 part 2
},
{ // CdB for HP: add 2 type
'2', // HP48Gii
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&pbyNoMEM, NULL, // Port 1 part 1
&pbyNoMEM, NULL, // Port 1 part 2
},
{ // CdB for HP: add P type
'P', // HP39G+
&pbyRom, &dwRomSize, // ROM
&Chipset.Port0, &Chipset.Port0Size, // RAM part 1
&pbyRom, &dwRomSize, // ROM
&Port0, &Chipset.Port0Size, // RAM
&pbyNoMEM, NULL, // BS
&pbyNoMEM, NULL, // nc.
&Chipset.Port2, &Chipset.Port2Size // RAM part 2
&Port2, &Chipset.Port2Size // RAM part 2
}
};
@ -1902,8 +1902,8 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM
if ((hSysMenu = GetSystemMenu(hDlg,FALSE)) != NULL)
{
// VERIFY(AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL));
// VERIFY(AppendMenu(hSysMenu,MF_STRING,IDM_DEBUG_SETTINGS,_T("Debugger Settings...")));
VERIFY(AppendMenu(hSysMenu,MF_SEPARATOR,0,NULL));
VERIFY(AppendMenu(hSysMenu,MF_STRING,IDM_DEBUG_SETTINGS,_T("Debugger Settings...")));
}
hWndToolbar = CreateToolbar(hDlg); // add toolbar

View file

@ -244,7 +244,7 @@ static BYTE rn_ram (DWORD *p)
*p = ++(*p) & (Chipset.Port0Size * 2048 - 1);
_ASSERT(d < Chipset.Port0Size * 2048);
return *(Chipset.Port0 + d);
return *(Port0 + d);
}
static BYTE rn_port1 (DWORD *p)
@ -254,7 +254,7 @@ static BYTE rn_port1 (DWORD *p)
*p = ++(*p) & (Chipset.Port1Size * 2048 - 1);
_ASSERT(d < Chipset.Port1Size * 2048);
return *(Chipset.Port1 + d);
return *(Port1 + d);
}
static BYTE rn_port2 (DWORD *p)
@ -267,7 +267,7 @@ static BYTE rn_port2 (DWORD *p)
*p = ++(*p) & (Chipset.Port2Size * 2048 - 1);
_ASSERT(d < Chipset.Port2Size * 2048);
pbyVal = Chipset.Port2;
pbyVal = Port2;
}
else // HP48SX/GX
{

View file

@ -13,7 +13,7 @@
#include "kml.h"
#include "debugger.h"
#define VERSION "1.46+"
#define VERSION "1.48+"
// #define MONOCHROME // CF_BITMAP clipboard format
@ -74,6 +74,7 @@ HPALETTE hPalette = NULL;
HPALETTE hOldPalette = NULL; // old palette of hWindowDC
HCURSOR hCursorArrow = NULL;
HCURSOR hCursorHand = NULL;
DWORD dwWakeupDelay = 200; // ON key hold time to switch on calculator
BOOL bAutoSave = FALSE;
BOOL bAutoSaveOnExit = TRUE;
BOOL bSaveDefConfirm = TRUE; // yes
@ -564,7 +565,7 @@ static INT_PTR CALLBACK SettingsProc(HWND hDlg, UINT message, WPARAM wParam, LPA
// 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);
dwWaveVol = (DWORD) 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));
@ -777,7 +778,7 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
{
// turn on HP
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
}
@ -810,7 +811,7 @@ static LRESULT OnDropFiles(HANDLE hFilesInfo)
goto cancel;
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
@ -883,6 +884,10 @@ static LRESULT OnFileMruOpen(UINT wID)
{
MruRemove(wID); // entry not valid any more
}
else
{
MruMoveTop(wID); // move entry to top of MRU list
}
cancel:
if (pbyRom) SwitchToState(SM_RUN);
return 0;
@ -1167,7 +1172,7 @@ static LRESULT OnObjectLoad(VOID)
if (!(Chipset.IORam[BITOFFSET]&DON))
{
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
@ -1224,7 +1229,7 @@ static LRESULT OnObjectLoad(VOID)
while (nState!=nNextState) Sleep(0);
_ASSERT(nState == SM_RUN);
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
while(Chipset.Shutdn == FALSE) Sleep(0);
@ -1270,6 +1275,7 @@ static INT_PTR CALLBACK Disasm(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
static DWORD dwAddress, dwAddressMax;
LONG i;
DWORD dwNxtAddr;
TCHAR *cpStop,szAddress[256] = _T("0");
switch (message)
@ -1335,7 +1341,24 @@ static INT_PTR CALLBACK Disasm(HWND hDlg, UINT message, WPARAM wParam, LPARAM lP
if (dwAddress >= dwAddressMax)
return FALSE;
i = wsprintf(szAddress,(dwAddress <= 0xFFFFF) ? _T("%05lX ") : _T("%06lX "),dwAddress);
dwAddress = disassemble(dwAddress,&szAddress[i]);
// check if address content is a PCO (Primitive Code Object)
dwNxtAddr = (dwAddress + 5) & 0xFFFFF;
if (Read5(dwAddress) == dwNxtAddr)
{
if (disassembler_mode == HP_MNEMONICS)
{
_tcscat(&szAddress[i],_T("CON(5) (*)+5"));
}
else
{
wsprintf(&szAddress[i],_T("dcr.5 $%05x"),dwNxtAddr);
}
dwAddress = dwNxtAddr;
}
else
{
dwAddress = disassemble(dwAddress,&szAddress[i]);
}
i = (LONG) 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);

View file

@ -99,6 +99,7 @@ extern HWND hDlgProfile;
extern HDC hWindowDC;
extern HCURSOR hCursorArrow;
extern HCURSOR hCursorHand;
extern DWORD dwWakeupDelay;
extern BOOL bAutoSave;
extern BOOL bAutoSaveOnExit;
extern BOOL bSaveDefConfirm;
@ -119,6 +120,7 @@ extern BOOL MruInit(INT nNum);
extern VOID MruCleanup(VOID);
extern VOID MruAdd(LPCTSTR lpszEntry);
extern VOID MruRemove(INT nIndex);
extern VOID MruMoveTop(INT nIndex);
extern INT MruEntries(VOID);
extern LPCTSTR MruFilename(INT nIndex);
extern VOID MruUpdateMenu(VOID);
@ -219,6 +221,9 @@ extern TCHAR szBufferFilename[MAX_PATH];
extern TCHAR szPort2Filename[MAX_PATH];
extern BYTE cCurrentRomType;
extern UINT nCurrentClass;
extern LPBYTE Port0;
extern LPBYTE Port1;
extern LPBYTE Port2;
extern LPBYTE pbyRom;
extern BOOL bRomWriteable;
extern DWORD dwRomSize;
@ -293,6 +298,7 @@ extern VOID ReadIO(BYTE *a, DWORD b, DWORD s, BOOL bUpdate);
extern VOID WriteIO(BYTE *a, DWORD b, DWORD s);
// Keyboard.c
extern DWORD dwKeyMinDelay;
extern VOID ScanKeyboard(BOOL bActive, BOOL bReset);
extern VOID KeyboardEvent(BOOL bPress, UINT out, UINT in);
@ -307,6 +313,7 @@ extern LRESULT OnToolMacroStop(VOID);
extern LRESULT OnToolMacroSettings(VOID);
// Stack.c
extern BOOL bDetectClpObject;
extern LRESULT OnStackCopy(VOID);
extern LRESULT OnStackPaste(VOID);
@ -337,11 +344,11 @@ extern BYTE read_nibble(DWORD *p);
extern DWORD disassemble(DWORD addr, LPTSTR out);
// Symbfile.c
#define RplTableEmpty() TRUE // function not implemented so far
#define RplLoadTable(n) FALSE // function not implemented so far
#define RplDeleteTable() // function not implemented so far
#define RplGetName(a) NULL // function not implemented so far
#define RplGetAddr(n,a) FALSE // function not implemented so far
extern BOOL RplTableEmpty(VOID);
extern BOOL RplLoadTable(LPCTSTR lpszFilename);
extern VOID RplDeleteTable(VOID);
extern LPCTSTR RplGetName(DWORD dwAddr);
extern BOOL RplGetAddr(LPCTSTR lpszName, DWORD *pdwAddr);
// Serial.c
extern BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort);
@ -355,11 +362,14 @@ extern VOID CommReceive(VOID);
// Cursor.c
extern HCURSOR CreateHandCursor(VOID);
#if defined _USRDLL // DLL version
#if defined _USRDLL // DLL version
// Emu48dll.c
extern VOID (CALLBACK *pEmuDocumentNotify)(LPCTSTR lpszFilename);
extern BOOL DLLCreateWnd(LPCTSTR lpszFilename, LPCTSTR lpszPort2Name);
extern BOOL DLLDestroyWnd(VOID);
// Symbfile.c
#define RplGetName(a) NULL // for linking
#endif
// Message Boxes

View file

@ -233,7 +233,7 @@ FONT 8, "MS Sans Serif"
BEGIN
ICON IDI_EMU48,IDC_STATIC,7,6,20,20,SS_REALSIZEIMAGE
LTEXT "",IDC_VERSION,29,6,151,8,NOT WS_GROUP
LTEXT "Copyright © 2009 Christoph Gießelink && Sébastien Carlier",
LTEXT "Copyright © 2010 Christoph Gießelink && Sébastien Carlier",
IDC_STATIC,29,18,181,8
DEFPUSHBUTTON "OK",IDOK,215,12,39,14
EDITTEXT IDC_LICENSE,7,33,247,112,ES_MULTILINE | ES_AUTOHSCROLL |
@ -542,8 +542,8 @@ BEGIN
EDITTEXT IDC_DEBUG_SET_FILE,15,65,143,14,ES_AUTOHSCROLL
PUSHBUTTON "...",IDC_DEBUG_SET_BROWSE,159,65,10,14
GROUPBOX "Symbolic",IDC_STATIC,7,36,170,53
DEFPUSHBUTTON "&Ok",IDOK,12,95,50,14
PUSHBUTTON "&Cancel",IDCANCEL,122,95,50,14
DEFPUSHBUTTON "OK",IDOK,12,95,50,14
PUSHBUTTON "Cancel",IDCANCEL,122,95,50,14
END
@ -583,8 +583,8 @@ END
//
VS_VERSION_INFO VERSIONINFO
FILEVERSION 1,4,6,0
PRODUCTVERSION 1,4,6,0
FILEVERSION 1,4,8,0
PRODUCTVERSION 1,4,8,0
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@ -601,12 +601,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Christoph Gießelink & Sebastien Carlier\0"
VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0"
VALUE "FileVersion", "1, 4, 6, 0\0"
VALUE "FileVersion", "1, 4, 8, 0\0"
VALUE "InternalName", "Emu48\0"
VALUE "LegalCopyright", "Copyright © 2009\0"
VALUE "LegalCopyright", "Copyright © 2010\0"
VALUE "OriginalFilename", "Emu48.exe\0"
VALUE "ProductName", "Emu48\0"
VALUE "ProductVersion", "1, 4, 6, 0\0"
VALUE "ProductVersion", "1, 4, 8, 0\0"
END
END
BLOCK "VarFileInfo"
@ -760,15 +760,15 @@ BEGIN
MENUITEM SEPARATOR
POPUP "&Mapping"
BEGIN
MENUITEM "Map", ID_DEBUG_MEM_MAP
MENUITEM "&Map", ID_DEBUG_MEM_MAP
MENUITEM SEPARATOR
MENUITEM "NCE1", ID_DEBUG_MEM_NCE1
MENUITEM "&NCE1", ID_DEBUG_MEM_NCE1
, GRAYED
MENUITEM "NCE2", ID_DEBUG_MEM_NCE2
MENUITEM "N&CE2", ID_DEBUG_MEM_NCE2
, GRAYED
MENUITEM "CE1", ID_DEBUG_MEM_CE1, GRAYED
MENUITEM "CE2", ID_DEBUG_MEM_CE2, GRAYED
MENUITEM "NCE3", ID_DEBUG_MEM_NCE3
MENUITEM "CE&1", ID_DEBUG_MEM_CE1, GRAYED
MENUITEM "CE&2", ID_DEBUG_MEM_CE2, GRAYED
MENUITEM "NCE&3", ID_DEBUG_MEM_NCE3
, GRAYED
END
END
@ -842,10 +842,6 @@ BEGIN
ID_DEBUG_STEP "Step Into"
ID_DEBUG_STEPOVER "Step Over"
ID_DEBUG_BREAK "Break Execution"
END
STRINGTABLE DISCARDABLE
BEGIN
ID_DEBUG_STEPOUT "Step Out"
ID_DEBUG_CANCEL "Stop Debugging"
ID_BREAKPOINTS_SETBREAK "Insert/Remove Breakpoint"

View file

@ -456,9 +456,9 @@ DECLSPEC BOOL CALLBACK EmuLoadObject(
if (!(Chipset.IORam[BITOFFSET]&DON)) // calculator off, turn on
{
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
// wait for sleep mode
while(Chipset.Shutdn == FALSE) Sleep(0);
}
@ -499,7 +499,7 @@ DECLSPEC BOOL CALLBACK EmuLoadObject(
while (nState!=nNextState) Sleep(0);
_ASSERT(nState == SM_RUN);
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
while(Chipset.Shutdn == FALSE) Sleep(0);

View file

@ -528,7 +528,7 @@ loop:
nState = SM_RUN;
// clear port2 status bits
Chipset.cards_status &= ~(PORT2_PRESENT | PORT2_WRITE);
if (pbyPort2 || Chipset.Port2) // card plugged in port2
if (pbyPort2 || Port2) // card plugged in port2
{
Chipset.cards_status |= PORT2_PRESENT;

View file

@ -47,7 +47,7 @@ RSC=rc.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /Yu"pch.h" /FD /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /Yu"pch.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "NDEBUG"
@ -73,7 +73,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /W3 /Gm /GX /Zi /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /YX /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /FR /Yu"pch.h" /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /FR /Yu"pch.h" /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "_DEBUG"
@ -100,7 +100,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /Yu"pch.h" /FD /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "_UNICODE" /D "UNICODE" /Yu"pch.h" /FD /c
# ADD CPP /nologo /Gr /MT /W3 /GX /O2 /Ob2 /D "NDEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /D "_UNICODE" /D "UNICODE" /Yu"pch.h" /FD /c
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "NDEBUG"
@ -127,7 +127,7 @@ LINK32=link.exe
# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /Zi /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /FR /Yu"pch.h" /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "_UNICODE" /D "UNICODE" /FR /Yu"pch.h" /FD /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "_DEBUG" /D "WIN32" /D "_WINDOWS" /D "STRICT" /D "REGISTRY" /D "_UNICODE" /D "UNICODE" /FR /Yu"pch.h" /FD /c
# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x40c /d "_DEBUG"
@ -305,6 +305,10 @@ SOURCE=.\stack.c
# End Source File
# Begin Source File
SOURCE=.\symbfile.c
# End Source File
# Begin Source File
SOURCE=.\timer.c
# End Source File
# End Group

View file

@ -27,6 +27,10 @@ TCHAR szPort2Filename[MAX_PATH];
BYTE cCurrentRomType = 0; // Model -> hardware
UINT nCurrentClass = 0; // Class -> derivate
LPBYTE Port0 = NULL;
LPBYTE Port1 = NULL;
LPBYTE Port2 = NULL;
LPBYTE pbyRom = NULL;
BOOL bRomWriteable = TRUE; // flag if ROM writeable
DWORD dwRomSize = 0;
@ -55,6 +59,9 @@ static BYTE pbySignatureV[16] = "Emu49 Document\xFE";
static HANDLE hCurrentFile = NULL;
static CHIPSET BackupChipset;
static LPBYTE BackupPort0;
static LPBYTE BackupPort1;
static LPBYTE BackupPort2;
//################
//#
@ -345,10 +352,13 @@ BOOL PatchRom(LPCTSTR szFilename)
while (lpBuf[nPos])
{
if (isxdigit(lpBuf[nPos]) == FALSE) break;
// patch ROM and save original nibble
PatchNibble(dwAddress, Asc2Nib(lpBuf[nPos]));
dwAddress = (dwAddress+1)&(dwRomSize-1);
nPos++;
if (dwAddress < dwRomSize) // patch ROM
{
// patch ROM and save original nibble
PatchNibble(dwAddress, Asc2Nib(lpBuf[nPos]));
}
++dwAddress;
++nPos;
}
}
HeapFree(hHeap,0,lpBuf);
@ -661,9 +671,9 @@ VOID ResetDocument(VOID)
}
szCurrentKml[0] = 0;
szCurrentFilename[0]=0;
if (Chipset.Port0) HeapFree(hHeap,0,Chipset.Port0);
if (Chipset.Port1) HeapFree(hHeap,0,Chipset.Port1);
if (Chipset.Port2) HeapFree(hHeap,0,Chipset.Port2); else UnmapPort2();
if (Port0) { HeapFree(hHeap,0,Port0); Port0 = NULL; }
if (Port1) { HeapFree(hHeap,0,Port1); Port1 = NULL; }
if (Port2) { HeapFree(hHeap,0,Port2); Port2 = NULL; } else UnmapPort2();
ZeroMemory(&Chipset,sizeof(Chipset));
ZeroMemory(&RMap,sizeof(RMap)); // delete MMU mappings
ZeroMemory(&WMap,sizeof(WMap));
@ -741,18 +751,18 @@ BOOL NewDocument(VOID)
// allocate port memory
if (Chipset.Port0Size)
{
Chipset.Port0 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port0Size*2048);
_ASSERT(Chipset.Port0 != NULL);
Port0 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port0Size*2048);
_ASSERT(Port0 != NULL);
}
if (Chipset.Port1Size)
{
Chipset.Port1 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port1Size*2048);
_ASSERT(Chipset.Port1 != NULL);
Port1 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port1Size*2048);
_ASSERT(Port1 != NULL);
}
if (Chipset.Port2Size)
{
Chipset.Port2 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port2Size*2048);
_ASSERT(Chipset.Port2 != NULL);
Port2 = HeapAlloc(hHeap,HEAP_ZERO_MEMORY,Chipset.Port2Size*2048);
_ASSERT(Port2 != NULL);
}
LoadBreakpointList(NULL); // clear debugger breakpoint list
RomSwitch(0); // boot ROM view of HP49G and map memory
@ -885,9 +895,6 @@ BOOL OpenDocument(LPCTSTR szFilename)
SetFilePointer(hFile, lSizeofChipset-sizeof(Chipset), NULL, FILE_CURRENT);
lSizeofChipset = sizeof(Chipset);
}
Chipset.Port0 = NULL; // delete invalid port pointers
Chipset.Port1 = NULL;
Chipset.Port2 = NULL;
if (lBytesRead != lSizeofChipset) goto read_err;
if (!isModelValid(Chipset.type)) // check for valid model in emulator state file
@ -920,32 +927,32 @@ BOOL OpenDocument(LPCTSTR szFilename)
if (Chipset.Port0Size)
{
Chipset.Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048);
if (Chipset.Port0 == NULL)
Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048);
if (Port0 == NULL)
{
AbortMessage(_T("Memory Allocation Failure."));
goto restore;
}
ReadFile(hFile, Chipset.Port0, Chipset.Port0Size*2048, &lBytesRead, NULL);
ReadFile(hFile, Port0, Chipset.Port0Size*2048, &lBytesRead, NULL);
if (lBytesRead != Chipset.Port0Size*2048) goto read_err;
if (IsDataPacked(Chipset.Port0,Chipset.Port0Size*2048)) goto read_err;
if (IsDataPacked(Port0,Chipset.Port0Size*2048)) goto read_err;
}
if (Chipset.Port1Size)
{
Chipset.Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048);
if (Chipset.Port1 == NULL)
Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048);
if (Port1 == NULL)
{
AbortMessage(_T("Memory Allocation Failure."));
goto restore;
}
ReadFile(hFile, Chipset.Port1, Chipset.Port1Size*2048, &lBytesRead, NULL);
ReadFile(hFile, Port1, Chipset.Port1Size*2048, &lBytesRead, NULL);
if (lBytesRead != Chipset.Port1Size*2048) goto read_err;
if (IsDataPacked(Chipset.Port1,Chipset.Port1Size*2048)) goto read_err;
if (IsDataPacked(Port1,Chipset.Port1Size*2048)) goto read_err;
}
// HP48SX/GX
@ -967,17 +974,17 @@ BOOL OpenDocument(LPCTSTR szFilename)
{
if (Chipset.Port2Size)
{
Chipset.Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048);
if (Chipset.Port2 == NULL)
Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048);
if (Port2 == NULL)
{
AbortMessage(_T("Memory Allocation Failure."));
goto restore;
}
ReadFile(hFile, Chipset.Port2, Chipset.Port2Size*2048, &lBytesRead, NULL);
ReadFile(hFile, Port2, Chipset.Port2Size*2048, &lBytesRead, NULL);
if (lBytesRead != Chipset.Port2Size*2048) goto read_err;
if (IsDataPacked(Chipset.Port2,Chipset.Port2Size*2048)) goto read_err;
if (IsDataPacked(Port2,Chipset.Port2Size*2048)) goto read_err;
bPort2Writeable = TRUE;
Chipset.cards_status = 0xF;
@ -1074,9 +1081,9 @@ BOOL SaveDocument(VOID)
lSizeofChipset = sizeof(CHIPSET);
WriteFile(hCurrentFile, &lSizeofChipset, sizeof(lSizeofChipset), &lBytesWritten, NULL);
WriteFile(hCurrentFile, &Chipset, lSizeofChipset, &lBytesWritten, NULL);
if (Chipset.Port0Size) WriteFile(hCurrentFile, Chipset.Port0, Chipset.Port0Size*2048, &lBytesWritten, NULL);
if (Chipset.Port1Size) WriteFile(hCurrentFile, Chipset.Port1, Chipset.Port1Size*2048, &lBytesWritten, NULL);
if (Chipset.Port2Size) WriteFile(hCurrentFile, Chipset.Port2, Chipset.Port2Size*2048, &lBytesWritten, NULL);
if (Chipset.Port0Size) WriteFile(hCurrentFile, Port0, Chipset.Port0Size*2048, &lBytesWritten, NULL);
if (Chipset.Port1Size) WriteFile(hCurrentFile, Port1, Chipset.Port1Size*2048, &lBytesWritten, NULL);
if (Chipset.Port2Size) WriteFile(hCurrentFile, Port2, Chipset.Port2Size*2048, &lBytesWritten, NULL);
SaveBreakpointList(hCurrentFile); // save debugger breakpoint list
SetEndOfFile(hCurrentFile); // cut the rest
return TRUE;
@ -1133,19 +1140,19 @@ BOOL SaveBackup(VOID)
lstrcpy(szBackupFilename, szCurrentFilename);
lstrcpy(szBackupKml, szCurrentKml);
if (BackupChipset.Port0) HeapFree(hHeap,0,BackupChipset.Port0);
if (BackupChipset.Port1) HeapFree(hHeap,0,BackupChipset.Port1);
if (BackupChipset.Port2) HeapFree(hHeap,0,BackupChipset.Port2);
if (BackupPort0) HeapFree(hHeap,0,BackupPort0);
if (BackupPort1) HeapFree(hHeap,0,BackupPort1);
if (BackupPort2) HeapFree(hHeap,0,BackupPort2);
CopyMemory(&BackupChipset, &Chipset, sizeof(Chipset));
BackupChipset.Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048);
CopyMemory(BackupChipset.Port0, Chipset.Port0, Chipset.Port0Size*2048);
BackupChipset.Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048);
CopyMemory(BackupChipset.Port1, Chipset.Port1, Chipset.Port1Size*2048);
BackupChipset.Port2 = NULL;
BackupPort0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048);
CopyMemory(BackupPort0,Port0,Chipset.Port0Size*2048);
BackupPort1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048);
CopyMemory(BackupPort1,Port1,Chipset.Port1Size*2048);
BackupPort2 = NULL;
if (Chipset.Port2Size) // internal port2
{
BackupChipset.Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048);
CopyMemory(BackupChipset.Port2, Chipset.Port2, Chipset.Port2Size*2048);
BackupPort2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048);
CopyMemory(BackupPort2,Port2,Chipset.Port2Size*2048);
}
CreateBackupBreakpointList();
bBackup = TRUE;
@ -1180,14 +1187,14 @@ BOOL RestoreBackup(VOID)
}
}
CopyMemory(&Chipset, &BackupChipset, sizeof(Chipset));
Chipset.Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048);
CopyMemory(Chipset.Port0, BackupChipset.Port0, Chipset.Port0Size*2048);
Chipset.Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048);
CopyMemory(Chipset.Port1, BackupChipset.Port1, Chipset.Port1Size*2048);
Port0 = HeapAlloc(hHeap,0,Chipset.Port0Size*2048);
CopyMemory(Port0, BackupPort0, Chipset.Port0Size*2048);
Port1 = HeapAlloc(hHeap,0,Chipset.Port1Size*2048);
CopyMemory(Port1, BackupPort1, Chipset.Port1Size*2048);
if (Chipset.Port2Size) // internal port2
{
Chipset.Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048);
CopyMemory(Chipset.Port2, BackupChipset.Port2, Chipset.Port2Size*2048);
Port2 = HeapAlloc(hHeap,0,Chipset.Port2Size*2048);
CopyMemory(Port2, BackupPort2, Chipset.Port2Size*2048);
}
// map port2
else
@ -1212,9 +1219,9 @@ BOOL ResetBackup(VOID)
if (!bBackup) return FALSE;
szBackupFilename[0] = 0;
szBackupKml[0] = 0;
if (BackupChipset.Port0) HeapFree(hHeap,0,BackupChipset.Port0);
if (BackupChipset.Port1) HeapFree(hHeap,0,BackupChipset.Port1);
if (BackupChipset.Port2) HeapFree(hHeap,0,BackupChipset.Port2);
if (BackupPort0) { HeapFree(hHeap,0,BackupPort0); BackupPort0 = NULL; }
if (BackupPort1) { HeapFree(hHeap,0,BackupPort1); BackupPort1 = NULL; }
if (BackupPort2) { HeapFree(hHeap,0,BackupPort2); BackupPort2 = NULL; }
ZeroMemory(&BackupChipset,sizeof(BackupChipset));
bBackup = FALSE;
UpdateWindowStatus();

View file

@ -10,6 +10,8 @@
#include "Emu48.h"
#include "io.h" // I/O definitions
DWORD dwKeyMinDelay = 50; // minimum time for key hold
static WORD Keyboard_GetIR(VOID)
{
WORD r = 0;
@ -124,6 +126,6 @@ VOID KeyboardEvent(BOOL bPress, UINT out, UINT in)
}
AdjKeySpeed(); // adjust key repeat speed
ScanKeyboard(FALSE,FALSE); // update Chipset.in register by 1ms keyboard poll
Sleep(50); // hold key state for a definite time
Sleep(dwKeyMinDelay); // hold key state for a definite time
return;
}

View file

@ -317,7 +317,7 @@ static INT_PTR CALLBACK MacroProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM
return TRUE;
case IDOK:
// get macro data
nMacroTimeout = MAX_SPEED - SendDlgItemMessage(hDlg,IDC_MACRO_SLIDER,TBM_GETPOS,0,0);
nMacroTimeout = MAX_SPEED - (INT) SendDlgItemMessage(hDlg,IDC_MACRO_SLIDER,TBM_GETPOS,0,0);
bMacroRealSpeed = IsDlgButtonChecked(hDlg,IDC_MACRO_REAL);
// no break
case IDCANCEL:

View file

@ -90,7 +90,7 @@ static KmlToken pLexToken[] =
{TOK_MODEL, 000002, 5,_T("Model")},
{TOK_CLASS, 000001, 5,_T("Class")},
{TOK_PRESS, 000001, 5,_T("Press")},
// {TOK_IFMEM, 000111, 5,_T("IfMem")},
{TOK_IFMEM, 000111, 5,_T("IfMem")},
{TOK_TYPE, 000001, 4,_T("Type")},
{TOK_SIZE, 000011, 4,_T("Size")},
{TOK_ZOOM, 000001, 4,_T("Zoom")},
@ -1406,7 +1406,7 @@ static KmlLine* RunLine(KmlLine* pLine)
case TOK_IFFLAG:
return If(pLine,(nKMLFlags>>(pLine->nParam[0]&0x1F))&1);
case TOK_IFMEM:
Npeek(&byVal,pLine->nParam[0],1);
Npeek(&byVal,(DWORD) pLine->nParam[0],1);
return If(pLine,(byVal & pLine->nParam[1]) == pLine->nParam[2]);
default:
break;
@ -2219,7 +2219,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog)
}
if (!CrcRom(&wRomCrc)) // build patched ROM fingerprint and check for unpacked data
{
AddToLog(_T("Packed ROM image detected."));
AddToLog(_T("Error, packed ROM image detected."));
UnmapRom(); // free memory
goto quit;
}

View file

@ -151,8 +151,8 @@ static VOID MapP0(BYTE a, BYTE b)
// mapping area may have holes
if (((i ^ Chipset.P0Base) & ~Chipset.P0Size) == 0)
{
RMap[i]=Chipset.Port0 + p;
WMap[i]=Chipset.Port0 + p;
RMap[i]=Port0 + p;
WMap[i]=Port0 + p;
}
p = (p+0x1000)&m;
}
@ -187,7 +187,7 @@ static VOID MapP1(BYTE a, BYTE b)
b = (BYTE)MIN(b,Chipset.P1End); // highest address for use is P1End
// port1 not plugged
if (Chipset.Port1 == NULL || !(Chipset.cards_status & PORT1_PRESENT))
if (Port1 == NULL || !(Chipset.cards_status & PORT1_PRESENT))
{
for (i=a; i<=b; i++) // scan each 2KB page
{
@ -210,8 +210,8 @@ static VOID MapP1(BYTE a, BYTE b)
// mapping area may have holes
if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0)
{
RMap[i]=Chipset.Port1 + p; // save page address for read
WMap[i]=Chipset.Port1 + p; // save page address for write
RMap[i]=Port1 + p; // save page address for read
WMap[i]=Port1 + p; // save page address for write
}
p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size
}
@ -223,7 +223,7 @@ static VOID MapP1(BYTE a, BYTE b)
// mapping area may have holes
if (((i ^ Chipset.P1Base) & ~Chipset.P1Size) == 0)
{
RMap[i]=Chipset.Port1 + p; // save page address for read
RMap[i]=Port1 + p; // save page address for read
WMap[i]=NULL; // no writing
}
p = (p+0x1000)&m; // next page, mirror page if real size smaller allocated size
@ -251,8 +251,8 @@ static VOID MapP2(BYTE a, BYTE b)
// mapping area may have holes
if (((i ^ Chipset.P2Base) & ~Chipset.P2Size) == 0)
{
RMap[i]=Chipset.Port2 + p;
WMap[i]=Chipset.Port2 + p;
RMap[i]=Port2 + p;
WMap[i]=Port2 + p;
}
p = (p+0x1000)&m;
}

View file

@ -133,7 +133,7 @@ VOID MruAdd(LPCTSTR lpszEntry)
if ( ppszFiles[i] != NULL
&& lstrcmpi(ppszFiles[i],szFilename) == 0)
{
MruUpdateMenu(); // update menu
MruMoveTop(i); // move to top and update menu
return;
}
}
@ -158,7 +158,7 @@ VOID MruRemove(INT nIndex)
{
HeapFree(hHeap,0,ppszFiles[nIndex]); // free entry
for (; nIndex < nEntry - 1; ++nIndex) // move old entries 1 line up
for (; nIndex < nEntry - 1; ++nIndex) // move below entries 1 line up
{
ppszFiles[nIndex] = ppszFiles[nIndex+1];
}
@ -169,6 +169,21 @@ VOID MruRemove(INT nIndex)
return;
}
VOID MruMoveTop(INT nIndex)
{
LPTSTR lpszEntry = ppszFiles[nIndex]; // remember selected entry
for (; nIndex > 0; --nIndex) // move above entries 1 line down
{
ppszFiles[nIndex] = ppszFiles[nIndex-1];
}
ppszFiles[0] = lpszEntry; // insert entry on top
MruUpdateMenu(); // update menu
return;
}
INT MruEntries(VOID)
{
return nEntry;

View file

@ -1031,7 +1031,10 @@ VOID o807(LPBYTE I) // SHUTDN
}
}
ScanKeyboard(TRUE,FALSE); // update Chipset.in register (direct)
if (w.in == 0 && bShutdn) // shut down only when enabled
// out register going low during shutdown, so normal keys produce a rising
// edge trigger when out register going high again. Because the ON key is not
// connected to the out register, the rising edge trigger must be done manually.
if ((w.in & 0x7FFF) == 0 && bShutdn) // shut down only when enabled
{
w.Shutdn = TRUE; // set mode before exit emulation loop
bInterrupt = TRUE;

View file

@ -37,22 +37,29 @@
static __inline LPBYTE FASTPTR(DWORD d)
{
static BYTE pbyNULL[16];
static BYTE pbyNULL[21];
LPBYTE lpbyPage;
DWORD u, v;
d &= 0xFFFFF; // handle address overflows
if ((Chipset.IOCfig)&&((d&0xFFFC0)==Chipset.IOBase))
return Chipset.IORam+d-Chipset.IOBase;
u = d >> 12; // page
v = d & 0xFFF; // offset
if((lpbyPage = RMap[d>>12]) != NULL) // page valid
if ( !(Chipset.IOCfig && ((d & 0xFFFC0) == Chipset.IOBase))
&& RMap[u] != NULL // page valid
&& ( v < 0x1000 - ARRAYSIZEOF(lpbyPage) // complete opcode inside page
// or next page continue linear addressing
|| (RMap[u] + 0x1000 == RMap[(u+1) & (ARRAYSIZEOF(RMap)-1)])
)
)
{
lpbyPage += d & 0xFFF; // full address
lpbyPage = RMap[u] + v; // full address
}
else
{
lpbyPage = pbyNULL; // memory allocation
Npeek(lpbyPage, d, 13); // fill with data (LA(8) = longest opcode)
Npeek(lpbyPage, d, ARRAYSIZEOF(lpbyPage)); // fill with data (LAHEX + 16 digits = longest opcode)
}
return lpbyPage;
}
@ -83,8 +90,7 @@ static __inline DWORD Npack(BYTE *a, UINT s)
static __inline VOID Nunpack(BYTE *a, DWORD b, UINT s)
{
UINT i;
for (i=0; i<s; i++) { a[i] = (BYTE)(b&0xf); b>>=4; }
for (; s>0; --s) { *a++ = (BYTE)(b&0xf); b>>=4; }
}
static __inline QWORD Npack64(BYTE *a, UINT s)

View file

@ -30,6 +30,10 @@
#define INVALID_SET_FILE_POINTER ((DWORD)-1)
#endif
#if !defined INVALID_FILE_ATTRIBUTES
#define INVALID_FILE_ATTRIBUTES ((DWORD)-1)
#endif
#if !defined IDC_HAND // Win2k specific definition
#define IDC_HAND MAKEINTRESOURCE(32649)
#endif
@ -37,3 +41,35 @@
#if _MSC_VER <= 1200 // missing type definition in the MSVC6.0 SDK and earlier
typedef SIZE_T DWORD_PTR, *PDWORD_PTR;
#endif
#if _MSC_VER >= 1400 // valid for VS2005 and later
#if defined _M_IX86
#pragma comment(linker,"/manifestdependency:\" \
type='win32' \
name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='x86' \
publicKeyToken='6595b64144ccf1df' \
language='*'\"")
#elif defined _M_IA64
#pragma comment(linker,"/manifestdependency:\" \
type='win32' \
name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='ia64' \
publicKeyToken='6595b64144ccf1df' \
language='*'\"")
#elif defined _M_X64
#pragma comment(linker,"/manifestdependency:\" \
type='win32' \
name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='amd64' \
publicKeyToken='6595b64144ccf1df' \
language='*'\"")
#else
#pragma comment(linker,"/manifestdependency:\" \
type='win32' \
name='Microsoft.Windows.Common-Controls' \
version='6.0.0.0' processorArchitecture='*' \
publicKeyToken='6595b64144ccf1df' \
language='*'\"")
#endif
#endif

View file

@ -79,18 +79,18 @@ static BOOL Metakernel(VOID)
BOOL bMkDetect = FALSE;
// card in slot1 of a HP48GX enabled
if (cCurrentRomType=='G' && Chipset.Port1 && Chipset.cards_status & PORT1_PRESENT)
if (cCurrentRomType=='G' && Port1 && Chipset.cards_status & PORT1_PRESENT)
{
// check for Metakernel string "MDGKER:"
if (!strncmp(&Chipset.Port1[12],"\xD\x4\x4\x4\x7\x4\xB\x4\x5\x4\x2\x5\xA\x3",14))
if (!strncmp(&Port1[12],"\xD\x4\x4\x4\x7\x4\xB\x4\x5\x4\x2\x5\xA\x3",14))
{
bMkDetect = TRUE; // Metakernel detected
// check for "MK"
if (!strncmp(&Chipset.Port1[26],"\xD\x4\xB\x4",4))
if (!strncmp(&Port1[26],"\xD\x4\xB\x4",4))
{
// get version number
WORD wVersion = ((Chipset.Port1[30] * 10) + Chipset.Port1[34]) * 10
+ Chipset.Port1[36];
WORD wVersion = ((Port1[30] * 10) + Port1[34]) * 10
+ Port1[36];
// version newer then V2.30, then compatible with HP OS
bMkDetect = (wVersion <= 230);

View file

@ -78,7 +78,7 @@ static VOID ReadReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, LPBYTE lpData, DWORD
return;
}
static VOID WriteReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
static BOOL WriteReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, CONST BYTE *lpData, DWORD cbData)
{
TCHAR lpKey[256] = _T(REGISTRYKEY) _T("\\");
@ -100,10 +100,10 @@ static VOID WriteReg(LPCTSTR lpSubKey, LPCTSTR lpValueName, DWORD dwType, CONST
RegSetValueEx(hKey,lpValueName,0,dwType,lpData,cbData);
RegCloseKey(hKey);
return;
return retCode == ERROR_SUCCESS;
}
static VOID DelReg(LPCTSTR lpSubKey, LPCTSTR lpValueName)
static BOOL DelReg(LPCTSTR lpSubKey, LPCTSTR lpValueName)
{
TCHAR lpKey[256] = _T(REGISTRYKEY) _T("\\");
@ -122,7 +122,7 @@ static VOID DelReg(LPCTSTR lpSubKey, LPCTSTR lpValueName)
retCode = RegDeleteValue(hKey,lpValueName);
RegCloseKey(hKey);
}
return;
return retCode == ERROR_SUCCESS;
}
static DWORD GetRegistryString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpDefault, LPTSTR lpData, DWORD dwSize)
@ -141,7 +141,7 @@ static DWORD GetRegistryString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR l
return dwSize;
}
static INT GetRegistryInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nDefault)
static UINT GetRegistryInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, INT nDefault)
{
UINT nValue;
DWORD dwSize = sizeof(nValue);
@ -185,6 +185,8 @@ VOID ReadSettings(VOID)
dwGXCycles = ReadInt(_T("Emulator"),_T("GXCycles"),dwGXCycles);
dwGPCycles = ReadInt(_T("Emulator"),_T("GPCycles"),dwGPCycles); // CdB for HP: add apples
dwG2Cycles = ReadInt(_T("Emulator"),_T("G2Cycles"),dwG2Cycles); // CdB for HP: add apples
dwKeyMinDelay = ReadInt(_T("Emulator"),_T("KeyMinDelay"),dwKeyMinDelay);
dwWakeupDelay = ReadInt(_T("Emulator"),_T("WakeupDelay"),dwWakeupDelay);
bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
bWaveBeep = ReadInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep);
dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);
@ -226,6 +228,8 @@ VOID WriteSettings(VOID)
WriteInt(_T("Emulator"),_T("GXCycles"),dwGXCycles);
WriteInt(_T("Emulator"),_T("GPCycles"),dwGPCycles); // CdB for HP: add apples
WriteInt(_T("Emulator"),_T("G2Cycles"),dwG2Cycles); // CdB for HP: add apples
WriteInt(_T("Emulator"),_T("KeyMinDelay"),dwKeyMinDelay);
WriteInt(_T("Emulator"),_T("WakeupDelay"),dwWakeupDelay);
WriteInt(_T("Emulator"),_T("Grayscale"),bGrayscale);
WriteInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep);
WriteInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol);

View file

@ -11,12 +11,15 @@
#include "Emu48.h"
#include "io.h"
#define fnRadix 51 // fraction mark
#define fnApprox 105 // exact / approx. mode (HP49G)
#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
#define DOINT 0x02614 // Precision Integer (HP49G)
#define DOREAL 0x02933 // Real
#define DOCMP 0x02977 // Complex
#define DOCSTR 0x02A2C // String
BOOL bDetectClpObject = TRUE; // try to detect clipboard object
//################
//#
@ -143,7 +146,7 @@ static INT RPL_GetBcd(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cD
}
// TRUE at x.E
bExpflag = v + lExp > 14 || v + lExp < -nMantLen;
bExpflag = v + lExp >= nMantLen || lExp < -nMantLen;
bPflag = !bExpflag && v < -lExp; // decimal point flag at neg. exponent
}
@ -314,6 +317,97 @@ static INT RPL_SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYT
return nMantLen + nExpLen + 1;
}
static INT RPL_GetComplex(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPTSTR cp,INT nSize)
{
INT nLen,nPos;
TCHAR cSep;
cSep = (cDec == _T('.')) // current separator
? _T(',') // radix mark '.' -> ',' separator
: _T(';'); // radix mark ',' -> ';' separator
nPos = 0; // write buffer position
if (nSize < 5) return 0; // target buffer to small
nSize -= 4; // reserved room for (,)\0
cp[nPos++] = _T('('); // start of complex number
// real part
nLen = RPL_GetBcd(pbyNum,12,3,cDec,&cp[1],nSize);
if (nLen == 0) return 0; // target buffer to small
_ASSERT(nLen <= nSize);
nPos += nLen; // actual buffer postion
nSize -= nLen; // remainder target buffer size
cp[nPos++] = cSep; // write of complex number seperator
// imaginary part
nLen = RPL_GetBcd(&pbyNum[16],12,3,cDec,&cp[nPos],nSize);
if (nLen == 0) return 0; // target buffer to small
nPos += nLen; // actual buffer postion
cp[nPos++] = _T(')'); // end of complex number
cp[nPos] = 0; // EOS
_ASSERT(lstrlen(cp) == nPos);
return nPos;
}
static INT RPL_SetComplex(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize)
{
LPTSTR pcSep,pszData;
INT nLen;
TCHAR cSep;
nLen = 0; // read data length
cSep = (cDec == _T('.')) // current separator
? _T(',') // radix mark '.' -> ',' separator
: _T(';'); // radix mark ',' -> ';' separator
// create a working copy of the string
if ((pszData = DuplicateString(cp)) != NULL)
{
INT nStrLength = lstrlen(pszData); // string length
// complex number with brackets around
if ( nStrLength > 0
&& pszData[0] == _T('(')
&& pszData[nStrLength - 1] == _T(')'))
{
pszData[--nStrLength] = 0; // replace ')' with EOS
// search for number separator
if ((pcSep = _tcschr(pszData+1,cSep)) != NULL)
{
INT nLen1st;
*pcSep = 0; // set EOS for 1st substring
// decode 1st substring
nLen1st = RPL_SetBcd(pszData+1,nMantLen,nExpLen,cDec,&pbyNum[0],nSize);
if (nLen1st > 0)
{
// decode 2nd substring
nLen = RPL_SetBcd(pcSep+1,nMantLen,nExpLen,cDec,&pbyNum[nMantLen+nExpLen+1],nSize-nLen1st);
if (nLen > 0)
{
nLen += nLen1st; // complete Bcd length
}
}
}
}
HeapFree(hHeap,0,pszData);
}
return nLen;
}
//################
//#
//# Object subroutines
@ -385,6 +479,15 @@ static INT DoReal(DWORD dwAddress,LPTSTR cp,INT nSize)
return RPL_GetBcd(byNumber,12,3,GetRadix(),cp,nSize);
}
static INT DoComplex(DWORD dwAddress,LPTSTR cp,INT nSize)
{
BYTE byNumber[32];
// get complex object content and decode it
Npeek(byNumber,dwAddress,ARRAYSIZEOF(byNumber));
return RPL_GetComplex(byNumber,12,3,GetRadix(),cp,nSize);
}
//################
//#
@ -422,6 +525,7 @@ LRESULT OnStackCopy(VOID) // copy data from stack
{
case DOINT: // Precision Integer (HP49G)
case DOREAL: // real object
case DOCMP: // complex object
dwAddress += 5; // object content
switch (dwObject)
@ -434,6 +538,10 @@ LRESULT OnStackCopy(VOID) // copy data from stack
// get real object content and decode it
dwSize = DoReal(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
break;
case DOCMP: // complex object
// get complex object content and decode it
dwSize = DoComplex(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer));
break;
}
// calculate buffer size
@ -527,7 +635,7 @@ LRESULT OnStackPaste(VOID) // paste data to stack
if (!(Chipset.IORam[BITOFFSET]&DON))
{
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode
@ -556,48 +664,76 @@ LRESULT OnStackPaste(VOID) // paste data to stack
DWORD dwAddress;
INT s;
do
{
// HP49G or HP49G+ in exact mode
if ( (cCurrentRomType == 'X' || cCurrentRomType == 'Q')
&& !RPL_GetSystemFlag(fnApprox))
if (bDetectClpObject) // autodetect clipboard object enabled
{
// 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
// HP49G or HP49G+ in exact mode
if ( (cCurrentRomType == 'X' || cCurrentRomType == 'Q')
&& !RPL_GetSystemFlag(fnApprox))
{
// get TEMPOB memory for HP49 precision integer object
dwAddress = RPL_CreateTemp(s+5+5,TRUE);
// 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,TRUE);
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(1,dwAddress);
}
break;
}
}
// try to convert string to real format
_ASSERT(16 <= ARRAYSIZEOF(byNumber));
s = RPL_SetBcd(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber));
if (s > 0) // is a real number
{
_ASSERT(s == 16); // length of real number BCD coded
// get TEMPOB memory for real object
dwAddress = RPL_CreateTemp(16+5,TRUE);
if ((bSuccess = (dwAddress > 0)))
{
Write5(dwAddress,DOINT); // prolog
Write5(dwAddress+5,s+5); // size
Nwrite(byNumber,dwAddress+10,s); // data
Write5(dwAddress,DOREAL); // prolog
Nwrite(byNumber,dwAddress+5,s); // data
// push object to stack
RPL_Push(1,dwAddress);
}
break;
}
}
// try to convert string to real format
s = RPL_SetBcd(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber));
// try to convert string to complex format
_ASSERT(32 <= ARRAYSIZEOF(byNumber));
s = RPL_SetComplex(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,TRUE);
if ((bSuccess = (dwAddress > 0)))
if (s > 0) // is a real complex
{
Write5(dwAddress,DOREAL); // prolog
Nwrite(byNumber,dwAddress+5,s); // data
_ASSERT(s == 32); // length of complex number BCD coded
// push object to stack
RPL_Push(1,dwAddress);
// get TEMPOB memory for complex object
dwAddress = RPL_CreateTemp(16+16+5,TRUE);
if ((bSuccess = (dwAddress > 0)))
{
Write5(dwAddress,DOCMP); // prolog
Nwrite(byNumber,dwAddress+5,s); // data
// push object to stack
RPL_Push(1,dwAddress);
}
break;
}
break;
}
// any other format
@ -662,7 +798,7 @@ LRESULT OnStackPaste(VOID) // paste data to stack
goto cancel;
KeyboardEvent(TRUE,0,0x8000);
Sleep(200);
Sleep(dwWakeupDelay);
KeyboardEvent(FALSE,0,0x8000);
// wait for sleep mode

259
source/SYMBFILE.C Normal file
View file

@ -0,0 +1,259 @@
/*
* symbfile.c
*
* This file is part of Emu48
*
* Copyright (C) 2008 Christoph Gießelink
*
*/
#include "pch.h"
#include "Emu48.h"
//################
//#
//# Saturn Object File Reading
//#
//################
#define RECORD_BLOCK 256 // block size
#define OS_RESOLVED 0x8000 // resolved symbol
#define OS_RELOCATABLE 0x4000 // relocatable symbol
#define SAT_ID "Saturn3" // saturn block header
#define SYMB_ID "Symb" // symbol block header
#define HASHENTRIES 199 // size of hash table
typedef struct RefData
{
LPTSTR lpszName; // symbol name
DWORD dwAddr; // resolved address
struct RefData* pNext;
} RefData;
static RefData *ppsBase[HASHENTRIES]; // base of symbol references (initialized with NULL)
static __inline DWORD GetHash(DWORD dwVal)
{
return dwVal % HASHENTRIES; // hash function
}
static DWORD GetBigEndian(LPBYTE pbyData, INT nSize)
{
DWORD dwVal = 0;
while (nSize-- > 0)
{
dwVal <<= 8;
dwVal += *pbyData++;
}
return dwVal;
}
//
// check if entry table is empty
//
BOOL RplTableEmpty(VOID)
{
DWORD i;
BOOL bEmpty = TRUE;
// check if hash table is empty
for (i = 0; bEmpty && i < ARRAYSIZEOF(ppsBase); ++i)
{
bEmpty = (ppsBase[i] == NULL); // check if empty
}
return bEmpty;
}
//
// load entry table
//
BOOL RplLoadTable(LPCTSTR lpszFilename)
{
BYTE byPage[RECORD_BLOCK]; // record page size
HANDLE hFile;
DWORD dwFileLength,dwCodeLength,dwNoSymbols,dwNoReferences;
DWORD dwBytesRead,dwSymb,dwPageIndex,dwResolvedSymb;
BOOL bSymbol;
hFile = CreateFile(lpszFilename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
RplDeleteTable(); // delete current table
return FALSE;
}
// read first page
ReadFile(hFile,byPage,sizeof(byPage),&dwBytesRead,NULL);
if ( dwBytesRead != sizeof(byPage)
|| memcmp(byPage,SAT_ID,7) != 0)
{
RplDeleteTable(); // delete current table
CloseHandle(hFile);
return FALSE;
}
// file length in bytes
dwFileLength = GetBigEndian(byPage+7,sizeof(WORD)) * sizeof(byPage);
// code area in nibbles
dwCodeLength = GetBigEndian(byPage+9,sizeof(DWORD));
// no. of symbols & references
dwNoSymbols = GetBigEndian(byPage+13,sizeof(WORD));
// no. of references
dwNoReferences = GetBigEndian(byPage+15,sizeof(WORD));
// convert code area length into no. of pages
dwPageIndex = (dwCodeLength + (2 * sizeof(byPage) - 1)) / (2 * sizeof(byPage));
// jump to begin of symbols by skipping no. of code pages
if (SetFilePointer(hFile,dwPageIndex*sizeof(byPage),NULL,FILE_CURRENT) == INVALID_SET_FILE_POINTER)
{
RplDeleteTable(); // delete current table
CloseHandle(hFile);
return FALSE;
}
dwResolvedSymb = 0; // no resolved symbols added
bSymbol = TRUE; // next set is a symbol
// read all symbol pages
for (dwPageIndex = 256, dwSymb = 0; dwSymb < dwNoSymbols; dwPageIndex += 42)
{
if (dwPageIndex >= 256) // read complete page
{
// read new symbol page
ReadFile(hFile,byPage,sizeof(byPage),&dwBytesRead,NULL);
if ( dwBytesRead != sizeof(byPage)
|| memcmp(byPage,SYMB_ID,4) != 0)
{
RplDeleteTable(); // delete current table
CloseHandle(hFile);
return FALSE;
}
dwPageIndex = 4; // begin of new symbol
}
if (bSymbol) // this is the 42 byte symbol set
{
WORD wSymbolType = (WORD) GetBigEndian(byPage+dwPageIndex+36,sizeof(WORD));
// check if it's a resolved or relocatable symbol
bSymbol = (wSymbolType & OS_RESOLVED) != 0;
if (bSymbol) ++dwResolvedSymb; // added resolved symbol
if (wSymbolType == OS_RESOLVED) // resolved symbol type
{
TCHAR szSymbolName[36+1],*pcPtr;
RefData *pData;
DWORD dwHash;
#if defined _UNICODE
{
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED,byPage+dwPageIndex,36,
szSymbolName,ARRAYSIZEOF(szSymbolName));
szSymbolName[36] = 0; // set EOS
}
#else
{
lstrcpyn(szSymbolName,byPage+dwPageIndex,ARRAYSIZEOF(szSymbolName));
}
#endif
// cut symbol name at first space character
if ((pcPtr = _tcschr(szSymbolName,_T(' '))) != NULL)
*pcPtr = 0; // set EOS
// allocate symbol memory
VERIFY(pData = HeapAlloc(hHeap,0,sizeof(RefData)));
pData->lpszName = DuplicateString(szSymbolName);
pData->dwAddr = GetBigEndian(byPage+dwPageIndex+38,sizeof(DWORD));
// add to hash table
dwHash = GetHash(pData->dwAddr);
pData->pNext = ppsBase[dwHash];
ppsBase[dwHash] = pData;
}
++dwSymb; // got symbol
}
else // 42 byte fill reference
{
bSymbol = TRUE; // nothing to do, next is a symbol set
}
}
_ASSERT(dwResolvedSymb == (dwNoSymbols - dwNoReferences));
CloseHandle(hFile);
return TRUE;
}
//
// delete entry table
//
VOID RplDeleteTable(VOID)
{
RefData *pData;
DWORD i;
// clear hash entries
for (i = 0; i < ARRAYSIZEOF(ppsBase); ++i)
{
while (ppsBase[i] != NULL) // walk through all datasets
{
pData = ppsBase[i]->pNext;
HeapFree(hHeap,0,ppsBase[i]->lpszName);
HeapFree(hHeap,0,ppsBase[i]);
ppsBase[i] = pData;
}
}
return;
}
//
// return name for given entry address
//
LPCTSTR RplGetName(DWORD dwAddr)
{
RefData *pData = ppsBase[GetHash(dwAddr)];
// walk through all datasets of hash entry
for (; pData != NULL; pData = pData->pNext)
{
if (pData->dwAddr == dwAddr) // found address
return pData->lpszName; // return symbol name
}
return NULL;
}
//
// return entry address for given name
//
BOOL RplGetAddr(LPCTSTR lpszName, DWORD *pdwAddr)
{
RefData *pData;
DWORD i;
// check for every dataset in hash table
for (i = 0; i < ARRAYSIZEOF(ppsBase); ++i)
{
// walk through all datasets of hash entry
for (pData = ppsBase[i]; pData != NULL; pData = pData->pNext)
{
// found symbol name
if (lstrcmp(lpszName,pData->lpszName) == 0)
{
*pdwAddr = pData->dwAddr; // return address
return FALSE; // found
}
}
}
return TRUE; // not found
}

View file

@ -292,23 +292,22 @@ VOID SetHP48Time(VOID) // set date and time
{
*p = (BYTE) ticks & 0xf;
crc = (crc >> 4) ^ (((crc ^ ((WORD) *p)) & 0xf) * 0x1081);
Chipset.Port0[dw] = *p; // always store in port0
Port0[dw] = *p; // always store in port0
ticks >>= 4;
}
Nunpack(p,crc,4); // write crc
memcpy(Chipset.Port0+dw,p,4); // always store in port0
memcpy(Port0+dw,p,4); // always store in port0
dw += 4; // HP addresses for timeout
for (i = 0; i < 13; ++i, ++dw) // write time for auto off
{
// always store in port0
Chipset.Port0[dw] = (BYTE) time & 0xf;
Port0[dw] = (BYTE) time & 0xf; // always store in port0
time >>= 4;
}
Chipset.Port0[dw] = 0xf; // always store in port0
Port0[dw] = 0xf; // always store in port0
return;
}

View file

@ -25,9 +25,9 @@ typedef struct
DWORD Port0Size; // real size of module in KB
DWORD Port1Size; // real size of module in KB
DWORD Port2Size; // real size of module in KB (HP49G only)
LPBYTE Port0;
LPBYTE Port1;
LPBYTE Port2;
DWORD dwUnused0; // not used, was memory pointer Port0
DWORD dwUnused1; // not used, was memory pointer Port1
DWORD dwUnused2; // not used, was memory pointer Port2
DWORD pc;
DWORD d0;