mirror of https://github.com/AxioDL/nod.git
Initial extractor automation
This commit is contained in:
parent
ec8db1694b
commit
293b7c0ce6
20
NODLib.pro
20
NODLib.pro
|
@ -1,13 +1,10 @@
|
||||||
TEMPLATE = app
|
TEMPLATE = subdirs
|
||||||
CONFIG += console c++11
|
|
||||||
CONFIG -= app_bundle
|
CONFIG -= app_bundle
|
||||||
CONFIG -= qt
|
CONFIG -= qt
|
||||||
QT =
|
QT =
|
||||||
|
|
||||||
QMAKE_CXXFLAGS += -maes
|
SUBDIRS += lib driver
|
||||||
QMAKE_LFLAGS += -maes
|
driver.depends += lib
|
||||||
|
|
||||||
INCLUDEPATH += include
|
|
||||||
|
|
||||||
HEADERS += \
|
HEADERS += \
|
||||||
include/Util.hpp \
|
include/Util.hpp \
|
||||||
|
@ -19,14 +16,3 @@ HEADERS += \
|
||||||
include/DiscWii.hpp \
|
include/DiscWii.hpp \
|
||||||
include/aes.hpp
|
include/aes.hpp
|
||||||
|
|
||||||
SOURCES += \
|
|
||||||
lib/NODLib.cpp \
|
|
||||||
lib/FileIOFILE.cpp \
|
|
||||||
lib/FileIOMEM.cpp \
|
|
||||||
lib/DiscBase.cpp \
|
|
||||||
lib/DiscGCN.cpp \
|
|
||||||
lib/DiscWii.cpp \
|
|
||||||
lib/DiscIOWBFS.cpp \
|
|
||||||
lib/DiscIOISO.cpp \
|
|
||||||
main.cpp \
|
|
||||||
lib/aes.cpp
|
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
TEMPLATE = app
|
||||||
|
CONFIG += console c++11
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
CONFIG -= qt
|
||||||
|
QT =
|
||||||
|
|
||||||
|
INCLUDEPATH += ../include
|
||||||
|
QMAKE_LFLAGS += -maes
|
||||||
|
LIBS += -L$$OUT_PWD/../lib -lNOD
|
||||||
|
|
||||||
|
SOURCES += main.cpp
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include "NODLib.hpp"
|
||||||
|
|
||||||
|
int main(int argc, char* argv[])
|
||||||
|
{
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: nodlib <image-in>\n");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::unique_ptr<NOD::DiscBase> disc = NOD::OpenDiscFromImage(argv[1]);
|
||||||
|
if (!disc)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
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 (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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
@ -36,17 +36,6 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
struct IPartReadStream
|
|
||||||
{
|
|
||||||
virtual void seek(size_t offset, int whence=SEEK_SET)=0;
|
|
||||||
virtual size_t read(void* buf, size_t length)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct IPartWriteStream
|
|
||||||
{
|
|
||||||
virtual size_t write(void* buf, size_t length)=0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class FSTNode
|
class FSTNode
|
||||||
{
|
{
|
||||||
uint32_t typeAndNameOffset;
|
uint32_t typeAndNameOffset;
|
||||||
|
@ -86,8 +75,8 @@ public:
|
||||||
size_t m_discLength;
|
size_t m_discLength;
|
||||||
std::string m_name;
|
std::string m_name;
|
||||||
|
|
||||||
std::vector<Node>::const_iterator m_childrenBegin;
|
std::vector<Node>::iterator m_childrenBegin;
|
||||||
std::vector<Node>::const_iterator m_childrenEnd;
|
std::vector<Node>::iterator m_childrenEnd;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Node(const IPartition& parent, const FSTNode& node, const char* name)
|
Node(const IPartition& parent, const FSTNode& node, const char* name)
|
||||||
|
@ -107,15 +96,15 @@ public:
|
||||||
}
|
}
|
||||||
return m_parent.beginReadStream(m_discOffset);
|
return m_parent.beginReadStream(m_discOffset);
|
||||||
}
|
}
|
||||||
inline std::vector<Node>::const_iterator rawBegin() const {return m_childrenBegin;}
|
inline std::vector<Node>::iterator rawBegin() const {return m_childrenBegin;}
|
||||||
inline std::vector<Node>::const_iterator rawEnd() const {return m_childrenEnd;}
|
inline std::vector<Node>::iterator rawEnd() const {return m_childrenEnd;}
|
||||||
|
|
||||||
class DirectoryIterator : std::iterator<std::forward_iterator_tag, const Node>
|
class DirectoryIterator : std::iterator<std::forward_iterator_tag, Node>
|
||||||
{
|
{
|
||||||
friend class Node;
|
friend class Node;
|
||||||
std::vector<Node>::const_iterator m_it;
|
std::vector<Node>::iterator m_it;
|
||||||
DirectoryIterator(std::vector<Node>::const_iterator&& it)
|
DirectoryIterator(const std::vector<Node>::iterator& it)
|
||||||
: m_it(std::move(it)) {}
|
: m_it(it) {}
|
||||||
public:
|
public:
|
||||||
inline bool operator!=(const DirectoryIterator& other) {return m_it != other.m_it;}
|
inline bool operator!=(const DirectoryIterator& other) {return m_it != other.m_it;}
|
||||||
inline DirectoryIterator& operator++()
|
inline DirectoryIterator& operator++()
|
||||||
|
@ -126,10 +115,12 @@ public:
|
||||||
++m_it;
|
++m_it;
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
inline const Node& operator*() {return *m_it;}
|
inline Node& operator*() {return *m_it;}
|
||||||
};
|
};
|
||||||
inline DirectoryIterator begin() const {return DirectoryIterator(rawBegin());}
|
inline DirectoryIterator begin() const {return DirectoryIterator(m_childrenBegin);}
|
||||||
inline DirectoryIterator end() const {return DirectoryIterator(rawEnd());}
|
inline DirectoryIterator end() const {return DirectoryIterator(m_childrenEnd);}
|
||||||
|
|
||||||
|
void extractToDirectory(const std::string& basePath, bool force=false);
|
||||||
};
|
};
|
||||||
protected:
|
protected:
|
||||||
uint32_t m_dolOff;
|
uint32_t m_dolOff;
|
||||||
|
@ -148,6 +139,9 @@ public:
|
||||||
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(size_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 void extractToDirectory(const std::string& path, bool force=false)
|
||||||
|
{m_nodes[0].extractToDirectory(path, force);}
|
||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -173,6 +167,11 @@ public:
|
||||||
return part.get();
|
return part.get();
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
inline void extractToDirectory(const std::string& path, bool force=false)
|
||||||
|
{
|
||||||
|
for (std::unique_ptr<IPartition>& part : m_partitions)
|
||||||
|
part->extractToDirectory(path, force);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,17 @@ public:
|
||||||
virtual std::unique_ptr<IWriteStream> beginWriteStream(size_t offset=0) const=0;
|
virtual std::unique_ptr<IWriteStream> beginWriteStream(size_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;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct IPartWriteStream
|
||||||
|
{
|
||||||
|
virtual size_t write(void* buf, size_t length)=0;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __NOD_IDISC_IO__
|
#endif // __NOD_IDISC_IO__
|
||||||
|
|
|
@ -17,18 +17,21 @@ public:
|
||||||
struct IWriteStream
|
struct IWriteStream
|
||||||
{
|
{
|
||||||
virtual ~IWriteStream() {}
|
virtual ~IWriteStream() {}
|
||||||
virtual size_t copyFromDisc(IDiscIO::IReadStream& discio, size_t length)=0;
|
virtual size_t copyFromDisc(struct IPartReadStream& discio, size_t length)=0;
|
||||||
};
|
};
|
||||||
virtual std::unique_ptr<IWriteStream> beginWriteStream();
|
virtual std::unique_ptr<IWriteStream> beginWriteStream() const=0;
|
||||||
|
|
||||||
struct IReadStream
|
struct IReadStream
|
||||||
{
|
{
|
||||||
virtual ~IReadStream() {}
|
virtual ~IReadStream() {}
|
||||||
virtual size_t copyToDisc(IDiscIO::IWriteStream& discio, size_t length)=0;
|
virtual size_t copyToDisc(struct IPartWriteStream& discio, size_t length)=0;
|
||||||
};
|
};
|
||||||
virtual std::unique_ptr<IReadStream> beginReadStream();
|
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);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#endif // __NOD_IFILE_IO__
|
#endif // __NOD_IFILE_IO__
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
|
||||||
#include <memory>
|
#include <memory>
|
||||||
|
|
||||||
namespace NOD
|
namespace NOD
|
||||||
|
|
|
@ -1,4 +1,6 @@
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "DiscBase.hpp"
|
#include "DiscBase.hpp"
|
||||||
|
#include "IFileIO.hpp"
|
||||||
|
|
||||||
namespace NOD
|
namespace NOD
|
||||||
{
|
{
|
||||||
|
@ -26,7 +28,7 @@ void DiscBase::IPartition::parseFST(IPartReadStream& s)
|
||||||
for (uint32_t n=0 ; n<nodeCount ; ++n)
|
for (uint32_t n=0 ; n<nodeCount ; ++n)
|
||||||
{
|
{
|
||||||
const FSTNode& node = nodes[n];
|
const FSTNode& node = nodes[n];
|
||||||
m_nodes.emplace_back(*this, node, n ? names + node.getNameOffset() : "<root>");
|
m_nodes.emplace_back(*this, node, n ? names + node.getNameOffset() : "");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Setup dir-child iterators */
|
/* Setup dir-child iterators */
|
||||||
|
@ -43,4 +45,27 @@ void DiscBase::IPartition::parseFST(IPartReadStream& s)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DiscBase::IPartition::Node::extractToDirectory(const std::string& basePath, bool force)
|
||||||
|
{
|
||||||
|
std::string path = basePath + "/" + getName();
|
||||||
|
if (m_kind == NODE_DIRECTORY)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
else if (m_kind == NODE_FILE)
|
||||||
|
{
|
||||||
|
struct stat theStat;
|
||||||
|
if (force || stat(path.c_str(), &theStat))
|
||||||
|
{
|
||||||
|
m_hddFile = NewFileIO(path);
|
||||||
|
std::unique_ptr<IPartReadStream> rs = beginReadStream();
|
||||||
|
std::unique_ptr<IFileIO::IWriteStream> ws = m_hddFile->beginWriteStream();
|
||||||
|
ws->copyFromDisc(*rs.get(), m_discLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,7 @@ public:
|
||||||
: IPartition(parent, kind, offset)
|
: IPartition(parent, kind, offset)
|
||||||
{
|
{
|
||||||
/* GCN-specific header reads */
|
/* GCN-specific header reads */
|
||||||
std::unique_ptr<DiscBase::IPartReadStream> s = beginReadStream(0x420);
|
std::unique_ptr<IPartReadStream> s = beginReadStream(0x420);
|
||||||
uint32_t vals[3];
|
uint32_t vals[3];
|
||||||
s->read(vals, 12);
|
s->read(vals, 12);
|
||||||
m_dolOff = SBig(vals[0]);
|
m_dolOff = SBig(vals[0]);
|
||||||
|
@ -21,7 +21,7 @@ public:
|
||||||
parseFST(*s.get());
|
parseFST(*s.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
class PartReadStream : public DiscBase::IPartReadStream
|
class PartReadStream : public IPartReadStream
|
||||||
{
|
{
|
||||||
const PartitionGCN& m_parent;
|
const PartitionGCN& m_parent;
|
||||||
std::unique_ptr<IDiscIO::IReadStream> m_dio;
|
std::unique_ptr<IDiscIO::IReadStream> m_dio;
|
||||||
|
@ -36,9 +36,9 @@ public:
|
||||||
{return m_dio->read(buf, length);}
|
{return m_dio->read(buf, length);}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<DiscBase::IPartReadStream> beginReadStream(size_t offset) const
|
std::unique_ptr<IPartReadStream> beginReadStream(size_t offset) const
|
||||||
{
|
{
|
||||||
return std::unique_ptr<DiscBase::IPartReadStream>(new PartReadStream(*this, offset));
|
return std::unique_ptr<IPartReadStream>(new PartReadStream(*this, offset));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
#include "DiscWii.hpp"
|
#include "DiscWii.hpp"
|
||||||
#include "aes.hpp"
|
#include "aes.hpp"
|
||||||
|
|
||||||
|
@ -12,6 +13,19 @@ static const uint8_t COMMON_KEY[] = {0xeb, 0xe4, 0x2a, 0x22,
|
||||||
|
|
||||||
class PartitionWii : public DiscBase::IPartition
|
class PartitionWii : public DiscBase::IPartition
|
||||||
{
|
{
|
||||||
|
enum SigType : uint32_t
|
||||||
|
{
|
||||||
|
SRSA_4096 = 0x00010000,
|
||||||
|
SRSA_2048 = 0x00010001,
|
||||||
|
SELIPTICAL_CURVE = 0x00010002
|
||||||
|
};
|
||||||
|
|
||||||
|
enum KeyType : uint32_t
|
||||||
|
{
|
||||||
|
KRSA_4096 = 0x00000000,
|
||||||
|
KRSA_2048 = 0x00000001
|
||||||
|
};
|
||||||
|
|
||||||
struct Ticket
|
struct Ticket
|
||||||
{
|
{
|
||||||
uint32_t sigType;
|
uint32_t sigType;
|
||||||
|
@ -57,7 +71,7 @@ class PartitionWii : public DiscBase::IPartition
|
||||||
|
|
||||||
struct TMD
|
struct TMD
|
||||||
{
|
{
|
||||||
uint32_t sigType;
|
SigType sigType;
|
||||||
char sig[256];
|
char sig[256];
|
||||||
char padding[60];
|
char padding[60];
|
||||||
char sigIssuer[64];
|
char sigIssuer[64];
|
||||||
|
@ -68,7 +82,7 @@ class PartitionWii : public DiscBase::IPartition
|
||||||
uint32_t iosIdMajor;
|
uint32_t iosIdMajor;
|
||||||
uint32_t iosIdMinor;
|
uint32_t iosIdMinor;
|
||||||
uint32_t titleIdMajor;
|
uint32_t titleIdMajor;
|
||||||
uint32_t titleIdMinor;
|
char titleIdMinor[4];
|
||||||
uint32_t titleType;
|
uint32_t titleType;
|
||||||
uint16_t groupId;
|
uint16_t groupId;
|
||||||
char padding2[62];
|
char padding2[62];
|
||||||
|
@ -100,11 +114,10 @@ class PartitionWii : public DiscBase::IPartition
|
||||||
void read(IDiscIO::IReadStream& s)
|
void read(IDiscIO::IReadStream& s)
|
||||||
{
|
{
|
||||||
s.read(this, 484);
|
s.read(this, 484);
|
||||||
sigType = SBig(sigType);
|
sigType = (SigType)SBig(sigType);
|
||||||
iosIdMajor = SBig(iosIdMajor);
|
iosIdMajor = SBig(iosIdMajor);
|
||||||
iosIdMinor = SBig(iosIdMinor);
|
iosIdMinor = SBig(iosIdMinor);
|
||||||
titleIdMajor = SBig(titleIdMajor);
|
titleIdMajor = SBig(titleIdMajor);
|
||||||
titleIdMinor = SBig(titleIdMinor);
|
|
||||||
titleType = SBig(titleType);
|
titleType = SBig(titleType);
|
||||||
groupId = SBig(groupId);
|
groupId = SBig(groupId);
|
||||||
accessFlags = SBig(accessFlags);
|
accessFlags = SBig(accessFlags);
|
||||||
|
@ -121,10 +134,10 @@ class PartitionWii : public DiscBase::IPartition
|
||||||
|
|
||||||
struct Certificate
|
struct Certificate
|
||||||
{
|
{
|
||||||
uint32_t sigType;
|
SigType sigType;
|
||||||
char sig[512];
|
char sig[512];
|
||||||
char issuer[64];
|
char issuer[64];
|
||||||
uint32_t keyType;
|
KeyType keyType;
|
||||||
char subject[64];
|
char subject[64];
|
||||||
char key[512];
|
char key[512];
|
||||||
uint32_t modulus;
|
uint32_t modulus;
|
||||||
|
@ -133,22 +146,22 @@ class PartitionWii : public DiscBase::IPartition
|
||||||
void read(IDiscIO::IReadStream& s)
|
void read(IDiscIO::IReadStream& s)
|
||||||
{
|
{
|
||||||
s.read(&sigType, 4);
|
s.read(&sigType, 4);
|
||||||
sigType = SBig(sigType);
|
sigType = (SigType)SBig(sigType);
|
||||||
if (sigType == 0x00010000)
|
if (sigType == SRSA_4096)
|
||||||
s.read(sig, 512);
|
s.read(sig, 512);
|
||||||
else if (sigType == 0x00010001)
|
else if (sigType == SRSA_2048)
|
||||||
s.read(sig, 256);
|
s.read(sig, 256);
|
||||||
else if (sigType == 0x00010002)
|
else if (sigType == SELIPTICAL_CURVE)
|
||||||
s.read(sig, 64);
|
s.read(sig, 64);
|
||||||
s.seek(60, SEEK_CUR);
|
s.seek(60, SEEK_CUR);
|
||||||
|
|
||||||
s.read(issuer, 64);
|
s.read(issuer, 64);
|
||||||
s.read(&keyType, 4);
|
s.read(&keyType, 4);
|
||||||
s.read(subject, 64);
|
s.read(subject, 64);
|
||||||
keyType = SBig(keyType);
|
keyType = (KeyType)SBig(keyType);
|
||||||
if (keyType == 0x00000000)
|
if (keyType == KRSA_4096)
|
||||||
s.read(key, 512);
|
s.read(key, 512);
|
||||||
else if (keyType == 0x00000001)
|
else if (keyType == KRSA_2048)
|
||||||
s.read(key, 256);
|
s.read(key, 256);
|
||||||
|
|
||||||
s.read(&modulus, 8);
|
s.read(&modulus, 8);
|
||||||
|
@ -214,7 +227,7 @@ public:
|
||||||
aes->decrypt(iv, m_ticket.encKey, m_decKey, 16);
|
aes->decrypt(iv, m_ticket.encKey, m_decKey, 16);
|
||||||
|
|
||||||
/* Wii-specific header reads (now using title key to decrypt) */
|
/* Wii-specific header reads (now using title key to decrypt) */
|
||||||
std::unique_ptr<DiscBase::IPartReadStream> ds = beginReadStream(0x420);
|
std::unique_ptr<IPartReadStream> ds = beginReadStream(0x420);
|
||||||
uint32_t vals[3];
|
uint32_t vals[3];
|
||||||
ds->read(vals, 12);
|
ds->read(vals, 12);
|
||||||
m_dolOff = SBig(vals[0]) << 2;
|
m_dolOff = SBig(vals[0]) << 2;
|
||||||
|
@ -225,7 +238,7 @@ public:
|
||||||
parseFST(*ds.get());
|
parseFST(*ds.get());
|
||||||
}
|
}
|
||||||
|
|
||||||
class PartReadStream : public DiscBase::IPartReadStream
|
class PartReadStream : public IPartReadStream
|
||||||
{
|
{
|
||||||
std::unique_ptr<IAES> m_aes;
|
std::unique_ptr<IAES> m_aes;
|
||||||
const PartitionWii& m_parent;
|
const PartitionWii& m_parent;
|
||||||
|
@ -233,6 +246,7 @@ public:
|
||||||
size_t m_offset;
|
size_t m_offset;
|
||||||
std::unique_ptr<IDiscIO::IReadStream> m_dio;
|
std::unique_ptr<IDiscIO::IReadStream> m_dio;
|
||||||
|
|
||||||
|
size_t m_curBlock = SIZE_MAX;
|
||||||
uint8_t m_encBuf[0x8000];
|
uint8_t m_encBuf[0x8000];
|
||||||
uint8_t m_decBuf[0x7c00];
|
uint8_t m_decBuf[0x7c00];
|
||||||
|
|
||||||
|
@ -248,6 +262,8 @@ public:
|
||||||
m_aes->setKey(parent.m_decKey);
|
m_aes->setKey(parent.m_decKey);
|
||||||
size_t block = m_offset / 0x7c00;
|
size_t block = m_offset / 0x7c00;
|
||||||
m_dio = m_parent.m_parent.getDiscIO().beginReadStream(m_baseOffset + block * 0x8000);
|
m_dio = m_parent.m_parent.getDiscIO().beginReadStream(m_baseOffset + block * 0x8000);
|
||||||
|
decryptBlock();
|
||||||
|
m_curBlock = block;
|
||||||
}
|
}
|
||||||
void seek(size_t offset, int whence)
|
void seek(size_t offset, int whence)
|
||||||
{
|
{
|
||||||
|
@ -259,16 +275,26 @@ public:
|
||||||
return;
|
return;
|
||||||
size_t block = m_offset / 0x7c00;
|
size_t block = m_offset / 0x7c00;
|
||||||
m_dio->seek(m_baseOffset + block * 0x8000);
|
m_dio->seek(m_baseOffset + block * 0x8000);
|
||||||
|
if (block != m_curBlock)
|
||||||
|
{
|
||||||
|
decryptBlock();
|
||||||
|
m_curBlock = block;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
size_t read(void* buf, size_t length)
|
size_t read(void* buf, size_t length)
|
||||||
{
|
{
|
||||||
|
size_t block = m_offset / 0x7c00;
|
||||||
size_t cacheOffset = m_offset % 0x7c00;
|
size_t cacheOffset = m_offset % 0x7c00;
|
||||||
size_t cacheSize;
|
size_t cacheSize;
|
||||||
uint8_t* dst = (uint8_t*)buf;
|
uint8_t* dst = (uint8_t*)buf;
|
||||||
|
|
||||||
while (length)
|
while (length)
|
||||||
|
{
|
||||||
|
if (block != m_curBlock)
|
||||||
{
|
{
|
||||||
decryptBlock();
|
decryptBlock();
|
||||||
|
m_curBlock = block;
|
||||||
|
}
|
||||||
|
|
||||||
cacheSize = length;
|
cacheSize = length;
|
||||||
if (cacheSize + cacheOffset > 0x7c00)
|
if (cacheSize + cacheOffset > 0x7c00)
|
||||||
|
@ -278,6 +304,7 @@ public:
|
||||||
dst += cacheSize;
|
dst += cacheSize;
|
||||||
length -= cacheSize;
|
length -= cacheSize;
|
||||||
cacheOffset = 0;
|
cacheOffset = 0;
|
||||||
|
++block;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_offset += length;
|
m_offset += length;
|
||||||
|
@ -285,9 +312,9 @@ public:
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
std::unique_ptr<DiscBase::IPartReadStream> beginReadStream(size_t offset) const
|
std::unique_ptr<IPartReadStream> beginReadStream(size_t offset) const
|
||||||
{
|
{
|
||||||
return std::unique_ptr<DiscBase::IPartReadStream>(new PartReadStream(*this, m_dataOff, offset));
|
return std::unique_ptr<IPartReadStream>(new PartReadStream(*this, m_dataOff, offset));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,99 @@
|
||||||
#include <sys/stat.h>
|
#include <sys/stat.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <stdlib.h>
|
||||||
#include <stdexcept>
|
#include <stdexcept>
|
||||||
#include "IFileIO.hpp"
|
#include "IFileIO.hpp"
|
||||||
|
|
||||||
|
/* Macros for min/max */
|
||||||
|
#define MIN(a,b) (((a)<(b))?(a):(b))
|
||||||
|
#define MAX(a,b) (((a)>(b))?(a):(b))
|
||||||
|
|
||||||
namespace NOD
|
namespace NOD
|
||||||
{
|
{
|
||||||
|
|
||||||
class FileIOFILE : public IFileIO
|
class FileIOFILE : public IFileIO
|
||||||
{
|
{
|
||||||
const char* filepath;
|
std::string m_path;
|
||||||
public:
|
public:
|
||||||
FileIOFILE(const char* path)
|
FileIOFILE(const std::string& path)
|
||||||
: filepath(path)
|
: m_path(path) {}
|
||||||
|
|
||||||
|
size_t size()
|
||||||
{
|
{
|
||||||
struct stat theStat;
|
FILE* fp = fopen(m_path.c_str(), "rb");
|
||||||
if (stat(path, &theStat))
|
if (!fp)
|
||||||
throw std::runtime_error("unable to ");
|
return 0;
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
size_t result = ftell(fp);
|
||||||
|
fclose(fp);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct WriteStream : public IFileIO::IWriteStream
|
||||||
|
{
|
||||||
|
FILE* fp;
|
||||||
|
uint8_t buf[0x7c00];
|
||||||
|
WriteStream(const std::string& path)
|
||||||
|
{
|
||||||
|
fp = fopen(path.c_str(), "wb");
|
||||||
|
if (!fp)
|
||||||
|
throw std::runtime_error("unable to open '" + path + "' for writing");
|
||||||
|
}
|
||||||
|
~WriteStream() {fclose(fp);}
|
||||||
|
size_t copyFromDisc(IPartReadStream& discio, size_t length)
|
||||||
|
{
|
||||||
|
size_t read = 0;
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
size_t thisSz = MIN(0x7c00, length);
|
||||||
|
size_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)
|
||||||
|
throw std::runtime_error("unable to write in file");
|
||||||
|
length -= thisSz;
|
||||||
|
read += thisSz;
|
||||||
|
}
|
||||||
|
return read;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
std::unique_ptr<IWriteStream> beginWriteStream() const
|
||||||
|
{return std::unique_ptr<IWriteStream>(new WriteStream(m_path));}
|
||||||
|
|
||||||
|
struct ReadStream : public IFileIO::IReadStream
|
||||||
|
{
|
||||||
|
FILE* fp;
|
||||||
|
uint8_t buf[0x7c00];
|
||||||
|
ReadStream(const std::string& path)
|
||||||
|
{
|
||||||
|
fp = fopen(path.c_str(), "rb");
|
||||||
|
if (!fp)
|
||||||
|
throw std::runtime_error("unable to open '" + path + "' for reading");
|
||||||
|
}
|
||||||
|
~ReadStream() {fclose(fp);}
|
||||||
|
size_t copyToDisc(IPartWriteStream& discio, size_t length)
|
||||||
|
{
|
||||||
|
size_t written = 0;
|
||||||
|
while (length)
|
||||||
|
{
|
||||||
|
size_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)
|
||||||
|
throw std::runtime_error("unable to write enough to disc");
|
||||||
|
length -= thisSz;
|
||||||
|
written += thisSz;
|
||||||
|
}
|
||||||
|
return written;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
std::unique_ptr<IReadStream> beginReadStream() const
|
||||||
|
{return std::unique_ptr<IReadStream>(new ReadStream(m_path));}
|
||||||
|
};
|
||||||
|
|
||||||
|
std::unique_ptr<IFileIO> NewFileIO(const std::string& path)
|
||||||
|
{
|
||||||
|
return std::unique_ptr<IFileIO>(new FileIOFILE(path));
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
18
lib/aes.cpp
18
lib/aes.cpp
|
@ -1,16 +1,5 @@
|
||||||
/* Rijndael Block Cipher - aes.c
|
|
||||||
|
|
||||||
Written by Mike Scott 21st April 1999
|
|
||||||
mike@compapp.dcu.ie
|
|
||||||
|
|
||||||
Permission for free direct or derivative use is granted subject
|
|
||||||
to compliance with any conditions that the originators of the
|
|
||||||
algorithm place on its exploitation.
|
|
||||||
|
|
||||||
*/
|
|
||||||
#include "aes.hpp"
|
#include "aes.hpp"
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
//#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <cpuid.h>
|
#include <cpuid.h>
|
||||||
|
|
||||||
|
@ -605,8 +594,6 @@ public:
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static int HAS_AES_NI = -1;
|
static int HAS_AES_NI = -1;
|
||||||
|
|
||||||
|
|
||||||
std::unique_ptr<IAES> NewAES()
|
std::unique_ptr<IAES> NewAES()
|
||||||
{
|
{
|
||||||
#if __AES__
|
#if __AES__
|
||||||
|
@ -614,10 +601,7 @@ std::unique_ptr<IAES> NewAES()
|
||||||
{
|
{
|
||||||
unsigned int a,b,c,d;
|
unsigned int a,b,c,d;
|
||||||
__cpuid(1, a,b,c,d);
|
__cpuid(1, a,b,c,d);
|
||||||
if (c & 0x2000000)
|
HAS_AES_NI = ((c & 0x2000000) != 0);
|
||||||
HAS_AES_NI = 1;
|
|
||||||
else
|
|
||||||
HAS_AES_NI = 0;
|
|
||||||
}
|
}
|
||||||
if (HAS_AES_NI)
|
if (HAS_AES_NI)
|
||||||
return std::unique_ptr<IAES>(new NiAES);
|
return std::unique_ptr<IAES>(new NiAES);
|
||||||
|
|
|
@ -0,0 +1,21 @@
|
||||||
|
TEMPLATE = lib
|
||||||
|
CONFIG += staticlib c++11
|
||||||
|
CONFIG -= app_bundle
|
||||||
|
CONFIG -= qt
|
||||||
|
QT =
|
||||||
|
TARGET = NOD
|
||||||
|
|
||||||
|
QMAKE_CXXFLAGS += -maes
|
||||||
|
INCLUDEPATH += ../include
|
||||||
|
|
||||||
|
SOURCES += \
|
||||||
|
NODLib.cpp \
|
||||||
|
FileIOFILE.cpp \
|
||||||
|
FileIOMEM.cpp \
|
||||||
|
DiscBase.cpp \
|
||||||
|
DiscGCN.cpp \
|
||||||
|
DiscWii.cpp \
|
||||||
|
DiscIOWBFS.cpp \
|
||||||
|
DiscIOISO.cpp \
|
||||||
|
aes.cpp
|
||||||
|
|
Loading…
Reference in New Issue