From 5e0c56d44cab81deaddfd1ca2338531984299093 Mon Sep 17 00:00:00 2001 From: Regis Cosnier Date: Fri, 8 Mar 2019 01:55:50 +0100 Subject: [PATCH] - Rewrite the StretchBlt() function to improve the pixel rendering. - Allow to build the project with "gradlew build". --- .gitignore | 5 +- ReadMe.txt | 9 ++-- app/CMakeLists.txt | 2 + app/build.gradle | 3 ++ .../forty/eight}/ExampleInstrumentedTest.java | 5 +- app/src/main/AndroidManifest.xml | 2 + app/src/main/assets/ReadMe.txt | 6 ++- app/src/main/cpp/win32-layer.c | 53 +++++++------------ .../emulator/forty/eight/MainActivity.java | 5 +- .../emulator/forty/eight/MainScreenView.java | 15 ++++-- .../res/drawable/ic_file_copy_black_24dp.xml | 2 +- .../res/drawable/ic_save_alt_black_24dp.xml | 2 +- .../forty/eight}/ExampleUnitTest.java | 0 13 files changed, 58 insertions(+), 51 deletions(-) rename app/src/androidTest/java/{com/regis/cosnier/emu48 => org/emulator/forty/eight}/ExampleInstrumentedTest.java (82%) rename app/src/test/java/{com/regis/cosnier/emu48 => org/emulator/forty/eight}/ExampleUnitTest.java (100%) diff --git a/.gitignore b/.gitignore index cc6ccda..341c6f3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,10 +1,7 @@ *.iml .gradle /local.properties -/.idea/caches/build_file_checksums.ser -/.idea/libraries -/.idea/modules.xml -/.idea/workspace.xml +.idea .DS_Store /build /captures diff --git a/ReadMe.txt b/ReadMe.txt index 97cce20..8861cdd 100644 --- a/ReadMe.txt +++ b/ReadMe.txt @@ -32,13 +32,15 @@ NOT WORKING YET CHANGES -Version 1.2 (2019-03-XX) +Version 1.2alpha (2019-03-XX) - Use the KML Global color as background color. - Set the extension .e49 when "Saving as" a state file with model 'Q'. - Fix a crash after opening several times a state file. - Fix On-D diagnostic not working for 48gII/49G/49g+/50g (rom 2.15 not good, change for 2.10). -- Fix the scrolling issue found in Emu48 1.59+ +- Improve the scrolling issue found in Emu48 1.59+. +- Rewrite the StretchBlt() function to improve the pixel rendering. +- Allow to build the project with "gradlew build". Version 1.1 (2019-03-01) @@ -66,9 +68,9 @@ Note: some included files are not covered by the GPL; these include ROM image fi The Eric's Real scripts ("real*.kml" and "real*.bmp") are embedded in this application with the kind permission of Eric Rechlin. TODO +- Build with Android 4.0 - Add a separation between the pixels (Suggestion from Jaime Meza) - Sometimes the "busy" annunciator gets stuck -- Pixel alignment (pixel squeeze?) issue - Add KML script loading dependencies fallback to the inner ROM (and may be KML include?) - Add haptic feedback when touch a button - Add a true fullscreen mode under the status bar and the bottom buttons @@ -114,3 +116,4 @@ DONE - Fix sound error at the initialization - Open Emu48 with a state (content://) file shared with it - Add sound switch settings +- Pixel alignment (pixel squeeze?) issue diff --git a/app/CMakeLists.txt b/app/CMakeLists.txt index 65dd1fb..44604c6 100644 --- a/app/CMakeLists.txt +++ b/app/CMakeLists.txt @@ -5,6 +5,8 @@ cmake_minimum_required(VERSION 3.4.1) +#add_compile_options(-D DEBUG_DISPLAY) + include_directories(src/main/cpp/win32) # Creates and names a library, sets it as either STATIC diff --git a/app/build.gradle b/app/build.gradle index 9f9fe52..0368943 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -37,4 +37,7 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha2' implementation 'com.google.android.material:material:1.1.0-alpha01' implementation 'com.android.support.constraint:constraint-layout:1.1.3' + testImplementation 'junit:junit:4.12' + androidTestImplementation 'androidx.test:runner:1.1.0-alpha4' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.0-alpha4' } diff --git a/app/src/androidTest/java/com/regis/cosnier/emu48/ExampleInstrumentedTest.java b/app/src/androidTest/java/org/emulator/forty/eight/ExampleInstrumentedTest.java similarity index 82% rename from app/src/androidTest/java/com/regis/cosnier/emu48/ExampleInstrumentedTest.java rename to app/src/androidTest/java/org/emulator/forty/eight/ExampleInstrumentedTest.java index 10a341b..05f5cf3 100644 --- a/app/src/androidTest/java/com/regis/cosnier/emu48/ExampleInstrumentedTest.java +++ b/app/src/androidTest/java/org/emulator/forty/eight/ExampleInstrumentedTest.java @@ -1,8 +1,9 @@ package org.emulator.forty.eight; import android.content.Context; -import android.support.test.InstrumentationRegistry; -import android.support.test.runner.AndroidJUnit4; + +import androidx.test.InstrumentationRegistry; +import androidx.test.runner.AndroidJUnit4; import org.junit.Test; import org.junit.runner.RunWith; diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index d245a2f..a822662 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -73,6 +73,7 @@ bitmapInfoHeader->biHeight); destinationBytes = hBitmapDestination->bitmapInfoHeader->biBitCount >> 3; - destinationStride = (float)(destinationBytes * ((destinationWidth * hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32)); + destinationStride = (float)(4 * ((destinationWidth * hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32)); } HPALETTE palette = hdcDest->realizedPalette; @@ -1404,11 +1404,9 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc int sourceBitCount = hBitmapSource->bitmapInfoHeader->biBitCount; int sourceBytes = sourceBitCount >> 3; - float sourceBytesWithDecimal = (float)sourceBitCount / 8.0f; - //TODO float sourceStride = (float)(sourceBytesWithDecimal * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32)); - float sourceStride = (float)(4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32)); + int sourceStride = 4 * ((sourceWidth * hBitmapSource->bitmapInfoHeader->biBitCount + 31) / 32); int destinationBytes = 0; - float destinationStride = 0; + int destinationStride = 0; JNIEnv * jniEnv = NULL; @@ -1444,24 +1442,12 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc destinationHeight = abs(hBitmapDestination->bitmapInfoHeader->biHeight); destinationBytes = (hBitmapDestination->bitmapInfoHeader->biBitCount >> 3); - destinationStride = (float)(destinationBytes * ((destinationWidth * hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32)); + destinationStride = destinationBytes * ((destinationWidth * hBitmapDestination->bitmapInfoHeader->biBitCount + 31) / 32); } xDest -= hdcDest->windowOrigineX; yDest -= hdcDest->windowOrigineY; - //https://softwareengineering.stackexchange.com/questions/148123/what-is-the-algorithm-to-copy-a-region-of-one-bitmap-into-a-region-in-another - float src_dx = (float)wSrc / (float)wDest; - float src_dy = (float)hSrc / (float)hDest; - float dst_maxx = xDest + wDest; - float dst_maxy = yDest + hDest; - float src_cury = ySrc; - - if(reverseHeight == FALSE) { - src_dy = -src_dy; - src_cury = sourceHeight - 1 - src_cury; - } - //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, sourceBytesWithDecimal); HPALETTE palette = hdcSrc->realizedPalette; if(!palette) @@ -1469,16 +1455,21 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc PALETTEENTRY * palPalEntry = palette && palette->paletteLog && palette->paletteLog->palPalEntry ? palette->paletteLog->palPalEntry : NULL; - for (float y = yDest; y < dst_maxy; y++) { - float src_curx = xSrc; - BYTE parity = xSrc; - for (float x = xDest; x < dst_maxx; x++, parity++) { - // Point sampling - you can also impl as bilinear or other + int dst_maxx = xDest + wDest; + int dst_maxy = yDest + hDest; + for (int y = yDest; y < dst_maxy; y++) { + int src_cury = ySrc + (y - yDest) * hSrc / hDest; + if(!reverseHeight) + src_cury = sourceHeight - 1 - src_cury; + 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_cury < 0 || src_curx >= sourceWidth || src_cury >= sourceHeight) + continue; - - float currentXBytes = sourceBytesWithDecimal * (int)src_curx; - BYTE * sourcePixel = pixelsSource + (int)(sourceStride * (int)src_cury) + (int)currentXBytes; - BYTE * destinationPixel = pixelsDestination + (int)(destinationStride * y + 4.0 * x); + int currentXBytes = ((sourceBitCount >> 2) * src_curx) >> 1; + BYTE * sourcePixel = pixelsSource + sourceStride * src_cury + currentXBytes; + BYTE * destinationPixel = pixelsDestination + destinationStride * y + 4 * x; // -> ARGB_8888 switch (sourceBitCount) { @@ -1486,7 +1477,7 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc BYTE colorIndex = (parity & 0x1 ? sourcePixel[0] & (BYTE)0x0F : sourcePixel[0] >> 4); //BYTE colorIndex = (parity & 0x1 ? sourcePixel[0] >> 4 : sourcePixel[0] & (BYTE)0x0F); if (palPalEntry) { - destinationPixel[0] = palPalEntry[colorIndex].peRed; //TODO Exchange Blue and Red? + destinationPixel[0] = palPalEntry[colorIndex].peRed; destinationPixel[1] = palPalEntry[colorIndex].peGreen; destinationPixel[2] = palPalEntry[colorIndex].peBlue; destinationPixel[3] = 255; @@ -1501,7 +1492,7 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc case 8: { BYTE colorIndex = sourcePixel[0]; if (palPalEntry) { - destinationPixel[0] = palPalEntry[colorIndex].peRed; //TODO Exchange Blue and Red? + destinationPixel[0] = palPalEntry[colorIndex].peRed; destinationPixel[1] = palPalEntry[colorIndex].peGreen; destinationPixel[2] = palPalEntry[colorIndex].peBlue; destinationPixel[3] = 255; @@ -1525,11 +1516,7 @@ BOOL StretchBlt(HDC hdcDest, int xDest, int yDest, int wDest, int hDest, HDC hdc default: break; } - - src_curx += src_dx; } - - src_cury += src_dy; } if(jniEnv) 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 8cd70ec..d84cb96 100644 --- a/app/src/main/java/org/emulator/forty/eight/MainActivity.java +++ b/app/src/main/java/org/emulator/forty/eight/MainActivity.java @@ -1177,7 +1177,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On private void updateFromPreferences(String key, boolean isDynamic) { int isDynamicValue = isDynamic ? 1 : 0; if(key == null) { - String[] settingKeys = { "settings_realspeed", "settings_grayscale", "settings_allow_rotation", "settings_fill_screen", "settings_allow_sound", "settings_kml", "settings_port1", "settings_port2" }; + String[] settingKeys = { "settings_realspeed", "settings_grayscale", "settings_allow_rotation", "settings_fill_screen", "settings_scale", "settings_allow_sound", "settings_kml", "settings_port1", "settings_port2" }; for (String settingKey : settingKeys) { updateFromPreferences(settingKey, false); } @@ -1199,6 +1199,9 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On case "settings_fill_screen": mainScreenView.setFillScreen(sharedPreferences.getBoolean("settings_fill_screen", false)); break; + case "settings_scale": + //mainScreenView.setScale(1.0f); //sharedPreferences.getFloat("settings_scale", 0.0f)); + break; case "settings_allow_sound": NativeLib.setConfiguration("settings_sound_volume", isDynamicValue, diff --git a/app/src/main/java/org/emulator/forty/eight/MainScreenView.java b/app/src/main/java/org/emulator/forty/eight/MainScreenView.java index f714424..2de1513 100644 --- a/app/src/main/java/org/emulator/forty/eight/MainScreenView.java +++ b/app/src/main/java/org/emulator/forty/eight/MainScreenView.java @@ -27,6 +27,7 @@ public class MainScreenView extends SurfaceView { private float screenOffsetX = 0.0f; private float screenOffsetY= 0.0f; private boolean fillScreen = false; + private float fixScale = 0.0f; private int backgroundColor = Color.BLACK; public MainScreenView(Context context) { @@ -201,13 +202,13 @@ public class MainScreenView extends SurfaceView { float viewRatio = (float)viewHeight / (float)viewWidth; float imageRatio = imageSizeY / imageSizeX; if(viewRatio > imageRatio) { - scaleX = scaleY = viewWidth / imageSizeX; - translateX = 0.0f; + scaleX = scaleY = this.fixScale != 0.0f ? this.fixScale : viewWidth / imageSizeX; + translateX = (viewWidth - scaleX * imageSizeX) / 2.0f; //0.0f; translateY = (viewHeight - scaleY * imageSizeY) / 2.0f; } else { - scaleX = scaleY = viewHeight / imageSizeY; + scaleX = scaleY = this.fixScale != 0.0f ? this.fixScale : viewHeight / imageSizeY; translateX = (viewWidth - scaleX * imageSizeX) / 2.0f; - translateY = 0.0f; + translateY = (viewHeight - scaleY * imageSizeY) / 2.0f; //0.0f; } } @@ -271,4 +272,10 @@ public class MainScreenView extends SurfaceView { calcTranslateAndScale(getWidth(), getHeight()); postInvalidate(); } + + public void setScale(float scale) { + this.fixScale = scale; + calcTranslateAndScale(getWidth(), getHeight()); + postInvalidate(); + } } diff --git a/app/src/main/res/drawable/ic_file_copy_black_24dp.xml b/app/src/main/res/drawable/ic_file_copy_black_24dp.xml index 3df37f1..999e7a1 100644 --- a/app/src/main/res/drawable/ic_file_copy_black_24dp.xml +++ b/app/src/main/res/drawable/ic_file_copy_black_24dp.xml @@ -5,5 +5,5 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> - + \ No newline at end of file diff --git a/app/src/main/res/drawable/ic_save_alt_black_24dp.xml b/app/src/main/res/drawable/ic_save_alt_black_24dp.xml index 809268c..2e33862 100644 --- a/app/src/main/res/drawable/ic_save_alt_black_24dp.xml +++ b/app/src/main/res/drawable/ic_save_alt_black_24dp.xml @@ -5,5 +5,5 @@ android:viewportWidth="24.0" android:viewportHeight="24.0"> + android:pathData="m 19,12 v 7 H 5 V 12 H 3 v 7 c 0,1.1 0.9,2 2,2 h 14 c 1.1,0 2,-0.9 2,-2 v -7 z m -6,0.67 2.59,-2.58 1.41,1.41 -5,5 -5,-5 1.41,-1.41 2.59,2.58 V 3 h 2 z"/> \ No newline at end of file diff --git a/app/src/test/java/com/regis/cosnier/emu48/ExampleUnitTest.java b/app/src/test/java/org/emulator/forty/eight/ExampleUnitTest.java similarity index 100% rename from app/src/test/java/com/regis/cosnier/emu48/ExampleUnitTest.java rename to app/src/test/java/org/emulator/forty/eight/ExampleUnitTest.java