chore: Make firmware optional rather than required

This commit makes firmware non-mandatory for the emulator to function. Changes include:
- Converting firmware errors to warnings in loader
- Removing firmware requirement checks in Android
- Removing firmware and title.keys setup screens
- Adding --allow-unsupported flag for Android vcpkg
- Updating vcpkg baseline
- Enforce software keyboard in Android

Signed-off-by: Zephyron <zephyron@citron-emu.org>
This commit is contained in:
Zephyron 2025-04-30 15:25:57 +10:00
parent 65dfe3234f
commit 257aad2431
5 changed files with 11 additions and 125 deletions

View file

@ -164,7 +164,8 @@ endif()
if (CITRON_USE_BUNDLED_VCPKG) if (CITRON_USE_BUNDLED_VCPKG)
if (ANDROID) if (ANDROID)
set(ENV{ANDROID_NDK_HOME} "${ANDROID_NDK}") set(ENV{ANDROID_NDK_HOME} ${ANDROID_NDK})
set(VCPKG_ADDITIONAL_FLAGS "--allow-unsupported")
list(APPEND VCPKG_MANIFEST_FEATURES "android") list(APPEND VCPKG_MANIFEST_FEATURES "android")
if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a") if (CMAKE_ANDROID_ARCH_ABI STREQUAL "arm64-v8a")

View file

@ -83,19 +83,6 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
// Check if firmware is available
if (!NativeLibrary.isFirmwareAvailable()) {
AlertDialog.Builder(this)
.setTitle(R.string.firmware_missing_title)
.setMessage(R.string.firmware_missing_message)
.setPositiveButton(R.string.ok) { _, _ ->
finish()
}
.setCancelable(false)
.show()
return
}
// Add license verification at the start // Add license verification at the start
LicenseVerifier.verifyLicense(this) LicenseVerifier.verifyLicense(this)
@ -168,22 +155,13 @@ class EmulationActivity : AppCompatActivity(), SensorEventListener {
override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean { override fun onKeyDown(keyCode: Int, event: KeyEvent): Boolean {
if (event.action == KeyEvent.ACTION_DOWN) { if (event.action == KeyEvent.ACTION_DOWN) {
if (keyCode == KeyEvent.KEYCODE_ENTER) { val textChar = event.unicodeChar
// Special case, we do not support multiline input, dismiss the keyboard. if (textChar == 0) {
val overlayView: View = // No text, button input.
this.findViewById(R.id.surface_input_overlay) NativeLibrary.submitInlineKeyboardInput(keyCode)
val im =
overlayView.context.getSystemService(INPUT_METHOD_SERVICE) as InputMethodManager
im.hideSoftInputFromWindow(overlayView.windowToken, 0)
} else { } else {
val textChar = event.unicodeChar // Text submitted.
if (textChar == 0) { NativeLibrary.submitInlineKeyboardText(textChar.toChar().toString())
// No text, button input.
NativeLibrary.submitInlineKeyboardInput(keyCode)
} else {
// Text submitted.
NativeLibrary.submitInlineKeyboardText(textChar.toChar().toString())
}
} }
} }
return super.onKeyDown(keyCode, event) return super.onKeyDown(keyCode, event)

View file

@ -181,61 +181,6 @@ class SetupFragment : Fragment() {
) )
) )
// Add title.keys installation page
add(
SetupPage(
R.drawable.ic_key,
R.string.install_title_keys,
R.string.install_title_keys_description,
R.drawable.ic_add,
true,
R.string.select_keys,
{
titleKeyCallback = it
getTitleKey.launch(arrayOf("*/*"))
},
true,
R.string.install_title_keys_warning,
R.string.install_title_keys_warning_description,
R.string.install_title_keys_warning_help,
{
val file = File(DirectoryInitialization.userDirectory + "/keys/title.keys")
if (file.exists()) {
StepState.COMPLETE
} else {
StepState.INCOMPLETE
}
}
)
)
// Add firmware installation page (mandatory)
add(
SetupPage(
R.drawable.ic_key,
R.string.install_firmware,
R.string.install_firmware_description,
R.drawable.ic_add,
true,
R.string.select_firmware,
{
firmwareCallback = it
getFirmware.launch(arrayOf("application/zip"))
},
true,
R.string.install_firmware_warning,
R.string.install_firmware_warning_description,
R.string.install_firmware_warning_help,
{
if (NativeLibrary.isFirmwareAvailable()) {
StepState.COMPLETE
} else {
StepState.INCOMPLETE
}
}
)
)
add( add(
SetupPage( SetupPage(
R.drawable.ic_controller, R.drawable.ic_controller,
@ -324,18 +269,6 @@ class SetupFragment : Fragment() {
return@setOnClickListener return@setOnClickListener
} }
// Special handling for firmware page - don't allow skipping
if (currentPage.titleId == R.string.install_firmware && !NativeLibrary.isFirmwareAvailable()) {
SetupWarningDialogFragment.newInstance(
currentPage.warningTitleId,
currentPage.warningDescriptionId,
currentPage.warningHelpLinkId,
index,
allowSkip = false
).show(childFragmentManager, SetupWarningDialogFragment.TAG)
return@setOnClickListener
}
if (!hasBeenWarned[index]) { if (!hasBeenWarned[index]) {
SetupWarningDialogFragment.newInstance( SetupWarningDialogFragment.newInstance(
currentPage.warningTitleId, currentPage.warningTitleId,
@ -414,30 +347,6 @@ class SetupFragment : Fragment() {
} }
} }
private lateinit var titleKeyCallback: SetupCallback
val getTitleKey =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
mainActivity.processTitleKey(result)
titleKeyCallback.onStepCompleted()
}
}
private lateinit var firmwareCallback: SetupCallback
val getFirmware =
registerForActivityResult(ActivityResultContracts.OpenDocument()) { result ->
if (result != null) {
mainActivity.getFirmware.launch(arrayOf("application/zip"))
binding.root.postDelayed({
if (NativeLibrary.isFirmwareAvailable()) {
firmwareCallback.onStepCompleted()
}
}, 1000)
}
}
private lateinit var gamesDirCallback: SetupCallback private lateinit var gamesDirCallback: SetupCallback
val getGamesDirectory = val getGamesDirectory =

View file

@ -260,12 +260,10 @@ std::unique_ptr<AppLoader> GetLoader(Core::System& system, FileSys::VirtualFile
if (bis_system) { if (bis_system) {
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program); auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
if (!mii_applet_nca) { if (!mii_applet_nca) {
LOG_ERROR(Loader, "Firmware is required to launch games but is not available"); LOG_WARNING(Loader, "Firmware is not available. Some games may not function correctly.");
return nullptr;
} }
} else { } else {
LOG_ERROR(Loader, "System NAND contents not available"); LOG_WARNING(Loader, "System NAND contents not available");
return nullptr;
} }
FileType type = IdentifyFile(file); FileType type = IdentifyFile(file);

View file

@ -1,7 +1,7 @@
{ {
"$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json", "$schema": "https://raw.githubusercontent.com/microsoft/vcpkg-tool/main/docs/vcpkg.schema.json",
"name": "citron", "name": "citron",
"builtin-baseline": "bc994510d2eb11aac7b43b03f67a7751d5bfe0e4", "builtin-baseline": "c82f74667287d3dc386bce81e44964370c91a289",
"version": "1.0", "version": "1.0",
"dependencies": [ "dependencies": [
"boost-algorithm", "boost-algorithm",