Merge pull request #3127 from JosJuice/read-return
DiscIO: Improve error handling for reading integers
This commit is contained in:
commit
25a584626f
|
@ -60,17 +60,18 @@ void CBoot::Load_FST(bool _bIsWii)
|
|||
if (_bIsWii)
|
||||
shift = 2;
|
||||
|
||||
u32 fstOffset = volume.Read32(0x0424, _bIsWii) << shift;
|
||||
u32 fstSize = volume.Read32(0x0428, _bIsWii) << shift;
|
||||
u32 maxFstSize = volume.Read32(0x042c, _bIsWii) << shift;
|
||||
u32 fst_offset, fst_size, max_fst_size;
|
||||
volume.ReadSwapped(0x0424, &fst_offset, _bIsWii);
|
||||
volume.ReadSwapped(0x0428, &fst_size, _bIsWii);
|
||||
volume.ReadSwapped(0x042c, &max_fst_size, _bIsWii);
|
||||
|
||||
u32 arenaHigh = ROUND_DOWN(0x817FFFFF - maxFstSize, 0x20);
|
||||
Memory::Write_U32(arenaHigh, 0x00000034);
|
||||
u32 arena_high = ROUND_DOWN(0x817FFFFF - (max_fst_size << shift), 0x20);
|
||||
Memory::Write_U32(arena_high, 0x00000034);
|
||||
|
||||
// load FST
|
||||
DVDRead(fstOffset, arenaHigh, fstSize, _bIsWii);
|
||||
Memory::Write_U32(arenaHigh, 0x00000038);
|
||||
Memory::Write_U32(maxFstSize, 0x0000003c);
|
||||
DVDRead(fst_offset << shift, arena_high, fst_size << shift, _bIsWii);
|
||||
Memory::Write_U32(arena_high, 0x00000038);
|
||||
Memory::Write_U32(max_fst_size << shift, 0x0000003c);
|
||||
}
|
||||
|
||||
void CBoot::UpdateDebugger_MapLoaded()
|
||||
|
|
|
@ -90,15 +90,18 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
// 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.
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
u32 iAppLoaderOffset = 0x2440;
|
||||
u32 iAppLoaderEntry = volume.Read32(iAppLoaderOffset + 0x10, false);
|
||||
u32 iAppLoaderSize = volume.Read32(iAppLoaderOffset + 0x14, false) + volume.Read32(iAppLoaderOffset + 0x18, false);
|
||||
if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1) || skipAppLoader)
|
||||
const u32 apploader_offset = 0x2440;
|
||||
u32 apploader_entry, apploader_size, apploader_trailer;
|
||||
if (skipAppLoader ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, false) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x18, &apploader_trailer, false) ||
|
||||
apploader_entry == (u32)-1 || apploader_size + apploader_trailer == (u32)-1)
|
||||
{
|
||||
INFO_LOG(BOOT, "GC BS2: Not running apploader!");
|
||||
return false;
|
||||
}
|
||||
DVDRead(iAppLoaderOffset + 0x20, 0x01200000, iAppLoaderSize, false);
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size + apploader_trailer, false);
|
||||
|
||||
// Setup pointers like real BS2 does
|
||||
if (SConfig::GetInstance().bNTSC)
|
||||
|
@ -122,7 +125,7 @@ bool CBoot::EmulatedBS2_GC(bool skipAppLoader)
|
|||
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
|
||||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(iAppLoaderEntry);
|
||||
RunFunction(apploader_entry);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
|
@ -365,18 +368,19 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
|
||||
PowerPC::ppcState.gpr[1] = 0x816ffff0; // StackPointer
|
||||
|
||||
u32 iAppLoaderOffset = 0x2440; // 0x1c40;
|
||||
const u32 apploader_offset = 0x2440; // 0x1c40;
|
||||
|
||||
// Load Apploader to Memory
|
||||
const DiscIO::IVolume& volume = DVDInterface::GetVolume();
|
||||
u32 iAppLoaderEntry = volume.Read32(iAppLoaderOffset + 0x10, true);
|
||||
u32 iAppLoaderSize = volume.Read32(iAppLoaderOffset + 0x14, true);
|
||||
if ((iAppLoaderEntry == (u32)-1) || (iAppLoaderSize == (u32)-1))
|
||||
u32 apploader_entry, apploader_size;
|
||||
if (!volume.ReadSwapped(apploader_offset + 0x10, &apploader_entry, true) ||
|
||||
!volume.ReadSwapped(apploader_offset + 0x14, &apploader_size, true) ||
|
||||
apploader_entry == (u32)-1 || apploader_size == (u32)-1)
|
||||
{
|
||||
ERROR_LOG(BOOT, "Invalid apploader. Probably your image is corrupted.");
|
||||
return false;
|
||||
}
|
||||
DVDRead(iAppLoaderOffset + 0x20, 0x01200000, iAppLoaderSize, true);
|
||||
DVDRead(apploader_offset + 0x20, 0x01200000, apploader_size, true);
|
||||
|
||||
//call iAppLoaderEntry
|
||||
DEBUG_LOG(BOOT, "Call iAppLoaderEntry");
|
||||
|
@ -385,7 +389,7 @@ bool CBoot::EmulatedBS2_Wii()
|
|||
PowerPC::ppcState.gpr[3] = iAppLoaderFuncAddr + 0;
|
||||
PowerPC::ppcState.gpr[4] = iAppLoaderFuncAddr + 4;
|
||||
PowerPC::ppcState.gpr[5] = iAppLoaderFuncAddr + 8;
|
||||
RunFunction(iAppLoaderEntry);
|
||||
RunFunction(apploader_entry);
|
||||
u32 iAppLoaderInit = PowerPC::Read_U32(iAppLoaderFuncAddr + 0);
|
||||
u32 iAppLoaderMain = PowerPC::Read_U32(iAppLoaderFuncAddr + 4);
|
||||
u32 iAppLoaderClose = PowerPC::Read_U32(iAppLoaderFuncAddr + 8);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
#include <array>
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
namespace DiscIO
|
||||
|
@ -77,6 +78,25 @@ private:
|
|||
std::array<u64, CACHE_SIZE> m_cache_tags;
|
||||
};
|
||||
|
||||
class CBlobBigEndianReader
|
||||
{
|
||||
public:
|
||||
CBlobBigEndianReader(IBlobReader& reader) : m_reader(reader) {}
|
||||
|
||||
template <typename T>
|
||||
bool ReadSwapped(u64 offset, T* buffer) const
|
||||
{
|
||||
T temp;
|
||||
if (!m_reader.Read(offset, sizeof(T), reinterpret_cast<u8*>(&temp)))
|
||||
return false;
|
||||
*buffer = Common::FromBigEndian(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
private:
|
||||
IBlobReader& m_reader;
|
||||
};
|
||||
|
||||
// Factory function - examines the path to choose the right type of IBlobReader, and returns one.
|
||||
std::unique_ptr<IBlobReader> CreateBlobReader(const std::string& filename);
|
||||
|
||||
|
|
|
@ -74,8 +74,8 @@ static SPartitionGroup PartitionGroup[4];
|
|||
|
||||
void MarkAsUsed(u64 _Offset, u64 _Size);
|
||||
void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size);
|
||||
void ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt);
|
||||
void ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt);
|
||||
bool ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt);
|
||||
bool ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt);
|
||||
bool ParseDisc();
|
||||
bool ParsePartitionData(SPartition& _rPartition);
|
||||
|
||||
|
@ -192,16 +192,18 @@ void MarkAsUsedE(u64 _PartitionDataOffset, u64 _Offset, u64 _Size)
|
|||
}
|
||||
|
||||
// Helper functions for reading the BE volume
|
||||
void ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt)
|
||||
bool ReadFromVolume(u64 _Offset, u32& _Buffer, bool _Decrypt)
|
||||
{
|
||||
s_disc->Read(_Offset, sizeof(u32), (u8*)&_Buffer, _Decrypt);
|
||||
_Buffer = Common::swap32(_Buffer);
|
||||
return s_disc->ReadSwapped(_Offset, &_Buffer, _Decrypt);
|
||||
}
|
||||
void ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt)
|
||||
|
||||
bool ReadFromVolume(u64 _Offset, u64& _Buffer, bool _Decrypt)
|
||||
{
|
||||
s_disc->Read(_Offset, sizeof(u32), (u8*)&_Buffer, _Decrypt);
|
||||
_Buffer = Common::swap32((u32)_Buffer);
|
||||
_Buffer <<= 2;
|
||||
u32 temp_buffer;
|
||||
if (!s_disc->ReadSwapped(_Offset, &temp_buffer, _Decrypt))
|
||||
return false;
|
||||
_Buffer = static_cast<u64>(temp_buffer) << 2;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ParseDisc()
|
||||
|
@ -211,8 +213,9 @@ bool ParseDisc()
|
|||
|
||||
for (int x = 0; x < 4; x++)
|
||||
{
|
||||
ReadFromVolume(0x40000 + (x * 8) + 0, PartitionGroup[x].numPartitions, false);
|
||||
ReadFromVolume(0x40000 + (x * 8) + 4, PartitionGroup[x].PartitionsOffset, false);
|
||||
if (!ReadFromVolume(0x40000 + (x * 8) + 0, PartitionGroup[x].numPartitions, false) ||
|
||||
!ReadFromVolume(0x40000 + (x * 8) + 4, PartitionGroup[x].PartitionsOffset, false))
|
||||
return false;
|
||||
|
||||
// Read all partitions
|
||||
for (u32 i = 0; i < PartitionGroup[x].numPartitions; i++)
|
||||
|
@ -222,16 +225,16 @@ bool ParseDisc()
|
|||
Partition.GroupNumber = x;
|
||||
Partition.Number = i;
|
||||
|
||||
ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 0, Partition.Offset, false);
|
||||
ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 4, Partition.Type, false);
|
||||
|
||||
ReadFromVolume(Partition.Offset + 0x2a4, Partition.Header.TMDSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2a8, Partition.Header.TMDOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2ac, Partition.Header.CertChainSize, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b0, Partition.Header.CertChainOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b4, Partition.Header.H3Offset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2b8, Partition.Header.DataOffset, false);
|
||||
ReadFromVolume(Partition.Offset + 0x2bc, Partition.Header.DataSize, false);
|
||||
if (!ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 0, Partition.Offset, false) ||
|
||||
!ReadFromVolume(PartitionGroup[x].PartitionsOffset + (i * 8) + 4, Partition.Type, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2a4, Partition.Header.TMDSize, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2a8, Partition.Header.TMDOffset, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2ac, Partition.Header.CertChainSize, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2b0, Partition.Header.CertChainOffset, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2b4, Partition.Header.H3Offset, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2b8, Partition.Header.DataOffset, false) ||
|
||||
!ReadFromVolume(Partition.Offset + 0x2bc, Partition.Header.DataSize, false))
|
||||
return false;
|
||||
|
||||
PartitionGroup[x].PartitionsVec.push_back(Partition);
|
||||
}
|
||||
|
@ -286,8 +289,8 @@ bool ParsePartitionData(SPartition& partition)
|
|||
{
|
||||
// Mark things as used which are not in the filesystem
|
||||
// Header, Header Information, Apploader
|
||||
ReadFromVolume(0x2440 + 0x14, partition.Header.ApploaderSize, true);
|
||||
ReadFromVolume(0x2440 + 0x18, partition.Header.ApploaderTrailerSize, true);
|
||||
parsed_ok = parsed_ok && ReadFromVolume(0x2440 + 0x14, partition.Header.ApploaderSize, true);
|
||||
parsed_ok = parsed_ok && ReadFromVolume(0x2440 + 0x18, partition.Header.ApploaderTrailerSize, true);
|
||||
MarkAsUsedE(partition.Offset
|
||||
+ partition.Header.DataOffset
|
||||
, 0
|
||||
|
@ -296,16 +299,17 @@ bool ParsePartitionData(SPartition& partition)
|
|||
+ partition.Header.ApploaderTrailerSize);
|
||||
|
||||
// DOL
|
||||
ReadFromVolume(0x420, partition.Header.DOLOffset, true);
|
||||
partition.Header.DOLOffset = filesystem->GetBootDOLOffset();
|
||||
partition.Header.DOLSize = filesystem->GetBootDOLSize(partition.Header.DOLOffset);
|
||||
parsed_ok = parsed_ok && partition.Header.DOLOffset && partition.Header.DOLSize;
|
||||
MarkAsUsedE(partition.Offset
|
||||
+ partition.Header.DataOffset
|
||||
, partition.Header.DOLOffset
|
||||
, partition.Header.DOLSize);
|
||||
|
||||
// FST
|
||||
ReadFromVolume(0x424, partition.Header.FSTOffset, true);
|
||||
ReadFromVolume(0x428, partition.Header.FSTSize, true);
|
||||
parsed_ok = parsed_ok && ReadFromVolume(0x424, partition.Header.FSTOffset, true);
|
||||
parsed_ok = parsed_ok && ReadFromVolume(0x428, partition.Header.FSTSize, true);
|
||||
MarkAsUsedE(partition.Offset
|
||||
+ partition.Header.DataOffset
|
||||
, partition.Header.FSTOffset
|
||||
|
|
|
@ -127,20 +127,24 @@ bool CFileSystemGCWii::ExportFile(const std::string& _rFullPath, const std::stri
|
|||
|
||||
bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const
|
||||
{
|
||||
u32 AppSize = m_rVolume->Read32(0x2440 + 0x14, m_Wii); // apploader size
|
||||
AppSize += m_rVolume->Read32(0x2440 + 0x18, m_Wii); // + trailer size
|
||||
AppSize += 0x20; // + header size
|
||||
DEBUG_LOG(DISCIO,"AppSize -> %x", AppSize);
|
||||
u32 apploader_size;
|
||||
u32 trailer_size;
|
||||
const u32 header_size = 0x20;
|
||||
if (!m_rVolume->ReadSwapped(0x2440 + 0x14, &apploader_size, m_Wii) ||
|
||||
!m_rVolume->ReadSwapped(0x2440 + 0x18, &trailer_size, m_Wii))
|
||||
return false;
|
||||
apploader_size += trailer_size + header_size;
|
||||
DEBUG_LOG(DISCIO, "Apploader size -> %x", apploader_size);
|
||||
|
||||
std::vector<u8> buffer(AppSize);
|
||||
if (m_rVolume->Read(0x2440, AppSize, &buffer[0], m_Wii))
|
||||
std::vector<u8> buffer(apploader_size);
|
||||
if (m_rVolume->Read(0x2440, apploader_size, buffer.data(), m_Wii))
|
||||
{
|
||||
std::string exportName(_rExportFolder + "/apploader.img");
|
||||
|
||||
File::IOFile AppFile(exportName, "wb");
|
||||
if (AppFile)
|
||||
{
|
||||
AppFile.WriteBytes(&buffer[0], AppSize);
|
||||
AppFile.WriteBytes(buffer.data(), apploader_size);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
@ -148,13 +152,20 @@ bool CFileSystemGCWii::ExportApploader(const std::string& _rExportFolder) const
|
|||
return false;
|
||||
}
|
||||
|
||||
u32 CFileSystemGCWii::GetBootDOLSize() const
|
||||
u64 CFileSystemGCWii::GetBootDOLOffset() const
|
||||
{
|
||||
return GetBootDOLSize((u64)m_rVolume->Read32(0x420, m_Wii) << GetOffsetShift());
|
||||
u32 offset = 0;
|
||||
m_rVolume->ReadSwapped(0x420, &offset, m_Wii);
|
||||
return static_cast<u64>(offset) << GetOffsetShift();
|
||||
}
|
||||
|
||||
u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const
|
||||
{
|
||||
// The dol_offset value is usually obtained by calling GetBootDOLOffset.
|
||||
// If GetBootDOLOffset fails by returning 0, GetBootDOLSize should also fail.
|
||||
if (dol_offset == 0)
|
||||
return 0;
|
||||
|
||||
u32 dol_size = 0;
|
||||
u32 offset = 0;
|
||||
u32 size = 0;
|
||||
|
@ -162,16 +173,18 @@ u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const
|
|||
// Iterate through the 7 code segments
|
||||
for (u8 i = 0; i < 7; i++)
|
||||
{
|
||||
offset = m_rVolume->Read32(dol_offset + 0x00 + i * 4, m_Wii);
|
||||
size = m_rVolume->Read32(dol_offset + 0x90 + i * 4, m_Wii);
|
||||
if (!m_rVolume->ReadSwapped(dol_offset + 0x00 + i * 4, &offset, m_Wii) ||
|
||||
!m_rVolume->ReadSwapped(dol_offset + 0x90 + i * 4, &size, m_Wii))
|
||||
return 0;
|
||||
dol_size = std::max(offset + size, dol_size);
|
||||
}
|
||||
|
||||
// Iterate through the 11 data segments
|
||||
for (u8 i = 0; i < 11; i++)
|
||||
{
|
||||
offset = m_rVolume->Read32(dol_offset + 0x1c + i * 4, m_Wii);
|
||||
size = m_rVolume->Read32(dol_offset + 0xac + i * 4, m_Wii);
|
||||
if (!m_rVolume->ReadSwapped(dol_offset + 0x1c + i * 4, &offset, m_Wii) ||
|
||||
!m_rVolume->ReadSwapped(dol_offset + 0xac + i * 4, &size, m_Wii))
|
||||
return 0;
|
||||
dol_size = std::max(offset + size, dol_size);
|
||||
}
|
||||
|
||||
|
@ -180,8 +193,11 @@ u32 CFileSystemGCWii::GetBootDOLSize(u64 dol_offset) const
|
|||
|
||||
bool CFileSystemGCWii::ExportDOL(const std::string& _rExportFolder) const
|
||||
{
|
||||
u32 DolOffset = m_rVolume->Read32(0x420, m_Wii) << GetOffsetShift();
|
||||
u32 DolSize = GetBootDOLSize();
|
||||
u64 DolOffset = GetBootDOLOffset();
|
||||
u32 DolSize = GetBootDOLSize(DolOffset);
|
||||
|
||||
if (DolOffset == 0 || DolSize == 0)
|
||||
return false;
|
||||
|
||||
std::vector<u8> buffer(DolSize);
|
||||
if (m_rVolume->Read(DolOffset, DolSize, &buffer[0], m_Wii))
|
||||
|
@ -234,12 +250,13 @@ const SFileInfo* CFileSystemGCWii::FindFileInfo(const std::string& _rFullPath)
|
|||
|
||||
bool CFileSystemGCWii::DetectFileSystem()
|
||||
{
|
||||
if (m_rVolume->Read32(0x18, false) == 0x5D1C9EA3)
|
||||
u32 magic_bytes;
|
||||
if (m_rVolume->ReadSwapped(0x18, &magic_bytes, false) && magic_bytes == 0x5D1C9EA3)
|
||||
{
|
||||
m_Wii = true;
|
||||
return true;
|
||||
}
|
||||
else if (m_rVolume->Read32(0x1c, false) == 0xC2339F3D)
|
||||
else if (m_rVolume->ReadSwapped(0x1c, &magic_bytes, false) && magic_bytes == 0xC2339F3D)
|
||||
{
|
||||
m_Wii = false;
|
||||
return true;
|
||||
|
@ -254,26 +271,26 @@ void CFileSystemGCWii::InitFileSystem()
|
|||
u32 const shift = GetOffsetShift();
|
||||
|
||||
// read the whole FST
|
||||
u64 FSTOffset = static_cast<u64>(m_rVolume->Read32(0x424, m_Wii)) << shift;
|
||||
// u32 FSTSize = Read32(0x428);
|
||||
// u32 FSTMaxSize = Read32(0x42C);
|
||||
|
||||
u32 fst_offset_unshifted;
|
||||
if (!m_rVolume->ReadSwapped(0x424, &fst_offset_unshifted, m_Wii))
|
||||
return;
|
||||
u64 FSTOffset = static_cast<u64>(fst_offset_unshifted) << shift;
|
||||
|
||||
// read all fileinfos
|
||||
SFileInfo Root
|
||||
{
|
||||
m_rVolume->Read32(FSTOffset + 0x0, m_Wii),
|
||||
static_cast<u64>(FSTOffset + 0x4) << shift,
|
||||
m_rVolume->Read32(FSTOffset + 0x8, m_Wii)
|
||||
};
|
||||
u32 name_offset, offset, size;
|
||||
if (!m_rVolume->ReadSwapped(FSTOffset + 0x0, &name_offset, m_Wii) ||
|
||||
!m_rVolume->ReadSwapped(FSTOffset + 0x4, &offset, m_Wii) ||
|
||||
!m_rVolume->ReadSwapped(FSTOffset + 0x8, &size, m_Wii))
|
||||
return;
|
||||
SFileInfo root = { name_offset, static_cast<u64>(offset) << shift, size };
|
||||
|
||||
if (!Root.IsDirectory())
|
||||
if (!root.IsDirectory())
|
||||
return;
|
||||
|
||||
// 12 bytes (the size of a file entry) times 10 * 1024 * 1024 is 120 MiB,
|
||||
// more than total RAM in a Wii. No file system should use anywhere near that much.
|
||||
static const u32 ARBITRARY_FILE_SYSTEM_SIZE_LIMIT = 10 * 1024 * 1024;
|
||||
if (Root.m_FileSize > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT)
|
||||
if (root.m_FileSize > ARBITRARY_FILE_SYSTEM_SIZE_LIMIT)
|
||||
{
|
||||
// Without this check, Dolphin can crash by trying to allocate too much
|
||||
// memory when loading the file systems of certain malformed disc images.
|
||||
|
@ -286,14 +303,17 @@ void CFileSystemGCWii::InitFileSystem()
|
|||
PanicAlert("Wtf?");
|
||||
u64 NameTableOffset = FSTOffset;
|
||||
|
||||
m_FileInfoVector.reserve((size_t)Root.m_FileSize);
|
||||
for (u32 i = 0; i < Root.m_FileSize; i++)
|
||||
m_FileInfoVector.reserve((size_t)root.m_FileSize);
|
||||
for (u32 i = 0; i < root.m_FileSize; i++)
|
||||
{
|
||||
u64 const read_offset = FSTOffset + (i * 0xC);
|
||||
u64 const name_offset = m_rVolume->Read32(read_offset + 0x0, m_Wii);
|
||||
u64 const offset = static_cast<u64>(m_rVolume->Read32(read_offset + 0x4, m_Wii)) << shift;
|
||||
u64 const size = m_rVolume->Read32(read_offset + 0x8, m_Wii);
|
||||
m_FileInfoVector.emplace_back(name_offset, offset, size);
|
||||
const u64 read_offset = FSTOffset + (i * 0xC);
|
||||
name_offset = 0;
|
||||
m_rVolume->ReadSwapped(read_offset + 0x0, &name_offset, m_Wii);
|
||||
offset = 0;
|
||||
m_rVolume->ReadSwapped(read_offset + 0x4, &offset, m_Wii);
|
||||
size = 0;
|
||||
m_rVolume->ReadSwapped(read_offset + 0x8, &size, m_Wii);
|
||||
m_FileInfoVector.emplace_back(name_offset, static_cast<u64>(offset) << shift, size);
|
||||
NameTableOffset += 0xC;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ public:
|
|||
bool ExportFile(const std::string& _rFullPath, const std::string&_rExportFilename) override;
|
||||
bool ExportApploader(const std::string& _rExportFolder) const override;
|
||||
bool ExportDOL(const std::string& _rExportFolder) const override;
|
||||
u32 GetBootDOLSize() const override;
|
||||
u64 GetBootDOLOffset() const override;
|
||||
u32 GetBootDOLSize(u64 dol_offset) const override;
|
||||
|
||||
private:
|
||||
|
|
|
@ -49,7 +49,7 @@ public:
|
|||
virtual bool ExportApploader(const std::string& _rExportFolder) const = 0;
|
||||
virtual bool ExportDOL(const std::string& _rExportFolder) const = 0;
|
||||
virtual const std::string GetFileName(u64 _Address) = 0;
|
||||
virtual u32 GetBootDOLSize() const = 0;
|
||||
virtual u64 GetBootDOLOffset() const = 0;
|
||||
virtual u32 GetBootDOLSize(u64 dol_offset) const = 0;
|
||||
|
||||
protected:
|
||||
|
|
|
@ -71,11 +71,14 @@ public:
|
|||
|
||||
// decrypt parameter must be false if not reading a Wii disc
|
||||
virtual bool Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const = 0;
|
||||
virtual u32 Read32(u64 _Offset, bool decrypt) const
|
||||
template <typename T>
|
||||
bool ReadSwapped(u64 offset, T* buffer, bool decrypt) const
|
||||
{
|
||||
u32 temp;
|
||||
Read(_Offset, sizeof(u32), (u8*)&temp, decrypt);
|
||||
return Common::swap32(temp);
|
||||
T temp;
|
||||
if (!Read(offset, sizeof(T), reinterpret_cast<u8*>(&temp), decrypt))
|
||||
return false;
|
||||
*buffer = Common::FromBigEndian(temp);
|
||||
return true;
|
||||
}
|
||||
|
||||
virtual bool GetTitleID(u64*) const { return false; }
|
||||
|
|
|
@ -34,33 +34,6 @@ enum EDiscType
|
|||
DISC_TYPE_WAD
|
||||
};
|
||||
|
||||
class CBlobBigEndianReader
|
||||
{
|
||||
public:
|
||||
CBlobBigEndianReader(IBlobReader& _rReader) : m_rReader(_rReader) {}
|
||||
|
||||
u32 Read32(u64 _Offset)
|
||||
{
|
||||
u32 Temp;
|
||||
m_rReader.Read(_Offset, 4, (u8*)&Temp);
|
||||
return Common::swap32(Temp);
|
||||
}
|
||||
u16 Read16(u64 _Offset)
|
||||
{
|
||||
u16 Temp;
|
||||
m_rReader.Read(_Offset, 2, (u8*)&Temp);
|
||||
return Common::swap16(Temp);
|
||||
}
|
||||
u8 Read8(u64 _Offset)
|
||||
{
|
||||
u8 Temp;
|
||||
m_rReader.Read(_Offset, 1, &Temp);
|
||||
return Temp;
|
||||
}
|
||||
private:
|
||||
IBlobReader& m_rReader;
|
||||
};
|
||||
|
||||
static const unsigned char s_master_key[16] = {
|
||||
0xeb,0xe4,0x2a,0x22,0x5e,0x85,0x93,0xe4,
|
||||
0x48,0xd9,0xc5,0x45,0x73,0x81,0xaa,0xf7
|
||||
|
@ -114,8 +87,6 @@ std::unique_ptr<IVolume> CreateVolumeFromDirectory(const std::string& directory,
|
|||
|
||||
void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey)
|
||||
{
|
||||
CBlobBigEndianReader Reader(_rReader);
|
||||
|
||||
u8 SubKey[16];
|
||||
_rReader.Read(offset + 0x1bf, 16, SubKey);
|
||||
|
||||
|
@ -123,16 +94,17 @@ void VolumeKeyForPartition(IBlobReader& _rReader, u64 offset, u8* VolumeKey)
|
|||
memset(IV, 0, 16);
|
||||
_rReader.Read(offset + 0x44c, 8, IV);
|
||||
|
||||
bool usingKoreanKey = false;
|
||||
// Issue: 6813
|
||||
// Magic value is at partition's offset + 0x1f1 (1byte)
|
||||
// If encrypted with the Korean key, the magic value would be 1
|
||||
// Otherwise it is zero
|
||||
if (Reader.Read8(0x3) == 'K' && Reader.Read8(offset + 0x1f1) == 1)
|
||||
usingKoreanKey = true;
|
||||
u8 using_korean_key = 0;
|
||||
_rReader.Read(offset + 0x1f1, sizeof(u8), &using_korean_key);
|
||||
u8 region = 0;
|
||||
_rReader.Read(0x3, sizeof(u8), ®ion);
|
||||
|
||||
mbedtls_aes_context AES_ctx;
|
||||
mbedtls_aes_setkey_dec(&AES_ctx, (usingKoreanKey ? s_master_key_korean : s_master_key), 128);
|
||||
mbedtls_aes_setkey_dec(&AES_ctx, (using_korean_key == 1 && region == 'K' ? s_master_key_korean : s_master_key), 128);
|
||||
|
||||
mbedtls_aes_crypt_cbc(&AES_ctx, MBEDTLS_AES_DECRYPT, 16, IV, SubKey, VolumeKey);
|
||||
}
|
||||
|
@ -141,15 +113,23 @@ static std::unique_ptr<IVolume> CreateVolumeFromCryptedWiiImage(std::unique_ptr<
|
|||
{
|
||||
CBlobBigEndianReader big_endian_reader(*reader);
|
||||
|
||||
u32 numPartitions = big_endian_reader.Read32(0x40000 + (partition_group * 8));
|
||||
u64 PartitionsOffset = (u64)big_endian_reader.Read32(0x40000 + (partition_group * 8) + 4) << 2;
|
||||
u32 num_partitions;
|
||||
if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8), &num_partitions))
|
||||
return nullptr;
|
||||
|
||||
// Check if we're looking for a valid partition
|
||||
if ((int)volume_number != -1 && volume_number > numPartitions)
|
||||
if ((int)volume_number != -1 && volume_number > num_partitions)
|
||||
return nullptr;
|
||||
|
||||
u32 partitions_offset_unshifted;
|
||||
if (!big_endian_reader.ReadSwapped(0x40000 + (partition_group * 8) + 4, &partitions_offset_unshifted))
|
||||
return nullptr;
|
||||
u64 partitions_offset = (u64)partitions_offset_unshifted << 2;
|
||||
|
||||
struct SPartition
|
||||
{
|
||||
SPartition(u64 offset, u32 type) : offset(offset), type(type) {}
|
||||
|
||||
u64 offset;
|
||||
u32 type;
|
||||
};
|
||||
|
@ -165,12 +145,14 @@ static std::unique_ptr<IVolume> CreateVolumeFromCryptedWiiImage(std::unique_ptr<
|
|||
// Read all partitions
|
||||
for (SPartitionGroup& group : partition_groups)
|
||||
{
|
||||
for (u32 i = 0; i < numPartitions; i++)
|
||||
for (u32 i = 0; i < num_partitions; i++)
|
||||
{
|
||||
SPartition partition;
|
||||
partition.offset = ((u64)big_endian_reader.Read32(PartitionsOffset + (i * 8) + 0)) << 2;
|
||||
partition.type = big_endian_reader.Read32(PartitionsOffset + (i * 8) + 4);
|
||||
group.partitions.push_back(partition);
|
||||
u32 partition_offset, partition_type;
|
||||
if (big_endian_reader.ReadSwapped(partitions_offset + (i * 8) + 0, &partition_offset) &&
|
||||
big_endian_reader.ReadSwapped(partitions_offset + (i * 8) + 4, &partition_type))
|
||||
{
|
||||
group.partitions.emplace_back((u64)partition_offset << 2, partition_type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -195,12 +177,12 @@ static std::unique_ptr<IVolume> CreateVolumeFromCryptedWiiImage(std::unique_ptr<
|
|||
EDiscType GetDiscType(IBlobReader& _rReader)
|
||||
{
|
||||
CBlobBigEndianReader Reader(_rReader);
|
||||
u32 WiiMagic = Reader.Read32(0x18);
|
||||
u32 WiiContainerMagic = Reader.Read32(0x60);
|
||||
u32 WADMagic = Reader.Read32(0x02);
|
||||
u32 GCMagic = Reader.Read32(0x1C);
|
||||
|
||||
// Check for Wii
|
||||
u32 WiiMagic = 0;
|
||||
Reader.ReadSwapped(0x18, &WiiMagic);
|
||||
u32 WiiContainerMagic = 0;
|
||||
Reader.ReadSwapped(0x60, &WiiContainerMagic);
|
||||
if (WiiMagic == 0x5D1C9EA3 && WiiContainerMagic != 0)
|
||||
return DISC_TYPE_WII;
|
||||
if (WiiMagic == 0x5D1C9EA3 && WiiContainerMagic == 0)
|
||||
|
@ -208,10 +190,14 @@ EDiscType GetDiscType(IBlobReader& _rReader)
|
|||
|
||||
// Check for WAD
|
||||
// 0x206962 for boot2 wads
|
||||
u32 WADMagic = 0;
|
||||
Reader.ReadSwapped(0x02, &WADMagic);
|
||||
if (WADMagic == 0x00204973 || WADMagic == 0x00206962)
|
||||
return DISC_TYPE_WAD;
|
||||
|
||||
// Check for GC
|
||||
u32 GCMagic = 0;
|
||||
Reader.ReadSwapped(0x1C, &GCMagic);
|
||||
if (GCMagic == 0xC2339F3D)
|
||||
return DISC_TYPE_GC;
|
||||
|
||||
|
|
|
@ -18,22 +18,6 @@
|
|||
namespace DiscIO
|
||||
{
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
WiiWAD::WiiWAD(const std::string& name)
|
||||
{
|
||||
std::unique_ptr<IBlobReader> reader(DiscIO::CreateBlobReader(name));
|
||||
|
@ -80,27 +64,17 @@ bool WiiWAD::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))
|
||||
if (!IsWiiWAD(ReaderBig))
|
||||
return false;
|
||||
|
||||
m_CertificateChainSize = ReaderBig.Read32(0x8);
|
||||
u32 Reserved = ReaderBig.Read32(0xC);
|
||||
m_TicketSize = ReaderBig.Read32(0x10);
|
||||
m_TMDSize = ReaderBig.Read32(0x14);
|
||||
m_DataAppSize = ReaderBig.Read32(0x18);
|
||||
m_FooterSize = ReaderBig.Read32(0x1C);
|
||||
u32 Reserved;
|
||||
if (!ReaderBig.ReadSwapped(0x8, &m_CertificateChainSize) ||
|
||||
!ReaderBig.ReadSwapped(0xC, &Reserved) ||
|
||||
!ReaderBig.ReadSwapped(0x10, &m_TicketSize) ||
|
||||
!ReaderBig.ReadSwapped(0x14, &m_TMDSize) ||
|
||||
!ReaderBig.ReadSwapped(0x18, &m_DataAppSize) ||
|
||||
!ReaderBig.ReadSwapped(0x1C, &m_FooterSize))
|
||||
return false;
|
||||
|
||||
if (MAX_LOGLEVEL >= LogTypes::LOG_LEVELS::LDEBUG)
|
||||
_dbg_assert_msg_(BOOT, Reserved==0x00, "WiiWAD: Reserved must be 0x00");
|
||||
|
@ -115,5 +89,13 @@ bool WiiWAD::ParseWAD(DiscIO::IBlobReader& _rReader)
|
|||
return true;
|
||||
}
|
||||
|
||||
} // namespace end
|
||||
bool WiiWAD::IsWiiWAD(const DiscIO::CBlobBigEndianReader& reader)
|
||||
{
|
||||
u32 header_size = 0;
|
||||
u32 header_type = 0;
|
||||
reader.ReadSwapped(0x0, &header_size);
|
||||
reader.ReadSwapped(0x4, &header_type);
|
||||
return header_size == 0x20 && (header_type == 0x49730000 || header_type == 0x69620000);
|
||||
}
|
||||
|
||||
} // namespace end
|
||||
|
|
|
@ -12,6 +12,7 @@ namespace DiscIO
|
|||
{
|
||||
|
||||
class IBlobReader;
|
||||
class CBlobBigEndianReader;
|
||||
|
||||
class WiiWAD
|
||||
{
|
||||
|
@ -52,6 +53,7 @@ private:
|
|||
|
||||
u8* CreateWADEntry(DiscIO::IBlobReader& _rReader, u32 _Size, u64 _Offset);
|
||||
bool ParseWAD(DiscIO::IBlobReader& _rReader);
|
||||
static bool IsWiiWAD(const DiscIO::CBlobBigEndianReader& reader);
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue