├── LICENSE.txt ├── Makefile ├── build.bat ├── cia ├── audio.wav ├── banner.bnr ├── banner.png ├── icon.icn ├── icon.png └── template.rsf ├── gfx └── sound.png ├── icon.png └── source ├── dsptest.c ├── dsptest.h ├── main.c ├── sha256.c └── sha256.h /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (C) 2017 zoogie 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 4 | 5 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 6 | 7 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 8 | -------------------------------------------------------------------------------- /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 | # 19 | # NO_SMDH: if set to anything, no SMDH file is generated. 20 | # APP_TITLE is the name of the app stored in the SMDH file (Optional) 21 | # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) 22 | # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) 23 | # ICON is the filename of the icon (.png), relative to the project folder. 24 | # If not set, it attempts to use one of the following (in this order): 25 | # - .png 26 | # - icon.png 27 | # - /default_icon.png 28 | #--------------------------------------------------------------------------------- 29 | TARGET := $(notdir $(CURDIR)) 30 | BUILD := build 31 | SOURCES := source 32 | DATA := 33 | INCLUDES := include 34 | GRAPHICS := gfx 35 | 36 | #--------------------------------------------------------------------------------- 37 | # options for code generation 38 | #--------------------------------------------------------------------------------- 39 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard 40 | 41 | CFLAGS := -g -Wall -O2 -mword-relocations \ 42 | -fomit-frame-pointer -ffast-math \ 43 | $(ARCH) 44 | 45 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 46 | 47 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 48 | 49 | ASFLAGS := -g $(ARCH) 50 | LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 51 | 52 | LIBS := -lctru -lm 53 | 54 | #--------------------------------------------------------------------------------- 55 | # list of directories containing libraries, this must be the top level containing 56 | # include and lib 57 | #--------------------------------------------------------------------------------- 58 | LIBDIRS := $(CTRULIB) 59 | 60 | #--------------------------------------------------------------------------------- 61 | # no real need to edit anything past this point unless you need to add additional 62 | # rules for different file extensions 63 | #--------------------------------------------------------------------------------- 64 | ifneq ($(BUILD),$(notdir $(CURDIR))) 65 | #--------------------------------------------------------------------------------- 66 | 67 | export OUTPUT := $(CURDIR)/$(TARGET) 68 | export TOPDIR := $(CURDIR) 69 | 70 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 71 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) \ 72 | $(foreach dir,$(GRAPHICS),$(CURDIR)/$(dir)) 73 | 74 | export DEPSDIR := $(CURDIR)/$(BUILD) 75 | 76 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 77 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 78 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 79 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 80 | PNGFILES := $(foreach dir,$(GRAPHICS),$(notdir $(wildcard $(dir)/*.png))) 81 | 82 | #--------------------------------------------------------------------------------- 83 | # use CXX for linking C++ projects, CC for standard C 84 | #--------------------------------------------------------------------------------- 85 | ifeq ($(strip $(CPPFILES)),) 86 | #--------------------------------------------------------------------------------- 87 | export LD := $(CC) 88 | #--------------------------------------------------------------------------------- 89 | else 90 | #--------------------------------------------------------------------------------- 91 | export LD := $(CXX) 92 | #--------------------------------------------------------------------------------- 93 | endif 94 | #--------------------------------------------------------------------------------- 95 | 96 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 97 | $(PNGFILES:.png=.bgr.o) \ 98 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) \ 99 | 100 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 101 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 102 | -I$(CURDIR)/$(BUILD) 103 | 104 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 105 | 106 | ifeq ($(strip $(ICON)),) 107 | icons := $(wildcard *.png) 108 | ifneq (,$(findstring $(TARGET).png,$(icons))) 109 | export APP_ICON := $(TOPDIR)/$(TARGET).png 110 | else 111 | ifneq (,$(findstring icon.png,$(icons))) 112 | export APP_ICON := $(TOPDIR)/icon.png 113 | endif 114 | endif 115 | else 116 | export APP_ICON := $(TOPDIR)/$(ICON) 117 | endif 118 | 119 | IMAGEMAGICK := $(shell which convert) 120 | 121 | ifeq ($(strip $(NO_SMDH)),) 122 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 123 | endif 124 | 125 | .PHONY: $(BUILD) clean all 126 | 127 | #--------------------------------------------------------------------------------- 128 | ifneq ($(strip $(IMAGEMAGICK)),) 129 | ifeq ($(findstring System32, $(IMAGEMAGICK)),) 130 | 131 | all: $(BUILD) 132 | 133 | else 134 | 135 | all: 136 | @echo "Image Magick not found!" 137 | @echo 138 | @echo "Please install Image Magick from http://www.imagemagick.org/ to build this example" 139 | 140 | endif 141 | endif 142 | 143 | 144 | #--------------------------------------------------------------------------------- 145 | $(BUILD): 146 | @[ -d $@ ] || mkdir -p $@ 147 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 148 | 149 | #--------------------------------------------------------------------------------- 150 | clean: 151 | @echo clean ... 152 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf 153 | 154 | 155 | #--------------------------------------------------------------------------------- 156 | else 157 | 158 | DEPENDS := $(OFILES:.o=.d) 159 | 160 | #--------------------------------------------------------------------------------- 161 | # main targets 162 | #--------------------------------------------------------------------------------- 163 | ifeq ($(strip $(NO_SMDH)),) 164 | $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh 165 | else 166 | $(OUTPUT).3dsx : $(OUTPUT).elf 167 | endif 168 | 169 | $(OUTPUT).elf : $(OFILES) 170 | 171 | #--------------------------------------------------------------------------------- 172 | # you need a rule like this for each extension you use as binary data 173 | #--------------------------------------------------------------------------------- 174 | %.bin.o : %.bin 175 | #--------------------------------------------------------------------------------- 176 | @echo $(notdir $<) 177 | @$(bin2o) 178 | 179 | 180 | 181 | #--------------------------------------------------------------------------------- 182 | %.bgr.o: %.bgr 183 | #--------------------------------------------------------------------------------- 184 | @echo $(notdir $<) 185 | @$(bin2o) 186 | 187 | #--------------------------------------------------------------------------------- 188 | %.bgr: %.png 189 | #--------------------------------------------------------------------------------- 190 | @echo $(notdir $<) 191 | @convert $< -rotate 90 $@ 192 | 193 | -include $(DEPENDS) 194 | 195 | #--------------------------------------------------------------------------------------- 196 | endif 197 | #--------------------------------------------------------------------------------------- 198 | -------------------------------------------------------------------------------- /build.bat: -------------------------------------------------------------------------------- 1 | make 2 | bannertool makebanner -i "cia/banner.png" -a "cia/audio.wav" -o "cia/banner.bnr" 3 | bannertool makesmdh -i "cia/icon.png" -l "DSP1 - dsp firm dumper" -s "DSP1" -p "zoogie" -o "cia/icon.icn" 4 | makerom -f cia -o DSP1.cia -rsf cia/template.rsf -target t -elf DSP1.elf -icon cia/icon.icn -banner cia/banner.bnr -exefslogo 5 | pause -------------------------------------------------------------------------------- /cia/audio.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/cia/audio.wav -------------------------------------------------------------------------------- /cia/banner.bnr: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/cia/banner.bnr -------------------------------------------------------------------------------- /cia/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/cia/banner.png -------------------------------------------------------------------------------- /cia/icon.icn: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/cia/icon.icn -------------------------------------------------------------------------------- /cia/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/cia/icon.png -------------------------------------------------------------------------------- /cia/template.rsf: -------------------------------------------------------------------------------- 1 | BasicInfo: 2 | Title : dsp1cia1 3 | ProductCode : CTR-P-DSP1 4 | Logo : Homebrew # Nintendo / Licensed / Distributed / iQue / iQueForSystem 5 | 6 | #RomFs: 7 | # Specifies the root path of the read only file system to include in the ROM. 8 | #RootPath : romfs 9 | 10 | TitleInfo: 11 | Category : Application 12 | UniqueId : 0x0D591 13 | 14 | Option: 15 | UseOnSD : true # true if App is to be installed to SD 16 | FreeProductCode : true # Removes limitations on ProductCode 17 | MediaFootPadding : false # If true CCI files are created with padding 18 | EnableCrypt : false # Enables encryption for NCCH and CIA 19 | EnableCompress : true # Compresses where applicable (currently only exefs:/.code) 20 | 21 | AccessControlInfo: 22 | CoreVersion : 2 23 | 24 | # Exheader Format Version 25 | DescVersion : 2 26 | 27 | # Minimum Required Kernel Version (below is for 4.5.0) 28 | ReleaseKernelMajor : "02" 29 | ReleaseKernelMinor : "33" 30 | 31 | # ExtData 32 | UseExtSaveData : false # enables ExtData 33 | #ExtSaveDataId : 0x300 # only set this when the ID is different to the UniqueId 34 | 35 | # FS:USER Archive Access Permissions 36 | # Uncomment as required 37 | FileSystemAccess: 38 | - CategorySystemApplication 39 | - CategoryHardwareCheck 40 | - CategoryFileSystemTool 41 | - Debug 42 | - TwlCardBackup 43 | - TwlNandData 44 | - Boss 45 | - DirectSdmc 46 | - Core 47 | - CtrNandRo 48 | - CtrNandRw 49 | - CtrNandRoWrite 50 | - CategorySystemSettings 51 | - CardBoard 52 | - ExportImportIvs 53 | - DirectSdmcWrite 54 | - SwitchCleanup 55 | - SaveDataMove 56 | - Shop 57 | - Shell 58 | - CategoryHomeMenu 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 : 64MB # 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 : Legacy # Legacy(Default)/124MB/178MB Legacy:Use Old3DS SystemMode 89 | CpuSpeed : 268MHz # 268MHz(Default)/804MHz 90 | EnableL2Cache : false # false(default)/true 91 | CanAccessCore2 : false 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 | - am:net 215 | - boss:U 216 | - cam:u 217 | - cecd:u 218 | - cfg:nor 219 | - cfg:u 220 | - csnd:SND 221 | - dsp::DSP 222 | - frd:u 223 | - fs:USER 224 | - gsp::Gpu 225 | - gsp::Lcd 226 | - hid:USER 227 | - http:C 228 | - ir:rst 229 | - ir:u 230 | - ir:USER 231 | - mic:u 232 | - ndm:u 233 | - news:s 234 | - nwm::EXT 235 | - nwm::UDS 236 | - ptm:sysm 237 | - ptm:u 238 | - pxi:dev 239 | - soc:U 240 | - ssl:C 241 | - y2r:u 242 | 243 | 244 | SystemControlInfo: 245 | SaveDataSize: 0KB # Change if the app uses savedata 246 | RemasterVersion: 0 247 | StackSize: 0x40000 248 | 249 | # Modules that run services listed above should be included below 250 | # Maximum 48 dependencies 251 | # : 252 | Dependency: 253 | ac: 0x0004013000002402 254 | #act: 0x0004013000003802 255 | am: 0x0004013000001502 256 | boss: 0x0004013000003402 257 | camera: 0x0004013000001602 258 | cecd: 0x0004013000002602 259 | cfg: 0x0004013000001702 260 | codec: 0x0004013000001802 261 | csnd: 0x0004013000002702 262 | dlp: 0x0004013000002802 263 | dsp: 0x0004013000001a02 264 | friends: 0x0004013000003202 265 | gpio: 0x0004013000001b02 266 | gsp: 0x0004013000001c02 267 | hid: 0x0004013000001d02 268 | http: 0x0004013000002902 269 | i2c: 0x0004013000001e02 270 | ir: 0x0004013000003302 271 | mcu: 0x0004013000001f02 272 | mic: 0x0004013000002002 273 | ndm: 0x0004013000002b02 274 | news: 0x0004013000003502 275 | #nfc: 0x0004013000004002 276 | nim: 0x0004013000002c02 277 | nwm: 0x0004013000002d02 278 | pdn: 0x0004013000002102 279 | ps: 0x0004013000003102 280 | ptm: 0x0004013000002202 281 | #qtm: 0x0004013020004202 282 | ro: 0x0004013000003702 283 | socket: 0x0004013000002e02 284 | spi: 0x0004013000002302 285 | ssl: 0x0004013000002f02 286 | -------------------------------------------------------------------------------- /gfx/sound.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/gfx/sound.png -------------------------------------------------------------------------------- /icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/DSP1/9b0180772d16dc688ad8b3527df294c11bb736a1/icon.png -------------------------------------------------------------------------------- /source/dsptest.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include <3ds.h> 7 | #include "dsptest.h" 8 | 9 | #define SAMPLERATE 22050 10 | #define SAMPLESPERBUF (SAMPLERATE / 30) 11 | #define BYTESPERSAMPLE 4 12 | 13 | //---------------------------------------------------------------------------- 14 | void fill_buffer(void *audioBuffer,size_t offset, size_t size, int frequency ) { 15 | //---------------------------------------------------------------------------- 16 | 17 | u32 *dest = (u32*)audioBuffer; 18 | 19 | for (int i=0; i 2 | #include 3 | #include <3ds.h> 4 | #include 5 | #include 6 | #include 7 | #include "sha256.h" 8 | #include "dsptest.h" 9 | #include "sound_bgr.h" 10 | #define NB_TITLES (sizeof(titles)/sizeof(TitleInfo)) 11 | 12 | typedef struct { 13 | u64 titleid; 14 | char name[50]; 15 | } TitleInfo; 16 | 17 | TitleInfo titles[] = { 18 | 19 | { 0x4003000008f02LL, "home_menu_usa"}, 20 | { 0x4003000008202LL, "home_menu_jpn"}, 21 | { 0x4003000009802LL, "home_menu_eur"}, 22 | { 0x400300000A102LL, "home_menu_chn"}, 23 | { 0x400300000A902LL, "home_menu_kor"}, 24 | { 0x400300000B102LL, "home_menu_twn"}, 25 | 26 | }; 27 | 28 | // decompression code stolen from ctrtool 29 | 30 | u32 getle32(const u8* p) 31 | { 32 | return (p[0]<<0) | (p[1]<<8) | (p[2]<<16) | (p[3]<<24); 33 | } 34 | 35 | u32 lzss_get_decompressed_size(u8* compressed, u32 compressedsize) 36 | { 37 | u8* footer = compressed + compressedsize - 8; 38 | 39 | u32 originalbottom = getle32(footer+4); 40 | 41 | return originalbottom + compressedsize; 42 | } 43 | 44 | int lzss_decompress(u8* compressed, u32 compressedsize, u8* decompressed, u32 decompressedsize) 45 | { 46 | u8* footer = compressed + compressedsize - 8; 47 | u32 buffertopandbottom = getle32(footer+0); 48 | //u32 originalbottom = getle32(footer+4); 49 | u32 i, j; 50 | u32 out = decompressedsize; 51 | u32 index = compressedsize - ((buffertopandbottom>>24)&0xFF); 52 | u32 segmentoffset; 53 | u32 segmentsize; 54 | u8 control; 55 | u32 stopindex = compressedsize - (buffertopandbottom&0xFFFFFF); 56 | 57 | memset(decompressed, 0, decompressedsize); 58 | memcpy(decompressed, compressed, compressedsize); 59 | 60 | 61 | while(index > stopindex) 62 | { 63 | control = compressed[--index]; 64 | 65 | 66 | for(i=0; i<8; i++) 67 | { 68 | if (index <= stopindex) 69 | break; 70 | 71 | if (index <= 0) 72 | break; 73 | 74 | if (out <= 0) 75 | break; 76 | 77 | if (control & 0x80) 78 | { 79 | if (index < 2) 80 | { 81 | // fprintf(stderr, "Error, compression out of bounds\n"); 82 | goto clean; 83 | } 84 | 85 | index -= 2; 86 | 87 | segmentoffset = compressed[index] | (compressed[index+1]<<8); 88 | segmentsize = ((segmentoffset >> 12)&15)+3; 89 | segmentoffset &= 0x0FFF; 90 | segmentoffset += 2; 91 | 92 | 93 | if (out < segmentsize) 94 | { 95 | // fprintf(stderr, "Error, compression out of bounds\n"); 96 | goto clean; 97 | } 98 | 99 | for(j=0; j= decompressedsize) 104 | { 105 | // fprintf(stderr, "Error, compression out of bounds\n"); 106 | goto clean; 107 | } 108 | 109 | data = decompressed[out+segmentoffset]; 110 | decompressed[--out] = data; 111 | } 112 | } 113 | else 114 | { 115 | if (out < 1) 116 | { 117 | // fprintf(stderr, "Error, compression out of bounds\n"); 118 | goto clean; 119 | } 120 | decompressed[--out] = compressed[--index]; 121 | } 122 | 123 | control <<= 1; 124 | } 125 | } 126 | 127 | return 0; 128 | 129 | clean: 130 | return -1; 131 | } 132 | 133 | 134 | Result openCode(Handle* out, u64 tid, u8 mediatype) 135 | { 136 | if(!out)return -1; 137 | 138 | u32 archivePath[] = {tid & 0xFFFFFFFF, (tid >> 32) & 0xFFFFFFFF, mediatype, 0x00000000}; 139 | static const u32 filePath[] = {0x00000000, 0x00000000, 0x00000002, 0x646F632E, 0x00000065}; 140 | 141 | return FSUSER_OpenFileDirectly(out, (FS_ArchiveID)0x2345678a, (FS_Path){PATH_BINARY, 0x10, (u8*)archivePath}, (FS_Path){PATH_BINARY, 0x14, (u8*)filePath}, FS_OPEN_READ, 0); 142 | } 143 | 144 | u32 u8to32(u8 *input){ //workaround for weird < 9.0 bug in built-in sha function 145 | return *(input+0) | *(input+1)<<8 | *(input+2)<<16 | *(input+3)<<24; 146 | } 147 | 148 | int sha_quick(uint8_t *dest, uint8_t *src, size_t src_len) //thanks to wolfvak https://github.com/Wolfvak/makefirm 149 | { 150 | SHA256_CTX *ctx = (SHA256_CTX*)malloc(sizeof(SHA256_CTX)); 151 | if (!ctx) return 1; 152 | sha256_init(ctx); 153 | sha256_update(ctx, src, src_len); 154 | sha256_final(ctx, dest); 155 | free(ctx); 156 | return 0; 157 | } 158 | 159 | int checkHashes(u8 *base){ 160 | 161 | u8 *pos = base + 0x120; 162 | u8 *dsp_section_offset = NULL; 163 | u32 dsp_hash_address = 0; 164 | u8 *dsp_hash_offset = NULL; 165 | u32 dsp_section_size = 0; 166 | u8 sha256[0x20]; 167 | int fail=0; 168 | 169 | for(int i=0 ; i<10 ; i++){ //there are a max of ten sections for dsp firm. i've only observed a usage of exactly 5 in the wild 170 | 171 | dsp_section_size = u8to32(pos + 0x8); 172 | dsp_hash_address = u8to32(pos); 173 | dsp_section_offset = (dsp_hash_address + base); 174 | dsp_hash_offset = (pos + 0x10); 175 | memset(sha256, 0, 0x20); 176 | 177 | if(dsp_section_size==0) break; //don't hash an empty section header. 178 | 179 | //res = FSUSER_UpdateSha256Context(dsp_section_offset, dsp_section_size, sha256); //couldn't use this because buggy on older firms, damn. 180 | sha_quick(sha256, dsp_section_offset, dsp_section_size); //call it twice and the fs session is revoked, lol. on >= 9.0 this doesn't happen 181 | 182 | if(memcmp(dsp_hash_offset, sha256, 0x20)){ 183 | fail=1; 184 | printf("sect %d hash failed %08X %08X\n", i, (int)dsp_hash_address, (int)dsp_section_size); 185 | } 186 | pos+=0x30; 187 | 188 | } 189 | 190 | return fail; 191 | } 192 | 193 | Result dumpCode(u64 tid , char* path) 194 | { 195 | Result ret; 196 | Handle fileHandle; 197 | 198 | ret = openCode(&fileHandle, tid, 0); 199 | 200 | char name[50]; 201 | 202 | sprintf(name, "%s.bin", path); 203 | 204 | u8* fileBuffer = NULL; 205 | u64 fileSize = 0; 206 | 207 | u32 bytesRead; 208 | 209 | ret = FSFILE_GetSize(fileHandle, &fileSize); 210 | if(ret)return ret; 211 | fileBuffer = malloc(fileSize); 212 | if(ret)return ret; 213 | ret = FSFILE_Read(fileHandle, &bytesRead, 0x0, fileBuffer, fileSize); 214 | if(ret)return ret; 215 | ret = FSFILE_Close(fileHandle); 216 | if(ret)return ret; 217 | 218 | u32 decompressedSize = lzss_get_decompressed_size(fileBuffer, fileSize); 219 | u8* decompressedBuffer = linearMemAlign(decompressedSize, 0x1000); 220 | if(!decompressedBuffer)return 1; 221 | 222 | lzss_decompress(fileBuffer, fileSize, decompressedBuffer, decompressedSize); 223 | free(fileBuffer); 224 | 225 | const char *magic = "DSP1"; 226 | u8 *dsp_loc = NULL; 227 | u32 dsp_size = 0; 228 | 229 | dsp_loc = (u8*)memmem(decompressedBuffer , decompressedSize, magic, 4); 230 | if(dsp_loc){ 231 | printf("Magic found! Beginning dsp dump! ...\n"); 232 | dsp_size = *(u32*)(dsp_loc + 4); //size usually 0xC25C 233 | dsp_loc -= 0x100; 234 | 235 | if(!checkHashes(dsp_loc)) printf("Sha256 verified! Size: %08X\nWriting dsp firm now ...\n", (int)dsp_size); 236 | else{ 237 | printf("\x1b[31;1m"); //red text for scaring people 238 | printf("Sha256 mismatch! Size: %08X\n", (int)dsp_size); 239 | printf("Dsp firm will be dumped, but it may not work!\n"); 240 | printf("\x1b[37;1m"); //back to white 241 | //linearFree(decompressedBuffer); 242 | //return 2; 243 | } 244 | 245 | FILE* f = fopen("sdmc:/3ds/dspfirm.cdc", "wb"); 246 | if(!f) { linearFree(decompressedBuffer); return 2; } 247 | fwrite(dsp_loc, 1, dsp_size, f); 248 | fclose(f); 249 | 250 | printf("\nDsp firm written to: sdmc:/3ds/dspfirm.cdc\n\n"); 251 | dsp_test(); 252 | printf("No more action required!\n"); 253 | } 254 | else{ 255 | printf("Dsp magic not found!\n"); 256 | linearFree(decompressedBuffer); 257 | return 1; 258 | } 259 | 260 | linearFree(decompressedBuffer); 261 | return 0; 262 | } 263 | 264 | int main(int argc, char** argv) 265 | { 266 | int i = 0; 267 | // Initialize services 268 | gfxInitDefault(); 269 | 270 | // Init console for text output 271 | consoleInit(GFX_TOP, NULL); 272 | Result res; 273 | 274 | mkdir("sdmc:/3ds", 0777); 275 | 276 | int screen_char_total=50*30; 277 | printf("\x1b[44;1m"); //blue background over entire screen 278 | while(screen_char_total--)printf(" "); 279 | printf("\x1b[0;0H"); //back to white text and cursor to top left corner 280 | 281 | printf(" DSP1 - zoogie\n\n\n"); //(50 - 13) / 2 = 18 282 | printf("Extracting home menu .code ...\n"); 283 | 284 | gfxSetDoubleBuffering(GFX_BOTTOM, false); 285 | u8 *fb = gfxGetFramebuffer(GFX_BOTTOM, GFX_LEFT, NULL, NULL); 286 | memcpy(fb, sound_bgr, sound_bgr_size); 287 | 288 | for(i = 0; i < NB_TITLES; ++i){ 289 | TitleInfo tl=titles[i]; 290 | res = dumpCode(tl.titleid, tl.name); 291 | if(res) printf("Not found: %s %08X\n", tl.name, (int)res); 292 | else break; 293 | } 294 | 295 | printf("\n\nSTART: Exit to home menu.\n B: Delete this app then exit to home menu.\n"); 296 | // Main loop 297 | while (aptMainLoop()) 298 | { 299 | hidScanInput(); 300 | 301 | u32 kDown = hidKeysDown(); 302 | if (kDown & KEY_START) 303 | break; // break in order to return to hbmenu 304 | else if (kDown & KEY_B) 305 | { 306 | if (argc >= 1) 307 | { 308 | if(remove(argv[0]) != 0) printf("\nSelf-delete failed!\n"); 309 | else printf("\nSelf-delete successful!\n"); 310 | svcSleepThread(500*1000*1000); 311 | break; 312 | } 313 | else 314 | { 315 | amInit(); 316 | res = AM_DeleteAppTitle(MEDIATYPE_SD, (u64)0x0004000000D59100); 317 | if(res) printf("\nSelf-delete failed, call in the FBI!\n"); 318 | else printf("\nSelf-delete successful!\n"); 319 | svcSleepThread(500*1000*1000); 320 | break; 321 | } 322 | } 323 | 324 | // Flush and swap framebuffers 325 | gfxFlushBuffers(); 326 | gfxSwapBuffers(); 327 | gspWaitForVBlank(); 328 | } 329 | 330 | // Exit services 331 | gfxExit(); 332 | return 0; 333 | } 334 | -------------------------------------------------------------------------------- /source/sha256.c: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: sha256.c 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Implementation of the SHA-256 hashing algorithm. 7 | SHA-256 is one of the three algorithms in the SHA2 8 | specification. The others, SHA-384 and SHA-512, are not 9 | offered in this implementation. 10 | Algorithm specification can be found here: 11 | * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2withchangenotice.pdf 12 | This implementation uses little endian byte order. 13 | *********************************************************************/ 14 | 15 | /*************************** HEADER FILES ***************************/ 16 | #include 17 | //#include 18 | #include "sha256.h" 19 | 20 | /****************************** MACROS ******************************/ 21 | #define ROTLEFT(a,b) (((a) << (b)) | ((a) >> (32-(b)))) 22 | #define ROTRIGHT(a,b) (((a) >> (b)) | ((a) << (32-(b)))) 23 | 24 | #define CH(x,y,z) (((x) & (y)) ^ (~(x) & (z))) 25 | #define MAJ(x,y,z) (((x) & (y)) ^ ((x) & (z)) ^ ((y) & (z))) 26 | #define EP0(x) (ROTRIGHT(x,2) ^ ROTRIGHT(x,13) ^ ROTRIGHT(x,22)) 27 | #define EP1(x) (ROTRIGHT(x,6) ^ ROTRIGHT(x,11) ^ ROTRIGHT(x,25)) 28 | #define SIG0(x) (ROTRIGHT(x,7) ^ ROTRIGHT(x,18) ^ ((x) >> 3)) 29 | #define SIG1(x) (ROTRIGHT(x,17) ^ ROTRIGHT(x,19) ^ ((x) >> 10)) 30 | 31 | /**************************** VARIABLES *****************************/ 32 | static const WORD k[64] = { 33 | 0x428a2f98,0x71374491,0xb5c0fbcf,0xe9b5dba5,0x3956c25b,0x59f111f1,0x923f82a4,0xab1c5ed5, 34 | 0xd807aa98,0x12835b01,0x243185be,0x550c7dc3,0x72be5d74,0x80deb1fe,0x9bdc06a7,0xc19bf174, 35 | 0xe49b69c1,0xefbe4786,0x0fc19dc6,0x240ca1cc,0x2de92c6f,0x4a7484aa,0x5cb0a9dc,0x76f988da, 36 | 0x983e5152,0xa831c66d,0xb00327c8,0xbf597fc7,0xc6e00bf3,0xd5a79147,0x06ca6351,0x14292967, 37 | 0x27b70a85,0x2e1b2138,0x4d2c6dfc,0x53380d13,0x650a7354,0x766a0abb,0x81c2c92e,0x92722c85, 38 | 0xa2bfe8a1,0xa81a664b,0xc24b8b70,0xc76c51a3,0xd192e819,0xd6990624,0xf40e3585,0x106aa070, 39 | 0x19a4c116,0x1e376c08,0x2748774c,0x34b0bcb5,0x391c0cb3,0x4ed8aa4a,0x5b9cca4f,0x682e6ff3, 40 | 0x748f82ee,0x78a5636f,0x84c87814,0x8cc70208,0x90befffa,0xa4506ceb,0xbef9a3f7,0xc67178f2 41 | }; 42 | 43 | /*********************** FUNCTION DEFINITIONS ***********************/ 44 | void sha256_transform(SHA256_CTX *ctx, const BYTE data[]) 45 | { 46 | WORD a, b, c, d, e, f, g, h, i, j, t1, t2, m[64]; 47 | 48 | for (i = 0, j = 0; i < 16; ++i, j += 4) 49 | m[i] = (data[j] << 24) | (data[j + 1] << 16) | (data[j + 2] << 8) | (data[j + 3]); 50 | for ( ; i < 64; ++i) 51 | m[i] = SIG1(m[i - 2]) + m[i - 7] + SIG0(m[i - 15]) + m[i - 16]; 52 | 53 | a = ctx->state[0]; 54 | b = ctx->state[1]; 55 | c = ctx->state[2]; 56 | d = ctx->state[3]; 57 | e = ctx->state[4]; 58 | f = ctx->state[5]; 59 | g = ctx->state[6]; 60 | h = ctx->state[7]; 61 | 62 | for (i = 0; i < 64; ++i) { 63 | t1 = h + EP1(e) + CH(e,f,g) + k[i] + m[i]; 64 | t2 = EP0(a) + MAJ(a,b,c); 65 | h = g; 66 | g = f; 67 | f = e; 68 | e = d + t1; 69 | d = c; 70 | c = b; 71 | b = a; 72 | a = t1 + t2; 73 | } 74 | 75 | ctx->state[0] += a; 76 | ctx->state[1] += b; 77 | ctx->state[2] += c; 78 | ctx->state[3] += d; 79 | ctx->state[4] += e; 80 | ctx->state[5] += f; 81 | ctx->state[6] += g; 82 | ctx->state[7] += h; 83 | } 84 | 85 | void sha256_init(SHA256_CTX *ctx) 86 | { 87 | ctx->datalen = 0; 88 | ctx->bitlen = 0; 89 | ctx->state[0] = 0x6a09e667; 90 | ctx->state[1] = 0xbb67ae85; 91 | ctx->state[2] = 0x3c6ef372; 92 | ctx->state[3] = 0xa54ff53a; 93 | ctx->state[4] = 0x510e527f; 94 | ctx->state[5] = 0x9b05688c; 95 | ctx->state[6] = 0x1f83d9ab; 96 | ctx->state[7] = 0x5be0cd19; 97 | } 98 | 99 | void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len) 100 | { 101 | WORD i; 102 | 103 | for (i = 0; i < len; ++i) { 104 | ctx->data[ctx->datalen] = data[i]; 105 | ctx->datalen++; 106 | if (ctx->datalen == 64) { 107 | sha256_transform(ctx, ctx->data); 108 | ctx->bitlen += 512; 109 | ctx->datalen = 0; 110 | } 111 | } 112 | } 113 | 114 | void sha256_final(SHA256_CTX *ctx, BYTE hash[]) 115 | { 116 | WORD i; 117 | 118 | i = ctx->datalen; 119 | 120 | // Pad whatever data is left in the buffer. 121 | if (ctx->datalen < 56) { 122 | ctx->data[i++] = 0x80; 123 | while (i < 56) 124 | ctx->data[i++] = 0x00; 125 | } 126 | else { 127 | ctx->data[i++] = 0x80; 128 | while (i < 64) 129 | ctx->data[i++] = 0x00; 130 | sha256_transform(ctx, ctx->data); 131 | memset(ctx->data, 0, 56); 132 | } 133 | 134 | // Append to the padding the total message's length in bits and transform. 135 | ctx->bitlen += ctx->datalen * 8; 136 | ctx->data[63] = ctx->bitlen; 137 | ctx->data[62] = ctx->bitlen >> 8; 138 | ctx->data[61] = ctx->bitlen >> 16; 139 | ctx->data[60] = ctx->bitlen >> 24; 140 | ctx->data[59] = ctx->bitlen >> 32; 141 | ctx->data[58] = ctx->bitlen >> 40; 142 | ctx->data[57] = ctx->bitlen >> 48; 143 | ctx->data[56] = ctx->bitlen >> 56; 144 | sha256_transform(ctx, ctx->data); 145 | 146 | // Since this implementation uses little endian byte ordering and SHA uses big endian, 147 | // reverse all the bytes when copying the final state to the output hash. 148 | for (i = 0; i < 4; ++i) { 149 | hash[i] = (ctx->state[0] >> (24 - i * 8)) & 0x000000ff; 150 | hash[i + 4] = (ctx->state[1] >> (24 - i * 8)) & 0x000000ff; 151 | hash[i + 8] = (ctx->state[2] >> (24 - i * 8)) & 0x000000ff; 152 | hash[i + 12] = (ctx->state[3] >> (24 - i * 8)) & 0x000000ff; 153 | hash[i + 16] = (ctx->state[4] >> (24 - i * 8)) & 0x000000ff; 154 | hash[i + 20] = (ctx->state[5] >> (24 - i * 8)) & 0x000000ff; 155 | hash[i + 24] = (ctx->state[6] >> (24 - i * 8)) & 0x000000ff; 156 | hash[i + 28] = (ctx->state[7] >> (24 - i * 8)) & 0x000000ff; 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /source/sha256.h: -------------------------------------------------------------------------------- 1 | /********************************************************************* 2 | * Filename: sha256.h 3 | * Author: Brad Conte (brad AT bradconte.com) 4 | * Copyright: 5 | * Disclaimer: This code is presented "as is" without any guarantees. 6 | * Details: Defines the API for the corresponding SHA1 implementation. 7 | *********************************************************************/ 8 | 9 | #ifndef SHA256_H 10 | #define SHA256_H 11 | 12 | /*************************** HEADER FILES ***************************/ 13 | #include 14 | 15 | /****************************** MACROS ******************************/ 16 | #define SHA256_BLOCK_SIZE 32 // SHA256 outputs a 32 byte digest 17 | 18 | /**************************** DATA TYPES ****************************/ 19 | typedef unsigned char BYTE; // 8-bit byte 20 | typedef unsigned int WORD; // 32-bit word, change to "long" for 16-bit machines 21 | 22 | typedef struct { 23 | BYTE data[64]; 24 | WORD datalen; 25 | unsigned long long bitlen; 26 | WORD state[8]; 27 | } SHA256_CTX; 28 | 29 | /*********************** FUNCTION DECLARATIONS **********************/ 30 | void sha256_init(SHA256_CTX *ctx); 31 | void sha256_update(SHA256_CTX *ctx, const BYTE data[], size_t len); 32 | void sha256_final(SHA256_CTX *ctx, BYTE hash[]); 33 | 34 | #endif // SHA256_H 35 | --------------------------------------------------------------------------------