From 9f58423a9372c3fecbd5d262cb74b6e5d6173345 Mon Sep 17 00:00:00 2001 From: dgis Date: Sat, 5 Oct 2024 21:19:13 +0200 Subject: [PATCH] Update to 1.66+, revert USB lib to 3.4, fix USB/Serial issue in Android 13+ - Updated source code with Emu48 version 1.66+ - Update Revert usb-serial-for-android to version 3.4 - Fix an USB serial issue with Android 13+ (fix #23) --- ReadMe.txt | 3 +- app/CMakeLists.txt | 2 +- app/build.gradle | 4 +- app/src/main/AndroidManifest.xml | 1 - app/src/main/assets/Emu48.htm | 30 +- app/src/main/assets/ReadMe.txt | 5 - app/src/main/cpp/core/Emu48.c | 17 +- app/src/main/cpp/core/Emu48.h | 1 + app/src/main/cpp/core/debugger.c | 108 +- app/src/main/cpp/core/external.c | 101 - app/src/main/cpp/core/fetch.c | 1184 ++-- app/src/main/cpp/core/lodepng.c | 18 +- app/src/main/cpp/core/lodepng.h | 2 +- app/src/main/cpp/core/mops.c | 4 +- app/src/main/cpp/core/resource.h | 119 +- app/src/main/cpp/core/romcrc.c | 4 +- app/src/main/cpp/core/serial.c | 1 - app/src/main/cpp/core/settings.c | 36 +- app/src/main/cpp/core/stack.c | 153 +- app/src/main/cpp/core/timer.c | 26 +- app/src/main/cpp/core/udp.c | 5 - app/src/main/cpp/win32-layer.c | 5100 +++++++++-------- app/src/main/cpp/win32-layer.h | 9 +- .../java/org/emulator/calculator/Serial.java | 4 +- .../usbserial/driver/CdcAcmSerialDriver.java | 162 +- .../usbserial/driver/Ch34xSerialDriver.java | 595 +- .../driver/ChromeCcdSerialDriver.java | 96 - .../usbserial/driver/CommonUsbSerialPort.java | 123 +- .../usbserial/driver/Cp21xxSerialDriver.java | 6 +- .../usbserial/driver/FtdiSerialDriver.java | 40 +- .../driver/GsmModemSerialDriver.java | 106 - .../usbserial/driver/ProbeTable.java | 49 +- .../driver/ProlificSerialDriver.java | 48 +- .../driver/SerialTimeoutException.java | 3 +- .../calculator/usbserial/driver/UsbId.java | 37 +- .../usbserial/driver/UsbSerialDriver.java | 13 +- .../usbserial/driver/UsbSerialPort.java | 25 +- .../usbserial/driver/UsbSerialProber.java | 8 +- .../calculator/usbserial/util/HexDump.java | 158 - .../util/SerialInputOutputManager.java | 44 +- .../calculator/usbserial/util/UsbUtils.java | 33 - .../emulator/forty/eight/MainActivity.java | 51 +- build.gradle | 2 +- gradle.properties | 2 +- gradle/wrapper/gradle-wrapper.properties | 2 +- 45 files changed, 4112 insertions(+), 4428 deletions(-) delete mode 100644 app/src/main/cpp/core/external.c delete mode 100644 app/src/main/java/org/emulator/calculator/usbserial/driver/ChromeCcdSerialDriver.java delete mode 100644 app/src/main/java/org/emulator/calculator/usbserial/driver/GsmModemSerialDriver.java delete mode 100644 app/src/main/java/org/emulator/calculator/usbserial/util/HexDump.java delete mode 100644 app/src/main/java/org/emulator/calculator/usbserial/util/UsbUtils.java diff --git a/ReadMe.txt b/ReadMe.txt index 0bb0f1a..a75ac76 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -60,7 +60,7 @@ CHANGES Version 2.8 (2024-xx-xx) -- Update the usb serial drivers usb-serial-for-android to version 3.7.3 +- Updated source code with Emu48 version 1.66+. Version 2.7 (2024-06-14) @@ -277,6 +277,7 @@ FAQ TODO - NDK 26 does not compile +- Adding a new KML command for Android only: CUSTOM_PIXEL_BORDER_ON 10001 / CUSTOM_PIXEL_BORDER_OFF 10002 / CUSTOM_PIXEL_BORDER_TOGGLE 10003 - Patching 49G to disable 10 min auto off causes a reset when touching the Recent button and coming back to the app (with a Flashcard loaded). - Add an "haptic" feedback with a sound instead of a vibration (F. Giampietro). - Add a Cancel button to the HP48 memory card creator dialog. diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index c7869d9..d0f0dd8 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -65,7 +65,7 @@ add_library( # Sets the name of the library. src/main/cpp/core/disrpl.c # src/main/cpp/core/Emu48.c #-> To rewrite src/main/cpp/core/engine.c - src/main/cpp/core/external.c +# src/main/cpp/core/external.c # Removed 167/166+ src/main/cpp/core/fetch.c src/main/cpp/core/files.c src/main/cpp/core/i28f160.c diff --git a/app/build.gradle b/app/build.gradle index 206140f..a82288b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -34,8 +34,8 @@ android { applicationId "org.emulator.forty.eight" minSdk 21 targetSdk 34 - versionCode 27 - versionName "2.8" + versionCode 26 + versionName "2.7" setProperty("archivesBaseName", "Emu48-v$versionName") testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" externalNativeBuild { diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index c07e59e..45978ec 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -16,7 +16,6 @@ android:fullBackupContent="@xml/backup_descriptor"> -

The decimal point (radix mark) of "Real Numbers" in the - clipboard is equal to the calculator setting. This is important when - you try to paste the numbers into a program using the locale settings - of the host operating system.

+

The decimal point of "Real Numbers" in the clipboard is + equal to the calculator setting. This is important when you try to + paste the numbers into a program using the locale settings of the host + operating system.

9.5 Paste Stack

This menu item is enabled for the HP48SX, HP48GX and the HP49G emulation.

@@ -539,14 +539,18 @@ h3 { color:red; font-size:1.1em; } object. Is the content a complex number object, the number will be saved as "Complex Number" object, otherwise cases as "String" object.

-

To import "Real or Complex Numbers" from the clipboard, the - decimal point (radix mark) of the clipboard and calculator must - match. A real or complex number is only detected in the case of valid - real number characters in the clipboard. Especially heading and tailing - white spaces aren't valid number characters also.

-

Complex numbers must be in the form (a,b) when using the point - radix mark or in the form (a;b) when using the comma radix mark. - The Cartesian or algebraic form a+bi is not supported.

+

To import "Real Numbers" from the clipboard, the decimal + point character of the clipboard and calculator must not match any + more. There's an auto detection for decoding the thousands separator and + decimal point character. The thousands separator is removed at decoding. + A real number is detected in the case of valid real number characters in + the clipboard.

+

"Complex Numbers" must be in the form (a,b) when + using the decimal point or in the form (a;b) when using the decimal + comma. Using a thousands separator is not allowed in complex number + strings because in decimal point mode, the comma is used as separator + between real and imaginary part of the number. The Cartesian or algebraic + form a+bi is not supported.

9.6 Reset Calculator

This emulates the Reset pin of the internal CPU.

9.7 Backup

@@ -675,7 +679,7 @@ h3 { color:red; font-size:1.1em; } Cyrille de Brebisson of Hewlett-Packard.

15. License

Emu48 - A HP38G/39G/40G/48SX/48GX/49G Emulator
- Copyright (C) 2022 Christoph Gießelink

+ Copyright (C) 2024 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 Foundation; either version 2 of the License, or (at your option) diff --git a/app/src/main/assets/ReadMe.txt b/app/src/main/assets/ReadMe.txt index 5ae997e..71490fd 100644 --- a/app/src/main/assets/ReadMe.txt +++ b/app/src/main/assets/ReadMe.txt @@ -58,11 +58,6 @@ LINKS CHANGES -Version 2.8 (2024-xx-xx) - -- Update the usb serial drivers usb-serial-for-android to version 3.7.3 - - Version 2.7 (2024-06-14) - Updated source code with Emu48 version 1.65+. This new version improve the serial communication. diff --git a/app/src/main/cpp/core/Emu48.c b/app/src/main/cpp/core/Emu48.c index fe045f6..5251f40 100644 --- a/app/src/main/cpp/core/Emu48.c +++ b/app/src/main/cpp/core/Emu48.c @@ -13,7 +13,7 @@ #include "kml.h" #include "debugger.h" -#define VERSION "1.65+" +#define VERSION "1.66+" #ifdef _DEBUG LPCTSTR szNoTitle = _T("Emu48 ")_T(VERSION)_T(" Debug"); @@ -2045,6 +2045,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC MSG msg; WNDCLASS wc; ATOM classAtom; + WSADATA wsd; RECT rectWindow; HACCEL hAccel; DWORD dwThreadId; @@ -2059,16 +2060,8 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF); hApp = hInst; - #if defined _UNICODE - { - ppArgv = (LPCTSTR*) CommandLineToArgvW(GetCommandLine(),&nArgc); - } - #else - { - nArgc = __argc; // no. of command line arguments - ppArgv = (LPCTSTR*) __argv; // command line arguments - } - #endif + nArgc = __argc; // no. of command line arguments + ppArgv = __targv; // command line arguments wc.style = CS_BYTEALIGNCLIENT; wc.lpfnWndProc = (WNDPROC)MainWndProc; @@ -2298,6 +2291,7 @@ int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmdLine, int nC if (NewDocument()) SetWindowTitle(_T("Untitled")); start: + VERIFY(WSAStartup(MAKEWORD(1,1),&wsd) == 0); if (bStartupBackup) SaveBackup(); // make a RAM backup at startup if (pbyRom) SwitchToState(SM_RUN); @@ -2313,6 +2307,7 @@ start: DispatchMessage(&msg); } } + WSACleanup(); // cleanup network stack // clean up DDE server DdeNameService(idDdeInst, hszService, NULL, DNS_UNREGISTER); diff --git a/app/src/main/cpp/core/Emu48.h b/app/src/main/cpp/core/Emu48.h index 26eb81e..d826005 100644 --- a/app/src/main/cpp/core/Emu48.h +++ b/app/src/main/cpp/core/Emu48.h @@ -369,6 +369,7 @@ extern BOOL SendByteUdp(BYTE byData); // Stack.c extern BOOL bDetectClpObject; +extern BOOL bLocaleDecimalPoint; extern LRESULT OnStackCopy(VOID); extern LRESULT OnStackPaste(VOID); diff --git a/app/src/main/cpp/core/debugger.c b/app/src/main/cpp/core/debugger.c index 67218f3..591907a 100644 --- a/app/src/main/cpp/core/debugger.c +++ b/app/src/main/cpp/core/debugger.c @@ -65,8 +65,8 @@ static CONST TCHAR cHex[] = { _T('0'),_T('1'),_T('2'),_T('3'), _T('8'),_T('9'),_T('A'),_T('B'), _T('C'),_T('D'),_T('E'),_T('F') }; -static INT nDbgPosX = 0; // position of debugger window -static INT nDbgPosY = 0; +static INT nDbgPosX = CW_USEDEFAULT; // position of debugger window +static INT nDbgPosY = CW_USEDEFAULT; static WORD wBreakpointCount = 0; // number of breakpoints static BP_T sBreakpoint[MAXBREAKPOINTS]; // breakpoint table @@ -1885,7 +1885,10 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM switch (message) { case WM_INITDIALOG: + if (nDbgPosX != CW_USEDEFAULT) // not default window position + { SetWindowLocation(hDlg,nDbgPosX,nDbgPosY); + } if (bAlwaysOnTop) SetWindowPos(hDlg,HWND_TOPMOST,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE); SendMessage(hDlg,WM_SETICON,ICON_BIG,(LPARAM) LoadIcon(hApp,MAKEINTRESOURCE(IDI_EMU48))); @@ -2201,7 +2204,7 @@ static INT_PTR CALLBACK Debugger(HWND hDlg, UINT message, WPARAM wParam, LPARAM LRESULT OnToolDebug(VOID) // debugger dialogbox call { - if ((hDlgDebug = CreateDialog(hApp,MAKEINTRESOURCE(IDD_DEBUG),NULL, + if ((hDlgDebug = CreateDialog(hApp,MAKEINTRESOURCE(IDD_DEBUG),hWnd, (DLGPROC)Debugger)) == NULL) AbortMessage(_T("Debugger Dialog Box Creation Error !")); return 0; @@ -3501,46 +3504,79 @@ static BOOL OnBrowseSaveMem(HWND hDlg) // // write file to memory // -static BOOL LoadMemData(LPCTSTR lpszFilename,DWORD dwStartAddr) +static BOOL LoadMemData(LPCTSTR lpszFilename,DWORD dwStartAddr,UINT uBitMode) { HANDLE hFile; - DWORD dwRead; - BYTE byData; + DWORD dwFileSize,dwRead; + LPBYTE pbyData; hFile = CreateFile(lpszFilename,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_FLAG_SEQUENTIAL_SCAN,NULL); if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file return FALSE; - while (dwStartAddr <= 0xFFFFF) // read until EOF or end of Saturn address space + dwFileSize = GetFileSize(hFile, NULL); + if ((pbyData = (LPBYTE) malloc(dwFileSize)) != NULL) { - ReadFile(hFile,&byData,sizeof(byData),&dwRead,NULL); - if (dwRead == 0) break; // EOF - - if (dwStartAddr < 0xFFFFF) + ReadFile(hFile,pbyData,dwFileSize,&dwRead,NULL); + if (uBitMode == 2) // auto mode (0=8-bit, 1=4-bit, 2=auto) { - Write2(dwStartAddr,byData); // write byte in map mode - dwStartAddr += 2; + BOOL bPacked = FALSE; // data not packed + DWORD dwIndex; + for (dwIndex = 0; !bPacked && dwIndex < dwFileSize; ++dwIndex) + { + bPacked = ((pbyData[dwIndex] & 0xF0) != 0); + } + uBitMode = bPacked ? 0 : 1; // 0=8-bit, 1=4-bit } + + if (uBitMode == 0) // 0=8-bit + { + LPBYTE pbyDataNew = (LPBYTE) realloc(pbyData,2*dwFileSize); + if (pbyDataNew) + { + LPBYTE pbySrc,pbyDest; + pbyData = pbyDataNew; + pbySrc = pbyData + dwFileSize; + dwFileSize *= 2; // new filesize + pbyDest = pbyData + dwFileSize; + while (pbySrc != pbyDest) // unpack source + { + CONST BYTE byValue = *(--pbySrc); + *(--pbyDest) = byValue >> 4; + *(--pbyDest) = byValue & 0xF; + } + _ASSERT(pbySrc == pbyData); + _ASSERT(pbyDest == pbyData); + } else // special handling to avoid address wrap around { - byData &= 0xF; - Nwrite(&byData,dwStartAddr,1); // write nibble in map mode - ++dwStartAddr; + free(pbyData); + pbyData = NULL; + } + } + if (pbyData) // have data to save + { + LPBYTE p = pbyData; + while (dwFileSize > 0 && dwStartAddr <= 0xFFFFF) + { + Nwrite(p++,dwStartAddr++,1); + --dwFileSize; } } - + free(pbyData); + } CloseHandle(hFile); - return TRUE; + return pbyData != NULL; } // // write memory data to file // -static BOOL SaveMemData(LPCTSTR lpszFilename,DWORD dwStartAddr,DWORD dwEndAddr) +static BOOL SaveMemData(LPCTSTR lpszFilename,DWORD dwStartAddr,DWORD dwEndAddr,UINT uBitMode) { HANDLE hFile; - DWORD dwAddr,dwWritten; - BYTE byData; + DWORD dwAddr,dwSend,dwWritten; + BYTE byData[2]; hFile = CreateFile(lpszFilename, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); if (hFile == INVALID_HANDLE_VALUE) // error, couldn't create a new file @@ -3549,8 +3585,14 @@ static BOOL SaveMemData(LPCTSTR lpszFilename,DWORD dwStartAddr,DWORD dwEndAddr) for (dwAddr = dwStartAddr; dwAddr <= dwEndAddr; dwAddr += 2) { _ASSERT(dwAddr <= 0xFFFFF); - byData = Read2(dwAddr); // read byte in map mode - WriteFile(hFile,&byData,sizeof(byData),&dwWritten,NULL); + Npeek(byData,dwAddr,2); // read two nibble in map mode + dwSend = 2; // send 2 nibble + if (uBitMode == 0) // (0=8-bit, 1=4-bit) + { + byData[0] = byData[0]|(byData[1]<<4); + dwSend = 1; // send 1 byte + } + WriteFile(hFile,&byData,dwSend,&dwWritten,NULL); } CloseHandle(hFile); @@ -3564,9 +3606,14 @@ static INT_PTR CALLBACK DebugMemLoad(HWND hDlg, UINT message, WPARAM wParam, LPA { TCHAR szFilename[MAX_PATH]; DWORD dwStartAddr; + int nButton; + UINT uBitMode; switch (message) { + case WM_INITDIALOG: + CheckDlgButton(hDlg,IDC_DEBUG_DATA_LOAD_ABIT,BST_CHECKED); + return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { @@ -3586,8 +3633,14 @@ static INT_PTR CALLBACK DebugMemLoad(HWND hDlg, UINT message, WPARAM wParam, LPA _ASSERT(dwStartAddr <= 0xFFFFF); + for (nButton = IDC_DEBUG_DATA_LOAD_8BIT; nButton <= IDC_DEBUG_DATA_LOAD_ABIT; ++nButton) + { + if (IsDlgButtonChecked(hDlg,nButton) == BST_CHECKED) + break; + } + uBitMode = (UINT) (nButton - IDC_DEBUG_DATA_LOAD_8BIT); // load memory dump file - if (!LoadMemData(szFilename,dwStartAddr)) + if (!LoadMemData(szFilename,dwStartAddr,uBitMode)) return FALSE; // update memory window @@ -3617,9 +3670,13 @@ static INT_PTR CALLBACK DebugMemSave(HWND hDlg, UINT message, WPARAM wParam, LPA { TCHAR szFilename[MAX_PATH]; DWORD dwStartAddr,dwEndAddr; + UINT uBitMode; switch (message) { + case WM_INITDIALOG: + CheckDlgButton(hDlg,IDC_DEBUG_DATA_SAVE_8BIT,BST_CHECKED); + return TRUE; case WM_COMMAND: switch(LOWORD(wParam)) { @@ -3643,8 +3700,9 @@ static INT_PTR CALLBACK DebugMemSave(HWND hDlg, UINT message, WPARAM wParam, LPA _ASSERT(dwStartAddr <= 0xFFFFF); _ASSERT(dwEndAddr <= 0xFFFFF); + uBitMode = IsDlgButtonChecked(hDlg,IDC_DEBUG_DATA_SAVE_4BIT); // save memory dump file - if (!SaveMemData(szFilename,dwStartAddr,dwEndAddr)) + if (!SaveMemData(szFilename,dwStartAddr,dwEndAddr,uBitMode)) return FALSE; // no break diff --git a/app/src/main/cpp/core/external.c b/app/src/main/cpp/core/external.c deleted file mode 100644 index e548b54..0000000 --- a/app/src/main/cpp/core/external.c +++ /dev/null @@ -1,101 +0,0 @@ -/* - * external.c - * - * This file is part of Emu48 - * - * Copyright (C) 1995 Sebastien Carlier - * - */ -#include "pch.h" -#include "Emu48.h" -#include "ops.h" - -#define SAMPLES_PER_SEC 44100 // sound sampling rate - -//| 38G | 39G | 40G | 48SX | 48GX | 49G | Name -//#F0E4F #80F0F #80F0F #706D2 #80850 #80F0F =SFLAG53_56 - -// memory address for flags -53 to -56 - // CdB for HP: add apples beep management -#define SFLAG53_56 ( (cCurrentRomType=='6') \ - ? 0xE0E4F \ - : ( (cCurrentRomType=='A') \ - ? 0xF0E4F \ - : ( (cCurrentRomType!='E' && cCurrentRomType!='X' && cCurrentRomType!='P' && cCurrentRomType!='2' && cCurrentRomType!='Q') \ - ? ( (cCurrentRomType=='S') \ - ? 0x706D2 \ - : 0x80850 \ - ) \ - : 0x80F0F \ - ) \ - ) \ - ) - -VOID External(CHIPSET* w) // Beep patch -{ - BYTE fbeep; - DWORD freq,dur; - - freq = Npack(w->D,5); // frequency in Hz - dur = Npack(w->C,5); // duration in ms - Nread(&fbeep,SFLAG53_56,1); // fetch system flags -53 to -56 - - w->carry = TRUE; // setting of no beep - if (!(fbeep & 0x8) && freq) // bit -56 clear and frequency > 0 Hz - { - if (freq > 4400) freq = 4400; // high limit of HP (SX) - - SoundBeep(freq,dur); // beeping - - // estimate cpu cycles for beeping time (2MHz / 4MHz) - w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000); - - // original routine return with... - w->P = 0; // P=0 - w->intk = TRUE; // INTON - w->carry = FALSE; // RTNCC - } - w->pc = rstkpop(); - return; -} - -VOID RCKBp(CHIPSET* w) // ROM Check Beep patch -{ - DWORD dw2F,dwCpuFreq; - DWORD freq,dur; - BYTE f,d; - - f = w->C[1]; // f = freq ctl - d = w->C[0]; // d = duration ctl - - if (cCurrentRomType == 'S') // Clarke chip with 48S ROM - { - // CPU strobe frequency @ RATE 14 = 1.97MHz - dwCpuFreq = ((14 + 1) * 524288) >> 2; - - dw2F = f * 126 + 262; // F=f*63+131 - } - else // York chip with 48G and later ROM - { - // CPU strobe frequency @ RATE 27 = 3.67MHz - // CPU strobe frequency @ RATE 29 = 3.93MHz - dwCpuFreq = ((27 + 1) * 524288) >> 2; - - dw2F = f * 180 + 367; // F=f*90+183.5 - } - - freq = dwCpuFreq / dw2F; - dur = (dw2F * (256 - 16 * d)) * 1000 / 2 / dwCpuFreq; - - if (freq > 4400) freq = 4400; // high limit of HP - - SoundBeep(freq,dur); // beeping - - // estimate cpu cycles for beeping time (2MHz / 4MHz) - w->cycles += dur * ((cCurrentRomType=='S') ? 2000 : 4000); - - w->P = 0; // P=0 - w->carry = FALSE; // RTNCC - w->pc = rstkpop(); - return; -} diff --git a/app/src/main/cpp/core/fetch.c b/app/src/main/cpp/core/fetch.c index e19cdf8..89eb246 100644 --- a/app/src/main/cpp/core/fetch.c +++ b/app/src/main/cpp/core/fetch.c @@ -20,742 +20,742 @@ typedef const struct // jump tables static JMPTAB oF_[] = { - (LPCVOID) oF0, F, - (LPCVOID) oF1, F, - (LPCVOID) oF2, F, - (LPCVOID) oF3, F, - (LPCVOID) oF4, F, - (LPCVOID) oF5, F, - (LPCVOID) oF6, F, - (LPCVOID) oF7, F, - (LPCVOID) oF8, F, - (LPCVOID) oF9, F, - (LPCVOID) oFA, F, - (LPCVOID) oFB, F, - (LPCVOID) oFC, F, - (LPCVOID) oFD, F, - (LPCVOID) oFE, F, - (LPCVOID) oFF, F + { (LPCVOID) oF0, F }, + { (LPCVOID) oF1, F }, + { (LPCVOID) oF2, F }, + { (LPCVOID) oF3, F }, + { (LPCVOID) oF4, F }, + { (LPCVOID) oF5, F }, + { (LPCVOID) oF6, F }, + { (LPCVOID) oF7, F }, + { (LPCVOID) oF8, F }, + { (LPCVOID) oF9, F }, + { (LPCVOID) oFA, F }, + { (LPCVOID) oFB, F }, + { (LPCVOID) oFC, F }, + { (LPCVOID) oFD, F }, + { (LPCVOID) oFE, F }, + { (LPCVOID) oFF, F } }; static JMPTAB oE_[] = { - (LPCVOID) oE0, F, - (LPCVOID) oE1, F, - (LPCVOID) oE2, F, - (LPCVOID) oE3, F, - (LPCVOID) oE4, F, - (LPCVOID) oE5, F, - (LPCVOID) oE6, F, - (LPCVOID) oE7, F, - (LPCVOID) oE8, F, - (LPCVOID) oE9, F, - (LPCVOID) oEA, F, - (LPCVOID) oEB, F, - (LPCVOID) oEC, F, - (LPCVOID) oED, F, - (LPCVOID) oEE, F, - (LPCVOID) oEF, F + { (LPCVOID) oE0, F }, + { (LPCVOID) oE1, F }, + { (LPCVOID) oE2, F }, + { (LPCVOID) oE3, F }, + { (LPCVOID) oE4, F }, + { (LPCVOID) oE5, F }, + { (LPCVOID) oE6, F }, + { (LPCVOID) oE7, F }, + { (LPCVOID) oE8, F }, + { (LPCVOID) oE9, F }, + { (LPCVOID) oEA, F }, + { (LPCVOID) oEB, F }, + { (LPCVOID) oEC, F }, + { (LPCVOID) oED, F }, + { (LPCVOID) oEE, F }, + { (LPCVOID) oEF, F } }; static JMPTAB oD_[] = { - (LPCVOID) oD0, F, - (LPCVOID) oD1, F, - (LPCVOID) oD2, F, - (LPCVOID) oD3, F, - (LPCVOID) oD4, F, - (LPCVOID) oD5, F, - (LPCVOID) oD6, F, - (LPCVOID) oD7, F, - (LPCVOID) oD8, F, - (LPCVOID) oD9, F, - (LPCVOID) oDA, F, - (LPCVOID) oDB, F, - (LPCVOID) oDC, F, - (LPCVOID) oDD, F, - (LPCVOID) oDE, F, - (LPCVOID) oDF, F + { (LPCVOID) oD0, F }, + { (LPCVOID) oD1, F }, + { (LPCVOID) oD2, F }, + { (LPCVOID) oD3, F }, + { (LPCVOID) oD4, F }, + { (LPCVOID) oD5, F }, + { (LPCVOID) oD6, F }, + { (LPCVOID) oD7, F }, + { (LPCVOID) oD8, F }, + { (LPCVOID) oD9, F }, + { (LPCVOID) oDA, F }, + { (LPCVOID) oDB, F }, + { (LPCVOID) oDC, F }, + { (LPCVOID) oDD, F }, + { (LPCVOID) oDE, F }, + { (LPCVOID) oDF, F } }; static JMPTAB oC_[] = { - (LPCVOID) oC0, F, - (LPCVOID) oC1, F, - (LPCVOID) oC2, F, - (LPCVOID) oC3, F, - (LPCVOID) oC4, F, - (LPCVOID) oC5, F, - (LPCVOID) oC6, F, - (LPCVOID) oC7, F, - (LPCVOID) oC8, F, - (LPCVOID) oC9, F, - (LPCVOID) oCA, F, - (LPCVOID) oCB, F, - (LPCVOID) oCC, F, - (LPCVOID) oCD, F, - (LPCVOID) oCE, F, - (LPCVOID) oCF, F + { (LPCVOID) oC0, F }, + { (LPCVOID) oC1, F }, + { (LPCVOID) oC2, F }, + { (LPCVOID) oC3, F }, + { (LPCVOID) oC4, F }, + { (LPCVOID) oC5, F }, + { (LPCVOID) oC6, F }, + { (LPCVOID) oC7, F }, + { (LPCVOID) oC8, F }, + { (LPCVOID) oC9, F }, + { (LPCVOID) oCA, F }, + { (LPCVOID) oCB, F }, + { (LPCVOID) oCC, F }, + { (LPCVOID) oCD, F }, + { (LPCVOID) oCE, F }, + { (LPCVOID) oCF, F } }; static JMPTAB oBb_[] = { - (LPCVOID) oBb0, F, - (LPCVOID) oBb1, F, - (LPCVOID) oBb2, F, - (LPCVOID) oBb3, F, - (LPCVOID) oBb4, F, - (LPCVOID) oBb5, F, - (LPCVOID) oBb6, F, - (LPCVOID) oBb7, F, - (LPCVOID) oBb8, F, - (LPCVOID) oBb9, F, - (LPCVOID) oBbA, F, - (LPCVOID) oBbB, F, - (LPCVOID) oBbC, F, - (LPCVOID) oBbD, F, - (LPCVOID) oBbE, F, - (LPCVOID) oBbF, F + { (LPCVOID) oBb0, F }, + { (LPCVOID) oBb1, F }, + { (LPCVOID) oBb2, F }, + { (LPCVOID) oBb3, F }, + { (LPCVOID) oBb4, F }, + { (LPCVOID) oBb5, F }, + { (LPCVOID) oBb6, F }, + { (LPCVOID) oBb7, F }, + { (LPCVOID) oBb8, F }, + { (LPCVOID) oBb9, F }, + { (LPCVOID) oBbA, F }, + { (LPCVOID) oBbB, F }, + { (LPCVOID) oBbC, F }, + { (LPCVOID) oBbD, F }, + { (LPCVOID) oBbE, F }, + { (LPCVOID) oBbF, F } }; static JMPTAB oBa_[] = { - (LPCVOID) oBa0, F, - (LPCVOID) oBa1, F, - (LPCVOID) oBa2, F, - (LPCVOID) oBa3, F, - (LPCVOID) oBa4, F, - (LPCVOID) oBa5, F, - (LPCVOID) oBa6, F, - (LPCVOID) oBa7, F, - (LPCVOID) oBa8, F, - (LPCVOID) oBa9, F, - (LPCVOID) oBaA, F, - (LPCVOID) oBaB, F, - (LPCVOID) oBaC, F, - (LPCVOID) oBaD, F, - (LPCVOID) oBaE, F, - (LPCVOID) oBaF, F + { (LPCVOID) oBa0, F }, + { (LPCVOID) oBa1, F }, + { (LPCVOID) oBa2, F }, + { (LPCVOID) oBa3, F }, + { (LPCVOID) oBa4, F }, + { (LPCVOID) oBa5, F }, + { (LPCVOID) oBa6, F }, + { (LPCVOID) oBa7, F }, + { (LPCVOID) oBa8, F }, + { (LPCVOID) oBa9, F }, + { (LPCVOID) oBaA, F }, + { (LPCVOID) oBaB, F }, + { (LPCVOID) oBaC, F }, + { (LPCVOID) oBaD, F }, + { (LPCVOID) oBaE, F }, + { (LPCVOID) oBaF, F } }; static JMPTAB oB_[] = { - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBa_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2, - (LPCVOID) oBb_, 2 + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBa_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 }, + { (LPCVOID) oBb_, 2 } }; static JMPTAB oAb_[] = { - (LPCVOID) oAb0, F, - (LPCVOID) oAb1, F, - (LPCVOID) oAb2, F, - (LPCVOID) oAb3, F, - (LPCVOID) oAb4, F, - (LPCVOID) oAb5, F, - (LPCVOID) oAb6, F, - (LPCVOID) oAb7, F, - (LPCVOID) oAb8, F, - (LPCVOID) oAb9, F, - (LPCVOID) oAbA, F, - (LPCVOID) oAbB, F, - (LPCVOID) oAbC, F, - (LPCVOID) oAbD, F, - (LPCVOID) oAbE, F, - (LPCVOID) oAbF, F + { (LPCVOID) oAb0, F }, + { (LPCVOID) oAb1, F }, + { (LPCVOID) oAb2, F }, + { (LPCVOID) oAb3, F }, + { (LPCVOID) oAb4, F }, + { (LPCVOID) oAb5, F }, + { (LPCVOID) oAb6, F }, + { (LPCVOID) oAb7, F }, + { (LPCVOID) oAb8, F }, + { (LPCVOID) oAb9, F }, + { (LPCVOID) oAbA, F }, + { (LPCVOID) oAbB, F }, + { (LPCVOID) oAbC, F }, + { (LPCVOID) oAbD, F }, + { (LPCVOID) oAbE, F }, + { (LPCVOID) oAbF, F } }; static JMPTAB oAa_[] = { - (LPCVOID) oAa0, F, - (LPCVOID) oAa1, F, - (LPCVOID) oAa2, F, - (LPCVOID) oAa3, F, - (LPCVOID) oAa4, F, - (LPCVOID) oAa5, F, - (LPCVOID) oAa6, F, - (LPCVOID) oAa7, F, - (LPCVOID) oAa8, F, - (LPCVOID) oAa9, F, - (LPCVOID) oAaA, F, - (LPCVOID) oAaB, F, - (LPCVOID) oAaC, F, - (LPCVOID) oAaD, F, - (LPCVOID) oAaE, F, - (LPCVOID) oAaF, F + { (LPCVOID) oAa0, F }, + { (LPCVOID) oAa1, F }, + { (LPCVOID) oAa2, F }, + { (LPCVOID) oAa3, F }, + { (LPCVOID) oAa4, F }, + { (LPCVOID) oAa5, F }, + { (LPCVOID) oAa6, F }, + { (LPCVOID) oAa7, F }, + { (LPCVOID) oAa8, F }, + { (LPCVOID) oAa9, F }, + { (LPCVOID) oAaA, F }, + { (LPCVOID) oAaB, F }, + { (LPCVOID) oAaC, F }, + { (LPCVOID) oAaD, F }, + { (LPCVOID) oAaE, F }, + { (LPCVOID) oAaF, F } }; static JMPTAB oA_[] = { - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAa_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2, - (LPCVOID) oAb_, 2 + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAa_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 }, + { (LPCVOID) oAb_, 2 } }; static JMPTAB o9b_[] = { - (LPCVOID) o9b0, F, - (LPCVOID) o9b1, F, - (LPCVOID) o9b2, F, - (LPCVOID) o9b3, F, - (LPCVOID) o9b4, F, - (LPCVOID) o9b5, F, - (LPCVOID) o9b6, F, - (LPCVOID) o9b7, F, - (LPCVOID) o9b8, F, - (LPCVOID) o9b9, F, - (LPCVOID) o9bA, F, - (LPCVOID) o9bB, F, - (LPCVOID) o9bC, F, - (LPCVOID) o9bD, F, - (LPCVOID) o9bE, F, - (LPCVOID) o9bF, F + { (LPCVOID) o9b0, F }, + { (LPCVOID) o9b1, F }, + { (LPCVOID) o9b2, F }, + { (LPCVOID) o9b3, F }, + { (LPCVOID) o9b4, F }, + { (LPCVOID) o9b5, F }, + { (LPCVOID) o9b6, F }, + { (LPCVOID) o9b7, F }, + { (LPCVOID) o9b8, F }, + { (LPCVOID) o9b9, F }, + { (LPCVOID) o9bA, F }, + { (LPCVOID) o9bB, F }, + { (LPCVOID) o9bC, F }, + { (LPCVOID) o9bD, F }, + { (LPCVOID) o9bE, F }, + { (LPCVOID) o9bF, F } }; static JMPTAB o9a_[] = { - (LPCVOID) o9a0, F, - (LPCVOID) o9a1, F, - (LPCVOID) o9a2, F, - (LPCVOID) o9a3, F, - (LPCVOID) o9a4, F, - (LPCVOID) o9a5, F, - (LPCVOID) o9a6, F, - (LPCVOID) o9a7, F, - (LPCVOID) o9a8, F, - (LPCVOID) o9a9, F, - (LPCVOID) o9aA, F, - (LPCVOID) o9aB, F, - (LPCVOID) o9aC, F, - (LPCVOID) o9aD, F, - (LPCVOID) o9aE, F, - (LPCVOID) o9aF, F + { (LPCVOID) o9a0, F }, + { (LPCVOID) o9a1, F }, + { (LPCVOID) o9a2, F }, + { (LPCVOID) o9a3, F }, + { (LPCVOID) o9a4, F }, + { (LPCVOID) o9a5, F }, + { (LPCVOID) o9a6, F }, + { (LPCVOID) o9a7, F }, + { (LPCVOID) o9a8, F }, + { (LPCVOID) o9a9, F }, + { (LPCVOID) o9aA, F }, + { (LPCVOID) o9aB, F }, + { (LPCVOID) o9aC, F }, + { (LPCVOID) o9aD, F }, + { (LPCVOID) o9aE, F }, + { (LPCVOID) o9aF, F } }; static JMPTAB o9_[] = { - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9a_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2, - (LPCVOID) o9b_, 2 + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9a_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 }, + { (LPCVOID) o9b_, 2 } }; static JMPTAB o8B_[] = { - (LPCVOID) o8B0, F, - (LPCVOID) o8B1, F, - (LPCVOID) o8B2, F, - (LPCVOID) o8B3, F, - (LPCVOID) o8B4, F, - (LPCVOID) o8B5, F, - (LPCVOID) o8B6, F, - (LPCVOID) o8B7, F, - (LPCVOID) o8B8, F, - (LPCVOID) o8B9, F, - (LPCVOID) o8BA, F, - (LPCVOID) o8BB, F, - (LPCVOID) o8BC, F, - (LPCVOID) o8BD, F, - (LPCVOID) o8BE, F, - (LPCVOID) o8BF, F + { (LPCVOID) o8B0, F }, + { (LPCVOID) o8B1, F }, + { (LPCVOID) o8B2, F }, + { (LPCVOID) o8B3, F }, + { (LPCVOID) o8B4, F }, + { (LPCVOID) o8B5, F }, + { (LPCVOID) o8B6, F }, + { (LPCVOID) o8B7, F }, + { (LPCVOID) o8B8, F }, + { (LPCVOID) o8B9, F }, + { (LPCVOID) o8BA, F }, + { (LPCVOID) o8BB, F }, + { (LPCVOID) o8BC, F }, + { (LPCVOID) o8BD, F }, + { (LPCVOID) o8BE, F }, + { (LPCVOID) o8BF, F } }; static JMPTAB o8A_[] = { - (LPCVOID) o8A0, F, - (LPCVOID) o8A1, F, - (LPCVOID) o8A2, F, - (LPCVOID) o8A3, F, - (LPCVOID) o8A4, F, - (LPCVOID) o8A5, F, - (LPCVOID) o8A6, F, - (LPCVOID) o8A7, F, - (LPCVOID) o8A8, F, - (LPCVOID) o8A9, F, - (LPCVOID) o8AA, F, - (LPCVOID) o8AB, F, - (LPCVOID) o8AC, F, - (LPCVOID) o8AD, F, - (LPCVOID) o8AE, F, - (LPCVOID) o8AF, F + { (LPCVOID) o8A0, F }, + { (LPCVOID) o8A1, F }, + { (LPCVOID) o8A2, F }, + { (LPCVOID) o8A3, F }, + { (LPCVOID) o8A4, F }, + { (LPCVOID) o8A5, F }, + { (LPCVOID) o8A6, F }, + { (LPCVOID) o8A7, F }, + { (LPCVOID) o8A8, F }, + { (LPCVOID) o8A9, F }, + { (LPCVOID) o8AA, F }, + { (LPCVOID) o8AB, F }, + { (LPCVOID) o8AC, F }, + { (LPCVOID) o8AD, F }, + { (LPCVOID) o8AE, F }, + { (LPCVOID) o8AF, F } }; static JMPTAB o81B_[] = { - (LPCVOID) o_invalid4, F, - (LPCVOID) o81B1, F, // normally o_invalid4, Apple: LOOP - (LPCVOID) o81B2, F, - (LPCVOID) o81B3, F, - (LPCVOID) o81B4, F, - (LPCVOID) o81B5, F, - (LPCVOID) o81B6, F, - (LPCVOID) o81B7, F, - (LPCVOID) o_invalid4, F, // Apple: SKPTOP - (LPCVOID) o_invalid4, F, // Apple: SKBOT - (LPCVOID) o_invalid4, F, // Apple: SKIP - (LPCVOID) o_invalid4, F, // Apple: SKPLEN - (LPCVOID) o_invalid4, F, // Apple: SKPID - (LPCVOID) o_invalid4, F, // Apple: $SEMI - (LPCVOID) o_invalid4, F, // Apple: DOCOL - (LPCVOID) o_invalid4, F + { (LPCVOID) o_invalid4, F }, + { (LPCVOID) o81B1, F }, // normally o_invalid4, Apple: LOOP + { (LPCVOID) o81B2, F }, + { (LPCVOID) o81B3, F }, + { (LPCVOID) o81B4, F }, + { (LPCVOID) o81B5, F }, + { (LPCVOID) o81B6, F }, + { (LPCVOID) o81B7, F }, + { (LPCVOID) o_invalid4, F }, // Apple: SKPTOP + { (LPCVOID) o_invalid4, F }, // Apple: SKBOT + { (LPCVOID) o_invalid4, F }, // Apple: SKIP + { (LPCVOID) o_invalid4, F }, // Apple: SKPLEN + { (LPCVOID) o_invalid4, F }, // Apple: SKPID + { (LPCVOID) o_invalid4, F }, // Apple: $SEMI + { (LPCVOID) o_invalid4, F }, // Apple: DOCOL + { (LPCVOID) o_invalid4, F } }; static JMPTAB o81Af2_[] = { - (LPCVOID) o81Af20, F, - (LPCVOID) o81Af21, F, - (LPCVOID) o81Af22, F, - (LPCVOID) o81Af23, F, - (LPCVOID) o81Af24, F, - (LPCVOID) o81Af21, F, - (LPCVOID) o81Af22, F, - (LPCVOID) o81Af23, F, - (LPCVOID) o81Af28, F, - (LPCVOID) o81Af29, F, - (LPCVOID) o81Af2A, F, - (LPCVOID) o81Af2B, F, - (LPCVOID) o81Af2C, F, - (LPCVOID) o81Af29, F, - (LPCVOID) o81Af2A, F, - (LPCVOID) o81Af2B, F + { (LPCVOID) o81Af20, F }, + { (LPCVOID) o81Af21, F }, + { (LPCVOID) o81Af22, F }, + { (LPCVOID) o81Af23, F }, + { (LPCVOID) o81Af24, F }, + { (LPCVOID) o81Af21, F }, + { (LPCVOID) o81Af22, F }, + { (LPCVOID) o81Af23, F }, + { (LPCVOID) o81Af28, F }, + { (LPCVOID) o81Af29, F }, + { (LPCVOID) o81Af2A, F }, + { (LPCVOID) o81Af2B, F }, + { (LPCVOID) o81Af2C, F }, + { (LPCVOID) o81Af29, F }, + { (LPCVOID) o81Af2A, F }, + { (LPCVOID) o81Af2B, F } }; static JMPTAB o81Af1_[] = { - (LPCVOID) o81Af10, F, - (LPCVOID) o81Af11, F, - (LPCVOID) o81Af12, F, - (LPCVOID) o81Af13, F, - (LPCVOID) o81Af14, F, - (LPCVOID) o81Af11, F, - (LPCVOID) o81Af12, F, - (LPCVOID) o81Af13, F, - (LPCVOID) o81Af18, F, - (LPCVOID) o81Af19, F, - (LPCVOID) o81Af1A, F, - (LPCVOID) o81Af1B, F, - (LPCVOID) o81Af1C, F, - (LPCVOID) o81Af19, F, - (LPCVOID) o81Af1A, F, - (LPCVOID) o81Af1B, F + { (LPCVOID) o81Af10, F }, + { (LPCVOID) o81Af11, F }, + { (LPCVOID) o81Af12, F }, + { (LPCVOID) o81Af13, F }, + { (LPCVOID) o81Af14, F }, + { (LPCVOID) o81Af11, F }, + { (LPCVOID) o81Af12, F }, + { (LPCVOID) o81Af13, F }, + { (LPCVOID) o81Af18, F }, + { (LPCVOID) o81Af19, F }, + { (LPCVOID) o81Af1A, F }, + { (LPCVOID) o81Af1B, F }, + { (LPCVOID) o81Af1C, F }, + { (LPCVOID) o81Af19, F }, + { (LPCVOID) o81Af1A, F }, + { (LPCVOID) o81Af1B, F } }; static JMPTAB o81Af0_[] = { - (LPCVOID) o81Af00, F, - (LPCVOID) o81Af01, F, - (LPCVOID) o81Af02, F, - (LPCVOID) o81Af03, F, - (LPCVOID) o81Af04, F, - (LPCVOID) o81Af01, F, - (LPCVOID) o81Af02, F, - (LPCVOID) o81Af03, F, - (LPCVOID) o81Af08, F, - (LPCVOID) o81Af09, F, - (LPCVOID) o81Af0A, F, - (LPCVOID) o81Af0B, F, - (LPCVOID) o81Af0C, F, - (LPCVOID) o81Af09, F, - (LPCVOID) o81Af0A, F, - (LPCVOID) o81Af0B, F + { (LPCVOID) o81Af00, F }, + { (LPCVOID) o81Af01, F }, + { (LPCVOID) o81Af02, F }, + { (LPCVOID) o81Af03, F }, + { (LPCVOID) o81Af04, F }, + { (LPCVOID) o81Af01, F }, + { (LPCVOID) o81Af02, F }, + { (LPCVOID) o81Af03, F }, + { (LPCVOID) o81Af08, F }, + { (LPCVOID) o81Af09, F }, + { (LPCVOID) o81Af0A, F }, + { (LPCVOID) o81Af0B, F }, + { (LPCVOID) o81Af0C, F }, + { (LPCVOID) o81Af09, F }, + { (LPCVOID) o81Af0A, F }, + { (LPCVOID) o81Af0B, F } }; static JMPTAB o81A_[] = { - (LPCVOID) o81Af0_, 5, - (LPCVOID) o81Af1_, 5, - (LPCVOID) o81Af2_, 5, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F + { (LPCVOID) o81Af0_, 5 }, + { (LPCVOID) o81Af1_, 5 }, + { (LPCVOID) o81Af2_, 5 }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F } }; static JMPTAB o819_[] = { - (LPCVOID) o819f0, F, - (LPCVOID) o819f1, F, - (LPCVOID) o819f2, F, - (LPCVOID) o819f3, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F + { (LPCVOID) o819f0, F }, + { (LPCVOID) o819f1, F }, + { (LPCVOID) o819f2, F }, + { (LPCVOID) o819f3, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F } }; static JMPTAB o818_[] = { - (LPCVOID) o818f0x, F, - (LPCVOID) o818f1x, F, - (LPCVOID) o818f2x, F, - (LPCVOID) o818f3x, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o818f8x, F, - (LPCVOID) o818f9x, F, - (LPCVOID) o818fAx, F, - (LPCVOID) o818fBx, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F, - (LPCVOID) o_invalid6, F + { (LPCVOID) o818f0x, F }, + { (LPCVOID) o818f1x, F }, + { (LPCVOID) o818f2x, F }, + { (LPCVOID) o818f3x, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o818f8x, F }, + { (LPCVOID) o818f9x, F }, + { (LPCVOID) o818fAx, F }, + { (LPCVOID) o818fBx, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F }, + { (LPCVOID) o_invalid6, F } }; static JMPTAB o81_[] = { - (LPCVOID) o810, F, - (LPCVOID) o811, F, - (LPCVOID) o812, F, - (LPCVOID) o813, F, - (LPCVOID) o814, F, - (LPCVOID) o815, F, - (LPCVOID) o816, F, - (LPCVOID) o817, F, - (LPCVOID) o818_, 4, - (LPCVOID) o819_, 4, - (LPCVOID) o81A_, 4, - (LPCVOID) o81B_, 3, - (LPCVOID) o81C, F, - (LPCVOID) o81D, F, - (LPCVOID) o81E, F, - (LPCVOID) o81F, F + { (LPCVOID) o810, F }, + { (LPCVOID) o811, F }, + { (LPCVOID) o812, F }, + { (LPCVOID) o813, F }, + { (LPCVOID) o814, F }, + { (LPCVOID) o815, F }, + { (LPCVOID) o816, F }, + { (LPCVOID) o817, F }, + { (LPCVOID) o818_, 4 }, + { (LPCVOID) o819_, 4 }, + { (LPCVOID) o81A_, 4 }, + { (LPCVOID) o81B_, 3 }, + { (LPCVOID) o81C, F }, + { (LPCVOID) o81D, F }, + { (LPCVOID) o81E, F }, + { (LPCVOID) o81F, F } }; static JMPTAB o8081_[] = { - (LPCVOID) o80810, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F, - (LPCVOID) o_invalid5, F + { (LPCVOID) o80810, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F }, + { (LPCVOID) o_invalid5, F } }; static JMPTAB o808_[] = { - (LPCVOID) o8080, F, - (LPCVOID) o8081_, 4, - (LPCVOID) o8082X, F, - (LPCVOID) o8083, F, - (LPCVOID) o8084n, F, - (LPCVOID) o8085n, F, - (LPCVOID) o8086n, F, - (LPCVOID) o8087n, F, - (LPCVOID) o8088n, F, - (LPCVOID) o8089n, F, - (LPCVOID) o808An, F, - (LPCVOID) o808Bn, F, - (LPCVOID) o808C, F, - (LPCVOID) o808D, F, - (LPCVOID) o808E, F, - (LPCVOID) o808F, F + { (LPCVOID) o8080, F }, + { (LPCVOID) o8081_, 4 }, + { (LPCVOID) o8082X, F }, + { (LPCVOID) o8083, F }, + { (LPCVOID) o8084n, F }, + { (LPCVOID) o8085n, F }, + { (LPCVOID) o8086n, F }, + { (LPCVOID) o8087n, F }, + { (LPCVOID) o8088n, F }, + { (LPCVOID) o8089n, F }, + { (LPCVOID) o808An, F }, + { (LPCVOID) o808Bn, F }, + { (LPCVOID) o808C, F }, + { (LPCVOID) o808D, F }, + { (LPCVOID) o808E, F }, + { (LPCVOID) o808F, F } }; static JMPTAB o80_[] = { - (LPCVOID) o800, F, - (LPCVOID) o801, F, - (LPCVOID) o802, F, - (LPCVOID) o803, F, - (LPCVOID) o804, F, - (LPCVOID) o805, F, - (LPCVOID) o806, F, - (LPCVOID) o807, F, - (LPCVOID) o808_, 3, - (LPCVOID) o809, F, - (LPCVOID) o80A, F, - (LPCVOID) o80B, F, - (LPCVOID) o80Cn, F, - (LPCVOID) o80Dn, F, - (LPCVOID) o80E, F, - (LPCVOID) o80Fn, F + { (LPCVOID) o800, F }, + { (LPCVOID) o801, F }, + { (LPCVOID) o802, F }, + { (LPCVOID) o803, F }, + { (LPCVOID) o804, F }, + { (LPCVOID) o805, F }, + { (LPCVOID) o806, F }, + { (LPCVOID) o807, F }, + { (LPCVOID) o808_, 3 }, + { (LPCVOID) o809, F }, + { (LPCVOID) o80A, F }, + { (LPCVOID) o80B, F }, + { (LPCVOID) o80Cn, F }, + { (LPCVOID) o80Dn, F }, + { (LPCVOID) o80E, F }, + { (LPCVOID) o80Fn, F } }; static JMPTAB o8_[] = { - (LPCVOID) o80_, 2, - (LPCVOID) o81_, 2, - (LPCVOID) o82n, F, - (LPCVOID) o83n, F, - (LPCVOID) o84n, F, - (LPCVOID) o85n, F, - (LPCVOID) o86n, F, - (LPCVOID) o87n, F, - (LPCVOID) o88n, F, - (LPCVOID) o89n, F, - (LPCVOID) o8A_, 2, - (LPCVOID) o8B_, 2, - (LPCVOID) o8Cd4, F, - (LPCVOID) o8Dd5, F, - (LPCVOID) o8Ed4, F, - (LPCVOID) o8Fd5, F + { (LPCVOID) o80_, 2 }, + { (LPCVOID) o81_, 2 }, + { (LPCVOID) o82n, F }, + { (LPCVOID) o83n, F }, + { (LPCVOID) o84n, F }, + { (LPCVOID) o85n, F }, + { (LPCVOID) o86n, F }, + { (LPCVOID) o87n, F }, + { (LPCVOID) o88n, F }, + { (LPCVOID) o89n, F }, + { (LPCVOID) o8A_, 2 }, + { (LPCVOID) o8B_, 2 }, + { (LPCVOID) o8Cd4, F }, + { (LPCVOID) o8Dd5, F }, + { (LPCVOID) o8Ed4, F }, + { (LPCVOID) o8Fd5, F } }; static JMPTAB o15_[] = { - (LPCVOID) o150a, F, - (LPCVOID) o151a, F, - (LPCVOID) o152a, F, - (LPCVOID) o153a, F, - (LPCVOID) o154a, F, - (LPCVOID) o155a, F, - (LPCVOID) o156a, F, - (LPCVOID) o157a, F, - (LPCVOID) o158x, F, - (LPCVOID) o159x, F, - (LPCVOID) o15Ax, F, - (LPCVOID) o15Bx, F, - (LPCVOID) o15Cx, F, - (LPCVOID) o15Dx, F, - (LPCVOID) o15Ex, F, - (LPCVOID) o15Fx, F + { (LPCVOID) o150a, F }, + { (LPCVOID) o151a, F }, + { (LPCVOID) o152a, F }, + { (LPCVOID) o153a, F }, + { (LPCVOID) o154a, F }, + { (LPCVOID) o155a, F }, + { (LPCVOID) o156a, F }, + { (LPCVOID) o157a, F }, + { (LPCVOID) o158x, F }, + { (LPCVOID) o159x, F }, + { (LPCVOID) o15Ax, F }, + { (LPCVOID) o15Bx, F }, + { (LPCVOID) o15Cx, F }, + { (LPCVOID) o15Dx, F }, + { (LPCVOID) o15Ex, F }, + { (LPCVOID) o15Fx, F } }; static JMPTAB o14_[] = { - (LPCVOID) o140, F, - (LPCVOID) o141, F, - (LPCVOID) o142, F, - (LPCVOID) o143, F, - (LPCVOID) o144, F, - (LPCVOID) o145, F, - (LPCVOID) o146, F, - (LPCVOID) o147, F, - (LPCVOID) o148, F, - (LPCVOID) o149, F, - (LPCVOID) o14A, F, - (LPCVOID) o14B, F, - (LPCVOID) o14C, F, - (LPCVOID) o14D, F, - (LPCVOID) o14E, F, - (LPCVOID) o14F, F + { (LPCVOID) o140, F }, + { (LPCVOID) o141, F }, + { (LPCVOID) o142, F }, + { (LPCVOID) o143, F }, + { (LPCVOID) o144, F }, + { (LPCVOID) o145, F }, + { (LPCVOID) o146, F }, + { (LPCVOID) o147, F }, + { (LPCVOID) o148, F }, + { (LPCVOID) o149, F }, + { (LPCVOID) o14A, F }, + { (LPCVOID) o14B, F }, + { (LPCVOID) o14C, F }, + { (LPCVOID) o14D, F }, + { (LPCVOID) o14E, F }, + { (LPCVOID) o14F, F } }; static JMPTAB o13_[] = { - (LPCVOID) o130, F, - (LPCVOID) o131, F, - (LPCVOID) o132, F, - (LPCVOID) o133, F, - (LPCVOID) o134, F, - (LPCVOID) o135, F, - (LPCVOID) o136, F, - (LPCVOID) o137, F, - (LPCVOID) o138, F, - (LPCVOID) o139, F, - (LPCVOID) o13A, F, - (LPCVOID) o13B, F, - (LPCVOID) o13C, F, - (LPCVOID) o13D, F, - (LPCVOID) o13E, F, - (LPCVOID) o13F, F + { (LPCVOID) o130, F }, + { (LPCVOID) o131, F }, + { (LPCVOID) o132, F }, + { (LPCVOID) o133, F }, + { (LPCVOID) o134, F }, + { (LPCVOID) o135, F }, + { (LPCVOID) o136, F }, + { (LPCVOID) o137, F }, + { (LPCVOID) o138, F }, + { (LPCVOID) o139, F }, + { (LPCVOID) o13A, F }, + { (LPCVOID) o13B, F }, + { (LPCVOID) o13C, F }, + { (LPCVOID) o13D, F }, + { (LPCVOID) o13E, F }, + { (LPCVOID) o13F, F } }; static JMPTAB o12_[] = { - (LPCVOID) o120, F, - (LPCVOID) o121, F, - (LPCVOID) o122, F, - (LPCVOID) o123, F, - (LPCVOID) o124, F, - (LPCVOID) o121, F, - (LPCVOID) o122, F, - (LPCVOID) o123, F, - (LPCVOID) o128, F, - (LPCVOID) o129, F, - (LPCVOID) o12A, F, - (LPCVOID) o12B, F, - (LPCVOID) o12C, F, - (LPCVOID) o129, F, - (LPCVOID) o12A, F, - (LPCVOID) o12B, F + { (LPCVOID) o120, F }, + { (LPCVOID) o121, F }, + { (LPCVOID) o122, F }, + { (LPCVOID) o123, F }, + { (LPCVOID) o124, F }, + { (LPCVOID) o121, F }, + { (LPCVOID) o122, F }, + { (LPCVOID) o123, F }, + { (LPCVOID) o128, F }, + { (LPCVOID) o129, F }, + { (LPCVOID) o12A, F }, + { (LPCVOID) o12B, F }, + { (LPCVOID) o12C, F }, + { (LPCVOID) o129, F }, + { (LPCVOID) o12A, F }, + { (LPCVOID) o12B, F } }; static JMPTAB o11_[] = { - (LPCVOID) o110, F, - (LPCVOID) o111, F, - (LPCVOID) o112, F, - (LPCVOID) o113, F, - (LPCVOID) o114, F, - (LPCVOID) o111, F, - (LPCVOID) o112, F, - (LPCVOID) o113, F, - (LPCVOID) o118, F, - (LPCVOID) o119, F, - (LPCVOID) o11A, F, - (LPCVOID) o11B, F, - (LPCVOID) o11C, F, - (LPCVOID) o119, F, - (LPCVOID) o11A, F, - (LPCVOID) o11B, F + { (LPCVOID) o110, F }, + { (LPCVOID) o111, F }, + { (LPCVOID) o112, F }, + { (LPCVOID) o113, F }, + { (LPCVOID) o114, F }, + { (LPCVOID) o111, F }, + { (LPCVOID) o112, F }, + { (LPCVOID) o113, F }, + { (LPCVOID) o118, F }, + { (LPCVOID) o119, F }, + { (LPCVOID) o11A, F }, + { (LPCVOID) o11B, F }, + { (LPCVOID) o11C, F }, + { (LPCVOID) o119, F }, + { (LPCVOID) o11A, F }, + { (LPCVOID) o11B, F } }; static JMPTAB o10_[] = { - (LPCVOID) o100, F, - (LPCVOID) o101, F, - (LPCVOID) o102, F, - (LPCVOID) o103, F, - (LPCVOID) o104, F, - (LPCVOID) o101, F, - (LPCVOID) o102, F, - (LPCVOID) o103, F, - (LPCVOID) o108, F, - (LPCVOID) o109, F, - (LPCVOID) o10A, F, - (LPCVOID) o10B, F, - (LPCVOID) o10C, F, - (LPCVOID) o109, F, - (LPCVOID) o10A, F, - (LPCVOID) o10B, F + { (LPCVOID) o100, F }, + { (LPCVOID) o101, F }, + { (LPCVOID) o102, F }, + { (LPCVOID) o103, F }, + { (LPCVOID) o104, F }, + { (LPCVOID) o101, F }, + { (LPCVOID) o102, F }, + { (LPCVOID) o103, F }, + { (LPCVOID) o108, F }, + { (LPCVOID) o109, F }, + { (LPCVOID) o10A, F }, + { (LPCVOID) o10B, F }, + { (LPCVOID) o10C, F }, + { (LPCVOID) o109, F }, + { (LPCVOID) o10A, F }, + { (LPCVOID) o10B, F } }; static JMPTAB o1_[] = { - (LPCVOID) o10_, 2, - (LPCVOID) o11_, 2, - (LPCVOID) o12_, 2, - (LPCVOID) o13_, 2, - (LPCVOID) o14_, 2, - (LPCVOID) o15_, 2, - (LPCVOID) o16x, F, - (LPCVOID) o17x, F, - (LPCVOID) o18x, F, - (LPCVOID) o19d2, F, - (LPCVOID) o1Ad4, F, - (LPCVOID) o1Bd5, F, - (LPCVOID) o1Cx, F, - (LPCVOID) o1Dd2, F, - (LPCVOID) o1Ed4, F, - (LPCVOID) o1Fd5, F + { (LPCVOID) o10_, 2 }, + { (LPCVOID) o11_, 2 }, + { (LPCVOID) o12_, 2 }, + { (LPCVOID) o13_, 2 }, + { (LPCVOID) o14_, 2 }, + { (LPCVOID) o15_, 2 }, + { (LPCVOID) o16x, F }, + { (LPCVOID) o17x, F }, + { (LPCVOID) o18x, F }, + { (LPCVOID) o19d2, F }, + { (LPCVOID) o1Ad4, F }, + { (LPCVOID) o1Bd5, F }, + { (LPCVOID) o1Cx, F }, + { (LPCVOID) o1Dd2, F }, + { (LPCVOID) o1Ed4, F }, + { (LPCVOID) o1Fd5, F } }; static JMPTAB o0E_[] = { - (LPCVOID) o0Ef0, F, - (LPCVOID) o0Ef1, F, - (LPCVOID) o0Ef2, F, - (LPCVOID) o0Ef3, F, - (LPCVOID) o0Ef4, F, - (LPCVOID) o0Ef5, F, - (LPCVOID) o0Ef6, F, - (LPCVOID) o0Ef7, F, - (LPCVOID) o0Ef8, F, - (LPCVOID) o0Ef9, F, - (LPCVOID) o0EfA, F, - (LPCVOID) o0EfB, F, - (LPCVOID) o0EfC, F, - (LPCVOID) o0EfD, F, - (LPCVOID) o0EfE, F, - (LPCVOID) o0EfF, F + { (LPCVOID) o0Ef0, F }, + { (LPCVOID) o0Ef1, F }, + { (LPCVOID) o0Ef2, F }, + { (LPCVOID) o0Ef3, F }, + { (LPCVOID) o0Ef4, F }, + { (LPCVOID) o0Ef5, F }, + { (LPCVOID) o0Ef6, F }, + { (LPCVOID) o0Ef7, F }, + { (LPCVOID) o0Ef8, F }, + { (LPCVOID) o0Ef9, F }, + { (LPCVOID) o0EfA, F }, + { (LPCVOID) o0EfB, F }, + { (LPCVOID) o0EfC, F }, + { (LPCVOID) o0EfD, F }, + { (LPCVOID) o0EfE, F }, + { (LPCVOID) o0EfF, F } }; static JMPTAB o0_[] = { - (LPCVOID) o00, F, - (LPCVOID) o01, F, - (LPCVOID) o02, F, - (LPCVOID) o03, F, - (LPCVOID) o04, F, - (LPCVOID) o05, F, - (LPCVOID) o06, F, - (LPCVOID) o07, F, - (LPCVOID) o08, F, - (LPCVOID) o09, F, - (LPCVOID) o0A, F, - (LPCVOID) o0B, F, - (LPCVOID) o0C, F, - (LPCVOID) o0D, F, - (LPCVOID) o0E_, 3, - (LPCVOID) o0F, F + { (LPCVOID) o00, F }, + { (LPCVOID) o01, F }, + { (LPCVOID) o02, F }, + { (LPCVOID) o03, F }, + { (LPCVOID) o04, F }, + { (LPCVOID) o05, F }, + { (LPCVOID) o06, F }, + { (LPCVOID) o07, F }, + { (LPCVOID) o08, F }, + { (LPCVOID) o09, F }, + { (LPCVOID) o0A, F }, + { (LPCVOID) o0B, F }, + { (LPCVOID) o0C, F }, + { (LPCVOID) o0D, F }, + { (LPCVOID) o0E_, 3 }, + { (LPCVOID) o0F, F } }; static JMPTAB o_[] = { - (LPCVOID) o0_, 1, - (LPCVOID) o1_, 1, - (LPCVOID) o2n, F, - (LPCVOID) o3X, F, - (LPCVOID) o4d2, F, - (LPCVOID) o5d2, F, - (LPCVOID) o6d3, F, - (LPCVOID) o7d3, F, - (LPCVOID) o8_, 1, - (LPCVOID) o9_, 1, - (LPCVOID) oA_, 1, - (LPCVOID) oB_, 1, - (LPCVOID) oC_, 1, - (LPCVOID) oD_, 1, - (LPCVOID) oE_, 1, - (LPCVOID) oF_, 1 + { (LPCVOID) o0_, 1 }, + { (LPCVOID) o1_, 1 }, + { (LPCVOID) o2n, F }, + { (LPCVOID) o3X, F }, + { (LPCVOID) o4d2, F }, + { (LPCVOID) o5d2, F }, + { (LPCVOID) o6d3, F }, + { (LPCVOID) o7d3, F }, + { (LPCVOID) o8_, 1 }, + { (LPCVOID) o9_, 1 }, + { (LPCVOID) oA_, 1 }, + { (LPCVOID) oB_, 1 }, + { (LPCVOID) oC_, 1 }, + { (LPCVOID) oD_, 1 }, + { (LPCVOID) oE_, 1 }, + { (LPCVOID) oF_, 1 } }; // opcode dispatcher diff --git a/app/src/main/cpp/core/lodepng.c b/app/src/main/cpp/core/lodepng.c index 2c807ef..e0dcdd2 100644 --- a/app/src/main/cpp/core/lodepng.c +++ b/app/src/main/cpp/core/lodepng.c @@ -664,7 +664,7 @@ which is possible in case of only 0 or 1 present symbols. */ static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { static const unsigned headsize = 1u << FIRSTBITS; /*size of the first table*/ static const unsigned mask = (1u << FIRSTBITS) /*headsize*/ - 1u; - unsigned i, numpresent, pointer, size; /*total table size*/ + size_t i, numpresent, pointer, size; /*total table size*/ unsigned* maxlens = (unsigned*)lodepng_malloc(headsize * sizeof(unsigned)); if(!maxlens) return 83; /*alloc fail*/ @@ -683,7 +683,7 @@ static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { size = headsize; for(i = 0; i < headsize; ++i) { unsigned l = maxlens[i]; - if(l > FIRSTBITS) size += (1u << (l - FIRSTBITS)); + if(l > FIRSTBITS) size += (((size_t)1) << (l - FIRSTBITS)); } tree->table_len = (unsigned char*)lodepng_malloc(size * sizeof(*tree->table_len)); tree->table_value = (unsigned short*)lodepng_malloc(size * sizeof(*tree->table_value)); @@ -701,8 +701,8 @@ static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { unsigned l = maxlens[i]; if(l <= FIRSTBITS) continue; tree->table_len[i] = l; - tree->table_value[i] = pointer; - pointer += (1u << (l - FIRSTBITS)); + tree->table_value[i] = (unsigned short)pointer; + pointer += (((size_t)1) << (l - FIRSTBITS)); } lodepng_free(maxlens); @@ -726,7 +726,7 @@ static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { unsigned index = reverse | (j << l); if(tree->table_len[index] != 16) return 55; /*invalid tree: long symbol shares prefix with short symbol*/ tree->table_len[index] = l; - tree->table_value[index] = i; + tree->table_value[index] = (unsigned short)i; } } else { /*long symbol, shares prefix with other long symbols in first lookup table, needs second lookup*/ @@ -743,7 +743,7 @@ static unsigned HuffmanTree_makeTable(HuffmanTree* tree) { unsigned reverse2 = reverse >> FIRSTBITS; /* l - FIRSTBITS bits */ unsigned index2 = start + (reverse2 | (j << (l - FIRSTBITS))); tree->table_len[index2] = l; - tree->table_value[index2] = i; + tree->table_value[index2] = (unsigned short)i; } } } @@ -2886,7 +2886,7 @@ static unsigned lodepng_chunk_createv(ucvector* out, } unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, - unsigned length, const char* type, const unsigned char* data) { + size_t length, const char* type, const unsigned char* data) { ucvector v = ucvector_init(*out, *outsize); unsigned error = lodepng_chunk_createv(&v, length, type, data); *out = v.data; @@ -3363,7 +3363,7 @@ unsigned lodepng_info_copy(LodePNGInfo* dest, const LodePNGInfo* source) { static void addColorBits(unsigned char* out, size_t index, unsigned bits, unsigned in) { unsigned m = bits == 1 ? 7 : bits == 2 ? 3 : 1; /*8 / bits - 1*/ /*p = the partial index in the byte, e.g. with 4 palettebits it is 0 for first half or 1 for second half*/ - unsigned p = (unsigned)index & m; + unsigned p = (unsigned) index & m; in &= (1u << bits) - 1u; /*filter out any other bits of the input value*/ in = in << (bits * (m - p)); if(p == 0) out[index * bits / 8u] = in; @@ -5889,7 +5889,7 @@ static size_t ilog2i(size_t i) { l = ilog2(i); /* approximate i*log2(i): l is integer logarithm, ((i - (1u << l)) << 1u) linearly approximates the missing fractional part multiplied by i */ - return i * l + ((i - ((size_t) 1u << l)) << 1u); + return i * l + ((i - (((size_t)1) << l)) << 1u); } static unsigned filter(unsigned char* out, const unsigned char* in, unsigned w, unsigned h, diff --git a/app/src/main/cpp/core/lodepng.h b/app/src/main/cpp/core/lodepng.h index 81d4985..3f3649d 100644 --- a/app/src/main/cpp/core/lodepng.h +++ b/app/src/main/cpp/core/lodepng.h @@ -1001,7 +1001,7 @@ and data separately. The type is a 4-letter string. The out variable and outsize are updated to reflect the new reallocated buffer. Returne error code (0 if it went ok) */ -unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, unsigned length, +unsigned lodepng_chunk_create(unsigned char** out, size_t* outsize, size_t length, const char* type, const unsigned char* data); diff --git a/app/src/main/cpp/core/mops.c b/app/src/main/cpp/core/mops.c index dfbb2e0..ded208d 100644 --- a/app/src/main/cpp/core/mops.c +++ b/app/src/main/cpp/core/mops.c @@ -1002,9 +1002,9 @@ static DWORD ReadT2Acc(VOID) // maybe CPU speed measurement, slow down the next 10 CPU opcodes if (dwCycDif < 150) { - InitAdjustSpeed(); // init variables if necessary EnterCriticalSection(&csSlowLock); { + InitAdjustSpeed(); // init variables if necessary nOpcSlow = 10; // slow down next 10 opcodes } LeaveCriticalSection(&csSlowLock); @@ -1146,9 +1146,9 @@ VOID ReadIO(BYTE *a, DWORD d, DWORD s, BOOL bUpdate) // CPU running with max. speed we may get a timeout overflow // -> to avoid this slow down CPU speed on transmit buffer full - InitAdjustSpeed(); // init variables if necessary EnterCriticalSection(&csSlowLock); { + InitAdjustSpeed(); // init variables if necessary nOpcSlow = 10; // slow down next 10 opcodes } LeaveCriticalSection(&csSlowLock); diff --git a/app/src/main/cpp/core/resource.h b/app/src/main/cpp/core/resource.h index 16274ad..601e56a 100644 --- a/app/src/main/cpp/core/resource.h +++ b/app/src/main/cpp/core/resource.h @@ -121,62 +121,67 @@ #define IDC_DEBUG_DATA_BUT 1084 #define IDC_DEBUG_DATA_STARTADDR 1085 #define IDC_DEBUG_DATA_ENDADDR 1086 -#define IDC_DEBUG_SET_SYMB 1087 -#define IDC_DEBUG_SET_MODEL 1088 -#define IDC_DEBUG_SET_FILE 1089 -#define IDC_DEBUG_SET_BROWSE 1090 -#define IDC_DEBUG_STACK 1091 -#define IDC_STATIC_BREAKPOINT 1092 -#define IDC_BREAKEDIT_ADD 1093 -#define IDC_BREAKEDIT_DELETE 1094 -#define IDC_BREAKEDIT_WND 1095 -#define IDC_STATIC_MMU 1096 -#define IDC_MMU_IO_A 1097 -#define IDC_MMU_NCE2_A 1098 -#define IDC_MMU_CE1_A 1099 -#define IDC_MMU_CE2_A 1100 -#define IDC_MMU_NCE3_A 1101 -#define IDC_MMU_IO_S 1102 -#define IDC_MMU_CE1_S 1103 -#define IDC_MMU_CE2_S 1104 -#define IDC_MMU_NCE2_S 1105 -#define IDC_MMU_NCE3_S 1106 -#define IDC_STATIC_MISC 1107 -#define IDC_MISC_BS_TXT 1108 -#define IDC_INSTR_TEXT 1109 -#define IDC_INSTR_CODE 1110 -#define IDC_INSTR_COPY 1111 -#define IDC_INSTR_CLEAR 1112 -#define IDC_PROFILE_LASTCYCLES 1113 -#define IDC_PROFILE_LASTTIME 1114 -#define IDC_BPCODE 1115 -#define IDC_BPRPL 1116 -#define IDC_BPACCESS 1117 -#define IDC_BPREAD 1118 -#define IDC_BPWRITE 1119 -#define IDC_FIND_DATA 1120 -#define IDC_FIND_PREV 1121 -#define IDC_FIND_NEXT 1122 -#define IDC_FIND_ASCII 1123 -#define IDC_ADDR20_24 1124 -#define IDC_ADDR25_27 1125 -#define IDC_ADDR28_29 1126 -#define IDC_ADDR30_34 1127 -#define IDC_RPLVIEW_DATA 1128 -#define IDC_MACRO_SLOW 1129 -#define IDC_MACRO_FAST 1130 -#define IDC_MACRO_SLIDER 1131 -#define IDC_MACRO_REAL 1132 -#define IDC_MACRO_MANUAL 1133 -#define IDC_SOUND_SLIDER 1134 -#define IDC_SOUND_DEVICE 1135 -#define IDC_TRACE_FILE 1136 -#define IDC_TRACE_BROWSE 1137 -#define IDC_TRACE_NEW 1138 -#define IDC_TRACE_APPEND 1139 -#define IDC_TRACE_REGISTER 1140 -#define IDC_TRACE_MMU 1141 -#define IDC_TRACE_OPCODE 1142 +#define IDC_DEBUG_DATA_SAVE_8BIT 1087 +#define IDC_DEBUG_DATA_SAVE_4BIT 1088 +#define IDC_DEBUG_DATA_LOAD_8BIT 1089 +#define IDC_DEBUG_DATA_LOAD_4BIT 1090 +#define IDC_DEBUG_DATA_LOAD_ABIT 1091 +#define IDC_DEBUG_SET_SYMB 1092 +#define IDC_DEBUG_SET_MODEL 1093 +#define IDC_DEBUG_SET_FILE 1094 +#define IDC_DEBUG_SET_BROWSE 1095 +#define IDC_DEBUG_STACK 1096 +#define IDC_STATIC_BREAKPOINT 1097 +#define IDC_BREAKEDIT_ADD 1098 +#define IDC_BREAKEDIT_DELETE 1099 +#define IDC_BREAKEDIT_WND 1100 +#define IDC_STATIC_MMU 1101 +#define IDC_MMU_IO_A 1102 +#define IDC_MMU_NCE2_A 1103 +#define IDC_MMU_CE1_A 1104 +#define IDC_MMU_CE2_A 1105 +#define IDC_MMU_NCE3_A 1106 +#define IDC_MMU_IO_S 1107 +#define IDC_MMU_CE1_S 1108 +#define IDC_MMU_CE2_S 1109 +#define IDC_MMU_NCE2_S 1110 +#define IDC_MMU_NCE3_S 1111 +#define IDC_STATIC_MISC 1112 +#define IDC_MISC_BS_TXT 1113 +#define IDC_INSTR_TEXT 1114 +#define IDC_INSTR_CODE 1115 +#define IDC_INSTR_COPY 1116 +#define IDC_INSTR_CLEAR 1117 +#define IDC_PROFILE_LASTCYCLES 1118 +#define IDC_PROFILE_LASTTIME 1119 +#define IDC_BPCODE 1120 +#define IDC_BPRPL 1121 +#define IDC_BPACCESS 1122 +#define IDC_BPREAD 1123 +#define IDC_BPWRITE 1124 +#define IDC_FIND_DATA 1125 +#define IDC_FIND_PREV 1126 +#define IDC_FIND_NEXT 1127 +#define IDC_FIND_ASCII 1128 +#define IDC_ADDR20_24 1129 +#define IDC_ADDR25_27 1130 +#define IDC_ADDR28_29 1131 +#define IDC_ADDR30_34 1132 +#define IDC_RPLVIEW_DATA 1133 +#define IDC_MACRO_SLOW 1134 +#define IDC_MACRO_FAST 1135 +#define IDC_MACRO_SLIDER 1136 +#define IDC_MACRO_REAL 1137 +#define IDC_MACRO_MANUAL 1138 +#define IDC_SOUND_SLIDER 1139 +#define IDC_SOUND_DEVICE 1140 +#define IDC_TRACE_FILE 1141 +#define IDC_TRACE_BROWSE 1142 +#define IDC_TRACE_NEW 1143 +#define IDC_TRACE_APPEND 1144 +#define IDC_TRACE_REGISTER 1145 +#define IDC_TRACE_MMU 1146 +#define IDC_TRACE_OPCODE 1147 #define ID_FILE_NEW 40001 #define ID_FILE_OPEN 40002 #define ID_FILE_SAVE 40003 @@ -257,7 +262,7 @@ #ifndef APSTUDIO_READONLY_SYMBOLS #define _APS_NEXT_RESOURCE_VALUE 131 #define _APS_NEXT_COMMAND_VALUE 40074 -#define _APS_NEXT_CONTROL_VALUE 1143 +#define _APS_NEXT_CONTROL_VALUE 1148 #define _APS_NEXT_SYMED_VALUE 109 #endif #endif diff --git a/app/src/main/cpp/core/romcrc.c b/app/src/main/cpp/core/romcrc.c index fd0c172..22a6891 100644 --- a/app/src/main/cpp/core/romcrc.c +++ b/app/src/main/cpp/core/romcrc.c @@ -241,8 +241,8 @@ VOID RebuildRomCrc(VOID) { // has no Crc } - // HP49G - if (cCurrentRomType == 'X' && dwRomSize == _KB(2048)) + // HP48GII/49G+/50G/49G + if ((strchr("2QX",cCurrentRomType)) && dwRomSize == _KB(2048)) { CorrectAllFlashPages(); // go through all pages } diff --git a/app/src/main/cpp/core/serial.c b/app/src/main/cpp/core/serial.c index 0433a06..6b5309f 100644 --- a/app/src/main/cpp/core/serial.c +++ b/app/src/main/cpp/core/serial.c @@ -104,7 +104,6 @@ BOOL CommOpen(LPTSTR strWirePort,LPTSTR strIrPort) LPCTSTR strPort = (Chipset.IORam[IR_CTRL] & EIRU) ? strIrPort : strWirePort; - _ASSERT(Chipset.IORam[IOC] & SON); // UART on CommClose(); // close port if already open dwBytesRead = 0L; // no bytes received diff --git a/app/src/main/cpp/core/settings.c b/app/src/main/cpp/core/settings.c index 6d5d539..44721ca 100644 --- a/app/src/main/cpp/core/settings.c +++ b/app/src/main/cpp/core/settings.c @@ -182,23 +182,24 @@ VOID ReadSettings(VOID) disassembler_mode = ReadInt(_T("Disassembler"),_T("Mnemonics"),disassembler_mode); disassembler_symb = ReadInt(_T("Disassembler"),_T("Symbolic"),disassembler_symb); // Emulator - bShowTitle = ReadInt(_T("Emulator"),_T("ShowTitle"),bShowTitle); - bShowMenu = ReadInt(_T("Emulator"),_T("ShowMenu"),bShowMenu); - bAlwaysOnTop = ReadInt(_T("Emulator"),_T("AlwaysOnTop"),bAlwaysOnTop); - bActFollowsMouse = ReadInt(_T("Emulator"),_T("ActivationFollowsMouse"),bActFollowsMouse); - bClientWinMove = ReadInt(_T("Emulator"),_T("ClientWinMove"),bClientWinMove); - bSingleInstance = ReadInt(_T("Emulator"),_T("SingleInstance"),bSingleInstance); - bRealSpeed = ReadInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed); - dwSXCycles = ReadInt(_T("Emulator"),_T("SXCycles"),dwSXCycles); - 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); - uWaveDevId = ReadInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId); - dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol); - dwWaveTime = ReadInt(_T("Emulator"),_T("WaveTime"),dwWaveTime); + bShowTitle = ReadInt(_T("Emulator"),_T("ShowTitle"),bShowTitle); + bShowMenu = ReadInt(_T("Emulator"),_T("ShowMenu"),bShowMenu); + bAlwaysOnTop = ReadInt(_T("Emulator"),_T("AlwaysOnTop"),bAlwaysOnTop); + bActFollowsMouse = ReadInt(_T("Emulator"),_T("ActivationFollowsMouse"),bActFollowsMouse); + bClientWinMove = ReadInt(_T("Emulator"),_T("ClientWinMove"),bClientWinMove); + bSingleInstance = ReadInt(_T("Emulator"),_T("SingleInstance"),bSingleInstance); + bRealSpeed = ReadInt(_T("Emulator"),_T("RealSpeed"),bRealSpeed); + dwSXCycles = ReadInt(_T("Emulator"),_T("SXCycles"),dwSXCycles); + 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); + uWaveDevId = ReadInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId); + dwWaveVol = ReadInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol); + dwWaveTime = ReadInt(_T("Emulator"),_T("WaveTime"),dwWaveTime); + bLocaleDecimalPoint = ReadInt(_T("Emulator"),_T("LocaleDecimalPoint"),bLocaleDecimalPoint); // LowBat bLowBatDisable = ReadInt(_T("LowBat"),_T("Disable"),bLowBatDisable); // Macro @@ -254,6 +255,7 @@ VOID WriteSettings(VOID) WriteInt(_T("Emulator"),_T("WaveDeviceId"),uWaveDevId); WriteInt(_T("Emulator"),_T("WaveVolume"),dwWaveVol); WriteInt(_T("Emulator"),_T("WaveTime"),dwWaveTime); + WriteInt(_T("Emulator"),_T("LocaleDecimalPoint"),bLocaleDecimalPoint); // LowBat WriteInt(_T("LowBat"),_T("Disable"),bLowBatDisable); // Macro diff --git a/app/src/main/cpp/core/stack.c b/app/src/main/cpp/core/stack.c index 570dcbc..2f68478 100644 --- a/app/src/main/cpp/core/stack.c +++ b/app/src/main/cpp/core/stack.c @@ -19,6 +19,7 @@ #define DOCSTR 0x02A2C // String BOOL bDetectClpObject = TRUE; // try to detect clipboard object +BOOL bLocaleDecimalPoint = FALSE; // use decimal point character from calculator //################ //# @@ -26,6 +27,100 @@ BOOL bDetectClpObject = TRUE; // try to detect clipboard object //# //################ +// +// check if cGroup character is thousands separator +// +static BOOL CheckThousandGroup(LPCTSTR cp,TCHAR cGroup) +{ + UINT uLastPos; + UINT i; + + // get decimal point + CONST TCHAR cDecimalPoint = cGroup ^ (_T('.') ^ _T(',')); + + BOOL bFound = FALSE; // 1st separator not found + BOOL bPosOK = TRUE; + + for (i = 0; bPosOK && cp[i] != cDecimalPoint && cp[i] != 0; ++i) + { + if (cp[i] == cGroup) // found separator + { + if (bFound) + { + // verify separator position + bPosOK = (uLastPos + 4 == i); + } + + uLastPos = i; // last position of separator + bFound = TRUE; // separator found + } + } + + // check last grouping + return bPosOK && bFound && (uLastPos + 4 == i); +} + +// +// get decimal point from clipboard +// +static TCHAR GetClpbrdDecimalPoint(LPCTSTR cp) +{ + TCHAR cDec = 0; // default for invalid decimal point detection + + TCHAR cLast = 0; // last decimal point + UINT uPoint = 0; // no. of points + UINT uComma = 0; // no. of commas + + LPCTSTR p; + for (p = cp; *p; ++p) // count '.' and ',' characters + { + if (*p == _T('.')) + { + cLast = *p; // last occurance + ++uPoint; + } + if (*p == _T(',')) + { + cLast = *p; // last occurance + ++uComma; + } + } + + if (uComma == 0 && uPoint == 0) // none of both + { + cDec = _T('.'); + } + else if (uComma == 1 && uPoint == 0) // one single ',' + { + cDec = _T(','); + } + else if (uComma == 0 && uPoint == 1) // one single '.' + { + cDec = _T('.'); + } + else if (uComma == 1 && uPoint == 1) // one single ',' and '.' + { + // change from ',' to '.' or vice versa + const TCHAR cFirst = cLast ^ (_T('.') ^ _T(',')); + + if (CheckThousandGroup(cp,cFirst)) // check if 1st character is grouped + { + cDec = cLast; + } + } + // multiple grouped ',' and single '.' + else if (uComma > 1 && uPoint == 1 && CheckThousandGroup(cp,_T(','))) + { + cDec = _T('.'); + } + // multiple grouped '.' and single ',' + else if (uComma == 1 && uPoint > 1 && CheckThousandGroup(cp,_T('.'))) + { + cDec = _T(','); + } + return cDec; +} + static LPTSTR Trim(LPCTSTR cp) { LPCTSTR pcWs = _T(" \t\n\r"); // valid whitespace characters @@ -238,22 +333,23 @@ static INT RPL_GetBcd(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHAR cD static __inline INT SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,LPBYTE pbyNum,INT nSize) { - TCHAR cVc[] = _T(".0123456789eE+-"); + TCHAR cVc[] = _T(",.0123456789eE+-"); BYTE byNum[80]; INT i,nIp,nDp,nMaxExp; LONG lExp; - cVc[0] = cDec; // replace decimal char + // get thousand separator + const TCHAR cThousand = cDec ^ (_T('.') ^ _T(',')); if ( nMantLen + nExpLen >= nSize // destination buffer too small || !*cp // empty string - || _tcsspn(cp,cVc) != (SIZE_T) lstrlen(cp) // real contain only these numbers + || _tcsspn(cp,cVc) != (SIZE_T) lstrlen(cp) // real doesn't contain only these numbers || (SIZE_T) 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 + if (*cp == _T('-') || *cp == _T('+')) // skip sign nibble cp++; // only '.', '0' .. '9' are valid here @@ -264,8 +360,13 @@ static __inline INT SetBcd(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec, if (*cp != cDec) // no decimal point { // count integer part - while (*cp >= _T('0') && *cp <= _T('9')) - byNum[++nIp] = *cp++ - _T('0'); + for (; (*cp >= _T('0') && *cp <= _T('9')) || *cp == cThousand; ++cp) + { + if (*cp != cThousand) // not thousand separator + { + byNum[++nIp] = *cp - _T('0'); + } + } if (!nIp) return 0; } @@ -376,8 +477,8 @@ static INT RPL_GetComplex(BYTE CONST *pbyNum,INT nMantLen,INT nExpLen,CONST TCHA TCHAR cSep; cSep = (cDec == _T('.')) // current separator - ? _T(',') // radix mark '.' -> ',' separator - : _T(';'); // radix mark ',' -> ';' separator + ? _T(',') // decimal point '.' -> ',' separator + : _T(';'); // decimal comma ',' -> ';' separator nPos = 0; // write buffer position @@ -420,8 +521,8 @@ static INT RPL_SetComplex(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,L nLen = 0; // read data length cSep = (cDec == _T('.')) // current separator - ? _T(',') // radix mark '.' -> ',' separator - : _T(';'); // radix mark ',' -> ';' separator + ? _T(',') // decimal point '.' -> ',' separator + : _T(';'); // decimal comma ',' -> ';' separator if ((pszData = Trim(cp)) != NULL) // create a trimmed working copy of the string { @@ -468,8 +569,14 @@ static INT RPL_SetComplex(LPCTSTR cp,INT nMantLen,INT nExpLen,CONST TCHAR cDec,L static TCHAR GetRadix(VOID) { - // get locale decimal point - // GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,&cDecimal,1); + if (bLocaleDecimalPoint) // use Windows Locale decimal point character + { + TCHAR cDecimal[2]; + + // get locale decimal point with zero terminator + GetLocaleInfo(LOCALE_USER_DEFAULT,LOCALE_SDECIMAL,cDecimal,2); + return cDecimal[0]; + } return RPL_GetSystemFlag(fnRadix) ? _T(',') : _T('.'); } @@ -683,9 +790,11 @@ LRESULT OnStackPaste(VOID) // paste data to stack if ((lpstrClipdata = (LPCTSTR) GlobalLock(hClipObj))) { + TCHAR cDec; BYTE byNumber[128]; DWORD dwAddress; - INT s; + + INT s = 0; // no valid object do { @@ -715,9 +824,14 @@ LRESULT OnStackPaste(VOID) // paste data to stack } } - // try to convert string to real format - _ASSERT(16 <= ARRAYSIZEOF(byNumber)); - s = RPL_SetBcd(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber)); + cDec = GetClpbrdDecimalPoint(lpstrClipdata); + + if (cDec) // valid decimal point + { + // try to convert string to real format + _ASSERT(16 <= ARRAYSIZEOF(byNumber)); + s = RPL_SetBcd(lpstrClipdata,12,3,cDec,byNumber,sizeof(byNumber)); + } if (s > 0) // is a real number { @@ -736,9 +850,14 @@ LRESULT OnStackPaste(VOID) // paste data to stack break; } + // search for ';' as separator + cDec = (_tcschr(lpstrClipdata,_T(';')) != NULL) + ? _T(',') // decimal comma + : _T('.'); // decimal point + // try to convert string to complex format _ASSERT(32 <= ARRAYSIZEOF(byNumber)); - s = RPL_SetComplex(lpstrClipdata,12,3,GetRadix(),byNumber,sizeof(byNumber)); + s = RPL_SetComplex(lpstrClipdata,12,3,cDec,byNumber,sizeof(byNumber)); if (s > 0) // is a real complex { diff --git a/app/src/main/cpp/core/timer.c b/app/src/main/cpp/core/timer.c index 15cf9c5..7f9c733 100644 --- a/app/src/main/cpp/core/timer.c +++ b/app/src/main/cpp/core/timer.c @@ -247,7 +247,7 @@ VOID SetHP48Time(VOID) // set date and time ULONGLONG ticks, time; DWORD dw; WORD crc, i; - BYTE p[4]; + LPBYTE pbyTime; _ASSERT(sizeof(ULONGLONG) == 8); // check size of datatype @@ -282,29 +282,23 @@ VOID SetHP48Time(VOID) // set date and time time = ticks; // save for calc. timeout time += OFF_TIME; // add 10 min for auto off - dw = RPLTIME; // HP addresses for clock in port0 + pbyTime = Port0 + RPLTIME; // HP addresses for clock in port0 crc = 0x0; // reset crc value - for (i = 0; i < 13; ++i, ++dw) // write date and time + for (i = 0; i < 13; ++i) // write date and time { - *p = (BYTE) ticks & 0xf; - crc = (crc >> 4) ^ (((crc ^ ((WORD) *p)) & 0xf) * 0x1081); - Port0[dw] = *p; // always store in port0 + *pbyTime = (BYTE) ticks & 0xf; // time + crc = UpCRC(crc,*pbyTime); ticks >>= 4; - } - Nunpack(p,crc,4); // write crc - 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 - { - Port0[dw] = (BYTE) time & 0xf; // always store in port0 + pbyTime[13+4] = (BYTE) time & 0xf; // auto off time >>= 4; + ++pbyTime; } - Port0[dw] = 0xf; // always store in port0 + Nunpack(pbyTime,crc,4); // write crc + + pbyTime[13+4] = 0xf; return; } diff --git a/app/src/main/cpp/core/udp.c b/app/src/main/cpp/core/udp.c index 7e20930..09972f6 100644 --- a/app/src/main/cpp/core/udp.c +++ b/app/src/main/cpp/core/udp.c @@ -22,13 +22,10 @@ VOID ResetUdp(VOID) BOOL SendByteUdp(BYTE byData) { - WSADATA wsd; SOCKET sClient; BOOL bErr = TRUE; - VERIFY(WSAStartup(MAKEWORD(1,1),&wsd) == 0); - // IP address not specified if (sServer.sin_addr.s_addr == INADDR_NONE) { @@ -72,7 +69,5 @@ BOOL SendByteUdp(BYTE byData) bErr = sendto(sClient, (LPCCH) &byData, sizeof(byData), 0, (LPSOCKADDR) &sServer, sizeof(sServer)) == SOCKET_ERROR; closesocket(sClient); } - - WSACleanup(); // cleanup network stack return bErr; } diff --git a/app/src/main/cpp/win32-layer.c b/app/src/main/cpp/win32-layer.c index 7edb8c1..4e8cb22 100644 --- a/app/src/main/cpp/win32-layer.c +++ b/app/src/main/cpp/win32-layer.c @@ -36,22 +36,21 @@ extern HANDLE hWnd; extern LPTSTR szTitle; LPTSTR szCurrentAssetDirectory = NULL; LPTSTR szCurrentContentDirectory = NULL; -AAssetManager * assetManager; -const TCHAR * assetsPrefix = _T("assets/"); +AAssetManager *assetManager; +const TCHAR *assetsPrefix = _T("assets/"); size_t assetsPrefixLength; -const TCHAR * contentScheme = _T("content://"); +const TCHAR *contentScheme = _T("content://"); size_t contentSchemeLength; -const TCHAR * documentScheme = _T("document:"); +const TCHAR *documentScheme = _T("document:"); size_t documentSchemeLength; -const TCHAR * comPrefix = _T("\\\\.\\"); +const TCHAR *comPrefix = _T("\\\\.\\"); size_t comPrefixLength; TCHAR szFilePathTmp[MAX_PATH]; - DWORD GetLastError(VOID) { - //TODO - return NO_ERROR; + //TODO + return NO_ERROR; } @@ -63,55 +62,55 @@ static HANDLE fileMappingHandles[MAX_FILE_MAPPING_HANDLE]; HBITMAP rootBITMAP; void win32Init() { - initTimer(); - for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { - fileMappingHandles[i] = NULL; - } + initTimer(); + for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { + fileMappingHandles[i] = NULL; + } - assetsPrefixLength = _tcslen(assetsPrefix); - contentSchemeLength = _tcslen(contentScheme); + assetsPrefixLength = _tcslen(assetsPrefix); + contentSchemeLength = _tcslen(contentScheme); documentSchemeLength = _tcslen(documentScheme); comPrefixLength = _tcslen(comPrefix); rootBITMAP = CreateCompatibleBitmap(NULL, 0, 0); } -int abs (int i) { - return i < 0 ? -i : i; +int abs(int i) { + return i < 0 ? -i : i; } VOID OutputDebugString(LPCSTR lpOutputString) { - LOGD("%s", lpOutputString); + LOGD("%s", lpOutputString); } DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer) { - if(getcwd(lpBuffer, nBufferLength)) { - return nBufferLength; - } - return 0; + if (getcwd(lpBuffer, nBufferLength)) { + return nBufferLength; + } + return 0; } BOOL SetCurrentDirectory(LPCTSTR path) { // Set the current directory for the next calls to CreateFile() API with a relative path. - szCurrentContentDirectory = NULL; - szCurrentAssetDirectory = NULL; + szCurrentContentDirectory = NULL; + szCurrentAssetDirectory = NULL; - if(path == NULL) - return FALSE; + if (path == NULL) + return FALSE; - if(_tcsncmp(path, contentScheme, contentSchemeLength) == 0) { - // Set the current directory with an URL with the scheme "content://". - szCurrentContentDirectory = (LPTSTR) path; - return TRUE; - } else if(_tcsncmp(path, assetsPrefix, assetsPrefixLength) == 0) { - // Set the current directory with a path to target the Android asset folders (embedded in the app). - szCurrentAssetDirectory = (LPTSTR) (path + assetsPrefixLength * sizeof(TCHAR)); - return TRUE; - } else - // Set the current directory using the file system "chdir" API. Deprecated, not supported by Android >= 10. - return (BOOL) chdir(path); + if (_tcsncmp(path, contentScheme, contentSchemeLength) == 0) { + // Set the current directory with an URL with the scheme "content://". + szCurrentContentDirectory = (LPTSTR) path; + return TRUE; + } else if (_tcsncmp(path, assetsPrefix, assetsPrefixLength) == 0) { + // Set the current directory with a path to target the Android asset folders (embedded in the app). + szCurrentAssetDirectory = (LPTSTR) (path + assetsPrefixLength * sizeof(TCHAR)); + return TRUE; + } else + // Set the current directory using the file system "chdir" API. Deprecated, not supported by Android >= 10. + return (BOOL) chdir(path); } extern BOOL settingsPort2en; @@ -122,14 +121,16 @@ static HANDLE comms[MAX_CREATED_COMM]; static pthread_mutex_t commsLock; -HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, DWORD dwFlagsAndAttributes, LPVOID hTemplateFile) { - FILE_LOGD("CreateFile(lpFileName: \"%s\", dwDesiredAccess: 0x%08x)", lpFileName, dwShareMode); +HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, + LPVOID lpSecurityAttributes, DWORD dwCreationDisposition, + DWORD dwFlagsAndAttributes, LPVOID hTemplateFile) { + FILE_LOGD("CreateFile(lpFileName: \"%s\", dwDesiredAccess: 0x%08x)", lpFileName, dwShareMode); BOOL foundCOMPrefix = _tcsncmp(lpFileName, comPrefix, comPrefixLength) == 0; - if(foundCOMPrefix) { + if (foundCOMPrefix) { int serialPortId = openSerialPort(lpFileName); - if(serialPortId > 0) { + if (serialPortId > 0) { // We try to open a COM/Serial port HANDLE handle = malloc(sizeof(struct _HANDLE)); memset(handle, 0, sizeof(struct _HANDLE)); @@ -139,8 +140,8 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, pthread_mutex_lock(&commsLock); handle->commIndex = -1; - for(int i = 0; i < MAX_CREATED_COMM; i++) { - if(comms[i] == NULL) { + for (int i = 0; i < MAX_CREATED_COMM; i++) { + if (comms[i] == NULL) { handle->commIndex = i; comms[handle->commIndex] = handle; break; @@ -148,157 +149,162 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, } pthread_mutex_unlock(&commsLock); - SERIAL_LOGD("CreateFile(lpFileName: \"%s\", ...) commId: %d, commIndex: %d", lpFileName, handle->commId, handle->commIndex); + SERIAL_LOGD("CreateFile(lpFileName: \"%s\", ...) commId: %d, commIndex: %d", lpFileName, + handle->commId, handle->commIndex); return handle; } else return (HANDLE) INVALID_HANDLE_VALUE; } - BOOL forceNormalFile = FALSE; - securityExceptionOccured = FALSE; + BOOL forceNormalFile = FALSE; + securityExceptionOccured = FALSE; #if EMUXX == 48 - if(_tcscmp(lpFileName, szPort2Filename) == 0) { - // Special case for Port2 filename - forceNormalFile = TRUE; - if(!settingsPort2wr && (dwDesiredAccess & GENERIC_WRITE)) - return (HANDLE) INVALID_HANDLE_VALUE; - } + if (_tcscmp(lpFileName, szPort2Filename) == 0) { + // Special case for Port2 filename + forceNormalFile = TRUE; + if (!settingsPort2wr && (dwDesiredAccess & GENERIC_WRITE)) + return (HANDLE) INVALID_HANDLE_VALUE; + } #endif BOOL foundDocumentScheme = _tcsncmp(lpFileName, documentScheme, documentSchemeLength) == 0; BOOL urlContentSchemeFound = _tcsncmp(lpFileName, contentScheme, contentSchemeLength) == 0; - if(chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN || chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN_WITH_FOLDER) { - // A E48 state file can contain a path to the KML script. - if(foundDocumentScheme) { - // Keep for compatibility: - // When the state file is created or saved with this Android version, - // an URL like: document:content://|content:// - // is created and saved in the state file. - // Here we want to open a file (lpFileName) which contains the prefix "document:" - // So, we are loading a KML script. - // We extract the KML File URL with "content://" scheme (in the variable "filename"), - // and we extract the folder URL with "content://" scheme (in the variable "szEmuDirectory"/"szRomDirectory" and "szCurrentContentDirectory") - // which should contain the script and its dependencies like the includes, the images and the ROMs. - _tcscpy(szFilePathTmp, lpFileName + _tcslen(documentScheme) * sizeof(TCHAR)); - TCHAR * filename = _tcschr(szFilePathTmp, _T('|')); - if(filename) - *filename = _T('\0'); - if(szFilePathTmp[0]) { - // If szFilePathTmp is empty, this mean that the variable "szEmuDirectory", "szRomDirectory" - // and "szCurrentContentDirectory" are set before that method, using the JSON settings embedded in the state file. - _tcscpy(szEmuDirectory, szFilePathTmp); + if (chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN || + chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN_WITH_FOLDER) { + // A E48 state file can contain a path to the KML script. + if (foundDocumentScheme) { + // Keep for compatibility: + // When the state file is created or saved with this Android version, + // an URL like: document:content://|content:// + // is created and saved in the state file. + // Here we want to open a file (lpFileName) which contains the prefix "document:" + // So, we are loading a KML script. + // We extract the KML File URL with "content://" scheme (in the variable "filename"), + // and we extract the folder URL with "content://" scheme (in the variable "szEmuDirectory"/"szRomDirectory" and "szCurrentContentDirectory") + // which should contain the script and its dependencies like the includes, the images and the ROMs. + _tcscpy(szFilePathTmp, lpFileName + _tcslen(documentScheme) * sizeof(TCHAR)); + TCHAR *filename = _tcschr(szFilePathTmp, _T('|')); + if (filename) + *filename = _T('\0'); + if (szFilePathTmp[0]) { + // If szFilePathTmp is empty, this mean that the variable "szEmuDirectory", "szRomDirectory" + // and "szCurrentContentDirectory" are set before that method, using the JSON settings embedded in the state file. + _tcscpy(szEmuDirectory, szFilePathTmp); #if EMUXX == 48 - _tcscpy(szRomDirectory, szFilePathTmp); + _tcscpy(szRomDirectory, szFilePathTmp); #endif - SetCurrentDirectory(szFilePathTmp); - } - } - } + SetCurrentDirectory(szFilePathTmp); + } + } + } - if(!forceNormalFile - && (szCurrentAssetDirectory || _tcsncmp(lpFileName, assetsPrefix, assetsPrefixLength) == 0) - && !foundDocumentScheme - && !urlContentSchemeFound) { - // Loading a file from the Android asset folders (embedded in the app) - TCHAR szFileName[MAX_PATH]; - AAsset * asset = NULL; - szFileName[0] = _T('\0'); - if(szCurrentAssetDirectory) { - _tcscpy(szFileName, szCurrentAssetDirectory); - _tcscat(szFileName, lpFileName); - asset = AAssetManager_open(assetManager, szFileName, AASSET_MODE_STREAMING); - } else { - asset = AAssetManager_open(assetManager, lpFileName + assetsPrefixLength * sizeof(TCHAR), AASSET_MODE_STREAMING); - } - if(asset) { - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - handle->handleType = HANDLE_TYPE_FILE_ASSET; - handle->fileAsset = asset; - return handle; - } - } else { - // Loading a "normal" file - // * either a file with the scheme "content://" - // * or a file with a simple name but within the current folder (szCurrentContentDirectory) - // * or a file with the scheme "file://". Deprecated not supported by Android >= 10. - BOOL useOpenFileFromContentResolver = FALSE; - int flags = O_RDWR; - int fd = -1; - struct flock lock; - mode_t perm = S_IRUSR | S_IWUSR; + if (!forceNormalFile + && (szCurrentAssetDirectory || _tcsncmp(lpFileName, assetsPrefix, assetsPrefixLength) == 0) + && !foundDocumentScheme + && !urlContentSchemeFound) { + // Loading a file from the Android asset folders (embedded in the app) + TCHAR szFileName[MAX_PATH]; + AAsset *asset = NULL; + szFileName[0] = _T('\0'); + if (szCurrentAssetDirectory) { + _tcscpy(szFileName, szCurrentAssetDirectory); + _tcscat(szFileName, lpFileName); + asset = AAssetManager_open(assetManager, szFileName, AASSET_MODE_STREAMING); + } else { + asset = AAssetManager_open(assetManager, + lpFileName + assetsPrefixLength * sizeof(TCHAR), + AASSET_MODE_STREAMING); + } + if (asset) { + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + handle->handleType = HANDLE_TYPE_FILE_ASSET; + handle->fileAsset = asset; + return handle; + } + } else { + // Loading a "normal" file + // * either a file with the scheme "content://" + // * or a file with a simple name but within the current folder (szCurrentContentDirectory) + // * or a file with the scheme "file://". Deprecated not supported by Android >= 10. + BOOL useOpenFileFromContentResolver = FALSE; + int flags = O_RDWR; + int fd = -1; + struct flock lock; + mode_t perm = S_IRUSR | S_IWUSR; - if (GENERIC_READ == dwDesiredAccess) - flags = O_RDONLY; - else { - if (GENERIC_WRITE == dwDesiredAccess) - flags = O_WRONLY; - else if (0 != ((GENERIC_READ | GENERIC_WRITE) & dwDesiredAccess)) - flags = O_RDWR; + if (GENERIC_READ == dwDesiredAccess) + flags = O_RDONLY; + else { + if (GENERIC_WRITE == dwDesiredAccess) + flags = O_WRONLY; + else if (0 != ((GENERIC_READ | GENERIC_WRITE) & dwDesiredAccess)) + flags = O_RDWR; - if (CREATE_ALWAYS == dwCreationDisposition) - flags |= O_CREAT; - } + if (CREATE_ALWAYS == dwCreationDisposition) + flags |= O_CREAT; + } - if(foundDocumentScheme) { - TCHAR * filename = _tcsrchr(lpFileName, _T('|')); - if(filename) - lpFileName = filename + 1; - } + if (foundDocumentScheme) { + TCHAR *filename = _tcsrchr(lpFileName, _T('|')); + if (filename) + lpFileName = filename + 1; + } - if(urlContentSchemeFound) { - // Case of an absolute file with the scheme "content://". - fd = openFileFromContentResolver(lpFileName, dwDesiredAccess); - useOpenFileFromContentResolver = TRUE; - if(fd == -2) { - FILE_LOGD("CreateFile() openFileFromContentResolver() %d", errno); - securityExceptionOccured = TRUE; - } - } else if(szCurrentContentDirectory) { - // Case of a relative file to a folder with the scheme "content://". - fd = openFileInFolderFromContentResolver(lpFileName, szCurrentContentDirectory, dwDesiredAccess); - useOpenFileFromContentResolver = TRUE; - if(fd == -1) { - FILE_LOGD("CreateFile() openFileFromContentResolver() %d", errno); - } - } else { - // Case of an absolute file with the scheme "file://". Deprecated not supported by Android >= 10. - TCHAR * urlFileSchemeFound = _tcsstr(lpFileName, _T("file://")); - if(urlFileSchemeFound) - lpFileName = urlFileSchemeFound + 7; - fd = open(lpFileName, flags, perm); - if(fd == -1) { - FILE_LOGD("CreateFile() open() %d", errno); - } - } - if (fd >= 0) { - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - handle->handleType = HANDLE_TYPE_FILE; - handle->fileDescriptor = fd; - handle->fileOpenFileFromContentResolver = useOpenFileFromContentResolver; - return handle; - } - } - FILE_LOGD("CreateFile() INVALID_HANDLE_VALUE"); - return (HANDLE) INVALID_HANDLE_VALUE; + if (urlContentSchemeFound) { + // Case of an absolute file with the scheme "content://". + fd = openFileFromContentResolver(lpFileName, dwDesiredAccess); + useOpenFileFromContentResolver = TRUE; + if (fd == -2) { + FILE_LOGD("CreateFile() openFileFromContentResolver() %d", errno); + securityExceptionOccured = TRUE; + } + } else if (szCurrentContentDirectory) { + // Case of a relative file to a folder with the scheme "content://". + fd = openFileInFolderFromContentResolver(lpFileName, szCurrentContentDirectory, + dwDesiredAccess); + useOpenFileFromContentResolver = TRUE; + if (fd == -1) { + FILE_LOGD("CreateFile() openFileFromContentResolver() %d", errno); + } + } else { + // Case of an absolute file with the scheme "file://". Deprecated not supported by Android >= 10. + TCHAR *urlFileSchemeFound = _tcsstr(lpFileName, _T("file://")); + if (urlFileSchemeFound) + lpFileName = urlFileSchemeFound + 7; + fd = open(lpFileName, flags, perm); + if (fd == -1) { + FILE_LOGD("CreateFile() open() %d", errno); + } + } + if (fd >= 0) { + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + handle->handleType = HANDLE_TYPE_FILE; + handle->fileDescriptor = fd; + handle->fileOpenFileFromContentResolver = useOpenFileFromContentResolver; + return handle; + } + } + FILE_LOGD("CreateFile() INVALID_HANDLE_VALUE"); + return (HANDLE) INVALID_HANDLE_VALUE; } -char * dumpToHexAscii(char * buffer, int inputSize, int charWidth) { +char *dumpToHexAscii(char *buffer, int inputSize, int charWidth) { int numLines = 1 + inputSize / charWidth; - char * hexAsciiDump = malloc(4 * inputSize + 3 * numLines + 10); - unsigned char * pBuff = (unsigned char *)buffer; - char * pDump = hexAsciiDump; + char *hexAsciiDump = malloc(4 * inputSize + 3 * numLines + 10); + unsigned char *pBuff = (unsigned char *) buffer; + char *pDump = hexAsciiDump; for (int l = 0, n = 0; l < numLines; ++l) { - *pDump++ = (char)'\t'; + *pDump++ = (char) '\t'; for (int c = 0; c < charWidth && n + c < inputSize; ++c) { - sprintf((char *const)pDump, "%02X ", pBuff[c]); + sprintf((char *const) pDump, "%02X ", pBuff[c]); pDump += 3; } for (int c = 0; c < charWidth && n + c < inputSize; ++c) - *pDump++ = isprint(pBuff[c]) ? ((char *)pBuff)[c] : '.'; + *pDump++ = isprint(pBuff[c]) ? ((char *) pBuff)[c] : '.'; *pDump++ = '\n'; pBuff += charWidth; n += charWidth; @@ -307,327 +313,336 @@ char * dumpToHexAscii(char * buffer, int inputSize, int charWidth) { return hexAsciiDump; } -BOOL ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, LPOVERLAPPED lpOverlapped) { - FILE_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d)", hFile, lpBuffer, nNumberOfBytesToRead); - DWORD readByteCount = 0; - if(hFile->handleType == HANDLE_TYPE_FILE) { - readByteCount = (DWORD) read(hFile->fileDescriptor, lpBuffer, nNumberOfBytesToRead); - } else if(hFile->handleType == HANDLE_TYPE_FILE_ASSET) { - readByteCount = (DWORD) AAsset_read(hFile->fileAsset, lpBuffer, nNumberOfBytesToRead); - } else if(hFile->handleType == HANDLE_TYPE_COM) { - readByteCount = (DWORD) readSerialPort(hFile->commId, lpBuffer, nNumberOfBytesToRead); +BOOL +ReadFile(HANDLE hFile, LPVOID lpBuffer, DWORD nNumberOfBytesToRead, LPDWORD lpNumberOfBytesRead, + LPOVERLAPPED lpOverlapped) { + FILE_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d)", hFile, lpBuffer, + nNumberOfBytesToRead); + DWORD readByteCount = 0; + if (hFile->handleType == HANDLE_TYPE_FILE) { + readByteCount = (DWORD) read(hFile->fileDescriptor, lpBuffer, nNumberOfBytesToRead); + } else if (hFile->handleType == HANDLE_TYPE_FILE_ASSET) { + readByteCount = (DWORD) AAsset_read(hFile->fileAsset, lpBuffer, nNumberOfBytesToRead); + } else if (hFile->handleType == HANDLE_TYPE_COM) { + readByteCount = (DWORD) readSerialPort(hFile->commId, lpBuffer, nNumberOfBytesToRead); #if defined DEBUG_ANDROID_SERIAL - char * hexAsciiDump = dumpToHexAscii(lpBuffer, readByteCount, 8); - SERIAL_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d) -> %d bytes\n%s", hFile, lpBuffer, nNumberOfBytesToRead, readByteCount, hexAsciiDump); - free(hexAsciiDump); + char * hexAsciiDump = dumpToHexAscii(lpBuffer, readByteCount, 8); + SERIAL_LOGD("ReadFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToRead: %d) -> %d bytes\n%s", hFile, lpBuffer, nNumberOfBytesToRead, readByteCount, hexAsciiDump); + free(hexAsciiDump); #endif - } - if(lpNumberOfBytesRead) - *lpNumberOfBytesRead = readByteCount; - return readByteCount >= 0; + } + if (lpNumberOfBytesRead) + *lpNumberOfBytesRead = readByteCount; + return readByteCount >= 0; } -BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite,LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { - FILE_LOGD("WriteFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToWrite: %d)", hFile, lpBuffer, nNumberOfBytesToWrite); - if(hFile->handleType == HANDLE_TYPE_FILE) { +BOOL WriteFile(HANDLE hFile, LPCVOID lpBuffer, DWORD nNumberOfBytesToWrite, + LPDWORD lpNumberOfBytesWritten, LPOVERLAPPED lpOverlapped) { + FILE_LOGD("WriteFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToWrite: %d)", hFile, lpBuffer, + nNumberOfBytesToWrite); + if (hFile->handleType == HANDLE_TYPE_FILE) { ssize_t writenByteCount = write(hFile->fileDescriptor, lpBuffer, nNumberOfBytesToWrite); - if(lpNumberOfBytesWritten) + if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = (DWORD) writenByteCount; return writenByteCount >= 0; - } else if(hFile->handleType == HANDLE_TYPE_COM) { + } else if (hFile->handleType == HANDLE_TYPE_COM) { ssize_t writenByteCount = writeSerialPort(hFile->commId, lpBuffer, nNumberOfBytesToWrite); #if defined DEBUG_ANDROID_SERIAL char * hexAsciiDump = dumpToHexAscii(lpBuffer, writenByteCount, 8); SERIAL_LOGD("WriteFile(hFile: %p, lpBuffer: 0x%08x, nNumberOfBytesToWrite: %d) -> %d bytes\n%s", hFile, lpBuffer, nNumberOfBytesToWrite, writenByteCount, hexAsciiDump); free(hexAsciiDump); #endif - if(serialPortSlowDown) + if (serialPortSlowDown) Sleep(4); // Seems to be needed else kermit/XSend packets do not fully reach the genuine calculator. - if(lpNumberOfBytesWritten) + if (lpNumberOfBytesWritten) *lpNumberOfBytesWritten = (DWORD) writenByteCount; return writenByteCount >= 0; } return FALSE; } -DWORD SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { - FILE_LOGD("SetFilePointer(hFile: %p, lDistanceToMove: %d, dwMoveMethod: %d)", hFile, lDistanceToMove, dwMoveMethod); - int moveMode = FILE_BEGIN; - if(dwMoveMethod == FILE_BEGIN) - moveMode = SEEK_SET; - else if(dwMoveMethod == FILE_CURRENT) - moveMode = SEEK_CUR; - else if(dwMoveMethod == FILE_END) - moveMode = SEEK_END; - int seekResult = -1; - if(hFile->handleType == HANDLE_TYPE_FILE) { - seekResult = (int) lseek(hFile->fileDescriptor, lDistanceToMove, moveMode); - } else if(hFile->handleType == HANDLE_TYPE_FILE_ASSET) { - seekResult = (int) AAsset_seek64(hFile->fileAsset, lDistanceToMove, moveMode); - } - return seekResult < 0 ? INVALID_SET_FILE_POINTER : seekResult; +DWORD +SetFilePointer(HANDLE hFile, LONG lDistanceToMove, PLONG lpDistanceToMoveHigh, DWORD dwMoveMethod) { + FILE_LOGD("SetFilePointer(hFile: %p, lDistanceToMove: %d, dwMoveMethod: %d)", hFile, + lDistanceToMove, dwMoveMethod); + int moveMode = FILE_BEGIN; + if (dwMoveMethod == FILE_BEGIN) + moveMode = SEEK_SET; + else if (dwMoveMethod == FILE_CURRENT) + moveMode = SEEK_CUR; + else if (dwMoveMethod == FILE_END) + moveMode = SEEK_END; + int seekResult = -1; + if (hFile->handleType == HANDLE_TYPE_FILE) { + seekResult = (int) lseek(hFile->fileDescriptor, lDistanceToMove, moveMode); + } else if (hFile->handleType == HANDLE_TYPE_FILE_ASSET) { + seekResult = (int) AAsset_seek64(hFile->fileAsset, lDistanceToMove, moveMode); + } + return seekResult < 0 ? INVALID_SET_FILE_POINTER : seekResult; } BOOL SetEndOfFile(HANDLE hFile) { - FILE_LOGD("SetEndOfFile(hFile: %p)", hFile); - if(hFile->handleType == HANDLE_TYPE_FILE_ASSET) - return FALSE; - off_t currentPosition = lseek(hFile->fileDescriptor, 0, SEEK_CUR); - int truncateResult = ftruncate(hFile->fileDescriptor, currentPosition); - return truncateResult == 0; + FILE_LOGD("SetEndOfFile(hFile: %p)", hFile); + if (hFile->handleType == HANDLE_TYPE_FILE_ASSET) + return FALSE; + off_t currentPosition = lseek(hFile->fileDescriptor, 0, SEEK_CUR); + int truncateResult = ftruncate(hFile->fileDescriptor, currentPosition); + return truncateResult == 0; } DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) { - FILE_LOGD("GetFileSize(hFile: %p)", hFile); - if(lpFileSizeHigh) - *lpFileSizeHigh = 0; - if(hFile->handleType == HANDLE_TYPE_FILE) { - off_t currentPosition = lseek(hFile->fileDescriptor, 0, SEEK_CUR); - off_t fileLength = lseek(hFile->fileDescriptor, 0, SEEK_END); // + 1; - lseek(hFile->fileDescriptor, currentPosition, SEEK_SET); - return (DWORD) fileLength; - } else if(hFile->handleType == HANDLE_TYPE_FILE_ASSET) { - return (DWORD) AAsset_getLength64(hFile->fileAsset); - } - return 0; + FILE_LOGD("GetFileSize(hFile: %p)", hFile); + if (lpFileSizeHigh) + *lpFileSizeHigh = 0; + if (hFile->handleType == HANDLE_TYPE_FILE) { + off_t currentPosition = lseek(hFile->fileDescriptor, 0, SEEK_CUR); + off_t fileLength = lseek(hFile->fileDescriptor, 0, SEEK_END); // + 1; + lseek(hFile->fileDescriptor, currentPosition, SEEK_SET); + return (DWORD) fileLength; + } else if (hFile->handleType == HANDLE_TYPE_FILE_ASSET) { + return (DWORD) AAsset_getLength64(hFile->fileAsset); + } + return 0; } //** https://www.ibm.com/developerworks/systems/library/es-MigratingWin32toLinux.html //https://www.ibm.com/developerworks/systems/library/es-win32linux.html //https://www.ibm.com/developerworks/systems/library/es-win32linux-sem.html -HANDLE CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName) { - FILE_LOGD("CreateFileMapping(hFile: %p, flProtect: 0x08x, dwMaximumSizeLow: %d)", hFile, flProtect, dwMaximumSizeLow); - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - if(hFile->handleType == HANDLE_TYPE_FILE) { - if(hFile->fileOpenFileFromContentResolver) - handle->handleType = HANDLE_TYPE_FILE_MAPPING_CONTENT; - else - handle->handleType = HANDLE_TYPE_FILE_MAPPING; - handle->fileDescriptor = hFile->fileDescriptor; - } else if(hFile->handleType == HANDLE_TYPE_FILE_ASSET) { - handle->handleType = HANDLE_TYPE_FILE_MAPPING_ASSET; - handle->fileAsset = hFile->fileAsset; - } - if(dwMaximumSizeHigh == 0 && dwMaximumSizeLow == 0) { - dwMaximumSizeLow = GetFileSize(hFile, &dwMaximumSizeHigh); - } - handle->fileMappingSize = /*(dwMaximumSizeHigh << 32) |*/ dwMaximumSizeLow; - handle->fileMappingAddress = NULL; - handle->fileMappingProtect = flProtect; - return handle; +HANDLE +CreateFileMapping(HANDLE hFile, LPSECURITY_ATTRIBUTES lpFileMappingAttributes, DWORD flProtect, + DWORD dwMaximumSizeHigh, DWORD dwMaximumSizeLow, LPCSTR lpName) { + FILE_LOGD("CreateFileMapping(hFile: %p, flProtect: 0x08x, dwMaximumSizeLow: %d)", hFile, + flProtect, dwMaximumSizeLow); + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + if (hFile->handleType == HANDLE_TYPE_FILE) { + if (hFile->fileOpenFileFromContentResolver) + handle->handleType = HANDLE_TYPE_FILE_MAPPING_CONTENT; + else + handle->handleType = HANDLE_TYPE_FILE_MAPPING; + handle->fileDescriptor = hFile->fileDescriptor; + } else if (hFile->handleType == HANDLE_TYPE_FILE_ASSET) { + handle->handleType = HANDLE_TYPE_FILE_MAPPING_ASSET; + handle->fileAsset = hFile->fileAsset; + } + if (dwMaximumSizeHigh == 0 && dwMaximumSizeLow == 0) { + dwMaximumSizeLow = GetFileSize(hFile, &dwMaximumSizeHigh); + } + handle->fileMappingSize = /*(dwMaximumSizeHigh << 32) |*/ dwMaximumSizeLow; + handle->fileMappingAddress = NULL; + handle->fileMappingProtect = flProtect; + return handle; } //https://msdn.microsoft.com/en-us/library/Aa366761(v=VS.85).aspx -LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) { - FILE_LOGD("MapViewOfFile(hFileMappingObject: %p, dwDesiredAccess: 0x%08x, dwFileOffsetLow: %d)", hFileMappingObject, dwDesiredAccess, dwFileOffsetLow); - hFileMappingObject->fileMappingOffset = /*(dwFileOffsetHigh << 32) |*/ dwFileOffsetLow; - LPVOID result = NULL; - if(hFileMappingObject->handleType == HANDLE_TYPE_FILE_MAPPING) { - int prot = PROT_NONE; - if (dwDesiredAccess & FILE_MAP_READ) - prot |= PROT_READ; - if (dwDesiredAccess & FILE_MAP_WRITE) - prot |= PROT_WRITE; - hFileMappingObject->fileMappingAddress = mmap(NULL, hFileMappingObject->fileMappingSize, - prot, MAP_PRIVATE, - hFileMappingObject->fileDescriptor, hFileMappingObject->fileMappingOffset); - } else if(hFileMappingObject->handleType == HANDLE_TYPE_FILE_MAPPING_CONTENT) { - size_t numberOfBytesToRead = hFileMappingObject->fileMappingSize - hFileMappingObject->fileMappingOffset; - hFileMappingObject->fileMappingAddress = malloc(numberOfBytesToRead); - off_t currentPosition = lseek(hFileMappingObject->fileDescriptor, 0, SEEK_CUR); - lseek(hFileMappingObject->fileDescriptor, hFileMappingObject->fileMappingOffset, SEEK_SET); - DWORD readByteCount = (DWORD) read(hFileMappingObject->fileDescriptor, hFileMappingObject->fileMappingAddress, numberOfBytesToRead); - lseek(hFileMappingObject->fileDescriptor, currentPosition, SEEK_SET); - } else if(hFileMappingObject->handleType == HANDLE_TYPE_FILE_MAPPING_ASSET) { - if (dwDesiredAccess & FILE_MAP_WRITE) - return NULL; - hFileMappingObject->fileMappingAddress = (LPVOID) (AAsset_getBuffer(hFileMappingObject->fileAsset) + hFileMappingObject->fileMappingOffset); - } - if(hFileMappingObject->fileMappingAddress) { - for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { - if(!fileMappingHandles[i]) { - fileMappingHandles[i] = hFileMappingObject; - break; - } - } - } - result = hFileMappingObject->fileMappingAddress; - return result; +LPVOID MapViewOfFile(HANDLE hFileMappingObject, DWORD dwDesiredAccess, DWORD dwFileOffsetHigh, + DWORD dwFileOffsetLow, SIZE_T dwNumberOfBytesToMap) { + FILE_LOGD("MapViewOfFile(hFileMappingObject: %p, dwDesiredAccess: 0x%08x, dwFileOffsetLow: %d)", + hFileMappingObject, dwDesiredAccess, dwFileOffsetLow); + hFileMappingObject->fileMappingOffset = /*(dwFileOffsetHigh << 32) |*/ dwFileOffsetLow; + LPVOID result = NULL; + if (hFileMappingObject->handleType == HANDLE_TYPE_FILE_MAPPING) { + int prot = PROT_NONE; + if (dwDesiredAccess & FILE_MAP_READ) + prot |= PROT_READ; + if (dwDesiredAccess & FILE_MAP_WRITE) + prot |= PROT_WRITE; + hFileMappingObject->fileMappingAddress = mmap(NULL, hFileMappingObject->fileMappingSize, + prot, MAP_PRIVATE, + hFileMappingObject->fileDescriptor, + hFileMappingObject->fileMappingOffset); + } else if (hFileMappingObject->handleType == HANDLE_TYPE_FILE_MAPPING_CONTENT) { + size_t numberOfBytesToRead = + hFileMappingObject->fileMappingSize - hFileMappingObject->fileMappingOffset; + hFileMappingObject->fileMappingAddress = malloc(numberOfBytesToRead); + off_t currentPosition = lseek(hFileMappingObject->fileDescriptor, 0, SEEK_CUR); + lseek(hFileMappingObject->fileDescriptor, hFileMappingObject->fileMappingOffset, SEEK_SET); + DWORD readByteCount = (DWORD) read(hFileMappingObject->fileDescriptor, + hFileMappingObject->fileMappingAddress, + numberOfBytesToRead); + lseek(hFileMappingObject->fileDescriptor, currentPosition, SEEK_SET); + } else if (hFileMappingObject->handleType == HANDLE_TYPE_FILE_MAPPING_ASSET) { + if (dwDesiredAccess & FILE_MAP_WRITE) + return NULL; + hFileMappingObject->fileMappingAddress = (LPVOID) ( + AAsset_getBuffer(hFileMappingObject->fileAsset) + + hFileMappingObject->fileMappingOffset); + } + if (hFileMappingObject->fileMappingAddress) { + for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { + if (!fileMappingHandles[i]) { + fileMappingHandles[i] = hFileMappingObject; + break; + } + } + } + result = hFileMappingObject->fileMappingAddress; + return result; } // https://msdn.microsoft.com/en-us/library/aa366882(v=vs.85).aspx BOOL UnmapViewOfFile(LPCVOID lpBaseAddress) { - FILE_LOGD("UnmapViewOfFile(lpBaseAddress: %p)", lpBaseAddress); - int result = -1; - for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { - HANDLE fileMappingHandle = fileMappingHandles[i]; - if(fileMappingHandle && lpBaseAddress == fileMappingHandle->fileMappingAddress) { - // Only save the file manually (for Port2 actually) - fileMappingHandles[i] = NULL; - break; - } - } + FILE_LOGD("UnmapViewOfFile(lpBaseAddress: %p)", lpBaseAddress); + int result = -1; + for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { + HANDLE fileMappingHandle = fileMappingHandles[i]; + if (fileMappingHandle && lpBaseAddress == fileMappingHandle->fileMappingAddress) { + // Only save the file manually (for Port2 actually) + fileMappingHandles[i] = NULL; + break; + } + } - return result == 0; + return result == 0; } // This is not a Win32 function BOOL SaveMapViewToFile(LPCVOID lpBaseAddress) { - FILE_LOGD("SaveMapViewToFile(lpBaseAddress: %p)", lpBaseAddress); - int result = -1; - for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { - HANDLE fileMappingHandle = fileMappingHandles[i]; - if(fileMappingHandle && lpBaseAddress == fileMappingHandle->fileMappingAddress) { - if(fileMappingHandle->handleType == HANDLE_TYPE_FILE_MAPPING - || fileMappingHandle->handleType == HANDLE_TYPE_FILE_MAPPING_CONTENT) { - //size_t numberOfBytesToWrite = fileMappingHandle->fileMappingSize - fileMappingHandle->fileMappingOffset; - size_t numberOfBytesToWrite = fileMappingHandle->fileMappingSize; - if(numberOfBytesToWrite > 0) { - off_t currentPosition = lseek(fileMappingHandle->fileDescriptor, 0, SEEK_CUR); - //lseek(fileMappingHandle->fileDescriptor, fileMappingHandle->fileMappingOffset, SEEK_SET); - lseek(fileMappingHandle->fileDescriptor, 0, SEEK_SET); - write(fileMappingHandle->fileDescriptor, fileMappingHandle->fileMappingAddress, numberOfBytesToWrite); - lseek(fileMappingHandle->fileDescriptor, currentPosition, SEEK_SET); - } else { - // BUG - } - } else if(fileMappingHandle->handleType == HANDLE_TYPE_FILE_MAPPING_ASSET) { - // No need to unmap - result = 0; - } - break; - } - } + FILE_LOGD("SaveMapViewToFile(lpBaseAddress: %p)", lpBaseAddress); + int result = -1; + for (int i = 0; i < MAX_FILE_MAPPING_HANDLE; ++i) { + HANDLE fileMappingHandle = fileMappingHandles[i]; + if (fileMappingHandle && lpBaseAddress == fileMappingHandle->fileMappingAddress) { + if (fileMappingHandle->handleType == HANDLE_TYPE_FILE_MAPPING + || fileMappingHandle->handleType == HANDLE_TYPE_FILE_MAPPING_CONTENT) { + //size_t numberOfBytesToWrite = fileMappingHandle->fileMappingSize - fileMappingHandle->fileMappingOffset; + size_t numberOfBytesToWrite = fileMappingHandle->fileMappingSize; + if (numberOfBytesToWrite > 0) { + off_t currentPosition = lseek(fileMappingHandle->fileDescriptor, 0, SEEK_CUR); + //lseek(fileMappingHandle->fileDescriptor, fileMappingHandle->fileMappingOffset, SEEK_SET); + lseek(fileMappingHandle->fileDescriptor, 0, SEEK_SET); + write(fileMappingHandle->fileDescriptor, fileMappingHandle->fileMappingAddress, + numberOfBytesToWrite); + lseek(fileMappingHandle->fileDescriptor, currentPosition, SEEK_SET); + } else { + // BUG + } + } else if (fileMappingHandle->handleType == HANDLE_TYPE_FILE_MAPPING_ASSET) { + // No need to unmap + result = 0; + } + break; + } + } - return result == 0; + return result == 0; } //https://github.com/neosmart/pevents/blob/master/src/pevents.cpp HANDLE CreateEvent(LPVOID lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR name) { - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - handle->handleType = HANDLE_TYPE_EVENT; + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + handle->handleType = HANDLE_TYPE_EVENT; - int result = pthread_cond_init(&(handle->eventCVariable), 0); - _ASSERT(result == 0); + int result = pthread_cond_init(&(handle->eventCVariable), 0); + _ASSERT(result == 0); - result = pthread_mutex_init(&(handle->eventMutex), 0); - _ASSERT(result == 0); + result = pthread_mutex_init(&(handle->eventMutex), 0); + _ASSERT(result == 0); - handle->eventState = FALSE; - handle->eventAutoReset = bManualReset ? FALSE : TRUE; + handle->eventState = FALSE; + handle->eventAutoReset = bManualReset ? FALSE : TRUE; - if (bInitialState) - { - result = SetEvent(handle); - _ASSERT(result == 0); - } + if (bInitialState) { + result = SetEvent(handle); + _ASSERT(result == 0); + } - return handle; + return handle; } BOOL SetEvent(HANDLE hEvent) { - int result = pthread_mutex_lock(&hEvent->eventMutex); - _ASSERT(result == 0); + int result = pthread_mutex_lock(&hEvent->eventMutex); + _ASSERT(result == 0); - hEvent->eventState = TRUE; + hEvent->eventState = TRUE; - //Depending on the event type, we either trigger everyone or only one - if (hEvent->eventAutoReset) - { - //hEvent->eventState can be false if compiled with WFMO support - if (hEvent->eventState) - { - result = pthread_mutex_unlock(&hEvent->eventMutex); - _ASSERT(result == 0); - result = pthread_cond_signal(&hEvent->eventCVariable); - _ASSERT(result == 0); - return 0; - } - } - else - { - result = pthread_mutex_unlock(&hEvent->eventMutex); - _ASSERT(result == 0); - result = pthread_cond_broadcast(&hEvent->eventCVariable); - _ASSERT(result == 0); - } + //Depending on the event type, we either trigger everyone or only one + if (hEvent->eventAutoReset) { + //hEvent->eventState can be false if compiled with WFMO support + if (hEvent->eventState) { + result = pthread_mutex_unlock(&hEvent->eventMutex); + _ASSERT(result == 0); + result = pthread_cond_signal(&hEvent->eventCVariable); + _ASSERT(result == 0); + return 0; + } + } else { + result = pthread_mutex_unlock(&hEvent->eventMutex); + _ASSERT(result == 0); + result = pthread_cond_broadcast(&hEvent->eventCVariable); + _ASSERT(result == 0); + } - return 0; + return 0; } BOOL ResetEvent(HANDLE hEvent) { - if(hEvent) { - int result = pthread_mutex_lock(&hEvent->eventMutex); - _ASSERT(result == 0); + if (hEvent) { + int result = pthread_mutex_lock(&hEvent->eventMutex); + _ASSERT(result == 0); - hEvent->eventState = FALSE; + hEvent->eventState = FALSE; - result = pthread_mutex_unlock(&hEvent->eventMutex); - _ASSERT(result == 0); + result = pthread_mutex_unlock(&hEvent->eventMutex); + _ASSERT(result == 0); - return TRUE; - } - return FALSE; + return TRUE; + } + return FALSE; } int UnlockedWaitForEvent(HANDLE hHandle, uint64_t milliseconds) { - int result = 0; - if (!hHandle->eventState) - { - //Zero-timeout event state check optimization - if (milliseconds == 0) - { - return WAIT_TIMEOUT; - } + int result = 0; + if (!hHandle->eventState) { + //Zero-timeout event state check optimization + if (milliseconds == 0) { + return WAIT_TIMEOUT; + } - struct timespec ts; - if (milliseconds != (uint64_t) -1) - { - struct timeval tv; - gettimeofday(&tv, NULL); + struct timespec ts; + if (milliseconds != (uint64_t) -1) { + struct timeval tv; + gettimeofday(&tv, NULL); - uint64_t nanoseconds = ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + ((uint64_t) tv.tv_usec) * 1000; + uint64_t nanoseconds = + ((uint64_t) tv.tv_sec) * 1000 * 1000 * 1000 + milliseconds * 1000 * 1000 + + ((uint64_t) tv.tv_usec) * 1000; - ts.tv_sec = nanoseconds / 1000 / 1000 / 1000; - ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000); - } + ts.tv_sec = nanoseconds / 1000 / 1000 / 1000; + ts.tv_nsec = (nanoseconds - ((uint64_t) ts.tv_sec) * 1000 * 1000 * 1000); + } - do - { - //Regardless of whether it's an auto-reset or manual-reset event: - //wait to obtain the event, then lock anyone else out - if (milliseconds != (uint64_t) -1) - { - result = pthread_cond_timedwait(&hHandle->eventCVariable, &hHandle->eventMutex, &ts); - THREAD_LOGD("UnlockedWaitForEvent() pthread_cond_timedwait() for event %x return %d", hHandle, result); - if(result == ETIMEDOUT) - result = WAIT_TIMEOUT; - } - else - { - result = pthread_cond_wait(&hHandle->eventCVariable, &hHandle->eventMutex); - } - } while (result == 0 && !hHandle->eventState); + do { + //Regardless of whether it's an auto-reset or manual-reset event: + //wait to obtain the event, then lock anyone else out + if (milliseconds != (uint64_t) -1) { + result = pthread_cond_timedwait(&hHandle->eventCVariable, &hHandle->eventMutex, + &ts); + THREAD_LOGD( + "UnlockedWaitForEvent() pthread_cond_timedwait() for event %x return %d", + hHandle, result); + if (result == ETIMEDOUT) + result = WAIT_TIMEOUT; + } else { + result = pthread_cond_wait(&hHandle->eventCVariable, &hHandle->eventMutex); + } + } while (result == 0 && !hHandle->eventState); - if (result == 0 && hHandle->eventAutoReset) - { - //We've only accquired the event if the wait succeeded - hHandle->eventState = FALSE; - } - } - else if (hHandle->eventAutoReset) - { - //It's an auto-reset event that's currently available; - //we need to stop anyone else from using it - result = 0; - hHandle->eventState = FALSE; - } - //Else we're trying to obtain a manual reset event with a signaled state; - //don't do anything + if (result == 0 && hHandle->eventAutoReset) { + //We've only accquired the event if the wait succeeded + hHandle->eventState = FALSE; + } + } else if (hHandle->eventAutoReset) { + //It's an auto-reset event that's currently available; + //we need to stop anyone else from using it + result = 0; + hHandle->eventState = FALSE; + } + //Else we're trying to obtain a manual reset event with a signaled state; + //don't do anything - return result; + return result; } extern int jniDetachCurrentThread(); @@ -637,64 +652,68 @@ extern int jniDetachCurrentThread(); static HANDLE threads[MAX_CREATED_THREAD]; static void ThreadStart(LPVOID lpThreadParameter) { - HANDLE handle = (HANDLE)lpThreadParameter; - if(handle) { - handle->threadStartAddress(handle->threadParameter); - } + HANDLE handle = (HANDLE) lpThreadParameter; + if (handle) { + handle->threadStartAddress(handle->threadParameter); + } - threads[handle->threadIndex] = NULL; - jniDetachCurrentThread(); - CloseHandle(handle->threadEventMessage); + threads[handle->threadIndex] = NULL; + jniDetachCurrentThread(); + CloseHandle(handle->threadEventMessage); } -HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId) { - THREAD_LOGD("CreateThread()"); - pthread_attr_t attr; - pthread_attr_init(&attr); - if(dwStackSize) - pthread_attr_setstacksize(&attr, dwStackSize); +HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, + LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, + DWORD dwCreationFlags, LPDWORD lpThreadId) { + THREAD_LOGD("CreateThread()"); + pthread_attr_t attr; + pthread_attr_init(&attr); + if (dwStackSize) + pthread_attr_setstacksize(&attr, dwStackSize); - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - handle->handleType = HANDLE_TYPE_THREAD; - handle->threadStartAddress = lpStartAddress; - handle->threadParameter = lpParameter; - handle->threadEventMessage = CreateEvent(NULL, FALSE, FALSE, NULL); - for(int i = 0; i < MAX_CREATED_THREAD; i++) { - if(threads[i] == NULL) { - handle->threadIndex = i; - threads[handle->threadIndex] = handle; - break; - } - } + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + handle->handleType = HANDLE_TYPE_THREAD; + handle->threadStartAddress = lpStartAddress; + handle->threadParameter = lpParameter; + handle->threadEventMessage = CreateEvent(NULL, FALSE, FALSE, NULL); + for (int i = 0; i < MAX_CREATED_THREAD; i++) { + if (threads[i] == NULL) { + handle->threadIndex = i; + threads[handle->threadIndex] = handle; + break; + } + } - //Suspended - //https://stackoverflow.com/questions/3140867/suspend-pthreads-without-using-condition - //https://stackoverflow.com/questions/7953917/create-thread-in-suspended-mode-using-pthreads - //http://man7.org/linux/man-pages/man3/pthread_create.3.html - int pthreadResult = pthread_create(&handle->threadId, &attr, (void *(*)(void *)) ThreadStart, handle); - if(pthreadResult == 0) { - if(lpThreadId) - *lpThreadId = (DWORD) handle->threadIndex; //handle->threadId; - THREAD_LOGD("CreateThread() threadId: 0x%lx, threadIndex: %d", handle->threadId, handle->threadIndex); - return handle; - } else { - threads[handle->threadIndex] = NULL; - if(handle->threadEventMessage) - CloseHandle(handle->threadEventMessage); - free(handle); - } - return NULL; + //Suspended + //https://stackoverflow.com/questions/3140867/suspend-pthreads-without-using-condition + //https://stackoverflow.com/questions/7953917/create-thread-in-suspended-mode-using-pthreads + //http://man7.org/linux/man-pages/man3/pthread_create.3.html + int pthreadResult = pthread_create(&handle->threadId, &attr, (void *(*)(void *)) ThreadStart, + handle); + if (pthreadResult == 0) { + if (lpThreadId) + *lpThreadId = (DWORD) handle->threadIndex; //handle->threadId; + THREAD_LOGD("CreateThread() threadId: 0x%lx, threadIndex: %d", handle->threadId, + handle->threadIndex); + return handle; + } else { + threads[handle->threadIndex] = NULL; + if (handle->threadEventMessage) + CloseHandle(handle->threadEventMessage); + free(handle); + } + return NULL; } DWORD ResumeThread(HANDLE hThread) { - THREAD_LOGD("ResumeThread()"); - //TODO - return 0; + THREAD_LOGD("ResumeThread()"); + //TODO + return 0; } BOOL SetThreadPriority(HANDLE hThread, int nPriority) { - THREAD_LOGD("SetThreadPriority()"); + THREAD_LOGD("SetThreadPriority()"); // if(hThread->handleType == HANDLE_TYPE_THREAD) { // int policy; // struct sched_param param; @@ -707,153 +726,149 @@ BOOL SetThreadPriority(HANDLE hThread, int nPriority) { // // THIS DOES NOT WORK WITH ANDROID! // return TRUE; // } - return FALSE; + return FALSE; } //https://docs.microsoft.com/en-us/windows/desktop/api/synchapi/nf-synchapi-waitforsingleobject -DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) -{ - if(hHandle->handleType == HANDLE_TYPE_THREAD) { - _ASSERT(dwMilliseconds == INFINITE) - if(dwMilliseconds == INFINITE) { - pthread_join(hHandle->threadId, NULL); - } - //TODO for dwMilliseconds != INFINITE - //https://stackoverflow.com/questions/2719580/waitforsingleobject-and-waitformultipleobjects-equivalent-in-linux - } else if(hHandle->handleType == HANDLE_TYPE_EVENT) { +DWORD WaitForSingleObject(HANDLE hHandle, DWORD dwMilliseconds) { + if (hHandle->handleType == HANDLE_TYPE_THREAD) { + _ASSERT(dwMilliseconds == INFINITE) + if (dwMilliseconds == INFINITE) { + pthread_join(hHandle->threadId, NULL); + } + //TODO for dwMilliseconds != INFINITE + //https://stackoverflow.com/questions/2719580/waitforsingleobject-and-waitformultipleobjects-equivalent-in-linux + } else if (hHandle->handleType == HANDLE_TYPE_EVENT) { - int tempResult; - if (dwMilliseconds == 0) - { - tempResult = pthread_mutex_trylock(&hHandle->eventMutex); - if (tempResult == EBUSY) - { - return WAIT_TIMEOUT; - } - } - else - { - tempResult = pthread_mutex_lock(&hHandle->eventMutex); - } + int tempResult; + if (dwMilliseconds == 0) { + tempResult = pthread_mutex_trylock(&hHandle->eventMutex); + if (tempResult == EBUSY) { + return WAIT_TIMEOUT; + } + } else { + tempResult = pthread_mutex_lock(&hHandle->eventMutex); + } - _ASSERT(tempResult == 0); + _ASSERT(tempResult == 0); - int result = UnlockedWaitForEvent(hHandle, dwMilliseconds); + int result = UnlockedWaitForEvent(hHandle, dwMilliseconds); - tempResult = pthread_mutex_unlock(&hHandle->eventMutex); - _ASSERT(tempResult == 0); + tempResult = pthread_mutex_unlock(&hHandle->eventMutex); + _ASSERT(tempResult == 0); - return (DWORD) result; - } + return (DWORD) result; + } - DWORD result = WAIT_OBJECT_0; - return result; + DWORD result = WAIT_OBJECT_0; + return result; } BOOL WINAPI CloseHandle(HANDLE hObject) { - FILE_LOGD("CloseHandle(hObject: %p)", hObject); - if(!hObject) - return FALSE; - //https://msdn.microsoft.com/en-us/9b84891d-62ca-4ddc-97b7-c4c79482abd9 - // Can be a thread/event/file handle! - switch(hObject->handleType) { - case HANDLE_TYPE_FILE: { - FILE_LOGD("CloseHandle() HANDLE_TYPE_FILE"); - int closeResult; - if(hObject->fileOpenFileFromContentResolver) { - closeResult = closeFileFromContentResolver(hObject->fileDescriptor); - } else { - closeResult = close(hObject->fileDescriptor); - if(closeResult == -1) { - LOGD("close() %d", errno); //9 -> EBADF - } - } - if(closeResult >= 0) { - hObject->handleType = HANDLE_TYPE_INVALID; - hObject->fileDescriptor = 0; - free(hObject); - return TRUE; - } + FILE_LOGD("CloseHandle(hObject: %p)", hObject); + if (!hObject) + return FALSE; + //https://msdn.microsoft.com/en-us/9b84891d-62ca-4ddc-97b7-c4c79482abd9 + // Can be a thread/event/file handle! + switch (hObject->handleType) { + case HANDLE_TYPE_FILE: { + FILE_LOGD("CloseHandle() HANDLE_TYPE_FILE"); + int closeResult; + if (hObject->fileOpenFileFromContentResolver) { + closeResult = closeFileFromContentResolver(hObject->fileDescriptor); + } else { + closeResult = close(hObject->fileDescriptor); + if (closeResult == -1) { + LOGD("close() %d", errno); //9 -> EBADF + } + } + if (closeResult >= 0) { + hObject->handleType = HANDLE_TYPE_INVALID; + hObject->fileDescriptor = 0; + free(hObject); + return TRUE; + } - break; - } - case HANDLE_TYPE_FILE_ASSET: { - FILE_LOGD("CloseHandle() HANDLE_TYPE_FILE_ASSET"); - AAsset_close(hObject->fileAsset); - hObject->handleType = HANDLE_TYPE_INVALID; - hObject->fileAsset = NULL; - free(hObject); - return TRUE; - } - case HANDLE_TYPE_FILE_MAPPING: - case HANDLE_TYPE_FILE_MAPPING_CONTENT: - case HANDLE_TYPE_FILE_MAPPING_ASSET: { - FILE_LOGD("CloseHandle() HANDLE_TYPE_FILE_MAPPING"); - hObject->handleType = HANDLE_TYPE_INVALID; - hObject->fileDescriptor = 0; - hObject->fileAsset = NULL; - hObject->fileMappingSize = 0; - hObject->fileMappingAddress = NULL; - free(hObject); - return TRUE; - } - case HANDLE_TYPE_EVENT: { - FILE_LOGD("CloseHandle() HANDLE_TYPE_EVENT"); - hObject->handleType = HANDLE_TYPE_INVALID; - int result = 0; - result = pthread_cond_destroy(&hObject->eventCVariable); - _ASSERT(result == 0); - result = pthread_mutex_destroy(&hObject->eventMutex); - _ASSERT(result == 0); - hObject->eventAutoReset = FALSE; - hObject->eventState = FALSE; - free(hObject); - return TRUE; - } - case HANDLE_TYPE_THREAD: - THREAD_LOGD("CloseHandle() THREAD 0x%lx", hObject->threadId); - if(hObject->threadEventMessage && hObject->threadEventMessage->handleType == HANDLE_TYPE_EVENT) { - CloseHandle(hObject->threadEventMessage); - hObject->threadEventMessage = NULL; - } - hObject->handleType = HANDLE_TYPE_INVALID; - hObject->threadId = 0; - hObject->threadStartAddress = NULL; - hObject->threadParameter = NULL; - free(hObject); - return TRUE; - case HANDLE_TYPE_COM: { - SERIAL_LOGD("CloseHandle(hObject: %p) for HANDLE_TYPE_COM", hObject); + break; + } + case HANDLE_TYPE_FILE_ASSET: { + FILE_LOGD("CloseHandle() HANDLE_TYPE_FILE_ASSET"); + AAsset_close(hObject->fileAsset); + hObject->handleType = HANDLE_TYPE_INVALID; + hObject->fileAsset = NULL; + free(hObject); + return TRUE; + } + case HANDLE_TYPE_FILE_MAPPING: + case HANDLE_TYPE_FILE_MAPPING_CONTENT: + case HANDLE_TYPE_FILE_MAPPING_ASSET: { + FILE_LOGD("CloseHandle() HANDLE_TYPE_FILE_MAPPING"); + hObject->handleType = HANDLE_TYPE_INVALID; + hObject->fileDescriptor = 0; + hObject->fileAsset = NULL; + hObject->fileMappingSize = 0; + hObject->fileMappingAddress = NULL; + free(hObject); + return TRUE; + } + case HANDLE_TYPE_EVENT: { + FILE_LOGD("CloseHandle() HANDLE_TYPE_EVENT"); + hObject->handleType = HANDLE_TYPE_INVALID; + int result = 0; + result = pthread_cond_destroy(&hObject->eventCVariable); + _ASSERT(result == 0); + result = pthread_mutex_destroy(&hObject->eventMutex); + _ASSERT(result == 0); + hObject->eventAutoReset = FALSE; + hObject->eventState = FALSE; + free(hObject); + return TRUE; + } + case HANDLE_TYPE_THREAD: + THREAD_LOGD("CloseHandle() THREAD 0x%lx", hObject->threadId); + if (hObject->threadEventMessage && + hObject->threadEventMessage->handleType == HANDLE_TYPE_EVENT) { + CloseHandle(hObject->threadEventMessage); + hObject->threadEventMessage = NULL; + } + hObject->handleType = HANDLE_TYPE_INVALID; + hObject->threadId = 0; + hObject->threadStartAddress = NULL; + hObject->threadParameter = NULL; + free(hObject); + return TRUE; + case HANDLE_TYPE_COM: { + SERIAL_LOGD("CloseHandle(hObject: %p) for HANDLE_TYPE_COM", hObject); - closeSerialPort(hObject->commId); - hObject->commId = 0; + closeSerialPort(hObject->commId); + hObject->commId = 0; - hObject->handleType = HANDLE_TYPE_INVALID; - if(hObject->commState) { - free(hObject->commState); - hObject->commState = NULL; - } - if(hObject->commEvent) { - CloseHandle(hObject->commEvent); - hObject->commEvent = NULL; - } - if(hObject->commIndex != -1) { - pthread_mutex_lock(&commsLock); - comms[hObject->commIndex] = NULL; - pthread_mutex_unlock(&commsLock); - } - free(hObject); - return TRUE; - } - default: - break; - } - return FALSE; + hObject->handleType = HANDLE_TYPE_INVALID; + if (hObject->commState) { + free(hObject->commState); + hObject->commState = NULL; + } + if (hObject->commEvent) { + CloseHandle(hObject->commEvent); + hObject->commEvent = NULL; + } + if (hObject->commIndex != -1) { + pthread_mutex_lock(&commsLock); + comms[hObject->commIndex] = NULL; + pthread_mutex_unlock(&commsLock); + } + free(hObject); + return TRUE; + } + default: + break; + } + return FALSE; } void Sleep(int ms) { - if(ms == 0) { + if (ms == 0) { // Because sched_yield() does not seem to work with Android, try to increase the pause duration, // hoping to switch to the others thread (WorkerThread). ms = 1; @@ -868,295 +883,305 @@ void Sleep(int ms) { } BOOL QueryPerformanceFrequency(PLARGE_INTEGER l) { - //https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx - l->QuadPart = 10000000; - return TRUE; + //https://msdn.microsoft.com/en-us/library/windows/desktop/ms644904(v=vs.85).aspx + l->QuadPart = 10000000; + return TRUE; } -BOOL QueryPerformanceCounter(PLARGE_INTEGER l) -{ - struct timespec /*{ +BOOL QueryPerformanceCounter(PLARGE_INTEGER l) { + struct timespec /*{ time_t tv_sec; long tv_nsec; } */ time; - clock_gettime(CLOCK_MONOTONIC, &time); - l->QuadPart = (uint64_t) ((1e9 * time.tv_sec + time.tv_nsec) / 100); - return TRUE; -} -void InitializeCriticalSection(CRITICAL_SECTION * lpCriticalSection) { - pthread_mutexattr_t Attr; - pthread_mutexattr_init(&Attr); - pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); - pthread_mutex_init(lpCriticalSection, &Attr); -} -void DeleteCriticalSection(CRITICAL_SECTION * lpCriticalSection) { - pthread_mutex_destroy(lpCriticalSection); + clock_gettime(CLOCK_MONOTONIC, &time); + l->QuadPart = (uint64_t) ((1e9 * time.tv_sec + time.tv_nsec) / 100); + return TRUE; } -void EnterCriticalSection(CRITICAL_SECTION *lock) -{ - pthread_mutex_lock(lock); +void InitializeCriticalSection(CRITICAL_SECTION *lpCriticalSection) { + pthread_mutexattr_t Attr; + pthread_mutexattr_init(&Attr); + pthread_mutexattr_settype(&Attr, PTHREAD_MUTEX_RECURSIVE); + pthread_mutex_init(lpCriticalSection, &Attr); } -void LeaveCriticalSection(CRITICAL_SECTION *lock) -{ - pthread_mutex_unlock(lock); +void DeleteCriticalSection(CRITICAL_SECTION *lpCriticalSection) { + pthread_mutex_destroy(lpCriticalSection); } -DWORD GetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName) { - //TODO +void EnterCriticalSection(CRITICAL_SECTION *lock) { + pthread_mutex_lock(lock); +} + +void LeaveCriticalSection(CRITICAL_SECTION *lock) { + pthread_mutex_unlock(lock); +} + +DWORD GetPrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpDefault, + LPTSTR lpReturnedString, DWORD nSize, LPCTSTR lpFileName) { + //TODO #ifdef UNICODE - wcsncpy(lpReturnedString, lpDefault, nSize); + wcsncpy(lpReturnedString, lpDefault, nSize); #else - strncpy(lpReturnedString, lpDefault, nSize); + strncpy(lpReturnedString, lpDefault, nSize); #endif - return 0; + return 0; } + UINT GetPrivateProfileInt(LPCTSTR lpAppName, LPCTSTR lpKeyName, INT nDefault, LPCTSTR lpFileName) { - //TODO - return (UINT) nDefault; + //TODO + return (UINT) nDefault; } -BOOL WritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, LPCTSTR lpFileName) { - //TODO - return 0; + +BOOL WritePrivateProfileString(LPCTSTR lpAppName, LPCTSTR lpKeyName, LPCTSTR lpString, + LPCTSTR lpFileName) { + //TODO + return 0; } HGLOBAL WINAPI GlobalAlloc(UINT uFlags, SIZE_T dwBytes) { - return malloc(dwBytes); + return malloc(dwBytes); } -LPVOID WINAPI GlobalLock (HGLOBAL hMem) { - return hMem; + +LPVOID WINAPI GlobalLock(HGLOBAL hMem) { + return hMem; } BOOL WINAPI GlobalUnlock(HGLOBAL hMem) { - return TRUE; + return TRUE; } HGLOBAL WINAPI GlobalFree(HGLOBAL hMem) { - free(hMem); - return NULL; + free(hMem); + return NULL; } BOOL GetOpenFileName(LPOPENFILENAME openFilename) { - if(openFilename) { - if(currentDialogBoxMode == DialogBoxMode_OPEN_MACRO) { - openFilename->nMaxFile = MAX_PATH; - openFilename->nFileExtension = 1; - //openFilename->lpstrFile = getSaveObjectFilenameResult; - _tcsncpy(openFilename->lpstrFile, getSaveObjectFilenameResult, openFilename->nMaxFile); - return TRUE; - } - } - return FALSE; + if (openFilename) { + if (currentDialogBoxMode == DialogBoxMode_OPEN_MACRO) { + openFilename->nMaxFile = MAX_PATH; + openFilename->nFileExtension = 1; + //openFilename->lpstrFile = getSaveObjectFilenameResult; + _tcsncpy(openFilename->lpstrFile, getSaveObjectFilenameResult, openFilename->nMaxFile); + return TRUE; + } + } + return FALSE; } TCHAR getSaveObjectFilenameResult[MAX_PATH]; + BOOL GetSaveFileName(LPOPENFILENAME openFilename) { - if(openFilename) { - if(currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42 - || currentDialogBoxMode == DialogBoxMode_SAVE_MACRO) { - openFilename->nMaxFile = MAX_PATH; - openFilename->nFileExtension = 1; - //openFilename->lpstrFile = getSaveObjectFilenameResult; - _tcsncpy(openFilename->lpstrFile, getSaveObjectFilenameResult, openFilename->nMaxFile); - return TRUE; - } - } - return FALSE; + if (openFilename) { + if (currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42 + || currentDialogBoxMode == DialogBoxMode_SAVE_MACRO) { + openFilename->nMaxFile = MAX_PATH; + openFilename->nFileExtension = 1; + //openFilename->lpstrFile = getSaveObjectFilenameResult; + _tcsncpy(openFilename->lpstrFile, getSaveObjectFilenameResult, openFilename->nMaxFile); + return TRUE; + } + } + return FALSE; } // Almost the same function as the private core function DibNumColors() -static __inline WORD DibNumColors(BITMAPINFOHEADER CONST *lpbi) -{ - if (lpbi->biClrUsed != 0) return (WORD) lpbi->biClrUsed; +static __inline WORD DibNumColors(BITMAPINFOHEADER CONST *lpbi) { + if (lpbi->biClrUsed != 0) return (WORD) lpbi->biClrUsed; - /* a 24 bitcount DIB has no color table */ - return (lpbi->biBitCount <= 8) ? (1 << lpbi->biBitCount) : 0; + /* a 24 bitcount DIB has no color table */ + return (lpbi->biBitCount <= 8) ? (1 << lpbi->biBitCount) : 0; } static HBITMAP DecodeBMPIcon(LPBYTE imageBuffer, size_t imageSize) { - // size of bitmap header information - DWORD dwFileSize = sizeof(BITMAPINFOHEADER); - if (imageSize < dwFileSize) - return NULL; + // size of bitmap header information + DWORD dwFileSize = sizeof(BITMAPINFOHEADER); + if (imageSize < dwFileSize) + return NULL; - LPBITMAPINFO pBmi = (LPBITMAPINFO)imageBuffer; + LPBITMAPINFO pBmi = (LPBITMAPINFO) imageBuffer; - // size with color table - if (pBmi->bmiHeader.biCompression == BI_BITFIELDS) - dwFileSize += 3 * sizeof(DWORD); - else - dwFileSize += DibNumColors(&pBmi->bmiHeader) * sizeof(RGBQUAD); + // size with color table + if (pBmi->bmiHeader.biCompression == BI_BITFIELDS) + dwFileSize += 3 * sizeof(DWORD); + else + dwFileSize += DibNumColors(&pBmi->bmiHeader) * sizeof(RGBQUAD); - pBmi->bmiHeader.biHeight /= 2; + pBmi->bmiHeader.biHeight /= 2; - DWORD stride = (((pBmi->bmiHeader.biWidth * (DWORD)pBmi->bmiHeader.biBitCount) + 31) / 32 * 4); - DWORD height = (DWORD) abs(pBmi->bmiHeader.biHeight); + DWORD stride = (((pBmi->bmiHeader.biWidth * (DWORD) pBmi->bmiHeader.biBitCount) + 31) / 32 * 4); + DWORD height = (DWORD) abs(pBmi->bmiHeader.biHeight); - // size with bitmap data - if (pBmi->bmiHeader.biCompression != BI_RGB) - dwFileSize += pBmi->bmiHeader.biSizeImage; - else { - pBmi->bmiHeader.biSizeImage = stride * height; - dwFileSize += pBmi->bmiHeader.biSizeImage; - } - if (imageSize < dwFileSize) - return NULL; + // size with bitmap data + if (pBmi->bmiHeader.biCompression != BI_RGB) + dwFileSize += pBmi->bmiHeader.biSizeImage; + else { + pBmi->bmiHeader.biSizeImage = stride * height; + dwFileSize += pBmi->bmiHeader.biSizeImage; + } + if (imageSize < dwFileSize) + return NULL; - HBITMAP hBitmap = CreateDIBitmap(hWindowDC, &pBmi->bmiHeader, CBM_INIT, imageBuffer, pBmi, DIB_RGB_COLORS); - if(hBitmap) { - // Inverse the height - BYTE *source = imageBuffer + dwFileSize - stride; - BYTE *destination = hBitmap->bitmapBits; - DWORD width = pBmi->bmiHeader.biWidth; - for (unsigned int y = 0; y < height; ++y) { - for (unsigned int x = 0; x < width; ++x) { - BYTE * sourcePixel = source + (x << 2); - BYTE * destinationPixel = destination + (x << 2); - destinationPixel[0] = sourcePixel[2]; - destinationPixel[1] = sourcePixel[1]; - destinationPixel[2] = sourcePixel[0]; - destinationPixel[3] = sourcePixel[3]; - } - source -= stride; - destination += stride; - } - } - // Only support 32bits RGBA BMP for now. - return hBitmap; + HBITMAP hBitmap = CreateDIBitmap(hWindowDC, &pBmi->bmiHeader, CBM_INIT, imageBuffer, pBmi, + DIB_RGB_COLORS); + if (hBitmap) { + // Inverse the height + BYTE *source = imageBuffer + dwFileSize - stride; + BYTE *destination = hBitmap->bitmapBits; + DWORD width = pBmi->bmiHeader.biWidth; + for (unsigned int y = 0; y < height; ++y) { + for (unsigned int x = 0; x < width; ++x) { + BYTE *sourcePixel = source + (x << 2); + BYTE *destinationPixel = destination + (x << 2); + destinationPixel[0] = sourcePixel[2]; + destinationPixel[1] = sourcePixel[1]; + destinationPixel[2] = sourcePixel[0]; + destinationPixel[3] = sourcePixel[3]; + } + source -= stride; + destination += stride; + } + } + // Only support 32bits RGBA BMP for now. + return hBitmap; } static HBITMAP DecodePNGIcon(LPBYTE imageBuffer, size_t imageSize) { - HBITMAP hBitmap = NULL; - UINT uWidth,uHeight; - LPBYTE pbyImage = NULL; - UINT uError = lodepng_decode_memory(&pbyImage, &uWidth, &uHeight, imageBuffer, imageSize, LCT_RGBA, 8); - if (uError == 0) { - BITMAPINFO bmi; - ZeroMemory(&bmi, sizeof(bmi)); // init bitmap info - bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - bmi.bmiHeader.biWidth = (LONG) uWidth; - bmi.bmiHeader.biHeight = (LONG) uHeight; - bmi.bmiHeader.biPlanes = 1; - bmi.bmiHeader.biBitCount = 32; // create a true color DIB - bmi.bmiHeader.biCompression = BI_RGB; + HBITMAP hBitmap = NULL; + UINT uWidth, uHeight; + LPBYTE pbyImage = NULL; + UINT uError = lodepng_decode_memory(&pbyImage, &uWidth, &uHeight, imageBuffer, imageSize, + LCT_RGBA, 8); + if (uError == 0) { + BITMAPINFO bmi; + ZeroMemory(&bmi, sizeof(bmi)); // init bitmap info + bmi.bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + bmi.bmiHeader.biWidth = (LONG) uWidth; + bmi.bmiHeader.biHeight = (LONG) uHeight; + bmi.bmiHeader.biPlanes = 1; + bmi.bmiHeader.biBitCount = 32; // create a true color DIB + bmi.bmiHeader.biCompression = BI_RGB; - // bitmap dimensions - LONG stride = (((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) / 32 * 4); - bmi.bmiHeader.biSizeImage = (DWORD) (stride * bmi.bmiHeader.biHeight); + // bitmap dimensions + LONG stride = (((bmi.bmiHeader.biWidth * bmi.bmiHeader.biBitCount) + 31) / 32 * 4); + bmi.bmiHeader.biSizeImage = (DWORD) (stride * bmi.bmiHeader.biHeight); - // allocate buffer for pixels - LPBYTE pbyPixels; // BMP buffer - hBitmap = CreateDIBSection(hWindowDC, &bmi, DIB_RGB_COLORS, (VOID **)&pbyPixels, NULL, 0); - if (hBitmap) - memcpy(pbyPixels, pbyImage, bmi.bmiHeader.biSizeImage); - } + // allocate buffer for pixels + LPBYTE pbyPixels; // BMP buffer + hBitmap = CreateDIBSection(hWindowDC, &bmi, DIB_RGB_COLORS, (VOID **) &pbyPixels, NULL, 0); + if (hBitmap) + memcpy(pbyPixels, pbyImage, bmi.bmiHeader.biSizeImage); + } - if (pbyImage != NULL) - free(pbyImage); - return hBitmap; + if (pbyImage != NULL) + free(pbyImage); + return hBitmap; } // ICO (file format) https://en.wikipedia.org/wiki/ICO_(file_format) // https://docs.microsoft.com/en-us/previous-versions/ms997538(v=msdn.10) typedef struct { - WORD idReserved; - WORD idType; - WORD idCount; + WORD idReserved; + WORD idType; + WORD idCount; } ICONDIR, *LPICONDIR; typedef struct ICONDIRENTRY { - BYTE bWidth; // Specifies image width in pixels. Can be any number between 0 and 255. Value 0 means image width is 256 pixels. - BYTE bHeight; // Specifies image height in pixels. Can be any number between 0 and 255. Value 0 means image height is 256 pixels. - BYTE bColorCount; // Specifies number of colors in the color palette. Should be 0 if the image does not use a color palette. - BYTE bReserved; // Reserved. Should be 0. - WORD wPlanes; // In ICO format: Specifies color planes. Should be 0 or 1. - WORD wBitCount; // In ICO format: Specifies bits per pixel. - DWORD dwBytesInRes; // Specifies the size of the image's data in bytes - DWORD dwImageOffset; // Specifies the offset of BMP or PNG data from the beginning of the ICO/CUR file + BYTE bWidth; // Specifies image width in pixels. Can be any number between 0 and 255. Value 0 means image width is 256 pixels. + BYTE bHeight; // Specifies image height in pixels. Can be any number between 0 and 255. Value 0 means image height is 256 pixels. + BYTE bColorCount; // Specifies number of colors in the color palette. Should be 0 if the image does not use a color palette. + BYTE bReserved; // Reserved. Should be 0. + WORD wPlanes; // In ICO format: Specifies color planes. Should be 0 or 1. + WORD wBitCount; // In ICO format: Specifies bits per pixel. + DWORD dwBytesInRes; // Specifies the size of the image's data in bytes + DWORD dwImageOffset; // Specifies the offset of BMP or PNG data from the beginning of the ICO/CUR file } ICONDIRENTRY, *LPICONDIRENTRY; typedef struct { - BITMAPINFOHEADER icHeader; // DIB header - RGBQUAD icColors[1]; // Color table - BYTE icXOR[1]; // DIB bits for XOR mask - BYTE icAND[1]; // DIB bits for AND mask + BITMAPINFOHEADER icHeader; // DIB header + RGBQUAD icColors[1]; // Color table + BYTE icXOR[1]; // DIB bits for XOR mask + BYTE icAND[1]; // DIB bits for AND mask } ICONIMAGE, *LPICONIMAGE; HANDLE LoadImage(HINSTANCE hInst, LPCSTR name, UINT type, int cx, int cy, UINT fuLoad) { - HANDLE hIconFile = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL); - if (hIconFile == INVALID_HANDLE_VALUE) - return NULL; + HANDLE hIconFile = CreateFile(name, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, + NULL); + if (hIconFile == INVALID_HANDLE_VALUE) + return NULL; - ICONDIR fileHeader; - DWORD nNumberOfBytesToRead = 0; - if(ReadFile(hIconFile, &fileHeader, sizeof(ICONDIR), &nNumberOfBytesToRead, NULL) == FALSE || sizeof(ICONDIR) != nNumberOfBytesToRead) { - CloseHandle(hIconFile); - return NULL; - } + ICONDIR fileHeader; + DWORD nNumberOfBytesToRead = 0; + if (ReadFile(hIconFile, &fileHeader, sizeof(ICONDIR), &nNumberOfBytesToRead, NULL) == FALSE || + sizeof(ICONDIR) != nNumberOfBytesToRead) { + CloseHandle(hIconFile); + return NULL; + } - size_t iconsBufferSize = fileHeader.idCount * sizeof(ICONDIRENTRY); - ICONDIRENTRY * iconHeaderArray = malloc(iconsBufferSize); - nNumberOfBytesToRead = 0; - if(ReadFile(hIconFile, iconHeaderArray, iconsBufferSize, &nNumberOfBytesToRead, NULL) == FALSE || iconsBufferSize != nNumberOfBytesToRead) { - CloseHandle(hIconFile); - return NULL; - } + size_t iconsBufferSize = fileHeader.idCount * sizeof(ICONDIRENTRY); + ICONDIRENTRY *iconHeaderArray = malloc(iconsBufferSize); + nNumberOfBytesToRead = 0; + if (ReadFile(hIconFile, iconHeaderArray, iconsBufferSize, &nNumberOfBytesToRead, NULL) == + FALSE || iconsBufferSize != nNumberOfBytesToRead) { + CloseHandle(hIconFile); + return NULL; + } - int maxWidth = -1; - int maxHeight = -1; - int maxBitPerPixel = -1; - int maxIconIndex = -1; - for (int i = 0; i < fileHeader.idCount; ++i) { - ICONDIRENTRY * iconHeader = &(iconHeaderArray[i]); - int width = iconHeader->bWidth == 0 ? 256 : iconHeader->bWidth; - int height = iconHeader->bHeight == 0 ? 256 : iconHeader->bHeight; - if(width >= maxWidth && height >= maxHeight && iconHeader->wBitCount > maxBitPerPixel) { - maxWidth = width; - maxHeight = height; - maxBitPerPixel = iconHeader->wBitCount; - maxIconIndex = i; - } - } - maxIconIndex = 1; // To test BMP - if(maxIconIndex == -1) { - CloseHandle(hIconFile); - return NULL; - } + int maxWidth = -1; + int maxHeight = -1; + int maxBitPerPixel = -1; + int maxIconIndex = -1; + for (int i = 0; i < fileHeader.idCount; ++i) { + ICONDIRENTRY *iconHeader = &(iconHeaderArray[i]); + int width = iconHeader->bWidth == 0 ? 256 : iconHeader->bWidth; + int height = iconHeader->bHeight == 0 ? 256 : iconHeader->bHeight; + if (width >= maxWidth && height >= maxHeight && iconHeader->wBitCount > maxBitPerPixel) { + maxWidth = width; + maxHeight = height; + maxBitPerPixel = iconHeader->wBitCount; + maxIconIndex = i; + } + } + maxIconIndex = 1; // To test BMP + if (maxIconIndex == -1) { + CloseHandle(hIconFile); + return NULL; + } - DWORD dwBytesInRes = iconHeaderArray[maxIconIndex].dwBytesInRes; - LPBYTE iconBuffer = malloc(dwBytesInRes); + DWORD dwBytesInRes = iconHeaderArray[maxIconIndex].dwBytesInRes; + LPBYTE iconBuffer = malloc(dwBytesInRes); - SetFilePointer(hIconFile, iconHeaderArray[maxIconIndex].dwImageOffset, 0, FILE_BEGIN); - if(ReadFile(hIconFile, iconBuffer, dwBytesInRes, &nNumberOfBytesToRead, NULL) == FALSE || dwBytesInRes != nNumberOfBytesToRead) { - CloseHandle(hIconFile); - free(iconHeaderArray); - free(iconBuffer); - return NULL; - } - CloseHandle(hIconFile); + SetFilePointer(hIconFile, iconHeaderArray[maxIconIndex].dwImageOffset, 0, FILE_BEGIN); + if (ReadFile(hIconFile, iconBuffer, dwBytesInRes, &nNumberOfBytesToRead, NULL) == FALSE || + dwBytesInRes != nNumberOfBytesToRead) { + CloseHandle(hIconFile); + free(iconHeaderArray); + free(iconBuffer); + return NULL; + } + CloseHandle(hIconFile); - HBITMAP icon = NULL; - if (dwBytesInRes >= 8 && memcmp(iconBuffer, "\x89PNG\r\n\x1a\n", 8) == 0) - // It is a PNG image - icon = DecodePNGIcon(iconBuffer, dwBytesInRes); - else - // It is a BMP image - icon = DecodeBMPIcon(iconBuffer, dwBytesInRes); + HBITMAP icon = NULL; + if (dwBytesInRes >= 8 && memcmp(iconBuffer, "\x89PNG\r\n\x1a\n", 8) == 0) + // It is a PNG image + icon = DecodePNGIcon(iconBuffer, dwBytesInRes); + else + // It is a BMP image + icon = DecodeBMPIcon(iconBuffer, dwBytesInRes); - free(iconHeaderArray); - free(iconBuffer); + free(iconHeaderArray); + free(iconBuffer); - if(!icon) - return NULL; + if (!icon) + return NULL; - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - handle->handleType = HANDLE_TYPE_ICON; - handle->icon = icon; - return handle; + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + handle->handleType = HANDLE_TYPE_ICON; + handle->icon = icon; + return handle; } @@ -1168,70 +1193,69 @@ int selItemDataCount = 0; TCHAR labels[MAX_LABEL_SIZE]; LRESULT SendMessage(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam) { - //TODO - if(currentDialogBoxMode == DialogBoxMode_GET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_GET_USRPRG42 - || currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42) { - if (Msg == LB_ADDSTRING && itemDataCount < MAX_ITEMDATA) { - itemString[itemDataCount] = (TCHAR *)lParam; - return itemDataCount++; - } else if (Msg == LB_SETITEMDATA && wParam < MAX_ITEMDATA) { - itemData[wParam] = lParam; - } else if (Msg == LB_GETITEMDATA && wParam < MAX_ITEMDATA) { - return itemData[wParam]; - } else if (Msg == LB_GETCOUNT) { - return itemDataCount; - } else if (Msg == LB_GETSELCOUNT) { - return selItemDataCount; - } else if (Msg == LB_GETSEL && wParam < itemDataCount && wParam < MAX_ITEMDATA) { - return selItemDataIndex[wParam]; - } - } - if(Msg == WM_SETICON && wParam == ICON_BIG) { - if(lParam != NULL) { - HANDLE hIcon = (HANDLE)lParam; - if(hIcon->handleType == HANDLE_TYPE_ICON && hIcon->icon != NULL) { - HBITMAP icon = hIcon->icon; - if(icon && icon->bitmapInfoHeader && icon->bitmapBits) - setKMLIcon(icon->bitmapInfoHeader->biWidth, icon->bitmapInfoHeader->biHeight, icon->bitmapBits, icon->bitmapInfoHeader->biSizeImage); - } - } else { - setKMLIcon(0, 0, NULL, 0); - } - } - return NULL; + //TODO + if (currentDialogBoxMode == DialogBoxMode_GET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_GET_USRPRG42 + || currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42) { + if (Msg == LB_ADDSTRING && itemDataCount < MAX_ITEMDATA) { + itemString[itemDataCount] = (TCHAR *) lParam; + return itemDataCount++; + } else if (Msg == LB_SETITEMDATA && wParam < MAX_ITEMDATA) { + itemData[wParam] = lParam; + } else if (Msg == LB_GETITEMDATA && wParam < MAX_ITEMDATA) { + return itemData[wParam]; + } else if (Msg == LB_GETCOUNT) { + return itemDataCount; + } else if (Msg == LB_GETSELCOUNT) { + return selItemDataCount; + } else if (Msg == LB_GETSEL && wParam < itemDataCount && wParam < MAX_ITEMDATA) { + return selItemDataIndex[wParam]; + } + } + if (Msg == WM_SETICON && wParam == ICON_BIG) { + if (lParam != NULL) { + HANDLE hIcon = (HANDLE) lParam; + if (hIcon->handleType == HANDLE_TYPE_ICON && hIcon->icon != NULL) { + HBITMAP icon = hIcon->icon; + if (icon && icon->bitmapInfoHeader && icon->bitmapBits) + setKMLIcon(icon->bitmapInfoHeader->biWidth, icon->bitmapInfoHeader->biHeight, + icon->bitmapBits, icon->bitmapInfoHeader->biSizeImage); + } + } else { + setKMLIcon(0, 0, NULL, 0); + } + } + return NULL; } + BOOL PostMessage(HWND handleWindow, UINT Msg, WPARAM wParam, LPARAM lParam) { - //TODO - if(handleWindow == hWnd && Msg == WM_COMMAND) { - int menuCommand = (int) ((wParam & 0xffff) - 40000); - LOGD("Menu Item %d", menuCommand); - sendMenuItemCommand(menuCommand); - } - return NULL; + //TODO + if (handleWindow == hWnd && Msg == WM_COMMAND) { + int menuCommand = (int) ((wParam & 0xffff) - 40000); + LOGD("Menu Item %d", menuCommand); + sendMenuItemCommand(menuCommand); + } + return NULL; } -int MessageBox(HANDLE h, LPCTSTR szMessage, LPCTSTR title, int flags) -{ - if(flags & MB_YESNO) { - return IDOK; - } +int MessageBox(HANDLE h, LPCTSTR szMessage, LPCTSTR title, int flags) { + if (flags & MB_YESNO) { + return IDOK; + } - return showAlert(szMessage, flags); + return showAlert(szMessage, flags); } -DWORD timeGetTime(void) -{ - time_t t = time(NULL); - return (DWORD)(t * 1000); +DWORD timeGetTime(void) { + time_t t = time(NULL); + return (DWORD) (t * 1000); } -BOOL GetSystemPowerStatus(LPSYSTEM_POWER_STATUS status) -{ - status->ACLineStatus = AC_LINE_ONLINE; - return TRUE; +BOOL GetSystemPowerStatus(LPSYSTEM_POWER_STATUS status) { + status->ACLineStatus = AC_LINE_ONLINE; + return TRUE; } @@ -1240,745 +1264,789 @@ BOOL GetSystemPowerStatus(LPSYSTEM_POWER_STATUS status) #if defined NEW_WIN32_SOUND_ENGINE // this callback handler is called every time a buffer finishes playing void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { - WAVE_OUT_LOGD("waveOut bqPlayerCallback()"); + WAVE_OUT_LOGD("waveOut bqPlayerCallback()"); - HWAVEOUT hwo = context; - LPWAVEHDR pWaveHeaderNextToRead = NULL; + HWAVEOUT hwo = context; + LPWAVEHDR pWaveHeaderNextToRead = NULL; - pthread_mutex_lock(&hwo->audioEngineLock); - if (hwo->pWaveHeaderNextToRead) { - pWaveHeaderNextToRead = hwo->pWaveHeaderNextToRead; - hwo->pWaveHeaderNextToRead = hwo->pWaveHeaderNextToRead->lpNext; - if(!hwo->pWaveHeaderNextToRead) { - hwo->pWaveHeaderNextToWrite = NULL; - } - } - pthread_mutex_unlock(&hwo->audioEngineLock); + pthread_mutex_lock(&hwo->audioEngineLock); + if (hwo->pWaveHeaderNextToRead) { + pWaveHeaderNextToRead = hwo->pWaveHeaderNextToRead; + hwo->pWaveHeaderNextToRead = hwo->pWaveHeaderNextToRead->lpNext; + if(!hwo->pWaveHeaderNextToRead) { + hwo->pWaveHeaderNextToWrite = NULL; + } + } + pthread_mutex_unlock(&hwo->audioEngineLock); - if(pWaveHeaderNextToRead) { - PostThreadMessage(1, MM_WOM_DONE, hwo, pWaveHeaderNextToRead); - } else { - WAVE_OUT_LOGD("waveOut bqPlayerCallback() Nothing to play?"); - } + if(pWaveHeaderNextToRead) { + PostThreadMessage(1, MM_WOM_DONE, hwo, pWaveHeaderNextToRead); + } else { + WAVE_OUT_LOGD("waveOut bqPlayerCallback() Nothing to play?"); + } - WAVE_OUT_LOGD("bqPlayerCallback() before sem_post() +1"); - sem_post(&hwo->waveOutLock); // Increment - WAVE_OUT_LOGD("bqPlayerCallback() after sem_post() +1"); + WAVE_OUT_LOGD("bqPlayerCallback() before sem_post() +1"); + sem_post(&hwo->waveOutLock); // Increment + WAVE_OUT_LOGD("bqPlayerCallback() after sem_post() +1"); } #else void onPlayerDone(HWAVEOUT hwo) { - WAVE_OUT_LOGD("waveOut onPlayerDone()"); - //PostThreadMessage(0, MM_WOM_DONE, hwo, hwo->pWaveHeaderNext); - // Artificially replace the post message MM_WOM_DONE - bSoundSlow = FALSE; // no sound slow down - bEnableSlow = TRUE; // reenable CPU slow down possibility + WAVE_OUT_LOGD("waveOut onPlayerDone()"); + //PostThreadMessage(0, MM_WOM_DONE, hwo, hwo->pWaveHeaderNext); + // Artificially replace the post message MM_WOM_DONE + bSoundSlow = FALSE; // no sound slow down + bEnableSlow = TRUE; // reenable CPU slow down possibility } // this callback handler is called every time a buffer finishes playing void bqPlayerCallback(SLAndroidSimpleBufferQueueItf bq, void *context) { - WAVE_OUT_LOGD("waveOut bqPlayerCallback()"); - HWAVEOUT hwo = context; - if (hwo->pWaveHeaderNext != NULL) { - LPWAVEHDR pWaveHeaderNext = hwo->pWaveHeaderNext->lpNext; - free(hwo->pWaveHeaderNext->lpData); - free(hwo->pWaveHeaderNext); - hwo->pWaveHeaderNext = pWaveHeaderNext; - if(pWaveHeaderNext != NULL) { - WAVE_OUT_LOGD("waveOut bqPlayerCallback() bqPlayerBufferQueue->Enqueue"); - SLresult result = (*hwo->bqPlayerBufferQueue)->Enqueue(hwo->bqPlayerBufferQueue, pWaveHeaderNext->lpData, pWaveHeaderNext->dwBufferLength); - if (SL_RESULT_SUCCESS != result) { - WAVE_OUT_LOGD("waveOut bqPlayerCallback() Enqueue Error %d", result); - onPlayerDone(hwo); - // Error - //pthread_mutex_unlock(&hwo->audioEngineLock); + WAVE_OUT_LOGD("waveOut bqPlayerCallback()"); + HWAVEOUT hwo = context; + if (hwo->pWaveHeaderNext != NULL) { + LPWAVEHDR pWaveHeaderNext = hwo->pWaveHeaderNext->lpNext; + free(hwo->pWaveHeaderNext->lpData); + free(hwo->pWaveHeaderNext); + hwo->pWaveHeaderNext = pWaveHeaderNext; + if (pWaveHeaderNext != NULL) { + WAVE_OUT_LOGD("waveOut bqPlayerCallback() bqPlayerBufferQueue->Enqueue"); + SLresult result = (*hwo->bqPlayerBufferQueue)->Enqueue(hwo->bqPlayerBufferQueue, + pWaveHeaderNext->lpData, + pWaveHeaderNext->dwBufferLength); + if (SL_RESULT_SUCCESS != result) { + WAVE_OUT_LOGD("waveOut bqPlayerCallback() Enqueue Error %d", result); + onPlayerDone(hwo); + // Error + //pthread_mutex_unlock(&hwo->audioEngineLock); // return; - } + } // return; - } else { - WAVE_OUT_LOGD("waveOut bqPlayerCallback() Nothing next, so, this is the end"); - onPlayerDone(hwo); - } - } else { - WAVE_OUT_LOGD("waveOut bqPlayerCallback() Nothing to play? So, this is the end"); - onPlayerDone(hwo); - } + } else { + WAVE_OUT_LOGD("waveOut bqPlayerCallback() Nothing next, so, this is the end"); + onPlayerDone(hwo); + } + } else { + WAVE_OUT_LOGD("waveOut bqPlayerCallback() Nothing to play? So, this is the end"); + onPlayerDone(hwo); + } } // Timer to replace the missing bqPlayerCallback void onPlayerDoneTimerCallback(void *context) { - WAVE_OUT_LOGD("waveOut onPlayerDoneTimerCallback()"); - HWAVEOUT hwo = context; - onPlayerDone(hwo); + WAVE_OUT_LOGD("waveOut onPlayerDoneTimerCallback()"); + HWAVEOUT hwo = context; + onPlayerDone(hwo); - //TODO May be needed if an attached occurs in the future - //jniDetachCurrentThread(); + //TODO May be needed if an attached occurs in the future + //jniDetachCurrentThread(); } #endif -MMRESULT waveOutOpen(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, DWORD_PTR dwInstance, DWORD fdwOpen) { - WAVE_OUT_LOGD("waveOutOpen()"); +MMRESULT waveOutOpen(LPHWAVEOUT phwo, UINT uDeviceID, LPCWAVEFORMATEX pwfx, DWORD_PTR dwCallback, + DWORD_PTR dwInstance, DWORD fdwOpen) { + WAVE_OUT_LOGD("waveOutOpen()"); - HWAVEOUT handle = (HWAVEOUT)malloc(sizeof(struct _HWAVEOUT)); - memset(handle, 0, sizeof(struct _HWAVEOUT)); - handle->pwfx = (WAVEFORMATEX *) pwfx; - handle->uDeviceID = uDeviceID; + HWAVEOUT handle = (HWAVEOUT) malloc(sizeof(struct _HWAVEOUT)); + memset(handle, 0, sizeof(struct _HWAVEOUT)); + handle->pwfx = (WAVEFORMATEX *) pwfx; + handle->uDeviceID = uDeviceID; - SLresult result; + SLresult result; - // create engine - result = slCreateEngine(&handle->engineObject, 0, NULL, 0, NULL, NULL); - //_ASSERT(SL_RESULT_SUCCESS == result); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() slCreateEngine error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // create engine + result = slCreateEngine(&handle->engineObject, 0, NULL, 0, NULL, NULL); + //_ASSERT(SL_RESULT_SUCCESS == result); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() slCreateEngine error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // realize the engine - result = (*handle->engineObject)->Realize(handle->engineObject, SL_BOOLEAN_FALSE); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() engineObject->Realize error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // realize the engine + result = (*handle->engineObject)->Realize(handle->engineObject, SL_BOOLEAN_FALSE); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() engineObject->Realize error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // get the engine interface, which is needed in order to create other objects - result = (*handle->engineObject)->GetInterface(handle->engineObject, SL_IID_ENGINE, &handle->engineEngine); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() engineObject->GetInterface error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // get the engine interface, which is needed in order to create other objects + result = (*handle->engineObject)->GetInterface(handle->engineObject, SL_IID_ENGINE, + &handle->engineEngine); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() engineObject->GetInterface error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // create output mix, with environmental reverb specified as a non-required interface - const SLInterfaceID ids[1] = { SL_IID_ENVIRONMENTALREVERB }; - const SLboolean req[1] = { SL_BOOLEAN_FALSE }; - result = (*handle->engineEngine)->CreateOutputMix(handle->engineEngine, &handle->outputMixObject, 1, ids, req); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() engineObject->CreateOutputMix error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } - // realize the output mix - result = (*handle->outputMixObject)->Realize(handle->outputMixObject, SL_BOOLEAN_FALSE); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() outputMixObject->Realize error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } - // configure audio source - SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { - SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType + // create output mix, with environmental reverb specified as a non-required interface + const SLInterfaceID ids[1] = {SL_IID_ENVIRONMENTALREVERB}; + const SLboolean req[1] = {SL_BOOLEAN_FALSE}; + result = (*handle->engineEngine)->CreateOutputMix(handle->engineEngine, + &handle->outputMixObject, 1, ids, req); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() engineObject->CreateOutputMix error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } + // realize the output mix + result = (*handle->outputMixObject)->Realize(handle->outputMixObject, SL_BOOLEAN_FALSE); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() outputMixObject->Realize error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } + // configure audio source + SLDataLocator_AndroidSimpleBufferQueue loc_bufq = { + SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE, // locatorType #if defined NEW_WIN32_SOUND_ENGINE - //1 // numBuffers - //2 // numBuffers - 20 // numBuffers + //1 // numBuffers + //2 // numBuffers + 20 // numBuffers #else - 20 // numBuffers + 20 // numBuffers #endif - }; - SLDataFormat_PCM format_pcm = { - SL_DATAFORMAT_PCM, // formatType - 1, // numChannels - SL_SAMPLINGRATE_8, // samplesPerSec - SL_PCMSAMPLEFORMAT_FIXED_16, // bitsPerSample - SL_PCMSAMPLEFORMAT_FIXED_16, // containerSize - SL_SPEAKER_FRONT_CENTER, // channelMask - SL_BYTEORDER_LITTLEENDIAN // endianness - }; - /* - * Enable Fast Audio when possible: once we set the same rate to be the native, fast audio path - * will be triggered - */ - format_pcm.samplesPerSec = pwfx->nSamplesPerSec * 1000; //sample rate in mili second - format_pcm.bitsPerSample = pwfx->wBitsPerSample; - format_pcm.containerSize = pwfx->wBitsPerSample; - format_pcm.numChannels = pwfx->nChannels; + }; + SLDataFormat_PCM format_pcm = { + SL_DATAFORMAT_PCM, // formatType + 1, // numChannels + SL_SAMPLINGRATE_8, // samplesPerSec + SL_PCMSAMPLEFORMAT_FIXED_16, // bitsPerSample + SL_PCMSAMPLEFORMAT_FIXED_16, // containerSize + SL_SPEAKER_FRONT_CENTER, // channelMask + SL_BYTEORDER_LITTLEENDIAN // endianness + }; + /* + * Enable Fast Audio when possible: once we set the same rate to be the native, fast audio path + * will be triggered + */ + format_pcm.samplesPerSec = pwfx->nSamplesPerSec * 1000; //sample rate in mili second + format_pcm.bitsPerSample = pwfx->wBitsPerSample; + format_pcm.containerSize = pwfx->wBitsPerSample; + format_pcm.numChannels = pwfx->nChannels; - SLDataSource audioSrc = { - &loc_bufq, // pLocator - &format_pcm // pFormat - }; + SLDataSource audioSrc = { + &loc_bufq, // pLocator + &format_pcm // pFormat + }; - // configure audio sink - SLDataLocator_OutputMix loc_outmix = { - SL_DATALOCATOR_OUTPUTMIX, // locatorType - handle->outputMixObject // outputMix - }; - SLDataSink audioSnk = { - &loc_outmix, // pLocator - NULL // pFormat - }; + // configure audio sink + SLDataLocator_OutputMix loc_outmix = { + SL_DATALOCATOR_OUTPUTMIX, // locatorType + handle->outputMixObject // outputMix + }; + SLDataSink audioSnk = { + &loc_outmix, // pLocator + NULL // pFormat + }; - /* - * create audio player: - * fast audio does not support when SL_IID_EFFECTSEND is required, skip it - * for fast audio case - */ - const SLInterfaceID ids2[3] = { - SL_IID_BUFFERQUEUE, - SL_IID_VOLUME, - //SL_IID_EFFECTSEND, - //SL_IID_MUTESOLO, - }; - const SLboolean req2[3] = { - SL_BOOLEAN_TRUE, - SL_BOOLEAN_TRUE, - //SL_BOOLEAN_TRUE, - //SL_BOOLEAN_TRUE, - }; + /* + * create audio player: + * fast audio does not support when SL_IID_EFFECTSEND is required, skip it + * for fast audio case + */ + const SLInterfaceID ids2[3] = { + SL_IID_BUFFERQUEUE, + SL_IID_VOLUME, + //SL_IID_EFFECTSEND, + //SL_IID_MUTESOLO, + }; + const SLboolean req2[3] = { + SL_BOOLEAN_TRUE, + SL_BOOLEAN_TRUE, + //SL_BOOLEAN_TRUE, + //SL_BOOLEAN_TRUE, + }; - result = (*handle->engineEngine)->CreateAudioPlayer(handle->engineEngine, &handle->bqPlayerObject, &audioSrc, &audioSnk, 2, ids2, req2); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() engineEngine->CreateAudioPlayer error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + result = (*handle->engineEngine)->CreateAudioPlayer(handle->engineEngine, + &handle->bqPlayerObject, &audioSrc, + &audioSnk, 2, ids2, req2); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() engineEngine->CreateAudioPlayer error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // realize the player - result = (*handle->bqPlayerObject)->Realize(handle->bqPlayerObject, SL_BOOLEAN_FALSE); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->Realize error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // realize the player + result = (*handle->bqPlayerObject)->Realize(handle->bqPlayerObject, SL_BOOLEAN_FALSE); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->Realize error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // get the play interface - result = (*handle->bqPlayerObject)->GetInterface(handle->bqPlayerObject, SL_IID_PLAY, &handle->bqPlayerPlay); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->GetInterface SL_IID_PLAY error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // get the play interface + result = (*handle->bqPlayerObject)->GetInterface(handle->bqPlayerObject, SL_IID_PLAY, + &handle->bqPlayerPlay); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->GetInterface SL_IID_PLAY error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // get the buffer queue interface - result = (*handle->bqPlayerObject)->GetInterface(handle->bqPlayerObject, SL_IID_BUFFERQUEUE, &handle->bqPlayerBufferQueue); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->GetInterface SL_IID_BUFFERQUEUE error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // get the buffer queue interface + result = (*handle->bqPlayerObject)->GetInterface(handle->bqPlayerObject, SL_IID_BUFFERQUEUE, + &handle->bqPlayerBufferQueue); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->GetInterface SL_IID_BUFFERQUEUE error: %d", + result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // register callback on the buffer queue - result = (*handle->bqPlayerBufferQueue)->RegisterCallback(handle->bqPlayerBufferQueue, bqPlayerCallback, handle); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() bqPlayerBufferQueue->RegisterCallback error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // register callback on the buffer queue + result = (*handle->bqPlayerBufferQueue)->RegisterCallback(handle->bqPlayerBufferQueue, + bqPlayerCallback, handle); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() bqPlayerBufferQueue->RegisterCallback error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // get the volume interface - result = (*handle->bqPlayerObject)->GetInterface(handle->bqPlayerObject, SL_IID_VOLUME, &handle->bqPlayerVolume); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->GetInterface SL_IID_VOLUME error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // get the volume interface + result = (*handle->bqPlayerObject)->GetInterface(handle->bqPlayerObject, SL_IID_VOLUME, + &handle->bqPlayerVolume); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->GetInterface SL_IID_VOLUME error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } - // set the player's state to playing - result = (*handle->bqPlayerPlay)->SetPlayState(handle->bqPlayerPlay, SL_PLAYSTATE_PLAYING); - if(result != SL_RESULT_SUCCESS) { - WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->SetPlayState error: %d", result); - waveOutClose(handle); - return MMSYSERR_ERROR; - } + // set the player's state to playing + result = (*handle->bqPlayerPlay)->SetPlayState(handle->bqPlayerPlay, SL_PLAYSTATE_PLAYING); + if (result != SL_RESULT_SUCCESS) { + WAVE_OUT_LOGD("waveOutOpen() bqPlayerObject->SetPlayState error: %d", result); + waveOutClose(handle); + return MMSYSERR_ERROR; + } #if defined NEW_WIN32_SOUND_ENGINE - sem_init(&handle->waveOutLock, 0, 1); + sem_init(&handle->waveOutLock, 0, 1); #else - struct sigevent sev; - sev.sigev_notify = SIGEV_THREAD; - sev.sigev_notify_function = (void (*)(sigval_t)) onPlayerDoneTimerCallback; //this function will be called when timer expires - sev.sigev_value.sival_ptr = handle; //this argument will be passed to cbf - sev.sigev_notify_attributes = NULL; - timer_t * timer = &(handle->playerDoneTimer); - if (timer_create(CLOCK_MONOTONIC, &sev, timer) == -1) { - WAVE_OUT_LOGD("waveOutOpen() ERROR in timer_create"); - return NULL; - } + struct sigevent sev; + sev.sigev_notify = SIGEV_THREAD; + sev.sigev_notify_function = (void (*)( + sigval_t)) onPlayerDoneTimerCallback; //this function will be called when timer expires + sev.sigev_value.sival_ptr = handle; //this argument will be passed to cbf + sev.sigev_notify_attributes = NULL; + timer_t *timer = &(handle->playerDoneTimer); + if (timer_create(CLOCK_MONOTONIC, &sev, timer) == -1) { + WAVE_OUT_LOGD("waveOutOpen() ERROR in timer_create"); + return NULL; + } - long delayInMilliseconds = 1000; // msecs - handle->playerDoneTimerSetTimes.it_value.tv_sec = delayInMilliseconds / 1000; - handle->playerDoneTimerSetTimes.it_value.tv_nsec = (delayInMilliseconds % 1000) * 1000000; - handle->playerDoneTimerSetTimes.it_interval.tv_sec = 0; - handle->playerDoneTimerSetTimes.it_interval.tv_nsec = 0; + long delayInMilliseconds = 1000; // msecs + handle->playerDoneTimerSetTimes.it_value.tv_sec = delayInMilliseconds / 1000; + handle->playerDoneTimerSetTimes.it_value.tv_nsec = (delayInMilliseconds % 1000) * 1000000; + handle->playerDoneTimerSetTimes.it_interval.tv_sec = 0; + handle->playerDoneTimerSetTimes.it_interval.tv_nsec = 0; #endif - *phwo = handle; - return MMSYSERR_NOERROR; + *phwo = handle; + return MMSYSERR_NOERROR; } MMRESULT waveOutReset(HWAVEOUT hwo) { - WAVE_OUT_LOGD("waveOutReset()"); - //TODO - return 0; + WAVE_OUT_LOGD("waveOutReset()"); + //TODO + return 0; } MMRESULT waveOutClose(HWAVEOUT handle) { - WAVE_OUT_LOGD("waveOutClose()"); + WAVE_OUT_LOGD("waveOutClose()"); - // destroy buffer queue audio player object, and invalidate all associated interfaces - if (handle->bqPlayerObject != NULL) { - (*handle->bqPlayerObject)->Destroy(handle->bqPlayerObject); - handle->bqPlayerObject = NULL; - handle->bqPlayerPlay = NULL; - handle->bqPlayerBufferQueue = NULL; - handle->bqPlayerVolume = NULL; - } + // destroy buffer queue audio player object, and invalidate all associated interfaces + if (handle->bqPlayerObject != NULL) { + (*handle->bqPlayerObject)->Destroy(handle->bqPlayerObject); + handle->bqPlayerObject = NULL; + handle->bqPlayerPlay = NULL; + handle->bqPlayerBufferQueue = NULL; + handle->bqPlayerVolume = NULL; + } - // destroy output mix object, and invalidate all associated interfaces - if (handle->outputMixObject != NULL) { - (*handle->outputMixObject)->Destroy(handle->outputMixObject); - handle->outputMixObject = NULL; - } + // destroy output mix object, and invalidate all associated interfaces + if (handle->outputMixObject != NULL) { + (*handle->outputMixObject)->Destroy(handle->outputMixObject); + handle->outputMixObject = NULL; + } - // destroy engine object, and invalidate all associated interfaces - if (handle->engineObject != NULL) { - (*handle->engineObject)->Destroy(handle->engineObject); - handle->engineObject = NULL; - handle->engineEngine = NULL; - } + // destroy engine object, and invalidate all associated interfaces + if (handle->engineObject != NULL) { + (*handle->engineObject)->Destroy(handle->engineObject); + handle->engineObject = NULL; + handle->engineEngine = NULL; + } - pthread_mutex_destroy(&handle->audioEngineLock); + pthread_mutex_destroy(&handle->audioEngineLock); #if defined NEW_WIN32_SOUND_ENGINE - sem_destroy(&handle->waveOutLock); + sem_destroy(&handle->waveOutLock); #else - onPlayerDone(handle); - if(handle->playerDoneTimer) - timer_delete(handle->playerDoneTimer); + onPlayerDone(handle); + if (handle->playerDoneTimer) + timer_delete(handle->playerDoneTimer); #endif - memset(handle, 0, sizeof(struct _HWAVEOUT)); - free(handle); - return 0; + memset(handle, 0, sizeof(struct _HWAVEOUT)); + free(handle); + return 0; } MMRESULT waveOutPrepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) { - WAVE_OUT_LOGD("waveOutPrepareHeader()"); - //TODO - return 0; + WAVE_OUT_LOGD("waveOutPrepareHeader()"); + //TODO + return 0; } MMRESULT waveOutUnprepareHeader(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) { - WAVE_OUT_LOGD("waveOutUnprepareHeader()"); - //TODO - return 0; + WAVE_OUT_LOGD("waveOutUnprepareHeader()"); + //TODO + return 0; } MMRESULT waveOutWrite(HWAVEOUT hwo, LPWAVEHDR pwh, UINT cbwh) { - WAVE_OUT_LOGD("waveOutWrite()"); + WAVE_OUT_LOGD("waveOutWrite()"); #if defined NEW_WIN32_SOUND_ENGINE - WAVE_OUT_LOGD("waveOutWrite() before sem_wait() -1"); - sem_wait(&hwo->waveOutLock); // Decrement, lock if 0 - WAVE_OUT_LOGD("waveOutWrite() after sem_wait() -1"); + WAVE_OUT_LOGD("waveOutWrite() before sem_wait() -1"); + sem_wait(&hwo->waveOutLock); // Decrement, lock if 0 + WAVE_OUT_LOGD("waveOutWrite() after sem_wait() -1"); - LPWAVEHDR pWaveHeaderNextToWriteBackup = hwo->pWaveHeaderNextToWrite; + LPWAVEHDR pWaveHeaderNextToWriteBackup = hwo->pWaveHeaderNextToWrite; - pthread_mutex_lock(&hwo->audioEngineLock); - if(hwo->pWaveHeaderNextToWrite) { - hwo->pWaveHeaderNextToWrite->lpNext = pwh; - } else { - hwo->pWaveHeaderNextToRead = pwh; - } - hwo->pWaveHeaderNextToWrite = pwh; - pwh->lpNext = NULL; - pthread_mutex_unlock(&hwo->audioEngineLock); + pthread_mutex_lock(&hwo->audioEngineLock); + if(hwo->pWaveHeaderNextToWrite) { + hwo->pWaveHeaderNextToWrite->lpNext = pwh; + } else { + hwo->pWaveHeaderNextToRead = pwh; + } + hwo->pWaveHeaderNextToWrite = pwh; + pwh->lpNext = NULL; + pthread_mutex_unlock(&hwo->audioEngineLock); - WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() play right now"); - SLresult result = (*hwo->bqPlayerBufferQueue)->Enqueue(hwo->bqPlayerBufferQueue, pwh->lpData, pwh->dwBufferLength); - if (SL_RESULT_SUCCESS != result) { - WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() error: %d (SL_RESULT_BUFFER_INSUFFICIENT=7)", result); + WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() play right now"); + SLresult result = (*hwo->bqPlayerBufferQueue)->Enqueue(hwo->bqPlayerBufferQueue, pwh->lpData, pwh->dwBufferLength); + if (SL_RESULT_SUCCESS != result) { + WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() error: %d (SL_RESULT_BUFFER_INSUFFICIENT=7)", result); - pthread_mutex_lock(&hwo->audioEngineLock); - if(pWaveHeaderNextToWriteBackup) { - hwo->pWaveHeaderNextToWrite = pWaveHeaderNextToWriteBackup; - hwo->pWaveHeaderNextToWrite->lpNext = NULL; - if(hwo->pWaveHeaderNextToRead == pwh) { - hwo->pWaveHeaderNextToRead = pWaveHeaderNextToWriteBackup; - } - } else { - hwo->pWaveHeaderNextToWrite = NULL; - hwo->pWaveHeaderNextToRead = NULL; - } - pthread_mutex_unlock(&hwo->audioEngineLock); + pthread_mutex_lock(&hwo->audioEngineLock); + if(pWaveHeaderNextToWriteBackup) { + hwo->pWaveHeaderNextToWrite = pWaveHeaderNextToWriteBackup; + hwo->pWaveHeaderNextToWrite->lpNext = NULL; + if(hwo->pWaveHeaderNextToRead == pwh) { + hwo->pWaveHeaderNextToRead = pWaveHeaderNextToWriteBackup; + } + } else { + hwo->pWaveHeaderNextToWrite = NULL; + hwo->pWaveHeaderNextToRead = NULL; + } + pthread_mutex_unlock(&hwo->audioEngineLock); - PostThreadMessage(1, MM_WOM_DONE, hwo, pwh); + PostThreadMessage(1, MM_WOM_DONE, hwo, pwh); - return MMSYSERR_ERROR; - } + return MMSYSERR_ERROR; + } #else - pwh->lpNext = NULL; - if(hwo->pWaveHeaderNext == NULL) { - hwo->pWaveHeaderNext = pwh; - WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() play right now"); - SLresult result = (*hwo->bqPlayerBufferQueue)->Enqueue(hwo->bqPlayerBufferQueue, pwh->lpData, pwh->dwBufferLength); - if (SL_RESULT_SUCCESS != result) { - WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() error: %d (SL_RESULT_BUFFER_INSUFFICIENT=7)", result); - //onPlayerDone(hwo); - //pthread_mutex_unlock(&hwo->audioEngineLock); - return MMSYSERR_ERROR; - } - } else { - LPWAVEHDR pWaveHeaderNext = hwo->pWaveHeaderNext; - while (pWaveHeaderNext->lpNext) - pWaveHeaderNext = pWaveHeaderNext->lpNext; - WAVE_OUT_LOGD("waveOutWrite() play when finishing the current one"); - pWaveHeaderNext->lpNext = pwh; - } + pwh->lpNext = NULL; + if (hwo->pWaveHeaderNext == NULL) { + hwo->pWaveHeaderNext = pwh; + WAVE_OUT_LOGD("waveOutWrite() bqPlayerBufferQueue->Enqueue() play right now"); + SLresult result = (*hwo->bqPlayerBufferQueue)->Enqueue(hwo->bqPlayerBufferQueue, + pwh->lpData, pwh->dwBufferLength); + if (SL_RESULT_SUCCESS != result) { + WAVE_OUT_LOGD( + "waveOutWrite() bqPlayerBufferQueue->Enqueue() error: %d (SL_RESULT_BUFFER_INSUFFICIENT=7)", + result); + //onPlayerDone(hwo); + //pthread_mutex_unlock(&hwo->audioEngineLock); + return MMSYSERR_ERROR; + } + } else { + LPWAVEHDR pWaveHeaderNext = hwo->pWaveHeaderNext; + while (pWaveHeaderNext->lpNext) + pWaveHeaderNext = pWaveHeaderNext->lpNext; + WAVE_OUT_LOGD("waveOutWrite() play when finishing the current one"); + pWaveHeaderNext->lpNext = pwh; + } - if (timer_settime(hwo->playerDoneTimer, 0, &(hwo->playerDoneTimerSetTimes), NULL) == -1) { - WAVE_OUT_LOGD("waveOutWrite() ERROR in timer_settime (playerDoneTimerSetTimes)"); - } + if (timer_settime(hwo->playerDoneTimer, 0, &(hwo->playerDoneTimerSetTimes), NULL) == -1) { + WAVE_OUT_LOGD("waveOutWrite() ERROR in timer_settime (playerDoneTimerSetTimes)"); + } #endif - return MMSYSERR_NOERROR; + return MMSYSERR_NOERROR; } MMRESULT waveOutGetDevCaps(UINT_PTR uDeviceID, LPWAVEOUTCAPS pwoc, UINT cbwoc) { - WAVE_OUT_LOGD("waveOutGetDevCaps()"); - if(pwoc) { - pwoc->dwFormats = WAVE_FORMAT_4M08; - } - return MMSYSERR_NOERROR; + WAVE_OUT_LOGD("waveOutGetDevCaps()"); + if (pwoc) { + pwoc->dwFormats = WAVE_FORMAT_4M08; + } + return MMSYSERR_NOERROR; } MMRESULT waveOutGetID(HWAVEOUT hwo, LPUINT puDeviceID) { - WAVE_OUT_LOGD("waveOutGetID()"); - //TODO - return 0; + WAVE_OUT_LOGD("waveOutGetID()"); + //TODO + return 0; } - - BOOL GetMessage(LPMSG lpMsg, HWND hWnd, UINT wMsgFilterMin, UINT wMsgFilterMax) { #if defined NEW_WIN32_SOUND_ENGINE - pthread_t thId = pthread_self(); - for(int i = 0; i < MAX_CREATED_THREAD; i++) { - HANDLE threadHandle = threads[i]; - if(threadHandle && threadHandle->threadId == thId) { - WaitForSingleObject(threadHandle->threadEventMessage, INFINITE); - if(lpMsg) - memcpy(lpMsg, &threadHandle->threadMessage, sizeof(MSG)); - if(lpMsg->message == WM_QUIT) - return FALSE; - return TRUE; - } - } + pthread_t thId = pthread_self(); + for(int i = 0; i < MAX_CREATED_THREAD; i++) { + HANDLE threadHandle = threads[i]; + if(threadHandle && threadHandle->threadId == thId) { + WaitForSingleObject(threadHandle->threadEventMessage, INFINITE); + if(lpMsg) + memcpy(lpMsg, &threadHandle->threadMessage, sizeof(MSG)); + if(lpMsg->message == WM_QUIT) + return FALSE; + return TRUE; + } + } - return FALSE; + return FALSE; #else - return FALSE; + return FALSE; #endif } BOOL PostThreadMessage(DWORD idThread, UINT Msg, WPARAM wParam, LPARAM lParam) { - WAVE_OUT_LOGD("waveOut PostThreadMessage()"); + WAVE_OUT_LOGD("waveOut PostThreadMessage()"); #if defined NEW_WIN32_SOUND_ENGINE - for(int i = 0; i < MAX_CREATED_THREAD; i++) { - HANDLE threadHandle = threads[i]; - if(threadHandle && threadHandle->threadIndex == idThread) { - threadHandle->threadMessage.hwnd = NULL; - threadHandle->threadMessage.message = Msg; - threadHandle->threadMessage.wParam = wParam; - threadHandle->threadMessage.lParam = lParam; - WAVE_OUT_LOGD("waveOut SetEvent()"); - SetEvent(threadHandle->threadEventMessage); - return TRUE; - } - } - return TRUE; - //return FALSE; + for(int i = 0; i < MAX_CREATED_THREAD; i++) { + HANDLE threadHandle = threads[i]; + if(threadHandle && threadHandle->threadIndex == idThread) { + threadHandle->threadMessage.hwnd = NULL; + threadHandle->threadMessage.message = Msg; + threadHandle->threadMessage.wParam = wParam; + threadHandle->threadMessage.lParam = lParam; + WAVE_OUT_LOGD("waveOut SetEvent()"); + SetEvent(threadHandle->threadEventMessage); + return TRUE; + } + } + return TRUE; + //return FALSE; #else - return TRUE; + return TRUE; #endif } HWND CreateWindow() { - HANDLE handle = malloc(sizeof(struct _HANDLE)); - memset(handle, 0, sizeof(struct _HANDLE)); - handle->handleType = HANDLE_TYPE_WINDOW; - handle->windowDC = CreateCompatibleDC(NULL); - return handle; + HANDLE handle = malloc(sizeof(struct _HANDLE)); + memset(handle, 0, sizeof(struct _HANDLE)); + handle->handleType = HANDLE_TYPE_WINDOW; + handle->windowDC = CreateCompatibleDC(NULL); + return handle; } BOOL DestroyWindow(HWND hWnd) { - memset(hWnd, 0, sizeof(struct _HANDLE)); - free(hWnd); - return TRUE; + memset(hWnd, 0, sizeof(struct _HANDLE)); + free(hWnd); + return TRUE; } BOOL GetWindowPlacement(HWND hWnd, WINDOWPLACEMENT *lpwndpl) { - if(lpwndpl) { - lpwndpl->rcNormalPosition.left = 0; - lpwndpl->rcNormalPosition.top = 0; - } - return TRUE; + if (lpwndpl) { + lpwndpl->rcNormalPosition.left = 0; + lpwndpl->rcNormalPosition.top = 0; + } + return TRUE; } -BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl) { return 0; } -extern void draw(); -BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase) { - // Update when switch the screen off - draw(); //TODO Need a true WM_PAINT event! - return 0; -} -BOOL AdjustWindowRect(LPRECT lpRect, DWORD dwStyle, BOOL bMenu) { return 0; } -LONG GetWindowLong(HWND hWnd, int nIndex) { return 0; } -HMENU GetMenu(HWND hWnd) { return NULL; } -int GetMenuItemCount(HMENU hMenu) { return 0; } -UINT GetMenuItemID(HMENU hMenu, int nPos) { return 0; } -HMENU GetSubMenu(HMENU hMenu, int nPos) { return NULL; } -int GetMenuString(HMENU hMenu, UINT uIDItem, LPTSTR lpString,int cchMax, UINT flags) { return 0; } -BOOL DeleteMenu(HMENU hMenu, UINT uPosition, UINT uFlags) { return FALSE; } -BOOL InsertMenu(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, LPCTSTR lpNewItem) { return FALSE; } -BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, UINT uFlags) { return 0; } +BOOL SetWindowPlacement(HWND hWnd, CONST WINDOWPLACEMENT *lpwndpl) { return 0; } + +extern void draw(); + +BOOL InvalidateRect(HWND hWnd, CONST RECT *lpRect, BOOL bErase) { + // Update when switch the screen off + draw(); //TODO Need a true WM_PAINT event! + return 0; +} + +BOOL AdjustWindowRect(LPRECT lpRect, DWORD dwStyle, BOOL bMenu) { return 0; } + +LONG GetWindowLong(HWND hWnd, int nIndex) { return 0; } + +HMENU GetMenu(HWND hWnd) { return NULL; } + +int GetMenuItemCount(HMENU hMenu) { return 0; } + +UINT GetMenuItemID(HMENU hMenu, int nPos) { return 0; } + +HMENU GetSubMenu(HMENU hMenu, int nPos) { return NULL; } + +int GetMenuString(HMENU hMenu, UINT uIDItem, LPTSTR lpString, int cchMax, UINT flags) { return 0; } + +BOOL DeleteMenu(HMENU hMenu, UINT uPosition, UINT uFlags) { return FALSE; } + +BOOL InsertMenu(HMENU hMenu, UINT uPosition, UINT uFlags, UINT_PTR uIDNewItem, + LPCTSTR lpNewItem) { return FALSE; } + +BOOL SetWindowPos(HWND hWnd, HWND hWndInsertAfter, int X, int Y, int cx, int cy, + UINT uFlags) { return 0; } BOOL WINAPI SetWindowOrgEx(HDC hdc, int x, int y, LPPOINT lppt) { - if(lppt) { - lppt->x = hdc->windowOriginX; - lppt->y = hdc->windowOriginY; - } - hdc->windowOriginX = x; - hdc->windowOriginY = y; - return TRUE; + if (lppt) { + lppt->x = hdc->windowOriginX; + lppt->y = hdc->windowOriginY; + } + hdc->windowOriginX = x; + hdc->windowOriginY = y; + return TRUE; } // GDI HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h) { - if(h) { - switch (h->handleType) { - case HGDIOBJ_TYPE_PEN: - break; - case HGDIOBJ_TYPE_BRUSH: { - HBRUSH oldSelectedBrushColor = hdc->selectedBrushColor; - hdc->selectedBrushColor = h; - return oldSelectedBrushColor; - } - case HGDIOBJ_TYPE_FONT: - break; - case HGDIOBJ_TYPE_BITMAP: { - HBITMAP oldSelectedBitmap = hdc->selectedBitmap; - hdc->selectedBitmap = h; - return oldSelectedBitmap; - } - case HGDIOBJ_TYPE_REGION: - break; - case HGDIOBJ_TYPE_PALETTE: { - HPALETTE oldSelectedPalette = hdc->selectedPalette; - hdc->selectedPalette = h; - return oldSelectedPalette; - } - default: - break; - } - } - return NULL; + if (h) { + switch (h->handleType) { + case HGDIOBJ_TYPE_PEN: + break; + case HGDIOBJ_TYPE_BRUSH: { + HBRUSH oldSelectedBrushColor = hdc->selectedBrushColor; + hdc->selectedBrushColor = h; + return oldSelectedBrushColor; + } + case HGDIOBJ_TYPE_FONT: + break; + case HGDIOBJ_TYPE_BITMAP: { + HBITMAP oldSelectedBitmap = hdc->selectedBitmap; + hdc->selectedBitmap = h; + return oldSelectedBitmap; + } + case HGDIOBJ_TYPE_REGION: + break; + case HGDIOBJ_TYPE_PALETTE: { + HPALETTE oldSelectedPalette = hdc->selectedPalette; + hdc->selectedPalette = h; + return oldSelectedPalette; + } + default: + break; + } + } + return NULL; } + int GetObject(HGDIOBJ h, int c, LPVOID pv) { - if(h) { - switch (h->handleType) { - case HGDIOBJ_TYPE_PEN: - break; - case HGDIOBJ_TYPE_BRUSH: - break; - case HGDIOBJ_TYPE_FONT: - break; - case HGDIOBJ_TYPE_BITMAP: - if(h && c == sizeof(BITMAP) && pv) { - BITMAP * pBITMAP = (BITMAP *)pv; - HBITMAP hBITMAP = (HBITMAP)h; - pBITMAP->bmType = 0; - pBITMAP->bmWidth = hBITMAP->bitmapInfoHeader->biWidth; - pBITMAP->bmHeight = hBITMAP->bitmapInfoHeader->biWidth; - pBITMAP->bmWidthBytes = (4 * ((hBITMAP->bitmapInfoHeader->biWidth * hBITMAP->bitmapInfoHeader->biBitCount + 31) / 32)); - pBITMAP->bmPlanes = hBITMAP->bitmapInfoHeader->biPlanes; - pBITMAP->bmBitsPixel = hBITMAP->bitmapInfoHeader->biBitCount; - pBITMAP->bmBits = (LPVOID)hBITMAP->bitmapBits; - return sizeof(BITMAP); - } - break; - case HGDIOBJ_TYPE_REGION: - break; - case HGDIOBJ_TYPE_PALETTE: - break; - default: - break; - } - } return 0; + if (h) { + switch (h->handleType) { + case HGDIOBJ_TYPE_PEN: + break; + case HGDIOBJ_TYPE_BRUSH: + break; + case HGDIOBJ_TYPE_FONT: + break; + case HGDIOBJ_TYPE_BITMAP: + if (h && c == sizeof(BITMAP) && pv) { + BITMAP *pBITMAP = (BITMAP *) pv; + HBITMAP hBITMAP = (HBITMAP) h; + pBITMAP->bmType = 0; + pBITMAP->bmWidth = hBITMAP->bitmapInfoHeader->biWidth; + pBITMAP->bmHeight = hBITMAP->bitmapInfoHeader->biWidth; + pBITMAP->bmWidthBytes = (4 * ((hBITMAP->bitmapInfoHeader->biWidth * + hBITMAP->bitmapInfoHeader->biBitCount + 31) / + 32)); + pBITMAP->bmPlanes = hBITMAP->bitmapInfoHeader->biPlanes; + pBITMAP->bmBitsPixel = hBITMAP->bitmapInfoHeader->biBitCount; + pBITMAP->bmBits = (LPVOID) hBITMAP->bitmapBits; + return sizeof(BITMAP); + } + break; + case HGDIOBJ_TYPE_REGION: + break; + case HGDIOBJ_TYPE_PALETTE: + break; + default: + break; + } + } + return 0; } + HGDIOBJ GetCurrentObject(HDC hdc, UINT type) { - if(hdc) - return hdc->selectedBitmap; - return NULL; + if (hdc) + return hdc->selectedBitmap; + return NULL; } + BOOL DeleteObject(HGDIOBJ ho) { - PAINT_LOGD("PAINT DeleteObject(ho: %p)", ho); - if(ho) { - switch(ho->handleType) { - case HGDIOBJ_TYPE_PALETTE: { - PAINT_LOGD("PAINT DeleteObject() HGDIOBJ_TYPE_PALETTE"); - ho->handleType = HGDIOBJ_TYPE_INVALID; - if(ho->paletteLog) - free(ho->paletteLog); - ho->paletteLog = NULL; - free(ho); - return TRUE; - } - case HGDIOBJ_TYPE_BITMAP: { - PAINT_LOGD("PAINT DeleteObject() HGDIOBJ_TYPE_BITMAP"); - if(ho == rootBITMAP) - return FALSE; - ho->handleType = HGDIOBJ_TYPE_INVALID; - if(ho->bitmapInfo) - free((void *) ho->bitmapInfo); - ho->bitmapInfo = NULL; - ho->bitmapInfoHeader = NULL; - if(ho->bitmapBits) - free((void *) ho->bitmapBits); - ho->bitmapBits = NULL; - free(ho); - return TRUE; - } - case HGDIOBJ_TYPE_BRUSH: { - PAINT_LOGD("PAINT DeleteObject() HGDIOBJ_TYPE_BRUSH"); - ho->handleType = HGDIOBJ_TYPE_INVALID; - ho->brushColor = 0; - free(ho); - return TRUE; - } - default: - break; - } - } - return FALSE; + PAINT_LOGD("PAINT DeleteObject(ho: %p)", ho); + if (ho) { + switch (ho->handleType) { + case HGDIOBJ_TYPE_PALETTE: { + PAINT_LOGD("PAINT DeleteObject() HGDIOBJ_TYPE_PALETTE"); + ho->handleType = HGDIOBJ_TYPE_INVALID; + if (ho->paletteLog) + free(ho->paletteLog); + ho->paletteLog = NULL; + free(ho); + return TRUE; + } + case HGDIOBJ_TYPE_BITMAP: { + PAINT_LOGD("PAINT DeleteObject() HGDIOBJ_TYPE_BITMAP"); + if (ho == rootBITMAP) + return FALSE; + ho->handleType = HGDIOBJ_TYPE_INVALID; + if (ho->bitmapInfo) + free((void *) ho->bitmapInfo); + ho->bitmapInfo = NULL; + ho->bitmapInfoHeader = NULL; + if (ho->bitmapBits) + free((void *) ho->bitmapBits); + ho->bitmapBits = NULL; + free(ho); + return TRUE; + } + case HGDIOBJ_TYPE_BRUSH: { + PAINT_LOGD("PAINT DeleteObject() HGDIOBJ_TYPE_BRUSH"); + ho->handleType = HGDIOBJ_TYPE_INVALID; + ho->brushColor = 0; + free(ho); + return TRUE; + } + default: + break; + } + } + return FALSE; } + HGDIOBJ GetStockObject(int i) { - //TODO - return NULL; + //TODO + return NULL; } -HPALETTE CreatePalette(CONST LOGPALETTE * plpal) { - HGDIOBJ handle = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); - memset(handle, 0, sizeof(_HGDIOBJ)); - handle->handleType = HGDIOBJ_TYPE_PALETTE; - if(plpal && plpal->palNumEntries >= 0 && plpal->palNumEntries <= 256) { - size_t structSize = sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * (size_t)(plpal->palNumEntries - 1); - handle->paletteLog = malloc(structSize); - memcpy(handle->paletteLog, plpal, structSize); - } - return handle; + +HPALETTE CreatePalette(CONST LOGPALETTE *plpal) { + HGDIOBJ handle = (HGDIOBJ) malloc(sizeof(_HGDIOBJ)); + memset(handle, 0, sizeof(_HGDIOBJ)); + handle->handleType = HGDIOBJ_TYPE_PALETTE; + if (plpal && plpal->palNumEntries >= 0 && plpal->palNumEntries <= 256) { + size_t structSize = + sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * (size_t) (plpal->palNumEntries - 1); + handle->paletteLog = malloc(structSize); + memcpy(handle->paletteLog, plpal, structSize); + } + return handle; } + HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd) { - if(!hdc) + if (!hdc) return NULL; - HPALETTE hOldPal = hdc->selectedPalette; - hdc->selectedPalette = hPal; - return hOldPal; + HPALETTE hOldPal = hdc->selectedPalette; + hdc->selectedPalette = hPal; + return hOldPal; } + UINT RealizePalette(HDC hdc) { - if(hdc && hdc->selectedPalette) { - PLOGPALETTE paletteLog = hdc->selectedPalette->paletteLog; - if (paletteLog) { - HPALETTE oldRealizedPalette = hdc->realizedPalette; - hdc->realizedPalette = CreatePalette(paletteLog); - if(oldRealizedPalette) - DeleteObject(oldRealizedPalette); - } - } - return 0; + if (hdc && hdc->selectedPalette) { + PLOGPALETTE paletteLog = hdc->selectedPalette->paletteLog; + if (paletteLog) { + HPALETTE oldRealizedPalette = hdc->realizedPalette; + hdc->realizedPalette = CreatePalette(paletteLog); + if (oldRealizedPalette) + DeleteObject(oldRealizedPalette); + } + } + return 0; } COLORREF SetBkColor(HDC hdc, COLORREF color) { - COLORREF backgroundColorBackup = hdc->backgroundColor; - hdc->backgroundColor = color; - hdc->isBackgroundColorSet = TRUE; - return backgroundColorBackup; + COLORREF backgroundColorBackup = hdc->backgroundColor; + hdc->backgroundColor = color; + hdc->isBackgroundColorSet = TRUE; + return backgroundColorBackup; } // DC HDC CreateCompatibleDC(HDC hdc) { - HDC handle = (HDC)malloc(sizeof(struct _HDC)); - memset(handle, 0, sizeof(struct _HDC)); - handle->handleType = HDC_TYPE_DC; - handle->hdcCompatible = hdc; + HDC handle = (HDC) malloc(sizeof(struct _HDC)); + memset(handle, 0, sizeof(struct _HDC)); + handle->handleType = HDC_TYPE_DC; + handle->hdcCompatible = hdc; handle->selectedBitmap = rootBITMAP; - return handle; + return handle; } + HDC GetDC(HWND hWnd) { - if(!hWnd) - return NULL; - return hWnd->windowDC; + if (!hWnd) + return NULL; + return hWnd->windowDC; } + int ReleaseDC(HWND hWnd, HDC hDC) { - if(!hWnd) - return NULL; - hWnd->windowDC = NULL; //? - return TRUE; + if (!hWnd) + return NULL; + hWnd->windowDC = NULL; //? + return TRUE; } BOOL DeleteDC(HDC hdc) { - memset(hdc, 0, sizeof(struct _HDC)); - free(hdc); - return TRUE; + memset(hdc, 0, sizeof(struct _HDC)); + free(hdc); + return TRUE; } HBRUSH WINAPI CreateSolidBrush(COLORREF color) { - HGDIOBJ handle = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); - memset(handle, 0, sizeof(_HGDIOBJ)); - handle->handleType = HGDIOBJ_TYPE_BRUSH; - handle->brushColor = color; - return handle; + HGDIOBJ handle = (HGDIOBJ) malloc(sizeof(_HGDIOBJ)); + memset(handle, 0, sizeof(_HGDIOBJ)); + handle->handleType = HGDIOBJ_TYPE_BRUSH; + handle->brushColor = color; + return handle; } BOOL MoveToEx(HDC hdc, int x, int y, LPPOINT lppt) { - //TODO - return 0; + //TODO + return 0; } + BOOL LineTo(HDC hdc, int x, int y) { - //TODO - return 0; + //TODO + return 0; } + BOOL PatBlt(HDC hdcDest, int x, int y, int w, int h, DWORD rop) { - PAINT_LOGD("PAINT PatBlt(hdcDest: %p, x: %d, y: %d, w: %d, h: %d, rop: 0x%08x)", hdcDest, x, y, w, h, rop); + PAINT_LOGD("PAINT PatBlt(hdcDest: %p, x: %d, y: %d, w: %d, h: %d, rop: 0x%08x)", hdcDest, x, y, + w, h, rop); - if((hdcDest->selectedBitmap || hdcDest->hdcCompatible == NULL) && w && h) { - HBITMAP hBitmapDestination = NULL; - void * pixelsDestination = NULL; - int destinationWidth = 0; - int destinationHeight = 0; - float destinationStride = 0; + if ((hdcDest->selectedBitmap || hdcDest->hdcCompatible == NULL) && w && h) { + HBITMAP hBitmapDestination = NULL; + void *pixelsDestination = NULL; + int destinationWidth = 0; + int destinationHeight = 0; + float destinationStride = 0; - JNIEnv * jniEnv = NULL; + JNIEnv *jniEnv = NULL; - if(hdcDest->hdcCompatible == NULL) { - // We update the main window + if (hdcDest->hdcCompatible == NULL) { + // We update the main window - jint ret; - BOOL needDetach = FALSE; - ret = (*java_machine)->GetEnv(java_machine, (void **) &jniEnv, JNI_VERSION_1_6); - if (ret == JNI_EDETACHED) { - // GetEnv: not attached - ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL); - if (ret == JNI_OK) { - needDetach = TRUE; - } - } + jint ret; + BOOL needDetach = FALSE; + ret = (*java_machine)->GetEnv(java_machine, (void **) &jniEnv, JNI_VERSION_1_6); + if (ret == JNI_EDETACHED) { + // GetEnv: not attached + ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL); + if (ret == JNI_OK) { + needDetach = TRUE; + } + } - destinationWidth = androidBitmapInfo.width; - destinationHeight = androidBitmapInfo.height; + destinationWidth = androidBitmapInfo.width; + destinationHeight = androidBitmapInfo.height; - destinationStride = androidBitmapInfo.stride; + destinationStride = androidBitmapInfo.stride; // RECT newRectangleToUpdate; // newRectangleToUpdate.left = x; @@ -1987,139 +2055,152 @@ BOOL PatBlt(HDC hdcDest, int x, int y, int w, int h, DWORD rop) { // newRectangleToUpdate.bottom = y + h; // UnionRect(&mainViewRectangleToUpdate, &mainViewRectangleToUpdate, &newRectangleToUpdate); - if ((ret = AndroidBitmap_lockPixels(jniEnv, bitmapMainScreen, &pixelsDestination)) < 0) { - LOGD("AndroidBitmap_lockPixels() failed ! error=%d", ret); - return FALSE; - } - } else { - hBitmapDestination = hdcDest->selectedBitmap; - pixelsDestination = (void *) hBitmapDestination->bitmapBits; + if ((ret = AndroidBitmap_lockPixels(jniEnv, bitmapMainScreen, &pixelsDestination)) < + 0) { + LOGD("AndroidBitmap_lockPixels() failed ! error=%d", ret); + return FALSE; + } + } else { + hBitmapDestination = hdcDest->selectedBitmap; + pixelsDestination = (void *) hBitmapDestination->bitmapBits; - destinationWidth = hBitmapDestination->bitmapInfoHeader->biWidth; - destinationHeight = abs(hBitmapDestination->bitmapInfoHeader->biHeight); - //TODO destinationTopDown = hBitmapDestination->bitmapInfoHeader->biHeight < 0; + destinationWidth = hBitmapDestination->bitmapInfoHeader->biWidth; + destinationHeight = abs(hBitmapDestination->bitmapInfoHeader->biHeight); + //TODO destinationTopDown = hBitmapDestination->bitmapInfoHeader->biHeight < 0; - destinationStride = (float)(4 * ((destinationWidth * hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32)); - } + destinationStride = (float) (4 * ((destinationWidth * + hBitmapDestination->bitmapInfoHeader->biBitCount + + 31) / 32)); + } - x -= hdcDest->windowOriginX; - y -= hdcDest->windowOriginY; + x -= hdcDest->windowOriginX; + y -= hdcDest->windowOriginY; - HPALETTE palette = hdcDest->realizedPalette; - if(!palette) - palette = hdcDest->selectedPalette; - PALETTEENTRY * palPalEntry = palette && palette->paletteLog && palette->paletteLog->palPalEntry ? - palette->paletteLog->palPalEntry : NULL; + HPALETTE palette = hdcDest->realizedPalette; + if (!palette) + palette = hdcDest->selectedPalette; + PALETTEENTRY *palPalEntry = + palette && palette->paletteLog && palette->paletteLog->palPalEntry ? + palette->paletteLog->palPalEntry : NULL; - COLORREF brushColor = 0xFF000000; // 0xAABBGGRR - if(hdcDest->selectedBrushColor) { - brushColor = hdcDest->selectedBrushColor->brushColor; - } + COLORREF brushColor = 0xFF000000; // 0xAABBGGRR + if (hdcDest->selectedBrushColor) { + brushColor = hdcDest->selectedBrushColor->brushColor; + } - for (int currentY = y; currentY < y + h; currentY++) { - for (int currentX = x; currentX < x + w; currentX++) { - BYTE * destinationPixel = pixelsDestination + (int)(destinationStride * currentY + 4.0 * currentX); + for (int currentY = y; currentY < y + h; currentY++) { + for (int currentX = x; currentX < x + w; currentX++) { + BYTE *destinationPixel = + pixelsDestination + (int) (destinationStride * currentY + 4.0 * currentX); - // -> ARGB_8888 - switch (rop) { - case DSTINVERT: - destinationPixel[0] = (BYTE) (255 - destinationPixel[0]); - destinationPixel[1] = (BYTE) (255 - destinationPixel[1]); - destinationPixel[2] = (BYTE) (255 - destinationPixel[2]); - destinationPixel[3] = 255; - break; - case BLACKNESS: - destinationPixel[0] = palPalEntry[0].peRed; - destinationPixel[1] = palPalEntry[0].peGreen; - destinationPixel[2] = palPalEntry[0].peBlue; - destinationPixel[3] = 255; - break; - case WHITENESS: - destinationPixel[0] = 255; //palPalEntry[1].peRed; - destinationPixel[1] = 255; //palPalEntry[1].peGreen; - destinationPixel[2] = 255; //palPalEntry[1].peBlue; - destinationPixel[3] = 255; - break; - case PATCOPY: - // 0xAABBGGRR - *((UINT *)destinationPixel) = brushColor; - break; - default: - break; - } - } - } + // -> ARGB_8888 + switch (rop) { + case DSTINVERT: + destinationPixel[0] = (BYTE) (255 - destinationPixel[0]); + destinationPixel[1] = (BYTE) (255 - destinationPixel[1]); + destinationPixel[2] = (BYTE) (255 - destinationPixel[2]); + destinationPixel[3] = 255; + break; + case BLACKNESS: + destinationPixel[0] = palPalEntry[0].peRed; + destinationPixel[1] = palPalEntry[0].peGreen; + destinationPixel[2] = palPalEntry[0].peBlue; + destinationPixel[3] = 255; + break; + case WHITENESS: + destinationPixel[0] = 255; //palPalEntry[1].peRed; + destinationPixel[1] = 255; //palPalEntry[1].peGreen; + destinationPixel[2] = 255; //palPalEntry[1].peBlue; + destinationPixel[3] = 255; + break; + case PATCOPY: + // 0xAABBGGRR + *((UINT *) destinationPixel) = brushColor; + break; + default: + break; + } + } + } - if(jniEnv) - AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen); - } - return 0; + if (jniEnv) + AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen); + } + return 0; } -#define ROP_PSDPxax 0x00B8074A // ternary ROP + +#define ROP_PSDPxax 0x00B8074A // ternary ROP #define ROP_PDSPxax 0x00D80745 + BOOL BitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop) { - if(hdcSrc && hdcSrc->selectedBitmap) { - HBITMAP hBitmap = hdcSrc->selectedBitmap; - int sourceWidth = hBitmap->bitmapInfoHeader->biWidth; - int sourceHeight = abs(hBitmap->bitmapInfoHeader->biHeight); - return StretchBlt(hdc, x, y, cx, cy, hdcSrc, x1, y1, min(cx, sourceWidth), min(cy, sourceHeight), rop); - } - return FALSE; + if (hdcSrc && hdcSrc->selectedBitmap) { + HBITMAP hBitmap = hdcSrc->selectedBitmap; + int sourceWidth = hBitmap->bitmapInfoHeader->biWidth; + int sourceHeight = abs(hBitmap->bitmapInfoHeader->biHeight); + return StretchBlt(hdc, x, y, cx, cy, hdcSrc, x1, y1, min(cx, sourceWidth), + min(cy, sourceHeight), rop); + } + return FALSE; } + int SetStretchBltMode(HDC hdc, int mode) { - //TODO - return 0; + //TODO + return 0; } -BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop) { - PAINT_LOGD("PAINT StretchBlt(hdcDest: %p, xDest: %d, yDest: %d, wDest: %d, hDest: %d, hdcSrc: %p, xSrc: %d, ySrc: %d, wSrc: %d, hSrc: %d, rop: 0x%08x)", - hdcDest, xDest, yDest, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, rop); +BOOL +StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, + int wSrc, int hSrc, DWORD rop) { + PAINT_LOGD( + "PAINT StretchBlt(hdcDest: %p, xDest: %d, yDest: %d, wDest: %d, hDest: %d, hdcSrc: %p, xSrc: %d, ySrc: %d, wSrc: %d, hSrc: %d, rop: 0x%08x)", + hdcDest, xDest, yDest, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, rop); - if(hdcDest && hdcSrc - && (hdcDest->selectedBitmap || hdcDest->hdcCompatible == NULL) - && hdcSrc->selectedBitmap && hDest && hSrc) { + if (hdcDest && hdcSrc + && (hdcDest->selectedBitmap || hdcDest->hdcCompatible == NULL) + && hdcSrc->selectedBitmap && hDest && hSrc) { - HBITMAP hBitmapSource = hdcSrc->selectedBitmap; - void * pixelsSource = (void *) hBitmapSource->bitmapBits; + HBITMAP hBitmapSource = hdcSrc->selectedBitmap; + void *pixelsSource = (void *) hBitmapSource->bitmapBits; - HBITMAP hBitmapDestination = NULL; - void * pixelsDestination = NULL; - int destinationBitCount = 8; + HBITMAP hBitmapDestination = NULL; + void *pixelsDestination = NULL; + int destinationBitCount = 8; - BOOL sourceTopDown = hBitmapSource->bitmapInfoHeader->biHeight < 0; - BOOL destinationTopDown = FALSE; + BOOL sourceTopDown = hBitmapSource->bitmapInfoHeader->biHeight < 0; + BOOL destinationTopDown = FALSE; - int sourceWidth = hBitmapSource->bitmapInfoHeader->biWidth; - int sourceHeight = abs(hBitmapSource->bitmapInfoHeader->biHeight); // Can be < 0 - int destinationWidth = 0; - int destinationHeight = 0; + int sourceWidth = hBitmapSource->bitmapInfoHeader->biWidth; + int sourceHeight = abs(hBitmapSource->bitmapInfoHeader->biHeight); // Can be < 0 + int destinationWidth = 0; + int destinationHeight = 0; - UINT sourceBitCount = hBitmapSource->bitmapInfoHeader->biBitCount; - int sourceStride = 4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32); - int destinationStride = 0; + UINT sourceBitCount = hBitmapSource->bitmapInfoHeader->biBitCount; + int sourceStride = + 4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32); + int destinationStride = 0; - JNIEnv * jniEnv = NULL; - jint ret; + JNIEnv *jniEnv = NULL; + jint ret; - if(hdcDest->hdcCompatible == NULL) { - // We update the main window + if (hdcDest->hdcCompatible == NULL) { + // We update the main window - BOOL needDetach = FALSE; - ret = (*java_machine)->GetEnv(java_machine, (void **) &jniEnv, JNI_VERSION_1_6); - if (ret == JNI_EDETACHED) { - // GetEnv: not attached - ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL); - if (ret == JNI_OK) { - needDetach = TRUE; - } - } + BOOL needDetach = FALSE; + ret = (*java_machine)->GetEnv(java_machine, (void **) &jniEnv, JNI_VERSION_1_6); + if (ret == JNI_EDETACHED) { + // GetEnv: not attached + ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL); + if (ret == JNI_OK) { + needDetach = TRUE; + } + } - destinationWidth = androidBitmapInfo.width; - destinationHeight = androidBitmapInfo.height; - destinationBitCount = 32; - destinationStride = androidBitmapInfo.stride; + destinationWidth = androidBitmapInfo.width; + destinationHeight = androidBitmapInfo.height; + destinationBitCount = 32; + destinationStride = androidBitmapInfo.stride; - destinationTopDown = TRUE; + destinationTopDown = TRUE; // RECT newRectangleToUpdate; // newRectangleToUpdate.left = xDest; @@ -2128,291 +2209,306 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc // newRectangleToUpdate.bottom = yDest + hDest; // UnionRect(&mainViewRectangleToUpdate, &mainViewRectangleToUpdate, &newRectangleToUpdate); - if ((ret = AndroidBitmap_lockPixels(jniEnv, bitmapMainScreen, &pixelsDestination)) < 0) { - LOGD("AndroidBitmap_lockPixels() failed ! error=%d", ret); - return FALSE; - } - } else { - hBitmapDestination = hdcDest->selectedBitmap; - pixelsDestination = (void *) hBitmapDestination->bitmapBits; + if ((ret = AndroidBitmap_lockPixels(jniEnv, bitmapMainScreen, &pixelsDestination)) < + 0) { + LOGD("AndroidBitmap_lockPixels() failed ! error=%d", ret); + return FALSE; + } + } else { + hBitmapDestination = hdcDest->selectedBitmap; + pixelsDestination = (void *) hBitmapDestination->bitmapBits; - destinationWidth = hBitmapDestination->bitmapInfoHeader->biWidth; - destinationHeight = abs(hBitmapDestination->bitmapInfoHeader->biHeight); - destinationTopDown = hBitmapDestination->bitmapInfoHeader->biHeight < 0; - destinationBitCount = hBitmapDestination->bitmapInfoHeader->biBitCount; - destinationStride = 4 * ((destinationWidth * hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32); - } + destinationWidth = hBitmapDestination->bitmapInfoHeader->biWidth; + destinationHeight = abs(hBitmapDestination->bitmapInfoHeader->biHeight); + destinationTopDown = hBitmapDestination->bitmapInfoHeader->biHeight < 0; + destinationBitCount = hBitmapDestination->bitmapInfoHeader->biBitCount; + destinationStride = 4 * ((destinationWidth * + hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32); + } - xDest -= hdcDest->windowOriginX; - yDest -= hdcDest->windowOriginY; + xDest -= hdcDest->windowOriginX; + yDest -= hdcDest->windowOriginY; - //LOGD("StretchBlt(%p, x:%d, y:%d, w:%d, h:%d, %08x, x:%d, y:%d, w:%d, h:%d) -> sourceBitCount: %d", hdcDest->hdcCompatible, xDest, yDest, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, sourceBitCount); + //LOGD("StretchBlt(%p, x:%d, y:%d, w:%d, h:%d, %08x, x:%d, y:%d, w:%d, h:%d) -> sourceBitCount: %d", hdcDest->hdcCompatible, xDest, yDest, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, sourceBitCount); - HPALETTE palette = hdcSrc->realizedPalette; - if(!palette) - palette = hdcSrc->selectedPalette; - PALETTEENTRY * palPalEntry = palette && palette->paletteLog && palette->paletteLog->palPalEntry ? - palette->paletteLog->palPalEntry : NULL; - if(!palPalEntry && sourceBitCount <= 8 && hBitmapSource->bitmapInfoHeader->biClrUsed > 0) { - palPalEntry = (PALETTEENTRY *)hBitmapSource->bitmapInfo->bmiColors; - } - COLORREF brushColor = 0xFF000000; // 0xAABBGGRR - if(hdcDest->selectedBrushColor) { - brushColor = hdcDest->selectedBrushColor->brushColor; - } - COLORREF backgroundColor = 0xFF000000; // 0xAABBGGRR - if(sourceBitCount > 1 && destinationBitCount == 1 && hdcSrc->isBackgroundColorSet) - { - backgroundColor = hdcSrc->backgroundColor; - } - else if(sourceBitCount == 1 && destinationBitCount > 1 && hdcDest->isBackgroundColorSet) - { - backgroundColor = hdcDest->backgroundColor; - } + HPALETTE palette = hdcSrc->realizedPalette; + if (!palette) + palette = hdcSrc->selectedPalette; + PALETTEENTRY *palPalEntry = + palette && palette->paletteLog && palette->paletteLog->palPalEntry ? + palette->paletteLog->palPalEntry : NULL; + if (!palPalEntry && sourceBitCount <= 8 && hBitmapSource->bitmapInfoHeader->biClrUsed > 0) { + palPalEntry = (PALETTEENTRY *) hBitmapSource->bitmapInfo->bmiColors; + } + COLORREF brushColor = 0xFF000000; // 0xAABBGGRR + if (hdcDest->selectedBrushColor) { + brushColor = hdcDest->selectedBrushColor->brushColor; + } + COLORREF backgroundColor = 0xFF000000; // 0xAABBGGRR + if (sourceBitCount > 1 && destinationBitCount == 1 && hdcSrc->isBackgroundColorSet) { + backgroundColor = hdcSrc->backgroundColor; + } else if (sourceBitCount == 1 && destinationBitCount > 1 && + hdcDest->isBackgroundColorSet) { + backgroundColor = hdcDest->backgroundColor; + } - StretchBltInternal(xDest, yDest, wDest, hDest, - pixelsDestination, destinationBitCount, destinationStride, destinationWidth, destinationHeight, - xSrc, ySrc, wSrc, hSrc, - pixelsSource, sourceBitCount, sourceStride, sourceWidth, sourceHeight, - rop, sourceTopDown, destinationTopDown, palPalEntry, brushColor, backgroundColor); + StretchBltInternal(xDest, yDest, wDest, hDest, + pixelsDestination, destinationBitCount, destinationStride, + destinationWidth, destinationHeight, + xSrc, ySrc, wSrc, hSrc, + pixelsSource, sourceBitCount, sourceStride, sourceWidth, sourceHeight, + rop, sourceTopDown, destinationTopDown, palPalEntry, brushColor, + backgroundColor); - if(jniEnv && hdcDest->hdcCompatible == NULL && (ret = AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen)) < 0) { - LOGD("AndroidBitmap_unlockPixels() failed ! error=%d", ret); - return FALSE; - } + if (jniEnv && hdcDest->hdcCompatible == NULL && + (ret = AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen)) < 0) { + LOGD("AndroidBitmap_unlockPixels() failed ! error=%d", ret); + return FALSE; + } - return TRUE; - } - return FALSE; + return TRUE; + } + return FALSE; } void StretchBltInternal(int xDest, int yDest, int wDest, int hDest, - const void *pixelsDestination, int destinationBitCount, int destinationStride, int destinationWidth, int destinationHeight, + const void *pixelsDestination, int destinationBitCount, + int destinationStride, int destinationWidth, int destinationHeight, int xSrc, int ySrc, int wSrc, int hSrc, - const void *pixelsSource, UINT sourceBitCount, int sourceStride, int sourceWidth, int sourceHeight, - DWORD rop, BOOL sourceTopDown, BOOL destinationTopDown, const PALETTEENTRY *palPalEntry, COLORREF brushColor, COLORREF backgroundColor) { - int dst_maxx = xDest + wDest; - int dst_maxy = yDest + hDest; + const void *pixelsSource, UINT sourceBitCount, int sourceStride, + int sourceWidth, int sourceHeight, + DWORD rop, BOOL sourceTopDown, BOOL destinationTopDown, + const PALETTEENTRY *palPalEntry, COLORREF brushColor, + COLORREF backgroundColor) { + int dst_maxx = xDest + wDest; + int dst_maxy = yDest + hDest; - if(xDest < 0) { - wDest += xDest; - xDest = 0; - } - if(yDest < 0) { - hDest += yDest; - yDest = 0; - } - if(dst_maxx > destinationWidth) - dst_maxx = destinationWidth; - if(dst_maxy > destinationHeight) - dst_maxy = destinationHeight; + if (xDest < 0) { + wDest += xDest; + xDest = 0; + } + if (yDest < 0) { + hDest += yDest; + yDest = 0; + } + if (dst_maxx > destinationWidth) + dst_maxx = destinationWidth; + if (dst_maxy > destinationHeight) + dst_maxy = destinationHeight; - int src_cury, dst_cury; - for (int y = yDest; y < dst_maxy; y++) { - if(sourceTopDown) + int src_cury, dst_cury; + for (int y = yDest; y < dst_maxy; y++) { + if (sourceTopDown) src_cury = ySrc + (y - yDest) * hSrc / hDest; // Source top-down else src_cury = sourceHeight - 1 - (ySrc + (y - yDest) * hSrc / hDest); // Source bottom-up - if (src_cury < 0 || src_cury >= sourceHeight) - continue; - if(destinationTopDown) - dst_cury = y; // Destination top-down - else - dst_cury = destinationHeight - 1 - y; // Destination bottom-up + if (src_cury < 0 || src_cury >= sourceHeight) + continue; + if (destinationTopDown) + dst_cury = y; // Destination top-down + else + dst_cury = destinationHeight - 1 - y; // Destination bottom-up - BYTE parity = (BYTE) xSrc; - for (int x = xDest; x < dst_maxx; x++, parity++) { - int src_curx = xSrc + (x - xDest) * wSrc / wDest; - if (src_curx < 0 || src_curx >= sourceWidth) - continue; + BYTE parity = (BYTE) xSrc; + for (int x = xDest; x < dst_maxx; x++, parity++) { + int src_curx = xSrc + (x - xDest) * wSrc / wDest; + if (src_curx < 0 || src_curx >= sourceWidth) + continue; - BYTE * sourcePixelBase = pixelsSource + sourceStride * src_cury; - BYTE * destinationPixelBase = pixelsDestination + destinationStride * dst_cury; + BYTE *sourcePixelBase = pixelsSource + sourceStride * src_cury; + BYTE *destinationPixelBase = pixelsDestination + destinationStride * dst_cury; - COLORREF sourceColor = 0xFF000000; - BYTE * sourceColorPointer = (BYTE *) &sourceColor; + COLORREF sourceColor = 0xFF000000; + BYTE *sourceColorPointer = (BYTE *) &sourceColor; - switch (sourceBitCount) { - case 1: { - //TODO https://devblogs.microsoft.com/oldnewthing/?p=29013 - // When blitting from a monochrome DC to a color DC, - // the color black in the source turns into the destination’s text color, - // and the color white in the source turns into the destination’s background - // color. - BYTE * sourcePixel = sourcePixelBase + ((UINT)src_curx >> (UINT)3); - UINT bitNumber = (UINT) (7 - (src_curx % 8)); - if(*sourcePixel & ((UINT)1 << bitNumber)) { - // Monochrome 1=White - sourceColorPointer[0] = 255; - sourceColorPointer[1] = 255; - sourceColorPointer[2] = 255; - } else { - // Monochrome 0=Black - sourceColorPointer[0] = 0; - sourceColorPointer[1] = 0; - sourceColorPointer[2] = 0; - } - sourceColorPointer[3] = 255; - break; - } - case 4: { - int currentXBytes = ((sourceBitCount >> (UINT)2) * src_curx) >> (UINT)1; - BYTE * sourcePixel = sourcePixelBase + currentXBytes; - BYTE colorIndex = (parity & (BYTE)0x1 ? sourcePixel[0] & (BYTE)0x0F : sourcePixel[0] >> (UINT)4); - if (palPalEntry) { - sourceColorPointer[0] = palPalEntry[colorIndex].peBlue; - sourceColorPointer[1] = palPalEntry[colorIndex].peGreen; - sourceColorPointer[2] = palPalEntry[colorIndex].peRed; - sourceColorPointer[3] = 255; - } else { - sourceColorPointer[0] = colorIndex; - sourceColorPointer[1] = colorIndex; - sourceColorPointer[2] = colorIndex; - sourceColorPointer[3] = 255; - } - break; - } - case 8: { - BYTE * sourcePixel = sourcePixelBase + src_curx; - BYTE colorIndex = sourcePixel[0]; - if (palPalEntry) { - sourceColorPointer[0] = palPalEntry[colorIndex].peBlue; - sourceColorPointer[1] = palPalEntry[colorIndex].peGreen; - sourceColorPointer[2] = palPalEntry[colorIndex].peRed; - sourceColorPointer[3] = 255; - } else { - sourceColorPointer[0] = colorIndex; - sourceColorPointer[1] = colorIndex; - sourceColorPointer[2] = colorIndex; - sourceColorPointer[3] = 255; - } - break; - } - case 24: { - BYTE * sourcePixel = sourcePixelBase + 3 * src_curx; - sourceColorPointer[0] = sourcePixel[2]; - sourceColorPointer[1] = sourcePixel[1]; - sourceColorPointer[2] = sourcePixel[0]; - sourceColorPointer[3] = 255; - break; - } - case 32: { - BYTE *sourcePixel = sourcePixelBase + 4 * src_curx; - memcpy(sourceColorPointer, sourcePixel, 4); - break; - } - default: - break; - } + switch (sourceBitCount) { + case 1: { + //TODO https://devblogs.microsoft.com/oldnewthing/?p=29013 + // When blitting from a monochrome DC to a color DC, + // the color black in the source turns into the destination’s text color, + // and the color white in the source turns into the destination’s background + // color. + BYTE *sourcePixel = sourcePixelBase + ((UINT) src_curx >> (UINT) 3); + UINT bitNumber = (UINT) (7 - (src_curx % 8)); + if (*sourcePixel & ((UINT) 1 << bitNumber)) { + // Monochrome 1=White + sourceColorPointer[0] = 255; + sourceColorPointer[1] = 255; + sourceColorPointer[2] = 255; + } else { + // Monochrome 0=Black + sourceColorPointer[0] = 0; + sourceColorPointer[1] = 0; + sourceColorPointer[2] = 0; + } + sourceColorPointer[3] = 255; + break; + } + case 4: { + int currentXBytes = ((sourceBitCount >> (UINT) 2) * src_curx) >> (UINT) 1; + BYTE *sourcePixel = sourcePixelBase + currentXBytes; + BYTE colorIndex = (parity & (BYTE) 0x1 ? sourcePixel[0] & (BYTE) 0x0F : + sourcePixel[0] >> (UINT) 4); + if (palPalEntry) { + sourceColorPointer[0] = palPalEntry[colorIndex].peBlue; + sourceColorPointer[1] = palPalEntry[colorIndex].peGreen; + sourceColorPointer[2] = palPalEntry[colorIndex].peRed; + sourceColorPointer[3] = 255; + } else { + sourceColorPointer[0] = colorIndex; + sourceColorPointer[1] = colorIndex; + sourceColorPointer[2] = colorIndex; + sourceColorPointer[3] = 255; + } + break; + } + case 8: { + BYTE *sourcePixel = sourcePixelBase + src_curx; + BYTE colorIndex = sourcePixel[0]; + if (palPalEntry) { + sourceColorPointer[0] = palPalEntry[colorIndex].peBlue; + sourceColorPointer[1] = palPalEntry[colorIndex].peGreen; + sourceColorPointer[2] = palPalEntry[colorIndex].peRed; + sourceColorPointer[3] = 255; + } else { + sourceColorPointer[0] = colorIndex; + sourceColorPointer[1] = colorIndex; + sourceColorPointer[2] = colorIndex; + sourceColorPointer[3] = 255; + } + break; + } + case 24: { + BYTE *sourcePixel = sourcePixelBase + 3 * src_curx; + sourceColorPointer[0] = sourcePixel[2]; + sourceColorPointer[1] = sourcePixel[1]; + sourceColorPointer[2] = sourcePixel[0]; + sourceColorPointer[3] = 255; + break; + } + case 32: { + BYTE *sourcePixel = sourcePixelBase + 4 * src_curx; + memcpy(sourceColorPointer, sourcePixel, 4); + break; + } + default: + break; + } - switch (destinationBitCount) { - case 1: { - //TODO https://devblogs.microsoft.com/oldnewthing/?p=29013 - // If you blit from a color DC to a monochrome DC, - // then all pixels in the source that are equal to the background color - // will turn white, and all other pixels will turn black. - // In other words, GDI considers a monochrome bitmap to be - // black pixels on a white background. - BYTE * destinationPixel = destinationPixelBase + (x >> 3); - UINT bitNumber = (UINT) (7 - (x % 8)); - if((backgroundColor & 0xFFFFFF) == (sourceColor & 0xFFFFFF)) { - *destinationPixel |= (1 << bitNumber); // 1 White - } else { - *destinationPixel &= ~(1 << bitNumber); // 0 Black - } - break; - } - case 4: { - //TODO - break; - } - case 8: { - //TODO - break; - } - case 24: { - BYTE * destinationPixel = destinationPixelBase + 3 * x; - destinationPixel[0] = sourceColorPointer[0]; - destinationPixel[1] = sourceColorPointer[1]; - destinationPixel[2] = sourceColorPointer[2]; - break; - } - case 32: { - BYTE * destinationPixel = destinationPixelBase + 4 * x; - // https://docs.microsoft.com/en-us/windows/desktop/gdi/ternary-raster-operations - // http://www.qnx.com/developers/docs/6.4.1/gf/dev_guide/api/gf_context_set_rop.html - if (rop == ROP_PDSPxax) { // P ^ (D & (S ^ P)) - UINT destination = *((UINT *) destinationPixel); - *((UINT *)destinationPixel) = (brushColor ^ (destination & (sourceColor ^ brushColor))) | 0xFF000000; - } else if (rop == ROP_PSDPxax) { // P ^ (S & (D ^ P)) - UINT destination = *((UINT *) destinationPixel); - *((UINT *)destinationPixel) = (brushColor ^ (sourceColor & (destination ^ brushColor))) | 0xFF000000; - } else if (rop == SRCAND) { // dest = source AND dest - UINT destination = *((UINT *) destinationPixel); - *((UINT *)destinationPixel) = (sourceColor & destination) | 0xFF000000; - } else - *((UINT *)destinationPixel) = sourceColor; - break; - } - default: - break; - } - } - } + switch (destinationBitCount) { + case 1: { + //TODO https://devblogs.microsoft.com/oldnewthing/?p=29013 + // If you blit from a color DC to a monochrome DC, + // then all pixels in the source that are equal to the background color + // will turn white, and all other pixels will turn black. + // In other words, GDI considers a monochrome bitmap to be + // black pixels on a white background. + BYTE *destinationPixel = destinationPixelBase + (x >> 3); + UINT bitNumber = (UINT) (7 - (x % 8)); + if ((backgroundColor & 0xFFFFFF) == (sourceColor & 0xFFFFFF)) { + *destinationPixel |= (1 << bitNumber); // 1 White + } else { + *destinationPixel &= ~(1 << bitNumber); // 0 Black + } + break; + } + case 4: { + //TODO + break; + } + case 8: { + //TODO + break; + } + case 24: { + BYTE *destinationPixel = destinationPixelBase + 3 * x; + destinationPixel[0] = sourceColorPointer[0]; + destinationPixel[1] = sourceColorPointer[1]; + destinationPixel[2] = sourceColorPointer[2]; + break; + } + case 32: { + BYTE *destinationPixel = destinationPixelBase + 4 * x; + // https://docs.microsoft.com/en-us/windows/desktop/gdi/ternary-raster-operations + // http://www.qnx.com/developers/docs/6.4.1/gf/dev_guide/api/gf_context_set_rop.html + if (rop == ROP_PDSPxax) { // P ^ (D & (S ^ P)) + UINT destination = *((UINT *) destinationPixel); + *((UINT *) destinationPixel) = + (brushColor ^ (destination & (sourceColor ^ brushColor))) | + 0xFF000000; + } else if (rop == ROP_PSDPxax) { // P ^ (S & (D ^ P)) + UINT destination = *((UINT *) destinationPixel); + *((UINT *) destinationPixel) = + (brushColor ^ (sourceColor & (destination ^ brushColor))) | + 0xFF000000; + } else if (rop == SRCAND) { // dest = source AND dest + UINT destination = *((UINT *) destinationPixel); + *((UINT *) destinationPixel) = (sourceColor & destination) | 0xFF000000; + } else + *((UINT *) destinationPixel) = sourceColor; + break; + } + default: + break; + } + } + } } -UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq) { - if(prgbq - && hdc && hdc->realizedPalette && hdc->realizedPalette->paletteLog && hdc->realizedPalette->paletteLog->palPalEntry - && hdc->realizedPalette->paletteLog->palNumEntries > 0 && iStart < hdc->realizedPalette->paletteLog->palNumEntries) { - PALETTEENTRY * palPalEntry = hdc->realizedPalette->paletteLog->palPalEntry; - for (int i = iStart, j = 0; i < cEntries; i++, j++) { - palPalEntry[i].peRed = prgbq[j].rgbRed; - palPalEntry[i].peGreen = prgbq[j].rgbGreen; - palPalEntry[i].peBlue = prgbq[j].rgbBlue; - palPalEntry[i].peFlags = 0; - } - } - return 0; +UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq) { + if (prgbq + && hdc && hdc->realizedPalette && hdc->realizedPalette->paletteLog && + hdc->realizedPalette->paletteLog->palPalEntry + && hdc->realizedPalette->paletteLog->palNumEntries > 0 && + iStart < hdc->realizedPalette->paletteLog->palNumEntries) { + PALETTEENTRY *palPalEntry = hdc->realizedPalette->paletteLog->palPalEntry; + for (int i = iStart, j = 0; i < cEntries; i++, j++) { + palPalEntry[i].peRed = prgbq[j].rgbRed; + palPalEntry[i].peGreen = prgbq[j].rgbGreen; + palPalEntry[i].peBlue = prgbq[j].rgbBlue; + palPalEntry[i].peFlags = 0; + } + } + return 0; } -HBITMAP CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits) { - PAINT_LOGD("PAINT CreateBitmap()"); - HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); - memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); - newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; +HBITMAP CreateBitmap(int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CONST VOID *lpBits) { + PAINT_LOGD("PAINT CreateBitmap()"); - BITMAPINFO * newBitmapInfo = malloc(sizeof(BITMAPINFO)); - memset(newBitmapInfo, 0, sizeof(BITMAPINFO)); - newBitmapInfo->bmiHeader.biBitCount = (WORD) nBitCount; - newBitmapInfo->bmiHeader.biClrUsed = 0; - newBitmapInfo->bmiHeader.biWidth = nWidth; + HGDIOBJ newHBITMAP = (HGDIOBJ) malloc(sizeof(_HGDIOBJ)); + memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); + newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; + + BITMAPINFO *newBitmapInfo = malloc(sizeof(BITMAPINFO)); + memset(newBitmapInfo, 0, sizeof(BITMAPINFO)); + newBitmapInfo->bmiHeader.biBitCount = (WORD) nBitCount; + newBitmapInfo->bmiHeader.biClrUsed = 0; + newBitmapInfo->bmiHeader.biWidth = nWidth; newBitmapInfo->bmiHeader.biHeight = nHeight; - newBitmapInfo->bmiHeader.biPlanes = (WORD) nPlanes; - newHBITMAP->bitmapInfo = newBitmapInfo; - newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo; + newBitmapInfo->bmiHeader.biPlanes = (WORD) nPlanes; + newHBITMAP->bitmapInfo = newBitmapInfo; + newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *) newBitmapInfo; - size_t stride = (size_t)(4 * ((newBitmapInfo->bmiHeader.biWidth * newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); - size_t size = abs(newBitmapInfo->bmiHeader.biHeight) * stride; - newBitmapInfo->bmiHeader.biSizeImage = (DWORD) size; - VOID * bitmapBits = malloc(size); - memset(bitmapBits, 0, size); - newHBITMAP->bitmapBits = bitmapBits; - return newHBITMAP; + size_t stride = (size_t) (4 * ((newBitmapInfo->bmiHeader.biWidth * + newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); + size_t size = abs(newBitmapInfo->bmiHeader.biHeight) * stride; + newBitmapInfo->bmiHeader.biSizeImage = (DWORD) size; + VOID *bitmapBits = malloc(size); + memset(bitmapBits, 0, size); + newHBITMAP->bitmapBits = bitmapBits; + return newHBITMAP; } // RLE decode from Christoph Giesselink in FILES.C from Emu48forPocketPC v125 #define WIDTHBYTES(bits) ((((bits) + 31) / 32) * 4) -typedef struct _BmpFile -{ - DWORD dwPos; // actual reading pos - DWORD dwFileSize; // file size - LPBYTE pbyFile; // buffer +typedef struct _BmpFile { + DWORD dwPos; // actual reading pos + DWORD dwFileSize; // file size + LPBYTE pbyFile; // buffer } BMPFILE, FAR *LPBMPFILE, *PBMPFILE; -static BOOL ReadRleBmpByte(LPBMPFILE pBmp, BYTE *n) -{ +static BOOL ReadRleBmpByte(LPBMPFILE pBmp, BYTE *n) { // outside BMP file if (pBmp->dwPos >= pBmp->dwFileSize) return TRUE; @@ -2421,15 +2517,14 @@ static BOOL ReadRleBmpByte(LPBMPFILE pBmp, BYTE *n) return FALSE; } -static BOOL DecodeRleBmp(LPBYTE ppvBits,BITMAPINFOHEADER CONST *lpbi, LPBMPFILE pBmp) -{ - BYTE byLength,byColorIndex; - DWORD dwPos,dwRow,dwSizeImage,dwPixelPerLine; - BOOL bDecoding; +static BOOL DecodeRleBmp(LPBYTE ppvBits, BITMAPINFOHEADER CONST *lpbi, LPBMPFILE pBmp) { + BYTE byLength, byColorIndex; + DWORD dwPos, dwRow, dwSizeImage, dwPixelPerLine; + BOOL bDecoding; - _ASSERT(ppvBits != NULL); // destination - _ASSERT(lpbi != NULL); // BITMAPINFOHEADER - _ASSERT(pBmp != NULL); // bitmap data + _ASSERT(ppvBits != NULL); // destination + _ASSERT(lpbi != NULL); // BITMAPINFOHEADER + _ASSERT(pBmp != NULL); // bitmap data // valid bit count for RLE bitmaps _ASSERT(lpbi->biBitCount == 4 || lpbi->biBitCount == 8); @@ -2438,14 +2533,14 @@ static BOOL DecodeRleBmp(LPBYTE ppvBits,BITMAPINFOHEADER CONST *lpbi, LPBMPFILE if ((lpbi->biBitCount != 4 && lpbi->biBitCount != 8) || lpbi->biHeight < 0) return TRUE; - bDecoding = TRUE; // RLE decoder running - dwPos = dwRow = 0; // reset absolute position and row counter + bDecoding = TRUE; // RLE decoder running + dwPos = dwRow = 0; // reset absolute position and row counter // image size _ASSERT(lpbi->biHeight >= 0); - dwSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount) * lpbi->biHeight; + dwSizeImage = WIDTHBYTES((DWORD) lpbi->biWidth * lpbi->biBitCount) * lpbi->biHeight; - ZeroMemory(ppvBits,dwSizeImage); // clear bitmap + ZeroMemory(ppvBits, dwSizeImage); // clear bitmap // image size in pixel dwSizeImage *= (8 / lpbi->biBitCount); @@ -2453,54 +2548,48 @@ static BOOL DecodeRleBmp(LPBYTE ppvBits,BITMAPINFOHEADER CONST *lpbi, LPBMPFILE // no. of pixels per line dwPixelPerLine = dwSizeImage / lpbi->biHeight; - do - { + do { // length information is WORD aligned _ASSERT(((DWORD) &pBmp->pbyFile[pBmp->dwPos] % sizeof(WORD)) == 0); - if (ReadRleBmpByte(pBmp,&byLength)) return TRUE; - if (ReadRleBmpByte(pBmp,&byColorIndex)) return TRUE; + if (ReadRleBmpByte(pBmp, &byLength)) return TRUE; + if (ReadRleBmpByte(pBmp, &byColorIndex)) return TRUE; - if (byLength) // length information + if (byLength) // length information { // check for buffer overflow - if (dwPos + byLength > dwSizeImage) - { + if (dwPos + byLength > dwSizeImage) { // write rest of data until buffer full byLength = (dwPos > dwSizeImage) ? 0 : (BYTE) (dwSizeImage - dwPos); - bDecoding = FALSE; // abort + bDecoding = FALSE; // abort } - if (lpbi->biBitCount == 4) // RLE4 + if (lpbi->biBitCount == 4) // RLE4 { BYTE byColor[2]; - UINT s,d; + UINT s, d; // split into upper/lower nibble byColor[0] = byColorIndex >> 4; byColor[1] = byColorIndex & 0x0F; - s = 0; // source nibble selector [0/1] - d = (~dwPos & 1) * 4; // destination shift [0/4] + s = 0; // source nibble selector [0/1] + d = (~dwPos & 1) * 4; // destination shift [0/4] - while (byLength-- > 0) - { + while (byLength-- > 0) { // write nibble to memory _ASSERT((byColor[s] & 0xF0) == 0); - ppvBits[dwPos++/2] |= (byColor[s] << d); - s ^= 1; // next source nibble - d ^= 4; // next destination shift + ppvBits[dwPos++ / 2] |= (byColor[s] << d); + s ^= 1; // next source nibble + d ^= 4; // next destination shift } - } - else // RLE8 + } else // RLE8 { while (byLength-- > 0) ppvBits[dwPos++] = byColorIndex; } - } - else // escape sequence + } else // escape sequence { - switch (byColorIndex) - { + switch (byColorIndex) { case 0: // End of Line dwPos = ++dwRow * dwPixelPerLine; break; @@ -2509,40 +2598,37 @@ static BOOL DecodeRleBmp(LPBYTE ppvBits,BITMAPINFOHEADER CONST *lpbi, LPBMPFILE break; case 2: // Delta // column offset - if (ReadRleBmpByte(pBmp,&byColorIndex)) return TRUE; + if (ReadRleBmpByte(pBmp, &byColorIndex)) return TRUE; dwPos += byColorIndex; // row offset - if (ReadRleBmpByte(pBmp,&byColorIndex)) return TRUE; + if (ReadRleBmpByte(pBmp, &byColorIndex)) return TRUE; dwRow += byColorIndex; dwPos += dwPixelPerLine * byColorIndex; break; default: // absolute mode // check for buffer overflow - if (dwPos + byColorIndex > dwSizeImage) - { + if (dwPos + byColorIndex > dwSizeImage) { // write rest of data until buffer full byColorIndex = (dwPos > dwSizeImage) ? 0 : (BYTE) (dwSizeImage - dwPos); - bDecoding = FALSE; // abort + bDecoding = FALSE; // abort } - if (lpbi->biBitCount == 4) // RLE4 + if (lpbi->biBitCount == 4) // RLE4 { - BYTE byColor,byColorPair; - UINT s,d; + BYTE byColor, byColorPair; + UINT s, d; - d = (~dwPos & 1) * 4; // destination shift [0/4] + d = (~dwPos & 1) * 4; // destination shift [0/4] - for (s = 0; s < byColorIndex; ++s) - { - if ((s & 1) == 0) // upper nibble + for (s = 0; s < byColorIndex; ++s) { + if ((s & 1) == 0) // upper nibble { // fetch color pair - if (ReadRleBmpByte(pBmp,&byColorPair)) return TRUE; + if (ReadRleBmpByte(pBmp, &byColorPair)) return TRUE; // get upper nibble byColor = (byColorPair >> 4); - } - else // lower nibble + } else // lower nibble { // get lower nibble byColor = (byColorPair & 0x0F); @@ -2550,17 +2636,16 @@ static BOOL DecodeRleBmp(LPBYTE ppvBits,BITMAPINFOHEADER CONST *lpbi, LPBMPFILE // write nibble to memory _ASSERT((byColor & 0xF0) == 0); - ppvBits[dwPos++/2] |= (byColor << d); - d ^= 4; // next destination shift + ppvBits[dwPos++ / 2] |= (byColor << d); + d ^= 4; // next destination shift } // for odd byte length detection byColorIndex = (++byColorIndex) >> 1; - } - else // RLE8 + } else // RLE8 { if (pBmp->dwPos + byColorIndex > pBmp->dwFileSize) return TRUE; - CopyMemory(ppvBits+dwPos,&pBmp->pbyFile[pBmp->dwPos],byColorIndex); + CopyMemory(ppvBits + dwPos, &pBmp->pbyFile[pBmp->dwPos], byColorIndex); dwPos += byColorIndex; pBmp->dwPos += byColorIndex; } @@ -2569,26 +2654,26 @@ static BOOL DecodeRleBmp(LPBYTE ppvBits,BITMAPINFOHEADER CONST *lpbi, LPBMPFILE break; } } - } - while (bDecoding); + } while (bDecoding); return FALSE; } -HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CONST VOID *pjBits, CONST BITMAPINFO *pbmi, UINT iUsage) { - PAINT_LOGD("PAINT CreateDIBitmap()"); +HBITMAP CreateDIBitmap(HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CONST VOID *pjBits, + CONST BITMAPINFO *pbmi, UINT iUsage) { + PAINT_LOGD("PAINT CreateDIBitmap()"); - HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); + HGDIOBJ newHBITMAP = (HGDIOBJ) malloc(sizeof(_HGDIOBJ)); memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; - BITMAPINFO * newBitmapInfo = malloc(sizeof(BITMAPINFO)); + BITMAPINFO *newBitmapInfo = malloc(sizeof(BITMAPINFO)); memcpy(newBitmapInfo, pbmi, sizeof(BITMAPINFO)); newHBITMAP->bitmapInfo = newBitmapInfo; - newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo; + newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *) newBitmapInfo; - if(flInit == CBM_INIT && pjBits) { - VOID * bitmapBits = NULL; - if(iUsage == DIB_RGB_COLORS) { + if (flInit == CBM_INIT && pjBits) { + VOID *bitmapBits = NULL; + if (iUsage == DIB_RGB_COLORS) { switch (pbmi->bmiHeader.biCompression) { case BI_RLE4: case BI_RLE8: { @@ -2596,13 +2681,18 @@ HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CO // Destination BOOL bErr; newBitmapInfo->bmiHeader.biCompression = BI_RGB; - size_t stride = (size_t)(4 * ((newBitmapInfo->bmiHeader.biWidth * newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); + size_t stride = (size_t) (4 * ((newBitmapInfo->bmiHeader.biWidth * + newBitmapInfo->bmiHeader.biBitCount + 31) / + 32)); size_t size = abs(newBitmapInfo->bmiHeader.biHeight) * stride; bitmapBits = malloc(size); BMPFILE Bmp; - int bitOffset = sizeof(BITMAPINFOHEADER) + (pbmi->bmiHeader.biCompression == BI_BITFIELDS ? 3 * sizeof(DWORD) : DibNumColors(&pbmi->bmiHeader) * sizeof(RGBQUAD)); + int bitOffset = sizeof(BITMAPINFOHEADER) + + (pbmi->bmiHeader.biCompression == BI_BITFIELDS ? 3 * + sizeof(DWORD) : + DibNumColors(&pbmi->bmiHeader) * sizeof(RGBQUAD)); - Bmp.pbyFile = ((LPBYTE)&pbmi->bmiHeader) + bitOffset; + Bmp.pbyFile = ((LPBYTE) &pbmi->bmiHeader) + bitOffset; Bmp.dwPos = 0; Bmp.dwFileSize = -1; //size; @@ -2615,7 +2705,9 @@ HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CO case BI_RGB: case BI_BITFIELDS: { // We consider the source and destination dib with the same format - size_t stride = (size_t)(4 * ((newBitmapInfo->bmiHeader.biWidth * newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); + size_t stride = (size_t) (4 * ((newBitmapInfo->bmiHeader.biWidth * + newBitmapInfo->bmiHeader.biBitCount + 31) / + 32)); size_t size = newBitmapInfo->bmiHeader.biSizeImage ? newBitmapInfo->bmiHeader.biSizeImage : abs(newBitmapInfo->bmiHeader.biHeight) * stride; @@ -2629,165 +2721,182 @@ HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CO } return newHBITMAP; } -HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) { - PAINT_LOGD("PAINT CreateDIBSection()"); - HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); - memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); - newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; +HBITMAP +CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, + DWORD offset) { + PAINT_LOGD("PAINT CreateDIBSection()"); - size_t bitmapInfoSize = sizeof(BITMAPINFO); - if(pbmi->bmiHeader.biClrUsed > 0) - bitmapInfoSize += sizeof(RGBQUAD) * min(pbmi->bmiHeader.biClrUsed, 2^16); - BITMAPINFO * newBitmapInfo = malloc(bitmapInfoSize); - memcpy(newBitmapInfo, pbmi, bitmapInfoSize); - newHBITMAP->bitmapInfo = newBitmapInfo; - newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo; + HGDIOBJ newHBITMAP = (HGDIOBJ) malloc(sizeof(_HGDIOBJ)); + memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); + newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; - // For DIB_RGB_COLORS only - size_t stride = (size_t)(4 * ((newBitmapInfo->bmiHeader.biWidth * newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); - size_t size = newBitmapInfo->bmiHeader.biSizeImage ? - newBitmapInfo->bmiHeader.biSizeImage : - abs(newBitmapInfo->bmiHeader.biHeight) * stride; - newHBITMAP->bitmapBits = malloc(size); + size_t bitmapInfoSize = sizeof(BITMAPINFO); + if (pbmi->bmiHeader.biClrUsed > 0) + bitmapInfoSize += sizeof(RGBQUAD) * min(pbmi->bmiHeader.biClrUsed, 2 ^ 16); + BITMAPINFO *newBitmapInfo = malloc(bitmapInfoSize); + memcpy(newBitmapInfo, pbmi, bitmapInfoSize); + newHBITMAP->bitmapInfo = newBitmapInfo; + newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *) newBitmapInfo; - memset((void *) newHBITMAP->bitmapBits, 0, size); - *ppvBits = (void *) newHBITMAP->bitmapBits; - return newHBITMAP; + // For DIB_RGB_COLORS only + size_t stride = (size_t) (4 * ((newBitmapInfo->bmiHeader.biWidth * + newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); + size_t size = newBitmapInfo->bmiHeader.biSizeImage ? + newBitmapInfo->bmiHeader.biSizeImage : + abs(newBitmapInfo->bmiHeader.biHeight) * stride; + newHBITMAP->bitmapBits = malloc(size); + + memset((void *) newHBITMAP->bitmapBits, 0, size); + *ppvBits = (void *) newHBITMAP->bitmapBits; + return newHBITMAP; } -HBITMAP CreateCompatibleBitmap( HDC hdc, int cx, int cy) { - PAINT_LOGD("PAINT CreateCompatibleBitmap()"); - HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); - memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); - newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; +HBITMAP CreateCompatibleBitmap(HDC hdc, int cx, int cy) { + PAINT_LOGD("PAINT CreateCompatibleBitmap()"); - BITMAPINFO * newBitmapInfo = malloc(sizeof(BITMAPINFO)); - memset(newBitmapInfo, 0, sizeof(BITMAPINFO)); - newHBITMAP->bitmapInfo = newBitmapInfo; - newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo; + HGDIOBJ newHBITMAP = (HGDIOBJ) malloc(sizeof(_HGDIOBJ)); + memset(newHBITMAP, 0, sizeof(_HGDIOBJ)); + newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP; - newBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); - newBitmapInfo->bmiHeader.biWidth = cx; - newBitmapInfo->bmiHeader.biHeight = cy; - newBitmapInfo->bmiHeader.biBitCount = 32; + BITMAPINFO *newBitmapInfo = malloc(sizeof(BITMAPINFO)); + memset(newBitmapInfo, 0, sizeof(BITMAPINFO)); + newHBITMAP->bitmapInfo = newBitmapInfo; + newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *) newBitmapInfo; - size_t stride = (size_t)(4 * ((newBitmapInfo->bmiHeader.biWidth * newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); - size_t size = abs(newBitmapInfo->bmiHeader.biHeight) * stride; - newBitmapInfo->bmiHeader.biSizeImage = (DWORD) size; - newHBITMAP->bitmapBits = malloc(size); - memset((void *) newHBITMAP->bitmapBits, 0, size); - return newHBITMAP; + newBitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + newBitmapInfo->bmiHeader.biWidth = cx; + newBitmapInfo->bmiHeader.biHeight = cy; + newBitmapInfo->bmiHeader.biBitCount = 32; + + size_t stride = (size_t) (4 * ((newBitmapInfo->bmiHeader.biWidth * + newBitmapInfo->bmiHeader.biBitCount + 31) / 32)); + size_t size = abs(newBitmapInfo->bmiHeader.biHeight) * stride; + newBitmapInfo->bmiHeader.biSizeImage = (DWORD) size; + newHBITMAP->bitmapBits = malloc(size); + memset((void *) newHBITMAP->bitmapBits, 0, size); + return newHBITMAP; } -int GetDIBits(HDC hdc, HBITMAP hbm, UINT start, UINT cLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT usage) { + +int GetDIBits(HDC hdc, HBITMAP hbm, UINT start, UINT cLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, + UINT usage) { PAINT_LOGD("PAINT GetDIBits()"); - //TODO Not sure at all for this function - if(hbm && lpbmi) { - CONST BITMAPINFO *pbmi = hbm->bitmapInfo; - if(!lpvBits) { - size_t bitmapInfoSize = sizeof(BITMAPINFOHEADER); - memcpy(lpbmi, pbmi, bitmapInfoSize); - } else { - // We consider the source and destination dib with the same format - size_t stride = (size_t)(4 * ((pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount + 31) / 32)); - VOID * sourceDibBits = (VOID *)hbm->bitmapBits; - VOID * destinationDibBits = lpvBits; - for(int y = 0; y < cLines; y++) { - size_t lineSize = (start + y) * stride; - memcpy(destinationDibBits + lineSize, sourceDibBits + lineSize, stride); - } - } - } - return 0; + //TODO Not sure at all for this function + if (hbm && lpbmi) { + CONST BITMAPINFO *pbmi = hbm->bitmapInfo; + if (!lpvBits) { + size_t bitmapInfoSize = sizeof(BITMAPINFOHEADER); + memcpy(lpbmi, pbmi, bitmapInfoSize); + } else { + // We consider the source and destination dib with the same format + size_t stride = (size_t) (4 * + ((pbmi->bmiHeader.biWidth * pbmi->bmiHeader.biBitCount + 31) / + 32)); + VOID *sourceDibBits = (VOID *) hbm->bitmapBits; + VOID *destinationDibBits = lpvBits; + for (int y = 0; y < cLines; y++) { + size_t lineSize = (start + y) * stride; + memcpy(destinationDibBits + lineSize, sourceDibBits + lineSize, stride); + } + } + } + return 0; } -COLORREF GetPixel(HDC hdc, int x ,int y) { - HBITMAP hBitmapSource = hdc->selectedBitmap; - void * pixelsSource = (void *) hBitmapSource->bitmapBits; - BOOL reverseHeight = hBitmapSource->bitmapInfoHeader->biHeight < 0; +COLORREF GetPixel(HDC hdc, int x, int y) { + HBITMAP hBitmapSource = hdc->selectedBitmap; + void *pixelsSource = (void *) hBitmapSource->bitmapBits; - int sourceWidth = hBitmapSource->bitmapInfoHeader->biWidth; - int sourceHeight = abs(hBitmapSource->bitmapInfoHeader->biHeight); // Can be < 0 + BOOL reverseHeight = hBitmapSource->bitmapInfoHeader->biHeight < 0; - int sourceBitCount = hBitmapSource->bitmapInfoHeader->biBitCount; - int sourceStride = 4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32); + int sourceWidth = hBitmapSource->bitmapInfoHeader->biWidth; + int sourceHeight = abs(hBitmapSource->bitmapInfoHeader->biHeight); // Can be < 0 - x -= hdc->windowOriginX; - y -= hdc->windowOriginY; + int sourceBitCount = hBitmapSource->bitmapInfoHeader->biBitCount; + int sourceStride = 4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32); - if(!reverseHeight) - y = sourceHeight - 1 - y; + x -= hdc->windowOriginX; + y -= hdc->windowOriginY; - HPALETTE palette = hdc->realizedPalette; - if(!palette) - palette = hdc->selectedPalette; - PALETTEENTRY * palPalEntry = palette && palette->paletteLog && palette->paletteLog->palPalEntry ? - palette->paletteLog->palPalEntry : NULL; - if(!palPalEntry && sourceBitCount <= 8 && hBitmapSource->bitmapInfoHeader->biClrUsed > 0) { - palPalEntry = (PALETTEENTRY *)hBitmapSource->bitmapInfo->bmiColors; - } - COLORREF resultColor = CLR_INVALID; // 0xAABBGGRR + if (!reverseHeight) + y = sourceHeight - 1 - y; - if(x >= 0 && y >= 0 && x < sourceWidth && y < sourceHeight) { - BYTE * sourcePixel = pixelsSource + sourceStride * y; + HPALETTE palette = hdc->realizedPalette; + if (!palette) + palette = hdc->selectedPalette; + PALETTEENTRY *palPalEntry = palette && palette->paletteLog && palette->paletteLog->palPalEntry ? + palette->paletteLog->palPalEntry : NULL; + if (!palPalEntry && sourceBitCount <= 8 && hBitmapSource->bitmapInfoHeader->biClrUsed > 0) { + palPalEntry = (PALETTEENTRY *) hBitmapSource->bitmapInfo->bmiColors; + } + COLORREF resultColor = CLR_INVALID; // 0xAABBGGRR - // -> ARGB_8888 - switch (sourceBitCount) { - case 1: - //TODO - break; - case 4: { - sourcePixel += x >> 2; - BYTE colorIndex = (x & 0x1 ? sourcePixel[0] & (BYTE)0x0F : sourcePixel[0] >> 4); - if (palPalEntry) { - resultColor = 0xFF000000 | RGB(palPalEntry[colorIndex].peRed, palPalEntry[colorIndex].peGreen, palPalEntry[colorIndex].peBlue); - } else { - resultColor = 0xFF000000 | RGB(colorIndex, colorIndex, colorIndex); - } - break; - } - case 8: { - sourcePixel += x; - BYTE colorIndex = sourcePixel[0]; - if (palPalEntry) { - resultColor = 0xFF000000 | RGB(palPalEntry[colorIndex].peRed, palPalEntry[colorIndex].peGreen, palPalEntry[colorIndex].peBlue); - } else { - resultColor = 0xFF000000 | RGB(sourcePixel[0], sourcePixel[0], sourcePixel[0]); - } - break; - } - case 24: - sourcePixel += 3 * x; - resultColor = 0xFF000000 | RGB(sourcePixel[2], sourcePixel[1], sourcePixel[0]); - break; - case 32: - sourcePixel += 4 * x; - resultColor = 0xFF000000 | RGB(sourcePixel[2], sourcePixel[1], sourcePixel[0]); - break; - default: - break; - } - } + if (x >= 0 && y >= 0 && x < sourceWidth && y < sourceHeight) { + BYTE *sourcePixel = pixelsSource + sourceStride * y; - return resultColor; + // -> ARGB_8888 + switch (sourceBitCount) { + case 1: + //TODO + break; + case 4: { + sourcePixel += x >> 2; + BYTE colorIndex = (x & 0x1 ? sourcePixel[0] & (BYTE) 0x0F : sourcePixel[0] >> 4); + if (palPalEntry) { + resultColor = 0xFF000000 | RGB(palPalEntry[colorIndex].peRed, + palPalEntry[colorIndex].peGreen, + palPalEntry[colorIndex].peBlue); + } else { + resultColor = 0xFF000000 | RGB(colorIndex, colorIndex, colorIndex); + } + break; + } + case 8: { + sourcePixel += x; + BYTE colorIndex = sourcePixel[0]; + if (palPalEntry) { + resultColor = 0xFF000000 | RGB(palPalEntry[colorIndex].peRed, + palPalEntry[colorIndex].peGreen, + palPalEntry[colorIndex].peBlue); + } else { + resultColor = 0xFF000000 | RGB(sourcePixel[0], sourcePixel[0], sourcePixel[0]); + } + break; + } + case 24: + sourcePixel += 3 * x; + resultColor = 0xFF000000 | RGB(sourcePixel[2], sourcePixel[1], sourcePixel[0]); + break; + case 32: + sourcePixel += 4 * x; + resultColor = 0xFF000000 | RGB(sourcePixel[2], sourcePixel[1], sourcePixel[0]); + break; + default: + break; + } + } + + return resultColor; } + BOOL SetRect(LPRECT lprc, int xLeft, int yTop, int xRight, int yBottom) { if (!lprc) return FALSE; - lprc->left = xLeft; - lprc->right = xRight; - lprc->top = yTop; + lprc->left = xLeft; + lprc->right = xRight; + lprc->top = yTop; lprc->bottom = yBottom; return TRUE; } + BOOL SetRectEmpty(LPRECT lprc) { - if(lprc) { - lprc->top = 0; - lprc->bottom = 0; - lprc->left = 0; - lprc->right = 0; - return TRUE; - } - return FALSE; + if (lprc) { + lprc->top = 0; + lprc->bottom = 0; + lprc->left = 0; + lprc->right = 0; + return TRUE; + } + return FALSE; } BOOL IsRectEmpty(CONST RECT *lprc) { @@ -2799,108 +2908,108 @@ BOOL IsRectEmpty(CONST RECT *lprc) { // This comes from Wine source code BOOL UnionRect(LPRECT dest, CONST RECT *src1, CONST RECT *src2) { if (!dest) return FALSE; - if (IsRectEmpty(src1)) - { - if (IsRectEmpty(src2)) - { - SetRectEmpty( dest ); + if (IsRectEmpty(src1)) { + if (IsRectEmpty(src2)) { + SetRectEmpty(dest); return FALSE; - } - else *dest = *src2; - } - else - { + } else *dest = *src2; + } else { if (IsRectEmpty(src2)) *dest = *src1; - else - { - dest->left = min( src1->left, src2->left ); - dest->right = max( src1->right, src2->right ); - dest->top = min( src1->top, src2->top ); - dest->bottom = max( src1->bottom, src2->bottom ); + else { + dest->left = min(src1->left, src2->left); + dest->right = max(src1->right, src2->right); + dest->top = min(src1->top, src2->top); + dest->bottom = max(src1->bottom, src2->bottom); } } return TRUE; } + int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw) { - //TODO - return 0; + //TODO + return 0; } -HRGN ExtCreateRegion(CONST XFORM * lpx, DWORD nCount, CONST RGNDATA * lpData) { - //TODO - return NULL; + +HRGN ExtCreateRegion(CONST XFORM *lpx, DWORD nCount, CONST RGNDATA *lpData) { + //TODO + return NULL; } + BOOL GdiFlush(void) { - mainViewUpdateCallback(); - return 0; + mainViewUpdateCallback(); + return 0; } + HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) { - if(lpPaint) { - memset(lpPaint, 0, sizeof(PAINTSTRUCT)); - lpPaint->fErase = TRUE; - lpPaint->hdc = CreateCompatibleDC(NULL); //hWnd->windowDC); - lpPaint->rcPaint.right = (short) nBackgroundW; - lpPaint->rcPaint.bottom = (short) nBackgroundH; - return lpPaint->hdc; - } - return NULL; + if (lpPaint) { + memset(lpPaint, 0, sizeof(PAINTSTRUCT)); + lpPaint->fErase = TRUE; + lpPaint->hdc = CreateCompatibleDC(NULL); //hWnd->windowDC); + lpPaint->rcPaint.right = (short) nBackgroundW; + lpPaint->rcPaint.bottom = (short) nBackgroundH; + return lpPaint->hdc; + } + return NULL; } + BOOL EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint) { - //mainViewUpdateCallback(); //TODO May be not needed - DeleteDC(lpPaint->hdc); - return 0; + //mainViewUpdateCallback(); //TODO May be not needed + DeleteDC(lpPaint->hdc); + return 0; } // Window BOOL WINAPI MessageBeep(UINT uType) { - //TODO System beep - return 1; + //TODO System beep + return 1; } BOOL WINAPI OpenClipboard(HWND hWndNewOwner) { - return TRUE; + return TRUE; } + BOOL WINAPI CloseClipboard(VOID) { - //TODO - return 0; + //TODO + return 0; } BOOL WINAPI EmptyClipboard(VOID) { - return TRUE; + return TRUE; } -HANDLE WINAPI SetClipboardData(UINT uFormat,HANDLE hMem) { - if(CF_TEXT) { - clipboardCopyText((const TCHAR *)hMem); - } - GlobalFree(hMem); - return NULL; +HANDLE WINAPI SetClipboardData(UINT uFormat, HANDLE hMem) { + if (CF_TEXT) { + clipboardCopyText((const TCHAR *) hMem); + } + GlobalFree(hMem); + return NULL; } BOOL WINAPI IsClipboardFormatAvailable(UINT format) { - TCHAR * szText = clipboardPasteText(); - BOOL result = szText != NULL; - GlobalFree(szText); - return result; + TCHAR *szText = clipboardPasteText(); + BOOL result = szText != NULL; + GlobalFree(szText); + return result; } HANDLE WINAPI GetClipboardData(UINT uFormat) { - TCHAR * szText = clipboardPasteText(); - return szText; + TCHAR *szText = clipboardPasteText(); + return szText; } struct timerEvent { - int timerId; - UINT uDelay; - UINT uResolution; - LPTIMECALLBACK fptc; - DWORD_PTR dwUser; - UINT fuEvent; + int timerId; + UINT uDelay; + UINT uResolution; + LPTIMECALLBACK fptc; + DWORD_PTR dwUser; + UINT fuEvent; - ULONGLONG triggerTime; + ULONGLONG triggerTime; - struct timerEvent * next; - struct timerEvent * prev; + struct timerEvent *next; + struct timerEvent *prev; }; static struct timerEvent timersList; static int lastTimerId; @@ -2909,66 +3018,68 @@ static pthread_t timerThreadId; static BOOL timerThreadToEnd; static void initTimer() { - timersList.next = &timersList; - timersList.prev = &timersList; - timerThreadId = 0; - timerThreadToEnd = TRUE; - lastTimerId = 0; + timersList.next = &timersList; + timersList.prev = &timersList; + timerThreadId = 0; + timerThreadToEnd = TRUE; + lastTimerId = 0; } static void dumpTimers() { TIMER_LOGD("dumpTimers()"); - for (struct timerEvent * nextTimer = timersList.next; nextTimer != &timersList; nextTimer = nextTimer->next) { + for (struct timerEvent *nextTimer = timersList.next; + nextTimer != &timersList; nextTimer = nextTimer->next) { TIMER_LOGD("\ttimerId: %d (%x), uDelay: %d, dwUser: %d, fuEvent: %d, triggerTime: %ld)", - nextTimer->timerId, nextTimer, nextTimer->uDelay, nextTimer->dwUser, nextTimer->fuEvent, nextTimer->triggerTime); + nextTimer->timerId, nextTimer, nextTimer->uDelay, nextTimer->dwUser, + nextTimer->fuEvent, nextTimer->triggerTime); } } MMRESULT timeKillEvent(UINT uTimerID) { - TIMER_LOGD("timeKillEvent(uTimerID: [%d])", uTimerID); + TIMER_LOGD("timeKillEvent(uTimerID: [%d])", uTimerID); - pthread_mutex_lock(&timerEventsLock); + pthread_mutex_lock(&timerEventsLock); - struct timerEvent * nextTimer, * timerToFree = NULL; - // Search the timer by id - for (nextTimer = timersList.next; nextTimer != &timersList; nextTimer = nextTimer->next) { - if(uTimerID == nextTimer->timerId) { - // Remove the timer - nextTimer->next->prev = nextTimer->prev; - nextTimer->prev->next = nextTimer->next; - timerToFree = nextTimer; - break; - } - } + struct timerEvent *nextTimer, *timerToFree = NULL; + // Search the timer by id + for (nextTimer = timersList.next; nextTimer != &timersList; nextTimer = nextTimer->next) { + if (uTimerID == nextTimer->timerId) { + // Remove the timer + nextTimer->next->prev = nextTimer->prev; + nextTimer->prev->next = nextTimer->next; + timerToFree = nextTimer; + break; + } + } #if defined(TIMER_LOGD) dumpTimers(); #endif - if(timersList.next == &timersList) { - // The list is empty - // Leave the thread? - timerThreadToEnd = TRUE; - TIMER_LOGD("timeKillEvent(uTimerID: [%d]) timerThreadToEnd = TRUE ", uTimerID); - } - pthread_mutex_unlock(&timerEventsLock); + if (timersList.next == &timersList) { + // The list is empty + // Leave the thread? + timerThreadToEnd = TRUE; + TIMER_LOGD("timeKillEvent(uTimerID: [%d]) timerThreadToEnd = TRUE ", uTimerID); + } + pthread_mutex_unlock(&timerEventsLock); - if(timerToFree) - free(timerToFree); + if (timerToFree) + free(timerToFree); - return 0; //No error + return 0; //No error } -static void insertTimer(struct timerEvent * newTimer) { - struct timerEvent * nextTimer; - // Search where to insert this new timer - for (nextTimer = timersList.next; nextTimer != &timersList; nextTimer = nextTimer->next) { - if(newTimer->triggerTime < nextTimer->triggerTime) - break; - } - // Insert this new timer - newTimer->next = nextTimer; - newTimer->prev = nextTimer->prev; - nextTimer->prev->next = newTimer; - nextTimer->prev = newTimer; +static void insertTimer(struct timerEvent *newTimer) { + struct timerEvent *nextTimer; + // Search where to insert this new timer + for (nextTimer = timersList.next; nextTimer != &timersList; nextTimer = nextTimer->next) { + if (newTimer->triggerTime < nextTimer->triggerTime) + break; + } + // Insert this new timer + newTimer->next = nextTimer; + newTimer->prev = nextTimer->prev; + nextTimer->prev->next = newTimer; + nextTimer->prev = newTimer; #if defined(TIMER_LOGD) dumpTimers(); @@ -2978,518 +3089,559 @@ static void insertTimer(struct timerEvent * newTimer) { static void timerThreadStart(LPVOID lpThreadParameter) { TIMER_LOGD("timerThreadStart() START"); pthread_mutex_lock(&timerEventsLock); - while (!timerThreadToEnd) { - TIMER_LOGD("timerThreadStart() %ld", GetTickCount64()); + while (!timerThreadToEnd) { + TIMER_LOGD("timerThreadStart() %ld", GetTickCount64()); - int sleep_time; - for (;;) { - struct timerEvent *timer = (timersList.next == &timersList ? NULL : timersList.next); - if (!timer) { - sleep_time = -1; - break; - } + int sleep_time; + for (;;) { + struct timerEvent *timer = (timersList.next == &timersList ? NULL : timersList.next); + if (!timer) { + sleep_time = -1; + break; + } - sleep_time = timer->triggerTime - GetTickCount64(); - if (sleep_time > 0) - break; + sleep_time = timer->triggerTime - GetTickCount64(); + if (sleep_time > 0) + break; - // Remove this timer from the linked list - timer->next->prev = timer->prev; - timer->prev->next = timer->next; + // Remove this timer from the linked list + timer->next->prev = timer->prev; + timer->prev->next = timer->next; - struct timerEvent *timerToFree; - if(timer->fuEvent == TIME_PERIODIC) { - timer->triggerTime += timer->uDelay; - /* Re-insert the timer */ - insertTimer(timer); - timerToFree = NULL; - } else - timerToFree = timer; + struct timerEvent *timerToFree; + if (timer->fuEvent == TIME_PERIODIC) { + timer->triggerTime += timer->uDelay; + /* Re-insert the timer */ + insertTimer(timer); + timerToFree = NULL; + } else + timerToFree = timer; - // Copy the timer data because we unlock the mutex! - int timerId = timer->timerId; - LPTIMECALLBACK fptc = timer->fptc; - DWORD_PTR dwUser = timer->dwUser; + // Copy the timer data because we unlock the mutex! + int timerId = timer->timerId; + LPTIMECALLBACK fptc = timer->fptc; + DWORD_PTR dwUser = timer->dwUser; - pthread_mutex_unlock(&timerEventsLock); + pthread_mutex_unlock(&timerEventsLock); - // Call the timer callback now! - fptc((UINT)timerId, 0, (DWORD) dwUser, 0, 0); + // Call the timer callback now! + fptc((UINT) timerId, 0, (DWORD) dwUser, 0, 0); - pthread_mutex_lock(&timerEventsLock); - if(timerToFree) - free(timerToFree); - } + pthread_mutex_lock(&timerEventsLock); + if (timerToFree) + free(timerToFree); + } #if defined(TIMER_LOGD) - dumpTimers(); + dumpTimers(); #endif - if (sleep_time < 0) - break; - if (sleep_time == 0) - continue; + if (sleep_time < 0) + break; + if (sleep_time == 0) + continue; - pthread_mutex_unlock(&timerEventsLock); - Sleep(sleep_time > 100 ? 100 : sleep_time); - pthread_mutex_lock(&timerEventsLock); - } - timerThreadId = 0; - pthread_mutex_unlock(&timerEventsLock); - jniDetachCurrentThread(); + pthread_mutex_unlock(&timerEventsLock); + Sleep(sleep_time > 100 ? 100 : sleep_time); + pthread_mutex_lock(&timerEventsLock); + } + timerThreadId = 0; + pthread_mutex_unlock(&timerEventsLock); + jniDetachCurrentThread(); TIMER_LOGD("timerThreadStart() END"); } -MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) { - TIMER_LOGD("timeSetEvent(uDelay: %d, fuEvent: %d)", uDelay, fuEvent); +MMRESULT +timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) { + TIMER_LOGD("timeSetEvent(uDelay: %d, fuEvent: %d)", uDelay, fuEvent); - struct timerEvent * newTimer = (struct timerEvent *)malloc(sizeof(struct timerEvent)); + struct timerEvent *newTimer = (struct timerEvent *) malloc(sizeof(struct timerEvent)); - pthread_mutex_lock(&timerEventsLock); + pthread_mutex_lock(&timerEventsLock); - newTimer->timerId = ++lastTimerId; - newTimer->uDelay = uDelay; // In ms - newTimer->uResolution = uResolution; - newTimer->fptc = fptc; - newTimer->dwUser = dwUser; - newTimer->fuEvent = fuEvent; // TIME_ONESHOT / TIME_PERIODIC + newTimer->timerId = ++lastTimerId; + newTimer->uDelay = uDelay; // In ms + newTimer->uResolution = uResolution; + newTimer->fptc = fptc; + newTimer->dwUser = dwUser; + newTimer->fuEvent = fuEvent; // TIME_ONESHOT / TIME_PERIODIC - newTimer->triggerTime = GetTickCount64() + (ULONGLONG)uDelay; + newTimer->triggerTime = GetTickCount64() + (ULONGLONG) uDelay; - insertTimer(newTimer); + insertTimer(newTimer); - timerThreadToEnd = FALSE; + timerThreadToEnd = FALSE; - if(!timerThreadId) { - // If not yet created, create the thread which will handle all the timers - TIMER_LOGD("timeSetEvent() pthread_create"); - if (pthread_create(&timerThreadId, NULL, (void *(*)(void *)) timerThreadStart, NULL) != 0) { - TIMER_LOGD("timeSetEvent() ERROR in pthread_create, errno: %d (EAGAIN 11 / EINVAL 22 / EPERM 1)", errno); - // EAGAIN Insufficient resources to create another thread. - // EINVAL Invalid settings in attr. - // ENOMEM No permission to set the scheduling policy and parameters specified in attr. - pthread_mutex_unlock(&timerEventsLock); - return NULL; - } - } + if (!timerThreadId) { + // If not yet created, create the thread which will handle all the timers + TIMER_LOGD("timeSetEvent() pthread_create"); + if (pthread_create(&timerThreadId, NULL, (void *(*)(void *)) timerThreadStart, NULL) != 0) { + TIMER_LOGD( + "timeSetEvent() ERROR in pthread_create, errno: %d (EAGAIN 11 / EINVAL 22 / EPERM 1)", + errno); + // EAGAIN Insufficient resources to create another thread. + // EINVAL Invalid settings in attr. + // ENOMEM No permission to set the scheduling policy and parameters specified in attr. + pthread_mutex_unlock(&timerEventsLock); + return NULL; + } + } - TIMER_LOGD("timeSetEvent() -> timerId: [%d]", newTimer->timerId); - pthread_mutex_unlock(&timerEventsLock); - return (MMRESULT) newTimer->timerId; // No error + TIMER_LOGD("timeSetEvent() -> timerId: [%d]", newTimer->timerId); + pthread_mutex_unlock(&timerEventsLock); + return (MMRESULT) newTimer->timerId; // No error } MMRESULT timeGetDevCaps(LPTIMECAPS ptc, UINT cbtc) { - if(ptc) { - ptc->wPeriodMin = 1; // ms - ptc->wPeriodMax = 1000000; // ms -> 1000s - } - return 0; //No error + if (ptc) { + ptc->wPeriodMin = 1; // ms + ptc->wPeriodMax = 1000000; // ms -> 1000s + } + return 0; //No error } + MMRESULT timeBeginPeriod(UINT uPeriod) { - //TODO - return 0; //No error + //TODO + return 0; //No error } + MMRESULT timeEndPeriod(UINT uPeriod) { - //TODO - return 0; //No error + //TODO + return 0; //No error } + VOID GetLocalTime(LPSYSTEMTIME lpSystemTime) { - if(lpSystemTime) { - struct timespec ts = {0, 0}; - struct tm tm = {}; - clock_gettime(CLOCK_REALTIME, &ts); - time_t tim = ts.tv_sec; - localtime_r(&tim, &tm); - lpSystemTime->wYear = (WORD) (1900 + tm.tm_year); - lpSystemTime->wMonth = (WORD) (1 + tm.tm_mon); - lpSystemTime->wDayOfWeek = (WORD) (tm.tm_wday); - lpSystemTime->wDay = (WORD) (tm.tm_mday); - lpSystemTime->wHour = (WORD) (tm.tm_hour); - lpSystemTime->wMinute = (WORD) (tm.tm_min); - lpSystemTime->wSecond = (WORD) (tm.tm_sec); - lpSystemTime->wMilliseconds = (WORD) (ts.tv_nsec / 1e6); - } + if (lpSystemTime) { + struct timespec ts = {0, 0}; + struct tm tm = {}; + clock_gettime(CLOCK_REALTIME, &ts); + time_t tim = ts.tv_sec; + localtime_r(&tim, &tm); + lpSystemTime->wYear = (WORD) (1900 + tm.tm_year); + lpSystemTime->wMonth = (WORD) (1 + tm.tm_mon); + lpSystemTime->wDayOfWeek = (WORD) (tm.tm_wday); + lpSystemTime->wDay = (WORD) (tm.tm_mday); + lpSystemTime->wHour = (WORD) (tm.tm_hour); + lpSystemTime->wMinute = (WORD) (tm.tm_min); + lpSystemTime->wSecond = (WORD) (tm.tm_sec); + lpSystemTime->wMilliseconds = (WORD) (ts.tv_nsec / 1e6); + } } + ULONGLONG GetTickCount64(VOID) { - struct timespec now; - if (clock_gettime(CLOCK_MONOTONIC, &now)) - return 0; - return (ULONGLONG) ((ULONGLONG)now.tv_sec * 1000UL + (ULONGLONG)now.tv_nsec / 1000000UL); + struct timespec now; + if (clock_gettime(CLOCK_MONOTONIC, &now)) + return 0; + return (ULONGLONG) ((ULONGLONG) now.tv_sec * 1000UL + (ULONGLONG) now.tv_nsec / 1000000UL); } + DWORD GetTickCount(VOID) { - return (DWORD)GetTickCount64(); + return (DWORD) GetTickCount64(); } BOOL EnableWindow(HWND hWnd, BOOL bEnable) { - //TODO - return 0; + //TODO + return 0; } + HWND GetDlgItem(HWND hDlg, int nIDDlgItem) { - //TODO - return NULL; + //TODO + return NULL; } -UINT GetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPSTR lpString,int cchMax) { - //TODO - return 0; + +UINT GetDlgItemTextA(HWND hDlg, int nIDDlgItem, LPSTR lpString, int cchMax) { + //TODO + return 0; } extern TCHAR szKmlLog[10240]; extern TCHAR szKmlTitle[10240]; BOOL SetDlgItemText(HWND hDlg, int nIDDlgItem, LPCTSTR lpString) { - if(nIDDlgItem == IDC_KMLLOG) { - //LOGD("KML log:\r\n%s", lpString); - _tcsncpy(szKmlLog, lpString, sizeof(szKmlLog)/sizeof(TCHAR)); - } if(nIDDlgItem == IDC_TITLE) { - _tcsncpy(szKmlTitle, lpString, sizeof(szKmlTitle)/sizeof(TCHAR)); - } - //TODO - return 0; + if (nIDDlgItem == IDC_KMLLOG) { + //LOGD("KML log:\r\n%s", lpString); + _tcsncpy(szKmlLog, lpString, sizeof(szKmlLog) / sizeof(TCHAR)); + } + if (nIDDlgItem == IDC_TITLE) { + _tcsncpy(szKmlTitle, lpString, sizeof(szKmlTitle) / sizeof(TCHAR)); + } + //TODO + return 0; } + LRESULT SendDlgItemMessage(HWND hDlg, int nIDDlgItem, UINT Msg, WPARAM wParam, LPARAM lParam) { - //TODO - return 0; + //TODO + return 0; } + BOOL CheckDlgButton(HWND hDlg, int nIDButton, UINT uCheck) { - //TODO - return 0; + //TODO + return 0; } + UINT IsDlgButtonChecked(HWND hDlg, int nIDButton) { - //TODO - return 0; + //TODO + return 0; } + BOOL EndDialog(HWND hDlg, INT_PTR nResult) { - //TODO - if(currentDialogBoxMode == DialogBoxMode_GET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_GET_USRPRG42 - || currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42) { - itemDataCount = 0; - selItemDataCount = 0; - } - return 0; + //TODO + if (currentDialogBoxMode == DialogBoxMode_GET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_GET_USRPRG42 + || currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42) { + itemDataCount = 0; + selItemDataCount = 0; + } + return 0; } -HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) { - //TODO - return INVALID_HANDLE_VALUE; + +HANDLE FindFirstFileA(LPCSTR lpFileName, LPWIN32_FIND_DATAA lpFindFileData) { + //TODO + return INVALID_HANDLE_VALUE; } + BOOL FindNextFileA(HANDLE hFindFile, LPWIN32_FIND_DATAA lpFindFileData) { - //TODO - return 0; + //TODO + return 0; } + BOOL FindClose(HANDLE hFindFile) { - //TODO - return 0; + //TODO + return 0; } + BOOL SHGetPathFromIDListA(PCIDLIST_ABSOLUTE pidl, LPSTR pszPath) { - //TODO - return 0; + //TODO + return 0; } + HRESULT SHGetMalloc(IMalloc **ppMalloc) { - //TODO - return 0; + //TODO + return 0; } + PIDLIST_ABSOLUTE SHBrowseForFolderA(LPBROWSEINFOA lpbi) { - //TODO - return NULL; + //TODO + return NULL; } + #ifndef IDD_USERCODE - #define IDD_USERCODE 121 +#define IDD_USERCODE 121 #endif -INT_PTR DialogBoxParam(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, LPARAM dwInitParam) { - if(lpTemplateName == MAKEINTRESOURCE(IDD_CHOOSEKML)) { - if(chooseCurrentKmlMode == ChooseKmlMode_UNKNOWN) { - } else if(chooseCurrentKmlMode == ChooseKmlMode_FILE_NEW) { - lstrcpy(szCurrentKml, szChosenCurrentKml); - } else if(chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN || chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN_WITH_FOLDER) { - // We are here because we open a state file and the embedded KML path is not reachable. - // So, we try to find a correct KML file in the current Custom KML scripts folder. - if(!getFirstKMLFilenameForType(Chipset.type)) { - kmlFileNotFound = TRUE; - return -1; - } - } - } else if(lpTemplateName == MAKEINTRESOURCE(IDD_KMLLOG)) { - lpDialogFunc(NULL, WM_INITDIALOG, 0, 0); - } else if(lpTemplateName == MAKEINTRESOURCE(IDD_USERCODE)) { - if(currentDialogBoxMode == DialogBoxMode_GET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_GET_USRPRG42) { - itemDataCount = 0; - selItemDataCount = 0; - lpDialogFunc(NULL, WM_INITDIALOG, 0, 0); - LPTSTR lpLabel = labels; - for(int i = 0; i < itemDataCount; i++) { - _tcscpy(lpLabel, itemString[i]); - lpLabel += _tcslen(itemString[i]) * sizeof(TCHAR); - *lpLabel = 9; // Separator (TAB) - lpLabel++; - } - *lpLabel = 0; // End of string - lpDialogFunc(NULL, WM_COMMAND, IDCANCEL, 0); - } else if(currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 - || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42) { - itemDataCount = 0; - lpDialogFunc(NULL, WM_INITDIALOG, 0, 0); - lpDialogFunc(NULL, WM_COMMAND, IDOK, 0); - } - } - return IDOK; + +INT_PTR +DialogBoxParam(HINSTANCE hInstance, LPCTSTR lpTemplateName, HWND hWndParent, DLGPROC lpDialogFunc, + LPARAM dwInitParam) { + if (lpTemplateName == MAKEINTRESOURCE(IDD_CHOOSEKML)) { + if (chooseCurrentKmlMode == ChooseKmlMode_UNKNOWN) { + } else if (chooseCurrentKmlMode == ChooseKmlMode_FILE_NEW) { + lstrcpy(szCurrentKml, szChosenCurrentKml); + } else if (chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN || + chooseCurrentKmlMode == ChooseKmlMode_FILE_OPEN_WITH_FOLDER) { + // We are here because we open a state file and the embedded KML path is not reachable. + // So, we try to find a correct KML file in the current Custom KML scripts folder. + if (!getFirstKMLFilenameForType(Chipset.type)) { + kmlFileNotFound = TRUE; + return -1; + } + } + } else if (lpTemplateName == MAKEINTRESOURCE(IDD_KMLLOG)) { + lpDialogFunc(NULL, WM_INITDIALOG, 0, 0); + } else if (lpTemplateName == MAKEINTRESOURCE(IDD_USERCODE)) { + if (currentDialogBoxMode == DialogBoxMode_GET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_GET_USRPRG42) { + itemDataCount = 0; + selItemDataCount = 0; + lpDialogFunc(NULL, WM_INITDIALOG, 0, 0); + LPTSTR lpLabel = labels; + for (int i = 0; i < itemDataCount; i++) { + _tcscpy(lpLabel, itemString[i]); + lpLabel += _tcslen(itemString[i]) * sizeof(TCHAR); + *lpLabel = 9; // Separator (TAB) + lpLabel++; + } + *lpLabel = 0; // End of string + lpDialogFunc(NULL, WM_COMMAND, IDCANCEL, 0); + } else if (currentDialogBoxMode == DialogBoxMode_SET_USRPRG32 + || currentDialogBoxMode == DialogBoxMode_SET_USRPRG42) { + itemDataCount = 0; + lpDialogFunc(NULL, WM_INITDIALOG, 0, 0); + lpDialogFunc(NULL, WM_COMMAND, IDOK, 0); + } + } + return IDOK; } + HCURSOR SetCursor(HCURSOR hCursor) { - //TODO - return NULL; + //TODO + return NULL; } + int MulDiv(int nNumber, int nNumerator, int nDenominator) { - //TODO - return 0; + //TODO + return 0; } BOOL GetKeyboardLayoutName(LPSTR pwszKLID) { - //TODO - //Trick to bypass UnmapROM in KillKML - if(pbyRom == NULL && pbyRomBackup) + //TODO + //Trick to bypass UnmapROM in KillKML + if (pbyRom == NULL && pbyRomBackup) pbyRom = pbyRomBackup; - return 0; + return 0; } void DragAcceptFiles(HWND hWnd, BOOL fAccept) { - //TODO + //TODO } +int GetLocaleInfo(LCID Locale, LCTYPE LCType, LPSTR lpLCData, int cchData) { + //TODO + return 0; +} #ifdef UNICODE -int WINAPI wvsprintf(LPWSTR, LPCWSTR, va_list arglist) { - return vswprintf(arg1, MAX_PATH, arg2, arglist); -} -DWORD GetFullPathName(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart) { return 0; } -LPWSTR lstrcpyn(LPWSTR lpString1, LPCWSTR lpString2,int iMaxLength) { - return strcpy(lpString1, lpString2); -} -LPWSTR lstrcat(LPWSTR lpString1, LPCWSTR lpString2) { - return NULL; -} -void __cdecl _wsplitpath(wchar_t const* _FullPath, wchar_t* _Drive, wchar_t* _Dir, wchar_t* _Filename, wchar_t* _Ext) {} -int WINAPI lstrcmp(LPCWSTR lpString1, LPCWSTR lpString2) { - return wcscmp(lpString1, lpString2); -} -int lstrcmpi(LPCWSTR lpString1, LPCWSTR lpString2) { - return wcscasecmp(lpString1, lpString2); -} -void _wmakepath(wchar_t _Buffer, wchar_t const* _Drive, wchar_t const* _Dir, wchar_t const* _Filename, wchar_t const* _Ext) -{ -} + int WINAPI wvsprintf(LPWSTR, LPCWSTR, va_list arglist) { + return vswprintf(arg1, MAX_PATH, arg2, arglist); + } + DWORD GetFullPathName(LPCWSTR lpFileName, DWORD nBufferLength, LPWSTR lpBuffer, LPWSTR* lpFilePart) { return 0; } + LPWSTR lstrcpyn(LPWSTR lpString1, LPCWSTR lpString2,int iMaxLength) { + return strcpy(lpString1, lpString2); + } + LPWSTR lstrcat(LPWSTR lpString1, LPCWSTR lpString2) { + return NULL; + } + void __cdecl _wsplitpath(wchar_t const* _FullPath, wchar_t* _Drive, wchar_t* _Dir, wchar_t* _Filename, wchar_t* _Ext) {} + int WINAPI lstrcmp(LPCWSTR lpString1, LPCWSTR lpString2) { + return wcscmp(lpString1, lpString2); + } + int lstrcmpi(LPCWSTR lpString1, LPCWSTR lpString2) { + return wcscasecmp(lpString1, lpString2); + } + void _wmakepath(wchar_t _Buffer, wchar_t const* _Drive, wchar_t const* _Dir, wchar_t const* _Filename, wchar_t const* _Ext) + { + } #else -int WINAPI wvsprintf(LPSTR arg1, LPCSTR arg2, va_list arglist) { - return vsprintf(arg1, arg2, arglist); -} -const char pathSeparator = + int WINAPI wvsprintf(LPSTR arg1, LPCSTR arg2, va_list arglist) { + return vsprintf(arg1, arg2, arglist); + } + const char pathSeparator = #ifdef _WIN32 - '\\'; + '\\'; #else - '/'; + '/'; #endif -DWORD GetFullPathName(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR* lpFilePart) { - lstrcpyn(lpBuffer, lpFileName, nBufferLength); - if(lpFilePart != NULL) { - *lpFilePart = strrchr(lpBuffer, pathSeparator); - if(*lpFilePart != NULL) - (*lpFilePart)++; - } - return lstrlen(lpBuffer); -} -LPSTR lstrcpyn(LPSTR lpString1, LPCSTR lpString2,int iMaxLength) { - return strcpy(lpString1, lpString2); -} -LPSTR lstrcat(LPSTR lpString1, LPCSTR lpString2) { - return strcat(lpString1, lpString2); -} -void __cdecl _splitpath(const char * _FullPath, char* _Drive, char* _Dir, char* _Filename, char* _Ext) { - if (_Drive) - _Drive[0] = 0; - char * filePart = strrchr(_FullPath, pathSeparator); - if(_Dir) { - if(filePart != NULL) { - strncpy(_Dir, _FullPath, (int)(filePart - _FullPath)); - } else - _Dir[0] = 0; - } - if(_Filename) { - if(filePart != NULL) { - strcpy(_Filename, filePart + 1); - } else - _Filename[0] = 0; - } - if(_Ext) { - _Ext[0] = 0; - if(_Filename) { - char * extPart = strrchr(_Filename, '.'); - if (extPart != NULL) { - strcpy(_Ext, extPart + 1); - } - } - } -} -int WINAPI lstrcmp(LPCSTR lpString1, LPCSTR lpString2) { - return strcmp(lpString1, lpString2); -} -int lstrcmpi(LPCSTR lpString1, LPCSTR lpString2) { - return strcasecmp(lpString1, lpString2); -} + DWORD + GetFullPathName(LPCSTR lpFileName, DWORD nBufferLength, LPSTR lpBuffer, LPSTR *lpFilePart) { + lstrcpyn(lpBuffer, lpFileName, nBufferLength); + if (lpFilePart != NULL) { + *lpFilePart = strrchr(lpBuffer, pathSeparator); + if (*lpFilePart != NULL) + (*lpFilePart)++; + } + return lstrlen(lpBuffer); + } + LPSTR lstrcpyn(LPSTR lpString1, LPCSTR lpString2, int iMaxLength) { + return strcpy(lpString1, lpString2); + } + LPSTR lstrcat(LPSTR lpString1, LPCSTR lpString2) { + return strcat(lpString1, lpString2); + } + void __cdecl + _splitpath(const char *_FullPath, char *_Drive, char *_Dir, char *_Filename, char *_Ext) { + if (_Drive) + _Drive[0] = 0; + char *filePart = strrchr(_FullPath, pathSeparator); + if (_Dir) { + if (filePart != NULL) { + strncpy(_Dir, _FullPath, (int) (filePart - _FullPath)); + } else + _Dir[0] = 0; + } + if (_Filename) { + if (filePart != NULL) { + strcpy(_Filename, filePart + 1); + } else + _Filename[0] = 0; + } + if (_Ext) { + _Ext[0] = 0; + if (_Filename) { + char *extPart = strrchr(_Filename, '.'); + if (extPart != NULL) { + strcpy(_Ext, extPart + 1); + } + } + } + } + int WINAPI lstrcmp(LPCSTR lpString1, LPCSTR lpString2) { + return strcmp(lpString1, lpString2); + } + int lstrcmpi(LPCSTR lpString1, LPCSTR lpString2) { + return strcasecmp(lpString1, lpString2); + } -void _makepath(char _Buffer, char const* _Drive, char const* _Dir, char const* _Filename, char const* _Ext) -{ -} + void _makepath(char _Buffer, char const *_Drive, char const *_Dir, char const *_Filename, + char const *_Ext) { + } #endif // !UNICODE - - -BOOL GetClientRect(HWND hWnd, LPRECT lpRect) -{ - return 0; -} + BOOL GetClientRect(HWND hWnd, LPRECT lpRect) { + return 0; + } // IO -BOOL GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, BOOL bWait) { - //TODO - return FALSE; -} + BOOL + GetOverlappedResult(HANDLE hFile, LPOVERLAPPED lpOverlapped, LPDWORD lpNumberOfBytesTransferred, + BOOL bWait) { + //TODO + return FALSE; + } // This is not a win32 API -void commEvent(int commId, int eventMask) { - SERIAL_LOGD("commEvent(commId: %d, eventMask: 0x%08x)", commId, eventMask); + void commEvent(int commId, int eventMask) { + SERIAL_LOGD("commEvent(commId: %d, eventMask: 0x%08x)", commId, eventMask); - HANDLE commHandleFound = NULL; - pthread_mutex_lock(&commsLock); - for(int i = 0; i < MAX_CREATED_COMM; i++) { - HANDLE commHandle = comms[i]; - if (commHandle && commHandle->commId == commId) { - commHandleFound = commHandle; - break; - } - } - pthread_mutex_unlock(&commsLock); - if(commHandleFound) { - commHandleFound->commEventMask = eventMask; - SetEvent(commHandleFound->commEvent); - } -} - -BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) { - SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p)", hFile, lpEvtMask); - if(hFile && hFile->handleType == HANDLE_TYPE_COM) { - SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject locking", hFile, lpEvtMask); - WaitForSingleObject(hFile->commEvent, INFINITE); - SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject unlocked", hFile, lpEvtMask); + HANDLE commHandleFound = NULL; pthread_mutex_lock(&commsLock); - if(lpEvtMask && hFile->commEventMask) { - *lpEvtMask = hFile->commEventMask; //EV_RXCHAR | EV_TXEMPTY | EV_ERR - hFile->commEventMask = 0; + for (int i = 0; i < MAX_CREATED_COMM; i++) { + HANDLE commHandle = comms[i]; + if (commHandle && commHandle->commId == commId) { + commHandleFound = commHandle; + break; + } } pthread_mutex_unlock(&commsLock); - SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> *lpEvtMask=%d", hFile, lpEvtMask, *lpEvtMask); - return TRUE; - } - return FALSE; -} -BOOL ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) { - SERIAL_LOGD("ClearCommError(hFile: %p, lpErrors: %p, lpStat: %p) TODO", hFile, lpErrors, lpStat); - //TODO - return FALSE; -} -BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { - SERIAL_LOGD("SetCommTimeouts(hFile: %p, lpCommTimeouts: %p) TODO", hFile, lpCommTimeouts); - //TODO - return FALSE; -} -BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) { - SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) TODO", hFile, dwEvtMask); - //TODO - if(hFile && hFile->handleType == HANDLE_TYPE_COM) { - if(dwEvtMask == 0) { - // When 0, clear all events and force WaitCommEvent to return. - SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) SetEvent(hEvent: %p)", hFile, dwEvtMask, hFile->commEvent); - SetEvent(hFile->commEvent); - return TRUE; + if (commHandleFound) { + commHandleFound->commEventMask = eventMask; + SetEvent(commHandleFound->commEvent); } } - return FALSE; -} -BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) { - SERIAL_LOGD("SetCommState(hFile: %p, lpDCB: %p)", hFile, lpDCB); - if(hFile && hFile->handleType == HANDLE_TYPE_COM && lpDCB) { - int result = setSerialPortParameters(hFile->commId, lpDCB->BaudRate); //TODO 2 stop bits? - if(result > 0) { - if (hFile->commState) - free(hFile->commState); - hFile->commState = malloc(sizeof(struct _DCB)); - memcpy(hFile->commState, lpDCB, sizeof(struct _DCB)); - } - return TRUE; - } - return FALSE; -} -BOOL PurgeComm(HANDLE hFile, DWORD dwFlags) { - SERIAL_LOGD("PurgeComm(hFile: %p, dwFlags: 0x%08X) TODO", hFile, dwFlags); - if(hFile && hFile->handleType == HANDLE_TYPE_COM) - return serialPortPurgeComm(hFile->commId, dwFlags); - return FALSE; -} -BOOL SetCommBreak(HANDLE hFile) { - SERIAL_LOGD("SetCommBreak(hFile: %p)", hFile); - if(hFile && hFile->handleType == HANDLE_TYPE_COM) - return serialPortSetBreak(hFile->commId); - return FALSE; -} -BOOL ClearCommBreak(HANDLE hFile) { - SERIAL_LOGD("ClearCommBreak(hFile: %p)", hFile); - if(hFile && hFile->handleType == HANDLE_TYPE_COM) - return serialPortClearBreak(hFile->commId); - return FALSE; -} + + BOOL WaitCommEvent(HANDLE hFile, LPDWORD lpEvtMask, LPOVERLAPPED lpOverlapped) { + SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p)", hFile, lpEvtMask); + if (hFile && hFile->handleType == HANDLE_TYPE_COM) { + SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject locking", + hFile, lpEvtMask); + WaitForSingleObject(hFile->commEvent, INFINITE); + SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> WaitForSingleObject unlocked", + hFile, lpEvtMask); + pthread_mutex_lock(&commsLock); + if (lpEvtMask && hFile->commEventMask) { + *lpEvtMask = hFile->commEventMask; //EV_RXCHAR | EV_TXEMPTY | EV_ERR + hFile->commEventMask = 0; + } + pthread_mutex_unlock(&commsLock); + SERIAL_LOGD("WaitCommEvent(hFile: %p, lpEvtMask: %p) -> *lpEvtMask=%d", hFile, + lpEvtMask, *lpEvtMask); + return TRUE; + } + return FALSE; + } + BOOL ClearCommError(HANDLE hFile, LPDWORD lpErrors, LPCOMSTAT lpStat) { + SERIAL_LOGD("ClearCommError(hFile: %p, lpErrors: %p, lpStat: %p) TODO", hFile, lpErrors, + lpStat); + //TODO + return FALSE; + } + BOOL SetCommTimeouts(HANDLE hFile, LPCOMMTIMEOUTS lpCommTimeouts) { + SERIAL_LOGD("SetCommTimeouts(hFile: %p, lpCommTimeouts: %p) TODO", hFile, lpCommTimeouts); + //TODO + return FALSE; + } + BOOL SetCommMask(HANDLE hFile, DWORD dwEvtMask) { + SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) TODO", hFile, dwEvtMask); + //TODO + if (hFile && hFile->handleType == HANDLE_TYPE_COM) { + if (dwEvtMask == 0) { + // When 0, clear all events and force WaitCommEvent to return. + SERIAL_LOGD("SetCommMask(hFile: %p, dwEvtMask: 0x%08X) SetEvent(hEvent: %p)", hFile, + dwEvtMask, hFile->commEvent); + SetEvent(hFile->commEvent); + return TRUE; + } + } + return FALSE; + } + BOOL SetCommState(HANDLE hFile, LPDCB lpDCB) { + SERIAL_LOGD("SetCommState(hFile: %p, lpDCB: %p)", hFile, lpDCB); + if (hFile && hFile->handleType == HANDLE_TYPE_COM && lpDCB) { + int result = setSerialPortParameters(hFile->commId, + lpDCB->BaudRate); //TODO 2 stop bits? + if (result > 0) { + if (hFile->commState) + free(hFile->commState); + hFile->commState = malloc(sizeof(struct _DCB)); + memcpy(hFile->commState, lpDCB, sizeof(struct _DCB)); + } + return TRUE; + } + return FALSE; + } + BOOL PurgeComm(HANDLE hFile, DWORD dwFlags) { + SERIAL_LOGD("PurgeComm(hFile: %p, dwFlags: 0x%08X) TODO", hFile, dwFlags); + if (hFile && hFile->handleType == HANDLE_TYPE_COM) + return serialPortPurgeComm(hFile->commId, dwFlags); + return FALSE; + } + BOOL SetCommBreak(HANDLE hFile) { + SERIAL_LOGD("SetCommBreak(hFile: %p)", hFile); + if (hFile && hFile->handleType == HANDLE_TYPE_COM) + return serialPortSetBreak(hFile->commId); + return FALSE; + } + BOOL ClearCommBreak(HANDLE hFile) { + SERIAL_LOGD("ClearCommBreak(hFile: %p)", hFile); + if (hFile && hFile->handleType == HANDLE_TYPE_COM) + return serialPortClearBreak(hFile->commId); + return FALSE; + } -int WSAGetLastError() { - //TODO - // Win9x break with WSAEINTR (a blocking socket call was canceled) + int WSAGetLastError() { + //TODO + // Win9x break with WSAEINTR (a blocking socket call was canceled) // if(errno == ECANCELED) // return WSAEINTR; - return 0; -} + return 0; + } -int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) { - return 0; -} + int WSAStartup(WORD wVersionRequested, LPWSADATA lpWSAData) { + return 0; + } -int WSACleanup() { - return 0; -} + int WSACleanup() { + return 0; + } -int closesocket(SOCKET s) { - int err = shutdown(s, SHUT_RDWR); - err = close(s); -} + int closesocket(SOCKET s) { + int err = shutdown(s, SHUT_RDWR); + err = close(s); + } -int win32_select(int __fd_count, fd_set* __read_fds, fd_set* __write_fds, fd_set* __exception_fds, struct timeval* __timeout) { - struct timeval timeout; - if(__timeout == NULL) { - timeout.tv_sec = 1; //0; - timeout.tv_usec = 0; //500000; - __timeout = &timeout; - } - return select(__fd_count, __read_fds, __write_fds, __exception_fds, __timeout); -} + int + win32_select(int __fd_count, fd_set *__read_fds, fd_set *__write_fds, fd_set *__exception_fds, + struct timeval *__timeout) { + struct timeval timeout; + if (__timeout == NULL) { + timeout.tv_sec = 1; //0; + timeout.tv_usec = 0; //500000; + __timeout = &timeout; + } + return select(__fd_count, __read_fds, __write_fds, __exception_fds, __timeout); + } -int win32_ioctlsocket(SOCKET s, long cmd, u_long FAR * argp) { - //TODO - return 0; -} + int win32_ioctlsocket(SOCKET s, long cmd, u_long FAR *argp) { + //TODO + return 0; + } diff --git a/app/src/main/cpp/win32-layer.h b/app/src/main/cpp/win32-layer.h index 28d524c..0a6b3fe 100644 --- a/app/src/main/cpp/win32-layer.h +++ b/app/src/main/cpp/win32-layer.h @@ -1199,9 +1199,12 @@ typedef struct tagCOPYDATASTRUCT { PVOID lpData; } COPYDATASTRUCT, *PCOPYDATASTRUCT; - - - +// Locale info +#define LOCALE_USER_DEFAULT 1024 +#define LOCALE_SDECIMAL 0x0000000E // decimal separator, eg "." for 1,234.00 +typedef DWORD LCID; +typedef DWORD LCTYPE; +extern int GetLocaleInfo(LCID Locale, LCTYPE LCType, LPSTR lpLCData, int cchData); #ifdef UNICODE diff --git a/app/src/main/java/org/emulator/calculator/Serial.java b/app/src/main/java/org/emulator/calculator/Serial.java index 5d351a1..9e6c018 100644 --- a/app/src/main/java/org/emulator/calculator/Serial.java +++ b/app/src/main/java/org/emulator/calculator/Serial.java @@ -158,7 +158,9 @@ public class Serial { if(usbConnection == null && usbPermission == UsbPermission.Unknown && !usbManager.hasPermission(driver.getDevice())) { usbPermission = UsbPermission.Requested; int flags = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M ? PendingIntent.FLAG_MUTABLE : 0; - PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, new Intent(INTENT_ACTION_GRANT_USB), flags); + Intent intent = new Intent(INTENT_ACTION_GRANT_USB); + intent.setPackage(context.getPackageName()); + PendingIntent usbPermissionIntent = PendingIntent.getBroadcast(context, 0, intent, flags); usbManager.requestPermission(driver.getDevice(), usbPermissionIntent); if(debug) Log.d(TAG, "Request permission"); connectionStatus = "serial_connection_failed_user_has_not_given_permission"; diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/CdcAcmSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/CdcAcmSerialDriver.java index 1dde5a0..df4d081 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/CdcAcmSerialDriver.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/CdcAcmSerialDriver.java @@ -8,13 +8,11 @@ package org.emulator.calculator.usbserial.driver; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.util.Log; -import org.emulator.calculator.usbserial.util.HexDump; -import org.emulator.calculator.usbserial.util.UsbUtils; - import java.io.IOException; import java.util.ArrayList; import java.util.EnumSet; @@ -32,8 +30,6 @@ import java.util.Map; */ public class CdcAcmSerialDriver implements UsbSerialDriver { - public static final int USB_SUBCLASS_ACM = 2; - private final String TAG = CdcAcmSerialDriver.class.getSimpleName(); private final UsbDevice mDevice; @@ -42,31 +38,21 @@ public class CdcAcmSerialDriver implements UsbSerialDriver { public CdcAcmSerialDriver(UsbDevice device) { mDevice = device; mPorts = new ArrayList<>(); - int ports = countPorts(device); - for (int port = 0; port < ports; port++) { - mPorts.add(new CdcAcmSerialPort(mDevice, port)); - } - if (mPorts.size() == 0) { - mPorts.add(new CdcAcmSerialPort(mDevice, -1)); - } - } - @SuppressWarnings({"unused"}) - public static boolean probe(UsbDevice device) { - return countPorts(device) > 0; - } - - private static int countPorts(UsbDevice device) { int controlInterfaceCount = 0; int dataInterfaceCount = 0; - for (int i = 0; i < device.getInterfaceCount(); i++) { - if (device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_COMM && - device.getInterface(i).getInterfaceSubclass() == USB_SUBCLASS_ACM) + for( int i = 0; i < device.getInterfaceCount(); i++) { + if(device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_COMM) controlInterfaceCount++; - if (device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) + if(device.getInterface(i).getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) dataInterfaceCount++; } - return Math.min(controlInterfaceCount, dataInterfaceCount); + for( int port = 0; port < Math.min(controlInterfaceCount, dataInterfaceCount); port++) { + mPorts.add(new CdcAcmSerialPort(mDevice, port)); + } + if(mPorts.size() == 0) { + mPorts.add(new CdcAcmSerialPort(mDevice, -1)); + } } @Override @@ -109,11 +95,7 @@ public class CdcAcmSerialDriver implements UsbSerialDriver { } @Override - protected void openInt() throws IOException { - Log.d(TAG, "interfaces:"); - for (int i = 0; i < mDevice.getInterfaceCount(); i++) { - Log.d(TAG, mDevice.getInterface(i).toString()); - } + protected void openInt(UsbDeviceConnection connection) throws IOException { if (mPortNumber == -1) { Log.d(TAG,"device might be castrated ACM device, trying single interface logic"); openSingleInterface(); @@ -149,57 +131,38 @@ public class CdcAcmSerialDriver implements UsbSerialDriver { } private void openInterface() throws IOException { + Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); + int controlInterfaceCount = 0; + int dataInterfaceCount = 0; mControlInterface = null; mDataInterface = null; - int j = getInterfaceIdFromDescriptors(); - Log.d(TAG, "interface count=" + mDevice.getInterfaceCount() + ", IAD=" + j); - if (j >= 0) { - for (int i = 0; i < mDevice.getInterfaceCount(); i++) { - UsbInterface usbInterface = mDevice.getInterface(i); - if (usbInterface.getId() == j || usbInterface.getId() == j+1) { - if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_COMM && - usbInterface.getInterfaceSubclass() == USB_SUBCLASS_ACM) { - mControlIndex = usbInterface.getId(); - mControlInterface = usbInterface; - } - if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) { - mDataInterface = usbInterface; - } + for (int i = 0; i < mDevice.getInterfaceCount(); i++) { + UsbInterface usbInterface = mDevice.getInterface(i); + if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_COMM) { + if(controlInterfaceCount == mPortNumber) { + mControlIndex = i; + mControlInterface = usbInterface; } + controlInterfaceCount++; } - } - if (mControlInterface == null || mDataInterface == null) { - Log.d(TAG, "no IAD fallback"); - int controlInterfaceCount = 0; - int dataInterfaceCount = 0; - for (int i = 0; i < mDevice.getInterfaceCount(); i++) { - UsbInterface usbInterface = mDevice.getInterface(i); - if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_COMM && - usbInterface.getInterfaceSubclass() == USB_SUBCLASS_ACM) { - if (controlInterfaceCount == mPortNumber) { - mControlIndex = usbInterface.getId(); - mControlInterface = usbInterface; - } - controlInterfaceCount++; - } - if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) { - if (dataInterfaceCount == mPortNumber) { - mDataInterface = usbInterface; - } - dataInterfaceCount++; + if (usbInterface.getInterfaceClass() == UsbConstants.USB_CLASS_CDC_DATA) { + if(dataInterfaceCount == mPortNumber) { + mDataInterface = usbInterface; } + dataInterfaceCount++; } } if(mControlInterface == null) { throw new IOException("No control interface"); } - Log.d(TAG, "Control interface id " + mControlInterface.getId()); + Log.d(TAG, "Control iface=" + mControlInterface); if (!mConnection.claimInterface(mControlInterface, true)) { throw new IOException("Could not claim control interface"); } + mControlEndpoint = mControlInterface.getEndpoint(0); if (mControlEndpoint.getDirection() != UsbConstants.USB_DIR_IN || mControlEndpoint.getType() != UsbConstants.USB_ENDPOINT_XFER_INT) { throw new IOException("Invalid control endpoint"); @@ -208,10 +171,12 @@ public class CdcAcmSerialDriver implements UsbSerialDriver { if(mDataInterface == null) { throw new IOException("No data interface"); } - Log.d(TAG, "data interface id " + mDataInterface.getId()); + Log.d(TAG, "data iface=" + mDataInterface); + if (!mConnection.claimInterface(mDataInterface, true)) { throw new IOException("Could not claim data interface"); } + for (int i = 0; i < mDataInterface.getEndpointCount(); i++) { UsbEndpoint ep = mDataInterface.getEndpoint(i); if (ep.getDirection() == UsbConstants.USB_DIR_IN && ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) @@ -221,36 +186,6 @@ public class CdcAcmSerialDriver implements UsbSerialDriver { } } - private int getInterfaceIdFromDescriptors() { - ArrayList descriptors = UsbUtils.getDescriptors(mConnection); - Log.d(TAG, "USB descriptor:"); - for(byte[] descriptor : descriptors) - Log.d(TAG, HexDump.toHexString(descriptor)); - - if (descriptors.size() > 0 && - descriptors.get(0).length == 18 && - descriptors.get(0)[1] == 1 && // bDescriptorType - descriptors.get(0)[4] == (byte)(UsbConstants.USB_CLASS_MISC) && //bDeviceClass - descriptors.get(0)[5] == 2 && // bDeviceSubClass - descriptors.get(0)[6] == 1) { // bDeviceProtocol - // is IAD device, see https://www.usb.org/sites/default/files/iadclasscode_r10.pdf - int port = -1; - for (int d = 1; d < descriptors.size(); d++) { - if (descriptors.get(d).length == 8 && - descriptors.get(d)[1] == 0x0b && // bDescriptorType == IAD - descriptors.get(d)[4] == UsbConstants.USB_CLASS_COMM && // bFunctionClass == CDC - descriptors.get(d)[5] == USB_SUBCLASS_ACM) { // bFunctionSubClass == ACM - port++; - if (port == mPortNumber && - descriptors.get(d)[3] == 2) { // bInterfaceCount - return descriptors.get(d)[2]; // bFirstInterface - } - } - } - } - return -1; - } - private int sendAcmControlMessage(int request, int value, byte[] buf) throws IOException { int len = mConnection.controlTransfer( USB_RT_ACM, request, value, mControlIndex, buf, buf != null ? buf.length : 0, 5000); @@ -351,9 +286,42 @@ public class CdcAcmSerialDriver implements UsbSerialDriver { } - @SuppressWarnings({"unused"}) public static Map getSupportedDevices() { - return new LinkedHashMap<>(); + final Map supportedDevices = new LinkedHashMap<>(); + supportedDevices.put(UsbId.VENDOR_ARDUINO, + new int[] { + UsbId.ARDUINO_UNO, + UsbId.ARDUINO_UNO_R3, + UsbId.ARDUINO_MEGA_2560, + UsbId.ARDUINO_MEGA_2560_R3, + UsbId.ARDUINO_SERIAL_ADAPTER, + UsbId.ARDUINO_SERIAL_ADAPTER_R3, + UsbId.ARDUINO_MEGA_ADK, + UsbId.ARDUINO_MEGA_ADK_R3, + UsbId.ARDUINO_LEONARDO, + UsbId.ARDUINO_MICRO, + }); + supportedDevices.put(UsbId.VENDOR_VAN_OOIJEN_TECH, + new int[] { + UsbId.VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL, + }); + supportedDevices.put(UsbId.VENDOR_ATMEL, + new int[] { + UsbId.ATMEL_LUFA_CDC_DEMO_APP, + }); + supportedDevices.put(UsbId.VENDOR_LEAFLABS, + new int[] { + UsbId.LEAFLABS_MAPLE, + }); + supportedDevices.put(UsbId.VENDOR_ARM, + new int[] { + UsbId.ARM_MBED, + }); + supportedDevices.put(UsbId.VENDOR_ST, + new int[] { + UsbId.ST_CDC, + }); + return supportedDevices; } } diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/Ch34xSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/Ch34xSerialDriver.java index 415acee..dd09763 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/Ch34xSerialDriver.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/Ch34xSerialDriver.java @@ -7,11 +7,9 @@ package org.emulator.calculator.usbserial.driver; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; -import android.util.Log; - -//import org.emulator.calculator.usbserial.BuildConfig; import java.io.IOException; import java.util.Collections; @@ -22,366 +20,355 @@ import java.util.Map; public class Ch34xSerialDriver implements UsbSerialDriver { - private static final String TAG = Ch34xSerialDriver.class.getSimpleName(); + private static final String TAG = Ch34xSerialDriver.class.getSimpleName(); - private final UsbDevice mDevice; - private final UsbSerialPort mPort; + private final UsbDevice mDevice; + private final UsbSerialPort mPort; - private static final int LCR_ENABLE_RX = 0x80; - private static final int LCR_ENABLE_TX = 0x40; - private static final int LCR_MARK_SPACE = 0x20; - private static final int LCR_PAR_EVEN = 0x10; - private static final int LCR_ENABLE_PAR = 0x08; - private static final int LCR_STOP_BITS_2 = 0x04; - private static final int LCR_CS8 = 0x03; - private static final int LCR_CS7 = 0x02; - private static final int LCR_CS6 = 0x01; - private static final int LCR_CS5 = 0x00; + private static final int LCR_ENABLE_RX = 0x80; + private static final int LCR_ENABLE_TX = 0x40; + private static final int LCR_MARK_SPACE = 0x20; + private static final int LCR_PAR_EVEN = 0x10; + private static final int LCR_ENABLE_PAR = 0x08; + private static final int LCR_STOP_BITS_2 = 0x04; + private static final int LCR_CS8 = 0x03; + private static final int LCR_CS7 = 0x02; + private static final int LCR_CS6 = 0x01; + private static final int LCR_CS5 = 0x00; - private static final int GCL_CTS = 0x01; - private static final int GCL_DSR = 0x02; - private static final int GCL_RI = 0x04; - private static final int GCL_CD = 0x08; - private static final int SCL_DTR = 0x20; - private static final int SCL_RTS = 0x40; + private static final int GCL_CTS = 0x01; + private static final int GCL_DSR = 0x02; + private static final int GCL_RI = 0x04; + private static final int GCL_CD = 0x08; + private static final int SCL_DTR = 0x20; + private static final int SCL_RTS = 0x40; - public Ch34xSerialDriver(UsbDevice device) { - mDevice = device; - mPort = new Ch340SerialPort(mDevice, 0); - } + public Ch34xSerialDriver(UsbDevice device) { + mDevice = device; + mPort = new Ch340SerialPort(mDevice, 0); + } - @Override - public UsbDevice getDevice() { - return mDevice; - } + @Override + public UsbDevice getDevice() { + return mDevice; + } - @Override - public List getPorts() { - return Collections.singletonList(mPort); - } + @Override + public List getPorts() { + return Collections.singletonList(mPort); + } - public class Ch340SerialPort extends CommonUsbSerialPort { + public class Ch340SerialPort extends CommonUsbSerialPort { - private static final int USB_TIMEOUT_MILLIS = 5000; + private static final int USB_TIMEOUT_MILLIS = 5000; - private final int DEFAULT_BAUD_RATE = 9600; + private final int DEFAULT_BAUD_RATE = 9600; - private boolean dtr = false; - private boolean rts = false; + private boolean dtr = false; + private boolean rts = false; - public Ch340SerialPort(UsbDevice device, int portNumber) { - super(device, portNumber); - } + public Ch340SerialPort(UsbDevice device, int portNumber) { + super(device, portNumber); + } - @Override - public UsbSerialDriver getDriver() { - return Ch34xSerialDriver.this; - } + @Override + public UsbSerialDriver getDriver() { + return Ch34xSerialDriver.this; + } - @Override - protected void openInt() throws IOException { - for (int i = 0; i < mDevice.getInterfaceCount(); i++) { - UsbInterface usbIface = mDevice.getInterface(i); - if (!mConnection.claimInterface(usbIface, true)) { - throw new IOException("Could not claim data interface"); - } - } + @Override + protected void openInt(UsbDeviceConnection connection) throws IOException { + for (int i = 0; i < mDevice.getInterfaceCount(); i++) { + UsbInterface usbIface = mDevice.getInterface(i); + if (!mConnection.claimInterface(usbIface, true)) { + throw new IOException("Could not claim data interface"); + } + } - UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1); - for (int i = 0; i < dataIface.getEndpointCount(); i++) { - UsbEndpoint ep = dataIface.getEndpoint(i); - if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) { - if (ep.getDirection() == UsbConstants.USB_DIR_IN) { - mReadEndpoint = ep; - } else { - mWriteEndpoint = ep; - } - } - } + UsbInterface dataIface = mDevice.getInterface(mDevice.getInterfaceCount() - 1); + for (int i = 0; i < dataIface.getEndpointCount(); i++) { + UsbEndpoint ep = dataIface.getEndpoint(i); + if (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK) { + if (ep.getDirection() == UsbConstants.USB_DIR_IN) { + mReadEndpoint = ep; + } else { + mWriteEndpoint = ep; + } + } + } - initialize(); - setBaudRate(DEFAULT_BAUD_RATE); - } + initialize(); + setBaudRate(DEFAULT_BAUD_RATE); + } - @Override - protected void closeInt() { - try { - for (int i = 0; i < mDevice.getInterfaceCount(); i++) - mConnection.releaseInterface(mDevice.getInterface(i)); - } catch(Exception ignored) {} - } + @Override + protected void closeInt() { + try { + for (int i = 0; i < mDevice.getInterfaceCount(); i++) + mConnection.releaseInterface(mDevice.getInterface(i)); + } catch(Exception ignored) {} + } - private int controlOut(int request, int value, int index) { - final int REQTYPE_HOST_TO_DEVICE = UsbConstants.USB_TYPE_VENDOR | UsbConstants.USB_DIR_OUT; - return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, - value, index, null, 0, USB_TIMEOUT_MILLIS); - } + private int controlOut(int request, int value, int index) { + final int REQTYPE_HOST_TO_DEVICE = UsbConstants.USB_TYPE_VENDOR | UsbConstants.USB_DIR_OUT; + return mConnection.controlTransfer(REQTYPE_HOST_TO_DEVICE, request, + value, index, null, 0, USB_TIMEOUT_MILLIS); + } - private int controlIn(int request, int value, int index, byte[] buffer) { - final int REQTYPE_DEVICE_TO_HOST = UsbConstants.USB_TYPE_VENDOR | UsbConstants.USB_DIR_IN; - return mConnection.controlTransfer(REQTYPE_DEVICE_TO_HOST, request, - value, index, buffer, buffer.length, USB_TIMEOUT_MILLIS); - } + private int controlIn(int request, int value, int index, byte[] buffer) { + final int REQTYPE_DEVICE_TO_HOST = UsbConstants.USB_TYPE_VENDOR | UsbConstants.USB_DIR_IN; + return mConnection.controlTransfer(REQTYPE_DEVICE_TO_HOST, request, + value, index, buffer, buffer.length, USB_TIMEOUT_MILLIS); + } - private void checkState(String msg, int request, int value, int[] expected) throws IOException { - byte[] buffer = new byte[expected.length]; - int ret = controlIn(request, value, 0, buffer); + private void checkState(String msg, int request, int value, int[] expected) throws IOException { + byte[] buffer = new byte[expected.length]; + int ret = controlIn(request, value, 0, buffer); - if (ret < 0) { - throw new IOException("Failed send cmd [" + msg + "]"); - } + if (ret < 0) { + throw new IOException("Failed send cmd [" + msg + "]"); + } - if (ret != expected.length) { - throw new IOException("Expected " + expected.length + " bytes, but get " + ret + " [" + msg + "]"); - } + if (ret != expected.length) { + throw new IOException("Expected " + expected.length + " bytes, but get " + ret + " [" + msg + "]"); + } - for (int i = 0; i < expected.length; i++) { - if (expected[i] == -1) { - continue; - } + for (int i = 0; i < expected.length; i++) { + if (expected[i] == -1) { + continue; + } - int current = buffer[i] & 0xff; - if (expected[i] != current) { - throw new IOException("Expected 0x" + Integer.toHexString(expected[i]) + " byte, but get 0x" + Integer.toHexString(current) + " [" + msg + "]"); - } - } - } + int current = buffer[i] & 0xff; + if (expected[i] != current) { + throw new IOException("Expected 0x" + Integer.toHexString(expected[i]) + " byte, but get 0x" + Integer.toHexString(current) + " [" + msg + "]"); + } + } + } - private void setControlLines() throws IOException { - if (controlOut(0xa4, ~((dtr ? SCL_DTR : 0) | (rts ? SCL_RTS : 0)), 0) < 0) { - throw new IOException("Failed to set control lines"); - } - } + private void setControlLines() throws IOException { + if (controlOut(0xa4, ~((dtr ? SCL_DTR : 0) | (rts ? SCL_RTS : 0)), 0) < 0) { + throw new IOException("Failed to set control lines"); + } + } - private byte getStatus() throws IOException { - byte[] buffer = new byte[2]; - int ret = controlIn(0x95, 0x0706, 0, buffer); - if (ret < 0) - throw new IOException("Error getting control lines"); - return buffer[0]; - } + private byte getStatus() throws IOException { + byte[] buffer = new byte[2]; + int ret = controlIn(0x95, 0x0706, 0, buffer); + if (ret < 0) + throw new IOException("Error getting control lines"); + return buffer[0]; + } - private void initialize() throws IOException { - checkState("init #1", 0x5f, 0, new int[]{-1 /* 0x27, 0x30 */, 0x00}); + private void initialize() throws IOException { + checkState("init #1", 0x5f, 0, new int[]{-1 /* 0x27, 0x30 */, 0x00}); - if (controlOut(0xa1, 0, 0) < 0) { - throw new IOException("Init failed: #2"); - } + if (controlOut(0xa1, 0, 0) < 0) { + throw new IOException("Init failed: #2"); + } - setBaudRate(DEFAULT_BAUD_RATE); + setBaudRate(DEFAULT_BAUD_RATE); - checkState("init #4", 0x95, 0x2518, new int[]{-1 /* 0x56, c3*/, 0x00}); + checkState("init #4", 0x95, 0x2518, new int[]{-1 /* 0x56, c3*/, 0x00}); - if (controlOut(0x9a, 0x2518, LCR_ENABLE_RX | LCR_ENABLE_TX | LCR_CS8) < 0) { - throw new IOException("Init failed: #5"); - } + if (controlOut(0x9a, 0x2518, LCR_ENABLE_RX | LCR_ENABLE_TX | LCR_CS8) < 0) { + throw new IOException("Init failed: #5"); + } - checkState("init #6", 0x95, 0x0706, new int[]{-1/*0xf?*/, -1/*0xec,0xee*/}); + checkState("init #6", 0x95, 0x0706, new int[]{-1/*0xf?*/, -1/*0xec,0xee*/}); - if (controlOut(0xa1, 0x501f, 0xd90a) < 0) { - throw new IOException("Init failed: #7"); - } + if (controlOut(0xa1, 0x501f, 0xd90a) < 0) { + throw new IOException("Init failed: #7"); + } - setBaudRate(DEFAULT_BAUD_RATE); + setBaudRate(DEFAULT_BAUD_RATE); - setControlLines(); + setControlLines(); - checkState("init #10", 0x95, 0x0706, new int[]{-1/* 0x9f, 0xff*/, -1/*0xec,0xee*/}); - } + checkState("init #10", 0x95, 0x0706, new int[]{-1/* 0x9f, 0xff*/, -1/*0xec,0xee*/}); + } - private void setBaudRate(int baudRate) throws IOException { - long factor; - long divisor; + private void setBaudRate(int baudRate) throws IOException { + final long CH341_BAUDBASE_FACTOR = 1532620800; + final int CH341_BAUDBASE_DIVMAX = 3; - if (baudRate == 921600) { - divisor = 7; - factor = 0xf300; - } else { - final long BAUDBASE_FACTOR = 1532620800; - final int BAUDBASE_DIVMAX = 3; + long factor = CH341_BAUDBASE_FACTOR / baudRate; + int divisor = CH341_BAUDBASE_DIVMAX; -// if(BuildConfig.DEBUG && (baudRate & (3<<29)) == (1<<29)) -// baudRate &= ~(1<<29); // for testing purpose bypass dedicated baud rate handling - factor = BAUDBASE_FACTOR / baudRate; - divisor = BAUDBASE_DIVMAX; - while ((factor > 0xfff0) && divisor > 0) { - factor >>= 3; - divisor--; - } - if (factor > 0xfff0) { - throw new UnsupportedOperationException("Unsupported baud rate: " + baudRate); - } - factor = 0x10000 - factor; - } + while ((factor > 0xfff0) && divisor > 0) { + factor >>= 3; + divisor--; + } - divisor |= 0x0080; // else ch341a waits until buffer full - int val1 = (int) ((factor & 0xff00) | divisor); - int val2 = (int) (factor & 0xff); - Log.d(TAG, String.format("baud rate=%d, 0x1312=0x%04x, 0x0f2c=0x%04x", baudRate, val1, val2)); - int ret = controlOut(0x9a, 0x1312, val1); - if (ret < 0) { - throw new IOException("Error setting baud rate: #1)"); - } - ret = controlOut(0x9a, 0x0f2c, val2); - if (ret < 0) { - throw new IOException("Error setting baud rate: #2"); - } - } + if (factor > 0xfff0) { + throw new UnsupportedOperationException("Unsupported baud rate: " + baudRate); + } - @Override - public void setParameters(int baudRate, int dataBits, int stopBits, @Parity int parity) throws IOException { - if(baudRate <= 0) { - throw new IllegalArgumentException("Invalid baud rate: " + baudRate); - } - setBaudRate(baudRate); + factor = 0x10000 - factor; + divisor |= 0x0080; // else ch341a waits until buffer full + int ret = controlOut(0x9a, 0x1312, (int) ((factor & 0xff00) | divisor)); + if (ret < 0) { + throw new IOException("Error setting baud rate: #1)"); + } - int lcr = LCR_ENABLE_RX | LCR_ENABLE_TX; + ret = controlOut(0x9a, 0x0f2c, (int) (factor & 0xff)); + if (ret < 0) { + throw new IOException("Error setting baud rate: #2"); + } + } - switch (dataBits) { - case DATABITS_5: - lcr |= LCR_CS5; - break; - case DATABITS_6: - lcr |= LCR_CS6; - break; - case DATABITS_7: - lcr |= LCR_CS7; - break; - case DATABITS_8: - lcr |= LCR_CS8; - break; - default: - throw new IllegalArgumentException("Invalid data bits: " + dataBits); - } + @Override + public void setParameters(int baudRate, int dataBits, int stopBits, @Parity int parity) throws IOException { + if(baudRate <= 0) { + throw new IllegalArgumentException("Invalid baud rate: " + baudRate); + } + setBaudRate(baudRate); - switch (parity) { - case PARITY_NONE: - break; - case PARITY_ODD: - lcr |= LCR_ENABLE_PAR; - break; - case PARITY_EVEN: - lcr |= LCR_ENABLE_PAR | LCR_PAR_EVEN; - break; - case PARITY_MARK: - lcr |= LCR_ENABLE_PAR | LCR_MARK_SPACE; - break; - case PARITY_SPACE: - lcr |= LCR_ENABLE_PAR | LCR_MARK_SPACE | LCR_PAR_EVEN; - break; - default: - throw new IllegalArgumentException("Invalid parity: " + parity); - } + int lcr = LCR_ENABLE_RX | LCR_ENABLE_TX; - switch (stopBits) { - case STOPBITS_1: - break; - case STOPBITS_1_5: - throw new UnsupportedOperationException("Unsupported stop bits: 1.5"); - case STOPBITS_2: - lcr |= LCR_STOP_BITS_2; - break; - default: - throw new IllegalArgumentException("Invalid stop bits: " + stopBits); - } + switch (dataBits) { + case DATABITS_5: + lcr |= LCR_CS5; + break; + case DATABITS_6: + lcr |= LCR_CS6; + break; + case DATABITS_7: + lcr |= LCR_CS7; + break; + case DATABITS_8: + lcr |= LCR_CS8; + break; + default: + throw new IllegalArgumentException("Invalid data bits: " + dataBits); + } - int ret = controlOut(0x9a, 0x2518, lcr); - if (ret < 0) { - throw new IOException("Error setting control byte"); - } - } + switch (parity) { + case PARITY_NONE: + break; + case PARITY_ODD: + lcr |= LCR_ENABLE_PAR; + break; + case PARITY_EVEN: + lcr |= LCR_ENABLE_PAR | LCR_PAR_EVEN; + break; + case PARITY_MARK: + lcr |= LCR_ENABLE_PAR | LCR_MARK_SPACE; + break; + case PARITY_SPACE: + lcr |= LCR_ENABLE_PAR | LCR_MARK_SPACE | LCR_PAR_EVEN; + break; + default: + throw new IllegalArgumentException("Invalid parity: " + parity); + } - @Override - public boolean getCD() throws IOException { - return (getStatus() & GCL_CD) == 0; - } + switch (stopBits) { + case STOPBITS_1: + break; + case STOPBITS_1_5: + throw new UnsupportedOperationException("Unsupported stop bits: 1.5"); + case STOPBITS_2: + lcr |= LCR_STOP_BITS_2; + break; + default: + throw new IllegalArgumentException("Invalid stop bits: " + stopBits); + } - @Override - public boolean getCTS() throws IOException { - return (getStatus() & GCL_CTS) == 0; - } + int ret = controlOut(0x9a, 0x2518, lcr); + if (ret < 0) { + throw new IOException("Error setting control byte"); + } + } - @Override - public boolean getDSR() throws IOException { - return (getStatus() & GCL_DSR) == 0; - } + @Override + public boolean getCD() throws IOException { + return (getStatus() & GCL_CD) == 0; + } - @Override - public boolean getDTR() throws IOException { - return dtr; - } + @Override + public boolean getCTS() throws IOException { + return (getStatus() & GCL_CTS) == 0; + } - @Override - public void setDTR(boolean value) throws IOException { - dtr = value; - setControlLines(); - } + @Override + public boolean getDSR() throws IOException { + return (getStatus() & GCL_DSR) == 0; + } - @Override - public boolean getRI() throws IOException { - return (getStatus() & GCL_RI) == 0; - } + @Override + public boolean getDTR() throws IOException { + return dtr; + } - @Override - public boolean getRTS() throws IOException { - return rts; - } + @Override + public void setDTR(boolean value) throws IOException { + dtr = value; + setControlLines(); + } - @Override - public void setRTS(boolean value) throws IOException { - rts = value; - setControlLines(); - } + @Override + public boolean getRI() throws IOException { + return (getStatus() & GCL_RI) == 0; + } - @Override - public EnumSet getControlLines() throws IOException { - int status = getStatus(); - EnumSet set = EnumSet.noneOf(ControlLine.class); - if(rts) set.add(ControlLine.RTS); - if((status & GCL_CTS) == 0) set.add(ControlLine.CTS); - if(dtr) set.add(ControlLine.DTR); - if((status & GCL_DSR) == 0) set.add(ControlLine.DSR); - if((status & GCL_CD) == 0) set.add(ControlLine.CD); - if((status & GCL_RI) == 0) set.add(ControlLine.RI); - return set; - } + @Override + public boolean getRTS() throws IOException { + return rts; + } - @Override - public EnumSet getSupportedControlLines() throws IOException { - return EnumSet.allOf(ControlLine.class); - } + @Override + public void setRTS(boolean value) throws IOException { + rts = value; + setControlLines(); + } - @Override - public void setBreak(boolean value) throws IOException { - byte[] req = new byte[2]; - if(controlIn(0x95, 0x1805, 0, req) < 0) { - throw new IOException("Error getting BREAK condition"); - } - if(value) { - req[0] &= ~1; - req[1] &= ~0x40; - } else { - req[0] |= 1; - req[1] |= 0x40; - } - int val = (req[1] & 0xff) << 8 | (req[0] & 0xff); - if(controlOut(0x9a, 0x1805, val) < 0) { - throw new IOException("Error setting BREAK condition"); - } - } - } + @Override + public EnumSet getControlLines() throws IOException { + int status = getStatus(); + EnumSet set = EnumSet.noneOf(ControlLine.class); + if(rts) set.add(ControlLine.RTS); + if((status & GCL_CTS) == 0) set.add(ControlLine.CTS); + if(dtr) set.add(ControlLine.DTR); + if((status & GCL_DSR) == 0) set.add(ControlLine.DSR); + if((status & GCL_CD) == 0) set.add(ControlLine.CD); + if((status & GCL_RI) == 0) set.add(ControlLine.RI); + return set; + } - @SuppressWarnings({"unused"}) - public static Map getSupportedDevices() { - final Map supportedDevices = new LinkedHashMap<>(); - supportedDevices.put(UsbId.VENDOR_QINHENG, new int[]{ - UsbId.QINHENG_CH340, - UsbId.QINHENG_CH341A, - }); - return supportedDevices; - } + @Override + public EnumSet getSupportedControlLines() throws IOException { + return EnumSet.allOf(ControlLine.class); + } + + @Override + public void setBreak(boolean value) throws IOException { + byte[] req = new byte[2]; + if(controlIn(0x95, 0x1805, 0, req) < 0) { + throw new IOException("Error getting BREAK condition"); + } + if(value) { + req[0] &= ~1; + req[1] &= ~0x40; + } else { + req[0] |= 1; + req[1] |= 0x40; + } + int val = (req[1] & 0xff) << 8 | (req[0] & 0xff); + if(controlOut(0x9a, 0x1805, val) < 0) { + throw new IOException("Error setting BREAK condition"); + } + } + } + + public static Map getSupportedDevices() { + final Map supportedDevices = new LinkedHashMap<>(); + supportedDevices.put(UsbId.VENDOR_QINHENG, new int[]{ + UsbId.QINHENG_CH340, + UsbId.QINHENG_CH341A, + }); + return supportedDevices; + } } \ No newline at end of file diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/ChromeCcdSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/ChromeCcdSerialDriver.java deleted file mode 100644 index ef93042..0000000 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/ChromeCcdSerialDriver.java +++ /dev/null @@ -1,96 +0,0 @@ -package org.emulator.calculator.usbserial.driver; - -import android.hardware.usb.UsbConstants; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbEndpoint; -import android.hardware.usb.UsbInterface; -import android.util.Log; - -import java.io.IOException; -import java.util.Collections; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.ArrayList; - -public class ChromeCcdSerialDriver implements UsbSerialDriver{ - - private final String TAG = ChromeCcdSerialDriver.class.getSimpleName(); - - private final UsbDevice mDevice; - private final List mPorts; - - @Override - public UsbDevice getDevice() { - return mDevice; - } - - @Override - public List getPorts() { - return mPorts; - } - - public ChromeCcdSerialDriver(UsbDevice mDevice) { - this.mDevice = mDevice; - mPorts = new ArrayList(); - for (int i = 0; i < 3; i++) - mPorts.add(new ChromeCcdSerialPort(mDevice, i)); - } - - public class ChromeCcdSerialPort extends CommonUsbSerialPort { - private UsbInterface mDataInterface; - - public ChromeCcdSerialPort(UsbDevice device, int portNumber) { - super(device, portNumber); - } - - @Override - protected void openInt() throws IOException { - Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); - mDataInterface = mDevice.getInterface(mPortNumber); - if (!mConnection.claimInterface(mDataInterface, true)) { - throw new IOException("Could not claim shared control/data interface"); - } - Log.d(TAG, "endpoint count=" + mDataInterface.getEndpointCount()); - for (int i = 0; i < mDataInterface.getEndpointCount(); ++i) { - UsbEndpoint ep = mDataInterface.getEndpoint(i); - if ((ep.getDirection() == UsbConstants.USB_DIR_IN) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) { - mReadEndpoint = ep; - } else if ((ep.getDirection() == UsbConstants.USB_DIR_OUT) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) { - mWriteEndpoint = ep; - } - } - } - - @Override - protected void closeInt() { - try { - mConnection.releaseInterface(mDataInterface); - } catch(Exception ignored) {} - } - - @Override - public UsbSerialDriver getDriver() { - return ChromeCcdSerialDriver.this; - } - - @Override - public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public EnumSet getSupportedControlLines() throws IOException { - return EnumSet.noneOf(ControlLine.class); - } - } - - public static Map getSupportedDevices() { - final Map supportedDevices = new LinkedHashMap<>(); - supportedDevices.put(UsbId.VENDOR_GOOGLE, new int[]{ - UsbId.GOOGLE_CR50, - }); - return supportedDevices; - } -} diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/CommonUsbSerialPort.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/CommonUsbSerialPort.java index d9faa34..0a7e93b 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/CommonUsbSerialPort.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/CommonUsbSerialPort.java @@ -25,32 +25,28 @@ import java.util.EnumSet; */ public abstract class CommonUsbSerialPort implements UsbSerialPort { - public static boolean DEBUG = false; - private static final String TAG = CommonUsbSerialPort.class.getSimpleName(); + private static final int DEFAULT_WRITE_BUFFER_SIZE = 16 * 1024; private static final int MAX_READ_SIZE = 16 * 1024; // = old bulkTransfer limit protected final UsbDevice mDevice; protected final int mPortNumber; // non-null when open() - protected UsbDeviceConnection mConnection; + protected UsbDeviceConnection mConnection = null; protected UsbEndpoint mReadEndpoint; protected UsbEndpoint mWriteEndpoint; protected UsbRequest mUsbRequest; - /** - * Internal write buffer. - * Guarded by {@link #mWriteBufferLock}. - * Default length = mReadEndpoint.getMaxPacketSize() - **/ - protected byte[] mWriteBuffer; protected final Object mWriteBufferLock = new Object(); - + /** Internal write buffer. Guarded by {@link #mWriteBufferLock}. */ + protected byte[] mWriteBuffer; public CommonUsbSerialPort(UsbDevice device, int portNumber) { mDevice = device; mPortNumber = portNumber; + + mWriteBuffer = new byte[DEFAULT_WRITE_BUFFER_SIZE]; } @Override @@ -89,19 +85,11 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { * Sets the size of the internal buffer used to exchange data with the USB * stack for write operations. Most users should not need to change this. * - * @param bufferSize the size in bytes, <= 0 resets original size + * @param bufferSize the size in bytes */ public final void setWriteBufferSize(int bufferSize) { synchronized (mWriteBufferLock) { - if (bufferSize <= 0) { - if (mWriteEndpoint != null) { - bufferSize = mWriteEndpoint.getMaxPacketSize(); - } else { - mWriteBuffer = null; - return; - } - } - if (mWriteBuffer != null && bufferSize == mWriteBuffer.length) { + if (bufferSize == mWriteBuffer.length) { return; } mWriteBuffer = new byte[bufferSize]; @@ -118,7 +106,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { } mConnection = connection; try { - openInt(); + openInt(connection); if (mReadEndpoint == null || mWriteEndpoint == null) { throw new IOException("Could not get read & write endpoints"); } @@ -132,18 +120,17 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { } } - protected abstract void openInt() throws IOException; + protected abstract void openInt(UsbDeviceConnection connection) throws IOException; @Override public void close() throws IOException { if (mConnection == null) { throw new IOException("Already closed"); } - UsbRequest usbRequest = mUsbRequest; - mUsbRequest = null; try { - usbRequest.cancel(); + mUsbRequest.cancel(); } catch(Exception ignored) {} + mUsbRequest = null; try { closeInt(); } catch(Exception ignored) {} @@ -158,40 +145,25 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { /** * use simple USB request supported by all devices to test if connection is still valid */ - protected void testConnection(boolean full) throws IOException { - testConnection(full, "USB get_status request failed"); - } - - protected void testConnection(boolean full, String msg) throws IOException { - if(mUsbRequest == null) { - throw new IOException("Connection closed"); - } - if(!full) { - return; - } + protected void testConnection() throws IOException { byte[] buf = new byte[2]; int len = mConnection.controlTransfer(0x80 /*DEVICE*/, 0 /*GET_STATUS*/, 0, 0, buf, buf.length, 200); if(len < 0) - throw new IOException(msg); + throw new IOException("USB get_status request failed"); } @Override public int read(final byte[] dest, final int timeout) throws IOException { - if(dest.length == 0) { - throw new IllegalArgumentException("Read buffer too small"); - } - return read(dest, dest.length, timeout); + return read(dest, timeout, true); } - @Override - public int read(final byte[] dest, final int length, final int timeout) throws IOException {return read(dest, length, timeout, true);} - - protected int read(final byte[] dest, int length, final int timeout, boolean testConnection) throws IOException { - testConnection(false); - if(length <= 0) { - throw new IllegalArgumentException("Read length too small"); + protected int read(final byte[] dest, final int timeout, boolean testConnection) throws IOException { + if(mConnection == null) { + throw new IOException("Connection closed"); + } + if(dest.length <= 0) { + throw new IllegalArgumentException("Read buffer to small"); } - length = Math.min(length, dest.length); final int nread; if (timeout != 0) { // bulkTransfer will cause data loss with short timeout + high baud rates + continuous transfer @@ -203,16 +175,16 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { // /system/lib64/libandroid_runtime.so (android_hardware_UsbDeviceConnection_request_wait(_JNIEnv*, _jobject*, long)+84) // data loss / crashes were observed with timeout up to 200 msec long endTime = testConnection ? MonotonicClock.millis() + timeout : 0; - int readMax = Math.min(length, MAX_READ_SIZE); + int readMax = Math.min(dest.length, MAX_READ_SIZE); nread = mConnection.bulkTransfer(mReadEndpoint, dest, readMax, timeout); // Android error propagation is improvable: // nread == -1 can be: timeout, connection lost, buffer to small, ??? - if(nread == -1 && testConnection) - testConnection(MonotonicClock.millis() < endTime); + if(nread == -1 && testConnection && MonotonicClock.millis() < endTime) + testConnection(); } else { - final ByteBuffer buf = ByteBuffer.wrap(dest, 0, length); - if (!mUsbRequest.queue(buf, length)) { + final ByteBuffer buf = ByteBuffer.wrap(dest); + if (!mUsbRequest.queue(buf, dest.length)) { throw new IOException("Queueing USB request failed"); } final UsbRequest response = mConnection.requestWait(); @@ -223,23 +195,21 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { // Android error propagation is improvable: // response != null & nread == 0 can be: connection lost, buffer to small, ??? if(nread == 0) { - testConnection(true); + testConnection(); } } return Math.max(nread, 0); } @Override - public void write(byte[] src, int timeout) throws IOException {write(src, src.length, timeout);} - - @Override - public void write(final byte[] src, int length, final int timeout) throws IOException { + public void write(final byte[] src, final int timeout) throws IOException { int offset = 0; - long startTime = MonotonicClock.millis(); - length = Math.min(length, src.length); + final long endTime = (timeout == 0) ? 0 : (MonotonicClock.millis() + timeout); - testConnection(false); - while (offset < length) { + if(mConnection == null) { + throw new IOException("Connection closed"); + } + while (offset < src.length) { int requestTimeout; final int requestLength; final int actualLength; @@ -247,10 +217,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { synchronized (mWriteBufferLock) { final byte[] writeBuffer; - if (mWriteBuffer == null) { - mWriteBuffer = new byte[mWriteEndpoint.getMaxPacketSize()]; - } - requestLength = Math.min(length - offset, mWriteBuffer.length); + requestLength = Math.min(src.length - offset, mWriteBuffer.length); if (offset == 0) { writeBuffer = src; } else { @@ -261,7 +228,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { if (timeout == 0 || offset == 0) { requestTimeout = timeout; } else { - requestTimeout = (int)(startTime + timeout - MonotonicClock.millis()); + requestTimeout = (int)(endTime - MonotonicClock.millis()); if(requestTimeout == 0) requestTimeout = -1; } @@ -271,18 +238,14 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { actualLength = mConnection.bulkTransfer(mWriteEndpoint, writeBuffer, requestLength, requestTimeout); } } - long elapsed = MonotonicClock.millis() - startTime; - if (DEBUG) { - Log.d(TAG, "Wrote " + actualLength + "/" + requestLength + " offset " + offset + "/" + length + " time " + elapsed + "/" + requestTimeout); - } + Log.d(TAG, "Wrote " + actualLength + "/" + requestLength + " offset " + offset + "/" + src.length + " timeout " + requestTimeout); if (actualLength <= 0) { - String msg = "Error writing " + requestLength + " bytes at offset " + offset + " of total " + src.length + " after " + elapsed + "msec, rc=" + actualLength; - if (timeout != 0) { - testConnection(elapsed < timeout, msg); - throw new SerialTimeoutException(msg, offset); + if (timeout != 0 && MonotonicClock.millis() >= endTime) { + SerialTimeoutException ex = new SerialTimeoutException("Error writing " + requestLength + " bytes at offset " + offset + " of total " + src.length + ", rc=" + actualLength); + ex.bytesTransferred = offset; + throw ex; } else { - throw new IOException(msg); - + throw new IOException("Error writing " + requestLength + " bytes at offset " + offset + " of total " + src.length); } } offset += actualLength; @@ -291,7 +254,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { @Override public boolean isOpen() { - return mUsbRequest != null; + return mConnection != null; } @Override @@ -322,7 +285,7 @@ public abstract class CommonUsbSerialPort implements UsbSerialPort { public void setRTS(boolean value) throws IOException { throw new UnsupportedOperationException(); } @Override - public EnumSet getControlLines() throws IOException { throw new UnsupportedOperationException(); } + public abstract EnumSet getControlLines() throws IOException; @Override public abstract EnumSet getSupportedControlLines() throws IOException; diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/Cp21xxSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/Cp21xxSerialDriver.java index 906486c..c8f02c0 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/Cp21xxSerialDriver.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/Cp21xxSerialDriver.java @@ -8,6 +8,7 @@ package org.emulator.calculator.usbserial.driver; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; @@ -118,14 +119,14 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { byte[] buffer = new byte[1]; int result = mConnection.controlTransfer(REQTYPE_DEVICE_TO_HOST, SILABSER_GET_MDMSTS_REQUEST_CODE, 0, mPortNumber, buffer, buffer.length, USB_WRITE_TIMEOUT_MILLIS); - if (result != buffer.length) { + if (result != 1) { throw new IOException("Control transfer failed: " + SILABSER_GET_MDMSTS_REQUEST_CODE + " / " + 0 + " -> " + result); } return buffer[0]; } @Override - protected void openInt() throws IOException { + protected void openInt(UsbDeviceConnection connection) throws IOException { mIsRestrictedPort = mDevice.getInterfaceCount() == 2 && mPortNumber == 1; if(mPortNumber >= mDevice.getInterfaceCount()) { throw new IOException("Unknown port number"); @@ -320,7 +321,6 @@ public class Cp21xxSerialDriver implements UsbSerialDriver { } } - @SuppressWarnings({"unused"}) public static Map getSupportedDevices() { final Map supportedDevices = new LinkedHashMap<>(); supportedDevices.put(UsbId.VENDOR_SILABS, diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/FtdiSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/FtdiSerialDriver.java index d28e729..4fa50e0 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/FtdiSerialDriver.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/FtdiSerialDriver.java @@ -9,6 +9,7 @@ package org.emulator.calculator.usbserial.driver; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; import android.util.Log; import org.emulator.calculator.usbserial.util.MonotonicClock; @@ -98,8 +99,8 @@ public class FtdiSerialDriver implements UsbSerialDriver { @Override - protected void openInt() throws IOException { - if (!mConnection.claimInterface(mDevice.getInterface(mPortNumber), true)) { + protected void openInt(UsbDeviceConnection connection) throws IOException { + if (!connection.claimInterface(mDevice.getInterface(mPortNumber), true)) { throw new IOException("Could not claim interface " + mPortNumber); } if (mDevice.getInterface(mPortNumber).getEndpointCount() < 2) { @@ -122,13 +123,12 @@ public class FtdiSerialDriver implements UsbSerialDriver { } // mDevice.getVersion() would require API 23 - byte[] rawDescriptors = mConnection.getRawDescriptors(); + byte[] rawDescriptors = connection.getRawDescriptors(); if(rawDescriptors == null || rawDescriptors.length < 14) { throw new IOException("Could not get device descriptors"); } int deviceType = rawDescriptors[13]; - baudRateWithPort = deviceType == 7 || deviceType == 8 || deviceType == 9 // ...H devices - || mDevice.getInterfaceCount() > 1; // FT2232C + baudRateWithPort = deviceType == 7 || deviceType == 8 || deviceType == 9; // ...H devices } @Override @@ -139,37 +139,24 @@ public class FtdiSerialDriver implements UsbSerialDriver { } @Override - public int read(final byte[] dest, final int timeout) throws IOException - { + public int read(final byte[] dest, final int timeout) throws IOException { if(dest.length <= READ_HEADER_LENGTH) { - throw new IllegalArgumentException("Read buffer too small"); + throw new IllegalArgumentException("Read buffer to small"); // could allocate larger buffer, including space for 2 header bytes, but this would // result in buffers not being 64 byte aligned any more, causing data loss at continuous // data transfer at high baud rates when buffers are fully filled. } - return read(dest, dest.length, timeout); - } - - @Override - public int read(final byte[] dest, int length, final int timeout) throws IOException { - if(length <= READ_HEADER_LENGTH) { - throw new IllegalArgumentException("Read length too small"); - // could allocate larger buffer, including space for 2 header bytes, but this would - // result in buffers not being 64 byte aligned any more, causing data loss at continuous - // data transfer at high baud rates when buffers are fully filled. - } - length = Math.min(length, dest.length); int nread; if (timeout != 0) { long endTime = MonotonicClock.millis() + timeout; do { - nread = super.read(dest, length, Math.max(1, (int)(endTime - MonotonicClock.millis())), false); + nread = super.read(dest, Math.max(1, (int)(endTime - MonotonicClock.millis())), false); } while (nread == READ_HEADER_LENGTH && MonotonicClock.millis() < endTime); - if(nread <= 0) - testConnection(MonotonicClock.millis() < endTime); + if(nread <= 0 && MonotonicClock.millis() < endTime) + testConnection(); } else { do { - nread = super.read(dest, length, timeout); + nread = super.read(dest, timeout, false); } while (nread == READ_HEADER_LENGTH); } return readFilter(dest, nread); @@ -303,7 +290,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { byte[] data = new byte[2]; int result = mConnection.controlTransfer(REQTYPE_DEVICE_TO_HOST, GET_MODEM_STATUS_REQUEST, 0, mPortNumber+1, data, data.length, USB_WRITE_TIMEOUT_MILLIS); - if (result != data.length) { + if (result != 2) { throw new IOException("Get modem status failed: result=" + result); } return data[0]; @@ -419,7 +406,7 @@ public class FtdiSerialDriver implements UsbSerialDriver { byte[] data = new byte[1]; int result = mConnection.controlTransfer(REQTYPE_DEVICE_TO_HOST, GET_LATENCY_TIMER_REQUEST, 0, mPortNumber+1, data, data.length, USB_WRITE_TIMEOUT_MILLIS); - if (result != data.length) { + if (result != 1) { throw new IOException("Get latency timer failed: result=" + result); } return data[0]; @@ -427,7 +414,6 @@ public class FtdiSerialDriver implements UsbSerialDriver { } - @SuppressWarnings({"unused"}) public static Map getSupportedDevices() { final Map supportedDevices = new LinkedHashMap<>(); supportedDevices.put(UsbId.VENDOR_FTDI, diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/GsmModemSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/GsmModemSerialDriver.java deleted file mode 100644 index c180401..0000000 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/GsmModemSerialDriver.java +++ /dev/null @@ -1,106 +0,0 @@ -package org.emulator.calculator.usbserial.driver; - -import android.hardware.usb.UsbConstants; -import android.hardware.usb.UsbDevice; -import android.hardware.usb.UsbEndpoint; -import android.hardware.usb.UsbInterface; -import android.util.Log; - -import java.io.IOException; -import java.util.Collections; -import java.util.EnumSet; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -public class GsmModemSerialDriver implements UsbSerialDriver{ - - private final String TAG = GsmModemSerialDriver.class.getSimpleName(); - - private final UsbDevice mDevice; - private final UsbSerialPort mPort; - - @Override - public UsbDevice getDevice() { - return mDevice; - } - - @Override - public List getPorts() { - return Collections.singletonList(mPort); - } - - public GsmModemSerialDriver(UsbDevice mDevice) { - this.mDevice = mDevice; - mPort = new GsmModemSerialPort(mDevice, 0); - } - - public class GsmModemSerialPort extends CommonUsbSerialPort { - - private UsbInterface mDataInterface; - - public GsmModemSerialPort(UsbDevice device, int portNumber) { - super(device, portNumber); - } - - @Override - protected void openInt() throws IOException { - Log.d(TAG, "claiming interfaces, count=" + mDevice.getInterfaceCount()); - mDataInterface = mDevice.getInterface(0); - if (!mConnection.claimInterface(mDataInterface, true)) { - throw new IOException("Could not claim shared control/data interface"); - } - Log.d(TAG, "endpoint count=" + mDataInterface.getEndpointCount()); - for (int i = 0; i < mDataInterface.getEndpointCount(); ++i) { - UsbEndpoint ep = mDataInterface.getEndpoint(i); - if ((ep.getDirection() == UsbConstants.USB_DIR_IN) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) { - mReadEndpoint = ep; - } else if ((ep.getDirection() == UsbConstants.USB_DIR_OUT) && (ep.getType() == UsbConstants.USB_ENDPOINT_XFER_BULK)) { - mWriteEndpoint = ep; - } - } - initGsmModem(); - } - - @Override - protected void closeInt() { - try { - mConnection.releaseInterface(mDataInterface); - } catch(Exception ignored) {} - - } - - private int initGsmModem() throws IOException { - int len = mConnection.controlTransfer( - 0x21, 0x22, 0x01, 0, null, 0, 5000); - if(len < 0) { - throw new IOException("init failed"); - } - return len; - } - - @Override - public UsbSerialDriver getDriver() { - return GsmModemSerialDriver.this; - } - - @Override - public void setParameters(int baudRate, int dataBits, int stopBits, int parity) throws IOException { - throw new UnsupportedOperationException(); - } - - @Override - public EnumSet getSupportedControlLines() throws IOException { - return EnumSet.noneOf(ControlLine.class); - } - } - - public static Map getSupportedDevices() { - final Map supportedDevices = new LinkedHashMap<>(); - supportedDevices.put(UsbId.VENDOR_UNISOC, new int[]{ - UsbId.FIBOCOM_L610, - UsbId.FIBOCOM_L612, - }); - return supportedDevices; - } -} diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/ProbeTable.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/ProbeTable.java index bcf6e0d..b64918e 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/ProbeTable.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/ProbeTable.java @@ -6,7 +6,6 @@ package org.emulator.calculator.usbserial.driver; -import android.hardware.usb.UsbDevice; import android.util.Pair; import java.lang.reflect.InvocationTargetException; @@ -15,14 +14,14 @@ import java.util.LinkedHashMap; import java.util.Map; /** - * Maps (vendor id, product id) pairs to the corresponding serial driver, - * or invoke 'probe' method to check actual USB devices for matching interfaces. + * Maps (vendor id, product id) pairs to the corresponding serial driver. + * + * @author mike wakerly (opensource@hoho.com) */ public class ProbeTable { - private final Map, Class> mVidPidProbeTable = + private final Map, Class> mProbeTable = new LinkedHashMap<>(); - private final Map> mMethodProbeTable = new LinkedHashMap<>(); /** * Adds or updates a (vendor, product) pair in the table. @@ -34,7 +33,7 @@ public class ProbeTable { */ public ProbeTable addProduct(int vendorId, int productId, Class driverClass) { - mVidPidProbeTable.put(Pair.create(vendorId, productId), driverClass); + mProbeTable.put(Pair.create(vendorId, productId), driverClass); return this; } @@ -42,11 +41,12 @@ public class ProbeTable { * Internal method to add all supported products from * {@code getSupportedProducts} static method. * - * @param driverClass to be added + * @param driverClass + * @return */ @SuppressWarnings("unchecked") - void addDriver(Class driverClass) { - Method method; + ProbeTable addDriver(Class driverClass) { + final Method method; try { method = driverClass.getMethod("getSupportedDevices"); @@ -68,35 +68,20 @@ public class ProbeTable { } } - try { - method = driverClass.getMethod("probe", UsbDevice.class); - mMethodProbeTable.put(method, driverClass); - } catch (SecurityException | NoSuchMethodException ignored) { - } + return this; } /** - * Returns the driver for the given USB device, or {@code null} if no match. + * Returns the driver for the given (vendor, product) pair, or {@code null} + * if no match. * - * @param usbDevice the USB device to be probed + * @param vendorId the USB vendor id + * @param productId the USB product id * @return the driver class matching this pair, or {@code null} */ - public Class findDriver(final UsbDevice usbDevice) { - final Pair pair = Pair.create(usbDevice.getVendorId(), usbDevice.getProductId()); - Class driverClass = mVidPidProbeTable.get(pair); - if (driverClass != null) - return driverClass; - for (Map.Entry> entry : mMethodProbeTable.entrySet()) { - try { - Method method = entry.getKey(); - Object o = method.invoke(null, usbDevice); - if((boolean)o) - return entry.getValue(); - } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } - } - return null; + public Class findDriver(int vendorId, int productId) { + final Pair pair = Pair.create(vendorId, productId); + return mProbeTable.get(pair); } } diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/ProlificSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/ProlificSerialDriver.java index 2ae4968..234215c 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/ProlificSerialDriver.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/ProlificSerialDriver.java @@ -11,6 +11,7 @@ package org.emulator.calculator.usbserial.driver; import android.hardware.usb.UsbConstants; import android.hardware.usb.UsbDevice; +import android.hardware.usb.UsbDeviceConnection; import android.hardware.usb.UsbEndpoint; import android.hardware.usb.UsbInterface; import android.util.Log; @@ -34,7 +35,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { 28800, 38400, 57600, 115200, 128000, 134400, 161280, 201600, 230400, 268800, 403200, 460800, 614400, 806400, 921600, 1228800, 2457600, 3000000, 6000000 }; - protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX, DEVICE_TYPE_HXN } + protected enum DeviceType { DEVICE_TYPE_01, DEVICE_TYPE_T, DEVICE_TYPE_HX, DEVICE_TYPE_HXN} private final UsbDevice mDevice; private final UsbSerialPort mPort; @@ -122,7 +123,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { private volatile Thread mReadStatusThread = null; private final Object mReadStatusThreadLock = new Object(); private boolean mStopReadStatusThread = false; - private Exception mReadStatusException = null; + private IOException mReadStatusException = null; public ProlificSerialPort(UsbDevice device, int portNumber) { @@ -138,7 +139,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { byte[] buffer = new byte[length]; int result = mConnection.controlTransfer(requestType, request, value, index, buffer, length, USB_READ_TIMEOUT_MILLIS); if (result != length) { - throw new IOException(String.format("ControlTransfer %s 0x%x failed: %d",mDeviceType.name(), value, result)); + throw new IOException(String.format("ControlTransfer 0x%x failed: %d",value, result)); } return buffer; } @@ -147,7 +148,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { int length = (data == null) ? 0 : data.length; int result = mConnection.controlTransfer(requestType, request, value, index, data, length, USB_WRITE_TIMEOUT_MILLIS); if (result != length) { - throw new IOException( String.format("ControlTransfer %s 0x%x failed: %d", mDeviceType.name(), value, result)); + throw new IOException( String.format("ControlTransfer 0x%x failed: %d", value, result)); } } @@ -201,12 +202,12 @@ public class ProlificSerialDriver implements UsbSerialDriver { private void readStatusThreadFunction() { try { - byte[] buffer = new byte[STATUS_BUFFER_SIZE]; while (!mStopReadStatusThread) { + byte[] buffer = new byte[STATUS_BUFFER_SIZE]; long endTime = MonotonicClock.millis() + 500; int readBytesCount = mConnection.bulkTransfer(mInterruptEndpoint, buffer, STATUS_BUFFER_SIZE, 500); - if(readBytesCount == -1) - testConnection(MonotonicClock.millis() < endTime); + if(readBytesCount == -1 && MonotonicClock.millis() < endTime) + testConnection(); if (readBytesCount > 0) { if (readBytesCount != STATUS_BUFFER_SIZE) { throw new IOException("Invalid status notification, expected " + STATUS_BUFFER_SIZE + " bytes, got " + readBytesCount); @@ -217,9 +218,8 @@ public class ProlificSerialDriver implements UsbSerialDriver { } } } - } catch (Exception e) { - if (isOpen()) - mReadStatusException = e; + } catch (IOException e) { + mReadStatusException = e; } //Log.d(TAG, "end control line status thread " + mStopReadStatusThread + " " + (mReadStatusException == null ? "-" : mReadStatusException.getMessage())); } @@ -250,8 +250,8 @@ public class ProlificSerialDriver implements UsbSerialDriver { } } - /* throw and clear an exception which occurred in the status read thread */ - Exception readStatusException = mReadStatusException; + /* throw and clear an exception which occured in the status read thread */ + IOException readStatusException = mReadStatusException; if (mReadStatusException != null) { mReadStatusException = null; throw new IOException(readStatusException); @@ -265,10 +265,10 @@ public class ProlificSerialDriver implements UsbSerialDriver { } @Override - public void openInt() throws IOException { + public void openInt(UsbDeviceConnection connection) throws IOException { UsbInterface usbInterface = mDevice.getInterface(0); - if (!mConnection.claimInterface(usbInterface, true)) { + if (!connection.claimInterface(usbInterface, true)) { throw new IOException("Error claiming Prolific interface 0"); } @@ -290,7 +290,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { } } - byte[] rawDescriptors = mConnection.getRawDescriptors(); + byte[] rawDescriptors = connection.getRawDescriptors(); if(rawDescriptors == null || rawDescriptors.length < 14) { throw new IOException("Could not get device descriptors"); } @@ -299,19 +299,15 @@ public class ProlificSerialDriver implements UsbSerialDriver { byte maxPacketSize0 = rawDescriptors[7]; if (mDevice.getDeviceClass() == 0x02 || maxPacketSize0 != 64) { mDeviceType = DeviceType.DEVICE_TYPE_01; - } else if(usbVersion == 0x200) { - if(deviceVersion == 0x300 && testHxStatus()) { - mDeviceType = DeviceType.DEVICE_TYPE_T; // TA - } else if(deviceVersion == 0x500 && testHxStatus()) { - mDeviceType = DeviceType.DEVICE_TYPE_T; // TB - } else { - mDeviceType = DeviceType.DEVICE_TYPE_HXN; - } + } else if(deviceVersion == 0x300 && usbVersion == 0x200) { + mDeviceType = DeviceType.DEVICE_TYPE_T; // TA + } else if(deviceVersion == 0x500) { + mDeviceType = DeviceType.DEVICE_TYPE_T; // TB + } else if(usbVersion == 0x200 && !testHxStatus()) { + mDeviceType = DeviceType.DEVICE_TYPE_HXN; } else { mDeviceType = DeviceType.DEVICE_TYPE_HX; } - Log.d(TAG, String.format("usbVersion=%x, deviceVersion=%x, deviceClass=%d, packetSize=%d => deviceType=%s", - usbVersion, deviceVersion, mDevice.getDeviceClass(), maxPacketSize0, mDeviceType.name())); resetDevice(); doBlackMagic(); setControlLines(mControlLinesValue); @@ -567,7 +563,6 @@ public class ProlificSerialDriver implements UsbSerialDriver { } } - @SuppressWarnings({"unused"}) public static Map getSupportedDevices() { final Map supportedDevices = new LinkedHashMap<>(); supportedDevices.put(UsbId.VENDOR_PROLIFIC, @@ -576,6 +571,7 @@ public class ProlificSerialDriver implements UsbSerialDriver { UsbId.PROLIFIC_PL2303GC, UsbId.PROLIFIC_PL2303GB, UsbId.PROLIFIC_PL2303GT, + UsbId.PROLIFIC_PL2303GT3, UsbId.PROLIFIC_PL2303GL, UsbId.PROLIFIC_PL2303GE, UsbId.PROLIFIC_PL2303GS, diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/SerialTimeoutException.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/SerialTimeoutException.java index 41bae99..c45ebac 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/SerialTimeoutException.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/SerialTimeoutException.java @@ -9,8 +9,7 @@ import java.io.InterruptedIOException; * {@see InterruptedIOException#bytesTransferred} may contain bytes transferred */ public class SerialTimeoutException extends InterruptedIOException { - public SerialTimeoutException(String s, int bytesTransferred) { + public SerialTimeoutException(String s) { super(s); - this.bytesTransferred = bytesTransferred; } } diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbId.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbId.java index 755f008..b94206f 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbId.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbId.java @@ -23,6 +23,27 @@ public final class UsbId { public static final int FTDI_FT232H = 0x6014; public static final int FTDI_FT231X = 0x6015; // same ID for FT230X, FT231X, FT234XD + public static final int VENDOR_ATMEL = 0x03EB; + public static final int ATMEL_LUFA_CDC_DEMO_APP = 0x2044; + + public static final int VENDOR_ARDUINO = 0x2341; + public static final int ARDUINO_UNO = 0x0001; + public static final int ARDUINO_MEGA_2560 = 0x0010; + public static final int ARDUINO_SERIAL_ADAPTER = 0x003b; + public static final int ARDUINO_MEGA_ADK = 0x003f; + public static final int ARDUINO_MEGA_2560_R3 = 0x0042; + public static final int ARDUINO_UNO_R3 = 0x0043; + public static final int ARDUINO_MEGA_ADK_R3 = 0x0044; + public static final int ARDUINO_SERIAL_ADAPTER_R3 = 0x0044; + public static final int ARDUINO_LEONARDO = 0x8036; + public static final int ARDUINO_MICRO = 0x8037; + + public static final int VENDOR_VAN_OOIJEN_TECH = 0x16c0; + public static final int VAN_OOIJEN_TECH_TEENSYDUINO_SERIAL = 0x0483; + + public static final int VENDOR_LEAFLABS = 0x1eaf; + public static final int LEAFLABS_MAPLE = 0x0004; + public static final int VENDOR_SILABS = 0x10c4; public static final int SILABS_CP2102 = 0xea60; // same ID for CP2101, CP2103, CP2104, CP2109 public static final int SILABS_CP2105 = 0xea70; @@ -32,22 +53,22 @@ public final class UsbId { public static final int PROLIFIC_PL2303 = 0x2303; // device type 01, T, HX public static final int PROLIFIC_PL2303GC = 0x23a3; // device type HXN public static final int PROLIFIC_PL2303GB = 0x23b3; // " - public static final int PROLIFIC_PL2303GT = 0x23c3; // " - public static final int PROLIFIC_PL2303GL = 0x23d3; // " + public static final int PROLIFIC_PL2303GT = 0x23cd; // " + public static final int PROLIFIC_PL2303GT3 = 0x23c3; // " + public static final int PROLIFIC_PL2303GL = 0x23e3; // " public static final int PROLIFIC_PL2303GE = 0x23e3; // " public static final int PROLIFIC_PL2303GS = 0x23f3; // " - public static final int VENDOR_GOOGLE = 0x18d1; - public static final int GOOGLE_CR50 = 0x5014; - public static final int VENDOR_QINHENG = 0x1a86; public static final int QINHENG_CH340 = 0x7523; public static final int QINHENG_CH341A = 0x5523; - public static final int VENDOR_UNISOC = 0x1782; - public static final int FIBOCOM_L610 = 0x4D10; - public static final int FIBOCOM_L612 = 0x4D12; + // at www.linux-usb.org/usb.ids listed for NXP/LPC1768, but all processors supported by ARM mbed DAPLink firmware report these ids + public static final int VENDOR_ARM = 0x0d28; + public static final int ARM_MBED = 0x0204; + public static final int VENDOR_ST = 0x0483; + public static final int ST_CDC = 0x5740; private UsbId() { throw new IllegalAccessError("Non-instantiable class"); diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialDriver.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialDriver.java index df8912f..bbc761a 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialDriver.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialDriver.java @@ -10,17 +10,12 @@ import android.hardware.usb.UsbDevice; import java.util.List; +/** + * + * @author mike wakerly (opensource@hoho.com) + */ public interface UsbSerialDriver { - /* - * Additional interface properties. Invoked thru reflection. - * - UsbSerialDriver(UsbDevice device); // constructor with device - static Map getSupportedDevices(); - static boolean probe(UsbDevice device); // optional - */ - - /** * Returns the raw {@link UsbDevice} backing this port. * diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialPort.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialPort.java index c162ac8..03f1e6b 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialPort.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialPort.java @@ -58,7 +58,7 @@ public interface UsbSerialPort extends Closeable { int STOPBITS_2 = 2; /** Values for get[Supported]ControlLines() */ - enum ControlLine { RTS, CTS, DTR, DSR, CD, RI } + enum ControlLine { RTS, CTS, DTR, DSR, CD, RI } /** * Returns the driver used by this port. @@ -122,17 +122,6 @@ public interface UsbSerialPort extends Closeable { */ int read(final byte[] dest, final int timeout) throws IOException; - /** - * Reads bytes with specified length into the destination buffer. - * - * @param dest the destination byte buffer - * @param length the maximum length of the data to read - * @param timeout the timeout for reading in milliseconds, 0 is infinite - * @return the actual number of bytes read - * @throws IOException if an error occurred during reading - */ - int read(final byte[] dest, int length, final int timeout) throws IOException; - /** * Writes as many bytes as possible from the source buffer. * @@ -144,18 +133,6 @@ public interface UsbSerialPort extends Closeable { */ void write(final byte[] src, final int timeout) throws IOException; - /** - * Writes bytes with specified length from the source buffer. - * - * @param src the source byte buffer - * @param length the length of the data to write - * @param timeout the timeout for writing in milliseconds, 0 is infinite - * @throws SerialTimeoutException if timeout reached before sending all data. - * ex.bytesTransferred may contain bytes transferred - * @throws IOException if an error occurred during writing - */ - void write(final byte[] src, int length, final int timeout) throws IOException; - /** * Sets various serial port parameters. * diff --git a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialProber.java b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialProber.java index 13c8f4b..6755bb0 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialProber.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/driver/UsbSerialProber.java @@ -37,8 +37,6 @@ public class UsbSerialProber { probeTable.addDriver(FtdiSerialDriver.class); probeTable.addDriver(ProlificSerialDriver.class); probeTable.addDriver(Ch34xSerialDriver.class); - probeTable.addDriver(GsmModemSerialDriver.class); - probeTable.addDriver(ChromeCcdSerialDriver.class); return probeTable; } @@ -71,7 +69,11 @@ public class UsbSerialProber { * {@code null} if none available. */ public UsbSerialDriver probeDevice(final UsbDevice usbDevice) { - final Class driverClass = mProbeTable.findDriver(usbDevice); + final int vendorId = usbDevice.getVendorId(); + final int productId = usbDevice.getProductId(); + + final Class driverClass = + mProbeTable.findDriver(vendorId, productId); if (driverClass != null) { final UsbSerialDriver driver; try { diff --git a/app/src/main/java/org/emulator/calculator/usbserial/util/HexDump.java b/app/src/main/java/org/emulator/calculator/usbserial/util/HexDump.java deleted file mode 100644 index 42a1eeb..0000000 --- a/app/src/main/java/org/emulator/calculator/usbserial/util/HexDump.java +++ /dev/null @@ -1,158 +0,0 @@ -/* - * Copyright (C) 2006 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.emulator.calculator.usbserial.util; - -import java.security.InvalidParameterException; - -/** - * Clone of Android's /core/java/com/android/internal/util/HexDump class, for use in debugging. - * Changes: space separated hex strings - */ -public class HexDump { - private final static char[] HEX_DIGITS = { - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; - - private HexDump() { - } - - public static String dumpHexString(byte[] array) { - return dumpHexString(array, 0, array.length); - } - - public static String dumpHexString(byte[] array, int offset, int length) { - StringBuilder result = new StringBuilder(); - - byte[] line = new byte[8]; - int lineIndex = 0; - - for (int i = offset; i < offset + length; i++) { - if (lineIndex == line.length) { - for (int j = 0; j < line.length; j++) { - if (line[j] > ' ' && line[j] < '~') { - result.append(new String(line, j, 1)); - } else { - result.append("."); - } - } - - result.append("\n"); - lineIndex = 0; - } - - byte b = array[i]; - result.append(HEX_DIGITS[(b >>> 4) & 0x0F]); - result.append(HEX_DIGITS[b & 0x0F]); - result.append(" "); - - line[lineIndex++] = b; - } - - for (int i = 0; i < (line.length - lineIndex); i++) { - result.append(" "); - } - for (int i = 0; i < lineIndex; i++) { - if (line[i] > ' ' && line[i] < '~') { - result.append(new String(line, i, 1)); - } else { - result.append("."); - } - } - - return result.toString(); - } - - public static String toHexString(byte b) { - return toHexString(toByteArray(b)); - } - - public static String toHexString(byte[] array) { - return toHexString(array, 0, array.length); - } - - public static String toHexString(byte[] array, int offset, int length) { - char[] buf = new char[length > 0 ? length * 3 - 1 : 0]; - - int bufIndex = 0; - for (int i = offset; i < offset + length; i++) { - if (i > offset) - buf[bufIndex++] = ' '; - byte b = array[i]; - buf[bufIndex++] = HEX_DIGITS[(b >>> 4) & 0x0F]; - buf[bufIndex++] = HEX_DIGITS[b & 0x0F]; - } - - return new String(buf); - } - - public static String toHexString(int i) { - return toHexString(toByteArray(i)); - } - - public static String toHexString(short i) { - return toHexString(toByteArray(i)); - } - - public static byte[] toByteArray(byte b) { - byte[] array = new byte[1]; - array[0] = b; - return array; - } - - public static byte[] toByteArray(int i) { - byte[] array = new byte[4]; - - array[3] = (byte) (i & 0xFF); - array[2] = (byte) ((i >> 8) & 0xFF); - array[1] = (byte) ((i >> 16) & 0xFF); - array[0] = (byte) ((i >> 24) & 0xFF); - - return array; - } - - public static byte[] toByteArray(short i) { - byte[] array = new byte[2]; - - array[1] = (byte) (i & 0xFF); - array[0] = (byte) ((i >> 8) & 0xFF); - - return array; - } - - private static int toByte(char c) { - if (c >= '0' && c <= '9') - return (c - '0'); - if (c >= 'A' && c <= 'F') - return (c - 'A' + 10); - if (c >= 'a' && c <= 'f') - return (c - 'a' + 10); - - throw new InvalidParameterException("Invalid hex char '" + c + "'"); - } - - /** accepts any separator, e.g. space or newline */ - public static byte[] hexStringToByteArray(String hexString) { - int length = hexString.length(); - byte[] buffer = new byte[(length + 1) / 3]; - - for (int i = 0; i < length; i += 3) { - buffer[i / 3] = (byte) ((toByte(hexString.charAt(i)) << 4) | toByte(hexString.charAt(i + 1))); - } - - return buffer; - } -} diff --git a/app/src/main/java/org/emulator/calculator/usbserial/util/SerialInputOutputManager.java b/app/src/main/java/org/emulator/calculator/usbserial/util/SerialInputOutputManager.java index f37dfbe..1bb9cf3 100644 --- a/app/src/main/java/org/emulator/calculator/usbserial/util/SerialInputOutputManager.java +++ b/app/src/main/java/org/emulator/calculator/usbserial/util/SerialInputOutputManager.java @@ -9,7 +9,6 @@ package org.emulator.calculator.usbserial.util; import android.os.Process; import android.util.Log; -import org.emulator.calculator.usbserial.driver.SerialTimeoutException; import org.emulator.calculator.usbserial.driver.UsbSerialPort; import java.io.IOException; @@ -22,15 +21,8 @@ import java.nio.ByteBuffer; */ public class SerialInputOutputManager implements Runnable { - public enum State { - STOPPED, - RUNNING, - STOPPING - } - - public static boolean DEBUG = false; - private static final String TAG = SerialInputOutputManager.class.getSimpleName(); + public static boolean DEBUG = false; private static final int BUFSIZ = 4096; /** @@ -45,6 +37,12 @@ public class SerialInputOutputManager implements Runnable { private ByteBuffer mReadBuffer; // default size = getReadEndpoint().getMaxPacketSize() private ByteBuffer mWriteBuffer = ByteBuffer.allocate(BUFSIZ); + public enum State { + STOPPED, + RUNNING, + STOPPING + } + private int mThreadPriority = Process.THREAD_PRIORITY_URGENT_AUDIO; private State mState = State.STOPPED; // Synchronized by 'this' private Listener mListener; // Synchronized by 'this' @@ -204,11 +202,7 @@ public class SerialInputOutputManager implements Runnable { step(); } } catch (Exception e) { - if(mSerialPort.isOpen()) { - Log.w(TAG, "Run ending due to exception: " + e.getMessage(), e); - } else { - Log.i(TAG, "Socket closed"); - } + Log.w(TAG, "Run ending due to exception: " + e.getMessage(), e); final Listener listener = getListener(); if (listener != null) { listener.onRunError(e); @@ -229,9 +223,7 @@ public class SerialInputOutputManager implements Runnable { } int len = mSerialPort.read(buffer, mReadTimeout); if (len > 0) { - if (DEBUG) { - Log.d(TAG, "Read data len=" + len); - } + if (DEBUG) Log.d(TAG, "Read data len=" + len); final Listener listener = getListener(); if (listener != null) { final byte[] data = new byte[len]; @@ -255,23 +247,7 @@ public class SerialInputOutputManager implements Runnable { if (DEBUG) { Log.d(TAG, "Writing data len=" + len); } - try { - mSerialPort.write(buffer, mWriteTimeout); - } catch (SerialTimeoutException ex) { - synchronized (mWriteBufferLock) { - byte[] buffer2 = null; - int len2 = mWriteBuffer.position(); - if (len2 > 0) { - buffer2 = new byte[len2]; - mWriteBuffer.rewind(); - mWriteBuffer.get(buffer2, 0, len2); - mWriteBuffer.clear(); - } - mWriteBuffer.put(buffer, ex.bytesTransferred, buffer.length - ex.bytesTransferred); - if (buffer2 != null) - mWriteBuffer.put(buffer2); - } - } + mSerialPort.write(buffer, mWriteTimeout); } } diff --git a/app/src/main/java/org/emulator/calculator/usbserial/util/UsbUtils.java b/app/src/main/java/org/emulator/calculator/usbserial/util/UsbUtils.java deleted file mode 100644 index 69aae75..0000000 --- a/app/src/main/java/org/emulator/calculator/usbserial/util/UsbUtils.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.emulator.calculator.usbserial.util; - -import android.hardware.usb.UsbDeviceConnection; - -import java.util.ArrayList; - -public class UsbUtils { - - private UsbUtils() { - } - - public static ArrayList getDescriptors(UsbDeviceConnection connection) { - ArrayList descriptors = new ArrayList<>(); - byte[] rawDescriptors = connection.getRawDescriptors(); - if (rawDescriptors != null) { - int pos = 0; - while (pos < rawDescriptors.length) { - int len = rawDescriptors[pos] & 0xFF; - if (len == 0) - break; - if (pos + len > rawDescriptors.length) - len = rawDescriptors.length - pos; - byte[] descriptor = new byte[len]; - System.arraycopy(rawDescriptors, pos, descriptor, 0, len); - descriptors.add(descriptor); - pos += len; - } - } - return descriptors; - } - - -} diff --git a/app/src/main/java/org/emulator/forty/eight/MainActivity.java b/app/src/main/java/org/emulator/forty/eight/MainActivity.java index f72b2d5..d190de5 100644 --- a/app/src/main/java/org/emulator/forty/eight/MainActivity.java +++ b/app/src/main/java/org/emulator/forty/eight/MainActivity.java @@ -140,13 +140,13 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On // Most Recently Used state files private final int MRU_ID_START = 10000; private final int MAX_MRU = 5; - private LinkedHashMap mruLinkedHashMap = new LinkedHashMap(5, 1.0f, true) { + private final LinkedHashMap mruLinkedHashMap = new LinkedHashMap(5, 1.0f, true) { @Override protected boolean removeEldestEntry(Map.Entry eldest) { return size() > MAX_MRU; } }; - private HashMap mruByMenuId = new HashMap<>(); + private final HashMap mruByMenuId = new HashMap<>(); private final PrinterSimulator printerSimulator = new PrinterSimulator(); private final PrinterSimulatorFragment fragmentPrinterSimulator = new PrinterSimulatorFragment(); @@ -246,7 +246,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On } } - if(documentToOpenUrl != null && documentToOpenUrl.length() > 0) + if(documentToOpenUrl != null && !documentToOpenUrl.isEmpty()) try { // FileOpen auto-open. onFileOpen(documentToOpenUrl, intent, null); @@ -276,7 +276,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On for (int i = mrus.length - 1; i >= 0; i--) { String mostRecentlyUsedFile = mrus[i]; String displayName = getFilenameFromURL(mostRecentlyUsedFile); - if(displayName == null || displayName.equals("") || displayName.equals(mostRecentlyUsedFile)) { + if(displayName == null || displayName.isEmpty() || displayName.equals(mostRecentlyUsedFile)) { // We should remove this file because it seems impossible to get the display name of this Most Recently Used state file. // It might be deleted or the permissions does not allow to reach it anymore. mruLinkedHashMap.remove(mostRecentlyUsedFile); @@ -301,7 +301,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On if (NativeLib.isDocumentAvailable() && settings.getBoolean("settings_autosave", true)) { String currentFilename = NativeLib.getCurrentFilename(); - if (currentFilename != null && currentFilename.length() > 0) + if (currentFilename != null && !currentFilename.isEmpty()) onFileSave(); } @@ -1140,7 +1140,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On saveWhenLaunchingActivity = false; startActivityForResult(intent, INTENT_LOAD_FLASH_ROM); }; - if(currentFlashPort2Url != null && currentFlashPort2Url.length() > 0) + if(currentFlashPort2Url != null && !currentFlashPort2Url.isEmpty()) new AlertDialog.Builder(this) .setTitle(getString(R.string.alert_losing_flash_rom_title)) .setMessage(getString(R.string.alert_losing_flash_rom_message)) @@ -1165,8 +1165,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On // Reset to default Flash ROM from the KML file settings.putString("settings_flash_port2", null); String kmlFilename = NativeLib.getCurrentKml(); - if(kmlFilename.length() > 0) { - String kmlFolder = kmlFolderURL == null || kmlFolderURL.length() == 0 ? null : kmlFolderURL; + if(!kmlFilename.isEmpty()) { + String kmlFolder = kmlFolderURL == null || kmlFolderURL.isEmpty() ? null : kmlFolderURL; // Reset the flashROM NativeLib.onLoadFlashROM(""); // Load the KML file again. TODO If it goes wrong, we are lost. @@ -1237,7 +1237,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On updateFromPreferences("settings_flash_port2", true); displayFilename(url); String settingsFlashPort2Url = settings.getString("settings_flash_port2", null); - if(settingsFlashPort2Url != null && settingsFlashPort2Url.length() > 0) + if(settingsFlashPort2Url != null && !settingsFlashPort2Url.isEmpty()) showAlert(String.format(Locale.US, getString(R.string.message_state_and_flash_saved), getFilenameFromURL(url), getFilenameFromURL(settingsFlashPort2Url))); else showAlert(String.format(Locale.US, getString(R.string.message_state_saved), getFilenameFromURL(url))); @@ -1344,8 +1344,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On // Not possible to save the current FlashROM :-( [NativeLib.onSaveFlashROM(url);] // So, we are going to create a new one from the ROM loaded by the current KML script! String kmlFilename = NativeLib.getCurrentKml(); - if(kmlFilename != null && kmlFilename.length() > 0) { - if(kmlFolderURL != null && kmlFolderURL.length() > 0) + if(kmlFilename != null && !kmlFilename.isEmpty()) { + if(kmlFolderURL != null && !kmlFolderURL.isEmpty()) copyROMFromFolder(kmlFilename, uri); else copyROMFromAsset(kmlFilename, uri); @@ -1453,7 +1453,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On } } } - if(romFilename != null && romFilename.length() > 0) { + if(romFilename != null && !romFilename.isEmpty()) { ParcelFileDescriptor pfdROM = openFileInFolderFromContentResolverPFD(romFilename, kmlFolderURL, GENERIC_READ); if(pfdROM != null) { try { @@ -1479,7 +1479,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On try { kmlInputStream = assetManager.open("calculators/" + kmlFilename); String romFilename = extractROMFilename(kmlInputStream); - if(romFilename != null && romFilename.length() > 0) { + if(romFilename != null && !romFilename.isEmpty()) { InputStream romInputStream = assetManager.open("calculators/" + romFilename); copyROMtoFlashROM(romInputStream, uri); } @@ -1583,7 +1583,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On if(getPackageName().contains("org.emulator.forty.eight") && settings.getBoolean("settings_port2en", false)) { // Check if the access to the port2 shared file is still possible. String port2Url = settings.getString("settings_port2load", ""); - if(port2Url != null && port2Url.length() > 0) { + if(port2Url != null && !port2Url.isEmpty()) { Uri port2Uri = Uri.parse(port2Url); DocumentFile port2DocumentFile = DocumentFile.fromSingleUri(this, port2Uri); if (port2DocumentFile == null || !port2DocumentFile.exists()) { @@ -1706,7 +1706,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On updateFromPreferences("settings_flash_port2", true); String settingsFlashPort2Url = settings.getString("settings_flash_port2", null); - if(settingsFlashPort2Url != null && settingsFlashPort2Url.length() > 0) + if(settingsFlashPort2Url != null && !settingsFlashPort2Url.isEmpty()) showAlert(String.format(Locale.US, getString(R.string.message_state_and_flash_saved), getFilenameFromURL(currentFilenameUrl), getFilenameFromURL(settingsFlashPort2Url))); else showAlert(String.format(Locale.US, getString(R.string.message_state_saved), getFilenameFromURL(currentFilenameUrl))); @@ -1716,7 +1716,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On private void displayFilename(String stateFileURL) { String displayName = getFilenameFromURL(stateFileURL == null ? "" : stateFileURL); String port2FileURL = settings.getString("settings_flash_port2", null); - if(port2FileURL != null && port2FileURL.length() > 0) + if(port2FileURL != null && !port2FileURL.isEmpty()) displayName += " " + getFilenameFromURL(port2FileURL); View headerView = displayKMLTitle(); if(headerView != null) { @@ -2082,14 +2082,14 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On } private int serialIndex = 1; - private HashMap serialsById = new HashMap<>(); + private final HashMap serialsById = new HashMap<>(); @SuppressWarnings("UnusedDeclaration") int openSerialPort(String serialPort) { // Search if this same serial port is not already opened - Integer serialPortId = serialIndex; + int serialPortId = serialIndex; Serial serial = new Serial(this, serialPortId); if(serial.connect(serialPort)) { serialsById.put(serialPortId, serial); @@ -2104,10 +2104,10 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On String connectionStatus = serial.getConnectionStatus(); try { int resId = Utils.resId(MainActivity.this, "string", connectionStatus); - Toast.makeText(MainActivity.this, resId, Toast.LENGTH_LONG).show(); + Toast.makeText(MainActivity.this, resId, Toast.LENGTH_SHORT).show(); } catch (Exception ex) { - Log.e(TAG, ex.getMessage()); - Toast.makeText(MainActivity.this, "Unknown error, connectionStatus: " + connectionStatus, Toast.LENGTH_LONG).show(); + Log.e(TAG, "Unknown error, connectionStatus: " + connectionStatus + ", " + ex.getMessage()); + Toast.makeText(MainActivity.this, "Unknown error, connectionStatus: " + connectionStatus, Toast.LENGTH_SHORT).show(); } }); return 0; @@ -2200,7 +2200,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On } private void setPort1Settings(boolean port1Plugged, boolean port1Writable) { - if(this.getClass().getPackage().getName().equals("org.emulator.forty.eight")) { + Package pack = this.getClass().getPackage(); + if(pack != null && pack.getName().equals("org.emulator.forty.eight")) { settings.putBoolean("settings_port1en", port1Plugged); settings.putBoolean("settings_port1wr", port1Writable); updateFromPreferences("settings_port1", true); @@ -2224,7 +2225,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On switch (key) { case "settings_realspeed": case "settings_grayscale": - NativeLib.setConfiguration(key, isDynamicValue, settings.getBoolean(key, false) ? 1 : 0, 0, null); + case "settings_serial_slowdown": + NativeLib.setConfiguration(key, isDynamicValue, settings.getBoolean(key, false) ? 1 : 0, 0, null); break; case "settings_rotation": @@ -2347,9 +2349,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On NativeLib.setConfiguration("settings_serial_ports_ir", isDynamicValue, 0, 0, DevicesFragment.SerialConnectParameters.fromSettingsString(settings.getString("settings_serial_ports_ir", "")).toWin32String()); break; - case "settings_serial_slowdown": - NativeLib.setConfiguration(key, isDynamicValue, settings.getBoolean(key, false) ? 1 : 0, 0, null); - break; } } } diff --git a/build.gradle b/build.gradle index bf9b331..cbacbf7 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { mavenCentral() } dependencies { - classpath 'com.android.tools.build:gradle:8.4.2' + classpath 'com.android.tools.build:gradle:8.6.1' // NOTE: Do not place your application dependencies here; they belong diff --git a/gradle.properties b/gradle.properties index 70517d2..0471563 100644 --- a/gradle.properties +++ b/gradle.properties @@ -6,7 +6,7 @@ # http://www.gradle.org/docs/current/userguide/build_environment.html # Specifies the JVM arguments used for the daemon process. # The setting is particularly useful for tweaking memory settings. -android.defaults.buildfeatures.buildconfig=true +#android.defaults.buildfeatures.buildconfig=true android.enableJetifier=true android.nonFinalResIds=true android.nonTransitiveRClass=true diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 3f37000..534e239 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ #Sat Jan 28 21:16:38 CET 2023 distributionBase=GRADLE_USER_HOME -distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip distributionPath=wrapper/dists zipStorePath=wrapper/dists zipStoreBase=GRADLE_USER_HOME