Add Taiwan to the Country Codes, move all country code switches to one function, add unk country flag and taiwan country flag

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3666 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
LPFaint99 2009-07-03 22:34:51 +00:00
parent 15e4eed7fa
commit 4c86d218c1
15 changed files with 762 additions and 737 deletions

View File

@ -65,11 +65,11 @@ void CBoot::EmulatedBIOS(bool _bDebug)
// //
DVDInterface::DVDRead(0x00000000, 0x80000000, 10); // write boot info needed for multidisc games DVDInterface::DVDRead(0x00000000, 0x80000000, 10); // write boot info needed for multidisc games
Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi
Memory::Write_U32(0xc2339f3d, 0x8000001C); // game disc Memory::Write_U32(0xc2339f3d, 0x8000001C); // game disc
Memory::Write_U32(0x0D15EA5E, 0x80000020); // booted from bootrom. 0xE5207C22 = booted from jtag Memory::Write_U32(0x0D15EA5E, 0x80000020); // booted from bootrom. 0xE5207C22 = booted from jtag
Memory::Write_U32(0x01800000, 0x80000028); // Physical Memory Size Memory::Write_U32(0x01800000, 0x80000028); // Physical Memory Size
// On any of the production boards, ikaruga fails to read the memcard the first time. It succeeds on the second time though. // On any of the production boards, ikaruga fails to read the memcard the first time. It succeeds on the second time though.
@ -83,9 +83,9 @@ void CBoot::EmulatedBIOS(bool _bDebug)
// Load Apploader to Memory - The apploader is hardcoded to begin at byte 9 280 on the disc, // Load Apploader to Memory - The apploader is hardcoded to begin at byte 9 280 on the disc,
// but it seems like the size can be variable. Compare with yagcd chap 13. // but it seems like the size can be variable. Compare with yagcd chap 13.
//
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
u32 iAppLoaderOffset = 0x2440; // 0x1c40 - 2MB lower...perhaps used on early GCMs? MYSTERY OLD COMMENT u32 iAppLoaderOffset = 0x2440; // 0x1c40 - 2MB lower...perhaps used on early GCMs? MYSTERY OLD COMMENT
u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10); u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10);
u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14); u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14);
if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1)) if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1))
@ -98,15 +98,15 @@ void CBoot::EmulatedBIOS(bool _bDebug)
u32 iAppLoaderFuncAddr = 0x80003100; u32 iAppLoaderFuncAddr = 0x80003100;
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0; PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4; PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8; PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(iAppLoaderEntry); RunFunction(iAppLoaderEntry);
u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 0); u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 0);
u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 4); u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 4);
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 8); u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 8);
// iAppLoaderInit // iAppLoaderInit
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit"); DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit");
PowerPC::ppcState.gpr[3] = 0x81300000; PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit); RunFunction(iAppLoaderInit);
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem). // iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
@ -141,136 +141,139 @@ void CBoot::EmulatedBIOS(bool _bDebug)
// return // return
PC = PowerPC::ppcState.gpr[3]; PC = PowerPC::ppcState.gpr[3];
// --- preinit some stuff from bios --- // --- preinit some stuff from bios ---
// Bus Clock Speed // Bus Clock Speed
Memory::Write_U32(0x09a7ec80, 0x800000F8); Memory::Write_U32(0x09a7ec80, 0x800000F8);
// CPU Clock Speed // CPU Clock Speed
Memory::Write_U32(0x1cf7c580, 0x800000FC); Memory::Write_U32(0x1cf7c580, 0x800000FC);
// fake the VI Init of the BIOS // fake the VI Init of the BIOS
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC
? 0 : 1, 0x800000CC); ? 0 : 1, 0x800000CC);
// preset time base ticks // preset time base ticks
Memory::Write_U64( (u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); Memory::Write_U64( (u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8);
} }
bool CBoot::SetupWiiMemory(unsigned int _CountryCode) bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
{ {
INFO_LOG(BOOT, "Setup Wii Memory..."); INFO_LOG(BOOT, "Setup Wii Memory...");
// Write the 256 byte setting.txt to memory. This may not be needed as // Write the 256 byte setting.txt to memory. This may not be needed as
// most or all games read the setting.txt file from // most or all games read the setting.txt file from
// \title\00000001\00000002\data\setting.txt directly after the read the // \title\00000001\00000002\data\setting.txt directly after the read the
// SYSCONF file. The games also read it to 0x3800, what is a little strange // SYSCONF file. The games also read it to 0x3800, what is a little strange
// however is that it only reads the first 100 bytes of it. // however is that it only reads the first 100 bytes of it.
std::string filename(File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_EUR_SETTING); std::string filename(File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_EUR_SETTING);
switch((DiscIO::IVolume::ECountry)_CountryCode) switch((DiscIO::IVolume::ECountry)_CountryCode)
{ {
case DiscIO::IVolume::COUNTRY_JAP: case DiscIO::IVolume::COUNTRY_KOREA:
filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_JAP_SETTING; case DiscIO::IVolume::COUNTRY_TAIWAN:
break; // TODO: Determine if Korea / Taiwan have their own specific settings.
case DiscIO::IVolume::COUNTRY_JAPAN:
filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_JAP_SETTING;
break;
case DiscIO::IVolume::COUNTRY_USA: case DiscIO::IVolume::COUNTRY_USA:
filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_USA_SETTING; filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_USA_SETTING;
break; break;
case DiscIO::IVolume::COUNTRY_EUROPE: case DiscIO::IVolume::COUNTRY_EUROPE:
filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_EUR_SETTING; filename = File::GetSysDirectory() + WII_SYS_DIR + DIR_SEP + WII_EUR_SETTING;
break; break;
default: default:
// PanicAlert("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings."); // PanicAlert("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings.");
filename = WII_EUR_SETTING_FILE; filename = WII_EUR_SETTING_FILE;
break; break;
} }
FILE* pTmp = fopen(filename.c_str(), "rb"); FILE* pTmp = fopen(filename.c_str(), "rb");
if (!pTmp) if (!pTmp)
{ {
PanicAlert("SetupWiiMem: Cant find setting file"); PanicAlert("SetupWiiMem: Cant find setting file");
return false; return false;
} }
fread(Memory::GetPointer(0x3800), 256, 1, pTmp); fread(Memory::GetPointer(0x3800), 256, 1, pTmp);
fclose(pTmp); fclose(pTmp);
/* Set hardcoded global variables to Wii memory. These are partly collected from /* Set hardcoded global variables to Wii memory. These are partly collected from
Wiibrew. These values are needed for the games to function correctly. A few Wiibrew. These values are needed for the games to function correctly. A few
values in this region will also be placed here by the game as it boots. values in this region will also be placed here by the game as it boots.
They are: They are:
// Strange values that I don't know the meaning of, all games write these // Strange values that I don't know the meaning of, all games write these
0x00 to 0x18: 0x029f0010 0x00 to 0x18: 0x029f0010
0x029f0033 0x029f0033
0x029f0034 0x029f0034
0x029f0035 0x029f0035
0x029f0036 0x029f0036
0x029f0037 0x029f0037
0x029f0038 0x029f0038
0x029f0039 // Replaces the previous 0x5d1c9ea3 magic word 0x029f0039 // Replaces the previous 0x5d1c9ea3 magic word
0x80000038 Start of FST 0x80000038 Start of FST
0x8000003c Size of FST Size 0x8000003c Size of FST Size
0x80000060 Copyright code */ 0x80000060 Copyright code */
DVDInterface::DVDRead(0x00000000, 0x00000000, 10); // Game Code DVDInterface::DVDRead(0x00000000, 0x00000000, 10); // Game Code
Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
Memory::Write_U32(0x00000001, 0x00000024); // Unknown Memory::Write_U32(0x00000001, 0x00000024); // Unknown
Memory::Write_U32(0x01800000, 0x00000028); // MEM1 size 24MB Memory::Write_U32(0x01800000, 0x00000028); // MEM1 size 24MB
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
Memory::Write_U32(0x00000000, 0x00000030); // Init Memory::Write_U32(0x00000000, 0x00000030); // Init
Memory::Write_U32(0x817FEC60, 0x00000034); // Init Memory::Write_U32(0x817FEC60, 0x00000034); // Init
// 38, 3C should get start, size of FST through apploader // 38, 3C should get start, size of FST through apploader
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
Memory::Write_U32(0x01800000, 0x000000f0); // "Simulated memory size" (debug mode?) Memory::Write_U32(0x01800000, 0x000000f0); // "Simulated memory size" (debug mode?)
Memory::Write_U32(0x8179b500, 0x000000f4); // __start Memory::Write_U32(0x8179b500, 0x000000f4); // __start
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
Memory::Write_U16(0x0000, 0x000030e6); // Console type Memory::Write_U16(0x0000, 0x000030e6); // Console type
Memory::Write_U32(0x00000000, 0x000030c0); // EXI Memory::Write_U32(0x00000000, 0x000030c0); // EXI
Memory::Write_U32(0x00000000, 0x000030c4); // EXI Memory::Write_U32(0x00000000, 0x000030c4); // EXI
Memory::Write_U32(0x00000000, 0x000030dc); // Time Memory::Write_U32(0x00000000, 0x000030dc); // Time
Memory::Write_U32(0x00000000, 0x000030d8); // Time Memory::Write_U32(0x00000000, 0x000030d8); // Time
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
Memory::Write_U32(0x01800000, 0x00003100); // BAT Memory::Write_U32(0x01800000, 0x00003100); // BAT
Memory::Write_U32(0x01800000, 0x00003104); // BAT Memory::Write_U32(0x01800000, 0x00003104); // BAT
Memory::Write_U32(0x00000000, 0x0000310c); // Init Memory::Write_U32(0x00000000, 0x0000310c); // Init
Memory::Write_U32(0x8179d500, 0x00003110); // Init Memory::Write_U32(0x8179d500, 0x00003110); // Init
Memory::Write_U32(0x04000000, 0x00003118); // Unknown Memory::Write_U32(0x04000000, 0x00003118); // Unknown
Memory::Write_U32(0x04000000, 0x0000311c); // BAT Memory::Write_U32(0x04000000, 0x0000311c); // BAT
Memory::Write_U32(0x93400000, 0x00003120); // BAT Memory::Write_U32(0x93400000, 0x00003120); // BAT
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type Memory::Write_U32(0x00000011, 0x00003138); // Console type
// 40 is copied from 88 after running apploader // 40 is copied from 88 after running apploader
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format
Memory::Write_U16(0x0113, 0x0000315e); // Apploader Memory::Write_U16(0x0113, 0x0000315e); // Apploader
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear) Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear)
Memory::Write_U8(0x80, 0x0000315c); // OSInit Memory::Write_U8(0x80, 0x0000315c); // OSInit
Memory::Write_U8(0x00, 0x00000006); // DVDInit Memory::Write_U8(0x00, 0x00000006); // DVDInit
Memory::Write_U8(0x00, 0x00000007); // DVDInit Memory::Write_U8(0x00, 0x00000007); // DVDInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit Memory::Write_U16(0x0000, 0x000030e0); // PADInit
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
// Fake the VI Init of the BIOS // Fake the VI Init of the BIOS
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC); Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC);
// Clear exception handler. Why? Don't we begin with only zeros? // Clear exception handler. Why? Don't we begin with only zeros?
for (int i = 0x3000; i <= 0x3038; i += 4) for (int i = 0x3000; i <= 0x3038; i += 4)
{ {
Memory::Write_U32(0x00000000, 0x80000000 + i); Memory::Write_U32(0x00000000, 0x80000000 + i);
} }
return true; return true;
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
@ -283,28 +286,28 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
{ {
INFO_LOG(BOOT, "Faking Wii BIOS..."); INFO_LOG(BOOT, "Faking Wii BIOS...");
// setup wii memory // setup wii memory
DiscIO::IVolume::ECountry CountryCode = DiscIO::IVolume::COUNTRY_UNKNOWN; DiscIO::IVolume::ECountry CountryCode = DiscIO::IVolume::COUNTRY_UNKNOWN;
if (VolumeHandler::IsValid()) if (VolumeHandler::IsValid())
CountryCode = VolumeHandler::GetVolume()->GetCountry(); CountryCode = VolumeHandler::GetVolume()->GetCountry();
if (SetupWiiMemory(CountryCode) == false) if (SetupWiiMemory(CountryCode) == false)
return false; return false;
// This is some kind of consistency check that is compared to the 0x00 // This is some kind of consistency check that is compared to the 0x00
// values as the game boots. This location keep the 4 byte ID for as long // values as the game boots. This location keep the 4 byte ID for as long
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime // as the game is running. The 6 byte ID at 0x00 is overwritten sometime
// after this check during booting. // after this check during booting.
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4); VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
// Execute the apploader // Execute the apploader
if (VolumeHandler::IsValid() && VolumeHandler::IsWii()) if (VolumeHandler::IsValid() && VolumeHandler::IsWii())
{ {
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr); UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
m_MSR.FP = 1; m_MSR.FP = 1;
Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi
Memory::Write_U32(((1 & 0x3f) << 26) | 2, 0x81300000); // HLE OSReport for Apploader Memory::Write_U32(((1 & 0x3f) << 26) | 2, 0x81300000); // HLE OSReport for Apploader

View File

@ -109,7 +109,10 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios)
Region = USA_DIR; Region = USA_DIR;
break; break;
case DiscIO::IVolume::COUNTRY_JAP: case DiscIO::IVolume::COUNTRY_TAIWAN:
case DiscIO::IVolume::COUNTRY_KOREA:
// TODO: Should these have their own Region Dir?
case DiscIO::IVolume::COUNTRY_JAPAN:
bNTSC = true; bNTSC = true;
Region = JAP_DIR; Region = JAP_DIR;
break; break;

View File

@ -536,6 +536,58 @@
RelativePath=".\Src\Volume.h" RelativePath=".\Src\Volume.h"
> >
</File> </File>
<File
RelativePath=".\Src\VolumeCommon.cpp"
>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
ForcedIncludeFiles="stdafx.h"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|x64"
>
<Tool
Name="VCCLCompilerTool"
ForcedIncludeFiles="stdafx.h"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
ForcedIncludeFiles="stdafx.h"
/>
</FileConfiguration>
<FileConfiguration
Name="Release|x64"
>
<Tool
Name="VCCLCompilerTool"
ForcedIncludeFiles="stdafx.h"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugFast|Win32"
>
<Tool
Name="VCCLCompilerTool"
ForcedIncludeFiles="stdafx.h"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugFast|x64"
>
<Tool
Name="VCCLCompilerTool"
ForcedIncludeFiles="stdafx.h"
/>
</FileConfiguration>
</File>
<File <File
RelativePath=".\Src\VolumeCreator.cpp" RelativePath=".\Src\VolumeCreator.cpp"
> >

View File

@ -31,48 +31,48 @@ namespace DiscIO
class CSharedContent class CSharedContent
{ {
public: public:
static CSharedContent& AccessInstance() { return m_Instance; }
std::string GetFilenameFromSHA1(u8* _pHash); static CSharedContent& AccessInstance() { return m_Instance; }
std::string GetFilenameFromSHA1(u8* _pHash);
private: private:
CSharedContent(); CSharedContent();
virtual ~CSharedContent(); virtual ~CSharedContent();
struct SElement struct SElement
{ {
u8 FileName[8]; u8 FileName[8];
u8 SHA1Hash[20]; u8 SHA1Hash[20];
}; };
std::vector<SElement> m_Elements; std::vector<SElement> m_Elements;
static CSharedContent m_Instance; static CSharedContent m_Instance;
}; };
CSharedContent CSharedContent::m_Instance; CSharedContent CSharedContent::m_Instance;
CSharedContent::CSharedContent() CSharedContent::CSharedContent()
{ {
char szFilename[1024]; char szFilename[1024];
sprintf(szFilename, "%sshared1/content.map", FULL_WII_USER_DIR); sprintf(szFilename, "%sshared1/content.map", FULL_WII_USER_DIR);
if (File::Exists(szFilename)) if (File::Exists(szFilename))
{ {
FILE* pFile = fopen(szFilename, "rb"); FILE* pFile = fopen(szFilename, "rb");
while(!feof(pFile)) while(!feof(pFile))
{ {
SElement Element; SElement Element;
if (fread(&Element, sizeof(SElement), 1, pFile) == 1) if (fread(&Element, sizeof(SElement), 1, pFile) == 1)
{ {
m_Elements.push_back(Element); m_Elements.push_back(Element);
} }
} }
} }
} }
CSharedContent::~CSharedContent() CSharedContent::~CSharedContent()
@ -80,18 +80,18 @@ CSharedContent::~CSharedContent()
std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash) std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash)
{ {
for (size_t i=0; i<m_Elements.size(); i++) for (size_t i=0; i<m_Elements.size(); i++)
{ {
if (memcmp(_pHash, m_Elements[i].SHA1Hash, 20) == 0) if (memcmp(_pHash, m_Elements[i].SHA1Hash, 20) == 0)
{ {
char szFilename[1024]; char szFilename[1024];
sprintf(szFilename, "%sshared1/%c%c%c%c%c%c%c%c.app", FULL_WII_USER_DIR, sprintf(szFilename, "%sshared1/%c%c%c%c%c%c%c%c.app", FULL_WII_USER_DIR,
m_Elements[i].FileName[0], m_Elements[i].FileName[1], m_Elements[i].FileName[2], m_Elements[i].FileName[3], m_Elements[i].FileName[0], m_Elements[i].FileName[1], m_Elements[i].FileName[2], m_Elements[i].FileName[3],
m_Elements[i].FileName[4], m_Elements[i].FileName[5], m_Elements[i].FileName[6], m_Elements[i].FileName[7]); m_Elements[i].FileName[4], m_Elements[i].FileName[5], m_Elements[i].FileName[6], m_Elements[i].FileName[7]);
return szFilename; return szFilename;
} }
} }
return "unk"; return "unk";
} }
@ -101,89 +101,89 @@ class CNANDContentLoader : public INANDContentLoader
{ {
public: public:
CNANDContentLoader(const std::string& _rName); CNANDContentLoader(const std::string& _rName);
virtual ~CNANDContentLoader(); virtual ~CNANDContentLoader();
bool IsValid() const { return m_Valid; } bool IsValid() const { return m_Valid; }
u64 GetTitleID() const { return m_TitleID; } u64 GetTitleID() const { return m_TitleID; }
u16 GetIosVersion() const { return m_IosVersion; } u16 GetIosVersion() const { return m_IosVersion; }
u32 GetBootIndex() const { return m_BootIndex; } u32 GetBootIndex() const { return m_BootIndex; }
size_t GetContentSize() const { return m_Content.size(); } size_t GetContentSize() const { return m_Content.size(); }
const SNANDContent* GetContentByIndex(int _Index) const; const SNANDContent* GetContentByIndex(int _Index) const;
const u8* GetTicketView() const { return m_TicketView; } const u8* GetTicketView() const { return m_TicketView; }
const u8* GetTmdHeader() const { return m_TmdHeader; } const u8* GetTmdHeader() const { return m_TmdHeader; }
const std::vector<SNANDContent>& GetContent() const { return m_Content; } const std::vector<SNANDContent>& GetContent() const { return m_Content; }
const u16 GetTitleVersion() const {return m_TileVersion;} const u16 GetTitleVersion() const {return m_TileVersion;}
const u16 GetNumEntries() const {return m_numEntries;} const u16 GetNumEntries() const {return m_numEntries;}
const DiscIO::IVolume::ECountry GetCountry() const; const DiscIO::IVolume::ECountry GetCountry() const;
private: private:
bool m_Valid; bool m_Valid;
u64 m_TitleID; u64 m_TitleID;
u16 m_IosVersion; u16 m_IosVersion;
u32 m_BootIndex; u32 m_BootIndex;
u16 m_numEntries; u16 m_numEntries;
u16 m_TileVersion; u16 m_TileVersion;
u8 m_TicketView[TICKET_VIEW_SIZE]; u8 m_TicketView[TICKET_VIEW_SIZE];
u8 m_TmdHeader[TMD_HEADER_SIZE]; u8 m_TmdHeader[TMD_HEADER_SIZE];
std::vector<SNANDContent> m_Content; std::vector<SNANDContent> m_Content;
bool CreateFromDirectory(const std::string& _rPath); bool CreateFromDirectory(const std::string& _rPath);
bool CreateFromWAD(const std::string& _rName); bool CreateFromWAD(const std::string& _rName);
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest); void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest);
void GetKeyFromTicket(u8* pTicket, u8* pTicketKey); void GetKeyFromTicket(u8* pTicket, u8* pTicketKey);
bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD); bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD);
}; };
CNANDContentLoader::CNANDContentLoader(const std::string& _rName) CNANDContentLoader::CNANDContentLoader(const std::string& _rName)
: m_TitleID(-1) : m_TitleID(-1)
, m_BootIndex(-1) , m_BootIndex(-1)
, m_Valid(false) , m_Valid(false)
, m_IosVersion(0x09) , m_IosVersion(0x09)
{ {
if (File::IsDirectory(_rName.c_str())) if (File::IsDirectory(_rName.c_str()))
{ {
m_Valid = CreateFromDirectory(_rName); m_Valid = CreateFromDirectory(_rName);
} }
else if (File::Exists(_rName.c_str())) else if (File::Exists(_rName.c_str()))
{ {
m_Valid = CreateFromWAD(_rName); m_Valid = CreateFromWAD(_rName);
} }
else else
{ {
// _dbg_assert_msg_(BOOT, 0, "CNANDContentLoader loads neither folder nor file"); // _dbg_assert_msg_(BOOT, 0, "CNANDContentLoader loads neither folder nor file");
} }
} }
CNANDContentLoader::~CNANDContentLoader() CNANDContentLoader::~CNANDContentLoader()
{ {
for (size_t i=0; i<m_Content.size(); i++) for (size_t i=0; i<m_Content.size(); i++)
{ {
delete [] m_Content[i].m_pData; delete [] m_Content[i].m_pData;
} }
m_Content.clear(); m_Content.clear();
} }
const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const
{ {
for (size_t i=0; i<m_Content.size(); i++) for (size_t i=0; i<m_Content.size(); i++)
{ {
if (m_Content[i].m_Index == _Index) if (m_Content[i].m_Index == _Index)
return &m_Content[i]; return &m_Content[i];
} }
return NULL; return NULL;
} }
bool CNANDContentLoader::CreateFromWAD(const std::string& _rName) bool CNANDContentLoader::CreateFromWAD(const std::string& _rName)
@ -197,93 +197,93 @@ bool CNANDContentLoader::CreateFromWAD(const std::string& _rName)
bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath) bool CNANDContentLoader::CreateFromDirectory(const std::string& _rPath)
{ {
std::string TMDFileName(_rPath); std::string TMDFileName(_rPath);
TMDFileName += "/title.tmd"; TMDFileName += "/title.tmd";
FILE* pTMDFile = fopen(TMDFileName.c_str(), "rb"); FILE* pTMDFile = fopen(TMDFileName.c_str(), "rb");
if (pTMDFile == NULL) { if (pTMDFile == NULL) {
ERROR_LOG(DISCIO, "CreateFromDirectory: error opening %s", ERROR_LOG(DISCIO, "CreateFromDirectory: error opening %s",
TMDFileName.c_str()); TMDFileName.c_str());
return false; return false;
} }
u64 Size = File::GetSize(TMDFileName.c_str()); u64 Size = File::GetSize(TMDFileName.c_str());
u8* pTMD = new u8[(u32)Size]; u8* pTMD = new u8[(u32)Size];
fread(pTMD, (size_t)Size, 1, pTMDFile); fread(pTMD, (size_t)Size, 1, pTMDFile);
fclose(pTMDFile); fclose(pTMDFile);
memcpy(m_TicketView, pTMD + 0x180, TICKET_VIEW_SIZE); memcpy(m_TicketView, pTMD + 0x180, TICKET_VIEW_SIZE);
memcpy(m_TmdHeader, pTMD, TMD_HEADER_SIZE); memcpy(m_TmdHeader, pTMD, TMD_HEADER_SIZE);
////// //////
m_TileVersion = Common::swap16(pTMD + 0x01dc); m_TileVersion = Common::swap16(pTMD + 0x01dc);
m_numEntries = Common::swap16(pTMD + 0x01de); m_numEntries = Common::swap16(pTMD + 0x01de);
m_BootIndex = Common::swap16(pTMD + 0x01e0); m_BootIndex = Common::swap16(pTMD + 0x01e0);
m_TitleID = Common::swap64(pTMD + 0x018c); m_TitleID = Common::swap64(pTMD + 0x018c);
m_IosVersion = Common::swap16(pTMD + 0x018a); m_IosVersion = Common::swap16(pTMD + 0x018a);
m_Content.resize(m_numEntries); m_Content.resize(m_numEntries);
for (u32 i = 0; i < m_numEntries; i++) for (u32 i = 0; i < m_numEntries; i++)
{ {
SNANDContent& rContent = m_Content[i]; SNANDContent& rContent = m_Content[i];
rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i); rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i);
rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i); rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i);
rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i); rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i);
rContent.m_Size = (u32)Common::swap64(pTMD + 0x01ec + 0x24*i); rContent.m_Size = (u32)Common::swap64(pTMD + 0x01ec + 0x24*i);
memcpy(rContent.m_SHA1Hash, pTMD + 0x01f4 + 0x24*i, 20); memcpy(rContent.m_SHA1Hash, pTMD + 0x01f4 + 0x24*i, 20);
memcpy(rContent.m_Header, pTMD + 0x01e4 + 0x24*i, 36); memcpy(rContent.m_Header, pTMD + 0x01e4 + 0x24*i, 36);
rContent.m_pData = NULL; rContent.m_pData = NULL;
char szFilename[1024]; char szFilename[1024];
if (rContent.m_Type & 0x8000) // shared app if (rContent.m_Type & 0x8000) // shared app
{ {
std::string Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash); std::string Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash);
strcpy(szFilename, Filename.c_str()); strcpy(szFilename, Filename.c_str());
} }
else else
{ {
sprintf(szFilename, "%s/%08x.app", _rPath.c_str(), rContent.m_ContentID); sprintf(szFilename, "%s/%08x.app", _rPath.c_str(), rContent.m_ContentID);
} }
INFO_LOG(DISCIO, "NANDContentLoader: load %s", szFilename); INFO_LOG(DISCIO, "NANDContentLoader: load %s", szFilename);
FILE* pFile = fopen(szFilename, "rb"); FILE* pFile = fopen(szFilename, "rb");
if (pFile != NULL) if (pFile != NULL)
{ {
u64 Size = File::GetSize(szFilename); u64 Size = File::GetSize(szFilename);
rContent.m_pData = new u8[(u32)Size]; rContent.m_pData = new u8[(u32)Size];
_dbg_assert_msg_(BOOT, rContent.m_Size==Size, "TMDLoader: Filesize doesnt fit (%s %i)... prolly you have a bad dump", szFilename, i); _dbg_assert_msg_(BOOT, rContent.m_Size==Size, "TMDLoader: Filesize doesnt fit (%s %i)... prolly you have a bad dump", szFilename, i);
fread(rContent.m_pData, (size_t)Size, 1, pFile); fread(rContent.m_pData, (size_t)Size, 1, pFile);
fclose(pFile); fclose(pFile);
} }
else else
{ {
PanicAlert("NANDContentLoader: error opening %s", szFilename); PanicAlert("NANDContentLoader: error opening %s", szFilename);
} }
} }
return true; return true;
} }
void CNANDContentLoader::AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest) void CNANDContentLoader::AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
{ {
AES_KEY AESKey; AES_KEY AESKey;
AES_set_decrypt_key(_pKey, 128, &AESKey); AES_set_decrypt_key(_pKey, 128, &AESKey);
AES_cbc_encrypt(_pSrc, _pDest, _Size, &AESKey, _IV, AES_DECRYPT); AES_cbc_encrypt(_pSrc, _pDest, _Size, &AESKey, _IV, AES_DECRYPT);
} }
void CNANDContentLoader::GetKeyFromTicket(u8* pTicket, u8* pTicketKey) void CNANDContentLoader::GetKeyFromTicket(u8* pTicket, u8* pTicketKey)
{ {
u8 CommonKey[16] = {0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4,0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7}; u8 CommonKey[16] = {0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4,0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7};
u8 IV[16]; u8 IV[16];
memset(IV, 0, sizeof IV); memset(IV, 0, sizeof IV);
memcpy(IV, pTicket + 0x01dc, 8); memcpy(IV, pTicket + 0x01dc, 8);
AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey); AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey);
} }
bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD) bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD)
@ -293,11 +293,11 @@ bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u
GetKeyFromTicket(pTicket, DecryptTitleKey); GetKeyFromTicket(pTicket, DecryptTitleKey);
memcpy(m_TicketView, pTMD + 0x180, TICKET_VIEW_SIZE); memcpy(m_TicketView, pTMD + 0x180, TICKET_VIEW_SIZE);
memcpy(m_TmdHeader, pTMD, TMD_HEADER_SIZE); memcpy(m_TmdHeader, pTMD, TMD_HEADER_SIZE);
m_TileVersion = Common::swap16(pTMD + 0x01dc); m_TileVersion = Common::swap16(pTMD + 0x01dc);
m_numEntries = Common::swap16(pTMD + 0x01de); m_numEntries = Common::swap16(pTMD + 0x01de);
m_BootIndex = Common::swap16(pTMD + 0x01e0); m_BootIndex = Common::swap16(pTMD + 0x01e0);
m_TitleID = Common::swap64(pTMD + 0x018c); m_TitleID = Common::swap64(pTMD + 0x018c);
m_IosVersion = Common::swap16(pTMD + 0x018a); m_IosVersion = Common::swap16(pTMD + 0x018a);
@ -313,11 +313,11 @@ bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u
rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i); rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i);
rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i); rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i);
rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i); rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i);
rContent.m_Size= (u32)Common::swap64(pTMD + 0x01ec + 0x24*i); rContent.m_Size= (u32)Common::swap64(pTMD + 0x01ec + 0x24*i);
memcpy(rContent.m_SHA1Hash, pTMD + 0x01f4 + 0x24*i, 20); memcpy(rContent.m_SHA1Hash, pTMD + 0x01f4 + 0x24*i, 20);
memcpy(rContent.m_Header, pTMD + 0x01e4 + 0x24*i, 36); memcpy(rContent.m_Header, pTMD + 0x01e4 + 0x24*i, 36);
u32 RoundedSize = ROUND_UP(rContent.m_Size, 0x40); u32 RoundedSize = ROUND_UP(rContent.m_Size, 0x40);
rContent.m_pData = new u8[RoundedSize]; rContent.m_pData = new u8[RoundedSize];
memset(IV, 0, sizeof IV); memset(IV, 0, sizeof IV);
@ -327,109 +327,53 @@ bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u
p += RoundedSize; p += RoundedSize;
} }
return true; return true;
} }
const DiscIO::IVolume::ECountry CNANDContentLoader::GetCountry() const const DiscIO::IVolume::ECountry CNANDContentLoader::GetCountry() const
{ {
DiscIO::IVolume::ECountry country = DiscIO::IVolume::COUNTRY_UNKNOWN; if (!IsValid())
return DiscIO::IVolume::COUNTRY_UNKNOWN;
if (IsValid()) u64 TitleID = GetTitleID();
{ char* pTitleID = (char*)&TitleID;
u64 TitleID = GetTitleID();
char* pTitleID = (char*)&TitleID;
switch (pTitleID[0]) return CountrySwitch((u8)pTitleID[0]);
{
case 'S':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // PAL // <- that is shitty :) zelda demo disc
case 'P':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // PAL
case 'D':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // PAL
case 'F':
country = DiscIO::IVolume::COUNTRY_FRANCE;
break; // PAL
case 'I':
country = DiscIO::IVolume::COUNTRY_ITALY;
break; // PAL
case 'X':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // XIII <- uses X but is PAL rip
case 'E':
country = DiscIO::IVolume::COUNTRY_USA;
break; // USA
case 'J':
country = DiscIO::IVolume::COUNTRY_JAP;
break; // JAP
case 'K':
country = DiscIO::IVolume::COUNTRY_KOR;
break; // KOR
case 'O':
country = DiscIO::IVolume::COUNTRY_UNKNOWN;
break; // SDK
default:
PanicAlert("Unknown Country Code!");
break;
}
}
return(country);
} }
///////////////////
CNANDContentManager CNANDContentManager::m_Instance; CNANDContentManager CNANDContentManager::m_Instance;
CNANDContentManager::~CNANDContentManager() CNANDContentManager::~CNANDContentManager()
{ {
CNANDContentMap::iterator itr = m_Map.begin(); CNANDContentMap::iterator itr = m_Map.begin();
while (itr != m_Map.end()) while (itr != m_Map.end())
{ {
delete itr->second; delete itr->second;
itr++; itr++;
} }
m_Map.clear(); m_Map.clear();
} }
const INANDContentLoader& CNANDContentManager::GetNANDLoader(const std::string& _rName) const INANDContentLoader& CNANDContentManager::GetNANDLoader(const std::string& _rName)
{ {
std::string KeyString(_rName); std::string KeyString(_rName);
std::transform(KeyString.begin(), KeyString.end(), KeyString.begin(), std::transform(KeyString.begin(), KeyString.end(), KeyString.begin(),
(int(*)(int)) toupper); (int(*)(int)) toupper);
CNANDContentMap::iterator itr = m_Map.find(KeyString); CNANDContentMap::iterator itr = m_Map.find(KeyString);
if (itr != m_Map.end()) if (itr != m_Map.end())
return *itr->second; return *itr->second;
m_Map[KeyString] = new CNANDContentLoader(KeyString); m_Map[KeyString] = new CNANDContentLoader(KeyString);
return *m_Map[KeyString]; return *m_Map[KeyString];
} }
} // namespace end } // namespace end

View File

@ -14,13 +14,14 @@ files = [
'FileHandlerARC.cpp', 'FileHandlerARC.cpp',
'Filesystem.cpp', 'Filesystem.cpp',
'FileSystemGCWii.cpp', 'FileSystemGCWii.cpp',
'VolumeCommon.cpp',
'VolumeCreator.cpp', 'VolumeCreator.cpp',
'VolumeDirectory.cpp', 'VolumeDirectory.cpp',
'VolumeGC.cpp', 'VolumeGC.cpp',
'VolumeWad.cpp', 'VolumeWad.cpp',
'VolumeWiiCrypted.cpp', 'VolumeWiiCrypted.cpp',
'NANDContentLoader.cpp', 'NANDContentLoader.cpp',
'WiiWad.cpp', 'WiiWad.cpp',
'AES/aes_cbc.c', 'AES/aes_cbc.c',
'AES/aes_core.c', 'AES/aes_core.c',
] ]

View File

@ -52,9 +52,11 @@ class IVolume
COUNTRY_EUROPE = 0, COUNTRY_EUROPE = 0,
COUNTRY_FRANCE = 1, COUNTRY_FRANCE = 1,
COUNTRY_USA = 2, COUNTRY_USA = 2,
COUNTRY_JAP, COUNTRY_JAPAN,
COUNTRY_KOR, COUNTRY_KOREA,
COUNTRY_ITALY, COUNTRY_ITALY,
COUNTRY_TAIWAN,
COUNTRY_SDK,
COUNTRY_UNKNOWN, COUNTRY_UNKNOWN,
NUMBER_OF_COUNTRIES NUMBER_OF_COUNTRIES
}; };
@ -62,6 +64,10 @@ class IVolume
virtual ECountry GetCountry() const = 0; virtual ECountry GetCountry() const = 0;
virtual u64 GetSize() const = 0; virtual u64 GetSize() const = 0;
}; };
// Generic Switch function for all volumes
IVolume::ECountry CountrySwitch(u8 CountryCode);
} // namespace } // namespace
#endif #endif

View File

@ -163,52 +163,7 @@ IVolume::ECountry CVolumeDirectory::GetCountry() const
u8 CountryCode = m_diskHeader[3]; u8 CountryCode = m_diskHeader[3];
ECountry country = COUNTRY_UNKNOWN; return CountrySwitch(CountryCode);
switch (CountryCode)
{
case 'S':
country = COUNTRY_EUROPE;
break; // PAL <- that is shitty :) zelda demo disc
case 'P':
country = COUNTRY_EUROPE;
break; // PAL
case 'D':
country = COUNTRY_EUROPE;
break; // PAL
case 'F':
country = COUNTRY_FRANCE;
break; // PAL
case 'I':
country = COUNTRY_ITALY;
break; // PAL
case 'X':
country = COUNTRY_EUROPE;
break; // XIII <- uses X but is PAL rip
case 'E':
country = COUNTRY_USA;
break; // USA
case 'J':
country = COUNTRY_JAP;
break; // JAP
case 'O':
country = COUNTRY_UNKNOWN;
break; // SDK
default:
country = COUNTRY_UNKNOWN;
break;
}
return(country);
} }
std::string CVolumeDirectory::GetMakerID() const std::string CVolumeDirectory::GetMakerID() const
@ -250,18 +205,12 @@ u64 CVolumeDirectory::GetSize() const
return 0; return 0;
} }
static const char DIR_SEPARATOR =
#ifdef _WIN32
'\\';
#else
'/';
#endif
std::string CVolumeDirectory::ExtractDirectoryName(const std::string& _rDirectory) std::string CVolumeDirectory::ExtractDirectoryName(const std::string& _rDirectory)
{ {
std::string directoryName = _rDirectory; std::string directoryName = _rDirectory;
size_t lastSep = directoryName.find_last_of(DIR_SEPARATOR); size_t lastSep = directoryName.find_last_of(DIR_SEP_CHR);
if(lastSep != directoryName.size() - 1) if(lastSep != directoryName.size() - 1)
{ {

View File

@ -70,53 +70,7 @@ IVolume::ECountry CVolumeGC::GetCountry() const
u8 CountryCode; u8 CountryCode;
m_pReader->Read(3, 1, &CountryCode); m_pReader->Read(3, 1, &CountryCode);
ECountry country = COUNTRY_UNKNOWN; return CountrySwitch(CountryCode);
switch (CountryCode)
{
case 'S':
country = COUNTRY_EUROPE;
break; // PAL // <- that is shitty :) zelda demo disc
case 'P':
country = COUNTRY_EUROPE;
break; // PAL
case 'D':
country = COUNTRY_EUROPE;
break; // PAL
case 'F':
country = COUNTRY_FRANCE;
break; // PAL
case 'I':
country = COUNTRY_ITALY;
break; // PAL
case 'X':
country = COUNTRY_EUROPE;
break; // XIII <- uses X but is PAL
case 'E':
country = COUNTRY_USA;
break; // USA
case 'J':
country = COUNTRY_JAP;
break; // JAP
case 'O':
country = COUNTRY_UNKNOWN;
break; // SDK
default:
// PanicAlert(StringFromFormat("Unknown Country Code!").c_str());
country = COUNTRY_UNKNOWN;
break;
}
return(country);
} }
std::string CVolumeGC::GetMakerID() const std::string CVolumeGC::GetMakerID() const

View File

@ -1,202 +1,156 @@
// Copyright (C) 2003-2009 Dolphin Project. // Copyright (C) 2003-2009 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "stdafx.h" #include "stdafx.h"
#include <math.h> #include <math.h>
#include "VolumeWad.h" #include "VolumeWad.h"
#include "StringUtil.h" #include "StringUtil.h"
#include "MathUtil.h" #include "MathUtil.h"
#define ALIGN_40(x) ROUND_UP(Common::swap32(x), 0x40) #define ALIGN_40(x) ROUND_UP(Common::swap32(x), 0x40)
namespace DiscIO namespace DiscIO
{ {
CVolumeWAD::CVolumeWAD(IBlobReader* _pReader) CVolumeWAD::CVolumeWAD(IBlobReader* _pReader)
: m_pReader(_pReader), OpeningBnrOffset(0), hdr_size(0), cert_size(0), tick_size(0), tmd_size(0), data_size(0) : m_pReader(_pReader), OpeningBnrOffset(0), hdr_size(0), cert_size(0), tick_size(0), tmd_size(0), data_size(0)
{ {
Read(0x00, 4, (u8*)&hdr_size); Read(0x00, 4, (u8*)&hdr_size);
Read(0x08, 4, (u8*)&cert_size); Read(0x08, 4, (u8*)&cert_size);
Read(0x10, 4, (u8*)&tick_size); Read(0x10, 4, (u8*)&tick_size);
Read(0x14, 4, (u8*)&tmd_size); Read(0x14, 4, (u8*)&tmd_size);
Read(0x18, 4, (u8*)&data_size); Read(0x18, 4, (u8*)&data_size);
OpeningBnrOffset = ALIGN_40(hdr_size) + ALIGN_40(cert_size) + ALIGN_40(tick_size) + ALIGN_40(tmd_size) + ALIGN_40(data_size); OpeningBnrOffset = ALIGN_40(hdr_size) + ALIGN_40(cert_size) + ALIGN_40(tick_size) + ALIGN_40(tmd_size) + ALIGN_40(data_size);
} }
CVolumeWAD::~CVolumeWAD() CVolumeWAD::~CVolumeWAD()
{ {
delete m_pReader; delete m_pReader;
} }
bool CVolumeWAD::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const bool CVolumeWAD::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const
{ {
if (m_pReader == NULL) if (m_pReader == NULL)
return false; return false;
return m_pReader->Read(_Offset, _Length, _pBuffer); return m_pReader->Read(_Offset, _Length, _pBuffer);
} }
IVolume::ECountry CVolumeWAD::GetCountry() const IVolume::ECountry CVolumeWAD::GetCountry() const
{ {
if (!m_pReader) if (!m_pReader)
return COUNTRY_UNKNOWN; return COUNTRY_UNKNOWN;
u8 CountryCode; u8 CountryCode;
u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size);
u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size);
// read the last digit of the titleID in the ticket
// read the last digit of the titleID in the ticket Read(Offset + 0x01E3, 1, &CountryCode);
Read(Offset + 0x01E3, 1, &CountryCode);
return CountrySwitch(CountryCode);
ECountry country = COUNTRY_UNKNOWN; }
switch (CountryCode) std::string CVolumeWAD::GetUniqueID() const
{ {
case 'S': std::string temp = GetMakerID();
country = COUNTRY_EUROPE; u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size);
break; // PAL // <- that is shitty :) zelda demo disc
char GameCode[8];
case 'P': if(!Read(Offset + 0x01E0, 4, (u8*)GameCode))
country = COUNTRY_EUROPE; return "0";
break; // PAL
GameCode[4] = temp.at(0);
case 'D': GameCode[5] = temp.at(1);
country = COUNTRY_EUROPE; GameCode[6] = 0;
break; // PAL
return GameCode;
case 'F': }
country = COUNTRY_FRANCE;
break; // PAL std::string CVolumeWAD::GetMakerID() const
{
case 'I': u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size) + ALIGN_40(tick_size);
country = COUNTRY_ITALY;
break; // PAL char temp[3] = {1};
// Some weird channels use 0x0000 in place of the MakerID, so we need a check there
case 'X': if (!Read(0x198 + Offset, 2, (u8*)temp) || temp[0] == 0 || temp[1] == 0)
country = COUNTRY_EUROPE; return "00";
break; // XIII <- uses X but is PAL
temp[2] = 0;
case 'E':
country = COUNTRY_USA; return temp;
break; // USA }
case 'J': bool CVolumeWAD::GetTitleID(u8* _pBuffer) const
country = COUNTRY_JAP; {
break; // JAP u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size);
case 'O': if(!Read(Offset + 0x01DC, 8, _pBuffer))
country = COUNTRY_UNKNOWN; return false;
break; // SDK
return true;
default: }
country = COUNTRY_UNKNOWN;
break; std::string CVolumeWAD::GetName() const
} {
u32 footer_size;
return(country);
} if (!Read(0x1C, 4, (u8*)&footer_size))
return "Unknown";
std::string CVolumeWAD::GetUniqueID() const
{ // Offset to the english title
std::string temp = GetMakerID(); char temp[85];
u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size); if (!Read(0xF1 + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1)
return "Unknown";
char GameCode[8];
if(!Read(Offset + 0x01E0, 4, (u8*)GameCode)) char out_temp[43];
return "0"; int j = 0;
GameCode[4] = temp.at(0); for (int i=0; i < 84; i++)
GameCode[5] = temp.at(1); {
GameCode[6] = 0; if (!(i & 1))
{
return GameCode; if (temp[i] != 0)
} out_temp[j] = temp[i];
else
std::string CVolumeWAD::GetMakerID() const {
{ // Some wads have a few consecutive Null chars followed by text
u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size) + ALIGN_40(tick_size); // as i don't know what to do there: replace the frst one with space
if (out_temp[j-1] != 32)
char temp[3] = {1}; out_temp[j] = 32;
// Some weird channels use 0x0000 in place of the MakerID, so we need a check there else
if (!Read(0x198 + Offset, 2, (u8*)temp) || temp[0] == 0 || temp[1] == 0) continue;
return "00"; }
temp[2] = 0; j++;
}
return temp; }
}
out_temp[j] = 0;
bool CVolumeWAD::GetTitleID(u8* _pBuffer) const
{ return out_temp;
u32 Offset = ALIGN_40(hdr_size) + ALIGN_40(cert_size); }
if(!Read(Offset + 0x01DC, 8, _pBuffer)) u64 CVolumeWAD::GetSize() const
return false; {
if (m_pReader)
return true; return (size_t)m_pReader->GetDataSize();
} else
return 0;
std::string CVolumeWAD::GetName() const }
{
u32 footer_size; } // namespace
if (!Read(0x1C, 4, (u8*)&footer_size))
return "Unknown";
// Offset to the english title
char temp[85];
if (!Read(0xF1 + OpeningBnrOffset, 84, (u8*)&temp) || Common::swap32(footer_size) < 0xF1)
return "Unknown";
char out_temp[43];
int j = 0;
for (int i=0; i < 84; i++)
{
if (!(i & 1))
{
if (temp[i] != 0)
out_temp[j] = temp[i];
else
{
// Some wads have a few consecutive Null chars followed by text
// as i don't know what to do there: replace the frst one with space
if (out_temp[j-1] != 32)
out_temp[j] = 32;
else
continue;
}
j++;
}
}
out_temp[j] = 0;
return out_temp;
}
u64 CVolumeWAD::GetSize() const
{
if (m_pReader)
return (size_t)m_pReader->GetDataSize();
else
return 0;
}
} // namespace

View File

@ -121,63 +121,12 @@ std::string CVolumeWiiCrypted::GetUniqueID() const
IVolume::ECountry CVolumeWiiCrypted::GetCountry() const IVolume::ECountry CVolumeWiiCrypted::GetCountry() const
{ {
if (!m_pReader) if (!m_pReader)
{ return COUNTRY_UNKNOWN;
return(COUNTRY_UNKNOWN);
}
u8 CountryCode; u8 CountryCode;
m_pReader->Read(3, 1, &CountryCode); m_pReader->Read(3, 1, &CountryCode);
ECountry country = COUNTRY_UNKNOWN; return CountrySwitch(CountryCode);
switch (CountryCode)
{
case 'S':
country = COUNTRY_EUROPE;
break; // PAL // <- that is shitty :) zelda demo disc
case 'P':
country = COUNTRY_EUROPE;
break; // PAL
case 'D':
country = COUNTRY_EUROPE;
break; // PAL
case 'F':
country = COUNTRY_FRANCE;
break; // PAL
case 'I':
country = COUNTRY_ITALY;
break; // PAL
case 'X':
country = COUNTRY_EUROPE;
break; // XIII <- uses X but is PAL rip
case 'E':
country = COUNTRY_USA;
break; // USA
case 'J':
country = COUNTRY_JAP;
break; // JAP
case 'K':
country = COUNTRY_KOR;
break; // KOR
case 'O':
country = COUNTRY_UNKNOWN;
break; // SDK
default:
PanicAlert("Unknown Country Code!");
break;
}
return(country);
} }
std::string CVolumeWiiCrypted::GetMakerID() const std::string CVolumeWiiCrypted::GetMakerID() const

View File

@ -948,6 +948,14 @@
RelativePath=".\resources\Flag_Japan.xpm" RelativePath=".\resources\Flag_Japan.xpm"
> >
</File> </File>
<File
RelativePath=".\resources\Flag_Taiwan.xpm"
>
</File>
<File
RelativePath=".\resources\Flag_Unknown.xpm"
>
</File>
<File <File
RelativePath=".\resources\Flag_USA.xpm" RelativePath=".\resources\Flag_USA.xpm"
> >

View File

@ -35,14 +35,17 @@
#include "WxUtils.h" #include "WxUtils.h"
#if USE_XPM_BITMAPS #if USE_XPM_BITMAPS
#include "../resources/Flag_Europe.xpm" #include "../resources/Flag_Europe.xpm"
#include "../resources/Flag_France.xpm" #include "../resources/Flag_France.xpm"
#include "../resources/Flag_Italy.xpm" #include "../resources/Flag_Italy.xpm"
#include "../resources/Flag_Japan.xpm" #include "../resources/Flag_Japan.xpm"
#include "../resources/Flag_USA.xpm"
#include "../resources/Flag_Taiwan.xpm"
#include "../resources/Flag_Unknown.xpm"
#include "../resources/Platform_Wad.xpm" #include "../resources/Platform_Wad.xpm"
#include "../resources/Flag_USA.xpm" #include "../resources/Platform_Wii.xpm"
#include "../resources/Platform_Wii.xpm" #include "../resources/Platform_Gamecube.xpm"
#include "../resources/Platform_Gamecube.xpm"
#endif // USE_XPM_BITMAPS #endif // USE_XPM_BITMAPS
size_t CGameListCtrl::m_currentItem = 0; size_t CGameListCtrl::m_currentItem = 0;
@ -58,14 +61,14 @@ bool operator < (const GameListItem &one, const GameListItem &other)
switch (one.GetCountry()) switch (one.GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP:; case DiscIO::IVolume::COUNTRY_JAPAN:;
case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break; case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break;
default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage; default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage;
} }
switch (other.GetCountry()) switch (other.GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP:; case DiscIO::IVolume::COUNTRY_JAPAN:;
case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break; case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break;
default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage; default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage;
} }
@ -116,17 +119,25 @@ void CGameListCtrl::InitBitmaps()
SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL); SetImageList(m_imageListSmall, wxIMAGE_LIST_SMALL);
m_FlagImageIndex.resize(DiscIO::IVolume::NUMBER_OF_COUNTRIES); m_FlagImageIndex.resize(DiscIO::IVolume::NUMBER_OF_COUNTRIES);
wxIcon iconTemp; wxIcon iconTemp;
iconTemp.CopyFromBitmap(wxBitmap(Flag_Europe_xpm)); iconTemp.CopyFromBitmap(wxBitmap(Flag_Europe_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_EUROPE] = m_imageListSmall->Add(iconTemp); m_FlagImageIndex[DiscIO::IVolume::COUNTRY_EUROPE] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_France_xpm)); iconTemp.CopyFromBitmap(wxBitmap(Flag_France_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_FRANCE] = m_imageListSmall->Add(iconTemp); m_FlagImageIndex[DiscIO::IVolume::COUNTRY_FRANCE] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Italy_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_ITALY] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_USA_xpm)); iconTemp.CopyFromBitmap(wxBitmap(Flag_USA_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_USA] = m_imageListSmall->Add(iconTemp); m_FlagImageIndex[DiscIO::IVolume::COUNTRY_USA] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Japan_xpm)); iconTemp.CopyFromBitmap(wxBitmap(Flag_Japan_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_JAP] = m_imageListSmall->Add(iconTemp); m_FlagImageIndex[DiscIO::IVolume::COUNTRY_JAPAN] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Europe_xpm)); iconTemp.CopyFromBitmap(wxBitmap(Flag_Unknown_xpm)); // TODO add korea flag
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_KOREA] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Italy_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_ITALY] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Taiwan_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_TAIWAN] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Unknown_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_SDK] = m_imageListSmall->Add(iconTemp);
iconTemp.CopyFromBitmap(wxBitmap(Flag_Unknown_xpm));
m_FlagImageIndex[DiscIO::IVolume::COUNTRY_UNKNOWN] = m_imageListSmall->Add(iconTemp); m_FlagImageIndex[DiscIO::IVolume::COUNTRY_UNKNOWN] = m_imageListSmall->Add(iconTemp);
m_PlatformImageIndex.resize(3); m_PlatformImageIndex.resize(3);
@ -308,7 +319,7 @@ void CGameListCtrl::InsertItemInReportView(long _Index)
switch (rISOFile.GetCountry()) switch (rISOFile.GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP: case DiscIO::IVolume::COUNTRY_JAPAN:
// keep these codes, when we move to wx unicode... // keep these codes, when we move to wx unicode...
//wxCSConv convFrom(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS)); //wxCSConv convFrom(wxFontMapper::GetEncodingName(wxFONTENCODING_SHIFT_JIS));
//wxCSConv convTo(wxFontMapper::GetEncodingName(wxFONTENCODING_DEFAULT)); //wxCSConv convTo(wxFontMapper::GetEncodingName(wxFONTENCODING_DEFAULT));
@ -526,7 +537,11 @@ void CGameListCtrl::ScanForISOs()
switch(ISOFile.GetCountry()) switch(ISOFile.GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP: case DiscIO::IVolume::COUNTRY_TAIWAN:
case DiscIO::IVolume::COUNTRY_KOREA:
// TODO: Add these to interface choices, or combine with japan?
break;
case DiscIO::IVolume::COUNTRY_JAPAN:
if (!SConfig::GetInstance().m_ListJap) if (!SConfig::GetInstance().m_ListJap)
list = false; list = false;
break; break;
@ -593,14 +608,14 @@ int wxCALLBACK wxListCompare(long item1, long item2, long sortData)
switch (iso1->GetCountry()) switch (iso1->GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP:; case DiscIO::IVolume::COUNTRY_JAPAN:;
case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break; case DiscIO::IVolume::COUNTRY_USA:indexOne = 0; break;
default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage; default: indexOne = (int)SConfig::GetInstance().m_InterfaceLanguage;
} }
switch (iso2->GetCountry()) switch (iso2->GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP:; case DiscIO::IVolume::COUNTRY_JAPAN:;
case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break; case DiscIO::IVolume::COUNTRY_USA:indexOther = 0; break;
default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage; default: indexOther = (int)SConfig::GetInstance().m_InterfaceLanguage;
} }

View File

@ -121,15 +121,28 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW
switch (OpenISO->GetCountry()) switch (OpenISO->GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_EUROPE: case DiscIO::IVolume::COUNTRY_EUROPE:
m_Country->SetValue(wxString::FromAscii("EUROPE"));
break;
case DiscIO::IVolume::COUNTRY_FRANCE: case DiscIO::IVolume::COUNTRY_FRANCE:
m_Country->SetValue(wxString::FromAscii("FRANCE"));
break;
case DiscIO::IVolume::COUNTRY_ITALY: case DiscIO::IVolume::COUNTRY_ITALY:
m_Country->SetValue(wxString::FromAscii("EUR")); m_Country->SetValue(wxString::FromAscii("ITALY"));
break; break;
case DiscIO::IVolume::COUNTRY_USA: case DiscIO::IVolume::COUNTRY_USA:
m_Country->SetValue(wxString::FromAscii("USA")); m_Country->SetValue(wxString::FromAscii("USA"));
break; break;
case DiscIO::IVolume::COUNTRY_JAP: case DiscIO::IVolume::COUNTRY_JAPAN:
m_Country->SetValue(wxString::FromAscii("JAP")); m_Country->SetValue(wxString::FromAscii("JAPAN"));
break;
case DiscIO::IVolume::COUNTRY_KOREA:
m_Country->SetValue(wxString::FromAscii("KOREA"));
break;
case DiscIO::IVolume::COUNTRY_TAIWAN:
m_Country->SetValue(wxString::FromAscii("TAIWAN"));
break;
case DiscIO::IVolume::COUNTRY_SDK:
m_Country->SetValue(wxString::FromAscii("No Country (SDK)"));
break; break;
default: default:
m_Country->SetValue(wxString::FromAscii("UNKNOWN")); m_Country->SetValue(wxString::FromAscii("UNKNOWN"));

View File

@ -0,0 +1,124 @@
/* XPM */
static const char * Flag_Taiwan_xpm[] = {
"96 32 89 1",
" c None",
". c #000000",
"# c #000099",
"$ c #000098",
"% c #03039A",
"& c #000094",
"' c #05059B",
"( c #050095",
") c #DC0014",
"* c #FF0000",
"+ c #FD0001",
", c #04049B",
"- c #000096",
"! c #020299",
"0 c #2424A7",
"1 c #04049A",
"2 c #000097",
"3 c #000093",
"4 c #6262BF",
"5 c #2828A8",
"6 c #6C6CC1",
"7 c #3E3EB1",
"8 c #3B3BB0",
"9 c #00008F",
": c #01019A",
"; c #1919A3",
"< c #4040B0",
"= c #6363C0",
"> c #D6D6EE",
"? c #D9D9ED",
"@ c #C5C5E7",
"A c #3F3FB0",
"B c #3D3DAF",
"C c #020297",
"D c #010199",
"E c #5E5EBE",
"F c #DFDFF2",
"G c white",
"H c #BFBFE5",
"I c #2626A7",
"J c #4242B0",
"K c #7D7DCA",
"L c #FAFAFD",
"M c #FBFBFD",
"N c #FCFCFD",
"O c #FCFCFE",
"P c #DADAF0",
"Q c #6A6AC2",
"R c #1B1BA3",
"S c #000199",
"T c #0E0E9B",
"U c #5858BC",
"V c #D3D3ED",
"W c #2727A6",
"X c #060699",
"Y c #1212A0",
"Z c #6464C0",
"[ c #8080CC",
"] c #F4F4FA",
"^ c #F8F8FB",
"_ c #7070C4",
"` c #4949B5",
"a c #000095",
"b c #040499",
"c c #000092",
"d c #6767C2",
"e c #8686CA",
"f c #7070C5",
"g c #2B2BA9",
"h c #00009A",
"i c #01049C",
"j c #1619A4",
"k c #393CB3",
"l c #00029A",
"m c #1619A5",
"n c #020096",
"o c #DB0014",
"p c #FC0001",
"q c #0A0092",
"r c #060090",
"s c #0B0092",
"t c #0F008E",
"u c #DD0013",
"v c #FD0000",
"w c #E5000F",
"x c #E6010F",
"y c #E60110",
"z c #FB0002",
"{ c #FE0000",
" ",
" ",
" ",
" ",
" ",
"................................ ",
".#####$%#&'$$$##()*+***********. ",
".###$$,-!0&1!$##()*+***********. ",
".##$#23456789:$#()*+***********. ",
".###2;<=>?@ABCD#()*+***********. ",
".###$CEFGGGHI&D$()*+***********. ",
".##D-JKLMNOPQR-S()*+***********. ",
".###$TUGGNGVWX$#()*+***********. ",
".###2YZ[]^P_`aD$()*+***********. ",
".###$bcdEefg3D$#()*+***********. ",
".hhhhhijiklm#hhhno*p***********. ",
".qqqqqqrsrqrqqqqtu*v***********. ",
".wwwwwwxwywxwwwwwz*{***********. ",
".******************************. ",
".{{{{{{{{{{{{{{{{{*{***********. ",
".******************************. ",
".******************************. ",
".******************************. ",
".******************************. ",
"................................ ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};

View File

@ -0,0 +1,50 @@
/* XPM */
static const char *const Flag_Unknown_xpm[] = {
"96 32 15 1",
" c None",
"! c black",
"# c #360000",
"$ c #D60000",
"% c #1B0000",
"& c #6B0000",
"' c #510000",
"( c #280000",
") c #BB0000",
"* c #780000",
"+ c #A00000",
", c #0D0000",
"- c #C90000",
". c #AE0000",
"0 c #430000",
" ",
" ",
" ",
" ",
" ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!####!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!#$$#!###! ",
"!!!%&'!!!!%&'!()$$$$$*!#$$##$$#! ",
"!!!#$+!!!!#$+,-$$$$$$$&#$$#))$#! ",
"!!!#$+!!!!#$+#$.!!!!0$+#$$)))#!! ",
"!!!#$+!!!!#$+#$+!!!!#$+#$$))#!!! ",
"!!!#$+!!!!#$+#$+!!!!#$+#$$))#!!! ",
"!!!#$+!!!!#$+#$+!!!!#$+#$$)))#!! ",
"!!!#$.!!!!0$+#$+!!!!#$+#))#))$#! ",
"!!!,-$$$$$$$&#$+!!!!#$+#$$!#$$#! ",
"!!!!()$$$$$*!%&'!!!!%&'!##!!##!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
"!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! ",
" ",
" ",
" ",
" ",
" ",
" ",
" "};