mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
[libctr] Add initial code for CTR library.
This commit is contained in:
parent
44e054fb6a
commit
91eede10d2
22
NNTools.sln
22
NNTools.sln
|
@ -32,6 +32,10 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac", "lib\libhac\libhac
|
||||||
EndProject
|
EndProject
|
||||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac-hb", "lib\libhac-hb\libhac-hb.vcxproj", "{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}"
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libhac-hb", "lib\libhac-hb\libhac-hb.vcxproj", "{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libctr", "lib\libctr\libctr.vcxproj", "{96900163-D5A3-42AA-A387-D7D5DAD0A11E}"
|
||||||
|
EndProject
|
||||||
|
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ctr-test", "programs\ctr-test\ctr-test.vcxproj", "{93C2F450-6682-41F8-9E19-35363BA15EF6}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|x64 = Debug|x64
|
Debug|x64 = Debug|x64
|
||||||
|
@ -104,6 +108,22 @@ Global
|
||||||
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x64.Build.0 = Release|x64
|
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x64.Build.0 = Release|x64
|
||||||
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.ActiveCfg = Release|Win32
|
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.ActiveCfg = Release|Win32
|
||||||
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.Build.0 = Release|Win32
|
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Release|x64.Build.0 = Release|x64
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E}.Release|x86.Build.0 = Release|Win32
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Debug|x64.ActiveCfg = Debug|x64
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Debug|x64.Build.0 = Debug|x64
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Debug|x86.ActiveCfg = Debug|Win32
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Debug|x86.Build.0 = Debug|Win32
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Release|x64.ActiveCfg = Release|x64
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Release|x64.Build.0 = Release|x64
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Release|x86.ActiveCfg = Release|Win32
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6}.Release|x86.Build.0 = Release|Win32
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
|
@ -117,6 +137,8 @@ Global
|
||||||
{7BE99936-0D40-410D-944B-4513C2EFF8DC} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
{7BE99936-0D40-410D-944B-4513C2EFF8DC} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||||
{91BA9E79-8242-4F7D-B997-0DFEC95EA22B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
{91BA9E79-8242-4F7D-B997-0DFEC95EA22B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||||
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
{738CB4FC-CD9E-4B81-A04B-DEADBFA71C63} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||||
|
{96900163-D5A3-42AA-A387-D7D5DAD0A11E} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||||
|
{93C2F450-6682-41F8-9E19-35363BA15EF6} = {E0863FCC-8E72-490D-BE1B-458F12CA8298}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {07DCCACC-D10D-47C9-85AE-FB9C54DB7D62}
|
SolutionGuid = {07DCCACC-D10D-47C9-85AE-FB9C54DB7D62}
|
||||||
|
|
78
lib/libctr/include/nn/ctr/CodeBinaryHeader.h
Normal file
78
lib/libctr/include/nn/ctr/CodeBinaryHeader.h
Normal file
|
@ -0,0 +1,78 @@
|
||||||
|
/*
|
||||||
|
CodeBinaryHeader.h
|
||||||
|
(c) 2018 Jakcron
|
||||||
|
|
||||||
|
This is a header to prepend to raw EXEFS .code binaries that provide enough data to be equivalent to an ELF.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <fnd/ISerialisable.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <nn/ctr/code.h>
|
||||||
|
#include <nn/ctr/CodeSegment.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
class CodeBinaryHeader : public fnd::ISerialisable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// constructors
|
||||||
|
CodeBinaryHeader();
|
||||||
|
CodeBinaryHeader(const CodeBinaryHeader& other);
|
||||||
|
|
||||||
|
void operator=(const CodeBinaryHeader& other);
|
||||||
|
bool operator==(const CodeBinaryHeader& other) const;
|
||||||
|
bool operator!=(const CodeBinaryHeader& other) const;
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
void toBytes();
|
||||||
|
void fromBytes(const byte_t* data, size_t len);
|
||||||
|
const fnd::Vec<byte_t>& getBytes() const;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// mutators
|
||||||
|
void setCodeBinOffset(uint32_t offset);
|
||||||
|
uint32_t getCodeBinOffset() const;
|
||||||
|
|
||||||
|
void setCodeBinSize(uint32_t size);
|
||||||
|
uint32_t getCodeBinSize() const;
|
||||||
|
|
||||||
|
void setStackSize(uint32_t size);
|
||||||
|
uint32_t getStackSize() const;
|
||||||
|
|
||||||
|
void setBssSize(uint32_t size);
|
||||||
|
uint32_t getBssSize() const;
|
||||||
|
|
||||||
|
void setTextSegment(const ctr::CodeSegment& segment);
|
||||||
|
const ctr::CodeSegment& getTextSegment() const;
|
||||||
|
|
||||||
|
void setRODataSegment(const ctr::CodeSegment& segment);
|
||||||
|
const ctr::CodeSegment& getRODataSegment() const;
|
||||||
|
|
||||||
|
void setDataSegment(const ctr::CodeSegment& segment);
|
||||||
|
const ctr::CodeSegment& getDataSegment() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "CODE_BINARY_HEADER";
|
||||||
|
|
||||||
|
|
||||||
|
// serialised data
|
||||||
|
fnd::Vec<byte_t> mRawBinary;
|
||||||
|
|
||||||
|
// members
|
||||||
|
uint32_t mCodeBinOffset;
|
||||||
|
uint32_t mCodeBinSize;
|
||||||
|
uint32_t mStackSize;
|
||||||
|
uint32_t mBssSize;
|
||||||
|
CodeSegment mSegmentList[code::kCodeSegmentNum];
|
||||||
|
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
37
lib/libctr/include/nn/ctr/CodeSegment.h
Normal file
37
lib/libctr/include/nn/ctr/CodeSegment.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
CodeSegment.h
|
||||||
|
(c) 2018 Jakcron
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
class CodeSegment
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CodeSegment();
|
||||||
|
CodeSegment(const CodeSegment& other);
|
||||||
|
CodeSegment(uint32_t address, uint32_t size, uint32_t page_num);
|
||||||
|
|
||||||
|
void operator=(const CodeSegment& other);
|
||||||
|
bool operator==(const CodeSegment& other) const;
|
||||||
|
bool operator!=(const CodeSegment& other) const;
|
||||||
|
|
||||||
|
void setAddress(uint32_t address);
|
||||||
|
uint32_t getAddress() const;
|
||||||
|
|
||||||
|
void setSize(uint32_t size);
|
||||||
|
uint32_t getSize() const;
|
||||||
|
|
||||||
|
void setPageNum(uint32_t num);
|
||||||
|
uint32_t getPageNum() const;
|
||||||
|
private:
|
||||||
|
uint32_t mAddress;
|
||||||
|
uint32_t mSize;
|
||||||
|
uint32_t mPageNum;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
210
lib/libctr/include/nn/ctr/NcchHeader.h
Normal file
210
lib/libctr/include/nn/ctr/NcchHeader.h
Normal file
|
@ -0,0 +1,210 @@
|
||||||
|
/*
|
||||||
|
NcchHeader.h
|
||||||
|
(c) 2018 Jakcron
|
||||||
|
|
||||||
|
This is a 0x100 byte header used to map/hash sections in CXI/CFA files, is preceeded by a RSA-2048 signature over
|
||||||
|
these 0x100 bytes in such files. It is also used in CCI files in the CardInfo structure
|
||||||
|
|
||||||
|
#Implementation Details
|
||||||
|
- sizes/offsets are in blocks (usually 512 bytes)
|
||||||
|
- all offsets in the raw structure are from the start of the file, not the start of the header.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/sha.h>
|
||||||
|
#include <fnd/Vec.h>
|
||||||
|
#include <fnd/List.h>
|
||||||
|
#include <fnd/ISerialisable.h>
|
||||||
|
#include <nn/ctr/ProgramId.h>
|
||||||
|
#include <nn/ctr/ncch.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
class NcchHeader : public fnd::ISerialisable
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
class Layout
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
Layout() :
|
||||||
|
mOffset(0),
|
||||||
|
mSize(0),
|
||||||
|
mHashedSize(0),
|
||||||
|
mHash()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void operator=(const Layout& other)
|
||||||
|
{
|
||||||
|
mOffset = other.mOffset;
|
||||||
|
mSize = other.mSize;
|
||||||
|
mHashedSize = other.mHashedSize;
|
||||||
|
mHash = other.mHash;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator==(const Layout& other) const
|
||||||
|
{
|
||||||
|
return (mOffset == other.mOffset) \
|
||||||
|
&& (mSize == other.mSize) \
|
||||||
|
&& (mHashedSize == other.mHashedSize) \
|
||||||
|
&& (mHash == other.mHash);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool operator!=(const Layout& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void setOffset(size_t offset)
|
||||||
|
{
|
||||||
|
mOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getOffset() const
|
||||||
|
{
|
||||||
|
return mOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setSize(size_t size)
|
||||||
|
{
|
||||||
|
mSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHashedSize(size_t hashed_size)
|
||||||
|
{
|
||||||
|
mHashedSize = hashed_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t getHashedSize() const
|
||||||
|
{
|
||||||
|
return mHashedSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void setHash(const fnd::sha::sSha256Hash& hash)
|
||||||
|
{
|
||||||
|
mHash = hash;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::sha::sSha256Hash& getHash() const
|
||||||
|
{
|
||||||
|
return mHash;
|
||||||
|
}
|
||||||
|
private:
|
||||||
|
size_t mOffset;
|
||||||
|
size_t mSize;
|
||||||
|
size_t mHashedSize;
|
||||||
|
fnd::sha::sSha256Hash mHash;
|
||||||
|
};
|
||||||
|
|
||||||
|
// constructors
|
||||||
|
NcchHeader();
|
||||||
|
NcchHeader(const NcchHeader& other);
|
||||||
|
|
||||||
|
void operator=(const NcchHeader& other);
|
||||||
|
bool operator==(const NcchHeader& other) const;
|
||||||
|
bool operator!=(const NcchHeader& other) const;
|
||||||
|
|
||||||
|
// export/import binary
|
||||||
|
void toBytes();
|
||||||
|
void fromBytes(const byte_t* data, size_t len);
|
||||||
|
const fnd::Vec<byte_t>& getBytes() const;
|
||||||
|
|
||||||
|
// variables
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
// data layout mutators
|
||||||
|
void setNcchBinarySize(size_t size);
|
||||||
|
size_t getNcchBinarySize() const;
|
||||||
|
|
||||||
|
void setExtendedHeaderLayout(const Layout layout);
|
||||||
|
const Layout& getExtendedHeaderLayout() const;
|
||||||
|
|
||||||
|
void setPlainRegionLayout(const Layout layout);
|
||||||
|
const Layout& getPlainRegionLayout() const;
|
||||||
|
|
||||||
|
void setLogoLayout(const Layout layout);
|
||||||
|
const Layout& getLogoLayout() const;
|
||||||
|
|
||||||
|
void setExefsLayout(const Layout layout);
|
||||||
|
const Layout& getExefsLayout() const;
|
||||||
|
|
||||||
|
void setRomfsLayout(const Layout layout);
|
||||||
|
const Layout& getRomfsLayout() const;
|
||||||
|
|
||||||
|
// property mutators
|
||||||
|
void setNcchType(ncch::NcchType type);
|
||||||
|
ncch::NcchType getNcchType() const;
|
||||||
|
|
||||||
|
void setNewCryptoFlag(ncch::NewCryptoFlag flag);
|
||||||
|
ncch::NewCryptoFlag getNewCryptoFlag() const;
|
||||||
|
|
||||||
|
void setPlatform(ncch::Platform platform);
|
||||||
|
ncch::Platform getPlatform() const;
|
||||||
|
|
||||||
|
void setFormType(ncch::FormType type);
|
||||||
|
ncch::FormType getFormType() const;
|
||||||
|
|
||||||
|
void setContentType(ncch::ContentType type);
|
||||||
|
ncch::ContentType getContentType() const;
|
||||||
|
|
||||||
|
void setBlockSize(ncch::BlockSizeFlag flag);
|
||||||
|
ncch::BlockSizeFlag getBlockSize() const;
|
||||||
|
|
||||||
|
void setOtherFlagList(const fnd::List<ncch::OtherFlag>& list);
|
||||||
|
const fnd::List<ncch::OtherFlag>& getOtherFlagList() const;
|
||||||
|
|
||||||
|
void setCompanyCode(const std::string& company_code);
|
||||||
|
const std::string& getCompanyCode() const;
|
||||||
|
|
||||||
|
void setTitleId(const ctr::ProgramId& id);
|
||||||
|
const ctr::ProgramId& getTitleId() const;
|
||||||
|
|
||||||
|
void setProgramId(const ctr::ProgramId& id);
|
||||||
|
const ctr::ProgramId& getProgramId() const;
|
||||||
|
|
||||||
|
void setProductCode(const std::string& product_code);
|
||||||
|
const std::string& getProductCode() const;
|
||||||
|
|
||||||
|
void setSeedChecksum(uint32_t checksum);
|
||||||
|
uint32_t getSeedChecksum() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const std::string kModuleName = "NCCH_HEADER";
|
||||||
|
|
||||||
|
// serialised data
|
||||||
|
fnd::Vec<byte_t> mRawBinary;
|
||||||
|
|
||||||
|
// members
|
||||||
|
size_t mNcchBinarySize;
|
||||||
|
Layout mExHeaderLayout;
|
||||||
|
Layout mPlainRegionLayout;
|
||||||
|
Layout mLogoLayout;
|
||||||
|
Layout mExefsLayout;
|
||||||
|
Layout mRomfsLayout;
|
||||||
|
|
||||||
|
std::string mCompanyCode;
|
||||||
|
std::string mProductCode;
|
||||||
|
|
||||||
|
uint32_t mSeedChecksum;
|
||||||
|
|
||||||
|
ncch::NcchType mNcchType;
|
||||||
|
ProgramId mTitleId;
|
||||||
|
ProgramId mProgramId;
|
||||||
|
|
||||||
|
ncch::NewCryptoFlag mNewCryptoFlag;
|
||||||
|
ncch::Platform mPlatform;
|
||||||
|
ncch::FormType mFormType;
|
||||||
|
ncch::ContentType mContentType;
|
||||||
|
ncch::BlockSizeFlag mBlockSize;
|
||||||
|
fnd::List<ncch::OtherFlag> mOtherFlagList;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
48
lib/libctr/include/nn/ctr/ProgramId.h
Normal file
48
lib/libctr/include/nn/ctr/ProgramId.h
Normal file
|
@ -0,0 +1,48 @@
|
||||||
|
/*
|
||||||
|
ProgramId.h
|
||||||
|
(c) 2018 Jakcron
|
||||||
|
|
||||||
|
This is a wrapper class for the 64bit unique id assigned to programs
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <nn/ctr/prog_id.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
class ProgramId
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ProgramId();
|
||||||
|
ProgramId(const ProgramId &other);
|
||||||
|
ProgramId(uint64_t prog_id);
|
||||||
|
ProgramId(uint16_t device_group, uint16_t category, uint32_t unique_id, uint8_t variation);
|
||||||
|
|
||||||
|
void operator=(const ProgramId& other);
|
||||||
|
bool operator==(const ProgramId& other) const;
|
||||||
|
bool operator!=(const ProgramId& other) const;
|
||||||
|
|
||||||
|
// mutators
|
||||||
|
void setInnerValue(uint64_t id);
|
||||||
|
uint64_t getInnerValue() const;
|
||||||
|
|
||||||
|
void setDeviceGroup(uint16_t device_group);
|
||||||
|
uint16_t getDeviceGroup() const;
|
||||||
|
|
||||||
|
void setCategory(uint16_t category);
|
||||||
|
uint16_t getCategory() const;
|
||||||
|
|
||||||
|
void setUniqueId(uint32_t uid);
|
||||||
|
uint32_t getUniqueId() const;
|
||||||
|
|
||||||
|
void setVariation(uint8_t variation);
|
||||||
|
uint8_t getVariation() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
|
||||||
|
uint64_t mProgramId;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
44
lib/libctr/include/nn/ctr/code.h
Normal file
44
lib/libctr/include/nn/ctr/code.h
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/rsa.h>
|
||||||
|
#include <nn/ctr/macro.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
namespace code
|
||||||
|
{
|
||||||
|
static const uint32_t kStructMagic = _MAKE_STRUCT_MAGIC_U32("CODE");
|
||||||
|
static const uint32_t kCtrFormatIdent = _MAKE_STRUCT_MAGIC_U32("CTR0");
|
||||||
|
static const size_t kCodeSegmentNum = 3;
|
||||||
|
|
||||||
|
enum CodeSegmentIndex
|
||||||
|
{
|
||||||
|
TEXT_SEGMENT,
|
||||||
|
RODATA_SEGMENT,
|
||||||
|
DATA_SEGMENT,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
#pragma pack(push,1)
|
||||||
|
struct sCodeBinaryHeader
|
||||||
|
{
|
||||||
|
le_uint32_t st_magic;
|
||||||
|
le_uint32_t format_ident;
|
||||||
|
le_uint32_t flags;
|
||||||
|
byte_t reserved_00[4];
|
||||||
|
le_uint32_t code_bin_offset;
|
||||||
|
le_uint32_t code_bin_size;
|
||||||
|
le_uint32_t stack_size;
|
||||||
|
le_uint32_t bss_size;
|
||||||
|
struct sCodeSegment
|
||||||
|
{
|
||||||
|
le_uint32_t v_addr;
|
||||||
|
le_uint32_t size;
|
||||||
|
le_uint32_t page_num;
|
||||||
|
le_uint32_t padding;
|
||||||
|
} segments[code::kCodeSegmentNum];
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
||||||
|
}
|
5
lib/libctr/include/nn/ctr/macro.h
Normal file
5
lib/libctr/include/nn/ctr/macro.h
Normal file
|
@ -0,0 +1,5 @@
|
||||||
|
#pragma once
|
||||||
|
#include <cstdint>
|
||||||
|
|
||||||
|
#define _MAKE_STRUCT_MAGIC_U32(x) ((uint32_t)(x[3]) << 24 | (uint32_t)(x[2]) << 16 | (uint32_t)(x[1]) << 8 | (uint32_t)(x[0]))
|
||||||
|
#define _MAKE_STRUCT_MAGIC_U64(x) ((uint64_t)(x[7]) << 56 | (uint64_t)(x[6]) << 48 | (uint64_t)(x[5]) << 40 | (uint64_t)(x[4]) << 32 | (uint64_t)(x[3]) << 24 | (uint64_t)(x[2]) << 16 | (uint64_t)(x[1]) << 8 | (uint64_t)(x[0]))
|
127
lib/libctr/include/nn/ctr/ncch.h
Normal file
127
lib/libctr/include/nn/ctr/ncch.h
Normal file
|
@ -0,0 +1,127 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/sha.h>
|
||||||
|
#include <fnd/rsa.h>
|
||||||
|
#include <nn/ctr/macro.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
namespace ncch
|
||||||
|
{
|
||||||
|
static const uint32_t kNcchStructMagic = _MAKE_STRUCT_MAGIC_U32("NCCH");
|
||||||
|
static const size_t kCompanyCodeLen = 2;
|
||||||
|
static const size_t kProductCodeLen = 0x10;
|
||||||
|
static const byte_t kFormTypeBitWidth = 2;
|
||||||
|
static const byte_t kContentTypeBitWidth = 6;
|
||||||
|
|
||||||
|
enum NcchType
|
||||||
|
{
|
||||||
|
TYPE_CFA = 0,
|
||||||
|
TYPE_CXI = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
enum NewCryptoFlag
|
||||||
|
{
|
||||||
|
CRYPTO_DEFAULT = 0x00,
|
||||||
|
CRYPTO_25 = 0x01,
|
||||||
|
CRYPTO_18 = 0x0A,
|
||||||
|
CRYPTO_1B = 0x0B
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Platform
|
||||||
|
{
|
||||||
|
PLATFORM_UNDEFINED,
|
||||||
|
PLATFORM_CTR,
|
||||||
|
PLATFORM_SNAKE,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FormType
|
||||||
|
{
|
||||||
|
UNASSIGNED,
|
||||||
|
SIMPLE_CONTENT,
|
||||||
|
EXECUTABLE_WITHOUT_ROMFS,
|
||||||
|
EXECUTABLE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ContentType
|
||||||
|
{
|
||||||
|
APPLICATION,
|
||||||
|
SYSTEM_UPDATE,
|
||||||
|
MANUAL,
|
||||||
|
CHILD,
|
||||||
|
TRIAL,
|
||||||
|
EXTENDED_SYSTEM_UPDATE
|
||||||
|
};
|
||||||
|
|
||||||
|
enum BlockSizeFlag
|
||||||
|
{
|
||||||
|
BLOCK_SIZE_512
|
||||||
|
};
|
||||||
|
|
||||||
|
enum OtherFlag
|
||||||
|
{
|
||||||
|
FIXED_AES_KEY = 0,
|
||||||
|
NO_MOUNT_ROMFS = 1,
|
||||||
|
NO_AES = 2,
|
||||||
|
SEED_KEY = 5,
|
||||||
|
MANUAL_DISCLOSURE = 6,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum FlagIndex
|
||||||
|
{
|
||||||
|
CRYPTO_FLAG_INDEX = 3,
|
||||||
|
PLATFORM_INDEX = 4,
|
||||||
|
CONTENT_TYPE_INDEX = 5,
|
||||||
|
BLOCK_SIZE_INDEX = 6,
|
||||||
|
OTHER_FLAG_INDEX = 7
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma pack(push, 1)
|
||||||
|
struct sLayout
|
||||||
|
{
|
||||||
|
le_uint32_t block_offset;
|
||||||
|
le_uint32_t block_num;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sLayoutHashed : public sLayout
|
||||||
|
{
|
||||||
|
le_uint32_t block_num_hash_protected;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sNcchHeader
|
||||||
|
{
|
||||||
|
le_uint32_t st_magic;
|
||||||
|
le_uint32_t size;
|
||||||
|
le_uint64_t title_id;
|
||||||
|
char company_code[ncch::kCompanyCodeLen];
|
||||||
|
le_uint16_t ncch_type;
|
||||||
|
le_uint32_t seed_checksum;
|
||||||
|
le_uint64_t program_id;
|
||||||
|
byte_t reserved1[0x10];
|
||||||
|
fnd::sha::sSha256Hash logo_hash;
|
||||||
|
char product_code[ncch::kProductCodeLen];
|
||||||
|
fnd::sha::sSha256Hash exheader_hash;
|
||||||
|
le_uint32_t exheader_size;
|
||||||
|
byte_t reserved2[0x4];
|
||||||
|
byte_t flags[8];
|
||||||
|
sLayout plain_region;
|
||||||
|
sLayout logo;
|
||||||
|
sLayoutHashed exefs;
|
||||||
|
byte_t reserved3[4];
|
||||||
|
sLayoutHashed romfs;
|
||||||
|
byte_t reserved4[4];
|
||||||
|
fnd::sha::sSha256Hash exefs_hash;
|
||||||
|
fnd::sha::sSha256Hash romfs_hash;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct sNcchHeaderBlock
|
||||||
|
{
|
||||||
|
byte_t rsa_signature[fnd::rsa::kRsa2048Size];
|
||||||
|
sNcchHeader header;
|
||||||
|
};
|
||||||
|
#pragma pack(pop)
|
||||||
|
}
|
||||||
|
}
|
87
lib/libctr/include/nn/ctr/prog_id.h
Normal file
87
lib/libctr/include/nn/ctr/prog_id.h
Normal file
|
@ -0,0 +1,87 @@
|
||||||
|
#pragma once
|
||||||
|
#include <fnd/types.h>
|
||||||
|
|
||||||
|
namespace nn
|
||||||
|
{
|
||||||
|
namespace ctr
|
||||||
|
{
|
||||||
|
namespace prog_id
|
||||||
|
{
|
||||||
|
static const uint64_t kDeviceGroupMask = 0xffff000000000000;
|
||||||
|
static const uint64_t kDeviceGroupShift = 48;
|
||||||
|
static const uint64_t kCategoryMask = 0x0000ffff00000000;
|
||||||
|
static const uint64_t kCategoryShift = 32;
|
||||||
|
static const uint64_t kUniqueIdMask = 0x00000000ffffff00;
|
||||||
|
static const uint64_t kUniqueIdShift = 8;
|
||||||
|
static const uint64_t kVariationMask = 0x00000000000000ff;
|
||||||
|
static const uint64_t kVariationShift = 0;
|
||||||
|
|
||||||
|
enum DeviceGroup
|
||||||
|
{
|
||||||
|
DEVICE_TWL = 0x0003,
|
||||||
|
DEVICE_CTR = 0x0004,
|
||||||
|
DEVICE_CAFE = 0x0005,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CategoryFlags
|
||||||
|
{
|
||||||
|
CATEGORY_FLAG_NORMAL = 0,
|
||||||
|
CATEGORY_FLAG_DLP_CHILD = _BIT(0),
|
||||||
|
CATEGORY_FLAG_DEMO = _BIT(1),
|
||||||
|
CATEGORY_FLAG_CONTENTS = _BIT(0) | _BIT(1),
|
||||||
|
CATEGORY_FLAG_ADD_ON_CONTENTS = _BIT(2),
|
||||||
|
CATEGORY_FLAG_PATCH = _BIT(1) | _BIT(2),
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE = _BIT(3),
|
||||||
|
CATEGORY_FLAG_SYSTEM = _BIT(4),
|
||||||
|
CATEGORY_FLAG_REQUIRE_BATCH_UPDATE = _BIT(5),
|
||||||
|
CATEGORY_FLAG_NOT_REQUIRE_USER_APPROVAL = _BIT(6),
|
||||||
|
CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT = _BIT(7),
|
||||||
|
CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID = _BIT(8),
|
||||||
|
CATEGORY_FLAG_TWL_LEGACY = _BIT(15),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum CategoryType
|
||||||
|
{
|
||||||
|
CATEGORY_APPLICATION = (CATEGORY_FLAG_NORMAL),
|
||||||
|
CATEGORY_DLP_CHILD = (CATEGORY_FLAG_DLP_CHILD),
|
||||||
|
CATEGORY_DEMO = (CATEGORY_FLAG_DEMO),
|
||||||
|
CATEGORY_CONTENTS = (CATEGORY_FLAG_CONTENTS),
|
||||||
|
CATEGORY_PATCH = (CATEGORY_FLAG_PATCH |
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE),
|
||||||
|
CATEGORY_ADD_ON_CONTENTS = (CATEGORY_FLAG_ADD_ON_CONTENTS |
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE |
|
||||||
|
CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT),
|
||||||
|
CATEGORY_FIRMWARE = (CATEGORY_FLAG_SYSTEM |
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE |
|
||||||
|
CATEGORY_FLAG_REQUIRE_BATCH_UPDATE |
|
||||||
|
CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID),
|
||||||
|
CATEGORY_MODULE = (CATEGORY_FLAG_SYSTEM |
|
||||||
|
CATEGORY_FLAG_REQUIRE_BATCH_UPDATE |
|
||||||
|
CATEGORY_FLAG_CAN_SKIP_CONVERT_JUMP_ID),
|
||||||
|
CATEGORY_APPLET = (CATEGORY_FLAG_SYSTEM |
|
||||||
|
CATEGORY_FLAG_REQUIRE_BATCH_UPDATE),
|
||||||
|
CATEGORY_SYSTEM_APPLICATION = (CATEGORY_FLAG_SYSTEM),
|
||||||
|
CATEGORY_SYSTEM_CONTENT = (CATEGORY_FLAG_SYSTEM |
|
||||||
|
CATEGORY_FLAG_CONTENTS |
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE),
|
||||||
|
CATEGORY_SHARED_CONTENT = (CATEGORY_FLAG_SYSTEM |
|
||||||
|
CATEGORY_FLAG_CONTENTS |
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE |
|
||||||
|
CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT),
|
||||||
|
CATEGORY_AUTO_UPDATE_CONTENT = (CATEGORY_FLAG_SYSTEM |
|
||||||
|
CATEGORY_FLAG_CONTENTS |
|
||||||
|
CATEGORY_FLAG_NOT_EXECUTABLE |
|
||||||
|
CATEGORY_FLAG_NOT_REQUIRE_RIGHT_FOR_MOUNT |
|
||||||
|
CATEGORY_FLAG_NOT_REQUIRE_USER_APPROVAL),
|
||||||
|
};
|
||||||
|
|
||||||
|
enum DeviceMask
|
||||||
|
{
|
||||||
|
ID_MASK = _BIT(28) - 1,
|
||||||
|
ID_MASK_CTR = 0, // 3DS
|
||||||
|
ID_MASK_CAFE = _BIT(28), // WiiU
|
||||||
|
ID_MASK_SNAKE = _BIT(29) // n3DS
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
150
lib/libctr/libctr.vcxproj
Normal file
150
lib/libctr/libctr.vcxproj
Normal file
|
@ -0,0 +1,150 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{96900163-D5A3-42AA-A387-D7D5DAD0A11E}</ProjectGuid>
|
||||||
|
<RootNamespace>libctr</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\libfnd\include;..\libctr\include;..\libes\include;..\libpki\include;</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\libfnd\include;..\libctr\include;..\libes\include;..\libpki\include;</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\libfnd\include;..\libctr\include;..\libes\include;..\libpki\include;</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\libfnd\include;..\libctr\include;..\libes\include;..\libpki\include;</AdditionalIncludeDirectories>
|
||||||
|
<PreprocessorDefinitions>_MBCS;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="source\CodeBinaryHeader.cpp" />
|
||||||
|
<ClCompile Include="source\CodeSegment.cpp" />
|
||||||
|
<ClCompile Include="source\NcchHeader.cpp" />
|
||||||
|
<ClCompile Include="source\ProgramId.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="makefile" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Text Include="notes.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="include\nn\ctr\code.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\CodeBinaryHeader.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\CodeSegment.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\macro.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\ncch.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\NcchHeader.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\ProgramId.h" />
|
||||||
|
<ClInclude Include="include\nn\ctr\prog_id.h" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
63
lib/libctr/libctr.vcxproj.filters
Normal file
63
lib/libctr/libctr.vcxproj.filters
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="source\CodeBinaryHeader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\CodeSegment.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\NcchHeader.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
<ClCompile Include="source\ProgramId.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="makefile" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<Text Include="notes.txt" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClInclude Include="include\nn\ctr\CodeBinaryHeader.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\CodeSegment.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\NcchHeader.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\ProgramId.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\code.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\macro.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\prog_id.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
<ClInclude Include="include\nn\ctr\ncch.h">
|
||||||
|
<Filter>Header Files</Filter>
|
||||||
|
</ClInclude>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
4
lib/libctr/libctr.vcxproj.user
Normal file
4
lib/libctr/libctr.vcxproj.user
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup />
|
||||||
|
</Project>
|
47
lib/libctr/makefile
Normal file
47
lib/libctr/makefile
Normal file
|
@ -0,0 +1,47 @@
|
||||||
|
# Sources
|
||||||
|
SRC_DIR = source
|
||||||
|
OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c)))
|
||||||
|
|
||||||
|
# External dependencies
|
||||||
|
DEPENDS = fnd crypto
|
||||||
|
LIB_DIR = ..
|
||||||
|
INCS = -I"include" $(foreach dep,$(DEPENDS), -I"$(LIB_DIR)/lib$(dep)/include")
|
||||||
|
|
||||||
|
|
||||||
|
# Compiler Settings
|
||||||
|
CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-but-set-variable -Wno-unused-value
|
||||||
|
CFLAGS = -std=c11 $(INCS) -Wall -Wno-unused-but-set-variable -Wno-unused-value
|
||||||
|
ARFLAGS = cr -o
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
# Windows Only Flags/Libs
|
||||||
|
CC = x86_64-w64-mingw32-gcc
|
||||||
|
CXX = x86_64-w64-mingw32-g++
|
||||||
|
CFLAGS +=
|
||||||
|
CXXFLAGS +=
|
||||||
|
else
|
||||||
|
UNAME = $(shell uname -s)
|
||||||
|
ifeq ($(UNAME), Darwin)
|
||||||
|
# MacOS Only Flags/Libs
|
||||||
|
CFLAGS +=
|
||||||
|
CXXFLAGS +=
|
||||||
|
ARFLAGS = rc
|
||||||
|
else
|
||||||
|
# *nix Only Flags/Libs
|
||||||
|
CFLAGS +=
|
||||||
|
CXXFLAGS +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
endif
|
||||||
|
|
||||||
|
# Output
|
||||||
|
OUTPUT = $(shell basename $(CURDIR)).a
|
||||||
|
|
||||||
|
main: build
|
||||||
|
|
||||||
|
rebuild: clean build
|
||||||
|
|
||||||
|
build: $(OBJS)
|
||||||
|
ar $(ARFLAGS) $(OUTPUT) $(OBJS)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OUTPUT) $(OBJS)
|
28
lib/libctr/notes.txt
Normal file
28
lib/libctr/notes.txt
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
Proposed classes
|
||||||
|
NcchHeader
|
||||||
|
NcsdHeader
|
||||||
|
CiaHeader
|
||||||
|
CiaFooter
|
||||||
|
ExtendedHeader
|
||||||
|
|
||||||
|
ncch:
|
||||||
|
NcchHeader
|
||||||
|
ExtendedHeader
|
||||||
|
SystemControlInfo
|
||||||
|
Arm11SystemCaps
|
||||||
|
Arm11KernelCaps
|
||||||
|
Arm9Caps
|
||||||
|
ExefsHeader
|
||||||
|
IvfcHeader
|
||||||
|
RomfsHeader
|
||||||
|
RomfsNodes**
|
||||||
|
|
||||||
|
ncsd:
|
||||||
|
NcsdHeader
|
||||||
|
CardInfoHeader
|
||||||
|
|
||||||
|
cia:
|
||||||
|
CiaHeader
|
||||||
|
CiaFooter
|
||||||
|
es::Ticket?
|
||||||
|
es::Tmd?
|
201
lib/libctr/source/CodeBinaryHeader.cpp
Normal file
201
lib/libctr/source/CodeBinaryHeader.cpp
Normal file
|
@ -0,0 +1,201 @@
|
||||||
|
#include <nn/ctr/CodeBinaryHeader.h>
|
||||||
|
#include <cstring>
|
||||||
|
|
||||||
|
nn::ctr::CodeBinaryHeader::CodeBinaryHeader() :
|
||||||
|
mRawBinary(),
|
||||||
|
mCodeBinSize(0),
|
||||||
|
mStackSize(0),
|
||||||
|
mBssSize(0),
|
||||||
|
mSegmentList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::CodeBinaryHeader::CodeBinaryHeader(const CodeBinaryHeader& other) :
|
||||||
|
CodeBinaryHeader()
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::operator=(const CodeBinaryHeader& other)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
mCodeBinOffset = other.mCodeBinOffset;
|
||||||
|
mCodeBinSize = other.mCodeBinSize;
|
||||||
|
mStackSize = other.mStackSize;
|
||||||
|
mBssSize = other.mBssSize;
|
||||||
|
mSegmentList[code::TEXT_SEGMENT] = other.mSegmentList[code::TEXT_SEGMENT];
|
||||||
|
mSegmentList[code::RODATA_SEGMENT] = other.mSegmentList[code::RODATA_SEGMENT];
|
||||||
|
mSegmentList[code::DATA_SEGMENT] = other.mSegmentList[code::DATA_SEGMENT];
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::CodeBinaryHeader::operator==(const CodeBinaryHeader& other) const
|
||||||
|
{
|
||||||
|
return (mCodeBinOffset == other.mCodeBinOffset) \
|
||||||
|
&& (mCodeBinSize == other.mCodeBinSize) \
|
||||||
|
&& (mStackSize == other.mStackSize) \
|
||||||
|
&& (mBssSize == other.mBssSize) \
|
||||||
|
&& (mSegmentList[code::TEXT_SEGMENT] == other.mSegmentList[code::TEXT_SEGMENT]) \
|
||||||
|
&& (mSegmentList[code::RODATA_SEGMENT] == other.mSegmentList[code::RODATA_SEGMENT]) \
|
||||||
|
&& (mSegmentList[code::DATA_SEGMENT] == other.mSegmentList[code::DATA_SEGMENT]);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::CodeBinaryHeader::operator!=(const CodeBinaryHeader& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::toBytes()
|
||||||
|
{
|
||||||
|
// allocate memory for header
|
||||||
|
mRawBinary.clear();
|
||||||
|
mRawBinary.alloc(sizeof(sCodeBinaryHeader));
|
||||||
|
|
||||||
|
// get ptr to header struct
|
||||||
|
sCodeBinaryHeader* hdr = (sCodeBinaryHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// write variables
|
||||||
|
hdr->st_magic = code::kStructMagic;
|
||||||
|
hdr->code_bin_size = le_word(mCodeBinSize);
|
||||||
|
hdr->stack_size = le_word(mStackSize);
|
||||||
|
hdr->bss_size = le_word(mBssSize);
|
||||||
|
for (size_t i = 0; i < code::kCodeSegmentNum; i++)
|
||||||
|
{
|
||||||
|
hdr->segments[i].v_addr = le_word(mSegmentList[i].getAddress());
|
||||||
|
hdr->segments[i].size = le_word(mSegmentList[i].getSize());
|
||||||
|
hdr->segments[i].page_num = le_word(mSegmentList[i].getPageNum());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::fromBytes(const byte_t* data, size_t len)
|
||||||
|
{
|
||||||
|
// check size
|
||||||
|
if (len < sizeof(sCodeBinaryHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "CODE header corrupt (binary is too small)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear variables
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// save a copy of the header
|
||||||
|
sCodeBinaryHeader hdr;
|
||||||
|
memcpy((void*)&hdr, data, sizeof(sCodeBinaryHeader));
|
||||||
|
|
||||||
|
// check magic
|
||||||
|
if (hdr.st_magic.get() != code::kStructMagic)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "CODE header corrupt (unrecognised header signature)");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (hdr.format_ident.get() != code::kCtrFormatIdent)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "CODE header corrupt (unsupported format version)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// allocate memory for header
|
||||||
|
mRawBinary.alloc(sizeof(sCodeBinaryHeader));
|
||||||
|
memcpy(mRawBinary.data(), data, mRawBinary.size());
|
||||||
|
|
||||||
|
// save variables
|
||||||
|
mCodeBinOffset = hdr.code_bin_offset.get();
|
||||||
|
mCodeBinSize = hdr.code_bin_size.get();
|
||||||
|
mStackSize = hdr.stack_size.get();
|
||||||
|
mBssSize = hdr.bss_size.get();
|
||||||
|
for (size_t i = 0; i < code::kCodeSegmentNum; i++)
|
||||||
|
{
|
||||||
|
mSegmentList[i].setAddress(hdr.segments[i].v_addr.get());
|
||||||
|
mSegmentList[i].setSize(hdr.segments[i].size.get());
|
||||||
|
mSegmentList[i].setPageNum(hdr.segments[i].page_num.get());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::Vec<byte_t>& nn::ctr::CodeBinaryHeader::getBytes() const
|
||||||
|
{
|
||||||
|
return mRawBinary;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::clear()
|
||||||
|
{
|
||||||
|
mRawBinary.clear();
|
||||||
|
mCodeBinOffset = 0;
|
||||||
|
mCodeBinSize = 0;
|
||||||
|
mStackSize = 0;
|
||||||
|
mBssSize = 0;
|
||||||
|
for (size_t i = 0; i < code::kCodeSegmentNum; i++)
|
||||||
|
{
|
||||||
|
mSegmentList[i].setAddress(0);
|
||||||
|
mSegmentList[i].setSize(0);
|
||||||
|
mSegmentList[i].setPageNum(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setCodeBinOffset(uint32_t offset)
|
||||||
|
{
|
||||||
|
mCodeBinOffset = offset;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeBinaryHeader::getCodeBinOffset() const
|
||||||
|
{
|
||||||
|
return mCodeBinOffset;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setCodeBinSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mCodeBinSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeBinaryHeader::getCodeBinSize() const
|
||||||
|
{
|
||||||
|
return mCodeBinSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setStackSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mStackSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeBinaryHeader::getStackSize() const
|
||||||
|
{
|
||||||
|
return mStackSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setBssSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mBssSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeBinaryHeader::getBssSize() const
|
||||||
|
{
|
||||||
|
return mBssSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setTextSegment(const nn::ctr::CodeSegment & segment)
|
||||||
|
{
|
||||||
|
mSegmentList[code::TEXT_SEGMENT] = segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::CodeSegment & nn::ctr::CodeBinaryHeader::getTextSegment() const
|
||||||
|
{
|
||||||
|
return mSegmentList[code::TEXT_SEGMENT];
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setRODataSegment(const nn::ctr::CodeSegment & segment)
|
||||||
|
{
|
||||||
|
mSegmentList[code::RODATA_SEGMENT] = segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::CodeSegment & nn::ctr::CodeBinaryHeader::getRODataSegment() const
|
||||||
|
{
|
||||||
|
return mSegmentList[code::RODATA_SEGMENT];
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeBinaryHeader::setDataSegment(const nn::ctr::CodeSegment & segment)
|
||||||
|
{
|
||||||
|
mSegmentList[code::DATA_SEGMENT] = segment;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::CodeSegment & nn::ctr::CodeBinaryHeader::getDataSegment() const
|
||||||
|
{
|
||||||
|
return mSegmentList[code::DATA_SEGMENT];
|
||||||
|
}
|
70
lib/libctr/source/CodeSegment.cpp
Normal file
70
lib/libctr/source/CodeSegment.cpp
Normal file
|
@ -0,0 +1,70 @@
|
||||||
|
#include <nn/ctr/CodeSegment.h>
|
||||||
|
|
||||||
|
nn::ctr::CodeSegment::CodeSegment() :
|
||||||
|
mAddress(0),
|
||||||
|
mSize(0),
|
||||||
|
mPageNum(0)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::CodeSegment::CodeSegment(const CodeSegment& other) :
|
||||||
|
mAddress(other.mAddress),
|
||||||
|
mSize(other.mSize),
|
||||||
|
mPageNum(other.mPageNum)
|
||||||
|
{}
|
||||||
|
|
||||||
|
|
||||||
|
nn::ctr::CodeSegment::CodeSegment(uint32_t address, uint32_t size, uint32_t page_num) :
|
||||||
|
mAddress(address),
|
||||||
|
mSize(size),
|
||||||
|
mPageNum(page_num)
|
||||||
|
{}
|
||||||
|
|
||||||
|
void nn::ctr::CodeSegment::operator=(const CodeSegment& other)
|
||||||
|
{
|
||||||
|
mAddress = other.mAddress;
|
||||||
|
mSize = other.mSize;
|
||||||
|
mPageNum = other.mPageNum;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::CodeSegment::operator==(const CodeSegment& other) const
|
||||||
|
{
|
||||||
|
return (mAddress == other.mAddress) \
|
||||||
|
&& (mSize == other.mSize) \
|
||||||
|
&& (mPageNum == other.mPageNum);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::CodeSegment::operator!=(const CodeSegment& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeSegment::setAddress(uint32_t address)
|
||||||
|
{
|
||||||
|
mAddress = address;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeSegment::getAddress() const
|
||||||
|
{
|
||||||
|
return mAddress;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeSegment::setSize(uint32_t size)
|
||||||
|
{
|
||||||
|
mSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeSegment::getSize() const
|
||||||
|
{
|
||||||
|
return mSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::CodeSegment::setPageNum(uint32_t num)
|
||||||
|
{
|
||||||
|
mPageNum = num;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::CodeSegment::getPageNum() const
|
||||||
|
{
|
||||||
|
return mPageNum;
|
||||||
|
}
|
473
lib/libctr/source/NcchHeader.cpp
Normal file
473
lib/libctr/source/NcchHeader.cpp
Normal file
|
@ -0,0 +1,473 @@
|
||||||
|
#include <nn/ctr/NcchHeader.h>
|
||||||
|
|
||||||
|
nn::ctr::NcchHeader::NcchHeader() :
|
||||||
|
mRawBinary(),
|
||||||
|
mNcchBinarySize(),
|
||||||
|
mExHeaderLayout(),
|
||||||
|
mPlainRegionLayout(),
|
||||||
|
mLogoLayout(),
|
||||||
|
mExefsLayout(),
|
||||||
|
mRomfsLayout(),
|
||||||
|
mCompanyCode(),
|
||||||
|
mProductCode(),
|
||||||
|
mSeedChecksum(),
|
||||||
|
mNcchType(),
|
||||||
|
mTitleId(),
|
||||||
|
mProgramId(),
|
||||||
|
mNewCryptoFlag(),
|
||||||
|
mPlatform(),
|
||||||
|
mFormType(),
|
||||||
|
mContentType(),
|
||||||
|
mBlockSize(),
|
||||||
|
mOtherFlagList()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::NcchHeader::NcchHeader(const NcchHeader& other) :
|
||||||
|
NcchHeader()
|
||||||
|
{
|
||||||
|
*this = other;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::operator=(const NcchHeader& other)
|
||||||
|
{
|
||||||
|
clear();
|
||||||
|
mRawBinary = other.mRawBinary;
|
||||||
|
mNcchBinarySize = other.mNcchBinarySize;
|
||||||
|
mExHeaderLayout = other.mExHeaderLayout;
|
||||||
|
mPlainRegionLayout = other.mPlainRegionLayout;
|
||||||
|
mLogoLayout = other.mLogoLayout;
|
||||||
|
mExefsLayout = other.mExefsLayout;
|
||||||
|
mRomfsLayout = other.mRomfsLayout;
|
||||||
|
mCompanyCode = other.mCompanyCode;
|
||||||
|
mProductCode = other.mProductCode;
|
||||||
|
mSeedChecksum = other.mSeedChecksum;
|
||||||
|
mNcchType = other.mNcchType;
|
||||||
|
mTitleId = other.mTitleId;
|
||||||
|
mProgramId = other.mProgramId;
|
||||||
|
mNewCryptoFlag = other.mNewCryptoFlag;
|
||||||
|
mPlatform = other.mPlatform;
|
||||||
|
mFormType = other.mFormType;
|
||||||
|
mContentType = other.mContentType;
|
||||||
|
mBlockSize = other.mBlockSize;
|
||||||
|
mOtherFlagList = other.mOtherFlagList;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::NcchHeader::operator==(const NcchHeader& other) const
|
||||||
|
{
|
||||||
|
return (mRawBinary == other.mRawBinary) \
|
||||||
|
&& (mNcchBinarySize == other.mNcchBinarySize) \
|
||||||
|
&& (mExHeaderLayout == other.mExHeaderLayout) \
|
||||||
|
&& (mPlainRegionLayout == other.mPlainRegionLayout) \
|
||||||
|
&& (mLogoLayout == other.mLogoLayout) \
|
||||||
|
&& (mExefsLayout == other.mExefsLayout) \
|
||||||
|
&& (mRomfsLayout == other.mRomfsLayout) \
|
||||||
|
&& (mCompanyCode == other.mCompanyCode) \
|
||||||
|
&& (mProductCode == other.mProductCode) \
|
||||||
|
&& (mSeedChecksum == other.mSeedChecksum) \
|
||||||
|
&& (mNcchType == other.mNcchType) \
|
||||||
|
&& (mTitleId == other.mTitleId) \
|
||||||
|
&& (mProgramId == other.mProgramId) \
|
||||||
|
&& (mNewCryptoFlag == other.mNewCryptoFlag) \
|
||||||
|
&& (mPlatform == other.mPlatform) \
|
||||||
|
&& (mFormType == other.mFormType) \
|
||||||
|
&& (mContentType == other.mContentType) \
|
||||||
|
&& (mBlockSize == other.mBlockSize) \
|
||||||
|
&& (mOtherFlagList == other.mOtherFlagList);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::NcchHeader::operator!=(const NcchHeader& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::toBytes()
|
||||||
|
{
|
||||||
|
mRawBinary.alloc(sizeof(sNcchHeader));
|
||||||
|
nn::ctr::sNcchHeader* hdr = (nn::ctr::sNcchHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// set header identifers
|
||||||
|
hdr->st_magic = ncch::kNcchStructMagic;
|
||||||
|
hdr->ncch_type = mNcchType;
|
||||||
|
|
||||||
|
// variable to store flag before commiting to header
|
||||||
|
byte_t otherflag = 0;
|
||||||
|
byte_t contentflag = 0;
|
||||||
|
for (size_t i = 0; i < mOtherFlagList.size(); i++)
|
||||||
|
{
|
||||||
|
_SET_BIT(otherflag, mOtherFlagList[i]);
|
||||||
|
}
|
||||||
|
contentflag |= (mContentType & _BITMASK(ncch::kContentTypeBitWidth)) << ncch::kFormTypeBitWidth;
|
||||||
|
contentflag |= (mFormType & _BITMASK(ncch::kFormTypeBitWidth));
|
||||||
|
|
||||||
|
// set flags
|
||||||
|
hdr->flags[ncch::CRYPTO_FLAG_INDEX] = mNewCryptoFlag;
|
||||||
|
hdr->flags[ncch::PLATFORM_INDEX] = mPlatform;
|
||||||
|
hdr->flags[ncch::CONTENT_TYPE_INDEX] = contentflag;
|
||||||
|
hdr->flags[ncch::BLOCK_SIZE_INDEX] = mBlockSize;
|
||||||
|
hdr->flags[ncch::OTHER_FLAG_INDEX] = otherflag;
|
||||||
|
|
||||||
|
// set strings
|
||||||
|
strncpy(hdr->product_code, mProductCode.c_str(), ncch::kProductCodeLen);
|
||||||
|
strncpy(hdr->company_code, mCompanyCode.c_str(), ncch::kCompanyCodeLen);
|
||||||
|
|
||||||
|
// misc
|
||||||
|
hdr->title_id = mTitleId.getInnerValue();
|
||||||
|
hdr->program_id = mProgramId.getInnerValue();
|
||||||
|
hdr->seed_checksum = mSeedChecksum;
|
||||||
|
|
||||||
|
// exheader
|
||||||
|
hdr->exheader_size = mExHeaderLayout.getSize();
|
||||||
|
hdr->exheader_hash = mExHeaderLayout.getHash();
|
||||||
|
|
||||||
|
// block size
|
||||||
|
size_t block_size = 0;
|
||||||
|
if (mBlockSize == ncch::BLOCK_SIZE_512)
|
||||||
|
block_size = 512;
|
||||||
|
else
|
||||||
|
throw fnd::Exception(kModuleName, "Illegal block size flag");
|
||||||
|
|
||||||
|
// plain region
|
||||||
|
if (mPlainRegionLayout.getOffset() % block_size || mPlainRegionLayout.getSize() % block_size)
|
||||||
|
throw fnd::Exception(kModuleName, "Plain region geometry not aligned to block size");
|
||||||
|
hdr->plain_region.block_offset = mPlainRegionLayout.getOffset() / block_size;
|
||||||
|
hdr->plain_region.block_num = mPlainRegionLayout.getSize() / block_size;
|
||||||
|
|
||||||
|
// logo
|
||||||
|
if (mLogoLayout.getOffset() % block_size || mLogoLayout.getSize() % block_size)
|
||||||
|
throw fnd::Exception(kModuleName, "Logo geometry not aligned to block size");
|
||||||
|
hdr->logo.block_offset = mLogoLayout.getOffset() / block_size;
|
||||||
|
hdr->logo.block_num = mLogoLayout.getSize() / block_size;
|
||||||
|
hdr->logo_hash = mLogoLayout.getHash();
|
||||||
|
|
||||||
|
// exefs
|
||||||
|
if (mExefsLayout.getOffset() % block_size || mExefsLayout.getSize() % block_size || mExefsLayout.getHashedSize() % block_size)
|
||||||
|
throw fnd::Exception(kModuleName, "ExeFs geometry not aligned to block size");
|
||||||
|
hdr->exefs.block_offset = mExefsLayout.getOffset() / block_size;
|
||||||
|
hdr->exefs.block_num = mExefsLayout.getSize() / block_size;
|
||||||
|
hdr->exefs.block_num_hash_protected = mExefsLayout.getHashedSize() / block_size;
|
||||||
|
hdr->exefs_hash = mExefsLayout.getHash();
|
||||||
|
|
||||||
|
// romfs
|
||||||
|
if (mRomfsLayout.getOffset() % block_size || mRomfsLayout.getSize() % block_size || mRomfsLayout.getHashedSize() % block_size)
|
||||||
|
throw fnd::Exception(kModuleName, "RomFs geometry not aligned to block size");
|
||||||
|
hdr->romfs.block_offset = mRomfsLayout.getOffset() / block_size;
|
||||||
|
hdr->romfs.block_num = mRomfsLayout.getSize() / block_size;
|
||||||
|
hdr->romfs.block_num_hash_protected = mRomfsLayout.getHashedSize() / block_size;
|
||||||
|
hdr->romfs_hash = mRomfsLayout.getHash();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::fromBytes(const byte_t* data, size_t len)
|
||||||
|
{
|
||||||
|
// check input data size
|
||||||
|
if (len < sizeof(sNcchHeader))
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "NCCH header size is too small");
|
||||||
|
}
|
||||||
|
|
||||||
|
// clear internal members
|
||||||
|
clear();
|
||||||
|
|
||||||
|
// allocate internal local binary copy
|
||||||
|
mRawBinary.alloc(sizeof(sNcchHeader));
|
||||||
|
memcpy(mRawBinary.data(), data, mRawBinary.size());
|
||||||
|
|
||||||
|
// get ptr
|
||||||
|
const nn::ctr::sNcchHeader* hdr = (const nn::ctr::sNcchHeader*)mRawBinary.data();
|
||||||
|
|
||||||
|
// check NCCH signature
|
||||||
|
if (hdr->st_magic.get() != ncch::kNcchStructMagic)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "NCCH header corrupt (unrecognised header signature)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// check NCCH type
|
||||||
|
if (hdr->ncch_type.get() != ncch::TYPE_CFA && hdr->ncch_type.get() != ncch::TYPE_CXI)
|
||||||
|
{
|
||||||
|
throw fnd::Exception(kModuleName, "NCCH header corrupt (unsupported NCCH type)");
|
||||||
|
}
|
||||||
|
|
||||||
|
// save flags
|
||||||
|
mNewCryptoFlag = (ncch::NewCryptoFlag)hdr->flags[ncch::CRYPTO_FLAG_INDEX];
|
||||||
|
mPlatform = (ncch::Platform)hdr->flags[ncch::PLATFORM_INDEX];
|
||||||
|
mBlockSize = (ncch::BlockSizeFlag)hdr->flags[ncch::BLOCK_SIZE_INDEX];
|
||||||
|
mContentType = (ncch::ContentType)((hdr->flags[ncch::CONTENT_TYPE_INDEX] >> ncch::kFormTypeBitWidth) & (byte_t)_BITMASK(ncch::kContentTypeBitWidth));
|
||||||
|
mFormType = (ncch::FormType)(hdr->flags[ncch::CONTENT_TYPE_INDEX] & (byte_t)_BITMASK(ncch::kFormTypeBitWidth));
|
||||||
|
for (size_t i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (_HAS_BIT(hdr->flags[ncch::OTHER_FLAG_INDEX], i))
|
||||||
|
mOtherFlagList.addElement((ncch::OtherFlag)i);
|
||||||
|
}
|
||||||
|
|
||||||
|
// save strings
|
||||||
|
if (hdr->company_code[0] != '\0')
|
||||||
|
mCompanyCode = std::string(hdr->company_code, _MIN(strlen(hdr->company_code), ncch::kCompanyCodeLen));
|
||||||
|
if (hdr->product_code[0] != '\0')
|
||||||
|
mCompanyCode = std::string(hdr->product_code, _MIN(strlen(hdr->product_code), ncch::kProductCodeLen));
|
||||||
|
|
||||||
|
// save misc
|
||||||
|
mTitleId = ProgramId(hdr->title_id.get());
|
||||||
|
mProgramId = ProgramId(hdr->program_id.get());
|
||||||
|
mSeedChecksum = hdr->seed_checksum.get();
|
||||||
|
|
||||||
|
|
||||||
|
// block size
|
||||||
|
size_t block_size = 0;
|
||||||
|
if (mBlockSize == ncch::BLOCK_SIZE_512)
|
||||||
|
block_size = 512;
|
||||||
|
else
|
||||||
|
throw fnd::Exception(kModuleName, "NCCH header corrupt (illegal block size flag)");
|
||||||
|
|
||||||
|
// save layouts
|
||||||
|
mNcchBinarySize = (size_t)hdr->size.get() * block_size;
|
||||||
|
|
||||||
|
// exheader
|
||||||
|
if (hdr->exheader_size.get() != 0)
|
||||||
|
{
|
||||||
|
mExHeaderLayout.setSize(hdr->exheader_size.get());
|
||||||
|
mExHeaderLayout.setHash(hdr->exheader_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// plain region
|
||||||
|
if (hdr->plain_region.block_num.get() != 0)
|
||||||
|
{
|
||||||
|
mPlainRegionLayout.setOffset((size_t)hdr->plain_region.block_offset.get() * block_size);
|
||||||
|
mPlainRegionLayout.setSize((size_t)hdr->plain_region.block_num.get() * block_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
// logo region
|
||||||
|
if (hdr->logo.block_num.get() != 0)
|
||||||
|
{
|
||||||
|
mLogoLayout.setOffset((size_t)hdr->logo.block_offset.get() * block_size);
|
||||||
|
mLogoLayout.setSize((size_t)hdr->logo.block_num.get() * block_size);
|
||||||
|
mLogoLayout.setHash(hdr->logo_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// exefs region
|
||||||
|
if (hdr->exefs.block_num.get() != 0)
|
||||||
|
{
|
||||||
|
mExefsLayout.setOffset((size_t)hdr->exefs.block_offset.get() * block_size);
|
||||||
|
mExefsLayout.setSize((size_t)hdr->exefs.block_num.get() * block_size);
|
||||||
|
mExefsLayout.setHashedSize((size_t)hdr->exefs.block_num_hash_protected.get() * block_size);
|
||||||
|
mExefsLayout.setHash(hdr->exefs_hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
// romfs region
|
||||||
|
if (hdr->romfs.block_num.get() != 0)
|
||||||
|
{
|
||||||
|
mRomfsLayout.setOffset((size_t)hdr->romfs.block_offset.get() * block_size);
|
||||||
|
mRomfsLayout.setSize((size_t)hdr->romfs.block_num.get() * block_size);
|
||||||
|
mRomfsLayout.setHashedSize((size_t)hdr->romfs.block_num_hash_protected.get() * block_size);
|
||||||
|
mRomfsLayout.setHash(hdr->romfs_hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::Vec<byte_t>& nn::ctr::NcchHeader::getBytes() const
|
||||||
|
{
|
||||||
|
return mRawBinary;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::clear()
|
||||||
|
{
|
||||||
|
mRawBinary.clear();
|
||||||
|
mNcchBinarySize = 0;
|
||||||
|
mExHeaderLayout = Layout();
|
||||||
|
mPlainRegionLayout = Layout();
|
||||||
|
mLogoLayout = Layout();
|
||||||
|
mExefsLayout = Layout();
|
||||||
|
mRomfsLayout = Layout();
|
||||||
|
mCompanyCode = std::string();
|
||||||
|
mProductCode = std::string();
|
||||||
|
mSeedChecksum = 0;
|
||||||
|
mNcchType = ncch::NcchType::TYPE_CFA;
|
||||||
|
mTitleId = ProgramId();
|
||||||
|
mProgramId = ProgramId();
|
||||||
|
mNewCryptoFlag = ncch::NewCryptoFlag::CRYPTO_DEFAULT;
|
||||||
|
mPlatform = ncch::Platform::PLATFORM_CTR;
|
||||||
|
mFormType = ncch::FormType::UNASSIGNED;
|
||||||
|
mContentType = ncch::ContentType::APPLICATION;
|
||||||
|
mBlockSize = ncch::BlockSizeFlag::BLOCK_SIZE_512;
|
||||||
|
mOtherFlagList.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setNcchBinarySize(size_t size)
|
||||||
|
{
|
||||||
|
mNcchBinarySize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t nn::ctr::NcchHeader::getNcchBinarySize() const
|
||||||
|
{
|
||||||
|
return mNcchBinarySize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setExtendedHeaderLayout(const Layout layout)
|
||||||
|
{
|
||||||
|
mExHeaderLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::NcchHeader::Layout& nn::ctr::NcchHeader::getExtendedHeaderLayout() const
|
||||||
|
{
|
||||||
|
return mExHeaderLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setPlainRegionLayout(const Layout layout)
|
||||||
|
{
|
||||||
|
mPlainRegionLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::NcchHeader::Layout& nn::ctr::NcchHeader::getPlainRegionLayout() const
|
||||||
|
{
|
||||||
|
return mPlainRegionLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setLogoLayout(const Layout layout)
|
||||||
|
{
|
||||||
|
mLogoLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::NcchHeader::Layout& nn::ctr::NcchHeader::getLogoLayout() const
|
||||||
|
{
|
||||||
|
return mLogoLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setExefsLayout(const Layout layout)
|
||||||
|
{
|
||||||
|
mExefsLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::NcchHeader::Layout& nn::ctr::NcchHeader::getExefsLayout() const
|
||||||
|
{
|
||||||
|
return mExefsLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setRomfsLayout(const Layout layout)
|
||||||
|
{
|
||||||
|
mRomfsLayout = layout;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::NcchHeader::Layout& nn::ctr::NcchHeader::getRomfsLayout() const
|
||||||
|
{
|
||||||
|
return mRomfsLayout;
|
||||||
|
}
|
||||||
|
|
||||||
|
// property mutators
|
||||||
|
void nn::ctr::NcchHeader::setNcchType(ncch::NcchType type)
|
||||||
|
{
|
||||||
|
mNcchType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::ncch::NcchType nn::ctr::NcchHeader::getNcchType() const
|
||||||
|
{
|
||||||
|
return mNcchType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setNewCryptoFlag(ncch::NewCryptoFlag flag)
|
||||||
|
{
|
||||||
|
mNewCryptoFlag = flag;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::ncch::NewCryptoFlag nn::ctr::NcchHeader::getNewCryptoFlag() const
|
||||||
|
{
|
||||||
|
return mNewCryptoFlag;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setPlatform(ncch::Platform platform)
|
||||||
|
{
|
||||||
|
mPlatform = platform;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::ncch::Platform nn::ctr::NcchHeader::getPlatform() const
|
||||||
|
{
|
||||||
|
return mPlatform;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setFormType(ncch::FormType type)
|
||||||
|
{
|
||||||
|
mFormType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::ncch::FormType nn::ctr::NcchHeader::getFormType() const
|
||||||
|
{
|
||||||
|
return mFormType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setContentType(ncch::ContentType type)
|
||||||
|
{
|
||||||
|
mContentType = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::ncch::ContentType nn::ctr::NcchHeader::getContentType() const
|
||||||
|
{
|
||||||
|
return mContentType;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setBlockSize(ncch::BlockSizeFlag size)
|
||||||
|
{
|
||||||
|
mBlockSize = size;
|
||||||
|
}
|
||||||
|
|
||||||
|
nn::ctr::ncch::BlockSizeFlag nn::ctr::NcchHeader::getBlockSize() const
|
||||||
|
{
|
||||||
|
return mBlockSize;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setOtherFlagList(const fnd::List<ncch::OtherFlag>& list)
|
||||||
|
{
|
||||||
|
mOtherFlagList = list;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fnd::List<nn::ctr::ncch::OtherFlag>& nn::ctr::NcchHeader::getOtherFlagList() const
|
||||||
|
{
|
||||||
|
return mOtherFlagList;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setCompanyCode(const std::string& company_code)
|
||||||
|
{
|
||||||
|
mCompanyCode = company_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& nn::ctr::NcchHeader::getCompanyCode() const
|
||||||
|
{
|
||||||
|
return mCompanyCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setTitleId(const ctr::ProgramId& id)
|
||||||
|
{
|
||||||
|
mTitleId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::ProgramId& nn::ctr::NcchHeader::getTitleId() const
|
||||||
|
{
|
||||||
|
return mTitleId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setProgramId(const ctr::ProgramId& id)
|
||||||
|
{
|
||||||
|
mProgramId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const nn::ctr::ProgramId& nn::ctr::NcchHeader::getProgramId() const
|
||||||
|
{
|
||||||
|
return mProgramId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setProductCode(const std::string& product_code)
|
||||||
|
{
|
||||||
|
mProductCode = product_code;
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string& nn::ctr::NcchHeader::getProductCode() const
|
||||||
|
{
|
||||||
|
return mProductCode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::NcchHeader::setSeedChecksum(uint32_t checksum)
|
||||||
|
{
|
||||||
|
mSeedChecksum = checksum;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::NcchHeader::getSeedChecksum() const
|
||||||
|
{
|
||||||
|
return mSeedChecksum;
|
||||||
|
}
|
91
lib/libctr/source/ProgramId.cpp
Normal file
91
lib/libctr/source/ProgramId.cpp
Normal file
|
@ -0,0 +1,91 @@
|
||||||
|
#include <nn/ctr/ProgramId.h>
|
||||||
|
|
||||||
|
nn::ctr::ProgramId::ProgramId() :
|
||||||
|
mProgramId(0)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nn::ctr::ProgramId::ProgramId(const ProgramId & other) :
|
||||||
|
mProgramId(other.getInnerValue())
|
||||||
|
{}
|
||||||
|
|
||||||
|
nn::ctr::ProgramId::ProgramId(uint64_t prog_id) :
|
||||||
|
mProgramId(prog_id)
|
||||||
|
{}
|
||||||
|
|
||||||
|
nn::ctr::ProgramId::ProgramId(uint16_t device_group, uint16_t category, uint32_t unique_id, uint8_t variation) :
|
||||||
|
mProgramId(0)
|
||||||
|
{
|
||||||
|
setDeviceGroup(device_group);
|
||||||
|
setCategory(category);
|
||||||
|
setUniqueId(unique_id);
|
||||||
|
setVariation(variation);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::ProgramId::operator=(const ProgramId& other)
|
||||||
|
{
|
||||||
|
mProgramId = other.mProgramId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::ProgramId::operator==(const ProgramId& other) const
|
||||||
|
{
|
||||||
|
return mProgramId == other.mProgramId;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool nn::ctr::ProgramId::operator!=(const ProgramId& other) const
|
||||||
|
{
|
||||||
|
return !(*this == other);
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::ProgramId::setInnerValue(uint64_t id)
|
||||||
|
{
|
||||||
|
mProgramId = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t nn::ctr::ProgramId::getInnerValue() const
|
||||||
|
{
|
||||||
|
return mProgramId;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::ProgramId::setDeviceGroup(uint16_t device_group)
|
||||||
|
{
|
||||||
|
mProgramId &= ~prog_id::kDeviceGroupMask;
|
||||||
|
mProgramId |= ((uint64_t)device_group) << prog_id::kDeviceGroupShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t nn::ctr::ProgramId::getDeviceGroup() const
|
||||||
|
{
|
||||||
|
return (mProgramId & prog_id::kDeviceGroupMask) >> prog_id::kDeviceGroupShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::ProgramId::setCategory(uint16_t category)
|
||||||
|
{
|
||||||
|
mProgramId &= ~prog_id::kCategoryMask;
|
||||||
|
mProgramId |= ((uint64_t)category) << prog_id::kCategoryShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t nn::ctr::ProgramId::getCategory() const
|
||||||
|
{
|
||||||
|
return (mProgramId & prog_id::kCategoryMask) >> prog_id::kCategoryShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::ProgramId::setUniqueId(uint32_t uid)
|
||||||
|
{
|
||||||
|
mProgramId &= ~prog_id::kUniqueIdMask;
|
||||||
|
mProgramId |= ((uint64_t)uid) << prog_id::kUniqueIdShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t nn::ctr::ProgramId::getUniqueId() const
|
||||||
|
{
|
||||||
|
return (mProgramId & prog_id::kUniqueIdMask) >> prog_id::kUniqueIdShift;
|
||||||
|
}
|
||||||
|
|
||||||
|
void nn::ctr::ProgramId::setVariation(uint8_t variation)
|
||||||
|
{
|
||||||
|
mProgramId &= ~prog_id::kVariationMask;
|
||||||
|
mProgramId |= (uint64_t)variation;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t nn::ctr::ProgramId::getVariation() const
|
||||||
|
{
|
||||||
|
return mProgramId & prog_id::kVariationMask;
|
||||||
|
}
|
4
makefile
4
makefile
|
@ -3,8 +3,8 @@ LIB_DIR = $(PROJECT_DIR)/lib
|
||||||
PROGRAM_DIR = $(PROJECT_DIR)/programs
|
PROGRAM_DIR = $(PROJECT_DIR)/programs
|
||||||
BIN_DIR = $(PROJECT_DIR)/bin
|
BIN_DIR = $(PROJECT_DIR)/bin
|
||||||
|
|
||||||
LIBS = libpolarssl liblz4 libfnd libes libpki libhac libhac-hb
|
LIBS = libpolarssl liblz4 libfnd libes libpki libctr libhac libhac-hb
|
||||||
PROGS = nstool
|
PROGS = nstool ctr-test
|
||||||
|
|
||||||
main: build
|
main: build
|
||||||
|
|
||||||
|
|
147
programs/ctr-test/ctr-test.vcxproj
Normal file
147
programs/ctr-test/ctr-test.vcxproj
Normal file
|
@ -0,0 +1,147 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup Label="ProjectConfigurations">
|
||||||
|
<ProjectConfiguration Include="Debug|Win32">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|Win32">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>Win32</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Debug|x64">
|
||||||
|
<Configuration>Debug</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
<ProjectConfiguration Include="Release|x64">
|
||||||
|
<Configuration>Release</Configuration>
|
||||||
|
<Platform>x64</Platform>
|
||||||
|
</ProjectConfiguration>
|
||||||
|
</ItemGroup>
|
||||||
|
<PropertyGroup Label="Globals">
|
||||||
|
<VCProjectVersion>15.0</VCProjectVersion>
|
||||||
|
<ProjectGuid>{93C2F450-6682-41F8-9E19-35363BA15EF6}</ProjectGuid>
|
||||||
|
<RootNamespace>ctrtest</RootNamespace>
|
||||||
|
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>true</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||||
|
<ConfigurationType>Application</ConfigurationType>
|
||||||
|
<UseDebugLibraries>false</UseDebugLibraries>
|
||||||
|
<PlatformToolset>v141</PlatformToolset>
|
||||||
|
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||||
|
<CharacterSet>MultiByte</CharacterSet>
|
||||||
|
</PropertyGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||||
|
<ImportGroup Label="ExtensionSettings">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="Shared">
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||||
|
</ImportGroup>
|
||||||
|
<PropertyGroup Label="UserMacros" />
|
||||||
|
<PropertyGroup />
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libctr\include;</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libctr\include;</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>Disabled</Optimization>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libctr\include;</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||||
|
<ClCompile>
|
||||||
|
<WarningLevel>Level3</WarningLevel>
|
||||||
|
<Optimization>MaxSpeed</Optimization>
|
||||||
|
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||||
|
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||||
|
<SDLCheck>true</SDLCheck>
|
||||||
|
<ConformanceMode>true</ConformanceMode>
|
||||||
|
<AdditionalIncludeDirectories>..\..\lib\libpki\include;..\..\lib\libes\include;..\..\lib\libfnd\include;..\..\lib\libctr\include;</AdditionalIncludeDirectories>
|
||||||
|
</ClCompile>
|
||||||
|
<Link>
|
||||||
|
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||||
|
<OptimizeReferences>true</OptimizeReferences>
|
||||||
|
</Link>
|
||||||
|
</ItemDefinitionGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\lib\libctr\libctr.vcxproj">
|
||||||
|
<Project>{96900163-d5a3-42aa-a387-d7d5dad0a11e}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\lib\libes\libes.vcxproj">
|
||||||
|
<Project>{7be99936-0d40-410d-944b-4513c2eff8dc}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\lib\libfnd\libfnd.vcxproj">
|
||||||
|
<Project>{4d27edb9-5110-44fe-8ce2-d46c5ad3c55b}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\lib\libpki\libpki.vcxproj">
|
||||||
|
<Project>{b9113734-6e84-44ff-8cf7-58199aa815c5}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
<ProjectReference Include="..\..\lib\libpolarssl\libpolarssl.vcxproj">
|
||||||
|
<Project>{394efc16-bd3a-4538-b33d-7ba1edb8dac1}</Project>
|
||||||
|
</ProjectReference>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="source\main.cpp" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="makefile" />
|
||||||
|
</ItemGroup>
|
||||||
|
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||||
|
<ImportGroup Label="ExtensionTargets">
|
||||||
|
</ImportGroup>
|
||||||
|
</Project>
|
25
programs/ctr-test/ctr-test.vcxproj.filters
Normal file
25
programs/ctr-test/ctr-test.vcxproj.filters
Normal file
|
@ -0,0 +1,25 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<ItemGroup>
|
||||||
|
<Filter Include="Source Files">
|
||||||
|
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||||
|
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Header Files">
|
||||||
|
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||||
|
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
|
||||||
|
</Filter>
|
||||||
|
<Filter Include="Resource Files">
|
||||||
|
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||||
|
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||||
|
</Filter>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<ClCompile Include="source\main.cpp">
|
||||||
|
<Filter>Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Include="makefile" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
4
programs/ctr-test/ctr-test.vcxproj.user
Normal file
4
programs/ctr-test/ctr-test.vcxproj.user
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||||
|
<PropertyGroup />
|
||||||
|
</Project>
|
39
programs/ctr-test/makefile
Normal file
39
programs/ctr-test/makefile
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
# Sources
|
||||||
|
SRC_DIR = source
|
||||||
|
OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c)))
|
||||||
|
|
||||||
|
# External dependencies
|
||||||
|
DEPENDS = polarssl lz4 fnd ctr
|
||||||
|
LIB_DIR = ../../lib
|
||||||
|
LIBS = $(foreach dep,$(DEPENDS), -L"$(LIB_DIR)/lib$(dep)" -l$(dep))
|
||||||
|
INCS = $(foreach dep,$(DEPENDS), -I"$(LIB_DIR)/lib$(dep)/include")
|
||||||
|
|
||||||
|
BIN_DIR = bin
|
||||||
|
OUTPUT = $(BIN_DIR)/$(shell basename $(CURDIR))
|
||||||
|
|
||||||
|
# Compiler Settings
|
||||||
|
CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-but-set-variable -Wno-unused-value
|
||||||
|
ifeq ($(OS),Windows_NT)
|
||||||
|
# Windows Only Flags/Libs
|
||||||
|
CC = x86_64-w64-mingw32-gcc
|
||||||
|
CXX = x86_64-w64-mingw32-g++
|
||||||
|
CFLAGS +=
|
||||||
|
CXXFLAGS +=
|
||||||
|
LIBS += -static
|
||||||
|
else
|
||||||
|
# *nix Only Flags/Libs
|
||||||
|
CFLAGS +=
|
||||||
|
CXXFLAGS +=
|
||||||
|
LIBS +=
|
||||||
|
endif
|
||||||
|
|
||||||
|
all: build
|
||||||
|
|
||||||
|
rebuild: clean build
|
||||||
|
|
||||||
|
build: $(OBJS)
|
||||||
|
mkdir -p $(BIN_DIR)
|
||||||
|
$(CXX) $(OBJS) $(LIBS) -o $(OUTPUT)
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -rf $(OBJS) $(OUTPUT) $(BIN_DIR)
|
307
programs/ctr-test/source/main.cpp
Normal file
307
programs/ctr-test/source/main.cpp
Normal file
|
@ -0,0 +1,307 @@
|
||||||
|
/*
|
||||||
|
(c) 2018 Jakcron
|
||||||
|
*/
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
|
#include <fnd/types.h>
|
||||||
|
#include <fnd/Vec.h>
|
||||||
|
#include <fnd/SimpleFile.h>
|
||||||
|
#include <nn/ctr/CodeBinaryHeader.h>
|
||||||
|
#include <nn/ctr/NcchHeader.h>
|
||||||
|
|
||||||
|
void dump_code_header(const nn::ctr::CodeBinaryHeader& codeHdr)
|
||||||
|
{
|
||||||
|
printf("Code Bin Size: 0x%08x\n", codeHdr.getCodeBinSize());
|
||||||
|
printf("Stack Size: 0x%08x\n", codeHdr.getStackSize());
|
||||||
|
printf("BSS Size: 0x%08x\n", codeHdr.getBssSize());
|
||||||
|
printf("Text Segment:\n");
|
||||||
|
printf(" Addr: 0x%08x\n", codeHdr.getTextSegment().getAddress());
|
||||||
|
printf(" Size: 0x%08x\n", codeHdr.getTextSegment().getSize());
|
||||||
|
printf(" PageNum: 0x%08x\n", codeHdr.getTextSegment().getPageNum());
|
||||||
|
printf("RO Data Segment:\n");
|
||||||
|
printf(" Addr: 0x%08x\n", codeHdr.getRODataSegment().getAddress());
|
||||||
|
printf(" Size: 0x%08x\n", codeHdr.getRODataSegment().getSize());
|
||||||
|
printf(" PageNum: 0x%08x\n", codeHdr.getRODataSegment().getPageNum());
|
||||||
|
printf("RW Data Segment:\n");
|
||||||
|
printf(" Addr: 0x%08x\n", codeHdr.getDataSegment().getAddress());
|
||||||
|
printf(" Size: 0x%08x\n", codeHdr.getDataSegment().getSize());
|
||||||
|
printf(" PageNum: 0x%08x\n", codeHdr.getDataSegment().getPageNum());
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* dump_ncch_header_ncch_type(uint16_t type)
|
||||||
|
{
|
||||||
|
const char* ret_string = nullptr;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (nn::ctr::ncch::TYPE_CFA):
|
||||||
|
ret_string = "CTR File Archive (CFA)";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::TYPE_CXI):
|
||||||
|
ret_string = "CTR Excutable Image (CXI)";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_string = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* dump_ncch_header_crypto_flag(uint8_t type)
|
||||||
|
{
|
||||||
|
const char* ret_string = nullptr;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (nn::ctr::ncch::CRYPTO_DEFAULT):
|
||||||
|
ret_string = "[CTR|SNAKE] 0x2C";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::CRYPTO_25):
|
||||||
|
ret_string = "[CTR|SNAKE] 0x2C/0x25";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::CRYPTO_18):
|
||||||
|
ret_string = "[SNAKE] 0x2C/0x18";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::CRYPTO_1B):
|
||||||
|
ret_string = "[SNAKE] 0x2C/0x1B";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_string = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* dump_ncch_header_platform_type(uint8_t type)
|
||||||
|
{
|
||||||
|
const char* ret_string = nullptr;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (nn::ctr::ncch::PLATFORM_CTR):
|
||||||
|
ret_string = "CTR";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::PLATFORM_SNAKE):
|
||||||
|
ret_string = "SNAKE";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_string = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* dump_ncch_header_form_type(uint8_t type)
|
||||||
|
{
|
||||||
|
const char* ret_string = nullptr;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (nn::ctr::ncch::SIMPLE_CONTENT):
|
||||||
|
ret_string = "Simple Content";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::EXECUTABLE_WITHOUT_ROMFS):
|
||||||
|
ret_string = "Executable Without RomFS";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::EXECUTABLE):
|
||||||
|
ret_string = "Executable";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_string = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* dump_ncch_header_content_type(uint8_t type)
|
||||||
|
{
|
||||||
|
const char* ret_string = nullptr;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case (nn::ctr::ncch::APPLICATION):
|
||||||
|
ret_string = "Application";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::SYSTEM_UPDATE):
|
||||||
|
ret_string = "System Update";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::MANUAL):
|
||||||
|
ret_string = "Manual";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::CHILD):
|
||||||
|
ret_string = "Child";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::TRIAL):
|
||||||
|
ret_string = "Trial";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::EXTENDED_SYSTEM_UPDATE):
|
||||||
|
ret_string = "Extended System Update";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_string = "Unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const char* dump_ncch_header_other_flag_bit(uint8_t bit)
|
||||||
|
{
|
||||||
|
const char* ret_string = nullptr;
|
||||||
|
|
||||||
|
switch (_BIT(bit))
|
||||||
|
{
|
||||||
|
case (nn::ctr::ncch::FIXED_AES_KEY):
|
||||||
|
ret_string = "FIXED_AES_KEY";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::NO_MOUNT_ROMFS):
|
||||||
|
ret_string = "NO_MOUNT_ROMFS";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::NO_AES):
|
||||||
|
ret_string = "NO_AES";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::SEED_KEY):
|
||||||
|
ret_string = "SEED_KEY";
|
||||||
|
break;
|
||||||
|
case (nn::ctr::ncch::MANUAL_DISCLOSURE):
|
||||||
|
ret_string = "MANUAL_DISCLOSURE";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ret_string = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret_string;
|
||||||
|
}
|
||||||
|
|
||||||
|
void dump_ncch_header(const nn::ctr::NcchHeader& ncchHdr)
|
||||||
|
{
|
||||||
|
printf("NcchSize: 0x%08x\n", ncchHdr.getNcchBinarySize());
|
||||||
|
printf("TitleID: %04x-%04x-%06x-%02x\n", ncchHdr.getTitleId().getDeviceGroup(), ncchHdr.getTitleId().getCategory(), ncchHdr.getTitleId().getUniqueId(), ncchHdr.getTitleId().getVariation());
|
||||||
|
printf("CompanyCode: %s\n", ncchHdr.getCompanyCode().c_str());
|
||||||
|
printf("NcchType: %04x (%s)\n", ncchHdr.getNcchType(), dump_ncch_header_ncch_type(ncchHdr.getNcchType()));
|
||||||
|
printf("SeedChecksum: %08x\n", ncchHdr.getSeedChecksum());
|
||||||
|
printf("ProgramID: %04x-%04x-%06x-%02x\n", ncchHdr.getProgramId().getDeviceGroup(), ncchHdr.getProgramId().getCategory(), ncchHdr.getProgramId().getUniqueId(), ncchHdr.getProgramId().getVariation());
|
||||||
|
printf("Product Code: %s\n", ncchHdr.getProductCode().c_str());
|
||||||
|
printf("Flags:\n");
|
||||||
|
printf(" NewCryptoFlag: %02x (%s)\n", ncchHdr.getNewCryptoFlag(), dump_ncch_header_crypto_flag(ncchHdr.getNewCryptoFlag()));
|
||||||
|
printf(" Platform: %02x (%s)\n", ncchHdr.getPlatform(), dump_ncch_header_platform_type(ncchHdr.getPlatform()));
|
||||||
|
printf(" FormType: %02x (%s)\n", ncchHdr.getFormType(), dump_ncch_header_form_type(ncchHdr.getFormType()));
|
||||||
|
printf(" ContentType: %02x (%s)\n", ncchHdr.getContentType(), dump_ncch_header_content_type(ncchHdr.getContentType()));
|
||||||
|
printf(" BlockSize: %02x\n", ncchHdr.getBlockSize());
|
||||||
|
|
||||||
|
if (ncchHdr.getOtherFlagList().size() > 0)
|
||||||
|
printf(" OtherFlag:\n");
|
||||||
|
for (size_t i = 0; i < ncchHdr.getOtherFlagList().size(); i++)
|
||||||
|
{
|
||||||
|
nn::ctr::ncch::OtherFlag flag = ncchHdr.getOtherFlagList()[i];
|
||||||
|
if (dump_ncch_header_other_flag_bit(flag) != nullptr)
|
||||||
|
{
|
||||||
|
printf(" %s\n", dump_ncch_header_other_flag_bit(flag));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
printf(" [bit%d]", flag);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
printf("Exheader:\n");
|
||||||
|
printf(" Size: 0x%08x\n", ncchHdr.getExtendedHeaderLayout().getSize());
|
||||||
|
printf(" Hash: ");
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
printf("%02x", ncchHdr.getExtendedHeaderLayout().getHash().bytes[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf("PlainRegion:\n");
|
||||||
|
printf(" Offset: 0x%08x\n", ncchHdr.getPlainRegionLayout().getOffset());
|
||||||
|
printf(" Size: 0x%08x\n", ncchHdr.getPlainRegionLayout().getSize());
|
||||||
|
printf("Logo:\n");
|
||||||
|
printf(" Offset: 0x%08x\n", ncchHdr.getLogoLayout().getOffset());
|
||||||
|
printf(" Size: 0x%08x\n", ncchHdr.getLogoLayout().getSize());
|
||||||
|
printf(" Hash: ");
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
printf("%02x", ncchHdr.getLogoLayout().getHash().bytes[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf("Exefs:\n");
|
||||||
|
printf(" Offset: 0x%08x\n", ncchHdr.getExefsLayout().getOffset());
|
||||||
|
printf(" Size: 0x%08x\n", ncchHdr.getExefsLayout().getSize());
|
||||||
|
printf(" ProtSize: 0x%08x\n", ncchHdr.getExefsLayout().getHashedSize());
|
||||||
|
printf(" Hash: ");
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
printf("%02x", ncchHdr.getExefsLayout().getHash().bytes[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
printf("Romfs:\n");
|
||||||
|
printf(" Offset: 0x%08x\n", ncchHdr.getRomfsLayout().getOffset());
|
||||||
|
printf(" Size: 0x%08x\n", ncchHdr.getRomfsLayout().getSize());
|
||||||
|
printf(" ProtSize: 0x%08x\n", ncchHdr.getRomfsLayout().getHashedSize());
|
||||||
|
printf(" Hash: ");
|
||||||
|
for (int i = 0; i < 32; i++)
|
||||||
|
{
|
||||||
|
printf("%02x", ncchHdr.getRomfsLayout().getHash().bytes[i]);
|
||||||
|
}
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
fnd::SimpleFile fileObj;
|
||||||
|
fnd::Vec<byte_t> fileData;
|
||||||
|
|
||||||
|
if (argc < 2)
|
||||||
|
{
|
||||||
|
printf("usage: %s <file>\n", argv[0]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// read file
|
||||||
|
try
|
||||||
|
{
|
||||||
|
fileObj.open(argv[1], fnd::SimpleFile::Read);
|
||||||
|
fileData.alloc(_MAX(fileObj.size(), 0x1000));
|
||||||
|
fileObj.read(fileData.data(), fileData.size());
|
||||||
|
}
|
||||||
|
catch (const fnd::Exception &e)
|
||||||
|
{
|
||||||
|
printf("[ERROR] %s\n", e.error());
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// attempt to read file
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nn::ctr::CodeBinaryHeader hdr, test;
|
||||||
|
hdr.fromBytes(fileData.data(), fileData.size());
|
||||||
|
printf("[NOTICE] .code file detected\n");
|
||||||
|
dump_code_header(hdr);
|
||||||
|
|
||||||
|
hdr.toBytes();
|
||||||
|
test.fromBytes(hdr.getBytes().data(), hdr.getBytes().size());
|
||||||
|
printf("Testing re-serialisation\n");
|
||||||
|
dump_code_header(test);
|
||||||
|
}
|
||||||
|
catch (const fnd::Exception &e)
|
||||||
|
{
|
||||||
|
printf("[NOTICE] not a .code file (%s)\n", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
nn::ctr::NcchHeader hdr, test;
|
||||||
|
hdr.fromBytes(fileData.data() + 0x100, fileData.size() >= 0x200 ? 0x100 : 0);
|
||||||
|
printf("[NOTICE] NCCH file detected\n");
|
||||||
|
dump_ncch_header(hdr);
|
||||||
|
|
||||||
|
hdr.toBytes();
|
||||||
|
test.fromBytes(hdr.getBytes().data(), hdr.getBytes().size());
|
||||||
|
printf("Testing re-serialisation\n");
|
||||||
|
dump_ncch_header(test);
|
||||||
|
}
|
||||||
|
catch (const fnd::Exception &e)
|
||||||
|
{
|
||||||
|
printf("[NOTICE] not a NCCH file (%s)\n", e.what());
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in a new issue