Initial commit

This commit is contained in:
Gericom
2025-11-22 11:08:28 +01:00
commit 9cf3ffbfcf
358 changed files with 58350 additions and 0 deletions

1
.gitattributes vendored Normal file
View File

@@ -0,0 +1 @@
*.bin binary

59
.github/workflows/nightly.yml vendored Normal file
View File

@@ -0,0 +1,59 @@
name: Build Pico Loader
on:
push:
branches: ["develop"]
paths-ignore:
- 'README.md'
pull_request:
branches: ["develop"]
paths-ignore:
- 'README.md'
workflow_dispatch:
jobs:
pico_loader:
strategy:
matrix:
platform: [
"ACE3DS",
"AK2",
"AKRPG",
"DSPICO",
"DSTT",
"G003",
"M3DS",
"R4",
"R4iDSN",
"SUPERCARD"
]
runs-on: ubuntu-latest
container: skylyrac/blocksds:slim-v1.13.1
name: Build Pico Loader
env:
DOTNET_CLI_TELEMETRY_OPTOUT: 1
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: 1
DOTNET_SYSTEM_GLOBALIZATION_INVARIANT: 1
DOTNET_NOLOGO: true
steps:
- name: Checkout repo
uses: actions/checkout@v4
with:
submodules: true
- uses: actions/setup-dotnet@v4
with:
dotnet-version: 9.x
- name: Run build script
run: |
make PICO_PLATFORM=${{ matrix.platform }}
mv picoLoader7.bin data/picoLoader7.bin
mv picoLoader9_${{ matrix.platform }}.bin data/picoLoader9.bin
- name: Publish build to GH Actions
uses: actions/upload-artifact@v4
with:
path: |
data/aplist.bin
data/savelist.bin
data/picoLoader7.bin
data/picoLoader9.bin
name: Pico Loader for ${{ matrix.platform }}

52
.gitignore vendored Normal file
View File

@@ -0,0 +1,52 @@
# Ignore build directories #
############################
Debug/
Release/
build/
out/
# Compiled source #
###################
*.com
*.class
*.dll
*.d
*.map
*.o
*.so
# Packages #
############
# it's better to unpack these files and commit the raw source
# git has its own built in compression methods
*.7z
*.dmg
*.gz
*.iso
*.jar
*.rar
*.tar
*.zip
# Logs and databases #
######################
*.log
*.sql
*.sqlite
# OS generated files #
######################
.DS_Store
.DS_Store?
._*
.Spotlight-V100
.Trashes
ehthumbs.db
Thumbs.db
*.nds
*.elf
*.a
picoLoader*.bin
.vscode/
data/aplist.bin
data/savelist.bin

3
.gitmodules vendored Normal file
View File

@@ -0,0 +1,3 @@
[submodule "libs/libtwl"]
path = libs/libtwl
url = https://github.com/Gericom/libtwl.git

17
LICENSE.txt Normal file
View File

@@ -0,0 +1,17 @@
Copyright (c) 2025 LNH team
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.

28
Makefile Normal file
View File

@@ -0,0 +1,28 @@
.PHONY: loader9 loader7 clean
all: checklibtwl loader9 loader7 apList saveList
PICO_PLATFORM ?= DSPICO
checklibtwl:
$(MAKE) -C libs/libtwl
loader9: checklibtwl
$(MAKE) -f Makefile.arm9 PLATFORM=$(PICO_PLATFORM)
loader7: checklibtwl
$(MAKE) -f Makefile.arm7
picoLoaderConverter:
dotnet build tools/PicoLoaderConverter/PicoLoaderConverter.sln
apList: picoLoaderConverter data/aplist.csv
dotnet tools/PicoLoaderConverter/PicoLoaderConverter/bin/Debug/net9.0/PicoLoaderConverter.dll aplist -i data/aplist.csv -o data/aplist.bin
saveList: picoLoaderConverter data/savelist.csv
dotnet tools/PicoLoaderConverter/PicoLoaderConverter/bin/Debug/net9.0/PicoLoaderConverter.dll savelist -i data/savelist.csv -o data/savelist.bin
clean:
$(MAKE) -f Makefile.arm7 clean
$(MAKE) -f Makefile.arm9 clean
rm -rf build

192
Makefile.arm7 Normal file
View File

@@ -0,0 +1,192 @@
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileContributor: Antonio Niño Díaz, 2023
export BLOCKSDS ?= /opt/blocksds/core
export BLOCKSDSEXT ?= /opt/blocksds/external
export LIBTWL ?= $(shell pwd)/libs/libtwl
export WONDERFUL_TOOLCHAIN ?= /opt/wonderful
ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/
# Source code paths
# -----------------
SOURCEDIRS := arm7/source common
INCLUDEDIRS := arm7/source common
BINDIRS :=
# Defines passed to all files
# ---------------------------
DEFINES := -DLIBTWL_ARM7 -DARM7
# Libraries
# ---------
LIBS := -ltwl7
LIBDIRS := $(BLOCKSDS)/libs/libnds \
$(LIBTWL)/libtwl7 $(LIBTWL)/common $(LIBTWL)
# Build artifacts
# -----------------
NAME := picoLoader7
BUILDDIR := build/$(NAME)
BIN := $(NAME).bin
ELF := build/$(NAME).elf
DUMP := build/$(NAME).dump
MAP := build/$(NAME).map
# Tools
# -----
PREFIX := $(ARM_NONE_EABI_PATH)arm-none-eabi-
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
LD := $(PREFIX)gcc
OBJCOPY := $(PREFIX)objcopy
OBJDUMP := $(PREFIX)objdump
MKDIR := mkdir
RM := rm -rf
# Verbose flag
# ------------
ifeq ($(VERBOSE),1)
V :=
else
V := @
endif
# Source files
# ------------
ifneq ($(BINDIRS),)
SOURCES_BIN := $(shell find -L $(BINDIRS) -name "*.bin")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(BINDIRS))
endif
SOURCES_S := $(shell find -L $(SOURCEDIRS) -name "*.s")
SOURCES_C := $(shell find -L $(SOURCEDIRS) -name "*.c")
SOURCES_CPP := $(shell find -L $(SOURCEDIRS) -name "*.cpp")
# Compiler and linker flags
# -------------------------
ARCH := -mthumb -mthumb-interwork -mcpu=arm7tdmi
WARNFLAGS := -Wall
ifeq ($(SOURCES_CPP),)
LIBS += -lc
else
LIBS += -lstdc++ -lc
endif
INCLUDEFLAGS := $(foreach path,$(INCLUDEDIRS),-I$(path)) \
$(foreach path,$(LIBDIRS),-I$(path)/include)
LIBDIRSFLAGS := $(foreach path,$(LIBDIRS),-L$(path)/lib)
ASFLAGS += -x assembler-with-cpp $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -ffunction-sections -fdata-sections
CFLAGS += -std=gnu17 $(WARNFLAGS) $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -O2 -ffunction-sections -fdata-sections
CXXFLAGS += -std=gnu++23 $(WARNFLAGS) $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -O2 -ffunction-sections -fdata-sections \
-fno-exceptions -fno-rtti \
-fno-threadsafe-statics \
-Wno-volatile -Wsuggest-override \
-Werror=suggest-override -Werror=return-type
LDFLAGS := $(ARCH) $(LIBDIRSFLAGS) $(DEFINES) \
-Wl,-Map,$(MAP),--gc-sections,--no-warn-rwx-segments,--entry=loaderMain \
-Wl,--start-group $(LIBS) -Wl,--end-group -T arm7/loader7.ld -nostartfiles
# Intermediate build files
# ------------------------
OBJS_ASSETS := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN)))
HEADERS_ASSETS := $(patsubst %.bin,%_bin.h,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN)))
OBJS_SOURCES := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_S))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_C))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_CPP)))
OBJS := $(OBJS_ASSETS) $(OBJS_SOURCES)
DEPS := $(OBJS:.o=.d)
# Targets
# -------
.PHONY: all clean dump
all: $(BIN)
$(BIN): $(ELF)
@echo " OBJCOPY.7 $@"
$(V)$(OBJCOPY) -O binary $< $@
$(ELF): $(OBJS)
@echo " LD.7 $@"
$(V)$(LD) -o $@ $(OBJS) $(LDFLAGS)
$(DUMP): $(ELF)
@echo " OBJDUMP.7 $@"
$(V)$(OBJDUMP) -h -C -S $< > $@
dump: $(DUMP)
clean:
@echo " CLEAN.7"
$(V)$(RM) picoLoader7*.bin $(ELF) $(DUMP) $(MAP) $(BUILDDIR)
# Rules
# -----
$(BUILDDIR)/%.s.o : %.s
@echo " AS.7 $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(ASFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.c.o : %.c
@echo " CC.7 $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.arm.c.o : %.arm.c
@echo " CC.7 $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -marm -mlong-calls -c -o $@ $<
$(BUILDDIR)/%.cpp.o : %.cpp
@echo " CXX.7 $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.arm.cpp.o : %.arm.cpp
@echo " CXX.7 $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -marm -mlong-calls -c -o $@ $<
$(BUILDDIR)/%.bin.o $(BUILDDIR)/%_bin.h : %.bin
@echo " BIN2C.7 $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $< $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.bin.o $(BUILDDIR)/$*_bin.c
# All assets must be built before the source code
# -----------------------------------------------
$(SOURCES_S) $(SOURCES_C) $(SOURCES_CPP): $(HEADERS_ASSETS)
# Include dependency files if they exist
# --------------------------------------
-include $(DEPS)

243
Makefile.arm9 Normal file
View File

@@ -0,0 +1,243 @@
# SPDX-License-Identifier: CC0-1.0
#
# SPDX-FileContributor: Antonio Niño Díaz, 2023
export BLOCKSDS ?= /opt/blocksds/core
export BLOCKSDSEXT ?= /opt/blocksds/external
export LIBTWL ?= $(shell pwd)/libs/libtwl
export WONDERFUL_TOOLCHAIN ?= /opt/wonderful
ARM_NONE_EABI_PATH ?= $(WONDERFUL_TOOLCHAIN)/toolchain/gcc-arm-none-eabi/bin/
# Source code paths
# -----------------
SOURCEDIRS := arm9/source common
INCLUDEDIRS := arm9/source common
GFXDIRS :=
BINDIRS := arm9/data
AUDIODIRS :=
# Defines passed to all files
# ---------------------------
PLATFORM ?= DSPICO
DEFINES := -DLIBTWL_ARM9 -DARM9 -DPICO_LOADER_TARGET_$(PLATFORM)
# Libraries
# ---------
LIBS := -ltwl9
LIBDIRS := $(BLOCKSDS)/libs/libnds \
$(LIBTWL)/libtwl9 $(LIBTWL)/common $(LIBTWL)
# Build artifacts
# ---------------
NAME := picoLoader9_$(PLATFORM)
BUILDDIR := build/$(NAME)
BIN := $(NAME).bin
ELF := build/$(NAME).elf
DUMP := build/$(NAME).dump
MAP := build/$(NAME).map
SOUNDBANKDIR := $(BUILDDIR)/maxmod
# Tools
# -----
PREFIX := $(ARM_NONE_EABI_PATH)arm-none-eabi-
CC := $(PREFIX)gcc
CXX := $(PREFIX)g++
LD := $(PREFIX)gcc
OBJCOPY := $(PREFIX)objcopy
OBJDUMP := $(PREFIX)objdump
MKDIR := mkdir
RM := rm -rf
# Verbose flag
# ------------
ifeq ($(VERBOSE),1)
V :=
else
V := @
endif
# Source files
# ------------
ifneq ($(BINDIRS),)
SOURCES_BIN := $(shell find -L $(BINDIRS) -name "*.bin")
SOURCES_NFT2 := $(shell find -L $(BINDIRS) -name "*.nft2")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(BINDIRS))
endif
ifneq ($(GFXDIRS),)
SOURCES_PNG := $(shell find -L $(GFXDIRS) -name "*.png")
INCLUDEDIRS += $(addprefix $(BUILDDIR)/,$(GFXDIRS))
endif
ifneq ($(AUDIODIRS),)
SOURCES_AUDIO := $(shell find -L $(AUDIODIRS) -regex '.*\.\(it\|mod\|s3m\|wav\|xm\)')
ifneq ($(SOURCES_AUDIO),)
INCLUDEDIRS += $(SOUNDBANKDIR)
endif
endif
SOURCES_S := $(shell find -L $(SOURCEDIRS) -name "*.s")
SOURCES_C := $(shell find -L $(SOURCEDIRS) -name "*.c")
SOURCES_CPP := $(shell find -L $(SOURCEDIRS) -name "*.cpp")
# Compiler and linker flags
# -------------------------
ARCH := -mthumb -mthumb-interwork -mcpu=arm946e-s+nofp
WARNFLAGS := -Wall
ifeq ($(SOURCES_CPP),)
LIBS += -lc
else
LIBS += -lstdc++ -lc
endif
INCLUDEFLAGS := $(foreach path,$(INCLUDEDIRS),-I$(path)) \
$(foreach path,$(LIBDIRS),-I$(path)/include)
LIBDIRSFLAGS := $(foreach path,$(LIBDIRS),-L$(path)/lib)
ASFLAGS += -x assembler-with-cpp $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -ffunction-sections -fdata-sections
CFLAGS += -std=gnu17 $(WARNFLAGS) $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -O2 -ffunction-sections -fdata-sections
CXXFLAGS += -std=gnu++23 $(WARNFLAGS) $(DEFINES) $(INCLUDEFLAGS) \
$(ARCH) -O2 -ffunction-sections -fdata-sections \
-fno-exceptions -fno-rtti \
-fno-threadsafe-statics -Wno-volatile \
-Wsuggest-override -Werror=suggest-override
LDFLAGS := $(ARCH) $(LIBDIRSFLAGS) $(DEFINES) -nostartfiles \
-Wl,-Map,$(MAP),--gc-sections,--use-blx,--no-warn-rwx-segments,--entry=loaderMain \
-Wl,--start-group $(LIBS) -Wl,--end-group -T arm9/loader9.ld
# Intermediate build files
# ------------------------
OBJS_ASSETS := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_NFT2))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_PNG)))
HEADERS_ASSETS := $(patsubst %.bin,%_bin.h,$(addprefix $(BUILDDIR)/,$(SOURCES_BIN))) \
$(patsubst %.nft2,%_nft2.h,$(addprefix $(BUILDDIR)/,$(SOURCES_NFT2))) \
$(patsubst %.png,%.h,$(addprefix $(BUILDDIR)/,$(SOURCES_PNG)))
ifneq ($(SOURCES_AUDIO),)
OBJS_ASSETS += $(SOUNDBANKDIR)/soundbank.c.o
HEADERS_ASSETS += $(SOUNDBANKDIR)/soundbank.h
endif
OBJS_SOURCES := $(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_S))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_C))) \
$(addsuffix .o,$(addprefix $(BUILDDIR)/,$(SOURCES_CPP)))
OBJS := $(OBJS_ASSETS) $(OBJS_SOURCES)
DEPS := $(OBJS:.o=.d)
# Targets
# -------
.PHONY: all clean dump
all: $(BIN)
$(BIN): $(ELF)
@echo " OBJCOPY.9 $@"
$(V)$(OBJCOPY) -O binary $< $@
$(ELF): $(OBJS)
@echo " LD.9 $@"
$(V)$(LD) -o $@ $(OBJS) $(LDFLAGS)
$(DUMP): $(ELF)
@echo " OBJDUMP.9 $@"
$(V)$(OBJDUMP) -h -C -S $< > $@
dump: $(DUMP)
clean:
@echo " CLEAN.9"
$(V)$(RM) picoLoader9*.bin $(ELF) $(DUMP) $(MAP) $(BUILDDIR)
# Rules
# -----
$(BUILDDIR)/%.s.o : %.s
@echo " AS.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(ASFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.c.o : %.c
@echo " CC.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.arm.c.o : %.arm.c
@echo " CC.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -marm -mlong-calls -c -o $@ $<
$(BUILDDIR)/%.cpp.o : %.cpp
@echo " CXX.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -c -o $@ $<
$(BUILDDIR)/%.arm.cpp.o : %.arm.cpp
@echo " CXX.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(CXX) $(CXXFLAGS) -MMD -MP -marm -mlong-calls -c -o $@ $<
$(BUILDDIR)/%.bin.o $(BUILDDIR)/%_bin.h : %.bin
@echo " BIN2C.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $< $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.bin.o $(BUILDDIR)/$*_bin.c
$(BUILDDIR)/%.nft2.o $(BUILDDIR)/%_nft2.h : %.nft2
@echo " BIN2C.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $< $(@D)
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.nft2.o $(BUILDDIR)/$*_nft2.c
$(BUILDDIR)/%.png.o $(BUILDDIR)/%.h : %.png %.grit
@echo " GRIT.9 $<"
@$(MKDIR) -p $(@D)
$(V)$(BLOCKSDS)/tools/grit/grit $< -ftc -W1 -o$(BUILDDIR)/$*
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(BUILDDIR)/$*.png.o $(BUILDDIR)/$*.c
$(V)touch $(BUILDDIR)/$*.png.o $(BUILDDIR)/$*.h
$(SOUNDBANKDIR)/soundbank.h: $(SOURCES_AUDIO)
@echo " MMUTIL $^"
@$(MKDIR) -p $(@D)
@$(BLOCKSDS)/tools/mmutil/mmutil $^ -d \
-o$(SOUNDBANKDIR)/soundbank.bin -h$(SOUNDBANKDIR)/soundbank.h
$(SOUNDBANKDIR)/soundbank.c.o: $(SOUNDBANKDIR)/soundbank.h
@echo " BIN2C soundbank.bin"
$(V)$(BLOCKSDS)/tools/bin2c/bin2c $(SOUNDBANKDIR)/soundbank.bin \
$(SOUNDBANKDIR)
@echo " CC.9 soundbank_bin.c"
$(V)$(CC) $(CFLAGS) -MMD -MP -c -o $(SOUNDBANKDIR)/soundbank.c.o \
$(SOUNDBANKDIR)/soundbank_bin.c
# All assets must be built before the source code
# -----------------------------------------------
$(SOURCES_S) $(SOURCES_C) $(SOURCES_CPP): $(HEADERS_ASSETS)
# Include dependency files if they exist
# --------------------------------------
-include $(DEPS)

106
README.md Normal file
View File

@@ -0,0 +1,106 @@
# Pico Loader
Pico Loader is a homebrew and retail DS(i) rom loader supporting a variety of platforms (see below).
## Features
- Supports both homebrew and retail DS(i) roms
- Supports DSiWare and redirects NAND to the flashcard SD card (acting as "emunand", see below for how to setup)
- Supports DS roms with an encrypted secure area if a DS arm7 bios is present at `/_pico/biosnds7.rom`
- Supports a wide range of platforms, including popular flashcards and the DSpico
- Built-in patches for DS Protect
- Fast loading
Note that Pico Loader can currently not run retail roms from the DSi SD card. Homebrew is supported, however.
Return to loader is also currently not supported yet.
## Supported platforms
> [!CAUTION]
> Using the wrong platform could damage your flashcard!
Note that there can be some game compatibility differences between different platforms.
| PICO_PLATFORM | Description | DMA |
| ------------- | ---------------------------------------------------------------------------------------------- | --- |
| ACE3DS | Ace3DS+, Gateway 3DS (blue), r4isdhc.com.cn carts, r4isdhc.hk carts 2020+, various derivatives | ✅ |
| AK2 | Acekard 2, 2.1, 2i, r4ids.cn, various derivatives | ❌ |
| AKRPG | Acekard RPG SD card | ❌ |
| DSPICO | DSpico | ✅ |
| DSTT | DSTT, SuperCard DSONE SDHC, r4isdhc.com carts 2014+, r4i-sdhc.com carts, various derivatives | ❌ |
| G003 | M3i Zero (GMP-Z003) | ✅ |
| ISNITRO | Supports the IS-NITRO-EMULATOR through agb semihosting. | ❌ |
| M3DS | M3 DS Real, M3i Zero, iTouchDS, r4rts.com, r4isdhc.com RTS (black) | ❌ |
| MELONDS | Melon DS support for testing purposes only. | ❌ |
| R4 | Original R4DS (non-SDHC), M3 DS Simply | ❌ |
| R4iDSN | r4idsn.com | ❌ |
| SUPERCARD | SuperCard (Slot-2 flashcart) | ❌ |
The DMA column indicates whether DMA card reads are implemented for the platform . Without DMA card reads, some games can have cache related issues.<br>
Note that there are still SDK versions and variants for which Pico Loader does not yet support DMA card reads.
## Setup & Configuration
We recommend using WSL (Windows Subsystem for Linux), or MSYS2 to compile this repository.
The steps provided will assume you already have one of those environments set up.
1. Install [BlocksDS](https://blocksds.skylyrac.net/docs/setup/options/)
2. Install [.NET 9.0](https://learn.microsoft.com/en-us/dotnet/core/install/linux-ubuntu-install?tabs=dotnet9&pivots=os-linux-ubuntu-2404) for your system (note: this link points to the instructions for Ubuntu, but links for most OS'es are available on the same page)
## Compiling
1. Run `make`
- By default this compiles for the DSpico platform. To specify a different platform use `make PICO_PLATFORM=PLATFORM`, for example `make PICO_PLATFORM=R4`. See the table above for the supported platforms.
2. To use Pico Loader, create a `_pico` folder in the root of your flashcard SD card and copy the following files to it:
- `picoLoader7.bin`
- `picoLoader9.bin` (the version for your platform)
- `aplist.bin` (generated in the `data` folder of the repo)
- `savelist.bin` (generated in the `data` folder of the repo)
## Emunand
When running DSiWare, Pico Loader redirects NAND to the flashcard SD card. This requires the following files and folders, obtained from a DSi nand dump, in the root of your flashcard SD card:
- `photo` - The photo partition of nand will be redirected to this folder
- `shared1`
- `TWLCFG0.dat`
- `TWLCFG1.dat`
- `shared2`
- `launcher`
- `wrap.bin`
- `sys`
- `log`
- `product.log`
- `shop.log`
- `sysmenu.log`
- `cert.sys`
- `dev.kp`
- `HWID.sgn`
- `HWINFO_N.dat`
- `HWINFO_S.dat`
- `TWLFontTable.dat`
## How to use Pico Loader from homebrew
On the arm9:
1. Map VRAM blocks A, B, C and D to LCDC
2. Load `picoLoader9.bin` to `0x06800000` (VRAM A and B)
3. Load `picoLoader7.bin` to `0x06840000` (VRAM C and D)
4. Setup the header of picoLoader7 to specify what should be loaded. See `pload_header7_t` in [include/picoLoader7.h](include/picoLoader7.h).
- Caution: VRAM does not support byte writes!
5. Disable irqs and dma
6. Ensure the cache is flushed
7. Map VRAM C and D to arm7
8. Request the arm7 to boot into picoLoader7
- Arm7: Disable sound, irqs and dma and jump to the `entryPoint` specified in the picoLoader7 header. Note that after mapping the VRAM to arm7, it appears at `0x06000000` on the arm7 side.
9. Arm9 jump to `0x06800000`
Note that vram must be executable on the arm9.
## License
This project is licensed under the Zlib license. For details, see `LICENSE.txt`.
Additional licenses may apply to the project. For details, see the `license` directory.
## Contributors
- [@Gericom](https://github.com/Gericom)
- [@lifehackerhansol](https://github.com/lifehackerhansol)
- [@Dartz150](https://github.com/Dartz150)
- [@XLuma](https://github.com/XLuma)
- [@edo9300](https://github.com/edo9300)
- [@Tcm0](https://github.com/Tcm0)
- [@RocketRobz](https://github.com/RocketRobz)

209
arm7/loader7.ld Normal file
View File

@@ -0,0 +1,209 @@
/*--------------------------------------------------------------------------------
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 https://mozilla.org/MPL/2.0/.
--------------------------------------------------------------------------------*/
OUTPUT_FORMAT("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
OUTPUT_ARCH(arm)
ENTRY(_start)
MEMORY {
vram : ORIGIN = 0x06000000, LENGTH = 256K
}
__heap_end = ORIGIN(vram) + LENGTH(vram);
SECTIONS
{
.crt0 :
{
__text_start = . ;
KEEP (build/picoLoader7/arm7/source/header.cpp.o(.crt0))
KEEP (*(.crt0))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.text : /* ALIGN (4): */
{
KEEP (*(SORT_NONE(.init)))
*(.text.*)
*(.stub)
/* .gnu.warning sections are handled specially by elf32.em. */
*(.gnu.warning)
*(.gnu.linkonce.t*)
__glue_start = ABSOLUTE(.);
*(.glue_7)
*(.glue_7t)
__glue_end = ABSOLUTE(.);
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.fini :
{
KEEP (*(.fini))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram =0xff
__text_end = . ;
.rodata :
{
*(.rodata)
*all.rodata*(*)
*(.roda)
*(.rodata.*)
*(.gnu.linkonce.r*)
SORT(CONSTRUCTORS)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.ARM.extab : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >vram
__exidx_start = .;
.ARM.exidx : { *(.ARM.exidx* .gnu.linkonce.armexidx.*) } >vram
__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);
.init_array :
{
PROVIDE (__preinit_array_start = .);
PROVIDE (__bothinit_array_start = .);
KEEP (*(.preinit_array))
PROVIDE (__preinit_array_end = .);
PROVIDE (__init_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.init_array.*) SORT_BY_INIT_PRIORITY(.ctors.*)))
KEEP (*(.init_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .ctors))
PROVIDE (__init_array_end = .);
PROVIDE (__bothinit_array_end = .);
} >vram
.fini_array :
{
PROVIDE (__fini_array_start = .);
KEEP (*(SORT_BY_INIT_PRIORITY(.fini_array.*) SORT_BY_INIT_PRIORITY(.dtors.*)))
KEEP (*(.fini_array EXCLUDE_FILE (*crtbegin.o *crtbegin?.o *crtend.o *crtend?.o ) .dtors))
/* Required by pico-exitprocs.c. */
KEEP (*(.fini_array*))
PROVIDE (__fini_array_end = .);
} >vram
.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. */
} >vram = 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. */
} >vram = 0xff
.eh_frame :
{
KEEP (*(.eh_frame))
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.gcc_except_table :
{
*(.gcc_except_table)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram = 0xff
.jcr : { KEEP (*(.jcr)) } >vram = 0
__got_start = . ;
.got :
{
*(.got.plt)
*(.got)
*(.rel.got)
} >vram = 0
__got_end = . ;
.data ALIGN(4) : {
__data_start = ABSOLUTE(.);
*(.data)
*(.data.*)
*(.gnu.linkonce.d*)
CONSTRUCTORS
. = ALIGN(4);
__data_end = ABSOLUTE(.) ;
} >vram = 0xff
__data_end = . ;
.bss ALIGN(4) :
{
__bss_start = ABSOLUTE(.);
__bss_start__ = ABSOLUTE(.);
*(.dynbss)
*(.gnu.linkonce.b*)
*(.bss*)
*(COMMON)
. = ALIGN(4); /* REQUIRED. LD is flaky without it. */
} >vram
__bss_end = . ;
__bss_end__ = . ;
__bss_size = __bss_end - __bss_start;
__heap_start = . ;
_end = . ;
__end__ = . ;
PROVIDE (end = _end);
/* Stabs debugging sections. */
.stab 0 : { *(.stab) }
.stabstr 0 : { *(.stabstr) }
.stab.excl 0 : { *(.stab.excl) }
.stab.exclstr 0 : { *(.stab.exclstr) }
.stab.index 0 : { *(.stab.index) }
.stab.indexstr 0 : { *(.stab.indexstr) }
.comment 0 : { *(.comment) }
/* DWARF debug sections.
Symbols in the DWARF debugging sections are relative to the beginning
of the section so we begin them at 0. */
/* DWARF 1 */
.debug 0 : { *(.debug) }
.line 0 : { *(.line) }
/* GNU DWARF 1 extensions */
.debug_srcinfo 0 : { *(.debug_srcinfo) }
.debug_sfnames 0 : { *(.debug_sfnames) }
/* DWARF 1.1 and DWARF 2 */
.debug_aranges 0 : { *(.debug_aranges) }
.debug_pubnames 0 : { *(.debug_pubnames) }
/* DWARF 2 */
.debug_info 0 : { *(.debug_info) }
.debug_abbrev 0 : { *(.debug_abbrev) }
.debug_line 0 : { *(.debug_line) }
.debug_frame 0 : { *(.debug_frame) }
.debug_str 0 : { *(.debug_str) }
.debug_loc 0 : { *(.debug_loc) }
.debug_macinfo 0 : { *(.debug_macinfo) }
/* SGI/MIPS DWARF 2 extensions */
.debug_weaknames 0 : { *(.debug_weaknames) }
.debug_funcnames 0 : { *(.debug_funcnames) }
.debug_typenames 0 : { *(.debug_typenames) }
.debug_varnames 0 : { *(.debug_varnames) }
.stack 0x80000 : { _stack = .; *(.stack) }
/* These must appear regardless of . */
}

3
arm7/source/clearFast.h Normal file
View File

@@ -0,0 +1,3 @@
#pragma once
extern "C" void clearFast(void* dst, u32 length);

29
arm7/source/clearFast.s Normal file
View File

@@ -0,0 +1,29 @@
.text
.thumb
.global clearFast
.type clearFast, %function
clearFast:
push {r4-r7,lr}
mov r12, sp
mov sp, r0
add sp, r1
mov r1, #0
mov r2, #0
mov r3, #0
mov r4, #0
mov r5, #0
mov r6, #0
mov r7, #0
mov lr, r7
1:
push {r1-r7,lr}
push {r1-r7,lr}
cmp sp, r0
bne 1b
mov sp, r12
pop {r4-r7}
pop {r3}
bx r3
.end

23
arm7/source/common.h Normal file
View File

@@ -0,0 +1,23 @@
#pragma once
#include <nds/ndstypes.h>
#include "fat/ff.h"
#ifdef __cplusplus
#include "header.h"
#include "logger/ILogger.h"
extern ILogger* gLogger;
#define MAX_COMPILED_LOG_LEVEL LogLevel::All
#define LOG_FATAL(...) if (LogLevel::Fatal < MAX_COMPILED_LOG_LEVEL) gLogger->Log(LogLevel::Fatal, __VA_ARGS__)
#define LOG_ERROR(...) if (LogLevel::Error < MAX_COMPILED_LOG_LEVEL) gLogger->Log(LogLevel::Error, __VA_ARGS__)
#define LOG_WARNING(...) if (LogLevel::Warning < MAX_COMPILED_LOG_LEVEL) gLogger->Log(LogLevel::Warning, __VA_ARGS__)
#define LOG_INFO(...) if (LogLevel::Info < MAX_COMPILED_LOG_LEVEL) gLogger->Log(LogLevel::Info, __VA_ARGS__)
#define LOG_DEBUG(...) if (LogLevel::Debug < MAX_COMPILED_LOG_LEVEL) gLogger->Log(LogLevel::Debug, __VA_ARGS__)
#define LOG_TRACE(...) if (LogLevel::Trace < MAX_COMPILED_LOG_LEVEL) gLogger->Log(LogLevel::Trace, __VA_ARGS__)
#endif
extern FATFS gFatFs;

View File

@@ -0,0 +1,61 @@
#include <nds.h>
#include "picoAgbAdapter.h"
#include "Environment.h"
u32 Environment::_flags;
static bool detectIsNitroEmulator()
{
u32 agbMemoryAddress = *(vu32*)0x027FFF7C;
if (agbMemoryAddress < 0x08000000 || agbMemoryAddress >= 0x0A000000)
return false;
// u32 monitorRomLoadAddress = *(vu32*)0x027FFF68;
// if (monitorRomLoadAddress < 0x02000000 || monitorRomLoadAddress >= 0x02800000)
// return false;
return true;
}
static bool detectNocashPrintSuppport()
{
u32 nocashIdentifier = *(vu32*)0x04FFFA00;
return nocashIdentifier == 0x67246F6E; //no$g
}
static bool detectPicoAgbAdapter()
{
REG_EXMEMSTAT &= ~0xFF;
return PICO_AGB_IDENTIFIER == PICO_AGB_IDENTIFIER_VALUE;
}
void Environment::Initialize(bool dsiMode)
{
_flags = ENVIRONMENT_FLAGS_NONE;
if (dsiMode)
{
_flags |= ENVIRONMENT_FLAGS_DSI_MODE;
}
else
{
if (detectIsNitroEmulator())
{
_flags |= ENVIRONMENT_FLAGS_IS_NITRO_EMULATOR;
_flags |= ENVIRONMENT_FLAGS_JTAG_SEMIHOSTING;
REG_EXMEMSTAT &= ~0xFF;
u32 agbMemoryAddress = *(vu32*)0x027FFF7C;
if (*(vu32*)(agbMemoryAddress + 0x100) == 0x44495349) //ISID
_flags |= ENVIRONMENT_FLAGS_AGB_SEMIHOSTING;
}
else
{
if (detectPicoAgbAdapter())
_flags |= ENVIRONMENT_FLAGS_PICO_AGB_ADAPTER;
}
}
if (!(_flags & ENVIRONMENT_FLAGS_IS_NITRO_EMULATOR))
{
if (detectNocashPrintSuppport())
_flags |= ENVIRONMENT_FLAGS_NOCASH_PRINT;
}
}

View File

@@ -0,0 +1,32 @@
#pragma once
class Environment
{
enum EnvironmentFlags : u32
{
ENVIRONMENT_FLAGS_NONE = 0,
ENVIRONMENT_FLAGS_DSI_MODE = (1 << 0),
ENVIRONMENT_FLAGS_NOCASH_PRINT = (1 << 1),
ENVIRONMENT_FLAGS_IS_NITRO_EMULATOR = (1 << 2),
ENVIRONMENT_FLAGS_JTAG_SEMIHOSTING = (1 << 3),
ENVIRONMENT_FLAGS_AGB_SEMIHOSTING = (1 << 4),
ENVIRONMENT_FLAGS_DLDI = (1 << 5),
ENVIRONMENT_FLAGS_ARGV = (1 << 6),
ENVIRONMENT_FLAGS_PICO_AGB_ADAPTER = (1 << 7)
};
static u32 _flags;
public:
static void Initialize(bool dsiMode);
static inline bool IsDsiMode() { return _flags & ENVIRONMENT_FLAGS_DSI_MODE; }
static inline bool SupportsNocashPrint() { return _flags & ENVIRONMENT_FLAGS_NOCASH_PRINT; }
static inline bool IsIsNitroEmulator() { return _flags & ENVIRONMENT_FLAGS_IS_NITRO_EMULATOR; }
static inline bool SupportsJtagSemihosting() { return _flags & ENVIRONMENT_FLAGS_JTAG_SEMIHOSTING; }
static inline bool SupportsAgbSemihosting() { return _flags & ENVIRONMENT_FLAGS_AGB_SEMIHOSTING; }
static inline bool SupportsDldi() { return _flags & ENVIRONMENT_FLAGS_DLDI; }
static inline bool SupportsArgv() { return _flags & ENVIRONMENT_FLAGS_ARGV; }
static inline bool HasPicoAgbAdapter() { return _flags & ENVIRONMENT_FLAGS_PICO_AGB_ADAPTER; }
};

26
arm7/source/crt0.s Normal file
View File

@@ -0,0 +1,26 @@
.section ".crt0", "ax"
.arm
.global _start
.type _start, %function
_start:
// disable irqs
ldr r0,= 0x04000208
strb r0, [r0]
// clear bss
ldr r0,= __bss_start
ldr r1,= __bss_end
cmp r0, r1
beq bss_done
mov r2, #0
1:
str r2, [r0], #4
cmp r0, r1
bne 1b
bss_done:
ldr sp,= 0x0380FD80
b loaderMain
.pool
.end

View File

@@ -0,0 +1,17 @@
#include "common.h"
#include <stdarg.h>
#include <libtwl/i2c/i2cMcu.h>
#include "ipc.h"
#include "ipcCommands.h"
#include "core/mini-printf.h"
#include "ErrorDisplay.h"
void ErrorDisplay::PrintError(const char* errorFormat, ...)
{
va_list va;
va_start(va, errorFormat);
mini_vsnprintf((char*)0x02000000, 1024, errorFormat, va);
sendToArm9(IPC_COMMAND_ARM9_DISPLAY_ERROR);
va_end(va);
while (true);
}

View File

@@ -0,0 +1,11 @@
#pragma once
/// @brief Class for displaying critical errors on screen.
class ErrorDisplay
{
public:
/// @brief Formats and sends a critical error message to the arm9 to display it on screen.
/// @note This function does not return.
/// @param errorFormat The error message to format.
void PrintError(const char* errorFormat, ...);
};

205
arm7/source/fat/diskio.cpp Normal file
View File

@@ -0,0 +1,205 @@
/*-----------------------------------------------------------------------*/
/* Low level disk I/O module skeleton for FatFs (C)ChaN, 2016 */
/*-----------------------------------------------------------------------*/
/* 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 <nds/ndstypes.h>
#include <nds/disc_io.h>
#include <string.h>
#include <libtwl/rtos/rtosIrq.h>
#include "core/Environment.h"
// #include <libtwl/rtos/rtosIrq.h>
// #include <libtwl/rtos/rtosEvent.h>
#include "ff.h" /* Obtains integer types */
#include "diskio.h" /* Declarations of disk functions */
#include "dldi.h"
#include "../mmc/sdmmc.h"
// #include "core/semihosting.h"
/* Definitions of physical drive number for each drive */
#define DEV_FAT 0 //dldi
#define DEV_SD 1 //dsi sd
#define DEV_PC 2 //image on pc via semihosting
#define DEV_PC2 3 //image on pc via agb semihosting
// static int sPcFileHandle;
// static rtos_event_t sSemihostingCommandDoneEvent;
//extern "C" int sdmmc_sd_startup();
// extern FN_MEDIUM_STARTUP _DLDI_startup_ptr;
// extern FN_MEDIUM_READSECTORS _DLDI_readSectors_ptr;
// extern FN_MEDIUM_WRITESECTORS _DLDI_writeSectors_ptr;
/*-----------------------------------------------------------------------*/
/* Get Drive Status */
/*-----------------------------------------------------------------------*/
extern "C" DSTATUS disk_status (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
return 0;
}
// static void gbaIrq(u32 mask)
// {
// rtos_signalEvent(&sSemihostingCommandDoneEvent);
// }
/*-----------------------------------------------------------------------*/
/* Inidialize a Drive */
/*-----------------------------------------------------------------------*/
extern "C" DSTATUS disk_initialize (
BYTE pdrv /* Physical drive nmuber to identify the drive */
)
{
if (pdrv == DEV_FAT)
{
return 0;
}
else if (Environment::IsDsiMode() && pdrv == DEV_SD)
{
pico_SDMMC_init(SDMMC_DEV_CARD);
return 0;
}
else if (pdrv == DEV_PC)
{
// sPcFileHandle = sh_openFile("d:\\Emulators\\No$Debugger 3.0\\DSI-1.SD", SH_OPEN_MODE_R_PLUS_B);
return 0;
}
else if (pdrv == DEV_PC2)
{
// rtos_createEvent(&sSemihostingCommandDoneEvent);
// rtos_disableIrqMask(RTOS_IRQ_GBA_IREQ);
// rtos_ackIrqMask(RTOS_IRQ_GBA_IREQ);
// rtos_setIrqFunc(RTOS_IRQ_GBA_IREQ, gbaIrq);
// rtos_enableIrqMask(RTOS_IRQ_GBA_IREQ);
return 0;
}
return STA_NOINIT;
}
/*-----------------------------------------------------------------------*/
/* Read Sector(s) */
/*-----------------------------------------------------------------------*/
extern "C" DRESULT disk_read (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
BYTE *buff, /* Data buffer to store read data */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to read */
)
{
if (pdrv == DEV_FAT)
{
dldi_readSectors(buff, sector, count);
return RES_OK;
}
else if (Environment::IsDsiMode() && pdrv == DEV_SD)
{
pico_SDMMC_readSectors(SDMMC_DEV_CARD, sector, buff, count);
return RES_OK;
}
else if (pdrv == DEV_PC)
{
// sh_seekFile(sPcFileHandle, sector * 512);
// sh_readFile(sPcFileHandle, buff, count * 512);
// return RES_OK;
}
else if (pdrv == DEV_PC2)
{
// rtos_clearEvent(&sSemihostingCommandDoneEvent);
u32 agbMem = *(u32*)0x027FFF7C;
*(vu16*)(agbMem + 0x10002) = 1;
*(vu32*)(agbMem + 0x10004) = sector;
*(vu32*)(agbMem + 0x10008) = count;
rtos_disableIrqMask(RTOS_IRQ_GBA_IREQ);
rtos_ackIrqMask(RTOS_IRQ_GBA_IREQ);
*(vu16*)(agbMem + 0x10000) = 0x55;
while (!(rtos_getIrqFlags() & RTOS_IRQ_GBA_IREQ));
// rtos_waitEvent(&sSemihostingCommandDoneEvent, false, true);
if (*(vu16*)(agbMem + 0x10000) != 0xAA)
return RES_ERROR;
memcpy(buff, (const void*)(agbMem + 0x10020), count * 512);
return RES_OK;
}
return RES_PARERR;
}
/*-----------------------------------------------------------------------*/
/* Write Sector(s) */
/*-----------------------------------------------------------------------*/
#if FF_FS_READONLY == 0
extern "C" DRESULT disk_write (
BYTE pdrv, /* Physical drive nmuber to identify the drive */
const BYTE *buff, /* Data to be written */
DWORD sector, /* Start sector in LBA */
UINT count /* Number of sectors to write */
)
{
if (pdrv == DEV_FAT)
{
dldi_writeSectors(buff, sector, count);
return RES_OK;
}
else if (Environment::IsDsiMode() && pdrv == DEV_SD)
{
pico_SDMMC_writeSectors(SDMMC_DEV_CARD, sector, buff, count);
return RES_OK;
}
else if (pdrv == DEV_PC)
{
// sh_seekFile(sPcFileHandle, sector * 512);
// sh_writeFile(sPcFileHandle, buff, count * 512);
// return RES_OK;
}
else if (pdrv == DEV_PC2)
{
// rtos_clearEvent(&sSemihostingCommandDoneEvent);
u32 agbMem = *(u32*)0x027FFF7C;
memcpy((void*)(agbMem + 0x10020), buff, count * 512);
*(vu16*)(agbMem + 0x10002) = 2;
*(vu32*)(agbMem + 0x10004) = sector;
*(vu32*)(agbMem + 0x10008) = count;
rtos_disableIrqMask(RTOS_IRQ_GBA_IREQ);
rtos_ackIrqMask(RTOS_IRQ_GBA_IREQ);
*(vu16*)(agbMem + 0x10000) = 0x55;
while (!(rtos_getIrqFlags() & RTOS_IRQ_GBA_IREQ));
// rtos_waitEvent(&sSemihostingCommandDoneEvent, false, true);
if (*(vu16*)(agbMem + 0x10000) != 0xAA)
return RES_ERROR;
return RES_OK;
}
return RES_PARERR;
}
#endif
/*-----------------------------------------------------------------------*/
/* Miscellaneous Functions */
/*-----------------------------------------------------------------------*/
extern "C" DRESULT disk_ioctl (
BYTE pdrv, /* Physical drive nmuber (0..) */
BYTE cmd, /* Control code */
void *buff /* Buffer to send/receive control data */
)
{
return RES_OK;
}

77
arm7/source/fat/diskio.h Normal file
View File

@@ -0,0 +1,77 @@
/*-----------------------------------------------------------------------/
/ Low level disk interface modlue include file (C)ChaN, 2014 /
/-----------------------------------------------------------------------*/
#ifndef _DISKIO_DEFINED
#define _DISKIO_DEFINED
#ifdef __cplusplus
extern "C" {
#endif
/* 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 FF_FS_READONLY == 0) */
#define GET_SECTOR_COUNT 1 /* Get media size (needed at FF_USE_MKFS == 1) */
#define GET_SECTOR_SIZE 2 /* Get sector size (needed at FF_MAX_SS != FF_MIN_SS) */
#define GET_BLOCK_SIZE 3 /* Get erase block size (needed at FF_USE_MKFS == 1) */
#define CTRL_TRIM 4 /* Inform device that the data on the block of sectors is no longer used (needed at FF_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 */
#define ISDIO_READ 55 /* Read data form SD iSDIO register */
#define ISDIO_WRITE 56 /* Write data to SD iSDIO register */
#define ISDIO_MRITE 57 /* Masked write data to SD iSDIO register */
/* 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

Some files were not shown because too many files have changed in this diff Show More