mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-03-12 06:39:14 +01:00
added support to load WAD files of the WII
the WiiWAD loader encrypts the WAD, loads the NAND AppLoader and executes it. The NAND Loader will load more parts of the WAD to memory and execute them. Some WADs show the loading screen but hanging because the BT devices cant be initialized. Dolphin is not able to connect to devices that arnt validates per SYSCONF. Perhaps a global flag is wrong or missing or we have to preload the SYSCONF by hand (or fix/improve the BT handling :)) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2348 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
ffa56ed61a
commit
5c2694a629
@ -218,6 +218,11 @@ inline u32 swap32(u32 data) {return((swap16(data) << 16) | swap16(data >> 16));}
|
||||
inline u64 swap64(u64 data) {return(((u64)swap32(data) << 32) | swap32(data >> 32));}
|
||||
#endif
|
||||
|
||||
inline u16 swap16(u8* _pData) {return(swap16(*(u16*)_pData));}
|
||||
inline u32 swap32(u8* _pData) {return(swap32(*(u32*)_pData));}
|
||||
inline u64 swap64(u8* _pData) {return(swap64(*(u64*)_pData));}
|
||||
|
||||
|
||||
} // end of namespace Common
|
||||
///////////////////////////////////
|
||||
|
||||
|
@ -34,4 +34,6 @@ void SaveSSEState();
|
||||
void LoadSSEState();
|
||||
void LoadDefaultSSEState();
|
||||
|
||||
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
|
||||
|
||||
#endif
|
||||
|
@ -2247,6 +2247,14 @@
|
||||
RelativePath=".\Src\Boot\Boot_ELF.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Boot\Boot_WiiWAD.cpp"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Boot\Boot_WiiWAD.h"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\Src\Boot\ElfReader.cpp"
|
||||
>
|
||||
|
@ -290,6 +290,13 @@ bool CBoot::BootUp()
|
||||
}
|
||||
break;
|
||||
|
||||
// Wii WAD
|
||||
// ===================================================================================
|
||||
case SCoreStartupParameter::BOOT_WIIWAD:
|
||||
Boot_WiiWAD(_StartupPara.m_strFilename.c_str());
|
||||
break;
|
||||
|
||||
|
||||
// BIOS
|
||||
// ===================================================================================
|
||||
case SCoreStartupParameter::BOOT_BIOS:
|
||||
|
@ -27,17 +27,9 @@ class CBoot
|
||||
{
|
||||
public:
|
||||
|
||||
enum TBootFileType
|
||||
{
|
||||
BOOT_ERROR,
|
||||
BOOT_DOL,
|
||||
BOOT_ELF,
|
||||
BOOT_ISO,
|
||||
BOOT_BIOS
|
||||
};
|
||||
|
||||
static bool BootUp();
|
||||
static bool IsElfWii(const char *filename);
|
||||
static bool IsWiiWAD(const char *filename);
|
||||
|
||||
static std::string GenerateMapFilename();
|
||||
|
||||
@ -50,6 +42,7 @@ private:
|
||||
|
||||
static bool LoadMapFromFilename(const std::string& _rFilename, const char* _gameID = NULL);
|
||||
static bool Boot_ELF(const char *filename);
|
||||
static bool Boot_WiiWAD(const char *filename);
|
||||
|
||||
static void EmulatedBIOS(bool _bDebug);
|
||||
static bool EmulatedBIOS_Wii(bool _bDebug);
|
||||
|
@ -16,62 +16,63 @@
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Boot_DOL.h"
|
||||
#include "FileUtil.h"
|
||||
|
||||
#include "../HW/Memmap.h"
|
||||
|
||||
CDolLoader::CDolLoader(const char* _szFilename) : m_bInit(false)
|
||||
|
||||
CDolLoader::CDolLoader(u8* _pBuffer, u32 _Size)
|
||||
: m_bInit(false)
|
||||
{
|
||||
// try to open file
|
||||
FILE* pStream = fopen(_szFilename, "rb");
|
||||
if (pStream)
|
||||
m_bInit = Initialize(_pBuffer, _Size);
|
||||
}
|
||||
|
||||
CDolLoader::CDolLoader(const char* _szFilename)
|
||||
: m_bInit(false)
|
||||
{
|
||||
u64 size = File::GetSize(_szFilename);
|
||||
u8* tmpBuffer = new u8[(size_t)size];
|
||||
|
||||
FILE* pStream = fopen(_szFilename, "rb");
|
||||
fread(tmpBuffer, size, 1, pStream);
|
||||
fclose(pStream);
|
||||
|
||||
m_bInit = Initialize(tmpBuffer, size);
|
||||
delete [] tmpBuffer;
|
||||
}
|
||||
|
||||
bool CDolLoader::Initialize(u8* _pBuffer, u32 _Size)
|
||||
{
|
||||
memcpy(&m_dolheader, _pBuffer, sizeof(SDolHeader));
|
||||
|
||||
// swap memory
|
||||
u32* p = (u32*)&m_dolheader;
|
||||
for (size_t i=0; i<(sizeof(SDolHeader)>>2); i++)
|
||||
p[i] = Common::swap32(p[i]);
|
||||
|
||||
// load all text (code) sections
|
||||
for(int i = 0; i < DOL_NUM_TEXT; i++)
|
||||
{
|
||||
fread(&m_dolheader, 1, sizeof(SDolHeader), pStream);
|
||||
|
||||
// swap memory
|
||||
u32* p = (u32*)&m_dolheader;
|
||||
for (size_t i=0; i<(sizeof(SDolHeader)>>2); i++)
|
||||
p[i] = Common::swap32(p[i]);
|
||||
|
||||
// load all text (code) sections
|
||||
for(int i = 0; i < DOL_NUM_TEXT; i++)
|
||||
if(m_dolheader.textOffset[i] != 0)
|
||||
{
|
||||
if(m_dolheader.textOffset[i] != 0)
|
||||
{
|
||||
u8* pTemp = new u8[m_dolheader.textSize[i]];
|
||||
|
||||
fseek(pStream, m_dolheader.textOffset[i], SEEK_SET);
|
||||
fread(pTemp, 1, m_dolheader.textSize[i], pStream);
|
||||
|
||||
for (u32 num = 0; num < m_dolheader.textSize[i]; num++)
|
||||
Memory::Write_U8(pTemp[num], m_dolheader.textAddress[i] + num);
|
||||
|
||||
delete [] pTemp;
|
||||
}
|
||||
u8* pTemp = &_pBuffer[m_dolheader.textOffset[i]];
|
||||
for (u32 num = 0; num < m_dolheader.textSize[i]; num++)
|
||||
Memory::Write_U8(pTemp[num], m_dolheader.textAddress[i] + num);
|
||||
}
|
||||
|
||||
// load all data sections
|
||||
for(int i = 0; i < DOL_NUM_DATA; i++)
|
||||
{
|
||||
if(m_dolheader.dataOffset[i] != 0)
|
||||
{
|
||||
u8* pTemp = new u8[m_dolheader.dataSize[i]];
|
||||
|
||||
fseek(pStream, m_dolheader.dataOffset[i], SEEK_SET);
|
||||
fread(pTemp, 1, m_dolheader.dataSize[i], pStream);
|
||||
|
||||
for (u32 num = 0; num < m_dolheader.dataSize[i]; num++)
|
||||
Memory::Write_U8(pTemp[num], m_dolheader.dataAddress[i] + num);
|
||||
|
||||
delete [] pTemp;
|
||||
}
|
||||
}
|
||||
|
||||
//TODO - we know where there is code, and where there is data
|
||||
//Make use of this!
|
||||
|
||||
fclose(pStream);
|
||||
m_bInit = true;
|
||||
}
|
||||
|
||||
// load all data sections
|
||||
for(int i = 0; i < DOL_NUM_DATA; i++)
|
||||
{
|
||||
if(m_dolheader.dataOffset[i] != 0)
|
||||
{
|
||||
u8* pTemp = &_pBuffer[m_dolheader.dataOffset[i]];
|
||||
for (u32 num = 0; num < m_dolheader.dataSize[i]; num++)
|
||||
Memory::Write_U8(pTemp[num], m_dolheader.dataAddress[i] + num);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
u32 CDolLoader::GetEntryPoint()
|
||||
|
@ -24,9 +24,12 @@ class CDolLoader
|
||||
{
|
||||
public:
|
||||
CDolLoader(const char* _szFilename);
|
||||
CDolLoader(u8* _pBuffer, u32 _Size);
|
||||
|
||||
u32 GetEntryPoint();
|
||||
|
||||
static bool IsDolWii(const char* filename);
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
@ -51,6 +54,8 @@ private:
|
||||
};
|
||||
SDolHeader m_dolheader;
|
||||
bool m_bInit;
|
||||
|
||||
bool Initialize(u8* _pBuffer, u32 _Size);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -19,6 +19,7 @@
|
||||
#include "Boot.h"
|
||||
#include "../HLE/HLE.h"
|
||||
#include "Boot_ELF.h"
|
||||
#include "Boot_WiiWAD.h"
|
||||
#include "ElfReader.h"
|
||||
#include "MappedFile.h"
|
||||
|
||||
|
279
Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp
Normal file
279
Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp
Normal file
@ -0,0 +1,279 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Boot.h"
|
||||
#include "../PowerPC/PowerPC.h"
|
||||
#include "../HLE/HLE.h"
|
||||
#include "../HW/Memmap.h"
|
||||
#include "../ConfigManager.h"
|
||||
#include "Blob.h"
|
||||
#include "MappedFile.h"
|
||||
#include "Boot_DOL.h"
|
||||
#include "Boot_WiiWAD.h"
|
||||
#include "AES/aes.h"
|
||||
#include "MathUtil.h"
|
||||
|
||||
class CBlobBigEndianReader
|
||||
{
|
||||
public:
|
||||
CBlobBigEndianReader(DiscIO::IBlobReader& _rReader) : m_rReader(_rReader) {}
|
||||
|
||||
u32 Read32(u64 _Offset)
|
||||
{
|
||||
u32 Temp;
|
||||
m_rReader.Read(_Offset, 4, (u8*)&Temp);
|
||||
return(Common::swap32(Temp));
|
||||
}
|
||||
|
||||
private:
|
||||
DiscIO::IBlobReader& m_rReader;
|
||||
};
|
||||
|
||||
std::vector<STileMetaContent> m_TileMetaContent;
|
||||
u16 m_BootIndex = -1;
|
||||
|
||||
void AESDecode(u8* _pKey, u8* _IV, u8* _pSrc, u32 _Size, u8* _pDest)
|
||||
{
|
||||
AES_KEY AESKey;
|
||||
|
||||
AES_set_decrypt_key(_pKey, 128, &AESKey);
|
||||
AES_cbc_encrypt(_pSrc, _pDest, _Size, &AESKey, _IV, AES_DECRYPT);
|
||||
}
|
||||
|
||||
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset)
|
||||
{
|
||||
if (_Size > 0)
|
||||
{
|
||||
u8* pTmpBuffer = new u8[_Size];
|
||||
_dbg_assert_msg_(BOOT, pTmpBuffer!=0, "WiiWAD: Cant allocate memory for WAD entry");
|
||||
|
||||
if (!_rReader.Read(_Offset, _Size, pTmpBuffer))
|
||||
{
|
||||
PanicAlert("WiiWAD: Could not read from file");
|
||||
}
|
||||
return pTmpBuffer;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void GetKeyFromTicket(u8* pTicket, u8* pTicketKey)
|
||||
{
|
||||
u8 CommonKey[16];
|
||||
FILE* pMasterKeyFile = fopen(WII_MASTERKEY_FILE, "rb");
|
||||
_dbg_assert_msg_(BOOT, pMasterKeyFile!=0x0, "WiiWAD: Cant open MasterKeyFile for WII");
|
||||
|
||||
if (pMasterKeyFile)
|
||||
{
|
||||
fread(CommonKey, 16, 1, pMasterKeyFile);
|
||||
fclose(pMasterKeyFile);
|
||||
|
||||
u8 IV[16];
|
||||
memset(IV, 0, sizeof IV);
|
||||
memcpy(IV, pTicket + 0x01dc, 8);
|
||||
AESDecode(CommonKey, IV, pTicket + 0x01bf, 16, pTicketKey);
|
||||
}
|
||||
}
|
||||
|
||||
bool ParseTMD(u8* pDataApp, u32 pDataAppSize, u8* pTicket, u8* pTMD)
|
||||
{
|
||||
u8 DecryptTitleKey[16];
|
||||
u8 IV[16];
|
||||
|
||||
GetKeyFromTicket(pTicket, DecryptTitleKey);
|
||||
|
||||
u32 numEntries = Common::swap16(pTMD + 0x01de);
|
||||
m_BootIndex = Common::swap16(pTMD + 0x01e0);
|
||||
u8* p = pDataApp;
|
||||
|
||||
m_TileMetaContent.resize(numEntries);
|
||||
|
||||
for (u32 i=0; i<numEntries; i++)
|
||||
{
|
||||
STileMetaContent& rContent = m_TileMetaContent[i];
|
||||
|
||||
rContent.m_ContentID = Common::swap32(pTMD + 0x01e4 + 0x24*i);
|
||||
rContent.m_Index = Common::swap16(pTMD + 0x01e8 + 0x24*i);
|
||||
rContent.m_Type = Common::swap16(pTMD + 0x01ea + 0x24*i);
|
||||
rContent.m_Size= (u32)ROUND_UP(Common::swap64(pTMD + 0x01ec + 0x24*i), 0x40);
|
||||
rContent.m_pData = new u8[rContent.m_Size];
|
||||
|
||||
memset(IV, 0, sizeof IV);
|
||||
memcpy(IV, pTMD + 0x01e8 + 0x24*i, 2);
|
||||
AESDecode(DecryptTitleKey, IV, p, rContent.m_Size, rContent.m_pData);
|
||||
|
||||
p += rContent.m_Size;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseWAD(DiscIO::IBlobReader& _rReader)
|
||||
{
|
||||
CBlobBigEndianReader ReaderBig(_rReader);
|
||||
|
||||
// get header size
|
||||
u32 HeaderSize = ReaderBig.Read32(0);
|
||||
if (HeaderSize != 0x20)
|
||||
{
|
||||
_dbg_assert_msg_(BOOT, (HeaderSize==0x20), "WiiWAD: Header size != 0x20");
|
||||
return false;
|
||||
}
|
||||
|
||||
// get header
|
||||
u8 Header[0x20];
|
||||
_rReader.Read(0, HeaderSize, Header);
|
||||
u32 HeaderType = ReaderBig.Read32(0x4);
|
||||
if ((0x49730000 != HeaderType) && (0x69620000 != HeaderType))
|
||||
return false;
|
||||
|
||||
u32 CertificateChainSize = ReaderBig.Read32(0x8);
|
||||
u32 Reserved = ReaderBig.Read32(0xC);
|
||||
u32 TicketSize = ReaderBig.Read32(0x10);
|
||||
u32 TMDSize = ReaderBig.Read32(0x14);
|
||||
u32 DataAppSize = ReaderBig.Read32(0x18);
|
||||
u32 FooterSize = ReaderBig.Read32(0x1C);
|
||||
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
|
||||
|
||||
u32 Offset = 0x40;
|
||||
u8* pCertificateChain = CreateWADEntry(_rReader, CertificateChainSize, Offset); Offset += ROUND_UP(CertificateChainSize, 0x40);
|
||||
u8* pTicket = CreateWADEntry(_rReader, TicketSize, Offset); Offset += ROUND_UP(TicketSize, 0x40);
|
||||
u8* pTMD = CreateWADEntry(_rReader, TMDSize, Offset); Offset += ROUND_UP(TMDSize, 0x40);
|
||||
u8* pDataApp = CreateWADEntry(_rReader, DataAppSize, Offset); Offset += ROUND_UP(DataAppSize, 0x40);
|
||||
u8* pFooter = CreateWADEntry(_rReader, FooterSize, Offset); Offset += ROUND_UP(FooterSize, 0x40);
|
||||
|
||||
bool Result = ParseTMD(pDataApp, DataAppSize, pTicket, pTMD);
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
bool CBoot::IsWiiWAD(const char* _pFileName)
|
||||
{
|
||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_pFileName);
|
||||
if (pReader == NULL)
|
||||
return false;
|
||||
|
||||
CBlobBigEndianReader Reader(*pReader);
|
||||
bool Result = false;
|
||||
|
||||
// check for wii wad
|
||||
if (Reader.Read32(0x00) == 0x20)
|
||||
{
|
||||
u32 WADTYpe = Reader.Read32(0x04);
|
||||
switch(WADTYpe)
|
||||
{
|
||||
case 0x49730000:
|
||||
case 0x69620000:
|
||||
Result = true;
|
||||
}
|
||||
}
|
||||
|
||||
delete pReader;
|
||||
|
||||
return Result;
|
||||
}
|
||||
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/* 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);
|
||||
// Memory::Write_U8(0x80, 0x00003184);
|
||||
// ================
|
||||
}
|
||||
|
||||
bool CBoot::Boot_WiiWAD(const char* _pFilename)
|
||||
{
|
||||
DiscIO::IBlobReader* pReader = DiscIO::CreateBlobReader(_pFilename);
|
||||
if (pReader == NULL)
|
||||
return false;
|
||||
|
||||
bool Result = ParseWAD(*pReader);
|
||||
delete pReader;
|
||||
|
||||
if (!Result)
|
||||
return false;
|
||||
|
||||
SetupWiiMem();
|
||||
|
||||
// DOL
|
||||
STileMetaContent& rContent = m_TileMetaContent[m_BootIndex];
|
||||
CDolLoader DolLoader(rContent.m_pData, rContent.m_Size);
|
||||
|
||||
PC = DolLoader.GetEntryPoint() | 0x80000000;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
35
Source/Core/Core/Src/Boot/Boot_WiiWAD.h
Normal file
35
Source/Core/Core/Src/Boot/Boot_WiiWAD.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct STileMetaContent
|
||||
{
|
||||
u32 m_ContentID;
|
||||
u16 m_Index;
|
||||
u16 m_Type;
|
||||
u32 m_Size;
|
||||
|
||||
u8* m_pData;
|
||||
};
|
||||
|
||||
|
||||
// [TODO]: this global internal stuff sux... the whole data should be inside the ES
|
||||
// but this is the easiest way atm
|
||||
extern std::vector<STileMetaContent> m_TileMetaContent;
|
@ -125,6 +125,14 @@ bool SCoreStartupParameter::AutoSetup(EBootBios _BootBios)
|
||||
m_BootType = BOOT_ELF;
|
||||
bNTSC = true;
|
||||
}
|
||||
else if ((!strcasecmp(Extension.c_str(), ".wad")) &&
|
||||
CBoot::IsWiiWAD(m_strFilename.c_str()))
|
||||
{
|
||||
bWii = true;
|
||||
Region = EUR_DIR;
|
||||
m_BootType = BOOT_WIIWAD;
|
||||
bNTSC = false;
|
||||
}
|
||||
else if (!strcasecmp(Extension.c_str(), ".dol"))
|
||||
{
|
||||
bWii = CDolLoader::IsDolWii(m_strFilename.c_str());
|
||||
|
@ -89,6 +89,7 @@ struct SCoreStartupParameter
|
||||
BOOT_ISO,
|
||||
BOOT_ELF,
|
||||
BOOT_DOL,
|
||||
BOOT_WIIWAD,
|
||||
BOOT_BIOS
|
||||
};
|
||||
EBootType m_BootType;
|
||||
|
@ -54,6 +54,23 @@
|
||||
#include "WII_IPC_HLE_Device.h"
|
||||
#include "../VolumeHandler.h"
|
||||
|
||||
#include "../boot/Boot_WiiWAD.h"
|
||||
|
||||
|
||||
struct SContentAccess
|
||||
{
|
||||
u32 m_Position;
|
||||
STileMetaContent* m_pContent;
|
||||
};
|
||||
|
||||
typedef std::map<u32, SContentAccess> CContenAccessMap;
|
||||
CContenAccessMap m_ContenAccessMap;
|
||||
u32 AccessIdentID = 0x60000000;
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// http://wiibrew.org/index.php?title=/dev/es
|
||||
|
||||
class CWII_IPC_HLE_Device_es : public IWII_IPC_HLE_Device
|
||||
@ -130,6 +147,90 @@ public:
|
||||
|
||||
switch(Buffer.Parameter)
|
||||
{
|
||||
case IOCTL_ES_OPENCONTENT: // 0x09
|
||||
{
|
||||
u32 CFD = AccessIdentID++;
|
||||
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
|
||||
m_ContenAccessMap[CFD].m_Position = 0;
|
||||
m_ContenAccessMap[CFD].m_pContent = &m_TileMetaContent[Index];
|
||||
|
||||
Memory::Write_U32(CFD, _CommandAddress + 0x4);
|
||||
|
||||
LOG(WII_IPC_ES, "ES: IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_READCONTENT:
|
||||
{
|
||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
||||
|
||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
u32 Size = Buffer.PayloadBuffer[0].m_Size;
|
||||
u32 Addr = Buffer.PayloadBuffer[0].m_Address;
|
||||
|
||||
_dbg_assert_(WII_IPC_ES, m_ContenAccessMap.find(CFD) != m_ContenAccessMap.end());
|
||||
SContentAccess& rContent = m_ContenAccessMap[CFD];
|
||||
|
||||
u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position];
|
||||
u8* pDest = Memory::GetPointer(Addr);
|
||||
|
||||
memcpy(pDest,pSrc, Size);
|
||||
rContent.m_Position += Size;
|
||||
|
||||
LOG(WII_IPC_ES, "ES: IOCTL_ES_READCONTENT: CFD %x, Addr 0x%x, Size %i -> stream pos %i", CFD, Addr, Size, rContent.m_Position);
|
||||
|
||||
Memory::Write_U32(Size, _CommandAddress + 0x4);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_CLOSECONTENT:
|
||||
{
|
||||
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
|
||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
|
||||
CContenAccessMap::iterator itr = m_ContenAccessMap.find(CFD);
|
||||
m_ContenAccessMap.erase(itr);
|
||||
|
||||
LOG(WII_IPC_ES, "ES: IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
|
||||
|
||||
Memory::Write_U32(0, _CommandAddress + 0x4);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_SEEKCONTENT:
|
||||
{
|
||||
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
|
||||
u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
|
||||
|
||||
_dbg_assert_(WII_IPC_ES, m_ContenAccessMap.find(CFD) != m_ContenAccessMap.end());
|
||||
SContentAccess& rContent = m_ContenAccessMap[CFD];
|
||||
|
||||
switch(Mode)
|
||||
{
|
||||
case 0: // SET
|
||||
rContent.m_Position = Addr;
|
||||
break;
|
||||
|
||||
case 1: // CUR
|
||||
break;
|
||||
|
||||
case 2: // END
|
||||
rContent.m_Position = rContent.m_pContent->m_Size;
|
||||
break;
|
||||
}
|
||||
|
||||
LOG(WII_IPC_ES, "ES: IOCTL_ES_SEEKCONTENT: CFD %x, Addr 0x%x, Mode %i -> Pos %i", CFD, Addr, Mode, rContent.m_Position);
|
||||
|
||||
Memory::Write_U32(rContent.m_Position, _CommandAddress + 0x4);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
|
||||
case IOCTL_ES_GETTITLEDIR: // 0x1d
|
||||
{
|
||||
/* I changed reading the TitleID from disc to reading from the
|
||||
@ -166,7 +267,9 @@ public:
|
||||
case IOCTL_ES_GETVIEWCNT: // 0x12 (Input: 8 bytes, Output: 4 bytes)
|
||||
{
|
||||
if(Buffer.NumberInBuffer)
|
||||
{
|
||||
u32 InBuffer = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
|
||||
}
|
||||
|
||||
// Should we write something here?
|
||||
//Memory::Write_U32(0, Buffer.PayloadBuffer[0].m_Address);
|
||||
|
@ -310,6 +310,14 @@ void dcbtst(UGeckoInstruction _inst)
|
||||
// TODO(ector) check docs
|
||||
void dcbz(UGeckoInstruction _inst)
|
||||
{
|
||||
// !!! after the dcbz follows a dcbf... dont clear the memory in this case !!!
|
||||
// 0x81330c2c
|
||||
u32 NextOpcode = Memory::Read_U32(PC+4);
|
||||
if (NextOpcode == 0x7C0400AC)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// HACK but works... we think
|
||||
Memory::Memset(Helper_Get_EA_X(_inst) & (~31), 0, 32);
|
||||
}
|
||||
|
@ -255,6 +255,8 @@
|
||||
// Zero cache line.
|
||||
void Jit64::dcbz(UGeckoInstruction inst)
|
||||
{
|
||||
Default(inst); return;
|
||||
|
||||
if(Core::g_CoreStartupParameter.bJITOff || Core::g_CoreStartupParameter.bJITLoadStoreOff)
|
||||
{Default(inst); return;} // turn off from debugger
|
||||
INSTRUCTION_START;
|
||||
|
@ -21,6 +21,7 @@ files = ["Console.cpp",
|
||||
"Boot/Boot_BIOSEmu.cpp",
|
||||
"Boot/Boot_DOL.cpp",
|
||||
"Boot/Boot_ELF.cpp",
|
||||
"Boot/Boot_WiiWAD.cpp",
|
||||
"Boot/ElfReader.cpp",
|
||||
"Debugger/Debugger_BreakPoints.cpp",
|
||||
"Debugger/Debugger_SymbolMap.cpp",
|
||||
|
@ -409,7 +409,7 @@ void CFrame::DoOpen(bool Boot)
|
||||
wxEmptyString, wxEmptyString, wxEmptyString,
|
||||
wxString::Format
|
||||
(
|
||||
_T("All GC/Wii files (elf, dol, gcm, iso)|*.elf;*.dol;*.gcm;*.iso;*.gcz|All files (%s)|%s"),
|
||||
_T("All GC/Wii files (elf, dol, gcm, iso, wad)|*.elf;*.dol;*.gcm;*.iso;*.gcz;*.wad|All files (%s)|%s"),
|
||||
wxFileSelectorDefaultWildcardStr,
|
||||
wxFileSelectorDefaultWildcardStr
|
||||
),
|
||||
|
Loading…
x
Reference in New Issue
Block a user