├── .github └── workflows │ └── main.yml ├── .gitignore ├── LICENSE ├── Makefile ├── Makefile_DSi ├── README.md ├── arm7 ├── Makefile └── source │ └── main.c ├── arm9 ├── Makefile └── source │ ├── common │ ├── inifile.cpp │ ├── inifile.h │ ├── nds_loader_arm9.c │ ├── nds_loader_arm9.h │ ├── singleton.h │ ├── stringtool.cpp │ ├── stringtool.h │ ├── systemdetails.cpp │ └── systemdetails.h │ └── main.cpp ├── bootloader ├── Makefile ├── arm9code │ └── mpu_reset.s ├── load.ld └── source │ ├── arm7clear.s │ ├── arm9clear.arm.c │ ├── arm9mpu_reset.s │ ├── bios.s │ ├── boot.c │ ├── boot.h │ ├── card.h │ ├── disc_io.h │ ├── dldi_patcher.c │ ├── dldi_patcher.h │ ├── fat.c │ ├── fat.h │ ├── i2c.c │ ├── i2c.h │ ├── io_dldi.h │ ├── io_dldi.s │ ├── load_crt0.s │ ├── sdmmc.c │ └── sdmmc.h ├── bootstub ├── Makefile └── bootstub.s ├── clean and compile.bat ├── compile.bat ├── icon.bmp └── make_cia /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | #Based On: https://github.com/Universal-Team/Relaunch/blob/master/.github/workflows/build.yml 2 | name: Compile ButtonBoot 3 | 4 | on: 5 | push: 6 | paths-ignore: 7 | - 'README.md' 8 | pull_request: 9 | branches: ["*"] 10 | paths-ignore: 11 | - 'README.md' 12 | release: 13 | types: [created] 14 | 15 | jobs: 16 | build: 17 | runs-on: ubuntu-latest 18 | container: devkitpro/devkitarm 19 | name: Build with Docker using devkitARM 20 | outputs: 21 | commit_tag: ${{ steps.build.outputs.commit_tag }} 22 | commit_hash: ${{ steps.build.outputs.commit_hash }} 23 | author_name: ${{ steps.build.outputs.author_name }} 24 | committer_name: ${{ steps.build.outputs.committer_name }} 25 | commit_subject: ${{ steps.build.outputs.commit_subject }} 26 | commit_message: ${{ steps.build.outputs.commit_message }} 27 | steps: 28 | - name: Checkout repo 29 | uses: actions/checkout@v3 30 | with: 31 | submodules: recursive 32 | - name: Build 33 | id: build 34 | run: | 35 | make 36 | 37 | mkdir -p ~/artifacts 38 | cp ButtonBoot.nds ~/artifacts 39 | 40 | - name: Publish build to GH Actions 41 | uses: actions/upload-artifact@v3 42 | with: 43 | path: ~/artifacts/ButtonBoot.nds 44 | name: build 45 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.o 2 | *.d 3 | *.elf 4 | *.map 5 | *.DS_Store 6 | *.nds 7 | *.bin 8 | */build/* 9 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | MIT License 3 | 4 | Copyright (c) 2019 5 | 6 | Permission is hereby granted, free of charge, to any person obtaining a copy 7 | of this software and associated documentation files (the "Software"), to deal 8 | in the Software without restriction, including without limitation the rights 9 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 10 | copies of the Software, and to permit persons to whom the Software is 11 | furnished to do so, subject to the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be included in all 14 | copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 19 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 20 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 21 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 22 | SOFTWARE. 23 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | .SECONDARY: 5 | 6 | ifeq ($(strip $(DEVKITARM)),) 7 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 8 | endif 9 | 10 | include $(DEVKITARM)/ds_rules 11 | 12 | export VERSION_MAJOR := 1 13 | export VERSION_MINOR := 0 14 | export VERSION_PATCH := 0 15 | 16 | 17 | VERSION := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) 18 | #--------------------------------------------------------------------------------- 19 | # TARGET is the name of the output 20 | # BUILD is the directory where object files & intermediate files will be placed 21 | # SOURCES is a list of directories containing source code 22 | # INCLUDES is a list of directories containing extra header files 23 | # DATA is a list of directories containing binary files embedded using bin2o 24 | # GRAPHICS is a list of directories containing image files to be converted with grit 25 | #--------------------------------------------------------------------------------- 26 | TARGET := ButtonBoot 27 | BUILD := build 28 | SOURCES := source 29 | INCLUDES := include 30 | DATA := data 31 | 32 | #--------------------------------------------------------------------------------- 33 | # options for code generation 34 | #--------------------------------------------------------------------------------- 35 | ARCH := -mthumb -mthumb-interwork 36 | 37 | CFLAGS := -g -Wall -O2 \ 38 | -ffunction-sections -fdata-sections \ 39 | -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ 40 | -ffast-math \ 41 | $(ARCH) 42 | 43 | CFLAGS += $(INCLUDE) -DARM9 44 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++11 45 | 46 | ASFLAGS := -g $(ARCH) 47 | LDFLAGS = -specs=ds_arm9.specs -g -Wl,--gc-sections $(ARCH) -Wl,-Map,$(notdir $*.map) 48 | 49 | 50 | #--------------------------------------------------------------------------------- 51 | # list of directories containing libraries, this must be the top level containing 52 | # include and lib 53 | #--------------------------------------------------------------------------------- 54 | LIBDIRS := $(LIBNDS) 55 | 56 | #--------------------------------------------------------------------------------- 57 | # no real need to edit anything past this point unless you need to add additional 58 | # rules for different file extensions 59 | #--------------------------------------------------------------------------------- 60 | ifneq ($(BUILD),$(notdir $(CURDIR))) 61 | #--------------------------------------------------------------------------------- 62 | export TOPDIR := $(CURDIR) 63 | 64 | export OUTPUT := $(CURDIR)/$(TARGET) 65 | 66 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 67 | 68 | export DEPSDIR := $(CURDIR)/$(BUILD) 69 | 70 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 71 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 72 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 73 | BINFILES := load.bin bootstub.bin 74 | 75 | #--------------------------------------------------------------------------------- 76 | # use CXX for linking C++ projects, CC for standard C 77 | #--------------------------------------------------------------------------------- 78 | ifeq ($(strip $(CPPFILES)),) 79 | #--------------------------------------------------------------------------------- 80 | export LD := $(CC) 81 | #--------------------------------------------------------------------------------- 82 | else 83 | #--------------------------------------------------------------------------------- 84 | export LD := $(CXX) 85 | #--------------------------------------------------------------------------------- 86 | endif 87 | #--------------------------------------------------------------------------------- 88 | 89 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 90 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 91 | 92 | export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ 93 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 94 | -I$(CURDIR)/$(BUILD) 95 | 96 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 97 | 98 | icons := $(wildcard *.bmp) 99 | 100 | ifneq (,$(findstring $(TARGET).bmp,$(icons))) 101 | export GAME_ICON := $(CURDIR)/$(TARGET).bmp 102 | else 103 | ifneq (,$(findstring icon.bmp,$(icons))) 104 | export GAME_ICON := $(CURDIR)/icon.bmp 105 | endif 106 | endif 107 | 108 | export GAME_TITLE := $(TARGET) 109 | 110 | .PHONY: bootloader bootstub clean arm7/$(TARGET).elf arm9/$(TARGET).elf 111 | 112 | all: bootloader bootstub $(TARGET).nds 113 | 114 | dist: all 115 | @rm -fr hbmenu 116 | @mkdir hbmenu 117 | @cp $(TARGET).nds hbmenu/BOOT.NDS 118 | @cp BootStrap/_BOOT_MP.NDS BootStrap/TTMENU.DAT BootStrap/_DS_MENU.DAT BootStrap/ez5sys.bin BootStrap/akmenu4.nds hbmenu 119 | @tar -cvjf $(TARGET)-$(VERSION).tar.bz2 hbmenu testfiles README.html COPYING hbmenu -X exclude.lst 120 | 121 | $(TARGET).nds: $(TARGET).arm7 $(TARGET).arm9 122 | # simple nds srl without dsi extended header thx Robz! 123 | ndstool -h 0x200 -c $(TARGET).nds -7 $(TARGET).arm7.elf -9 $(TARGET).arm9.elf -b icon.bmp "ButtonBoot;FlameKat53, Epicpkmn11" 124 | 125 | $(TARGET).arm7: arm7/$(TARGET).elf 126 | cp arm7/$(TARGET).elf $(TARGET).arm7.elf 127 | 128 | $(TARGET).arm9: arm9/$(TARGET).elf 129 | cp arm9/$(TARGET).elf $(TARGET).arm9.elf 130 | 131 | #--------------------------------------------------------------------------------- 132 | arm7/$(TARGET).elf: 133 | @$(MAKE) -C arm7 134 | 135 | #--------------------------------------------------------------------------------- 136 | arm9/$(TARGET).elf: 137 | @$(MAKE) -C arm9 138 | 139 | #--------------------------------------------------------------------------------- 140 | #$(BUILD): 141 | #@[ -d $@ ] || mkdir -p $@ 142 | #@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 143 | #--------------------------------------------------------------------------------- 144 | clean: 145 | @echo clean ... 146 | @rm -fr data 147 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds 148 | @rm -fr $(TARGET).arm7.elf 149 | @rm -fr $(TARGET).arm9.elf 150 | @$(MAKE) -C bootloader clean 151 | @$(MAKE) -C bootstub clean 152 | @$(MAKE) -C arm9 clean 153 | @$(MAKE) -C arm7 clean 154 | 155 | data: 156 | @mkdir -p data 157 | 158 | bootloader: data 159 | @$(MAKE) -C bootloader 160 | 161 | bootstub: data 162 | @$(MAKE) -C bootstub 163 | 164 | #--------------------------------------------------------------------------------- 165 | else 166 | 167 | #--------------------------------------------------------------------------------- 168 | # main targets 169 | #--------------------------------------------------------------------------------- 170 | #$(OUTPUT).nds : $(OUTPUT).elf 171 | #$(OUTPUT).elf : $(OFILES) 172 | 173 | #--------------------------------------------------------------------------------- 174 | %.bin.o : %.bin 175 | #--------------------------------------------------------------------------------- 176 | @echo $(notdir $<) 177 | $(bin2o) 178 | 179 | #--------------------------------------------------------------------------------- 180 | # This rule creates assembly source files using grit 181 | # grit takes an image file and a .grit describing how the file is to be processed 182 | # add additional rules like this for each image extension 183 | # you use in the graphics folders 184 | #--------------------------------------------------------------------------------- 185 | %.s %.h : %.bmp %.grit 186 | #--------------------------------------------------------------------------------- 187 | grit $< -fts -o$* 188 | 189 | 190 | #--------------------------------------------------------------------------------- 191 | %.s %.h : %.png %.grit 192 | #--------------------------------------------------------------------------------- 193 | grit $< -fts -o$* 194 | 195 | -include $(DEPSDIR)/*.d 196 | 197 | #--------------------------------------------------------------------------------------- 198 | endif 199 | #--------------------------------------------------------------------------------------- 200 | -------------------------------------------------------------------------------- /Makefile_DSi: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | .SECONDARY: 5 | 6 | ifeq ($(strip $(DEVKITARM)),) 7 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 8 | endif 9 | 10 | include $(DEVKITARM)/ds_rules 11 | 12 | export VERSION_MAJOR := 1 13 | export VERSION_MINOR := 0 14 | export VERSION_PATCH := 0 15 | 16 | 17 | VERSION := $(VERSION_MAJOR).$(VERSION_MINOR).$(VERSION_PATCH) 18 | #--------------------------------------------------------------------------------- 19 | # TARGET is the name of the output 20 | # BUILD is the directory where object files & intermediate files will be placed 21 | # SOURCES is a list of directories containing source code 22 | # INCLUDES is a list of directories containing extra header files 23 | # DATA is a list of directories containing binary files embedded using bin2o 24 | # GRAPHICS is a list of directories containing image files to be converted with grit 25 | #--------------------------------------------------------------------------------- 26 | TARGET := ButtonBoot 27 | BUILD := build 28 | SOURCES := source 29 | INCLUDES := include 30 | DATA := data 31 | 32 | #--------------------------------------------------------------------------------- 33 | # options for code generation 34 | #--------------------------------------------------------------------------------- 35 | ARCH := -mthumb -mthumb-interwork 36 | 37 | CFLAGS := -g -Wall -O2 \ 38 | -ffunction-sections -fdata-sections \ 39 | -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ 40 | -ffast-math \ 41 | $(ARCH) 42 | 43 | CFLAGS += $(INCLUDE) -DARM9 44 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=c++11 45 | 46 | ASFLAGS := -g $(ARCH) 47 | LDFLAGS = -specs=ds_arm9.specs -g -Wl,--gc-sections $(ARCH) -Wl,-Map,$(notdir $*.map) 48 | 49 | 50 | #--------------------------------------------------------------------------------- 51 | # list of directories containing libraries, this must be the top level containing 52 | # include and lib 53 | #--------------------------------------------------------------------------------- 54 | LIBDIRS := $(LIBNDS) 55 | 56 | #--------------------------------------------------------------------------------- 57 | # no real need to edit anything past this point unless you need to add additional 58 | # rules for different file extensions 59 | #--------------------------------------------------------------------------------- 60 | ifneq ($(BUILD),$(notdir $(CURDIR))) 61 | #--------------------------------------------------------------------------------- 62 | export TOPDIR := $(CURDIR) 63 | 64 | export OUTPUT := $(CURDIR)/$(TARGET) 65 | 66 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 67 | 68 | export DEPSDIR := $(CURDIR)/$(BUILD) 69 | 70 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 71 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 72 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 73 | BINFILES := load.bin bootstub.bin 74 | 75 | #--------------------------------------------------------------------------------- 76 | # use CXX for linking C++ projects, CC for standard C 77 | #--------------------------------------------------------------------------------- 78 | ifeq ($(strip $(CPPFILES)),) 79 | #--------------------------------------------------------------------------------- 80 | export LD := $(CC) 81 | #--------------------------------------------------------------------------------- 82 | else 83 | #--------------------------------------------------------------------------------- 84 | export LD := $(CXX) 85 | #--------------------------------------------------------------------------------- 86 | endif 87 | #--------------------------------------------------------------------------------- 88 | 89 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 90 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 91 | 92 | export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ 93 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 94 | -I$(CURDIR)/$(BUILD) 95 | 96 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 97 | 98 | icons := $(wildcard *.bmp) 99 | 100 | ifneq (,$(findstring $(TARGET).bmp,$(icons))) 101 | export GAME_ICON := $(CURDIR)/$(TARGET).bmp 102 | else 103 | ifneq (,$(findstring icon.bmp,$(icons))) 104 | export GAME_ICON := $(CURDIR)/icon.bmp 105 | endif 106 | endif 107 | 108 | export GAME_TITLE := $(TARGET) 109 | 110 | .PHONY: bootloader bootstub clean arm7/$(TARGET).elf arm9/$(TARGET).elf 111 | 112 | all: bootloader bootstub $(TARGET).nds 113 | 114 | dist: all 115 | @rm -fr hbmenu 116 | @mkdir hbmenu 117 | @cp $(TARGET).nds hbmenu/BOOT.NDS 118 | @cp BootStrap/_BOOT_MP.NDS BootStrap/TTMENU.DAT BootStrap/_DS_MENU.DAT BootStrap/ez5sys.bin BootStrap/akmenu4.nds hbmenu 119 | @tar -cvjf $(TARGET)-$(VERSION).tar.bz2 hbmenu testfiles README.html COPYING hbmenu -X exclude.lst 120 | 121 | $(TARGET).nds: $(TARGET).arm7 $(TARGET).arm9 122 | ndstool -c $(TARGET).nds -7 $(TARGET).arm7.elf -9 $(TARGET).arm9.elf \ 123 | -g HBBA 01 "BUTTONBOOT" -z 80040000 -u 00030004 -a 00000143 -b icon.bmp "ButtonBoot;FlameKat53, Epicpkmn11" 124 | 125 | $(TARGET).arm7: arm7/$(TARGET).elf 126 | cp arm7/$(TARGET).elf $(TARGET).arm7.elf 127 | 128 | $(TARGET).arm9: arm9/$(TARGET).elf 129 | cp arm9/$(TARGET).elf $(TARGET).arm9.elf 130 | 131 | #--------------------------------------------------------------------------------- 132 | arm7/$(TARGET).elf: 133 | @$(MAKE) -C arm7 134 | 135 | #--------------------------------------------------------------------------------- 136 | arm9/$(TARGET).elf: 137 | @$(MAKE) -C arm9 138 | 139 | #--------------------------------------------------------------------------------- 140 | #$(BUILD): 141 | #@[ -d $@ ] || mkdir -p $@ 142 | #@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 143 | #--------------------------------------------------------------------------------- 144 | clean: 145 | @echo clean ... 146 | @rm -fr data 147 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds 148 | @rm -fr $(TARGET).arm7.elf 149 | @rm -fr $(TARGET).arm9.elf 150 | @$(MAKE) -C bootloader clean 151 | @$(MAKE) -C bootstub clean 152 | @$(MAKE) -C arm9 clean 153 | @$(MAKE) -C arm7 clean 154 | 155 | data: 156 | @mkdir -p data 157 | 158 | bootloader: data 159 | @$(MAKE) -C bootloader 160 | 161 | bootstub: data 162 | @$(MAKE) -C bootstub 163 | 164 | #--------------------------------------------------------------------------------- 165 | else 166 | 167 | #--------------------------------------------------------------------------------- 168 | # main targets 169 | #--------------------------------------------------------------------------------- 170 | #$(OUTPUT).nds : $(OUTPUT).elf 171 | #$(OUTPUT).elf : $(OFILES) 172 | 173 | #--------------------------------------------------------------------------------- 174 | %.bin.o : %.bin 175 | #--------------------------------------------------------------------------------- 176 | @echo $(notdir $<) 177 | $(bin2o) 178 | 179 | #--------------------------------------------------------------------------------- 180 | # This rule creates assembly source files using grit 181 | # grit takes an image file and a .grit describing how the file is to be processed 182 | # add additional rules like this for each image extension 183 | # you use in the graphics folders 184 | #--------------------------------------------------------------------------------- 185 | %.s %.h : %.bmp %.grit 186 | #--------------------------------------------------------------------------------- 187 | grit $< -fts -o$* 188 | 189 | 190 | #--------------------------------------------------------------------------------- 191 | %.s %.h : %.png %.grit 192 | #--------------------------------------------------------------------------------- 193 | grit $< -fts -o$* 194 | 195 | -include $(DEPSDIR)/*.d 196 | 197 | #--------------------------------------------------------------------------------------- 198 | endif 199 | #--------------------------------------------------------------------------------------- 200 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 |

ButtonBoot

2 |

Made by FlameKat53, Epicpkmn11, RocketRobz

3 |

4 | 5 | 6 | 7 | 8 |

9 | 10 |

How To Use

11 |

12 | 13 | - 1.) Get some .nds homebrew. (You can get some [here](https://www.gamebrew.org/wiki/List_of_DS_homebrew_applications)) 14 | 15 | - 2.) Name your .nds files boot#.nds with # being one of these buttons; `A`, `B`, `X`, `Y`, `Start`, `Select`, `L`, `R`, `Left`, `Right`, `Down`, `Up`, or `Touch`. Alternatively, you can edit the `ButtonBoot.ini` file and set custom paths, names, and file extensions for your .nds files. 16 | 17 | - 3.) Put all of your .nds files into `_nds/extras/`, if you edited the .ini file with custom .nds paths you don't need to do this 18 | 19 | - 4.) Launch ButtonBoot and hold the button corresponding to the .nds file you want to launch. 20 | 21 | - 5.) Enjoy! 22 | 23 | 24 |

How to Autoboot into the app

25 |

26 | 27 | - If you use an `r4isdhc.com` or `r4i-sdhc.com` card, get the special `R4.dat` from [here](https://cdn.discordapp.com/attachments/286686210225864725/558474658274607114/r4.dat), then rename `ButtonBoot.nds` to `_BOOT_DS.nds` and place it on the root of your microSD card. 28 | 29 | - If you use DSiWarehax, rename `ButtonBoot_DSi.nds` to `BOOT.NDS` 30 | 31 |

Other

32 |

33 | 34 | - Please note retail .nds roms do not work, though YSMenu does. 35 | - [devkitPro](https://github.com/devkitPro), [WinterMute](https://github.com/WinterMute): Code used in nds-hb-menu, and the use of the bootloader, devkitARM, libnds, and libfat. 36 | - [CardIDGetter](https://github.com/RocketRobz/CardIDGetter), The arm7 code and Makefile's. 37 | - [TWiLightMenu](https://github.com/DS-Homebrew/TWiLightMenu), Inifile, bootstub, bootloader code and a lot more. 38 | - [GodMode9i](https://github.com/DS-Homebrew/GodMode9i), Some code from the GitHub Actions -------------------------------------------------------------------------------- /arm7/Makefile: -------------------------------------------------------------------------------- 1 | 2 | export ARM7_MAJOR := 0 3 | export ARM7_MINOR := 6 4 | export ARM7_PATCH := 0 5 | 6 | VERSTRING := $(ARM7_MAJOR).$(ARM7_MINOR).$(ARM7_PATCH) 7 | #--------------------------------------------------------------------------------- 8 | .SUFFIXES: 9 | #--------------------------------------------------------------------------------- 10 | ifeq ($(strip $(DEVKITARM)),) 11 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM) 12 | endif 13 | 14 | include $(DEVKITARM)/ds_rules 15 | #--------------------------------------------------------------------------------- 16 | # TARGET is the name of the output 17 | # BUILD is the directory where object files & intermediate files will be placed 18 | # SOURCES is a list of directories containing source code 19 | # INCLUDES is a list of directories containing extra header files 20 | #--------------------------------------------------------------------------------- 21 | TARGET := ButtonBoot 22 | BUILD := build 23 | SOURCES := source 24 | INCLUDES := include build 25 | 26 | #--------------------------------------------------------------------------------- 27 | # options for code generation 28 | #--------------------------------------------------------------------------------- 29 | ARCH := -march=armv4t -mthumb -mthumb-interwork 30 | 31 | CFLAGS := -g -Wall -O2\ 32 | -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ 33 | -ffast-math \ 34 | $(ARCH) 35 | 36 | CFLAGS += $(INCLUDE) -DARM7 37 | 38 | ASFLAGS := -g $(ARCH) 39 | LDFLAGS = -specs=ds_arm7.specs -g $(ARCH) -Wl,--nmagic -Wl,-Map,$(notdir $*).map 40 | 41 | 42 | #--------------------------------------------------------------------------------- 43 | # any extra libraries we wish to link with the project 44 | #--------------------------------------------------------------------------------- 45 | LIBS := -lnds7 46 | 47 | 48 | #--------------------------------------------------------------------------------- 49 | # list of directories containing libraries, this must be the top level containing 50 | # include and lib 51 | #--------------------------------------------------------------------------------- 52 | LIBDIRS := $(LIBNDS) 53 | 54 | 55 | #--------------------------------------------------------------------------------- 56 | # no real need to edit anything past this point unless you need to add additional 57 | # rules for different file extensions 58 | #--------------------------------------------------------------------------------- 59 | ifneq ($(BUILD),$(notdir $(CURDIR))) 60 | #--------------------------------------------------------------------------------- 61 | 62 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 63 | 64 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 65 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 66 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 67 | 68 | export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 69 | 70 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 71 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 72 | -I$(CURDIR)/$(BUILD) 73 | 74 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 75 | 76 | export DEPSDIR := $(CURDIR)/$(BUILD) 77 | 78 | export OUTPUT := $(CURDIR)/$(TARGET) 79 | 80 | #--------------------------------------------------------------------------------- 81 | # use CXX for linking C++ projects, CC for standard C 82 | #--------------------------------------------------------------------------------- 83 | ifeq ($(strip $(CPPFILES)),) 84 | #--------------------------------------------------------------------------------- 85 | export LD := $(CC) 86 | #--------------------------------------------------------------------------------- 87 | else 88 | #--------------------------------------------------------------------------------- 89 | export LD := $(CXX) 90 | #--------------------------------------------------------------------------------- 91 | endif 92 | #--------------------------------------------------------------------------------- 93 | 94 | .PHONY: all $(BUILD) clean 95 | 96 | all : $(BUILD) 97 | 98 | #--------------------------------------------------------------------------------- 99 | $(BUILD): 100 | @[ -d $@ ] || mkdir -p $@ 101 | @$(MAKE) -C $(BUILD) -f $(CURDIR)/Makefile 102 | 103 | 104 | #--------------------------------------------------------------------------------- 105 | dist: all 106 | #--------------------------------------------------------------------------------- 107 | @tar --exclude=*CVS* --exclude=.svn -cvjf default_arm7-src-$(VERSTRING).tar.bz2 source Makefile 108 | @tar -cvjf default_arm7-$(VERSTRING).tar.bz2 default.elf 109 | 110 | #--------------------------------------------------------------------------------- 111 | install: all 112 | #--------------------------------------------------------------------------------- 113 | cp $(TARGET).elf $(LIBNDS) 114 | 115 | #--------------------------------------------------------------------------------- 116 | clean: 117 | @echo clean ... 118 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).arm7 119 | 120 | 121 | #--------------------------------------------------------------------------------- 122 | else 123 | 124 | DEPENDS := $(OFILES:.o=.d) 125 | 126 | #--------------------------------------------------------------------------------- 127 | # main targets 128 | #--------------------------------------------------------------------------------- 129 | 130 | $(OUTPUT).elf : $(OFILES) $(LIBNDS)/lib/libnds7.a 131 | 132 | -include $(DEPENDS) 133 | 134 | #--------------------------------------------------------------------------------------- 135 | endif 136 | #--------------------------------------------------------------------------------------- 137 | -------------------------------------------------------------------------------- /arm7/source/main.c: -------------------------------------------------------------------------------- 1 | 2 | /*--------------------------------------------------------------------------------- 3 | default ARM7 core 4 | Copyright (C) 2005 - 2010 5 | Michael Noland (joat) 6 | Jason Rogers (dovoto) 7 | Dave Murphy (WinterMute) 8 | This software is provided 'as-is', without any express or implied 9 | warranty. In no event will the authors be held liable for any 10 | damages arising from the use of this software. 11 | Permission is granted to anyone to use this software for any 12 | purpose, including commercial applications, and to alter it and 13 | redistribute it freely, subject to the following restrictions: 14 | 1. The origin of this software must not be misrepresented; you 15 | must not claim that you wrote the original software. If you use 16 | this software in a product, an acknowledgment in the product 17 | documentation would be appreciated but is not required. 18 | 2. Altered source versions must be plainly marked as such, and 19 | must not be misrepresented as being the original software. 20 | 3. This notice may not be removed or altered from any source 21 | distribution. 22 | ---------------------------------------------------------------------------------*/ 23 | #include 24 | 25 | //--------------------------------------------------------------------------------- 26 | void VblankHandler(void) { 27 | //--------------------------------------------------------------------------------- 28 | } 29 | 30 | //--------------------------------------------------------------------------------- 31 | void VcountHandler() { 32 | //--------------------------------------------------------------------------------- 33 | inputGetAndSend(); 34 | } 35 | 36 | volatile bool exitflag = false; 37 | 38 | //--------------------------------------------------------------------------------- 39 | void powerButtonCB() { 40 | //--------------------------------------------------------------------------------- 41 | exitflag = true; 42 | } 43 | 44 | //--------------------------------------------------------------------------------- 45 | int main() { 46 | //--------------------------------------------------------------------------------- 47 | nocashMessage("ARM7 main.c main"); 48 | 49 | // clear sound registers 50 | dmaFillWords(0, (void*)0x04000400, 0x100); 51 | 52 | REG_SOUNDCNT |= SOUND_ENABLE; 53 | writePowerManagement(PM_CONTROL_REG, ( readPowerManagement(PM_CONTROL_REG) & ~PM_SOUND_MUTE ) | PM_SOUND_AMP ); 54 | powerOn(POWER_SOUND); 55 | 56 | ledBlink(0); 57 | 58 | irqInit(); 59 | 60 | fifoInit(); 61 | 62 | SetYtrigger(80); 63 | 64 | installSystemFIFO(); 65 | 66 | irqSet(IRQ_VCOUNT, VcountHandler); 67 | irqSet(IRQ_VBLANK, VblankHandler); 68 | 69 | irqEnable( IRQ_VBLANK | IRQ_VCOUNT ); 70 | 71 | setPowerButtonCB(powerButtonCB); 72 | 73 | // Keep the ARM7 mostly idle 74 | while (!exitflag) { 75 | // fifocheck(); 76 | swiWaitForVBlank(); 77 | } 78 | return 0; 79 | } 80 | -------------------------------------------------------------------------------- /arm9/Makefile: -------------------------------------------------------------------------------- 1 | 2 | #--------------------------------------------------------------------------------- 3 | .SUFFIXES: 4 | #--------------------------------------------------------------------------------- 5 | 6 | ifeq ($(strip $(DEVKITARM)),) 7 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM") 8 | endif 9 | 10 | include $(DEVKITARM)/ds_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 | # INCLUDES is a list of directories containing extra header files 17 | # DATA is a list of directories containing binary files embedded using bin2o 18 | # GRAPHICS is a list of directories containing image files to be converted with grit 19 | # MAXMOD_SOUNDBANK contains a directory of music and sound effect files 20 | #--------------------------------------------------------------------------------- 21 | TARGET := ButtonBoot 22 | BUILD := build 23 | SOURCES := source source/common 24 | INCLUDES := include 25 | DATA := ../data 26 | 27 | #--------------------------------------------------------------------------------- 28 | # options for code generation 29 | #--------------------------------------------------------------------------------- 30 | ARCH := -mthumb -mthumb-interwork 31 | 32 | CFLAGS := -g -Wall -O2\ 33 | -march=armv5te -mtune=arm946e-s -fomit-frame-pointer\ 34 | -ffast-math \ 35 | $(ARCH) 36 | 37 | CFLAGS += $(INCLUDE) -DARM9 38 | CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11 39 | 40 | ASFLAGS := -g $(ARCH) 41 | LDFLAGS = -specs=ds_arm9.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map) 42 | 43 | #--------------------------------------------------------------------------------- 44 | # any extra libraries we wish to link with the project (order is important) 45 | #--------------------------------------------------------------------------------- 46 | LIBS := -lfat -lnds9 47 | 48 | 49 | #--------------------------------------------------------------------------------- 50 | # list of directories containing libraries, this must be the top level containing 51 | # include and lib 52 | #--------------------------------------------------------------------------------- 53 | LIBDIRS := $(CURDIR) ../ $(LIBNDS) 54 | 55 | #--------------------------------------------------------------------------------- 56 | # no real need to edit anything past this point unless you need to add additional 57 | # rules for different file extensions 58 | #--------------------------------------------------------------------------------- 59 | ifneq ($(BUILD),$(notdir $(CURDIR))) 60 | #--------------------------------------------------------------------------------- 61 | 62 | export OUTPUT := $(CURDIR)/$(TARGET) 63 | 64 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \ 65 | $(foreach dir,$(DATA),$(CURDIR)/$(dir)) 66 | 67 | export DEPSDIR := $(CURDIR)/$(BUILD) 68 | 69 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 70 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 71 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 72 | BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*))) 73 | 74 | #--------------------------------------------------------------------------------- 75 | # use CXX for linking C++ projects, CC for standard C 76 | #--------------------------------------------------------------------------------- 77 | ifeq ($(strip $(CPPFILES)),) 78 | #--------------------------------------------------------------------------------- 79 | export LD := $(CC) 80 | #--------------------------------------------------------------------------------- 81 | else 82 | #--------------------------------------------------------------------------------- 83 | export LD := $(CXX) 84 | #--------------------------------------------------------------------------------- 85 | endif 86 | #--------------------------------------------------------------------------------- 87 | 88 | export OFILES := $(addsuffix .o,$(BINFILES)) \ 89 | $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 90 | 91 | export INCLUDE := $(foreach dir,$(INCLUDES),-iquote $(CURDIR)/$(dir)) \ 92 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 93 | -I$(CURDIR)/$(BUILD) 94 | 95 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 96 | 97 | 98 | export OUTPUT := $(CURDIR)/$(TARGET) 99 | 100 | .PHONY: $(BUILD) clean 101 | 102 | all : $(BUILD) 103 | 104 | #--------------------------------------------------------------------------------- 105 | $(BUILD): 106 | @[ -d $@ ] || mkdir -p $@ 107 | @make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile 108 | #--------------------------------------------------------------------------------- 109 | clean: 110 | @echo clean ... 111 | @rm -fr $(BUILD) $(TARGET).elf $(TARGET).nds *.bin 112 | 113 | #--------------------------------------------------------------------------------- 114 | else 115 | 116 | DEPENDS := $(OFILES:.o=.d) 117 | 118 | #--------------------------------------------------------------------------------- 119 | # main targets 120 | #--------------------------------------------------------------------------------- 121 | $(OUTPUT).elf : $(OFILES) 122 | 123 | #--------------------------------------------------------------------------------- 124 | %.bin.o : %.bin 125 | #--------------------------------------------------------------------------------- 126 | @echo $(notdir $<) 127 | $(bin2o) 128 | 129 | #--------------------------------------------------------------------------------- 130 | # This rule creates assembly source files using grit 131 | # grit takes an image file and a .grit describing how the file is to be processed 132 | # add additional rules like this for each image extension 133 | # you use in the graphics folders 134 | #--------------------------------------------------------------------------------- 135 | %.s %.h : %.bmp %.grit 136 | #--------------------------------------------------------------------------------- 137 | grit $< -fts -o$* 138 | 139 | 140 | #--------------------------------------------------------------------------------- 141 | %.s %.h : %.png %.grit 142 | #--------------------------------------------------------------------------------- 143 | grit $< -fts -o$* 144 | 145 | -include $(DEPSDIR)/*.d 146 | 147 | #--------------------------------------------------------------------------------------- 148 | endif 149 | #--------------------------------------------------------------------------------------- 150 | -------------------------------------------------------------------------------- /arm9/source/common/inifile.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | inifile.cpp 3 | Copyright (C) 2007 Acekard, www.acekard.com 4 | Copyright (C) 2007-2009 somebody 5 | Copyright (C) 2009 yellow wood goblin 6 | This program is free software: you can redistribute it and/or modify 7 | it under the terms of the GNU General Public License as published by 8 | the Free Software Foundation, either version 3 of the License, or 9 | (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | */ 17 | 18 | #include 19 | #include 20 | #include "inifile.h" 21 | #include "stringtool.h" 22 | 23 | static bool freadLine(FILE* f,std::string& str) 24 | { 25 | str.clear(); 26 | __read: 27 | char p=0; 28 | 29 | size_t readed=fread(&p,1,1,f); 30 | if(0==readed) 31 | { 32 | str=""; 33 | return false; 34 | } 35 | if('\n'==p||'\r'==p) 36 | { 37 | str=""; 38 | return true; 39 | } 40 | 41 | while(p!='\n'&&p!='\r'&&readed) 42 | { 43 | str+=p; 44 | readed=fread(&p,1,1,f); 45 | } 46 | 47 | if(str.empty()||""==str) 48 | { 49 | goto __read; 50 | } 51 | 52 | return true; 53 | } 54 | 55 | static void trimString(std::string& str) 56 | { 57 | size_t first=str.find_first_not_of(" \t"),last; 58 | if(first==str.npos) 59 | { 60 | str=""; 61 | } 62 | else 63 | { 64 | last=str.find_last_not_of(" \t"); 65 | if(first>0||(last+1)0) 88 | { 89 | m_FileContainer.clear(); 90 | } 91 | } 92 | 93 | void CIniFile::SetString(const std::string& Section,const std::string& Item,const std::string& Value) 94 | { 95 | if(GetFileString(Section,Item)!=Value) 96 | { 97 | SetFileString(Section,Item,Value); 98 | m_bModified=true; 99 | } 100 | } 101 | 102 | void CIniFile::SetInt(const std::string& Section,const std::string& Item,int Value) 103 | { 104 | std::string strtemp=formatString("%d",Value); 105 | 106 | if(GetFileString(Section,Item)!=strtemp) 107 | { 108 | SetFileString(Section,Item,strtemp); 109 | m_bModified=true; 110 | } 111 | } 112 | 113 | std::string CIniFile::GetString(const std::string& Section,const std::string& Item) 114 | { 115 | return GetFileString(Section,Item); 116 | } 117 | 118 | std::string CIniFile::GetString(const std::string& Section,const std::string& Item,const std::string& DefaultValue) 119 | { 120 | std::string temp=GetString(Section,Item); 121 | if(!m_bLastResult) 122 | { 123 | SetString(Section,Item,DefaultValue); 124 | temp=DefaultValue; 125 | } 126 | return temp; 127 | } 128 | 129 | void CIniFile::GetStringVector(const std::string& Section,const std::string& Item,std::vector< std::string >& strings,char delimiter) 130 | { 131 | std::string strValue=GetFileString(Section,Item); 132 | strings.clear(); 133 | size_t pos; 134 | while((pos=strValue.find(delimiter),strValue.npos!=pos)) 135 | { 136 | const std::string string=strValue.substr(0,pos); 137 | if(string.length()) 138 | { 139 | strings.push_back(string); 140 | } 141 | strValue=strValue.substr(pos+1,strValue.npos); 142 | } 143 | if(strValue.length()) 144 | { 145 | strings.push_back(strValue); 146 | } 147 | } 148 | 149 | void CIniFile::SetStringVector(const std::string& Section,const std::string& Item,std::vector& strings,char delimiter) 150 | { 151 | std::string strValue; 152 | for(size_t ii=0;ii2&&'0'==value[0]&&('x'==value[1]||'X'==value[1])) 164 | return strtol(value.c_str(),NULL,16); 165 | else 166 | return strtol(value.c_str(),NULL,10); 167 | } 168 | 169 | int CIniFile::GetInt(const std::string& Section,const std::string& Item,int DefaultValue) 170 | { 171 | int temp; 172 | temp=GetInt(Section,Item); 173 | if(!m_bLastResult) 174 | { 175 | SetInt(Section,Item,DefaultValue); 176 | temp=DefaultValue; 177 | } 178 | return temp; 179 | } 180 | 181 | bool CIniFile::LoadIniFile(const std::string& FileName) 182 | { 183 | //dbg_printf("load %s\n",FileName.c_str()); 184 | if(FileName!="") m_sFileName=FileName; 185 | 186 | FILE* f=fopen(FileName.c_str(),"rb"); 187 | 188 | if(NULL==f) return false; 189 | 190 | //check for utf8 bom. 191 | char bom[3]; 192 | if(fread(bom,3,1,f)==1&&bom[0]==0xef&&bom[1]==0xbb&&bom[2]==0xbf) ; 193 | else fseek(f,0,SEEK_SET); 194 | 195 | std::string strline(""); 196 | m_FileContainer.clear(); 197 | 198 | while(freadLine(f,strline)) 199 | { 200 | trimString(strline); 201 | if(strline!=""&&';'!=strline[0]&&'/'!=strline[0]&&'!'!=strline[0]) m_FileContainer.push_back(strline); 202 | } 203 | 204 | fclose(f); 205 | 206 | m_bLastResult=false; 207 | m_bModified=false; 208 | 209 | return true; 210 | } 211 | 212 | bool CIniFile::SaveIniFileModified(const std::string& FileName) 213 | { 214 | if(m_bModified==true) 215 | { 216 | return SaveIniFile(FileName); 217 | } 218 | 219 | return true; 220 | } 221 | 222 | bool CIniFile::SaveIniFile(const std::string& FileName) 223 | { 224 | if(FileName!="") 225 | m_sFileName=FileName; 226 | 227 | FILE* f=fopen(m_sFileName.c_str(),"wb"); 228 | if(NULL==f) 229 | { 230 | return false; 231 | } 232 | 233 | for(size_t ii=0;ii0) 239 | { 240 | if(!m_FileContainer[ii-1].empty()&&m_FileContainer[ii-1]!="") 241 | fwrite("\r\n",1,2,f); 242 | } 243 | if(!strline.empty()&&strline!="") 244 | { 245 | fwrite(strline.c_str(),1,strline.length(),f); 246 | fwrite("\r\n",1,2,f); 247 | } 248 | } 249 | 250 | fclose(f); 251 | 252 | m_bModified=false; 253 | 254 | return true; 255 | } 256 | 257 | std::string CIniFile::GetFileString(const std::string& Section,const std::string& Item) 258 | { 259 | std::string strline; 260 | std::string strSection; 261 | std::string strItem; 262 | std::string strValue; 263 | 264 | size_t ii=0; 265 | size_t iFileLines=m_FileContainer.size(); 266 | 267 | if(m_bReadOnly) 268 | { 269 | cSectionCache::iterator it=m_Cache.find(Section); 270 | if((it!=m_Cache.end())) ii=it->second; 271 | } 272 | 273 | m_bLastResult=false; 274 | 275 | if(iFileLines>=0) 276 | { 277 | while(ii0&&rBracketPos!=std::string::npos) 284 | { 285 | strSection=strline.substr(1,rBracketPos-1); 286 | if(m_bReadOnly) m_Cache.insert(std::make_pair(strSection,ii-1)); 287 | if(strSection==Section) 288 | { 289 | while(ii0&&rBracketPos!=std::string::npos) 339 | { 340 | strSection=strline.substr(1,rBracketPos-1); 341 | if(strSection==Section) 342 | { 343 | while(ii 19 | #include 20 | #include 21 | #include 22 | #include 23 | 24 | #include 25 | #include 26 | 27 | #include "load_bin.h" 28 | 29 | #ifndef _NO_BOOTSTUB_ 30 | #include "bootstub_bin.h" 31 | #endif 32 | 33 | #include "nds_loader_arm9.h" 34 | #define LCDC_BANK_C (u16*)0x06840000 35 | #define STORED_FILE_CLUSTER (*(((u32*)LCDC_BANK_C) + 1)) 36 | #define INIT_DISC (*(((u32*)LCDC_BANK_C) + 2)) 37 | #define WANT_TO_PATCH_DLDI (*(((u32*)LCDC_BANK_C) + 3)) 38 | 39 | #define STORED_FILE_CLUSTER_OFFSET 4 40 | #define INIT_DISC_OFFSET 8 41 | #define WANT_TO_PATCH_DLDI_OFFSET 12 42 | #define ARG_START_OFFSET 16 43 | #define ARG_SIZE_OFFSET 20 44 | #define HAVE_DSISD_OFFSET 28 45 | #define DSIMODE_OFFSET 32 46 | #define CLEAR_MASTER_BRIGHT_OFFSET 36 47 | 48 | 49 | typedef signed int addr_t; 50 | typedef unsigned char data_t; 51 | 52 | #define FIX_ALL 0x01 53 | #define FIX_GLUE 0x02 54 | #define FIX_GOT 0x04 55 | #define FIX_BSS 0x08 56 | 57 | enum DldiOffsets { 58 | DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" 59 | DO_magicToken = 0x00, // 0xBF8DA5ED 60 | DO_magicShortString = 0x04, // " Chishm" 61 | DO_version = 0x0C, 62 | DO_driverSize = 0x0D, 63 | DO_fixSections = 0x0E, 64 | DO_allocatedSpace = 0x0F, 65 | 66 | DO_friendlyName = 0x10, 67 | 68 | DO_text_start = 0x40, // Data start 69 | DO_data_end = 0x44, // Data end 70 | DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing 71 | DO_glue_end = 0x4C, // Interworking glue end 72 | DO_got_start = 0x50, // GOT start -- Needs address fixing 73 | DO_got_end = 0x54, // GOT end 74 | DO_bss_start = 0x58, // bss start -- Needs setting to zero 75 | DO_bss_end = 0x5C, // bss end 76 | 77 | // IO_INTERFACE data 78 | DO_ioType = 0x60, 79 | DO_features = 0x64, 80 | DO_startup = 0x68, 81 | DO_isInserted = 0x6C, 82 | DO_readSectors = 0x70, 83 | DO_writeSectors = 0x74, 84 | DO_clearStatus = 0x78, 85 | DO_shutdown = 0x7C, 86 | DO_code = 0x80 87 | }; 88 | 89 | static addr_t readAddr (data_t *mem, addr_t offset) { 90 | return ((addr_t*)mem)[offset/sizeof(addr_t)]; 91 | } 92 | 93 | static void writeAddr (data_t *mem, addr_t offset, addr_t value) { 94 | ((addr_t*)mem)[offset/sizeof(addr_t)] = value; 95 | } 96 | 97 | static void vramcpy (void* dst, const void* src, int len) 98 | { 99 | u16* dst16 = (u16*)dst; 100 | u16* src16 = (u16*)src; 101 | 102 | //dmaCopy(src, dst, len); 103 | 104 | for ( ; len > 0; len -= 2) { 105 | *dst16++ = *src16++; 106 | } 107 | } 108 | 109 | static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { 110 | const int* dataChunk = (const int*) data; 111 | int searchChunk = ((const int*)search)[0]; 112 | addr_t i; 113 | addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int)); 114 | 115 | for ( i = 0; i < dataChunkEnd; i++) { 116 | if (dataChunk[i] == searchChunk) { 117 | if ((i*sizeof(int) + searchLen) > dataLen) { 118 | return -1; 119 | } 120 | if (memcmp (&data[i*sizeof(int)], search, searchLen) == 0) { 121 | return i*sizeof(int); 122 | } 123 | } 124 | } 125 | 126 | return -1; 127 | } 128 | 129 | // Normal DLDI uses "\xED\xA5\x8D\xBF Chishm" 130 | // Bootloader string is different to avoid being patched 131 | static const data_t dldiMagicLoaderString[] = "\xEE\xA5\x8D\xBF Chishm"; // Different to a normal DLDI file 132 | 133 | #define DEVICE_TYPE_DLDI 0x49444C44 134 | 135 | static bool dldiPatchLoader (data_t *binData, u32 binSize, bool clearBSS) 136 | { 137 | addr_t memOffset; // Offset of DLDI after the file is loaded into memory 138 | addr_t patchOffset; // Position of patch destination in the file 139 | addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly 140 | addr_t ddmemOffset; // Original offset used in the DLDI file 141 | addr_t ddmemStart; // Start of range that offsets can be in the DLDI file 142 | addr_t ddmemEnd; // End of range that offsets can be in the DLDI file 143 | addr_t ddmemSize; // Size of range that offsets can be in the DLDI file 144 | 145 | addr_t addrIter; 146 | 147 | data_t *pDH; 148 | data_t *pAH; 149 | 150 | size_t dldiFileSize = 0; 151 | 152 | // Find the DLDI reserved space in the file 153 | patchOffset = quickFind (binData, dldiMagicLoaderString, binSize, sizeof(dldiMagicLoaderString)); 154 | 155 | if (patchOffset < 0) { 156 | // does not have a DLDI section 157 | return false; 158 | } 159 | 160 | pDH = (data_t*)(io_dldi_data); 161 | 162 | pAH = &(binData[patchOffset]); 163 | 164 | if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI) { 165 | // No DLDI patch 166 | return false; 167 | } 168 | 169 | if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { 170 | // Not enough space for patch 171 | return false; 172 | } 173 | 174 | dldiFileSize = 1 << pDH[DO_driverSize]; 175 | 176 | memOffset = readAddr (pAH, DO_text_start); 177 | if (memOffset == 0) { 178 | memOffset = readAddr (pAH, DO_startup) - DO_code; 179 | } 180 | ddmemOffset = readAddr (pDH, DO_text_start); 181 | relocationOffset = memOffset - ddmemOffset; 182 | 183 | ddmemStart = readAddr (pDH, DO_text_start); 184 | ddmemSize = (1 << pDH[DO_driverSize]); 185 | ddmemEnd = ddmemStart + ddmemSize; 186 | 187 | // Remember how much space is actually reserved 188 | pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; 189 | // Copy the DLDI patch into the application 190 | vramcpy (pAH, pDH, dldiFileSize); 191 | 192 | // Fix the section pointers in the header 193 | writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); 194 | writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); 195 | writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); 196 | writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); 197 | writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); 198 | writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); 199 | writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); 200 | writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); 201 | // Fix the function pointers in the header 202 | writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); 203 | writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); 204 | writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); 205 | writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); 206 | writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); 207 | writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); 208 | 209 | if (pDH[DO_fixSections] & FIX_ALL) { 210 | // Search through and fix pointers within the data section of the file 211 | for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { 212 | if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { 213 | writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); 214 | } 215 | } 216 | } 217 | 218 | if (pDH[DO_fixSections] & FIX_GLUE) { 219 | // Search through and fix pointers within the glue section of the file 220 | for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { 221 | if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { 222 | writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); 223 | } 224 | } 225 | } 226 | 227 | if (pDH[DO_fixSections] & FIX_GOT) { 228 | // Search through and fix pointers within the Global Offset Table section of the file 229 | for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { 230 | if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { 231 | writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); 232 | } 233 | } 234 | } 235 | 236 | if (clearBSS && (pDH[DO_fixSections] & FIX_BSS)) { 237 | // Initialise the BSS to 0, only if the disc is being re-inited 238 | memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); 239 | } 240 | 241 | return true; 242 | } 243 | 244 | int runNds (const void* loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char** argv, bool clearMasterBright) 245 | { 246 | char* argStart; 247 | u16* argData; 248 | u16 argTempVal = 0; 249 | int argSize; 250 | const char* argChar; 251 | 252 | irqDisable(IRQ_ALL); 253 | 254 | // Direct CPU access to VRAM bank C 255 | VRAM_C_CR = VRAM_ENABLE | VRAM_C_LCD; 256 | // Load the loader/patcher into the correct address 257 | vramcpy (LCDC_BANK_C, loader, loaderSize); 258 | 259 | // Set the parameters for the loader 260 | // STORED_FILE_CLUSTER = cluster; 261 | writeAddr ((data_t*) LCDC_BANK_C, STORED_FILE_CLUSTER_OFFSET, cluster); 262 | // INIT_DISC = initDisc; 263 | writeAddr ((data_t*) LCDC_BANK_C, INIT_DISC_OFFSET, initDisc); 264 | 265 | writeAddr ((data_t*) LCDC_BANK_C, DSIMODE_OFFSET, isDSiMode()); 266 | if(argv[0][0]=='s' && argv[0][1]=='d') { 267 | dldiPatchNds = false; 268 | writeAddr ((data_t*) LCDC_BANK_C, HAVE_DSISD_OFFSET, 1); 269 | } 270 | 271 | writeAddr ((data_t*) LCDC_BANK_C, CLEAR_MASTER_BRIGHT_OFFSET, clearMasterBright); 272 | 273 | // WANT_TO_PATCH_DLDI = dldiPatchNds; 274 | writeAddr ((data_t*) LCDC_BANK_C, WANT_TO_PATCH_DLDI_OFFSET, dldiPatchNds); 275 | // Give arguments to loader 276 | argStart = (char*)LCDC_BANK_C + readAddr((data_t*)LCDC_BANK_C, ARG_START_OFFSET); 277 | argStart = (char*)(((int)argStart + 3) & ~3); // Align to word 278 | argData = (u16*)argStart; 279 | argSize = 0; 280 | 281 | for (; argc > 0 && *argv; ++argv, --argc) 282 | { 283 | for (argChar = *argv; *argChar != 0; ++argChar, ++argSize) 284 | { 285 | if (argSize & 1) 286 | { 287 | argTempVal |= (*argChar) << 8; 288 | *argData = argTempVal; 289 | ++argData; 290 | } 291 | else 292 | { 293 | argTempVal = *argChar; 294 | } 295 | } 296 | if (argSize & 1) 297 | { 298 | *argData = argTempVal; 299 | ++argData; 300 | } 301 | argTempVal = 0; 302 | ++argSize; 303 | } 304 | *argData = argTempVal; 305 | 306 | writeAddr ((data_t*) LCDC_BANK_C, ARG_START_OFFSET, (addr_t)argStart - (addr_t)LCDC_BANK_C); 307 | writeAddr ((data_t*) LCDC_BANK_C, ARG_SIZE_OFFSET, argSize); 308 | 309 | 310 | if(dldiPatchNds) { 311 | // Patch the loader with a DLDI for the card 312 | if (!dldiPatchLoader ((data_t*)LCDC_BANK_C, loaderSize, initDisc)) { 313 | return 3; 314 | } 315 | } 316 | 317 | irqDisable(IRQ_ALL); 318 | 319 | // Give the VRAM to the ARM7 320 | VRAM_C_CR = VRAM_ENABLE | VRAM_C_ARM7_0x06000000; 321 | // Reset into a passme loop 322 | REG_EXMEMCNT |= ARM7_OWNS_ROM | ARM7_OWNS_CARD; 323 | *((vu32*)0x02FFFFFC) = 0; 324 | *((vu32*)0x02FFFE04) = (u32)0xE59FF018; 325 | *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; 326 | 327 | resetARM7(0x06000000); 328 | 329 | swiSoftReset(); 330 | return true; 331 | } 332 | 333 | int runNdsFile (const char* filename, int argc, const char** argv, bool clearMasterBright) { 334 | struct stat st; 335 | char filePath[PATH_MAX]; 336 | int pathLen; 337 | const char* args[1]; 338 | 339 | 340 | if (stat (filename, &st) < 0) { 341 | return 1; 342 | } 343 | 344 | if (argc <= 0 || !argv) { 345 | // Construct a command line if we weren't supplied with one 346 | if (!getcwd (filePath, PATH_MAX)) { 347 | return 2; 348 | } 349 | pathLen = strlen (filePath); 350 | strcpy (filePath + pathLen, filename); 351 | args[0] = filePath; 352 | argv = args; 353 | } 354 | 355 | bool havedsiSD = false; 356 | 357 | if(argv[0][0]=='s' && argv[0][1]=='d') havedsiSD = true; 358 | 359 | installBootStub(havedsiSD); 360 | 361 | return runNds (load_bin, load_bin_size, st.st_ino, true, true, argc, argv, clearMasterBright); 362 | } 363 | 364 | bool installBootStub(bool havedsiSD) { 365 | #ifndef _NO_BOOTSTUB_ 366 | extern char *fake_heap_end; 367 | struct __bootstub *bootstub = (struct __bootstub *)fake_heap_end; 368 | u32 *bootloader = (u32*)(fake_heap_end+bootstub_bin_size); 369 | 370 | memcpy(bootstub,bootstub_bin,bootstub_bin_size); 371 | memcpy(bootloader,load_bin,load_bin_size); 372 | bool ret = false; 373 | 374 | bootloader[8] = isDSiMode(); 375 | if( havedsiSD) { 376 | ret = true; 377 | bootloader[3] = 0; // don't dldi patch 378 | bootloader[7] = 1; // use internal dsi SD code 379 | } else { 380 | ret = dldiPatchLoader((data_t*)bootloader, load_bin_size,false); 381 | } 382 | bootstub->arm9reboot = (VoidFn)(((u32)bootstub->arm9reboot)+fake_heap_end); 383 | bootstub->arm7reboot = (VoidFn)(((u32)bootstub->arm7reboot)+fake_heap_end); 384 | bootstub->bootsize = load_bin_size; 385 | 386 | DC_FlushAll(); 387 | 388 | return ret; 389 | #else 390 | return true; 391 | #endif 392 | 393 | } 394 | -------------------------------------------------------------------------------- /arm9/source/common/nds_loader_arm9.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | Copyright (C) 2005 - 2010 3 | Michael "Chishm" Chisholm 4 | Dave "WinterMute" Murphy 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | You should have received a copy of the GNU General Public License 14 | along with this program; if not, write to the Free Software 15 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 16 | ------------------------------------------------------------------*/ 17 | 18 | #ifndef NDS_LOADER_ARM9_H 19 | #define NDS_LOADER_ARM9_H 20 | 21 | #ifdef __cplusplus 22 | extern "C" 23 | { 24 | #endif 25 | 26 | #define LOAD_DEFAULT_NDS 0 27 | 28 | int runNds(const void *loader, u32 loaderSize, u32 cluster, bool initDisc, bool dldiPatchNds, int argc, const char **argv, bool clearMasterBright); 29 | 30 | int runNdsFile(const char *filename, int argc, const char **argv, bool clearMasterBright); 31 | 32 | bool installBootStub(bool havedsiSD); 33 | 34 | #ifdef __cplusplus 35 | } 36 | #endif 37 | 38 | #endif // NDS_LOADER_ARM7_H 39 | -------------------------------------------------------------------------------- /arm9/source/common/singleton.h: -------------------------------------------------------------------------------- 1 | /* 2 | common/singleton.h 3 | Copyright (c) 2018 chyyran 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 | */ 23 | 24 | #pragma once 25 | #ifndef _SINGLETON_H_ 26 | #define _SINGLETON_H_ 27 | #include 28 | #include 29 | #include // std::nothrow 30 | 31 | template 32 | class singleton 33 | { 34 | 35 | public: 36 | static inline T &instance(Args &&... args) 37 | { 38 | if (!_instance) 39 | make(std::forward(args)...); 40 | return *_instance; 41 | } 42 | 43 | private: 44 | static inline void make(Args... args) 45 | { 46 | if (!_instance) 47 | _instance = new (std::nothrow) T(std::forward(args)...); 48 | } 49 | 50 | static inline void reset() 51 | { 52 | if (_instance) 53 | { 54 | delete _instance; 55 | _instance = NULL; 56 | } 57 | } 58 | 59 | private: 60 | static T *_instance; 61 | }; 62 | 63 | template 64 | T * singleton::_instance = NULL; 65 | 66 | #endif //_SINGLETON_H_ 67 | -------------------------------------------------------------------------------- /arm9/source/common/stringtool.cpp: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------- 2 | Copyright (C) 2007 Acekard, www.acekard.com 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in 10 | all copies or substantial portions of the Software. 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | ---------------------------------------------------------------------------------*/ 19 | 20 | #include "stringtool.h" 21 | #include 22 | #include 23 | #include 24 | 25 | std::string formatString( const char* fmt, ... ) 26 | { 27 | const char * f = fmt; 28 | va_list argList; 29 | va_start(argList, fmt); 30 | char * ptempStr = NULL; 31 | size_t max_len = vasiprintf( &ptempStr, f, argList); 32 | std::string str( ptempStr ); 33 | str.resize( max_len ); 34 | free( ptempStr ); 35 | va_end(argList); 36 | return str; 37 | } 38 | -------------------------------------------------------------------------------- /arm9/source/common/stringtool.h: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------- 2 | Copyright (C) 2007 Acekard, www.acekard.com 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | The above copyright notice and this permission notice shall be included in 10 | all copies or substantial portions of the Software. 11 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 12 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 13 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 14 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 15 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 16 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 17 | THE SOFTWARE. 18 | ---------------------------------------------------------------------------------*/ 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | #ifndef _STRINGTOOL_H_ 29 | #define _STRINGTOOL_H_ 30 | 31 | #include 32 | 33 | std::string formatString( const char* fmt, ... ); 34 | 35 | 36 | 37 | #endif//_STRINGTOOL_H_ 38 | -------------------------------------------------------------------------------- /arm9/source/common/systemdetails.cpp: -------------------------------------------------------------------------------- 1 | #include "systemdetails.h" 2 | 3 | SystemDetails::SystemDetails() 4 | { 5 | 6 | _isRegularDS = true; 7 | 8 | fifoWaitValue32(FIFO_USER_06); 9 | if (fifoGetValue32(FIFO_USER_03) == 0) 10 | _arm7SCFGLocked = true; // If ButtonBoot4R4 is being run from flashcard, then arm7 SCFG is locked. 11 | 12 | u16 arm7_SNDEXCNT = fifoGetValue32(FIFO_USER_07); 13 | if (arm7_SNDEXCNT != 0) 14 | { 15 | _isRegularDS = false; // If sound frequency setting is found, then the console is not a DS Phat/Lite 16 | } 17 | 18 | // Restore value. 19 | fifoSendValue32(FIFO_USER_07, arm7_SNDEXCNT); 20 | } 21 | -------------------------------------------------------------------------------- /arm9/source/common/systemdetails.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | #ifndef __SYSTEM_DETAILS__ 3 | #define __SYSTEM_DETAILS__ 4 | #include "singleton.h" 5 | #include 6 | #include 7 | #include 8 | 9 | class SystemDetails 10 | { 11 | public: 12 | SystemDetails(); 13 | ~SystemDetails() {} 14 | 15 | public: 16 | bool arm7SCFGLocked() { return _arm7SCFGLocked; } 17 | bool flashcardUsed() 18 | { 19 | if (_flashcardUsed) 20 | return _flashcardUsed; 21 | if (!access("fat:/", F_OK)) 22 | { 23 | _flashcardUsed = true; 24 | } 25 | 26 | return _flashcardUsed; 27 | } 28 | bool isRegularDS() { return _isRegularDS; } 29 | bool fatInitOk() { return _fatInitOk; } 30 | bool useNitroFS() { return _nitroFsInitOk; } 31 | void initFilesystem(const char *runningPath = NULL); 32 | 33 | private: 34 | bool _arm7SCFGLocked; 35 | bool _flashcardUsed; 36 | bool _isRegularDS; 37 | bool _fatInitOk; 38 | bool _nitroFsInitOk; 39 | }; 40 | 41 | typedef singleton systemDetails_s; 42 | 43 | inline SystemDetails &sys() { return systemDetails_s::instance(); } 44 | #endif -------------------------------------------------------------------------------- /arm9/source/main.cpp: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | Copyright (C) 2005 - 2013 3 | Michael "Chishm" Chisholm 4 | Dave "WinterMute" Murphy 5 | Claudio "sverx" 6 | This program is free software; you can redistribute it and/or 7 | modify it under the terms of the GNU General Public License 8 | as published by the Free Software Foundation; either version 2 9 | of the License, or (at your option) any later version. 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | You should have received a copy of the GNU General Public License 15 | along with this program; if not, write to the Free Software 16 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 17 | ------------------------------------------------------------------*/ 18 | #include 19 | #include 20 | #include 21 | #include 22 | #include 23 | #include 24 | #include 25 | #include "common/nds_loader_arm9.h" 26 | #include "common/inifile.h" 27 | //--------------------------------------------------------------------------------- 28 | void stop (void) { 29 | //--------------------------------------------------------------------------------- 30 | while (1) { 31 | swiWaitForVBlank(); 32 | } 33 | } 34 | 35 | //--------------------------------------------------------------------------------- 36 | void bootApp (std::string bruh) { 37 | //--------------------------------------------------------------------------------- 38 | if((access(bruh.c_str(), F_OK) == 0)) { 39 | const char *argarray[] = {bruh.c_str()}; 40 | int err = runNdsFile(argarray[0], 1, argarray, false); 41 | iprintf("oof: Error %i\n", err); 42 | stop(); 43 | } else { 44 | printf("oof: %s not found", bruh.c_str()); 45 | stop(); 46 | } 47 | } 48 | 49 | //--------------------------------------------------------------------------------- 50 | int main(int argc, char **argv) { 51 | //--------------------------------------------------------------------------------- 52 | std::string bootA = "/_nds/extras/bootA.nds"; 53 | std::string bootB = "/_nds/extras/bootB.nds"; 54 | std::string bootX = "/_nds/extras/bootX.nds"; 55 | std::string bootY = "/_nds/extras/bootY.nds"; 56 | std::string bootL = "/_nds/extras/bootL.nds"; 57 | std::string bootR = "/_nds/extras/bootR.nds"; 58 | std::string bootDown = "/_nds/extras/bootDown.nds"; 59 | std::string bootUp = "/_nds/extras/bootUp.nds"; 60 | std::string bootLeft = "/_nds/extras/bootLeft.nds"; 61 | std::string bootRight = "/_nds/extras/bootRight.nds"; 62 | std::string bootStart = "/_nds/extras/bootStart.nds"; 63 | std::string bootSelect = "/_nds/extras/bootSelect.nds"; 64 | std::string bootTouch = "/_nds/extras/bootTouch.nds"; 65 | std::string bootDefault = "/boot.nds"; 66 | 67 | videoSetMode(MODE_0_2D); 68 | videoSetModeSub(MODE_0_2D); 69 | vramSetBankH(VRAM_H_SUB_BG); 70 | consoleInit(NULL, 1, BgType_Text4bpp, BgSize_T_256x256, 15, 0, false, true); 71 | 72 | if (!fatInitDefault()) { 73 | iprintf ("fatInitDefault failed!\n"); 74 | stop(); 75 | } 76 | CIniFile ini("/_nds/extras/ButtonBoot.ini"); 77 | 78 | bootA = ini.GetString("BUTTONBOOT", "BOOT_A_PATH", bootA); 79 | bootB = ini.GetString("BUTTONBOOT", "BOOT_B_PATH", bootB); 80 | bootX = ini.GetString("BUTTONBOOT", "BOOT_X_PATH", bootX); 81 | bootY = ini.GetString("BUTTONBOOT", "BOOT_Y_PATH", bootY); 82 | bootL = ini.GetString("BUTTONBOOT", "BOOT_L_PATH", bootL); 83 | bootR = ini.GetString("BUTTONBOOT", "BOOT_R_PATH", bootR); 84 | bootDown = ini.GetString("BUTTONBOOT", "BOOT_DOWN_PATH", bootDown); 85 | bootUp = ini.GetString("BUTTONBOOT", "BOOT_UP_PATH", bootUp); 86 | bootLeft = ini.GetString("BUTTONBOOT", "BOOT_LEFT_PATH", bootLeft); 87 | bootRight = ini.GetString("BUTTONBOOT", "BOOT_RIGHT_PATH", bootRight); 88 | bootStart = ini.GetString("BUTTONBOOT", "BOOT_START_PATH", bootStart); 89 | bootSelect = ini.GetString("BUTTONBOOT", "BOOT_SELECT_PATH", bootSelect); 90 | bootTouch = ini.GetString("BUTTONBOOT", "BOOT_TOUCH_PATH", bootTouch); 91 | bootDefault = ini.GetString("BUTTONBOOT", "BOOT_DEFAULT_PATH", bootDefault); 92 | 93 | ini.SetString("BUTTONBOOT", "BOOT_A_PATH", bootA); 94 | ini.SetString("BUTTONBOOT", "BOOT_B_PATH", bootB); 95 | ini.SetString("BUTTONBOOT", "BOOT_X_PATH", bootX); 96 | ini.SetString("BUTTONBOOT", "BOOT_Y_PATH", bootY); 97 | ini.SetString("BUTTONBOOT", "BOOT_L_PATH", bootL); 98 | ini.SetString("BUTTONBOOT", "BOOT_R_PATH", bootR); 99 | ini.SetString("BUTTONBOOT", "BOOT_DOWN_PATH", bootDown); 100 | ini.SetString("BUTTONBOOT", "BOOT_UP_PATH", bootUp); 101 | ini.SetString("BUTTONBOOT", "BOOT_LEFT_PATH", bootLeft); 102 | ini.SetString("BUTTONBOOT", "BOOT_RIGHT_PATH", bootRight); 103 | ini.SetString("BUTTONBOOT", "BOOT_START_PATH", bootStart); 104 | ini.SetString("BUTTONBOOT", "BOOT_SELECT_PATH", bootSelect); 105 | ini.SetString("BUTTONBOOT", "BOOT_DEFAULT_PATH", bootDefault); 106 | 107 | mkdir("/_nds/",0777); 108 | mkdir("/_nds/extras/",0777); 109 | ini.SaveIniFile("/_nds/extras/ButtonBoot.ini"); 110 | 111 | scanKeys(); 112 | int pressed = keysHeld(); 113 | 114 | if (pressed & KEY_A) { 115 | bootApp(bootA); 116 | } else if (pressed & KEY_B) { 117 | bootApp(bootB); 118 | } else if (pressed & KEY_X) { 119 | bootApp(bootX); 120 | } else if (pressed & KEY_Y) { 121 | bootApp(bootY); 122 | } else if (pressed & KEY_R) { 123 | bootApp(bootR); 124 | } else if (pressed & KEY_L) { 125 | bootApp(bootL); 126 | } else if (pressed & KEY_RIGHT) { 127 | bootApp(bootRight); 128 | } else if (pressed & KEY_LEFT) { 129 | bootApp(bootLeft); 130 | } else if (pressed & KEY_DOWN) { 131 | bootApp(bootDown); 132 | } else if (pressed & KEY_UP) { 133 | bootApp(bootUp); 134 | } else if (pressed & KEY_START) { 135 | bootApp(bootStart); 136 | } else if (pressed & KEY_SELECT) { 137 | bootApp(bootSelect); 138 | } else if (pressed & KEY_TOUCH) { 139 | bootApp(bootTouch); 140 | } else { 141 | bootApp(bootDefault); 142 | } 143 | } 144 | -------------------------------------------------------------------------------- /bootloader/Makefile: -------------------------------------------------------------------------------- 1 | #--------------------------------------------------------------------------------- 2 | .SUFFIXES: 3 | #--------------------------------------------------------------------------------- 4 | ifeq ($(strip $(DEVKITARM)),) 5 | $(error "Please set DEVKITARM in your environment. export DEVKITARM=devkitARM) 6 | endif 7 | 8 | -include $(DEVKITARM)/ds_rules 9 | 10 | #--------------------------------------------------------------------------------- 11 | # BUILD is the directory where object files & intermediate files will be placed 12 | # SOURCES is a list of directories containing source code 13 | # INCLUDES is a list of directories containing extra header files 14 | #--------------------------------------------------------------------------------- 15 | TARGET := load 16 | BUILD ?= build 17 | SOURCES := source source/patches 18 | INCLUDES := build 19 | SPECS := specs 20 | 21 | #--------------------------------------------------------------------------------- 22 | # options for code generation 23 | #--------------------------------------------------------------------------------- 24 | ARCH := -mthumb -mthumb-interwork 25 | 26 | CFLAGS := -g -Wall -Os\ 27 | -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer\ 28 | -ffast-math \ 29 | $(ARCH) 30 | 31 | CFLAGS += $(INCLUDE) $(EXTRA_CFLAGS) -DARM7 32 | 33 | ASFLAGS := -g $(ARCH) $(EXTRA_CFLAGS) $(INCLUDE) 34 | LDFLAGS = -nostartfiles -T $(TOPDIR)/load.ld -g $(ARCH) -Wl,-Map,$(TARGET).map 35 | 36 | LIBS := 37 | 38 | #--------------------------------------------------------------------------------- 39 | # list of directories containing libraries, this must be the top level containing 40 | # include and lib 41 | #--------------------------------------------------------------------------------- 42 | LIBDIRS := $(LIBNDS) 43 | 44 | 45 | #--------------------------------------------------------------------------------- 46 | # no real need to edit anything past this point unless you need to add additional 47 | # rules for different file extensions 48 | #--------------------------------------------------------------------------------- 49 | ifneq ($(BUILD),$(notdir $(CURDIR))) 50 | #--------------------------------------------------------------------------------- 51 | 52 | export TOPDIR := $(CURDIR) 53 | export LOADBIN := $(CURDIR)/../data/$(TARGET).bin 54 | export LOADELF := $(CURDIR)/$(TARGET).elf 55 | export DEPSDIR := $(CURDIR)/$(BUILD) 56 | 57 | export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) 58 | 59 | export CC := $(PREFIX)gcc 60 | export CXX := $(PREFIX)g++ 61 | export AR := $(PREFIX)ar 62 | export OBJCOPY := $(PREFIX)objcopy 63 | 64 | CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c))) 65 | CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp))) 66 | SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s))) 67 | 68 | export OFILES := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o) 69 | 70 | export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \ 71 | $(foreach dir,$(LIBDIRS),-I$(dir)/include) \ 72 | -I$(CURDIR)/$(BUILD) 73 | 74 | export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib) 75 | 76 | #--------------------------------------------------------------------------------- 77 | # use CC for linking standard C 78 | #--------------------------------------------------------------------------------- 79 | export LD := $(CC) 80 | #--------------------------------------------------------------------------------- 81 | 82 | .PHONY: $(BUILD) clean 83 | 84 | #--------------------------------------------------------------------------------- 85 | $(BUILD): 86 | @[ -d $@ ] || mkdir -p $@ 87 | @$(MAKE) -C $(BUILD) -f $(CURDIR)/Makefile 88 | 89 | #--------------------------------------------------------------------------------- 90 | clean: 91 | @echo clean ... 92 | @rm -fr $(BUILD) *.elf *.bin 93 | 94 | 95 | #--------------------------------------------------------------------------------- 96 | else 97 | 98 | DEPENDS := $(OFILES:.o=.d) 99 | 100 | #--------------------------------------------------------------------------------- 101 | # main targets 102 | #--------------------------------------------------------------------------------- 103 | $(LOADBIN) : $(LOADELF) 104 | @$(OBJCOPY) -O binary $< $@ 105 | @echo built ... $(notdir $@) 106 | 107 | 108 | $(LOADELF) : $(OFILES) 109 | @echo linking $(notdir $@) 110 | @$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@ 111 | 112 | arm9mpu_reset.o: mpu_reset.bin 113 | 114 | mpu_reset.bin: mpu_reset.elf 115 | $(OBJCOPY) -O binary $< $@ 116 | 117 | mpu_reset.elf: $(TOPDIR)/arm9code/mpu_reset.s 118 | $(CC) $(ASFLAGS) -Ttext=0 -x assembler-with-cpp -nostartfiles -nostdlib $< -o $@ 119 | 120 | -include $(DEPENDS) 121 | #--------------------------------------------------------------------------------------- 122 | endif 123 | #--------------------------------------------------------------------------------------- -------------------------------------------------------------------------------- /bootloader/arm9code/mpu_reset.s: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2006 - 2015 Dave Murphy (WinterMute) 3 | 4 | This program is free software: you can redistribute it and/or modify 5 | it under the terms of the GNU General Public License as published by 6 | the Free Software Foundation, either version 2 of the License, or 7 | (at your option) any later version. 8 | 9 | This program is distributed in the hope that it will be useful, 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | GNU General Public License for more details. 13 | 14 | You should have received a copy of the GNU General Public License 15 | along with this program. If not, see . 16 | 17 | */ 18 | 19 | #include 20 | 21 | .text 22 | .align 4 23 | 24 | .arm 25 | 26 | .arch armv5te 27 | .cpu arm946e-s 28 | 29 | @--------------------------------------------------------------------------------- 30 | .global _start 31 | .type _start STT_FUNC 32 | @--------------------------------------------------------------------------------- 33 | _start: 34 | @--------------------------------------------------------------------------------- 35 | @ Switch off MPU 36 | mrc p15, 0, r0, c1, c0, 0 37 | bic r0, r0, #PROTECT_ENABLE 38 | mcr p15, 0, r0, c1, c0, 0 39 | 40 | 41 | adr r12, mpu_initial_data 42 | ldmia r12, {r0-r10} 43 | 44 | mcr p15, 0, r0, c2, c0, 0 45 | mcr p15, 0, r0, c2, c0, 1 46 | mcr p15, 0, r1, c3, c0, 0 47 | mcr p15, 0, r2, c5, c0, 2 48 | mcr p15, 0, r3, c5, c0, 3 49 | mcr p15, 0, r4, c6, c0, 0 50 | mcr p15, 0, r5, c6, c1, 0 51 | mcr p15, 0, r6, c6, c3, 0 52 | mcr p15, 0, r7, c6, c4, 0 53 | mcr p15, 0, r8, c6, c6, 0 54 | mcr p15, 0, r9, c6, c7, 0 55 | mcr p15, 0, r10, c9, c1, 0 56 | 57 | mov r0, #0 58 | mcr p15, 0, r0, c6, c2, 0 @ PU Protection Unit Data/Unified Region 2 59 | mcr p15, 0, r0, c6, c5, 0 @ PU Protection Unit Data/Unified Region 5 60 | 61 | mrc p15, 0, r0, c9, c1, 0 @ DTCM 62 | mov r0, r0, lsr #12 @ base 63 | mov r0, r0, lsl #12 @ size 64 | add r0, r0, #0x4000 @ dtcm top 65 | 66 | sub r0, r0, #4 @ irq vector 67 | mov r1, #0 68 | str r1, [r0] 69 | sub r0, r0, #4 @ IRQ1 Check Bits 70 | str r1, [r0] 71 | 72 | sub r0, r0, #128 73 | bic r0, r0, #7 74 | 75 | msr cpsr_c, #0xd3 @ svc mode 76 | mov sp, r0 77 | sub r0, r0, #128 78 | msr cpsr_c, #0xd2 @ irq mode 79 | mov sp, r0 80 | sub r0, r0, #128 81 | msr cpsr_c, #0xdf @ system mode 82 | mov sp, r0 83 | 84 | @ enable cache & tcm 85 | mrc p15, 0, r0, c1, c0, 0 86 | ldr r1,= ITCM_ENABLE | DTCM_ENABLE | ICACHE_ENABLE | DCACHE_ENABLE 87 | orr r0,r0,r1 88 | mcr p15, 0, r0, c1, c0, 0 89 | 90 | ldr r10, =0x2FFFE04 91 | ldr r0, =0xE59FF018 92 | str r0, [r10] 93 | add r1, r10, #0x20 94 | str r10, [r1] 95 | bx r10 96 | 97 | .pool 98 | 99 | mpu_initial_data: 100 | .word 0x00000042 @ p15,0,c2,c0,0..1,r0 ;PU Cachability Bits for Data/Unified+Instruction Protection Region 101 | .word 0x00000002 @ p15,0,c3,c0,0,r1 ;PU Write-Bufferability Bits for Data Protection Regions 102 | .word 0x15111011 @ p15,0,c5,c0,2,r2 ;PU Extended Access Permission Data/Unified Protection Region 103 | .word 0x05100011 @ p15,0,c5,c0,3,r3 ;PU Extended Access Permission Instruction Protection Region 104 | .word 0x04000033 @ p15,0,c6,c0,0,r4 ;PU Protection Unit Data/Unified Region 0 105 | .word 0x0200002b @ p15,0,c6,c1,0,r5 ;PU Protection Unit Data/Unified Region 1 4MB 106 | .word 0x08000035 @ p15,0,c6,c3,0,r6 ;PU Protection Unit Data/Unified Region 3 107 | .word 0x0300001b @ p15,0,c6,c4,0,r7 ;PU Protection Unit Data/Unified Region 4 108 | .word 0xffff001d @ p15,0,c6,c6,0,r8 ;PU Protection Unit Data/Unified Region 6 109 | .word 0x02fff017 @ p15,0,c6,c7,0,r9 ;PU Protection Unit Data/Unified Region 7 4KB 110 | .word 0x0300000a @ p15,0,c9,c1,0,r10 ;TCM Data TCM Base and Virtual Size 111 | -------------------------------------------------------------------------------- /bootloader/load.ld: -------------------------------------------------------------------------------- 1 | OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm") 2 | OUTPUT_ARCH(arm) 3 | ENTRY(_start) 4 | 5 | MEMORY { 6 | 7 | vram : ORIGIN = 0x06000000, LENGTH = 128K 8 | } 9 | 10 | __vram_start = ORIGIN(vram); 11 | __vram_top = ORIGIN(vram)+ LENGTH(vram); 12 | __sp_irq = __vram_top - 0x60; 13 | __sp_svc = __sp_irq - 0x100; 14 | __sp_usr = __sp_svc - 0x100; 15 | 16 | __irq_flags = __vram_top - 8; 17 | __irq_vector = __vram_top - 4; 18 | 19 | SECTIONS 20 | { 21 | .init : 22 | { 23 | __text_start = . ; 24 | KEEP (*(.init)) 25 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 26 | } >vram = 0xff 27 | 28 | .plt : 29 | { 30 | *(.plt) 31 | } >vram = 0xff 32 | 33 | .text : /* ALIGN (4): */ 34 | { 35 | 36 | *(.text*) 37 | *(.stub) 38 | /* .gnu.warning sections are handled specially by elf32.em. */ 39 | *(.gnu.warning) 40 | *(.gnu.linkonce.t*) 41 | *(.glue_7) 42 | *(.glue_7t) 43 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 44 | } >vram = 0xff 45 | 46 | .fini : 47 | { 48 | KEEP (*(.fini)) 49 | } >vram =0xff 50 | 51 | __text_end = . ; 52 | 53 | .rodata : 54 | { 55 | *(.rodata) 56 | *all.rodata*(*) 57 | *(.roda) 58 | *(.rodata.*) 59 | *(.gnu.linkonce.r*) 60 | SORT(CONSTRUCTORS) 61 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 62 | } >vram = 0xff 63 | 64 | .ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >vram 65 | __exidx_start = .; 66 | .ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >vram 67 | __exidx_end = .; 68 | 69 | /* Ensure the __preinit_array_start label is properly aligned. We 70 | could instead move the label definition inside the section, but 71 | the linker would then create the section even if it turns out to 72 | be empty, which isn't pretty. */ 73 | . = ALIGN(32 / 8); 74 | PROVIDE (__preinit_array_start = .); 75 | .preinit_array : { KEEP (*(.preinit_array)) } >vram = 0xff 76 | PROVIDE (__preinit_array_end = .); 77 | PROVIDE (__init_array_start = .); 78 | .init_array : { KEEP (*(.init_array)) } >vram = 0xff 79 | PROVIDE (__init_array_end = .); 80 | PROVIDE (__fini_array_start = .); 81 | .fini_array : { KEEP (*(.fini_array)) } >vram = 0xff 82 | PROVIDE (__fini_array_end = .); 83 | 84 | .ctors : 85 | { 86 | /* gcc uses crtbegin.o to find the start of the constructors, so 87 | we make sure it is first. Because this is a wildcard, it 88 | doesn't matter if the user does not actually link against 89 | crtbegin.o; the linker won't look for a file to match a 90 | wildcard. The wildcard also means that it doesn't matter which 91 | directory crtbegin.o is in. */ 92 | KEEP (*crtbegin.o(.ctors)) 93 | KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors)) 94 | KEEP (*(SORT(.ctors.*))) 95 | KEEP (*(.ctors)) 96 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 97 | } >vram = 0xff 98 | 99 | .dtors : 100 | { 101 | KEEP (*crtbegin.o(.dtors)) 102 | KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors)) 103 | KEEP (*(SORT(.dtors.*))) 104 | KEEP (*(.dtors)) 105 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 106 | } >vram = 0xff 107 | 108 | .eh_frame : 109 | { 110 | KEEP (*(.eh_frame)) 111 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 112 | } >vram = 0xff 113 | 114 | .gcc_except_table : 115 | { 116 | *(.gcc_except_table) 117 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 118 | } >vram = 0xff 119 | .jcr : { KEEP (*(.jcr)) } >vram = 0 120 | .got : { *(.got.plt) *(.got) } >vram = 0 121 | 122 | 123 | .vram ALIGN(4) : 124 | { 125 | __vram_start = ABSOLUTE(.) ; 126 | *(.vram) 127 | *vram.*(.text) 128 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 129 | __vram_end = ABSOLUTE(.) ; 130 | } >vram = 0xff 131 | 132 | 133 | .data ALIGN(4) : { 134 | __data_start = ABSOLUTE(.); 135 | *(.data) 136 | *(.data.*) 137 | *(.gnu.linkonce.d*) 138 | CONSTRUCTORS 139 | . = ALIGN(4); 140 | __data_end = ABSOLUTE(.) ; 141 | } >vram = 0xff 142 | 143 | 144 | 145 | .bss ALIGN(4) : 146 | { 147 | __bss_start = ABSOLUTE(.); 148 | __bss_start__ = ABSOLUTE(.); 149 | *(.dynbss) 150 | *(.gnu.linkonce.b*) 151 | *(.bss*) 152 | *(COMMON) 153 | . = ALIGN(4); /* REQUIRED. LD is flaky without it. */ 154 | } >vram 155 | 156 | __bss_end = . ; 157 | __bss_end__ = . ; 158 | 159 | _end = . ; 160 | __end__ = . ; 161 | PROVIDE (end = _end); 162 | 163 | /* Stabs debugging sections. */ 164 | .stab 0 : { *(.stab) } 165 | .stabstr 0 : { *(.stabstr) } 166 | .stab.excl 0 : { *(.stab.excl) } 167 | .stab.exclstr 0 : { *(.stab.exclstr) } 168 | .stab.index 0 : { *(.stab.index) } 169 | .stab.indexstr 0 : { *(.stab.indexstr) } 170 | .comment 0 : { *(.comment) } 171 | /* DWARF debug sections. 172 | Symbols in the DWARF debugging sections are relative to the beginning 173 | of the section so we begin them at 0. */ 174 | /* DWARF 1 */ 175 | .debug 0 : { *(.debug) } 176 | .line 0 : { *(.line) } 177 | /* GNU DWARF 1 extensions */ 178 | .debug_srcinfo 0 : { *(.debug_srcinfo) } 179 | .debug_sfnames 0 : { *(.debug_sfnames) } 180 | /* DWARF 1.1 and DWARF 2 */ 181 | .debug_aranges 0 : { *(.debug_aranges) } 182 | .debug_pubnames 0 : { *(.debug_pubnames) } 183 | /* DWARF 2 */ 184 | .debug_info 0 : { *(.debug_info) } 185 | .debug_abbrev 0 : { *(.debug_abbrev) } 186 | .debug_line 0 : { *(.debug_line) } 187 | .debug_frame 0 : { *(.debug_frame) } 188 | .debug_str 0 : { *(.debug_str) } 189 | .debug_loc 0 : { *(.debug_loc) } 190 | .debug_macinfo 0 : { *(.debug_macinfo) } 191 | /* SGI/MIPS DWARF 2 extensions */ 192 | .debug_weaknames 0 : { *(.debug_weaknames) } 193 | .debug_funcnames 0 : { *(.debug_funcnames) } 194 | .debug_typenames 0 : { *(.debug_typenames) } 195 | .debug_varnames 0 : { *(.debug_varnames) } 196 | .stack 0x80000 : { _stack = .; *(.stack) } 197 | /* These must appear regardless of . */ 198 | } 199 | -------------------------------------------------------------------------------- /bootloader/source/arm7clear.s: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2005 Michael "Chishm" Chisholm 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | If you use this code, please give due credit and email me about your 20 | project at chishm@hotmail.com 21 | ------------------------------------------------------------------*/ 22 | 23 | .arm 24 | .global arm7clearRAM 25 | .type arm7clearRAM STT_FUNC 26 | arm7clearRAM: 27 | 28 | push {r0-r9} 29 | // clear exclusive IWRAM 30 | // 0380:0000 to 0380:FFFF, total 64KiB 31 | mov r0, #0 32 | mov r1, #0 33 | mov r2, #0 34 | mov r3, #0 35 | mov r4, #0 36 | mov r5, #0 37 | mov r6, #0 38 | mov r7, #0 39 | mov r8, #0x03800000 40 | sub r8, #0x00008000 41 | mov r9, #0x03800000 42 | orr r9, r9, #0x10000 43 | clear_IWRAM_loop: 44 | stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7} 45 | cmp r8, r9 46 | blt clear_IWRAM_loop 47 | 48 | // clear most of EWRAM - except after RAM end - 0xc000, which has the bootstub 49 | mov r8, #0x02000000 50 | 51 | ldr r9,=0x4004008 52 | ldr r9,[r9] 53 | ands r9,r9,#0x8000 54 | bne dsi_mode 55 | 56 | mov r9, #0x02400000 57 | b ds_mode 58 | dsi_mode: 59 | mov r9, #0x03000000 60 | ds_mode: 61 | sub r9, #0x0000c000 62 | clear_EWRAM_loop: 63 | stmia r8!, {r0, r1, r2, r3, r4, r5, r6, r7} 64 | cmp r8, r9 65 | blt clear_EWRAM_loop 66 | 67 | pop {r0-r9} 68 | 69 | bx lr 70 | 71 | -------------------------------------------------------------------------------- /bootloader/source/arm9clear.arm.c: -------------------------------------------------------------------------------- 1 | #define ARM9 2 | #undef ARM7 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | #include 11 | #include 12 | #include 13 | 14 | #include "boot.h" 15 | 16 | /*------------------------------------------------------------------------- 17 | resetMemory2_ARM9 18 | Clears the ARM9's DMA channels and resets video memory 19 | Written by Darkain. 20 | Modified by Chishm: 21 | * Changed MultiNDS specific stuff 22 | --------------------------------------------------------------------------*/ 23 | void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9 (void) 24 | { 25 | register int i; 26 | 27 | //clear out ARM9 DMA channels 28 | for (i=0; i<4; i++) { 29 | DMA_CR(i) = 0; 30 | DMA_SRC(i) = 0; 31 | DMA_DEST(i) = 0; 32 | TIMER_CR(i) = 0; 33 | TIMER_DATA(i) = 0; 34 | } 35 | 36 | VRAM_CR = (VRAM_CR & 0xffff0000) | 0x00008080 ; 37 | 38 | u16 *mainregs = (u16*)0x04000000; 39 | u16 *subregs = (u16*)0x04001000; 40 | 41 | for (i=0; i<43; i++) { 42 | mainregs[i] = 0; 43 | subregs[i] = 0; 44 | } 45 | 46 | REG_DISPSTAT = 0; 47 | 48 | VRAM_A_CR = 0; 49 | VRAM_B_CR = 0; 50 | // Don't mess with the ARM7's VRAM 51 | // VRAM_C_CR = 0; 52 | VRAM_D_CR = 0; 53 | VRAM_E_CR = 0; 54 | VRAM_F_CR = 0; 55 | VRAM_G_CR = 0; 56 | VRAM_H_CR = 0; 57 | VRAM_I_CR = 0; 58 | REG_POWERCNT = 0x820F; 59 | 60 | //set shared ram to ARM7 61 | WRAM_CR = 0x03; 62 | 63 | // Return to passme loop 64 | *((vu32*)0x02FFFE04) = (u32)0xE59FF018; // ldr pc, 0x02FFFE24 65 | *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; // Set ARM9 Loop address 66 | 67 | asm volatile( 68 | "\tbx %0\n" 69 | : : "r" (0x02FFFE04) 70 | ); 71 | while(1); 72 | } 73 | 74 | void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) clearMasterBright_ARM9 (void) 75 | { 76 | u16 mode = 1 << 14; 77 | 78 | *(u16*)(0x0400006C + (0x1000 * 0)) = 0 + mode; 79 | *(u16*)(0x0400006C + (0x1000 * 1)) = 0 + mode; 80 | 81 | // Return to passme loop 82 | *((vu32*)0x02FFFE04) = (u32)0xE59FF018; // ldr pc, 0x02FFFE24 83 | *((vu32*)0x02FFFE24) = (u32)0x02FFFE04; // Set ARM9 Loop address 84 | 85 | asm volatile( 86 | "\tbx %0\n" 87 | : : "r" (0x02FFFE04) 88 | ); 89 | while(1); 90 | } 91 | 92 | /*------------------------------------------------------------------------- 93 | startBinary_ARM9 94 | Jumps to the ARM9 NDS binary in sync with the display and ARM7 95 | Written by Darkain. 96 | Modified by Chishm: 97 | * Removed MultiNDS specific stuff 98 | --------------------------------------------------------------------------*/ 99 | void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 (void) 100 | { 101 | REG_IME=0; 102 | REG_EXMEMCNT = 0xE880; 103 | // set ARM9 load address to 0 and wait for it to change again 104 | ARM9_START_FLAG = 0; 105 | while(REG_VCOUNT!=191); 106 | while(REG_VCOUNT==191); 107 | while ( ARM9_START_FLAG != 1 ); 108 | VoidFn arm9code = *(VoidFn*)(0x2FFFE24); 109 | arm9code(); 110 | while(1); 111 | } 112 | 113 | -------------------------------------------------------------------------------- /bootloader/source/arm9mpu_reset.s: -------------------------------------------------------------------------------- 1 | .arm 2 | .global mpu_reset, mpu_reset_end 3 | 4 | mpu_reset: 5 | .incbin "mpu_reset.bin" 6 | mpu_reset_end: 7 | -------------------------------------------------------------------------------- /bootloader/source/bios.s: -------------------------------------------------------------------------------- 1 | .text 2 | .align 4 3 | 4 | .thumb 5 | 6 | @--------------------------------------------------------------------------------- 7 | .global swiDelay 8 | .thumb_func 9 | @--------------------------------------------------------------------------------- 10 | swiDelay: 11 | @--------------------------------------------------------------------------------- 12 | swi 0x03 13 | bx lr 14 | -------------------------------------------------------------------------------- /bootloader/source/boot.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | boot.c 3 | 4 | BootLoader 5 | Loads a file into memory and runs it 6 | 7 | All resetMemory and startBinary functions are based 8 | on the MultiNDS loader by Darkain. 9 | Original source available at: 10 | http://cvs.sourceforge.net/viewcvs.py/ndslib/ndslib/examples/loader/boot/main.cpp 11 | 12 | License: 13 | Copyright (C) 2005 Michael "Chishm" Chisholm 14 | 15 | This program is free software; you can redistribute it and/or 16 | modify it under the terms of the GNU General Public License 17 | as published by the Free Software Foundation; either version 2 18 | of the License, or (at your option) any later version. 19 | 20 | This program is distributed in the hope that it will be useful, 21 | but WITHOUT ANY WARRANTY; without even the implied warranty of 22 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 | GNU General Public License for more details. 24 | 25 | You should have received a copy of the GNU General Public License 26 | along with this program; if not, write to the Free Software 27 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 28 | 29 | If you use this code, please give due credit and email me about your 30 | project at chishm@hotmail.com 31 | 32 | Helpful information: 33 | This code runs from VRAM bank C on ARM7 34 | ------------------------------------------------------------------*/ 35 | 36 | #include 37 | #include 38 | #include 39 | #include 40 | #include 41 | #define ARM9 42 | #undef ARM7 43 | #include 44 | #include 45 | #include 46 | #undef ARM9 47 | #define ARM7 48 | #include 49 | #include "sdmmc.h" 50 | #include "i2c.h" 51 | #include "fat.h" 52 | #include "dldi_patcher.h" 53 | #include "card.h" 54 | #include "boot.h" 55 | 56 | void arm7clearRAM(); 57 | 58 | //+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 59 | // Important things 60 | #define TEMP_MEM 0x02FFD000 61 | #define TWL_HEAD 0x02FFE000 62 | #define NDS_HEAD 0x02FFFE00 63 | #define TEMP_ARM9_START_ADDRESS (*(vu32*)0x02FFFFF4) 64 | 65 | 66 | const char* bootName = "BOOT.NDS"; 67 | 68 | extern unsigned long _start; 69 | extern unsigned long storedFileCluster; 70 | extern unsigned long initDisc; 71 | extern unsigned long wantToPatchDLDI; 72 | extern unsigned long argStart; 73 | extern unsigned long argSize; 74 | extern unsigned long dsiSD; 75 | extern unsigned long dsiMode; 76 | extern unsigned long clearMasterBright; 77 | extern unsigned long dsMode; 78 | 79 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 80 | // Firmware stuff 81 | 82 | #define FW_READ 0x03 83 | 84 | void boot_readFirmware (uint32 address, uint8 * buffer, uint32 size) { 85 | uint32 index; 86 | 87 | // Read command 88 | while (REG_SPICNT & SPI_BUSY); 89 | REG_SPICNT = SPI_ENABLE | SPI_CONTINUOUS | SPI_DEVICE_NVRAM; 90 | REG_SPIDATA = FW_READ; 91 | while (REG_SPICNT & SPI_BUSY); 92 | 93 | // Set the address 94 | REG_SPIDATA = (address>>16) & 0xFF; 95 | while (REG_SPICNT & SPI_BUSY); 96 | REG_SPIDATA = (address>>8) & 0xFF; 97 | while (REG_SPICNT & SPI_BUSY); 98 | REG_SPIDATA = (address) & 0xFF; 99 | while (REG_SPICNT & SPI_BUSY); 100 | 101 | for (index = 0; index < size; index++) { 102 | REG_SPIDATA = 0; 103 | while (REG_SPICNT & SPI_BUSY); 104 | buffer[index] = REG_SPIDATA & 0xFF; 105 | } 106 | REG_SPICNT = 0; 107 | } 108 | 109 | 110 | static inline void copyLoop (u32* dest, const u32* src, u32 size) { 111 | size = (size +3) & ~3; 112 | do { 113 | *dest++ = *src++; 114 | } while (size -= 4); 115 | } 116 | 117 | 118 | /*------------------------------------------------------------------------- 119 | passArgs_ARM7 120 | Copies the command line arguments to the end of the ARM9 binary, 121 | then sets a flag in memory for the loaded NDS to use 122 | --------------------------------------------------------------------------*/ 123 | void passArgs_ARM7 (void) { 124 | u32 ARM9_DST = *((u32*)(NDS_HEAD + 0x028)); 125 | u32 ARM9_LEN = *((u32*)(NDS_HEAD + 0x02C)); 126 | u32* argSrc; 127 | u32* argDst; 128 | 129 | if (!argStart || !argSize) return; 130 | 131 | if ( ARM9_DST == 0 && ARM9_LEN == 0) { 132 | ARM9_DST = *((u32*)(NDS_HEAD + 0x038)); 133 | ARM9_LEN = *((u32*)(NDS_HEAD + 0x03C)); 134 | } 135 | 136 | argSrc = (u32*)(argStart + (int)&_start); 137 | 138 | argDst = (u32*)((ARM9_DST + ARM9_LEN + 3) & ~3); // Word aligned 139 | 140 | if (dsiMode && (*(u8*)(NDS_HEAD + 0x012) & BIT(1))) 141 | { 142 | u32 ARM9i_DST = *((u32*)(TWL_HEAD + 0x1C8)); 143 | u32 ARM9i_LEN = *((u32*)(TWL_HEAD + 0x1CC)); 144 | if (ARM9i_LEN) 145 | { 146 | u32* argDst2 = (u32*)((ARM9i_DST + ARM9i_LEN + 3) & ~3); // Word aligned 147 | if (argDst2 > argDst) 148 | argDst = argDst2; 149 | } 150 | } 151 | 152 | copyLoop(argDst, argSrc, argSize); 153 | 154 | __system_argv->argvMagic = ARGV_MAGIC; 155 | __system_argv->commandLine = (char*)argDst; 156 | __system_argv->length = argSize; 157 | } 158 | 159 | 160 | 161 | 162 | /*------------------------------------------------------------------------- 163 | resetMemory_ARM7 164 | Clears all of the NDS's RAM that is visible to the ARM7 165 | Written by Darkain. 166 | Modified by Chishm: 167 | * Added STMIA clear mem loop 168 | --------------------------------------------------------------------------*/ 169 | void resetMemory_ARM7 (void) 170 | { 171 | int i; 172 | u8 settings1, settings2; 173 | u32 settingsOffset = 0; 174 | 175 | REG_IME = 0; 176 | 177 | for (i=0; i<16; i++) { 178 | SCHANNEL_CR(i) = 0; 179 | SCHANNEL_TIMER(i) = 0; 180 | SCHANNEL_SOURCE(i) = 0; 181 | SCHANNEL_LENGTH(i) = 0; 182 | } 183 | 184 | REG_SOUNDCNT = 0; 185 | 186 | //clear out ARM7 DMA channels and timers 187 | for (i=0; i<4; i++) { 188 | DMA_CR(i) = 0; 189 | DMA_SRC(i) = 0; 190 | DMA_DEST(i) = 0; 191 | TIMER_CR(i) = 0; 192 | TIMER_DATA(i) = 0; 193 | } 194 | 195 | arm7clearRAM(); 196 | 197 | REG_IE = 0; 198 | REG_IF = ~0; 199 | (*(vu32*)(0x04000000-4)) = 0; //IRQ_HANDLER ARM7 version 200 | (*(vu32*)(0x04000000-8)) = ~0; //VBLANK_INTR_WAIT_FLAGS, ARM7 version 201 | REG_POWERCNT = 1; //turn off power to stuff 202 | 203 | // Get settings location 204 | boot_readFirmware((u32)0x00020, (u8*)&settingsOffset, 0x2); 205 | settingsOffset *= 8; 206 | 207 | // Reload DS Firmware settings 208 | boot_readFirmware(settingsOffset + 0x070, &settings1, 0x1); 209 | boot_readFirmware(settingsOffset + 0x170, &settings2, 0x1); 210 | 211 | if ((settings1 & 0x7F) == ((settings2+1) & 0x7F)) { 212 | boot_readFirmware(settingsOffset + 0x000, (u8*)0x02FFFC80, 0x70); 213 | } else { 214 | boot_readFirmware(settingsOffset + 0x100, (u8*)0x02FFFC80, 0x70); 215 | } 216 | 217 | ((vu32*)0x040044f0)[2] = 0x202DDD1D; 218 | ((vu32*)0x040044f0)[3] = 0xE1A00005; 219 | while((*(vu32*)0x04004400) & 0x2000000); 220 | 221 | } 222 | 223 | 224 | u32 ROM_TID; 225 | 226 | void loadBinary_ARM7 (u32 fileCluster) 227 | { 228 | u32 ndsHeader[0x170>>2]; 229 | 230 | // read NDS header 231 | fileRead ((char*)ndsHeader, fileCluster, 0, 0x170); 232 | // read ARM9 info from NDS header 233 | u32 ARM9_SRC = ndsHeader[0x020>>2]; 234 | char* ARM9_DST = (char*)ndsHeader[0x028>>2]; 235 | u32 ARM9_LEN = ndsHeader[0x02C>>2]; 236 | // read ARM7 info from NDS header 237 | u32 ARM7_SRC = ndsHeader[0x030>>2]; 238 | char* ARM7_DST = (char*)ndsHeader[0x038>>2]; 239 | u32 ARM7_LEN = ndsHeader[0x03C>>2]; 240 | 241 | ROM_TID = ndsHeader[0x00C>>2]; 242 | 243 | // Load binaries into memory 244 | fileRead(ARM9_DST, fileCluster, ARM9_SRC, ARM9_LEN); 245 | fileRead(ARM7_DST, fileCluster, ARM7_SRC, ARM7_LEN); 246 | 247 | // first copy the header to its proper location, excluding 248 | // the ARM9 start address, so as not to start it 249 | TEMP_ARM9_START_ADDRESS = ndsHeader[0x024>>2]; // Store for later 250 | ndsHeader[0x024>>2] = 0; 251 | dmaCopyWords(3, (void*)ndsHeader, (void*)NDS_HEAD, 0x170); 252 | 253 | if (!dsMode && dsiMode && (ndsHeader[0x10>>2]&BIT(16+1))) 254 | { 255 | // Read full TWL header 256 | fileRead((char*)TWL_HEAD, fileCluster, 0, 0x1000); 257 | 258 | if (REG_SCFG_EXT != 0) { 259 | *(u8*)(TWL_HEAD+0x1BF) = 0x00; // Tell homebrew to use NTR touch 260 | } else { 261 | *(u8*)(TWL_HEAD+0x1BF) = 0x01; // TWL touch, if in DSiWarehax 262 | } 263 | 264 | u32 ARM9i_SRC = *(u32*)(TWL_HEAD+0x1C0); 265 | char* ARM9i_DST = (char*)*(u32*)(TWL_HEAD+0x1C8); 266 | u32 ARM9i_LEN = *(u32*)(TWL_HEAD+0x1CC); 267 | u32 ARM7i_SRC = *(u32*)(TWL_HEAD+0x1D0); 268 | char* ARM7i_DST = (char*)*(u32*)(TWL_HEAD+0x1D8); 269 | u32 ARM7i_LEN = *(u32*)(TWL_HEAD+0x1DC); 270 | 271 | if (ARM9i_LEN) 272 | fileRead(ARM9i_DST, fileCluster, ARM9i_SRC, ARM9i_LEN); 273 | if (ARM7i_LEN) 274 | fileRead(ARM7i_DST, fileCluster, ARM7i_SRC, ARM7i_LEN); 275 | } 276 | } 277 | 278 | /*------------------------------------------------------------------------- 279 | startBinary_ARM7 280 | Jumps to the ARM7 NDS binary in sync with the display and ARM9 281 | Written by Darkain. 282 | Modified by Chishm: 283 | * Removed MultiNDS specific stuff 284 | --------------------------------------------------------------------------*/ 285 | void startBinary_ARM7 (void) { 286 | REG_IME=0; 287 | while(REG_VCOUNT!=191); 288 | while(REG_VCOUNT==191); 289 | // copy NDS ARM9 start address into the header, starting ARM9 290 | *((vu32*)0x02FFFE24) = TEMP_ARM9_START_ADDRESS; 291 | ARM9_START_FLAG = 1; 292 | // Start ARM7 293 | VoidFn arm7code = *(VoidFn*)(0x2FFFE34); 294 | arm7code(); 295 | } 296 | #ifndef NO_SDMMC 297 | int sdmmc_sd_readsectors(u32 sector_no, u32 numsectors, void *out); 298 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 299 | // Main function 300 | bool sdmmc_inserted() { 301 | return true; 302 | } 303 | 304 | bool sdmmc_startup() { 305 | sdmmc_controller_init(true); 306 | return sdmmc_sdcard_init() == 0; 307 | } 308 | 309 | bool sdmmc_readsectors(u32 sector_no, u32 numsectors, void *out) { 310 | return sdmmc_sdcard_readsectors(sector_no, numsectors, out) == 0; 311 | } 312 | #endif 313 | void mpu_reset(); 314 | void mpu_reset_end(); 315 | 316 | int main (void) { 317 | #ifdef NO_DLDI 318 | dsiSD = true; 319 | dsiMode = true; 320 | #endif 321 | #ifndef NO_SDMMC 322 | if (dsiSD && dsiMode) { 323 | _io_dldi.fn_readSectors = sdmmc_readsectors; 324 | _io_dldi.fn_isInserted = sdmmc_inserted; 325 | _io_dldi.fn_startup = sdmmc_startup; 326 | } 327 | #endif 328 | u32 fileCluster = storedFileCluster; 329 | // Init card 330 | if(!FAT_InitFiles(initDisc)) 331 | { 332 | return -1; 333 | } 334 | if ((fileCluster < CLUSTER_FIRST) || (fileCluster >= CLUSTER_EOF)) /* Invalid file cluster specified */ 335 | { 336 | fileCluster = getBootFileCluster(bootName); 337 | } 338 | if (fileCluster == CLUSTER_FREE) 339 | { 340 | return -1; 341 | } 342 | 343 | // ARM9 clears its memory part 2 344 | // copy ARM9 function to RAM, and make the ARM9 jump to it 345 | copyLoop((void*)TEMP_MEM, (void*)resetMemory2_ARM9, resetMemory2_ARM9_size); 346 | (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function 347 | // Wait until the ARM9 has completed its task 348 | while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); 349 | 350 | if (clearMasterBright) { 351 | // ARM9 clears master brightness 352 | // copy ARM9 function to RAM, and make the ARM9 jump to it 353 | copyLoop((void*)TEMP_MEM, (void*)clearMasterBright_ARM9, clearMasterBright_ARM9_size); 354 | (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function 355 | // Wait until the ARM9 has completed its task 356 | while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); 357 | } 358 | 359 | // ARM9 sets up mpu 360 | // copy ARM9 function to RAM, and make the ARM9 jump to it 361 | copyLoop((void*)TEMP_MEM, (void*)mpu_reset, mpu_reset_end - mpu_reset); 362 | (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function 363 | // Wait until the ARM9 has completed its task 364 | while ((*(vu32*)0x02FFFE24) == (u32)TEMP_MEM); 365 | 366 | // Get ARM7 to clear RAM 367 | resetMemory_ARM7(); 368 | 369 | // ARM9 enters a wait loop 370 | // copy ARM9 function to RAM, and make the ARM9 jump to it 371 | copyLoop((void*)TEMP_MEM, (void*)startBinary_ARM9, startBinary_ARM9_size); 372 | (*(vu32*)0x02FFFE24) = (u32)TEMP_MEM; // Make ARM9 jump to the function 373 | 374 | // Load the NDS file 375 | loadBinary_ARM7(fileCluster); 376 | 377 | // Fix for Pictochat and DLP 378 | if (ROM_TID == 0x41444E48 || ROM_TID == 0x41454E48) { 379 | (*(vu16*)0x02FFFCFA) = 0x1041; // NoCash: channel ch1+7+13 380 | } 381 | 382 | if (dsMode) { 383 | i2cWriteRegister(I2C_PM, I2CREGPM_MMCPWR, 0); // Press power button for auto-reset 384 | i2cWriteRegister(I2C_PM, I2CREGPM_RESETFLAG, 1); // Bootflag = Warmboot/SkipHealthSafety 385 | if (REG_SCFG_EXT != 0) { 386 | REG_SCFG_ROM = 0x703; // NTR BIOS 387 | REG_SCFG_EXT = 0x12A03000; 388 | } 389 | } 390 | 391 | #ifndef NO_DLDI 392 | // Patch with DLDI if desired 393 | if (wantToPatchDLDI) { 394 | dldiPatchBinary ((u8*)((u32*)NDS_HEAD)[0x0A], ((u32*)NDS_HEAD)[0x0B]); 395 | } 396 | #endif 397 | 398 | #ifndef NO_SDMMC 399 | if (dsiSD && !dsMode && dsiMode) { 400 | sdmmc_controller_init(true); 401 | } 402 | #endif 403 | // Pass command line arguments to loaded program 404 | passArgs_ARM7(); 405 | 406 | startBinary_ARM7(); 407 | 408 | return 0; 409 | } 410 | 411 | -------------------------------------------------------------------------------- /bootloader/source/boot.h: -------------------------------------------------------------------------------- 1 | #ifndef _BOOT_H_ 2 | #define _BOOT_H_ 3 | 4 | #define resetMemory2_ARM9_size 0x400 5 | void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) resetMemory2_ARM9(); 6 | #define clearMasterBright_ARM9_size 0x200 7 | void __attribute__ ((long_call)) __attribute__((naked)) __attribute__((noreturn)) clearMasterBright_ARM9(); 8 | #define startBinary_ARM9_size 0x100 9 | void __attribute__ ((long_call)) __attribute__((noreturn)) __attribute__((naked)) startBinary_ARM9 (); 10 | #define ARM9_START_FLAG (*(vu8*)0x02FFFDFB) 11 | 12 | #endif // _BOOT_H_ 13 | -------------------------------------------------------------------------------- /bootloader/source/card.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2005 Michael "Chishm" Chisholm 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | If you use this code, please give due credit and email me about your 20 | project at chishm@hotmail.com 21 | ------------------------------------------------------------------*/ 22 | 23 | #ifndef CARD_H 24 | #define CARD_H 25 | 26 | #include "disc_io.h" 27 | #include "io_dldi.h" 28 | 29 | static inline bool CARD_StartUp (void) { 30 | return _io_dldi.fn_startup(); 31 | } 32 | 33 | static inline bool CARD_IsInserted (void) { 34 | return _io_dldi.fn_isInserted(); 35 | } 36 | 37 | static inline bool CARD_ReadSector (u32 sector, void *buffer) { 38 | return _io_dldi.fn_readSectors(sector, 1, buffer); 39 | } 40 | 41 | static inline bool CARD_ReadSectors (u32 sector, int count, void *buffer) { 42 | return _io_dldi.fn_readSectors(sector, count, buffer); 43 | } 44 | 45 | #endif // CARD_H 46 | -------------------------------------------------------------------------------- /bootloader/source/disc_io.h: -------------------------------------------------------------------------------- 1 | /* 2 | disc_io.h 3 | Interface template for low level disc functions. 4 | 5 | Copyright (c) 2006 Michael "Chishm" Chisholm 6 | 7 | Redistribution and use in source and binary forms, with or without modification, 8 | are permitted provided that the following conditions are met: 9 | 10 | 1. Redistributions of source code must retain the above copyright notice, 11 | this list of conditions and the following disclaimer. 12 | 2. Redistributions in binary form must reproduce the above copyright notice, 13 | this list of conditions and the following disclaimer in the documentation and/or 14 | other materials provided with the distribution. 15 | 3. The name of the author may not be used to endorse or promote products derived 16 | from this software without specific prior written permission. 17 | 18 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 19 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 20 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 21 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 23 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 26 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 | 28 | 2006-07-11 - Chishm 29 | * Original release 30 | 31 | 2006-07-16 - Chishm 32 | * Renamed _CF_USE_DMA to _IO_USE_DMA 33 | * Renamed _CF_ALLOW_UNALIGNED to _IO_ALLOW_UNALIGNED 34 | */ 35 | 36 | #ifndef _DISC_IO_H 37 | #define _DISC_IO_H 38 | 39 | #include 40 | #define BYTES_PER_SECTOR 512 41 | 42 | //---------------------------------------------------------------------- 43 | // Customisable features 44 | 45 | // Use DMA to read the card, remove this line to use normal reads/writes 46 | // #define _IO_USE_DMA 47 | 48 | // Allow buffers not alligned to 16 bits when reading files. 49 | // Note that this will slow down access speed, so only use if you have to. 50 | // It is also incompatible with DMA 51 | #define _IO_ALLOW_UNALIGNED 52 | 53 | #if defined _IO_USE_DMA && defined _IO_ALLOW_UNALIGNED 54 | #error "You can't use both DMA and unaligned memory" 55 | #endif 56 | 57 | #define FEATURE_MEDIUM_CANREAD 0x00000001 58 | #define FEATURE_MEDIUM_CANWRITE 0x00000002 59 | #define FEATURE_SLOT_GBA 0x00000010 60 | #define FEATURE_SLOT_NDS 0x00000020 61 | 62 | typedef bool (* FN_MEDIUM_STARTUP)(void) ; 63 | typedef bool (* FN_MEDIUM_ISINSERTED)(void) ; 64 | typedef bool (* FN_MEDIUM_READSECTORS)(u32 sector, u32 numSectors, void* buffer) ; 65 | typedef bool (* FN_MEDIUM_WRITESECTORS)(u32 sector, u32 numSectors, const void* buffer) ; 66 | typedef bool (* FN_MEDIUM_CLEARSTATUS)(void) ; 67 | typedef bool (* FN_MEDIUM_SHUTDOWN)(void) ; 68 | 69 | struct IO_INTERFACE_STRUCT { 70 | unsigned long ioType ; 71 | unsigned long features ; 72 | FN_MEDIUM_STARTUP fn_startup ; 73 | FN_MEDIUM_ISINSERTED fn_isInserted ; 74 | FN_MEDIUM_READSECTORS fn_readSectors ; 75 | FN_MEDIUM_WRITESECTORS fn_writeSectors ; 76 | FN_MEDIUM_CLEARSTATUS fn_clearStatus ; 77 | FN_MEDIUM_SHUTDOWN fn_shutdown ; 78 | } ; 79 | 80 | typedef struct IO_INTERFACE_STRUCT IO_INTERFACE ; 81 | 82 | #endif // define _DISC_IO_H 83 | -------------------------------------------------------------------------------- /bootloader/source/dldi_patcher.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2005 Michael "Chishm" Chisholm 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | If you use this code, please give due credit and email me about your 20 | project at chishm@hotmail.com 21 | ------------------------------------------------------------------*/ 22 | #ifndef NO_DLDI 23 | #include 24 | #include 25 | #include "dldi_patcher.h" 26 | 27 | #define FIX_ALL 0x01 28 | #define FIX_GLUE 0x02 29 | #define FIX_GOT 0x04 30 | #define FIX_BSS 0x08 31 | 32 | enum DldiOffsets { 33 | DO_magicString = 0x00, // "\xED\xA5\x8D\xBF Chishm" 34 | DO_magicToken = 0x00, // 0xBF8DA5ED 35 | DO_magicShortString = 0x04, // " Chishm" 36 | DO_version = 0x0C, 37 | DO_driverSize = 0x0D, 38 | DO_fixSections = 0x0E, 39 | DO_allocatedSpace = 0x0F, 40 | 41 | DO_friendlyName = 0x10, 42 | 43 | DO_text_start = 0x40, // Data start 44 | DO_data_end = 0x44, // Data end 45 | DO_glue_start = 0x48, // Interworking glue start -- Needs address fixing 46 | DO_glue_end = 0x4C, // Interworking glue end 47 | DO_got_start = 0x50, // GOT start -- Needs address fixing 48 | DO_got_end = 0x54, // GOT end 49 | DO_bss_start = 0x58, // bss start -- Needs setting to zero 50 | DO_bss_end = 0x5C, // bss end 51 | 52 | // IO_INTERFACE data 53 | DO_ioType = 0x60, 54 | DO_features = 0x64, 55 | DO_startup = 0x68, 56 | DO_isInserted = 0x6C, 57 | DO_readSectors = 0x70, 58 | DO_writeSectors = 0x74, 59 | DO_clearStatus = 0x78, 60 | DO_shutdown = 0x7C, 61 | DO_code = 0x80 62 | }; 63 | 64 | static addr_t readAddr (data_t *mem, addr_t offset) { 65 | return ((addr_t*)mem)[offset/sizeof(addr_t)]; 66 | } 67 | 68 | static void writeAddr (data_t *mem, addr_t offset, addr_t value) { 69 | ((addr_t*)mem)[offset/sizeof(addr_t)] = value; 70 | } 71 | 72 | 73 | static addr_t quickFind (const data_t* data, const data_t* search, size_t dataLen, size_t searchLen) { 74 | const int* dataChunk = (const int*) data; 75 | int searchChunk = ((const int*)search)[0]; 76 | addr_t i; 77 | addr_t dataChunkEnd = (addr_t)(dataLen / sizeof(int)); 78 | 79 | for ( i = 0; i < dataChunkEnd; i++) { 80 | if (dataChunk[i] == searchChunk) { 81 | if ((i*sizeof(int) + searchLen) > dataLen) { 82 | return -1; 83 | } 84 | if (memcmp (&data[i*sizeof(int)], search, searchLen) == 0) { 85 | return i*sizeof(int); 86 | } 87 | } 88 | } 89 | 90 | return -1; 91 | } 92 | 93 | static const data_t dldiMagicString[] = "\xED\xA5\x8D\xBF Chishm"; // Normal DLDI file 94 | static const data_t dldiMagicLoaderString[] = "\xEE\xA5\x8D\xBF Chishm"; // Different to a normal DLDI file 95 | #define DEVICE_TYPE_DLDI 0x49444C44 96 | 97 | extern const u32 _io_dldi; 98 | 99 | bool dldiPatchBinary (data_t *binData, u32 binSize) { 100 | 101 | addr_t memOffset; // Offset of DLDI after the file is loaded into memory 102 | addr_t patchOffset; // Position of patch destination in the file 103 | addr_t relocationOffset; // Value added to all offsets within the patch to fix it properly 104 | addr_t ddmemOffset; // Original offset used in the DLDI file 105 | addr_t ddmemStart; // Start of range that offsets can be in the DLDI file 106 | addr_t ddmemEnd; // End of range that offsets can be in the DLDI file 107 | addr_t ddmemSize; // Size of range that offsets can be in the DLDI file 108 | addr_t addrIter; 109 | 110 | data_t *pDH; 111 | data_t *pAH; 112 | 113 | size_t dldiFileSize = 0; 114 | 115 | // Find the DLDI reserved space in the file 116 | patchOffset = quickFind (binData, dldiMagicString, binSize, sizeof(dldiMagicLoaderString)); 117 | 118 | if (patchOffset < 0) { 119 | // does not have a DLDI section 120 | return false; 121 | } 122 | 123 | pDH = (data_t*)(((u32*)(&_io_dldi)) - 24); 124 | pAH = &(binData[patchOffset]); 125 | 126 | if (*((u32*)(pDH + DO_ioType)) == DEVICE_TYPE_DLDI) { 127 | // No DLDI patch 128 | return false; 129 | } 130 | 131 | if (pDH[DO_driverSize] > pAH[DO_allocatedSpace]) { 132 | // Not enough space for patch 133 | return false; 134 | } 135 | 136 | dldiFileSize = 1 << pDH[DO_driverSize]; 137 | 138 | memOffset = readAddr (pAH, DO_text_start); 139 | if (memOffset == 0) { 140 | memOffset = readAddr (pAH, DO_startup) - DO_code; 141 | } 142 | ddmemOffset = readAddr (pDH, DO_text_start); 143 | relocationOffset = memOffset - ddmemOffset; 144 | 145 | ddmemStart = readAddr (pDH, DO_text_start); 146 | ddmemSize = (1 << pDH[DO_driverSize]); 147 | ddmemEnd = ddmemStart + ddmemSize; 148 | 149 | // Remember how much space is actually reserved 150 | pDH[DO_allocatedSpace] = pAH[DO_allocatedSpace]; 151 | // Copy the DLDI patch into the application 152 | memcpy (pAH, pDH, dldiFileSize); 153 | 154 | // Fix the section pointers in the header 155 | writeAddr (pAH, DO_text_start, readAddr (pAH, DO_text_start) + relocationOffset); 156 | writeAddr (pAH, DO_data_end, readAddr (pAH, DO_data_end) + relocationOffset); 157 | writeAddr (pAH, DO_glue_start, readAddr (pAH, DO_glue_start) + relocationOffset); 158 | writeAddr (pAH, DO_glue_end, readAddr (pAH, DO_glue_end) + relocationOffset); 159 | writeAddr (pAH, DO_got_start, readAddr (pAH, DO_got_start) + relocationOffset); 160 | writeAddr (pAH, DO_got_end, readAddr (pAH, DO_got_end) + relocationOffset); 161 | writeAddr (pAH, DO_bss_start, readAddr (pAH, DO_bss_start) + relocationOffset); 162 | writeAddr (pAH, DO_bss_end, readAddr (pAH, DO_bss_end) + relocationOffset); 163 | // Fix the function pointers in the header 164 | writeAddr (pAH, DO_startup, readAddr (pAH, DO_startup) + relocationOffset); 165 | writeAddr (pAH, DO_isInserted, readAddr (pAH, DO_isInserted) + relocationOffset); 166 | writeAddr (pAH, DO_readSectors, readAddr (pAH, DO_readSectors) + relocationOffset); 167 | writeAddr (pAH, DO_writeSectors, readAddr (pAH, DO_writeSectors) + relocationOffset); 168 | writeAddr (pAH, DO_clearStatus, readAddr (pAH, DO_clearStatus) + relocationOffset); 169 | writeAddr (pAH, DO_shutdown, readAddr (pAH, DO_shutdown) + relocationOffset); 170 | 171 | // Put the correct DLDI magic string back into the DLDI header 172 | memcpy (pAH, dldiMagicString, sizeof (dldiMagicString)); 173 | 174 | if (pDH[DO_fixSections] & FIX_ALL) { 175 | // Search through and fix pointers within the data section of the file 176 | for (addrIter = (readAddr(pDH, DO_text_start) - ddmemStart); addrIter < (readAddr(pDH, DO_data_end) - ddmemStart); addrIter++) { 177 | if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { 178 | writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); 179 | } 180 | } 181 | } 182 | 183 | if (pDH[DO_fixSections] & FIX_GLUE) { 184 | // Search through and fix pointers within the glue section of the file 185 | for (addrIter = (readAddr(pDH, DO_glue_start) - ddmemStart); addrIter < (readAddr(pDH, DO_glue_end) - ddmemStart); addrIter++) { 186 | if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { 187 | writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); 188 | } 189 | } 190 | } 191 | 192 | if (pDH[DO_fixSections] & FIX_GOT) { 193 | // Search through and fix pointers within the Global Offset Table section of the file 194 | for (addrIter = (readAddr(pDH, DO_got_start) - ddmemStart); addrIter < (readAddr(pDH, DO_got_end) - ddmemStart); addrIter++) { 195 | if ((ddmemStart <= readAddr(pAH, addrIter)) && (readAddr(pAH, addrIter) < ddmemEnd)) { 196 | writeAddr (pAH, addrIter, readAddr(pAH, addrIter) + relocationOffset); 197 | } 198 | } 199 | } 200 | 201 | if (pDH[DO_fixSections] & FIX_BSS) { 202 | // Initialise the BSS to 0 203 | memset (&pAH[readAddr(pDH, DO_bss_start) - ddmemStart] , 0, readAddr(pDH, DO_bss_end) - readAddr(pDH, DO_bss_start)); 204 | } 205 | 206 | return true; 207 | } 208 | #endif -------------------------------------------------------------------------------- /bootloader/source/dldi_patcher.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2005 Michael "Chishm" Chisholm 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | If you use this code, please give due credit and email me about your 20 | project at chishm@hotmail.com 21 | ------------------------------------------------------------------*/ 22 | 23 | #ifndef DLDI_PATCHER_H 24 | #define DLDI_PATCHER_H 25 | 26 | #include 27 | 28 | typedef signed int addr_t; 29 | typedef unsigned char data_t; 30 | bool dldiPatchBinary (data_t *binData, u32 binSize); 31 | 32 | #endif // DLDI_PATCHER_H 33 | -------------------------------------------------------------------------------- /bootloader/source/fat.c: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | fat.c 3 | 4 | NDS MP 5 | GBAMP NDS Firmware Hack Version 2.12 6 | An NDS aware firmware patch for the GBA Movie Player. 7 | By Michael Chisholm (Chishm) 8 | 9 | Filesystem code based on GBAMP_CF.c by Chishm (me). 10 | 11 | License: 12 | Copyright (C) 2005 Michael "Chishm" Chisholm 13 | 14 | This program is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU General Public License 16 | as published by the Free Software Foundation; either version 2 17 | of the License, or (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 27 | 28 | If you use this code, please give due credit and email me about your 29 | project at chishm@hotmail.com 30 | ------------------------------------------------------------------*/ 31 | 32 | #include "fat.h" 33 | #include "card.h" 34 | 35 | 36 | //--------------------------------------------------------------- 37 | // FAT constants 38 | 39 | #define FILE_LAST 0x00 40 | #define FILE_FREE 0xE5 41 | 42 | #define ATTRIB_ARCH 0x20 43 | #define ATTRIB_DIR 0x10 44 | #define ATTRIB_LFN 0x0F 45 | #define ATTRIB_VOL 0x08 46 | #define ATTRIB_HID 0x02 47 | #define ATTRIB_SYS 0x04 48 | #define ATTRIB_RO 0x01 49 | 50 | #define FAT16_ROOT_DIR_CLUSTER 0x00 51 | 52 | // File Constants 53 | #ifndef EOF 54 | #define EOF -1 55 | #define SEEK_SET 0 56 | #define SEEK_CUR 1 57 | #define SEEK_END 2 58 | #endif 59 | 60 | 61 | //----------------------------------------------------------------- 62 | // FAT constants 63 | #define CLUSTER_EOF_16 0xFFFF 64 | 65 | #define ATTRIB_ARCH 0x20 66 | #define ATTRIB_DIR 0x10 67 | #define ATTRIB_LFN 0x0F 68 | #define ATTRIB_VOL 0x08 69 | #define ATTRIB_HID 0x02 70 | #define ATTRIB_SYS 0x04 71 | #define ATTRIB_RO 0x01 72 | 73 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 74 | // Data Structures 75 | 76 | #define __PACKED __attribute__ ((__packed__)) 77 | 78 | // Boot Sector - must be packed 79 | typedef struct 80 | { 81 | u8 jmpBoot[3]; 82 | u8 OEMName[8]; 83 | // BIOS Parameter Block 84 | u16 bytesPerSector; 85 | u8 sectorsPerCluster; 86 | u16 reservedSectors; 87 | u8 numFATs; 88 | u16 rootEntries; 89 | u16 numSectorsSmall; 90 | u8 mediaDesc; 91 | u16 sectorsPerFAT; 92 | u16 sectorsPerTrk; 93 | u16 numHeads; 94 | u32 numHiddenSectors; 95 | u32 numSectors; 96 | union // Different types of extended BIOS Parameter Block for FAT16 and FAT32 97 | { 98 | struct 99 | { 100 | // Ext BIOS Parameter Block for FAT16 101 | u8 driveNumber; 102 | u8 reserved1; 103 | u8 extBootSig; 104 | u32 volumeID; 105 | u8 volumeLabel[11]; 106 | u8 fileSysType[8]; 107 | // Bootcode 108 | u8 bootCode[448]; 109 | } fat16; 110 | struct 111 | { 112 | // FAT32 extended block 113 | u32 sectorsPerFAT32; 114 | u16 extFlags; 115 | u16 fsVer; 116 | u32 rootClus; 117 | u16 fsInfo; 118 | u16 bkBootSec; 119 | u8 reserved[12]; 120 | // Ext BIOS Parameter Block for FAT16 121 | u8 driveNumber; 122 | u8 reserved1; 123 | u8 extBootSig; 124 | u32 volumeID; 125 | u8 volumeLabel[11]; 126 | u8 fileSysType[8]; 127 | // Bootcode 128 | u8 bootCode[420]; 129 | } fat32; 130 | } extBlock; 131 | 132 | __PACKED u16 bootSig; 133 | 134 | } __PACKED BOOT_SEC; 135 | 136 | // Directory entry - must be packed 137 | typedef struct 138 | { 139 | u8 name[8]; 140 | u8 ext[3]; 141 | u8 attrib; 142 | u8 reserved; 143 | u8 cTime_ms; 144 | u16 cTime; 145 | u16 cDate; 146 | u16 aDate; 147 | u16 startClusterHigh; 148 | u16 mTime; 149 | u16 mDate; 150 | u16 startCluster; 151 | u32 fileSize; 152 | } __PACKED DIR_ENT; 153 | 154 | // File information - no need to pack 155 | typedef struct 156 | { 157 | u32 firstCluster; 158 | u32 length; 159 | u32 curPos; 160 | u32 curClus; // Current cluster to read from 161 | int curSect; // Current sector within cluster 162 | int curByte; // Current byte within sector 163 | char readBuffer[512]; // Buffer used for unaligned reads 164 | u32 appClus; // Cluster to append to 165 | int appSect; // Sector within cluster for appending 166 | int appByte; // Byte within sector for appending 167 | bool read; // Can read from file 168 | bool write; // Can write to file 169 | bool append;// Can append to file 170 | bool inUse; // This file is open 171 | u32 dirEntSector; // The sector where the directory entry is stored 172 | int dirEntOffset; // The offset within the directory sector 173 | } FAT_FILE; 174 | 175 | 176 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 177 | // Global Variables 178 | 179 | // _VARS_IN_RAM variables are stored in the largest section of WRAM 180 | // available: IWRAM on NDS ARM7, EWRAM on NDS ARM9 and GBA 181 | 182 | // Locations on card 183 | int discRootDir; 184 | int discRootDirClus; 185 | int discFAT; 186 | int discSecPerFAT; 187 | int discNumSec; 188 | int discData; 189 | int discBytePerSec; 190 | int discSecPerClus; 191 | int discBytePerClus; 192 | 193 | enum {FS_UNKNOWN, FS_FAT12, FS_FAT16, FS_FAT32} discFileSystem; 194 | 195 | // Global sector buffer to save on stack space 196 | unsigned char globalBuffer[BYTES_PER_SECTOR]; 197 | 198 | 199 | //++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 200 | //FAT routines 201 | 202 | u32 FAT_ClustToSect (u32 cluster) { 203 | return (((cluster-2) * discSecPerClus) + discData); 204 | } 205 | 206 | /*----------------------------------------------------------------- 207 | FAT_NextCluster 208 | Internal function - gets the cluster linked from input cluster 209 | -----------------------------------------------------------------*/ 210 | u32 FAT_NextCluster(u32 cluster) 211 | { 212 | u32 nextCluster = CLUSTER_FREE; 213 | u32 sector; 214 | int offset; 215 | 216 | 217 | switch (discFileSystem) 218 | { 219 | case FS_UNKNOWN: 220 | nextCluster = CLUSTER_FREE; 221 | break; 222 | 223 | case FS_FAT12: 224 | sector = discFAT + (((cluster * 3) / 2) / BYTES_PER_SECTOR); 225 | offset = ((cluster * 3) / 2) % BYTES_PER_SECTOR; 226 | CARD_ReadSector(sector, globalBuffer); 227 | nextCluster = ((u8*) globalBuffer)[offset]; 228 | offset++; 229 | 230 | if (offset >= BYTES_PER_SECTOR) { 231 | offset = 0; 232 | sector++; 233 | } 234 | 235 | CARD_ReadSector(sector, globalBuffer); 236 | nextCluster |= (((u8*) globalBuffer)[offset]) << 8; 237 | 238 | if (cluster & 0x01) { 239 | nextCluster = nextCluster >> 4; 240 | } else { 241 | nextCluster &= 0x0FFF; 242 | } 243 | 244 | break; 245 | 246 | case FS_FAT16: 247 | sector = discFAT + ((cluster << 1) / BYTES_PER_SECTOR); 248 | offset = cluster % (BYTES_PER_SECTOR >> 1); 249 | 250 | CARD_ReadSector(sector, globalBuffer); 251 | // read the nextCluster value 252 | nextCluster = ((u16*)globalBuffer)[offset]; 253 | 254 | if (nextCluster >= 0xFFF7) 255 | { 256 | nextCluster = CLUSTER_EOF; 257 | } 258 | break; 259 | 260 | case FS_FAT32: 261 | sector = discFAT + ((cluster << 2) / BYTES_PER_SECTOR); 262 | offset = cluster % (BYTES_PER_SECTOR >> 2); 263 | 264 | CARD_ReadSector(sector, globalBuffer); 265 | // read the nextCluster value 266 | nextCluster = (((u32*)globalBuffer)[offset]) & 0x0FFFFFFF; 267 | 268 | if (nextCluster >= 0x0FFFFFF7) 269 | { 270 | nextCluster = CLUSTER_EOF; 271 | } 272 | break; 273 | 274 | default: 275 | nextCluster = CLUSTER_FREE; 276 | break; 277 | } 278 | 279 | return nextCluster; 280 | } 281 | 282 | /*----------------------------------------------------------------- 283 | ucase 284 | Returns the uppercase version of the given char 285 | char IN: a character 286 | char return OUT: uppercase version of character 287 | -----------------------------------------------------------------*/ 288 | char ucase (char character) 289 | { 290 | if ((character > 0x60) && (character < 0x7B)) 291 | character = character - 0x20; 292 | return (character); 293 | } 294 | 295 | /*----------------------------------------------------------------- 296 | FAT_InitFiles 297 | Reads the FAT information from the CF card. 298 | You need to call this before reading any files. 299 | bool return OUT: true if successful. 300 | -----------------------------------------------------------------*/ 301 | bool FAT_InitFiles (bool initCard) 302 | { 303 | int i; 304 | int bootSector; 305 | BOOT_SEC* bootSec; 306 | 307 | if (initCard && !CARD_StartUp()) 308 | { 309 | return (false); 310 | } 311 | 312 | // Read first sector of card 313 | if (!CARD_ReadSector (0, globalBuffer)) 314 | { 315 | return false; 316 | } 317 | // Check if there is a FAT string, which indicates this is a boot sector 318 | if ((globalBuffer[0x36] == 'F') && (globalBuffer[0x37] == 'A') && (globalBuffer[0x38] == 'T')) 319 | { 320 | bootSector = 0; 321 | } 322 | // Check for FAT32 323 | else if ((globalBuffer[0x52] == 'F') && (globalBuffer[0x53] == 'A') && (globalBuffer[0x54] == 'T')) 324 | { 325 | bootSector = 0; 326 | } 327 | else // This is an MBR 328 | { 329 | // Find first valid partition from MBR 330 | // First check for an active partition 331 | for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i] != 0x80); i+= 0x10); 332 | // If it didn't find an active partition, search for any valid partition 333 | if (i == 0x1FE) 334 | for (i=0x1BE; (i < 0x1FE) && (globalBuffer[i+0x04] == 0x00); i+= 0x10); 335 | 336 | // Go to first valid partition 337 | if ( i != 0x1FE) // Make sure it found a partition 338 | { 339 | bootSector = globalBuffer[0x8 + i] + (globalBuffer[0x9 + i] << 8) + (globalBuffer[0xA + i] << 16) + ((globalBuffer[0xB + i] << 24) & 0x0F); 340 | } else { 341 | bootSector = 0; // No partition found, assume this is a MBR free disk 342 | } 343 | } 344 | 345 | // Read in boot sector 346 | bootSec = (BOOT_SEC*) globalBuffer; 347 | CARD_ReadSector (bootSector, bootSec); 348 | 349 | // Store required information about the file system 350 | if (bootSec->sectorsPerFAT != 0) 351 | { 352 | discSecPerFAT = bootSec->sectorsPerFAT; 353 | } 354 | else 355 | { 356 | discSecPerFAT = bootSec->extBlock.fat32.sectorsPerFAT32; 357 | } 358 | 359 | if (bootSec->numSectorsSmall != 0) 360 | { 361 | discNumSec = bootSec->numSectorsSmall; 362 | } 363 | else 364 | { 365 | discNumSec = bootSec->numSectors; 366 | } 367 | 368 | discBytePerSec = BYTES_PER_SECTOR; // Sector size is redefined to be 512 bytes 369 | discSecPerClus = bootSec->sectorsPerCluster * bootSec->bytesPerSector / BYTES_PER_SECTOR; 370 | discBytePerClus = discBytePerSec * discSecPerClus; 371 | discFAT = bootSector + bootSec->reservedSectors; 372 | 373 | discRootDir = discFAT + (bootSec->numFATs * discSecPerFAT); 374 | discData = discRootDir + ((bootSec->rootEntries * sizeof(DIR_ENT)) / BYTES_PER_SECTOR); 375 | 376 | if ((discNumSec - discData) / bootSec->sectorsPerCluster < 4085) 377 | { 378 | discFileSystem = FS_FAT12; 379 | } 380 | else if ((discNumSec - discData) / bootSec->sectorsPerCluster < 65525) 381 | { 382 | discFileSystem = FS_FAT16; 383 | } 384 | else 385 | { 386 | discFileSystem = FS_FAT32; 387 | } 388 | 389 | if (discFileSystem != FS_FAT32) 390 | { 391 | discRootDirClus = FAT16_ROOT_DIR_CLUSTER; 392 | } 393 | else // Set up for the FAT32 way 394 | { 395 | discRootDirClus = bootSec->extBlock.fat32.rootClus; 396 | // Check if FAT mirroring is enabled 397 | if (!(bootSec->extBlock.fat32.extFlags & 0x80)) 398 | { 399 | // Use the active FAT 400 | discFAT = discFAT + ( discSecPerFAT * (bootSec->extBlock.fat32.extFlags & 0x0F)); 401 | } 402 | } 403 | 404 | return (true); 405 | } 406 | 407 | 408 | /*----------------------------------------------------------------- 409 | getBootFileCluster 410 | -----------------------------------------------------------------*/ 411 | u32 getBootFileCluster (const char* bootName) 412 | { 413 | DIR_ENT dir; 414 | int firstSector = 0; 415 | bool notFound = false; 416 | bool found = false; 417 | // int maxSectors; 418 | u32 wrkDirCluster = discRootDirClus; 419 | u32 wrkDirSector = 0; 420 | int wrkDirOffset = 0; 421 | int nameOffset; 422 | 423 | dir.startCluster = CLUSTER_FREE; // default to no file found 424 | dir.startClusterHigh = CLUSTER_FREE; 425 | 426 | 427 | // Check if fat has been initialised 428 | if (discBytePerSec == 0) 429 | { 430 | return (CLUSTER_FREE); 431 | } 432 | 433 | char *ptr = (char*)bootName; 434 | while (*ptr != '.') ptr++; 435 | int namelen = ptr - bootName; 436 | 437 | // maxSectors = (wrkDirCluster == FAT16_ROOT_DIR_CLUSTER ? (discData - discRootDir) : discSecPerClus); 438 | // Scan Dir for correct entry 439 | firstSector = discRootDir; 440 | CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); 441 | found = false; 442 | notFound = false; 443 | wrkDirOffset = -1; // Start at entry zero, Compensating for increment 444 | while (!found && !notFound) { 445 | wrkDirOffset++; 446 | if (wrkDirOffset == BYTES_PER_SECTOR / sizeof (DIR_ENT)) 447 | { 448 | wrkDirOffset = 0; 449 | wrkDirSector++; 450 | if ((wrkDirSector == discSecPerClus) && (wrkDirCluster != FAT16_ROOT_DIR_CLUSTER)) 451 | { 452 | wrkDirSector = 0; 453 | wrkDirCluster = FAT_NextCluster(wrkDirCluster); 454 | if (wrkDirCluster == CLUSTER_EOF) 455 | { 456 | notFound = true; 457 | } 458 | firstSector = FAT_ClustToSect(wrkDirCluster); 459 | } 460 | else if ((wrkDirCluster == FAT16_ROOT_DIR_CLUSTER) && (wrkDirSector == (discData - discRootDir))) 461 | { 462 | notFound = true; // Got to end of root dir 463 | } 464 | CARD_ReadSector (firstSector + wrkDirSector, globalBuffer); 465 | } 466 | dir = ((DIR_ENT*) globalBuffer)[wrkDirOffset]; 467 | found = true; 468 | if ((dir.attrib & ATTRIB_DIR) || (dir.attrib & ATTRIB_VOL)) 469 | { 470 | found = false; 471 | } 472 | if(namelen<8 && dir.name[namelen]!=0x20) found = false; 473 | for (nameOffset = 0; nameOffset < namelen && found; nameOffset++) 474 | { 475 | if (ucase(dir.name[nameOffset]) != bootName[nameOffset]) 476 | found = false; 477 | } 478 | for (nameOffset = 0; nameOffset < 3 && found; nameOffset++) 479 | { 480 | if (ucase(dir.ext[nameOffset]) != bootName[nameOffset+namelen+1]) 481 | found = false; 482 | } 483 | if (dir.name[0] == FILE_LAST) 484 | { 485 | notFound = true; 486 | } 487 | } 488 | 489 | // If no file is found, return CLUSTER_FREE 490 | if (notFound) 491 | { 492 | return CLUSTER_FREE; 493 | } 494 | 495 | return (dir.startCluster | (dir.startClusterHigh << 16)); 496 | } 497 | 498 | /*----------------------------------------------------------------- 499 | fileRead(buffer, cluster, startOffset, length) 500 | -----------------------------------------------------------------*/ 501 | u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length) 502 | { 503 | int curByte; 504 | int curSect; 505 | 506 | int dataPos = 0; 507 | int chunks; 508 | int beginBytes; 509 | 510 | if (cluster == CLUSTER_FREE || cluster == CLUSTER_EOF) 511 | { 512 | return 0; 513 | } 514 | 515 | // Follow cluster list until desired one is found 516 | for (chunks = startOffset / discBytePerClus; chunks > 0; chunks--) 517 | { 518 | cluster = FAT_NextCluster (cluster); 519 | } 520 | 521 | // Calculate the sector and byte of the current position, 522 | // and store them 523 | curSect = (startOffset % discBytePerClus) / BYTES_PER_SECTOR; 524 | curByte = startOffset % BYTES_PER_SECTOR; 525 | 526 | // Load sector buffer for new position in file 527 | CARD_ReadSector( curSect + FAT_ClustToSect(cluster), globalBuffer); 528 | curSect++; 529 | 530 | // Number of bytes needed to read to align with a sector 531 | beginBytes = (BYTES_PER_SECTOR < length + curByte ? (BYTES_PER_SECTOR - curByte) : length); 532 | 533 | // Read first part from buffer, to align with sector boundary 534 | for (dataPos = 0 ; dataPos < beginBytes; dataPos++) 535 | { 536 | buffer[dataPos] = globalBuffer[curByte++]; 537 | } 538 | 539 | // Read in all the 512 byte chunks of the file directly, saving time 540 | for ( chunks = ((int)length - beginBytes) / BYTES_PER_SECTOR; chunks > 0;) 541 | { 542 | int sectorsToRead; 543 | 544 | // Move to the next cluster if necessary 545 | if (curSect >= discSecPerClus) 546 | { 547 | curSect = 0; 548 | cluster = FAT_NextCluster (cluster); 549 | } 550 | 551 | // Calculate how many sectors to read (read a maximum of discSecPerClus at a time) 552 | sectorsToRead = discSecPerClus - curSect; 553 | if(chunks < sectorsToRead) 554 | sectorsToRead = chunks; 555 | 556 | // Read the sectors 557 | CARD_ReadSectors(curSect + FAT_ClustToSect(cluster), sectorsToRead, buffer + dataPos); 558 | chunks -= sectorsToRead; 559 | curSect += sectorsToRead; 560 | dataPos += BYTES_PER_SECTOR * sectorsToRead; 561 | } 562 | 563 | // Take care of any bytes left over before end of read 564 | if (dataPos < length) 565 | { 566 | 567 | // Update the read buffer 568 | curByte = 0; 569 | if (curSect >= discSecPerClus) 570 | { 571 | curSect = 0; 572 | cluster = FAT_NextCluster (cluster); 573 | } 574 | CARD_ReadSector( curSect + FAT_ClustToSect( cluster), globalBuffer); 575 | 576 | // Read in last partial chunk 577 | for (; dataPos < length; dataPos++) 578 | { 579 | buffer[dataPos] = globalBuffer[curByte]; 580 | curByte++; 581 | } 582 | } 583 | 584 | return dataPos; 585 | } 586 | -------------------------------------------------------------------------------- /bootloader/source/fat.h: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | fat.h 3 | 4 | NDS MP 5 | GBAMP NDS Firmware Hack Version 2.12 6 | An NDS aware firmware patch for the GBA Movie Player. 7 | By Michael Chisholm (Chishm) 8 | 9 | Filesystem code based on GBAMP_CF.c by Chishm (me). 10 | 11 | License: 12 | Copyright (C) 2005 Michael "Chishm" Chisholm 13 | 14 | This program is free software; you can redistribute it and/or 15 | modify it under the terms of the GNU General Public License 16 | as published by the Free Software Foundation; either version 2 17 | of the License, or (at your option) any later version. 18 | 19 | This program is distributed in the hope that it will be useful, 20 | but WITHOUT ANY WARRANTY; without even the implied warranty of 21 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 22 | GNU General Public License for more details. 23 | 24 | You should have received a copy of the GNU General Public License 25 | along with this program; if not, write to the Free Software 26 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 27 | 28 | If you use this code, please give due credit and email me about your 29 | project at chishm@hotmail.com 30 | ------------------------------------------------------------------*/ 31 | 32 | #ifndef FAT_H 33 | #define FAT_H 34 | 35 | #include 36 | 37 | #define CLUSTER_FREE 0x00000000 38 | #define CLUSTER_EOF 0x0FFFFFFF 39 | #define CLUSTER_FIRST 0x00000002 40 | 41 | bool FAT_InitFiles (bool initCard); 42 | u32 getBootFileCluster (const char* bootName); 43 | u32 fileRead (char* buffer, u32 cluster, u32 startOffset, u32 length); 44 | u32 FAT_ClustToSect (u32 cluster); 45 | 46 | #endif // FAT_H 47 | -------------------------------------------------------------------------------- /bootloader/source/i2c.c: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------- 2 | 3 | I2C control for the ARM7 4 | 5 | Copyright (C) 2011 6 | Dave Murphy (WinterMute) 7 | 8 | This software is provided 'as-is', without any express or implied 9 | warranty. In no event will the authors be held liable for any 10 | damages arising from the use of this software. 11 | 12 | Permission is granted to anyone to use this software for any 13 | purpose, including commercial applications, and to alter it and 14 | redistribute it freely, subject to the following restrictions: 15 | 16 | 1. The origin of this software must not be misrepresented; you 17 | must not claim that you wrote the original software. If you use 18 | this software in a product, an acknowledgment in the product 19 | documentation would be appreciated but is not required. 20 | 2. Altered source versions must be plainly marked as such, and 21 | must not be misrepresented as being the original software. 22 | 3. This notice may not be removed or altered from any source 23 | distribution. 24 | 25 | ---------------------------------------------------------------------------------*/ 26 | 27 | #include 28 | #include 29 | 30 | static u32 i2cCurrentDelay = 0; 31 | 32 | //--------------------------------------------------------------------------------- 33 | void i2cDelay() { 34 | //--------------------------------------------------------------------------------- 35 | i2cWaitBusy(); 36 | swiDelay(i2cCurrentDelay); 37 | } 38 | 39 | //--------------------------------------------------------------------------------- 40 | void i2cStop(u8 arg0) { 41 | //--------------------------------------------------------------------------------- 42 | if(i2cCurrentDelay) { 43 | REG_I2CCNT = (arg0 << 5) | 0xC0; 44 | i2cDelay(); 45 | REG_I2CCNT = 0xC5; 46 | } else REG_I2CCNT = (arg0 << 5) | 0xC1; 47 | } 48 | 49 | 50 | //--------------------------------------------------------------------------------- 51 | u8 i2cGetResult() { 52 | //--------------------------------------------------------------------------------- 53 | i2cWaitBusy(); 54 | return (REG_I2CCNT >> 4) & 0x01; 55 | } 56 | 57 | //--------------------------------------------------------------------------------- 58 | u8 i2cGetData() { 59 | //--------------------------------------------------------------------------------- 60 | i2cWaitBusy(); 61 | return REG_I2CDATA; 62 | } 63 | 64 | //--------------------------------------------------------------------------------- 65 | void i2cSetDelay(u8 device) { 66 | //--------------------------------------------------------------------------------- 67 | if (device == I2C_PM ) { 68 | i2cCurrentDelay = 0x180; 69 | } else { 70 | i2cCurrentDelay = 0; 71 | } 72 | } 73 | 74 | //--------------------------------------------------------------------------------- 75 | u8 i2cSelectDevice(u8 device) { 76 | //--------------------------------------------------------------------------------- 77 | i2cWaitBusy(); 78 | REG_I2CDATA = device; 79 | REG_I2CCNT = 0xC2; 80 | return i2cGetResult(); 81 | } 82 | 83 | //--------------------------------------------------------------------------------- 84 | u8 i2cSelectRegister(u8 reg) { 85 | //--------------------------------------------------------------------------------- 86 | i2cDelay(); 87 | REG_I2CDATA = reg; 88 | REG_I2CCNT = 0xC0; 89 | return i2cGetResult(); 90 | } 91 | 92 | //--------------------------------------------------------------------------------- 93 | u8 i2cWriteRegister(u8 device, u8 reg, u8 data) { 94 | //--------------------------------------------------------------------------------- 95 | i2cSetDelay(device); 96 | int i; 97 | 98 | for(i = 0; i < 8; i++) { 99 | if((i2cSelectDevice(device) != 0) && (i2cSelectRegister(reg) != 0)) { 100 | i2cDelay(); 101 | REG_I2CDATA = data; 102 | i2cStop(0); 103 | if(i2cGetResult() != 0) return 1; 104 | } 105 | REG_I2CCNT = 0xC5; 106 | } 107 | 108 | return 0; 109 | } 110 | 111 | //--------------------------------------------------------------------------------- 112 | u8 i2cReadRegister(u8 device, u8 reg) { 113 | //--------------------------------------------------------------------------------- 114 | i2cSetDelay(device); 115 | int i; 116 | 117 | for(i = 0; i < 8; i++) { 118 | 119 | if((i2cSelectDevice(device) != 0) && (i2cSelectRegister(reg) != 0)) { 120 | i2cDelay(); 121 | if(i2cSelectDevice(device | 1)) { 122 | i2cDelay(); 123 | i2cStop(1); 124 | return i2cGetData(); 125 | } 126 | } 127 | 128 | REG_I2CCNT = 0xC5; 129 | } 130 | 131 | return 0xff; 132 | } -------------------------------------------------------------------------------- /bootloader/source/i2c.h: -------------------------------------------------------------------------------- 1 | /*--------------------------------------------------------------------------------- 2 | 3 | I2C control for the ARM7 4 | 5 | Copyright (C) 2011 6 | Dave Murphy (WinterMute) 7 | 8 | This software is provided 'as-is', without any express or implied 9 | warranty. In no event will the authors be held liable for any 10 | damages arising from the use of this software. 11 | 12 | Permission is granted to anyone to use this software for any 13 | purpose, including commercial applications, and to alter it and 14 | redistribute it freely, subject to the following restrictions: 15 | 16 | 1. The origin of this software must not be misrepresented; you 17 | must not claim that you wrote the original software. If you use 18 | this software in a product, an acknowledgment in the product 19 | documentation would be appreciated but is not required. 20 | 2. Altered source versions must be plainly marked as such, and 21 | must not be misrepresented as being the original software. 22 | 3. This notice may not be removed or altered from any source 23 | distribution. 24 | 25 | ---------------------------------------------------------------------------------*/ 26 | #ifndef I2C_ARM7_INCLUDE 27 | #define I2C_ARM7_INCLUDE 28 | 29 | #ifndef ARM7 30 | #error i2c header is for ARM7 only 31 | #endif 32 | 33 | #include 34 | 35 | #define REG_I2CDATA (*(vu8 *)0x4004500) 36 | #define REG_I2CCNT (*(vu8 *)0x4004501) 37 | 38 | static inline void i2cWaitBusy() { 39 | while(REG_I2CCNT & 0x80); 40 | } 41 | 42 | enum i2cDevices { 43 | I2C_CAM0 = 0x7A, 44 | I2C_CAM1 = 0x78, 45 | I2C_UNK1 = 0xA0, 46 | I2C_UNK2 = 0xE0, 47 | I2C_PM = 0x4A, 48 | I2C_UNK3 = 0x40, 49 | I2C_GPIO = 0x90 50 | }; 51 | 52 | // Registers for Power Management (I2C_PM) 53 | #define I2CREGPM_BATUNK 0x00 54 | #define I2CREGPM_PWRIF 0x10 55 | #define I2CREGPM_PWRCNT 0x11 56 | #define I2CREGPM_MMCPWR 0x12 57 | #define I2CREGPM_BATTERY 0x20 58 | #define I2CREGPM_CAMLED 0x31 59 | #define I2CREGPM_VOL 0x40 60 | #define I2CREGPM_RESETFLAG 0x70 61 | 62 | u8 i2cWriteRegister(u8 device, u8 reg, u8 data); 63 | u8 i2cReadRegister(u8 device, u8 reg); 64 | 65 | #endif // I2C_ARM7_INCLUDE -------------------------------------------------------------------------------- /bootloader/source/io_dldi.h: -------------------------------------------------------------------------------- 1 | /*-------------------------------------------------------------------------------------------- 2 | io_dldi.h 3 | 4 | Reserved space for post-compilation adding of an extra driver 5 | 6 | Copyright (c) 2006 Michael "Chishm" Chisholm 7 | 8 | Redistribution and use in source and binary forms, with or without modification, 9 | are permitted provided that the following conditions are met: 10 | 11 | 1. Redistributions of source code must retain the above copyright notice, 12 | this list of conditions and the following disclaimer. 13 | 2. Redistributions in binary form must reproduce the above copyright notice, 14 | this list of conditions and the following disclaimer in the documentation and/or 15 | other materials provided with the distribution. 16 | 3. The name of the author may not be used to endorse or promote products derived 17 | from this software without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED 20 | WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY 21 | AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE 22 | LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 | DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 | LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 25 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 27 | EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 | 29 | 2006-12-22 - Chishm 30 | * Original release 31 | --------------------------------------------------------------------------------------------*/ 32 | 33 | #ifndef IO_DLDI_H 34 | #define IO_DLDI_H 35 | 36 | // 'DLDD' 37 | #define DEVICE_TYPE_DLDD 0x49444C44 38 | 39 | #include "disc_io.h" 40 | 41 | // export interface 42 | extern IO_INTERFACE _io_dldi ; 43 | 44 | #endif // define IO_DLDI_H 45 | -------------------------------------------------------------------------------- /bootloader/source/io_dldi.s: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2005 Michael "Chishm" Chisholm 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | If you use this code, please give due credit and email me about your 20 | project at chishm@hotmail.com 21 | ------------------------------------------------------------------*/ 22 | @--------------------------------------------------------------------------------- 23 | .align 4 24 | .arm 25 | .global _dldi_start 26 | .global _io_dldi 27 | @--------------------------------------------------------------------------------- 28 | .equ FEATURE_MEDIUM_CANREAD, 0x00000001 29 | .equ FEATURE_MEDIUM_CANWRITE, 0x00000002 30 | .equ FEATURE_SLOT_GBA, 0x00000010 31 | .equ FEATURE_SLOT_NDS, 0x00000020 32 | 33 | 34 | _dldi_start: 35 | #ifndef NO_DLDI 36 | 37 | @--------------------------------------------------------------------------------- 38 | @ Driver patch file standard header -- 16 bytes 39 | #ifdef STANDARD_DLDI 40 | .word 0xBF8DA5ED @ Magic number to identify this region 41 | #else 42 | .word 0xBF8DA5EE @ Magic number to identify this region 43 | #endif 44 | .asciz " Chishm" @ Identifying Magic string (8 bytes with null terminator) 45 | .byte 0x01 @ Version number 46 | .byte 0x0e @ 16KiB @ Log [base-2] of the size of this driver in bytes. 47 | .byte 0x00 @ Sections to fix 48 | .byte 0x0e @ 16KiB @ Log [base-2] of the allocated space in bytes. 49 | 50 | @--------------------------------------------------------------------------------- 51 | @ Text identifier - can be anything up to 47 chars + terminating null -- 16 bytes 52 | .align 4 53 | .asciz "Loader (No interface)" 54 | 55 | @--------------------------------------------------------------------------------- 56 | @ Offsets to important sections within the data -- 32 bytes 57 | .align 6 58 | .word _dldi_start @ data start 59 | .word _dldi_end @ data end 60 | .word 0x00000000 @ Interworking glue start -- Needs address fixing 61 | .word 0x00000000 @ Interworking glue end 62 | .word 0x00000000 @ GOT start -- Needs address fixing 63 | .word 0x00000000 @ GOT end 64 | .word 0x00000000 @ bss start -- Needs setting to zero 65 | .word 0x00000000 @ bss end 66 | @--------------------------------------------------------------------------------- 67 | @ IO_INTERFACE data -- 32 bytes 68 | _io_dldi: 69 | .ascii "DLDI" @ ioType 70 | .word 0x00000000 @ Features 71 | .word _DLDI_startup @ 72 | .word _DLDI_isInserted @ 73 | .word _DLDI_readSectors @ Function pointers to standard device driver functions 74 | .word _DLDI_writeSectors @ 75 | .word _DLDI_clearStatus @ 76 | .word _DLDI_shutdown @ 77 | 78 | 79 | @--------------------------------------------------------------------------------- 80 | 81 | _DLDI_startup: 82 | _DLDI_isInserted: 83 | _DLDI_readSectors: 84 | _DLDI_writeSectors: 85 | _DLDI_clearStatus: 86 | _DLDI_shutdown: 87 | mov r0, #0x00 @ Return false for every function 88 | bx lr 89 | 90 | 91 | 92 | @--------------------------------------------------------------------------------- 93 | .align 94 | .pool 95 | 96 | .space (_dldi_start + 16384) - . @ Fill to 16KiB 97 | 98 | _dldi_end: 99 | .end 100 | @--------------------------------------------------------------------------------- 101 | #else 102 | @--------------------------------------------------------------------------------- 103 | @ IO_INTERFACE data -- 32 bytes 104 | _io_dldi: 105 | .ascii "DLDI" @ ioType 106 | .word 0x00000000 @ Features 107 | .word _DLDI_startup @ 108 | .word _DLDI_isInserted @ 109 | .word _DLDI_readSectors @ Function pointers to standard device driver functions 110 | .word _DLDI_writeSectors @ 111 | .word _DLDI_clearStatus @ 112 | .word _DLDI_shutdown @ 113 | 114 | _DLDI_startup: 115 | _DLDI_isInserted: 116 | _DLDI_readSectors: 117 | _DLDI_writeSectors: 118 | _DLDI_clearStatus: 119 | _DLDI_shutdown: 120 | mov r0, #0x00 @ Return false for every function 121 | bx lr 122 | 123 | 124 | #endif 125 | -------------------------------------------------------------------------------- /bootloader/source/load_crt0.s: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2005 Michael "Chishm" Chisholm 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | If you use this code, please give due credit and email me about your 20 | project at chishm@hotmail.com 21 | ------------------------------------------------------------------*/ 22 | 23 | @--------------------------------------------------------------------------------- 24 | .section ".init" 25 | .global _start 26 | .global storedFileCluster 27 | .global initDisc 28 | .global wantToPatchDLDI 29 | .global argStart 30 | .global argSize 31 | .global dsiSD 32 | .global dsiMode 33 | .global clearMasterBright 34 | .global dsMode 35 | @--------------------------------------------------------------------------------- 36 | .align 4 37 | .arm 38 | @--------------------------------------------------------------------------------- 39 | _start: 40 | @--------------------------------------------------------------------------------- 41 | b startUp 42 | 43 | storedFileCluster: 44 | .word 0x0FFFFFFF @ default BOOT.NDS 45 | initDisc: 46 | .word 0x00000001 @ init the disc by default 47 | wantToPatchDLDI: 48 | .word 0x00000001 @ by default patch the DLDI section of the loaded NDS 49 | @ Used for passing arguments to the loaded app 50 | argStart: 51 | .word _end - _start 52 | argSize: 53 | .word 0x00000000 54 | dldiOffset: 55 | .word _dldi_start - _start 56 | dsiSD: 57 | .word 0 58 | dsiMode: 59 | .word 0 60 | clearMasterBright: 61 | .word 0 62 | dsMode: 63 | .word 0 64 | 65 | startUp: 66 | mov r0, #0x04000000 67 | mov r1, #0 68 | str r1, [r0,#0x208] @ REG_IME 69 | str r1, [r0,#0x210] @ REG_IE 70 | str r1, [r0,#0x218] @ REG_AUXIE 71 | 72 | mov r0, #0x12 @ Switch to IRQ Mode 73 | msr cpsr, r0 74 | ldr sp, =__sp_irq @ Set IRQ stack 75 | 76 | mov r0, #0x13 @ Switch to SVC Mode 77 | msr cpsr, r0 78 | ldr sp, =__sp_svc @ Set SVC stack 79 | 80 | mov r0, #0x1F @ Switch to System Mode 81 | msr cpsr, r0 82 | ldr sp, =__sp_usr @ Set user stack 83 | 84 | ldr r0, =__bss_start @ Clear BSS section to 0x00 85 | ldr r1, =__bss_end 86 | sub r1, r1, r0 87 | bl ClearMem 88 | 89 | mov r0, #0 @ int argc 90 | mov r1, #0 @ char *argv[] 91 | ldr r3, =main 92 | bl _blx_r3_stub @ jump to user code 93 | 94 | @ If the user ever returns, restart 95 | b _start 96 | 97 | @--------------------------------------------------------------------------------- 98 | _blx_r3_stub: 99 | @--------------------------------------------------------------------------------- 100 | bx r3 101 | 102 | @--------------------------------------------------------------------------------- 103 | @ Clear memory to 0x00 if length != 0 104 | @ r0 = Start Address 105 | @ r1 = Length 106 | @--------------------------------------------------------------------------------- 107 | ClearMem: 108 | @--------------------------------------------------------------------------------- 109 | mov r2, #3 @ Round down to nearest word boundary 110 | add r1, r1, r2 @ Shouldn't be needed 111 | bics r1, r1, r2 @ Clear 2 LSB (and set Z) 112 | bxeq lr @ Quit if copy size is 0 113 | 114 | mov r2, #0 115 | ClrLoop: 116 | stmia r0!, {r2} 117 | subs r1, r1, #4 118 | bne ClrLoop 119 | bx lr 120 | 121 | @--------------------------------------------------------------------------------- 122 | @ Copy memory if length != 0 123 | @ r1 = Source Address 124 | @ r2 = Dest Address 125 | @ r4 = Dest Address + Length 126 | @--------------------------------------------------------------------------------- 127 | CopyMemCheck: 128 | @--------------------------------------------------------------------------------- 129 | sub r3, r4, r2 @ Is there any data to copy? 130 | @--------------------------------------------------------------------------------- 131 | @ Copy memory 132 | @ r1 = Source Address 133 | @ r2 = Dest Address 134 | @ r3 = Length 135 | @--------------------------------------------------------------------------------- 136 | CopyMem: 137 | @--------------------------------------------------------------------------------- 138 | mov r0, #3 @ These commands are used in cases where 139 | add r3, r3, r0 @ the length is not a multiple of 4, 140 | bics r3, r3, r0 @ even though it should be. 141 | bxeq lr @ Length is zero, so exit 142 | CIDLoop: 143 | ldmia r1!, {r0} 144 | stmia r2!, {r0} 145 | subs r3, r3, #4 146 | bne CIDLoop 147 | bx lr 148 | 149 | @--------------------------------------------------------------------------------- 150 | .align 151 | .pool 152 | .end 153 | @--------------------------------------------------------------------------------- 154 | -------------------------------------------------------------------------------- /bootloader/source/sdmmc.c: -------------------------------------------------------------------------------- 1 | #ifndef NO_SDMMC 2 | #include 3 | #include "sdmmc.h" 4 | #include 5 | 6 | static struct mmcdevice deviceSD; 7 | 8 | //--------------------------------------------------------------------------------- 9 | int geterror(struct mmcdevice *ctx) { 10 | //--------------------------------------------------------------------------------- 11 | //if(ctx->error == 0x4) return -1; 12 | //else return 0; 13 | return (ctx->error << 29) >> 31; 14 | } 15 | 16 | 17 | //--------------------------------------------------------------------------------- 18 | void setTarget(struct mmcdevice *ctx) { 19 | //--------------------------------------------------------------------------------- 20 | sdmmc_mask16(REG_SDPORTSEL,0x3,(u16)ctx->devicenumber); 21 | setckl(ctx->clk); 22 | if (ctx->SDOPT == 0) { 23 | sdmmc_mask16(REG_SDOPT, 0, 0x8000); 24 | } else { 25 | sdmmc_mask16(REG_SDOPT, 0x8000, 0); 26 | } 27 | 28 | } 29 | 30 | 31 | //--------------------------------------------------------------------------------- 32 | void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args) { 33 | //--------------------------------------------------------------------------------- 34 | const bool getSDRESP = (cmd << 15) >> 31; 35 | u16 flags = (cmd << 15) >> 31; 36 | const bool readdata = cmd & 0x20000; 37 | const bool writedata = cmd & 0x40000; 38 | 39 | if(readdata || writedata) 40 | { 41 | flags |= TMIO_STAT0_DATAEND; 42 | } 43 | 44 | ctx->error = 0; 45 | while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working? 46 | sdmmc_write16(REG_SDIRMASK0,0); 47 | sdmmc_write16(REG_SDIRMASK1,0); 48 | sdmmc_write16(REG_SDSTATUS0,0); 49 | sdmmc_write16(REG_SDSTATUS1,0); 50 | sdmmc_mask16(REG_SDDATACTL32,0x1800,0x400); // Disable TX32RQ and RX32RDY IRQ. Clear fifo. 51 | sdmmc_write16(REG_SDCMDARG0,args &0xFFFF); 52 | sdmmc_write16(REG_SDCMDARG1,args >> 16); 53 | sdmmc_write16(REG_SDCMD,cmd &0xFFFF); 54 | 55 | u32 size = ctx->size; 56 | const u16 blkSize = sdmmc_read16(REG_SDBLKLEN32); 57 | u32 *rDataPtr32 = (u32*)ctx->rData; 58 | u8 *rDataPtr8 = ctx->rData; 59 | const u32 *tDataPtr32 = (u32*)ctx->tData; 60 | const u8 *tDataPtr8 = ctx->tData; 61 | 62 | bool rUseBuf = ( NULL != rDataPtr32 ); 63 | bool tUseBuf = ( NULL != tDataPtr32 ); 64 | 65 | u16 status0 = 0; 66 | while(1) 67 | { 68 | volatile u16 status1 = sdmmc_read16(REG_SDSTATUS1); 69 | #ifdef DATA32_SUPPORT 70 | volatile u16 ctl32 = sdmmc_read16(REG_SDDATACTL32); 71 | if((ctl32 & 0x100)) 72 | #else 73 | if((status1 & TMIO_STAT1_RXRDY)) 74 | #endif 75 | { 76 | if(readdata) 77 | { 78 | if(rUseBuf) 79 | { 80 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0); 81 | if(size >= blkSize) 82 | { 83 | #ifdef DATA32_SUPPORT 84 | if(!((u32)rDataPtr32 & 3)) 85 | { 86 | for(u32 i = 0; i < blkSize; i += 4) 87 | { 88 | *rDataPtr32++ = sdmmc_read32(REG_SDFIFO32); 89 | } 90 | } 91 | else 92 | { 93 | for(u32 i = 0; i < blkSize; i += 4) 94 | { 95 | u32 data = sdmmc_read32(REG_SDFIFO32); 96 | *rDataPtr8++ = data; 97 | *rDataPtr8++ = data >> 8; 98 | *rDataPtr8++ = data >> 16; 99 | *rDataPtr8++ = data >> 24; 100 | } 101 | } 102 | #else 103 | if(!((u32)rDataPtr16 & 1)) 104 | { 105 | for(u32 i = 0; i < blkSize; i += 4) 106 | { 107 | *rDataPtr16++ = sdmmc_read16(REG_SDFIFO); 108 | } 109 | } 110 | else 111 | { 112 | for(u32 i = 0; i < blkSize; i += 4) 113 | { 114 | u16 data = sdmmc_read16(REG_SDFIFO); 115 | *rDataPtr8++ = data; 116 | *rDataPtr8++ = data >> 8; 117 | } 118 | } 119 | #endif 120 | size -= blkSize; 121 | } 122 | } 123 | 124 | sdmmc_mask16(REG_SDDATACTL32, 0x800, 0); 125 | } 126 | } 127 | #ifdef DATA32_SUPPORT 128 | if(!(ctl32 & 0x200)) 129 | #else 130 | if((status1 & TMIO_STAT1_TXRQ)) 131 | #endif 132 | { 133 | if(writedata) 134 | { 135 | if(tUseBuf) 136 | { 137 | sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0); 138 | if(size >= blkSize) 139 | { 140 | #ifdef DATA32_SUPPORT 141 | if(!((u32)tDataPtr32 & 3)) 142 | { 143 | for(u32 i = 0; i < blkSize; i += 4) 144 | { 145 | sdmmc_write32(REG_SDFIFO32, *tDataPtr32++); 146 | } 147 | } 148 | else 149 | { 150 | for(u32 i = 0; i < blkSize; i += 4) 151 | { 152 | u32 data = *tDataPtr8++; 153 | data |= (u32)*tDataPtr8++ << 8; 154 | data |= (u32)*tDataPtr8++ << 16; 155 | data |= (u32)*tDataPtr8++ << 24; 156 | sdmmc_write32(REG_SDFIFO32, data); 157 | } 158 | } 159 | #else 160 | if(!((u32)tDataPtr16 & 1)) 161 | { 162 | for(u32 i = 0; i < blkSize; i += 2) 163 | { 164 | sdmmc_write16(REG_SDFIFO, *tDataPtr16++); 165 | } 166 | } 167 | else 168 | { 169 | for(u32 i = 0; i < blkSize; i += 2) 170 | { 171 | u16 data = *tDataPtr8++; 172 | data |= (u16)(*tDataPtr8++ << 8); 173 | sdmmc_write16(REG_SDFIFO, data); 174 | } 175 | } 176 | #endif 177 | size -= blkSize; 178 | } 179 | } 180 | 181 | sdmmc_mask16(REG_SDDATACTL32, 0x1000, 0); 182 | } 183 | } 184 | if(status1 & TMIO_MASK_GW) 185 | { 186 | ctx->error |= 4; 187 | break; 188 | } 189 | 190 | if(!(status1 & TMIO_STAT1_CMD_BUSY)) 191 | { 192 | status0 = sdmmc_read16(REG_SDSTATUS0); 193 | if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND) 194 | { 195 | ctx->error |= 0x1; 196 | } 197 | if(status0 & TMIO_STAT0_DATAEND) 198 | { 199 | ctx->error |= 0x2; 200 | } 201 | 202 | if((status0 & flags) == flags) 203 | break; 204 | } 205 | } 206 | ctx->stat0 = sdmmc_read16(REG_SDSTATUS0); 207 | ctx->stat1 = sdmmc_read16(REG_SDSTATUS1); 208 | sdmmc_write16(REG_SDSTATUS0,0); 209 | sdmmc_write16(REG_SDSTATUS1,0); 210 | 211 | if(getSDRESP != 0) 212 | { 213 | ctx->ret[0] = (u32)(sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16)); 214 | ctx->ret[1] = (u32)(sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16)); 215 | ctx->ret[2] = (u32)(sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16)); 216 | ctx->ret[3] = (u32)(sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16)); 217 | } 218 | } 219 | 220 | //--------------------------------------------------------------------------------- 221 | static u32 calcSDSize(u8* csd, int type) { 222 | //--------------------------------------------------------------------------------- 223 | u32 result = 0; 224 | if (type == -1) type = csd[14] >> 6; 225 | switch (type) { 226 | case 0: 227 | { 228 | u32 block_len = csd[9] & 0xf; 229 | block_len = 1 << block_len; 230 | u32 mult = (csd[4] >> 7) | ((csd[5] & 3) << 1); 231 | mult = 1 << (mult + 2); 232 | result = csd[8] & 3; 233 | result = (result << 8) | csd[7]; 234 | result = (result << 2) | (csd[6] >> 6); 235 | result = (result + 1) * mult * block_len / 512; 236 | } 237 | break; 238 | case 1: 239 | result = csd[7] & 0x3f; 240 | result = (result << 8) | csd[6]; 241 | result = (result << 8) | csd[5]; 242 | result = (result + 1) * 1024; 243 | break; 244 | } 245 | return result; 246 | } 247 | 248 | //--------------------------------------------------------------------------------- 249 | void sdmmc_controller_init(bool force) { 250 | //--------------------------------------------------------------------------------- 251 | deviceSD.isSDHC = 0; 252 | deviceSD.SDOPT = 0; 253 | deviceSD.res = 0; 254 | deviceSD.initarg = 0; 255 | deviceSD.clk = 0x80; 256 | deviceSD.devicenumber = 0; 257 | 258 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xF7FFu; 259 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xEFFFu; 260 | #ifdef DATA32_SUPPORT 261 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; 262 | #else 263 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) |= 0x402u; 264 | #endif 265 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL) = (*(vu16*)(SDMMC_BASE + REG_SDDATACTL) & 0xFFDD) | 2; 266 | #ifdef DATA32_SUPPORT 267 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFFu; 268 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDFu; 269 | *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 512; 270 | #else 271 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL32) &= 0xFFFDu; 272 | *(vu16*)(SDMMC_BASE + REG_SDDATACTL) &= 0xFFDDu; 273 | *(vu16*)(SDMMC_BASE + REG_SDBLKLEN32) = 0; 274 | #endif 275 | *(vu16*)(SDMMC_BASE + REG_SDBLKCOUNT32) = 1; 276 | *(vu16*)(SDMMC_BASE + REG_SDRESET) &= 0xFFFEu; 277 | *(vu16*)(SDMMC_BASE + REG_SDRESET) |= 1u; 278 | *(vu16*)(SDMMC_BASE + REG_SDIRMASK0) |= TMIO_MASK_ALL; 279 | *(vu16*)(SDMMC_BASE + REG_SDIRMASK1) |= TMIO_MASK_ALL>>16; 280 | *(vu16*)(SDMMC_BASE + 0x0fc) |= 0xDBu; //SDCTL_RESERVED7 281 | *(vu16*)(SDMMC_BASE + 0x0fe) |= 0xDBu; //SDCTL_RESERVED8 282 | *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; 283 | #ifdef DATA32_SUPPORT 284 | *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x20; 285 | *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EE; 286 | #else 287 | *(vu16*)(SDMMC_BASE + REG_SDCLKCTL) = 0x40; //Nintendo sets this to 0x20 288 | *(vu16*)(SDMMC_BASE + REG_SDOPT) = 0x40EB; //Nintendo sets this to 0x40EE 289 | #endif 290 | *(vu16*)(SDMMC_BASE + REG_SDPORTSEL) &= 0xFFFCu; 291 | *(vu16*)(SDMMC_BASE + REG_SDBLKLEN) = 512; 292 | *(vu16*)(SDMMC_BASE + REG_SDSTOP) = 0; 293 | 294 | setTarget(&deviceSD); 295 | } 296 | 297 | //--------------------------------------------------------------------------------- 298 | int sdmmc_sdcard_init() { 299 | //--------------------------------------------------------------------------------- 300 | // We need to send at least 74 clock pulses. 301 | setTarget(&deviceSD); 302 | swiDelay(0x1980); // ~75-76 clocks 303 | 304 | // card reset 305 | sdmmc_send_command(&deviceSD,0,0); 306 | 307 | // CMD8 0x1AA 308 | sdmmc_send_command(&deviceSD,0x10408,0x1AA); 309 | u32 temp = (deviceSD.error & 0x1) << 0x1E; 310 | 311 | u32 temp2 = 0; 312 | do { 313 | do { 314 | // CMD55 315 | sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); 316 | // ACMD41 317 | sdmmc_send_command(&deviceSD,0x10769,0x00FF8000 | temp); 318 | temp2 = 1; 319 | } while ( !(deviceSD.error & 1) ); 320 | 321 | } while((deviceSD.ret[0] & 0x80000000) == 0); 322 | 323 | if(!((deviceSD.ret[0] >> 30) & 1) || !temp) 324 | temp2 = 0; 325 | 326 | deviceSD.isSDHC = temp2; 327 | 328 | sdmmc_send_command(&deviceSD,0x10602,0); 329 | if (deviceSD.error & 0x4) return -1; 330 | 331 | sdmmc_send_command(&deviceSD,0x10403,0); 332 | if (deviceSD.error & 0x4) return -2; 333 | deviceSD.initarg = deviceSD.ret[0] >> 0x10; 334 | 335 | sdmmc_send_command(&deviceSD,0x10609,deviceSD.initarg << 0x10); 336 | if (deviceSD.error & 0x4) return -3; 337 | 338 | // Command Class 10 support 339 | const bool cmd6Supported = ((u8*)deviceSD.ret)[10] & 0x40; 340 | deviceSD.total_size = calcSDSize((u8*)&deviceSD.ret[0],-1); 341 | setckl(0x201); // 16.756991 MHz 342 | 343 | sdmmc_send_command(&deviceSD,0x10507,deviceSD.initarg << 0x10); 344 | if (deviceSD.error & 0x4) return -4; 345 | 346 | // CMD55 347 | sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); 348 | if (deviceSD.error & 0x4) return -5; 349 | 350 | // ACMD42 351 | sdmmc_send_command(&deviceSD,0x1076A,0x0); 352 | if (deviceSD.error & 0x4) return -6; 353 | 354 | // CMD55 355 | sdmmc_send_command(&deviceSD,0x10437,deviceSD.initarg << 0x10); 356 | if (deviceSD.error & 0x4) return -7; 357 | 358 | deviceSD.SDOPT = 1; 359 | sdmmc_send_command(&deviceSD,0x10446,0x2); 360 | if (deviceSD.error & 0x4) return -8; 361 | sdmmc_mask16(REG_SDOPT, 0x8000, 0); // Switch to 4 bit mode. 362 | 363 | // TODO: CMD6 to switch to high speed mode. 364 | if(cmd6Supported) 365 | { 366 | sdmmc_write16(REG_SDSTOP,0); 367 | sdmmc_write16(REG_SDBLKLEN32,64); 368 | sdmmc_write16(REG_SDBLKLEN,64); 369 | deviceSD.rData = NULL; 370 | deviceSD.size = 64; 371 | sdmmc_send_command(&deviceSD,0x31C06,0x80FFFFF1); 372 | sdmmc_write16(REG_SDBLKLEN,512); 373 | if(deviceSD.error & 0x4) return -9; 374 | 375 | deviceSD.clk = 0x200; // 33.513982 MHz 376 | setckl(0x200); 377 | } 378 | else deviceSD.clk = 0x201; // 16.756991 MHz 379 | 380 | sdmmc_send_command(&deviceSD,0x1040D,deviceSD.initarg << 0x10); 381 | if (deviceSD.error & 0x4) return -9; 382 | 383 | sdmmc_send_command(&deviceSD,0x10410,0x200); 384 | if (deviceSD.error & 0x4) return -10; 385 | 386 | return 0; 387 | 388 | } 389 | 390 | //--------------------------------------------------------------------------------- 391 | int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out) { 392 | //--------------------------------------------------------------------------------- 393 | if (deviceSD.isSDHC == 0) 394 | sector_no <<= 9; 395 | setTarget(&deviceSD); 396 | sdmmc_write16(REG_SDSTOP,0x100); 397 | 398 | #ifdef DATA32_SUPPORT 399 | sdmmc_write16(REG_SDBLKCOUNT32,numsectors); 400 | sdmmc_write16(REG_SDBLKLEN32,0x200); 401 | #endif 402 | 403 | sdmmc_write16(REG_SDBLKCOUNT,numsectors); 404 | deviceSD.rData = out; 405 | deviceSD.size = numsectors << 9; 406 | sdmmc_send_command(&deviceSD,0x33C12,sector_no); 407 | return geterror(&deviceSD); 408 | } 409 | #endif -------------------------------------------------------------------------------- /bootloader/source/sdmmc.h: -------------------------------------------------------------------------------- 1 | #ifndef __SDMMC_H__ 2 | #define __SDMMC_H__ 3 | 4 | #include 5 | 6 | #define DATA32_SUPPORT 7 | 8 | #define SDMMC_BASE 0x04004800 9 | 10 | 11 | #define REG_SDCMD 0x00 12 | #define REG_SDPORTSEL 0x02 13 | #define REG_SDCMDARG 0x04 14 | #define REG_SDCMDARG0 0x04 15 | #define REG_SDCMDARG1 0x06 16 | #define REG_SDSTOP 0x08 17 | #define REG_SDRESP 0x0c 18 | #define REG_SDBLKCOUNT 0x0a 19 | 20 | #define REG_SDRESP0 0x0c 21 | #define REG_SDRESP1 0x0e 22 | #define REG_SDRESP2 0x10 23 | #define REG_SDRESP3 0x12 24 | #define REG_SDRESP4 0x14 25 | #define REG_SDRESP5 0x16 26 | #define REG_SDRESP6 0x18 27 | #define REG_SDRESP7 0x1a 28 | 29 | #define REG_SDSTATUS0 0x1c 30 | #define REG_SDSTATUS1 0x1e 31 | 32 | #define REG_SDIRMASK0 0x20 33 | #define REG_SDIRMASK1 0x22 34 | #define REG_SDCLKCTL 0x24 35 | 36 | #define REG_SDBLKLEN 0x26 37 | #define REG_SDOPT 0x28 38 | #define REG_SDFIFO 0x30 39 | 40 | #define REG_SDDATACTL 0xd8 41 | #define REG_SDRESET 0xe0 42 | #define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not? 43 | 44 | #define REG_SDDATACTL32 0x100 45 | #define REG_SDBLKLEN32 0x104 46 | #define REG_SDBLKCOUNT32 0x108 47 | #define REG_SDFIFO32 0x10C 48 | 49 | #define REG_CLK_AND_WAIT_CTL 0x138 50 | #define REG_RESET_SDIO 0x1e0 51 | //The below defines are from linux kernel drivers/mmc tmio_mmc.h. 52 | /* Definitions for values the CTRL_STATUS register can take. */ 53 | #define TMIO_STAT0_CMDRESPEND 0x0001 54 | #define TMIO_STAT0_DATAEND 0x0004 55 | #define TMIO_STAT0_CARD_REMOVE 0x0008 56 | #define TMIO_STAT0_CARD_INSERT 0x0010 57 | #define TMIO_STAT0_SIGSTATE 0x0020 58 | #define TMIO_STAT0_WRPROTECT 0x0080 59 | #define TMIO_STAT0_CARD_REMOVE_A 0x0100 60 | #define TMIO_STAT0_CARD_INSERT_A 0x0200 61 | #define TMIO_STAT0_SIGSTATE_A 0x0400 62 | 63 | #define TMIO_STAT1_CMD_IDX_ERR 0x0001 64 | #define TMIO_STAT1_CRCFAIL 0x0002 65 | #define TMIO_STAT1_STOPBIT_ERR 0x0004 66 | #define TMIO_STAT1_DATATIMEOUT 0x0008 67 | #define TMIO_STAT1_RXOVERFLOW 0x0010 68 | #define TMIO_STAT1_TXUNDERRUN 0x0020 69 | #define TMIO_STAT1_CMDTIMEOUT 0x0040 70 | #define TMIO_STAT1_RXRDY 0x0100 71 | #define TMIO_STAT1_TXRQ 0x0200 72 | #define TMIO_STAT1_ILL_FUNC 0x2000 73 | #define TMIO_STAT1_CMD_BUSY 0x4000 74 | #define TMIO_STAT1_ILL_ACCESS 0x8000 75 | 76 | #define SDMC_NORMAL 0x00000000 77 | #define SDMC_ERR_COMMAND 0x00000001 78 | #define SDMC_ERR_CRC 0x00000002 79 | #define SDMC_ERR_END 0x00000004 80 | #define SDMC_ERR_TIMEOUT 0x00000008 81 | #define SDMC_ERR_FIFO_OVF 0x00000010 82 | #define SDMC_ERR_FIFO_UDF 0x00000020 83 | #define SDMC_ERR_WP 0x00000040 84 | #define SDMC_ERR_ABORT 0x00000080 85 | #define SDMC_ERR_FPGA_TIMEOUT 0x00000100 86 | #define SDMC_ERR_PARAM 0x00000200 87 | #define SDMC_ERR_R1_STATUS 0x00000800 88 | #define SDMC_ERR_NUM_WR_SECTORS 0x00001000 89 | #define SDMC_ERR_RESET 0x00002000 90 | #define SDMC_ERR_ILA 0x00004000 91 | #define SDMC_ERR_INFO_DETECT 0x00008000 92 | 93 | #define SDMC_STAT_ERR_UNKNOWN 0x00080000 94 | #define SDMC_STAT_ERR_CC 0x00100000 95 | #define SDMC_STAT_ERR_ECC_FAILED 0x00200000 96 | #define SDMC_STAT_ERR_CRC 0x00800000 97 | #define SDMC_STAT_ERR_OTHER 0xf9c70008 98 | 99 | #define TMIO_MASK_ALL 0x837f031d 100 | 101 | #define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \ 102 | TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR) 103 | 104 | #define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND) 105 | #define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND) 106 | 107 | typedef struct mmcdevice { 108 | u8* rData; 109 | const u8* tData; 110 | u32 size; 111 | u32 startOffset; 112 | u32 endOffset; 113 | u32 error; 114 | u16 stat0; 115 | u16 stat1; 116 | u32 ret[4]; 117 | u32 initarg; 118 | u32 isSDHC; 119 | u32 clk; 120 | u32 SDOPT; 121 | u32 devicenumber; 122 | u32 total_size; //size in sectors of the device 123 | u32 res; 124 | } mmcdevice; 125 | 126 | enum { 127 | MMC_DEVICE_SDCARD, 128 | MMC_DEVICE_NAND, 129 | }; 130 | 131 | void sdmmc_controller_init(bool force_init); 132 | void sdmmc_initirq(); 133 | int sdmmc_cardinserted(); 134 | 135 | int sdmmc_sdcard_init(); 136 | int sdmmc_nand_init(); 137 | void sdmmc_get_cid(int devicenumber, u32 *cid); 138 | 139 | static inline void sdmmc_nand_cid( u32 *cid) { 140 | sdmmc_get_cid(MMC_DEVICE_NAND,cid); 141 | } 142 | 143 | static inline void sdmmc_sdcard_cid( u32 *cid) { 144 | sdmmc_get_cid(MMC_DEVICE_SDCARD,cid); 145 | } 146 | 147 | int sdmmc_sdcard_readsectors(u32 sector_no, u32 numsectors, void *out); 148 | int sdmmc_sdcard_writesectors(u32 sector_no, u32 numsectors, void *in); 149 | int sdmmc_nand_readsectors(u32 sector_no, u32 numsectors, void *out); 150 | int sdmmc_nand_writesectors(u32 sector_no, u32 numsectors, void *in); 151 | 152 | extern u32 sdmmc_cid[]; 153 | extern int sdmmc_curdevice; 154 | 155 | //--------------------------------------------------------------------------------- 156 | static inline u16 sdmmc_read16(u16 reg) { 157 | //--------------------------------------------------------------------------------- 158 | return *(vu16*)(SDMMC_BASE + reg); 159 | } 160 | 161 | //--------------------------------------------------------------------------------- 162 | static inline void sdmmc_write16(u16 reg, u16 val) { 163 | //--------------------------------------------------------------------------------- 164 | *(vu16*)(SDMMC_BASE + reg) = val; 165 | } 166 | 167 | //--------------------------------------------------------------------------------- 168 | static inline u32 sdmmc_read32(u16 reg) { 169 | //--------------------------------------------------------------------------------- 170 | return *(vu32*)(SDMMC_BASE + reg); 171 | } 172 | 173 | //--------------------------------------------------------------------------------- 174 | static inline void sdmmc_write32(u16 reg, u32 val) { 175 | //--------------------------------------------------------------------------------- 176 | *(vu32*)(SDMMC_BASE + reg) = val; 177 | } 178 | 179 | //--------------------------------------------------------------------------------- 180 | static inline void sdmmc_mask16(u16 reg, u16 clear, u16 set) { 181 | //--------------------------------------------------------------------------------- 182 | u16 val = sdmmc_read16(reg); 183 | val &= ~clear; 184 | val |= set; 185 | sdmmc_write16(reg, val); 186 | } 187 | 188 | 189 | //--------------------------------------------------------------------------------- 190 | static inline void setckl(u32 data) { 191 | //--------------------------------------------------------------------------------- 192 | sdmmc_mask16(REG_SDCLKCTL, 0x100, 0); 193 | sdmmc_mask16(REG_SDCLKCTL, 0x2FF, data & 0x2FF); 194 | sdmmc_mask16(REG_SDCLKCTL, 0x0, 0x100); 195 | } 196 | 197 | #endif 198 | -------------------------------------------------------------------------------- /bootstub/Makefile: -------------------------------------------------------------------------------- 1 | include $(DEVKITARM)/base_tools 2 | 3 | TARGET := bootstub 4 | 5 | ../data/$(TARGET).bin: $(TARGET).elf 6 | $(OBJCOPY) -O binary $< $@ 7 | 8 | $(TARGET).elf: $(TARGET).s Makefile 9 | $(CC) -Wl,-Ttext=0 -x assembler-with-cpp -nostartfiles -nostdlib $(TARGET).s -o $@ 10 | 11 | 12 | clean: 13 | rm -f $(TARGET).elf $(TARGET).bin 14 | -------------------------------------------------------------------------------- /bootstub/bootstub.s: -------------------------------------------------------------------------------- 1 | /*----------------------------------------------------------------- 2 | 3 | Copyright (C) 2010 Dave "WinterMute" Murphy 4 | 5 | This program is free software; you can redistribute it and/or 6 | modify it under the terms of the GNU General Public License 7 | as published by the Free Software Foundation; either version 2 8 | of the License, or (at your option) any later version. 9 | 10 | This program is distributed in the hope that it will be useful, 11 | but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13 | GNU General Public License for more details. 14 | 15 | You should have received a copy of the GNU General Public License 16 | along with this program; if not, write to the Free Software 17 | Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | 19 | ------------------------------------------------------------------*/ 20 | .global _start 21 | 22 | //----------------------------------------------------------------- 23 | _start: 24 | //----------------------------------------------------------------- 25 | .ascii "bootstub" 26 | .word hook7from9 - _start 27 | .word hook9from7 - _start 28 | _loader_size: 29 | .word 0 30 | 31 | .arch armv4t 32 | .cpu arm7tdmi 33 | 34 | //----------------------------------------------------------------- 35 | hook9from7: 36 | //----------------------------------------------------------------- 37 | ldr r0, arm9bootaddr 38 | adr r1, hook7from9 39 | str r1, [r0] 40 | 41 | mov r3, #0x04000000 42 | ldr r0, resetcode 43 | str r0, [r3, #0x188] 44 | add r3, r3, #0x180 45 | 46 | adr r0, waitcode_start 47 | ldr r1, arm7base 48 | adr r2, waitcode_end 49 | 1: ldr r4, [r0],#4 50 | str r4, [r1],#4 51 | cmp r2, r0 52 | bne 1b 53 | 54 | ldr r1, arm7base 55 | bx r1 56 | 57 | //----------------------------------------------------------------- 58 | waitcode_start: 59 | //----------------------------------------------------------------- 60 | push {lr} 61 | mov r2, #1 62 | bl waitsync 63 | 64 | mov r0, #0x100 65 | strh r0, [r3] 66 | 67 | mov r2, #0 68 | bl waitsync 69 | 70 | mov r0, #0 71 | strh r0, [r3] 72 | pop {lr} 73 | 74 | bx lr 75 | 76 | waitsync: 77 | ldrh r0, [r3] 78 | and r0, r0, #0x000f 79 | cmp r0, r2 80 | bne waitsync 81 | bx lr 82 | waitcode_end: 83 | 84 | arm7base: 85 | .word 0x037f8000 86 | arm7bootaddr: 87 | .word 0x02FFFE34 88 | arm9bootaddr: 89 | .word 0x02FFFE24 90 | tcmpudisable: 91 | .word 0x2078 92 | 93 | resetcode: 94 | .word 0x0c04000c 95 | 96 | //----------------------------------------------------------------- 97 | hook7from9: 98 | //----------------------------------------------------------------- 99 | mov r12, #0x04000000 100 | strb r12, [r12,#0x208] 101 | 102 | .arch armv5te 103 | .cpu arm946e-s 104 | 105 | ldr r1, tcmpudisable @ disable TCM and protection unit 106 | mcr p15, 0, r1, c1, c0 107 | 108 | @ Disable cache 109 | mov r0, #0 110 | mcr p15, 0, r0, c7, c5, 0 @ Instruction cache 111 | mcr p15, 0, r0, c7, c6, 0 @ Data cache 112 | mcr p15, 0, r0, c3, c0, 0 @ write buffer 113 | 114 | @ Wait for write buffer to empty 115 | mcr p15, 0, r0, c7, c10, 4 116 | 117 | add r3, r12, #0x180 @ r3 = 4000180 118 | 119 | mov r0,#0x80 120 | strb r0,[r3,#0x242-0x180] 121 | 122 | adr r0, _loader 123 | ldr r2, _loader_size 124 | mov r1, #0x06800000 125 | add r1, r1, #0x40000 126 | add r2, r0, r2 127 | _copyloader: 128 | ldr r4, [r0], #4 129 | str r4, [r1], #4 130 | cmp r0, r2 131 | blt _copyloader 132 | 133 | mov r0,#0x82 134 | strb r0,[r3,#0x242-0x180] 135 | 136 | ldrh r0,[r3,#0x204-0x180] 137 | orr r0,r0,#(1<<11) | (1<<7) 138 | strh r0,[r3,#0x204-0x180] 139 | 140 | 141 | ldr r0, arm7bootaddr 142 | mov r1, #0x06000000 143 | str r1, [r0] 144 | 145 | ldr r0, resetcode 146 | str r0, [r12, #0x188] 147 | 148 | mov r2, #1 149 | bl waitsync 150 | 151 | mov r0, #0x100 152 | strh r0, [r3] 153 | 154 | mov r2, #0 155 | bl waitsync 156 | 157 | mov r0, #0 158 | strh r0, [r3] 159 | 160 | // set up and enter passme loop 161 | 162 | ldr r0,arm9branchaddr 163 | ldr r1,branchinst 164 | str r1,[r0] 165 | str r0,[r0,#0x20] 166 | 167 | bx r0 168 | 169 | branchinst: 170 | .word 0xE59FF018 171 | 172 | arm9branchaddr: 173 | .word 0x02fffe04 174 | 175 | 176 | _loader: 177 | -------------------------------------------------------------------------------- /clean and compile.bat: -------------------------------------------------------------------------------- 1 | make clean 2 | make 3 | pause 4 | -------------------------------------------------------------------------------- /compile.bat: -------------------------------------------------------------------------------- 1 | make 2 | pause 3 | -------------------------------------------------------------------------------- /icon.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlameKat53/ButtonBoot/962a79a05eee28502dfa964855b6bd5b87a6d8e3/icon.bmp -------------------------------------------------------------------------------- /make_cia: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/FlameKat53/ButtonBoot/962a79a05eee28502dfa964855b6bd5b87a6d8e3/make_cia --------------------------------------------------------------------------------