diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java
index 480e7472e3..8fa685128b 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/ui/main/MainActivity.java
@@ -161,9 +161,12 @@ public final class MainActivity extends AppCompatActivity
if (WiiUtils.isSystemMenuInstalled())
{
+ int resId = WiiUtils.isSystemMenuvWii() ?
+ R.string.grid_menu_load_vwii_system_menu_installed :
+ R.string.grid_menu_load_wii_system_menu_installed;
+
menu.findItem(R.id.menu_load_wii_system_menu).setTitle(
- getString(R.string.grid_menu_load_wii_system_menu_installed,
- WiiUtils.getSystemMenuVersion()));
+ getString(resId, WiiUtils.getSystemMenuVersion()));
}
return true;
diff --git a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java
index fb1d7e90cb..61dfedf5cd 100644
--- a/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java
+++ b/Source/Android/app/src/main/java/org/dolphinemu/dolphinemu/utils/WiiUtils.java
@@ -32,6 +32,8 @@ public final class WiiUtils
public static native boolean isSystemMenuInstalled();
+ public static native boolean isSystemMenuvWii();
+
public static native String getSystemMenuVersion();
public static native boolean syncSdFolderToSdImage();
diff --git a/Source/Android/app/src/main/res/values/strings.xml b/Source/Android/app/src/main/res/values/strings.xml
index 23eccd0c10..72c4d73356 100644
--- a/Source/Android/app/src/main/res/values/strings.xml
+++ b/Source/Android/app/src/main/res/values/strings.xml
@@ -441,6 +441,7 @@
Perform Online System Update
Load Wii System Menu
Load Wii System Menu (%s)
+ Load vWii System Menu (%s)
Importing...
Exporting...
Do not close the app!
diff --git a/Source/Android/jni/WiiUtils.cpp b/Source/Android/jni/WiiUtils.cpp
index e26ac485e9..5939816b8e 100644
--- a/Source/Android/jni/WiiUtils.cpp
+++ b/Source/Android/jni/WiiUtils.cpp
@@ -165,6 +165,15 @@ Java_org_dolphinemu_dolphinemu_utils_WiiUtils_isSystemMenuInstalled(JNIEnv* env,
return tmd.IsValid();
}
+JNIEXPORT jboolean JNICALL
+Java_org_dolphinemu_dolphinemu_utils_WiiUtils_isSystemMenuvWii(JNIEnv* env, jclass)
+{
+ IOS::HLE::Kernel ios;
+ const auto tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
+
+ return tmd.IsvWii();
+}
+
JNIEXPORT jstring JNICALL
Java_org_dolphinemu_dolphinemu_utils_WiiUtils_getSystemMenuVersion(JNIEnv* env, jclass)
{
@@ -176,7 +185,7 @@ Java_org_dolphinemu_dolphinemu_utils_WiiUtils_getSystemMenuVersion(JNIEnv* env,
return ToJString(env, "");
}
- return ToJString(env, DiscIO::GetSysMenuVersionString(tmd.GetTitleVersion()));
+ return ToJString(env, DiscIO::GetSysMenuVersionString(tmd.GetTitleVersion(), tmd.IsvWii()));
}
JNIEXPORT jboolean JNICALL
diff --git a/Source/Core/Core/IOS/ES/Formats.cpp b/Source/Core/Core/IOS/ES/Formats.cpp
index 7adb86e772..f091cf1769 100644
--- a/Source/Core/Core/IOS/ES/Formats.cpp
+++ b/Source/Core/Core/IOS/ES/Formats.cpp
@@ -291,6 +291,11 @@ DiscIO::Region TMDReader::GetRegion() const
return region <= DiscIO::Region::NTSC_K ? region : DiscIO::Region::Unknown;
}
+bool TMDReader::IsvWii() const
+{
+ return *(m_bytes.data() + offsetof(TMDHeader, is_vwii));
+}
+
std::string TMDReader::GetGameID() const
{
char game_id[6];
diff --git a/Source/Core/Core/IOS/ES/Formats.h b/Source/Core/Core/IOS/ES/Formats.h
index 5918a04a0e..d1c19ce75c 100644
--- a/Source/Core/Core/IOS/ES/Formats.h
+++ b/Source/Core/Core/IOS/ES/Formats.h
@@ -68,6 +68,8 @@ struct TMDHeader
u8 tmd_version;
u8 ca_crl_version;
u8 signer_crl_version;
+ // This is usually an always 0 padding byte, which is set to 1 on vWii TMDs
+ u8 is_vwii;
u64 ios_id;
u64 title_id;
u32 title_flags;
@@ -85,6 +87,7 @@ struct TMDHeader
u16 fill2;
};
static_assert(sizeof(TMDHeader) == 0x1e4, "TMDHeader has the wrong size");
+static_assert(offsetof(TMDHeader, ios_id) == 0x184);
struct Content
{
@@ -200,6 +203,7 @@ public:
u16 GetTitleVersion() const;
u16 GetGroupId() const;
DiscIO::Region GetRegion() const;
+ bool IsvWii() const;
// Constructs a 6-character game ID in the format typically used by Dolphin.
// If the 6-character game ID would contain unprintable characters,
diff --git a/Source/Core/DiscIO/Enums.cpp b/Source/Core/DiscIO/Enums.cpp
index 0594e3161a..393f30076f 100644
--- a/Source/Core/DiscIO/Enums.cpp
+++ b/Source/Core/DiscIO/Enums.cpp
@@ -362,7 +362,7 @@ Region GetSysMenuRegion(u16 title_version)
}
}
-std::string GetSysMenuVersionString(u16 title_version)
+std::string GetSysMenuVersionString(u16 title_version, bool is_vwii)
{
std::string version;
char region_letter = '\0';
@@ -386,52 +386,74 @@ std::string GetSysMenuVersionString(u16 title_version)
break;
}
- switch (title_version & 0xff0)
+ if (is_vwii)
{
- case 32:
- version = "1.0";
- break;
- case 96:
- case 128:
- version = "2.0";
- break;
- case 160:
- version = "2.1";
- break;
- case 192:
- version = "2.2";
- break;
- case 224:
- version = "3.0";
- break;
- case 256:
- version = "3.1";
- break;
- case 288:
- version = "3.2";
- break;
- case 320:
- case 352:
- version = "3.3";
- break;
- case 384:
- version = (region_letter != 'K' ? "3.4" : "3.5");
- break;
- case 416:
- version = "4.0";
- break;
- case 448:
- version = "4.1";
- break;
- case 480:
- version = "4.2";
- break;
- case 512:
- version = "4.3";
- break;
- default:
- version = "?.?";
- break;
+ // For vWii return the Wii U version which installed the menu
+ switch (title_version & 0xff0)
+ {
+ case 512:
+ version = "1.0.0";
+ break;
+ case 544:
+ version = "4.0.0";
+ break;
+ case 608:
+ version = "5.2.0";
+ break;
+ default:
+ version = "?.?.?";
+ break;
+ }
+ }
+ else
+ {
+ switch (title_version & 0xff0)
+ {
+ case 32:
+ version = "1.0";
+ break;
+ case 96:
+ case 128:
+ version = "2.0";
+ break;
+ case 160:
+ version = "2.1";
+ break;
+ case 192:
+ version = "2.2";
+ break;
+ case 224:
+ version = "3.0";
+ break;
+ case 256:
+ version = "3.1";
+ break;
+ case 288:
+ version = "3.2";
+ break;
+ case 320:
+ case 352:
+ version = "3.3";
+ break;
+ case 384:
+ version = (region_letter != 'K' ? "3.4" : "3.5");
+ break;
+ case 416:
+ version = "4.0";
+ break;
+ case 448:
+ version = "4.1";
+ break;
+ case 480:
+ version = "4.2";
+ break;
+ case 512:
+ version = "4.3";
+ break;
+ default:
+ version = "?.?";
+ break;
+ }
}
if (region_letter != '\0')
diff --git a/Source/Core/DiscIO/Enums.h b/Source/Core/DiscIO/Enums.h
index 087234b59d..ebbef8cd42 100644
--- a/Source/Core/DiscIO/Enums.h
+++ b/Source/Core/DiscIO/Enums.h
@@ -88,7 +88,7 @@ Country CountryCodeToCountry(u8 country_code, Platform platform, Region region =
std::optional revision = {});
Region GetSysMenuRegion(u16 title_version);
-std::string GetSysMenuVersionString(u16 title_version);
+std::string GetSysMenuVersionString(u16 title_version, bool is_vwii);
const std::string& GetCompanyFromID(const std::string& company_id);
} // namespace DiscIO
diff --git a/Source/Core/DolphinQt/MenuBar.cpp b/Source/Core/DolphinQt/MenuBar.cpp
index f901f3e726..f36a1d9a1d 100644
--- a/Source/Core/DolphinQt/MenuBar.cpp
+++ b/Source/Core/DolphinQt/MenuBar.cpp
@@ -1010,10 +1010,14 @@ void MenuBar::UpdateToolsMenu(bool emulation_started)
const auto tmd = ios.GetES()->FindInstalledTMD(Titles::SYSTEM_MENU);
const QString sysmenu_version =
- tmd.IsValid() ?
- QString::fromStdString(DiscIO::GetSysMenuVersionString(tmd.GetTitleVersion())) :
- QString{};
- m_boot_sysmenu->setText(tr("Load Wii System Menu %1").arg(sysmenu_version));
+ tmd.IsValid() ? QString::fromStdString(
+ DiscIO::GetSysMenuVersionString(tmd.GetTitleVersion(), tmd.IsvWii())) :
+ QString{};
+
+ const QString sysmenu_text = (tmd.IsValid() && tmd.IsvWii()) ? tr("Load vWii System Menu %1") :
+ tr("Load Wii System Menu %1");
+
+ m_boot_sysmenu->setText(sysmenu_text.arg(sysmenu_version));
m_boot_sysmenu->setEnabled(tmd.IsValid());