Various cleanup and bug fixes.

- Remove hard-coded paths to emulator assets - instead, the app now
  `chdir()`s into the correct folder before starting the core emulator.
- Replace all `findViewById()` calls with auto-generated variables.
- Fix a potential crash from not re-initialising the window if the EGL
  context is lost for some reason.
This commit is contained in:
Phil Jones 2020-05-05 22:47:15 +01:00
parent edf493fa46
commit 5e8dc627bb
No known key found for this signature in database
GPG Key ID: 7E6F59EE25CDC6A5
8 changed files with 264 additions and 247 deletions

1
app/.gitignore vendored
View File

@ -1,2 +1,3 @@
/build
/release
/debug

View File

@ -11,8 +11,8 @@ android {
applicationId "com.philj56.gbcc"
minSdkVersion 21
targetSdkVersion 29
versionCode 13
versionName "beta13"
versionCode 14
versionName "beta14"
archivesBaseName = "gbcc"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {

View File

@ -6,9 +6,19 @@
android:glEsVersion="0x00030000"
android:required="true" />
<!-- Hardware features -->
<uses-feature
android:name="android.hardware.audio.low_latency"
android:required="false" />
<uses-feature
android:name="android.hardware.camera"
android:required="false" />
<uses-feature
android:name="android.hardware.camera.any"
android:required="false" />
<uses-feature
android:name="android.hardware.sensor.accelerometer"
android:required="false" />
<uses-permission
android:name="android.permission.VIBRATE" />
@ -25,20 +35,27 @@
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppThemeDayNight">
<activity android:name=".GLActivity"
android:parentActivityName="MainActivity"
android:theme="@style/AppThemeDayNight.NoActionBar"/>
android:theme="@style/AppThemeDayNight.Fullscreen"/>
<activity android:name=".SettingsActivity"
android:parentActivityName="MainActivity"
android:label="@string/settings_title"
android:theme="@style/SettingsThemeDayNight"/>
<activity android:name=".ArrangeActivity"
android:parentActivityName=".SettingsActivity"/>
android:parentActivityName=".SettingsActivity"
android:theme="@style/AppThemeDayNight.Fullscreen"/>
<activity android:name=".LicenseListActivity"
android:parentActivityName=".SettingsActivity"
android:label="@string/license_title"/>
<activity android:name=".LicenseActivity"
android:parentActivityName=".LicenseListActivity"/>
<activity android:name=".MainActivity"
android:theme="@style/AppThemeDayNight.NoActionBar">
<intent-filter>

View File

@ -25,10 +25,10 @@ set(GBCC_DIR ${CMAKE_CURRENT_SOURCE_DIR}/../../../libs/gbcc)
include_directories(${GBCC_DIR}/src)
add_definitions(
-DPRINTER_SOUND_PATH="/data/user/0/com.philj56.gbcc/files/print.wav"
-DTILESET_PATH="/data/user/0/com.philj56.gbcc/files/tileset.png"
-DCAMERA_PATH="/data/user/0/com.philj56.gbcc/files/camera.png"
-DSHADER_PATH="/data/user/0/com.philj56.gbcc/files/shaders/"
-DPRINTER_SOUND_PATH="print.wav"
-DTILESET_PATH="tileset.png"
-DCAMERA_PATH="camera.png"
-DSHADER_PATH="shaders/"
)
#set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -O3 -flto -fprofile-instr-use=${GBCC_DIR}/default.profdata")

View File

@ -18,14 +18,15 @@
#include <android/log.h>
#include <pthread.h>
#include <semaphore.h>
#include <unistd.h>
extern "C" {
#pragma GCC visibility push(hidden)
#include <gbcc.h>
#include <camera/camera.h>
#include <core.h>
#include <camera/camera.h>
#include <core.h>
#include <save.h>
#include <window.h>
#include <window.h>
#pragma GCC visibility pop
}
@ -112,53 +113,68 @@ bool check_autoresume(JNIEnv *env, jobject prefs) {
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_MyGLRenderer_initWindow(
JNIEnv *env,
jobject obj) {
JNIEnv *env,
jobject obj) {
gbcc_window_initialise(&gbc);
gbcc_window_use_shader(&gbc, shader);
gbcc_menu_init(&gbc);
gbcc_window_use_shader(&gbc, shader);
gbcc_menu_init(&gbc);
gbcc_menu_update(&gbc);
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_MyGLSurfaceView_destroyWindow(
JNIEnv *env,
jobject obj) {
gbcc_menu_destroy(&gbc);
// Have to destroy the window manually, as the OpenGL context is likely to be gone by now
gbc.window.initialised = false;
gbcc_fontmap_destroy(&gbc.window.font);
JNIEnv *env,
jobject obj) {
if (gbc.window.initialised) {
gbcc_menu_destroy(&gbc);
// Have to destroy the window manually, as the OpenGL context is likely to be gone by now
gbc.window.initialised = false;
gbcc_fontmap_destroy(&gbc.window.font);
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_MyGLRenderer_updateWindow(
JNIEnv *env,
jobject obj) {
JNIEnv *env,
jobject obj) {
if (gbc.core.initialised) {
if (!gbc.window.initialised) {
gbcc_window_initialise(&gbc);
}
gbcc_window_update(&gbc);
}
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_MyGLRenderer_resizeWindow(
JNIEnv *env,
jobject obj,
jint width,
jint height) {
JNIEnv *env,
jobject obj,
jint width,
jint height) {
gbc.window.width = width;
gbc.window.height = height;
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_chdir(
JNIEnv *env,
jobject obj,/* this */
jstring dirName) {
const char *path = env->GetStringUTFChars(dirName, nullptr);
chdir(path);
env->ReleaseStringUTFChars(dirName, path);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_philj56_gbcc_GLActivity_loadRom(
JNIEnv *env,
jobject obj,/* this */
jstring file,
jint sampleRate,
jint samplesPerBuffer,
jstring saveDir,
jobject prefs) {
JNIEnv *env,
jobject obj,/* this */
jstring file,
jint sampleRate,
jint samplesPerBuffer,
jstring saveDir,
jobject prefs) {
const char *string = env->GetStringUTFChars(file, nullptr);
@ -203,8 +219,8 @@ Java_com_philj56_gbcc_GLActivity_getErrorMessage(
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_quit(
JNIEnv *env,
jobject obj/* this */) {
JNIEnv *env,
jobject obj/* this */) {
gbc.quit = true;
sem_post(&gbc.core.ppu.vsync_semaphore);
@ -217,25 +233,25 @@ Java_com_philj56_gbcc_GLActivity_quit(
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_toggleMenu(
JNIEnv *env,
jobject obj/* this */,
jobject view) {
JNIEnv *env,
jobject obj/* this */,
jobject view) {
gbcc_input_process_key(&gbc, GBCC_KEY_MENU, true);
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_toggleTurbo(
JNIEnv *env,
jobject obj/* this */) {
JNIEnv *env,
jobject obj/* this */) {
gbcc_input_process_key(&gbc, GBCC_KEY_TURBO, true);
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_press(
JNIEnv *env,
jobject obj/* this */,
jint key,
jboolean pressed) {
JNIEnv *env,
jobject obj/* this */,
jint key,
jboolean pressed) {
switch (key) {
case 0:
gbcc_input_process_key(&gbc, GBCC_KEY_A, pressed);
@ -268,9 +284,9 @@ Java_com_philj56_gbcc_GLActivity_press(
extern "C" JNIEXPORT jboolean JNICALL
Java_com_philj56_gbcc_GLActivity_isPressed(
JNIEnv *env,
jobject obj/* this */,
jint key) {
JNIEnv *env,
jobject obj/* this */,
jint key) {
switch (key) {
case 0:
return static_cast<jboolean>(gbc.core.keys.a);
@ -295,24 +311,24 @@ Java_com_philj56_gbcc_GLActivity_isPressed(
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_saveState(
JNIEnv *env,
jobject obj/* this */,
jint state) {
JNIEnv *env,
jobject obj/* this */,
jint state) {
gbc.save_state = static_cast<int8_t>(state);
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_loadState(
JNIEnv *env,
jobject obj/* this */,
jint state) {
JNIEnv *env,
jobject obj/* this */,
jint state) {
gbc.load_state = static_cast<int8_t>(state);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_philj56_gbcc_GLActivity_checkVibrationFun(
JNIEnv *env,
jobject obj/* this */) {
JNIEnv *env,
jobject obj/* this */) {
static bool last_rumble = false;
bool rumble = gbc.core.cart.rumble_state;
bool ret = (rumble != last_rumble);
@ -322,10 +338,10 @@ Java_com_philj56_gbcc_GLActivity_checkVibrationFun(
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_updateAccelerometer(
JNIEnv *env,
jobject obj/* this */,
jfloat x,
jfloat y) {
JNIEnv *env,
jobject obj/* this */,
jfloat x,
jfloat y) {
const float g = 9.81;
gbc.core.cart.mbc.accelerometer.real_x = static_cast<uint16_t>(0x81D0u + (0x70 * x / g));
gbc.core.cart.mbc.accelerometer.real_y = static_cast<uint16_t>(0x81D0u - (0x70 * y / g));
@ -333,124 +349,124 @@ Java_com_philj56_gbcc_GLActivity_updateAccelerometer(
extern "C" JNIEXPORT jboolean JNICALL
Java_com_philj56_gbcc_GLActivity_hasRumble(
JNIEnv *env,
jobject obj/* this */) {
JNIEnv *env,
jobject obj/* this */) {
return static_cast<jboolean>(gbc.core.cart.rumble);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_philj56_gbcc_GLActivity_hasAccelerometer(
JNIEnv *env,
jobject obj/* this */) {
JNIEnv *env,
jobject obj/* this */) {
return static_cast<jboolean>(gbc.core.cart.mbc.type == MBC7);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_philj56_gbcc_GLActivity_isCamera(
JNIEnv *env,
jobject obj/* this */) {
return static_cast<jboolean>(gbc.core.cart.mbc.type == CAMERA);
JNIEnv *env,
jobject obj/* this */) {
return static_cast<jboolean>(gbc.core.cart.mbc.type == CAMERA);
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_updateCamera(
JNIEnv *env,
jobject obj/* this */,
jbyteArray array,
jint width,
jint height,
jint rotation,
jint rowStride) {
jbyte *image = env->GetByteArrayElements(array, NULL);
JNIEnv *env,
jobject obj/* this */,
jbyteArray array,
jint width,
jint height,
jint rotation,
jint rowStride) {
jbyte *image = env->GetByteArrayElements(array, NULL);
// Perform box-blur downsampling of the sensor image to get out 128x128 gb camera image
int box_size = MIN(width, height) / 128 / 2 + 1;
// Perform box-blur downsampling of the sensor image to get out 128x128 gb camera image
int box_size = MIN(width, height) / 128 / 2 + 1;
// First we perform the horizontal blur
uint8_t *new_row = static_cast<uint8_t *>(calloc(width, 1));
for (int j = 0; j < height; j++) {
jbyte *row = &image[j * rowStride];
int sum = 0;
int div = 0;
// First we perform the horizontal blur
uint8_t *new_row = static_cast<uint8_t *>(calloc(width, 1));
for (int j = 0; j < height; j++) {
jbyte *row = &image[j * rowStride];
int sum = 0;
int div = 0;
for (int i = -box_size; i < width; i++) {
if (i < width - box_size) {
sum += static_cast<uint8_t>(row[i + box_size]);
} else {
div--;
}
if (i >= box_size) {
sum -= static_cast<uint8_t>(row[i - box_size]);
} else {
div++;
}
for (int i = -box_size; i < width; i++) {
if (i < width - box_size) {
sum += static_cast<uint8_t>(row[i + box_size]);
} else {
div--;
}
if (i >= box_size) {
sum -= static_cast<uint8_t>(row[i - box_size]);
} else {
div++;
}
if (i >= 0) {
new_row[i] = static_cast<uint8_t>(sum / div);
}
}
memcpy(row, new_row, width);
}
free(new_row);
if (i >= 0) {
new_row[i] = static_cast<uint8_t>(sum / div);
}
}
memcpy(row, new_row, width);
}
free(new_row);
// Then the vertical blur
uint8_t *new_col = static_cast<uint8_t *>(calloc(height, 1));
for (int i = 0; i < width; i++) {
int sum = 0;
int div = 0;
// Then the vertical blur
uint8_t *new_col = static_cast<uint8_t *>(calloc(height, 1));
for (int i = 0; i < width; i++) {
int sum = 0;
int div = 0;
for (int j = -box_size; j < height; j++) {
if (j < height - box_size) {
sum += static_cast<uint8_t>(image[(j + box_size) * rowStride + i]);
} else {
div--;
}
if (j >= box_size) {
sum -= static_cast<uint8_t>(image[(j - box_size) * rowStride + i]);
} else {
div++;
}
for (int j = -box_size; j < height; j++) {
if (j < height - box_size) {
sum += static_cast<uint8_t>(image[(j + box_size) * rowStride + i]);
} else {
div--;
}
if (j >= box_size) {
sum -= static_cast<uint8_t>(image[(j - box_size) * rowStride + i]);
} else {
div++;
}
if (i >= 0) {
new_col[j] = static_cast<uint8_t>(sum / div);
}
}
for (int j = 0; j < height; j++) {
image[j * rowStride + i] = new_col[j];
}
}
free(new_col);
if (i >= 0) {
new_col[j] = static_cast<uint8_t>(sum / div);
}
}
for (int j = 0; j < height; j++) {
image[j * rowStride + i] = new_col[j];
}
}
free(new_col);
// Then we nearest-neighbour downscale and rotate
double scale = MIN(height, width) / 128.0;
for (int j = 0; j < 128; j++) {
for (int i = 0; i < 128; i++) {
int src_idx = (int)(j * scale) * rowStride + (int)(i * scale);
int dst_idx;
if (rotation == 90) {
dst_idx = i * 128 + (127 - j);
} else if (rotation == 180) {
dst_idx = (127 - j) * 128 + (127 - i);
} else if (rotation == 270) {
dst_idx = (127 - i) * 128 + j;
} else {
dst_idx = j * 128 + i;
}
// Then we nearest-neighbour downscale and rotate
double scale = MIN(height, width) / 128.0;
for (int j = 0; j < 128; j++) {
for (int i = 0; i < 128; i++) {
int src_idx = (int)(j * scale) * rowStride + (int)(i * scale);
int dst_idx;
if (rotation == 90) {
dst_idx = i * 128 + (127 - j);
} else if (rotation == 180) {
dst_idx = (127 - j) * 128 + (127 - i);
} else if (rotation == 270) {
dst_idx = (127 - i) * 128 + j;
} else {
dst_idx = j * 128 + i;
}
camera_image[dst_idx] = static_cast<uint8_t>(image[src_idx]);
}
}
camera_image[dst_idx] = static_cast<uint8_t>(image[src_idx]);
}
}
env->ReleaseByteArrayElements(array, image, JNI_ABORT);
env->ReleaseByteArrayElements(array, image, JNI_ABORT);
}
extern "C" JNIEXPORT void JNICALL
Java_com_philj56_gbcc_GLActivity_useNullCamera(
JNIEnv *env,
jobject obj/* this */) {
gbcc_camera_default_image(camera_image);
JNIEnv *env,
jobject obj/* this */) {
gbcc_camera_default_image(camera_image);
}
void gbcc_camera_platform_capture_image(uint8_t image[GB_CAMERA_SENSOR_SIZE]) {
memcpy(image, camera_image, GB_CAMERA_SENSOR_SIZE);
}
}

View File

@ -16,7 +16,6 @@ import android.content.res.Configuration
import android.os.*
import android.util.AttributeSet
import android.view.*
import android.widget.ImageView
import android.widget.SeekBar
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate
@ -24,6 +23,7 @@ import androidx.appcompat.widget.AppCompatImageView
import androidx.core.content.ContextCompat
import androidx.core.content.edit
import androidx.preference.PreferenceManager
import kotlinx.android.synthetic.main.activity_arrange.*
import kotlin.math.log
import kotlin.math.min
import kotlin.math.pow
@ -35,16 +35,6 @@ class ArrangeActivity : AppCompatActivity() {
private lateinit var prefs : SharedPreferences
private lateinit var buttonA : ResizableImage
private lateinit var buttonB : ResizableImage
private lateinit var buttonStart : ResizableImage
private lateinit var buttonSelect : ResizableImage
private lateinit var dpad : ResizableImage
private lateinit var abSeekBar: SeekBar
private lateinit var startSelectSeekBar: SeekBar
private lateinit var dpadSeekBar: SeekBar
private fun updateLayout(gbc: Boolean) {
val bgColor = when (gbc) {
true -> when (prefs.getString("color", "Teal")) {
@ -59,31 +49,21 @@ class ArrangeActivity : AppCompatActivity() {
}
window.setBackgroundDrawableResource(bgColor)
abSeekBar = findViewById(R.id.abSeekBar)
startSelectSeekBar = findViewById(R.id.startSelectSeekBar)
dpadSeekBar = findViewById(R.id.dpadSeekBar)
abSeekBar.setOnSeekBarChangeListener(seekBarListener)
startSelectSeekBar.setOnSeekBarChangeListener(seekBarListener)
dpadSeekBar.setOnSeekBarChangeListener(seekBarListener)
buttonA = findViewById(R.id.buttonA)
buttonB = findViewById(R.id.buttonB)
buttonStart = findViewById(R.id.buttonStart)
buttonSelect = findViewById(R.id.buttonSelect)
dpad = findViewById(R.id.dpad)
if (!gbc) {
val screenBorderColor = ContextCompat.getColor(this, R.color.dmgScreenBorder)
val borders = intArrayOf(
R.id.screenBorderTop,
R.id.screenBorderBottom,
R.id.screenBorderLeft,
R.id.screenBorderRight
val borders = arrayOf(
screenBorderTop,
screenBorderBottom,
screenBorderLeft,
screenBorderRight
)
borders.forEach { border ->
findViewById<ImageView>(border).setColorFilter(
borders.forEach {
it.setColorFilter(
screenBorderColor,
android.graphics.PorterDuff.Mode.SRC_IN
)
@ -99,16 +79,14 @@ class ArrangeActivity : AppCompatActivity() {
buttonSelect.rotation = -45f
if (resources.configuration.orientation == Configuration.ORIENTATION_PORTRAIT) {
val bottomLeft = findViewById<ImageView>(R.id.bottomLeftCorner)
val bottomRight = findViewById<ImageView>(R.id.bottomRightCorner)
val px = (resources.displayMetrics.density + 0.5f).toInt()
bottomLeft.layoutParams.apply {
bottomLeftCorner.layoutParams.apply {
width = 16 * px
height = width
}
bottomRight.layoutParams.apply {
bottomRightCorner.layoutParams.apply {
width = 64 * px
height = width
}
@ -144,9 +122,12 @@ class ArrangeActivity : AppCompatActivity() {
delegate.localNightMode = AppCompatDelegate.MODE_NIGHT_YES
super.onCreate(savedInstanceState)
window.decorView.setOnSystemUiVisibilityChangeListener {
hideNavigation()
}
prefs = PreferenceManager.getDefaultSharedPreferences(this)
requestedOrientation = prefs.getString("orientation", "-1")?.toInt() ?: -1
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.activity_arrange)
@ -159,21 +140,6 @@ class ArrangeActivity : AppCompatActivity() {
)
}
override fun onResume() {
super.onResume()
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.decorView.apply {
systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
}
override fun onStop() {
super.onStop()
@ -265,6 +231,22 @@ class ArrangeActivity : AppCompatActivity() {
override fun onStopTrackingTouch(seekBar: SeekBar?) {
}
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
hideNavigation()
}
}
private fun hideNavigation() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
}
class ResizableImage : AppCompatImageView {

View File

@ -28,7 +28,6 @@ import android.util.AttributeSet
import android.util.Log
import android.util.Size
import android.view.*
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
@ -66,13 +65,8 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
private var dpadState = 0
private lateinit var saveDir : String
private lateinit var buttonA : ImageButton
private lateinit var buttonB : ImageButton
private lateinit var buttonStart : ImageButton
private lateinit var buttonSelect : ImageButton
private lateinit var dpad : View
external fun toggleMenu(view: View)
private external fun chdir(dirName: String)
private external fun loadRom(file: String, sampleRate: Int, samplesPerBuffer: Int, saveDir: String, prefs: SharedPreferences): Boolean
private external fun getErrorMessage(): String
private external fun quit()
@ -174,15 +168,15 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
if (!gbc) {
val screenBorderColor = ContextCompat.getColor(this, R.color.dmgScreenBorder)
val borders = intArrayOf(
R.id.screenBorderTop,
R.id.screenBorderBottom,
R.id.screenBorderLeft,
R.id.screenBorderRight
val borders = arrayOf(
screenBorderTop,
screenBorderBottom,
screenBorderLeft,
screenBorderRight
)
borders.forEach { border ->
findViewById<ImageView>(border).setColorFilter(
borders.forEach {
it.setColorFilter(
screenBorderColor,
android.graphics.PorterDuff.Mode.SRC_IN
)
@ -239,16 +233,19 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
chdir(filesDir.absolutePath)
window.decorView.setOnSystemUiVisibilityChangeListener {
hideNavigation()
}
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
requestedOrientation = prefs.getString("orientation", "-1")?.toInt() ?: -1
setContentView(R.layout.activity_gl)
val save = filesDir.resolve("saves")
save.mkdirs()
saveDir = save.absolutePath
val prefs = PreferenceManager.getDefaultSharedPreferences(this)
requestedOrientation = prefs.getString("orientation", "-1")?.toInt() ?: -1
requestWindowFeature(Window.FEATURE_NO_TITLE)
setContentView(R.layout.activity_gl)
val bundle = intent.extras
filename = bundle?.getString("file") ?: ""
if (filename == "") {
@ -256,12 +253,6 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
finish()
}
buttonA = findViewById(R.id.buttonA)
buttonB = findViewById(R.id.buttonB)
buttonStart = findViewById(R.id.buttonStart)
buttonSelect = findViewById(R.id.buttonSelect)
dpad = findViewById(R.id.dpad)
updateLayout(
when(prefs.getString("skin", "auto")) {
"dmg" -> false
@ -358,20 +349,25 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
})
}
override fun onWindowFocusChanged(hasFocus: Boolean) {
super.onWindowFocusChanged(hasFocus)
if (hasFocus) {
hideNavigation()
}
}
private fun hideNavigation() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
override fun onResume() {
super.onResume()
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
window.addFlags(WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS)
window.decorView.apply {
systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN
or View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY)
}
val am = getSystemService(Context.AUDIO_SERVICE) as AudioManager
val sampleRate = am.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE)?.let { str ->
Integer.parseInt(str).takeUnless { it == 0 }
@ -415,15 +411,13 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
override fun onPause() {
screen.onPause()
if (!loadedSuccessfully) {
super.onPause()
return
if (loadedSuccessfully) {
sensorManager.unregisterListener(this)
handler.removeCallbacks(checkVibration)
saveState(autoSaveState)
quit()
resume = true
}
sensorManager.unregisterListener(this)
handler.removeCallbacks(checkVibration)
saveState(autoSaveState)
quit()
resume = true
super.onPause()
}
@ -457,27 +451,30 @@ class GLActivity : AppCompatActivity(), SensorEventListener, LifecycleOwner {
}
}
private fun checkCameraPermission() = (ContextCompat.checkSelfPermission(baseContext, Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED)
private fun checkCameraPermission() : Boolean {
val permissionStatus = ContextCompat.checkSelfPermission(baseContext, Manifest.permission.CAMERA)
return permissionStatus == PackageManager.PERMISSION_GRANTED
}
private fun checkFiles() {
val filePath = filesDir
assets.open("tileset.png").use { iStream ->
val file = File("$filePath/tileset.png")
FileOutputStream(file).use { it.write(iStream.readBytes()) }
FileOutputStream(file).use { iStream.copyTo(it) }
}
assets.open("camera.png").use { iStream ->
val file = File("$filePath/camera.png")
FileOutputStream(file).use { it.write(iStream.readBytes()) }
FileOutputStream(file).use { iStream.copyTo(it) }
}
assets.open("print.wav").use { iStream ->
val file = File("$filePath/print.wav")
FileOutputStream(file).use { it.write(iStream.readBytes()) }
FileOutputStream(file).use { iStream.copyTo(it) }
}
assets.list("shaders")?.forEach { shader ->
File("$filePath/shaders").mkdirs()
assets.open("shaders/$shader").use { iStream ->
val file = File("$filePath/shaders/$shader")
FileOutputStream(file).use { it.write(iStream.readBytes()) }
FileOutputStream(file).use { iStream.copyTo(it) }
}
}
}

View File

@ -29,6 +29,10 @@
<item name="windowNoTitle">true</item>
</style>
<style name="AppThemeDayNight.Fullscreen" parent="AppThemeDayNight.NoActionBar">
<item name="android:windowFullscreen">true</item>
</style>
<!-- Colour the toolbar correctly. -->
<style name="Toolbar">
<item name="android:minHeight">?actionBarSize</item>