├── EULASetter.xml ├── Makefile ├── README.md ├── img └── screenshot.png └── source └── main.c /EULASetter.xml: -------------------------------------------------------------------------------- 1 | 2 | 0004001000020000 3 | 0004001000021000 4 | 0004001000022000 5 | 0004001000026000 6 | 0004001000027000 7 | 0004001000028000 8 | 9 | -------------------------------------------------------------------------------- /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 | SOURCES := source 33 | DATA := data 34 | INCLUDES := include 35 | 36 | APP_TITLE := EULA Setter 37 | APP_DESCRIPTION := Set your EULA version! 38 | APP_AUTHOR := SciresM 39 | 40 | #--------------------------------------------------------------------------------- 41 | # options for code generation 42 | #--------------------------------------------------------------------------------- 43 | ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft 44 | 45 | CFLAGS := -g -Wall -O2 -mword-relocations \ 46 | -fomit-frame-pointer -ffunction-sections \ 47 | $(ARCH) 48 | 49 | CFLAGS += $(INCLUDE) -DARM11 -D_3DS 50 | 51 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 52 | 53 | ASFLAGS := -g $(ARCH) 54 | LDFLAGS = -specs=3dsx.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 55 | 56 | LIBS := -lctru -lm 57 | 58 | #--------------------------------------------------------------------------------- 59 | # list of directories containing libraries, this must be the top level containing 60 | # include and lib 61 | #--------------------------------------------------------------------------------- 62 | LIBDIRS := $(CTRULIB) 63 | 64 | 65 | #--------------------------------------------------------------------------------- 66 | # no real need to edit anything past this point unless you need to add additional 67 | # rules for different file extensions 68 | #--------------------------------------------------------------------------------- 69 | ifneq ($(BUILD),$(notdir $(CURDIR))) 70 | #--------------------------------------------------------------------------------- 71 | 72 | export OUTPUT := $(CURDIR)/$(TARGET) 73 | export TOPDIR := $(CURDIR) 74 | 75 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 76 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 77 | 78 | export DEPSDIR := $(CURDIR)/$(BUILD) 79 | 80 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 81 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 82 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 83 | PICAFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.v.pica))) 84 | SHLISTFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.shlist))) 85 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 86 | 87 | #--------------------------------------------------------------------------------- 88 | # use CXX for linking C++ projects, CC for standard C 89 | #--------------------------------------------------------------------------------- 90 | ifeq ($(strip $(CPPFILES)),) 91 | #--------------------------------------------------------------------------------- 92 | export LD := $(CC) 93 | #--------------------------------------------------------------------------------- 94 | else 95 | #--------------------------------------------------------------------------------- 96 | export LD := $(CXX) 97 | #--------------------------------------------------------------------------------- 98 | endif 99 | #--------------------------------------------------------------------------------- 100 | 101 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 102 | $(PICAFILES:.v.pica=.shbin.o) $(SHLISTFILES:.shlist=.shbin.o) \ 103 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 104 | 105 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 106 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 107 | -I$(CURDIR)/$(BUILD) 108 | 109 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 110 | 111 | ifeq ($(strip $(ICON)),) 112 | icons := $(wildcard *.png) 113 | ifneq (,$(findstring $(TARGET).png,$(icons))) 114 | export APP_ICON := $(TOPDIR)/$(TARGET).png 115 | else 116 | ifneq (,$(findstring icon.png,$(icons))) 117 | export APP_ICON := $(TOPDIR)/icon.png 118 | endif 119 | endif 120 | else 121 | export APP_ICON := $(TOPDIR)/$(ICON) 122 | endif 123 | 124 | ifeq ($(strip $(NO_SMDH)),) 125 | export _3DSXFLAGS += --smdh=$(CURDIR)/$(TARGET).smdh 126 | endif 127 | 128 | ifneq ($(ROMFS),) 129 | export _3DSXFLAGS += --romfs=$(CURDIR)/$(ROMFS) 130 | endif 131 | 132 | .PHONY: $(BUILD) clean all 133 | 134 | #--------------------------------------------------------------------------------- 135 | all: $(BUILD) 136 | 137 | $(BUILD): 138 | @[ -d $@ ] || mkdir -p $@ 139 | @$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 140 | 141 | #--------------------------------------------------------------------------------- 142 | clean: 143 | @echo clean ... 144 | @rm -fr $(BUILD) $(TARGET).3dsx $(OUTPUT).smdh $(TARGET).elf 145 | 146 | 147 | #--------------------------------------------------------------------------------- 148 | else 149 | 150 | DEPENDS := $(OFILES:.o=.d) 151 | 152 | #--------------------------------------------------------------------------------- 153 | # main targets 154 | #--------------------------------------------------------------------------------- 155 | ifeq ($(strip $(NO_SMDH)),) 156 | $(OUTPUT).3dsx : $(OUTPUT).elf $(OUTPUT).smdh 157 | else 158 | $(OUTPUT).3dsx : $(OUTPUT).elf 159 | endif 160 | 161 | $(OUTPUT).elf : $(OFILES) 162 | 163 | #--------------------------------------------------------------------------------- 164 | # you need a rule like this for each extension you use as binary data 165 | #--------------------------------------------------------------------------------- 166 | %.bin.o : %.bin 167 | #--------------------------------------------------------------------------------- 168 | @echo $(notdir $<) 169 | @$(bin2o) 170 | 171 | #--------------------------------------------------------------------------------- 172 | # rules for assembling GPU shaders 173 | #--------------------------------------------------------------------------------- 174 | define shader-as 175 | $(eval CURBIN := $(patsubst %.shbin.o,%.shbin,$(notdir $@))) 176 | picasso -o $(CURBIN) $1 177 | bin2s $(CURBIN) | $(AS) -o $@ 178 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"_end[];" > `(echo $(CURBIN) | tr . _)`.h 179 | echo "extern const u8" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> `(echo $(CURBIN) | tr . _)`.h 180 | echo "extern const u32" `(echo $(CURBIN) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> `(echo $(CURBIN) | tr . _)`.h 181 | endef 182 | 183 | %.shbin.o : %.v.pica %.g.pica 184 | @echo $(notdir $^) 185 | @$(call shader-as,$^) 186 | 187 | %.shbin.o : %.v.pica 188 | @echo $(notdir $<) 189 | @$(call shader-as,$<) 190 | 191 | %.shbin.o : %.shlist 192 | @echo $(notdir $<) 193 | @$(call shader-as,$(foreach file,$(shell cat $<),$(dir $<)/$(file))) 194 | 195 | -include $(DEPENDS) 196 | 197 | #--------------------------------------------------------------------------------------- 198 | endif 199 | #--------------------------------------------------------------------------------------- 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | This is an example homebrew using cfg:i service commands to adjust the agreed EULA version value in the config NAND savegame. 2 | 3 | ![Screenshot](/img/screenshot.png) -------------------------------------------------------------------------------- /img/screenshot.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/SciresM/EULASetter/ba3b52b97f4473fe55c642f34644fc0cc8b7830a/img/screenshot.png -------------------------------------------------------------------------------- /source/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include <3ds.h> 5 | 6 | #define HIGH 1 7 | #define LOW 0 8 | 9 | static uint8_t eulaData[4]; 10 | static PrintConsole *console; 11 | static int x, y; 12 | 13 | static int modIndex; 14 | 15 | // Function prototypes 16 | static void initStatics(void); 17 | static uint16_t getEulaVersion(void); 18 | static void setEulaVersion(uint16_t version); 19 | static void refreshEulaVal(void); 20 | 21 | int main(int argc, char **argv) 22 | { 23 | // Initialize services 24 | aptInit(); 25 | gfxInitDefault(); 26 | hidInit(); 27 | cfguInit(); 28 | 29 | initStatics(); 30 | 31 | refreshEulaVal(); 32 | uint16_t origVal = getEulaVersion(); 33 | 34 | //Flushes the buffer 35 | gfxFlushBuffers(); 36 | gfxSwapBuffers(); 37 | 38 | while(aptMainLoop()) //Always have the main code loop in here 39 | { 40 | hidScanInput(); //Checks which keys are pressed 41 | 42 | u32 button = hidKeysDown(); // Checks which keys are up and which ones are down 43 | if (button & KEY_LEFT) 44 | { 45 | modIndex = HIGH; 46 | refreshEulaVal(); 47 | } 48 | if (button & KEY_RIGHT) 49 | { 50 | modIndex = LOW; 51 | refreshEulaVal(); 52 | } 53 | if (button & KEY_UP) 54 | { 55 | eulaData[modIndex] += 1; 56 | refreshEulaVal(); 57 | } 58 | if (button & KEY_DOWN) 59 | { 60 | eulaData[modIndex] -= 1; 61 | refreshEulaVal(); 62 | } 63 | if (button & KEY_X) 64 | { 65 | setEulaVersion(0xFFFF); 66 | refreshEulaVal(); 67 | } 68 | if (button & KEY_Y) 69 | { 70 | setEulaVersion(0x0000); 71 | refreshEulaVal(); 72 | } 73 | if (button & KEY_START) 74 | { 75 | CFG_UpdateConfigNANDSavegame(); 76 | break; 77 | } 78 | if (button & KEY_SELECT) 79 | { 80 | setEulaVersion(origVal); 81 | CFG_UpdateConfigNANDSavegame(); 82 | break; 83 | } 84 | } 85 | 86 | // Exit services 87 | aptExit(); 88 | gfxExit(); 89 | hidExit(); 90 | cfguExit(); 91 | return 0; 92 | } 93 | 94 | static void initStatics(void) 95 | { 96 | // Initialize static pointers/values 97 | console = consoleInit(GFX_TOP, NULL); 98 | printf("\nEULA Setter:\n"); 99 | printf("Press UP to increase selected byte\n"); 100 | printf("Press DOWN to decrease selected byte\n"); 101 | printf("Press LEFT to modify high byte\n"); 102 | printf("Press RIGHT to modify low byte\n"); 103 | printf("Press X for 0xFFFF\n"); 104 | printf("Press Y for 0x0000\n"); 105 | printf("Press START to save and exit\n"); 106 | printf("Press SELECT to exit without saving\n\n"); 107 | printf("Current accepted EULA version: "); 108 | 109 | x = console->cursorX; 110 | y = console->cursorY; 111 | 112 | modIndex = LOW; 113 | 114 | CFGU_GetConfigInfoBlk2(4, 0xD0000, eulaData); 115 | } 116 | 117 | static uint16_t getEulaVersion(void) 118 | { 119 | return (uint16_t)((eulaData[HIGH] << 8) | (eulaData[LOW])); 120 | } 121 | 122 | static void setEulaVersion(uint16_t version) 123 | { 124 | *((uint16_t *)eulaData) = version; 125 | CFG_SetConfigInfoBlk8(4, 0xD0000, eulaData); 126 | } 127 | 128 | static void refreshEulaVal(void) 129 | { 130 | console->cursorX = x; 131 | console->cursorY = y; 132 | setEulaVersion(getEulaVersion()); 133 | if (modIndex == LOW) 134 | { 135 | printf(" %02X .[%02X]\n\n", eulaData[HIGH], eulaData[LOW]); 136 | } 137 | else 138 | { 139 | printf("[%02X]. %02X \n\n", eulaData[HIGH], eulaData[LOW]); 140 | } 141 | } --------------------------------------------------------------------------------