From 83c9e4fcb23a835bbd6887c5ea4b9beb50c52268 Mon Sep 17 00:00:00 2001
From: Emmanuel Hansen <emmausssss@gmail.com>
Date: Sun, 6 Aug 2023 12:53:01 +0000
Subject: [PATCH] move game view to new activity

---
 src/RyujinxAndroid/app/build.gradle           |   6 +
 .../app/src/main/AndroidManifest.xml          |  17 +-
 .../app/src/main/cpp/ryujinx.cpp              |   6 +
 .../java/org/ryujinx/android/GameActivity.kt  | 346 ++++++++++++++++++
 .../main/java/org/ryujinx/android/GameHost.kt |  17 +-
 .../main/java/org/ryujinx/android/Helpers.kt  |  14 +-
 .../main/java/org/ryujinx/android/Icons.kt    |   2 -
 .../java/org/ryujinx/android/MainActivity.kt  |  93 +----
 .../ryujinx/android/NativeGraphicsInterop.kt  |   4 +-
 .../java/org/ryujinx/android/NativeHelpers.kt |  10 +-
 .../org/ryujinx/android/PerformanceManager.kt |   6 +-
 .../android/PhysicalControllerManager.kt      |   8 +-
 .../java/org/ryujinx/android/RyujinxNative.kt |  24 +-
 .../android/viewmodels/MainViewModel.kt       |  55 +--
 .../org/ryujinx/android/views/HomeViews.kt    |   5 +-
 .../org/ryujinx/android/views/MainView.kt     | 240 ------------
 16 files changed, 444 insertions(+), 409 deletions(-)
 create mode 100644 src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameActivity.kt

diff --git a/src/RyujinxAndroid/app/build.gradle b/src/RyujinxAndroid/app/build.gradle
index 581fe1aa1..c1e90b005 100644
--- a/src/RyujinxAndroid/app/build.gradle
+++ b/src/RyujinxAndroid/app/build.gradle
@@ -75,6 +75,12 @@ tasks.named("preBuild") {
 }
 
 dependencies {
+    implementation 'androidx.appcompat:appcompat:1.6.1'
+    implementation 'com.google.android.material:material:1.9.0'
+    implementation platform('androidx.compose:compose-bom:2023.03.00')
+    implementation platform('androidx.compose:compose-bom:2023.03.00')
+    androidTestImplementation platform('androidx.compose:compose-bom:2023.03.00')
+    androidTestImplementation platform('androidx.compose:compose-bom:2023.03.00')
     runtimeOnly project(":libryujinx")
     implementation 'androidx.core:core-ktx:1.10.1'
     implementation platform('org.jetbrains.kotlin:kotlin-bom:1.8.0')
diff --git a/src/RyujinxAndroid/app/src/main/AndroidManifest.xml b/src/RyujinxAndroid/app/src/main/AndroidManifest.xml
index ad43a05f7..96c7072de 100644
--- a/src/RyujinxAndroid/app/src/main/AndroidManifest.xml
+++ b/src/RyujinxAndroid/app/src/main/AndroidManifest.xml
@@ -2,7 +2,10 @@
 <manifest xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:tools="http://schemas.android.com/tools">
 
-    <uses-feature android:name="android.hardware.audio.output" android:required="true" />
+    <uses-feature
+        android:name="android.hardware.audio.output"
+        android:required="true" />
+
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
@@ -12,23 +15,29 @@
         tools:ignore="ScopedStorage" />
     <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
     <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
+
     <application
         android:allowBackup="true"
+        android:appCategory="game"
         android:dataExtractionRules="@xml/data_extraction_rules"
         android:fullBackupContent="@xml/backup_rules"
         android:icon="@mipmap/ic_launcher"
+        android:isGame="true"
         android:label="@string/app_name"
         android:roundIcon="@mipmap/ic_launcher_round"
         android:supportsRtl="true"
-        android:largeHeap="true"
-        android:appCategory="game"
         android:theme="@style/Theme.RyujinxAndroid"
         tools:targetApi="31">
+        <activity
+            android:name=".GameActivity"
+            android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
+            android:launchMode="singleTask"
+            android:label="@string/title_activity_game"
+            android:theme="@style/Theme.RyujinxAndroid" />
         <activity
             android:name=".MainActivity"
             android:exported="true"
             android:hardwareAccelerated="false"
-            android:configChanges="density|fontScale|keyboard|keyboardHidden|layoutDirection|locale|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode"
             android:theme="@style/Theme.RyujinxAndroid">
             <intent-filter>
                 <action android:name="android.intent.action.MAIN" />
diff --git a/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp b/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
index a93948d42..12a331b9d 100644
--- a/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
+++ b/src/RyujinxAndroid/app/src/main/cpp/ryujinx.cpp
@@ -225,3 +225,9 @@ void debug_break(int code){
     if(code >= 3)
     int r = 0;
 }
+
+extern "C"
+JNIEXPORT void JNICALL
+Java_org_ryujinx_android_NativeHelpers_setTurboMode(JNIEnv *env, jobject thiz, jboolean enable) {
+    adrenotools_set_turbo(enable);
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameActivity.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameActivity.kt
new file mode 100644
index 000000000..3f9c4fe86
--- /dev/null
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameActivity.kt
@@ -0,0 +1,346 @@
+package org.ryujinx.android
+
+import android.annotation.SuppressLint
+import android.content.Intent
+import android.content.pm.ActivityInfo
+import android.os.Bundle
+import android.view.KeyEvent
+import android.view.MotionEvent
+import androidx.activity.ComponentActivity
+import androidx.activity.compose.BackHandler
+import androidx.activity.compose.setContent
+import androidx.compose.foundation.layout.Arrangement
+import androidx.compose.foundation.layout.Box
+import androidx.compose.foundation.layout.Column
+import androidx.compose.foundation.layout.Row
+import androidx.compose.foundation.layout.fillMaxSize
+import androidx.compose.foundation.layout.fillMaxWidth
+import androidx.compose.foundation.layout.padding
+import androidx.compose.foundation.layout.wrapContentHeight
+import androidx.compose.foundation.layout.wrapContentWidth
+import androidx.compose.material3.AlertDialog
+import androidx.compose.material3.AlertDialogDefaults
+import androidx.compose.material3.Button
+import androidx.compose.material3.ExperimentalMaterial3Api
+import androidx.compose.material3.Icon
+import androidx.compose.material3.IconButton
+import androidx.compose.material3.MaterialTheme
+import androidx.compose.material3.Surface
+import androidx.compose.material3.Text
+import androidx.compose.runtime.Composable
+import androidx.compose.runtime.mutableStateOf
+import androidx.compose.runtime.remember
+import androidx.compose.ui.Alignment
+import androidx.compose.ui.Modifier
+import androidx.compose.ui.graphics.Color
+import androidx.compose.ui.input.pointer.PointerEventType
+import androidx.compose.ui.input.pointer.pointerInput
+import androidx.compose.ui.unit.dp
+import androidx.compose.ui.viewinterop.AndroidView
+import androidx.compose.ui.window.Popup
+import androidx.core.view.WindowCompat
+import androidx.core.view.WindowInsetsCompat
+import androidx.core.view.WindowInsetsControllerCompat
+import compose.icons.CssGgIcons
+import compose.icons.cssggicons.ToolbarBottom
+import org.ryujinx.android.ui.theme.RyujinxAndroidTheme
+import org.ryujinx.android.viewmodels.MainViewModel
+import org.ryujinx.android.viewmodels.QuickSettings
+import kotlin.math.abs
+import kotlin.math.roundToInt
+
+class GameActivity : ComponentActivity() {
+    private var physicalControllerManager: PhysicalControllerManager = PhysicalControllerManager(this)
+    override fun onCreate(savedInstanceState: Bundle?) {
+        super.onCreate(savedInstanceState)
+
+        MainActivity.mainViewModel!!.physicalControllerManager = physicalControllerManager
+        setContent {
+            RyujinxAndroidTheme {
+                Surface(
+                    modifier = Modifier.fillMaxSize(),
+                    color = MaterialTheme.colorScheme.background
+                ) {
+                    GameView(mainViewModel = MainActivity.mainViewModel!!)
+                }
+            }
+        }
+    }
+
+    @SuppressLint("RestrictedApi")
+    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
+        event?.apply {
+            if(physicalControllerManager.onKeyEvent(this))
+                return true
+        }
+        return super.dispatchKeyEvent(event)
+    }
+
+    override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
+        ev?.apply {
+            physicalControllerManager.onMotionEvent(this)
+        }
+        return super.dispatchGenericMotionEvent(ev)
+    }
+
+    override fun onStop() {
+        super.onStop()
+
+        NativeHelpers().setTurboMode(false)
+        force60HzRefreshRate(false)
+    }
+
+    override fun onResume() {
+        super.onResume()
+
+        setFullScreen(true)
+        NativeHelpers().setTurboMode(true)
+        force60HzRefreshRate(true)
+    }
+
+    override fun onPause() {
+        super.onPause()
+
+        NativeHelpers().setTurboMode(false)
+        force60HzRefreshRate(false)
+    }
+
+    private fun force60HzRefreshRate(enable : Boolean) {
+        // Hack for MIUI devices since they don't support the standard Android APIs
+        try {
+            val setFpsIntent = Intent("com.miui.powerkeeper.SET_ACTIVITY_FPS")
+            setFpsIntent.putExtra("package_name", "org.ryujinx.android")
+            setFpsIntent.putExtra("isEnter", enable)
+            sendBroadcast(setFpsIntent)
+        } catch (_ : Exception) {
+        }
+
+        if (enable)
+            display?.supportedModes?.minByOrNull { abs(it.refreshRate - 60f) }?.let { window.attributes.preferredDisplayModeId = it.modeId }
+        else
+            display?.supportedModes?.maxByOrNull { it.refreshRate }?.let { window.attributes.preferredDisplayModeId = it.modeId }
+    }
+
+    private fun setFullScreen(fullscreen: Boolean) {
+        requestedOrientation =
+            if (fullscreen) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_FULL_USER
+
+        val insets = WindowCompat.getInsetsController(window, window.decorView)
+
+        insets.apply {
+            if (fullscreen) {
+                insets.hide(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars())
+                insets.systemBarsBehavior =
+                    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
+            } else {
+                insets.show(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars())
+                insets.systemBarsBehavior =
+                    WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
+            }
+        }
+    }
+    @Composable
+    fun GameView(mainViewModel: MainViewModel) {
+        Box(modifier = Modifier.fillMaxSize()) {
+            AndroidView(
+                modifier = Modifier.fillMaxSize(),
+                factory = { context ->
+                    GameHost(context, mainViewModel)
+                }
+            )
+            GameOverlay(mainViewModel)
+        }
+    }
+
+    @OptIn(ExperimentalMaterial3Api::class)
+    @Composable
+    fun GameOverlay(mainViewModel: MainViewModel) {
+        Box(modifier = Modifier.fillMaxSize()) {
+            GameStats(mainViewModel)
+
+            val ryujinxNative = RyujinxNative()
+
+            val showController = remember {
+                mutableStateOf(QuickSettings(mainViewModel.activity).useVirtualController)
+            }
+            val enableVsync = remember {
+                mutableStateOf(QuickSettings(mainViewModel.activity).enableVsync)
+            }
+            val showMore = remember {
+                mutableStateOf(false)
+            }
+
+            // touch surface
+            Surface(color = Color.Transparent, modifier = Modifier
+                .fillMaxSize()
+                .padding(0.dp)
+                .pointerInput(Unit) {
+                    awaitPointerEventScope {
+                        while (true) {
+                            val event = awaitPointerEvent()
+                            if (!showController.value)
+                                continue
+
+                            val change = event
+                                .component1()
+                                .firstOrNull()
+                            change?.apply {
+                                val position = this.position
+
+                                when (event.type) {
+                                    PointerEventType.Press -> {
+                                        ryujinxNative.inputSetTouchPoint(
+                                            position.x.roundToInt(),
+                                            position.y.roundToInt()
+                                        )
+                                    }
+
+                                    PointerEventType.Release -> {
+                                        ryujinxNative.inputReleaseTouchPoint()
+
+                                    }
+
+                                    PointerEventType.Move -> {
+                                        ryujinxNative.inputSetTouchPoint(
+                                            position.x.roundToInt(),
+                                            position.y.roundToInt()
+                                        )
+
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }) {
+            }
+            GameController.Compose(mainViewModel)
+            Row(
+                modifier = Modifier
+                    .align(Alignment.BottomCenter)
+                    .padding(8.dp)
+            ) {
+                IconButton(modifier = Modifier.padding(4.dp), onClick = {
+                    showMore.value = true
+                }) {
+                    Icon(
+                        imageVector = CssGgIcons.ToolbarBottom,
+                        contentDescription = "Open Panel"
+                    )
+                }
+            }
+
+            if(showMore.value){
+                Popup(alignment = Alignment.BottomCenter, onDismissRequest = {showMore.value = false}) {
+                    Surface(modifier = Modifier.padding(16.dp),
+                        shape = MaterialTheme.shapes.medium) {
+                        Row(modifier = Modifier.padding(8.dp)) {
+                            IconButton(modifier = Modifier.padding(4.dp), onClick = {
+                                showMore.value = false
+                                showController.value = !showController.value
+                                mainViewModel.controller?.setVisible(showController.value)
+                            }) {
+                                Icon(
+                                    imageVector = Icons.videoGame(),
+                                    contentDescription = "Toggle Virtual Pad"
+                                )
+                            }
+                            IconButton(modifier = Modifier.padding(4.dp), onClick = {
+                                showMore.value = false
+                                enableVsync.value = !enableVsync.value
+                                RyujinxNative().graphicsRendererSetVsync(enableVsync.value)
+                            }) {
+                                Icon(
+                                    imageVector = Icons.vSync(),
+                                    tint = if(enableVsync.value) Color.Green else Color.Red,
+                                    contentDescription = "Toggle VSync"
+                                )
+                            }
+                        }
+                    }
+                }
+            }
+
+            val showBackNotice = remember {
+                mutableStateOf(false)
+            }
+
+            BackHandler {
+                showBackNotice.value = true
+            }
+
+            if (showBackNotice.value) {
+                AlertDialog(onDismissRequest = { showBackNotice.value = false }) {
+                    Column {
+                        Surface(
+                            modifier = Modifier
+                                .wrapContentWidth()
+                                .wrapContentHeight(),
+                            shape = MaterialTheme.shapes.large,
+                            tonalElevation = AlertDialogDefaults.TonalElevation
+                        ) {
+                            Column {
+                                Column(
+                                    modifier = Modifier
+                                        .fillMaxWidth()
+                                        .padding(16.dp)
+                                ) {
+                                    Text(text = "Are you sure you want to exit the game?")
+                                    Text(text = "All unsaved data will be lost!")
+                                }
+                                Row(
+                                    horizontalArrangement = Arrangement.End,
+                                    modifier = Modifier
+                                        .fillMaxWidth()
+                                        .padding(16.dp)
+                                ) {
+                                    Button(onClick = {
+                                        mainViewModel.closeGame()
+                                        setFullScreen(false)
+                                        finishActivity(0)
+                                    }, modifier = Modifier.padding(16.dp)) {
+                                        Text(text = "Exit Game")
+                                    }
+
+                                    Button(onClick = {
+                                        showBackNotice.value = false
+                                    }, modifier = Modifier.padding(16.dp)) {
+                                        Text(text = "Dismiss")
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+
+    @Composable
+    fun GameStats(mainViewModel: MainViewModel) {
+        val fifo = remember {
+            mutableStateOf(0.0)
+        }
+        val gameFps = remember {
+            mutableStateOf(0.0)
+        }
+        val gameTime = remember {
+            mutableStateOf(0.0)
+        }
+
+        Surface(
+            modifier = Modifier.padding(16.dp),
+            color = MaterialTheme.colorScheme.surface.copy(0.4f)
+        ) {
+            Column {
+                var gameTimeVal = 0.0
+                if (!gameTime.value.isInfinite())
+                    gameTimeVal = gameTime.value
+                Text(text = "${String.format("%.3f", fifo.value)} %")
+                Text(text = "${String.format("%.3f", gameFps.value)} FPS")
+                Text(text = "${String.format("%.3f", gameTimeVal)} ms")
+            }
+        }
+
+        mainViewModel.setStatStates(fifo, gameFps, gameTime)
+    }
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt
index a85b6852c..76bc2c9f2 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/GameHost.kt
@@ -1,5 +1,6 @@
 package org.ryujinx.android
 
+import android.annotation.SuppressLint
 import android.content.Context
 import android.os.Build
 import android.view.SurfaceHolder
@@ -7,22 +8,19 @@ import android.view.SurfaceView
 import org.ryujinx.android.viewmodels.GameModel
 import org.ryujinx.android.viewmodels.MainViewModel
 import org.ryujinx.android.viewmodels.QuickSettings
-import org.ryujinx.android.viewmodels.VulkanDriverViewModel
-import java.io.File
 import kotlin.concurrent.thread
 
-class GameHost(context: Context?, val mainViewModel: MainViewModel) : SurfaceView(context), SurfaceHolder.Callback {
+@SuppressLint("ViewConstructor")
+class GameHost(context: Context?, private val mainViewModel: MainViewModel) : SurfaceView(context), SurfaceHolder.Callback {
     private var game: GameModel? = null
     private var _isClosed: Boolean = false
     private var _renderingThreadWatcher: Thread? = null
     private var _height: Int = 0
     private var _width: Int = 0
     private var _updateThread: Thread? = null
-    private var nativeInterop: NativeGraphicsInterop? = null
     private var _guestThread: Thread? = null
     private var _isInit: Boolean = false
     private var _isStarted: Boolean = false
-    private var _nativeWindow: Long = 0
 
     private var _nativeRyujinx: RyujinxNative = RyujinxNative()
 
@@ -48,6 +46,11 @@ class GameHost(context: Context?, val mainViewModel: MainViewModel) : SurfaceVie
         _width = width
         _height = height
 
+        _nativeRyujinx.graphicsRendererSetSize(
+            width,
+            height
+        )
+
         if(_isStarted)
         {
             _nativeRyujinx.inputSetClientSize(width, height)
@@ -70,7 +73,7 @@ class GameHost(context: Context?, val mainViewModel: MainViewModel) : SurfaceVie
     private fun start(surfaceHolder: SurfaceHolder) {
         mainViewModel.gameHost = this
         if(_isStarted)
-            return;
+            return
 
         game = mainViewModel.gameModel
 
@@ -85,7 +88,7 @@ class GameHost(context: Context?, val mainViewModel: MainViewModel) : SurfaceVie
             mainViewModel.controller?.connect()
         }
 
-        mainViewModel.activity.physicalControllerManager.connect()
+        mainViewModel.physicalControllerManager?.connect()
 
         _nativeRyujinx.graphicsRendererSetSize(
             surfaceHolder.surfaceFrame.width(),
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt
index e833b82d4..780a8fa6d 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Helpers.kt
@@ -4,7 +4,6 @@ import android.content.ContentUris
 import android.content.Context
 import android.database.Cursor
 import android.net.Uri
-import android.os.Build
 import android.os.Environment
 import android.provider.DocumentsContract
 import android.provider.MediaStore
@@ -12,10 +11,9 @@ import android.provider.MediaStore
 class Helpers {
     companion object{
         fun getPath(context: Context, uri: Uri): String? {
-            val isKitKatorAbove = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
 
             // DocumentProvider
-            if (isKitKatorAbove && DocumentsContract.isDocumentUri(context, uri)) {
+            if (DocumentsContract.isDocumentUri(context, uri)) {
                 // ExternalStorageProvider
                 if (isExternalStorageDocument(uri)) {
                     val docId = DocumentsContract.getDocumentId(uri)
@@ -57,7 +55,7 @@ class Helpers {
             return null
         }
 
-        fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
+        private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
             var cursor: Cursor? = null
             val column = "_data"
             val projection = arrayOf(column)
@@ -73,16 +71,16 @@ class Helpers {
             return null
         }
 
-        fun isExternalStorageDocument(uri: Uri): Boolean {
+        private fun isExternalStorageDocument(uri: Uri): Boolean {
             return "com.android.externalstorage.documents" == uri.authority
         }
 
-        fun isDownloadsDocument(uri: Uri): Boolean {
+        private fun isDownloadsDocument(uri: Uri): Boolean {
             return "com.android.providers.downloads.documents" == uri.authority
         }
 
-        fun isMediaDocument(uri: Uri): Boolean {
+        private fun isMediaDocument(uri: Uri): Boolean {
             return "com.android.providers.media.documents" == uri.authority
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Icons.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Icons.kt
index 23e8d6fef..13820e150 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Icons.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/Icons.kt
@@ -1,8 +1,6 @@
 package org.ryujinx.android
 
 import androidx.compose.foundation.layout.padding
-import androidx.compose.material.icons.Icons
-import androidx.compose.material.icons.filled.KeyboardArrowUp
 import androidx.compose.material3.Icon
 import androidx.compose.material3.IconButton
 import androidx.compose.material3.MaterialTheme
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/MainActivity.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/MainActivity.kt
index 178ee43b6..d9817f69a 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/MainActivity.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/MainActivity.kt
@@ -1,39 +1,23 @@
 package org.ryujinx.android
 
-import android.annotation.SuppressLint
-import android.content.Context
-import android.content.pm.ActivityInfo
-import android.media.AudioDeviceInfo
-import android.media.AudioManager
 import android.os.Build
 import android.os.Bundle
 import android.os.Environment
-import android.view.KeyEvent
-import android.view.MotionEvent
 import android.view.WindowManager
 import androidx.activity.ComponentActivity
-import androidx.activity.addCallback
 import androidx.activity.compose.setContent
 import androidx.compose.foundation.layout.fillMaxSize
 import androidx.compose.material3.MaterialTheme
 import androidx.compose.material3.Surface
-import androidx.compose.runtime.Composable
 import androidx.compose.ui.Modifier
-import androidx.compose.ui.tooling.preview.Preview
 import androidx.core.view.WindowCompat
-import androidx.core.view.WindowInsetsCompat
-import androidx.core.view.WindowInsetsControllerCompat
 import com.anggrayudi.storage.SimpleStorageHelper
 import org.ryujinx.android.ui.theme.RyujinxAndroidTheme
 import org.ryujinx.android.viewmodels.MainViewModel
-import org.ryujinx.android.viewmodels.VulkanDriverViewModel
-import org.ryujinx.android.views.HomeViews
 import org.ryujinx.android.views.MainView
-import java.io.File
 
 
 class MainActivity : ComponentActivity() {
-    var physicalControllerManager: PhysicalControllerManager = PhysicalControllerManager(this)
     private var _isInit: Boolean = false
     var storageHelper: SimpleStorageHelper? = null
     companion object {
@@ -61,60 +45,7 @@ class MainActivity : ComponentActivity() {
     }
 
     external fun getRenderingThreadId() : Long
-    external fun initVm()
-
-    fun setFullScreen(fullscreen: Boolean) {
-        requestedOrientation =
-            if (fullscreen) ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE else ActivityInfo.SCREEN_ORIENTATION_FULL_USER
-
-        val insets = WindowCompat.getInsetsController(window, window.decorView)
-
-        insets.apply {
-            if (fullscreen) {
-                insets.hide(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars())
-                insets.systemBarsBehavior =
-                    WindowInsetsControllerCompat.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE
-            } else {
-                insets.show(WindowInsetsCompat.Type.statusBars() or WindowInsetsCompat.Type.navigationBars())
-                insets.systemBarsBehavior =
-                    WindowInsetsControllerCompat.BEHAVIOR_DEFAULT
-            }
-        }
-    }
-
-    private fun getAudioDevice () : Int {
-        val audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
-
-        val devices = audioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS)
-
-        return if (devices.isEmpty())
-            0
-        else {
-            val speaker = devices.find { it.type == AudioDeviceInfo.TYPE_BUILTIN_SPEAKER }
-            val earPiece = devices.find { it.type == AudioDeviceInfo.TYPE_WIRED_HEADPHONES || it.type == AudioDeviceInfo.TYPE_WIRED_HEADSET }
-            if(earPiece != null)
-                return earPiece.id
-            if(speaker != null)
-                return  speaker.id
-            devices.first().id
-        }
-    }
-
-    @SuppressLint("RestrictedApi")
-    override fun dispatchKeyEvent(event: KeyEvent?): Boolean {
-        event?.apply {
-            if(physicalControllerManager.onKeyEvent(this))
-                return true;
-        }
-        return super.dispatchKeyEvent(event)
-    }
-
-    override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
-        ev?.apply {
-            physicalControllerManager.onMotionEvent(this)
-        }
-        return super.dispatchGenericMotionEvent(ev)
-    }
+    private external fun initVm()
 
     private fun initialize() {
         if (_isInit)
@@ -150,15 +81,6 @@ class MainActivity : ComponentActivity() {
                         modifier = Modifier.fillMaxSize(),
                         color = MaterialTheme.colorScheme.background
                     ) {
-                        /*Box {
-                        AndroidView(
-                            modifier = Modifier.fillMaxSize(),
-                            factory = { context ->
-                                GameHost(context)
-                            }
-                        )
-                        controller.Compose(lifecycleScope, lifecycle)
-                    }*/
                         MainView.Main(mainViewModel = this)
                     }
                 }
@@ -176,16 +98,3 @@ class MainActivity : ComponentActivity() {
         storageHelper?.onRestoreInstanceState(savedInstanceState)
     }
 }
-
-@Composable
-fun Greeting(name: String, modifier: Modifier = Modifier) {
-
-}
-
-@Preview(showBackground = true)
-@Composable
-fun GreetingPreview() {
-    RyujinxAndroidTheme {
-        HomeViews.Home()
-    }
-}
\ No newline at end of file
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeGraphicsInterop.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeGraphicsInterop.kt
index 262b551c3..e4dddff01 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeGraphicsInterop.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeGraphicsInterop.kt
@@ -1,9 +1,7 @@
 package org.ryujinx.android
 
-import android.view.Surface
-
 class NativeGraphicsInterop {
     var VkCreateSurface: Long = 0
     var SurfaceHandle: Long = 0
     var VkRequiredExtensions: Array<String>? = null
-}
\ No newline at end of file
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt
index 4b52c2862..f37114ad7 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/NativeHelpers.kt
@@ -9,12 +9,14 @@ class NativeHelpers {
             System.loadLibrary("ryujinxjni")
         }
     }
-    external fun releaseNativeWindow(window:Long) : Unit
+    external fun releaseNativeWindow(window:Long)
     external fun createSurface(vkInstance:Long, window:Long) : Long
     external fun getCreateSurfacePtr() : Long
     external fun getNativeWindow(surface:Surface) : Long
-    external fun attachCurrentThread() : Unit
-    external fun detachCurrentThread() : Unit
+    external fun attachCurrentThread()
+    external fun detachCurrentThread()
 
     external fun loadDriver(nativeLibPath:String, privateAppsPath:String, driverName:String) : Long
-}
\ No newline at end of file
+
+    external fun setTurboMode(enable: Boolean)
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PerformanceManager.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PerformanceManager.kt
index b675854e5..0b1cdbfdd 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PerformanceManager.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PerformanceManager.kt
@@ -4,10 +4,10 @@ import android.os.Build
 import android.os.PerformanceHintManager
 import androidx.annotation.RequiresApi
 
-class PerformanceManager(val performanceHintManager: PerformanceHintManager) {
+class PerformanceManager(private val performanceHintManager: PerformanceHintManager) {
     private var _isEnabled: Boolean = false
     private var renderingSession: PerformanceHintManager.Session? = null
-    val DEFAULT_TARGET_NS = 16666666L
+    private val DEFAULT_TARGET_NS = 16666666L
 
     @RequiresApi(Build.VERSION_CODES.S)
     fun initializeRenderingSession(threadId : Long){
@@ -46,4 +46,4 @@ class PerformanceManager(val performanceHintManager: PerformanceHintManager) {
             this.reportActualWorkDuration(effectiveTime)
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PhysicalControllerManager.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PhysicalControllerManager.kt
index 7191c883e..9913956bd 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PhysicalControllerManager.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/PhysicalControllerManager.kt
@@ -3,13 +3,13 @@ package org.ryujinx.android
 import android.view.KeyEvent
 import android.view.MotionEvent
 
-class PhysicalControllerManager(val activity: MainActivity) {
+class PhysicalControllerManager(val activity: GameActivity) {
     private var controllerId: Int = -1
     private var ryujinxNative: RyujinxNative = RyujinxNative()
 
     fun onKeyEvent(event: KeyEvent) : Boolean{
         if(controllerId != -1) {
-            val id = GetGamePadButtonInputId(event.keyCode)
+            val id = getGamePadButtonInputId(event.keyCode)
 
             if(id != GamePadButtonInputId.None) {
                 when (event.action) {
@@ -45,7 +45,7 @@ class PhysicalControllerManager(val activity: MainActivity) {
         controllerId = ryujinxNative.inputConnectGamepad(0)
     }
 
-    fun GetGamePadButtonInputId(keycode: Int): GamePadButtonInputId {
+    private fun getGamePadButtonInputId(keycode: Int): GamePadButtonInputId {
         return when (keycode) {
             KeyEvent.KEYCODE_BUTTON_A -> GamePadButtonInputId.B
             KeyEvent.KEYCODE_BUTTON_B -> GamePadButtonInputId.A
@@ -66,4 +66,4 @@ class PhysicalControllerManager(val activity: MainActivity) {
             else -> GamePadButtonInputId.None
         }
     }
-}
\ No newline at end of file
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt
index c89259147..682050602 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/RyujinxNative.kt
@@ -35,21 +35,21 @@ class RyujinxNative {
     external fun deviceGetGameInfo(fileDescriptor: Int,  isXci:Boolean): GameInfo
     external fun deviceGetGameInfoFromPath(path: String): GameInfo
     external fun deviceLoadDescriptor(fileDescriptor: Int,  isXci:Boolean): Boolean
-    external fun graphicsRendererSetSize(width: Int, height: Int): Unit
-    external fun graphicsRendererSetVsync(enabled: Boolean): Unit
-    external fun graphicsRendererRunLoop(): Unit
-    external fun inputInitialize(width: Int, height: Int): Unit
-    external fun inputSetClientSize(width: Int, height: Int): Unit
-    external fun inputSetTouchPoint(x: Int, y: Int): Unit
-    external fun inputReleaseTouchPoint(): Unit
-    external fun inputUpdate(): Unit
-    external fun inputSetButtonPressed(button: Int, id: Int): Unit
-    external fun inputSetButtonReleased(button: Int, id: Int): Unit
+    external fun graphicsRendererSetSize(width: Int, height: Int)
+    external fun graphicsRendererSetVsync(enabled: Boolean)
+    external fun graphicsRendererRunLoop()
+    external fun inputInitialize(width: Int, height: Int)
+    external fun inputSetClientSize(width: Int, height: Int)
+    external fun inputSetTouchPoint(x: Int, y: Int)
+    external fun inputReleaseTouchPoint()
+    external fun inputUpdate()
+    external fun inputSetButtonPressed(button: Int, id: Int)
+    external fun inputSetButtonReleased(button: Int, id: Int)
     external fun inputConnectGamepad(index: Int): Int
-    external fun inputSetStickAxis(stick: Int, x: Float, y: Float, id: Int): Unit
+    external fun inputSetStickAxis(stick: Int, x: Float, y: Float, id: Int)
     external fun graphicsSetSurface(surface: Long)
     external fun deviceCloseEmulation()
     external fun deviceSignalEmulationClose()
     external fun deviceGetDlcTitleId(path: String, ncaPath: String) : String
     external fun deviceGetDlcContentList(path: String, titleId: Long) : Array<String>
-}
\ No newline at end of file
+}
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/MainViewModel.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/MainViewModel.kt
index b86d7d799..c6c157f8d 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/MainViewModel.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/viewmodels/MainViewModel.kt
@@ -2,10 +2,12 @@ package org.ryujinx.android.viewmodels
 
 import android.annotation.SuppressLint
 import android.content.Context
+import android.content.Intent
 import android.os.Build
 import android.os.PerformanceHintManager
 import androidx.compose.runtime.MutableState
 import androidx.navigation.NavHostController
+import org.ryujinx.android.GameActivity
 import org.ryujinx.android.GameController
 import org.ryujinx.android.GameHost
 import org.ryujinx.android.GraphicsConfiguration
@@ -13,6 +15,7 @@ import org.ryujinx.android.MainActivity
 import org.ryujinx.android.NativeGraphicsInterop
 import org.ryujinx.android.NativeHelpers
 import org.ryujinx.android.PerformanceManager
+import org.ryujinx.android.PhysicalControllerManager
 import org.ryujinx.android.RegionCode
 import org.ryujinx.android.RyujinxNative
 import org.ryujinx.android.SystemLanguage
@@ -20,6 +23,7 @@ import java.io.File
 
 @SuppressLint("WrongConstant")
 class MainViewModel(val activity: MainActivity) {
+    var physicalControllerManager: PhysicalControllerManager? = null
     var gameModel: GameModel? = null
     var gameHost: GameHost? = null
     var controller: GameController? = null
@@ -44,23 +48,17 @@ class MainViewModel(val activity: MainActivity) {
         RyujinxNative().deviceSignalEmulationClose()
         gameHost?.close()
         RyujinxNative().deviceCloseEmulation()
-        goBack()
-        activity.setFullScreen(false)
-    }
-
-    fun goBack(){
-        navController?.popBackStack()
     }
 
     fun loadGame(game:GameModel) : Boolean {
-        var nativeRyujinx = RyujinxNative()
+        val nativeRyujinx = RyujinxNative()
 
         val descriptor = game.open()
 
         if(descriptor == 0)
             return false
 
-        gameModel = game;
+        gameModel = game
 
         val settings = QuickSettings(activity)
 
@@ -68,42 +66,45 @@ class MainViewModel(val activity: MainActivity) {
             EnableShaderCache = settings.enableShaderCache
             EnableTextureRecompression = settings.enableTextureRecompression
             ResScale = settings.resScale
+            BackendThreading = org.ryujinx.android.BackendThreading.Auto.ordinal
         })
 
         if(!success)
             return false
 
         val nativeHelpers = NativeHelpers()
-        var nativeInterop = NativeGraphicsInterop()
-        nativeInterop!!.VkRequiredExtensions = arrayOf(
+        val nativeInterop = NativeGraphicsInterop()
+        nativeInterop.VkRequiredExtensions = arrayOf(
             "VK_KHR_surface", "VK_KHR_android_surface"
         )
-        nativeInterop!!.VkCreateSurface = nativeHelpers.getCreateSurfacePtr()
-        nativeInterop!!.SurfaceHandle = 0
+        nativeInterop.VkCreateSurface = nativeHelpers.getCreateSurfacePtr()
+        nativeInterop.SurfaceHandle = 0
 
-        var driverViewModel = VulkanDriverViewModel(activity);
-        var drivers = driverViewModel.getAvailableDrivers()
+        val driverViewModel = VulkanDriverViewModel(activity)
+        val drivers = driverViewModel.getAvailableDrivers()
 
-        var driverHandle = 0L;
+        var driverHandle = 0L
 
         if (driverViewModel.selected.isNotEmpty()) {
-            var metaData = drivers.find { it.driverPath == driverViewModel.selected }
+            val metaData = drivers.find { it.driverPath == driverViewModel.selected }
 
             metaData?.apply {
-                var privatePath = activity.filesDir;
-                var privateDriverPath = privatePath.canonicalPath + "/driver/"
+                val privatePath = activity.filesDir
+                val privateDriverPath = privatePath.canonicalPath + "/driver/"
                 val pD = File(privateDriverPath)
                 if (pD.exists())
                     pD.deleteRecursively()
 
                 pD.mkdirs()
 
-                var driver = File(driverViewModel.selected)
-                var parent = driver.parentFile
-                for (file in parent.walkTopDown()) {
-                    if (file.absolutePath == parent.absolutePath)
-                        continue
-                    file.copyTo(File(privateDriverPath + file.name), true)
+                val driver = File(driverViewModel.selected)
+                val parent = driver.parentFile
+                if (parent != null) {
+                    for (file in parent.walkTopDown()) {
+                        if (file.absolutePath == parent.absolutePath)
+                            continue
+                        file.copyTo(File(privateDriverPath + file.name), true)
+                    }
                 }
 
                 driverHandle = NativeHelpers().loadDriver(
@@ -116,7 +117,7 @@ class MainViewModel(val activity: MainActivity) {
         }
 
         success = nativeRyujinx.graphicsInitializeRenderer(
-            nativeInterop!!.VkRequiredExtensions!!,
+            nativeInterop.VkRequiredExtensions!!,
             driverHandle
         )
         if(!success)
@@ -175,6 +176,8 @@ class MainViewModel(val activity: MainActivity) {
         this.controller = controller
     }
 
-    fun backCalled() {
+    fun navigateToGame() {
+        val intent = Intent(activity, GameActivity::class.java)
+        activity.startActivity(intent)
     }
 }
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
index 3c7e7d9e3..5a8e44167 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/HomeViews.kt
@@ -387,10 +387,7 @@ class HomeViews {
                                             viewModel.mainViewModel?.loadGame(gameModel) ?: false
                                         if (success) {
                                             launchOnUiThread {
-                                                viewModel.mainViewModel?.activity?.setFullScreen(
-                                                    true
-                                                )
-                                                viewModel.mainViewModel?.navController?.navigate("game")
+                                                viewModel.mainViewModel?.navigateToGame()
                                             }
                                         } else {
                                             gameModel.close()
diff --git a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt
index 872c19119..7c5c988e1 100644
--- a/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt
+++ b/src/RyujinxAndroid/app/src/main/java/org/ryujinx/android/views/MainView.kt
@@ -1,48 +1,11 @@
 package org.ryujinx.android.views
 
-import androidx.activity.compose.BackHandler
-import androidx.compose.foundation.layout.Arrangement
-import androidx.compose.foundation.layout.Box
-import androidx.compose.foundation.layout.Column
-import androidx.compose.foundation.layout.Row
-import androidx.compose.foundation.layout.fillMaxSize
-import androidx.compose.foundation.layout.fillMaxWidth
-import androidx.compose.foundation.layout.padding
-import androidx.compose.foundation.layout.wrapContentHeight
-import androidx.compose.foundation.layout.wrapContentWidth
-import androidx.compose.material3.AlertDialog
-import androidx.compose.material3.AlertDialogDefaults
-import androidx.compose.material3.Button
-import androidx.compose.material3.ExperimentalMaterial3Api
-import androidx.compose.material3.Icon
-import androidx.compose.material3.IconButton
-import androidx.compose.material3.MaterialTheme
-import androidx.compose.material3.Surface
-import androidx.compose.material3.Text
 import androidx.compose.runtime.Composable
-import androidx.compose.runtime.mutableStateOf
-import androidx.compose.runtime.remember
-import androidx.compose.ui.Alignment
-import androidx.compose.ui.Modifier
-import androidx.compose.ui.graphics.Color
-import androidx.compose.ui.input.pointer.PointerEventType
-import androidx.compose.ui.input.pointer.pointerInput
-import androidx.compose.ui.unit.dp
-import androidx.compose.ui.viewinterop.AndroidView
-import androidx.compose.ui.window.Popup
 import androidx.navigation.compose.NavHost
 import androidx.navigation.compose.composable
 import androidx.navigation.compose.rememberNavController
-import compose.icons.CssGgIcons
-import compose.icons.cssggicons.ToolbarBottom
-import org.ryujinx.android.GameController
-import org.ryujinx.android.GameHost
-import org.ryujinx.android.Icons
-import org.ryujinx.android.RyujinxNative
 import org.ryujinx.android.viewmodels.MainViewModel
-import org.ryujinx.android.viewmodels.QuickSettings
 import org.ryujinx.android.viewmodels.SettingsViewModel
-import kotlin.math.roundToInt
 
 class MainView {
     companion object {
@@ -53,7 +16,6 @@ class MainView {
 
             NavHost(navController = navController, startDestination = "home") {
                 composable("home") { HomeViews.Home(mainViewModel.homeViewModel, navController) }
-                composable("game") { GameView(mainViewModel) }
                 composable("settings") {
                     SettingViews.Main(
                         SettingsViewModel(
@@ -64,207 +26,5 @@ class MainView {
                 }
             }
         }
-
-        @Composable
-        fun GameView(mainViewModel: MainViewModel) {
-            Box(modifier = Modifier.fillMaxSize()) {
-                AndroidView(
-                    modifier = Modifier.fillMaxSize(),
-                    factory = { context ->
-                        GameHost(context, mainViewModel)
-                    }
-                )
-                GameOverlay(mainViewModel)
-            }
-        }
-
-        @OptIn(ExperimentalMaterial3Api::class)
-        @Composable
-        fun GameOverlay(mainViewModel: MainViewModel) {
-            Box(modifier = Modifier.fillMaxSize()) {
-                GameStats(mainViewModel)
-
-                val ryujinxNative = RyujinxNative()
-
-                var showController = remember {
-                    mutableStateOf(QuickSettings(mainViewModel.activity).useVirtualController)
-                }
-                var enableVsync = remember {
-                    mutableStateOf(QuickSettings(mainViewModel.activity).enableVsync)
-                }
-                var showMore = remember {
-                    mutableStateOf(false)
-                }
-
-                // touch surface
-                Surface(color = Color.Transparent, modifier = Modifier
-                    .fillMaxSize()
-                    .padding(0.dp)
-                    .pointerInput(Unit) {
-                        awaitPointerEventScope {
-                            while (true) {
-                                val event = awaitPointerEvent()
-                                if (!showController.value)
-                                    continue
-
-                                val change = event
-                                    .component1()
-                                    .firstOrNull()
-                                change?.apply {
-                                    val position = this.position
-
-                                    when (event.type) {
-                                        PointerEventType.Press -> {
-                                            ryujinxNative.inputSetTouchPoint(
-                                                position.x.roundToInt(),
-                                                position.y.roundToInt()
-                                            )
-                                        }
-
-                                        PointerEventType.Release -> {
-                                            ryujinxNative.inputReleaseTouchPoint()
-
-                                        }
-
-                                        PointerEventType.Move -> {
-                                            ryujinxNative.inputSetTouchPoint(
-                                                position.x.roundToInt(),
-                                                position.y.roundToInt()
-                                            )
-
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }) {
-                }
-                GameController.Compose(mainViewModel)
-                Row(
-                    modifier = Modifier
-                        .align(Alignment.BottomCenter)
-                        .padding(8.dp)
-                ) {
-                    IconButton(modifier = Modifier.padding(4.dp), onClick = {
-                        showMore.value = true
-                    }) {
-                        Icon(
-                            imageVector = CssGgIcons.ToolbarBottom,
-                            contentDescription = "Open Panel"
-                        )
-                    }
-                }
-
-                if(showMore.value){
-                    Popup(alignment = Alignment.BottomCenter, onDismissRequest = {showMore.value = false}) {
-                        Surface(modifier = Modifier.padding(16.dp),
-                            shape = MaterialTheme.shapes.medium) {
-                            Row(modifier = Modifier.padding(8.dp)) {
-                                IconButton(modifier = Modifier.padding(4.dp), onClick = {
-                                    showMore.value = false
-                                    showController.value = !showController.value
-                                    mainViewModel.controller?.setVisible(showController.value)
-                                }) {
-                                    Icon(
-                                        imageVector = Icons.videoGame(),
-                                        contentDescription = "Toggle Virtual Pad"
-                                    )
-                                }
-                                IconButton(modifier = Modifier.padding(4.dp), onClick = {
-                                    showMore.value = false
-                                    enableVsync.value = !enableVsync.value
-                                    RyujinxNative().graphicsRendererSetVsync(enableVsync.value)
-                                }) {
-                                    Icon(
-                                        imageVector = Icons.vSync(),
-                                        tint = if(enableVsync.value) Color.Green else Color.Red,
-                                        contentDescription = "Toggle VSync"
-                                    )
-                                }
-                            }
-                        }
-                    }
-                }
-
-                var showBackNotice = remember {
-                    mutableStateOf(false)
-                }
-
-                BackHandler {
-                    showBackNotice.value = true
-                }
-
-                if (showBackNotice.value) {
-                    AlertDialog(onDismissRequest = { showBackNotice.value = false }) {
-                        Column {
-                            Surface(
-                                modifier = Modifier
-                                    .wrapContentWidth()
-                                    .wrapContentHeight(),
-                                shape = MaterialTheme.shapes.large,
-                                tonalElevation = AlertDialogDefaults.TonalElevation
-                            ) {
-                                Column {
-                                    Column(
-                                        modifier = Modifier
-                                            .fillMaxWidth()
-                                            .padding(16.dp)
-                                    ) {
-                                        Text(text = "Are you sure you want to exit the game?")
-                                        Text(text = "All unsaved data will be lost!")
-                                    }
-                                    Row(
-                                        horizontalArrangement = Arrangement.End,
-                                        modifier = Modifier
-                                            .fillMaxWidth()
-                                            .padding(16.dp)
-                                    ) {
-                                        Button(onClick = {
-                                            mainViewModel.closeGame()
-                                        }, modifier = Modifier.padding(16.dp)) {
-                                            Text(text = "Exit Game")
-                                        }
-
-                                        Button(onClick = {
-                                            showBackNotice.value = false
-                                        }, modifier = Modifier.padding(16.dp)) {
-                                            Text(text = "Dismiss")
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
-                }
-            }
-        }
-        @Composable
-        fun GameStats(mainViewModel: MainViewModel) {
-            val fifo = remember {
-                mutableStateOf(0.0)
-            }
-            val gameFps = remember {
-                mutableStateOf(0.0)
-            }
-            val gameTime = remember {
-                mutableStateOf(0.0)
-            }
-
-            Surface(
-                modifier = Modifier.padding(16.dp),
-                color = MaterialTheme.colorScheme.surface.copy(0.4f)
-            ) {
-                Column {
-                    var gameTimeVal = 0.0
-                    if (!gameTime.value.isInfinite())
-                        gameTimeVal = gameTime.value
-                    Text(text = "${String.format("%.3f", fifo.value)} %")
-                    Text(text = "${String.format("%.3f", gameFps.value)} FPS")
-                    Text(text = "${String.format("%.3f", gameTimeVal)} ms")
-                }
-            }
-
-            mainViewModel.setStatStates(fifo, gameFps, gameTime)
-        }
     }
 }