Add floating point progress to builder callbacks

This commit is contained in:
Jack Andersen 2017-05-21 23:12:48 -04:00
parent e494dbba9f
commit dd20c1d255
10 changed files with 285 additions and 150 deletions

View File

@ -40,7 +40,7 @@ int main(int argc, char* argv[])
logvisor::RegisterConsoleLogger();
nod::ExtractionContext ctx = { true, true, [&](const std::string& str, float c){
fprintf(stderr, "Current node: %s, Extraction %g%% Complete\n", str.c_str(), c);
fprintf(stderr, "Current node: %s, Extraction %g%% Complete\n", str.c_str(), c * 100.f);
}};
const nod::SystemChar* inDir = nullptr;
const nod::SystemChar* outDir = _S(".");
@ -58,18 +58,13 @@ int main(int argc, char* argv[])
outDir = argv[a];
}
size_t lastIdx = -1;
auto progFunc = [&](size_t idx, const nod::SystemString& name, size_t bytes)
auto progFunc = [&](float prog, const nod::SystemString& name, size_t bytes)
{
if (idx != lastIdx)
{
lastIdx = idx;
printf("\n");
}
nod::Printf(_S("\r "));
if (bytes != -1)
nod::Printf(_S("\r%s %" PRISize " B"), name.c_str(), bytes);
nod::Printf(_S("\r%g%% %s %" PRISize " B"), prog * 100.f, name.c_str(), bytes);
else
nod::Printf(_S("\r%s"), name.c_str());
nod::Printf(_S("\r%g%% %s"), prog * 100.f, name.c_str());
fflush(stdout);
};
@ -135,7 +130,7 @@ int main(int argc, char* argv[])
if (nod::DiscBuilderGCN::CalculateTotalSizeRequired(argv[4], argv[5]) == -1)
return 1;
bool ret;
nod::EBuildResult ret;
if (argc < 8)
{
@ -151,7 +146,7 @@ int main(int argc, char* argv[])
}
printf("\n");
if (!ret)
if (ret != nod::EBuildResult::Success)
return 1;
}
else if (!strcasecmp(argv[1], _S("makewii")))
@ -202,7 +197,7 @@ int main(int argc, char* argv[])
if (nod::DiscBuilderWii::CalculateTotalSizeRequired(argv[4], argv[5], dual) == -1)
return 1;
bool ret;
nod::EBuildResult ret;
if (argc < 9)
{
@ -218,7 +213,7 @@ int main(int argc, char* argv[])
}
printf("\n");
if (!ret)
if (ret != nod::EBuildResult::Success)
return 1;
}
else if (!strcasecmp(argv[1], _S("mergegcn")))
@ -252,7 +247,7 @@ int main(int argc, char* argv[])
if (nod::DiscMergerGCN::CalculateTotalSizeRequired(static_cast<nod::DiscGCN&>(*disc), argv[2]) == -1)
return 1;
bool ret;
nod::EBuildResult ret;
if (argc < 5)
{
@ -268,7 +263,7 @@ int main(int argc, char* argv[])
}
printf("\n");
if (!ret)
if (ret != nod::EBuildResult::Success)
return 1;
}
else if (!strcasecmp(argv[1], _S("mergewii")))
@ -303,7 +298,7 @@ int main(int argc, char* argv[])
if (nod::DiscMergerWii::CalculateTotalSizeRequired(static_cast<nod::DiscWii&>(*disc), argv[2], dual) == -1)
return 1;
bool ret;
nod::EBuildResult ret;
if (argc < 5)
{
@ -319,7 +314,7 @@ int main(int argc, char* argv[])
}
printf("\n");
if (!ret)
if (ret != nod::EBuildResult::Success)
return 1;
}
else

View File

@ -15,7 +15,14 @@
namespace nod
{
using FProgress = std::function<void(size_t, const SystemString&, size_t)>;
using FProgress = std::function<void(float totalProg, const SystemString& fileName, size_t fileBytesXfered)>;
enum class EBuildResult
{
Success,
Failed,
DiskFull
};
class FSTNode
{
@ -237,6 +244,18 @@ public:
uint64_t m_offset;
public:
mutable size_t m_curNodeIdx = 0;
float getProgressFactor() const { return getNodeCount() ? m_curNodeIdx / float(getNodeCount()) : 0.f; }
float getProgressFactorMidFile(size_t curByte, size_t totalBytes) const
{
if (!getNodeCount())
return 0.f;
if (totalBytes)
return (m_curNodeIdx + (curByte / float(totalBytes))) / float(getNodeCount());
else
return m_curNodeIdx / float(getNodeCount());
}
IPartition(const DiscBase& parent, Kind kind, uint64_t offset)
: m_parent(parent), m_kind(kind), m_offset(offset) {}
virtual uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset;}
@ -342,18 +361,25 @@ public:
size_t m_buildNameOff = 0;
virtual uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws)=0;
virtual uint32_t packOffset(uint64_t offset) const=0;
void recursiveBuildNodesPre(const SystemChar* dirIn, uint64_t dolInode);
bool recursiveBuildNodes(IPartWriteStream& ws, bool system, const SystemChar* dirIn, uint64_t dolInode);
bool recursiveBuildFST(const SystemChar* dirIn, uint64_t dolInode,
std::function<void(void)> incParents);
void recursiveMergeNodesPre(const DiscBase::IPartition::Node* nodeIn, const SystemChar* dirIn);
bool recursiveMergeNodes(IPartWriteStream& ws, bool system,
const DiscBase::IPartition::Node* nodeIn, const SystemChar* dirIn,
const SystemString& keyPath);
bool recursiveMergeFST(const DiscBase::IPartition::Node* nodeIn,
const SystemChar* dirIn, std::function<void(void)> incParents,
const SystemString& keyPath);
static bool RecursiveCalculateTotalSize(uint64_t& totalSz,
const DiscBase::IPartition::Node* nodeIn,
const SystemChar* dirIn);
void addBuildName(const SystemString& str)
{
SystemUTF8View utf8View(str);
@ -396,11 +422,26 @@ protected:
std::vector<std::unique_ptr<PartitionBuilderBase>> m_partitions;
int64_t m_discCapacity;
public:
std::function<void(size_t idx, const SystemString&, size_t)> m_progressCB;
FProgress m_progressCB;
size_t m_progressIdx = 0;
size_t m_progressTotal = 0;
float getProgressFactor() const
{
return m_progressTotal ? std::min(1.f, m_progressIdx / float(m_progressTotal)) : 0.f;
}
float getProgressFactorMidFile(size_t curByte, size_t totalBytes) const
{
if (!m_progressTotal)
return 0.f;
if (totalBytes)
return (m_progressIdx + (curByte / float(totalBytes))) / float(m_progressTotal);
else
return m_progressIdx / float(m_progressTotal);
}
virtual ~DiscBuilderBase() = default;
DiscBuilderBase(const SystemChar* outPath, int64_t discCapacity,
std::function<void(size_t idx, const SystemString&, size_t)> progressCB)
DiscBuilderBase(const SystemChar* outPath, int64_t discCapacity, FProgress progressCB)
: m_outPath(outPath), m_fileIO(NewFileIO(outPath, discCapacity)),
m_discCapacity(discCapacity), m_progressCB(progressCB) {}
DiscBuilderBase(DiscBuilderBase&&) = default;

View File

@ -21,8 +21,8 @@ class DiscBuilderGCN : public DiscBuilderBase
public:
DiscBuilderGCN(const SystemChar* outPath, const char gameID[6], const char* gameTitle,
uint32_t fstMemoryAddr, FProgress progressCB);
bool buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn);
EBuildResult buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn);
static uint64_t CalculateTotalSizeRequired(const SystemChar* dirIn, const SystemChar* dolIn);
};
@ -32,7 +32,7 @@ class DiscMergerGCN
DiscBuilderGCN m_builder;
public:
DiscMergerGCN(const SystemChar* outPath, DiscGCN& sourceDisc, FProgress progressCB);
bool mergeFromDirectory(const SystemChar* dirIn);
EBuildResult mergeFromDirectory(const SystemChar* dirIn);
static uint64_t CalculateTotalSizeRequired(DiscGCN& sourceDisc, const SystemChar* dirIn);
};

View File

@ -21,10 +21,10 @@ class DiscBuilderWii : public DiscBuilderBase
public:
DiscBuilderWii(const SystemChar* outPath, const char gameID[6], const char* gameTitle,
bool dualLayer, FProgress progressCB);
bool buildFromDirectory(const SystemChar* dirIn,
const SystemChar* dolIn,
const SystemChar* apploaderIn,
const SystemChar* partHeadIn);
EBuildResult buildFromDirectory(const SystemChar* dirIn,
const SystemChar* dolIn,
const SystemChar* apploaderIn,
const SystemChar* partHeadIn);
static uint64_t CalculateTotalSizeRequired(const SystemChar* dirIn, const SystemChar* dolIn,
bool& dualLayer);
};
@ -36,7 +36,7 @@ class DiscMergerWii
public:
DiscMergerWii(const SystemChar* outPath, DiscWii& sourceDisc,
bool dualLayer, FProgress progressCB);
bool mergeFromDirectory(const SystemChar* dirIn);
EBuildResult mergeFromDirectory(const SystemChar* dirIn);
static uint64_t CalculateTotalSizeRequired(DiscWii& sourceDisc, const SystemChar* dirIn,
bool& dualLayer);
};

View File

@ -20,7 +20,55 @@ public:
{
virtual ~IWriteStream() {}
virtual uint64_t write(const void* buf, uint64_t length)=0;
virtual uint64_t copyFromDisc(struct IPartReadStream& discio, uint64_t length)=0;
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{
uint64_t read = 0;
uint8_t buf[0x7c00];
while (length)
{
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz)
{
LogModule.report(logvisor::Error, "unable to read enough from disc");
return read;
}
if (write(buf, readSz) != readSz)
{
LogModule.report(logvisor::Error, "unable to write in file");
return read;
}
length -= thisSz;
read += thisSz;
}
return read;
}
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length, const std::function<void(float)>& prog)
{
uint64_t read = 0;
uint8_t buf[0x7c00];
uint64_t total = length;
while (length)
{
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz)
{
LogModule.report(logvisor::Error, "unable to read enough from disc");
return read;
}
if (write(buf, readSz) != readSz)
{
LogModule.report(logvisor::Error, "unable to write in file");
return read;
}
length -= thisSz;
read += thisSz;
prog(read / float(total));
}
return read;
}
};
virtual std::unique_ptr<IWriteStream> beginWriteStream() const=0;
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const=0;

View File

@ -99,7 +99,7 @@ bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath
{
++m_parent.m_curNodeIdx;
if (ctx.verbose && ctx.progressCB && !getName().empty())
ctx.progressCB(getName(), float(m_parent.m_curNodeIdx * 100.f) / m_parent.getNodeCount());
ctx.progressCB(getName(), m_parent.m_curNodeIdx / float(m_parent.getNodeCount()));
if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
{
LogModule.report(logvisor::Error, _S("unable to mkdir '%s'"), path.c_str());
@ -112,9 +112,8 @@ bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath
else if (m_kind == Kind::File)
{
Sstat theStat;
++m_parent.m_curNodeIdx;
if (ctx.verbose && ctx.progressCB)
ctx.progressCB(getName(), float(m_parent.m_curNodeIdx * 100.f) / m_parent.getNodeCount());
ctx.progressCB(getName(), m_parent.m_curNodeIdx / float(m_parent.getNodeCount()));
if (ctx.force || Stat(path.c_str(), &theStat))
{
@ -122,8 +121,14 @@ bool DiscBase::IPartition::Node::extractToDirectory(const SystemString& basePath
std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(path)->beginWriteStream();
if (!rs || !ws)
return false;
ws->copyFromDisc(*rs, m_discLength);
ws->copyFromDisc(*rs, m_discLength,
[&](float prog)
{
if (ctx.verbose && ctx.progressCB)
ctx.progressCB(getName(), (m_parent.m_curNodeIdx + prog) / float(m_parent.getNodeCount()));
});
}
++m_parent.m_curNodeIdx;
}
return true;
}
@ -263,6 +268,26 @@ static size_t PatchDOL(IFileIO::IReadStream& in, IPartWriteStream& out, size_t s
return out.write(buf.get(), sz);
}
void DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodesPre(const SystemChar* dirIn,
uint64_t dolInode)
{
DirectoryEnumerator dEnum(dirIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
if (e.m_isDir)
{
recursiveBuildNodesPre(e.m_path.c_str(), dolInode);
}
else
{
if (dolInode == GetInode(e.m_path.c_str()))
continue;
++m_parent.m_progressTotal;
}
}
}
bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream& ws,
bool system,
const SystemChar* dirIn,
@ -299,12 +324,12 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream
{
bool patched;
xferSz = PatchDOL(*rs, ws, e.m_fileSz, patched);
m_parent.m_progressCB(++m_parent.m_progressIdx, e.m_name + (patched ? _S(" [PATCHED]") : _S("")), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), e.m_name + (patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
}
else
{
char buf[0x8000];
++m_parent.m_progressIdx;
while (xferSz < e.m_fileSz)
{
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000ul), e.m_fileSz - xferSz));
@ -312,8 +337,9 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream
break;
ws.write(buf, rdSz);
xferSz += rdSz;
m_parent.m_progressCB(m_parent.m_progressIdx, e.m_name, xferSz);
m_parent.m_progressCB(m_parent.getProgressFactorMidFile(xferSz, e.m_fileSz), e.m_name, xferSz);
}
++m_parent.m_progressIdx;
}
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1);
@ -358,6 +384,64 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildFST(const SystemChar*
return true;
}
void DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodesPre(const DiscBase::IPartition::Node* nodeIn,
const SystemChar* dirIn)
{
/* Build map of existing nodes to write-through later */
std::unordered_map<std::string, const Partition::Node*> fileNodes;
std::unordered_map<std::string, const Partition::Node*> dirNodes;
if (nodeIn)
{
fileNodes.reserve(nodeIn->size());
dirNodes.reserve(nodeIn->size());
for (const Partition::Node& ch : *nodeIn)
{
if (ch.getKind() == Partition::Node::Kind::File)
fileNodes.insert(std::make_pair(ch.getName(), &ch));
else if (ch.getKind() == Partition::Node::Kind::Directory)
dirNodes.insert(std::make_pair(ch.getName(), &ch));
}
}
/* Merge this directory's files */
if (dirIn)
{
DirectoryEnumerator dEnum(dirIn, DirectoryEnumerator::Mode::DirsThenFilesSorted, false, false, true);
for (const DirectoryEnumerator::Entry& e : dEnum)
{
SystemUTF8View nameView(e.m_name);
if (e.m_isDir)
{
auto search = dirNodes.find(nameView.utf8_str());
if (search != dirNodes.cend())
{
recursiveMergeNodesPre(search->second, e.m_path.c_str());
dirNodes.erase(search);
}
else
{
recursiveMergeNodesPre(nullptr, e.m_path.c_str());
}
}
else
{
fileNodes.erase(nameView.utf8_str());
++m_parent.m_progressTotal;
}
}
}
/* Write-through remaining dir nodes */
for (const auto& p : dirNodes)
{
recursiveMergeNodesPre(p.second, nullptr);
}
/* Write-through remaining file nodes */
m_parent.m_progressTotal += fileNodes.size();
}
bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream& ws,
bool system,
const DiscBase::IPartition::Node* nodeIn,
@ -426,13 +510,13 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
{
bool patched;
xferSz = PatchDOL(*rs, ws, e.m_fileSz, patched);
m_parent.m_progressCB(++m_parent.m_progressIdx, e.m_name +
m_parent.m_progressCB(m_parent.getProgressFactor(), e.m_name +
(patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
}
else
{
char buf[0x8000];
++m_parent.m_progressIdx;
while (xferSz < e.m_fileSz)
{
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000ul), e.m_fileSz - xferSz));
@ -440,8 +524,9 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
break;
ws.write(buf, rdSz);
xferSz += rdSz;
m_parent.m_progressCB(m_parent.m_progressIdx, e.m_name, xferSz);
m_parent.m_progressCB(m_parent.getProgressFactorMidFile(xferSz, e.m_fileSz), e.m_name, xferSz);
}
++m_parent.m_progressIdx;
}
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1);
@ -486,13 +571,13 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
bool patched;
PatchDOL(dolBuf, xferSz, patched);
ws.write(dolBuf.get(), xferSz);
m_parent.m_progressCB(++m_parent.m_progressIdx, sysName.sys_str() +
m_parent.m_progressCB(m_parent.getProgressFactor(), sysName.sys_str() +
(patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
}
else
{
char buf[0x8000];
++m_parent.m_progressIdx;
while (xferSz < ch.size())
{
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000), size_t(ch.size() - xferSz)));
@ -500,8 +585,9 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
break;
ws.write(buf, rdSz);
xferSz += rdSz;
m_parent.m_progressCB(m_parent.m_progressIdx, sysName.sys_str(), xferSz);
m_parent.m_progressCB(m_parent.getProgressFactorMidFile(xferSz, ch.size()), sysName.sys_str(), xferSz);
}
++m_parent.m_progressIdx;
}
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1);
@ -689,9 +775,14 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
return false;
}
/* 1st pass - Tally up total progress steps */
uint64_t dolInode = GetInode(dolIn);
m_parent.m_progressTotal += 2; /* Prep and DOL */
recursiveBuildNodesPre(dirIn, dolInode);
/* Clear file */
m_parent.m_progressCB(m_parent.getProgressFactor(), _S("Preparing output image"), -1);
++m_parent.m_progressIdx;
m_parent.m_progressCB(m_parent.m_progressIdx, _S("Preparing output image"), -1);
/* Add root node */
m_buildNodes.emplace_back(true, m_buildNameOff, 0, 1);
@ -716,14 +807,14 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
return false;
bool patched;
size_t xferSz = PatchDOL(*rs, ws, dolStat.st_size, patched);
m_parent.m_progressCB(++m_parent.m_progressIdx, SystemString(dolIn) +
m_parent.m_progressCB(m_parent.getProgressFactor(), SystemString(dolIn) +
(patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1);
}
/* Gather files in root directory */
uint64_t dolInode = GetInode(dolIn);
if (!recursiveBuildNodes(ws, true, dirIn, dolInode))
return false;
if (!recursiveBuildNodes(ws, false, dirIn, dolInode))
@ -759,9 +850,13 @@ bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream&
return false;
}
/* 1st pass - Tally up total progress steps */
m_parent.m_progressTotal += 2; /* Prep and DOL */
recursiveMergeNodesPre(&partIn->getFSTRoot(), dirIn);
/* Clear file */
m_parent.m_progressCB(m_parent.getProgressFactor(), _S("Preparing output image"), -1);
++m_parent.m_progressIdx;
m_parent.m_progressCB(m_parent.m_progressIdx, _S("Preparing output image"), -1);
/* Add root node */
m_buildNodes.emplace_back(true, m_buildNameOff, 0, 1);
@ -780,8 +875,9 @@ bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream&
bool patched;
PatchDOL(dolBuf, xferSz, patched);
ws.write(dolBuf.get(), xferSz);
m_parent.m_progressCB(++m_parent.m_progressIdx, SystemString(_S("<boot-dol>")) +
m_parent.m_progressCB(m_parent.getProgressFactor(), SystemString(_S("<boot-dol>")) +
(patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1);
}

View File

@ -264,7 +264,6 @@ public:
return false;
char buf[8192];
SystemString apploaderName(apploaderIn);
++m_parent.m_progressIdx;
while (true)
{
size_t rdSz = rs->read(buf, 8192);
@ -278,8 +277,9 @@ public:
"apploader flows into user area (one or the other is too big)");
return false;
}
m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderName, xferSz);
}
++m_parent.m_progressIdx;
return true;
});
}
@ -298,7 +298,6 @@ public:
std::unique_ptr<uint8_t[]> apploaderBuf = partIn->getApploaderBuf();
size_t apploaderSz = partIn->getApploaderSize();
SystemString apploaderName(_S("<apploader>"));
++m_parent.m_progressIdx;
ws.write(apploaderBuf.get(), apploaderSz);
xferSz += apploaderSz;
if (0x2440 + xferSz >= m_curUser)
@ -307,31 +306,32 @@ public:
"apploader flows into user area (one or the other is too big)");
return false;
}
m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderName, xferSz);
++m_parent.m_progressIdx;
return true;
});
}
};
bool DiscBuilderGCN::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn)
EBuildResult DiscBuilderGCN::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn)
{
if (!m_fileIO->beginWriteStream())
return false;
return EBuildResult::Failed;
if (!CheckFreeSpace(m_outPath.c_str(), 0x57058000))
{
LogModule.report(logvisor::Error, _S("not enough free disk space for %s"), m_outPath.c_str());
return false;
return EBuildResult::DiskFull;
}
m_progressCB(getProgressFactor(), _S("Preallocating image"), -1);
++m_progressIdx;
m_progressCB(m_progressIdx, _S("Preallocating image"), -1);
auto ws = m_fileIO->beginWriteStream(0x57058000 - 1);
if (!ws)
return false;
return EBuildResult::Failed;
ws->write("", 1);
PartitionBuilderGCN& pb = static_cast<PartitionBuilderGCN&>(*m_partitions[0]);
return pb.buildFromDirectory(dirIn, dolIn, apploaderIn);
return pb.buildFromDirectory(dirIn, dolIn, apploaderIn) ? EBuildResult::Success : EBuildResult::Failed;
}
uint64_t DiscBuilderGCN::CalculateTotalSizeRequired(const SystemChar* dirIn, const SystemChar* dolIn)
@ -361,24 +361,25 @@ DiscMergerGCN::DiscMergerGCN(const SystemChar* outPath, DiscGCN& sourceDisc, FPr
: m_sourceDisc(sourceDisc), m_builder(sourceDisc.makeMergeBuilder(outPath, progressCB))
{}
bool DiscMergerGCN::mergeFromDirectory(const SystemChar* dirIn)
EBuildResult DiscMergerGCN::mergeFromDirectory(const SystemChar* dirIn)
{
if (!m_builder.getFileIO().beginWriteStream())
return false;
return EBuildResult::Failed;
if (!CheckFreeSpace(m_builder.m_outPath.c_str(), 0x57058000))
{
LogModule.report(logvisor::Error, _S("not enough free disk space for %s"), m_builder.m_outPath.c_str());
return false;
return EBuildResult::DiskFull;
}
m_builder.m_progressCB(m_builder.getProgressFactor(), _S("Preallocating image"), -1);
++m_builder.m_progressIdx;
m_builder.m_progressCB(m_builder.m_progressIdx, _S("Preallocating image"), -1);
auto ws = m_builder.m_fileIO->beginWriteStream(0x57058000 - 1);
if (!ws)
return false;
return EBuildResult::Failed;
ws->write("", 1);
PartitionBuilderGCN& pb = static_cast<PartitionBuilderGCN&>(*m_builder.m_partitions[0]);
return pb.mergeFromDirectory(static_cast<PartitionGCN*>(m_sourceDisc.getDataPartition()), dirIn);
return pb.mergeFromDirectory(static_cast<PartitionGCN*>(m_sourceDisc.getDataPartition()), dirIn) ?
EBuildResult::Success : EBuildResult::Failed;
}
uint64_t DiscMergerGCN::CalculateTotalSizeRequired(DiscGCN& sourceDisc, const SystemChar* dirIn)

View File

@ -928,7 +928,6 @@ public:
bool good = false;
uint64_t attempts = 0;
SystemString bfName(_S("Brute force attempts"));
++m_parent.m_progressIdx;
for (int w=0 ; w<7 ; ++w)
{
for (uint64_t i=0 ; i<UINT64_MAX ; ++i)
@ -943,12 +942,13 @@ public:
good = true;
break;
}
m_parent.m_progressCB(m_parent.m_progressIdx, bfName, attempts);
m_parent.m_progressCB(m_parent.getProgressFactor(), bfName, attempts);
}
if (good)
break;
}
m_parent.m_progressCB(m_parent.m_progressIdx, bfName, attempts);
m_parent.m_progressCB(m_parent.getProgressFactor(), bfName, attempts);
++m_parent.m_progressIdx;
ws = m_parent.getFileIO().beginWriteStream(m_baseOffset + 0x2C0);
if (!ws)
@ -994,7 +994,6 @@ public:
return false;
char buf[8192];
SystemString apploaderName(apploaderIn);
++m_parent.m_progressIdx;
while (true)
{
size_t rdSz = rs->read(buf, 8192);
@ -1008,8 +1007,9 @@ public:
"apploader flows into user area (one or the other is too big)");
return false;
}
m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderName, xferSz);
}
++m_parent.m_progressIdx;
return true;
}, phBuf.get(), phSz, theStat.st_size);
}
@ -1030,7 +1030,6 @@ public:
std::unique_ptr<uint8_t[]> apploaderBuf = partIn->getApploaderBuf();
size_t apploaderSz = partIn->getApploaderSize();
SystemString apploaderName(_S("<apploader>"));
++m_parent.m_progressIdx;
cws.write(apploaderBuf.get(), apploaderSz);
xferSz += apploaderSz;
if (0x2440 + xferSz >= 0x1F0000)
@ -1039,69 +1038,70 @@ public:
"apploader flows into user area (one or the other is too big)");
return false;
}
m_parent.m_progressCB(m_parent.m_progressIdx, apploaderName, xferSz);
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderName, xferSz);
++m_parent.m_progressIdx;
return true;
}, phBuf.get(), phSz, partIn->getApploaderSize());
}
};
bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn, const SystemChar* partHeadIn)
EBuildResult DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemChar* dolIn,
const SystemChar* apploaderIn, const SystemChar* partHeadIn)
{
PartitionBuilderWii& pb = static_cast<PartitionBuilderWii&>(*m_partitions[0]);
uint64_t filledSz = pb.m_baseOffset;
if (!m_fileIO->beginWriteStream())
return false;
return EBuildResult::Failed;
if (!CheckFreeSpace(m_outPath.c_str(), m_discCapacity))
{
LogModule.report(logvisor::Error, _S("not enough free disk space for %s"), m_outPath.c_str());
return false;
return EBuildResult::DiskFull;
}
m_progressCB(getProgressFactor(), _S("Preallocating image"), -1);
++m_progressIdx;
m_progressCB(m_progressIdx, _S("Preallocating image"), -1);
std::unique_ptr<IFileIO::IWriteStream> ws = m_fileIO->beginWriteStream(m_discCapacity - 1);
if (!ws)
return false;
return EBuildResult::Failed;
ws->write("", 1);
/* Assemble image */
filledSz = pb.buildFromDirectory(dirIn, dolIn, apploaderIn, partHeadIn);
if (filledSz == -1)
return false;
return EBuildResult::Failed;
else if (filledSz >= uint64_t(m_discCapacity))
{
LogModule.report(logvisor::Error, "data partition exceeds disc capacity");
return false;
return EBuildResult::Failed;
}
m_progressCB(getProgressFactor(), _S("Finishing Disc"), -1);
++m_progressIdx;
m_progressCB(m_progressIdx, _S("Finishing Disc"), -1);
/* Populate disc header */
ws = m_fileIO->beginWriteStream(0);
if (!ws)
return false;
return EBuildResult::Failed;
Header header(pb.getGameID(), pb.getGameTitle().c_str(), true, 0, 0, 0);
header.write(*ws);
/* Populate partition info */
ws = m_fileIO->beginWriteStream(0x40000);
if (!ws)
return false;
return EBuildResult::Failed;
uint32_t vals[2] = {SBig(uint32_t(1)), SBig(uint32_t(0x40020 >> uint64_t(2)))};
ws->write(vals, 8);
ws = m_fileIO->beginWriteStream(0x40020);
if (!ws)
return false;
return EBuildResult::Failed;
vals[0] = SBig(uint32_t(pb.m_baseOffset >> uint64_t(2)));
ws->write(vals, 4);
/* Populate region info */
ws = m_fileIO->beginWriteStream(0x4E000);
if (!ws)
return false;
return EBuildResult::Failed;
const char* gameID = pb.getGameID();
if (gameID[3] == 'P')
vals[0] = SBig(uint32_t(2));
@ -1114,14 +1114,14 @@ bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemCha
/* Make disc unrated */
ws = m_fileIO->beginWriteStream(0x4E010);
if (!ws)
return false;
return EBuildResult::Failed;
for (int i=0 ; i<16 ; ++i)
ws->write("\x80", 1);
/* Fill image to end */
ws = m_fileIO->beginWriteStream(filledSz);
if (!ws)
return false;
return EBuildResult::Failed;
uint8_t fillBuf[512];
memset(fillBuf, 0xff, 512);
for (size_t i=m_discCapacity-filledSz ; i>0 ;)
@ -1136,7 +1136,7 @@ bool DiscBuilderWii::buildFromDirectory(const SystemChar* dirIn, const SystemCha
break;
}
return true;
return EBuildResult::Success;
}
uint64_t DiscBuilderWii::CalculateTotalSizeRequired(const SystemChar* dirIn, const SystemChar* dolIn,
@ -1172,61 +1172,61 @@ DiscMergerWii::DiscMergerWii(const SystemChar* outPath, DiscWii& sourceDisc,
: m_sourceDisc(sourceDisc), m_builder(sourceDisc.makeMergeBuilder(outPath, dualLayer, progressCB))
{}
bool DiscMergerWii::mergeFromDirectory(const SystemChar* dirIn)
EBuildResult DiscMergerWii::mergeFromDirectory(const SystemChar* dirIn)
{
PartitionBuilderWii& pb = static_cast<PartitionBuilderWii&>(*m_builder.m_partitions[0]);
uint64_t filledSz = pb.m_baseOffset;
if (!m_builder.m_fileIO->beginWriteStream())
return false;
return EBuildResult::Failed;
if (!CheckFreeSpace(m_builder.m_outPath.c_str(), m_builder.m_discCapacity))
{
LogModule.report(logvisor::Error, _S("not enough free disk space for %s"), m_builder.m_outPath.c_str());
return false;
return EBuildResult::DiskFull;
}
m_builder.m_progressCB(m_builder.getProgressFactor(), _S("Preallocating image"), -1);
++m_builder.m_progressIdx;
m_builder.m_progressCB(m_builder.m_progressIdx, _S("Preallocating image"), -1);
std::unique_ptr<IFileIO::IWriteStream> ws = m_builder.m_fileIO->beginWriteStream(m_builder.m_discCapacity - 1);
if (!ws)
return false;
return EBuildResult::Failed;
ws->write("", 1);
/* Assemble image */
filledSz = pb.mergeFromDirectory(static_cast<PartitionWii*>(m_sourceDisc.getDataPartition()), dirIn);
if (filledSz == -1)
return false;
return EBuildResult::Failed;
else if (filledSz >= uint64_t(m_builder.m_discCapacity))
{
LogModule.report(logvisor::Error, "data partition exceeds disc capacity");
return false;
return EBuildResult::Failed;
}
m_builder.m_progressCB(m_builder.getProgressFactor(), _S("Finishing Disc"), -1);
++m_builder.m_progressIdx;
m_builder.m_progressCB(m_builder.m_progressIdx, _S("Finishing Disc"), -1);
/* Populate disc header */
ws = m_builder.m_fileIO->beginWriteStream(0);
if (!ws)
return false;
return EBuildResult::Failed;
m_sourceDisc.getHeader().write(*ws);
/* Populate partition info */
ws = m_builder.m_fileIO->beginWriteStream(0x40000);
if (!ws)
return false;
return EBuildResult::Failed;
uint32_t vals[2] = {SBig(uint32_t(1)), SBig(uint32_t(0x40020 >> uint64_t(2)))};
ws->write(vals, 8);
ws = m_builder.m_fileIO->beginWriteStream(0x40020);
if (!ws)
return false;
return EBuildResult::Failed;
vals[0] = SBig(uint32_t(pb.m_baseOffset >> uint64_t(2)));
ws->write(vals, 4);
/* Populate region info */
ws = m_builder.m_fileIO->beginWriteStream(0x4E000);
if (!ws)
return false;
return EBuildResult::Failed;
const char* gameID = pb.getGameID();
if (gameID[3] == 'P')
vals[0] = SBig(uint32_t(2));
@ -1239,14 +1239,14 @@ bool DiscMergerWii::mergeFromDirectory(const SystemChar* dirIn)
/* Make disc unrated */
ws = m_builder.m_fileIO->beginWriteStream(0x4E010);
if (!ws)
return false;
return EBuildResult::Failed;
for (int i=0 ; i<16 ; ++i)
ws->write("\x80", 1);
/* Fill image to end */
ws = m_builder.m_fileIO->beginWriteStream(filledSz);
if (!ws)
return false;
return EBuildResult::Failed;
uint8_t fillBuf[512];
memset(fillBuf, 0xff, 512);
for (size_t i=m_builder.m_discCapacity-filledSz ; i>0 ;)
@ -1261,7 +1261,7 @@ bool DiscMergerWii::mergeFromDirectory(const SystemChar* dirIn)
break;
}
return true;
return EBuildResult::Success;
}
uint64_t DiscMergerWii::CalculateTotalSizeRequired(DiscWii& sourceDisc,

View File

@ -83,29 +83,6 @@ public:
}
return fwrite(buf, 1, length, fp);
}
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{
uint64_t read = 0;
uint8_t buf[0x7c00];
while (length)
{
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz)
{
LogModule.report(logvisor::Error, "unable to read enough from disc");
return read;
}
if (write(buf, readSz) != readSz)
{
LogModule.report(logvisor::Error, "unable to write in file");
return read;
}
length -= thisSz;
read += thisSz;
}
return read;
}
};
std::unique_ptr<IWriteStream> beginWriteStream() const
{

View File

@ -95,29 +95,6 @@ public:
WriteFile(fp, buf, length, &ret, nullptr);
return ret;
}
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{
uint64_t read = 0;
uint8_t buf[0x7c00];
while (length)
{
uint64_t thisSz = nod::min(uint64_t(0x7c00), length);
uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz)
{
LogModule.report(logvisor::Error, "unable to read enough from disc");
return read;
}
if (write(buf, readSz) != readSz)
{
LogModule.report(logvisor::Error, "unable to write in file");
return read;
}
length -= thisSz;
read += thisSz;
}
return read;
}
};
std::unique_ptr<IWriteStream> beginWriteStream() const
{