mirror of
https://github.com/dgis/emu48android
synced 2024-12-26 09:58:49 +01:00
Version 2.5 (2022-03-03)
- Allow to load RLE4, RLE8 and monochrome BMP images. - Optimize the number of draw calls when displaying the LCD pixel borders.
This commit is contained in:
parent
8a54fb0b33
commit
d27d777153
12 changed files with 310 additions and 48 deletions
|
@ -58,6 +58,12 @@ LINKS
|
||||||
|
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
|
Version 2.5 (2022-03-03)
|
||||||
|
|
||||||
|
- Allow to load RLE4, RLE8 and monochrome BMP images.
|
||||||
|
- Optimize the number of draw calls when displaying the LCD pixel borders.
|
||||||
|
|
||||||
|
|
||||||
Version 2.4 (2021-12-08)
|
Version 2.4 (2021-12-08)
|
||||||
|
|
||||||
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
||||||
|
|
|
@ -28,13 +28,13 @@ if (keystorePropertiesFile.exists()) {
|
||||||
}
|
}
|
||||||
|
|
||||||
android {
|
android {
|
||||||
compileSdkVersion 30
|
compileSdkVersion 31
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "org.emulator.forty.eight"
|
applicationId "org.emulator.forty.eight"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 30
|
targetSdkVersion 31
|
||||||
versionCode 23
|
versionCode 24
|
||||||
versionName "2.4"
|
versionName "2.5"
|
||||||
setProperty("archivesBaseName", "Emu48-v$versionName")
|
setProperty("archivesBaseName", "Emu48-v$versionName")
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
|
@ -84,12 +84,12 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||||
implementation 'androidx.preference:preference:1.1.1'
|
implementation 'androidx.preference:preference:1.2.0'
|
||||||
implementation 'com.google.android.material:material:1.4.0'
|
implementation 'com.google.android.material:material:1.5.0'
|
||||||
implementation 'androidx.documentfile:documentfile:1.0.1'
|
implementation 'androidx.documentfile:documentfile:1.0.1'
|
||||||
testImplementation 'junit:junit:4.13.1'
|
testImplementation 'junit:junit:4.13.2'
|
||||||
androidTestImplementation 'androidx.test:runner:1.4.0'
|
androidTestImplementation 'androidx.test:runner:1.4.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||||
android:launchMode="singleTop"
|
android:launchMode="singleTop"
|
||||||
android:theme="@style/AppTheme.NoActionBar"
|
android:theme="@style/AppTheme.NoActionBar"
|
||||||
>
|
android:exported="true">
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN" />
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
|
|
|
@ -58,6 +58,12 @@ LINKS
|
||||||
|
|
||||||
CHANGES
|
CHANGES
|
||||||
|
|
||||||
|
Version 2.5 (2022-03-03)
|
||||||
|
|
||||||
|
- Allow to load RLE4, RLE8 and monochrome BMP images.
|
||||||
|
- Optimize the number of draw calls when displaying the LCD pixel borders.
|
||||||
|
|
||||||
|
|
||||||
Version 2.4 (2021-12-08)
|
Version 2.4 (2021-12-08)
|
||||||
|
|
||||||
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
||||||
|
|
|
@ -2237,7 +2237,7 @@ void StretchBltInternal(int xDest, int yDest, int wDest, int hDest,
|
||||||
// and the color white in the source turns into the destination’s background
|
// and the color white in the source turns into the destination’s background
|
||||||
// color.
|
// color.
|
||||||
BYTE * sourcePixel = sourcePixelBase + ((UINT)src_curx >> (UINT)3);
|
BYTE * sourcePixel = sourcePixelBase + ((UINT)src_curx >> (UINT)3);
|
||||||
UINT bitNumber = (UINT) (src_curx % 8);
|
UINT bitNumber = (UINT) (7 - (src_curx % 8));
|
||||||
if(*sourcePixel & ((UINT)1 << bitNumber)) {
|
if(*sourcePixel & ((UINT)1 << bitNumber)) {
|
||||||
// Monochrome 1=White
|
// Monochrome 1=White
|
||||||
sourceColorPointer[0] = 255;
|
sourceColorPointer[0] = 255;
|
||||||
|
@ -2311,7 +2311,7 @@ void StretchBltInternal(int xDest, int yDest, int wDest, int hDest,
|
||||||
// In other words, GDI considers a monochrome bitmap to be
|
// In other words, GDI considers a monochrome bitmap to be
|
||||||
// black pixels on a white background.
|
// black pixels on a white background.
|
||||||
BYTE * destinationPixel = destinationPixelBase + (x >> 3);
|
BYTE * destinationPixel = destinationPixelBase + (x >> 3);
|
||||||
UINT bitNumber = x % 8;
|
UINT bitNumber = (UINT) (7 - (x % 8));
|
||||||
if(backgroundColor == sourceColor) {
|
if(backgroundColor == sourceColor) {
|
||||||
*destinationPixel |= (1 << bitNumber); // 1 White
|
*destinationPixel |= (1 << bitNumber); // 1 White
|
||||||
} else {
|
} else {
|
||||||
|
@ -2397,6 +2397,180 @@ HBITMAP CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CON
|
||||||
newHBITMAP->bitmapBits = bitmapBits;
|
newHBITMAP->bitmapBits = bitmapBits;
|
||||||
return newHBITMAP;
|
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
|
||||||
|
} BMPFILE, FAR *LPBMPFILE, *PBMPFILE;
|
||||||
|
|
||||||
|
static BOOL ReadRleBmpByte(LPBMPFILE pBmp, BYTE *n)
|
||||||
|
{
|
||||||
|
// outside BMP file
|
||||||
|
if (pBmp->dwPos >= pBmp->dwFileSize)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
*n = pBmp->pbyFile[pBmp->dwPos++];
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
// valid bit count for RLE bitmaps
|
||||||
|
_ASSERT(lpbi->biBitCount == 4 || lpbi->biBitCount == 8);
|
||||||
|
|
||||||
|
// wrong bit count for compressed bitmap or top-down bitmap
|
||||||
|
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
|
||||||
|
|
||||||
|
// image size
|
||||||
|
_ASSERT(lpbi->biHeight >= 0);
|
||||||
|
dwSizeImage = WIDTHBYTES((DWORD)lpbi->biWidth * lpbi->biBitCount) * lpbi->biHeight;
|
||||||
|
|
||||||
|
ZeroMemory(ppvBits,dwSizeImage); // clear bitmap
|
||||||
|
|
||||||
|
// image size in pixel
|
||||||
|
dwSizeImage *= (8 / lpbi->biBitCount);
|
||||||
|
|
||||||
|
// no. of pixels per line
|
||||||
|
dwPixelPerLine = dwSizeImage / lpbi->biHeight;
|
||||||
|
|
||||||
|
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 (byLength) // length information
|
||||||
|
{
|
||||||
|
// check for buffer overflow
|
||||||
|
if (dwPos + byLength > dwSizeImage)
|
||||||
|
{
|
||||||
|
// write rest of data until buffer full
|
||||||
|
byLength = (dwPos > dwSizeImage) ? 0 : (BYTE) (dwSizeImage - dwPos);
|
||||||
|
bDecoding = FALSE; // abort
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpbi->biBitCount == 4) // RLE4
|
||||||
|
{
|
||||||
|
BYTE byColor[2];
|
||||||
|
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]
|
||||||
|
|
||||||
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // RLE8
|
||||||
|
{
|
||||||
|
while (byLength-- > 0)
|
||||||
|
ppvBits[dwPos++] = byColorIndex;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else // escape sequence
|
||||||
|
{
|
||||||
|
switch (byColorIndex)
|
||||||
|
{
|
||||||
|
case 0: // End of Line
|
||||||
|
dwPos = ++dwRow * dwPixelPerLine;
|
||||||
|
break;
|
||||||
|
case 1: // End of Bitmap
|
||||||
|
bDecoding = FALSE;
|
||||||
|
break;
|
||||||
|
case 2: // Delta
|
||||||
|
// column offset
|
||||||
|
if (ReadRleBmpByte(pBmp,&byColorIndex)) return TRUE;
|
||||||
|
dwPos += byColorIndex;
|
||||||
|
// row offset
|
||||||
|
if (ReadRleBmpByte(pBmp,&byColorIndex)) return TRUE;
|
||||||
|
dwRow += byColorIndex;
|
||||||
|
dwPos += dwPixelPerLine * byColorIndex;
|
||||||
|
break;
|
||||||
|
default: // absolute mode
|
||||||
|
// check for buffer overflow
|
||||||
|
if (dwPos + byColorIndex > dwSizeImage)
|
||||||
|
{
|
||||||
|
// write rest of data until buffer full
|
||||||
|
byColorIndex = (dwPos > dwSizeImage) ? 0 : (BYTE) (dwSizeImage - dwPos);
|
||||||
|
bDecoding = FALSE; // abort
|
||||||
|
}
|
||||||
|
|
||||||
|
if (lpbi->biBitCount == 4) // RLE4
|
||||||
|
{
|
||||||
|
BYTE byColor,byColorPair;
|
||||||
|
UINT s,d;
|
||||||
|
|
||||||
|
d = (~dwPos & 1) * 4; // destination shift [0/4]
|
||||||
|
|
||||||
|
for (s = 0; s < byColorIndex; ++s)
|
||||||
|
{
|
||||||
|
if ((s & 1) == 0) // upper nibble
|
||||||
|
{
|
||||||
|
// fetch color pair
|
||||||
|
if (ReadRleBmpByte(pBmp,&byColorPair)) return TRUE;
|
||||||
|
|
||||||
|
// get upper nibble
|
||||||
|
byColor = (byColorPair >> 4);
|
||||||
|
}
|
||||||
|
else // lower nibble
|
||||||
|
{
|
||||||
|
// get lower nibble
|
||||||
|
byColor = (byColorPair & 0x0F);
|
||||||
|
}
|
||||||
|
|
||||||
|
// write nibble to memory
|
||||||
|
_ASSERT((byColor & 0xF0) == 0);
|
||||||
|
ppvBits[dwPos++/2] |= (byColor << d);
|
||||||
|
d ^= 4; // next destination shift
|
||||||
|
}
|
||||||
|
|
||||||
|
// for odd byte length detection
|
||||||
|
byColorIndex = (++byColorIndex) >> 1;
|
||||||
|
}
|
||||||
|
else // RLE8
|
||||||
|
{
|
||||||
|
if (pBmp->dwPos + byColorIndex > pBmp->dwFileSize) return TRUE;
|
||||||
|
CopyMemory(ppvBits+dwPos,&pBmp->pbyFile[pBmp->dwPos],byColorIndex);
|
||||||
|
dwPos += byColorIndex;
|
||||||
|
pBmp->dwPos += byColorIndex;
|
||||||
|
}
|
||||||
|
// word align on odd byte length
|
||||||
|
if (byColorIndex & 1) ++pBmp->dwPos;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
while (bDecoding);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CONST VOID *pjBits, CONST BITMAPINFO *pbmi, UINT iUsage) {
|
HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CONST VOID *pjBits, CONST BITMAPINFO *pbmi, UINT iUsage) {
|
||||||
PAINT_LOGD("PAINT CreateDIBitmap()");
|
PAINT_LOGD("PAINT CreateDIBitmap()");
|
||||||
|
|
||||||
|
@ -2409,17 +2583,51 @@ HBITMAP CreateDIBitmap( HDC hdc, CONST BITMAPINFOHEADER *pbmih, DWORD flInit, CO
|
||||||
newHBITMAP->bitmapInfo = newBitmapInfo;
|
newHBITMAP->bitmapInfo = newBitmapInfo;
|
||||||
newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo;
|
newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo;
|
||||||
|
|
||||||
|
if(flInit == CBM_INIT && pjBits) {
|
||||||
|
VOID * bitmapBits = NULL;
|
||||||
|
if(iUsage == DIB_RGB_COLORS) {
|
||||||
|
switch (pbmi->bmiHeader.biCompression) {
|
||||||
|
case BI_RLE4:
|
||||||
|
case BI_RLE8: {
|
||||||
|
|
||||||
|
// Destination
|
||||||
|
BOOL bErr;
|
||||||
|
newBitmapInfo->bmiHeader.biCompression = BI_RGB;
|
||||||
|
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));
|
||||||
|
|
||||||
|
Bmp.pbyFile = ((LPBYTE)&pbmi->bmiHeader) + bitOffset;
|
||||||
|
Bmp.dwPos = 0;
|
||||||
|
Bmp.dwFileSize = -1; //size;
|
||||||
|
|
||||||
|
bErr = DecodeRleBmp(
|
||||||
|
/* Destination */ bitmapBits,
|
||||||
|
/* Destination header */ &newBitmapInfo->bmiHeader,
|
||||||
|
/* Source */ &Bmp);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
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 ?
|
size_t size = newBitmapInfo->bmiHeader.biSizeImage ?
|
||||||
newBitmapInfo->bmiHeader.biSizeImage :
|
newBitmapInfo->bmiHeader.biSizeImage :
|
||||||
abs(newBitmapInfo->bmiHeader.biHeight) * stride;
|
abs(newBitmapInfo->bmiHeader.biHeight) * stride;
|
||||||
VOID * bitmapBits = malloc(size);
|
bitmapBits = malloc(size);
|
||||||
memcpy(bitmapBits, pjBits, size);
|
memcpy(bitmapBits, pjBits, size);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
newHBITMAP->bitmapBits = bitmapBits;
|
newHBITMAP->bitmapBits = bitmapBits;
|
||||||
|
}
|
||||||
return newHBITMAP;
|
return newHBITMAP;
|
||||||
}
|
}
|
||||||
HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) {
|
HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppvBits, HANDLE hSection, DWORD offset) {
|
||||||
PAINT_LOGD("PAINT CreateDIBitmap()");
|
PAINT_LOGD("PAINT CreateDIBSection()");
|
||||||
|
|
||||||
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
||||||
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
||||||
|
@ -2445,7 +2653,7 @@ HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppv
|
||||||
return newHBITMAP;
|
return newHBITMAP;
|
||||||
}
|
}
|
||||||
HBITMAP CreateCompatibleBitmap( HDC hdc, int cx, int cy) {
|
HBITMAP CreateCompatibleBitmap( HDC hdc, int cx, int cy) {
|
||||||
PAINT_LOGD("PAINT CreateDIBitmap()");
|
PAINT_LOGD("PAINT CreateCompatibleBitmap()");
|
||||||
|
|
||||||
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
||||||
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
||||||
|
@ -2469,6 +2677,7 @@ HBITMAP CreateCompatibleBitmap( HDC hdc, int cx, int cy) {
|
||||||
return newHBITMAP;
|
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
|
//TODO Not sure at all for this function
|
||||||
if(hbm && lpbmi) {
|
if(hbm && lpbmi) {
|
||||||
CONST BITMAPINFO *pbmi = hbm->bitmapInfo;
|
CONST BITMAPINFO *pbmi = hbm->bitmapInfo;
|
||||||
|
|
|
@ -811,6 +811,7 @@ typedef struct _RGNDATA {
|
||||||
char Buffer[1];
|
char Buffer[1];
|
||||||
} RGNDATA, *PRGNDATA, NEAR *NPRGNDATA, FAR *LPRGNDATA;
|
} RGNDATA, *PRGNDATA, NEAR *NPRGNDATA, FAR *LPRGNDATA;
|
||||||
extern int GetDIBits(HDC hdc, HBITMAP hbm, UINT start, UINT cLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT usage);
|
extern int GetDIBits(HDC hdc, HBITMAP hbm, UINT start, UINT cLines, LPVOID lpvBits, LPBITMAPINFO lpbmi, UINT usage);
|
||||||
|
extern int SetDIBits(HDC hdc, HBITMAP hbm, UINT start, UINT cLines, const VOID *lpBits, const BITMAPINFO *lpbmi, UINT ColorUse);
|
||||||
extern COLORREF GetPixel(HDC hdc, int x ,int y);
|
extern COLORREF GetPixel(HDC hdc, int x ,int y);
|
||||||
extern HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd);
|
extern HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd);
|
||||||
extern UINT RealizePalette(HDC hdc);
|
extern UINT RealizePalette(HDC hdc);
|
||||||
|
|
|
@ -256,7 +256,7 @@ public class MainScreenView extends PanAndScaleView {
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||||
if((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) == 0
|
if((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) == 0
|
||||||
&& (event.getSource() & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
&& ((event.getSource() & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) || event.getSource() == 0) {
|
||||||
if(!event.isNumLockOn() && numpadKey.indexOf(keyCode) != -1)
|
if(!event.isNumLockOn() && numpadKey.indexOf(keyCode) != -1)
|
||||||
return false;
|
return false;
|
||||||
char pressedKey = (char) event.getUnicodeChar();
|
char pressedKey = (char) event.getUnicodeChar();
|
||||||
|
@ -277,7 +277,7 @@ public class MainScreenView extends PanAndScaleView {
|
||||||
@Override
|
@Override
|
||||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||||
if((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) == 0
|
if((event.getFlags() & KeyEvent.FLAG_VIRTUAL_HARD_KEY) == 0
|
||||||
&& (event.getSource() & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) {
|
&& ((event.getSource() & InputDevice.SOURCE_KEYBOARD) == InputDevice.SOURCE_KEYBOARD) || event.getSource() == 0) {
|
||||||
if(!event.isNumLockOn() && numpadKey.indexOf(keyCode) != -1)
|
if(!event.isNumLockOn() && numpadKey.indexOf(keyCode) != -1)
|
||||||
return false;
|
return false;
|
||||||
char pressedKey = (char) event.getUnicodeChar();
|
char pressedKey = (char) event.getUnicodeChar();
|
||||||
|
@ -451,20 +451,36 @@ public class MainScreenView extends PanAndScaleView {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static float[] pointsBuffer = new float[0];
|
||||||
static void drawPixelBorder(Canvas canvas, int lcdWidthNative, int lcdHeightNative, float screenPositionX, float screenPositionY, float screenWidth, float screenHeight, Paint paintLCD) {
|
static void drawPixelBorder(Canvas canvas, int lcdWidthNative, int lcdHeightNative, float screenPositionX, float screenPositionY, float screenWidth, float screenHeight, Paint paintLCD) {
|
||||||
// Draw the LCD grid lines without antialiasing to emulate the genuine pixels borders
|
// Draw the LCD grid lines without antialiasing to emulate the genuine pixels borders
|
||||||
int lcdBackgroundColor = 0xFF000000 | NativeLib.getLCDBackgroundColor();
|
int lcdBackgroundColor = 0xFF000000 | NativeLib.getLCDBackgroundColor();
|
||||||
paintLCD.setColor(lcdBackgroundColor);
|
paintLCD.setColor(lcdBackgroundColor);
|
||||||
float stepX = screenWidth / lcdWidthNative;
|
float stepX = screenWidth / lcdWidthNative;
|
||||||
|
|
||||||
|
// Optimized drawcalls
|
||||||
|
int pointBufferLength = (lcdWidthNative + lcdHeightNative) << 2;
|
||||||
|
if(pointsBuffer.length != pointBufferLength)
|
||||||
|
pointsBuffer = new float[pointBufferLength]; // Adjust the buffer of points
|
||||||
|
|
||||||
|
int pointsIndex = 0;
|
||||||
for (int x = 0; x < lcdWidthNative; x++) {
|
for (int x = 0; x < lcdWidthNative; x++) {
|
||||||
float screenX = screenPositionX + x * stepX;
|
float screenX = screenPositionX + x * stepX;
|
||||||
canvas.drawLine(screenX, screenPositionY, screenX, screenPositionY + screenHeight, paintLCD);
|
pointsBuffer[pointsIndex++] = screenX;
|
||||||
|
pointsBuffer[pointsIndex++] = screenPositionY;
|
||||||
|
pointsBuffer[pointsIndex++] = screenX;
|
||||||
|
pointsBuffer[pointsIndex++] = screenPositionY + screenHeight;
|
||||||
}
|
}
|
||||||
float stepY = screenHeight / lcdHeightNative;
|
float stepY = screenHeight / lcdHeightNative;
|
||||||
for (int y = 0; y < lcdHeightNative; y++) {
|
for (int y = 0; y < lcdHeightNative; y++) {
|
||||||
float screenY = screenPositionY + y * stepY;
|
float screenY = screenPositionY + y * stepY;
|
||||||
canvas.drawLine(screenPositionX, screenY, screenPositionX + screenWidth, screenY, paintLCD);
|
pointsBuffer[pointsIndex++] = screenPositionX;
|
||||||
|
pointsBuffer[pointsIndex++] = screenY;
|
||||||
|
pointsBuffer[pointsIndex++] = screenPositionX + screenWidth;
|
||||||
|
pointsBuffer[pointsIndex++] = screenY;
|
||||||
}
|
}
|
||||||
|
canvas.drawLines(pointsBuffer, paintLCD);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void updateCallback(int type, int param1, int param2, String param3, String param4) {
|
public void updateCallback(int type, int param1, int param2, String param3, String param4) {
|
||||||
|
|
|
@ -169,6 +169,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
|
|
||||||
ViewGroup mainScreenContainer = findViewById(R.id.main_screen_container);
|
ViewGroup mainScreenContainer = findViewById(R.id.main_screen_container);
|
||||||
mainScreenView = new MainScreenView(this);
|
mainScreenView = new MainScreenView(this);
|
||||||
|
mainScreenView.setId(R.id.main_screen_view);
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||||
mainScreenView.setStatusBarColor(getWindow().getStatusBarColor());
|
mainScreenView.setStatusBarColor(getWindow().getStatusBarColor());
|
||||||
mainScreenContainer.addView(mainScreenView, 0, new ViewGroup.LayoutParams(
|
mainScreenContainer.addView(mainScreenView, 0, new ViewGroup.LayoutParams(
|
||||||
|
@ -437,6 +438,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
boolean bStackCEnable = bObjectEnable;
|
boolean bStackCEnable = bObjectEnable;
|
||||||
boolean bStackPEnable = bObjectEnable;
|
boolean bStackPEnable = bObjectEnable;
|
||||||
|
|
||||||
|
menu.findItem(R.id.nav_manage_flash_rom).setEnabled(uRun && (cCurrentRomType == 'X' || cCurrentRomType == 'Q'));
|
||||||
|
|
||||||
menu.findItem(R.id.nav_save).setEnabled(uRun);
|
menu.findItem(R.id.nav_save).setEnabled(uRun);
|
||||||
menu.findItem(R.id.nav_save_as).setEnabled(uRun);
|
menu.findItem(R.id.nav_save_as).setEnabled(uRun);
|
||||||
menu.findItem(R.id.nav_close).setEnabled(uRun);
|
menu.findItem(R.id.nav_close).setEnabled(uRun);
|
||||||
|
@ -451,7 +454,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
menu.findItem(R.id.nav_backup_delete).setEnabled(uRun && isBackup);
|
menu.findItem(R.id.nav_backup_delete).setEnabled(uRun && isBackup);
|
||||||
menu.findItem(R.id.nav_change_kml_script).setEnabled(uRun);
|
menu.findItem(R.id.nav_change_kml_script).setEnabled(uRun);
|
||||||
menu.findItem(R.id.nav_show_kml_script_compilation_result).setEnabled(uRun);
|
menu.findItem(R.id.nav_show_kml_script_compilation_result).setEnabled(uRun);
|
||||||
menu.findItem(R.id.nav_manage_flash_rom).setEnabled(uRun && (cCurrentRomType == 'X' || cCurrentRomType == 'Q'));
|
|
||||||
menu.findItem(R.id.nav_macro_record).setEnabled(uRun && nMacroState == 0 /* MACRO_OFF */);
|
menu.findItem(R.id.nav_macro_record).setEnabled(uRun && nMacroState == 0 /* MACRO_OFF */);
|
||||||
menu.findItem(R.id.nav_macro_play).setEnabled(uRun && nMacroState == 0 /* MACRO_OFF */);
|
menu.findItem(R.id.nav_macro_play).setEnabled(uRun && nMacroState == 0 /* MACRO_OFF */);
|
||||||
menu.findItem(R.id.nav_macro_stop).setEnabled(uRun && nMacroState != 0 /* MACRO_OFF */);
|
menu.findItem(R.id.nav_macro_stop).setEnabled(uRun && nMacroState != 0 /* MACRO_OFF */);
|
||||||
|
@ -844,7 +846,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
} else
|
} else
|
||||||
openDocument();
|
openDocument();
|
||||||
}
|
}
|
||||||
private void OnObjectSave() {
|
private void SaveObject() {
|
||||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||||
intent.setType("*/*");
|
intent.setType("*/*");
|
||||||
|
@ -852,6 +854,23 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
saveWhenLaunchingActivity = false;
|
saveWhenLaunchingActivity = false;
|
||||||
startActivityForResult(intent, INTENT_OBJECT_SAVE);
|
startActivityForResult(intent, INTENT_OBJECT_SAVE);
|
||||||
}
|
}
|
||||||
|
private void OnObjectSave() {
|
||||||
|
int model = NativeLib.getCurrentModel();
|
||||||
|
if(model == 'L' // HP32S # Leonardo
|
||||||
|
|| model == 'N' // HP32SII # Nardo
|
||||||
|
|| model == 'D') { // HP42S # Davinci
|
||||||
|
final String[] objectsToSave = NativeLib.getObjectsToSave();
|
||||||
|
objectsToSaveItemChecked = new boolean[objectsToSave.length];
|
||||||
|
new AlertDialog.Builder(MainActivity.this)
|
||||||
|
.setTitle(getResources().getString(R.string.message_object_save_program))
|
||||||
|
.setMultiChoiceItems(objectsToSave, null, (dialog, which, isChecked) -> objectsToSaveItemChecked[which] = isChecked).setPositiveButton("OK", (dialog, id) -> {
|
||||||
|
//NativeLib.onObjectSave(url);
|
||||||
|
SaveObject();
|
||||||
|
}).setNegativeButton("Cancel", (dialog, id) -> objectsToSaveItemChecked = null).show();
|
||||||
|
} else
|
||||||
|
SaveObject(); // Others calculators
|
||||||
|
}
|
||||||
|
|
||||||
private void OnViewCopyFullscreen() {
|
private void OnViewCopyFullscreen() {
|
||||||
Bitmap bitmapScreen = mainScreenView.getBitmap();
|
Bitmap bitmapScreen = mainScreenView.getBitmap();
|
||||||
if(bitmapScreen == null)
|
if(bitmapScreen == null)
|
||||||
|
@ -1222,7 +1241,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
}
|
}
|
||||||
case INTENT_OBJECT_SAVE: {
|
case INTENT_OBJECT_SAVE: {
|
||||||
if(debug) Log.d(TAG, "onActivityResult INTENT_OBJECT_SAVE " + url);
|
if(debug) Log.d(TAG, "onActivityResult INTENT_OBJECT_SAVE " + url);
|
||||||
NativeLib.onObjectSave(url, null);
|
NativeLib.onObjectSave(url, objectsToSaveItemChecked);
|
||||||
|
objectsToSaveItemChecked = null;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case INTENT_PORT2LOAD: {
|
case INTENT_PORT2LOAD: {
|
||||||
|
@ -1544,7 +1564,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(settings.getBoolean("settings_port2en", false)) {
|
if(getPackageName().contains("org.emulator.forty.eight") && settings.getBoolean("settings_port2en", false)) {
|
||||||
// Check if the access to the port2 shared file is still possible.
|
// Check if the access to the port2 shared file is still possible.
|
||||||
String port2Url = settings.getString("settings_port2load", "");
|
String port2Url = settings.getString("settings_port2load", "");
|
||||||
if(port2Url != null && port2Url.length() > 0) {
|
if(port2Url != null && port2Url.length() > 0) {
|
||||||
|
@ -2201,9 +2221,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
mainScreenView.setRotationMode(rotationMode, isDynamic);
|
mainScreenView.setRotationMode(rotationMode, isDynamic);
|
||||||
break;
|
break;
|
||||||
case "settings_auto_layout":
|
case "settings_auto_layout":
|
||||||
int autoLayoutMode = 1;
|
int autoLayoutMode = getPackageName().contains("org.emulator.forty.eight") ? 1 : 2;
|
||||||
try {
|
try {
|
||||||
autoLayoutMode = Integer.parseInt(settings.getString("settings_auto_layout", "1"));
|
autoLayoutMode = Integer.parseInt(settings.getString("settings_auto_layout", String.valueOf(autoLayoutMode)));
|
||||||
} catch (NumberFormatException ex) {
|
} catch (NumberFormatException ex) {
|
||||||
// Catch bad number format
|
// Catch bad number format
|
||||||
}
|
}
|
||||||
|
|
4
app/src/main/res/values/ids.xml
Normal file
4
app/src/main/res/values/ids.xml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<resources>
|
||||||
|
<item type="id" name="main_screen_view"/>
|
||||||
|
</resources>
|
|
@ -7,7 +7,7 @@ buildscript {
|
||||||
jcenter()
|
jcenter()
|
||||||
}
|
}
|
||||||
dependencies {
|
dependencies {
|
||||||
classpath 'com.android.tools.build:gradle:7.0.4'
|
classpath 'com.android.tools.build:gradle:7.1.2'
|
||||||
|
|
||||||
|
|
||||||
// NOTE: Do not place your application dependencies here; they belong
|
// NOTE: Do not place your application dependencies here; they belong
|
||||||
|
|
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -3,4 +3,4 @@ distributionBase=GRADLE_USER_HOME
|
||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip
|
||||||
|
|
Loading…
Reference in a new issue