mirror of
https://github.com/d0k3/GodMode9.git
synced 2025-06-26 05:32:47 +00:00
Took over source files from Decrypt9
... this is not compilable and by no means anywhere near even a proof of concept now.
This commit is contained in:
parent
0eff8e99cf
commit
0df734a76a
6
.gitignore
vendored
6
.gitignore
vendored
@ -30,3 +30,9 @@
|
|||||||
|
|
||||||
# Debug files
|
# Debug files
|
||||||
*.dSYM/
|
*.dSYM/
|
||||||
|
|
||||||
|
# Build directories
|
||||||
|
/build
|
||||||
|
/output
|
||||||
|
/release
|
||||||
|
/zzz_backup
|
||||||
|
11
.gitmodules
vendored
Normal file
11
.gitmodules
vendored
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[submodule "CakeHax"]
|
||||||
|
path = CakeHax
|
||||||
|
url = https://github.com/mid-kid/CakeHax
|
||||||
|
[submodule "BrahmaLoader"]
|
||||||
|
path = BrahmaLoader
|
||||||
|
url = https://github.com/d0k3/BrahmaLoader
|
||||||
|
ignore = dirty
|
||||||
|
[submodule "CakesROP"]
|
||||||
|
path = CakesROP
|
||||||
|
url = https://github.com/mid-kid/CakesROP
|
||||||
|
ignore = dirty
|
41
.travis.yml
Normal file
41
.travis.yml
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
language: c
|
||||||
|
|
||||||
|
before_install:
|
||||||
|
- wget http://sourceforge.net/projects/devkitpro/files/Automated%20Installer/devkitARMupdate.pl
|
||||||
|
- export DEVKITPRO=/home/travis/devkitPro
|
||||||
|
- export DEVKITARM=${DEVKITPRO}/devkitARM
|
||||||
|
|
||||||
|
install:
|
||||||
|
- sudo perl devkitARMupdate.pl
|
||||||
|
|
||||||
|
script:
|
||||||
|
- git submodule update --init --recursive
|
||||||
|
- make gateway
|
||||||
|
- mv output/Launcher.dat .
|
||||||
|
- make clean
|
||||||
|
- make bootstrap
|
||||||
|
- mv output/Decrypt9.bin .
|
||||||
|
|
||||||
|
env:
|
||||||
|
global:
|
||||||
|
secure: "QeQ3FDs8vOcB7+TJBPIszTPo6EuYOTcqTlC15fAXTHLLnGsY36ySSMKXKq9aV5mqJr9t92WGY169fAW35vg9wwQAx09A2EIEkaqLysozkNxaR9LralgwEEAXXJP2lD5NvJ0n13PMPloGyDCnjBRUjJ+WdDz5H6F329PbItKo5uE="
|
||||||
|
|
||||||
|
after_success:
|
||||||
|
- >
|
||||||
|
if [ "$TRAVIS_BRANCH" == "master" ]; then
|
||||||
|
GITDATE="`git show -s --date=short --format='%ad' | sed 's/-//g'`"
|
||||||
|
GITREV="`git show -s --format='%h'`"
|
||||||
|
REV_NAME_GW="decrypt9-${GITDATE}-${GITREV}-browser"
|
||||||
|
REV_NAME_BS="decrypt9-${GITDATE}-${GITREV}-bootstrap"
|
||||||
|
|
||||||
|
sudo apt-get -qq install lftp p7zip-full
|
||||||
|
mkdir "$REV_NAME_GW" "$REV_NAME_BS"
|
||||||
|
|
||||||
|
cp -R README.md Launcher.dat scripts "$REV_NAME_GW"
|
||||||
|
cp -R README.md Decrypt9.bin scripts "$REV_NAME_BS"
|
||||||
|
7z a "$REV_NAME_GW" "$REV_NAME_GW/*"
|
||||||
|
7z a "$REV_NAME_BS" "$REV_NAME_BS/*"
|
||||||
|
|
||||||
|
lftp -c "open -u builds,$BUILD_PASSWORD sftp://archshift.com; put -O '/decrypt9/nightly/browser' '${REV_NAME_GW}.7z'"
|
||||||
|
lftp -c "open -u builds,$BUILD_PASSWORD sftp://archshift.com; put -O '/decrypt9/nightly/bootstrap' '${REV_NAME_BS}.7z'"
|
||||||
|
fi
|
193
Makefile
Normal file
193
Makefile
Normal file
@ -0,0 +1,193 @@
|
|||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
.SUFFIXES:
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
ifeq ($(strip $(DEVKITARM)),)
|
||||||
|
$(error "Please set DEVKITARM in your environment. export DEVKITARM=<path to>devkitARM")
|
||||||
|
endif
|
||||||
|
|
||||||
|
include $(DEVKITARM)/ds_rules
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# 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
|
||||||
|
# SPECS is the directory containing the important build and link files
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
export TARGET := GodMode9
|
||||||
|
BUILD := build
|
||||||
|
SOURCES := source source/fatfs source/fatfs/crypto source/abstraction
|
||||||
|
DATA := data
|
||||||
|
INCLUDES := include source source/fatfs source/fatfs/crypto
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# options for code generation
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
ARCH := -mthumb -mthumb-interwork
|
||||||
|
|
||||||
|
CFLAGS := -g -Wall -O2\
|
||||||
|
-march=armv5te -mtune=arm946e-s -fomit-frame-pointer\
|
||||||
|
-ffast-math -std=c99\
|
||||||
|
$(ARCH)
|
||||||
|
|
||||||
|
CFLAGS += $(INCLUDE) -DEXEC_$(EXEC_METHOD) -DARM9
|
||||||
|
|
||||||
|
CFLAGS += -DBUILD_NAME="\"$(TARGET) (`date +'%Y/%m/%d'`)\""
|
||||||
|
|
||||||
|
ifneq ($(strip $(THEME)),)
|
||||||
|
CFLAGS += -DUSE_THEME=\"\/$(THEME)\"
|
||||||
|
endif
|
||||||
|
|
||||||
|
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
|
||||||
|
|
||||||
|
ASFLAGS := -g $(ARCH) -DEXEC_$(EXEC_METHOD)
|
||||||
|
LDFLAGS = -nostartfiles -g $(ARCH) -Wl,-Map,$(TARGET).map
|
||||||
|
|
||||||
|
ifeq ($(EXEC_METHOD),GATEWAY)
|
||||||
|
LDFLAGS += --specs=../gateway.specs
|
||||||
|
else ifeq ($(EXEC_METHOD),BOOTSTRAP)
|
||||||
|
LDFLAGS += --specs=../bootstrap.specs
|
||||||
|
endif
|
||||||
|
|
||||||
|
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_D := $(CURDIR)/output
|
||||||
|
export OUTPUT := $(OUTPUT_D)/$(TARGET)
|
||||||
|
export RELEASE := $(CURDIR)/release
|
||||||
|
|
||||||
|
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 := $(addsuffix .o,$(BINFILES)) \
|
||||||
|
$(CPPFILES:.cpp=.o) $(CFILES:.c=.o) $(SFILES:.s=.o)
|
||||||
|
|
||||||
|
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: common clean all gateway bootstrap cakehax cakerop brahma release
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
all: brahma
|
||||||
|
|
||||||
|
common:
|
||||||
|
@[ -d $(OUTPUT_D) ] || mkdir -p $(OUTPUT_D)
|
||||||
|
@[ -d $(BUILD) ] || mkdir -p $(BUILD)
|
||||||
|
|
||||||
|
submodules:
|
||||||
|
@-git submodule update --init --recursive
|
||||||
|
|
||||||
|
gateway: common
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=GATEWAY
|
||||||
|
@cp resources/LauncherTemplate.dat $(OUTPUT_D)/Launcher.dat
|
||||||
|
@dd if=$(OUTPUT).bin of=$(OUTPUT_D)/Launcher.dat bs=1497296 seek=1 conv=notrunc
|
||||||
|
|
||||||
|
bootstrap: common
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=BOOTSTRAP
|
||||||
|
|
||||||
|
cakehax: submodules common
|
||||||
|
@make --no-print-directory -C $(BUILD) -f $(CURDIR)/Makefile EXEC_METHOD=GATEWAY
|
||||||
|
@make dir_out=$(OUTPUT_D) name=$(TARGET).dat -C CakeHax bigpayload
|
||||||
|
@dd if=$(OUTPUT).bin of=$(OUTPUT).dat bs=512 seek=160
|
||||||
|
|
||||||
|
cakerop: cakehax
|
||||||
|
@make DATNAME=$(TARGET).dat DISPNAME=$(TARGET) GRAPHICS=../resources/CakesROP -C CakesROP
|
||||||
|
@mv CakesROP/CakesROP.nds $(OUTPUT_D)/$(TARGET).nds
|
||||||
|
|
||||||
|
brahma: submodules bootstrap
|
||||||
|
@[ -d BrahmaLoader/data ] || mkdir -p BrahmaLoader/data
|
||||||
|
@cp $(OUTPUT).bin BrahmaLoader/data/payload.bin
|
||||||
|
@cp resources/BrahmaAppInfo BrahmaLoader/resources/AppInfo
|
||||||
|
@cp resources/BrahmaIcon.png BrahmaLoader/resources/icon.png
|
||||||
|
@make --no-print-directory -C BrahmaLoader APP_TITLE=$(TARGET)
|
||||||
|
@mv BrahmaLoader/output/*.3dsx $(OUTPUT_D)
|
||||||
|
@mv BrahmaLoader/output/*.smdh $(OUTPUT_D)
|
||||||
|
|
||||||
|
release:
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT_D) $(RELEASE)
|
||||||
|
@make --no-print-directory gateway
|
||||||
|
@-make --no-print-directory cakerop
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT).bin $(OUTPUT).elf $(CURDIR)/$(LOADER)/data
|
||||||
|
@-make --no-print-directory brahma
|
||||||
|
@[ -d $(RELEASE) ] || mkdir -p $(RELEASE)
|
||||||
|
@[ -d $(RELEASE)/$(TARGET) ] || mkdir -p $(RELEASE)/$(TARGET)
|
||||||
|
@cp $(OUTPUT_D)/Launcher.dat $(RELEASE)
|
||||||
|
@-cp $(OUTPUT).bin $(RELEASE)
|
||||||
|
@-cp $(OUTPUT).dat $(RELEASE)
|
||||||
|
@-cp $(OUTPUT).nds $(RELEASE)
|
||||||
|
@-cp $(OUTPUT).3dsx $(RELEASE)/$(TARGET)
|
||||||
|
@-cp $(OUTPUT).smdh $(RELEASE)/$(TARGET)
|
||||||
|
@cp $(CURDIR)/README.md $(RELEASE)
|
||||||
|
@-7z a $(RELEASE)/$(TARGET)-`date +'%Y%m%d-%H%M%S'`.zip $(RELEASE)/*
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
clean:
|
||||||
|
@echo clean ...
|
||||||
|
@-make clean --no-print-directory -C CakeHax
|
||||||
|
@-make clean --no-print-directory -C CakesROP
|
||||||
|
@-make clean --no-print-directory -C BrahmaLoader
|
||||||
|
@rm -fr $(BUILD) $(OUTPUT_D) $(RELEASE)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
else
|
||||||
|
|
||||||
|
DEPENDS := $(OFILES:.o=.d)
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
# main targets
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
$(OUTPUT).bin : $(OUTPUT).elf
|
||||||
|
$(OUTPUT).elf : $(OFILES)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------
|
||||||
|
%.bin: %.elf
|
||||||
|
@$(OBJCOPY) --set-section-flags .bss=alloc,load,contents -O binary $< $@
|
||||||
|
@echo built ... $(notdir $@)
|
||||||
|
|
||||||
|
|
||||||
|
-include $(DEPENDS)
|
||||||
|
|
||||||
|
|
||||||
|
#---------------------------------------------------------------------------------------
|
||||||
|
endif
|
||||||
|
#---------------------------------------------------------------------------------------
|
130
bootstrap.ld
Normal file
130
bootstrap.ld
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ram : ORIGIN = 0x23F00000, LENGTH = 128K
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
__text_start = . ;
|
||||||
|
KEEP (*(.init))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
.plt : { *(.plt) } >ram = 0xff
|
||||||
|
|
||||||
|
.text : /* ALIGN (4): */
|
||||||
|
{
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
KEEP (*(.text.*personality*))
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(.fini))
|
||||||
|
} >ram =0xff
|
||||||
|
|
||||||
|
__text_end = . ;
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
*all.rodata*(*)
|
||||||
|
*(.roda)
|
||||||
|
*(.rodata.*)
|
||||||
|
*(.gnu.linkonce.r*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ram
|
||||||
|
__exidx_start = .;
|
||||||
|
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ram
|
||||||
|
__exidx_end = .;
|
||||||
|
|
||||||
|
/* Ensure the __preinit_array_start label is properly aligned. We
|
||||||
|
could instead move the label definition inside the section, but
|
||||||
|
the linker would then create the section even if it turns out to
|
||||||
|
be empty, which isn't pretty. */
|
||||||
|
. = ALIGN(32 / 8);
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
.preinit_array : { KEEP (*(.preinit_array)) } >ram = 0xff
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
.init_array : { KEEP (*(.init_array)) } >ram = 0xff
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
.fini_array : { KEEP (*(.fini_array)) } >ram = 0xff
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of the constructors, so
|
||||||
|
we make sure it is first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not actually link against
|
||||||
|
crtbegin.o; the linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it doesn't matter which
|
||||||
|
directory crtbegin.o is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.eh_frame :
|
||||||
|
{
|
||||||
|
KEEP (*(.eh_frame))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.gcc_except_table :
|
||||||
|
{
|
||||||
|
*(.gcc_except_table)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
.jcr : { KEEP (*(.jcr)) } >ram = 0
|
||||||
|
.got : { *(.got.plt) *(.got) } >ram = 0
|
||||||
|
|
||||||
|
.data ALIGN(4) : {
|
||||||
|
__data_start = ABSOLUTE(.);
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
*(.gnu.linkonce.d*)
|
||||||
|
CONSTRUCTORS
|
||||||
|
. = ALIGN(4);
|
||||||
|
__data_end = ABSOLUTE(.) ;
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.bss ALIGN(4) :
|
||||||
|
{
|
||||||
|
__bss_start = ABSOLUTE(.);
|
||||||
|
__bss_start__ = ABSOLUTE(.);
|
||||||
|
*(.dynbss)
|
||||||
|
*(.gnu.linkonce.b*)
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
__bss_end__ = ABSOLUTE(.);
|
||||||
|
__end__ = ABSOLUTE(.);
|
||||||
|
} >ram
|
||||||
|
|
||||||
|
.stack 0x80000 : { _stack = .; *(.stack) }
|
||||||
|
}
|
5
bootstrap.specs
Normal file
5
bootstrap.specs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T ../bootstrap.ld%s
|
||||||
|
|
130
gateway.ld
Normal file
130
gateway.ld
Normal file
@ -0,0 +1,130 @@
|
|||||||
|
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||||
|
OUTPUT_ARCH(arm)
|
||||||
|
ENTRY(_start)
|
||||||
|
|
||||||
|
MEMORY
|
||||||
|
{
|
||||||
|
ram : ORIGIN = 0x08000000, LENGTH = 128K
|
||||||
|
}
|
||||||
|
|
||||||
|
SECTIONS
|
||||||
|
{
|
||||||
|
.init :
|
||||||
|
{
|
||||||
|
__text_start = . ;
|
||||||
|
KEEP (*(.init))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
.plt : { *(.plt) } >ram = 0xff
|
||||||
|
|
||||||
|
.text : /* ALIGN (4): */
|
||||||
|
{
|
||||||
|
*(.text .stub .text.* .gnu.linkonce.t.*)
|
||||||
|
KEEP (*(.text.*personality*))
|
||||||
|
/* .gnu.warning sections are handled specially by elf32.em. */
|
||||||
|
*(.gnu.warning)
|
||||||
|
*(.glue_7t) *(.glue_7) *(.vfp11_veneer)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.fini :
|
||||||
|
{
|
||||||
|
KEEP (*(.fini))
|
||||||
|
} >ram =0xff
|
||||||
|
|
||||||
|
__text_end = . ;
|
||||||
|
|
||||||
|
.rodata :
|
||||||
|
{
|
||||||
|
*(.rodata)
|
||||||
|
*all.rodata*(*)
|
||||||
|
*(.roda)
|
||||||
|
*(.rodata.*)
|
||||||
|
*(.gnu.linkonce.r*)
|
||||||
|
SORT(CONSTRUCTORS)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >ram
|
||||||
|
__exidx_start = .;
|
||||||
|
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >ram
|
||||||
|
__exidx_end = .;
|
||||||
|
|
||||||
|
/* Ensure the __preinit_array_start label is properly aligned. We
|
||||||
|
could instead move the label definition inside the section, but
|
||||||
|
the linker would then create the section even if it turns out to
|
||||||
|
be empty, which isn't pretty. */
|
||||||
|
. = ALIGN(32 / 8);
|
||||||
|
PROVIDE (__preinit_array_start = .);
|
||||||
|
.preinit_array : { KEEP (*(.preinit_array)) } >ram = 0xff
|
||||||
|
PROVIDE (__preinit_array_end = .);
|
||||||
|
PROVIDE (__init_array_start = .);
|
||||||
|
.init_array : { KEEP (*(.init_array)) } >ram = 0xff
|
||||||
|
PROVIDE (__init_array_end = .);
|
||||||
|
PROVIDE (__fini_array_start = .);
|
||||||
|
.fini_array : { KEEP (*(.fini_array)) } >ram = 0xff
|
||||||
|
PROVIDE (__fini_array_end = .);
|
||||||
|
|
||||||
|
.ctors :
|
||||||
|
{
|
||||||
|
/* gcc uses crtbegin.o to find the start of the constructors, so
|
||||||
|
we make sure it is first. Because this is a wildcard, it
|
||||||
|
doesn't matter if the user does not actually link against
|
||||||
|
crtbegin.o; the linker won't look for a file to match a
|
||||||
|
wildcard. The wildcard also means that it doesn't matter which
|
||||||
|
directory crtbegin.o is in. */
|
||||||
|
KEEP (*crtbegin.o(.ctors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .ctors))
|
||||||
|
KEEP (*(SORT(.ctors.*)))
|
||||||
|
KEEP (*(.ctors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.dtors :
|
||||||
|
{
|
||||||
|
KEEP (*crtbegin.o(.dtors))
|
||||||
|
KEEP (*(EXCLUDE_FILE (*crtend.o) .dtors))
|
||||||
|
KEEP (*(SORT(.dtors.*)))
|
||||||
|
KEEP (*(.dtors))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.eh_frame :
|
||||||
|
{
|
||||||
|
KEEP (*(.eh_frame))
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.gcc_except_table :
|
||||||
|
{
|
||||||
|
*(.gcc_except_table)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
} >ram = 0xff
|
||||||
|
.jcr : { KEEP (*(.jcr)) } >ram = 0
|
||||||
|
.got : { *(.got.plt) *(.got) } >ram = 0
|
||||||
|
|
||||||
|
.data ALIGN(4) : {
|
||||||
|
__data_start = ABSOLUTE(.);
|
||||||
|
*(.data)
|
||||||
|
*(.data.*)
|
||||||
|
*(.gnu.linkonce.d*)
|
||||||
|
CONSTRUCTORS
|
||||||
|
. = ALIGN(4);
|
||||||
|
__data_end = ABSOLUTE(.) ;
|
||||||
|
} >ram = 0xff
|
||||||
|
|
||||||
|
.bss ALIGN(4) :
|
||||||
|
{
|
||||||
|
__bss_start = ABSOLUTE(.);
|
||||||
|
__bss_start__ = ABSOLUTE(.);
|
||||||
|
*(.dynbss)
|
||||||
|
*(.gnu.linkonce.b*)
|
||||||
|
*(.bss*)
|
||||||
|
*(COMMON)
|
||||||
|
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
|
||||||
|
__bss_end__ = ABSOLUTE(.);
|
||||||
|
__end__ = ABSOLUTE(.);
|
||||||
|
} >ram
|
||||||
|
|
||||||
|
.stack 0x80000 : { _stack = .; *(.stack) }
|
||||||
|
}
|
5
gateway.specs
Normal file
5
gateway.specs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
%rename link old_link
|
||||||
|
|
||||||
|
*link:
|
||||||
|
%(old_link) -T ../gateway.ld%s
|
||||||
|
|
339
license.txt
Normal file
339
license.txt
Normal file
@ -0,0 +1,339 @@
|
|||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
Version 2, June 1991
|
||||||
|
|
||||||
|
Copyright (C) 1989, 1991 Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
||||||
|
Everyone is permitted to copy and distribute verbatim copies
|
||||||
|
of this license document, but changing it is not allowed.
|
||||||
|
|
||||||
|
Preamble
|
||||||
|
|
||||||
|
The licenses for most software are designed to take away your
|
||||||
|
freedom to share and change it. By contrast, the GNU General Public
|
||||||
|
License is intended to guarantee your freedom to share and change free
|
||||||
|
software--to make sure the software is free for all its users. This
|
||||||
|
General Public License applies to most of the Free Software
|
||||||
|
Foundation's software and to any other program whose authors commit to
|
||||||
|
using it. (Some other Free Software Foundation software is covered by
|
||||||
|
the GNU Lesser General Public License instead.) You can apply it to
|
||||||
|
your programs, too.
|
||||||
|
|
||||||
|
When we speak of free software, we are referring to freedom, not
|
||||||
|
price. Our General Public Licenses are designed to make sure that you
|
||||||
|
have the freedom to distribute copies of free software (and charge for
|
||||||
|
this service if you wish), that you receive source code or can get it
|
||||||
|
if you want it, that you can change the software or use pieces of it
|
||||||
|
in new free programs; and that you know you can do these things.
|
||||||
|
|
||||||
|
To protect your rights, we need to make restrictions that forbid
|
||||||
|
anyone to deny you these rights or to ask you to surrender the rights.
|
||||||
|
These restrictions translate to certain responsibilities for you if you
|
||||||
|
distribute copies of the software, or if you modify it.
|
||||||
|
|
||||||
|
For example, if you distribute copies of such a program, whether
|
||||||
|
gratis or for a fee, you must give the recipients all the rights that
|
||||||
|
you have. You must make sure that they, too, receive or can get the
|
||||||
|
source code. And you must show them these terms so they know their
|
||||||
|
rights.
|
||||||
|
|
||||||
|
We protect your rights with two steps: (1) copyright the software, and
|
||||||
|
(2) offer you this license which gives you legal permission to copy,
|
||||||
|
distribute and/or modify the software.
|
||||||
|
|
||||||
|
Also, for each author's protection and ours, we want to make certain
|
||||||
|
that everyone understands that there is no warranty for this free
|
||||||
|
software. If the software is modified by someone else and passed on, we
|
||||||
|
want its recipients to know that what they have is not the original, so
|
||||||
|
that any problems introduced by others will not reflect on the original
|
||||||
|
authors' reputations.
|
||||||
|
|
||||||
|
Finally, any free program is threatened constantly by software
|
||||||
|
patents. We wish to avoid the danger that redistributors of a free
|
||||||
|
program will individually obtain patent licenses, in effect making the
|
||||||
|
program proprietary. To prevent this, we have made it clear that any
|
||||||
|
patent must be licensed for everyone's free use or not licensed at all.
|
||||||
|
|
||||||
|
The precise terms and conditions for copying, distribution and
|
||||||
|
modification follow.
|
||||||
|
|
||||||
|
GNU GENERAL PUBLIC LICENSE
|
||||||
|
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||||
|
|
||||||
|
0. This License applies to any program or other work which contains
|
||||||
|
a notice placed by the copyright holder saying it may be distributed
|
||||||
|
under the terms of this General Public License. The "Program", below,
|
||||||
|
refers to any such program or work, and a "work based on the Program"
|
||||||
|
means either the Program or any derivative work under copyright law:
|
||||||
|
that is to say, a work containing the Program or a portion of it,
|
||||||
|
either verbatim or with modifications and/or translated into another
|
||||||
|
language. (Hereinafter, translation is included without limitation in
|
||||||
|
the term "modification".) Each licensee is addressed as "you".
|
||||||
|
|
||||||
|
Activities other than copying, distribution and modification are not
|
||||||
|
covered by this License; they are outside its scope. The act of
|
||||||
|
running the Program is not restricted, and the output from the Program
|
||||||
|
is covered only if its contents constitute a work based on the
|
||||||
|
Program (independent of having been made by running the Program).
|
||||||
|
Whether that is true depends on what the Program does.
|
||||||
|
|
||||||
|
1. You may copy and distribute verbatim copies of the Program's
|
||||||
|
source code as you receive it, in any medium, provided that you
|
||||||
|
conspicuously and appropriately publish on each copy an appropriate
|
||||||
|
copyright notice and disclaimer of warranty; keep intact all the
|
||||||
|
notices that refer to this License and to the absence of any warranty;
|
||||||
|
and give any other recipients of the Program a copy of this License
|
||||||
|
along with the Program.
|
||||||
|
|
||||||
|
You may charge a fee for the physical act of transferring a copy, and
|
||||||
|
you may at your option offer warranty protection in exchange for a fee.
|
||||||
|
|
||||||
|
2. You may modify your copy or copies of the Program or any portion
|
||||||
|
of it, thus forming a work based on the Program, and copy and
|
||||||
|
distribute such modifications or work under the terms of Section 1
|
||||||
|
above, provided that you also meet all of these conditions:
|
||||||
|
|
||||||
|
a) You must cause the modified files to carry prominent notices
|
||||||
|
stating that you changed the files and the date of any change.
|
||||||
|
|
||||||
|
b) You must cause any work that you distribute or publish, that in
|
||||||
|
whole or in part contains or is derived from the Program or any
|
||||||
|
part thereof, to be licensed as a whole at no charge to all third
|
||||||
|
parties under the terms of this License.
|
||||||
|
|
||||||
|
c) If the modified program normally reads commands interactively
|
||||||
|
when run, you must cause it, when started running for such
|
||||||
|
interactive use in the most ordinary way, to print or display an
|
||||||
|
announcement including an appropriate copyright notice and a
|
||||||
|
notice that there is no warranty (or else, saying that you provide
|
||||||
|
a warranty) and that users may redistribute the program under
|
||||||
|
these conditions, and telling the user how to view a copy of this
|
||||||
|
License. (Exception: if the Program itself is interactive but
|
||||||
|
does not normally print such an announcement, your work based on
|
||||||
|
the Program is not required to print an announcement.)
|
||||||
|
|
||||||
|
These requirements apply to the modified work as a whole. If
|
||||||
|
identifiable sections of that work are not derived from the Program,
|
||||||
|
and can be reasonably considered independent and separate works in
|
||||||
|
themselves, then this License, and its terms, do not apply to those
|
||||||
|
sections when you distribute them as separate works. But when you
|
||||||
|
distribute the same sections as part of a whole which is a work based
|
||||||
|
on the Program, the distribution of the whole must be on the terms of
|
||||||
|
this License, whose permissions for other licensees extend to the
|
||||||
|
entire whole, and thus to each and every part regardless of who wrote it.
|
||||||
|
|
||||||
|
Thus, it is not the intent of this section to claim rights or contest
|
||||||
|
your rights to work written entirely by you; rather, the intent is to
|
||||||
|
exercise the right to control the distribution of derivative or
|
||||||
|
collective works based on the Program.
|
||||||
|
|
||||||
|
In addition, mere aggregation of another work not based on the Program
|
||||||
|
with the Program (or with a work based on the Program) on a volume of
|
||||||
|
a storage or distribution medium does not bring the other work under
|
||||||
|
the scope of this License.
|
||||||
|
|
||||||
|
3. You may copy and distribute the Program (or a work based on it,
|
||||||
|
under Section 2) in object code or executable form under the terms of
|
||||||
|
Sections 1 and 2 above provided that you also do one of the following:
|
||||||
|
|
||||||
|
a) Accompany it with the complete corresponding machine-readable
|
||||||
|
source code, which must be distributed under the terms of Sections
|
||||||
|
1 and 2 above on a medium customarily used for software interchange; or,
|
||||||
|
|
||||||
|
b) Accompany it with a written offer, valid for at least three
|
||||||
|
years, to give any third party, for a charge no more than your
|
||||||
|
cost of physically performing source distribution, a complete
|
||||||
|
machine-readable copy of the corresponding source code, to be
|
||||||
|
distributed under the terms of Sections 1 and 2 above on a medium
|
||||||
|
customarily used for software interchange; or,
|
||||||
|
|
||||||
|
c) Accompany it with the information you received as to the offer
|
||||||
|
to distribute corresponding source code. (This alternative is
|
||||||
|
allowed only for noncommercial distribution and only if you
|
||||||
|
received the program in object code or executable form with such
|
||||||
|
an offer, in accord with Subsection b above.)
|
||||||
|
|
||||||
|
The source code for a work means the preferred form of the work for
|
||||||
|
making modifications to it. For an executable work, complete source
|
||||||
|
code means all the source code for all modules it contains, plus any
|
||||||
|
associated interface definition files, plus the scripts used to
|
||||||
|
control compilation and installation of the executable. However, as a
|
||||||
|
special exception, the source code distributed need not include
|
||||||
|
anything that is normally distributed (in either source or binary
|
||||||
|
form) with the major components (compiler, kernel, and so on) of the
|
||||||
|
operating system on which the executable runs, unless that component
|
||||||
|
itself accompanies the executable.
|
||||||
|
|
||||||
|
If distribution of executable or object code is made by offering
|
||||||
|
access to copy from a designated place, then offering equivalent
|
||||||
|
access to copy the source code from the same place counts as
|
||||||
|
distribution of the source code, even though third parties are not
|
||||||
|
compelled to copy the source along with the object code.
|
||||||
|
|
||||||
|
4. You may not copy, modify, sublicense, or distribute the Program
|
||||||
|
except as expressly provided under this License. Any attempt
|
||||||
|
otherwise to copy, modify, sublicense or distribute the Program is
|
||||||
|
void, and will automatically terminate your rights under this License.
|
||||||
|
However, parties who have received copies, or rights, from you under
|
||||||
|
this License will not have their licenses terminated so long as such
|
||||||
|
parties remain in full compliance.
|
||||||
|
|
||||||
|
5. You are not required to accept this License, since you have not
|
||||||
|
signed it. However, nothing else grants you permission to modify or
|
||||||
|
distribute the Program or its derivative works. These actions are
|
||||||
|
prohibited by law if you do not accept this License. Therefore, by
|
||||||
|
modifying or distributing the Program (or any work based on the
|
||||||
|
Program), you indicate your acceptance of this License to do so, and
|
||||||
|
all its terms and conditions for copying, distributing or modifying
|
||||||
|
the Program or works based on it.
|
||||||
|
|
||||||
|
6. Each time you redistribute the Program (or any work based on the
|
||||||
|
Program), the recipient automatically receives a license from the
|
||||||
|
original licensor to copy, distribute or modify the Program subject to
|
||||||
|
these terms and conditions. You may not impose any further
|
||||||
|
restrictions on the recipients' exercise of the rights granted herein.
|
||||||
|
You are not responsible for enforcing compliance by third parties to
|
||||||
|
this License.
|
||||||
|
|
||||||
|
7. If, as a consequence of a court judgment or allegation of patent
|
||||||
|
infringement or for any other reason (not limited to patent issues),
|
||||||
|
conditions are imposed on you (whether by court order, agreement or
|
||||||
|
otherwise) that contradict the conditions of this License, they do not
|
||||||
|
excuse you from the conditions of this License. If you cannot
|
||||||
|
distribute so as to satisfy simultaneously your obligations under this
|
||||||
|
License and any other pertinent obligations, then as a consequence you
|
||||||
|
may not distribute the Program at all. For example, if a patent
|
||||||
|
license would not permit royalty-free redistribution of the Program by
|
||||||
|
all those who receive copies directly or indirectly through you, then
|
||||||
|
the only way you could satisfy both it and this License would be to
|
||||||
|
refrain entirely from distribution of the Program.
|
||||||
|
|
||||||
|
If any portion of this section is held invalid or unenforceable under
|
||||||
|
any particular circumstance, the balance of the section is intended to
|
||||||
|
apply and the section as a whole is intended to apply in other
|
||||||
|
circumstances.
|
||||||
|
|
||||||
|
It is not the purpose of this section to induce you to infringe any
|
||||||
|
patents or other property right claims or to contest validity of any
|
||||||
|
such claims; this section has the sole purpose of protecting the
|
||||||
|
integrity of the free software distribution system, which is
|
||||||
|
implemented by public license practices. Many people have made
|
||||||
|
generous contributions to the wide range of software distributed
|
||||||
|
through that system in reliance on consistent application of that
|
||||||
|
system; it is up to the author/donor to decide if he or she is willing
|
||||||
|
to distribute software through any other system and a licensee cannot
|
||||||
|
impose that choice.
|
||||||
|
|
||||||
|
This section is intended to make thoroughly clear what is believed to
|
||||||
|
be a consequence of the rest of this License.
|
||||||
|
|
||||||
|
8. If the distribution and/or use of the Program is restricted in
|
||||||
|
certain countries either by patents or by copyrighted interfaces, the
|
||||||
|
original copyright holder who places the Program under this License
|
||||||
|
may add an explicit geographical distribution limitation excluding
|
||||||
|
those countries, so that distribution is permitted only in or among
|
||||||
|
countries not thus excluded. In such case, this License incorporates
|
||||||
|
the limitation as if written in the body of this License.
|
||||||
|
|
||||||
|
9. The Free Software Foundation may publish revised and/or new versions
|
||||||
|
of the General Public License from time to time. Such new versions will
|
||||||
|
be similar in spirit to the present version, but may differ in detail to
|
||||||
|
address new problems or concerns.
|
||||||
|
|
||||||
|
Each version is given a distinguishing version number. If the Program
|
||||||
|
specifies a version number of this License which applies to it and "any
|
||||||
|
later version", you have the option of following the terms and conditions
|
||||||
|
either of that version or of any later version published by the Free
|
||||||
|
Software Foundation. If the Program does not specify a version number of
|
||||||
|
this License, you may choose any version ever published by the Free Software
|
||||||
|
Foundation.
|
||||||
|
|
||||||
|
10. If you wish to incorporate parts of the Program into other free
|
||||||
|
programs whose distribution conditions are different, write to the author
|
||||||
|
to ask for permission. For software which is copyrighted by the Free
|
||||||
|
Software Foundation, write to the Free Software Foundation; we sometimes
|
||||||
|
make exceptions for this. Our decision will be guided by the two goals
|
||||||
|
of preserving the free status of all derivatives of our free software and
|
||||||
|
of promoting the sharing and reuse of software generally.
|
||||||
|
|
||||||
|
NO WARRANTY
|
||||||
|
|
||||||
|
11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY
|
||||||
|
FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN
|
||||||
|
OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES
|
||||||
|
PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED
|
||||||
|
OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
||||||
|
MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS
|
||||||
|
TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE
|
||||||
|
PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,
|
||||||
|
REPAIR OR CORRECTION.
|
||||||
|
|
||||||
|
12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
|
||||||
|
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR
|
||||||
|
REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,
|
||||||
|
INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING
|
||||||
|
OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED
|
||||||
|
TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY
|
||||||
|
YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER
|
||||||
|
PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE
|
||||||
|
POSSIBILITY OF SUCH DAMAGES.
|
||||||
|
|
||||||
|
END OF TERMS AND CONDITIONS
|
||||||
|
|
||||||
|
How to Apply These Terms to Your New Programs
|
||||||
|
|
||||||
|
If you develop a new program, and you want it to be of the greatest
|
||||||
|
possible use to the public, the best way to achieve this is to make it
|
||||||
|
free software which everyone can redistribute and change under these terms.
|
||||||
|
|
||||||
|
To do so, attach the following notices to the program. It is safest
|
||||||
|
to attach them to the start of each source file to most effectively
|
||||||
|
convey the exclusion of warranty; and each file should have at least
|
||||||
|
the "copyright" line and a pointer to where the full notice is found.
|
||||||
|
|
||||||
|
<one line to give the program's name and a brief idea of what it does.>
|
||||||
|
Copyright (C) <year> <name of author>
|
||||||
|
|
||||||
|
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 2 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, write to the Free Software Foundation, Inc.,
|
||||||
|
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||||
|
|
||||||
|
Also add information on how to contact you by electronic and paper mail.
|
||||||
|
|
||||||
|
If the program is interactive, make it output a short notice like this
|
||||||
|
when it starts in an interactive mode:
|
||||||
|
|
||||||
|
Gnomovision version 69, Copyright (C) year name of author
|
||||||
|
Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
|
||||||
|
This is free software, and you are welcome to redistribute it
|
||||||
|
under certain conditions; type `show c' for details.
|
||||||
|
|
||||||
|
The hypothetical commands `show w' and `show c' should show the appropriate
|
||||||
|
parts of the General Public License. Of course, the commands you use may
|
||||||
|
be called something other than `show w' and `show c'; they could even be
|
||||||
|
mouse-clicks or menu items--whatever suits your program.
|
||||||
|
|
||||||
|
You should also get your employer (if you work as a programmer) or your
|
||||||
|
school, if any, to sign a "copyright disclaimer" for the program, if
|
||||||
|
necessary. Here is a sample; alter the names:
|
||||||
|
|
||||||
|
Yoyodyne, Inc., hereby disclaims all copyright interest in the program
|
||||||
|
`Gnomovision' (which makes passes at compilers) written by James Hacker.
|
||||||
|
|
||||||
|
<signature of Ty Coon>, 1 April 1989
|
||||||
|
Ty Coon, President of Vice
|
||||||
|
|
||||||
|
This General Public License does not permit incorporating your program into
|
||||||
|
proprietary programs. If your program is a subroutine library, you may
|
||||||
|
consider it more useful to permit linking proprietary applications with the
|
||||||
|
library. If this is what you want to do, use the GNU Lesser General
|
||||||
|
Public License instead of this License.
|
6
resources/BrahmaAppInfo
Normal file
6
resources/BrahmaAppInfo
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
APP_TITLE = GodMode9
|
||||||
|
APP_DESCRIPTION = Open source 3DS all access file browser
|
||||||
|
APP_AUTHOR = d0k3
|
||||||
|
|
||||||
|
PAYLOAD_MEM = 1
|
||||||
|
VOODOO = 0xF
|
BIN
resources/BrahmaIcon.png
Normal file
BIN
resources/BrahmaIcon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.0 KiB |
11
resources/CakesROP/drunkenlogo.grit
Normal file
11
resources/CakesROP/drunkenlogo.grit
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
-W3
|
||||||
|
# disable alpha and set opaque bit for all pixels
|
||||||
|
-gT!
|
||||||
|
|
||||||
|
# use lz77 compression
|
||||||
|
-gzl
|
||||||
|
|
||||||
|
# 16 bit bitmap
|
||||||
|
-gB16
|
||||||
|
|
||||||
|
-gb
|
BIN
resources/CakesROP/drunkenlogo.png
Normal file
BIN
resources/CakesROP/drunkenlogo.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
BIN
resources/LauncherTemplate.dat
Normal file
BIN
resources/LauncherTemplate.dat
Normal file
Binary file not shown.
106
source/abstraction/bs-start.s
Normal file
106
source/abstraction/bs-start.s
Normal file
@ -0,0 +1,106 @@
|
|||||||
|
#ifdef EXEC_BOOTSTRAP
|
||||||
|
|
||||||
|
.section ".init"
|
||||||
|
.global _start
|
||||||
|
.extern main
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
|
||||||
|
#define SIZE_32KB 0b01110
|
||||||
|
#define SIZE_128KB 0b10000
|
||||||
|
#define SIZE_512KB 0b10010
|
||||||
|
#define SIZE_2MB 0b10100
|
||||||
|
#define SIZE_128MB 0b11010
|
||||||
|
#define SIZE_256MB 0b11011
|
||||||
|
#define SIZE_4GB 0b11111
|
||||||
|
|
||||||
|
@ Makes a MPU partition value
|
||||||
|
#define MAKE_PARTITION(offset, size_enum) \
|
||||||
|
(((offset) >> 12 << 12) | ((size_enum) << 1) | 1)
|
||||||
|
|
||||||
|
|
||||||
|
_start:
|
||||||
|
b _init
|
||||||
|
|
||||||
|
@ required, don't move :)
|
||||||
|
@ will be set to FIRM ARM9 entry point by BRAHMA
|
||||||
|
arm9ep_backup: .long 0xFFFF0000
|
||||||
|
|
||||||
|
_mpu_partition_table:
|
||||||
|
.word MAKE_PARTITION(0x00000000, SIZE_4GB) @ 0: Background region
|
||||||
|
.word MAKE_PARTITION(0x00000000, SIZE_128MB) @ 1: Instruction TCM (mirrored every 32KB)
|
||||||
|
.word MAKE_PARTITION(0x08000000, SIZE_2MB) @ 2: ARM9 internal memory
|
||||||
|
.word MAKE_PARTITION(0x10000000, SIZE_128MB) @ 3: IO region
|
||||||
|
.word MAKE_PARTITION(0x18000000, SIZE_128MB) @ 4: external device memory
|
||||||
|
.word MAKE_PARTITION(0x1FF80000, SIZE_512KB) @ 5: AXI WRAM
|
||||||
|
.word MAKE_PARTITION(0x20000000, SIZE_256MB) @ 6: FCRAM
|
||||||
|
.word 0 @ 7: Unused
|
||||||
|
|
||||||
|
_populate_mpu:
|
||||||
|
push {r4-r5, lr}
|
||||||
|
ldr r4, =_mpu_partition_table
|
||||||
|
|
||||||
|
ldr r5, [r4, #0x0] @ mmu_partition_table[0] load
|
||||||
|
mcr p15, 0, r5, c6, c0, 0 @ mmu_partition_table[0] write
|
||||||
|
ldr r5, [r4, #0x4]
|
||||||
|
mcr p15, 0, r5, c6, c1, 0
|
||||||
|
ldr r5, [r4, #0x8]
|
||||||
|
mcr p15, 0, r5, c6, c2, 0
|
||||||
|
ldr r5, [r4, #0xC]
|
||||||
|
mcr p15, 0, r5, c6, c3, 0
|
||||||
|
ldr r5, [r4, #0x10]
|
||||||
|
mcr p15, 0, r5, c6, c4, 0
|
||||||
|
ldr r5, [r4, #0x14]
|
||||||
|
mcr p15, 0, r5, c6, c5, 0
|
||||||
|
ldr r5, [r4, #0x18]
|
||||||
|
mcr p15, 0, r5, c6, c6, 0
|
||||||
|
ldr r5, [r4, #0x1C]
|
||||||
|
mcr p15, 0, r5, c6, c7, 0
|
||||||
|
|
||||||
|
@ Give read/write access to all the memory regions
|
||||||
|
ldr r5, =0x03333333
|
||||||
|
mcr p15, 0, r5, c5, c0, 2 @ data access
|
||||||
|
ldr r5, =0x03300330
|
||||||
|
mcr p15, 0, r5, c5, c0, 3 @ instruction access
|
||||||
|
|
||||||
|
mov r5, #0x66
|
||||||
|
mcr p15, 0, r5, c2, c0, 0 @ data cachable
|
||||||
|
mcr p15, 0, r5, c2, c0, 1 @ instruction cachable
|
||||||
|
|
||||||
|
mov r5, #0x10
|
||||||
|
mcr p15, 0, r5, c3, c0, 0 @ data bufferable
|
||||||
|
|
||||||
|
pop {r4-r5, pc}
|
||||||
|
|
||||||
|
_enable_caches:
|
||||||
|
push {r4-r5, lr}
|
||||||
|
|
||||||
|
bl _populate_mpu
|
||||||
|
mov r5, #0
|
||||||
|
mcr p15, 0, r5, c7, c5, 0 @ flush I-cache
|
||||||
|
mcr p15, 0, r5, c7, c6, 0 @ flush D-cache
|
||||||
|
|
||||||
|
mrc p15, 0, r4, c1, c0, 0
|
||||||
|
orr r4, r4, #(1<<12) @ instruction cache enable
|
||||||
|
orr r4, r4, #(1<<2) @ data cache enable
|
||||||
|
orr r4, r4, #(1<<0) @ mpu enable
|
||||||
|
mcr p15, 0, r4, c1, c0, 0
|
||||||
|
|
||||||
|
pop {r4-r5, pc}
|
||||||
|
|
||||||
|
_init:
|
||||||
|
push {r0-r12, lr}
|
||||||
|
|
||||||
|
bl _enable_caches
|
||||||
|
bl main
|
||||||
|
|
||||||
|
mrc p15, 0, r4, c1, c0, 0
|
||||||
|
bic r4, r4, #(1<<0) @ mpu disable
|
||||||
|
mcr p15, 0, r4, c1, c0, 0
|
||||||
|
|
||||||
|
pop {r0-r12, lr}
|
||||||
|
|
||||||
|
@ return control to FIRM
|
||||||
|
ldr pc, arm9ep_backup
|
||||||
|
|
||||||
|
#endif // EXEC_BOOTSTRAP
|
51
source/abstraction/gw-start.s
Normal file
51
source/abstraction/gw-start.s
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
#ifdef EXEC_GATEWAY
|
||||||
|
|
||||||
|
.section ".init"
|
||||||
|
|
||||||
|
.global _start
|
||||||
|
.extern main
|
||||||
|
|
||||||
|
.align 4
|
||||||
|
.arm
|
||||||
|
|
||||||
|
_vectors:
|
||||||
|
ldr pc, =InfiniteLoop
|
||||||
|
.pool
|
||||||
|
ldr pc, =InfiniteLoop
|
||||||
|
.pool
|
||||||
|
ldr pc, =InfiniteLoop
|
||||||
|
.pool
|
||||||
|
ldr pc, =InfiniteLoop
|
||||||
|
.pool
|
||||||
|
ldr pc, =InfiniteLoop
|
||||||
|
.pool
|
||||||
|
ldr pc, =InfiniteLoop
|
||||||
|
.pool
|
||||||
|
|
||||||
|
_start:
|
||||||
|
ldr sp,=0x22140000
|
||||||
|
|
||||||
|
@@wait for the arm11 kernel threads to be ready
|
||||||
|
ldr r1, =0x10000
|
||||||
|
waitLoop9:
|
||||||
|
sub r1, #1
|
||||||
|
|
||||||
|
cmp r1, #0
|
||||||
|
bgt waitLoop9
|
||||||
|
|
||||||
|
ldr r1, =0x10000
|
||||||
|
waitLoop92:
|
||||||
|
sub r1, #1
|
||||||
|
|
||||||
|
cmp r1, #0
|
||||||
|
bgt waitLoop92
|
||||||
|
|
||||||
|
ldr sp,=0x22160000
|
||||||
|
ldr r3, =main
|
||||||
|
blx r3
|
||||||
|
.pool
|
||||||
|
|
||||||
|
InfiniteLoop:
|
||||||
|
b InfiniteLoop
|
||||||
|
|
||||||
|
#endif // EXEC_GATEWAY
|
53
source/common.h
Normal file
53
source/common.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <ctype.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#define u8 uint8_t
|
||||||
|
#define u16 uint16_t
|
||||||
|
#define u32 uint32_t
|
||||||
|
#define u64 uint64_t
|
||||||
|
|
||||||
|
#define vu8 volatile u8
|
||||||
|
#define vu16 volatile u16
|
||||||
|
#define vu32 volatile u32
|
||||||
|
#define vu64 volatile u64
|
||||||
|
|
||||||
|
#define max(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a > _b ? _a : _b; })
|
||||||
|
#define min(a,b) \
|
||||||
|
({ __typeof__ (a) _a = (a); \
|
||||||
|
__typeof__ (b) _b = (b); \
|
||||||
|
_a < _b ? _a : _b; })
|
||||||
|
#define getbe16(d) \
|
||||||
|
(((d)[0]<<8) | (d)[1])
|
||||||
|
#define getbe32(d) \
|
||||||
|
((((u32) getbe16(d))<<16) | ((u32) getbe16(d+2)))
|
||||||
|
#define getbe64(d) \
|
||||||
|
((((u64) getbe32(d))<<32) | ((u64) getbe32(d+4)))
|
||||||
|
#define getle16(d) (*((u16*) (d)))
|
||||||
|
#define getle32(d) (*((u32*) (d)))
|
||||||
|
#define getle64(d) (*((u64*) (d)))
|
||||||
|
#define align(v,a) \
|
||||||
|
(((v) % (a)) ? ((v) + (a) - ((v) % (a))) : (v))
|
||||||
|
|
||||||
|
// work files / directories
|
||||||
|
#define GAME_DIR "/D9Game"
|
||||||
|
#define WORK_DIR "/Decrypt9"
|
||||||
|
#define LOG_FILE "Decrypt9.log"
|
||||||
|
|
||||||
|
inline u32 strchrcount(const char* str, char symbol) {
|
||||||
|
u32 count = 0;
|
||||||
|
for (u32 i = 0; str[i] != '\0'; i++) {
|
||||||
|
if (str[i] == symbol)
|
||||||
|
count++;
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
202
source/draw.c
Normal file
202
source/draw.c
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
// Copyright 2013 Normmatt
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdarg.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include "font.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#ifdef USE_THEME
|
||||||
|
#include "theme.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static char debugstr[DBG_N_CHARS_X * DBG_N_CHARS_Y] = { 0 };
|
||||||
|
|
||||||
|
void ClearScreen(u8* screen, int width, int color)
|
||||||
|
{
|
||||||
|
if (color == COLOR_TRANSPARENT) color = COLOR_BLACK;
|
||||||
|
for (int i = 0; i < (width * SCREEN_HEIGHT); i++) {
|
||||||
|
*(screen++) = color >> 16; // B
|
||||||
|
*(screen++) = color >> 8; // G
|
||||||
|
*(screen++) = color & 0xFF; // R
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ClearScreenFull(bool clear_top, bool clear_bottom)
|
||||||
|
{
|
||||||
|
if (clear_top) {
|
||||||
|
ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, STD_COLOR_BG);
|
||||||
|
ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, STD_COLOR_BG);
|
||||||
|
}
|
||||||
|
if (clear_bottom) {
|
||||||
|
ClearScreen(BOT_SCREEN0, SCREEN_WIDTH_BOT, STD_COLOR_BG);
|
||||||
|
ClearScreen(BOT_SCREEN1, SCREEN_WIDTH_BOT, STD_COLOR_BG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawCharacter(u8* screen, int character, int x, int y, int color, int bgcolor)
|
||||||
|
{
|
||||||
|
for (int yy = 0; yy < 8; yy++) {
|
||||||
|
int xDisplacement = (x * BYTES_PER_PIXEL * SCREEN_HEIGHT);
|
||||||
|
int yDisplacement = ((SCREEN_HEIGHT - (y + yy) - 1) * BYTES_PER_PIXEL);
|
||||||
|
u8* screenPos = screen + xDisplacement + yDisplacement;
|
||||||
|
|
||||||
|
u8 charPos = font[character * 8 + yy];
|
||||||
|
for (int xx = 7; xx >= 0; xx--) {
|
||||||
|
if ((charPos >> xx) & 1) {
|
||||||
|
*(screenPos + 0) = color >> 16; // B
|
||||||
|
*(screenPos + 1) = color >> 8; // G
|
||||||
|
*(screenPos + 2) = color & 0xFF; // R
|
||||||
|
} else if (bgcolor != COLOR_TRANSPARENT) {
|
||||||
|
*(screenPos + 0) = bgcolor >> 16; // B
|
||||||
|
*(screenPos + 1) = bgcolor >> 8; // G
|
||||||
|
*(screenPos + 2) = bgcolor & 0xFF; // R
|
||||||
|
}
|
||||||
|
screenPos += BYTES_PER_PIXEL * SCREEN_HEIGHT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawString(u8* screen, const char *str, int x, int y, int color, int bgcolor)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < strlen(str); i++)
|
||||||
|
DrawCharacter(screen, str[i], x + i * 8, y, color, bgcolor);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DrawStringF(int x, int y, bool use_top, const char *format, ...)
|
||||||
|
{
|
||||||
|
char str[512] = {}; // 512 should be more than enough
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
vsnprintf(str, 512, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
for (char* text = strtok(str, "\n"); text != NULL; text = strtok(NULL, "\n"), y += 10) {
|
||||||
|
if (use_top) {
|
||||||
|
DrawString(TOP_SCREEN0, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||||
|
DrawString(TOP_SCREEN1, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||||
|
} else {
|
||||||
|
DrawString(BOT_SCREEN0, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||||
|
DrawString(BOT_SCREEN1, text, x, y, STD_COLOR_FONT, STD_COLOR_BG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Screenshot(const char* path)
|
||||||
|
{
|
||||||
|
u8* buffer = (u8*) 0x21000000; // careful, this area is used by other functions in Decrypt9
|
||||||
|
u8* buffer_t = buffer + (400 * 240 * 3);
|
||||||
|
u8 bmp_header[54] = {
|
||||||
|
0x42, 0x4D, 0x36, 0xCA, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00, 0x00, 0x00, 0x28, 0x00,
|
||||||
|
0x00, 0x00, 0x90, 0x01, 0x00, 0x00, 0xE0, 0x01, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xCA, 0x08, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
};
|
||||||
|
static u32 n = 0;
|
||||||
|
|
||||||
|
if (path == NULL) {
|
||||||
|
for (; n < 1000; n++) {
|
||||||
|
char filename[16];
|
||||||
|
snprintf(filename, 16, "snap%03i.bmp", (int) n);
|
||||||
|
if (!FileOpen(filename)) {
|
||||||
|
FileCreate(filename, true);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
FileClose();
|
||||||
|
}
|
||||||
|
if (n >= 1000)
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
FileCreate(path, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
memset(buffer, 0x1F, 400 * 240 * 3 * 2);
|
||||||
|
for (u32 x = 0; x < 400; x++)
|
||||||
|
for (u32 y = 0; y < 240; y++)
|
||||||
|
memcpy(buffer_t + (y*400 + x) * 3, TOP_SCREEN0 + (x*240 + y) * 3, 3);
|
||||||
|
for (u32 x = 0; x < 320; x++)
|
||||||
|
for (u32 y = 0; y < 240; y++)
|
||||||
|
memcpy(buffer + (y*400 + x + 40) * 3, BOT_SCREEN0 + (x*240 + y) * 3, 3);
|
||||||
|
FileWrite(bmp_header, 54, 0);
|
||||||
|
FileWrite(buffer, 400 * 240 * 3 * 2, 54);
|
||||||
|
FileClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugClear()
|
||||||
|
{
|
||||||
|
memset(debugstr, 0x00, DBG_N_CHARS_X * DBG_N_CHARS_Y);
|
||||||
|
ClearScreen(TOP_SCREEN0, SCREEN_WIDTH_TOP, DBG_COLOR_BG);
|
||||||
|
ClearScreen(TOP_SCREEN1, SCREEN_WIDTH_TOP, DBG_COLOR_BG);
|
||||||
|
#if defined USE_THEME && defined GFX_DEBUG_BG
|
||||||
|
LoadThemeGfx(GFX_DEBUG_BG, true);
|
||||||
|
#endif
|
||||||
|
LogWrite("");
|
||||||
|
LogWrite(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DebugSet(const char **strs)
|
||||||
|
{
|
||||||
|
if (strs != NULL) for (int y = 0; y < DBG_N_CHARS_Y; y++) {
|
||||||
|
int pos_dbgstr = DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1 - y);
|
||||||
|
snprintf(debugstr + pos_dbgstr, DBG_N_CHARS_X, "%-*.*s", DBG_N_CHARS_X - 1, DBG_N_CHARS_X - 1, strs[y]);
|
||||||
|
}
|
||||||
|
|
||||||
|
int pos_y = DBG_START_Y;
|
||||||
|
for (char* str = debugstr + (DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1)); str >= debugstr; str -= DBG_N_CHARS_X) {
|
||||||
|
if (str[0] != '\0') {
|
||||||
|
DrawString(TOP_SCREEN0, str, DBG_START_X, pos_y, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||||
|
DrawString(TOP_SCREEN1, str, DBG_START_X, pos_y, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||||
|
pos_y += DBG_STEP_Y;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Debug(const char *format, ...)
|
||||||
|
{
|
||||||
|
static bool adv_output = true;
|
||||||
|
char tempstr[128] = { 0 }; // 128 instead of DBG_N_CHARS_X for log file
|
||||||
|
va_list va;
|
||||||
|
|
||||||
|
va_start(va, format);
|
||||||
|
vsnprintf(tempstr, 128, format, va);
|
||||||
|
va_end(va);
|
||||||
|
|
||||||
|
if (adv_output) {
|
||||||
|
memmove(debugstr + DBG_N_CHARS_X, debugstr, DBG_N_CHARS_X * (DBG_N_CHARS_Y - 1));
|
||||||
|
} else {
|
||||||
|
adv_output = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (*tempstr != '\r') { // not a good way of doing this - improve this later
|
||||||
|
snprintf(debugstr, DBG_N_CHARS_X, "%-*.*s", DBG_N_CHARS_X - 1, DBG_N_CHARS_X - 1, tempstr);
|
||||||
|
LogWrite(tempstr);
|
||||||
|
} else {
|
||||||
|
snprintf(debugstr, DBG_N_CHARS_X, "%-*.*s", DBG_N_CHARS_X - 1, DBG_N_CHARS_X - 1, tempstr + 1);
|
||||||
|
adv_output = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
DebugSet(NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !defined(USE_THEME) || !defined(ALT_PROGRESS)
|
||||||
|
void ShowProgress(u64 current, u64 total)
|
||||||
|
{
|
||||||
|
const u32 progX = SCREEN_WIDTH_TOP - 40;
|
||||||
|
const u32 progY = SCREEN_HEIGHT - 20;
|
||||||
|
|
||||||
|
if (total > 0) {
|
||||||
|
char progStr[8];
|
||||||
|
snprintf(progStr, 8, "%3llu%%", (current * 100) / total);
|
||||||
|
DrawString(TOP_SCREEN0, progStr, progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||||
|
DrawString(TOP_SCREEN1, progStr, progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||||
|
} else {
|
||||||
|
DrawString(TOP_SCREEN0, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||||
|
DrawString(TOP_SCREEN1, " ", progX, progY, DBG_COLOR_FONT, DBG_COLOR_BG);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
63
source/draw.h
Normal file
63
source/draw.h
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
// Copyright 2013 Normmatt
|
||||||
|
// Licensed under GPLv2 or any later version
|
||||||
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define BYTES_PER_PIXEL 3
|
||||||
|
#define SCREEN_HEIGHT 240
|
||||||
|
#define SCREEN_WIDTH_TOP 400
|
||||||
|
#define SCREEN_WIDTH_BOT 320
|
||||||
|
|
||||||
|
#define RGB(r,g,b) (r<<24|b<<16|g<<8|r)
|
||||||
|
|
||||||
|
#define COLOR_BLACK RGB(0x00, 0x00, 0x00)
|
||||||
|
#define COLOR_WHITE RGB(0xFF, 0xFF, 0xFF)
|
||||||
|
#define COLOR_TRANSPARENT RGB(0xFF, 0x00, 0xEF) // otherwise known as 'super fuchsia'
|
||||||
|
|
||||||
|
#ifndef USE_THEME
|
||||||
|
#define STD_COLOR_BG COLOR_BLACK
|
||||||
|
#define STD_COLOR_FONT COLOR_WHITE
|
||||||
|
|
||||||
|
#define DBG_COLOR_BG COLOR_BLACK
|
||||||
|
#define DBG_COLOR_FONT COLOR_WHITE
|
||||||
|
|
||||||
|
#define DBG_START_Y 10
|
||||||
|
#define DBG_END_Y (SCREEN_HEIGHT - 10)
|
||||||
|
#define DBG_START_X 10
|
||||||
|
#define DBG_END_X (SCREEN_WIDTH_TOP - 10)
|
||||||
|
#define DBG_STEP_Y 10
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define DBG_N_CHARS_Y ((DBG_END_Y - DBG_START_Y) / DBG_STEP_Y)
|
||||||
|
#define DBG_N_CHARS_X (((DBG_END_X - DBG_START_X) / 8) + 1)
|
||||||
|
|
||||||
|
#ifdef EXEC_GATEWAY
|
||||||
|
#define TOP_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFC0 + 4 * (*(u32*)0x080FFFD8 & 1)))
|
||||||
|
#define BOT_SCREEN0 (u8*)(*(u32*)((uint32_t)0x080FFFD0 + 4 * (*(u32*)0x080FFFDC & 1)))
|
||||||
|
#define TOP_SCREEN1 TOP_SCREEN0
|
||||||
|
#define BOT_SCREEN1 BOT_SCREEN0
|
||||||
|
#elif defined(EXEC_BOOTSTRAP)
|
||||||
|
#define TOP_SCREEN0 (u8*)(0x20000000)
|
||||||
|
#define TOP_SCREEN1 (u8*)(0x20046500)
|
||||||
|
#define BOT_SCREEN0 (u8*)(0x2008CA00)
|
||||||
|
#define BOT_SCREEN1 (u8*)(0x200C4E00)
|
||||||
|
#else
|
||||||
|
#error "Unknown execution method"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
void ClearScreen(unsigned char *screen, int width, int color);
|
||||||
|
void ClearScreenFull(bool clear_top, bool clear_bottom);
|
||||||
|
|
||||||
|
void DrawCharacter(unsigned char *screen, int character, int x, int y, int color, int bgcolor);
|
||||||
|
void DrawString(unsigned char *screen, const char *str, int x, int y, int color, int bgcolor);
|
||||||
|
void DrawStringF(int x, int y, bool use_top, const char *format, ...);
|
||||||
|
|
||||||
|
void Screenshot(const char* path);
|
||||||
|
void DebugClear();
|
||||||
|
void DebugSet(const char **strs);
|
||||||
|
void Debug(const char *format, ...);
|
||||||
|
|
||||||
|
void ShowProgress(u64 current, u64 total);
|
21
source/fatfs/00readme.txt
Normal file
21
source/fatfs/00readme.txt
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
FatFs Module Source Files R0.11
|
||||||
|
|
||||||
|
|
||||||
|
FILES
|
||||||
|
|
||||||
|
00readme.txt This file.
|
||||||
|
history.txt Revision history.
|
||||||
|
ffconf.h Configuration file for FatFs module.
|
||||||
|
ff.h Common include file for FatFs and application module.
|
||||||
|
ff.c FatFs 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.
|
||||||
|
integer.h Integer type definitions for FatFs.
|
||||||
|
option Optional external functions.
|
||||||
|
|
||||||
|
|
||||||
|
Low level disk I/O module is not included in this archive because the FatFs
|
||||||
|
module is only a generic file system layer and not depend on any specific
|
||||||
|
storage device. You have to provide a low level disk I/O module that written
|
||||||
|
to control the target storage device.
|
||||||
|
|
164
source/fatfs/crypto/aes.c
Normal file
164
source/fatfs/crypto/aes.c
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
/* original version by megazig */
|
||||||
|
#include "aes.h"
|
||||||
|
|
||||||
|
void setup_aeskeyX(u8 keyslot, void* keyx)
|
||||||
|
{
|
||||||
|
u32 * _keyx = (u32*)keyx;
|
||||||
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||||
|
*REG_AESKEYXFIFO = _keyx[0];
|
||||||
|
*REG_AESKEYXFIFO = _keyx[1];
|
||||||
|
*REG_AESKEYXFIFO = _keyx[2];
|
||||||
|
*REG_AESKEYXFIFO = _keyx[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_aeskeyY(u8 keyslot, void* keyy)
|
||||||
|
{
|
||||||
|
u32 * _keyy = (u32*)keyy;
|
||||||
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||||
|
*REG_AESKEYYFIFO = _keyy[0];
|
||||||
|
*REG_AESKEYYFIFO = _keyy[1];
|
||||||
|
*REG_AESKEYYFIFO = _keyy[2];
|
||||||
|
*REG_AESKEYYFIFO = _keyy[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup_aeskey(u8 keyslot, void* key)
|
||||||
|
{
|
||||||
|
u32 * _key = (u32*)key;
|
||||||
|
*REG_AESKEYCNT = (*REG_AESKEYCNT >> 6 << 6) | keyslot | 0x80;
|
||||||
|
*REG_AESKEYFIFO = _key[0];
|
||||||
|
*REG_AESKEYFIFO = _key[1];
|
||||||
|
*REG_AESKEYFIFO = _key[2];
|
||||||
|
*REG_AESKEYFIFO = _key[3];
|
||||||
|
}
|
||||||
|
|
||||||
|
void use_aeskey(u32 keyno)
|
||||||
|
{
|
||||||
|
if (keyno > 0x3F)
|
||||||
|
return;
|
||||||
|
*REG_AESKEYSEL = keyno;
|
||||||
|
*REG_AESCNT = *REG_AESCNT | 0x04000000; /* mystery bit */
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_ctr(void* iv)
|
||||||
|
{
|
||||||
|
u32 * _iv = (u32*)iv;
|
||||||
|
*REG_AESCNT = (*REG_AESCNT) | AES_CNT_INPUT_ENDIAN | AES_CNT_INPUT_ORDER;
|
||||||
|
*(REG_AESCTR + 0) = _iv[3];
|
||||||
|
*(REG_AESCTR + 1) = _iv[2];
|
||||||
|
*(REG_AESCTR + 2) = _iv[1];
|
||||||
|
*(REG_AESCTR + 3) = _iv[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
void add_ctr(void* ctr, u32 carry)
|
||||||
|
{
|
||||||
|
u32 counter[4];
|
||||||
|
u8 *outctr = (u8 *) ctr;
|
||||||
|
u32 sum;
|
||||||
|
int32_t i;
|
||||||
|
|
||||||
|
for(i=0; i<4; i++) {
|
||||||
|
counter[i] = (outctr[i*4+0]<<24) | (outctr[i*4+1]<<16) | (outctr[i*4+2]<<8) | (outctr[i*4+3]<<0);
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=3; i>=0; i--)
|
||||||
|
{
|
||||||
|
sum = counter[i] + carry;
|
||||||
|
if (sum < counter[i]) {
|
||||||
|
carry = 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
carry = 0;
|
||||||
|
}
|
||||||
|
counter[i] = sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(i=0; i<4; i++)
|
||||||
|
{
|
||||||
|
outctr[i*4+0] = counter[i]>>24;
|
||||||
|
outctr[i*4+1] = counter[i]>>16;
|
||||||
|
outctr[i*4+2] = counter[i]>>8;
|
||||||
|
outctr[i*4+3] = counter[i]>>0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void aes_decrypt(void* inbuf, void* outbuf, size_t size, u32 mode)
|
||||||
|
{
|
||||||
|
u32 in = (u32)inbuf;
|
||||||
|
u32 out = (u32)outbuf;
|
||||||
|
size_t block_count = size;
|
||||||
|
size_t blocks;
|
||||||
|
while (block_count != 0)
|
||||||
|
{
|
||||||
|
blocks = (block_count >= 0xFFFF) ? 0xFFFF : block_count;
|
||||||
|
*REG_AESCNT = 0;
|
||||||
|
*REG_AESBLKCNT = blocks << 16;
|
||||||
|
*REG_AESCNT = mode |
|
||||||
|
AES_CNT_START |
|
||||||
|
AES_CNT_FLUSH_READ |
|
||||||
|
AES_CNT_FLUSH_WRITE;
|
||||||
|
aes_fifos((void*)in, (void*)out, blocks);
|
||||||
|
in += blocks * AES_BLOCK_SIZE;
|
||||||
|
out += blocks * AES_BLOCK_SIZE;
|
||||||
|
block_count -= blocks;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void aes_fifos(void* inbuf, void* outbuf, size_t blocks)
|
||||||
|
{
|
||||||
|
u32 in = (u32)inbuf;
|
||||||
|
if (!in) return;
|
||||||
|
|
||||||
|
u32 out = (u32)outbuf;
|
||||||
|
size_t curblock = 0;
|
||||||
|
while (curblock != blocks)
|
||||||
|
{
|
||||||
|
while (aescnt_checkwrite());
|
||||||
|
|
||||||
|
int ii = 0;
|
||||||
|
for (ii = in; ii != in + AES_BLOCK_SIZE; ii += 4)
|
||||||
|
{
|
||||||
|
set_aeswrfifo( *(u32*)(ii) );
|
||||||
|
}
|
||||||
|
if (out)
|
||||||
|
{
|
||||||
|
while (aescnt_checkread()) ;
|
||||||
|
for (ii = out; ii != out + AES_BLOCK_SIZE; ii += 4)
|
||||||
|
{
|
||||||
|
*(u32*)ii = read_aesrdfifo();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
curblock++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_aeswrfifo(u32 value)
|
||||||
|
{
|
||||||
|
*REG_AESWRFIFO = value;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 read_aesrdfifo(void)
|
||||||
|
{
|
||||||
|
return *REG_AESRDFIFO;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 aes_getwritecount()
|
||||||
|
{
|
||||||
|
return *REG_AESCNT & 0x1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 aes_getreadcount()
|
||||||
|
{
|
||||||
|
return (*REG_AESCNT >> 5) & 0x1F;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 aescnt_checkwrite()
|
||||||
|
{
|
||||||
|
size_t ret = aes_getwritecount();
|
||||||
|
return (ret > 0xF);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 aescnt_checkread()
|
||||||
|
{
|
||||||
|
size_t ret = aes_getreadcount();
|
||||||
|
return (ret <= 3);
|
||||||
|
}
|
53
source/fatfs/crypto/aes.h
Normal file
53
source/fatfs/crypto/aes.h
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define AES_BLOCK_SIZE 0x10
|
||||||
|
|
||||||
|
#define AES_CCM_DECRYPT_MODE (0 << 27)
|
||||||
|
#define AES_CCM_ENCRYPT_MODE (1 << 27)
|
||||||
|
#define AES_CTR_MODE (2 << 27)
|
||||||
|
#define AES_CBC_DECRYPT_MODE (4 << 27)
|
||||||
|
#define AES_CBC_ENCRYPT_MODE (5 << 27)
|
||||||
|
#define AES_ECB_DECRYPT_MODE (6 << 27)
|
||||||
|
#define AES_ECB_ENCRYPT_MODE (7 << 27)
|
||||||
|
|
||||||
|
#define REG_AESCNT ((volatile u32*)0x10009000)
|
||||||
|
#define REG_AESBLKCNT ((volatile u32*)0x10009004)
|
||||||
|
#define REG_AESWRFIFO ((volatile u32*)0x10009008)
|
||||||
|
#define REG_AESRDFIFO ((volatile u32*)0x1000900C)
|
||||||
|
#define REG_AESKEYSEL ((volatile u8 *)0x10009010)
|
||||||
|
#define REG_AESKEYCNT ((volatile u8 *)0x10009011)
|
||||||
|
#define REG_AESCTR ((volatile u32*)0x10009020)
|
||||||
|
#define REG_AESKEYFIFO ((volatile u32*)0x10009100)
|
||||||
|
#define REG_AESKEYXFIFO ((volatile u32*)0x10009104)
|
||||||
|
#define REG_AESKEYYFIFO ((volatile u32*)0x10009108)
|
||||||
|
|
||||||
|
#define AES_CNT_START 0x80000000
|
||||||
|
#define AES_CNT_INPUT_ORDER 0x02000000
|
||||||
|
#define AES_CNT_OUTPUT_ORDER 0x01000000
|
||||||
|
#define AES_CNT_INPUT_ENDIAN 0x00800000
|
||||||
|
#define AES_CNT_OUTPUT_ENDIAN 0x00400000
|
||||||
|
#define AES_CNT_FLUSH_READ 0x00000800
|
||||||
|
#define AES_CNT_FLUSH_WRITE 0x00000400
|
||||||
|
|
||||||
|
#define AES_CNT_CTRNAND_MODE (AES_CTR_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||||
|
#define AES_CNT_TWLNAND_MODE AES_CTR_MODE
|
||||||
|
#define AES_CNT_TITLEKEY_DECRYPT_MODE (AES_CBC_DECRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||||
|
#define AES_CNT_TITLEKEY_ENCRYPT_MODE (AES_CBC_ENCRYPT_MODE | AES_CNT_INPUT_ORDER | AES_CNT_OUTPUT_ORDER | AES_CNT_INPUT_ENDIAN | AES_CNT_OUTPUT_ENDIAN)
|
||||||
|
|
||||||
|
|
||||||
|
void setup_aeskeyX(u8 keyslot, void* keyx);
|
||||||
|
void setup_aeskeyY(u8 keyslot, void* keyy);
|
||||||
|
void setup_aeskey(u8 keyslot, void* keyy);
|
||||||
|
void use_aeskey(u32 keyno);
|
||||||
|
void set_ctr(void* iv);
|
||||||
|
void add_ctr(void* ctr, u32 carry);
|
||||||
|
void aes_decrypt(void* inbuf, void* outbuf, size_t size, u32 mode);
|
||||||
|
void aes_fifos(void* inbuf, void* outbuf, size_t blocks);
|
||||||
|
void set_aeswrfifo(u32 value);
|
||||||
|
u32 read_aesrdfifo(void);
|
||||||
|
u32 aes_getwritecount();
|
||||||
|
u32 aes_getreadcount();
|
||||||
|
u32 aescnt_checkwrite();
|
||||||
|
u32 aescnt_checkread();
|
68
source/fatfs/crypto/decryptor.c
Normal file
68
source/fatfs/crypto/decryptor.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "fs.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "decryptor/decryptor.h"
|
||||||
|
#include "decryptor/aes.h"
|
||||||
|
|
||||||
|
|
||||||
|
u32 CryptBuffer(CryptBufferInfo *info)
|
||||||
|
{
|
||||||
|
u8 ctr[16] __attribute__((aligned(32)));
|
||||||
|
memcpy(ctr, info->ctr, 16);
|
||||||
|
|
||||||
|
u8* buffer = info->buffer;
|
||||||
|
u32 size = info->size;
|
||||||
|
u32 mode = info->mode;
|
||||||
|
|
||||||
|
if (info->setKeyY) {
|
||||||
|
u8 keyY[16] __attribute__((aligned(32)));
|
||||||
|
memcpy(keyY, info->keyY, 16);
|
||||||
|
setup_aeskeyY(info->keyslot, keyY);
|
||||||
|
info->setKeyY = 0;
|
||||||
|
}
|
||||||
|
use_aeskey(info->keyslot);
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size; i += 0x10, buffer += 0x10) {
|
||||||
|
set_ctr(ctr);
|
||||||
|
if ((mode & (0x7 << 27)) == AES_CBC_DECRYPT_MODE)
|
||||||
|
memcpy(ctr, buffer, 0x10);
|
||||||
|
aes_decrypt((void*) buffer, (void*) buffer, 1, mode);
|
||||||
|
if ((mode & (0x7 << 27)) == AES_CBC_ENCRYPT_MODE)
|
||||||
|
memcpy(ctr, buffer, 0x10);
|
||||||
|
else if ((mode & (0x7 << 27)) == AES_CTR_MODE)
|
||||||
|
add_ctr(ctr, 0x1);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(info->ctr, ctr, 16);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CreatePad(PadInfo *info)
|
||||||
|
{
|
||||||
|
u8* buffer = BUFFER_ADDRESS;
|
||||||
|
u32 result = 0;
|
||||||
|
|
||||||
|
if (!FileCreate(info->filename, true)) // No DebugFileCreate() here - messages are already given
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
CryptBufferInfo decryptInfo = {.keyslot = info->keyslot, .setKeyY = info->setKeyY, .mode = info->mode, .buffer = buffer};
|
||||||
|
memcpy(decryptInfo.ctr, info->ctr, 16);
|
||||||
|
memcpy(decryptInfo.keyY, info->keyY, 16);
|
||||||
|
u32 size_bytes = info->size_mb * 1024*1024;
|
||||||
|
for (u32 i = 0; i < size_bytes; i += BUFFER_MAX_SIZE) {
|
||||||
|
u32 curr_block_size = min(BUFFER_MAX_SIZE, size_bytes - i);
|
||||||
|
decryptInfo.size = curr_block_size;
|
||||||
|
memset(buffer, 0x00, curr_block_size);
|
||||||
|
ShowProgress(i, size_bytes);
|
||||||
|
CryptBuffer(&decryptInfo);
|
||||||
|
if (!DebugFileWrite((void*)buffer, curr_block_size, i)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowProgress(0, 0);
|
||||||
|
FileClose();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
30
source/fatfs/crypto/decryptor.h
Normal file
30
source/fatfs/crypto/decryptor.h
Normal file
@ -0,0 +1,30 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define BUFFER_ADDRESS ((u8*) 0x21000000)
|
||||||
|
#define BUFFER_MAX_SIZE (1 * 1024 * 1024) // must be a multiple of 0x40 (64)
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 keyslot;
|
||||||
|
u32 setKeyY;
|
||||||
|
u8 ctr[16];
|
||||||
|
u8 keyY[16];
|
||||||
|
u32 size;
|
||||||
|
u32 mode;
|
||||||
|
u8* buffer;
|
||||||
|
} __attribute__((packed)) CryptBufferInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 keyslot;
|
||||||
|
u32 setKeyY;
|
||||||
|
u8 ctr[16];
|
||||||
|
u8 keyY[16];
|
||||||
|
u32 size_mb;
|
||||||
|
u32 mode;
|
||||||
|
char filename[180];
|
||||||
|
} __attribute__((packed, aligned(16))) PadInfo;
|
||||||
|
|
||||||
|
|
||||||
|
u32 CryptBuffer(CryptBufferInfo *info);
|
||||||
|
u32 CreatePad(PadInfo *info);
|
1313
source/fatfs/crypto/game.c
Normal file
1313
source/fatfs/crypto/game.c
Normal file
File diff suppressed because it is too large
Load Diff
107
source/fatfs/crypto/game.h
Normal file
107
source/fatfs/crypto/game.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
#include "decryptor/decryptor.h"
|
||||||
|
|
||||||
|
#define GC_NCCH_PROCESS (1<<0)
|
||||||
|
#define GC_CIA_PROCESS (1<<1)
|
||||||
|
#define GC_CIA_DEEP (1<<2)
|
||||||
|
#define GC_NCCH_ENCRYPT (1<<3)
|
||||||
|
#define GC_CIA_ENCRYPT (1<<4)
|
||||||
|
#define GC_CXI_ONLY (1<<5)
|
||||||
|
|
||||||
|
#define MAX_ENTRIES 1024
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u64 titleId;
|
||||||
|
u8 external_seed[16];
|
||||||
|
u8 reserved[8];
|
||||||
|
} __attribute__((packed)) SeedInfoEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 n_entries;
|
||||||
|
u8 padding[12];
|
||||||
|
SeedInfoEntry entries[MAX_ENTRIES];
|
||||||
|
} __attribute__((packed)) SeedInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 ctr[16];
|
||||||
|
u32 size_mb;
|
||||||
|
char filename[180];
|
||||||
|
} __attribute__((packed)) SdInfoEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 n_entries;
|
||||||
|
SdInfoEntry entries[MAX_ENTRIES];
|
||||||
|
} __attribute__((packed, aligned(16))) SdInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 ctr[16];
|
||||||
|
u8 keyY[16];
|
||||||
|
u32 size_mb;
|
||||||
|
u8 reserved[4];
|
||||||
|
u32 usesSeedCrypto;
|
||||||
|
u32 uses7xCrypto;
|
||||||
|
u64 titleId;
|
||||||
|
char filename[112];
|
||||||
|
} __attribute__((packed)) NcchInfoEntry;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 padding;
|
||||||
|
u32 ncch_info_version;
|
||||||
|
u32 n_entries;
|
||||||
|
u8 reserved[4];
|
||||||
|
NcchInfoEntry entries[MAX_ENTRIES];
|
||||||
|
} __attribute__((packed, aligned(16))) NcchInfo;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u8 signature[0x100];
|
||||||
|
u8 magic[0x4];
|
||||||
|
u32 size;
|
||||||
|
u64 partitionId;
|
||||||
|
u16 makercode;
|
||||||
|
u16 version;
|
||||||
|
u8 reserved0[0x4];
|
||||||
|
u64 programId;
|
||||||
|
u8 reserved1[0x10];
|
||||||
|
u8 hash_logo[0x20];
|
||||||
|
char productCode[0x10];
|
||||||
|
u8 hash_exthdr[0x20];
|
||||||
|
u32 size_exthdr;
|
||||||
|
u8 reserved2[0x4];
|
||||||
|
u8 flags[0x8];
|
||||||
|
u32 offset_plain;
|
||||||
|
u32 size_plain;
|
||||||
|
u32 offset_logo;
|
||||||
|
u32 size_logo;
|
||||||
|
u32 offset_exefs;
|
||||||
|
u32 size_exefs;
|
||||||
|
u32 size_exefs_hash;
|
||||||
|
u8 reserved3[0x4];
|
||||||
|
u32 offset_romfs;
|
||||||
|
u32 size_romfs;
|
||||||
|
u32 size_romfs_hash;
|
||||||
|
u8 reserved4[0x4];
|
||||||
|
u8 hash_exefs[0x20];
|
||||||
|
u8 hash_romfs[0x20];
|
||||||
|
} __attribute__((packed, aligned(16))) NcchHeader;
|
||||||
|
|
||||||
|
|
||||||
|
u32 GetSdCtr(u8* ctr, const char* path);
|
||||||
|
u32 GetSd0x34KeyY(u8* movable_keyY, bool from_nand);
|
||||||
|
u32 SdFolderSelector(char* path, u8* keyY);
|
||||||
|
u32 SdInfoGen(SdInfo* info, const char* base_path);
|
||||||
|
u32 CryptSdToSd(const char* filename, u32 offset, u32 size, CryptBufferInfo* info);
|
||||||
|
u32 GetHashFromFile(const char* filename, u32 offset, u32 size, u8* hash);
|
||||||
|
u32 CheckHashFromFile(const char* filename, u32 offset, u32 size, u8* hash);
|
||||||
|
u32 CryptNcch(const char* filename, u32 offset, u32 size, u64 seedId, u8* encrypt_flags);
|
||||||
|
u32 CryptCia(const char* filename, u8* ncch_crypt, bool cia_encrypt, bool cxi_only);
|
||||||
|
|
||||||
|
// --> FEATURE FUNCTIONS <--
|
||||||
|
u32 NcchPadgen(u32 param);
|
||||||
|
u32 SdPadgen(u32 param);
|
||||||
|
u32 SdPadgenDirect(u32 param);
|
||||||
|
u32 UpdateSeedDb(u32 param);
|
||||||
|
u32 CryptGameFiles(u32 param);
|
||||||
|
u32 CryptSdFiles(u32 param);
|
||||||
|
u32 DecryptSdFilesDirect(u32 param);
|
682
source/fatfs/crypto/nand.c
Normal file
682
source/fatfs/crypto/nand.c
Normal file
@ -0,0 +1,682 @@
|
|||||||
|
#include "fs.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "hid.h"
|
||||||
|
#include "platform.h"
|
||||||
|
#include "decryptor/aes.h"
|
||||||
|
#include "decryptor/decryptor.h"
|
||||||
|
#include "decryptor/nand.h"
|
||||||
|
#include "fatfs/sdmmc.h"
|
||||||
|
|
||||||
|
// see: http://3dbrew.org/wiki/Flash_Filesystem
|
||||||
|
static PartitionInfo partitions[] = {
|
||||||
|
{ "TWLN", {0xE9, 0x00, 0x00, 0x54, 0x57, 0x4C, 0x20, 0x20}, 0x00012E00, 0x08FB5200, 0x3, AES_CNT_TWLNAND_MODE },
|
||||||
|
{ "TWLP", {0xE9, 0x00, 0x00, 0x54, 0x57, 0x4C, 0x20, 0x20}, 0x09011A00, 0x020B6600, 0x3, AES_CNT_TWLNAND_MODE },
|
||||||
|
{ "AGBSAVE", {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}, 0x0B100000, 0x00030000, 0x7, AES_CNT_CTRNAND_MODE },
|
||||||
|
{ "FIRM0", {0x46, 0x49, 0x52, 0x4D, 0x00, 0x00, 0x00, 0x00}, 0x0B130000, 0x00400000, 0x6, AES_CNT_CTRNAND_MODE },
|
||||||
|
{ "FIRM1", {0x46, 0x49, 0x52, 0x4D, 0x00, 0x00, 0x00, 0x00}, 0x0B530000, 0x00400000, 0x6, AES_CNT_CTRNAND_MODE },
|
||||||
|
{ "CTRNAND", {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20}, 0x0B95CA00, 0x2F3E3600, 0x4, AES_CNT_CTRNAND_MODE }, // O3DS
|
||||||
|
{ "CTRNAND", {0xE9, 0x00, 0x00, 0x43, 0x54, 0x52, 0x20, 0x20}, 0x0B95AE00, 0x41D2D200, 0x5, AES_CNT_CTRNAND_MODE } // N3DS
|
||||||
|
};
|
||||||
|
|
||||||
|
static u32 emunand_header = 0;
|
||||||
|
static u32 emunand_offset = 0;
|
||||||
|
|
||||||
|
|
||||||
|
u32 CheckEmuNand(void)
|
||||||
|
{
|
||||||
|
u8* buffer = BUFFER_ADDRESS;
|
||||||
|
u32 nand_size_sectors = getMMCDevice(0)->total_size;
|
||||||
|
u32 multi_sectors = (GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS;
|
||||||
|
u32 ret = EMUNAND_NOT_READY;
|
||||||
|
|
||||||
|
// check the MBR for presence of a hidden partition
|
||||||
|
sdmmc_sdcard_readsectors(0, 1, buffer);
|
||||||
|
u32 hidden_sectors = getle32(buffer + 0x1BE + 0x8);
|
||||||
|
|
||||||
|
for (u32 offset_sector = 0; offset_sector + nand_size_sectors < hidden_sectors; offset_sector += multi_sectors) {
|
||||||
|
// check for Gateway type EmuNAND
|
||||||
|
sdmmc_sdcard_readsectors(offset_sector + nand_size_sectors, 1, buffer);
|
||||||
|
if (memcmp(buffer + 0x100, "NCSD", 4) == 0) {
|
||||||
|
ret |= EMUNAND_GATEWAY << (2 * (offset_sector / multi_sectors));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// check for RedNAND type EmuNAND
|
||||||
|
sdmmc_sdcard_readsectors(offset_sector + 1, 1, buffer);
|
||||||
|
if (memcmp(buffer + 0x100, "NCSD", 4) == 0) {
|
||||||
|
ret |= EMUNAND_REDNAND << (2 * (offset_sector / multi_sectors));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
// EmuNAND ready but not set up
|
||||||
|
ret |= EMUNAND_READY << (2 * (offset_sector / multi_sectors));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 SetNand(bool set_emunand, bool force_emunand)
|
||||||
|
{
|
||||||
|
if (set_emunand) {
|
||||||
|
u32 emunand_state = CheckEmuNand();
|
||||||
|
u32 emunand_count = 0;
|
||||||
|
u32 offset_sector = 0;
|
||||||
|
|
||||||
|
for (emunand_count = 0; (emunand_state >> (2 * emunand_count)) & 0x3; emunand_count++);
|
||||||
|
if (emunand_count > 1) { // multiple EmuNANDs -> use selector
|
||||||
|
u32 multi_sectors = (GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS;
|
||||||
|
u32 emunand_no = 0;
|
||||||
|
Debug("Use arrow keys and <A> to choose EmuNAND");
|
||||||
|
while (true) {
|
||||||
|
u32 emunandn_state = (emunand_state >> (2 * emunand_no)) & 0x3;
|
||||||
|
offset_sector = emunand_no * multi_sectors;
|
||||||
|
Debug("\rEmuNAND #%u: %s", emunand_no, (emunandn_state == EMUNAND_READY) ? "EmuNAND ready" : (emunandn_state == EMUNAND_GATEWAY) ? "GW EmuNAND" : "RedNAND");
|
||||||
|
// user input routine
|
||||||
|
u32 pad_state = InputWait();
|
||||||
|
if (pad_state & BUTTON_DOWN) {
|
||||||
|
emunand_no = (emunand_no + 1) % emunand_count;
|
||||||
|
} else if (pad_state & BUTTON_UP) {
|
||||||
|
emunand_no = (emunand_no) ? emunand_no - 1 : emunand_count - 1;
|
||||||
|
} else if (pad_state & BUTTON_A) {
|
||||||
|
Debug("EmuNAND #%u", emunand_no);
|
||||||
|
emunand_state = emunandn_state;
|
||||||
|
break;
|
||||||
|
} else if (pad_state & BUTTON_B) {
|
||||||
|
Debug("(cancelled by user)");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((emunand_state == EMUNAND_READY) && force_emunand)
|
||||||
|
emunand_state = EMUNAND_GATEWAY;
|
||||||
|
switch (emunand_state) {
|
||||||
|
case EMUNAND_NOT_READY:
|
||||||
|
Debug("SD is not formatted for EmuNAND");
|
||||||
|
return 1;
|
||||||
|
case EMUNAND_GATEWAY:
|
||||||
|
emunand_header = offset_sector + getMMCDevice(0)->total_size;
|
||||||
|
emunand_offset = offset_sector;
|
||||||
|
Debug("Using EmuNAND @ %06X/%06X", emunand_header, emunand_offset);
|
||||||
|
return 0;
|
||||||
|
case EMUNAND_REDNAND:
|
||||||
|
emunand_header = offset_sector + 1;
|
||||||
|
emunand_offset = offset_sector + 1;
|
||||||
|
Debug("Using RedNAND @ %06X/%06X", emunand_header, emunand_offset);
|
||||||
|
return 0;
|
||||||
|
default:
|
||||||
|
Debug("EmuNAND is not available");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
emunand_header = 0;
|
||||||
|
emunand_offset = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int ReadNandSectors(u32 sector_no, u32 numsectors, u8 *out)
|
||||||
|
{
|
||||||
|
if (emunand_header) {
|
||||||
|
if (sector_no == 0) {
|
||||||
|
int errorcode = sdmmc_sdcard_readsectors(emunand_header, 1, out);
|
||||||
|
if (errorcode) return errorcode;
|
||||||
|
sector_no = 1;
|
||||||
|
numsectors--;
|
||||||
|
out += 0x200;
|
||||||
|
}
|
||||||
|
return sdmmc_sdcard_readsectors(sector_no + emunand_offset, numsectors, out);
|
||||||
|
} else return sdmmc_nand_readsectors(sector_no, numsectors, out);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int WriteNandSectors(u32 sector_no, u32 numsectors, u8 *in)
|
||||||
|
{
|
||||||
|
if (emunand_header) {
|
||||||
|
if (sector_no == 0) {
|
||||||
|
int errorcode = sdmmc_sdcard_writesectors(emunand_header, 1, in);
|
||||||
|
if (errorcode) return errorcode;
|
||||||
|
sector_no = 1;
|
||||||
|
numsectors--;
|
||||||
|
in += 0x200;
|
||||||
|
}
|
||||||
|
return sdmmc_sdcard_writesectors(sector_no + emunand_offset, numsectors, in);
|
||||||
|
} else return sdmmc_nand_writesectors(sector_no, numsectors, in);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 OutputFileNameSelector(char* filename, const char* basename, char* extension) {
|
||||||
|
char bases[3][64] = { 0 };
|
||||||
|
char* dotpos = NULL;
|
||||||
|
|
||||||
|
// build first base name and extension
|
||||||
|
strncpy(bases[0], basename, 63);
|
||||||
|
dotpos = strrchr(bases[0], '.');
|
||||||
|
|
||||||
|
if (dotpos) {
|
||||||
|
*dotpos = '\0';
|
||||||
|
if (!extension)
|
||||||
|
extension = dotpos + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// build other two base names
|
||||||
|
snprintf(bases[1], 63, "%s_%s", bases[0], (emunand_header) ? "emu" : "sys");
|
||||||
|
snprintf(bases[2], 63, "%s%s" , (emunand_header) ? "emu" : "sys", bases[0]);
|
||||||
|
|
||||||
|
u32 fn_id = (emunand_header) ? 1 : 0;
|
||||||
|
u32 fn_num = (emunand_header) ? (emunand_offset / ((GetUnitPlatform() == PLATFORM_3DS) ? EMUNAND_MULTI_OFFSET_O3DS : EMUNAND_MULTI_OFFSET_N3DS)) : 0;
|
||||||
|
bool exists = false;
|
||||||
|
char extstr[16] = { 0 };
|
||||||
|
if (extension)
|
||||||
|
snprintf(extstr, 15, ".%s", extension);
|
||||||
|
Debug("Use arrow keys and <A> to choose a name");
|
||||||
|
while (true) {
|
||||||
|
char numstr[2] = { 0 };
|
||||||
|
// build and output file name (plus "(!)" if existing)
|
||||||
|
numstr[0] = (fn_num > 0) ? '0' + fn_num : '\0';
|
||||||
|
snprintf(filename, 63, "%s%s%s", bases[fn_id], numstr, extstr);
|
||||||
|
if ((exists = FileOpen(filename)))
|
||||||
|
FileClose();
|
||||||
|
Debug("\r%s%s", filename, (exists) ? " (!)" : "");
|
||||||
|
// user input routine
|
||||||
|
u32 pad_state = InputWait();
|
||||||
|
if (pad_state & BUTTON_DOWN) { // increment filename id
|
||||||
|
fn_id = (fn_id + 1) % 3;
|
||||||
|
} else if (pad_state & BUTTON_UP) { // decrement filename id
|
||||||
|
fn_id = (fn_id > 0) ? fn_id - 1 : 2;
|
||||||
|
} else if ((pad_state & BUTTON_RIGHT) && (fn_num < 9)) { // increment number
|
||||||
|
fn_num++;
|
||||||
|
} else if ((pad_state & BUTTON_LEFT) && (fn_num > 0)) { // decrement number
|
||||||
|
fn_num--;
|
||||||
|
} else if (pad_state & BUTTON_A) {
|
||||||
|
Debug("%s%s", filename, (exists) ? " (!)" : "");
|
||||||
|
break;
|
||||||
|
} else if (pad_state & BUTTON_B) {
|
||||||
|
Debug("(cancelled by user)");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// overwrite confirmation
|
||||||
|
if (exists) {
|
||||||
|
Debug("Press <A> to overwrite existing file");
|
||||||
|
while (true) {
|
||||||
|
u32 pad_state = InputWait();
|
||||||
|
if (pad_state & BUTTON_A) {
|
||||||
|
break;
|
||||||
|
} else if (pad_state & BUTTON_B) {
|
||||||
|
Debug("(cancelled by user)");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 InputFileNameSelector(char* filename, const char* basename, char* extension, u8* magic, u32 msize, u32 fsize) {
|
||||||
|
char** fnptr = (char**) 0x20400000; // allow using 0x8000 byte
|
||||||
|
char* fnlist = (char*) 0x20408000; // allow using 0x80000 byte
|
||||||
|
u32 n_names = 0;
|
||||||
|
|
||||||
|
// get the file list - try work directory first
|
||||||
|
if (!GetFileList(WORK_DIR, fnlist, 0x80000, false, true, false) && !GetFileList("/", fnlist, 0x800000, false, true, false)) {
|
||||||
|
Debug("Failed retrieving the file names list");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// get base name, extension
|
||||||
|
char base[64] = { 0 };
|
||||||
|
if (basename != NULL) {
|
||||||
|
// build base name and extension
|
||||||
|
strncpy(base, basename, 63);
|
||||||
|
char* dotpos = strrchr(base, '.');
|
||||||
|
if (dotpos) {
|
||||||
|
*dotpos = '\0';
|
||||||
|
if (!extension)
|
||||||
|
extension = dotpos + 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// limit magic number size
|
||||||
|
if (msize > 0x200)
|
||||||
|
msize = 0x200;
|
||||||
|
|
||||||
|
// parse the file names list for usable entries
|
||||||
|
for (char* fn = strtok(fnlist, "\n"); fn != NULL; fn = strtok(NULL, "\n")) {
|
||||||
|
u8 data[0x200];
|
||||||
|
char* dotpos = strrchr(fn, '.');
|
||||||
|
if (strrchr(fn, '/'))
|
||||||
|
fn = strrchr(fn, '/') + 1;
|
||||||
|
if (strnlen(fn, 128) > 63)
|
||||||
|
continue; // file name too long
|
||||||
|
if ((basename != NULL) && !strstr(fn, base))
|
||||||
|
continue; // basename check failed
|
||||||
|
if ((extension != NULL) && (dotpos != NULL) && (strncmp(dotpos + 1, extension, strnlen(extension, 16))))
|
||||||
|
continue; // extension check failed
|
||||||
|
else if ((extension == NULL) != (dotpos == NULL))
|
||||||
|
continue; // extension check failed
|
||||||
|
if (!FileOpen(fn))
|
||||||
|
continue; // file can't be opened
|
||||||
|
if (fsize && (FileGetSize() != fsize)) {
|
||||||
|
FileClose();
|
||||||
|
continue; // file size check failed
|
||||||
|
}
|
||||||
|
if (msize) {
|
||||||
|
if (FileRead(data, msize, 0) != msize) {
|
||||||
|
FileClose();
|
||||||
|
continue; // can't be read
|
||||||
|
}
|
||||||
|
if (memcmp(data, magic, msize) != 0) {
|
||||||
|
FileClose();
|
||||||
|
continue; // magic number does not match
|
||||||
|
}
|
||||||
|
}
|
||||||
|
FileClose();
|
||||||
|
// this is a match - keep it
|
||||||
|
fnptr[n_names++] = fn;
|
||||||
|
if (n_names * sizeof(char**) >= 0x8000)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (n_names == 0) {
|
||||||
|
Debug("No usable file found");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 index = 0;
|
||||||
|
Debug("Use arrow keys and <A> to choose a file");
|
||||||
|
while (true) {
|
||||||
|
snprintf(filename, 63, "%s", fnptr[index]);
|
||||||
|
Debug("\r%s", filename);
|
||||||
|
u32 pad_state = InputWait();
|
||||||
|
if (pad_state & BUTTON_DOWN) { // next filename
|
||||||
|
index = (index + 1) % n_names;
|
||||||
|
} else if (pad_state & BUTTON_UP) { // previous filename
|
||||||
|
index = (index > 0) ? index - 1 : n_names - 1;
|
||||||
|
} else if (pad_state & BUTTON_A) {
|
||||||
|
Debug("%s", filename);
|
||||||
|
break;
|
||||||
|
} else if (pad_state & BUTTON_B) {
|
||||||
|
Debug("(cancelled by user)");
|
||||||
|
return 2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
PartitionInfo* GetPartitionInfo(u32 partition_id)
|
||||||
|
{
|
||||||
|
u32 partition_num = 0;
|
||||||
|
|
||||||
|
if (partition_id == P_CTRNAND) {
|
||||||
|
partition_num = (GetUnitPlatform() == PLATFORM_3DS) ? 5 : 6;
|
||||||
|
} else {
|
||||||
|
for(; !(partition_id & (1<<partition_num)) && (partition_num < 32); partition_num++);
|
||||||
|
}
|
||||||
|
|
||||||
|
return (partition_num >= 32) ? NULL : &(partitions[partition_num]);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 CtrNandPadgen(u32 param)
|
||||||
|
{
|
||||||
|
u32 keyslot;
|
||||||
|
u32 nand_size;
|
||||||
|
|
||||||
|
// legacy sizes & offset, to work with 3DSFAT16Tool
|
||||||
|
if (GetUnitPlatform() == PLATFORM_3DS) {
|
||||||
|
keyslot = 0x4;
|
||||||
|
nand_size = 758;
|
||||||
|
} else {
|
||||||
|
keyslot = 0x5;
|
||||||
|
nand_size = 1055;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug("Creating NAND FAT16 xorpad. Size (MB): %u", nand_size);
|
||||||
|
Debug("Filename: nand.fat16.xorpad");
|
||||||
|
|
||||||
|
PadInfo padInfo = {
|
||||||
|
.keyslot = keyslot,
|
||||||
|
.setKeyY = 0,
|
||||||
|
.size_mb = nand_size,
|
||||||
|
.filename = "nand.fat16.xorpad",
|
||||||
|
.mode = AES_CNT_CTRNAND_MODE
|
||||||
|
};
|
||||||
|
if(GetNandCtr(padInfo.ctr, 0xB930000) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return CreatePad(&padInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 TwlNandPadgen(u32 param)
|
||||||
|
{
|
||||||
|
u32 size_mb = (partitions[0].size + (1024 * 1024) - 1) / (1024 * 1024);
|
||||||
|
Debug("Creating TWLN FAT16 xorpad. Size (MB): %u", size_mb);
|
||||||
|
Debug("Filename: twlnand.fat16.xorpad");
|
||||||
|
|
||||||
|
PadInfo padInfo = {
|
||||||
|
.keyslot = partitions[0].keyslot,
|
||||||
|
.setKeyY = 0,
|
||||||
|
.size_mb = size_mb,
|
||||||
|
.filename = "twlnand.fat16.xorpad",
|
||||||
|
.mode = AES_CNT_TWLNAND_MODE
|
||||||
|
};
|
||||||
|
if(GetNandCtr(padInfo.ctr, partitions[0].offset) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return CreatePad(&padInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 Firm0Firm1Padgen(u32 param)
|
||||||
|
{
|
||||||
|
u32 size_mb = (partitions[3].size + partitions[4].size + (1024 * 1024) - 1) / (1024 * 1024);
|
||||||
|
Debug("Creating FIRM0FIRM1 xorpad. Size (MB): %u", size_mb);
|
||||||
|
Debug("Filename: firm0firm1.xorpad");
|
||||||
|
|
||||||
|
PadInfo padInfo = {
|
||||||
|
.keyslot = partitions[3].keyslot,
|
||||||
|
.setKeyY = 0,
|
||||||
|
.size_mb = size_mb,
|
||||||
|
.filename = "firm0firm1.xorpad",
|
||||||
|
.mode = AES_CNT_CTRNAND_MODE
|
||||||
|
};
|
||||||
|
if(GetNandCtr(padInfo.ctr, partitions[3].offset) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return CreatePad(&padInfo);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 GetNandCtr(u8* ctr, u32 offset)
|
||||||
|
{
|
||||||
|
static const char* versions[] = {"4.x", "5.x", "6.x", "7.x", "8.x", "9.x"};
|
||||||
|
static const u8* version_ctrs[] = {
|
||||||
|
(u8*)0x080D7CAC,
|
||||||
|
(u8*)0x080D858C,
|
||||||
|
(u8*)0x080D748C,
|
||||||
|
(u8*)0x080D740C,
|
||||||
|
(u8*)0x080D74CC,
|
||||||
|
(u8*)0x080D794C
|
||||||
|
};
|
||||||
|
static const u32 version_ctrs_len = sizeof(version_ctrs) / sizeof(u32);
|
||||||
|
static u8* ctr_start = NULL;
|
||||||
|
|
||||||
|
if (ctr_start == NULL) {
|
||||||
|
for (u32 i = 0; i < version_ctrs_len; i++) {
|
||||||
|
if (*(u32*)version_ctrs[i] == 0x5C980) {
|
||||||
|
Debug("System version %s", versions[i]);
|
||||||
|
ctr_start = (u8*) version_ctrs[i] + 0x30;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If value not in previous list start memory scanning (test range)
|
||||||
|
if (ctr_start == NULL) {
|
||||||
|
for (u8* c = (u8*) 0x080D8FFF; c > (u8*) 0x08000000; c--) {
|
||||||
|
if (*(u32*)c == 0x5C980 && *(u32*)(c + 1) == 0x800005C9) {
|
||||||
|
ctr_start = c + 0x30;
|
||||||
|
Debug("CTR start 0x%08X", ctr_start);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ctr_start == NULL) {
|
||||||
|
Debug("CTR start not found!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// the ctr is stored backwards in memory
|
||||||
|
if (offset >= 0x0B100000) { // CTRNAND/AGBSAVE region
|
||||||
|
for (u32 i = 0; i < 16; i++)
|
||||||
|
ctr[i] = *(ctr_start + (0xF - i));
|
||||||
|
} else { // TWL region
|
||||||
|
for (u32 i = 0; i < 16; i++)
|
||||||
|
ctr[i] = *(ctr_start + 0x88 + (0xF - i));
|
||||||
|
}
|
||||||
|
|
||||||
|
// increment counter
|
||||||
|
add_ctr(ctr, offset / 0x10);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 DecryptNandToMem(u8* buffer, u32 offset, u32 size, PartitionInfo* partition)
|
||||||
|
{
|
||||||
|
CryptBufferInfo info = {.keyslot = partition->keyslot, .setKeyY = 0, .size = size, .buffer = buffer, .mode = partition->mode};
|
||||||
|
if(GetNandCtr(info.ctr, offset) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u32 n_sectors = (size + NAND_SECTOR_SIZE - 1) / NAND_SECTOR_SIZE;
|
||||||
|
u32 start_sector = offset / NAND_SECTOR_SIZE;
|
||||||
|
ReadNandSectors(start_sector, n_sectors, buffer);
|
||||||
|
CryptBuffer(&info);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 DecryptNandToFile(const char* filename, u32 offset, u32 size, PartitionInfo* partition)
|
||||||
|
{
|
||||||
|
u8* buffer = BUFFER_ADDRESS;
|
||||||
|
u32 result = 0;
|
||||||
|
|
||||||
|
if (!DebugFileCreate(filename, true))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size; i += NAND_SECTOR_SIZE * SECTORS_PER_READ) {
|
||||||
|
u32 read_bytes = min(NAND_SECTOR_SIZE * SECTORS_PER_READ, (size - i));
|
||||||
|
ShowProgress(i, size);
|
||||||
|
DecryptNandToMem(buffer, offset + i, read_bytes, partition);
|
||||||
|
if(!DebugFileWrite(buffer, read_bytes, i)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowProgress(0, 0);
|
||||||
|
FileClose();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 DumpNand(u32 param)
|
||||||
|
{
|
||||||
|
char filename[64];
|
||||||
|
u8* buffer = BUFFER_ADDRESS;
|
||||||
|
u32 nand_size = getMMCDevice(0)->total_size * NAND_SECTOR_SIZE;
|
||||||
|
u32 result = 0;
|
||||||
|
|
||||||
|
Debug("Dumping %sNAND. Size (MB): %u", (param & N_EMUNAND) ? "Emu" : "Sys", nand_size / (1024 * 1024));
|
||||||
|
|
||||||
|
if (OutputFileNameSelector(filename, "NAND.bin", NULL) != 0)
|
||||||
|
return 1;
|
||||||
|
if (!DebugFileCreate(filename, true))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u32 n_sectors = nand_size / NAND_SECTOR_SIZE;
|
||||||
|
for (u32 i = 0; i < n_sectors; i += SECTORS_PER_READ) {
|
||||||
|
u32 read_sectors = min(SECTORS_PER_READ, (n_sectors - i));
|
||||||
|
ShowProgress(i, n_sectors);
|
||||||
|
ReadNandSectors(i, read_sectors, buffer);
|
||||||
|
if(!DebugFileWrite(buffer, NAND_SECTOR_SIZE * read_sectors, i * NAND_SECTOR_SIZE)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowProgress(0, 0);
|
||||||
|
FileClose();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 DecryptNandPartition(u32 param)
|
||||||
|
{
|
||||||
|
PartitionInfo* p_info = NULL;
|
||||||
|
char filename[64];
|
||||||
|
u8 magic[NAND_SECTOR_SIZE];
|
||||||
|
|
||||||
|
for (u32 partition_id = P_TWLN; partition_id <= P_CTRNAND; partition_id = partition_id << 1) {
|
||||||
|
if (param & partition_id) {
|
||||||
|
p_info = GetPartitionInfo(partition_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p_info == NULL) {
|
||||||
|
Debug("No partition to dump");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug("Dumping & Decrypting %s, size (MB): %u", p_info->name, p_info->size / (1024 * 1024));
|
||||||
|
if (DecryptNandToMem(magic, p_info->offset, 16, p_info) != 0)
|
||||||
|
return 1;
|
||||||
|
if ((p_info->magic[0] != 0xFF) && (memcmp(p_info->magic, magic, 8) != 0)) {
|
||||||
|
Debug("Decryption error, please contact us");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (OutputFileNameSelector(filename, p_info->name, "bin") != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
return DecryptNandToFile(filename, p_info->offset, p_info->size, p_info);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 EncryptMemToNand(u8* buffer, u32 offset, u32 size, PartitionInfo* partition)
|
||||||
|
{
|
||||||
|
CryptBufferInfo info = {.keyslot = partition->keyslot, .setKeyY = 0, .size = size, .buffer = buffer, .mode = partition->mode};
|
||||||
|
if(GetNandCtr(info.ctr, offset) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
u32 n_sectors = (size + NAND_SECTOR_SIZE - 1) / NAND_SECTOR_SIZE;
|
||||||
|
u32 start_sector = offset / NAND_SECTOR_SIZE;
|
||||||
|
CryptBuffer(&info);
|
||||||
|
WriteNandSectors(start_sector, n_sectors, buffer);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 EncryptFileToNand(const char* filename, u32 offset, u32 size, PartitionInfo* partition)
|
||||||
|
{
|
||||||
|
u8* buffer = BUFFER_ADDRESS;
|
||||||
|
u32 result = 0;
|
||||||
|
|
||||||
|
if (!DebugFileOpen(filename))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (FileGetSize() != size) {
|
||||||
|
Debug("%s has wrong size", filename);
|
||||||
|
FileClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 i = 0; i < size; i += NAND_SECTOR_SIZE * SECTORS_PER_READ) {
|
||||||
|
u32 read_bytes = min(NAND_SECTOR_SIZE * SECTORS_PER_READ, (size - i));
|
||||||
|
ShowProgress(i, size);
|
||||||
|
if(!DebugFileRead(buffer, read_bytes, i)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
EncryptMemToNand(buffer, offset + i, read_bytes, partition);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowProgress(0, 0);
|
||||||
|
FileClose();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 RestoreNand(u32 param)
|
||||||
|
{
|
||||||
|
char filename[64];
|
||||||
|
u8* buffer = BUFFER_ADDRESS;
|
||||||
|
u32 nand_size = getMMCDevice(0)->total_size * NAND_SECTOR_SIZE;
|
||||||
|
u32 result = 0;
|
||||||
|
u8 magic[4];
|
||||||
|
|
||||||
|
if (!(param & N_NANDWRITE)) // developer screwup protection
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// User file select
|
||||||
|
if (InputFileNameSelector(filename, "NAND.bin", NULL, NULL, 0, nand_size) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (!DebugFileOpen(filename))
|
||||||
|
return 1;
|
||||||
|
if (nand_size != FileGetSize()) {
|
||||||
|
FileClose();
|
||||||
|
Debug("NAND backup has the wrong size!");
|
||||||
|
return 1;
|
||||||
|
};
|
||||||
|
if(!DebugFileRead(magic, 4, 0x100)) {
|
||||||
|
FileClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (memcmp(magic, "NCSD", 4) != 0) {
|
||||||
|
FileClose();
|
||||||
|
Debug("Not a proper NAND backup!");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug("Restoring %sNAND. Size (MB): %u", (param & N_EMUNAND) ? "Emu" : "Sys", nand_size / (1024 * 1024));
|
||||||
|
|
||||||
|
u32 n_sectors = nand_size / NAND_SECTOR_SIZE;
|
||||||
|
for (u32 i = 0; i < n_sectors; i += SECTORS_PER_READ) {
|
||||||
|
u32 read_sectors = min(SECTORS_PER_READ, (n_sectors - i));
|
||||||
|
ShowProgress(i, n_sectors);
|
||||||
|
if(!DebugFileRead(buffer, NAND_SECTOR_SIZE * read_sectors, i * NAND_SECTOR_SIZE)) {
|
||||||
|
result = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
WriteNandSectors(i, read_sectors, buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
ShowProgress(0, 0);
|
||||||
|
FileClose();
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 InjectNandPartition(u32 param)
|
||||||
|
{
|
||||||
|
PartitionInfo* p_info = NULL;
|
||||||
|
char filename[64];
|
||||||
|
u8 magic[NAND_SECTOR_SIZE];
|
||||||
|
|
||||||
|
if (!(param & N_NANDWRITE)) // developer screwup protection
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
for (u32 partition_id = P_TWLN; partition_id <= P_CTRNAND; partition_id = partition_id << 1) {
|
||||||
|
if (param & partition_id) {
|
||||||
|
p_info = GetPartitionInfo(partition_id);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (p_info == NULL) {
|
||||||
|
Debug("No partition to inject to");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
Debug("Encrypting & Injecting %s, size (MB): %u", p_info->name, p_info->size / (1024 * 1024));
|
||||||
|
// User file select
|
||||||
|
if (InputFileNameSelector(filename, p_info->name, "bin",
|
||||||
|
p_info->magic, (p_info->magic[0] != 0xFF) ? 8 : 0, p_info->size) != 0)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
// Encryption check
|
||||||
|
if (DecryptNandToMem(magic, p_info->offset, 16, p_info) != 0)
|
||||||
|
return 1;
|
||||||
|
if ((p_info->magic[0] != 0xFF) && (memcmp(p_info->magic, magic, 8) != 0)) {
|
||||||
|
Debug("Decryption error, please contact us");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// File check
|
||||||
|
if (FileOpen(filename)) {
|
||||||
|
if(!DebugFileRead(magic, 8, 0)) {
|
||||||
|
FileClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if ((p_info->magic[0] != 0xFF) && (memcmp(p_info->magic, magic, 8) != 0)) {
|
||||||
|
Debug("Bad file content, won't inject");
|
||||||
|
FileClose();
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FileClose();
|
||||||
|
}
|
||||||
|
|
||||||
|
return EncryptFileToNand(filename, p_info->offset, p_info->size, p_info);
|
||||||
|
}
|
62
source/fatfs/crypto/nand.h
Normal file
62
source/fatfs/crypto/nand.h
Normal file
@ -0,0 +1,62 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define NAND_SECTOR_SIZE 0x200
|
||||||
|
#define SECTORS_PER_READ (BUFFER_MAX_SIZE / NAND_SECTOR_SIZE)
|
||||||
|
|
||||||
|
#define P_TWLN (1<<0)
|
||||||
|
#define P_TWLP (1<<1)
|
||||||
|
#define P_AGBSAVE (1<<2)
|
||||||
|
#define P_FIRM0 (1<<3)
|
||||||
|
#define P_FIRM1 (1<<4)
|
||||||
|
#define P_CTRNAND (1<<5)
|
||||||
|
|
||||||
|
// these three are not handled by the feature functions
|
||||||
|
// they have to be handled by the menu system
|
||||||
|
#define N_EMUNAND (1<<29)
|
||||||
|
#define N_FORCENAND (1<<30)
|
||||||
|
#define N_NANDWRITE (1<<31)
|
||||||
|
|
||||||
|
// return values for the CheckEmuNAND() function
|
||||||
|
#define EMUNAND_NOT_READY 0 // must be zero
|
||||||
|
#define EMUNAND_READY 1
|
||||||
|
#define EMUNAND_GATEWAY 2
|
||||||
|
#define EMUNAND_REDNAND 3
|
||||||
|
|
||||||
|
// these offsets are used by Multi EmuNAND Creator
|
||||||
|
#define EMUNAND_MULTI_OFFSET_O3DS 0x00200000
|
||||||
|
#define EMUNAND_MULTI_OFFSET_N3DS 0x00400000
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
char name[16];
|
||||||
|
u8 magic[8];
|
||||||
|
u32 offset;
|
||||||
|
u32 size;
|
||||||
|
u32 keyslot;
|
||||||
|
u32 mode;
|
||||||
|
} __attribute__((packed)) PartitionInfo;
|
||||||
|
|
||||||
|
PartitionInfo* GetPartitionInfo(u32 partition_id);
|
||||||
|
u32 GetNandCtr(u8* ctr, u32 offset);
|
||||||
|
|
||||||
|
u32 OutputFileNameSelector(char* filename, const char* basename, char* extension);
|
||||||
|
u32 InputFileNameSelector(char* filename, const char* basename, char* extension, u8* magic, u32 msize, u32 fsize);
|
||||||
|
|
||||||
|
u32 DecryptNandToMem(u8* buffer, u32 offset, u32 size, PartitionInfo* partition);
|
||||||
|
u32 DecryptNandToFile(const char* filename, u32 offset, u32 size, PartitionInfo* partition);
|
||||||
|
u32 EncryptMemToNand(u8* buffer, u32 offset, u32 size, PartitionInfo* partition);
|
||||||
|
u32 EncryptFileToNand(const char* filename, u32 offset, u32 size, PartitionInfo* partition);
|
||||||
|
|
||||||
|
// --> FEATURE FUNCTIONS <--
|
||||||
|
u32 CheckEmuNand(void);
|
||||||
|
u32 SetNand(bool set_emunand, bool force_emunand);
|
||||||
|
|
||||||
|
u32 CtrNandPadgen(u32 param);
|
||||||
|
u32 TwlNandPadgen(u32 param);
|
||||||
|
u32 Firm0Firm1Padgen(u32 param);
|
||||||
|
|
||||||
|
u32 DumpNand(u32 param);
|
||||||
|
u32 RestoreNand(u32 param);
|
||||||
|
u32 DecryptNandPartition(u32 param);
|
||||||
|
u32 InjectNandPartition(u32 param);
|
32
source/fatfs/crypto/sha.c
Normal file
32
source/fatfs/crypto/sha.c
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
#include "sha.h"
|
||||||
|
|
||||||
|
void sha_init(u32 mode)
|
||||||
|
{
|
||||||
|
while(*REG_SHACNT & 1);
|
||||||
|
*REG_SHACNT = mode | SHA_CNT_OUTPUT_ENDIAN | SHA_NORMAL_ROUND;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha_update(const void* src, u32 size)
|
||||||
|
{
|
||||||
|
const u32* src32 = (const u32*)src;
|
||||||
|
|
||||||
|
while(size >= 0x40) {
|
||||||
|
while(*REG_SHACNT & 1);
|
||||||
|
for(u32 i = 0; i < 4; i++) {
|
||||||
|
*REG_SHAINFIFO = *src32++;
|
||||||
|
*REG_SHAINFIFO = *src32++;
|
||||||
|
*REG_SHAINFIFO = *src32++;
|
||||||
|
*REG_SHAINFIFO = *src32++;
|
||||||
|
}
|
||||||
|
size -= 0x40;
|
||||||
|
}
|
||||||
|
while(*REG_SHACNT & 1);
|
||||||
|
memcpy((void*)REG_SHAINFIFO, src32, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
void sha_get(void* res) {
|
||||||
|
*REG_SHACNT = (*REG_SHACNT & ~SHA_NORMAL_ROUND) | SHA_FINAL_ROUND;
|
||||||
|
while(*REG_SHACNT & SHA_FINAL_ROUND);
|
||||||
|
while(*REG_SHACNT & 1);
|
||||||
|
memcpy(res, (void*)REG_SHAHASH, (256 / 8));
|
||||||
|
}
|
27
source/fatfs/crypto/sha.h
Normal file
27
source/fatfs/crypto/sha.h
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define REG_SHACNT ((volatile uint32_t*)0x1000A000)
|
||||||
|
#define REG_SHABLKCNT ((volatile uint32_t*)0x1000A004)
|
||||||
|
#define REG_SHAHASH ((volatile uint32_t*)0x1000A040)
|
||||||
|
#define REG_SHAINFIFO ((volatile uint32_t*)0x1000A080)
|
||||||
|
|
||||||
|
#define SHA_CNT_STATE 0x00000003
|
||||||
|
#define SHA_CNT_OUTPUT_ENDIAN 0x00000008
|
||||||
|
#define SHA_CNT_MODE 0x00000030
|
||||||
|
#define SHA_CNT_ENABLE 0x00010000
|
||||||
|
#define SHA_CNT_ACTIVE 0x00020000
|
||||||
|
|
||||||
|
#define SHA_HASH_READY 0x00000000
|
||||||
|
#define SHA_NORMAL_ROUND 0x00000001
|
||||||
|
#define SHA_FINAL_ROUND 0x00000002
|
||||||
|
|
||||||
|
#define SHA256_MODE 0
|
||||||
|
#define SHA224_MODE 0x00000010
|
||||||
|
#define SHA1_MODE 0x00000020
|
||||||
|
|
||||||
|
|
||||||
|
void sha_init(u32 mode);
|
||||||
|
void sha_update(const void* src, u32 size);
|
||||||
|
void sha_get(void* res);
|
15
source/fatfs/delay.s
Normal file
15
source/fatfs/delay.s
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
.arm
|
||||||
|
.global waitcycles
|
||||||
|
.type waitcycles STT_FUNC
|
||||||
|
|
||||||
|
@waitcycles ( u32 us )
|
||||||
|
waitcycles:
|
||||||
|
PUSH {R0-R2,LR}
|
||||||
|
STR R0, [SP,#4]
|
||||||
|
waitcycles_loop:
|
||||||
|
LDR R3, [SP,#4]
|
||||||
|
SUBS R2, R3, #1
|
||||||
|
STR R2, [SP,#4]
|
||||||
|
CMP R3, #0
|
||||||
|
BNE waitcycles_loop
|
||||||
|
POP {R0-R2,PC}
|
117
source/fatfs/diskio.c
Normal file
117
source/fatfs/diskio.c
Normal file
@ -0,0 +1,117 @@
|
|||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2014 */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* If a working storage control module is available, it should be */
|
||||||
|
/* attached to the FatFs via a glue function rather than modifying it. */
|
||||||
|
/* This is an example of glue functions to attach various exsisting */
|
||||||
|
/* storage control modules to the FatFs module with a defined API. */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#include "diskio.h" /* FatFs lower layer API */
|
||||||
|
#include "sdmmc.h"
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Get Drive Status */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DSTATUS disk_status (
|
||||||
|
__attribute__((unused))
|
||||||
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Inidialize a Drive */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DSTATUS disk_initialize (
|
||||||
|
__attribute__((unused))
|
||||||
|
BYTE pdrv /* Physical drive nmuber to identify the drive */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
sdmmc_sdcard_init();
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Read Sector(s) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
DRESULT disk_read (
|
||||||
|
__attribute__((unused))
|
||||||
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
|
BYTE *buff, /* Data buffer to store read data */
|
||||||
|
DWORD sector, /* Sector address in LBA */
|
||||||
|
UINT count /* Number of sectors to read */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (sdmmc_sdcard_readsectors(sector, count, buff)) {
|
||||||
|
return RES_PARERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Write Sector(s) */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if _USE_WRITE
|
||||||
|
DRESULT disk_write (
|
||||||
|
__attribute__((unused))
|
||||||
|
BYTE pdrv, /* Physical drive nmuber to identify the drive */
|
||||||
|
const BYTE *buff, /* Data to be written */
|
||||||
|
DWORD sector, /* Sector address in LBA */
|
||||||
|
UINT count /* Number of sectors to write */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
if (sdmmc_sdcard_writesectors(sector, count, (BYTE *)buff)) {
|
||||||
|
return RES_PARERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
/* Miscellaneous Functions */
|
||||||
|
/*-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#if _USE_IOCTL
|
||||||
|
DRESULT disk_ioctl (
|
||||||
|
__attribute__((unused))
|
||||||
|
BYTE pdrv, /* Physical drive nmuber (0..) */
|
||||||
|
__attribute__((unused))
|
||||||
|
BYTE cmd, /* Control code */
|
||||||
|
__attribute__((unused))
|
||||||
|
void *buff /* Buffer to send/receive control data */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
switch (cmd) {
|
||||||
|
case GET_SECTOR_SIZE:
|
||||||
|
*((DWORD*) buff) = 0x200;
|
||||||
|
return RES_OK;
|
||||||
|
case GET_SECTOR_COUNT:
|
||||||
|
*((DWORD*) buff) = getMMCDevice(1)->total_size;
|
||||||
|
return RES_OK;
|
||||||
|
case GET_BLOCK_SIZE:
|
||||||
|
*((DWORD*) buff) = 0x2000;
|
||||||
|
return RES_OK;
|
||||||
|
case CTRL_SYNC:
|
||||||
|
// nothing to do here - the disk_write function handles that
|
||||||
|
return RES_OK;
|
||||||
|
}
|
||||||
|
return RES_PARERR;
|
||||||
|
}
|
||||||
|
#endif
|
80
source/fatfs/diskio.h
Normal file
80
source/fatfs/diskio.h
Normal file
@ -0,0 +1,80 @@
|
|||||||
|
/*-----------------------------------------------------------------------/
|
||||||
|
/ Low level disk interface modlue include file (C)ChaN, 2014 /
|
||||||
|
/-----------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _DISKIO_DEFINED
|
||||||
|
#define _DISKIO_DEFINED
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define _USE_WRITE 1 /* 1: Enable disk_write function */
|
||||||
|
#define _USE_IOCTL 1 /* 1: Enable disk_ioctl fucntion */
|
||||||
|
|
||||||
|
#include "integer.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Status of Disk Functions */
|
||||||
|
typedef BYTE DSTATUS;
|
||||||
|
|
||||||
|
/* Results of Disk Functions */
|
||||||
|
typedef enum {
|
||||||
|
RES_OK = 0, /* 0: Successful */
|
||||||
|
RES_ERROR, /* 1: R/W Error */
|
||||||
|
RES_WRPRT, /* 2: Write Protected */
|
||||||
|
RES_NOTRDY, /* 3: Not Ready */
|
||||||
|
RES_PARERR /* 4: Invalid Parameter */
|
||||||
|
} DRESULT;
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------*/
|
||||||
|
/* Prototypes for disk control functions */
|
||||||
|
|
||||||
|
|
||||||
|
DSTATUS disk_initialize (BYTE pdrv);
|
||||||
|
DSTATUS disk_status (BYTE pdrv);
|
||||||
|
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_ioctl (BYTE pdrv, BYTE cmd, void* buff);
|
||||||
|
|
||||||
|
|
||||||
|
/* Disk Status Bits (DSTATUS) */
|
||||||
|
|
||||||
|
#define STA_NOINIT 0x01 /* Drive not initialized */
|
||||||
|
#define STA_NODISK 0x02 /* No medium in the drive */
|
||||||
|
#define STA_PROTECT 0x04 /* Write protected */
|
||||||
|
|
||||||
|
|
||||||
|
/* Command code for disk_ioctrl fucntion */
|
||||||
|
|
||||||
|
/* Generic command (Used by FatFs) */
|
||||||
|
#define CTRL_SYNC 0 /* Complete pending write process (needed at _FS_READONLY == 0) */
|
||||||
|
#define GET_SECTOR_COUNT 1 /* Get media size (needed at _USE_MKFS == 1) */
|
||||||
|
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at _MAX_SS != _MIN_SS) */
|
||||||
|
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at _USE_MKFS == 1) */
|
||||||
|
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at _USE_TRIM == 1) */
|
||||||
|
|
||||||
|
/* Generic command (Not used by FatFs) */
|
||||||
|
#define CTRL_POWER 5 /* Get/Set power status */
|
||||||
|
#define CTRL_LOCK 6 /* Lock/Unlock media removal */
|
||||||
|
#define CTRL_EJECT 7 /* Eject media */
|
||||||
|
#define CTRL_FORMAT 8 /* Create physical format on the media */
|
||||||
|
|
||||||
|
/* MMC/SDC specific ioctl command */
|
||||||
|
#define MMC_GET_TYPE 10 /* Get card type */
|
||||||
|
#define MMC_GET_CSD 11 /* Get CSD */
|
||||||
|
#define MMC_GET_CID 12 /* Get CID */
|
||||||
|
#define MMC_GET_OCR 13 /* Get OCR */
|
||||||
|
#define MMC_GET_SDSTAT 14 /* Get SD status */
|
||||||
|
|
||||||
|
/* ATA/CF specific ioctl command */
|
||||||
|
#define ATA_GET_REV 20 /* Get F/W revision */
|
||||||
|
#define ATA_GET_MODEL 21 /* Get model name */
|
||||||
|
#define ATA_GET_SN 22 /* Get serial number */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
4694
source/fatfs/ff.c
Normal file
4694
source/fatfs/ff.c
Normal file
File diff suppressed because it is too large
Load Diff
350
source/fatfs/ff.h
Normal file
350
source/fatfs/ff.h
Normal file
@ -0,0 +1,350 @@
|
|||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ FatFs - FAT file system module include R0.11 (C)ChaN, 2015
|
||||||
|
/----------------------------------------------------------------------------/
|
||||||
|
/ FatFs module is a free software that opened under license policy of
|
||||||
|
/ following conditions.
|
||||||
|
/
|
||||||
|
/ Copyright (C) 2015, ChaN, all right reserved.
|
||||||
|
/
|
||||||
|
/ 1. Redistributions of source code must retain the above copyright notice,
|
||||||
|
/ this condition and the following disclaimer.
|
||||||
|
/
|
||||||
|
/ This software is provided by the copyright holder and contributors "AS IS"
|
||||||
|
/ and any warranties related to this software are DISCLAIMED.
|
||||||
|
/ The copyright owner or contributors be NOT LIABLE for any damages caused
|
||||||
|
/ by use of this software.
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#ifndef _FATFS
|
||||||
|
#define _FATFS 32020 /* Revision ID */
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "integer.h" /* Basic integer types */
|
||||||
|
#include "ffconf.h" /* FatFs configuration options */
|
||||||
|
#if _FATFS != _FFCONF
|
||||||
|
#error Wrong configuration file (ffconf.h).
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Definitions of volume management */
|
||||||
|
|
||||||
|
#if _MULTI_PARTITION /* Multiple partition configuration */
|
||||||
|
typedef struct {
|
||||||
|
BYTE pd; /* Physical drive number */
|
||||||
|
BYTE pt; /* Partition: 0:Auto detect, 1-4:Forced partition) */
|
||||||
|
} PARTITION;
|
||||||
|
extern PARTITION VolToPart[]; /* Volume - Partition resolution table */
|
||||||
|
#define LD2PD(vol) (VolToPart[vol].pd) /* Get physical drive number */
|
||||||
|
#define LD2PT(vol) (VolToPart[vol].pt) /* Get partition index */
|
||||||
|
|
||||||
|
#else /* Single partition configuration */
|
||||||
|
#define LD2PD(vol) (BYTE)(vol) /* Each logical drive is bound to the same physical drive number */
|
||||||
|
#define LD2PT(vol) 0 /* Find first valid partition or in SFD */
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Type of path name strings on FatFs API */
|
||||||
|
|
||||||
|
#if _LFN_UNICODE /* Unicode string */
|
||||||
|
#if !_USE_LFN
|
||||||
|
#error _LFN_UNICODE must be 0 at non-LFN cfg.
|
||||||
|
#endif
|
||||||
|
#ifndef _INC_TCHAR
|
||||||
|
typedef WCHAR TCHAR;
|
||||||
|
#define _T(x) L ## x
|
||||||
|
#define _TEXT(x) L ## x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#else /* ANSI/OEM string */
|
||||||
|
#ifndef _INC_TCHAR
|
||||||
|
typedef char TCHAR;
|
||||||
|
#define _T(x) x
|
||||||
|
#define _TEXT(x) x
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* File system object structure (FATFS) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
BYTE fs_type; /* FAT sub-type (0:Not mounted) */
|
||||||
|
BYTE drv; /* Physical drive number */
|
||||||
|
BYTE csize; /* Sectors per cluster (1,2,4...128) */
|
||||||
|
BYTE n_fats; /* Number of FAT copies (1 or 2) */
|
||||||
|
BYTE wflag; /* win[] flag (b0:dirty) */
|
||||||
|
BYTE fsi_flag; /* FSINFO flags (b7:disabled, b0:dirty) */
|
||||||
|
WORD id; /* File system mount ID */
|
||||||
|
WORD n_rootdir; /* Number of root directory entries (FAT12/16) */
|
||||||
|
#if _MAX_SS != _MIN_SS
|
||||||
|
WORD ssize; /* Bytes per sector (512, 1024, 2048 or 4096) */
|
||||||
|
#endif
|
||||||
|
#if _FS_REENTRANT
|
||||||
|
_SYNC_t sobj; /* Identifier of sync object */
|
||||||
|
#endif
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD last_clust; /* Last allocated cluster */
|
||||||
|
DWORD free_clust; /* Number of free clusters */
|
||||||
|
#endif
|
||||||
|
#if _FS_RPATH
|
||||||
|
DWORD cdir; /* Current directory start cluster (0:root) */
|
||||||
|
#endif
|
||||||
|
DWORD n_fatent; /* Number of FAT entries, = number of clusters + 2 */
|
||||||
|
DWORD fsize; /* Sectors per FAT */
|
||||||
|
DWORD volbase; /* Volume start sector */
|
||||||
|
DWORD fatbase; /* FAT start sector */
|
||||||
|
DWORD dirbase; /* Root directory start sector (FAT32:Cluster#) */
|
||||||
|
DWORD database; /* Data start sector */
|
||||||
|
DWORD winsect; /* Current sector appearing in the win[] */
|
||||||
|
BYTE win[_MAX_SS]; /* Disk access window for Directory, FAT (and file data at tiny cfg) */
|
||||||
|
} FATFS;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* File object structure (FIL) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FATFS* fs; /* Pointer to the related file system object (**do not change order**) */
|
||||||
|
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||||
|
BYTE flag; /* Status flags */
|
||||||
|
BYTE err; /* Abort flag (error code) */
|
||||||
|
DWORD fptr; /* File read/write pointer (Zeroed on file open) */
|
||||||
|
DWORD fsize; /* File size */
|
||||||
|
DWORD sclust; /* File start cluster (0:no cluster chain, always 0 when fsize is 0) */
|
||||||
|
DWORD clust; /* Current cluster of fpter (not valid when fprt is 0) */
|
||||||
|
DWORD dsect; /* Sector number appearing in buf[] (0:invalid) */
|
||||||
|
#if !_FS_READONLY
|
||||||
|
DWORD dir_sect; /* Sector number containing the directory entry */
|
||||||
|
BYTE* dir_ptr; /* Pointer to the directory entry in the win[] */
|
||||||
|
#endif
|
||||||
|
#if _USE_FASTSEEK
|
||||||
|
DWORD* cltbl; /* Pointer to the cluster link map table (Nulled on file open) */
|
||||||
|
#endif
|
||||||
|
#if _FS_LOCK
|
||||||
|
UINT lockid; /* File lock ID origin from 1 (index of file semaphore table Files[]) */
|
||||||
|
#endif
|
||||||
|
#if !_FS_TINY
|
||||||
|
BYTE buf[_MAX_SS]; /* File private data read/write window */
|
||||||
|
#endif
|
||||||
|
} FIL;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* Directory object structure (DIR) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
FATFS* fs; /* Pointer to the owner file system object (**do not change order**) */
|
||||||
|
WORD id; /* Owner file system mount ID (**do not change order**) */
|
||||||
|
WORD index; /* Current read/write index number */
|
||||||
|
DWORD sclust; /* Table start cluster (0:Root dir) */
|
||||||
|
DWORD clust; /* Current cluster */
|
||||||
|
DWORD sect; /* Current sector */
|
||||||
|
BYTE* dir; /* Pointer to the current SFN entry in the win[] */
|
||||||
|
BYTE* fn; /* Pointer to the SFN (in/out) {file[8],ext[3],status[1]} */
|
||||||
|
#if _FS_LOCK
|
||||||
|
UINT lockid; /* File lock ID (index of file semaphore table Files[]) */
|
||||||
|
#endif
|
||||||
|
#if _USE_LFN
|
||||||
|
WCHAR* lfn; /* Pointer to the LFN working buffer */
|
||||||
|
WORD lfn_idx; /* Last matched LFN index number (0xFFFF:No LFN) */
|
||||||
|
#endif
|
||||||
|
#if _USE_FIND
|
||||||
|
const TCHAR* pat; /* Pointer to the name matching pattern */
|
||||||
|
#endif
|
||||||
|
} DIR;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* File information structure (FILINFO) */
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
DWORD fsize; /* File size */
|
||||||
|
WORD fdate; /* Last modified date */
|
||||||
|
WORD ftime; /* Last modified time */
|
||||||
|
BYTE fattrib; /* Attribute */
|
||||||
|
TCHAR fname[13]; /* Short file name (8.3 format) */
|
||||||
|
#if _USE_LFN
|
||||||
|
TCHAR* lfname; /* Pointer to the LFN buffer */
|
||||||
|
UINT lfsize; /* Size of LFN buffer in TCHAR */
|
||||||
|
#endif
|
||||||
|
} FILINFO;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/* File function return code (FRESULT) */
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
FR_OK = 0, /* (0) Succeeded */
|
||||||
|
FR_DISK_ERR, /* (1) A hard error occurred in the low level disk I/O layer */
|
||||||
|
FR_INT_ERR, /* (2) Assertion failed */
|
||||||
|
FR_NOT_READY, /* (3) The physical drive cannot work */
|
||||||
|
FR_NO_FILE, /* (4) Could not find the file */
|
||||||
|
FR_NO_PATH, /* (5) Could not find the path */
|
||||||
|
FR_INVALID_NAME, /* (6) The path name format is invalid */
|
||||||
|
FR_DENIED, /* (7) Access denied due to prohibited access or directory full */
|
||||||
|
FR_EXIST, /* (8) Access denied due to prohibited access */
|
||||||
|
FR_INVALID_OBJECT, /* (9) The file/directory object is invalid */
|
||||||
|
FR_WRITE_PROTECTED, /* (10) The physical drive is write protected */
|
||||||
|
FR_INVALID_DRIVE, /* (11) The logical drive number is invalid */
|
||||||
|
FR_NOT_ENABLED, /* (12) The volume has no work area */
|
||||||
|
FR_NO_FILESYSTEM, /* (13) There is no valid FAT volume */
|
||||||
|
FR_MKFS_ABORTED, /* (14) The f_mkfs() aborted due to any parameter error */
|
||||||
|
FR_TIMEOUT, /* (15) Could not get a grant to access the volume within defined period */
|
||||||
|
FR_LOCKED, /* (16) The operation is rejected according to the file sharing policy */
|
||||||
|
FR_NOT_ENOUGH_CORE, /* (17) LFN working buffer could not be allocated */
|
||||||
|
FR_TOO_MANY_OPEN_FILES, /* (18) Number of open files > _FS_SHARE */
|
||||||
|
FR_INVALID_PARAMETER /* (19) Given parameter is invalid */
|
||||||
|
} FRESULT;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* FatFs module application interface */
|
||||||
|
|
||||||
|
FRESULT f_open (FIL* fp, const TCHAR* path, BYTE mode); /* Open or create a file */
|
||||||
|
FRESULT f_close (FIL* fp); /* Close an open file object */
|
||||||
|
FRESULT f_read (FIL* fp, void* buff, UINT btr, UINT* br); /* Read data from a file */
|
||||||
|
FRESULT f_write (FIL* fp, const void* buff, UINT btw, UINT* bw); /* Write data to a file */
|
||||||
|
FRESULT f_forward (FIL* fp, UINT(*func)(const BYTE*,UINT), UINT btf, UINT* bf); /* Forward data to the stream */
|
||||||
|
FRESULT f_lseek (FIL* fp, DWORD ofs); /* Move file pointer of a file object */
|
||||||
|
FRESULT f_truncate (FIL* fp); /* Truncate file */
|
||||||
|
FRESULT f_sync (FIL* fp); /* Flush cached data of a writing file */
|
||||||
|
FRESULT f_opendir (DIR* dp, const TCHAR* path); /* Open a directory */
|
||||||
|
FRESULT f_closedir (DIR* dp); /* Close an open directory */
|
||||||
|
FRESULT f_readdir (DIR* dp, FILINFO* fno); /* Read a directory item */
|
||||||
|
FRESULT f_findfirst (DIR* dp, FILINFO* fno, const TCHAR* path, const TCHAR* pattern); /* Find first file */
|
||||||
|
FRESULT f_findnext (DIR* dp, FILINFO* fno); /* Find next file */
|
||||||
|
FRESULT f_mkdir (const TCHAR* path); /* Create a sub directory */
|
||||||
|
FRESULT f_unlink (const TCHAR* path); /* Delete an existing file or directory */
|
||||||
|
FRESULT f_rename (const TCHAR* path_old, const TCHAR* path_new); /* Rename/Move a file or directory */
|
||||||
|
FRESULT f_stat (const TCHAR* path, FILINFO* fno); /* Get file status */
|
||||||
|
FRESULT f_chmod (const TCHAR* path, BYTE attr, BYTE mask); /* Change attribute of the file/dir */
|
||||||
|
FRESULT f_utime (const TCHAR* path, const FILINFO* fno); /* Change times-tamp of the file/dir */
|
||||||
|
FRESULT f_chdir (const TCHAR* path); /* Change current directory */
|
||||||
|
FRESULT f_chdrive (const TCHAR* path); /* Change current drive */
|
||||||
|
FRESULT f_getcwd (TCHAR* buff, UINT len); /* Get current directory */
|
||||||
|
FRESULT f_getfree (const TCHAR* path, DWORD* nclst, FATFS** fatfs); /* Get number of free clusters on the drive */
|
||||||
|
FRESULT f_getlabel (const TCHAR* path, TCHAR* label, DWORD* vsn); /* Get volume label */
|
||||||
|
FRESULT f_setlabel (const TCHAR* label); /* Set volume label */
|
||||||
|
FRESULT f_mount (FATFS* fs, const TCHAR* path, BYTE opt); /* Mount/Unmount a logical drive */
|
||||||
|
FRESULT f_mkfs (const TCHAR* path, BYTE sfd, UINT au); /* Create a file system on the volume */
|
||||||
|
FRESULT f_fdisk (BYTE pdrv, const DWORD szt[], void* work); /* Divide a physical drive into some partitions */
|
||||||
|
int f_putc (TCHAR c, FIL* fp); /* Put a character to the file */
|
||||||
|
int f_puts (const TCHAR* str, FIL* cp); /* Put a string to the file */
|
||||||
|
int f_printf (FIL* fp, const TCHAR* str, ...); /* Put a formatted string to the file */
|
||||||
|
TCHAR* f_gets (TCHAR* buff, int len, FIL* fp); /* Get a string from the file */
|
||||||
|
|
||||||
|
#define f_eof(fp) ((int)((fp)->fptr == (fp)->fsize))
|
||||||
|
#define f_error(fp) ((fp)->err)
|
||||||
|
#define f_tell(fp) ((fp)->fptr)
|
||||||
|
#define f_size(fp) ((fp)->fsize)
|
||||||
|
#define f_rewind(fp) f_lseek((fp), 0)
|
||||||
|
#define f_rewinddir(dp) f_readdir((dp), 0)
|
||||||
|
|
||||||
|
#ifndef EOF
|
||||||
|
#define EOF (-1)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Additional user defined functions */
|
||||||
|
|
||||||
|
/* RTC function */
|
||||||
|
#if !_FS_READONLY && !_FS_NORTC
|
||||||
|
DWORD get_fattime (void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Unicode support functions */
|
||||||
|
#if _USE_LFN /* Unicode - OEM code conversion */
|
||||||
|
WCHAR ff_convert (WCHAR chr, UINT dir); /* OEM-Unicode bidirectional conversion */
|
||||||
|
WCHAR ff_wtoupper (WCHAR chr); /* Unicode upper-case conversion */
|
||||||
|
#if _USE_LFN == 3 /* Memory functions */
|
||||||
|
void* ff_memalloc (UINT msize); /* Allocate memory block */
|
||||||
|
void ff_memfree (void* mblock); /* Free memory block */
|
||||||
|
#endif
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* Sync functions */
|
||||||
|
#if _FS_REENTRANT
|
||||||
|
int ff_cre_syncobj (BYTE vol, _SYNC_t* sobj); /* Create a sync object */
|
||||||
|
int ff_req_grant (_SYNC_t sobj); /* Lock sync object */
|
||||||
|
void ff_rel_grant (_SYNC_t sobj); /* Unlock sync object */
|
||||||
|
int ff_del_syncobj (_SYNC_t sobj); /* Delete a sync object */
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------------------------------------*/
|
||||||
|
/* Flags and offset address */
|
||||||
|
|
||||||
|
|
||||||
|
/* File access control and file status flags (FIL.flag) */
|
||||||
|
|
||||||
|
#define FA_READ 0x01
|
||||||
|
#define FA_OPEN_EXISTING 0x00
|
||||||
|
|
||||||
|
#if !_FS_READONLY
|
||||||
|
#define FA_WRITE 0x02
|
||||||
|
#define FA_CREATE_NEW 0x04
|
||||||
|
#define FA_CREATE_ALWAYS 0x08
|
||||||
|
#define FA_OPEN_ALWAYS 0x10
|
||||||
|
#define FA__WRITTEN 0x20
|
||||||
|
#define FA__DIRTY 0x40
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* FAT sub type (FATFS.fs_type) */
|
||||||
|
|
||||||
|
#define FS_FAT12 1
|
||||||
|
#define FS_FAT16 2
|
||||||
|
#define FS_FAT32 3
|
||||||
|
|
||||||
|
|
||||||
|
/* File attribute bits for directory entry */
|
||||||
|
|
||||||
|
#define AM_RDO 0x01 /* Read only */
|
||||||
|
#define AM_HID 0x02 /* Hidden */
|
||||||
|
#define AM_SYS 0x04 /* System */
|
||||||
|
#define AM_VOL 0x08 /* Volume label */
|
||||||
|
#define AM_LFN 0x0F /* LFN entry */
|
||||||
|
#define AM_DIR 0x10 /* Directory */
|
||||||
|
#define AM_ARC 0x20 /* Archive */
|
||||||
|
#define AM_MASK 0x3F /* Mask of defined bits */
|
||||||
|
|
||||||
|
|
||||||
|
/* Fast seek feature */
|
||||||
|
#define CREATE_LINKMAP 0xFFFFFFFF
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*--------------------------------*/
|
||||||
|
/* Multi-byte word access macros */
|
||||||
|
|
||||||
|
#if _WORD_ACCESS == 1 /* Enable word access to the FAT structure */
|
||||||
|
#define LD_WORD(ptr) (WORD)(*(WORD*)(BYTE*)(ptr))
|
||||||
|
#define LD_DWORD(ptr) (DWORD)(*(DWORD*)(BYTE*)(ptr))
|
||||||
|
#define ST_WORD(ptr,val) *(WORD*)(BYTE*)(ptr)=(WORD)(val)
|
||||||
|
#define ST_DWORD(ptr,val) *(DWORD*)(BYTE*)(ptr)=(DWORD)(val)
|
||||||
|
#else /* Use byte-by-byte access to the FAT structure */
|
||||||
|
#define LD_WORD(ptr) (WORD)(((WORD)*((BYTE*)(ptr)+1)<<8)|(WORD)*(BYTE*)(ptr))
|
||||||
|
#define LD_DWORD(ptr) (DWORD)(((DWORD)*((BYTE*)(ptr)+3)<<24)|((DWORD)*((BYTE*)(ptr)+2)<<16)|((WORD)*((BYTE*)(ptr)+1)<<8)|*(BYTE*)(ptr))
|
||||||
|
#define ST_WORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8)
|
||||||
|
#define ST_DWORD(ptr,val) *(BYTE*)(ptr)=(BYTE)(val); *((BYTE*)(ptr)+1)=(BYTE)((WORD)(val)>>8); *((BYTE*)(ptr)+2)=(BYTE)((DWORD)(val)>>16); *((BYTE*)(ptr)+3)=(BYTE)((DWORD)(val)>>24)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* _FATFS */
|
271
source/fatfs/ffconf.h
Normal file
271
source/fatfs/ffconf.h
Normal file
@ -0,0 +1,271 @@
|
|||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ FatFs - FAT file system module configuration file R0.11 (C)ChaN, 2015
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _FFCONF 32020 /* Revision ID */
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ Functions and Buffer Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _FS_TINY 0
|
||||||
|
/* This option switches tiny buffer configuration. (0:Normal or 1:Tiny)
|
||||||
|
/ At the tiny configuration, size of the file object (FIL) is reduced _MAX_SS
|
||||||
|
/ bytes. Instead of private sector buffer eliminated from the file object,
|
||||||
|
/ common sector buffer in the file system object (FATFS) is used for the file
|
||||||
|
/ data transfer. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_READONLY 0
|
||||||
|
/* This option switches read-only configuration. (0:Read/Write or 1:Read-only)
|
||||||
|
/ Read-only configuration removes writing API functions, f_write(), f_sync(),
|
||||||
|
/ f_unlink(), f_mkdir(), f_chmod(), f_rename(), f_truncate(), f_getfree()
|
||||||
|
/ and optional writing functions as well. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_MINIMIZE 0
|
||||||
|
/* This option defines minimization level to remove some basic API functions.
|
||||||
|
/
|
||||||
|
/ 0: All basic functions are enabled.
|
||||||
|
/ 1: f_stat(), f_getfree(), f_unlink(), f_mkdir(), f_chmod(), f_utime(),
|
||||||
|
/ f_truncate() and f_rename() function are removed.
|
||||||
|
/ 2: f_opendir(), f_readdir() and f_closedir() are removed in addition to 1.
|
||||||
|
/ 3: f_lseek() function is removed in addition to 2. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_STRFUNC 0
|
||||||
|
/* This option switches string functions, f_gets(), f_putc(), f_puts() and
|
||||||
|
/ f_printf().
|
||||||
|
/
|
||||||
|
/ 0: Disable string functions.
|
||||||
|
/ 1: Enable without LF-CRLF conversion.
|
||||||
|
/ 2: Enable with LF-CRLF conversion. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_FIND 0
|
||||||
|
/* This option switches filtered directory read feature and related functions,
|
||||||
|
/ f_findfirst() and f_findnext(). (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_MKFS 0
|
||||||
|
/* This option switches f_mkfs() function. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_FASTSEEK 0
|
||||||
|
/* This option switches fast seek feature. (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_LABEL 0
|
||||||
|
/* This option switches volume label functions, f_getlabel() and f_setlabel().
|
||||||
|
/ (0:Disable or 1:Enable) */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_FORWARD 0
|
||||||
|
/* This option switches f_forward() function. (0:Disable or 1:Enable)
|
||||||
|
/ To enable it, also _FS_TINY need to be set to 1. */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ Locale and Namespace Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _CODE_PAGE 437
|
||||||
|
/* This option specifies the OEM code page to be used on the target system.
|
||||||
|
/ Incorrect setting of the code page can cause a file open failure.
|
||||||
|
/
|
||||||
|
/ 1 - ASCII (No extended character. Non-LFN cfg. only)
|
||||||
|
/ 437 - U.S.
|
||||||
|
/ 720 - Arabic
|
||||||
|
/ 737 - Greek
|
||||||
|
/ 775 - Baltic
|
||||||
|
/ 850 - Multilingual Latin 1
|
||||||
|
/ 852 - Latin 2
|
||||||
|
/ 855 - Cyrillic
|
||||||
|
/ 857 - Turkish
|
||||||
|
/ 858 - Multilingual Latin 1 + Euro
|
||||||
|
/ 862 - Hebrew
|
||||||
|
/ 866 - Russian
|
||||||
|
/ 874 - Thai
|
||||||
|
/ 932 - Japanese Shift_JIS (DBCS)
|
||||||
|
/ 936 - Simplified Chinese GBK (DBCS)
|
||||||
|
/ 949 - Korean (DBCS)
|
||||||
|
/ 950 - Traditional Chinese Big5 (DBCS)
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_LFN 2
|
||||||
|
#define _MAX_LFN 255
|
||||||
|
/* The _USE_LFN option switches the LFN feature.
|
||||||
|
/
|
||||||
|
/ 0: Disable LFN feature. _MAX_LFN has no effect.
|
||||||
|
/ 1: Enable LFN with static working buffer on the BSS. Always NOT thread-safe.
|
||||||
|
/ 2: Enable LFN with dynamic working buffer on the STACK.
|
||||||
|
/ 3: Enable LFN with dynamic working buffer on the HEAP.
|
||||||
|
/
|
||||||
|
/ When enable the LFN feature, Unicode handling functions (option/unicode.c) must
|
||||||
|
/ be added to the project. The LFN working buffer occupies (_MAX_LFN + 1) * 2 bytes.
|
||||||
|
/ 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
|
||||||
|
/ ff_memfree(), must be added to the project. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _LFN_UNICODE 0
|
||||||
|
/* This option switches character encoding on the API. (0:ANSI/OEM or 1:Unicode)
|
||||||
|
/ To use Unicode string for the path name, enable LFN feature and set _LFN_UNICODE
|
||||||
|
/ to 1. This option also affects behavior of string I/O functions. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _STRF_ENCODE 0
|
||||||
|
/* When _LFN_UNICODE is 1, this option selects the character encoding on the file to
|
||||||
|
/ be read/written via string I/O functions, f_gets(), f_putc(), f_puts and f_printf().
|
||||||
|
/
|
||||||
|
/ 0: ANSI/OEM
|
||||||
|
/ 1: UTF-16LE
|
||||||
|
/ 2: UTF-16BE
|
||||||
|
/ 3: UTF-8
|
||||||
|
/
|
||||||
|
/ When _LFN_UNICODE is 0, this option has no effect. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_RPATH 1
|
||||||
|
/* This option configures relative path feature.
|
||||||
|
/
|
||||||
|
/ 0: Disable relative path feature and remove related functions.
|
||||||
|
/ 1: Enable relative path feature. f_chdir() and f_chdrive() are available.
|
||||||
|
/ 2: f_getcwd() function is available in addition to 1.
|
||||||
|
/
|
||||||
|
/ Note that directory items read via f_readdir() are affected by this option. */
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ Drive/Volume Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _VOLUMES 1
|
||||||
|
/* Number of volumes (logical drives) to be used. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _STR_VOLUME_ID 0
|
||||||
|
#define _VOLUME_STRS "RAM","NAND","CF","SD1","SD2","USB1","USB2","USB3"
|
||||||
|
/* _STR_VOLUME_ID option switches string volume ID feature.
|
||||||
|
/ When _STR_VOLUME_ID is set to 1, also pre-defined strings can be used as drive
|
||||||
|
/ number in the path name. _VOLUME_STRS defines the drive ID strings for each
|
||||||
|
/ logical drives. Number of items must be equal to _VOLUMES. Valid characters for
|
||||||
|
/ the drive ID strings are: A-Z and 0-9. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _MULTI_PARTITION 0
|
||||||
|
/* This option switches multi-partition feature. By default (0), each logical drive
|
||||||
|
/ number is bound to the same physical drive number and only an FAT volume found on
|
||||||
|
/ the physical drive will be mounted. When multi-partition feature is enabled (1),
|
||||||
|
/ each logical drive number is bound to arbitrary physical drive and partition
|
||||||
|
/ listed in the VolToPart[]. Also f_fdisk() funciton will be available. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _MIN_SS 512
|
||||||
|
#define _MAX_SS 512
|
||||||
|
/* These options configure the range of sector size to be supported. (512, 1024,
|
||||||
|
/ 2048 or 4096) Always set both 512 for most systems, all type of memory cards and
|
||||||
|
/ harddisk. But a larger value may be required for on-board flash memory and some
|
||||||
|
/ type of optical media. When _MAX_SS is larger than _MIN_SS, FatFs is configured
|
||||||
|
/ to variable sector size and GET_SECTOR_SIZE command must be implemented to the
|
||||||
|
/ disk_ioctl() function. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _USE_TRIM 0
|
||||||
|
/* This option switches ATA-TRIM feature. (0:Disable or 1:Enable)
|
||||||
|
/ To enable Trim feature, also CTRL_TRIM command should be implemented to the
|
||||||
|
/ disk_ioctl() function. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_NOFSINFO 0
|
||||||
|
/* If you need to know correct free space on the FAT32 volume, set bit 0 of this
|
||||||
|
/ option, and f_getfree() function at first time after volume mount will force
|
||||||
|
/ a full FAT scan. Bit 1 controls the use of last allocated cluster number.
|
||||||
|
/
|
||||||
|
/ bit0=0: Use free cluster count in the FSINFO if available.
|
||||||
|
/ bit0=1: Do not trust free cluster count in the FSINFO.
|
||||||
|
/ bit1=0: Use last allocated cluster number in the FSINFO if available.
|
||||||
|
/ bit1=1: Do not trust last allocated cluster number in the FSINFO.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*---------------------------------------------------------------------------/
|
||||||
|
/ System Configurations
|
||||||
|
/---------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
#define _FS_NORTC 1
|
||||||
|
#define _NORTC_MON 2
|
||||||
|
#define _NORTC_MDAY 1
|
||||||
|
#define _NORTC_YEAR 2015
|
||||||
|
/* The _FS_NORTC option switches timestamp feature. If the system does not have
|
||||||
|
/ an RTC function or valid timestamp is not needed, set _FS_NORTC to 1 to disable
|
||||||
|
/ the timestamp feature. All objects modified by FatFs will have a fixed timestamp
|
||||||
|
/ defined by _NORTC_MON, _NORTC_MDAY and _NORTC_YEAR.
|
||||||
|
/ When timestamp feature is enabled (_FS_NORTC == 0), get_fattime() function need
|
||||||
|
/ to be added to the project to read current time form RTC. _NORTC_MON,
|
||||||
|
/ _NORTC_MDAY and _NORTC_YEAR have no effect.
|
||||||
|
/ These options have no effect at read-only configuration (_FS_READONLY == 1). */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_LOCK 0
|
||||||
|
/* The _FS_LOCK option switches file lock feature to control duplicated file open
|
||||||
|
/ and illegal operation to open objects. This option must be 0 when _FS_READONLY
|
||||||
|
/ is 1.
|
||||||
|
/
|
||||||
|
/ 0: Disable file lock feature. To avoid volume corruption, application program
|
||||||
|
/ should avoid illegal open, remove and rename to the open objects.
|
||||||
|
/ >0: Enable file lock feature. The value defines how many files/sub-directories
|
||||||
|
/ can be opened simultaneously under file lock control. Note that the file
|
||||||
|
/ lock feature is independent of re-entrancy. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _FS_REENTRANT 0
|
||||||
|
#define _FS_TIMEOUT 1000
|
||||||
|
#define _SYNC_t HANDLE
|
||||||
|
/* The _FS_REENTRANT option switches the re-entrancy (thread safe) of the FatFs
|
||||||
|
/ module itself. Note that regardless of this option, file access to different
|
||||||
|
/ volume is always re-entrant and volume control functions, f_mount(), f_mkfs()
|
||||||
|
/ and f_fdisk() function, are always not re-entrant. Only file/directory access
|
||||||
|
/ to the same volume is under control of this feature.
|
||||||
|
/
|
||||||
|
/ 0: Disable re-entrancy. _FS_TIMEOUT and _SYNC_t have no effect.
|
||||||
|
/ 1: Enable re-entrancy. Also user provided synchronization handlers,
|
||||||
|
/ ff_req_grant(), ff_rel_grant(), ff_del_syncobj() and ff_cre_syncobj()
|
||||||
|
/ function, must be added to the project. Samples are available in
|
||||||
|
/ option/syscall.c.
|
||||||
|
/
|
||||||
|
/ The _FS_TIMEOUT defines timeout period in unit of time tick.
|
||||||
|
/ The _SYNC_t defines O/S dependent sync object type. e.g. HANDLE, ID, OS_EVENT*,
|
||||||
|
/ SemaphoreHandle_t and etc.. A header file for O/S definitions needs to be
|
||||||
|
/ included somewhere in the scope of ff.c. */
|
||||||
|
|
||||||
|
|
||||||
|
#define _WORD_ACCESS 0
|
||||||
|
/* The _WORD_ACCESS option is an only platform dependent option. It defines
|
||||||
|
/ which access method is used to the word data on the FAT volume.
|
||||||
|
/
|
||||||
|
/ 0: Byte-by-byte access. Always compatible with all platforms.
|
||||||
|
/ 1: Word access. Do not choose this unless under both the following conditions.
|
||||||
|
/
|
||||||
|
/ * Address misaligned memory access is always allowed to ALL instructions.
|
||||||
|
/ * Byte order on the memory is little-endian.
|
||||||
|
/
|
||||||
|
/ If it is the case, _WORD_ACCESS can also be set to 1 to reduce code size.
|
||||||
|
/ Following table shows allowable settings of some processor types.
|
||||||
|
/
|
||||||
|
/ ARM7TDMI 0 *2 ColdFire 0 *1 V850E 0 *2
|
||||||
|
/ Cortex-M3 0 *3 Z80 0/1 V850ES 0/1
|
||||||
|
/ Cortex-M0 0 *2 x86 0/1 TLCS-870 0/1
|
||||||
|
/ AVR 0/1 RX600(LE) 0/1 TLCS-900 0/1
|
||||||
|
/ AVR32 0 *1 RL78 0 *2 R32C 0 *2
|
||||||
|
/ PIC18 0/1 SH-2 0 *1 M16C 0/1
|
||||||
|
/ PIC24 0 *2 H8S 0 *1 MSP430 0 *2
|
||||||
|
/ PIC32 0 *1 H8/300H 0 *1 8051 0/1
|
||||||
|
/
|
||||||
|
/ *1:Big-endian.
|
||||||
|
/ *2:Unaligned memory access is not supported.
|
||||||
|
/ *3:Some compilers generate LDM/STM for mem_cpy function.
|
||||||
|
*/
|
||||||
|
|
180
source/fatfs/history.txt
Normal file
180
source/fatfs/history.txt
Normal file
@ -0,0 +1,180 @@
|
|||||||
|
----------------------------------------------------------------------------
|
||||||
|
Revision history of FatFs module
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
R0.00 (February 26, 2006)
|
||||||
|
Prototype.
|
||||||
|
|
||||||
|
|
||||||
|
R0.01 (April 29, 2006)
|
||||||
|
First stable version.
|
||||||
|
|
||||||
|
|
||||||
|
R0.02 (June 01, 2006)
|
||||||
|
Added FAT12 support.
|
||||||
|
Removed unbuffered mode.
|
||||||
|
Fixed a problem on small (<32M) partition.
|
||||||
|
|
||||||
|
|
||||||
|
R0.02a (June 10, 2006)
|
||||||
|
Added a configuration option (_FS_MINIMUM).
|
||||||
|
|
||||||
|
|
||||||
|
R0.03 (September 22, 2006)
|
||||||
|
Added f_rename().
|
||||||
|
Changed option _FS_MINIMUM to _FS_MINIMIZE.
|
||||||
|
|
||||||
|
|
||||||
|
R0.03a (December 11, 2006)
|
||||||
|
Improved cluster scan algorithm to write files fast.
|
||||||
|
Fixed f_mkdir() creates incorrect directory on FAT32.
|
||||||
|
|
||||||
|
|
||||||
|
R0.04 (February 04, 2007)
|
||||||
|
Added f_mkfs().
|
||||||
|
Supported multiple drive system.
|
||||||
|
Changed some interfaces for multiple drive system.
|
||||||
|
Changed f_mountdrv() to f_mount().
|
||||||
|
|
||||||
|
|
||||||
|
R0.04a (April 01, 2007)
|
||||||
|
Supported multiple partitions on a physical drive.
|
||||||
|
Added a capability of extending file size to f_lseek().
|
||||||
|
Added minimization level 3.
|
||||||
|
Fixed an endian sensitive code in f_mkfs().
|
||||||
|
|
||||||
|
|
||||||
|
R0.04b (May 05, 2007)
|
||||||
|
Added a configuration option _USE_NTFLAG.
|
||||||
|
Added FSINFO support.
|
||||||
|
Fixed DBCS name can result FR_INVALID_NAME.
|
||||||
|
Fixed short seek (<= csize) collapses the file object.
|
||||||
|
|
||||||
|
|
||||||
|
R0.05 (August 25, 2007)
|
||||||
|
Changed arguments of f_read(), f_write() and f_mkfs().
|
||||||
|
Fixed f_mkfs() on FAT32 creates incorrect FSINFO.
|
||||||
|
Fixed f_mkdir() on FAT32 creates incorrect directory.
|
||||||
|
|
||||||
|
|
||||||
|
R0.05a (February 03, 2008)
|
||||||
|
Added f_truncate() and f_utime().
|
||||||
|
Fixed off by one error at FAT sub-type determination.
|
||||||
|
Fixed btr in f_read() can be mistruncated.
|
||||||
|
Fixed cached sector is not flushed when create and close without write.
|
||||||
|
|
||||||
|
|
||||||
|
R0.06 (April 01, 2008)
|
||||||
|
Added fputc(), fputs(), fprintf() and fgets().
|
||||||
|
Improved performance of f_lseek() on moving to the same or following cluster.
|
||||||
|
|
||||||
|
|
||||||
|
R0.07 (April 01, 2009)
|
||||||
|
Merged Tiny-FatFs as a configuration option. (_FS_TINY)
|
||||||
|
Added long file name feature. (_USE_LFN)
|
||||||
|
Added multiple code page feature. (_CODE_PAGE)
|
||||||
|
Added re-entrancy for multitask operation. (_FS_REENTRANT)
|
||||||
|
Added auto cluster size selection to f_mkfs().
|
||||||
|
Added rewind option to f_readdir().
|
||||||
|
Changed result code of critical errors.
|
||||||
|
Renamed string functions to avoid name collision.
|
||||||
|
|
||||||
|
|
||||||
|
R0.07a (April 14, 2009)
|
||||||
|
Septemberarated out OS dependent code on reentrant cfg.
|
||||||
|
Added multiple sector size feature.
|
||||||
|
|
||||||
|
|
||||||
|
R0.07c (June 21, 2009)
|
||||||
|
Fixed f_unlink() can return FR_OK on error.
|
||||||
|
Fixed wrong cache control in f_lseek().
|
||||||
|
Added relative path feature.
|
||||||
|
Added f_chdir() and f_chdrive().
|
||||||
|
Added proper case conversion to extended character.
|
||||||
|
|
||||||
|
|
||||||
|
R0.07e (November 03, 2009)
|
||||||
|
Septemberarated out configuration options from ff.h to ffconf.h.
|
||||||
|
Fixed f_unlink() fails to remove a sub-directory on _FS_RPATH.
|
||||||
|
Fixed name matching error on the 13 character boundary.
|
||||||
|
Added a configuration option, _LFN_UNICODE.
|
||||||
|
Changed f_readdir() to return the SFN with always upper case on non-LFN cfg.
|
||||||
|
|
||||||
|
|
||||||
|
R0.08 (May 15, 2010)
|
||||||
|
Added a memory configuration option. (_USE_LFN = 3)
|
||||||
|
Added file lock feature. (_FS_SHARE)
|
||||||
|
Added fast seek feature. (_USE_FASTSEEK)
|
||||||
|
Changed some types on the API, XCHAR->TCHAR.
|
||||||
|
Changed .fname in the FILINFO structure on Unicode cfg.
|
||||||
|
String functions support UTF-8 encoding files on Unicode cfg.
|
||||||
|
|
||||||
|
|
||||||
|
R0.08a (August 16, 2010)
|
||||||
|
Added f_getcwd(). (_FS_RPATH = 2)
|
||||||
|
Added sector erase feature. (_USE_ERASE)
|
||||||
|
Moved file lock semaphore table from fs object to the bss.
|
||||||
|
Fixed f_mkfs() creates wrong FAT32 volume.
|
||||||
|
|
||||||
|
|
||||||
|
R0.08b (January 15, 2011)
|
||||||
|
Fast seek feature is also applied to f_read() and f_write().
|
||||||
|
f_lseek() reports required table size on creating CLMP.
|
||||||
|
Extended format syntax of f_printf().
|
||||||
|
Ignores duplicated directory separators in given path name.
|
||||||
|
|
||||||
|
|
||||||
|
R0.09 (September 06, 2011)
|
||||||
|
f_mkfs() supports multiple partition to complete the multiple partition feature.
|
||||||
|
Added f_fdisk().
|
||||||
|
|
||||||
|
|
||||||
|
R0.09a (August 27, 2012)
|
||||||
|
Changed f_open() and f_opendir() reject null object pointer to avoid crash.
|
||||||
|
Changed option name _FS_SHARE to _FS_LOCK.
|
||||||
|
Fixed assertion failure due to OS/2 EA on FAT12/16 volume.
|
||||||
|
|
||||||
|
|
||||||
|
R0.09b (January 24, 2013)
|
||||||
|
Added f_setlabel() and f_getlabel().
|
||||||
|
|
||||||
|
|
||||||
|
R0.10 (October 02, 2013)
|
||||||
|
Added selection of character encoding on the file. (_STRF_ENCODE)
|
||||||
|
Added f_closedir().
|
||||||
|
Added forced full FAT scan for f_getfree(). (_FS_NOFSINFO)
|
||||||
|
Added forced mount feature with changes of f_mount().
|
||||||
|
Improved behavior of volume auto detection.
|
||||||
|
Improved write throughput of f_puts() and f_printf().
|
||||||
|
Changed argument of f_chdrive(), f_mkfs(), disk_read() and disk_write().
|
||||||
|
Fixed f_write() can be truncated when the file size is close to 4GB.
|
||||||
|
Fixed f_open(), f_mkdir() and f_setlabel() can return incorrect error code.
|
||||||
|
|
||||||
|
|
||||||
|
R0.10a (January 15, 2014)
|
||||||
|
Added arbitrary strings as drive number in the path name. (_STR_VOLUME_ID)
|
||||||
|
Added a configuration option of minimum sector size. (_MIN_SS)
|
||||||
|
2nd argument of f_rename() can have a drive number and it will be ignored.
|
||||||
|
Fixed f_mount() with forced mount fails when drive number is >= 1. (appeared at R0.10)
|
||||||
|
Fixed f_close() invalidates the file object without volume lock.
|
||||||
|
Fixed f_closedir() returns but the volume lock is left acquired. (appeared at R0.10)
|
||||||
|
Fixed creation of an entry with LFN fails on too many SFN collisions. (appeared at R0.07)
|
||||||
|
|
||||||
|
|
||||||
|
R0.10b (May 19, 2014)
|
||||||
|
Fixed a hard error in the disk I/O layer can collapse the directory entry.
|
||||||
|
Fixed LFN entry is not deleted on delete/rename an object with lossy converted SFN. (appeared at R0.07)
|
||||||
|
|
||||||
|
|
||||||
|
R0.10c (November 09, 2014)
|
||||||
|
Added a configuration option for the platforms without RTC. (_FS_NORTC)
|
||||||
|
Changed option name _USE_ERASE to _USE_TRIM.
|
||||||
|
Fixed volume label created by Mac OS X cannot be retrieved with f_getlabel(). (appeared at R0.09b)
|
||||||
|
Fixed a potential problem of FAT access that can appear on disk error.
|
||||||
|
Fixed null pointer dereference on attempting to delete the root direcotry. (appeared at R0.08)
|
||||||
|
|
||||||
|
|
||||||
|
R0.11 (February 09, 2015)
|
||||||
|
Added f_findfirst(), f_findnext() and f_findclose(). (_USE_FIND)
|
||||||
|
Fixed f_unlink() does not remove cluster chain of the file. (appeared at R0.10c)
|
||||||
|
Fixed _FS_NORTC option does not work properly. (appeared at R0.10c)
|
33
source/fatfs/integer.h
Normal file
33
source/fatfs/integer.h
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*-------------------------------------------*/
|
||||||
|
/* Integer type definitions for FatFs module */
|
||||||
|
/*-------------------------------------------*/
|
||||||
|
|
||||||
|
#ifndef _FF_INTEGER
|
||||||
|
#define _FF_INTEGER
|
||||||
|
|
||||||
|
#ifdef _WIN32 /* FatFs development platform */
|
||||||
|
|
||||||
|
#include <windows.h>
|
||||||
|
#include <tchar.h>
|
||||||
|
|
||||||
|
#else /* Embedded platform */
|
||||||
|
|
||||||
|
/* This type MUST be 8 bit */
|
||||||
|
typedef unsigned char BYTE;
|
||||||
|
|
||||||
|
/* These types MUST be 16 bit */
|
||||||
|
typedef short SHORT;
|
||||||
|
typedef unsigned short WORD;
|
||||||
|
typedef unsigned short WCHAR;
|
||||||
|
|
||||||
|
/* These types MUST be 16 bit or 32 bit */
|
||||||
|
typedef int INT;
|
||||||
|
typedef unsigned int UINT;
|
||||||
|
|
||||||
|
/* These types MUST be 32 bit */
|
||||||
|
typedef long LONG;
|
||||||
|
typedef unsigned long DWORD;
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
3829
source/fatfs/option/cc932.c
Normal file
3829
source/fatfs/option/cc932.c
Normal file
File diff suppressed because it is too large
Load Diff
348
source/fatfs/option/ccsbcs.c
Normal file
348
source/fatfs/option/ccsbcs.c
Normal file
@ -0,0 +1,348 @@
|
|||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Unicode - Local code bidirectional converter (C)ChaN, 2015 */
|
||||||
|
/* (SBCS code pages) */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* 437 U.S.
|
||||||
|
/ 720 Arabic
|
||||||
|
/ 737 Greek
|
||||||
|
/ 771 KBL
|
||||||
|
/ 775 Baltic
|
||||||
|
/ 850 Latin 1
|
||||||
|
/ 852 Latin 2
|
||||||
|
/ 855 Cyrillic
|
||||||
|
/ 857 Turkish
|
||||||
|
/ 860 Portuguese
|
||||||
|
/ 861 Icelandic
|
||||||
|
/ 862 Hebrew
|
||||||
|
/ 863 Canadian French
|
||||||
|
/ 864 Arabic
|
||||||
|
/ 865 Nordic
|
||||||
|
/ 866 Russian
|
||||||
|
/ 869 Greek 2
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "../ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if _CODE_PAGE == 437
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP437(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 720
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP720(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x0628, 0x0629, 0x062A, 0x062B, 0x062C, 0x062D, 0x062E, 0x062F, 0x0630, 0x0631, 0x0632, 0x0633, 0x0634, 0x0635, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x0636, 0x0637, 0x0638, 0x0639, 0x063A, 0x0641, 0x00B5, 0x0642, 0x0643, 0x0644, 0x0645, 0x0646, 0x0647, 0x0648, 0x0649, 0x064A,
|
||||||
|
0x2261, 0x064B, 0x064C, 0x064D, 0x064E, 0x064F, 0x0650, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 737
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP737(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x03C5, 0x03C6, 0x03C7, 0x03C8,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03C9, 0x03AC, 0x03AD, 0x03AE, 0x03CA, 0x03AF, 0x03CC, 0x03CD, 0x03CB, 0x03CE, 0x0386, 0x0388, 0x0389, 0x038A, 0x038C, 0x038E,
|
||||||
|
0x038F, 0x00B1, 0x2265, 0x2264, 0x03AA, 0x03AB, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 771
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP771(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x0104, 0x0105, 0x010C, 0x010D,
|
||||||
|
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
|
||||||
|
0x0118, 0x0119, 0x0116, 0x0117, 0x012E, 0x012F, 0x0160, 0x0161, 0x0172, 0x0173, 0x016A, 0x016B, 0x017D, 0x017E, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 775
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP775(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x0100, 0x012A, 0x00F3, 0x017B, 0x017C, 0x017A, 0x201D, 0x00A6, 0x00A9, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x0141, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0104, 0x010C, 0x0118, 0x0116, 0x2563, 0x2551, 0x2557, 0x255D, 0x012E, 0x0160, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0172, 0x016A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x017D,
|
||||||
|
0x0105, 0x010D, 0x0119, 0x0117, 0x012F, 0x0161, 0x0173, 0x016B, 0x017E, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x014C, 0x0143, 0x00F5, 0x00D5, 0x00B5, 0x0144, 0x0136, 0x0137, 0x013B, 0x013C, 0x0146, 0x0112, 0x0145, 0x2019,
|
||||||
|
0x00AD, 0x00B1, 0x201C, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x201E, 0x00B0, 0x2219, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 850
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP850(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x00F0, 0x00D0, 0x00CA, 0x00CB, 0x00C8, 0x0131, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x00FE, 0x00DE, 0x00DA, 0x00DB, 0x00D9, 0x00FD, 0x00DD, 0x00AF, 0x00B4,
|
||||||
|
0x00AD, 0x00B1, 0x2017, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 852
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP852(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x0104, 0x0105, 0x017D, 0x017E, 0x0118, 0x0119, 0x00AC, 0x017A, 0x010C, 0x015F, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x011A, 0x015E, 0x2563, 0x2551, 0x2557, 0x255D, 0x017B, 0x017C, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0102, 0x0103, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x0111, 0x0110, 0x010E, 0x00CB, 0x010F, 0x0147, 0x00CD, 0x00CE, 0x011B, 0x2518, 0x250C, 0x2588, 0x2584, 0x0162, 0x016E, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x00D4, 0x0143, 0x0144, 0x0148, 0x0160, 0x0161, 0x0154, 0x00DA, 0x0155, 0x0170, 0x00FD, 0x00DD, 0x0163, 0x00B4,
|
||||||
|
0x00AD, 0x02DD, 0x02DB, 0x02C7, 0x02D8, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x02D9, 0x0171, 0x0158, 0x0159, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 855
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP855(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x0430, 0x0410, 0x0431, 0x0411, 0x0446, 0x0426, 0x0434, 0x0414, 0x0435, 0x0415, 0x0444, 0x0424, 0x0433, 0x0413, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x0445, 0x0425, 0x0438, 0x0418, 0x2563, 0x2551, 0x2557, 0x255D, 0x0439, 0x0419, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x043A, 0x041A, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x043B, 0x041B, 0x043C, 0x041C, 0x043D, 0x041D, 0x043E, 0x041E, 0x043F, 0x2518, 0x250C, 0x2588, 0x2584, 0x041F, 0x044F, 0x2580,
|
||||||
|
0x042F, 0x0440, 0x0420, 0x0441, 0x0421, 0x0442, 0x0422, 0x0443, 0x0423, 0x0436, 0x0416, 0x0432, 0x0412, 0x044C, 0x042C, 0x2116,
|
||||||
|
0x00AD, 0x044B, 0x042B, 0x0437, 0x0417, 0x0448, 0x0428, 0x044D, 0x042D, 0x0449, 0x0429, 0x0447, 0x0427, 0x00A7, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 857
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP857(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x011E, 0x011F, 0x00BF, 0x00AE, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x00C1, 0x00C2, 0x00C0, 0x00A9, 0x2563, 0x2551, 0x2557, 0x255D, 0x00A2, 0x00A5, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x00E3, 0x00C3, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x00A4,
|
||||||
|
0x00BA, 0x00AA, 0x00CA, 0x00CB, 0x00C8, 0x0000, 0x00CD, 0x00CE, 0x00CF, 0x2518, 0x250C, 0x2588, 0x2584, 0x00A6, 0x00CC, 0x2580,
|
||||||
|
0x00D3, 0x00DF, 0x00D4, 0x00D2, 0x00F5, 0x00D5, 0x00B5, 0x0000, 0x00D7, 0x00DA, 0x00DB, 0x00D9, 0x00EC, 0x00FF, 0x00AF, 0x00B4,
|
||||||
|
0x00AD, 0x00B1, 0x0000, 0x00BE, 0x00B6, 0x00A7, 0x00F7, 0x00B8, 0x00B0, 0x00A8, 0x00B7, 0x00B9, 0x00B3, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 860
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP860(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x00D2, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 861
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP861(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00C1, 0x00CD, 0x00D3, 0x00DA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 862
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP862(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 863
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP863(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00A6, 0x00B4, 0x00F3, 0x00FA, 0x00A8, 0x00BB, 0x00B3, 0x00AF, 0x00CE, 0x3210, 0x00AC, 0x00BD, 0x00BC, 0x00BE, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2219,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 864
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP864(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00A0, 0x00AD, 0xFE82, 0x00A3, 0x00A4, 0xFE84, 0x0000, 0x20AC, 0xFE8E, 0xFE8F, 0xFE95, 0xFE99, 0x060C, 0xFE9D, 0xFEA1, 0xFEA5,
|
||||||
|
0x0660, 0x0661, 0x0662, 0x0663, 0x0664, 0x0665, 0x0666, 0x0667, 0x0668, 0x0669, 0xFED1, 0x061B, 0xFEB1, 0xFEB5, 0xFEB9, 0x061F,
|
||||||
|
0x00A2, 0xFE80, 0xFE81, 0xFE83, 0xFE85, 0xFECA, 0xFE8B, 0xFE8D, 0xFE91, 0xFE93, 0xFE97, 0xFE9B, 0xFE9F, 0xFEA3, 0xFEA7, 0xFEA9,
|
||||||
|
0xFEAB, 0xFEAD, 0xFEAF, 0xFEB3, 0xFEB7, 0xFEBB, 0xFEBF, 0xFEC1, 0xFEC5, 0xFECB, 0xFECF, 0x00A6, 0x00AC, 0x00F7, 0x00D7, 0xFEC9,
|
||||||
|
0x0640, 0xFED3, 0xFED7, 0xFEDB, 0xFEDF, 0xFEE3, 0xFEE7, 0xFEEB, 0xFEED, 0xFEEF, 0xFEF3, 0xFEBD, 0xFECC, 0xFECE, 0xFECD, 0xFEE1,
|
||||||
|
0xFE7D, 0x0651, 0xFEE5, 0xFEE9, 0xFEEC, 0xFEF0, 0xFEF2, 0xFED0, 0xFED5, 0xFEF5, 0xFEF6, 0xFEDD, 0xFED9, 0xFEF1, 0x25A0, 0x0000
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 865
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP865(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x00E1, 0x00ED, 0x00F3, 0x00FA, 0x00F1, 0x00D1, 0x00AA, 0x00BA, 0x00BF, 0x2310, 0x00AC, 0x00BD, 0x00BC, 0x00A1, 0x00AB, 0x00A4,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x2558, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x03B1, 0x00DF, 0x0393, 0x03C0, 0x03A3, 0x03C3, 0x00B5, 0x03C4, 0x03A6, 0x0398, 0x03A9, 0x03B4, 0x221E, 0x03C6, 0x03B5, 0x2229,
|
||||||
|
0x2261, 0x00B1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00F7, 0x2248, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x207F, 0x00B2, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 866
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP866(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436, 0x0437, 0x0438, 0x0439, 0x043A, 0x043B, 0x043C, 0x043D, 0x043E, 0x043F,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567,
|
||||||
|
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580,
|
||||||
|
0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446, 0x0447, 0x0448, 0x0449, 0x044A, 0x044B, 0x044C, 0x044D, 0x044E, 0x044F,
|
||||||
|
0x0401, 0x0451, 0x0404, 0x0454, 0x0407, 0x0457, 0x040E, 0x045E, 0x00B0, 0x2219, 0x00B7, 0x221A, 0x2116, 0x00A4, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#elif _CODE_PAGE == 869
|
||||||
|
#define _TBLDEF 1
|
||||||
|
static
|
||||||
|
const WCHAR Tbl[] = { /* CP869(0x80-0xFF) to Unicode conversion table */
|
||||||
|
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,
|
||||||
|
0x03CA, 0x0390, 0x03CC, 0x03CD, 0x0391, 0x0392, 0x0393, 0x0394, 0x0395, 0x0396, 0x0397, 0x00BD, 0x0398, 0x0399, 0x00AB, 0x00BB,
|
||||||
|
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x039A, 0x039B, 0x039C, 0x039D, 0x2563, 0x2551, 0x2557, 0x255D, 0x039E, 0x039F, 0x2510,
|
||||||
|
0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x0A30, 0x03A1, 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x03A3,
|
||||||
|
0x03A4, 0x03A5, 0x03A6, 0x03A7, 0x03A8, 0x03A9, 0x03B1, 0x03B2, 0x03B3, 0x2518, 0x250C, 0x2588, 0x2584, 0x03B4, 0x03B5, 0x2580,
|
||||||
|
0x03B6, 0x03B7, 0x03B8, 0x03B9, 0x03BA, 0x03BB, 0x03BC, 0x03BD, 0x03BE, 0x03BF, 0x03C0, 0x03C1, 0x03C3, 0x03C2, 0x03C4, 0x0384,
|
||||||
|
0x00AD, 0x00B1, 0x03C5, 0x03C6, 0x03C7, 0x00A7, 0x03C8, 0x0385, 0x00B0, 0x00A8, 0x03C9, 0x03CB, 0x03B0, 0x03CE, 0x25A0, 0x00A0
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
#if !_TBLDEF || !_USE_LFN
|
||||||
|
#error This file is not needed at current configuration. Remove from the project.
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WCHAR ff_convert ( /* Converted character, Returns zero on error */
|
||||||
|
WCHAR chr, /* Character code to be converted */
|
||||||
|
UINT dir /* 0: Unicode to OEM code, 1: OEM code to Unicode */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
WCHAR c;
|
||||||
|
|
||||||
|
|
||||||
|
if (chr < 0x80) { /* ASCII */
|
||||||
|
c = chr;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
if (dir) { /* OEM code to Unicode */
|
||||||
|
c = (chr >= 0x100) ? 0 : Tbl[chr - 0x80];
|
||||||
|
|
||||||
|
} else { /* Unicode to OEM code */
|
||||||
|
for (c = 0; c < 0x80; c++) {
|
||||||
|
if (chr == Tbl[c]) break;
|
||||||
|
}
|
||||||
|
c = (c + 0x80) & 0xFF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
WCHAR ff_wtoupper ( /* Returns upper converted character */
|
||||||
|
WCHAR chr /* Unicode character to be upper converted */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
static const WCHAR lower[] = { /* Lower case characters to be converted */
|
||||||
|
/* Latin Supplement */ 0xE0,0xE1,0xE2,0xE3,0xE4,0xE5,0xE6,0xE7,0xE8,0xE9,0xEA,0xEB,0xEC,0xED,0xEE,0xEF,0xF0,0xF1,0xF2,0xF3,0xF4,0xF5,0xF6,0xF8,0xF9,0xFA,0xFB,0xFC,0xFD,0xFE,0xFF,
|
||||||
|
/* Latin Extended-A */ 0x101,0x103,0x105,0x107,0x109,0x10B,0x10D,0x10F,0x111,0x113,0x115,0x117,0x119,0x11B,0x11D,0x11F,0x121,0x123,0x125,0x127,0x129,0x12B,0x12D,0x12F,0x131,0x133,0x135,0x137,0x13A,0x13C,0x13E,0x140,0x142,0x144,0x146,0x148,0x14B,0x14D,0x14F,0x151,0x153,0x155,0x157,0x159,0x15B,0x15D,0x15F,0x161,0x163,0x165,0x167,0x169,0x16B,0x16D,0x16F,0x171,0x173,0x175,0x177,0x17A,0x17C,0x17E,
|
||||||
|
/* Latin Extended-B */ 0x183,0x185,0x188,0x18C,0x192,0x199,0x1A1,0x1A3,0x1A8,0x1AD,0x1B0,0x1B4,0x1B6,0x1B9,0x1BD,0x1C6,0x1C9,0x1CC,0x1CE,0x1D0,0x1D2,0x1D4,0x1D6,0x1D8,0x1DA,0x1DC,0x1DD,0x1DF,0x1E1,0x1E3,0x1E5,0x1E7,0x1E9,0x1EB,0x1ED,0x1EF,0x1F3,0x1F5,0x1FB,0x1FD,0x1FF,0x201,0x203,0x205,0x207,0x209,0x20B,0x20D,0x20F,0x211,0x213,0x215,0x217,
|
||||||
|
/* Greek, Coptic */ 0x3B1,0x3B2,0x3B3,0x3B4,0x3B5,0x3B6,0x3B7,0x3B8,0x3B9,0x3BA,0x3BB,0x3BC,0x3BD,0x3BE,0x3BF,0x3C0,0x3C1,0x3C3,0x3C4,0x3C5,0x3C6,0x3C7,0x3C8,0x3C9,0x3CA,0x3CB,0x3CC,0x3CD,0x3CE,0x3E3,0x3E5,0x3E7,0x3E9,0x3EB,
|
||||||
|
/* Cyrillic */ 0x430,0x431,0x432,0x433,0x434,0x435,0x436,0x437,0x438,0x439,0x43A,0x43B,0x43C,0x43D,0x43E,0x43F,0x440,0x441,0x442,0x443,0x444,0x445,0x446,0x447,0x448,0x449,0x44A,0x44B,0x44C,0x44D,0x44E,0x44F,0x452,0x453,0x454,0x455,0x456,0x457,0x458,0x459,0x45A,0x45B,0x45C,0x45E,0x45F,0x461,0x463,0x465,0x467,0x469,0x46B,0x46D,0x46F,0x471,0x473,0x475,0x477,0x479,0x47B,0x47D,0x47F,0x481,0x491,0x493,0x495,0x497,0x499,0x49B,0x49D,0x49F,0x4A1,0x4A3,0x4A5,0x4A7,0x4A9,0x4AB,0x4AD,0x4AF,0x4B1,0x4B3,0x4B5,0x4B7,0x4B9,0x4BB,0x4BD,0x4BF,0x4C2,0x4C4,0x4C8,0x4D1,0x4D3,0x4D5,0x4D7,0x4D9,0x4DB,0x4DD,0x4DF,0x4E1,0x4E3,0x4E5,0x4E7,0x4E9,0x4EB,0x4ED,0x4EF,0x4F1,0x4F3,0x4F5,0x4F9,
|
||||||
|
/* Armenian */ 0x561,0x562,0x563,0x564,0x565,0x566,0x567,0x568,0x569,0x56A,0x56B,0x56C,0x56D,0x56E,0x56F,0x570,0x571,0x572,0x573,0x574,0x575,0x576,0x577,0x578,0x579,0x57A,0x57B,0x57C,0x57D,0x57E,0x57F,0x580,0x581,0x582,0x583,0x584,0x585,0x586,
|
||||||
|
/* Latin Extended Additional */ 0x1E01,0x1E03,0x1E05,0x1E07,0x1E09,0x1E0B,0x1E0D,0x1E0F,0x1E11,0x1E13,0x1E15,0x1E17,0x1E19,0x1E1B,0x1E1D,0x1E1F,0x1E21,0x1E23,0x1E25,0x1E27,0x1E29,0x1E2B,0x1E2D,0x1E2F,0x1E31,0x1E33,0x1E35,0x1E37,0x1E39,0x1E3B,0x1E3D,0x1E3F,0x1E41,0x1E43,0x1E45,0x1E47,0x1E49,0x1E4B,0x1E4D,0x1E4F,0x1E51,0x1E53,0x1E55,0x1E57,0x1E59,0x1E5B,0x1E5D,0x1E5F,0x1E61,0x1E63,0x1E65,0x1E67,0x1E69,0x1E6B,0x1E6D,0x1E6F,0x1E71,0x1E73,0x1E75,0x1E77,0x1E79,0x1E7B,0x1E7D,0x1E7F,0x1E81,0x1E83,0x1E85,0x1E87,0x1E89,0x1E8B,0x1E8D,0x1E8F,0x1E91,0x1E93,0x1E95,0x1E97,0x1E99,0x1E9B,0x1E9D,0x1E9F,0x1EA1,0x1EA3,0x1EA5,0x1EA7,0x1EA9,0x1EAB,0x1EAD,0x1EAF,0x1EB1,0x1EB3,0x1EB5,0x1EB7,0x1EB9,0x1EBB,0x1EBD,0x1EBF,0x1EC1,0x1EC3,0x1EC5,0x1EC7,0x1EC9,0x1ECB,0x1ECD,0x1ECF,0x1ED1,0x1ED3,0x1ED5,0x1ED7,0x1ED9,0x1EDB,0x1EDD,0x1EDF,0x1EE1,0x1EE3,0x1EE5,0x1EE7,0x1EE9,0x1EEB,0x1EED,0x1EEF,0x1EF1,0x1EF3,0x1EF5,0x1EF7,0x1EF9,
|
||||||
|
/* Number forms */ 0x2170,0x2171,0x2172,0x2173,0x2174,0x2175,0x2176,0x2177,0x2178,0x2179,0x217A,0x217B,0x217C,0x217D,0x217E,0x217F,
|
||||||
|
/* Full-width */ 0xFF41,0xFF42,0xFF43,0xFF44,0xFF45,0xFF46,0xFF47,0xFF48,0xFF49,0xFF4A,0xFF4B,0xFF4C,0xFF4D,0xFF4E,0xFF4F,0xFF50,0xFF51,0xFF52,0xFF53,0xFF54,0xFF55,0xFF56,0xFF57,0xFF58,0xFF59,0xFF5A
|
||||||
|
};
|
||||||
|
static const WCHAR upper[] = { /* Upper case characters correspond to lower[] */
|
||||||
|
0xC0,0xC1,0xC2,0xC3,0xC4,0xC5,0xC6,0xC7,0xC8,0xC9,0xCA,0xCB,0xCC,0xCD,0xCE,0xCF,0xD0,0xD1,0xD2,0xD3,0xD4,0xD5,0xD6,0xD8,0xD9,0xDA,0xDB,0xDC,0xDD,0xDE,0x178,
|
||||||
|
0x100,0x102,0x104,0x106,0x108,0x10A,0x10C,0x10E,0x110,0x112,0x114,0x116,0x118,0x11A,0x11C,0x11E,0x120,0x122,0x124,0x126,0x128,0x12A,0x12C,0x12E,0x130,0x132,0x134,0x136,0x139,0x13B,0x13D,0x13F,0x141,0x143,0x145,0x147,0x14A,0x14C,0x14E,0x150,0x152,0x154,0x156,0x158,0x15A,0x15C,0x15E,0x160,0x162,0x164,0x166,0x168,0x16A,0x16C,0x16E,0x170,0x172,0x174,0x176,0x179,0x17B,0x17D,
|
||||||
|
0x182,0x184,0x187,0x18B,0x191,0x198,0x1A0,0x1A2,0x1A7,0x1AC,0x1AF,0x1B3,0x1B5,0x1B8,0x1BC,0x1C4,0x1C7,0x1CA,0x1CD,0x1CF,0x1D1,0x1D3,0x1D5,0x1D7,0x1D9,0x1DB,0x18E,0x1DE,0x1E0,0x1E2,0x1E4,0x1E6,0x1E8,0x1EA,0x1EC,0x1EE,0x1F1,0x1F4,0x1FA,0x1FC,0x1FE,0x200,0x202,0x204,0x206,0x208,0x20A,0x20C,0x20E,0x210,0x212,0x214,0x216,
|
||||||
|
0x391,0x392,0x393,0x394,0x395,0x396,0x397,0x398,0x399,0x39A,0x39B,0x39C,0x39D,0x39E,0x39F,0x3A0,0x3A1,0x3A3,0x3A4,0x3A5,0x3A6,0x3A7,0x3A8,0x3A9,0x3AA,0x3AB,0x38C,0x38E,0x38F,0x3E2,0x3E4,0x3E6,0x3E8,0x3EA,
|
||||||
|
0x410,0x411,0x412,0x413,0x414,0x415,0x416,0x417,0x418,0x419,0x41A,0x41B,0x41C,0x41D,0x41E,0x41F,0x420,0x421,0x422,0x423,0x424,0x425,0x426,0x427,0x428,0x429,0x42A,0x42B,0x42C,0x42D,0x42E,0x42F,0x402,0x403,0x404,0x405,0x406,0x407,0x408,0x409,0x40A,0x40B,0x40C,0x40E,0x40F,0x460,0x462,0x464,0x466,0x468,0x46A,0x46C,0x46E,0x470,0x472,0x474,0x476,0x478,0x47A,0x47C,0x47E,0x480,0x490,0x492,0x494,0x496,0x498,0x49A,0x49C,0x49E,0x4A0,0x4A2,0x4A4,0x4A6,0x4A8,0x4AA,0x4AC,0x4AE,0x4B0,0x4B2,0x4B4,0x4B6,0x4B8,0x4BA,0x4BC,0x4BE,0x4C1,0x4C3,0x5C7,0x4D0,0x4D2,0x4D4,0x4D6,0x4D8,0x4DA,0x4DC,0x4DE,0x4E0,0x4E2,0x4E4,0x4E6,0x4E8,0x4EA,0x4EC,0x4EE,0x4F0,0x4F2,0x4F4,0x4F8,
|
||||||
|
0x531,0x532,0x533,0x534,0x535,0x536,0x537,0x538,0x539,0x53A,0x53B,0x53C,0x53D,0x53E,0x53F,0x540,0x541,0x542,0x543,0x544,0x545,0x546,0x547,0x548,0x549,0x54A,0x54B,0x54C,0x54D,0x54E,0x54F,0x550,0x551,0x552,0x553,0x554,0x555,0x556,
|
||||||
|
0x1E00,0x1E02,0x1E04,0x1E06,0x1E08,0x1E0A,0x1E0C,0x1E0E,0x1E10,0x1E12,0x1E14,0x1E16,0x1E18,0x1E1A,0x1E1C,0x1E1E,0x1E20,0x1E22,0x1E24,0x1E26,0x1E28,0x1E2A,0x1E2C,0x1E2E,0x1E30,0x1E32,0x1E34,0x1E36,0x1E38,0x1E3A,0x1E3C,0x1E3E,0x1E40,0x1E42,0x1E44,0x1E46,0x1E48,0x1E4A,0x1E4C,0x1E4E,0x1E50,0x1E52,0x1E54,0x1E56,0x1E58,0x1E5A,0x1E5C,0x1E5E,0x1E60,0x1E62,0x1E64,0x1E66,0x1E68,0x1E6A,0x1E6C,0x1E6E,0x1E70,0x1E72,0x1E74,0x1E76,0x1E78,0x1E7A,0x1E7C,0x1E7E,0x1E80,0x1E82,0x1E84,0x1E86,0x1E88,0x1E8A,0x1E8C,0x1E8E,0x1E90,0x1E92,0x1E94,0x1E96,0x1E98,0x1E9A,0x1E9C,0x1E9E,0x1EA0,0x1EA2,0x1EA4,0x1EA6,0x1EA8,0x1EAA,0x1EAC,0x1EAE,0x1EB0,0x1EB2,0x1EB4,0x1EB6,0x1EB8,0x1EBA,0x1EBC,0x1EBE,0x1EC0,0x1EC2,0x1EC4,0x1EC6,0x1EC8,0x1ECA,0x1ECC,0x1ECE,0x1ED0,0x1ED2,0x1ED4,0x1ED6,0x1ED8,0x1EDA,0x1EDC,0x1EDE,0x1EE0,0x1EE2,0x1EE4,0x1EE6,0x1EE8,0x1EEA,0x1EEC,0x1EEE,0x1EF0,0x1EF2,0x1EF4,0x1EF6,0x1EF8,
|
||||||
|
0x2160,0x2161,0x2162,0x2163,0x2164,0x2165,0x2166,0x2167,0x2168,0x2169,0x216A,0x216B,0x216C,0x216D,0x216E,0x216F,
|
||||||
|
0xFF21,0xFF22,0xFF23,0xFF24,0xFF25,0xFF26,0xFF27,0xFF28,0xFF29,0xFF2A,0xFF2B,0xFF2C,0xFF2D,0xFF2E,0xFF2F,0xFF30,0xFF31,0xFF32,0xFF33,0xFF34,0xFF35,0xFF36,0xFF37,0xFF38,0xFF39,0xFF3A
|
||||||
|
};
|
||||||
|
UINT i, n, hi, li;
|
||||||
|
|
||||||
|
|
||||||
|
if (chr < 0x80) { /* ASCII characters (acceleration) */
|
||||||
|
if (chr >= 0x61 && chr <= 0x7A) chr -= 0x20;
|
||||||
|
|
||||||
|
} else { /* Non ASCII characters (table search) */
|
||||||
|
n = 12; li = 0; hi = sizeof lower / sizeof lower[0];
|
||||||
|
do {
|
||||||
|
i = li + (hi - li) / 2;
|
||||||
|
if (chr == lower[i]) break;
|
||||||
|
if (chr > lower[i]) li = i; else hi = i;
|
||||||
|
} while (--n);
|
||||||
|
if (n) chr = upper[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return chr;
|
||||||
|
}
|
||||||
|
|
151
source/fatfs/option/syscall.c
Normal file
151
source/fatfs/option/syscall.c
Normal file
@ -0,0 +1,151 @@
|
|||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Sample code of OS dependent controls for FatFs */
|
||||||
|
/* (C)ChaN, 2014 */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
|
||||||
|
#include "../ff.h"
|
||||||
|
|
||||||
|
|
||||||
|
#if _FS_REENTRANT
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Create a Synchronization Object */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called in f_mount() function to create a new
|
||||||
|
/ synchronization object, such as semaphore and mutex. When a 0 is returned,
|
||||||
|
/ the f_mount() function fails with FR_INT_ERR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ff_cre_syncobj ( /* !=0:Function succeeded, ==0:Could not create due to any error */
|
||||||
|
BYTE vol, /* Corresponding logical drive being processed */
|
||||||
|
_SYNC_t *sobj /* Pointer to return the created sync object */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
*sobj = CreateMutex(NULL, FALSE, NULL); /* Win32 */
|
||||||
|
ret = (int)(*sobj != INVALID_HANDLE_VALUE);
|
||||||
|
|
||||||
|
// *sobj = SyncObjects[vol]; /* uITRON (give a static created sync object) */
|
||||||
|
// ret = 1; /* The initial value of the semaphore must be 1. */
|
||||||
|
|
||||||
|
// *sobj = OSMutexCreate(0, &err); /* uC/OS-II */
|
||||||
|
// ret = (int)(err == OS_NO_ERR);
|
||||||
|
|
||||||
|
// *sobj = xSemaphoreCreateMutex(); /* FreeRTOS */
|
||||||
|
// ret = (int)(*sobj != NULL);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Delete a Synchronization Object */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called in f_mount() function to delete a synchronization
|
||||||
|
/ object that created with ff_cre_syncobj function. When a 0 is returned,
|
||||||
|
/ the f_mount() function fails with FR_INT_ERR.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ff_del_syncobj ( /* !=0:Function succeeded, ==0:Could not delete due to any error */
|
||||||
|
_SYNC_t sobj /* Sync object tied to the logical drive to be deleted */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
|
||||||
|
ret = CloseHandle(sobj); /* Win32 */
|
||||||
|
|
||||||
|
// ret = 1; /* uITRON (nothing to do) */
|
||||||
|
|
||||||
|
// OSMutexDel(sobj, OS_DEL_ALWAYS, &err); /* uC/OS-II */
|
||||||
|
// ret = (int)(err == OS_NO_ERR);
|
||||||
|
|
||||||
|
// vSemaphoreDelete(sobj); /* FreeRTOS */
|
||||||
|
// ret = 1;
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Request Grant to Access the Volume */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called on entering file functions to lock the volume.
|
||||||
|
/ When a 0 is returned, the file function fails with FR_TIMEOUT.
|
||||||
|
*/
|
||||||
|
|
||||||
|
int ff_req_grant ( /* 1:Got a grant to access the volume, 0:Could not get a grant */
|
||||||
|
_SYNC_t sobj /* Sync object to wait */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = (int)(WaitForSingleObject(sobj, _FS_TIMEOUT) == WAIT_OBJECT_0); /* Win32 */
|
||||||
|
|
||||||
|
// ret = (int)(wai_sem(sobj) == E_OK); /* uITRON */
|
||||||
|
|
||||||
|
// OSMutexPend(sobj, _FS_TIMEOUT, &err)); /* uC/OS-II */
|
||||||
|
// ret = (int)(err == OS_NO_ERR);
|
||||||
|
|
||||||
|
// ret = (int)(xSemaphoreTake(sobj, _FS_TIMEOUT) == pdTRUE); /* FreeRTOS */
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Release Grant to Access the Volume */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* This function is called on leaving file functions to unlock the volume.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void ff_rel_grant (
|
||||||
|
_SYNC_t sobj /* Sync object to be signaled */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
ReleaseMutex(sobj); /* Win32 */
|
||||||
|
|
||||||
|
// sig_sem(sobj); /* uITRON */
|
||||||
|
|
||||||
|
// OSMutexPost(sobj); /* uC/OS-II */
|
||||||
|
|
||||||
|
// xSemaphoreGive(sobj); /* FreeRTOS */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#if _USE_LFN == 3 /* LFN with a working buffer on the heap */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Allocate a memory block */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* If a NULL is returned, the file function fails with FR_NOT_ENOUGH_CORE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
void* ff_memalloc ( /* Returns pointer to the allocated memory block */
|
||||||
|
UINT msize /* Number of bytes to allocate */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
return malloc(msize); /* Allocate a new memory block with POSIX API */
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
/* Free a memory block */
|
||||||
|
/*------------------------------------------------------------------------*/
|
||||||
|
|
||||||
|
void ff_memfree (
|
||||||
|
void* mblock /* Pointer to the memory block to free */
|
||||||
|
)
|
||||||
|
{
|
||||||
|
free(mblock); /* Discard the memory block with POSIX API */
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
17
source/fatfs/option/unicode.c
Normal file
17
source/fatfs/option/unicode.c
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
#include "../ff.h"
|
||||||
|
|
||||||
|
#if _USE_LFN != 0
|
||||||
|
|
||||||
|
#if _CODE_PAGE == 932 /* Japanese Shift_JIS */
|
||||||
|
#include "cc932.c"
|
||||||
|
#elif _CODE_PAGE == 936 /* Simplified Chinese GBK */
|
||||||
|
#include "cc936.c"
|
||||||
|
#elif _CODE_PAGE == 949 /* Korean */
|
||||||
|
#include "cc949.c"
|
||||||
|
#elif _CODE_PAGE == 950 /* Traditional Chinese Big5 */
|
||||||
|
#include "cc950.c"
|
||||||
|
#else /* Single Byte Character-Set */
|
||||||
|
#include "ccsbcs.c"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
620
source/fatfs/sdmmc.c
Normal file
620
source/fatfs/sdmmc.c
Normal file
@ -0,0 +1,620 @@
|
|||||||
|
/*
|
||||||
|
* This Source Code Form is subject to the terms of the Mozilla Public
|
||||||
|
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||||
|
* You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||||
|
*
|
||||||
|
* Copyright (c) 2014, Normmatt
|
||||||
|
*
|
||||||
|
* Alternatively, the contents of this file may be used under the terms
|
||||||
|
* of the GNU General Public License Version 2, as described below:
|
||||||
|
*
|
||||||
|
* This file is free software: you may copy, redistribute and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation, either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This file 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 <stdint.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <inttypes.h>
|
||||||
|
#include <malloc.h>
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <dirent.h>
|
||||||
|
#include <errno.h>
|
||||||
|
|
||||||
|
#include "sdmmc.h"
|
||||||
|
//#include "DrawCharacter.h"
|
||||||
|
|
||||||
|
//Uncomment to enable 32bit fifo support?
|
||||||
|
//not currently working
|
||||||
|
//#define DATA32_SUPPORT
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
#define bool int
|
||||||
|
|
||||||
|
#define NO_INLINE __attribute__ ((noinline))
|
||||||
|
|
||||||
|
#define RGB(r,g,b) (r<<24|b<<16|g<<8|r)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
void waitcycles(uint32_t val);
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//#define DEBUG_SDMMC
|
||||||
|
|
||||||
|
#ifdef DEBUG_SDMMC
|
||||||
|
extern uint8_t* topScreen;
|
||||||
|
extern void DrawHexWithName(unsigned char *screen, const char *str, unsigned int hex, int x, int y, int color, int bgcolor);
|
||||||
|
#define DEBUGPRINT(scr,str,hex,x,y,color,bg) DrawHexWithName(scr,str,hex,x,y,color,bg)
|
||||||
|
#else
|
||||||
|
#define DEBUGPRINT(...)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//extern "C" void sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args);
|
||||||
|
//extern "C" void inittarget(struct mmcdevice *ctx);
|
||||||
|
//extern "C" int SD_Init();
|
||||||
|
//extern "C" int SD_Init2();
|
||||||
|
//extern "C" int Nand_Init2();
|
||||||
|
//extern "C" void InitSD();
|
||||||
|
|
||||||
|
struct mmcdevice handelNAND;
|
||||||
|
struct mmcdevice handelSD;
|
||||||
|
|
||||||
|
mmcdevice *getMMCDevice(int drive)
|
||||||
|
{
|
||||||
|
if(drive==0) return &handelNAND;
|
||||||
|
return &handelSD;
|
||||||
|
}
|
||||||
|
|
||||||
|
int geterror(struct mmcdevice *ctx)
|
||||||
|
{
|
||||||
|
return (ctx->error << 29) >> 31;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void inittarget(struct mmcdevice *ctx)
|
||||||
|
{
|
||||||
|
sdmmc_mask16(REG_SDPORTSEL,0x3,(uint16_t)ctx->devicenumber);
|
||||||
|
setckl(ctx->clk);
|
||||||
|
if(ctx->SDOPT == 0)
|
||||||
|
{
|
||||||
|
sdmmc_mask16(REG_SDOPT,0,0x8000);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
sdmmc_mask16(REG_SDOPT,0x8000,0);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void NO_INLINE sdmmc_send_command(struct mmcdevice *ctx, uint32_t cmd, uint32_t args)
|
||||||
|
{
|
||||||
|
bool getSDRESP = (cmd << 15) >> 31;
|
||||||
|
uint16_t flags = (cmd << 15) >> 31;
|
||||||
|
const bool readdata = cmd & 0x20000;
|
||||||
|
const bool writedata = cmd & 0x40000;
|
||||||
|
|
||||||
|
if(readdata || writedata)
|
||||||
|
{
|
||||||
|
flags |= TMIO_STAT0_DATAEND;
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx->error = 0;
|
||||||
|
while((sdmmc_read16(REG_SDSTATUS1) & TMIO_STAT1_CMD_BUSY)); //mmc working?
|
||||||
|
sdmmc_write16(REG_SDIRMASK0,0);
|
||||||
|
sdmmc_write16(REG_SDIRMASK1,0);
|
||||||
|
sdmmc_write16(REG_SDSTATUS0,0);
|
||||||
|
sdmmc_write16(REG_SDSTATUS1,0);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
// if(readdata)sdmmc_mask16(REG_DATACTL32, 0x1000, 0x800);
|
||||||
|
// if(writedata)sdmmc_mask16(REG_DATACTL32, 0x800, 0x1000);
|
||||||
|
// sdmmc_mask16(REG_DATACTL32,0x1800,2);
|
||||||
|
#else
|
||||||
|
sdmmc_mask16(REG_DATACTL32,0x1800,0);
|
||||||
|
#endif
|
||||||
|
sdmmc_write16(REG_SDCMDARG0,args &0xFFFF);
|
||||||
|
sdmmc_write16(REG_SDCMDARG1,args >> 16);
|
||||||
|
sdmmc_write16(REG_SDCMD,cmd &0xFFFF);
|
||||||
|
|
||||||
|
uint32_t size = ctx->size;
|
||||||
|
uint16_t *dataPtr = (uint16_t*)ctx->data;
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
uint32_t *dataPtr32 = (uint32_t*)ctx->data;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
bool useBuf = ( NULL != dataPtr );
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
bool useBuf32 = (useBuf && (0 == (3 & ((uint32_t)dataPtr))));
|
||||||
|
#endif
|
||||||
|
|
||||||
|
uint16_t status0 = 0;
|
||||||
|
while(1)
|
||||||
|
{
|
||||||
|
volatile uint16_t status1 = sdmmc_read16(REG_SDSTATUS1);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
volatile uint16_t ctl32 = sdmmc_read16(REG_DATACTL32);
|
||||||
|
if((ctl32 & 0x100))
|
||||||
|
#else
|
||||||
|
if((status1 & TMIO_STAT1_RXRDY))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if(readdata)
|
||||||
|
{
|
||||||
|
if(useBuf)
|
||||||
|
{
|
||||||
|
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_RXRDY, 0);
|
||||||
|
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_RXRDY);
|
||||||
|
if(size > 0x1FF)
|
||||||
|
{
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
if(useBuf32)
|
||||||
|
{
|
||||||
|
for(int i = 0; i<0x200; i+=4)
|
||||||
|
{
|
||||||
|
*dataPtr32++ = sdmmc_read32(REG_SDFIFO32);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
#endif
|
||||||
|
for(int i = 0; i<0x200; i+=2)
|
||||||
|
{
|
||||||
|
*dataPtr++ = sdmmc_read16(REG_SDFIFO);
|
||||||
|
}
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
size -= 0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdmmc_mask16(REG_DATACTL32, 0x800, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
if(!(ctl32 & 0x200))
|
||||||
|
#else
|
||||||
|
if((status1 & TMIO_STAT1_TXRQ))
|
||||||
|
#endif
|
||||||
|
{
|
||||||
|
if(writedata)
|
||||||
|
{
|
||||||
|
if(useBuf)
|
||||||
|
{
|
||||||
|
sdmmc_mask16(REG_SDSTATUS1, TMIO_STAT1_TXRQ, 0);
|
||||||
|
//sdmmc_write16(REG_SDSTATUS1,~TMIO_STAT1_TXRQ);
|
||||||
|
if(size > 0x1FF)
|
||||||
|
{
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
for(int i = 0; i<0x200; i+=4)
|
||||||
|
{
|
||||||
|
sdmmc_write32(REG_SDFIFO32,*dataPtr32++);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
for(int i = 0; i<0x200; i+=2)
|
||||||
|
{
|
||||||
|
sdmmc_write16(REG_SDFIFO,*dataPtr++);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
size -= 0x200;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sdmmc_mask16(REG_DATACTL32, 0x1000, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(status1 & TMIO_MASK_GW)
|
||||||
|
{
|
||||||
|
ctx->error |= 4;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!(status1 & TMIO_STAT1_CMD_BUSY))
|
||||||
|
{
|
||||||
|
status0 = sdmmc_read16(REG_SDSTATUS0);
|
||||||
|
if(sdmmc_read16(REG_SDSTATUS0) & TMIO_STAT0_CMDRESPEND)
|
||||||
|
{
|
||||||
|
ctx->error |= 0x1;
|
||||||
|
}
|
||||||
|
if(status0 & TMIO_STAT0_DATAEND)
|
||||||
|
{
|
||||||
|
ctx->error |= 0x2;
|
||||||
|
}
|
||||||
|
|
||||||
|
if((status0 & flags) == flags)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ctx->stat0 = sdmmc_read16(REG_SDSTATUS0);
|
||||||
|
ctx->stat1 = sdmmc_read16(REG_SDSTATUS1);
|
||||||
|
sdmmc_write16(REG_SDSTATUS0,0);
|
||||||
|
sdmmc_write16(REG_SDSTATUS1,0);
|
||||||
|
|
||||||
|
if(getSDRESP != 0)
|
||||||
|
{
|
||||||
|
ctx->ret[0] = sdmmc_read16(REG_SDRESP0) | (sdmmc_read16(REG_SDRESP1) << 16);
|
||||||
|
ctx->ret[1] = sdmmc_read16(REG_SDRESP2) | (sdmmc_read16(REG_SDRESP3) << 16);
|
||||||
|
ctx->ret[2] = sdmmc_read16(REG_SDRESP4) | (sdmmc_read16(REG_SDRESP5) << 16);
|
||||||
|
ctx->ret[3] = sdmmc_read16(REG_SDRESP6) | (sdmmc_read16(REG_SDRESP7) << 16);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int NO_INLINE sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in)
|
||||||
|
{
|
||||||
|
if(handelSD.isSDHC == 0) sector_no <<= 9;
|
||||||
|
inittarget(&handelSD);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
sdmmc_write16(REG_SDBLKLEN32,0x200);
|
||||||
|
#endif
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
handelSD.data = in;
|
||||||
|
handelSD.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handelSD,0x52C19,sector_no);
|
||||||
|
return geterror(&handelSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NO_INLINE sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
|
||||||
|
{
|
||||||
|
if(handelSD.isSDHC == 0) sector_no <<= 9;
|
||||||
|
inittarget(&handelSD);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
sdmmc_write16(REG_SDBLKLEN32,0x200);
|
||||||
|
#endif
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
handelSD.data = out;
|
||||||
|
handelSD.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handelSD,0x33C12,sector_no);
|
||||||
|
return geterror(&handelSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
int NO_INLINE sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out)
|
||||||
|
{
|
||||||
|
if(handelNAND.isSDHC == 0) sector_no <<= 9;
|
||||||
|
inittarget(&handelNAND);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
sdmmc_write16(REG_SDBLKLEN32,0x200);
|
||||||
|
#endif
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
handelNAND.data = out;
|
||||||
|
handelNAND.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handelNAND,0x33C12,sector_no);
|
||||||
|
inittarget(&handelSD);
|
||||||
|
return geterror(&handelNAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
int NO_INLINE sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in) //experimental
|
||||||
|
{
|
||||||
|
if(handelNAND.isSDHC == 0) sector_no <<= 9;
|
||||||
|
inittarget(&handelNAND);
|
||||||
|
sdmmc_write16(REG_SDSTOP,0x100);
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT32,numsectors);
|
||||||
|
sdmmc_write16(REG_SDBLKLEN32,0x200);
|
||||||
|
#endif
|
||||||
|
sdmmc_write16(REG_SDBLKCOUNT,numsectors);
|
||||||
|
handelNAND.data = in;
|
||||||
|
handelNAND.size = numsectors << 9;
|
||||||
|
sdmmc_send_command(&handelNAND,0x52C19,sector_no);
|
||||||
|
inittarget(&handelSD);
|
||||||
|
return geterror(&handelNAND);
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint32_t calcSDSize(uint8_t* csd, int type)
|
||||||
|
{
|
||||||
|
uint32_t result=0;
|
||||||
|
if(type == -1) type = csd[14] >> 6;
|
||||||
|
switch(type)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
uint32_t block_len=csd[9]&0xf;
|
||||||
|
block_len=1<<block_len;
|
||||||
|
uint32_t mult=(csd[4]>>7)|((csd[5]&3)<<1);
|
||||||
|
mult=1<<(mult+2);
|
||||||
|
result=csd[8]&3;
|
||||||
|
result=(result<<8)|csd[7];
|
||||||
|
result=(result<<2)|(csd[6]>>6);
|
||||||
|
result=(result+1)*mult*block_len/512;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
result=csd[7]&0x3f;
|
||||||
|
result=(result<<8)|csd[6];
|
||||||
|
result=(result<<8)|csd[5];
|
||||||
|
result=(result+1)*1024;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void InitSD()
|
||||||
|
{
|
||||||
|
//NAND
|
||||||
|
handelNAND.isSDHC = 0;
|
||||||
|
handelNAND.SDOPT = 0;
|
||||||
|
handelNAND.res = 0;
|
||||||
|
handelNAND.initarg = 1;
|
||||||
|
handelNAND.clk = 0x80;
|
||||||
|
handelNAND.devicenumber = 1;
|
||||||
|
|
||||||
|
//SD
|
||||||
|
handelSD.isSDHC = 0;
|
||||||
|
handelSD.SDOPT = 0;
|
||||||
|
handelSD.res = 0;
|
||||||
|
handelSD.initarg = 0;
|
||||||
|
handelSD.clk = 0x80;
|
||||||
|
handelSD.devicenumber = 0;
|
||||||
|
|
||||||
|
//sdmmc_mask16(0x100,0x800,0);
|
||||||
|
//sdmmc_mask16(0x100,0x1000,0);
|
||||||
|
//sdmmc_mask16(0x100,0x0,0x402);
|
||||||
|
//sdmmc_mask16(0xD8,0x22,0x2);
|
||||||
|
//sdmmc_mask16(0x100,0x2,0);
|
||||||
|
//sdmmc_mask16(0xD8,0x22,0);
|
||||||
|
//sdmmc_write16(0x104,0);
|
||||||
|
//sdmmc_write16(0x108,1);
|
||||||
|
//sdmmc_mask16(REG_SDRESET,1,0); //not in new Version -- nintendo's code does this
|
||||||
|
//sdmmc_mask16(REG_SDRESET,0,1); //not in new Version -- nintendo's code does this
|
||||||
|
//sdmmc_mask16(0x20,0,0x31D);
|
||||||
|
//sdmmc_mask16(0x22,0,0x837F);
|
||||||
|
//sdmmc_mask16(0xFC,0,0xDB);
|
||||||
|
//sdmmc_mask16(0xFE,0,0xDB);
|
||||||
|
////sdmmc_write16(REG_SDCLKCTL,0x20);
|
||||||
|
////sdmmc_write16(REG_SDOPT,0x40EE);
|
||||||
|
////sdmmc_mask16(0x02,0x3,0);
|
||||||
|
//sdmmc_write16(REG_SDCLKCTL,0x40);
|
||||||
|
//sdmmc_write16(REG_SDOPT,0x40EB);
|
||||||
|
//sdmmc_mask16(0x02,0x3,0);
|
||||||
|
//sdmmc_write16(REG_SDBLKLEN,0x200);
|
||||||
|
//sdmmc_write16(REG_SDSTOP,0);
|
||||||
|
|
||||||
|
*(volatile uint16_t*)0x10006100 &= 0xF7FFu; //SDDATACTL32
|
||||||
|
*(volatile uint16_t*)0x10006100 &= 0xEFFFu; //SDDATACTL32
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
*(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
|
||||||
|
#else
|
||||||
|
*(volatile uint16_t*)0x10006100 |= 0x402u; //SDDATACTL32
|
||||||
|
#endif
|
||||||
|
*(volatile uint16_t*)0x100060D8 = (*(volatile uint16_t*)0x100060D8 & 0xFFDD) | 2;
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
*(volatile uint16_t*)0x10006100 &= 0xFFFFu; //SDDATACTL32
|
||||||
|
*(volatile uint16_t*)0x100060D8 &= 0xFFDFu; //SDDATACTL
|
||||||
|
*(volatile uint16_t*)0x10006104 = 512; //SDBLKLEN32
|
||||||
|
#else
|
||||||
|
*(volatile uint16_t*)0x10006100 &= 0xFFFDu; //SDDATACTL32
|
||||||
|
*(volatile uint16_t*)0x100060D8 &= 0xFFDDu; //SDDATACTL
|
||||||
|
*(volatile uint16_t*)0x10006104 = 0; //SDBLKLEN32
|
||||||
|
#endif
|
||||||
|
*(volatile uint16_t*)0x10006108 = 1; //SDBLKCOUNT32
|
||||||
|
*(volatile uint16_t*)0x100060E0 &= 0xFFFEu; //SDRESET
|
||||||
|
*(volatile uint16_t*)0x100060E0 |= 1u; //SDRESET
|
||||||
|
*(volatile uint16_t*)0x10006020 |= TMIO_MASK_ALL; //SDIR_MASK0
|
||||||
|
*(volatile uint16_t*)0x10006022 |= TMIO_MASK_ALL>>16; //SDIR_MASK1
|
||||||
|
*(volatile uint16_t*)0x100060FC |= 0xDBu; //SDCTL_RESERVED7
|
||||||
|
*(volatile uint16_t*)0x100060FE |= 0xDBu; //SDCTL_RESERVED8
|
||||||
|
*(volatile uint16_t*)0x10006002 &= 0xFFFCu; //SDPORTSEL
|
||||||
|
#ifdef DATA32_SUPPORT
|
||||||
|
*(volatile uint16_t*)0x10006024 = 0x20;
|
||||||
|
*(volatile uint16_t*)0x10006028 = 0x40EE;
|
||||||
|
#else
|
||||||
|
*(volatile uint16_t*)0x10006024 = 0x40; //Nintendo sets this to 0x20
|
||||||
|
*(volatile uint16_t*)0x10006028 = 0x40EB; //Nintendo sets this to 0x40EE
|
||||||
|
#endif
|
||||||
|
*(volatile uint16_t*)0x10006002 &= 0xFFFCu; ////SDPORTSEL
|
||||||
|
*(volatile uint16_t*)0x10006026 = 512; //SDBLKLEN
|
||||||
|
*(volatile uint16_t*)0x10006008 = 0; //SDSTOP
|
||||||
|
|
||||||
|
inittarget(&handelSD);
|
||||||
|
}
|
||||||
|
|
||||||
|
int Nand_Init()
|
||||||
|
{
|
||||||
|
inittarget(&handelNAND);
|
||||||
|
waitcycles(0xF000);
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x00000 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0,0);
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10701 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sdmmc_send_command(&handelNAND,0x10701,0x100000);
|
||||||
|
DEBUGPRINT(topScreen, "error ", handelNAND.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
DEBUGPRINT(topScreen, "ret: ", handelNAND.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
DEBUGPRINT(topScreen, "test ", 3, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
} while ( !(handelNAND.error & 1) );
|
||||||
|
}
|
||||||
|
while((handelNAND.ret[0] & 0x80000000) == 0);
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10602 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10602,0x0);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10403 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10403,handelNAND.initarg << 0x10);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10609 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10609,handelNAND.initarg << 0x10);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10407 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
handelNAND.total_size = calcSDSize((uint8_t*)&handelNAND.ret[0],0);
|
||||||
|
handelNAND.clk = 1;
|
||||||
|
setckl(1);
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10407,handelNAND.initarg << 0x10);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
handelNAND.SDOPT = 1;
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10506,0x3B70100);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10506 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10506,0x3B90100);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x1040D ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x1040D,handelNAND.initarg << 0x10);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10410 ", handelNAND.error, 10, 20 + 13*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelNAND,0x10410,0x200);
|
||||||
|
if((handelNAND.error & 0x4))return -1;
|
||||||
|
|
||||||
|
handelNAND.clk |= 0x200;
|
||||||
|
|
||||||
|
inittarget(&handelSD);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SD_Init()
|
||||||
|
{
|
||||||
|
inittarget(&handelSD);
|
||||||
|
//waitcycles(0x3E8);
|
||||||
|
waitcycles(0xF000);
|
||||||
|
DEBUGPRINT(topScreen, "0x00000 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
sdmmc_send_command(&handelSD,0,0);
|
||||||
|
DEBUGPRINT(topScreen, "0x10408 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
sdmmc_send_command(&handelSD,0x10408,0x1AA);
|
||||||
|
//uint32_t temp = (handelSD.ret[0] == 0x1AA) << 0x1E;
|
||||||
|
uint32_t temp = (handelSD.error & 0x1) << 0x1E;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10769 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 15*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
DEBUGPRINT(topScreen, "temp: ", temp, 10, 20 + 16*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
//int count = 0;
|
||||||
|
uint32_t temp2 = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
do
|
||||||
|
{
|
||||||
|
sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
|
||||||
|
sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
|
||||||
|
temp2 = 1;
|
||||||
|
} while ( !(handelSD.error & 1) );
|
||||||
|
|
||||||
|
//DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
//DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
//DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
}
|
||||||
|
while((handelSD.ret[0] & 0x80000000) == 0);
|
||||||
|
//do
|
||||||
|
//{
|
||||||
|
// sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
|
||||||
|
// sdmmc_send_command(&handelSD,0x10769,0x00FF8000 | temp);
|
||||||
|
//
|
||||||
|
// DEBUGPRINT(topScreen, "sd error ", handelSD.error, 10, 20 + 17*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
// DEBUGPRINT(topScreen, "sd ret: ", handelSD.ret[0], 10, 20 + 18*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
// DEBUGPRINT(topScreen, "count: ", count++, 10, 20 + 19*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
//}
|
||||||
|
//while(!(handelSD.ret[0] & 0x80000000));
|
||||||
|
|
||||||
|
if(!((handelSD.ret[0] >> 30) & 1) || !temp)
|
||||||
|
temp2 = 0;
|
||||||
|
|
||||||
|
handelSD.isSDHC = temp2;
|
||||||
|
//handelSD.isSDHC = (handelSD.ret[0] & 0x40000000);
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10602 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x10602,0);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10403 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x10403,0);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
handelSD.initarg = handelSD.ret[0] >> 0x10;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10609 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x10609,handelSD.initarg << 0x10);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
|
||||||
|
handelSD.total_size = calcSDSize((uint8_t*)&handelSD.ret[0],-1);
|
||||||
|
handelSD.clk = 1;
|
||||||
|
setckl(1);
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10507 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x10507,handelSD.initarg << 0x10);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10437 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x10437,handelSD.initarg << 0x10);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10446 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
handelSD.SDOPT = 1;
|
||||||
|
sdmmc_send_command(&handelSD,0x10446,0x2);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x1040D ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x1040D,handelSD.initarg << 0x10);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
|
||||||
|
DEBUGPRINT(topScreen, "0x10410 ", handelSD.error, 10, 20 + 14*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
|
||||||
|
sdmmc_send_command(&handelSD,0x10410,0x200);
|
||||||
|
if((handelSD.error & 0x4)) return -1;
|
||||||
|
handelSD.clk |= 0x200;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void sdmmc_sdcard_init()
|
||||||
|
{
|
||||||
|
DEBUGPRINT(topScreen, "sdmmc_sdcard_init ", handelSD.error, 10, 20 + 2*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
InitSD();
|
||||||
|
//SD_Init2();
|
||||||
|
//Nand_Init();
|
||||||
|
Nand_Init();
|
||||||
|
DEBUGPRINT(topScreen, "nand_res ", nand_res, 10, 20 + 3*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
SD_Init();
|
||||||
|
DEBUGPRINT(topScreen, "sd_res ", sd_res, 10, 20 + 4*8, RGB(40, 40, 40), RGB(208, 208, 208));
|
||||||
|
}
|
184
source/fatfs/sdmmc.h
Normal file
184
source/fatfs/sdmmc.h
Normal file
@ -0,0 +1,184 @@
|
|||||||
|
#ifndef __SDMMC_H__
|
||||||
|
#define __SDMMC_H__
|
||||||
|
|
||||||
|
#define TRUE 1
|
||||||
|
#define FALSE 0
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#define SDMMC_BASE 0x10006000
|
||||||
|
|
||||||
|
#define REG_SDCMD 0x00
|
||||||
|
#define REG_SDPORTSEL 0x02
|
||||||
|
#define REG_SDCMDARG 0x04
|
||||||
|
#define REG_SDCMDARG0 0x04
|
||||||
|
#define REG_SDCMDARG1 0x06
|
||||||
|
#define REG_SDSTOP 0x08
|
||||||
|
#define REG_SDBLKCOUNT 0x0a
|
||||||
|
|
||||||
|
#define REG_SDRESP0 0x0c
|
||||||
|
#define REG_SDRESP1 0x0e
|
||||||
|
#define REG_SDRESP2 0x10
|
||||||
|
#define REG_SDRESP3 0x12
|
||||||
|
#define REG_SDRESP4 0x14
|
||||||
|
#define REG_SDRESP5 0x16
|
||||||
|
#define REG_SDRESP6 0x18
|
||||||
|
#define REG_SDRESP7 0x1a
|
||||||
|
|
||||||
|
#define REG_SDSTATUS0 0x1c
|
||||||
|
#define REG_SDSTATUS1 0x1e
|
||||||
|
|
||||||
|
#define REG_SDIRMASK0 0x20
|
||||||
|
#define REG_SDIRMASK1 0x22
|
||||||
|
#define REG_SDCLKCTL 0x24
|
||||||
|
|
||||||
|
#define REG_SDBLKLEN 0x26
|
||||||
|
#define REG_SDOPT 0x28
|
||||||
|
#define REG_SDFIFO 0x30
|
||||||
|
|
||||||
|
#define REG_DATACTL 0xd8
|
||||||
|
#define REG_SDRESET 0xe0
|
||||||
|
#define REG_SDPROTECTED 0xf6 //bit 0 determines if sd is protected or not?
|
||||||
|
|
||||||
|
#define REG_DATACTL32 0x100
|
||||||
|
#define REG_SDBLKLEN32 0x104
|
||||||
|
#define REG_SDBLKCOUNT32 0x108
|
||||||
|
#define REG_SDFIFO32 0x10C
|
||||||
|
|
||||||
|
#define REG_CLK_AND_WAIT_CTL 0x138
|
||||||
|
#define REG_RESET_SDIO 0x1e0
|
||||||
|
|
||||||
|
#define TMIO_STAT0_CMDRESPEND 0x0001
|
||||||
|
#define TMIO_STAT0_DATAEND 0x0004
|
||||||
|
#define TMIO_STAT0_CARD_REMOVE 0x0008
|
||||||
|
#define TMIO_STAT0_CARD_INSERT 0x0010
|
||||||
|
#define TMIO_STAT0_SIGSTATE 0x0020
|
||||||
|
#define TMIO_STAT0_WRPROTECT 0x0080
|
||||||
|
#define TMIO_STAT0_CARD_REMOVE_A 0x0100
|
||||||
|
#define TMIO_STAT0_CARD_INSERT_A 0x0200
|
||||||
|
#define TMIO_STAT0_SIGSTATE_A 0x0400
|
||||||
|
#define TMIO_STAT1_CMD_IDX_ERR 0x0001
|
||||||
|
#define TMIO_STAT1_CRCFAIL 0x0002
|
||||||
|
#define TMIO_STAT1_STOPBIT_ERR 0x0004
|
||||||
|
#define TMIO_STAT1_DATATIMEOUT 0x0008
|
||||||
|
#define TMIO_STAT1_RXOVERFLOW 0x0010
|
||||||
|
#define TMIO_STAT1_TXUNDERRUN 0x0020
|
||||||
|
#define TMIO_STAT1_CMDTIMEOUT 0x0040
|
||||||
|
#define TMIO_STAT1_RXRDY 0x0100
|
||||||
|
#define TMIO_STAT1_TXRQ 0x0200
|
||||||
|
#define TMIO_STAT1_ILL_FUNC 0x2000
|
||||||
|
#define TMIO_STAT1_CMD_BUSY 0x4000
|
||||||
|
#define TMIO_STAT1_ILL_ACCESS 0x8000
|
||||||
|
|
||||||
|
//Comes from TWLSDK mongoose.tef DWARF info
|
||||||
|
#define SDMC_NORMAL 0x00000000
|
||||||
|
#define SDMC_ERR_COMMAND 0x00000001
|
||||||
|
#define SDMC_ERR_CRC 0x00000002
|
||||||
|
#define SDMC_ERR_END 0x00000004
|
||||||
|
#define SDMC_ERR_TIMEOUT 0x00000008
|
||||||
|
#define SDMC_ERR_FIFO_OVF 0x00000010
|
||||||
|
#define SDMC_ERR_FIFO_UDF 0x00000020
|
||||||
|
#define SDMC_ERR_WP 0x00000040
|
||||||
|
#define SDMC_ERR_ABORT 0x00000080
|
||||||
|
#define SDMC_ERR_FPGA_TIMEOUT 0x00000100
|
||||||
|
#define SDMC_ERR_PARAM 0x00000200
|
||||||
|
#define SDMC_ERR_R1_STATUS 0x00000800
|
||||||
|
#define SDMC_ERR_NUM_WR_SECTORS 0x00001000
|
||||||
|
#define SDMC_ERR_RESET 0x00002000
|
||||||
|
#define SDMC_ERR_ILA 0x00004000
|
||||||
|
#define SDMC_ERR_INFO_DETECT 0x00008000
|
||||||
|
|
||||||
|
#define SDMC_STAT_ERR_UNKNOWN 0x00080000
|
||||||
|
#define SDMC_STAT_ERR_CC 0x00100000
|
||||||
|
#define SDMC_STAT_ERR_ECC_FAILED 0x00200000
|
||||||
|
#define SDMC_STAT_ERR_CRC 0x00800000
|
||||||
|
#define SDMC_STAT_ERR_OTHER 0xf9c70008
|
||||||
|
|
||||||
|
#define TMIO_MASK_ALL 0x837f031d
|
||||||
|
|
||||||
|
#define TMIO_MASK_GW (TMIO_STAT1_ILL_ACCESS | TMIO_STAT1_CMDTIMEOUT | TMIO_STAT1_TXUNDERRUN | TMIO_STAT1_RXOVERFLOW | \
|
||||||
|
TMIO_STAT1_DATATIMEOUT | TMIO_STAT1_STOPBIT_ERR | TMIO_STAT1_CRCFAIL | TMIO_STAT1_CMD_IDX_ERR)
|
||||||
|
|
||||||
|
#define TMIO_MASK_READOP (TMIO_STAT1_RXRDY | TMIO_STAT1_DATAEND)
|
||||||
|
#define TMIO_MASK_WRITEOP (TMIO_STAT1_TXRQ | TMIO_STAT1_DATAEND)
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
typedef struct mmcdevice {
|
||||||
|
uint8_t* data;
|
||||||
|
uint32_t size;
|
||||||
|
uint32_t error;
|
||||||
|
uint16_t stat0;
|
||||||
|
uint16_t stat1;
|
||||||
|
uint32_t ret[4];
|
||||||
|
uint32_t initarg;
|
||||||
|
uint32_t isSDHC;
|
||||||
|
uint32_t clk;
|
||||||
|
uint32_t SDOPT;
|
||||||
|
uint32_t devicenumber;
|
||||||
|
uint32_t total_size; //size in sectors of the device
|
||||||
|
uint32_t res;
|
||||||
|
} mmcdevice;
|
||||||
|
|
||||||
|
void sdmmc_sdcard_init();
|
||||||
|
int sdmmc_sdcard_readsector(uint32_t sector_no, uint8_t *out);
|
||||||
|
int sdmmc_sdcard_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
|
||||||
|
int sdmmc_sdcard_writesector(uint32_t sector_no, uint8_t *in);
|
||||||
|
int sdmmc_sdcard_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
|
||||||
|
|
||||||
|
int sdmmc_nand_readsectors(uint32_t sector_no, uint32_t numsectors, uint8_t *out);
|
||||||
|
int sdmmc_nand_writesectors(uint32_t sector_no, uint32_t numsectors, uint8_t *in);
|
||||||
|
|
||||||
|
mmcdevice *getMMCDevice(int drive);
|
||||||
|
|
||||||
|
void InitSD();
|
||||||
|
int Nand_Init();
|
||||||
|
int SD_Init();
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
};
|
||||||
|
#endif
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static inline uint16_t sdmmc_read16(uint16_t reg) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
return *(volatile uint16_t*)(SDMMC_BASE + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static inline void sdmmc_write16(uint16_t reg, uint16_t val) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
*(volatile uint16_t*)(SDMMC_BASE + reg) = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static inline uint32_t sdmmc_read32(uint16_t reg) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
return *(volatile uint32_t*)(SDMMC_BASE + reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static inline void sdmmc_write32(uint16_t reg, uint32_t val) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
*(volatile uint32_t*)(SDMMC_BASE + reg) = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static inline void sdmmc_mask16(uint16_t reg, const uint16_t clear, const uint16_t set) {
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
uint16_t val = sdmmc_read16(reg);
|
||||||
|
val &= ~clear;
|
||||||
|
val |= set;
|
||||||
|
sdmmc_write16(reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void setckl(uint32_t data)
|
||||||
|
{
|
||||||
|
sdmmc_mask16(REG_SDCLKCTL,0x100,0);
|
||||||
|
sdmmc_mask16(REG_SDCLKCTL,0x2FF,data&0x2FF);
|
||||||
|
sdmmc_mask16(REG_SDCLKCTL,0x0,0x100);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
144
source/font.h
Normal file
144
source/font.h
Normal file
@ -0,0 +1,144 @@
|
|||||||
|
/*
|
||||||
|
This file was autogenerated by raw2c.
|
||||||
|
Visit http://www.devkitpro.org
|
||||||
|
*/
|
||||||
|
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
#ifndef _font_h_
|
||||||
|
#define _font_h_
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
static const unsigned char font[] = {
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7e, 0x81, 0xa5, 0x81, 0xbd, 0x99, 0x81, 0x7e,
|
||||||
|
0x7e, 0xff, 0xdb, 0xff, 0xc3, 0xe7, 0xff, 0x7e, 0x6c, 0xfe, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00,
|
||||||
|
0x10, 0x38, 0x7c, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x3c, 0x3c, 0x18, 0xff, 0xe7, 0x18, 0x3c, 0x00,
|
||||||
|
0x10, 0x38, 0x7c, 0xfe, 0xee, 0x10, 0x38, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x00, 0x00,
|
||||||
|
0xff, 0xff, 0xe7, 0xc3, 0xc3, 0xe7, 0xff, 0xff, 0x00, 0x3c, 0x66, 0x42, 0x42, 0x66, 0x3c, 0x00,
|
||||||
|
0xff, 0xc3, 0x99, 0xbd, 0xbd, 0x99, 0xc3, 0xff, 0x0f, 0x07, 0x0f, 0x7d, 0xcc, 0xcc, 0xcc, 0x78,
|
||||||
|
0x3c, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x08, 0x0c, 0x0a, 0x0a, 0x08, 0x78, 0xf0, 0x00,
|
||||||
|
0x18, 0x14, 0x1a, 0x16, 0x72, 0xe2, 0x0e, 0x1c, 0x10, 0x54, 0x38, 0xee, 0x38, 0x54, 0x10, 0x00,
|
||||||
|
0x80, 0xe0, 0xf8, 0xfe, 0xf8, 0xe0, 0x80, 0x00, 0x02, 0x0e, 0x3e, 0xfe, 0x3e, 0x0e, 0x02, 0x00,
|
||||||
|
0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x00, 0x66, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x00,
|
||||||
|
0x7f, 0xdb, 0xdb, 0xdb, 0x7b, 0x1b, 0x1b, 0x00, 0x1c, 0x22, 0x38, 0x44, 0x44, 0x38, 0x88, 0x70,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x7e, 0x7e, 0x7e, 0x00, 0x18, 0x3c, 0x5a, 0x18, 0x5a, 0x3c, 0x18, 0x7e,
|
||||||
|
0x18, 0x3c, 0x5a, 0x18, 0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x18, 0x5a, 0x3c, 0x18, 0x00,
|
||||||
|
0x00, 0x18, 0x0c, 0xfe, 0x0c, 0x18, 0x00, 0x00, 0x00, 0x30, 0x60, 0xfe, 0x60, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0xc0, 0xc0, 0xc0, 0xfe, 0x00, 0x00, 0x00, 0x24, 0x42, 0xff, 0x42, 0x24, 0x00, 0x00,
|
||||||
|
0x00, 0x10, 0x38, 0x7c, 0xfe, 0xfe, 0x00, 0x00, 0x00, 0xfe, 0xfe, 0x7c, 0x38, 0x10, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x3c, 0x3c, 0x18, 0x18, 0x00, 0x18, 0x00,
|
||||||
|
0x6c, 0x24, 0x24, 0x00, 0x00, 0x00, 0x00, 0x00, 0x6c, 0x6c, 0xfe, 0x6c, 0xfe, 0x6c, 0x6c, 0x00,
|
||||||
|
0x10, 0x7c, 0xd0, 0x7c, 0x16, 0xfc, 0x10, 0x00, 0x00, 0x66, 0xac, 0xd8, 0x36, 0x6a, 0xcc, 0x00,
|
||||||
|
0x38, 0x4c, 0x38, 0x78, 0xce, 0xcc, 0x7a, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x30, 0x60, 0x60, 0x60, 0x30, 0x18, 0x00, 0x60, 0x30, 0x18, 0x18, 0x18, 0x30, 0x60, 0x00,
|
||||||
|
0x00, 0x66, 0x3c, 0xff, 0x3c, 0x66, 0x00, 0x00, 0x00, 0x30, 0x30, 0xfc, 0x30, 0x30, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20, 0x00, 0x00, 0x00, 0xfc, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x02, 0x06, 0x0c, 0x18, 0x30, 0x60, 0xc0, 0x00,
|
||||||
|
0x7c, 0xce, 0xde, 0xf6, 0xe6, 0xe6, 0x7c, 0x00, 0x18, 0x38, 0x78, 0x18, 0x18, 0x18, 0x7e, 0x00,
|
||||||
|
0x7c, 0xc6, 0x06, 0x1c, 0x70, 0xc6, 0xfe, 0x00, 0x7c, 0xc6, 0x06, 0x3c, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x1c, 0x3c, 0x6c, 0xcc, 0xfe, 0x0c, 0x1e, 0x00, 0xfe, 0xc0, 0xfc, 0x06, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc0, 0xfc, 0xc6, 0xc6, 0x7c, 0x00, 0xfe, 0xc6, 0x0c, 0x18, 0x30, 0x30, 0x30, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc6, 0x7c, 0xc6, 0xc6, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0x7e, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x30, 0x10, 0x20,
|
||||||
|
0x0c, 0x18, 0x30, 0x60, 0x30, 0x18, 0x0c, 0x00, 0x00, 0x00, 0x7e, 0x00, 0x00, 0x7e, 0x00, 0x00,
|
||||||
|
0x60, 0x30, 0x18, 0x0c, 0x18, 0x30, 0x60, 0x00, 0x78, 0xcc, 0x0c, 0x18, 0x30, 0x00, 0x30, 0x00,
|
||||||
|
0x7c, 0x82, 0x9e, 0xa6, 0x9e, 0x80, 0x7c, 0x00, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00,
|
||||||
|
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xfc, 0x00, 0x7c, 0xc6, 0xc0, 0xc0, 0xc0, 0xc6, 0x7c, 0x00,
|
||||||
|
0xfc, 0x66, 0x66, 0x66, 0x66, 0x66, 0xfc, 0x00, 0xfe, 0x62, 0x68, 0x78, 0x68, 0x62, 0xfe, 0x00,
|
||||||
|
0xfe, 0x62, 0x68, 0x78, 0x68, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc0, 0xce, 0xc6, 0x7e, 0x00,
|
||||||
|
0xc6, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0xc6, 0x00, 0x3c, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x1e, 0x0c, 0x0c, 0x0c, 0xcc, 0xcc, 0x78, 0x00, 0xe6, 0x66, 0x6c, 0x78, 0x6c, 0x66, 0xe6, 0x00,
|
||||||
|
0xf0, 0x60, 0x60, 0x60, 0x62, 0x66, 0xfe, 0x00, 0x82, 0xc6, 0xee, 0xfe, 0xd6, 0xc6, 0xc6, 0x00,
|
||||||
|
0xc6, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xfc, 0x66, 0x66, 0x7c, 0x60, 0x60, 0xf0, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xd6, 0xde, 0x7c, 0x06,
|
||||||
|
0xfc, 0x66, 0x66, 0x7c, 0x66, 0x66, 0xe6, 0x00, 0x7c, 0xc6, 0xc0, 0x7c, 0x06, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7e, 0x5a, 0x5a, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xc6, 0xc6, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0xc6, 0xc6, 0xd6, 0xfe, 0xee, 0xc6, 0x82, 0x00,
|
||||||
|
0xc6, 0x6c, 0x38, 0x38, 0x38, 0x6c, 0xc6, 0x00, 0x66, 0x66, 0x66, 0x3c, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0xfe, 0xc6, 0x8c, 0x18, 0x32, 0x66, 0xfe, 0x00, 0x78, 0x60, 0x60, 0x60, 0x60, 0x60, 0x78, 0x00,
|
||||||
|
0xc0, 0x60, 0x30, 0x18, 0x0c, 0x06, 0x02, 0x00, 0x78, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0x00,
|
||||||
|
0x10, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff,
|
||||||
|
0x30, 0x20, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
|
||||||
|
0xe0, 0x60, 0x60, 0x7c, 0x66, 0x66, 0x7c, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc0, 0xc6, 0x7c, 0x00,
|
||||||
|
0x1c, 0x0c, 0x0c, 0x7c, 0xcc, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
|
||||||
|
0x1c, 0x36, 0x30, 0x78, 0x30, 0x30, 0x78, 0x00, 0x00, 0x00, 0x76, 0xcc, 0xcc, 0x7c, 0x0c, 0x78,
|
||||||
|
0xe0, 0x60, 0x6c, 0x76, 0x66, 0x66, 0xe6, 0x00, 0x18, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x00, 0x0c, 0x00, 0x1c, 0x0c, 0x0c, 0xcc, 0x78, 0xe0, 0x60, 0x66, 0x6c, 0x78, 0x6c, 0xe6, 0x00,
|
||||||
|
0x38, 0x18, 0x18, 0x18, 0x18, 0x18, 0x3c, 0x00, 0x00, 0x00, 0xcc, 0xfe, 0xd6, 0xd6, 0xd6, 0x00,
|
||||||
|
0x00, 0x00, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0x00, 0x00, 0xdc, 0x66, 0x66, 0x7c, 0x60, 0xf0, 0x00, 0x00, 0x7c, 0xcc, 0xcc, 0x7c, 0x0c, 0x1e,
|
||||||
|
0x00, 0x00, 0xde, 0x76, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0x7c, 0x06, 0x7c, 0x00,
|
||||||
|
0x10, 0x30, 0xfc, 0x30, 0x30, 0x34, 0x18, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0x00, 0x00, 0xc6, 0xc6, 0x6c, 0x38, 0x10, 0x00, 0x00, 0x00, 0xc6, 0xd6, 0xd6, 0xfe, 0x6c, 0x00,
|
||||||
|
0x00, 0x00, 0xc6, 0x6c, 0x38, 0x6c, 0xc6, 0x00, 0x00, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8,
|
||||||
|
0x00, 0x00, 0xfc, 0x98, 0x30, 0x64, 0xfc, 0x00, 0x0e, 0x18, 0x18, 0x30, 0x18, 0x18, 0x0e, 0x00,
|
||||||
|
0x18, 0x18, 0x18, 0x00, 0x18, 0x18, 0x18, 0x00, 0xe0, 0x30, 0x30, 0x18, 0x30, 0x30, 0xe0, 0x00,
|
||||||
|
0x76, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x38, 0x6c, 0xc6, 0xc6, 0xfe, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc0, 0xc0, 0xc6, 0x7c, 0x18, 0x70, 0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0x0e, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x7c, 0x82, 0x38, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
|
||||||
|
0xcc, 0x00, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00,
|
||||||
|
0x30, 0x30, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x00, 0x00, 0x7c, 0xc0, 0xc0, 0x7c, 0x18, 0x70,
|
||||||
|
0x7c, 0x82, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00,
|
||||||
|
0xe0, 0x10, 0x7c, 0xc6, 0xfe, 0xc0, 0x7c, 0x00, 0x66, 0x00, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x7c, 0x82, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00, 0xe0, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0xc6, 0x00, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00, 0x38, 0x38, 0x7c, 0xc6, 0xfe, 0xc6, 0xc6, 0x00,
|
||||||
|
0x0e, 0x10, 0xfe, 0x60, 0x78, 0x60, 0xfe, 0x00, 0x00, 0x00, 0x7c, 0x12, 0x7e, 0xd0, 0x7e, 0x00,
|
||||||
|
0x7e, 0xc8, 0xc8, 0xfe, 0xc8, 0xc8, 0xce, 0x00, 0x7c, 0x82, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xc6, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0xe0, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7c, 0x82, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00, 0xe0, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0xcc, 0x00, 0xcc, 0xcc, 0xcc, 0x7c, 0x0c, 0xf8, 0xc6, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0xc6, 0x00, 0xc6, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x18, 0x7c, 0xd6, 0xd0, 0xd6, 0x7c, 0x18, 0x00,
|
||||||
|
0x38, 0x6c, 0x60, 0xf0, 0x60, 0xf2, 0xdc, 0x00, 0x66, 0x3c, 0x18, 0x7e, 0x18, 0x7e, 0x18, 0x00,
|
||||||
|
0xf8, 0xcc, 0xf8, 0xc4, 0xcc, 0xde, 0xcc, 0x06, 0x0e, 0x1b, 0x18, 0x3c, 0x18, 0x18, 0xd8, 0x70,
|
||||||
|
0x0e, 0x10, 0x78, 0x0c, 0x7c, 0xcc, 0x76, 0x00, 0x0e, 0x10, 0x38, 0x18, 0x18, 0x18, 0x3c, 0x00,
|
||||||
|
0x0e, 0x10, 0x7c, 0xc6, 0xc6, 0xc6, 0x7c, 0x00, 0x0e, 0x10, 0xcc, 0xcc, 0xcc, 0xcc, 0x76, 0x00,
|
||||||
|
0x66, 0x98, 0xdc, 0x66, 0x66, 0x66, 0x66, 0x00, 0x66, 0x98, 0xe6, 0xf6, 0xde, 0xce, 0xc6, 0x00,
|
||||||
|
0x38, 0x0c, 0x3c, 0x34, 0x00, 0x7e, 0x00, 0x00, 0x38, 0x6c, 0x6c, 0x38, 0x00, 0x7c, 0x00, 0x00,
|
||||||
|
0x30, 0x00, 0x30, 0x60, 0xc6, 0xc6, 0x7c, 0x00, 0x00, 0x00, 0x00, 0xfc, 0xc0, 0xc0, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0xfc, 0x0c, 0x0c, 0x00, 0x00, 0xc0, 0xc8, 0xd0, 0xfe, 0x46, 0x8c, 0x1e, 0x00,
|
||||||
|
0xc0, 0xc8, 0xd0, 0xec, 0x5c, 0xbe, 0x0c, 0x00, 0x18, 0x00, 0x18, 0x18, 0x3c, 0x3c, 0x18, 0x00,
|
||||||
|
0x00, 0x36, 0x6c, 0xd8, 0x6c, 0x36, 0x00, 0x00, 0x00, 0xd8, 0x6c, 0x36, 0x6c, 0xd8, 0x00, 0x00,
|
||||||
|
0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x22, 0x88, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa, 0x55, 0xaa,
|
||||||
|
0xdb, 0x77, 0xdb, 0xee, 0xdb, 0x77, 0xdb, 0xee, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0xf6, 0x36, 0x36, 0x36, 0x00, 0x00, 0x00, 0x00, 0xfe, 0x36, 0x36, 0x36,
|
||||||
|
0x00, 0x00, 0xf8, 0x18, 0xf8, 0x18, 0x18, 0x18, 0x36, 0x36, 0xf6, 0x06, 0xf6, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x00, 0x00, 0xfe, 0x06, 0xf6, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0xf6, 0x06, 0xfe, 0x00, 0x00, 0x00, 0x36, 0x36, 0x36, 0x36, 0xfe, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x18, 0xf8, 0x18, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf8, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x18, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x1f, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0x00, 0x18, 0x18, 0x18, 0x18, 0xff, 0x18, 0x18, 0x18,
|
||||||
|
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18, 0x36, 0x36, 0x36, 0x36, 0x37, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x37, 0x30, 0x3f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3f, 0x30, 0x37, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0xf7, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xf7, 0x36, 0x36, 0x36,
|
||||||
|
0x36, 0x36, 0x37, 0x30, 0x37, 0x36, 0x36, 0x36, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x36, 0xf7, 0x00, 0xf7, 0x36, 0x36, 0x36, 0x18, 0x18, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00,
|
||||||
|
0x36, 0x36, 0x36, 0x36, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x3f, 0x00, 0x00, 0x00,
|
||||||
|
0x18, 0x18, 0x1f, 0x18, 0x1f, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x1f, 0x18, 0x18, 0x18,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x3f, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0xff, 0x36, 0x36, 0x36,
|
||||||
|
0x18, 0x18, 0xff, 0x18, 0xff, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xf8, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x1f, 0x18, 0x18, 0x18, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0xff, 0xff, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0, 0xf0,
|
||||||
|
0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0x0f, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x74, 0xcc, 0xc8, 0xdc, 0x76, 0x00, 0x78, 0xcc, 0xd8, 0xcc, 0xc6, 0xc6, 0xdc, 0x40,
|
||||||
|
0xfe, 0x62, 0x60, 0x60, 0x60, 0x60, 0xf0, 0x00, 0x00, 0x02, 0x7e, 0xec, 0x6c, 0x6c, 0x48, 0x00,
|
||||||
|
0xfe, 0x62, 0x30, 0x18, 0x30, 0x62, 0xfe, 0x00, 0x00, 0x00, 0x7e, 0xd0, 0xc8, 0xc8, 0x70, 0x00,
|
||||||
|
0x00, 0x00, 0xcc, 0xcc, 0xcc, 0xcc, 0xf8, 0x80, 0x00, 0x00, 0x7e, 0xd8, 0x18, 0x18, 0x10, 0x00,
|
||||||
|
0x38, 0x10, 0x7c, 0xd6, 0xd6, 0x7c, 0x10, 0x38, 0x7c, 0xc6, 0xc6, 0xfe, 0xc6, 0xc6, 0x7c, 0x00,
|
||||||
|
0x7c, 0xc6, 0xc6, 0xc6, 0x6c, 0x28, 0xee, 0x00, 0x3c, 0x22, 0x18, 0x7c, 0xcc, 0xcc, 0x78, 0x00,
|
||||||
|
0x00, 0x00, 0x66, 0x99, 0x99, 0x66, 0x00, 0x00, 0x00, 0x06, 0x7c, 0x9e, 0xf2, 0x7c, 0xc0, 0x00,
|
||||||
|
0x00, 0x00, 0x7c, 0xc0, 0xf8, 0xc0, 0x7c, 0x00, 0x00, 0x7c, 0xc6, 0xc6, 0xc6, 0xc6, 0xc6, 0x00,
|
||||||
|
0x00, 0xfe, 0x00, 0xfe, 0x00, 0xfe, 0x00, 0x00, 0x18, 0x18, 0x7e, 0x18, 0x18, 0x00, 0x7e, 0x00,
|
||||||
|
0x30, 0x18, 0x0c, 0x18, 0x30, 0x00, 0x7c, 0x00, 0x18, 0x30, 0x60, 0x30, 0x18, 0x00, 0x7c, 0x00,
|
||||||
|
0x0e, 0x1b, 0x1b, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xd8, 0xd8, 0x70,
|
||||||
|
0x00, 0x18, 0x00, 0x7e, 0x00, 0x18, 0x00, 0x00, 0x00, 0x76, 0xdc, 0x00, 0x76, 0xdc, 0x00, 0x00,
|
||||||
|
0x38, 0x6c, 0x38, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x18, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x00, 0x00, 0x18, 0x00, 0x00, 0x00, 0x0f, 0x0c, 0x0c, 0x0c, 0xec, 0x6c, 0x3c, 0x00,
|
||||||
|
0xd8, 0x6c, 0x6c, 0x6c, 0x00, 0x00, 0x00, 0x00, 0xf0, 0x30, 0xc0, 0xf0, 0x00, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0x00, 0x3c, 0x3c, 0x3c, 0x3c, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||||
|
|
||||||
|
};
|
||||||
|
const int font_size = sizeof(font);
|
||||||
|
//---------------------------------------------------------------------------------
|
||||||
|
#endif //_font_h_
|
||||||
|
//---------------------------------------------------------------------------------
|
329
source/fs.c
Normal file
329
source/fs.c
Normal file
@ -0,0 +1,329 @@
|
|||||||
|
#include "fs.h"
|
||||||
|
#include "draw.h"
|
||||||
|
|
||||||
|
#include "fatfs/ff.h"
|
||||||
|
|
||||||
|
static FATFS fs;
|
||||||
|
static FIL file;
|
||||||
|
static DIR dir;
|
||||||
|
|
||||||
|
bool InitFS()
|
||||||
|
{
|
||||||
|
#ifndef EXEC_GATEWAY
|
||||||
|
// TODO: Magic?
|
||||||
|
*(u32*)0x10000020 = 0;
|
||||||
|
*(u32*)0x10000020 = 0x340;
|
||||||
|
#endif
|
||||||
|
bool ret = (f_mount(&fs, "0:", 0) == FR_OK);
|
||||||
|
#ifdef WORK_DIR
|
||||||
|
f_chdir(WORK_DIR);
|
||||||
|
#endif
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DeinitFS()
|
||||||
|
{
|
||||||
|
LogWrite(NULL);
|
||||||
|
f_mount(NULL, "0:", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileOpen(const char* path)
|
||||||
|
{
|
||||||
|
unsigned flags = FA_READ | FA_WRITE | FA_OPEN_EXISTING;
|
||||||
|
if (*path == '/')
|
||||||
|
path++;
|
||||||
|
bool ret = (f_open(&file, path, flags) == FR_OK);
|
||||||
|
#ifdef WORK_DIR
|
||||||
|
f_chdir("/"); // temporarily change the current directory
|
||||||
|
if (!ret) ret = (f_open(&file, path, flags) == FR_OK);
|
||||||
|
f_chdir(WORK_DIR);
|
||||||
|
#endif
|
||||||
|
f_lseek(&file, 0);
|
||||||
|
f_sync(&file);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugFileOpen(const char* path)
|
||||||
|
{
|
||||||
|
Debug("Opening %s ...", path);
|
||||||
|
if (!FileOpen(path)) {
|
||||||
|
Debug("Could not open %s!", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool FileCreate(const char* path, bool truncate)
|
||||||
|
{
|
||||||
|
unsigned flags = FA_READ | FA_WRITE;
|
||||||
|
flags |= truncate ? FA_CREATE_ALWAYS : FA_OPEN_ALWAYS;
|
||||||
|
if (*path == '/')
|
||||||
|
path++;
|
||||||
|
bool ret = (f_open(&file, path, flags) == FR_OK);
|
||||||
|
f_lseek(&file, 0);
|
||||||
|
f_sync(&file);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugFileCreate(const char* path, bool truncate) {
|
||||||
|
Debug("Creating %s ...", path);
|
||||||
|
if (!FileCreate(path, truncate)) {
|
||||||
|
Debug("Could not create %s!", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FileCopyTo(const char* dest, void* buf, size_t bufsize)
|
||||||
|
{
|
||||||
|
unsigned flags = FA_READ | FA_WRITE | FA_CREATE_ALWAYS;
|
||||||
|
size_t fsize = f_size(&file);
|
||||||
|
size_t result = fsize;
|
||||||
|
FIL dfile;
|
||||||
|
// make sure the containing folder exists
|
||||||
|
char tmp[256] = { 0 };
|
||||||
|
strncpy(tmp, dest, sizeof(tmp) - 1);
|
||||||
|
for (char* p = tmp + 1; *p; p++) {
|
||||||
|
if (*p == '/') {
|
||||||
|
char s = *p;
|
||||||
|
*p = 0;
|
||||||
|
f_mkdir(tmp);
|
||||||
|
*p = s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// do the actual copying
|
||||||
|
if (f_open(&dfile, dest, flags) != FR_OK)
|
||||||
|
return 0;
|
||||||
|
f_lseek(&dfile, 0);
|
||||||
|
f_sync(&dfile);
|
||||||
|
f_lseek(&file, 0);
|
||||||
|
f_sync(&file);
|
||||||
|
for (size_t pos = 0; pos < fsize; pos += bufsize) {
|
||||||
|
UINT bytes_read = 0;
|
||||||
|
UINT bytes_written = 0;
|
||||||
|
ShowProgress(pos, fsize);
|
||||||
|
f_read(&file, buf, bufsize, &bytes_read);
|
||||||
|
f_write(&dfile, buf, bytes_read, &bytes_written);
|
||||||
|
if (bytes_read != bytes_written) {
|
||||||
|
result = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ShowProgress(0, 0);
|
||||||
|
f_close(&dfile);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FileRead(void* buf, size_t size, size_t foffset)
|
||||||
|
{
|
||||||
|
UINT bytes_read = 0;
|
||||||
|
f_lseek(&file, foffset);
|
||||||
|
f_read(&file, buf, size, &bytes_read);
|
||||||
|
return bytes_read;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugFileRead(void* buf, size_t size, size_t foffset) {
|
||||||
|
size_t bytesRead = FileRead(buf, size, foffset);
|
||||||
|
if(bytesRead != size) {
|
||||||
|
Debug("ERROR, file is too small!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FileWrite(void* buf, size_t size, size_t foffset)
|
||||||
|
{
|
||||||
|
UINT bytes_written = 0;
|
||||||
|
f_lseek(&file, foffset);
|
||||||
|
f_write(&file, buf, size, &bytes_written);
|
||||||
|
f_sync(&file);
|
||||||
|
return bytes_written;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugFileWrite(void* buf, size_t size, size_t foffset)
|
||||||
|
{
|
||||||
|
size_t bytesWritten = FileWrite(buf, size, foffset);
|
||||||
|
if(bytesWritten != size) {
|
||||||
|
Debug("ERROR, SD card may be full!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t FileGetSize()
|
||||||
|
{
|
||||||
|
return f_size(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FileClose()
|
||||||
|
{
|
||||||
|
f_close(&file);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirMake(const char* path)
|
||||||
|
{
|
||||||
|
FRESULT res = f_mkdir(path);
|
||||||
|
bool ret = (res == FR_OK) || (res == FR_EXIST);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugDirMake(const char* path)
|
||||||
|
{
|
||||||
|
Debug("Creating dir %s ...", path);
|
||||||
|
if (!DirMake(path)) {
|
||||||
|
Debug("Could not create %s!", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirOpen(const char* path)
|
||||||
|
{
|
||||||
|
return (f_opendir(&dir, path) == FR_OK);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DebugDirOpen(const char* path)
|
||||||
|
{
|
||||||
|
Debug("Opening %s ...", path);
|
||||||
|
if (!DirOpen(path)) {
|
||||||
|
Debug("Could not open %s!", path);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool DirRead(char* fname, int fsize)
|
||||||
|
{
|
||||||
|
FILINFO fno;
|
||||||
|
fno.lfname = fname;
|
||||||
|
fno.lfsize = fsize;
|
||||||
|
bool ret = false;
|
||||||
|
while (f_readdir(&dir, &fno) == FR_OK) {
|
||||||
|
if (fno.fname[0] == 0) break;
|
||||||
|
if ((fno.fname[0] != '.') && !(fno.fattrib & AM_DIR)) {
|
||||||
|
if (fname[0] == 0)
|
||||||
|
strcpy(fname, fno.fname);
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void DirClose()
|
||||||
|
{
|
||||||
|
f_closedir(&dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetFileListWorker(char** list, int* lsize, char* fpath, int fsize, bool recursive, bool inc_files, bool inc_dirs)
|
||||||
|
{
|
||||||
|
DIR pdir;
|
||||||
|
FILINFO fno;
|
||||||
|
char* fname = fpath + strnlen(fpath, fsize - 1);
|
||||||
|
bool ret = false;
|
||||||
|
|
||||||
|
if (f_opendir(&pdir, fpath) != FR_OK)
|
||||||
|
return false;
|
||||||
|
(fname++)[0] = '/';
|
||||||
|
fno.lfname = fname;
|
||||||
|
fno.lfsize = fsize - (fname - fpath);
|
||||||
|
|
||||||
|
while (f_readdir(&pdir, &fno) == FR_OK) {
|
||||||
|
if ((strncmp(fno.fname, ".", 2) == 0) || (strncmp(fno.fname, "..", 3) == 0))
|
||||||
|
continue; // filter out virtual entries
|
||||||
|
if (fname[0] == 0)
|
||||||
|
strncpy(fname, fno.fname, (fsize - 1) - (fname - fpath));
|
||||||
|
if (fno.fname[0] == 0) {
|
||||||
|
ret = true;
|
||||||
|
break;
|
||||||
|
} else if ((inc_files && !(fno.fattrib & AM_DIR)) || (inc_dirs && (fno.fattrib & AM_DIR))) {
|
||||||
|
snprintf(*list, *lsize, "%s\n", fpath);
|
||||||
|
for(;(*list)[0] != '\0' && (*lsize) > 1; (*list)++, (*lsize)--);
|
||||||
|
if ((*lsize) <= 1) break;
|
||||||
|
}
|
||||||
|
if (recursive && (fno.fattrib & AM_DIR)) {
|
||||||
|
if (!GetFileListWorker(list, lsize, fpath, fsize, recursive, inc_files, inc_dirs))
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
f_closedir(&pdir);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool GetFileList(const char* path, char* list, int lsize, bool recursive, bool inc_files, bool inc_dirs)
|
||||||
|
{
|
||||||
|
char fpath[256]; // 256 is the maximum length of a full path
|
||||||
|
strncpy(fpath, path, 256);
|
||||||
|
return GetFileListWorker(&list, &lsize, fpath, 256, recursive, inc_files, inc_dirs);
|
||||||
|
}
|
||||||
|
|
||||||
|
size_t LogWrite(const char* text)
|
||||||
|
{
|
||||||
|
#ifdef LOG_FILE
|
||||||
|
static FIL lfile;
|
||||||
|
static bool lready = false;
|
||||||
|
static size_t lstart = 0;
|
||||||
|
|
||||||
|
if ((text == NULL) && lready) {
|
||||||
|
f_sync(&lfile);
|
||||||
|
f_close(&lfile);
|
||||||
|
lready = false;
|
||||||
|
return lstart; // return the current log start
|
||||||
|
} else if (text == NULL) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!lready) {
|
||||||
|
unsigned flags = FA_READ | FA_WRITE | FA_OPEN_ALWAYS;
|
||||||
|
lready = (f_open(&lfile, LOG_FILE, flags) == FR_OK);
|
||||||
|
if (!lready) return 0;
|
||||||
|
lstart = f_size(&lfile);
|
||||||
|
f_lseek(&lfile, lstart);
|
||||||
|
f_sync(&lfile);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char newline = '\n';
|
||||||
|
UINT bytes_written;
|
||||||
|
UINT tlen = strnlen(text, 128);
|
||||||
|
f_write(&lfile, text, tlen, &bytes_written);
|
||||||
|
if (bytes_written != tlen) return 0;
|
||||||
|
f_write(&lfile, &newline, 1, &bytes_written);
|
||||||
|
if (bytes_written != 1) return 0;
|
||||||
|
|
||||||
|
return f_size(&lfile); // return the current position
|
||||||
|
#else
|
||||||
|
return 0;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static uint64_t ClustersToBytes(FATFS* fs, DWORD clusters)
|
||||||
|
{
|
||||||
|
uint64_t sectors = clusters * fs->csize;
|
||||||
|
#if _MAX_SS != _MIN_SS
|
||||||
|
return sectors * fs->ssize;
|
||||||
|
#else
|
||||||
|
return sectors * _MAX_SS;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t RemainingStorageSpace()
|
||||||
|
{
|
||||||
|
DWORD free_clusters;
|
||||||
|
FATFS *fs2;
|
||||||
|
FRESULT res = f_getfree("0:", &free_clusters, &fs2);
|
||||||
|
if (res)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return ClustersToBytes(&fs, free_clusters);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t TotalStorageSpace()
|
||||||
|
{
|
||||||
|
return ClustersToBytes(&fs, fs.n_fatent - 2);
|
||||||
|
}
|
57
source/fs.h
Normal file
57
source/fs.h
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
bool InitFS();
|
||||||
|
void DeinitFS();
|
||||||
|
|
||||||
|
/** Opens existing files */
|
||||||
|
bool FileOpen(const char* path);
|
||||||
|
bool DebugFileOpen(const char* path);
|
||||||
|
|
||||||
|
/** Opens new files (and creates them if they don't already exist) */
|
||||||
|
bool FileCreate(const char* path, bool truncate);
|
||||||
|
bool DebugFileCreate(const char* path, bool truncate);
|
||||||
|
|
||||||
|
/** Copies currently opened file to destination (must provide buffer) */
|
||||||
|
size_t FileCopyTo(const char* dest, void* buf, size_t bufsize);
|
||||||
|
|
||||||
|
/** Reads contents of the opened file */
|
||||||
|
size_t FileRead(void* buf, size_t size, size_t foffset);
|
||||||
|
bool DebugFileRead(void* buf, size_t size, size_t foffset);
|
||||||
|
|
||||||
|
/** Writes to the opened file */
|
||||||
|
size_t FileWrite(void* buf, size_t size, size_t foffset);
|
||||||
|
bool DebugFileWrite(void* buf, size_t size, size_t foffset);
|
||||||
|
|
||||||
|
/** Gets the size of the opened file */
|
||||||
|
size_t FileGetSize();
|
||||||
|
|
||||||
|
/** Creates a directory */
|
||||||
|
bool DirMake(const char* path);
|
||||||
|
bool DebugDirMake(const char* path);
|
||||||
|
|
||||||
|
/** Opens an existing directory */
|
||||||
|
bool DirOpen(const char* path);
|
||||||
|
bool DebugDirOpen(const char* path);
|
||||||
|
|
||||||
|
/** Reads next file name to fname from opened directory,
|
||||||
|
returns false if all files in directory are processed.
|
||||||
|
fname needs to be allocated to fsize bytes minimum. */
|
||||||
|
bool DirRead(char* fname, int fsize);
|
||||||
|
|
||||||
|
/** Get list of files under a given path **/
|
||||||
|
bool GetFileList(const char* path, char* list, int lsize, bool recursive, bool inc_files, bool inc_dirs);
|
||||||
|
|
||||||
|
/** Writes text to a constantly open log file **/
|
||||||
|
size_t LogWrite(const char* text);
|
||||||
|
|
||||||
|
/** Gets remaining space on SD card in bytes */
|
||||||
|
uint64_t RemainingStorageSpace();
|
||||||
|
|
||||||
|
/** Gets total space on SD card in bytes */
|
||||||
|
uint64_t TotalStorageSpace();
|
||||||
|
|
||||||
|
void FileClose();
|
||||||
|
|
||||||
|
void DirClose();
|
10
source/hid.c
Normal file
10
source/hid.c
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#include "hid.h"
|
||||||
|
|
||||||
|
u32 InputWait() {
|
||||||
|
u32 pad_state_old = HID_STATE;
|
||||||
|
while (true) {
|
||||||
|
u32 pad_state = HID_STATE;
|
||||||
|
if (pad_state ^ pad_state_old)
|
||||||
|
return ~pad_state;
|
||||||
|
}
|
||||||
|
}
|
21
source/hid.h
Normal file
21
source/hid.h
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define HID_STATE (*(volatile u32*)0x10146000)
|
||||||
|
|
||||||
|
#define BUTTON_A (1 << 0)
|
||||||
|
#define BUTTON_B (1 << 1)
|
||||||
|
#define BUTTON_SELECT (1 << 2)
|
||||||
|
#define BUTTON_START (1 << 3)
|
||||||
|
#define BUTTON_RIGHT (1 << 4)
|
||||||
|
#define BUTTON_LEFT (1 << 5)
|
||||||
|
#define BUTTON_UP (1 << 6)
|
||||||
|
#define BUTTON_DOWN (1 << 7)
|
||||||
|
#define BUTTON_R1 (1 << 8)
|
||||||
|
#define BUTTON_L1 (1 << 9)
|
||||||
|
#define BUTTON_X (1 << 10)
|
||||||
|
#define BUTTON_Y (1 << 11)
|
||||||
|
#define BUTTON_ANY 0x00000FFF
|
||||||
|
|
||||||
|
u32 InputWait();
|
150
source/i2c.c
Normal file
150
source/i2c.c
Normal file
@ -0,0 +1,150 @@
|
|||||||
|
#include "i2c.h"
|
||||||
|
#include "draw.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},
|
||||||
|
};
|
||||||
|
|
||||||
|
const inline u8 i2cGetDeviceBusId(u8 device_id) {
|
||||||
|
return dev_data[device_id].bus_id;
|
||||||
|
}
|
||||||
|
|
||||||
|
const inline u8 i2cGetDeviceRegAddr(u8 device_id) {
|
||||||
|
return dev_data[device_id].reg_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static vu8* const reg_data_addrs[] = {
|
||||||
|
(vu8*)(I2C1_REG_OFF + I2C_REG_DATA),
|
||||||
|
(vu8*)(I2C2_REG_OFF + I2C_REG_DATA),
|
||||||
|
(vu8*)(I2C3_REG_OFF + I2C_REG_DATA),
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vu8* const i2cGetDataReg(u8 bus_id) {
|
||||||
|
return reg_data_addrs[bus_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
static vu8* const reg_cnt_addrs[] = {
|
||||||
|
(vu8*)(I2C1_REG_OFF + I2C_REG_CNT),
|
||||||
|
(vu8*)(I2C2_REG_OFF + I2C_REG_CNT),
|
||||||
|
(vu8*)(I2C3_REG_OFF + I2C_REG_CNT),
|
||||||
|
};
|
||||||
|
|
||||||
|
inline vu8* const i2cGetCntReg(u8 bus_id) {
|
||||||
|
return reg_cnt_addrs[bus_id];
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline void i2cWaitBusy(u8 bus_id) {
|
||||||
|
while (*i2cGetCntReg(bus_id) & 0x80);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool i2cGetResult(u8 bus_id) {
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
return (*i2cGetCntReg(bus_id) >> 4) & 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
void i2cStop(u8 bus_id, u8 arg0) {
|
||||||
|
*i2cGetCntReg(bus_id) = (arg0 << 5) | 0xC0;
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*i2cGetCntReg(bus_id) = 0xC5;
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
bool i2cSelectDevice(u8 bus_id, u8 dev_reg) {
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*i2cGetDataReg(bus_id) = dev_reg;
|
||||||
|
*i2cGetCntReg(bus_id) = 0xC2;
|
||||||
|
return i2cGetResult(bus_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i2cSelectRegister(u8 bus_id, u8 reg) {
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*i2cGetDataReg(bus_id) = reg;
|
||||||
|
*i2cGetCntReg(bus_id) = 0xC0;
|
||||||
|
return i2cGetResult(bus_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
u8 i2cReadRegister(u8 dev_id, u8 reg) {
|
||||||
|
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
||||||
|
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 8; i++) {
|
||||||
|
if (i2cSelectDevice(bus_id, dev_addr) && i2cSelectRegister(bus_id, reg)) {
|
||||||
|
if (i2cSelectDevice(bus_id, dev_addr | 1)) {
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
i2cStop(bus_id, 1);
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
return *i2cGetDataReg(bus_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*i2cGetCntReg(bus_id) = 0xC5;
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
}
|
||||||
|
return 0xff;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size) {
|
||||||
|
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
||||||
|
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
||||||
|
|
||||||
|
size_t j = 0;
|
||||||
|
while (!i2cSelectDevice(bus_id, dev_addr)
|
||||||
|
|| !i2cSelectRegister(bus_id, reg)
|
||||||
|
|| !i2cSelectDevice(bus_id, dev_addr | 1))
|
||||||
|
{
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*i2cGetCntReg(bus_id) = 0xC5;
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
if (++j >= 8)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (buf_size != 1) {
|
||||||
|
for (int i = 0; i < buf_size - 1; i++) {
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*i2cGetCntReg(bus_id) = 0xF0;
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
buffer[i] = *i2cGetDataReg(bus_id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*i2cGetCntReg(bus_id) = 0xE1;
|
||||||
|
i2cWaitBusy(bus_id);
|
||||||
|
*buffer = *i2cGetDataReg(bus_id);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data) {
|
||||||
|
u8 bus_id = i2cGetDeviceBusId(dev_id);
|
||||||
|
u8 dev_addr = i2cGetDeviceRegAddr(dev_id);
|
||||||
|
|
||||||
|
for (int 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;
|
||||||
|
}
|
35
source/i2c.h
Normal file
35
source/i2c.h
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "common.h"
|
||||||
|
|
||||||
|
#define I2C1_REG_OFF 0x10161000
|
||||||
|
#define I2C2_REG_OFF 0x10144000
|
||||||
|
#define I2C3_REG_OFF 0x10148000
|
||||||
|
|
||||||
|
#define I2C_REG_DATA 0
|
||||||
|
#define I2C_REG_CNT 1
|
||||||
|
#define I2C_REG_CNTEX 2
|
||||||
|
#define I2C_REG_SCL 4
|
||||||
|
|
||||||
|
#define I2C_DEV_MCU 3
|
||||||
|
#define I2C_DEV_GYRO 10
|
||||||
|
#define I2C_DEV_IR 13
|
||||||
|
|
||||||
|
const u8 i2cGetDeviceBusId(u8 device_id);
|
||||||
|
const u8 i2cGetDeviceRegAddr(u8 device_id);
|
||||||
|
|
||||||
|
vu8* const i2cGetDataReg(u8 bus_id);
|
||||||
|
vu8* const i2cGetCntReg(u8 bus_id);
|
||||||
|
|
||||||
|
void i2cWaitBusy(u8 bus_id);
|
||||||
|
bool i2cGetResult(u8 bus_id);
|
||||||
|
u8 i2cGetData(u8 bus_id);
|
||||||
|
void i2cStop(u8 bus_id, u8 arg0);
|
||||||
|
|
||||||
|
bool i2cSelectDevice(u8 bus_id, u8 dev_reg);
|
||||||
|
bool i2cSelectRegister(u8 bus_id, u8 reg);
|
||||||
|
|
||||||
|
u8 i2cReadRegister(u8 dev_id, u8 reg);
|
||||||
|
bool i2cWriteRegister(u8 dev_id, u8 reg, u8 data);
|
||||||
|
|
||||||
|
bool i2cReadRegisterBuffer(unsigned int dev_id, int reg, u8* buffer, size_t buf_size);
|
215
source/main.c
Normal file
215
source/main.c
Normal file
@ -0,0 +1,215 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "draw.h"
|
||||||
|
#include "fs.h"
|
||||||
|
#include "menu.h"
|
||||||
|
#include "i2c.h"
|
||||||
|
#include "decryptor/game.h"
|
||||||
|
#include "decryptor/nand.h"
|
||||||
|
#include "decryptor/nandfat.h"
|
||||||
|
#include "decryptor/titlekey.h"
|
||||||
|
|
||||||
|
#define SUBMENU_START 5
|
||||||
|
|
||||||
|
|
||||||
|
MenuInfo menu[] =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
"XORpad Generator Options", 7,
|
||||||
|
{
|
||||||
|
{ "NCCH Padgen", &NcchPadgen, 0 },
|
||||||
|
{ "SD Padgen (SDinfo.bin)", &SdPadgen, 0 },
|
||||||
|
{ "SD Padgen (SysNAND dir)", &SdPadgenDirect, 0 },
|
||||||
|
{ "SD Padgen (EmuNAND dir)", &SdPadgenDirect, N_EMUNAND },
|
||||||
|
{ "CTRNAND Padgen", &CtrNandPadgen, 0 },
|
||||||
|
{ "TWLNAND Padgen", &TwlNandPadgen, 0 },
|
||||||
|
{ "FIRM0FIRM1 Padgen", &Firm0Firm1Padgen, 0 }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Titlekey Decrypt Options", 3,
|
||||||
|
{
|
||||||
|
{ "Titlekey Decrypt (file)", &DecryptTitlekeysFile, 0 },
|
||||||
|
{ "Titlekey Decrypt (SysNAND)", &DecryptTitlekeysNand, 0 },
|
||||||
|
{ "Titlekey Decrypt (EmuNAND)", &DecryptTitlekeysNand, N_EMUNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"SysNAND Options", 8,
|
||||||
|
{
|
||||||
|
{ "NAND Backup", &DumpNand, 0 },
|
||||||
|
{ "NAND Restore", &RestoreNand, N_NANDWRITE },
|
||||||
|
{ "Partition Dump...", NULL, SUBMENU_START + 0 },
|
||||||
|
{ "Partition Inject...", NULL, SUBMENU_START + 2 },
|
||||||
|
{ "File Dump...", NULL, SUBMENU_START + 4 },
|
||||||
|
{ "File Inject...", NULL, SUBMENU_START + 6 },
|
||||||
|
{ "Health&Safety Dump", &DumpHealthAndSafety, 0 },
|
||||||
|
{ "Health&Safety Inject", &InjectHealthAndSafety, N_NANDWRITE }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"EmuNAND Options", 9,
|
||||||
|
{
|
||||||
|
{ "EmuNAND Backup", &DumpNand, N_EMUNAND },
|
||||||
|
{ "EmuNAND Restore", &RestoreNand, N_NANDWRITE | N_EMUNAND | N_FORCENAND },
|
||||||
|
{ "Partition Dump...", NULL, SUBMENU_START + 1 },
|
||||||
|
{ "Partition Inject...", NULL, SUBMENU_START + 3 },
|
||||||
|
{ "File Dump...", NULL, SUBMENU_START + 5 },
|
||||||
|
{ "File Inject...", NULL, SUBMENU_START + 7 },
|
||||||
|
{ "Health&Safety Dump", &DumpHealthAndSafety, N_EMUNAND },
|
||||||
|
{ "Health&Safety Inject", &InjectHealthAndSafety, N_NANDWRITE | N_EMUNAND },
|
||||||
|
{ "Update SeedDB", &UpdateSeedDb, N_EMUNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Game Decryptor Options", 10,
|
||||||
|
{
|
||||||
|
{ "NCCH/NCSD Decryptor", &CryptGameFiles, GC_NCCH_PROCESS },
|
||||||
|
{ "NCCH/NCSD Encryptor", &CryptGameFiles, GC_NCCH_PROCESS | GC_NCCH_ENCRYPT },
|
||||||
|
{ "CIA Decryptor (shallow)", &CryptGameFiles, GC_CIA_PROCESS },
|
||||||
|
{ "CIA Decryptor (deep)", &CryptGameFiles, GC_CIA_PROCESS | GC_CIA_DEEP },
|
||||||
|
{ "CIA Decryptor (CXI only)", &CryptGameFiles, GC_CIA_PROCESS | GC_CIA_DEEP | GC_CXI_ONLY },
|
||||||
|
{ "CIA Encryptor (NCCH)", &CryptGameFiles, GC_CIA_PROCESS | GC_NCCH_ENCRYPT },
|
||||||
|
{ "CIA Encryptor (CXI only)", &CryptGameFiles, GC_CIA_PROCESS | GC_NCCH_ENCRYPT | GC_CXI_ONLY },
|
||||||
|
{ "SD Decryptor/Encryptor", &CryptSdFiles, 0 },
|
||||||
|
{ "SD Decryptor (SysNAND dir)", &DecryptSdFilesDirect, 0 },
|
||||||
|
{ "SD Decryptor (EmuNAND dir)", &DecryptSdFilesDirect, N_EMUNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
// everything below is not contained in the main menu
|
||||||
|
{
|
||||||
|
"Partition Dump... (SysNAND)", 6, // ID 0
|
||||||
|
{
|
||||||
|
{ "Dump TWLN Partition", &DecryptNandPartition, P_TWLN },
|
||||||
|
{ "Dump TWLP Partition", &DecryptNandPartition, P_TWLP },
|
||||||
|
{ "Dump AGBSAVE Partition", &DecryptNandPartition, P_AGBSAVE },
|
||||||
|
{ "Dump FIRM0 Partition", &DecryptNandPartition, P_FIRM0 },
|
||||||
|
{ "Dump FIRM1 Partition", &DecryptNandPartition, P_FIRM1 },
|
||||||
|
{ "Dump CTRNAND Partition", &DecryptNandPartition, P_CTRNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Partition Dump...(EmuNAND)", 6, // ID 1
|
||||||
|
{
|
||||||
|
{ "Dump TWLN Partition", &DecryptNandPartition, N_EMUNAND | P_TWLN },
|
||||||
|
{ "Dump TWLP Partition", &DecryptNandPartition, N_EMUNAND | P_TWLP },
|
||||||
|
{ "Dump AGBSAVE Partition", &DecryptNandPartition, N_EMUNAND | P_AGBSAVE },
|
||||||
|
{ "Dump FIRM0 Partition", &DecryptNandPartition, N_EMUNAND | P_FIRM0 },
|
||||||
|
{ "Dump FIRM1 Partition", &DecryptNandPartition, N_EMUNAND | P_FIRM1 },
|
||||||
|
{ "Dump CTRNAND Partition", &DecryptNandPartition, N_EMUNAND | P_CTRNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Partition Inject... (SysNAND)", 6, // ID 2
|
||||||
|
{
|
||||||
|
{ "Inject TWLN Partition", &InjectNandPartition, N_NANDWRITE | P_TWLN },
|
||||||
|
{ "Inject TWLP Partition", &InjectNandPartition, N_NANDWRITE | P_TWLP },
|
||||||
|
{ "Inject AGBSAVE Partition", &InjectNandPartition, N_NANDWRITE | P_AGBSAVE },
|
||||||
|
{ "Inject FIRM0 Partition", &InjectNandPartition, N_NANDWRITE | P_FIRM0 },
|
||||||
|
{ "Inject FIRM1 Partition", &InjectNandPartition, N_NANDWRITE | P_FIRM1 },
|
||||||
|
{ "Inject CTRNAND Partition", &InjectNandPartition, N_NANDWRITE | P_CTRNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Partition Inject... (EmuNAND)", 6, // ID 3
|
||||||
|
{
|
||||||
|
{ "Inject TWLN Partition", &InjectNandPartition, N_NANDWRITE | N_EMUNAND | P_TWLN },
|
||||||
|
{ "Inject TWLP Partition", &InjectNandPartition, N_NANDWRITE | N_EMUNAND | P_TWLP },
|
||||||
|
{ "Inject AGBSAVE Partition", &InjectNandPartition, N_NANDWRITE | N_EMUNAND | P_AGBSAVE },
|
||||||
|
{ "Inject FIRM0 Partition", &InjectNandPartition, N_NANDWRITE | N_EMUNAND | P_FIRM0 },
|
||||||
|
{ "Inject FIRM1 Partition", &InjectNandPartition, N_NANDWRITE | N_EMUNAND | P_FIRM1 },
|
||||||
|
{ "Inject CTRNAND Partition", &InjectNandPartition, N_NANDWRITE | N_EMUNAND | P_CTRNAND }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File Dump... (SysNAND)", 10, // ID 4
|
||||||
|
{
|
||||||
|
{ "Dump ticket.db", &DumpFile, F_TICKET },
|
||||||
|
{ "Dump title.db", &DumpFile, F_TITLE },
|
||||||
|
{ "Dump import.db", &DumpFile, F_IMPORT },
|
||||||
|
{ "Dump certs.db", &DumpFile, F_CERTS },
|
||||||
|
{ "Dump SecureInfo_A", &DumpFile, F_SECUREINFO },
|
||||||
|
{ "Dump LocalFriendCodeSeed_B", &DumpFile, F_LOCALFRIEND },
|
||||||
|
{ "Dump rand_seed", &DumpFile, F_RANDSEED },
|
||||||
|
{ "Dump movable.sed", &DumpFile, F_MOVABLE },
|
||||||
|
{ "Dump nagsave.bin", &DumpFile, F_NAGSAVE },
|
||||||
|
{ "Dump nnidsave.bin", &DumpFile, F_NNIDSAVE }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File Dump... (EmuNAND)", 11, // ID 5
|
||||||
|
{
|
||||||
|
{ "Dump ticket.db", &DumpFile, N_EMUNAND | F_TICKET },
|
||||||
|
{ "Dump title.db", &DumpFile, N_EMUNAND | F_TITLE },
|
||||||
|
{ "Dump import.db", &DumpFile, N_EMUNAND | F_IMPORT },
|
||||||
|
{ "Dump certs.db", &DumpFile, N_EMUNAND | F_CERTS },
|
||||||
|
{ "Dump SecureInfo_A", &DumpFile, N_EMUNAND | F_SECUREINFO },
|
||||||
|
{ "Dump LocalFriendCodeSeed_B", &DumpFile, N_EMUNAND | F_LOCALFRIEND },
|
||||||
|
{ "Dump rand_seed", &DumpFile, N_EMUNAND | F_RANDSEED },
|
||||||
|
{ "Dump movable.sed", &DumpFile, N_EMUNAND | F_MOVABLE },
|
||||||
|
{ "Dump seedsave.bin", &DumpFile, N_EMUNAND | F_SEEDSAVE },
|
||||||
|
{ "Dump nagsave.bin", &DumpFile, N_EMUNAND | F_NAGSAVE },
|
||||||
|
{ "Dump nnidsave.bin", &DumpFile, N_EMUNAND | F_NNIDSAVE }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File Inject... (SysNAND)", 10, // ID 6
|
||||||
|
{
|
||||||
|
{ "Inject ticket.db", &InjectFile, N_NANDWRITE | F_TICKET },
|
||||||
|
{ "Inject title.db", &InjectFile, N_NANDWRITE | F_TITLE },
|
||||||
|
{ "Inject import.db", &InjectFile, N_NANDWRITE | F_IMPORT },
|
||||||
|
{ "Inject certs.db", &InjectFile, N_NANDWRITE | F_CERTS },
|
||||||
|
{ "Inject SecureInfo_A", &InjectFile, N_NANDWRITE | F_SECUREINFO },
|
||||||
|
{ "Inject LocalFriendCodeSeed_B", &InjectFile, N_NANDWRITE | F_LOCALFRIEND },
|
||||||
|
{ "Inject rand_seed", &InjectFile, N_NANDWRITE | F_RANDSEED },
|
||||||
|
{ "Inject movable.sed", &InjectFile, N_NANDWRITE | F_MOVABLE },
|
||||||
|
{ "Inject nagsave.bin", &InjectFile, N_NANDWRITE | F_NAGSAVE },
|
||||||
|
{ "Inject nnidsave.bin", &InjectFile, N_NANDWRITE | F_NNIDSAVE }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"File Inject... (EmuNAND)", 11, // ID 7
|
||||||
|
{
|
||||||
|
{ "Inject ticket.db", &InjectFile, N_NANDWRITE | N_EMUNAND | F_TICKET },
|
||||||
|
{ "Inject title.db", &InjectFile, N_NANDWRITE | N_EMUNAND | F_TITLE },
|
||||||
|
{ "Inject import.db", &InjectFile, N_NANDWRITE | N_EMUNAND | F_IMPORT },
|
||||||
|
{ "Inject certs.db", &InjectFile, N_NANDWRITE | N_EMUNAND | F_CERTS },
|
||||||
|
{ "Inject SecureInfo_A", &InjectFile, N_NANDWRITE | N_EMUNAND | F_SECUREINFO },
|
||||||
|
{ "Inject LocalFriendCodeSeed_B", &InjectFile, N_NANDWRITE | N_EMUNAND | F_LOCALFRIEND },
|
||||||
|
{ "Inject rand_seed", &InjectFile, N_NANDWRITE | N_EMUNAND | F_RANDSEED },
|
||||||
|
{ "Inject movable.sed", &InjectFile, N_NANDWRITE | N_EMUNAND | F_MOVABLE },
|
||||||
|
{ "Inject seedsave.bin", &InjectFile, N_NANDWRITE | N_EMUNAND | F_SEEDSAVE },
|
||||||
|
{ "Inject nagsave.bin", &InjectFile, N_NANDWRITE | N_EMUNAND | F_NAGSAVE },
|
||||||
|
{ "Inject nnidsave.bin", &InjectFile, N_NANDWRITE | N_EMUNAND | F_NNIDSAVE }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
NULL, 0, {}, // empty menu to signal end
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
void Reboot()
|
||||||
|
{
|
||||||
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 2);
|
||||||
|
while(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PowerOff()
|
||||||
|
{
|
||||||
|
i2cWriteRegister(I2C_DEV_MCU, 0x20, 1 << 0);
|
||||||
|
while (true);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int main()
|
||||||
|
{
|
||||||
|
ClearScreenFull(true, true);
|
||||||
|
InitFS();
|
||||||
|
|
||||||
|
u32 menu_exit = ProcessMenu(menu, SUBMENU_START);
|
||||||
|
|
||||||
|
DeinitFS();
|
||||||
|
(menu_exit == MENU_EXIT_REBOOT) ? Reboot() : PowerOff();
|
||||||
|
return 0;
|
||||||
|
}
|
15
source/platform.c
Normal file
15
source/platform.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "common.h"
|
||||||
|
#include "platform.h"
|
||||||
|
|
||||||
|
#define CONFIG_PLATFORM_REG ((volatile u32*)0x10140FFC)
|
||||||
|
|
||||||
|
Platform GetUnitPlatform()
|
||||||
|
{
|
||||||
|
switch (*CONFIG_PLATFORM_REG) {
|
||||||
|
case 7:
|
||||||
|
return PLATFORM_N3DS;
|
||||||
|
case 1:
|
||||||
|
default:
|
||||||
|
return PLATFORM_3DS;
|
||||||
|
}
|
||||||
|
}
|
8
source/platform.h
Normal file
8
source/platform.h
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
PLATFORM_3DS,
|
||||||
|
PLATFORM_N3DS,
|
||||||
|
} Platform;
|
||||||
|
|
||||||
|
Platform GetUnitPlatform();
|
Loading…
x
Reference in New Issue
Block a user