Add an early version of WIABlobReader
It can currently only read the first 0x80 bytes of a disc image, which is enough for identifying it but not for doing anything else.
This commit is contained in:
parent
0bc7dcd172
commit
8da5d0c4fe
|
@ -22,7 +22,7 @@ import java.util.List;
|
|||
public final class FileBrowserHelper
|
||||
{
|
||||
public static final HashSet<String> GAME_EXTENSIONS = new HashSet<>(Arrays.asList(
|
||||
"gcm", "tgc", "iso", "ciso", "gcz", "wbfs", "wad", "dol", "elf", "dff"));
|
||||
"gcm", "tgc", "iso", "ciso", "gcz", "wbfs", "wia", "wad", "dol", "elf", "dff"));
|
||||
|
||||
public static final HashSet<String> RAW_EXTENSION = new HashSet<>(Collections.singletonList(
|
||||
"raw"));
|
||||
|
|
|
@ -159,7 +159,7 @@ BootParameters::GenerateFromFile(std::vector<std::string> paths,
|
|||
paths.clear();
|
||||
|
||||
static const std::unordered_set<std::string> disc_image_extensions = {
|
||||
{".gcm", ".iso", ".tgc", ".wbfs", ".ciso", ".gcz", ".dol", ".elf"}};
|
||||
{".gcm", ".iso", ".tgc", ".wbfs", ".ciso", ".gcz", ".wia", ".dol", ".elf"}};
|
||||
if (disc_image_extensions.find(extension) != disc_image_extensions.end() || is_drive)
|
||||
{
|
||||
std::unique_ptr<DiscIO::VolumeDisc> disc = DiscIO::CreateDisc(path);
|
||||
|
|
|
@ -20,6 +20,7 @@
|
|||
#include "DiscIO/DriveBlob.h"
|
||||
#include "DiscIO/FileBlob.h"
|
||||
#include "DiscIO/TGCBlob.h"
|
||||
#include "DiscIO/WIABlob.h"
|
||||
#include "DiscIO/WbfsBlob.h"
|
||||
|
||||
namespace DiscIO
|
||||
|
@ -205,6 +206,8 @@ std::unique_ptr<BlobReader> CreateBlobReader(const std::string& filename)
|
|||
return TGCFileReader::Create(std::move(file));
|
||||
case WBFS_MAGIC:
|
||||
return WbfsFileReader::Create(std::move(file), filename);
|
||||
case WIA_MAGIC:
|
||||
return WIAFileReader::Create(std::move(file), filename);
|
||||
default:
|
||||
if (auto directory_blob = DirectoryBlobReader::Create(filename))
|
||||
return std::move(directory_blob);
|
||||
|
|
|
@ -34,7 +34,8 @@ enum class BlobType
|
|||
GCZ,
|
||||
CISO,
|
||||
WBFS,
|
||||
TGC
|
||||
TGC,
|
||||
WIA
|
||||
};
|
||||
|
||||
class BlobReader
|
||||
|
|
|
@ -42,6 +42,8 @@ add_library(discio
|
|||
VolumeWii.h
|
||||
WbfsBlob.cpp
|
||||
WbfsBlob.h
|
||||
WIABlob.cpp
|
||||
WIABlob.h
|
||||
WiiEncryptionCache.cpp
|
||||
WiiEncryptionCache.h
|
||||
WiiSaveBanner.cpp
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
<ClCompile Include="VolumeWad.cpp" />
|
||||
<ClCompile Include="VolumeWii.cpp" />
|
||||
<ClCompile Include="WbfsBlob.cpp" />
|
||||
<ClCompile Include="WIABlob.cpp" />
|
||||
<ClCompile Include="WiiEncryptionCache.cpp" />
|
||||
<ClCompile Include="WiiSaveBanner.cpp" />
|
||||
</ItemGroup>
|
||||
|
@ -91,6 +92,7 @@
|
|||
<ClInclude Include="VolumeWad.h" />
|
||||
<ClInclude Include="VolumeWii.h" />
|
||||
<ClInclude Include="WbfsBlob.h" />
|
||||
<ClInclude Include="WIABlob.h" />
|
||||
<ClInclude Include="WiiEncryptionCache.h" />
|
||||
<ClInclude Include="WiiSaveBanner.h" />
|
||||
</ItemGroup>
|
||||
|
|
|
@ -90,6 +90,9 @@
|
|||
<ClCompile Include="ScrubbedBlob.cpp">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="WIABlob.cpp">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="DiscScrubber.h">
|
||||
|
@ -164,6 +167,9 @@
|
|||
<ClInclude Include="MultithreadedCompressor.h">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="WIABlob.h">
|
||||
<Filter>Volume\Blob</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="CMakeLists.txt" />
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include "DiscIO/WIABlob.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/File.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Swap.h"
|
||||
|
||||
#include "DiscIO/VolumeWii.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
WIAFileReader::WIAFileReader(File::IOFile file, const std::string& path) : m_file(std::move(file))
|
||||
{
|
||||
m_valid = Initialize(path);
|
||||
}
|
||||
|
||||
WIAFileReader::~WIAFileReader() = default;
|
||||
|
||||
bool WIAFileReader::Initialize(const std::string& path)
|
||||
{
|
||||
if (!m_file.Seek(0, SEEK_SET) || !m_file.ReadArray(&m_header_1, 1))
|
||||
return false;
|
||||
|
||||
if (m_header_1.magic != WIA_MAGIC)
|
||||
return false;
|
||||
|
||||
const u32 version = Common::swap32(m_header_1.version);
|
||||
const u32 version_compatible = Common::swap32(m_header_1.version_compatible);
|
||||
if (WIA_VERSION < version_compatible || WIA_VERSION_READ_COMPATIBLE > version)
|
||||
{
|
||||
ERROR_LOG(DISCIO, "Unsupported WIA version %s in %s", VersionToString(version).c_str(),
|
||||
path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Common::swap64(m_header_1.wia_file_size) != m_file.GetSize())
|
||||
{
|
||||
ERROR_LOG(DISCIO, "File size is incorrect for %s", path.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (Common::swap32(m_header_1.header_2_size) < sizeof(WIAHeader2))
|
||||
return false;
|
||||
|
||||
if (!m_file.ReadArray(&m_header_2, 1))
|
||||
return false;
|
||||
|
||||
const u32 chunk_size = Common::swap32(m_header_2.chunk_size);
|
||||
if (chunk_size % VolumeWii::GROUP_TOTAL_SIZE != 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
std::unique_ptr<WIAFileReader> WIAFileReader::Create(File::IOFile file, const std::string& path)
|
||||
{
|
||||
std::unique_ptr<WIAFileReader> blob(new WIAFileReader(std::move(file), path));
|
||||
return blob->m_valid ? std::move(blob) : nullptr;
|
||||
}
|
||||
|
||||
bool WIAFileReader::Read(u64 offset, u64 size, u8* out_ptr)
|
||||
{
|
||||
if (offset + size <= sizeof(WIAHeader2::disc_header))
|
||||
{
|
||||
std::memcpy(out_ptr, m_header_2.disc_header.data() + offset, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
// Not implemented
|
||||
return false;
|
||||
}
|
||||
|
||||
std::string WIAFileReader::VersionToString(u32 version)
|
||||
{
|
||||
const u8 a = version >> 24;
|
||||
const u8 b = (version >> 16) & 0xff;
|
||||
const u8 c = (version >> 8) & 0xff;
|
||||
const u8 d = version & 0xff;
|
||||
|
||||
if (d == 0 || d == 0xff)
|
||||
return StringFromFormat("%u.%02x.%02x", a, b, c);
|
||||
else
|
||||
return StringFromFormat("%u.%02x.%02x.beta%u", a, b, c, d);
|
||||
}
|
||||
} // namespace DiscIO
|
|
@ -0,0 +1,102 @@
|
|||
// Copyright 2018 Dolphin Emulator Project
|
||||
// Licensed under GPLv2+
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/File.h"
|
||||
#include "Common/Swap.h"
|
||||
#include "DiscIO/Blob.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
constexpr u32 WIA_MAGIC = 0x01414957; // "WIA\x1" (byteswapped to little endian)
|
||||
|
||||
class WIAFileReader : public BlobReader
|
||||
{
|
||||
public:
|
||||
~WIAFileReader();
|
||||
|
||||
static std::unique_ptr<WIAFileReader> Create(File::IOFile file, const std::string& path);
|
||||
|
||||
BlobType GetBlobType() const override { return BlobType::WIA; }
|
||||
|
||||
u64 GetRawSize() const override { return Common::swap64(m_header_1.wia_file_size); }
|
||||
u64 GetDataSize() const override { return Common::swap64(m_header_1.iso_file_size); }
|
||||
bool IsDataSizeAccurate() const override { return true; }
|
||||
|
||||
u64 GetBlockSize() const override { return Common::swap32(m_header_2.chunk_size); }
|
||||
bool HasFastRandomAccessInBlock() const override { return false; }
|
||||
|
||||
bool Read(u64 offset, u64 size, u8* out_ptr) override;
|
||||
|
||||
private:
|
||||
explicit WIAFileReader(File::IOFile file, const std::string& path);
|
||||
bool Initialize(const std::string& path);
|
||||
|
||||
static std::string VersionToString(u32 version);
|
||||
|
||||
using SHA1 = std::array<u8, 20>;
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct WIAHeader1
|
||||
{
|
||||
u32 magic;
|
||||
u32 version;
|
||||
u32 version_compatible;
|
||||
u32 header_2_size;
|
||||
SHA1 header_2_hash;
|
||||
u64 iso_file_size;
|
||||
u64 wia_file_size;
|
||||
SHA1 header_1_hash;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(WIAHeader1) == 0x48, "Wrong size for WIA header 1");
|
||||
|
||||
#pragma pack(push, 1)
|
||||
struct WIAHeader2
|
||||
{
|
||||
u32 disc_type;
|
||||
u32 compression_type;
|
||||
u32 compression_level; // Informative only
|
||||
u32 chunk_size;
|
||||
|
||||
std::array<u8, 0x80> disc_header;
|
||||
|
||||
u32 number_of_partitions_entries;
|
||||
u32 partition_entry_size;
|
||||
u64 partition_entries_offset;
|
||||
SHA1 partition_entries_hash;
|
||||
|
||||
u32 number_of_raw_data_entries;
|
||||
u64 raw_data_entries_offset;
|
||||
u32 raw_data_entries_size;
|
||||
|
||||
u32 number_of_group_entries;
|
||||
u64 group_entries_offset;
|
||||
u32 group_entries_size;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
static_assert(sizeof(WIAHeader2) == 0xd4, "Wrong size for WIA header 2");
|
||||
|
||||
bool m_valid;
|
||||
|
||||
File::IOFile m_file;
|
||||
|
||||
WIAHeader1 m_header_1;
|
||||
WIAHeader2 m_header_2;
|
||||
|
||||
static constexpr u32 WIA_VERSION = 0x01000000;
|
||||
static constexpr u32 WIA_VERSION_WRITE_COMPATIBLE = 0x01000000;
|
||||
static constexpr u32 WIA_VERSION_READ_COMPATIBLE = 0x00080000;
|
||||
|
||||
// Perhaps we could set WIA_VERSION_WRITE_COMPATIBLE to 0.9, but WIA version 0.9 was never in
|
||||
// any official release of wit, and interim versions (either source or binaries) are hard to find.
|
||||
// Since we've been unable to check if we're write compatible with 0.9, we set it 1.0 to be safe.
|
||||
};
|
||||
|
||||
} // namespace DiscIO
|
|
@ -24,8 +24,8 @@ static const QStringList game_filters{
|
|||
QStringLiteral("*.[gG][cC][mM]"), QStringLiteral("*.[iI][sS][oO]"),
|
||||
QStringLiteral("*.[tT][gG][cC]"), QStringLiteral("*.[cC][iI][sS][oO]"),
|
||||
QStringLiteral("*.[gG][cC][zZ]"), QStringLiteral("*.[wW][bB][fF][sS]"),
|
||||
QStringLiteral("*.[wW][aA][dD]"), QStringLiteral("*.[eE][lL][fF]"),
|
||||
QStringLiteral("*.[dD][oO][lL]")};
|
||||
QStringLiteral("*.[wW][iI][aA]"), QStringLiteral("*.[wW][aA][dD]"),
|
||||
QStringLiteral("*.[eE][lL][fF]"), QStringLiteral("*.[dD][oO][lL]")};
|
||||
|
||||
GameTracker::GameTracker(QObject* parent) : QFileSystemWatcher(parent)
|
||||
{
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
<string>m3u</string>
|
||||
<string>tgc</string>
|
||||
<string>wad</string>
|
||||
<string>wia</string>
|
||||
<string>wbfs</string>
|
||||
</array>
|
||||
<key>CFBundleTypeIconFile</key>
|
||||
|
|
|
@ -686,8 +686,8 @@ QStringList MainWindow::PromptFileNames()
|
|||
QStringList paths = QFileDialog::getOpenFileNames(
|
||||
this, tr("Select a File"),
|
||||
settings.value(QStringLiteral("mainwindow/lastdir"), QString{}).toString(),
|
||||
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wad *.dff *.m3u);;"
|
||||
"All Files (*)"));
|
||||
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wia *.wad *.dff "
|
||||
"*.m3u);;All Files (*)"));
|
||||
|
||||
if (!paths.isEmpty())
|
||||
{
|
||||
|
|
|
@ -44,7 +44,7 @@ void PathPane::BrowseDefaultGame()
|
|||
{
|
||||
QString file = QDir::toNativeSeparators(QFileDialog::getOpenFileName(
|
||||
this, tr("Select a Game"), Settings::Instance().GetDefaultGame(),
|
||||
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wad *.m3u);;"
|
||||
tr("All GC/Wii files (*.elf *.dol *.gcm *.iso *.tgc *.wbfs *.ciso *.gcz *.wia *.wad *.m3u);;"
|
||||
"All Files (*)")));
|
||||
|
||||
if (!file.isEmpty())
|
||||
|
|
|
@ -33,7 +33,7 @@ std::vector<std::string> FindAllGamePaths(const std::vector<std::string>& direct
|
|||
bool recursive_scan)
|
||||
{
|
||||
static const std::vector<std::string> search_extensions = {
|
||||
".gcm", ".tgc", ".iso", ".ciso", ".gcz", ".wbfs", ".wad", ".dol", ".elf"};
|
||||
".gcm", ".tgc", ".iso", ".ciso", ".gcz", ".wbfs", ".wia", ".wad", ".dol", ".elf"};
|
||||
|
||||
// TODO: We could process paths iteratively as they are found
|
||||
return Common::DoFileSearch(directories_to_scan, search_extensions, recursive_scan);
|
||||
|
|
Loading…
Reference in New Issue