[nx] Implemented NpdmBinary and associated child classes.

This commit is contained in:
jakcron 2017-07-17 18:21:39 +10:00
parent 7dd27fd5c8
commit 99151507c6
24 changed files with 768 additions and 354 deletions

View file

@ -3,7 +3,9 @@
nx::AciBinary::AciBinary() nx::AciBinary::AciBinary()
{} {
clear();
}
nx::AciBinary::AciBinary(const AciBinary & other) nx::AciBinary::AciBinary(const AciBinary & other)
{ {

View file

@ -2,28 +2,17 @@
using namespace nx; using namespace nx;
void AciHeader::clearVariables()
{
mType = TYPE_ACI0;
mProgramId = 0;
mFac.offset = 0;
mFac.size = 0;
mSac.offset = 0;
mSac.size = 0;
mKc.offset = 0;
mKc.size = 0;
}
void AciHeader::calculateSectionOffsets() void AciHeader::calculateSectionOffsets()
{ {
mFac.offset = align(sizeof(sAciHeader), kAciAlignSize); mFac.offset = align(mHeaderOffset, kAciAlignSize) + align(sizeof(sAciHeader), kAciAlignSize);
mSac.offset = mFac.offset + align(mFac.size, kAciAlignSize); mSac.offset = mFac.offset + align(mFac.size, kAciAlignSize);
mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize); mKc.offset = mSac.offset + align(mSac.size, kAciAlignSize);
} }
bool AciHeader::isEqual(const AciHeader & other) const bool AciHeader::isEqual(const AciHeader & other) const
{ {
return (mType == other.mType) \ return (mHeaderOffset == other.mHeaderOffset) \
&& (mType == other.mType) \
&& (mAcidSize == other.mAcidSize) \ && (mAcidSize == other.mAcidSize) \
&& (mProgramId == other.mProgramId) \ && (mProgramId == other.mProgramId) \
&& (mFac == other.mFac) \ && (mFac == other.mFac) \
@ -39,6 +28,7 @@ void AciHeader::copyFrom(const AciHeader & other)
} }
else else
{ {
mHeaderOffset = other.mHeaderOffset;
mType = other.mType; mType = other.mType;
mAcidSize = other.mAcidSize; mAcidSize = other.mAcidSize;
mProgramId = other.mProgramId; mProgramId = other.mProgramId;
@ -50,7 +40,7 @@ void AciHeader::copyFrom(const AciHeader & other)
AciHeader::AciHeader() AciHeader::AciHeader()
{ {
clearVariables(); clear();
} }
AciHeader::AciHeader(const AciHeader & other) AciHeader::AciHeader(const AciHeader & other)
@ -106,17 +96,36 @@ void AciHeader::exportBinary()
throw fnd::Exception(kModuleName, "Unexpected ACI type"); throw fnd::Exception(kModuleName, "Unexpected ACI type");
} }
// set offset/size
calculateSectionOffsets();
hdr->fac().set_offset(mFac.offset);
hdr->fac().set_size(mFac.size);
hdr->sac().set_offset(mSac.offset);
hdr->sac().set_size(mSac.size);
hdr->kc().set_offset(mKc.offset);
hdr->kc().set_size(mKc.size);
hdr->set_version(mFormatVersion);
if (mType == TYPE_ACI0) if (mType == TYPE_ACI0)
{ {
// set program // set program
hdr->set_program_id(mProgramId); hdr->set_program_id(mProgramId);
switch (mFormatVersion)
{
case(0):
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
}
} }
else if (mType == TYPE_ACID) else if (mType == TYPE_ACID)
{ {
hdr->set_version(mAcidVersion);
switch (mAcidVersion) switch (mFormatVersion)
{ {
case(0): case(0):
mAcidSize = getAciSize();
hdr->set_size(mAcidSize); hdr->set_size(mAcidSize);
hdr->set_program_id_min(0); hdr->set_program_id_min(0);
hdr->set_program_id_max(0); hdr->set_program_id_max(0);
@ -130,16 +139,6 @@ void AciHeader::exportBinary()
throw fnd::Exception(kModuleName, "Unsupported ACID version"); throw fnd::Exception(kModuleName, "Unsupported ACID version");
} }
} }
// set offset/size
calculateSectionOffsets();
hdr->fac().set_offset(mFac.offset);
hdr->fac().set_size(mFac.size);
hdr->sac().set_offset(mSac.offset);
hdr->sac().set_size(mSac.size);
hdr->kc().set_offset(mKc.offset);
hdr->kc().set_size(mKc.size);
} }
void AciHeader::importBinary(const u8 * bytes, size_t len) void AciHeader::importBinary(const u8 * bytes, size_t len)
@ -149,7 +148,7 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
throw fnd::Exception(kModuleName, "ACI header too small"); throw fnd::Exception(kModuleName, "ACI header too small");
} }
clearVariables(); clear();
mBinaryBlob.alloc(sizeof(sAciHeader)); mBinaryBlob.alloc(sizeof(sAciHeader));
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader)); memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sAciHeader));
@ -173,16 +172,24 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
if (mType == TYPE_ACI0) if (mType == TYPE_ACI0)
{ {
mProgramId = hdr->program_id(); mProgramId = hdr->program_id();
mAcidVersion = 0; mFormatVersion = hdr->version();
mAcidSize = 0; mAcidSize = 0;
mProgramIdMin = 0; mProgramIdMin = 0;
mProgramIdMax = 0; mProgramIdMax = 0;
switch (mFormatVersion)
{
case(0):
break;
default:
throw fnd::Exception(kModuleName, "Unsupported ACI0 version");
}
} }
else if (mType == TYPE_ACID) else if (mType == TYPE_ACID)
{ {
mProgramId = 0; mProgramId = 0;
mAcidVersion = hdr->version(); mFormatVersion = hdr->version();
switch (mAcidVersion) switch (mFormatVersion)
{ {
case(0): case(0):
mAcidSize = hdr->size(); mAcidSize = hdr->size();
@ -199,17 +206,28 @@ void AciHeader::importBinary(const u8 * bytes, size_t len)
} }
} }
mFac.offset = hdr->fac().offset(); // the header offset is the MIN(sac.offset, fac.offset, kc.offset) - sizeof(sHeader)
mHeaderOffset = MAX(MIN(hdr->sac().offset(), MIN(hdr->fac().offset(), hdr->kc().offset())), align(sizeof(sAciHeader), kAciAlignSize)) - align(sizeof(sAciHeader), kAciAlignSize);
mFac.offset = hdr->fac().offset() - mHeaderOffset;
mFac.size = hdr->fac().size(); mFac.size = hdr->fac().size();
mSac.offset = hdr->sac().offset(); mSac.offset = hdr->sac().offset() - mHeaderOffset;
mSac.size = hdr->sac().size(); mSac.size = hdr->sac().size();
mKc.offset = hdr->kc().offset(); mKc.offset = hdr->kc().offset() - mHeaderOffset;
mKc.size = hdr->kc().size(); mKc.size = hdr->kc().size();
} }
void nx::AciHeader::clear() void nx::AciHeader::clear()
{ {
clearVariables(); mHeaderOffset = 0;
mType = TYPE_ACI0;
mProgramId = 0;
mFac.offset = 0;
mFac.size = 0;
mSac.offset = 0;
mSac.size = 0;
mKc.offset = 0;
mKc.size = 0;
} }
size_t nx::AciHeader::getAciSize() const size_t nx::AciHeader::getAciSize() const
@ -217,14 +235,14 @@ size_t nx::AciHeader::getAciSize() const
return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader)); return MAX(MAX(MAX(mSac.offset + mSac.size, mKc.offset + mKc.size), mFac.offset + mFac.size), sizeof(sAciHeader));
} }
u32 nx::AciHeader::getAcidVersion() const u32 nx::AciHeader::getFormatVersion() const
{ {
return mAcidVersion; return mFormatVersion;
} }
void nx::AciHeader::setAcidVersion(u32 version) void nx::AciHeader::setFormatVersion(u32 version)
{ {
mAcidVersion = version; mFormatVersion = version;
} }
size_t nx::AciHeader::getAcidSize() const size_t nx::AciHeader::getAcidSize() const
@ -232,10 +250,12 @@ size_t nx::AciHeader::getAcidSize() const
return mAcidSize; return mAcidSize;
} }
/*
void nx::AciHeader::setAcidSize(size_t size) void nx::AciHeader::setAcidSize(size_t size)
{ {
mAcidSize = size; mAcidSize = size;
} }
*/
u64 nx::AciHeader::getProgramIdMin() const u64 nx::AciHeader::getProgramIdMin() const
{ {
@ -257,6 +277,11 @@ void nx::AciHeader::setProgramIdMax(u64 program_id)
mProgramIdMax = program_id; mProgramIdMax = program_id;
} }
void nx::AciHeader::setHeaderOffset(size_t offset)
{
mHeaderOffset = offset;
}
AciHeader::AciType AciHeader::getAciType() const AciHeader::AciType AciHeader::getAciType() const
{ {
return mType; return mType;
@ -282,7 +307,7 @@ const AciHeader::sSection & AciHeader::getFacPos() const
return mFac; return mFac;
} }
void AciHeader::setFacSize(u32 size) void AciHeader::setFacSize(size_t size)
{ {
mFac.size = size; mFac.size = size;
} }
@ -292,7 +317,7 @@ const AciHeader::sSection & AciHeader::getSacPos() const
return mSac; return mSac;
} }
void AciHeader::setSacSize(u32 size) void AciHeader::setSacSize(size_t size)
{ {
mSac.size = size; mSac.size = size;
} }
@ -302,7 +327,7 @@ const AciHeader::sSection & AciHeader::getKcPos() const
return mKc; return mKc;
} }
void AciHeader::setKcSize(u32 size) void AciHeader::setKcSize(size_t size)
{ {
mKc.size = size; mKc.size = size;
} }

View file

@ -63,24 +63,25 @@ namespace nx
void setProgramId(u64 program_id); void setProgramId(u64 program_id);
// ACID only // ACID only
u32 getAcidVersion() const;
void setAcidVersion(u32 version);
size_t getAcidSize() const; size_t getAcidSize() const;
void setAcidSize(size_t size); //void setAcidSize(size_t size);
u64 getProgramIdMin() const; u64 getProgramIdMin() const;
void setProgramIdMin(u64 program_id); void setProgramIdMin(u64 program_id);
u64 getProgramIdMax() const; u64 getProgramIdMax() const;
void setProgramIdMax(u64 program_id); void setProgramIdMax(u64 program_id);
// ACID & ACI0 // ACID & ACI0
void setHeaderOffset(size_t offset);
AciType getAciType() const; AciType getAciType() const;
void setAciType(AciType type); void setAciType(AciType type);
u32 getFormatVersion() const;
void setFormatVersion(u32 version);
const sSection& getFacPos() const; const sSection& getFacPos() const;
void setFacSize(u32 size); void setFacSize(size_t size);
const sSection& getSacPos() const; const sSection& getSacPos() const;
void setSacSize(u32 size); void setSacSize(size_t size);
const sSection& getKcPos() const; const sSection& getKcPos() const;
void setKcSize(u32 size); void setKcSize(size_t size);
private: private:
const std::string kModuleName = "ACI_HEADER"; const std::string kModuleName = "ACI_HEADER";
@ -94,8 +95,8 @@ namespace nx
private: private:
u8 signature_[4]; u8 signature_[4];
u32 size_; // includes prefacing signature, set only in ACID since it is signed u32 size_; // includes prefacing signature, set only in ACID since it is signed
u8 reserved_0[4];
u32 version_; // set in ACID only, v0 has size, but no pid range, v1 has no size by pid range u32 version_; // set in ACID only, v0 has size, but no pid range, v1 has no size by pid range
u8 reserved_1[4];
u64 program_id_; // set only in ACI0 (since ACID is generic) u64 program_id_; // set only in ACI0 (since ACID is generic)
u64 program_id_max_; u64 program_id_max_;
struct sAciSection struct sAciSection
@ -109,7 +110,7 @@ namespace nx
u32 size() const { return le_word(size_); } u32 size() const { return le_word(size_); }
void set_size(u32 size) { size_ = le_word(size); } void set_size(u32 size) { size_ = le_word(size); }
} fac_, sac_, kc_, reserved_3; } fac_, sac_, kc_;
public: public:
const char* signature() const { return (const char*)signature_; } const char* signature() const { return (const char*)signature_; }
void set_signature(const char* signature) { memcpy(signature_, signature, 4); } void set_signature(const char* signature) { memcpy(signature_, signature, 4); }
@ -147,16 +148,15 @@ namespace nx
u64 mProgramId; u64 mProgramId;
// ACID variables // ACID variables
u32 mAcidVersion;
size_t mAcidSize; size_t mAcidSize;
u64 mProgramIdMin; u64 mProgramIdMin;
u64 mProgramIdMax; u64 mProgramIdMax;
// ACI(D) variables // ACI(D) variables
size_t mHeaderOffset;
AciType mType; AciType mType;
u32 mFormatVersion;
sSection mFac, mSac, mKc; sSection mFac, mSac, mKc;
void clearVariables();
void calculateSectionOffsets(); void calculateSectionOffsets();
bool isEqual(const AciHeader& other) const; bool isEqual(const AciHeader& other) const;
void copyFrom(const AciHeader& other); void copyFrom(const AciHeader& other);

142
lib/nx/AcidBinary.cpp Normal file
View file

@ -0,0 +1,142 @@
#include "AcidBinary.h"
nx::AcidBinary::AcidBinary()
{
clear();
}
nx::AcidBinary::AcidBinary(const AcidBinary & other)
{
copyFrom(other);
}
nx::AcidBinary::AcidBinary(const u8 * bytes, size_t len)
{
importBinary(bytes, len);
}
void nx::AcidBinary::clear()
{
AciBinary::clear();
mEmbeddedPublicKey = crypto::rsa::sRsa2048Key();
}
const crypto::rsa::sRsa2048Key & nx::AcidBinary::getPublicKey() const
{
return mEmbeddedPublicKey;
}
void nx::AcidBinary::setPublicKey(const crypto::rsa::sRsa2048Key & key)
{
mEmbeddedPublicKey = key;
}
bool nx::AcidBinary::isEqual(const AcidBinary & other) const
{
return AciBinary::operator==(other) \
&& (mEmbeddedPublicKey == other.mEmbeddedPublicKey);
}
void nx::AcidBinary::copyFrom(const AcidBinary & other)
{
if (other.getSize())
{
importBinary(other.getBytes(), other.getSize());
}
else
{
AciBinary::operator=(other);
mEmbeddedPublicKey = other.mEmbeddedPublicKey;
}
}
bool nx::AcidBinary::operator==(const AcidBinary & other) const
{
return isEqual(other);
}
bool nx::AcidBinary::operator!=(const AcidBinary & other) const
{
return !isEqual(other);
}
void nx::AcidBinary::operator=(const AcidBinary & other)
{
copyFrom(other);
}
const u8 * nx::AcidBinary::getBytes() const
{
return mBinaryBlob.getBytes();
}
size_t nx::AcidBinary::getSize() const
{
return mBinaryBlob.getSize();
}
void nx::AcidBinary::exportBinary()
{
AciBinary::setHeaderOffset(crypto::rsa::kRsa2048Size); // not include signature
AciBinary::exportBinary();
mBinaryBlob.alloc(AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2);
memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mEmbeddedPublicKey.modulus, crypto::rsa::kRsa2048Size);
memcpy(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size * 2, AciBinary::getBytes(), AciBinary::getSize());
}
void nx::AcidBinary::signBinary(const crypto::rsa::sRsa2048Key & key)
{
if (mBinaryBlob.getSize() == 0)
{
exportBinary();
}
u8 hash[crypto::sha::kSha256HashLen];
crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash);
if (crypto::rsa::pkcs::rsaSign(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0)
{
throw fnd::Exception(kModuleName, "Failed to sign ACID");
}
}
void nx::AcidBinary::importBinary(const u8 * bytes, size_t len)
{
if (len <= crypto::rsa::kRsa2048Size*2)
{
throw fnd::Exception(kModuleName, "ACID binary too small");
}
// import aci binary past sig + pubkey
AciBinary::importBinary(bytes + crypto::rsa::kRsa2048Size * 2, len - crypto::rsa::kRsa2048Size * 2);
// save internal copy
size_t acid_size = AciBinary::getSize() + crypto::rsa::kRsa2048Size * 2;
if (acid_size > len)
{
throw fnd::Exception(kModuleName, "ACID binary too small");
}
mBinaryBlob.alloc(acid_size);
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
memcpy(mEmbeddedPublicKey.modulus, bytes + crypto::rsa::kRsa2048Size, crypto::rsa::kRsa2048Size);
}
void nx::AcidBinary::verifyBinary(const crypto::rsa::sRsa2048Key & key)
{
if (mBinaryBlob.getSize() == 0)
{
throw fnd::Exception(kModuleName, "No ACID binary exists to verify");
}
u8 hash[crypto::sha::kSha256HashLen];
crypto::sha::Sha256(mBinaryBlob.getBytes() + crypto::rsa::kRsa2048Size, mBinaryBlob.getSize() - crypto::rsa::kRsa2048Size, hash);
if (crypto::rsa::pkcs::rsaVerify(key, crypto::sha::HASH_SHA256, hash, mBinaryBlob.getBytes()) != 0)
{
throw fnd::Exception(kModuleName, "Failed to verify ACID");
}
}

51
lib/nx/AcidBinary.h Normal file
View file

@ -0,0 +1,51 @@
#pragma once
#include <string>
#include <fnd/memory_blob.h>
#include <nx/ISerialiseableBinary.h>
#include <nx/AciBinary.h>
#include <crypto/rsa.h>
namespace nx
{
class AcidBinary :
public AciBinary
{
public:
AcidBinary();
AcidBinary(const AcidBinary& other);
AcidBinary(const u8* bytes, size_t len);
bool operator==(const AcidBinary& other) const;
bool operator!=(const AcidBinary& other) const;
void operator=(const AcidBinary& other);
// to be used after export
const u8* getBytes() const;
size_t getSize() const;
// export/import binary
virtual void exportBinary();
void signBinary(const crypto::rsa::sRsa2048Key& key);
virtual void importBinary(const u8* bytes, size_t len);
void verifyBinary(const crypto::rsa::sRsa2048Key& key);
// variables
virtual void clear();
const crypto::rsa::sRsa2048Key& getPublicKey() const;
void setPublicKey(const crypto::rsa::sRsa2048Key& key);
private:
const std::string kModuleName = "ACID_BINARY";
// raw binary
fnd::MemoryBlob mBinaryBlob;
// variables
crypto::rsa::sRsa2048Key mEmbeddedPublicKey;
bool isEqual(const AcidBinary& other) const;
void copyFrom(const AcidBinary& other);
};
}

View file

@ -1,156 +1,102 @@
#include "FacBinary.h" #include "FacBinary.h"
using namespace nx;
FacBinary::FacBinary() :
mHeader()
{
clearVariables();
}
FacBinary::FacBinary(const FacBinary & other) nx::FacBinary::FacBinary()
{ {}
importBinary(other.getBytes(), other.getSize());
}
FacBinary::FacBinary(const u8 * bytes, size_t len) nx::FacBinary::FacBinary(const FacBinary & other)
{
importBinary(bytes, len);
}
bool FacBinary::operator==(const FacBinary & other) const
{
return isEqual(other);
}
bool FacBinary::operator!=(const FacBinary & other) const
{
return !isEqual(other);
}
void FacBinary::operator=(const FacBinary & other)
{ {
copyFrom(other); copyFrom(other);
} }
const u8 * FacBinary::getBytes() const nx::FacBinary::FacBinary(const u8 * bytes, size_t len)
{
importBinary(bytes, len);
}
bool nx::FacBinary::operator==(const FacBinary & other) const
{
return isEqual(other);
}
bool nx::FacBinary::operator!=(const FacBinary & other) const
{
return !isEqual(other);
}
void nx::FacBinary::operator=(const FacBinary & other)
{
copyFrom(other);
}
const u8 * nx::FacBinary::getBytes() const
{ {
return mBinaryBlob.getBytes(); return mBinaryBlob.getBytes();
} }
size_t FacBinary::getSize() const size_t nx::FacBinary::getSize() const
{ {
return mBinaryBlob.getSize(); return mBinaryBlob.getSize();
} }
void FacBinary::exportBinary() void nx::FacBinary::exportBinary()
{ {
mHeader.setFsaRights(mFsaRights); FacHeader::setContentOwnerIdSize(mContentOwnerIdList.getSize() * sizeof(u32));
mHeader.setContentOwnerIdSize(mContentOwnerIds.getSize() * sizeof(u32)); FacHeader::setSaveDataOwnerIdSize(mSaveDataOwnerIdList.getSize() * sizeof(u32));
mHeader.setSaveDataOwnerIdSize(mSaveDataOwnerIds.getSize() * sizeof(u32)); FacHeader::exportBinary();
mHeader.exportBinary();
mBinaryBlob.alloc(mHeader.getFacSize()); mBinaryBlob.alloc(getFacSize());
memcpy(mBinaryBlob.getBytes(), mHeader.getBytes(), mHeader.getSize()); memcpy(mBinaryBlob.getBytes(), FacHeader::getBytes(), FacHeader::getSize());
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getContentOwnerIdOffset()); u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset());
for (size_t i = 0; i < mContentOwnerIds.getSize(); i++) for (size_t i = 0; i < mContentOwnerIdList.getSize(); i++)
{ {
rawContentOwnerIds[i] = le_word(mContentOwnerIds[i]); rawContentOwnerIds[i] = le_word(mContentOwnerIdList[i]);
} }
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getSaveDataOwnerIdOffset()); u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset());
for (size_t i = 0; i < mSaveDataOwnerIds.getSize(); i++) for (size_t i = 0; i < mSaveDataOwnerIdList.getSize(); i++)
{ {
rawSaveDataOwnerIds[i] = le_word(mSaveDataOwnerIds[i]); rawSaveDataOwnerIds[i] = le_word(mSaveDataOwnerIdList[i]);
} }
} }
void FacBinary::importBinary(const u8 * bytes, size_t len) void nx::FacBinary::importBinary(const u8 * bytes, size_t len)
{ {
clearVariables(); clear();
mHeader.importBinary(bytes, len); FacHeader::importBinary(bytes, len);
if (mHeader.getFacSize() > len) if (FacHeader::getFacSize() > len)
{ {
throw fnd::Exception(kModuleName, "FAC binary too small"); throw fnd::Exception(kModuleName, "FAC binary too small");
} }
mBinaryBlob.alloc(mHeader.getFacSize()); mBinaryBlob.alloc(FacHeader::getFacSize());
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
mFsaRights = mHeader.getFsaRights(); u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getContentOwnerIdOffset());
u32* rawContentOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getContentOwnerIdOffset()); size_t rawContentOwnerIdNum = FacHeader::getContentOwnerIdSize() / sizeof(u32);
size_t rawContentOwnerIdNum = mHeader.getContentOwnerIdSize() / sizeof(u32);
for (size_t i = 0; i < rawContentOwnerIdNum; i++) for (size_t i = 0; i < rawContentOwnerIdNum; i++)
{ {
addContentOwnerId(le_word(rawContentOwnerIds[i])); mContentOwnerIdList.addElement(le_word(rawContentOwnerIds[i]));
} }
u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + mHeader.getSaveDataOwnerIdOffset()); u32* rawSaveDataOwnerIds = (u32*)(mBinaryBlob.getBytes() + FacHeader::getSaveDataOwnerIdOffset());
size_t rawSaveDataOwnerIdNum = mHeader.getSaveDataOwnerIdSize() / sizeof(u32); size_t rawSaveDataOwnerIdNum = FacHeader::getSaveDataOwnerIdSize() / sizeof(u32);
for (size_t i = 0; i < rawSaveDataOwnerIdNum; i++) for (size_t i = 0; i < rawSaveDataOwnerIdNum; i++)
{ {
addSaveDataOwnerId(le_word(rawSaveDataOwnerIds[i])); mSaveDataOwnerIdList.addElement(le_word(rawSaveDataOwnerIds[i]));
} }
} }
void nx::FacBinary::clear() bool nx::FacBinary::isEqual(const FacBinary & other) const
{ {
clearVariables(); return (FacHeader::operator==(other)) \
&& (mContentOwnerIdList == other.mContentOwnerIdList) \
&& (mSaveDataOwnerIdList == other.mSaveDataOwnerIdList);
} }
bool FacBinary::isPermissionSet(FsAccessFlag flag) const void nx::FacBinary::copyFrom(const FacBinary & other)
{
return (mFsaRights & flag) == flag;
}
void FacBinary::addPermission(FsAccessFlag flag)
{
mFsaRights |= flag;
}
void FacBinary::removePermission(FsAccessFlag flag)
{
mFsaRights &= ~(u64)flag;
}
const fnd::List<u32>& FacBinary::getContentOwnerIds() const
{
return mContentOwnerIds;
}
void FacBinary::addContentOwnerId(u32 id)
{
mContentOwnerIds.addElement(id);
}
const fnd::List<u32>& FacBinary::getSaveDataOwnerIds() const
{
return mSaveDataOwnerIds;
}
void FacBinary::addSaveDataOwnerId(u32 id)
{
mSaveDataOwnerIds.addElement(id);
}
void FacBinary::clearVariables()
{
mHeader = FacHeader();
mFsaRights = 0;
mContentOwnerIds.clear();
mSaveDataOwnerIds.clear();
}
bool FacBinary::isEqual(const FacBinary & other) const
{
return (mHeader == other.mHeader) \
&& (mFsaRights == other.mFsaRights) \
&& (mContentOwnerIds == other.mContentOwnerIds) \
&& (mSaveDataOwnerIds == other.mSaveDataOwnerIds);
}
void FacBinary::copyFrom(const FacBinary & other)
{ {
if (other.getSize()) if (other.getSize())
{ {
@ -158,10 +104,35 @@ void FacBinary::copyFrom(const FacBinary & other)
} }
else else
{ {
mBinaryBlob.clear(); FacHeader::operator=(other);
mHeader = other.mHeader; mContentOwnerIdList = other.mContentOwnerIdList;
mFsaRights = other.mFsaRights; mSaveDataOwnerIdList = other.mSaveDataOwnerIdList;
mContentOwnerIds = other.mContentOwnerIds;
mSaveDataOwnerIds = other.mSaveDataOwnerIds;
} }
} }
void nx::FacBinary::clear()
{
FacHeader::clear();
mContentOwnerIdList.clear();
mSaveDataOwnerIdList.clear();
}
const fnd::List<u32>& nx::FacBinary::getContentOwnerIdList() const
{
return mContentOwnerIdList;
}
void nx::FacBinary::setContentOwnerIdList(const fnd::List<u32>& list)
{
mContentOwnerIdList = list;
}
const fnd::List<u32>& nx::FacBinary::getSaveDataOwnerIdList() const
{
return mSaveDataOwnerIdList;
}
void nx::FacBinary::setSaveDataOwnerIdList(const fnd::List<u32>& list)
{
mSaveDataOwnerIdList = list;
}

View file

@ -5,38 +5,13 @@
#include <nx/ISerialiseableBinary.h> #include <nx/ISerialiseableBinary.h>
#include <nx/FacHeader.h> #include <nx/FacHeader.h>
namespace nx namespace nx
{ {
class FacBinary : class FacBinary :
public ISerialiseableBinary public FacHeader
{ {
public: public:
enum FsAccessFlag
{
FSA_APPLICATION_INFO = BIT(0),
FSA_BOOT_MODE_CONTROL = BIT(1),
FSA_CALIBRATION = BIT(2),
FSA_SYSTEM_SAVE_DATA = BIT(3),
FSA_GAME_CARD = BIT(4),
FSA_SAVE_DATA_BACKUP = BIT(5),
FSA_SAVE_DATA_MANAGEMENT = BIT(6),
FSA_BIS_ALL_RAW = BIT(7),
FSA_GAME_CARD_RAW = BIT(8),
FSA_GAME_CARD_PRIVATE = BIT(9),
FSA_SET_TIME = BIT(10),
FSA_CONTENT_MANAGER = BIT(11),
FSA_IMAGE_MANAGER = BIT(12),
FSA_CREATE_SAVE_DATA = BIT(13),
FSA_SYSTEM_SAVE_DATA_MANAGEMENT = BIT(14),
FSA_BIS_FILE_SYSTEM = BIT(15),
FSA_SYSTEM_UPDATE = BIT(16),
FSA_SAVE_DATA_META = BIT(17),
FSA_DEVICE_SAVE_CONTROL = BIT(19),
FSA_SETTINGS_CONTROL = BIT(20),
FSA_DEBUG = BIT(62),
FSA_FULL_PERMISSION = BIT(63),
};
FacBinary(); FacBinary();
FacBinary(const FacBinary& other); FacBinary(const FacBinary& other);
FacBinary(const u8* bytes, size_t len); FacBinary(const u8* bytes, size_t len);
@ -55,28 +30,24 @@ namespace nx
// variables // variables
void clear(); void clear();
bool isPermissionSet(FsAccessFlag flag) const;
void addPermission(FsAccessFlag flag);
void removePermission(FsAccessFlag flag);
const fnd::List<u32>& getContentOwnerIds() const; const fnd::List<u32>& getContentOwnerIdList() const;
void addContentOwnerId(u32 id); void setContentOwnerIdList(const fnd::List<u32>& list);
const fnd::List<u32>& getSaveDataOwnerIdList() const;
void setSaveDataOwnerIdList(const fnd::List<u32>& list);
const fnd::List<u32>& getSaveDataOwnerIds() const;
void addSaveDataOwnerId(u32 id);
private: private:
const std::string kModuleName = "FAC_BINARY"; const std::string kModuleName = "FAC_BINARY";
static const u32 kFacFormatVersion = 1;
// raw binary // raw binary
fnd::MemoryBlob mBinaryBlob; fnd::MemoryBlob mBinaryBlob;
// variables // variables
FacHeader mHeader; fnd::List<u32> mContentOwnerIdList;
u64 mFsaRights; fnd::List<u32> mSaveDataOwnerIdList;
fnd::List<u32> mContentOwnerIds;
fnd::List<u32> mSaveDataOwnerIds;
void clearVariables();
bool isEqual(const FacBinary& other) const; bool isEqual(const FacBinary& other) const;
void copyFrom(const FacBinary& other); void copyFrom(const FacBinary& other);
}; };

View file

@ -2,17 +2,20 @@
nx::FacHeader::FacHeader() nx::FacHeader::FacHeader() :
mFsaRights()
{ {
clearVariables(); clear();
} }
nx::FacHeader::FacHeader(const FacHeader & other) nx::FacHeader::FacHeader(const FacHeader & other) :
mFsaRights()
{ {
copyFrom(other); copyFrom(other);
} }
nx::FacHeader::FacHeader(const u8 * bytes, size_t len) nx::FacHeader::FacHeader(const u8 * bytes, size_t len) :
mFsaRights()
{ {
importBinary(bytes, len); importBinary(bytes, len);
} }
@ -47,8 +50,18 @@ void nx::FacHeader::exportBinary()
mBinaryBlob.alloc(sizeof(sFacHeader)); mBinaryBlob.alloc(sizeof(sFacHeader));
sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes(); sFacHeader* hdr = (sFacHeader*)mBinaryBlob.getBytes();
hdr->set_version(kFacFormatVersion); if (mVersion != kFacFormatVersion)
hdr->set_fac_flags(mFsaRights); {
fnd::Exception(kModuleName, "Unsupported format version");
}
hdr->set_version(mVersion);
u64 flag = 0;
for (size_t i = 0; i < mFsaRights.getSize(); i++)
{
flag |= BIT((u64)mFsaRights[i]);
}
hdr->set_fac_flags(flag);
calculateOffsets(); calculateOffsets();
hdr->content_owner_ids().set_start(mContentOwnerIdPos.offset); hdr->content_owner_ids().set_start(mContentOwnerIdPos.offset);
@ -72,8 +85,16 @@ void nx::FacHeader::importBinary(const u8 * bytes, size_t len)
{ {
throw fnd::Exception(kModuleName, "Unsupported FAC format version"); throw fnd::Exception(kModuleName, "Unsupported FAC format version");
} }
mVersion = hdr->version();
mFsaRights = hdr->fac_flags(); clear();
for (u64 i = 0; i < 64; i++)
{
if ((hdr->fac_flags() >> i) & 1)
{
mFsaRights.addElement((FsAccessFlag)i);
}
}
mContentOwnerIdPos.offset = hdr->content_owner_ids().start(); mContentOwnerIdPos.offset = hdr->content_owner_ids().start();
mContentOwnerIdPos.size = hdr->content_owner_ids().end() > hdr->content_owner_ids().start() ? hdr->content_owner_ids().end() - hdr->content_owner_ids().start() : 0; mContentOwnerIdPos.size = hdr->content_owner_ids().end() > hdr->content_owner_ids().start() ? hdr->content_owner_ids().end() - hdr->content_owner_ids().start() : 0;
mSaveDataOwnerIdPos.offset = hdr->save_data_owner_ids().start(); mSaveDataOwnerIdPos.offset = hdr->save_data_owner_ids().start();
@ -82,7 +103,11 @@ void nx::FacHeader::importBinary(const u8 * bytes, size_t len)
void nx::FacHeader::clear() void nx::FacHeader::clear()
{ {
clearVariables(); mFsaRights.clear();
mContentOwnerIdPos.offset = 0;
mContentOwnerIdPos.size = 0;
mSaveDataOwnerIdPos.offset = 0;
mSaveDataOwnerIdPos.size = 0;
} }
size_t nx::FacHeader::getFacSize() const size_t nx::FacHeader::getFacSize() const
@ -92,14 +117,28 @@ size_t nx::FacHeader::getFacSize() const
return MAX(MAX(savedata, content), sizeof(sFacHeader)); return MAX(MAX(savedata, content), sizeof(sFacHeader));
} }
u64 nx::FacHeader::getFsaRights() const u32 nx::FacHeader::getFormatVersion() const
{
return mVersion;
}
void nx::FacHeader::setFormatVersion(u32 version)
{
mVersion = version;
}
const fnd::List<nx::FacHeader::FsAccessFlag>& nx::FacHeader::getFsaRightsList() const
{ {
return mFsaRights; return mFsaRights;
} }
void nx::FacHeader::setFsaRights(u64 flag) void nx::FacHeader::setFsaRightsList(const fnd::List<FsAccessFlag>& list)
{ {
mFsaRights = flag; mFsaRights.clear();
for (size_t i = 0; i < list.getSize(); i++)
{
mFsaRights.hasElement(list[i]) ? mFsaRights.addElement(list[i]) : throw fnd::Exception(kModuleName, "FSA right already exists");
}
} }
size_t nx::FacHeader::getContentOwnerIdOffset() const size_t nx::FacHeader::getContentOwnerIdOffset() const
@ -132,15 +171,6 @@ void nx::FacHeader::setSaveDataOwnerIdSize(size_t size)
mSaveDataOwnerIdPos.size = size; mSaveDataOwnerIdPos.size = size;
} }
void nx::FacHeader::clearVariables()
{
mFsaRights = 0;
mContentOwnerIdPos.offset = 0;
mContentOwnerIdPos.size = 0;
mSaveDataOwnerIdPos.offset = 0;
mSaveDataOwnerIdPos.size = 0;
}
void nx::FacHeader::calculateOffsets() void nx::FacHeader::calculateOffsets()
{ {
mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4); mContentOwnerIdPos.offset = align(sizeof(sFacHeader), 4);

View file

@ -1,6 +1,7 @@
#pragma once #pragma once
#include <string> #include <string>
#include <fnd/memory_blob.h> #include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h> #include <nx/ISerialiseableBinary.h>
namespace nx namespace nx
@ -9,6 +10,32 @@ namespace nx
public ISerialiseableBinary public ISerialiseableBinary
{ {
public: public:
enum FsAccessFlag
{
FSA_APPLICATION_INFO,
FSA_BOOT_MODE_CONTROL,
FSA_CALIBRATION,
FSA_SYSTEM_SAVE_DATA,
FSA_GAME_CARD,
FSA_SAVE_DATA_BACKUP,
FSA_SAVE_DATA_MANAGEMENT,
FSA_BIS_ALL_RAW,
FSA_GAME_CARD_RAW,
FSA_GAME_CARD_PRIVATE,
FSA_SET_TIME,
FSA_CONTENT_MANAGER,
FSA_IMAGE_MANAGER,
FSA_CREATE_SAVE_DATA,
FSA_SYSTEM_SAVE_DATA_MANAGEMENT,
FSA_BIS_FILE_SYSTEM,
FSA_SYSTEM_UPDATE,
FSA_SAVE_DATA_META,
FSA_DEVICE_SAVE_CONTROL,
FSA_SETTINGS_CONTROL,
FSA_DEBUG = 62,
FSA_FULL_PERMISSION = 63,
};
FacHeader(); FacHeader();
FacHeader(const FacHeader& other); FacHeader(const FacHeader& other);
FacHeader(const u8* bytes, size_t len); FacHeader(const u8* bytes, size_t len);
@ -29,8 +56,11 @@ namespace nx
void clear(); void clear();
size_t getFacSize() const; size_t getFacSize() const;
u64 getFsaRights() const; u32 getFormatVersion() const;
void setFsaRights(u64 flag); void setFormatVersion(u32 version);
const fnd::List<FsAccessFlag>& getFsaRightsList() const;
void setFsaRightsList(const fnd::List<FsAccessFlag>& list);
size_t getContentOwnerIdOffset() const; size_t getContentOwnerIdOffset() const;
size_t getContentOwnerIdSize() const; size_t getContentOwnerIdSize() const;
@ -81,14 +111,14 @@ namespace nx
fnd::MemoryBlob mBinaryBlob; fnd::MemoryBlob mBinaryBlob;
// variables // variables
u64 mFsaRights; u32 mVersion;
fnd::List<FsAccessFlag> mFsaRights;
struct sSection struct sSection
{ {
size_t offset; size_t offset;
size_t size; size_t size;
} mContentOwnerIdPos, mSaveDataOwnerIdPos; } mContentOwnerIdPos, mSaveDataOwnerIdPos;
void clearVariables();
void calculateOffsets(); void calculateOffsets();
bool isEqual(const FacHeader& other) const; bool isEqual(const FacHeader& other) const;
void copyFrom(const FacHeader& other); void copyFrom(const FacHeader& other);

View file

@ -131,7 +131,15 @@ void nx::KcBinary::importBinary(const u8 * bytes, size_t len)
void nx::KcBinary::clear() void nx::KcBinary::clear()
{ {
clearVariables(); mBinaryBlob.clear();
mThreadInfo.clear();
mSystemCalls.clear();
mMemoryMap.clear();
mInterupts.clear();
mMiscParams.clear();
mKernelVersion.clear();
mHandleTableSize.clear();
mMiscFlags.clear();
} }
const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const const nx::ThreadInfoHandler & nx::KcBinary::getThreadInfo() const
@ -214,19 +222,6 @@ nx::MiscFlagsHandler & nx::KcBinary::getMiscFlags()
return mMiscFlags; return mMiscFlags;
} }
void nx::KcBinary::clearVariables()
{
mBinaryBlob.clear();
mThreadInfo.clear();
mSystemCalls.clear();
mMemoryMap.clear();
mInterupts.clear();
mMiscParams.clear();
mKernelVersion.clear();
mHandleTableSize.clear();
mMiscFlags.clear();
}
bool nx::KcBinary::isEqual(const KcBinary & other) const bool nx::KcBinary::isEqual(const KcBinary & other) const
{ {
return (mThreadInfo == other.mThreadInfo) \ return (mThreadInfo == other.mThreadInfo) \

View file

@ -41,7 +41,7 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len)
throw fnd::Exception(kModuleName, "NCA header size is too small"); throw fnd::Exception(kModuleName, "NCA header size is too small");
} }
clearVariables(); clear();
mBinaryBlob.alloc(sizeof(sNcaHeader)); mBinaryBlob.alloc(sizeof(sNcaHeader));
memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader)); memcpy(mBinaryBlob.getBytes(), bytes, sizeof(sNcaHeader));
@ -78,7 +78,12 @@ void NcaHeader::importBinary(const u8 * bytes, size_t len)
void nx::NcaHeader::clear() void nx::NcaHeader::clear()
{ {
clearVariables(); mBlockSize = 0;
mNcaSize = 0;
mProgramId = 0;
mUnk0 = 0;
mSections.clear();
mAesKeys.clear();
} }
u64 NcaHeader::getNcaSize() const u64 NcaHeader::getNcaSize() const
@ -135,16 +140,6 @@ void NcaHeader::addKey(const crypto::aes::sAes128Key & key)
mAesKeys.addElement(key); mAesKeys.addElement(key);
} }
void NcaHeader::clearVariables()
{
mBlockSize = 0;
mNcaSize = 0;
mProgramId = 0;
mUnk0 = 0;
mSections.clear();
mAesKeys.clear();
}
u64 NcaHeader::blockNumToSize(u32 block_num) const u64 NcaHeader::blockNumToSize(u32 block_num) const
{ {
return block_num*mBlockSize; return block_num*mBlockSize;
@ -185,7 +180,7 @@ void NcaHeader::copyFrom(const NcaHeader & other)
NcaHeader::NcaHeader() NcaHeader::NcaHeader()
{ {
clearVariables(); clear();
} }
NcaHeader::NcaHeader(const NcaHeader & other) NcaHeader::NcaHeader(const NcaHeader & other)

View file

@ -149,7 +149,6 @@ namespace nx
fnd::List<sSection> mSections; fnd::List<sSection> mSections;
fnd::List<crypto::aes::sAes128Key> mAesKeys; fnd::List<crypto::aes::sAes128Key> mAesKeys;
void clearVariables();
u64 blockNumToSize(u32 block_num) const; u64 blockNumToSize(u32 block_num) const;
u32 sizeToBlockNum(u64 real_size) const; u32 sizeToBlockNum(u64 real_size) const;
bool isEqual(const NcaHeader& other) const; bool isEqual(const NcaHeader& other) const;

136
lib/nx/NpdmBinary.cpp Normal file
View file

@ -0,0 +1,136 @@
#include "NpdmBinary.h"
nx::NpdmBinary::NpdmBinary() :
mAci(),
mAcid()
{
clear();
}
nx::NpdmBinary::NpdmBinary(const NpdmBinary & other) :
mAci(),
mAcid()
{
copyFrom(other);
}
nx::NpdmBinary::NpdmBinary(const u8 * bytes, size_t len) :
mAci(),
mAcid()
{
importBinary(bytes, len);
}
bool nx::NpdmBinary::operator==(const NpdmBinary & other) const
{
return isEqual(other);
}
bool nx::NpdmBinary::operator!=(const NpdmBinary & other) const
{
return !isEqual(other);
}
void nx::NpdmBinary::operator=(const NpdmBinary & other)
{
copyFrom(other);
}
void nx::NpdmBinary::exportBinary()
{
mAci.exportBinary();
mAcid.exportBinary();
setAciSize(mAci.getSize());
setAcidSize(mAcid.getSize());
}
void nx::NpdmBinary::importBinary(const u8 * bytes, size_t len)
{
// clear
clear();
// import header
NpdmHeader::importBinary(bytes, len);
// check size
if (getNpdmSize() > len)
{
throw fnd::Exception(kModuleName, "NPDM binary too small");
}
// save local copy
mBinaryBlob.alloc(getNpdmSize());
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
// import Aci/Acid
if (getAciPos().size)
{
mAci.importBinary(mBinaryBlob.getBytes() + getAciPos().offset, getAciPos().size);
}
if (getAcidPos().size)
{
mAcid.importBinary(mBinaryBlob.getBytes() + getAcidPos().offset, getAcidPos().size);
}
}
void nx::NpdmBinary::clear()
{
NpdmHeader::clear();
mAci.clear();
mAcid.clear();
}
const nx::AciBinary & nx::NpdmBinary::getAci() const
{
return mAci;
}
void nx::NpdmBinary::setAci(const AciBinary & aci)
{
mAci = aci;
}
const nx::AcidBinary & nx::NpdmBinary::getAcid() const
{
return mAcid;
}
void nx::NpdmBinary::setAcid(const AcidBinary & acid)
{
mAcid = acid;
}
bool nx::NpdmBinary::isEqual(const NpdmBinary & other) const
{
return (NpdmHeader::operator==(other)) \
&& (mAci == other.mAci) \
&& (mAcid == other.mAcid);
}
void nx::NpdmBinary::copyFrom(const NpdmBinary & other)
{
if (other.getSize())
{
importBinary(other.getBytes(), other.getSize());
}
else
{
NpdmHeader::operator=(other);
mAci = other.mAci;
mAcid = other.mAcid;
}
}
const u8 * nx::NpdmBinary::getBytes() const
{
return mBinaryBlob.getBytes();
}
size_t nx::NpdmBinary::getSize() const
{
return mBinaryBlob.getSize();
}

55
lib/nx/NpdmBinary.h Normal file
View file

@ -0,0 +1,55 @@
#pragma once
#include <string>
#include <fnd/memory_blob.h>
#include <fnd/List.h>
#include <nx/ISerialiseableBinary.h>
#include <nx/NpdmHeader.h>
#include <nx/AciBinary.h>
#include <nx/AcidBinary.h>
namespace nx
{
class NpdmBinary :
public NpdmHeader
{
public:
NpdmBinary();
NpdmBinary(const NpdmBinary& other);
NpdmBinary(const u8* bytes, size_t len);
bool operator==(const NpdmBinary& other) const;
bool operator!=(const NpdmBinary& other) const;
void operator=(const NpdmBinary& other);
// to be used after export
const u8* getBytes() const;
size_t getSize() const;
// export/import binary
void exportBinary();
void importBinary(const u8* bytes, size_t len);
// variables
void clear();
const AciBinary& getAci() const;
void setAci(const AciBinary& aci);
const AcidBinary& getAcid() const;
void setAcid(const AcidBinary& acid);
private:
const std::string kModuleName = "NPDM_BINARY";
// raw binary
fnd::MemoryBlob mBinaryBlob;
// variables
AciBinary mAci;
AcidBinary mAcid;
bool isEqual(const NpdmBinary& other) const;
void copyFrom(const NpdmBinary& other);
};
}

View file

@ -4,7 +4,7 @@
nx::NpdmHeader::NpdmHeader() nx::NpdmHeader::NpdmHeader()
{ {
clearVariables(); clear();
} }
nx::NpdmHeader::NpdmHeader(const NpdmHeader & other) nx::NpdmHeader::NpdmHeader(const NpdmHeader & other)
@ -42,23 +42,6 @@ size_t nx::NpdmHeader::getSize() const
return mBinaryBlob.getSize(); return mBinaryBlob.getSize();
} }
void nx::NpdmHeader::clearVariables()
{
mBinaryBlob.clear();
mInstructionType = INSTR_64BIT;
mProcAddressSpaceType = ADDR_SPACE_64BIT;
mMainThreadPriority = 0;
mMainThreadCoreNumber = 0;
mVersion = 0;
mMainThreadStackSize = 0;
mName.clear();
mProductCode.clear();
mAciPos.offset = 0;
mAciPos.size = 0;
mAcidPos.offset = 0;
mAcidPos.size = 0;
}
void nx::NpdmHeader::calculateOffsets() void nx::NpdmHeader::calculateOffsets()
{ {
mAcidPos.offset = align(sizeof(sNpdmHeader), kNpdmAlignSize); mAcidPos.offset = align(sizeof(sNpdmHeader), kNpdmAlignSize);
@ -70,7 +53,7 @@ bool nx::NpdmHeader::isEqual(const NpdmHeader & other) const
return (mInstructionType == other.mInstructionType) \ return (mInstructionType == other.mInstructionType) \
&& (mProcAddressSpaceType == other.mProcAddressSpaceType) \ && (mProcAddressSpaceType == other.mProcAddressSpaceType) \
&& (mMainThreadPriority == other.mMainThreadPriority) \ && (mMainThreadPriority == other.mMainThreadPriority) \
&& (mMainThreadCoreNumber == other.mMainThreadCoreNumber) \ && (mMainThreadCpuId == other.mMainThreadCpuId) \
&& (mVersion == other.mVersion) \ && (mVersion == other.mVersion) \
&& (mMainThreadStackSize == other.mMainThreadStackSize) \ && (mMainThreadStackSize == other.mMainThreadStackSize) \
&& (mName == other.mName) \ && (mName == other.mName) \
@ -90,7 +73,7 @@ void nx::NpdmHeader::copyFrom(const NpdmHeader & other)
mInstructionType = other.mInstructionType; mInstructionType = other.mInstructionType;
mProcAddressSpaceType = other.mProcAddressSpaceType; mProcAddressSpaceType = other.mProcAddressSpaceType;
mMainThreadPriority = other.mMainThreadPriority; mMainThreadPriority = other.mMainThreadPriority;
mMainThreadCoreNumber = other.mMainThreadCoreNumber; mMainThreadCpuId = other.mMainThreadCpuId;
mVersion = other.mVersion; mVersion = other.mVersion;
mMainThreadStackSize = other.mMainThreadStackSize; mMainThreadStackSize = other.mMainThreadStackSize;
mName = other.mName; mName = other.mName;
@ -109,7 +92,7 @@ void nx::NpdmHeader::exportBinary()
u8 flag = ((u8)(mInstructionType & 1) | (u8)((mProcAddressSpaceType & 3) << 1)) & 0xf; u8 flag = ((u8)(mInstructionType & 1) | (u8)((mProcAddressSpaceType & 3) << 1)) & 0xf;
hdr->set_flags(flag); hdr->set_flags(flag);
hdr->set_main_thread_priority(mMainThreadPriority); hdr->set_main_thread_priority(mMainThreadPriority);
hdr->set_main_thread_core_number(mMainThreadCoreNumber); hdr->set_main_thread_cpu_id(mMainThreadCpuId);
hdr->set_version(mVersion); hdr->set_version(mVersion);
hdr->set_main_thread_stack_size(mMainThreadStackSize); hdr->set_main_thread_stack_size(mMainThreadStackSize);
hdr->set_name(mName.c_str()); hdr->set_name(mName.c_str());
@ -129,7 +112,7 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
throw fnd::Exception(kModuleName, "NPDM header too small"); throw fnd::Exception(kModuleName, "NPDM header too small");
} }
clearVariables(); clear();
mBinaryBlob.alloc(sizeof(sNpdmHeader)); mBinaryBlob.alloc(sizeof(sNpdmHeader));
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
@ -144,11 +127,19 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
mInstructionType = (InstructionType)(flag & 1); mInstructionType = (InstructionType)(flag & 1);
mProcAddressSpaceType = (ProcAddrSpaceType)((flag >> 1) & 3); mProcAddressSpaceType = (ProcAddrSpaceType)((flag >> 1) & 3);
mMainThreadPriority = hdr->main_thread_priority(); mMainThreadPriority = hdr->main_thread_priority();
mMainThreadCoreNumber = hdr->main_thread_core_number(); mMainThreadCpuId = hdr->main_thread_cpu_id();
mVersion = hdr->version(); mVersion = hdr->version();
mMainThreadStackSize = hdr->main_thread_stack_size(); mMainThreadStackSize = hdr->main_thread_stack_size();
mName = std::string(hdr->name(), kNameMaxLen); mName = std::string(hdr->name(), kNameMaxLen);
if (mName[0] == '\0')
{
mName.clear();
}
mProductCode = std::string(hdr->product_code(), kProductCodeMaxLen); mProductCode = std::string(hdr->product_code(), kProductCodeMaxLen);
if (mProductCode[0] == '\0')
{
mProductCode.clear();
}
mAciPos.offset = hdr->aci().offset(); mAciPos.offset = hdr->aci().offset();
mAciPos.size = hdr->aci().size(); mAciPos.size = hdr->aci().size();
mAcidPos.offset = hdr->acid().offset(); mAcidPos.offset = hdr->acid().offset();
@ -157,7 +148,19 @@ void nx::NpdmHeader::importBinary(const u8 * bytes, size_t len)
void nx::NpdmHeader::clear() void nx::NpdmHeader::clear()
{ {
clearVariables(); mBinaryBlob.clear();
mInstructionType = INSTR_64BIT;
mProcAddressSpaceType = ADDR_SPACE_64BIT;
mMainThreadPriority = 0;
mMainThreadCpuId = 0;
mVersion = 0;
mMainThreadStackSize = 0;
mName.clear();
mProductCode.clear();
mAciPos.offset = 0;
mAciPos.size = 0;
mAcidPos.offset = 0;
mAcidPos.size = 0;
} }
size_t nx::NpdmHeader::getNpdmSize() const size_t nx::NpdmHeader::getNpdmSize() const
@ -200,14 +203,14 @@ void nx::NpdmHeader::setMainThreadPriority(u8 priority)
mMainThreadPriority = priority; mMainThreadPriority = priority;
} }
u8 nx::NpdmHeader::getMainThreadCoreNumber() const u8 nx::NpdmHeader::getMainThreadCpuId() const
{ {
return mMainThreadCoreNumber; return mMainThreadCpuId;
} }
void nx::NpdmHeader::setMainThreadCoreNumber(u8 core_num) void nx::NpdmHeader::setMainThreadCpuId(u8 core_num)
{ {
mMainThreadCoreNumber = core_num; mMainThreadCpuId = core_num;
} }
u32 nx::NpdmHeader::getVersion() const u32 nx::NpdmHeader::getVersion() const
@ -265,7 +268,7 @@ const nx::NpdmHeader::sSection & nx::NpdmHeader::getAciPos() const
return mAciPos; return mAciPos;
} }
void nx::NpdmHeader::setSetAciSize(size_t size) void nx::NpdmHeader::setAciSize(size_t size)
{ {
mAciPos.size = size; mAciPos.size = size;
} }
@ -275,7 +278,7 @@ const nx::NpdmHeader::sSection & nx::NpdmHeader::getAcidPos() const
return mAcidPos; return mAcidPos;
} }
void nx::NpdmHeader::setSetAcidSize(size_t size) void nx::NpdmHeader::setAcidSize(size_t size)
{ {
mAcidPos.size = size; mAcidPos.size = size;
} }

View file

@ -76,8 +76,8 @@ namespace nx
u8 getMainThreadPriority() const; u8 getMainThreadPriority() const;
void setMainThreadPriority(u8 priority); void setMainThreadPriority(u8 priority);
u8 getMainThreadCoreNumber() const; u8 getMainThreadCpuId() const;
void setMainThreadCoreNumber(u8 core_num); void setMainThreadCpuId(u8 cpu_id);
u32 getVersion() const; u32 getVersion() const;
void setVersion(u32 version); void setVersion(u32 version);
@ -92,10 +92,10 @@ namespace nx
void setProductCode(const std::string& product_code); void setProductCode(const std::string& product_code);
const sSection& getAciPos() const; const sSection& getAciPos() const;
void setSetAciSize(size_t size); void setAciSize(size_t size);
const sSection& getAcidPos() const; const sSection& getAcidPos() const;
void setSetAcidSize(size_t size); void setAcidSize(size_t size);
private: private:
const std::string kModuleName = "NPDM_HEADER"; const std::string kModuleName = "NPDM_HEADER";
const std::string kNpdmStructSig = "META"; const std::string kNpdmStructSig = "META";
@ -114,7 +114,7 @@ namespace nx
u8 flags_; u8 flags_;
u8 reserved_1; u8 reserved_1;
u8 main_thread_priority_; // 0-63 inclusive u8 main_thread_priority_; // 0-63 inclusive
u8 main_thread_core_number_; u8 main_thread_cpu_id_;
u8 reserved_2[8]; u8 reserved_2[8];
u32 version_; u32 version_;
u32 main_thread_stack_size_; // default 4096 u32 main_thread_stack_size_; // default 4096
@ -144,8 +144,8 @@ namespace nx
u8 main_thread_priority() const { return main_thread_priority_; } u8 main_thread_priority() const { return main_thread_priority_; }
void set_main_thread_priority(u8 priority) { main_thread_priority_ = priority; } void set_main_thread_priority(u8 priority) { main_thread_priority_ = priority; }
u8 main_thread_core_number() const { return main_thread_core_number_; } u8 main_thread_cpu_id() const { return main_thread_cpu_id_; }
void set_main_thread_core_number(u8 core_number) { main_thread_core_number_ = core_number; } void set_main_thread_cpu_id(u8 cpu_id) { main_thread_cpu_id_ = cpu_id; }
u32 version() const { return le_word(version_); } u32 version() const { return le_word(version_); }
void set_version(u32 version) { version_ = le_word(version); } void set_version(u32 version) { version_ = le_word(version); }
@ -174,7 +174,7 @@ namespace nx
InstructionType mInstructionType; InstructionType mInstructionType;
ProcAddrSpaceType mProcAddressSpaceType; ProcAddrSpaceType mProcAddressSpaceType;
u8 mMainThreadPriority; u8 mMainThreadPriority;
u8 mMainThreadCoreNumber; u8 mMainThreadCpuId;
u32 mVersion; u32 mVersion;
u32 mMainThreadStackSize; u32 mMainThreadStackSize;
std::string mName; std::string mName;
@ -182,7 +182,6 @@ namespace nx
sSection mAciPos; sSection mAciPos;
sSection mAcidPos; sSection mAcidPos;
void clearVariables();
void calculateOffsets(); void calculateOffsets();
bool isEqual(const NpdmHeader& other) const; bool isEqual(const NpdmHeader& other) const;
void copyFrom(const NpdmHeader& other); void copyFrom(const NpdmHeader& other);

View file

@ -59,7 +59,7 @@ void SacBinary::exportBinary()
void SacBinary::importBinary(const u8 * bytes, size_t len) void SacBinary::importBinary(const u8 * bytes, size_t len)
{ {
clearVariables(); clear();
mBinaryBlob.alloc(len); mBinaryBlob.alloc(len);
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize()); memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
@ -73,7 +73,8 @@ void SacBinary::importBinary(const u8 * bytes, size_t len)
void nx::SacBinary::clear() void nx::SacBinary::clear()
{ {
clearVariables(); mBinaryBlob.clear();
mServices.clear();
} }
const fnd::List<SacEntry>& SacBinary::getServiceList() const const fnd::List<SacEntry>& SacBinary::getServiceList() const
@ -86,12 +87,6 @@ void SacBinary::addService(const SacEntry& service)
mServices.addElement(service); mServices.addElement(service);
} }
void SacBinary::clearVariables()
{
mBinaryBlob.clear();
mServices.clear();
}
bool SacBinary::isEqual(const SacBinary & other) const bool SacBinary::isEqual(const SacBinary & other) const
{ {
return mServices == other.mServices; return mServices == other.mServices;

View file

@ -41,7 +41,6 @@ namespace nx
// variables // variables
fnd::List<SacEntry> mServices; fnd::List<SacEntry> mServices;
void clearVariables();
bool isEqual(const SacBinary& other) const; bool isEqual(const SacBinary& other) const;
void copyFrom(const SacBinary& other); void copyFrom(const SacBinary& other);
}; };

View file

@ -6,16 +6,16 @@ nx::ThreadInfoEntry::ThreadInfoEntry() :
mCap(kCapId), mCap(kCapId),
mMinPriority(kDefaultPriority), mMinPriority(kDefaultPriority),
mMaxPriority(kDefaultPriority), mMaxPriority(kDefaultPriority),
mMinCoreNumber(kDefaultCoreNumber), mMinCpuId(kDefaultCpuId),
mMaxCoreNumber(kDefaultCoreNumber) mMaxCpuId(kDefaultCpuId)
{} {}
nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapability & kernel_cap) : nx::ThreadInfoEntry::ThreadInfoEntry(const KernelCapability & kernel_cap) :
mCap(kCapId), mCap(kCapId),
mMinPriority(kDefaultPriority), mMinPriority(kDefaultPriority),
mMaxPriority(kDefaultPriority), mMaxPriority(kDefaultPriority),
mMinCoreNumber(kDefaultCoreNumber), mMinCpuId(kDefaultCpuId),
mMaxCoreNumber(kDefaultCoreNumber) mMaxCpuId(kDefaultCpuId)
{ {
setKernelCapability(kernel_cap); setKernelCapability(kernel_cap);
} }
@ -24,13 +24,13 @@ nx::ThreadInfoEntry::ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_co
mCap(kCapId), mCap(kCapId),
mMinPriority(kDefaultPriority), mMinPriority(kDefaultPriority),
mMaxPriority(kDefaultPriority), mMaxPriority(kDefaultPriority),
mMinCoreNumber(kDefaultCoreNumber), mMinCpuId(kDefaultCpuId),
mMaxCoreNumber(kDefaultCoreNumber) mMaxCpuId(kDefaultCpuId)
{ {
setMinPriority(min_priority); setMinPriority(min_priority);
setMaxPriority(max_priority); setMaxPriority(max_priority);
setMinCoreNumber(min_core_number); setMinCpuId(min_core_number);
setMaxCoreNumber(max_core_number); setMaxCpuId(max_core_number);
} }
const nx::KernelCapability & nx::ThreadInfoEntry::getKernelCapability() const const nx::KernelCapability & nx::ThreadInfoEntry::getKernelCapability() const
@ -81,34 +81,34 @@ void nx::ThreadInfoEntry::setMaxPriority(u8 priority)
updateCapField(); updateCapField();
} }
u8 nx::ThreadInfoEntry::getMinCoreNumber() const u8 nx::ThreadInfoEntry::getMinCpuId() const
{ {
return mMinCoreNumber; return mMinCpuId;
} }
void nx::ThreadInfoEntry::setMinCoreNumber(u8 core_num) void nx::ThreadInfoEntry::setMinCpuId(u8 core_num)
{ {
if (core_num > kMaxVal) if (core_num > kMaxVal)
{ {
throw fnd::Exception(kModuleName, "Illegal MinCoreNumber (range 0-63)"); throw fnd::Exception(kModuleName, "Illegal MinCoreNumber (range 0-63)");
} }
mMinCoreNumber = core_num; mMinCpuId = core_num;
updateCapField(); updateCapField();
} }
u8 nx::ThreadInfoEntry::getMaxCoreNumber() const u8 nx::ThreadInfoEntry::getMaxCpuId() const
{ {
return mMaxCoreNumber; return mMaxCpuId;
} }
void nx::ThreadInfoEntry::setMaxCoreNumber(u8 core_num) void nx::ThreadInfoEntry::setMaxCpuId(u8 core_num)
{ {
if (core_num > kMaxVal) if (core_num > kMaxVal)
{ {
throw fnd::Exception(kModuleName, "Illegal MaxCoreNumber (range 0-63)"); throw fnd::Exception(kModuleName, "Illegal MaxCoreNumber (range 0-63)");
} }
mMaxCoreNumber = core_num; mMaxCpuId = core_num;
updateCapField(); updateCapField();
} }

View file

@ -10,7 +10,7 @@ namespace nx
public: public:
ThreadInfoEntry(); ThreadInfoEntry();
ThreadInfoEntry(const KernelCapability& kernel_cap); ThreadInfoEntry(const KernelCapability& kernel_cap);
ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_core_number, u8 max_core_number); ThreadInfoEntry(u8 min_priority, u8 max_priority, u8 min_cpu_id, u8 max_cpu_id);
// kernel capability // kernel capability
const KernelCapability& getKernelCapability() const; const KernelCapability& getKernelCapability() const;
@ -21,10 +21,10 @@ namespace nx
void setMinPriority(u8 priority); void setMinPriority(u8 priority);
u8 getMaxPriority() const; u8 getMaxPriority() const;
void setMaxPriority(u8 priority); void setMaxPriority(u8 priority);
u8 getMinCoreNumber() const; u8 getMinCpuId() const;
void setMinCoreNumber(u8 core_num); void setMinCpuId(u8 cpu_id);
u8 getMaxCoreNumber() const; u8 getMaxCpuId() const;
void setMaxCoreNumber(u8 core_num); void setMaxCpuId(u8 cpu_id);
private: private:
const std::string kModuleName = "THREAD_INFO_ENTRY"; const std::string kModuleName = "THREAD_INFO_ENTRY";
@ -32,21 +32,21 @@ namespace nx
static const u8 kValBits = 6; static const u8 kValBits = 6;
static const u8 kMaxVal = BIT(kValBits)-1; static const u8 kMaxVal = BIT(kValBits)-1;
static const u8 kDefaultPriority = 6; static const u8 kDefaultPriority = 6;
static const u8 kDefaultCoreNumber = 8; static const u8 kDefaultCpuId = 8;
KernelCapability mCap; KernelCapability mCap;
u8 mMinPriority; u8 mMinPriority;
u8 mMaxPriority; u8 mMaxPriority;
u8 mMinCoreNumber; u8 mMinCpuId;
u8 mMaxCoreNumber; u8 mMaxCpuId;
inline void updateCapField() inline void updateCapField()
{ {
u32 field = 0; u32 field = 0;
field |= (u32)(mMinPriority & kMaxVal) << (kValBits * 0); field |= (u32)(mMinPriority & kMaxVal) << (kValBits * 0);
field |= (u32)(mMaxPriority & kMaxVal) << (kValBits * 1); field |= (u32)(mMaxPriority & kMaxVal) << (kValBits * 1);
field |= (u32)(mMinCoreNumber & kMaxVal) << (kValBits * 2); field |= (u32)(mMinCpuId & kMaxVal) << (kValBits * 2);
field |= (u32)(mMaxCoreNumber & kMaxVal) << (kValBits * 3); field |= (u32)(mMaxCpuId & kMaxVal) << (kValBits * 3);
mCap.setField(field); mCap.setField(field);
} }
@ -55,8 +55,8 @@ namespace nx
u32 field = mCap.getField(); u32 field = mCap.getField();
mMinPriority = (field >> (kValBits * 0)) & kMaxVal; mMinPriority = (field >> (kValBits * 0)) & kMaxVal;
mMaxPriority = (field >> (kValBits * 1)) & kMaxVal; mMaxPriority = (field >> (kValBits * 1)) & kMaxVal;
mMinCoreNumber = (field >> (kValBits * 2)) & kMaxVal; mMinCpuId = (field >> (kValBits * 2)) & kMaxVal;
mMaxCoreNumber = (field >> (kValBits * 3)) & kMaxVal; mMaxCpuId = (field >> (kValBits * 3)) & kMaxVal;
} }
}; };
} }

View file

@ -49,8 +49,8 @@ void nx::ThreadInfoHandler::clear()
mIsSet = false; mIsSet = false;
mEntry.setMaxPriority(0); mEntry.setMaxPriority(0);
mEntry.setMinPriority(0); mEntry.setMinPriority(0);
mEntry.setMaxCoreNumber(0); mEntry.setMaxCpuId(0);
mEntry.setMinCoreNumber(0); mEntry.setMinCpuId(0);
} }
bool nx::ThreadInfoHandler::isSet() const bool nx::ThreadInfoHandler::isSet() const
@ -80,25 +80,25 @@ void nx::ThreadInfoHandler::setMaxPriority(u8 priority)
mIsSet = true; mIsSet = true;
} }
u8 nx::ThreadInfoHandler::getMinCoreNumber() const u8 nx::ThreadInfoHandler::getMinCpuId() const
{ {
return mEntry.getMinCoreNumber(); return mEntry.getMinCpuId();
} }
void nx::ThreadInfoHandler::setMinCoreNumber(u8 core_num) void nx::ThreadInfoHandler::setMinCpuId(u8 core_num)
{ {
mEntry.setMinCoreNumber(core_num); mEntry.setMinCpuId(core_num);
mIsSet = true; mIsSet = true;
} }
u8 nx::ThreadInfoHandler::getMaxCoreNumber() const u8 nx::ThreadInfoHandler::getMaxCpuId() const
{ {
return mEntry.getMaxCoreNumber(); return mEntry.getMaxCpuId();
} }
void nx::ThreadInfoHandler::setMaxCoreNumber(u8 core_num) void nx::ThreadInfoHandler::setMaxCpuId(u8 core_num)
{ {
mEntry.setMaxCoreNumber(core_num); mEntry.setMaxCpuId(core_num);
mIsSet = true; mIsSet = true;
} }

View file

@ -25,10 +25,10 @@ namespace nx
void setMinPriority(u8 priority); void setMinPriority(u8 priority);
u8 getMaxPriority() const; u8 getMaxPriority() const;
void setMaxPriority(u8 priority); void setMaxPriority(u8 priority);
u8 getMinCoreNumber() const; u8 getMinCpuId() const;
void setMinCoreNumber(u8 core_num); void setMinCpuId(u8 core_num);
u8 getMaxCoreNumber() const; u8 getMaxCpuId() const;
void setMaxCoreNumber(u8 core_num); void setMaxCpuId(u8 core_num);
private: private:
const std::string kModuleName = "THREAD_INFO_HANDLER"; const std::string kModuleName = "THREAD_INFO_HANDLER";

View file

@ -20,6 +20,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="AciBinary.h" /> <ClInclude Include="AciBinary.h" />
<ClInclude Include="AcidBinary.h" />
<ClInclude Include="AciHeader.h" /> <ClInclude Include="AciHeader.h" />
<ClInclude Include="FacBinary.h" /> <ClInclude Include="FacBinary.h" />
<ClInclude Include="FacHeader.h" /> <ClInclude Include="FacHeader.h" />
@ -39,6 +40,7 @@
<ClInclude Include="MiscFlagsHandler.h" /> <ClInclude Include="MiscFlagsHandler.h" />
<ClInclude Include="MiscParamsEntry.h" /> <ClInclude Include="MiscParamsEntry.h" />
<ClInclude Include="MiscParamsHandler.h" /> <ClInclude Include="MiscParamsHandler.h" />
<ClInclude Include="NpdmBinary.h" />
<ClInclude Include="NpdmHeader.h" /> <ClInclude Include="NpdmHeader.h" />
<ClInclude Include="NcaHeader.h" /> <ClInclude Include="NcaHeader.h" />
<ClInclude Include="NXCrypto.h" /> <ClInclude Include="NXCrypto.h" />
@ -51,6 +53,7 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="AciBinary.cpp" /> <ClCompile Include="AciBinary.cpp" />
<ClCompile Include="AcidBinary.cpp" />
<ClCompile Include="AciHeader.cpp" /> <ClCompile Include="AciHeader.cpp" />
<ClCompile Include="FacBinary.cpp" /> <ClCompile Include="FacBinary.cpp" />
<ClCompile Include="FacHeader.cpp" /> <ClCompile Include="FacHeader.cpp" />
@ -68,6 +71,7 @@
<ClCompile Include="MiscFlagsHandler.cpp" /> <ClCompile Include="MiscFlagsHandler.cpp" />
<ClCompile Include="MiscParamsEntry.cpp" /> <ClCompile Include="MiscParamsEntry.cpp" />
<ClCompile Include="MiscParamsHandler.cpp" /> <ClCompile Include="MiscParamsHandler.cpp" />
<ClCompile Include="NpdmBinary.cpp" />
<ClCompile Include="NpdmHeader.cpp" /> <ClCompile Include="NpdmHeader.cpp" />
<ClCompile Include="NcaHeader.cpp" /> <ClCompile Include="NcaHeader.cpp" />
<ClCompile Include="SacBinary.cpp" /> <ClCompile Include="SacBinary.cpp" />

View file

@ -33,9 +33,6 @@
<ClInclude Include="FacHeader.h"> <ClInclude Include="FacHeader.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="FacBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SacBinary.h"> <ClInclude Include="SacBinary.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -102,6 +99,15 @@
<ClInclude Include="KcBinary.h"> <ClInclude Include="KcBinary.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="AcidBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FacBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NpdmBinary.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="NcaHeader.cpp"> <ClCompile Include="NcaHeader.cpp">
@ -116,9 +122,6 @@
<ClCompile Include="FacHeader.cpp"> <ClCompile Include="FacHeader.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="FacBinary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SacBinary.cpp"> <ClCompile Include="SacBinary.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -182,5 +185,14 @@
<ClCompile Include="KcBinary.cpp"> <ClCompile Include="KcBinary.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="AcidBinary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FacBinary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NpdmBinary.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>