summaryrefslogtreecommitdiff
path: root/Source/Android
diff options
context:
space:
mode:
authorJosJuice <josjuice@gmail.com>2023-08-25 21:04:34 +0200
committerGitHub <noreply@github.com>2023-08-25 21:04:34 +0200
commitb149ea51cfe44a2b64a8bc28593dc7b4fcf8e2c2 (patch)
treec497bafb5f99be9bc396b5634f25d0a4399ce324 /Source/Android
parent260bad74eac728c3c64a1a2e8b00efc7d9bede92 (diff)
parent6a19629fc6da96fc8fb7f65bae9c72ba4a08f7b0 (diff)
Merge pull request #11922 from t895/kotlin-model
Android: Convert "model" package to Kotlin
Diffstat (limited to 'Source/Android')
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.kt8
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.kt6
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.kt50
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt22
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.java78
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.kt69
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java139
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.kt152
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.java63
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.kt12
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java32
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.kt5
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt2
-rw-r--r--Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CoverHelper.kt6
-rw-r--r--Source/Android/jni/AndroidCommon/IDCache.cpp4
15 files changed, 291 insertions, 357 deletions
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.kt
index 103ba4a318..520c96d812 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameAdapter.kt
@@ -61,12 +61,12 @@ class GameAdapter(private val mActivity: FragmentActivity) : RecyclerView.Adapte
holder.apply {
if (BooleanSetting.MAIN_SHOW_GAME_TITLES.boolean) {
- binding.textGameTitle.text = gameFile.title
+ binding.textGameTitle.text = gameFile.getTitle()
binding.textGameTitle.visibility = View.VISIBLE
binding.textGameTitleInner.visibility = View.GONE
binding.textGameCaption.visibility = View.VISIBLE
} else {
- binding.textGameTitleInner.text = gameFile.title
+ binding.textGameTitleInner.text = gameFile.getTitle()
binding.textGameTitleInner.visibility = View.VISIBLE
binding.textGameTitle.visibility = View.GONE
binding.textGameCaption.visibility = View.GONE
@@ -94,9 +94,9 @@ class GameAdapter(private val mActivity: FragmentActivity) : RecyclerView.Adapte
holder.apply {
if (GameFileCacheManager.findSecondDisc(gameFile) != null) {
binding.textGameCaption.text =
- context.getString(R.string.disc_number, gameFile.discNumber + 1)
+ context.getString(R.string.disc_number, gameFile.getDiscNumber() + 1)
} else {
- binding.textGameCaption.text = gameFile.company
+ binding.textGameCaption.text = gameFile.getCompany()
}
holder.gameFile = gameFile
binding.root.onFocusChangeListener =
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.kt
index c23b4b3e14..b355dc8f6d 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/adapters/GameRowPresenter.kt
@@ -48,7 +48,7 @@ class GameRowPresenter(private val mActivity: FragmentActivity) : Presenter() {
holder.apply {
imageScreenshot.setImageDrawable(null)
- cardParent.titleText = gameFile.title
+ cardParent.titleText = gameFile.getTitle()
holder.gameFile = gameFile
// Set the background color of the card
@@ -64,9 +64,9 @@ class GameRowPresenter(private val mActivity: FragmentActivity) : Presenter() {
if (GameFileCacheManager.findSecondDisc(gameFile) != null) {
holder.cardParent.contentText =
- context.getString(R.string.disc_number, gameFile.discNumber + 1)
+ context.getString(R.string.disc_number, gameFile.getDiscNumber() + 1)
} else {
- holder.cardParent.contentText = gameFile.company
+ holder.cardParent.contentText = gameFile.getCompany()
}
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.kt
index 83d69ebbb4..53b1467bbc 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/dialogs/GameDetailsDialog.kt
@@ -25,8 +25,8 @@ class GameDetailsDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val gameFile = GameFileCacheManager.addOrGet(requireArguments().getString(ARG_GAME_PATH))
- val country = resources.getStringArray(R.array.countryNames)[gameFile.country]
- val fileSize = NativeLibrary.FormatSize(gameFile.fileSize, 2)
+ val country = resources.getStringArray(R.array.countryNames)[gameFile.getCountry()]
+ val fileSize = NativeLibrary.FormatSize(gameFile.getFileSize(), 2)
// TODO: Remove dialog_game_details_tv if we switch to an AppCompatActivity for leanback
val binding: DialogGameDetailsBinding
@@ -35,16 +35,16 @@ class GameDetailsDialog : DialogFragment() {
if (requireActivity() is AppCompatActivity) {
binding = DialogGameDetailsBinding.inflate(layoutInflater)
binding.apply {
- textGameTitle.text = gameFile.title
- textDescription.text = gameFile.description
- if (gameFile.description.isEmpty()) {
+ textGameTitle.text = gameFile.getTitle()
+ textDescription.text = gameFile.getDescription()
+ if (gameFile.getDescription().isEmpty()) {
textDescription.visibility = View.GONE
}
textCountry.text = country
- textCompany.text = gameFile.company
- textGameId.text = gameFile.gameId
- textRevision.text = gameFile.revision.toString()
+ textCompany.text = gameFile.getCompany()
+ textGameId.text = gameFile.getGameId()
+ textRevision.text = gameFile.getRevision().toString()
if (!gameFile.shouldShowFileFormatDetails()) {
labelFileFormat.setText(R.string.game_details_file_size)
@@ -55,19 +55,19 @@ class GameDetailsDialog : DialogFragment() {
labelBlockSize.visibility = View.GONE
textBlockSize.visibility = View.GONE
} else {
- val blockSize = gameFile.blockSize
- val compression = gameFile.compressionMethod
+ val blockSize = gameFile.getBlockSize()
+ val compression = gameFile.getCompressionMethod()
textFileFormat.text = resources.getString(
R.string.game_details_size_and_format,
- gameFile.fileFormatName,
+ gameFile.getFileFormatName(),
fileSize
)
if (compression.isEmpty()) {
textCompression.setText(R.string.game_details_no_compression)
} else {
- textCompression.text = gameFile.compressionMethod
+ textCompression.text = gameFile.getCompressionMethod()
}
if (blockSize > 0) {
@@ -87,16 +87,16 @@ class GameDetailsDialog : DialogFragment() {
} else {
tvBinding = DialogGameDetailsTvBinding.inflate(layoutInflater)
tvBinding.apply {
- textGameTitle.text = gameFile.title
- textDescription.text = gameFile.description
- if (gameFile.description.isEmpty()) {
+ textGameTitle.text = gameFile.getTitle()
+ textDescription.text = gameFile.getDescription()
+ if (gameFile.getDescription().isEmpty()) {
tvBinding.textDescription.visibility = View.GONE
}
textCountry.text = country
- textCompany.text = gameFile.company
- textGameId.text = gameFile.gameId
- textRevision.text = gameFile.revision.toString()
+ textCompany.text = gameFile.getCompany()
+ textGameId.text = gameFile.getGameId()
+ textRevision.text = gameFile.getRevision().toString()
if (!gameFile.shouldShowFileFormatDetails()) {
labelFileFormat.setText(R.string.game_details_file_size)
@@ -107,19 +107,19 @@ class GameDetailsDialog : DialogFragment() {
labelBlockSize.visibility = View.GONE
textBlockSize.visibility = View.GONE
} else {
- val blockSize = gameFile.blockSize
- val compression = gameFile.compressionMethod
+ val blockSize = gameFile.getBlockSize()
+ val compression = gameFile.getCompressionMethod()
textFileFormat.text = resources.getString(
R.string.game_details_size_and_format,
- gameFile.fileFormatName,
+ gameFile.getFileFormatName(),
fileSize
)
if (compression.isEmpty()) {
textCompression.setText(R.string.game_details_no_compression)
} else {
- textCompression.text = gameFile.compressionMethod
+ textCompression.text = gameFile.getCompressionMethod()
}
if (blockSize > 0) {
@@ -141,9 +141,9 @@ class GameDetailsDialog : DialogFragment() {
}
private suspend fun loadGameBanner(imageView: ImageView, gameFile: GameFile) {
- val vector = gameFile.banner
- val width = gameFile.bannerWidth
- val height = gameFile.bannerHeight
+ val vector = gameFile.getBanner()
+ val width = gameFile.getBannerWidth()
+ val height = gameFile.getBannerHeight()
imageView.scaleType = ImageView.ScaleType.FIT_CENTER
val request = ImageRequest.Builder(imageView.context)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt
index 01a5d97743..0f5760a210 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/fragments/ConvertFragment.kt
@@ -210,7 +210,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
R.array.convertFormatValues,
format
)
- if (gameFile.blobType == BLOB_TYPE_ISO) {
+ if (gameFile.getBlobType() == BLOB_TYPE_ISO) {
setDropdownSelection(
binding.dropdownFormat,
format,
@@ -240,6 +240,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
binding.dropdownBlockSize.adapter.getItem(0).toString(), false
)
}
+
BLOB_TYPE_WIA -> {
populateDropdown(
binding.blockSize,
@@ -253,6 +254,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
binding.dropdownBlockSize.adapter.getItem(0).toString(), false
)
}
+
BLOB_TYPE_RVZ -> {
populateDropdown(
binding.blockSize,
@@ -266,6 +268,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
binding.dropdownBlockSize.adapter.getItem(2).toString(), false
)
}
+
else -> clearDropdown(binding.blockSize, binding.dropdownBlockSize, blockSize)
}
}
@@ -285,6 +288,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
binding.dropdownCompression.adapter.getItem(0).toString(), false
)
}
+
BLOB_TYPE_WIA -> {
populateDropdown(
binding.compression,
@@ -298,6 +302,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
binding.dropdownCompression.adapter.getItem(0).toString(), false
)
}
+
BLOB_TYPE_RVZ -> {
populateDropdown(
binding.compression,
@@ -311,6 +316,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
binding.dropdownCompression.adapter.getItem(4).toString(), false
)
}
+
else -> clearDropdown(
binding.compression,
binding.dropdownCompression,
@@ -336,6 +342,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
).toString(), false
)
}
+
COMPRESSION_ZSTD -> {
// TODO: Query DiscIO for the supported compression levels, like we do in DolphinQt?
populateDropdown(
@@ -352,6 +359,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
).toString(), false
)
}
+
else -> clearDropdown(
binding.compressionLevel,
binding.dropdownCompressionLevel,
@@ -362,7 +370,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
private fun populateRemoveJunkData() {
val scrubbingAllowed = format.getValue(requireContext()) != BLOB_TYPE_RVZ &&
- !gameFile.isDatelDisc
+ !gameFile.isDatelDisc()
binding.switchRemoveJunkData.isEnabled = scrubbingAllowed
if (!scrubbingAllowed) binding.switchRemoveJunkData.isChecked = false
@@ -374,11 +382,11 @@ class ConvertFragment : Fragment(), View.OnClickListener {
var action = Runnable { showSavePrompt() }
- if (gameFile.isNKit) {
+ if (gameFile.isNKit()) {
action = addAreYouSureDialog(action, R.string.convert_warning_nkit)
}
- if (!scrub && format == BLOB_TYPE_GCZ && !gameFile.isDatelDisc && gameFile.platform == Platform.WII.toInt()) {
+ if (!scrub && format == BLOB_TYPE_GCZ && !gameFile.isDatelDisc() && gameFile.getPlatform() == Platform.WII.toInt()) {
action = addAreYouSureDialog(action, R.string.convert_warning_gcz)
}
@@ -401,7 +409,7 @@ class ConvertFragment : Fragment(), View.OnClickListener {
}
private fun showSavePrompt() {
- val originalPath = gameFile.path
+ val originalPath = gameFile.getPath()
val filename = StringBuilder(File(originalPath).name)
val dotIndex = filename.lastIndexOf(".")
@@ -449,9 +457,9 @@ class ConvertFragment : Fragment(), View.OnClickListener {
thread = Thread {
val success = NativeLibrary.ConvertDiscImage(
- gameFile.path,
+ gameFile.getPath(),
outPath,
- gameFile.platform,
+ gameFile.getPlatform(),
format.getValue(context),
blockSize.getValueOr(context, 0),
compression.getValueOr(context, 0),
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.java
deleted file mode 100644
index 26f4c169ce..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.java
+++ /dev/null
@@ -1,78 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.model;
-
-import androidx.annotation.Keep;
-
-public class GameFile
-{
- public static int REGION_NTSC_J = 0;
- public static int REGION_NTSC_U = 1;
- public static int REGION_PAL = 2;
- public static int REGION_NTSC_K = 4;
-
- @Keep
- private long mPointer;
-
- @Keep
- private GameFile(long pointer)
- {
- mPointer = pointer;
- }
-
- public native static GameFile parse(String path);
-
- @Override
- public native void finalize();
-
- public native int getPlatform();
-
- public native String getTitle();
-
- public native String getDescription();
-
- public native String getCompany();
-
- public native int getCountry();
-
- public native int getRegion();
-
- public native String getPath();
-
- public native String getGameId();
-
- public native String getGameTdbId();
-
- public native int getDiscNumber();
-
- public native int getRevision();
-
- public native int getBlobType();
-
- public native String getFileFormatName();
-
- public native long getBlockSize();
-
- public native String getCompressionMethod();
-
- public native boolean shouldShowFileFormatDetails();
-
- public native boolean shouldAllowConversion();
-
- public native long getFileSize();
-
- public native boolean isDatelDisc();
-
- public native boolean isNKit();
-
- public native int[] getBanner();
-
- public native int getBannerWidth();
-
- public native int getBannerHeight();
-
- public String getCustomCoverPath()
- {
- return getPath().substring(0, getPath().lastIndexOf(".")) + ".cover.png";
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.kt
new file mode 100644
index 0000000000..347433f552
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFile.kt
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.model
+
+import androidx.annotation.Keep
+
+@Keep
+class GameFile private constructor(private val pointer: Long) {
+ external fun finalize()
+
+ external fun getPlatform(): Int
+
+ external fun getTitle(): String
+
+ external fun getDescription(): String
+
+ external fun getCompany(): String
+
+ external fun getCountry(): Int
+
+ external fun getRegion(): Int
+
+ external fun getPath(): String
+
+ external fun getGameId(): String
+
+ external fun getGameTdbId(): String
+
+ external fun getDiscNumber(): Int
+
+ external fun getRevision(): Int
+
+ external fun getBlobType(): Int
+
+ external fun getFileFormatName(): String
+
+ external fun getBlockSize(): Long
+
+ external fun getCompressionMethod(): String
+
+ external fun shouldShowFileFormatDetails(): Boolean
+
+ external fun shouldAllowConversion(): Boolean
+
+ external fun getFileSize(): Long
+
+ external fun isDatelDisc(): Boolean
+
+ external fun isNKit(): Boolean
+
+ external fun getBanner(): IntArray
+
+ external fun getBannerWidth(): Int
+
+ external fun getBannerHeight(): Int
+
+ val customCoverPath: String
+ get() = "${getPath().substring(0, getPath().lastIndexOf("."))}.cover.png"
+
+ companion object {
+ var REGION_NTSC_J = 0
+ var REGION_NTSC_U = 1
+ var REGION_PAL = 2
+ var REGION_NTSC_K = 4
+
+ @JvmStatic
+ external fun parse(path: String): GameFile?
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java
deleted file mode 100644
index 59c8893dcf..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.java
+++ /dev/null
@@ -1,139 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.model;
-
-import androidx.annotation.Keep;
-
-import org.dolphinemu.dolphinemu.NativeLibrary;
-import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting;
-import org.dolphinemu.dolphinemu.features.settings.model.Settings;
-import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile;
-import org.dolphinemu.dolphinemu.utils.ContentHandler;
-import org.dolphinemu.dolphinemu.utils.IniFile;
-
-import java.io.File;
-import java.util.LinkedHashSet;
-
-public class GameFileCache
-{
- @Keep
- private long mPointer;
-
- public GameFileCache()
- {
- mPointer = newGameFileCache();
- }
-
- private static native long newGameFileCache();
-
- @Override
- public native void finalize();
-
- public static void addGameFolder(String path)
- {
- File dolphinFile = SettingsFile.getSettingsFile(Settings.FILE_DOLPHIN);
- IniFile dolphinIni = new IniFile(dolphinFile);
- LinkedHashSet<String> pathSet = getPathSet(false);
- int totalISOPaths =
- dolphinIni.getInt(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATHS, 0);
-
- if (!pathSet.contains(path))
- {
- dolphinIni.setInt(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATHS,
- totalISOPaths + 1);
- dolphinIni.setString(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATH_BASE +
- totalISOPaths, path);
- dolphinIni.save(dolphinFile);
- NativeLibrary.ReloadConfig();
- }
- }
-
- private static LinkedHashSet<String> getPathSet(boolean removeNonExistentFolders)
- {
- File dolphinFile = SettingsFile.getSettingsFile(Settings.FILE_DOLPHIN);
- IniFile dolphinIni = new IniFile(dolphinFile);
- LinkedHashSet<String> pathSet = new LinkedHashSet<>();
- int totalISOPaths =
- dolphinIni.getInt(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATHS, 0);
-
- for (int i = 0; i < totalISOPaths; i++)
- {
- String path = dolphinIni.getString(Settings.SECTION_INI_GENERAL,
- SettingsFile.KEY_ISO_PATH_BASE + i, "");
-
- if (ContentHandler.isContentUri(path) ? ContentHandler.exists(path) : new File(path).exists())
- {
- pathSet.add(path);
- }
- }
-
- if (removeNonExistentFolders && totalISOPaths > pathSet.size())
- {
- int setIndex = 0;
-
- dolphinIni.setInt(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATHS,
- pathSet.size());
-
- // One or more folders have been removed.
- for (String entry : pathSet)
- {
- dolphinIni.setString(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATH_BASE +
- setIndex, entry);
-
- setIndex++;
- }
-
- // Delete known unnecessary keys. Ignore i values beyond totalISOPaths.
- for (int i = setIndex; i < totalISOPaths; i++)
- {
- dolphinIni.deleteKey(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATH_BASE + i);
- }
-
- dolphinIni.save(dolphinFile);
- NativeLibrary.ReloadConfig();
- }
-
- return pathSet;
- }
-
- public static String[] getAllGamePaths()
- {
- boolean recursiveScan = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.getBoolean();
-
- LinkedHashSet<String> folderPathsSet = getPathSet(true);
-
- String[] folderPaths = folderPathsSet.toArray(new String[0]);
-
- return getAllGamePaths(folderPaths, recursiveScan);
- }
-
- public static native String[] getAllGamePaths(String[] folderPaths, boolean recursiveScan);
-
- public synchronized native int getSize();
-
- public synchronized native GameFile[] getAllGames();
-
- public synchronized native GameFile addOrGet(String gamePath);
-
- /**
- * Sets the list of games to cache.
- *
- * Games which are in the passed-in list but not in the cache are scanned and added to the cache,
- * and games which are in the cache but not in the passed-in list are removed from the cache.
- *
- * @return true if the cache was modified
- */
- public synchronized native boolean update(String[] gamePaths);
-
- /**
- * For each game that already is in the cache, scans the folder that contains the game
- * for additional metadata files (PNG/XML).
- *
- * @return true if the cache was modified
- */
- public synchronized native boolean updateAdditionalMetadata();
-
- public synchronized native boolean load();
-
- public synchronized native boolean save();
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.kt
new file mode 100644
index 0000000000..74b1bd535a
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/GameFileCache.kt
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.model
+
+import androidx.annotation.Keep
+import org.dolphinemu.dolphinemu.NativeLibrary
+import org.dolphinemu.dolphinemu.features.settings.model.BooleanSetting
+import org.dolphinemu.dolphinemu.features.settings.model.Settings
+import org.dolphinemu.dolphinemu.features.settings.utils.SettingsFile
+import org.dolphinemu.dolphinemu.utils.ContentHandler
+import org.dolphinemu.dolphinemu.utils.IniFile
+import java.io.File
+
+class GameFileCache {
+ @Keep
+ private val pointer: Long = newGameFileCache()
+
+ external fun finalize()
+
+ @Synchronized
+ external fun getSize(): Int
+
+ @Synchronized
+ external fun getAllGames(): Array<GameFile>
+
+ @Synchronized
+ external fun addOrGet(gamePath: String): GameFile?
+
+ /**
+ * Sets the list of games to cache.
+ *
+ * Games which are in the passed-in list but not in the cache are scanned and added to the cache,
+ * and games which are in the cache but not in the passed-in list are removed from the cache.
+ *
+ * @return true if the cache was modified
+ */
+ @Synchronized
+ external fun update(gamePaths: Array<String>): Boolean
+
+ /**
+ * For each game that already is in the cache, scans the folder that contains the game
+ * for additional metadata files (PNG/XML).
+ *
+ * @return true if the cache was modified
+ */
+ @Synchronized
+ external fun updateAdditionalMetadata(): Boolean
+
+ @Synchronized
+ external fun load(): Boolean
+
+ @Synchronized
+ external fun save(): Boolean
+
+ companion object {
+ @JvmStatic
+ private external fun newGameFileCache(): Long
+
+ fun addGameFolder(path: String) {
+ val dolphinFile = SettingsFile.getSettingsFile(Settings.FILE_DOLPHIN)
+ val dolphinIni = IniFile(dolphinFile)
+ val pathSet = getPathSet(false)
+ val totalISOPaths =
+ dolphinIni.getInt(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATHS, 0)
+
+ if (!pathSet.contains(path)) {
+ dolphinIni.setInt(
+ Settings.SECTION_INI_GENERAL,
+ SettingsFile.KEY_ISO_PATHS,
+ totalISOPaths + 1
+ )
+ dolphinIni.setString(
+ Settings.SECTION_INI_GENERAL,
+ SettingsFile.KEY_ISO_PATH_BASE + totalISOPaths,
+ path
+ )
+ dolphinIni.save(dolphinFile)
+ NativeLibrary.ReloadConfig()
+ }
+ }
+
+ private fun getPathSet(removeNonExistentFolders: Boolean): LinkedHashSet<String> {
+ val dolphinFile = SettingsFile.getSettingsFile(Settings.FILE_DOLPHIN)
+ val dolphinIni = IniFile(dolphinFile)
+ val pathSet = LinkedHashSet<String>()
+ val totalISOPaths =
+ dolphinIni.getInt(Settings.SECTION_INI_GENERAL, SettingsFile.KEY_ISO_PATHS, 0)
+
+ for (i in 0 until totalISOPaths) {
+ val path = dolphinIni.getString(
+ Settings.SECTION_INI_GENERAL,
+ SettingsFile.KEY_ISO_PATH_BASE + i,
+ ""
+ )
+
+ val pathExists = if (ContentHandler.isContentUri(path))
+ ContentHandler.exists(path)
+ else
+ File(path).exists()
+ if (pathExists) {
+ pathSet.add(path)
+ }
+ }
+
+ if (removeNonExistentFolders && totalISOPaths > pathSet.size) {
+ var setIndex = 0
+
+ dolphinIni.setInt(
+ Settings.SECTION_INI_GENERAL,
+ SettingsFile.KEY_ISO_PATHS,
+ pathSet.size
+ )
+
+ // One or more folders have been removed.
+ for (entry in pathSet) {
+ dolphinIni.setString(
+ Settings.SECTION_INI_GENERAL,
+ SettingsFile.KEY_ISO_PATH_BASE + setIndex,
+ entry
+ )
+ setIndex++
+ }
+
+ // Delete known unnecessary keys. Ignore i values beyond totalISOPaths.
+ for (i in setIndex until totalISOPaths) {
+ dolphinIni.deleteKey(
+ Settings.SECTION_INI_GENERAL,
+ SettingsFile.KEY_ISO_PATH_BASE + i
+ )
+ }
+
+ dolphinIni.save(dolphinFile)
+ NativeLibrary.ReloadConfig()
+ }
+ return pathSet
+ }
+
+ @JvmStatic
+ fun getAllGamePaths(): Array<String> {
+ val recursiveScan = BooleanSetting.MAIN_RECURSIVE_ISO_PATHS.boolean
+ val folderPathsSet = getPathSet(true)
+ val folderPaths = folderPathsSet.toTypedArray()
+ return getAllGamePaths(folderPaths, recursiveScan)
+ }
+
+ @JvmStatic
+ external fun getAllGamePaths(
+ folderPaths: Array<String>,
+ recursiveScan: Boolean
+ ): Array<String>
+ }
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.java
deleted file mode 100644
index 6e35b1de83..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.java
+++ /dev/null
@@ -1,63 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.model;
-
-import android.net.Uri;
-
-/**
- * Represents a home screen channel for Android TV api 26+
- */
-public class HomeScreenChannel
-{
- private long channelId;
- private String name;
- private String description;
- private Uri appLinkIntentUri;
-
- public HomeScreenChannel(String name, String description, Uri appLinkIntentUri)
- {
- this.name = name;
- this.description = description;
- this.appLinkIntentUri = appLinkIntentUri;
- }
-
- public long getChannelId()
- {
- return channelId;
- }
-
- public void setChannelId(long channelId)
- {
- this.channelId = channelId;
- }
-
- public String getName()
- {
- return name;
- }
-
- public void setName(String name)
- {
- this.name = name;
- }
-
- public String getDescription()
- {
- return description;
- }
-
- public void setDescription(String description)
- {
- this.description = description;
- }
-
- public Uri getAppLinkIntentUri()
- {
- return appLinkIntentUri;
- }
-
- public void setAppLinkIntentUri(Uri appLinkIntentUri)
- {
- this.appLinkIntentUri = appLinkIntentUri;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.kt
new file mode 100644
index 0000000000..b5b269fa77
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/HomeScreenChannel.kt
@@ -0,0 +1,12 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.model
+
+import android.net.Uri
+
+/**
+ * Represents a home screen channel for Android TV api 26+
+ */
+class HomeScreenChannel(var name: String, var description: String, var appLinkIntentUri: Uri) {
+ var channelId: Long = 0
+}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java
deleted file mode 100644
index c9c4019d94..0000000000
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.java
+++ /dev/null
@@ -1,32 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0-or-later
-
-package org.dolphinemu.dolphinemu.model;
-
-public final class TvSettingsItem
-{
- private final int mItemId;
- private final int mIconId;
- private final int mLabelId;
-
- public TvSettingsItem(int itemId, int iconId, int labelId)
- {
- mItemId = itemId;
- mIconId = iconId;
- mLabelId = labelId;
- }
-
- public int getItemId()
- {
- return mItemId;
- }
-
- public int getIconId()
- {
- return mIconId;
- }
-
- public int getLabelId()
- {
- return mLabelId;
- }
-}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.kt
new file mode 100644
index 0000000000..5c4d5aa3c9
--- /dev/null
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/model/TvSettingsItem.kt
@@ -0,0 +1,5 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+package org.dolphinemu.dolphinemu.model
+
+class TvSettingsItem(val itemId: Int, val iconId: Int, val labelId: Int)
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt
index 64695a0ace..e77b694096 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainPresenter.kt
@@ -123,7 +123,7 @@ class MainPresenter(private val mainView: MainView, private val activity: Fragme
fun onResume() {
if (dirToAdd != null) {
- GameFileCache.addGameFolder(dirToAdd)
+ GameFileCache.addGameFolder(dirToAdd!!)
dirToAdd = null
}
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CoverHelper.kt b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CoverHelper.kt
index 9359d38eb3..172be697e9 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CoverHelper.kt
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/CoverHelper.kt
@@ -8,16 +8,16 @@ object CoverHelper {
@JvmStatic
fun buildGameTDBUrl(game: GameFile, region: String?): String {
val baseUrl = "https://art.gametdb.com/wii/cover/%s/%s.png"
- return String.format(baseUrl, region, game.gameTdbId)
+ return String.format(baseUrl, region, game.getGameTdbId())
}
@JvmStatic
fun getRegion(game: GameFile): String {
- val region: String = when (game.region) {
+ val region: String = when (game.getRegion()) {
GameFile.REGION_NTSC_J -> "JA"
GameFile.REGION_NTSC_U -> "US"
GameFile.REGION_NTSC_K -> "KO"
- GameFile.REGION_PAL -> when (game.country) {
+ GameFile.REGION_PAL -> when (game.getCountry()) {
3 -> "AU" // Australia
4 -> "FR" // France
5 -> "DE" // Germany
diff --git a/Source/Android/jni/AndroidCommon/IDCache.cpp b/Source/Android/jni/AndroidCommon/IDCache.cpp
index e4cacaa462..f83707cebe 100644
--- a/Source/Android/jni/AndroidCommon/IDCache.cpp
+++ b/Source/Android/jni/AndroidCommon/IDCache.cpp
@@ -563,14 +563,14 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved)
const jclass game_file_class = env->FindClass("org/dolphinemu/dolphinemu/model/GameFile");
s_game_file_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_file_class));
- s_game_file_pointer = env->GetFieldID(game_file_class, "mPointer", "J");
+ s_game_file_pointer = env->GetFieldID(game_file_class, "pointer", "J");
s_game_file_constructor = env->GetMethodID(game_file_class, "<init>", "(J)V");
env->DeleteLocalRef(game_file_class);
const jclass game_file_cache_class =
env->FindClass("org/dolphinemu/dolphinemu/model/GameFileCache");
s_game_file_cache_class = reinterpret_cast<jclass>(env->NewGlobalRef(game_file_cache_class));
- s_game_file_cache_pointer = env->GetFieldID(game_file_cache_class, "mPointer", "J");
+ s_game_file_cache_pointer = env->GetFieldID(game_file_cache_class, "pointer", "J");
env->DeleteLocalRef(game_file_cache_class);
const jclass analytics_class = env->FindClass("org/dolphinemu/dolphinemu/utils/Analytics");