diff --git a/EMU48.TXT b/EMU48.TXT index f1121b1..5203c36 100644 --- a/EMU48.TXT +++ b/EMU48.TXT @@ -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 diff --git a/EMU48PLUS.TXT b/EMU48PLUS.TXT index 55b3950..f7910d9 100644 --- a/EMU48PLUS.TXT +++ b/EMU48PLUS.TXT @@ -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 diff --git a/Emu48.dll b/Emu48.dll index 6f0ac4e..e204fb4 100644 Binary files a/Emu48.dll and b/Emu48.dll differ diff --git a/Emu48.exe b/Emu48.exe index b4ba2e1..4b44b5a 100644 Binary files a/Emu48.exe and b/Emu48.exe differ diff --git a/PROBLEMS.TXT b/PROBLEMS.TXT index 49c5ded..b8a2f51 100644 --- a/PROBLEMS.TXT +++ b/PROBLEMS.TXT @@ -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 diff --git a/source/CHANGES.TXT b/source/CHANGES.TXT index 2f455aa..340ff2d 100644 --- a/source/CHANGES.TXT +++ b/source/CHANGES.TXT @@ -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 @@ -144,7 +294,7 @@ DEBUGGER.C - changed function OnDrawCodeWnd(), added draw style for label line - changed function Debugger(), added initialization and uninitialization of smybol table and bold font and added +/- key - handling for memory window + handling for memory window - added functions for Debugger Settings handling - changed function EnterAddr(), added decoding a symbolic entry into an address @@ -549,7 +699,7 @@ RESOURCE.H SETTINGS.C - bugfix in function WriteSettings(), in the INI-File in section - [Files] the item "SaveDefaultConfirm" was missing and saving item + [Files] the item "SaveDefaultConfirm" was missing and saving item "AutoSaveOnExit" was called twice - changed function ReadSettings() and WriteSettings(), removed item "ClassicCursor" from [KML] section in the INI-File diff --git a/source/DDESERV.C b/source/DDESERV.C index 998a110..2ced4d3 100644 --- a/source/DDESERV.C +++ b/source/DDESERV.C @@ -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); diff --git a/source/DEBUGGER.C b/source/DEBUGGER.C index 0f03c77..c638ea6 100644 --- a/source/DEBUGGER.C +++ b/source/DEBUGGER.C @@ -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 diff --git a/source/DISASM.C b/source/DISASM.C index 9954589..944302a 100644 --- a/source/DISASM.C +++ b/source/DISASM.C @@ -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 { diff --git a/source/EMU48.C b/source/EMU48.C index 60e82b1..aad92e5 100644 --- a/source/EMU48.C +++ b/source/EMU48.C @@ -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); diff --git a/source/EMU48.H b/source/EMU48.H index 3d19d61..7a6fea2 100644 --- a/source/EMU48.H +++ b/source/EMU48.H @@ -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 diff --git a/source/EMU48.RC b/source/EMU48.RC index 8f10a73..d632f15 100644 --- a/source/EMU48.RC +++ b/source/EMU48.RC @@ -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" diff --git a/source/EMU48DLL.C b/source/EMU48DLL.C index ecd9e7d..e971ef1 100644 --- a/source/EMU48DLL.C +++ b/source/EMU48DLL.C @@ -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); diff --git a/source/ENGINE.C b/source/ENGINE.C index 6e189bc..7d7f5c6 100644 --- a/source/ENGINE.C +++ b/source/ENGINE.C @@ -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; diff --git a/source/Emu48.dsp b/source/Emu48.dsp index e07260d..60b085f 100644 --- a/source/Emu48.dsp +++ b/source/Emu48.dsp @@ -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 diff --git a/source/FILES.C b/source/FILES.C index 629707e..fec6518 100644 --- a/source/FILES.C +++ b/source/FILES.C @@ -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(); diff --git a/source/KEYBOARD.C b/source/KEYBOARD.C index 53d3dab..9072982 100644 --- a/source/KEYBOARD.C +++ b/source/KEYBOARD.C @@ -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; } diff --git a/source/KEYMACRO.C b/source/KEYMACRO.C index cfed585..80eb82a 100644 --- a/source/KEYMACRO.C +++ b/source/KEYMACRO.C @@ -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: diff --git a/source/KML.C b/source/KML.C index 44f43b8..870dfd0 100644 --- a/source/KML.C +++ b/source/KML.C @@ -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; } diff --git a/source/MOPS.C b/source/MOPS.C index a94749b..1ff578c 100644 --- a/source/MOPS.C +++ b/source/MOPS.C @@ -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; } diff --git a/source/MRU.C b/source/MRU.C index 9e388ef..82c62a9 100644 --- a/source/MRU.C +++ b/source/MRU.C @@ -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; diff --git a/source/OPCODES.C b/source/OPCODES.C index 53ccd40..6874c7e 100644 --- a/source/OPCODES.C +++ b/source/OPCODES.C @@ -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; diff --git a/source/OPS.H b/source/OPS.H index a4a5efb..5312027 100644 --- a/source/OPS.H +++ b/source/OPS.H @@ -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>=4; } + for (; s>0; --s) { *a++ = (BYTE)(b&0xf); b>>=4; } } static __inline QWORD Npack64(BYTE *a, UINT s) diff --git a/source/PCH.H b/source/PCH.H index 468233b..81dddc3 100644 --- a/source/PCH.H +++ b/source/PCH.H @@ -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 diff --git a/source/RPL.C b/source/RPL.C index 88c7e5e..6cd5ff0 100644 --- a/source/RPL.C +++ b/source/RPL.C @@ -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); diff --git a/source/SETTINGS.C b/source/SETTINGS.C index a323e92..6994a51 100644 --- a/source/SETTINGS.C +++ b/source/SETTINGS.C @@ -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); diff --git a/source/STACK.C b/source/STACK.C index 28c605a..e260bef 100644 --- a/source/STACK.C +++ b/source/STACK.C @@ -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 diff --git a/source/SYMBFILE.C b/source/SYMBFILE.C new file mode 100644 index 0000000..3784887 --- /dev/null +++ b/source/SYMBFILE.C @@ -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 +} diff --git a/source/TIMER.C b/source/TIMER.C index b784928..fc830bf 100644 --- a/source/TIMER.C +++ b/source/TIMER.C @@ -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; } diff --git a/source/TYPES.H b/source/TYPES.H index fe25002..1017b06 100644 --- a/source/TYPES.H +++ b/source/TYPES.H @@ -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;