- Rewrite the StretchBlt() function to improve the pixel rendering.

- Allow to build the project with "gradlew build".
This commit is contained in:
Regis Cosnier 2019-03-08 01:55:50 +01:00
parent a0844c5023
commit 5e0c56d44c
13 changed files with 58 additions and 51 deletions

5
.gitignore vendored
View file

@ -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

View file

@ -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

View file

@ -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

View file

@ -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'
}

View file

@ -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;

View file

@ -73,6 +73,7 @@
</activity>
<activity
android:name="org.emulator.forty.eight.InfoWebActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:label="@string/title_web_activity_info">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
@ -80,6 +81,7 @@
</activity>
<activity
android:name="org.emulator.forty.eight.InfoActivity"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout"
android:label="@string/title_activity_info">
<meta-data
android:name="android.support.PARENT_ACTIVITY"

View file

@ -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).
- Improve 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)

View file

@ -1333,7 +1333,7 @@ BOOL PatBlt(HDC hdcDest, int x, int y, int w, int h, DWORD rop) {
destinationHeight = abs(hBitmapDestination->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)

View file

@ -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,

View file

@ -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();
}
}

View file

@ -5,5 +5,5 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path android:fillColor="#FF000000" android:pathData="M16 1H4c-1.1 0-2 .9-2 2v14h2V3h12V1zm-1 4l6 6v10c0 1.1-.9 2-2 2H7.99C6.89 23 6 22.1 6 21l.01-14c0-1.1.89-2 1.99-2h7zm-1 7h5.5L14 6.5V12z"/>
<path android:fillColor="#FF000000" android:pathData="M 16,1 H 4 C 2.9,1 2,1.9 2,3 V 17 H 4 V 3 h 12 z m -1,4 6,6 v 10 c 0,1.1 -0.9,2 -2,2 H 7.99 C 6.89,23 6,22.1 6,21 L 6.01,7 C 6.01,5.9 6.9,5 8,5 Z m -1,7 h 5.5 L 14,6.5 Z"/>
</vector>

View file

@ -5,5 +5,5 @@
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path android:fillColor="#FF000000"
android:pathData="M19 12v7H5v-7H3v7c0 1.1.9 2 2 2h14c1.1 0 2-.9 2-2v-7h-2zm-6 .67l2.59-2.58L17 11.5l-5 5-5-5 1.41-1.41L11 12.67V3h2z"/>
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"/>
</vector>