mirror of
https://github.com/jakcron/nstool
synced 2024-11-15 02:06:40 +00:00
[nx] Add ISerialiseableInterface, which AciHeader and NcaHeader inherit from. Also added SacEntry.
This commit is contained in:
parent
bd8a232160
commit
337a5eff25
9 changed files with 260 additions and 19 deletions
|
@ -19,20 +19,45 @@ void AciHeader::calculateSectionOffsets()
|
||||||
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
|
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AciHeader::AciHeader()
|
||||||
|
{
|
||||||
|
clearVariables();
|
||||||
|
}
|
||||||
|
|
||||||
|
AciHeader::AciHeader(const AciHeader & other)
|
||||||
|
{
|
||||||
|
importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
AciHeader::AciHeader(const u8 * bytes)
|
||||||
|
{
|
||||||
|
importBinary(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AciHeader::operator==(const AciHeader & other)
|
||||||
|
{
|
||||||
|
return memcmp(this->getBytes(), other.getBytes(), this->getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
void AciHeader::operator=(const AciHeader & other)
|
||||||
|
{
|
||||||
|
this->importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
const u8 * AciHeader::getBytes() const
|
const u8 * AciHeader::getBytes() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.data();
|
return mBinaryBlob.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t AciHeader::getSize() const
|
size_t AciHeader::getSize() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.size();
|
return mBinaryBlob.getSize();
|
||||||
}
|
}
|
||||||
|
|
||||||
void AciHeader::exportBinary()
|
void AciHeader::exportBinary()
|
||||||
{
|
{
|
||||||
mBinaryBlob.alloc(sizeof(sAciHeader));
|
mBinaryBlob.alloc(sizeof(sAciHeader));
|
||||||
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.data();
|
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
// set type
|
// set type
|
||||||
switch (mType)
|
switch (mType)
|
||||||
|
@ -65,9 +90,9 @@ void AciHeader::importBinary(const u8 * bytes)
|
||||||
clearVariables();
|
clearVariables();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sAciHeader));
|
mBinaryBlob.alloc(sizeof(sAciHeader));
|
||||||
memcpy(mBinaryBlob.data(), bytes, sizeof(sAciHeader));
|
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader));
|
||||||
|
|
||||||
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.data();
|
sAciHeader* hdr = (sAciHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
if (memcmp(hdr->signature(), kAciStructSig.c_str(), 4) == 0)
|
if (memcmp(hdr->signature(), kAciStructSig.c_str(), 4) == 0)
|
||||||
{
|
{
|
||||||
|
@ -91,6 +116,15 @@ void AciHeader::importBinary(const u8 * bytes)
|
||||||
mKc.size = hdr->kc().size();
|
mKc.size = hdr->kc().size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AciHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
if (len < sizeof(sAciHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "ACI header too small");
|
||||||
|
}
|
||||||
|
importBinary(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
AciHeader::AciType AciHeader::getAciType() const
|
AciHeader::AciType AciHeader::getAciType() const
|
||||||
{
|
{
|
||||||
return mType;
|
return mType;
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <string>
|
||||||
#include <fnd/types.h>
|
#include <fnd/types.h>
|
||||||
#include <fnd/memory_blob.h>
|
#include <fnd/memory_blob.h>
|
||||||
#include <string>
|
#include <nx/ISerialiseableBinary.h>
|
||||||
|
|
||||||
class AciHeader
|
class AciHeader : public ISerialiseableBinary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
enum AciType
|
enum AciType
|
||||||
|
@ -18,6 +19,13 @@ public:
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
AciHeader();
|
||||||
|
AciHeader(const AciHeader& other);
|
||||||
|
AciHeader(const u8* bytes);
|
||||||
|
|
||||||
|
bool operator==(const AciHeader& other);
|
||||||
|
void operator=(const AciHeader& other);
|
||||||
|
|
||||||
// to be used after export
|
// to be used after export
|
||||||
const u8* getBytes() const;
|
const u8* getBytes() const;
|
||||||
size_t getSize() const;
|
size_t getSize() const;
|
||||||
|
@ -25,6 +33,7 @@ public:
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
void importBinary(const u8* bytes);
|
||||||
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
AciType getAciType() const;
|
AciType getAciType() const;
|
||||||
|
@ -56,13 +65,13 @@ private:
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
u32 offset_; // aligned by 0x10 from the last one
|
u32 offset_; // aligned by 0x10 from the last one
|
||||||
u32 size_;
|
u32 mSize;
|
||||||
public:
|
public:
|
||||||
u32 offset() const { return le_word(offset_); }
|
u32 offset() const { return le_word(offset_); }
|
||||||
void set_offset(u32 offset) { offset_ = le_word(offset); }
|
void set_offset(u32 offset) { offset_ = le_word(offset); }
|
||||||
|
|
||||||
u32 size() const { return le_word(size_); }
|
u32 size() const { return le_word(mSize); }
|
||||||
void set_size(u32 size) { size_ = le_word(size); }
|
void set_size(u32 size) { mSize = le_word(size); }
|
||||||
} fac_, sac_, kc_;
|
} fac_, sac_, kc_;
|
||||||
u8 reserved_3[8];
|
u8 reserved_3[8];
|
||||||
public:
|
public:
|
||||||
|
|
17
lib/nx/ISerialiseableBinary.h
Normal file
17
lib/nx/ISerialiseableBinary.h
Normal file
|
@ -0,0 +1,17 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
|
||||||
|
class ISerialiseableBinary
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual bool operator==(const ISerialiseableBinary& other) = 0;
|
||||||
|
virtual void operator=(const ISerialiseableBinary& other) = 0;
|
||||||
|
|
||||||
|
virtual const u8* getBytes() const = 0;
|
||||||
|
virtual size_t getSize() const = 0;
|
||||||
|
|
||||||
|
virtual void exportBinary() = 0;
|
||||||
|
virtual void importBinary(const u8* bytes) = 0;
|
||||||
|
virtual void importBinary(const u8* bytes, size_t len) = 0;
|
||||||
|
};
|
||||||
|
|
|
@ -4,7 +4,7 @@
|
||||||
void NcaHeader::exportBinary()
|
void NcaHeader::exportBinary()
|
||||||
{
|
{
|
||||||
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
||||||
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.data();
|
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
hdr->set_signature(kNcaSig.c_str());
|
hdr->set_signature(kNcaSig.c_str());
|
||||||
hdr->set_block_size(kDefaultBlockSize);
|
hdr->set_block_size(kDefaultBlockSize);
|
||||||
|
@ -36,9 +36,9 @@ void NcaHeader::importBinary(const u8 * bytes)
|
||||||
clearVariables();
|
clearVariables();
|
||||||
|
|
||||||
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
mBinaryBlob.alloc(sizeof(sNcaHeader));
|
||||||
memcpy(mBinaryBlob.data(), bytes, sizeof(sNcaHeader));
|
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader));
|
||||||
|
|
||||||
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.data();
|
sNcaHeader* hdr = (sNcaHeader*)mBinaryBlob.getBytes();
|
||||||
|
|
||||||
if (memcmp(hdr->signature(), kNcaSig.c_str(), 4) != 0)
|
if (memcmp(hdr->signature(), kNcaSig.c_str(), 4) != 0)
|
||||||
{
|
{
|
||||||
|
@ -68,6 +68,15 @@ void NcaHeader::importBinary(const u8 * bytes)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NcaHeader::importBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
if (len < sizeof(sNcaHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "NCA header size is too small");
|
||||||
|
}
|
||||||
|
importBinary(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
u64 NcaHeader::getNcaSize() const
|
u64 NcaHeader::getNcaSize() const
|
||||||
{
|
{
|
||||||
return mNcaSize;
|
return mNcaSize;
|
||||||
|
@ -157,12 +166,22 @@ NcaHeader::NcaHeader(const u8 * bytes)
|
||||||
importBinary(bytes);
|
importBinary(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool NcaHeader::operator==(const NcaHeader & other)
|
||||||
|
{
|
||||||
|
return memcmp(this->getBytes(), other.getBytes(), this->getSize()) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NcaHeader::operator=(const NcaHeader & other)
|
||||||
|
{
|
||||||
|
this->importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
const u8 * NcaHeader::getBytes() const
|
const u8 * NcaHeader::getBytes() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.data();
|
return mBinaryBlob.getBytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t NcaHeader::getSize() const
|
size_t NcaHeader::getSize() const
|
||||||
{
|
{
|
||||||
return mBinaryBlob.size();
|
return mBinaryBlob.getSize();
|
||||||
}
|
}
|
|
@ -1,12 +1,13 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
#include <fnd/types.h>
|
#include <fnd/types.h>
|
||||||
#include <fnd/memory_blob.h>
|
#include <fnd/memory_blob.h>
|
||||||
#include <crypto/aes.h>
|
#include <crypto/aes.h>
|
||||||
#include <crypto/sha.h>
|
#include <crypto/sha.h>
|
||||||
#include <vector>
|
#include <nx/ISerialiseableBinary.h>
|
||||||
#include <string>
|
|
||||||
|
|
||||||
class NcaHeader
|
class NcaHeader : public ISerialiseableBinary
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
struct sSection
|
struct sSection
|
||||||
|
@ -19,10 +20,15 @@ public:
|
||||||
crypto::sha::sSha256Hash hash;
|
crypto::sha::sSha256Hash hash;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const size_t kDefaultBlockSize = 0x200;
|
||||||
|
|
||||||
NcaHeader();
|
NcaHeader();
|
||||||
NcaHeader(const NcaHeader& other);
|
NcaHeader(const NcaHeader& other);
|
||||||
NcaHeader(const u8* bytes);
|
NcaHeader(const u8* bytes);
|
||||||
|
|
||||||
|
bool operator==(const NcaHeader& other);
|
||||||
|
void operator=(const NcaHeader& other);
|
||||||
|
|
||||||
// to be used after export
|
// to be used after export
|
||||||
const u8* getBytes() const;
|
const u8* getBytes() const;
|
||||||
size_t getSize() const;
|
size_t getSize() const;
|
||||||
|
@ -30,6 +36,7 @@ public:
|
||||||
// export/import binary
|
// export/import binary
|
||||||
void exportBinary();
|
void exportBinary();
|
||||||
void importBinary(const u8* bytes);
|
void importBinary(const u8* bytes);
|
||||||
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
// variables
|
// variables
|
||||||
u64 getNcaSize() const;
|
u64 getNcaSize() const;
|
||||||
|
@ -45,7 +52,6 @@ public:
|
||||||
private:
|
private:
|
||||||
const std::string kModuleName = "NCA_HEADER";
|
const std::string kModuleName = "NCA_HEADER";
|
||||||
const std::string kNcaSig = "NCA2";
|
const std::string kNcaSig = "NCA2";
|
||||||
static const size_t kDefaultBlockSize = 0x200;
|
|
||||||
static const size_t kSectionNum = 4;
|
static const size_t kSectionNum = 4;
|
||||||
static const size_t kAesKeyNum = 4;
|
static const size_t kAesKeyNum = 4;
|
||||||
|
|
||||||
|
|
101
lib/nx/SacEntry.cpp
Normal file
101
lib/nx/SacEntry.cpp
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
#include "SacEntry.h"
|
||||||
|
|
||||||
|
SacEntry::SacEntry() :
|
||||||
|
mIsServer(false),
|
||||||
|
mName("")
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
SacEntry::SacEntry(const SacEntry & other)
|
||||||
|
{
|
||||||
|
importBinary(other.getBytes(), other.getSize());
|
||||||
|
}
|
||||||
|
|
||||||
|
SacEntry::SacEntry(const u8 * bytes)
|
||||||
|
{
|
||||||
|
importBinary(bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
const u8 * SacEntry::getBytes() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getBytes();
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t SacEntry::getSize() const
|
||||||
|
{
|
||||||
|
return mBinaryBlob.getSize();
|
||||||
|
}
|
||||||
|
|
||||||
|
void SacEntry::exportBinary()
|
||||||
|
{
|
||||||
|
try {
|
||||||
|
mBinaryBlob.alloc(mName.size() + 1);
|
||||||
|
}
|
||||||
|
catch (const fnd::Exception& e)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Failed to allocate memory for SacEntry: " + std::string(e.what()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mName.length() > kMaxServiceNameLen)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// copy data into binary blob
|
||||||
|
mBinaryBlob[0] = (mIsServer ? SAC_IS_SERVER : 0) | (mName.length() & SAC_NAME_LEN_MASK);
|
||||||
|
memcpy(mBinaryBlob.getBytes() + 1, mName.c_str(), mName.length());
|
||||||
|
}
|
||||||
|
|
||||||
|
void SacEntry::importBinary(const u8 * bytes)
|
||||||
|
{
|
||||||
|
bool isServer = (bytes[0] & SAC_IS_SERVER) == SAC_IS_SERVER;
|
||||||
|
size_t nameLen = (bytes[0] & SAC_NAME_LEN_MASK);
|
||||||
|
if (nameLen == 0)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "SAC entry has no service name");
|
||||||
|
}
|
||||||
|
else if (nameLen > kMaxServiceNameLen)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
|
||||||
|
}
|
||||||
|
|
||||||
|
mBinaryBlob.alloc(nameLen + 1);
|
||||||
|
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||||
|
|
||||||
|
mIsServer = isServer;
|
||||||
|
mName = std::string((const char*)(mBinaryBlob.getBytes() + 1), nameLen);
|
||||||
|
}
|
||||||
|
|
||||||
|
void SacEntry::importBinary(const u8 * bytes, size_t len)
|
||||||
|
{
|
||||||
|
importBinary(bytes);
|
||||||
|
if (getSize() != len)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "SAC Entry has unexpected size");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SacEntry::isServer() const
|
||||||
|
{
|
||||||
|
return mIsServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SacEntry::setIsServer(bool isServer)
|
||||||
|
{
|
||||||
|
mIsServer = isServer;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string & SacEntry::getName() const
|
||||||
|
{
|
||||||
|
return mName;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SacEntry::setName(const std::string & name)
|
||||||
|
{
|
||||||
|
if (name.length() > kMaxServiceNameLen)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "Service name string too long (max 8 chars)");
|
||||||
|
}
|
||||||
|
|
||||||
|
mName = name;
|
||||||
|
}
|
43
lib/nx/SacEntry.h
Normal file
43
lib/nx/SacEntry.h
Normal file
|
@ -0,0 +1,43 @@
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/memory_blob.h>
|
||||||
|
#include <nx/ISerialiseableBinary.h>
|
||||||
|
|
||||||
|
class SacEntry : public ISerialiseableBinary
|
||||||
|
{
|
||||||
|
SacEntry();
|
||||||
|
SacEntry(const SacEntry& other);
|
||||||
|
SacEntry(const u8* bytes);
|
||||||
|
|
||||||
|
// to be used after export
|
||||||
|
const u8* getBytes() const;
|
||||||
|
size_t getSize() const;
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
void exportBinary();
|
||||||
|
void importBinary(const u8* bytes);
|
||||||
|
void importBinary(const u8* bytes, size_t len);
|
||||||
|
|
||||||
|
// variables
|
||||||
|
bool isServer() const;
|
||||||
|
void setIsServer(bool isServer);
|
||||||
|
const std::string& getName() const;
|
||||||
|
void setName(const std::string& name);
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "SAC_ENTRY";
|
||||||
|
static const size_t kMaxServiceNameLen = 8;
|
||||||
|
|
||||||
|
enum SacEntryFlag
|
||||||
|
{
|
||||||
|
SAC_IS_SERVER = BIT(7),
|
||||||
|
SAC_NAME_LEN_MASK = BIT(7)-1
|
||||||
|
};
|
||||||
|
|
||||||
|
// raw binary
|
||||||
|
fnd::MemoryBlob mBinaryBlob;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
bool mIsServer;
|
||||||
|
std::string mName;
|
||||||
|
};
|
|
@ -20,12 +20,15 @@
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClInclude Include="AciHeader.h" />
|
<ClInclude Include="AciHeader.h" />
|
||||||
|
<ClInclude Include="ISerialiseableBinary.h" />
|
||||||
<ClInclude Include="NcaHeader.h" />
|
<ClInclude Include="NcaHeader.h" />
|
||||||
<ClInclude Include="NXCrypto.h" />
|
<ClInclude Include="NXCrypto.h" />
|
||||||
|
<ClInclude Include="SacEntry.h" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="AciHeader.cpp" />
|
<ClCompile Include="AciHeader.cpp" />
|
||||||
<ClCompile Include="NcaHeader.cpp" />
|
<ClCompile Include="NcaHeader.cpp" />
|
||||||
|
<ClCompile Include="SacEntry.cpp" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<PropertyGroup Label="Globals">
|
<PropertyGroup Label="Globals">
|
||||||
<VCProjectVersion>15.0</VCProjectVersion>
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
|
|
@ -24,6 +24,12 @@
|
||||||
<ClInclude Include="AciHeader.h">
|
<ClInclude Include="AciHeader.h">
|
||||||
<Filter>Header Files</Filter>
|
<Filter>Header Files</Filter>
|
||||||
</ClInclude>
|
</ClInclude>
|
||||||
|
<ClInclude Include="SacEntry.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="ISerialiseableBinary.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ClCompile Include="NcaHeader.cpp">
|
<ClCompile Include="NcaHeader.cpp">
|
||||||
|
@ -32,5 +38,8 @@
|
||||||
<ClCompile Include="AciHeader.cpp">
|
<ClCompile Include="AciHeader.cpp">
|
||||||
<Filter>Source Files</Filter>
|
<Filter>Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="SacEntry.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
Loading…
Reference in a new issue