mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-09-30 05:08:46 +00:00
Reformat all the things. Have fun with merge conflicts.
This commit is contained in:
parent
2115e8a4a6
commit
3570c7f03a
1116 changed files with 187405 additions and 180344 deletions
|
@ -12,12 +12,10 @@
|
|||
#include "Common/MathUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/Boot/Boot_DOL.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/Debugger/Debugger_SymbolMap.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/DVDInterface.h"
|
||||
|
@ -25,10 +23,12 @@
|
|||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/ProcessorInterface.h"
|
||||
#include "Core/HW/VideoInterface.h"
|
||||
#include "Core/Host.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PPCAnalyst.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
#include "Core/PowerPC/SignatureDB.h"
|
||||
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
|
@ -36,129 +36,125 @@
|
|||
|
||||
bool CBoot::DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt)
|
||||
{
|
||||
std::vector<u8> buffer(length);
|
||||
if (!DVDInterface::GetVolume().Read(dvd_offset, length, buffer.data(), decrypt))
|
||||
return false;
|
||||
Memory::CopyToEmu(output_address, buffer.data(), length);
|
||||
return true;
|
||||
std::vector<u8> buffer(length);
|
||||
if (!DVDInterface::GetVolume().Read(dvd_offset, length, buffer.data(), decrypt))
|
||||
return false;
|
||||
Memory::CopyToEmu(output_address, buffer.data(), length);
|
||||
return true;
|
||||
}
|
||||
|
||||
void CBoot::Load_FST(bool _bIsWii)
|
||||
{
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return;
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return;
|
||||
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
|
||||
// copy first 20 bytes of disc to start of Mem 1
|
||||
DVDRead(/*offset*/0, /*address*/0, /*length*/0x20, false);
|
||||
// copy first 20 bytes of disc to start of Mem 1
|
||||
DVDRead(/*offset*/ 0, /*address*/ 0, /*length*/ 0x20, false);
|
||||
|
||||
// copy of game id
|
||||
Memory::Write_U32(Memory::Read_U32(0x0000), 0x3180);
|
||||
// copy of game id
|
||||
Memory::Write_U32(Memory::Read_U32(0x0000), 0x3180);
|
||||
|
||||
u32 shift = 0;
|
||||
if (_bIsWii)
|
||||
shift = 2;
|
||||
u32 shift = 0;
|
||||
if (_bIsWii)
|
||||
shift = 2;
|
||||
|
||||
u32 fst_offset = 0;
|
||||
u32 fst_size = 0;
|
||||
u32 max_fst_size = 0;
|
||||
u32 fst_offset = 0;
|
||||
u32 fst_size = 0;
|
||||
u32 max_fst_size = 0;
|
||||
|
||||
volume.ReadSwapped(0x0424, &fst_offset, _bIsWii);
|
||||
volume.ReadSwapped(0x0428, &fst_size, _bIsWii);
|
||||
volume.ReadSwapped(0x042c, &max_fst_size, _bIsWii);
|
||||
volume.ReadSwapped(0x0424, &fst_offset, _bIsWii);
|
||||
volume.ReadSwapped(0x0428, &fst_size, _bIsWii);
|
||||
volume.ReadSwapped(0x042c, &max_fst_size, _bIsWii);
|
||||
|
||||
u32 arena_high = ROUND_DOWN(0x817FFFFF - (max_fst_size << shift), 0x20);
|
||||
Memory::Write_U32(arena_high, 0x00000034);
|
||||
u32 arena_high = ROUND_DOWN(0x817FFFFF - (max_fst_size << shift), 0x20);
|
||||
Memory::Write_U32(arena_high, 0x00000034);
|
||||
|
||||
// load FST
|
||||
DVDRead(fst_offset << shift, arena_high, fst_size << shift, _bIsWii);
|
||||
Memory::Write_U32(arena_high, 0x00000038);
|
||||
Memory::Write_U32(max_fst_size << shift, 0x0000003c);
|
||||
// load FST
|
||||
DVDRead(fst_offset << shift, arena_high, fst_size << shift, _bIsWii);
|
||||
Memory::Write_U32(arena_high, 0x00000038);
|
||||
Memory::Write_U32(max_fst_size << shift, 0x0000003c);
|
||||
}
|
||||
|
||||
void CBoot::UpdateDebugger_MapLoaded()
|
||||
{
|
||||
Host_NotifyMapLoaded();
|
||||
Host_NotifyMapLoaded();
|
||||
}
|
||||
|
||||
bool CBoot::FindMapFile(std::string* existing_map_file,
|
||||
std::string* writable_map_file,
|
||||
bool CBoot::FindMapFile(std::string* existing_map_file, std::string* writable_map_file,
|
||||
std::string* title_id)
|
||||
{
|
||||
std::string title_id_str;
|
||||
size_t name_begin_index;
|
||||
std::string title_id_str;
|
||||
size_t name_begin_index;
|
||||
|
||||
SConfig& _StartupPara = SConfig::GetInstance();
|
||||
switch (_StartupPara.m_BootType)
|
||||
{
|
||||
case SConfig::BOOT_WII_NAND:
|
||||
{
|
||||
const DiscIO::CNANDContentLoader& Loader =
|
||||
DiscIO::CNANDContentManager::Access().GetNANDLoader(_StartupPara.m_strFilename);
|
||||
if (Loader.IsValid())
|
||||
{
|
||||
u64 TitleID = Loader.GetTitleID();
|
||||
title_id_str = StringFromFormat("%08X_%08X",
|
||||
(u32)(TitleID >> 32) & 0xFFFFFFFF,
|
||||
(u32)TitleID & 0xFFFFFFFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
SConfig& _StartupPara = SConfig::GetInstance();
|
||||
switch (_StartupPara.m_BootType)
|
||||
{
|
||||
case SConfig::BOOT_WII_NAND:
|
||||
{
|
||||
const DiscIO::CNANDContentLoader& Loader =
|
||||
DiscIO::CNANDContentManager::Access().GetNANDLoader(_StartupPara.m_strFilename);
|
||||
if (Loader.IsValid())
|
||||
{
|
||||
u64 TitleID = Loader.GetTitleID();
|
||||
title_id_str = StringFromFormat("%08X_%08X", (u32)(TitleID >> 32) & 0xFFFFFFFF,
|
||||
(u32)TitleID & 0xFFFFFFFF);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case SConfig::BOOT_ELF:
|
||||
case SConfig::BOOT_DOL:
|
||||
// Strip the .elf/.dol file extension and directories before the name
|
||||
name_begin_index = _StartupPara.m_strFilename.find_last_of("/") + 1;
|
||||
if ((_StartupPara.m_strFilename.find_last_of("\\") + 1) > name_begin_index)
|
||||
{
|
||||
name_begin_index = _StartupPara.m_strFilename.find_last_of("\\") + 1;
|
||||
}
|
||||
title_id_str = _StartupPara.m_strFilename.substr(
|
||||
name_begin_index, _StartupPara.m_strFilename.size() - 4 - name_begin_index);
|
||||
break;
|
||||
case SConfig::BOOT_ELF:
|
||||
case SConfig::BOOT_DOL:
|
||||
// Strip the .elf/.dol file extension and directories before the name
|
||||
name_begin_index = _StartupPara.m_strFilename.find_last_of("/") + 1;
|
||||
if ((_StartupPara.m_strFilename.find_last_of("\\") + 1) > name_begin_index)
|
||||
{
|
||||
name_begin_index = _StartupPara.m_strFilename.find_last_of("\\") + 1;
|
||||
}
|
||||
title_id_str = _StartupPara.m_strFilename.substr(
|
||||
name_begin_index, _StartupPara.m_strFilename.size() - 4 - name_begin_index);
|
||||
break;
|
||||
|
||||
default:
|
||||
title_id_str = _StartupPara.GetUniqueID();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
title_id_str = _StartupPara.GetUniqueID();
|
||||
break;
|
||||
}
|
||||
|
||||
if (writable_map_file)
|
||||
*writable_map_file = File::GetUserPath(D_MAPS_IDX) + title_id_str + ".map";
|
||||
if (writable_map_file)
|
||||
*writable_map_file = File::GetUserPath(D_MAPS_IDX) + title_id_str + ".map";
|
||||
|
||||
if (title_id)
|
||||
*title_id = title_id_str;
|
||||
if (title_id)
|
||||
*title_id = title_id_str;
|
||||
|
||||
bool found = false;
|
||||
static const std::string maps_directories[] = {
|
||||
File::GetUserPath(D_MAPS_IDX),
|
||||
File::GetSysDirectory() + MAPS_DIR DIR_SEP
|
||||
};
|
||||
for (size_t i = 0; !found && i < ArraySize(maps_directories); ++i)
|
||||
{
|
||||
std::string path = maps_directories[i] + title_id_str + ".map";
|
||||
if (File::Exists(path))
|
||||
{
|
||||
found = true;
|
||||
if (existing_map_file)
|
||||
*existing_map_file = path;
|
||||
}
|
||||
}
|
||||
bool found = false;
|
||||
static const std::string maps_directories[] = {File::GetUserPath(D_MAPS_IDX),
|
||||
File::GetSysDirectory() + MAPS_DIR DIR_SEP};
|
||||
for (size_t i = 0; !found && i < ArraySize(maps_directories); ++i)
|
||||
{
|
||||
std::string path = maps_directories[i] + title_id_str + ".map";
|
||||
if (File::Exists(path))
|
||||
{
|
||||
found = true;
|
||||
if (existing_map_file)
|
||||
*existing_map_file = path;
|
||||
}
|
||||
}
|
||||
|
||||
return found;
|
||||
return found;
|
||||
}
|
||||
|
||||
bool CBoot::LoadMapFromFilename()
|
||||
{
|
||||
std::string strMapFilename;
|
||||
bool found = FindMapFile(&strMapFilename, nullptr);
|
||||
if (found && g_symbolDB.LoadMap(strMapFilename))
|
||||
{
|
||||
UpdateDebugger_MapLoaded();
|
||||
return true;
|
||||
}
|
||||
std::string strMapFilename;
|
||||
bool found = FindMapFile(&strMapFilename, nullptr);
|
||||
if (found && g_symbolDB.LoadMap(strMapFilename))
|
||||
{
|
||||
UpdateDebugger_MapLoaded();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If ipl.bin is not found, this function does *some* of what BS1 does:
|
||||
|
@ -166,314 +162,319 @@ bool CBoot::LoadMapFromFilename()
|
|||
// It does not initialize the hardware or anything else like BS1 does.
|
||||
bool CBoot::Load_BS2(const std::string& _rBootROMFilename)
|
||||
{
|
||||
// CRC32
|
||||
const u32 USA_v1_0 = 0x6D740AE7; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385344#pid385344
|
||||
const u32 USA_v1_1 = 0xD5E6FEEA; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385334#pid385334
|
||||
const u32 USA_v1_2 = 0x86573808; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385399#pid385399
|
||||
const u32 BRA_v1_0 = 0x667D0B64; // GameCubes sold in Brazil have this IPL. Same as USA v1.2 but localized
|
||||
const u32 JAP_v1_0 = 0x6DAC1F2A; // Redump
|
||||
const u32 JAP_v1_1 = 0xD235E3F9; // https://bugs.dolphin-emu.org/issues/8936
|
||||
const u32 PAL_v1_0 = 0x4F319F43; // Redump
|
||||
const u32 PAL_v1_2 = 0xAD1B7F16; // Redump
|
||||
// CRC32
|
||||
const u32 USA_v1_0 =
|
||||
0x6D740AE7; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385344#pid385344
|
||||
const u32 USA_v1_1 =
|
||||
0xD5E6FEEA; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385334#pid385334
|
||||
const u32 USA_v1_2 =
|
||||
0x86573808; // https://forums.dolphin-emu.org/Thread-unknown-hash-on-ipl-bin?pid=385399#pid385399
|
||||
const u32 BRA_v1_0 =
|
||||
0x667D0B64; // GameCubes sold in Brazil have this IPL. Same as USA v1.2 but localized
|
||||
const u32 JAP_v1_0 = 0x6DAC1F2A; // Redump
|
||||
const u32 JAP_v1_1 = 0xD235E3F9; // https://bugs.dolphin-emu.org/issues/8936
|
||||
const u32 PAL_v1_0 = 0x4F319F43; // Redump
|
||||
const u32 PAL_v1_2 = 0xAD1B7F16; // Redump
|
||||
|
||||
// Load the whole ROM dump
|
||||
std::string data;
|
||||
if (!File::ReadFileToString(_rBootROMFilename, data))
|
||||
return false;
|
||||
// Load the whole ROM dump
|
||||
std::string data;
|
||||
if (!File::ReadFileToString(_rBootROMFilename, data))
|
||||
return false;
|
||||
|
||||
// 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;
|
||||
switch (ipl_hash)
|
||||
{
|
||||
case USA_v1_0:
|
||||
case USA_v1_1:
|
||||
case USA_v1_2:
|
||||
case BRA_v1_0:
|
||||
ipl_region = USA_DIR;
|
||||
break;
|
||||
case JAP_v1_0:
|
||||
case JAP_v1_1:
|
||||
ipl_region = JAP_DIR;
|
||||
break;
|
||||
case PAL_v1_0:
|
||||
case PAL_v1_2:
|
||||
ipl_region = EUR_DIR;
|
||||
break;
|
||||
default:
|
||||
PanicAlertT("IPL with unknown hash %x", ipl_hash);
|
||||
break;
|
||||
}
|
||||
// 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;
|
||||
switch (ipl_hash)
|
||||
{
|
||||
case USA_v1_0:
|
||||
case USA_v1_1:
|
||||
case USA_v1_2:
|
||||
case BRA_v1_0:
|
||||
ipl_region = USA_DIR;
|
||||
break;
|
||||
case JAP_v1_0:
|
||||
case JAP_v1_1:
|
||||
ipl_region = JAP_DIR;
|
||||
break;
|
||||
case PAL_v1_0:
|
||||
case PAL_v1_2:
|
||||
ipl_region = EUR_DIR;
|
||||
break;
|
||||
default:
|
||||
PanicAlertT("IPL with unknown hash %x", ipl_hash);
|
||||
break;
|
||||
}
|
||||
|
||||
std::string BootRegion = _rBootROMFilename.substr(_rBootROMFilename.find_last_of(DIR_SEP) - 3, 3);
|
||||
if (BootRegion != ipl_region)
|
||||
PanicAlertT("%s IPL found in %s directory. The disc might not be recognized",
|
||||
ipl_region.c_str(), BootRegion.c_str());
|
||||
std::string BootRegion = _rBootROMFilename.substr(_rBootROMFilename.find_last_of(DIR_SEP) - 3, 3);
|
||||
if (BootRegion != ipl_region)
|
||||
PanicAlertT("%s IPL found in %s directory. The disc might not be recognized",
|
||||
ipl_region.c_str(), BootRegion.c_str());
|
||||
|
||||
// Run the descrambler over the encrypted section containing BS1/BS2
|
||||
CEXIIPL::Descrambler((u8*)data.data() + 0x100, 0x1AFE00);
|
||||
// Run the descrambler over the encrypted section containing BS1/BS2
|
||||
CEXIIPL::Descrambler((u8*)data.data() + 0x100, 0x1AFE00);
|
||||
|
||||
// TODO: Execution is supposed to start at 0xFFF00000, not 0x81200000;
|
||||
// copying the initial boot code to 0x81200000 is a hack.
|
||||
// For now, HLE the first few instructions and start at 0x81200150
|
||||
// to work around this.
|
||||
Memory::CopyToEmu(0x01200000, data.data() + 0x100, 0x700);
|
||||
Memory::CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00);
|
||||
PowerPC::ppcState.gpr[3] = 0xfff0001f;
|
||||
PowerPC::ppcState.gpr[4] = 0x00002030;
|
||||
PowerPC::ppcState.gpr[5] = 0x0000009c;
|
||||
PowerPC::ppcState.msr = 0x00002030;
|
||||
PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT3U] = 0xfff0001f;
|
||||
PowerPC::ppcState.spr[SPR_IBAT3L] = 0xfff00001;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT3U] = 0xfff0001f;
|
||||
PowerPC::ppcState.spr[SPR_DBAT3L] = 0xfff00001;
|
||||
PC = 0x81200150;
|
||||
return true;
|
||||
// TODO: Execution is supposed to start at 0xFFF00000, not 0x81200000;
|
||||
// copying the initial boot code to 0x81200000 is a hack.
|
||||
// For now, HLE the first few instructions and start at 0x81200150
|
||||
// to work around this.
|
||||
Memory::CopyToEmu(0x01200000, data.data() + 0x100, 0x700);
|
||||
Memory::CopyToEmu(0x01300000, data.data() + 0x820, 0x1AFE00);
|
||||
PowerPC::ppcState.gpr[3] = 0xfff0001f;
|
||||
PowerPC::ppcState.gpr[4] = 0x00002030;
|
||||
PowerPC::ppcState.gpr[5] = 0x0000009c;
|
||||
PowerPC::ppcState.msr = 0x00002030;
|
||||
PowerPC::ppcState.spr[SPR_HID0] = 0x0011c464;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT3U] = 0xfff0001f;
|
||||
PowerPC::ppcState.spr[SPR_IBAT3L] = 0xfff00001;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT3U] = 0xfff0001f;
|
||||
PowerPC::ppcState.spr[SPR_DBAT3L] = 0xfff00001;
|
||||
PC = 0x81200150;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// Third boot step after BootManager and Core. See Call schedule in BootManager.cpp
|
||||
bool CBoot::BootUp()
|
||||
{
|
||||
SConfig& _StartupPara = SConfig::GetInstance();
|
||||
SConfig& _StartupPara = SConfig::GetInstance();
|
||||
|
||||
NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str());
|
||||
NOTICE_LOG(BOOT, "Booting %s", _StartupPara.m_strFilename.c_str());
|
||||
|
||||
g_symbolDB.Clear();
|
||||
g_symbolDB.Clear();
|
||||
|
||||
// PAL Wii uses NTSC framerate and linecount in 60Hz modes
|
||||
VideoInterface::Preset(_StartupPara.bNTSC || (_StartupPara.bWii && _StartupPara.bPAL60));
|
||||
// PAL Wii uses NTSC framerate and linecount in 60Hz modes
|
||||
VideoInterface::Preset(_StartupPara.bNTSC || (_StartupPara.bWii && _StartupPara.bPAL60));
|
||||
|
||||
switch (_StartupPara.m_BootType)
|
||||
{
|
||||
// GCM and Wii
|
||||
case SConfig::BOOT_ISO:
|
||||
{
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strFilename);
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return false;
|
||||
switch (_StartupPara.m_BootType)
|
||||
{
|
||||
// GCM and Wii
|
||||
case SConfig::BOOT_ISO:
|
||||
{
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strFilename);
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return false;
|
||||
|
||||
const DiscIO::IVolume& pVolume = DVDInterface::GetVolume();
|
||||
const DiscIO::IVolume& pVolume = DVDInterface::GetVolume();
|
||||
|
||||
if ((pVolume.GetVolumeType() == DiscIO::IVolume::WII_DISC) != _StartupPara.bWii)
|
||||
{
|
||||
PanicAlertT("Warning - starting ISO in wrong console mode!");
|
||||
}
|
||||
if ((pVolume.GetVolumeType() == DiscIO::IVolume::WII_DISC) != _StartupPara.bWii)
|
||||
{
|
||||
PanicAlertT("Warning - starting ISO in wrong console mode!");
|
||||
}
|
||||
|
||||
std::string unique_id = DVDInterface::GetVolume().GetUniqueID();
|
||||
if (unique_id.size() >= 4)
|
||||
VideoInterface::SetRegionReg(unique_id.at(3));
|
||||
std::string unique_id = DVDInterface::GetVolume().GetUniqueID();
|
||||
if (unique_id.size() >= 4)
|
||||
VideoInterface::SetRegionReg(unique_id.at(3));
|
||||
|
||||
std::vector<u8> tmd_buffer = pVolume.GetTMD();
|
||||
if (!tmd_buffer.empty())
|
||||
{
|
||||
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
|
||||
}
|
||||
std::vector<u8> tmd_buffer = pVolume.GetTMD();
|
||||
if (!tmd_buffer.empty())
|
||||
{
|
||||
WII_IPC_HLE_Interface::ES_DIVerify(tmd_buffer);
|
||||
}
|
||||
|
||||
_StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::IVolume::WII_DISC;
|
||||
_StartupPara.bWii = pVolume.GetVolumeType() == DiscIO::IVolume::WII_DISC;
|
||||
|
||||
// HLE BS2 or not
|
||||
if (_StartupPara.bHLE_BS2)
|
||||
{
|
||||
EmulatedBS2(_StartupPara.bWii);
|
||||
}
|
||||
else if (!Load_BS2(_StartupPara.m_strBootROM))
|
||||
{
|
||||
// If we can't load the bootrom file we HLE it instead
|
||||
EmulatedBS2(_StartupPara.bWii);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load patches if they weren't already
|
||||
PatchEngine::LoadPatches();
|
||||
}
|
||||
// HLE BS2 or not
|
||||
if (_StartupPara.bHLE_BS2)
|
||||
{
|
||||
EmulatedBS2(_StartupPara.bWii);
|
||||
}
|
||||
else if (!Load_BS2(_StartupPara.m_strBootROM))
|
||||
{
|
||||
// If we can't load the bootrom file we HLE it instead
|
||||
EmulatedBS2(_StartupPara.bWii);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Load patches if they weren't already
|
||||
PatchEngine::LoadPatches();
|
||||
}
|
||||
|
||||
// Scan for common HLE functions
|
||||
if (_StartupPara.bSkipIdle && _StartupPara.bHLE_BS2 && !_StartupPara.bEnableDebugging)
|
||||
{
|
||||
PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB);
|
||||
SignatureDB db;
|
||||
if (db.Load(File::GetSysDirectory() + TOTALDB))
|
||||
{
|
||||
db.Apply(&g_symbolDB);
|
||||
HLE::PatchFunctions();
|
||||
db.Clear();
|
||||
}
|
||||
}
|
||||
// Scan for common HLE functions
|
||||
if (_StartupPara.bSkipIdle && _StartupPara.bHLE_BS2 && !_StartupPara.bEnableDebugging)
|
||||
{
|
||||
PPCAnalyst::FindFunctions(0x80004000, 0x811fffff, &g_symbolDB);
|
||||
SignatureDB db;
|
||||
if (db.Load(File::GetSysDirectory() + TOTALDB))
|
||||
{
|
||||
db.Apply(&g_symbolDB);
|
||||
HLE::PatchFunctions();
|
||||
db.Clear();
|
||||
}
|
||||
}
|
||||
|
||||
// Try to load the symbol map if there is one, and then scan it for
|
||||
// and eventually replace code
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
// Try to load the symbol map if there is one, and then scan it for
|
||||
// and eventually replace code
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// DOL
|
||||
case SConfig::BOOT_DOL:
|
||||
{
|
||||
CDolLoader dolLoader(_StartupPara.m_strFilename);
|
||||
if (!dolLoader.IsValid())
|
||||
return false;
|
||||
// DOL
|
||||
case SConfig::BOOT_DOL:
|
||||
{
|
||||
CDolLoader dolLoader(_StartupPara.m_strFilename);
|
||||
if (!dolLoader.IsValid())
|
||||
return false;
|
||||
|
||||
// Check if we have gotten a Wii file or not
|
||||
bool dolWii = dolLoader.IsWii();
|
||||
if (dolWii != _StartupPara.bWii)
|
||||
{
|
||||
PanicAlertT("Warning - starting DOL in wrong console mode!");
|
||||
}
|
||||
// Check if we have gotten a Wii file or not
|
||||
bool dolWii = dolLoader.IsWii();
|
||||
if (dolWii != _StartupPara.bWii)
|
||||
{
|
||||
PanicAlertT("Warning - starting DOL in wrong console mode!");
|
||||
}
|
||||
|
||||
bool BS2Success = false;
|
||||
bool BS2Success = false;
|
||||
|
||||
if (dolWii)
|
||||
{
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
else if ((!DVDInterface::VolumeIsValid() || DVDInterface::GetVolume().GetVolumeType() != DiscIO::IVolume::WII_DISC) &&
|
||||
!_StartupPara.m_strDefaultISO.empty())
|
||||
{
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
if (dolWii)
|
||||
{
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
else if ((!DVDInterface::VolumeIsValid() ||
|
||||
DVDInterface::GetVolume().GetVolumeType() != DiscIO::IVolume::WII_DISC) &&
|
||||
!_StartupPara.m_strDefaultISO.empty())
|
||||
{
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str());
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, dolWii, _StartupPara.m_strApploader, _StartupPara.m_strFilename);
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str());
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, dolWii,
|
||||
_StartupPara.m_strApploader, _StartupPara.m_strFilename);
|
||||
BS2Success = EmulatedBS2(dolWii);
|
||||
}
|
||||
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
|
||||
if (!BS2Success)
|
||||
{
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
if (!BS2Success)
|
||||
{
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
|
||||
dolLoader.Load();
|
||||
PC = dolLoader.GetEntryPoint();
|
||||
}
|
||||
dolLoader.Load();
|
||||
PC = dolLoader.GetEntryPoint();
|
||||
}
|
||||
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// ELF
|
||||
case SConfig::BOOT_ELF:
|
||||
{
|
||||
// load image or create virtual drive from directory
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str());
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, _StartupPara.bWii);
|
||||
}
|
||||
else if (!_StartupPara.m_strDefaultISO.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Loading default ISO %s", _StartupPara.m_strDefaultISO.c_str());
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
}
|
||||
else
|
||||
{
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strFilename, _StartupPara.bWii);
|
||||
}
|
||||
// ELF
|
||||
case SConfig::BOOT_ELF:
|
||||
{
|
||||
// load image or create virtual drive from directory
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Setting DVDRoot %s", _StartupPara.m_strDVDRoot.c_str());
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, _StartupPara.bWii);
|
||||
}
|
||||
else if (!_StartupPara.m_strDefaultISO.empty())
|
||||
{
|
||||
NOTICE_LOG(BOOT, "Loading default ISO %s", _StartupPara.m_strDefaultISO.c_str());
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
}
|
||||
else
|
||||
{
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strFilename, _StartupPara.bWii);
|
||||
}
|
||||
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
|
||||
// Poor man's bootup
|
||||
if(_StartupPara.bWii)
|
||||
SetupWiiMemory(DiscIO::IVolume::COUNTRY_UNKNOWN);
|
||||
else
|
||||
EmulatedBS2_GC(true);
|
||||
// Poor man's bootup
|
||||
if (_StartupPara.bWii)
|
||||
SetupWiiMemory(DiscIO::IVolume::COUNTRY_UNKNOWN);
|
||||
else
|
||||
EmulatedBS2_GC(true);
|
||||
|
||||
Load_FST(_StartupPara.bWii);
|
||||
if(!Boot_ELF(_StartupPara.m_strFilename))
|
||||
return false;
|
||||
Load_FST(_StartupPara.bWii);
|
||||
if (!Boot_ELF(_StartupPara.m_strFilename))
|
||||
return false;
|
||||
|
||||
UpdateDebugger_MapLoaded();
|
||||
Dolphin_Debugger::AddAutoBreakpoints();
|
||||
break;
|
||||
}
|
||||
UpdateDebugger_MapLoaded();
|
||||
Dolphin_Debugger::AddAutoBreakpoints();
|
||||
break;
|
||||
}
|
||||
|
||||
// Wii WAD
|
||||
case SConfig::BOOT_WII_NAND:
|
||||
Boot_WiiWAD(_StartupPara.m_strFilename);
|
||||
// Wii WAD
|
||||
case SConfig::BOOT_WII_NAND:
|
||||
Boot_WiiWAD(_StartupPara.m_strFilename);
|
||||
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
|
||||
// load default image or create virtual drive from directory
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, true);
|
||||
else if (!_StartupPara.m_strDefaultISO.empty())
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
// load default image or create virtual drive from directory
|
||||
if (!_StartupPara.m_strDVDRoot.empty())
|
||||
DVDInterface::SetVolumeDirectory(_StartupPara.m_strDVDRoot, true);
|
||||
else if (!_StartupPara.m_strDefaultISO.empty())
|
||||
DVDInterface::SetVolumeName(_StartupPara.m_strDefaultISO);
|
||||
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
break;
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
break;
|
||||
|
||||
// Bootstrap 2 (AKA: Initial Program Loader, "BIOS")
|
||||
case SConfig::BOOT_BS2:
|
||||
{
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
if (Load_BS2(_StartupPara.m_strBootROM))
|
||||
{
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Bootstrap 2 (AKA: Initial Program Loader, "BIOS")
|
||||
case SConfig::BOOT_BS2:
|
||||
{
|
||||
DVDInterface::SetDiscInside(DVDInterface::VolumeIsValid());
|
||||
if (Load_BS2(_StartupPara.m_strBootROM))
|
||||
{
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case SConfig::BOOT_DFF:
|
||||
// do nothing
|
||||
break;
|
||||
|
||||
case SConfig::BOOT_DFF:
|
||||
// do nothing
|
||||
break;
|
||||
default:
|
||||
{
|
||||
PanicAlertT("Tried to load an unknown file type.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
{
|
||||
PanicAlertT("Tried to load an unknown file type.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code
|
||||
// handler
|
||||
if (!SConfig::GetInstance().bEnableCheats)
|
||||
{
|
||||
HLE::Patch(0x80001800, "HBReload");
|
||||
Memory::CopyToEmu(0x00001804, "STUBHAXX", 8);
|
||||
}
|
||||
|
||||
// HLE jump to loader (homebrew). Disabled when Gecko is active as it interferes with the code handler
|
||||
if (!SConfig::GetInstance().bEnableCheats)
|
||||
{
|
||||
HLE::Patch(0x80001800, "HBReload");
|
||||
Memory::CopyToEmu(0x00001804, "STUBHAXX", 8);
|
||||
}
|
||||
|
||||
// Not part of the binary itself, but either we or Gecko OS might insert
|
||||
// this, and it doesn't clear the icache properly.
|
||||
HLE::Patch(0x800018a8, "GeckoCodehandler");
|
||||
return true;
|
||||
// Not part of the binary itself, but either we or Gecko OS might insert
|
||||
// this, and it doesn't clear the icache properly.
|
||||
HLE::Patch(0x800018a8, "GeckoCodehandler");
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -11,50 +11,48 @@
|
|||
|
||||
struct CountrySetting
|
||||
{
|
||||
const std::string area;
|
||||
const std::string video;
|
||||
const std::string game;
|
||||
const std::string code;
|
||||
const std::string area;
|
||||
const std::string video;
|
||||
const std::string game;
|
||||
const std::string code;
|
||||
};
|
||||
|
||||
class CBoot
|
||||
{
|
||||
public:
|
||||
static bool BootUp();
|
||||
static bool IsElfWii(const std::string& filename);
|
||||
|
||||
static bool BootUp();
|
||||
static bool IsElfWii(const std::string& filename);
|
||||
|
||||
// Tries to find a map file for the current game by looking first in the
|
||||
// local user directory, then in the shared user directory.
|
||||
//
|
||||
// If existing_map_file is not nullptr and a map file exists, it is set to the
|
||||
// path to the existing map file.
|
||||
//
|
||||
// If writable_map_file is not nullptr, it is set to the path to where a map
|
||||
// file should be saved.
|
||||
//
|
||||
// If title_id is not nullptr, it is set to the title id
|
||||
//
|
||||
// Returns true if a map file exists, false if none could be found.
|
||||
static bool FindMapFile(std::string* existing_map_file,
|
||||
std::string* writable_map_file,
|
||||
std::string* title_id = nullptr);
|
||||
// Tries to find a map file for the current game by looking first in the
|
||||
// local user directory, then in the shared user directory.
|
||||
//
|
||||
// If existing_map_file is not nullptr and a map file exists, it is set to the
|
||||
// path to the existing map file.
|
||||
//
|
||||
// If writable_map_file is not nullptr, it is set to the path to where a map
|
||||
// file should be saved.
|
||||
//
|
||||
// If title_id is not nullptr, it is set to the title id
|
||||
//
|
||||
// Returns true if a map file exists, false if none could be found.
|
||||
static bool FindMapFile(std::string* existing_map_file, std::string* writable_map_file,
|
||||
std::string* title_id = nullptr);
|
||||
|
||||
private:
|
||||
static bool DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt);
|
||||
static void RunFunction(u32 _iAddr);
|
||||
static bool DVDRead(u64 dvd_offset, u32 output_address, u32 length, bool decrypt);
|
||||
static void RunFunction(u32 _iAddr);
|
||||
|
||||
static void UpdateDebugger_MapLoaded();
|
||||
static void UpdateDebugger_MapLoaded();
|
||||
|
||||
static bool LoadMapFromFilename();
|
||||
static bool Boot_ELF(const std::string& filename);
|
||||
static bool Boot_WiiWAD(const std::string& filename);
|
||||
static bool LoadMapFromFilename();
|
||||
static bool Boot_ELF(const std::string& filename);
|
||||
static bool Boot_WiiWAD(const std::string& filename);
|
||||
|
||||
static bool EmulatedBS2_GC(bool skipAppLoader = false);
|
||||
static bool EmulatedBS2_Wii();
|
||||
static bool EmulatedBS2(bool _bIsWii);
|
||||
static bool Load_BS2(const std::string& _rBootROMFilename);
|
||||
static void Load_FST(bool _bIsWii);
|
||||
static bool EmulatedBS2_GC(bool skipAppLoader = false);
|
||||
static bool EmulatedBS2_Wii();
|
||||
static bool EmulatedBS2(bool _bIsWii);
|
||||
static bool Load_BS2(const std::string& _rBootROMFilename);
|
||||
static void Load_FST(bool _bIsWii);
|
||||
|
||||
static bool SetupWiiMemory(DiscIO::IVolume::ECountry country);
|
||||
static bool SetupWiiMemory(DiscIO::IVolume::ECountry country);
|
||||
};
|
||||
|
|
|
@ -8,25 +8,25 @@
|
|||
#include "Common/NandPaths.h"
|
||||
#include "Common/SettingsHandler.h"
|
||||
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/Core.h"
|
||||
#include "Core/MemTools.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/CPU.h"
|
||||
#include "Core/HW/DVDInterface.h"
|
||||
#include "Core/HW/EXI_DeviceIPL.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/MemTools.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
void CBoot::RunFunction(u32 _iAddr)
|
||||
{
|
||||
PC = _iAddr;
|
||||
LR = 0x00;
|
||||
PC = _iAddr;
|
||||
LR = 0x00;
|
||||
|
||||
while (PC != 0x00)
|
||||
PowerPC::SingleStep();
|
||||
while (PC != 0x00)
|
||||
PowerPC::SingleStep();
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
|
@ -35,282 +35,293 @@ void CBoot::RunFunction(u32 _iAddr)
|
|||
// execute the apploader, function by function, using the above utility.
|
||||
bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
||||
{
|
||||
INFO_LOG(BOOT, "Faking GC BS2...");
|
||||
INFO_LOG(BOOT, "Faking GC BS2...");
|
||||
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
|
||||
// Write necessary values
|
||||
// Here we write values to memory that the apploader does not take care of. Game info goes
|
||||
// to 0x80000000 according to YAGCD 4.2.
|
||||
// Write necessary values
|
||||
// Here we write values to memory that the apploader does not take care of. Game info goes
|
||||
// to 0x80000000 according to YAGCD 4.2.
|
||||
|
||||
// It's possible to boot DOL and ELF files without a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDRead(/*offset*/0x00000000, /*address*/0x00000000, 0x20, false); // write disc info
|
||||
// It's possible to boot DOL and ELF files without a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDRead(/*offset*/ 0x00000000, /*address*/ 0x00000000, 0x20, false); // write disc info
|
||||
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E, 0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail)
|
||||
// TODO determine why some games fail when using a retail ID. (Seem to take different EXI paths, see Ikaruga for example)
|
||||
PowerPC::HostWrite_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see YAGCD 4.2.1.1.2
|
||||
PowerPC::HostWrite_U32(0x0D15EA5E,
|
||||
0x80000020); // Booted from bootrom. 0xE5207C22 = booted from jtag
|
||||
PowerPC::HostWrite_U32(Memory::REALRAM_SIZE,
|
||||
0x80000028); // Physical Memory Size (24MB on retail)
|
||||
// TODO determine why some games fail when using a retail ID. (Seem to take different EXI paths,
|
||||
// see Ikaruga for example)
|
||||
PowerPC::HostWrite_U32(
|
||||
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)
|
||||
PowerPC::HostWrite_U32(SConfig::GetInstance().bNTSC ? 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)
|
||||
PowerPC::HostWrite_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external
|
||||
// (retail consoles have no external ARAM)
|
||||
|
||||
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
PowerPC::HostWrite_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
|
||||
PowerPC::HostWrite_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
|
||||
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000300); // Write default DFI Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000800); // Write default FPU Handler: rfi
|
||||
PowerPC::HostWrite_U32(0x4c000064, 0x80000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
PowerPC::HostWrite_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); // Preset time base ticks
|
||||
// HIO checks this
|
||||
//PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||
PowerPC::HostWrite_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000,
|
||||
0x800030D8); // Preset time base ticks
|
||||
// HIO checks this
|
||||
// PowerPC::HostWrite_U16(0x8200, 0x000030e6); // Console type
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return false;
|
||||
if (!DVDInterface::VolumeIsValid())
|
||||
return false;
|
||||
|
||||
// Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc,
|
||||
// but the size can differ between discs. Compare with YAGCD chap 13.
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
const u32 apploader_offset = 0x2440;
|
||||
u32 apploader_entry, apploader_size, apploader_trailer;
|
||||
if (skipAppLoader ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, false) ||
|
||||
apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1)
|
||||
{
|
||||
INFO_LOG(BOOT, "GC BS2: Not running apploader!");
|
||||
return false;
|
||||
}
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, false);
|
||||
// Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc,
|
||||
// but the size can differ between discs. Compare with YAGCD chap 13.
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
const u32 apploader_offset = 0x2440;
|
||||
u32 apploader_entry, apploader_size, apploader_trailer;
|
||||
if (skipAppLoader || !volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, false) ||
|
||||
apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1)
|
||||
{
|
||||
INFO_LOG(BOOT, "GC BS2: Not running apploader!");
|
||||
return false;
|
||||
}
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, false);
|
||||
|
||||
// Setup pointers like real BS2 does
|
||||
if (SConfig::GetInstance().bNTSC)
|
||||
{
|
||||
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)
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::ppcState.gpr[1] = 0x815edca8;
|
||||
PowerPC::ppcState.gpr[2] = 0x814b5b20;
|
||||
PowerPC::ppcState.gpr[13] = 0x814b4fc0;
|
||||
}
|
||||
// Setup pointers like real BS2 does
|
||||
if (SConfig::GetInstance().bNTSC)
|
||||
{
|
||||
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)
|
||||
}
|
||||
else
|
||||
{
|
||||
PowerPC::ppcState.gpr[1] = 0x815edca8;
|
||||
PowerPC::ppcState.gpr[2] = 0x814b5b20;
|
||||
PowerPC::ppcState.gpr[13] = 0x814b4fc0;
|
||||
}
|
||||
|
||||
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
|
||||
// TODO - Make Apploader(or just RunFunction()) debuggable!!!
|
||||
|
||||
// Call iAppLoaderEntry.
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry");
|
||||
u32 iAppLoaderFuncAddr = 0x80003100;
|
||||
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
|
||||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(apploader_entry);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
// Call iAppLoaderEntry.
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry");
|
||||
u32 iAppLoaderFuncAddr = 0x80003100;
|
||||
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
|
||||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(apploader_entry);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit");
|
||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||
RunFunction(iAppLoaderInit);
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit");
|
||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||
RunFunction(iAppLoaderInit);
|
||||
|
||||
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
|
||||
// To give you an idea about where the stuff is located on the disc take a look at yagcd
|
||||
// ch 13.
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderMain");
|
||||
do
|
||||
{
|
||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||
PowerPC::ppcState.gpr[4] = 0x81300008;
|
||||
PowerPC::ppcState.gpr[5] = 0x8130000c;
|
||||
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
|
||||
// To give you an idea about where the stuff is located on the disc take a look at yagcd
|
||||
// ch 13.
|
||||
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderMain");
|
||||
do
|
||||
{
|
||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||
PowerPC::ppcState.gpr[4] = 0x81300008;
|
||||
PowerPC::ppcState.gpr[5] = 0x8130000c;
|
||||
|
||||
RunFunction(iAppLoaderMain);
|
||||
RunFunction(iAppLoaderMain);
|
||||
|
||||
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c);
|
||||
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c);
|
||||
|
||||
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
|
||||
DVDRead(iDVDOffset, iRamAddress, iLength, false);
|
||||
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
|
||||
iRamAddress, iLength);
|
||||
DVDRead(iDVDOffset, iRamAddress, iLength, false);
|
||||
|
||||
} while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
} while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
|
||||
// iAppLoaderClose
|
||||
DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose");
|
||||
RunFunction(iAppLoaderClose);
|
||||
// iAppLoaderClose
|
||||
DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose");
|
||||
RunFunction(iAppLoaderClose);
|
||||
|
||||
// return
|
||||
PC = PowerPC::ppcState.gpr[3];
|
||||
// return
|
||||
PC = PowerPC::ppcState.gpr[3];
|
||||
|
||||
// Load patches
|
||||
PatchEngine::LoadPatches();
|
||||
// Load patches
|
||||
PatchEngine::LoadPatches();
|
||||
|
||||
// If we have any patches that need to be applied very early, here's a good place
|
||||
PatchEngine::ApplyFramePatches();
|
||||
// If we have any patches that need to be applied very early, here's a good place
|
||||
PatchEngine::ApplyFramePatches();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CBoot::SetupWiiMemory(DiscIO::IVolume::ECountry country)
|
||||
{
|
||||
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::IVolume::ECountry, const CountrySetting> country_settings = {
|
||||
{DiscIO::IVolume::COUNTRY_EUROPE, SETTING_EUROPE},
|
||||
{DiscIO::IVolume::COUNTRY_USA, SETTING_USA},
|
||||
{DiscIO::IVolume::COUNTRY_JAPAN, SETTING_JAPAN},
|
||||
{DiscIO::IVolume::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::IVolume::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 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::IVolume::ECountry, const CountrySetting> country_settings = {
|
||||
{DiscIO::IVolume::COUNTRY_EUROPE, SETTING_EUROPE},
|
||||
{DiscIO::IVolume::COUNTRY_USA, SETTING_USA},
|
||||
{DiscIO::IVolume::COUNTRY_JAPAN, SETTING_JAPAN},
|
||||
{DiscIO::IVolume::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::IVolume::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
|
||||
|
||||
SettingsHandler gen;
|
||||
std::string serno;
|
||||
std::string settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_SETTING);
|
||||
if (File::Exists(settings_Filename))
|
||||
{
|
||||
File::IOFile settingsFileHandle(settings_Filename, "rb");
|
||||
if (settingsFileHandle.ReadBytes((void*)gen.GetData(), SettingsHandler::SETTINGS_SIZE))
|
||||
{
|
||||
gen.Decrypt();
|
||||
serno = gen.GetValue("SERNO");
|
||||
gen.Reset();
|
||||
}
|
||||
File::Delete(settings_Filename);
|
||||
}
|
||||
SettingsHandler gen;
|
||||
std::string serno;
|
||||
std::string settings_Filename(
|
||||
Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_SETTING);
|
||||
if (File::Exists(settings_Filename))
|
||||
{
|
||||
File::IOFile settingsFileHandle(settings_Filename, "rb");
|
||||
if (settingsFileHandle.ReadBytes((void*)gen.GetData(), SettingsHandler::SETTINGS_SIZE))
|
||||
{
|
||||
gen.Decrypt();
|
||||
serno = gen.GetValue("SERNO");
|
||||
gen.Reset();
|
||||
}
|
||||
File::Delete(settings_Filename);
|
||||
}
|
||||
|
||||
if (serno.empty() || serno == "000000000")
|
||||
{
|
||||
if (Core::g_want_determinism)
|
||||
serno = "123456789";
|
||||
else
|
||||
serno = gen.generateSerialNumber();
|
||||
INFO_LOG(BOOT, "No previous serial number found, generated one instead: %s", serno.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(BOOT, "Using serial number: %s", serno.c_str());
|
||||
}
|
||||
if (serno.empty() || serno == "000000000")
|
||||
{
|
||||
if (Core::g_want_determinism)
|
||||
serno = "123456789";
|
||||
else
|
||||
serno = gen.generateSerialNumber();
|
||||
INFO_LOG(BOOT, "No previous serial number found, generated one instead: %s", serno.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
INFO_LOG(BOOT, "Using serial number: %s", serno.c_str());
|
||||
}
|
||||
|
||||
std::string model = "RVL-001(" + country_setting.area + ")";
|
||||
gen.AddSetting("AREA", country_setting.area);
|
||||
gen.AddSetting("MODEL", model);
|
||||
gen.AddSetting("DVD", "0");
|
||||
gen.AddSetting("MPCH", "0x7FFE");
|
||||
gen.AddSetting("CODE", country_setting.code);
|
||||
gen.AddSetting("SERNO", serno);
|
||||
gen.AddSetting("VIDEO", country_setting.video);
|
||||
gen.AddSetting("GAME", country_setting.game);
|
||||
std::string model = "RVL-001(" + country_setting.area + ")";
|
||||
gen.AddSetting("AREA", country_setting.area);
|
||||
gen.AddSetting("MODEL", model);
|
||||
gen.AddSetting("DVD", "0");
|
||||
gen.AddSetting("MPCH", "0x7FFE");
|
||||
gen.AddSetting("CODE", country_setting.code);
|
||||
gen.AddSetting("SERNO", serno);
|
||||
gen.AddSetting("VIDEO", country_setting.video);
|
||||
gen.AddSetting("GAME", country_setting.game);
|
||||
|
||||
File::CreateFullPath(settings_Filename);
|
||||
{
|
||||
File::IOFile settingsFileHandle(settings_Filename, "wb");
|
||||
File::CreateFullPath(settings_Filename);
|
||||
{
|
||||
File::IOFile settingsFileHandle(settings_Filename, "wb");
|
||||
|
||||
if (!settingsFileHandle.WriteBytes(gen.GetData(), SettingsHandler::SETTINGS_SIZE))
|
||||
{
|
||||
PanicAlertT("SetupWiiMemory: Can't create setting.txt file");
|
||||
return false;
|
||||
}
|
||||
// Write the 256 byte setting.txt to memory.
|
||||
Memory::CopyToEmu(0x3800, gen.GetData(), SettingsHandler::SETTINGS_SIZE);
|
||||
}
|
||||
if (!settingsFileHandle.WriteBytes(gen.GetData(), SettingsHandler::SETTINGS_SIZE))
|
||||
{
|
||||
PanicAlertT("SetupWiiMemory: Can't create setting.txt file");
|
||||
return false;
|
||||
}
|
||||
// Write the 256 byte setting.txt to memory.
|
||||
Memory::CopyToEmu(0x3800, gen.GetData(), SettingsHandler::SETTINGS_SIZE);
|
||||
}
|
||||
|
||||
INFO_LOG(BOOT, "Setup Wii Memory...");
|
||||
INFO_LOG(BOOT, "Setup Wii Memory...");
|
||||
|
||||
/*
|
||||
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
|
||||
values in this region will also be placed here by the game as it boots.
|
||||
They are:
|
||||
0x80000038 Start of FST
|
||||
0x8000003c Size of FST Size
|
||||
0x80000060 Copyright code
|
||||
*/
|
||||
/*
|
||||
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
|
||||
values in this region will also be placed here by the game as it boots.
|
||||
They are:
|
||||
0x80000038 Start of FST
|
||||
0x8000003c Size of FST Size
|
||||
0x80000060 Copyright code
|
||||
*/
|
||||
|
||||
// When booting a WAD or the system menu, there will probably not be a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDRead(0x00000000, 0x00000000, 0x20, false); // Game Code
|
||||
// When booting a WAD or the system menu, there will probably not be a disc inserted
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
DVDRead(0x00000000, 0x00000000, 0x20, false); // Game Code
|
||||
|
||||
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
|
||||
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
|
||||
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
|
||||
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
||||
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
||||
// 38, 3C should get start, size of FST through apploader
|
||||
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
|
||||
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
|
||||
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
|
||||
Memory::Write_U16(0x0000, 0x000030e6); // Console type
|
||||
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
||||
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
|
||||
Memory::Write_U32(0x00000000, 0x000030dc); // Time
|
||||
Memory::Write_U32(0x00000000, 0x000030d8); // Time
|
||||
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
|
||||
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
|
||||
Memory::Write_U32(0x01800000, 0x00003100); // BAT
|
||||
Memory::Write_U32(0x01800000, 0x00003104); // BAT
|
||||
Memory::Write_U32(0x00000000, 0x0000310c); // Init
|
||||
Memory::Write_U32(0x8179d500, 0x00003110); // Init
|
||||
Memory::Write_U32(0x04000000, 0x00003118); // Unknown
|
||||
Memory::Write_U32(0x04000000, 0x0000311c); // BAT
|
||||
Memory::Write_U32(0x93400000, 0x00003120); // BAT
|
||||
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
|
||||
Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high
|
||||
Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low
|
||||
Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high
|
||||
Memory::Write_U32(0x00000012, 0x00003138); // Console type
|
||||
// 40 is copied from 88 after running apploader
|
||||
Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
|
||||
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)
|
||||
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
|
||||
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(0x00090204, 0x00003188); // Expected IOS revision
|
||||
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
|
||||
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
|
||||
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
|
||||
Memory::Write_U32(0x00000000, 0x00000030); // Init
|
||||
Memory::Write_U32(0x817FEC60, 0x00000034); // Init
|
||||
// 38, 3C should get start, size of FST through apploader
|
||||
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
|
||||
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
|
||||
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
|
||||
Memory::Write_U32(0x8179b500, 0x000000f4); // __start
|
||||
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
|
||||
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
|
||||
Memory::Write_U16(0x0000, 0x000030e6); // Console type
|
||||
Memory::Write_U32(0x00000000, 0x000030c0); // EXI
|
||||
Memory::Write_U32(0x00000000, 0x000030c4); // EXI
|
||||
Memory::Write_U32(0x00000000, 0x000030dc); // Time
|
||||
Memory::Write_U32(0x00000000, 0x000030d8); // Time
|
||||
Memory::Write_U16(0x8201, 0x000030e6); // Dev console / debug capable
|
||||
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
|
||||
Memory::Write_U32(0x01800000, 0x00003100); // BAT
|
||||
Memory::Write_U32(0x01800000, 0x00003104); // BAT
|
||||
Memory::Write_U32(0x00000000, 0x0000310c); // Init
|
||||
Memory::Write_U32(0x8179d500, 0x00003110); // Init
|
||||
Memory::Write_U32(0x04000000, 0x00003118); // Unknown
|
||||
Memory::Write_U32(0x04000000, 0x0000311c); // BAT
|
||||
Memory::Write_U32(0x93400000, 0x00003120); // BAT
|
||||
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
|
||||
Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high
|
||||
Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low
|
||||
Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high
|
||||
Memory::Write_U32(0x00000012, 0x00003138); // Console type
|
||||
// 40 is copied from 88 after running apploader
|
||||
Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
|
||||
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)
|
||||
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
|
||||
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(0x00090204, 0x00003188); // Expected IOS revision
|
||||
|
||||
Memory::Write_U8(0x80, 0x0000315c); // OSInit
|
||||
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
|
||||
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
|
||||
Memory::Write_U8(0x80, 0x0000315c); // OSInit
|
||||
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
|
||||
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
|
||||
|
||||
// Fake the VI Init of the IPL
|
||||
Memory::Write_U32(SConfig::GetInstance().bNTSC ? 0 : 1, 0x000000CC);
|
||||
// Fake the VI Init of the IPL
|
||||
Memory::Write_U32(SConfig::GetInstance().bNTSC ? 0 : 1, 0x000000CC);
|
||||
|
||||
// Clear exception handler. Why? Don't we begin with only zeros?
|
||||
for (int i = 0x3000; i <= 0x3038; i += 4)
|
||||
{
|
||||
Memory::Write_U32(0x00000000, i);
|
||||
}
|
||||
return true;
|
||||
// Clear exception handler. Why? Don't we begin with only zeros?
|
||||
for (int i = 0x3000; i <= 0x3038; i += 4)
|
||||
{
|
||||
Memory::Write_U32(0x00000000, i);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
|
@ -319,129 +330,131 @@ bool CBoot::SetupWiiMemory(DiscIO::IVolume::ECountry country)
|
|||
// execute the apploader
|
||||
bool CBoot::EmulatedBS2_Wii()
|
||||
{
|
||||
INFO_LOG(BOOT, "Faking Wii BS2...");
|
||||
INFO_LOG(BOOT, "Faking Wii BS2...");
|
||||
|
||||
// Setup Wii memory
|
||||
DiscIO::IVolume::ECountry country_code = DiscIO::IVolume::COUNTRY_UNKNOWN;
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
country_code = DVDInterface::GetVolume().GetCountry();
|
||||
if (SetupWiiMemory(country_code) == false)
|
||||
return false;
|
||||
// Setup Wii memory
|
||||
DiscIO::IVolume::ECountry country_code = DiscIO::IVolume::COUNTRY_UNKNOWN;
|
||||
if (DVDInterface::VolumeIsValid())
|
||||
country_code = DVDInterface::GetVolume().GetCountry();
|
||||
if (SetupWiiMemory(country_code) == false)
|
||||
return false;
|
||||
|
||||
// Execute the apploader
|
||||
bool apploaderRan = false;
|
||||
if (DVDInterface::VolumeIsValid() && DVDInterface::GetVolume().GetVolumeType() == DiscIO::IVolume::WII_DISC)
|
||||
{
|
||||
// This is some kind of consistency check that is compared to the 0x00
|
||||
// values as the game boots. This location keeps the 4 byte ID for as long
|
||||
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
||||
// after this check during booting.
|
||||
DVDRead(0, 0x3180, 4, true);
|
||||
// Execute the apploader
|
||||
bool apploaderRan = false;
|
||||
if (DVDInterface::VolumeIsValid() &&
|
||||
DVDInterface::GetVolume().GetVolumeType() == DiscIO::IVolume::WII_DISC)
|
||||
{
|
||||
// This is some kind of consistency check that is compared to the 0x00
|
||||
// values as the game boots. This location keeps the 4 byte ID for as long
|
||||
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
||||
// after this check during booting.
|
||||
DVDRead(0, 0x3180, 4, true);
|
||||
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
|
||||
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000300); // Write default DSI Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000800); // Write default FPU Handler: rfi
|
||||
Memory::Write_U32(0x4c000064, 0x00000C00); // Write default Syscall Handler: rfi
|
||||
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
|
||||
|
||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||
|
||||
const u32 apploader_offset = 0x2440; // 0x1c40;
|
||||
const u32 apploader_offset = 0x2440; // 0x1c40;
|
||||
|
||||
// Load Apploader to Memory
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
u32 apploader_entry, apploader_size;
|
||||
if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) ||
|
||||
apploader_entry == (u32)-1 || apploader_size == (u32)-1)
|
||||
{
|
||||
ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
|
||||
return false;
|
||||
}
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true);
|
||||
// Load Apploader to Memory
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
u32 apploader_entry, apploader_size;
|
||||
if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) ||
|
||||
apploader_entry == (u32)-1 || apploader_size == (u32)-1)
|
||||
{
|
||||
ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
|
||||
return false;
|
||||
}
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true);
|
||||
|
||||
//call iAppLoaderEntry
|
||||
DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
|
||||
// call iAppLoaderEntry
|
||||
DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
|
||||
|
||||
u32 iAppLoaderFuncAddr = 0x80004000;
|
||||
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
|
||||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(apploader_entry);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
u32 iAppLoaderFuncAddr = 0x80004000;
|
||||
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
|
||||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(apploader_entry);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderInit");
|
||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||
RunFunction(iAppLoaderInit);
|
||||
// iAppLoaderInit
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderInit");
|
||||
PowerPC::ppcState.gpr[3] = 0x81300000;
|
||||
RunFunction(iAppLoaderInit);
|
||||
|
||||
// Let the apploader load the exe to memory. At this point I get an unknown IPC command
|
||||
// (command zero) when I load Wii Sports or other games a second time. I don't notice
|
||||
// any side effects however. It's a little disconcerting however that Start after Stop
|
||||
// behaves differently than the first Start after starting Dolphin. It means something
|
||||
// was not reset correctly.
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderMain");
|
||||
do
|
||||
{
|
||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||
PowerPC::ppcState.gpr[4] = 0x81300008;
|
||||
PowerPC::ppcState.gpr[5] = 0x8130000c;
|
||||
// Let the apploader load the exe to memory. At this point I get an unknown IPC command
|
||||
// (command zero) when I load Wii Sports or other games a second time. I don't notice
|
||||
// any side effects however. It's a little disconcerting however that Start after Stop
|
||||
// behaves differently than the first Start after starting Dolphin. It means something
|
||||
// was not reset correctly.
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderMain");
|
||||
do
|
||||
{
|
||||
PowerPC::ppcState.gpr[3] = 0x81300004;
|
||||
PowerPC::ppcState.gpr[4] = 0x81300008;
|
||||
PowerPC::ppcState.gpr[5] = 0x8130000c;
|
||||
|
||||
RunFunction(iAppLoaderMain);
|
||||
RunFunction(iAppLoaderMain);
|
||||
|
||||
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
|
||||
u32 iRamAddress = PowerPC::Read_U32(0x81300004);
|
||||
u32 iLength = PowerPC::Read_U32(0x81300008);
|
||||
u32 iDVDOffset = PowerPC::Read_U32(0x8130000c) << 2;
|
||||
|
||||
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
|
||||
DVDRead(iDVDOffset, iRamAddress, iLength, true);
|
||||
} while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset,
|
||||
iRamAddress, iLength);
|
||||
DVDRead(iDVDOffset, iRamAddress, iLength, true);
|
||||
} while (PowerPC::ppcState.gpr[3] != 0x00);
|
||||
|
||||
// iAppLoaderClose
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderClose");
|
||||
RunFunction(iAppLoaderClose);
|
||||
// iAppLoaderClose
|
||||
DEBUG_LOG(BOOT, "Run iAppLoaderClose");
|
||||
RunFunction(iAppLoaderClose);
|
||||
|
||||
apploaderRan = true;
|
||||
apploaderRan = true;
|
||||
|
||||
// Pass the "#002 check"
|
||||
// Apploader writes the IOS version and revision here, we copy it
|
||||
// Fake IOSv9 r2.4 if no version is found (elf loading)
|
||||
u32 firmwareVer = PowerPC::Read_U32(0x80003188);
|
||||
PowerPC::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x80003140);
|
||||
// Pass the "#002 check"
|
||||
// Apploader writes the IOS version and revision here, we copy it
|
||||
// Fake IOSv9 r2.4 if no version is found (elf loading)
|
||||
u32 firmwareVer = PowerPC::Read_U32(0x80003188);
|
||||
PowerPC::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x80003140);
|
||||
|
||||
// Load patches and run startup patches
|
||||
PatchEngine::LoadPatches();
|
||||
// Load patches and run startup patches
|
||||
PatchEngine::LoadPatches();
|
||||
|
||||
// return
|
||||
PC = PowerPC::ppcState.gpr[3];
|
||||
}
|
||||
// return
|
||||
PC = PowerPC::ppcState.gpr[3];
|
||||
}
|
||||
|
||||
return apploaderRan;
|
||||
return apploaderRan;
|
||||
}
|
||||
|
||||
// Returns true if apploader has run successfully
|
||||
bool CBoot::EmulatedBS2(bool _bIsWii)
|
||||
{
|
||||
return _bIsWii ? EmulatedBS2_Wii() : EmulatedBS2_GC();
|
||||
return _bIsWii ? EmulatedBS2_Wii() : EmulatedBS2_GC();
|
||||
}
|
||||
|
|
|
@ -14,20 +14,20 @@
|
|||
|
||||
CDolLoader::CDolLoader(const std::vector<u8>& buffer)
|
||||
{
|
||||
m_is_valid = Initialize(buffer);
|
||||
m_is_valid = Initialize(buffer);
|
||||
}
|
||||
|
||||
CDolLoader::CDolLoader(const std::string& filename)
|
||||
{
|
||||
const u64 size = File::GetSize(filename);
|
||||
std::vector<u8> temp_buffer(size);
|
||||
const u64 size = File::GetSize(filename);
|
||||
std::vector<u8> temp_buffer(size);
|
||||
|
||||
{
|
||||
File::IOFile pStream(filename, "rb");
|
||||
pStream.ReadBytes(temp_buffer.data(), temp_buffer.size());
|
||||
}
|
||||
{
|
||||
File::IOFile pStream(filename, "rb");
|
||||
pStream.ReadBytes(temp_buffer.data(), temp_buffer.size());
|
||||
}
|
||||
|
||||
m_is_valid = Initialize(temp_buffer);
|
||||
m_is_valid = Initialize(temp_buffer);
|
||||
}
|
||||
|
||||
CDolLoader::~CDolLoader()
|
||||
|
@ -36,76 +36,78 @@ CDolLoader::~CDolLoader()
|
|||
|
||||
bool CDolLoader::Initialize(const std::vector<u8>& buffer)
|
||||
{
|
||||
if (buffer.size() < sizeof(SDolHeader))
|
||||
return false;
|
||||
if (buffer.size() < sizeof(SDolHeader))
|
||||
return false;
|
||||
|
||||
memcpy(&m_dolheader, buffer.data(), sizeof(SDolHeader));
|
||||
memcpy(&m_dolheader, buffer.data(), sizeof(SDolHeader));
|
||||
|
||||
// swap memory
|
||||
u32* p = (u32*)&m_dolheader;
|
||||
for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++)
|
||||
p[i] = Common::swap32(p[i]);
|
||||
// swap memory
|
||||
u32* p = (u32*)&m_dolheader;
|
||||
for (size_t i = 0; i < (sizeof(SDolHeader) / sizeof(u32)); i++)
|
||||
p[i] = Common::swap32(p[i]);
|
||||
|
||||
const u32 HID4_pattern = Common::swap32(0x7c13fba6);
|
||||
const u32 HID4_mask = Common::swap32(0xfc1fffff);
|
||||
const u32 HID4_pattern = Common::swap32(0x7c13fba6);
|
||||
const u32 HID4_mask = Common::swap32(0xfc1fffff);
|
||||
|
||||
m_is_wii = false;
|
||||
m_is_wii = false;
|
||||
|
||||
m_text_sections.reserve(DOL_NUM_TEXT);
|
||||
for (int i = 0; i < DOL_NUM_TEXT; ++i)
|
||||
{
|
||||
if (m_dolheader.textSize[i] != 0)
|
||||
{
|
||||
if (buffer.size() < m_dolheader.textOffset[i] + m_dolheader.textSize[i])
|
||||
return false;
|
||||
m_text_sections.reserve(DOL_NUM_TEXT);
|
||||
for (int i = 0; i < DOL_NUM_TEXT; ++i)
|
||||
{
|
||||
if (m_dolheader.textSize[i] != 0)
|
||||
{
|
||||
if (buffer.size() < m_dolheader.textOffset[i] + m_dolheader.textSize[i])
|
||||
return false;
|
||||
|
||||
const u8* text_start = &buffer[m_dolheader.textOffset[i]];
|
||||
m_text_sections.emplace_back(text_start, &text_start[m_dolheader.textSize[i]]);
|
||||
const u8* text_start = &buffer[m_dolheader.textOffset[i]];
|
||||
m_text_sections.emplace_back(text_start, &text_start[m_dolheader.textSize[i]]);
|
||||
|
||||
for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j)
|
||||
{
|
||||
u32 word = ((u32*)text_start)[j];
|
||||
if ((word & HID4_mask) == HID4_pattern)
|
||||
m_is_wii = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure that m_text_sections indexes match header indexes
|
||||
m_text_sections.emplace_back();
|
||||
}
|
||||
}
|
||||
for (unsigned int j = 0; !m_is_wii && j < (m_dolheader.textSize[i] / sizeof(u32)); ++j)
|
||||
{
|
||||
u32 word = ((u32*)text_start)[j];
|
||||
if ((word & HID4_mask) == HID4_pattern)
|
||||
m_is_wii = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure that m_text_sections indexes match header indexes
|
||||
m_text_sections.emplace_back();
|
||||
}
|
||||
}
|
||||
|
||||
m_data_sections.reserve(DOL_NUM_DATA);
|
||||
for (int i = 0; i < DOL_NUM_DATA; ++i)
|
||||
{
|
||||
if (m_dolheader.dataSize[i] != 0)
|
||||
{
|
||||
if (buffer.size() < m_dolheader.dataOffset[i] + m_dolheader.dataSize[i])
|
||||
return false;
|
||||
m_data_sections.reserve(DOL_NUM_DATA);
|
||||
for (int i = 0; i < DOL_NUM_DATA; ++i)
|
||||
{
|
||||
if (m_dolheader.dataSize[i] != 0)
|
||||
{
|
||||
if (buffer.size() < m_dolheader.dataOffset[i] + m_dolheader.dataSize[i])
|
||||
return false;
|
||||
|
||||
const u8* data_start = &buffer[m_dolheader.dataOffset[i]];
|
||||
m_data_sections.emplace_back(data_start, &data_start[m_dolheader.dataSize[i]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure that m_data_sections indexes match header indexes
|
||||
m_data_sections.emplace_back();
|
||||
}
|
||||
}
|
||||
const u8* data_start = &buffer[m_dolheader.dataOffset[i]];
|
||||
m_data_sections.emplace_back(data_start, &data_start[m_dolheader.dataSize[i]]);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Make sure that m_data_sections indexes match header indexes
|
||||
m_data_sections.emplace_back();
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDolLoader::Load() const
|
||||
{
|
||||
// load all text (code) sections
|
||||
for (size_t i = 0; i < m_text_sections.size(); ++i)
|
||||
if (!m_text_sections[i].empty())
|
||||
Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(), m_text_sections[i].size());
|
||||
// load all text (code) sections
|
||||
for (size_t i = 0; i < m_text_sections.size(); ++i)
|
||||
if (!m_text_sections[i].empty())
|
||||
Memory::CopyToEmu(m_dolheader.textAddress[i], m_text_sections[i].data(),
|
||||
m_text_sections[i].size());
|
||||
|
||||
// load all data sections
|
||||
for (size_t i = 0; i < m_data_sections.size(); ++i)
|
||||
if (!m_data_sections[i].empty())
|
||||
Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(), m_data_sections[i].size());
|
||||
// load all data sections
|
||||
for (size_t i = 0; i < m_data_sections.size(); ++i)
|
||||
if (!m_data_sections[i].empty())
|
||||
Memory::CopyToEmu(m_dolheader.dataAddress[i], m_data_sections[i].data(),
|
||||
m_data_sections[i].size());
|
||||
}
|
||||
|
|
|
@ -12,47 +12,46 @@
|
|||
class CDolLoader
|
||||
{
|
||||
public:
|
||||
CDolLoader(const std::string& filename);
|
||||
CDolLoader(const std::vector<u8>& buffer);
|
||||
~CDolLoader();
|
||||
CDolLoader(const std::string& filename);
|
||||
CDolLoader(const std::vector<u8>& buffer);
|
||||
~CDolLoader();
|
||||
|
||||
bool IsValid() const { return m_is_valid; }
|
||||
bool IsWii() const { return m_is_wii; }
|
||||
u32 GetEntryPoint() const { return m_dolheader.entryPoint; }
|
||||
|
||||
// Load into emulated memory
|
||||
void Load() const;
|
||||
bool IsValid() const { return m_is_valid; }
|
||||
bool IsWii() const { return m_is_wii; }
|
||||
u32 GetEntryPoint() const { return m_dolheader.entryPoint; }
|
||||
// Load into emulated memory
|
||||
void Load() const;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
DOL_NUM_TEXT = 7,
|
||||
DOL_NUM_DATA = 11
|
||||
};
|
||||
enum
|
||||
{
|
||||
DOL_NUM_TEXT = 7,
|
||||
DOL_NUM_DATA = 11
|
||||
};
|
||||
|
||||
struct SDolHeader
|
||||
{
|
||||
u32 textOffset[DOL_NUM_TEXT];
|
||||
u32 dataOffset[DOL_NUM_DATA];
|
||||
struct SDolHeader
|
||||
{
|
||||
u32 textOffset[DOL_NUM_TEXT];
|
||||
u32 dataOffset[DOL_NUM_DATA];
|
||||
|
||||
u32 textAddress[DOL_NUM_TEXT];
|
||||
u32 dataAddress[DOL_NUM_DATA];
|
||||
u32 textAddress[DOL_NUM_TEXT];
|
||||
u32 dataAddress[DOL_NUM_DATA];
|
||||
|
||||
u32 textSize[DOL_NUM_TEXT];
|
||||
u32 dataSize[DOL_NUM_DATA];
|
||||
u32 textSize[DOL_NUM_TEXT];
|
||||
u32 dataSize[DOL_NUM_DATA];
|
||||
|
||||
u32 bssAddress;
|
||||
u32 bssSize;
|
||||
u32 entryPoint;
|
||||
};
|
||||
SDolHeader m_dolheader;
|
||||
u32 bssAddress;
|
||||
u32 bssSize;
|
||||
u32 entryPoint;
|
||||
};
|
||||
SDolHeader m_dolheader;
|
||||
|
||||
std::vector<std::vector<u8>> m_data_sections;
|
||||
std::vector<std::vector<u8>> m_text_sections;
|
||||
std::vector<std::vector<u8>> m_data_sections;
|
||||
std::vector<std::vector<u8>> m_text_sections;
|
||||
|
||||
bool m_is_valid;
|
||||
bool m_is_wii;
|
||||
bool m_is_valid;
|
||||
bool m_is_wii;
|
||||
|
||||
// Copy sections to internal buffers
|
||||
bool Initialize(const std::vector<u8>& buffer);
|
||||
// Copy sections to internal buffers
|
||||
bool Initialize(const std::vector<u8>& buffer);
|
||||
};
|
||||
|
|
|
@ -12,91 +12,90 @@
|
|||
|
||||
bool CBoot::IsElfWii(const std::string& filename)
|
||||
{
|
||||
/* We already check if filename existed before we called this function, so
|
||||
there is no need for another check, just read the file right away */
|
||||
/* We already check if filename existed before we called this function, so
|
||||
there is no need for another check, just read the file right away */
|
||||
|
||||
size_t filesize = File::GetSize(filename);
|
||||
auto elf = std::make_unique<u8 []>(filesize);
|
||||
size_t filesize = File::GetSize(filename);
|
||||
auto elf = std::make_unique<u8[]>(filesize);
|
||||
|
||||
{
|
||||
File::IOFile f(filename, "rb");
|
||||
f.ReadBytes(elf.get(), filesize);
|
||||
}
|
||||
{
|
||||
File::IOFile f(filename, "rb");
|
||||
f.ReadBytes(elf.get(), filesize);
|
||||
}
|
||||
|
||||
// Use the same method as the DOL loader uses: search for mfspr from HID4,
|
||||
// which should only be used in Wii ELFs.
|
||||
//
|
||||
// Likely to have some false positives/negatives, patches implementing a
|
||||
// better heuristic are welcome.
|
||||
// Use the same method as the DOL loader uses: search for mfspr from HID4,
|
||||
// which should only be used in Wii ELFs.
|
||||
//
|
||||
// Likely to have some false positives/negatives, patches implementing a
|
||||
// better heuristic are welcome.
|
||||
|
||||
// Swap these once, instead of swapping every word in the file.
|
||||
u32 HID4_pattern = Common::swap32(0x7c13fba6);
|
||||
u32 HID4_mask = Common::swap32(0xfc1fffff);
|
||||
ElfReader reader(elf.get());
|
||||
// Swap these once, instead of swapping every word in the file.
|
||||
u32 HID4_pattern = Common::swap32(0x7c13fba6);
|
||||
u32 HID4_mask = Common::swap32(0xfc1fffff);
|
||||
ElfReader reader(elf.get());
|
||||
|
||||
for (int i = 0; i < reader.GetNumSections(); ++i)
|
||||
{
|
||||
if (reader.IsCodeSection(i))
|
||||
{
|
||||
u32* code = (u32*)reader.GetSectionDataPtr(i);
|
||||
for (u32 j = 0; j < reader.GetSectionSize(i) / sizeof(u32); ++j)
|
||||
{
|
||||
if ((code[j] & HID4_mask) == HID4_pattern)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < reader.GetNumSections(); ++i)
|
||||
{
|
||||
if (reader.IsCodeSection(i))
|
||||
{
|
||||
u32* code = (u32*)reader.GetSectionDataPtr(i);
|
||||
for (u32 j = 0; j < reader.GetSectionSize(i) / sizeof(u32); ++j)
|
||||
{
|
||||
if ((code[j] & HID4_mask) == HID4_pattern)
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool CBoot::Boot_ELF(const std::string& filename)
|
||||
{
|
||||
// Read ELF from file
|
||||
size_t filesize = File::GetSize(filename);
|
||||
auto elf = std::make_unique<u8 []>(filesize);
|
||||
// Read ELF from file
|
||||
size_t filesize = File::GetSize(filename);
|
||||
auto elf = std::make_unique<u8[]>(filesize);
|
||||
|
||||
{
|
||||
File::IOFile f(filename, "rb");
|
||||
f.ReadBytes(elf.get(), filesize);
|
||||
}
|
||||
{
|
||||
File::IOFile f(filename, "rb");
|
||||
f.ReadBytes(elf.get(), filesize);
|
||||
}
|
||||
|
||||
// Load ELF into GameCube Memory
|
||||
ElfReader reader(elf.get());
|
||||
if (!reader.LoadIntoMemory())
|
||||
return false;
|
||||
// Load ELF into GameCube Memory
|
||||
ElfReader reader(elf.get());
|
||||
if (!reader.LoadIntoMemory())
|
||||
return false;
|
||||
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
// Set up MSR and the BAT SPR registers.
|
||||
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
|
||||
m_MSR.FP = 1;
|
||||
m_MSR.DR = 1;
|
||||
m_MSR.IR = 1;
|
||||
m_MSR.EE = 1;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_IBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0U] = 0x80001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT0L] = 0x00000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1U] = 0xc0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT1L] = 0x0000002a;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4U] = 0x90001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT4L] = 0x10000002;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5U] = 0xd0001fff;
|
||||
PowerPC::ppcState.spr[SPR_DBAT5L] = 0x1000002a;
|
||||
|
||||
if (!reader.LoadSymbols())
|
||||
{
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
}
|
||||
else
|
||||
{
|
||||
HLE::PatchFunctions();
|
||||
}
|
||||
if (!reader.LoadSymbols())
|
||||
{
|
||||
if (LoadMapFromFilename())
|
||||
HLE::PatchFunctions();
|
||||
}
|
||||
else
|
||||
{
|
||||
HLE::PatchFunctions();
|
||||
}
|
||||
|
||||
PC = reader.GetEntryPoint();
|
||||
PC = reader.GetEntryPoint();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -9,15 +9,15 @@
|
|||
#include "Common/FileUtil.h"
|
||||
#include "Common/NandPaths.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/Boot/Boot.h"
|
||||
#include "Core/Boot/Boot_DOL.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HLE/HLE.h"
|
||||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/HW/VideoInterface.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE.h"
|
||||
#include "Core/IPC_HLE/WII_IPC_HLE_Device_FileIO.h"
|
||||
#include "Core/PatchEngine.h"
|
||||
#include "Core/PowerPC/PowerPC.h"
|
||||
|
||||
#include "DiscIO/NANDContentLoader.h"
|
||||
|
@ -25,104 +25,106 @@
|
|||
#include "DiscIO/VolumeCreator.h"
|
||||
#include "DiscIO/WiiWad.h"
|
||||
|
||||
static u32 state_checksum(u32 *buf, int len)
|
||||
static u32 state_checksum(u32* buf, int len)
|
||||
{
|
||||
u32 checksum = 0;
|
||||
len = len >> 2;
|
||||
u32 checksum = 0;
|
||||
len = len >> 2;
|
||||
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
checksum += buf[i];
|
||||
}
|
||||
for (int i = 0; i < len; i++)
|
||||
{
|
||||
checksum += buf[i];
|
||||
}
|
||||
|
||||
return checksum;
|
||||
return checksum;
|
||||
}
|
||||
|
||||
struct StateFlags
|
||||
{
|
||||
u32 checksum;
|
||||
u8 flags;
|
||||
u8 type;
|
||||
u8 discstate;
|
||||
u8 returnto;
|
||||
u32 unknown[6];
|
||||
u32 checksum;
|
||||
u8 flags;
|
||||
u8 type;
|
||||
u8 discstate;
|
||||
u8 returnto;
|
||||
u32 unknown[6];
|
||||
};
|
||||
|
||||
bool CBoot::Boot_WiiWAD(const std::string& _pFilename)
|
||||
{
|
||||
std::string state_filename(Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) + WII_STATE);
|
||||
std::string state_filename(Common::GetTitleDataPath(TITLEID_SYSMENU, Common::FROM_SESSION_ROOT) +
|
||||
WII_STATE);
|
||||
|
||||
if (File::Exists(state_filename))
|
||||
{
|
||||
File::IOFile state_file(state_filename, "r+b");
|
||||
StateFlags state;
|
||||
state_file.ReadBytes(&state, sizeof(StateFlags));
|
||||
if (File::Exists(state_filename))
|
||||
{
|
||||
File::IOFile state_file(state_filename, "r+b");
|
||||
StateFlags state;
|
||||
state_file.ReadBytes(&state, sizeof(StateFlags));
|
||||
|
||||
state.type = 0x03; // TYPE_RETURN
|
||||
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags) - 4);
|
||||
state.type = 0x03; // TYPE_RETURN
|
||||
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags) - 4);
|
||||
|
||||
state_file.Seek(0, SEEK_SET);
|
||||
state_file.WriteBytes(&state, sizeof(StateFlags));
|
||||
}
|
||||
else
|
||||
{
|
||||
File::CreateFullPath(state_filename);
|
||||
File::IOFile state_file(state_filename, "a+b");
|
||||
StateFlags state;
|
||||
memset(&state, 0, sizeof(StateFlags));
|
||||
state.type = 0x03; // TYPE_RETURN
|
||||
state.discstate = 0x01; // DISCSTATE_WII
|
||||
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags) - 4);
|
||||
state_file.WriteBytes(&state, sizeof(StateFlags));
|
||||
}
|
||||
state_file.Seek(0, SEEK_SET);
|
||||
state_file.WriteBytes(&state, sizeof(StateFlags));
|
||||
}
|
||||
else
|
||||
{
|
||||
File::CreateFullPath(state_filename);
|
||||
File::IOFile state_file(state_filename, "a+b");
|
||||
StateFlags state;
|
||||
memset(&state, 0, sizeof(StateFlags));
|
||||
state.type = 0x03; // TYPE_RETURN
|
||||
state.discstate = 0x01; // DISCSTATE_WII
|
||||
state.checksum = state_checksum((u32*)&state.flags, sizeof(StateFlags) - 4);
|
||||
state_file.WriteBytes(&state, sizeof(StateFlags));
|
||||
}
|
||||
|
||||
const DiscIO::CNANDContentLoader& ContentLoader = DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename);
|
||||
if (!ContentLoader.IsValid())
|
||||
return false;
|
||||
const DiscIO::CNANDContentLoader& ContentLoader =
|
||||
DiscIO::CNANDContentManager::Access().GetNANDLoader(_pFilename);
|
||||
if (!ContentLoader.IsValid())
|
||||
return false;
|
||||
|
||||
u64 titleID = ContentLoader.GetTitleID();
|
||||
// create data directory
|
||||
File::CreateFullPath(Common::GetTitleDataPath(titleID, Common::FROM_SESSION_ROOT));
|
||||
u64 titleID = ContentLoader.GetTitleID();
|
||||
// create data directory
|
||||
File::CreateFullPath(Common::GetTitleDataPath(titleID, Common::FROM_SESSION_ROOT));
|
||||
|
||||
if (titleID == TITLEID_SYSMENU)
|
||||
HLE_IPC_CreateVirtualFATFilesystem();
|
||||
// setup Wii memory
|
||||
if (!SetupWiiMemory(ContentLoader.GetCountry()))
|
||||
return false;
|
||||
// this sets a bit that is used to detect NTSC-J
|
||||
if (ContentLoader.GetCountry() == DiscIO::IVolume::COUNTRY_JAPAN)
|
||||
{
|
||||
VideoInterface::SetRegionReg('J');
|
||||
}
|
||||
// DOL
|
||||
const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());
|
||||
if (pContent == nullptr)
|
||||
return false;
|
||||
if (titleID == TITLEID_SYSMENU)
|
||||
HLE_IPC_CreateVirtualFATFilesystem();
|
||||
// setup Wii memory
|
||||
if (!SetupWiiMemory(ContentLoader.GetCountry()))
|
||||
return false;
|
||||
// this sets a bit that is used to detect NTSC-J
|
||||
if (ContentLoader.GetCountry() == DiscIO::IVolume::COUNTRY_JAPAN)
|
||||
{
|
||||
VideoInterface::SetRegionReg('J');
|
||||
}
|
||||
// DOL
|
||||
const DiscIO::SNANDContent* pContent =
|
||||
ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());
|
||||
if (pContent == nullptr)
|
||||
return false;
|
||||
|
||||
WII_IPC_HLE_Interface::SetDefaultContentFile(_pFilename);
|
||||
WII_IPC_HLE_Interface::SetDefaultContentFile(_pFilename);
|
||||
|
||||
std::unique_ptr<CDolLoader> pDolLoader = std::make_unique<CDolLoader>(pContent->m_Data->Get());
|
||||
if (!pDolLoader->IsValid())
|
||||
return false;
|
||||
std::unique_ptr<CDolLoader> pDolLoader = std::make_unique<CDolLoader>(pContent->m_Data->Get());
|
||||
if (!pDolLoader->IsValid())
|
||||
return false;
|
||||
|
||||
pDolLoader->Load();
|
||||
PC = pDolLoader->GetEntryPoint();
|
||||
pDolLoader->Load();
|
||||
PC = pDolLoader->GetEntryPoint();
|
||||
|
||||
// Pass the "#002 check"
|
||||
// Apploader should write the IOS version and revision to 0x3140, and compare it
|
||||
// to 0x3188 to pass the check, but we don't do it, and i don't know where to read the IOS rev...
|
||||
// Currently we just write 0xFFFF for the revision, copy manually and it works fine :p
|
||||
// Pass the "#002 check"
|
||||
// Apploader should write the IOS version and revision to 0x3140, and compare it
|
||||
// to 0x3188 to pass the check, but we don't do it, and i don't know where to read the IOS rev...
|
||||
// Currently we just write 0xFFFF for the revision, copy manually and it works fine :p
|
||||
|
||||
// TODO : figure it correctly : where should we read the IOS rev that the wad "needs" ?
|
||||
Memory::Write_U16(ContentLoader.GetIosVersion(), 0x00003140);
|
||||
Memory::Write_U16(0xFFFF, 0x00003142);
|
||||
Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188);
|
||||
// TODO : figure it correctly : where should we read the IOS rev that the wad "needs" ?
|
||||
Memory::Write_U16(ContentLoader.GetIosVersion(), 0x00003140);
|
||||
Memory::Write_U16(0xFFFF, 0x00003142);
|
||||
Memory::Write_U32(Memory::Read_U32(0x00003140), 0x00003188);
|
||||
|
||||
// Load patches and run startup patches
|
||||
const std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(_pFilename));
|
||||
if (pVolume != nullptr)
|
||||
PatchEngine::LoadPatches();
|
||||
// Load patches and run startup patches
|
||||
const std::unique_ptr<DiscIO::IVolume> pVolume(DiscIO::CreateVolumeFromFilename(_pFilename));
|
||||
if (pVolume != nullptr)
|
||||
PatchEngine::LoadPatches();
|
||||
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -13,183 +13,191 @@
|
|||
#include "Core/HW/Memmap.h"
|
||||
#include "Core/PowerPC/PPCSymbolDB.h"
|
||||
|
||||
static void bswap(u32 &w) {w = Common::swap32(w);}
|
||||
static void bswap(u16 &w) {w = Common::swap16(w);}
|
||||
|
||||
static void byteswapHeader(Elf32_Ehdr &ELF_H)
|
||||
static void bswap(u32& w)
|
||||
{
|
||||
bswap(ELF_H.e_type);
|
||||
bswap(ELF_H.e_machine);
|
||||
bswap(ELF_H.e_ehsize);
|
||||
bswap(ELF_H.e_phentsize);
|
||||
bswap(ELF_H.e_phnum);
|
||||
bswap(ELF_H.e_shentsize);
|
||||
bswap(ELF_H.e_shnum);
|
||||
bswap(ELF_H.e_shstrndx);
|
||||
bswap(ELF_H.e_version);
|
||||
bswap(ELF_H.e_entry);
|
||||
bswap(ELF_H.e_phoff);
|
||||
bswap(ELF_H.e_shoff);
|
||||
bswap(ELF_H.e_flags);
|
||||
w = Common::swap32(w);
|
||||
}
|
||||
static void bswap(u16& w)
|
||||
{
|
||||
w = Common::swap16(w);
|
||||
}
|
||||
|
||||
static void byteswapSegment(Elf32_Phdr &sec)
|
||||
static void byteswapHeader(Elf32_Ehdr& ELF_H)
|
||||
{
|
||||
bswap(sec.p_align);
|
||||
bswap(sec.p_filesz);
|
||||
bswap(sec.p_flags);
|
||||
bswap(sec.p_memsz);
|
||||
bswap(sec.p_offset);
|
||||
bswap(sec.p_paddr);
|
||||
bswap(sec.p_vaddr);
|
||||
bswap(sec.p_type);
|
||||
bswap(ELF_H.e_type);
|
||||
bswap(ELF_H.e_machine);
|
||||
bswap(ELF_H.e_ehsize);
|
||||
bswap(ELF_H.e_phentsize);
|
||||
bswap(ELF_H.e_phnum);
|
||||
bswap(ELF_H.e_shentsize);
|
||||
bswap(ELF_H.e_shnum);
|
||||
bswap(ELF_H.e_shstrndx);
|
||||
bswap(ELF_H.e_version);
|
||||
bswap(ELF_H.e_entry);
|
||||
bswap(ELF_H.e_phoff);
|
||||
bswap(ELF_H.e_shoff);
|
||||
bswap(ELF_H.e_flags);
|
||||
}
|
||||
|
||||
static void byteswapSection(Elf32_Shdr &sec)
|
||||
static void byteswapSegment(Elf32_Phdr& sec)
|
||||
{
|
||||
bswap(sec.sh_addr);
|
||||
bswap(sec.sh_addralign);
|
||||
bswap(sec.sh_entsize);
|
||||
bswap(sec.sh_flags);
|
||||
bswap(sec.sh_info);
|
||||
bswap(sec.sh_link);
|
||||
bswap(sec.sh_name);
|
||||
bswap(sec.sh_offset);
|
||||
bswap(sec.sh_size);
|
||||
bswap(sec.sh_type);
|
||||
bswap(sec.p_align);
|
||||
bswap(sec.p_filesz);
|
||||
bswap(sec.p_flags);
|
||||
bswap(sec.p_memsz);
|
||||
bswap(sec.p_offset);
|
||||
bswap(sec.p_paddr);
|
||||
bswap(sec.p_vaddr);
|
||||
bswap(sec.p_type);
|
||||
}
|
||||
|
||||
ElfReader::ElfReader(void *ptr)
|
||||
static void byteswapSection(Elf32_Shdr& sec)
|
||||
{
|
||||
base = (char*)ptr;
|
||||
base32 = (u32*)ptr;
|
||||
header = (Elf32_Ehdr*)ptr;
|
||||
byteswapHeader(*header);
|
||||
bswap(sec.sh_addr);
|
||||
bswap(sec.sh_addralign);
|
||||
bswap(sec.sh_entsize);
|
||||
bswap(sec.sh_flags);
|
||||
bswap(sec.sh_info);
|
||||
bswap(sec.sh_link);
|
||||
bswap(sec.sh_name);
|
||||
bswap(sec.sh_offset);
|
||||
bswap(sec.sh_size);
|
||||
bswap(sec.sh_type);
|
||||
}
|
||||
|
||||
segments = (Elf32_Phdr *)(base + header->e_phoff);
|
||||
sections = (Elf32_Shdr *)(base + header->e_shoff);
|
||||
ElfReader::ElfReader(void* ptr)
|
||||
{
|
||||
base = (char*)ptr;
|
||||
base32 = (u32*)ptr;
|
||||
header = (Elf32_Ehdr*)ptr;
|
||||
byteswapHeader(*header);
|
||||
|
||||
for (int i = 0; i < GetNumSegments(); i++)
|
||||
{
|
||||
byteswapSegment(segments[i]);
|
||||
}
|
||||
segments = (Elf32_Phdr*)(base + header->e_phoff);
|
||||
sections = (Elf32_Shdr*)(base + header->e_shoff);
|
||||
|
||||
for (int i = 0; i < GetNumSections(); i++)
|
||||
{
|
||||
byteswapSection(sections[i]);
|
||||
}
|
||||
entryPoint = header->e_entry;
|
||||
for (int i = 0; i < GetNumSegments(); i++)
|
||||
{
|
||||
byteswapSegment(segments[i]);
|
||||
}
|
||||
|
||||
for (int i = 0; i < GetNumSections(); i++)
|
||||
{
|
||||
byteswapSection(sections[i]);
|
||||
}
|
||||
entryPoint = header->e_entry;
|
||||
}
|
||||
|
||||
const char* ElfReader::GetSectionName(int section) const
|
||||
{
|
||||
if (sections[section].sh_type == SHT_NULL)
|
||||
return nullptr;
|
||||
if (sections[section].sh_type == SHT_NULL)
|
||||
return nullptr;
|
||||
|
||||
int nameOffset = sections[section].sh_name;
|
||||
char* ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
|
||||
int nameOffset = sections[section].sh_name;
|
||||
char* ptr = (char*)GetSectionDataPtr(header->e_shstrndx);
|
||||
|
||||
if (ptr)
|
||||
return ptr + nameOffset;
|
||||
else
|
||||
return nullptr;
|
||||
if (ptr)
|
||||
return ptr + nameOffset;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
// This is just a simple elf loader, good enough to load elfs generated by devkitPPC
|
||||
bool ElfReader::LoadIntoMemory()
|
||||
{
|
||||
DEBUG_LOG(MASTER_LOG, "String section: %i", header->e_shstrndx);
|
||||
DEBUG_LOG(MASTER_LOG, "String section: %i", header->e_shstrndx);
|
||||
|
||||
// Should we relocate?
|
||||
bRelocate = (header->e_type != ET_EXEC);
|
||||
// Should we relocate?
|
||||
bRelocate = (header->e_type != ET_EXEC);
|
||||
|
||||
if (bRelocate)
|
||||
{
|
||||
PanicAlert("Error: Dolphin doesn't know how to load a relocatable elf.");
|
||||
return false;
|
||||
}
|
||||
if (bRelocate)
|
||||
{
|
||||
PanicAlert("Error: Dolphin doesn't know how to load a relocatable elf.");
|
||||
return false;
|
||||
}
|
||||
|
||||
INFO_LOG(MASTER_LOG, "%i segments:", header->e_phnum);
|
||||
INFO_LOG(MASTER_LOG, "%i segments:", header->e_phnum);
|
||||
|
||||
// Copy segments into ram.
|
||||
for (int i = 0; i < header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr* p = segments + i;
|
||||
// Copy segments into ram.
|
||||
for (int i = 0; i < header->e_phnum; i++)
|
||||
{
|
||||
Elf32_Phdr* p = segments + i;
|
||||
|
||||
INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ",
|
||||
p->p_type, p->p_vaddr, p->p_filesz, p->p_memsz);
|
||||
INFO_LOG(MASTER_LOG, "Type: %i Vaddr: %08x Filesz: %i Memsz: %i ", p->p_type, p->p_vaddr,
|
||||
p->p_filesz, p->p_memsz);
|
||||
|
||||
if (p->p_type == PT_LOAD)
|
||||
{
|
||||
u32 writeAddr = p->p_vaddr;
|
||||
const u8* src = GetSegmentPtr(i);
|
||||
u32 srcSize = p->p_filesz;
|
||||
u32 dstSize = p->p_memsz;
|
||||
if (p->p_type == PT_LOAD)
|
||||
{
|
||||
u32 writeAddr = p->p_vaddr;
|
||||
const u8* src = GetSegmentPtr(i);
|
||||
u32 srcSize = p->p_filesz;
|
||||
u32 dstSize = p->p_memsz;
|
||||
|
||||
Memory::CopyToEmu(writeAddr, src, srcSize);
|
||||
if (srcSize < dstSize)
|
||||
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); //zero out bss
|
||||
Memory::CopyToEmu(writeAddr, src, srcSize);
|
||||
if (srcSize < dstSize)
|
||||
Memory::Memset(writeAddr + srcSize, 0, dstSize - srcSize); // zero out bss
|
||||
|
||||
INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", writeAddr, p->p_memsz);
|
||||
}
|
||||
}
|
||||
INFO_LOG(MASTER_LOG, "Loadable Segment Copied to %08x, size %08x", writeAddr, p->p_memsz);
|
||||
}
|
||||
}
|
||||
|
||||
INFO_LOG(MASTER_LOG, "Done loading.");
|
||||
return true;
|
||||
INFO_LOG(MASTER_LOG, "Done loading.");
|
||||
return true;
|
||||
}
|
||||
|
||||
SectionID ElfReader::GetSectionByName(const char *name, int firstSection) const
|
||||
SectionID ElfReader::GetSectionByName(const char* name, int firstSection) const
|
||||
{
|
||||
for (int i = firstSection; i < header->e_shnum; i++)
|
||||
{
|
||||
const char* secname = GetSectionName(i);
|
||||
for (int i = firstSection; i < header->e_shnum; i++)
|
||||
{
|
||||
const char* secname = GetSectionName(i);
|
||||
|
||||
if (secname != nullptr && strcmp(name, secname) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
if (secname != nullptr && strcmp(name, secname) == 0)
|
||||
return i;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
bool ElfReader::LoadSymbols()
|
||||
{
|
||||
bool hasSymbols = false;
|
||||
SectionID sec = GetSectionByName(".symtab");
|
||||
if (sec != -1)
|
||||
{
|
||||
int stringSection = sections[sec].sh_link;
|
||||
const char* stringBase = (const char *)GetSectionDataPtr(stringSection);
|
||||
bool hasSymbols = false;
|
||||
SectionID sec = GetSectionByName(".symtab");
|
||||
if (sec != -1)
|
||||
{
|
||||
int stringSection = sections[sec].sh_link;
|
||||
const char* stringBase = (const char*)GetSectionDataPtr(stringSection);
|
||||
|
||||
//We have a symbol table!
|
||||
Elf32_Sym* symtab = (Elf32_Sym *)(GetSectionDataPtr(sec));
|
||||
int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
|
||||
for (int sym = 0; sym < numSymbols; sym++)
|
||||
{
|
||||
int size = Common::swap32(symtab[sym].st_size);
|
||||
if (size == 0)
|
||||
continue;
|
||||
// We have a symbol table!
|
||||
Elf32_Sym* symtab = (Elf32_Sym*)(GetSectionDataPtr(sec));
|
||||
int numSymbols = sections[sec].sh_size / sizeof(Elf32_Sym);
|
||||
for (int sym = 0; sym < numSymbols; sym++)
|
||||
{
|
||||
int size = Common::swap32(symtab[sym].st_size);
|
||||
if (size == 0)
|
||||
continue;
|
||||
|
||||
// int bind = symtab[sym].st_info >> 4;
|
||||
int type = symtab[sym].st_info & 0xF;
|
||||
int sectionIndex = Common::swap16(symtab[sym].st_shndx);
|
||||
int value = Common::swap32(symtab[sym].st_value);
|
||||
const char* name = stringBase + Common::swap32(symtab[sym].st_name);
|
||||
if (bRelocate)
|
||||
value += sectionAddrs[sectionIndex];
|
||||
// int bind = symtab[sym].st_info >> 4;
|
||||
int type = symtab[sym].st_info & 0xF;
|
||||
int sectionIndex = Common::swap16(symtab[sym].st_shndx);
|
||||
int value = Common::swap32(symtab[sym].st_value);
|
||||
const char* name = stringBase + Common::swap32(symtab[sym].st_name);
|
||||
if (bRelocate)
|
||||
value += sectionAddrs[sectionIndex];
|
||||
|
||||
int symtype = Symbol::SYMBOL_DATA;
|
||||
switch (type)
|
||||
{
|
||||
case STT_OBJECT:
|
||||
symtype = Symbol::SYMBOL_DATA; break;
|
||||
case STT_FUNC:
|
||||
symtype = Symbol::SYMBOL_FUNCTION; break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
g_symbolDB.AddKnownSymbol(value, size, name, symtype);
|
||||
hasSymbols = true;
|
||||
}
|
||||
}
|
||||
g_symbolDB.Index();
|
||||
return hasSymbols;
|
||||
int symtype = Symbol::SYMBOL_DATA;
|
||||
switch (type)
|
||||
{
|
||||
case STT_OBJECT:
|
||||
symtype = Symbol::SYMBOL_DATA;
|
||||
break;
|
||||
case STT_FUNC:
|
||||
symtype = Symbol::SYMBOL_FUNCTION;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
g_symbolDB.AddKnownSymbol(value, size, name, symtype);
|
||||
hasSymbols = true;
|
||||
}
|
||||
}
|
||||
g_symbolDB.Index();
|
||||
return hasSymbols;
|
||||
}
|
||||
|
|
|
@ -8,10 +8,10 @@
|
|||
|
||||
enum KnownElfTypes
|
||||
{
|
||||
KNOWNELF_PSP = 0,
|
||||
KNOWNELF_DS = 1,
|
||||
KNOWNELF_GBA = 2,
|
||||
KNOWNELF_GC = 3,
|
||||
KNOWNELF_PSP = 0,
|
||||
KNOWNELF_DS = 1,
|
||||
KNOWNELF_GBA = 2,
|
||||
KNOWNELF_GC = 3,
|
||||
};
|
||||
|
||||
typedef int SectionID;
|
||||
|
@ -19,58 +19,47 @@ typedef int SectionID;
|
|||
class ElfReader
|
||||
{
|
||||
private:
|
||||
char* base;
|
||||
u32* base32;
|
||||
char* base;
|
||||
u32* base32;
|
||||
|
||||
Elf32_Ehdr* header;
|
||||
Elf32_Phdr* segments;
|
||||
Elf32_Shdr* sections;
|
||||
Elf32_Ehdr* header;
|
||||
Elf32_Phdr* segments;
|
||||
Elf32_Shdr* sections;
|
||||
|
||||
u32 *sectionAddrs;
|
||||
bool bRelocate;
|
||||
u32 entryPoint;
|
||||
u32* sectionAddrs;
|
||||
bool bRelocate;
|
||||
u32 entryPoint;
|
||||
|
||||
public:
|
||||
ElfReader(void* ptr);
|
||||
~ElfReader() { }
|
||||
ElfReader(void* ptr);
|
||||
~ElfReader() {}
|
||||
u32 Read32(int off) const { return base32[off >> 2]; }
|
||||
// Quick accessors
|
||||
ElfType GetType() const { return (ElfType)(header->e_type); }
|
||||
ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
|
||||
u32 GetEntryPoint() const { return entryPoint; }
|
||||
u32 GetFlags() const { return (u32)(header->e_flags); }
|
||||
bool LoadIntoMemory();
|
||||
bool LoadSymbols();
|
||||
|
||||
u32 Read32(int off) const { return base32[off>>2]; }
|
||||
int GetNumSegments() const { return (int)(header->e_phnum); }
|
||||
int GetNumSections() const { return (int)(header->e_shnum); }
|
||||
const u8* GetPtr(int offset) const { return (u8*)base + offset; }
|
||||
const char* GetSectionName(int section) const;
|
||||
const u8* GetSectionDataPtr(int section) const
|
||||
{
|
||||
if (section < 0 || section >= header->e_shnum)
|
||||
return nullptr;
|
||||
if (sections[section].sh_type != SHT_NOBITS)
|
||||
return GetPtr(sections[section].sh_offset);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
bool IsCodeSection(int section) const { return sections[section].sh_type == SHT_PROGBITS; }
|
||||
const u8* GetSegmentPtr(int segment) { return GetPtr(segments[segment].p_offset); }
|
||||
u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
|
||||
int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
|
||||
SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
|
||||
|
||||
// Quick accessors
|
||||
ElfType GetType() const { return (ElfType)(header->e_type); }
|
||||
ElfMachine GetMachine() const { return (ElfMachine)(header->e_machine); }
|
||||
u32 GetEntryPoint() const { return entryPoint; }
|
||||
u32 GetFlags() const { return (u32)(header->e_flags); }
|
||||
bool LoadIntoMemory();
|
||||
bool LoadSymbols();
|
||||
|
||||
int GetNumSegments() const { return (int)(header->e_phnum); }
|
||||
int GetNumSections() const { return (int)(header->e_shnum); }
|
||||
const u8* GetPtr(int offset) const { return (u8*)base + offset; }
|
||||
const char* GetSectionName(int section) const;
|
||||
const u8 *GetSectionDataPtr(int section) const
|
||||
{
|
||||
if (section < 0 || section >= header->e_shnum)
|
||||
return nullptr;
|
||||
if (sections[section].sh_type != SHT_NOBITS)
|
||||
return GetPtr(sections[section].sh_offset);
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
bool IsCodeSection(int section) const
|
||||
{
|
||||
return sections[section].sh_type == SHT_PROGBITS;
|
||||
}
|
||||
const u8* GetSegmentPtr(int segment)
|
||||
{
|
||||
return GetPtr(segments[segment].p_offset);
|
||||
}
|
||||
u32 GetSectionAddr(SectionID section) const { return sectionAddrs[section]; }
|
||||
int GetSectionSize(SectionID section) const { return sections[section].sh_size; }
|
||||
SectionID GetSectionByName(const char* name, int firstSection = 0) const; //-1 for not found
|
||||
|
||||
bool DidRelocate() const
|
||||
{
|
||||
return bRelocate;
|
||||
}
|
||||
bool DidRelocate() const { return bRelocate; }
|
||||
};
|
||||
|
|
|
@ -11,85 +11,83 @@
|
|||
// File type
|
||||
enum ElfType
|
||||
{
|
||||
ET_NONE = 0,
|
||||
ET_REL = 1,
|
||||
ET_EXEC = 2,
|
||||
ET_DYN = 3,
|
||||
ET_CORE = 4,
|
||||
ET_LOPROC = 0xFF00,
|
||||
ET_HIPROC = 0xFFFF,
|
||||
ET_NONE = 0,
|
||||
ET_REL = 1,
|
||||
ET_EXEC = 2,
|
||||
ET_DYN = 3,
|
||||
ET_CORE = 4,
|
||||
ET_LOPROC = 0xFF00,
|
||||
ET_HIPROC = 0xFFFF,
|
||||
};
|
||||
|
||||
// Machine/Architecture
|
||||
enum ElfMachine
|
||||
{
|
||||
EM_NONE = 0,
|
||||
EM_M32 = 1,
|
||||
EM_SPARC = 2,
|
||||
EM_386 = 3,
|
||||
EM_68K = 4,
|
||||
EM_88K = 5,
|
||||
EM_860 = 7,
|
||||
EM_MIPS = 8
|
||||
EM_NONE = 0,
|
||||
EM_M32 = 1,
|
||||
EM_SPARC = 2,
|
||||
EM_386 = 3,
|
||||
EM_68K = 4,
|
||||
EM_88K = 5,
|
||||
EM_860 = 7,
|
||||
EM_MIPS = 8
|
||||
};
|
||||
|
||||
// File version
|
||||
#define EV_NONE 0
|
||||
#define EV_NONE 0
|
||||
#define EV_CURRENT 1
|
||||
|
||||
// Identification index
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_MAG0 0
|
||||
#define EI_MAG1 1
|
||||
#define EI_MAG2 2
|
||||
#define EI_MAG3 3
|
||||
#define EI_CLASS 4
|
||||
#define EI_DATA 5
|
||||
#define EI_VERSION 6
|
||||
#define EI_PAD 7
|
||||
#define EI_PAD 7
|
||||
#define EI_NIDENT 16
|
||||
|
||||
// Magic number
|
||||
#define ELFMAG0 0x7F
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
#define ELFMAG1 'E'
|
||||
#define ELFMAG2 'L'
|
||||
#define ELFMAG3 'F'
|
||||
|
||||
// File class
|
||||
#define ELFCLASSNONE 0
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
#define ELFCLASS32 1
|
||||
#define ELFCLASS64 2
|
||||
|
||||
// Encoding
|
||||
#define ELFDATANONE 0
|
||||
#define ELFDATA2LSB 1
|
||||
#define ELFDATA2MSB 2
|
||||
|
||||
|
||||
|
||||
// Sections constants
|
||||
|
||||
// Section indexes
|
||||
#define SHN_UNDEF 0
|
||||
#define SHN_UNDEF 0
|
||||
#define SHN_LORESERVE 0xFF00
|
||||
#define SHN_LOPROC 0xFF00
|
||||
#define SHN_HIPROC 0xFF1F
|
||||
#define SHN_ABS 0xFFF1
|
||||
#define SHN_COMMON 0xFFF2
|
||||
#define SHN_LOPROC 0xFF00
|
||||
#define SHN_HIPROC 0xFF1F
|
||||
#define SHN_ABS 0xFFF1
|
||||
#define SHN_COMMON 0xFFF2
|
||||
#define SHN_HIRESERVE 0xFFFF
|
||||
|
||||
// Section types
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
#define SHT_NULL 0
|
||||
#define SHT_PROGBITS 1
|
||||
#define SHT_SYMTAB 2
|
||||
#define SHT_STRTAB 3
|
||||
#define SHT_RELA 4
|
||||
#define SHT_HASH 5
|
||||
#define SHT_DYNAMIC 6
|
||||
#define SHT_NOTE 7
|
||||
#define SHT_NOBITS 8
|
||||
#define SHT_REL 9
|
||||
#define SHT_SHLIB 10
|
||||
#define SHT_DYNSYM 11
|
||||
#define SHT_LOPROC 0x70000000
|
||||
#define SHT_HIPROC 0x7FFFFFFF
|
||||
#define SHT_LOUSER 0x80000000
|
||||
|
@ -98,58 +96,57 @@ enum ElfMachine
|
|||
// Custom section types
|
||||
#define SHT_PSPREL 0x700000a0
|
||||
|
||||
|
||||
// Section flags
|
||||
enum ElfSectionFlags
|
||||
{
|
||||
SHF_WRITE = 0x1,
|
||||
SHF_ALLOC = 0x2,
|
||||
SHF_EXECINSTR = 0x4,
|
||||
SHF_MASKPROC = 0xF0000000,
|
||||
SHF_WRITE = 0x1,
|
||||
SHF_ALLOC = 0x2,
|
||||
SHF_EXECINSTR = 0x4,
|
||||
SHF_MASKPROC = 0xF0000000,
|
||||
};
|
||||
|
||||
// Symbol binding
|
||||
#define STB_LOCAL 0
|
||||
#define STB_GLOBAL 1
|
||||
#define STB_WEAK 2
|
||||
#define STB_LOCAL 0
|
||||
#define STB_GLOBAL 1
|
||||
#define STB_WEAK 2
|
||||
#define STB_LOPROC 13
|
||||
#define STB_HIPROC 15
|
||||
|
||||
// Symbol types
|
||||
#define STT_NOTYPE 0
|
||||
#define STT_OBJECT 1
|
||||
#define STT_FUNC 2
|
||||
#define STT_SECTION 3
|
||||
#define STT_FILE 4
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
#define STT_NOTYPE 0
|
||||
#define STT_OBJECT 1
|
||||
#define STT_FUNC 2
|
||||
#define STT_SECTION 3
|
||||
#define STT_FILE 4
|
||||
#define STT_LOPROC 13
|
||||
#define STT_HIPROC 15
|
||||
|
||||
// Undefined name
|
||||
#define STN_UNDEF 0
|
||||
|
||||
// Relocation types
|
||||
#define R_386_NONE 0
|
||||
#define R_386_32 1
|
||||
#define R_386_PC32 2
|
||||
#define R_386_GOT32 3
|
||||
#define R_386_PLT32 4
|
||||
#define R_386_COPY 5
|
||||
#define R_386_GLOB_DAT 6
|
||||
#define R_386_JMP_SLOT 7
|
||||
#define R_386_RELATIVE 8
|
||||
#define R_386_GOTOFF 9
|
||||
#define R_386_GOTPC 10
|
||||
#define R_386_NONE 0
|
||||
#define R_386_32 1
|
||||
#define R_386_PC32 2
|
||||
#define R_386_GOT32 3
|
||||
#define R_386_PLT32 4
|
||||
#define R_386_COPY 5
|
||||
#define R_386_GLOB_DAT 6
|
||||
#define R_386_JMP_SLOT 7
|
||||
#define R_386_RELATIVE 8
|
||||
#define R_386_GOTOFF 9
|
||||
#define R_386_GOTPC 10
|
||||
|
||||
// Segment types
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7FFFFFFF
|
||||
#define PT_NULL 0
|
||||
#define PT_LOAD 1
|
||||
#define PT_DYNAMIC 2
|
||||
#define PT_INTERP 3
|
||||
#define PT_NOTE 4
|
||||
#define PT_SHLIB 5
|
||||
#define PT_PHDR 6
|
||||
#define PT_LOPROC 0x70000000
|
||||
#define PT_HIPROC 0x7FFFFFFF
|
||||
|
||||
// Segment flags
|
||||
#define PF_X 1
|
||||
|
@ -157,120 +154,118 @@ enum ElfSectionFlags
|
|||
#define PF_R 4
|
||||
|
||||
// Dynamic Array Tags
|
||||
#define DT_NULL 0
|
||||
#define DT_NEEDED 1
|
||||
#define DT_PLTRELSZ 2
|
||||
#define DT_PLTGOT 3
|
||||
#define DT_HASH 4
|
||||
#define DT_STRTAB 5
|
||||
#define DT_SYMTAB 6
|
||||
#define DT_RELA 7
|
||||
#define DT_RELASZ 8
|
||||
#define DT_RELAENT 9
|
||||
#define DT_STRSZ 10
|
||||
#define DT_SYMENT 11
|
||||
#define DT_INIT 12
|
||||
#define DT_FINI 13
|
||||
#define DT_SONAME 14
|
||||
#define DT_RPATH 15
|
||||
#define DT_SYMBOLIC 16
|
||||
#define DT_REL 17
|
||||
#define DT_RELSZ 18
|
||||
#define DT_RELENT 19
|
||||
#define DT_PLTREL 20
|
||||
#define DT_DEBUG 21
|
||||
#define DT_TEXTREL 22
|
||||
#define DT_JMPREL 23
|
||||
#define DT_LOPROC 0x70000000
|
||||
#define DT_HIPROC 0x7FFFFFFF
|
||||
#define DT_NULL 0
|
||||
#define DT_NEEDED 1
|
||||
#define DT_PLTRELSZ 2
|
||||
#define DT_PLTGOT 3
|
||||
#define DT_HASH 4
|
||||
#define DT_STRTAB 5
|
||||
#define DT_SYMTAB 6
|
||||
#define DT_RELA 7
|
||||
#define DT_RELASZ 8
|
||||
#define DT_RELAENT 9
|
||||
#define DT_STRSZ 10
|
||||
#define DT_SYMENT 11
|
||||
#define DT_INIT 12
|
||||
#define DT_FINI 13
|
||||
#define DT_SONAME 14
|
||||
#define DT_RPATH 15
|
||||
#define DT_SYMBOLIC 16
|
||||
#define DT_REL 17
|
||||
#define DT_RELSZ 18
|
||||
#define DT_RELENT 19
|
||||
#define DT_PLTREL 20
|
||||
#define DT_DEBUG 21
|
||||
#define DT_TEXTREL 22
|
||||
#define DT_JMPREL 23
|
||||
#define DT_LOPROC 0x70000000
|
||||
#define DT_HIPROC 0x7FFFFFFF
|
||||
|
||||
// ELF file header
|
||||
struct Elf32_Ehdr
|
||||
{
|
||||
u8 e_ident[EI_NIDENT];
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u32 e_entry;
|
||||
u32 e_phoff;
|
||||
u32 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
u8 e_ident[EI_NIDENT];
|
||||
u16 e_type;
|
||||
u16 e_machine;
|
||||
u32 e_version;
|
||||
u32 e_entry;
|
||||
u32 e_phoff;
|
||||
u32 e_shoff;
|
||||
u32 e_flags;
|
||||
u16 e_ehsize;
|
||||
u16 e_phentsize;
|
||||
u16 e_phnum;
|
||||
u16 e_shentsize;
|
||||
u16 e_shnum;
|
||||
u16 e_shstrndx;
|
||||
};
|
||||
|
||||
// Section header
|
||||
struct Elf32_Shdr
|
||||
{
|
||||
u32 sh_name;
|
||||
u32 sh_type;
|
||||
u32 sh_flags;
|
||||
u32 sh_addr;
|
||||
u32 sh_offset;
|
||||
u32 sh_size;
|
||||
u32 sh_link;
|
||||
u32 sh_info;
|
||||
u32 sh_addralign;
|
||||
u32 sh_entsize;
|
||||
u32 sh_name;
|
||||
u32 sh_type;
|
||||
u32 sh_flags;
|
||||
u32 sh_addr;
|
||||
u32 sh_offset;
|
||||
u32 sh_size;
|
||||
u32 sh_link;
|
||||
u32 sh_info;
|
||||
u32 sh_addralign;
|
||||
u32 sh_entsize;
|
||||
};
|
||||
|
||||
// Segment header
|
||||
struct Elf32_Phdr
|
||||
{
|
||||
u32 p_type;
|
||||
u32 p_offset;
|
||||
u32 p_vaddr;
|
||||
u32 p_paddr;
|
||||
u32 p_filesz;
|
||||
u32 p_memsz;
|
||||
u32 p_flags;
|
||||
u32 p_align;
|
||||
u32 p_type;
|
||||
u32 p_offset;
|
||||
u32 p_vaddr;
|
||||
u32 p_paddr;
|
||||
u32 p_filesz;
|
||||
u32 p_memsz;
|
||||
u32 p_flags;
|
||||
u32 p_align;
|
||||
};
|
||||
|
||||
// Symbol table entry
|
||||
struct Elf32_Sym
|
||||
{
|
||||
u32 st_name;
|
||||
u32 st_value;
|
||||
u32 st_size;
|
||||
u8 st_info;
|
||||
u8 st_other;
|
||||
u16 st_shndx;
|
||||
u32 st_name;
|
||||
u32 st_value;
|
||||
u32 st_size;
|
||||
u8 st_info;
|
||||
u8 st_other;
|
||||
u16 st_shndx;
|
||||
};
|
||||
|
||||
#define ELF32_ST_BIND(i) ((i)>>4)
|
||||
#define ELF32_ST_TYPE(i) ((i)&0xf)
|
||||
#define ELF32_ST_INFO(b,t) (((b)<<4)+((t)&0xf))
|
||||
#define ELF32_ST_BIND(i) ((i) >> 4)
|
||||
#define ELF32_ST_TYPE(i) ((i)&0xf)
|
||||
#define ELF32_ST_INFO(b, t) (((b) << 4) + ((t)&0xf))
|
||||
|
||||
// Relocation entries
|
||||
struct Elf32_Rel
|
||||
{
|
||||
u32 r_offset;
|
||||
u32 r_info;
|
||||
u32 r_offset;
|
||||
u32 r_info;
|
||||
};
|
||||
|
||||
struct Elf32_Rela
|
||||
{
|
||||
u32 r_offset;
|
||||
u32 r_info;
|
||||
s32 r_addend;
|
||||
u32 r_offset;
|
||||
u32 r_info;
|
||||
s32 r_addend;
|
||||
};
|
||||
|
||||
#define ELF32_R_SYM(i) ((i)>>8)
|
||||
#define ELF32_R_SYM(i) ((i) >> 8)
|
||||
#define ELF32_R_TYPE(i) ((u8)(i))
|
||||
#define ELF32_R_INFO(s,t) (((s)<<8 )+(u8)(t))
|
||||
|
||||
#define ELF32_R_INFO(s, t) (((s) << 8) + (u8)(t))
|
||||
|
||||
struct Elf32_Dyn
|
||||
{
|
||||
s32 d_tag;
|
||||
union
|
||||
{
|
||||
u32 d_val;
|
||||
u32 d_ptr;
|
||||
} d_un;
|
||||
s32 d_tag;
|
||||
union {
|
||||
u32 d_val;
|
||||
u32 d_ptr;
|
||||
} d_un;
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue