diff --git a/DEFAULTS.BMP b/Defaults.bmp similarity index 85% rename from DEFAULTS.BMP rename to Defaults.bmp index 89a8d5e..fafa9c3 100644 Binary files a/DEFAULTS.BMP and b/Defaults.bmp differ diff --git a/EMU48.EXE b/EMU48.EXE index 8404c62..c5c3586 100755 Binary files a/EMU48.EXE and b/EMU48.EXE differ diff --git a/PROBLEMS.TXT b/PROBLEMS.TXT index 2ee38c8..78ddf5e 100644 --- a/PROBLEMS.TXT +++ b/PROBLEMS.TXT @@ -1,4 +1,4 @@ -Known bugs and restrictions of Emu48 V1.38 +Known bugs and restrictions of Emu48 V1.40 ------------------------------------------ - the following I/O bits aren't emulated (incomplete) @@ -42,8 +42,7 @@ Known bugs and restrictions of Emu48 V1.38 - no MP interrupt on card control circuit or timer restart - no beeper support with OUT command -> all programs that aren't use the "=makebeep" subroutine, like alarm wake up, have no sound -- beeper emulation, ATTN key doesn't work, - Windows 9x: plays only default sound event or standard system beep +- beeper emulation, ATTN key doesn't work - no infrared printer support - Shell OS: clock isn't synchronized with real time - HP49G: the flash memory is emulated now with some restrictions @@ -55,4 +54,4 @@ Known bugs and restrictions of Emu48 V1.38 - quitting the emulator while programming the flash isn't allowed, because the content of flash state machine isn't saved so far -08/30/05 (c) by Christoph Gießelink, c dot giesselink at gmx dot de +12/13/05 (c) by Christoph Gießelink, c dot giesselink at gmx dot de diff --git a/Sources/Emu48/CHANGES.TXT b/Sources/Emu48/CHANGES.TXT index 313ac93..250027e 100644 --- a/Sources/Emu48/CHANGES.TXT +++ b/Sources/Emu48/CHANGES.TXT @@ -1,3 +1,133 @@ +Service Pack 40 for Emu48 Version 1.0 + +DISPLAY.C +- bugfix in function UpdateContrast(), used background Color 0 in + calculator off state even if Color 32 was defined +- bugfix in function CreateLcdBitmap(), DIB section shouldn't + created from the memory DC + +EMU48.C +- added function IsPort2Writeable() to check if read only file + attribute is not set on port2 file +- major changes in function SettingsProc(), added "Port 2 is + Writeable" handling and make port2 changeable without closing the + current emulation session +- changed function SaveChanges(), default button for confirming the + "Do you want to save changes ?" message depends now on the + "SaveDefaultConfirm" INI-File setting (1=yes / 0=no button) + +EMU48.H +- extern declaration of global variable and functions + +EMU48.RC +- added item "Port 2 is Writeable" in settings dialog +- changed version + +ENGINE.C +- bugfix in function WorkerThread(), when changing into SM_RUN state + display constrast must also be restored + +FILES.C +- changed function CrcPort2(), made it global accessible + +KML.C +- added keywords "Topbar" and "Vga" to pLexToken[] table -> scripts + using these keywords now are parsed with warnings and not quit + with a fatal error any more +- bugfix in function SkipWhite(), skipping remark text hadn't stop + at string end +- bugfix in function ParseBlocks(), stopped script parsing without + error at unknown block token +- bugfix in function SkipLines(), TOK_END was handeled wrong -> + this caused a RunKey end if condition of TOK_IFPRESSED or + TOK_IFFLAG was false and there was no TOK_ELSE inside this level +- bugfix in function KillKML(), ROM type wasn't reset to the preset + value at the end + +KML.H +- added TOK_TOPBAR and TOK_VGA definition + +RESOURCE.H +- added definition + +RPL.C +- added function RPL_GetSystemFlag() returning the state of the + given system flag + +SETTINGS.C +- changed function ReadSettings() and WriteSettings(), added item + "SaveDefaultConfirm" in section [File] in the INI-File + +STACK.C +- added helper functions RPL_GetZInt() and RPL_SetZInt() to handle + HP49G Precision Integer objects +- added function DoInt() to handle a HP49G Precision Integer object +- changed function OnStackCopy() and OnStackPaste(), added HP49G + Precision Integer support (limited to 127/128 digits incl. sign) + +TIMER.C +- changed function CheckT1() and CheckT2(), minor optimization in + checking if INT or WAKE bit is set + + +Service Pack 39 for Emu48 Version 1.0 + +DISPLAY.C +- bugfix in function CreateMainBitmap(), in error case hMainDC + variable wasn't cleared + +EMU48.C +- changed function SettingsProc(), added sound handling +- moved function OnStackCopy() and OnStackPaste() to STACK.C +- changed function WinMain(), added accelerator key access for menus + +EMU48.DSP +- added stack.c sources + +EMU48.H +- extern declaration of global variables and functions + +EMU48.RC +- added "Sound" group in Settings dialog +- changed menu text "Copy String" to "Copy Stack" and menu text + "Paste String" to "Paste Stack" +- added accelerator resource +- changed version + +EXTERNAL.C +- added function BeepWave(), beeper function using sound card +- added function BeepWin9x(), PC speaker function for working on + Win9x +- changed function External(), removed range checking of duration; + call function BeepWin9x() on Win9x instead of Beep() or in the + case of wave sound the function BeepWave() + +KML.C +- bugfix in function InitKML(), changed log message for no "Model" + definition found and a missing "Bitmap" definition wasn't detected + +PCH.H +- added include conio.h + +RESOURCE.H +- added several definitions + +SETTINGS.C +- changed function ReadSettings() and WriteSettings(), added item + "WaveBeep" and "WaveVolume" in section [Emulator] in the INI-File + +STACK.C +- new modul with the message handler functions OnStackCopy() and + OnStackPaste() prior located in EMU48.C +- changed function OnStackCopy() and OnStackPaste(), they can now + also copy real numbers from and to the clipboard + +TIMER.C +- bugfix in function SetT1(), fixed unsynchronized access to timer1 + value, stop timer1 only if running and restart timer1 only when + timer2 is running + + Service Pack 38 for Emu48 Version 1.0 DISPLAY.C diff --git a/Sources/Emu48/DISPLAY.C b/Sources/Emu48/DISPLAY.C index 88a6999..311339f 100644 --- a/Sources/Emu48/DISPLAY.C +++ b/Sources/Emu48/DISPLAY.C @@ -124,15 +124,20 @@ static __inline VOID BuildPattern(VOID) VOID UpdateContrast(BYTE byContrast) { + RGBQUAD c,b; INT i,nColors; // table for max. 8 colors const INT nCAdj[] = { 0, 1, 1, 2, 1, 2, 2, 3 }; - RGBQUAD c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color - RGBQUAD b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color - if ((Chipset.IORam[BITOFFSET] & DON) == 0 || I == *(DWORD*)&b) - b = *(RGBQUAD*)&dwKMLColor[0]; + // when display is off use contrast 0 + if ((Chipset.IORam[BITOFFSET] & DON) == 0) byContrast = 0; + + c = *(RGBQUAD*)&dwKMLColor[byContrast]; // pixel on color + b = *(RGBQUAD*)&dwKMLColor[byContrast+32]; // pixel off color + + // if background color is undefined, use color 0 for compatibility + if (I == *(DWORD*)&b) b = *(RGBQUAD*)&dwKMLColor[0]; nColors = bGrayscale ? (NOCOLORSGRAY-1) : (NOCOLORSBW-1); @@ -189,7 +194,7 @@ VOID CreateLcdBitmap(VOID) bmiLcd.Lcd_bmih.biHeight = -64 * nLcdZoom; _ASSERT(hLcdDC == NULL); VERIFY(hLcdDC = CreateCompatibleDC(hWindowDC)); - VERIFY(hLcdBitmap = CreateDIBSection(hLcdDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0)); + VERIFY(hLcdBitmap = CreateDIBSection(hWindowDC,(BITMAPINFO*)&bmiLcd,DIB_RGB_COLORS,(VOID **)&pbyLcd,NULL,0)); hLcdBitmap = SelectObject(hLcdDC,hLcdBitmap); _ASSERT(hPalette != NULL); SelectPalette(hLcdDC,hPalette,FALSE); // set palette for LCD DC @@ -230,6 +235,7 @@ BOOL CreateMainBitmap(LPCTSTR szFilename) if (hMainBitmap == NULL) { DeleteDC(hMainDC); + hMainDC = NULL; return FALSE; } hMainBitmap = SelectObject(hMainDC,hMainBitmap); diff --git a/Sources/Emu48/EMU48.C b/Sources/Emu48/EMU48.C index 1d771f7..73921c6 100644 --- a/Sources/Emu48/EMU48.C +++ b/Sources/Emu48/EMU48.C @@ -13,7 +13,7 @@ #include "kml.h" #include "debugger.h" -#define VERSION "1.38" +#define VERSION "1.40" #define CF_HPOBJ "CF_HPOBJ" // clipboard format for DDE #define MAXPORTS 256 // number of COM ports @@ -80,6 +80,7 @@ HCURSOR hCursorHand = NULL; BOOL bClassicCursor = FALSE; // use hand instead of arrow cursor BOOL bAutoSave = FALSE; BOOL bAutoSaveOnExit = TRUE; +BOOL bSaveDefConfirm = TRUE; // yes BOOL bAlwaysDisplayLog = TRUE; BOOL bLoadObjectWarning = TRUE; @@ -221,6 +222,21 @@ VOID CopyItemsToClipboard(HWND hWnd) // save selected Listbox Items to Clipboar //# //################ +// get R/W state of port2 file +static BOOL IsPort2Writeable(VOID) +{ + DWORD dwFileAtt; + + BOOL bWriteable = FALSE; + + SetCurrentDirectory(szEmuDirectory); + dwFileAtt = GetFileAttributes(szPort2Filename); + if (dwFileAtt != 0xFFFFFFFF) + bWriteable = ((dwFileAtt & FILE_ATTRIBUTE_READONLY) == 0); + SetCurrentDirectory(szCurrentDirectory); + return bWriteable; +} + // set listfield for serial combobox static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting) { @@ -257,6 +273,9 @@ static VOID SetCommList(HWND hDlg,int nIDDlgItem,LPCTSTR szSetting) static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lParam) { + BOOL bPort2CfgChange = FALSE; + BOOL bPort2AttChange = FALSE; + switch (message) { case WM_INITDIALOG: @@ -271,6 +290,15 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP // set disassebler mode CheckDlgButton(hDlg,(disassembler_mode == HP_MNEMONICS) ? IDC_DISASM_HP : IDC_DISASM_CLASS,BST_CHECKED); + // set sound slider + SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETRANGE,FALSE,MAKELONG(0,255)); + SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETTICFREQ,256/8,0); + SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_SETPOS,TRUE,dwWaveVol); + + // set sound radio button + CheckDlgButton(hDlg,bWaveBeep ? IDC_SOUND_WAVE : IDC_SOUND_SPEAKER,BST_CHECKED); + EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),bWaveBeep); + // set combobox parameter SetCommList(hDlg,IDC_WIRE,szSerialWire); SetCommList(hDlg,IDC_IR,szSerialIr); @@ -281,13 +309,14 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP } // HP48SX/GX - if (cCurrentRomType=='S' || cCurrentRomType=='G') + if (cCurrentRomType=='S' || cCurrentRomType=='G' || cCurrentRomType==0) { // init port1 enable checkbox CheckDlgButton(hDlg,IDC_PORT1EN,(Chipset.cards_status & PORT1_PRESENT) != 0); CheckDlgButton(hDlg,IDC_PORT1WR,(Chipset.cards_status & PORT1_WRITE) != 0); - // init port2 shared checkbox and set port2 filename + // init port2 shared and writeable checkbox and set port2 filename CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared); + CheckDlgButton(hDlg,IDC_PORT2WR,IsPort2Writeable()); SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename); if (nState == SM_INVALID) // Invalid State { @@ -299,29 +328,26 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP { EnableWindow(GetDlgItem(hDlg,IDC_PORT1EN),FALSE); EnableWindow(GetDlgItem(hDlg,IDC_PORT1WR),FALSE); - if (nState == SM_INVALID) // Invalid State - { - // init port2 shared checkbox and set port2 filename - CheckDlgButton(hDlg,IDC_PORT2ISSHARED,bPort2IsShared); - SetDlgItemText(hDlg,IDC_PORT2,szPort2Filename); - } + EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_PORT2WR),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE); + EnableWindow(GetDlgItem(hDlg,IDC_PORT2LOAD),FALSE); if (cCurrentRomType=='X') // HP49G { SendDlgItemMessage(hDlg,IDC_IR,CB_RESETCONTENT,0,0); EnableWindow(GetDlgItem(hDlg,IDC_IR),FALSE); } } - if (nState != SM_INVALID) // not in Invalid State - { - // hide port2 settings - EnableWindow(GetDlgItem(hDlg,IDC_PORT2ISSHARED),FALSE); - EnableWindow(GetDlgItem(hDlg,IDC_PORT2),FALSE); - EnableWindow(GetDlgItem(hDlg,IDC_PORT2LOAD),FALSE); - } return TRUE; case WM_COMMAND: switch (LOWORD(wParam)) { + case IDC_SOUND_SPEAKER: + EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),FALSE); + return TRUE; + case IDC_SOUND_WAVE: + EnableWindow(GetDlgItem(hDlg,IDC_SOUND_SLIDER),TRUE); + return TRUE; case IDC_PORT2LOAD: if (GetLoadObjectFilename()) { @@ -366,9 +392,37 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP Chipset.SoftInt = TRUE; // set interrupt bInterrupt = TRUE; } - Map(0x00,0xFF); SwitchToState(nOldState); } + // HP48SX/GX port2 change settings detection + if(cCurrentRomType=='S' || cCurrentRomType=='G' || cCurrentRomType==0) + { + TCHAR szFilename[MAX_PATH]; + BOOL bPortShared; + + // shared port + bPortShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED); + if (bPort2IsShared != bPortShared) + { + bPort2IsShared = bPortShared; + bPort2CfgChange = TRUE; // slot2 configuration changed + } + + // get current filename and notify difference + GetDlgItemText(hDlg,IDC_PORT2,szFilename,ARRAYSIZEOF(szFilename)); + if (lstrcmp(szPort2Filename,szFilename) != 0) + { + lstrcpyn(szPort2Filename,szFilename,ARRAYSIZEOF(szPort2Filename)); + bPort2CfgChange = TRUE; // slot2 configuration changed + } + + // R/W port + if (IsDlgButtonChecked(hDlg,IDC_PORT2WR) != (UINT) IsPort2Writeable()) + { + bPort2AttChange = TRUE; // slot2 file R/W attribute changed + bPort2CfgChange = TRUE; // slot2 configuration changed + } + } // get speed checkbox value bRealSpeed = IsDlgButtonChecked(hDlg,IDC_REALSPEED); bAutoSave = IsDlgButtonChecked(hDlg, IDC_AUTOSAVE); @@ -383,13 +437,54 @@ static BOOL CALLBACK SettingsProc(HWND hDlg, UINT message, DWORD wParam, LONG lP SetLcdMode(!bGrayscale); // set new display mode SwitchToState(nOldState); } - if (nState == SM_INVALID) + if (bPort2CfgChange) // slot2 configuration changed { - bPort2IsShared = IsDlgButtonChecked(hDlg,IDC_PORT2ISSHARED); - GetDlgItemText(hDlg,IDC_PORT2,szPort2Filename,ARRAYSIZEOF(szPort2Filename)); + UINT nOldState = SwitchToState(SM_INVALID); + + UnmapPort2(); // unmap port2 + + if (bPort2AttChange) // slot2 R/W mode changed + { + DWORD dwFileAtt; + + SetCurrentDirectory(szEmuDirectory); + dwFileAtt = GetFileAttributes(szPort2Filename); + if (dwFileAtt != 0xFFFFFFFF) + { + if (IsDlgButtonChecked(hDlg,IDC_PORT2WR)) + dwFileAtt &= ~FILE_ATTRIBUTE_READONLY; + else + dwFileAtt |= FILE_ATTRIBUTE_READONLY; + + SetFileAttributes(szPort2Filename,dwFileAtt); + } + SetCurrentDirectory(szCurrentDirectory); + } + + if (cCurrentRomType) // ROM defined + { + // use 2nd command line argument if defined + MapPort2((nArgc < 3) ? szPort2Filename : ppArgv[2]); + // port2 changed and card detection enabled + if ( (bPort2AttChange || Chipset.wPort2Crc != CrcPort2()) + && (Chipset.IORam[CARDCTL] & ECDT) != 0 && (Chipset.IORam[TIMER2_CTRL] & RUN) != 0 + ) + { + Chipset.HST |= MP; // set Module Pulled + IOBit(SRQ2,NINT,FALSE); // set NINT to low + Chipset.SoftInt = TRUE; // set interrupt + bInterrupt = TRUE; + } + // save fingerprint of port2 + Chipset.wPort2Crc = CrcPort2(); + } + SwitchToState(nOldState); } - // set disassebler mode + // set disassembler mode disassembler_mode = IsDlgButtonChecked(hDlg,IDC_DISASM_HP) ? HP_MNEMONICS : CLASS_MNEMONICS; + // set sound data + dwWaveVol = SendDlgItemMessage(hDlg,IDC_SOUND_SLIDER,TBM_GETPOS,0,0); + bWaveBeep = IsDlgButtonChecked(hDlg,IDC_SOUND_WAVE); // set combobox parameter GetDlgItemText(hDlg,IDC_WIRE,szSerialWire,ARRAYSIZEOF(szSerialWire)); if (cCurrentRomType!='X') // HP49G Ir port is not connected @@ -427,7 +522,11 @@ static UINT SaveChanges(BOOL bAuto) if (bAuto) uReply = IDYES; else - uReply = YesNoCancelMessage(_T("Do you want to save changes ?")); + { + UINT uStyle = bSaveDefConfirm ? 0 : MB_DEFBUTTON2; + + uReply = YesNoCancelMessage(_T("Do you want to save changes ?"),uStyle); + } if (uReply != IDYES) return uReply; @@ -739,148 +838,6 @@ static LRESULT OnFileExit(VOID) return 0; } -// -// ID_STACK_COPY -// -static LRESULT OnStackCopy(VOID) // copy data from stack -{ - HANDLE hClipObj; - LPBYTE lpData; - DWORD dwAddress,dwSize; - - _ASSERT(nState == SM_RUN); // emulator must be in RUN state - if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state - { - InfoMessage(_T("The emulator is busy.")); - return 0; - } - - _ASSERT(nState == SM_SLEEP); - - if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object - { - MessageBeep(MB_OK); // error beep - goto error; - } - - if (Read5(dwAddress) != 0x02A2C) // string object - { - MessageBeep(MB_OK); // error beep - goto error; - } - - dwAddress += 5; // address of string length - dwSize = (Read5(dwAddress) - 5) / 2; // length of string - - // memory allocation for clipboard data - if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize + 1)) == NULL) - goto error; - - if ((lpData = GlobalLock(hClipObj))) // lock memory - { - // copy data into clipboard buffer - for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpData) - *lpData = Read2(dwAddress); - *lpData = 0; // set end of string - - GlobalUnlock(hClipObj); // unlock memory - - if (OpenClipboard(hWnd)) - { - if (EmptyClipboard()) - SetClipboardData(CF_TEXT,hClipObj); - else - GlobalFree(hClipObj); - CloseClipboard(); - } - } - else // lock memory failed - { - GlobalFree(hClipObj); - } - -error: - SwitchToState(SM_RUN); - return 0; -} - -// -// ID_STACK_PASTE -// -static LRESULT OnStackPaste(VOID) // paste data to stack -{ - HANDLE hClipObj; - LPBYTE lpClipdata,lpData; - - BOOL bSuccess = FALSE; - - // check if clipboard format is available - if (!IsClipboardFormatAvailable(CF_TEXT)) - { - MessageBeep(MB_OK); // error beep - return 0; - } - - SuspendDebugger(); // suspend debugger - bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control - - // calculator off, turn on - if (!(Chipset.IORam[BITOFFSET]&DON)) - { - KeyboardEvent(TRUE,0,0x8000); - KeyboardEvent(FALSE,0,0x8000); - - // wait for sleep mode - while(Chipset.Shutdn == FALSE) Sleep(0); - } - - _ASSERT(nState == SM_RUN); // emulator must be in RUN state - if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state - { - InfoMessage(_T("The emulator is busy.")); - goto cancel; - } - - _ASSERT(nState == SM_SLEEP); - - if (OpenClipboard(hWnd)) - { - if ((hClipObj = GetClipboardData(CF_TEXT))) - { - if ((lpClipdata = GlobalLock(hClipObj))) - { - DWORD dwSize = strlen(lpClipdata); - if ((lpData = HeapAlloc(hHeap,0,dwSize * 2))) - { - memcpy(lpData+dwSize,lpClipdata,dwSize); // copy data - bSuccess = (WriteStack(lpData,dwSize) == S_ERR_NO); - HeapFree(hHeap,0,lpData); - } - GlobalUnlock(hClipObj); - } - } - CloseClipboard(); - } - - SwitchToState(SM_RUN); // run state - while (nState!=nNextState) Sleep(0); - _ASSERT(nState == SM_RUN); - - if (bSuccess == FALSE) // data not copied - goto cancel; - - KeyboardEvent(TRUE,0,0x8000); - KeyboardEvent(FALSE,0,0x8000); - - // wait for sleep mode - while(Chipset.Shutdn == FALSE) Sleep(0); - -cancel: - bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control - ResumeDebugger(); - return 0; -} - // // ID_VIEW_COPY // @@ -1127,7 +1084,7 @@ static LRESULT OnObjectLoad(VOID) _T("Warning: Trying to load an object while the emulator is busy\n") _T("will certainly result in a memory lost. Before loading an object\n") _T("you should be sure that the calculator is not doing anything.\n") - _T("Do you want to see this warning next time you try to load an object ?")); + _T("Do you want to see this warning next time you try to load an object ?"),0); switch (uReply) { case IDYES: @@ -1452,6 +1409,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC MSG msg; WNDCLASS wc; RECT rectWindow; + HACCEL hAccel; HSZ hszService, hszTopic; // variables for DDE server DWORD dwAffMask; @@ -1514,6 +1472,8 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC return FALSE; } + VERIFY(hAccel = LoadAccelerators(hInst, MAKEINTRESOURCE(IDR_MENU))); + // initialization QueryPerformanceFrequency(&lFreq); // init high resolution counter QueryPerformanceCounter(&lAppStart); @@ -1607,7 +1567,8 @@ start: while (GetMessage(&msg, NULL, 0, 0)) { - if( (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg)) + if( !TranslateAccelerator(hWnd, hAccel, &msg) + && (hDlgDebug == NULL || !IsDialogMessage(hDlgDebug, &msg)) && (hDlgFind == NULL || !IsDialogMessage(hDlgFind, &msg)) && (hDlgProfile == NULL || !IsDialogMessage(hDlgProfile, &msg))) { diff --git a/Sources/Emu48/EMU48.DSP b/Sources/Emu48/EMU48.DSP index dcdb6e8..3c0391f 100644 --- a/Sources/Emu48/EMU48.DSP +++ b/Sources/Emu48/EMU48.DSP @@ -7,21 +7,21 @@ CFG=Emu48 - Win32 Release !MESSAGE This is not a valid makefile. To build this project using NMAKE, !MESSAGE use the Export Makefile command and run -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Emu48.mak". -!MESSAGE +!MESSAGE !MESSAGE You can specify a configuration when running NMAKE !MESSAGE by defining the macro CFG on the command line. For example: -!MESSAGE +!MESSAGE !MESSAGE NMAKE /f "Emu48.mak" CFG="Emu48 - Win32 Release" -!MESSAGE +!MESSAGE !MESSAGE Possible choices for configuration are: -!MESSAGE +!MESSAGE !MESSAGE "Emu48 - Win32 Release" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Debug" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Release Unicode" (based on "Win32 (x86) Application") !MESSAGE "Emu48 - Win32 Debug Unicode" (based on "Win32 (x86) Application") -!MESSAGE +!MESSAGE # Begin Project # PROP AllowPerConfigDependencies 0 @@ -137,7 +137,7 @@ LINK32=link.exe # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 # ADD LINK32 kernel32.lib user32.lib gdi32.lib comdlg32.lib shell32.lib winmm.lib comctl32.lib advapi32.lib /nologo /subsystem:windows /debug /machine:I386 -!ENDIF +!ENDIF # Begin Target @@ -235,6 +235,10 @@ SOURCE=.\settings.c # End Source File # Begin Source File +SOURCE=.\stack.c +# End Source File +# Begin Source File + SOURCE=.\timer.c # End Source File # End Group diff --git a/Sources/Emu48/EMU48.H b/Sources/Emu48/EMU48.H index c9529c6..856fc89 100644 --- a/Sources/Emu48/EMU48.H +++ b/Sources/Emu48/EMU48.H @@ -93,6 +93,7 @@ extern HCURSOR hCursorHand; extern BOOL bClassicCursor; extern BOOL bAutoSave; extern BOOL bAutoSaveOnExit; +extern BOOL bSaveDefConfirm; extern BOOL bAlwaysDisplayLog; extern BOOL bLoadObjectWarning; extern HANDLE hThread; @@ -203,6 +204,7 @@ extern VOID UpdatePatches(BOOL bPatch); extern BOOL PatchRom(LPCTSTR szFilename); extern BOOL MapRom(LPCTSTR szFilename); extern VOID UnmapRom(VOID); +extern WORD CrcPort2(VOID); extern BOOL MapPort2(LPCTSTR szFilename); extern VOID UnmapPort2(VOID); extern VOID ResetDocument(VOID); @@ -268,7 +270,12 @@ extern LRESULT OnToolMacroPlay(VOID); extern LRESULT OnToolMacroStop(VOID); extern LRESULT OnToolMacroSettings(VOID); +// Stack.c +extern LRESULT OnStackCopy(VOID); +extern LRESULT OnStackPaste(VOID); + // RPL.c +extern BOOL RPL_GetSystemFlag(INT nFlag); extern DWORD RPL_SkipOb(DWORD d); extern DWORD RPL_ObjectSize(BYTE *o); extern DWORD RPL_CreateTemp(DWORD l); @@ -277,7 +284,9 @@ extern VOID RPL_Replace(DWORD n); extern VOID RPL_Push(DWORD n); // External.c -extern VOID External(CHIPSET* w); +extern BOOL bWaveBeep; +extern DWORD dwWaveVol; +extern VOID External(CHIPSET* w); // DDEserv.c extern HDDEDATA CALLBACK DdeCallback(UINT, UINT, HCONV, HSZ, HSZ, HDDEDATA, DWORD, DWORD); @@ -310,7 +319,7 @@ extern BOOL DLLDestroyWnd(VOID); static __inline int InfoMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONINFORMATION|MB_SETFOREGROUND);} static __inline int AbortMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_OK|MB_ICONSTOP|MB_SETFOREGROUND);} static __inline int YesNoMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNO|MB_ICONEXCLAMATION|MB_SETFOREGROUND);} -static __inline int YesNoCancelMessage(LPCTSTR szMessage) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND);} +static __inline int YesNoCancelMessage(LPCTSTR szMessage,UINT uStyle) {return MessageBox(hWnd, szMessage, szTitle, MB_APPLMODAL|MB_YESNOCANCEL|MB_ICONEXCLAMATION|MB_SETFOREGROUND|uStyle);} // Missing Win32 API calls static __inline LPTSTR DuplicateString(LPCTSTR szString) diff --git a/Sources/Emu48/EMU48.RC b/Sources/Emu48/EMU48.RC index 92ed6ef..c8a4d0e 100644 --- a/Sources/Emu48/EMU48.RC +++ b/Sources/Emu48/EMU48.RC @@ -74,7 +74,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 160 TOPMARGIN, 4 - BOTTOMMARGIN, 222 + BOTTOMMARGIN, 256 END IDD_CHOOSEKML, DIALOG @@ -232,15 +232,15 @@ BEGIN ES_READONLY END -IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 229 +IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 263 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings" FONT 8, "MS Sans Serif" BEGIN CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,13,13,100,10 - CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10 + CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10 CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,13,37,89,10 CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT, @@ -255,25 +255,35 @@ BEGIN CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button", BS_AUTORADIOBUTTON,84,101,70,11 GROUPBOX "Disassembler",IDC_STATIC,7,90,153,28 + LTEXT "Volume",IDC_STATIC,13,134,24,8 + CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32", + TBS_AUTOTICKS | WS_TABSTOP,39,129,68,18 + CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,111,128,43,10 + CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,111, + 139,43,10 + GROUPBOX "Sound",IDC_STATIC,7,120,153,34 CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,13,131,67,10 + WS_TABSTOP,13,165,67,10 CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,84,131,69,10 + BS_AUTOCHECKBOX | WS_TABSTOP,84,165,69,10 CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,143,65,10 - LTEXT "Port 2 File :",IDC_STATIC,13,159,37,8 - EDITTEXT IDC_PORT2,51,156,94,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_PORT2LOAD,145,156,10,12 - GROUPBOX "Memory Cards",IDC_STATIC,7,122,153,51 - LTEXT "Wire:",IDC_STATIC,13,188,17,8 - COMBOBOX IDC_WIRE,31,186,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | + BS_AUTOCHECKBOX | WS_TABSTOP,13,177,65,10 + CONTROL "Port 2 is Writeable",IDC_PORT2WR,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,84,177,69,10 + LTEXT "Port 2 File :",IDC_STATIC,13,192,37,8 + EDITTEXT IDC_PORT2,51,190,94,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_PORT2LOAD,145,190,10,12 + GROUPBOX "Memory Cards",IDC_STATIC,7,156,153,51 + LTEXT "Wire:",IDC_STATIC,13,221,17,8 + COMBOBOX IDC_WIRE,31,219,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "IR:",IDC_STATIC,89,188,9,8 - COMBOBOX IDC_IR,107,186,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | + LTEXT "IR:",IDC_STATIC,89,221,9,8 + COMBOBOX IDC_IR,107,219,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Serial Ports",IDC_STATIC,7,176,153,27 - DEFPUSHBUTTON "&Ok",IDOK,9,208,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,107,208,50,14 + GROUPBOX "Serial Ports",IDC_STATIC,7,209,153,27 + DEFPUSHBUTTON "&Ok",IDOK,9,242,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,107,242,50,14 END IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66 @@ -492,7 +502,7 @@ BEGIN LTEXT "Fast",IDC_MACRO_FAST,78,16,14,8,WS_DISABLED CONTROL "Slider1",IDC_MACRO_SLIDER,"msctls_trackbar32", TBS_AUTOTICKS | WS_DISABLED | WS_TABSTOP,12,26,82,21 - CONTROL "&Real",IDC_MACRO_REAL,"Button",BS_AUTORADIOBUTTON | + CONTROL "&Real",IDC_MACRO_REAL,"Button",BS_AUTORADIOBUTTON | WS_GROUP | WS_TABSTOP,103,18,39,10 CONTROL "&Manual",IDC_MACRO_MANUAL,"Button",BS_AUTORADIOBUTTON, 103,32,39,10 @@ -538,8 +548,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,8,0 - PRODUCTVERSION 1,3,8,0 + FILEVERSION 1,4,0,0 + PRODUCTVERSION 1,4,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -556,12 +566,12 @@ BEGIN BEGIN VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" - VALUE "FileVersion", "1, 3, 8, 0\0" + VALUE "FileVersion", "1, 4, 0, 0\0" VALUE "InternalName", "Emu48\0" VALUE "LegalCopyright", "Copyright © 2005\0" VALUE "OriginalFilename", "Emu48.exe\0" VALUE "ProductName", "Emu48\0" - VALUE "ProductVersion", "1, 3, 8, 0\0" + VALUE "ProductVersion", "1, 4, 0, 0\0" END END BLOCK "VarFileInfo" @@ -607,8 +617,8 @@ BEGIN MENUITEM "&Save Object...", ID_OBJECT_SAVE MENUITEM SEPARATOR MENUITEM "C&opy Screen", ID_VIEW_COPY - MENUITEM "&Copy String", ID_STACK_COPY - MENUITEM "&Paste String", ID_STACK_PASTE + MENUITEM "&Copy Stack", ID_STACK_COPY + MENUITEM "&Paste Stack", ID_STACK_PASTE MENUITEM SEPARATOR MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED POPUP "&Backup" @@ -755,6 +765,25 @@ END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// 24 +// + +CREATEPROCESS_MANIFEST_RESOURCE_ID 24 MOVEABLE PURE "Emu48.xml" + +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MENU ACCELERATORS DISCARDABLE +BEGIN + "C", ID_STACK_COPY, VIRTKEY, CONTROL, NOINVERT + "V", ID_STACK_PASTE, VIRTKEY, CONTROL, NOINVERT +END + + ///////////////////////////////////////////////////////////////////////////// // // String Table @@ -773,14 +802,6 @@ BEGIN ID_BREAKPOINTS_CODEEDIT "Breakpoint List" END - -///////////////////////////////////////////////////////////////////////////// -// -// Manifest -// - -CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST "Emu48.xml" - #endif // English (U.S.) resources ///////////////////////////////////////////////////////////////////////////// diff --git a/Sources/Emu48/ENGINE.C b/Sources/Emu48/ENGINE.C index dd30ef7..3dde5be 100644 --- a/Sources/Emu48/ENGINE.C +++ b/Sources/Emu48/ENGINE.C @@ -549,6 +549,7 @@ loop: IOBit(SRQ2,NINT,bNINT); } RomSwitch(Chipset.Bank_FF); // select HP49G ROM bank and update memory mapping + UpdateContrast(Chipset.contrast); UpdateDisplayPointers(); UpdateMainDisplay(); UpdateMenuDisplay(); diff --git a/Sources/Emu48/EXTERNAL.C b/Sources/Emu48/EXTERNAL.C index dbffcd1..71315da 100644 --- a/Sources/Emu48/EXTERNAL.C +++ b/Sources/Emu48/EXTERNAL.C @@ -4,12 +4,15 @@ * This file is part of Emu48 * * Copyright (C) 1995 Sebastien Carlier + * Copyright (C) 2005 Christoph Gießelink * */ #include "pch.h" #include "Emu48.h" #include "ops.h" +#define MUSIC_FREQ 11025 // this can be adjusted for quality + //| 38G | 39G | 40G | 48SX | 48GX | 49G | Name //#F0E4F #80F0F #80F0F #706D2 #80850 #80F0F =SFLAG53_56 @@ -28,6 +31,102 @@ ) \ ) +BOOL bWaveBeep = FALSE; // PC speaker +DWORD dwWaveVol = 64; // wave sound volume + +static __inline VOID BeepWave(DWORD dwFrequency,DWORD dwDuration) +{ + HWAVEOUT hSoundDevice; + WAVEFORMATEX wf; + WAVEHDR wh; + HANDLE hEventSound; + DWORD i; + + if (dwFrequency == 0) // this is just a delay + { + Sleep(dwDuration); + return; + } + + hEventSound = CreateEvent(NULL,FALSE,FALSE,NULL); + + wf.wFormatTag = WAVE_FORMAT_PCM; + wf.nChannels = 1; + wf.nSamplesPerSec = MUSIC_FREQ; + wf.nAvgBytesPerSec = MUSIC_FREQ; + wf.nBlockAlign = 1; + wf.wBitsPerSample = 8; + wf.cbSize = 0; + + if (waveOutOpen(&hSoundDevice,WAVE_MAPPER,&wf,(DWORD)hEventSound,0,CALLBACK_EVENT) != 0) + { + CloseHandle(hEventSound); // no sound available + return; + } + + // (samp/sec) * msecs * (secs/msec) = samps + wh.dwBufferLength = (DWORD) ((QWORD) MUSIC_FREQ * dwDuration / 1000); + VERIFY(wh.lpData = HeapAlloc(hHeap,0,wh.dwBufferLength)); + wh.dwBytesRecorded = 0; + wh.dwUser = 0; + wh.dwFlags = 0; + wh.dwLoops = 0; + + for (i = 0; i < wh.dwBufferLength; ++i) // generate square wave + { + wh.lpData[i] = (BYTE) ((((QWORD) 2 * dwFrequency * i / MUSIC_FREQ) & 1) * dwWaveVol); + } + + VERIFY(waveOutPrepareHeader(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR); + + ResetEvent(hEventSound); // prepare event for finishing + VERIFY(waveOutWrite(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR); + WaitForSingleObject(hEventSound,INFINITE); // wait for finishing + + VERIFY(waveOutUnprepareHeader(hSoundDevice,&wh,sizeof(wh)) == MMSYSERR_NOERROR); + VERIFY(waveOutClose(hSoundDevice) == MMSYSERR_NOERROR); + + HeapFree(hHeap,0,wh.lpData); + CloseHandle(hEventSound); + return; +} + +static __inline VOID BeepWin9x(DWORD dwFrequency,DWORD dwDuration) +{ + #define PIT8254_CNT2 0x42 + #define PIT8254_MCR 0x43 + #define PPI8255_PBO 0x61 + + BYTE bySpk = _inp(PPI8255_PBO); // get current status + + if (dwFrequency != 0) + { + WORD wCount; + + // limit low frequency + if (lFreq.QuadPart / 65535 >= dwFrequency) + dwFrequency = (DWORD) (lFreq.QuadPart / 65535) + 1; + + // determine the timer frequency + wCount = (WORD) (lFreq.QuadPart / dwFrequency); + + _outp(PIT8254_MCR,0xB6); // set up the timer + + _outp(PIT8254_CNT2,wCount&0xff); + _outp(PIT8254_CNT2,wCount>>8); + + _outp(PPI8255_PBO,bySpk | 0x03); // turn on the speaker + } + + Sleep(dwDuration); + + _outp(PPI8255_PBO,bySpk & 0xFC); // turn off the speaker + return; + #undef PIT8254_CNT2 + #undef PIT8254_MCR + #undef PPI8255_PBO +} + static __inline VOID Return(CHIPSET* w) { w->rstkp=(w->rstkp-1)&7; @@ -48,13 +147,30 @@ VOID External(CHIPSET* w) // Beep patch w->carry = TRUE; // setting of no beep if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz { - if (freq < 37) freq = 37; // low limit of freqency (NT) if (freq > 4400) freq = 4400; // high limit of HP (SX) - if (dur > 1048575) // high limit of HP (SX) - dur = 1048575; + if (bWaveBeep) + { + BeepWave(freq,dur); // wave output over sound card + } + else + { + OSVERSIONINFO version; + version.dwOSVersionInfoSize = sizeof(version); + GetVersionEx(&version); - Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep + if (version.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) + { + BeepWin9x(freq,dur); // do it the hard way on '9x / Me + } + else // VER_PLATFORM_WIN32_NT + { + if (freq < 37) freq = 37; // low limit of freqency (NT) + + _ASSERT(freq >= 0x25 && freq <= 0x7FFF); + Beep(freq,dur); // NT: ok, Windows 95: default sound or standard system beep + } + } // estimate cpu cycles for beeping time (2MHz / 4MHz) w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000); diff --git a/Sources/Emu48/FILES.C b/Sources/Emu48/FILES.C index a40c120..ffa1e10 100644 --- a/Sources/Emu48/FILES.C +++ b/Sources/Emu48/FILES.C @@ -422,7 +422,7 @@ VOID UnmapRom(VOID) //# //################ -static WORD CrcPort2(VOID) // calculate fingerprint of port2 +WORD CrcPort2(VOID) // calculate fingerprint of port2 { DWORD dwCount; DWORD dwFileSize; diff --git a/Sources/Emu48/KML.C b/Sources/Emu48/KML.C index ca657b6..c92c4e5 100644 --- a/Sources/Emu48/KML.C +++ b/Sources/Emu48/KML.C @@ -83,6 +83,7 @@ static KmlToken pLexToken[] = {TOK_IFFLAG, 000001, 6,_T("IfFlag")}, {TOK_ONDOWN, 000000, 6,_T("OnDown")}, {TOK_NOHOLD, 000000, 6,_T("NoHold")}, + {TOK_TOPBAR, 000001, 6,_T("Topbar")}, // for PPC compatibility reasons {TOK_TITLE, 000002, 5,_T("Title")}, {TOK_OUTIN, 000011, 5,_T("OutIn")}, {TOK_PATCH, 000002, 5,_T("Patch")}, @@ -100,6 +101,7 @@ static KmlToken pLexToken[] = {TOK_ONUP, 000000, 4,_T("OnUp")}, {TOK_MAP, 000011, 3,_T("Map")}, {TOK_ROM, 000002, 3,_T("Rom")}, + {TOK_VGA, 000001, 3,_T("Vga")}, // for PPC compatibility reasons {TOK_LCD, 000000, 3,_T("Lcd")}, {TOK_END, 000000, 3,_T("End")}, {0, 000000, 0,_T("")}, @@ -574,7 +576,7 @@ loop: } if (*szText==_T('#')) { - do szText++; while (*szText != _T('\n')); + do szText++; while (*szText != _T('\n') && *szText != 0); if (nMode != LEX_PARAM) goto loop; } return; @@ -1024,6 +1026,11 @@ static KmlBlock* ParseBlocks(VOID) } } if (pFirst) pBlock->pNext = NULL; + if (*szText != 0) // still KML text left + { + FatalError(); // error unknown block token + goto abort; + } return pFirst; abort: if (pFirst) FreeBlocks(pFirst); @@ -1288,8 +1295,9 @@ static KmlLine* SkipLines(KmlLine* pLine, TokenId eCommand) while (pLine) { if (IsBlock(pLine->eCommand)) nLevel++; - if (pLine->eCommand==eCommand) + if (pLine->eCommand == eCommand) { + // found token, return command behind token if (nLevel == 0) return pLine->pNext; } if (pLine->eCommand == TOK_END) @@ -1297,7 +1305,7 @@ static KmlLine* SkipLines(KmlLine* pLine, TokenId eCommand) if (nLevel) nLevel--; else - return NULL; + break; } pLine = pLine->pNext; } @@ -1467,6 +1475,7 @@ VOID KillKML(VOID) nBackgroundW = 256; nBackgroundH = 0; nLcdZoom = 1; + cCurrentRomType = 0; UpdateWindowStatus(); ResizeWindow(); return; @@ -2156,7 +2165,7 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog) if (cCurrentRomType == 0) { - AddToLog(_T("This KML Script doesn't specify the ROM Type.")); + AddToLog(_T("This KML Script doesn't specify the model.")); goto quit; } if (pbyRom == NULL) @@ -2164,6 +2173,12 @@ BOOL InitKML(LPCTSTR szFilename, BOOL bNoLog) AddToLog(_T("This KML Script doesn't specify the ROM to use, or the ROM could not be loaded.")); goto quit; } + if (hMainDC == NULL) + { + AddToLog(_T("This KML Script doesn't specify the background bitmap, or bitmap could not be loaded.")); + goto quit; + } + CreateLcdBitmap(); PrintfToLog(_T("%i Buttons Defined"), nButtons); diff --git a/Sources/Emu48/KML.H b/Sources/Emu48/KML.H index 07ed190..262db65 100644 --- a/Sources/Emu48/KML.H +++ b/Sources/Emu48/KML.H @@ -35,27 +35,29 @@ typedef enum eTokenId TOK_IFFLAG, //19 TOK_ONDOWN, //20 TOK_NOHOLD, //21 - TOK_TITLE, //22 - TOK_OUTIN, //23 - TOK_PATCH, //24 - TOK_PRINT, //25 - TOK_DEBUG, //26 - TOK_COLOR, //27 - TOK_MODEL, //28 - TOK_CLASS, //29 - TOK_PRESS, //30 - TOK_TYPE, //31 - TOK_SIZE, //32 - TOK_DOWN, //33 - TOK_ZOOM, //34 - TOK_ELSE, //35 - TOK_ONUP, //36 - TOK_EOL, //37 - TOK_MAP, //38 - TOK_ROM, //39 - TOK_LCD, //40 - TOK_NOTFLAG, //41 - TOK_END //42 + TOK_TOPBAR, //22 + TOK_TITLE, //23 + TOK_OUTIN, //24 + TOK_PATCH, //25 + TOK_PRINT, //26 + TOK_DEBUG, //27 + TOK_COLOR, //28 + TOK_MODEL, //29 + TOK_CLASS, //30 + TOK_PRESS, //31 + TOK_TYPE, //32 + TOK_SIZE, //33 + TOK_DOWN, //34 + TOK_ZOOM, //35 + TOK_ELSE, //36 + TOK_ONUP, //37 + TOK_EOL, //38 + TOK_MAP, //39 + TOK_ROM, //40 + TOK_VGA, //41 + TOK_LCD, //42 + TOK_NOTFLAG, //43 + TOK_END //44 } TokenId; #define TYPE_NONE 00 diff --git a/Sources/Emu48/PCH.H b/Sources/Emu48/PCH.H index 5dfe309..34d1989 100644 --- a/Sources/Emu48/PCH.H +++ b/Sources/Emu48/PCH.H @@ -13,6 +13,7 @@ #include #include #include +#include #include #if !defined VERIFY diff --git a/Sources/Emu48/RESOURCE.H b/Sources/Emu48/RESOURCE.H index b7ab665..e22d0af 100644 --- a/Sources/Emu48/RESOURCE.H +++ b/Sources/Emu48/RESOURCE.H @@ -36,116 +36,120 @@ #define IDC_PORT1EN 1006 #define IDC_PORT1WR 1007 #define IDC_PORT2ISSHARED 1008 -#define IDC_PORT2 1009 -#define IDC_PORT2LOAD 1010 -#define IDC_WIRE 1011 -#define IDC_IR 1012 -#define IDC_EMUDIR 1013 -#define IDC_EMUDIRSEL 1014 -#define IDC_UPDATE 1015 -#define IDC_KMLSCRIPT 1016 -#define IDC_AUTHOR 1017 -#define IDC_TITLE 1018 -#define IDC_KMLLOG 1019 -#define IDC_VERSION 1020 -#define IDC_LICENSE 1021 -#define IDC_DISASM_WIN 1022 -#define IDC_DISASM_MAP 1023 -#define IDC_DISASM_ROM 1024 -#define IDC_DISASM_RAM 1025 -#define IDC_DISASM_PORT1 1026 -#define IDC_DISASM_PORT2 1027 -#define IDC_DISASM_MODULE 1028 -#define IDC_DISASM_HP 1029 -#define IDC_DISASM_CLASS 1030 -#define IDC_ADDRESS 1031 -#define IDC_DISASM_ADR 1032 -#define IDC_DISASM_NEXT 1033 -#define IDC_DISASM_COPY 1034 -#define IDC_DEBUG_CODE 1035 -#define IDC_STATIC_CODE 1036 -#define IDC_STATIC_REGISTERS 1037 -#define IDC_STATIC_MEMORY 1038 -#define IDC_STATIC_STACK 1039 -#define IDC_REG_A 1040 -#define IDC_REG_B 1041 -#define IDC_REG_C 1042 -#define IDC_REG_D 1043 -#define IDC_REG_R0 1044 -#define IDC_REG_R1 1045 -#define IDC_REG_R2 1046 -#define IDC_REG_R3 1047 -#define IDC_REG_R4 1048 -#define IDC_REG_D0 1049 -#define IDC_REG_D1 1050 -#define IDC_REG_P 1051 -#define IDC_REG_PC 1052 -#define IDC_REG_OUT 1053 -#define IDC_REG_IN 1054 -#define IDC_REG_ST 1055 -#define IDC_REG_CY 1056 -#define IDC_REG_MODE 1057 -#define IDC_REG_MP 1058 -#define IDC_REG_SR 1059 -#define IDC_REG_SB 1060 -#define IDC_REG_XM 1061 -#define IDC_MISC_INT 1062 -#define IDC_MISC_KEY 1063 -#define IDC_MISC_BS 1064 -#define IDC_NEWVALUE 1065 -#define IDC_ENTERADR 1066 -#define IDC_DEBUG_MEM 1067 -#define IDC_DEBUG_MEM_ADDR 1068 -#define IDC_DEBUG_MEM_COL0 1069 -#define IDC_DEBUG_MEM_COL1 1070 -#define IDC_DEBUG_MEM_COL2 1071 -#define IDC_DEBUG_MEM_COL3 1072 -#define IDC_DEBUG_MEM_COL4 1073 -#define IDC_DEBUG_MEM_COL5 1074 -#define IDC_DEBUG_MEM_COL6 1075 -#define IDC_DEBUG_MEM_COL7 1076 -#define IDC_DEBUG_MEM_TEXT 1077 -#define IDC_DEBUG_STACK 1078 -#define IDC_STATIC_BREAKPOINT 1079 -#define IDC_BREAKEDIT_ADD 1080 -#define IDC_BREAKEDIT_DELETE 1081 -#define IDC_BREAKEDIT_WND 1082 -#define IDC_STATIC_MMU 1083 -#define IDC_MMU_IO_A 1084 -#define IDC_MMU_NCE2_A 1085 -#define IDC_MMU_CE1_A 1086 -#define IDC_MMU_CE2_A 1087 -#define IDC_MMU_NCE3_A 1088 -#define IDC_MMU_IO_S 1089 -#define IDC_MMU_CE1_S 1090 -#define IDC_MMU_CE2_S 1091 -#define IDC_MMU_NCE2_S 1092 -#define IDC_MMU_NCE3_S 1093 -#define IDC_STATIC_MISC 1094 -#define IDC_MISC_BS_TXT 1095 -#define IDC_INSTR_TEXT 1096 -#define IDC_INSTR_CODE 1097 -#define IDC_INSTR_COPY 1098 -#define IDC_INSTR_CLEAR 1099 -#define IDC_PROFILE_LASTCYCLES 1100 -#define IDC_PROFILE_LASTTIME 1101 -#define IDC_BPCODE 1102 -#define IDC_BPRPL 1103 -#define IDC_BPACCESS 1104 -#define IDC_BPREAD 1105 -#define IDC_BPWRITE 1106 -#define IDC_FIND_DATA 1107 -#define IDC_FIND_ASCII 1108 -#define IDC_FIND_CASE 1109 -#define IDC_ADDR20_24 1110 -#define IDC_ADDR25_27 1111 -#define IDC_ADDR28_29 1112 -#define IDC_ADDR30_34 1113 -#define IDC_MACRO_SLOW 1114 -#define IDC_MACRO_FAST 1115 -#define IDC_MACRO_SLIDER 1116 -#define IDC_MACRO_REAL 1117 -#define IDC_MACRO_MANUAL 1118 +#define IDC_PORT2WR 1009 +#define IDC_PORT2 1010 +#define IDC_PORT2LOAD 1011 +#define IDC_WIRE 1012 +#define IDC_IR 1013 +#define IDC_EMUDIR 1014 +#define IDC_EMUDIRSEL 1015 +#define IDC_UPDATE 1016 +#define IDC_KMLSCRIPT 1017 +#define IDC_AUTHOR 1018 +#define IDC_TITLE 1019 +#define IDC_KMLLOG 1020 +#define IDC_VERSION 1021 +#define IDC_LICENSE 1022 +#define IDC_DISASM_WIN 1023 +#define IDC_DISASM_MAP 1024 +#define IDC_DISASM_ROM 1025 +#define IDC_DISASM_RAM 1026 +#define IDC_DISASM_PORT1 1027 +#define IDC_DISASM_PORT2 1028 +#define IDC_DISASM_MODULE 1029 +#define IDC_DISASM_HP 1030 +#define IDC_DISASM_CLASS 1031 +#define IDC_ADDRESS 1032 +#define IDC_DISASM_ADR 1033 +#define IDC_DISASM_NEXT 1034 +#define IDC_DISASM_COPY 1035 +#define IDC_DEBUG_CODE 1036 +#define IDC_STATIC_CODE 1037 +#define IDC_STATIC_REGISTERS 1038 +#define IDC_STATIC_MEMORY 1039 +#define IDC_STATIC_STACK 1040 +#define IDC_REG_A 1041 +#define IDC_REG_B 1042 +#define IDC_REG_C 1043 +#define IDC_REG_D 1044 +#define IDC_REG_R0 1045 +#define IDC_REG_R1 1046 +#define IDC_REG_R2 1047 +#define IDC_REG_R3 1048 +#define IDC_REG_R4 1049 +#define IDC_REG_D0 1050 +#define IDC_REG_D1 1051 +#define IDC_REG_P 1052 +#define IDC_REG_PC 1053 +#define IDC_REG_OUT 1054 +#define IDC_REG_IN 1055 +#define IDC_REG_ST 1056 +#define IDC_REG_CY 1057 +#define IDC_REG_MODE 1058 +#define IDC_REG_MP 1059 +#define IDC_REG_SR 1060 +#define IDC_REG_SB 1061 +#define IDC_REG_XM 1062 +#define IDC_MISC_INT 1063 +#define IDC_MISC_KEY 1064 +#define IDC_MISC_BS 1065 +#define IDC_NEWVALUE 1066 +#define IDC_ENTERADR 1067 +#define IDC_DEBUG_MEM 1068 +#define IDC_DEBUG_MEM_ADDR 1069 +#define IDC_DEBUG_MEM_COL0 1070 +#define IDC_DEBUG_MEM_COL1 1071 +#define IDC_DEBUG_MEM_COL2 1072 +#define IDC_DEBUG_MEM_COL3 1073 +#define IDC_DEBUG_MEM_COL4 1074 +#define IDC_DEBUG_MEM_COL5 1075 +#define IDC_DEBUG_MEM_COL6 1076 +#define IDC_DEBUG_MEM_COL7 1077 +#define IDC_DEBUG_MEM_TEXT 1078 +#define IDC_DEBUG_STACK 1079 +#define IDC_STATIC_BREAKPOINT 1080 +#define IDC_BREAKEDIT_ADD 1081 +#define IDC_BREAKEDIT_DELETE 1082 +#define IDC_BREAKEDIT_WND 1083 +#define IDC_STATIC_MMU 1084 +#define IDC_MMU_IO_A 1085 +#define IDC_MMU_NCE2_A 1086 +#define IDC_MMU_CE1_A 1087 +#define IDC_MMU_CE2_A 1088 +#define IDC_MMU_NCE3_A 1089 +#define IDC_MMU_IO_S 1090 +#define IDC_MMU_CE1_S 1091 +#define IDC_MMU_CE2_S 1092 +#define IDC_MMU_NCE2_S 1093 +#define IDC_MMU_NCE3_S 1094 +#define IDC_STATIC_MISC 1095 +#define IDC_MISC_BS_TXT 1096 +#define IDC_INSTR_TEXT 1097 +#define IDC_INSTR_CODE 1098 +#define IDC_INSTR_COPY 1099 +#define IDC_INSTR_CLEAR 1100 +#define IDC_PROFILE_LASTCYCLES 1101 +#define IDC_PROFILE_LASTTIME 1102 +#define IDC_BPCODE 1103 +#define IDC_BPRPL 1104 +#define IDC_BPACCESS 1105 +#define IDC_BPREAD 1106 +#define IDC_BPWRITE 1107 +#define IDC_FIND_DATA 1108 +#define IDC_FIND_ASCII 1109 +#define IDC_FIND_CASE 1110 +#define IDC_ADDR20_24 1111 +#define IDC_ADDR25_27 1112 +#define IDC_ADDR28_29 1113 +#define IDC_ADDR30_34 1114 +#define IDC_MACRO_SLOW 1115 +#define IDC_MACRO_FAST 1116 +#define IDC_MACRO_SLIDER 1117 +#define IDC_MACRO_REAL 1118 +#define IDC_MACRO_MANUAL 1119 +#define IDC_SOUND_SLIDER 1120 +#define IDC_SOUND_SPEAKER 1121 +#define IDC_SOUND_WAVE 1122 #define ID_FILE_NEW 40001 #define ID_FILE_OPEN 40002 #define ID_FILE_SAVE 40003 @@ -212,7 +216,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 123 #define _APS_NEXT_COMMAND_VALUE 40062 -#define _APS_NEXT_CONTROL_VALUE 1119 +#define _APS_NEXT_CONTROL_VALUE 1122 #define _APS_NEXT_SYMED_VALUE 108 #endif #endif diff --git a/Sources/Emu48/RPL.C b/Sources/Emu48/RPL.C index 8b84931..147fab4 100644 --- a/Sources/Emu48/RPL.C +++ b/Sources/Emu48/RPL.C @@ -18,13 +18,15 @@ //#F0697 #806F8 #806F8 #70579 #806F8 #806F8 =DSKTOP (D1) //#F0DEA #80E9B #80E9B #7066E #807ED #80E9B =AVMEM (D) //#F0705 #8076B #8076B #705B0 #8072F #8076B =INTRPPTR (D0) +// #80F02 #80F02 #706C5 #80843 #80F02 =SystemFlags -#define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9) -#define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE) -#define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3) -#define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8) -#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B) -#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B) +#define TEMPOB ((cCurrentRomType=='S')?0x7056A:0x806E9) +#define TEMPTOP ((cCurrentRomType=='S')?0x7056F:0x806EE) +#define RSKTOP ((cCurrentRomType=='S')?0x70574:0x806F3) +#define DSKTOP ((cCurrentRomType=='S')?0x70579:0x806F8) +#define AVMEM ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x7066E:0x807ED):0x80E9B) +#define INTRPPTR ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x705B0:0x8072F):0x8076B) +#define SYSTEMFLAGS ((cCurrentRomType!='X')?((cCurrentRomType=='S')?0x706C5:0x80843):0x80F02) #define DOINT 0x02614 // Precision Integer (HP49G) #define DOLNGREAL 0x0263A // Precision Real (HP49G) @@ -93,6 +95,21 @@ static BOOL Metakernel(VOID) return bMkDetect; } +BOOL RPL_GetSystemFlag(INT nFlag) +{ + DWORD dwAddr; + BYTE byMask,byFlag; + + _ASSERT(nFlag > 0); // first flag is 1 + + // calculate memory address and bit mask + dwAddr = SYSTEMFLAGS + (nFlag - 1) / 4; + byMask = 1 << ((nFlag - 1) & 0x3); + + Npeek(&byFlag,dwAddr,sizeof(byFlag)); + return (byFlag & byMask) != 0; +} + DWORD RPL_SkipOb(DWORD d) { BYTE X[8]; diff --git a/Sources/Emu48/SETTINGS.C b/Sources/Emu48/SETTINGS.C index 63dc282..0a68aa7 100644 --- a/Sources/Emu48/SETTINGS.C +++ b/Sources/Emu48/SETTINGS.C @@ -141,6 +141,7 @@ VOID ReadSettings(VOID) ReadString(_T("Files"),_T("Emu48Directory"),szCurrentDirectory,szEmuDirectory,ARRAYSIZEOF(szEmuDirectory)); bAutoSave = ReadInt(_T("Files"),_T("AutoSave"),bAutoSave); bAutoSaveOnExit = ReadInt(_T("Files"),_T("AutoSaveOnExit"),bAutoSaveOnExit); + bSaveDefConfirm = ReadInt(_T("Files"),_T("SaveDefaultConfirm"),bSaveDefConfirm); bLoadObjectWarning = ReadInt(_T("Files"),_T("LoadObjectWarning"),bLoadObjectWarning); // Port2 bPort2IsShared = ReadInt(_T("Port2"),_T("IsShared"),bPort2IsShared); @@ -152,9 +153,11 @@ VOID ReadSettings(VOID) disassembler_mode = ReadInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode); // Emulator bRealSpeed = ReadInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed); - bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale); dwSXCycles = ReadInt(_T("Emulator"),_T("SXCycles"),dwSXCycles); dwGXCycles = ReadInt(_T("Emulator"),_T("GXCycles"),dwGXCycles); + bGrayscale = ReadInt(_T("Emulator"),_T("Grayscale"),bGrayscale); + bWaveBeep = ReadInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep); + dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol); SetSpeed(bRealSpeed); // set speed // Macro bMacroRealSpeed = ReadInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed); @@ -174,6 +177,7 @@ VOID WriteSettings(VOID) WriteString(_T("Files"),_T("Emu48Directory"),szEmuDirectory); WriteInt(_T("Files"),_T("AutoSave"),bAutoSave); WriteInt(_T("Files"),_T("AutoSaveOnExit"),bAutoSaveOnExit); + WriteInt(_T("Files"),_T("SaveDefaultConfirm"),bSaveDefConfirm); WriteInt(_T("Files"),_T("LoadObjectWarning"),bLoadObjectWarning); // Port2 WriteInt(_T("Port2"),_T("IsShared"),bPort2IsShared); @@ -185,9 +189,11 @@ VOID WriteSettings(VOID) WriteInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode); // Emulator WriteInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed); - WriteInt(_T("Emulator"),_T("Grayscale"),bGrayscale); WriteInt(_T("Emulator"),_T("SXCycles"),dwSXCycles); WriteInt(_T("Emulator"),_T("GXCycles"),dwGXCycles); + WriteInt(_T("Emulator"),_T("Grayscale"),bGrayscale); + WriteInt(_T("Emulator"),_T("WaveBeep"),bWaveBeep); + WriteInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol); // Macro WriteInt(_T("Macro"),_T("RealSpeed"),bMacroRealSpeed); WriteInt(_T("Macro"),_T("ReplayTimeout"),nMacroTimeout); diff --git a/Sources/Emu48/STACK.C b/Sources/Emu48/STACK.C new file mode 100644 index 0000000..48f6e50 --- /dev/null +++ b/Sources/Emu48/STACK.C @@ -0,0 +1,646 @@ +/* + * stack.c + * + * This file is part of Emu48 + * + * Copyright (C) 2005 Christoph Gießelink + * + */ +#include "pch.h" +#include "resource.h" +#include "Emu48.h" +#include "io.h" + +#define fnRadix 51 // fraction mark +#define fnApprox 105 // exact / approx. mode (HP49G) + +#define DOINT 0x02614 // Precision Integer (HP49G) +#define DOREAL 0x02933 // Real +#define DOCSTR 0x02A2C // String + +//################ +//# +//# Low level subroutines +//# +//################ + +static INT RPL_GetZInt(BYTE CONST *pbyNum,INT nIntLen,LPTSTR cp,INT nSize) +{ + INT i = 0; // character counter + + _ASSERT(nSize > 0); // target buffer size + + if (nIntLen > 1) // has sign nibble + { + --nIntLen; // remove sign from digit length + + // check for valid sign + _ASSERT(pbyNum[nIntLen] == 0 || pbyNum[nIntLen] == 9); + if (pbyNum[nIntLen] == 9) // negative number + { + *cp++ = _T('-'); // add sign + --nSize; // dec dest buffer size + ++i; // wrote one character + } + } + + if (nIntLen >= nSize) return 0; // dest buffer overflow + i += nIntLen; // adjust character counter + + while (nIntLen-- > 0) // write all digits + { + // check for valid digit + _ASSERT(pbyNum[nIntLen] >= 0 && pbyNum[nIntLen] <= 9); + *cp++ = _T('0') + pbyNum[nIntLen]; // and write + } + *cp = 0; // set EOS + return i; +} + +static INT RPL_SetZInt(LPCTSTR cp,LPBYTE pbyNum,INT nSize) +{ + BYTE bySign; + INT nStrLen,nNumSize; + + _ASSERT(nSize > 0); // target buffer size + + nStrLen = lstrlen(cp); // source string length + + if ( nStrLen == 0 // empty string + // precisition integer contain only these numbers + || _tcsspn(cp,_T("0123456789+-")) != (SIZE_T) nStrLen) + return 0; + + bySign = (*cp != _T('-')) ? 0 : 9; // set sign nibble + if (*cp == _T('-') || *cp == _T('+')) // skip sign character + { + ++cp; + --nStrLen; + } + + if (nStrLen == 1 && *cp == _T('0')) // special code for zero + { + *pbyNum = 0; // zero data + return 1; // finish + } + + // nStrLen = no. of digits without sign + if (nStrLen >= nSize) // destination buffer too small + return 0; + + nNumSize = nStrLen + 1; // no. of written data + + while (--nStrLen >= 0) // eval all digits + { + TCHAR c = cp[nStrLen]; + + // only '0' .. '9' are valid here + if (!((c >= _T('0')) || (c <= _T('9')))) + return 0; + + c -= _T('0'); + *pbyNum++ = (BYTE) c; + } + *pbyNum = bySign; // add sign + + return nNumSize; +} + +static INT RPL_GetBcd(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPTSTR cp,INT nSize) +{ + BYTE byNib; + LONG v,lExp; + BOOL bPflag,bExpflag; + INT i; + + lExp = 0; + for (v = 1; nExpLen--; v *= 10) // fetch exponent + { + lExp += (LONG) *pbyNum++ * v; // calc. exponent + } + + if (lExp > v / 2) lExp -= v; // negative exponent + + lExp -= nMantLen - 1; // set decimal point to end of mantissa + + i = 0; // first character + bPflag = FALSE; // show no decimal point + + // scan mantissa + for (v = (LONG) nMantLen - 1; v >= 0 || bPflag; v--) + { + if (v >= 0L) // still mantissa digits left + byNib = *pbyNum++; + else + byNib = 0; // zero for negativ exponent + + if (!i) // still delete zeros at end + { + if (byNib == 0 && lExp && v > 0) // delete zeros + { + lExp++; // adjust exponent + continue; + } + + // TRUE at x.E + bExpflag = v + lExp > 14 || v + lExp < -nMantLen; + bPflag = !bExpflag && v < -lExp; // decimal point flag at neg. exponent + } + + // set decimal point + if ((bExpflag && v == 0) || (!lExp && i)) + { + if (i >= nSize) return 0; // dest buffer overflow + cp[i++] = cDec; // write decimal point + if (v < 0) // no mantissa digits any more + { + if (i >= nSize) return 0; // dest buffer overflow + cp[i++] = _T('0'); // write heading zero + } + bPflag = FALSE; // finished with negativ exponents + } + + if (v >= 0 || bPflag) + { + if (i >= nSize) return 0; // dest buffer overflow + cp[i++] = (TCHAR) byNib + _T('0'); // write character + } + + lExp++; // next position + } + + if (*pbyNum == 9) // negative number + { + if (i >= nSize) return 0; // dest buffer overflow + cp[i++] = _T('-'); // write sign + } + + if (i >= nSize) return 0; // dest buffer overflow + cp[i] = 0; // set EOS + + for (v = 0; v < (i / 2); v++) // reverse string + { + TCHAR cNib = cp[v]; // swap chars + cp[v] = cp[i-v-1]; + cp[i-v-1] = cNib; + } + + // write number with exponent + if (bExpflag) + { + if (i + 5 >= nSize) return 0; // dest buffer overflow + i += wsprintf(&cp[i],_T("E%d"),lExp-1); + } + return i; +} + +static INT RPL_SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize) +{ + TCHAR cVc[] = _T(".0123456789eE+-"); + + BYTE byNum[80]; + INT i,nIp,nDp,nMaxExp; + LONG lExp; + + cVc[0] = cDec; // replace decimal char + + if ( nMantLen + nExpLen >= nSize // destination buffer too small + || !*cp // empty string + || _tcsspn(cp,cVc) != (SIZE_T) lstrlen(cp) // real contain only these numbers + || lstrlen(cp) >= ARRAYSIZEOF(byNum)) // ignore too long reals + return 0; + + byNum[0] = (*cp != _T('-')) ? 0 : 9; // set sign nibble + if (*cp == _T('-') || *cp == _T('+')) // skip sign character + cp++; + + // only '.', '0' .. '9' are valid here + if (!((*cp == cDec) || (*cp >= _T('0')) || (*cp <= _T('9')))) + return 0; + + nIp = 0; // length of integer part + if (*cp != cDec) // no decimal point + { + // count integer part + while (*cp >= _T('0') && *cp <= _T('9')) + byNum[++nIp] = *cp++ - _T('0'); + if (!nIp) return 0; + } + + // only '.', 'E', 'e' or end are valid here + if (!(!*cp || (*cp == cDec) || (*cp == _T('E')) || (*cp == _T('e')))) + return 0; + + nDp = 0; // length of decimal part + if (*cp == cDec) // decimal point + { + cp++; // skip '.' + + // count decimal part + while (*cp >= _T('0') && *cp <= _T('9')) + byNum[nIp + ++nDp] = *cp++ - _T('0'); + } + + // count number of heading zeros in mantissa + for (i = 0; byNum[i+1] == 0 && i + 1 < nIp + nDp; ++i) { } + + if (i > 0) // have to normalize + { + INT j; + + nIp -= i; // for later ajust of exponent + for (j = 1; j <= nIp + nDp; ++j) // normalize mantissa + byNum[j] = byNum[j + i]; + } + + if(byNum[1] == 0) // number is 0 + { + ZeroMemory(pbyNum,nMantLen + nExpLen + 1); + return nMantLen + nExpLen + 1; + } + + for (i = nIp + nDp; i < nMantLen;) // fill rest of mantissa with 0 + byNum[++i] = 0; + + // must be 'E', 'e' or end + if (!(!*cp || (*cp == _T('E')) || (*cp == _T('e')))) + return 0; + + lExp = 0; + if (*cp == _T('E') || *cp == _T('e')) + { + cp++; // skip 'E' + + i = FALSE; // positive exponent + if (*cp == _T('-') || *cp == _T('+')) + { + i = (*cp++ == _T('-')); // adjust exponent sign + } + + // exponent symbol must be followed by number + if (*cp < _T('0') || *cp > _T('9')) return 0; + + while (*cp >= _T('0') && *cp <= _T('9')) + lExp = lExp * 10 + *cp++ - _T('0'); + + if(i) lExp = -lExp; + } + + if (*cp != 0) return 0; + + // adjust exponent value with exponent from normalized mantissa + lExp += nIp - 1; + + // calculate max. posive exponent + for (nMaxExp = 5, i = 1; i < nExpLen; ++i) + nMaxExp *= 10; + + // check range of exponent + if ((lExp < 0 && -lExp >= nMaxExp) || (lExp >= nMaxExp)) + return 0; + + if (lExp < 0) lExp += 2 * nMaxExp; // adjust negative offset + + for (i = nExpLen; i > 0; --i) // convert number into digits + { + byNum[nMantLen + i] = lExp % 10; + lExp /= 10; + } + + // copy to target in reversed order + for (i = nMantLen + nExpLen; i >= 0; --i) + *pbyNum++ = byNum[i]; + + return nMantLen + nExpLen + 1; +} + +//################ +//# +//# Object subroutines +//# +//################ + +#if 0 +static INT IsRealNumber(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize) +{ + LPTSTR lpszNumber; + INT nLength = 0; + + if ((lpszNumber = DuplicateString(cp)) != NULL) + { + LPTSTR p = lpszNumber; + INT i; + + // cut heading whitespaces + for (; *p == _T(' ') || *p == _T('\t'); ++p) { } + + // cut tailing whitespaces + for (i = lstrlen(p); --i >= 0;) + { + if (p[i] != _T(' ') && p[i] != _T('\t')) + break; + } + p[++i] = 0; // new EOS + + nLength = RPL_SetBcd(p,nMantLen,nExpLen,cDec,pbyNum,nSize); + HeapFree(hHeap,0,lpszNumber); + } + return nLength; +} +#endif + +static TCHAR GetRadix(VOID) +{ + // get locale decimal point + // GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,&cDecimal,1); + + return RPL_GetSystemFlag(fnRadix) ? _T(',') : _T('.'); +} + +static INT DoInt(DWORD dwAddress,LPTSTR cp,INT nSize) +{ + LPBYTE lpbyData; + INT nLength,nIntLen; + + nIntLen = Read5(dwAddress) - 5; // no. of digits + if (nIntLen <= 0) return 0; // error in calculator object + + nLength = 0; + if ((lpbyData = HeapAlloc(hHeap,0,nIntLen))) + { + // get precisition integer object content and decode it + Npeek(lpbyData,dwAddress+5,nIntLen); + nLength = RPL_GetZInt(lpbyData,nIntLen,cp,nSize); + HeapFree(hHeap,0,lpbyData); + } + return nLength; +} + +static INT DoReal(DWORD dwAddress,LPTSTR cp,INT nSize) +{ + BYTE byNumber[16]; + + // get real object content and decode it + Npeek(byNumber,dwAddress,ARRAYSIZEOF(byNumber)); + return RPL_GetBcd(byNumber,12,3,GetRadix(),cp,nSize); +} + + +//################ +//# +//# Stack routines +//# +//################ + +// +// ID_STACK_COPY +// +LRESULT OnStackCopy(VOID) // copy data from stack +{ + TCHAR cBuffer[128]; + HANDLE hClipObj; + LPBYTE lpbyData; + DWORD dwAddress,dwObject,dwSize; + UINT uClipboardFormat; + + _ASSERT(nState == SM_RUN); // emulator must be in RUN state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state + { + InfoMessage(_T("The emulator is busy.")); + return 0; + } + + _ASSERT(nState == SM_SLEEP); + + if ((dwAddress = RPL_Pick(1)) == 0) // pick address of level1 object + { + MessageBeep(MB_OK); // error beep + goto error; + } + + switch (dwObject = Read5(dwAddress)) // select object + { + case DOINT: // Precision Integer (HP49G) + case DOREAL: // real object + dwAddress += 5; // object content + + switch (dwObject) + { + case DOINT: // Precision Integer (HP49G) + // get precision integer object content and decode it + dwSize = DoInt(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer)); + break; + case DOREAL: // real object + // get real object content and decode it + dwSize = DoReal(dwAddress,cBuffer,ARRAYSIZEOF(cBuffer)); + break; + } + + // calculate buffer size + dwSize = (dwSize + 1) * sizeof(*cBuffer); + + // memory allocation for clipboard data + if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize)) == NULL) + goto error; + + if ((lpbyData = GlobalLock(hClipObj))) + { + // copy data to memory + CopyMemory(lpbyData,cBuffer,dwSize); + GlobalUnlock(hClipObj); // unlock memory + } + + #if defined _UNICODE + uClipboardFormat = CF_UNICODETEXT; + #else + uClipboardFormat = CF_TEXT; + #endif + break; + case DOCSTR: // string + dwAddress += 5; // address of string length + dwSize = (Read5(dwAddress) - 5) / 2; // length of string + + // memory allocation for clipboard data + if ((hClipObj = GlobalAlloc(GMEM_MOVEABLE,dwSize + 1)) == NULL) + goto error; + + if ((lpbyData = GlobalLock(hClipObj))) // lock memory + { + // copy data into clipboard buffer + for (dwAddress += 5;dwSize-- > 0;dwAddress += 2,++lpbyData) + *lpbyData = Read2(dwAddress); + *lpbyData = 0; // set EOS + + GlobalUnlock(hClipObj); // unlock memory + uClipboardFormat = CF_TEXT; // always text + } + break; + default: + MessageBeep(MB_OK); // error beep + goto error; + } + + if (OpenClipboard(hWnd)) + { + if (EmptyClipboard()) + SetClipboardData(uClipboardFormat,hClipObj); + else + GlobalFree(hClipObj); + CloseClipboard(); + } + else // clipboard open failed + { + GlobalFree(hClipObj); + } + +error: + SwitchToState(SM_RUN); + return 0; +} + +// +// ID_STACK_PASTE +// +LRESULT OnStackPaste(VOID) // paste data to stack +{ + #if defined _UNICODE + #define CF_TEXTFORMAT CF_UNICODETEXT + #else + #define CF_TEXTFORMAT CF_TEXT + #endif + + HANDLE hClipObj; + + BOOL bSuccess = FALSE; + + // check if clipboard format is available + if (!IsClipboardFormatAvailable(CF_TEXTFORMAT)) + { + MessageBeep(MB_OK); // error beep + return 0; + } + + SuspendDebugger(); // suspend debugger + bDbgAutoStateCtrl = FALSE; // disable automatic debugger state control + + // calculator off, turn on + if (!(Chipset.IORam[BITOFFSET]&DON)) + { + KeyboardEvent(TRUE,0,0x8000); + KeyboardEvent(FALSE,0,0x8000); + + // wait for sleep mode + while(Chipset.Shutdn == FALSE) Sleep(0); + } + + _ASSERT(nState == SM_RUN); // emulator must be in RUN state + if (WaitForSleepState()) // wait for cpu SHUTDN then sleep state + { + InfoMessage(_T("The emulator is busy.")); + goto cancel; + } + + _ASSERT(nState == SM_SLEEP); + + if (OpenClipboard(hWnd)) + { + if ((hClipObj = GetClipboardData(CF_TEXTFORMAT))) + { + LPCTSTR lpstrClipdata; + LPBYTE lpbyData; + + if ((lpstrClipdata = GlobalLock(hClipObj))) + { + BYTE byNumber[128]; + DWORD dwAddress; + INT s; + + do + { + // HP49G in exact mode + if (cCurrentRomType == 'X' && !RPL_GetSystemFlag(fnApprox)) + { + // try to convert string to HP49 precision integer + s = RPL_SetZInt(lpstrClipdata,byNumber,sizeof(byNumber)); + + if (s > 0) // is a real number for exact mode + { + // get TEMPOB memory for HP49 precision integer object + dwAddress = RPL_CreateTemp(s+5+5); + if ((bSuccess = (dwAddress > 0))) + { + Write5(dwAddress,DOINT); // prolog + Write5(dwAddress+5,s+5); // size + Nwrite(byNumber,dwAddress+10,s); // data + + // push object to stack + RPL_Push(dwAddress); + } + break; + } + } + + // try to convert string to real format + s = RPL_SetBcd(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber)); + + if (s > 0) // is a real number + { + // get TEMPOB memory for real object + dwAddress = RPL_CreateTemp(16+5); + if ((bSuccess = (dwAddress > 0))) + { + Write5(dwAddress,DOREAL); // prolog + Nwrite(byNumber,dwAddress+5,s); // data + + // push object to stack + RPL_Push(dwAddress); + } + break; + } + + // any other format + { + DWORD dwSize = lstrlen(lpstrClipdata); + if ((lpbyData = HeapAlloc(hHeap,0,dwSize * 2))) + { + #if defined _UNICODE + // copy data UNICODE -> ASCII + WideCharToMultiByte(CP_ACP, WC_COMPOSITECHECK, + lpstrClipdata, dwSize, + lpbyData+dwSize, dwSize, NULL, NULL); + #else + // copy data + memcpy(lpbyData+dwSize,lpstrClipdata,dwSize); + #endif + bSuccess = (WriteStack(lpbyData,dwSize) == S_ERR_NO); + HeapFree(hHeap,0,lpbyData); + } + } + } + while(FALSE); + + GlobalUnlock(hClipObj); + } + } + CloseClipboard(); + } + + SwitchToState(SM_RUN); // run state + while (nState!=nNextState) Sleep(0); + _ASSERT(nState == SM_RUN); + + if (bSuccess == FALSE) // data not copied + goto cancel; + + KeyboardEvent(TRUE,0,0x8000); + KeyboardEvent(FALSE,0,0x8000); + + // wait for sleep mode + while(Chipset.Shutdn == FALSE) Sleep(0); + +cancel: + bDbgAutoStateCtrl = TRUE; // enable automatic debugger state control + ResumeDebugger(); + return 0; + #undef CF_TEXTFORMAT +} diff --git a/Sources/Emu48/TIMER.C b/Sources/Emu48/TIMER.C index d357893..0c04bad 100644 --- a/Sources/Emu48/TIMER.C +++ b/Sources/Emu48/TIMER.C @@ -108,9 +108,8 @@ static VOID CheckT1(BYTE nT1) _ASSERT((nT1&8) != 0); // timer1 MSB set - // timer MSB is one and either INT or WAKE is set - if ( (Chipset.IORam[TIMER1_CTRL]&WKE) - || (Chipset.IORam[TIMER1_CTRL]&INTR)) + // timer MSB and INT or WAKE bit is set + if ((Chipset.IORam[TIMER1_CTRL]&(WKE|INTR)) != 0) Chipset.IORam[TIMER1_CTRL] |= SRQ; // set SRQ // cpu not sleeping and T1 -> Interrupt if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER1_CTRL]&WKE)) @@ -143,9 +142,8 @@ static VOID CheckT2(DWORD dwT2) _ASSERT((dwT2&0x80000000) != 0); // timer2 MSB set - // timer MSB is one and either INT or WAKE is set - if ( (Chipset.IORam[TIMER2_CTRL]&WKE) - || (Chipset.IORam[TIMER2_CTRL]&INTR)) + // timer MSB and INT or WAKE bit is set + if ((Chipset.IORam[TIMER2_CTRL]&(WKE|INTR)) != 0) Chipset.IORam[TIMER2_CTRL] |= SRQ; // set SRQ // cpu not sleeping and T2 -> Interrupt if ( (!Chipset.Shutdn || (Chipset.IORam[TIMER2_CTRL]&WKE)) @@ -185,7 +183,7 @@ static VOID RescheduleT2(BOOL bRefPoint) uDelay = __max(tc.wPeriodMin,uDelay); // wait minimum delay of timer _ASSERT(uDelay <= tc.wPeriodMax); // inside maximum event delay // start timer2; schedule event, when Chipset.t2 will be zero - VERIFY(uT2TimerId = timeSetEvent(uDelay,0,(LPTIMECALLBACK)&TimeProc,2,TIME_ONESHOT)); + VERIFY(uT2TimerId = timeSetEvent(uDelay,0,&TimeProc,2,TIME_ONESHOT)); return; } @@ -323,7 +321,7 @@ VOID StartTimers(VOID) // set timer resolution to greatest possible one bAccurateTimer = (timeBeginPeriod(tc.wPeriodMin) == TIMERR_NOERROR); // set timer1 with given period - VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC)); + VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,&TimeProc,1,TIME_PERIODIC)); RescheduleT2(TRUE); // start timer2 } return; @@ -398,20 +396,32 @@ BYTE ReadT1(VOID) VOID SetT1(BYTE byValue) { + BOOL bEqual; + _ASSERT(byValue < 0x10); // timer1 is only a 4bit counter - if (Chipset.t1 == byValue) // same value doesn't restart timer period - return; + EnterCriticalSection(&csT1Lock); + { + bEqual = (Chipset.t1 == byValue); // check for same value + } + LeaveCriticalSection(&csT1Lock); + if (bEqual) return; // same value doesn't restart timer period - timeKillEvent(uT1TimerId); // stop timer1 - uT1TimerId = 0; // set flag timer1 stopped + if (uT1TimerId != 0) // timer1 running + { + timeKillEvent(uT1TimerId); // stop timer1 + uT1TimerId = 0; // set flag timer1 stopped + } EnterCriticalSection(&csT1Lock); { Chipset.t1 = byValue; // set new timer1 value CheckT1(Chipset.t1); // test timer1 control bits } LeaveCriticalSection(&csT1Lock); - // restart timer1 to get full period of frequency - VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,(LPTIMECALLBACK)&TimeProc,1,TIME_PERIODIC)); + if (bStarted) // timer running + { + // restart timer1 to get full period of frequency + VERIFY(uT1TimerId = timeSetEvent(T1_FREQ,0,&TimeProc,1,TIME_PERIODIC)); + } return; } diff --git a/Sources/GCCPatch/EMU48GCC.RC b/Sources/GCCPatch/EMU48GCC.RC index 9c5c1f4..33f09c8 100644 --- a/Sources/GCCPatch/EMU48GCC.RC +++ b/Sources/GCCPatch/EMU48GCC.RC @@ -74,7 +74,7 @@ BEGIN LEFTMARGIN, 7 RIGHTMARGIN, 160 TOPMARGIN, 4 - BOTTOMMARGIN, 210 + BOTTOMMARGIN, 256 END IDD_CHOOSEKML, DIALOG @@ -232,15 +232,15 @@ BEGIN ES_READONLY END -IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 229 +IDD_SETTINGS DIALOG DISCARDABLE 0, 0, 167, 263 STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU CAPTION "Settings" FONT 8, "MS Sans Serif" BEGIN CONTROL "Authentic Calculator Speed",IDC_REALSPEED,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,13,13,100,10 - CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE, - "Button",BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10 + CONTROL "Enable Virtual LCD Delay",IDC_GRAYSCALE,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,13,25,100,10 CONTROL "Automatically Save Files",IDC_AUTOSAVE,"Button", BS_AUTOCHECKBOX | WS_TABSTOP,13,37,89,10 CONTROL "Automatically Save Files On Exit",IDC_AUTOSAVEONEXIT, @@ -255,25 +255,35 @@ BEGIN CONTROL "Class Mnemonics",IDC_DISASM_CLASS,"Button", BS_AUTORADIOBUTTON,84,101,70,11 GROUPBOX "Disassembler",IDC_STATIC,7,90,153,28 + LTEXT "Volume",IDC_STATIC,13,134,24,8 + CONTROL "Slider1",IDC_SOUND_SLIDER,"msctls_trackbar32", + TBS_AUTOTICKS | WS_TABSTOP,39,129,68,18 + CONTROL "Speaker",IDC_SOUND_SPEAKER,"Button",BS_AUTORADIOBUTTON | + WS_GROUP | WS_TABSTOP,111,128,43,10 + CONTROL "Wave",IDC_SOUND_WAVE,"Button",BS_AUTORADIOBUTTON,111, + 139,43,10 + GROUPBOX "Sound",IDC_STATIC,7,120,153,34 CONTROL "Port 1 is Plugged",IDC_PORT1EN,"Button",BS_AUTOCHECKBOX | - WS_TABSTOP,13,131,67,10 + WS_TABSTOP,13,165,67,10 CONTROL "Port 1 is Writeable",IDC_PORT1WR,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,84,131,69,10 + BS_AUTOCHECKBOX | WS_TABSTOP,84,165,69,10 CONTROL "Port 2 is Shared",IDC_PORT2ISSHARED,"Button", - BS_AUTOCHECKBOX | WS_TABSTOP,13,143,65,10 - LTEXT "Port 2 File :",IDC_STATIC,13,159,37,8 - EDITTEXT IDC_PORT2,51,156,94,12,ES_AUTOHSCROLL - PUSHBUTTON "...",IDC_PORT2LOAD,145,156,10,12 - GROUPBOX "Memory Cards",IDC_STATIC,7,122,153,51 - LTEXT "Wire:",IDC_STATIC,13,188,17,8 - COMBOBOX IDC_WIRE,31,186,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | + BS_AUTOCHECKBOX | WS_TABSTOP,13,177,65,10 + CONTROL "Port 2 is Writeable",IDC_PORT2WR,"Button", + BS_AUTOCHECKBOX | WS_TABSTOP,84,177,69,10 + LTEXT "Port 2 File :",IDC_STATIC,13,192,37,8 + EDITTEXT IDC_PORT2,51,190,94,12,ES_AUTOHSCROLL + PUSHBUTTON "...",IDC_PORT2LOAD,145,190,10,12 + GROUPBOX "Memory Cards",IDC_STATIC,7,156,153,51 + LTEXT "Wire:",IDC_STATIC,13,221,17,8 + COMBOBOX IDC_WIRE,31,219,48,42,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - LTEXT "IR:",IDC_STATIC,89,188,9,8 - COMBOBOX IDC_IR,107,186,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | + LTEXT "IR:",IDC_STATIC,89,221,9,8 + COMBOBOX IDC_IR,107,219,48,43,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP - GROUPBOX "Serial Ports",IDC_STATIC,7,176,153,27 - DEFPUSHBUTTON "&Ok",IDOK,9,208,50,14 - PUSHBUTTON "&Cancel",IDCANCEL,107,208,50,14 + GROUPBOX "Serial Ports",IDC_STATIC,7,209,153,27 + DEFPUSHBUTTON "&Ok",IDOK,9,242,50,14 + PUSHBUTTON "&Cancel",IDCANCEL,107,242,50,14 END IDD_CHOOSEKML DIALOG DISCARDABLE 0, 0, 195, 66 @@ -566,8 +576,8 @@ END // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,3,7,0 - PRODUCTVERSION 1,3,7,0 + FILEVERSION 1,4,0,0 + PRODUCTVERSION 1,4,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -584,12 +594,12 @@ BEGIN BEGIN VALUE "CompanyName", "Sebastien Carlier & Christoph Gießelink\0" VALUE "FileDescription", "HP38/39/40/48/49 Emulator\0" - VALUE "FileVersion", "1, 3, 7, 0\0" + VALUE "FileVersion", "1, 4, 0, 0\0" VALUE "InternalName", "Emu48\0" VALUE "LegalCopyright", "Copyright © 2005\0" VALUE "OriginalFilename", "Emu48.exe\0" VALUE "ProductName", "Emu48\0" - VALUE "ProductVersion", "1, 3, 7, 0\0" + VALUE "ProductVersion", "1, 4, 0, 0\0" END END BLOCK "VarFileInfo" @@ -634,9 +644,9 @@ BEGIN MENUITEM "&Load Object...", ID_OBJECT_LOAD MENUITEM "&Save Object...", ID_OBJECT_SAVE MENUITEM SEPARATOR - MENUITEM "&Copy String", ID_STACK_COPY MENUITEM "C&opy Screen", ID_VIEW_COPY - MENUITEM "&Paste String", ID_STACK_PASTE + MENUITEM "&Copy Stack", ID_STACK_COPY + MENUITEM "&Paste Stack", ID_STACK_PASTE MENUITEM SEPARATOR MENUITEM "&Reset Calculator", ID_VIEW_RESET, GRAYED POPUP "&Backup" @@ -783,6 +793,18 @@ END #endif // APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Accelerator +// + +IDR_MENU ACCELERATORS DISCARDABLE +BEGIN + "C", ID_STACK_COPY, VIRTKEY, CONTROL, NOINVERT + "V", ID_STACK_PASTE, VIRTKEY, CONTROL, NOINVERT +END + + ///////////////////////////////////////////////////////////////////////////// // // String Table diff --git a/Sources/GCCPatch/Makefile b/Sources/GCCPatch/Makefile index fa073c3..6f5fdbc 100644 --- a/Sources/GCCPatch/Makefile +++ b/Sources/GCCPatch/Makefile @@ -24,7 +24,8 @@ RSRCOBJ=$(PRJ).o OBJS=cursor.o disasm.o display.o debugger.o ddeserv.o \ emu48.o engine.o external.o fetch.o files.o i28f160.o keyboard.o \ - keymacro.o kml.o mops.o opcodes.o rpl.o serial.o settings.o timer.o \ + keymacro.o kml.o mops.o opcodes.o rpl.o serial.o settings.o stack.o \ + timer.o \ $(RSRCOBJ) LIBS=-lwinmm -lcomctl32 @@ -111,6 +112,9 @@ serial.o: serial.c pch.h emu48.h types.h io.h settings.o: settings.c pch.h emu48.h types.h i28f160.h $(CC) $(CFLAGS) $(DEFINES) -c -o settings.o settings.c +stack.o: stack.c pch.h resource.h Emu48.h io.h + $(CC) $(CFLAGS) $(DEFINES) -c -o stack.o stack.c + timer.o: timer.c pch.h emu48.h types.h io.h $(CC) $(CFLAGS) $(DEFINES) -c -o timer.o timer.c diff --git a/Sources/GCCPatch/PCH.H b/Sources/GCCPatch/PCH.H index 698e95b..7a94210 100644 --- a/Sources/GCCPatch/PCH.H +++ b/Sources/GCCPatch/PCH.H @@ -13,6 +13,7 @@ #include #include #include +#include // #include // missing file #if !defined VERIFY diff --git a/Sources/GCCPatch/README.TXT b/Sources/GCCPatch/README.TXT index d2c7582..4b2ea1b 100644 --- a/Sources/GCCPatch/README.TXT +++ b/Sources/GCCPatch/README.TXT @@ -29,7 +29,7 @@ or MinGW-3.1.0-1.exe w32api-3.3.tar.gz mingw-runtime-3.8.tar.gz -binutils-2.15.94-20050118-1.tar.gz +binutils-2.16.91-20050827-1.tar.gz gcc-core-3.4.4-20050522-1.tar.gz Older versions of the MinGW package might not work, because there are several @@ -43,4 +43,4 @@ Many thanks to Pedro A. Arranda Guti compatible. -08/22/05 (c) by Christoph Gießelink +12/05/05 (c) by Christoph Gießelink diff --git a/uninst.exe b/uninst.exe index 62ef141..238d424 100755 Binary files a/uninst.exe and b/uninst.exe differ