├── .gitmodules ├── LICENSE ├── readme.md ├── seedminer ├── Makefile ├── saves │ ├── lfcs.dat │ ├── lfcs_new.dat │ ├── new-v2.dat │ └── old-v2.dat ├── seedminer_launcher3.py ├── seedminer_launcher3_GUI.py └── source │ ├── main.c │ └── types.h └── seedstarter ├── LICENSE ├── Makefile ├── include ├── fs.h ├── services │ └── frd.h └── utils.h ├── resources ├── banner.png ├── banner.wav ├── cia.rsf ├── icon.png └── logo.bcma.lz └── source ├── fs.c ├── main.c ├── services └── frd.c └── utils.c /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "bfCL"] 2 | path = bfCL 3 | url = https://github.com/zoogie/bfCL.git 4 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 zoogie 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 | -------------------------------------------------------------------------------- /readme.md: -------------------------------------------------------------------------------- 1 | # seedminer 2 | 3 | Implementation of [34⅕c3](https://zoogie.github.io/web/34%E2%85%95c3/) 4 | See release archive for instructions -------------------------------------------------------------------------------- /seedminer/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | 5 | #--------------------------------------------------------------------------------- 6 | # the prefix on the compiler executables 7 | #--------------------------------------------------------------------------------- 8 | PREFIX := 9 | 10 | export CC := $(PREFIX)gcc 11 | export CXX := $(PREFIX)g++ 12 | export AS := $(PREFIX)as 13 | export AR := $(PREFIX)ar 14 | export OBJCOPY := $(PREFIX)objcopy 15 | 16 | #--------------------------------------------------------------------------------- 17 | %.a: 18 | #--------------------------------------------------------------------------------- 19 | @echo $(notdir $@) 20 | @rm -f $@ 21 | $(AR) -rc $@ $^ 22 | 23 | #--------------------------------------------------------------------------------- 24 | %.o: %.cpp 25 | @echo $(notdir $<) 26 | $(CXX) -MMD -MP -MF $(DEPSDIR)/$*.d $(CXXFLAGS) -c $< -o $@ 27 | 28 | #--------------------------------------------------------------------------------- 29 | %.o: %.c 30 | @echo $(notdir $<) 31 | $(CC) -MMD -MP -MF $(DEPSDIR)/$*.d $(CFLAGS) -c $< -o $@ 32 | 33 | 34 | #--------------------------------------------------------------------------------- 35 | %.o: %.s 36 | @echo $(notdir $<) 37 | $(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ 38 | 39 | #--------------------------------------------------------------------------------- 40 | %.o: %.S 41 | @echo $(notdir $<) 42 | $(CC) -MMD -MP -MF $(DEPSDIR)/$*.d -x assembler-with-cpp $(ASFLAGS) -c $< -o $@ 43 | 44 | #--------------------------------------------------------------------------------- 45 | # TARGET is the name of the output 46 | # BUILD is the directory where object files & intermediate files will be placed 47 | # SOURCES is a list of directories containing source code 48 | # INCLUDES is a list of directories containing extra header files 49 | # MAXMOD_SOUNDBANK contains a directory of music and sound effect files 50 | #--------------------------------------------------------------------------------- 51 | TARGET := $(shell basename $(CURDIR)) 52 | BUILD := build_nix 53 | SOURCES := source 54 | DATA := data 55 | INCLUDES := include 56 | 57 | #--------------------------------------------------------------------------------- 58 | # options for code generation 59 | #--------------------------------------------------------------------------------- 60 | 61 | CFLAGS := -Wall -Werror -O3 -m64 62 | 63 | CFLAGS += $(INCLUDE) 64 | ifeq ($(shell uname), Darwin) 65 | # Assume that we've downloaded OpenSSL through Homebrew 66 | CFLAGS += -I/usr/local/opt/openssl/include 67 | endif 68 | CXXFLAGS := $(CFLAGS) 69 | 70 | ASFLAGS := -g 71 | LDFLAGS = -g 72 | 73 | #--------------------------------------------------------------------------------- 74 | # any extra libraries we wish to link with the project (order is important) 75 | #--------------------------------------------------------------------------------- 76 | ifeq ($(shell uname), Darwin) 77 | # Once again, assume that we've downloaded OpenSSL through Homebrew 78 | LIBS := "/usr/local/opt/openssl/lib/libcrypto.dylib" 79 | # If you want to use the OpenSSL crypto static library instead (on macOS), change "/usr/local/opt/openssl/lib/libcrypto.dylib" to "/usr/local/opt/openssl/lib/libcrypto.a" (if you downloaded OpenSSL through Homebrew) with the quotes. 80 | else 81 | LIBS := -lcrypto 82 | # If you want to use the OpenSSL crypto static library instead (whether you're using MSYS2 or are on Linux), change "-lcrypto" to "-l:libcrypto.a" without the quotes. 83 | endif 84 | 85 | 86 | #--------------------------------------------------------------------------------- 87 | # list of directories containing libraries, this must be the top level containing 88 | # include and lib 89 | #--------------------------------------------------------------------------------- 90 | LIBDIRS := 91 | 92 | #--------------------------------------------------------------------------------- 93 | # no real need to edit anything past this point unless you need to add additional 94 | # rules for different file extensions 95 | #--------------------------------------------------------------------------------- 96 | ifneq ($(BUILD),$(notdir $(CURDIR))) 97 | #--------------------------------------------------------------------------------- 98 | 99 | export OUTPUT := $(CURDIR)/$(TARGET) 100 | 101 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 102 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 103 | 104 | export DEPSDIR := $(CURDIR)/$(BUILD) 105 | 106 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 107 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 108 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 109 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 110 | 111 | #--------------------------------------------------------------------------------- 112 | # use CXX for linking C++ projects, CC for standard C 113 | #--------------------------------------------------------------------------------- 114 | ifeq ($(strip $(CPPFILES)),) 115 | #--------------------------------------------------------------------------------- 116 | export LD := $(CC) 117 | #--------------------------------------------------------------------------------- 118 | else 119 | #--------------------------------------------------------------------------------- 120 | export LD := $(CXX) 121 | #--------------------------------------------------------------------------------- 122 | endif 123 | #--------------------------------------------------------------------------------- 124 | 125 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 126 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 127 | 128 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 129 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 130 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 131 | -I$(CURDIR)/$(BUILD) 132 | 133 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 134 | 135 | .PHONY: $(BUILD) clean 136 | 137 | #--------------------------------------------------------------------------------- 138 | $(BUILD): 139 | @[ -d $@ ] || mkdir -p $@ 140 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 141 | 142 | #--------------------------------------------------------------------------------- 143 | clean: 144 | @echo clean ... 145 | @rm -fr $(BUILD) $(TARGET) 146 | 147 | #--------------------------------------------------------------------------------- 148 | else 149 | 150 | #--------------------------------------------------------------------------------- 151 | # main targets 152 | #--------------------------------------------------------------------------------- 153 | $(OUTPUT) : $(OFILES) 154 | @echo linking $(notdir $@) 155 | @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ 156 | 157 | #--------------------------------------------------------------------------------- 158 | %.bin.o : %.bin 159 | #--------------------------------------------------------------------------------- 160 | @echo $(notdir $<) 161 | $(bin2o) 162 | 163 | -include $(DEPSDIR)/*.d 164 | 165 | #--------------------------------------------------------------------------------------- 166 | endif 167 | #--------------------------------------------------------------------------------------- 168 | -------------------------------------------------------------------------------- /seedminer/saves/lfcs.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedminer/saves/lfcs.dat -------------------------------------------------------------------------------- /seedminer/saves/lfcs_new.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedminer/saves/lfcs_new.dat -------------------------------------------------------------------------------- /seedminer/saves/new-v2.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedminer/saves/new-v2.dat -------------------------------------------------------------------------------- /seedminer/saves/old-v2.dat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedminer/saves/old-v2.dat -------------------------------------------------------------------------------- /seedminer/seedminer_launcher3.py: -------------------------------------------------------------------------------- 1 | # Seedminer v2.1.5 2 | from binascii import hexlify, unhexlify 3 | import glob 4 | import os 5 | import signal 6 | import struct 7 | import subprocess 8 | import sys 9 | import time 10 | import urllib.request 11 | 12 | # don't change this mid brute force - can be different amount multiple computers - powers of two recommended for even distribution of workload 1 2 4 8 etc. 13 | process_count = 4 14 | # ----------------------------------------------------------------------------------------------------------------- 15 | # Note: Optional argument parsing will override the following two variables and multiply them by 2! 16 | # If optional arguments are not provided, the following two variables will not be multiplied. 17 | # --- 18 | # for gpu options 19 | offset_override = 0 # this allows starting brute-force at a user-defined offset 20 | # --- 21 | # only for the do_gpu() function (movable.sed brute-forcing) 22 | max_msky_offset = 16384 # this allows ending at a user-defined offset; 16384 should be considered the max though! 23 | # ----------------------------------------------------------------------------------------------------------------- 24 | # for gpu options 25 | # set this variable to "True" (without the quotes) if you want to use less of your gpu while mining 26 | # your hash rate will decrease by a bit 27 | force_reduced_work_size = False 28 | # ----------------------------------------------------------------------------------------------------------------- 29 | # Don't edit below this line unless you have multiple computers brute-forcing - most of you won't need this feature 30 | # ----------------------------------------------------------------------------------------------------------------- 31 | number_of_computers = 1 # each computer needs this set to same number if more than one 32 | which_computer_is_this = 0 # each computer has a different id # that's less than number_of_computers 33 | # ----------------------------------------------------------------------------------------------------------------- 34 | # Don't edit below this line unless you know what you're doing (function defs begin) 35 | # ----------------------------------------------------------------------------------------------------------------- 36 | lfcs = [] 37 | ftune = [] 38 | lfcs_new = [] 39 | ftune_new = [] 40 | err_correct = 0 41 | os_name = os.name 42 | 43 | 44 | def signal_handler(sig, frame): # So KeyboardInterrupt exceptions don't appear 45 | sys.exit(0) 46 | 47 | 48 | signal.signal(signal.SIGINT, signal_handler) 49 | 50 | 51 | def int16bytes(n): 52 | return n.to_bytes(16, 'big') 53 | 54 | 55 | def expand(): 56 | for i in range(1, len(lfcs)): 57 | lfcs[i] = lfcs[i] << 12 | 0x800 58 | 59 | for i in range(1, len(lfcs_new)): 60 | lfcs_new[i] = lfcs_new[i] << 12 | 0x800 61 | 62 | 63 | def bytes2int(s): 64 | n = 0 65 | for i in range(4): 66 | n += ord(s[i:i + 1]) << (i * 8) 67 | return n 68 | 69 | 70 | def int2bytes(n): 71 | s = bytearray(4) 72 | for i in range(4): 73 | s[i] = n & 0xFF 74 | n = n >> 8 75 | return s 76 | 77 | 78 | def byteswap4(n): 79 | # using a slice to reverse is better, and easier for bytes 80 | return n[::-1] 81 | 82 | 83 | def endian4(n): 84 | return (n & 0xFF000000) >> 24 | (n & 0x00FF0000) >> 8 | (n & 0x0000FF00) << 8 | (n & 0x000000FF) << 24 85 | 86 | 87 | def getmsed3estimate(n, isnew): 88 | global err_correct 89 | newbit = 0x0 90 | if isnew: 91 | fc = lfcs_new 92 | ft = ftune_new 93 | newbit = 0x80000000 94 | else: 95 | fc = lfcs 96 | ft = ftune 97 | 98 | fc_size = len(fc) 99 | ft_size = len(ft) 100 | 101 | if fc_size != ft_size: 102 | return -1 103 | 104 | for i in range(fc_size): 105 | if n < fc[i]: 106 | xs = (n - fc[i - 1]) 107 | xl = (fc[i] - fc[i - 1]) 108 | y = ft[i - 1] 109 | yl = (ft[i] - ft[i - 1]) 110 | ys = ((xs * yl) // xl) + y 111 | err_correct = ys 112 | return ((n // 5) - ys) | newbit 113 | 114 | return ((n // 5) - ft[ft_size - 1]) | newbit 115 | 116 | 117 | def mii_gpu(year = 0, model = None): 118 | from Cryptodome.Cipher import AES 119 | 120 | nk31 = 0x59FC817E6446EA6190347B20E9BDCE52 121 | with open("input.bin", "rb") as f: 122 | enc = f.read() 123 | if len(enc) != 0x70: 124 | print("Error: input.bin is invalid size (likely QR -> input.bin conversion issue)") 125 | sys.exit(1) 126 | nonce = enc[:8] + b"\x00" * 4 127 | cipher = AES.new(int16bytes(nk31), AES.MODE_CCM, nonce) 128 | dec = cipher.decrypt(enc[8:0x60]) 129 | nonce = nonce[:8] 130 | final = dec[:12] + nonce + dec[12:] 131 | 132 | with open("output.bin", "wb") as f: 133 | f.write(final) 134 | if len(sys.argv) >= 3: 135 | model = sys.argv[2].lower() 136 | else: 137 | print("Error: need to specify new|old movable.sed") 138 | sys.exit(1) 139 | model_str = b"" 140 | start_lfcs_old = 0x0B000000 // 2 141 | start_lfcs_new = 0x05000000 // 2 142 | start_lfcs = 0 143 | 144 | if len(sys.argv) == 4: 145 | year = int(sys.argv[3]) 146 | 147 | if model == "old": 148 | model_str = b"\x00\x00" 149 | if year == 2011: 150 | start_lfcs_old = 0x01000000 151 | elif year == 2012: 152 | start_lfcs_old = 0x04000000 153 | elif year == 2013: 154 | start_lfcs_old = 0x07000000 155 | elif year == 2014: 156 | start_lfcs_old = 0x09000000 157 | elif year == 2015: 158 | start_lfcs_old = 0x09800000 159 | elif year == 2016: 160 | start_lfcs_old = 0x0A000000 161 | elif year == 2017: 162 | start_lfcs_old = 0x0A800000 163 | else: 164 | print("Year 2011-2017 not entered so beginning at lfcs midpoint " + hex(start_lfcs_old)) 165 | start_lfcs = start_lfcs_old 166 | 167 | elif model == "new": 168 | model_str = b"\x02\x00" 169 | if year == 2014: 170 | start_lfcs_new = 0x00800000 171 | elif year == 2015: 172 | start_lfcs_new = 0x01800000 173 | elif year == 2016: 174 | start_lfcs_new = 0x03000000 175 | elif year == 2017: 176 | start_lfcs_new = 0x04000000 177 | else: 178 | print("Year 2014-2017 not entered so beginning at lfcs midpoint " + hex(start_lfcs_new)) 179 | start_lfcs = start_lfcs_new 180 | start_lfcs = endian4(start_lfcs) 181 | if os_name == 'nt': 182 | init_command = "bfcl lfcs {:08X} {} {} {:08X}".format(start_lfcs, hexlify(model_str).decode('ascii'), hexlify(final[4:4 + 8]).decode('ascii'), endian4(offset_override)) 183 | else: 184 | init_command = "./bfcl lfcs {:08X} {} {} {:08X}".format(start_lfcs, hexlify(model_str).decode('ascii'), hexlify(final[4:4 + 8]).decode('ascii'), endian4(offset_override)) 185 | print(init_command) 186 | if force_reduced_work_size is True: 187 | command = "{} rws".format(init_command) 188 | subprocess.call(command.split()) 189 | else: 190 | command = "{} sws".format(init_command) 191 | proc = subprocess.call(command.split()) 192 | if proc == 251 or proc == 4294967291: # Help wanted for a better way of catching an exit code of '-5' 193 | time.sleep(3) # Just wait a few seconds so we don't burn out our graphics card 194 | subprocess.call("{} rws".format(init_command).split()) 195 | 196 | 197 | def generate_part2(): 198 | global err_correct 199 | with open("saves/old-v2.dat", "rb") as f: 200 | buf = f.read() 201 | 202 | lfcs_len = len(buf) // 8 203 | err_correct = 0 204 | 205 | for i in range(lfcs_len): 206 | lfcs.append(struct.unpack(" 1: 322 | print("Too many ID0 dirs! ({})\nMove the ones your 3DS isn't using!".format(hashcount)) 323 | pause() 324 | sys.exit(1) 325 | 326 | if hashcount == 1: 327 | print("Hash added!") 328 | else: 329 | print("No hashes added!") 330 | pause() 331 | sys.exit(0) 332 | 333 | with open("movable_part1.sed.backup", "wb") as f: 334 | f.write(file) 335 | 336 | file = file[:0x10] 337 | pad_len = 0x1000 - len(file+buf) 338 | pad = b"\x00" * pad_len 339 | with open("movable_part1.sed", "wb") as f: 340 | f.write(file + buf + pad) 341 | print("There are now {} ID0 hashes in your movable_part1.sed!".format(len(file + buf) // 0x20)) 342 | print("Done!") 343 | 344 | 345 | def do_cpu(): 346 | global process_count 347 | if len(sys.argv) == 3: 348 | process_count = int(sys.argv[2]) 349 | 350 | if which_computer_is_this >= number_of_computers: 351 | print("You can't assign an id # to a computer that doesn't exist") 352 | sys.exit(1) 353 | 354 | max_1 = 0x100000000 355 | address_begin = 0 356 | address_end = max_1 357 | 358 | address_space = max_1 // number_of_computers 359 | 360 | for i in range(number_of_computers): 361 | if which_computer_is_this == i: 362 | address_begin = (i * address_space) 363 | address_end = (address_begin + address_space) 364 | print("This computer id: " + str(i)) 365 | if which_computer_is_this == number_of_computers - 1: 366 | address_end = max_1 367 | 368 | print("Overall starting msed2 address: " + hex(address_begin)) 369 | print("Overall ending msed2 address: " + hex(address_end) + "\n") 370 | 371 | process_space = address_end - address_begin 372 | process_size = process_space // process_count 373 | 374 | multi_procs = [] 375 | for i in range(process_count): 376 | process_begin = address_begin + (process_size * i) 377 | process_end = process_begin + process_size 378 | if i == process_count - 1: 379 | process_end = address_end 380 | start = process_begin 381 | size = process_end - process_begin 382 | time.sleep(0.25) # For readability and organization 383 | print("\nProcess: " + str(i) + " Start: " + hex(process_begin) + " Size: " + hex(size)) 384 | if os_name == 'nt': 385 | proc = subprocess.Popen("seedminer {:08X} {:09X}".format(start, size).split()) 386 | else: 387 | proc = subprocess.Popen("./seedminer {:08X} {:09X}".format(start, size).split()) 388 | multi_procs.append(proc) 389 | for proc in multi_procs: 390 | proc.wait() 391 | 392 | 393 | def do_gpu(): 394 | with open("movable_part2.sed", "rb") as f: 395 | buf = f.read() 396 | keyy = hexlify(buf[:16]).decode('ascii') 397 | id0 = hexlify(buf[16:32]).decode('ascii') 398 | if os_name == 'nt': 399 | init_command = "bfcl msky {} {} {:08X} {:08X}".format(keyy, id0, endian4(offset_override), endian4(max_msky_offset)) 400 | else: 401 | init_command = "./bfcl msky {} {} {:08X} {:08X}".format(keyy, id0, endian4(offset_override), endian4(max_msky_offset)) 402 | print(init_command) 403 | if force_reduced_work_size is True: 404 | command = "{} rws".format(init_command) 405 | proc = subprocess.call(command.split()) 406 | else: 407 | command = "{} sws sm".format(init_command) 408 | proc = subprocess.call(command.split()) 409 | if proc == 251 or proc == 4294967291: # Help wanted for a better way of catching an exit code of '-5' 410 | time.sleep(3) # Just wait a few seconds so we don't burn out our graphics card 411 | command = "{} rws sm".format(init_command) 412 | proc = subprocess.call(command.split()) 413 | return proc 414 | 415 | 416 | def download(url, dest): 417 | try: 418 | data=b"" 419 | response = urllib.request.urlopen(url) 420 | html = response.read() 421 | if os.path.exists(dest): 422 | with open(dest, "rb") as f: 423 | data = f.read() 424 | if len(data) < len(html): 425 | with open(dest, "wb") as f: 426 | f.write(html) 427 | print("Updating " + dest + " success!") 428 | else: 429 | print(dest + " is already up-to-date!") 430 | except: 431 | print("Error updating " + dest) 432 | 433 | 434 | def update_db(): 435 | download("https://github.com/zoogie/nodes/blob/master/old-v2.dat?raw=true", "saves/old-v2.dat") 436 | download("https://github.com/zoogie/nodes/blob/master/new-v2.dat?raw=true", "saves/new-v2.dat") 437 | 438 | 439 | def error_print(): 440 | print("\nCommand line error") 441 | print("Usage:") 442 | print("python {} cpu|gpu|id0|mii old|mii new|update-db [# cpu processes] [starting gpu offset] [max gpu offset] [ID0 hash] [year 3ds built]".format(sys.argv[0])) 443 | print("Examples:") 444 | print("python {} cpu".format(sys.argv[0])) 445 | print("python {} cpu 4".format(sys.argv[0])) 446 | print("python {} gpu".format(sys.argv[0])) 447 | print("python {} gpu 0".format(sys.argv[0])) 448 | print("python {} gpu 0 8192".format(sys.argv[0])) 449 | print("python {} id0 abcdef012345EXAMPLEdef0123456789".format(sys.argv[0])) 450 | print("python {} mii new 2017".format(sys.argv[0])) 451 | print("python {} mii old 2011".format(sys.argv[0])) 452 | print("python {} mii new".format(sys.argv[0])) 453 | print("python {} mii old".format(sys.argv[0])) 454 | print("python {} update-db".format(sys.argv[0])) 455 | 456 | 457 | # --------------------------------------------------------------------------- 458 | # command handler 459 | # --------------------------------------------------------------------------- 460 | abspath = os.path.abspath(__file__) 461 | dname = os.path.dirname(abspath) 462 | os.chdir(dname) 463 | 464 | #Here the "__name__" == "__main__" part is needed in order to avoid the script from printing the error messages and exiting when imported from the other script 465 | if __name__ == "__main__": 466 | if len(sys.argv) < 2 or len(sys.argv) > 4: 467 | error_print() 468 | sys.exit(1) 469 | 470 | if sys.argv[1].lower() == "gpu": 471 | if len(sys.argv) == 3 or len(sys.argv) == 4: 472 | try: 473 | offset_override = int(sys.argv[2]) * 2 474 | except ValueError: 475 | print("Invalid parameter supplied!") 476 | sys.exit(1) 477 | if len(sys.argv) == 4: 478 | try: 479 | max_msky_offset = int(sys.argv[3]) * 2 480 | except ValueError: 481 | print("Invalid parameter supplied!") 482 | sys.exit(1) 483 | print("GPU selected") 484 | generate_part2() 485 | sys.exit(do_gpu()) 486 | elif sys.argv[1].lower() == "cpu": 487 | print("CPU selected") 488 | generate_part2() 489 | do_cpu() 490 | sys.exit(0) 491 | elif sys.argv[1].lower() == "id0": 492 | print("ID0 selected") 493 | hash_clusterer() 494 | sys.exit(0) 495 | elif sys.argv[1].lower() == "mii": 496 | print("MII selected") 497 | mii_gpu() 498 | generate_part2() 499 | offset_override = 0 500 | sys.exit(do_gpu()) 501 | elif sys.argv[1].lower() == "update-db": 502 | print("Update msed_data selected") 503 | update_db() 504 | sys.exit(0) 505 | else: 506 | error_print() 507 | sys.exit(1) 508 | -------------------------------------------------------------------------------- /seedminer/seedminer_launcher3_GUI.py: -------------------------------------------------------------------------------- 1 | #Seedminer Text-based UI v1.0 2 | 3 | #fef0fef0fef0fef0fef0fef0fef0fef0 4 | #↑↑↑↑↑dummy ID0 for testing↑↑↑↑↑ 5 | #10 points for Gryffindor if you get the reference 6 | 7 | #"Press any key to continue" message 8 | def pause(alt_msg = None): 9 | if alt_msg == None: 10 | input("Press any key to continue...") 11 | else: 12 | input(alt_msg) 13 | 14 | try: 15 | import seedminer_launcher3 as sl3 16 | except ModuleNotFoundError: 17 | print("This script needs to be placed in the same direcory as the seedminer_launcher3.py script") 18 | pause("Press any key to exit") 19 | exit(1) 20 | 21 | import os 22 | import sys 23 | import signal 24 | from textwrap import dedent 25 | 26 | force_reduced_work_size = False 27 | offset_override = 0 28 | 29 | ##########FUNCTIONS########## 30 | def signal_handler(sig, frame): # So KeyboardInterrupt exceptions don't appear 31 | sys.exit(0) 32 | 33 | def bfcl_signal_handler(sig, frame): #Shows a message if the users interrupts bruteforcing 34 | print("\n\nBruteforcing aborted by the user. If you want to resume it later, TAKE NOTE of the offset value shown above!") 35 | pause() 36 | sys.exit(0) 37 | 38 | signal.signal(signal.SIGINT, signal_handler) 39 | 40 | #Checks if ID0 is valid 41 | def is_id0_valid(id0): 42 | try: 43 | print(id0, end='') 44 | sys.stdout.flush() 45 | int(id0, 16) 46 | if len(id0) == 32: 47 | print(" -- valid ID0") 48 | return True 49 | else: 50 | print(" -- improper ID0 length") 51 | sys.stdout.flush() 52 | return False 53 | except: 54 | print(" -- not an ID0") 55 | return False 56 | 57 | #Clears the screen 58 | def clear_screen(): 59 | stupidworkaroundvariable = os.system("cls") if os.name == "nt" else print("\033c", end="") 60 | del stupidworkaroundvariable 61 | #This mess of a code is to support clearing the screen on both Windows and Unix 62 | #The "stupidworkaroundvariable" is used to prevent the cls return code on the screen (without it a 0 would've been automatically printed after clearing the screen, which is kinda pointless) 63 | #Thank you https://stackoverflow.com/a/23075152 and https://stackoverflow.com/a/2084628 , my solution uses a combination of both 64 | 65 | #Asks a simple yes/no questions, and returns True or False accordingly 66 | def ask_yes_no(msg): 67 | inp = input(msg + " (y/n) ") 68 | while True: 69 | if inp.lower() == "y": 70 | return True 71 | elif inp.lower() == "n": 72 | return False; 73 | else: 74 | inp = input("Please enter a valid option (y/n) ") 75 | 76 | #Asks to input a number from a list of choices 77 | def ask_list_input(count, allow_s): 78 | rang = range(1, count + 1) 79 | inp = input("\nPlease select an option: ") 80 | while True: 81 | if inp.lower() == "s": 82 | return "s" 83 | try: 84 | if int(inp) in rang: 85 | return int(inp) 86 | else: 87 | raise ValueError 88 | except ValueError: 89 | inp = input("Please select a valid option: ") 90 | 91 | 92 | 93 | #Asks to delete no longer needed files 94 | def ask_for_deletion(): 95 | inp = ask_yes_no("\nDo you want to delete no longer needed files? ") 96 | if inp == True: 97 | try: 98 | os.remove("movable_part1.sed") 99 | os.remove("movable_part1.sed.backup") 100 | os.remove("movable_part2.sed") 101 | os.remove("input.bin") 102 | except FileNotFoundError: 103 | print("", end="") #really stupid workaround 104 | 105 | #Asks to rename the movable.sed in order to contain the friend code 106 | def ask_for_renaming(): 107 | inp = ask_yes_no("Do you want to rename the movable.sed file to contain the friend code?") 108 | if inp == True: 109 | inp = input("Enter the friend code: ") 110 | fc = ''.join([i for i in inp if i.isdigit()]) 111 | os.rename("movable.sed", "movable_" + fc + ".sed") 112 | 113 | #Due to how bfcl's offset argument works, this is required so support negative numbers. Does NOT include non-integer input failsafe, so this should be wrapped in a try/except block 114 | def get_offset_arg(ofs): 115 | ofs = int(ofs) 116 | if ofs == 0: 117 | offset_override = 0 118 | elif ofs > 0: 119 | offset_override = ofs * 2 - 1 120 | else: 121 | offset_override = abs(ofs) * 2 122 | print("Bruteforcing will resume on offset {}".format(ofs)) 123 | return offset_override 124 | 125 | #Shows the main menu 126 | def show_main_menu(): 127 | clear_screen() 128 | #Protip about dedent: by doing like this print statement below, eg triple quotes without immediately going to a new line, the other lines will still show one unit of indent. On the other hand, immediately going to a new line after the quotes (like in show_gpu_options()) will make everything dedented. 129 | print(dedent("""Available options: 130 | 1. GPU bruteforce (normal) (recommended) 131 | 2. GPU bruteforce (with options) 132 | 3. CPU bruteforce 133 | 4. Mii bruteforce 134 | Note: the LCFS databases will be automatically updated""")) 135 | mode = ask_list_input(4, False) 136 | while True: 137 | inp = input("Enter the ID0: ") 138 | if is_id0_valid(inp) == True: 139 | id0 = inp 140 | break; 141 | if mode == 1: 142 | sl3.update_db() 143 | sl3.hash_clusterer(id0) 144 | sl3.generate_part2() 145 | signal.signal(signal.SIGINT, bfcl_signal_handler) 146 | sl3.do_gpu() 147 | elif mode == 2: 148 | show_gpu_options() 149 | sl3.update_db() 150 | sl3.hash_clusterer(id0) 151 | sl3.generate_part2() 152 | signal.signal(signal.SIGINT, bfcl_signal_handler) 153 | sl3.do_gpu() 154 | elif mode == 3: 155 | sl3.update_db() 156 | sl3.hash_clusterer(id0) 157 | sl3.generate_part2() 158 | sl3.do_cpu() 159 | elif mode == 4: 160 | model = None 161 | year = None 162 | inp = input("Which model is the 3DS? (old/new) ") 163 | while True: 164 | if inp.lower() == "old": 165 | model = "old" 166 | break 167 | elif inp.lower() == "new": 168 | model = "new" 169 | break 170 | else: 171 | inp = input("Please enter a valid option (old/new): ") 172 | while True: 173 | inp = input("Which year was the 3DS built (if you're not sure/don't know, enter 0)? ") 174 | try: 175 | year = int(inp) 176 | break 177 | except ValueError: 178 | inp = ("Please enter the year was the 3DS built (if you're not sure/don't know, enter 0): ") 179 | sl3.mii_gpu(year, model) 180 | sl3.hash_clusterer(id0) 181 | sl3.generate_part2() 182 | sl3.offset_override = 0 183 | sl3.force_reduced_work_size = False 184 | signal.signal(signal.SIGINT, bfcl_signal_handler) 185 | sl3.do_gpu() 186 | ask_for_deletion() 187 | ask_for_renaming() 188 | print("Done") 189 | pause() 190 | 191 | #Shows the GPU bruteforcing options if the corresponding option is selected 192 | def show_gpu_options(): 193 | ofs = 0 194 | while True: 195 | clear_screen() 196 | print(dedent("""Available options (and their respective current status): 197 | 1. Enabled reduced work size: {} (default is False) 198 | 2. Starting offset: {} (Default is 0) 199 | Type "s" when you're ready to start""".format(sl3.force_reduced_work_size, ofs))) 200 | inp = ask_list_input(2, True) 201 | if inp == 1: 202 | sl3.force_reduced_work_size = ask_yes_no(dedent(""" 203 | Reduced work size allows to use less of your GPU while bruteforcing. This can be useful if the computer becomes unresponsive, but it will make the bruteforcing process slower. 204 | Do you want to enable reduced work size?""")) 205 | 206 | elif inp == 2: 207 | print(dedent(""" 208 | This allows to resuming a previous bruteforcing job, by changing which offset to start bruteforcing at. 209 | WARNING! ONLY use this is you're resuming a previous bruteforce, and ONLY if you know exactly where it stopped! 210 | Don't use this to start bruteforcing at random offsets!""")) 211 | print("Which offset do you want to resume from? ", end="") 212 | while True: 213 | ofs = input() 214 | try: 215 | sl3.offset_override = get_offset_arg(ofs) 216 | break 217 | except ValueError: 218 | print("Please enter a valid number: ", end="") 219 | elif inp == "s": 220 | print("") 221 | break 222 | 223 | ##########END OF FUNCTIONS########## 224 | 225 | show_main_menu() -------------------------------------------------------------------------------- /seedminer/source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include "types.h" 10 | 11 | #ifdef _WIN32 12 | #define LL "I64" 13 | #else 14 | #define LL "ll" 15 | #endif 16 | 17 | u8 sha256[0x20]={0}; 18 | u8 ID0[0x10]={0}; 19 | u8 part2[0x20]={0}; 20 | u8 msed[0x140]={0}; 21 | u32 keyy[4]={0}; 22 | u32 save_offset=0; 23 | 24 | u32 check_finish(){ 25 | FILE *f=fopen("movable.sed","rb"); 26 | if(!f) return 0; 27 | fclose(f); 28 | printf("Dumped movable.sed detected, closing down process...\n"); 29 | return 1; 30 | } 31 | 32 | u32 save_progress(u64 start, u64 size, u32 progress){ 33 | char savename[0x100]={0}; 34 | snprintf(savename,0xFF,"saves/save_%08"LL"X-%09"LL"X.bin", (unsigned long long) start, (unsigned long long) size); 35 | FILE *f=fopen(savename,"wb+"); 36 | if(f){ 37 | printf("\nSaving progress to file %s ...\n\n", savename); 38 | fwrite(&progress, 1, 4, f); 39 | fclose(f); 40 | } 41 | else{ 42 | printf("\nError: could not open %s\n\n", savename); 43 | return 1; 44 | } 45 | return 0; 46 | } 47 | 48 | u32 load_progress(u64 start, u64 size){ 49 | char savename[0x100]={0}; 50 | snprintf(savename,0xFF,"saves/save_%08"LL"X-%09"LL"X.bin", (unsigned long long) start, (unsigned long long) size); 51 | FILE *f=fopen(savename,"rb"); 52 | if(f){ 53 | printf("Loading %s ...\n", savename); 54 | if (fread(&save_offset, 1, 4, f) != 4) { 55 | fprintf(stderr, "error durring fread\n"); 56 | exit(-1); 57 | } 58 | fclose(f); 59 | 60 | s32 neg = save_offset&1 ? -1 : 1; 61 | s32 offset_converted = neg*((s32)save_offset+1)/2; 62 | printf("Resuming at msed3 offset %d\n\n", offset_converted); 63 | } 64 | else{ 65 | printf("Note: could not open %s\n", savename); 66 | printf("Starting at msed3 offset 0\n\n"); 67 | return 1; 68 | } 69 | return 0; 70 | } 71 | 72 | s32 bf_block(u32 offset, u64 start, u64 size){ 73 | //size=0x800000; 74 | u64 finish=start+size; 75 | 76 | s32 neg = offset&1 ? -1 : 1; 77 | s32 offset_converted = neg*((s32)offset+1)/2; 78 | 79 | if(offset_converted+((s32)keyy[3]&0x7FFFFFFF) < 0) return -2; //oob check 80 | 81 | printf("At msed2 address 0x%08"LL"X, size 0x%09"LL"X:\n", (unsigned long long) start, (unsigned long long) size); 82 | 83 | u32 original=keyy[3]; 84 | printf("Brute forcing msed3 offset %d (0x%08X)...\n\n", offset_converted, keyy[3]+offset_converted); 85 | keyy[3]+=offset_converted; 86 | for(u64 i=start;i \nNote that all values interpreted as hex\n"); 105 | #else 106 | printf("./seedminer \nNote that all values interpreted as hex\n"); 107 | #endif 108 | return 1; 109 | } 110 | 111 | start=strtoul(argv[1], NULL, 16); 112 | size=strtoul(argv[2],NULL, 16); 113 | 114 | printf("Loading movable_part2.sed...\n"); 115 | 116 | FILE *f; 117 | f = fopen("movable_part2.sed", "rb"); 118 | if(f==NULL)return 0; 119 | if (fread(part2, 1, 0x20, f) != 0x20) { 120 | fprintf(stderr, "error durring fread\n"); 121 | exit(-1); 122 | } 123 | fclose(f); 124 | 125 | memcpy(keyy, part2, 0x10); 126 | memcpy(ID0, part2+0x10, 0x10); 127 | 128 | load_progress(start, size); 129 | 130 | //keyy[3]=0x80000004; 131 | 132 | for(u32 i=save_offset;i<0x100000;i++){ 133 | ret = bf_block(i, start, size); 134 | if(!ret)break; 135 | if(check_finish()) return 0; 136 | if(ret == -1) save_progress(start, size, i+1); 137 | } 138 | 139 | printf("\nKEYY HIT!!!\n"); 140 | printf("Writing keyy to movable.sed...\n"); 141 | memcpy(msed+0x110, keyy, 0x10); 142 | printf("Dumping movable.sed (don't inject this to real 3ds) ...\n"); 143 | f = fopen("movable.sed", "wb"); 144 | fwrite(msed, 1, 0x140, f); 145 | fclose(f); 146 | printf("Done!\n"); 147 | 148 | srand(time(NULL)); 149 | char filename[0x100]={0}; 150 | u32 lfcs=keyy[0]; 151 | u32 lfcs_blk=lfcs>>12; 152 | s32 error=(lfcs/5)-((s32)keyy[3]&0x7FFFFFFF); 153 | u32 seedtype=(keyy[3]&0x80000000)>>31; 154 | snprintf(filename, 0x100, "msed_data_%08X.bin",rand()); 155 | f = fopen(filename, "wb"); 156 | fwrite(&lfcs_blk, 1, 4, f); 157 | fwrite(&error, 1, 4, f); 158 | fwrite(&seedtype, 1, 4, f); 159 | fclose(f); 160 | printf("\n%s dumped!\nJust keep it handy if you don't know what to do with it!\n", filename); 161 | printf("Done!\n\n"); 162 | printf("If applicable, any other seedminer processes will terminate shortly!\n\n"); 163 | return 0; 164 | } -------------------------------------------------------------------------------- /seedminer/source/types.h: -------------------------------------------------------------------------------- 1 | // Copyright 2010 booto 2 | // Licensed under the terms of the GNU GPL, version 2 3 | // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt 4 | #ifndef types_h 5 | #define types_h 6 | 7 | #include 8 | 9 | typedef int8_t s8; 10 | typedef uint8_t u8; 11 | typedef int16_t s16; 12 | typedef uint16_t u16; 13 | typedef int32_t s32; 14 | typedef uint32_t u32; 15 | typedef int64_t s64; 16 | typedef uint64_t u64; 17 | 18 | #endif 19 | -------------------------------------------------------------------------------- /seedstarter/LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 seedstarter 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 | -------------------------------------------------------------------------------- /seedstarter/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 | # ROMFS is the directory which contains the RomFS, relative to the Makefile (Optional) 21 | # APP_TITLE is the name of the app stored in the SMDH file (Optional) 22 | # APP_DESCRIPTION is the description of the app stored in the SMDH file (Optional) 23 | # APP_AUTHOR is the author of the app stored in the SMDH file (Optional) 24 | # ICON is the filename of the icon (.png), relative to the project folder. 25 | # If not set, it attempts to use one of the following (in this order): 26 | # - .png 27 | # - icon.png 28 | # - /default_icon.png 29 | #--------------------------------------------------------------------------------- 30 | TARGET := $(notdir $(CURDIR)) 31 | BUILD := build 32 | RESOURCES := resources 33 | SOURCES := source source/graphics source/services 34 | DATA := data 35 | INCLUDES := include include/graphics include/services 36 | ROMFS := romfs 37 | 38 | APP_TITLE := seedStarter 39 | APP_DESCRIPTION := Gather data for seedMiner 40 | APP_AUTHOR := Zoogie & Joel16 41 | 42 | ICON := $(RESOURCES)/icon.png 43 | BANNER := $(RESOURCES)/banner.png 44 | JINGLE := $(RESOURCES)/banner.wav 45 | LOGO := resources/logo.bcma.lz 46 | 47 | # CIA 48 | APP_PRODUCT_CODE := SEDMI 49 | APP_UNIQUE_ID := 0x5333D 50 | APP_SYSTEM_MODE := 64MB 51 | APP_SYSTEM_MODE_EXT := Legacy 52 | APP_ROMFS_DIR := $(TOPDIR)/romfs 53 | RSF_FILE := resources/cia.rsf 54 | 55 | VERSION_MAJOR := 1 56 | VERSION_MINOR := 2 57 | VERSION_MICRO := 0 58 | 59 | #--------------------------------------------------------------------------------- 60 | # options for code generation 61 | #--------------------------------------------------------------------------------- 62 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft 63 | 64 | CFLAGS := -g -Wall -O2 -mword-relocations \ 65 | -fomit-frame-pointer -ffunction-sections \ 66 | -DVERSION_MAJOR=$(VERSION_MAJOR) -DVERSION_MINOR=$(VERSION_MINOR) \ 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 := -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,$(DATA),$(CURDIR)/$(dir)) 96 | 97 | export DEPSDIR := $(CURDIR)/$(BUILD) 98 | 99 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 100 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 101 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 102 | PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) 103 | SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) 104 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 105 | 106 | #--------------------------------------------------------------------------------- 107 | # use CXX for linking C++ projects, CC for standard C 108 | #--------------------------------------------------------------------------------- 109 | ifeq ($(strip $(CPPFILES)),) 110 | #--------------------------------------------------------------------------------- 111 | export LD := $(CC) 112 | #--------------------------------------------------------------------------------- 113 | else 114 | #--------------------------------------------------------------------------------- 115 | export LD := $(CXX) 116 | #--------------------------------------------------------------------------------- 117 | endif 118 | #--------------------------------------------------------------------------------- 119 | 120 | export OFILES_SOURCES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 121 | 122 | export OFILES_BIN := $(addsuffix .o,$(BINFILES)) \ 123 | $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) 124 | 125 | export OFILES := $(OFILES_BIN) $(OFILES_SOURCES) 126 | 127 | export HFILES := $(PICAFILES:.v.pica=_shbin.h) $(addsuffix .h,$(subst .,_,$(BINFILES))) 128 | 129 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 130 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 131 | -I$(CURDIR)/$(BUILD) 132 | 133 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 134 | 135 | ifeq ($(strip $(ICON)),) 136 | icons := $(wildcard *.png) 137 | ifneq (,$(findstring $(TARGET).png,$(icons))) 138 | export APP_ICON := $(TOPDIR)/$(TARGET).png 139 | else 140 | ifneq (,$(findstring icon.png,$(icons))) 141 | export APP_ICON := $(TOPDIR)/icon.png 142 | endif 143 | endif 144 | else 145 | export APP_ICON := $(TOPDIR)/$(ICON) 146 | endif 147 | 148 | ifeq ($(strip $(NO_SMDH)),) 149 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 150 | endif 151 | 152 | ifneq ($(ROMFS),) 153 | export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) 154 | endif 155 | 156 | .PHONY: $(BUILD) clean all cia 157 | 158 | #--------------------------------------------------------------------------------- 159 | all: $(BUILD) 160 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 161 | 162 | #--------------------------------------------------------------------------------- 163 | $(BUILD): 164 | @[ -d $@ ] || mkdir -p $@ 165 | 166 | #--------------------------------------------------------------------------------- 167 | clean: 168 | @echo clean ... 169 | @rm -fr $(BUILD) $(TARGET).bin $(TARGET).3dsx $(TARGET).smdh $(TARGET).cia $(TARGET).elf 170 | 171 | 172 | #--------------------------------------------------------------------------------- 173 | cia: $(BUILD) 174 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile cia 175 | 176 | #--------------------------------------------------------------------------------- 177 | 3dsx: $(BUILD) 178 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 3dsx 179 | 180 | #--------------------------------------------------------------------------------- 181 | else 182 | 183 | DEPENDS := $(OFILES:.o=.d) 184 | 185 | #--------------------------------------------------------------------------------- 186 | # main targets 187 | #--------------------------------------------------------------------------------- 188 | all: $(OUTPUT).cia $(OUTPUT).3dsx 189 | 190 | 3dsx: $(OUTPUT).3dsx 191 | 192 | cia: $(OUTPUT).cia 193 | 194 | ifeq ($(strip $(NO_SMDH)),) 195 | $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh 196 | $(OUTPUT).smdh : $(TOPDIR)/Makefile 197 | else 198 | $(OUTPUT).3dsx : $(OUTPUT).elf 199 | endif 200 | 201 | $(OUTPUT).elf : $(OFILES) 202 | 203 | $(OUTPUT).smdh : $(APP_ICON) 204 | @bannertool makesmdh -s "$(APP_TITLE)" -l "$(APP_DESCRIPTION)" -p "$(APP_AUTHOR)" -i $(APP_ICON) -o $@ 205 | @echo "built ... $(notdir $@)" 206 | 207 | $(OUTPUT).cia : $(OUTPUT).elf $(OUTPUT).smdh $(TARGET).bnr 208 | @3dstool -cvtf romfs $(OUTPUT).bin --romfs-dir $(APP_ROMFS_DIR) 209 | @makerom -f cia -o $(OUTPUT).cia -DAPP_ENCRYPTED=false -DAPP_UNIQUE_ID=$(APP_UNIQUE_ID) \ 210 | -elf $(OUTPUT).elf -rsf $(TOPDIR)/$(RSF_FILE) \ 211 | -icon $(OUTPUT).smdh -banner $(TARGET).bnr \ 212 | -exefslogo -target t -romfs "$(OUTPUT).bin" \ 213 | -major $(VERSION_MAJOR) \ 214 | -minor $(VERSION_MINOR) \ 215 | -micro $(VERSION_MICRO) 216 | 217 | @echo "built ... $(notdir $@)" 218 | 219 | $(TARGET).bnr : $(TOPDIR)/$(BANNER) $(TOPDIR)/$(JINGLE) 220 | @bannertool makebanner -o $@ -i $(TOPDIR)/$(BANNER) -ca $(TOPDIR)/$(JINGLE) 221 | @echo "built ... $@" 222 | 223 | #--------------------------------------------------------------------------------- 224 | # you need a rule like this for each extension you use as binary data 225 | #--------------------------------------------------------------------------------- 226 | %.bin.o : %.bin 227 | #--------------------------------------------------------------------------------- 228 | @echo $(notdir $<) 229 | @$(bin2o) 230 | 231 | #--------------------------------------------------------------------------------- 232 | # you need a rule like this for each extension you use as binary data 233 | #--------------------------------------------------------------------------------- 234 | %.png.o %_png.h : %.png 235 | #--------------------------------------------------------------------------------- 236 | @echo $(notdir $<) 237 | @$(bin2o) 238 | 239 | #--------------------------------------------------------------------------------- 240 | # rules for assembling GPU shaders 241 | #--------------------------------------------------------------------------------- 242 | define shader-as 243 | $(eval CURBIN := $*.shbin) 244 | $(eval DEPSFILE := $(DEPSDIR)/$*.shbin.d) 245 | echo "$(CURBIN).o: $< $1" > $(DEPSFILE) 246 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h 247 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h 248 | echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h 249 | picasso -o $(CURBIN) $1 250 | bin2s $(CURBIN) | $(AS) -o $*.shbin.o 251 | endef 252 | 253 | %.shbin.o %_shbin.h : %.v.pica %.g.pica 254 | @echo $(notdir $^) 255 | @$(call shader-as,$^) 256 | 257 | %.shbin.o %_shbin.h : %.v.pica 258 | @echo $(notdir $<) 259 | @$(call shader-as,$<) 260 | 261 | %.shbin.o %_shbin.h : %.shlist 262 | @echo $(notdir $<) 263 | @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)$(file))) 264 | @$(call shader-as,$<) 265 | 266 | -include $(DEPENDS) 267 | 268 | #--------------------------------------------------------------------------------------- 269 | endif 270 | #--------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /seedstarter/include/fs.h: -------------------------------------------------------------------------------- 1 | #ifndef FS_H 2 | #define FS_H 3 | 4 | #include <3ds.h> 5 | 6 | FS_Archive fsArchive, ctrArchive; 7 | 8 | void openArchive(FS_ArchiveID id); 9 | void closeArchive(FS_ArchiveID id); 10 | Result makeDir(FS_Archive archive, const char * path); 11 | bool fileExists(FS_Archive archive, const char * path); 12 | bool fileExistsNand(const char * path); 13 | bool dirExists(FS_Archive archive, const char * path); 14 | Result writeFile(const char * path, void * buf); 15 | Result copy_file(char * old_path, char * new_path); 16 | 17 | 18 | #endif -------------------------------------------------------------------------------- /seedstarter/include/services/frd.h: -------------------------------------------------------------------------------- 1 | #ifndef FRD_H 2 | #define FRD_H 3 | 4 | #include <3ds.h> 5 | 6 | #define SDK(a, b, c, d) ((a<<24) | (b<<16) | (c<<8) | d) 7 | 8 | #define FRIENDS_SCREEN_NAME_SIZE 0x16 // 11 (0x16 because UTF-16) 9 | #define FRIENDS_COMMENT_SIZE 0x22 // 16 (0x21 because UTF-16 + null character) 10 | #define FRIEND_LIST_SIZE 0x64 // 100 11 | #define FRIEND_MII_STORE_DATA_SIZE 0x60 // 96 12 | 13 | typedef struct 14 | { 15 | u32 principalId; 16 | u64 localFriendCode; 17 | } FriendKey; 18 | 19 | typedef struct 20 | { 21 | u32 joinAvailabilityFlag; 22 | u32 matchmakeSystemType; 23 | u32 joinGameId; 24 | u32 joinGameMode; 25 | u32 ownerPrincipalId; 26 | u32 joinGroupId; 27 | u8 applicationArg[0x14]; 28 | } GameMode; 29 | 30 | typedef struct 31 | { 32 | GameMode gameMode; 33 | wchar_t modeDescription[0x80]; 34 | } MyPresence; 35 | 36 | /* 37 | The following Mii data struct is from SpecializeMii. 38 | */ 39 | typedef enum MII_SPECIALNESS_t 40 | { 41 | MII_SPECIAL = 0, 42 | MII_NONSPECIAL = 1, 43 | } MII_SPECIALNESS; 44 | 45 | typedef enum MII_COPYABLE_t 46 | { 47 | MII_COPYABLE_OFF = 0, 48 | MII_COPYABLE_ON = 1, 49 | } MII_COPYABLE; 50 | 51 | typedef enum MII_SHAREABLE_t 52 | { 53 | MII_SHAREABLE_ON = 0, 54 | MII_SHAREABLE_OFF = 1, 55 | } MII_SHAREABLE; 56 | 57 | /* Fuck yeah! Bitfields and compiler dependent struct padding! 58 | * 59 | * This is absolutely *NOT* portable in any way, shape or form. 60 | * */ 61 | 62 | typedef union MiiPosition_t 63 | { 64 | u8 raw; 65 | struct 66 | { 67 | u8 page : 4; 68 | u8 slot : 4; 69 | }; 70 | } MiiPosition; 71 | 72 | typedef union MiiEyebrow_t 73 | { 74 | u32 raw; 75 | struct 76 | { 77 | u32 rotation : 4; 78 | u32 _unk_bit_4 : 1; 79 | u32 xspacing : 4; 80 | u32 ypos : 5; 81 | u32 _unk_bit_14_15 : 2; 82 | u32 style : 5; 83 | u32 color : 3; 84 | u32 xscale : 4; 85 | u32 yscale : 4; 86 | }; 87 | } MiiEyebrow; 88 | /* 89 | typedef struct 90 | { 91 | u16 pad1[0x45]; 92 | u16 name[0xA]; 93 | u16 pad2[0x31]; 94 | u16 pad3[0x100]; 95 | } MiiStoreData; 96 | */ 97 | 98 | typedef struct 99 | { 100 | union 101 | { 102 | struct 103 | { 104 | u8 _unk_0x00; 105 | u8 copyable; // 0 = not copyable, and 1 = copyable 106 | MiiPosition position; 107 | u8 category; 108 | }; 109 | u32 mii_id; 110 | }; 111 | 112 | u32 sys_id; 113 | u32 _unk_0x08; 114 | 115 | union 116 | { 117 | // This unsigned 32bit integer is stored in big-endian and holds the 118 | // date of creation in its lower 28 bit: 119 | // 120 | // seconds since 01/01/2010 00:00:00 121 | // = (date_of_creation[bit 0 .. bit 27]) * 2 122 | u32 date_of_creation; 123 | 124 | // Non special Miis have bit 31 of aforementioned big-endian word set, 125 | // which corresponds to bit 8 in little endian, which the 3DS uses. 126 | struct 127 | { 128 | u32 : 7; 129 | u32 specialness : 1; 130 | u32 : 24; 131 | }; 132 | }; 133 | 134 | u8 mac[6]; 135 | u8 _pad_0x16[2]; 136 | 137 | u16 gender : 1; // 0 = male, 1 = female 138 | u16 bday_month : 4; 139 | u16 bday_day : 5; 140 | u16 color : 4; // 0 = Red, 1 = Orange, 2 = Yellow, 3 = Lime green, 4 = Green, 5 = Blue, 6 = Neon blue, 7 = Pink, 8 = Purple, 9 = Brown, 10 = White, and 11 = Black. 141 | u16 favorite : 1; // 0 = No, and 1 = Yes. 142 | u16 _unk_0x19 : 1; 143 | 144 | u16 name[0xA]; 145 | 146 | u8 width; 147 | u8 height; 148 | 149 | u8 disable_sharing : 1; // 0 = Sharing enabled, and 1 = Sharing disabled. 150 | u8 face_shape : 4; 151 | u8 skin_color : 3; 152 | 153 | u8 wrinkles : 4; 154 | u8 makeup : 4; 155 | 156 | u8 hair_style; 157 | u8 hair_color : 3; 158 | u8 hair_flip : 1; 159 | 160 | u8 _unk_0x33 : 4; 161 | u32 _unk_0x34; 162 | 163 | MiiEyebrow eyebrow; 164 | 165 | u8 _unk_0x3c[12]; 166 | 167 | u16 author[0xA]; 168 | u8 pad3[4]; 169 | 170 | } MiiStoreData; 171 | 172 | typedef struct 173 | { 174 | u8 region; // The region code for the hardware region. 175 | u8 country; // Country code. 176 | u8 area; // Area code. 177 | u8 language; // Language code. 178 | u8 platform; // Platform code. 179 | } Profile; 180 | 181 | Result frdInit(void); 182 | void frdExit(void); 183 | Result FRDU_IsOnline(bool * state); 184 | Result FRDU_HasLoggedIn(bool * state); 185 | Result FRD_Login(Handle event); 186 | Result FRD_Logout(void); 187 | Result FRD_GetMyFriendKey(FriendKey * key); 188 | Result FRD_GetMyPreference(bool * isPublicMode, bool * isShowGameName, bool * isShowPlayedGame); 189 | Result FRD_GetMyProfile(Profile * profile); 190 | Result FRD_GetMyPresence(MyPresence * myPresence); 191 | Result FRD_GetMyScreenName(u16 * name); 192 | Result FRD_GetMyMii(MiiStoreData * mii); 193 | Result FRD_GetMyComment(u16 * comment); 194 | Result FRD_GetMyPlayingGame(u64 * titleId); 195 | Result FRD_GetMyFavoriteGame(u64 * titleId); 196 | Result FRD_IsFromFriendList(u64 friendCode, bool * isFromList); 197 | Result FRD_UpdateGameModeDescription(const wchar_t * desc); 198 | Result FRD_PrincipalIdToFriendCode(u32 principalId, u64 * friendCode); 199 | Result FRD_FriendCodeToPrincipalId(u64 friendCode, u32 * principalId); 200 | Result FRD_GetFriendKeyList(FriendKey * friendKeyList, size_t * num, size_t offset, size_t size); 201 | Result FRD_GetFriendMii(MiiStoreData * miiDataList, const FriendKey * friendKeyList, size_t size); 202 | Result FRD_GetFriendProfile(Profile * profileList, const FriendKey * friendKeyList, size_t size); 203 | Result FRD_GetFriendPlayingGame(u64 * titleid, const FriendKey * friendKeyList, size_t size); 204 | Result FRD_IsValidFriendCode(u64 friendCode, bool * isValid); 205 | Result FRD_SetClientSdkVersion(u32 sdkVer); 206 | 207 | #endif -------------------------------------------------------------------------------- /seedstarter/include/utils.h: -------------------------------------------------------------------------------- 1 | #ifndef UTILS_H 2 | #define UTILS_H 3 | 4 | #include <3ds.h> 5 | 6 | #define touchInRect(x1, x2, y1, y2) ((touchGetX() >= (x1) && touchGetX() <= (x2)) && (touchGetY() >= (y1) && touchGetY() <= (y2))) 7 | 8 | bool isN3DS(void); 9 | void u16_to_u8(char * buf, u16 * input, size_t bufsize); 10 | u16 touchGetX(void); 11 | u16 touchGetY(void); 12 | 13 | #endif -------------------------------------------------------------------------------- /seedstarter/resources/banner.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedstarter/resources/banner.png -------------------------------------------------------------------------------- /seedstarter/resources/banner.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedstarter/resources/banner.wav -------------------------------------------------------------------------------- /seedstarter/resources/cia.rsf: -------------------------------------------------------------------------------- 1 | BasicInfo: 2 | Title : $(APP_TITLE) 3 | ProductCode : $(APP_PRODUCT_CODE) 4 | Logo : Homebrew 5 | 6 | RomFs: 7 | RootPath : $(APP_ROMFS) 8 | 9 | TitleInfo: 10 | Category : Application 11 | UniqueId : $(APP_UNIQUE_ID) 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 : false # 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:i 221 | - cfg:u 222 | - dsp::DSP 223 | - fs:USER 224 | - frd:u 225 | - gsp::Gpu 226 | - gsp::Lcd 227 | - hid:USER 228 | - http:C 229 | - ir:rst 230 | - ir:u 231 | - ir:USER 232 | - mcu::HWC 233 | - ndm:u 234 | - nim:u 235 | - nwm::EXT 236 | - nwm::UDS 237 | - ps:ps 238 | - ptm:sysm 239 | - ptm:u 240 | - pxi:dev 241 | - soc:U 242 | - ssl:C 243 | - y2r:u 244 | 245 | SystemControlInfo: 246 | SaveDataSize: 0KB # Change if the app uses savedata 247 | RemasterVersion: 1 248 | StackSize: 0x40000 249 | 250 | # Modules that run services listed above should be included below 251 | # Maximum 48 dependencies 252 | # : 253 | Dependency: 254 | ac: 0x0004013000002402 255 | act: 0x0004013000003802 256 | am: 0x0004013000001502 257 | boss: 0x0004013000003402 258 | camera: 0x0004013000001602 259 | cecd: 0x0004013000002602 260 | cfg: 0x0004013000001702 261 | codec: 0x0004013000001802 262 | csnd: 0x0004013000002702 263 | dlp: 0x0004013000002802 264 | dsp: 0x0004013000001a02 265 | friends: 0x0004013000003202 266 | gpio: 0x0004013000001b02 267 | gsp: 0x0004013000001c02 268 | hid: 0x0004013000001d02 269 | http: 0x0004013000002902 270 | i2c: 0x0004013000001e02 271 | ir: 0x0004013000003302 272 | mcu: 0x0004013000001f02 273 | mic: 0x0004013000002002 274 | ndm: 0x0004013000002b02 275 | news: 0x0004013000003502 276 | #nfc: 0x0004013000004002 277 | nim: 0x0004013000002c02 278 | nwm: 0x0004013000002d02 279 | pdn: 0x0004013000002102 280 | ps: 0x0004013000003102 281 | ptm: 0x0004013000002202 282 | #qtm: 0x0004013020004202 283 | ro: 0x0004013000003702 284 | socket: 0x0004013000002e02 285 | spi: 0x0004013000002302 286 | ssl: 0x0004013000002f02 -------------------------------------------------------------------------------- /seedstarter/resources/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedstarter/resources/icon.png -------------------------------------------------------------------------------- /seedstarter/resources/logo.bcma.lz: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/zoogie/seedminer/9225edfe3c6912d3c164e3dc79a8e9498e41f2b1/seedstarter/resources/logo.bcma.lz -------------------------------------------------------------------------------- /seedstarter/source/fs.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include <3ds.h> 4 | 5 | u32 keyy[4]={0}; 6 | 7 | #include "fs.h" 8 | 9 | void openArchive(FS_ArchiveID id) 10 | { 11 | FSUSER_OpenArchive(&fsArchive, id, fsMakePath(PATH_EMPTY, "")); 12 | } 13 | 14 | void closeArchive(FS_ArchiveID id) 15 | { 16 | FSUSER_CloseArchive(fsArchive); 17 | } 18 | 19 | Result makeDir(FS_Archive archive, const char * path) 20 | { 21 | if ((!archive) || (!path)) 22 | return -1; 23 | 24 | return FSUSER_CreateDirectory(archive, fsMakePath(PATH_ASCII, path), 0); 25 | } 26 | 27 | bool fileExists(FS_Archive archive, const char * path) 28 | { 29 | if ((!path) || (!archive)) 30 | return false; 31 | 32 | Handle handle; 33 | 34 | Result ret = FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0); 35 | 36 | if (R_FAILED(ret)) 37 | return false; 38 | 39 | ret = FSFILE_Close(handle); 40 | 41 | if (R_FAILED(ret)) 42 | return false; 43 | 44 | return true; 45 | } 46 | 47 | bool fileExistsNand(const char * path) 48 | { 49 | if (!path) 50 | return false; 51 | 52 | Handle handle; 53 | 54 | openArchive(ARCHIVE_NAND_CTR_FS); 55 | Result ret = FSUSER_OpenFileDirectly(&handle, ARCHIVE_NAND_CTR_FS, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0); 56 | 57 | if (R_FAILED(ret)) 58 | { 59 | closeArchive(ARCHIVE_NAND_CTR_FS); 60 | return false; 61 | } 62 | 63 | ret = FSFILE_Close(handle); 64 | 65 | if (R_FAILED(ret)) 66 | { 67 | closeArchive(ARCHIVE_NAND_CTR_FS); 68 | return false; 69 | } 70 | 71 | closeArchive(ARCHIVE_NAND_CTR_FS); 72 | return true; 73 | } 74 | 75 | bool dirExists(FS_Archive archive, const char * path) 76 | { 77 | if ((!path) || (!archive)) 78 | return false; 79 | 80 | Handle handle; 81 | 82 | Result ret = FSUSER_OpenDirectory(&handle, archive, fsMakePath(PATH_ASCII, path)); 83 | 84 | if (R_FAILED(ret)) 85 | return false; 86 | 87 | ret = FSDIR_Close(handle); 88 | 89 | if (R_FAILED(ret)) 90 | return false; 91 | 92 | return true; 93 | } 94 | 95 | u64 getFileSize(FS_Archive archive, const char * path) 96 | { 97 | u64 st_size; 98 | Handle handle; 99 | 100 | FSUSER_OpenFile(&handle, archive, fsMakePath(PATH_ASCII, path), FS_OPEN_READ, 0); 101 | FSFILE_GetSize(handle, &st_size); 102 | FSFILE_Close(handle); 103 | 104 | return st_size; 105 | } 106 | 107 | Result writeFile(const char * path, void * buf) 108 | { 109 | Handle handle; 110 | u32 len = strlen(buf); 111 | u64 size; 112 | u32 written; 113 | 114 | if (fileExists(fsArchive, path)) 115 | FSUSER_DeleteFile(fsArchive, fsMakePath(PATH_ASCII, path)); 116 | 117 | Result ret = FSUSER_OpenFileDirectly(&handle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, path), (FS_OPEN_WRITE | FS_OPEN_CREATE), 0); 118 | ret = FSFILE_GetSize(handle, &size); 119 | ret = FSFILE_SetSize(handle, size + len); 120 | ret = FSFILE_Write(handle, &written, size, buf, len, FS_WRITE_FLUSH); 121 | ret = FSFILE_Close(handle); 122 | 123 | return R_SUCCEEDED(ret)? 0 : -1; 124 | } 125 | 126 | Result copy_file(char * old_path, char * new_path) 127 | { 128 | int chunksize = (512 * 1024); 129 | char * buffer = (char *)malloc(chunksize); 130 | 131 | u32 bytesWritten = 0, bytesRead = 0; 132 | u64 offset = 0; 133 | Result ret = 0; 134 | 135 | Handle inputHandle, outputHandle; 136 | 137 | openArchive(ARCHIVE_NAND_CTR_FS); 138 | Result in = FSUSER_OpenFileDirectly(&inputHandle, ARCHIVE_NAND_CTR_FS, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, old_path), FS_OPEN_READ, 0); 139 | 140 | u64 size = getFileSize(fsArchive, old_path); 141 | 142 | if (R_SUCCEEDED(in)) 143 | { 144 | // Delete output file (if existing) 145 | FSUSER_DeleteFile(fsArchive, fsMakePath(PATH_ASCII, new_path)); 146 | 147 | Result out = FSUSER_OpenFileDirectly(&outputHandle, ARCHIVE_SDMC, fsMakePath(PATH_EMPTY, ""), fsMakePath(PATH_ASCII, new_path), (FS_OPEN_CREATE | FS_OPEN_WRITE), 0); 148 | 149 | if (R_SUCCEEDED(out)) 150 | { 151 | // Copy loop (512KB at a time) 152 | do 153 | { 154 | ret = FSFILE_Read(inputHandle, &bytesRead, offset, buffer, chunksize); 155 | memset(buffer, 0, 0x110); 156 | memset(buffer+0x120, 0, 0x20); 157 | bytesWritten += FSFILE_Write(outputHandle, &bytesWritten, offset, buffer, size, FS_WRITE_FLUSH); 158 | 159 | if (bytesWritten == bytesRead) 160 | break; 161 | } 162 | while(bytesRead); 163 | 164 | ret = FSFILE_Close(outputHandle); 165 | 166 | if (bytesRead != bytesWritten) 167 | return ret; 168 | } 169 | else 170 | return out; 171 | 172 | FSFILE_Close(inputHandle); 173 | closeArchive(ARCHIVE_NAND_CTR_FS); 174 | } 175 | else 176 | return in; 177 | 178 | memcpy(keyy, buffer+0x110, 0x10); 179 | free(buffer); 180 | return ret; 181 | } -------------------------------------------------------------------------------- /seedstarter/source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | 6 | #include "frd.h" 7 | #include "utils.h" 8 | #include "fs.h" 9 | 10 | extern u32 keyy[4]; 11 | u32 rnd; 12 | 13 | static Handle amHandle; 14 | 15 | Result amGetServiceHandle(void) 16 | { 17 | return srvGetServiceHandle(&amHandle, "am:net"); 18 | } 19 | 20 | Result amCloseServiceHandle(void) 21 | { 22 | return svcCloseHandle(amHandle); 23 | } 24 | 25 | Result amNetGetDeviceCert(u8 const * buffer) //from https://github.com/joel16/3DSident 26 | { 27 | Result ret = 0; 28 | u32 *cmdbuf = getThreadCommandBuffer(); 29 | 30 | cmdbuf[0] = IPC_MakeHeader(0x818, 1, 2); // 0x08180042 31 | cmdbuf[1] = 0x180; 32 | cmdbuf[2] = (0x180 << 4) | 0xC; 33 | cmdbuf[3] = (u32)buffer; 34 | 35 | if(R_FAILED(ret = svcSendSyncRequest(amHandle))) 36 | return ret; 37 | 38 | return (Result)cmdbuf[1]; 39 | } 40 | 41 | Result dumpFriend(u64 lfcs_share, u64 lfcs_msed, int num){ 42 | Result res; 43 | char filename[0x100]={0}; 44 | u8 part1[0x1000]={0}; 45 | memcpy(part1, &lfcs_msed, 5); 46 | snprintf(filename, 0xFF,"/seedstarter/LFCS/%d_%04llu-%04llu-%04llu_part1.sed", num, lfcs_share/100000000LL, (lfcs_share/10000)%10000, lfcs_share%10000); 47 | FILE *g=fopen(filename,"wb"); 48 | res = fwrite(part1, 1, 0x1000, g); 49 | fclose(g); 50 | return res; 51 | } 52 | 53 | int strlen16(u16* strarg) 54 | { 55 | if(!strarg) 56 | return -1; //strarg is NULL pointer 57 | u16* str = strarg; 58 | for(;*str;++str) 59 | ; // empty body 60 | return str-strarg; 61 | } 62 | 63 | void data_dump() 64 | { 65 | Result ret=0; 66 | ret = cfguInit(); 67 | printf("cfgu %08X\n",(int)ret); 68 | if(R_FAILED(ret)) 69 | { 70 | printf("\ncfguInit failed: 0x%08x\n", (unsigned int)ret); 71 | return; 72 | } 73 | 74 | u64 lfcs=0; 75 | u64 lfcs2=0; 76 | u64 lfcs3=0; 77 | u8 filebuffer[0x1000]={0}; 78 | u16 id0buf[0x80]={0}; 79 | 80 | ret = CFGU_GetConfigInfoBlk2(8, 0x00090001, (u8*)&lfcs); 81 | ret = CFGU_GetConfigInfoBlk2(8, 0x00090000, (u8*)&lfcs2); //debugging possible issues with false lfcs's. both lfcs and lfcs2 should be the same. 82 | printf("cfgu_getblk2: %08X\n",(int)ret); 83 | if(ret){ 84 | printf("GetConfigInfoBlk2 failed! Exiting...\n"); 85 | return; 86 | } 87 | ret = CFGI_GetLocalFriendCodeSeed(&lfcs3); 88 | 89 | printf("LFCS %016llX\n",lfcs); 90 | printf("LFCS2 %016llX\n",lfcs2); 91 | lfcs &= 0xFFFFFFFFFFLL; //low 5 bytes of lfcs, which should be the same as movable.sed lfcs 92 | lfcs2 &= 0xFFFFFFFFFFLL; //ditto 93 | if(!ret){ 94 | printf("LFCS3 %016llX\n",lfcs3); 95 | if(lfcs != lfcs2 || lfcs2 != lfcs3 || lfcs != lfcs3) printf("WARNING: lfcs's not equal, please report\n\n"); 96 | lfcs=lfcs3; //lfcs3 is from a much more trusted function than the config savegame derived lfcs's. 97 | } 98 | else{ 99 | printf("LFCS3 not available - need cfg:i\n"); 100 | if(lfcs != lfcs2) printf("WARNING: lfcs's not equal, please report\n\n"); 101 | } 102 | memcpy(filebuffer, &lfcs, 8); 103 | 104 | ret = FSUSER_GetSdmcCtrRootPath((u8*)id0buf, 0x80*2); 105 | printf("id0 get: %08X\n",(int)ret); 106 | 107 | if(!ret && lfcs){ 108 | for(int i=0;i<32;i++){ 109 | filebuffer[0x10+i]=(u8)id0buf[14+i]; 110 | printf("%c",(char)filebuffer[0x10+i]); 111 | } 112 | 113 | FILE *f=fopen("/seedstarter/movable_part1.sed","wb"); 114 | fwrite(filebuffer, 1, 0x1000, f); 115 | fclose(f); 116 | printf("\n\nSuccess! movable_part1.sed dumped\n"); 117 | } 118 | else{ 119 | printf("\nERROR!!\nGetSdmcCtrRootPath or getConfigInfoBlk2 failed\n"); 120 | } 121 | 122 | } 123 | 124 | Result friends_dump(){ 125 | 126 | Result res; 127 | u8 lfcs[8]; 128 | 129 | res = frdInit(); 130 | printf("frd:u %08X\n",(int)res); 131 | 132 | if(res) { 133 | printf("ERROR: frd:u could not be initialized\n"); 134 | printf("to get this service, app-takeover may be required\n\n"); 135 | return 1; 136 | } 137 | 138 | size_t friendCount = 0; 139 | FriendKey friendKey[FRIEND_LIST_SIZE]; 140 | FRD_GetFriendKeyList(friendKey, &friendCount, 0, FRIEND_LIST_SIZE); 141 | 142 | MiiStoreData friendMii[FRIEND_LIST_SIZE]; 143 | FRD_GetFriendMii(friendMii, friendKey, friendCount); 144 | char friendNames[FRIEND_LIST_SIZE][0x14]; 145 | memset(friendNames, 0, FRIEND_LIST_SIZE*0x14); 146 | 147 | //FILE *g=fopen("friends.bin","wb"); 148 | //fwrite(friendMii, 1, sizeof(friendMii[0])*friendCount, g); 149 | //fclose(g); 150 | 151 | u64 friendCodes[FRIEND_LIST_SIZE]; 152 | for (size_t i = 0x0; i < friendCount; i++) 153 | { 154 | FRD_PrincipalIdToFriendCode(friendKey[i].principalId, &friendCodes[i]); 155 | u16_to_u8(&friendNames[i][0x0], &friendMii[i].name[0], 0x14); 156 | //memcpy(&friendNames[i][0x0], &friendMii[i].name[0], 0x14); 157 | } 158 | 159 | FILE *f=fopen("/seedstarter/LFCS/friends.txt","w"); 160 | fprintf(f,"\tName : Friend Code LFCS(BE) : LFCS(LE)\n"); 161 | fprintf(f,"-----------------------------------------------------------------\n"); 162 | for (size_t i = 0x0; i < friendCount; i++) 163 | { 164 | memcpy(lfcs, &friendKey[i].localFriendCode, 8); 165 | fprintf(f,"%d.\t%s : %04llu-%04llu-%04llu %016llX : ", i, &friendNames[i][0], friendCodes[i]/100000000LL, (friendCodes[i]/10000)%10000, friendCodes[i]%10000, friendKey[i].localFriendCode); 166 | for(int i=0;i<5;i++){ 167 | fprintf(f,"%02X ",lfcs[i]); 168 | } 169 | fprintf(f,"\n"); 170 | res = dumpFriend(friendCodes[i], friendKey[i].localFriendCode&0xFFFFFFFFFFLL, i); 171 | if(res) printf("Friend %d dumped to /seedstarter/LFCS/\n", i); 172 | else printf("Friend %d file dump error\n", i); 173 | } 174 | fclose(f); 175 | 176 | printf("\n%d friends dumped to sdmc:/seedstarter/LFCS\n",friendCount); 177 | return 0; 178 | } 179 | 180 | Result msed_data(){ 181 | Result res; 182 | 183 | struct msed_data{ 184 | u32 lfcs_blk; 185 | s32 msed3offset; 186 | u32 seedtype; 187 | } mdata; 188 | 189 | //nand to sd copy function from the following. 190 | //https://github.com/joel16/3DS-Recovery-Tool Thanks to Joel16 for it. 191 | res = copy_file( "/private/movable.sed", "/seedstarter/movable.sed"); 192 | 193 | if(res){ 194 | printf("Movable.sed dump failed.\n"); 195 | printf("no cfw or luma3DS 9.0+ possible reasons\n\n"); 196 | } 197 | else{ 198 | char filename[0x100]={0}; 199 | u32 lfcs=*keyy; 200 | u32 lfcs_blk=lfcs >> 12; 201 | u32 msed3=*(keyy+3); 202 | s32 msed3offset=(lfcs/5)-(msed3&0x7FFFFFFF); 203 | u32 seedtype=(msed3&0x80000000)>>31; 204 | printf("Movable.sed (keyy only) dump to sdmc:/ success!\nDon't inject to a real 3DS - TADpole use only!\n\n"); 205 | printf(" LFCS exact %08lX\n", lfcs); 206 | printf("* LFCS block %08lX\n", lfcs_blk); 207 | printf(" Msed3 exact %08lX\n", msed3); 208 | printf("* Msed3 offset %ld\n", msed3offset); 209 | printf("* Seedtype %ld\n", seedtype); 210 | mdata.lfcs_blk=lfcs_blk; 211 | mdata.msed3offset=msed3offset; 212 | mdata.seedtype=seedtype; 213 | snprintf(filename, 0x100, "/seedstarter/msed_data_%08lX.bin", rnd); 214 | printf("\n* will be written to\nsdmc:%s\n\n",filename); 215 | FILE *f=fopen(filename,"wb"); 216 | fwrite(&mdata, 1, sizeof(mdata), f); 217 | fclose(f); 218 | printf("Done.\n"); 219 | } 220 | return res; 221 | } 222 | 223 | Result ctcert_dump(){ 224 | Result res; 225 | u8 ctcert[0x19E]={0}; 226 | 227 | res = amGetServiceHandle(); 228 | printf("am:net %08X\n",(int)res); 229 | 230 | if(res){ 231 | printf("ERROR: am:net failed\n"); 232 | printf("no cfw or luma3DS 9.0+ possible reasons\n\n"); 233 | return 1; 234 | } 235 | 236 | res = amNetGetDeviceCert(ctcert); //thanks joel16 for this 237 | printf("getcert %08X\n",(int)res); 238 | memcpy(ctcert+0x180, "ctcert privkey goes here", 25); 239 | 240 | FILE *f=fopen("/seedstarter/ctcert.bin","wb"); 241 | fwrite(ctcert, 1, 0x19E, f); 242 | fclose(f); 243 | printf("Remember to run ctcertifier.firm to add privkey!\n"); 244 | printf("Done.\n"); 245 | return res; 246 | } 247 | 248 | void showMenu(){ 249 | consoleClear(); 250 | printf("<< seedstarter - zoogie >> v1.2\n\n"); 251 | printf("Based on friendMii, 3DSident, and\n"); 252 | printf("3DS-Recovery-Tool by Joel16\n"); 253 | printf("Please run with Luma3DS 9.0+ if possible\n\n"); 254 | 255 | printf(" A dump LFCS from GetConfigInfoBlk2\n"); 256 | printf(" B dump LFCS from friendlist\n"); 257 | printf("CFW-X dump msed_data.bin\n"); 258 | printf("CFW-Y dump ctcert.bin (no privkey)\n"); 259 | printf("START exit app\n\n"); 260 | } 261 | 262 | void waitKey(){ 263 | printf("Press A to continue...\n"); 264 | 265 | while (1) 266 | { 267 | hidScanInput(); 268 | u32 kDown = hidKeysDown(); 269 | if (kDown & KEY_A) break; 270 | gfxFlushBuffers(); 271 | gfxSwapBuffers(); 272 | gspWaitForVBlank(); 273 | } 274 | showMenu(); 275 | } 276 | 277 | int main(int argc, char **argv) 278 | { 279 | gfxInitDefault(); 280 | consoleInit(GFX_TOP, NULL); 281 | srand(time(NULL)); 282 | rnd=rand(); 283 | 284 | showMenu(); 285 | mkdir("sdmc:/seedstarter/", 0777); 286 | mkdir("sdmc:/seedstarter/LFCS/", 0777); 287 | 288 | while (aptMainLoop()) 289 | { 290 | hidScanInput(); 291 | u32 kDown = hidKeysDown(); 292 | //u32 kHeld = hidKeysHeld(); 293 | 294 | if (kDown & KEY_START) 295 | break; 296 | else if (kDown & KEY_A){ 297 | data_dump(); 298 | waitKey(); 299 | } 300 | else if (kDown & KEY_B){ 301 | friends_dump(); 302 | waitKey(); 303 | } 304 | else if (kDown & KEY_X){ 305 | msed_data(); 306 | waitKey(); 307 | } 308 | else if (kDown & KEY_Y){ 309 | ctcert_dump(); 310 | waitKey(); 311 | } 312 | gfxFlushBuffers(); 313 | gfxSwapBuffers(); 314 | gspWaitForVBlank(); 315 | } 316 | 317 | gfxExit(); 318 | return 0; 319 | } 320 | -------------------------------------------------------------------------------- /seedstarter/source/services/frd.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | #include "frd.h" 5 | 6 | static Handle frdHandle; 7 | static int frdRefCount; 8 | 9 | Result frdInit(void) 10 | { 11 | Result ret = 0; 12 | 13 | if (AtomicPostIncrement(&frdRefCount)) 14 | return 0; 15 | 16 | ret = srvGetServiceHandle(&frdHandle, "frd:u"); 17 | 18 | if (R_FAILED(ret)) 19 | ret = srvGetServiceHandle(&frdHandle, "frd:n"); 20 | 21 | if (R_FAILED(ret)) 22 | ret = srvGetServiceHandle(&frdHandle, "frd:a"); 23 | 24 | if (R_FAILED(ret)) 25 | AtomicDecrement(&frdRefCount); 26 | 27 | return ret; 28 | } 29 | 30 | void frdExit(void) 31 | { 32 | if (AtomicDecrement(&frdRefCount)) 33 | return; 34 | 35 | svcCloseHandle(frdHandle); 36 | } 37 | 38 | Result FRDU_IsOnline(bool * state) // Online state 39 | { 40 | Result ret = 0; 41 | u32 * cmdbuf = getThreadCommandBuffer(); 42 | 43 | cmdbuf[0] = IPC_MakeHeader(0x02, 0, 0); // 0x00020000 44 | 45 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 46 | return ret; 47 | 48 | *state = cmdbuf[2] & 0xFF; 49 | 50 | return cmdbuf[1]; 51 | } 52 | 53 | Result FRDU_HasLoggedIn(bool * state) 54 | { 55 | Result ret = 0; 56 | u32 * cmdbuf = getThreadCommandBuffer(); 57 | 58 | cmdbuf[0] = IPC_MakeHeader(0x01, 0, 0); // 0x00010000 59 | 60 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 61 | return ret; 62 | 63 | *state = cmdbuf[2] & 0xFF; 64 | 65 | return cmdbuf[1]; 66 | } 67 | 68 | Result FRD_Login(Handle event) 69 | { 70 | Result ret = 0; 71 | u32 * cmdbuf = getThreadCommandBuffer(); 72 | 73 | cmdbuf[0] = IPC_MakeHeader(0x03, 0, 2); // 0x00030002 74 | cmdbuf[1] = 0; 75 | cmdbuf[2] = event; 76 | 77 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 78 | return ret; 79 | 80 | return cmdbuf[1]; 81 | } 82 | 83 | Result FRD_Logout(void) 84 | { 85 | Result ret = 0; 86 | u32 * cmdbuf = getThreadCommandBuffer(); 87 | 88 | cmdbuf[0] = IPC_MakeHeader(0x04, 0, 0); // 0x00040000 89 | 90 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 91 | return ret; 92 | 93 | return cmdbuf[1]; 94 | } 95 | 96 | Result FRD_GetMyFriendKey(FriendKey * key) 97 | { 98 | Result ret = 0; 99 | u32 * cmdbuf = getThreadCommandBuffer(); 100 | 101 | cmdbuf[0] = IPC_MakeHeader(0x05, 0, 0); // 0x00050000 102 | 103 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 104 | return ret; 105 | 106 | memcpy(key, &cmdbuf[2], sizeof(FriendKey)); 107 | 108 | return cmdbuf[1]; 109 | } 110 | 111 | Result FRD_GetMyPreference(bool * isPublicMode, bool * isShowGameName, bool * isShowPlayedGame) 112 | { 113 | Result ret = 0; 114 | u32 * cmdbuf = getThreadCommandBuffer(); 115 | 116 | cmdbuf[0] = IPC_MakeHeader(0x06, 0, 0); // 0x00060000 117 | 118 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 119 | return ret; 120 | 121 | *isPublicMode = cmdbuf[2] & 0xFF; // Public mode 122 | *isShowGameName = cmdbuf[3] & 0xFF; // Show current game 123 | *isShowPlayedGame = cmdbuf[4] & 0xFF; // Show game history. 124 | 125 | return cmdbuf[1]; 126 | } 127 | 128 | Result FRD_GetMyProfile(Profile * profile) 129 | { 130 | Result ret = 0; 131 | u32 * cmdbuf = getThreadCommandBuffer(); 132 | 133 | cmdbuf[0] = IPC_MakeHeader(0x07, 0, 0); // 0x00070000 134 | 135 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 136 | return ret; 137 | 138 | memcpy(profile, &cmdbuf[2], sizeof(Profile)); 139 | 140 | return cmdbuf[1]; 141 | } 142 | 143 | Result FRD_GetMyPresence(MyPresence * myPresence) 144 | { 145 | Result ret = 0; 146 | u32 * cmdbuf = getThreadCommandBuffer(); 147 | u32 * statbuf = getThreadStaticBuffers(); 148 | 149 | cmdbuf[0] = IPC_MakeHeader(0x08, 0, 0); // 0x00080000 150 | statbuf[0] = 0x4B0002; 151 | statbuf[1] = (u32)myPresence; 152 | 153 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 154 | return ret; 155 | 156 | return cmdbuf[1]; 157 | } 158 | 159 | Result FRD_GetMyScreenName(u16 * name) 160 | { 161 | Result ret = 0; 162 | u32 * cmdbuf = getThreadCommandBuffer(); 163 | 164 | cmdbuf[0] = IPC_MakeHeader(0x09, 0, 0); // 0x00090000 165 | 166 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 167 | return ret; 168 | 169 | memcpy(name, &cmdbuf[2], FRIENDS_SCREEN_NAME_SIZE); // 11-byte UTF-16 screen name (with null terminator) 170 | 171 | return cmdbuf[1]; 172 | } 173 | 174 | Result FRD_GetMyMii(MiiStoreData * mii) 175 | { 176 | Result ret = 0; 177 | u32 * cmdbuf = getThreadCommandBuffer(); 178 | 179 | cmdbuf[0] = IPC_MakeHeader(0x0A, 0, 0); // 0x000A0000 180 | 181 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 182 | return ret; 183 | 184 | memcpy(mii, &cmdbuf[2], FRIEND_MII_STORE_DATA_SIZE); 185 | 186 | return cmdbuf[1]; 187 | } 188 | 189 | Result FRD_GetMyComment(u16 * comment) 190 | { 191 | Result ret = 0; 192 | u32 * cmdbuf = getThreadCommandBuffer(); 193 | 194 | cmdbuf[0] = IPC_MakeHeader(0x0F, 0, 0); // 0x000F0000 195 | 196 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 197 | return ret; 198 | 199 | memcpy(comment, &cmdbuf[2], FRIENDS_COMMENT_SIZE); // 16-byte UTF-16 comment 200 | 201 | return cmdbuf[1]; 202 | } 203 | 204 | Result FRD_GetMyPlayingGame(u64 * titleId) 205 | { 206 | Result ret = 0; 207 | u32 * cmdbuf = getThreadCommandBuffer(); 208 | 209 | cmdbuf[0] = IPC_MakeHeader(0x0C, 0, 0); // 0x000C0000 210 | 211 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 212 | return ret; 213 | 214 | *titleId = (((u64)cmdbuf[3]) << 32 | (u64)cmdbuf[2]); 215 | 216 | return cmdbuf[1]; 217 | } 218 | 219 | Result FRD_GetMyFavoriteGame(u64 * titleId) 220 | { 221 | Result ret = 0; 222 | u32 * cmdbuf = getThreadCommandBuffer(); 223 | 224 | cmdbuf[0] = IPC_MakeHeader(0x0D, 0, 0); // 0x000D0000 225 | 226 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 227 | return ret; 228 | 229 | *titleId = (((u64)cmdbuf[3]) << 32 | (u64)cmdbuf[2]); 230 | 231 | return cmdbuf[1]; 232 | } 233 | 234 | Result FRD_IsFromFriendList(u64 friendCode, bool * isFromList) 235 | { 236 | Result ret = 0; 237 | u32 * cmdbuf = getThreadCommandBuffer(); 238 | 239 | cmdbuf[0] = IPC_MakeHeader(0x1B, 2, 0); // 0x001B0080 240 | cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF); 241 | cmdbuf[2] = (u32)(friendCode >> 32); 242 | 243 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 244 | return ret; 245 | 246 | *isFromList = cmdbuf[2] & 0xFF; 247 | 248 | return cmdbuf[1]; 249 | } 250 | 251 | Result FRD_UpdateGameModeDescription(const wchar_t * desc) 252 | { 253 | Result ret = 0; 254 | u32 * cmdbuf = getThreadCommandBuffer(); 255 | 256 | cmdbuf[0] = IPC_MakeHeader(0x1D, 0, 2); // 0x001D0002 257 | cmdbuf[1] = 0x400802; 258 | cmdbuf[2] = (uintptr_t)desc; 259 | 260 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 261 | return ret; 262 | 263 | return cmdbuf[1]; 264 | } 265 | 266 | Result FRD_PrincipalIdToFriendCode(u32 principalId, u64 * friendCode) 267 | { 268 | Result ret = 0; 269 | u32 * cmdbuf = getThreadCommandBuffer(); 270 | 271 | cmdbuf[0] = IPC_MakeHeader(0x24, 1, 0); // 0x00240040 272 | cmdbuf[1] = principalId; 273 | 274 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 275 | return ret; 276 | 277 | *friendCode = (((u64)cmdbuf[3]) << 32 | (u64)cmdbuf[2]); 278 | 279 | return cmdbuf[1]; 280 | } 281 | 282 | Result FRD_FriendCodeToPrincipalId(u64 friendCode, u32 * principalId) 283 | { 284 | Result ret = 0; 285 | u32 * cmdbuf = getThreadCommandBuffer(); 286 | 287 | cmdbuf[0] = IPC_MakeHeader(0x25, 2, 0); // 0x00250080 288 | cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF); 289 | cmdbuf[2] = (u32)(friendCode >> 32); 290 | 291 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 292 | return ret; 293 | 294 | *principalId = cmdbuf[2]; 295 | 296 | return cmdbuf[1]; 297 | } 298 | 299 | Result FRD_GetFriendKeyList(FriendKey * friendKeyList, size_t * num, size_t offset, size_t size) 300 | { 301 | Result ret = 0; 302 | u32 * cmdbuf = getThreadCommandBuffer(); 303 | 304 | cmdbuf[0] = IPC_MakeHeader(0x11, 2, 0); // 0x00110080 305 | cmdbuf[1] = 0; 306 | cmdbuf[2] = size; 307 | cmdbuf[64] = (size << 18) | 2; 308 | cmdbuf[65] = (u32)friendKeyList; 309 | 310 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 311 | return ret; 312 | 313 | *num = cmdbuf[2]; 314 | 315 | return cmdbuf[1]; 316 | } 317 | 318 | Result FRD_GetFriendMii(MiiStoreData * miiDataList, const FriendKey * friendKeyList, size_t size) 319 | { 320 | Result ret = 0; 321 | u32 * cmdbuf = getThreadCommandBuffer(); 322 | 323 | cmdbuf[0] = IPC_MakeHeader(0x14, 1, 4); // 0x00140044 324 | cmdbuf[1] = size; 325 | cmdbuf[2] = (size << 18) | 2; 326 | cmdbuf[3] = (u32)friendKeyList; 327 | cmdbuf[4] = IPC_Desc_Buffer((size * 0x60), IPC_BUFFER_W); 328 | cmdbuf[5] = (u32)miiDataList; 329 | 330 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 331 | return ret; 332 | 333 | return cmdbuf[1]; 334 | } 335 | 336 | Result FRD_GetFriendProfile(Profile * profileList, const FriendKey * friendKeyList, size_t size) 337 | { 338 | Result ret = 0; 339 | u32 * cmdbuf = getThreadCommandBuffer(); 340 | u32 profileSize = size * sizeof(Profile); 341 | 342 | cmdbuf[0] = IPC_MakeHeader(0x15, 1, 2); // 0x00150042 343 | cmdbuf[1] = size; 344 | cmdbuf[2] = (size << 18) | 2; 345 | cmdbuf[3] = (u32)friendKeyList; 346 | cmdbuf[64] = (profileSize << 10) | 2; 347 | cmdbuf[65] = (u32)profileList; 348 | 349 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 350 | return ret; 351 | 352 | return cmdbuf[1]; 353 | } 354 | 355 | Result FRD_GetFriendPlayingGame(u64 * titleid, const FriendKey * friendKeyList, size_t size) 356 | { 357 | Result ret = 0; 358 | u32 * cmdbuf = getThreadCommandBuffer(); 359 | 360 | cmdbuf[0] = IPC_MakeHeader(0x18, 1, 4); // 0x00180044 361 | cmdbuf[1] = 0; 362 | cmdbuf[2] = (size << 18) | 2; 363 | cmdbuf[3] = (u32)friendKeyList; 364 | cmdbuf[4] = (4352 * size) | 0xC; 365 | cmdbuf[5] = (u32)titleid; 366 | 367 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 368 | return ret; 369 | 370 | return cmdbuf[1]; 371 | } 372 | 373 | Result FRD_IsValidFriendCode(u64 friendCode, bool * isValid) 374 | { 375 | Result ret = 0; 376 | u32 * cmdbuf = getThreadCommandBuffer(); 377 | 378 | cmdbuf[0] = IPC_MakeHeader(0x26, 2, 0); // 0x00260080 379 | cmdbuf[1] = (u32)(friendCode & 0xFFFFFFFF); 380 | cmdbuf[2] = (u32)(friendCode >> 32); 381 | 382 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 383 | return ret; 384 | 385 | *isValid = cmdbuf[2] & 0xFF; 386 | 387 | return cmdbuf[1]; 388 | } 389 | 390 | Result FRD_SetClientSdkVersion(u32 sdkVer) 391 | { 392 | Result ret = 0; 393 | u32 * cmdbuf = getThreadCommandBuffer(); 394 | 395 | cmdbuf[0] = IPC_MakeHeader(0x32, 1, 2); // 0x00320042 396 | cmdbuf[1] = sdkVer; 397 | cmdbuf[2] = IPC_Desc_CurProcessHandle(); 398 | 399 | if (R_FAILED(ret = svcSendSyncRequest(frdHandle))) 400 | return ret; 401 | 402 | return cmdbuf[1]; 403 | } -------------------------------------------------------------------------------- /seedstarter/source/utils.c: -------------------------------------------------------------------------------- 1 | #include "utils.h" 2 | 3 | bool isN3DS(void) 4 | { 5 | bool isNew3DS = false; 6 | 7 | if (R_SUCCEEDED(APT_CheckNew3DS(&isNew3DS))) 8 | return isNew3DS; 9 | 10 | return false; 11 | } 12 | 13 | void u16_to_u8(char * buf, u16 * input, size_t bufsize) 14 | { 15 | u32 end=0; 16 | if(bufsize>0x14)bufsize=0x14; 17 | if(bufsize<=0) return; 18 | for(int i=0;i