mirror of https://github.com/AxioDL/nod.git
Shared NFS data class not necessary
This commit is contained in:
parent
19604b2a3b
commit
48a2981a93
|
@ -54,14 +54,21 @@
|
||||||
namespace nod {
|
namespace nod {
|
||||||
/* define our own min/max to avoid MSVC BS */
|
/* define our own min/max to avoid MSVC BS */
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T min(T a, T b) {
|
constexpr T min(T a, T b) {
|
||||||
return a < b ? a : b;
|
return a < b ? a : b;
|
||||||
}
|
}
|
||||||
template <typename T>
|
template <typename T>
|
||||||
inline T max(T a, T b) {
|
constexpr T max(T a, T b) {
|
||||||
return a > b ? a : b;
|
return a > b ? a : b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* template-based div for flexible typing and avoiding a library call */
|
||||||
|
template <typename T>
|
||||||
|
constexpr auto div(T a, T b) {
|
||||||
|
struct DivTp { T quot, rem; };
|
||||||
|
return DivTp{a / b, a % b};
|
||||||
|
}
|
||||||
|
|
||||||
/* Log Module */
|
/* Log Module */
|
||||||
extern logvisor::Module LogModule;
|
extern logvisor::Module LogModule;
|
||||||
|
|
||||||
|
|
|
@ -5,8 +5,6 @@
|
||||||
|
|
||||||
#include <logvisor/logvisor.hpp>
|
#include <logvisor/logvisor.hpp>
|
||||||
|
|
||||||
#include <array>
|
|
||||||
|
|
||||||
namespace nod {
|
namespace nod {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
@ -16,137 +14,132 @@ namespace nod {
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class DiscIONFS : public IDiscIO {
|
class DiscIONFS : public IDiscIO {
|
||||||
struct DiscIONFSShared {
|
std::vector<std::unique_ptr<IFileIO>> files;
|
||||||
std::vector<std::unique_ptr<IFileIO>> files;
|
|
||||||
|
|
||||||
struct NFSHead {
|
struct NFSHead {
|
||||||
uint32_t magic; // EGGS
|
uint32_t magic; // EGGS
|
||||||
uint32_t version;
|
uint32_t version;
|
||||||
uint32_t unknown[2]; // Signature, UUID?
|
uint32_t unknown[2]; // Signature, UUID?
|
||||||
uint32_t lbaRangeCount;
|
uint32_t lbaRangeCount;
|
||||||
struct {
|
struct {
|
||||||
uint32_t startBlock;
|
uint32_t startBlock;
|
||||||
uint32_t numBlocks;
|
uint32_t numBlocks;
|
||||||
} lbaRanges[61];
|
} lbaRanges[61];
|
||||||
uint32_t endMagic; // SGGE
|
uint32_t endMagic; // SGGE
|
||||||
} nfsHead;
|
} nfsHead;
|
||||||
|
|
||||||
uint8_t key[16];
|
uint8_t key[16];
|
||||||
|
|
||||||
uint32_t calculateNumFiles() const {
|
uint32_t calculateNumFiles() const {
|
||||||
uint32_t totalBlockCount = 0;
|
uint32_t totalBlockCount = 0;
|
||||||
for (uint32_t i = 0; i < nfsHead.lbaRangeCount; ++i)
|
for (uint32_t i = 0; i < nfsHead.lbaRangeCount; ++i)
|
||||||
totalBlockCount += nfsHead.lbaRanges[i].numBlocks;
|
totalBlockCount += nfsHead.lbaRanges[i].numBlocks;
|
||||||
return (uint64_t(totalBlockCount) * uint64_t(0x8000) +
|
return (uint64_t(totalBlockCount) * uint64_t(0x8000) +
|
||||||
(uint64_t(0x200) + uint64_t(0xF9FFFFF))) / uint64_t(0xFA00000);
|
(uint64_t(0x200) + uint64_t(0xF9FFFFF))) / uint64_t(0xFA00000);
|
||||||
}
|
}
|
||||||
|
|
||||||
struct FBO {
|
struct FBO {
|
||||||
uint32_t file, block, lblock, offset;
|
uint32_t file, block, lblock, offset;
|
||||||
};
|
|
||||||
|
|
||||||
FBO logicalToFBO(uint64_t offset) const {
|
|
||||||
auto blockAndRemBytes = std::lldiv(offset, 0x8000); /* 32768 bytes per block */
|
|
||||||
uint32_t block = UINT32_MAX;
|
|
||||||
for (uint32_t i = 0, physicalBlock = 0; i < nfsHead.lbaRangeCount; ++i) {
|
|
||||||
const auto& range = nfsHead.lbaRanges[i];
|
|
||||||
if (blockAndRemBytes.quot >= range.startBlock && blockAndRemBytes.quot - range.startBlock < range.numBlocks) {
|
|
||||||
block = physicalBlock + (blockAndRemBytes.quot - range.startBlock);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
physicalBlock += range.numBlocks;
|
|
||||||
}
|
|
||||||
/* This offset has no physical mapping, read zeroes */
|
|
||||||
if (block == UINT32_MAX)
|
|
||||||
return {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
|
|
||||||
auto fileAndRemBlocks = std::lldiv(block, 8000); /* 8000 blocks per file */
|
|
||||||
return {uint32_t(fileAndRemBlocks.quot), uint32_t(fileAndRemBlocks.rem),
|
|
||||||
uint32_t(blockAndRemBytes.quot), uint32_t(blockAndRemBytes.rem)};
|
|
||||||
}
|
|
||||||
|
|
||||||
DiscIONFSShared(SystemStringView fpin, bool& err) {
|
|
||||||
/* Validate file path format */
|
|
||||||
using SignedSize = std::make_signed<SystemString::size_type>::type;
|
|
||||||
const auto dotPos = SignedSize(fpin.rfind('.'));
|
|
||||||
const auto slashPos = SignedSize(fpin.find_last_of("/\\"));
|
|
||||||
if (fpin.size() <= 4 || dotPos == -1 || dotPos <= slashPos ||
|
|
||||||
fpin.compare(slashPos + 1, 4, "hif_") ||
|
|
||||||
fpin.compare(dotPos, fpin.size() - dotPos, ".nfs")) {
|
|
||||||
LogModule.report(logvisor::Error,
|
|
||||||
fmt("'{}' must begin with 'hif_' and end with '.nfs' to be accepted as an NFS image"), fpin);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load key file */
|
|
||||||
const SystemString dir(fpin.begin(), fpin.begin() + slashPos + 1);
|
|
||||||
auto keyFile = NewFileIO(dir + "../code/htk.bin")->beginReadStream();
|
|
||||||
if (!keyFile)
|
|
||||||
keyFile = NewFileIO(dir + "htk.bin")->beginReadStream();
|
|
||||||
if (!keyFile) {
|
|
||||||
LogModule.report(logvisor::Error, fmt("Unable to open '{}../code/htk.bin' or '{}htk.bin'"), dir, dir);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (keyFile->read(key, 16) != 16) {
|
|
||||||
LogModule.report(logvisor::Error, fmt("Unable to read from '{}../code/htk.bin' or '{}htk.bin'"), dir, dir);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Load header from first file */
|
|
||||||
const SystemString firstPath = fmt::format(fmt("{}hif_{:06}.nfs"), dir, 0);
|
|
||||||
files.push_back(NewFileIO(firstPath));
|
|
||||||
auto rs = files.back()->beginReadStream();
|
|
||||||
if (!rs) {
|
|
||||||
LogModule.report(logvisor::Error, fmt("'{}' does not exist"), firstPath);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (rs->read(&nfsHead, 0x200) != 0x200) {
|
|
||||||
LogModule.report(logvisor::Error, fmt("Unable to read header from '{}'"), firstPath);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (std::memcmp(&nfsHead.magic, "EGGS", 4)) {
|
|
||||||
LogModule.report(logvisor::Error, fmt("Invalid magic in '{}'"), firstPath);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
nfsHead.lbaRangeCount = SBig(nfsHead.lbaRangeCount);
|
|
||||||
for (uint32_t i = 0; i < nfsHead.lbaRangeCount; ++i) {
|
|
||||||
auto& range = nfsHead.lbaRanges[i];
|
|
||||||
range.startBlock = SBig(range.startBlock);
|
|
||||||
range.numBlocks = SBig(range.numBlocks);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Ensure remaining files exist */
|
|
||||||
const uint32_t numFiles = calculateNumFiles();
|
|
||||||
files.reserve(numFiles);
|
|
||||||
for (uint32_t i = 1; i < numFiles; ++i) {
|
|
||||||
SystemString path = fmt::format(fmt("{}hif_{:06}.nfs"), dir, i);
|
|
||||||
files.push_back(NewFileIO(path));
|
|
||||||
if (!files.back()->exists()) {
|
|
||||||
LogModule.report(logvisor::Error, fmt("'{}' does not exist"), path);
|
|
||||||
err = true;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
std::shared_ptr<DiscIONFSShared> m_shared;
|
|
||||||
|
FBO logicalToFBO(uint64_t offset) const {
|
||||||
|
auto blockAndRemBytes = nod::div(offset, uint64_t(0x8000)); /* 32768 bytes per block */
|
||||||
|
uint32_t block = UINT32_MAX;
|
||||||
|
for (uint32_t i = 0, physicalBlock = 0; i < nfsHead.lbaRangeCount; ++i) {
|
||||||
|
const auto& range = nfsHead.lbaRanges[i];
|
||||||
|
if (blockAndRemBytes.quot >= range.startBlock && blockAndRemBytes.quot - range.startBlock < range.numBlocks) {
|
||||||
|
block = physicalBlock + (blockAndRemBytes.quot - range.startBlock);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
physicalBlock += range.numBlocks;
|
||||||
|
}
|
||||||
|
/* This offset has no physical mapping, read zeroes */
|
||||||
|
if (block == UINT32_MAX)
|
||||||
|
return {UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX};
|
||||||
|
auto fileAndRemBlocks = nod::div(block, uint32_t(8000)); /* 8000 blocks per file */
|
||||||
|
return {uint32_t(fileAndRemBlocks.quot), uint32_t(fileAndRemBlocks.rem),
|
||||||
|
uint32_t(blockAndRemBytes.quot), uint32_t(blockAndRemBytes.rem)};
|
||||||
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
DiscIONFS(SystemStringView fpin, bool& err) : m_shared(std::make_shared<DiscIONFSShared>(fpin, err)) {}
|
DiscIONFS(SystemStringView fpin, bool& err) {
|
||||||
|
/* Validate file path format */
|
||||||
|
using SignedSize = std::make_signed<SystemString::size_type>::type;
|
||||||
|
const auto dotPos = SignedSize(fpin.rfind('.'));
|
||||||
|
const auto slashPos = SignedSize(fpin.find_last_of("/\\"));
|
||||||
|
if (fpin.size() <= 4 || dotPos == -1 || dotPos <= slashPos ||
|
||||||
|
fpin.compare(slashPos + 1, 4, "hif_") ||
|
||||||
|
fpin.compare(dotPos, fpin.size() - dotPos, ".nfs")) {
|
||||||
|
LogModule.report(logvisor::Error,
|
||||||
|
fmt("'{}' must begin with 'hif_' and end with '.nfs' to be accepted as an NFS image"), fpin);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load key file */
|
||||||
|
const SystemString dir(fpin.begin(), fpin.begin() + slashPos + 1);
|
||||||
|
auto keyFile = NewFileIO(dir + "../code/htk.bin")->beginReadStream();
|
||||||
|
if (!keyFile)
|
||||||
|
keyFile = NewFileIO(dir + "htk.bin")->beginReadStream();
|
||||||
|
if (!keyFile) {
|
||||||
|
LogModule.report(logvisor::Error, fmt("Unable to open '{}../code/htk.bin' or '{}htk.bin'"), dir, dir);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (keyFile->read(key, 16) != 16) {
|
||||||
|
LogModule.report(logvisor::Error, fmt("Unable to read from '{}../code/htk.bin' or '{}htk.bin'"), dir, dir);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load header from first file */
|
||||||
|
const SystemString firstPath = fmt::format(fmt("{}hif_{:06}.nfs"), dir, 0);
|
||||||
|
files.push_back(NewFileIO(firstPath));
|
||||||
|
auto rs = files.back()->beginReadStream();
|
||||||
|
if (!rs) {
|
||||||
|
LogModule.report(logvisor::Error, fmt("'{}' does not exist"), firstPath);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (rs->read(&nfsHead, 0x200) != 0x200) {
|
||||||
|
LogModule.report(logvisor::Error, fmt("Unable to read header from '{}'"), firstPath);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (std::memcmp(&nfsHead.magic, "EGGS", 4)) {
|
||||||
|
LogModule.report(logvisor::Error, fmt("Invalid magic in '{}'"), firstPath);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
nfsHead.lbaRangeCount = SBig(nfsHead.lbaRangeCount);
|
||||||
|
for (uint32_t i = 0; i < nfsHead.lbaRangeCount; ++i) {
|
||||||
|
auto& range = nfsHead.lbaRanges[i];
|
||||||
|
range.startBlock = SBig(range.startBlock);
|
||||||
|
range.numBlocks = SBig(range.numBlocks);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Ensure remaining files exist */
|
||||||
|
const uint32_t numFiles = calculateNumFiles();
|
||||||
|
files.reserve(numFiles);
|
||||||
|
for (uint32_t i = 1; i < numFiles; ++i) {
|
||||||
|
SystemString path = fmt::format(fmt("{}hif_{:06}.nfs"), dir, i);
|
||||||
|
files.push_back(NewFileIO(path));
|
||||||
|
if (!files.back()->exists()) {
|
||||||
|
LogModule.report(logvisor::Error, fmt("'{}' does not exist"), path);
|
||||||
|
err = true;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ReadStream : public IReadStream {
|
class ReadStream : public IReadStream {
|
||||||
friend class DiscIONFS;
|
friend class DiscIONFS;
|
||||||
std::shared_ptr<DiscIONFSShared> m_shared;
|
const DiscIONFS& m_parent;
|
||||||
std::unique_ptr<IReadStream> m_rs;
|
std::unique_ptr<IReadStream> m_rs;
|
||||||
std::unique_ptr<IAES> m_aes;
|
std::unique_ptr<IAES> m_aes;
|
||||||
|
|
||||||
/* Physical address - all UINT32_MAX indicates logical zero block */
|
/* Physical address - all UINT32_MAX indicates logical zero block */
|
||||||
DiscIONFSShared::FBO m_physAddr;
|
DiscIONFS::FBO m_physAddr;
|
||||||
|
|
||||||
/* Logical address */
|
/* Logical address */
|
||||||
uint64_t m_offset;
|
uint64_t m_offset;
|
||||||
|
@ -156,24 +149,24 @@ public:
|
||||||
uint32_t m_curFile = UINT32_MAX;
|
uint32_t m_curFile = UINT32_MAX;
|
||||||
uint32_t m_curBlock = UINT32_MAX;
|
uint32_t m_curBlock = UINT32_MAX;
|
||||||
|
|
||||||
ReadStream(std::shared_ptr<DiscIONFSShared> shared, uint64_t offset, bool& err)
|
ReadStream(const DiscIONFS& parent, uint64_t offset, bool& err)
|
||||||
: m_shared(std::move(shared)), m_aes(NewAES()),
|
: m_parent(parent), m_aes(NewAES()),
|
||||||
m_physAddr({UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX}), m_offset(offset) {
|
m_physAddr({UINT32_MAX, UINT32_MAX, UINT32_MAX, UINT32_MAX}), m_offset(offset) {
|
||||||
m_aes->setKey(m_shared->key);
|
m_aes->setKey(m_parent.key);
|
||||||
setNewLogicalAddr(offset);
|
setLogicalAddr(offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t m_encBuf[0x8000] = {};
|
uint8_t m_encBuf[0x8000] = {};
|
||||||
uint8_t m_decBuf[0x8000] = {};
|
uint8_t m_decBuf[0x8000] = {};
|
||||||
|
|
||||||
void setCurFile(uint32_t curFile) {
|
void setCurFile(uint32_t curFile) {
|
||||||
if (curFile >= m_shared->files.size()) {
|
if (curFile >= m_parent.files.size()) {
|
||||||
LogModule.report(logvisor::Error, fmt("Out of bounds NFS file access"));
|
LogModule.report(logvisor::Error, fmt("Out of bounds NFS file access"));
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
m_curFile = curFile;
|
m_curFile = curFile;
|
||||||
m_curBlock = UINT32_MAX;
|
m_curBlock = UINT32_MAX;
|
||||||
m_rs = m_shared->files[m_curFile]->beginReadStream();
|
m_rs = m_parent.files[m_curFile]->beginReadStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
void setCurBlock(uint32_t curBlock) {
|
void setCurBlock(uint32_t curBlock) {
|
||||||
|
@ -181,7 +174,7 @@ public:
|
||||||
m_rs->seek(m_curBlock * 0x8000 + 0x200);
|
m_rs->seek(m_curBlock * 0x8000 + 0x200);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNewPhysicalAddr(DiscIONFSShared::FBO physAddr) {
|
void setPhysicalAddr(DiscIONFS::FBO physAddr) {
|
||||||
/* If we're just changing the offset, nothing else needs to be done */
|
/* If we're just changing the offset, nothing else needs to be done */
|
||||||
if (m_physAddr.file == physAddr.file && m_physAddr.block == physAddr.block) {
|
if (m_physAddr.file == physAddr.file && m_physAddr.block == physAddr.block) {
|
||||||
m_physAddr.offset = physAddr.offset;
|
m_physAddr.offset = physAddr.offset;
|
||||||
|
@ -217,9 +210,7 @@ public:
|
||||||
m_aes->decrypt((const uint8_t*)ivBuf, m_encBuf, m_decBuf, 0x8000);
|
m_aes->decrypt((const uint8_t*)ivBuf, m_encBuf, m_decBuf, 0x8000);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setNewLogicalAddr(uint64_t addr) {
|
void setLogicalAddr(uint64_t addr) { setPhysicalAddr(m_parent.logicalToFBO(m_offset)); }
|
||||||
setNewPhysicalAddr(m_shared->logicalToFBO(m_offset));
|
|
||||||
}
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
uint64_t read(void* buf, uint64_t length) override {
|
uint64_t read(void* buf, uint64_t length) override {
|
||||||
|
@ -237,7 +228,7 @@ public:
|
||||||
dst += readSize;
|
dst += readSize;
|
||||||
rem -= readSize;
|
rem -= readSize;
|
||||||
m_offset += readSize;
|
m_offset += readSize;
|
||||||
setNewLogicalAddr(m_offset);
|
setLogicalAddr(m_offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
return dst - (uint8_t*)buf;
|
return dst - (uint8_t*)buf;
|
||||||
|
@ -250,13 +241,13 @@ public:
|
||||||
m_offset += offset;
|
m_offset += offset;
|
||||||
else
|
else
|
||||||
return;
|
return;
|
||||||
setNewLogicalAddr(m_offset);
|
setLogicalAddr(m_offset);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const override {
|
std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const override {
|
||||||
bool err = false;
|
bool err = false;
|
||||||
auto ret = std::unique_ptr<IReadStream>(new ReadStream(m_shared, offset, err));
|
auto ret = std::unique_ptr<IReadStream>(new ReadStream(*this, offset, err));
|
||||||
|
|
||||||
if (err)
|
if (err)
|
||||||
return {};
|
return {};
|
||||||
|
|
|
@ -373,7 +373,7 @@ public:
|
||||||
}
|
}
|
||||||
uint64_t position() const override { return m_offset; }
|
uint64_t position() const override { return m_offset; }
|
||||||
uint64_t read(void* buf, uint64_t length) override {
|
uint64_t read(void* buf, uint64_t length) override {
|
||||||
auto blockAndRemOff = std::lldiv(m_offset, 0x7c00);
|
auto blockAndRemOff = nod::div(m_offset, uint64_t(0x7c00));
|
||||||
uint64_t rem = length;
|
uint64_t rem = length;
|
||||||
uint8_t* dst = (uint8_t*)buf;
|
uint8_t* dst = (uint8_t*)buf;
|
||||||
|
|
||||||
|
@ -1239,7 +1239,7 @@ std::optional<uint64_t> DiscBuilderWii::CalculateTotalSizeRequired(SystemStringV
|
||||||
std::optional<uint64_t> sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(dirIn, PartitionKind::Data, true);
|
std::optional<uint64_t> sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(dirIn, PartitionKind::Data, true);
|
||||||
if (!sz)
|
if (!sz)
|
||||||
return sz;
|
return sz;
|
||||||
auto szDiv = std::lldiv(*sz, 0x1F0000);
|
auto szDiv = nod::div(*sz, uint64_t(0x1F0000));
|
||||||
if (szDiv.rem)
|
if (szDiv.rem)
|
||||||
++szDiv.quot;
|
++szDiv.quot;
|
||||||
sz = szDiv.quot * 0x200000;
|
sz = szDiv.quot * 0x200000;
|
||||||
|
@ -1346,7 +1346,7 @@ std::optional<uint64_t> DiscMergerWii::CalculateTotalSizeRequired(DiscWii& sourc
|
||||||
std::optional<uint64_t> sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(sourceDisc.getDataPartition(), dirIn);
|
std::optional<uint64_t> sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(sourceDisc.getDataPartition(), dirIn);
|
||||||
if (!sz)
|
if (!sz)
|
||||||
return std::nullopt;
|
return std::nullopt;
|
||||||
auto szDiv = std::lldiv(*sz, 0x1F0000);
|
auto szDiv = nod::div(*sz, uint64_t(0x1F0000));
|
||||||
if (szDiv.rem)
|
if (szDiv.rem)
|
||||||
++szDiv.quot;
|
++szDiv.quot;
|
||||||
sz = szDiv.quot * 0x200000;
|
sz = szDiv.quot * 0x200000;
|
||||||
|
|
10
lib/nod.cpp
10
lib/nod.cpp
|
@ -68,16 +68,14 @@ std::unique_ptr<DiscBase> OpenDiscFromImage(SystemStringView path, bool& isWii)
|
||||||
std::unique_ptr<DiscBase> ret;
|
std::unique_ptr<DiscBase> ret;
|
||||||
if (isWii) {
|
if (isWii) {
|
||||||
ret = std::make_unique<DiscWii>(std::move(discIO), err);
|
ret = std::make_unique<DiscWii>(std::move(discIO), err);
|
||||||
if (err) {
|
if (err)
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = std::make_unique<DiscGCN>(std::move(discIO), err);
|
ret = std::make_unique<DiscGCN>(std::move(discIO), err);
|
||||||
if (err) {
|
if (err)
|
||||||
return nullptr;
|
return {};
|
||||||
}
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue