some changes of HLE of the WII game loader

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2655 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
fires.gc 2009-03-14 19:13:21 +00:00
parent bf30cc8a72
commit 56ec588c49
5 changed files with 218 additions and 229 deletions

View File

@ -48,6 +48,8 @@ private:
static bool EmulatedBIOS_Wii(bool _bDebug); static bool EmulatedBIOS_Wii(bool _bDebug);
static bool Load_BIOS(const std::string& _rBiosFilename); static bool Load_BIOS(const std::string& _rBiosFilename);
static void Load_FST(bool _bIsWii); static void Load_FST(bool _bIsWii);
static bool SetupWiiMemory(unsigned int _CountryCode);
}; };
#endif #endif

View File

@ -57,41 +57,34 @@ void CBoot::EmulatedBIOS(bool _bDebug)
// ======================================================================================= // =======================================================================================
// Write necessary values // Write necessary values
// --------------------------------------------------------------------------------------- //
/* Here we write values to memory that the apploader does not take care of. Game iso info goes // Here we write values to memory that the apploader does not take care of. Game iso info goes
to 0x80000000 according to yagcd 4.2. I'm not sure what bytes 8-10 does (version and // to 0x80000000 according to yagcd 4.2. I'm not sure what bytes 8-10 does (version and
streaming), but I include them anyway because it seems like they are supposed to be there. */ // streaming), but I include them anyway because it seems like they are supposed to be there.
// --------------------------------------------------------------------------------------- //
DVDInterface::DVDRead(0x00000000, 0x80000000, 10); // write boot info needed for multidisc games DVDInterface::DVDRead(0x00000000, 0x80000000, 10); // write boot info needed for multidisc games
Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi Memory::Write_U32(0x4c000064, 0x80000300); // write default DFI Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi Memory::Write_U32(0x4c000064, 0x80000800); // write default FPU Handler: rfi
Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi Memory::Write_U32(0x4c000064, 0x80000C00); // write default Syscall Handler: rfi
// Memory::Write_U32(0xc2339f3d, 0x8000001C); // game disc
Memory::Write_U32(0xc2339f3d, 0x8000001C); //game disc Memory::Write_U32(0x0D15EA5E, 0x80000020); // funny magic word for normal boot
Memory::Write_U32(0x0D15EA5E, 0x80000020); //funny magic word for normal boot
Memory::Write_U32(0x01800000, 0x80000028); // Physical Memory Size Memory::Write_U32(0x01800000, 0x80000028); // Physical Memory Size
// Memory::Write_U32(0x00000003, 0x8000002C); // Console type - retail Memory::Write_U32(0x00000003, 0x8000002C); // Console type - retail (DevKit ID == 0x10000006)
Memory::Write_U32(0x10000006, 0x8000002C); // DevKit
Memory::Write_U32(((1 & 0x3f) << 26) | 2, 0x81300000); // HLE OSReport for Apploader Memory::Write_U32(((1 & 0x3f) << 26) | 2, 0x81300000); // HLE OSReport for Apploader
// =======================================================================================
// =======================================================================================
// Load Apploader to Memory - The apploader is hardcoded to begin at byte 9 280 on the disc, // Load Apploader to Memory - The apploader is hardcoded to begin at byte 9 280 on the disc,
// but it seems like the size can be variable. Compare with yagcd chap 13. // but it seems like the size can be variable. Compare with yagcd chap 13.
// --------------------------------------------------------------------------------------- //
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
u32 iAppLoaderOffset = 0x2440; // 0x1c40 (what is 0x1c40?) u32 iAppLoaderOffset = 0x2440; // 0x1c40 (what is 0x1c40?)
// ---------------------------------------------------------------------------------------
u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10); u32 iAppLoaderEntry = VolumeHandler::Read32(iAppLoaderOffset + 0x10);
u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14); u32 iAppLoaderSize = VolumeHandler::Read32(iAppLoaderOffset + 0x14);
if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1)) if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1))
return; return;
VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize); VolumeHandler::ReadToPtr(Memory::GetPointer(0x81200000), iAppLoaderOffset + 0x20, iAppLoaderSize);
// =======================================================================================
// Call iAppLoaderEntry. // Call iAppLoaderEntry.
DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry"); DEBUG_LOG(MASTER_LOG, "Call iAppLoaderEntry");
@ -110,11 +103,9 @@ void CBoot::EmulatedBIOS(bool _bDebug)
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
{ {
@ -132,7 +123,6 @@ void CBoot::EmulatedBIOS(bool _bDebug)
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");
@ -161,40 +151,18 @@ void CBoot::EmulatedBIOS(bool _bDebug)
} }
// __________________________________________________________________________________________________
// bool CBoot::SetupWiiMemory(unsigned int _CountryCode)
// Wii BIOS HLE:
// copy the apploader to 0x81200000
// execute the apploader
//
bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
{ {
INFO_LOG(BOOT, "Faking Wii BIOS..."); INFO_LOG(BOOT, "Setup Wii Memory...");
// See if we have a memory dump to boot // Write the 256 byte setting.txt to memory. This may not be needed as
FILE* pDump = fopen(FULL_WII_SYS_DIR "dump_0x0000_0x4000.bin", "rb"); // most or all games read the setting.txt file from \title\00000001\00000002\
if (pDump != NULL) // data\setting.txt directly after the read the SYSCONF file. The games also
{ // read it to 0x3800, what is a little strange however is that it only reads
INFO_LOG(MASTER_LOG, "Init from memory dump."); // the first 100 bytes of it.
fread(Memory::GetMainRAMPtr(), 1, 16384, pDump);
fclose(pDump);
pDump = NULL;
}
else
{
// =======================================================
/* Write the 256 byte setting.txt to memory. This may not be needed as
most or all games read the setting.txt file from \title\00000001\00000002\
data\setting.txt directly after the read the SYSCONF file. The games also
read it to 0x3800, what is a little strange however is that it only reads
the first 100 bytes of it. */
// -------------
{
std::string filename(WII_EUR_SETTING_FILE); std::string filename(WII_EUR_SETTING_FILE);
if (VolumeHandler::IsValid()) switch((DiscIO::IVolume::ECountry)_CountryCode)
{
switch(VolumeHandler::GetVolume()->GetCountry())
{ {
case DiscIO::IVolume::COUNTRY_JAP: case DiscIO::IVolume::COUNTRY_JAP:
filename = WII_JAP_SETTING_FILE; filename = WII_JAP_SETTING_FILE;
@ -209,26 +177,22 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
break; break;
default: default:
PanicAlert("Unknown country. Wii boot process will be switched to European settings."); PanicAlert("SetupWiiMem: Unknown country. Wii boot process will be switched to European settings.");
filename = WII_EUR_SETTING_FILE; filename = WII_EUR_SETTING_FILE;
break; break;
} }
}
FILE* pTmp = fopen(filename.c_str(), "rb"); FILE* pTmp = fopen(filename.c_str(), "rb");
if (!pTmp) if (!pTmp)
{ {
ERROR_LOG(MASTER_LOG, "Cant find setting file"); PanicAlert("SetupWiiMem: Cant find setting file");
return false; return false;
} }
fread(Memory::GetPointer(0x3800), 256, 1, pTmp); fread(Memory::GetPointer(0x3800), 256, 1, pTmp);
fclose(pTmp); fclose(pTmp);
}
// =============
// =======================================================
/* Set hardcoded global variables to Wii memory. These are partly collected from /* Set hardcoded global variables to Wii memory. These are partly collected from
Wiibrew. These values are needed for the games to function correctly. A few Wiibrew. These values are needed for the games to function correctly. A few
values in this region will also be placed here by the game as it boots. values in this region will also be placed here by the game as it boots.
@ -247,8 +211,7 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
0x80000038 Start of FST 0x80000038 Start of FST
0x8000003c Size of FST Size 0x8000003c Size of FST Size
0x80000060 Copyright code */ 0x80000060 Copyright code */
// -------------
{
DVDInterface::DVDRead(0x00000000, 0x00000000, 6); // Game Code DVDInterface::DVDRead(0x00000000, 0x00000000, 6); // Game Code
Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
@ -278,9 +241,9 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
Memory::Write_U32(0x04000000, 0x0000311c); // BAT Memory::Write_U32(0x04000000, 0x0000311c); // BAT
Memory::Write_U32(0x93400000, 0x00003120); // BAT Memory::Write_U32(0x93400000, 0x00003120); // BAT
Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low Memory::Write_U32(0x90000800, 0x00003124); // Init - MEM2 low
Memory::Write_U32(0x933e0000, 0x00003128); // Init - MEM2 high Memory::Write_U32(0x93ae0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x933e0000, 0x00003130); // IOS MEM2 low Memory::Write_U32(0x93ae0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x93400000, 0x00003134); // IOS MEM2 high Memory::Write_U32(0x93b00000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type Memory::Write_U32(0x00000011, 0x00003138); // Console type
Memory::Write_U64(0x0009020400062507ULL, 0x00003140); // IOS Version Memory::Write_U64(0x0009020400062507ULL, 0x00003140); // IOS Version
Memory::Write_U16(0x0113, 0x0000315e); // Apploader Memory::Write_U16(0x0113, 0x0000315e); // Apploader
@ -290,6 +253,7 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
Memory::Write_U8(0x00, 0x00000006); // DVDInit Memory::Write_U8(0x00, 0x00000006); // DVDInit
Memory::Write_U8(0x00, 0x00000007); // DVDInit Memory::Write_U8(0x00, 0x00000007); // DVDInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit Memory::Write_U16(0x0000, 0x000030e0); // PADInit
Memory::Write_U32(0x80000000, 0x00003184); // GameID Address
// Fake the VI Init of the BIOS // Fake the VI Init of the BIOS
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC); Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC);
@ -300,15 +264,31 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
Memory::Write_U32(0x00000000, 0x80000000 + i); Memory::Write_U32(0x00000000, 0x80000000 + i);
} }
/* This is some kind of consistency check that is compared to the 0x00 return true;
values as the game boots. This location keep the 4 byte ID for as long }
as the game is running. The 6 byte ID at 0x00 is overwritten sometime
after this check during booting. */ // __________________________________________________________________________________________________
//
// Wii BIOS HLE:
// copy the apploader to 0x81200000
// execute the apploader
//
bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
{
INFO_LOG(BOOT, "Faking Wii BIOS...");
// setup wii memory
DiscIO::IVolume::ECountry CountryCode = DiscIO::IVolume::COUNTRY_UNKNOWN;
if (VolumeHandler::IsValid())
CountryCode = VolumeHandler::GetVolume()->GetCountry();
if (SetupWiiMemory(CountryCode) == false)
return false;
// 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
// as the game is running. The 6 byte ID at 0x00 is overwritten sometime
// after this check during booting.
VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4); VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
Memory::Write_U8(0x80, 0x00003184);
// ================
}
}
// Execute the apploader // Execute the apploader
if (VolumeHandler::IsValid() && VolumeHandler::IsWii()) if (VolumeHandler::IsValid() && VolumeHandler::IsWii())
@ -355,11 +335,11 @@ bool CBoot::EmulatedBIOS_Wii(bool _bDebug)
PowerPC::ppcState.gpr[3] = 0x81300000; PowerPC::ppcState.gpr[3] = 0x81300000;
RunFunction(iAppLoaderInit); RunFunction(iAppLoaderInit);
/* Let the apploader load the exe to memory. At this point I get an unknwon IPC command // Let the apploader load the exe to memory. At this point I get an unknwon IPC command
(command zero) when I load Wii Sports or other games a second time. I don't notice // (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 disconcerning however that Start after Stop // any side effects however. It's a little disconcerning however that Start after Stop
behaves differently than the first Start after starting Dolphin. It means something // behaves differently than the first Start after starting Dolphin. It means something
was not reset correctly. */ // was not reset correctly.
DEBUG_LOG(BOOT, "Run iAppLoaderMain"); DEBUG_LOG(BOOT, "Run iAppLoaderMain");
do do
{ {

View File

@ -25,65 +25,9 @@
#include "NANDContentLoader.h" #include "NANDContentLoader.h"
#include "FileUtil.h" #include "FileUtil.h"
#include "Boot_DOL.h" #include "Boot_DOL.h"
#include "Volume.h"
void SetupWiiMem()
{
//
// TODO: REDUDANT CODE SUX ....
//
Memory::Write_U32(0x5d1c9ea3, 0x00000018); // Magic word it is a wii disc
Memory::Write_U32(0x0D15EA5E, 0x00000020); // Another magic word
Memory::Write_U32(0x00000001, 0x00000024); // Unknown
Memory::Write_U32(0x01800000, 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(0x01800000, 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_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(0x933e0000, 0x00003128); // Init - MEM2 high
Memory::Write_U32(0x933e0000, 0x00003130); // IOS MEM2 low
Memory::Write_U32(0x93400000, 0x00003134); // IOS MEM2 high
Memory::Write_U32(0x00000011, 0x00003138); // Console type
Memory::Write_U64(0x0009020400062507ULL, 0x00003140); // IOS Version
Memory::Write_U16(0x0113, 0x0000315e); // Apploader
Memory::Write_U32(0x0000FF16, 0x00003158); // DDR ram vendor code
Memory::Write_U8(0x80, 0x0000315c); // OSInit
Memory::Write_U8(0x00, 0x00000006); // DVDInit
Memory::Write_U8(0x00, 0x00000007); // DVDInit
Memory::Write_U16(0x0000, 0x000030e0); // PADInit
// Fake the VI Init of the BIOS
Memory::Write_U32(SConfig::GetInstance().m_LocalCoreStartupParameter.bNTSC ? 0 : 1, 0x000000CC);
// Clear exception handler. Why? Don't we begin with only zeroes?
for (int i = 0x3000; i <= 0x3038; i += 4)
{
Memory::Write_U32(0x00000000, 0x80000000 + i);
}
}
bool CBoot::IsWiiWAD(const char *filename) bool CBoot::IsWiiWAD(const char *filename)
{ {
return DiscIO::CNANDContentManager::IsWiiWAD(filename); return DiscIO::CNANDContentManager::IsWiiWAD(filename);
@ -95,8 +39,6 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename)
if (ContentLoader.IsValid() == false) if (ContentLoader.IsValid() == false)
return false; return false;
SetupWiiMem();
// create Home directory // create Home directory
char Path[260+1]; char Path[260+1];
u64 TitleID = ContentLoader.GetTitleID(); u64 TitleID = ContentLoader.GetTitleID();
@ -106,7 +48,9 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename)
(u8)pTitleID[3], (u8)pTitleID[2], (u8)pTitleID[1], (u8)pTitleID[0]); (u8)pTitleID[3], (u8)pTitleID[2], (u8)pTitleID[1], (u8)pTitleID[0]);
File::CreateFullPath(Path); File::CreateFullPath(Path);
Memory::Write_U64( ContentLoader.GetTitleID(), 0x0000318c); // NAND Load Title ID // setup wii mem
if (SetupWiiMemory(ContentLoader.GetCountry()) == false)
return false;
// DOL // DOL
const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex()); const DiscIO::SNANDContent* pContent = ContentLoader.GetContentByIndex(ContentLoader.GetBootIndex());

View File

@ -132,6 +132,7 @@ public:
const u16 GetTitleVersion() const {return m_TileVersion;} const u16 GetTitleVersion() const {return m_TileVersion;}
const u16 GetNumEntries() const {return m_numEntries;} const u16 GetNumEntries() const {return m_numEntries;}
const DiscIO::IVolume::ECountry GetCountry() const;
private: private:
@ -352,6 +353,66 @@ bool CNANDContentLoader::ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u
return true; return true;
} }
const DiscIO::IVolume::ECountry CNANDContentLoader::GetCountry() const
{
DiscIO::IVolume::ECountry country = DiscIO::IVolume::COUNTRY_UNKNOWN;
if (IsValid())
{
u64 TitleID = GetTitleID();
char* pTitleID = (char*)&TitleID;
switch (pTitleID[0])
{
case 'S':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // PAL // <- that is shitty :) zelda demo disc
case 'P':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // PAL
case 'D':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // PAL
case 'F':
country = DiscIO::IVolume::COUNTRY_FRANCE;
break; // PAL
case 'I':
country = DiscIO::IVolume::COUNTRY_ITALY;
break; // PAL
case 'X':
country = DiscIO::IVolume::COUNTRY_EUROPE;
break; // XIII <- uses X but is PAL rip
case 'E':
country = DiscIO::IVolume::COUNTRY_USA;
break; // USA
case 'J':
country = DiscIO::IVolume::COUNTRY_JAP;
break; // JAP
case 'K':
country = DiscIO::IVolume::COUNTRY_KOR;
break; // KOR
case 'O':
country = DiscIO::IVolume::COUNTRY_UNKNOWN;
break; // SDK
default:
PanicAlert("Unknown Country Code!");
break;
}
}
return(country);
}
bool CNANDContentLoader::ParseWAD(DiscIO::IBlobReader& _rReader) bool CNANDContentLoader::ParseWAD(DiscIO::IBlobReader& _rReader)
{ {
CBlobBigEndianReader ReaderBig(_rReader); CBlobBigEndianReader ReaderBig(_rReader);

View File

@ -24,6 +24,7 @@
#include "Common.h" #include "Common.h"
#include "Blob.h" #include "Blob.h"
#include "Volume.h"
namespace DiscIO namespace DiscIO
{ {
@ -56,6 +57,7 @@ public:
virtual const std::vector<SNANDContent>& GetContent() const = 0; virtual const std::vector<SNANDContent>& GetContent() const = 0;
virtual const u16 GetTitleVersion() const = 0; virtual const u16 GetTitleVersion() const = 0;
virtual const u16 GetNumEntries() const = 0; virtual const u16 GetNumEntries() const = 0;
virtual const DiscIO::IVolume::ECountry GetCountry() const = 0;
enum enum
{ {