daedalus/Source/Core/ROM.cpp

650 lines
19 KiB
C++

/*
Copyright (C) 2001 StrmnNrmn
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 the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "BuildOptions.h"
#include "Base/Types.h"
#include "ROM.h"
#include <stdio.h>
#include "Core/Cheats.h"
#include "Core/CPU.h"
#include "Core/PIF.h" // CController
#include "Core/R4300.h"
#include "Core/ROMBuffer.h"
#include "Core/ROMImage.h"
#include "Core/RomSettings.h"
#include "Config/ConfigOptions.h"
#include "Debug/DBGConsole.h"
#include "Debug/DebugLog.h"
#include "Interface/RomDB.h"
#include "Base/MathUtil.h"
#include "OSHLE/patch.h" // Patch_ApplyPatches
#include "Ultra/ultra_os.h" // System type
#include "Ultra/ultra_R4300.h"
#include "HLEAudio/AudioPlugin.h"
#include "HLEGraphics/GraphicsPlugin.h"
#include "Utility/CRC.h"
#include "Core/FramerateLimiter.h"
#include "System/IO.h"
#include "Base/Macros.h"
#include "Interface/Preferences.h"
#include "RomFile/RomFile.h"
#include "Utility/Stream.h"
#include "Debug/Synchroniser.h"
#if defined(DAEDALUS_ENABLE_DYNAREC_PROFILE) || defined(DAEDALUS_W32)
// This isn't really the most appropriate place. Need to check with
// the graphics plugin really
u32 g_dwNumFrames = 0;
#endif
RomInfo g_ROM;
static void DumpROMInfo( const ROMHeader & header )
{
// The "Header" is actually something to do with the PI_DOM_*_OFS values...
DBGConsole_Msg(0, "Header: 0x%02x%02x%02x%02x", header.x1, header.x2, header.x3, header.x4);
DBGConsole_Msg(0, "Clockrate: 0x%08x", header.ClockRate);
DBGConsole_Msg(0, "BootAddr: 0x%08x", BSWAP32(header.BootAddress));
DBGConsole_Msg(0, "Release: 0x%08x", header.Release);
DBGConsole_Msg(0, "CRC1: 0x%08x", header.CRC1);
DBGConsole_Msg(0, "CRC2: 0x%08x", header.CRC2);
DBGConsole_Msg(0, "Unknown0: 0x%08x", header.Unknown0);
DBGConsole_Msg(0, "Unknown1: 0x%08x", header.Unknown1);
DBGConsole_Msg(0, "ImageName: '%s'", header.Name);
DBGConsole_Msg(0, "Unknown2: 0x%08x", header.Unknown2);
DBGConsole_Msg(0, "Unknown3: 0x%04x", header.Unknown3);
DBGConsole_Msg(0, "Unknown4: 0x%02x", header.Unknown4);
DBGConsole_Msg(0, "Manufacturer: 0x%02x", header.Manufacturer);
DBGConsole_Msg(0, "CartID: 0x%04x", header.CartID);
DBGConsole_Msg(0, "CountryID: 0x%02x - '%c'", header.CountryID, (char)header.CountryID);
DBGConsole_Msg(0, "Unknown5: 0x%02x", header.Unknown5);
}
static void ROM_SimulatePIFBoot( ECicType cic_chip, u32 Country )
{
// Copy low 1000 bytes to MEM_SP_MEM
RomBuffer::GetRomBytesRaw( (u8*)g_pMemoryBuffers[MEM_SP_MEM] + RAMROM_BOOTSTRAP_OFFSET,
RAMROM_BOOTSTRAP_OFFSET,
RAMROM_GAME_OFFSET - RAMROM_BOOTSTRAP_OFFSET );
// Need to copy to SP_IMEM for CIC-6105 boot.
u8 * pIMemBase = (u8*)g_pMemoryBuffers[ MEM_SP_MEM ] + 0x1000;
gCPUState.CPUControl[C0_RAND]._u32 = 0x1F;
gCPUState.CPUControl[C0_COUNT]._u32 = 0x5000;
Memory_MI_SetRegister(MI_VERSION_REG, 0x02020102);
Memory_SP_SetRegister(SP_STATUS_REG, SP_STATUS_HALT);
gCPUState.CPUControl[C0_CAUSE]._u32 = 0x0000005C;
gCPUState.CPUControl[C0_CONTEXT]._u32 = 0x007FFFF0;
gCPUState.CPUControl[C0_EPC]._u32 = 0xFFFFFFFF;
gCPUState.CPUControl[C0_BADVADDR]._u32 = 0xFFFFFFFF;
gCPUState.CPUControl[C0_ERROR_EPC]._u32 = 0xFFFFFFFF;
gCPUState.CPUControl[C0_CONFIG]._u32 = 0x0006E463;
gCPUState.CPUControl[C0_SR]._u32 = 0x34000000; //*SR_FR |*/ SR_ERL | SR_CU2|SR_CU1|SR_CU0;
//R4300_SetSR(0x34000000);
// From R4300 manual
//gCPUState.CPUControl[C0_SR]._u32 = 0x70400004; //*SR_FR |*/ SR_ERL | SR_CU2|SR_CU1|SR_CU0;
R4300_SetSR(0x70400004);
gCPUState.CPUControl[C0_PRID]._u32 = 0x00000b10; // Was 0xb00 - test rom reports 0xb10!!
gCPUState.CPUControl[C0_WIRED]._u32 = 0x0;
gCPUState.FPUControl[0]._u32 = 0x00000511;
((u32 *)g_pMemoryBuffers[MEM_RI_REG])[3] = 1; // RI_CONFIG_REG Skips most of init
gGPR[0]._u64=0x0000000000000000LL;
gGPR[1]._u64=0x0000000000000000LL;
gGPR[2]._u64=0xFFFFFFFFD1731BE9LL;
gGPR[3]._u64=0xFFFFFFFFD1731BE9LL;
gGPR[4]._u64=0x0000000000001BE9LL;
gGPR[5]._u64=0xFFFFFFFFF45231E5LL;
gGPR[6]._u64=0xFFFFFFFFA4001F0CLL;
gGPR[7]._u64=0xFFFFFFFFA4001F08LL;
gGPR[8]._u64=0x00000000000000C0LL;
gGPR[9]._u64=0x0000000000000000LL;
gGPR[10]._u64=0x0000000000000040LL;
gGPR[11]._u64=0xFFFFFFFFA4000040LL;
gGPR[16]._u64=0x0000000000000000LL;
gGPR[17]._u64=0x0000000000000000LL;
gGPR[18]._u64=0x0000000000000000LL;
gGPR[19]._u64=0x0000000000000000LL;
gGPR[20]._u64=g_ROM.TvType;
gGPR[21]._u64=0x0000000000000000LL;
gGPR[23]._u64=0x0000000000000006LL;
gGPR[24]._u64=0x0000000000000000LL;
gGPR[25]._u64=0xFFFFFFFFD73f2993LL;
gGPR[26]._u64=0x0000000000000000LL;
gGPR[27]._u64=0x0000000000000000LL;
gGPR[28]._u64=0x0000000000000000LL;
gGPR[29]._u64=0xFFFFFFFFA4001FF0LL;
gGPR[30]._u64=0x0000000000000000LL;
gGPR[31]._u64=0xFFFFFFFFA4001554LL;
switch (Country) {
case 0x44: //Germany
case 0x46: //french
case 0x49: //Italian
case 0x50: //Europe
case 0x53: //Spanish
case 0x55: //Australia
case 0x58: // ????
case 0x59: // X (PAL)
switch (cic_chip) {
case CIC_6102:
gGPR[5]._u64=0xFFFFFFFFC0F1D859LL;
gGPR[14]._u64=0x000000002DE108EALL;
gGPR[24]._u64=0x0000000000000000LL;
break;
case CIC_6103:
gGPR[5]._u64=0xFFFFFFFFD4646273LL;
gGPR[14]._u64=0x000000001AF99984LL;
gGPR[24]._u64=0x0000000000000000LL;
break;
case CIC_6105:
*(u32 *)&pIMemBase[0x04] = 0xBDA807FC;
gGPR[5]._u64=0xFFFFFFFFDECAAAD1LL;
gGPR[14]._u64=0x000000000CF85C13LL;
gGPR[24]._u64=0x0000000000000002LL;
break;
case CIC_6106:
gGPR[5]._u64=0xFFFFFFFFB04DC903LL;
gGPR[14]._u64=0x000000001AF99984LL;
gGPR[24]._u64=0x0000000000000002LL;
break;
default:
break;
}
gGPR[20]._u64=0x0000000000000000LL;
gGPR[23]._u64=0x0000000000000006LL;
gGPR[31]._u64=0xFFFFFFFFA4001554LL;
break;
case 0x37: // 7 (Beta)
case 0x41: // ????
case 0x45: //USA
case 0x4A: //Japan
default:
switch (cic_chip) {
case CIC_6102:
gGPR[5]._u64=0xFFFFFFFFC95973D5LL;
gGPR[14]._u64=0x000000002449A366LL;
break;
case CIC_6103:
gGPR[5]._u64=0xFFFFFFFF95315A28LL;
gGPR[14]._u64=0x000000005BACA1DFLL;
break;
case CIC_6105:
*(u32 *)&pIMemBase[0x04] = 0x8DA807FC;
gGPR[5]._u64=0x000000005493FB9ALL;
gGPR[14]._u64=0xFFFFFFFFC2C20384LL;
break;
case CIC_6106:
gGPR[5]._u64=0xFFFFFFFFE067221FLL;
gGPR[14]._u64=0x000000005CD2B70FLL;
break;
default:
break;
}
gGPR[20]._u64=0x0000000000000001LL;
gGPR[23]._u64=0x0000000000000000LL;
gGPR[24]._u64=0x0000000000000003LL;
gGPR[31]._u64=0xFFFFFFFFA4001550LL;
}
switch (cic_chip) {
case CIC_6101:
gGPR[22]._u64=0x000000000000003FLL;
break;
case CIC_6102:
gGPR[1]._u64=0x0000000000000001LL;
gGPR[2]._u64=0x000000000EBDA536LL;
gGPR[3]._u64=0x000000000EBDA536LL;
gGPR[4]._u64=0x000000000000A536LL;
gGPR[12]._u64=0xFFFFFFFFED10D0B3LL;
gGPR[13]._u64=0x000000001402A4CCLL;
gGPR[15]._u64=0x000000003103E121LL;
gGPR[22]._u64=0x000000000000003FLL;
gGPR[25]._u64=0xFFFFFFFF9DEBB54FLL;
break;
case CIC_6103:
gGPR[1]._u64=0x0000000000000001LL;
gGPR[2]._u64=0x0000000049A5EE96LL;
gGPR[3]._u64=0x0000000049A5EE96LL;
gGPR[4]._u64=0x000000000000EE96LL;
gGPR[12]._u64=0xFFFFFFFFCE9DFBF7LL;
gGPR[13]._u64=0xFFFFFFFFCE9DFBF7LL;
gGPR[15]._u64=0x0000000018B63D28LL;
gGPR[22]._u64=0x0000000000000078LL;
gGPR[25]._u64=0xFFFFFFFF825B21C9LL;
break;
case CIC_6105:
*(u32 *)&pIMemBase[0x00] = 0x3C0DBFC0;
*(u32 *)&pIMemBase[0x08] = 0x25AD07C0;
*(u32 *)&pIMemBase[0x0C] = 0x31080080;
*(u32 *)&pIMemBase[0x10] = 0x5500FFFC;
*(u32 *)&pIMemBase[0x14] = 0x3C0DBFC0;
*(u32 *)&pIMemBase[0x18] = 0x8DA80024;
*(u32 *)&pIMemBase[0x1C] = 0x3C0BB000;
gGPR[1]._u64=0x0000000000000000LL;
gGPR[2]._u64=0xFFFFFFFFF58B0FBFLL;
gGPR[3]._u64=0xFFFFFFFFF58B0FBFLL;
gGPR[4]._u64=0x0000000000000FBFLL;
gGPR[12]._u64=0xFFFFFFFF9651F81ELL;
gGPR[13]._u64=0x000000002D42AAC5LL;
gGPR[15]._u64=0x0000000056584D60LL;
gGPR[22]._u64=0x0000000000000091LL;
gGPR[25]._u64=0xFFFFFFFFCDCE565FLL;
break;
case CIC_6106:
gGPR[1]._u64=0x0000000000000000LL;
gGPR[2]._u64=0xFFFFFFFFA95930A4LL;
gGPR[3]._u64=0xFFFFFFFFA95930A4LL;
gGPR[4]._u64=0x00000000000030A4LL;
gGPR[12]._u64=0xFFFFFFFFBCB59510LL;
gGPR[13]._u64=0xFFFFFFFFBCB59510LL;
gGPR[15]._u64=0x000000007A3C07F4LL;
gGPR[22]._u64=0x0000000000000085LL;
gGPR[25]._u64=0x00000000465E3F72LL;
break;
default:
break;
}
// Also need to set up PI_BSD_DOM1 regs etc!
CPU_SetPC(0xA4000040);
}
bool ROM_ReBoot()
{
//
// Find out the CIC type and initialise various systems based on the CIC type
//
u8 rom_base[ RAMROM_GAME_OFFSET ];
RomBuffer::GetRomBytesRaw( rom_base, 0, RAMROM_GAME_OFFSET );
g_ROM.cic_chip = ROM_GenerateCICType( rom_base );
#ifdef DAEDALUS_DEBUG_CONSOLE
if (g_ROM.cic_chip == CIC_UNKNOWN)
{
//DAEDALUS_ERROR( "Unknown CIC CRC: 0x%08x\nAssuming CIC-6102", crc );
//DBGConsole_Msg(0, "[MUnknown CIC CRC: 0x%08x]", crc );
DBGConsole_Msg(0, "[MUnknown CIC]" );
}
else
{
DBGConsole_Msg(0, "[MRom uses %s]", ROM_GetCicName( g_ROM.cic_chip ) );
/* goodn64 already tell us if the rom is good or bad
u32 crc1;
u32 crc2;
if( ROM_DoCicCheckSum( g_ROM.cic_chip, &crc1, &crc2 ) )
{
if (crc1 != RomBuffer::ReadValueRaw< u32 >( 0x10 ) ||
crc2 != RomBuffer::ReadValueRaw< u32 >( 0x14 ))
{
DBGConsole_Msg(0, "[MWarning, CRC values don't match, fixing]");
RomBuffer::WriteValueRaw< u32 >( 0x10, crc1 );
RomBuffer::WriteValueRaw< u32 >( 0x14, crc2 );
}
}
else
{
// Unable to checksum - just continue with what we have
}
*/
}
#endif
// XXXX Update this rom's boot info
#ifdef DAEDALUS_ENABLE_DYNAREC_PROFILE
g_dwNumFrames = 0;
#endif
#ifdef DAEDALUS_ENABLE_OS_HOOKS
Patch_Reset();
#endif
// This will always return false since we always simulate boot code instead of loading from file
//
/*if ( ROM_LoadPIF( g_ROM.TvType ) )
{
ROM_RunPIFBoot( g_ROM.cic_chip );
}
else
{
ROM_SimulatePIFBoot( g_ROM.cic_chip, g_ROM.rh.CountryID );
}*/
ROM_SimulatePIFBoot( g_ROM.cic_chip, g_ROM.rh.CountryID );
return true;
}
void ROM_Unload()
{
}
//Most hacks are for the PSP, due the limitations of the hardware, and because we prefer speed over accuracy
void SpecificGameHacks( const ROMHeader & id )
{
printf("ROM ID[%04X]\n", id.CartID);
g_ROM.HACKS_u32 = 0; //Default to no game hacks
switch( id.CartID )
{
case 0x324a: g_ROM.GameHacks = WONDER_PROJECTJ2; break;
case 0x4547: g_ROM.GameHacks = GOLDEN_EYE; break;
case 0x5742: g_ROM.GameHacks = SUPER_BOWLING; break;
case 0x514D: g_ROM.GameHacks = PMARIO; break;
case 0x5632: g_ROM.GameHacks = CHAMELEON_TWIST_2; break;
case 0x4154: g_ROM.GameHacks = TARZAN; break;
case 0x4643: g_ROM.GameHacks = CLAY_FIGHTER_63; break;
case 0x504A: g_ROM.GameHacks = ISS64; break;
case 0x5944: g_ROM.GameHacks = DKR; break;
case 0x3247: g_ROM.GameHacks = EXTREME_G2; break;
case 0x5359: g_ROM.GameHacks = YOSHI; break;
case 0x4C42: g_ROM.GameHacks = BUCK_BUMBLE; break;
case 0x4441: g_ROM.GameHacks = WORMS_ARMAGEDDON; break;
case 0x3357: g_ROM.GameHacks = WCW_NITRO; break;
case 0x464A: // Jet Force Geminy
case 0x5647: // Glover
g_ROM.SET_ROUND_MODE = true;
break;
case 0x4B42: //Banjo-Kazooie
g_ROM.TLUT_HACK = true;
// g_ROM.DISABLE_LBU_OPT = true;
break;
//case 0x5750: //PilotWings64
case 0x4450: //Perfect Dark
g_ROM.DISABLE_LBU_OPT = true;
break;
case 0x5941: //AIDYN_CRONICLES
g_ROM.ALPHA_HACK = true;
g_ROM.GameHacks = AIDYN_CRONICLES;
break;
case 0x424C: //Mario Party 1
g_ROM.DISABLE_SIM_CVT_D_S = true;
break;
case 0x4A54: //Tom and Jerry
case 0x4d4a: //Earthworm Jim
case 0x5150: //PowerPuff Girls
g_ROM.DISABLE_SIM_CVT_D_S = true;
g_ROM.LOAD_T1_HACK = true;
break;
case 0x5144: //Donald Duck
case 0x3259: //Rayman2
g_ROM.SET_ROUND_MODE = true;
g_ROM.LOAD_T1_HACK = true;
g_ROM.T1_HACK = true;
break;
case 0x3358: //GEX3
case 0x3258: //GEX64
g_ROM.GameHacks = GEX_GECKO;
break;
case 0x4c5a: //ZELDA_OOT
g_ROM.ZELDA_HACK = true;
g_ROM.GameHacks = ZELDA_OOT;
break;
case 0x4F44: //DK64
g_ROM.SET_ROUND_MODE = true;
g_ROM.GameHacks = DK64;
break;
case 0x535a: //ZELDA_MM
g_ROM.TLUT_HACK = true;
g_ROM.ZELDA_HACK = true;
g_ROM.GameHacks = ZELDA_MM;
break;
case 0x5653: //SSV
g_ROM.LOAD_T1_HACK = true;
g_ROM.TLUT_HACK = true;
break;
case 0x5547: //Sin and punishment
g_ROM.TLUT_HACK = true;
g_ROM.GameHacks = SIN_PUNISHMENT;
break;
case 0x3742: //Banjo Tooie
g_ROM.GameHacks = BANJO_TOOIE;
g_ROM.TLUT_HACK = true;
break;
case 0x5544: //Duck Dodgers
case 0x3653: //Star soldier - vanishing earth
case 0x324C: //Top Gear Rally 2
case 0x5247: //Top Gear Rally
case 0x4552: //Resident Evil 2
case 0x4446: //Flying Dragon
case 0x534E: //Beetle Racing
g_ROM.TLUT_HACK = true;
break;
case 0x4641: //Animal crossing
g_ROM.TLUT_HACK = true;
g_ROM.GameHacks = ANIMAL_CROSSING;
break;
case 0x4842: //Body Harvest
case 0x434E: //Nightmare Creatures
case 0x5543: //Cruisn' USA
g_ROM.GameHacks = BODY_HARVEST;
break;
default:
break;
}
}
// Copy across text, nullptr terminate, and strip spaces
void ROM_GetRomNameFromHeader( std::string & rom_name, const ROMHeader & header )
{
char buffer[20+1];
memcpy( buffer, header.Name, 20 );
buffer[20] = '\0';
rom_name = buffer;
const char * whitespace_chars = " \t\r\n";
rom_name.erase( 0, rom_name.find_first_not_of(whitespace_chars) );
rom_name.erase( rom_name.find_last_not_of(whitespace_chars)+1 );
}
bool ROM_LoadFile()
{
RomID rom_id;
u32 rom_size;
ECicType boot_type;
if (ROM_GetRomDetailsByFilename(g_ROM.mFileName, &rom_id, &rom_size, &boot_type ))
{
RomSettings settings;
SRomPreferences preferences;
if (!CRomSettingsDB::Get().GetSettings( rom_id, &settings ))
{
settings.Reset();
}
if (!CPreferences::Get().GetRomPreferences( rom_id, &preferences ))
{
preferences.Reset();
}
return ROM_LoadFile( rom_id, settings, preferences );
}
return false;
}
void ROM_UnloadFile()
{
// Copy across various bits
g_ROM.mRomID = RomID();
g_ROM.settings = RomSettings();
}
bool ROM_LoadFile(const RomID & rom_id, const RomSettings & settings, const SRomPreferences & preferences )
{
DBGConsole_Msg(0, "Reading rom image: [C%s]", g_ROM.mFileName.c_str());
// Get information about the rom header
RomBuffer::GetRomBytesRaw( &g_ROM.rh, 0, sizeof(ROMHeader) );
// Swap into native format
ROMFile::ByteSwap_3210( &g_ROM.rh, sizeof(ROMHeader) );
#ifdef DAEDALUS_ENABLE_ASSERTS
DAEDALUS_ASSERT( RomID( g_ROM.rh ) == rom_id, "Why is the rom id incorrect?" );
#endif
// Copy across various bits
g_ROM.mRomID = rom_id;
g_ROM.settings = settings;
g_ROM.TvType = ROM_GetTvTypeFromID( g_ROM.rh.CountryID );
// Game specific hacks..
SpecificGameHacks( g_ROM.rh );
DumpROMInfo( g_ROM.rh );
// Read and apply preferences from preferences.ini
preferences.Apply();
// Parse cheat file this rom, if cheat feature is enabled
// This is also done when accessing the cheat menu
// But we do this when ROM is loaded too, to allow any forced enabled cheats to work.
if (gCheatsEnabled)
{
CheatCodes_Read( g_ROM.settings.GameName.c_str(), "Daedalus.cht", g_ROM.rh.CountryID );
}
DBGConsole_Msg(0, "[G%s]", g_ROM.settings.GameName.c_str());
DBGConsole_Msg(0, "This game has been certified as [G%s] (%s)", g_ROM.settings.Comment.c_str(), g_ROM.settings.Info.c_str());
DBGConsole_Msg(0, "SaveType: [G%s]", ROM_GetSaveTypeName( g_ROM.settings.SaveType ) );
DBGConsole_Msg(0, "ApplyPatches: [G%s]", gOSHooksEnabled ? "on" : "off");
DBGConsole_Msg(0, "Check Texture Hash Freq: [G%d]", gCheckTextureHashFrequency);
DBGConsole_Msg(0, "SpeedSync: [G%d]", gSpeedSyncEnabled);
DBGConsole_Msg(0, "DynaRec: [G%s]", gDynarecEnabled ? "on" : "off");
DBGConsole_Msg(0, "Cheats: [G%s]", gCheatsEnabled ? "on" : "off");
//Patch_ApplyPatches();
return true;
}
bool ROM_GetRomName( const std::filesystem::path filename, std::string & game_name )
{
auto p_rom_file = ROMFile::Create( filename );
if (p_rom_file == nullptr)
{
return false;
}
CNullOutputStream messages;
if (!p_rom_file->Open( messages ))
{
// delete p_rom_file;
return false;
}
// Only read in the header
const u32 bytes_to_read = sizeof(ROMHeader);
u32 size_aligned = AlignPow2( bytes_to_read, 4 ); // Needed?
u8 * p_bytes = new u8[size_aligned];
if (!p_rom_file->LoadData( bytes_to_read, p_bytes, messages ))
{
// Lots of files don't have any info - don't worry about it
delete [] p_bytes;
// delete p_rom_file;
return false;
}
// Swap into native format
ROMFile::ByteSwap_3210( p_bytes, bytes_to_read );
// Get the address of the rom header
// Setup the rom id and size
const ROMHeader * prh = reinterpret_cast<const ROMHeader *>( p_bytes );
ROM_GetRomNameFromHeader( game_name, *prh );
delete [] p_bytes;
return true;
}
bool ROM_GetRomDetailsByFilename( const std::filesystem::path filename, RomID * id, u32 * rom_size, ECicType * boot_type )
{
return CRomDB::Get().QueryByFilename( filename.c_str(), id, rom_size, boot_type );
}
bool ROM_GetRomDetailsByID( const RomID & id, u32 * rom_size, ECicType * boot_type )
{
return CRomDB::Get().QueryByID( id, rom_size, boot_type );
}
// Association between a country id value, tv type and name
struct CountryIDInfo
{
s8 CountryID;
const char * CountryName;
u32 TvType;
};
static constexpr std::array<CountryIDInfo, 13> g_CountryCodeInfo {
// static const CountryIDInfo g_CountryCodeInfo[] =
{
{ 0, "0", OS_TV_NTSC },
{ '7', "Beta", OS_TV_NTSC },
{ 'A', "NTSC", OS_TV_NTSC },
{ 'D', "Germany", OS_TV_PAL },
{ 'E', "USA", OS_TV_NTSC },
{ 'F', "France", OS_TV_PAL },
{ 'I', "Italy", OS_TV_PAL },
{ 'J', "Japan", OS_TV_NTSC },
{ 'P', "Europe", OS_TV_PAL },
{ 'S', "Spain", OS_TV_PAL },
{ 'U', "Australia", OS_TV_PAL },
{ 'X', "PAL", OS_TV_PAL },
{ 'Y', "PAL", OS_TV_PAL }
}};
// Get a string representing the country name from an ID value
const char * ROM_GetCountryNameFromID( u8 country_id )
{
for (u32 i = 0; i < g_CountryCodeInfo.size(); i++)
{
if (g_CountryCodeInfo[i].CountryID == country_id)
{
return g_CountryCodeInfo[i].CountryName;
}
}
return "?";
}
u32 ROM_GetTvTypeFromID( u8 country_id )
{
for (u32 i = 0; i < g_CountryCodeInfo.size(); i++)
{
if (g_CountryCodeInfo[i].CountryID == country_id)
{
return g_CountryCodeInfo[i].TvType;
}
}
return OS_TV_NTSC;
}