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
|
||||
|
||||
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)
|
||||
|
||||
- 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 {
|
||||
compileSdkVersion 30
|
||||
compileSdkVersion 31
|
||||
defaultConfig {
|
||||
applicationId "org.emulator.forty.eight"
|
||||
minSdkVersion 19
|
||||
targetSdkVersion 30
|
||||
versionCode 23
|
||||
versionName "2.4"
|
||||
targetSdkVersion 31
|
||||
versionCode 24
|
||||
versionName "2.5"
|
||||
setProperty("archivesBaseName", "Emu48-v$versionName")
|
||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||
externalNativeBuild {
|
||||
|
@ -84,12 +84,12 @@ android {
|
|||
|
||||
dependencies {
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'androidx.appcompat:appcompat:1.3.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.1'
|
||||
implementation 'androidx.preference:preference:1.1.1'
|
||||
implementation 'com.google.android.material:material:1.4.0'
|
||||
implementation 'androidx.appcompat:appcompat:1.4.1'
|
||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.3'
|
||||
implementation 'androidx.preference:preference:1.2.0'
|
||||
implementation 'com.google.android.material:material:1.5.0'
|
||||
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.espresso:espresso-core:3.4.0'
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
|
||||
android:launchMode="singleTop"
|
||||
android:theme="@style/AppTheme.NoActionBar"
|
||||
>
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
|
|
|
@ -58,6 +58,12 @@ LINKS
|
|||
|
||||
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)
|
||||
|
||||
- Updated source code from Eric Rechlin's Emu48 version 1.63+ that was merged from Christoph Gießelink's Emu48 version 1.64.
|
||||
|
|
|
@ -725,7 +725,7 @@ JNIEXPORT jint JNICALL Java_org_emulator_calculator_NativeLib_onFileOpen(JNIEnv
|
|||
pbyRomBackup = pbyRom;
|
||||
pbyRom = NULL;
|
||||
}
|
||||
BOOL result = OpenDocument(szBufferFilename);
|
||||
BOOL result = OpenDocument(szBufferFilename);
|
||||
if(pbyRomBackup) pbyRomBackup = NULL;
|
||||
chooseCurrentKmlMode = ChooseKmlMode_UNKNOWN;
|
||||
mainViewResizeCallback(nBackgroundW, nBackgroundH);
|
||||
|
|
|
@ -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
|
||||
// color.
|
||||
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)) {
|
||||
// Monochrome 1=White
|
||||
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
|
||||
// black pixels on a white background.
|
||||
BYTE * destinationPixel = destinationPixelBase + (x >> 3);
|
||||
UINT bitNumber = x % 8;
|
||||
UINT bitNumber = (UINT) (7 - (x % 8));
|
||||
if(backgroundColor == sourceColor) {
|
||||
*destinationPixel |= (1 << bitNumber); // 1 White
|
||||
} else {
|
||||
|
@ -2397,29 +2397,237 @@ HBITMAP CreateBitmap( int nWidth, int nHeight, UINT nPlanes, UINT nBitCount, CON
|
|||
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
|
||||
} 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) {
|
||||
PAINT_LOGD("PAINT CreateDIBitmap()");
|
||||
|
||||
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
||||
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
||||
newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP;
|
||||
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
||||
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
||||
newHBITMAP->handleType = HGDIOBJ_TYPE_BITMAP;
|
||||
|
||||
BITMAPINFO * newBitmapInfo = malloc(sizeof(BITMAPINFO));
|
||||
memcpy(newBitmapInfo, pbmi, sizeof(BITMAPINFO));
|
||||
newHBITMAP->bitmapInfo = newBitmapInfo;
|
||||
newHBITMAP->bitmapInfoHeader = (BITMAPINFOHEADER *)newBitmapInfo;
|
||||
BITMAPINFO * newBitmapInfo = malloc(sizeof(BITMAPINFO));
|
||||
memcpy(newBitmapInfo, pbmi, 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 = newBitmapInfo->bmiHeader.biSizeImage ?
|
||||
newBitmapInfo->bmiHeader.biSizeImage :
|
||||
abs(newBitmapInfo->bmiHeader.biHeight) * stride;
|
||||
VOID * bitmapBits = malloc(size);
|
||||
memcpy(bitmapBits, pjBits, size);
|
||||
newHBITMAP->bitmapBits = bitmapBits;
|
||||
return newHBITMAP;
|
||||
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 size = newBitmapInfo->bmiHeader.biSizeImage ?
|
||||
newBitmapInfo->bmiHeader.biSizeImage :
|
||||
abs(newBitmapInfo->bmiHeader.biHeight) * stride;
|
||||
bitmapBits = malloc(size);
|
||||
memcpy(bitmapBits, pjBits, size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
newHBITMAP->bitmapBits = bitmapBits;
|
||||
}
|
||||
return newHBITMAP;
|
||||
}
|
||||
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));
|
||||
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
||||
|
@ -2445,7 +2653,7 @@ HBITMAP CreateDIBSection(HDC hdc, CONST BITMAPINFO *pbmi, UINT usage, VOID **ppv
|
|||
return newHBITMAP;
|
||||
}
|
||||
HBITMAP CreateCompatibleBitmap( HDC hdc, int cx, int cy) {
|
||||
PAINT_LOGD("PAINT CreateDIBitmap()");
|
||||
PAINT_LOGD("PAINT CreateCompatibleBitmap()");
|
||||
|
||||
HGDIOBJ newHBITMAP = (HGDIOBJ)malloc(sizeof(_HGDIOBJ));
|
||||
memset(newHBITMAP, 0, sizeof(_HGDIOBJ));
|
||||
|
@ -2469,6 +2677,7 @@ HBITMAP CreateCompatibleBitmap( HDC hdc, int cx, int cy) {
|
|||
return newHBITMAP;
|
||||
}
|
||||
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;
|
||||
|
|
|
@ -811,6 +811,7 @@ typedef struct _RGNDATA {
|
|||
char Buffer[1];
|
||||
} 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 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 HPALETTE SelectPalette(HDC hdc, HPALETTE hPal, BOOL bForceBkgd);
|
||||
extern UINT RealizePalette(HDC hdc);
|
||||
|
|
|
@ -256,7 +256,7 @@ public class MainScreenView extends PanAndScaleView {
|
|||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
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)
|
||||
return false;
|
||||
char pressedKey = (char) event.getUnicodeChar();
|
||||
|
@ -277,7 +277,7 @@ public class MainScreenView extends PanAndScaleView {
|
|||
@Override
|
||||
public boolean onKeyUp(int keyCode, KeyEvent event) {
|
||||
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)
|
||||
return false;
|
||||
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) {
|
||||
// Draw the LCD grid lines without antialiasing to emulate the genuine pixels borders
|
||||
int lcdBackgroundColor = 0xFF000000 | NativeLib.getLCDBackgroundColor();
|
||||
paintLCD.setColor(lcdBackgroundColor);
|
||||
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++) {
|
||||
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;
|
||||
for (int y = 0; y < lcdHeightNative; y++) {
|
||||
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) {
|
||||
|
|
|
@ -154,7 +154,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
|
||||
drawer = findViewById(R.id.drawer_layout);
|
||||
|
@ -169,6 +169,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
|
||||
ViewGroup mainScreenContainer = findViewById(R.id.main_screen_container);
|
||||
mainScreenView = new MainScreenView(this);
|
||||
mainScreenView.setId(R.id.main_screen_view);
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
|
||||
mainScreenView.setStatusBarColor(getWindow().getStatusBarColor());
|
||||
mainScreenContainer.addView(mainScreenView, 0, new ViewGroup.LayoutParams(
|
||||
|
@ -437,6 +438,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
boolean bStackCEnable = 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_as).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_change_kml_script).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_play).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
|
||||
openDocument();
|
||||
}
|
||||
private void OnObjectSave() {
|
||||
private void SaveObject() {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
|
@ -852,6 +854,23 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
saveWhenLaunchingActivity = false;
|
||||
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() {
|
||||
Bitmap bitmapScreen = mainScreenView.getBitmap();
|
||||
if(bitmapScreen == null)
|
||||
|
@ -1147,7 +1166,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
}
|
||||
}
|
||||
|
||||
private void OnMacroRecord() {
|
||||
private void OnMacroRecord() {
|
||||
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
intent.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
intent.setType("*/*");
|
||||
|
@ -1220,11 +1239,12 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
NativeLib.onObjectLoad(url);
|
||||
break;
|
||||
}
|
||||
case INTENT_OBJECT_SAVE: {
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_OBJECT_SAVE " + url);
|
||||
NativeLib.onObjectSave(url, null);
|
||||
break;
|
||||
}
|
||||
case INTENT_OBJECT_SAVE: {
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_OBJECT_SAVE " + url);
|
||||
NativeLib.onObjectSave(url, objectsToSaveItemChecked);
|
||||
objectsToSaveItemChecked = null;
|
||||
break;
|
||||
}
|
||||
case INTENT_PORT2LOAD: {
|
||||
if(debug) Log.d(TAG, "onActivityResult INTENT_PORT2LOAD " + url);
|
||||
//TODO Duplicate code in SettingsFragment!
|
||||
|
@ -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.
|
||||
String port2Url = settings.getString("settings_port2load", "");
|
||||
if(port2Url != null && port2Url.length() > 0) {
|
||||
|
@ -2201,9 +2221,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
|||
mainScreenView.setRotationMode(rotationMode, isDynamic);
|
||||
break;
|
||||
case "settings_auto_layout":
|
||||
int autoLayoutMode = 1;
|
||||
int autoLayoutMode = getPackageName().contains("org.emulator.forty.eight") ? 1 : 2;
|
||||
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 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()
|
||||
}
|
||||
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
|
||||
|
|
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
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
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