diff --git a/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp b/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp index cb71234d..6f62572c 100644 --- a/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp +++ b/src/Cafe/HW/Espresso/Recompiler/BackendAArch64/BackendAArch64.cpp @@ -68,6 +68,7 @@ class AArch64Allocator : public Allocator #else inline static Allocator s_allocator; #endif + inline static std::mutex s_allocatorMutex; Allocator* m_allocatorImpl; bool m_freeDisabled = false; @@ -77,6 +78,7 @@ class AArch64Allocator : public Allocator uint32* alloc(size_t size) override { + std::lock_guard lock{s_allocatorMutex}; return m_allocatorImpl->alloc(size); } @@ -87,8 +89,11 @@ class AArch64Allocator : public Allocator void free(uint32* p) override { - if (!m_freeDisabled) - m_allocatorImpl->free(p); + if (m_freeDisabled) + return; + + std::lock_guard lock{s_allocatorMutex}; + m_allocatorImpl->free(p); } [[nodiscard]] bool useProtect() const override diff --git a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp index 4d4a13ad..f9754efe 100644 --- a/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Vulkan/VulkanRenderer.cpp @@ -2097,10 +2097,10 @@ void VulkanRenderer::SubmitCommandBuffer(VkSemaphore signalSemaphore, VkSemaphor const VkPipelineStageFlags semWaitStageMask[2] = { VK_PIPELINE_STAGE_ALL_COMMANDS_BIT, VK_PIPELINE_STAGE_ALL_COMMANDS_BIT }; VkSemaphore waitSemArray[2]; submitInfo.waitSemaphoreCount = 0; - if (m_numSubmittedCmdBuffers > 0) - waitSemArray[submitInfo.waitSemaphoreCount++] = prevSem; // wait on semaphore from previous submit if (waitSemaphore != VK_NULL_HANDLE) waitSemArray[submitInfo.waitSemaphoreCount++] = waitSemaphore; + if (m_numSubmittedCmdBuffers > 0) + waitSemArray[submitInfo.waitSemaphoreCount++] = prevSem; // wait on semaphore from previous submit submitInfo.pWaitDstStageMask = semWaitStageMask; submitInfo.pWaitSemaphores = waitSemArray; diff --git a/src/Common/version.h b/src/Common/version.h index 36925a52..9ba92219 100644 --- a/src/Common/version.h +++ b/src/Common/version.h @@ -7,7 +7,7 @@ #define _XSTRINGFY(s) _STRINGFY(s) #define _STRINGFY(s) #s -#if EMULATOR_VERSION_MAJOR != 0 +#if EMULATOR_VERSION_MAJOR != 0 || EMULATOR_VERSION_MINOR != 0 #define BUILD_VERSION_WITH_NAME_STRING (EMULATOR_NAME " " _XSTRINGFY(EMULATOR_VERSION_MAJOR) "." _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX) #define BUILD_VERSION_STRING (_XSTRINGFY(EMULATOR_VERSION_MAJOR) "." _XSTRINGFY(EMULATOR_VERSION_MINOR) EMULATOR_VERSION_SUFFIX) #else diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index da5927ab..dd0541a6 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -90,7 +90,7 @@ android { debug { applicationIdSuffix = ".debug" } - create("githubRelease") { + create("github") { if (keystoreFilePath != null) { initWith(getByName("release")) isMinifyEnabled = true @@ -177,16 +177,16 @@ abstract class ComputeCemuDataFilesHashTask : DefaultTask() { assetDir.mkdirs() } - val cemuDataFilesFile = File(project.projectDir, cemuDataFolder.get()) + val cemuDataFilesDir = File(project.projectDir, cemuDataFolder.get()) val hashFile = File(assetDir, "hash.txt") val md = MessageDigest.getInstance("SHA-256") - if (!cemuDataFilesFile.isDirectory) { + if (!cemuDataFilesDir.isDirectory) { hashFile.writeText("invalid") return } - val fileHashes = cemuDataFilesFile.walkTopDown() + val fileHashes = cemuDataFilesDir.walkTopDown() .filter { it.isFile && !isFileIgnored(it) } .sortedBy { it.path } .map { @@ -204,10 +204,10 @@ abstract class ComputeCemuDataFilesHashTask : DefaultTask() { } } -tasks.register("computeCemuDataFilesHash") { +val computeCemuDataFilesHashTask =tasks.register("computeCemuDataFilesHash") { cemuDataFolder = cemuDataFilesFolder } -tasks.preBuild.dependsOn("computeCemuDataFilesHash") +tasks.preBuild.dependsOn(computeCemuDataFilesHashTask) dependencies { implementation(libs.androidx.lifecycle.runtime.ktx) diff --git a/src/android/app/src/debug/AndroidManifest.xml b/src/android/app/src/debug/AndroidManifest.xml new file mode 100644 index 00000000..0e716a78 --- /dev/null +++ b/src/android/app/src/debug/AndroidManifest.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/src/android/app/src/main/cpp/JNIUtils.cpp b/src/android/app/src/main/cpp/JNIUtils.cpp index 00dbaf44..c3019c01 100644 --- a/src/android/app/src/main/cpp/JNIUtils.cpp +++ b/src/android/app/src/main/cpp/JNIUtils.cpp @@ -87,11 +87,3 @@ jobject JNIUtils::createJavaStringArrayList(JNIEnv* env, const std::vector& func) -{ - std::thread([&]() { - ScopedJNIENV env; - func(*env); - }).join(); -} diff --git a/src/android/app/src/main/cpp/JNIUtils.h b/src/android/app/src/main/cpp/JNIUtils.h index 04e0253a..7a60a0ca 100644 --- a/src/android/app/src/main/cpp/JNIUtils.h +++ b/src/android/app/src/main/cpp/JNIUtils.h @@ -191,5 +191,11 @@ namespace JNIUtils return obj; } - void fiberSafeJNICall(const std::function& func); + inline void fiberSafeJNICall(const std::function& func) + { + std::thread([&]() { + ScopedJNIENV env; + func(*env); + }).join(); + } } // namespace JNIUtils diff --git a/src/android/app/src/main/cpp/NativeSettings.cpp b/src/android/app/src/main/cpp/NativeSettings.cpp index 7bc9bf4f..3efbaa5e 100644 --- a/src/android/app/src/main/cpp/NativeSettings.cpp +++ b/src/android/app/src/main/cpp/NativeSettings.cpp @@ -348,7 +348,6 @@ Java_info_cemu_cemu_nativeinterface_NativeSettings_getCustomDriverPath(JNIEnv* e extern "C" [[maybe_unused]] JNIEXPORT void JNICALL Java_info_cemu_cemu_nativeinterface_NativeSettings_setCustomDriverPath(JNIEnv* env, [[maybe_unused]] jclass clazz, jstring custom_driver_path) { - throw std::runtime_error("todo"); g_config.data().custom_driver_path = JNIUtils::toString(env, custom_driver_path); } diff --git a/src/android/app/src/main/cpp/WuaConverter.cpp b/src/android/app/src/main/cpp/WuaConverter.cpp index f6bcd04e..bca728bf 100644 --- a/src/android/app/src/main/cpp/WuaConverter.cpp +++ b/src/android/app/src/main/cpp/WuaConverter.cpp @@ -21,15 +21,7 @@ void WuaConverter::startConversion(int fd, std::unique_ptronError(); return; } - - struct ScopedFd - { - int fd; - ~ScopedFd() - { - close(fd); - } - } scopedFd{.fd = fd}; + stdx::scope_exit fdCleanup([fd](){ close(fd); }); if (m_started) return; diff --git a/src/android/app/src/main/java/info/cemu/cemu/MainActivity.kt b/src/android/app/src/main/java/info/cemu/cemu/MainActivity.kt index ddae386b..d98cd92f 100644 --- a/src/android/app/src/main/java/info/cemu/cemu/MainActivity.kt +++ b/src/android/app/src/main/java/info/cemu/cemu/MainActivity.kt @@ -27,23 +27,26 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.stringResource import androidx.compose.ui.unit.dp +import androidx.documentfile.provider.DocumentFile import androidx.navigation.compose.NavHost import androidx.navigation.compose.rememberNavController import info.cemu.cemu.about.AboutCemuRoute import info.cemu.cemu.about.aboutCemuNavigation import info.cemu.cemu.emulation.EmulationActivity -import info.cemu.cemu.provider.DocumentsProvider import info.cemu.cemu.gamelist.GameListRoute import info.cemu.cemu.gamelist.gameListNavigation import info.cemu.cemu.graphicpacks.GraphicPacksRoute import info.cemu.cemu.graphicpacks.graphicPacksNavigation import info.cemu.cemu.guicore.components.ActivityContent +import info.cemu.cemu.nativeinterface.NativeActiveSettings import info.cemu.cemu.nativeinterface.NativeGameTitles.Game import info.cemu.cemu.nativeinterface.NativeSettings +import info.cemu.cemu.provider.DocumentsProvider import info.cemu.cemu.settings.SettingsRoute import info.cemu.cemu.settings.settingsNavigation import info.cemu.cemu.titlemanager.TitleManagerRoute import info.cemu.cemu.titlemanager.titleManagerNavigation +import java.io.File class MainActivity : ComponentActivity() { override fun onCreate(savedInstanceState: Bundle?) { @@ -55,6 +58,11 @@ class MainActivity : ComponentActivity() { } } + override fun onDestroy() { + super.onDestroy() + NativeSettings.saveSettings() + } + override fun onPause() { super.onPause() NativeSettings.saveSettings() @@ -123,7 +131,7 @@ private fun GameListToolBarActionsMenu( ) { Icon( imageVector = Icons.Filled.MoreVert, - contentDescription = "More options" + contentDescription = stringResource(R.string.more_options) ) } DropdownMenu( @@ -146,6 +154,10 @@ private fun GameListToolBarActionsMenu( onClick = { openCemuFolder(context) }, text = stringResource(R.string.open_cemu_folder) ) + DropdownMenuItem( + onClick = { shareLogFile(context) }, + text = stringResource(R.string.log_file_share_label), + ) DropdownMenuItem( onClick = goToAboutCemu, text = stringResource(R.string.about_cemu), @@ -153,22 +165,45 @@ private fun GameListToolBarActionsMenu( } } +private fun shareLogFile(context: Context) { + val logFileName = "log.txt" + val logFile = File(NativeActiveSettings.getUserDataPath()).resolve(logFileName) + + if (!logFile.isFile) { + Toast.makeText(context, R.string.log_file_not_available, Toast.LENGTH_LONG).show() + return + } + + val fileUri = DocumentsContract.buildDocumentUri( + DocumentsProvider.AUTHORITY, + DocumentsProvider.ROOT_ID + "/$logFileName" + ) + + val documentFile = DocumentFile.fromSingleUri(context, fileUri) ?: return + + val intent = Intent(Intent.ACTION_SEND) + .setDataAndType(documentFile.uri, "text/plain") + .addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + .putExtra(Intent.EXTRA_STREAM, documentFile.uri) + + context.startActivity(Intent.createChooser(intent, null)) +} + private fun openCemuFolder(context: Context) { try { - Intent(Intent.ACTION_VIEW).apply { - addCategory(Intent.CATEGORY_DEFAULT) - data = DocumentsContract.buildRootUri( - DocumentsProvider.AUTHORITY, - DocumentsProvider.ROOT_ID - ) - addFlags( + val intent = Intent(Intent.ACTION_VIEW) + .addCategory(Intent.CATEGORY_DEFAULT) + .addFlags( Intent.FLAG_GRANT_PERSISTABLE_URI_PERMISSION or Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION or Intent.FLAG_GRANT_WRITE_URI_PERMISSION ) - context.startActivity(this@apply) - } + intent.data = DocumentsContract.buildRootUri( + DocumentsProvider.AUTHORITY, + DocumentsProvider.ROOT_ID + ) + context.startActivity(intent) } catch (activityNotFoundException: ActivityNotFoundException) { Toast.makeText(context, R.string.failed_to_open_cemu_folder, Toast.LENGTH_LONG).show() } diff --git a/src/android/app/src/main/java/info/cemu/cemu/emulation/EmulationActivity.kt b/src/android/app/src/main/java/info/cemu/cemu/emulation/EmulationActivity.kt index 0b8468b4..ded35356 100644 --- a/src/android/app/src/main/java/info/cemu/cemu/emulation/EmulationActivity.kt +++ b/src/android/app/src/main/java/info/cemu/cemu/emulation/EmulationActivity.kt @@ -12,6 +12,7 @@ import android.view.SurfaceHolder import android.view.SurfaceView import android.view.View import android.view.ViewGroup +import android.view.WindowManager import android.widget.LinearLayout import android.widget.Toast import androidx.activity.OnBackPressedCallback @@ -119,6 +120,9 @@ class EmulationActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + + window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON) + emulationActivityInstance = WeakReference(this) overlaySettings = InputOverlaySettingsManager(this).overlaySettings @@ -189,7 +193,9 @@ class EmulationActivity : AppCompatActivity() { } } - private fun LayoutSideMenuEmulationBinding.configureSideMenu(isInputOverlayEnabled: Boolean) { + private fun LayoutSideMenuEmulationBinding.configureSideMenu() { + val isInputOverlayEnabled = overlaySettings.isOverlayEnabled + enableMotionCheckbox.configure(onCheckChanged = ::setMotionEnabled) replaceTvWithPadCheckbox.configure(onCheckChanged = NativeEmulation::setReplaceTVWithPadView) showPadCheckbox.configure(onCheckChanged = ::setPadViewVisibility) @@ -217,7 +223,9 @@ class EmulationActivity : AppCompatActivity() { binding = ActivityEmulationBinding.inflate(layoutInflater) inputOverlaySurfaceView = binding.inputOverlay - binding.sideMenu.configureSideMenu(overlaySettings.isOverlayEnabled) + inputOverlaySurfaceView.setVisible(overlaySettings.isOverlayEnabled) + + binding.sideMenu.configureSideMenu() binding.moveInputsButton.setOnClickListener { _ -> if (inputOverlaySurfaceView.getInputMode() == InputOverlaySurfaceView.InputMode.EDIT_POSITION) { @@ -416,6 +424,7 @@ class EmulationActivity : AppCompatActivity() { } val parentTextInputLayout = inputEditTextLayout.requireViewById(R.id.emulation_input_layout) + if (maxLength > 0) { parentTextInputLayout.isCounterEnabled = true parentTextInputLayout.counterMaxLength = maxLength @@ -423,6 +432,7 @@ class EmulationActivity : AppCompatActivity() { } else { parentTextInputLayout.isCounterEnabled = false } + emulationActivity.emulationTextInputDialog = dialog } } diff --git a/src/android/app/src/main/java/info/cemu/cemu/settings/graphics/GraphicsSettingsScreen.kt b/src/android/app/src/main/java/info/cemu/cemu/settings/graphics/GraphicsSettingsScreen.kt index 41d21f09..403b6d76 100644 --- a/src/android/app/src/main/java/info/cemu/cemu/settings/graphics/GraphicsSettingsScreen.kt +++ b/src/android/app/src/main/java/info/cemu/cemu/settings/graphics/GraphicsSettingsScreen.kt @@ -30,12 +30,12 @@ fun GraphicsSettingsScreen(navigateBack: () -> Unit, goToCustomDriversSettings: appBarText = stringResource(R.string.general_settings), navigateBack = navigateBack, ) { -// if (supportsLoadingCustomDrivers) { -// Button( -// label = stringResource(R.string.custom_drivers), -// onClick = goToCustomDriversSettings -// ) -// } + if (supportsLoadingCustomDrivers) { + Button( + label = stringResource(R.string.custom_drivers), + onClick = goToCustomDriversSettings + ) + } Toggle( label = stringResource(R.string.async_shader_compile), description = stringResource(R.string.async_shader_compile_description), diff --git a/src/android/app/src/main/res/values/strings.xml b/src/android/app/src/main/res/values/strings.xml index 5ba96cfa..e93f8393 100644 --- a/src/android/app/src/main/res/values/strings.xml +++ b/src/android/app/src/main/res/values/strings.xml @@ -337,4 +337,6 @@ Select a controller Side menu button Show the emulation side menu button + Log file doesn\'t exist + Share log file \ No newline at end of file