├── LICENSE ├── Makefile ├── README.md ├── include ├── c2d_helper.h ├── dialog.h ├── fs.h ├── status_bar.h ├── textures.h └── utils.h ├── res ├── app.rsf ├── banner.png ├── banner.wav ├── drawable │ ├── Roboto-Regular.ttf │ ├── battery_20.png │ ├── battery_20_charging.png │ ├── battery_30.png │ ├── battery_30_charging.png │ ├── battery_50.png │ ├── battery_50_charging.png │ ├── battery_60.png │ ├── battery_60_charging.png │ ├── battery_80.png │ ├── battery_80_charging.png │ ├── battery_90.png │ ├── battery_90_charging.png │ ├── battery_full.png │ ├── battery_full_charging.png │ ├── battery_low.png │ ├── battery_unknown.png │ ├── btn_material_light_toggle_off_normal.png │ ├── btn_material_light_toggle_on_normal.png │ ├── ic_arrow_back_normal.png │ ├── sprites.t3s │ ├── stat_sys_wifi_signal_0.png │ ├── stat_sys_wifi_signal_1.png │ ├── stat_sys_wifi_signal_2.png │ └── stat_sys_wifi_signal_3.png ├── ic_launcher_recovery_tool.png └── logo.bcma.lz └── source ├── c2d_helper.c ├── dialog.c ├── fs.c ├── main.c ├── status_bar.c ├── textures.c └── utils.c /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2017 Joel 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | ifeq ($(strip $(DEVKITARM)),) 6 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 7 | endif 8 | 9 | TOPDIR ?= $(CURDIR) 10 | include $(DEVKITARM)/3ds_rules 11 | 12 | #--------------------------------------------------------------------------------- 13 | # TARGET is the name of the output 14 | # BUILD is the directory where object files & intermediate files will be placed 15 | # SOURCES is a list of directories containing source code 16 | # DATA is a list of directories containing data files 17 | # INCLUDES is a list of directories containing header files 18 | # GRAPHICS is a list of directories containing graphics files 19 | # GFXBUILD is the directory where converted graphics files will be placed 20 | # If set to $(BUILD), it will statically link in the converted 21 | # files as if they were data files. 22 | # 23 | # NO_SMDH: if set to anything, no SMDH file is generated. 24 | # ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) 25 | # APP_TITLE is the name of the app stored in the SMDH file (Optional) 26 | # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) 27 | # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) 28 | # ICON is the filename of the icon (.png), relative to the project folder. 29 | # If not set, it attempts to use one of the following (in this order): 30 | # - .png 31 | # - icon.png 32 | # - /default_icon.png 33 | #--------------------------------------------------------------------------------- 34 | TARGET := $(notdir $(CURDIR)) 35 | BUILD := build 36 | SOURCES := source 37 | DATA := data 38 | INCLUDES := include 39 | GRAPHICS := res/drawable 40 | ROMFS := romfs 41 | GFXBUILD := $(ROMFS)/res/drawable 42 | 43 | APP_TITLE := 3DS Recovery Tool 44 | APP_DESCRIPTION := Restore and backup misc data 45 | APP_AUTHOR := Joel16 46 | VERSION_MAJOR := 1 47 | VERSION_MINOR := 5 48 | VERSION_MICRO := 0 49 | ICON := res/ic_launcher_recovery_tool.png 50 | 51 | # CIA 52 | BANNER_AUDIO := res/banner.wav 53 | BANNER_IMAGE := res/banner.png 54 | RSF_PATH := res/app.rsf 55 | LOGO := res/logo.bcma.lz 56 | UNIQUE_ID := 0x16600 57 | PRODUCT_CODE := CTR-3D-RECT 58 | ICON_FLAGS := nosavebackups,visible 59 | 60 | #--------------------------------------------------------------------------------- 61 | # options for code generation 62 | #--------------------------------------------------------------------------------- 63 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard 64 | 65 | CFLAGS := -g -Wall -O3 -mword-relocations -fomit-frame-pointer -ffast-math \ 66 | -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) -DVERSION_MICRO=$(VERSION_MICRO) \ 67 | $(ARCH) 68 | 69 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 70 | 71 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 72 | 73 | ASFLAGS := -g $(ARCH) 74 | LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 75 | 76 | LIBS := -lcitro2d -lcitro3d -lctru -lm 77 | 78 | #--------------------------------------------------------------------------------- 79 | # list of directories containing libraries, this must be the top level containing 80 | # include and lib 81 | #--------------------------------------------------------------------------------- 82 | LIBDIRS := $(CTRULIB) 83 | 84 | #--------------------------------------------------------------------------------- 85 | # no real need to edit anything past this point unless you need to add additional 86 | # rules for different file extensions 87 | #--------------------------------------------------------------------------------- 88 | ifneq ($(BUILD),$(notdir $(CURDIR))) 89 | #--------------------------------------------------------------------------------- 90 | 91 | export OUTPUT := $(CURDIR)/$(TARGET) 92 | export TOPDIR := $(CURDIR) 93 | 94 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 95 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) \ 96 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 97 | 98 | export DEPSDIR := $(CURDIR)/$(BUILD) 99 | 100 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 101 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 102 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 103 | PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) 104 | SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) 105 | GFXFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.t3s))) 106 | FONTFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.ttf))) 107 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 108 | 109 | #--------------------------------------------------------------------------------- 110 | # use CXX for linking C++ projects, CC for standard C 111 | #--------------------------------------------------------------------------------- 112 | ifeq ($(strip $(CPPFILES)),) 113 | #--------------------------------------------------------------------------------- 114 | export LD := $(CC) 115 | #--------------------------------------------------------------------------------- 116 | else 117 | #--------------------------------------------------------------------------------- 118 | export LD := $(CXX) 119 | #--------------------------------------------------------------------------------- 120 | endif 121 | #--------------------------------------------------------------------------------- 122 | 123 | #--------------------------------------------------------------------------------- 124 | ifeq ($(GFXBUILD),$(BUILD)) 125 | #--------------------------------------------------------------------------------- 126 | export T3XFILES := $(GFXFILES:.t3s=.t3x) 127 | #--------------------------------------------------------------------------------- 128 | else 129 | #--------------------------------------------------------------------------------- 130 | export ROMFS_T3XFILES := $(patsubst %.t3s, $(GFXBUILD)/%.t3x, $(GFXFILES)) 131 | export ROMFS_FONTFILES := $(patsubst %.ttf, $(GFXBUILD)/%.bcfnt, $(FONTFILES)) 132 | export T3XHFILES := $(patsubst %.t3s, $(BUILD)/%.h, $(GFXFILES)) 133 | #--------------------------------------------------------------------------------- 134 | endif 135 | #--------------------------------------------------------------------------------- 136 | 137 | 138 | export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 139 | 140 | export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \ 141 | $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ 142 | $(addsuffix .o,$(T3XFILES)) 143 | 144 | export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) 145 | 146 | export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(SHLISTFILES:.shlist=_shbin.h) \ 147 | $(addsuffix .h,$(subst .,_,$(BINFILES))) \ 148 | $(GFXFILES:.t3s=.h) 149 | 150 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 151 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 152 | -I$(CURDIR)/$(BUILD) 153 | 154 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 155 | 156 | export _3DSXDEPS := $(if $(NO_SMDH),,$(OUTPUT).smdh) 157 | 158 | ifeq ($(strip $(ICON)),) 159 | icons := $(wildcard *.png) 160 | ifneq (,$(findstring $(TARGET).png,$(icons))) 161 | export APP_ICON := $(TOPDIR)/$(TARGET).png 162 | else 163 | ifneq (,$(findstring icon.png,$(icons))) 164 | export APP_ICON := $(TOPDIR)/icon.png 165 | endif 166 | endif 167 | else 168 | export APP_ICON := $(TOPDIR)/$(ICON) 169 | endif 170 | 171 | ifeq ($(strip $(NO_SMDH)),) 172 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 173 | endif 174 | 175 | ifneq ($(ROMFS),) 176 | export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) 177 | endif 178 | 179 | .PHONY: all clean 180 | 181 | #--------------------------------------------------------------------------------- 182 | MAKEROM ?= makerom 183 | MAKEROM_ARGS := -elf "$(OUTPUT).elf" -rsf "$(RSF_PATH)" -banner "$(BUILD)/banner.bnr" -icon "$(BUILD)/icon.icn" -DAPP_TITLE="$(APP_TITLE)" -DAPP_PRODUCT_CODE="$(PRODUCT_CODE)" -DAPP_UNIQUE_ID="$(UNIQUE_ID)" 184 | MAKEROM_ARGS += -major $(VERSION_MAJOR) -minor $(VERSION_MINOR) -micro $(VERSION_MICRO) 185 | 186 | ifneq ($(strip $(LOGO)),) 187 | MAKEROM_ARGS += -logo "$(LOGO)" 188 | endif 189 | ifneq ($(strip $(ROMFS)),) 190 | MAKEROM_ARGS += -DAPP_ROMFS="$(ROMFS)" 191 | endif 192 | 193 | BANNERTOOL ?= bannertool 194 | 195 | ifeq ($(suffix $(BANNER_IMAGE)),.cgfx) 196 | BANNER_IMAGE_ARG := -ci 197 | else 198 | BANNER_IMAGE_ARG := -i 199 | endif 200 | 201 | ifeq ($(suffix $(BANNER_AUDIO)),.cwav) 202 | BANNER_AUDIO_ARG := -ca 203 | else 204 | BANNER_AUDIO_ARG := -a 205 | endif 206 | 207 | #--------------------------------------------------------------------------------- 208 | all: $(BUILD) $(GFXBUILD) $(DEPSDIR) $(ROMFS_T3XFILES) $(ROMFS_FONTFILES) $(T3XHFILES) 209 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 210 | @$(BANNERTOOL) makebanner $(BANNER_IMAGE_ARG) "$(BANNER_IMAGE)" $(BANNER_AUDIO_ARG) "$(BANNER_AUDIO)" -o "$(BUILD)/banner.bnr" 211 | @$(BANNERTOOL) makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i "$(APP_ICON)" -f "$(ICON_FLAGS)" -o "$(BUILD)/icon.icn" 212 | $(MAKEROM) -f cia -o "$(OUTPUT).cia" -target t -exefslogo $(MAKEROM_ARGS) 213 | 214 | $(BUILD): 215 | @mkdir -p $@ 216 | 217 | ifneq ($(GFXBUILD),$(BUILD)) 218 | $(GFXBUILD): 219 | @mkdir -p $@ 220 | endif 221 | 222 | ifneq ($(DEPSDIR),$(BUILD)) 223 | $(DEPSDIR): 224 | @mkdir -p $@ 225 | endif 226 | 227 | #--------------------------------------------------------------------------------- 228 | clean: 229 | @echo clean ... 230 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf $(GFXBUILD) 231 | 232 | #--------------------------------------------------------------------------------- 233 | $(GFXBUILD)/%.t3x $(BUILD)/%.h : %.t3s 234 | #--------------------------------------------------------------------------------- 235 | @echo $(notdir $<) 236 | @tex3ds -i $< -H $(BUILD)/$*.h -d $(DEPSDIR)/$*.d -o $(GFXBUILD)/$*.t3x 237 | 238 | #--------------------------------------------------------------------------------- 239 | $(GFXBUILD)/%.bcfnt : %.ttf 240 | #--------------------------------------------------------------------------------- 241 | @echo $(notdir $<) 242 | @mkbcfnt -o $(GFXBUILD)/$*.bcfnt $< 243 | 244 | #--------------------------------------------------------------------------------- 245 | else 246 | 247 | #--------------------------------------------------------------------------------- 248 | # main targets 249 | #--------------------------------------------------------------------------------- 250 | $(OUTPUT).3dsx : $(OUTPUT).elf $(_3DSXDEPS) 251 | 252 | $(OFILES_SOURCES) : $(HFILES) 253 | 254 | $(OUTPUT).elf : $(OFILES) 255 | 256 | #--------------------------------------------------------------------------------- 257 | # you need a rule like this for each extension you use as binary data 258 | #--------------------------------------------------------------------------------- 259 | %.bin.o %_bin.h : %.bin 260 | #--------------------------------------------------------------------------------- 261 | @echo $(notdir $<) 262 | @$(bin2o) 263 | 264 | #--------------------------------------------------------------------------------- 265 | .PRECIOUS : %.t3x 266 | #--------------------------------------------------------------------------------- 267 | %.t3x.o %_t3x.h : %.t3x 268 | #--------------------------------------------------------------------------------- 269 | @echo $(notdir $<) 270 | @$(bin2o) 271 | 272 | #--------------------------------------------------------------------------------- 273 | # rules for assembling GPU shaders 274 | #--------------------------------------------------------------------------------- 275 | define shader-as 276 | $(eval CURBIN := $*.shbin) 277 | $(eval DEPSFILE := $(DEPSDIR)/$*.shbin.d) 278 | echo "$(CURBIN).o: $< $1" > $(DEPSFILE) 279 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h 280 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h 281 | echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h 282 | picasso -o $(CURBIN) $1 283 | bin2s $(CURBIN) | $(AS) -o $*.shbin.o 284 | endef 285 | 286 | %.shbin.o %_shbin.h : %.v.pica %.g.pica 287 | @echo $(notdir $^) 288 | @$(call shader-as,$^) 289 | 290 | %.shbin.o %_shbin.h : %.v.pica 291 | @echo $(notdir $<) 292 | @$(call shader-as,$<) 293 | 294 | %.shbin.o %_shbin.h : %.shlist 295 | @echo $(notdir $<) 296 | @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file))) 297 | 298 | #--------------------------------------------------------------------------------- 299 | %.t3x %.h : %.t3s 300 | #--------------------------------------------------------------------------------- 301 | @echo $(notdir $<) 302 | @tex3ds -i $< -H $*.h -d $*.d -o $*.t3x 303 | 304 | #--------------------------------------------------------------------------------- 305 | %.bcfnt : %.ttf 306 | #--------------------------------------------------------------------------------- 307 | @echo $(notdir $<) 308 | @mkbcfnt -o $*.bcfnt $< 309 | 310 | -include $(DEPSDIR)/*.d 311 | 312 | #--------------------------------------------------------------------------------------- 313 | endif 314 | #--------------------------------------------------------------------------------------- 315 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 3DS Recovery Tool ![Github latest downloads](https://img.shields.io/github/downloads/joel16/3DS-Recovery-Tool/total.svg) 2 | A tool for dumping, restoring, and backing-up unique data on the Nintendo 3DS. It also allows you to format/wipe various files. 3 | 4 | # Features: 5 | - Back up LocalFriendCodeSeed, SecureInfo, movable.sed, HWCAL0.dat and HWCAL1.dat from NAND. 6 | - Dump original LocalFriendCodeSeed from data. (This is different from copying the seed from nand) 7 | - Dump original SecureInfo from data. (This is different from copying the SecureInfo from nand) 8 | - Restore LocalFriendCodeSeed and SecureInfo from memory. 9 | - Restore LocalFriendCodeSeed and SecureInfo from backup. 10 | - Verify LocalFriendCodeSeed and SecureInfo. 11 | - Wipe temporary titles, expired titles, TWL titles, pending titles, demo launch infos, config, parental controls and CTRNAND. 12 | - Format (delete) SMDC root and NAND ext savedata. 13 | 14 | # Credits: 15 | - preetisketch - for the banner and the toggle buttons. 16 | -------------------------------------------------------------------------------- /include/c2d_helper.h: -------------------------------------------------------------------------------- 1 | #ifndef _3DS_RECOVERY_TOOL_C2D_HELPER_H 2 | #define _3DS_RECOVERY_TOOL_C2D_HELPER_H 3 | 4 | #include 5 | 6 | #define WHITE C2D_Color32(255, 255, 255, 255) 7 | #define BG_COLOUR_LIGHT C2D_Color32(250, 250, 250, 255) 8 | #define BG_COLOUR_DARK C2D_Color32(48, 48, 48, 255) 9 | #define SELECTOR_COLOUR_LIGHT C2D_Color32(230, 232, 232, 255) 10 | #define SELECTOR_COLOUR_DARK C2D_Color32(28, 30, 30, 255) 11 | #define TEXT_COLOUR_LIGHT C2D_Color32(54, 54, 54, 255) 12 | #define TEXT_COLOUR_DARK C2D_Color32(230, 230, 230, 255) 13 | 14 | extern C3D_RenderTarget *RENDER_TOP, *RENDER_BOTTOM; 15 | extern C2D_TextBuf c2d_static_buf, c2d_dynamic_buf, c2d_size_buf; 16 | extern C2D_Font font; 17 | typedef u32 Colour; 18 | 19 | void Draw_EndFrame(void); 20 | void Draw_Text(float x, float y, float size, Colour colour, const char *text); 21 | void Draw_Textf(float x, float y, float size, Colour colour, const char* text, ...); 22 | void Draw_GetTextSize(float size, float *width, float *height, const char *text); 23 | float Draw_GetTextWidth(float size, const char *text); 24 | float Draw_GetTextHeight(float size, const char *text); 25 | bool Draw_Rect(float x, float y, float w, float h, Colour colour); 26 | bool Draw_Image(C2D_Image image, float x, float y); 27 | 28 | #endif 29 | -------------------------------------------------------------------------------- /include/dialog.h: -------------------------------------------------------------------------------- 1 | #ifndef _3DS_RECOVERY_TOOL_DIALOG_H 2 | #define _3DS_RECOVERY_TOOL_DIALOG_H 3 | 4 | Result Dialog_Draw(const char *top_message, const char *bottom_message); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/fs.h: -------------------------------------------------------------------------------- 1 | #ifndef _3DS_RECOVERY_TOOL_FS_H 2 | #define _3DS_RECOVERY_TOOL_FS_H 3 | 4 | #include <3ds.h> 5 | 6 | extern FS_Archive sdmc_archive, nand_archive; 7 | 8 | Result FS_OpenArchive(FS_Archive *archive, FS_ArchiveID id); 9 | Result FS_CloseArchive(FS_Archive archive); 10 | Result FS_MakeDir(FS_Archive archive, const char *path); 11 | Result FS_RecursiveMakeDir(FS_Archive archive, const char *path); 12 | bool FS_FileExists(FS_Archive archive, const char *path); 13 | bool FS_DirExists(FS_Archive archive, const char *path); 14 | Result FS_GetFileSize(FS_Archive archive, const char *path, u64 *size); 15 | Result FS_Write(FS_Archive archive, const char *path, const void *buf, u32 size); 16 | Result FS_CopyFile(FS_Archive src_archive, FS_Archive dest_archive, char *src_path, char *dest_path); 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /include/status_bar.h: -------------------------------------------------------------------------------- 1 | #ifndef _3DS_RECOVERY_TOOL_STATUS_BAR_H 2 | #define _3DS_RECOVERY_TOOL_STATUS_BAR_H 3 | 4 | void StatusBar_DisplayBar(void); 5 | 6 | #endif 7 | -------------------------------------------------------------------------------- /include/textures.h: -------------------------------------------------------------------------------- 1 | #ifndef _3DS_RECOVERY_TOOL_TEXTURES_H 2 | #define _3DS_RECOVERY_TOOL_TEXTURES_H 3 | 4 | C2D_Image icon_toggle_on, icon_toggle_off, icon_back, icon_wifi_0, icon_wifi_1, icon_wifi_2, icon_wifi_3, \ 5 | battery_20, battery_20_charging, battery_30, battery_30_charging, battery_50, battery_50_charging, \ 6 | battery_60, battery_60_charging, battery_80, battery_80_charging, battery_90, battery_90_charging, \ 7 | battery_full, battery_full_charging, battery_low, battery_unknown; 8 | 9 | void Textures_Load(void); 10 | void Textures_Free(void); 11 | 12 | #endif 13 | -------------------------------------------------------------------------------- /include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef _3DS_RECOVERY_TOOL_UTILS_H 2 | #define _3DS_RECOVERY_TOOL_UTILS_H 3 | 4 | #include <3ds.h> 5 | 6 | #define touchInRect(x1, y1, x2, y2) ((touchGetX() >= (x1) && touchGetX() <= (x2)) && (touchGetY() >= (y1) && touchGetY() <= (y2))) 7 | 8 | extern bool dark_theme; 9 | 10 | Result Utils_SaveConfig(bool dark_theme); 11 | Result Utils_LoadConfig(void); 12 | u16 touchGetX(void); 13 | u16 touchGetY(void); 14 | void Utils_SetMax(int *set, int value, int max); 15 | void Utils_SetMin(int *set, int value, int min); 16 | 17 | #endif 18 | -------------------------------------------------------------------------------- /res/app.rsf: -------------------------------------------------------------------------------- 1 | BasicInfo: 2 | Title : 3DS Recovery Tool 3 | ProductCode : CTR-3D-RECT 4 | Logo : Homebrew 5 | 6 | RomFs: 7 | RootPath : romfs 8 | 9 | TitleInfo: 10 | Category : Application 11 | UniqueId : 0x16600 12 | 13 | Option: 14 | UseOnSD : true # true if App is to be installed to SD 15 | FreeProductCode : true # Removes limitations on ProductCode 16 | MediaFootPadding : false # If true CCI files are created with padding 17 | EnableCrypt : false # Enables encryption for NCCH and CIA 18 | EnableCompress : true # Compresses where applicable (currently only exefs:/.code) 19 | 20 | AccessControlInfo: 21 | CoreVersion : 2 22 | 23 | # Exheader Format Version 24 | DescVersion : 2 25 | 26 | # Minimum Required Kernel Version (below is for 4.5.0) 27 | ReleaseKernelMajor : "02" 28 | ReleaseKernelMinor : "33" 29 | 30 | # ExtData 31 | UseExtSaveData : false # enables ExtData 32 | #ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId 33 | 34 | # FS:USER Archive Access Permissions 35 | # Uncomment as required 36 | FileSystemAccess: 37 | - CategorySystemApplication 38 | - CategoryHardwareCheck 39 | - CategoryFileSystemTool 40 | - Debug 41 | - TwlCardBackup 42 | - TwlNandData 43 | - Boss 44 | - DirectSdmc 45 | - Core 46 | - CtrNandRo 47 | - CtrNandRw 48 | - CtrNandRoWrite 49 | - CategorySystemSettings 50 | - CardBoard 51 | - ExportImportIvs 52 | - DirectSdmcWrite 53 | - SwitchCleanup 54 | - SaveDataMove 55 | - Shop 56 | - Shell 57 | - CategoryHomeMenu 58 | - SeedDB 59 | IoAccessControl: 60 | - FsMountNand 61 | - FsMountNandRoWrite 62 | - FsMountTwln 63 | - FsMountWnand 64 | - FsMountCardSpi 65 | - UseSdif3 66 | - CreateSeed 67 | - UseCardSpi 68 | 69 | # Process Settings 70 | MemoryType : Application # Application/System/Base 71 | SystemMode : $(APP_SYSTEM_MODE) # 64MB(Default)/96MB/80MB/72MB/32MB 72 | IdealProcessor : 0 73 | AffinityMask : 1 74 | Priority : 16 75 | MaxCpu : 0x9E # Default 76 | HandleTableSize : 0x200 77 | DisableDebug : false 78 | EnableForceDebug : false 79 | CanWriteSharedPage : true 80 | CanUsePrivilegedPriority : false 81 | CanUseNonAlphabetAndNumber : true 82 | PermitMainFunctionArgument : true 83 | CanShareDeviceMemory : true 84 | RunnableOnSleep : false 85 | SpecialMemoryArrange : true 86 | 87 | # New3DS Exclusive Process Settings 88 | SystemModeExt : $(APP_SYSTEM_MODE_EXT) # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode 89 | CpuSpeed : $(APP_CPU_SPEED) # 268MHz(Default)/804MHz 90 | EnableL2Cache : true # false(default)/true 91 | CanAccessCore2 : true 92 | 93 | # Virtual Address Mappings 94 | IORegisterMapping: 95 | - 1ff00000-1ff7ffff # DSP memory 96 | MemoryMapping: 97 | - 1f000000-1f5fffff:r # VRAM 98 | 99 | # Accessible SVCs, : 100 | SystemCallAccess: 101 | ControlMemory: 1 102 | QueryMemory: 2 103 | ExitProcess: 3 104 | GetProcessAffinityMask: 4 105 | SetProcessAffinityMask: 5 106 | GetProcessIdealProcessor: 6 107 | SetProcessIdealProcessor: 7 108 | CreateThread: 8 109 | ExitThread: 9 110 | SleepThread: 10 111 | GetThreadPriority: 11 112 | SetThreadPriority: 12 113 | GetThreadAffinityMask: 13 114 | SetThreadAffinityMask: 14 115 | GetThreadIdealProcessor: 15 116 | SetThreadIdealProcessor: 16 117 | GetCurrentProcessorNumber: 17 118 | Run: 18 119 | CreateMutex: 19 120 | ReleaseMutex: 20 121 | CreateSemaphore: 21 122 | ReleaseSemaphore: 22 123 | CreateEvent: 23 124 | SignalEvent: 24 125 | ClearEvent: 25 126 | CreateTimer: 26 127 | SetTimer: 27 128 | CancelTimer: 28 129 | ClearTimer: 29 130 | CreateMemoryBlock: 30 131 | MapMemoryBlock: 31 132 | UnmapMemoryBlock: 32 133 | CreateAddressArbiter: 33 134 | ArbitrateAddress: 34 135 | CloseHandle: 35 136 | WaitSynchronization1: 36 137 | WaitSynchronizationN: 37 138 | SignalAndWait: 38 139 | DuplicateHandle: 39 140 | GetSystemTick: 40 141 | GetHandleInfo: 41 142 | GetSystemInfo: 42 143 | GetProcessInfo: 43 144 | GetThreadInfo: 44 145 | ConnectToPort: 45 146 | SendSyncRequest1: 46 147 | SendSyncRequest2: 47 148 | SendSyncRequest3: 48 149 | SendSyncRequest4: 49 150 | SendSyncRequest: 50 151 | OpenProcess: 51 152 | OpenThread: 52 153 | GetProcessId: 53 154 | GetProcessIdOfThread: 54 155 | GetThreadId: 55 156 | GetResourceLimit: 56 157 | GetResourceLimitLimitValues: 57 158 | GetResourceLimitCurrentValues: 58 159 | GetThreadContext: 59 160 | Break: 60 161 | OutputDebugString: 61 162 | ControlPerformanceCounter: 62 163 | CreatePort: 71 164 | CreateSessionToPort: 72 165 | CreateSession: 73 166 | AcceptSession: 74 167 | ReplyAndReceive1: 75 168 | ReplyAndReceive2: 76 169 | ReplyAndReceive3: 77 170 | ReplyAndReceive4: 78 171 | ReplyAndReceive: 79 172 | BindInterrupt: 80 173 | UnbindInterrupt: 81 174 | InvalidateProcessDataCache: 82 175 | StoreProcessDataCache: 83 176 | FlushProcessDataCache: 84 177 | StartInterProcessDma: 85 178 | StopDma: 86 179 | GetDmaState: 87 180 | RestartDma: 88 181 | DebugActiveProcess: 96 182 | BreakDebugProcess: 97 183 | TerminateDebugProcess: 98 184 | GetProcessDebugEvent: 99 185 | ContinueDebugEvent: 100 186 | GetProcessList: 101 187 | GetThreadList: 102 188 | GetDebugThreadContext: 103 189 | SetDebugThreadContext: 104 190 | QueryDebugProcessMemory: 105 191 | ReadProcessMemory: 106 192 | WriteProcessMemory: 107 193 | SetHardwareBreakPoint: 108 194 | GetDebugThreadParam: 109 195 | ControlProcessMemory: 112 196 | MapProcessMemory: 113 197 | UnmapProcessMemory: 114 198 | CreateCodeSet: 115 199 | CreateProcess: 117 200 | TerminateProcess: 118 201 | SetProcessResourceLimits: 119 202 | CreateResourceLimit: 120 203 | SetResourceLimitValues: 121 204 | AddCodeSegment: 122 205 | Backdoor: 123 206 | KernelSetState: 124 207 | QueryProcessMemory: 125 208 | 209 | # Service List 210 | # Maximum 34 services (32 if firmware is prior to 9.6.0) 211 | ServiceAccessControl: 212 | - APT:U 213 | - ac:u 214 | - act:u 215 | - am:net 216 | - boss:U 217 | - cam:u 218 | - cecd:u 219 | - cfg:nor 220 | - cfg:u 221 | - cfg:i 222 | - cfg:s 223 | - csnd:SND 224 | - dsp::DSP 225 | - fs:USER 226 | - gsp::Gpu 227 | - gsp::Lcd 228 | - hid:USER 229 | - http:C 230 | - ir:rst 231 | - ir:u 232 | - ir:USER 233 | - mcu::HWC 234 | - ndm:u 235 | - news:s 236 | - nim:u 237 | - nwm::EXT 238 | - nwm::UDS 239 | - ps:ps 240 | - ptm:sysm 241 | - ptm:u 242 | - pxi:dev 243 | - soc:U 244 | - ssl:C 245 | - y2r:u 246 | 247 | SystemControlInfo: 248 | SaveDataSize: 0KB # Change if the app uses savedata 249 | RemasterVersion: 1 250 | StackSize: 0x40000 251 | 252 | # Modules that run services listed above should be included below 253 | # Maximum 48 dependencies 254 | # : 255 | Dependency: 256 | ac: 0x0004013000002402 257 | #act: 0x0004013000003802 258 | am: 0x0004013000001502 259 | boss: 0x0004013000003402 260 | camera: 0x0004013000001602 261 | cecd: 0x0004013000002602 262 | cfg: 0x0004013000001702 263 | codec: 0x0004013000001802 264 | csnd: 0x0004013000002702 265 | dlp: 0x0004013000002802 266 | dsp: 0x0004013000001a02 267 | friends: 0x0004013000003202 268 | gpio: 0x0004013000001b02 269 | gsp: 0x0004013000001c02 270 | hid: 0x0004013000001d02 271 | http: 0x0004013000002902 272 | i2c: 0x0004013000001e02 273 | ir: 0x0004013000003302 274 | mcu: 0x0004013000001f02 275 | mic: 0x0004013000002002 276 | ndm: 0x0004013000002b02 277 | news: 0x0004013000003502 278 | #nfc: 0x0004013000004002 279 | nim: 0x0004013000002c02 280 | nwm: 0x0004013000002d02 281 | pdn: 0x0004013000002102 282 | ps: 0x0004013000003102 283 | ptm: 0x0004013000002202 284 | #qtm: 0x0004013020004202 285 | ro: 0x0004013000003702 286 | socket: 0x0004013000002e02 287 | spi: 0x0004013000002302 288 | ssl: 0x0004013000002f02 -------------------------------------------------------------------------------- /res/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/banner.png -------------------------------------------------------------------------------- /res/banner.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/banner.wav -------------------------------------------------------------------------------- /res/drawable/Roboto-Regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/Roboto-Regular.ttf -------------------------------------------------------------------------------- /res/drawable/battery_20.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_20.png -------------------------------------------------------------------------------- /res/drawable/battery_20_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_20_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_30.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_30.png -------------------------------------------------------------------------------- /res/drawable/battery_30_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_30_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_50.png -------------------------------------------------------------------------------- /res/drawable/battery_50_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_50_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_60.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_60.png -------------------------------------------------------------------------------- /res/drawable/battery_60_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_60_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_80.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_80.png -------------------------------------------------------------------------------- /res/drawable/battery_80_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_80_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_90.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_90.png -------------------------------------------------------------------------------- /res/drawable/battery_90_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_90_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_full.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_full.png -------------------------------------------------------------------------------- /res/drawable/battery_full_charging.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_full_charging.png -------------------------------------------------------------------------------- /res/drawable/battery_low.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_low.png -------------------------------------------------------------------------------- /res/drawable/battery_unknown.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/battery_unknown.png -------------------------------------------------------------------------------- /res/drawable/btn_material_light_toggle_off_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/btn_material_light_toggle_off_normal.png -------------------------------------------------------------------------------- /res/drawable/btn_material_light_toggle_on_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/btn_material_light_toggle_on_normal.png -------------------------------------------------------------------------------- /res/drawable/ic_arrow_back_normal.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/ic_arrow_back_normal.png -------------------------------------------------------------------------------- /res/drawable/sprites.t3s: -------------------------------------------------------------------------------- 1 | --atlas -f rgba -z auto 2 | battery_20.png 3 | battery_20_charging.png 4 | battery_30.png 5 | battery_30_charging.png 6 | battery_50.png 7 | battery_50_charging.png 8 | battery_60.png 9 | battery_60_charging.png 10 | battery_80.png 11 | battery_80_charging.png 12 | battery_90.png 13 | battery_90_charging.png 14 | battery_full.png 15 | battery_full_charging.png 16 | battery_low.png 17 | battery_unknown.png 18 | btn_material_light_toggle_off_normal.png 19 | btn_material_light_toggle_on_normal.png 20 | ic_arrow_back_normal.png 21 | stat_sys_wifi_signal_0.png 22 | stat_sys_wifi_signal_1.png 23 | stat_sys_wifi_signal_2.png 24 | stat_sys_wifi_signal_3.png 25 | 26 | -------------------------------------------------------------------------------- /res/drawable/stat_sys_wifi_signal_0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/stat_sys_wifi_signal_0.png -------------------------------------------------------------------------------- /res/drawable/stat_sys_wifi_signal_1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/stat_sys_wifi_signal_1.png -------------------------------------------------------------------------------- /res/drawable/stat_sys_wifi_signal_2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/stat_sys_wifi_signal_2.png -------------------------------------------------------------------------------- /res/drawable/stat_sys_wifi_signal_3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/drawable/stat_sys_wifi_signal_3.png -------------------------------------------------------------------------------- /res/ic_launcher_recovery_tool.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/ic_launcher_recovery_tool.png -------------------------------------------------------------------------------- /res/logo.bcma.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/joel16/3DS-Recovery-Tool/531be8a812537b310043fcde380241c5f64fe115/res/logo.bcma.lz -------------------------------------------------------------------------------- /source/c2d_helper.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #include "c2d_helper.h" 4 | 5 | C3D_RenderTarget *RENDER_TOP, *RENDER_BOTTOM; 6 | C2D_TextBuf c2d_static_buf, c2d_dynamic_buf, c2d_size_buf; 7 | C2D_Font font; 8 | 9 | void Draw_EndFrame(void) { 10 | C2D_TextBufClear(c2d_dynamic_buf); 11 | C2D_TextBufClear(c2d_size_buf); 12 | C3D_FrameEnd(0); 13 | } 14 | 15 | void Draw_Text(float x, float y, float size, Colour colour, const char *text) { 16 | C2D_Text c2d_text; 17 | C2D_TextFontParse(&c2d_text, font, c2d_dynamic_buf, text); 18 | C2D_TextOptimize(&c2d_text); 19 | C2D_DrawText(&c2d_text, C2D_WithColor, x, y, 0.5f, size, size, colour); 20 | } 21 | 22 | void Draw_Textf(float x, float y, float size, Colour colour, const char* text, ...) { 23 | char buffer[256]; 24 | va_list args; 25 | va_start(args, text); 26 | vsnprintf(buffer, 256, text, args); 27 | Draw_Text(x, y, size, colour, buffer); 28 | va_end(args); 29 | } 30 | 31 | void Draw_GetTextSize(float size, float *width, float *height, const char *text) { 32 | C2D_Text c2d_text; 33 | C2D_TextFontParse(&c2d_text, font, c2d_size_buf, text); 34 | C2D_TextGetDimensions(&c2d_text, size, size, width, height); 35 | } 36 | 37 | float Draw_GetTextWidth(float size, const char *text) { 38 | float width = 0; 39 | Draw_GetTextSize(size, &width, NULL, text); 40 | return width; 41 | } 42 | 43 | float Draw_GetTextHeight(float size, const char *text) { 44 | float height = 0; 45 | Draw_GetTextSize(size, NULL, &height, text); 46 | return height; 47 | } 48 | 49 | bool Draw_Rect(float x, float y, float w, float h, Colour colour) { 50 | return C2D_DrawRectSolid(x, y, 0.5f, w, h, colour); 51 | } 52 | 53 | bool Draw_Image(C2D_Image image, float x, float y) { 54 | return C2D_DrawImageAt(image, x, y, 0.5f, NULL, 1.0f, 1.0f); 55 | } 56 | -------------------------------------------------------------------------------- /source/dialog.c: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | 3 | #include "c2d_helper.h" 4 | #include "utils.h" 5 | 6 | Result Dialog_Draw(const char *top_message, const char *bottom_message) { 7 | Result ret = 0; 8 | 9 | float top_width = Draw_GetTextWidth(0.6f, top_message); 10 | float top_height = Draw_GetTextHeight(0.6f, top_message); 11 | 12 | float bottom_width = Draw_GetTextWidth(0.6f, bottom_message); 13 | float bottom_height = Draw_GetTextHeight(0.6f, bottom_message); 14 | 15 | touchPosition touch; 16 | 17 | while (aptMainLoop()) { 18 | C3D_FrameBegin(C3D_FRAME_SYNCDRAW); 19 | C2D_SceneBegin(RENDER_TOP); 20 | Draw_Rect(0, 0, 400, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 21 | Draw_Text(((400 - top_width) / 2), (((240 - top_height) / 2) - 20), 0.6f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, top_message); 22 | Draw_Text(((400 - bottom_width) / 2), (((240 - bottom_height) / 2) + 20), 0.6f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, bottom_message); 23 | 24 | C2D_SceneBegin(RENDER_BOTTOM); 25 | Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 26 | Draw_Text(((160 - Draw_GetTextWidth(0.5f, "CANCEL")) / 2), (220 - Draw_GetTextHeight(0.5f, "CANCEL")), 0.5f, C2D_Color32(0, 151, 136, 255), "CANCEL"); 27 | Draw_Text((((160 - Draw_GetTextWidth(0.5f, "OK")) / 2) + 160), (220 - Draw_GetTextHeight(0.5f, "OK")), 0.5f, C2D_Color32(0, 151, 136, 255), "OK"); 28 | 29 | Draw_EndFrame(); 30 | 31 | hidScanInput(); 32 | hidTouchRead(&touch); 33 | u32 kDown = hidKeysDown(); 34 | 35 | if ((kDown & KEY_A) || ((touchInRect(160, 190, 320, 240)) && (kDown & KEY_TOUCH))) { 36 | ret = 1; 37 | break; 38 | } 39 | else if ((kDown & KEY_B) || ((touchInRect(0, 190, 159, 240)) && (kDown & KEY_TOUCH))) { 40 | ret = -1; 41 | break; 42 | } 43 | } 44 | 45 | return ret; 46 | } 47 | -------------------------------------------------------------------------------- /source/fs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include "fs.h" 6 | 7 | FS_Archive sdmc_archive, nand_archive; 8 | 9 | Result FS_OpenArchive(FS_Archive *archive, FS_ArchiveID archiveID) { 10 | Result ret = 0; 11 | 12 | if (R_FAILED(ret = FSUSER_OpenArchive(archive, archiveID, fsMakePath(PATH_EMPTY, "")))) 13 | return ret; 14 | 15 | return 0; 16 | } 17 | 18 | Result FS_CloseArchive(FS_Archive archive) { 19 | Result ret = 0; 20 | 21 | if (R_FAILED(ret = FSUSER_CloseArchive(archive))) 22 | return ret; 23 | 24 | return 0; 25 | } 26 | 27 | Result FS_MakeDir(FS_Archive archive, const char *path) { 28 | Result ret = 0; 29 | 30 | if (R_FAILED(ret = FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, path), 0))) 31 | return ret; 32 | 33 | return 0; 34 | } 35 | 36 | Result FS_RecursiveMakeDir(FS_Archive archive, const char *path) { 37 | Result ret = 0; 38 | char buf[256]; 39 | char *p = NULL; 40 | size_t len; 41 | 42 | snprintf(buf, sizeof(buf), "%s", path); 43 | len = strlen(buf); 44 | 45 | if (buf[len - 1] == '/') 46 | buf[len - 1] = 0; 47 | 48 | for (p = buf + 1; *p; p++) { 49 | if (*p == '/') { 50 | *p = 0; 51 | 52 | if (!FS_DirExists(archive, buf)) 53 | ret = FS_MakeDir(archive, buf); 54 | 55 | *p = '/'; 56 | } 57 | 58 | if (!FS_DirExists(archive, buf)) 59 | ret = FS_MakeDir(archive, buf); 60 | } 61 | 62 | return ret; 63 | } 64 | 65 | bool FS_FileExists(FS_Archive archive, const char *path) { 66 | Handle handle; 67 | 68 | if (R_FAILED(FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0))) 69 | return false; 70 | 71 | if (R_FAILED(FSFILE_Close(handle))) 72 | return false; 73 | 74 | return true; 75 | } 76 | 77 | bool FS_DirExists(FS_Archive archive, const char *path) { 78 | Handle handle; 79 | 80 | if (R_FAILED(FSUSER_OpenDirectory(&handle, archive, fsMakePath(PATH_ASCII, path)))) 81 | return false; 82 | 83 | if (R_FAILED(FSDIR_Close(handle))) 84 | return false; 85 | 86 | return true; 87 | } 88 | 89 | Result FS_GetFileSize(FS_Archive archive, const char *path, u64 *size) { 90 | Result ret = 0; 91 | Handle handle; 92 | 93 | if (R_FAILED(ret = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0))) 94 | return ret; 95 | 96 | if (R_FAILED(ret = FSFILE_GetSize(handle, size))) { 97 | FSFILE_Close(handle); 98 | return ret; 99 | } 100 | 101 | if (R_FAILED(ret = FSFILE_Close(handle))) 102 | return ret; 103 | 104 | return 0; 105 | } 106 | 107 | static Result FS_RemoveFile(FS_Archive archive, const char *path) { 108 | Result ret = 0; 109 | 110 | if (R_FAILED(ret = FSUSER_DeleteFile(archive, fsMakePath(PATH_ASCII, path)))) 111 | return ret; 112 | 113 | return 0; 114 | } 115 | 116 | Result FS_Write(FS_Archive archive, const char *path, const void *buf, u32 size) { 117 | Result ret = 0; 118 | Handle handle; 119 | u32 bytes_written = 0; 120 | 121 | if (FS_FileExists(archive, path)) { 122 | if (R_FAILED(ret = FS_RemoveFile(archive, path))) 123 | return ret; 124 | } 125 | 126 | if (R_FAILED(ret = FSUSER_CreateFile(archive, fsMakePath(PATH_ASCII, path), 0, size))) 127 | return ret; 128 | 129 | if (R_FAILED(ret = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_WRITE, 0))) 130 | return ret; 131 | 132 | if (R_FAILED(ret = FSFILE_Write(handle, &bytes_written, 0, buf, size, FS_WRITE_FLUSH))) { 133 | FSFILE_Close(handle); 134 | return ret; 135 | } 136 | 137 | if (R_FAILED(ret = FSFILE_Close(handle))) 138 | return ret; 139 | 140 | return 0; 141 | } 142 | 143 | Result FS_CopyFile(FS_Archive src_archive, FS_Archive dest_archive, char *src_path, char *dest_path) { 144 | Handle src_handle, dst_handle; 145 | Result ret = 0; 146 | 147 | if (R_FAILED(ret = FSUSER_OpenFile(&src_handle, src_archive, fsMakePath(PATH_ASCII, src_path), FS_OPEN_READ, 0))) 148 | return ret; 149 | 150 | if (R_FAILED(ret = FSUSER_OpenFile(&dst_handle, dest_archive, fsMakePath(PATH_ASCII, dest_path), FS_OPEN_CREATE | FS_OPEN_WRITE, 0))) { 151 | FSFILE_Close(src_handle); 152 | return ret; 153 | } 154 | 155 | u32 bytes_read = 0; 156 | u64 offset = 0, size = 0; 157 | size_t buf_size = 0x10000; 158 | u8 *buf = malloc(buf_size); // Chunk size 159 | FS_GetFileSize(src_archive, src_path, &size); 160 | 161 | do { 162 | memset(buf, 0, buf_size); 163 | 164 | if (R_FAILED(ret = FSFILE_Read(src_handle, &bytes_read, offset, buf, buf_size))) { 165 | free(buf); 166 | FSFILE_Close(src_handle); 167 | FSFILE_Close(dst_handle); 168 | return ret; 169 | } 170 | if (R_FAILED(ret = FSFILE_Write(dst_handle, NULL, offset, buf, bytes_read, FS_WRITE_FLUSH))) { 171 | free(buf); 172 | FSFILE_Close(src_handle); 173 | FSFILE_Close(dst_handle); 174 | return ret; 175 | } 176 | 177 | offset += bytes_read; 178 | } 179 | while(offset < size); 180 | 181 | free(buf); 182 | FSFILE_Close(src_handle); 183 | FSFILE_Close(dst_handle); 184 | return 0; 185 | } 186 | -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | #include <3ds.h> 6 | 7 | #include "c2d_helper.h" 8 | #include "dialog.h" 9 | #include "fs.h" 10 | #include "status_bar.h" 11 | #include "textures.h" 12 | #include "utils.h" 13 | 14 | #define DISTANCE_Y 30 15 | #define LIST_PER_PAGE 6 16 | 17 | static jmp_buf exitJmp; 18 | static int selection = 0; 19 | 20 | static bool Utils_IsN3DS(void) { 21 | bool isNew3DS = false; 22 | 23 | if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS))) 24 | return isNew3DS; 25 | 26 | return false; 27 | } 28 | 29 | static void Init_Services(void) { 30 | amInit(); 31 | cfguInit(); 32 | mcuHwcInit(); 33 | FS_OpenArchive(&sdmc_archive, ARCHIVE_SDMC); 34 | FS_OpenArchive(&nand_archive, ARCHIVE_NAND_CTR_FS); 35 | 36 | romfsInit(); 37 | gfxInitDefault(); 38 | C3D_Init(C3D_DEFAULT_CMDBUF_SIZE); 39 | C2D_Init(C2D_DEFAULT_MAX_OBJECTS); 40 | C2D_Prepare(); 41 | 42 | if (Utils_IsN3DS()) 43 | osSetSpeedupEnable(true); 44 | 45 | c2d_static_buf = C2D_TextBufNew(4096); 46 | c2d_dynamic_buf = C2D_TextBufNew(4096); 47 | c2d_size_buf = C2D_TextBufNew(4096); 48 | font = C2D_FontLoad("romfs:/res/drawable/Roboto-Regular.bcfnt"); 49 | 50 | RENDER_TOP = C2D_CreateScreenTarget(GFX_TOP, GFX_LEFT); 51 | RENDER_BOTTOM = C2D_CreateScreenTarget(GFX_BOTTOM, GFX_LEFT); 52 | 53 | Textures_Load(); 54 | 55 | FS_RecursiveMakeDir(sdmc_archive, "/3ds/3DSRecoveryTool/dumps"); 56 | FS_RecursiveMakeDir(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/ro/sys"); 57 | FS_RecursiveMakeDir(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys"); 58 | FS_RecursiveMakeDir(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/private"); 59 | 60 | Utils_LoadConfig(); 61 | } 62 | 63 | static void Term_Services(void) { 64 | Textures_Free(); 65 | 66 | C2D_FontFree(font); 67 | C2D_TextBufDelete(c2d_size_buf); 68 | C2D_TextBufDelete(c2d_dynamic_buf); 69 | C2D_TextBufDelete(c2d_static_buf); 70 | 71 | if (Utils_IsN3DS()) 72 | osSetSpeedupEnable(0); 73 | 74 | C2D_Fini(); 75 | C3D_Fini(); 76 | gfxExit(); 77 | romfsExit(); 78 | 79 | FS_CloseArchive(nand_archive); 80 | FS_CloseArchive(sdmc_archive); 81 | mcuHwcExit(); 82 | cfguExit(); 83 | amExit(); 84 | } 85 | 86 | static void Menu_DrawUI(int *selection, int max_items, const char *item_list[], const char *title, bool main) { 87 | C3D_FrameBegin(C3D_FRAME_SYNCDRAW); 88 | C2D_TargetClear(RENDER_TOP, C2D_Color32(19, 23, 26, 255)); 89 | C2D_TargetClear(RENDER_BOTTOM, C2D_Color32(39, 50, 56, 255)); 90 | C2D_SceneBegin(RENDER_TOP); 91 | 92 | Draw_Rect(0, 0, 400, 18, C2D_Color32(19, 23, 26, 255)); 93 | Draw_Rect(0, 18, 400, 38, C2D_Color32(39, 50, 56, 255)); 94 | Draw_Rect(0, 55, 400, 185, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 95 | 96 | StatusBar_DisplayBar(); 97 | 98 | if (main) 99 | Draw_Text(10, 27, 0.5f, C2D_Color32(240, 242, 242, 255), title); 100 | else { 101 | Draw_Image(icon_back, 5, 22); 102 | Draw_Text(30 + 10, 27, 0.5f, C2D_Color32(240, 242, 242, 255), title); 103 | } 104 | 105 | int printed = 0; 106 | for (int i = 0; i < max_items + 1; i++) { 107 | if (printed == LIST_PER_PAGE) 108 | break; 109 | 110 | if (*selection < LIST_PER_PAGE || i > (*selection - LIST_PER_PAGE)) { 111 | if (i == *selection) 112 | Draw_Rect(0, 55 + (DISTANCE_Y * printed), 400, 30, dark_theme? SELECTOR_COLOUR_DARK : SELECTOR_COLOUR_LIGHT); 113 | 114 | Draw_Text(10, 62 + (DISTANCE_Y * printed), 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, item_list[i]); 115 | printed++; 116 | } 117 | } 118 | } 119 | 120 | static void Menu_HandleControls(u32 *kDown, int max_items) { 121 | hidScanInput(); 122 | *kDown = hidKeysDown(); 123 | 124 | if (*kDown & KEY_START) 125 | longjmp(exitJmp, 1); 126 | 127 | if (*kDown & KEY_DDOWN) 128 | selection++; 129 | else if (*kDown & KEY_DUP) 130 | selection--; 131 | 132 | Utils_SetMax(&selection, 0, max_items); 133 | Utils_SetMin(&selection, max_items, 0); 134 | } 135 | 136 | static void Menu_Backup(void) { 137 | Result ret = 0; 138 | selection = 0; 139 | int max_items = 4; 140 | bool is_selected = false; 141 | char func[50]; 142 | const char *item_list[] = { 143 | "Back", 144 | "Backup NAND LocalFriendCodeSeed", 145 | "Backup NAND SecureInfo", 146 | "Backup moveable.sed", 147 | "Backup HWCAL" 148 | }; 149 | 150 | while (aptMainLoop()) { 151 | Menu_DrawUI(&selection, max_items, item_list, "Backup", false); 152 | 153 | C2D_SceneBegin(RENDER_BOTTOM); 154 | Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 155 | 156 | if (R_FAILED(ret)) 157 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "Backup %s failed with err 0x%08x.", func, (unsigned int)ret); 158 | else if ((R_SUCCEEDED(ret)) && (is_selected)) 159 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "%s backed-up successfully.", func); 160 | 161 | Draw_EndFrame(); 162 | 163 | u32 kDown = 0; 164 | Menu_HandleControls(&kDown, max_items); 165 | 166 | if (kDown & KEY_A) { 167 | if (selection == 0) 168 | break; 169 | 170 | switch(selection) { 171 | case 1: 172 | if (FS_FileExists(nand_archive, "/rw/sys/LocalFriendCodeSeed_B")) 173 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/rw/sys/LocalFriendCodeSeed_B", "/3ds/3DSRecoveryTool/backups/nand/rw/sys/LocalFriendCodeSeed_B"); 174 | else if (FS_FileExists(nand_archive, "/rw/sys/LocalFriendCodeSeed_A")) 175 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/rw/sys/LocalFriendCodeSeed_A", "/3ds/3DSRecoveryTool/backups/nand/rw/sys/LocalFriendCodeSeed_A"); 176 | 177 | snprintf(func, 20, "LocalFriendCodeSeed"); 178 | break; 179 | 180 | case 2: 181 | if (FS_FileExists(nand_archive, "/rw/sys/SecureInfo_C")) 182 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/rw/sys/SecureInfo_C", "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_C"); 183 | if (FS_FileExists(nand_archive, "/rw/sys/SecureInfo_A")) 184 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/rw/sys/SecureInfo_A", "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_A"); 185 | else if (FS_FileExists(nand_archive, "/rw/sys/SecureInfo_B")) 186 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/rw/sys/SecureInfo_B", "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_B"); 187 | 188 | snprintf(func, 11, "SecureInfo"); 189 | break; 190 | 191 | case 3: 192 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/private/movable.sed", "/3ds/3DSRecoveryTool/backups/nand/private/movable.sed"); 193 | snprintf(func, 12, "movable.sed"); 194 | break; 195 | 196 | case 4: 197 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/ro/sys/HWCAL0.dat", "/3ds/3DSRecoveryTool/backups/nand/ro/sys/HWCAL0.dat"); 198 | ret = FS_CopyFile(nand_archive, sdmc_archive, "/ro/sys/HWCAL1.dat", "/3ds/3DSRecoveryTool/backups/nand/ro/sys/HWCAL1.dat"); 199 | snprintf(func, 6, "HWCAL"); 200 | break; 201 | } 202 | 203 | is_selected = true; 204 | selection = 0; 205 | } 206 | else if (kDown & KEY_B) 207 | break; 208 | } 209 | } 210 | 211 | static void Menu_Restore(void) { 212 | Result ret = 0; 213 | selection = 0; 214 | int max_items = 4; 215 | bool is_selected = false; 216 | char func[50]; 217 | const char *item_list[] = { 218 | "Back", 219 | "Restore original LocalFriendCodeSeed", 220 | "Restore original SecureInfo", 221 | "Restore backup LocalFriendCodeSeed", 222 | "Restore backup SecureInfo" 223 | }; 224 | 225 | while (aptMainLoop()) { 226 | Menu_DrawUI(&selection, max_items, item_list, "Restore", false); 227 | 228 | C2D_SceneBegin(RENDER_BOTTOM); 229 | Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 230 | 231 | if (R_FAILED(ret)) 232 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "Restore %s failed with err 0x%08x.", func, (unsigned int)ret); 233 | else if ((R_SUCCEEDED(ret)) && (is_selected)) 234 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "%s restored successful.", func); 235 | 236 | Draw_EndFrame(); 237 | 238 | u32 kDown = 0; 239 | Menu_HandleControls(&kDown, max_items); 240 | 241 | if (kDown & KEY_A) { 242 | if (selection == 0) 243 | break; 244 | 245 | switch(selection) { 246 | case 1: 247 | ret = CFGI_RestoreLocalFriendCodeSeed(); 248 | snprintf(func, 20, "LocalFriendCodeSeed"); 249 | break; 250 | 251 | case 2: 252 | ret = CFGI_RestoreSecureInfo(); 253 | snprintf(func, 11, "SecureInfo"); 254 | 255 | case 3: 256 | if (FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/LocalFriendCodeSeed_B")) 257 | ret = FS_CopyFile(sdmc_archive, nand_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/LocalFriendCodeSeed_B", "/rw/sys/LocalFriendCodeSeed_B"); 258 | else if (FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/LocalFriendCodeSeed_A")) 259 | ret = FS_CopyFile(sdmc_archive, nand_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/LocalFriendCodeSeed_A", "/rw/sys/LocalFriendCodeSeed_A"); 260 | 261 | snprintf(func, 20, "LocalFriendCodeSeed"); 262 | break; 263 | 264 | case 4: 265 | if (FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_C")) 266 | ret = FS_CopyFile(sdmc_archive, nand_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_C", "/rw/sys/SecureInfo_C"); 267 | if (FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_A")) 268 | ret = FS_CopyFile(sdmc_archive, nand_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_A", "/rw/sys/SecureInfo_A"); 269 | else if (FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_B")) 270 | ret = FS_CopyFile(sdmc_archive, nand_archive, "/3ds/3DSRecoveryTool/backups/nand/rw/sys/SecureInfo_B", "/rw/sys/SecureInfo_B"); 271 | 272 | snprintf(func, 11, "SecureInfo"); 273 | break; 274 | } 275 | 276 | is_selected = true; 277 | selection = 0; 278 | } 279 | else if (kDown & KEY_B) 280 | break; 281 | } 282 | } 283 | 284 | static void Menu_Advanced_Wipe(void) { 285 | Result ret = 0; 286 | selection = 0; 287 | int max_items = 9; 288 | bool is_selected = false; 289 | char func[50]; 290 | const char *item_list[] = { 291 | "Back", 292 | "Wipe all temporary and expired titles", 293 | "Wipe all TWL titles", 294 | "Wipe all pending titles", 295 | "Wipe all demo launch infos", 296 | "Wipe config", 297 | "Wipe parental controls", 298 | "Wipe all data (NAND)", 299 | "Format SDMC root", 300 | "Format NAND ext savedata" 301 | }; 302 | 303 | while (aptMainLoop()) { 304 | Menu_DrawUI(&selection, max_items, item_list, "Advanced Wipe", false); 305 | 306 | C2D_SceneBegin(RENDER_BOTTOM); 307 | Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 308 | 309 | if (R_FAILED(ret)) 310 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "Wipe %s failed with err 0x%08x.", func, (unsigned int)ret); 311 | else if ((R_SUCCEEDED(ret)) && (is_selected)) 312 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "Wiped %s successful.", func); 313 | 314 | Draw_EndFrame(); 315 | 316 | u32 kDown = 0; 317 | Menu_HandleControls(&kDown, max_items); 318 | 319 | if (kDown & KEY_A) { 320 | if (selection == 0) 321 | break; 322 | 323 | switch(selection) { 324 | case 1: 325 | if (R_SUCCEEDED(Dialog_Draw("You will lose all expired titles.", "Do you wish to continue?"))) { 326 | ret = AM_DeleteAllTemporaryTitles(); 327 | ret = AM_DeleteAllExpiredTitles(MEDIATYPE_SD); 328 | snprintf(func, 27, "temporary & expired titles"); 329 | } 330 | break; 331 | 332 | case 2: 333 | if (R_SUCCEEDED(Dialog_Draw("You will lose all TWL titles.", "Do you wish to continue?"))) { 334 | ret = AM_DeleteAllTwlTitles(); 335 | snprintf(func, 11, "TWL titles"); 336 | } 337 | break; 338 | 339 | case 3: 340 | if (R_SUCCEEDED(Dialog_Draw("You will lose all pending tiles.", "Do you wish to continue?"))) { 341 | ret = AM_DeleteAllPendingTitles(MEDIATYPE_NAND); 342 | ret = AM_DeleteAllPendingTitles(MEDIATYPE_SD); 343 | snprintf(func, 14, "pending tiles"); 344 | } 345 | break; 346 | 347 | case 4: 348 | if (R_SUCCEEDED(Dialog_Draw("You will lose all demo launch infos.", "Do you wish to continue?"))) { 349 | ret = AM_DeleteAllDemoLaunchInfos(); 350 | snprintf(func, 18, "demo launch infos"); 351 | } 352 | break; 353 | 354 | case 5: 355 | if (R_SUCCEEDED(Dialog_Draw("You will lose all data in Settings.", "Do you wish to continue?"))) { 356 | ret = CFGI_FormatConfig(); 357 | snprintf(func, 7, "config"); 358 | } 359 | break; 360 | 361 | case 6: 362 | if (R_SUCCEEDED(Dialog_Draw("This will disable parental controls.", "Do you wish to continue?"))) { 363 | ret = CFGI_ClearParentalControls(); 364 | snprintf(func, 18, "parental controls"); 365 | } 366 | break; 367 | 368 | case 7: 369 | if (R_SUCCEEDED(Dialog_Draw("You will lose ALL data.", "Do you wish to continue?"))) { 370 | ret = FSUSER_DeleteAllExtSaveDataOnNand(); 371 | ret = FSUSER_InitializeCtrFileSystem(); 372 | snprintf(func, 9, "all data"); 373 | } 374 | break; 375 | 376 | case 8: 377 | if (R_SUCCEEDED(Dialog_Draw("You will lose ALL data in your SD.", "Do you wish to continue?"))) { 378 | ret = FSUSER_DeleteSdmcRoot(); 379 | snprintf(func, 5, "SDMC"); 380 | } 381 | break; 382 | 383 | case 9: 384 | if (R_SUCCEEDED(Dialog_Draw("You will lose ALL ext savedata in nand.", "Do you wish to continue?"))) { 385 | ret = FSUSER_DeleteAllExtSaveDataOnNand(); 386 | snprintf(func, 18, "NAND ext savedata"); 387 | } 388 | } 389 | 390 | is_selected = true; 391 | selection = 0; 392 | } 393 | else if (kDown & KEY_B) 394 | break; 395 | } 396 | } 397 | 398 | static void Menu_Misc(void) { 399 | Result ret = 0; 400 | selection = 0; 401 | int max_items = 5; 402 | bool is_selected = false; 403 | char func[50]; 404 | const char *item_list[] = { 405 | "Back", 406 | "Dump original LocalFriendCodeSeed data", 407 | "Dump original SecureInfo data", 408 | "Verify LocalFriendCodeSeed sig", 409 | "Verify SecureInfo sig", 410 | "Dark theme" 411 | }; 412 | 413 | u8 lfcs_data[0x110], sig_data[0x100], secureinfo_data[0x11], secureinfo_sig_data[0x111]; 414 | 415 | while (aptMainLoop()) { 416 | Menu_DrawUI(&selection, max_items, item_list, "Miscellaneous", false); 417 | dark_theme? Draw_Image(icon_toggle_on, 350, 205) : Draw_Image(icon_toggle_off, 350, 205); 418 | 419 | C2D_SceneBegin(RENDER_BOTTOM); 420 | Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 421 | 422 | if (R_FAILED(ret)) 423 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "%s failed with err 0x%08x.", func, (unsigned int)ret); 424 | else if ((R_SUCCEEDED(ret)) && (is_selected)) 425 | Draw_Textf(10, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "%s successful.", func); 426 | 427 | Draw_EndFrame(); 428 | 429 | u32 kDown = 0; 430 | Menu_HandleControls(&kDown, max_items); 431 | 432 | if (kDown & KEY_A) { 433 | if (selection == 0) 434 | break; 435 | 436 | switch(selection) { 437 | case 1: 438 | if (R_SUCCEEDED(ret = CFGI_GetLocalFriendCodeSeedData(lfcs_data))) { 439 | if (FS_FileExists(nand_archive, "/rw/sys/LocalFriendCodeSeed_B")) 440 | ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/dumps/LocalFriendCodeSeed_B", lfcs_data, 0x110); 441 | else if (FS_FileExists(nand_archive, "/rw/sys/LocalFriendCodeSeed_A")) 442 | ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/dumps/LocalFriendCodeSeed_A", lfcs_data, 0x110); 443 | } 444 | 445 | snprintf(func, 25, "LocalFriendCodeSeed dump"); 446 | selection = 0; 447 | is_selected = true; 448 | break; 449 | 450 | case 2: 451 | if (R_SUCCEEDED(ret = CFGI_GetSecureInfoSignature(sig_data)) && R_SUCCEEDED(ret = CFGI_GetSecureInfoData(secureinfo_data))) { 452 | memcpy(&secureinfo_sig_data[0x0], sig_data, 0x100); 453 | memcpy(&secureinfo_sig_data[0x100], secureinfo_data, 0x11); 454 | 455 | if (FS_FileExists(nand_archive, "/rw/sys/SecureInfo_C")) 456 | ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/dumps/SecureInfo_C", secureinfo_sig_data, 0x111); 457 | else if (FS_FileExists(nand_archive, "/rw/sys/SecureInfo_A")) 458 | ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/dumps/SecureInfo_A", secureinfo_sig_data, 0x111); 459 | else if (FS_FileExists(nand_archive, "/rw/sys/SecureInfo_B")) 460 | ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/dumps/SecureInfo_B", secureinfo_sig_data, 0x111); 461 | } 462 | 463 | snprintf(func, 25, "SecureInfo dump"); 464 | selection = 0; 465 | is_selected = true; 466 | break; 467 | 468 | case 3: 469 | ret = CFGI_VerifySigLocalFriendCodeSeed(); 470 | snprintf(func, 33, "LocalFriendCodeSeed verification"); 471 | selection = 0; 472 | is_selected = true; 473 | break; 474 | 475 | case 4: 476 | ret = CFGI_VerifySigSecureInfo(); 477 | snprintf(func, 24, "SecureInfo verification"); 478 | selection = 0; 479 | is_selected = true; 480 | break; 481 | 482 | case 5: 483 | if (dark_theme == false) 484 | dark_theme = true; 485 | else 486 | dark_theme = false; 487 | Utils_SaveConfig(dark_theme); 488 | break; 489 | } 490 | } 491 | else if (kDown & KEY_B) 492 | break; 493 | } 494 | } 495 | 496 | static void Menu_Main(void) { 497 | selection = 0; 498 | int max_items = 4; 499 | const char *item_list[] = { 500 | "Back-up", 501 | "Restore", 502 | "Advanced wipe", 503 | "Misc", 504 | "Exit" 505 | }; 506 | 507 | while (aptMainLoop()) { 508 | Menu_DrawUI(&selection, max_items, item_list, "3DS Recovery Tool", true); 509 | 510 | C2D_SceneBegin(RENDER_BOTTOM); 511 | Draw_Rect(0, 0, 320, 240, dark_theme? BG_COLOUR_DARK : BG_COLOUR_LIGHT); 512 | Draw_Textf(5, 220, 0.45f, dark_theme? TEXT_COLOUR_DARK : TEXT_COLOUR_LIGHT, "3DS Recovery Tool v%d.%d%d", VERSION_MAJOR, VERSION_MINOR, VERSION_MICRO); 513 | 514 | Draw_EndFrame(); 515 | 516 | u32 kDown = 0; 517 | Menu_HandleControls(&kDown, max_items); 518 | 519 | if (kDown & KEY_A) { 520 | switch(selection) { 521 | case 0: 522 | Menu_Backup(); 523 | break; 524 | 525 | case 1: 526 | Menu_Restore(); 527 | break; 528 | 529 | case 2: 530 | Menu_Advanced_Wipe(); 531 | break; 532 | 533 | case 3: 534 | Menu_Misc(); 535 | break; 536 | 537 | case 4: 538 | longjmp(exitJmp, 1); 539 | break; 540 | } 541 | } 542 | } 543 | } 544 | 545 | int main(int argc, char **argv) { 546 | Init_Services(); 547 | if (setjmp(exitJmp)) { 548 | Term_Services(); 549 | return 0; 550 | } 551 | 552 | Menu_Main(); 553 | Term_Services(); 554 | 555 | return 0; 556 | } 557 | -------------------------------------------------------------------------------- /source/status_bar.c: -------------------------------------------------------------------------------- 1 | #include <3ds.h> 2 | #include 3 | 4 | #include "c2d_helper.h" 5 | #include "status_bar.h" 6 | #include "textures.h" 7 | 8 | static char *Clock_GetCurrentTime(void) { 9 | time_t t = time(0); 10 | int hour = localtime(&t)->tm_hour % 12; 11 | int min = localtime(&t)->tm_min; 12 | int AmPm = localtime(&t)->tm_hour / 12; 13 | 14 | static char buffer[27]; 15 | snprintf(buffer, 27, "%2i:%02i %s", (hour == 0)? 12 : hour, min, AmPm? "PM" : "AM"); 16 | return buffer; 17 | } 18 | 19 | static void StatusBar_GetBatteryStatus(int x, int y, float *percent_width) { 20 | u8 percent = 0, state = 0; 21 | char buf[5]; 22 | 23 | if (R_FAILED(PTMU_GetBatteryChargeState(&state))) 24 | state = 0; 25 | 26 | if (R_SUCCEEDED(MCUHWC_GetBatteryLevel(&percent))) { 27 | if (percent < 20) 28 | Draw_Image(battery_low, x, 1); 29 | else if ((percent >= 20) && (percent < 30)) 30 | Draw_Image(state == 1? battery_20_charging : battery_20, x, 1); 31 | else if ((percent >= 30) && (percent < 50)) 32 | Draw_Image(state == 1? battery_50_charging : battery_50, x, 1); 33 | else if ((percent >= 50) && (percent < 60)) 34 | Draw_Image(state == 1? battery_50_charging : battery_50, x, 1); 35 | else if ((percent >= 60) && (percent < 80)) 36 | Draw_Image(state == 1? battery_60_charging : battery_60, x, 1); 37 | else if ((percent >= 80) && (percent < 90)) 38 | Draw_Image(state == 1? battery_80_charging : battery_80, x, 1); 39 | else if ((percent >= 90) && (percent < 100)) 40 | Draw_Image(state == 1? battery_90_charging : battery_90, x, 1); 41 | else if (percent == 100) 42 | Draw_Image(state == 1? battery_full_charging : battery_full, x, 1); 43 | 44 | snprintf(buf, 5, "%d%%", percent); 45 | *percent_width = Draw_GetTextWidth(0.45f, buf); 46 | Draw_Text((float)(x - *percent_width - 5), y - 1, 0.4f, WHITE, buf); 47 | } 48 | else { 49 | snprintf(buf, 5, "%d%%", percent); 50 | *percent_width = Draw_GetTextWidth(0.45f, buf); 51 | Draw_Text((float)(x - *percent_width - 5), y - 1, 0.4f, WHITE, buf); 52 | Draw_Image(battery_unknown, x, 1); 53 | } 54 | } 55 | 56 | static void StatusBar_GetWifiStatus(int x) { 57 | switch(osGetWifiStrength()) { 58 | case 0: 59 | Draw_Image(icon_wifi_0, x, 2); 60 | break; 61 | case 1: 62 | Draw_Image(icon_wifi_1, x, 2); 63 | break; 64 | case 2: 65 | Draw_Image(icon_wifi_2, x, 2); 66 | break; 67 | case 3: 68 | Draw_Image(icon_wifi_3, x, 2); 69 | break; 70 | } 71 | } 72 | 73 | void StatusBar_DisplayBar(void) { 74 | float width = 0, height = 0, percent_width = 0; 75 | Draw_GetTextSize(0.4f, &width, &height, Clock_GetCurrentTime()); 76 | 77 | StatusBar_GetBatteryStatus((float)((395 - width) - (10 + 12)), (float)((18 - height) / 2), &percent_width); 78 | StatusBar_GetWifiStatus((float)((395 - width) - (10 + 14) - (10 + 12) - (percent_width + 10))); 79 | 80 | Draw_Text((float)(395 - width), (float)((18 - height) / 2) - 2, 0.4f, WHITE, Clock_GetCurrentTime()); 81 | } 82 | -------------------------------------------------------------------------------- /source/textures.c: -------------------------------------------------------------------------------- 1 | #include "c2d_helper.h" 2 | #include "sprites.h" 3 | #include "textures.h" 4 | 5 | static C2D_SpriteSheet spritesheet; 6 | 7 | void Textures_Load(void) { 8 | spritesheet = C2D_SpriteSheetLoad("romfs:/res/drawable/sprites.t3x"); 9 | icon_toggle_on = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_on_normal_idx); 10 | icon_toggle_off = C2D_SpriteSheetGetImage(spritesheet, sprites_btn_material_light_toggle_off_normal_idx); 11 | icon_back = C2D_SpriteSheetGetImage(spritesheet, sprites_ic_arrow_back_normal_idx); 12 | icon_wifi_0 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_0_idx); 13 | icon_wifi_1 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_1_idx); 14 | icon_wifi_2 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_2_idx); 15 | icon_wifi_3 = C2D_SpriteSheetGetImage(spritesheet, sprites_stat_sys_wifi_signal_3_idx); 16 | battery_20 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_20_idx); 17 | battery_20_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_20_charging_idx); 18 | battery_30 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_30_idx); 19 | battery_30_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_30_charging_idx); 20 | battery_50 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_50_idx); 21 | battery_50_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_50_charging_idx); 22 | battery_60 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_60_idx); 23 | battery_60_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_60_charging_idx); 24 | battery_80 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_80_idx); 25 | battery_80_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_80_charging_idx); 26 | battery_90 = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_90_idx); 27 | battery_90_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_90_charging_idx); 28 | battery_full = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_full_idx); 29 | battery_full_charging = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_full_charging_idx); 30 | battery_low = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_low_idx); 31 | battery_unknown = C2D_SpriteSheetGetImage(spritesheet, sprites_battery_unknown_idx); 32 | } 33 | 34 | void Textures_Free(void) { 35 | C2D_SpriteSheetFree(spritesheet); 36 | } 37 | -------------------------------------------------------------------------------- /source/utils.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "fs.h" 5 | #include "utils.h" 6 | 7 | bool dark_theme = false; 8 | 9 | Result Utils_SaveConfig(bool dark_theme) { 10 | Result ret = 0; 11 | 12 | char *buf = malloc(32); 13 | int length = snprintf(buf, 32, "dark_theme = %d\n", dark_theme); 14 | 15 | if (R_FAILED(ret = FS_Write(sdmc_archive, "/3ds/3DSRecoveryTool/config.cfg", buf, length))) { 16 | free(buf); 17 | return ret; 18 | } 19 | 20 | free(buf); 21 | return 0; 22 | } 23 | 24 | Result Utils_LoadConfig(void) { 25 | Handle handle; 26 | Result ret = 0; 27 | 28 | if (!FS_FileExists(sdmc_archive, "/3ds/3DSRecoveryTool/config.cfg")) { 29 | dark_theme = false; 30 | return Utils_SaveConfig(dark_theme); 31 | } 32 | 33 | if (R_FAILED(ret = FSUSER_OpenFile(&handle, sdmc_archive, fsMakePath(PATH_ASCII, "/3ds/3DSRecoveryTool/config.cfg"), FS_OPEN_READ, 0))) 34 | return ret; 35 | 36 | u64 size = 0; 37 | if (R_FAILED(ret = FSFILE_GetSize(handle, &size))) 38 | return ret; 39 | 40 | char *buf = malloc(size + 1); 41 | if (R_FAILED(ret = FSFILE_Read(handle, NULL, 0, (u32 *)buf, size))) { 42 | free(buf); 43 | return ret; 44 | } 45 | 46 | buf[size] = '\0'; 47 | sscanf(buf, "dark_theme = %d\n", (int *)&dark_theme); 48 | free(buf); 49 | 50 | if (R_FAILED(ret = FSFILE_Close(handle))) 51 | return ret; 52 | 53 | return 0; 54 | } 55 | 56 | bool Utils_IsN3DS(void) { 57 | bool isNew3DS = false; 58 | 59 | if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS))) 60 | return isNew3DS; 61 | 62 | return false; 63 | } 64 | 65 | u16 touchGetX(void) { 66 | touchPosition pos; 67 | hidTouchRead(&pos); 68 | return pos.px; 69 | } 70 | 71 | u16 touchGetY(void) { 72 | touchPosition pos; 73 | hidTouchRead(&pos); 74 | return pos.py; 75 | } 76 | 77 | void Utils_SetMax(int *set, int value, int max) { 78 | if (*set > max) 79 | *set = value; 80 | } 81 | 82 | void Utils_SetMin(int *set, int value, int min) { 83 | if (*set < min) 84 | *set = value; 85 | } 86 | --------------------------------------------------------------------------------