2016-03-04 23:04:30 +00:00
|
|
|
#include "nod/DiscGCN.hpp"
|
2019-08-30 07:52:22 +00:00
|
|
|
|
2017-12-29 07:57:54 +00:00
|
|
|
#include <cinttypes>
|
2019-08-30 07:52:22 +00:00
|
|
|
#include <cstddef>
|
|
|
|
#include <cstdint>
|
|
|
|
#include <memory>
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
#include "nod/nod.hpp"
|
|
|
|
#include "nod/Util.hpp"
|
|
|
|
|
|
|
|
#include <logvisor/logvisor.hpp>
|
|
|
|
|
2015-07-14 02:24:17 +00:00
|
|
|
#define BUFFER_SZ 0x8000
|
2015-06-28 05:43:53 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
namespace nod {
|
2015-06-28 05:43:53 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
class PartitionGCN : public IPartition {
|
2015-06-30 00:07:46 +00:00
|
|
|
public:
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
PartitionGCN(const DiscGCN& parent, uint64_t offset, bool& err, Codepage_t codepage)
|
|
|
|
: IPartition(parent, PartitionKind::Data, false, offset, codepage) {
|
2018-12-08 05:21:47 +00:00
|
|
|
/* GCN-specific header reads */
|
|
|
|
std::unique_ptr<IPartReadStream> s = beginReadStream(0x0);
|
|
|
|
if (!s) {
|
|
|
|
err = true;
|
|
|
|
return;
|
2015-06-30 00:07:46 +00:00
|
|
|
}
|
2018-12-08 05:21:47 +00:00
|
|
|
m_header.read(*s);
|
|
|
|
m_bi2Header.read(*s);
|
|
|
|
m_dolOff = m_header.m_dolOff;
|
|
|
|
m_fstOff = m_header.m_fstOff;
|
|
|
|
m_fstSz = m_header.m_fstSz;
|
|
|
|
uint32_t vals[2];
|
|
|
|
s->seek(0x2440 + 0x14);
|
|
|
|
s->read(vals, 8);
|
|
|
|
m_apploaderSz = 32 + SBig(vals[0]) + SBig(vals[1]);
|
|
|
|
|
|
|
|
/* Yay files!! */
|
|
|
|
parseFST(*s);
|
|
|
|
|
|
|
|
/* Also make DOL header and size handy */
|
|
|
|
s->seek(m_dolOff);
|
|
|
|
parseDOL(*s);
|
|
|
|
}
|
|
|
|
|
|
|
|
class PartReadStream : public IPartReadStream {
|
|
|
|
const PartitionGCN& m_parent;
|
|
|
|
std::unique_ptr<IReadStream> m_dio;
|
|
|
|
|
|
|
|
uint64_t m_offset;
|
|
|
|
size_t m_curBlock = SIZE_MAX;
|
|
|
|
uint8_t m_buf[BUFFER_SZ];
|
|
|
|
|
|
|
|
public:
|
|
|
|
PartReadStream(const PartitionGCN& parent, uint64_t offset, bool& err) : m_parent(parent), m_offset(offset) {
|
|
|
|
size_t block = m_offset / BUFFER_SZ;
|
|
|
|
m_dio = m_parent.m_parent.getDiscIO().beginReadStream(block * BUFFER_SZ);
|
|
|
|
if (!m_dio) {
|
|
|
|
err = true;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
m_dio->read(m_buf, BUFFER_SZ);
|
|
|
|
m_curBlock = block;
|
|
|
|
}
|
2019-08-10 05:41:41 +00:00
|
|
|
void seek(int64_t offset, int whence) override {
|
2018-12-08 05:21:47 +00:00
|
|
|
if (whence == SEEK_SET)
|
|
|
|
m_offset = offset;
|
|
|
|
else if (whence == SEEK_CUR)
|
|
|
|
m_offset += offset;
|
|
|
|
else
|
|
|
|
return;
|
|
|
|
size_t block = m_offset / BUFFER_SZ;
|
|
|
|
if (block != m_curBlock) {
|
|
|
|
m_dio->seek(block * BUFFER_SZ);
|
|
|
|
m_dio->read(m_buf, BUFFER_SZ);
|
|
|
|
m_curBlock = block;
|
|
|
|
}
|
|
|
|
}
|
2019-08-10 05:41:41 +00:00
|
|
|
uint64_t position() const override { return m_offset; }
|
|
|
|
uint64_t read(void* buf, uint64_t length) override {
|
2018-12-08 05:21:47 +00:00
|
|
|
size_t block = m_offset / BUFFER_SZ;
|
|
|
|
size_t cacheOffset = m_offset % BUFFER_SZ;
|
|
|
|
uint64_t cacheSize;
|
|
|
|
uint64_t rem = length;
|
|
|
|
uint8_t* dst = (uint8_t*)buf;
|
|
|
|
|
|
|
|
while (rem) {
|
|
|
|
if (block != m_curBlock) {
|
|
|
|
m_dio->read(m_buf, BUFFER_SZ);
|
|
|
|
m_curBlock = block;
|
2015-07-14 02:24:17 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
cacheSize = rem;
|
|
|
|
if (cacheSize + cacheOffset > BUFFER_SZ)
|
|
|
|
cacheSize = BUFFER_SZ - cacheOffset;
|
|
|
|
|
|
|
|
memmove(dst, m_buf + cacheOffset, cacheSize);
|
|
|
|
dst += cacheSize;
|
|
|
|
rem -= cacheSize;
|
|
|
|
cacheOffset = 0;
|
|
|
|
++block;
|
|
|
|
}
|
|
|
|
|
|
|
|
m_offset += length;
|
|
|
|
return dst - (uint8_t*)buf;
|
2015-06-30 00:07:46 +00:00
|
|
|
}
|
2018-12-08 05:21:47 +00:00
|
|
|
};
|
|
|
|
|
2019-08-10 05:41:41 +00:00
|
|
|
std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset) const override {
|
2019-08-30 09:02:35 +00:00
|
|
|
bool err = false;
|
|
|
|
auto ret = std::make_unique<PartReadStream>(*this, offset, err);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
2015-06-30 00:07:46 +00:00
|
|
|
};
|
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
DiscGCN::DiscGCN(std::unique_ptr<IDiscIO>&& dio, bool& err, Codepage_t codepage) : DiscBase(std::move(dio), err) {
|
2018-12-08 05:21:47 +00:00
|
|
|
if (err)
|
|
|
|
return;
|
2017-02-05 06:19:34 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
/* One lone partition for GCN */
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
m_partitions.emplace_back(std::make_unique<PartitionGCN>(*this, 0, err, codepage));
|
2017-02-05 06:19:34 +00:00
|
|
|
}
|
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
DiscBuilderGCN DiscGCN::makeMergeBuilder(SystemStringView outPath, FProgress progressCB, Codepage_t codepage) {
|
|
|
|
return DiscBuilderGCN(outPath, progressCB, codepage);
|
2017-07-01 23:36:16 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
bool DiscGCN::extractDiscHeaderFiles(SystemStringView path, const ExtractionContext& ctx) const { return true; }
|
2015-06-28 05:43:53 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
class PartitionBuilderGCN : public DiscBuilderBase::PartitionBuilderBase {
|
|
|
|
uint64_t m_curUser = 0x57058000;
|
2016-01-25 02:00:02 +00:00
|
|
|
|
2016-01-21 06:30:37 +00:00
|
|
|
public:
|
2018-12-08 05:21:47 +00:00
|
|
|
class PartWriteStream : public IPartWriteStream {
|
|
|
|
const PartitionBuilderGCN& m_parent;
|
|
|
|
uint64_t m_offset;
|
|
|
|
std::unique_ptr<IFileIO::IWriteStream> m_fio;
|
|
|
|
|
|
|
|
public:
|
|
|
|
PartWriteStream(const PartitionBuilderGCN& parent, uint64_t offset, bool& err)
|
|
|
|
: m_parent(parent), m_offset(offset) {
|
|
|
|
m_fio = m_parent.m_parent.getFileIO().beginWriteStream(offset);
|
|
|
|
if (!m_fio)
|
|
|
|
err = true;
|
2016-01-21 06:30:37 +00:00
|
|
|
}
|
2019-08-10 05:41:41 +00:00
|
|
|
void close() override { m_fio.reset(); }
|
|
|
|
uint64_t position() const override { return m_offset; }
|
|
|
|
uint64_t write(const void* buf, uint64_t length) override {
|
2018-12-08 05:21:47 +00:00
|
|
|
uint64_t len = m_fio->write(buf, length);
|
|
|
|
m_offset += len;
|
|
|
|
return len;
|
2016-01-22 23:45:58 +00:00
|
|
|
}
|
2018-12-08 05:21:47 +00:00
|
|
|
void seek(size_t off) {
|
|
|
|
m_offset = off;
|
|
|
|
m_fio = m_parent.m_parent.getFileIO().beginWriteStream(off);
|
2016-01-25 02:00:02 +00:00
|
|
|
}
|
2018-12-08 05:21:47 +00:00
|
|
|
};
|
2016-01-25 02:00:02 +00:00
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
PartitionBuilderGCN(DiscBuilderBase& parent, Codepage_t codepage)
|
|
|
|
: DiscBuilderBase::PartitionBuilderBase(parent, PartitionKind::Data, false, codepage) {}
|
2016-01-21 06:30:37 +00:00
|
|
|
|
2019-08-10 05:41:41 +00:00
|
|
|
uint64_t userAllocate(uint64_t reqSz, IPartWriteStream& ws) override {
|
2018-12-08 05:21:47 +00:00
|
|
|
m_curUser -= reqSz;
|
|
|
|
m_curUser &= 0xfffffffffffffff0;
|
|
|
|
if (m_curUser < 0x30000) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING("user area low mark reached"));
|
2018-12-08 05:21:47 +00:00
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
static_cast<PartWriteStream&>(ws).seek(m_curUser);
|
|
|
|
return m_curUser;
|
|
|
|
}
|
|
|
|
|
2019-08-10 05:41:41 +00:00
|
|
|
uint32_t packOffset(uint64_t offset) const override { return offset; }
|
2018-12-08 05:21:47 +00:00
|
|
|
|
2019-08-10 05:41:41 +00:00
|
|
|
std::unique_ptr<IPartWriteStream> beginWriteStream(uint64_t offset) override {
|
2019-08-30 09:02:35 +00:00
|
|
|
bool err = false;
|
|
|
|
auto ret = std::make_unique<PartWriteStream>(*this, offset, err);
|
|
|
|
|
|
|
|
if (err) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool
|
|
|
|
_build(const std::function<bool(IPartWriteStream&, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t)>& headerFunc,
|
|
|
|
const std::function<bool(IPartWriteStream&)>& bi2Func,
|
|
|
|
const std::function<bool(IPartWriteStream&, size_t&)>& apploaderFunc) {
|
|
|
|
std::unique_ptr<IPartWriteStream> ws = beginWriteStream(0x2440);
|
|
|
|
if (!ws)
|
|
|
|
return false;
|
|
|
|
size_t xferSz = 0;
|
|
|
|
if (!apploaderFunc(*ws, xferSz))
|
|
|
|
return false;
|
|
|
|
|
|
|
|
size_t fstOff = ROUND_UP_32(xferSz);
|
|
|
|
size_t fstSz = sizeof(FSTNode) * m_buildNodes.size();
|
|
|
|
for (size_t i = 0; i < fstOff - xferSz; ++i)
|
|
|
|
ws->write("\xff", 1);
|
|
|
|
fstOff += 0x2440;
|
|
|
|
ws->write(m_buildNodes.data(), fstSz);
|
|
|
|
for (const std::string& str : m_buildNames)
|
|
|
|
ws->write(str.data(), str.size() + 1);
|
|
|
|
fstSz += m_buildNameOff;
|
|
|
|
fstSz = ROUND_UP_32(fstSz);
|
|
|
|
|
|
|
|
if (fstOff + fstSz >= m_curUser) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING("FST flows into user area (one or the other is too big)"));
|
2018-12-08 05:21:47 +00:00
|
|
|
return false;
|
2016-01-21 06:30:37 +00:00
|
|
|
}
|
2017-02-05 06:19:34 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
ws = beginWriteStream(0);
|
|
|
|
if (!ws)
|
|
|
|
return false;
|
|
|
|
if (!headerFunc(*ws, m_dolOffset, fstOff, fstSz, m_curUser, 0x57058000 - m_curUser))
|
|
|
|
return false;
|
|
|
|
if (!bi2Func(*ws))
|
|
|
|
return false;
|
2017-02-05 06:19:34 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
return true;
|
|
|
|
}
|
|
|
|
|
|
|
|
bool buildFromDirectory(SystemStringView dirIn) {
|
|
|
|
std::unique_ptr<IPartWriteStream> ws = beginWriteStream(0);
|
|
|
|
if (!ws)
|
|
|
|
return false;
|
|
|
|
bool result = DiscBuilderBase::PartitionBuilderBase::buildFromDirectory(*ws, dirIn);
|
|
|
|
if (!result)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
SystemString dirStr(dirIn);
|
|
|
|
|
|
|
|
/* Check Apploader */
|
|
|
|
SystemString apploaderIn = dirStr + _SYS_STR("/sys/apploader.img");
|
|
|
|
Sstat apploaderStat;
|
|
|
|
if (Stat(apploaderIn.c_str(), &apploaderStat)) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {}")), apploaderIn);
|
2018-12-08 05:21:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-07-01 23:36:16 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
/* Check Boot */
|
|
|
|
SystemString bootIn = dirStr + _SYS_STR("/sys/boot.bin");
|
|
|
|
Sstat bootStat;
|
|
|
|
if (Stat(bootIn.c_str(), &bootStat)) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {}")), bootIn);
|
2018-12-08 05:21:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-07-01 23:36:16 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
/* Check BI2 */
|
|
|
|
SystemString bi2In = dirStr + _SYS_STR("/sys/bi2.bin");
|
|
|
|
Sstat bi2Stat;
|
|
|
|
if (Stat(bi2In.c_str(), &bi2Stat)) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("unable to stat {}")), bi2In);
|
2018-12-08 05:21:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
2017-07-01 23:36:16 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
return _build(
|
|
|
|
[&bootIn](IPartWriteStream& ws, uint32_t dolOff, uint32_t fstOff, uint32_t fstSz, uint32_t userOff,
|
|
|
|
uint32_t userSz) -> bool {
|
|
|
|
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(bootIn.c_str())->beginReadStream();
|
|
|
|
if (!rs)
|
2018-07-06 07:02:23 +00:00
|
|
|
return false;
|
2018-12-08 05:21:47 +00:00
|
|
|
Header header;
|
|
|
|
header.read(*rs);
|
|
|
|
header.m_dolOff = dolOff;
|
|
|
|
header.m_fstOff = fstOff;
|
|
|
|
header.m_fstSz = fstSz;
|
|
|
|
header.m_fstMaxSz = fstSz;
|
|
|
|
header.m_userPosition = userOff;
|
|
|
|
header.m_userSz = userSz;
|
|
|
|
header.write(ws);
|
|
|
|
return true;
|
2017-07-01 23:36:16 +00:00
|
|
|
},
|
2018-12-08 05:21:47 +00:00
|
|
|
[&bi2In](IPartWriteStream& ws) -> bool {
|
|
|
|
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(bi2In.c_str())->beginReadStream();
|
|
|
|
if (!rs)
|
|
|
|
return false;
|
|
|
|
BI2Header bi2;
|
|
|
|
bi2.read(*rs);
|
|
|
|
bi2.write(ws);
|
|
|
|
return true;
|
2017-07-01 23:36:16 +00:00
|
|
|
},
|
2018-12-08 05:21:47 +00:00
|
|
|
[this, &apploaderIn](IPartWriteStream& ws, size_t& xferSz) -> bool {
|
|
|
|
std::unique_ptr<IFileIO::IReadStream> rs = NewFileIO(apploaderIn.c_str())->beginReadStream();
|
|
|
|
if (!rs)
|
|
|
|
return false;
|
|
|
|
char buf[8192];
|
|
|
|
while (true) {
|
|
|
|
size_t rdSz = rs->read(buf, 8192);
|
|
|
|
if (!rdSz)
|
|
|
|
break;
|
|
|
|
ws.write(buf, rdSz);
|
|
|
|
xferSz += rdSz;
|
|
|
|
if (0x2440 + xferSz >= m_curUser) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING("apploader flows into user area (one or the other is too big)"));
|
2018-12-08 05:21:47 +00:00
|
|
|
return false;
|
2017-02-05 06:19:34 +00:00
|
|
|
}
|
2018-12-08 05:21:47 +00:00
|
|
|
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderIn, xferSz);
|
|
|
|
}
|
|
|
|
++m_parent.m_progressIdx;
|
|
|
|
return true;
|
2017-02-05 06:19:34 +00:00
|
|
|
});
|
2018-12-08 05:21:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
bool mergeFromDirectory(const PartitionGCN* partIn, SystemStringView dirIn) {
|
|
|
|
std::unique_ptr<IPartWriteStream> ws = beginWriteStream(0);
|
|
|
|
if (!ws)
|
|
|
|
return false;
|
|
|
|
bool result = DiscBuilderBase::PartitionBuilderBase::mergeFromDirectory(*ws, partIn, dirIn);
|
|
|
|
if (!result)
|
|
|
|
return false;
|
|
|
|
|
|
|
|
return _build(
|
|
|
|
[partIn](IPartWriteStream& ws, uint32_t dolOff, uint32_t fstOff, uint32_t fstSz, uint32_t userOff,
|
|
|
|
uint32_t userSz) -> bool {
|
|
|
|
Header header = partIn->getHeader();
|
|
|
|
header.m_dolOff = dolOff;
|
|
|
|
header.m_fstOff = fstOff;
|
|
|
|
header.m_fstSz = fstSz;
|
|
|
|
header.m_fstMaxSz = fstSz;
|
|
|
|
header.m_userPosition = userOff;
|
|
|
|
header.m_userSz = userSz;
|
|
|
|
header.write(ws);
|
|
|
|
return true;
|
2017-07-01 23:36:16 +00:00
|
|
|
},
|
2018-12-08 05:21:47 +00:00
|
|
|
[partIn](IPartWriteStream& ws) -> bool {
|
|
|
|
partIn->getBI2().write(ws);
|
|
|
|
return true;
|
2017-07-01 23:36:16 +00:00
|
|
|
},
|
2018-12-08 05:21:47 +00:00
|
|
|
[this, partIn](IPartWriteStream& ws, size_t& xferSz) -> bool {
|
|
|
|
std::unique_ptr<uint8_t[]> apploaderBuf = partIn->getApploaderBuf();
|
|
|
|
size_t apploaderSz = partIn->getApploaderSize();
|
|
|
|
SystemString apploaderName(_SYS_STR("<apploader>"));
|
|
|
|
ws.write(apploaderBuf.get(), apploaderSz);
|
|
|
|
xferSz += apploaderSz;
|
|
|
|
if (0x2440 + xferSz >= m_curUser) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING("apploader flows into user area (one or the other is too big)"));
|
2018-12-08 05:21:47 +00:00
|
|
|
return false;
|
|
|
|
}
|
|
|
|
m_parent.m_progressCB(m_parent.getProgressFactor(), apploaderName, xferSz);
|
|
|
|
++m_parent.m_progressIdx;
|
|
|
|
return true;
|
2017-02-05 06:19:34 +00:00
|
|
|
});
|
2018-12-08 05:21:47 +00:00
|
|
|
}
|
2016-01-21 06:30:37 +00:00
|
|
|
};
|
2016-01-20 03:17:24 +00:00
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
EBuildResult DiscBuilderGCN::buildFromDirectory(SystemStringView dirIn) {
|
|
|
|
if (!m_fileIO->beginWriteStream())
|
|
|
|
return EBuildResult::Failed;
|
|
|
|
if (!CheckFreeSpace(m_outPath.c_str(), 0x57058000)) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("not enough free disk space for {}")), m_outPath);
|
2018-12-08 05:21:47 +00:00
|
|
|
return EBuildResult::DiskFull;
|
|
|
|
}
|
|
|
|
m_progressCB(getProgressFactor(), _SYS_STR("Preallocating image"), -1);
|
|
|
|
++m_progressIdx;
|
|
|
|
{
|
|
|
|
auto ws = m_fileIO->beginWriteStream(0);
|
|
|
|
if (!ws)
|
|
|
|
return EBuildResult::Failed;
|
|
|
|
char zeroBytes[1024] = {};
|
|
|
|
for (uint64_t i = 0; i < 0x57058000; i += 1024)
|
|
|
|
ws->write(zeroBytes, 1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
PartitionBuilderGCN& pb = static_cast<PartitionBuilderGCN&>(*m_partitions[0]);
|
|
|
|
return pb.buildFromDirectory(dirIn) ? EBuildResult::Success : EBuildResult::Failed;
|
2016-01-21 06:30:37 +00:00
|
|
|
}
|
2016-01-20 03:17:24 +00:00
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
std::optional<uint64_t> DiscBuilderGCN::CalculateTotalSizeRequired(SystemStringView dirIn, Codepage_t codepage) {
|
|
|
|
std::optional<uint64_t> sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeBuild(dirIn, PartitionKind::Data, false, codepage);
|
2018-07-21 04:03:59 +00:00
|
|
|
if (!sz)
|
|
|
|
return sz;
|
|
|
|
*sz += 0x30000;
|
2018-12-08 05:21:47 +00:00
|
|
|
if (sz > 0x57058000) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("disc capacity exceeded [{} / {}]")), *sz, 0x57058000);
|
2018-07-21 04:03:59 +00:00
|
|
|
return std::nullopt;
|
2018-12-08 05:21:47 +00:00
|
|
|
}
|
|
|
|
return sz;
|
2017-02-05 06:19:34 +00:00
|
|
|
}
|
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
DiscBuilderGCN::DiscBuilderGCN(SystemStringView outPath, FProgress progressCB, Codepage_t codepage)
|
2018-12-08 05:21:47 +00:00
|
|
|
: DiscBuilderBase(outPath, 0x57058000, progressCB) {
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
m_partitions.emplace_back(std::make_unique<PartitionBuilderGCN>(*this, codepage));
|
2015-06-28 05:43:53 +00:00
|
|
|
}
|
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
DiscMergerGCN::DiscMergerGCN(SystemStringView outPath, DiscGCN& sourceDisc, FProgress progressCB, Codepage_t codepage)
|
|
|
|
: m_sourceDisc(sourceDisc), m_builder(sourceDisc.makeMergeBuilder(outPath, progressCB, codepage)) {}
|
2018-12-08 05:21:47 +00:00
|
|
|
|
|
|
|
EBuildResult DiscMergerGCN::mergeFromDirectory(SystemStringView dirIn) {
|
|
|
|
if (!m_builder.getFileIO().beginWriteStream())
|
|
|
|
return EBuildResult::Failed;
|
|
|
|
if (!CheckFreeSpace(m_builder.m_outPath.c_str(), 0x57058000)) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("not enough free disk space for {}")), m_builder.m_outPath);
|
2018-12-08 05:21:47 +00:00
|
|
|
return EBuildResult::DiskFull;
|
|
|
|
}
|
|
|
|
m_builder.m_progressCB(m_builder.getProgressFactor(), _SYS_STR("Preallocating image"), -1);
|
|
|
|
++m_builder.m_progressIdx;
|
|
|
|
{
|
|
|
|
auto ws = m_builder.m_fileIO->beginWriteStream(0);
|
|
|
|
if (!ws)
|
|
|
|
return EBuildResult::Failed;
|
|
|
|
char zeroBytes[1024] = {};
|
|
|
|
for (uint64_t i = 0; i < 0x57058000; i += 1024)
|
|
|
|
ws->write(zeroBytes, 1024);
|
|
|
|
}
|
|
|
|
|
|
|
|
PartitionBuilderGCN& pb = static_cast<PartitionBuilderGCN&>(*m_builder.m_partitions[0]);
|
|
|
|
return pb.mergeFromDirectory(static_cast<PartitionGCN*>(m_sourceDisc.getDataPartition()), dirIn)
|
|
|
|
? EBuildResult::Success
|
|
|
|
: EBuildResult::Failed;
|
2017-02-05 06:19:34 +00:00
|
|
|
}
|
|
|
|
|
The Encoding Update
While Nintendo's own documents claim GameCube and Wii disc file symbol tables only support 7-bit ASCII, this is far from the truth. Indeed, even some first-party Nintendo games shipped with Shift-JIS encoded file symbol tables. My guess? The locale of whatever Windows machine mastered a GameCube or Wii disc influenced how wide character strings (UCS-2) were converted to narrow character strings. To account for all possibilites, this update adds extensible multi-byte character set options to NOD-Tool.
A rundown of notable changes:
- "-c XXXXX" option added to set the encoding of the GameCube / Wii ISO(s) being processed.
- "SystemStringConv" renamed to "DiscLocToSystemConv"
- "SystemUTF8Conv" renamed to "SystemToDiscLocConv"
- Help message updated with new info.
- Bugfix: AddBuildName had a logic error wherein the length of the SystemString was being used instead of length of the disc locale string. This would corrupt the File Symbol Table if the disc locale string's length was greater than the SystemString's length.
- Bugfix: recursiveMergeFST was not keeping track of parent indexes at all, meaning nested folders and their contents would be corrupted. I simply copied the way recursiveBuildFST did things to fix this.
- Bugfix (Windows): On Windows, for some reason, Sstat was a typedef for _stat (32-bit) instead of _stat64 (64-bit). This is confounding, because untrimmed Wii ISOs will always be larger than the unsigned 32-bit integer limit (4,699,979,776 bytes vs 4,294,967,295 bytes), meaning the MergeWii errand has never worked for untrimmed ISOs on Windows. Was this never tested??
- Bugfix (Windows): Did you know Windows Command Prompt fully supports Unicode? Stdio streams are now in _O_U16TEXT mode for Windows only. Previously, attempting to print any character that could not be narrowed to your locale's encoding would either silently fail (std functions), or throw an exception (fmt functions). As a minor drawback, narrow character print functions can no longer be used when stdio is in _O_U16TEXT mode, necessitating my PR for Logvisor here: (AxioDL/logvisor#7)
- ExtractionContext::progressCB now uses SystemStringView because widechar printing works correctly on Windows now.
- progFunc lambda no longer throws exceptions when printing unicode because widechar printing works correctly on Windows now.
- Top-level constructors and functions with a Codepage_t parameter have also signatures that default to the US-ASCII codepage.
- DiscGCN constructor
- DiscBuilderGCN constructor
- DiscBuilderGCN::CalculateTotalSizeRequired
- DiscMergerGCN constructor
- DiscMergerGCN::CalculateTotalSizeRequired
- DiscWii constructor
- DiscBuilderWii constructor
- DiscBuilderWii::CalculateTotalSizeRequired
- DiscMergerWii constructor
- DiscMergerWii::CalculateTotalSizeRequired
- OpenDiscFromImage
- Conversion between system encoding and disc locale encoding has checks in place to warn the user if string conversion goes awry.
2021-06-27 08:26:20 +00:00
|
|
|
std::optional<uint64_t> DiscMergerGCN::CalculateTotalSizeRequired(DiscGCN& sourceDisc, SystemStringView dirIn, Codepage_t codepage) {
|
|
|
|
std::optional<uint64_t> sz = DiscBuilderBase::PartitionBuilderBase::CalculateTotalSizeMerge(sourceDisc.getDataPartition(), dirIn, codepage);
|
2018-07-21 04:03:59 +00:00
|
|
|
if (!sz)
|
|
|
|
return std::nullopt;
|
|
|
|
*sz += 0x30000;
|
2018-12-08 05:21:47 +00:00
|
|
|
if (sz > 0x57058000) {
|
2020-04-11 22:45:06 +00:00
|
|
|
LogModule.report(logvisor::Error, FMT_STRING(_SYS_STR("disc capacity exceeded [{} / {}]")), *sz, 0x57058000);
|
2018-07-21 04:03:59 +00:00
|
|
|
return std::nullopt;
|
2018-12-08 05:21:47 +00:00
|
|
|
}
|
|
|
|
return sz;
|
2017-02-05 06:19:34 +00:00
|
|
|
}
|
|
|
|
|
2018-12-08 05:21:47 +00:00
|
|
|
} // namespace nod
|