Added Korean handling of settings file.

Fixes issue 5215.
This commit is contained in:
parlane 2012-02-19 23:02:01 +00:00
parent b9aeba7f7c
commit c42a6f156e

View File

@ -1,444 +1,452 @@
// Copyright (C) 2003 Dolphin Project. // Copyright (C) 2003 Dolphin Project.
// This program is free software: you can redistribute it and/or modify // This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by // it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0. // the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful, // This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of // but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details. // GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program. // A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/ // If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at // Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/ // http://code.google.com/p/dolphin-emu/
#include "Common.h" #include "Common.h"
#include "CommonPaths.h" #include "CommonPaths.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "NandPaths.h" #include "NandPaths.h"
#include "../PowerPC/PowerPC.h" #include "../PowerPC/PowerPC.h"
#include "../Core.h" #include "../Core.h"
#include "../HW/EXI_DeviceIPL.h" #include "../HW/EXI_DeviceIPL.h"
#include "../HW/Memmap.h" #include "../HW/Memmap.h"
#include "../HW/DVDInterface.h" #include "../HW/DVDInterface.h"
#include "../HW/CPU.h" #include "../HW/CPU.h"
#include "../Host.h" #include "../Host.h"
#include "../VolumeHandler.h" #include "../VolumeHandler.h"
#include "../PatchEngine.h" #include "../PatchEngine.h"
#include "../MemTools.h" #include "../MemTools.h"
#include "../ConfigManager.h" #include "../ConfigManager.h"
#include "VolumeCreator.h" #include "VolumeCreator.h"
#include "Boot.h" #include "Boot.h"
#include "HLE/HLE.h" #include "HLE/HLE.h"
#include "SettingsHandler.h" #include "SettingsHandler.h"
void CBoot::RunFunction(u32 _iAddr) void CBoot::RunFunction(u32 _iAddr)
{ {
PC = _iAddr; PC = _iAddr;
LR = 0x00; LR = 0x00;
while (PC != 0x00) while (PC != 0x00)
PowerPC::SingleStep(); PowerPC::SingleStep();
} }
// __________________________________________________________________________________________________ // __________________________________________________________________________________________________
// GameCube Bootstrap 2 HLE: // GameCube Bootstrap 2 HLE:
// copy the apploader to 0x81200000 // copy the apploader to 0x81200000
// execute the apploader, function by function, using the above utility. // execute the apploader, function by function, using the above utility.
bool CBoot::EmulatedBS2_GC() bool CBoot::EmulatedBS2_GC()
{ {
INFO_LOG(BOOT, "Faking GC BS2..."); INFO_LOG(BOOT, "Faking GC BS2...");
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr); UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
m_MSR.FP = 1; m_MSR.FP = 1;
// Clear ALL memory // Clear ALL memory
Memory::Clear(); Memory::Clear();
// Write necessary values // Write necessary values
// Here we write values to memory that the apploader does not take care of. Game info goes // Here we write values to memory that the apploader does not take care of. Game info goes
// to 0x80000000 according to yagcd 4.2. // to 0x80000000 according to yagcd 4.2.
DVDInterface::DVDRead(0x00000000, 0x80000000, 0x20); // write disc info DVDInterface::DVDRead(0x00000000, 0x80000000, 0x20); // write disc info
Memory::Write_U32(0x0D15EA5E, 0x80000020); // booted from bootrom. 0xE5207C22 = booted from jtag Memory::Write_U32(0x0D15EA5E, 0x80000020); // booted from bootrom. 0xE5207C22 = booted from jtag
Memory::Write_U32(Memory::REALRAM_SIZE, 0x80000028); // Physical Memory Size (24MB on retail) Memory::Write_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) // TODO determine why some games fail when using a retail id. (Seem to take different EXI paths, see ikaruga for example)
Memory::Write_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see yagcd 4.2.1.1.2 Memory::Write_U32(0x10000006, 0x8000002C); // Console type - DevKit (retail ID == 0x00000003) see yagcd 4.2.1.1.2
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC
? 0 : 1, 0x800000CC); // fake the VI Init of the IPL (yagcd 4.2.1.4) ? 0 : 1, 0x800000CC); // fake the VI Init of the IPL (yagcd 4.2.1.4)
Memory::Write_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external (retail consoles have no external ARAM) Memory::Write_U32(0x01000000, 0x800000d0); // ARAM Size. 16MB main + 4/16/32MB external (retail consoles have no external ARAM)
Memory::Write_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed Memory::Write_U32(0x09a7ec80, 0x800000F8); // Bus Clock Speed
Memory::Write_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed Memory::Write_U32(0x1cf7c580, 0x800000FC); // CPU Clock Speed
Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi
Memory::Write_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); // preset time base ticks Memory::Write_U64((u64)CEXIIPL::GetGCTime() * (u64)40500000, 0x800030D8); // preset time base ticks
// HIO checks this // HIO checks this
//Memory::Write_U16(0x8200, 0x000030e6); // Console type //Memory::Write_U16(0x8200, 0x000030e6); // Console type
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
// Load Apploader to Memory - The apploader is hardcoded to begin at 0x2440 on the disc, // 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. // but the size can differ between discs. Compare with yagcd chap 13.
u32 iAppLoaderOffset = 0x2440; u32 iAppLoaderOffset = 0x2440;
u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10); u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10);
u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14) + VolumeHandler::Read32(iAppLoaderOffset + 0x18); u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14) + VolumeHandler::Read32(iAppLoaderOffset + 0x18);
if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1)) if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1))
{ {
INFO_LOG(BOOT, "GC BS2: Not running apploader!"); INFO_LOG(BOOT, "GC BS2: Not running apploader!");
return false; return false;
} }
VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize); VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize);
// Setup pointers like real BS2 does // Setup pointers like real BS2 does
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC) if (SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC)
{ {
PowerPC::ppcState.gpr[1] = 0x81566550; // StackPointer, used to be set to 0x816ffff0 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[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) PowerPC::ppcState.gpr[13] = 0x81465320; // global pointer to Small Data Area Base (Luigi's Mansion's apploader uses it)
} }
else else
{ {
PowerPC::ppcState.gpr[1] = 0x815edca8; PowerPC::ppcState.gpr[1] = 0x815edca8;
PowerPC::ppcState.gpr[2] = 0x814b5b20; PowerPC::ppcState.gpr[2] = 0x814b5b20;
PowerPC::ppcState.gpr[13] = 0x814b4fc0; PowerPC::ppcState.gpr[13] = 0x814b4fc0;
} }
// TODO - Make Apploader(or just RunFunction()) debuggable!!! // TODO - Make Apploader(or just RunFunction()) debuggable!!!
// Call iAppLoaderEntry. // Call iAppLoaderEntry.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry"); DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry");
u32 iAppLoaderFuncAddr = 0x80003100; u32 iAppLoaderFuncAddr = 0x80003100;
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0; PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4; PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8; PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(iAppLoaderEntry); RunFunction(iAppLoaderEntry);
u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 0); u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 0);
u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 4); u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 4);
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 8); u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr + 8);
// iAppLoaderInit // iAppLoaderInit
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit"); DEBUG_LOG(MASTER_LOG, "Call iAppLoaderInit");
PowerPC::ppcState.gpr[3] = 0x81300000; PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit); RunFunction(iAppLoaderInit);
// iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem). // iAppLoaderMain - Here we load the apploader, the DOL (the exe) and the FST (filesystem).
// To give you an idea about where the stuff is located on the disc take a look at yagcd // To give you an idea about where the stuff is located on the disc take a look at yagcd
// ch 13. // ch 13.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderMain"); DEBUG_LOG(MASTER_LOG, "Call iAppLoaderMain");
do do
{ {
PowerPC::ppcState.gpr[3] = 0x81300004; PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008; PowerPC::ppcState.gpr[4] = 0x81300008;
PowerPC::ppcState.gpr[5] = 0x8130000c; PowerPC::ppcState.gpr[5] = 0x8130000c;
RunFunction(iAppLoaderMain); RunFunction(iAppLoaderMain);
u32 iRamAddress = Memory::ReadUnchecked_U32(0x81300004); u32 iRamAddress = Memory::ReadUnchecked_U32(0x81300004);
u32 iLength = Memory::ReadUnchecked_U32(0x81300008); u32 iLength = Memory::ReadUnchecked_U32(0x81300008);
u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c); u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c);
INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength); INFO_LOG(MASTER_LOG, "DVDRead: offset: %08x memOffset: %08x length: %i", iDVDOffset, iRamAddress, iLength);
DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength); DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength);
} while(PowerPC::ppcState.gpr[3] != 0x00); } while(PowerPC::ppcState.gpr[3] != 0x00);
// iAppLoaderClose // iAppLoaderClose
DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose"); DEBUG_LOG(MASTER_LOG, "call iAppLoaderClose");
RunFunction(iAppLoaderClose); RunFunction(iAppLoaderClose);
// return // return
PC = PowerPC::ppcState.gpr[3]; PC = PowerPC::ppcState.gpr[3];
// Load patches // Load patches
std::string gameID = VolumeHandler::GetVolume()->GetUniqueID(); std::string gameID = VolumeHandler::GetVolume()->GetUniqueID();
PatchEngine::LoadPatches(gameID.c_str()); PatchEngine::LoadPatches(gameID.c_str());
PowerPC::ppcState.DebugCount = 0; PowerPC::ppcState.DebugCount = 0;
// If we have any patches that need to be applied very early, here's a good place // If we have any patches that need to be applied very early, here's a good place
PatchEngine::ApplyFramePatches(); PatchEngine::ApplyFramePatches();
return true; return true;
} }
bool CBoot::SetupWiiMemory(unsigned int _CountryCode) bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
{ {
INFO_LOG(BOOT, "Setup Wii Memory..."); INFO_LOG(BOOT, "Setup Wii Memory...");
// Write the 256 byte setting.txt to memory. // Write the 256 byte setting.txt to memory.
std::string settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_SETTING); std::string settings_Filename(Common::GetTitleDataPath(TITLEID_SYSMENU) + WII_SETTING);
std::string area, model, code, video, game; std::string area, model, code, video, game;
switch((DiscIO::IVolume::ECountry)_CountryCode) switch((DiscIO::IVolume::ECountry)_CountryCode)
{ {
case DiscIO::IVolume::COUNTRY_KOREA: case DiscIO::IVolume::COUNTRY_KOREA:
case DiscIO::IVolume::COUNTRY_TAIWAN: area = "KOR";
// TODO: Determine if Korea / Taiwan have their own specific settings. video = "NTSC";
case DiscIO::IVolume::COUNTRY_JAPAN: game = "KR";
area = "JPN"; code = "LKH";
video = "NTSC"; break;
break; case DiscIO::IVolume::COUNTRY_TAIWAN:
// TODO: Determine if Taiwan have their own specific settings.
case DiscIO::IVolume::COUNTRY_USA: case DiscIO::IVolume::COUNTRY_JAPAN:
area = "USA"; area = "JPN";
video = "NTSC"; video = "NTSC";
break; game = "JP";
code = "LU";
case DiscIO::IVolume::COUNTRY_EUROPE: break;
area = "EUR"; case DiscIO::IVolume::COUNTRY_USA:
video = "PAL"; area = "USA";
break; video = "NTSC";
game = "US";
default: code = "LU";
// PanicAlertT("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings."); break;
area = "EUR"; case DiscIO::IVolume::COUNTRY_EUROPE:
video = "PAL"; area = "EUR";
break; video = "PAL";
} game = "EU";
code = "LE";
model = "RVL-001(" + area + ")"; break;
code = "L" + area.substr(0,1); default:
game = area.substr(0,2); // PanicAlertT("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings.");
area = "EUR";
SettingsHandler gen; video = "PAL";
std::string serno = ""; game = "EU";
if (File::Exists(settings_Filename)) code = "LE";
{ break;
File::IOFile settingsFileHandle(settings_Filename, "rb"); }
if (settingsFileHandle.ReadBytes((void*)gen.GetData(), SettingsHandler::SETTINGS_SIZE))
{ model = "RVL-001(" + area + ")";
gen.Decrypt();
serno = gen.GetValue("SERNO"); SettingsHandler gen;
gen.Reset(); std::string serno = "";
} if (File::Exists(settings_Filename))
File::Delete(settings_Filename); {
} File::IOFile settingsFileHandle(settings_Filename, "rb");
if (settingsFileHandle.ReadBytes((void*)gen.GetData(), SettingsHandler::SETTINGS_SIZE))
if (serno.empty() || serno == "000000000") {
{ gen.Decrypt();
serno = gen.generateSerialNumber(); serno = gen.GetValue("SERNO");
INFO_LOG(BOOT, "No previous serial number found, generated one instead: %s", serno.c_str()); gen.Reset();
} }
else File::Delete(settings_Filename);
{ }
INFO_LOG(BOOT, "Using serial number: %s", serno.c_str());
} if (serno.empty() || serno == "000000000")
{
gen.AddSetting("AREA", area.c_str()); serno = gen.generateSerialNumber();
gen.AddSetting("MODEL", model.c_str()); INFO_LOG(BOOT, "No previous serial number found, generated one instead: %s", serno.c_str());
gen.AddSetting("DVD", "0"); }
gen.AddSetting("MPCH", "0x7FFE"); else
gen.AddSetting("CODE", code.c_str()); {
gen.AddSetting("SERNO", serno.c_str()); INFO_LOG(BOOT, "Using serial number: %s", serno.c_str());
gen.AddSetting("VIDEO", video.c_str()); }
gen.AddSetting("GAME", game.c_str());
gen.AddSetting("AREA", area.c_str());
gen.AddSetting("MODEL", model.c_str());
File::CreateFullPath(settings_Filename); gen.AddSetting("DVD", "0");
gen.AddSetting("MPCH", "0x7FFE");
{ gen.AddSetting("CODE", code.c_str());
File::IOFile settingsFileHandle(settings_Filename, "wb"); gen.AddSetting("SERNO", serno.c_str());
gen.AddSetting("VIDEO", video.c_str());
if (!settingsFileHandle.WriteBytes(gen.GetData(), SettingsHandler::SETTINGS_SIZE)) gen.AddSetting("GAME", game.c_str());
{
PanicAlertT("SetupWiiMem: Cant create setting file");
return false; File::CreateFullPath(settings_Filename);
}
Memory::WriteBigEData(gen.GetData(), 0x3800, SettingsHandler::SETTINGS_SIZE); {
} File::IOFile settingsFileHandle(settings_Filename, "wb");
/* if (!settingsFileHandle.WriteBytes(gen.GetData(), SettingsHandler::SETTINGS_SIZE))
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 PanicAlertT("SetupWiiMem: Cant create setting file");
values in this region will also be placed here by the game as it boots. return false;
They are: }
0x80000038 Start of FST Memory::WriteBigEData(gen.GetData(), 0x3800, SettingsHandler::SETTINGS_SIZE);
0x8000003c Size of FST Size }
0x80000060 Copyright code
*/ /*
Set hardcoded global variables to Wii memory. These are partly collected from
DVDInterface::DVDRead(0x00000000, 0x00000000, 0x20); // Game Code Wiibrew. These values are needed for the games to function correctly. A few
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word values in this region will also be placed here by the game as it boots.
Memory::Write_U32(0x00000001, 0x00000024); // Unknown They are:
Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB 0x80000038 Start of FST
Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model 0x8000003c Size of FST Size
Memory::Write_U32(0x00000000, 0x00000030); // Init 0x80000060 Copyright code
Memory::Write_U32(0x817FEC60, 0x00000034); // Init */
// 38, 3C should get start, size of FST through apploader
Memory::Write_U32(0x38a00040, 0x00000060); // Exception init DVDInterface::DVDRead(0x00000000, 0x00000000, 0x20); // Game Code
Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?) Memory::Write_U32(0x00000001, 0x00000024); // Unknown
Memory::Write_U32(0x8179b500, 0x000000f4); // __start Memory::Write_U32(Memory::REALRAM_SIZE, 0x00000028); // MEM1 size 24MB
Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed Memory::Write_U32(0x00000023, 0x0000002c); // Production Board Model
Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed Memory::Write_U32(0x00000000, 0x00000030); // Init
Memory::Write_U16(0x0000, 0x000030e6); // Console type Memory::Write_U32(0x817FEC60, 0x00000034); // Init
Memory::Write_U32(0x00000000, 0x000030c0); // EXI // 38, 3C should get start, size of FST through apploader
Memory::Write_U32(0x00000000, 0x000030c4); // EXI Memory::Write_U32(0x38a00040, 0x00000060); // Exception init
Memory::Write_U32(0x00000000, 0x000030dc); // Time Memory::Write_U32(0x8008f7b8, 0x000000e4); // Thread Init
Memory::Write_U32(0x00000000, 0x000030d8); // Time Memory::Write_U32(Memory::REALRAM_SIZE, 0x000000f0); // "Simulated memory size" (debug mode?)
Memory::Write_U32(0x00000000, 0x000030f0); // Apploader Memory::Write_U32(0x8179b500, 0x000000f4); // __start
Memory::Write_U32(0x01800000, 0x00003100); // BAT Memory::Write_U32(0x0e7be2c0, 0x000000f8); // Bus speed
Memory::Write_U32(0x01800000, 0x00003104); // BAT Memory::Write_U32(0x2B73A840, 0x000000fc); // CPU speed
Memory::Write_U32(0x00000000, 0x0000310c); // Init Memory::Write_U16(0x0000, 0x000030e6); // Console type
Memory::Write_U32(0x8179d500, 0x00003110); // Init Memory::Write_U32(0x00000000, 0x000030c0); // EXI
Memory::Write_U32(0x04000000, 0x00003118); // Unknown Memory::Write_U32(0x00000000, 0x000030c4); // EXI
Memory::Write_U32(0x04000000, 0x0000311c); // BAT Memory::Write_U32(0x00000000, 0x000030dc); // Time
Memory::Write_U32(0x93400000, 0x00003120); // BAT Memory::Write_U32(0x00000000, 0x000030d8); // Time
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low Memory::Write_U32(0x00000000, 0x000030f0); // Apploader
Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high Memory::Write_U32(0x01800000, 0x00003100); // BAT
Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low Memory::Write_U32(0x01800000, 0x00003104); // BAT
Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high Memory::Write_U32(0x00000000, 0x0000310c); // Init
Memory::Write_U32(0x00000011, 0x00003138); // Console type Memory::Write_U32(0x8179d500, 0x00003110); // Init
// 40 is copied from 88 after running apploader Memory::Write_U32(0x04000000, 0x00003118); // Unknown
Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4) Memory::Write_U32(0x04000000, 0x0000311c); // BAT
Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007) Memory::Write_U32(0x93400000, 0x00003120); // BAT
Memory::Write_U16(0x0113, 0x0000315e); // Apploader Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear) Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x00090204, 0x00003188); // Expected IOS revision Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type
Memory::Write_U8(0x80, 0x0000315c); // OSInit // 40 is copied from 88 after running apploader
Memory::Write_U16(0x0000, 0x000030e0); // PADInit Memory::Write_U32(0x00090204, 0x00003140); // IOS revision (IOS9, v2.4)
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address Memory::Write_U32(0x00062507, 0x00003144); // IOS date in USA format (June 25, 2007)
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
// Fake the VI Init of the IPL Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC); Memory::Write_U32(0x00000000, 0x00003160); // Init semaphore (sysmenu waits for this to clear)
Memory::Write_U32(0x00090204, 0x00003188); // Expected IOS revision
// Clear exception handler. Why? Don't we begin with only zeros?
for (int i = 0x3000; i <= 0x3038; i += 4) Memory::Write_U8(0x80, 0x0000315c); // OSInit
{ Memory::Write_U16(0x0000, 0x000030e0); // PADInit
Memory::Write_U32(0x00000000, 0x80000000 + i); Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
}
return true; // Fake the VI Init of the IPL
} Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC);
// __________________________________________________________________________________________________ // Clear exception handler. Why? Don't we begin with only zeros?
// Wii Bootstrap 2 HLE: for (int i = 0x3000; i <= 0x3038; i += 4)
// copy the apploader to 0x81200000 {
// execute the apploader Memory::Write_U32(0x00000000, 0x80000000 + i);
bool CBoot::EmulatedBS2_Wii() }
{ return true;
INFO_LOG(BOOT, "Faking Wii BS2..."); }
// setup wii memory // __________________________________________________________________________________________________
DiscIO::IVolume::ECountry CountryCode = DiscIO::IVolume::COUNTRY_UNKNOWN; // Wii Bootstrap 2 HLE:
if (VolumeHandler::IsValid()) // copy the apploader to 0x81200000
CountryCode = VolumeHandler::GetVolume()->GetCountry(); // execute the apploader
if (SetupWiiMemory(CountryCode) == false) bool CBoot::EmulatedBS2_Wii()
return false; {
INFO_LOG(BOOT, "Faking Wii BS2...");
// This is some kind of consistency check that is compared to the 0x00
// values as the game boots. This location keep the 4 byte ID for as long // setup wii memory
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime DiscIO::IVolume::ECountry CountryCode = DiscIO::IVolume::COUNTRY_UNKNOWN;
// after this check during booting. if (VolumeHandler::IsValid())
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4); CountryCode = VolumeHandler::GetVolume()->GetCountry();
if (SetupWiiMemory(CountryCode) == false)
// Execute the apploader return false;
bool apploaderRan = false;
if (VolumeHandler::IsValid() && VolumeHandler::IsWii()) // This is some kind of consistency check that is compared to the 0x00
{ // values as the game boots. This location keep the 4 byte ID for as long
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr); // as the game is running. The 6 byte ID at 0x00 is overwritten sometime
m_MSR.FP = 1; // after this check during booting.
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi // Execute the apploader
Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi bool apploaderRan = false;
if (VolumeHandler::IsValid() && VolumeHandler::IsWii())
HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader {
UReg_MSR& m_MSR = ((UReg_MSR&)PowerPC::ppcState.msr);
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer m_MSR.FP = 1;
u32 iAppLoaderOffset = 0x2440; // 0x1c40; Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi
// Load Apploader to Memory Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi
u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10);
u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14); HLE::Patch(0x81300000, "OSReport"); // HLE OSReport for Apploader
if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1))
{ PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
return false; u32 iAppLoaderOffset = 0x2440; // 0x1c40;
}
VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize); // Load Apploader to Memory
u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10);
//call iAppLoaderEntry u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14);
DEBUG_LOG(BOOT, "Call iAppLoaderEntry"); if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1))
{
u32 iAppLoaderFuncAddr = 0x80004000; ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0; return false;
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4; }
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8; VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize);
RunFunction(iAppLoaderEntry);
u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+0); //call iAppLoaderEntry
u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+4); DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+8);
u32 iAppLoaderFuncAddr = 0x80004000;
// iAppLoaderInit PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
DEBUG_LOG(BOOT, "Run iAppLoaderInit"); PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
PowerPC::ppcState.gpr[3] = 0x81300000; PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
RunFunction(iAppLoaderInit); RunFunction(iAppLoaderEntry);
u32 iAppLoaderInit = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+0);
// Let the apploader load the exe to memory. At this point I get an unknown IPC command u32 iAppLoaderMain = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+4);
// (command zero) when I load Wii Sports or other games a second time. I don't notice u32 iAppLoaderClose = Memory::ReadUnchecked_U32(iAppLoaderFuncAddr+8);
// 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 // iAppLoaderInit
// was not reset correctly. DEBUG_LOG(BOOT, "Run iAppLoaderInit");
DEBUG_LOG(BOOT, "Run iAppLoaderMain"); PowerPC::ppcState.gpr[3] = 0x81300000;
do RunFunction(iAppLoaderInit);
{
PowerPC::ppcState.gpr[3] = 0x81300004; // Let the apploader load the exe to memory. At this point I get an unknown IPC command
PowerPC::ppcState.gpr[4] = 0x81300008; // (command zero) when I load Wii Sports or other games a second time. I don't notice
PowerPC::ppcState.gpr[5] = 0x8130000c; // 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
RunFunction(iAppLoaderMain); // was not reset correctly.
DEBUG_LOG(BOOT, "Run iAppLoaderMain");
u32 iRamAddress = Memory::ReadUnchecked_U32(0x81300004); do
u32 iLength = Memory::ReadUnchecked_U32(0x81300008); {
u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c) << 2; PowerPC::ppcState.gpr[3] = 0x81300004;
PowerPC::ppcState.gpr[4] = 0x81300008;
INFO_LOG(BOOT, "DVDRead: offset: %08x memOffse: %08x length: %i", iDVDOffset, iRamAddress, iLength); PowerPC::ppcState.gpr[5] = 0x8130000c;
DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength);
} while(PowerPC::ppcState.gpr[3] != 0x00); RunFunction(iAppLoaderMain);
// iAppLoaderClose u32 iRamAddress = Memory::ReadUnchecked_U32(0x81300004);
DEBUG_LOG(BOOT, "Run iAppLoaderClose"); u32 iLength = Memory::ReadUnchecked_U32(0x81300008);
RunFunction(iAppLoaderClose); u32 iDVDOffset = Memory::ReadUnchecked_U32(0x8130000c) << 2;
apploaderRan = true; INFO_LOG(BOOT, "DVDRead: offset: %08x memOffse: %08x length: %i", iDVDOffset, iRamAddress, iLength);
DVDInterface::DVDRead(iDVDOffset, iRamAddress, iLength);
// Pass the "#002 check" } while(PowerPC::ppcState.gpr[3] != 0x00);
// Apploader writes the IOS version and revision here, we copy it
// Fake IOSv9 r2.4 if no version is found (elf loading) // iAppLoaderClose
u32 firmwareVer = Memory::Read_U32(0x80003188); DEBUG_LOG(BOOT, "Run iAppLoaderClose");
Memory::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x00003140); RunFunction(iAppLoaderClose);
// Load patches and run startup patches apploaderRan = true;
std::string gameID = VolumeHandler::GetVolume()->GetUniqueID();
PatchEngine::LoadPatches(gameID.c_str()); // Pass the "#002 check"
// Apploader writes the IOS version and revision here, we copy it
// return // Fake IOSv9 r2.4 if no version is found (elf loading)
PC = PowerPC::ppcState.gpr[3]; u32 firmwareVer = Memory::Read_U32(0x80003188);
} Memory::Write_U32(firmwareVer ? firmwareVer : 0x00090204, 0x00003140);
PowerPC::ppcState.DebugCount = 0; // Load patches and run startup patches
std::string gameID = VolumeHandler::GetVolume()->GetUniqueID();
return apploaderRan; PatchEngine::LoadPatches(gameID.c_str());
}
// return
// Returns true if apploader has run successfully PC = PowerPC::ppcState.gpr[3];
bool CBoot::EmulatedBS2(bool _bIsWii) }
{
return _bIsWii ? EmulatedBS2_Wii() : EmulatedBS2_GC(); PowerPC::ppcState.DebugCount = 0;
}
return apploaderRan;
}
// Returns true if apploader has run successfully
bool CBoot::EmulatedBS2(bool _bIsWii)
{
return _bIsWii ? EmulatedBS2_Wii() : EmulatedBS2_GC();
}