diff --git a/Source/Core/Common/Src/Common.h b/Source/Core/Common/Src/Common.h index ac8f57e772..c46e6219e3 100644 --- a/Source/Core/Common/Src/Common.h +++ b/Source/Core/Common/Src/Common.h @@ -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 /////////////////////////////////// diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index 6edaffb2ca..6e55b4a789 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -34,4 +34,6 @@ void SaveSSEState(); void LoadSSEState(); void LoadDefaultSSEState(); +#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) + #endif diff --git a/Source/Core/Core/Core.vcproj b/Source/Core/Core/Core.vcproj index f0bb0a466c..6a95657e88 100644 --- a/Source/Core/Core/Core.vcproj +++ b/Source/Core/Core/Core.vcproj @@ -2247,6 +2247,14 @@ RelativePath=".\Src\Boot\Boot_ELF.h" > + + + + diff --git a/Source/Core/Core/Src/Boot/Boot.cpp b/Source/Core/Core/Src/Boot/Boot.cpp index 13ab8fe007..f9ec920058 100644 --- a/Source/Core/Core/Src/Boot/Boot.cpp +++ b/Source/Core/Core/Src/Boot/Boot.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: diff --git a/Source/Core/Core/Src/Boot/Boot.h b/Source/Core/Core/Src/Boot/Boot.h index 6388e802da..8461e5fe91 100644 --- a/Source/Core/Core/Src/Boot/Boot.h +++ b/Source/Core/Core/Src/Boot/Boot.h @@ -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); diff --git a/Source/Core/Core/Src/Boot/Boot_DOL.cpp b/Source/Core/Core/Src/Boot/Boot_DOL.cpp index c864c787c3..fc0345a9b9 100644 --- a/Source/Core/Core/Src/Boot/Boot_DOL.cpp +++ b/Source/Core/Core/Src/Boot/Boot_DOL.cpp @@ -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() diff --git a/Source/Core/Core/Src/Boot/Boot_DOL.h b/Source/Core/Core/Src/Boot/Boot_DOL.h index 730d65506c..cfebb13756 100644 --- a/Source/Core/Core/Src/Boot/Boot_DOL.h +++ b/Source/Core/Core/Src/Boot/Boot_DOL.h @@ -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 diff --git a/Source/Core/Core/Src/Boot/Boot_ELF.cpp b/Source/Core/Core/Src/Boot/Boot_ELF.cpp index 087c2dbe16..c560c660a2 100644 --- a/Source/Core/Core/Src/Boot/Boot_ELF.cpp +++ b/Source/Core/Core/Src/Boot/Boot_ELF.cpp @@ -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" diff --git a/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp new file mode 100644 index 0000000000..396367245d --- /dev/null +++ b/Source/Core/Core/Src/Boot/Boot_WiiWAD.cpp @@ -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 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 + +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 m_TileMetaContent; \ No newline at end of file diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index c205bfe79e..ed3136cccf 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -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()); diff --git a/Source/Core/Core/Src/CoreParameter.h b/Source/Core/Core/Src/CoreParameter.h index f71d13fed5..33138122fe 100644 --- a/Source/Core/Core/Src/CoreParameter.h +++ b/Source/Core/Core/Src/CoreParameter.h @@ -89,6 +89,7 @@ struct SCoreStartupParameter BOOT_ISO, BOOT_ELF, BOOT_DOL, + BOOT_WIIWAD, BOOT_BIOS }; EBootType m_BootType; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h index 3c13b6f05d..459e0b87d2 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.h @@ -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 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); diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp index 2653771c35..c21de268d4 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_LoadStore.cpp @@ -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); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp index 7ed0ed84df..f0b28f797e 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStore.cpp @@ -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; diff --git a/Source/Core/Core/Src/SConscript b/Source/Core/Core/Src/SConscript index d4538c4183..3c53bcd8d7 100644 --- a/Source/Core/Core/Src/SConscript +++ b/Source/Core/Core/Src/SConscript @@ -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", diff --git a/Source/Core/DolphinWX/Src/FrameTools.cpp b/Source/Core/DolphinWX/Src/FrameTools.cpp index 401349f43a..15745e00cd 100644 --- a/Source/Core/DolphinWX/Src/FrameTools.cpp +++ b/Source/Core/DolphinWX/Src/FrameTools.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 ),