mirror of
https://github.com/dgis/emu48android
synced 2024-12-28 09:58:32 +01:00
- 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:
parent
7679d2d460
commit
32bc5a0983
18 changed files with 255 additions and 63 deletions
28
ReadMe.txt
28
ReadMe.txt
|
@ -1,5 +1,8 @@
|
||||||
DESCRIPTION
|
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.
|
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!
|
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.
|
This win32 layer will allow to easily update from the original Emu48 source code.
|
||||||
|
@ -24,11 +27,22 @@ QUICK START
|
||||||
NOTES
|
NOTES
|
||||||
|
|
||||||
- When using a custom KML script by selecting a folder, you must take care of the case sensitivity of its dependency files.
|
- 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",
|
- Starting with the version 1.4, a RAM card generator for the port 2 of the HP48SX and HP48GX has been added.
|
||||||
which allows to write the port2 (128KB) in the ROM! Because in Android, it is not possible to write in the embedded ROM,
|
Like with the MKSHARED.EXE on Windows, you can generate the card in a file (i.e.: SHARED.BIN).
|
||||||
we have the same behavior as under Windows with "HKEY_CURRENT_USER\Software\Emu48\ROM[Writeable]=0".
|
And then, to use with the HP48SX or the HP48GX, you must select this generated file in the "Settings/Port2 File".
|
||||||
The port 2 is well saved in the state file "*.e49", but once this state file is reloaded,
|
- By default when you create a new HP49/50 with the embedded readonly file "rom.49g",
|
||||||
this causes a warmstart and the port 2 is never loaded.
|
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
|
NOT WORKING YET
|
||||||
|
@ -44,9 +58,11 @@ CHANGES
|
||||||
|
|
||||||
Version 1.4 (2019-04-xx)
|
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 authentic speed issue at the first start.
|
||||||
- Fix the non working Restore/Delete backup.
|
- Fix the non working Restore/Delete backup.
|
||||||
- Update the Win32 layer.
|
|
||||||
|
|
||||||
|
|
||||||
Version 1.3 (2019-04-04)
|
Version 1.3 (2019-04-04)
|
||||||
|
|
|
@ -20,6 +20,7 @@ cmake_minimum_required(VERSION 3.4.1)
|
||||||
|
|
||||||
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
|
#add_compile_options(-DNEW_WIN32_SOUND_ENGINE)
|
||||||
|
|
||||||
|
add_compile_options(-DEMUXX=48)
|
||||||
|
|
||||||
include_directories(src/main/cpp/win32)
|
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/win32-layer.c
|
||||||
src/main/cpp/android-layer.c
|
src/main/cpp/android-layer.c
|
||||||
src/main/cpp/android-emu48.c # Emu48.c rewrite
|
src/main/cpp/android-emu.c # Emu48.c rewrite
|
||||||
src/main/cpp/emu48-jni.c
|
src/main/cpp/emu-jni.c
|
||||||
)
|
)
|
||||||
|
|
||||||
# Specifies libraries CMake should link to your target library. You
|
# Specifies libraries CMake should link to your target library. You
|
||||||
|
|
|
@ -33,8 +33,8 @@ android {
|
||||||
applicationId "org.emulator.forty.eight"
|
applicationId "org.emulator.forty.eight"
|
||||||
minSdkVersion 19
|
minSdkVersion 19
|
||||||
targetSdkVersion 28
|
targetSdkVersion 28
|
||||||
versionCode 4
|
versionCode 5
|
||||||
versionName "1.3"
|
versionName "1.4"
|
||||||
setProperty("archivesBaseName", "Emu48-v$versionName")
|
setProperty("archivesBaseName", "Emu48-v$versionName")
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
externalNativeBuild {
|
externalNativeBuild {
|
||||||
|
@ -76,11 +76,11 @@ android {
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
|
implementation 'androidx.appcompat:appcompat:1.1.0-alpha04'
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha3'
|
implementation 'androidx.constraintlayout:constraintlayout:2.0.0-alpha5'
|
||||||
implementation 'androidx.preference:preference:1.0.0'
|
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'
|
testImplementation 'junit:junit:4.12'
|
||||||
androidTestImplementation 'androidx.test:runner:1.1.2-alpha02'
|
androidTestImplementation 'androidx.test:runner:1.2.0-alpha04'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha02'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0-alpha04'
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,11 +27,23 @@ QUICK START
|
||||||
NOTES
|
NOTES
|
||||||
|
|
||||||
- When using a custom KML script by selecting a folder, you must take care of the case sensitivity of its dependency files.
|
- 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",
|
- Starting with the version 1.4, a RAM card generator for the port 2 of the HP48SX and HP48GX has been added.
|
||||||
which allows to write the port2 (128KB) in the ROM! Because in Android, it is not possible to write in the embedded ROM,
|
Like with the MKSHARED.EXE on Windows, you can generate the card in a file (i.e.: SHARED.BIN).
|
||||||
we have the same behavior as under Windows with "HKEY_CURRENT_USER\Software\Emu48\ROM[Writeable]=0".
|
And then, to use with the HP48SX or the HP48GX, you must select this generated file in the "Settings/Port2 File".
|
||||||
The port 2 is well saved in the state file "*.e49", but once this state file is reloaded,
|
- By default when you create a new HP49/50 with the embedded readonly file "rom.49g",
|
||||||
this causes a warmstart and the port 2 is never loaded.
|
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
|
NOT WORKING YET
|
||||||
|
|
||||||
|
@ -46,6 +58,9 @@ CHANGES
|
||||||
|
|
||||||
Version 1.4 (2019-04-xx)
|
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 authentic speed issue at the first start.
|
||||||
- Fix the non working Restore/Delete backup.
|
- Fix the non working Restore/Delete backup.
|
||||||
|
|
||||||
|
|
|
@ -90,7 +90,7 @@ static LRESULT OnPaint(HWND hWindow)
|
||||||
PAINTSTRUCT Paint;
|
PAINTSTRUCT Paint;
|
||||||
HDC hPaintDC;
|
HDC hPaintDC;
|
||||||
|
|
||||||
PAINT_LOGD("Emu48-PAINT OnPaint()");
|
PAINT_LOGD("PAINT OnPaint()");
|
||||||
|
|
||||||
//UpdateWindowBars(); // update visibility of title and menu bar
|
//UpdateWindowBars(); // update visibility of title and menu bar
|
||||||
|
|
||||||
|
@ -108,7 +108,7 @@ static LRESULT OnPaint(HWND hWindow)
|
||||||
UINT nLines = MAINSCREENHEIGHT;
|
UINT nLines = MAINSCREENHEIGHT;
|
||||||
|
|
||||||
// redraw background bitmap
|
// redraw background bitmap
|
||||||
PAINT_LOGD("Emu48-PAINT OnPaint() BitBlt()");
|
PAINT_LOGD("PAINT OnPaint() BitBlt()");
|
||||||
BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top,
|
BitBlt(hPaintDC, Paint.rcPaint.left, Paint.rcPaint.top,
|
||||||
Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top,
|
Paint.rcPaint.right-Paint.rcPaint.left, Paint.rcPaint.bottom-Paint.rcPaint.top,
|
||||||
hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY);
|
hMainDC, rcMainPaint.left, rcMainPaint.top, SRCCOPY);
|
|
@ -803,7 +803,7 @@ JNIEXPORT void JNICALL Java_org_emulator_forty_eight_NativeLib_onViewReset(JNIEn
|
||||||
SwitchToState(SM_RUN);
|
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];
|
TCHAR szKmlFile[MAX_PATH];
|
||||||
// BOOL bKMLChanged,bSucc;
|
// BOOL bKMLChanged,bSucc;
|
|
@ -14,7 +14,6 @@ extern JavaVM *java_machine;
|
||||||
extern jobject bitmapMainScreen;
|
extern jobject bitmapMainScreen;
|
||||||
extern AndroidBitmapInfo androidBitmapInfo;
|
extern AndroidBitmapInfo androidBitmapInfo;
|
||||||
|
|
||||||
|
|
||||||
HANDLE hWnd;
|
HANDLE hWnd;
|
||||||
LPTSTR szTitle;
|
LPTSTR szTitle;
|
||||||
LPTSTR szCurrentAssetDirectory = NULL;
|
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);
|
FILE_LOGD("CreateFile(lpFileName: \"%s\", dwDesiredAccess: 0x%08x)", lpFileName, dwShareMode);
|
||||||
BOOL forceNormalFile = FALSE;
|
BOOL forceNormalFile = FALSE;
|
||||||
// if(_tcscmp(lpFileName, szPort2Filename) == 0) {
|
#if EMUXX == 48
|
||||||
// // Special case for Port2 filename
|
if(_tcscmp(lpFileName, szPort2Filename) == 0) {
|
||||||
// forceNormalFile = TRUE;
|
// Special case for Port2 filename
|
||||||
// if(!settingsPort2wr && (dwDesiredAccess & GENERIC_WRITE))
|
forceNormalFile = TRUE;
|
||||||
// return (HANDLE) INVALID_HANDLE_VALUE;
|
if(!settingsPort2wr && (dwDesiredAccess & GENERIC_WRITE))
|
||||||
// }
|
return (HANDLE) INVALID_HANDLE_VALUE;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
TCHAR * foundDocumentScheme = _tcsstr(lpFileName, documentScheme);
|
TCHAR * foundDocumentScheme = _tcsstr(lpFileName, documentScheme);
|
||||||
|
|
||||||
|
@ -117,7 +118,9 @@ HANDLE CreateFile(LPCTSTR lpFileName, DWORD dwDesiredAccess, DWORD dwShareMode,
|
||||||
if(filename) {
|
if(filename) {
|
||||||
*filename = _T('\0');
|
*filename = _T('\0');
|
||||||
}
|
}
|
||||||
//_tcscpy(szRomDirectory, szEmuDirectory);
|
#if EMUXX == 48
|
||||||
|
_tcscpy(szRomDirectory, szEmuDirectory);
|
||||||
|
#endif
|
||||||
SetCurrentDirectory(szEmuDirectory);
|
SetCurrentDirectory(szEmuDirectory);
|
||||||
} else if(foundDocumentScheme) {
|
} else if(foundDocumentScheme) {
|
||||||
// With a recorded "document:" scheme, extract the folder URL with content:// scheme
|
// 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) {
|
if(filename) {
|
||||||
*filename = _T('\0');
|
*filename = _T('\0');
|
||||||
}
|
}
|
||||||
//_tcscpy(szRomDirectory, szEmuDirectory);
|
#if EMUXX == 48
|
||||||
|
_tcscpy(szRomDirectory, szEmuDirectory);
|
||||||
|
#endif
|
||||||
SetCurrentDirectory(szEmuDirectory);
|
SetCurrentDirectory(szEmuDirectory);
|
||||||
} else {
|
} else {
|
||||||
_tcscpy(szEmuDirectory, "assets/calculators/");
|
_tcscpy(szEmuDirectory, "assets/calculators/");
|
||||||
//_tcscpy(szRomDirectory, "assets/calculators/");
|
#if EMUXX == 48
|
||||||
|
_tcscpy(szRomDirectory, "assets/calculators/");
|
||||||
|
#endif
|
||||||
SetCurrentDirectory(szEmuDirectory);
|
SetCurrentDirectory(szEmuDirectory);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -902,6 +909,9 @@ void onPlayerDoneTimerCallback(void *context) {
|
||||||
WAVE_OUT_LOGD("waveOut onPlayerDoneTimerCallback()");
|
WAVE_OUT_LOGD("waveOut onPlayerDoneTimerCallback()");
|
||||||
HWAVEOUT hwo = context;
|
HWAVEOUT hwo = context;
|
||||||
onPlayerDone(hwo);
|
onPlayerDone(hwo);
|
||||||
|
|
||||||
|
//TODO May be needed if an attached occurs in the future
|
||||||
|
//jniDetachCurrentThread();
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -2151,6 +2161,8 @@ void timerCallback(int timerId) {
|
||||||
TIMER_LOGD("timerCallback remove timer uTimerID [%d]", timerId + 1);
|
TIMER_LOGD("timerCallback remove timer uTimerID [%d]", timerId + 1);
|
||||||
deleteTimeEvent((UINT) (timerId + 1));
|
deleteTimeEvent((UINT) (timerId + 1));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
jniDetachCurrentThread();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {
|
MMRESULT timeSetEvent(UINT uDelay, UINT uResolution, LPTIMECALLBACK fptc, DWORD_PTR dwUser, UINT fuEvent) {
|
||||||
|
|
|
@ -10,7 +10,7 @@
|
||||||
#include <android/bitmap.h>
|
#include <android/bitmap.h>
|
||||||
#include <android/asset_manager.h>
|
#include <android/asset_manager.h>
|
||||||
#include <android/log.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 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__))
|
#define LOGE(...) ((void)__android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__))
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.emulator.forty.eight;
|
package org.emulator.forty.eight;
|
||||||
|
|
||||||
|
import android.annotation.SuppressLint;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.content.ClipData;
|
import android.content.ClipData;
|
||||||
import android.content.ClipboardManager;
|
import android.content.ClipboardManager;
|
||||||
|
@ -24,20 +25,34 @@ import android.view.SubMenu;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
|
import android.view.WindowManager;
|
||||||
import android.widget.ImageButton;
|
import android.widget.ImageButton;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
import android.widget.Toast;
|
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 com.google.android.material.navigation.NavigationView;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.InputStreamReader;
|
import java.io.InputStreamReader;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
@ -52,17 +67,6 @@ import java.util.Set;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
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 {
|
public class MainActivity extends AppCompatActivity implements NavigationView.OnNavigationItemSelectedListener {
|
||||||
|
|
||||||
private static final String TAG = "MainActivity";
|
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_NEW_FILE = 7;
|
||||||
public static final int INTENT_PICK_KML_FOLDER_FOR_CHANGING = 8;
|
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_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 String kmlMimeType = "application/vnd.google-earth.kml+xml";
|
||||||
private boolean kmlFolderUseDefault = true;
|
private boolean kmlFolderUseDefault = true;
|
||||||
private String kmlFolderURL = "";
|
private String kmlFolderURL = "";
|
||||||
private boolean kmFolderChange = true;
|
private boolean kmFolderChange = true;
|
||||||
|
|
||||||
|
private int selectedRAMSize = -1;
|
||||||
|
|
||||||
private int MRU_ID_START = 10000;
|
private int MRU_ID_START = 10000;
|
||||||
private int MAX_MRU = 5;
|
private int MAX_MRU = 5;
|
||||||
private LinkedHashMap<String, String> mruLinkedHashMap = new LinkedHashMap<String, String>(5, 1.0f, true) {
|
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
|
@Override
|
||||||
public void onBackPressed() {
|
public void onBackPressed() {
|
||||||
DrawerLayout drawer = findViewById(R.id.drawer_layout);
|
|
||||||
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
if (drawer.isDrawerOpen(GravityCompat.START)) {
|
||||||
drawer.closeDrawer(GravityCompat.START);
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
} else {
|
} else {
|
||||||
|
@ -312,6 +318,8 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
OnBackupDelete();
|
OnBackupDelete();
|
||||||
} else if (id == R.id.nav_change_kml_script) {
|
} else if (id == R.id.nav_change_kml_script) {
|
||||||
OnViewScript();
|
OnViewScript();
|
||||||
|
} else if (id == R.id.nav_create_ram_card) {
|
||||||
|
OnCreateRAMCard();
|
||||||
} else if (id == R.id.nav_help) {
|
} else if (id == R.id.nav_help) {
|
||||||
OnTopics();
|
OnTopics();
|
||||||
} else if (id == R.id.nav_about) {
|
} 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);
|
drawer.closeDrawer(GravityCompat.START);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -615,6 +622,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
case 'S': //HP48SX
|
case 'S': //HP48SX
|
||||||
case 'G': //HP48GX
|
case 'G': //HP48GX
|
||||||
extension = "e48";
|
extension = "e48";
|
||||||
|
break;
|
||||||
case '6': //HP38G 64K RAM
|
case '6': //HP38G 64K RAM
|
||||||
case 'A': //HP38G 32K RAM
|
case 'A': //HP38G 32K RAM
|
||||||
extension = "e38";
|
extension = "e38";
|
||||||
|
@ -814,6 +822,54 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
}).show();
|
}).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() {
|
private void OnTopics() {
|
||||||
startActivity(new Intent(this, InfoWebActivity.class));
|
startActivity(new Intent(this, InfoWebActivity.class));
|
||||||
}
|
}
|
||||||
|
@ -910,6 +966,30 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
}
|
}
|
||||||
break;
|
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:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1208,7 +1288,7 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
if(key == null) {
|
if(key == null) {
|
||||||
String[] settingKeys = {
|
String[] settingKeys = {
|
||||||
"settings_realspeed", "settings_grayscale", "settings_allow_rotation", "settings_fill_screen",
|
"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_background_kml_color", "settings_background_fallback_color",
|
||||||
"settings_kml", "settings_port1", "settings_port2" };
|
"settings_kml", "settings_port1", "settings_port2" };
|
||||||
for (String settingKey : settingKeys) {
|
for (String settingKey : settingKeys) {
|
||||||
|
@ -1232,6 +1312,15 @@ public class MainActivity extends AppCompatActivity implements NavigationView.On
|
||||||
case "settings_fill_screen":
|
case "settings_fill_screen":
|
||||||
mainScreenView.setFillScreen(sharedPreferences.getBoolean("settings_fill_screen", false));
|
mainScreenView.setFillScreen(sharedPreferences.getBoolean("settings_fill_screen", false));
|
||||||
break;
|
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":
|
case "settings_scale":
|
||||||
//mainScreenView.setScale(1.0f); //sharedPreferences.getFloat("settings_scale", 0.0f));
|
//mainScreenView.setScale(1.0f); //sharedPreferences.getFloat("settings_scale", 0.0f));
|
||||||
break;
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -225,7 +225,7 @@ public class MainScreenView extends SurfaceView {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onDraw(Canvas canvas) {
|
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());
|
canvas.drawColor(getBackgroundColor());
|
||||||
|
|
||||||
|
@ -242,13 +242,13 @@ public class MainScreenView extends SurfaceView {
|
||||||
int updateCallback(int type, int param1, int param2, String param3, String param4) {
|
int updateCallback(int type, int param1, int param2, String param3, String param4) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case CALLBACK_TYPE_INVALIDATE:
|
case CALLBACK_TYPE_INVALIDATE:
|
||||||
//Log.d(TAG, "Emu48-PAINT updateCallback() postInvalidate()");
|
//Log.d(TAG, "PAINT updateCallback() postInvalidate()");
|
||||||
postInvalidate();
|
postInvalidate();
|
||||||
break;
|
break;
|
||||||
case CALLBACK_TYPE_WINDOW_RESIZE:
|
case CALLBACK_TYPE_WINDOW_RESIZE:
|
||||||
// New Bitmap size
|
// New Bitmap size
|
||||||
if(bitmapMainScreen == null || bitmapMainScreen.getWidth() != param1 || bitmapMainScreen.getHeight() != param2) {
|
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;
|
Bitmap oldBitmapMainScreen = bitmapMainScreen;
|
||||||
bitmapMainScreen = Bitmap.createBitmap(Math.max(1, param1), Math.max(1, param2), Bitmap.Config.ARGB_8888);
|
bitmapMainScreen = Bitmap.createBitmap(Math.max(1, param1), Math.max(1, param2), Bitmap.Config.ARGB_8888);
|
||||||
int globalColor = NativeLib.getGlobalColor();
|
int globalColor = NativeLib.getGlobalColor();
|
||||||
|
|
9
app/src/main/res/drawable/ic_memory_black_24dp.xml
Normal file
9
app/src/main/res/drawable/ic_memory_black_24dp.xml
Normal 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>
|
|
@ -6,8 +6,8 @@
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
tools:context="org.emulator.forty.eight.MainActivity"
|
tools:context="org.emulator.forty.eight.MainActivity"
|
||||||
android:fitsSystemWindows="true"
|
|
||||||
tools:openDrawer="start">
|
tools:openDrawer="start">
|
||||||
|
<!--android:fitsSystemWindows="true"-->
|
||||||
|
|
||||||
<include
|
<include
|
||||||
layout="@layout/app_bar_main"
|
layout="@layout/app_bar_main"
|
||||||
|
|
|
@ -24,13 +24,4 @@
|
||||||
|
|
||||||
<include layout="@layout/content_main" />
|
<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>
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
|
@ -90,6 +90,14 @@
|
||||||
android:title="@string/nav_change_kml_script" />
|
android:title="@string/nav_change_kml_script" />
|
||||||
</menu>
|
</menu>
|
||||||
</item>
|
</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">
|
<item android:title="@string/nav_help">
|
||||||
<menu>
|
<menu>
|
||||||
<item
|
<item
|
||||||
|
|
|
@ -12,4 +12,14 @@
|
||||||
<!--<item>2</item>-->
|
<!--<item>2</item>-->
|
||||||
</string-array>
|
</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>
|
</resources>
|
|
@ -4,5 +4,4 @@
|
||||||
<!--<dimen name="activity_vertical_margin">16dp</dimen>-->
|
<!--<dimen name="activity_vertical_margin">16dp</dimen>-->
|
||||||
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
<dimen name="nav_header_vertical_spacing">8dp</dimen>
|
||||||
<!--<dimen name="nav_header_height">176dp</dimen>-->
|
<!--<dimen name="nav_header_height">176dp</dimen>-->
|
||||||
<dimen name="fab_margin">16dp</dimen>
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|
|
@ -40,12 +40,19 @@
|
||||||
<string name="nav_delete_backup">Delete Backup</string>
|
<string name="nav_delete_backup">Delete Backup</string>
|
||||||
<string name="nav_view">View</string>
|
<string name="nav_view">View</string>
|
||||||
<string name="nav_change_kml_script">Change KML Script...</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_help">Help</string>
|
||||||
<string name="nav_item_help">Help</string>
|
<string name="nav_item_help">Help</string>
|
||||||
<string name="nav_about">About Emu48...</string>
|
<string name="nav_about">About Emu48...</string>
|
||||||
|
|
||||||
<string name="load_custom_kml">[Custom KML script...]</string>
|
<string name="load_custom_kml">[Custom KML script...]</string>
|
||||||
<string name="load_default_kml">[Default KML script]</string>
|
<string name="load_default_kml">[Default KML script]</string>
|
||||||
<string name="pick_calculator">Pick a calculator</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_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_do_you_want_to_save">Do you want to save changes?\n(BACK to cancel)</string>
|
||||||
<string name="message_yes">Yes</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_alwaysdisplog_title">Always Show KML Compilation Result</string>
|
||||||
<string name="settings_allow_rotation_title">Allow rotation</string>
|
<string name="settings_allow_rotation_title">Allow rotation</string>
|
||||||
<string name="settings_fill_screen_title">Fill screen</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_allow_sound_title">Allow sounds</string>
|
||||||
<string name="settings_haptic_feedback_title">Allow haptic feedback</string>
|
<string name="settings_haptic_feedback_title">Allow haptic feedback</string>
|
||||||
<string name="settings_category_background_title">Background Color</string>
|
<string name="settings_category_background_title">Background Color</string>
|
||||||
|
|
|
@ -32,6 +32,14 @@
|
||||||
android:key="settings_fill_screen"
|
android:key="settings_fill_screen"
|
||||||
android:title="@string/settings_fill_screen_title"
|
android:title="@string/settings_fill_screen_title"
|
||||||
android:defaultValue="false" />
|
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
|
<SwitchPreference
|
||||||
android:key="settings_allow_sound"
|
android:key="settings_allow_sound"
|
||||||
android:title="@string/settings_allow_sound_title"
|
android:title="@string/settings_allow_sound_title"
|
||||||
|
|
Loading…
Reference in a new issue