added some more function for ES emulation and NANDLoader... but IOCTL_ES_LAUNCH so a lot of WADs aren't loaded completely
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2425 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
1f029ab1b5
commit
bf7d379537
|
@ -26,6 +26,7 @@
|
||||||
#include "Boot_WiiWAD.h"
|
#include "Boot_WiiWAD.h"
|
||||||
#include "AES/aes.h"
|
#include "AES/aes.h"
|
||||||
#include "MathUtil.h"
|
#include "MathUtil.h"
|
||||||
|
#include "FileUtil.h"
|
||||||
|
|
||||||
class CBlobBigEndianReader
|
class CBlobBigEndianReader
|
||||||
{
|
{
|
||||||
|
@ -45,6 +46,7 @@ private:
|
||||||
|
|
||||||
std::vector<STileMetaContent> m_TileMetaContent;
|
std::vector<STileMetaContent> m_TileMetaContent;
|
||||||
u16 m_BootIndex = -1;
|
u16 m_BootIndex = -1;
|
||||||
|
u64 m_TitleID = -1;
|
||||||
|
|
||||||
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
|
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
|
||||||
{
|
{
|
||||||
|
@ -97,6 +99,8 @@ bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD)
|
||||||
|
|
||||||
u32 numEntries = Common::swap16(pTMD + 0x01de);
|
u32 numEntries = Common::swap16(pTMD + 0x01de);
|
||||||
m_BootIndex = Common::swap16(pTMD + 0x01e0);
|
m_BootIndex = Common::swap16(pTMD + 0x01e0);
|
||||||
|
m_TitleID = Common::swap64(pTMD + 0x018C);
|
||||||
|
|
||||||
u8* p = pDataApp;
|
u8* p = pDataApp;
|
||||||
|
|
||||||
m_TileMetaContent.resize(numEntries);
|
m_TileMetaContent.resize(numEntries);
|
||||||
|
@ -243,12 +247,29 @@ void SetupWiiMem()
|
||||||
Memory::Write_U32(0x00000000, 0x80000000 + i);
|
Memory::Write_U32(0x00000000, 0x80000000 + i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// create Home directory
|
||||||
|
{
|
||||||
|
char Path[260+1];
|
||||||
|
char* pTitleID = (char*)&m_TitleID;
|
||||||
|
sprintf(Path, FULL_WII_USER_DIR "title//%02x%02x%02x%02x/%02x%02x%02x%02x/data/nocopy/",
|
||||||
|
(u8)pTitleID[7], (u8)pTitleID[6], (u8)pTitleID[5], (u8)pTitleID[4],
|
||||||
|
(u8)pTitleID[3], (u8)pTitleID[2], (u8)pTitleID[1], (u8)pTitleID[0]);
|
||||||
|
File::CreateDirectoryStructure(Path);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* This is some kind of consistency check that is compared to the 0x00
|
/* This is some kind of consistency check that is compared to the 0x00
|
||||||
values as the game boots. This location keep the 4 byte ID for as long
|
values as the game boots. This location keep the 4 byte ID for as long
|
||||||
as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
as the game is running. The 6 byte ID at 0x00 is overwritten sometime
|
||||||
after this check during booting. */
|
after this check during booting. */
|
||||||
|
|
||||||
|
|
||||||
|
Memory::Write_U64(m_TitleID, 0x0000318c); // NAND Load Title ID
|
||||||
|
|
||||||
// VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
|
// VolumeHandler::ReadToPtr(Memory::GetPointer(0x3180), 0, 4);
|
||||||
// Memory::Write_U8(0x80, 0x00003184);
|
// Memory::Write_U8(0x80, 0x00003184);
|
||||||
// ================
|
// ================
|
||||||
|
|
|
@ -33,4 +33,5 @@ struct STileMetaContent
|
||||||
// [TODO]: this global internal stuff sux... the whole data should be inside the ES
|
// [TODO]: this global internal stuff sux... the whole data should be inside the ES
|
||||||
// but this is the easiest way atm
|
// but this is the easiest way atm
|
||||||
extern std::vector<STileMetaContent> m_TileMetaContent;
|
extern std::vector<STileMetaContent> m_TileMetaContent;
|
||||||
|
extern u64 m_TitleID;
|
||||||
|
|
||||||
|
|
|
@ -36,6 +36,11 @@ void HWCALL Read32(u32& _rReturnValue, const u32 _Address)
|
||||||
{
|
{
|
||||||
switch(_Address & 0xFFFF)
|
switch(_Address & 0xFFFF)
|
||||||
{
|
{
|
||||||
|
// NAND Loader ... no idea
|
||||||
|
case 0x018:
|
||||||
|
LOGV(WII_IOB, 0, "IOP: Read32 from 0x18 = 0x%08x", _Address);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xc0: // __VISendI2CData
|
case 0xc0: // __VISendI2CData
|
||||||
_rReturnValue = 0;
|
_rReturnValue = 0;
|
||||||
LOGV(WII_IOB, 2, "IOP: Read32 from 0xc0 = 0x%08x (__VISendI2CData)", _rReturnValue);
|
LOGV(WII_IOB, 2, "IOP: Read32 from 0xc0 = 0x%08x (__VISendI2CData)", _rReturnValue);
|
||||||
|
@ -91,6 +96,11 @@ void HWCALL Write32(const u32 _Value, const u32 _Address)
|
||||||
{
|
{
|
||||||
switch(_Address & 0xFFFF)
|
switch(_Address & 0xFFFF)
|
||||||
{
|
{
|
||||||
|
// NAND Loader ... no idea
|
||||||
|
case 0x18:
|
||||||
|
LOGV(WII_IOB, 0, "IOP: Write32 0x%08x to 0x%08x", _Value, _Address);
|
||||||
|
break;
|
||||||
|
|
||||||
case 0xc0: // __VISendI2CData
|
case 0xc0: // __VISendI2CData
|
||||||
LOGV(WII_IOB, 2, "IOP: Write32 to 0xc0 = 0x%08x (__VISendI2CData)", _Value);
|
LOGV(WII_IOB, 2, "IOP: Write32 to 0xc0 = 0x%08x (__VISendI2CData)", _Value);
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -274,7 +274,7 @@ void CopySettingsFile(std::string DeviceName)
|
||||||
void ExecuteCommand(u32 _Address)
|
void ExecuteCommand(u32 _Address)
|
||||||
{
|
{
|
||||||
bool GenerateReply = false;
|
bool GenerateReply = false;
|
||||||
u32 erased = 0;
|
u32 ClosedDeviceID = 0;
|
||||||
|
|
||||||
ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address));
|
ECommandType Command = static_cast<ECommandType>(Memory::Read_U32(_Address));
|
||||||
switch (Command)
|
switch (Command)
|
||||||
|
@ -368,7 +368,7 @@ void ExecuteCommand(u32 _Address)
|
||||||
// Delete the device when CLOSE is called, this does not effect
|
// Delete the device when CLOSE is called, this does not effect
|
||||||
// GenerateReply() for any other purpose than the logging because
|
// GenerateReply() for any other purpose than the logging because
|
||||||
// it's a true / false only function //
|
// it's a true / false only function //
|
||||||
erased = DeviceID;
|
ClosedDeviceID = DeviceID;
|
||||||
GenerateReply = true;
|
GenerateReply = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -449,7 +449,7 @@ void ExecuteCommand(u32 _Address)
|
||||||
g_ReplyQueue.push(std::pair<u32, std::string>(_Address, "unknown"));
|
g_ReplyQueue.push(std::pair<u32, std::string>(_Address, "unknown"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (erased > 0 && erased == DeviceID)
|
if (ClosedDeviceID > 0 && ClosedDeviceID == DeviceID)
|
||||||
DeleteDeviceByID(DeviceID);
|
DeleteDeviceByID(DeviceID);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -56,6 +56,8 @@
|
||||||
|
|
||||||
#include "../Boot/Boot_WiiWAD.h"
|
#include "../Boot/Boot_WiiWAD.h"
|
||||||
|
|
||||||
|
#include "../PowerPC/PowerPC.h"
|
||||||
|
|
||||||
|
|
||||||
struct SContentAccess
|
struct SContentAccess
|
||||||
{
|
{
|
||||||
|
@ -147,6 +149,25 @@ public:
|
||||||
|
|
||||||
switch(Buffer.Parameter)
|
switch(Buffer.Parameter)
|
||||||
{
|
{
|
||||||
|
case IOCTL_ES_LAUNCH: // 0x08
|
||||||
|
{
|
||||||
|
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 2);
|
||||||
|
|
||||||
|
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||||
|
|
||||||
|
u32 view = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
||||||
|
u64 ticketid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+4);
|
||||||
|
u32 devicetype =Memory::Read_U32(Buffer.InBuffer[1].m_Address+12);
|
||||||
|
u64 titleid = Memory::Read_U64(Buffer.InBuffer[1].m_Address+16);
|
||||||
|
u16 access = Memory::Read_U16(Buffer.InBuffer[1].m_Address+24);
|
||||||
|
|
||||||
|
PanicAlert("IOCTL_ES_LAUNCH: src titleID %08x/%08x -> start %08x/%08x", TitleID>>32, TitleID, titleid>>32, titleid );
|
||||||
|
|
||||||
|
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_OPENCONTENT: // 0x09
|
case IOCTL_ES_OPENCONTENT: // 0x09
|
||||||
{
|
{
|
||||||
u32 CFD = AccessIdentID++;
|
u32 CFD = AccessIdentID++;
|
||||||
|
@ -245,12 +266,13 @@ public:
|
||||||
/* I changed reading the TitleID from disc to reading from the
|
/* I changed reading the TitleID from disc to reading from the
|
||||||
InBuffer, if it fails it's because of some kind of memory error
|
InBuffer, if it fails it's because of some kind of memory error
|
||||||
that we would want to fix anyway */
|
that we would want to fix anyway */
|
||||||
u32 TitleID = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
|
||||||
if (TitleID == 0) TitleID = 0xF00DBEEF;
|
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||||
|
_dbg_assert_msg_(WII_IPC_HLE, TitleID == GetCurrentTitleID(), "Get Dir from unkw title dir?? this can be okay...");
|
||||||
|
|
||||||
char* pTitleID = (char*)&TitleID;
|
char* pTitleID = (char*)&TitleID;
|
||||||
char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
char* Path = (char*)Memory::GetPointer(Buffer.PayloadBuffer[0].m_Address);
|
||||||
sprintf(Path, "/00010000/%08x/data", TitleID);
|
sprintf(Path, "/%08x/%08x/data", (TitleID >> 32) & 0xFFFFFFFF, TitleID & 0xFFFFFFFF);
|
||||||
|
|
||||||
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEDIR: %s)", Path);
|
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEDIR: %s)", Path);
|
||||||
}
|
}
|
||||||
|
@ -258,8 +280,8 @@ public:
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLEID: // 0x20
|
case IOCTL_ES_GETTITLEID: // 0x20
|
||||||
{
|
{
|
||||||
u32 TitleID = VolumeHandler::Read32(0);
|
_dbg_assert_msg_(WII_IPC_HLE, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETTITLEID no in buffer");
|
||||||
if (TitleID == 0) TitleID = 0xF00DBEEF;
|
|
||||||
|
|
||||||
/* This seems to be the right address to write the Title ID to
|
/* This seems to be the right address to write the Title ID to
|
||||||
because then it shows up in the InBuffer of IOCTL_ES_GETTITLEDIR
|
because then it shows up in the InBuffer of IOCTL_ES_GETTITLEDIR
|
||||||
|
@ -268,28 +290,73 @@ public:
|
||||||
IOCTL_ES_GETTITLEDIR. This values is not stored in 0x3180 or anywhere
|
IOCTL_ES_GETTITLEDIR. This values is not stored in 0x3180 or anywhere
|
||||||
else as I have seen, it's just used as an input buffer in the following
|
else as I have seen, it's just used as an input buffer in the following
|
||||||
IOCTL_ES_GETTITLEDIR call and then forgotten. */
|
IOCTL_ES_GETTITLEDIR call and then forgotten. */
|
||||||
Memory::Write_U32(TitleID, Buffer.PayloadBuffer[0].m_Address);
|
|
||||||
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: 0x%x", TitleID);
|
u64 TitleID = GetCurrentTitleID();
|
||||||
|
|
||||||
|
Memory::Write_U64(TitleID, Buffer.PayloadBuffer[0].m_Address);
|
||||||
|
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETTITLEID: 0x%x 0x%x", TitleID>>32, TitleID);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETVIEWCNT: // 0x12 (Input: 8 bytes, Output: 4 bytes)
|
case IOCTL_ES_GETVIEWCNT: // 0x12 (Input: 8 bytes, Output: 4 bytes)
|
||||||
{
|
{
|
||||||
if(Buffer.NumberInBuffer)
|
_dbg_assert_msg_(WII_IPC_HLE, Buffer.NumberInBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETVIEWCNT no in buffer");
|
||||||
|
_dbg_assert_msg_(WII_IPC_HLE, Buffer.NumberPayloadBuffer == 1, "CWII_IPC_HLE_Device_es: IOCTL_ES_GETVIEWCNT no out buffer");
|
||||||
|
|
||||||
|
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||||
|
|
||||||
|
// [TODO] here we should have a map from title id to tickets or something like that...
|
||||||
|
if (m_TileMetaContent.size() > 0)
|
||||||
{
|
{
|
||||||
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
Memory::Write_U32(1, Buffer.PayloadBuffer[0].m_Address);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Should we write something here?
|
LOG(WII_IPC_ES, "ES: IOCTL_ES_GETVIEWCNT titleID: %08x/%08x", TitleID>>32, TitleID );
|
||||||
//Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
|
|
||||||
|
|
||||||
//DumpCommands(Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size / 4,
|
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||||
// LogTypes::WII_IPC_NET);
|
return true;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IOCTL_ES_GETVIEWS:
|
||||||
|
{
|
||||||
|
_dbg_assert_msg_(WII_IPC_HLE, Buffer.NumberInBuffer == 2, "IOCTL_ES_GETVIEWS no in buffer");
|
||||||
|
_dbg_assert_msg_(WII_IPC_HLE, Buffer.NumberPayloadBuffer == 1, "IOCTL_ES_GETVIEWS no out buffer");
|
||||||
|
|
||||||
|
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||||
|
u32 Count = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
||||||
|
|
||||||
|
_dbg_assert_msg_(WII_IPC_HLE, TitleID==0x0000000100000002, "IOCTL_ES_GETVIEWS: TitleID != 00000001/00000002");
|
||||||
|
|
||||||
|
/* write ticket data... hmmm
|
||||||
|
typedef struct _tikview {
|
||||||
|
u32 view;
|
||||||
|
u64 ticketid;
|
||||||
|
u32 devicetype;
|
||||||
|
u64 titleid;
|
||||||
|
u16 access_mask;
|
||||||
|
u8 reserved[0x3c];
|
||||||
|
u8 cidx_mask[0x40];
|
||||||
|
u16 padding;
|
||||||
|
tiklimit limits[8];
|
||||||
|
} __attribute__((packed)) tikview;
|
||||||
|
*/
|
||||||
|
|
||||||
|
Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
|
||||||
|
Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address+4);
|
||||||
|
Memory::Write_U32(0x00010001, Buffer.PayloadBuffer[0].m_Address+12);
|
||||||
|
Memory::Write_U64(m_TitleID, Buffer.PayloadBuffer[0].m_Address+16);
|
||||||
|
Memory::Write_U16(0x777, Buffer.PayloadBuffer[0].m_Address+24);
|
||||||
|
|
||||||
|
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
|
||||||
case IOCTL_ES_GETTMDVIEWCNT: // 0x14
|
case IOCTL_ES_GETTMDVIEWCNT: // 0x14
|
||||||
{
|
{
|
||||||
|
PanicAlert("IOCTL_ES_GETTMDVIEWCNT: this looks really wrong...");
|
||||||
if(Buffer.NumberInBuffer)
|
if(Buffer.NumberInBuffer)
|
||||||
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||||
|
|
||||||
|
@ -299,14 +366,19 @@ public:
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETCONSUMPTION: // (Input: 8 bytes, Output: 0 bytes, 4 bytes)
|
case IOCTL_ES_GETCONSUMPTION: // (Input: 8 bytes, Output: 0 bytes, 4 bytes)
|
||||||
|
PanicAlert("IOCTL_ES_GETCONSUMPTION: this looks really wrong...");
|
||||||
//DumpCommands(Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size / 4,
|
//DumpCommands(Buffer.InBuffer[0].m_Address, Buffer.InBuffer[0].m_Size / 4,
|
||||||
// LogTypes::WII_IPC_NET);
|
// LogTypes::WII_IPC_NET);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_DIGETTICKETVIEW: // (Input: none, Output: 216 bytes)
|
case IOCTL_ES_DIGETTICKETVIEW: // (Input: none, Output: 216 bytes)
|
||||||
|
PanicAlert("IOCTL_ES_DIGETTICKETVIEW: this looks really wrong...");
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case IOCTL_ES_GETTITLECOUNT:
|
case IOCTL_ES_GETTITLECOUNT:
|
||||||
{
|
{
|
||||||
|
PanicAlert("IOCTL_ES_GETTITLECOUNT: this looks really wrong...");
|
||||||
|
|
||||||
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
|
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
|
||||||
|
|
||||||
Memory::Write_U32(0, OutBuffer);
|
Memory::Write_U32(0, OutBuffer);
|
||||||
|
@ -318,6 +390,9 @@ public:
|
||||||
|
|
||||||
case IOCTL_ES_GETSTOREDTMDSIZE:
|
case IOCTL_ES_GETSTOREDTMDSIZE:
|
||||||
{
|
{
|
||||||
|
PanicAlert("IOCTL_ES_GETSTOREDTMDSIZE: this looks really wrong...");
|
||||||
|
|
||||||
|
|
||||||
u64 TitleId = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
u64 TitleId = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
|
||||||
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
|
u32 OutBuffer = Memory::Read_U32(Buffer.PayloadBuffer[0].m_Address);
|
||||||
|
|
||||||
|
@ -344,8 +419,27 @@ public:
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 GetCurrentTitleID()
|
||||||
|
{
|
||||||
|
u64 TitleID = 0;
|
||||||
|
|
||||||
|
// check for cd ...
|
||||||
|
if (VolumeHandler::IsValid())
|
||||||
|
{
|
||||||
|
TitleID = ((u64)0x00010000 << 32) | VolumeHandler::Read32(0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (m_TileMetaContent.size() > 0)
|
||||||
|
{
|
||||||
|
TitleID = m_TitleID;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (TitleID == -1)
|
||||||
|
TitleID = ((u64)0x00010000 << 32) | 0xF00DBEEF;
|
||||||
|
|
||||||
|
return TitleID;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue