draft transfer implementation

This commit is contained in:
2024-08-25 00:02:59 +03:00
parent 31953464e7
commit d2f369af9a
109 changed files with 2314 additions and 4165 deletions
Vendored
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
+36
View File
@@ -0,0 +1,36 @@
.DS_Store
# Prerequisites
*.d
# Compiled Object files
*.slo
*.lo
*.o
*.obj
# Precompiled Headers
*.gch
*.pch
# Compiled Dynamic libraries
*.so
*.dylib
*.dll
# Fortran module files
*.mod
*.smod
# Compiled Static libraries
*.lai
*.la
*.a
*.lib
# Executables
*.exe
*.out
*.app
server
client
-8
View File
@@ -1,8 +0,0 @@
# Default ignored files
/shelf/
/workspace.xml
# Editor-based HTTP Client requests
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
-18
View File
@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MakefileSettings">
<option name="linkedExternalProjectsSettings">
<MakefileProjectSettings>
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
</set>
</option>
<option name="version" value="2" />
</MakefileProjectSettings>
</option>
</component>
<component name="MakefileWorkspace" PROJECT_DIR="$PROJECT_DIR$" />
</project>
Generated
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="Git" />
<mapping directory="$PROJECT_DIR$/lib" vcs="Git" />
</component>
</project>
+28 -21
View File
@@ -1,23 +1,30 @@
{ {
"configurations": [ "configurations": [
{ {
"name": "DKP aarch64", "name": "DKP aarch64",
"includePath": [ "includePath": [
"${env:DEVKITPRO}/devkitA64/aarch64-none-elf/include/**", "${env:DEVKITPRO}/devkitA64/aarch64-none-elf/include/**",
"${env:DEVKITPRO}/devkitARM/arm-none-eabi/include/**", "${env:DEVKITPRO}/devkitARM/arm-none-eabi/include/**",
"${env:DEVKITPRO}/devkitA64/lib/gcc/aarch64-none-elf/13.2.0/include/**", "${env:DEVKITPRO}/devkitA64/lib/gcc/aarch64-none-elf/13.2.0/include/**",
"${env:DEVKITPRO}/libnx/include/**", "${env:DEVKITPRO}/libnx/include/**",
"${env:DEVKITPRO}/portlibs/switch/include/**", "${env:DEVKITPRO}/portlibs/switch/include/**",
"${workspaceFolder}/include/**", "${workspaceFolder}/include/**",
"${workspaceFolder}/lib/Plutonium/include/**", "${workspaceFolder}/lib/Plutonium/include/**",
"/opt/homebrew/opt/lz4/include/**" "/usr/local/include/**",
], "/opt/homebrew/opt/lz4/include/**",
"defines": ["SWITCH", "__SWITCH__", "DEBUG", "__BSD_VISIBLE"], "/opt/devkitpro/devkitA64/aarch64-none-elf/include/machine"
"compilerPath": "${env:DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++", ],
"cStandard": "c17", "defines": [
"cppStandard": "c++14", "SWITCH",
"intelliSenseMode": "linux-gcc-arm64" "__SWITCH__",
} "DEBUG",
], "__BSD_VISIBLE"
"version": 4 ],
"compilerPath": "${env:DEVKITPRO}/devkitA64/bin/aarch64-none-elf-g++",
"cStandard": "c17",
"cppStandard": "c++14",
"intelliSenseMode": "linux-gcc-arm64"
}
],
"version": 4
} }
+26 -27
View File
@@ -3,30 +3,23 @@
"string.h": "c", "string.h": "c",
"stdlib.h": "c", "stdlib.h": "c",
"switch.h": "c", "switch.h": "c",
"psm.h": "c", "optional": "cpp",
"vector": "cpp",
"any": "cpp",
"array": "cpp", "array": "cpp",
"mutex": "cpp",
"any": "cpp",
"atomic": "cpp", "atomic": "cpp",
"barrier": "cpp",
"bit": "cpp", "bit": "cpp",
"*.tcc": "cpp", "*.tcc": "cpp",
"bitset": "cpp", "bitset": "cpp",
"cctype": "cpp", "cctype": "cpp",
"cfenv": "cpp",
"charconv": "cpp", "charconv": "cpp",
"chrono": "cpp", "chrono": "cpp",
"cinttypes": "cpp",
"clocale": "cpp", "clocale": "cpp",
"cmath": "cpp", "cmath": "cpp",
"codecvt": "cpp", "codecvt": "cpp",
"compare": "cpp", "compare": "cpp",
"complex": "cpp",
"concepts": "cpp", "concepts": "cpp",
"condition_variable": "cpp", "condition_variable": "cpp",
"coroutine": "cpp",
"csetjmp": "cpp",
"csignal": "cpp",
"cstdarg": "cpp", "cstdarg": "cpp",
"cstddef": "cpp", "cstddef": "cpp",
"cstdint": "cpp", "cstdint": "cpp",
@@ -34,7 +27,6 @@
"cstdlib": "cpp", "cstdlib": "cpp",
"cstring": "cpp", "cstring": "cpp",
"ctime": "cpp", "ctime": "cpp",
"cuchar": "cpp",
"cwchar": "cpp", "cwchar": "cpp",
"cwctype": "cpp", "cwctype": "cpp",
"deque": "cpp", "deque": "cpp",
@@ -44,20 +36,16 @@
"set": "cpp", "set": "cpp",
"string": "cpp", "string": "cpp",
"unordered_map": "cpp", "unordered_map": "cpp",
"unordered_set": "cpp", "vector": "cpp",
"exception": "cpp", "exception": "cpp",
"expected": "cpp",
"algorithm": "cpp", "algorithm": "cpp",
"functional": "cpp", "functional": "cpp",
"iterator": "cpp", "iterator": "cpp",
"memory": "cpp", "memory": "cpp",
"memory_resource": "cpp", "memory_resource": "cpp",
"numeric": "cpp", "numeric": "cpp",
"optional": "cpp",
"random": "cpp", "random": "cpp",
"ratio": "cpp", "ratio": "cpp",
"regex": "cpp",
"source_location": "cpp",
"string_view": "cpp", "string_view": "cpp",
"system_error": "cpp", "system_error": "cpp",
"tuple": "cpp", "tuple": "cpp",
@@ -65,37 +53,48 @@
"utility": "cpp", "utility": "cpp",
"format": "cpp", "format": "cpp",
"fstream": "cpp", "fstream": "cpp",
"future": "cpp",
"initializer_list": "cpp", "initializer_list": "cpp",
"iomanip": "cpp", "iomanip": "cpp",
"iosfwd": "cpp", "iosfwd": "cpp",
"iostream": "cpp", "iostream": "cpp",
"istream": "cpp", "istream": "cpp",
"latch": "cpp",
"limits": "cpp", "limits": "cpp",
"mutex": "cpp",
"new": "cpp", "new": "cpp",
"numbers": "cpp", "numbers": "cpp",
"ostream": "cpp", "ostream": "cpp",
"ranges": "cpp", "ranges": "cpp",
"scoped_allocator": "cpp",
"semaphore": "cpp", "semaphore": "cpp",
"shared_mutex": "cpp",
"span": "cpp", "span": "cpp",
"spanstream": "cpp",
"sstream": "cpp", "sstream": "cpp",
"stacktrace": "cpp",
"stdexcept": "cpp", "stdexcept": "cpp",
"stdfloat": "cpp",
"stop_token": "cpp", "stop_token": "cpp",
"streambuf": "cpp", "streambuf": "cpp",
"syncstream": "cpp",
"thread": "cpp", "thread": "cpp",
"typeindex": "cpp", "cinttypes": "cpp",
"typeinfo": "cpp", "typeinfo": "cpp",
"valarray": "cpp", "valarray": "cpp",
"variant": "cpp", "variant": "cpp",
"filesystem": "cpp", "filesystem": "cpp",
"plutonium": "cpp" "plutonium": "cpp",
"barrier": "cpp",
"cfenv": "cpp",
"complex": "cpp",
"coroutine": "cpp",
"csetjmp": "cpp",
"csignal": "cpp",
"cuchar": "cpp",
"unordered_set": "cpp",
"expected": "cpp",
"regex": "cpp",
"source_location": "cpp",
"future": "cpp",
"latch": "cpp",
"scoped_allocator": "cpp",
"shared_mutex": "cpp",
"spanstream": "cpp",
"stacktrace": "cpp",
"stdfloat": "cpp",
"syncstream": "cpp",
"typeindex": "cpp"
} }
} }
+2 -3
View File
@@ -49,7 +49,7 @@ ARCH := -march=armv8-a+crc+crypto -mtune=cortex-a57 -mtp=soft -fPIE
CFLAGS += -g -O2 -ffunction-sections \ CFLAGS += -g -O2 -ffunction-sections \
$(ARCH) $(DEFINES) $(ARCH) $(DEFINES)
CFLAGS += $(INCLUDE) -D__SWITCH__ CFLAGS += $(INCLUDE) -D__SWITCH__ -D_GNU_SOURCE=1
CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17 CXXFLAGS:= $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++17
@@ -153,8 +153,7 @@ $(BUILD):
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
clean: clean:
@echo clean ... @echo clean ...
@rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf @rm -fr $(BUILD) $(TARGET).pfs0 $(TARGET).nso $(TARGET).nro $(TARGET).nacp $(TARGET).elf $(TARGET).lst
#--------------------------------------------------------------------------------- #---------------------------------------------------------------------------------
send: $(BUILD) send: $(BUILD)
-2
View File
@@ -1,2 +0,0 @@
-CSn
/Users/n.fedorov/dev/NXST/NXST.elf
-10
View File
@@ -1,10 +0,0 @@
rm build/ -r || true
# TRY to remove Iridium.nsp, ignore if it fails
rm Iridium.nro || true
rm Iridium.nacp || true
rm Iridium.elf || true
rm Iridium.lst || true
-428
View File
@@ -1,428 +0,0 @@
[
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/Main.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/Main.cpp",
"-o",
"Main.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/Main.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/MainApplication.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/MainApplication.cpp",
"-o",
"MainApplication.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/MainApplication.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/TitlesLayout.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/TitlesLayout.cpp",
"-o",
"TitlesLayout.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/TitlesLayout.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/UsersLayout.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/UsersLayout.cpp",
"-o",
"UsersLayout.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/UsersLayout.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/data.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/data.cpp",
"-o",
"data.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/data.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/fs.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/fs.cpp",
"-o",
"fs.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/fs.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/ldn.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/ldn.cpp",
"-o",
"ldn.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/ldn.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/threads.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/threads.cpp",
"-o",
"threads.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/threads.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/util.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/util.cpp",
"-o",
"util.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/util.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/dir.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/fs/dir.cpp",
"-o",
"dir.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/fs/dir.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/file.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/fs/file.cpp",
"-o",
"file.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/fs/file.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-g++",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/zip.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-fno-rtti",
"-fno-exceptions",
"-std=gnu++17",
"-c",
"/Users/n.fedorov/dev/NXST/source/fs/zip.cpp",
"-o",
"zip.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/fs/zip.cpp"
},
{
"directory": "/Users/n.fedorov/dev/NXST",
"arguments": [
"aarch64-none-elf-gcc",
"-MMD",
"-MP",
"-MF",
"/Users/n.fedorov/dev/NXST/build/fsfile.d",
"-g",
"-O2",
"-ffunction-sections",
"-march=armv8-a+crc+crypto",
"-mtune=cortex-a57",
"-mtp=soft",
"-fPIE",
"-I/Users/n.fedorov/dev/NXST/include",
"-I/Users/n.fedorov/dev/NXST/include/fs",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/opt/devkitpro/portlibs/switch/include",
"-I/opt/devkitpro/libnx/include",
"-I/Users/n.fedorov/dev/NXST/lib/Plutonium/include",
"-I/Users/n.fedorov/dev/NXST/build",
"-D__SWITCH__",
"-c",
"/Users/n.fedorov/dev/NXST/source/fs/fsfile.c",
"-o",
"fsfile.o"
],
"file": "/Users/n.fedorov/dev/NXST/source/fs/fsfile.c"
}
]
+37
View File
@@ -0,0 +1,37 @@
#include <stdio.h>
#include <stdlib.h>
#include "asprintf.h"
int vasprintf(char **strp, const char *fmt, va_list ap) {
int size, res;
va_list cp;
va_copy(cp, ap);
size = vsnprintf(NULL, 0, fmt, cp);
va_end(cp);
if (size < 0)
return -1;
*strp = (char *)malloc(size + 1);
if (*strp == NULL)
return -1;
res = vsnprintf(*strp, size + 1, fmt, ap);
if (res < 0) {
free(*strp);
return -1;
}
return res;
}
int asprintf(char **s, const char *fmt, ...) {
int ret;
va_list ap;
va_start(ap, fmt);
ret = vasprintf(s, fmt, ap);
va_end(ap);
return ret;
}
+10
View File
@@ -0,0 +1,10 @@
#ifndef HAVE_ASPRINTF
#define HAVE_ASPRINTF 1
#include <stdarg.h>
int vasprintf(char **strp, const char *fmt, va_list ap);
int asprintf(char **s, const char *fmt, ...);
#endif
+9
View File
@@ -0,0 +1,9 @@
{
"name": "asprintf",
"version": "1.0.0",
"repo": "Neved4/asprintf",
"description": "asprintf, vasprintf - print to allocated string",
"license": "MIT",
"keywords": ["asprintf", "sprintf", "alloc", "string"],
"src": ["asprintf.c", "asprintf.h"]
}
BIN
View File
Binary file not shown.
+1 -1
View File
@@ -1,6 +1,6 @@
#include <pu/Plutonium> #include <pu/Plutonium>
#include <const.h> #include <const.h>
#include <data.h> #include <title.hpp>
namespace ui { namespace ui {
class TitlesLayout : public pu::ui::Layout { class TitlesLayout : public pu::ui::Layout {
+74
View File
@@ -0,0 +1,74 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef ACCOUNT_HPP
#define ACCOUNT_HPP
#include <map>
#include <string.h>
#include <string>
#include <switch.h>
#include <vector>
#define USER_ICON_SIZE 64
namespace std {
template <>
struct hash<AccountUid> {
size_t operator()(const AccountUid& a) const { return ((hash<u64>()(a.uid[0]) ^ (hash<u64>()(a.uid[1]) << 1)) >> 1); }
};
}
inline bool operator==(const AccountUid& x, const AccountUid& y)
{
return x.uid[0] == y.uid[0] && x.uid[1] == y.uid[1];
}
inline bool operator==(const AccountUid& x, u64 y)
{
return x.uid[0] == y && x.uid[1] == y;
}
inline bool operator<(const AccountUid& x, const AccountUid& y)
{
return x.uid[0] < y.uid[0] && x.uid[1] == y.uid[1];
}
struct User {
AccountUid id;
std::string name;
};
namespace Account {
Result init(void);
void exit(void);
std::vector<AccountUid> ids(void);
AccountUid selectAccount(void);
std::string username(AccountUid id);
}
#endif
+7
View File
@@ -0,0 +1,7 @@
#ifdef __SWITCH__
namespace fs = std::filesystem;
#else
namespace fs = std::__fs::filesystem;
#endif
int transfer_files(fs::path directory, char** filenames, int file_count);
+65
View File
@@ -0,0 +1,65 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef COMMON_HPP
#define COMMON_HPP
#include <algorithm>
#include <arpa/inet.h>
#include <codecvt>
#include <cstdio>
#include <locale>
#include <memory>
#include <netinet/in.h>
#include <stdarg.h>
#include <string.h>
#include <string>
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>
#define ATEXIT(func) atexit((void (*)())func)
namespace DateTime {
std::string timeStr(void);
std::string dateTimeStr(void);
std::string logDateTime(void);
}
namespace StringUtils {
bool containsInvalidChar(const std::string& str);
std::string escapeJson(const std::string& s);
std::string format(const std::string fmt_str, ...);
std::string removeForbiddenCharacters(std::string src);
std::string UTF16toUTF8(const std::u16string& src);
void ltrim(std::string& s);
void rtrim(std::string& s);
void trim(std::string& s);
}
char* getConsoleIP(void);
#endif
-91
View File
@@ -1,91 +0,0 @@
#pragma once
#include <switch.h>
#include <vector>
#include <string>
#include <unordered_map>
#define BLD_MON 02
#define BLD_DAY 23
#define BLD_YEAR 2023
namespace data
{
//Loads user + title info
void init();
void exit();
bool loadUsersTitles(bool clearUsers);
void sortUserTitles();
//Draws some stats to the upper left corner
void dispStats();
//Global stuff for all titles/saves
typedef struct
{
NacpStruct nacp;
std::string title, safeTitle, author;//Shortcuts sorta.
bool fav;
} titleInfo;
//Holds stuff specific to user's titles/saves
typedef struct
{
//Makes it easier to grab id
uint64_t tid;
FsSaveDataInfo saveInfo;
PdmPlayStatistics playStats;
} userTitleInfo;
//Class to store user info + titles
class user
{
public:
user() = default;
user(const AccountUid& _id, const std::string& _backupName, const std::string& _safeBackupName);
//Sets ID
void setUID(const AccountUid& _id);
//Returns user ID
AccountUid getUID() const { return userID; }
u128 getUID128() const { return uID128; }
//Returns username
std::string getUsername() const { return username; }
std::string getUsernameSafe() const { return userSafe; }
std::vector<data::userTitleInfo> titleInfo;
void addUserTitleInfo(const uint64_t& _tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats);
private:
AccountUid userID;
u128 uID128;
std::string username, userSafe;
//User icon
};
//User vector
extern std::vector<user> users;
//Title data/info map
extern std::unordered_map<uint64_t, data::titleInfo> titles;
//Sets/Retrieves current user/title
void setUserIndex(unsigned _sUser);
data::user *getCurrentUser();
unsigned getCurrentUserIndex();
void setTitleIndex(unsigned _sTitle);
data::userTitleInfo *getCurrentUserTitleInfo();
unsigned getCurrentUserTitleInfoIndex();
//Gets pointer to info that also has title + nacp
data::titleInfo *getTitleInfoByTID(const uint64_t& tid);
//More shortcut functions
std::string getTitleNameByTID(const uint64_t& tid);
std::string getTitleSafeNameByTID(const uint64_t& tid);
int getTitleIndexInUser(const data::user& u, const uint64_t& tid);
extern SetLanguage sysLang;
}
+58
View File
@@ -0,0 +1,58 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef DIRECTORY_HPP
#define DIRECTORY_HPP
#include <dirent.h>
#include <errno.h>
#include <string>
#include <switch.h>
#include <vector>
struct DirectoryEntry {
std::string name;
bool directory;
};
class Directory {
public:
Directory(const std::string& root);
~Directory() = default;
Result error(void);
std::string entry(size_t index);
bool folder(size_t index);
bool good(void);
size_t size(void);
private:
std::vector<struct DirectoryEntry> mList;
Result mError;
bool mGood;
};
#endif
+39
View File
@@ -0,0 +1,39 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef FILESYSTEM_HPP
#define FILESYSTEM_HPP
#include "account.hpp"
#include <switch.h>
namespace FileSystem {
Result mount(FsFileSystem* fileSystem, u64 titleID, AccountUid userID);
int mount(FsFileSystem fs);
void unmount(void);
}
#endif
-54
View File
@@ -1,54 +0,0 @@
#pragma once
#include <cstring>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "fs/fstype.h"
#include "fs/file.h"
#include "fs/dir.h"
#include "fs/fsfile.h"
#include "fs/zip.h"
#define BUFF_SIZE 0x4000
#define ZIP_BUFF_SIZE 0x20000
#define TRANSFER_BUFFER_LIMIT 0xC00000
namespace fs
{
copyArgs *copyArgsCreate(const std::string& src, const std::string& dst, const std::string& dev, zipFile z, unzFile unz, bool _cleanup, bool _trimZipPath, uint8_t _trimPlaces);
void copyArgsDestroy(copyArgs *c);
void init();
bool mountSave(const FsSaveDataInfo& _m);
inline bool unmountSave() { return fsdevUnmountDevice("sv") == 0; }
bool commitToDevice(const std::string& dev);
std::string getWorkDir();
void setWorkDir(const std::string& _w);
//Loads paths to filter from backup/deletion
void loadPathFilters(const uint64_t& tid);
bool pathIsFiltered(const std::string& _path);
void freePathFilters();
void createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _uid, threadInfo *t);
void createSaveDataThreaded(FsSaveDataType _type, uint64_t _tid, AccountUid _uid);
bool extendSaveData(const data::userTitleInfo *tinfo, uint64_t extSize, threadInfo *t);
void extendSaveDataThreaded(const data::userTitleInfo *tinfo, uint64_t extSize);
uint64_t getJournalSize(const data::userTitleInfo *tinfo);
uint64_t getJournalSizeMax(const data::userTitleInfo *tinfo);
//Always threaded
void wipeSave();
void createNewBackup(void *a);
void overwriteBackup(void *a);
void restoreBackup(void *a);
void deleteBackup(void *a);
void dumpAllUserSaves(void *a);
void dumpAllUsersAllSaves(void *a);
void logOpen();
void logWrite(const char *fmt, ...);
}
-54
View File
@@ -1,54 +0,0 @@
#pragma once
#include <string>
#include "type.h"
namespace fs
{
void mkDir(const std::string& _p);
void mkDirRec(const std::string& _p);
void delDir(const std::string& _p);
bool dirNotEmpty(const std::string& _dir);
bool isDir(const std::string& _path);
//threadInfo is optional. Only for updating task status.
void copyDirToDir(const std::string& src, const std::string& dst, threadInfo *t);
void copyDirToDirThreaded(const std::string& src, const std::string& dst);
void copyDirToDirCommit(const std::string& src, const std::string& dst, const std::string& dev, threadInfo *t);
void copyDirToDirCommitThreaded(const std::string& src, const std::string& dst, const std::string& dev);
void getDirProps(const std::string& path, unsigned& dirCount, unsigned& fileCount, uint64_t& totalSize);
class dirItem
{
public:
dirItem(const std::string& pathTo, const std::string& sItem);
std::string getItm() const { return itm; }
std::string getName() const;
std::string getExt() const;
bool isDir() const { return dir; }
private:
std::string itm;
bool dir = false;
};
//Just retrieves a listing for _path and stores it in item vector
class dirList
{
public:
dirList() = default;
dirList(const std::string& _path);
void reassign(const std::string& _path);
void rescan();
std::string getItem(int index) const { return item[index].getItm(); }
std::string getItemExt(int index) const { return item[index].getExt(); }
bool isDir(int index) const { return item[index].isDir(); }
unsigned getCount() const { return item.size(); }
fs::dirItem *getDirItemAt(unsigned int _ind) { return &item[_ind]; }
private:
std::string path;
std::vector<dirItem> item;
};
}
-64
View File
@@ -1,64 +0,0 @@
#pragma once
#include <string>
#include <cstdio>
#include <vector>
#include <switch.h>
#include <dirent.h>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "fs.h"
#include "data.h"
namespace fs
{
//Copy args are optional and only used if passed and threaded
void copyFile(const std::string& src, const std::string& dst, threadInfo *t);
void copyFileThreaded(const std::string& src, const std::string& dst);
void copyFileCommit(const std::string& src, const std::string& dst, const std::string& dev, threadInfo *t);
void copyFileCommitThreaded(const std::string& src, const std::string& dst, const std::string& dev);
void fileDrawFunc(void *a);
//deletes file
void delfile(const std::string& _p);
//Dumps all titles for current user
void dumpAllUserSaves();
void getShowFileProps(const std::string& _path);
void getShowDirProps(const std::string& _path);
bool fileExists(const std::string& _path);
//Returns file size
size_t fsize(const std::string& _f);
class dataFile
{
public:
dataFile(const std::string& _path);
~dataFile();
void close(){ fclose(f); }
bool isOpen() const { return opened; }
bool readNextLine(bool proc);
//Finds where variable name ends. When a '(' or '=' is hit. Strips spaces
void procLine();
std::string getLine() const { return line; }
std::string getName() const { return name; }
//Reads until ';', ',', or '\n' is hit and returns as string.
std::string getNextValueStr();
int getNextValueInt();
private:
FILE *f;
std::string line, name;
size_t lPos = 0;
bool opened = false;
};
void logOpen();
void logWrite(const char *fmt, ...);
void logClose();
}
-100
View File
@@ -1,100 +0,0 @@
#pragma once
#include <switch.h>
#include <stdint.h>
//Bare minimum wrapper around switch fs for JKSV
#define FS_SEEK_SET 0
#define FS_SEEK_CUR 1
#define FS_SEEK_END 2
#ifdef __cplusplus
extern "C"
{
#endif
typedef struct
{
FsFile _f;
Result error;
s64 offset, fsize;
} FSFILE;
int fsremove(const char *_p);
Result fsDelDirRec(const char *_p);
char *getDeviceFromPath(char *dev, size_t _max, const char *path);
char *getFilePath(char *pathOut, size_t _max, const char *path);
bool fsMkDir(const char *_p);
/*Opens file. Device is fetched from path. Libnx romfs doesn't work with this.
Mode needs to be:
FsOpenMode_Read
FsOpenMode_Write
FsOpenMode_Append
*/
bool fsfcreate(const char *_p, int64_t crSize);
FSFILE *fsfopen(const char *_p, uint32_t mode);
/*Same as above, but FsFileSystem _s is used. Path cannot have device in it*/
FSFILE *fsfopenWithSystem(FsFileSystem *_s, const char *_p, uint32_t mode);
//Closes _f
inline void fsfclose(FSFILE *_f)
{
if(_f != NULL)
{
fsFileClose(&_f->_f);
free(_f);
}
}
//Seeks like stdio
inline void fsfseek(FSFILE *_f, int offset, int origin)
{
switch(origin)
{
case FS_SEEK_SET:
_f->offset = offset;
break;
case FS_SEEK_CUR:
_f->offset += offset;
break;
case FS_SEEK_END:
_f->offset = offset + _f->fsize;
break;
}
}
//Returns offset
inline size_t fsftell(FSFILE *_f) { return _f->offset; }
//Writes buf to file. Automatically resizes _f to fit buf
size_t fsfwrite(const void *buf, size_t sz, size_t count, FSFILE *_f);
//Reads to buff
inline size_t fsfread(void *buf, size_t sz, size_t count, FSFILE *_f)
{
uint64_t read = 0;
_f->error = fsFileRead(&_f->_f, _f->offset, buf, sz * count, 0, &read);
_f->offset += read;
return read;
}
//Gets byte from file
inline char fsfgetc(FSFILE *_f)
{
char ret = 0;
uint64_t read = 0;
_f->error = fsFileRead(&_f->_f, _f->offset++, &ret, 1, 0, &read);
return ret;
}
//Writes byte to file
inline void fsfputc(int ch, FSFILE *_f) { fsfwrite(&ch, 1, 1, _f); }
#ifdef __cplusplus
}
#endif
-46
View File
@@ -1,46 +0,0 @@
#pragma once
#include "data.h"
#include "type.h"
#include "ldn.h"
namespace fs
{
typedef struct
{
std::string src, dst, dev;
zipFile z;
unzFile unz;
LDN::LDNCommunicate *comm;
bool cleanup = false, trimZipPath = false;
uint8_t trimZipPlaces = 0;
uint64_t offset = 0;
threadStatus *thrdStatus;
Mutex arglck = 0;
void argLock() { mutexLock(&arglck); }
void argUnlock() { mutexUnlock(&arglck); }
} copyArgs;
typedef struct
{
FsSaveDataType type;
uint64_t tid;
AccountUid account;
uint16_t index;
} svCreateArgs;
typedef struct
{
const data::userTitleInfo *tinfo;
uint64_t extSize;
} svExtendArgs;
typedef struct
{
std::string path;
bool origin = false;
unsigned dirCount = 0;
unsigned fileCount = 0;
uint64_t totalSize = 0;
} dirCountArgs;
}
-94
View File
@@ -1,94 +0,0 @@
#pragma once
#include <switch.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <string>
#include <vector>
#include <lz4.h>
#include <lz4frame.h>
#include <lz4frame_static.h>
#include <mutex>
#include "type.h"
#define SAVE_DATA_SERVER_PORT 25789
#define SOCKET_BUFFER_SIZE 4096
#define LENGTH_OF_LISTEN_QUEUE 20
enum LDN_COMMUNICATE_TYPE {
UPDATE_FILE,
UPDATE_ABORT,
UPDATE_OK,
UPDATE_DONE,
};
struct LZ4_readFile_s {
LZ4F_dctx *dctxPtr;
int socket;
LZ4_byte *srcBuf;
size_t srcBufNext;
size_t srcBufSize;
size_t srcBufMaxSize;
};
struct LZ4_writeFile_s {
LZ4F_cctx *cctxPtr;
int socket;
LZ4_byte *dstBuf;
size_t maxWriteSize;
size_t dstBufMaxSize;
LZ4F_errorCode_t errCode;
};
namespace LDN {
typedef struct {
// point to server's socket fd;
int serverFD;
// point to communicate socket fd, send meta data
int commFD;
// for client to bind with server, communicate create file socket fd
struct sockaddr_in serverAddr;
} LDNCommunicate;
typedef struct {
LDNCommunicate *comm;
unsigned int filesize = 0, writeLimit = 0;
std::string fullPath;
std::mutex bufferLock;
std::condition_variable cond;
std::vector<uint8_t> sharedBuffer;
bool bufferIsFull = false;
std::string dst, dev;
LZ4_writeFile_s* lz4fWrite;
} LDNfcopyArgs;
typedef struct {
u32 type;
size_t fsz;
} commMeta;
void destroyLDN();
LDN::LDNCommunicate *createCommunicate(void);
void destroyCommunicate(LDNCommunicate *comm);
Result createLDNServer(LDNCommunicate *comm);
Result createLDNClient(LDNCommunicate *comm);
int bindClient(int serverFD);
int bindServer(sockaddr_in *serverAddr);
bool waitForOK(int socketfd);
bool waitForDONE(int socketfd);
void sendOK(int socket_fd);
void sendDONE(int socket_fd);
void sendAbort(int socket_fd);
void reciveMeta(commMeta *meta, int socketfd);
void sendMeta(commMeta *meta, int socketfd);
void copySaveFileToRemote(const std::string &local, threadInfo *t);
void copyRemoteSaveFile(threadInfo *t);
};
-18
View File
@@ -1,18 +0,0 @@
#pragma once
#include <string>
#include <minizip/zip.h>
#include <minizip/unzip.h>
#include "type.h"
namespace fs
{
//threadInfo is optional and only used when threaded versions are used
void copyDirToZip(const std::string& src, zipFile dst, bool trimPath, int trimPlaces, threadInfo *t);
void copyDirToZipThreaded(const std::string& src, zipFile dst, bool trimPath, int trimPlaces);
void copyZipToDir(unzFile src, const std::string& dst, const std::string& dev, threadInfo *t);
void copyZipToDirThreaded(unzFile src, const std::string& dst, const std::string& dev);
uint64_t getZipTotalSize(unzFile unz);
bool zipNotEmpty(unzFile unz);
}
+55
View File
@@ -0,0 +1,55 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef IO_HPP
#define IO_HPP
#include "account.hpp"
#include "directory.hpp"
#include "title.hpp"
#include "util.hpp"
#include <dirent.h>
#include <switch.h>
#include <sys/stat.h>
#include <tuple>
#include <unistd.h>
#include <utility>
#define BUFFER_SIZE 0x80000
namespace io {
std::tuple<bool, Result, std::string> backup(size_t index, AccountUid uid);
std::tuple<bool, Result, std::string> restore(size_t index, AccountUid uid, size_t cellIndex, const std::string& nameFromCell);
Result copyDirectory(const std::string& srcPath, const std::string& dstPath);
void copyFile(const std::string& srcPath, const std::string& dstPath);
Result createDirectory(const std::string& path);
Result deleteFolderRecursively(const std::string& path);
bool directoryExists(const std::string& path);
bool fileExists(const std::string& path);
}
#endif
+84
View File
@@ -0,0 +1,84 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef LOGGER_HPP
#define LOGGER_HPP
#include "common.hpp"
#include <stdio.h>
#include <string>
class Logger {
public:
static Logger& getInstance(void)
{
static Logger mLogger;
return mLogger;
}
inline static const std::string INFO = "[ INFO]";
inline static const std::string DEBUG = "[DEBUG]";
inline static const std::string ERROR = "[ERROR]";
inline static const std::string WARN = "[ WARN]";
template <typename... Args>
void log(const std::string& level, const std::string& format = {}, Args... args)
{
// xcbuffer += StringUtils::format(("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
printf("%s\n", format.c_str());
// printf("%s\n",StringUtils::format("[" + DateTime::logDateTime() + "] " + level + " " + format + "\n").c_str(), args...);
}
void flush(void)
{
mFile = fopen(mPath.c_str(), "a");
if (mFile != NULL) {
fprintf(mFile, buffer.c_str());
fprintf(stderr, buffer.c_str());
fclose(mFile);
}
}
private:
Logger(void) { buffer = ""; }
~Logger(void) {}
Logger(Logger const&) = delete;
void operator=(Logger const&) = delete;
#if defined(__SWITCH__)
const std::string mPath = "/switch/NXST/log.log";
#else
const std::string mPath = "log.log";
#endif
FILE* mFile;
std::string buffer;
};
#endif
+26
View File
@@ -0,0 +1,26 @@
#ifndef MAIN_HPP
#define MAIN_HPP
#include <const.h>
#include "account.hpp"
#include "title.hpp"
#include "util.hpp"
#include <memory>
#include <switch.h>
#include "logger.hpp"
typedef enum { SORT_ALPHA, SORT_LAST_PLAYED, SORT_PLAY_TIME, SORT_MODES_COUNT } sort_t;
inline float g_currentTime = 0;
inline AccountUid g_currentUId;
inline bool g_backupScrollEnabled = 0;
inline bool g_notificationLedAvailable = false;
inline bool g_shouldExitNetworkLoop = false;
inline std::string g_selectedCheatKey;
inline std::vector<std::string> g_selectedCheatCodes;
inline u32 g_username_dotsize;
inline sort_t g_sortMode = SORT_ALPHA;
inline std::string g_currentFile = "";
inline bool g_isTransferringFile = false;
inline const std::string g_emptySave = "New...";
#endif
-44
View File
@@ -1,44 +0,0 @@
#include <switch.h>
#include "type.h"
namespace threads {
//pad data cause i don't know where else to put it
extern PadState pad;
extern HidTouchScreenState touchState;
static inline void updateInput() {
touchState = {0};
padUpdate(&pad);
hidGetTouchScreenStates(&touchState, 1);
}
inline uint64_t padKeysDown() { return padGetButtonsDown(&pad); }
inline uint64_t padKeysHeld() { return padGetButtons(&pad); }
inline uint64_t padKeysUp() { return padGetButtonsUp(&pad); }
threadInfo *newThread(ThreadFunc func, void *args, funcPtr _drawFunc);
class threadProcMngr {
public:
~threadProcMngr();
//Draw function is used and called to draw on overlay
threadInfo *newThread(ThreadFunc func, void *args, funcPtr _drawFunc);
void update();
void draw();
bool empty() { return threads.empty(); }
private:
std::vector<threadInfo *> threads;
uint8_t lgFrame = 0, clrShft = 0;
bool clrAdd = true;
unsigned frameCount = 0;
Mutex threadLock = 0;
};
}
+90
View File
@@ -0,0 +1,90 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef TITLE_HPP
#define TITLE_HPP
#include "account.hpp"
#include "filesystem.hpp"
#include "io.hpp"
#include <algorithm>
#include <stdlib.h>
#include <string>
#include <switch.h>
#include <unordered_map>
#include <utility>
#include <vector>
class Title {
public:
void init(u8 saveDataType, u64 titleid, AccountUid userID, const std::string& name, const std::string& author);
~Title() = default;
std::string author(void);
std::pair<std::string, std::string> displayName(void);
u64 id(void);
std::string name(void);
std::string path(void);
u64 playTimeNanoseconds(void);
std::string playTime(void);
void playTimeNanoseconds(u64 playTimeNanoseconds);
u32 lastPlayedTimestamp(void);
void lastPlayedTimestamp(u32 lastPlayedTimestamp);
std::string fullPath(size_t index);
void refreshDirectories(void);
u64 saveId();
void saveId(u64 id);
std::vector<std::string> saves(void);
u8 saveDataType(void);
AccountUid userId(void);
std::string userName(void);
private:
u64 mId;
u64 mSaveId;
AccountUid mUserId;
std::string mUserName;
std::string mName;
std::string mSafeName;
std::string mAuthor;
std::string mPath;
std::vector<std::string> mSaves;
std::vector<std::string> mFullSavePaths;
u8 mSaveDataType;
std::pair<std::string, std::string> mDisplayName;
u64 mPlayTimeNanoseconds;
u32 mLastPlayedTimestamp;
};
void getTitle(Title& dst, AccountUid uid, size_t i);
size_t getTitleCount(AccountUid uid);
void loadTitles(void);
void sortTitles(void);
void rotateSortMode(void);
void refreshDirectories(u64 id);
std::unordered_map<std::string, std::string> getCompleteTitleList(void);
#endif
-29
View File
@@ -1,29 +0,0 @@
#pragma once
#include <stdio.h>
#include <stdarg.h>
#include <string>
#include <switch.h>
//Misc stuff for new menu code
typedef void (*funcPtr)(void *);
class threadStatus
{
public:
void setStatus(const char *fmt, ...);
void getStatus(std::string& statusOut);
private:
Mutex statusLock = 0;
std::string status;
};
typedef struct
{
bool running = false, finished = false;
Thread thrd;
ThreadFunc thrdFunc;
void *argPtr = NULL;
funcPtr drawFunc = NULL;//Draw func is passed threadInfo pointer too
threadStatus *status;
} threadInfo;
-152
View File
@@ -1,152 +0,0 @@
#pragma once
#include "data.h"
//#include "ui.h"
#include "fs/file.h"
//#include "gfx.h"
namespace util
{
enum
{
DATE_FMT_YMD,
DATE_FMT_YDM,
DATE_FMT_HOYSTE,
DATE_FMT_JHK,
DATE_FMT_ASC
};
typedef enum
{
CPU_SPEED_204MHz = 204000000,
CPU_SPEED_306MHz = 306000000,
CPU_SPEED_408MHz = 408000000,
CPU_SPEED_510MHz = 510000000,
CPU_SPEED_612MHz = 612000000,
CPU_SPEED_714MHz = 714000000,
CPU_SPEED_816MHz = 816000000,
CPU_SPEED_918MHz = 918000000,
CPU_SPEED_1020MHz = 1020000000, //Default
CPU_SPEED_1122MHz = 1122000000,
CPU_SPEED_1224MHz = 1224000000,
CPU_SPEED_1326MHz = 1326000000,
CPU_SPEED_1428MHz = 1428000000,
CPU_SPEED_1581MHz = 1581000000,
CPU_SPEED_1683MHz = 1683000000,
CPU_SPEED_1785MHz = 1785000000
} cpuSpds;
typedef enum
{
GPU_SPEED_0MHz = 0,
GPU_SPEED_76MHz = 76800000,
GPU_SPEED_153MHz = 153600000,
GPU_SPEED_203MHz = 230400000,
GPU_SPEED_307MHz = 307200000, //Handheld 1
GPU_SPEED_384MHz = 384000000, //Handheld 2
GPU_SPEED_460MHz = 460800000,
GPU_SPEED_537MHz = 537600000,
GPU_SPEED_614MHz = 614400000,
GPU_SPEED_768MHz = 768000000, //Docked
GPU_SPEED_844MHz = 844800000,
GPU_SPEED_921MHZ = 921600000
} gpuSpds;
typedef enum
{
RAM_SPEED_0MHz = 0,
RAM_SPEED_40MHz = 40800000,
RAM_SPEED_68MHz = 68000000,
RAM_SPEED_102MHz = 102000000,
RAM_SPEED_204MHz = 204000000,
RAM_SPEED_408MHz = 408000000,
RAM_SPEED_665MHz = 665600000,
RAM_SPEED_800MHz = 800000000,
RAM_SPEED_1065MHz = 1065600000,
RAM_SPEED_1331MHz = 1331200000,
RAM_SPEED_1600MHz = 1600000000
} ramSpds;
//Returns string with date S+ time
std::string getDateTime(int fmt);
//Removes last folder from '_path'
void removeLastFolderFromString(std::string& _path);
size_t getTotalPlacesInPath(const std::string& _path);
void trimPath(std::string& _path, uint8_t _places);
inline bool isASCII(const uint32_t& t)
{
return t > 30 && t < 127;
}
std::string safeString(const std::string& s);
std::string getStringInput(SwkbdType _type, const std::string& def, const std::string& head, size_t maxLength, unsigned dictCnt, const std::string dictWords[]);
std::string getExtensionFromString(const std::string& get);
std::string getFilenameFromPath(const std::string& get);
std::string generateAbbrev(const uint64_t& tid);
//removes char from C++ string
void stripChar(char _c, std::string& _s);
void replaceStr(std::string& _str, const std::string& _find, const std::string& _rep);
//For future external translation support. Replaces [button] with button chars
void replaceButtonsInString(std::string& rep);
inline u128 accountUIDToU128(AccountUid uid)
{
return ((u128)uid.uid[0] << 64 | uid.uid[1]);
}
inline AccountUid u128ToAccountUID(u128 id)
{
AccountUid ret;
ret.uid[0] = id >> 64;
ret.uid[1] = id;
return ret;
}
inline std::string getIDStr(const uint64_t& _id)
{
char tmp[18];
sprintf(tmp, "%016lX", _id);
return std::string(tmp);
}
inline std::string getIDStrLower(const uint64_t& _id)
{
char tmp[18];
sprintf(tmp, "%08X", (uint32_t)_id);
return std::string(tmp);
}
inline std::string generatePathByTID(const uint64_t& tid)
{
return fs::getWorkDir() + data::getTitleSafeNameByTID(tid) + "/";
}
std::string getSizeString(const uint64_t& _size);
inline void createTitleDirectoryByTID(const uint64_t& tid)
{
std::string makePath = fs::getWorkDir() + data::getTitleSafeNameByTID(tid);
mkdir(makePath.c_str(), 777);
}
Result accountDeleteUser(AccountUid *uid);
void sysBoost();
void sysNormal();
inline bool isApplet()
{
AppletType type = appletGetAppletType();
return type == AppletType_LibraryApplet;
}
void checkForUpdate(void *a);
}
+52
View File
@@ -0,0 +1,52 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#ifndef UTIL_HPP
#define UTIL_HPP
#include "account.hpp"
#include "common.hpp"
#include "io.hpp"
#include <switch.h>
#include <sys/stat.h>
// debug
#include <arpa/inet.h>
#include <sys/errno.h>
#include <sys/socket.h>
void servicesExit(void);
Result servicesInit(void);
HidsysNotificationLedPattern blinkLedPattern(u8 times);
void blinkLed(u8 times);
namespace StringUtils {
std::string removeAccents(std::string str);
std::string removeNotAscii(std::string str);
std::u16string UTF8toUTF16(const char* src);
}
#endif
+237
View File
@@ -0,0 +1,237 @@
#include <iostream>
#include <fstream>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <string.h>
#include <filesystem>
#ifdef __SWITCH__
#include <switch.h>
#endif
#define PORT 8080
#define BUFFER_SIZE 1024
#define MULTICAST_PORT 8081
#define MULTICAST_GROUP "239.0.0.1" // Multicast group IP
void sendAck(int sock) {
const char *ack = "ACK";
std::cout << "Sending ACK " << std::endl;
send(sock, ack, strlen(ack), 0);
}
// Функция для получения файла
void receive_file(std::string dirname, int client_socket) {
char buffer[BUFFER_SIZE] = {0};
// Receive filename length
uint32_t filename_len;
ssize_t bytes_read = read(client_socket, &filename_len, sizeof(filename_len));
std::cout << "Filename length: " << filename_len << std::endl;
// Check for end-of-transmission signal
if (bytes_read <= 0 || filename_len == 0) {
std::cout << "End of transmission detected." << std::endl;
pthread_exit(nullptr);
}
// Receive filename
char *filename = new char[filename_len + 1];
read(client_socket, filename, filename_len);
filename[filename_len] = '\0';
std::cout << "Receiving file: " << filename << std::endl;
// Receive file size
size_t file_size;
read(client_socket, &file_size, sizeof(file_size));
std::cout << "With size: " << file_size << std::endl;
// Open a file to write the received data
std::ofstream outfile(dirname + "/" + filename, std::ios::binary);
delete[] filename; // Clean up filename buffer
size_t total_bytes_received = 0;
while (total_bytes_received < file_size) {
ssize_t bytes_received = read(client_socket, buffer, BUFFER_SIZE);
std::cout << "bytes received: " << bytes_received << std::endl;
if (bytes_received <= 0) {
break;
}
outfile.write(buffer, bytes_received);
total_bytes_received += bytes_received;
// Send acknowledgment for each chunk received
sendAck(client_socket);
}
std::cout << "File received successfully." << std::endl;
outfile.close();
}
void *handle_client(void *socket_desc) {
int client_socket = *(int *)socket_desc;
free(socket_desc);
std::cout << "Обработка нового клиента в потоке " << pthread_self() << "\n";
// Receive directory length
uint32_t directory_len;
ssize_t bytes_read = read(client_socket, &directory_len, sizeof(directory_len));
// Check for end-of-transmission signal
if (bytes_read <= 0 || directory_len == 0) {
std::cout << "End of transmission detected." << std::endl;
pthread_exit(nullptr);
}
// Receive filename
char *dirname = new char[directory_len + 1];
read(client_socket, dirname, directory_len);
dirname[directory_len] = '\0';
std::cout << "Directory name is " << dirname << std::endl;
if (!std::filesystem::create_directory(dirname)) {
std::cerr << "Unable to create directory" << std::endl;
pthread_exit(nullptr);
}
// Получаем файлы до тех пор, пока клиент не закроет соединение
while (true) {
receive_file(dirname, client_socket);
}
close(client_socket);
pthread_exit(nullptr);
}
void *broadcast_listener(void *) {
int sockfd;
struct sockaddr_in servaddr;
char buffer[BUFFER_SIZE];
struct ip_mreq group;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("socket creation failed");
pthread_exit(nullptr);
}
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(MULTICAST_PORT);
if (bind(sockfd, (struct sockaddr*)&servaddr, sizeof(servaddr))) {
perror("binding datagram socket");
close(sockfd);
pthread_exit(nullptr);
}
group.imr_multiaddr.s_addr = inet_addr(MULTICAST_GROUP);
group.imr_interface.s_addr = htonl(INADDR_ANY);
if (setsockopt(sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group)) < 0) {
perror("setsockopt failed");
close(sockfd);
pthread_exit(nullptr);
}
std::cout << "Broadcast listener started" << std::endl;
struct sockaddr_in client_addr;
socklen_t addr_len = sizeof(client_addr);
while (true) {
int n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr*)&client_addr, &addr_len);
if (n < 0) {
perror("recvfrom failed");
continue;
}
std::cout << buffer << std::endl;
buffer[n] = '\0';
if (strcmp(buffer, "DISCOVER_SERVER") == 0) {
const char *message = "SERVER_HERE";
sendto(sockfd, message, strlen(message), 0, (const struct sockaddr *)&client_addr, addr_len);
std::cout << "Server discovery response sent to multicast group" << std::endl;
}
}
close(sockfd);
pthread_exit(nullptr);
}
int main() {
#ifdef __SWITCH__
socketInitializeDefault();
nxlinkStdio();
#endif
pthread_t broadcast_thread;
if (pthread_create(&broadcast_thread, nullptr, broadcast_listener, nullptr) < 0) {
perror("Thread creation failed");
return 1;
}
int server_fd, new_socket;
struct sockaddr_in address;
socklen_t addrlen = sizeof(address);
if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) {
perror("Socket creation failed");
exit(EXIT_FAILURE);
}
address.sin_family = AF_INET;
address.sin_addr.s_addr = INADDR_ANY;
address.sin_port = htons(PORT);
if (bind(server_fd, (struct sockaddr *)&address, sizeof(address)) < 0) {
perror("Bind failed");
close(server_fd);
exit(EXIT_FAILURE);
}
if (listen(server_fd, 3) < 0) {
perror("Listen failed");
close(server_fd);
exit(EXIT_FAILURE);
}
std::cout << "Server listening on port " << PORT << std::endl;
while (true) {
sockaddr_in client_address;
socklen_t client_len = sizeof(client_address);
int client_socket = accept(server_fd, (sockaddr *)&client_address, &client_len);
if (client_socket < 0) {
std::cerr << "Ошибка принятия подключения\n";
continue;
}
// Создаем новый поток для обработки клиента
pthread_t thread_id;
int *pclient = new (std::nothrow) int(client_socket);
if (!pclient) {
std::cerr << "Ошибка выделения памяти\n";
close(client_socket);
continue;
}
if (pthread_create(&thread_id, nullptr, handle_client, pclient) != 0) {
std::cerr << "Ошибка создания потока\n";
delete pclient; // Освобождаем память при ошибке
} else {
pthread_detach(thread_id); // Отсоединяем поток, чтобы он мог завершиться самостоятельно
}
}
close(server_fd);
#ifdef __SWITCH__
socketExit();
#endif
return 0;
}
BIN
View File
Binary file not shown.
+10 -5
View File
@@ -1,6 +1,6 @@
#include <MainApplication.hpp> #include <MainApplication.hpp>
#include <data.h> #include "util.hpp"
#include <fs.h> #include "main.hpp"
static int nxlink_sock = -1; static int nxlink_sock = -1;
@@ -35,7 +35,14 @@ extern "C" void userAppExit() {
// Main entrypoint // Main entrypoint
int main() { int main() {
printf("main\n"); Result res = servicesInit();
if (R_FAILED(res)) {
servicesExit();
exit(res);
}
loadTitles();
// First create our renderer, where one can customize SDL or other stuff's // First create our renderer, where one can customize SDL or other stuff's
// initialization. // initialization.
auto renderer_opts = pu::ui::render::RendererInitOptions( auto renderer_opts = pu::ui::render::RendererInitOptions(
@@ -46,8 +53,6 @@ int main() {
auto renderer = pu::ui::render::Renderer::New(renderer_opts); auto renderer = pu::ui::render::Renderer::New(renderer_opts);
data::init();
fs::init();
// Create our main application from the renderer // Create our main application from the renderer
auto main = ui::MainApplication::New(renderer); auto main = ui::MainApplication::New(renderer);
+33 -36
View File
@@ -1,43 +1,21 @@
#include <MainApplication.hpp> #include <MainApplication.hpp>
#include <cinttypes> #include <stdio.h>
#include <cstdio> #include <main.hpp>
#include <data.h> #include <const.h>
#include <client.hpp>
static std::vector<uint64_t> accSids, devSids, bcatSids, cacheSids; static std::vector<uint64_t> accSids, devSids, bcatSids, cacheSids;
//Sort save create tids alphabetically by title from data
static struct
{
bool operator()(const uint64_t& tid1, const uint64_t& tid2)
{
std::string tid1Title = data::getTitleNameByTID(tid1);
std::string tid2Title = data::getTitleNameByTID(tid2);
uint32_t pointA = 0, pointB = 0;
for(unsigned i = 0, j = 0; i < tid1Title.length(); )
{
ssize_t tid1Cnt = decode_utf8(&pointA, (const uint8_t *)&tid1Title.c_str()[i]);
ssize_t tid2Cnt = decode_utf8(&pointB, (const uint8_t *)&tid2Title.c_str()[j]);
pointA = tolower(pointA), pointB = tolower(pointB);
if(pointA != pointB)
return pointA < pointB;
i += tid1Cnt, j += tid2Cnt;
}
return false;
}
} sortCreateTIDs;
namespace ui { namespace ui {
extern MainApplication *mainApp; extern MainApplication *mainApp;
void TitlesLayout::InitTitles() { void TitlesLayout::InitTitles() {
this->titlesMenu = pu::ui::elm::Menu::New(0, 0, 1280, COLOR("#67000000"), COLOR("#170909FF"), 94, 7); this->titlesMenu = pu::ui::elm::Menu::New(0, 0, 1280, COLOR("#67000000"), COLOR("#170909FF"), 94, 7);
const data::user *u = data::getCurrentUser(); for (size_t i = 0; i < getTitleCount(g_currentUId); i++) {
for(const data::userTitleInfo& t : u->titleInfo) { Title title;
auto titleItem = pu::ui::elm::MenuItem::New(data::getTitleNameByTID(t.tid).c_str()); getTitle(title, g_currentUId, i);
auto titleItem = pu::ui::elm::MenuItem::New(title.name().c_str());
titleItem->SetColor(COLOR("#FFFFFFFF")); titleItem->SetColor(COLOR("#FFFFFFFF"));
titlesMenu->AddItem(titleItem); this->titlesMenu->AddItem(titleItem);
} }
this->Add(this->titlesMenu); this->Add(this->titlesMenu);
@@ -52,13 +30,32 @@ namespace ui {
} }
if (Down & HidNpadButton_A) { if (Down & HidNpadButton_A) {
printf("current game index is %i\n", this->titlesMenu->GetSelectedIndex()); auto index = this->titlesMenu->GetSelectedIndex();
data::setTitleIndex(this->titlesMenu->GetSelectedIndex()); Title title;
int opt = mainApp->CreateShowDialog("", "What do you want?", { "Transfer", "Receive" }, true); getTitle(title, g_currentUId, index);
printf("opt is %d\n", opt); printf("userid is 0x%lX%lX\n", title.userId().uid[1], title.userId().uid[0]);
printf("current game index is %i\n", index);
int opt = mainApp->CreateShowDialog(title.name().c_str(), "What do you want?", { "Transfer", "Receive" }, true);
switch (opt) { switch (opt) {
case 0: { case 0: {
// Transfert selected printf("path is %s\n", title.fullPath(0).c_str());
// Transfer selected
auto result = io::backup(index, g_currentUId);
if (std::get<0>(result)) {
printf("path is %s\n", std::get<2>(result).c_str());
std::string path = std::get<2>(result);
std::vector<std::string> files;
std::vector<char*> cstrings{};
auto directory = std::filesystem::path(path);
for (const auto & entry : std::filesystem::directory_iterator(path)) {
std::cout << entry.path() << std::endl;
files.push_back(entry.path().string());
}
for (auto& file : files) {
cstrings.push_back(&file.front());
}
transfer_files(directory, cstrings.data(), cstrings.size());
}
break; break;
} }
case 1: { case 1: {
+5 -6
View File
@@ -1,17 +1,16 @@
#include <cstdio> #include <cstdio>
#include <data.h>
#include <MainApplication.hpp> #include <MainApplication.hpp>
#include "main.hpp"
namespace ui { namespace ui {
extern MainApplication *mainApp; extern MainApplication *mainApp;
UsersLayout::UsersLayout() : Layout::Layout() { UsersLayout::UsersLayout() : Layout::Layout() {
this->usersMenu = pu::ui::elm::Menu::New(0, 0, 1280, COLOR("#67000000"), COLOR("#170909FF"), 94, this->usersMenu = pu::ui::elm::Menu::New(0, 0, 1280, COLOR("#67000000"), COLOR("#170909FF"), 94, 7);
7);
this->usersMenu->SetScrollbarColor(COLOR("#170909FF")); this->usersMenu->SetScrollbarColor(COLOR("#170909FF"));
for (data::user &u: data::users) { for (AccountUid const& uid : Account::ids()) {
auto username = pu::ui::elm::MenuItem::New(u.getUsername() + ": " + std::to_string(u.titleInfo.size())); auto username = pu::ui::elm::MenuItem::New(Account::username(uid) + ": " + std::to_string(getTitleCount(uid)));
username->SetColor(COLOR("#FFFFFFFF")); username->SetColor(COLOR("#FFFFFFFF"));
this->usersMenu->AddItem(username); this->usersMenu->AddItem(username);
} }
@@ -31,7 +30,7 @@ namespace ui {
if (Down & HidNpadButton_A) { if (Down & HidNpadButton_A) {
printf("current index is %i\n", this->usersMenu->GetSelectedIndex()); printf("current index is %i\n", this->usersMenu->GetSelectedIndex());
data::setUserIndex(this->usersMenu->GetSelectedIndex()); g_currentUId = Account::ids().at(this->usersMenu->GetSelectedIndex());
mainApp->titlesLayout->InitTitles(); mainApp->titlesLayout->InitTitles();
mainApp->LoadLayout(mainApp->titlesLayout); mainApp->LoadLayout(mainApp->titlesLayout);
} }
+95
View File
@@ -0,0 +1,95 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "account.hpp"
#include <main.hpp>
static std::map<AccountUid, User> mUsers;
Result Account::init(void)
{
return accountInitialize(AccountServiceType_Application);
}
void Account::exit(void)
{
accountExit();
}
std::vector<AccountUid> Account::ids(void)
{
std::vector<AccountUid> v;
for (auto& value : mUsers) {
v.push_back(value.second.id);
}
return v;
}
static User getUser(AccountUid id)
{
User user{id, ""};
AccountProfile profile;
AccountProfileBase profilebase;
memset(&profilebase, 0, sizeof(profilebase));
if (R_SUCCEEDED(accountGetProfile(&profile, id)) && R_SUCCEEDED(accountProfileGet(&profile, NULL, &profilebase))) {
user.name = std::string(profilebase.nickname, 0x20);
}
accountProfileClose(&profile);
return user;
}
std::string Account::username(AccountUid id)
{
std::map<AccountUid, User>::const_iterator got = mUsers.find(id);
if (got == mUsers.end()) {
User user = getUser(id);
mUsers.insert({id, user});
return user.name;
}
return got->second.name;
}
AccountUid Account::selectAccount(void)
{
LibAppletArgs args;
libappletArgsCreate(&args, 0x10000);
u8 st_in[0xA0] = {0};
u8 st_out[0x18] = {0};
size_t repsz;
Result res = libappletLaunch(AppletId_LibraryAppletPlayerSelect, &args, st_in, 0xA0, st_out, 0x18, &repsz);
if (R_SUCCEEDED(res)) {
u64 lres = *(u64*)st_out;
AccountUid uid = *(AccountUid*)&st_out[8];
if (lres == 0)
return uid;
}
return g_currentUId;
}
+258
View File
@@ -0,0 +1,258 @@
#include <cstring>
#include <fcntl.h>
#include <filesystem>
#include <fstream>
#include <iostream>
#include <ostream>
#include <pthread.h>
#include <string>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <logger.hpp>
#ifdef __SWITCH__
#include <switch.h>
#include <client.hpp>
namespace fs = std::filesystem;
#else
namespace fs = std::__fs::filesystem;
#endif
#define PORT 8080
#define BUFFER_SIZE 1024
#define MULTICAST_PORT 8081
#define MULTICAST_GROUP "239.0.0.1" // Multicast group IP
struct ThreadArgs
{
char **filenames;
int file_count;
int sock;
fs::path directory;
};
bool receiveAck(int sock)
{
char ack[4] = {0};
int bytes_received = read(sock, ack, 3);
return bytes_received > 0 && std::string(ack) == "ACK";
}
// Отправка строки с учетом её длины
void send_string(int sock, const std::string &str)
{
size_t length = str.size();
send(sock, &length, sizeof(length), 0);
send(sock, str.c_str(), length, 0);
}
void *send_files_thread(void *args)
{
ThreadArgs *thread_args = static_cast<ThreadArgs *>(args);
char **filenames = thread_args->filenames;
int file_count = thread_args->file_count;
int sock = thread_args->sock;
fs::path cwd = thread_args->directory;
delete thread_args;
char buffer[BUFFER_SIZE];
// Send the directory length
std::cout << Logger::INFO << "cwd.filename is: " << cwd.filename().c_str() << std::endl; // Get the parent directory
std::string dirname = cwd.parent_path().filename();
uint32_t directory_len = dirname.size();
send(sock, &directory_len, sizeof(directory_len), 0);
// Send the dirname
send(sock, dirname.c_str(), directory_len, 0);
for (int i = 0; i < file_count; ++i)
{
std::string path = filenames[i];
std::size_t found = path.find_last_of("/\\");
std::string filename = path.substr(found+1);
std::ifstream infile(path, std::ios::binary | std::ios::ate);
if (!infile.is_open())
{
std::cout << Logger::ERROR << "File not found: " << filename.c_str() << std::endl;
return nullptr;
}
// Get the size of the file
std::streamsize file_size = infile.tellg();
infile.seekg(0, std::ios::beg);
// Send the filename length
uint32_t filename_len = filename.size();
std::cout << Logger::INFO << "Send filename length: " << filename_len << std::endl;
send(sock, &filename_len, sizeof(filename_len), 0);
// Send the filename
std::cout << Logger::INFO << "Send file name: " << filename.c_str() << std::endl;
send(sock, filename.c_str(), filename_len, 0);
// Send the file size
std::cout << Logger::INFO << "Send file size: " << file_size << std::endl;
send(sock, &file_size, sizeof(file_size), 0);
char buffer[BUFFER_SIZE];
// Send the file data
while (file_size > 0)
{
infile.read(buffer, BUFFER_SIZE);
send(sock, buffer, infile.gcount(), 0);
file_size -= infile.gcount();
std::cout << Logger::INFO << "wait for ACK" << std::endl;
// Wait for acknowledgment after each chunk
if (!receiveAck(sock))
{
std::cout << Logger::ERROR << "Failed to receive acknowledgment" << std::endl;;
}
}
send(sock, 0, 0, 0);
std::cout << Logger::INFO << "File sent successfully: " << filename.c_str() << std::endl;
infile.close();
}
close(sock);
pthread_exit(nullptr);
}
int find_server(char *server_ip)
{
std::cout << Logger::INFO << "Init find_server" << std::endl;;
int sockfd;
struct sockaddr_in multicast_addr;
std::cout << Logger::INFO << "Create socket" << std::endl;
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0)
{
std::cout << Logger::ERROR << "Socket creation error" << std::endl;
return -1;
}
memset(&multicast_addr, 0, sizeof(multicast_addr));
multicast_addr.sin_family = AF_INET;
multicast_addr.sin_port = htons(MULTICAST_PORT);
multicast_addr.sin_addr.s_addr = inet_addr(MULTICAST_GROUP);
std::cout << Logger::INFO << "Send DISCOVER_SERVER" << std::endl;
const char *multicast_message = "DISCOVER_SERVER";
if (sendto(sockfd, multicast_message, strlen(multicast_message), 0, (struct sockaddr *)&multicast_addr, sizeof(multicast_addr)) < 0)
{
std::cout << Logger::ERROR << "sendto failed" << std::endl;
close(sockfd);
return -1;
}
else
{
std::cout << Logger::INFO << "send multicast message success" << std::endl;
}
struct sockaddr_in cliaddr;
socklen_t len = sizeof(cliaddr);
char buffer[BUFFER_SIZE];
ssize_t n = recvfrom(sockfd, buffer, BUFFER_SIZE, 0, (struct sockaddr *)&cliaddr, &len);
std::cout << Logger::INFO << "recvfrom n: %i" << n << std::endl;
if (n < 0)
{
std::cout << Logger::ERROR << "recvfrom failed" << std::endl;
close(sockfd);
return -1;
}
std::cout << Logger::INFO << "buffer: " << buffer << std::endl;
buffer[n] = '\0';
if (strcmp(buffer, "SERVER_HERE") == 0)
{
std::cout << Logger::INFO << "Server found" << std::endl;
inet_ntop(AF_INET, &cliaddr.sin_addr, server_ip, INET_ADDRSTRLEN);
}
else
{
std::cout << Logger::ERROR << "Unable to find server, close socket" << std::endl;;
close(sockfd);
return -1;
}
close(sockfd);
return 0;
}
int transfer_files(fs::path directory, char **filenames, int file_count) {
std::cout << Logger::INFO << "Init transfer_files" << std::endl;
char server_ip[INET_ADDRSTRLEN];
if (find_server(server_ip) != 0)
{
std::cout << Logger::ERROR << "Failed to find server" << std::endl;
return -1;
}
int sock = 0;
struct sockaddr_in serv_addr;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
{
std::cout << Logger::ERROR << "Socket creation error" << std::endl;
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons(PORT);
if (inet_pton(AF_INET, server_ip, &serv_addr.sin_addr) <= 0)
{
std::cout << Logger::ERROR << "Invalid address / Address not supported" << std::endl;
return -1;
}
if (connect(sock, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0)
{
std::cout << Logger::ERROR << "Connection failed" << std::endl;
return -1;
}
pthread_t file_thread;
ThreadArgs *thread_args = new ThreadArgs{filenames, file_count, sock, directory};
if (pthread_create(&file_thread, nullptr, send_files_thread,
(void *)thread_args) < 0)
{
std::cout << Logger::ERROR << "Thread creation failed" << std::endl;
close(sock);
delete thread_args;
return -1;
}
else
{
std::cout << Logger::INFO << "Wait for file_thread" << std::endl;
pthread_join(file_thread, nullptr);
}
return 0;
}
#ifndef __SWITCH__ // for desktop
int main(int argc, char *argv[])
{
if (argc < 2)
{
std::cerr << "Usage: " << argv[0] << " <filename1> <filename2> ..." << std::endl;
return 1;
}
char **filenames = const_cast<char **>(&argv[1]);
int file_count = argc - 1;
transfer_files(filenames, file_count);
return 0;
}
#endif
+124
View File
@@ -0,0 +1,124 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "common.hpp"
std::string DateTime::timeStr(void)
{
time_t unixTime;
struct tm timeStruct;
time(&unixTime);
localtime_r(&unixTime, &timeStruct);
return StringUtils::format("%02i:%02i:%02i", timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec);
}
std::string DateTime::dateTimeStr(void)
{
time_t unixTime;
struct tm timeStruct;
time(&unixTime);
localtime_r(&unixTime, &timeStruct);
return StringUtils::format("%04i%02i%02i-%02i%02i%02i", timeStruct.tm_year + 1900, timeStruct.tm_mon + 1, timeStruct.tm_mday, timeStruct.tm_hour,
timeStruct.tm_min, timeStruct.tm_sec);
}
std::string DateTime::logDateTime(void)
{
time_t unixTime;
struct tm timeStruct;
time(&unixTime);
localtime_r(&unixTime, &timeStruct);
return StringUtils::format("%04i-%02i-%02i %02i:%02i:%02i", timeStruct.tm_year + 1900, timeStruct.tm_mon + 1, timeStruct.tm_mday,
timeStruct.tm_hour, timeStruct.tm_min, timeStruct.tm_sec);
}
std::string StringUtils::UTF16toUTF8(const std::u16string& src)
{
static std::wstring_convert<std::codecvt_utf8_utf16<char16_t>, char16_t> convert;
std::string dst = convert.to_bytes(src);
return dst;
}
std::string StringUtils::removeForbiddenCharacters(std::string src)
{
static const std::string illegalChars = ".,!\\/:?*\"<>|";
for (size_t i = 0, sz = src.length(); i < sz; i++) {
if (illegalChars.find(src[i]) != std::string::npos) {
src[i] = ' ';
}
}
size_t i;
for (i = src.length() - 1; i > 0 && src[i] == ' '; i--)
;
src.erase(i + 1, src.length() - i);
return src;
}
std::string StringUtils::format(const std::string fmt_str, ...)
{
va_list ap;
char* fp = NULL;
va_start(ap, fmt_str);
vasprintf(&fp, fmt_str.c_str(), ap);
va_end(ap);
std::unique_ptr<char[]> formatted(fp);
return std::string(formatted.get());
}
bool StringUtils::containsInvalidChar(const std::string& str)
{
for (size_t i = 0, sz = str.length(); i < sz; i++) {
if (!isascii(str[i])) {
return true;
}
}
return false;
}
void StringUtils::ltrim(std::string& s)
{
s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); }));
}
void StringUtils::rtrim(std::string& s)
{
s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end());
}
void StringUtils::trim(std::string& s)
{
ltrim(s);
rtrim(s);
}
char* getConsoleIP(void)
{
struct in_addr in;
in.s_addr = gethostid();
return inet_ntoa(in);
}
-352
View File
@@ -1,352 +0,0 @@
#include <vector>
#include <unordered_map>
#include <string>
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <ctime>
#include <switch.h>
#include "data.h"
#include "fs/file.h"
#include "util.h"
#include "type.h"
//FsSaveDataSpaceId_All doesn't work for SD
static const unsigned saveOrder[] = {0, 1, 2, 3, 4, 100, 101};
int selUser = 0, selData = 0;
//User vector
std::vector <data::user> data::users;
//For other save types
static bool sysBCATPushed = false, tempPushed = false;
std::unordered_map <uint64_t, data::titleInfo> data::titles;
//Sorts titles by sortType
static struct {
bool operator()(const data::userTitleInfo &a, const data::userTitleInfo &b) {
std::string titleA = data::getTitleNameByTID(a.tid);
std::string titleB = data::getTitleNameByTID(b.tid);
uint32_t pointA, pointB;
for (unsigned i = 0, j = 0; i < titleA.length();) {
ssize_t aCnt = decode_utf8(&pointA, (const uint8_t *) &titleA.data()[i]);
ssize_t bCnt = decode_utf8(&pointB, (const uint8_t *) &titleB.data()[j]);
pointA = tolower(pointA), pointB = tolower(pointB);
if (pointA != pointB)
return pointA < pointB;
i += aCnt;
j += bCnt;
}
return false;
}
} sortTitles;
//Returns -1 for new
static int getUserIndex(const AccountUid &id) {
u128 nId = util::accountUIDToU128(id);
for (unsigned i = 0; i < data::users.size(); i++)
if (data::users[i].getUID128() == nId) return i;
return -1;
}
static inline bool accountSystemSaveCheck(const FsSaveDataInfo &_inf) {
if (_inf.save_data_type == FsSaveDataType_System && util::accountUIDToU128(_inf.uid) != 0)
return false;
return true;
}
//Minimal init/test to avoid loading and creating things I don't need
static bool testMount(const FsSaveDataInfo &_inf) {
bool ret = false;
if ((ret = fs::mountSave(_inf)))
fs::unmountSave();
return ret;
}
static inline void addTitleToList(const uint64_t &tid) {
uint64_t outSize = 0;
NsApplicationControlData *ctrlData = new NsApplicationControlData;
NacpLanguageEntry *ent;
Result ctrlRes = nsGetApplicationControlData(NsApplicationControlSource_Storage, tid, ctrlData,
sizeof(NsApplicationControlData), &outSize);
Result nacpRes = nacpGetLanguageEntry(&ctrlData->nacp, &ent);
size_t iconSize = outSize - sizeof(ctrlData->nacp);
if (R_SUCCEEDED(ctrlRes) && !(outSize < sizeof(ctrlData->nacp)) && R_SUCCEEDED(nacpRes) && iconSize > 0) {
//Copy nacp
memcpy(&data::titles[tid].nacp, &ctrlData->nacp, sizeof(NacpStruct));
//Setup 'shortcuts' to strings
NacpLanguageEntry *ent;
nacpGetLanguageEntry(&data::titles[tid].nacp, &ent);
if (strlen(ent->name) == 0)
data::titles[tid].title = ctrlData->nacp.lang[SetLanguage_ENUS].name;
else
data::titles[tid].title = ent->name;
data::titles[tid].author = ent->author;
if ((data::titles[tid].safeTitle = util::safeString(ent->name)) == "")
data::titles[tid].safeTitle = util::getIDStr(tid);
} else {
memset(&data::titles[tid].nacp, 0, sizeof(NacpStruct));
data::titles[tid].title = util::getIDStr(tid);
data::titles[tid].author = "Someone?";
data::titles[tid].safeTitle = util::getIDStr(tid);
}
delete ctrlData;
}
static inline bool titleIsLoaded(const uint64_t &tid) {
auto findTid = data::titles.find(tid);
return findTid == data::titles.end() ? false : true;
}
static void loadUserAccounts() {
s32 total = 0;
AccountUid *uids = new AccountUid[8];
if (R_SUCCEEDED(accountListAllUsers(uids, 8, &total))) {
for (int i = 0; i < total; i++)
data::users.emplace_back(uids[i], "", "");
}
delete[] uids;
}
//This can load titles installed without having save data
static void loadTitlesFromRecords() {
NsApplicationRecord nsRecord;
int32_t entryCount = 0, recordOffset = 0;
while (R_SUCCEEDED(nsListApplicationRecord(&nsRecord, 1, recordOffset++, &entryCount)) && entryCount > 0) {
if (!titleIsLoaded(nsRecord.application_id))
addTitleToList(nsRecord.application_id);
}
}
bool data::loadUsersTitles(bool clearUsers) {
static unsigned systemUserCount = 4;
FsSaveDataInfoReader it;
FsSaveDataInfo info;
s64 total = 0;
//Clear titles
for (data::user &u: data::users)
u.titleInfo.clear();
if (clearUsers) {
systemUserCount = 4;
data::users.clear();
loadUserAccounts();
sysBCATPushed = false;
tempPushed = false;
users.emplace_back(util::u128ToAccountUID(3), "Device", "Device");
users.emplace_back(util::u128ToAccountUID(2), "BCAT", "BCAT");
users.emplace_back(util::u128ToAccountUID(5), "Cache", "Cache");
users.emplace_back(util::u128ToAccountUID(0), "System", "System");
}
for (unsigned i = 0; i < 7; i++) {
if (R_FAILED(fsOpenSaveDataInfoReader(&it, (FsSaveDataSpaceId) saveOrder[i])))
continue;
while (R_SUCCEEDED(fsSaveDataInfoReaderRead(&it, &info, 1, &total)) && total != 0) {
uint64_t tid = 0;
if (info.save_data_type == FsSaveDataType_System || info.save_data_type == FsSaveDataType_SystemBcat)
tid = info.system_save_data_id;
else
tid = info.application_id;
if (!titleIsLoaded(tid))
addTitleToList(tid);
//Don't bother with this stuff
if (!accountSystemSaveCheck(info) || !testMount(info))
continue;
switch (info.save_data_type) {
case FsSaveDataType_Bcat:
info.uid = util::u128ToAccountUID(2);
break;
case FsSaveDataType_Device:
info.uid = util::u128ToAccountUID(3);
break;
case FsSaveDataType_SystemBcat:
info.uid = util::u128ToAccountUID(4);
if (!sysBCATPushed) {
++systemUserCount;
sysBCATPushed = true;
users.emplace_back(util::u128ToAccountUID(4), "System BCAT",
"System BCAT");
}
break;
case FsSaveDataType_Cache:
info.uid = util::u128ToAccountUID(5);
break;
case FsSaveDataType_Temporary:
info.uid = util::u128ToAccountUID(6);
if (!tempPushed) {
++systemUserCount;
tempPushed = true;
users.emplace_back(util::u128ToAccountUID(6), "Temporary",
"Temporary");
}
break;
}
int u = getUserIndex(info.uid);
if (u == -1) {
users.emplace(data::users.end() - systemUserCount, info.uid, "", "");
u = getUserIndex(info.uid);
}
PdmPlayStatistics playStats;
if (info.save_data_type == FsSaveDataType_Account || info.save_data_type == FsSaveDataType_Device)
pdmqryQueryPlayStatisticsByApplicationIdAndUserAccountId(info.application_id, info.uid, false,
&playStats);
else
memset(&playStats, 0, sizeof(PdmPlayStatistics));
users[u].addUserTitleInfo(tid, &info, &playStats);
}
fsSaveDataInfoReaderClose(&it);
}
//Get reference to device save user
unsigned devPos = getUserIndex(util::u128ToAccountUID(3));
data::user &dev = data::users[devPos];
for (unsigned i = 0; i < devPos; i++) {
//Not needed but makes this easier to read
data::user &u = data::users[i];
u.titleInfo.insert(u.titleInfo.end(), dev.titleInfo.begin(), dev.titleInfo.end());
}
data::sortUserTitles();
return true;
}
void data::sortUserTitles() {
for (data::user &u: data::users)
std::sort(u.titleInfo.begin(), u.titleInfo.end(), sortTitles);
}
void data::init() {
data::loadUsersTitles(true);
}
void data::exit() {
/*Still needed for planned future revisions*/
}
void data::setUserIndex(unsigned _sUser) {
selUser = _sUser;
}
data::user *data::getCurrentUser() {
return &users[selUser];
}
unsigned data::getCurrentUserIndex() {
return selUser;
}
void data::setTitleIndex(unsigned _sTitle) {
selData = _sTitle;
}
data::userTitleInfo *data::getCurrentUserTitleInfo() {
return &users[selUser].titleInfo[selData];
}
unsigned data::getCurrentUserTitleInfoIndex() {
return selData;
}
data::titleInfo *data::getTitleInfoByTID(const uint64_t &tid) {
if (titles.find(tid) != titles.end())
return &titles[tid];
return NULL;
}
std::string data::getTitleNameByTID(const uint64_t &tid) {
return titles[tid].title;
}
std::string data::getTitleSafeNameByTID(const uint64_t &tid) {
return titles[tid].safeTitle;
}
int data::getTitleIndexInUser(const data::user &u, const uint64_t &tid) {
for (unsigned i = 0; i < u.titleInfo.size(); i++) {
if (u.titleInfo[i].tid == tid)
return i;
}
return -1;
}
data::user::user(const AccountUid &_id, const std::string &_backupName, const std::string &_safeBackupName) {
userID = _id;
uID128 = util::accountUIDToU128(_id);
AccountProfile prof;
AccountProfileBase base;
if (R_SUCCEEDED(accountGetProfile(&prof, userID)) && R_SUCCEEDED(accountProfileGet(&prof, NULL, &base))) {
username = base.nickname;
userSafe = util::safeString(username);
if (userSafe.empty()) {
char tmp[32];
sprintf(tmp, "Acc%08X", (uint32_t) uID128);
userSafe = tmp;
}
uint32_t jpgSize = 0;
accountProfileGetImageSize(&prof, &jpgSize);
uint8_t *jpegData = new uint8_t[jpgSize];
accountProfileLoadImage(&prof, jpegData, jpgSize, &jpgSize);
delete[] jpegData;
accountProfileClose(&prof);
} else {
username = _backupName.empty() ? util::getIDStr((uint64_t) uID128) : _backupName;
userSafe = _safeBackupName.empty() ? util::getIDStr((uint64_t) uID128) : _safeBackupName;
}
titles.reserve(64);
}
void data::user::setUID(const AccountUid &_id) {
userID = _id;
uID128 = util::accountUIDToU128(_id);
}
void data::user::addUserTitleInfo(const uint64_t &tid, const FsSaveDataInfo *_saveInfo, const PdmPlayStatistics *_stats) {
data::userTitleInfo newInfo;
newInfo.tid = tid;
memcpy(&newInfo.saveInfo, _saveInfo, sizeof(FsSaveDataInfo));
memcpy(&newInfo.playStats, _stats, sizeof(PdmPlayStatistics));
titleInfo.push_back(newInfo);
}
void data::dispStats() {
data::user *cu = data::getCurrentUser();
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
//Easiest/laziest way to do this
std::string stats = std::to_string(users.size()) + "\n";
for (data::user &u: data::users) {
stats += u.getUsername() + ": " + std::to_string(u.titleInfo.size()) + "\n";
}
}
+77
View File
@@ -0,0 +1,77 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "directory.hpp"
Directory::Directory(const std::string& root)
{
mGood = false;
mError = 0;
mList.clear();
DIR* dir = opendir(root.c_str());
struct dirent* ent;
if (dir == NULL) {
mError = (Result)errno;
}
else {
while ((ent = readdir(dir))) {
std::string name = std::string(ent->d_name);
bool directory = ent->d_type == DT_DIR;
struct DirectoryEntry de = {name, directory};
mList.push_back(de);
}
}
closedir(dir);
mGood = true;
}
Result Directory::error(void)
{
return mError;
}
bool Directory::good(void)
{
return mGood;
}
std::string Directory::entry(size_t index)
{
return index < mList.size() ? mList.at(index).name : "";
}
bool Directory::folder(size_t index)
{
return index < mList.size() ? mList.at(index).directory : false;
}
size_t Directory::size(void)
{
return mList.size();
}
+42
View File
@@ -0,0 +1,42 @@
/*
* This file is part of Checkpoint
* Copyright (C) 2017-2021 Bernardo Giordano, FlagBrew
*
* 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 3 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, see <http://www.gnu.org/licenses/>.
*
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
* * Requiring preservation of specified reasonable legal notices or
* author attributions in that material or in the Appropriate Legal
* Notices displayed by works containing it.
* * Prohibiting misrepresentation of the origin of that material,
* or requiring that modified versions of such material be marked in
* reasonable ways as different from the original version.
*/
#include "filesystem.hpp"
Result FileSystem::mount(FsFileSystem* fileSystem, u64 titleID, AccountUid userID)
{
return fsOpen_SaveData(fileSystem, titleID, userID);
}
int FileSystem::mount(FsFileSystem fs)
{
return fsdevMountDevice("save", fs);
}
void FileSystem::unmount(void)
{
fsdevUnmountDevice("save");
}
-519
View File
@@ -1,519 +0,0 @@
#include <switch.h>
#include "fs.h"
#include "threads.h"
#include "util.h"
static std::string wd = "sdmc:/NXST/";
static FSFILE *debLog;
static FsFileSystem sv;
static std::vector <std::string> pathFilter;
void fs::init() {
mkDirRec(wd);
fs::logOpen();
}
bool fs::mountSave(const FsSaveDataInfo &_m) {
Result svOpen;
FsSaveDataAttribute attr = {0};
switch (_m.save_data_type) {
case FsSaveDataType_System:
case FsSaveDataType_SystemBcat: {
attr.uid = _m.uid;
attr.system_save_data_id = _m.system_save_data_id;
attr.save_data_type = _m.save_data_type;
svOpen = fsOpenSaveDataFileSystemBySystemSaveDataId(&sv, (FsSaveDataSpaceId) _m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Account: {
attr.uid = _m.uid;
attr.application_id = _m.application_id;
attr.save_data_type = _m.save_data_type;
attr.save_data_rank = _m.save_data_rank;
attr.save_data_index = _m.save_data_index;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId) _m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Device: {
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Device;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId) _m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Bcat: {
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Bcat;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId) _m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Cache: {
attr.application_id = _m.application_id;
attr.save_data_type = FsSaveDataType_Cache;
attr.save_data_index = _m.save_data_index;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId) _m.save_data_space_id, &attr);
}
break;
case FsSaveDataType_Temporary: {
attr.application_id = _m.application_id;
attr.save_data_type = _m.save_data_type;
svOpen = fsOpenSaveDataFileSystem(&sv, (FsSaveDataSpaceId) _m.save_data_space_id, &attr);
}
break;
default:
svOpen = 1;
break;
}
return R_SUCCEEDED(svOpen) && fsdevMountDevice("sv", sv) != -1;
}
bool fs::commitToDevice(const std::string &dev) {
bool ret = true;
Result res = fsdevCommitDevice(dev.c_str());
if (R_FAILED(res)) {
fs::logWrite("Error committing file to device -> 0x%X\n", res);
ret = false;
}
return ret;
}
std::string fs::getWorkDir() { return wd; }
void fs::setWorkDir(const std::string &_w) { wd = _w; }
void fs::loadPathFilters(const uint64_t &tid) {
char path[256];
// sprintf(path, "sdmc:/config/JKSV/0x%016lX_filter.txt", tid);
if (fs::fileExists(path)) {
fs::dataFile filter(path);
while (filter.readNextLine(false))
pathFilter.push_back(filter.getLine());
}
}
bool fs::pathIsFiltered(const std::string &_path) {
if (pathFilter.empty())
return false;
for (std::string &_p: pathFilter) {
if (_path == _p)
return true;
}
return false;
}
void fs::freePathFilters() {
pathFilter.clear();
}
void fs::createSaveData(FsSaveDataType _type, uint64_t _tid, AccountUid _uid, threadInfo *t) {
data::titleInfo *tinfo = data::getTitleInfoByTID(_tid);
if (t)
t->status->setStatus("Creating Save Data for #%s#...", tinfo->title.c_str());
uint16_t cacheIndex = 0;
std::string indexStr;
if (_type == FsSaveDataType_Cache &&
!(indexStr = util::getStringInput(SwkbdType_NumPad, "0", "Enter cache index", 2, 0, NULL)).empty())
cacheIndex = strtoul(indexStr.c_str(), NULL, 10);
else if (_type == FsSaveDataType_Cache && indexStr.empty()) {
if (t)
t->finished = true;
return;
}
FsSaveDataAttribute attr;
memset(&attr, 0, sizeof(FsSaveDataAttribute));
attr.application_id = _tid;
attr.uid = _uid;
attr.system_save_data_id = 0;
attr.save_data_type = _type;
attr.save_data_rank = 0;
attr.save_data_index = cacheIndex;
FsSaveDataCreationInfo crt;
memset(&crt, 0, sizeof(FsSaveDataCreationInfo));
int64_t saveSize = 0, journalSize = 0;
switch (_type) {
case FsSaveDataType_Account:
saveSize = tinfo->nacp.user_account_save_data_size;
journalSize = tinfo->nacp.user_account_save_data_journal_size;
break;
case FsSaveDataType_Device:
saveSize = tinfo->nacp.device_save_data_size;
journalSize = tinfo->nacp.device_save_data_journal_size;
break;
case FsSaveDataType_Bcat:
saveSize = tinfo->nacp.bcat_delivery_cache_storage_size;
journalSize = tinfo->nacp.bcat_delivery_cache_storage_size;
break;
case FsSaveDataType_Cache:
saveSize = 32 * 1024 * 1024;
if (tinfo->nacp.cache_storage_journal_size > tinfo->nacp.cache_storage_data_and_journal_size_max)
journalSize = tinfo->nacp.cache_storage_journal_size;
else
journalSize = tinfo->nacp.cache_storage_data_and_journal_size_max;
break;
default:
if (t)
t->finished = true;
return;
break;
}
crt.save_data_size = saveSize;
crt.journal_size = journalSize;
crt.available_size = 0x4000;
crt.owner_id = _type == FsSaveDataType_Bcat ? 0x010000000000000C : tinfo->nacp.save_data_owner_id;
crt.flags = 0;
crt.save_data_space_id = FsSaveDataSpaceId_User;
FsSaveDataMetaInfo meta;
memset(&meta, 0, sizeof(FsSaveDataMetaInfo));
if (_type != FsSaveDataType_Bcat) {
meta.size = 0x40060;
meta.type = FsSaveDataMetaType_Thumbnail;
}
Result res = 0;
if (R_SUCCEEDED(res = fsCreateSaveDataFileSystem(&attr, &crt, &meta))) {
util::createTitleDirectoryByTID(_tid);
data::loadUsersTitles(false);
} else {
fs::logWrite("SaveCreate Failed -> %X\n", res);
}
}
static void createSaveData_t(void *a) {
threadInfo *t = (threadInfo *) a;
fs::svCreateArgs *crt = (fs::svCreateArgs *) t->argPtr;
fs::createSaveData(crt->type, crt->tid, crt->account, t);
delete crt;
t->finished = true;
}
void fs::createSaveDataThreaded(FsSaveDataType _type, uint64_t _tid, AccountUid _uid) {
fs::svCreateArgs *send = new fs::svCreateArgs;
send->type = _type;
send->tid = _tid;
send->account = _uid;
threads::newThread(createSaveData_t, send, NULL);
}
bool fs::extendSaveData(const data::userTitleInfo *tinfo, uint64_t extSize, threadInfo *t) {
if (t)
t->status->setStatus("Extending Save Data for #%s#...", data::getTitleNameByTID(tinfo->tid).c_str());
uint64_t journal = fs::getJournalSizeMax(tinfo);
uint64_t saveID = tinfo->saveInfo.save_data_id;
FsSaveDataSpaceId space = (FsSaveDataSpaceId) tinfo->saveInfo.save_data_space_id;
Result res = 0;
if (R_FAILED((res = fsExtendSaveDataFileSystem(space, saveID, extSize, journal)))) {
int64_t totalSize = 0;
fs::mountSave(tinfo->saveInfo);
fsFsGetTotalSpace(fsdevGetDeviceFileSystem("sv"), "/", &totalSize);
fs::unmountSave();
fs::logWrite("Extend Failed: %uMB to %uMB -> %X\n", totalSize / 1024 / 1024, extSize / 1024 / 1024, res);
// ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataExtendFailed", 0));
return false;
}
return true;
}
static void extendSaveData_t(void *a) {
threadInfo *t = (threadInfo *) a;
fs::svExtendArgs *e = (fs::svExtendArgs *) t->argPtr;
fs::extendSaveData(e->tinfo, e->extSize, t);
delete e;
t->finished = true;
}
void fs::extendSaveDataThreaded(const data::userTitleInfo *tinfo, uint64_t extSize) {
fs::svExtendArgs *send = new fs::svExtendArgs;
send->tinfo = tinfo;
send->extSize = extSize;
threads::newThread(extendSaveData_t, send, NULL);
}
uint64_t fs::getJournalSize(const data::userTitleInfo *tinfo) {
uint64_t ret = 0;
data::titleInfo *t = data::getTitleInfoByTID(tinfo->tid);
switch (tinfo->saveInfo.save_data_type) {
case FsSaveDataType_Account:
ret = t->nacp.user_account_save_data_journal_size;
break;
case FsSaveDataType_Device:
ret = t->nacp.device_save_data_journal_size;
break;
case FsSaveDataType_Bcat:
ret = t->nacp.bcat_delivery_cache_storage_size;
break;
case FsSaveDataType_Cache:
if (t->nacp.cache_storage_journal_size > 0)
ret = t->nacp.cache_storage_journal_size;
else
ret = t->nacp.cache_storage_data_and_journal_size_max;
break;
default:
ret = BUFF_SIZE;
break;
}
return ret;
}
uint64_t fs::getJournalSizeMax(const data::userTitleInfo *tinfo) {
uint64_t ret = 0;
data::titleInfo *extend = data::getTitleInfoByTID(tinfo->tid);
switch (tinfo->saveInfo.save_data_type) {
case FsSaveDataType_Account:
if (extend->nacp.user_account_save_data_journal_size_max > extend->nacp.user_account_save_data_journal_size)
ret = extend->nacp.user_account_save_data_journal_size_max;
else
ret = extend->nacp.user_account_save_data_journal_size;
break;
case FsSaveDataType_Bcat:
ret = extend->nacp.bcat_delivery_cache_storage_size;
break;
case FsSaveDataType_Cache:
if (extend->nacp.cache_storage_data_and_journal_size_max > extend->nacp.cache_storage_journal_size)
ret = extend->nacp.cache_storage_data_and_journal_size_max;
else
ret = extend->nacp.cache_storage_journal_size;
break;
case FsSaveDataType_Device:
if (extend->nacp.device_save_data_journal_size_max > extend->nacp.device_save_data_journal_size)
ret = extend->nacp.device_save_data_journal_size_max;
else
ret = extend->nacp.device_save_data_journal_size;
break;
default:
//will just fail
ret = 0;
break;
}
return ret;
}
static void wipeSave_t(void *a) {
threadInfo *t = (threadInfo *) a;
t->status->setStatus("Resetting save data...");
fs::delDir("sv:/");
fs::commitToDevice("sv");
t->finished = true;
}
void fs::wipeSave() {
threads::newThread(wipeSave_t, NULL, NULL);
}
void fs::createNewBackup(void *a) {
if (!fs::dirNotEmpty("sv:/")) {
// ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popSaveIsEmpty", 0));
return;
}
uint64_t held = threads::padKeysHeld();
data::user *u = data::getCurrentUser();
data::userTitleInfo *d = data::getCurrentUserTitleInfo();
data::titleInfo *t = data::getTitleInfoByTID(d->tid);
std::string out;
const std::string dict[] =
{
util::getDateTime(util::DATE_FMT_YMD),
util::getDateTime(util::DATE_FMT_YDM),
util::getDateTime(util::DATE_FMT_HOYSTE),
util::getDateTime(util::DATE_FMT_JHK),
util::getDateTime(util::DATE_FMT_ASC),
u->getUsernameSafe(),
t->safeTitle,
util::generateAbbrev(d->tid),
".zip"
};
std::string defaultText = u->getUsernameSafe() + " - " + util::getDateTime(util::DATE_FMT_YMD);
out = util::getStringInput(SwkbdType_QWERTY, defaultText, "Enter a new name", 64, 9, dict);
out = util::safeString(out);
if (!out.empty()) {
std::string ext = util::getExtensionFromString(out);
std::string path = util::generatePathByTID(d->tid) + out;
fs::mkDir(path);
path += "/";
fs::copyDirToDirThreaded("sv:/", path);
// ui::fldRefreshMenu();
}
}
void fs::overwriteBackup(void *a) {
threadInfo *t = (threadInfo *) a;
std::string *dst = (std::string *) t->argPtr;
bool saveHasFiles = fs::dirNotEmpty("sv:/");
if (fs::isDir(*dst) && saveHasFiles) {
fs::delDir(*dst);
fs::mkDir(*dst);
dst->append("/");
fs::copyDirToDirThreaded("sv:/", *dst);
}
delete dst;
t->finished = true;
}
void fs::restoreBackup(void *a) {
threadInfo *t = (threadInfo *) a;
std::string *restore = (std::string *) t->argPtr;
data::user *u = data::getCurrentUser();
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
if ((utinfo->saveInfo.save_data_type != FsSaveDataType_System)) {
bool saveHasFiles = fs::dirNotEmpty("sv:/");
if (saveHasFiles) {
std::string autoFolder = util::generatePathByTID(utinfo->tid) + "/AUTO - " + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + "/";
fs::mkDir(autoFolder.substr(0, autoFolder.length() - 1));
fs::copyDirToDirThreaded("sv:/", autoFolder);
}
if (fs::isDir(*restore)) {
restore->append("/");
if (fs::dirNotEmpty(*restore)) {
t->status->setStatus("Calculating save data size...");
unsigned dirCount = 0, fileCount = 0;
uint64_t saveSize = 0;
int64_t availSize = 0;
fs::getDirProps(*restore, dirCount, fileCount, saveSize);
fsFsGetTotalSpace(fsdevGetDeviceFileSystem("sv"), "/", &availSize);
if ((int) saveSize > availSize) {
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
fs::unmountSave();
fs::extendSaveData(utinfo, saveSize + 0x500000, t);
fs::mountSave(utinfo->saveInfo);
}
fs::wipeSave();
fs::copyDirToDirCommitThreaded(*restore, "sv:/", "sv");
}
// else
// ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("popFolderIsEmpty", 0));
} else {
std::string dstPath = "sv:/" + util::getFilenameFromPath(*restore);
fs::copyFileCommitThreaded(*restore, dstPath, "sv");
}
}
delete restore;
t->finished = true;
}
void fs::deleteBackup(void *a) {
threadInfo *t = (threadInfo *) a;
std::string *deletePath = (std::string *) t->argPtr;
std::string backupName = util::getFilenameFromPath(*deletePath);
t->status->setStatus("Deleting...");
data::userTitleInfo *utinfo = data::getCurrentUserTitleInfo();
if (fs::isDir(*deletePath)) {
*deletePath += "/";
fs::delDir(*deletePath);
// ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupDeleted", 0), backupName.c_str());
} else {
fs::delfile(*deletePath);
// ui::showPopMessage(POP_FRAME_DEFAULT, ui::getUICString("saveDataBackupDeleted", 0), backupName.c_str());
}
// ui::fldRefreshMenu();
delete deletePath;
t->finished = true;
}
void fs::dumpAllUserSaves(void *a) {
threadInfo *t = (threadInfo *) a;
fs::copyArgs *c = fs::copyArgsCreate("", "", "", NULL, NULL, false, false, 0);
t->argPtr = c;
data::user *u = data::getCurrentUser();
for (unsigned i = 0; i < u->titleInfo.size(); i++) {
bool saveMounted = fs::mountSave(u->titleInfo[i].saveInfo);
util::createTitleDirectoryByTID(u->titleInfo[i].tid);
if (saveMounted && fs::dirNotEmpty("sv:/")) {
fs::loadPathFilters(u->titleInfo[i].tid);
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + "/";
fs::mkDir(dst.substr(0, dst.length() - 1));
fs::copyDirToDir("sv:/", dst, t);
fs::freePathFilters();
}
fs::unmountSave();
}
fs::copyArgsDestroy(c);
t->finished = true;
}
void fs::dumpAllUsersAllSaves(void *a) {
threadInfo *t = (threadInfo *) a;
fs::copyArgs *c = fs::copyArgsCreate("", "", "", NULL, NULL, false, false, 0);
t->argPtr = c;
unsigned curUser = 0;
while (data::users[curUser].getUID128() != 2) {
data::user *u = &data::users[curUser++];
for (unsigned i = 0; i < u->titleInfo.size(); i++) {
bool saveMounted = fs::mountSave(u->titleInfo[i].saveInfo);
util::createTitleDirectoryByTID(u->titleInfo[i].tid);
if (saveMounted && fs::dirNotEmpty("sv:/")) {
fs::loadPathFilters(u->titleInfo[i].tid);
std::string dst = util::generatePathByTID(u->titleInfo[i].tid) + u->getUsernameSafe() + " - " +
util::getDateTime(util::DATE_FMT_YMD) + "/";
fs::mkDir(dst.substr(0, dst.length() - 1));
fs::copyDirToDir("sv:/", dst, t);
fs::freePathFilters();
}
fs::unmountSave();
}
}
fs::copyArgsDestroy(c);
t->finished = true;
}
void fs::logOpen() {
std::string logPath = wd + "log.txt";
debLog = fsfopen(logPath.c_str(), FsOpenMode_Write);
fsfclose(debLog);
}
void fs::logWrite(const char *fmt, ...) {
std::string logPath = wd + "log.txt";
debLog = fsfopen(logPath.c_str(), FsOpenMode_Append | FsOpenMode_Write);
char tmp[256];
va_list args;
va_start(args, fmt);
vsprintf(tmp, fmt, args);
va_end(args);
fsfwrite(tmp, 1, strlen(tmp), debLog);
fsfclose(debLog);
}

Some files were not shown because too many files have changed in this diff Show More