mirror of
https://github.com/jakcron/nstool.git
synced 2024-12-22 18:55:29 +00:00
commit
7ace472d77
46
LICENSE
46
LICENSE
|
@ -1,5 +1,4 @@
|
|||
MIT License
|
||||
|
||||
NXTools
|
||||
Copyright (c) 2017-2018 Jack
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
|
@ -19,3 +18,46 @@ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
PolarSSL
|
||||
Copyright (C) 2006-2013, Brainspark B.V.
|
||||
All rights reserved.
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License along
|
||||
with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
|
||||
LZ4 Library
|
||||
Copyright (c) 2011-2016, Yann Collet
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
* Redistributions in binary form must reproduce the above copyright notice, this
|
||||
list of conditions and the following disclaimer in the documentation and/or
|
||||
other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
14
NXTools.sln
14
NXTools.sln
|
@ -35,6 +35,11 @@ EndProject
|
|||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libes", "lib\libes\es.vcxproj", "{7BE99936-0D40-410D-944B-4513C2EFF8DC}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "nstool", "programs\nstool\nstool.vcxproj", "{AF09FA96-4463-417D-8FE6-526063F41349}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177} = {CF01B5B7-730A-447F-9BB2-5EDA9B082177}
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "libcompress", "lib\libcompress\libcompress.vcxproj", "{CF01B5B7-730A-447F-9BB2-5EDA9B082177}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
|
@ -84,6 +89,14 @@ Global
|
|||
{AF09FA96-4463-417D-8FE6-526063F41349}.Release|x64.Build.0 = Release|x64
|
||||
{AF09FA96-4463-417D-8FE6-526063F41349}.Release|x86.ActiveCfg = Release|Win32
|
||||
{AF09FA96-4463-417D-8FE6-526063F41349}.Release|x86.Build.0 = Release|Win32
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Debug|x64.Build.0 = Debug|x64
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Debug|x86.Build.0 = Debug|Win32
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Release|x64.ActiveCfg = Release|x64
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Release|x64.Build.0 = Release|x64
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Release|x86.ActiveCfg = Release|Win32
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
@ -94,6 +107,7 @@ Global
|
|||
{91BA9E79-8242-4F7D-B997-0DFEC95EA22B} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||
{7BE99936-0D40-410D-944B-4513C2EFF8DC} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||
{AF09FA96-4463-417D-8FE6-526063F41349} = {E0863FCC-8E72-490D-BE1B-458F12CA8298}
|
||||
{CF01B5B7-730A-447F-9BB2-5EDA9B082177} = {170B4A09-1B67-4A62-93AB-116EBCFF4A8C}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {07DCCACC-D10D-47C9-85AE-FB9C54DB7D62}
|
||||
|
|
11
README.md
11
README.md
|
@ -6,14 +6,15 @@ Tools & Libraries for NX (Nintendo Switch).
|
|||
|
||||
# Tools
|
||||
|
||||
* __nstool__ - read *.npdm, read/extract PartitionFS (PFS0|HFS0) blobs (including *.nsp), read/extract *.xci, read/extract *.nca, read *.cnmt
|
||||
* __nstool__ - read *.npdm, read/extract PartitionFS (PFS0|HFS0) blobs (including *.nsp), read/extract *.xci, read/extract *.nca, read *.cnmt, read *.nso
|
||||
|
||||
# Libraries
|
||||
|
||||
* __libfnd__ - Foundation library.
|
||||
* __libcrypto__ - Cryptographic functions (AES,SHA,RSA). Wrapper for [mbedTLS](https://github.com/ARMmbed/mbedtls)
|
||||
* __libes__ - Handling of (NX relevant) eShop file type processing. (eTickets, etc)
|
||||
* __libnx__ - Handling of NX file types
|
||||
* __libfnd__ - Foundation library.
|
||||
* __libcrypto__ - Cryptographic functions (AES,SHA,RSA). Wrapper for [mbedTLS](https://github.com/ARMmbed/mbedtls)
|
||||
* __libcompress__ - Compression algorithms (LZ4). Wrapper for [lz4](https://github.com/lz4/lz4)
|
||||
* __libes__ - Handling of (NX relevant) eShop file type processing. (eTickets, etc)
|
||||
* __libnx__ - Handling of NX file types
|
||||
|
||||
# Building
|
||||
|
||||
|
|
11
lib/libcompress/include/compress/lz4.h
Normal file
11
lib/libcompress/include/compress/lz4.h
Normal file
|
@ -0,0 +1,11 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
|
||||
namespace compress
|
||||
{
|
||||
namespace lz4
|
||||
{
|
||||
void compressData(const uint8_t* src, uint32_t src_len, uint8_t* dst, uint32_t dst_capacity, uint32_t& compressed_size);
|
||||
void decompressData(const uint8_t* src, uint32_t src_len, uint8_t* dst, uint32_t dst_capacity, uint32_t& decompressed_size);
|
||||
}
|
||||
}
|
135
lib/libcompress/libcompress.vcxproj
Normal file
135
lib/libcompress/libcompress.vcxproj
Normal file
|
@ -0,0 +1,135 @@
|
|||
<?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>{CF01B5B7-730A-447F-9BB2-5EDA9B082177}</ProjectGuid>
|
||||
<RootNamespace>libcompress</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>..\libcompress\include;..\libcompress\source\lz4;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\libcompress\include;..\libcompress\source\lz4;</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>..\libcompress\include;..\libcompress\source\lz4;</AdditionalIncludeDirectories>
|
||||
</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>..\libcompress\include;..\libcompress\source\lz4;</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\compress\lz4.h" />
|
||||
<ClInclude Include="source\lz4\lz4.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\lz4_wrapper.cpp" />
|
||||
<ClCompile Include="source\lz4\lz4.c" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
42
lib/libcompress/libcompress.vcxproj.filters
Normal file
42
lib/libcompress/libcompress.vcxproj.filters
Normal file
|
@ -0,0 +1,42 @@
|
|||
<?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>
|
||||
<Filter Include="Header Files\compress">
|
||||
<UniqueIdentifier>{8b967d21-0d8f-4bf9-aa1c-54d33abdcec6}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Source Files\lz4">
|
||||
<UniqueIdentifier>{73860001-f667-4a56-a6e3-9007611f7da7}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\compress\lz4.h">
|
||||
<Filter>Header Files\compress</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\lz4\lz4.h">
|
||||
<Filter>Source Files\lz4</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\lz4\lz4.c">
|
||||
<Filter>Source Files\lz4</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\lz4_wrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
</ItemGroup>
|
||||
</Project>
|
4
lib/libcompress/libcompress.vcxproj.user
Normal file
4
lib/libcompress/libcompress.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/libcompress/makefile
Normal file
47
lib/libcompress/makefile
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Sources
|
||||
SRC_DIR = source source/lz4
|
||||
OBJS = $(foreach dir,$(SRC_DIR),$(subst .cpp,.o,$(wildcard $(dir)/*.cpp))) $(foreach dir,$(SRC_DIR),$(subst .c,.o,$(wildcard $(dir)/*.c)))
|
||||
|
||||
# External dependencies
|
||||
DEPENDS =
|
||||
LIB_DIR = ..
|
||||
INCS = -I"include" -I"source/lz4" $(foreach dep,$(DEPENDS), -I"$(LIB_DIR)/lib$(dep)/include")
|
||||
|
||||
|
||||
# Compiler Settings
|
||||
CXXFLAGS = -std=c++11 $(INCS) -D__STDC_FORMAT_MACROS -Wall -Wno-unused-value
|
||||
CFLAGS = -std=c11 $(INCS) -Wall -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 += -Wno-unused-but-set-variable
|
||||
CXXFLAGS += -Wno-unused-but-set-variable
|
||||
else
|
||||
UNAME = $(shell uname -s)
|
||||
ifeq ($(UNAME), Darwin)
|
||||
# MacOS Only Flags/Libs
|
||||
CFLAGS += -Wno-unused-private-field
|
||||
CXXFLAGS += -Wno-unused-private-field
|
||||
ARFLAGS = rc
|
||||
else
|
||||
# *nix Only Flags/Libs
|
||||
CFLAGS += -Wno-unused-but-set-variable
|
||||
CXXFLAGS += -Wno-unused-but-set-variable
|
||||
endif
|
||||
|
||||
endif
|
||||
|
||||
# Output
|
||||
OUTPUT = $(shell basename $(CURDIR)).a
|
||||
|
||||
main: build
|
||||
|
||||
rebuild: clean build
|
||||
|
||||
build: $(OBJS)
|
||||
ar $(ARFLAGS) $(OUTPUT) $(OBJS)
|
||||
|
||||
clean:
|
||||
rm -rf $(OUTPUT) $(OBJS)
|
1930
lib/libcompress/source/lz4/lz4.c
Normal file
1930
lib/libcompress/source/lz4/lz4.c
Normal file
File diff suppressed because it is too large
Load diff
607
lib/libcompress/source/lz4/lz4.h
Normal file
607
lib/libcompress/source/lz4/lz4.h
Normal file
|
@ -0,0 +1,607 @@
|
|||
/*
|
||||
* LZ4 - Fast LZ compression algorithm
|
||||
* Header File
|
||||
* Copyright (C) 2011-2017, Yann Collet.
|
||||
|
||||
BSD 2-Clause License (http://www.opensource.org/licenses/bsd-license.php)
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are
|
||||
met:
|
||||
|
||||
* Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above
|
||||
copyright notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other materials provided with the
|
||||
distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
You can contact the author at :
|
||||
- LZ4 homepage : http://www.lz4.org
|
||||
- LZ4 source repository : https://github.com/lz4/lz4
|
||||
*/
|
||||
#if defined (__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifndef LZ4_H_2983827168210
|
||||
#define LZ4_H_2983827168210
|
||||
|
||||
/* --- Dependency --- */
|
||||
#include <stddef.h> /* size_t */
|
||||
|
||||
|
||||
/**
|
||||
Introduction
|
||||
|
||||
LZ4 is lossless compression algorithm, providing compression speed at 400 MB/s per core,
|
||||
scalable with multi-cores CPU. It features an extremely fast decoder, with speed in
|
||||
multiple GB/s per core, typically reaching RAM speed limits on multi-core systems.
|
||||
|
||||
The LZ4 compression library provides in-memory compression and decompression functions.
|
||||
Compression can be done in:
|
||||
- a single step (described as Simple Functions)
|
||||
- a single step, reusing a context (described in Advanced Functions)
|
||||
- unbounded multiple steps (described as Streaming compression)
|
||||
|
||||
lz4.h provides block compression functions. It gives full buffer control to user.
|
||||
Decompressing an lz4-compressed block also requires metadata (such as compressed size).
|
||||
Each application is free to encode such metadata in whichever way it wants.
|
||||
|
||||
An additional format, called LZ4 frame specification (doc/lz4_Frame_format.md),
|
||||
take care of encoding standard metadata alongside LZ4-compressed blocks.
|
||||
If your application requires interoperability, it's recommended to use it.
|
||||
A library is provided to take care of it, see lz4frame.h.
|
||||
*/
|
||||
|
||||
/*^***************************************************************
|
||||
* Export parameters
|
||||
*****************************************************************/
|
||||
/*
|
||||
* LZ4_DLL_EXPORT :
|
||||
* Enable exporting of functions when building a Windows DLL
|
||||
* LZ4LIB_VISIBILITY :
|
||||
* Control library symbols visibility.
|
||||
*/
|
||||
#ifndef LZ4LIB_VISIBILITY
|
||||
# if defined(__GNUC__) && (__GNUC__ >= 4)
|
||||
# define LZ4LIB_VISIBILITY __attribute__ ((visibility ("default")))
|
||||
# else
|
||||
# define LZ4LIB_VISIBILITY
|
||||
# endif
|
||||
#endif
|
||||
#if defined(LZ4_DLL_EXPORT) && (LZ4_DLL_EXPORT==1)
|
||||
# define LZ4LIB_API __declspec(dllexport) LZ4LIB_VISIBILITY
|
||||
#elif defined(LZ4_DLL_IMPORT) && (LZ4_DLL_IMPORT==1)
|
||||
# define LZ4LIB_API __declspec(dllimport) LZ4LIB_VISIBILITY /* It isn't required but allows to generate better code, saving a function pointer load from the IAT and an indirect jump.*/
|
||||
#else
|
||||
# define LZ4LIB_API LZ4LIB_VISIBILITY
|
||||
#endif
|
||||
|
||||
/*------ Version ------*/
|
||||
#define LZ4_VERSION_MAJOR 1 /* for breaking interface changes */
|
||||
#define LZ4_VERSION_MINOR 8 /* for new (non-breaking) interface capabilities */
|
||||
#define LZ4_VERSION_RELEASE 2 /* for tweaks, bug-fixes, or development */
|
||||
|
||||
#define LZ4_VERSION_NUMBER (LZ4_VERSION_MAJOR *100*100 + LZ4_VERSION_MINOR *100 + LZ4_VERSION_RELEASE)
|
||||
|
||||
#define LZ4_LIB_VERSION LZ4_VERSION_MAJOR.LZ4_VERSION_MINOR.LZ4_VERSION_RELEASE
|
||||
#define LZ4_QUOTE(str) #str
|
||||
#define LZ4_EXPAND_AND_QUOTE(str) LZ4_QUOTE(str)
|
||||
#define LZ4_VERSION_STRING LZ4_EXPAND_AND_QUOTE(LZ4_LIB_VERSION)
|
||||
|
||||
LZ4LIB_API int LZ4_versionNumber (void); /**< library version number; useful to check dll version */
|
||||
LZ4LIB_API const char* LZ4_versionString (void); /**< library version string; unseful to check dll version */
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Tuning parameter
|
||||
**************************************/
|
||||
/*!
|
||||
* LZ4_MEMORY_USAGE :
|
||||
* Memory usage formula : N->2^N Bytes (examples : 10 -> 1KB; 12 -> 4KB ; 16 -> 64KB; 20 -> 1MB; etc.)
|
||||
* Increasing memory usage improves compression ratio
|
||||
* Reduced memory usage may improve speed, thanks to cache effect
|
||||
* Default value is 14, for 16KB, which nicely fits into Intel x86 L1 cache
|
||||
*/
|
||||
#ifndef LZ4_MEMORY_USAGE
|
||||
# define LZ4_MEMORY_USAGE 14
|
||||
#endif
|
||||
|
||||
/*-************************************
|
||||
* Simple Functions
|
||||
**************************************/
|
||||
/*! LZ4_compress_default() :
|
||||
Compresses 'srcSize' bytes from buffer 'src'
|
||||
into already allocated 'dst' buffer of size 'dstCapacity'.
|
||||
Compression is guaranteed to succeed if 'dstCapacity' >= LZ4_compressBound(srcSize).
|
||||
It also runs faster, so it's a recommended setting.
|
||||
If the function cannot compress 'src' into a more limited 'dst' budget,
|
||||
compression stops *immediately*, and the function result is zero.
|
||||
Note : as a consequence, 'dst' content is not valid.
|
||||
Note 2 : This function is protected against buffer overflow scenarios (never writes outside 'dst' buffer, nor read outside 'source' buffer).
|
||||
srcSize : max supported value is LZ4_MAX_INPUT_SIZE.
|
||||
dstCapacity : size of buffer 'dst' (which must be already allocated)
|
||||
return : the number of bytes written into buffer 'dst' (necessarily <= dstCapacity)
|
||||
or 0 if compression fails */
|
||||
LZ4LIB_API int LZ4_compress_default(const char* src, char* dst, int srcSize, int dstCapacity);
|
||||
|
||||
/*! LZ4_decompress_safe() :
|
||||
compressedSize : is the exact complete size of the compressed block.
|
||||
dstCapacity : is the size of destination buffer, which must be already allocated.
|
||||
return : the number of bytes decompressed into destination buffer (necessarily <= dstCapacity)
|
||||
If destination buffer is not large enough, decoding will stop and output an error code (negative value).
|
||||
If the source stream is detected malformed, the function will stop decoding and return a negative result.
|
||||
This function is protected against malicious data packets.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe (const char* src, char* dst, int compressedSize, int dstCapacity);
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Advanced Functions
|
||||
**************************************/
|
||||
#define LZ4_MAX_INPUT_SIZE 0x7E000000 /* 2 113 929 216 bytes */
|
||||
#define LZ4_COMPRESSBOUND(isize) ((unsigned)(isize) > (unsigned)LZ4_MAX_INPUT_SIZE ? 0 : (isize) + ((isize)/255) + 16)
|
||||
|
||||
/*!
|
||||
LZ4_compressBound() :
|
||||
Provides the maximum size that LZ4 compression may output in a "worst case" scenario (input data not compressible)
|
||||
This function is primarily useful for memory allocation purposes (destination buffer size).
|
||||
Macro LZ4_COMPRESSBOUND() is also provided for compilation-time evaluation (stack memory allocation for example).
|
||||
Note that LZ4_compress_default() compresses faster when dstCapacity is >= LZ4_compressBound(srcSize)
|
||||
inputSize : max supported value is LZ4_MAX_INPUT_SIZE
|
||||
return : maximum output size in a "worst case" scenario
|
||||
or 0, if input size is incorrect (too large or negative)
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compressBound(int inputSize);
|
||||
|
||||
/*!
|
||||
LZ4_compress_fast() :
|
||||
Same as LZ4_compress_default(), but allows selection of "acceleration" factor.
|
||||
The larger the acceleration value, the faster the algorithm, but also the lesser the compression.
|
||||
It's a trade-off. It can be fine tuned, with each successive value providing roughly +~3% to speed.
|
||||
An acceleration value of "1" is the same as regular LZ4_compress_default()
|
||||
Values <= 0 will be replaced by ACCELERATION_DEFAULT (currently == 1, see lz4.c).
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_fast (const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||
|
||||
|
||||
/*!
|
||||
LZ4_compress_fast_extState() :
|
||||
Same compression function, just using an externally allocated memory space to store compression state.
|
||||
Use LZ4_sizeofState() to know how much memory must be allocated,
|
||||
and allocate it on 8-bytes boundaries (using malloc() typically).
|
||||
Then, provide it as 'void* state' to compression function.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_sizeofState(void);
|
||||
LZ4LIB_API int LZ4_compress_fast_extState (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||
|
||||
|
||||
/*!
|
||||
LZ4_compress_destSize() :
|
||||
Reverse the logic : compresses as much data as possible from 'src' buffer
|
||||
into already allocated buffer 'dst' of size 'targetDestSize'.
|
||||
This function either compresses the entire 'src' content into 'dst' if it's large enough,
|
||||
or fill 'dst' buffer completely with as much data as possible from 'src'.
|
||||
*srcSizePtr : will be modified to indicate how many bytes where read from 'src' to fill 'dst'.
|
||||
New value is necessarily <= old value.
|
||||
return : Nb bytes written into 'dst' (necessarily <= targetDestSize)
|
||||
or 0 if compression fails
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_destSize (const char* src, char* dst, int* srcSizePtr, int targetDstSize);
|
||||
|
||||
|
||||
/*!
|
||||
LZ4_decompress_fast() : **unsafe!**
|
||||
This function is a bit faster than LZ4_decompress_safe(),
|
||||
but it may misbehave on malformed input because it doesn't perform full validation of compressed data.
|
||||
originalSize : is the uncompressed size to regenerate
|
||||
Destination buffer must be already allocated, and its size must be >= 'originalSize' bytes.
|
||||
return : number of bytes read from source buffer (== compressed size).
|
||||
If the source stream is detected malformed, the function stops decoding and return a negative result.
|
||||
note : This function is only usable if the originalSize of uncompressed data is known in advance.
|
||||
The caller should also check that all the compressed input has been consumed properly,
|
||||
i.e. that the return value matches the size of the buffer with compressed input.
|
||||
The function never writes past the output buffer. However, since it doesn't know its 'src' size,
|
||||
it may read past the intended input. Also, because match offsets are not validated during decoding,
|
||||
reads from 'src' may underflow. Use this function in trusted environment **only**.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_fast (const char* src, char* dst, int originalSize);
|
||||
|
||||
/*!
|
||||
LZ4_decompress_safe_partial() :
|
||||
This function decompress a compressed block of size 'srcSize' at position 'src'
|
||||
into destination buffer 'dst' of size 'dstCapacity'.
|
||||
The function will decompress a minimum of 'targetOutputSize' bytes, and stop after that.
|
||||
However, it's not accurate, and may write more than 'targetOutputSize' (but always <= dstCapacity).
|
||||
@return : the number of bytes decoded in the destination buffer (necessarily <= dstCapacity)
|
||||
Note : this number can also be < targetOutputSize, if compressed block contains less data.
|
||||
Therefore, always control how many bytes were decoded.
|
||||
If source stream is detected malformed, function returns a negative result.
|
||||
This function is protected against malicious data packets.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_partial (const char* src, char* dst, int srcSize, int targetOutputSize, int dstCapacity);
|
||||
|
||||
|
||||
/*-*********************************************
|
||||
* Streaming Compression Functions
|
||||
***********************************************/
|
||||
typedef union LZ4_stream_u LZ4_stream_t; /* incomplete type (defined later) */
|
||||
|
||||
/*! LZ4_createStream() and LZ4_freeStream() :
|
||||
* LZ4_createStream() will allocate and initialize an `LZ4_stream_t` structure.
|
||||
* LZ4_freeStream() releases its memory.
|
||||
*/
|
||||
LZ4LIB_API LZ4_stream_t* LZ4_createStream(void);
|
||||
LZ4LIB_API int LZ4_freeStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*! LZ4_resetStream() :
|
||||
* An LZ4_stream_t structure can be allocated once and re-used multiple times.
|
||||
* Use this function to start compressing a new stream.
|
||||
*/
|
||||
LZ4LIB_API void LZ4_resetStream (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*! LZ4_loadDict() :
|
||||
* Use this function to load a static dictionary into LZ4_stream_t.
|
||||
* Any previous data will be forgotten, only 'dictionary' will remain in memory.
|
||||
* Loading a size of 0 is allowed, and is the same as reset.
|
||||
* @return : dictionary size, in bytes (necessarily <= 64 KB)
|
||||
*/
|
||||
LZ4LIB_API int LZ4_loadDict (LZ4_stream_t* streamPtr, const char* dictionary, int dictSize);
|
||||
|
||||
/*! LZ4_compress_fast_continue() :
|
||||
* Compress 'src' content using data from previously compressed blocks, for better compression ratio.
|
||||
* 'dst' buffer must be already allocated.
|
||||
* If dstCapacity >= LZ4_compressBound(srcSize), compression is guaranteed to succeed, and runs faster.
|
||||
*
|
||||
* Important : The previous 64KB of compressed data is assumed to remain present and unmodified in memory!
|
||||
*
|
||||
* Special 1 : When input is a double-buffer, they can have any size, including < 64 KB.
|
||||
* Make sure that buffers are separated by at least one byte.
|
||||
* This way, each block only depends on previous block.
|
||||
* Special 2 : If input buffer is a ring-buffer, it can have any size, including < 64 KB.
|
||||
*
|
||||
* @return : size of compressed block
|
||||
* or 0 if there is an error (typically, cannot fit into 'dst').
|
||||
* After an error, the stream status is invalid, it can only be reset or freed.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_fast_continue (LZ4_stream_t* streamPtr, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||
|
||||
/*! LZ4_saveDict() :
|
||||
* If last 64KB data cannot be guaranteed to remain available at its current memory location,
|
||||
* save it into a safer place (char* safeBuffer).
|
||||
* This is schematically equivalent to a memcpy() followed by LZ4_loadDict(),
|
||||
* but is much faster, because LZ4_saveDict() doesn't need to rebuild tables.
|
||||
* @return : saved dictionary size in bytes (necessarily <= maxDictSize), or 0 if error.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_saveDict (LZ4_stream_t* streamPtr, char* safeBuffer, int maxDictSize);
|
||||
|
||||
|
||||
/*-**********************************************
|
||||
* Streaming Decompression Functions
|
||||
* Bufferless synchronous API
|
||||
************************************************/
|
||||
typedef union LZ4_streamDecode_u LZ4_streamDecode_t; /* tracking context */
|
||||
|
||||
/*! LZ4_createStreamDecode() and LZ4_freeStreamDecode() :
|
||||
* creation / destruction of streaming decompression tracking context.
|
||||
* A tracking context can be re-used multiple times.
|
||||
*/
|
||||
LZ4LIB_API LZ4_streamDecode_t* LZ4_createStreamDecode(void);
|
||||
LZ4LIB_API int LZ4_freeStreamDecode (LZ4_streamDecode_t* LZ4_stream);
|
||||
|
||||
/*! LZ4_setStreamDecode() :
|
||||
* An LZ4_streamDecode_t context can be allocated once and re-used multiple times.
|
||||
* Use this function to start decompression of a new stream of blocks.
|
||||
* A dictionary can optionnally be set. Use NULL or size 0 for a reset order.
|
||||
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
|
||||
* @return : 1 if OK, 0 if error
|
||||
*/
|
||||
LZ4LIB_API int LZ4_setStreamDecode (LZ4_streamDecode_t* LZ4_streamDecode, const char* dictionary, int dictSize);
|
||||
|
||||
/*! LZ4_decoderRingBufferSize() : v1.8.2
|
||||
* Note : in a ring buffer scenario (optional),
|
||||
* blocks are presumed decompressed next to each other
|
||||
* up to the moment there is not enough remaining space for next block (remainingSize < maxBlockSize),
|
||||
* at which stage it resumes from beginning of ring buffer.
|
||||
* When setting such a ring buffer for streaming decompression,
|
||||
* provides the minimum size of this ring buffer
|
||||
* to be compatible with any source respecting maxBlockSize condition.
|
||||
* @return : minimum ring buffer size,
|
||||
* or 0 if there is an error (invalid maxBlockSize).
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decoderRingBufferSize(int maxBlockSize);
|
||||
#define LZ4_DECODER_RING_BUFFER_SIZE(mbs) (65536 + 14 + (mbs)) /* for static allocation; mbs presumed valid */
|
||||
|
||||
/*! LZ4_decompress_*_continue() :
|
||||
* These decoding functions allow decompression of consecutive blocks in "streaming" mode.
|
||||
* A block is an unsplittable entity, it must be presented entirely to a decompression function.
|
||||
* Decompression functions only accepts one block at a time.
|
||||
* The last 64KB of previously decoded data *must* remain available and unmodified at the memory position where they were decoded.
|
||||
* If less than 64KB of data has been decoded, all the data must be present.
|
||||
*
|
||||
* Special : if decompression side sets a ring buffer, it must respect one of the following conditions :
|
||||
* - Decompression buffer size is _at least_ LZ4_decoderRingBufferSize(maxBlockSize).
|
||||
* maxBlockSize is the maximum size of any single block. It can have any value > 16 bytes.
|
||||
* In which case, encoding and decoding buffers do not need to be synchronized.
|
||||
* Actually, data can be produced by any source compliant with LZ4 format specification, and respecting maxBlockSize.
|
||||
* - Synchronized mode :
|
||||
* Decompression buffer size is _exactly_ the same as compression buffer size,
|
||||
* and follows exactly same update rule (block boundaries at same positions),
|
||||
* and decoding function is provided with exact decompressed size of each block (exception for last block of the stream),
|
||||
* _then_ decoding & encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||
* - Decompression buffer is larger than encoding buffer, by a minimum of maxBlockSize more bytes.
|
||||
* In which case, encoding and decoding buffers do not need to be synchronized,
|
||||
* and encoding ring buffer can have any size, including small ones ( < 64 KB).
|
||||
*
|
||||
* Whenever these conditions are not possible,
|
||||
* save the last 64KB of decoded data into a safe buffer where it can't be modified during decompression,
|
||||
* then indicate where this data is saved using LZ4_setStreamDecode(), before decompressing next block.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int srcSize, int dstCapacity);
|
||||
LZ4LIB_API int LZ4_decompress_fast_continue (LZ4_streamDecode_t* LZ4_streamDecode, const char* src, char* dst, int originalSize);
|
||||
|
||||
|
||||
/*! LZ4_decompress_*_usingDict() :
|
||||
* These decoding functions work the same as
|
||||
* a combination of LZ4_setStreamDecode() followed by LZ4_decompress_*_continue()
|
||||
* They are stand-alone, and don't need an LZ4_streamDecode_t structure.
|
||||
* Dictionary is presumed stable : it must remain accessible and unmodified during next decompression.
|
||||
*/
|
||||
LZ4LIB_API int LZ4_decompress_safe_usingDict (const char* src, char* dst, int srcSize, int dstCapcity, const char* dictStart, int dictSize);
|
||||
LZ4LIB_API int LZ4_decompress_fast_usingDict (const char* src, char* dst, int originalSize, const char* dictStart, int dictSize);
|
||||
|
||||
|
||||
/*^**********************************************
|
||||
* !!!!!! STATIC LINKING ONLY !!!!!!
|
||||
***********************************************/
|
||||
|
||||
/*-************************************
|
||||
* Unstable declarations
|
||||
**************************************
|
||||
* Declarations in this section should be considered unstable.
|
||||
* Use at your own peril, etc., etc.
|
||||
* They may be removed in the future.
|
||||
* Their signatures may change.
|
||||
**************************************/
|
||||
|
||||
#ifdef LZ4_STATIC_LINKING_ONLY
|
||||
|
||||
/*! LZ4_resetStream_fast() :
|
||||
* Use this, like LZ4_resetStream(), to prepare a context for a new chain of
|
||||
* calls to a streaming API (e.g., LZ4_compress_fast_continue()).
|
||||
*
|
||||
* Note:
|
||||
* Using this in advance of a non- streaming-compression function is redundant,
|
||||
* and potentially bad for performance, since they all perform their own custom
|
||||
* reset internally.
|
||||
*
|
||||
* Differences from LZ4_resetStream():
|
||||
* When an LZ4_stream_t is known to be in a internally coherent state,
|
||||
* it can often be prepared for a new compression with almost no work, only
|
||||
* sometimes falling back to the full, expensive reset that is always required
|
||||
* when the stream is in an indeterminate state (i.e., the reset performed by
|
||||
* LZ4_resetStream()).
|
||||
*
|
||||
* LZ4_streams are guaranteed to be in a valid state when:
|
||||
* - returned from LZ4_createStream()
|
||||
* - reset by LZ4_resetStream()
|
||||
* - memset(stream, 0, sizeof(LZ4_stream_t)), though this is discouraged
|
||||
* - the stream was in a valid state and was reset by LZ4_resetStream_fast()
|
||||
* - the stream was in a valid state and was then used in any compression call
|
||||
* that returned success
|
||||
* - the stream was in an indeterminate state and was used in a compression
|
||||
* call that fully reset the state (e.g., LZ4_compress_fast_extState()) and
|
||||
* that returned success
|
||||
*
|
||||
* When a stream isn't known to be in a valid state, it is not safe to pass to
|
||||
* any fastReset or streaming function. It must first be cleansed by the full
|
||||
* LZ4_resetStream().
|
||||
*/
|
||||
LZ4LIB_API void LZ4_resetStream_fast (LZ4_stream_t* streamPtr);
|
||||
|
||||
/*! LZ4_compress_fast_extState_fastReset() :
|
||||
* A variant of LZ4_compress_fast_extState().
|
||||
*
|
||||
* Using this variant avoids an expensive initialization step. It is only safe
|
||||
* to call if the state buffer is known to be correctly initialized already
|
||||
* (see above comment on LZ4_resetStream_fast() for a definition of "correctly
|
||||
* initialized"). From a high level, the difference is that this function
|
||||
* initializes the provided state with a call to something like
|
||||
* LZ4_resetStream_fast() while LZ4_compress_fast_extState() starts with a
|
||||
* call to LZ4_resetStream().
|
||||
*/
|
||||
LZ4LIB_API int LZ4_compress_fast_extState_fastReset (void* state, const char* src, char* dst, int srcSize, int dstCapacity, int acceleration);
|
||||
|
||||
/*! LZ4_attach_dictionary() :
|
||||
* This is an experimental API that allows for the efficient use of a
|
||||
* static dictionary many times.
|
||||
*
|
||||
* Rather than re-loading the dictionary buffer into a working context before
|
||||
* each compression, or copying a pre-loaded dictionary's LZ4_stream_t into a
|
||||
* working LZ4_stream_t, this function introduces a no-copy setup mechanism,
|
||||
* in which the working stream references the dictionary stream in-place.
|
||||
*
|
||||
* Several assumptions are made about the state of the dictionary stream.
|
||||
* Currently, only streams which have been prepared by LZ4_loadDict() should
|
||||
* be expected to work.
|
||||
*
|
||||
* Alternatively, the provided dictionary stream pointer may be NULL, in which
|
||||
* case any existing dictionary stream is unset.
|
||||
*
|
||||
* If a dictionary is provided, it replaces any pre-existing stream history.
|
||||
* The dictionary contents are the only history that can be referenced and
|
||||
* logically immediately precede the data compressed in the first subsequent
|
||||
* compression call.
|
||||
*
|
||||
* The dictionary will only remain attached to the working stream through the
|
||||
* first compression call, at the end of which it is cleared. The dictionary
|
||||
* stream (and source buffer) must remain in-place / accessible / unchanged
|
||||
* through the completion of the first compression call on the stream.
|
||||
*/
|
||||
LZ4LIB_API void LZ4_attach_dictionary(LZ4_stream_t *working_stream, const LZ4_stream_t *dictionary_stream);
|
||||
|
||||
#endif
|
||||
|
||||
/*-************************************
|
||||
* Private definitions
|
||||
**************************************
|
||||
* Do not use these definitions.
|
||||
* They are exposed to allow static allocation of `LZ4_stream_t` and `LZ4_streamDecode_t`.
|
||||
* Using these definitions will expose code to API and/or ABI break in future versions of the library.
|
||||
**************************************/
|
||||
#define LZ4_HASHLOG (LZ4_MEMORY_USAGE-2)
|
||||
#define LZ4_HASHTABLESIZE (1 << LZ4_MEMORY_USAGE)
|
||||
#define LZ4_HASH_SIZE_U32 (1 << LZ4_HASHLOG) /* required as macro for static allocation */
|
||||
|
||||
#if defined(__cplusplus) || (defined (__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 */)
|
||||
#include <stdint.h>
|
||||
|
||||
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||
struct LZ4_stream_t_internal {
|
||||
uint32_t hashTable[LZ4_HASH_SIZE_U32];
|
||||
uint32_t currentOffset;
|
||||
uint16_t initCheck;
|
||||
uint16_t tableType;
|
||||
const uint8_t* dictionary;
|
||||
const LZ4_stream_t_internal* dictCtx;
|
||||
uint32_t dictSize;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const uint8_t* externalDict;
|
||||
size_t extDictSize;
|
||||
const uint8_t* prefixEnd;
|
||||
size_t prefixSize;
|
||||
} LZ4_streamDecode_t_internal;
|
||||
|
||||
#else
|
||||
|
||||
typedef struct LZ4_stream_t_internal LZ4_stream_t_internal;
|
||||
struct LZ4_stream_t_internal {
|
||||
unsigned int hashTable[LZ4_HASH_SIZE_U32];
|
||||
unsigned int currentOffset;
|
||||
unsigned short initCheck;
|
||||
unsigned short tableType;
|
||||
const unsigned char* dictionary;
|
||||
const LZ4_stream_t_internal* dictCtx;
|
||||
unsigned int dictSize;
|
||||
};
|
||||
|
||||
typedef struct {
|
||||
const unsigned char* externalDict;
|
||||
size_t extDictSize;
|
||||
const unsigned char* prefixEnd;
|
||||
size_t prefixSize;
|
||||
} LZ4_streamDecode_t_internal;
|
||||
|
||||
#endif
|
||||
|
||||
/*!
|
||||
* LZ4_stream_t :
|
||||
* information structure to track an LZ4 stream.
|
||||
* init this structure before first use.
|
||||
* note : only use in association with static linking !
|
||||
* this definition is not API/ABI safe,
|
||||
* it may change in a future version !
|
||||
*/
|
||||
#define LZ4_STREAMSIZE_U64 ((1 << (LZ4_MEMORY_USAGE-3)) + 4)
|
||||
#define LZ4_STREAMSIZE (LZ4_STREAMSIZE_U64 * sizeof(unsigned long long))
|
||||
union LZ4_stream_u {
|
||||
unsigned long long table[LZ4_STREAMSIZE_U64];
|
||||
LZ4_stream_t_internal internal_donotuse;
|
||||
} ; /* previously typedef'd to LZ4_stream_t */
|
||||
|
||||
|
||||
/*!
|
||||
* LZ4_streamDecode_t :
|
||||
* information structure to track an LZ4 stream during decompression.
|
||||
* init this structure using LZ4_setStreamDecode (or memset()) before first use
|
||||
* note : only use in association with static linking !
|
||||
* this definition is not API/ABI safe,
|
||||
* and may change in a future version !
|
||||
*/
|
||||
#define LZ4_STREAMDECODESIZE_U64 4
|
||||
#define LZ4_STREAMDECODESIZE (LZ4_STREAMDECODESIZE_U64 * sizeof(unsigned long long))
|
||||
union LZ4_streamDecode_u {
|
||||
unsigned long long table[LZ4_STREAMDECODESIZE_U64];
|
||||
LZ4_streamDecode_t_internal internal_donotuse;
|
||||
} ; /* previously typedef'd to LZ4_streamDecode_t */
|
||||
|
||||
|
||||
/*-************************************
|
||||
* Obsolete Functions
|
||||
**************************************/
|
||||
|
||||
/*! Deprecation warnings
|
||||
Should deprecation warnings be a problem,
|
||||
it is generally possible to disable them,
|
||||
typically with -Wno-deprecated-declarations for gcc
|
||||
or _CRT_SECURE_NO_WARNINGS in Visual.
|
||||
Otherwise, it's also possible to define LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||
#ifdef LZ4_DISABLE_DEPRECATE_WARNINGS
|
||||
# define LZ4_DEPRECATED(message) /* disable deprecation warnings */
|
||||
#else
|
||||
# define LZ4_GCC_VERSION (__GNUC__ * 100 + __GNUC_MINOR__)
|
||||
# if defined (__cplusplus) && (__cplusplus >= 201402) /* C++14 or greater */
|
||||
# define LZ4_DEPRECATED(message) [[deprecated(message)]]
|
||||
# elif (LZ4_GCC_VERSION >= 405) || defined(__clang__)
|
||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated(message)))
|
||||
# elif (LZ4_GCC_VERSION >= 301)
|
||||
# define LZ4_DEPRECATED(message) __attribute__((deprecated))
|
||||
# elif defined(_MSC_VER)
|
||||
# define LZ4_DEPRECATED(message) __declspec(deprecated(message))
|
||||
# else
|
||||
# pragma message("WARNING: You need to implement LZ4_DEPRECATED for this compiler")
|
||||
# define LZ4_DEPRECATED(message)
|
||||
# endif
|
||||
#endif /* LZ4_DISABLE_DEPRECATE_WARNINGS */
|
||||
|
||||
/* Obsolete compression functions */
|
||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress (const char* source, char* dest, int sourceSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_default() instead") LZ4LIB_API int LZ4_compress_limitedOutput (const char* source, char* dest, int sourceSize, int maxOutputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_withState (void* state, const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_extState() instead") LZ4LIB_API int LZ4_compress_limitedOutput_withState (void* state, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize);
|
||||
LZ4_DEPRECATED("use LZ4_compress_fast_continue() instead") LZ4LIB_API int LZ4_compress_limitedOutput_continue (LZ4_stream_t* LZ4_streamPtr, const char* source, char* dest, int inputSize, int maxOutputSize);
|
||||
|
||||
/* Obsolete decompression functions */
|
||||
LZ4_DEPRECATED("use LZ4_decompress_fast() instead") LZ4LIB_API int LZ4_uncompress (const char* source, char* dest, int outputSize);
|
||||
LZ4_DEPRECATED("use LZ4_decompress_safe() instead") LZ4LIB_API int LZ4_uncompress_unknownOutputSize (const char* source, char* dest, int isize, int maxOutputSize);
|
||||
|
||||
/* Obsolete streaming functions; degraded functionality; do not use!
|
||||
*
|
||||
* In order to perform streaming compression, these functions depended on data
|
||||
* that is no longer tracked in the state. They have been preserved as well as
|
||||
* possible: using them will still produce a correct output. However, they don't
|
||||
* actually retain any history between compression calls. The compression ratio
|
||||
* achieved will therefore be no better than compressing each chunk
|
||||
* independently.
|
||||
*/
|
||||
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API void* LZ4_create (char* inputBuffer);
|
||||
LZ4_DEPRECATED("Use LZ4_createStream() instead") LZ4LIB_API int LZ4_sizeofStreamState(void);
|
||||
LZ4_DEPRECATED("Use LZ4_resetStream() instead") LZ4LIB_API int LZ4_resetStreamState(void* state, char* inputBuffer);
|
||||
LZ4_DEPRECATED("Use LZ4_saveDict() instead") LZ4LIB_API char* LZ4_slideInputBuffer (void* state);
|
||||
|
||||
/* Obsolete streaming decoding functions */
|
||||
LZ4_DEPRECATED("use LZ4_decompress_safe_usingDict() instead") LZ4LIB_API int LZ4_decompress_safe_withPrefix64k (const char* src, char* dst, int compressedSize, int maxDstSize);
|
||||
LZ4_DEPRECATED("use LZ4_decompress_fast_usingDict() instead") LZ4LIB_API int LZ4_decompress_fast_withPrefix64k (const char* src, char* dst, int originalSize);
|
||||
|
||||
#endif /* LZ4_H_2983827168210 */
|
||||
|
||||
|
||||
#if defined (__cplusplus)
|
||||
}
|
||||
#endif
|
14
lib/libcompress/source/lz4_wrapper.cpp
Normal file
14
lib/libcompress/source/lz4_wrapper.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
#include <compress/lz4.h>
|
||||
#include "lz4/lz4.h"
|
||||
|
||||
void compress::lz4::compressData(const uint8_t* src, uint32_t src_len, uint8_t* dst, uint32_t dst_capacity, uint32_t& compressed_size)
|
||||
{
|
||||
compressed_size = LZ4_compress_default((const char*)src, (char*)dst, (int)src_len, (int)dst_capacity);
|
||||
}
|
||||
|
||||
void compress::lz4::decompressData(const uint8_t* src, uint32_t src_len, uint8_t* dst, uint32_t dst_capacity, uint32_t& decompressed_size)
|
||||
{
|
||||
decompressed_size = LZ4_decompress_safe((const char*)src, (char*)dst, (int)src_len, (int)dst_capacity);
|
||||
}
|
||||
|
||||
|
|
@ -135,17 +135,17 @@
|
|||
<ClInclude Include="source\libpolarssl\include\polarssl\sha2.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\aes.cpp" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_aes.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_base64.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_bignum.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_md.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_md_wrap.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_rsa.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_sha1.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\polar_sha2.c" />
|
||||
<ClCompile Include="source\rsa.cpp" />
|
||||
<ClCompile Include="source\sha.cpp" />
|
||||
<ClCompile Include="source\aes_wrapper.cpp" />
|
||||
<ClCompile Include="source\libpolarssl\source\aes.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\base64.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\bignum.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\md.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\md_wrap.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\rsa.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\sha1.c" />
|
||||
<ClCompile Include="source\libpolarssl\source\sha2.c" />
|
||||
<ClCompile Include="source\rsa_wrapper.cpp" />
|
||||
<ClCompile Include="source\sha_wrapper.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
|
|
|
@ -65,37 +65,37 @@
|
|||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\aes.cpp">
|
||||
<ClCompile Include="source\aes_wrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\rsa.cpp">
|
||||
<ClCompile Include="source\rsa_wrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\sha.cpp">
|
||||
<ClCompile Include="source\sha_wrapper.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_aes.c">
|
||||
<ClCompile Include="source\libpolarssl\source\aes.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_base64.c">
|
||||
<ClCompile Include="source\libpolarssl\source\base64.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_bignum.c">
|
||||
<ClCompile Include="source\libpolarssl\source\bignum.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_rsa.c">
|
||||
<ClCompile Include="source\libpolarssl\source\md.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_sha2.c">
|
||||
<ClCompile Include="source\libpolarssl\source\md_wrap.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_sha1.c">
|
||||
<ClCompile Include="source\libpolarssl\source\rsa.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_md.c">
|
||||
<ClCompile Include="source\libpolarssl\source\sha1.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\libpolarssl\source\polar_md_wrap.c">
|
||||
<ClCompile Include="source\libpolarssl\source\sha2.c">
|
||||
<Filter>Source Files\polarssl</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
|
|
|
@ -19,7 +19,7 @@ void fnd::SimpleTextOutput::hxdStyleDump(const byte_t* data, size_t len, size_t
|
|||
printf(" ");
|
||||
for (size_t j = 0; j < row_len; j++)
|
||||
{
|
||||
printf("%c", isalnum(data[(i * row_len) + j]) ? data[(i * row_len) + j] : '.');
|
||||
printf("%c", iscntrl(data[(i * row_len) + j]) ? '.' : data[(i * row_len) + j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
@ -43,7 +43,7 @@ void fnd::SimpleTextOutput::hxdStyleDump(const byte_t* data, size_t len, size_t
|
|||
for (size_t j = 0; j < row_len; j++)
|
||||
{
|
||||
if (j < (len % row_len))
|
||||
printf("%c", isalnum(data[(i * row_len) + j]) ? data[(i * row_len) + j] : '.');
|
||||
printf("%c", iscntrl(data[(i * row_len) + j]) ? '.' : data[(i * row_len) + j]);
|
||||
else
|
||||
printf(" ");
|
||||
}
|
||||
|
|
155
lib/libnx/include/nx/NsoHeader.h
Normal file
155
lib/libnx/include/nx/NsoHeader.h
Normal file
|
@ -0,0 +1,155 @@
|
|||
#pragma once
|
||||
#include <nx/nso.h>
|
||||
#include <fnd/MemoryBlob.h>
|
||||
#include <fnd/List.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
class NsoHeader :
|
||||
public fnd::ISerialiseableBinary
|
||||
{
|
||||
public:
|
||||
struct sModuleId
|
||||
{
|
||||
byte_t data[nso::kModuleIdLen];
|
||||
|
||||
void operator=(const sModuleId& other)
|
||||
{
|
||||
memcpy(data, other.data, nso::kModuleIdLen);
|
||||
}
|
||||
|
||||
bool operator==(const sModuleId& other) const
|
||||
{
|
||||
return memcmp(data, other.data, nso::kModuleIdLen) == 0;
|
||||
}
|
||||
|
||||
bool operator!=(const sModuleId& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct sLayout
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t size;
|
||||
|
||||
void operator=(const sLayout& other)
|
||||
{
|
||||
offset = other.offset;
|
||||
size = other.size;
|
||||
}
|
||||
|
||||
bool operator==(const sLayout& other) const
|
||||
{
|
||||
return (offset == other.offset) \
|
||||
&& (size == other.size);
|
||||
}
|
||||
|
||||
bool operator!=(const sLayout& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
struct sCodeSegment
|
||||
{
|
||||
sLayout file_layout;
|
||||
sLayout memory_layout;
|
||||
bool is_compressed;
|
||||
bool is_hashed;
|
||||
crypto::sha::sSha256Hash hash;
|
||||
|
||||
void operator=(const sCodeSegment& other)
|
||||
{
|
||||
file_layout = other.file_layout;
|
||||
memory_layout = other.memory_layout;
|
||||
is_compressed = other.is_compressed;
|
||||
is_hashed = other.is_hashed;
|
||||
hash = other.hash;
|
||||
}
|
||||
|
||||
bool operator==(const sCodeSegment& other) const
|
||||
{
|
||||
return (file_layout == other.file_layout) \
|
||||
&& (memory_layout == other.memory_layout) \
|
||||
&& (is_compressed == other.is_compressed) \
|
||||
&& (is_hashed == other.is_hashed) \
|
||||
&& (hash == other.hash);
|
||||
}
|
||||
|
||||
bool operator!=(const sCodeSegment& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
NsoHeader();
|
||||
NsoHeader(const NsoHeader& other);
|
||||
NsoHeader(const byte_t* bytes, size_t len);
|
||||
|
||||
bool operator==(const NsoHeader& other) const;
|
||||
bool operator!=(const NsoHeader& other) const;
|
||||
void operator=(const NsoHeader& other);
|
||||
|
||||
// to be used after export
|
||||
const byte_t* getBytes() const;
|
||||
size_t getSize() const;
|
||||
|
||||
// export/import binary
|
||||
void exportBinary();
|
||||
void importBinary(const byte_t* bytes, size_t len);
|
||||
|
||||
// variables
|
||||
void clear();
|
||||
|
||||
const sModuleId& getModuleId() const;
|
||||
void setModuleId(const sModuleId& id);
|
||||
|
||||
uint32_t getBssSize() const;
|
||||
void setBssSize(uint32_t size);
|
||||
|
||||
const sCodeSegment& getTextSegmentInfo() const;
|
||||
void setTextSegmentInfo(const sCodeSegment& info);
|
||||
|
||||
const sCodeSegment& getRoSegmentInfo() const;
|
||||
void setRoSegmentInfo(const sCodeSegment& info);
|
||||
|
||||
const sCodeSegment& getDataSegmentInfo() const;
|
||||
void setDataSegmentInfo(const sCodeSegment& info);
|
||||
|
||||
const sLayout& getModuleNameInfo() const;
|
||||
void setModuleNameInfo(const sLayout& info);
|
||||
|
||||
const sLayout& getRoEmbeddedInfo() const;
|
||||
void setRoEmbeddedInfo(const sLayout& info);
|
||||
|
||||
const sLayout& getRoDynStrInfo() const;
|
||||
void setRoDynStrInfo(const sLayout& info);
|
||||
|
||||
const sLayout& getRoDynSymInfo() const;
|
||||
void setRoDynSymInfo(const sLayout& info);
|
||||
private:
|
||||
const std::string kModuleName = "NSO_HEADER";
|
||||
|
||||
// binary
|
||||
fnd::MemoryBlob mBinaryBlob;
|
||||
|
||||
// data
|
||||
sModuleId mModuleId;
|
||||
uint32_t mBssSize;
|
||||
sCodeSegment mTextSegmentInfo;
|
||||
sCodeSegment mRoSegmentInfo;
|
||||
sCodeSegment mDataSegmentInfo;
|
||||
sLayout mModuleNameInfo;
|
||||
sLayout mRoEmbeddedInfo;
|
||||
sLayout mRoDynStrInfo;
|
||||
sLayout mRoDynSymInfo;
|
||||
|
||||
// helpers
|
||||
bool isEqual(const NsoHeader& other) const;
|
||||
void copyFrom(const NsoHeader& other);
|
||||
};
|
||||
|
||||
}
|
56
lib/libnx/include/nx/dynamic_symbol.h
Normal file
56
lib/libnx/include/nx/dynamic_symbol.h
Normal file
|
@ -0,0 +1,56 @@
|
|||
#pragma once
|
||||
#include <fnd/types.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
namespace dynsym
|
||||
{
|
||||
enum SpecialSectionIndex
|
||||
{
|
||||
SHN_UNDEF,
|
||||
SHN_LORESERVE = 65280,
|
||||
SHN_LOPROC = 65280,
|
||||
SHN_HIPROC = 65311,
|
||||
SHN_LOOS,
|
||||
SHN_HIOS = 65343,
|
||||
SHN_ABS = 65521,
|
||||
SHN_COMMON,
|
||||
SHN_HIRESERVE = 0xFFFF
|
||||
};
|
||||
|
||||
enum SymbolType
|
||||
{
|
||||
STT_NOTYPE,
|
||||
STT_OBJECT,
|
||||
STT_FUNC,
|
||||
STT_SECTION,
|
||||
STT_FILE,
|
||||
STT_LOOS = 10,
|
||||
STT_HIOS = 12,
|
||||
STT_LOPROC,
|
||||
STT_HIPROC = 0xF
|
||||
};
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct sDynSymbol32Bit
|
||||
{
|
||||
le_uint32_t name;
|
||||
le_uint32_t value;
|
||||
le_uint32_t size;
|
||||
le_uint32_t info;
|
||||
le_uint32_t other;
|
||||
le_uint32_t special_section_index;
|
||||
};
|
||||
|
||||
struct sDynSymbol64Bit
|
||||
{
|
||||
le_uint32_t name;
|
||||
byte_t info;
|
||||
byte_t other;
|
||||
le_uint16_t special_section_index;
|
||||
le_uint64_t value;
|
||||
le_uint64_t size;
|
||||
};
|
||||
#pragma pack(pop)
|
||||
}
|
68
lib/libnx/include/nx/nso.h
Normal file
68
lib/libnx/include/nx/nso.h
Normal file
|
@ -0,0 +1,68 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <fnd/List.h>
|
||||
#include <crypto/sha.h>
|
||||
#include <fnd/ISerialiseableBinary.h>
|
||||
|
||||
namespace nx
|
||||
{
|
||||
namespace nso
|
||||
{
|
||||
const std::string kNsoSig = "NSO0";
|
||||
|
||||
enum HeaderFlags
|
||||
{
|
||||
FLAG_TEXT_COMPRESS,
|
||||
FLAG_RO_COMPRESS,
|
||||
FLAG_DATA_COMPRESS,
|
||||
FLAG_TEXT_HASH,
|
||||
FLAG_RO_HASH,
|
||||
FLAG_DATA_HASH
|
||||
};
|
||||
|
||||
static const uint32_t kDefaultFormatVersion = 0;
|
||||
static const size_t kModuleIdLen = 32;
|
||||
}
|
||||
|
||||
#pragma pack(push,1)
|
||||
struct sNsoCodeSegment
|
||||
{
|
||||
le_uint32_t file_offset;
|
||||
le_uint32_t memory_offset;
|
||||
le_uint32_t size;
|
||||
};
|
||||
|
||||
struct sNsoSection
|
||||
{
|
||||
le_uint32_t offset;
|
||||
le_uint32_t size;
|
||||
};
|
||||
|
||||
struct sNsoHeader
|
||||
{
|
||||
char signature[4];
|
||||
le_uint32_t format_version;
|
||||
byte_t reserved_1[4];
|
||||
le_uint32_t flags;
|
||||
sNsoCodeSegment text;
|
||||
le_uint32_t module_name_offset;
|
||||
sNsoCodeSegment ro;
|
||||
le_uint32_t module_name_size;
|
||||
sNsoCodeSegment data;
|
||||
le_uint32_t bss_size;
|
||||
byte_t module_id[nso::kModuleIdLen];
|
||||
le_uint32_t text_file_size;
|
||||
le_uint32_t ro_file_size;
|
||||
le_uint32_t data_file_size;
|
||||
byte_t reserved_2[28];
|
||||
sNsoSection embedded;
|
||||
sNsoSection dyn_str;
|
||||
sNsoSection dyn_sym;
|
||||
crypto::sha::sSha256Hash text_hash;
|
||||
crypto::sha::sSha256Hash ro_hash;
|
||||
crypto::sha::sSha256Hash data_hash;
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
}
|
|
@ -26,6 +26,7 @@
|
|||
<ClInclude Include="include\nx\AesKeygen.h" />
|
||||
<ClInclude Include="include\nx\cnmt.h" />
|
||||
<ClInclude Include="include\nx\ContentMetaBinary.h" />
|
||||
<ClInclude Include="include\nx\dynamic_symbol.h" />
|
||||
<ClInclude Include="include\nx\FacBinary.h" />
|
||||
<ClInclude Include="include\nx\FacHeader.h" />
|
||||
<ClInclude Include="include\nx\HandleTableSizeEntry.h" />
|
||||
|
@ -53,6 +54,8 @@
|
|||
<ClInclude Include="include\nx\NpdmBinary.h" />
|
||||
<ClInclude Include="include\nx\NpdmHeader.h" />
|
||||
<ClInclude Include="include\nx\NcaHeader.h" />
|
||||
<ClInclude Include="include\nx\nso.h" />
|
||||
<ClInclude Include="include\nx\NsoHeader.h" />
|
||||
<ClInclude Include="include\nx\NXCrypto.h" />
|
||||
<ClInclude Include="include\nx\pfs.h" />
|
||||
<ClInclude Include="include\nx\PfsHeader.h" />
|
||||
|
@ -67,6 +70,9 @@
|
|||
<ClInclude Include="include\nx\XciHeader.h" />
|
||||
<ClInclude Include="include\nx\XciUtils.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\AciBinary.cpp" />
|
||||
<ClCompile Include="source\AcidBinary.cpp" />
|
||||
|
@ -91,10 +97,11 @@
|
|||
<ClCompile Include="source\MiscFlagsHandler.cpp" />
|
||||
<ClCompile Include="source\MiscParamsEntry.cpp" />
|
||||
<ClCompile Include="source\MiscParamsHandler.cpp" />
|
||||
<ClCompile Include="source\NcaHeader.cpp" />
|
||||
<ClCompile Include="source\NcaUtils.cpp" />
|
||||
<ClCompile Include="source\NpdmBinary.cpp" />
|
||||
<ClCompile Include="source\NpdmHeader.cpp" />
|
||||
<ClCompile Include="source\NcaHeader.cpp" />
|
||||
<ClCompile Include="source\NsoHeader.cpp" />
|
||||
<ClCompile Include="source\PfsHeader.cpp" />
|
||||
<ClCompile Include="source\SacBinary.cpp" />
|
||||
<ClCompile Include="source\SacEntry.cpp" />
|
||||
|
@ -105,9 +112,6 @@
|
|||
<ClCompile Include="source\XciHeader.cpp" />
|
||||
<ClCompile Include="source\XciUtils.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<VCProjectVersion>15.0</VCProjectVersion>
|
||||
<ProjectGuid>{91BA9E79-8242-4F7D-B997-0DFEC95EA22B}</ProjectGuid>
|
||||
|
|
|
@ -156,6 +156,18 @@
|
|||
<ClInclude Include="include\nx\HierarchicalIntegrityHeader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\nso.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\NsoHeader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\nx\dynamic_symbol.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\AciBinary.cpp">
|
||||
|
@ -167,6 +179,12 @@
|
|||
<ClCompile Include="source\AciHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\AesKeygen.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\ContentMetaBinary.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\FacBinary.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -179,6 +197,12 @@
|
|||
<ClCompile Include="source\HandleTableSizeHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\HierarchicalIntegrityHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\HierarchicalSha256Header.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\InteruptEntry.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -215,13 +239,19 @@
|
|||
<ClCompile Include="source\MiscParamsHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NcaHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NcaUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NpdmBinary.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NpdmHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NcaHeader.cpp">
|
||||
<ClCompile Include="source\NsoHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\PfsHeader.cpp">
|
||||
|
@ -245,29 +275,11 @@
|
|||
<ClCompile Include="source\ThreadInfoHandler.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\AesKeygen.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NcaUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\XciHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\XciUtils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\ContentMetaBinary.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\HierarchicalIntegrityHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\HierarchicalSha256Header.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
</ItemGroup>
|
||||
</Project>
|
323
lib/libnx/source/NsoHeader.cpp
Normal file
323
lib/libnx/source/NsoHeader.cpp
Normal file
|
@ -0,0 +1,323 @@
|
|||
#include <nx/NsoHeader.h>
|
||||
|
||||
nx::NsoHeader::NsoHeader()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
nx::NsoHeader::NsoHeader(const NsoHeader& other)
|
||||
{
|
||||
copyFrom(other);
|
||||
}
|
||||
|
||||
nx::NsoHeader::NsoHeader(const byte_t* bytes, size_t len)
|
||||
{
|
||||
importBinary(bytes, len);
|
||||
}
|
||||
|
||||
bool nx::NsoHeader::operator==(const NsoHeader& other) const
|
||||
{
|
||||
return isEqual(other);
|
||||
}
|
||||
|
||||
bool nx::NsoHeader::operator!=(const NsoHeader& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
|
||||
void nx::NsoHeader::operator=(const NsoHeader& other)
|
||||
{
|
||||
copyFrom(other);
|
||||
}
|
||||
|
||||
const byte_t* nx::NsoHeader::getBytes() const
|
||||
{
|
||||
return mBinaryBlob.getBytes();
|
||||
}
|
||||
|
||||
size_t nx::NsoHeader::getSize() const
|
||||
{
|
||||
return mBinaryBlob.getSize();
|
||||
}
|
||||
|
||||
void nx::NsoHeader::exportBinary()
|
||||
{
|
||||
mBinaryBlob.alloc(sizeof(sNsoHeader));
|
||||
nx::sNsoHeader* hdr = (nx::sNsoHeader*)mBinaryBlob.getBytes();
|
||||
|
||||
// set header identifers
|
||||
memcpy(hdr->signature, nso::kNsoSig.c_str(), 4);
|
||||
hdr->format_version = nso::kDefaultFormatVersion;
|
||||
|
||||
// variable to store flags before commiting to header
|
||||
uint32_t flags = 0;
|
||||
|
||||
// set moduleid
|
||||
memcpy(hdr->module_id, mModuleId.data, nso::kModuleIdLen);
|
||||
|
||||
// set bss size
|
||||
hdr->bss_size = mBssSize;
|
||||
|
||||
// set text segment
|
||||
hdr->text.file_offset = mTextSegmentInfo.file_layout.offset;
|
||||
hdr->text.memory_offset = mTextSegmentInfo.memory_layout.offset;
|
||||
hdr->text.size = mTextSegmentInfo.memory_layout.size;
|
||||
hdr->text_file_size = mTextSegmentInfo.file_layout.size;
|
||||
if (mTextSegmentInfo.is_compressed)
|
||||
{
|
||||
flags |= _BIT(nso::FLAG_TEXT_COMPRESS);
|
||||
}
|
||||
if (mTextSegmentInfo.is_hashed)
|
||||
{
|
||||
flags |= _BIT(nso::FLAG_TEXT_HASH);
|
||||
hdr->text_hash = mTextSegmentInfo.hash;
|
||||
}
|
||||
|
||||
// set ro segment
|
||||
hdr->ro.file_offset = mRoSegmentInfo.file_layout.offset;
|
||||
hdr->ro.memory_offset = mRoSegmentInfo.memory_layout.offset;
|
||||
hdr->ro.size = mRoSegmentInfo.memory_layout.size;
|
||||
hdr->ro_file_size = mRoSegmentInfo.file_layout.size;
|
||||
if (mRoSegmentInfo.is_compressed)
|
||||
{
|
||||
flags |= _BIT(nso::FLAG_RO_COMPRESS);
|
||||
}
|
||||
if (mRoSegmentInfo.is_hashed)
|
||||
{
|
||||
flags |= _BIT(nso::FLAG_RO_HASH);
|
||||
hdr->ro_hash = mRoSegmentInfo.hash;
|
||||
}
|
||||
|
||||
// set data segment
|
||||
hdr->data.file_offset = mDataSegmentInfo.file_layout.offset;
|
||||
hdr->data.memory_offset = mDataSegmentInfo.memory_layout.offset;
|
||||
hdr->data.size = mDataSegmentInfo.memory_layout.size;
|
||||
hdr->data_file_size = mDataSegmentInfo.file_layout.size;
|
||||
if (mDataSegmentInfo.is_compressed)
|
||||
{
|
||||
flags |= _BIT(nso::FLAG_DATA_COMPRESS);
|
||||
}
|
||||
if (mDataSegmentInfo.is_hashed)
|
||||
{
|
||||
flags |= _BIT(nso::FLAG_DATA_HASH);
|
||||
hdr->data_hash = mDataSegmentInfo.hash;
|
||||
}
|
||||
|
||||
// set module name info
|
||||
hdr->module_name_offset = mModuleNameInfo.offset;
|
||||
hdr->module_name_size = mModuleNameInfo.size;
|
||||
|
||||
// set ro embedded info
|
||||
hdr->embedded.offset = mRoEmbeddedInfo.offset;
|
||||
hdr->embedded.size = mRoEmbeddedInfo.size;
|
||||
|
||||
// set ro dyn str info
|
||||
hdr->dyn_str.offset = mRoDynStrInfo.offset;
|
||||
hdr->dyn_str.size = mRoDynStrInfo.size;
|
||||
|
||||
// set ro dyn sym info
|
||||
hdr->dyn_sym.offset = mRoDynSymInfo.offset;
|
||||
hdr->dyn_sym.size = mRoDynSymInfo.size;
|
||||
|
||||
hdr->flags = flags;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::importBinary(const byte_t* bytes, size_t len)
|
||||
{
|
||||
// check input data size
|
||||
if (len < sizeof(sNsoHeader))
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO header size is too small");
|
||||
}
|
||||
|
||||
// clear internal members
|
||||
clear();
|
||||
|
||||
// allocate internal local binary copy
|
||||
mBinaryBlob.alloc(sizeof(sNsoHeader));
|
||||
memcpy(mBinaryBlob.getBytes(), bytes, mBinaryBlob.getSize());
|
||||
|
||||
// get sNsoHeader ptr
|
||||
const nx::sNsoHeader* hdr = (const nx::sNsoHeader*)mBinaryBlob.getBytes();
|
||||
|
||||
// check NSO signature
|
||||
if (std::string(hdr->signature, 4) != nso::kNsoSig)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO header corrupt (unrecognised header signature)");
|
||||
}
|
||||
|
||||
// check NSO format version
|
||||
if (hdr->format_version.get() != nso::kDefaultFormatVersion)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO header corrupt (unsupported format version)");
|
||||
}
|
||||
|
||||
memcpy(mModuleId.data, hdr->module_id, nso::kModuleIdLen);
|
||||
|
||||
mBssSize = hdr->bss_size.get();
|
||||
|
||||
mTextSegmentInfo.file_layout.offset = hdr->text.file_offset.get();
|
||||
mTextSegmentInfo.file_layout.size = hdr->text_file_size.get();
|
||||
mTextSegmentInfo.memory_layout.offset = hdr->text.memory_offset.get();
|
||||
mTextSegmentInfo.memory_layout.size = hdr->text.size.get();
|
||||
mTextSegmentInfo.is_compressed = _HAS_BIT(hdr->flags.get(), nso::FLAG_TEXT_COMPRESS);
|
||||
mTextSegmentInfo.is_hashed = _HAS_BIT(hdr->flags.get(), nso::FLAG_TEXT_HASH);
|
||||
mTextSegmentInfo.hash = hdr->text_hash;
|
||||
|
||||
mRoSegmentInfo.file_layout.offset = hdr->ro.file_offset.get();
|
||||
mRoSegmentInfo.file_layout.size = hdr->ro_file_size.get();
|
||||
mRoSegmentInfo.memory_layout.offset = hdr->ro.memory_offset.get();
|
||||
mRoSegmentInfo.memory_layout.size = hdr->ro.size.get();
|
||||
mRoSegmentInfo.is_compressed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_COMPRESS);
|
||||
mRoSegmentInfo.is_hashed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_HASH);
|
||||
mRoSegmentInfo.hash = hdr->ro_hash;
|
||||
|
||||
mDataSegmentInfo.file_layout.offset = hdr->data.file_offset.get();
|
||||
mDataSegmentInfo.file_layout.size = hdr->data_file_size.get();
|
||||
mDataSegmentInfo.memory_layout.offset = hdr->data.memory_offset.get();
|
||||
mDataSegmentInfo.memory_layout.size = hdr->data.size.get();
|
||||
mDataSegmentInfo.is_compressed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_COMPRESS);
|
||||
mDataSegmentInfo.is_hashed = _HAS_BIT(hdr->flags.get(), nso::FLAG_RO_HASH);
|
||||
mDataSegmentInfo.hash = hdr->data_hash;
|
||||
|
||||
mModuleNameInfo.offset = hdr->module_name_offset.get();
|
||||
mModuleNameInfo.size = hdr->module_name_size.get();
|
||||
|
||||
mRoEmbeddedInfo.offset = hdr->embedded.offset.get();
|
||||
mRoEmbeddedInfo.size = hdr->embedded.size.get();
|
||||
|
||||
mRoDynStrInfo.offset = hdr->dyn_str.offset.get();
|
||||
mRoDynStrInfo.size = hdr->dyn_str.size.get();
|
||||
|
||||
mRoDynSymInfo.offset = hdr->dyn_sym.offset.get();
|
||||
mRoDynSymInfo.size = hdr->dyn_sym.size.get();
|
||||
}
|
||||
|
||||
void nx::NsoHeader::clear()
|
||||
{
|
||||
mBinaryBlob.clear();
|
||||
memset(&mModuleId, 0, sizeof(mModuleId));
|
||||
mBssSize = 0;
|
||||
memset(&mTextSegmentInfo, 0, sizeof(mTextSegmentInfo));
|
||||
memset(&mRoSegmentInfo, 0, sizeof(mRoSegmentInfo));
|
||||
memset(&mDataSegmentInfo, 0, sizeof(mDataSegmentInfo));
|
||||
memset(&mModuleNameInfo, 0, sizeof(mModuleNameInfo));
|
||||
memset(&mRoEmbeddedInfo, 0, sizeof(mRoEmbeddedInfo));
|
||||
memset(&mRoDynStrInfo, 0, sizeof(mRoDynStrInfo));
|
||||
memset(&mRoDynSymInfo, 0, sizeof(mRoDynSymInfo));
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sModuleId& nx::NsoHeader::getModuleId() const
|
||||
{
|
||||
return mModuleId;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setModuleId(const sModuleId& id)
|
||||
{
|
||||
mModuleId = id;
|
||||
}
|
||||
|
||||
uint32_t nx::NsoHeader::getBssSize() const
|
||||
{
|
||||
return mBssSize;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setBssSize(uint32_t size)
|
||||
{
|
||||
mBssSize = size;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sCodeSegment& nx::NsoHeader::getTextSegmentInfo() const
|
||||
{
|
||||
return mTextSegmentInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setTextSegmentInfo(const sCodeSegment& info)
|
||||
{
|
||||
mTextSegmentInfo = info;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sCodeSegment& nx::NsoHeader::getRoSegmentInfo() const
|
||||
{
|
||||
return mRoSegmentInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setRoSegmentInfo(const sCodeSegment& info)
|
||||
{
|
||||
mRoSegmentInfo = info;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sCodeSegment& nx::NsoHeader::getDataSegmentInfo() const
|
||||
{
|
||||
return mDataSegmentInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setDataSegmentInfo(const sCodeSegment& info)
|
||||
{
|
||||
mDataSegmentInfo = info;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sLayout& nx::NsoHeader::getModuleNameInfo() const
|
||||
{
|
||||
return mModuleNameInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setModuleNameInfo(const sLayout& info)
|
||||
{
|
||||
mModuleNameInfo = info;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sLayout& nx::NsoHeader::getRoEmbeddedInfo() const
|
||||
{
|
||||
return mRoEmbeddedInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setRoEmbeddedInfo(const sLayout& info)
|
||||
{
|
||||
mRoEmbeddedInfo = info;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sLayout& nx::NsoHeader::getRoDynStrInfo() const
|
||||
{
|
||||
return mRoDynStrInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setRoDynStrInfo(const sLayout& info)
|
||||
{
|
||||
mRoDynStrInfo = info;
|
||||
}
|
||||
|
||||
const nx::NsoHeader::sLayout& nx::NsoHeader::getRoDynSymInfo() const
|
||||
{
|
||||
return mRoDynSymInfo;
|
||||
}
|
||||
|
||||
void nx::NsoHeader::setRoDynSymInfo(const sLayout& info)
|
||||
{
|
||||
mRoDynSymInfo = info;
|
||||
}
|
||||
|
||||
bool nx::NsoHeader::isEqual(const NsoHeader& other) const
|
||||
{
|
||||
return (mModuleId == other.mModuleId) \
|
||||
&& (mBssSize == other.mBssSize) \
|
||||
&& (mTextSegmentInfo == other.mTextSegmentInfo) \
|
||||
&& (mRoSegmentInfo == other.mRoSegmentInfo) \
|
||||
&& (mDataSegmentInfo == other.mDataSegmentInfo) \
|
||||
&& (mModuleNameInfo == other.mModuleNameInfo) \
|
||||
&& (mRoEmbeddedInfo == other.mRoEmbeddedInfo) \
|
||||
&& (mRoDynStrInfo == other.mRoDynStrInfo) \
|
||||
&& (mRoDynSymInfo == other.mRoDynSymInfo);
|
||||
}
|
||||
void nx::NsoHeader::copyFrom(const NsoHeader& other)
|
||||
{
|
||||
mModuleId = other.mModuleId;
|
||||
mBssSize = other.mBssSize;
|
||||
mTextSegmentInfo = other.mTextSegmentInfo;
|
||||
mRoSegmentInfo = other.mRoSegmentInfo;
|
||||
mDataSegmentInfo = other.mDataSegmentInfo;
|
||||
mModuleNameInfo = other.mModuleNameInfo;
|
||||
mRoEmbeddedInfo = other.mRoEmbeddedInfo;
|
||||
mRoDynStrInfo = other.mRoDynStrInfo;
|
||||
mRoDynSymInfo = other.mRoDynSymInfo;
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
LIBS = libfnd libcrypto libes libnx
|
||||
LIBS = libfnd libcrypto libcompress libes libnx
|
||||
main: build
|
||||
|
||||
rebuild: clean build
|
||||
|
|
|
@ -90,7 +90,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcompress\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -105,7 +105,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcompress\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -122,7 +122,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcompress\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -141,7 +141,7 @@
|
|||
<SDLCheck>true</SDLCheck>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include;</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\..\lib\libfnd\include;..\..\lib\libcompress\include;..\..\lib\libcrypto\include;..\..\lib\libnx\include</AdditionalIncludeDirectories>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
|
@ -151,6 +151,9 @@
|
|||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\lib\libcompress\libcompress.vcxproj">
|
||||
<Project>{cf01b5b7-730a-447f-9bb2-5eda9b082177}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\..\lib\libcrypto\crypto.vcxproj">
|
||||
<Project>{6adbb60d-dba0-411d-bd2d-a355ef8e0fe1}</Project>
|
||||
</ProjectReference>
|
||||
|
@ -165,10 +168,12 @@
|
|||
<ClInclude Include="source\AesCtrWrappedIFile.h" />
|
||||
<ClInclude Include="source\CnmtProcess.h" />
|
||||
<ClInclude Include="source\CopiedIFile.h" />
|
||||
<ClInclude Include="source\DynamicSymbolParser.h" />
|
||||
<ClInclude Include="source\HashTreeMeta.h" />
|
||||
<ClInclude Include="source\HashTreeWrappedIFile.h" />
|
||||
<ClInclude Include="source\NcaProcess.h" />
|
||||
<ClInclude Include="source\NpdmProcess.h" />
|
||||
<ClInclude Include="source\NsoProcess.h" />
|
||||
<ClInclude Include="source\nstool.h" />
|
||||
<ClInclude Include="source\OffsetAdjustedIFile.h" />
|
||||
<ClInclude Include="source\PfsProcess.h" />
|
||||
|
@ -180,11 +185,13 @@
|
|||
<ItemGroup>
|
||||
<ClCompile Include="source\AesCtrWrappedIFile.cpp" />
|
||||
<ClCompile Include="source\CnmtProcess.cpp" />
|
||||
<ClCompile Include="source\DynamicSymbolParser.cpp" />
|
||||
<ClCompile Include="source\HashTreeMeta.cpp" />
|
||||
<ClCompile Include="source\HashTreeWrappedIFile.cpp" />
|
||||
<ClCompile Include="source\main.cpp" />
|
||||
<ClCompile Include="source\NcaProcess.cpp" />
|
||||
<ClCompile Include="source\NpdmProcess.cpp" />
|
||||
<ClCompile Include="source\NsoProcess.cpp" />
|
||||
<ClCompile Include="source\OffsetAdjustedIFile.cpp" />
|
||||
<ClCompile Include="source\PfsProcess.cpp" />
|
||||
<ClCompile Include="source\RomfsProcess.cpp" />
|
||||
|
|
|
@ -57,6 +57,12 @@
|
|||
<ClInclude Include="source\HashTreeWrappedIFile.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\NsoProcess.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="source\DynamicSymbolParser.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="source\main.cpp">
|
||||
|
@ -95,6 +101,12 @@
|
|||
<ClCompile Include="source\HashTreeWrappedIFile.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\NsoProcess.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="source\DynamicSymbolParser.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="makefile" />
|
||||
|
|
|
@ -1,4 +1,23 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LocalDebuggerCommandArguments>--titlekey F28921A36270C34B5476A384A212FC18 --part1 winromfsext test\nsp\nsout\32a23f30763ca916909399fc03c57bd2.nca</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>..\..</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LocalDebuggerCommandArguments>--titlekey F28921A36270C34B5476A384A212FC18 --part1 winromfsext test\nsp\nsout\32a23f30763ca916909399fc03c57bd2.nca</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>..\..</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LocalDebuggerCommandArguments>--titlekey F28921A36270C34B5476A384A212FC18 --part1 winromfsext test\nsp\nsout\32a23f30763ca916909399fc03c57bd2.nca</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>..\..</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LocalDebuggerCommandArguments>--titlekey F28921A36270C34B5476A384A212FC18 --part1 winromfsext test\nsp\nsout\32a23f30763ca916909399fc03c57bd2.nca</LocalDebuggerCommandArguments>
|
||||
<DebuggerFlavor>WindowsLocalDebugger</DebuggerFlavor>
|
||||
<LocalDebuggerWorkingDirectory>..\..</LocalDebuggerWorkingDirectory>
|
||||
</PropertyGroup>
|
||||
</Project>
|
70
programs/nstool/source/DynamicSymbolParser.cpp
Normal file
70
programs/nstool/source/DynamicSymbolParser.cpp
Normal file
|
@ -0,0 +1,70 @@
|
|||
#include "DynamicSymbolParser.h"
|
||||
|
||||
DynamicSymbolParser::DynamicSymbolParser()
|
||||
{
|
||||
mDynSymbolList.clear();
|
||||
}
|
||||
|
||||
bool DynamicSymbolParser::operator==(const DynamicSymbolParser& other) const
|
||||
{
|
||||
return isEqual(other);
|
||||
}
|
||||
|
||||
bool DynamicSymbolParser::operator!=(const DynamicSymbolParser& other) const
|
||||
{
|
||||
return !isEqual(other);
|
||||
}
|
||||
|
||||
void DynamicSymbolParser::operator=(const DynamicSymbolParser& other)
|
||||
{
|
||||
copyFrom(other);
|
||||
}
|
||||
|
||||
void DynamicSymbolParser::parseData(const byte_t *dyn_sym, size_t dyn_sym_size, const byte_t *dyn_str, size_t dyn_str_size, bool is64Bit)
|
||||
{
|
||||
//printf("DynamicSymbolParser::parseData()");
|
||||
size_t dynSymSize = is64Bit ? sizeof(nx::sDynSymbol64Bit) : sizeof(nx::sDynSymbol32Bit);
|
||||
|
||||
sDynSymbol symbol;
|
||||
for (size_t i = 0; i < dyn_sym_size; i += dynSymSize)
|
||||
{
|
||||
//printf("pos %x\n", i);
|
||||
|
||||
uint32_t name_pos;
|
||||
|
||||
if (is64Bit)
|
||||
{
|
||||
name_pos = ((nx::sDynSymbol64Bit*)(dyn_sym + i))->name.get();
|
||||
symbol.shn_index = (nx::dynsym::SpecialSectionIndex)((nx::sDynSymbol64Bit*)(dyn_sym + i))->special_section_index.get();
|
||||
symbol.symbol_type = (nx::dynsym::SymbolType)((((nx::sDynSymbol64Bit*)(dyn_sym + i))->info) & nx::dynsym::STT_HIPROC);
|
||||
}
|
||||
else
|
||||
{
|
||||
name_pos = ((nx::sDynSymbol64Bit*)(dyn_sym + i))->name.get();
|
||||
symbol.shn_index = (nx::dynsym::SpecialSectionIndex)((nx::sDynSymbol32Bit*)(dyn_sym + i))->special_section_index.get();
|
||||
symbol.symbol_type = (nx::dynsym::SymbolType)((((nx::sDynSymbol32Bit*)(dyn_sym + i))->info.get()) & nx::dynsym::STT_HIPROC);
|
||||
}
|
||||
|
||||
for (; dyn_str[name_pos] == 0x00 && name_pos < dyn_str_size; name_pos++);
|
||||
|
||||
//printf("name_pos = 0x%x\n", name_pos);
|
||||
symbol.name = std::string((char*)&dyn_str[name_pos]);
|
||||
mDynSymbolList.addElement(symbol);
|
||||
}
|
||||
//printf("DynamicSymbolParser::parseData() end\n");
|
||||
}
|
||||
|
||||
const fnd::List<DynamicSymbolParser::sDynSymbol>& DynamicSymbolParser::getDynamicSymbolList() const
|
||||
{
|
||||
return mDynSymbolList;
|
||||
}
|
||||
|
||||
bool DynamicSymbolParser::isEqual(const DynamicSymbolParser& other) const
|
||||
{
|
||||
return mDynSymbolList == other.mDynSymbolList;
|
||||
}
|
||||
|
||||
void DynamicSymbolParser::copyFrom(const DynamicSymbolParser& other)
|
||||
{
|
||||
mDynSymbolList = other.mDynSymbolList;
|
||||
}
|
49
programs/nstool/source/DynamicSymbolParser.h
Normal file
49
programs/nstool/source/DynamicSymbolParser.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/List.h>
|
||||
#include <nx/dynamic_symbol.h>
|
||||
|
||||
class DynamicSymbolParser
|
||||
{
|
||||
public:
|
||||
struct sDynSymbol
|
||||
{
|
||||
nx::dynsym::SpecialSectionIndex shn_index;
|
||||
nx::dynsym::SymbolType symbol_type;
|
||||
std::string name;
|
||||
|
||||
void operator=(const sDynSymbol& other)
|
||||
{
|
||||
shn_index = other.shn_index;
|
||||
symbol_type = other.symbol_type;
|
||||
name = other.name;
|
||||
}
|
||||
|
||||
bool operator==(const sDynSymbol& other) const
|
||||
{
|
||||
return (shn_index == other.shn_index && symbol_type == other.symbol_type && name == other.name);
|
||||
}
|
||||
|
||||
bool operator!=(const sDynSymbol& other) const
|
||||
{
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
|
||||
DynamicSymbolParser();
|
||||
|
||||
bool operator==(const DynamicSymbolParser& other) const;
|
||||
bool operator!=(const DynamicSymbolParser& other) const;
|
||||
void operator=(const DynamicSymbolParser& other);
|
||||
|
||||
void parseData(const byte_t *dyn_sym, size_t dyn_sym_size, const byte_t *dyn_str, size_t dyn_str_size, bool is64Bit);
|
||||
|
||||
const fnd::List<sDynSymbol>& getDynamicSymbolList() const;
|
||||
private:
|
||||
|
||||
// data
|
||||
fnd::List<sDynSymbol> mDynSymbolList;
|
||||
|
||||
bool isEqual(const DynamicSymbolParser& other) const;
|
||||
void copyFrom(const DynamicSymbolParser& other);
|
||||
};
|
302
programs/nstool/source/NsoProcess.cpp
Normal file
302
programs/nstool/source/NsoProcess.cpp
Normal file
|
@ -0,0 +1,302 @@
|
|||
#include <sstream>
|
||||
#include <fnd/SimpleTextOutput.h>
|
||||
#include <fnd/MemoryBlob.h>
|
||||
#include <compress/lz4.h>
|
||||
#include "OffsetAdjustedIFile.h"
|
||||
#include "NsoProcess.h"
|
||||
|
||||
NsoProcess::NsoProcess():
|
||||
mReader(nullptr),
|
||||
mCliOutputType(OUTPUT_NORMAL),
|
||||
mVerify(false)
|
||||
{
|
||||
mArchType.isSet = false;
|
||||
}
|
||||
|
||||
NsoProcess::~NsoProcess()
|
||||
{
|
||||
if (mReader != nullptr)
|
||||
{
|
||||
delete mReader;
|
||||
}
|
||||
}
|
||||
|
||||
void NsoProcess::process()
|
||||
{
|
||||
if (mReader == nullptr)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "No file reader set.");
|
||||
}
|
||||
|
||||
importHeader();
|
||||
importCodeSegments();
|
||||
importApiList();
|
||||
|
||||
if (mCliOutputType >= OUTPUT_NORMAL)
|
||||
{
|
||||
displayHeader();
|
||||
displayRoApiList();
|
||||
}
|
||||
}
|
||||
|
||||
void NsoProcess::setInputFile(fnd::IFile* file, size_t offset, size_t size)
|
||||
{
|
||||
mReader = new OffsetAdjustedIFile(file, offset, size);
|
||||
}
|
||||
|
||||
void NsoProcess::setCliOutputMode(CliOutputType type)
|
||||
{
|
||||
mCliOutputType = type;
|
||||
}
|
||||
|
||||
void NsoProcess::setVerifyMode(bool verify)
|
||||
{
|
||||
mVerify = verify;
|
||||
}
|
||||
|
||||
void NsoProcess::setArchType(nx::npdm::InstructionType type)
|
||||
{
|
||||
mArchType = type;
|
||||
}
|
||||
|
||||
const nx::NsoHeader& NsoProcess::getNsoHeader() const
|
||||
{
|
||||
return mHdr;
|
||||
}
|
||||
|
||||
const fnd::MemoryBlob& NsoProcess::getTextBlob() const
|
||||
{
|
||||
return mTextBlob;
|
||||
}
|
||||
|
||||
const fnd::MemoryBlob& NsoProcess::getRoBlob() const
|
||||
{
|
||||
return mRoBlob;
|
||||
}
|
||||
|
||||
const fnd::MemoryBlob& NsoProcess::getDataBlob() const
|
||||
{
|
||||
return mDataBlob;
|
||||
}
|
||||
|
||||
const std::vector<std::string>& NsoProcess::getApiList() const
|
||||
{
|
||||
return mApiList;
|
||||
}
|
||||
|
||||
|
||||
void NsoProcess::importHeader()
|
||||
{
|
||||
fnd::MemoryBlob scratch;
|
||||
if (mReader->size() < sizeof(nx::sNsoHeader))
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "Corrupt NSO file too small");
|
||||
}
|
||||
|
||||
scratch.alloc(sizeof(nx::sNsoHeader));
|
||||
mReader->read(scratch.getBytes(), 0, scratch.getSize());
|
||||
|
||||
mHdr.importBinary(scratch.getBytes(), scratch.getSize());
|
||||
}
|
||||
|
||||
void NsoProcess::importCodeSegments()
|
||||
{
|
||||
fnd::MemoryBlob scratch;
|
||||
uint32_t decompressed_len;
|
||||
crypto::sha::sSha256Hash calc_hash;
|
||||
|
||||
// process text segment
|
||||
if (mHdr.getTextSegmentInfo().is_compressed)
|
||||
{
|
||||
scratch.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
||||
mReader->read(scratch.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, scratch.getSize());
|
||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().memory_layout.size);
|
||||
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mTextBlob.getBytes(), mTextBlob.getSize(), decompressed_len);
|
||||
if (decompressed_len != mTextBlob.getSize())
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO text segment failed to decompress");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mTextBlob.alloc(mHdr.getTextSegmentInfo().file_layout.size);
|
||||
mReader->read(mTextBlob.getBytes(), mHdr.getTextSegmentInfo().file_layout.offset, mTextBlob.getSize());
|
||||
}
|
||||
if (mHdr.getTextSegmentInfo().is_hashed)
|
||||
{
|
||||
crypto::sha::Sha256(mTextBlob.getBytes(), mTextBlob.getSize(), calc_hash.bytes);
|
||||
if (calc_hash != mHdr.getTextSegmentInfo().hash)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO text segment failed SHA256 verification");
|
||||
}
|
||||
}
|
||||
|
||||
// process ro segment
|
||||
if (mHdr.getRoSegmentInfo().is_compressed)
|
||||
{
|
||||
scratch.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
||||
mReader->read(scratch.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, scratch.getSize());
|
||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().memory_layout.size);
|
||||
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mRoBlob.getBytes(), mRoBlob.getSize(), decompressed_len);
|
||||
if (decompressed_len != mRoBlob.getSize())
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO ro segment failed to decompress");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mRoBlob.alloc(mHdr.getRoSegmentInfo().file_layout.size);
|
||||
mReader->read(mRoBlob.getBytes(), mHdr.getRoSegmentInfo().file_layout.offset, mRoBlob.getSize());
|
||||
}
|
||||
if (mHdr.getRoSegmentInfo().is_hashed)
|
||||
{
|
||||
crypto::sha::Sha256(mRoBlob.getBytes(), mRoBlob.getSize(), calc_hash.bytes);
|
||||
if (calc_hash != mHdr.getRoSegmentInfo().hash)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO ro segment failed SHA256 verification");
|
||||
}
|
||||
}
|
||||
|
||||
// process data segment
|
||||
if (mHdr.getDataSegmentInfo().is_compressed)
|
||||
{
|
||||
scratch.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
||||
mReader->read(scratch.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, scratch.getSize());
|
||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().memory_layout.size);
|
||||
compress::lz4::decompressData(scratch.getBytes(), scratch.getSize(), mDataBlob.getBytes(), mDataBlob.getSize(), decompressed_len);
|
||||
if (decompressed_len != mDataBlob.getSize())
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO data segment failed to decompress");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mDataBlob.alloc(mHdr.getDataSegmentInfo().file_layout.size);
|
||||
mReader->read(mDataBlob.getBytes(), mHdr.getDataSegmentInfo().file_layout.offset, mDataBlob.getSize());
|
||||
}
|
||||
if (mHdr.getDataSegmentInfo().is_hashed)
|
||||
{
|
||||
crypto::sha::Sha256(mDataBlob.getBytes(), mDataBlob.getSize(), calc_hash.bytes);
|
||||
if (calc_hash != mHdr.getDataSegmentInfo().hash)
|
||||
{
|
||||
throw fnd::Exception(kModuleName, "NSO data segment failed SHA256 verification");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void NsoProcess::importApiList()
|
||||
{
|
||||
if (mHdr.getRoEmbeddedInfo().size > 0)
|
||||
{
|
||||
std::stringstream list_stream(std::string((char*)mRoBlob.getBytes() + mHdr.getRoEmbeddedInfo().offset, mHdr.getRoEmbeddedInfo().size));
|
||||
std::string api;
|
||||
|
||||
while(std::getline(list_stream, api, (char)0x00))
|
||||
{
|
||||
mApiList.push_back(api);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mApiList.clear();
|
||||
}
|
||||
|
||||
if (mHdr.getRoDynSymInfo().size > 0 && mArchType.isSet == true)
|
||||
{
|
||||
mDynSymbolList.parseData(mRoBlob.getBytes() + mHdr.getRoDynSymInfo().offset, mHdr.getRoDynSymInfo().size, mRoBlob.getBytes() + mHdr.getRoDynStrInfo().offset, mHdr.getRoDynStrInfo().size, *mArchType == nx::npdm::INSTR_64BIT);
|
||||
}
|
||||
}
|
||||
|
||||
void NsoProcess::displayHeader()
|
||||
{
|
||||
#define _HEXDUMP_L(var, len) do { for (size_t a__a__A = 0; a__a__A < len; a__a__A++) printf("%02x", var[a__a__A]); } while(0)
|
||||
|
||||
printf("[NSO Header]\n");
|
||||
printf(" ModuleId: ");
|
||||
_HEXDUMP_L(mHdr.getModuleId().data, nx::nso::kModuleIdLen);
|
||||
printf("\n");
|
||||
printf(" Program Segments:\n");
|
||||
printf(" .module_name:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getModuleNameInfo().offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "\n", mHdr.getModuleNameInfo().size);
|
||||
printf(" .text:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getTextSegmentInfo().file_layout.size, mHdr.getTextSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" .ro:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getRoSegmentInfo().file_layout.size, mHdr.getRoSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" .data:\n");
|
||||
printf(" FileOffset: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().file_layout.offset);
|
||||
printf(" FileSize: 0x%" PRIx32 "%s\n", mHdr.getDataSegmentInfo().file_layout.size, mHdr.getDataSegmentInfo().is_compressed? " (COMPRESSED)" : "");
|
||||
printf(" Program Sections:\n");
|
||||
printf(" .text:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getTextSegmentInfo().memory_layout.size);
|
||||
if (mHdr.getTextSegmentInfo().is_hashed && mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mHdr.getTextSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
printf(" .ro:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoSegmentInfo().memory_layout.size);
|
||||
if (mHdr.getRoSegmentInfo().is_hashed && mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mHdr.getRoSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
if (mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" .api_info:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoEmbeddedInfo().size);
|
||||
printf(" .dynstr:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynStrInfo().size);
|
||||
printf(" .dynsym:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getRoDynSymInfo().size);
|
||||
}
|
||||
|
||||
printf(" .data:\n");
|
||||
printf(" MemoryOffset: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().memory_layout.offset);
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getDataSegmentInfo().memory_layout.size);
|
||||
if (mHdr.getDataSegmentInfo().is_hashed && mCliOutputType >= OUTPUT_VERBOSE)
|
||||
{
|
||||
printf(" Hash: ");
|
||||
_HEXDUMP_L(mHdr.getDataSegmentInfo().hash.bytes, 32);
|
||||
printf("\n");
|
||||
}
|
||||
printf(" .bss:\n");
|
||||
printf(" MemorySize: 0x%" PRIx32 "\n", mHdr.getBssSize());
|
||||
|
||||
#undef _HEXDUMP_L
|
||||
}
|
||||
|
||||
void NsoProcess::displayRoApiList()
|
||||
{
|
||||
if (mApiList.size() > 0 || mDynSymbolList.getDynamicSymbolList().getSize() > 0)
|
||||
{
|
||||
printf("[NSO RO Segment]\n");
|
||||
if (mApiList.size() > 0)
|
||||
{
|
||||
printf(" API List:\n");
|
||||
for (size_t i = 0; i < mApiList.size(); i++)
|
||||
{
|
||||
printf(" %s\n", mApiList[i].c_str());
|
||||
}
|
||||
}
|
||||
if (mDynSymbolList.getDynamicSymbolList().getSize() > 0)
|
||||
{
|
||||
printf(" Undefined Symbol List:\n");
|
||||
for (size_t i = 0; i < mDynSymbolList.getDynamicSymbolList().getSize(); i++)
|
||||
{
|
||||
if (mDynSymbolList.getDynamicSymbolList()[i].shn_index == nx::dynsym::SHN_UNDEF && (mDynSymbolList.getDynamicSymbolList()[i].symbol_type == nx::dynsym::STT_FUNC || mDynSymbolList.getDynamicSymbolList()[i].symbol_type == nx::dynsym::STT_NOTYPE))
|
||||
printf(" %s\n", mDynSymbolList.getDynamicSymbolList()[i].name.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
50
programs/nstool/source/NsoProcess.h
Normal file
50
programs/nstool/source/NsoProcess.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
#pragma once
|
||||
#include <vector>
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <fnd/IFile.h>
|
||||
#include <nx/NsoHeader.h>
|
||||
|
||||
#include "nstool.h"
|
||||
#include "DynamicSymbolParser.h"
|
||||
|
||||
class NsoProcess
|
||||
{
|
||||
public:
|
||||
NsoProcess();
|
||||
~NsoProcess();
|
||||
|
||||
void process();
|
||||
|
||||
void setInputFile(fnd::IFile* file, size_t offset, size_t size);
|
||||
void setCliOutputMode(CliOutputType type);
|
||||
void setVerifyMode(bool verify);
|
||||
|
||||
void setArchType(nx::npdm::InstructionType type);
|
||||
|
||||
// processed data
|
||||
const nx::NsoHeader& getNsoHeader() const;
|
||||
const fnd::MemoryBlob& getTextBlob() const;
|
||||
const fnd::MemoryBlob& getRoBlob() const;
|
||||
const fnd::MemoryBlob& getDataBlob() const;
|
||||
const std::vector<std::string>& getApiList() const;
|
||||
|
||||
private:
|
||||
const std::string kModuleName = "NsoProcess";
|
||||
|
||||
fnd::IFile* mReader;
|
||||
CliOutputType mCliOutputType;
|
||||
bool mVerify;
|
||||
sOptional<nx::npdm::InstructionType> mArchType;
|
||||
|
||||
nx::NsoHeader mHdr;
|
||||
fnd::MemoryBlob mTextBlob, mRoBlob, mDataBlob;
|
||||
std::vector<std::string> mApiList;
|
||||
DynamicSymbolParser mDynSymbolList;
|
||||
|
||||
void importHeader();
|
||||
void importCodeSegments();
|
||||
void importApiList();
|
||||
void displayHeader();
|
||||
void displayRoApiList();
|
||||
};
|
|
@ -17,6 +17,7 @@
|
|||
#include <nx/nca.h>
|
||||
#include <nx/npdm.h>
|
||||
#include <nx/romfs.h>
|
||||
#include <nx/nso.h>
|
||||
|
||||
UserSettings::UserSettings()
|
||||
{}
|
||||
|
@ -38,7 +39,7 @@ void UserSettings::showHelp()
|
|||
printf("\n General Options:\n");
|
||||
printf(" -d, --dev Use devkit keyset\n");
|
||||
printf(" -k, --keyset Specify keyset file\n");
|
||||
printf(" -t, --type Specify input file type [xci, pfs, romfs, nca, npdm, cnmt]\n");
|
||||
printf(" -t, --type Specify input file type [xci, pfs, romfs, nca, npdm, cnmt, nso]\n");
|
||||
printf(" -y, --verify Verify file\n");
|
||||
printf(" -v, --verbose Verbose output\n");
|
||||
printf(" -q, --quiet Minimal output\n");
|
||||
|
@ -61,6 +62,10 @@ void UserSettings::showHelp()
|
|||
printf(" --part1 Extract \"partition 1\" to directory \n");
|
||||
printf(" --part2 Extract \"partition 2\" to directory \n");
|
||||
printf(" --part3 Extract \"partition 3\" to directory \n");
|
||||
printf("\n NSO (Nintendo Software Object)\n");
|
||||
printf(" nstool [--arch <architecture>] <.nso>\n");
|
||||
printf(" --arch Specify code architecture [32bit, 64bit]\n");
|
||||
|
||||
}
|
||||
|
||||
const std::string UserSettings::getInputPath() const
|
||||
|
@ -93,6 +98,11 @@ bool UserSettings::isListFs() const
|
|||
return mListFs;
|
||||
}
|
||||
|
||||
const sOptional<nx::npdm::InstructionType>& UserSettings::getArchType() const
|
||||
{
|
||||
return mArchType;
|
||||
}
|
||||
|
||||
const sOptional<std::string>& UserSettings::getUpdatePath() const
|
||||
{
|
||||
return mUpdatePath;
|
||||
|
@ -268,6 +278,12 @@ void UserSettings::populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args)
|
|||
cmd_args.part3_path = args[i+1];
|
||||
}
|
||||
|
||||
else if (args[i] == "--arch")
|
||||
{
|
||||
if (!hasParamter) throw fnd::Exception(kModuleName, args[i] + " requries a parameter.");
|
||||
cmd_args.arch_type = args[i + 1];
|
||||
}
|
||||
|
||||
else
|
||||
{
|
||||
throw fnd::Exception(kModuleName, args[i] + " is not recognised.");
|
||||
|
@ -523,6 +539,12 @@ void UserSettings::populateUserSettings(sCmdArgs& args)
|
|||
mPart2Path = args.part2_path;
|
||||
mPart3Path = args.part3_path;
|
||||
|
||||
// determine the architecture type for NSO
|
||||
if (args.arch_type.isSet)
|
||||
mArchType = getInstructionTypeFromString(*args.arch_type);
|
||||
else
|
||||
mArchType.isSet = false;
|
||||
|
||||
// determine output path
|
||||
if (args.verbose_output.isSet)
|
||||
mOutputType = OUTPUT_VERBOSE;
|
||||
|
@ -579,6 +601,8 @@ FileType UserSettings::getFileTypeFromString(const std::string& type_str)
|
|||
type = FILE_NPDM;
|
||||
else if (str == "cnmt")
|
||||
type = FILE_CNMT;
|
||||
else if (str == "nso")
|
||||
type = FILE_NSO;
|
||||
else
|
||||
type = FILE_INVALID;
|
||||
|
||||
|
@ -635,6 +659,8 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path)
|
|||
// test npdm
|
||||
else if (_ASSERT_SIZE(sizeof(nx::sNpdmHeader)) && std::string(_QUICK_CAST(nx::sNpdmHeader, 0)->signature, 4) == nx::npdm::kNpdmStructSig)
|
||||
file_type = FILE_NPDM;
|
||||
else if (_ASSERT_SIZE(sizeof(nx::sNsoHeader)) && std::string(_QUICK_CAST(nx::sNsoHeader, 0)->signature, 4) == nx::nso::kNsoSig)
|
||||
file_type = FILE_NSO;
|
||||
// else unrecognised
|
||||
else
|
||||
file_type = FILE_INVALID;
|
||||
|
@ -644,3 +670,19 @@ FileType UserSettings::determineFileTypeFromFile(const std::string& path)
|
|||
|
||||
return file_type;
|
||||
}
|
||||
|
||||
nx::npdm::InstructionType UserSettings::getInstructionTypeFromString(const std::string & type_str)
|
||||
{
|
||||
std::string str = type_str;
|
||||
std::transform(str.begin(), str.end(), str.begin(), ::tolower);
|
||||
|
||||
nx::npdm::InstructionType type;
|
||||
if (str == "32bit")
|
||||
type = nx::npdm::INSTR_32BIT;
|
||||
else if (str == "64bit")
|
||||
type = nx::npdm::INSTR_64BIT;
|
||||
else
|
||||
throw fnd::Exception(kModuleName, "Unsupported architecture type: " + str);
|
||||
|
||||
return type;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#pragma once
|
||||
#include <string>
|
||||
#include <fnd/types.h>
|
||||
#include <nx/npdm.h>
|
||||
#include "nstool.h"
|
||||
|
||||
class UserSettings
|
||||
|
@ -20,6 +21,7 @@ public:
|
|||
|
||||
// specialised toggles
|
||||
bool isListFs() const;
|
||||
const sOptional<nx::npdm::InstructionType>& getArchType() const;
|
||||
|
||||
// specialised paths
|
||||
const sOptional<std::string>& getUpdatePath() const;
|
||||
|
@ -54,6 +56,7 @@ private:
|
|||
sOptional<std::string> part1_path;
|
||||
sOptional<std::string> part2_path;
|
||||
sOptional<std::string> part3_path;
|
||||
sOptional<std::string> arch_type;
|
||||
|
||||
void clear()
|
||||
{
|
||||
|
@ -75,6 +78,7 @@ private:
|
|||
part1_path.isSet = false;
|
||||
part2_path.isSet = false;
|
||||
part3_path.isSet = false;
|
||||
arch_type.isSet = false;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -95,10 +99,13 @@ private:
|
|||
sOptional<std::string> mPart2Path;
|
||||
sOptional<std::string> mPart3Path;
|
||||
|
||||
sOptional<nx::npdm::InstructionType> mArchType;
|
||||
|
||||
void populateCmdArgs(int argc, char** argv, sCmdArgs& cmd_args);
|
||||
void populateKeyset(sCmdArgs& args);
|
||||
void populateUserSettings(sCmdArgs& args);
|
||||
void decodeHexStringToBytes(const std::string& name, const std::string& str, byte_t* out, size_t out_len);
|
||||
FileType getFileTypeFromString(const std::string& type_str);
|
||||
FileType determineFileTypeFromFile(const std::string& path);
|
||||
nx::npdm::InstructionType getInstructionTypeFromString(const std::string& type_str);
|
||||
};
|
|
@ -7,6 +7,7 @@
|
|||
#include "NcaProcess.h"
|
||||
#include "NpdmProcess.h"
|
||||
#include "CnmtProcess.h"
|
||||
#include "NsoProcess.h"
|
||||
|
||||
|
||||
int main(int argc, char** argv)
|
||||
|
@ -109,6 +110,19 @@ int main(int argc, char** argv)
|
|||
|
||||
cnmt.process();
|
||||
}
|
||||
else if (user_set.getFileType() == FILE_NSO)
|
||||
{
|
||||
NsoProcess nso;
|
||||
|
||||
nso.setInputFile(&inputFile, 0, inputFile.size());
|
||||
nso.setCliOutputMode(user_set.getCliOutputType());
|
||||
nso.setVerifyMode(user_set.isVerifyFile());
|
||||
|
||||
if (user_set.getArchType().isSet)
|
||||
nso.setArchType(user_set.getArchType().var);
|
||||
|
||||
nso.process();
|
||||
}
|
||||
}
|
||||
catch (const fnd::Exception& e) {
|
||||
printf("\n\n%s\n", e.what());
|
||||
|
|
|
@ -19,6 +19,7 @@ enum FileType
|
|||
FILE_NCA,
|
||||
FILE_NPDM,
|
||||
FILE_CNMT,
|
||||
FILE_NSO,
|
||||
FILE_INVALID = -1,
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in a new issue