- Add a RAM card generator for the port 2 of the HP48SX and HP48GX.

- Add the possibility to hide the status and/or the navigation bars.
This commit is contained in:
dgis 2019-04-28 00:23:37 +02:00
parent 7679d2d460
commit 32bc5a0983
18 changed files with 255 additions and 63 deletions

View file

@ -1,5 +1,8 @@
DESCRIPTION
WARNING: WITH VERSION 1.3, THE STATUS FILE HAS BEEN MODIFIED AND IS NOW FULLY COMPATIBLE WITH THE WINDOWS VERSION AS IT SHOULD HAVE BEEN.
HOWEVER, BEFORE THE UPDATE, BACK UP YOUR DATA BECAUSE YOU COULD LOSE THEM.
This project ports the Windows application Emu48 written in C to Android.
It uses the Android NDK. The former Emu48 source code remains untouched because of a thin win32 emulation layer above Linux/NDK!
This win32 layer will allow to easily update from the original Emu48 source code.
@ -24,11 +27,22 @@ QUICK START
NOTES
- When using a custom KML script by selecting a folder, you must take care of the case sensitivity of its dependency files.
- By default, in Emu48 for Windows with the HP49/50, the "HKEY_CURRENT_USER\Software\Emu48\ROM[Writeable]=1",
which allows to write the port2 (128KB) in the ROM! Because in Android, it is not possible to write in the embedded ROM,
we have the same behavior as under Windows with "HKEY_CURRENT_USER\Software\Emu48\ROM[Writeable]=0".
The port 2 is well saved in the state file "*.e49", but once this state file is reloaded,
this causes a warmstart and the port 2 is never loaded.
- Starting with the version 1.4, a RAM card generator for the port 2 of the HP48SX and HP48GX has been added.
Like with the MKSHARED.EXE on Windows, you can generate the card in a file (i.e.: SHARED.BIN).
And then, to use with the HP48SX or the HP48GX, you must select this generated file in the "Settings/Port2 File".
- By default when you create a new HP49/50 with the embedded readonly file "rom.49g",
everything that you store in port 2 is lost just because the file "rom.49g" is READONLY.
But it works exactly like with Windows. If you can write in the ROM file,
it should save the content of port 2 in the ROM file with Android too.
To save the port 2 in the HP49/50 with Emu48 for Android:
* copy "real50g-lc.kml", "real50g-lc.png", "keyb4950.kmi", "rom.49g" in a FOLDER of your Android device,
* in the menu:
- touch "New..." to create a new device
- or touch "Change KML Script..." to change the current KML script and ROM location
* select "[Custom KML script...]"
* select the FOLDER
* pick the calculator (which should be "Eric's Real 50g (Large Cropped)")!
And because, the file "FOLDER/rom.49g" is not readonly anymore, you can save your port 2.
NOT WORKING YET
@ -44,9 +58,11 @@ CHANGES
Version 1.4 (2019-04-xx)
- Add a RAM card generator for the port 2 of the HP48SX and HP48GX.
- Add the possibility to hide the status and/or the navigation bars.
- Update the Win32 layer.
- Fix the authentic speed issue at the first start.
- Fix the non working Restore/Delete backup.
- Update the Win32 layer.
Version 1.3 (2019-04-04)

View file

@ -20,6 +20,7 @@ cmake_minimum_required(VERSION 3.4.1)
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
add_compile_options(-DEMUXX=48)
include_directories(src/main/cpp/win32)
@ -72,8 +73,8 @@ add_library( # Sets the name of the library.
src/main/cpp/win32-layer.c
src/main/cpp/android-layer.c
src/main/cpp/android-emu48.c # Emu48.c rewrite
src/main/cpp/emu48-jni.c
src/main/cpp/android-emu.c # Emu48.c rewrite
src/main/cpp/emu-jni.c
)
# Specifies libraries CMake should link to your target library. You

View file

@ -33,8 +33,8 @@ android {
applicationId "org.emulator.forty.eight"
minSdkVersion 19
targetSdkVersion 28
versionCode 4
versionName "1.3"
versionCode 5
versionName "1.4"
setProperty("archivesBaseName", "Emu48-v$versionName")
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
@ -76,11 +76,11 @@ android {
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha5'
implementation 'androidx.preference:preference:1.0.0'
implementation 'com.google.android.material:material:1.1.0-alpha04'
implementation 'com.google.android.material:material:1.1.0-alpha05'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'androidx.test:runner:1.1.2-alpha02'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'
androidTestImplementation 'androidx.test:runner:1.2.0-alpha04'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha04'
}

View file

@ -27,11 +27,23 @@ QUICK START
NOTES
- When using a custom KML script by selecting a folder, you must take care of the case sensitivity of its dependency files.
- By default, in Emu48 for Windows with the HP49/50, the "HKEY_CURRENT_USER\Software\Emu48\ROM[Writeable]=1",
which allows to write the port2 (128KB) in the ROM! Because in Android, it is not possible to write in the embedded ROM,
we have the same behavior as under Windows with "HKEY_CURRENT_USER\Software\Emu48\ROM[Writeable]=0".
The port 2 is well saved in the state file "*.e49", but once this state file is reloaded,
this causes a warmstart and the port 2 is never loaded.
- Starting with the version 1.4, a RAM card generator for the port 2 of the HP48SX and HP48GX has been added.
Like with the MKSHARED.EXE on Windows, you can generate the card in a file (i.e.: SHARED.BIN).
And then, to use with the HP48SX or the HP48GX, you must select this generated file in the "Settings/Port2 File".
- By default when you create a new HP49/50 with the embedded readonly file "rom.49g",
everything that you store in port 2 is lost just because the file "rom.49g" is READONLY.
But it works exactly like with Windows. If you can write in the ROM file,
it should save the content of port 2 in the ROM file with Android too.
To save the port 2 in the HP49/50 with Emu48 for Android:
* copy "real50g-lc.kml", "real50g-lc.png", "keyb4950.kmi", "rom.49g" in a FOLDER of your Android device,
* in the menu:
- touch "New..." to create a new device
- or touch "Change KML Script..." to change the current KML script and ROM location
* select "[Custom KML script...]"
* select the FOLDER
* pick the calculator (which should be "Eric's Real 50g (Large Cropped)")!
And because, the file "FOLDER/rom.49g" is not readonly anymore, you can save your port 2.
NOT WORKING YET
@ -46,6 +58,9 @@ CHANGES
Version 1.4 (2019-04-xx)
- Add a RAM card generator for the port 2 of the HP48SX and HP48GX.
- Add the possibility to hide the status and/or the navigation bars.
- Update the Win32 layer.
- Fix the authentic speed issue at the first start.
- Fix the non working Restore/Delete backup.
@ -110,4 +125,4 @@ This program is distributed in the hope that it will be useful, but WITHOUT ANY
You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Note: some included files are not covered by the GPL; these include ROM image files (copyrighted by HP), KML files and faceplate images (copyrighted by their authors).
The Eric's Real scripts ("real*.kml" and "real*.bmp") are embedded in this application with the kind permission of Eric Rechlin.
The Eric's Real scripts ("real*.kml" and "real*.bmp") are embedded in this application with the kind permission of Eric Rechlin.

View file

@ -90,7 +90,7 @@ static LRESULT OnPaint(HWND hWindow)
PAINTSTRUCT Paint;
HDC hPaintDC;
PAINT_LOGD("Emu48-PAINT OnPaint()");
PAINT_LOGD("PAINT OnPaint()");
//UpdateWindowBars(); // update visibility of title and menu bar
@ -108,7 +108,7 @@ static LRESULT OnPaint(HWND hWindow)
UINT nLines = MAINSCREENHEIGHT;
// redraw background bitmap
PAINT_LOGD("Emu48-PAINT OnPaint() BitBlt()");
PAINT_LOGD("PAINT OnPaint() BitBlt()");
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);

View file

@ -803,7 +803,7 @@ JNIEXPORT void JNICALL Java_org_emulator_forty_eight_NativeLib_onViewReset(JNIEn
SwitchToState(SM_RUN);
}
JNIEXPORT int JNICALL Java_org_emulator_forty_eight_NativeLib_onViewScript(JNIEnv *env, jobject thisz, jstring kmlFilename) {
JNIEXPORT jint JNICALL Java_org_emulator_forty_eight_NativeLib_onViewScript(JNIEnv *env, jobject thisz, jstring kmlFilename) {
TCHAR szKmlFile[MAX_PATH];
// BOOL bKMLChanged,bSucc;

View file

@ -14,7 +14,6 @@ extern JavaVM *java_machine;
extern jobject bitmapMainScreen;
extern AndroidBitmapInfo androidBitmapInfo;
HANDLE hWnd;
LPTSTR szTitle;
LPTSTR szCurrentAssetDirectory = NULL;
@ -94,12 +93,14 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
{
FILE_LOGD("CreateFile(lpFileName: \"%s\", dwDesiredAccess: 0x%08x)", lpFileName, dwShareMode);
BOOL forceNormalFile = FALSE;
// if(_tcscmp(lpFileName, szPort2Filename) == 0) {
// // Special case for Port2 filename
// forceNormalFile = TRUE;
// if(!settingsPort2wr && (dwDesiredAccess & GENERIC_WRITE))
// return (HANDLE) INVALID_HANDLE_VALUE;
// }
#if EMUXX == 48
if(_tcscmp(lpFileName, szPort2Filename) == 0) {
// Special case for Port2 filename
forceNormalFile = TRUE;
if(!settingsPort2wr && (dwDesiredAccess & GENERIC_WRITE))
return (HANDLE) INVALID_HANDLE_VALUE;
}
#endif
TCHAR * foundDocumentScheme = _tcsstr(lpFileName, documentScheme);
@ -117,7 +118,9 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
if(filename) {
*filename = _T('\0');
}
//_tcscpy(szRomDirectory, szEmuDirectory);
#if EMUXX == 48
_tcscpy(szRomDirectory, szEmuDirectory);
#endif
SetCurrentDirectory(szEmuDirectory);
} else if(foundDocumentScheme) {
// With a recorded "document:" scheme, extract the folder URL with content:// scheme
@ -126,11 +129,15 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
if(filename) {
*filename = _T('\0');
}
//_tcscpy(szRomDirectory, szEmuDirectory);
#if EMUXX == 48
_tcscpy(szRomDirectory, szEmuDirectory);
#endif
SetCurrentDirectory(szEmuDirectory);
} else {
_tcscpy(szEmuDirectory, "assets/calculators/");
//_tcscpy(szRomDirectory, "assets/calculators/");
#if EMUXX == 48
_tcscpy(szRomDirectory, "assets/calculators/");
#endif
SetCurrentDirectory(szEmuDirectory);
}
}
@ -902,6 +909,9 @@ void onPlayerDoneTimerCallback(void *context) {
WAVE_OUT_LOGD("waveOut onPlayerDoneTimerCallback()");
HWAVEOUT hwo = context;
onPlayerDone(hwo);
//TODO May be needed if an attached occurs in the future
//jniDetachCurrentThread();
}
#endif
@ -2151,6 +2161,8 @@ void timerCallback(int timerId) {
TIMER_LOGD("timerCallback remove timer uTimerID [%d]", timerId + 1);
deleteTimeEvent((UINT) (timerId + 1));
}
jniDetachCurrentThread();
}
}
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {

View file

@ -10,7 +10,7 @@
#include <android/bitmap.h>
#include <android/asset_manager.h>
#include <android/log.h>
#define LOG_TAG "NDK_NativeEmu48"
#define LOG_TAG "NDK_NativeEmuXX"
#define LOGD(...) ((void)__android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__))
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))

View file

@ -1,5 +1,6 @@
package org.emulator.forty.eight;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.ClipData;
import android.content.ClipboardManager;
@ -24,20 +25,34 @@ import android.view.SubMenu;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.ImageButton;
import android.widget.TextView;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.core.view.GravityCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.drawerlayout.widget.DrawerLayout;
import com.google.android.material.navigation.NavigationView;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.Date;
@ -52,17 +67,6 @@ import java.util.Set;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBarDrawerToggle;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.content.FileProvider;
import androidx.core.view.GravityCompat;
import androidx.documentfile.provider.DocumentFile;
import androidx.drawerlayout.widget.DrawerLayout;
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
private static final String TAG = "MainActivity";
@ -81,12 +85,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
public static final int INTENT_PICK_KML_FOLDER_FOR_NEW_FILE = 7;
public static final int INTENT_PICK_KML_FOLDER_FOR_CHANGING = 8;
public static final int INTENT_PICK_KML_FOLDER_FOR_SETTINGS = 9;
public static final int INTENT_CREATE_RAM_CARD = 10;
private String kmlMimeType = "application/vnd.google-earth.kml+xml";
private boolean kmlFolderUseDefault = true;
private String kmlFolderURL = "";
private boolean kmFolderChange = true;
private int selectedRAMSize = -1;
private int MRU_ID_START = 10000;
private int MAX_MRU = 5;
private LinkedHashMap<String, String> mruLinkedHashMap = new LinkedHashMap<String, String>(5, 1.0f, true) {
@ -245,7 +252,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
@Override
public void onBackPressed() {
DrawerLayout drawer = findViewById(R.id.drawer_layout);
if (drawer.isDrawerOpen(GravityCompat.START)) {
drawer.closeDrawer(GravityCompat.START);
} else {
@ -312,6 +318,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
OnBackupDelete();
} else if (id == R.id.nav_change_kml_script) {
OnViewScript();
} else if (id == R.id.nav_create_ram_card) {
OnCreateRAMCard();
} else if (id == R.id.nav_help) {
OnTopics();
} else if (id == R.id.nav_about) {
@ -337,7 +345,6 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
DrawerLayout drawer = findViewById(R.id.drawer_layout);
drawer.closeDrawer(GravityCompat.START);
return true;
}
@ -615,6 +622,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
case 'S': //HP48SX
case 'G': //HP48GX
extension = "e48";
break;
case '6': //HP38G 64K RAM
case 'A': //HP38G 32K RAM
extension = "e38";
@ -814,6 +822,54 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}).show();
}
private void OnCreateRAMCard() {
String[] stringArrayRAMCards = getResources().getStringArray(R.array.ram_cards);
new AlertDialog.Builder(MainActivity.this)
.setTitle(getResources().getString(R.string.create_ram_card_title))
.setItems(stringArrayRAMCards, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent(Intent.ACTION_CREATE_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("*/*");
String sizeTitle = "2mb";
selectedRAMSize = -1;
switch (which) {
case 0: // 32kb (1 port: 2)
sizeTitle = "32kb";
selectedRAMSize = 32;
break;
case 1: // 128kb (1 port: 2)
sizeTitle = "128kb";
selectedRAMSize = 128;
break;
case 2: // 256kb (2 ports: 2,3)
sizeTitle = "256kb";
selectedRAMSize = 256;
break;
case 3: // 512kb (4 ports: 2 through 5)
sizeTitle = "512kb";
selectedRAMSize = 512;
break;
case 4: // 1mb (8 ports: 2 through 9)
sizeTitle = "1mb";
selectedRAMSize = 1024;
break;
case 5: // 2mb (16 ports: 2 through 17)
sizeTitle = "2mb";
selectedRAMSize = 2048;
break;
case 6: // 4mb (32 ports: 2 through 33)
sizeTitle = "4mb";
selectedRAMSize = 4096;
break;
}
intent.putExtra(Intent.EXTRA_TITLE, "shared-" + sizeTitle + ".bin");
startActivityForResult(intent, INTENT_CREATE_RAM_CARD);
}
}).show();
}
private void OnTopics() {
startActivity(new Intent(this, InfoWebActivity.class));
}
@ -910,6 +966,30 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
break;
}
case INTENT_CREATE_RAM_CARD: {
//Log.d(TAG, "onActivityResult INTENT_CREATE_RAM_CARD " + url);
if(selectedRAMSize > 0) {
int size = 2 * selectedRAMSize;
FileOutputStream fileOutputStream = null;
try {
ParcelFileDescriptor pfd = getContentResolver().openFileDescriptor(uri, "w");
fileOutputStream = new FileOutputStream(pfd.getFileDescriptor());
byte[] zero = new byte[1024];
Arrays.fill(zero, (byte) 0);
for (int i = 0; i < size; i++)
fileOutputStream.write(zero);
fileOutputStream.flush();
fileOutputStream.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
selectedRAMSize = -1;
}
break;
}
default:
break;
}
@ -1208,7 +1288,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
if(key == null) {
String[] settingKeys = {
"settings_realspeed", "settings_grayscale", "settings_allow_rotation", "settings_fill_screen",
"settings_scale", "settings_allow_sound", "settings_haptic_feedback",
"settings_hide_bar", "settings_scale", "settings_allow_sound", "settings_haptic_feedback",
"settings_background_kml_color", "settings_background_fallback_color",
"settings_kml", "settings_port1", "settings_port2" };
for (String settingKey : settingKeys) {
@ -1232,6 +1312,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
case "settings_fill_screen":
mainScreenView.setFillScreen(sharedPreferences.getBoolean("settings_fill_screen", false));
break;
case "settings_hide_bar":
case "settings_hide_bar_status":
case "settings_hide_bar_nav":
if(sharedPreferences.getBoolean("settings_hide_bar_status", false)
|| sharedPreferences.getBoolean("settings_hide_bar_nav", false))
hideSystemUI();
else
showSystemUI();
break;
case "settings_scale":
//mainScreenView.setScale(1.0f); //sharedPreferences.getFloat("settings_scale", 0.0f));
break;
@ -1288,4 +1377,29 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
}
}
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus && (
sharedPreferences.getBoolean("settings_hide_bar_status", false)
|| sharedPreferences.getBoolean("settings_hide_bar_nav", false)
)) {
hideSystemUI();
}
}
private void hideSystemUI() {
int flags = View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
if(sharedPreferences.getBoolean("settings_hide_bar_status", false))
flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
if(sharedPreferences.getBoolean("settings_hide_bar_nav", false))
flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
getWindow().getDecorView().setSystemUiVisibility(flags);
}
private void showSystemUI() {
getWindow().getDecorView().setSystemUiVisibility(0);
}
}

View file

@ -225,7 +225,7 @@ public class MainScreenView extends SurfaceView {
@Override
protected void onDraw(Canvas canvas) {
//Log.d(TAG, "Emu48-PAINT onDraw() mIsScaling: " + mIsScaling + ", mIsPanning: " + mIsPanning + ", mIsFlinging: " + mIsFlinging);
//Log.d(TAG, "PAINT onDraw() mIsScaling: " + mIsScaling + ", mIsPanning: " + mIsPanning + ", mIsFlinging: " + mIsFlinging);
canvas.drawColor(getBackgroundColor());
@ -242,13 +242,13 @@ public class MainScreenView extends SurfaceView {
int updateCallback(int type, int param1, int param2, String param3, String param4) {
switch (type) {
case CALLBACK_TYPE_INVALIDATE:
//Log.d(TAG, "Emu48-PAINT updateCallback() postInvalidate()");
//Log.d(TAG, "PAINT updateCallback() postInvalidate()");
postInvalidate();
break;
case CALLBACK_TYPE_WINDOW_RESIZE:
// New Bitmap size
if(bitmapMainScreen == null || bitmapMainScreen.getWidth() != param1 || bitmapMainScreen.getHeight() != param2) {
//Log.d(TAG, "Emu48-PAINT updateCallback() Bitmap.createBitmap(x: " + Math.max(1, param1) + ", y: " + Math.max(1, param2) + ")");
//Log.d(TAG, "PAINT updateCallback() Bitmap.createBitmap(x: " + Math.max(1, param1) + ", y: " + Math.max(1, param2) + ")");
Bitmap oldBitmapMainScreen = bitmapMainScreen;
bitmapMainScreen = Bitmap.createBitmap(Math.max(1, param1), Math.max(1, param2), Bitmap.Config.ARGB_8888);
int globalColor = NativeLib.getGlobalColor();

View file

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#FF000000"
android:pathData="M15,9L9,9v6h6L15,9zM13,13h-2v-2h2v2zM21,11L21,9h-2L19,7c0,-1.1 -0.9,-2 -2,-2h-2L15,3h-2v2h-2L11,3L9,3v2L7,5c-1.1,0 -2,0.9 -2,2v2L3,9v2h2v2L3,13v2h2v2c0,1.1 0.9,2 2,2h2v2h2v-2h2v2h2v-2h2c1.1,0 2,-0.9 2,-2v-2h2v-2h-2v-2h2zM17,17L7,17L7,7h10v10z"/>
</vector>

View file

@ -6,8 +6,8 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="org.emulator.forty.eight.MainActivity"
android:fitsSystemWindows="true"
tools:openDrawer="start">
<!--android:fitsSystemWindows="true"-->
<include
layout="@layout/app_bar_main"

View file

@ -24,13 +24,4 @@
<include layout="@layout/content_main" />
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="@dimen/fab_margin"
android:visibility="gone"
app:srcCompat="@android:drawable/ic_dialog_email" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View file

@ -90,6 +90,14 @@
android:title="@string/nav_change_kml_script" />
</menu>
</item>
<item android:title="@string/nav_tool">
<menu>
<item
android:id="@+id/nav_create_ram_card"
android:icon="@drawable/ic_memory_black_24dp"
android:title="@string/nav_create_ram_card" />
</menu>
</item>
<item android:title="@string/nav_help">
<menu>
<item

View file

@ -12,4 +12,14 @@
<!--<item>2</item>-->
</string-array>
<string-array name="ram_cards">
<item>32kb (1 port: 2)</item>
<item>128kb (1 port: 2)</item>
<item>256kb (2 ports: 2,3)</item>
<item>512kb (4 ports: 2 through 5)</item>
<item>1mb (8 ports: 2 through 9)</item>
<item>2mb (16 ports: 2 through 17)</item>
<item>4mb (32 ports: 2 through 33)</item>
</string-array>
</resources>

View file

@ -4,5 +4,4 @@
<!--<dimen name="activity_vertical_margin">16dp</dimen>-->
<dimen name="nav_header_vertical_spacing">8dp</dimen>
<!--<dimen name="nav_header_height">176dp</dimen>-->
<dimen name="fab_margin">16dp</dimen>
</resources>

View file

@ -40,12 +40,19 @@
<string name="nav_delete_backup">Delete Backup</string>
<string name="nav_view">View</string>
<string name="nav_change_kml_script">Change KML Script...</string>
<string name="nav_tool">Tool</string>
<string name="nav_create_ram_card">Create RAM Card...</string>
<string name="nav_help">Help</string>
<string name="nav_item_help">Help</string>
<string name="nav_about">About Emu48...</string>
<string name="load_custom_kml">[Custom KML script...]</string>
<string name="load_default_kml">[Default KML script]</string>
<string name="pick_calculator">Pick a calculator</string>
<string name="create_ram_card_title">Create RAM Card</string>
<string name="message_state_saved">State saved</string>
<string name="message_do_you_want_to_save">Do you want to save changes?\n(BACK to cancel)</string>
<string name="message_yes">Yes</string>
@ -64,6 +71,8 @@
<string name="settings_alwaysdisplog_title">Always Show KML Compilation Result</string>
<string name="settings_allow_rotation_title">Allow rotation</string>
<string name="settings_fill_screen_title">Fill screen</string>
<string name="settings_hide_bar_status">Hide the status bar</string>
<string name="settings_hide_bar_nav">Hide the navigation bar</string>
<string name="settings_allow_sound_title">Allow sounds</string>
<string name="settings_haptic_feedback_title">Allow haptic feedback</string>
<string name="settings_category_background_title">Background Color</string>

View file

@ -32,6 +32,14 @@
android:key="settings_fill_screen"
android:title="@string/settings_fill_screen_title"
android:defaultValue="false" />
<SwitchPreference
android:key="settings_hide_bar_status"
android:title="@string/settings_hide_bar_status"
android:defaultValue="false" />
<SwitchPreference
android:key="settings_hide_bar_nav"
android:title="@string/settings_hide_bar_nav"
android:defaultValue="false" />
<SwitchPreference
android:key="settings_allow_sound"
android:title="@string/settings_allow_sound_title"