working file extractor; removed hard-coded paths

This commit is contained in:
Jack Andersen 2015-06-30 09:38:51 -10:00
parent 293b7c0ce6
commit a1b2a262bf
13 changed files with 194 additions and 100 deletions

View File

@ -2,34 +2,53 @@
#include <string.h> #include <string.h>
#include "NODLib.hpp" #include "NODLib.hpp"
static void printHelp()
{
fprintf(stderr, "Usage:\n"
" nodlib extract [-f] <image-in> [<dir-out>]\n"
" nodlib make <dir-in> [<image-out>]\n");
}
int main(int argc, char* argv[]) int main(int argc, char* argv[])
{ {
if (argc < 2) if (argc < 3)
{ {
fprintf(stderr, "Usage: nodlib <image-in>\n"); printHelp();
return -1; return -1;
} }
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(argv[1]); const char* inDir = nullptr;
if (!disc) const char* outDir = ".";
return -1; bool force = false;
for (int a=2 ; a<argc ; ++a)
disc->extractToDirectory("/home/jacko/Desktop/TrilogyDump2");
const NOD::DiscBase::IPartition* dataPart = disc->getDataPartition();
if (dataPart)
{ {
for (const NOD::DiscBase::IPartition::Node& node : dataPart->getFSTRoot()) if (argv[a][0] == '-' && argv[a][1] == 'f')
{ force = true;
if (node.getKind() == NOD::DiscBase::IPartition::Node::NODE_FILE) else if (!inDir)
printf("FILE: %s\n", node.getName().c_str()); inDir = argv[a];
else if (node.getKind() == NOD::DiscBase::IPartition::Node::NODE_DIRECTORY) else
{ outDir = argv[a];
printf("DIR: %s\n", node.getName().c_str()); }
for (const NOD::DiscBase::IPartition::Node& subnode : node)
printf("SUBFILE: %s\n", subnode.getName().c_str()); if (!strcasecmp(argv[1], "extract"))
} {
} std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(inDir);
if (!disc)
return -1;
NOD::DiscBase::IPartition* dataPart = disc->getDataPartition();
if (!dataPart)
return -1;
dataPart->extractToDirectory(outDir, force);
}
else if (!strcasecmp(argv[1], "make"))
{
}
else
{
printHelp();
return -1;
} }
return 0; return 0;

View File

@ -5,6 +5,7 @@
#include <memory> #include <memory>
#include <string> #include <string>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include "Util.hpp" #include "Util.hpp"
#include "IDiscIO.hpp" #include "IDiscIO.hpp"
#include "IFileIO.hpp" #include "IFileIO.hpp"
@ -71,8 +72,8 @@ public:
Kind m_kind; Kind m_kind;
std::unique_ptr<IFileIO> m_hddFile; std::unique_ptr<IFileIO> m_hddFile;
size_t m_discOffset; uint64_t m_discOffset;
size_t m_discLength; uint64_t m_discLength;
std::string m_name; std::string m_name;
std::vector<Node>::iterator m_childrenBegin; std::vector<Node>::iterator m_childrenBegin;
@ -82,7 +83,7 @@ public:
Node(const IPartition& parent, const FSTNode& node, const char* name) Node(const IPartition& parent, const FSTNode& node, const char* name)
: m_parent(parent), : m_parent(parent),
m_kind(node.isDir() ? NODE_DIRECTORY : NODE_FILE), m_kind(node.isDir() ? NODE_DIRECTORY : NODE_FILE),
m_discOffset(node.getOffset()), m_discOffset(parent.normalizeOffset(node.getOffset())),
m_discLength(node.getLength()), m_discLength(node.getLength()),
m_name(name) {} m_name(name) {}
inline Kind getKind() const {return m_kind;} inline Kind getKind() const {return m_kind;}
@ -123,25 +124,31 @@ public:
void extractToDirectory(const std::string& basePath, bool force=false); void extractToDirectory(const std::string& basePath, bool force=false);
}; };
protected: protected:
uint32_t m_dolOff; uint64_t m_dolOff;
uint32_t m_fstOff; uint64_t m_fstOff;
uint32_t m_fstSz; uint64_t m_fstSz;
uint32_t m_apploaderOff; uint64_t m_apploaderSz;
std::vector<Node> m_nodes; std::vector<Node> m_nodes;
void parseFST(IPartReadStream& s); void parseFST(IPartReadStream& s);
const DiscBase& m_parent; const DiscBase& m_parent;
Kind m_kind; Kind m_kind;
size_t m_offset; uint64_t m_offset;
public: public:
IPartition(const DiscBase& parent, Kind kind, size_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;}
inline Kind getKind() const {return m_kind;} inline Kind getKind() const {return m_kind;}
virtual std::unique_ptr<IPartReadStream> beginReadStream(size_t offset=0) const=0; virtual std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset=0) const=0;
inline const Node& getFSTRoot() const {return m_nodes[0];} inline const Node& getFSTRoot() const {return m_nodes[0];}
inline Node& getFSTRoot() {return m_nodes[0];} inline Node& getFSTRoot() {return m_nodes[0];}
inline void extractToDirectory(const std::string& path, bool force=false) std::string pathOfNode(const Node& node);
{m_nodes[0].extractToDirectory(path, force);} void extractToDirectory(const std::string& path, bool force=false);
private:
bool _recursivePathOfNode(const std::string& basePath,
const Node& refNode,
const Node& curNode,
std::string& result);
}; };
protected: protected:
@ -153,14 +160,14 @@ public:
virtual bool commit()=0; virtual bool commit()=0;
inline const Header& getHeader() const {return m_header;} inline const Header& getHeader() const {return m_header;}
inline const IDiscIO& getDiscIO() const {return *m_discIO.get();} inline const IDiscIO& getDiscIO() const {return *m_discIO.get();}
inline const IPartition* getDataPartition() const inline IPartition* getDataPartition()
{ {
for (const std::unique_ptr<IPartition>& part : m_partitions) for (const std::unique_ptr<IPartition>& part : m_partitions)
if (part->getKind() == IPartition::PART_DATA) if (part->getKind() == IPartition::PART_DATA)
return part.get(); return part.get();
return nullptr; return nullptr;
} }
inline const IPartition* getUpdatePartition() const inline IPartition* getUpdatePartition()
{ {
for (const std::unique_ptr<IPartition>& part : m_partitions) for (const std::unique_ptr<IPartition>& part : m_partitions)
if (part->getKind() == IPartition::PART_UPDATE) if (part->getKind() == IPartition::PART_UPDATE)

View File

@ -4,6 +4,7 @@
#include <memory> #include <memory>
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
namespace NOD namespace NOD
{ {
@ -15,27 +16,27 @@ public:
struct IReadStream struct IReadStream
{ {
virtual size_t read(void* buf, size_t length)=0; virtual uint64_t read(void* buf, uint64_t length)=0;
virtual void seek(size_t offset, int whence=SEEK_SET)=0; virtual void seek(int64_t offset, int whence=SEEK_SET)=0;
}; };
virtual std::unique_ptr<IReadStream> beginReadStream(size_t offset=0) const=0; virtual std::unique_ptr<IReadStream> beginReadStream(uint64_t offset=0) const=0;
struct IWriteStream struct IWriteStream
{ {
virtual size_t write(void* buf, size_t length)=0; virtual uint64_t write(void* buf, uint64_t length)=0;
}; };
virtual std::unique_ptr<IWriteStream> beginWriteStream(size_t offset=0) const=0; virtual std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset=0) const=0;
}; };
struct IPartReadStream struct IPartReadStream
{ {
virtual void seek(size_t offset, int whence=SEEK_SET)=0; virtual void seek(int64_t offset, int whence=SEEK_SET)=0;
virtual size_t read(void* buf, size_t length)=0; virtual uint64_t read(void* buf, uint64_t length)=0;
}; };
struct IPartWriteStream struct IPartWriteStream
{ {
virtual size_t write(void* buf, size_t length)=0; virtual uint64_t write(void* buf, uint64_t length)=0;
}; };
} }

View File

@ -12,25 +12,27 @@ class IFileIO
{ {
public: public:
virtual ~IFileIO() {} virtual ~IFileIO() {}
virtual size_t size()=0; virtual uint64_t size()=0;
struct IWriteStream struct IWriteStream
{ {
virtual ~IWriteStream() {} virtual ~IWriteStream() {}
virtual size_t copyFromDisc(struct IPartReadStream& discio, size_t length)=0; virtual uint64_t write(void* buf, uint64_t length)=0;
virtual uint64_t copyFromDisc(struct IPartReadStream& discio, uint64_t length)=0;
}; };
virtual std::unique_ptr<IWriteStream> beginWriteStream() const=0; virtual std::unique_ptr<IWriteStream> beginWriteStream() const=0;
struct IReadStream struct IReadStream
{ {
virtual ~IReadStream() {} virtual ~IReadStream() {}
virtual size_t copyToDisc(struct IPartWriteStream& discio, size_t length)=0; virtual uint64_t read(void* buf, uint64_t length)=0;
virtual uint64_t copyToDisc(struct IPartWriteStream& discio, uint64_t length)=0;
}; };
virtual std::unique_ptr<IReadStream> beginReadStream() const=0; virtual std::unique_ptr<IReadStream> beginReadStream() const=0;
}; };
std::unique_ptr<IFileIO> NewFileIO(const std::string& path); std::unique_ptr<IFileIO> NewFileIO(const std::string& path);
std::unique_ptr<IFileIO> NewMemIO(void* buf, size_t size); std::unique_ptr<IFileIO> NewMemIO(void* buf, uint64_t size);
} }

View File

@ -11,8 +11,8 @@ namespace NOD
class IAES class IAES
{ {
public: public:
virtual void encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)=0; virtual void encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0;
virtual void decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len)=0; virtual void decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)=0;
virtual void setKey(const uint8_t* key)=0; virtual void setKey(const uint8_t* key)=0;
}; };

View File

@ -2,6 +2,10 @@
#include "DiscBase.hpp" #include "DiscBase.hpp"
#include "IFileIO.hpp" #include "IFileIO.hpp"
#ifndef _WIN32
#include <unistd.h>
#endif
namespace NOD namespace NOD
{ {
@ -52,8 +56,8 @@ void DiscBase::IPartition::Node::extractToDirectory(const std::string& basePath,
{ {
if (mkdir(path.c_str(), 0755) && errno != EEXIST) if (mkdir(path.c_str(), 0755) && errno != EEXIST)
throw std::runtime_error("unable to mkdir '" + path + "'"); throw std::runtime_error("unable to mkdir '" + path + "'");
for (DiscBase::IPartition::Node& subnode : *this) for (Node& subnode : *this)
subnode.extractToDirectory(path); subnode.extractToDirectory(path, force);
} }
else if (m_kind == NODE_FILE) else if (m_kind == NODE_FILE)
{ {
@ -68,4 +72,52 @@ void DiscBase::IPartition::Node::extractToDirectory(const std::string& basePath,
} }
} }
bool DiscBase::IPartition::_recursivePathOfNode(const std::string& basePath,
const Node& refNode,
const Node& curNode,
std::string& result)
{
std::string path = basePath + "/" + curNode.getName();
if (&refNode == &curNode)
{
result = path;
return true;
}
else if (curNode.m_kind == Node::NODE_DIRECTORY)
{
for (const Node& subnode : curNode)
if (_recursivePathOfNode(path, refNode, subnode, result))
break;
}
return false;
}
std::string DiscBase::IPartition::pathOfNode(const Node& node)
{
std::string result;
_recursivePathOfNode("", node, m_nodes[0], result);
return result;
}
void DiscBase::IPartition::extractToDirectory(const std::string& path, bool force)
{
struct stat theStat;
if (mkdir(path.c_str(), 0755) && errno != EEXIST)
throw std::runtime_error("unable to mkdir '" + path + "'");
/* Extract Apploader */
std::string apploaderPath = path + "/apploader.bin";
if (force || stat(apploaderPath.c_str(), &theStat))
{
std::unique_ptr<uint8_t[]> buf(new uint8_t[m_apploaderSz]);
std::unique_ptr<IPartReadStream> rs = beginReadStream(0x2440);
rs->read(buf.get(), m_apploaderSz);
std::unique_ptr<IFileIO::IWriteStream> ws = NewFileIO(path + "/apploader.bin")->beginWriteStream();
ws->write(buf.get(), m_apploaderSz);
}
/* Extract Filesystem */
m_nodes[0].extractToDirectory(path, force);
}
} }

View File

@ -6,7 +6,7 @@ namespace NOD
class PartitionGCN : public DiscBase::IPartition class PartitionGCN : public DiscBase::IPartition
{ {
public: public:
PartitionGCN(const DiscGCN& parent, Kind kind, size_t offset) PartitionGCN(const DiscGCN& parent, Kind kind, uint64_t offset)
: IPartition(parent, kind, offset) : IPartition(parent, kind, offset)
{ {
/* GCN-specific header reads */ /* GCN-specific header reads */
@ -16,6 +16,9 @@ public:
m_dolOff = SBig(vals[0]); m_dolOff = SBig(vals[0]);
m_fstOff = SBig(vals[1]); m_fstOff = SBig(vals[1]);
m_fstSz = SBig(vals[2]); m_fstSz = SBig(vals[2]);
s->seek(0x2440 + 0x14);
s->read(vals, 8);
m_apploaderSz = SBig(vals[0]) + SBig(vals[1]);
/* Yay files!! */ /* Yay files!! */
parseFST(*s.get()); parseFST(*s.get());
@ -27,16 +30,16 @@ public:
std::unique_ptr<IDiscIO::IReadStream> m_dio; std::unique_ptr<IDiscIO::IReadStream> m_dio;
public: public:
PartReadStream(const PartitionGCN& parent, size_t offset) PartReadStream(const PartitionGCN& parent, uint64_t offset)
: m_parent(parent) : m_parent(parent)
{m_dio = m_parent.m_parent.getDiscIO().beginReadStream(offset);} {m_dio = m_parent.m_parent.getDiscIO().beginReadStream(offset);}
void seek(size_t offset, int whence) void seek(int64_t offset, int whence)
{m_dio->seek(offset, whence);} {m_dio->seek(offset, whence);}
size_t read(void* buf, size_t length) uint64_t read(void* buf, uint64_t length)
{return m_dio->read(buf, length);} {return m_dio->read(buf, length);}
}; };
std::unique_ptr<IPartReadStream> beginReadStream(size_t offset) const std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset) const
{ {
return std::unique_ptr<IPartReadStream>(new PartReadStream(*this, offset)); return std::unique_ptr<IPartReadStream>(new PartReadStream(*this, offset));
} }

View File

@ -20,12 +20,12 @@ public:
: fp(fpin) {} : fp(fpin) {}
~ReadStream() {fclose(fp);} ~ReadStream() {fclose(fp);}
public: public:
size_t read(void* buf, size_t length) uint64_t read(void* buf, uint64_t length)
{return fread(buf, 1, length, fp);} {return fread(buf, 1, length, fp);}
void seek(size_t offset, int whence) void seek(int64_t offset, int whence)
{fseek(fp, offset, whence);} {fseeko(fp, offset, whence);}
}; };
std::unique_ptr<IReadStream> beginReadStream(size_t offset) const std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{ {
FILE* fp = fopen(filepath.c_str(), "rb"); FILE* fp = fopen(filepath.c_str(), "rb");
if (!fp) if (!fp)
@ -33,7 +33,7 @@ public:
throw std::runtime_error("Unable to open '" + filepath + "' for reading"); throw std::runtime_error("Unable to open '" + filepath + "' for reading");
return std::unique_ptr<IReadStream>(); return std::unique_ptr<IReadStream>();
} }
fseek(fp, offset, SEEK_SET); fseeko(fp, offset, SEEK_SET);
return std::unique_ptr<IReadStream>(new ReadStream(fp)); return std::unique_ptr<IReadStream>(new ReadStream(fp));
} }
@ -45,10 +45,10 @@ public:
: fp(fpin) {} : fp(fpin) {}
~WriteStream() {fclose(fp);} ~WriteStream() {fclose(fp);}
public: public:
size_t write(void* buf, size_t length) uint64_t write(void* buf, uint64_t length)
{return fwrite(buf, 1, length, fp);} {return fwrite(buf, 1, length, fp);}
}; };
std::unique_ptr<IWriteStream> beginWriteStream(size_t offset) const std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{ {
FILE* fp = fopen(filepath.c_str(), "wb"); FILE* fp = fopen(filepath.c_str(), "wb");
if (!fp) if (!fp)
@ -56,7 +56,7 @@ public:
throw std::runtime_error("Unable to open '" + filepath + "' for writing"); throw std::runtime_error("Unable to open '" + filepath + "' for writing");
return std::unique_ptr<IWriteStream>(); return std::unique_ptr<IWriteStream>();
} }
fseek(fp, offset, SEEK_SET); fseeko(fp, offset, SEEK_SET);
return std::unique_ptr<IWriteStream>(new WriteStream(fp)); return std::unique_ptr<IWriteStream>(new WriteStream(fp));
} }
}; };

View File

@ -20,12 +20,12 @@ public:
: fp(fpin) {} : fp(fpin) {}
~ReadStream() {fclose(fp);} ~ReadStream() {fclose(fp);}
public: public:
size_t read(void* buf, size_t length) uint64_t read(void* buf, uint64_t length)
{return fread(buf, 1, length, fp);} {return fread(buf, 1, length, fp);}
void seek(size_t offset, int whence) void seek(int64_t offset, int whence)
{fseek(fp, offset, whence);} {fseeko(fp, offset, whence);}
}; };
std::unique_ptr<IReadStream> beginReadStream(size_t offset) const std::unique_ptr<IReadStream> beginReadStream(uint64_t offset) const
{ {
FILE* fp = fopen(filepath.c_str(), "rb"); FILE* fp = fopen(filepath.c_str(), "rb");
if (!fp) if (!fp)
@ -33,7 +33,7 @@ public:
throw std::runtime_error("Unable to open '" + filepath + "' for reading"); throw std::runtime_error("Unable to open '" + filepath + "' for reading");
return std::unique_ptr<IReadStream>(); return std::unique_ptr<IReadStream>();
} }
fseek(fp, offset, SEEK_SET); fseeko(fp, offset, SEEK_SET);
return std::unique_ptr<IReadStream>(new ReadStream(fp)); return std::unique_ptr<IReadStream>(new ReadStream(fp));
} }
@ -45,10 +45,10 @@ public:
: fp(fpin) {} : fp(fpin) {}
~WriteStream() {fclose(fp);} ~WriteStream() {fclose(fp);}
public: public:
size_t write(void* buf, size_t length) uint64_t write(void* buf, uint64_t length)
{return fwrite(buf, 1, length, fp);} {return fwrite(buf, 1, length, fp);}
}; };
std::unique_ptr<IWriteStream> beginWriteStream(size_t offset) const std::unique_ptr<IWriteStream> beginWriteStream(uint64_t offset) const
{ {
FILE* fp = fopen(filepath.c_str(), "wb"); FILE* fp = fopen(filepath.c_str(), "wb");
if (!fp) if (!fp)
@ -56,7 +56,7 @@ public:
throw std::runtime_error("Unable to open '" + filepath + "' for writing"); throw std::runtime_error("Unable to open '" + filepath + "' for writing");
return std::unique_ptr<IWriteStream>(); return std::unique_ptr<IWriteStream>();
} }
fseek(fp, offset, SEEK_SET); fseeko(fp, offset, SEEK_SET);
return std::unique_ptr<IWriteStream>(new WriteStream(fp)); return std::unique_ptr<IWriteStream>(new WriteStream(fp));
} }
}; };

View File

@ -6,6 +6,7 @@
namespace NOD namespace NOD
{ {
/* Not much of a secret anymore I suppose */
static const uint8_t COMMON_KEY[] = {0xeb, 0xe4, 0x2a, 0x22, static const uint8_t COMMON_KEY[] = {0xeb, 0xe4, 0x2a, 0x22,
0x5e, 0x85, 0x93, 0xe4, 0x5e, 0x85, 0x93, 0xe4,
0x48, 0xd9, 0xc5, 0x45, 0x48, 0xd9, 0xc5, 0x45,
@ -124,7 +125,7 @@ class PartitionWii : public DiscBase::IPartition
titleVersion = SBig(titleVersion); titleVersion = SBig(titleVersion);
numContents = SBig(numContents); numContents = SBig(numContents);
bootIdx = SBig(bootIdx); bootIdx = SBig(bootIdx);
for (size_t c=0 ; c<numContents ; ++c) for (uint16_t c=0 ; c<numContents ; ++c)
{ {
contents.emplace_back(); contents.emplace_back();
contents.back().read(s); contents.back().read(s);
@ -175,11 +176,11 @@ class PartitionWii : public DiscBase::IPartition
Certificate m_tmdCert; Certificate m_tmdCert;
Certificate m_ticketCert; Certificate m_ticketCert;
size_t m_dataOff; uint64_t m_dataOff;
uint8_t m_decKey[16]; uint8_t m_decKey[16];
public: public:
PartitionWii(const DiscWii& parent, Kind kind, size_t offset) PartitionWii(const DiscWii& parent, Kind kind, uint64_t offset)
: IPartition(parent, kind, offset) : IPartition(parent, kind, offset)
{ {
std::unique_ptr<IDiscIO::IReadStream> s = parent.getDiscIO().beginReadStream(offset); std::unique_ptr<IDiscIO::IReadStream> s = parent.getDiscIO().beginReadStream(offset);
@ -233,6 +234,9 @@ public:
m_dolOff = SBig(vals[0]) << 2; m_dolOff = SBig(vals[0]) << 2;
m_fstOff = SBig(vals[1]) << 2; m_fstOff = SBig(vals[1]) << 2;
m_fstSz = SBig(vals[2]) << 2; m_fstSz = SBig(vals[2]) << 2;
ds->seek(0x2440 + 0x14);
ds->read(vals, 8);
m_apploaderSz = SBig(vals[0]) + SBig(vals[1]);
/* Yay files!! */ /* Yay files!! */
parseFST(*ds.get()); parseFST(*ds.get());
@ -242,8 +246,8 @@ public:
{ {
std::unique_ptr<IAES> m_aes; std::unique_ptr<IAES> m_aes;
const PartitionWii& m_parent; const PartitionWii& m_parent;
size_t m_baseOffset; uint64_t m_baseOffset;
size_t m_offset; uint64_t m_offset;
std::unique_ptr<IDiscIO::IReadStream> m_dio; std::unique_ptr<IDiscIO::IReadStream> m_dio;
size_t m_curBlock = SIZE_MAX; size_t m_curBlock = SIZE_MAX;
@ -256,7 +260,7 @@ public:
m_aes->decrypt(&m_encBuf[0x3d0], &m_encBuf[0x400], m_decBuf, 0x7c00); m_aes->decrypt(&m_encBuf[0x3d0], &m_encBuf[0x400], m_decBuf, 0x7c00);
} }
public: public:
PartReadStream(const PartitionWii& parent, size_t baseOffset, size_t offset) PartReadStream(const PartitionWii& parent, uint64_t baseOffset, uint64_t offset)
: m_aes(NewAES()), m_parent(parent), m_baseOffset(baseOffset), m_offset(offset) : m_aes(NewAES()), m_parent(parent), m_baseOffset(baseOffset), m_offset(offset)
{ {
m_aes->setKey(parent.m_decKey); m_aes->setKey(parent.m_decKey);
@ -265,7 +269,7 @@ public:
decryptBlock(); decryptBlock();
m_curBlock = block; m_curBlock = block;
} }
void seek(size_t offset, int whence) void seek(int64_t offset, int whence)
{ {
if (whence == SEEK_SET) if (whence == SEEK_SET)
m_offset = offset; m_offset = offset;
@ -281,11 +285,11 @@ public:
m_curBlock = block; m_curBlock = block;
} }
} }
size_t read(void* buf, size_t length) uint64_t read(void* buf, uint64_t length)
{ {
size_t block = m_offset / 0x7c00; size_t block = m_offset / 0x7c00;
size_t cacheOffset = m_offset % 0x7c00; size_t cacheOffset = m_offset % 0x7c00;
size_t cacheSize; uint64_t cacheSize;
uint8_t* dst = (uint8_t*)buf; uint8_t* dst = (uint8_t*)buf;
while (length) while (length)
@ -312,10 +316,12 @@ public:
} }
}; };
std::unique_ptr<IPartReadStream> beginReadStream(size_t offset) const std::unique_ptr<IPartReadStream> beginReadStream(uint64_t offset) const
{ {
return std::unique_ptr<IPartReadStream>(new PartReadStream(*this, m_dataOff, offset)); return std::unique_ptr<IPartReadStream>(new PartReadStream(*this, m_dataOff, offset));
} }
uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset << 2;}
}; };
DiscWii::DiscWii(std::unique_ptr<IDiscIO>&& dio) DiscWii::DiscWii(std::unique_ptr<IDiscIO>&& dio)

View File

@ -18,13 +18,13 @@ public:
FileIOFILE(const std::string& path) FileIOFILE(const std::string& path)
: m_path(path) {} : m_path(path) {}
size_t size() uint64_t size()
{ {
FILE* fp = fopen(m_path.c_str(), "rb"); FILE* fp = fopen(m_path.c_str(), "rb");
if (!fp) if (!fp)
return 0; return 0;
fseek(fp, 0, SEEK_END); fseeko(fp, 0, SEEK_END);
size_t result = ftell(fp); uint64_t result = ftello(fp);
fclose(fp); fclose(fp);
return result; return result;
} }
@ -40,13 +40,15 @@ public:
throw std::runtime_error("unable to open '" + path + "' for writing"); throw std::runtime_error("unable to open '" + path + "' for writing");
} }
~WriteStream() {fclose(fp);} ~WriteStream() {fclose(fp);}
size_t copyFromDisc(IPartReadStream& discio, size_t length) uint64_t write(void* buf, uint64_t length)
{return fwrite(buf, 1, length, fp);}
uint64_t copyFromDisc(IPartReadStream& discio, uint64_t length)
{ {
size_t read = 0; uint64_t read = 0;
while (length) while (length)
{ {
size_t thisSz = MIN(0x7c00, length); uint64_t thisSz = MIN(0x7c00, length);
size_t readSz = discio.read(buf, thisSz); uint64_t readSz = discio.read(buf, thisSz);
if (thisSz != readSz) if (thisSz != readSz)
throw std::runtime_error("unable to read enough from disc"); throw std::runtime_error("unable to read enough from disc");
if (fwrite(buf, 1, readSz, fp) != readSz) if (fwrite(buf, 1, readSz, fp) != readSz)
@ -71,12 +73,14 @@ public:
throw std::runtime_error("unable to open '" + path + "' for reading"); throw std::runtime_error("unable to open '" + path + "' for reading");
} }
~ReadStream() {fclose(fp);} ~ReadStream() {fclose(fp);}
size_t copyToDisc(IPartWriteStream& discio, size_t length) uint64_t read(void* buf, uint64_t length)
{return fread(buf, 1, length, fp);}
uint64_t copyToDisc(IPartWriteStream& discio, uint64_t length)
{ {
size_t written = 0; uint64_t written = 0;
while (length) while (length)
{ {
size_t thisSz = MIN(0x7c00, length); uint64_t thisSz = MIN(0x7c00, length);
if (fread(buf, 1, thisSz, fp) != thisSz) if (fread(buf, 1, thisSz, fp) != thisSz)
throw std::runtime_error("unable to read enough from file"); throw std::runtime_error("unable to read enough from file");
if (discio.write(buf, thisSz) != thisSz) if (discio.write(buf, thisSz) != thisSz)

View File

@ -29,7 +29,7 @@ std::unique_ptr<DiscBase> OpenDiscFromImage(const char* path, bool& isWii)
} }
else else
{ {
fseek(fp, 0x18, SEEK_SET); fseeko(fp, 0x18, SEEK_SET);
fread(&magic, 1, 4, fp); fread(&magic, 1, 4, fp);
magic = NOD::SBig(magic); magic = NOD::SBig(magic);
if (magic == 0x5D1C9EA3) if (magic == 0x5D1C9EA3)

View File

@ -76,8 +76,8 @@ protected:
void _decrypt(uint8_t* buff); void _decrypt(uint8_t* buff);
public: public:
void encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len); void encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len);
void decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len); void decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len);
void setKey(const uint8_t* key); void setKey(const uint8_t* key);
}; };
@ -440,7 +440,7 @@ void SoftwareAES::decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, si
} }
// CBC mode encryption // CBC mode encryption
void SoftwareAES::encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) void SoftwareAES::encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)
{ {
uint8_t block[16]; uint8_t block[16];
unsigned int blockno = 0, i; unsigned int blockno = 0, i;
@ -485,10 +485,10 @@ class NiAES : public IAES
__m128i m_ekey[11]; __m128i m_ekey[11];
__m128i m_dkey[11]; __m128i m_dkey[11];
public: public:
void encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) void encrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)
{ {
__m128i feedback,data; __m128i feedback,data;
size_t i,j; uint64_t i,j;
if (len%16) if (len%16)
len = len/16+1; len = len/16+1;
else else
@ -505,10 +505,10 @@ public:
_mm_storeu_si128(&((__m128i*)outbuf)[i], feedback); _mm_storeu_si128(&((__m128i*)outbuf)[i], feedback);
} }
} }
void decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, size_t len) void decrypt(uint8_t* iv, const uint8_t* inbuf, uint8_t* outbuf, uint64_t len)
{ {
__m128i data,feedback,last_in; __m128i data,feedback,last_in;
size_t i,j; uint64_t i,j;
if (len%16) if (len%16)
len = len/16+1; len = len/16+1;
else else