From c6d1648cd7cc651ebbec1a40377c0118ea30c9ca Mon Sep 17 00:00:00 2001 From: dgis Date: Sat, 1 Dec 2018 23:28:39 +0000 Subject: [PATCH] --- app/src/main/cpp/android-emu48.c | 120 +++++--- app/src/main/cpp/emu48-jni.c | 58 +++- app/src/main/cpp/win32-layer.c | 150 ++++++--- app/src/main/cpp/win32-layer.h | 16 +- .../regis/cosnier/emu48/MainScreenView.java | 287 +++++++++--------- .../com/regis/cosnier/emu48/NativeLib.java | 5 + 6 files changed, 400 insertions(+), 236 deletions(-) diff --git a/app/src/main/cpp/android-emu48.c b/app/src/main/cpp/android-emu48.c index 993a589..437d2f6 100644 --- a/app/src/main/cpp/android-emu48.c +++ b/app/src/main/cpp/android-emu48.c @@ -12,6 +12,7 @@ #include "io.h" #include "kml.h" #include "debugger.h" +#include "win32-layer.h" #define VERSION "1.59+" @@ -859,54 +860,54 @@ static LRESULT OnDestroy(HWND hWindow) // static LRESULT OnPaint(HWND hWindow) { -// PAINTSTRUCT Paint; -// HDC hPaintDC; -// -// UpdateWindowBars(); // update visibility of title and menu bar -// -// hPaintDC = BeginPaint(hWindow, &Paint); -// if (hMainDC != NULL) -// { -// RECT rcMainPaint = Paint.rcPaint; -// rcMainPaint.left += nBackgroundX; // coordinates in source bitmap -// rcMainPaint.top += nBackgroundY; -// rcMainPaint.right += nBackgroundX; -// rcMainPaint.bottom += nBackgroundY; -// -// EnterCriticalSection(&csGDILock); // solving NT GDI problems -// { -// UINT nLines = MAINSCREENHEIGHT; -// -// // redraw background bitmap -// BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top, -// Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top, -// hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY); -// -// // CdB for HP: add apples display stuff -// SetWindowOrgEx(hPaintDC, nBackgroundX, nBackgroundY, NULL); -// -// // redraw header display area -// StretchBlt(hPaintDC, nLcdX, nLcdY, -// 131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom, -// hLcdDC, Chipset.d0offset, 0, -// 131, Chipset.d0size, SRCCOPY); -// // redraw main display area -// StretchBlt(hPaintDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom*nGdiYZoom, -// 131*nLcdZoom*nGdiXZoom, nLines*nLcdZoom*nGdiYZoom, -// hLcdDC, Chipset.boffset, Chipset.d0size, -// 131, nLines, SRCCOPY); -// // redraw menu display area -// StretchBlt(hPaintDC, nLcdX, nLcdY+(nLines+Chipset.d0size)*nLcdZoom*nGdiYZoom, -// 131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom, -// hLcdDC, 0, (nLines+Chipset.d0size), -// 131, MENUHEIGHT, SRCCOPY); -// GdiFlush(); -// } -// LeaveCriticalSection(&csGDILock); -// UpdateAnnunciators(); -// RefreshButtons(&rcMainPaint); -// } -// EndPaint(hWindow, &Paint); + PAINTSTRUCT Paint; + HDC hPaintDC; + + UpdateWindowBars(); // update visibility of title and menu bar + + hPaintDC = BeginPaint(hWindow, &Paint); + if (hMainDC != NULL) + { + RECT rcMainPaint = Paint.rcPaint; + rcMainPaint.left += nBackgroundX; // coordinates in source bitmap + rcMainPaint.top += nBackgroundY; + rcMainPaint.right += nBackgroundX; + rcMainPaint.bottom += nBackgroundY; + + EnterCriticalSection(&csGDILock); // solving NT GDI problems + { + UINT nLines = MAINSCREENHEIGHT; + + // redraw background bitmap + BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top, + Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top, + hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY); + + // CdB for HP: add apples display stuff + SetWindowOrgEx(hPaintDC, nBackgroundX, nBackgroundY, NULL); + + // redraw header display area + StretchBlt(hPaintDC, nLcdX, nLcdY, + 131*nLcdZoom*nGdiXZoom, Chipset.d0size*nLcdZoom*nGdiYZoom, + hLcdDC, Chipset.d0offset, 0, + 131, Chipset.d0size, SRCCOPY); + // redraw main display area + StretchBlt(hPaintDC, nLcdX, nLcdY+Chipset.d0size*nLcdZoom*nGdiYZoom, + 131*nLcdZoom*nGdiXZoom, nLines*nLcdZoom*nGdiYZoom, + hLcdDC, Chipset.boffset, Chipset.d0size, + 131, nLines, SRCCOPY); + // redraw menu display area + StretchBlt(hPaintDC, nLcdX, nLcdY+(nLines+Chipset.d0size)*nLcdZoom*nGdiYZoom, + 131*nLcdZoom*nGdiXZoom, MENUHEIGHT*nLcdZoom*nGdiYZoom, + hLcdDC, 0, (nLines+Chipset.d0size), + 131, MENUHEIGHT, SRCCOPY); + GdiFlush(); + } + LeaveCriticalSection(&csGDILock); + UpdateAnnunciators(); + RefreshButtons(&rcMainPaint); + } + EndPaint(hWindow, &Paint); return 0; } @@ -2246,6 +2247,8 @@ BOOL emu48Start() // no default document, ask for new one if (NewDocument()) SetWindowTitle(_T("Untitled")); + //BitBlt(hWindowDC, 0, 0, hMainDC->selectedBitmap->bitmapInfoHeader->biWidth, hMainDC->selectedBitmap->bitmapInfoHeader->biHeight, hMainDC, 0, 0, 0); + OnPaint(NULL); //start: if (bStartupBackup) SaveBackup(); // make a RAM backup at startup if (pbyRom) SwitchToState(SM_RUN); @@ -2302,3 +2305,24 @@ BOOL emu48Start() // lstrcpy(szCurrentKml, "hello.kml"); // return TRUE; //} + +void draw() { + OnPaint(NULL); +} + +INT nMacroState = MACRO_OFF; + +void buttonDown(int x, int y) { + OnLButtonDown(0, x, y); +} + +void buttonUp(int x, int y) { + OnLButtonUp(0, x, y); +} + +void keyDown(int virtKey) { + OnKeyDown(virtKey, 0); +} +void keyUp(int virtKey) { + OnKeyUp(virtKey, 0); +} diff --git a/app/src/main/cpp/emu48-jni.c b/app/src/main/cpp/emu48-jni.c index 57cc67e..8ebe7cf 100644 --- a/app/src/main/cpp/emu48-jni.c +++ b/app/src/main/cpp/emu48-jni.c @@ -19,16 +19,28 @@ extern void emu48Start(); extern AAssetManager * assetManager; static jobject viewToUpdate = NULL; jobject bitmapMainScreen; +AndroidBitmapInfo androidBitmapInfo; // https://stackoverflow.com/questions/9630134/jni-how-to-callback-from-c-or-c-to-java void mainViewUpdateCallback() { if (viewToUpdate) { - JNIEnv *jni; - jint result = (*java_machine)->AttachCurrentThread(java_machine, &jni, NULL); - jclass viewToUpdateClass = (*jni)->GetObjectClass(jni, viewToUpdate); - jmethodID midStr = (*jni)->GetMethodID(jni, viewToUpdateClass, "updateCallback", "()V"); - (*jni)->CallVoidMethod(jni, viewToUpdate, midStr); - result = (*java_machine)->DetachCurrentThread(java_machine); + JNIEnv * jniEnv; + jint ret; + BOOL needDetach = FALSE; + ret = (*java_machine)->GetEnv(java_machine, &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; + } + } + + jclass viewToUpdateClass = (*jniEnv)->GetObjectClass(jniEnv, viewToUpdate); + jmethodID midStr = (*jniEnv)->GetMethodID(jniEnv, viewToUpdateClass, "updateCallback", "()V"); + (*jniEnv)->CallVoidMethod(jniEnv, viewToUpdate, midStr); +// if(needDetach) +// ret = (*java_machine)->DetachCurrentThread(java_machine); } } @@ -38,6 +50,11 @@ JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_start(JNIEnv *env, viewToUpdate = (*env)->NewGlobalRef(env, view); bitmapMainScreen = (*env)->NewGlobalRef(env, bitmapMainScreen0); + int ret = AndroidBitmap_getInfo(env, bitmapMainScreen, &androidBitmapInfo); + if (ret < 0) { + LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); + } + assetManager = AAssetManager_fromJava(env, assetMgr); emu48Start(); } @@ -57,4 +74,31 @@ JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_stop(JNIEnv *env, JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_resize(JNIEnv *env, jobject thisz, jint width, jint height) { -} \ No newline at end of file +} + +extern void draw(); +extern void buttonDown(int x, int y); +extern void buttonUp(int x, int y); +extern void keyDown(int virtKey); +extern void keyUp(int virtKey); + +JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_draw(JNIEnv *env, jobject thisz) { + draw(); +} +JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_buttonDown(JNIEnv *env, jobject thisz, jint x, jint y) { + buttonDown(x, y); +} +JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_buttonUp(JNIEnv *env, jobject thisz, jint x, jint y) { + buttonUp(x, y); +} +JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_keyDown(JNIEnv *env, jobject thisz, jint virtKey) { + keyDown(virtKey); +} +JNIEXPORT void JNICALL Java_com_regis_cosnier_emu48_NativeLib_keyUp(JNIEnv *env, jobject thisz, jint virtKey) { + keyUp(virtKey); +} + +//p Read5(0x7050E) +// -> $1 = 461076 +//p Read5(0x70914) +// -> 31 ? \ No newline at end of file diff --git a/app/src/main/cpp/win32-layer.c b/app/src/main/cpp/win32-layer.c index f3d8c01..10b8b8c 100644 --- a/app/src/main/cpp/win32-layer.c +++ b/app/src/main/cpp/win32-layer.c @@ -4,11 +4,15 @@ #include #include #include +#include #include "resource.h" #include "win32-layer.h" extern JavaVM *java_machine; extern jobject bitmapMainScreen; +extern AndroidBitmapInfo androidBitmapInfo; +extern UINT nBackgroundW; +extern UINT nBackgroundH; HANDLE hWnd; LPTSTR szTitle; @@ -16,6 +20,7 @@ LPTSTR szCurrentDirectorySet = NULL; const TCHAR * assetsPrefix = _T("assets/"), assetsPrefixLength = 7; AAssetManager * assetManager; +static HDC mainPaintDC = NULL; VOID OutputDebugString(LPCSTR lpOutputString) { LOGD("%s", lpOutputString); @@ -56,6 +61,7 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, } if(asset) { HANDLE handle = malloc(sizeof(_HANDLE)); + memset(handle, 0, sizeof(_HANDLE)); handle->handleType = HANDLE_TYPE_FILE_ASSET; handle->fileAsset = asset; return handle; @@ -98,6 +104,7 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode, } if (fd != -1) { HANDLE handle = malloc(sizeof(_HANDLE)); + memset(handle, 0, sizeof(_HANDLE)); handle->handleType = HANDLE_TYPE_FILE; handle->fileDescriptor = fd; return handle; @@ -170,6 +177,7 @@ DWORD GetFileSize(HANDLE hFile, LPDWORD lpFileSizeHigh) { //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) { HANDLE handle = malloc(sizeof(_HANDLE)); + memset(handle, 0, sizeof(_HANDLE)); if(hFile->handleType == HANDLE_TYPE_FILE) { handle->handleType = HANDLE_TYPE_FILE_MAPPING; handle->fileDescriptor = hFile->fileDescriptor; @@ -214,6 +222,7 @@ BOOL UnmapViewOfFile(LPCVOID lpBaseAddress) { HANDLE CreateEvent(LPVOID lpEventAttributes, BOOL bManualReset, BOOL bInitialState, LPCTSTR name) { HANDLE handle = malloc(sizeof(_HANDLE)); + memset(handle, 0, sizeof(_HANDLE)); handle->handleType = HANDLE_TYPE_EVENT; int result = pthread_cond_init(&(handle->eventCVariable), 0); @@ -345,10 +354,11 @@ HANDLE CreateThread(LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize //http://man7.org/linux/man-pages/man3/pthread_create.3.html int pthreadResult = pthread_create(&threadId, &attr, /*(void*(*)(void*))*/lpStartAddress, lpParameter); if(pthreadResult == 0) { - HANDLE result = malloc(sizeof(_HANDLE)); - result->handleType = HANDLE_TYPE_THREAD; - result->threadId = threadId; - return result; + HANDLE handle = malloc(sizeof(_HANDLE)); + memset(handle, 0, sizeof(_HANDLE)); + handle->handleType = HANDLE_TYPE_THREAD; + handle->threadId = threadId; + return handle; } return NULL; } @@ -654,12 +664,12 @@ HGDIOBJ SelectObject(HDC hdc, HGDIOBJ h) { break; case HGDIOBJ_TYPE_BITMAP: hdc->selectedBitmap = h; - break; + return h; case HGDIOBJ_TYPE_REGION: break; case HGDIOBJ_TYPE_PALETTE: hdc->selectedPalette = h; - break; + return h; } return NULL; } @@ -695,10 +705,11 @@ HGDIOBJ GetStockObject(int i) { return NULL; } HPALETTE CreatePalette(CONST LOGPALETTE * plpal) { - HGDIOBJ newHDC = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); - newHDC->handleType = HGDIOBJ_TYPE_PALETTE; - newHDC->paletteLog = (PLOGPALETTE)plpal; // Can be free -> we have to make a copy - return newHDC; + HGDIOBJ handle = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); + memset(handle, 0, sizeof(_HGDIOBJ)); + handle->handleType = HGDIOBJ_TYPE_PALETTE; + handle->paletteLog = (PLOGPALETTE)plpal; // Can be free -> we have to make a copy + return handle; } HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd) { hdc->selectedPalette = hPal; @@ -712,14 +723,16 @@ UINT RealizePalette(HDC hdc) { // DC HDC CreateCompatibleDC(HDC hdc) { - HDC newHDC = (HDC)malloc(sizeof(struct _HDC)); - newHDC->handleType = HDC_TYPE_DC; - newHDC->hdcCompatible = hdc; - return newHDC; + HDC handle = (HDC)malloc(sizeof(struct _HDC)); + memset(handle, 0, sizeof(struct _HDC)); + handle->handleType = HDC_TYPE_DC; + handle->hdcCompatible = hdc; + return handle; } BOOL DeleteDC(HDC hdc) { - //TODO - return 0; + memset(hdc, 0, sizeof(struct _HDC)); + free(hdc); + return TRUE; } BOOL MoveToEx(HDC hdc, int x, int y, LPPOINT lppt) { //TODO @@ -734,8 +747,13 @@ BOOL PatBlt(HDC hdc, int x, int y, int w, int h, DWORD rop) { return 0; } BOOL BitBlt(HDC hdc, int x, int y, int cx, int cy, HDC hdcSrc, int x1, int y1, DWORD rop) { - mainViewUpdateCallback(); - return 0; + 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 @@ -743,14 +761,19 @@ int SetStretchBltMode(HDC hdc, int mode) { } BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdcSrc, int xSrc, int ySrc, int wSrc, int hSrc, DWORD rop) { - if(hdcDest->hdcCompatible == NULL && hdcSrc->selectedBitmap) { + if(hdcDest->hdcCompatible == NULL && hdcSrc->selectedBitmap && hDest && hSrc) { // We update the main window - JNIEnv * jniEnv; - jint ret = (*java_machine)->AttachCurrentThread(java_machine, &jniEnv, NULL); - AndroidBitmapInfo androidBitmapInfo; - if ((ret = AndroidBitmap_getInfo(jniEnv, bitmapMainScreen, &androidBitmapInfo)) < 0) { - LOGE("AndroidBitmap_getInfo() failed ! error=%d", ret); + JNIEnv * jniEnv; + jint ret; + BOOL needDetach = FALSE; + ret = (*java_machine)->GetEnv(java_machine, &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; + } } void * pixelsDestination; @@ -760,7 +783,6 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc HBITMAP hBitmap = hdcSrc->selectedBitmap; - //void * pixelsSource = hBitmap->bitmapInfo->bmiColors; void * pixelsSource = hBitmap->bitmapBits; int sourceWidth = hBitmap->bitmapInfoHeader->biWidth; @@ -777,8 +799,10 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc float dst_maxy = yDest + hDest; float src_cury = ySrc; - float sourceStride = sourceWidth * 4; - float destinationStride = androidBitmapInfo.stride; + int sourceBytes = (hBitmap->bitmapInfoHeader->biBitCount >> 3); + float sourceStride = sourceWidth * sourceBytes; + float destinationStride = androidBitmapInfo.stride; // Destination always 4 bytes RGBA + LOGD("StretchBlt(%08x, x:%d, y:%d, w:%d, h:%d, %08x, x:%d, y:%d, w:%d, h:%d) -> sourceBytes: %d", hdcDest->hdcCompatible, xDest, yDest, wDest, hDest, hdcSrc, xSrc, ySrc, wSrc, hSrc, sourceBytes); for (float y = yDest; y < dst_maxy; y++) { @@ -789,8 +813,28 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc //dst.bmp[x,y] = src.bmp[src_curx, src_cury]; BYTE * destinationPixel = pixelsDestination + (int)(4.0 * x + destinationStride * y); - BYTE * sourcePixel = pixelsSource + (int)(4.0 * src_curx + sourceStride * src_cury); - memcpy(destinationPixel, sourcePixel, 4); + BYTE * sourcePixel = pixelsSource + (int)(sourceBytes * src_curx + sourceStride * src_cury); + + // -> ARGB_8888 + switch (sourceBytes) { + case 1: + destinationPixel[0] = sourcePixel[0]; + destinationPixel[1] = sourcePixel[0]; + destinationPixel[2] = sourcePixel[0]; + destinationPixel[3] = 255; + break; + case 3: + destinationPixel[0] = sourcePixel[0]; + destinationPixel[1] = sourcePixel[1]; + destinationPixel[2] = sourcePixel[2]; + destinationPixel[3] = 255; + break; + case 4: + memcpy(destinationPixel, sourcePixel, sourceBytes); + break; + default: + break; + } src_curx += src_dx; } @@ -800,11 +844,13 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc AndroidBitmap_unlockPixels(jniEnv, bitmapMainScreen); - ret = (*java_machine)->DetachCurrentThread(java_machine); +// if(needDetach) +// ret = (*java_machine)->DetachCurrentThread(java_machine); mainViewUpdateCallback(); + return TRUE; } - return 0; + return FALSE; } UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq) { //TODO @@ -812,14 +858,32 @@ UINT SetDIBColorTable(HDC hdc, UINT iStart, UINT cEntries, CONST RGBQUAD *prgbq } HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CONST VOID *pjBits, CONST BITMAPINFO *pbmi, UINT iUsage) { HGDIOBJ newHDC = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); + memset(newHDC, 0, sizeof(_HGDIOBJ)); newHDC->handleType = HGDIOBJ_TYPE_BITMAP; - newHDC->bitmapInfo = pbmi; - newHDC->bitmapInfoHeader = pbmih; - newHDC->bitmapBits = pjBits; + BITMAPINFO * newBitmapInfo = malloc(sizeof(BITMAPINFO)); + memcpy(newBitmapInfo, pbmi, sizeof(BITMAPINFO)); + newHDC->bitmapInfo = newBitmapInfo; + newHDC->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo; + size_t stride = (size_t)(newBitmapInfo->bmiHeader.biWidth * (newBitmapInfo->bmiHeader.biBitCount >> 3)); + size_t size = newBitmapInfo->bmiHeader.biSizeImage ? + newBitmapInfo->bmiHeader.biSizeImage : + newBitmapInfo->bmiHeader.biHeight * stride; + VOID * bitmapBits = malloc(size); + //memcpy(bitmapBits, pjBits, size); + // Switch Y + VOID * bitmapBitsSource = (VOID *)pjBits; + VOID * bitmapBitsDestination = bitmapBits + (newBitmapInfo->bmiHeader.biHeight - 1) * stride; + for(int y = 0; y < newBitmapInfo->bmiHeader.biHeight; y++) { + memcpy(bitmapBitsDestination, bitmapBitsSource, stride); + bitmapBitsSource += stride; + bitmapBitsDestination -= stride; + } + newHDC->bitmapBits = bitmapBits; return newHDC; } HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) { HGDIOBJ newHDC = (HGDIOBJ)malloc(sizeof(_HGDIOBJ)); + memset(newHDC, 0, sizeof(_HGDIOBJ)); newHDC->handleType = HGDIOBJ_TYPE_BITMAP; newHDC->bitmapInfo = pbmi; newHDC->bitmapInfoHeader = pbmi; @@ -850,10 +914,28 @@ HRGN ExtCreateRegion(CONST XFORM * lpx, DWORD nCount, CONST RGNDATA * lpData) { return NULL; } BOOL GdiFlush(void) { + //mainViewUpdateCallback(); + return 0; +} +HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint) { + if(!mainPaintDC) + mainPaintDC = CreateCompatibleDC(NULL); + if(lpPaint) { + memset(lpPaint, 0, sizeof(PAINTSTRUCT)); + lpPaint->fErase = TRUE; + lpPaint->hdc = mainPaintDC; + lpPaint->rcPaint.right = nBackgroundW; //androidBitmapInfo.width; // - 1; + lpPaint->rcPaint.bottom = nBackgroundH; //androidBitmapInfo.height; // - 1; + } + return mainPaintDC; +} +BOOL EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint) { //TODO return 0; } +// Window + BOOL WINAPI MessageBeep(UINT uType) { //TODO System beep return 1; diff --git a/app/src/main/cpp/win32-layer.h b/app/src/main/cpp/win32-layer.h index eb20808..b3b8c64 100644 --- a/app/src/main/cpp/win32-layer.h +++ b/app/src/main/cpp/win32-layer.h @@ -574,8 +574,8 @@ extern HPALETTE CreatePalette(CONST LOGPALETTE * plpal); // DC enum HDC_TYPE { - HDC_TYPE_DC = 1, - HDC_TYPE_FILE_ASSET + HDC_TYPE_INVALID = 0, + HDC_TYPE_DC }; struct _HDC; typedef struct _HDC * HDC; @@ -622,7 +622,6 @@ typedef struct _RGNDATAHEADER { DWORD nRgnSize; RECT rcBound; } RGNDATAHEADER, *PRGNDATAHEADER; - typedef struct _RGNDATA { RGNDATAHEADER rdh; char Buffer[1]; @@ -648,6 +647,17 @@ typedef struct tagXFORM extern int SetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw); extern HRGN ExtCreateRegion(CONST XFORM * lpx, DWORD nCount, CONST RGNDATA * lpData); extern BOOL GdiFlush(void); +typedef struct tagPAINTSTRUCT { + HDC hdc; + BOOL fErase; + RECT rcPaint; + BOOL fRestore; + BOOL fIncUpdate; + BYTE rgbReserved[32]; +} PAINTSTRUCT, *PPAINTSTRUCT, *NPPAINTSTRUCT, *LPPAINTSTRUCT; +extern HDC BeginPaint(HWND hWnd, LPPAINTSTRUCT lpPaint); +extern BOOL EndPaint(HWND hWnd, CONST PAINTSTRUCT *lpPaint); + // Window diff --git a/app/src/main/java/com/regis/cosnier/emu48/MainScreenView.java b/app/src/main/java/com/regis/cosnier/emu48/MainScreenView.java index 577dd66..b0c7de5 100644 --- a/app/src/main/java/com/regis/cosnier/emu48/MainScreenView.java +++ b/app/src/main/java/com/regis/cosnier/emu48/MainScreenView.java @@ -10,6 +10,7 @@ import android.graphics.Color; import android.graphics.Paint; import android.support.v4.view.ViewCompat; import android.util.DisplayMetrics; +import android.util.Log; import android.view.GestureDetector; import android.view.InputDevice; import android.view.KeyEvent; @@ -19,10 +20,14 @@ import android.view.SurfaceView; import android.view.View; import android.widget.OverScroller; +import java.util.HashMap; +import java.util.Map; + public class MainScreenView extends SurfaceView { protected static final String TAG = "MainScreenView"; private Bitmap bitmapMainScreen; + private HashMap vkmap; public MainScreenView(Context context) { super(context); @@ -32,6 +37,7 @@ public class MainScreenView extends SurfaceView { DisplayMetrics displayMetrics = new DisplayMetrics(); ((Activity)context).getWindowManager().getDefaultDisplay().getMetrics(displayMetrics); bitmapMainScreen = Bitmap.createBitmap(displayMetrics.widthPixels, displayMetrics.heightPixels, Bitmap.Config.ARGB_8888); + bitmapMainScreen.eraseColor(Color.LTGRAY); NativeLib.start(mgr, bitmapMainScreen, this); commonInitialize(context); @@ -40,12 +46,10 @@ public class MainScreenView extends SurfaceView { /** * Common initialize method. * @param context The activity context. - * @param currentProject The current project. */ private void commonInitialize(Context context) { -// //this.mContext = context; -// this.currentProject = currentProject; -// + //this.mContext = context; + // // Prevent the out of memory in OpenGL with Tegra 2 devices // //if(!Utils.hasHighMemory(context)) // setLayerType(View.LAYER_TYPE_SOFTWARE, null); @@ -59,7 +63,7 @@ public class MainScreenView extends SurfaceView { // paint.setStyle(Paint.Style.STROKE); // paint.setStrokeWidth(1.0f * mScreenDensity); // paint.setAntiAlias(mAntiAliased); -// + // mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() { // // @Override @@ -89,79 +93,123 @@ public class MainScreenView extends SurfaceView { // } // // }); -// -// this.setFocusable(true); -// this.setFocusableInTouchMode(true); -// + + vkmap = new HashMap(); + vkmap.put(KeyEvent.KEYCODE_BACK, 0x08); // VK_BACK + vkmap.put(KeyEvent.KEYCODE_TAB, 0x09); // VK_TAB + vkmap.put(KeyEvent.KEYCODE_ENTER, 0x0D); // VK_RETURN + vkmap.put(KeyEvent.KEYCODE_NUMPAD_ENTER, 0x0D); // VK_RETURN + vkmap.put(KeyEvent.KEYCODE_DEL, 0x2E); // VK_DELETE + vkmap.put(KeyEvent.KEYCODE_INSERT, 0x2D); // VK_INSERT + vkmap.put(KeyEvent.KEYCODE_SHIFT_LEFT, 0x10); // VK_SHIFT + vkmap.put(KeyEvent.KEYCODE_SHIFT_RIGHT, 0x10); // VK_SHIFT + vkmap.put(KeyEvent.KEYCODE_CTRL_LEFT, 0x11); // VK_CONTROL + vkmap.put(KeyEvent.KEYCODE_CTRL_RIGHT, 0x11); // VK_CONTROL + vkmap.put(KeyEvent.KEYCODE_ESCAPE, 0x1B); // VK_ESCAPE + vkmap.put(KeyEvent.KEYCODE_SPACE, 0x20); // VK_SPACE + vkmap.put(KeyEvent.KEYCODE_DPAD_LEFT, 0x25); // VK_LEFT + vkmap.put(KeyEvent.KEYCODE_DPAD_UP, 0x26); // VK_UP + vkmap.put(KeyEvent.KEYCODE_DPAD_RIGHT, 0x27); // VK_RIGHT + vkmap.put(KeyEvent.KEYCODE_DPAD_DOWN, 0x28); // VK_DOWN + vkmap.put(KeyEvent.KEYCODE_0, 0x30); // 0 + vkmap.put(KeyEvent.KEYCODE_1, 0x31); // 1 + vkmap.put(KeyEvent.KEYCODE_2, 0x32); // 2 + vkmap.put(KeyEvent.KEYCODE_3, 0x33); // 3 + vkmap.put(KeyEvent.KEYCODE_4, 0x34); // 4 + vkmap.put(KeyEvent.KEYCODE_5, 0x35); // 5 + vkmap.put(KeyEvent.KEYCODE_6, 0x36); // 6 + vkmap.put(KeyEvent.KEYCODE_7, 0x37); // 7 + vkmap.put(KeyEvent.KEYCODE_8, 0x38); // 8 + vkmap.put(KeyEvent.KEYCODE_9, 0x39); // 9 + vkmap.put(KeyEvent.KEYCODE_A, 0x41); // A + vkmap.put(KeyEvent.KEYCODE_B, 0x42); // B + vkmap.put(KeyEvent.KEYCODE_C, 0x43); // C + vkmap.put(KeyEvent.KEYCODE_D, 0x44); // D + vkmap.put(KeyEvent.KEYCODE_E, 0x45); // E + vkmap.put(KeyEvent.KEYCODE_F, 0x46); // F + vkmap.put(KeyEvent.KEYCODE_G, 0x47); // G + vkmap.put(KeyEvent.KEYCODE_H, 0x48); // H + vkmap.put(KeyEvent.KEYCODE_I, 0x49); // I + vkmap.put(KeyEvent.KEYCODE_J, 0x4A); // J + vkmap.put(KeyEvent.KEYCODE_K, 0x4B); // K + vkmap.put(KeyEvent.KEYCODE_L, 0x4C); // L + vkmap.put(KeyEvent.KEYCODE_M, 0x4D); // M + vkmap.put(KeyEvent.KEYCODE_N, 0x4E); // N + vkmap.put(KeyEvent.KEYCODE_O, 0x4F); // O + vkmap.put(KeyEvent.KEYCODE_P, 0x50); // P + vkmap.put(KeyEvent.KEYCODE_Q, 0x51); // Q + vkmap.put(KeyEvent.KEYCODE_R, 0x52); // R + vkmap.put(KeyEvent.KEYCODE_S, 0x53); // S + vkmap.put(KeyEvent.KEYCODE_T, 0x54); // T + vkmap.put(KeyEvent.KEYCODE_U, 0x55); // U + vkmap.put(KeyEvent.KEYCODE_V, 0x56); // V + vkmap.put(KeyEvent.KEYCODE_W, 0x57); // W + vkmap.put(KeyEvent.KEYCODE_X, 0x58); // X + vkmap.put(KeyEvent.KEYCODE_Y, 0x59); // Y + vkmap.put(KeyEvent.KEYCODE_Z, 0x5A); // Z + vkmap.put(KeyEvent.KEYCODE_NUMPAD_0, 0x60); // VK_NUMPAD0 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_1, 0x61); // VK_NUMPAD1 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_2, 0x62); // VK_NUMPAD2 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_3, 0x63); // VK_NUMPAD3 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_4, 0x64); // VK_NUMPAD4 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_5, 0x65); // VK_NUMPAD5 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_6, 0x66); // VK_NUMPAD6 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_7, 0x67); // VK_NUMPAD7 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_8, 0x68); // VK_NUMPAD8 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_9, 0x69); // VK_NUMPAD9 + vkmap.put(KeyEvent.KEYCODE_NUMPAD_MULTIPLY, 0x6A); // VK_MULTIPLY + vkmap.put(KeyEvent.KEYCODE_NUMPAD_ADD, 0x6B); // VK_ADD + vkmap.put(KeyEvent.KEYCODE_NUMPAD_SUBTRACT, 0x6D); // VK_SUBTRACT + vkmap.put(KeyEvent.KEYCODE_NUMPAD_DOT, 0x6E); // VK_DECIMAL + vkmap.put(KeyEvent.KEYCODE_NUMPAD_DIVIDE, 0x6F); // VK_DIVIDE +// vkmap.put(KeyEvent.KEYCODE_SEMICOLON, 0xBA); // VK_OEM_1 (:);) + vkmap.put(KeyEvent.KEYCODE_COMMA, 0xBC); // VK_OEM_COMMA + vkmap.put(KeyEvent.KEYCODE_PERIOD, 0xBE); // VK_OEM_PERIOD +// vkmap.put(KeyEvent.0x2C, 0xBF); // VK_OEM_2 (?) +// vkmap.put(KeyEvent.0x32, 0xC0); // VK_OEM_3 (~) +// vkmap.put(KeyEvent.KEYCODE_LEFT_BRACKET, 0xDB); // VK_OEM_4 ([{) +// vkmap.put(KeyEvent.0x27, 0xDE); // VK_OEM_7 (‘ ») + + this.setFocusable(true); + this.setFocusableInTouchMode(true); + // This call is necessary, or else the // draw method will not be called. setWillNotDraw(false); } -// -// @SuppressLint("ClickableViewAccessibility") -// public boolean onTouchEvent(MotionEvent event) { -// // Let the ScaleGestureDetector inspect all events. + + @SuppressLint("ClickableViewAccessibility") + public boolean onTouchEvent(MotionEvent event) { + // Let the ScaleGestureDetector inspect all events. // boolean retValScaleDetector = mScaleDetector.onTouchEvent(event); // boolean retValGestureDetector = mGestureDetector.onTouchEvent(event); -// boolean retVal = retValGestureDetector || retValScaleDetector; -// -// int touchCount = event.getPointerCount(); -// if(touchCount == 1) { -// int action = event.getAction(); -// switch (action) { -//// case MotionEvent.ACTION_DOWN: -//// -//// mPanPrevious.x = event.getX(0); -//// mPanPrevious.y = event.getY(0); -//// mIsPanning = true; -//// -//// //Log.d(TAG, "ACTION_DOWN count: " + touchCount + ", PanPrevious: " + mPanPrevious.toString()); -//// -//// break; -//// case MotionEvent.ACTION_MOVE: -//// float panCurrentX = event.getX(0); -//// float panCurrentY = event.getY(0); -//// if(mIsPanning && Math.abs(panCurrentX - mPanPrevious.x) > 1.0f && Math.abs(panCurrentY - mPanPrevious.y) > 1.0f) { -//// mPanCurrent.x = panCurrentX; -//// mPanCurrent.y = panCurrentY; -//// currentProject.viewPanOffsetX += mPanCurrent.x - mPanPrevious.x; -//// currentProject.viewPanOffsetY += mPanCurrent.y - mPanPrevious.y; -//// -//// //Log.d(TAG, "Before viewPanOffsetX: " + currentProject.viewPanOffsetX + ", viewPanOffsetY: " + currentProject.viewPanOffsetY); -//// -//// constrainScale(); -//// constrainPan(); -//// -//// //Log.d(TAG, "After viewPanOffsetX: " + currentProject.viewPanOffsetX + ", viewPanOffsetY: " + currentProject.viewPanOffsetY); -//// -//// //Log.d(TAG, "ACTION_MOVE count: " + touchCount + ", PanPrevious: " + mPanPrevious.toString() + ", PanCurrent: " + mPanCurrent.toString()); -//// -//// mPanPrevious.x = mPanCurrent.x; -//// mPanPrevious.y = mPanCurrent.y; -//// -//// invalidate(); -//// } -//// break; -// case MotionEvent.ACTION_UP: -// if(mIsPanning) { -// //Log.d(TAG, "Stop PANNING"); -// mIsPanning = false; -// if(!mIsFlinging) -// invalidate(); -// } -// break; -//// case MotionEvent.ACTION_CANCEL: -//// break; -//// case MotionEvent.ACTION_OUTSIDE: -//// break; -// default: -// } -// return true; -// } -// return retVal || super.onTouchEvent(event); -// } -// + boolean retVal = false; //retValGestureDetector || retValScaleDetector; + + int touchCount = event.getPointerCount(); + if(touchCount == 1) { + int action = event.getAction(); + switch (action) { + case MotionEvent.ACTION_DOWN: + //Log.d(TAG, "ACTION_DOWN count: " + touchCount + ", PanPrevious: " + mPanPrevious.toString()); + NativeLib.buttonDown((int)event.getX(0), (int)event.getY(0)); + break; +// case MotionEvent.ACTION_MOVE: +// break; + case MotionEvent.ACTION_UP: + NativeLib.buttonUp((int)event.getX(0), (int)event.getY(0)); + break; +// case MotionEvent.ACTION_CANCEL: +// break; +// case MotionEvent.ACTION_OUTSIDE: +// break; + default: + } + return true; + } + return retVal || super.onTouchEvent(event); + } + // @Override // public boolean onGenericMotionEvent(MotionEvent event) { // if ((event.getSource() & InputDevice.SOURCE_CLASS_POINTER) != 0) { @@ -178,19 +226,28 @@ public class MainScreenView extends SurfaceView { // } // return super.onGenericMotionEvent(event); // } -// -// @Override -// public boolean onKeyUp(int keyCode, KeyEvent event) { -// char character = (char)event.getUnicodeChar(); -// if(character == '+') { -// scaleByStep(mScaleStep, getWidth() / 2.0f, getHeight() / 2.0f); -// return true; -// } else if(character == '-') { -// scaleByStep(1.0f / mScaleStep, getWidth() / 2.0f, getHeight() / 2.0f); -// return true; -// } -// return super.onKeyUp(keyCode, event); -// } + + + @Override + public boolean onKeyDown(int keyCode, KeyEvent event) { + Integer windowsKeycode = vkmap.get(keyCode); + if(windowsKeycode != null) + NativeLib.keyDown(windowsKeycode.intValue()); + else + Log.e(TAG, String.format("windowsKeycode: %d", windowsKeycode.intValue())); + return super.onKeyDown(keyCode, event); + } + + @Override + public boolean onKeyUp(int keyCode, KeyEvent event) { + //char character = (char)event.getUnicodeChar(); + Integer windowsKeycode = vkmap.get(keyCode); + if(windowsKeycode != null) + NativeLib.keyUp(windowsKeycode.intValue()); + else + Log.e(TAG, String.format("windowsKeycode: %d", windowsKeycode.intValue())); + return super.onKeyUp(keyCode, event); + } @Override protected void onSizeChanged(int viewWidth, int viewHeight, int oldViewWidth, int oldViewHeight) { @@ -202,69 +259,11 @@ public class MainScreenView extends SurfaceView { @Override protected void onDraw(Canvas canvas) { //Log.d(TAG, "onDraw() mIsScaling: " + mIsScaling + ", mIsPanning: " + mIsPanning + ", mIsFlinging: " + mIsFlinging); - -// //renderPlasma(mBitmap, System.currentTimeMillis() - mStartTime); + //NativeLib.draw(); canvas.drawBitmap(bitmapMainScreen, 0, 0, null); - -// Paint paint = mVectorsCanvasRenderer.getPaint(); -// -// canvas.drawColor(Color.rgb(224, 224, 224)); -// -// canvas.save(); -// canvas.translate(currentProject.viewPanOffsetX, currentProject.viewPanOffsetY); -// canvas.scale(currentProject.viewScaleFactor, currentProject.viewScaleFactor); -// paint.setColor(Color.BLACK); -// mVectorsCanvasRenderer.setCanvas(canvas); -// mVectorsCanvasRenderer.setShowLabels(currentProject.showLabels); -// if(mIsPanning || mIsScaling || mIsFlinging) -// { -// // We are scaling or panning, trying to optimize... -// if(mVectorsCanvasRenderer.getBackground() == null) -// // Display polygons only if there is no background map -// mVectorsCanvasRenderer.drawVectors(false, true, true, false); -// else -// // Best optimization -// mVectorsCanvasRenderer.drawBackgroundMap(); -// } -// else -// // Draw everything following the parameters -// mVectorsCanvasRenderer.drawVectors(); -// canvas.restore(); -// -// if(currentProject.viewScaleFactor > mScaleFactorMin) { -// // Draw the scale thumbnail -// paint.setColor(Color.RED); -// paint.setStrokeWidth(1.0f * mScreenDensity); -// -// float scale = 0.2f; -// if(mImageSize.x > mImageSize.y) -// scale *= mViewBounds.width() / mImageSize.x; -// else -// scale *= mViewBounds.height() / mImageSize.y; -// float marginX = 10f * mScreenDensity, marginY = 10f * mScreenDensity; -// mRectScaleImage.set(mViewBounds.right - marginX - scale * mImageSize.x, -// mViewBounds.bottom - marginY - scale * mImageSize.y, -// mViewBounds.right - marginX, -// mViewBounds.bottom - marginY -// ); -// canvas.drawRect(mRectScaleImage, paint); -// if(backgroundMapIndex >= 0 && mBitmap != null) { -// //Bitmap background = nativePNP.getBitmap(ParamImageSourceMat); -// mRectBitmapSource.set(0, 0, (int)mImageSize.x, (int)mImageSize.y); -// canvas.drawBitmap(mBitmap, mRectBitmapSource, mRectScaleImage, paint); -// } -// -// mRectScaleView.set(mRectScaleImage.left + scale * (-currentProject.viewPanOffsetX / currentProject.viewScaleFactor), -// mRectScaleImage.top + scale * (-currentProject.viewPanOffsetY / currentProject.viewScaleFactor), -// mRectScaleImage.left + scale * (mViewBounds.width() - currentProject.viewPanOffsetX) / currentProject.viewScaleFactor, -// mRectScaleImage.top + scale * (mViewBounds.height() - currentProject.viewPanOffsetY) / currentProject.viewScaleFactor -// ); -// canvas.drawRect(mRectScaleView, paint); -// } } void updateCallback() { - //invalidate(); - postInvalidate(); + //postInvalidate(); } } diff --git a/app/src/main/java/com/regis/cosnier/emu48/NativeLib.java b/app/src/main/java/com/regis/cosnier/emu48/NativeLib.java index 84299c1..2571cd1 100644 --- a/app/src/main/java/com/regis/cosnier/emu48/NativeLib.java +++ b/app/src/main/java/com/regis/cosnier/emu48/NativeLib.java @@ -13,4 +13,9 @@ public class NativeLib { public static native void start(AssetManager mgr, Bitmap bitmapMainScreen, MainScreenView view); public static native void stop(); public static native void resize(int width, int height); + public static native void draw(); + public static native void buttonDown(int x, int y); + public static native void buttonUp(int x, int y); + public static native void keyDown(int virtKey); + public static native void keyUp(int virtKey); }