diff --git a/.gitignore b/.gitignore index 259148f..ef76937 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,20 @@ *.lib # Executables +splatsave *.exe *.out *.app + +# Switch +build/ +*.elf +*.nacp +*.nro +*.nso +*.pfs0 + +# Test files +*.dat +*.enc +*.dec diff --git a/Makefile b/Makefile index aebd38a..7ba868e 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,198 @@ -main : main.cpp - g++ main.cpp -o splatsave -std=c++11 -lmbedcrypto -lz +#--------------------------------------------------------------------------------- +.SUFFIXES: +#--------------------------------------------------------------------------------- + +TOPDIR ?= $(CURDIR) +include $(DEVKITPRO)/libnx/switch_rules + +#--------------------------------------------------------------------------------- +# TARGET is the name of the output +# BUILD is the directory where object files & intermediate files will be placed +# SOURCES is a list of directories containing source code +# DATA is a list of directories containing data files +# INCLUDES is a list of directories containing header files +# EXEFS_SRC is the optional input directory containing data copied into exefs, if anything this normally should only contain "main.npdm". +# ROMFS is the directory containing data to be added to RomFS, relative to the Makefile (Optional) +# +# NO_ICON: if set to anything, do not use icon. +# NO_NACP: if set to anything, no .nacp file is generated. +# APP_TITLE is the name of the app stored in the .nacp file (Optional) +# APP_AUTHOR is the author of the app stored in the .nacp file (Optional) +# APP_VERSION is the version of the app stored in the .nacp file (Optional) +# APP_TITLEID is the titleID of the app stored in the .nacp file (Optional) +# ICON is the filename of the icon (.jpg), relative to the project folder. +# If not set, it attempts to use one of the following (in this order): +# - .jpg +# - icon.jpg +# - /default_icon.jpg +#--------------------------------------------------------------------------------- +TARGET := splatsave +BUILD := build +SOURCES := . +DATA := data +INCLUDES := include +EXEFS_SRC := exefs_src +#ROMFS := romfs + +#--------------------------------------------------------------------------------- +# options for code generation +#--------------------------------------------------------------------------------- +ARCH := -march=armv8-a -mtune=cortex-a57 -mtp=soft -fPIE + +CFLAGS := -g -Wall -O2 -ffunction-sections \ + $(ARCH) $(DEFINES) + +CFLAGS += $(INCLUDE) -D__SWITCH__ + +CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 + +ASFLAGS := -g $(ARCH) +LDFLAGS = -specs=$(DEVKITPRO)/libnx/switch.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) + +LIBS := -lmbedcrypto -lz -lnx + +#--------------------------------------------------------------------------------- +# list of directories containing libraries, this must be the top level containing +# include and lib +#--------------------------------------------------------------------------------- +LIBDIRS := $(PORTLIBS) $(LIBNX) + + +#--------------------------------------------------------------------------------- +# no real need to edit anything past this point unless you need to add additional +# rules for different file extensions +#--------------------------------------------------------------------------------- +ifneq ($(BUILD),$(notdir $(CURDIR))) +#--------------------------------------------------------------------------------- + +export OUTPUT := $(CURDIR)/$(TARGET) +export TOPDIR := $(CURDIR) + +export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ + $(foreach dir,$(DATA),$(CURDIR)/$(dir)) + +export DEPSDIR := $(CURDIR)/$(BUILD) + +CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) +CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) +SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) +BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) + +#--------------------------------------------------------------------------------- +# use CXX for linking C++ projects, CC for standard C +#--------------------------------------------------------------------------------- +ifeq ($(strip $(CPPFILES)),) +#--------------------------------------------------------------------------------- + export LD := $(CC) +#--------------------------------------------------------------------------------- +else +#--------------------------------------------------------------------------------- + export LD := $(CXX) +#--------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------- + +export OFILES_BIN := $(addsuffix .o,$(BINFILES)) +export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) +export OFILES := $(OFILES_BIN) $(OFILES_SRC) +export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES))) + +export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ + $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ + -I$(CURDIR)/$(BUILD) + +export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) + +export BUILD_EXEFS_SRC := $(TOPDIR)/$(EXEFS_SRC) +ifeq ($(strip $(ICON)),) + icons := $(wildcard *.jpg) + ifneq (,$(findstring $(TARGET).jpg,$(icons))) + export APP_ICON := $(TOPDIR)/$(TARGET).jpg + else + ifneq (,$(findstring icon.jpg,$(icons))) + export APP_ICON := $(TOPDIR)/icon.jpg + endif + endif +else + export APP_ICON := $(TOPDIR)/$(ICON) +endif + +ifeq ($(strip $(NO_ICON)),) + export NROFLAGS += --icon=$(APP_ICON) +endif + +ifeq ($(strip $(NO_NACP)),) + export NROFLAGS += --nacp=$(CURDIR)/$(TARGET).nacp +endif + +ifneq ($(APP_TITLEID),) + export NACPFLAGS += --titleid=$(APP_TITLEID) +endif + +ifneq ($(ROMFS),) + export NROFLAGS += --romfsdir=$(CURDIR)/$(ROMFS) +endif + +.PHONY: $(BUILD) clean switch bin win +#--------------------------------------------------------------------------------- +bin: main.cpp + g++ main.cpp -o splatsave -std=c++11 -lmbedcrypto -lz +#--------------------------------------------------------------------------------- # Windows rule to use with mingw, mingw openssl pre-built binary: https://wiki.openssl.org/index.php/Binaries win: main.cpp - g++ main.cpp -o splatsave.exe -std=c++11 -lmbedcrypto -static-libstdc++ -static-libgcc + g++ main.cpp -o splatsave.exe -std=c++11 -lmbedcrypto -lz -static-libstdc++ -static-libgcc + +#--------------------------------------------------------------------------------- +switch: $(BUILD) + +$(BUILD): + @[ -d $@ ] || mkdir -p $@ + @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile +#--------------------------------------------------------------------------------- clean: + @echo clean ... + @rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf $(RM) splatsave $(RM) splatsave.exe + + +#--------------------------------------------------------------------------------- +else +.PHONY: switch + +DEPENDS := $(OFILES:.o=.d) + +#--------------------------------------------------------------------------------- +# main targets +#--------------------------------------------------------------------------------- +switch : $(OUTPUT).pfs0 $(OUTPUT).nro + +$(OUTPUT).pfs0 : $(OUTPUT).nso + +$(OUTPUT).nso : $(OUTPUT).elf + +ifeq ($(strip $(NO_NACP)),) +$(OUTPUT).nro : $(OUTPUT).elf $(OUTPUT).nacp +else +$(OUTPUT).nro : $(OUTPUT).elf +endif + +$(OUTPUT).elf : $(OFILES) + +$(OFILES_SRC) : $(HFILES_BIN) + +#--------------------------------------------------------------------------------- +# you need a rule like this for each extension you use as binary data +#--------------------------------------------------------------------------------- +%.bin.o %_bin.h : %.bin +#--------------------------------------------------------------------------------- + @echo $(notdir $<) + @$(bin2o) + +-include $(DEPENDS) + +#--------------------------------------------------------------------------------------- +endif +#--------------------------------------------------------------------------------------- diff --git a/main.cpp b/main.cpp index 0389ccf..d4a3246 100644 --- a/main.cpp +++ b/main.cpp @@ -9,6 +9,10 @@ #include #include +#ifdef __SWITCH__ +#include +#endif + const int FILE_SIZE[4] = {0x483B0, 0x483B0, 0x86840, 0x88D90}; const int BODY_SIZE[4] = {0x483A0, 0x483A0, 0x86800, 0x88D50}; @@ -122,6 +126,8 @@ int calcAes128Cmac(uint8_t* msg, size_t msg_len, uint8_t* key, uint8_t* mac) { } int rand_bytes(uint8_t* output, size_t output_len) { + int ret; +#ifndef __SWITCH__ mbedtls_ctr_drbg_context ctr_drbg; mbedtls_entropy_context entropy; mbedtls_entropy_init(&entropy); @@ -129,14 +135,19 @@ int rand_bytes(uint8_t* output, size_t output_len) { std::string pers = "Flow best waifu"; - int ret; if((ret = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (unsigned char*)pers.c_str(), pers.size())) != 0) { return ret; } - if((ret = mbedtls_ctr_drbg_random(&ctr_drbg, output, output_len)) != 0) { + ret = mbedtls_ctr_drbg_random(&ctr_drbg, output, output_len); +#else + if((ret = csrngInitialize()) != 0) { return ret; } + ret = csrngGetRandomBytes(output, output_len); + csrngExit(); +#endif + return ret; } SaveFooter encryptBody(uint8_t* save_file, const uint32_t* crypt_tab, @@ -193,7 +204,7 @@ int decryptBody(uint8_t* save_file, const uint32_t* crypt_tab, return 0; } -int main(int argc, char const *argv[]) { +int splatsave(int argc, char const *argv[]) { std::string path; if (argc < 2) path = "save.dat"; @@ -204,8 +215,20 @@ int main(int argc, char const *argv[]) { std::streamsize size = fileis.tellg(); fileis.seekg(0, std::ios::beg); - uint8_t save_file[size]; - if (!fileis.read((char*)save_file, size)) { + uint8_t* save_file; + bool fileis_error = false; + if(size > -1) { + save_file = new uint8_t[size]; + if(!fileis.read((char*)save_file, size)) { + delete[] save_file; + fileis_error = true; + } + } else { + fileis_error = true; + } + + if (fileis_error) { + fileis.close(); std::cout << "Could not open " << path << std::endl; std::cout << "Usage: " << std::endl; @@ -219,6 +242,7 @@ int main(int argc, char const *argv[]) { << std::endl; return -1; } + fileis.close(); uint32_t vers = *(uint32_t*)save_file; @@ -257,7 +281,7 @@ int main(int argc, char const *argv[]) { else out_path = argv[2]; - uint8_t new_body[BODY_SIZE[vers]]; + uint8_t* new_body = new uint8_t[BODY_SIZE[vers]]; SaveFooter footer; if(isEncrypt) { @@ -278,6 +302,8 @@ int main(int argc, char const *argv[]) { std::ofstream fileos(out_path, std::fstream::binary); if(!fileos) { + fileos.close(); + delete[] new_body; std::cout << "Could not open " << out_path << std::endl; return -2; } @@ -291,6 +317,32 @@ int main(int argc, char const *argv[]) { } else { std::cout << "Decrypted " << path << " to " << out_path << "!" << std::endl; - } + } + + fileos.close(); + delete[] save_file; + delete[] new_body; + return 0; } + +int main(int argc, char const *argv[]) { +#ifdef __SWITCH__ + gfxInitDefault(); + consoleInit(NULL); +#endif + + int ret = splatsave(argc, argv); + +#ifdef __SWITCH__ + std::cout << "Press + to exit..." << std::endl; + while(appletMainLoop()) { + hidScanInput(); u64 kDown = hidKeysDown(CONTROLLER_P1_AUTO); + if (kDown & KEY_PLUS) break; + gfxFlushBuffers(); gfxSwapBuffers(); gfxWaitForVsync(); + } + gfxExit(); +#endif + + return ret; +}