Android: Update platform enum values

71f654c added a new platform in the middle of the C++ platform enum
without updating the corresponding Android code, making the Android code
incorrectly treat Wii discs as WAD files, WAD files as DOL/ELF files,
and so on. This commit fixes the problem.

To be able to add the new Triforce entry into the Platform enum without
it leading to the UI getting an additional tab, I'm splitting the enum
into Platform and PlatformTab. Platform now exactly matches the C++
enum (previously it excluded ELFOrDOL), and PlatformTab has the same
content as the old Platform.
This commit is contained in:
JosJuice 2025-04-22 20:02:52 +02:00
parent fd8ce3ce80
commit 25fdde4204
11 changed files with 94 additions and 56 deletions

View file

@ -7,16 +7,16 @@ import androidx.fragment.app.FragmentManager
import androidx.fragment.app.FragmentPagerAdapter import androidx.fragment.app.FragmentPagerAdapter
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener import androidx.swiperefreshlayout.widget.SwipeRefreshLayout.OnRefreshListener
import org.dolphinemu.dolphinemu.R import org.dolphinemu.dolphinemu.R
import org.dolphinemu.dolphinemu.ui.platform.Platform
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesFragment import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesFragment
import org.dolphinemu.dolphinemu.ui.platform.PlatformTab
class PlatformPagerAdapter( class PlatformPagerAdapter(
fm: FragmentManager, fm: FragmentManager,
private val onRefreshListener: OnRefreshListener private val onRefreshListener: OnRefreshListener
) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) { ) : FragmentPagerAdapter(fm, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
override fun getItem(position: Int): Fragment { override fun getItem(position: Int): Fragment {
val platform = Platform.fromPosition(position) val platformTab = PlatformTab.fromPosition(position)
val fragment = PlatformGamesFragment.newInstance(platform) val fragment = PlatformGamesFragment.newInstance(platformTab)
fragment.setOnRefreshListener(onRefreshListener) fragment.setOnRefreshListener(onRefreshListener)
return fragment return fragment
} }

View file

@ -72,8 +72,9 @@ public class GamePropertiesDialog extends DialogFragment
requireArguments().getBoolean(ARG_SHOULD_ALLOW_CONVERSION); requireArguments().getBoolean(ARG_SHOULD_ALLOW_CONVERSION);
final boolean isDisc = platform == Platform.GAMECUBE.toInt() || final boolean isDisc = platform == Platform.GAMECUBE.toInt() ||
platform == Platform.WII.toInt(); platform == Platform.TRIFORCE.toInt() || platform == Platform.WII.toInt();
final boolean isWii = platform != Platform.GAMECUBE.toInt(); final boolean isWii = platform == Platform.WII.toInt() ||
platform == Platform.WIIWARE.toInt();
AlertDialogItemsBuilder itemsBuilder = new AlertDialogItemsBuilder(requireContext()); AlertDialogItemsBuilder itemsBuilder = new AlertDialogItemsBuilder(requireContext());

View file

@ -13,6 +13,7 @@ import org.dolphinemu.dolphinemu.features.settings.model.ConfigChangedCallback;
import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.model.GameFileCache; import org.dolphinemu.dolphinemu.model.GameFileCache;
import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.Platform;
import org.dolphinemu.dolphinemu.ui.platform.PlatformTab;
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner; import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner;
import java.util.ArrayList; import java.util.ArrayList;
@ -46,18 +47,18 @@ public final class GameFileCacheManager
return sGameFiles; return sGameFiles;
} }
public static List<GameFile> getGameFilesForPlatform(Platform platform) public static List<GameFile> getGameFilesForPlatformTab(PlatformTab platformTab)
{ {
GameFile[] allGames = sGameFiles.getValue(); GameFile[] allGames = sGameFiles.getValue();
ArrayList<GameFile> platformGames = new ArrayList<>(); ArrayList<GameFile> platformTabGames = new ArrayList<>();
for (GameFile game : allGames) for (GameFile game : allGames)
{ {
if (Platform.fromNativeInt(game.getPlatform()) == platform) if (Platform.fromInt(game.getPlatform()).toPlatformTab() == platformTab)
{ {
platformGames.add(game); platformTabGames.add(game);
} }
} }
return platformGames; return platformTabGames;
} }
public static GameFile getGameFileByGameId(String gameId) public static GameFile getGameFileByGameId(String gameId)

View file

@ -16,7 +16,7 @@ import androidx.tvprovider.media.tv.TvContractCompat;
import org.dolphinemu.dolphinemu.R; import org.dolphinemu.dolphinemu.R;
import org.dolphinemu.dolphinemu.model.GameFile; import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.PlatformTab;
import org.dolphinemu.dolphinemu.utils.AppLinkHelper; import org.dolphinemu.dolphinemu.utils.AppLinkHelper;
import org.dolphinemu.dolphinemu.utils.TvUtil; import org.dolphinemu.dolphinemu.utils.TvUtil;
@ -96,12 +96,12 @@ public class SyncProgramsJobService extends JobService
for (Long channelId : params) for (Long channelId : params)
{ {
Channel channel = TvUtil.getChannelById(context, channelId); Channel channel = TvUtil.getChannelById(context, channelId);
for (Platform platform : Platform.values()) for (PlatformTab platformTab : PlatformTab.values())
{ {
if (channel != null && if (channel != null &&
channel.getAppLinkIntentUri().equals(AppLinkHelper.buildBrowseUri(platform))) channel.getAppLinkIntentUri().equals(AppLinkHelper.buildBrowseUri(platformTab)))
{ {
getGamesByPlatform(platform); getGamesByPlatform(platformTab);
syncPrograms(channelId); syncPrograms(channelId);
} }
} }
@ -110,9 +110,9 @@ public class SyncProgramsJobService extends JobService
return true; return true;
} }
private void getGamesByPlatform(Platform platform) private void getGamesByPlatform(PlatformTab platformTab)
{ {
updatePrograms = GameFileCacheManager.getGameFilesForPlatform(platform); updatePrograms = GameFileCacheManager.getGameFilesForPlatformTab(platformTab);
} }
private void syncPrograms(long channelId) private void syncPrograms(long channelId)

View file

@ -27,8 +27,8 @@ import org.dolphinemu.dolphinemu.features.settings.ui.MenuTag
import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity import org.dolphinemu.dolphinemu.features.settings.ui.SettingsActivity
import org.dolphinemu.dolphinemu.fragments.GridOptionDialogFragment import org.dolphinemu.dolphinemu.fragments.GridOptionDialogFragment
import org.dolphinemu.dolphinemu.services.GameFileCacheManager import org.dolphinemu.dolphinemu.services.GameFileCacheManager
import org.dolphinemu.dolphinemu.ui.platform.Platform
import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView import org.dolphinemu.dolphinemu.ui.platform.PlatformGamesView
import org.dolphinemu.dolphinemu.ui.platform.PlatformTab
import org.dolphinemu.dolphinemu.utils.Action1 import org.dolphinemu.dolphinemu.utils.Action1
import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner import org.dolphinemu.dolphinemu.utils.AfterDirectoryInitializationRunner
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
@ -258,17 +258,17 @@ class MainActivity : AppCompatActivity(), MainView, OnRefreshListener, ThemeProv
GridOptionDialogFragment().show(supportFragmentManager, "gridOptions") GridOptionDialogFragment().show(supportFragmentManager, "gridOptions")
private fun forEachPlatformGamesView(action: Action1<PlatformGamesView>) { private fun forEachPlatformGamesView(action: Action1<PlatformGamesView>) {
for (platform in Platform.values()) { for (platformTab in PlatformTab.values()) {
val fragment = getPlatformGamesView(platform) val fragment = getPlatformGamesView(platformTab)
if (fragment != null) { if (fragment != null) {
action.call(fragment) action.call(fragment)
} }
} }
} }
private fun getPlatformGamesView(platform: Platform): PlatformGamesView? { private fun getPlatformGamesView(platformTab: PlatformTab): PlatformGamesView? {
val fragmentTag = val fragmentTag =
"android:switcher:" + binding.pagerPlatforms.id + ":" + platform.toInt() "android:switcher:" + binding.pagerPlatforms.id + ":" + platformTab.toInt()
return supportFragmentManager.findFragmentByTag(fragmentTag) as PlatformGamesView? return supportFragmentManager.findFragmentByTag(fragmentTag) as PlatformGamesView?
} }

View file

@ -30,7 +30,7 @@ import org.dolphinemu.dolphinemu.fragments.GridOptionDialogFragment
import org.dolphinemu.dolphinemu.model.GameFile import org.dolphinemu.dolphinemu.model.GameFile
import org.dolphinemu.dolphinemu.model.TvSettingsItem import org.dolphinemu.dolphinemu.model.TvSettingsItem
import org.dolphinemu.dolphinemu.services.GameFileCacheManager import org.dolphinemu.dolphinemu.services.GameFileCacheManager
import org.dolphinemu.dolphinemu.ui.platform.Platform import org.dolphinemu.dolphinemu.ui.platform.PlatformTab
import org.dolphinemu.dolphinemu.utils.DirectoryInitialization import org.dolphinemu.dolphinemu.utils.DirectoryInitialization
import org.dolphinemu.dolphinemu.utils.FileBrowserHelper import org.dolphinemu.dolphinemu.utils.FileBrowserHelper
import org.dolphinemu.dolphinemu.utils.PermissionsHandler import org.dolphinemu.dolphinemu.utils.PermissionsHandler
@ -240,9 +240,11 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener {
GameFileCacheManager.startLoad() GameFileCacheManager.startLoad()
} }
for (platform in Platform.values()) { for (platformTab in PlatformTab.values()) {
val row = val row = buildGamesRow(
buildGamesRow(platform, GameFileCacheManager.getGameFilesForPlatform(platform)) platformTab,
GameFileCacheManager.getGameFilesForPlatformTab(platformTab)
)
// Add row to the adapter only if it is not empty. // Add row to the adapter only if it is not empty.
if (row != null) { if (row != null) {
@ -255,7 +257,7 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener {
browseFragment!!.adapter = rowsAdapter browseFragment!!.adapter = rowsAdapter
} }
private fun buildGamesRow(platform: Platform, gameFiles: Collection<GameFile?>): ListRow? { private fun buildGamesRow(platformTab: PlatformTab, gameFiles: Collection<GameFile?>): ListRow? {
// If there are no games, don't return a Row. // If there are no games, don't return a Row.
if (gameFiles.isEmpty()) { if (gameFiles.isEmpty()) {
return null return null
@ -269,7 +271,7 @@ class TvMainActivity : FragmentActivity(), MainView, OnRefreshListener {
gameRows.add(row) gameRows.add(row)
// Create a header for this row. // Create a header for this row.
val header = HeaderItem(platform.toInt().toLong(), getString(platform.headerName)) val header = HeaderItem(platformTab.toInt().toLong(), getString(platformTab.headerName))
// Create the row, passing it the filled adapter and the header, and give it to the master adapter. // Create the row, passing it the filled adapter and the header, and give it to the master adapter.
return ListRow(header, row) return ListRow(header, row)

View file

@ -7,30 +7,34 @@ import org.dolphinemu.dolphinemu.R
/** /**
* Enum to represent platform (eg GameCube, Wii). * Enum to represent platform (eg GameCube, Wii).
*/ */
enum class Platform(private val value: Int, val headerName: Int, val idString: String) { enum class Platform(private val value: Int) {
GAMECUBE(0, R.string.platform_gamecube, "GameCube Games"), GAMECUBE(0),
WII(1, R.string.platform_wii, "Wii Games"), TRIFORCE(1),
WIIWARE(2, R.string.platform_wiiware, "WiiWare Games"); WII(2),
WIIWARE(3),
ELF_DOL(4);
fun toInt(): Int { fun toInt(): Int {
return value return value
} }
/**
* Returns which UI tab this platform should be shown in.
*/
fun toPlatformTab(): PlatformTab {
return when (this) {
GAMECUBE -> PlatformTab.GAMECUBE
TRIFORCE -> PlatformTab.GAMECUBE
WII -> PlatformTab.WII
WIIWARE -> PlatformTab.WIIWARE
ELF_DOL -> PlatformTab.WIIWARE
}
}
companion object { companion object {
@JvmStatic
fun fromInt(i: Int): Platform { fun fromInt(i: Int): Platform {
return values()[i] return values()[i]
} }
@JvmStatic
fun fromNativeInt(i: Int): Platform {
// TODO: Proper support for DOL and ELF files
val inRange = i >= 0 && i < values().size
return values()[if (inRange) i else WIIWARE.value]
}
@JvmStatic
fun fromPosition(position: Int): Platform {
return values()[position]
}
} }
} }

View file

@ -73,9 +73,9 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {
return return
if (binding.gridGames.adapter != null) { if (binding.gridGames.adapter != null) {
val platform = requireArguments().getSerializable(ARG_PLATFORM) as Platform val platformTab = requireArguments().getSerializable(ARG_PLATFORM_TAB) as PlatformTab
(binding.gridGames.adapter as GameAdapter?)!!.swapDataSet( (binding.gridGames.adapter as GameAdapter?)!!.swapDataSet(
GameFileCacheManager.getGameFilesForPlatform(platform) GameFileCacheManager.getGameFilesForPlatformTab(platformTab)
) )
} }
} }
@ -108,13 +108,13 @@ class PlatformGamesFragment : Fragment(), PlatformGamesView {
} }
companion object { companion object {
private const val ARG_PLATFORM = "platform" private const val ARG_PLATFORM_TAB = "platform_tab"
@JvmStatic @JvmStatic
fun newInstance(platform: Platform?): PlatformGamesFragment { fun newInstance(platformTab: PlatformTab?): PlatformGamesFragment {
val fragment = PlatformGamesFragment() val fragment = PlatformGamesFragment()
val args = Bundle() val args = Bundle()
args.putSerializable(ARG_PLATFORM, platform) args.putSerializable(ARG_PLATFORM_TAB, platformTab)
fragment.arguments = args fragment.arguments = args
return fragment return fragment
} }

View file

@ -0,0 +1,30 @@
// SPDX-License-Identifier: GPL-2.0-or-later
package org.dolphinemu.dolphinemu.ui.platform
import org.dolphinemu.dolphinemu.R
/**
* Enum to represent platform tabs in the UI.
*
* Each platform tab corresponds to one or more platforms.
*/
enum class PlatformTab(private val value: Int, val headerName: Int, val idString: String) {
GAMECUBE(0, R.string.platform_gamecube, "GameCube Games"),
WII(1, R.string.platform_wii, "Wii Games"),
WIIWARE(2, R.string.platform_wiiware, "WiiWare Games");
fun toInt(): Int {
return value
}
companion object {
fun fromInt(i: Int): PlatformTab {
return values()[i]
}
fun fromPosition(position: Int): PlatformTab {
return values()[position]
}
}
}

View file

@ -6,7 +6,7 @@ import android.net.Uri;
import androidx.annotation.StringDef; import androidx.annotation.StringDef;
import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.PlatformTab;
import java.util.List; import java.util.List;
@ -33,9 +33,9 @@ public class AppLinkHelper
.build(); .build();
} }
public static Uri buildBrowseUri(Platform platform) public static Uri buildBrowseUri(PlatformTab platformTab)
{ {
return Uri.parse(URI_VIEW).buildUpon().appendPath(platform.getIdString()).build(); return Uri.parse(URI_VIEW).buildUpon().appendPath(platformTab.getIdString()).build();
} }
public static AppLinkAction extractAction(Uri uri) public static AppLinkAction extractAction(Uri uri)

View file

@ -30,7 +30,7 @@ import org.dolphinemu.dolphinemu.model.GameFile;
import org.dolphinemu.dolphinemu.model.HomeScreenChannel; import org.dolphinemu.dolphinemu.model.HomeScreenChannel;
import org.dolphinemu.dolphinemu.services.SyncChannelJobService; import org.dolphinemu.dolphinemu.services.SyncChannelJobService;
import org.dolphinemu.dolphinemu.services.SyncProgramsJobService; import org.dolphinemu.dolphinemu.services.SyncProgramsJobService;
import org.dolphinemu.dolphinemu.ui.platform.Platform; import org.dolphinemu.dolphinemu.ui.platform.PlatformTab;
import java.io.File; import java.io.File;
import java.io.FileNotFoundException; import java.io.FileNotFoundException;
@ -279,12 +279,12 @@ public class TvUtil
private static List<HomeScreenChannel> createPlatformSubscriptions(Context context) private static List<HomeScreenChannel> createPlatformSubscriptions(Context context)
{ {
List<HomeScreenChannel> subs = new ArrayList<>(); List<HomeScreenChannel> subs = new ArrayList<>();
for (Platform platform : Platform.values()) for (PlatformTab platformTab : PlatformTab.values())
{ {
subs.add(new HomeScreenChannel( subs.add(new HomeScreenChannel(
context.getString(platform.getHeaderName()), context.getString(platformTab.getHeaderName()),
context.getString(platform.getHeaderName()), context.getString(platformTab.getHeaderName()),
AppLinkHelper.buildBrowseUri(platform))); AppLinkHelper.buildBrowseUri(platformTab)));
} }
return subs; return subs;
} }