Add DSi support

This commit is contained in:
Rafael Caetano 2021-01-05 21:40:34 +00:00
parent 9375033c0d
commit 9d913e56e9
19 changed files with 298 additions and 63 deletions

View File

@ -23,4 +23,5 @@
-keepclassmembers enum * { *; }
-keep class me.magnum.melonds.domain.model.RendererConfiguration { *; }
-keep class me.magnum.melonds.domain.model.EmulatorConfiguration { *; }
-keep class me.magnum.melonds.domain.model.EmulatorConfiguration { *; }
-keep class me.magnum.melonds.domain.model.ConsoleType { *; }

View File

@ -25,17 +25,24 @@ JNIEXPORT void JNICALL
Java_me_magnum_melonds_MelonEmulator_setupEmulator(JNIEnv* env, jclass type, jobject emulatorConfiguration, jobject javaAssetManager)
{
jclass emulatorConfigurationClass = env->GetObjectClass(emulatorConfiguration);
jstring configDir = (jstring) env->GetObjectField(emulatorConfiguration, env->GetFieldID(emulatorConfigurationClass, "configDirectory", "Ljava/lang/String;"));
jclass consoleTypeEnumClass = env->FindClass("me/magnum/melonds/domain/model/ConsoleType");
jstring dsConfigDir = (jstring) env->GetObjectField(emulatorConfiguration, env->GetFieldID(emulatorConfigurationClass, "dsConfigDirectory", "Ljava/lang/String;"));
jstring dsiConfigDir = (jstring) env->GetObjectField(emulatorConfiguration, env->GetFieldID(emulatorConfigurationClass, "dsiConfigDirectory", "Ljava/lang/String;"));
jboolean useJit = env->GetBooleanField(emulatorConfiguration, env->GetFieldID(emulatorConfigurationClass, "useJit", "Z"));
const char* dir = env->GetStringUTFChars(configDir, JNI_FALSE);
jobject consoleTypeEnum = env->GetObjectField(emulatorConfiguration, env->GetFieldID(emulatorConfigurationClass, "consoleType", "Lme/magnum/melonds/domain/model/ConsoleType;"));
jint consoleType = env->GetIntField(consoleTypeEnum, env->GetFieldID(consoleTypeEnumClass, "consoleType", "I"));
const char* dsDir = env->GetStringUTFChars(dsConfigDir, JNI_FALSE);
const char* dsiDir = env->GetStringUTFChars(dsiConfigDir, JNI_FALSE);
jobject rendererConfigurationObject = env->GetObjectField(emulatorConfiguration, env->GetFieldID(emulatorConfigurationClass, "rendererConfiguration", "Lme/magnum/melonds/domain/model/RendererConfiguration;"));
jobject globalAssetManager = env->NewGlobalRef(javaAssetManager);
AAssetManager* assetManager = AAssetManager_fromJava(env, globalAssetManager);
MelonDSAndroid::EmulatorConfiguration finalEmulatorConfiguration;
finalEmulatorConfiguration.configDir = const_cast<char*>(dir);
finalEmulatorConfiguration.dsConfigDir = const_cast<char*>(dsDir);
finalEmulatorConfiguration.dsiConfigDir = const_cast<char*>(dsiDir);
finalEmulatorConfiguration.useJit = useJit;
finalEmulatorConfiguration.consoleType = consoleType;
finalEmulatorConfiguration.renderSettings = buildRenderSettings(env, rendererConfigurationObject);
MelonDSAndroid::setup(finalEmulatorConfiguration, assetManager);
}
@ -218,7 +225,7 @@ void* emulate(void*)
if (frameLimitError < -frameRate)
frameLimitError = -frameRate;
if (frameLimitError > frameRate)
frameLimitError =frameRate;
frameLimitError = frameRate;
if (round(frameLimitError) > 0.0)
{

View File

@ -2,13 +2,16 @@ package me.magnum.melonds.di
import android.content.Context
import android.content.SharedPreferences
import android.net.Uri
import androidx.preference.PreferenceManager
import com.google.gson.Gson
import com.google.gson.GsonBuilder
import dagger.Module
import dagger.Provides
import dagger.hilt.InstallIn
import dagger.hilt.android.components.ApplicationComponent
import dagger.hilt.android.qualifiers.ApplicationContext
import me.magnum.melonds.utils.UriTypeHierarchyAdapter
import javax.inject.Singleton
@Module
@ -25,6 +28,8 @@ object AppModule {
@Provides
@Singleton
fun provideGson(): Gson {
return Gson()
return GsonBuilder()
.registerTypeHierarchyAdapter(Uri::class.java, UriTypeHierarchyAdapter())
.create()
}
}

View File

@ -0,0 +1,16 @@
package me.magnum.melonds.domain.model
enum class ConsoleType(val consoleType: Int) {
DS(0),
DSi(1);
companion object {
fun valueOfIgnoreCase(value: String): ConsoleType {
values().forEach {
if (it.name.equals(value, true))
return it
}
throw IllegalArgumentException("Value $value does not represent an enum entry")
}
}
}

View File

@ -1,3 +1,9 @@
package me.magnum.melonds.domain.model
data class EmulatorConfiguration(val configDirectory: String, val useJit: Boolean, val rendererConfiguration: RendererConfiguration)
data class EmulatorConfiguration(
val dsConfigDirectory: String,
val dsiConfigDirectory: String,
val useJit: Boolean,
val consoleType: ConsoleType,
val rendererConfiguration: RendererConfiguration
)

View File

@ -2,7 +2,7 @@ package me.magnum.melonds.domain.model
import android.net.Uri
data class RomConfig(private var loadGbaCart: Boolean = false, var gbaCartPath: Uri? = null, var gbaSavePath: Uri? = null) {
data class RomConfig(var runtimeConsoleType: RuntimeConsoleType = RuntimeConsoleType.DEFAULT, private var loadGbaCart: Boolean = false, var gbaCartPath: Uri? = null, var gbaSavePath: Uri? = null) {
fun loadGbaCart(): Boolean {
return loadGbaCart
}

View File

@ -0,0 +1,7 @@
package me.magnum.melonds.domain.model
enum class RuntimeConsoleType(val targetConsoleType: ConsoleType?) {
DEFAULT(null),
DS(ConsoleType.DS),
DSi(ConsoleType.DSi)
}

View File

@ -12,7 +12,9 @@ interface SettingsRepository {
fun getRomSearchDirectories(): Array<Uri>
fun getBiosDirectory(): Uri?
fun getDefaultConsoleType(): ConsoleType
fun getDsBiosDirectory(): Uri?
fun getDsiBiosDirectory(): Uri?
fun showBootScreen(): Boolean
fun isJitEnabled(): Boolean
@ -32,7 +34,8 @@ interface SettingsRepository {
fun observeTheme(): Observable<Theme>
fun observeRomSearchDirectories(): Observable<Array<Uri>>
fun setBiosDirectory(directoryUri: Uri)
fun setDsBiosDirectory(directoryUri: Uri)
fun setDsiBiosDirectory(directoryUri: Uri)
fun addRomSearchDirectory(directoryUri: Uri)
fun setControllerConfiguration(controllerConfiguration: ControllerConfiguration)
fun setRomSortingMode(sortingMode: SortingMode)

View File

@ -41,14 +41,24 @@ class SharedPreferencesSettingsRepository(private val context: Context, private
}
override fun getEmulatorConfiguration(): EmulatorConfiguration {
val biosDirUri = getBiosDirectory() ?: throw IllegalStateException("BIOS directory not set")
val biosDirPath = FileUtils.getAbsolutePathFromSAFUri(context, biosDirUri)
val consoleType = getDefaultConsoleType()
val dsBiosDirUri = getDsBiosDirectory()
val dsiBiosDirUri = getDsiBiosDirectory()
val configDirectoryPath = "$biosDirPath/"
// Ensure all BIOS dirs are set. DSi requires both dirs to be set
if (dsBiosDirUri == null || (consoleType == ConsoleType.DSi && dsiBiosDirUri == null))
throw IllegalStateException("BIOS directory not set")
val dsBiosDirPath = FileUtils.getAbsolutePathFromSAFUri(context, dsBiosDirUri)
val dsiBiosDirPath = FileUtils.getAbsolutePathFromSAFUri(context, dsiBiosDirUri)
val dsConfigDirectoryPath = "$dsBiosDirPath/"
val dsiConfigDirectoryPath = "$dsiBiosDirPath/"
return EmulatorConfiguration(
configDirectoryPath,
dsConfigDirectoryPath,
dsiConfigDirectoryPath,
isJitEnabled(),
consoleType,
RendererConfiguration(
getVideoFiltering(),
isThreadedRenderingEnabled()
@ -66,11 +76,21 @@ class SharedPreferencesSettingsRepository(private val context: Context, private
return dirPreference?.map { Uri.parse(it) }?.toTypedArray() ?: emptyArray()
}
override fun getBiosDirectory(): Uri? {
override fun getDefaultConsoleType(): ConsoleType {
val consoleTypePreference = preferences.getString("console_type", "ds")!!
return ConsoleType.valueOfIgnoreCase(consoleTypePreference)
}
override fun getDsBiosDirectory(): Uri? {
val dirPreference = preferences.getStringSet("bios_dir", null)?.firstOrNull()
return dirPreference?.let { Uri.parse(it) }
}
override fun getDsiBiosDirectory(): Uri? {
val dirPreference = preferences.getStringSet("dsi_bios_dir", null)?.firstOrNull()
return dirPreference?.let { Uri.parse(it) }
}
override fun showBootScreen(): Boolean {
return preferences.getBoolean("show_bios", false)
}
@ -169,12 +189,18 @@ class SharedPreferencesSettingsRepository(private val context: Context, private
}
}
override fun setBiosDirectory(directoryUri: Uri) {
override fun setDsBiosDirectory(directoryUri: Uri) {
preferences.edit {
putStringSet("bios_dir", setOf(directoryUri.toString()))
}
}
override fun setDsiBiosDirectory(directoryUri: Uri) {
preferences.edit {
putStringSet("dsi_bios_dir", setOf(directoryUri.toString()))
}
}
override fun addRomSearchDirectory(directoryUri: Uri) {
preferences.edit {
putStringSet("rom_search_dirs", setOf(directoryUri.toString()))

View File

@ -5,10 +5,7 @@ import androidx.documentfile.provider.DocumentFile
import androidx.hilt.lifecycle.ViewModelInject
import androidx.lifecycle.ViewModel
import io.reactivex.Single
import me.magnum.melonds.domain.model.EmulatorConfiguration
import me.magnum.melonds.domain.model.Rom
import me.magnum.melonds.domain.model.RomConfig
import me.magnum.melonds.domain.model.SaveStateSlot
import me.magnum.melonds.domain.model.*
import me.magnum.melonds.domain.repositories.RomsRepository
import me.magnum.melonds.domain.repositories.SettingsRepository
import me.magnum.melonds.utils.FileUtils

View File

@ -4,7 +4,6 @@ import android.Manifest
import android.app.SearchManager
import android.content.Intent
import android.content.pm.PackageManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.Menu
@ -18,15 +17,14 @@ import androidx.core.content.ContextCompat
import androidx.lifecycle.Observer
import dagger.hilt.android.AndroidEntryPoint
import me.magnum.melonds.R
import me.magnum.melonds.domain.model.ConsoleType
import me.magnum.melonds.domain.model.Rom
import me.magnum.melonds.domain.model.SortingMode
import me.magnum.melonds.domain.repositories.SettingsRepository
import me.magnum.melonds.parcelables.RomParcelable
import me.magnum.melonds.ui.settings.SettingsActivity
import me.magnum.melonds.ui.emulator.EmulatorActivity
import me.magnum.melonds.ui.settings.SettingsActivity
import me.magnum.melonds.utils.ConfigurationUtils
import me.magnum.melonds.utils.DirectoryPickerContract
import javax.inject.Inject
@AndroidEntryPoint
class RomListActivity : AppCompatActivity() {
@ -38,11 +36,21 @@ class RomListActivity : AppCompatActivity() {
}
private val viewModel: RomListViewModel by viewModels()
@Inject lateinit var settingsRepository: SettingsRepository
private val biosPickerLauncher by lazy { registerForActivityResult(DirectoryPickerContract()) {
if (checkConfigDirectorySetup(it)) {
settingsRepository.setBiosDirectory(it!!)
private val dsBiosPickerLauncher by lazy { registerForActivityResult(DirectoryPickerContract()) { uri ->
if (uri != null) {
viewModel.setDsBiosDirectory(uri)
val currentRom = selectedRom
if (currentRom != null)
loadRom(currentRom)
else
checkConfigDirectorySetup()
}
} }
private val dsiBiosPickerLauncher by lazy { registerForActivityResult(DirectoryPickerContract()) { uri ->
if (uri != null) {
viewModel.setDsiBiosDirectory(uri)
selectedRom?.let { loadRom(it) }
}
} }
@ -141,20 +149,19 @@ class RomListActivity : AppCompatActivity() {
Toast.makeText(this, getString(R.string.info_no_storage_permission), Toast.LENGTH_LONG).show()
}
private fun checkConfigDirectorySetup(checkDirectory: Uri? = null): Boolean {
val configDir = checkDirectory ?: settingsRepository.getBiosDirectory()
when (ConfigurationUtils.checkConfigurationDirectory(this, configDir)) {
private fun checkConfigDirectorySetup(): Boolean {
when (viewModel.getDsConfigurationDirStatus()) {
ConfigurationUtils.ConfigurationDirStatus.VALID -> return true
ConfigurationUtils.ConfigurationDirStatus.UNSET -> AlertDialog.Builder(this)
.setTitle(R.string.bios_dir_not_set)
.setMessage(R.string.bios_dir_not_set_info)
.setPositiveButton(R.string.ok) { _, _ -> biosPickerLauncher.launch(null) }
.setTitle(R.string.ds_bios_dir_not_set)
.setMessage(R.string.ds_bios_dir_not_set_info)
.setPositiveButton(R.string.ok) { _, _ -> dsBiosPickerLauncher.launch(null) }
.setCancelable(false)
.show()
ConfigurationUtils.ConfigurationDirStatus.INVALID -> AlertDialog.Builder(this)
.setTitle(R.string.incorrect_bios_dir)
.setMessage(R.string.incorrect_bios_dir_info)
.setPositiveButton(R.string.ok) { _, _ -> biosPickerLauncher.launch(null) }
.setMessage(R.string.ds_incorrect_bios_dir_info)
.setPositiveButton(R.string.ok) { _, _ -> dsBiosPickerLauncher.launch(null) }
.setCancelable(false)
.show()
}
@ -202,13 +209,58 @@ class RomListActivity : AppCompatActivity() {
}
private fun loadRom(rom: Rom) {
if (isStoragePermissionGranted()) {
val intent = Intent(this, EmulatorActivity::class.java)
intent.putExtra(EmulatorActivity.KEY_ROM, RomParcelable(rom))
startActivity(intent)
} else {
if (!isStoragePermissionGranted()) {
selectedRom = rom
requestStoragePermission(false)
} else {
val configurationDirStatus = viewModel.getRomConfigurationDirStatus(rom)
if (configurationDirStatus == ConfigurationUtils.ConfigurationDirStatus.VALID) {
val intent = Intent(this, EmulatorActivity::class.java)
intent.putExtra(EmulatorActivity.KEY_ROM, RomParcelable(rom))
startActivity(intent)
} else {
selectedRom = rom
when (viewModel.getRomTargetConsoleType(rom)) {
ConsoleType.DS -> {
val titleRes: Int
val messageRes: Int
if (configurationDirStatus == ConfigurationUtils.ConfigurationDirStatus.UNSET) {
titleRes = R.string.ds_bios_dir_not_set
messageRes = R.string.ds_bios_dir_not_set_info
} else {
titleRes = R.string.incorrect_bios_dir
messageRes = R.string.ds_incorrect_bios_dir_info
}
AlertDialog.Builder(this)
.setTitle(titleRes)
.setMessage(messageRes)
.setPositiveButton(R.string.ok) { _, _ -> dsBiosPickerLauncher.launch(null) }
.setNegativeButton(R.string.cancel, null)
.setCancelable(true)
.show()
}
ConsoleType.DSi -> {
val titleRes: Int
val messageRes: Int
if (configurationDirStatus == ConfigurationUtils.ConfigurationDirStatus.UNSET) {
titleRes = R.string.dsi_bios_dir_not_set
messageRes = R.string.dsi_bios_dir_not_set_info
} else {
titleRes = R.string.incorrect_bios_dir
messageRes = R.string.dsi_incorrect_bios_dir_info
}
AlertDialog.Builder(this)
.setTitle(titleRes)
.setMessage(messageRes)
.setPositiveButton(R.string.ok) { _, _ -> dsiBiosPickerLauncher.launch(null) }
.setNegativeButton(R.string.cancel, null)
.setCancelable(true)
.show()
}
}
}
}
}
}

View File

@ -13,6 +13,7 @@ import me.magnum.melonds.domain.model.*
import me.magnum.melonds.domain.repositories.RomsRepository
import me.magnum.melonds.domain.repositories.SettingsRepository
import me.magnum.melonds.extensions.addTo
import me.magnum.melonds.utils.ConfigurationUtils
import java.text.Normalizer
import java.util.*
@ -116,10 +117,35 @@ class RomListViewModel @ViewModelInject constructor(private val context: Context
romsLiveData.value = romsLiveData.value
}
fun getRomTargetConsoleType(rom: Rom): ConsoleType {
return rom.config.runtimeConsoleType.targetConsoleType ?: settingsRepository.getDefaultConsoleType()
}
fun getDsConfigurationDirStatus(): ConfigurationUtils.ConfigurationDirStatus {
return ConfigurationUtils.checkConfigurationDirectory(context, settingsRepository.getDsBiosDirectory(), ConsoleType.DS)
}
fun getRomConfigurationDirStatus(rom: Rom): ConfigurationUtils.ConfigurationDirStatus {
val romTargetConsoleType = getRomTargetConsoleType(rom)
val romTargetConfigurationDir = when(romTargetConsoleType) {
ConsoleType.DS -> settingsRepository.getDsBiosDirectory()
ConsoleType.DSi -> settingsRepository.getDsiBiosDirectory()
}
return ConfigurationUtils.checkConfigurationDirectory(context, romTargetConfigurationDir, romTargetConsoleType)
}
fun addRomSearchDirectory(directoryUri: Uri) {
settingsRepository.addRomSearchDirectory(directoryUri)
}
fun setDsBiosDirectory(uri: Uri) {
settingsRepository.setDsBiosDirectory(uri)
}
fun setDsiBiosDirectory(uri: Uri) {
settingsRepository.setDsiBiosDirectory(uri)
}
private fun buildAlphabeticalRomComparator(): Comparator<Rom> {
return if (sortingOrder == SortingOrder.ASCENDING) {
Comparator { o1: Rom, o2: Rom ->

View File

@ -4,11 +4,14 @@ import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.view.MenuItem
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.preference.*
import dagger.hilt.android.AndroidEntryPoint
import me.magnum.melonds.R
import me.magnum.melonds.domain.model.ConsoleType
import me.magnum.melonds.preferences.DirectoryPickerPreference
import me.magnum.melonds.utils.ConfigurationUtils
import me.magnum.melonds.utils.DirectoryPickerContract
import me.magnum.melonds.utils.FileUtils
@ -99,15 +102,19 @@ class SettingsActivity : AppCompatActivity() {
override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
setPreferencesFromResource(R.xml.pref_main, rootKey)
val romDirsPreference = findPreference<DirectoryPickerPreference>("rom_search_dirs")!!
val biosDirPreference = findPreference<DirectoryPickerPreference>("bios_dir")!!
val consoleTypePreference = findPreference<ListPreference>("console_type")!!
val dsBiosDirPreference = findPreference<DirectoryPickerPreference>("bios_dir")!!
val dsiBiosDirPreference = findPreference<DirectoryPickerPreference>("dsi_bios_dir")!!
val sramDirPreference = findPreference<DirectoryPickerPreference>("sram_dir")!!
val jitPreference = findPreference<SwitchPreference>("enable_jit")!!
bindPreferenceSummaryToValue(romDirsPreference)
bindPreferenceSummaryToValue(biosDirPreference)
bindPreferenceSummaryToValue(dsBiosDirPreference)
bindPreferenceSummaryToValue(dsiBiosDirPreference)
bindPreferenceSummaryToValue(sramDirPreference)
val romPickerLauncher = registerForActivityResult(DirectoryPickerContract(), romDirsPreference::onDirectoryPicked)
val biosPickerLauncher = registerForActivityResult(DirectoryPickerContract(), biosDirPreference::onDirectoryPicked)
val dsBiosPickerLauncher = registerForActivityResult(DirectoryPickerContract(), dsBiosDirPreference::onDirectoryPicked)
val dsiBiosPickerLauncher = registerForActivityResult(DirectoryPickerContract(), dsiBiosDirPreference::onDirectoryPicked)
val sramPickerLauncher = registerForActivityResult(DirectoryPickerContract(), sramDirPreference::onDirectoryPicked)
if (Build.SUPPORTED_64_BIT_ABIS.isEmpty()) {
@ -116,16 +123,42 @@ class SettingsActivity : AppCompatActivity() {
jitPreference.setSummary(R.string.jit_not_supported)
}
romDirsPreference.setOnPreferenceClickListener {
romPickerLauncher.launch(null)
consoleTypePreference.setOnPreferenceChangeListener { _, newValue ->
val consoleTypePreferenceValue = newValue as String
val newConsoleType = ConsoleType.valueOfIgnoreCase(consoleTypePreferenceValue)
val newTypeBiosDir = when(newConsoleType) {
ConsoleType.DS -> dsBiosDirPreference.getPersistedStringSet(null)?.firstOrNull()?.let { Uri.parse(it) }
ConsoleType.DSi -> dsiBiosDirPreference.getPersistedStringSet(null)?.firstOrNull()?.let { Uri.parse(it) }
}
if (ConfigurationUtils.checkConfigurationDirectory(requireContext(), newTypeBiosDir, newConsoleType) != ConfigurationUtils.ConfigurationDirStatus.VALID) {
val textRes = when(newConsoleType) {
ConsoleType.DS -> R.string.ds_incorrect_bios_dir_info
ConsoleType.DSi -> R.string.dsi_incorrect_bios_dir_info
}
AlertDialog.Builder(requireContext())
.setMessage(textRes)
.setPositiveButton(R.string.ok, null)
.show()
}
true
}
biosDirPreference.setOnPreferenceClickListener {
biosPickerLauncher.launch(null)
romDirsPreference.setOnPreferenceClickListener { preference ->
romPickerLauncher.launch(preference.getPersistedStringSet(null)?.firstOrNull()?.let { Uri.parse(it) })
true
}
sramDirPreference.setOnPreferenceClickListener {
sramPickerLauncher.launch(null)
dsBiosDirPreference.setOnPreferenceClickListener { preference ->
dsBiosPickerLauncher.launch(preference.getPersistedStringSet(null)?.firstOrNull()?.let { Uri.parse(it) })
true
}
dsiBiosDirPreference.setOnPreferenceClickListener { preference ->
dsiBiosPickerLauncher.launch(preference.getPersistedStringSet(null)?.firstOrNull()?.let { Uri.parse(it) })
true
}
sramDirPreference.setOnPreferenceClickListener { preference ->
sramPickerLauncher.launch(preference.getPersistedStringSet(null)?.firstOrNull()?.let { Uri.parse(it) })
true
}
}

View File

@ -3,6 +3,7 @@ package me.magnum.melonds.utils
import android.content.Context
import android.net.Uri
import androidx.documentfile.provider.DocumentFile
import me.magnum.melonds.domain.model.ConsoleType
import me.magnum.melonds.utils.FileUtils.getAbsolutePathFromSAFUri
import java.io.File
@ -12,7 +13,7 @@ object ConfigurationUtils {
}
@JvmStatic
fun checkConfigurationDirectory(context: Context, configurationDir: Uri?): ConfigurationDirStatus {
fun checkConfigurationDirectory(context: Context, configurationDir: Uri?, consoleType: ConsoleType): ConfigurationDirStatus {
if (configurationDir == null)
return ConfigurationDirStatus.UNSET
@ -21,13 +22,23 @@ object ConfigurationUtils {
if (!dir.isDirectory)
return ConfigurationDirStatus.INVALID
val bios7File = DocumentFile.fromFile(File(dir, "bios7.bin"))
val bios9File = DocumentFile.fromFile(File(dir, "bios9.bin"))
val firmwareFile = DocumentFile.fromFile(File(dir, "firmware.bin"))
val requiredFiles = when(consoleType) {
ConsoleType.DS -> listOf(
DocumentFile.fromFile(File(dir, "bios7.bin")),
DocumentFile.fromFile(File(dir, "bios9.bin")),
DocumentFile.fromFile(File(dir, "firmware.bin"))
)
ConsoleType.DSi -> listOf(
DocumentFile.fromFile(File(dir, "bios7.bin")),
DocumentFile.fromFile(File(dir, "bios9.bin")),
DocumentFile.fromFile(File(dir, "firmware.bin")),
DocumentFile.fromFile(File(dir, "nand.bin"))
)
}
return if (!bios7File.isFile || !bios9File.isFile || !firmwareFile.isFile)
ConfigurationDirStatus.INVALID
else
return if (requiredFiles.all { it.isFile })
ConfigurationDirStatus.VALID
else
ConfigurationDirStatus.INVALID
}
}

View File

@ -0,0 +1,18 @@
package me.magnum.melonds.utils
import android.net.Uri
import com.google.gson.*
import java.lang.reflect.Type
import kotlin.jvm.Throws
class UriTypeHierarchyAdapter : JsonDeserializer<Uri?>, JsonSerializer<Uri?> {
@Throws(JsonParseException::class)
override fun deserialize(json: JsonElement, typeOfT: Type?, context: JsonDeserializationContext?): Uri {
return Uri.parse(json.asString)
}
override fun serialize(src: Uri?, typeOfSrc: Type?, context: JsonSerializationContext?): JsonElement {
return JsonPrimitive(src.toString())
}
}

View File

@ -1,5 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string-array name="console_type_values">
<item>ds</item>
<item>dsi</item>
</string-array>
<string-array name="video_filtering_values">
<item>none</item>
<item>linear</item>

View File

@ -23,12 +23,15 @@
<string name="action_sort_alphabetically">Alphabetically</string>
<string name="action_sort_recently_played">Recently played</string>
<string name="bios_dir_not_set">BIOS directory not set</string>
<string name="bios_dir_not_set_info">BIOS directory is not set. Go to the Settings and select the directory that contains bios7.bin, bios9.bin and firmware.bin</string>
<string name="ds_bios_dir_not_set">DS BIOS directory not set</string>
<string name="ds_bios_dir_not_set_info">DS BIOS directory is not set. Select the directory that contains bios7.bin, bios9.bin and firmware.bin</string>
<string name="dsi_bios_dir_not_set">DSi BIOS directory not set</string>
<string name="dsi_bios_dir_not_set_info">DSi BIOS directory is not set. Select the directory that contains bios7.bin, bios9.bin, firmware.bin and nand.bin</string>
<string name="incorrect_bios_dir">Incorrect BIOS directory</string>
<string name="incorrect_bios_dir_info">The BIOS directory that you specified is not correct. Make sure that the selected directory contains bios7.bin, bios9.bin and firmware.bin</string>
<string name="ds_incorrect_bios_dir_info">The BIOS directory for the DS system is not correct. Make sure that the selected directory contains bios7.bin, bios9.bin and firmware.bin</string>
<string name="dsi_incorrect_bios_dir_info">The BIOS directory for the DSi system is not correct. Make sure that you select a directory that contains bios7.bin, bios9.bin, firmware.bin and nand.bin</string>
<string name="storage_permission_required">Storage permission required</string>
<string name="storage_permission_required_info">Storage permission is required to load ROMs on your device. Please grant access to storage on the next dialog.</string>
<string name="storage_permission_required_info">Storage permission is required to load ROMs from your device. Please grant access to storage on the next dialog.</string>
<string name="no_rom_search_directory_specified">No ROM search directory specified</string>
<string name="set_rom_directory">Set ROM directory</string>
<string name="info_no_storage_permission">Cannot load ROM without storage permission</string>
@ -49,7 +52,9 @@
<string name="category_system">System</string>
<string name="theme">Theme</string>
<string name="rom_search_directories">Search directories</string>
<string name="bios_directory">BIOS directory</string>
<string name="console_type">Default system</string>
<string name="bios_directory">DS BIOS directory</string>
<string name="dsi_bios_directory">DSi BIOS directory</string>
<string name="show_boot_screen">Show boot screen</string>
<string name="enable_jit">Enable JIT</string>
<string name="enable_jit_summary">Improves performance but may cause freezes or crashes</string>
@ -96,6 +101,11 @@
<item>@string/theme_option_dark</item>
</string-array>
<string-array name="console_type_options">
<item>DS</item>
<item>DSi (Experimental)</item>
</string-array>
<string-array name="video_filtering_options">
<item>None</item>
<item>Linear</item>

View File

@ -27,10 +27,22 @@
<PreferenceCategory
android:title="@string/category_system">
<ListPreference
android:key="console_type"
android:title="@string/console_type"
android:summary="%s"
android:entries="@array/console_type_options"
android:entryValues="@array/console_type_values"
android:defaultValue="ds" />
<me.magnum.melonds.preferences.DirectoryPickerPreference
android:key="bios_dir"
android:title="@string/bios_directory" />
<me.magnum.melonds.preferences.DirectoryPickerPreference
android:key="dsi_bios_dir"
android:title="@string/dsi_bios_directory" />
<SwitchPreference
android:key="show_bios"
android:title="@string/show_boot_screen"

@ -1 +1 @@
Subproject commit d5c53e4292eeef5e4d62c6b5038cfdf0b16c22f0
Subproject commit dc127a33d2642c5ea03e2ab02b5a1ed53d5a3f80