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