Merge pull request #4544 from JosJuice/region-enum

DiscIO: Add GetRegion function and Region enum
This commit is contained in:
Matthew Parlane 2017-01-13 09:19:27 +13:00 committed by GitHub
commit d346d4ced1
32 changed files with 264 additions and 269 deletions

View File

@ -188,32 +188,34 @@ bool CBoot::Load_BS2(const std::string& _rBootROMFilename)
// Use zlibs crc32 implementation to compute the hash
u32 ipl_hash = crc32(0L, Z_NULL, 0);
ipl_hash = crc32(ipl_hash, (const Bytef*)data.data(), (u32)data.size());
std::string ipl_region;
DiscIO::Region ipl_region;
switch (ipl_hash)
{
case USA_v1_0:
case USA_v1_1:
case USA_v1_2:
case BRA_v1_0:
ipl_region = USA_DIR;
ipl_region = DiscIO::Region::NTSC_U;
break;
case JAP_v1_0:
case JAP_v1_1:
ipl_region = JAP_DIR;
ipl_region = DiscIO::Region::NTSC_J;
break;
case PAL_v1_0:
case PAL_v1_2:
ipl_region = EUR_DIR;
ipl_region = DiscIO::Region::PAL;
break;
default:
PanicAlertT("IPL with unknown hash %x", ipl_hash);
ipl_region = DiscIO::Region::UNKNOWN_REGION;
break;
}
std::string BootRegion = _rBootROMFilename.substr(_rBootROMFilename.find_last_of(DIR_SEP) - 3, 3);
if (BootRegion != ipl_region)
const DiscIO::Region boot_region = SConfig::GetInstance().m_region;
if (ipl_region != DiscIO::Region::UNKNOWN_REGION && boot_region != ipl_region)
PanicAlertT("%s IPL found in %s directory. The disc might not be recognized",
ipl_region.c_str(), BootRegion.c_str());
SConfig::GetDirectoryForRegion(ipl_region),
SConfig::GetDirectoryForRegion(boot_region));
// Run the descrambler over the encrypted section containing BS1/BS2
CEXIIPL::Descrambler((u8*)data.data() + 0x100, 0x1AFE00);
@ -255,7 +257,8 @@ bool CBoot::BootUp()
g_symbolDB.Clear();
// PAL Wii uses NTSC framerate and linecount in 60Hz modes
VideoInterface::Preset(_StartupPara.bNTSC || (_StartupPara.bWii && _StartupPara.bPAL60));
VideoInterface::Preset(DiscIO::IsNTSC(_StartupPara.m_region) ||
(_StartupPara.bWii && _StartupPara.bPAL60));
switch (_StartupPara.m_BootType)
{
@ -275,8 +278,6 @@ bool CBoot::BootUp()
}
std::string game_id = DVDInterface::GetVolume().GetGameID();
if (game_id.size() >= 4)
VideoInterface::SetRegionReg(game_id.at(3));
std::vector<u8> tmd_buffer = pVolume.GetTMD();
if (!tmd_buffer.empty())
@ -419,7 +420,7 @@ bool CBoot::BootUp()
// Poor man's bootup
if (_StartupPara.bWii)
SetupWiiMemory(DiscIO::Country::COUNTRY_UNKNOWN);
SetupWiiMemory();
else
EmulatedBS2_GC(true);

View File

@ -7,12 +7,7 @@
#include <cstdlib>
#include <string>
namespace DiscIO
{
enum class Country;
}
struct CountrySetting
struct RegionSetting
{
const std::string area;
const std::string video;
@ -57,5 +52,5 @@ private:
static bool Load_BS2(const std::string& _rBootROMFilename);
static void Load_FST(bool _bIsWii);
static bool SetupWiiMemory(DiscIO::Country country);
static bool SetupWiiMemory();
};

View File

@ -74,8 +74,8 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
0x10000006,
0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
PowerPC::HostWrite_U32(SConfig::GetInstance().bNTSC ? 0 : 1,
0x800000CC); // Fake the VI Init of the IPL (YAGCD 4.2.1.4)
const bool ntsc = DiscIO::IsNTSC(SConfig::GetInstance().m_region);
PowerPC::HostWrite_U32(ntsc ? 0 : 1, 0x800000CC); // Fake the VI Init of the IPL (YAGCD 4.2.1.4)
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external
// (retail consoles have no external ARAM)
@ -113,13 +113,14 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, false);
// Setup pointers like real BS2 does
if (SConfig::GetInstance().bNTSC)
if (ntsc)
{
PowerPC::ppcState.gpr[1] = 0x81566550; // StackPointer, used to be set to 0x816ffff0
PowerPC::ppcState.gpr[2] = 0x81465cc0; // Global pointer to Small Data Area 2 Base (haven't
// seen anything use it...meh)
PowerPC::ppcState.gpr[13] =
0x81465320; // Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
// StackPointer, used to be set to 0x816ffff0
PowerPC::ppcState.gpr[1] = 0x81566550;
// Global pointer to Small Data Area 2 Base (haven't seen anything use it...meh)
PowerPC::ppcState.gpr[2] = 0x81465cc0;
// Global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
PowerPC::ppcState.gpr[13] = 0x81465320;
}
else
{
@ -181,28 +182,15 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
return true;
}
bool CBoot::SetupWiiMemory(DiscIO::Country country)
bool CBoot::SetupWiiMemory()
{
static const CountrySetting SETTING_EUROPE = {"EUR", "PAL", "EU", "LE"};
static const CountrySetting SETTING_USA = {"USA", "NTSC", "US", "LU"};
static const CountrySetting SETTING_JAPAN = {"JPN", "NTSC", "JP", "LJ"};
static const CountrySetting SETTING_KOREA = {"KOR", "NTSC", "KR", "LKH"};
static const std::map<DiscIO::Country, const CountrySetting> country_settings = {
{DiscIO::Country::COUNTRY_EUROPE, SETTING_EUROPE},
{DiscIO::Country::COUNTRY_USA, SETTING_USA},
{DiscIO::Country::COUNTRY_JAPAN, SETTING_JAPAN},
{DiscIO::Country::COUNTRY_KOREA, SETTING_KOREA},
// TODO: Determine if Taiwan have their own specific settings.
// Also determine if there are other specific settings
// for other countries.
{DiscIO::Country::COUNTRY_TAIWAN, SETTING_JAPAN}};
auto entryPos = country_settings.find(country);
const CountrySetting& country_setting =
(entryPos != country_settings.end()) ?
entryPos->second :
(SConfig::GetInstance().bNTSC ?
SETTING_USA :
SETTING_EUROPE); // default to USA or EUR depending on game's video mode
static const std::map<DiscIO::Region, const RegionSetting> region_settings = {
{DiscIO::Region::NTSC_J, {"JPN", "NTSC", "JP", "LJ"}},
{DiscIO::Region::NTSC_U, {"USA", "NTSC", "US", "LU"}},
{DiscIO::Region::PAL, {"EUR", "PAL", "EU", "LE"}},
{DiscIO::Region::NTSC_K, {"KOR", "NTSC", "KR", "LKH"}}};
auto entryPos = region_settings.find(SConfig::GetInstance().m_region);
const RegionSetting& region_setting = entryPos->second;
SettingsHandler gen;
std::string serno;
@ -233,15 +221,15 @@ bool CBoot::SetupWiiMemory(DiscIO::Country country)
INFO_LOG(BOOT, "Using serial number: %s", serno.c_str());
}
std::string model = "RVL-001(" + country_setting.area + ")";
gen.AddSetting("AREA", country_setting.area);
std::string model = "RVL-001(" + region_setting.area + ")";
gen.AddSetting("AREA", region_setting.area);
gen.AddSetting("MODEL", model);
gen.AddSetting("DVD", "0");
gen.AddSetting("MPCH", "0x7FFE");
gen.AddSetting("CODE", country_setting.code);
gen.AddSetting("CODE", region_setting.code);
gen.AddSetting("SERNO", serno);
gen.AddSetting("VIDEO", country_setting.video);
gen.AddSetting("GAME", country_setting.game);
gen.AddSetting("VIDEO", region_setting.video);
gen.AddSetting("GAME", region_setting.game);
File::CreateFullPath(settings_Filename);
{
@ -317,7 +305,7 @@ bool CBoot::SetupWiiMemory(DiscIO::Country country)
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
// Fake the VI Init of the IPL
Memory::Write_U32(SConfig::GetInstance().bNTSC ? 0 : 1, 0x000000CC);
Memory::Write_U32(DiscIO::IsNTSC(SConfig::GetInstance().m_region) ? 0 : 1, 0x000000CC);
// Clear exception handler. Why? Don't we begin with only zeros?
for (int i = 0x3000; i <= 0x3038; i += 4)
@ -336,10 +324,7 @@ bool CBoot::EmulatedBS2_Wii()
INFO_LOG(BOOT, "Faking Wii BS2...");
// Setup Wii memory
DiscIO::Country country_code = DiscIO::Country::COUNTRY_UNKNOWN;
if (DVDInterface::VolumeIsValid())
country_code = DVDInterface::GetVolume().GetCountry();
if (SetupWiiMemory(country_code) == false)
if (!SetupWiiMemory())
return false;
// Execute the apploader

View File

@ -89,13 +89,8 @@ bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
if (titleID == TITLEID_SYSMENU)
HLE_IPC_CreateVirtualFATFilesystem();
// setup Wii memory
if (!SetupWiiMemory(ContentLoader.GetCountry()))
if (!SetupWiiMemory())
return false;
// this sets a bit that is used to detect NTSC-J
if (ContentLoader.GetCountry() == DiscIO::Country::COUNTRY_JAPAN)
{
VideoInterface::SetRegionReg('J');
}
// DOL
const DiscIO::SNANDContent* pContent =
ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());

View File

@ -28,6 +28,7 @@
#include "Common/IniFile.h"
#include "Common/Logging/Log.h"
#include "Common/MsgHandler.h"
#include "Core/BootManager.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
@ -38,6 +39,9 @@
#include "Core/Host.h"
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
#include "DiscIO/Enums.h"
#include "VideoCommon/VideoBackendBase.h"
namespace BootManager
@ -349,17 +353,19 @@ bool BootCore(const std::string& _rFilename)
g_SRAM_netplay_initialized = false;
}
const bool ntsc = DiscIO::IsNTSC(StartUp.m_region);
// Apply overrides
// Some NTSC GameCube games such as Baten Kaitos react strangely to language settings that would
// be invalid on an NTSC system
if (!StartUp.bOverrideGCLanguage && StartUp.bNTSC)
// Some NTSC GameCube games such as Baten Kaitos react strangely to
// language settings that would be invalid on an NTSC system
if (!StartUp.bOverrideGCLanguage && ntsc)
{
StartUp.SelectedLanguage = 0;
}
// Some NTSC Wii games such as Doc Louis's Punch-Out!! and 1942 (Virtual Console) crash if the
// PAL60 option is enabled
if (StartUp.bWii && StartUp.bNTSC)
// Some NTSC Wii games such as Doc Louis's Punch-Out!! and
// 1942 (Virtual Console) crash if the PAL60 option is enabled
if (StartUp.bWii && ntsc)
{
StartUp.bPAL60 = false;
}

View File

@ -761,31 +761,28 @@ void SConfig::LoadDefaults()
m_revision = 0;
}
static const char* GetRegionOfCountry(DiscIO::Country country)
const char* SConfig::GetDirectoryForRegion(DiscIO::Region region)
{
switch (country)
switch (region)
{
case DiscIO::Country::COUNTRY_USA:
return USA_DIR;
case DiscIO::Country::COUNTRY_TAIWAN:
case DiscIO::Country::COUNTRY_KOREA:
// TODO: Should these have their own Region Dir?
case DiscIO::Country::COUNTRY_JAPAN:
case DiscIO::Region::NTSC_J:
return JAP_DIR;
case DiscIO::Country::COUNTRY_AUSTRALIA:
case DiscIO::Country::COUNTRY_EUROPE:
case DiscIO::Country::COUNTRY_FRANCE:
case DiscIO::Country::COUNTRY_GERMANY:
case DiscIO::Country::COUNTRY_ITALY:
case DiscIO::Country::COUNTRY_NETHERLANDS:
case DiscIO::Country::COUNTRY_RUSSIA:
case DiscIO::Country::COUNTRY_SPAIN:
case DiscIO::Country::COUNTRY_WORLD:
case DiscIO::Region::NTSC_U:
return USA_DIR;
case DiscIO::Region::PAL:
return EUR_DIR;
case DiscIO::Country::COUNTRY_UNKNOWN:
case DiscIO::Region::NTSC_K:
// This function can't return a Korean directory name, because this
// function is only used for GameCube things (memory cards, IPL), and
// GameCube has no NTSC-K region. Since NTSC-K doesn't correspond to any
// GameCube region, let's return an arbitrary pick. Returning nullptr like
// with unknown regions would be inappropriate, because Dolphin expects
// to get valid memory card paths even when running an NTSC-K Wii game.
return JAP_DIR;
default:
return nullptr;
}
@ -837,17 +834,18 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
// Check if we have a Wii disc
bWii = pVolume->GetVolumeType() == DiscIO::Platform::WII_DISC;
const char* retrieved_region_dir = GetRegionOfCountry(pVolume->GetCountry());
m_region = pVolume->GetRegion();
const char* retrieved_region_dir = GetDirectoryForRegion(m_region);
if (!retrieved_region_dir)
{
if (!PanicYesNoT("Your GCM/ISO file seems to be invalid (invalid country)."
"\nContinue with PAL region?"))
return false;
m_region = DiscIO::Region::PAL;
retrieved_region_dir = EUR_DIR;
}
set_region_dir = retrieved_region_dir;
bNTSC = set_region_dir == USA_DIR || set_region_dir == JAP_DIR;
}
else if (!strcasecmp(Extension.c_str(), ".elf"))
{
@ -857,8 +855,8 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
// all GC homebrew to 50Hz.
// In the future, it probably makes sense to add a Region setting for homebrew somewhere in
// the emulator config.
bNTSC = bWii ? false : true;
set_region_dir = bNTSC ? USA_DIR : EUR_DIR;
m_region = bWii ? DiscIO::Region::PAL : DiscIO::Region::NTSC_U;
set_region_dir = bWii ? EUR_DIR : USA_DIR;
m_BootType = BOOT_ELF;
}
else if (!strcasecmp(Extension.c_str(), ".dol"))
@ -866,15 +864,15 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
CDolLoader dolfile(m_strFilename);
bWii = dolfile.IsWii();
// TODO: See the ELF code above.
bNTSC = bWii ? false : true;
set_region_dir = bNTSC ? USA_DIR : EUR_DIR;
m_region = bWii ? DiscIO::Region::PAL : DiscIO::Region::NTSC_U;
set_region_dir = bWii ? EUR_DIR : USA_DIR;
m_BootType = BOOT_DOL;
}
else if (!strcasecmp(Extension.c_str(), ".dff"))
{
bWii = true;
m_region = DiscIO::Region::NTSC_U;
set_region_dir = USA_DIR;
bNTSC = true;
m_BootType = BOOT_DFF;
std::unique_ptr<FifoDataFile> ddfFile(FifoDataFile::Load(m_strFilename, true));
@ -899,9 +897,9 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
return false; // do not boot
}
const char* retrieved_region_dir = GetRegionOfCountry(ContentLoader.GetCountry());
m_region = ContentLoader.GetRegion();
const char* retrieved_region_dir = GetDirectoryForRegion(m_region);
set_region_dir = retrieved_region_dir ? retrieved_region_dir : EUR_DIR;
bNTSC = set_region_dir == USA_DIR || set_region_dir == JAP_DIR;
bWii = true;
m_BootType = BOOT_WII_NAND;
@ -942,21 +940,21 @@ bool SConfig::AutoSetup(EBootBS2 _BootBS2)
break;
case BOOT_BS2_USA:
m_region = DiscIO::Region::NTSC_U;
set_region_dir = USA_DIR;
m_strFilename.clear();
bNTSC = true;
break;
case BOOT_BS2_JAP:
m_region = DiscIO::Region::NTSC_J;
set_region_dir = JAP_DIR;
m_strFilename.clear();
bNTSC = true;
break;
case BOOT_BS2_EUR:
m_region = DiscIO::Region::PAL;
set_region_dir = EUR_DIR;
m_strFilename.clear();
bNTSC = false;
break;
}

View File

@ -16,6 +16,7 @@
namespace DiscIO
{
enum class Language;
enum class Region;
}
// DSP Backend Types
@ -92,7 +93,6 @@ struct SConfig : NonCopyable
bool bDSPThread = false;
bool bDSPHLE = true;
bool bSyncGPUOnSkipIdleHack = true;
bool bNTSC = false;
bool bForceNTSCJ = false;
bool bHLE_BS2 = true;
bool bEnableCheats = false;
@ -183,7 +183,9 @@ struct SConfig : NonCopyable
BOOT_BS2,
BOOT_DFF
};
EBootType m_BootType;
DiscIO::Region m_region;
std::string m_strVideoBackend;
std::string m_strGPUDeterminismMode;
@ -206,6 +208,7 @@ struct SConfig : NonCopyable
std::string m_perfDir;
void LoadDefaults();
static const char* GetDirectoryForRegion(DiscIO::Region region);
bool AutoSetup(EBootBS2 _BootBS2);
const std::string& GetGameID() const { return m_strGameID; }
void CheckMemcardPath(std::string& memcardPath, const std::string& gameRegion, bool isSlotA);

View File

@ -13,6 +13,7 @@
#include "Common/MemoryUtil.h"
#include "Common/StringUtil.h"
#include "Common/Timer.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
@ -22,6 +23,8 @@
#include "Core/Movie.h"
#include "Core/NetPlayProto.h"
#include "DiscIO/Enums.h"
// We should provide an option to choose from the above, or figure out the checksum (the algo in
// yagcd seems wrong)
// so that people can change default language.
@ -88,17 +91,16 @@ void CEXIIPL::Descrambler(u8* data, u32 size)
CEXIIPL::CEXIIPL() : m_uPosition(0), m_uAddress(0), m_uRWOffset(0), m_FontsLoaded(false)
{
// Determine region
m_bNTSC = SConfig::GetInstance().bNTSC;
// Create the IPL
m_pIPL = static_cast<u8*>(Common::AllocateMemoryPages(ROM_SIZE));
if (SConfig::GetInstance().bHLE_BS2)
{
// Copy header
memcpy(m_pIPL, m_bNTSC ? iplverNTSC : iplverPAL,
m_bNTSC ? sizeof(iplverNTSC) : sizeof(iplverPAL));
if (DiscIO::IsNTSC(SConfig::GetInstance().m_region))
memcpy(m_pIPL, iplverNTSC, sizeof(iplverNTSC));
else
memcpy(m_pIPL, iplverPAL, sizeof(iplverPAL));
// Load fonts
LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_SHIFT_JIS), 0x1aff00);

View File

@ -52,9 +52,6 @@ private:
REGION_EUART = 0x300001
};
// Region
bool m_bNTSC;
//! IPL
u8* m_pIPL;

View File

@ -152,73 +152,18 @@ CEXIMemoryCard::CEXIMemoryCard(const int index, bool gciFolder) : card_index(ind
void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
{
DiscIO::Country country_code = DiscIO::Country::COUNTRY_UNKNOWN;
DiscIO::Region region = SConfig::GetInstance().m_region;
std::string game_id = SConfig::GetInstance().m_strGameID;
u32 CurrentGameId = 0;
if (game_id == TITLEID_SYSMENU_STRING)
{
const DiscIO::CNANDContentLoader& SysMenu_Loader =
DiscIO::CNANDContentManager::Access().GetNANDLoader(TITLEID_SYSMENU,
Common::FROM_SESSION_ROOT);
if (SysMenu_Loader.IsValid())
{
country_code = DiscIO::CountrySwitch(SysMenu_Loader.GetCountryChar());
}
}
else if (game_id.length() >= 4)
{
country_code = DiscIO::CountrySwitch(game_id.at(3));
if (game_id.length() >= 4 && game_id != "00000000" && game_id != TITLEID_SYSMENU_STRING)
CurrentGameId = BE32((u8*)game_id.c_str());
}
bool shift_jis = false;
std::string strDirectoryName = File::GetUserPath(D_GCUSER_IDX);
switch (country_code)
{
case DiscIO::Country::COUNTRY_JAPAN:
shift_jis = true;
strDirectoryName += JAP_DIR DIR_SEP;
break;
case DiscIO::Country::COUNTRY_USA:
strDirectoryName += USA_DIR DIR_SEP;
break;
case DiscIO::Country::COUNTRY_UNKNOWN:
{
// The current game's region is not passed down to the EXI device level.
// Usually, we can retrieve the region from SConfig::GetInstance().m_strUniqueId.
// The Wii System Menu requires a lookup based on the version number.
// This is not possible in some cases ( e.g. FIFO logs, homebrew elf/dol files).
// Instead, we then lookup the region from the memory card name
// Earlier in the boot process the region is added to the memory card name (This is done by the
// function checkMemcardPath)
// For now take advantage of this.
// Future options:
// Set memory card directory path in the checkMemcardPath function.
// or Add region to SConfig::GetInstance().
// or Pass region down to the EXI device creation.
std::string memcardFilename = (card_index == 0) ? SConfig::GetInstance().m_strMemoryCardA :
SConfig::GetInstance().m_strMemoryCardB;
std::string region = memcardFilename.substr(memcardFilename.size() - 7, 3);
if (region == JAP_DIR)
{
country_code = DiscIO::Country::COUNTRY_JAPAN;
shift_jis = true;
strDirectoryName += JAP_DIR DIR_SEP;
break;
}
else if (region == USA_DIR)
{
country_code = DiscIO::Country::COUNTRY_USA;
strDirectoryName += USA_DIR DIR_SEP;
break;
}
}
default:
country_code = DiscIO::Country::COUNTRY_EUROPE;
strDirectoryName += EUR_DIR DIR_SEP;
}
strDirectoryName += StringFromFormat("Card %c", 'A' + card_index);
const bool shift_jis = region == DiscIO::Region::NTSC_J;
std::string strDirectoryName = File::GetUserPath(D_GCUSER_IDX) +
SConfig::GetDirectoryForRegion(region) + DIR_SEP +
StringFromFormat("Card %c", 'A' + card_index);
if (!File::Exists(strDirectoryName)) // first use of memcard folder, migrate automatically
{
@ -234,16 +179,15 @@ void CEXIMemoryCard::SetupGciFolder(u16 sizeMb)
else // we tried but the user wants to crash
{
// TODO more user friendly abort
PanicAlertT("%s is not a directory, failed to move to *.original.\n Verify your write "
"permissions or move "
"the file outside of Dolphin",
PanicAlertT("%s is not a directory, failed to move to *.original.\n Verify your "
"write permissions or move the file outside of Dolphin",
strDirectoryName.c_str());
exit(0);
}
}
memorycard = std::make_unique<GCMemcardDirectory>(strDirectoryName + DIR_SEP, card_index, sizeMb,
shift_jis, country_code, CurrentGameId);
shift_jis, region, CurrentGameId);
}
void CEXIMemoryCard::SetupRawMemcard(u16 sizeMb)

View File

@ -108,7 +108,7 @@ struct Header // Offset Size Description
// end Serial in libogc
u8 deviceID[2]; // 0x0020 2 0 if formated in slot A 1 if formated in slot B
u8 SizeMb[2]; // 0x0022 2 Size of memcard in Mbits
u16 Encoding; // 0x0024 2 Encoding (ASCII or Japanese)
u16 Encoding; // 0x0024 2 Encoding (Windows-1252 or Shift JIS)
u8 Unused1[468]; // 0x0026 468 Unused (0xff)
u16 UpdateCounter; // 0x01fa 2 Update Counter (?, probably unused)
u16 Checksum; // 0x01fc 2 Additive Checksum

View File

@ -24,7 +24,7 @@
const int NO_INDEX = -1;
static const char* MC_HDR = "MC_SYSTEM_AREA";
int GCMemcardDirectory::LoadGCI(const std::string& fileName, DiscIO::Country card_region,
int GCMemcardDirectory::LoadGCI(const std::string& fileName, DiscIO::Region card_region,
bool currentGameOnly)
{
File::IOFile gcifile(fileName, "rb");
@ -39,27 +39,12 @@ int GCMemcardDirectory::LoadGCI(const std::string& fileName, DiscIO::Country car
return NO_INDEX;
}
DiscIO::Country gci_region;
// check region
switch (gci.m_gci_header.Gamecode[3])
{
case 'J':
gci_region = DiscIO::Country::COUNTRY_JAPAN;
break;
case 'E':
gci_region = DiscIO::Country::COUNTRY_USA;
break;
case 'C':
// Used by Datel Action Replay Save
// can be on any regions card
gci_region = card_region;
break;
default:
gci_region = DiscIO::Country::COUNTRY_EUROPE;
break;
}
if (gci_region != card_region)
DiscIO::Region gci_region = DiscIO::RegionSwitchGC(gci.m_gci_header.Gamecode[3]);
// Some special save files have game IDs that we parse as UNKNOWN_REGION. For instance:
// - Datel Action Replay uses C as the fourth character. (Can be on any region's card.)
// - Homeland's network config file only uses null bytes. (Homeland is exclusive to Japan,
// but maybe the network config file ID was intended to be used in other regions too.)
if (card_region != gci_region && gci_region != DiscIO::Region::UNKNOWN_REGION)
{
PanicAlertT(
"GCI save file was not loaded because it is the wrong region for this memory card:\n%s",
@ -146,7 +131,7 @@ int GCMemcardDirectory::LoadGCI(const std::string& fileName, DiscIO::Country car
}
GCMemcardDirectory::GCMemcardDirectory(const std::string& directory, int slot, u16 sizeMb,
bool shift_jis, DiscIO::Country card_region, int gameId)
bool shift_jis, DiscIO::Region card_region, int gameId)
: MemoryCardBase(slot, sizeMb), m_GameId(gameId), m_LastBlock(-1),
m_hdr(slot, sizeMb, shift_jis), m_bat1(sizeMb), m_saves(0), m_SaveDirectory(directory),
m_exiting(false)

View File

@ -22,9 +22,8 @@ void MigrateFromMemcardFile(const std::string& strDirectoryName, int card_index)
class GCMemcardDirectory : public MemoryCardBase, NonCopyable
{
public:
GCMemcardDirectory(const std::string& directory, int slot = 0, u16 sizeMb = MemCard2043Mb,
bool shift_jis = false,
DiscIO::Country card_region = DiscIO::Country::COUNTRY_EUROPE, int gameId = 0);
GCMemcardDirectory(const std::string& directory, int slot, u16 sizeMb, bool shift_jis,
DiscIO::Region card_region, int gameId);
~GCMemcardDirectory();
void FlushToFile();
void FlushThread();
@ -35,7 +34,7 @@ public:
void DoState(PointerWrap& p) override;
private:
int LoadGCI(const std::string& fileName, DiscIO::Country card_region, bool currentGameOnly);
int LoadGCI(const std::string& fileName, DiscIO::Region card_region, bool currentGameOnly);
inline s32 SaveAreaRW(u32 block, bool writing = false);
// s32 DirectoryRead(u32 offset, u32 length, u8* destaddress);
s32 DirectoryWrite(u32 destaddress, u32 length, u8* srcaddress);

View File

@ -8,6 +8,7 @@
#include "Common/CommonTypes.h"
#include "Common/Logging/Log.h"
#include "Common/MathUtil.h"
#include "Core/ConfigManager.h"
#include "Core/Core.h"
#include "Core/CoreTiming.h"
@ -16,6 +17,9 @@
#include "Core/HW/SI.h"
#include "Core/HW/SystemTimers.h"
#include "Core/HW/VideoInterface.h"
#include "DiscIO/Enums.h"
#include "VideoCommon/VideoBackendBase.h"
#include "VideoCommon/VideoConfig.h"
@ -167,12 +171,14 @@ void Preset(bool _bNTSC)
m_FilterCoefTables = {};
m_UnkAARegister = 0;
DiscIO::Region region = SConfig::GetInstance().m_region;
// 54MHz, capable of progressive scan
m_Clock = SConfig::GetInstance().bNTSC;
m_Clock = DiscIO::IsNTSC(region);
// Say component cable is plugged
m_DTVStatus.component_plugged = SConfig::GetInstance().bProgressive;
m_DTVStatus.ntsc_j = SConfig::GetInstance().bForceNTSCJ;
m_DTVStatus.ntsc_j = SConfig::GetInstance().bForceNTSCJ || region == DiscIO::Region::NTSC_J;
m_FBWidth.Hex = 0;
m_BorderHBlank.Hex = 0;
@ -408,12 +414,6 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
}
}
void SetRegionReg(char region)
{
if (!SConfig::GetInstance().bForceNTSCJ)
m_DTVStatus.ntsc_j = region == 'J';
}
void UpdateInterrupts()
{
if ((m_InterruptRegister[0].IR_INT && m_InterruptRegister[0].IR_MASK) ||

View File

@ -343,7 +343,6 @@ union UVIHorizontalStepping
void Preset(bool _bNTSC);
void Init();
void SetRegionReg(char region);
void DoState(PointerWrap& p);
void RegisterMMIO(MMIO::Mapping* mmio, u32 base);

View File

@ -11,8 +11,57 @@
namespace DiscIO
{
bool IsNTSC(Region region)
{
return region == Region::NTSC_J || region == Region::NTSC_U || region == Region::NTSC_K;
}
// Increment CACHE_REVISION (ISOFile.cpp & GameFile.cpp) if the code below is modified
Region RegionSwitchGC(u8 country_code)
{
Region region = RegionSwitchWii(country_code);
return region == Region::NTSC_K ? Region::UNKNOWN_REGION : region;
}
Region RegionSwitchWii(u8 country_code)
{
switch (country_code)
{
case 'J':
case 'W':
return Region::NTSC_J;
case 'B':
case 'E':
case 'N':
case 'Z':
return Region::NTSC_U;
case 'D':
case 'F':
case 'H':
case 'I':
case 'L':
case 'M':
case 'P':
case 'R':
case 'S':
case 'U':
case 'X':
case 'Y':
return Region::PAL;
case 'K':
case 'Q':
case 'T':
return Region::NTSC_K;
default:
return Region::UNKNOWN_REGION;
}
}
Country CountrySwitch(u8 country_code)
{
switch (country_code)

View File

@ -38,6 +38,16 @@ enum class Country
NUMBER_OF_COUNTRIES
};
// Regions 0 - 2 and 4 match Nintendo's Wii region numbering.
enum class Region
{
NTSC_J = 0, // Japan and Taiwan
NTSC_U = 1, // Mainly North America
PAL = 2, // Mainly Europe and Oceania
UNKNOWN_REGION = 3, // 3 seems to be unused? Anyway, we need an UNKNOWN_REGION. Let's put it here
NTSC_K = 4 // South Korea (Wii only)
};
// Languages 0 - 9 match Nintendo's Wii language numbering.
// Languages 1 - 6 match Nintendo's PAL GameCube languages 0 - 5.
// NTSC GameCubes only support one language and thus don't number languages.
@ -56,6 +66,9 @@ enum class Language
LANGUAGE_UNKNOWN
};
bool IsNTSC(Region region);
Region RegionSwitchGC(u8 country_code);
Region RegionSwitchWii(u8 country_code);
Country CountrySwitch(u8 country_code);
u8 GetSysMenuRegion(u16 title_version);
std::string GetCompanyFromID(const std::string& company_id);

View File

@ -311,12 +311,12 @@ std::vector<u8> CNANDContentLoader::GetKeyFromTicket(const std::vector<u8>& tick
return AESDecode(common_key, iv, &ticket[0x01BF], 16);
}
DiscIO::Country CNANDContentLoader::GetCountry() const
DiscIO::Region CNANDContentLoader::GetRegion() const
{
if (!IsValid())
return DiscIO::Country::COUNTRY_UNKNOWN;
return DiscIO::Region::UNKNOWN_REGION;
return CountrySwitch(m_Country);
return RegionSwitchWii(m_Country);
}
CNANDContentManager::~CNANDContentManager()

View File

@ -20,7 +20,7 @@ class IOFile;
namespace DiscIO
{
enum class Country;
enum class Region;
bool AddTicket(u64 title_id, const std::vector<u8>& ticket);
@ -94,7 +94,7 @@ public:
const std::vector<SNANDContent>& GetContent() const { return m_Content; }
u16 GetTitleVersion() const { return m_TitleVersion; }
u16 GetNumEntries() const { return m_NumEntries; }
DiscIO::Country GetCountry() const;
DiscIO::Region GetRegion() const;
u8 GetCountryChar() const { return m_Country; }
enum
{

View File

@ -55,6 +55,7 @@ public:
virtual bool SupportsIntegrityCheck() const { return false; }
virtual bool CheckIntegrity() const { return false; }
virtual bool ChangePartition(u64 offset) { return false; }
virtual Region GetRegion() const = 0;
virtual Country GetCountry() const = 0;
virtual BlobType GetBlobType() const = 0;
// Size of virtual disc (not always accurate)
@ -71,12 +72,7 @@ protected:
// strnlen to trim NULLs
std::string string(data, strnlen(data, sizeof(data)));
// There doesn't seem to be any GC discs with the country set to Taiwan...
// But maybe they would use Shift_JIS if they existed? Not sure
bool use_shift_jis =
(Country::COUNTRY_JAPAN == GetCountry() || Country::COUNTRY_TAIWAN == GetCountry());
if (use_shift_jis)
if (GetRegion() == Region::NTSC_J)
return SHIFTJISToUTF8(string);
else
return CP1252ToUTF8(string);

View File

@ -166,6 +166,14 @@ void CVolumeDirectory::SetGameID(const std::string& id)
memcpy(m_disk_header.data(), id.c_str(), std::min(id.length(), MAX_ID_LENGTH));
}
Region CVolumeDirectory::GetRegion() const
{
if (m_is_wii)
return RegionSwitchWii(m_disk_header[3]);
return RegionSwitchGC(m_disk_header[3]);
}
Country CVolumeDirectory::GetCountry() const
{
return CountrySwitch(m_disk_header[3]);

View File

@ -26,6 +26,7 @@ namespace DiscIO
enum class BlobType;
enum class Country;
enum class Language;
enum class Region;
enum class Platform;
class CVolumeDirectory : public IVolume
@ -56,6 +57,7 @@ public:
std::string GetApploaderDate() const override;
Platform GetVolumeType() const override;
Region GetRegion() const override;
Country GetCountry() const override;
BlobType GetBlobType() const override;

View File

@ -61,13 +61,20 @@ std::string CVolumeGC::GetGameID() const
return DecodeString(ID);
}
Region CVolumeGC::GetRegion() const
{
u8 country_code;
if (!m_pReader->Read(3, 1, &country_code))
return Region::UNKNOWN_REGION;
return RegionSwitchGC(country_code);
}
Country CVolumeGC::GetCountry() const
{
if (!m_pReader)
return Country::COUNTRY_UNKNOWN;
u8 country_code;
m_pReader->Read(3, 1, &country_code);
if (!m_pReader->Read(3, 1, &country_code))
return Country::COUNTRY_UNKNOWN;
return CountrySwitch(country_code);
}
@ -247,7 +254,7 @@ void CVolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bn
if (is_bnr1) // NTSC
{
bool is_japanese = GetCountry() == Country::COUNTRY_JAPAN;
bool is_japanese = GetRegion() == Region::NTSC_J;
number_of_languages = 1;
start_language = is_japanese ? Language::LANGUAGE_JAPANESE : Language::LANGUAGE_ENGLISH;
}

View File

@ -19,6 +19,7 @@ namespace DiscIO
enum class BlobType;
enum class Country;
enum class Language;
enum class Region;
enum class Platform;
class CVolumeGC : public IVolume
@ -42,6 +43,7 @@ public:
u8 GetDiscNumber() const override;
Platform GetVolumeType() const override;
Region GetRegion() const override;
Country GetCountry() const override;
BlobType GetBlobType() const override;
u64 GetSize() const override;

View File

@ -57,14 +57,21 @@ bool CVolumeWAD::Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) cons
return m_pReader->Read(_Offset, _Length, _pBuffer);
}
Region CVolumeWAD::GetRegion() const
{
u8 country_code;
if (!Read(m_tmd_offset + 0x0193, 1, &country_code))
return Region::UNKNOWN_REGION;
return RegionSwitchWii(country_code);
}
Country CVolumeWAD::GetCountry() const
{
if (!m_pReader)
return Country::COUNTRY_UNKNOWN;
// read the last digit of the titleID in the ticket
u8 country_code;
Read(m_tmd_offset + 0x0193, 1, &country_code);
if (!Read(m_tmd_offset + 0x0193, 1, &country_code))
return Country::COUNTRY_UNKNOWN;
if (country_code == 2) // SYSMENU
{

View File

@ -21,6 +21,7 @@ namespace DiscIO
enum class BlobType;
enum class Country;
enum class Language;
enum class Region;
enum class Platform;
class CVolumeWAD : public IVolume
@ -39,6 +40,7 @@ public:
u64 GetFSTSize() const override { return 0; }
std::string GetApploaderDate() const override { return ""; }
Platform GetVolumeType() const override;
Region GetRegion() const override;
Country GetCountry() const override;
BlobType GetBlobType() const override;

View File

@ -153,51 +153,38 @@ std::string CVolumeWiiCrypted::GetGameID() const
return DecodeString(ID);
}
Region CVolumeWiiCrypted::GetRegion() const
{
u32 region_code;
if (!ReadSwapped(0x4E000, &region_code, false))
return Region::UNKNOWN_REGION;
return static_cast<Region>(region_code);
}
Country CVolumeWiiCrypted::GetCountry() const
{
if (!m_pReader)
return Country::COUNTRY_UNKNOWN;
u8 country_byte;
if (!m_pReader->Read(3, 1, &country_byte))
return Country::COUNTRY_UNKNOWN;
Country country_value = CountrySwitch(country_byte);
const Region region = GetRegion();
u32 region_code;
if (!ReadSwapped(0x4E000, &region_code, false))
return country_value;
if (RegionSwitchWii(country_byte) == region)
return CountrySwitch(country_byte);
switch (region_code)
switch (region)
{
case 0:
switch (country_value)
{
case Country::COUNTRY_TAIWAN:
return Country::COUNTRY_TAIWAN;
default:
return Country::COUNTRY_JAPAN;
}
case 1:
case Region::NTSC_J:
return Country::COUNTRY_JAPAN;
case Region::NTSC_U:
return Country::COUNTRY_USA;
case 2:
switch (country_value)
{
case Country::COUNTRY_FRANCE:
case Country::COUNTRY_GERMANY:
case Country::COUNTRY_ITALY:
case Country::COUNTRY_NETHERLANDS:
case Country::COUNTRY_RUSSIA:
case Country::COUNTRY_SPAIN:
case Country::COUNTRY_AUSTRALIA:
return country_value;
default:
return Country::COUNTRY_EUROPE;
}
case 4:
case Region::PAL:
return Country::COUNTRY_EUROPE;
case Region::NTSC_K:
return Country::COUNTRY_KOREA;
default:
return country_value;
return Country::COUNTRY_UNKNOWN;
}
}

View File

@ -20,6 +20,7 @@ namespace DiscIO
enum class BlobType;
enum class Country;
enum class Language;
enum class Region;
enum class Platform;
class CVolumeWiiCrypted : public IVolume
@ -46,6 +47,7 @@ public:
bool CheckIntegrity() const override;
bool ChangePartition(u64 offset) override;
Region GetRegion() const override;
Country GetCountry() const override;
BlobType GetBlobType() const override;
u64 GetSize() const override;

View File

@ -155,6 +155,7 @@ bool GameFile::TryLoadVolume()
m_descriptions = ConvertLanguageMap(volume->GetDescriptions());
m_disc_number = volume->GetDiscNumber();
m_platform = volume->GetVolumeType();
m_region = volume->GetRegion();
m_country = volume->GetCountry();
m_blob_type = volume->GetBlobType();
m_raw_size = volume->GetRawSize();
@ -174,6 +175,7 @@ bool GameFile::TryLoadElfDol()
m_revision = 0;
m_long_names[DiscIO::Language::LANGUAGE_ENGLISH] = m_file_name;
m_platform = DiscIO::Platform::ELF_DOL;
m_region = DiscIO::Region::UNKNOWN_REGION;
m_country = DiscIO::Country::COUNTRY_UNKNOWN;
m_blob_type = DiscIO::BlobType::DIRECTORY;
m_raw_size = m_size;

View File

@ -16,6 +16,7 @@ namespace DiscIO
enum class BlobType;
enum class Country;
enum class Language;
enum class Region;
enum class Platform;
class IVolume;
}
@ -47,6 +48,7 @@ public:
QString GetApploaderDate() const { return m_apploader_date; }
DiscIO::Platform GetPlatformID() const { return m_platform; }
QString GetPlatform() const;
DiscIO::Region GetRegion() const { return m_region; }
DiscIO::Country GetCountryID() const { return m_country; }
QString GetCountry() const;
DiscIO::BlobType GetBlobType() const { return m_blob_type; }
@ -96,6 +98,7 @@ private:
QMap<DiscIO::Language, QString> m_descriptions;
QString m_company;
u8 m_disc_number = 0;
DiscIO::Region m_region;
DiscIO::Platform m_platform;
DiscIO::Country m_country;
DiscIO::BlobType m_blob_type;

View File

@ -36,7 +36,7 @@
#include "DolphinWX/ISOFile.h"
#include "DolphinWX/WxUtils.h"
static const u32 CACHE_REVISION = 0x127; // Last changed in PR 3309
static const u32 CACHE_REVISION = 0x128; // Last changed in PR 4542
static std::string GetLanguageString(DiscIO::Language language,
std::map<DiscIO::Language, std::string> strings)
@ -64,8 +64,9 @@ static std::string GetLanguageString(DiscIO::Language language,
GameListItem::GameListItem(const std::string& _rFileName,
const std::unordered_map<std::string, std::string>& custom_titles)
: m_FileName(_rFileName), m_title_id(0), m_emu_state(0), m_FileSize(0),
m_Country(DiscIO::Country::COUNTRY_UNKNOWN), m_Revision(0), m_Valid(false), m_ImageWidth(0),
m_ImageHeight(0), m_disc_number(0), m_has_custom_name(false)
m_region(DiscIO::Region::UNKNOWN_REGION), m_Country(DiscIO::Country::COUNTRY_UNKNOWN),
m_Revision(0), m_Valid(false), m_ImageWidth(0), m_ImageHeight(0), m_disc_number(0),
m_has_custom_name(false)
{
if (LoadFromCache())
{
@ -99,6 +100,7 @@ GameListItem::GameListItem(const std::string& _rFileName,
if (m_company.empty())
m_company = GetLanguageString(DiscIO::Language::LANGUAGE_ENGLISH, volume->GetShortMakers());
m_region = volume->GetRegion();
m_Country = volume->GetCountry();
m_blob_type = volume->GetBlobType();
m_FileSize = volume->GetRawSize();
@ -214,6 +216,7 @@ void GameListItem::DoState(PointerWrap& p)
p.Do(m_title_id);
p.Do(m_FileSize);
p.Do(m_VolumeSize);
p.Do(m_region);
p.Do(m_Country);
p.Do(m_blob_type);
p.Do(m_pImage);

View File

@ -21,6 +21,7 @@ namespace DiscIO
enum class BlobType;
enum class Country;
enum class Language;
enum class Region;
enum class Platform;
}
@ -48,6 +49,7 @@ public:
u16 GetRevision() const { return m_Revision; }
const std::string& GetGameID() const { return m_game_id; }
const std::string GetWiiFSPath() const;
DiscIO::Region GetRegion() const { return m_region; }
DiscIO::Country GetCountry() const { return m_Country; }
DiscIO::Platform GetPlatform() const { return m_Platform; }
DiscIO::BlobType GetBlobType() const { return m_blob_type; }
@ -82,6 +84,7 @@ private:
u64 m_FileSize;
u64 m_VolumeSize;
DiscIO::Region m_region;
DiscIO::Country m_Country;
DiscIO::Platform m_Platform;
DiscIO::BlobType m_blob_type;