mirror of https://github.com/AxioDL/nod.git
working file extractor; removed hard-coded paths
This commit is contained in:
parent
293b7c0ce6
commit
a1b2a262bf
|
@ -2,34 +2,53 @@
|
|||
#include <string.h>
|
||||
#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[])
|
||||
{
|
||||
if (argc < 2)
|
||||
if (argc < 3)
|
||||
{
|
||||
fprintf(stderr, "Usage: nodlib <image-in>\n");
|
||||
printHelp();
|
||||
return -1;
|
||||
}
|
||||
|
||||
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(argv[1]);
|
||||
const char* inDir = nullptr;
|
||||
const char* outDir = ".";
|
||||
bool force = false;
|
||||
for (int a=2 ; a<argc ; ++a)
|
||||
{
|
||||
if (argv[a][0] == '-' && argv[a][1] == 'f')
|
||||
force = true;
|
||||
else if (!inDir)
|
||||
inDir = argv[a];
|
||||
else
|
||||
outDir = argv[a];
|
||||
}
|
||||
|
||||
if (!strcasecmp(argv[1], "extract"))
|
||||
{
|
||||
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(inDir);
|
||||
if (!disc)
|
||||
return -1;
|
||||
|
||||
disc->extractToDirectory("/home/jacko/Desktop/TrilogyDump2");
|
||||
NOD::DiscBase::IPartition* dataPart = disc->getDataPartition();
|
||||
if (!dataPart)
|
||||
return -1;
|
||||
|
||||
const NOD::DiscBase::IPartition* dataPart = disc->getDataPartition();
|
||||
if (dataPart)
|
||||
{
|
||||
for (const NOD::DiscBase::IPartition::Node& node : dataPart->getFSTRoot())
|
||||
{
|
||||
if (node.getKind() == NOD::DiscBase::IPartition::Node::NODE_FILE)
|
||||
printf("FILE: %s\n", node.getName().c_str());
|
||||
else if (node.getKind() == NOD::DiscBase::IPartition::Node::NODE_DIRECTORY)
|
||||
{
|
||||
printf("DIR: %s\n", node.getName().c_str());
|
||||
for (const NOD::DiscBase::IPartition::Node& subnode : node)
|
||||
printf("SUBFILE: %s\n", subnode.getName().c_str());
|
||||
dataPart->extractToDirectory(outDir, force);
|
||||
}
|
||||
else if (!strcasecmp(argv[1], "make"))
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
printHelp();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -5,6 +5,7 @@
|
|||
#include <memory>
|
||||
#include <string>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include "Util.hpp"
|
||||
#include "IDiscIO.hpp"
|
||||
#include "IFileIO.hpp"
|
||||
|
@ -71,8 +72,8 @@ public:
|
|||
Kind m_kind;
|
||||
|
||||
std::unique_ptr<IFileIO> m_hddFile;
|
||||
size_t m_discOffset;
|
||||
size_t m_discLength;
|
||||
uint64_t m_discOffset;
|
||||
uint64_t m_discLength;
|
||||
std::string m_name;
|
||||
|
||||
std::vector<Node>::iterator m_childrenBegin;
|
||||
|
@ -82,7 +83,7 @@ public:
|
|||
Node(const IPartition& parent, const FSTNode& node, const char* name)
|
||||
: m_parent(parent),
|
||||
m_kind(node.isDir() ? NODE_DIRECTORY : NODE_FILE),
|
||||
m_discOffset(node.getOffset()),
|
||||
m_discOffset(parent.normalizeOffset(node.getOffset())),
|
||||
m_discLength(node.getLength()),
|
||||
m_name(name) {}
|
||||
inline Kind getKind() const {return m_kind;}
|
||||
|
@ -123,25 +124,31 @@ public:
|
|||
void extractToDirectory(const std::string& basePath, bool force=false);
|
||||
};
|
||||
protected:
|
||||
uint32_t m_dolOff;
|
||||
uint32_t m_fstOff;
|
||||
uint32_t m_fstSz;
|
||||
uint32_t m_apploaderOff;
|
||||
uint64_t m_dolOff;
|
||||
uint64_t m_fstOff;
|
||||
uint64_t m_fstSz;
|
||||
uint64_t m_apploaderSz;
|
||||
std::vector<Node> m_nodes;
|
||||
void parseFST(IPartReadStream& s);
|
||||
|
||||
const DiscBase& m_parent;
|
||||
Kind m_kind;
|
||||
size_t m_offset;
|
||||
uint64_t m_offset;
|
||||
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) {}
|
||||
virtual uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset;}
|
||||
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 Node& getFSTRoot() {return m_nodes[0];}
|
||||
inline void extractToDirectory(const std::string& path, bool force=false)
|
||||
{m_nodes[0].extractToDirectory(path, force);}
|
||||
std::string pathOfNode(const Node& node);
|
||||
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:
|
||||
|
@ -153,14 +160,14 @@ public:
|
|||
virtual bool commit()=0;
|
||||
inline const Header& getHeader() const {return m_header;}
|
||||
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)
|
||||
if (part->getKind() == IPartition::PART_DATA)
|
||||
return part.get();
|
||||
return nullptr;
|
||||
}
|
||||
inline const IPartition* getUpdatePartition() const
|
||||
inline IPartition* getUpdatePartition()
|
||||
{
|
||||
for (const std::unique_ptr<IPartition>& part : m_partitions)
|
||||
if (part->getKind() == IPartition::PART_UPDATE)
|
||||
|
|
|
@ -4,6 +4,7 @@
|
|||
#include <memory>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace NOD
|
||||
{
|
||||
|
@ -15,27 +16,27 @@ public:
|
|||
|
||||
struct IReadStream
|
||||
{
|
||||
virtual size_t read(void* buf, size_t length)=0;
|
||||
virtual void seek(size_t offset, int whence=SEEK_SET)=0;
|
||||
virtual uint64_t read(void* buf, uint64_t length)=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
|
||||
{
|
||||
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
|
||||
{
|
||||
virtual void seek(size_t offset, int whence=SEEK_SET)=0;
|
||||
virtual size_t read(void* buf, size_t length)=0;
|
||||
virtual void seek(int64_t offset, int whence=SEEK_SET)=0;
|
||||
virtual uint64_t read(void* buf, uint64_t length)=0;
|
||||
};
|
||||
|
||||
struct IPartWriteStream
|
||||
{
|
||||
virtual size_t write(void* buf, size_t length)=0;
|
||||
virtual uint64_t write(void* buf, uint64_t length)=0;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -12,25 +12,27 @@ class IFileIO
|
|||
{
|
||||
public:
|
||||
virtual ~IFileIO() {}
|
||||
virtual size_t size()=0;
|
||||
virtual uint64_t size()=0;
|
||||
|
||||
struct 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;
|
||||
|
||||
struct 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;
|
||||
};
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -11,8 +11,8 @@ namespace NOD
|
|||
class IAES
|
||||
{
|
||||
public:
|
||||
virtual void encrypt(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, 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, uint64_t len)=0;
|
||||
virtual void setKey(const uint8_t* key)=0;
|
||||
};
|
||||
|
||||
|
|
|
@ -2,6 +2,10 @@
|
|||
#include "DiscBase.hpp"
|
||||
#include "IFileIO.hpp"
|
||||
|
||||
#ifndef _WIN32
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
namespace NOD
|
||||
{
|
||||
|
||||
|
@ -52,8 +56,8 @@ void DiscBase::IPartition::Node::extractToDirectory(const std::string& basePath,
|
|||
{
|
||||
if (mkdir(path.c_str(), 0755) && errno != EEXIST)
|
||||
throw std::runtime_error("unable to mkdir '" + path + "'");
|
||||
for (DiscBase::IPartition::Node& subnode : *this)
|
||||
subnode.extractToDirectory(path);
|
||||
for (Node& subnode : *this)
|
||||
subnode.extractToDirectory(path, force);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@ namespace NOD
|
|||
class PartitionGCN : public DiscBase::IPartition
|
||||
{
|
||||
public:
|
||||
PartitionGCN(const DiscGCN& parent, Kind kind, size_t offset)
|
||||
PartitionGCN(const DiscGCN& parent, Kind kind, uint64_t offset)
|
||||
: IPartition(parent, kind, offset)
|
||||
{
|
||||
/* GCN-specific header reads */
|
||||
|
@ -16,6 +16,9 @@ public:
|
|||
m_dolOff = SBig(vals[0]);
|
||||
m_fstOff = SBig(vals[1]);
|
||||
m_fstSz = SBig(vals[2]);
|
||||
s->seek(0x2440 + 0x14);
|
||||
s->read(vals, 8);
|
||||
m_apploaderSz = SBig(vals[0]) + SBig(vals[1]);
|
||||
|
||||
/* Yay files!! */
|
||||
parseFST(*s.get());
|
||||
|
@ -27,16 +30,16 @@ public:
|
|||
std::unique_ptr<IDiscIO::IReadStream> m_dio;
|
||||
|
||||
public:
|
||||
PartReadStream(const PartitionGCN& parent, size_t offset)
|
||||
PartReadStream(const PartitionGCN& parent, uint64_t offset)
|
||||
: m_parent(parent)
|
||||
{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);}
|
||||
size_t read(void* buf, size_t length)
|
||||
uint64_t read(void* buf, uint64_t 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));
|
||||
}
|
||||
|
|
|
@ -20,12 +20,12 @@ public:
|
|||
: fp(fpin) {}
|
||||
~ReadStream() {fclose(fp);}
|
||||
public:
|
||||
size_t read(void* buf, size_t length)
|
||||
uint64_t read(void* buf, uint64_t length)
|
||||
{return fread(buf, 1, length, fp);}
|
||||
void seek(size_t offset, int whence)
|
||||
{fseek(fp, offset, whence);}
|
||||
void seek(int64_t offset, int 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");
|
||||
if (!fp)
|
||||
|
@ -33,7 +33,7 @@ public:
|
|||
throw std::runtime_error("Unable to open '" + filepath + "' for reading");
|
||||
return std::unique_ptr<IReadStream>();
|
||||
}
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
fseeko(fp, offset, SEEK_SET);
|
||||
return std::unique_ptr<IReadStream>(new ReadStream(fp));
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,10 @@ public:
|
|||
: fp(fpin) {}
|
||||
~WriteStream() {fclose(fp);}
|
||||
public:
|
||||
size_t write(void* buf, size_t length)
|
||||
uint64_t write(void* buf, uint64_t length)
|
||||
{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");
|
||||
if (!fp)
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
throw std::runtime_error("Unable to open '" + filepath + "' for writing");
|
||||
return std::unique_ptr<IWriteStream>();
|
||||
}
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
fseeko(fp, offset, SEEK_SET);
|
||||
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -20,12 +20,12 @@ public:
|
|||
: fp(fpin) {}
|
||||
~ReadStream() {fclose(fp);}
|
||||
public:
|
||||
size_t read(void* buf, size_t length)
|
||||
uint64_t read(void* buf, uint64_t length)
|
||||
{return fread(buf, 1, length, fp);}
|
||||
void seek(size_t offset, int whence)
|
||||
{fseek(fp, offset, whence);}
|
||||
void seek(int64_t offset, int 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");
|
||||
if (!fp)
|
||||
|
@ -33,7 +33,7 @@ public:
|
|||
throw std::runtime_error("Unable to open '" + filepath + "' for reading");
|
||||
return std::unique_ptr<IReadStream>();
|
||||
}
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
fseeko(fp, offset, SEEK_SET);
|
||||
return std::unique_ptr<IReadStream>(new ReadStream(fp));
|
||||
}
|
||||
|
||||
|
@ -45,10 +45,10 @@ public:
|
|||
: fp(fpin) {}
|
||||
~WriteStream() {fclose(fp);}
|
||||
public:
|
||||
size_t write(void* buf, size_t length)
|
||||
uint64_t write(void* buf, uint64_t length)
|
||||
{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");
|
||||
if (!fp)
|
||||
|
@ -56,7 +56,7 @@ public:
|
|||
throw std::runtime_error("Unable to open '" + filepath + "' for writing");
|
||||
return std::unique_ptr<IWriteStream>();
|
||||
}
|
||||
fseek(fp, offset, SEEK_SET);
|
||||
fseeko(fp, offset, SEEK_SET);
|
||||
return std::unique_ptr<IWriteStream>(new WriteStream(fp));
|
||||
}
|
||||
};
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
namespace NOD
|
||||
{
|
||||
|
||||
/* Not much of a secret anymore I suppose */
|
||||
static const uint8_t COMMON_KEY[] = {0xeb, 0xe4, 0x2a, 0x22,
|
||||
0x5e, 0x85, 0x93, 0xe4,
|
||||
0x48, 0xd9, 0xc5, 0x45,
|
||||
|
@ -124,7 +125,7 @@ class PartitionWii : public DiscBase::IPartition
|
|||
titleVersion = SBig(titleVersion);
|
||||
numContents = SBig(numContents);
|
||||
bootIdx = SBig(bootIdx);
|
||||
for (size_t c=0 ; c<numContents ; ++c)
|
||||
for (uint16_t c=0 ; c<numContents ; ++c)
|
||||
{
|
||||
contents.emplace_back();
|
||||
contents.back().read(s);
|
||||
|
@ -175,11 +176,11 @@ class PartitionWii : public DiscBase::IPartition
|
|||
Certificate m_tmdCert;
|
||||
Certificate m_ticketCert;
|
||||
|
||||
size_t m_dataOff;
|
||||
uint64_t m_dataOff;
|
||||
uint8_t m_decKey[16];
|
||||
|
||||
public:
|
||||
PartitionWii(const DiscWii& parent, Kind kind, size_t offset)
|
||||
PartitionWii(const DiscWii& parent, Kind kind, uint64_t offset)
|
||||
: IPartition(parent, kind, offset)
|
||||
{
|
||||
std::unique_ptr<IDiscIO::IReadStream> s = parent.getDiscIO().beginReadStream(offset);
|
||||
|
@ -233,6 +234,9 @@ public:
|
|||
m_dolOff = SBig(vals[0]) << 2;
|
||||
m_fstOff = SBig(vals[1]) << 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!! */
|
||||
parseFST(*ds.get());
|
||||
|
@ -242,8 +246,8 @@ public:
|
|||
{
|
||||
std::unique_ptr<IAES> m_aes;
|
||||
const PartitionWii& m_parent;
|
||||
size_t m_baseOffset;
|
||||
size_t m_offset;
|
||||
uint64_t m_baseOffset;
|
||||
uint64_t m_offset;
|
||||
std::unique_ptr<IDiscIO::IReadStream> m_dio;
|
||||
|
||||
size_t m_curBlock = SIZE_MAX;
|
||||
|
@ -256,7 +260,7 @@ public:
|
|||
m_aes->decrypt(&m_encBuf[0x3d0], &m_encBuf[0x400], m_decBuf, 0x7c00);
|
||||
}
|
||||
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->setKey(parent.m_decKey);
|
||||
|
@ -265,7 +269,7 @@ public:
|
|||
decryptBlock();
|
||||
m_curBlock = block;
|
||||
}
|
||||
void seek(size_t offset, int whence)
|
||||
void seek(int64_t offset, int whence)
|
||||
{
|
||||
if (whence == SEEK_SET)
|
||||
m_offset = offset;
|
||||
|
@ -281,11 +285,11 @@ public:
|
|||
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 cacheOffset = m_offset % 0x7c00;
|
||||
size_t cacheSize;
|
||||
uint64_t cacheSize;
|
||||
uint8_t* dst = (uint8_t*)buf;
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
uint64_t normalizeOffset(uint64_t anOffset) const {return anOffset << 2;}
|
||||
};
|
||||
|
||||
DiscWii::DiscWii(std::unique_ptr<IDiscIO>&& dio)
|
||||
|
|
|
@ -18,13 +18,13 @@ public:
|
|||
FileIOFILE(const std::string& path)
|
||||
: m_path(path) {}
|
||||
|
||||
size_t size()
|
||||
uint64_t size()
|
||||
{
|
||||
FILE* fp = fopen(m_path.c_str(), "rb");
|
||||
if (!fp)
|
||||
return 0;
|
||||
fseek(fp, 0, SEEK_END);
|
||||
size_t result = ftell(fp);
|
||||
fseeko(fp, 0, SEEK_END);
|
||||
uint64_t result = ftello(fp);
|
||||
fclose(fp);
|
||||
return result;
|
||||
}
|
||||
|
@ -40,13 +40,15 @@ public:
|
|||
throw std::runtime_error("unable to open '" + path + "' for writing");
|
||||
}
|
||||
~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)
|
||||
{
|
||||
size_t thisSz = MIN(0x7c00, length);
|
||||
size_t readSz = discio.read(buf, thisSz);
|
||||
uint64_t thisSz = MIN(0x7c00, length);
|
||||
uint64_t readSz = discio.read(buf, thisSz);
|
||||
if (thisSz != readSz)
|
||||
throw std::runtime_error("unable to read enough from disc");
|
||||
if (fwrite(buf, 1, readSz, fp) != readSz)
|
||||
|
@ -71,12 +73,14 @@ public:
|
|||
throw std::runtime_error("unable to open '" + path + "' for reading");
|
||||
}
|
||||
~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)
|
||||
{
|
||||
size_t thisSz = MIN(0x7c00, length);
|
||||
uint64_t thisSz = MIN(0x7c00, length);
|
||||
if (fread(buf, 1, thisSz, fp) != thisSz)
|
||||
throw std::runtime_error("unable to read enough from file");
|
||||
if (discio.write(buf, thisSz) != thisSz)
|
||||
|
|
|
@ -29,7 +29,7 @@ std::unique_ptr<DiscBase> OpenDiscFromImage(const char* path, bool& isWii)
|
|||
}
|
||||
else
|
||||
{
|
||||
fseek(fp, 0x18, SEEK_SET);
|
||||
fseeko(fp, 0x18, SEEK_SET);
|
||||
fread(&magic, 1, 4, fp);
|
||||
magic = NOD::SBig(magic);
|
||||
if (magic == 0x5D1C9EA3)
|
||||
|
|
14
lib/aes.cpp
14
lib/aes.cpp
|
@ -76,8 +76,8 @@ protected:
|
|||
void _decrypt(uint8_t* buff);
|
||||
|
||||
public:
|
||||
void encrypt(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, 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, uint64_t len);
|
||||
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
|
||||
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];
|
||||
unsigned int blockno = 0, i;
|
||||
|
@ -485,10 +485,10 @@ class NiAES : public IAES
|
|||
__m128i m_ekey[11];
|
||||
__m128i m_dkey[11];
|
||||
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;
|
||||
size_t i,j;
|
||||
uint64_t i,j;
|
||||
if (len%16)
|
||||
len = len/16+1;
|
||||
else
|
||||
|
@ -505,10 +505,10 @@ public:
|
|||
_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;
|
||||
size_t i,j;
|
||||
uint64_t i,j;
|
||||
if (len%16)
|
||||
len = len/16+1;
|
||||
else
|
||||
|
|
Loading…
Reference in New Issue