Compare commits
229 Commits
v9.0-joyco
...
v10.1.2
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
44cd3928fb | ||
|
|
8c54613e44 | ||
|
|
7dfa83b8c0 | ||
|
|
b551061264 | ||
|
|
3e228c33c9 | ||
|
|
2b23be8f44 | ||
|
|
ced78cb072 | ||
|
|
fb17850c3d | ||
|
|
7f7c4852cc | ||
|
|
f334e3b951 | ||
|
|
9d62995799 | ||
|
|
1d8b793cf7 | ||
|
|
33431cb939 | ||
|
|
e677e0142c | ||
|
|
b313a4aa2f | ||
|
|
37c5c6f049 | ||
|
|
a6d92ed8fe | ||
|
|
eb37ac4142 | ||
|
|
a0d4b96915 | ||
|
|
31891efbca | ||
|
|
58f3edda12 | ||
|
|
4a655384e2 | ||
|
|
0543c208fd | ||
|
|
0e834ec004 | ||
|
|
26454dc832 | ||
|
|
5c16836626 | ||
|
|
67e28b2a82 | ||
|
|
c2a2893b5c | ||
|
|
68b670f94f | ||
|
|
5a83a46423 | ||
|
|
8785fd0236 | ||
|
|
a67e8e60c6 | ||
|
|
c7551a731c | ||
|
|
d9c5437902 | ||
|
|
55d51217d8 | ||
|
|
11c9caaf13 | ||
|
|
c4711e5e3a | ||
|
|
d34f0a8eca | ||
|
|
8233d4e226 | ||
|
|
ca49956219 | ||
|
|
5edfbfc1f7 | ||
|
|
dfd50d9d75 | ||
|
|
1946941340 | ||
|
|
31dae90dcd | ||
|
|
da8df54649 | ||
|
|
0e1415299a | ||
|
|
93f770888d | ||
|
|
0886b10619 | ||
|
|
e8493d18c5 | ||
|
|
60a8bf56c6 | ||
|
|
c95b59c72e | ||
|
|
7e14c83bdd | ||
|
|
a2e46919c1 | ||
|
|
a4befc29c8 | ||
|
|
93e87284aa | ||
|
|
236dbb043c | ||
|
|
77f0295a04 | ||
|
|
c3b97999f5 | ||
|
|
3061001fb1 | ||
|
|
0bc51d5c34 | ||
|
|
c913de1e67 | ||
|
|
c9a578734e | ||
|
|
37544a0eb9 | ||
|
|
3ad314a5ac | ||
|
|
58a6a25eb3 | ||
|
|
6ed93a1f09 | ||
|
|
76dbdf45cf | ||
|
|
d4e1da0174 | ||
|
|
fde3b70d03 | ||
|
|
8c03702c7d | ||
|
|
31c6ead2ad | ||
|
|
454fa16b3a | ||
|
|
301e84f1ca | ||
|
|
69634fdbd5 | ||
|
|
10e823a9d5 | ||
|
|
f4851cd533 | ||
|
|
39287d43e3 | ||
|
|
09b2bf5fb1 | ||
|
|
e989309771 | ||
|
|
d989c45c3d | ||
|
|
84c5cf0661 | ||
|
|
648541bb1f | ||
|
|
2cf04e8a83 | ||
|
|
af10782500 | ||
|
|
fe0e5ae83d | ||
|
|
8e4af5c823 | ||
|
|
570a8d5222 | ||
|
|
2c8a1eb5c6 | ||
|
|
23c40aeb8e | ||
|
|
c7c832a0dd | ||
|
|
6423d0c1b3 | ||
|
|
8b56098d64 | ||
|
|
2927bd5aa3 | ||
|
|
d357db25f2 | ||
|
|
9b3cc5391b | ||
|
|
54eeb97b24 | ||
|
|
593f50de91 | ||
|
|
85af8d9fa4 | ||
|
|
58ff96dc83 | ||
|
|
a5803d1b62 | ||
|
|
eddb0988a0 | ||
|
|
5d3585a33d | ||
|
|
4285736286 | ||
|
|
32b8cf6172 | ||
|
|
3e724e88a8 | ||
|
|
687dfddd9f | ||
|
|
90a43089ba | ||
|
|
1e0baeb30e | ||
|
|
353f7d1705 | ||
|
|
f5f3764f99 | ||
|
|
eef22f8701 | ||
|
|
9e1a9f2842 | ||
|
|
0b33134f6c | ||
|
|
5c4d6c68b2 | ||
|
|
89e42a457c | ||
|
|
17ca09346d | ||
|
|
54de645dc3 | ||
|
|
da6c02068b | ||
|
|
06bcb39721 | ||
|
|
2b31a4ab5c | ||
|
|
3b4ef682fe | ||
|
|
eab9a31dff | ||
|
|
ff86ed2e77 | ||
|
|
2fe1169423 | ||
|
|
4c9fe186d7 | ||
|
|
e11cc090b2 | ||
|
|
763a1de8d3 | ||
|
|
e57b546dd4 | ||
|
|
bd670cf87c | ||
|
|
1e0996c395 | ||
|
|
5f295c4227 | ||
|
|
4f699ccb81 | ||
|
|
70757e564d | ||
|
|
af822e5af5 | ||
|
|
63736d7873 | ||
|
|
fb800bd4c9 | ||
|
|
219f38169f | ||
|
|
c688600d33 | ||
|
|
ea14d8a186 | ||
|
|
cd18b85632 | ||
|
|
22ec031495 | ||
|
|
43b998d37d | ||
|
|
127101a683 | ||
|
|
5955ca6957 | ||
|
|
dcddcfc94d | ||
|
|
1453d9adac | ||
|
|
ef034a87d4 | ||
|
|
e688ec9257 | ||
|
|
ae1f85d341 | ||
|
|
7177799021 | ||
|
|
1041d7c438 | ||
|
|
e57abad52f | ||
|
|
74bbfb95d3 | ||
|
|
8345f31c2a | ||
|
|
d44055d232 | ||
|
|
4a431b8fdf | ||
|
|
e2ed200509 | ||
|
|
4e5f6e1eff | ||
|
|
474eb3001b | ||
|
|
f72d99d9b0 | ||
|
|
a9a569c79d | ||
|
|
68b8c99ad0 | ||
|
|
d8c6f94887 | ||
|
|
8b51141f54 | ||
|
|
0195ab34e9 | ||
|
|
0bb82feb81 | ||
|
|
6199f598e5 | ||
|
|
b92406afe2 | ||
|
|
244409fc98 | ||
|
|
f3b2a6c30d | ||
|
|
a65f7fbf88 | ||
|
|
35ad240018 | ||
|
|
e64f267e4c | ||
|
|
d28e961adc | ||
|
|
e6b7dc1dc5 | ||
|
|
9e7e967a5f | ||
|
|
33d40b491e | ||
|
|
7cb50d38b9 | ||
|
|
d6d440a47e | ||
|
|
52cd950ca6 | ||
|
|
9fad2dff21 | ||
|
|
4b40dd52f4 | ||
|
|
6bd7070d38 | ||
|
|
0c9365bcb7 | ||
|
|
c0bd69309a | ||
|
|
55bd62d7a9 | ||
|
|
020236742f | ||
|
|
faeb0d9395 | ||
|
|
b05f993221 | ||
|
|
e796abb155 | ||
|
|
3d2c12cf09 | ||
|
|
8ff5111e30 | ||
|
|
673ec9fc51 | ||
|
|
a7100a1e7f | ||
|
|
710ad11819 | ||
|
|
f718297591 | ||
|
|
1c7b55ee1e | ||
|
|
f437d92374 | ||
|
|
47916b2831 | ||
|
|
0791aabbf8 | ||
|
|
bd15f51af3 | ||
|
|
932ed4222f | ||
|
|
1052e04679 | ||
|
|
3903ac6409 | ||
|
|
53622d777b | ||
|
|
2219b19d5f | ||
|
|
bc06b17823 | ||
|
|
89cc6ede1a | ||
|
|
dd6e071dde | ||
|
|
2127271b33 | ||
|
|
1600171ffa | ||
|
|
7f7a9fab2d | ||
|
|
b15d86f31d | ||
|
|
89a3dc8643 | ||
|
|
3477beb05c | ||
|
|
8447c209a7 | ||
|
|
e78f706c1a | ||
|
|
f776c56cd4 | ||
|
|
dc195dffad | ||
|
|
74a0b2feae | ||
|
|
71039fc248 | ||
|
|
d0306609c3 | ||
|
|
d13cde3d7b | ||
|
|
38f54fd2b6 | ||
|
|
b5728e9c11 | ||
|
|
a2177c0510 | ||
|
|
356a94cc2e | ||
|
|
9d507e046c | ||
|
|
47c47f967a |
1
.gitattributes
vendored
Normal file
1
.gitattributes
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
*.xml text eol=lf
|
||||||
@@ -1,3 +1,8 @@
|
|||||||
|
---
|
||||||
|
name: Bug report
|
||||||
|
about: Use this to report bugs you encounter with Luma3DS. Make sure you upload the crash dumps if Luma3DS crashes.
|
||||||
|
---
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
-- THIS IS NOT A SUPPORT FORUM! For support go here:
|
-- THIS IS NOT A SUPPORT FORUM! For support go here:
|
||||||
-- Nintendo Homebrew: https://discord.gg/MjzatM8
|
-- Nintendo Homebrew: https://discord.gg/MjzatM8
|
||||||
@@ -6,7 +11,7 @@
|
|||||||
--
|
--
|
||||||
-- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
|
-- Also check the Wiki (https://github.com/AuroraWright/Luma3DS/wiki) before making an issue.
|
||||||
--
|
--
|
||||||
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.guide/troubleshooting
|
-- For GBA/DSiWare/DS/AGB_FIRM/TWL_FIRM problems: https://3ds.hacks.guide/troubleshooting
|
||||||
-- If you're using an emu/redNAND try installing anything on it to sysNAND.
|
-- If you're using an emu/redNAND try installing anything on it to sysNAND.
|
||||||
-- Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
|
-- Please make sure to read "Enable game patching" https://github.com/AuroraWright/Luma3DS/wiki/Options-and-usage before posting any issues about the "Enable game patching" option(s).
|
||||||
--
|
--
|
||||||
@@ -20,7 +25,8 @@
|
|||||||
|
|
||||||
**SysNAND version (+emu/redNAND version if applicable):**
|
**SysNAND version (+emu/redNAND version if applicable):**
|
||||||
|
|
||||||
[e.g. 11.6.0-39U SysNAND, 11.6.0-39J EmuNAND]
|
[e.g. 11.13.0-45U SysNAND, 11.13.0-45E EmuNAND]
|
||||||
|
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
|
||||||
|
|
||||||
**Entrypoint (How/what you're using to boot Luma3DS):**
|
**Entrypoint (How/what you're using to boot Luma3DS):**
|
||||||
|
|
||||||
@@ -28,18 +34,19 @@
|
|||||||
|
|
||||||
**Luma3DS version:**
|
**Luma3DS version:**
|
||||||
|
|
||||||
[e.g. 8.1.1 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/9570e6cbeca53128433abbf5e3473cb8a07fe69e]
|
[e.g. v10.1.2 stable or if using nightly/hourly specify the commit like this https://github.com/AuroraWright/Luma3DS/commit/0543c208fd154e6326ea5da8cbf66ffcbdef010c]
|
||||||
<!--You can check which version you're on in System Settings. It will be on the bottom right of the top screen.-->
|
|
||||||
|
|
||||||
|
|
||||||
**Luma3DS configuration/options:**
|
**Luma3DS configuration/options:**
|
||||||
|
|
||||||
Default EmuNAND: ( )
|
Default EmuNAND: ( )
|
||||||
|
<!--This option is only available if there's at least one EmuNAND.-->
|
||||||
|
|
||||||
Screen brightness: ( )
|
Screen brightness: ( )
|
||||||
|
|
||||||
Splash: ( )
|
Splash: ( )
|
||||||
|
|
||||||
|
Splash duration: ( )
|
||||||
|
|
||||||
PIN lock: ( )
|
PIN lock: ( )
|
||||||
|
|
||||||
New 3DS CPU: ( )
|
New 3DS CPU: ( )
|
||||||
@@ -48,8 +55,10 @@ New 3DS CPU: ( )
|
|||||||
--
|
--
|
||||||
|
|
||||||
Autoboot EmuNAND: ( )
|
Autoboot EmuNAND: ( )
|
||||||
|
<!--This option is only available if there's at least one EmuNAND.-->
|
||||||
|
|
||||||
Use EmuNAND FIRM if booting with R: ( )
|
Use EmuNAND FIRM if booting with R: ( )
|
||||||
|
<!--This option is only available if there's at least one EmuNAND.-->
|
||||||
|
|
||||||
Enable loading external FIRMs and modules: ( )
|
Enable loading external FIRMs and modules: ( )
|
||||||
<!--Firmware (.bin) files are not required by Luma, or NTR CFW anymore.
|
<!--Firmware (.bin) files are not required by Luma, or NTR CFW anymore.
|
||||||
@@ -61,11 +70,11 @@ Show NAND or user string in System Settings: ( )
|
|||||||
|
|
||||||
Show GBA boot screen in patched AGB_FIRM: ( )
|
Show GBA boot screen in patched AGB_FIRM: ( )
|
||||||
|
|
||||||
Patch ARM9 access: ( )
|
Patch Arm9 access: ( )
|
||||||
|
|
||||||
Set developer UNITINFO: ( )
|
Set developer UNITINFO: ( )
|
||||||
|
|
||||||
Disable ARM11 exception handlers: ( )
|
Disable Arm11 exception handlers: ( )
|
||||||
|
|
||||||
--
|
--
|
||||||
|
|
||||||
@@ -85,6 +94,6 @@ Disable ARM11 exception handlers: ( )
|
|||||||
|
|
||||||
|
|
||||||
**Dump file:**
|
**Dump file:**
|
||||||
<!--If the issue leads to a crash you must uncheck the "Disable ARM11 exception handlers" option.
|
<!--If the issue leads to a crash you must uncheck the "Disable Arm11 exception handlers" option.
|
||||||
-- The error message will tell you where the dump is.
|
-- The error message will tell you where the dump is.
|
||||||
-- Zip the dmp file and drag & drop it below.-->
|
-- Zip the dmp file and drag & drop it below.-->
|
||||||
180
Makefile
180
Makefile
@@ -1,177 +1,29 @@
|
|||||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifneq ($(strip $(shell firmtool -v 2>&1 | grep usage)),)
|
ifneq ($(strip $(shell firmtool -v 2>&1 | grep usage)),)
|
||||||
$(error "Please install firmtool v1.1 or greater")
|
$(error "Please install firmtool v1.1 or greater")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(DEVKITARM)/base_tools
|
NAME := $(notdir $(CURDIR))
|
||||||
|
REVISION := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
|
||||||
|
|
||||||
name := Luma3DS
|
SUBFOLDERS := sysmodules arm11 arm9 k11_extension
|
||||||
revision := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
|
|
||||||
version_major := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
|
|
||||||
version_minor := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f2 -d.)
|
|
||||||
version_build := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f3 -d.)
|
|
||||||
commit := $(shell git rev-parse --short=8 HEAD)
|
|
||||||
is_release := 0
|
|
||||||
|
|
||||||
ifeq ($(strip $(revision)),)
|
.PHONY: all release clean $(SUBFOLDERS)
|
||||||
revision := v0.0.0-0
|
|
||||||
version_major := 0
|
|
||||||
version_minor := 0
|
|
||||||
version_build := 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(strip $(commit)),)
|
all: boot.firm
|
||||||
commit := 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(strip $(version_build)),)
|
release: $(NAME)$(REVISION).zip
|
||||||
version_build := 0
|
|
||||||
endif
|
|
||||||
|
|
||||||
ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),)
|
|
||||||
is_release := 1
|
|
||||||
endif
|
|
||||||
|
|
||||||
dir_source := source
|
|
||||||
dir_patches := patches
|
|
||||||
dir_arm11 := arm11
|
|
||||||
dir_chainloader := chainloader
|
|
||||||
dir_exceptions := exceptions
|
|
||||||
dir_arm9_exceptions := $(dir_exceptions)/arm9
|
|
||||||
dir_k11_extension := k11_extension
|
|
||||||
dir_sysmodules := sysmodules
|
|
||||||
dir_loader := $(dir_sysmodules)/loader
|
|
||||||
dir_rosalina := $(dir_sysmodules)/rosalina
|
|
||||||
dir_sm := $(dir_sysmodules)/sm
|
|
||||||
dir_pxi := $(dir_sysmodules)/pxi
|
|
||||||
dir_build := build
|
|
||||||
dir_out := out
|
|
||||||
|
|
||||||
ASFLAGS := -mcpu=arm946e-s
|
|
||||||
CFLAGS := -Wall -Wextra $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
|
||||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
|
||||||
|
|
||||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
|
||||||
|
|
||||||
bundled = $(dir_build)/reboot.bin.o $(dir_build)/emunand.bin.o $(dir_build)/chainloader.bin.o $(dir_build)/arm9_exceptions.bin.o
|
|
||||||
|
|
||||||
modules = $(dir_build)/loader.cxi $(dir_build)/rosalina.cxi $(dir_build)/sm.cxi $(dir_build)/pxi.cxi
|
|
||||||
|
|
||||||
define bin2o
|
|
||||||
bin2s $< | $(AS) -o $(@)
|
|
||||||
endef
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
all: firm
|
|
||||||
|
|
||||||
.PHONY: release
|
|
||||||
release: $(dir_out)/$(name)$(revision).7z
|
|
||||||
|
|
||||||
.PHONY: firm
|
|
||||||
firm: $(dir_out)/boot.firm
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
clean:
|
||||||
@$(MAKE) -C $(dir_arm11) clean
|
@$(foreach dir, $(SUBFOLDERS), $(MAKE) -C $(dir) clean &&) true
|
||||||
@$(MAKE) -C $(dir_chainloader) clean
|
@rm -rf *.firm *.zip
|
||||||
@$(MAKE) -C $(dir_arm9_exceptions) clean
|
|
||||||
@$(MAKE) -C $(dir_k11_extension) clean
|
|
||||||
@$(MAKE) -C $(dir_loader) clean
|
|
||||||
@$(MAKE) -C $(dir_rosalina) clean
|
|
||||||
@$(MAKE) -C $(dir_sm) clean
|
|
||||||
@$(MAKE) -C $(dir_pxi) clean
|
|
||||||
@rm -rf $(dir_out) $(dir_build)
|
|
||||||
|
|
||||||
.PRECIOUS: $(dir_build)/%.bin
|
$(NAME)$(REVISION).zip: boot.firm exception_dump_parser
|
||||||
|
@zip -r $@ $^ -x "*.DS_Store*" "*__MACOSX*"
|
||||||
|
|
||||||
.PHONY: $(dir_arm11)
|
boot.firm: $(SUBFOLDERS)
|
||||||
.PHONY: $(dir_chainloader)
|
@firmtool build $@ -D sysmodules/sysmodules.bin arm11/arm11.elf arm9/arm9.elf k11_extension/k11_extension.elf \
|
||||||
.PHONY: $(dir_arm9_exceptions)
|
-A 0x18180000 -C XDMA XDMA NDMA XDMA
|
||||||
.PHONY: $(dir_k11_extension)
|
@echo built... $(notdir $@)
|
||||||
.PHONY: $(dir_loader)
|
|
||||||
.PHONY: $(dir_rosalina)
|
|
||||||
.PHONY: $(dir_sm)
|
|
||||||
.PHONY: $(dir_pxi)
|
|
||||||
|
|
||||||
|
$(SUBFOLDERS):
|
||||||
$(dir_out)/$(name)$(revision).7z: all
|
@$(MAKE) -C $@ all
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@[ -f "$@" ] || 7z a -mx $@ ./$(@D)/* ./$(dir_exceptions)/exception_dump_parser -xr!.DS_Store
|
|
||||||
|
|
||||||
$(dir_out)/boot.firm: $(dir_build)/modules.bin $(dir_build)/arm11.elf $(dir_build)/main.elf $(dir_build)/k11_extension.bin
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@firmtool build $@ -D $^ -A 0x18180000 0x18000000 -C XDMA XDMA NDMA XDMA
|
|
||||||
|
|
||||||
$(dir_build)/modules.bin: $(modules)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
cat $^ > $@
|
|
||||||
|
|
||||||
$(dir_build)/arm11.elf: $(dir_arm11)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/main.elf: $(bundled) $(objects)
|
|
||||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
|
||||||
|
|
||||||
$(dir_build)/k11_extension.bin: $(dir_k11_extension)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/loader.cxi: $(dir_loader)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/rosalina.cxi: $(dir_rosalina)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/sm.cxi: $(dir_sm)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/pxi.cxi: $(dir_pxi)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/%.bin.o: $(dir_build)/%.bin
|
|
||||||
@$(bin2o)
|
|
||||||
|
|
||||||
$(dir_build)/chainloader.bin: $(dir_chainloader)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/arm9_exceptions.bin: $(dir_arm9_exceptions)
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@$(MAKE) -C $<
|
|
||||||
|
|
||||||
$(dir_build)/%.bin: $(dir_patches)/%.s
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
@armips $<
|
|
||||||
|
|
||||||
$(dir_build)/memory.o $(dir_build)/strings.o: CFLAGS += -O3
|
|
||||||
$(dir_build)/config.o: CFLAGS += -DCONFIG_TITLE="\"$(name) $(revision) configuration\""
|
|
||||||
$(dir_build)/patches.o: CFLAGS += -DVERSION_MAJOR="$(version_major)" -DVERSION_MINOR="$(version_minor)"\
|
|
||||||
-DVERSION_BUILD="$(version_build)" -DISRELEASE="$(is_release)" -DCOMMIT_HASH="0x$(commit)"
|
|
||||||
$(dir_build)/firm.o: $(dir_build)/modules.bin
|
|
||||||
$(dir_build)/firm.o: CFLAGS += -DLUMA_SECTION0_SIZE="$(shell wc -c $(dir_build)/modules.bin | tr -d [:space:][:alpha:][:punct:])"
|
|
||||||
|
|
||||||
$(dir_build)/bundled.h: $(bundled)
|
|
||||||
@$(foreach f, $(bundled),\
|
|
||||||
echo "extern const u8" `(echo $(basename $(notdir $(f))) | sed -e 's/^\([0-9]\)/_\1/' | tr . _)`"[];" >> $@;\
|
|
||||||
echo "extern const u32" `(echo $(basename $(notdir $(f)))| sed -e 's/^\([0-9]\)/_\1/' | tr . _)`_size";" >> $@;\
|
|
||||||
)
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c $(dir_build)/bundled.h
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.s
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
|
||||||
|
|||||||
50
README.md
50
README.md
@@ -1,40 +1,36 @@
|
|||||||
# Luma3DS
|
# Luma3DS
|
||||||
*Noob-proof (N)3DS "Custom Firmware"*
|
*Noob-proof (N)3DS "Custom Firmware"*
|
||||||
|
|
||||||
## What it is
|
### What it is
|
||||||
|
**Luma3DS** is a program to patch the system software of (New) Nintendo (2)3DS handheld consoles "on the fly", adding features such as per-game language settings, debugging capabilities for developers, and removing restrictions enforced by Nintendo such as the region lock.
|
||||||
|
|
||||||
**Luma3DS** is a program to patch the system software of (New) Nintendo 3DS handheld consoles "on the fly", adding features (such as per-game language settings and debugging capabilities for developers) and removing restrictions enforced by Nintendo (such as the region lock).
|
It also allows you to run unauthorized ("homebrew") content by removing signature checks.
|
||||||
It also allows you to run unauthorized ("homebrew") content by removing signature checks.
|
To use it, you will need a console capable of running homebrew software on the Arm9 processor. We recommend [Plailect's guide](https://3ds.hacks.guide/) for details on how to get your system ready.
|
||||||
To use it, you will need a console capable of running homebrew software on the ARM9 processor. We recommend [Plailect's guide](https://3ds.guide/) for details on how to get your system ready.
|
|
||||||
|
|
||||||
Since Luma3DS v8.0, Luma3DS has its own in-game menu, triggerable by `L+Down+Select` (see the [release notes](https://github.com/AuroraWright/Luma3DS/releases/tag/v8.0)).
|
Since v8.0, Luma3DS has its own in-game menu, triggerable by <kbd>L+Down+Select</kbd> (see the [release notes](https://github.com/AuroraWright/Luma3DS/releases/tag/v8.0)).
|
||||||
|
|
||||||
---
|
#
|
||||||
|
### Compiling
|
||||||
|
* Prerequisites
|
||||||
|
1. git
|
||||||
|
2. [makerom](https://github.com/jakcron/Project_CTR) in PATH
|
||||||
|
3. [firmtool](https://github.com/TuxSH/firmtool)
|
||||||
|
4. Up-to-date devkitARM+libctru
|
||||||
|
1. Clone the repository with `git clone https://github.com/AuroraWright/Luma3DS.git`
|
||||||
|
2. Run `make`.
|
||||||
|
|
||||||
## Compiling
|
The produced `boot.firm` is meant to be copied to the root of your SD card for usage with Boot9Strap.
|
||||||
|
|
||||||
First you need to clone the repository with: `git clone https://github.com/AuroraWright/Luma3DS.git`
|
|
||||||
To compile, you'll need [armips](https://github.com/Kingcom/armips) and a build of a recent commit of [makerom](https://github.com/profi200/Project_CTR) added to your PATH. You'll also need to install [firmtool](https://github.com/TuxSH/firmtool), its README contains installation instructions.
|
|
||||||
You'll also need to update your [libctru](https://github.com/smealum/ctrulib) install, building from the latest commit.
|
|
||||||
Here are [Windows](https://buildbot.orphis.net/armips/) and [Linux](https://mega.nz/#!uQ1T1IAD!Q91O0e12LXKiaXh_YjXD3D5m8_W3FuMI-hEa6KVMRDQ) builds of armips (thanks to who compiled them!) and [makerom](https://github.com/Steveice10/buildtools/tree/master/3ds) (thanks @Steveice10!).
|
|
||||||
Run `make` and everything should work!
|
|
||||||
You can find the compiled files in the `out` folder.
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
## Setup / Usage / Features
|
|
||||||
|
|
||||||
|
#
|
||||||
|
### Setup / Usage / Features
|
||||||
See https://github.com/AuroraWright/Luma3DS/wiki
|
See https://github.com/AuroraWright/Luma3DS/wiki
|
||||||
|
|
||||||
---
|
#
|
||||||
|
### Credits
|
||||||
## Credits
|
|
||||||
|
|
||||||
See https://github.com/AuroraWright/Luma3DS/wiki/Credits
|
See https://github.com/AuroraWright/Luma3DS/wiki/Credits
|
||||||
|
|
||||||
---
|
#
|
||||||
|
### Licensing
|
||||||
|
This software is licensed under the terms of the GPLv3. You can find a copy of the license in the LICENSE.txt file.
|
||||||
|
|
||||||
## Licensing
|
Files in the GDB stub are instead triple-licensed as MIT or "GPLv2 or any later version", in which case it's specified in the file header.
|
||||||
|
|
||||||
This software is licensed under the terms of the GPLv3.
|
|
||||||
You can find a copy of the license in the LICENSE.txt file.
|
|
||||||
|
|||||||
156
arm11/Makefile
156
arm11/Makefile
@@ -1,39 +1,147 @@
|
|||||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(DEVKITARM)/base_tools
|
TOPDIR ?= $(CURDIR)
|
||||||
|
include $(DEVKITARM)/base_rules
|
||||||
|
|
||||||
name := $(shell basename $(CURDIR))
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# DATA is a list of directories containing data files
|
||||||
|
# INCLUDES is a list of directories containing header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source source/svc
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include include/svc
|
||||||
|
|
||||||
dir_source := source
|
#---------------------------------------------------------------------------------
|
||||||
dir_build := build
|
# options for code generation
|
||||||
dir_out := ../$(dir_build)
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||||
|
DEFINES := -DARM11 -D_3DS
|
||||||
|
|
||||||
ASFLAGS := -mcpu=mpcore
|
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
|
||||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
-fomit-frame-pointer -ffunction-sections -fdata-sections \
|
||||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
-Wno-main -fno-builtin $(ARCH) $(DEFINES)
|
||||||
|
|
||||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
CFLAGS += $(INCLUDE)
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
|
||||||
|
|
||||||
.PHONY: all
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
all: $(dir_out)/$(name).elf
|
|
||||||
|
|
||||||
.PHONY: clean
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(dir_build)
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||||
|
|
||||||
$(dir_out)/$(name).elf: $(objects)
|
|
||||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c
|
#---------------------------------------------------------------------------------
|
||||||
@mkdir -p "$(@D)"
|
else
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
.PHONY: all
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.s
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).bin
|
||||||
|
|
||||||
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
|
$(OBJCOPY) -S -O binary $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
|||||||
158
arm11/linker.ld
158
arm11/linker.ld
@@ -1,16 +1,158 @@
|
|||||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
OUTPUT_ARCH(arm)
|
OUTPUT_ARCH(arm)
|
||||||
|
|
||||||
ENTRY(_start)
|
ENTRY(_start)
|
||||||
|
|
||||||
|
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
main PT_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
SECTIONS
|
SECTIONS
|
||||||
{
|
{
|
||||||
. = 0x1FF80000;
|
PROVIDE(__start__ = 0x1FF80000);
|
||||||
|
PROVIDE(__stack_top__ = 0x1FFFE000);
|
||||||
|
PROVIDE(__stack_bottom__ = 0x1FFFD000);
|
||||||
|
|
||||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
. = __start__;
|
||||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
|
||||||
.data : ALIGN(4) { *(.data*); . = ALIGN(4); }
|
|
||||||
.bss : ALIGN(8) { __bss_start = .; *(.bss* COMMON); . = ALIGN(8); __bss_end = .; }
|
|
||||||
|
|
||||||
__stack_top__ = 0x1FFFE000;
|
.text :
|
||||||
. = ALIGN(4);
|
{
|
||||||
|
KEEP( *(.text.start) )
|
||||||
|
KEEP( *(.init) )
|
||||||
|
|
||||||
|
/* .text */
|
||||||
|
*(.text)
|
||||||
|
*(.text.*)
|
||||||
|
*(.glue_7)
|
||||||
|
*(.glue_7t)
|
||||||
|
*(.stub)
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t*)
|
||||||
|
|
||||||
|
/* .fini */
|
||||||
|
KEEP( *(.fini) )
|
||||||
|
. = ALIGN(32);
|
||||||
|
} :main
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
*(.roda)
|
||||||
|
*(.rodata.*)
|
||||||
|
*all.rodata*(*)
|
||||||
|
*(.gnu.linkonce.r*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
. = ALIGN(8);
|
||||||
|
}
|
||||||
|
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
}
|
||||||
|
|
||||||
|
.init_array :
|
||||||
|
{
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
}
|
||||||
|
|
||||||
|
.fini_array :
|
||||||
|
{
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
}
|
||||||
|
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
}
|
||||||
|
|
||||||
|
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = .;}
|
||||||
|
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = .;}
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
KEEP (*(.large_patch*))
|
||||||
|
*(.gnu.linkonce.d*)
|
||||||
|
CONSTRUCTORS
|
||||||
|
. = ALIGN(32);
|
||||||
|
}
|
||||||
|
|
||||||
|
.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(.gnu.linkonce.b*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(8);
|
||||||
|
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||||
|
} :NONE
|
||||||
|
|
||||||
|
PROVIDE (__end__ = ABSOLUTE(.));
|
||||||
|
|
||||||
|
/* ==================
|
||||||
|
==== Metadata ====
|
||||||
|
================== */
|
||||||
|
|
||||||
|
/* Discard sections that difficult post-processing */
|
||||||
|
/DISCARD/ : { *(.group .comment .note) }
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
}
|
}
|
||||||
|
|||||||
7
arm11/linker.specs
Normal file
7
arm11/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||||
|
|
||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -40,6 +40,10 @@ extern volatile Arm11Operation operation;
|
|||||||
static void initScreens(u32 brightnessLevel, struct fb *fbs)
|
static void initScreens(u32 brightnessLevel, struct fb *fbs)
|
||||||
{
|
{
|
||||||
*(vu32 *)0x10141200 = 0x1007F;
|
*(vu32 *)0x10141200 = 0x1007F;
|
||||||
|
|
||||||
|
*(vu32 *)0x10202204 = 0x01000000; //set LCD fill black to hide potential garbage -- NFIRM does it before firmlaunching
|
||||||
|
*(vu32 *)0x10202A04 = 0x01000000;
|
||||||
|
|
||||||
*(vu32 *)0x10202014 = 0x00000001;
|
*(vu32 *)0x10202014 = 0x00000001;
|
||||||
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
*(vu32 *)0x1020200C &= 0xFFFEFFFE;
|
||||||
*(vu32 *)0x10202240 = brightnessLevel;
|
*(vu32 *)0x10202240 = brightnessLevel;
|
||||||
@@ -118,16 +122,33 @@ static void initScreens(u32 brightnessLevel, struct fb *fbs)
|
|||||||
//Disco register
|
//Disco register
|
||||||
for(u32 i = 0; i < 256; i++)
|
for(u32 i = 0; i < 256; i++)
|
||||||
*(vu32 *)0x10400584 = 0x10101 * i;
|
*(vu32 *)0x10400584 = 0x10101 * i;
|
||||||
|
|
||||||
|
*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill
|
||||||
|
*(vu32 *)0x10202A04 = 0x00000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setupFramebuffers(struct fb *fbs)
|
static void setupFramebuffers(struct fb *fbs)
|
||||||
{
|
{
|
||||||
|
*(vu32 *)0x10202204 = 0x01000000; //set LCD fill black to hide potential garbage -- NFIRM does it before firmlaunching
|
||||||
|
*(vu32 *)0x10202A04 = 0x01000000;
|
||||||
|
|
||||||
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
|
*(vu32 *)0x10400468 = (u32)fbs[0].top_left;
|
||||||
*(vu32 *)0x1040046c = (u32)fbs[1].top_left;
|
*(vu32 *)0x1040046c = (u32)fbs[1].top_left;
|
||||||
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
|
*(vu32 *)0x10400494 = (u32)fbs[0].top_right;
|
||||||
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
|
*(vu32 *)0x10400498 = (u32)fbs[1].top_right;
|
||||||
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
|
*(vu32 *)0x10400568 = (u32)fbs[0].bottom;
|
||||||
*(vu32 *)0x1040056c = (u32)fbs[1].bottom;
|
*(vu32 *)0x1040056c = (u32)fbs[1].bottom;
|
||||||
|
|
||||||
|
//Set framebuffer format, framebuffer select and stride
|
||||||
|
*(vu32 *)0x10400470 = 0x80341;
|
||||||
|
*(vu32 *)0x10400478 = 0;
|
||||||
|
*(vu32 *)0x10400490 = 0x2D0;
|
||||||
|
*(vu32 *)0x10400570 = 0x80301;
|
||||||
|
*(vu32 *)0x10400578 = 0;
|
||||||
|
*(vu32 *)0x10400590 = 0x2D0;
|
||||||
|
|
||||||
|
*(vu32 *)0x10202204 = 0x00000000; //unset LCD fill
|
||||||
|
*(vu32 *)0x10202A04 = 0x00000000;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void clearScreens(struct fb *fb)
|
static void clearScreens(struct fb *fb)
|
||||||
@@ -196,7 +217,7 @@ void main(void)
|
|||||||
break;
|
break;
|
||||||
case UPDATE_BRIGHTNESS:
|
case UPDATE_BRIGHTNESS:
|
||||||
updateBrightness(*(vu32 *)ARM11_PARAMETERS_ADDRESS);
|
updateBrightness(*(vu32 *)ARM11_PARAMETERS_ADDRESS);
|
||||||
break;
|
break;
|
||||||
case DEINIT_SCREENS:
|
case DEINIT_SCREENS:
|
||||||
deinitScreens();
|
deinitScreens();
|
||||||
break;
|
break;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
@ This file is part of Luma3DS
|
@ This file is part of Luma3DS
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
@
|
@
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
@ This program is free software: you can redistribute it and/or modify
|
||||||
@ it under the terms of the GNU General Public License as published by
|
@ it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,8 +21,8 @@
|
|||||||
@ * Prohibiting misrepresentation of the origin of that material,
|
@ * Prohibiting misrepresentation of the origin of that material,
|
||||||
@ or requiring that modified versions of such material be marked in
|
@ or requiring that modified versions of such material be marked in
|
||||||
@ reasonable ways as different from the original version.
|
@ reasonable ways as different from the original version.
|
||||||
|
|
||||||
.section .text.start
|
.section .text.start, "ax", %progbits
|
||||||
.align 4
|
.align 4
|
||||||
.global _start
|
.global _start
|
||||||
.type _start, %function
|
.type _start, %function
|
||||||
@@ -53,20 +53,25 @@ start:
|
|||||||
mcr p15, 0, r0, c7, c7, 0
|
mcr p15, 0, r0, c7, c7, 0
|
||||||
mcr p15, 0, r0, c7, c10, 4
|
mcr p15, 0, r0, c7, c10, 4
|
||||||
|
|
||||||
@ Clear BSS
|
|
||||||
ldr r0, =__bss_start
|
|
||||||
mov r1, #0
|
|
||||||
ldr r2, =__bss_end
|
|
||||||
sub r2, r0
|
|
||||||
bl memset32
|
|
||||||
|
|
||||||
ldr sp, =__stack_top__
|
ldr sp, =__stack_top__
|
||||||
|
mov fp, #0
|
||||||
|
|
||||||
|
@ Clear BSS
|
||||||
|
ldr r0, =__bss_start__
|
||||||
|
mov r1, #0
|
||||||
|
ldr r2, =__bss_end__
|
||||||
|
sub r2, r0
|
||||||
|
bl memset
|
||||||
|
|
||||||
|
@ Call the init array
|
||||||
|
bl __libc_init_array
|
||||||
|
|
||||||
b main
|
b main
|
||||||
|
|
||||||
.global prepareForFirmlaunch
|
.global prepareForFirmlaunch
|
||||||
.type prepareForFirmlaunch, %function
|
.type prepareForFirmlaunch, %function
|
||||||
prepareForFirmlaunch:
|
prepareForFirmlaunch:
|
||||||
str r0, [r1] @ tell ARM9 we're done
|
str r0, [r1] @ tell Arm9 we're done
|
||||||
mov r0, #0x20000000
|
mov r0, #0x20000000
|
||||||
|
|
||||||
_wait_for_core0_entrypoint_loop:
|
_wait_for_core0_entrypoint_loop:
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
176
arm9/Makefile
Normal file
176
arm9/Makefile
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
TOPDIR ?= $(CURDIR)
|
||||||
|
include $(DEVKITARM)/base_rules
|
||||||
|
|
||||||
|
export REVISION := $(shell git describe --tags --match v[0-9]* --abbrev=8 | sed 's/-[0-9]*-g/-/')
|
||||||
|
export VERSION_MAJOR := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f1 -d.)
|
||||||
|
export VERSION_MINOR := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f2 -d.)
|
||||||
|
export VERSION_BUILD := $(shell git describe --tags --match v[0-9]* | cut -c2- | cut -f1 -d- | cut -f3 -d.)
|
||||||
|
export COMMIT := $(shell git rev-parse --short=8 HEAD)
|
||||||
|
export IS_RELEASE := 0
|
||||||
|
|
||||||
|
ifeq ($(strip $(REVISION)),)
|
||||||
|
export REVISION := v0.0.0-0
|
||||||
|
export VERSION_MAJOR := 0
|
||||||
|
export VERSION_MINOR := 0
|
||||||
|
export VERSION_BUILD := 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(COMMIT)),)
|
||||||
|
export COMMIT := 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(VERSION_BUILD)),)
|
||||||
|
export VERSION_BUILD := 0
|
||||||
|
endif
|
||||||
|
|
||||||
|
ifeq ($(strip $(shell git describe --tags --match v[0-9]* | grep -)),)
|
||||||
|
export IS_RELEASE := 1
|
||||||
|
endif
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# DATA is a list of directories containing data files
|
||||||
|
# INCLUDES is a list of directories containing header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
APP_TITLE := Luma3DS
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source source/fatfs source/fatfs/sdmmc
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -marm -march=armv5te -mtune=arm946e-s
|
||||||
|
DEFINES := -DARM9 -D_3DS
|
||||||
|
|
||||||
|
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
|
||||||
|
-fomit-frame-pointer -ffunction-sections -fdata-sections \
|
||||||
|
-Wno-main $(ARCH) $(DEFINES)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE)
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export APP_TITLE := $(notdir $(TOPDIR)/..)
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).bin $(TARGET).elf
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).elf
|
||||||
|
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
%.elf: $(OFILES)
|
||||||
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
|
memory.o strings.o: CFLAGS += -O3
|
||||||
|
config.o: CFLAGS += -DCONFIG_TITLE="\"$(APP_TITLE) $(REVISION) configuration\""
|
||||||
|
patches.o: CFLAGS += -DVERSION_MAJOR="$(VERSION_MAJOR)" -DVERSION_MINOR="$(VERSION_MINOR)"\
|
||||||
|
-DVERSION_BUILD="$(VERSION_BUILD)" -DISRELEASE="$(IS_RELEASE)" -DCOMMIT_HASH="0x$(COMMIT)"
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
209
arm9/linker.ld
Normal file
209
arm9/linker.ld
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
PHDRS
|
||||||
|
{
|
||||||
|
crt0 PT_LOAD;
|
||||||
|
itcm PT_LOAD;
|
||||||
|
main PT_LOAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Mostly copied from https://github.com/devkitPro/buildscripts/blob/master/dkarm-eabi/crtls/3dsx.ld */
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
main : ORIGIN = 0x08006000, LENGTH = 0x080F0000 - 0x08006000
|
||||||
|
itcm : ORIGIN = 0x01FF8000, LENGTH = 0x01FFB800 - 0x01FF8000 /* Unused ITCM slice. */
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
PROVIDE(__start__ = 0x08006000);
|
||||||
|
PROVIDE(__stack_top__ = 0x08100000);
|
||||||
|
PROVIDE(__stack_bottom__ = 0x080F0000);
|
||||||
|
|
||||||
|
PROVIDE(__itcm_stack_top__ = 0x01FFB800);
|
||||||
|
PROVIDE(__itcm_stack_bottom__ = 0x01FFA800);
|
||||||
|
|
||||||
|
. = __start__;
|
||||||
|
|
||||||
|
.crt0 :
|
||||||
|
{
|
||||||
|
KEEP( *(.text.start) )
|
||||||
|
KEEP( *(.init) )
|
||||||
|
. = ALIGN(32);
|
||||||
|
} >main :crt0
|
||||||
|
|
||||||
|
.itcm_loadable :
|
||||||
|
{
|
||||||
|
PROVIDE (__itcm_start__ = ABSOLUTE(.));
|
||||||
|
PROVIDE (__itcm_lma__ = LOADADDR(.itcm_loadable));
|
||||||
|
|
||||||
|
KEEP(*(.arm9_exception_handlers.text))
|
||||||
|
*(.arm9_exception_handlers.text*)
|
||||||
|
KEEP(*(.chainloader.text.start))
|
||||||
|
|
||||||
|
chainloader.o(.text*)
|
||||||
|
i2c.o(.text*)
|
||||||
|
arm9_exception_handlers.o(.text*)
|
||||||
|
|
||||||
|
*(.arm9_exception_handlers.rodata*)
|
||||||
|
chainloader.o(.rodata*)
|
||||||
|
i2c.o(.rodata*)
|
||||||
|
arm9_exception_handlers.o(.rodata*)
|
||||||
|
|
||||||
|
*(.arm9_exception_handlers.data*)
|
||||||
|
chainloader.o(.data*)
|
||||||
|
i2c.o(.data*)
|
||||||
|
arm9_exception_handlers.o(.data*)
|
||||||
|
. = ALIGN(32);
|
||||||
|
} >itcm AT>main :itcm
|
||||||
|
|
||||||
|
.itcm_bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__itcm_bss_start__ = ABSOLUTE(.));
|
||||||
|
|
||||||
|
*(.arm9_exception_handlers.bss*)
|
||||||
|
chainloader.o(.bss* COMMON)
|
||||||
|
i2c.o(.bss* COMMON)
|
||||||
|
arm9_exception_handlers.o(.bss* COMMON)
|
||||||
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__itcm_end__ = ABSOLUTE(.));
|
||||||
|
} >itcm :NONE
|
||||||
|
|
||||||
|
.text :
|
||||||
|
{
|
||||||
|
/* .text */
|
||||||
|
*(.text)
|
||||||
|
*(.text.*)
|
||||||
|
*(.glue_7)
|
||||||
|
*(.glue_7t)
|
||||||
|
*(.stub)
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.gnu.linkonce.t*)
|
||||||
|
|
||||||
|
/* .fini */
|
||||||
|
KEEP( *(.fini) )
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >main :main
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
*(.roda)
|
||||||
|
*(.rodata.*)
|
||||||
|
*all.rodata*(*)
|
||||||
|
*(.gnu.linkonce.r*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
. = ALIGN(8);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.preinit_array :
|
||||||
|
{
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
KEEP (*(.preinit_array))
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.init_array ALIGN(4) :
|
||||||
|
{
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
KEEP (*(SORT(.init_array.*)))
|
||||||
|
KEEP (*(.init_array))
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.fini_array ALIGN(4) :
|
||||||
|
{
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
KEEP (*(.fini_array))
|
||||||
|
KEEP (*(SORT(.fini_array.*)))
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.ctors ALIGN(4) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.ctors)) /* MUST be first -- GCC requires it */
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.dtors ALIGN(4) :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) __exidx_start = ABSOLUTE(.);} >main
|
||||||
|
ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) __exidx_end = ABSOLUTE(.);} >main
|
||||||
|
|
||||||
|
.data :
|
||||||
|
{
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
KEEP (*(.large_patch*))
|
||||||
|
*(.gnu.linkonce.d*)
|
||||||
|
CONSTRUCTORS
|
||||||
|
. = ALIGN(32);
|
||||||
|
} >main
|
||||||
|
|
||||||
|
.bss (NOLOAD) :
|
||||||
|
{
|
||||||
|
. = ALIGN(32);
|
||||||
|
PROVIDE (__bss_start__ = ABSOLUTE(.));
|
||||||
|
*(.dynbss)
|
||||||
|
*(.bss)
|
||||||
|
*(.bss.*)
|
||||||
|
*(.gnu.linkonce.b*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(8);
|
||||||
|
PROVIDE (__bss_end__ = ABSOLUTE(.));
|
||||||
|
} >main :NONE
|
||||||
|
__end__ = ABSOLUTE(.) ;
|
||||||
|
|
||||||
|
/* ==================
|
||||||
|
==== Metadata ====
|
||||||
|
================== */
|
||||||
|
|
||||||
|
/* Discard sections that difficult post-processing */
|
||||||
|
/DISCARD/ : { *(.group .comment .note) }
|
||||||
|
|
||||||
|
/* Stabs debugging sections. */
|
||||||
|
.stab 0 : { *(.stab) }
|
||||||
|
.stabstr 0 : { *(.stabstr) }
|
||||||
|
.stab.excl 0 : { *(.stab.excl) }
|
||||||
|
.stab.exclstr 0 : { *(.stab.exclstr) }
|
||||||
|
.stab.index 0 : { *(.stab.index) }
|
||||||
|
.stab.indexstr 0 : { *(.stab.indexstr) }
|
||||||
|
|
||||||
|
/* DWARF debug sections.
|
||||||
|
Symbols in the DWARF debugging sections are relative to the beginning
|
||||||
|
of the section so we begin them at 0. */
|
||||||
|
|
||||||
|
/* DWARF 1 */
|
||||||
|
.debug 0 : { *(.debug) }
|
||||||
|
.line 0 : { *(.line) }
|
||||||
|
|
||||||
|
/* GNU DWARF 1 extensions */
|
||||||
|
.debug_srcinfo 0 : { *(.debug_srcinfo) }
|
||||||
|
.debug_sfnames 0 : { *(.debug_sfnames) }
|
||||||
|
|
||||||
|
/* DWARF 1.1 and DWARF 2 */
|
||||||
|
.debug_aranges 0 : { *(.debug_aranges) }
|
||||||
|
.debug_pubnames 0 : { *(.debug_pubnames) }
|
||||||
|
|
||||||
|
/* DWARF 2 */
|
||||||
|
.debug_info 0 : { *(.debug_info) }
|
||||||
|
.debug_abbrev 0 : { *(.debug_abbrev) }
|
||||||
|
.debug_line 0 : { *(.debug_line) }
|
||||||
|
.debug_frame 0 : { *(.debug_frame) }
|
||||||
|
.debug_str 0 : { *(.debug_str) }
|
||||||
|
.debug_loc 0 : { *(.debug_loc) }
|
||||||
|
.debug_macinfo 0 : { *(.debug_macinfo) }
|
||||||
|
}
|
||||||
7
arm9/linker.specs
Normal file
7
arm9/linker.specs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T %:getenv(TOPDIR /linker.ld) --nmagic --gc-sections
|
||||||
|
|
||||||
|
*startfile:
|
||||||
|
crti%O%s crtbegin%O%s
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,21 +30,21 @@
|
|||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 address;
|
u32 address;
|
||||||
u32 phyRegionSize;
|
u32 phyRegionSize;
|
||||||
u32 size;
|
u32 size;
|
||||||
} CodeSetInfo;
|
} CodeSetInfo;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 saveDataSize[2];
|
u32 saveDataSize[2];
|
||||||
u32 jumpID[2];
|
u32 jumpID[2];
|
||||||
u8 reserved[0x30];
|
u8 reserved[0x30];
|
||||||
} SystemInfo;
|
} SystemInfo;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
char appTitle[8];
|
char appTitle[8];
|
||||||
u8 reserved1[5];
|
u8 reserved1[5];
|
||||||
@@ -60,7 +60,7 @@ typedef struct __attribute__((packed))
|
|||||||
SystemInfo systemInfo;
|
SystemInfo systemInfo;
|
||||||
} SystemControlInfo;
|
} SystemControlInfo;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
SystemControlInfo systemControlInfo;
|
SystemControlInfo systemControlInfo;
|
||||||
u8 aci[0x200];
|
u8 aci[0x200];
|
||||||
@@ -69,7 +69,7 @@ typedef struct __attribute__((packed))
|
|||||||
u8 aciLim[0x200];
|
u8 aciLim[0x200];
|
||||||
} ExHeader;
|
} ExHeader;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 sig[0x100]; //RSA-2048 signature of the NCCH header, using SHA-256
|
u8 sig[0x100]; //RSA-2048 signature of the NCCH header, using SHA-256
|
||||||
char magic[4]; //NCCH
|
char magic[4]; //NCCH
|
||||||
@@ -102,13 +102,13 @@ typedef struct __attribute__((packed))
|
|||||||
u8 romFsHash[0x20]; //RomFS superblock SHA-256 hash
|
u8 romFsHash[0x20]; //RomFS superblock SHA-256 hash
|
||||||
} Ncch;
|
} Ncch;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
Ncch ncch;
|
Ncch ncch;
|
||||||
ExHeader exHeader;
|
ExHeader exHeader;
|
||||||
} Cxi;
|
} Cxi;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
char sigIssuer[0x40];
|
char sigIssuer[0x40];
|
||||||
u8 eccPubKey[0x3C];
|
u8 eccPubKey[0x3C];
|
||||||
@@ -134,7 +134,7 @@ typedef struct __attribute__((packed))
|
|||||||
u8 contentIndex[0xAC];
|
u8 contentIndex[0xAC];
|
||||||
} Ticket;
|
} Ticket;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u8 *address;
|
u8 *address;
|
||||||
@@ -143,7 +143,7 @@ typedef struct __attribute__((packed))
|
|||||||
u8 hash[0x20];
|
u8 hash[0x20];
|
||||||
} FirmSection;
|
} FirmSection;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
char magic[4];
|
char magic[4];
|
||||||
u32 reserved1;
|
u32 reserved1;
|
||||||
@@ -153,7 +153,7 @@ typedef struct __attribute__((packed))
|
|||||||
FirmSection section[4];
|
FirmSection section[4];
|
||||||
} Firm;
|
} Firm;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u8 keyX[0x10];
|
u8 keyX[0x10];
|
||||||
u8 keyY[0x10];
|
u8 keyY[0x10];
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -23,9 +23,6 @@
|
|||||||
* or requiring that modified versions of such material be marked in
|
* or requiring that modified versions of such material be marked in
|
||||||
* reasonable ways as different from the original version.
|
* reasonable ways as different from the original version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
void flushCaches(void);
|
void *alignedseqmemcpy(void *dst, const void *src, u32 len);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@ This file is part of Luma3DS
|
@ This file is part of Luma3DS
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
@
|
@
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
@ This program is free software: you can redistribute it and/or modify
|
||||||
@ it under the terms of the GNU General Public License as published by
|
@ it under the terms of the GNU General Public License as published by
|
||||||
@@ -21,40 +21,45 @@
|
|||||||
@ * Prohibiting misrepresentation of the origin of that material,
|
@ * Prohibiting misrepresentation of the origin of that material,
|
||||||
@ or requiring that modified versions of such material be marked in
|
@ or requiring that modified versions of such material be marked in
|
||||||
@ reasonable ways as different from the original version.
|
@ reasonable ways as different from the original version.
|
||||||
|
|
||||||
|
.section .text.alignedseqmemcpy, "ax", %progbits
|
||||||
.arm
|
.arm
|
||||||
|
@ Align on cache line boundaries & make sure the loops don't cross them.
|
||||||
|
.align 5
|
||||||
|
.global alignedseqmemcpy
|
||||||
|
.type alignedseqmemcpy, %function
|
||||||
|
alignedseqmemcpy:
|
||||||
|
@ src=r1 and dst=r0 are expected to be 4-byte-aligned
|
||||||
|
push {r4-r10, lr}
|
||||||
|
|
||||||
.section .text.start
|
lsrs r12, r2, #5
|
||||||
.align 4
|
sub r2, r2, r12, lsl #5
|
||||||
.global _start
|
beq 2f
|
||||||
_start:
|
|
||||||
ldr sp, =__stack_top__
|
|
||||||
b main
|
|
||||||
|
|
||||||
.text
|
1:
|
||||||
.balign 4
|
ldmia r1!, {r3-r10}
|
||||||
.global disableMpuAndJumpToEntrypoints
|
stmia r0!, {r3-r10}
|
||||||
.type disableMpuAndJumpToEntrypoints, %function
|
subs r12, #1
|
||||||
disableMpuAndJumpToEntrypoints:
|
bne 1b
|
||||||
mov r4, r0
|
|
||||||
mov r5, r1
|
|
||||||
mov r6, r2
|
|
||||||
mov r7, r3
|
|
||||||
|
|
||||||
bl flushCaches
|
2:
|
||||||
|
lsrs r12, r2, #2
|
||||||
|
sub r2, r2, r12, lsl #2
|
||||||
|
beq 4f
|
||||||
|
|
||||||
@ Disable caches / MPU
|
3:
|
||||||
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
ldr r3, [r1], #4
|
||||||
bic r0, #(1<<12) @ - instruction cache disable
|
str r3, [r0], #4
|
||||||
bic r0, #(1<<2) @ - data cache disable
|
subs r12, #1
|
||||||
bic r0, #(1<<0) @ - MPU disable
|
bne 3b
|
||||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
|
||||||
|
|
||||||
@ Set the ARM11 entrypoint
|
4:
|
||||||
mov r0, #0x20000000
|
tst r2, #2
|
||||||
str r7, [r0, #-4]
|
ldrneh r3, [r1], #2
|
||||||
|
strneh r3, [r0], #2
|
||||||
|
|
||||||
@ Jump to the ARM9 entrypoint
|
tst r2, #1
|
||||||
mov r0, r4
|
ldrneb r3, [r1], #1
|
||||||
mov r1, r5
|
strneb r3, [r0], #1
|
||||||
ldr r2, =0x3BEEF
|
|
||||||
bx r6
|
pop {r4-r10, pc}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,15 +24,16 @@
|
|||||||
* reasonable ways as different from the original version.
|
* reasonable ways as different from the original version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
#include "arm9_exception_handlers.h"
|
||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "handlers.h"
|
#include "screen.h"
|
||||||
|
|
||||||
#define FINAL_BUFFER 0x25000000
|
#define FINAL_BUFFER 0x25000000
|
||||||
|
|
||||||
#define REG_DUMP_SIZE 4 * 17
|
#define REG_DUMP_SIZE 4 * 17
|
||||||
#define CODE_DUMP_SIZE 48
|
#define CODE_DUMP_SIZE 48
|
||||||
|
|
||||||
void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
|
void __attribute__((noreturn)) arm9ExceptionHandlerMain(u32 *registerDump, u32 type)
|
||||||
{
|
{
|
||||||
ExceptionDumpHeader dumpHeader;
|
ExceptionDumpHeader dumpHeader;
|
||||||
|
|
||||||
@@ -73,10 +74,10 @@ void __attribute__((noreturn)) mainHandler(u32 *registerDump, u32 type)
|
|||||||
//Copy header (actually optimized by the compiler)
|
//Copy header (actually optimized by the compiler)
|
||||||
*(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader;
|
*(ExceptionDumpHeader *)FINAL_BUFFER = dumpHeader;
|
||||||
|
|
||||||
if(ARESCREENSINITIALIZED) i2cWriteRegister(I2C_DEV_MCU, 0x22, 1 << 0); //Shutdown LCD
|
if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0); //Shutdown LCD
|
||||||
|
|
||||||
((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
((void (*)())0xFFFF0830)(); //Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
|
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
|
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 2); //Reboot
|
||||||
while(true);
|
while(true);
|
||||||
}
|
}
|
||||||
32
arm9/source/arm9_exception_handlers.h
Normal file
32
arm9/source/arm9_exception_handlers.h
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Luma3DS
|
||||||
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||||
|
* * Requiring preservation of specified reasonable legal notices or
|
||||||
|
* author attributions in that material or in the Appropriate Legal
|
||||||
|
* Notices displayed by works containing it.
|
||||||
|
* * Prohibiting misrepresentation of the origin of that material,
|
||||||
|
* or requiring that modified versions of such material be marked in
|
||||||
|
* reasonable ways as different from the original version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
extern const u32 arm9ExceptionHandlerAddressTable[6];
|
||||||
|
extern u32 arm9ExceptionHandlerSvcBreakAddress;
|
||||||
|
|
||||||
|
u32 safecpy(void *dst, const void *src, u32 len);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@ This file is part of Luma3DS
|
@ This file is part of Luma3DS
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
@
|
@
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
@ This program is free software: you can redistribute it and/or modify
|
||||||
@ it under the terms of the GNU General Public License as published by
|
@ it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,16 +28,16 @@
|
|||||||
stmia sp, {r0-r7}
|
stmia sp, {r0-r7}
|
||||||
|
|
||||||
mov r0, #\index
|
mov r0, #\index
|
||||||
b _commonHandler
|
b _arm9ExceptionHandlerCommon
|
||||||
.endm
|
.endm
|
||||||
|
|
||||||
.text
|
.section .arm9_exception_handlers.text, "ax", %progbits
|
||||||
.arm
|
.arm
|
||||||
.balign 4
|
.align 4
|
||||||
|
|
||||||
.global _commonHandler
|
.global _arm9ExceptionHandlerCommon
|
||||||
.type _commonHandler, %function
|
.type _arm9ExceptionHandlerCommon, %function
|
||||||
_commonHandler:
|
_arm9ExceptionHandlerCommon:
|
||||||
mov r1, r0
|
mov r1, r0
|
||||||
mov r0, sp
|
mov r0, sp
|
||||||
mrs r2, spsr
|
mrs r2, spsr
|
||||||
@@ -60,7 +60,7 @@ _commonHandler:
|
|||||||
|
|
||||||
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
|
msr cpsr_cxsf, #0xdf @ finally, switch to system mode, mask interrupts and clear flags (in case of double faults)
|
||||||
ldr sp, =0x02000000
|
ldr sp, =0x02000000
|
||||||
b mainHandler
|
b arm9ExceptionHandlerMain
|
||||||
|
|
||||||
|
|
||||||
.global FIQHandler
|
.global FIQHandler
|
||||||
@@ -80,7 +80,7 @@ prefetchAbortHandler:
|
|||||||
cmp sp, #0x13
|
cmp sp, #0x13
|
||||||
bne _prefetchAbortNormalHandler
|
bne _prefetchAbortNormalHandler
|
||||||
|
|
||||||
ldr sp, =BreakPtr
|
ldr sp, =arm9ExceptionHandlerSvcBreakAddress
|
||||||
ldr sp, [sp]
|
ldr sp, [sp]
|
||||||
cmp sp, #0
|
cmp sp, #0
|
||||||
beq _prefetchAbortNormalHandler
|
beq _prefetchAbortNormalHandler
|
||||||
@@ -147,6 +147,22 @@ safecpy:
|
|||||||
|
|
||||||
_safecpy_end:
|
_safecpy_end:
|
||||||
|
|
||||||
.bss
|
.section .arm9_exception_handlers.rodata, "a", %progbits
|
||||||
.balign 4
|
.align 4
|
||||||
|
.global arm9ExceptionHandlerAddressTable
|
||||||
|
arm9ExceptionHandlerAddressTable:
|
||||||
|
.word 0 @ IRQ
|
||||||
|
.word FIQHandler @ FIQ
|
||||||
|
.word 0 @ SVC
|
||||||
|
.word undefinedInstructionHandler @ Undefined instruction
|
||||||
|
.word prefetchAbortHandler @ Prefetch abort
|
||||||
|
.word dataAbortHandler @ Data abort
|
||||||
|
|
||||||
|
.section .arm9_exception_handlers.bss, "aw", %nobits
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
.global arm9ExceptionHandlerSvcBreakAddress
|
||||||
|
arm9ExceptionHandlerSvcBreakAddress:
|
||||||
|
.skip 4
|
||||||
|
|
||||||
_regs: .skip (4 * 17)
|
_regs: .skip (4 * 17)
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
The data cache and/or the instruction cache MUST be flushed before doing one of the following:
|
The data cache and/or the instruction cache MUST be flushed before doing one of the following:
|
||||||
- rebooting
|
- rebooting
|
||||||
- powering down
|
- powering down
|
||||||
- setting the ARM11 entrypoint to execute a function
|
- setting the Arm11 entrypoint to execute a function
|
||||||
- jumping to a payload
|
- jumping to a payload
|
||||||
***/
|
***/
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@ This file is part of Luma3DS
|
@ This file is part of Luma3DS
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
@
|
@
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
@ This program is free software: you can redistribute it and/or modify
|
||||||
@ it under the terms of the GNU General Public License as published by
|
@ it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
@ or requiring that modified versions of such material be marked in
|
@ or requiring that modified versions of such material be marked in
|
||||||
@ reasonable ways as different from the original version.
|
@ reasonable ways as different from the original version.
|
||||||
|
|
||||||
.text
|
.section .text.cache, "ax", %progbits
|
||||||
.arm
|
.arm
|
||||||
.align 4
|
.align 4
|
||||||
|
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
flushEntireDCache:
|
flushEntireDCache:
|
||||||
@ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html,
|
@ Adapted from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html,
|
||||||
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
||||||
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
@ Note: Arm's example is actually for a 8KB DCache (which is what the 3DS has)
|
||||||
|
|
||||||
@ Implemented in bootROM at address 0xffff0830
|
@ Implemented in bootROM at address 0xffff0830
|
||||||
mov r1, #0 @ segment counter
|
mov r1, #0 @ segment counter
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,11 +24,37 @@
|
|||||||
* reasonable ways as different from the original version.
|
* reasonable ways as different from the original version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "memory.h"
|
#include "chainloader.h"
|
||||||
#include "cache.h"
|
#include "screen.h"
|
||||||
#include "firm.h"
|
|
||||||
|
|
||||||
void main(int argc, char **argv, Firm *firm)
|
void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
|
||||||
|
|
||||||
|
#pragma GCC optimize (3)
|
||||||
|
|
||||||
|
static void *xmemcpy(void *dst, const void *src, u32 len)
|
||||||
|
{
|
||||||
|
const u8 *src8 = (const u8 *)src;
|
||||||
|
u8 *dst8 = (u8 *)dst;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < len; i++) {
|
||||||
|
dst8[i] = src8[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return dst;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void doLaunchFirm(Firm *firm, int argc, char **argv)
|
||||||
|
{
|
||||||
|
//Copy FIRM sections to respective memory locations
|
||||||
|
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
|
||||||
|
xmemcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
|
||||||
|
|
||||||
|
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
|
||||||
|
|
||||||
|
__builtin_unreachable();
|
||||||
|
}
|
||||||
|
|
||||||
|
void chainloader_main(int argc, char **argv, Firm *firm)
|
||||||
{
|
{
|
||||||
char *argvPassed[2],
|
char *argvPassed[2],
|
||||||
absPath[24 + 255];
|
absPath[24 + 255];
|
||||||
@@ -54,5 +80,5 @@ void main(int argc, char **argv, Firm *firm)
|
|||||||
argvPassed[1] = (char *)&fbs;
|
argvPassed[1] = (char *)&fbs;
|
||||||
}
|
}
|
||||||
|
|
||||||
launchFirm(firm, argc, argvPassed);
|
doLaunchFirm(firm, argc, argvPassed);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,12 +24,9 @@
|
|||||||
* reasonable ways as different from the original version.
|
* reasonable ways as different from the original version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
|
||||||
* memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
#include "firm.h"
|
||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size);
|
void chainload(int argc, char **argv, Firm *firm);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -27,10 +27,10 @@
|
|||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
|
#include "emunand.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "pin.h"
|
#include "pin.h"
|
||||||
|
|
||||||
@@ -94,7 +94,7 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
"( ) Show NAND or user string in System Settings",
|
"( ) Show NAND or user string in System Settings",
|
||||||
"( ) Show GBA boot screen in patched AGB_FIRM",
|
"( ) Show GBA boot screen in patched AGB_FIRM",
|
||||||
"( ) Set developer UNITINFO",
|
"( ) Set developer UNITINFO",
|
||||||
"( ) Disable ARM11 exception handlers",
|
"( ) Disable Arm11 exception handlers",
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
|
static const char *optionsDescription[] = { "Select the default EmuNAND.\n\n"
|
||||||
@@ -189,20 +189,27 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
"are doing!",
|
"are doing!",
|
||||||
|
|
||||||
"Disables the fatal error exception\n"
|
"Disables the fatal error exception\n"
|
||||||
"handlers for the ARM11 CPU.\n\n"
|
"handlers for the Arm11 CPU.\n\n"
|
||||||
"Note: Disabling the exception handlers\n"
|
"Note: Disabling the exception handlers\n"
|
||||||
"will disqualify you from submitting\n"
|
"will disqualify you from submitting\n"
|
||||||
"issues or bug reports to the Luma3DS\n"
|
"issues or bug reports to the Luma3DS\n"
|
||||||
"GitHub repository!"
|
"GitHub repository!"
|
||||||
};
|
};
|
||||||
|
|
||||||
|
FirmwareSource nandType = FIRMWARE_SYSNAND;
|
||||||
|
if(isSdMode)
|
||||||
|
{
|
||||||
|
nandType = FIRMWARE_EMUNAND;
|
||||||
|
locateEmuNand(&nandType);
|
||||||
|
}
|
||||||
|
|
||||||
struct multiOption {
|
struct multiOption {
|
||||||
u32 posXs[4];
|
u32 posXs[4];
|
||||||
u32 posY;
|
u32 posY;
|
||||||
u32 enabled;
|
u32 enabled;
|
||||||
bool visible;
|
bool visible;
|
||||||
} multiOptions[] = {
|
} multiOptions[] = {
|
||||||
{ .visible = isSdMode },
|
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
@@ -215,8 +222,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
bool enabled;
|
bool enabled;
|
||||||
bool visible;
|
bool visible;
|
||||||
} singleOptions[] = {
|
} singleOptions[] = {
|
||||||
{ .visible = isSdMode },
|
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||||
{ .visible = isSdMode },
|
{ .visible = nandType == FIRMWARE_EMUNAND },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
{ .visible = true },
|
{ .visible = true },
|
||||||
@@ -229,8 +236,8 @@ void configMenu(bool oldPinStatus, u32 oldPinMode)
|
|||||||
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
|
u32 multiOptionsAmount = sizeof(multiOptions) / sizeof(struct multiOption),
|
||||||
singleOptionsAmount = sizeof(singleOptions) / sizeof(struct singleOption),
|
singleOptionsAmount = sizeof(singleOptions) / sizeof(struct singleOption),
|
||||||
totalIndexes = multiOptionsAmount + singleOptionsAmount - 1,
|
totalIndexes = multiOptionsAmount + singleOptionsAmount - 1,
|
||||||
selectedOption,
|
selectedOption = 0,
|
||||||
singleSelected;
|
singleSelected = 0;
|
||||||
bool isMultiOption = false;
|
bool isMultiOption = false;
|
||||||
|
|
||||||
//Parse the existing options
|
//Parse the existing options
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -34,8 +34,9 @@
|
|||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
#include "alignedseqmemcpy.h"
|
||||||
|
#include "strings.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
|
|
||||||
/****************************************************************
|
/****************************************************************
|
||||||
@@ -288,24 +289,18 @@ void sha(void *res, const void *src, u32 size, u32 mode)
|
|||||||
sha_wait_idle();
|
sha_wait_idle();
|
||||||
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
|
*REG_SHA_CNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
|
||||||
|
|
||||||
const u32 *src32 = (const u32 *)src;
|
const u8 *src8 = (const u8 *)src;
|
||||||
int i;
|
|
||||||
while(size >= 0x40)
|
while(size >= 0x40)
|
||||||
{
|
{
|
||||||
sha_wait_idle();
|
sha_wait_idle();
|
||||||
for(i = 0; i < 4; ++i)
|
alignedseqmemcpy((void *)REG_SHA_INFIFO, src8, 0x40);
|
||||||
{
|
|
||||||
*REG_SHA_INFIFO = *src32++;
|
|
||||||
*REG_SHA_INFIFO = *src32++;
|
|
||||||
*REG_SHA_INFIFO = *src32++;
|
|
||||||
*REG_SHA_INFIFO = *src32++;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
src8 += 0x40;
|
||||||
size -= 0x40;
|
size -= 0x40;
|
||||||
}
|
}
|
||||||
|
|
||||||
sha_wait_idle();
|
sha_wait_idle();
|
||||||
memcpy((void *)REG_SHA_INFIFO, src32, size);
|
alignedseqmemcpy((void *)REG_SHA_INFIFO, src8, size);
|
||||||
|
|
||||||
*REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
|
*REG_SHA_CNT = (*REG_SHA_CNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
|
||||||
|
|
||||||
@@ -318,7 +313,7 @@ void sha(void *res, const void *src, u32 size, u32 mode)
|
|||||||
else if(mode == SHA_1_MODE)
|
else if(mode == SHA_1_MODE)
|
||||||
hashSize = SHA_1_HASH_SIZE;
|
hashSize = SHA_1_HASH_SIZE;
|
||||||
|
|
||||||
memcpy(res, (void *)REG_SHA_HASH, hashSize);
|
alignedseqmemcpy(res, (void *)REG_SHA_HASH, hashSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************/
|
/*****************************************************************/
|
||||||
@@ -532,7 +527,7 @@ void setupKeyslots(void)
|
|||||||
aes_setkey(0x25, keyX0x25s[ISDEVUNIT ? 1 : 0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x25, keyX0x25s[ISDEVUNIT ? 1 : 0], AES_KEYX, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_setkey(0x2F, keyY0x2Fs[ISDEVUNIT ? 1 : 0], AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x2F, keyY0x2Fs[ISDEVUNIT ? 1 : 0], AES_KEYY, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
if(ISN3DS)
|
if(ISN3DS)
|
||||||
{
|
{
|
||||||
//Setup 0x05 KeyY
|
//Setup 0x05 KeyY
|
||||||
__attribute__((aligned(4))) static const u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
|
__attribute__((aligned(4))) static const u8 keyY0x5[AES_BLOCK_SIZE] = {0x4D, 0x80, 0x4F, 0x4E, 0x99, 0x90, 0x19, 0x46, 0x13, 0xA2, 0x04, 0xAC, 0x58, 0x44, 0x60, 0xBE};
|
||||||
@@ -547,7 +542,7 @@ void setupKeyslots(void)
|
|||||||
{0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}
|
{0xDD, 0xDA, 0xA4, 0xC6, 0x2C, 0xC4, 0x50, 0xE9, 0xDA, 0xB6, 0x9B, 0x0D, 0x9D, 0x2A, 0x21, 0x98}
|
||||||
}, decKey[AES_BLOCK_SIZE];
|
}, decKey[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
//Initialize Key 0x18
|
//Initialize Key 0x18
|
||||||
aes_setkey(0x11, key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes_setkey(0x11, key1s[ISDEVUNIT ? 1 : 0], AES_KEYNORMAL, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
aes(decKey, keyBlocks[0], 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
aes(decKey, keyBlocks[0], 1, NULL, AES_ECB_DECRYPT_MODE, 0);
|
||||||
@@ -586,6 +581,9 @@ void kernel9Loader(Arm9Bin *arm9Section)
|
|||||||
|
|
||||||
u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16;
|
u8 arm9BinSlot = k9lVersion == 0 ? 0x15 : 0x16;
|
||||||
|
|
||||||
|
// Get size
|
||||||
|
u32 arm9SectionSize = decAtoi(arm9Section->size, 8);
|
||||||
|
|
||||||
//Set keyX
|
//Set keyX
|
||||||
__attribute__((aligned(4))) u8 keyX[AES_BLOCK_SIZE];
|
__attribute__((aligned(4))) u8 keyX[AES_BLOCK_SIZE];
|
||||||
aes_use_keyslot(0x11);
|
aes_use_keyslot(0x11);
|
||||||
@@ -601,11 +599,11 @@ void kernel9Loader(Arm9Bin *arm9Section)
|
|||||||
__attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE];
|
__attribute__((aligned(4))) u8 arm9BinCtr[AES_BLOCK_SIZE];
|
||||||
memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr));
|
memcpy(arm9BinCtr, arm9Section->ctr, sizeof(arm9BinCtr));
|
||||||
|
|
||||||
//Decrypt ARM9 binary
|
//Decrypt Arm9 binary
|
||||||
aes_use_keyslot(arm9BinSlot);
|
aes_use_keyslot(arm9BinSlot);
|
||||||
aes(startOfArm9Bin, startOfArm9Bin, decAtoi(arm9Section->size, sizeof(arm9Section->size)) / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(startOfArm9Bin, startOfArm9Bin, arm9SectionSize / AES_BLOCK_SIZE, arm9BinCtr, AES_CTR_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
|
|
||||||
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the ARM9 binary.");
|
if(*startOfArm9Bin != 0x47704770 && *startOfArm9Bin != 0xB0862000) error("Failed to decrypt the Arm9 binary.");
|
||||||
}
|
}
|
||||||
|
|
||||||
void computePinHash(u8 *outbuf, const u8 *inbuf)
|
void computePinHash(u8 *outbuf, const u8 *inbuf)
|
||||||
@@ -614,7 +612,7 @@ void computePinHash(u8 *outbuf, const u8 *inbuf)
|
|||||||
cipherText[AES_BLOCK_SIZE];
|
cipherText[AES_BLOCK_SIZE];
|
||||||
|
|
||||||
sdmmc_get_cid(1, (u32 *)cid);
|
sdmmc_get_cid(1, (u32 *)cid);
|
||||||
aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the ARM9 bootROM
|
aes_use_keyslot(0x04); //Console-unique keyslot whose keys are set by the Arm9 bootROM
|
||||||
aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
aes(cipherText, inbuf, 1, cid, AES_CBC_ENCRYPT_MODE, AES_INPUT_BE | AES_INPUT_NORMAL);
|
||||||
sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE);
|
sha(outbuf, cipherText, sizeof(cipherText), SHA_256_MODE);
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "strings.h"
|
#include "memory.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,7 +33,7 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
#include "../build/bundled.h"
|
#include "large_patches.h"
|
||||||
|
|
||||||
u32 emuOffset,
|
u32 emuOffset,
|
||||||
emuHeader;
|
emuHeader;
|
||||||
@@ -109,8 +109,8 @@ static inline bool getFreeK9Space(u8 *pos, u32 size, u8 **freeK9Space)
|
|||||||
//Looking for the last free space before Process9
|
//Looking for the last free space before Process9
|
||||||
*freeK9Space = memsearch(pos, pattern, size, sizeof(pattern));
|
*freeK9Space = memsearch(pos, pattern, size, sizeof(pattern));
|
||||||
|
|
||||||
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunand_bin_size ||
|
if(*freeK9Space == NULL || (u32)(pos + size - *freeK9Space) < 0x455 + emunandPatchSize ||
|
||||||
*(u32 *)(*freeK9Space + 0x455 + emunand_bin_size - 4) != 0xFFFFFFFF) return false;
|
*(u32 *)(*freeK9Space + 0x455 + emunandPatchSize - 4) != 0xFFFFFFFF) return false;
|
||||||
|
|
||||||
*freeK9Space += 0x455;
|
*freeK9Space += 0x455;
|
||||||
|
|
||||||
@@ -195,20 +195,17 @@ u32 patchEmuNand(u8 *arm9Section, u32 kernel9Size, u8 *process9Offset, u32 proce
|
|||||||
|
|
||||||
u32 ret = 0;
|
u32 ret = 0;
|
||||||
|
|
||||||
//Copy EmuNAND code
|
|
||||||
memcpy(freeK9Space, emunand_bin, emunand_bin_size);
|
|
||||||
|
|
||||||
//Add the data of the found EmuNAND
|
//Add the data of the found EmuNAND
|
||||||
u32 *posOffset = (u32 *)memsearch(freeK9Space, "NAND", emunand_bin_size, 4),
|
emunandPatchNandOffset = emuOffset;
|
||||||
*posHeader = (u32 *)memsearch(freeK9Space, "NCSD", emunand_bin_size, 4);
|
emunandPatchNcsdHeaderOffset = emuHeader;
|
||||||
*posOffset = emuOffset;
|
|
||||||
*posHeader = emuHeader;
|
|
||||||
|
|
||||||
//Find and add the SDMMC struct
|
//Find and add the SDMMC struct
|
||||||
u32 *posSdmmc = (u32 *)memsearch(freeK9Space, "SDMC", emunand_bin_size, 4);
|
|
||||||
u32 sdmmc;
|
u32 sdmmc;
|
||||||
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
|
ret += !ISN3DS && firmVersion < 0x25 ? getOldSdmmc(&sdmmc, firmVersion) : getSdmmc(process9Offset, process9Size, &sdmmc);
|
||||||
if(!ret) *posSdmmc = sdmmc;
|
if(!ret) emunandPatchSdmmcStructPtr = sdmmc;
|
||||||
|
|
||||||
|
//Copy EmuNAND code
|
||||||
|
memcpy(freeK9Space, emunandPatch, emunandPatchSize);
|
||||||
|
|
||||||
//Add EmuNAND hooks
|
//Add EmuNAND hooks
|
||||||
u32 branchOffset = (u32)(freeK9Space - arm9Section + kernel9Address);
|
u32 branchOffset = (u32)(freeK9Space - arm9Section + kernel9Address);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,31 +26,26 @@
|
|||||||
|
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "../build/bundled.h"
|
#include "arm9_exception_handlers.h"
|
||||||
|
|
||||||
void installArm9Handlers(void)
|
void installArm9Handlers(void)
|
||||||
{
|
{
|
||||||
memcpy((void *)0x01FF8000, arm9_exceptions_bin, arm9_exceptions_bin_size);
|
vu32 *dstVeneers = (vu32 *)0x08000000;
|
||||||
|
|
||||||
/* IRQHandler is at 0x08000000, but we won't handle it for some reasons
|
for(u32 i = 0; i < 6; i++)
|
||||||
svcHandler is at 0x08000010, but we won't handle svc either */
|
|
||||||
|
|
||||||
static const u32 offsets[] = {0x08, 0x18, 0x20, 0x28};
|
|
||||||
|
|
||||||
for(u32 i = 0; i < 4; i++)
|
|
||||||
{
|
{
|
||||||
*(vu32 *)(0x08000000 + offsets[i]) = 0xE51FF004;
|
if(arm9ExceptionHandlerAddressTable[i] != 0)
|
||||||
*(vu32 *)(0x08000000 + offsets[i] + 4) = *(vu32 *)(0x01FF8008 + 4 * i);
|
{
|
||||||
|
dstVeneers[2 * i] = 0xE51FF004;
|
||||||
|
dstVeneers[2 * i + 1] = arm9ExceptionHandlerAddressTable[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
*(vu32 *)0x01FF8004 = 0; //BreakPtr
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void detectAndProcessExceptionDumps(void)
|
void detectAndProcessExceptionDumps(void)
|
||||||
@@ -90,8 +85,8 @@ void detectAndProcessExceptionDumps(void)
|
|||||||
|
|
||||||
drawString(true, 10, 10, COLOR_RED, "An exception occurred");
|
drawString(true, 10, 10, COLOR_RED, "An exception occurred");
|
||||||
u32 posY;
|
u32 posY;
|
||||||
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: ARM11 (core %u)", dumpHeader->core);
|
if(dumpHeader->processor == 11) posY = drawFormattedString(true, 10, 30, COLOR_WHITE, "Processor: Arm11 (core %u)", dumpHeader->core);
|
||||||
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: ARM9");
|
else posY = drawString(true, 10, 30, COLOR_WHITE, "Processor: Arm9");
|
||||||
|
|
||||||
if(dumpHeader->type == 2)
|
if(dumpHeader->type == 2)
|
||||||
{
|
{
|
||||||
@@ -138,16 +133,16 @@ void detectAndProcessExceptionDumps(void)
|
|||||||
|
|
||||||
for(u32 i = 0; i < 17; i += 2)
|
for(u32 i = 0; i < 17; i += 2)
|
||||||
{
|
{
|
||||||
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X", registerNames[i], regs[i]);
|
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08lX", registerNames[i], regs[i]);
|
||||||
|
|
||||||
if(i != 16)
|
if(i != 16)
|
||||||
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[i + 1]);
|
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08lX", registerNames[i + 1], regs[i + 1]);
|
||||||
else if(dumpHeader->processor == 11)
|
else if(dumpHeader->processor == 11)
|
||||||
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08X", registerNames[i + 1], regs[20]);
|
posY = drawFormattedString(true, 10 + 22 * SPACING_X, posY, COLOR_WHITE, "%-7s%08lX", registerNames[i + 1], regs[20]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(dumpHeader->processor == 11 && dumpHeader->type == 3)
|
if(dumpHeader->processor == 11 && dumpHeader->type == 3)
|
||||||
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08X Access type: %s", "FAR", regs[19], regs[17] & (1u << 11) ? "Write" : "Read");
|
posY = drawFormattedString(true, 10, posY + SPACING_Y, COLOR_WHITE, "%-7s%08lX Access type: %s", "FAR", regs[19], regs[17] & (1u << 11) ? "Write" : "Read");
|
||||||
|
|
||||||
posY += SPACING_Y;
|
posY += SPACING_Y;
|
||||||
|
|
||||||
@@ -159,7 +154,7 @@ void detectAndProcessExceptionDumps(void)
|
|||||||
|
|
||||||
for(u32 line = 0; line < 19 && stackDump < additionalData; line++)
|
for(u32 line = 0; line < 19 && stackDump < additionalData; line++)
|
||||||
{
|
{
|
||||||
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08X:", regs[13] + 8 * line);
|
posYBottom = drawFormattedString(false, 10, posYBottom + SPACING_Y, COLOR_WHITE, "%08lX:", regs[13] + 8 * line);
|
||||||
|
|
||||||
for(u32 i = 0; i < 8 && stackDump < additionalData; i++, stackDump++)
|
for(u32 i = 0; i < 8 && stackDump < additionalData; i++, stackDump++)
|
||||||
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
|
drawFormattedString(false, 10 + 10 * SPACING_X + 3 * i * SPACING_X, posYBottom, COLOR_WHITE, "%02X", *stackDump);
|
||||||
@@ -175,9 +170,9 @@ void detectAndProcessExceptionDumps(void)
|
|||||||
drawString(true, 10, posY + SPACING_Y, COLOR_BLACK, choiceMessage[0]);
|
drawString(true, 10, posY + SPACING_Y, COLOR_BLACK, choiceMessage[0]);
|
||||||
drawString(true, 10, posY + SPACING_Y + SPACING_Y , COLOR_BLACK, choiceMessage[1]);
|
drawString(true, 10, posY + SPACING_Y + SPACING_Y , COLOR_BLACK, choiceMessage[1]);
|
||||||
|
|
||||||
char folderPath[12],
|
char folderPath[32],
|
||||||
path[36],
|
path[128],
|
||||||
fileName[24];
|
fileName[32];
|
||||||
|
|
||||||
sprintf(folderPath, "dumps/arm%u", dumpHeader->processor);
|
sprintf(folderPath, "dumps/arm%u", dumpHeader->processor);
|
||||||
findDumpFile(folderPath, fileName);
|
findDumpFile(folderPath, fileName);
|
||||||
@@ -195,6 +190,6 @@ void detectAndProcessExceptionDumps(void)
|
|||||||
waitInput(false);
|
waitInput(false);
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
memset32((void *)dumpHeader, 0, dumpHeader->totalSize);
|
memset((void *)dumpHeader, 0, dumpHeader->totalSize);
|
||||||
mcuPowerOff();
|
mcuPowerOff();
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -300,3 +300,31 @@ R0.13 (May 21, 2017)
|
|||||||
Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c)
|
Fixed exFAT FAT entry can be collapsed when write or lseek operation to the existing file is done. (appeared at R0.12c)
|
||||||
Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c)
|
Fixed creating a file can fail when a new cluster allocation to the exFAT directory occures. (appeared at R0.12c)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.13a (October 14, 2017)
|
||||||
|
|
||||||
|
Added support for UTF-8 encoding on the API. (FF_LFN_UNICODE = 2)
|
||||||
|
Added options for file name output buffer. (FF_LFN_BUF, FF_SFN_BUF).
|
||||||
|
Added dynamic memory allocation option for working buffer of f_mkfs() and f_fdisk().
|
||||||
|
Fixed f_fdisk() and f_mkfs() create the partition table with wrong CHS parameters. (appeared at R0.09)
|
||||||
|
Fixed f_unlink() can cause lost clusters at fragmented file on the exFAT volume. (appeared at R0.12c)
|
||||||
|
Fixed f_setlabel() rejects some valid characters for exFAT volume. (appeared at R0.12)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.13b (April 07, 2018)
|
||||||
|
|
||||||
|
Added support for UTF-32 encoding on the API. (FF_LFN_UNICODE = 3)
|
||||||
|
Added support for Unix style volume ID. (FF_STR_VOLUME_ID = 2)
|
||||||
|
Fixed accesing any object on the exFAT root directory beyond the cluster boundary can fail. (appeared at R0.12c)
|
||||||
|
Fixed f_setlabel() does not reject some invalid characters. (appeared at R0.09b)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
R0.13c (October 14, 2018)
|
||||||
|
Supported stdint.h for C99 and later. (integer.h was included in ff.h)
|
||||||
|
Fixed reading a directory gets infinite loop when the last directory entry is not empty. (appeared at R0.12)
|
||||||
|
Fixed creating a sub-directory in the fragmented sub-directory on the exFAT volume collapses FAT chain of the parent directory. (appeared at R0.12)
|
||||||
|
Fixed f_getcwd() cause output buffer overrun when the buffer has a valid drive number. (appeared at R0.13b)
|
||||||
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
FatFs Module Source Files R0.13
|
FatFs Module Source Files R0.13c
|
||||||
|
|
||||||
|
|
||||||
FILES
|
FILES
|
||||||
@@ -10,7 +10,6 @@ FILES
|
|||||||
ff.h Common include file for FatFs and application module.
|
ff.h Common include file for FatFs and application module.
|
||||||
diskio.h Common include file for FatFs and disk I/O module.
|
diskio.h Common include file for FatFs and disk I/O module.
|
||||||
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
diskio.c An example of glue function to attach existing disk I/O module to FatFs.
|
||||||
integer.h Integer type definitions for FatFs.
|
|
||||||
ffunicode.c Optional Unicode utility functions.
|
ffunicode.c Optional Unicode utility functions.
|
||||||
ffsystem.c An example of optional O/S related functions.
|
ffsystem.c An example of optional O/S related functions.
|
||||||
|
|
||||||
@@ -10,6 +10,7 @@
|
|||||||
#include "diskio.h" /* FatFs lower layer API */
|
#include "diskio.h" /* FatFs lower layer API */
|
||||||
#include "sdmmc/sdmmc.h"
|
#include "sdmmc/sdmmc.h"
|
||||||
#include "../crypto.h"
|
#include "../crypto.h"
|
||||||
|
#include "../i2c.h"
|
||||||
|
|
||||||
/* Definitions of physical drive number for each media */
|
/* Definitions of physical drive number for each media */
|
||||||
#define SDCARD 0
|
#define SDCARD 0
|
||||||
@@ -20,11 +21,11 @@
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DSTATUS disk_status (
|
DSTATUS disk_status (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return RES_OK;
|
return RES_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -34,7 +35,7 @@ DSTATUS disk_status (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DSTATUS disk_initialize (
|
DSTATUS disk_initialize (
|
||||||
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
static u32 sdmmcInitResult = 4;
|
static u32 sdmmcInitResult = 4;
|
||||||
@@ -52,10 +53,10 @@ DSTATUS disk_initialize (
|
|||||||
/*-----------------------------------------------------------------------*/
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
DRESULT disk_read (
|
DRESULT disk_read (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
BYTE *buff, /* Data buffer to store read data */
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to read */
|
UINT count /* Number of sectors to read */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, buff)) ||
|
return ((pdrv == SDCARD && !sdmmc_sdcard_readsectors(sector, count, buff)) ||
|
||||||
@@ -70,10 +71,10 @@ DRESULT disk_read (
|
|||||||
|
|
||||||
#if _USE_WRITE
|
#if _USE_WRITE
|
||||||
DRESULT disk_write (
|
DRESULT disk_write (
|
||||||
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
const BYTE *buff, /* Data to be written */
|
const BYTE *buff, /* Data to be written */
|
||||||
DWORD sector, /* Sector address in LBA */
|
DWORD sector, /* Sector address in LBA */
|
||||||
UINT count /* Number of sectors to write */
|
UINT count /* Number of sectors to write */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return ((pdrv == SDCARD && (*(vu16 *)(SDMMC_BASE + REG_SDSTATUS0) & TMIO_STAT0_WRPROTECT) != 0 && !sdmmc_sdcard_writesectors(sector, count, buff)) ||
|
return ((pdrv == SDCARD && (*(vu16 *)(SDMMC_BASE + REG_SDSTATUS0) & TMIO_STAT0_WRPROTECT) != 0 && !sdmmc_sdcard_writesectors(sector, count, buff)) ||
|
||||||
@@ -89,13 +90,49 @@ DRESULT disk_write (
|
|||||||
|
|
||||||
#if _USE_IOCTL
|
#if _USE_IOCTL
|
||||||
DRESULT disk_ioctl (
|
DRESULT disk_ioctl (
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
BYTE pdrv, /* Physical drive nmuber (0..) */
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
BYTE cmd, /* Control code */
|
BYTE cmd, /* Control code */
|
||||||
__attribute__((unused))
|
__attribute__((unused))
|
||||||
void *buff /* Buffer to send/receive control data */
|
void *buff /* Buffer to send/receive control data */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
return cmd == CTRL_SYNC ? RES_OK : RES_PARERR;
|
return cmd == CTRL_SYNC ? RES_OK : RES_PARERR;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
// From GodMode9
|
||||||
|
#define BCDVALID(b) (((b)<=0x99)&&(((b)&0xF)<=0x9)&&((((b)>>4)&0xF)<=0x9))
|
||||||
|
#define BCD2NUM(b) (BCDVALID(b) ? (((b)&0xF)+((((b)>>4)&0xF)*10)) : 0xFF)
|
||||||
|
#define NUM2BCD(n) ((n<99) ? (((n/10)*0x10)|(n%10)) : 0x99)
|
||||||
|
#define DSTIMEGET(bcd,n) (BCD2NUM((bcd)->n))
|
||||||
|
|
||||||
|
// see: http://3dbrew.org/wiki/I2C_Registers#Device_3 (register 30)
|
||||||
|
typedef struct DsTime {
|
||||||
|
u8 bcd_s;
|
||||||
|
u8 bcd_m;
|
||||||
|
u8 bcd_h;
|
||||||
|
u8 weekday;
|
||||||
|
u8 bcd_D;
|
||||||
|
u8 bcd_M;
|
||||||
|
u8 bcd_Y;
|
||||||
|
u8 leap_count;
|
||||||
|
} DsTime;
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Get current FAT time */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DWORD get_fattime( void ) {
|
||||||
|
DsTime dstime;
|
||||||
|
I2C_readRegBuf(I2C_DEV_MCU, 0x30, (u8 *)&dstime, sizeof(DsTime));
|
||||||
|
DWORD fattime =
|
||||||
|
((DSTIMEGET(&dstime, bcd_s)&0x3F) >> 1 ) |
|
||||||
|
((DSTIMEGET(&dstime, bcd_m)&0x3F) << 5 ) |
|
||||||
|
((DSTIMEGET(&dstime, bcd_h)&0x3F) << 11) |
|
||||||
|
((DSTIMEGET(&dstime, bcd_D)&0x1F) << 16) |
|
||||||
|
((DSTIMEGET(&dstime, bcd_M)&0x0F) << 21) |
|
||||||
|
(((DSTIMEGET(&dstime, bcd_Y)+(2000-1980))&0x7F) << 25);
|
||||||
|
|
||||||
|
return fattime;
|
||||||
|
}
|
||||||
@@ -38,6 +38,7 @@ DRESULT disk_read (BYTE pdrv, BYTE* buff, DWORD sector, UINT count);
|
|||||||
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
DRESULT disk_write (BYTE pdrv, const BYTE* buff, DWORD sector, UINT count);
|
||||||
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
DRESULT disk_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||||
|
|
||||||
|
DWORD get_fattime( void ); // not a disk control function, but fits here
|
||||||
|
|
||||||
/* Disk Status Bits (DSTATUS) */
|
/* Disk Status Bits (DSTATUS) */
|
||||||
|
|
||||||
File diff suppressed because it is too large
Load Diff
@@ -1,8 +1,8 @@
|
|||||||
/*----------------------------------------------------------------------------/
|
/*----------------------------------------------------------------------------/
|
||||||
/ FatFs - Generic FAT Filesystem module R0.13 /
|
/ FatFs - Generic FAT Filesystem module R0.13c /
|
||||||
/-----------------------------------------------------------------------------/
|
/-----------------------------------------------------------------------------/
|
||||||
/
|
/
|
||||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
@@ -20,13 +20,12 @@
|
|||||||
|
|
||||||
|
|
||||||
#ifndef FF_DEFINED
|
#ifndef FF_DEFINED
|
||||||
#define FF_DEFINED 87030 /* Revision ID */
|
#define FF_DEFINED 86604 /* Revision ID */
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include "integer.h" /* Basic integer types */
|
|
||||||
#include "ffconf.h" /* FatFs configuration options */
|
#include "ffconf.h" /* FatFs configuration options */
|
||||||
|
|
||||||
#if FF_DEFINED != FFCONF_DEF
|
#if FF_DEFINED != FFCONF_DEF
|
||||||
@@ -34,6 +33,30 @@ extern "C" {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* Integer types used for FatFs API */
|
||||||
|
|
||||||
|
#if defined(_WIN32) /* Main development platform */
|
||||||
|
#define FF_INTDEF 2
|
||||||
|
#include <windows.h>
|
||||||
|
typedef unsigned __int64 QWORD;
|
||||||
|
#elif (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || defined(__cplusplus) /* C99 or later */
|
||||||
|
#define FF_INTDEF 2
|
||||||
|
#include <stdint.h>
|
||||||
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
|
typedef uint16_t WORD; /* 16-bit unsigned integer */
|
||||||
|
typedef uint16_t WCHAR; /* 16-bit unsigned integer */
|
||||||
|
typedef uint32_t DWORD; /* 32-bit unsigned integer */
|
||||||
|
typedef uint64_t QWORD; /* 64-bit unsigned integer */
|
||||||
|
#else /* Earlier than C99 */
|
||||||
|
#define FF_INTDEF 1
|
||||||
|
typedef unsigned int UINT; /* int must be 16-bit or 32-bit */
|
||||||
|
typedef unsigned char BYTE; /* char must be 8-bit */
|
||||||
|
typedef unsigned short WORD; /* 16-bit unsigned integer */
|
||||||
|
typedef unsigned short WCHAR; /* 16-bit unsigned integer */
|
||||||
|
typedef unsigned long DWORD; /* 32-bit unsigned integer */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
/* Definitions of volume management */
|
/* Definitions of volume management */
|
||||||
|
|
||||||
@@ -45,24 +68,39 @@ typedef struct {
|
|||||||
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if FF_STR_VOLUME_ID
|
||||||
|
#ifndef FF_VOLUME_STRS
|
||||||
|
extern const char* VolumeStr[FF_VOLUMES]; /* User defied volume ID */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* Type of path name strings on FatFs API */
|
/* Type of path name strings on FatFs API */
|
||||||
|
|
||||||
#if FF_LFN_UNICODE && FF_USE_LFN /* Unicode (UTF-16) string */
|
|
||||||
#ifndef _INC_TCHAR
|
#ifndef _INC_TCHAR
|
||||||
|
#define _INC_TCHAR
|
||||||
|
|
||||||
|
#if FF_USE_LFN && FF_LFN_UNICODE == 1 /* Unicode in UTF-16 encoding */
|
||||||
typedef WCHAR TCHAR;
|
typedef WCHAR TCHAR;
|
||||||
#define _T(x) L ## x
|
#define _T(x) L ## x
|
||||||
#define _TEXT(x) L ## x
|
#define _TEXT(x) L ## x
|
||||||
#define _INC_TCHAR
|
#elif FF_USE_LFN && FF_LFN_UNICODE == 2 /* Unicode in UTF-8 encoding */
|
||||||
#endif
|
typedef char TCHAR;
|
||||||
#else /* ANSI/OEM string */
|
#define _T(x) u8 ## x
|
||||||
#ifndef _INC_TCHAR
|
#define _TEXT(x) u8 ## x
|
||||||
|
#elif FF_USE_LFN && FF_LFN_UNICODE == 3 /* Unicode in UTF-32 encoding */
|
||||||
|
typedef DWORD TCHAR;
|
||||||
|
#define _T(x) U ## x
|
||||||
|
#define _TEXT(x) U ## x
|
||||||
|
#elif FF_USE_LFN && (FF_LFN_UNICODE < 0 || FF_LFN_UNICODE > 3)
|
||||||
|
#error Wrong FF_LFN_UNICODE setting
|
||||||
|
#else /* ANSI/OEM code in SBCS/DBCS */
|
||||||
typedef char TCHAR;
|
typedef char TCHAR;
|
||||||
#define _T(x) x
|
#define _T(x) x
|
||||||
#define _TEXT(x) x
|
#define _TEXT(x) x
|
||||||
#define _INC_TCHAR
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
@@ -70,8 +108,8 @@ typedef char TCHAR;
|
|||||||
/* Type of file size variables */
|
/* Type of file size variables */
|
||||||
|
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
#if !FF_USE_LFN
|
#if FF_INTDEF != 2
|
||||||
#error LFN must be enabled when enable exFAT
|
#error exFAT feature wants C99 or later
|
||||||
#endif
|
#endif
|
||||||
typedef QWORD FSIZE_t;
|
typedef QWORD FSIZE_t;
|
||||||
#else
|
#else
|
||||||
@@ -83,8 +121,8 @@ typedef DWORD FSIZE_t;
|
|||||||
/* Filesystem object structure (FATFS) */
|
/* Filesystem object structure (FATFS) */
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
BYTE fs_type; /* Filesystem type (0:N/A) */
|
BYTE fs_type; /* Filesystem type (0:not mounted) */
|
||||||
BYTE pdrv; /* Physical drive number */
|
BYTE pdrv; /* Associated physical drive */
|
||||||
BYTE n_fats; /* Number of FATs (1 or 2) */
|
BYTE n_fats; /* Number of FATs (1 or 2) */
|
||||||
BYTE wflag; /* win[] flag (b0:dirty) */
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
@@ -121,6 +159,9 @@ typedef struct {
|
|||||||
DWORD fatbase; /* FAT base sector */
|
DWORD fatbase; /* FAT base sector */
|
||||||
DWORD dirbase; /* Root directory base sector/cluster */
|
DWORD dirbase; /* Root directory base sector/cluster */
|
||||||
DWORD database; /* Data base sector */
|
DWORD database; /* Data base sector */
|
||||||
|
#if FF_FS_EXFAT
|
||||||
|
DWORD bitbase; /* Allocation bitmap base sector */
|
||||||
|
#endif
|
||||||
DWORD winsect; /* Current sector appearing in the win[] */
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
BYTE win[FF_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
} FATFS;
|
} FATFS;
|
||||||
@@ -133,7 +174,7 @@ typedef struct {
|
|||||||
FATFS* fs; /* Pointer to the hosting volume of this object */
|
FATFS* fs; /* Pointer to the hosting volume of this object */
|
||||||
WORD id; /* Hosting volume mount ID */
|
WORD id; /* Hosting volume mount ID */
|
||||||
BYTE attr; /* Object attribute */
|
BYTE attr; /* Object attribute */
|
||||||
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:flagmented in this session, b2:sub-directory stretched) */
|
BYTE stat; /* Object chain status (b1-0: =0:not contiguous, =2:contiguous, =3:fragmented in this session, b2:sub-directory stretched) */
|
||||||
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
DWORD sclust; /* Object data start cluster (0:no cluster or root directory) */
|
||||||
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
FSIZE_t objsize; /* Object size (valid when sclust != 0) */
|
||||||
#if FF_FS_EXFAT
|
#if FF_FS_EXFAT
|
||||||
@@ -200,10 +241,10 @@ typedef struct {
|
|||||||
WORD ftime; /* Modified time */
|
WORD ftime; /* Modified time */
|
||||||
BYTE fattrib; /* File attribute */
|
BYTE fattrib; /* File attribute */
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN
|
||||||
TCHAR altname[13]; /* Altenative file name */
|
TCHAR altname[FF_SFN_BUF + 1];/* Altenative file name */
|
||||||
TCHAR fname[FF_MAX_LFN + 1]; /* Primary file name */
|
TCHAR fname[FF_LFN_BUF + 1]; /* Primary file name */
|
||||||
#else
|
#else
|
||||||
TCHAR fname[13]; /* File name */
|
TCHAR fname[12 + 1]; /* File name */
|
||||||
#endif
|
#endif
|
||||||
} FILINFO;
|
} FILINFO;
|
||||||
|
|
||||||
@@ -299,10 +340,10 @@ DWORD get_fattime (void);
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* LFN support functions */
|
/* LFN support functions */
|
||||||
#if FF_USE_LFN /* Code conversion (defined in unicode.c) */
|
#if FF_USE_LFN >= 1 /* Code conversion (defined in unicode.c) */
|
||||||
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
|
WCHAR ff_oem2uni (WCHAR oem, WORD cp); /* OEM code to Unicode conversion */
|
||||||
WCHAR ff_uni2oem (WCHAR uni, WORD cp); /* Unicode to OEM code conversion */
|
WCHAR ff_uni2oem (DWORD uni, WORD cp); /* Unicode to OEM code conversion */
|
||||||
WCHAR ff_wtoupper (WCHAR uni); /* Unicode upper-case conversion */
|
DWORD ff_wtoupper (DWORD uni); /* Unicode upper-case conversion */
|
||||||
#endif
|
#endif
|
||||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||||
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ FatFs - Configuration file
|
/ FatFs Functional Configurations
|
||||||
/---------------------------------------------------------------------------*/
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#define FFCONF_DEF 87030 /* Revision ID */
|
#define FFCONF_DEF 86604 /* Revision ID */
|
||||||
|
|
||||||
/*---------------------------------------------------------------------------/
|
/*---------------------------------------------------------------------------/
|
||||||
/ Function Configurations
|
/ Function Configurations
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
#define FF_FS_MINIMIZE 0
|
#define FF_FS_MINIMIZE 0
|
||||||
/* This option defines minimization level to remove some basic API functions.
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
/
|
/
|
||||||
/ 0: All basic functions are enabled.
|
/ 0: Basic functions are fully enabled.
|
||||||
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
|
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_truncate() and f_rename()
|
||||||
/ are removed.
|
/ are removed.
|
||||||
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||||
@@ -106,32 +106,47 @@
|
|||||||
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||||
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||||
/
|
/
|
||||||
/ To enable the LFN, Unicode handling functions (option/unicode.c) must be added
|
/ To enable the LFN, ffunicode.c needs to be added to the project. The LFN function
|
||||||
/ to the project. The working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
/ requiers certain internal working buffer occupies (FF_MAX_LFN + 1) * 2 bytes and
|
||||||
/ additional 608 bytes at exFAT enabled. FF_MAX_LFN can be in range from 12 to 255.
|
/ additional (FF_MAX_LFN + 44) / 15 * 32 bytes when exFAT is enabled.
|
||||||
/ It should be set 255 to support full featured LFN operations.
|
/ The FF_MAX_LFN defines size of the working buffer in UTF-16 code unit and it can
|
||||||
|
/ be in range of 12 to 255. It is recommended to be set 255 to fully support LFN
|
||||||
|
/ specification.
|
||||||
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
/ When use stack for the working buffer, take care on stack overflow. When use heap
|
||||||
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
/ memory for the working buffer, memory management functions, ff_memalloc() and
|
||||||
/ ff_memfree(), must be added to the project. */
|
/ ff_memfree() in ffsystem.c, need to be added to the project. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_LFN_UNICODE 0
|
#define FF_LFN_UNICODE 2
|
||||||
/* This option switches character encoding on the API, 0:ANSI/OEM or 1:UTF-16,
|
/* This option switches the character encoding on the API when LFN is enabled.
|
||||||
/ when LFN is enabled. Also behavior of string I/O functions will be affected by
|
/
|
||||||
/ this option. When LFN is not enabled, this option has no effect.
|
/ 0: ANSI/OEM in current CP (TCHAR = char)
|
||||||
*/
|
/ 1: Unicode in UTF-16 (TCHAR = WCHAR)
|
||||||
|
/ 2: Unicode in UTF-8 (TCHAR = char)
|
||||||
|
/ 3: Unicode in UTF-32 (TCHAR = DWORD)
|
||||||
|
/
|
||||||
|
/ Also behavior of string I/O functions will be affected by this option.
|
||||||
|
/ When LFN is not enabled, this option has no effect. */
|
||||||
|
|
||||||
|
|
||||||
|
#define FF_LFN_BUF 255
|
||||||
|
#define FF_SFN_BUF 12
|
||||||
|
/* This set of options defines size of file name members in the FILINFO structure
|
||||||
|
/ which is used to read out directory items. These values should be suffcient for
|
||||||
|
/ the file names to read. The maximum possible length of the read file name depends
|
||||||
|
/ on character encoding. When LFN is not enabled, these options have no effect. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_STRF_ENCODE 3
|
#define FF_STRF_ENCODE 3
|
||||||
/* When FF_LFN_UNICODE = 1 with LFN enabled, string I/O functions, f_gets(),
|
/* When FF_LFN_UNICODE >= 1 with LFN enabled, string I/O functions, f_gets(),
|
||||||
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
|
/ f_putc(), f_puts and f_printf() convert the character encoding in it.
|
||||||
/ This option selects assumption of character encoding ON THE FILE to be
|
/ This option selects assumption of character encoding ON THE FILE to be
|
||||||
/ read/written via those functions.
|
/ read/written via those functions.
|
||||||
/
|
/
|
||||||
/ 0: ANSI/OEM
|
/ 0: ANSI/OEM in current CP
|
||||||
/ 1: UTF-16LE
|
/ 1: Unicode in UTF-16LE
|
||||||
/ 2: UTF-16BE
|
/ 2: Unicode in UTF-16BE
|
||||||
/ 3: UTF-8
|
/ 3: Unicode in UTF-8
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
@@ -154,11 +169,16 @@
|
|||||||
|
|
||||||
#define FF_STR_VOLUME_ID 0
|
#define FF_STR_VOLUME_ID 0
|
||||||
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
|
#define FF_VOLUME_STRS "RAM","NAND","CF","SD","SD2","USB","USB2","USB3"
|
||||||
/* FF_STR_VOLUME_ID switches string support for volume ID.
|
/* FF_STR_VOLUME_ID switches support for volume ID in arbitrary strings.
|
||||||
/ When FF_STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
/ When FF_STR_VOLUME_ID is set to 1 or 2, arbitrary strings can be used as drive
|
||||||
/ number in the path name. FF_VOLUME_STRS defines the drive ID strings for each
|
/ number in the path name. FF_VOLUME_STRS defines the volume ID strings for each
|
||||||
/ logical drives. Number of items must be equal to FF_VOLUMES. Valid characters for
|
/ logical drives. Number of items must not be less than FF_VOLUMES. Valid
|
||||||
/ the drive ID strings are: A-Z and 0-9. */
|
/ characters for the volume ID strings are A-Z, a-z and 0-9, however, they are
|
||||||
|
/ compared in case-insensitive. If FF_STR_VOLUME_ID >= 1 and FF_VOLUME_STRS is
|
||||||
|
/ not defined, a user defined volume string table needs to be defined as:
|
||||||
|
/
|
||||||
|
/ const char* VolumeStr[FF_VOLUMES] = {"ram","flash","sd","usb",...
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
#define FF_MULTI_PARTITION 0
|
#define FF_MULTI_PARTITION 0
|
||||||
@@ -212,17 +232,17 @@
|
|||||||
|
|
||||||
#define FF_FS_EXFAT 0
|
#define FF_FS_EXFAT 0
|
||||||
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
/* This option switches support for exFAT filesystem. (0:Disable or 1:Enable)
|
||||||
/ When enable exFAT, also LFN needs to be enabled.
|
/ To enable exFAT, also LFN needs to be enabled. (FF_USE_LFN >= 1)
|
||||||
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
/ Note that enabling exFAT discards ANSI C (C89) compatibility. */
|
||||||
|
|
||||||
|
|
||||||
#define FF_FS_NORTC 1
|
#define FF_FS_NORTC 0
|
||||||
#define FF_NORTC_MON 5
|
#define FF_NORTC_MON 1
|
||||||
#define FF_NORTC_MDAY 1
|
#define FF_NORTC_MDAY 1
|
||||||
#define FF_NORTC_YEAR 2017
|
#define FF_NORTC_YEAR 2019
|
||||||
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
|
/* The option FF_FS_NORTC switches timestamp functiton. If the system does not have
|
||||||
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
/ any RTC function or valid timestamp is not needed, set FF_FS_NORTC = 1 to disable
|
||||||
/ the timestamp function. All objects modified by FatFs will have a fixed timestamp
|
/ the timestamp function. Every object modified by FatFs will have a fixed timestamp
|
||||||
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
/ defined by FF_NORTC_MON, FF_NORTC_MDAY and FF_NORTC_YEAR in local time.
|
||||||
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
/ To enable timestamp function (FF_FS_NORTC = 0), get_fattime() function need to be
|
||||||
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
/ added to the project to read current time form real-time clock. FF_NORTC_MON,
|
||||||
@@ -242,6 +262,7 @@
|
|||||||
/ lock control is independent of re-entrancy. */
|
/ lock control is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
|
/* #include <somertos.h> // O/S definitions */
|
||||||
#define FF_FS_REENTRANT 0
|
#define FF_FS_REENTRANT 0
|
||||||
#define FF_FS_TIMEOUT 1000
|
#define FF_FS_TIMEOUT 1000
|
||||||
#define FF_SYNC_t HANDLE
|
#define FF_SYNC_t HANDLE
|
||||||
@@ -262,8 +283,6 @@
|
|||||||
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
/ SemaphoreHandle_t and etc. A header file for O/S definitions needs to be
|
||||||
/ included somewhere in the scope of ff.h. */
|
/ included somewhere in the scope of ff.h. */
|
||||||
|
|
||||||
/* #include <windows.h> // O/S definitions */
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*--- End of configuration options ---*/
|
/*--- End of configuration options ---*/
|
||||||
@@ -1,20 +1,19 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Sample code of OS dependent controls for FatFs */
|
/* Sample Code of OS Dependent Functions for FatFs */
|
||||||
/* (C)ChaN, 2017 */
|
/* (C)ChaN, 2018 */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
#if FF_USE_LFN == 3 /* Dynamic memory allocation */
|
||||||
|
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Allocate a memory block */
|
/* Allocate a memory block */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on not enough core) */
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block (null if not enough core) */
|
||||||
UINT msize /* Number of bytes to allocate */
|
UINT msize /* Number of bytes to allocate */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -27,7 +26,7 @@ void* ff_memalloc ( /* Returns pointer to the allocated memory block (null on no
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
void ff_memfree (
|
void ff_memfree (
|
||||||
void* mblock /* Pointer to the memory block to free */
|
void* mblock /* Pointer to the memory block to free (nothing to do if null) */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
free(mblock); /* Free the memory block with POSIX API */
|
free(mblock); /* Free the memory block with POSIX API */
|
||||||
@@ -47,12 +46,12 @@ void ff_memfree (
|
|||||||
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
/ When a 0 is returned, the f_mount() function fails with FR_INT_ERR.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//const osMutexDef_t Mutex[FF_VOLUMES]; /* CMSIS-RTOS */
|
//const osMutexDef_t Mutex[FF_VOLUMES]; /* Table of CMSIS-RTOS mutex */
|
||||||
|
|
||||||
|
|
||||||
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object */
|
||||||
BYTE vol, /* Corresponding volume (logical drive number) */
|
BYTE vol, /* Corresponding volume (logical drive number) */
|
||||||
FF_SYNC_t *sobj /* Pointer to return the created sync object */
|
FF_SYNC_t* sobj /* Pointer to return the created sync object */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Win32 */
|
/* Win32 */
|
||||||
@@ -74,7 +73,7 @@ int ff_cre_syncobj ( /* 1:Function succeeded, 0:Could not create the sync object
|
|||||||
// return (int)(*sobj != NULL);
|
// return (int)(*sobj != NULL);
|
||||||
|
|
||||||
/* CMSIS-RTOS */
|
/* CMSIS-RTOS */
|
||||||
// *sobj = osMutexCreate(Mutex + vol);
|
// *sobj = osMutexCreate(&Mutex[vol]);
|
||||||
// return (int)(*sobj != NULL);
|
// return (int)(*sobj != NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* Unicode handling functions for FatFs R0.13+ */
|
/* Unicode handling functions for FatFs R0.13c */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
/* This module will occupy a huge memory in the .const section when the /
|
/* This module will occupy a huge memory in the .const section when the /
|
||||||
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
/ FatFs is configured for LFN with DBCS. If the system has any Unicode /
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
/ that function to avoid silly memory consumption. /
|
/ that function to avoid silly memory consumption. /
|
||||||
/-------------------------------------------------------------------------*/
|
/-------------------------------------------------------------------------*/
|
||||||
/*
|
/*
|
||||||
/ Copyright (C) 2017, ChaN, all right reserved.
|
/ Copyright (C) 2018, ChaN, all right reserved.
|
||||||
/
|
/
|
||||||
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
/ FatFs module is an open source software. Redistribution and use of FatFs in
|
||||||
/ source and binary forms, with or without modification, are permitted provided
|
/ source and binary forms, with or without modification, are permitted provided
|
||||||
@@ -25,7 +25,11 @@
|
|||||||
|
|
||||||
#include "ff.h"
|
#include "ff.h"
|
||||||
|
|
||||||
#if FF_USE_LFN
|
#if FF_USE_LFN /* This module will be blanked at non-LFN configuration */
|
||||||
|
|
||||||
|
#if FF_DEFINED != 86604 /* Revision ID */
|
||||||
|
#error Wrong include file (ff.h).
|
||||||
|
#endif
|
||||||
|
|
||||||
#define MERGE2(a, b) a ## b
|
#define MERGE2(a, b) a ## b
|
||||||
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
|
#define CVTBL(tbl, cp) MERGE2(tbl, cp)
|
||||||
@@ -36,8 +40,7 @@
|
|||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */
|
#if FF_CODE_PAGE == 932 || FF_CODE_PAGE == 0 /* Japanese */
|
||||||
static
|
static const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
|
||||||
const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
|
|
||||||
0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180,
|
0x00A7, 0x8198, 0x00A8, 0x814E, 0x00B0, 0x818B, 0x00B1, 0x817D, 0x00B4, 0x814C, 0x00B6, 0x81F7, 0x00D7, 0x817E, 0x00F7, 0x8180,
|
||||||
0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6,
|
0x0391, 0x839F, 0x0392, 0x83A0, 0x0393, 0x83A1, 0x0394, 0x83A2, 0x0395, 0x83A3, 0x0396, 0x83A4, 0x0397, 0x83A5, 0x0398, 0x83A6,
|
||||||
0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE,
|
0x0399, 0x83A7, 0x039A, 0x83A8, 0x039B, 0x83A9, 0x039C, 0x83AA, 0x039D, 0x83AB, 0x039E, 0x83AC, 0x039F, 0x83AD, 0x03A0, 0x83AE,
|
||||||
@@ -964,8 +967,7 @@ const WCHAR uni2oem932[] = { /* Unicode --> Shift_JIS pairs */
|
|||||||
0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0
|
0xFFE1, 0x8192, 0xFFE2, 0x81CA, 0xFFE3, 0x8150, 0xFFE4, 0xFA55, 0xFFE5, 0x818F, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
static const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
|
||||||
const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
|
|
||||||
0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68,
|
0x00A1, 0xFF61, 0x00A2, 0xFF62, 0x00A3, 0xFF63, 0x00A4, 0xFF64, 0x00A5, 0xFF65, 0x00A6, 0xFF66, 0x00A7, 0xFF67, 0x00A8, 0xFF68,
|
||||||
0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70,
|
0x00A9, 0xFF69, 0x00AA, 0xFF6A, 0x00AB, 0xFF6B, 0x00AC, 0xFF6C, 0x00AD, 0xFF6D, 0x00AE, 0xFF6E, 0x00AF, 0xFF6F, 0x00B0, 0xFF70,
|
||||||
0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78,
|
0x00B1, 0xFF71, 0x00B2, 0xFF72, 0x00B3, 0xFF73, 0x00B4, 0xFF74, 0x00B5, 0xFF75, 0x00B6, 0xFF76, 0x00B7, 0xFF77, 0x00B8, 0xFF78,
|
||||||
@@ -1894,8 +1896,7 @@ const WCHAR oem2uni932[] = { /* Shift_JIS --> Unicode pairs */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */
|
#if FF_CODE_PAGE == 936 || FF_CODE_PAGE == 0 /* Simplified Chinese */
|
||||||
static
|
static const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
|
||||||
const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
|
|
||||||
0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,
|
0x00A4, 0xA1E8, 0x00A7, 0xA1EC, 0x00A8, 0xA1A7, 0x00B0, 0xA1E3, 0x00B1, 0xA1C0, 0x00B7, 0xA1A4, 0x00D7, 0xA1C1, 0x00E0, 0xA8A4,
|
||||||
0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE,
|
0x00E1, 0xA8A2, 0x00E8, 0xA8A8, 0x00E9, 0xA8A6, 0x00EA, 0xA8BA, 0x00EC, 0xA8AC, 0x00ED, 0xA8AA, 0x00F2, 0xA8B0, 0x00F3, 0xA8AE,
|
||||||
0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9,
|
0x00F7, 0xA1C2, 0x00F9, 0xA8B4, 0x00FA, 0xA8B2, 0x00FC, 0xA8B9, 0x0101, 0xA8A1, 0x0113, 0xA8A5, 0x011B, 0xA8A7, 0x012B, 0xA8A9,
|
||||||
@@ -4623,8 +4624,7 @@ const WCHAR uni2oem936[] = { /* Unicode --> GBK pairs */
|
|||||||
0, 0
|
0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
static const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
|
||||||
const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
|
|
||||||
0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17,
|
0x0080, 0x20AC, 0x8140, 0x4E02, 0x8141, 0x4E04, 0x8142, 0x4E05, 0x8143, 0x4E06, 0x8144, 0x4E0F, 0x8145, 0x4E12, 0x8146, 0x4E17,
|
||||||
0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F,
|
0x8147, 0x4E1F, 0x8148, 0x4E20, 0x8149, 0x4E21, 0x814A, 0x4E23, 0x814B, 0x4E26, 0x814C, 0x4E29, 0x814D, 0x4E2E, 0x814E, 0x4E2F,
|
||||||
0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42,
|
0x814F, 0x4E31, 0x8150, 0x4E33, 0x8151, 0x4E35, 0x8152, 0x4E37, 0x8153, 0x4E3C, 0x8154, 0x4E40, 0x8155, 0x4E41, 0x8156, 0x4E42,
|
||||||
@@ -7354,8 +7354,7 @@ const WCHAR oem2uni936[] = { /* GBK --> Unicode pairs */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */
|
#if FF_CODE_PAGE == 949 || FF_CODE_PAGE == 0 /* Korean */
|
||||||
static
|
static const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
|
||||||
const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
|
|
||||||
0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6,
|
0x00A1, 0xA2AE, 0x00A4, 0xA2B4, 0x00A7, 0xA1D7, 0x00A8, 0xA1A7, 0x00AA, 0xA8A3, 0x00AD, 0xA1A9, 0x00AE, 0xA2E7, 0x00B0, 0xA1C6,
|
||||||
0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6,
|
0x00B1, 0xA1BE, 0x00B2, 0xA9F7, 0x00B3, 0xA9F8, 0x00B4, 0xA2A5, 0x00B6, 0xA2D2, 0x00B7, 0xA1A4, 0x00B8, 0xA2AC, 0x00B9, 0xA9F6,
|
||||||
0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF,
|
0x00BA, 0xA8AC, 0x00BC, 0xA8F9, 0x00BD, 0xA8F6, 0x00BE, 0xA8FA, 0x00BF, 0xA2AF, 0x00C6, 0xA8A1, 0x00D0, 0xA8A2, 0x00D7, 0xA1BF,
|
||||||
@@ -9490,8 +9489,7 @@ const WCHAR uni2oem949[] = { /* Unicode --> Korean pairs */
|
|||||||
0, 0
|
0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
static const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
|
||||||
const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
|
|
||||||
0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E,
|
0x8141, 0xAC02, 0x8142, 0xAC03, 0x8143, 0xAC05, 0x8144, 0xAC06, 0x8145, 0xAC0B, 0x8146, 0xAC0C, 0x8147, 0xAC0D, 0x8148, 0xAC0E,
|
||||||
0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25,
|
0x8149, 0xAC0F, 0x814A, 0xAC18, 0x814B, 0xAC1E, 0x814C, 0xAC1F, 0x814D, 0xAC21, 0x814E, 0xAC22, 0x814F, 0xAC23, 0x8150, 0xAC25,
|
||||||
0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32,
|
0x8151, 0xAC26, 0x8152, 0xAC27, 0x8153, 0xAC28, 0x8154, 0xAC29, 0x8155, 0xAC2A, 0x8156, 0xAC2B, 0x8157, 0xAC2E, 0x8158, 0xAC32,
|
||||||
@@ -11628,8 +11626,7 @@ const WCHAR oem2uni949[] = { /* Korean --> Unicode pairs */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */
|
#if FF_CODE_PAGE == 950 || FF_CODE_PAGE == 0 /* Traditional Chinese */
|
||||||
static
|
static const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
|
||||||
const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
|
|
||||||
0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE,
|
0x00A7, 0xA1B1, 0x00AF, 0xA1C2, 0x00B0, 0xA258, 0x00B1, 0xA1D3, 0x00B7, 0xA150, 0x00D7, 0xA1D1, 0x00F7, 0xA1D2, 0x02C7, 0xA3BE,
|
||||||
0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346,
|
0x02C9, 0xA3BC, 0x02CA, 0xA3BD, 0x02CB, 0xA3BF, 0x02CD, 0xA1C5, 0x02D9, 0xA3BB, 0x0391, 0xA344, 0x0392, 0xA345, 0x0393, 0xA346,
|
||||||
0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E,
|
0x0394, 0xA347, 0x0395, 0xA348, 0x0396, 0xA349, 0x0397, 0xA34A, 0x0398, 0xA34B, 0x0399, 0xA34C, 0x039A, 0xA34D, 0x039B, 0xA34E,
|
||||||
@@ -13320,8 +13317,7 @@ const WCHAR uni2oem950[] = { /* Unicode --> Big5 pairs */
|
|||||||
0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0
|
0xFF5C, 0xA155, 0xFF5D, 0xA162, 0xFF5E, 0xA1E3, 0xFFE0, 0xA246, 0xFFE1, 0xA247, 0xFFE3, 0xA1C3, 0xFFE5, 0xA244, 0, 0
|
||||||
};
|
};
|
||||||
|
|
||||||
static
|
static const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
|
||||||
const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
|
|
||||||
0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A,
|
0xA140, 0x3000, 0xA141, 0xFF0C, 0xA142, 0x3001, 0xA143, 0x3002, 0xA144, 0xFF0E, 0xA145, 0x2027, 0xA146, 0xFF1B, 0xA147, 0xFF1A,
|
||||||
0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52,
|
0xA148, 0xFF1F, 0xA149, 0xFF01, 0xA14A, 0xFE30, 0xA14B, 0x2026, 0xA14C, 0x2025, 0xA14D, 0xFE50, 0xA14E, 0xFE51, 0xA14F, 0xFE52,
|
||||||
0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31,
|
0xA150, 0x00B7, 0xA151, 0xFE54, 0xA152, 0xFE55, 0xA153, 0xFE56, 0xA154, 0xFE57, 0xA155, 0xFF5C, 0xA156, 0x2013, 0xA157, 0xFE31,
|
||||||
@@ -15014,8 +15010,7 @@ const WCHAR oem2uni950[] = { /* Big5 --> Unicode pairs */
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 437 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
|
||||||
const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
|
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
@@ -15027,8 +15022,7 @@ const WCHAR uc437[] = { /* CP437(U.S.) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 720 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
|
||||||
const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
|
|
||||||
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
|
0x0000, 0x0000, 0x00E9, 0x00E2, 0x0000, 0x00E0, 0x0000, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0000, 0x0000, 0x0000,
|
||||||
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
|
0x0000, 0x0651, 0x0652, 0x00F4, 0x00A4, 0x0640, 0x00FB, 0x00F9, 0x0621, 0x0622, 0x0623, 0x0624, 0x00A3, 0x0625, 0x0626, 0x0627,
|
||||||
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
|
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
|
||||||
@@ -15040,8 +15034,7 @@ const WCHAR uc720[] = { /* CP720(Arabic) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 737 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
|
||||||
const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
|
|
||||||
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
|
0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x0398, 0x0399, 0x039A, 0x039B, 0x039C, 0x039D, 0x039E, 0x039F, 0x03A0,
|
||||||
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
|
0x03A1, 0x03A3, 0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x03B4, 0x03B5, 0x03B6, 0x03B7, 0x03B8,
|
||||||
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
|
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
|
||||||
@@ -15053,8 +15046,7 @@ const WCHAR uc737[] = { /* CP737(Greek) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 771 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
|
||||||
const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
|
|
||||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||||
@@ -15066,8 +15058,7 @@ const WCHAR uc771[] = { /* CP771(KBL) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 775 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
|
||||||
const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
|
|
||||||
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
|
0x0106, 0x00FC, 0x00E9, 0x0101, 0x00E4, 0x0123, 0x00E5, 0x0107, 0x0142, 0x0113, 0x0156, 0x0157, 0x012B, 0x0179, 0x00C4, 0x00C5,
|
||||||
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
|
0x00C9, 0x00E6, 0x00C6, 0x014D, 0x00F6, 0x0122, 0x00A2, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x00A4,
|
||||||
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
|
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
|
||||||
@@ -15079,8 +15070,7 @@ const WCHAR uc775[] = { /* CP775(Baltic) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 850 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
|
||||||
const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
|
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x00D7, 0x0192,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
@@ -15092,8 +15082,7 @@ const WCHAR uc850[] = { /* CP850(Latin 1) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 852 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
|
||||||
const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x016F, 0x0107, 0x00E7, 0x0142, 0x00EB, 0x0150, 0x0151, 0x00EE, 0x0179, 0x00C4, 0x0106,
|
||||||
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
|
0x00C9, 0x0139, 0x013A, 0x00F4, 0x00F6, 0x013D, 0x013E, 0x015A, 0x015B, 0x00D6, 0x00DC, 0x0164, 0x0165, 0x0141, 0x00D7, 0x010D,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
|
||||||
@@ -15105,8 +15094,7 @@ const WCHAR uc852[] = { /* CP852(Latin 2) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 855 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
|
||||||
const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
|
|
||||||
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
|
0x0452, 0x0402, 0x0453, 0x0403, 0x0451, 0x0401, 0x0454, 0x0404, 0x0455, 0x0405, 0x0456, 0x0406, 0x0457, 0x0407, 0x0458, 0x0408,
|
||||||
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
|
0x0459, 0x0409, 0x045A, 0x040A, 0x045B, 0x040B, 0x045C, 0x040C, 0x045E, 0x040E, 0x045F, 0x040F, 0x044E, 0x042E, 0x044A, 0x042A,
|
||||||
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
|
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
|
||||||
@@ -15118,8 +15106,7 @@ const WCHAR uc855[] = { /* CP855(Cyrillic) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 857 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
|
||||||
const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x0131, 0x00C4, 0x00C5,
|
||||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
|
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x0130, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x015E, 0x015F,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
@@ -15131,8 +15118,7 @@ const WCHAR uc857[] = { /* CP857(Turkish) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 860 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
|
||||||
const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E3, 0x00E0, 0x00C1, 0x00E7, 0x00EA, 0x00CA, 0x00E8, 0x00CD, 0x00D4, 0x00EC, 0x00C3, 0x00C2,
|
||||||
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
|
0x00C9, 0x00C0, 0x00C8, 0x00F4, 0x00F5, 0x00F2, 0x00DA, 0x00F9, 0x00CC, 0x00D5, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x20A7, 0x00D3,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
@@ -15144,8 +15130,7 @@ const WCHAR uc860[] = { /* CP860(Portuguese) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 861 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
|
||||||
const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00D0, 0x00F0, 0x00DE, 0x00C4, 0x00C5,
|
||||||
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
|
0x00C9, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00FE, 0x00FB, 0x00DD, 0x00FD, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
@@ -15157,8 +15142,7 @@ const WCHAR uc861[] = { /* CP861(Icelandic) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 862 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
|
||||||
const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
|
|
||||||
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
0x05D0, 0x05D1, 0x05D2, 0x05D3, 0x05D4, 0x05D5, 0x05D6, 0x05D7, 0x05D8, 0x05D9, 0x05DA, 0x05DB, 0x05DC, 0x05DD, 0x05DE, 0x05DF,
|
||||||
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
|
0x05E0, 0x05E1, 0x05E2, 0x05E3, 0x05E4, 0x05E5, 0x05E6, 0x05E7, 0x05E8, 0x05E9, 0x05EA, 0x00A2, 0x00A3, 0x00A5, 0x20A7, 0x0192,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
@@ -15170,8 +15154,7 @@ const WCHAR uc862[] = { /* CP862(Hebrew) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 863 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
|
||||||
const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00C2, 0x00E0, 0x00B6, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x2017, 0x00C0,
|
||||||
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
|
0x00C9, 0x00C8, 0x00CA, 0x00F4, 0x00CB, 0x00CF, 0x00FB, 0x00F9, 0x00A4, 0x00D4, 0x00DC, 0x00A2, 0x00A3, 0x00D9, 0x00DB, 0x0192,
|
||||||
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
|
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
|
||||||
@@ -15183,8 +15166,7 @@ const WCHAR uc863[] = { /* CP863(Canadian French) to Unicode conversion table *
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 864 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
|
||||||
const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
|
|
||||||
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
|
0x00B0, 0x00B7, 0x2219, 0x221A, 0x2592, 0x2500, 0x2502, 0x253C, 0x2524, 0x252C, 0x251C, 0x2534, 0x2510, 0x250C, 0x2514, 0x2518,
|
||||||
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
|
0x03B2, 0x221E, 0x03C6, 0x00B1, 0x00BD, 0x00BC, 0x2248, 0x00AB, 0x00BB, 0xFEF7, 0xFEF8, 0x0000, 0x0000, 0xFEFB, 0xFEFC, 0x0000,
|
||||||
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
|
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
|
||||||
@@ -15196,8 +15178,7 @@ const WCHAR uc864[] = { /* CP864(Arabic) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 865 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
|
||||||
const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
|
|
||||||
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
0x00C7, 0x00FC, 0x00E9, 0x00E2, 0x00E4, 0x00E0, 0x00E5, 0x00E7, 0x00EA, 0x00EB, 0x00E8, 0x00EF, 0x00EE, 0x00EC, 0x00C4, 0x00C5,
|
||||||
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
|
0x00C5, 0x00E6, 0x00C6, 0x00F4, 0x00F6, 0x00F2, 0x00FB, 0x00F9, 0x00FF, 0x00D6, 0x00DC, 0x00F8, 0x00A3, 0x00D8, 0x20A7, 0x0192,
|
||||||
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
|
||||||
@@ -15209,8 +15190,7 @@ const WCHAR uc865[] = { /* CP865(Nordic) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 866 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
|
||||||
const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
|
|
||||||
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416, 0x0417, 0x0418, 0x0419, 0x041A, 0x041B, 0x041C, 0x041D, 0x041E, 0x041F,
|
||||||
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426, 0x0427, 0x0428, 0x0429, 0x042A, 0x042B, 0x042C, 0x042D, 0x042E, 0x042F,
|
||||||
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||||
@@ -15222,8 +15202,7 @@ const WCHAR uc866[] = { /* CP866(Russian) to Unicode conversion table */
|
|||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 869 || FF_CODE_PAGE == 0
|
||||||
static
|
static const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
|
||||||
const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
|
|
||||||
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
|
0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x00B7, 0x0386, 0x00B7, 0x00B7, 0x00AC, 0x00A6, 0x2018, 0x2019, 0x0388, 0x2015, 0x0389,
|
||||||
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
|
0x038A, 0x03AA, 0x038C, 0x00B7, 0x00B7, 0x038E, 0x03AB, 0x00A9, 0x038F, 0x00B2, 0x00B3, 0x03AC, 0x00A3, 0x03AD, 0x03AE, 0x03AF,
|
||||||
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
|
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
|
||||||
@@ -15245,7 +15224,7 @@ const WCHAR uc869[] = { /* CP869(Greek 2) to Unicode conversion table */
|
|||||||
|
|
||||||
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
|
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE < 900
|
||||||
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||||
WCHAR uni, /* Unicode character to be converted */
|
DWORD uni, /* UTF-16 encoded character to be converted */
|
||||||
WORD cp /* Code page for the conversion */
|
WORD cp /* Code page for the conversion */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -15253,15 +15232,16 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
|||||||
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
|
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
|
||||||
|
|
||||||
|
|
||||||
if (uni < 0x80) { /* ASCII char */
|
if (uni < 0x80) { /* ASCII? */
|
||||||
c = uni;
|
c = (WCHAR)uni;
|
||||||
|
|
||||||
} else { /* Non-ASCII char */
|
} else { /* Non-ASCII */
|
||||||
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
|
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
|
||||||
for (c = 0; c < 0x80 && uni != p[c]; c++) ;
|
for (c = 0; c < 0x80 && uni != p[c]; c++) ;
|
||||||
c = (c + 0x80) & 0xFF;
|
c = (c + 0x80) & 0xFF;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15274,7 +15254,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
|
const WCHAR *p = CVTBL(uc, FF_CODE_PAGE);
|
||||||
|
|
||||||
|
|
||||||
if (oem < 0x80) { /* ASCII char */
|
if (oem < 0x80) { /* ASCII? */
|
||||||
c = oem;
|
c = oem;
|
||||||
|
|
||||||
} else { /* Extended char */
|
} else { /* Extended char */
|
||||||
@@ -15282,6 +15262,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
if (oem < 0x100) c = p[oem - 0x80];
|
if (oem < 0x100) c = p[oem - 0x80];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15294,29 +15275,30 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
/* DBCS fixed code page */
|
/* DBCS fixed code page */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
#if FF_CODE_PAGE != 0 && FF_CODE_PAGE >= 900
|
#if FF_CODE_PAGE >= 900
|
||||||
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||||
WCHAR uni, /* Unicode character to be converted */
|
DWORD uni, /* UTF-16 encoded character to be converted */
|
||||||
WORD cp /* Code page for the conversion */
|
WORD cp /* Code page for the conversion */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const WCHAR *p;
|
const WCHAR *p;
|
||||||
WCHAR c = 0;
|
WCHAR c = 0, uc;
|
||||||
UINT i, n, li, hi;
|
UINT i = 0, n, li, hi;
|
||||||
|
|
||||||
|
|
||||||
if (uni < 0x80) { /* ASCII char */
|
if (uni < 0x80) { /* ASCII? */
|
||||||
c = uni;
|
c = (WCHAR)uni;
|
||||||
|
|
||||||
} else { /* Non-ASCII char */
|
} else { /* Non-ASCII */
|
||||||
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
|
if (uni < 0x10000 && cp == FF_CODE_PAGE) { /* Is it in BMP and valid code page? */
|
||||||
|
uc = (WCHAR)uni;
|
||||||
p = CVTBL(uni2oem, FF_CODE_PAGE);
|
p = CVTBL(uni2oem, FF_CODE_PAGE);
|
||||||
hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
|
hi = sizeof CVTBL(uni2oem, FF_CODE_PAGE) / 4 - 1;
|
||||||
li = 0;
|
li = 0;
|
||||||
for (n = 16; n; n--) {
|
for (n = 16; n; n--) {
|
||||||
i = li + (hi - li) / 2;
|
i = li + (hi - li) / 2;
|
||||||
if (uni == p[i * 2]) break;
|
if (uc == p[i * 2]) break;
|
||||||
if (uni > p[i * 2]) {
|
if (uc > p[i * 2]) {
|
||||||
li = i;
|
li = i;
|
||||||
} else {
|
} else {
|
||||||
hi = i;
|
hi = i;
|
||||||
@@ -15325,6 +15307,7 @@ WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
|||||||
if (n != 0) c = p[i * 2 + 1];
|
if (n != 0) c = p[i * 2 + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -15336,14 +15319,14 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
{
|
{
|
||||||
const WCHAR *p;
|
const WCHAR *p;
|
||||||
WCHAR c = 0;
|
WCHAR c = 0;
|
||||||
UINT i, n, li, hi;
|
UINT i = 0, n, li, hi;
|
||||||
|
|
||||||
|
|
||||||
if (oem < 0x80) { /* ASCII char */
|
if (oem < 0x80) { /* ASCII? */
|
||||||
c = oem;
|
c = oem;
|
||||||
|
|
||||||
} else { /* Extended char */
|
} else { /* Extended char */
|
||||||
if (cp == FF_CODE_PAGE) { /* Is it a valid code page? */
|
if (cp == FF_CODE_PAGE) { /* Is it valid code page? */
|
||||||
p = CVTBL(oem2uni, FF_CODE_PAGE);
|
p = CVTBL(oem2uni, FF_CODE_PAGE);
|
||||||
hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
|
hi = sizeof CVTBL(oem2uni, FF_CODE_PAGE) / 4 - 1;
|
||||||
li = 0;
|
li = 0;
|
||||||
@@ -15359,6 +15342,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
if (n != 0) c = p[i * 2 + 1];
|
if (n != 0) c = p[i * 2 + 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -15372,59 +15356,63 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
#if FF_CODE_PAGE == 0
|
#if FF_CODE_PAGE == 0
|
||||||
|
|
||||||
static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0};
|
static const WORD cp_code[] = { 437, 720, 737, 771, 775, 850, 852, 855, 857, 860, 861, 862, 863, 864, 865, 866, 869, 0};
|
||||||
static const WCHAR *const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
|
static const WCHAR* const cp_table[] = {uc437, uc720, uc737, uc771, uc775, uc850, uc852, uc855, uc857, uc860, uc861, uc862, uc863, uc864, uc865, uc866, uc869, 0};
|
||||||
|
|
||||||
|
|
||||||
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
WCHAR ff_uni2oem ( /* Returns OEM code character, zero on error */
|
||||||
WCHAR uni, /* Unicode character to be converted */
|
DWORD uni, /* UTF-16 encoded character to be converted */
|
||||||
WORD cp /* Code page for the conversion */
|
WORD cp /* Code page for the conversion */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
const WCHAR *p;
|
const WCHAR *p;
|
||||||
WCHAR c = 0;
|
WCHAR c = 0, uc;
|
||||||
UINT i, n, li, hi;
|
UINT i, n, li, hi;
|
||||||
|
|
||||||
|
|
||||||
if (uni < 0x80) { /* ASCII char */
|
if (uni < 0x80) { /* ASCII? */
|
||||||
c = uni;
|
c = (WCHAR)uni;
|
||||||
|
|
||||||
} else { /* Non-ASCII char */
|
} else { /* Non-ASCII */
|
||||||
p = 0;
|
if (uni < 0x10000) { /* Is it in BMP? */
|
||||||
if (cp < 900) { /* SBCS */
|
uc = (WCHAR)uni;
|
||||||
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get table */
|
p = 0;
|
||||||
p = cp_table[i];
|
if (cp < 900) { /* SBCS */
|
||||||
if (p) { /* Is it a valid CP ? */
|
for (i = 0; cp_code[i] != 0 && cp_code[i] != cp; i++) ; /* Get conversion table */
|
||||||
for (c = 0; c < 0x80 && uni != p[c]; c++) ; /* Find OEM code in the table */
|
p = cp_table[i];
|
||||||
c = (c + 0x80) & 0xFF;
|
if (p) { /* Is it valid code page ? */
|
||||||
}
|
for (c = 0; c < 0x80 && uc != p[c]; c++) ; /* Find OEM code in the table */
|
||||||
} else { /* DBCS */
|
c = (c + 0x80) & 0xFF;
|
||||||
switch (cp) {
|
}
|
||||||
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
|
} else { /* DBCS */
|
||||||
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
|
switch (cp) { /* Get conversion table */
|
||||||
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
|
case 932 : p = uni2oem932; hi = sizeof uni2oem932 / 4 - 1; break;
|
||||||
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
|
case 936 : p = uni2oem936; hi = sizeof uni2oem936 / 4 - 1; break;
|
||||||
}
|
case 949 : p = uni2oem949; hi = sizeof uni2oem949 / 4 - 1; break;
|
||||||
if (p) { /* Is it a valid code page? */
|
case 950 : p = uni2oem950; hi = sizeof uni2oem950 / 4 - 1; break;
|
||||||
li = 0;
|
}
|
||||||
for (n = 16; n; n--) { /* Find OEM code */
|
if (p) { /* Is it valid code page? */
|
||||||
i = li + (hi - li) / 2;
|
li = 0;
|
||||||
if (uni == p[i * 2]) break;
|
for (n = 16; n; n--) { /* Find OEM code */
|
||||||
if (uni > p[i * 2]) {
|
i = li + (hi - li) / 2;
|
||||||
li = i;
|
if (uc == p[i * 2]) break;
|
||||||
} else {
|
if (uc > p[i * 2]) {
|
||||||
hi = i;
|
li = i;
|
||||||
}
|
} else {
|
||||||
|
hi = i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (n != 0) c = p[i * 2 + 1];
|
||||||
}
|
}
|
||||||
if (n != 0) c = p[i * 2 + 1];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
||||||
WCHAR oem, /* OEM code to be converted */
|
WCHAR oem, /* OEM code to be converted (DBC if >=0x100) */
|
||||||
WORD cp /* Code page for the conversion */
|
WORD cp /* Code page for the conversion */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
@@ -15433,7 +15421,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
UINT i, n, li, hi;
|
UINT i, n, li, hi;
|
||||||
|
|
||||||
|
|
||||||
if (oem < 0x80) { /* ASCII char */
|
if (oem < 0x80) { /* ASCII? */
|
||||||
c = oem;
|
c = oem;
|
||||||
|
|
||||||
} else { /* Extended char */
|
} else { /* Extended char */
|
||||||
@@ -15466,6 +15454,7 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -15476,54 +15465,94 @@ WCHAR ff_oem2uni ( /* Returns Unicode character, zero on error */
|
|||||||
/* Unicode up-case conversion */
|
/* Unicode up-case conversion */
|
||||||
/*------------------------------------------------------------------------*/
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
WCHAR ff_wtoupper ( /* Returns up-converted character */
|
DWORD ff_wtoupper ( /* Returns up-converted code point */
|
||||||
WCHAR uni /* Unicode character to be upper converted (BMP only) */
|
DWORD uni /* Unicode code point to be up-converted */
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
/* Compressed upper conversion table */
|
const WORD *p;
|
||||||
static const WCHAR cvt1[] = { /* U+0000 - U+0FFF */
|
WORD uc, bc, nc, cmd;
|
||||||
|
static const WORD cvt1[] = { /* Compressed up conversion table for U+0000 - U+0FFF */
|
||||||
/* Basic Latin */
|
/* Basic Latin */
|
||||||
0x0061,0x031A,
|
0x0061,0x031A,
|
||||||
/* Latin-1 Supplement */
|
/* Latin-1 Supplement */
|
||||||
0x00E0,0x0317, 0x00F8,0x0307, 0x00FF,0x0001,0x0178,
|
0x00E0,0x0317,
|
||||||
|
0x00F8,0x0307,
|
||||||
|
0x00FF,0x0001,0x0178,
|
||||||
/* Latin Extended-A */
|
/* Latin Extended-A */
|
||||||
0x0100,0x0130, 0x0132,0x0106, 0x0139,0x0110, 0x014A,0x012E, 0x0179,0x0106,
|
0x0100,0x0130,
|
||||||
|
0x0132,0x0106,
|
||||||
|
0x0139,0x0110,
|
||||||
|
0x014A,0x012E,
|
||||||
|
0x0179,0x0106,
|
||||||
/* Latin Extended-B */
|
/* Latin Extended-B */
|
||||||
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
|
0x0180,0x004D,0x0243,0x0181,0x0182,0x0182,0x0184,0x0184,0x0186,0x0187,0x0187,0x0189,0x018A,0x018B,0x018B,0x018D,0x018E,0x018F,0x0190,0x0191,0x0191,0x0193,0x0194,0x01F6,0x0196,0x0197,0x0198,0x0198,0x023D,0x019B,0x019C,0x019D,0x0220,0x019F,0x01A0,0x01A0,0x01A2,0x01A2,0x01A4,0x01A4,0x01A6,0x01A7,0x01A7,0x01A9,0x01AA,0x01AB,0x01AC,0x01AC,0x01AE,0x01AF,0x01AF,0x01B1,0x01B2,0x01B3,0x01B3,0x01B5,0x01B5,0x01B7,0x01B8,0x01B8,0x01BA,0x01BB,0x01BC,0x01BC,0x01BE,0x01F7,0x01C0,0x01C1,0x01C2,0x01C3,0x01C4,0x01C5,0x01C4,0x01C7,0x01C8,0x01C7,0x01CA,0x01CB,0x01CA,
|
||||||
0x01CD,0x0110, 0x01DD,0x0001,0x018E, 0x01DE,0x0112, 0x01F3,0x0003,0x01F1,0x01F4,0x01F4, 0x01F8,0x0128,
|
0x01CD,0x0110,
|
||||||
0x0222,0x0112, 0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241, 0x0246,0x010A,
|
0x01DD,0x0001,0x018E,
|
||||||
|
0x01DE,0x0112,
|
||||||
|
0x01F3,0x0003,0x01F1,0x01F4,0x01F4,
|
||||||
|
0x01F8,0x0128,
|
||||||
|
0x0222,0x0112,
|
||||||
|
0x023A,0x0009,0x2C65,0x023B,0x023B,0x023D,0x2C66,0x023F,0x0240,0x0241,0x0241,
|
||||||
|
0x0246,0x010A,
|
||||||
/* IPA Extensions */
|
/* IPA Extensions */
|
||||||
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
|
0x0253,0x0040,0x0181,0x0186,0x0255,0x0189,0x018A,0x0258,0x018F,0x025A,0x0190,0x025C,0x025D,0x025E,0x025F,0x0193,0x0261,0x0262,0x0194,0x0264,0x0265,0x0266,0x0267,0x0197,0x0196,0x026A,0x2C62,0x026C,0x026D,0x026E,0x019C,0x0270,0x0271,0x019D,0x0273,0x0274,0x019F,0x0276,0x0277,0x0278,0x0279,0x027A,0x027B,0x027C,0x2C64,0x027E,0x027F,0x01A6,0x0281,0x0282,0x01A9,0x0284,0x0285,0x0286,0x0287,0x01AE,0x0244,0x01B1,0x01B2,0x0245,0x028D,0x028E,0x028F,0x0290,0x0291,0x01B7,
|
||||||
/* Greek, Coptic */
|
/* Greek, Coptic */
|
||||||
0x037B,0x0003,0x03FD,0x03FE,0x03FF, 0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A, 0x03B1,0x0311,
|
0x037B,0x0003,0x03FD,0x03FE,0x03FF,
|
||||||
0x03C2,0x0002,0x03A3,0x03A3, 0x03C4,0x0308, 0x03CC,0x0003,0x038C,0x038E,0x038F, 0x03D8,0x0118,
|
0x03AC,0x0004,0x0386,0x0388,0x0389,0x038A,
|
||||||
|
0x03B1,0x0311,
|
||||||
|
0x03C2,0x0002,0x03A3,0x03A3,
|
||||||
|
0x03C4,0x0308,
|
||||||
|
0x03CC,0x0003,0x038C,0x038E,0x038F,
|
||||||
|
0x03D8,0x0118,
|
||||||
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
|
0x03F2,0x000A,0x03F9,0x03F3,0x03F4,0x03F5,0x03F6,0x03F7,0x03F7,0x03F9,0x03FA,0x03FA,
|
||||||
/* Cyrillic */
|
/* Cyrillic */
|
||||||
0x0430,0x0320, 0x0450,0x0710, 0x0460,0x0122, 0x048A,0x0136, 0x04C1,0x010E, 0x04CF,0x0001,0x04C0, 0x04D0,0x0144,
|
0x0430,0x0320,
|
||||||
|
0x0450,0x0710,
|
||||||
|
0x0460,0x0122,
|
||||||
|
0x048A,0x0136,
|
||||||
|
0x04C1,0x010E,
|
||||||
|
0x04CF,0x0001,0x04C0,
|
||||||
|
0x04D0,0x0144,
|
||||||
/* Armenian */
|
/* Armenian */
|
||||||
0x0561,0x0426,
|
0x0561,0x0426,
|
||||||
|
|
||||||
0x0000
|
0x0000 /* EOT */
|
||||||
};
|
};
|
||||||
static const WCHAR cvt2[] = { /* U+1000 - U+FFFF */
|
static const WORD cvt2[] = { /* Compressed up conversion table for U+1000 - U+FFFF */
|
||||||
/* Phonetic Extensions */
|
/* Phonetic Extensions */
|
||||||
0x1D7D,0x0001,0x2C63,
|
0x1D7D,0x0001,0x2C63,
|
||||||
/* Latin Extended Additional */
|
/* Latin Extended Additional */
|
||||||
0x1E00,0x0196, 0x1EA0,0x015A,
|
0x1E00,0x0196,
|
||||||
|
0x1EA0,0x015A,
|
||||||
/* Greek Extended */
|
/* Greek Extended */
|
||||||
0x1F00,0x0608, 0x1F10,0x0606, 0x1F20,0x0608, 0x1F30,0x0608, 0x1F40,0x0606,
|
0x1F00,0x0608,
|
||||||
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F, 0x1F60,0x0608,
|
0x1F10,0x0606,
|
||||||
|
0x1F20,0x0608,
|
||||||
|
0x1F30,0x0608,
|
||||||
|
0x1F40,0x0606,
|
||||||
|
0x1F51,0x0007,0x1F59,0x1F52,0x1F5B,0x1F54,0x1F5D,0x1F56,0x1F5F,
|
||||||
|
0x1F60,0x0608,
|
||||||
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
|
0x1F70,0x000E,0x1FBA,0x1FBB,0x1FC8,0x1FC9,0x1FCA,0x1FCB,0x1FDA,0x1FDB,0x1FF8,0x1FF9,0x1FEA,0x1FEB,0x1FFA,0x1FFB,
|
||||||
0x1F80,0x0608, 0x1F90,0x0608, 0x1FA0,0x0608, 0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
|
0x1F80,0x0608,
|
||||||
0x1FCC,0x0001,0x1FC3, 0x1FD0,0x0602, 0x1FE0,0x0602, 0x1FE5,0x0001,0x1FEC, 0x1FF3,0x0001,0x1FFC,
|
0x1F90,0x0608,
|
||||||
|
0x1FA0,0x0608,
|
||||||
|
0x1FB0,0x0004,0x1FB8,0x1FB9,0x1FB2,0x1FBC,
|
||||||
|
0x1FCC,0x0001,0x1FC3,
|
||||||
|
0x1FD0,0x0602,
|
||||||
|
0x1FE0,0x0602,
|
||||||
|
0x1FE5,0x0001,0x1FEC,
|
||||||
|
0x1FF3,0x0001,0x1FFC,
|
||||||
/* Letterlike Symbols */
|
/* Letterlike Symbols */
|
||||||
0x214E,0x0001,0x2132,
|
0x214E,0x0001,0x2132,
|
||||||
/* Number forms */
|
/* Number forms */
|
||||||
0x2170,0x0210, 0x2184,0x0001,0x2183,
|
0x2170,0x0210,
|
||||||
|
0x2184,0x0001,0x2183,
|
||||||
/* Enclosed Alphanumerics */
|
/* Enclosed Alphanumerics */
|
||||||
0x24D0,0x051A, 0x2C30,0x042F,
|
0x24D0,0x051A,
|
||||||
|
0x2C30,0x042F,
|
||||||
/* Latin Extended-C */
|
/* Latin Extended-C */
|
||||||
0x2C60,0x0102, 0x2C67,0x0106, 0x2C75,0x0102,
|
0x2C60,0x0102,
|
||||||
|
0x2C67,0x0106, 0x2C75,0x0102,
|
||||||
/* Coptic */
|
/* Coptic */
|
||||||
0x2C80,0x0164,
|
0x2C80,0x0164,
|
||||||
/* Georgian Supplement */
|
/* Georgian Supplement */
|
||||||
@@ -15531,36 +15560,38 @@ WCHAR ff_wtoupper ( /* Returns up-converted character */
|
|||||||
/* Full-width */
|
/* Full-width */
|
||||||
0xFF41,0x031A,
|
0xFF41,0x031A,
|
||||||
|
|
||||||
0x0000
|
0x0000 /* EOT */
|
||||||
};
|
};
|
||||||
const WCHAR *p;
|
|
||||||
WCHAR bc, nc, cmd;
|
|
||||||
|
|
||||||
|
|
||||||
p = uni < 0x1000 ? cvt1 : cvt2;
|
if (uni < 0x10000) { /* Is it in BMP? */
|
||||||
for (;;) {
|
uc = (WORD)uni;
|
||||||
bc = *p++; /* Get block base */
|
p = uc < 0x1000 ? cvt1 : cvt2;
|
||||||
if (!bc || uni < bc) break;
|
for (;;) {
|
||||||
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
|
bc = *p++; /* Get the block base */
|
||||||
if (uni < bc + nc) { /* In the block? */
|
if (bc == 0 || uc < bc) break; /* Not matched? */
|
||||||
switch (cmd) {
|
nc = *p++; cmd = nc >> 8; nc &= 0xFF; /* Get processing command and block size */
|
||||||
case 0: uni = p[uni - bc]; break; /* Table conversion */
|
if (uc < bc + nc) { /* In the block? */
|
||||||
case 1: uni -= (uni - bc) & 1; break; /* Case pairs */
|
switch (cmd) {
|
||||||
case 2: uni -= 16; break; /* Shift -16 */
|
case 0: uc = p[uc - bc]; break; /* Table conversion */
|
||||||
case 3: uni -= 32; break; /* Shift -32 */
|
case 1: uc -= (uc - bc) & 1; break; /* Case pairs */
|
||||||
case 4: uni -= 48; break; /* Shift -48 */
|
case 2: uc -= 16; break; /* Shift -16 */
|
||||||
case 5: uni -= 26; break; /* Shift -26 */
|
case 3: uc -= 32; break; /* Shift -32 */
|
||||||
case 6: uni += 8; break; /* Shift +8 */
|
case 4: uc -= 48; break; /* Shift -48 */
|
||||||
case 7: uni -= 80; break; /* Shift -80 */
|
case 5: uc -= 26; break; /* Shift -26 */
|
||||||
case 8: uni -= 0x1C60; break; /* Shift -0x1C60 */
|
case 6: uc += 8; break; /* Shift +8 */
|
||||||
|
case 7: uc -= 80; break; /* Shift -80 */
|
||||||
|
case 8: uc -= 0x1C60; break; /* Shift -0x1C60 */
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
if (cmd == 0) p += nc; /* Skip table if needed */
|
||||||
}
|
}
|
||||||
if (!cmd) p += nc;
|
uni = uc;
|
||||||
}
|
}
|
||||||
|
|
||||||
return uni;
|
return uni;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* #if _USE_LFN */
|
#endif /* #if FF_USE_LFN */
|
||||||
@@ -476,7 +476,7 @@ u32 sdmmc_sdcard_init()
|
|||||||
{
|
{
|
||||||
u32 ret = 0;
|
u32 ret = 0;
|
||||||
InitSD();
|
InitSD();
|
||||||
if(Nand_Init() != 0) ret &= 1;
|
if(Nand_Init() != 0) ret |= 1;
|
||||||
if(SD_Init() != 0) ret &= 2;
|
if(SD_Init() != 0) ret |= 2;
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -31,13 +31,12 @@
|
|||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "patches.h"
|
#include "patches.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "emunand.h"
|
#include "emunand.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "../build/bundled.h"
|
#include "chainloader.h"
|
||||||
|
|
||||||
static Firm *firm = (Firm *)0x20001000;
|
static Firm *firm = (Firm *)0x20001000;
|
||||||
|
|
||||||
@@ -59,7 +58,7 @@ static __attribute__((noinline)) bool inRange(u32 as, u32 ae, u32 bs, u32 be)
|
|||||||
|
|
||||||
static bool checkFirm(u32 firmSize)
|
static bool checkFirm(u32 firmSize)
|
||||||
{
|
{
|
||||||
if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the ARM11 entrypoint to be zero in which case nothing is done on the ARM11 side
|
if(memcmp(firm->magic, "FIRM", 4) != 0 || firm->arm9Entry == NULL) //Allow for the Arm11 entrypoint to be zero in which case nothing is done on the Arm11 side
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
bool arm9EpFound = false,
|
bool arm9EpFound = false,
|
||||||
@@ -185,7 +184,7 @@ u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadF
|
|||||||
else if(ctrNandError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one.");
|
else if(ctrNandError) error("Unable to mount CTRNAND or load the CTRNAND FIRM.\nPlease use an external one.");
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check that the FIRM is right for the console from the ARM9 section address
|
//Check that the FIRM is right for the console from the Arm9 section address
|
||||||
if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
if((firm->section[3].offset != 0 ? firm->section[3].address : firm->section[2].address) != (ISN3DS ? (u8 *)0x8006000 : (u8 *)0x8006800))
|
||||||
error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND");
|
error("The %s FIRM is not for this console.", loadedFromStorage ? "external" : "CTRNAND");
|
||||||
|
|
||||||
@@ -282,7 +281,7 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
|||||||
if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D))
|
if(firmType == NATIVE_FIRM && (ISN3DS || firmVersion >= 0x1D))
|
||||||
{
|
{
|
||||||
//2) Merge that info with our own modules'
|
//2) Merge that info with our own modules'
|
||||||
for(u8 *src = (u8 *)0x18180000; src < (u8 *)(0x18180000 + LUMA_SECTION0_SIZE); src += srcModuleSize)
|
for(u8 *src = (u8 *)0x18180000; memcmp(((Cxi *)src)->ncch.magic, "NCCH", 4) == 0; src += srcModuleSize)
|
||||||
{
|
{
|
||||||
const char *name = ((Cxi *)src)->exHeader.systemControlInfo.appTitle;
|
const char *name = ((Cxi *)src)->exHeader.systemControlInfo.appTitle;
|
||||||
|
|
||||||
@@ -344,14 +343,14 @@ static inline void mergeSection0(FirmwareType firmType, u32 firmVersion, bool lo
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool isSafeMode, bool doUnitinfoPatch)
|
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool needToInitSd, bool doUnitinfoPatch)
|
||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + firm->section[2].offset,
|
u8 *arm9Section = (u8 *)firm + firm->section[2].offset,
|
||||||
*arm11Section1 = (u8 *)firm + firm->section[1].offset;
|
*arm11Section1 = (u8 *)firm + firm->section[1].offset;
|
||||||
|
|
||||||
if(ISN3DS)
|
if(ISN3DS)
|
||||||
{
|
{
|
||||||
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
//Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||||
kernel9Loader((Arm9Bin *)arm9Section);
|
kernel9Loader((Arm9Bin *)arm9Section);
|
||||||
firm->arm9Entry = (u8 *)0x801B01C;
|
firm->arm9Entry = (u8 *)0x801B01C;
|
||||||
}
|
}
|
||||||
@@ -374,7 +373,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
|||||||
//Skip on FIRMs < 4.0
|
//Skip on FIRMs < 4.0
|
||||||
if(ISN3DS || firmVersion >= 0x1D)
|
if(ISN3DS || firmVersion >= 0x1D)
|
||||||
{
|
{
|
||||||
ret += installK11Extension(arm11Section1, firm->section[1].size, isSafeMode, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
ret += installK11Extension(arm11Section1, firm->section[1].size, needToInitSd, baseK11VA, arm11ExceptionsPage, &freeK11Space);
|
||||||
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
|
ret += patchKernel11(arm11Section1, firm->section[1].size, baseK11VA, arm11SvcTable, arm11ExceptionsPage);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -400,6 +399,9 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
|||||||
//Apply anti-anti-DG patches on 11.0+
|
//Apply anti-anti-DG patches on 11.0+
|
||||||
if(firmVersion >= (ISN3DS ? 0x21 : 0x52)) ret += patchTitleInstallMinVersionChecks(process9Offset, process9Size, firmVersion);
|
if(firmVersion >= (ISN3DS ? 0x21 : 0x52)) ret += patchTitleInstallMinVersionChecks(process9Offset, process9Size, firmVersion);
|
||||||
|
|
||||||
|
//Patch P9 AM ticket wrapper on 11.8+ to use 0 Key and IV, only with UNITINFO patch on to prevent NIM from actually sending any
|
||||||
|
if(doUnitinfoPatch && firmVersion >= (ISN3DS ? 0x35 : 0x64)) ret += patchP9AMTicketWrapperZeroKeyIV(process9Offset, process9Size, firmVersion);
|
||||||
|
|
||||||
//Apply UNITINFO patches
|
//Apply UNITINFO patches
|
||||||
if(doUnitinfoPatch)
|
if(doUnitinfoPatch)
|
||||||
{
|
{
|
||||||
@@ -407,7 +409,7 @@ u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStora
|
|||||||
if(!ISDEVUNIT) ret += patchCheckForDevCommonKey(process9Offset, process9Size);
|
if(!ISDEVUNIT) ret += patchCheckForDevCommonKey(process9Offset, process9Size);
|
||||||
}
|
}
|
||||||
|
|
||||||
//ARM9 exception handlers
|
//Arm9 exception handlers
|
||||||
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
||||||
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
||||||
ret += patchKernel9Panic(arm9Section, kernel9Size);
|
ret += patchKernel9Panic(arm9Section, kernel9Size);
|
||||||
@@ -424,7 +426,7 @@ u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch)
|
|||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
|
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
|
||||||
|
|
||||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
//On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||||
if(ISN3DS)
|
if(ISN3DS)
|
||||||
{
|
{
|
||||||
kernel9Loader((Arm9Bin *)arm9Section);
|
kernel9Loader((Arm9Bin *)arm9Section);
|
||||||
@@ -463,7 +465,7 @@ u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch)
|
|||||||
{
|
{
|
||||||
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
|
u8 *arm9Section = (u8 *)firm + firm->section[3].offset;
|
||||||
|
|
||||||
//On N3DS, decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
//On N3DS, decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||||
if(ISN3DS)
|
if(ISN3DS)
|
||||||
{
|
{
|
||||||
kernel9Loader((Arm9Bin *)arm9Section);
|
kernel9Loader((Arm9Bin *)arm9Section);
|
||||||
@@ -499,7 +501,7 @@ u32 patch1x2xNativeAndSafeFirm(void)
|
|||||||
|
|
||||||
if(ISN3DS)
|
if(ISN3DS)
|
||||||
{
|
{
|
||||||
//Decrypt ARM9Bin and patch ARM9 entrypoint to skip kernel9loader
|
//Decrypt Arm9Bin and patch Arm9 entrypoint to skip kernel9loader
|
||||||
kernel9Loader((Arm9Bin *)arm9Section);
|
kernel9Loader((Arm9Bin *)arm9Section);
|
||||||
firm->arm9Entry = (u8 *)0x801B01C;
|
firm->arm9Entry = (u8 *)0x801B01C;
|
||||||
}
|
}
|
||||||
@@ -516,7 +518,7 @@ u32 patch1x2xNativeAndSafeFirm(void)
|
|||||||
|
|
||||||
ret += ISN3DS ? patchSignatureChecks(process9Offset, process9Size) : patchOldSignatureChecks(process9Offset, process9Size);
|
ret += ISN3DS ? patchSignatureChecks(process9Offset, process9Size) : patchOldSignatureChecks(process9Offset, process9Size);
|
||||||
|
|
||||||
//ARM9 exception handlers
|
//Arm9 exception handlers
|
||||||
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
ret += patchArm9ExceptionHandlersInstall(arm9Section, kernel9Size);
|
||||||
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
ret += patchSvcBreak9(arm9Section, kernel9Size, (u32)firm->section[2].address);
|
||||||
|
|
||||||
@@ -525,12 +527,6 @@ u32 patch1x2xNativeAndSafeFirm(void)
|
|||||||
|
|
||||||
void launchFirm(int argc, char **argv)
|
void launchFirm(int argc, char **argv)
|
||||||
{
|
{
|
||||||
u32 *chainloaderAddress = (u32 *)0x01FF9000;
|
|
||||||
|
|
||||||
prepareArm11ForFirmlaunch();
|
prepareArm11ForFirmlaunch();
|
||||||
|
chainload(argc, argv, firm);
|
||||||
memcpy(chainloaderAddress, chainloader_bin, chainloader_bin_size);
|
|
||||||
|
|
||||||
// No need to flush caches here, the chainloader is in ITCM
|
|
||||||
((void (*)(int, char **, Firm *))chainloaderAddress)(argc, argv, firm);
|
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
|
u32 loadNintendoFirm(FirmwareType *firmType, FirmwareSource nandType, bool loadFromStorage, bool isSafeMode);
|
||||||
void loadHomebrewFirm(u32 pressed);
|
void loadHomebrewFirm(u32 pressed);
|
||||||
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool isSafeMode, bool doUnitinfoPatch);
|
u32 patchNativeFirm(u32 firmVersion, FirmwareSource nandType, bool loadFromStorage, bool isFirmProtEnabled, bool needToInitSd, bool doUnitinfoPatch);
|
||||||
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
|
u32 patchTwlFirm(u32 firmVersion, bool loadFromStorage, bool doUnitinfoPatch);
|
||||||
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
|
u32 patchAgbFirm(bool loadFromStorage, bool doUnitinfoPatch);
|
||||||
u32 patch1x2xNativeAndSafeFirm(void);
|
u32 patch1x2xNativeAndSafeFirm(void);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -59,7 +59,7 @@ This code is based on a file that contains the following:
|
|||||||
|
|
||||||
//TuxSH's changes: add support for 64-bit numbers, remove floating-point code
|
//TuxSH's changes: add support for 64-bit numbers, remove floating-point code
|
||||||
|
|
||||||
#include "strings.h"
|
#include "memory.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
|
|
||||||
#define ZEROPAD (1<<0) //Pad with zero
|
#define ZEROPAD (1<<0) //Pad with zero
|
||||||
@@ -148,7 +148,7 @@ static char *processNumber(char *str, s64 num, bool isHex, s32 size, s32 precisi
|
|||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 vsprintf(char *buf, const char *fmt, va_list args)
|
int vsprintf(char *buf, const char *fmt, va_list args)
|
||||||
{
|
{
|
||||||
char *str;
|
char *str;
|
||||||
|
|
||||||
@@ -218,7 +218,7 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
|
|||||||
fmt++;
|
fmt++;
|
||||||
integerType = 1;
|
integerType = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
else if(*fmt == 'h')
|
else if(*fmt == 'h')
|
||||||
{
|
{
|
||||||
@@ -306,14 +306,14 @@ u32 vsprintf(char *buf, const char *fmt, va_list args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
*str = 0;
|
*str = 0;
|
||||||
return str - buf;
|
return (int)(str - buf);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 sprintf(char *buf, const char *fmt, ...)
|
int sprintf(char *buf, const char *fmt, ...)
|
||||||
{
|
{
|
||||||
va_list args;
|
va_list args;
|
||||||
va_start(args, fmt);
|
va_start(args, fmt);
|
||||||
u32 res = vsprintf(buf, fmt, args);
|
int res = vsprintf(buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,5 +28,5 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include <stdarg.h>
|
#include <stdarg.h>
|
||||||
|
|
||||||
u32 vsprintf(char *buf, const char *fmt, va_list args);
|
int vsprintf(char *buf, const char *fmt, va_list args);
|
||||||
u32 sprintf(char *buf, const char *fmt, ...);
|
int sprintf(char *buf, const char *fmt, ...);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,7 +26,6 @@
|
|||||||
|
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
@@ -37,7 +36,7 @@
|
|||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "firm.h"
|
#include "firm.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "../build/bundled.h"
|
#include "strings.h"
|
||||||
|
|
||||||
static FATFS sdFs,
|
static FATFS sdFs,
|
||||||
nandFs;
|
nandFs;
|
||||||
@@ -88,7 +87,7 @@ u32 getFileSize(const char *path)
|
|||||||
bool fileWrite(const void *buffer, const char *path, u32 size)
|
bool fileWrite(const void *buffer, const char *path, u32 size)
|
||||||
{
|
{
|
||||||
FIL file;
|
FIL file;
|
||||||
FRESULT result;
|
FRESULT result = FR_OK;
|
||||||
|
|
||||||
switch(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS))
|
switch(f_open(&file, path, FA_WRITE | FA_OPEN_ALWAYS))
|
||||||
{
|
{
|
||||||
@@ -283,7 +282,7 @@ u32 firmRead(void *dest, u32 firmType)
|
|||||||
if(f_closedir(&dir) != FR_OK || firmVersion == 0xFFFFFFFF) goto exit;
|
if(f_closedir(&dir) != FR_OK || firmVersion == 0xFFFFFFFF) goto exit;
|
||||||
|
|
||||||
//Complete the string with the .app name
|
//Complete the string with the .app name
|
||||||
sprintf(path, "%s/%08x.app", folderPath, firmVersion);
|
sprintf(path, "%s/%08lx.app", folderPath, firmVersion);
|
||||||
|
|
||||||
if(fileRead(dest, path, 0x400000 + sizeof(Cxi) + 0x200) <= sizeof(Cxi) + 0x400) firmVersion = 0xFFFFFFFF;
|
if(fileRead(dest, path, 0x400000 + sizeof(Cxi) + 0x200) <= sizeof(Cxi) + 0x400) firmVersion = 0xFFFFFFFF;
|
||||||
|
|
||||||
@@ -300,7 +299,7 @@ void findDumpFile(const char *folderPath, char *fileName)
|
|||||||
{
|
{
|
||||||
FILINFO info;
|
FILINFO info;
|
||||||
|
|
||||||
sprintf(fileName, "crash_dump_%08u.dmp", n);
|
sprintf(fileName, "crash_dump_%08lu.dmp", n);
|
||||||
result = f_findfirst(&dir, &info, folderPath, fileName);
|
result = f_findfirst(&dir, &info, folderPath, fileName);
|
||||||
|
|
||||||
if(result != FR_OK || !info.fname[0]) break;
|
if(result != FR_OK || !info.fname[0]) break;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
225
arm9/source/i2c.c
Normal file
225
arm9/source/i2c.c
Normal file
@@ -0,0 +1,225 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of fastboot 3DS
|
||||||
|
* Copyright (C) 2017 derrek, profi200
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
#include "i2c.h"
|
||||||
|
#include "utils.h"
|
||||||
|
|
||||||
|
#define I2C1_REGS_BASE (0x10161000)
|
||||||
|
|
||||||
|
#define I2C2_REGS_BASE (0x10144000)
|
||||||
|
|
||||||
|
#define I2C3_REGS_BASE (0x10148000)
|
||||||
|
|
||||||
|
|
||||||
|
typedef struct
|
||||||
|
{
|
||||||
|
vu8 REG_I2C_DATA;
|
||||||
|
vu8 REG_I2C_CNT;
|
||||||
|
vu16 REG_I2C_CNTEX;
|
||||||
|
vu16 REG_I2C_SCL;
|
||||||
|
} I2cRegs;
|
||||||
|
|
||||||
|
static const struct
|
||||||
|
{
|
||||||
|
u8 busId;
|
||||||
|
u8 devAddr;
|
||||||
|
} i2cDevTable[] =
|
||||||
|
{
|
||||||
|
{0, 0x4A},
|
||||||
|
{0, 0x7A},
|
||||||
|
{0, 0x78},
|
||||||
|
{1, 0x4A},
|
||||||
|
{1, 0x78},
|
||||||
|
{1, 0x2C},
|
||||||
|
{1, 0x2E},
|
||||||
|
{1, 0x40},
|
||||||
|
{1, 0x44},
|
||||||
|
{2, 0xA6}, // TODO: Find out if 0xA6 or 0xD6 is correct
|
||||||
|
{2, 0xD0},
|
||||||
|
{2, 0xD2},
|
||||||
|
{2, 0xA4},
|
||||||
|
{2, 0x9A},
|
||||||
|
{2, 0xA0},
|
||||||
|
{1, 0xEE},
|
||||||
|
{0, 0x40},
|
||||||
|
{2, 0x54}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static void i2cWaitBusy(I2cRegs *const regs)
|
||||||
|
{
|
||||||
|
while(regs->REG_I2C_CNT & I2C_ENABLE);
|
||||||
|
}
|
||||||
|
|
||||||
|
static I2cRegs* i2cGetBusRegsBase(u8 busId)
|
||||||
|
{
|
||||||
|
I2cRegs *base;
|
||||||
|
switch(busId)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
base = (I2cRegs*)I2C1_REGS_BASE;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
base = (I2cRegs*)I2C2_REGS_BASE;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
base = (I2cRegs*)I2C3_REGS_BASE;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
base = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return base;
|
||||||
|
}
|
||||||
|
|
||||||
|
void I2C_init(void)
|
||||||
|
{
|
||||||
|
I2cRegs *regs = i2cGetBusRegsBase(0); // Bus 1
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
regs->REG_I2C_CNTEX = 2; // ?
|
||||||
|
regs->REG_I2C_SCL = 1280; // ?
|
||||||
|
|
||||||
|
regs = i2cGetBusRegsBase(1); // Bus 2
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
regs->REG_I2C_CNTEX = 2; // ?
|
||||||
|
regs->REG_I2C_SCL = 1280; // ?
|
||||||
|
|
||||||
|
regs = i2cGetBusRegsBase(2); // Bus 3
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
regs->REG_I2C_CNTEX = 2; // ?
|
||||||
|
regs->REG_I2C_SCL = 1280; // ?
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool i2cStartTransfer(I2cDevice devId, u8 regAddr, bool read, I2cRegs *const regs)
|
||||||
|
{
|
||||||
|
const u8 devAddr = i2cDevTable[devId].devAddr;
|
||||||
|
|
||||||
|
|
||||||
|
u32 i = 0;
|
||||||
|
for(; i < 8; i++)
|
||||||
|
{
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
|
||||||
|
// Select device and start.
|
||||||
|
regs->REG_I2C_DATA = devAddr;
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select register and change direction to write.
|
||||||
|
regs->REG_I2C_DATA = regAddr;
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Select device in read mode for read transfer.
|
||||||
|
if(read)
|
||||||
|
{
|
||||||
|
regs->REG_I2C_DATA = devAddr | 1u; // Set bit 0 for read.
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_START;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(i < 8) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size)
|
||||||
|
{
|
||||||
|
const u8 busId = i2cDevTable[devId].busId;
|
||||||
|
I2cRegs *const regs = i2cGetBusRegsBase(busId);
|
||||||
|
|
||||||
|
|
||||||
|
if(!i2cStartTransfer(devId, regAddr, true, regs)) return false;
|
||||||
|
|
||||||
|
while(--size)
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_ACK;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
*out++ = regs->REG_I2C_DATA;
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_READ | I2C_STOP;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
*out = regs->REG_I2C_DATA; // Last byte
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size)
|
||||||
|
{
|
||||||
|
const u8 busId = i2cDevTable[devId].busId;
|
||||||
|
I2cRegs *const regs = i2cGetBusRegsBase(busId);
|
||||||
|
|
||||||
|
|
||||||
|
if(!i2cStartTransfer(devId, regAddr, false, regs)) return false;
|
||||||
|
|
||||||
|
while(--size)
|
||||||
|
{
|
||||||
|
regs->REG_I2C_DATA = *in++;
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
regs->REG_I2C_DATA = *in;
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_DIRE_WRITE | I2C_STOP;
|
||||||
|
i2cWaitBusy(regs);
|
||||||
|
if(!I2C_GET_ACK(regs->REG_I2C_CNT)) // If ack flag is 0 it failed.
|
||||||
|
{
|
||||||
|
regs->REG_I2C_CNT = I2C_ENABLE | I2C_IRQ_ENABLE | I2C_ERROR | I2C_STOP;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 I2C_readReg(I2cDevice devId, u8 regAddr)
|
||||||
|
{
|
||||||
|
u8 data;
|
||||||
|
if(!I2C_readRegBuf(devId, regAddr, &data, 1)) return 0xFF;
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data)
|
||||||
|
{
|
||||||
|
return I2C_writeRegBuf(devId, regAddr, &data, 1);
|
||||||
|
}
|
||||||
102
arm9/source/i2c.h
Normal file
102
arm9/source/i2c.h
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This file is part of fastboot 3DS
|
||||||
|
* Copyright (C) 2017 derrek, profi200
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
|
||||||
|
#define I2C_STOP (1u)
|
||||||
|
#define I2C_START (1u<<1)
|
||||||
|
#define I2C_ERROR (1u<<2)
|
||||||
|
#define I2C_ACK (1u<<4)
|
||||||
|
#define I2C_DIRE_WRITE (0u)
|
||||||
|
#define I2C_DIRE_READ (1u<<5)
|
||||||
|
#define I2C_IRQ_ENABLE (1u<<6)
|
||||||
|
#define I2C_ENABLE (1u<<7)
|
||||||
|
|
||||||
|
#define I2C_GET_ACK(reg) ((bool)((reg)>>4 & 1u))
|
||||||
|
|
||||||
|
|
||||||
|
typedef enum
|
||||||
|
{
|
||||||
|
I2C_DEV_POWER = 0, // Unconfirmed
|
||||||
|
I2C_DEV_CAMERA = 1, // Unconfirmed
|
||||||
|
I2C_DEV_CAMERA2 = 2, // Unconfirmed
|
||||||
|
I2C_DEV_MCU = 3,
|
||||||
|
I2C_DEV_GYRO = 10,
|
||||||
|
I2C_DEV_DEBUG_PAD = 12,
|
||||||
|
I2C_DEV_IR = 13,
|
||||||
|
I2C_DEV_EEPROM = 14, // Unconfirmed
|
||||||
|
I2C_DEV_NFC = 15,
|
||||||
|
I2C_DEV_QTM = 16,
|
||||||
|
I2C_DEV_N3DS_HID = 17
|
||||||
|
} I2cDevice;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initializes the I2C buses. Call this only once.
|
||||||
|
*/
|
||||||
|
void I2C_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads data from a I2C register to a buffer.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
* @param out The output buffer pointer.
|
||||||
|
* @param[in] size The read size.
|
||||||
|
*
|
||||||
|
* @return Returns true on success and false on failure.
|
||||||
|
*/
|
||||||
|
bool I2C_readRegBuf(I2cDevice devId, u8 regAddr, u8 *out, u32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a buffer to a I2C register.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
* @param[in] in The input buffer pointer.
|
||||||
|
* @param[in] size The write size.
|
||||||
|
*
|
||||||
|
* @return Returns true on success and false on failure.
|
||||||
|
*/
|
||||||
|
bool I2C_writeRegBuf(I2cDevice devId, u8 regAddr, const u8 *in, u32 size);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Reads a byte from a I2C register.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
*
|
||||||
|
* @return Returns the value read on success otherwise 0xFF.
|
||||||
|
*/
|
||||||
|
u8 I2C_readReg(I2cDevice devId, u8 regAddr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Writes a byte to a I2C register.
|
||||||
|
*
|
||||||
|
* @param[in] devId The device ID. Use the enum above.
|
||||||
|
* @param[in] regAddr The register address.
|
||||||
|
* @param[in] data The data to write.
|
||||||
|
*
|
||||||
|
* @return Returns true on success and false on failure.
|
||||||
|
*/
|
||||||
|
bool I2C_writeReg(I2cDevice devId, u8 regAddr, u8 data);
|
||||||
38
arm9/source/large_patches.h
Normal file
38
arm9/source/large_patches.h
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Luma3DS
|
||||||
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*
|
||||||
|
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
||||||
|
* * Requiring preservation of specified reasonable legal notices or
|
||||||
|
* author attributions in that material or in the Appropriate Legal
|
||||||
|
* Notices displayed by works containing it.
|
||||||
|
* * Prohibiting misrepresentation of the origin of that material,
|
||||||
|
* or requiring that modified versions of such material be marked in
|
||||||
|
* reasonable ways as different from the original version.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
|
extern const u8 emunandPatch[];
|
||||||
|
extern const u32 emunandPatchSize;
|
||||||
|
extern u32 emunandPatchSdmmcStructPtr, emunandPatchNandOffset, emunandPatchNcsdHeaderOffset;
|
||||||
|
|
||||||
|
extern const u8 rebootPatch[];
|
||||||
|
extern const u32 rebootPatchSize;
|
||||||
|
extern u32 rebootPatchFopenPtr;
|
||||||
|
extern u16 rebootPatchFileName[80+1];
|
||||||
291
arm9/source/large_patches.s
Normal file
291
arm9/source/large_patches.s
Normal file
@@ -0,0 +1,291 @@
|
|||||||
|
.section .large_patch.emunand, "aw", %progbits
|
||||||
|
.arm
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
@ Code originally by Normmatt
|
||||||
|
|
||||||
|
.global emunandPatch
|
||||||
|
emunandPatch:
|
||||||
|
@ Original code that still needs to be executed
|
||||||
|
mov r4, r0
|
||||||
|
mov r5, r1
|
||||||
|
mov r7, r2
|
||||||
|
mov r6, r3
|
||||||
|
@ End
|
||||||
|
|
||||||
|
@ If we're already trying to access the SD, return
|
||||||
|
ldr r2, [r0, #4]
|
||||||
|
ldr r1, emunandPatchSdmmcStructPtr
|
||||||
|
cmp r2, r1
|
||||||
|
beq out
|
||||||
|
|
||||||
|
str r1, [r0, #4] @ Set object to be SD
|
||||||
|
ldr r2, [r0, #8] @ Get sector to read
|
||||||
|
cmp r2, #0 @ For GW compatibility, see if we're trying to read the ncsd header (sector 0)
|
||||||
|
|
||||||
|
ldr r3, emunandPatchNandOffset
|
||||||
|
add r2, r3 @ Add the offset to the NAND in the SD
|
||||||
|
|
||||||
|
ldreq r3, emunandPatchNcsdHeaderOffset
|
||||||
|
addeq r2, r3 @ If we're reading the ncsd header, add the offset of that sector
|
||||||
|
|
||||||
|
str r2, [r0, #8] @ Store sector to read
|
||||||
|
|
||||||
|
out:
|
||||||
|
@ Restore registers.
|
||||||
|
mov r1, r5
|
||||||
|
mov r2, r7
|
||||||
|
mov r3, r6
|
||||||
|
|
||||||
|
@ Return 4 bytes behind where we got called,
|
||||||
|
@ due to the offset of this function being stored there
|
||||||
|
mov r0, lr
|
||||||
|
add r0, #4
|
||||||
|
bx r0
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.global emunandPatchSdmmcStructPtr
|
||||||
|
.global emunandPatchNandOffset
|
||||||
|
.global emunandPatchNcsdHeaderOffset
|
||||||
|
|
||||||
|
emunandPatchSdmmcStructPtr: .word 0 @ Pointer to sdmmc struct
|
||||||
|
emunandPatchNandOffset: .word 0 @ For rednand this should be 1
|
||||||
|
emunandPatchNcsdHeaderOffset: .word 0 @ Depends on nand manufacturer + emunand type (GW/RED)
|
||||||
|
|
||||||
|
.pool
|
||||||
|
.balign 4
|
||||||
|
|
||||||
|
_emunandPatchEnd:
|
||||||
|
|
||||||
|
.global emunandPatchSize
|
||||||
|
emunandPatchSize:
|
||||||
|
.word _emunandPatchEnd - emunandPatch
|
||||||
|
|
||||||
|
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||||||
|
|
||||||
|
@ Code originally from delebile and mid-kid
|
||||||
|
|
||||||
|
.section .large_patch.reboot, "aw", %progbits
|
||||||
|
.arm
|
||||||
|
.align 4
|
||||||
|
|
||||||
|
#define copy_launch_stub_stack_top 0x01FFB800
|
||||||
|
#define copy_launch_stub_stack_bottom 0x01FFA800
|
||||||
|
#define copy_launch_stub_addr 0x01FF9000
|
||||||
|
|
||||||
|
#define argv_addr (copy_launch_stub_stack_bottom - 0x100)
|
||||||
|
#define fname_addr (copy_launch_stub_stack_bottom - 0x200)
|
||||||
|
#define low_tid_addr (copy_launch_stub_stack_bottom - 0x300)
|
||||||
|
|
||||||
|
#define firm_addr 0x20001000
|
||||||
|
#define firm_maxsize 0x07FFF000
|
||||||
|
|
||||||
|
.global rebootPatch
|
||||||
|
rebootPatch:
|
||||||
|
@ Interesting registers and locations to keep in mind, set just before this code is ran:
|
||||||
|
@ - r1: FIRM path in exefs.
|
||||||
|
@ - r7 (or r8): pointer to file object
|
||||||
|
@ - *r7: vtable
|
||||||
|
@ - *(vtable + 0x28): fread function
|
||||||
|
@ - *(r7 + 8): file handle
|
||||||
|
|
||||||
|
sub r7, r0, #8
|
||||||
|
mov r8, r1
|
||||||
|
|
||||||
|
pxi_wait_recv:
|
||||||
|
ldr r2, =0x44846
|
||||||
|
ldr r0, =0x10008000
|
||||||
|
readPxiLoop1:
|
||||||
|
ldrh r1, [r0, #4]
|
||||||
|
lsls r1, #0x17
|
||||||
|
bmi readPxiLoop1
|
||||||
|
ldr r0, [r0, #0xC]
|
||||||
|
cmp r0, r2
|
||||||
|
bne pxi_wait_recv
|
||||||
|
|
||||||
|
@ Open file
|
||||||
|
add r0, r7, #8
|
||||||
|
adr r1, rebootPatchFileName
|
||||||
|
mov r2, #1
|
||||||
|
adr r6, rebootPatchFopenPtr
|
||||||
|
ldr r6, [r6]
|
||||||
|
orr r6, #1
|
||||||
|
blx r6
|
||||||
|
cmp r0, #0
|
||||||
|
bne panic
|
||||||
|
|
||||||
|
@ Read file
|
||||||
|
mov r0, r7
|
||||||
|
adr r1, bytes_read
|
||||||
|
ldr r2, =firm_addr
|
||||||
|
ldr r3, =firm_maxsize
|
||||||
|
ldr r6, [r7]
|
||||||
|
ldr r6, [r6, #0x28]
|
||||||
|
blx r6
|
||||||
|
|
||||||
|
@ Copy the low TID (in UTF-16) of the wanted firm
|
||||||
|
ldr r0, =low_tid_addr
|
||||||
|
add r1, r8, #0x1A
|
||||||
|
mov r2, #0x10
|
||||||
|
bl memcpy16
|
||||||
|
|
||||||
|
@ Copy argv[0]
|
||||||
|
ldr r0, =fname_addr
|
||||||
|
adr r1, rebootPatchFileName
|
||||||
|
mov r2, #82
|
||||||
|
bl memcpy16
|
||||||
|
|
||||||
|
ldr r0, =argv_addr
|
||||||
|
ldr r1, =fname_addr
|
||||||
|
ldr r2, =low_tid_addr
|
||||||
|
stmia r0, {r1, r2}
|
||||||
|
|
||||||
|
@ Set kernel state
|
||||||
|
mov r0, #0
|
||||||
|
mov r1, #0
|
||||||
|
mov r2, #0
|
||||||
|
mov r3, #0
|
||||||
|
svc 0x7C
|
||||||
|
|
||||||
|
goto_reboot:
|
||||||
|
@ Jump to reboot code
|
||||||
|
ldr r0, kernel_func_displ
|
||||||
|
add r0, pc @ pc is two instructions ahead of the instruction being executed (12 = 2*4 + 4)
|
||||||
|
svc 0x7B
|
||||||
|
|
||||||
|
die:
|
||||||
|
b die
|
||||||
|
|
||||||
|
memcpy16:
|
||||||
|
cmp r2, #0
|
||||||
|
bxeq lr
|
||||||
|
add r2, r0, r2
|
||||||
|
copy_loop16:
|
||||||
|
ldrh r3, [r1], #2
|
||||||
|
strh r3, [r0], #2
|
||||||
|
cmp r0, r2
|
||||||
|
blo copy_loop16
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
panic:
|
||||||
|
mov r1, r0 @ unused register
|
||||||
|
mov r0, #0
|
||||||
|
svc 0x3C @ svcBreak(USERBREAK_PANIC)
|
||||||
|
b die
|
||||||
|
|
||||||
|
kernel_func_displ:
|
||||||
|
.word kernelcode_start - goto_reboot - 12
|
||||||
|
|
||||||
|
bytes_read:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.global rebootPatchFopenPtr
|
||||||
|
rebootPatchFopenPtr:
|
||||||
|
.word 0
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.global rebootPatchFileName
|
||||||
|
rebootPatchFileName:
|
||||||
|
.skip 2*(80+1)
|
||||||
|
|
||||||
|
.balign 4
|
||||||
|
kernelcode_start:
|
||||||
|
|
||||||
|
msr cpsr_cxsf, #0xD3 @ disable interrupts and clear flags
|
||||||
|
|
||||||
|
ldr sp, =copy_launch_stub_stack_top
|
||||||
|
|
||||||
|
ldr r0, =copy_launch_stub_addr
|
||||||
|
adr r1, copy_launch_stub
|
||||||
|
mov r2, #(copy_launch_stub_end - copy_launch_stub)
|
||||||
|
bl memcpy32
|
||||||
|
|
||||||
|
@ Disable MPU
|
||||||
|
ldr r0, =0x42078 @ alt vector select, enable itcm
|
||||||
|
mcr p15, 0, r0, c1, c0, 0
|
||||||
|
|
||||||
|
bl flushCaches
|
||||||
|
|
||||||
|
ldr r0, =copy_launch_stub_addr
|
||||||
|
bx r0
|
||||||
|
|
||||||
|
copy_launch_stub:
|
||||||
|
|
||||||
|
ldr r4, =firm_addr
|
||||||
|
|
||||||
|
mov r5, #0
|
||||||
|
load_section_loop:
|
||||||
|
@ Such checks. Very ghetto. Wow.
|
||||||
|
add r3, r4, #0x40
|
||||||
|
add r3, r5,lsl #5
|
||||||
|
add r3, r5,lsl #4
|
||||||
|
ldmia r3, {r6-r8}
|
||||||
|
cmp r8, #0
|
||||||
|
movne r0, r7
|
||||||
|
addne r1, r4, r6
|
||||||
|
movne r2, r8
|
||||||
|
blne memcpy32
|
||||||
|
add r5, #1
|
||||||
|
cmp r5, #4
|
||||||
|
blo load_section_loop
|
||||||
|
|
||||||
|
mov r0, #2 @ argc
|
||||||
|
ldr r1, =argv_addr @ argv
|
||||||
|
ldr r2, =0xBABE @ magic word
|
||||||
|
|
||||||
|
mov r5, #0x20000000
|
||||||
|
ldr r6, [r4, #0x08]
|
||||||
|
str r6, [r5, #-4] @ store arm11 entrypoint
|
||||||
|
|
||||||
|
ldr lr, [r4, #0x0c]
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
memcpy32:
|
||||||
|
add r2, r0, r2
|
||||||
|
copy_loop32:
|
||||||
|
ldr r3, [r1], #4
|
||||||
|
str r3, [r0], #4
|
||||||
|
cmp r0, r2
|
||||||
|
blo copy_loop32
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.pool
|
||||||
|
|
||||||
|
copy_launch_stub_end:
|
||||||
|
|
||||||
|
flushCaches:
|
||||||
|
|
||||||
|
@ Clean and flush data cache
|
||||||
|
mov r1, #0 @ segment counter
|
||||||
|
outer_loop:
|
||||||
|
mov r0, #0 @ line counter
|
||||||
|
|
||||||
|
inner_loop:
|
||||||
|
orr r2, r1, r0 @ generate segment and line address
|
||||||
|
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
||||||
|
add r0, #0x20 @ increment to next line
|
||||||
|
cmp r0, #0x400
|
||||||
|
bne inner_loop
|
||||||
|
|
||||||
|
add r1, #0x40000000
|
||||||
|
cmp r1, #0
|
||||||
|
bne outer_loop
|
||||||
|
|
||||||
|
@ Drain write buffer
|
||||||
|
mcr p15, 0, r1, c7, c10, 4
|
||||||
|
|
||||||
|
@ Flush instruction cache
|
||||||
|
mcr p15, 0, r1, c7, c5, 0
|
||||||
|
|
||||||
|
bx lr
|
||||||
|
|
||||||
|
.pool
|
||||||
|
.balign 4
|
||||||
|
|
||||||
|
_rebootPatchEnd:
|
||||||
|
|
||||||
|
.global rebootPatchSize
|
||||||
|
rebootPatchSize:
|
||||||
|
.word _rebootPatchEnd - rebootPatch
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -31,42 +31,47 @@
|
|||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "exceptions.h"
|
#include "exceptions.h"
|
||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "strings.h"
|
|
||||||
#include "buttons.h"
|
#include "buttons.h"
|
||||||
#include "pin.h"
|
#include "pin.h"
|
||||||
#include "crypto.h"
|
#include "crypto.h"
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "screen.h"
|
#include "screen.h"
|
||||||
|
#include "i2c.h"
|
||||||
#include "fatfs/sdmmc/sdmmc.h"
|
#include "fatfs/sdmmc/sdmmc.h"
|
||||||
|
|
||||||
|
extern u8 __itcm_start__[], __itcm_lma__[], __itcm_bss_start__[], __itcm_end__[];
|
||||||
|
|
||||||
extern CfgData configData;
|
extern CfgData configData;
|
||||||
extern ConfigurationStatus needConfig;
|
extern ConfigurationStatus needConfig;
|
||||||
extern FirmwareSource firmSource;
|
extern FirmwareSource firmSource;
|
||||||
|
|
||||||
bool isSdMode;
|
bool isSdMode;
|
||||||
u16 launchedPath[41];
|
u16 launchedPath[80+1];
|
||||||
BootType bootType;
|
BootType bootType;
|
||||||
|
|
||||||
void main(int argc, char **argv, u32 magicWord)
|
void main(int argc, char **argv, u32 magicWord)
|
||||||
{
|
{
|
||||||
bool isFirmProtEnabled,
|
bool isFirmProtEnabled,
|
||||||
isSafeMode = false,
|
isSafeMode = false,
|
||||||
|
needToInitSd = false,
|
||||||
isNoForceFlagSet = false,
|
isNoForceFlagSet = false,
|
||||||
|
isInvalidLoader = false,
|
||||||
isNtrBoot;
|
isNtrBoot;
|
||||||
FirmwareType firmType;
|
FirmwareType firmType;
|
||||||
FirmwareSource nandType;
|
FirmwareSource nandType;
|
||||||
const vu8 *bootMediaStatus = (const vu8 *)0x1FFFE00C;
|
const vu8 *bootMediaStatus = (const vu8 *)0x1FFFE00C;
|
||||||
const vu32 *bootPartitionsStatus = (const vu32 *)0x1FFFE010;
|
const vu32 *bootPartitionsStatus = (const vu32 *)0x1FFFE010;
|
||||||
|
u32 firmlaunchTidLow = 0;
|
||||||
|
|
||||||
//Shell closed, no error booting NTRCARD, NAND paritions not even considered
|
//Shell closed, no error booting NTRCARD, NAND paritions not even considered
|
||||||
isNtrBoot = bootMediaStatus[3] == 2 && !bootMediaStatus[1] && !bootPartitionsStatus[0] && !bootPartitionsStatus[1];
|
isNtrBoot = bootMediaStatus[3] == 2 && !bootMediaStatus[1] && !bootPartitionsStatus[0] && !bootPartitionsStatus[1];
|
||||||
|
|
||||||
if((magicWord & 0xFFFF) == 0xBEEF && argc >= 1) //Normal (B9S) boot
|
if((magicWord & 0xFFFF) == 0xBEEF && argc >= 1) //Normal (B9S) boot
|
||||||
{
|
{
|
||||||
bootType = isNtrBoot ? B9SNTR : B9S;
|
bootType = isNtrBoot ? B9SNTR : B9S;
|
||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
for(i = 0; i < 40 && argv[0][i] != 0; i++) //Copy and convert the path to UTF-16
|
for(i = 0; i < sizeof(launchedPath)/2 - 1 && argv[0][i] != 0; i++) //Copy and convert the path to UTF-16
|
||||||
launchedPath[i] = argv[0][i];
|
launchedPath[i] = argv[0][i];
|
||||||
launchedPath[i] = 0;
|
launchedPath[i] = 0;
|
||||||
}
|
}
|
||||||
@@ -76,9 +81,12 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
|
|
||||||
u32 i;
|
u32 i;
|
||||||
u16 *p = (u16 *)argv[0];
|
u16 *p = (u16 *)argv[0];
|
||||||
for(i = 0; i < 40 && p[i] != 0; i++)
|
for(i = 0; i < sizeof(launchedPath)/2 - 1 && p[i] != 0; i++)
|
||||||
launchedPath[i] = p[i];
|
launchedPath[i] = p[i];
|
||||||
launchedPath[i] = 0;
|
launchedPath[i] = 0;
|
||||||
|
|
||||||
|
for(i = 0; i < 8; i++)
|
||||||
|
firmlaunchTidLow = (argv[1][2 * i] > '9' ? argv[1][2 * i] - 'a' + 10 : argv[1][2 * i] - '0') | (firmlaunchTidLow << 4);
|
||||||
}
|
}
|
||||||
else if(magicWord == 0xB002) //FIRM/NTRCARD boot
|
else if(magicWord == 0xB002) //FIRM/NTRCARD boot
|
||||||
{
|
{
|
||||||
@@ -103,7 +111,15 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
|
|
||||||
setupKeyslots();
|
setupKeyslots();
|
||||||
}
|
}
|
||||||
else error("Launched using an unsupported loader.");
|
else isInvalidLoader = true;
|
||||||
|
|
||||||
|
// Set up the additional sections, overwrites argc
|
||||||
|
memcpy(__itcm_start__, __itcm_lma__, __itcm_bss_start__ - __itcm_start__);
|
||||||
|
memset(__itcm_bss_start__, 0, __itcm_end__ - __itcm_bss_start__);
|
||||||
|
I2C_init();
|
||||||
|
if(isInvalidLoader) error("Launched using an unsupported loader.");
|
||||||
|
|
||||||
|
installArm9Handlers();
|
||||||
|
|
||||||
if(memcmp(launchedPath, u"sdmc", 8) == 0)
|
if(memcmp(launchedPath, u"sdmc", 8) == 0)
|
||||||
{
|
{
|
||||||
@@ -140,6 +156,8 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
error("Launched from an unsupported location: %s.", mountPoint);
|
error("Launched from an unsupported location: %s.", mountPoint);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detectAndProcessExceptionDumps();
|
||||||
|
|
||||||
//Attempt to read the configuration file
|
//Attempt to read the configuration file
|
||||||
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
needConfig = readConfig() ? MODIFY_CONFIGURATION : CREATE_CONFIGURATION;
|
||||||
|
|
||||||
@@ -148,15 +166,15 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
{
|
{
|
||||||
if(needConfig == CREATE_CONFIGURATION) mcuPowerOff();
|
if(needConfig == CREATE_CONFIGURATION) mcuPowerOff();
|
||||||
|
|
||||||
switch(argv[1][14])
|
switch(firmlaunchTidLow & 0xF)
|
||||||
{
|
{
|
||||||
case '2':
|
case 2:
|
||||||
firmType = (FirmwareType)(argv[1][10] - '0');
|
firmType = (FirmwareType)((firmlaunchTidLow >> 8) & 0xF);
|
||||||
break;
|
break;
|
||||||
case '3':
|
case 3:
|
||||||
firmType = SAFE_FIRM;
|
firmType = SAFE_FIRM;
|
||||||
break;
|
break;
|
||||||
case '1':
|
case 1:
|
||||||
firmType = SYSUPDATER_FIRM;
|
firmType = SYSUPDATER_FIRM;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -168,9 +186,6 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
goto boot;
|
goto boot;
|
||||||
}
|
}
|
||||||
|
|
||||||
detectAndProcessExceptionDumps();
|
|
||||||
installArm9Handlers();
|
|
||||||
|
|
||||||
firmType = NATIVE_FIRM;
|
firmType = NATIVE_FIRM;
|
||||||
isFirmProtEnabled = bootType != NTR;
|
isFirmProtEnabled = bootType != NTR;
|
||||||
|
|
||||||
@@ -192,9 +207,16 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
goto boot;
|
goto boot;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Else, force the last used boot options unless a button is pressed
|
//Account for DSiWare soft resets if exiting TWL_FIRM
|
||||||
|
if(CFG_BOOTENV == 3)
|
||||||
|
{
|
||||||
|
static const u8 TLNC[] = {0x54, 0x4C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4E, 0x43};
|
||||||
|
if(memcmp((void *)0x20000C00, TLNC, 10) == 0) needToInitSd = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Force the last used boot options if autobooting a TWL title, or unless a button is pressed
|
||||||
or the no-forcing flag is set */
|
or the no-forcing flag is set */
|
||||||
if(!pressed && !BOOTCFG_NOFORCEFLAG)
|
if(needToInitSd || memcmp((void *)0x20000300, "TLNC", 4) == 0 || (!pressed && !BOOTCFG_NOFORCEFLAG))
|
||||||
{
|
{
|
||||||
nandType = (FirmwareSource)BOOTCFG_NAND;
|
nandType = (FirmwareSource)BOOTCFG_NAND;
|
||||||
firmSource = (FirmwareSource)BOOTCFG_FIRM;
|
firmSource = (FirmwareSource)BOOTCFG_FIRM;
|
||||||
@@ -204,11 +226,21 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
}
|
}
|
||||||
|
|
||||||
u32 pinMode = MULTICONFIG(PIN);
|
u32 pinMode = MULTICONFIG(PIN);
|
||||||
|
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
|
||||||
bool pinExists = pinMode != 0 && verifyPin(pinMode);
|
bool pinExists = pinMode != 0 && verifyPin(pinMode);
|
||||||
|
|
||||||
//If no configuration file exists or SELECT is held or if booted from NTRCARD, load configuration menu
|
/* If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo or the configuration menu button
|
||||||
bool shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
|
(if not already pressed, for the latter) */
|
||||||
|
if(pinExists && !shouldLoadConfigMenu)
|
||||||
|
{
|
||||||
|
while(HID_PAD & PIN_BUTTONS);
|
||||||
|
wait(2000ULL);
|
||||||
|
|
||||||
|
//Update pressed buttons
|
||||||
|
pressed = HID_PAD;
|
||||||
|
}
|
||||||
|
|
||||||
|
shouldLoadConfigMenu = needConfig == CREATE_CONFIGURATION || ((pressed & (BUTTON_SELECT | BUTTON_L1)) == BUTTON_SELECT);
|
||||||
if(shouldLoadConfigMenu)
|
if(shouldLoadConfigMenu)
|
||||||
{
|
{
|
||||||
configMenu(pinExists, pinMode);
|
configMenu(pinExists, pinMode);
|
||||||
@@ -223,13 +255,7 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
firmSource = FIRMWARE_SYSNAND;
|
firmSource = FIRMWARE_SYSNAND;
|
||||||
|
|
||||||
isSafeMode = true;
|
isSafeMode = true;
|
||||||
|
needToInitSd = true;
|
||||||
//If the PIN has been verified, wait to make it easier to press the SAFE_MODE combo
|
|
||||||
if(pinExists && !shouldLoadConfigMenu)
|
|
||||||
{
|
|
||||||
while(HID_PAD & PIN_BUTTONS);
|
|
||||||
wait(2000ULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto boot;
|
goto boot;
|
||||||
}
|
}
|
||||||
@@ -248,7 +274,19 @@ void main(int argc, char **argv, u32 magicWord)
|
|||||||
else if((((pressed & SINGLE_PAYLOAD_BUTTONS) || (!autoBootEmu && (pressed & DPAD_BUTTONS))) && !(pressed & (BUTTON_L1 | BUTTON_R1))) ||
|
else if((((pressed & SINGLE_PAYLOAD_BUTTONS) || (!autoBootEmu && (pressed & DPAD_BUTTONS))) && !(pressed & (BUTTON_L1 | BUTTON_R1))) ||
|
||||||
(((pressed & L_PAYLOAD_BUTTONS) || (autoBootEmu && (pressed & DPAD_BUTTONS))) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed);
|
(((pressed & L_PAYLOAD_BUTTONS) || (autoBootEmu && (pressed & DPAD_BUTTONS))) && (pressed & BUTTON_L1))) loadHomebrewFirm(pressed);
|
||||||
|
|
||||||
if(splashMode == 2) loadSplash();
|
if(splashMode == 2 && loadSplash()) pressed = HID_PAD;
|
||||||
|
|
||||||
|
//Check SAFE_MODE combo again
|
||||||
|
if(!CFG_BOOTENV && pressed == SAFE_MODE)
|
||||||
|
{
|
||||||
|
nandType = FIRMWARE_SYSNAND;
|
||||||
|
firmSource = FIRMWARE_SYSNAND;
|
||||||
|
|
||||||
|
isSafeMode = true;
|
||||||
|
needToInitSd = true;
|
||||||
|
|
||||||
|
goto boot;
|
||||||
|
}
|
||||||
|
|
||||||
//If booting from CTRNAND, always use SysNAND
|
//If booting from CTRNAND, always use SysNAND
|
||||||
if(!isSdMode) nandType = FIRMWARE_SYSNAND;
|
if(!isSdMode) nandType = FIRMWARE_SYSNAND;
|
||||||
@@ -324,11 +362,11 @@ boot:
|
|||||||
u32 firmVersion = loadNintendoFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
|
u32 firmVersion = loadNintendoFirm(&firmType, firmSource, loadFromStorage, isSafeMode);
|
||||||
|
|
||||||
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO);
|
bool doUnitinfoPatch = CONFIG(PATCHUNITINFO);
|
||||||
u32 res;
|
u32 res = 0;
|
||||||
switch(firmType)
|
switch(firmType)
|
||||||
{
|
{
|
||||||
case NATIVE_FIRM:
|
case NATIVE_FIRM:
|
||||||
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, isSafeMode, doUnitinfoPatch);
|
res = patchNativeFirm(firmVersion, nandType, loadFromStorage, isFirmProtEnabled, needToInitSd, doUnitinfoPatch);
|
||||||
break;
|
break;
|
||||||
case TWL_FIRM:
|
case TWL_FIRM:
|
||||||
res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
|
res = patchTwlFirm(firmVersion, loadFromStorage, doUnitinfoPatch);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -26,50 +26,11 @@
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
|
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
|
||||||
* memcpy, memset32 and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
* memcpy, memset and memcmp adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size)
|
|
||||||
{
|
|
||||||
u8 *destc = (u8 *)dest;
|
|
||||||
const u8 *srcc = (const u8 *)src;
|
|
||||||
|
|
||||||
for(u32 i = 0; i < size; i++)
|
|
||||||
destc[i] = srcc[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
void memset(void *dest, u32 filler, u32 size)
|
|
||||||
{
|
|
||||||
u8 *destc = (u8 *)dest;
|
|
||||||
|
|
||||||
for(u32 i = 0; i < size; i++)
|
|
||||||
destc[i] = (u8)filler;
|
|
||||||
}
|
|
||||||
|
|
||||||
void memset32(void *dest, u32 filler, u32 size)
|
|
||||||
{
|
|
||||||
u32 *dest32 = (u32 *)dest;
|
|
||||||
|
|
||||||
for(u32 i = 0; i < size / 4; i++)
|
|
||||||
dest32[i] = filler;
|
|
||||||
}
|
|
||||||
|
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size)
|
|
||||||
{
|
|
||||||
const u8 *buf1c = (const u8 *)buf1,
|
|
||||||
*buf2c = (const u8 *)buf2;
|
|
||||||
|
|
||||||
for(u32 i = 0; i < size; i++)
|
|
||||||
{
|
|
||||||
int cmp = buf1c[i] - buf2c[i];
|
|
||||||
if(cmp != 0) return cmp;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize)
|
||||||
{
|
{
|
||||||
const u8 *patternc = (const u8 *)pattern;
|
const u8 *patternc = (const u8 *)pattern;
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -24,22 +24,13 @@
|
|||||||
* reasonable ways as different from the original version.
|
* reasonable ways as different from the original version.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Boyer-Moore Horspool algorithm adapted from http://www-igm.univ-mlv.fr/~lecroq/string/node18.html#SECTION00180
|
||||||
|
*/
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <string.h>
|
||||||
|
#include "types.h"
|
||||||
|
|
||||||
//Common data types
|
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
||||||
typedef uint8_t u8;
|
|
||||||
typedef uint16_t u16;
|
|
||||||
typedef uint32_t u32;
|
|
||||||
typedef uint64_t u64;
|
|
||||||
typedef volatile u8 vu8;
|
|
||||||
typedef volatile u16 vu16;
|
|
||||||
typedef volatile u32 vu32;
|
|
||||||
typedef volatile u64 vu64;
|
|
||||||
|
|
||||||
struct fb {
|
|
||||||
u8 *top_left;
|
|
||||||
u8 *top_right;
|
|
||||||
u8 *bottom;
|
|
||||||
};
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -39,7 +39,8 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
#include "../build/bundled.h"
|
#include "arm9_exception_handlers.h"
|
||||||
|
#include "large_patches.h"
|
||||||
|
|
||||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr)
|
||||||
{
|
{
|
||||||
@@ -78,8 +79,8 @@ u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 *
|
|||||||
return arm11SvcTable;
|
return arm11SvcTable;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For ARM prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
|
// For Arm prologs in the form of: push {regs} ... sub sp, #off (this obviously doesn't intend to cover all cases)
|
||||||
static inline u32 computeARMFrameSize(const u32 *prolog)
|
static inline u32 computeArmFrameSize(const u32 *prolog)
|
||||||
{
|
{
|
||||||
const u32 *off;
|
const u32 *off;
|
||||||
|
|
||||||
@@ -100,13 +101,12 @@ static inline u32 *getKernel11HandlerVAPos(u8 *pos, u32 *arm11ExceptionsPage, u3
|
|||||||
return (u32 *)(pos + pointedInstructionVA - baseK11VA + 8);
|
return (u32 *)(pos + pointedInstructionVA - baseK11VA + 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space)
|
||||||
{
|
{
|
||||||
//The parameters to be passed on to the kernel ext
|
//The parameters to be passed on to the kernel ext
|
||||||
//Please keep that in sync with the definition in k11_extension/source/main.c
|
//Please keep that in sync with the definition in k11_extension/source/main.c
|
||||||
struct KExtParameters
|
struct KExtParameters
|
||||||
{
|
{
|
||||||
u32 __attribute__((aligned(0x400))) L2MMUTableFor0x40000000[256];
|
|
||||||
u32 basePA;
|
u32 basePA;
|
||||||
void *originalHandlers[4];
|
void *originalHandlers[4];
|
||||||
u32 L1MMUTableAddrs[4];
|
u32 L1MMUTableAddrs[4];
|
||||||
@@ -201,7 +201,7 @@ u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *
|
|||||||
|
|
||||||
if(ISRELEASE) info->flags = 1;
|
if(ISRELEASE) info->flags = 1;
|
||||||
if(ISN3DS) info->flags |= 1 << 4;
|
if(ISN3DS) info->flags |= 1 << 4;
|
||||||
if(isSafeMode) info->flags |= 1 << 5;
|
if(needToInitSd) info->flags |= 1 << 5;
|
||||||
if(isSdMode) info->flags |= 1 << 6;
|
if(isSdMode) info->flags |= 1 << 6;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -230,7 +230,7 @@ u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm
|
|||||||
*/
|
*/
|
||||||
for(off = (u32 *)ControlMemoryPos; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
|
for(off = (u32 *)ControlMemoryPos; (off[0] & 0xFFF0FFFF) != 0xE3500001 || (off[1] & 0xFFFF0FFF) != 0x13A00000; off++);
|
||||||
off -= 2;
|
off -= 2;
|
||||||
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeARMFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
|
*off = 0xE59D0000 | (*off & 0x0000F000) | (8 + computeArmFrameSize((u32 *)ControlMemoryPos)); // ldr r0, [sp, #(frameSize + 8)]
|
||||||
|
|
||||||
//Patch DebugActiveProcess
|
//Patch DebugActiveProcess
|
||||||
for(off = (u32 *)(pos + (arm11SvcTable[0x60] - baseK11VA)); *off != 0xE3110001; off++);
|
for(off = (u32 *)(pos + (arm11SvcTable[0x60] - baseK11VA)); *off != 0xE3110001; off++);
|
||||||
@@ -302,7 +302,7 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
|||||||
static const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90};
|
static const u8 pattern[] = {0xE2, 0x20, 0x20, 0x90};
|
||||||
|
|
||||||
u32 pathLen;
|
u32 pathLen;
|
||||||
for(pathLen = 0; pathLen < 41 && launchedPath[pathLen] != 0; pathLen++);
|
for(pathLen = 0; pathLen < sizeof(launchedPath)/2 && launchedPath[pathLen] != 0; pathLen++);
|
||||||
|
|
||||||
if(launchedPath[pathLen] != 0) return 1;
|
if(launchedPath[pathLen] != 0) return 1;
|
||||||
|
|
||||||
@@ -312,18 +312,17 @@ u32 patchFirmlaunches(u8 *pos, u32 size, u32 process9MemAddr)
|
|||||||
|
|
||||||
off -= 0x13;
|
off -= 0x13;
|
||||||
|
|
||||||
//Firmlaunch function offset - offset in BLX opcode (A4-16 - ARM DDI 0100E) + 1
|
//Firmlaunch function offset - offset in BLX opcode (A4-16 - Arm DDI 0100E) + 1
|
||||||
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
u32 fOpenOffset = (u32)(off + 9 - (-((*(u32 *)off & 0x00FFFFFF) << 2) & (0xFFFFFF << 2)) - pos + process9MemAddr);
|
||||||
|
|
||||||
//Copy firmlaunch code
|
|
||||||
memcpy(off, reboot_bin, reboot_bin_size);
|
|
||||||
|
|
||||||
//Put the fOpen offset in the right location
|
//Put the fOpen offset in the right location
|
||||||
u32 *pos_fopen = (u32 *)memsearch(off, "OPEN", reboot_bin_size, 4);
|
rebootPatchFopenPtr = fOpenOffset;
|
||||||
*pos_fopen = fOpenOffset;
|
|
||||||
|
|
||||||
u16 *fname = (u16 *)memsearch(off, "FILE", reboot_bin_size, 8);
|
//Copy the launched path
|
||||||
memcpy(fname, launchedPath, 2 * (1 + pathLen));
|
memcpy(rebootPatchFileName, launchedPath, 2 * (1 + pathLen));
|
||||||
|
|
||||||
|
//Copy firmlaunch code
|
||||||
|
memcpy(off, rebootPatch, rebootPatchSize);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -373,7 +372,7 @@ u32 patchTitleInstallMinVersionChecks(u8 *pos, u32 size, u32 firmVersion)
|
|||||||
off++;
|
off++;
|
||||||
|
|
||||||
//Zero out the first TitleID in the list
|
//Zero out the first TitleID in the list
|
||||||
memset32(off, 0, 8);
|
memset(off, 0, 8);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@@ -501,20 +500,20 @@ u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address)
|
|||||||
addr[0] = 0xE1A0800D;
|
addr[0] = 0xE1A0800D;
|
||||||
addr[1] = 0xE12FFF7F;
|
addr[1] = 0xE12FFF7F;
|
||||||
|
|
||||||
*(vu32 *)0x01FF8004 = arm9SvcTable[0x3C]; //BreakPtr
|
arm9ExceptionHandlerSvcBreakAddress = arm9SvcTable[0x3C]; //BreakPtr
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 patchKernel9Panic(u8 *pos, u32 size)
|
u32 patchKernel9Panic(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
static const u8 pattern[] = {0xFF, 0xEA, 0x04, 0xD0};
|
static const u8 pattern[] = {0x00, 0x20, 0x92, 0x15};
|
||||||
|
|
||||||
u8 *temp = memsearch(pos, pattern, size, sizeof(pattern));
|
u8 *temp = memsearch(pos, pattern, size, sizeof(pattern));
|
||||||
|
|
||||||
if(temp == NULL) return 1;
|
if(temp == NULL) return 1;
|
||||||
|
|
||||||
u32 *off = (u32 *)(temp - 0x12);
|
u32 *off = (u32 *)(temp - 0x34);
|
||||||
*off = 0xE12FFF7E;
|
*off = 0xE12FFF7E;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
@@ -550,6 +549,34 @@ u32 patchUnitInfoValueSet(u8 *pos, u32 size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 patchP9AMTicketWrapperZeroKeyIV(u8 *pos, u32 size, u32 firmVersion)
|
||||||
|
{
|
||||||
|
static const u8 __rt_memclr_pattern[] = {0x00, 0x20, 0xA0, 0xE3, 0x04, 0x00, 0x51, 0xE3, 0x07, 0x00, 0x00, 0x3A};
|
||||||
|
static const u8 pattern[] = {0x20, 0x21, 0xA6, 0xA8};
|
||||||
|
|
||||||
|
u32 function = (u32)memsearch(pos, __rt_memclr_pattern, size, sizeof(__rt_memclr_pattern));
|
||||||
|
u16 *off = (u16 *)memsearch(pos, pattern, size, sizeof(pattern));
|
||||||
|
|
||||||
|
if(function == 0 || off == NULL) return firmVersion == 0xFFFFFFFF ? 0 : 1;
|
||||||
|
|
||||||
|
//After the found code it's a BL call (at &off[2]), that will be replaced
|
||||||
|
//From Thumb, op distance for setting in BLX can be got with,
|
||||||
|
//(Destination_offset - blx_op_offset+2) / 2
|
||||||
|
s32 opjumpdistance = (s32)(function - ((u32)&off[3])) / 2;
|
||||||
|
|
||||||
|
//Beyond limit
|
||||||
|
if(opjumpdistance < -0x1fffff || opjumpdistance > 0x1fffff) return 1;
|
||||||
|
|
||||||
|
//r0 and r1 for old call are already correct for this one
|
||||||
|
//BLX __rt_memclr
|
||||||
|
u32 op = (0xE800F000U | (((u32)opjumpdistance & 0x7FF) << 16) | (((u32)opjumpdistance >> 11) & 0x3FF) | (((u32)opjumpdistance >> 21) & 0x400)) & ~(1<<16);
|
||||||
|
|
||||||
|
off[2] = op;
|
||||||
|
off[3] = op >> 16;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u32 patchLgySignatureChecks(u8 *pos, u32 size)
|
u32 patchLgySignatureChecks(u8 *pos, u32 size)
|
||||||
{
|
{
|
||||||
static const u8 pattern[] = {0x47, 0xC1, 0x17, 0x49};
|
static const u8 pattern[] = {0x47, 0xC1, 0x17, 0x49};
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -39,7 +39,7 @@
|
|||||||
|
|
||||||
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
u8 *getProcess9Info(u8 *pos, u32 size, u32 *process9Size, u32 *process9MemAddr);
|
||||||
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
|
u32 *getKernel11Info(u8 *pos, u32 size, u32 *baseK11VA, u8 **freeK11Space, u32 **arm11SvcHandler, u32 **arm11ExceptionsPage);
|
||||||
u32 installK11Extension(u8 *pos, u32 size, bool isSafeMode, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
u32 installK11Extension(u8 *pos, u32 size, bool needToInitSd, u32 baseK11VA, u32 *arm11ExceptionsPage, u8 **freeK11Space);
|
||||||
u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage);
|
u32 patchKernel11(u8 *pos, u32 size, u32 baseK11VA, u32 *arm11SvcTable, u32 *arm11ExceptionsPage);
|
||||||
u32 patchSignatureChecks(u8 *pos, u32 size);
|
u32 patchSignatureChecks(u8 *pos, u32 size);
|
||||||
u32 patchOldSignatureChecks(u8 *pos, u32 size);
|
u32 patchOldSignatureChecks(u8 *pos, u32 size);
|
||||||
@@ -56,6 +56,7 @@ u32 patchSvcBreak9(u8 *pos, u32 size, u32 kernel9Address);
|
|||||||
u32 patchKernel9Panic(u8 *pos, u32 size);
|
u32 patchKernel9Panic(u8 *pos, u32 size);
|
||||||
u32 patchP9AccessChecks(u8 *pos, u32 size);
|
u32 patchP9AccessChecks(u8 *pos, u32 size);
|
||||||
u32 patchUnitInfoValueSet(u8 *pos, u32 size);
|
u32 patchUnitInfoValueSet(u8 *pos, u32 size);
|
||||||
|
u32 patchP9AMTicketWrapperZeroKeyIV(u8 *pos, u32 size, u32 firmVersion);
|
||||||
u32 patchLgySignatureChecks(u8 *pos, u32 size);
|
u32 patchLgySignatureChecks(u8 *pos, u32 size);
|
||||||
u32 patchTwlInvalidSignatureChecks(u8 *pos, u32 size);
|
u32 patchTwlInvalidSignatureChecks(u8 *pos, u32 size);
|
||||||
u32 patchTwlNintendoLogoChecks(u8 *pos, u32 size);
|
u32 patchTwlNintendoLogoChecks(u8 *pos, u32 size);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -69,7 +69,7 @@ void newPin(bool allowSkipping, u32 pinMode)
|
|||||||
{
|
{
|
||||||
if(reset)
|
if(reset)
|
||||||
{
|
{
|
||||||
for(u32 i = 0; i < cnt; i++)
|
for(u32 i = 0; i < cnt; i++)
|
||||||
drawCharacter(true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK, (char)enteredPassword[i]);
|
drawCharacter(true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK, (char)enteredPassword[i]);
|
||||||
|
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
@@ -154,7 +154,7 @@ bool verifyPin(u32 pinMode)
|
|||||||
drawFormattedString(true, 10, 10 + 3 * SPACING_Y, COLOR_WHITE, "PIN (%u digits): ", lengthBlock[0]);
|
drawFormattedString(true, 10, 10 + 3 * SPACING_Y, COLOR_WHITE, "PIN (%u digits): ", lengthBlock[0]);
|
||||||
|
|
||||||
bool isBottomSplashValid = getFileSize("splashpin.bin") == SCREEN_BOTTOM_FBSIZE;
|
bool isBottomSplashValid = getFileSize("splashpin.bin") == SCREEN_BOTTOM_FBSIZE;
|
||||||
if(isBottomSplashValid)
|
if(isBottomSplashValid)
|
||||||
{
|
{
|
||||||
isBottomSplashValid = fileRead(fbs[0].bottom, "splashpin.bin", SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE;
|
isBottomSplashValid = fileRead(fbs[0].bottom, "splashpin.bin", SCREEN_BOTTOM_FBSIZE) == SCREEN_BOTTOM_FBSIZE;
|
||||||
}
|
}
|
||||||
@@ -184,7 +184,7 @@ bool verifyPin(u32 pinMode)
|
|||||||
{
|
{
|
||||||
if(reset)
|
if(reset)
|
||||||
{
|
{
|
||||||
for(u32 i = 0; i < cnt; i++)
|
for(u32 i = 0; i < cnt; i++)
|
||||||
drawCharacter(true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK, '*');
|
drawCharacter(true, 10 + (16 + 2 * i) * SPACING_X, 10 + 3 * SPACING_Y, COLOR_BLACK, '*');
|
||||||
|
|
||||||
cnt = 0;
|
cnt = 0;
|
||||||
@@ -225,7 +225,7 @@ bool verifyPin(u32 pinMode)
|
|||||||
{
|
{
|
||||||
reset = true;
|
reset = true;
|
||||||
|
|
||||||
drawString(true, 10, 10 + 5 * SPACING_Y, COLOR_RED, "Wrong PIN, try again");
|
drawString(true, 10, 10 + 5 * SPACING_Y, COLOR_RED, "Wrong PIN, try again");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -35,6 +35,8 @@
|
|||||||
#include "i2c.h"
|
#include "i2c.h"
|
||||||
#include "utils.h"
|
#include "utils.h"
|
||||||
|
|
||||||
|
bool needToSetupScreens = true;
|
||||||
|
|
||||||
struct fb fbs[2] =
|
struct fb fbs[2] =
|
||||||
{
|
{
|
||||||
{
|
{
|
||||||
@@ -57,7 +59,7 @@ static void invokeArm11Function(Arm11Operation op)
|
|||||||
{
|
{
|
||||||
while(*operation != ARM11_READY);
|
while(*operation != ARM11_READY);
|
||||||
*operation = op;
|
*operation = op;
|
||||||
while(*operation != ARM11_READY);
|
while(*operation != ARM11_READY);
|
||||||
}
|
}
|
||||||
|
|
||||||
void prepareArm11ForFirmlaunch(void)
|
void prepareArm11ForFirmlaunch(void)
|
||||||
@@ -92,18 +94,17 @@ void clearScreens(bool isAlternate)
|
|||||||
|
|
||||||
void initScreens(void)
|
void initScreens(void)
|
||||||
{
|
{
|
||||||
static bool needToSetup = true;
|
if(needToSetupScreens)
|
||||||
|
|
||||||
if(needToSetup)
|
|
||||||
{
|
{
|
||||||
if(!ARESCREENSINITIALIZED)
|
if(!ARESCREENSINITIALIZED || bootType == FIRMLAUNCH)
|
||||||
{
|
{
|
||||||
*(vu32 *)ARM11_PARAMETERS_ADDRESS = brightness[MULTICONFIG(BRIGHTNESS)];
|
*(vu32 *)ARM11_PARAMETERS_ADDRESS = brightness[MULTICONFIG(BRIGHTNESS)];
|
||||||
memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs));
|
memcpy((void *)(ARM11_PARAMETERS_ADDRESS + 4), fbs, sizeof(fbs));
|
||||||
invokeArm11Function(INIT_SCREENS);
|
invokeArm11Function(INIT_SCREENS);
|
||||||
|
|
||||||
//Turn on backlight
|
//Turn on backlight
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x22, 0x2A);
|
I2C_writeReg(I2C_DEV_MCU, 0x22, 0x2A);
|
||||||
|
wait(5);
|
||||||
}
|
}
|
||||||
else updateBrightness(MULTICONFIG(BRIGHTNESS));
|
else updateBrightness(MULTICONFIG(BRIGHTNESS));
|
||||||
|
|
||||||
@@ -111,7 +112,7 @@ void initScreens(void)
|
|||||||
invokeArm11Function(SETUP_FRAMEBUFFERS);
|
invokeArm11Function(SETUP_FRAMEBUFFERS);
|
||||||
|
|
||||||
clearScreens(true);
|
clearScreens(true);
|
||||||
needToSetup = false;
|
needToSetupScreens = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
clearScreens(false);
|
clearScreens(false);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -33,9 +33,9 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
#define PDN_GPU_CNT (*(vu8 *)0x10141200)
|
#define PDN_GPU_CNT (*(vu32 *)0x10141200)
|
||||||
|
|
||||||
#define ARESCREENSINITIALIZED (PDN_GPU_CNT != 1)
|
#define ARESCREENSINITIALIZED ((PDN_GPU_CNT & 0xFF) != 1)
|
||||||
|
|
||||||
#define ARM11_PARAMETERS_ADDRESS 0x1FFFF000
|
#define ARM11_PARAMETERS_ADDRESS 0x1FFFF000
|
||||||
|
|
||||||
@@ -65,6 +65,8 @@ typedef enum
|
|||||||
|
|
||||||
extern struct fb fbs[2];
|
extern struct fb fbs[2];
|
||||||
|
|
||||||
|
extern bool needToSetupScreens;
|
||||||
|
|
||||||
void prepareArm11ForFirmlaunch(void);
|
void prepareArm11ForFirmlaunch(void);
|
||||||
void deinitScreens(void);
|
void deinitScreens(void);
|
||||||
void swapFramebuffers(bool isAlternate);
|
void swapFramebuffers(bool isAlternate);
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
@ This file is part of Luma3DS
|
@ This file is part of Luma3DS
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
@ Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
@
|
@
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
@ This program is free software: you can redistribute it and/or modify
|
||||||
@ it under the terms of the GNU General Public License as published by
|
@ it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
@ or requiring that modified versions of such material be marked in
|
@ or requiring that modified versions of such material be marked in
|
||||||
@ reasonable ways as different from the original version.
|
@ reasonable ways as different from the original version.
|
||||||
|
|
||||||
.section .text.start
|
.section .text.start, "ax", %progbits
|
||||||
.align 4
|
.align 4
|
||||||
.global _start
|
.global _start
|
||||||
_start:
|
_start:
|
||||||
@@ -77,7 +77,7 @@ _start:
|
|||||||
ldr r1, =0xFFF0001B @ fff00000 16k | dtcm
|
ldr r1, =0xFFF0001B @ fff00000 16k | dtcm
|
||||||
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
ldr r2, =0x01FF801D @ 01ff8000 32k | itcm
|
||||||
ldr r3, =0x08000027 @ 08000000 1M | arm9 mem
|
ldr r3, =0x08000027 @ 08000000 1M | arm9 mem
|
||||||
ldr r4, =0x10000029 @ 10000000 2M | io mem (ARM9 / first 2MB)
|
ldr r4, =0x10000029 @ 10000000 2M | io mem (Arm9 / first 2MB)
|
||||||
ldr r5, =0x20000035 @ 20000000 128M | fcram
|
ldr r5, =0x20000035 @ 20000000 128M | fcram
|
||||||
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
ldr r6, =0x1FF00027 @ 1FF00000 1M | dsp / axi wram
|
||||||
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
ldr r7, =0x1800002D @ 18000000 8M | vram (+ 2MB)
|
||||||
@@ -109,13 +109,58 @@ _start:
|
|||||||
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||||
|
|
||||||
@ Clear BSS
|
@ Clear BSS
|
||||||
ldr r0, =__bss_start
|
ldr r0, =__bss_start__
|
||||||
mov r1, #0
|
mov r1, #0
|
||||||
ldr r2, =__bss_end
|
ldr r2, =__bss_end__
|
||||||
sub r2, r0
|
sub r2, r0
|
||||||
bl memset32
|
bl memset
|
||||||
|
|
||||||
|
bl __libc_init_array
|
||||||
|
|
||||||
mov r0, r9
|
mov r0, r9
|
||||||
mov r1, r10
|
mov r1, r10
|
||||||
mov r2, r11
|
mov r2, r11
|
||||||
b main
|
b main
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.section .chainloader.text.start, "ax", %progbits
|
||||||
|
.align 4
|
||||||
|
.global chainload
|
||||||
|
.type chainload, %function
|
||||||
|
chainload:
|
||||||
|
ldr sp, =__itcm_stack_top__
|
||||||
|
b chainloader_main
|
||||||
|
.pool
|
||||||
|
|
||||||
|
.global disableMpuAndJumpToEntrypoints
|
||||||
|
.type disableMpuAndJumpToEntrypoints, %function
|
||||||
|
disableMpuAndJumpToEntrypoints:
|
||||||
|
mov r4, r0
|
||||||
|
mov r5, r1
|
||||||
|
mov r6, r2
|
||||||
|
mov r7, r3
|
||||||
|
|
||||||
|
@ Flush caches
|
||||||
|
ldr r12, =0xFFFF0830
|
||||||
|
blx r12
|
||||||
|
ldr r12, =0xFFFF0AB4
|
||||||
|
blx r12
|
||||||
|
|
||||||
|
@ Disable caches / MPU
|
||||||
|
mrc p15, 0, r0, c1, c0, 0 @ read control register
|
||||||
|
bic r0, #(1<<12) @ - instruction cache disable
|
||||||
|
bic r0, #(1<<2) @ - data cache disable
|
||||||
|
bic r0, #(1<<0) @ - MPU disable
|
||||||
|
mcr p15, 0, r0, c1, c0, 0 @ write control register
|
||||||
|
|
||||||
|
@ Set the Arm11 entrypoint
|
||||||
|
mov r0, #0x20000000
|
||||||
|
str r7, [r0, #-4]
|
||||||
|
|
||||||
|
@ Jump to the Arm9 entrypoint
|
||||||
|
mov r0, r4
|
||||||
|
mov r1, r5
|
||||||
|
ldr r2, =0x3BEEF
|
||||||
|
bx r6
|
||||||
|
|
||||||
|
.pool
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -25,25 +25,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
#include "strings.h"
|
#include "strings.h"
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
u32 strlen(const char *string)
|
|
||||||
{
|
|
||||||
char *stringEnd = (char *)string;
|
|
||||||
|
|
||||||
while(*stringEnd != 0) stringEnd++;
|
|
||||||
|
|
||||||
return stringEnd - string;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 strnlen(const char *string, u32 maxlen)
|
|
||||||
{
|
|
||||||
u32 size;
|
|
||||||
|
|
||||||
for(size = 0; size < maxlen && *string; string++, size++);
|
|
||||||
|
|
||||||
return size;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 hexAtoi(const char *in, u32 digits)
|
u32 hexAtoi(const char *in, u32 digits)
|
||||||
{
|
{
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -28,7 +28,5 @@
|
|||||||
|
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
|
|
||||||
u32 strlen(const char *string);
|
|
||||||
u32 strnlen(const char *string, u32 maxlen);
|
|
||||||
u32 hexAtoi(const char *in, u32 digits);
|
u32 hexAtoi(const char *in, u32 digits);
|
||||||
u32 decAtoi(const char *in, u32 digits);
|
u32 decAtoi(const char *in, u32 digits);
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -61,7 +61,7 @@ typedef volatile s64 vs64;
|
|||||||
#define ISN3DS (CFG11_SOCINFO & 2)
|
#define ISN3DS (CFG11_SOCINFO & 2)
|
||||||
#define ISDEVUNIT (CFG_UNITINFO != 0)
|
#define ISDEVUNIT (CFG_UNITINFO != 0)
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct __attribute__((packed, aligned(4)))
|
||||||
{
|
{
|
||||||
char magic[4];
|
char magic[4];
|
||||||
u16 formatVersionMajor, formatVersionMinor;
|
u16 formatVersionMajor, formatVersionMinor;
|
||||||
@@ -71,7 +71,7 @@ typedef struct __attribute__((packed))
|
|||||||
u32 rosalinaMenuCombo;
|
u32 rosalinaMenuCombo;
|
||||||
} CfgData;
|
} CfgData;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
char magic[4];
|
char magic[4];
|
||||||
u16 formatVersionMajor, formatVersionMinor;
|
u16 formatVersionMajor, formatVersionMinor;
|
||||||
@@ -80,7 +80,7 @@ typedef struct __attribute__((packed))
|
|||||||
u8 hash[32];
|
u8 hash[32];
|
||||||
} PinData;
|
} PinData;
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 magic[2];
|
u32 magic[2];
|
||||||
u16 versionMinor, versionMajor;
|
u16 versionMinor, versionMajor;
|
||||||
@@ -129,4 +129,4 @@ extern bool isSdMode;
|
|||||||
extern BootType bootType;
|
extern BootType bootType;
|
||||||
|
|
||||||
extern u16 launchedFirmTidLow[8];
|
extern u16 launchedFirmTidLow[8];
|
||||||
extern u16 launchedPath[41];
|
extern u16 launchedPath[80+1];
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -35,7 +35,7 @@
|
|||||||
#include "draw.h"
|
#include "draw.h"
|
||||||
#include "cache.h"
|
#include "cache.h"
|
||||||
#include "fmt.h"
|
#include "fmt.h"
|
||||||
#include "strings.h"
|
#include "memory.h"
|
||||||
#include "fs.h"
|
#include "fs.h"
|
||||||
|
|
||||||
static void startChrono(void)
|
static void startChrono(void)
|
||||||
@@ -86,8 +86,17 @@ u32 waitInput(bool isMenu)
|
|||||||
|
|
||||||
if(!key)
|
if(!key)
|
||||||
{
|
{
|
||||||
if((!(i2cReadRegister(I2C_DEV_MCU, 0xF) & 2) && shouldShellShutdown) ||
|
if(shouldShellShutdown)
|
||||||
(i2cReadRegister(I2C_DEV_MCU, 0x10) & 1) == 1) mcuPowerOff();
|
{
|
||||||
|
u8 shellState = I2C_readReg(I2C_DEV_MCU, 0xF);
|
||||||
|
wait(5);
|
||||||
|
if(!(shellState & 2)) mcuPowerOff();
|
||||||
|
}
|
||||||
|
|
||||||
|
u8 intStatus = I2C_readReg(I2C_DEV_MCU, 0x10);
|
||||||
|
wait(5);
|
||||||
|
if(intStatus & 1) mcuPowerOff(); //Power button pressed
|
||||||
|
|
||||||
oldKey = 0;
|
oldKey = 0;
|
||||||
dPadDelay = 0;
|
dPadDelay = 0;
|
||||||
continue;
|
continue;
|
||||||
@@ -106,15 +115,15 @@ u32 waitInput(bool isMenu)
|
|||||||
|
|
||||||
void mcuPowerOff(void)
|
void mcuPowerOff(void)
|
||||||
{
|
{
|
||||||
if(bootType != FIRMLAUNCH && ARESCREENSINITIALIZED) clearScreens(false);
|
if(!needToSetupScreens) clearScreens(false);
|
||||||
|
|
||||||
//Shutdown LCD
|
//Shutdown LCD
|
||||||
if(ARESCREENSINITIALIZED) i2cWriteRegister(I2C_DEV_MCU, 0x22, 1 << 0);
|
if(ARESCREENSINITIALIZED) I2C_writeReg(I2C_DEV_MCU, 0x22, 1 << 0);
|
||||||
|
|
||||||
//Ensure that all memory transfers have completed and that the data cache has been flushed
|
//Ensure that all memory transfers have completed and that the data cache has been flushed
|
||||||
flushEntireDCache();
|
flushEntireDCache();
|
||||||
|
|
||||||
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
|
I2C_writeReg(I2C_DEV_MCU, 0x20, 1 << 0);
|
||||||
while(true);
|
while(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -136,17 +145,12 @@ void error(const char *fmt, ...)
|
|||||||
vsprintf(buf, fmt, args);
|
vsprintf(buf, fmt, args);
|
||||||
va_end(args);
|
va_end(args);
|
||||||
|
|
||||||
if(bootType != FIRMLAUNCH)
|
initScreens();
|
||||||
{
|
drawString(true, 10, 10, COLOR_RED, "An error has occurred:");
|
||||||
initScreens();
|
u32 posY = drawString(true, 10, 30, COLOR_WHITE, buf);
|
||||||
|
drawString(true, 10, posY + 2 * SPACING_Y, COLOR_WHITE, "Press any button to shutdown");
|
||||||
|
|
||||||
drawString(true, 10, 10, COLOR_RED, "An error has occurred:");
|
waitInput(false);
|
||||||
u32 posY = drawString(true, 10, 30, COLOR_WHITE, buf);
|
|
||||||
drawString(true, 10, posY + 2 * SPACING_Y, COLOR_WHITE, "Press any button to shutdown");
|
|
||||||
|
|
||||||
waitInput(false);
|
|
||||||
}
|
|
||||||
else fileWrite(buf, "firmlauncherror.txt", strlen(buf));
|
|
||||||
|
|
||||||
mcuPowerOff();
|
mcuPowerOff();
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -1,44 +0,0 @@
|
|||||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(DEVKITARM)/base_tools
|
|
||||||
|
|
||||||
name := $(shell basename $(CURDIR))
|
|
||||||
|
|
||||||
dir_source := source
|
|
||||||
dir_build := build
|
|
||||||
dir_out := ../$(dir_build)
|
|
||||||
|
|
||||||
ASFLAGS := -mcpu=arm946e-s
|
|
||||||
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -O2 -flto -ffast-math
|
|
||||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
|
||||||
|
|
||||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
all: $(dir_out)/$(name).bin
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
@rm -rf $(dir_build)
|
|
||||||
|
|
||||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
|
||||||
|
|
||||||
$(dir_build)/$(name).elf: $(objects)
|
|
||||||
$(LINK.o) -T linker.ld $(OUTPUT_OPTION) $^
|
|
||||||
|
|
||||||
$(dir_build)/memory.o: CFLAGS += -O3
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.s
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
|
||||||
OUTPUT_ARCH(arm)
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x01FF9000;
|
|
||||||
|
|
||||||
__start__ = ABSOLUTE(.);
|
|
||||||
|
|
||||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
|
||||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
|
||||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
|
|
||||||
__end__ = ABSOLUTE(.);
|
|
||||||
|
|
||||||
__stack_top__ = 0x01FFB800;
|
|
||||||
__stack_bottom__ = 0x01FFA800;
|
|
||||||
}
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
@ This file is part of Luma3DS
|
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
@
|
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
|
||||||
@ it under the terms of the GNU General Public License as published by
|
|
||||||
@ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
@ (at your option) any later version.
|
|
||||||
@
|
|
||||||
@ This program is distributed in the hope that it will be useful,
|
|
||||||
@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
@ GNU General Public License for more details.
|
|
||||||
@
|
|
||||||
@ You should have received a copy of the GNU General Public License
|
|
||||||
@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
@
|
|
||||||
@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
@ * Requiring preservation of specified reasonable legal notices or
|
|
||||||
@ author attributions in that material or in the Appropriate Legal
|
|
||||||
@ Notices displayed by works containing it.
|
|
||||||
@ * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
@ or requiring that modified versions of such material be marked in
|
|
||||||
@ reasonable ways as different from the original version.
|
|
||||||
|
|
||||||
.text
|
|
||||||
.arm
|
|
||||||
.align 4
|
|
||||||
|
|
||||||
.global flushCaches
|
|
||||||
.type flushCaches, %function
|
|
||||||
flushCaches:
|
|
||||||
@ Clean and flush both the data cache and instruction caches
|
|
||||||
|
|
||||||
@ Adpated from http://infocenter.arm.com/help/index.jsp?topic=/com.arm.doc.ddi0155a/ch03s03s05.html ,
|
|
||||||
@ and https://github.com/gemarcano/libctr9_io/blob/master/src/ctr_system_ARM.c#L39 as well
|
|
||||||
@ Note: ARM's example is actually for a 8KB DCache (which is what the 3DS has)
|
|
||||||
|
|
||||||
@ Implemented in bootROM at addresses 0xffff0830 (DCache) and 0xffff0ab4 (ICache)
|
|
||||||
|
|
||||||
mov r1, #0 @ segment counter
|
|
||||||
outer_loop:
|
|
||||||
mov r0, #0 @ line counter
|
|
||||||
|
|
||||||
inner_loop:
|
|
||||||
orr r2, r1, r0 @ generate segment and line address
|
|
||||||
mcr p15, 0, r2, c7, c14, 2 @ clean and flush the line
|
|
||||||
add r0, #0x20 @ increment to next line
|
|
||||||
cmp r0, #0x400
|
|
||||||
bne inner_loop
|
|
||||||
|
|
||||||
add r1, #0x40000000
|
|
||||||
cmp r1, #0
|
|
||||||
bne outer_loop
|
|
||||||
|
|
||||||
mcr p15, 0, r1, c7, c10, 4 @ drain write buffer
|
|
||||||
|
|
||||||
@ Flush instruction cache
|
|
||||||
mcr p15, 0, r1, c7, c5, 0
|
|
||||||
|
|
||||||
bx lr
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "firm.h"
|
|
||||||
#include "memory.h"
|
|
||||||
#include "cache.h"
|
|
||||||
|
|
||||||
void disableMpuAndJumpToEntrypoints(int argc, char **argv, void *arm11Entry, void *arm9Entry);
|
|
||||||
|
|
||||||
void launchFirm(Firm *firm, int argc, char **argv)
|
|
||||||
{
|
|
||||||
//Copy FIRM sections to respective memory locations
|
|
||||||
for(u32 sectionNum = 0; sectionNum < 4; sectionNum++)
|
|
||||||
memcpy(firm->section[sectionNum].address, (u8 *)firm + firm->section[sectionNum].offset, firm->section[sectionNum].size);
|
|
||||||
|
|
||||||
disableMpuAndJumpToEntrypoints(argc, argv, firm->arm9Entry, firm->arm11Entry);
|
|
||||||
|
|
||||||
__builtin_unreachable();
|
|
||||||
}
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
|
||||||
{
|
|
||||||
u32 offset;
|
|
||||||
u8 *address;
|
|
||||||
u32 size;
|
|
||||||
u32 procType;
|
|
||||||
u8 hash[0x20];
|
|
||||||
} FirmSection;
|
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
|
||||||
{
|
|
||||||
char magic[4];
|
|
||||||
u32 reserved1;
|
|
||||||
u8 *arm11Entry;
|
|
||||||
u8 *arm9Entry;
|
|
||||||
u8 reserved2[0x30];
|
|
||||||
FirmSection section[4];
|
|
||||||
} Firm;
|
|
||||||
|
|
||||||
void launchFirm(Firm *firm, int argc, char **argv);
|
|
||||||
@@ -1,40 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* memcpy adapted from https://github.com/mid-kid/CakesForeveryWan/blob/557a8e8605ab3ee173af6497486e8f22c261d0e2/source/memfuncs.c
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "memory.h"
|
|
||||||
|
|
||||||
void memcpy(void *dest, const void *src, u32 size)
|
|
||||||
{
|
|
||||||
u8 *destc = (u8 *)dest;
|
|
||||||
const u8 *srcc = (const u8 *)src;
|
|
||||||
|
|
||||||
for(u32 i = 0; i < size; i++)
|
|
||||||
destc[i] = srcc[i];
|
|
||||||
}
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
# Requires Python >= 3.2 or >= 2.7
|
# Requires Python >= 3.2 or >= 2.7
|
||||||
|
|
||||||
# This file is part of Luma3DS
|
# This file is part of Luma3DS
|
||||||
# Copyright (C) 2016 Aurora Wright, TuxSH
|
# Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
#
|
#
|
||||||
# This program is free software: you can redistribute it and/or modify
|
# This program is free software: you can redistribute it and/or modify
|
||||||
# it under the terms of the GNU General Public License as published by
|
# it under the terms of the GNU General Public License as published by
|
||||||
@@ -22,7 +22,7 @@
|
|||||||
# Notices displayed by works containing it.
|
# Notices displayed by works containing it.
|
||||||
|
|
||||||
__author__ = "TuxSH"
|
__author__ = "TuxSH"
|
||||||
__copyright__ = "Copyright (c) 2016 TuxSH"
|
__copyright__ = "Copyright (c) 2016-2020 TuxSH"
|
||||||
__license__ = "GPLv3"
|
__license__ = "GPLv3"
|
||||||
__version__ = "v1.2"
|
__version__ = "v1.2"
|
||||||
|
|
||||||
@@ -121,8 +121,8 @@ def main(args=None):
|
|||||||
addtionalDataOffset = stackOffset + stackDumpSize
|
addtionalDataOffset = stackOffset + stackDumpSize
|
||||||
additionalData = data[addtionalDataOffset : addtionalDataOffset + additionalDataSize]
|
additionalData = data[addtionalDataOffset : addtionalDataOffset + additionalDataSize]
|
||||||
|
|
||||||
if processor == 9: print("Processor: ARM9")
|
if processor == 9: print("Processor: Arm9")
|
||||||
else: print("Processor: ARM11 (core {0})".format(processor >> 16))
|
else: print("Processor: Arm11 (core {0})".format(processor >> 16))
|
||||||
|
|
||||||
typeDetailsStr = ""
|
typeDetailsStr = ""
|
||||||
if exceptionType == 2:
|
if exceptionType == 2:
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
|
||||||
endif
|
|
||||||
|
|
||||||
include $(DEVKITARM)/base_tools
|
|
||||||
|
|
||||||
name := arm9_exceptions
|
|
||||||
|
|
||||||
dir_source := source
|
|
||||||
dir_build := build
|
|
||||||
dir_out := ../../$(dir_build)
|
|
||||||
|
|
||||||
ASFLAGS := -mcpu=arm946e-s
|
|
||||||
CFLAGS := -Wall -Wextra -marm $(ASFLAGS) -fno-builtin -std=c11 -Wno-main -Os -ffast-math
|
|
||||||
LDFLAGS := -nostartfiles -Wl,--nmagic
|
|
||||||
|
|
||||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
|
||||||
|
|
||||||
.PHONY: all
|
|
||||||
all: $(dir_out)/$(name).bin
|
|
||||||
|
|
||||||
.PHONY: clean
|
|
||||||
clean:
|
|
||||||
@rm -rf $(dir_build)
|
|
||||||
|
|
||||||
$(dir_out)/$(name).bin: $(dir_build)/$(name).elf
|
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
|
||||||
|
|
||||||
$(dir_build)/$(name).elf: $(objects)
|
|
||||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.s
|
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
|
||||||
OUTPUT_ARCH(arm)
|
|
||||||
|
|
||||||
ENTRY(_start)
|
|
||||||
SECTIONS
|
|
||||||
{
|
|
||||||
. = 0x01FF8000;
|
|
||||||
|
|
||||||
.text : ALIGN(4) { *(.text.start) *(.text*); . = ALIGN(4); }
|
|
||||||
.rodata : ALIGN(4) { *(.rodata*); . = ALIGN(4); }
|
|
||||||
.data : ALIGN(4) { *(.data*); . = ALIGN(8); *(.bss* COMMON); . = ALIGN(8); }
|
|
||||||
|
|
||||||
. = ALIGN(4);
|
|
||||||
}
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
|
||||||
{
|
|
||||||
u32 magic[2];
|
|
||||||
u16 versionMinor, versionMajor;
|
|
||||||
|
|
||||||
u16 processor, core;
|
|
||||||
u32 type;
|
|
||||||
|
|
||||||
u32 totalSize;
|
|
||||||
u32 registerDumpSize;
|
|
||||||
u32 codeDumpSize;
|
|
||||||
u32 stackDumpSize;
|
|
||||||
u32 additionalDataSize;
|
|
||||||
} ExceptionDumpHeader;
|
|
||||||
|
|
||||||
void FIQHandler(void);
|
|
||||||
void undefinedInstructionHandler(void);
|
|
||||||
void dataAbortHandler(void);
|
|
||||||
void prefetchAbortHandler(void);
|
|
||||||
|
|
||||||
u32 safecpy(void *dst, const void *src, u32 len);
|
|
||||||
@@ -1,143 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/*
|
|
||||||
* Thanks to whoever contributed in the development of this file
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "i2c.h"
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static const struct { u8 bus_id, reg_addr; } dev_data[] = {
|
|
||||||
{0, 0x4A}, {0, 0x7A}, {0, 0x78},
|
|
||||||
{1, 0x4A}, {1, 0x78}, {1, 0x2C},
|
|
||||||
{1, 0x2E}, {1, 0x40}, {1, 0x44},
|
|
||||||
{2, 0xD6}, {2, 0xD0}, {2, 0xD2},
|
|
||||||
{2, 0xA4}, {2, 0x9A}, {2, 0xA0},
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline u8 i2cGetDeviceBusId(u8 device_id)
|
|
||||||
{
|
|
||||||
return dev_data[device_id].bus_id;
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline u8 i2cGetDeviceRegAddr(u8 device_id)
|
|
||||||
{
|
|
||||||
return dev_data[device_id].reg_addr;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static vu8 *reg_data_addrs[] = {
|
|
||||||
(vu8 *)(I2C1_REG_OFF + I2C_REG_DATA),
|
|
||||||
(vu8 *)(I2C2_REG_OFF + I2C_REG_DATA),
|
|
||||||
(vu8 *)(I2C3_REG_OFF + I2C_REG_DATA),
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline vu8 *i2cGetDataReg(u8 bus_id)
|
|
||||||
{
|
|
||||||
return reg_data_addrs[bus_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static vu8 *reg_cnt_addrs[] = {
|
|
||||||
(vu8 *)(I2C1_REG_OFF + I2C_REG_CNT),
|
|
||||||
(vu8 *)(I2C2_REG_OFF + I2C_REG_CNT),
|
|
||||||
(vu8 *)(I2C3_REG_OFF + I2C_REG_CNT),
|
|
||||||
};
|
|
||||||
|
|
||||||
static inline vu8 *i2cGetCntReg(u8 bus_id)
|
|
||||||
{
|
|
||||||
return reg_cnt_addrs[bus_id];
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static inline void i2cWaitBusy(u8 bus_id)
|
|
||||||
{
|
|
||||||
while (*i2cGetCntReg(bus_id) & 0x80);
|
|
||||||
}
|
|
||||||
|
|
||||||
static inline bool i2cGetResult(u8 bus_id)
|
|
||||||
{
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
|
|
||||||
return (*i2cGetCntReg(bus_id) >> 4) & 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void i2cStop(u8 bus_id, u8 arg0)
|
|
||||||
{
|
|
||||||
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC5;
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
static bool i2cSelectDevice(u8 bus_id, u8 dev_reg)
|
|
||||||
{
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetDataReg(bus_id) = dev_reg;
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC2;
|
|
||||||
|
|
||||||
return i2cGetResult(bus_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static bool i2cSelectRegister(u8 bus_id, u8 reg)
|
|
||||||
{
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetDataReg(bus_id) = reg;
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC0;
|
|
||||||
|
|
||||||
return i2cGetResult(bus_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
//-----------------------------------------------------------------------------
|
|
||||||
|
|
||||||
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data)
|
|
||||||
{
|
|
||||||
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
|
||||||
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
|
||||||
|
|
||||||
for(u32 i = 0; i < 8; i++)
|
|
||||||
{
|
|
||||||
if(i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg))
|
|
||||||
{
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
*i2cGetDataReg(bus_id) = data;
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC1;
|
|
||||||
i2cStop(bus_id, 0);
|
|
||||||
|
|
||||||
if(i2cGetResult(bus_id)) return true;
|
|
||||||
}
|
|
||||||
*i2cGetCntReg(bus_id) = 0xC5;
|
|
||||||
i2cWaitBusy(bus_id);
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
@@ -1,39 +0,0 @@
|
|||||||
@ This file is part of Luma3DS
|
|
||||||
@ Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
@
|
|
||||||
@ This program is free software: you can redistribute it and/or modify
|
|
||||||
@ it under the terms of the GNU General Public License as published by
|
|
||||||
@ the Free Software Foundation, either version 3 of the License, or
|
|
||||||
@ (at your option) any later version.
|
|
||||||
@
|
|
||||||
@ This program is distributed in the hope that it will be useful,
|
|
||||||
@ but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
@ GNU General Public License for more details.
|
|
||||||
@
|
|
||||||
@ You should have received a copy of the GNU General Public License
|
|
||||||
@ along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
@
|
|
||||||
@ Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
@ * Requiring preservation of specified reasonable legal notices or
|
|
||||||
@ author attributions in that material or in the Appropriate Legal
|
|
||||||
@ Notices displayed by works containing it.
|
|
||||||
@ * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
@ or requiring that modified versions of such material be marked in
|
|
||||||
@ reasonable ways as different from the original version.
|
|
||||||
|
|
||||||
.section .text.start
|
|
||||||
.align 4
|
|
||||||
.global _start
|
|
||||||
_start:
|
|
||||||
add pc, r0, #(handlers - .) @ Dummy instruction
|
|
||||||
|
|
||||||
.global BreakPtr
|
|
||||||
BreakPtr: .word 0
|
|
||||||
|
|
||||||
.global handlers
|
|
||||||
handlers:
|
|
||||||
.word FIQHandler
|
|
||||||
.word undefinedInstructionHandler
|
|
||||||
.word prefetchAbortHandler
|
|
||||||
.word dataAbortHandler
|
|
||||||
@@ -1,47 +1,143 @@
|
|||||||
rwildcard = $(foreach d, $(wildcard $1*), $(filter $(subst *, %, $2), $d) $(call rwildcard, $d/, $2))
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
ifeq ($(strip $(DEVKITARM)),)
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
endif
|
endif
|
||||||
|
|
||||||
include $(DEVKITARM)/base_tools
|
TOPDIR ?= $(CURDIR)
|
||||||
|
include $(DEVKITARM)/base_rules
|
||||||
|
|
||||||
name := k11_extension
|
#---------------------------------------------------------------------------------
|
||||||
|
# TARGET is the name of the output
|
||||||
|
# BUILD is the directory where object files & intermediate files will be placed
|
||||||
|
# SOURCES is a list of directories containing source code
|
||||||
|
# DATA is a list of directories containing data files
|
||||||
|
# INCLUDES is a list of directories containing header files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
TARGET := $(notdir $(CURDIR))
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source source/svc
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include include/svc
|
||||||
|
|
||||||
dir_source := source
|
#---------------------------------------------------------------------------------
|
||||||
dir_include := include
|
# options for code generation
|
||||||
dir_build := build
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -march=armv6k -mtune=mpcore -mfloat-abi=hard -mtp=soft
|
||||||
|
DEFINES := -DARM11 -D_3DS
|
||||||
|
|
||||||
ARCH := -mcpu=mpcore -mfpu=vfp
|
CFLAGS := -g -std=gnu11 -Wall -Wextra -Werror -O2 -mword-relocations \
|
||||||
ASFLAGS := $(ARCH)
|
-fomit-frame-pointer -ffunction-sections -fdata-sections \
|
||||||
CFLAGS := -Wall -Wextra -MMD -MP -marm $(ASFLAGS) -I$(dir_include) -fno-builtin -std=c11 -Wno-main -g -flto -O2 -ffast-math \
|
-Wno-main $(ARCH) $(DEFINES)
|
||||||
-mword-relocations -ffunction-sections -fdata-sections
|
|
||||||
LDFLAGS := -nostdlib -Wl,--gc-sections,--nmagic $(ARCH)
|
|
||||||
|
|
||||||
objects = $(patsubst $(dir_source)/%.s, $(dir_build)/%.o, \
|
CFLAGS += $(INCLUDE)
|
||||||
$(patsubst $(dir_source)/%.c, $(dir_build)/%.o, \
|
|
||||||
$(call rwildcard, $(dir_source), *.s *.c)))
|
|
||||||
|
|
||||||
.PHONY: all
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -std=gnu++11
|
||||||
all: ../$(dir_build)/$(name).bin
|
|
||||||
|
|
||||||
.PHONY: clean
|
ASFLAGS := -g $(ARCH)
|
||||||
|
LDFLAGS = -specs=$(TOPDIR)/linker.specs -g $(ARCH) -Wl,-Map,$(notdir $*.map)
|
||||||
|
|
||||||
|
LIBS :=
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# list of directories containing libraries, this must be the top level containing
|
||||||
|
# include and lib
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
LIBDIRS :=
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# no real need to edit anything past this point unless you need to add additional
|
||||||
|
# rules for different file extensions
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifneq ($(BUILD),$(notdir $(CURDIR)))
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OUTPUT := $(CURDIR)/$(TARGET)
|
||||||
|
export TOPDIR := $(CURDIR)
|
||||||
|
|
||||||
|
export VPATH := $(foreach dir,$(SOURCES),$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(DATA),$(CURDIR)/$(dir))
|
||||||
|
|
||||||
|
export DEPSDIR := $(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
CFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.c)))
|
||||||
|
CPPFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.cpp)))
|
||||||
|
SFILES := $(foreach dir,$(SOURCES),$(notdir $(wildcard $(dir)/*.s)))
|
||||||
|
BINFILES := $(foreach dir,$(DATA),$(notdir $(wildcard $(dir)/*.*)))
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# use CXX for linking C++ projects, CC for standard C
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ifeq ($(strip $(CPPFILES)),)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CC)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export LD := $(CXX)
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
export OFILES_BIN := $(addsuffix .o,$(BINFILES))
|
||||||
|
export OFILES_SRC := $(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
export OFILES := $(OFILES_BIN) $(OFILES_SRC)
|
||||||
|
export HFILES_BIN := $(addsuffix .h,$(subst .,_,$(BINFILES)))
|
||||||
|
|
||||||
|
export INCLUDE := $(foreach dir,$(INCLUDES),-I$(CURDIR)/$(dir)) \
|
||||||
|
$(foreach dir,$(LIBDIRS),-I$(dir)/include) \
|
||||||
|
-I$(CURDIR)/$(BUILD)
|
||||||
|
|
||||||
|
export LIBPATHS := $(foreach dir,$(LIBDIRS),-L$(dir)/lib)
|
||||||
|
|
||||||
|
.PHONY: $(BUILD) clean all
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: $(BUILD)
|
||||||
|
|
||||||
|
$(BUILD):
|
||||||
|
@[ -d $@ ] || mkdir -p $@
|
||||||
|
@$(MAKE) --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
clean:
|
clean:
|
||||||
@rm -rf $(dir_build)
|
@echo clean ...
|
||||||
|
@rm -fr $(BUILD) $(TARGET).elf
|
||||||
|
|
||||||
../$(dir_build)/$(name).bin: $(dir_build)/$(name).elf
|
|
||||||
$(OBJCOPY) -S -O binary $< $@
|
|
||||||
|
|
||||||
$(dir_build)/$(name).elf: $(objects)
|
#---------------------------------------------------------------------------------
|
||||||
$(CC) $(LDFLAGS) -T linker.ld $(OUTPUT_OPTION) $^
|
else
|
||||||
|
.PHONY: all
|
||||||
|
|
||||||
$(dir_build)/memory.o : CFLAGS += -O3 -marm
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.c
|
#---------------------------------------------------------------------------------
|
||||||
@mkdir -p "$(@D)"
|
# main targets
|
||||||
$(COMPILE.c) $(OUTPUT_OPTION) $<
|
#---------------------------------------------------------------------------------
|
||||||
|
all : $(OUTPUT).elf
|
||||||
|
|
||||||
$(dir_build)/%.o: $(dir_source)/%.s
|
$(OUTPUT).elf : $(OFILES)
|
||||||
@mkdir -p "$(@D)"
|
|
||||||
$(COMPILE.s) $(OUTPUT_OPTION) $<
|
%.elf: $(OFILES)
|
||||||
include $(call rwildcard, $(dir_build), *.d)
|
@echo linking $(notdir $@)
|
||||||
|
@$(LD) $(LDFLAGS) $(OFILES) $(LIBPATHS) $(LIBS) -o $@
|
||||||
|
@$(NM) -CSn $@ > $(notdir $*.lst)
|
||||||
|
|
||||||
|
$(OFILES_SRC) : $(HFILES_BIN)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# you need a rule like this for each extension you use as binary data
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin.o %_bin.h : %.bin
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
@echo $(notdir $<)
|
||||||
|
@$(bin2o)
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -36,7 +36,7 @@ void undefinedInstructionHandler(void);
|
|||||||
void prefetchAbortHandler(void);
|
void prefetchAbortHandler(void);
|
||||||
void dataAbortHandler(void);
|
void dataAbortHandler(void);
|
||||||
|
|
||||||
typedef struct __attribute__((packed))
|
typedef struct
|
||||||
{
|
{
|
||||||
u32 magic[2];
|
u32 magic[2];
|
||||||
u16 versionMinor, versionMajor;
|
u16 versionMinor, versionMajor;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
@@ -57,5 +57,4 @@ void SessionInfo_Add(KSession *session, const char *name);
|
|||||||
void SessionInfo_Remove(KSession *session);
|
void SessionInfo_Remove(KSession *session);
|
||||||
|
|
||||||
bool doLangEmu(Result *res, u32 *cmdbuf);
|
bool doLangEmu(Result *res, u32 *cmdbuf);
|
||||||
Result doPublishToProcessHook(Handle handle, u32 *cmdbuf);
|
|
||||||
bool doErrfThrowHook(u32 *cmdbuf);
|
bool doErrfThrowHook(u32 *cmdbuf);
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,42 +0,0 @@
|
|||||||
/*
|
|
||||||
* This file is part of Luma3DS
|
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*
|
|
||||||
* Additional Terms 7.b and 7.c of GPLv3 apply to this file:
|
|
||||||
* * Requiring preservation of specified reasonable legal notices or
|
|
||||||
* author attributions in that material or in the Appropriate Legal
|
|
||||||
* Notices displayed by works containing it.
|
|
||||||
* * Prohibiting misrepresentation of the origin of that material,
|
|
||||||
* or requiring that modified versions of such material be marked in
|
|
||||||
* reasonable ways as different from the original version.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#pragma once
|
|
||||||
|
|
||||||
#include "types.h"
|
|
||||||
|
|
||||||
void *memcpy(void *dest, const void *src, u32 size) USED;
|
|
||||||
int memcmp(const void *buf1, const void *buf2, u32 size) USED;
|
|
||||||
void *memset(void *dest, u32 value, u32 size) USED; // thanks binutils for the nice bug involving memset.
|
|
||||||
void *memset32(void *dest, u32 value, u32 size);
|
|
||||||
u8 *memsearch(u8 *startPos, const void *pattern, u32 size, u32 patternSize);
|
|
||||||
char *strcpy(char *dest, const char *src);
|
|
||||||
char *strncpy(char *dest, const char *src, u32 size);
|
|
||||||
s32 strnlen(const char *string, s32 maxlen);
|
|
||||||
s32 strlen(const char *string);
|
|
||||||
s32 strcmp(const char *str1, const char *str2);
|
|
||||||
s32 strncmp(const char *str1, const char *str2, u32 size);
|
|
||||||
void hexItoa(u64 number, char *out, u32 digits, bool uppercase);
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* This file is part of Luma3DS
|
* This file is part of Luma3DS
|
||||||
* Copyright (C) 2016-2017 Aurora Wright, TuxSH
|
* Copyright (C) 2016-2020 Aurora Wright, TuxSH
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
* it under the terms of the GNU General Public License as published by
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user