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

View File

@ -15,7 +15,14 @@
namespace nod 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 class FSTNode
{ {
@ -237,6 +244,18 @@ public:
uint64_t m_offset; uint64_t m_offset;
public: public:
mutable size_t m_curNodeIdx = 0; 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) IPartition(const DiscBase& parent, Kind kind, uint64_t offset)
: m_parent(parent), m_kind(kind), m_offset(offset) {} : m_parent(parent), m_kind(kind), m_offset(offset) {}
virtual uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset;} virtual uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset;}
@ -342,18 +361,25 @@ public:
size_t m_buildNameOff = 0; size_t m_buildNameOff = 0;
virtual uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws)=0; virtual uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws)=0;
virtual uint32_t packOffset(uint64_t offset) const=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 recursiveBuildNodes(IPartWriteStream& ws, bool system, const SystemChar* dirIn, uint64_t dolInode);
bool recursiveBuildFST(const SystemChar* dirIn, uint64_t dolInode, bool recursiveBuildFST(const SystemChar* dirIn, uint64_t dolInode,
std::function<void(void)> incParents); std::function<void(void)> incParents);
void recursiveMergeNodesPre(const DiscBase::IPartition::Node* nodeIn, const SystemChar* dirIn);
bool recursiveMergeNodes(IPartWriteStream& ws, bool system, bool recursiveMergeNodes(IPartWriteStream& ws, bool system,
const DiscBase::IPartition::Node* nodeIn, const SystemChar* dirIn, const DiscBase::IPartition::Node* nodeIn, const SystemChar* dirIn,
const SystemString& keyPath); const SystemString& keyPath);
bool recursiveMergeFST(const DiscBase::IPartition::Node* nodeIn, bool recursiveMergeFST(const DiscBase::IPartition::Node* nodeIn,
const SystemChar* dirIn, std::function<void(void)> incParents, const SystemChar* dirIn, std::function<void(void)> incParents,
const SystemString& keyPath); const SystemString& keyPath);
static bool RecursiveCalculateTotalSize(uint64_t& totalSz, static bool RecursiveCalculateTotalSize(uint64_t& totalSz,
const DiscBase::IPartition::Node* nodeIn, const DiscBase::IPartition::Node* nodeIn,
const SystemChar* dirIn); const SystemChar* dirIn);
void addBuildName(const SystemString& str) void addBuildName(const SystemString& str)
{ {
SystemUTF8View utf8View(str); SystemUTF8View utf8View(str);
@ -396,11 +422,26 @@ protected:
std::vector<std::unique_ptr<PartitionBuilderBase>> m_partitions; std::vector<std::unique_ptr<PartitionBuilderBase>> m_partitions;
int64_t m_discCapacity; int64_t m_discCapacity;
public: public:
std::function<void(size_t idx, const SystemString&, size_t)> m_progressCB; FProgress m_progressCB;
size_t m_progressIdx = 0; 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; virtual ~DiscBuilderBase() = default;
DiscBuilderBase(const SystemChar* outPath, int64_t discCapacity, DiscBuilderBase(const SystemChar* outPath, int64_t discCapacity, FProgress progressCB)
std::function<void(size_t idx, const SystemString&, size_t)> progressCB)
: m_outPath(outPath), m_fileIO(NewFileIO(outPath, discCapacity)), : m_outPath(outPath), m_fileIO(NewFileIO(outPath, discCapacity)),
m_discCapacity(discCapacity), m_progressCB(progressCB) {} m_discCapacity(discCapacity), m_progressCB(progressCB) {}
DiscBuilderBase(DiscBuilderBase&&) = default; DiscBuilderBase(DiscBuilderBase&&) = default;

View File

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

View File

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

View File

@ -20,7 +20,55 @@ public:
{ {
virtual ~IWriteStream() {} virtual ~IWriteStream() {}
virtual uint64_t write(const void* buf, uint64_t length)=0; 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() const=0;
virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) 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; ++m_parent.m_curNodeIdx;
if (ctx.verbose && ctx.progressCB && !getName().empty()) 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) if (Mkdir(path.c_str(), 0755) && errno != EEXIST)
{ {
LogModule.report(logvisor::Error, _S("unable to mkdir '%s'"), path.c_str()); 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) else if (m_kind == Kind::File)
{ {
Sstat theStat; Sstat theStat;
++m_parent.m_curNodeIdx;
if (ctx.verbose && ctx.progressCB) 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)) 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(); std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(path)->beginWriteStream();
if (!rs || !ws) if (!rs || !ws)
return false; 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; return true;
} }
@ -263,6 +268,26 @@ static size_t PatchDOL(IFileIO::IReadStream& in, IPartWriteStream& out, size_t s
return out.write(buf.get(), sz); 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 DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream& ws,
bool system, bool system,
const SystemChar* dirIn, const SystemChar* dirIn,
@ -299,12 +324,12 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildNodes(IPartWriteStream
{ {
bool patched; bool patched;
xferSz = PatchDOL(*rs, ws, e.m_fileSz, 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 else
{ {
char buf[0x8000]; char buf[0x8000];
++m_parent.m_progressIdx;
while (xferSz < e.m_fileSz) while (xferSz < e.m_fileSz)
{ {
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000ul), e.m_fileSz - xferSz)); 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; break;
ws.write(buf, rdSz); ws.write(buf, rdSz);
xferSz += 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) for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1); ws.write("\xff", 1);
@ -358,6 +384,64 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveBuildFST(const SystemChar*
return true; 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 DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream& ws,
bool system, bool system,
const DiscBase::IPartition::Node* nodeIn, const DiscBase::IPartition::Node* nodeIn,
@ -426,13 +510,13 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
{ {
bool patched; bool patched;
xferSz = PatchDOL(*rs, ws, e.m_fileSz, 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); (patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
} }
else else
{ {
char buf[0x8000]; char buf[0x8000];
++m_parent.m_progressIdx;
while (xferSz < e.m_fileSz) while (xferSz < e.m_fileSz)
{ {
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000ul), e.m_fileSz - xferSz)); 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; break;
ws.write(buf, rdSz); ws.write(buf, rdSz);
xferSz += 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) for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1); ws.write("\xff", 1);
@ -486,13 +571,13 @@ bool DiscBuilderBase::PartitionBuilderBase::recursiveMergeNodes(IPartWriteStream
bool patched; bool patched;
PatchDOL(dolBuf, xferSz, patched); PatchDOL(dolBuf, xferSz, patched);
ws.write(dolBuf.get(), xferSz); 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); (patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
} }
else else
{ {
char buf[0x8000]; char buf[0x8000];
++m_parent.m_progressIdx;
while (xferSz < ch.size()) while (xferSz < ch.size())
{ {
size_t rdSz = rs->read(buf, nod::min(size_t(0x8000), size_t(ch.size() - xferSz))); 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; break;
ws.write(buf, rdSz); ws.write(buf, rdSz);
xferSz += 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) for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1); ws.write("\xff", 1);
@ -689,9 +775,14 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
return false; 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 */ /* Clear file */
m_parent.m_progressCB(m_parent.getProgressFactor(), _S("Preparing output image"), -1);
++m_parent.m_progressIdx; ++m_parent.m_progressIdx;
m_parent.m_progressCB(m_parent.m_progressIdx, _S("Preparing output image"), -1);
/* Add root node */ /* Add root node */
m_buildNodes.emplace_back(true, m_buildNameOff, 0, 1); m_buildNodes.emplace_back(true, m_buildNameOff, 0, 1);
@ -716,14 +807,14 @@ bool DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(IPartWriteStream&
return false; return false;
bool patched; bool patched;
size_t xferSz = PatchDOL(*rs, ws, dolStat.st_size, 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); (patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
for (size_t i=0 ; i<fileSz-xferSz ; ++i) for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1); ws.write("\xff", 1);
} }
/* Gather files in root directory */ /* Gather files in root directory */
uint64_t dolInode = GetInode(dolIn);
if (!recursiveBuildNodes(ws, true, dirIn, dolInode)) if (!recursiveBuildNodes(ws, true, dirIn, dolInode))
return false; return false;
if (!recursiveBuildNodes(ws, false, dirIn, dolInode)) if (!recursiveBuildNodes(ws, false, dirIn, dolInode))
@ -759,9 +850,13 @@ bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream&
return false; return false;
} }
/* 1st pass - Tally up total progress steps */
m_parent.m_progressTotal += 2; /* Prep and DOL */
recursiveMergeNodesPre(&partIn->getFSTRoot(), dirIn);
/* Clear file */ /* Clear file */
m_parent.m_progressCB(m_parent.getProgressFactor(), _S("Preparing output image"), -1);
++m_parent.m_progressIdx; ++m_parent.m_progressIdx;
m_parent.m_progressCB(m_parent.m_progressIdx, _S("Preparing output image"), -1);
/* Add root node */ /* Add root node */
m_buildNodes.emplace_back(true, m_buildNameOff, 0, 1); m_buildNodes.emplace_back(true, m_buildNameOff, 0, 1);
@ -780,8 +875,9 @@ bool DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(IPartWriteStream&
bool patched; bool patched;
PatchDOL(dolBuf, xferSz, patched); PatchDOL(dolBuf, xferSz, patched);
ws.write(dolBuf.get(), xferSz); 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); (patched ? _S(" [PATCHED]") : _S("")), xferSz);
++m_parent.m_progressIdx;
for (size_t i=0 ; i<fileSz-xferSz ; ++i) for (size_t i=0 ; i<fileSz-xferSz ; ++i)
ws.write("\xff", 1); ws.write("\xff", 1);
} }

View File

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

View File

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

View File

@ -83,29 +83,6 @@ public:
} }
return fwrite(buf, 1, length, fp); 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 std::unique_ptr<IWriteStream> beginWriteStream() const
{ {

View File

@ -95,29 +95,6 @@ public:
WriteFile(fp, buf, length, &ret, nullptr); WriteFile(fp, buf, length, &ret, nullptr);
return ret; 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 std::unique_ptr<IWriteStream> beginWriteStream() const
{ {